mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-14 18:01:06 +00:00
DatePicker rework (#737)
* fix(date-picker): append calendar to date picker element #345 Fixes #345 * fix(date-picker): do not import rangePlugin from esm folder * fix(date-picker): correctly type change event for single/range types * feat(date-picker): add valueFrom, valueTo for range datepicker * docs(date-picker): add range type example * docs(date-picker): extract range example to iframe * docs(date-picker): extract single type to iframe
This commit is contained in:
parent
569d7021cb
commit
edefd6429b
11 changed files with 139 additions and 56 deletions
|
@ -1047,18 +1047,19 @@ None.
|
|||
|
||||
### Props
|
||||
|
||||
| Prop name | Kind | Reactive | Type | Default value | Description |
|
||||
| :------------- | :--------------- | :------- | :--------------------------------------------------- | ------------------------------------------------ | --------------------------------------------- |
|
||||
| value | <code>let</code> | Yes | <code>number | string</code> | <code>""</code> | Specify the date picker input value |
|
||||
| datePickerType | <code>let</code> | No | <code>"simple" | "single" | "range"</code> | <code>"simple"</code> | Specify the date picker type |
|
||||
| appendTo | <code>let</code> | No | <code>HTMLElement</code> | -- | Specify the element to append the calendar to |
|
||||
| dateFormat | <code>let</code> | No | <code>string</code> | <code>"m/d/Y"</code> | Specify the date format |
|
||||
| maxDate | <code>let</code> | No | <code>null | string | Date</code> | <code>null</code> | Specify the maximum date |
|
||||
| minDate | <code>let</code> | No | <code>null | string | Date</code> | <code>null</code> | Specify the minimum date |
|
||||
| locale | <code>let</code> | No | <code>string</code> | <code>"en"</code> | Specify the locale |
|
||||
| short | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to use the short variant |
|
||||
| light | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to enable the light variant |
|
||||
| id | <code>let</code> | No | <code>string</code> | <code>"ccs-" + Math.random().toString(36)</code> | Set an id for the date picker element |
|
||||
| Prop name | Kind | Reactive | Type | Default value | Description |
|
||||
| :------------- | :--------------- | :------- | :--------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
|
||||
| valueTo | <code>let</code> | Yes | <code>string</code> | <code>""</code> | Specify the date picker end date value (to)<br />Only works with the "range" date picker type |
|
||||
| valueFrom | <code>let</code> | Yes | <code>string</code> | <code>""</code> | Specify the date picker start date value (from)<br />Only works with the "range" date picker type |
|
||||
| value | <code>let</code> | Yes | <code>number | string</code> | <code>""</code> | Specify the date picker input value |
|
||||
| datePickerType | <code>let</code> | No | <code>"simple" | "single" | "range"</code> | <code>"simple"</code> | Specify the date picker type |
|
||||
| dateFormat | <code>let</code> | No | <code>string</code> | <code>"m/d/Y"</code> | Specify the date format |
|
||||
| maxDate | <code>let</code> | No | <code>null | string | Date</code> | <code>null</code> | Specify the maximum date |
|
||||
| minDate | <code>let</code> | No | <code>null | string | Date</code> | <code>null</code> | Specify the minimum date |
|
||||
| locale | <code>let</code> | No | <code>string</code> | <code>"en"</code> | Specify the locale |
|
||||
| short | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to use the short variant |
|
||||
| light | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to enable the light variant |
|
||||
| id | <code>let</code> | No | <code>string</code> | <code>"ccs-" + Math.random().toString(36)</code> | Set an id for the date picker element |
|
||||
|
||||
### Slots
|
||||
|
||||
|
@ -1068,13 +1069,13 @@ None.
|
|||
|
||||
### Events
|
||||
|
||||
| Event name | Type | Detail |
|
||||
| :--------- | :--------- | :----- |
|
||||
| click | forwarded | -- |
|
||||
| mouseover | forwarded | -- |
|
||||
| mouseenter | forwarded | -- |
|
||||
| mouseleave | forwarded | -- |
|
||||
| change | dispatched | -- |
|
||||
| Event name | Type | Detail |
|
||||
| :--------- | :--------- | :---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| change | dispatched | <code>string | { selectedDates: [dateFrom: Date, dateTo?: Date]; dateStr: string | { from: string; to: string; } }</code> |
|
||||
| click | forwarded | -- |
|
||||
| mouseover | forwarded | -- |
|
||||
| mouseenter | forwarded | -- |
|
||||
| mouseleave | forwarded | -- |
|
||||
|
||||
## `DatePickerInput`
|
||||
|
||||
|
|
|
@ -2393,13 +2393,24 @@
|
|||
"reactive": true
|
||||
},
|
||||
{
|
||||
"name": "appendTo",
|
||||
"name": "valueFrom",
|
||||
"kind": "let",
|
||||
"description": "Specify the element to append the calendar to",
|
||||
"type": "HTMLElement",
|
||||
"description": "Specify the date picker start date value (from)\nOnly works with the \"range\" date picker type",
|
||||
"type": "string",
|
||||
"value": "\"\"",
|
||||
"isFunction": false,
|
||||
"constant": false,
|
||||
"reactive": false
|
||||
"reactive": true
|
||||
},
|
||||
{
|
||||
"name": "valueTo",
|
||||
"kind": "let",
|
||||
"description": "Specify the date picker end date value (to)\nOnly works with the \"range\" date picker type",
|
||||
"type": "string",
|
||||
"value": "\"\"",
|
||||
"isFunction": false,
|
||||
"constant": false,
|
||||
"reactive": true
|
||||
},
|
||||
{
|
||||
"name": "dateFormat",
|
||||
|
@ -2474,11 +2485,15 @@
|
|||
],
|
||||
"slots": [{ "name": "__default__", "default": true, "slot_props": "{}" }],
|
||||
"events": [
|
||||
{
|
||||
"type": "dispatched",
|
||||
"name": "change",
|
||||
"detail": "string | { selectedDates: [dateFrom: Date, dateTo?: Date]; dateStr: string | { from: string; to: string; } }"
|
||||
},
|
||||
{ "type": "forwarded", "name": "click", "element": "div" },
|
||||
{ "type": "forwarded", "name": "mouseover", "element": "div" },
|
||||
{ "type": "forwarded", "name": "mouseenter", "element": "div" },
|
||||
{ "type": "forwarded", "name": "mouseleave", "element": "div" },
|
||||
{ "type": "dispatched", "name": "change" }
|
||||
{ "type": "forwarded", "name": "mouseleave", "element": "div" }
|
||||
],
|
||||
"typedefs": [],
|
||||
"rest_props": { "type": "Element", "name": "div" }
|
||||
|
|
|
@ -57,9 +57,11 @@ components: ["DatePicker", "DatePickerInput", "DatePickerSkeleton"]
|
|||
|
||||
### Single
|
||||
|
||||
<DatePicker datePickerType="single">
|
||||
<DatePickerInput labelText="Schedule a meeting" placeholder="mm/dd/yyyy" />
|
||||
</DatePicker>
|
||||
<FileSource src="/framed/DatePicker/DatePickerSingle" />
|
||||
|
||||
### Range
|
||||
|
||||
<FileSource src="/framed/DatePicker/DatePickerRange" />
|
||||
|
||||
### Skeleton
|
||||
|
||||
|
|
8
docs/src/pages/framed/DatePicker/DatePickerRange.svelte
Normal file
8
docs/src/pages/framed/DatePicker/DatePickerRange.svelte
Normal file
|
@ -0,0 +1,8 @@
|
|||
<script>
|
||||
import { DatePicker, DatePickerInput } from "carbon-components-svelte";
|
||||
</script>
|
||||
|
||||
<DatePicker datePickerType="range" on:change>
|
||||
<DatePickerInput labelText="Start date" placeholder="mm/dd/yyyy" />
|
||||
<DatePickerInput labelText="End date" placeholder="mm/dd/yyyy" />
|
||||
</DatePicker>
|
7
docs/src/pages/framed/DatePicker/DatePickerSingle.svelte
Normal file
7
docs/src/pages/framed/DatePicker/DatePickerSingle.svelte
Normal file
|
@ -0,0 +1,7 @@
|
|||
<script>
|
||||
import { DatePicker, DatePickerInput } from "carbon-components-svelte";
|
||||
</script>
|
||||
|
||||
<DatePicker datePickerType="single" on:change>
|
||||
<DatePickerInput labelText="Meeting date" placeholder="mm/dd/yyyy" />
|
||||
</DatePicker>
|
|
@ -1,6 +1,6 @@
|
|||
module.exports = {
|
||||
optimizeDeps: {
|
||||
include: ["clipboard-copy"],
|
||||
include: ["clipboard-copy", "flatpickr/dist/plugins/rangePlugin"],
|
||||
exclude: ["@sveltech/routify"],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
/**
|
||||
* @dispatch {string} change
|
||||
* @event {string | { selectedDates: [dateFrom: Date, dateTo?: Date]; dateStr: string | { from: string; to: string; } }} change
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -16,10 +16,18 @@
|
|||
export let value = "";
|
||||
|
||||
/**
|
||||
* Specify the element to append the calendar to
|
||||
* @type {HTMLElement}
|
||||
* Specify the date picker start date value (from)
|
||||
* Only works with the "range" date picker type
|
||||
* @type {string}
|
||||
*/
|
||||
export let appendTo = document.body;
|
||||
export let valueFrom = "";
|
||||
|
||||
/**
|
||||
* Specify the date picker end date value (to)
|
||||
* Only works with the "range" date picker type
|
||||
* @type {string}
|
||||
*/
|
||||
export let valueTo = "";
|
||||
|
||||
/** Specify the date format */
|
||||
export let dateFormat = "m/d/Y";
|
||||
|
@ -65,18 +73,23 @@
|
|||
(_) => _.filter(({ labelText }) => !!labelText).length === 0
|
||||
);
|
||||
const inputValue = writable(value);
|
||||
const inputValueFrom = writable(valueFrom);
|
||||
const inputValueTo = writable(valueTo);
|
||||
const mode = writable(datePickerType);
|
||||
const range = derived(mode, (_) => _ === "range");
|
||||
const hasCalendar = derived(mode, (_) => _ === "single" || _ === "range");
|
||||
|
||||
let calendar = undefined;
|
||||
let datePickerRef = undefined;
|
||||
let inputRef = undefined;
|
||||
let inputRefTo = undefined;
|
||||
let calendar = null;
|
||||
let datePickerRef = null;
|
||||
let inputRef = null;
|
||||
let inputRefTo = null;
|
||||
|
||||
setContext("DatePicker", {
|
||||
range,
|
||||
inputValue,
|
||||
inputValueFrom,
|
||||
inputValueTo,
|
||||
inputIds,
|
||||
hasCalendar,
|
||||
add: (data) => {
|
||||
inputs.update((_) => [..._, data]);
|
||||
|
@ -119,7 +132,7 @@
|
|||
if ($hasCalendar && !calendar) {
|
||||
calendar = createCalendar({
|
||||
options: {
|
||||
appendTo,
|
||||
appendTo: datePickerRef,
|
||||
dateFormat,
|
||||
defaultDate: $inputValue,
|
||||
locale,
|
||||
|
@ -133,10 +146,16 @@
|
|||
const detail = { selectedDates: calendar.selectedDates };
|
||||
|
||||
if ($range) {
|
||||
const from = inputRef.value;
|
||||
const to = inputRefTo.value;
|
||||
|
||||
detail.dateStr = {
|
||||
from: inputRef.value,
|
||||
to: inputRefTo.value,
|
||||
};
|
||||
|
||||
valueFrom = from;
|
||||
valueTo = to;
|
||||
} else {
|
||||
detail.dateStr = inputRef.value;
|
||||
}
|
||||
|
@ -146,8 +165,15 @@
|
|||
});
|
||||
}
|
||||
|
||||
if (calendar && !$range) {
|
||||
calendar.setDate($inputValue);
|
||||
if (calendar) {
|
||||
if ($range) {
|
||||
calendar.setDate([$inputValueFrom, $inputValueTo]);
|
||||
|
||||
// workaround to remove the default range plugin separator "to"
|
||||
inputRef.value = $inputValueFrom;
|
||||
} else {
|
||||
calendar.setDate($inputValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -159,19 +185,17 @@
|
|||
|
||||
$: inputValue.set(value);
|
||||
$: value = $inputValue;
|
||||
$: inputValueFrom.set(valueFrom);
|
||||
$: valueFrom = $inputValueFrom;
|
||||
$: inputValueTo.set(valueTo);
|
||||
$: valueTo = $inputValueTo;
|
||||
</script>
|
||||
|
||||
<svelte:body
|
||||
on:click="{({ target }) => {
|
||||
if (!calendar || !calendar.isOpen) {
|
||||
return;
|
||||
}
|
||||
if (datePickerRef && datePickerRef.contains(target)) {
|
||||
return;
|
||||
}
|
||||
if (!calendar.calendarContainer.contains(target)) {
|
||||
calendar.close();
|
||||
}
|
||||
if (!calendar || !calendar.isOpen) return;
|
||||
if (datePickerRef && datePickerRef.contains(target)) return;
|
||||
if (!calendar.calendarContainer.contains(target)) calendar.close();
|
||||
}}" />
|
||||
|
||||
<div
|
||||
|
|
|
@ -60,11 +60,14 @@
|
|||
add,
|
||||
hasCalendar,
|
||||
declareRef,
|
||||
inputIds,
|
||||
updateValue,
|
||||
blurInput,
|
||||
openCalendar,
|
||||
focusCalendar,
|
||||
inputValue,
|
||||
inputValueFrom,
|
||||
inputValueTo,
|
||||
} = getContext("DatePicker");
|
||||
|
||||
add({ id, labelText });
|
||||
|
@ -105,7 +108,11 @@
|
|||
pattern="{pattern}"
|
||||
disabled="{disabled}"
|
||||
{...$$restProps}
|
||||
value="{!$range ? $inputValue : undefined}"
|
||||
value="{$range
|
||||
? $inputIds.indexOf(id) === 0
|
||||
? $inputValueFrom
|
||||
: $inputValueTo
|
||||
: $inputValue}"
|
||||
class:bx--date-picker__input="{true}"
|
||||
class:bx--date-picker__input--invalid="{invalid}"
|
||||
class="{size && `bx--date-picker__input--${size}`}"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import flatpickr from "flatpickr";
|
||||
import rangePlugin from "flatpickr/dist/esm/plugins/rangePlugin";
|
||||
import rangePlugin from "flatpickr/dist/plugins/rangePlugin";
|
||||
|
||||
let l10n;
|
||||
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
import { DatePicker, DatePickerSkeleton, DatePickerInput } from "../types";
|
||||
</script>
|
||||
|
||||
<DatePicker>
|
||||
<DatePicker
|
||||
on:change="{(e) => {
|
||||
console.log(e.detail);
|
||||
}}"
|
||||
>
|
||||
<DatePickerInput labelText="Date of birth" placeholder="mm/dd/yyyy" />
|
||||
</DatePicker>
|
||||
|
||||
|
@ -51,7 +55,7 @@
|
|||
/>
|
||||
</DatePicker>
|
||||
|
||||
<DatePicker datePickerType="single">
|
||||
<DatePicker valueFrom="" valueTo="" datePickerType="single">
|
||||
<DatePickerInput labelText="Schedule a meeting" placeholder="mm/dd/yyyy" />
|
||||
</DatePicker>
|
||||
|
||||
|
|
21
types/DatePicker/DatePicker.d.ts
vendored
21
types/DatePicker/DatePicker.d.ts
vendored
|
@ -16,9 +16,18 @@ export interface DatePickerProps
|
|||
value?: number | string;
|
||||
|
||||
/**
|
||||
* Specify the element to append the calendar to
|
||||
* Specify the date picker start date value (from)
|
||||
* Only works with the "range" date picker type
|
||||
* @default ""
|
||||
*/
|
||||
appendTo?: HTMLElement;
|
||||
valueFrom?: string;
|
||||
|
||||
/**
|
||||
* Specify the date picker end date value (to)
|
||||
* Only works with the "range" date picker type
|
||||
* @default ""
|
||||
*/
|
||||
valueTo?: string;
|
||||
|
||||
/**
|
||||
* Specify the date format
|
||||
|
@ -66,11 +75,17 @@ export interface DatePickerProps
|
|||
export default class DatePicker extends SvelteComponentTyped<
|
||||
DatePickerProps,
|
||||
{
|
||||
change: CustomEvent<
|
||||
| string
|
||||
| {
|
||||
selectedDates: [dateFrom: Date, dateTo?: Date];
|
||||
dateStr: string | { from: string; to: string };
|
||||
}
|
||||
>;
|
||||
click: WindowEventMap["click"];
|
||||
mouseover: WindowEventMap["mouseover"];
|
||||
mouseenter: WindowEventMap["mouseenter"];
|
||||
mouseleave: WindowEventMap["mouseleave"];
|
||||
change: CustomEvent<any>;
|
||||
},
|
||||
{ default: {} }
|
||||
> {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue