Skip to content

Commit

Permalink
Merge pull request #1453 from weslleyrsr/vNext
Browse files Browse the repository at this point in the history
feat: implement CvDatePicker
  • Loading branch information
davidnixon authored May 13, 2023
2 parents 9b094c6 + 87dcf39 commit 8faa627
Show file tree
Hide file tree
Showing 12 changed files with 1,255 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@carbon/icons-vue": "^10.60.0",
"@vueuse/core": "^4.11.2",
"carbon-components": "^10.58.5",
"flatpickr": "^4.6.13",
"mitt": "^3.0.0"
},
"devDependencies": {
Expand Down
86 changes: 86 additions & 0 deletions src/components/CvDatePicker/CvDatePicker-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# cv-date-picker

A Vue implementation of a Carbon Components date-picker.

http://www.carbondesignsystem.com/components/date-picker/code

## Usage

### Short

```html
<cv-date-picker
kind="short"
pattern="\d{1,2}/\d{2}"
placeholder="mm/yy"
@onChange="actionChange"
>
</cv-date-picker>
```

### Simple

```html
<cv-date-picker
kind="simple"
pattern="\d{1,2}/\d{1,2}/\d{4}"
placeholder="mm/dd/yyyy"
@onChange="actionChange"
>
</cv-date-picker>
```

### Single

```html
<cv-date-picker
kind="single"
pattern="\d{1,2}/\d{1,2}/\d{4}"
placeholder="mm/dd/yyyy"
:cal-options="calOptions"
@onChange="actionChange"
>
</cv-date-picker>
```

### Range

```html
<cv-date-picker
kind="range"
pattern="\d{1,2}/\d{1,2}/\d{4}"
placeholder="mm/dd/yyyy"
:cal-options="calOptions"
@onChange="actionChange"
>
</cv-date-picker>
```

## Attributes

- dateLabel: optional label for the date input (first in range)
- dateEndLabel: optional for the end range date input (first in range)
- kind: 'short', 'simple', 'single', 'range' as per carbon components core only single and range have a date picker
- calOptions: Options to confiure flatpickr, see flatpickr for full details.

- e.g. { dateFormat: 'd/m/Y', defaultDate: '01/01/2019' }
- NOTE: passing event handlers onChange and onValueUpdate are swallowed internally. Both produce an onChange.

- pattern: Regex pattern used for form validation '\\d{1,2}/\\d{1,2}/\\d{4}',
- placeholder: Shown when date picker is empty,
- invalidMessage: Message displayed if invalid is true

- value: can be
- Javascript Date
- String with a date matching the format based on the calendar options
- Object (kind === 'range' only): { startDate: val, endDate: val2 } where val and val2 are a javascript date or date string as per format option

## Slots

invalid-message: Overrides the invalid message property

###

## Events

- change raised when single or ranged date picker value changes.
241 changes: 241 additions & 0 deletions src/components/CvDatePicker/CvDatePicker.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
import {
sbCompPrefix,
storyParametersObject,
} from '../../global/storybook-utils';

import { CvDatePicker } from '.';
import { CvDatePickerSkeleton } from '.';
import { action } from '@storybook/addon-actions';
import { ref } from 'vue';

const initArgs = {
dateLabel: 'Date label',
invalidMessage: '',
};

const now = new Date();
const tomorrow = new Date();
tomorrow.setDate(now.getDate() + 1);

export default {
title: `${sbCompPrefix}/CvDatePicker`,
component: CvDatePicker,
parameters: {
a11y: {
config: {
rules: [],
},
manual: true,
},
},
argTypes: {
dateLabel: { type: String, description: 'Date picker label' },
invalidMessage: {
type: String,
description: 'Date picker text on invalid value',
},
},
};

/* DEFAULT STORY */

const template = `
<div>
<cv-date-picker v-bind='args' @change='onChange'>
</cv-date-picker>
</div>
`;
const Template = args => {
return {
components: { CvDatePicker },
setup: () => ({
args,
onChange: action('change'),
}),
template,
};
};

export const Default = Template.bind({});
Default.args = initArgs;
Default.parameters = storyParametersObject(
Default.parameters,
template,
Default.args
);

/* V-MODEL STORY */

const modelValue = ref('');
const templateVModel = `
<div>
<cv-date-picker v-bind='args' @change='onChange' v-model="modelValue">
</cv-date-picker>
</div>
<div style="margin: 32px 0;">
<div style="font-size: 150%;">Sample interaction</div>
<label for="date-model" style='margin-right: 0.5rem'>V-model:</label>
<input id="date-model" type="text" :value="modelValue.startDate || modelValue" @change="ev => { if (args.kind === 'range') { modelValue.startDate = ev.currentTarget.value } else { modelValue = ev.currentTarget.value } }"/>
<input v-if="args.kind === 'range'" id="date-model" type="text" :value="modelValue.endDate" @change="ev => modelValue.endDate = ev.currentTarget.value"/>
</div>
`;

const TemplateVModel = args => {
return {
components: { CvDatePicker },
setup: () => ({
args,
modelValue,
now,
onChange: action('change'),
}),
template: templateVModel,
};
};

export const vModel = TemplateVModel.bind({});
vModel.args = initArgs;
vModel.parameters = storyParametersObject(
vModel.parameters,
templateVModel,
vModel.args
);

/* INVALID MESSAGE STORY */

const templateInvalidMessage = `
<div>
<cv-date-picker v-bind='args' @change='onChange'>
</cv-date-picker>
</div>
`;

const TemplateInvalidMessage = args => {
return {
components: { CvDatePicker },
setup: () => ({
args,
onChange: action('change'),
}),
template: templateInvalidMessage,
};
};

export const InvalidMessage = TemplateInvalidMessage.bind({});
InvalidMessage.args = { ...initArgs, invalidMessage: 'Invalid date' };

/* INVALID MESSAGE SLOT STORY */

const templateInvalidMessageSlot = `
<div>
<cv-date-picker v-bind='args' @change='onChange'>
<template #invalid-message>Invalid date slot</template>
</cv-date-picker>
</div>
`;

const TemplateInvalidMessageSlot = args => {
return {
components: { CvDatePicker },
setup: () => ({
args,
onChange: action('change'),
}),
template: templateInvalidMessageSlot,
};
};

export const InvalidMessageSlot = TemplateInvalidMessageSlot.bind({});
InvalidMessageSlot.args = initArgs;

/* SINGLE USING DATE STORY */

const templateSingleUsingDate = `
<div>
<cv-date-picker v-bind='args' @change='onChange' kind="single" :value="now">
</cv-date-picker>
</div>
`;

const TemplateSingleUsingDate = args => {
return {
components: { CvDatePicker },
setup: () => ({
args,
now,
onChange: action('change'),
}),
template: templateSingleUsingDate,
};
};

export const SingleUsingDate = TemplateSingleUsingDate.bind({});
SingleUsingDate.args = initArgs;

/* RANGE USING DATE STORY */

const templateRangeUsingDate = `
<div>
<cv-date-picker v-bind='args' @change='onChange' kind="range" :value="{startDate: now.toLocaleDateString(), endDate: tomorrow.toLocaleDateString()}">
</cv-date-picker>
</div>
`;

const TemplateRangeUsingDate = args => {
return {
components: { CvDatePicker },
setup: () => ({
args,
now,
tomorrow,
onChange: action('change'),
}),
template: templateRangeUsingDate,
};
};

export const RangeUsingDate = TemplateRangeUsingDate.bind({});
RangeUsingDate.args = initArgs;

/* MINIMAL STORY */

const templateMinimal = `
<div>
<cv-date-picker v-bind='args' @change='onChange'>
</cv-date-picker>
</div>
`;

const TemplateMinimal = args => {
return {
components: { CvDatePicker },
setup: () => ({
args,
onChange: action('change'),
}),
template: templateMinimal,
};
};

export const Minimal = TemplateMinimal.bind({});

/* SKELETON STORY */

const templateSkeleton = `
<div>
<cv-date-picker-skeleton v-bind='args'></cv-date-picker-skeleton>
</div>
`;

const TemplateSkeleton = args => {
return {
components: { CvDatePicker, CvDatePickerSkeleton },
setup: () => ({
args,
onChange: action('change'),
}),
template: templateSkeleton,
};
};

export const Skeleton = TemplateSkeleton.bind({});
Loading

0 comments on commit 8faa627

Please sign in to comment.