@wordpress/components 29.12.0 → 29.13.1-next.719a03cbe.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/build/box-control/input-control.js +2 -2
- package/build/box-control/input-control.js.map +1 -1
- package/build/calendar/date-calendar/index.js +60 -0
- package/build/calendar/date-calendar/index.js.map +1 -0
- package/build/calendar/date-range-calendar/index.js +168 -0
- package/build/calendar/date-range-calendar/index.js.map +1 -0
- package/build/calendar/index.js +27 -0
- package/build/calendar/index.js.map +1 -0
- package/build/calendar/types.js +6 -0
- package/build/calendar/types.js.map +1 -0
- package/build/calendar/utils/constants.js +68 -0
- package/build/calendar/utils/constants.js.map +1 -0
- package/build/calendar/utils/day-cell.js +137 -0
- package/build/calendar/utils/day-cell.js.map +1 -0
- package/build/calendar/utils/misc.js +10 -0
- package/build/calendar/utils/misc.js.map +1 -0
- package/build/calendar/utils/use-controlled-value.js +58 -0
- package/build/calendar/utils/use-controlled-value.js.map +1 -0
- package/build/calendar/utils/use-localization-props.js +162 -0
- package/build/calendar/utils/use-localization-props.js.map +1 -0
- package/build/custom-gradient-picker/gradient-bar/control-points.js +1 -1
- package/build/custom-gradient-picker/gradient-bar/control-points.js.map +1 -1
- package/build/custom-select-control-v2/custom-select.js +3 -3
- package/build/custom-select-control-v2/custom-select.js.map +1 -1
- package/build/date-time/date/index.js +1 -1
- package/build/date-time/date/index.js.map +1 -1
- package/build/form-token-field/index.js +11 -1
- package/build/form-token-field/index.js.map +1 -1
- package/build/form-token-field/token.js +1 -1
- package/build/form-token-field/token.js.map +1 -1
- package/build/index.js +19 -0
- package/build/index.js.map +1 -1
- package/build/mobile/bottom-sheet/cell.native.js +2 -2
- package/build/mobile/bottom-sheet/cell.native.js.map +1 -1
- package/build/mobile/link-picker/index.native.js +1 -1
- package/build/mobile/link-picker/index.native.js.map +1 -1
- package/build/navigation/menu/menu-title-search.js +1 -1
- package/build/navigation/menu/menu-title-search.js.map +1 -1
- package/build/palette-edit/index.js +4 -4
- package/build/palette-edit/index.js.map +1 -1
- package/build-module/box-control/input-control.js +2 -2
- package/build-module/box-control/input-control.js.map +1 -1
- package/build-module/calendar/date-calendar/index.js +51 -0
- package/build-module/calendar/date-calendar/index.js.map +1 -0
- package/build-module/calendar/date-range-calendar/index.js +157 -0
- package/build-module/calendar/date-range-calendar/index.js.map +1 -0
- package/build-module/calendar/index.js +4 -0
- package/build-module/calendar/index.js.map +1 -0
- package/build-module/calendar/types.js +2 -0
- package/build-module/calendar/types.js.map +1 -0
- package/build-module/calendar/utils/constants.js +61 -0
- package/build-module/calendar/utils/constants.js.map +1 -0
- package/build-module/calendar/utils/day-cell.js +131 -0
- package/build-module/calendar/utils/day-cell.js.map +1 -0
- package/build-module/calendar/utils/misc.js +4 -0
- package/build-module/calendar/utils/misc.js.map +1 -0
- package/build-module/calendar/utils/use-controlled-value.js +51 -0
- package/build-module/calendar/utils/use-controlled-value.js.map +1 -0
- package/build-module/calendar/utils/use-localization-props.js +154 -0
- package/build-module/calendar/utils/use-localization-props.js.map +1 -0
- package/build-module/custom-gradient-picker/gradient-bar/control-points.js +1 -1
- package/build-module/custom-gradient-picker/gradient-bar/control-points.js.map +1 -1
- package/build-module/custom-select-control-v2/custom-select.js +4 -4
- package/build-module/custom-select-control-v2/custom-select.js.map +1 -1
- package/build-module/date-time/date/index.js +1 -1
- package/build-module/date-time/date/index.js.map +1 -1
- package/build-module/form-token-field/index.js +11 -1
- package/build-module/form-token-field/index.js.map +1 -1
- package/build-module/form-token-field/token.js +1 -1
- package/build-module/form-token-field/token.js.map +1 -1
- package/build-module/index.js +1 -0
- package/build-module/index.js.map +1 -1
- package/build-module/mobile/bottom-sheet/cell.native.js +2 -2
- package/build-module/mobile/bottom-sheet/cell.native.js.map +1 -1
- package/build-module/mobile/link-picker/index.native.js +1 -1
- package/build-module/mobile/link-picker/index.native.js.map +1 -1
- package/build-module/navigation/menu/menu-title-search.js +1 -1
- package/build-module/navigation/menu/menu-title-search.js.map +1 -1
- package/build-module/palette-edit/index.js +4 -4
- package/build-module/palette-edit/index.js.map +1 -1
- package/build-style/style-rtl.css +358 -5
- package/build-style/style.css +358 -5
- package/build-types/box-control/input-control.d.ts.map +1 -1
- package/build-types/box-control/utils.d.ts +7 -7
- package/build-types/calendar/date-calendar/index.d.ts +11 -0
- package/build-types/calendar/date-calendar/index.d.ts.map +1 -0
- package/build-types/calendar/date-range-calendar/index.d.ts +14 -0
- package/build-types/calendar/date-range-calendar/index.d.ts.map +1 -0
- package/build-types/calendar/index.d.ts +4 -0
- package/build-types/calendar/index.d.ts.map +1 -0
- package/build-types/calendar/stories/date-calendar.story.d.ts +16 -0
- package/build-types/calendar/stories/date-calendar.story.d.ts.map +1 -0
- package/build-types/calendar/stories/date-range-calendar.story.d.ts +16 -0
- package/build-types/calendar/stories/date-range-calendar.story.d.ts.map +1 -0
- package/build-types/calendar/test/__utils__/index.d.ts +10 -0
- package/build-types/calendar/test/__utils__/index.d.ts.map +1 -0
- package/build-types/calendar/test/date-calendar.d.ts +2 -0
- package/build-types/calendar/test/date-calendar.d.ts.map +1 -0
- package/build-types/calendar/test/date-range-calendar.d.ts +2 -0
- package/build-types/calendar/test/date-range-calendar.d.ts.map +1 -0
- package/build-types/calendar/types.d.ts +317 -0
- package/build-types/calendar/types.d.ts.map +1 -0
- package/build-types/calendar/utils/constants.d.ts +52 -0
- package/build-types/calendar/utils/constants.d.ts.map +1 -0
- package/build-types/calendar/utils/day-cell.d.ts +21 -0
- package/build-types/calendar/utils/day-cell.d.ts.map +1 -0
- package/build-types/calendar/utils/misc.d.ts +2 -0
- package/build-types/calendar/utils/misc.d.ts.map +1 -0
- package/build-types/calendar/utils/use-controlled-value.d.ts +27 -0
- package/build-types/calendar/utils/use-controlled-value.d.ts.map +1 -0
- package/build-types/calendar/utils/use-localization-props.d.ts +64 -0
- package/build-types/calendar/utils/use-localization-props.d.ts.map +1 -0
- package/build-types/custom-gradient-picker/constants.d.ts +6 -3
- package/build-types/custom-gradient-picker/constants.d.ts.map +1 -1
- package/build-types/custom-select-control-v2/custom-select.d.ts.map +1 -1
- package/build-types/dimension-control/sizes.d.ts +15 -3
- package/build-types/dimension-control/sizes.d.ts.map +1 -1
- package/build-types/font-size-picker/constants.d.ts +2 -2
- package/build-types/font-size-picker/constants.d.ts.map +1 -1
- package/build-types/form-token-field/index.d.ts.map +1 -1
- package/build-types/index.d.ts +1 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/popover/overlay-middlewares.d.ts +6 -1
- package/build-types/popover/overlay-middlewares.d.ts.map +1 -1
- package/package.json +21 -20
- package/src/box-control/input-control.tsx +14 -5
- package/src/calendar/date-calendar/README.md +250 -0
- package/src/calendar/date-calendar/index.tsx +55 -0
- package/src/calendar/date-range-calendar/README.md +287 -0
- package/src/calendar/date-range-calendar/index.tsx +203 -0
- package/src/calendar/index.tsx +3 -0
- package/src/calendar/stories/date-calendar.story.tsx +221 -0
- package/src/calendar/stories/date-range-calendar.story.tsx +230 -0
- package/src/calendar/style.scss +431 -0
- package/src/calendar/test/__utils__/index.ts +56 -0
- package/src/calendar/test/date-calendar.tsx +975 -0
- package/src/calendar/test/date-range-calendar.tsx +1701 -0
- package/src/calendar/types.ts +342 -0
- package/src/calendar/utils/constants.ts +62 -0
- package/src/calendar/utils/day-cell.tsx +133 -0
- package/src/calendar/utils/misc.ts +3 -0
- package/src/calendar/utils/use-controlled-value.ts +61 -0
- package/src/calendar/utils/use-localization-props.ts +169 -0
- package/src/custom-gradient-picker/gradient-bar/control-points.tsx +1 -1
- package/src/custom-select-control-v2/custom-select.tsx +6 -3
- package/src/date-time/date/index.tsx +1 -1
- package/src/form-token-field/index.tsx +12 -1
- package/src/form-token-field/token.tsx +1 -1
- package/src/index.ts +1 -0
- package/src/mobile/bottom-sheet/cell.native.js +2 -2
- package/src/mobile/link-picker/index.native.js +1 -1
- package/src/navigation/menu/menu-title-search.tsx +1 -1
- package/src/palette-edit/index.tsx +4 -4
- package/src/select-control/style.scss +0 -6
- package/src/style.scss +1 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { differenceInCalendarDays } from 'date-fns';
|
|
5
|
+
import { DayPicker, rangeContainsModifiers } from 'react-day-picker';
|
|
6
|
+
import { enUS } from 'react-day-picker/locale';
|
|
7
|
+
/**
|
|
8
|
+
* WordPress dependencies
|
|
9
|
+
*/
|
|
10
|
+
import { useMemo, useState } from '@wordpress/element';
|
|
11
|
+
/**
|
|
12
|
+
* Internal dependencies
|
|
13
|
+
*/
|
|
14
|
+
import { COMMON_PROPS, MODIFIER_CLASSNAMES } from '../utils/constants';
|
|
15
|
+
import { clampNumberOfMonths } from '../utils/misc';
|
|
16
|
+
import { useControlledValue } from '../utils/use-controlled-value';
|
|
17
|
+
import { useLocalizationProps } from '../utils/use-localization-props';
|
|
18
|
+
import type { DateRangeCalendarProps, DateRange } from '../types';
|
|
19
|
+
|
|
20
|
+
export function usePreviewRange( {
|
|
21
|
+
selected,
|
|
22
|
+
hoveredDate,
|
|
23
|
+
excludeDisabled,
|
|
24
|
+
min,
|
|
25
|
+
max,
|
|
26
|
+
disabled,
|
|
27
|
+
}: Pick<
|
|
28
|
+
DateRangeCalendarProps,
|
|
29
|
+
'selected' | 'excludeDisabled' | 'min' | 'max' | 'disabled'
|
|
30
|
+
> & {
|
|
31
|
+
hoveredDate: Date | undefined;
|
|
32
|
+
} ) {
|
|
33
|
+
return useMemo( () => {
|
|
34
|
+
if ( ! hoveredDate || ! selected?.from ) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let previewHighlight: DateRange | undefined;
|
|
39
|
+
let potentialNewRange: { from: Date; to: Date } | undefined;
|
|
40
|
+
|
|
41
|
+
// Hovering on a date before the start of the selected range
|
|
42
|
+
if ( hoveredDate < selected.from ) {
|
|
43
|
+
previewHighlight = {
|
|
44
|
+
from: hoveredDate,
|
|
45
|
+
to: selected.from,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
potentialNewRange = {
|
|
49
|
+
from: hoveredDate,
|
|
50
|
+
to: selected.to ?? selected.from,
|
|
51
|
+
};
|
|
52
|
+
} else if (
|
|
53
|
+
selected.to &&
|
|
54
|
+
hoveredDate > selected.from &&
|
|
55
|
+
hoveredDate < selected.to
|
|
56
|
+
) {
|
|
57
|
+
// Hovering on a date between the start and end of the selected range
|
|
58
|
+
previewHighlight = {
|
|
59
|
+
from: selected.from,
|
|
60
|
+
to: hoveredDate,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
potentialNewRange = {
|
|
64
|
+
from: selected.from,
|
|
65
|
+
to: hoveredDate,
|
|
66
|
+
};
|
|
67
|
+
} else if ( hoveredDate > selected.from ) {
|
|
68
|
+
// Hovering on a date after the end of the selected range (either
|
|
69
|
+
// because it's greater than selected.to, or because it's not defined)
|
|
70
|
+
previewHighlight = {
|
|
71
|
+
from: selected.to ?? selected.from,
|
|
72
|
+
to: hoveredDate,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
potentialNewRange = {
|
|
76
|
+
from: selected.from,
|
|
77
|
+
to: hoveredDate,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (
|
|
82
|
+
min !== undefined &&
|
|
83
|
+
min > 0 &&
|
|
84
|
+
potentialNewRange &&
|
|
85
|
+
differenceInCalendarDays(
|
|
86
|
+
potentialNewRange.to,
|
|
87
|
+
potentialNewRange.from
|
|
88
|
+
) < min
|
|
89
|
+
) {
|
|
90
|
+
previewHighlight = {
|
|
91
|
+
from: hoveredDate,
|
|
92
|
+
to: hoveredDate,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (
|
|
97
|
+
max !== undefined &&
|
|
98
|
+
max > 0 &&
|
|
99
|
+
potentialNewRange &&
|
|
100
|
+
differenceInCalendarDays(
|
|
101
|
+
potentialNewRange.to,
|
|
102
|
+
potentialNewRange.from
|
|
103
|
+
) > max
|
|
104
|
+
) {
|
|
105
|
+
previewHighlight = {
|
|
106
|
+
from: hoveredDate,
|
|
107
|
+
to: hoveredDate,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (
|
|
112
|
+
excludeDisabled &&
|
|
113
|
+
disabled &&
|
|
114
|
+
potentialNewRange &&
|
|
115
|
+
rangeContainsModifiers( potentialNewRange, disabled )
|
|
116
|
+
) {
|
|
117
|
+
previewHighlight = {
|
|
118
|
+
from: hoveredDate,
|
|
119
|
+
to: hoveredDate,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return previewHighlight;
|
|
124
|
+
}, [ selected, hoveredDate, excludeDisabled, min, max, disabled ] );
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* `DateRangeCalendar` is a React component that provides a customizable calendar
|
|
129
|
+
* interface for **date range** selection.
|
|
130
|
+
*
|
|
131
|
+
* The component is built with accessibility in mind and follows ARIA best
|
|
132
|
+
* practices for calendar widgets. It provides keyboard navigation, screen reader
|
|
133
|
+
* support, and customizable labels for internationalization.
|
|
134
|
+
*/
|
|
135
|
+
export const DateRangeCalendar = ( {
|
|
136
|
+
defaultSelected,
|
|
137
|
+
selected: selectedProp,
|
|
138
|
+
onSelect,
|
|
139
|
+
numberOfMonths = 1,
|
|
140
|
+
excludeDisabled,
|
|
141
|
+
min,
|
|
142
|
+
max,
|
|
143
|
+
disabled,
|
|
144
|
+
locale = enUS,
|
|
145
|
+
timeZone,
|
|
146
|
+
...props
|
|
147
|
+
}: DateRangeCalendarProps ) => {
|
|
148
|
+
const localizationProps = useLocalizationProps( {
|
|
149
|
+
locale,
|
|
150
|
+
timeZone,
|
|
151
|
+
mode: 'range',
|
|
152
|
+
} );
|
|
153
|
+
|
|
154
|
+
const [ selected, setSelected ] = useControlledValue<
|
|
155
|
+
DateRange | undefined
|
|
156
|
+
>( {
|
|
157
|
+
defaultValue: defaultSelected,
|
|
158
|
+
value: selectedProp,
|
|
159
|
+
onChange: onSelect,
|
|
160
|
+
} );
|
|
161
|
+
|
|
162
|
+
const [ hoveredDate, setHoveredDate ] = useState< Date | undefined >(
|
|
163
|
+
undefined
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
// Compute the preview range for hover effect
|
|
167
|
+
const previewRange = usePreviewRange( {
|
|
168
|
+
selected,
|
|
169
|
+
hoveredDate,
|
|
170
|
+
excludeDisabled,
|
|
171
|
+
min,
|
|
172
|
+
max,
|
|
173
|
+
disabled,
|
|
174
|
+
} );
|
|
175
|
+
|
|
176
|
+
const modifiers = useMemo( () => {
|
|
177
|
+
return {
|
|
178
|
+
preview: previewRange,
|
|
179
|
+
preview_start: previewRange?.from,
|
|
180
|
+
preview_end: previewRange?.to,
|
|
181
|
+
};
|
|
182
|
+
}, [ previewRange ] );
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<DayPicker
|
|
186
|
+
{ ...COMMON_PROPS }
|
|
187
|
+
{ ...localizationProps }
|
|
188
|
+
{ ...props }
|
|
189
|
+
mode="range"
|
|
190
|
+
numberOfMonths={ clampNumberOfMonths( numberOfMonths ) }
|
|
191
|
+
disabled={ disabled }
|
|
192
|
+
excludeDisabled={ excludeDisabled }
|
|
193
|
+
min={ min }
|
|
194
|
+
max={ max }
|
|
195
|
+
selected={ selected }
|
|
196
|
+
onSelect={ setSelected }
|
|
197
|
+
onDayMouseEnter={ ( date ) => setHoveredDate( date ) }
|
|
198
|
+
onDayMouseLeave={ () => setHoveredDate( undefined ) }
|
|
199
|
+
modifiers={ modifiers }
|
|
200
|
+
modifiersClassNames={ MODIFIER_CLASSNAMES }
|
|
201
|
+
/>
|
|
202
|
+
);
|
|
203
|
+
};
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { fn } from '@storybook/test';
|
|
5
|
+
import {
|
|
6
|
+
enUS,
|
|
7
|
+
fr,
|
|
8
|
+
es,
|
|
9
|
+
de,
|
|
10
|
+
it,
|
|
11
|
+
he,
|
|
12
|
+
ru,
|
|
13
|
+
ja,
|
|
14
|
+
ptBR,
|
|
15
|
+
nl,
|
|
16
|
+
ko,
|
|
17
|
+
tr,
|
|
18
|
+
id,
|
|
19
|
+
zhCN,
|
|
20
|
+
zhTW,
|
|
21
|
+
ar,
|
|
22
|
+
sv,
|
|
23
|
+
} from 'date-fns/locale';
|
|
24
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* WordPress dependencies
|
|
28
|
+
*/
|
|
29
|
+
import { useState, useEffect } from '@wordpress/element';
|
|
30
|
+
/**
|
|
31
|
+
* Internal dependencies
|
|
32
|
+
*/
|
|
33
|
+
import { DateCalendar, TZDate } from '..';
|
|
34
|
+
|
|
35
|
+
const meta: Meta< typeof DateCalendar > = {
|
|
36
|
+
title: 'Components/Selection & Input/Time & Date/DateCalendar',
|
|
37
|
+
component: DateCalendar,
|
|
38
|
+
argTypes: {
|
|
39
|
+
locale: {
|
|
40
|
+
options: [
|
|
41
|
+
'English (US)',
|
|
42
|
+
'French',
|
|
43
|
+
'Spanish',
|
|
44
|
+
'German',
|
|
45
|
+
'Italian',
|
|
46
|
+
'Hebrew',
|
|
47
|
+
'Russian',
|
|
48
|
+
'Japanese',
|
|
49
|
+
'Portuguese (Brazil)',
|
|
50
|
+
'Dutch',
|
|
51
|
+
'Korean',
|
|
52
|
+
'Turkish',
|
|
53
|
+
'Indonesian',
|
|
54
|
+
'Chinese (Simplified)',
|
|
55
|
+
'Chinese (Traditional)',
|
|
56
|
+
'Arabic',
|
|
57
|
+
'Swedish',
|
|
58
|
+
],
|
|
59
|
+
mapping: {
|
|
60
|
+
'English (US)': enUS,
|
|
61
|
+
French: fr,
|
|
62
|
+
Spanish: es,
|
|
63
|
+
German: de,
|
|
64
|
+
Italian: it,
|
|
65
|
+
Hebrew: he,
|
|
66
|
+
Russian: ru,
|
|
67
|
+
Japanese: ja,
|
|
68
|
+
'Portuguese (Brazil)': ptBR,
|
|
69
|
+
Dutch: nl,
|
|
70
|
+
Korean: ko,
|
|
71
|
+
Turkish: tr,
|
|
72
|
+
Indonesian: id,
|
|
73
|
+
'Chinese (Simplified)': zhCN,
|
|
74
|
+
'Chinese (Traditional)': zhTW,
|
|
75
|
+
Arabic: ar,
|
|
76
|
+
Swedish: sv,
|
|
77
|
+
},
|
|
78
|
+
control: 'select',
|
|
79
|
+
},
|
|
80
|
+
timeZone: {
|
|
81
|
+
options: [
|
|
82
|
+
'Pacific/Honolulu',
|
|
83
|
+
'America/New_York',
|
|
84
|
+
'Europe/London',
|
|
85
|
+
'Asia/Tokyo',
|
|
86
|
+
'Pacific/Auckland',
|
|
87
|
+
],
|
|
88
|
+
control: 'select',
|
|
89
|
+
},
|
|
90
|
+
labels: {
|
|
91
|
+
control: false,
|
|
92
|
+
},
|
|
93
|
+
defaultSelected: { control: 'date' },
|
|
94
|
+
selected: { control: 'date' },
|
|
95
|
+
onSelect: {
|
|
96
|
+
control: false,
|
|
97
|
+
},
|
|
98
|
+
defaultMonth: { control: 'date' },
|
|
99
|
+
month: { control: 'date' },
|
|
100
|
+
onMonthChange: {
|
|
101
|
+
control: false,
|
|
102
|
+
},
|
|
103
|
+
endMonth: { control: 'date' },
|
|
104
|
+
startMonth: { control: 'date' },
|
|
105
|
+
},
|
|
106
|
+
args: {
|
|
107
|
+
onMonthChange: fn(),
|
|
108
|
+
onSelect: fn(),
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
export default meta;
|
|
112
|
+
|
|
113
|
+
type Story = StoryObj< typeof DateCalendar >;
|
|
114
|
+
|
|
115
|
+
export const Default: Story = {};
|
|
116
|
+
|
|
117
|
+
export const DisabledDates: Story = {
|
|
118
|
+
args: {
|
|
119
|
+
disabled: [
|
|
120
|
+
// Disable tomorrow (single date)
|
|
121
|
+
new Date( new Date().setDate( new Date().getDate() + 1 ) ),
|
|
122
|
+
// Disable all dates after Feb 1st of next year
|
|
123
|
+
{ after: new Date( new Date().getFullYear() + 1, 1, 1 ) },
|
|
124
|
+
// Disable all dates before Dec 1st of last year
|
|
125
|
+
{ before: new Date( new Date().getFullYear() - 1, 11, 1 ) },
|
|
126
|
+
// Disable all dates between 12th and 14th of August of this year
|
|
127
|
+
{
|
|
128
|
+
after: new Date( new Date().getFullYear(), 7, 11 ),
|
|
129
|
+
before: new Date( new Date().getFullYear(), 7, 15 ),
|
|
130
|
+
},
|
|
131
|
+
// Disable all dates between 21st and 26th of October of this year
|
|
132
|
+
{
|
|
133
|
+
from: new Date( new Date().getFullYear(), 9, 21 ),
|
|
134
|
+
to: new Date( new Date().getFullYear(), 9, 26 ),
|
|
135
|
+
},
|
|
136
|
+
// Disable all Wednesdays
|
|
137
|
+
{ dayOfWeek: 3 },
|
|
138
|
+
// Disable all prime day numbers
|
|
139
|
+
function isPrimeDate( date: Date ) {
|
|
140
|
+
return [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 ].includes(
|
|
141
|
+
date.getDate()
|
|
142
|
+
);
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const nextMonth = new Date().getMonth() === 11 ? 0 : new Date().getMonth() + 1;
|
|
149
|
+
const nextMonthYear =
|
|
150
|
+
new Date().getMonth() === 11
|
|
151
|
+
? new Date().getFullYear() + 1
|
|
152
|
+
: new Date().getFullYear();
|
|
153
|
+
const firstDayOfNextMonth = new Date( nextMonthYear, nextMonth, 1 );
|
|
154
|
+
export const WithSelectedDateAndMonth: Story = {
|
|
155
|
+
args: {
|
|
156
|
+
defaultSelected: firstDayOfNextMonth,
|
|
157
|
+
defaultMonth: firstDayOfNextMonth,
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* When working with time zones, use the `TZDate` object exported by this package instead of the native `Date` object.
|
|
163
|
+
*/
|
|
164
|
+
export const WithTimeZone: Story = {
|
|
165
|
+
render: function DateCalendarWithTimeZone( args ) {
|
|
166
|
+
const [ selected, setSelected ] = useState< TZDate | null >( null );
|
|
167
|
+
|
|
168
|
+
useEffect( () => {
|
|
169
|
+
setSelected(
|
|
170
|
+
// Select one week from today every time the time zone changes.
|
|
171
|
+
new TZDate(
|
|
172
|
+
new Date().setDate( new Date().getDate() + 7 ),
|
|
173
|
+
args.timeZone
|
|
174
|
+
)
|
|
175
|
+
);
|
|
176
|
+
}, [ args.timeZone ] );
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<>
|
|
180
|
+
<DateCalendar
|
|
181
|
+
{ ...args }
|
|
182
|
+
selected={ selected }
|
|
183
|
+
onSelect={ ( selectedDate, ...rest ) => {
|
|
184
|
+
setSelected(
|
|
185
|
+
selectedDate
|
|
186
|
+
? new TZDate( selectedDate, args.timeZone )
|
|
187
|
+
: null
|
|
188
|
+
);
|
|
189
|
+
args.onSelect?.( selectedDate, ...rest );
|
|
190
|
+
} }
|
|
191
|
+
disabled={ [
|
|
192
|
+
{
|
|
193
|
+
// Disable any date before today
|
|
194
|
+
before: new TZDate( new Date(), args.timeZone ),
|
|
195
|
+
},
|
|
196
|
+
] }
|
|
197
|
+
/>
|
|
198
|
+
|
|
199
|
+
<p>
|
|
200
|
+
Calendar set to { args.timeZone ?? 'current' } timezone,
|
|
201
|
+
disabling selection for all dates before today, and starting
|
|
202
|
+
with a default date of 1 week from today.
|
|
203
|
+
</p>
|
|
204
|
+
</>
|
|
205
|
+
);
|
|
206
|
+
},
|
|
207
|
+
args: {
|
|
208
|
+
timeZone: 'Pacific/Auckland',
|
|
209
|
+
},
|
|
210
|
+
argTypes: {
|
|
211
|
+
selected: {
|
|
212
|
+
control: false,
|
|
213
|
+
},
|
|
214
|
+
defaultSelected: {
|
|
215
|
+
control: false,
|
|
216
|
+
},
|
|
217
|
+
disabled: {
|
|
218
|
+
control: false,
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { fn } from '@storybook/test';
|
|
5
|
+
import {
|
|
6
|
+
enUS,
|
|
7
|
+
fr,
|
|
8
|
+
es,
|
|
9
|
+
de,
|
|
10
|
+
it,
|
|
11
|
+
he,
|
|
12
|
+
ru,
|
|
13
|
+
ja,
|
|
14
|
+
ptBR,
|
|
15
|
+
nl,
|
|
16
|
+
ko,
|
|
17
|
+
tr,
|
|
18
|
+
id,
|
|
19
|
+
zhCN,
|
|
20
|
+
zhTW,
|
|
21
|
+
ar,
|
|
22
|
+
sv,
|
|
23
|
+
} from 'date-fns/locale';
|
|
24
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
25
|
+
/**
|
|
26
|
+
* WordPress dependencies
|
|
27
|
+
*/
|
|
28
|
+
import { useState, useEffect } from '@wordpress/element';
|
|
29
|
+
/**
|
|
30
|
+
* Internal dependencies
|
|
31
|
+
*/
|
|
32
|
+
import { DateRangeCalendar, TZDate } from '..';
|
|
33
|
+
|
|
34
|
+
const meta: Meta< typeof DateRangeCalendar > = {
|
|
35
|
+
title: 'Components/Selection & Input/Time & Date/DateRangeCalendar',
|
|
36
|
+
component: DateRangeCalendar,
|
|
37
|
+
argTypes: {
|
|
38
|
+
locale: {
|
|
39
|
+
options: [
|
|
40
|
+
'English (US)',
|
|
41
|
+
'French',
|
|
42
|
+
'Spanish',
|
|
43
|
+
'German',
|
|
44
|
+
'Italian',
|
|
45
|
+
'Hebrew',
|
|
46
|
+
'Russian',
|
|
47
|
+
'Japanese',
|
|
48
|
+
'Portuguese (Brazil)',
|
|
49
|
+
'Dutch',
|
|
50
|
+
'Korean',
|
|
51
|
+
'Turkish',
|
|
52
|
+
'Indonesian',
|
|
53
|
+
'Chinese (Simplified)',
|
|
54
|
+
'Chinese (Traditional)',
|
|
55
|
+
'Arabic',
|
|
56
|
+
'Swedish',
|
|
57
|
+
],
|
|
58
|
+
mapping: {
|
|
59
|
+
'English (US)': enUS,
|
|
60
|
+
French: fr,
|
|
61
|
+
Spanish: es,
|
|
62
|
+
German: de,
|
|
63
|
+
Italian: it,
|
|
64
|
+
Hebrew: he,
|
|
65
|
+
Russian: ru,
|
|
66
|
+
Japanese: ja,
|
|
67
|
+
'Portuguese (Brazil)': ptBR,
|
|
68
|
+
Dutch: nl,
|
|
69
|
+
Korean: ko,
|
|
70
|
+
Turkish: tr,
|
|
71
|
+
Indonesian: id,
|
|
72
|
+
'Chinese (Simplified)': zhCN,
|
|
73
|
+
'Chinese (Traditional)': zhTW,
|
|
74
|
+
Arabic: ar,
|
|
75
|
+
Swedish: sv,
|
|
76
|
+
},
|
|
77
|
+
control: 'select',
|
|
78
|
+
},
|
|
79
|
+
timeZone: {
|
|
80
|
+
options: [
|
|
81
|
+
'Pacific/Honolulu',
|
|
82
|
+
'America/New_York',
|
|
83
|
+
'Europe/London',
|
|
84
|
+
'Asia/Tokyo',
|
|
85
|
+
'Pacific/Auckland',
|
|
86
|
+
],
|
|
87
|
+
control: 'select',
|
|
88
|
+
},
|
|
89
|
+
labels: {
|
|
90
|
+
control: false,
|
|
91
|
+
},
|
|
92
|
+
defaultSelected: { control: false },
|
|
93
|
+
selected: { control: false },
|
|
94
|
+
onSelect: {
|
|
95
|
+
control: false,
|
|
96
|
+
},
|
|
97
|
+
defaultMonth: { control: 'date' },
|
|
98
|
+
month: { control: 'date' },
|
|
99
|
+
onMonthChange: {
|
|
100
|
+
control: false,
|
|
101
|
+
},
|
|
102
|
+
endMonth: { control: 'date' },
|
|
103
|
+
startMonth: { control: 'date' },
|
|
104
|
+
},
|
|
105
|
+
args: {
|
|
106
|
+
onMonthChange: fn(),
|
|
107
|
+
onSelect: fn(),
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
export default meta;
|
|
111
|
+
|
|
112
|
+
type Story = StoryObj< typeof DateRangeCalendar >;
|
|
113
|
+
|
|
114
|
+
export const Default: Story = {};
|
|
115
|
+
|
|
116
|
+
export const DisabledDates: Story = {
|
|
117
|
+
args: {
|
|
118
|
+
disabled: [
|
|
119
|
+
// Disable tomorrow (single date)
|
|
120
|
+
new Date( new Date().setDate( new Date().getDate() + 1 ) ),
|
|
121
|
+
// Disable all dates after Feb 1st of next year
|
|
122
|
+
{ after: new Date( new Date().getFullYear() + 1, 1, 1 ) },
|
|
123
|
+
// Disable all dates before Dec 1st of last year
|
|
124
|
+
{ before: new Date( new Date().getFullYear() - 1, 11, 1 ) },
|
|
125
|
+
// Disable all dates between 12th and 14th of August of this year
|
|
126
|
+
{
|
|
127
|
+
after: new Date( new Date().getFullYear(), 7, 11 ),
|
|
128
|
+
before: new Date( new Date().getFullYear(), 7, 15 ),
|
|
129
|
+
},
|
|
130
|
+
// Disable all dates between 21st and 26th of October of this year
|
|
131
|
+
{
|
|
132
|
+
from: new Date( new Date().getFullYear(), 9, 21 ),
|
|
133
|
+
to: new Date( new Date().getFullYear(), 9, 26 ),
|
|
134
|
+
},
|
|
135
|
+
// Disable all Wednesdays
|
|
136
|
+
{ dayOfWeek: 3 },
|
|
137
|
+
// Disable all prime day numbers
|
|
138
|
+
function isPrimeDate( date: Date ) {
|
|
139
|
+
return [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 ].includes(
|
|
140
|
+
date.getDate()
|
|
141
|
+
);
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const nextMonth = new Date().getMonth() === 11 ? 0 : new Date().getMonth() + 1;
|
|
148
|
+
const nextMonthYear =
|
|
149
|
+
new Date().getMonth() === 11
|
|
150
|
+
? new Date().getFullYear() + 1
|
|
151
|
+
: new Date().getFullYear();
|
|
152
|
+
const firstDayOfNextMonth = new Date( nextMonthYear, nextMonth, 1 );
|
|
153
|
+
const fourthDayOfNextMonth = new Date( nextMonthYear, nextMonth, 4 );
|
|
154
|
+
export const WithSelectedRangeAndMonth: Story = {
|
|
155
|
+
args: {
|
|
156
|
+
defaultSelected: {
|
|
157
|
+
from: firstDayOfNextMonth,
|
|
158
|
+
to: fourthDayOfNextMonth,
|
|
159
|
+
},
|
|
160
|
+
defaultMonth: firstDayOfNextMonth,
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* When working with time zones, use the `TZDate` object exported by this package instead of the native `Date` object.
|
|
166
|
+
*/
|
|
167
|
+
export const WithTimeZone: Story = {
|
|
168
|
+
render: function DateCalendarWithTimeZone( args ) {
|
|
169
|
+
const [ range, setRange ] = useState< typeof args.selected | null >(
|
|
170
|
+
null
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
useEffect( () => {
|
|
174
|
+
setRange(
|
|
175
|
+
// Select from one week from today to two weeks from today
|
|
176
|
+
// every time the timezone changes.
|
|
177
|
+
{
|
|
178
|
+
from: new TZDate(
|
|
179
|
+
new Date().setDate( new Date().getDate() + 7 ),
|
|
180
|
+
args.timeZone
|
|
181
|
+
),
|
|
182
|
+
to: new TZDate(
|
|
183
|
+
new Date().setDate( new Date().getDate() + 14 ),
|
|
184
|
+
args.timeZone
|
|
185
|
+
),
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
}, [ args.timeZone ] );
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<>
|
|
192
|
+
<DateRangeCalendar
|
|
193
|
+
{ ...args }
|
|
194
|
+
selected={ range }
|
|
195
|
+
onSelect={ ( selectedDate, ...rest ) => {
|
|
196
|
+
setRange(
|
|
197
|
+
// Set controlled state to null if there's no selection
|
|
198
|
+
! selectedDate ||
|
|
199
|
+
( selectedDate.from === undefined &&
|
|
200
|
+
selectedDate.to === undefined )
|
|
201
|
+
? null
|
|
202
|
+
: selectedDate
|
|
203
|
+
);
|
|
204
|
+
args.onSelect?.( selectedDate, ...rest );
|
|
205
|
+
} }
|
|
206
|
+
disabled={ [
|
|
207
|
+
{
|
|
208
|
+
// Disable any date before today
|
|
209
|
+
before: new TZDate( new Date(), args.timeZone ),
|
|
210
|
+
},
|
|
211
|
+
] }
|
|
212
|
+
/>
|
|
213
|
+
<p>
|
|
214
|
+
Calendar set to { args.timeZone ?? 'current' } timezone,
|
|
215
|
+
disabling selection for all dates before today, and starting
|
|
216
|
+
with a default date range of 1 week from today to 2 weeks
|
|
217
|
+
from today.
|
|
218
|
+
</p>
|
|
219
|
+
</>
|
|
220
|
+
);
|
|
221
|
+
},
|
|
222
|
+
args: {
|
|
223
|
+
timeZone: 'Pacific/Auckland',
|
|
224
|
+
},
|
|
225
|
+
argTypes: {
|
|
226
|
+
disabled: {
|
|
227
|
+
control: false,
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
};
|