@wordpress/components 29.11.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 +22 -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-file-upload/index.js +4 -6
- package/build/form-file-upload/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/image/index.native.js +1 -1
- package/build/mobile/image/index.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-file-upload/index.js +4 -6
- package/build-module/form-file-upload/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/image/index.native.js +1 -1
- package/build-module/mobile/image/index.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-file-upload/index.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/circular-option-picker/stories/index.story.tsx +2 -2
- 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-file-upload/index.tsx +6 -12
- 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/image/index.native.js +1 -1
- 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,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
|
+
};
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
/* Root of the component. */
|
|
2
|
+
// Internal variables
|
|
3
|
+
$wp-components-calendar-outline-focus: var(--wp-admin-border-width-focus) solid $components-color-accent;
|
|
4
|
+
$wp-components-calendar-button-height: 2rem;
|
|
5
|
+
$wp-components-calendar-button-width: 2rem;
|
|
6
|
+
$wp-components-calendar-nav-height: 2rem;
|
|
7
|
+
$wp-components-calendar-range-middle-background-color: color-mix(in srgb, $components-color-accent 4%, transparent);
|
|
8
|
+
$wp-components-calendar-preview-border-color: color-mix(in srgb, $components-color-accent 16%, transparent);
|
|
9
|
+
|
|
10
|
+
.components-calendar {
|
|
11
|
+
// TODO: add font family rule when Theme is ready
|
|
12
|
+
|
|
13
|
+
position: relative; /* Required to position the navigation toolbar. */
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
display: inline flow-root;
|
|
16
|
+
color: $gray-900;
|
|
17
|
+
background-color: $white;
|
|
18
|
+
font-size: 13px;
|
|
19
|
+
font-weight: 400;
|
|
20
|
+
z-index: 0; // Create a stacking context and render on top of the background.
|
|
21
|
+
|
|
22
|
+
*,
|
|
23
|
+
*::before,
|
|
24
|
+
*::after {
|
|
25
|
+
box-sizing: border-box;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.components-calendar__day {
|
|
30
|
+
padding: 0;
|
|
31
|
+
position: relative;
|
|
32
|
+
|
|
33
|
+
// Setting text color on the day container instead of directly on the
|
|
34
|
+
// day button to ensure that the color of the dot used to indicate today's
|
|
35
|
+
// date follows the same color as the button's text, since the button
|
|
36
|
+
// inherits its text color.
|
|
37
|
+
&:has(.components-calendar__day-button:disabled) {
|
|
38
|
+
color: $gray-600;
|
|
39
|
+
}
|
|
40
|
+
&:has(.components-calendar__day-button:hover:not(:disabled)),
|
|
41
|
+
&:has(.components-calendar__day-button:focus-visible) {
|
|
42
|
+
color: $components-color-accent;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.components-calendar__day-button {
|
|
47
|
+
background: none;
|
|
48
|
+
padding: 0;
|
|
49
|
+
margin: 0;
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
align-items: center;
|
|
53
|
+
display: flex;
|
|
54
|
+
position: relative;
|
|
55
|
+
|
|
56
|
+
width: $wp-components-calendar-button-width;
|
|
57
|
+
height: $wp-components-calendar-button-height;
|
|
58
|
+
|
|
59
|
+
border: none;
|
|
60
|
+
border-radius: 2px;
|
|
61
|
+
|
|
62
|
+
font: inherit;
|
|
63
|
+
font-variant-numeric: tabular-nums;
|
|
64
|
+
color: inherit;
|
|
65
|
+
|
|
66
|
+
// Use the button's ::before to render date's background, which keeps the
|
|
67
|
+
// border-radius of the button intact. This technique allows the focus ring
|
|
68
|
+
// to have rounded corners even when the background needs square corners
|
|
69
|
+
// (eg. in the middle of a date range).
|
|
70
|
+
&::before {
|
|
71
|
+
content: "";
|
|
72
|
+
position: absolute;
|
|
73
|
+
z-index: -1;
|
|
74
|
+
inset: 0;
|
|
75
|
+
border: none; // No default border to avoid polluting high-contrast mode.
|
|
76
|
+
border-radius: 2px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Use the button's ::after to show the selection preview.
|
|
80
|
+
&::after {
|
|
81
|
+
content: "";
|
|
82
|
+
position: absolute;
|
|
83
|
+
z-index: 1;
|
|
84
|
+
inset: 0;
|
|
85
|
+
pointer-events: none;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&:disabled {
|
|
89
|
+
cursor: revert;
|
|
90
|
+
|
|
91
|
+
@media ( forced-colors: active ) {
|
|
92
|
+
// As an extra visual cue, show a line-through on disabled days
|
|
93
|
+
// in forced-colors (high-contrast) mode.
|
|
94
|
+
text-decoration: line-through;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
&:focus-visible {
|
|
99
|
+
outline: $wp-components-calendar-outline-focus;
|
|
100
|
+
outline-offset: 1px;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.components-calendar__caption-label {
|
|
105
|
+
z-index: 1;
|
|
106
|
+
|
|
107
|
+
position: relative;
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
|
|
111
|
+
white-space: nowrap;
|
|
112
|
+
border: 0;
|
|
113
|
+
|
|
114
|
+
text-transform: capitalize;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.components-calendar__button-next,
|
|
118
|
+
.components-calendar__button-previous {
|
|
119
|
+
border: none;
|
|
120
|
+
border-radius: 2px;
|
|
121
|
+
background: none;
|
|
122
|
+
padding: 0;
|
|
123
|
+
margin: 0;
|
|
124
|
+
cursor: pointer;
|
|
125
|
+
-moz-appearance: none;
|
|
126
|
+
-webkit-appearance: none;
|
|
127
|
+
display: inline-flex;
|
|
128
|
+
align-items: center;
|
|
129
|
+
justify-content: center;
|
|
130
|
+
position: relative;
|
|
131
|
+
appearance: none;
|
|
132
|
+
|
|
133
|
+
width: $wp-components-calendar-button-width;
|
|
134
|
+
height: $wp-components-calendar-button-height;
|
|
135
|
+
|
|
136
|
+
color: inherit;
|
|
137
|
+
|
|
138
|
+
&:disabled,
|
|
139
|
+
&[aria-disabled="true"] {
|
|
140
|
+
cursor: revert;
|
|
141
|
+
|
|
142
|
+
color: $gray-600;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
&:focus-visible {
|
|
146
|
+
outline: $wp-components-calendar-outline-focus;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.components-calendar__chevron {
|
|
151
|
+
display: inline-block;
|
|
152
|
+
fill: currentColor;
|
|
153
|
+
width: 16px;
|
|
154
|
+
height: 16px;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.components-calendar[dir="rtl"]
|
|
158
|
+
.components-calendar__nav
|
|
159
|
+
.components-calendar__chevron {
|
|
160
|
+
transform: rotate(180deg);
|
|
161
|
+
transform-origin: 50%;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.components-calendar__month-caption {
|
|
165
|
+
display: flex;
|
|
166
|
+
justify-content: center;
|
|
167
|
+
align-content: center;
|
|
168
|
+
|
|
169
|
+
height: $wp-components-calendar-nav-height;
|
|
170
|
+
margin-bottom: 12px;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.components-calendar__months {
|
|
174
|
+
position: relative;
|
|
175
|
+
display: flex;
|
|
176
|
+
justify-content: center;
|
|
177
|
+
flex-wrap: wrap;
|
|
178
|
+
gap: 1rem;
|
|
179
|
+
max-width: fit-content;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.components-calendar__month-grid {
|
|
183
|
+
border-collapse: separate;
|
|
184
|
+
border-spacing: 0 4px;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.components-calendar__nav {
|
|
188
|
+
position: absolute;
|
|
189
|
+
inset-block-start: 0;
|
|
190
|
+
inset-inline-start: 0;
|
|
191
|
+
inset-inline-end: 0;
|
|
192
|
+
|
|
193
|
+
display: flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
justify-content: space-between;
|
|
196
|
+
|
|
197
|
+
height: $wp-components-calendar-nav-height;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.components-calendar__weekday {
|
|
201
|
+
width: $wp-components-calendar-button-width;
|
|
202
|
+
height: $wp-components-calendar-button-height;
|
|
203
|
+
padding: 0;
|
|
204
|
+
|
|
205
|
+
color: $gray-700;
|
|
206
|
+
text-align: center;
|
|
207
|
+
text-transform: uppercase;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* DAY MODIFIERS */
|
|
211
|
+
// Today's date: show a dot in the top-right corner of the button
|
|
212
|
+
.components-calendar__day--today::after {
|
|
213
|
+
content: "";
|
|
214
|
+
position: absolute;
|
|
215
|
+
z-index: 1;
|
|
216
|
+
inset-block-start: 2px;
|
|
217
|
+
inset-inline-end: 2px;
|
|
218
|
+
width: 0;
|
|
219
|
+
height: 0;
|
|
220
|
+
border-radius: 50%;
|
|
221
|
+
border: 2px solid currentColor;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Selected date button (individual date, range start, and range end)
|
|
225
|
+
.components-calendar__day--selected:not(.components-calendar__range-middle) {
|
|
226
|
+
&:has(
|
|
227
|
+
.components-calendar__day-button,
|
|
228
|
+
.components-calendar__day-button:hover:not(:disabled)
|
|
229
|
+
) {
|
|
230
|
+
color: $white;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.components-calendar__day-button {
|
|
234
|
+
&::before {
|
|
235
|
+
background-color: $gray-900;
|
|
236
|
+
// Render a transparent border to highlight the selected day in
|
|
237
|
+
// forced-colors (high-contrast) mode, since the background is not
|
|
238
|
+
// visible.
|
|
239
|
+
border: 1px solid transparent;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
&:disabled::before {
|
|
243
|
+
background-color: $gray-600;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
&:hover:not(:disabled)::before {
|
|
247
|
+
background-color: $gray-800;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Hidden button (ie. outside current month but still rendered)
|
|
253
|
+
.components-calendar__day--hidden {
|
|
254
|
+
visibility: hidden;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Range start button, but not when start and end are the same day.
|
|
258
|
+
.components-calendar__range-start:not(.components-calendar__range-end)
|
|
259
|
+
.components-calendar__day-button {
|
|
260
|
+
// Apply border-radius changes to the button itself too, so that the focus
|
|
261
|
+
// ring follows the same shape as the button's background.
|
|
262
|
+
&,
|
|
263
|
+
&::before {
|
|
264
|
+
border-start-end-radius: 0;
|
|
265
|
+
border-end-end-radius: 0;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Middle of date range
|
|
270
|
+
.components-calendar__range-middle .components-calendar__day-button {
|
|
271
|
+
&::before {
|
|
272
|
+
background-color: $wp-components-calendar-range-middle-background-color;
|
|
273
|
+
border-radius: 0;
|
|
274
|
+
|
|
275
|
+
// Render a top and bottom transparent border to highlight the selected
|
|
276
|
+
// day in forced-colors (high-contrast) mode, since the background is not
|
|
277
|
+
// visible.
|
|
278
|
+
border-width: 1px 0;
|
|
279
|
+
border-color: transparent;
|
|
280
|
+
border-style: solid;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Range end button, but not when start and end are the same day.
|
|
285
|
+
.components-calendar__range-end:not(.components-calendar__range-start)
|
|
286
|
+
.components-calendar__day-button {
|
|
287
|
+
// Apply border-radius changes to the button itself too, so that the focus
|
|
288
|
+
// ring follows the same shape as the button's background.
|
|
289
|
+
&,
|
|
290
|
+
&::before {
|
|
291
|
+
border-start-start-radius: 0;
|
|
292
|
+
border-end-start-radius: 0;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/*
|
|
297
|
+
* RANGE PREVIEW (range calendar only)
|
|
298
|
+
*
|
|
299
|
+
* The preview is rendered in the button's ::after pseudo-element, so that it
|
|
300
|
+
* can be rendered over the button's contents.
|
|
301
|
+
* The selection preview is shown with a dashed border. In order to have
|
|
302
|
+
* control over the dash pattern (especially the seams between days), the
|
|
303
|
+
* dashed borders are rendered as SVGs via the url() CSS function.
|
|
304
|
+
* Since SVGs rendered in the url() function don't seem to be able to access
|
|
305
|
+
* CSS variables, we're using the SVGs as masks, and using `background-color`
|
|
306
|
+
* to consume the accent color variable.
|
|
307
|
+
*/
|
|
308
|
+
.components-calendar__day--preview svg {
|
|
309
|
+
position: absolute;
|
|
310
|
+
inset: 0;
|
|
311
|
+
pointer-events: none;
|
|
312
|
+
color: $wp-components-calendar-preview-border-color;
|
|
313
|
+
|
|
314
|
+
@media ( forced-colors: active ) {
|
|
315
|
+
color: inherit;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.components-calendar[dir="rtl"] & {
|
|
319
|
+
transform: scaleX(-1);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.components-calendar__day--preview.components-calendar__range-middle
|
|
324
|
+
.components-calendar__day-button::before {
|
|
325
|
+
// Remove the transparent border shown on the middle of the range
|
|
326
|
+
// in forced-colors (high-contrast) mode, to allow for the dashed border
|
|
327
|
+
// to be visible.
|
|
328
|
+
border: none;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/* ANIMATIONS */
|
|
332
|
+
@keyframes slide-in-left {
|
|
333
|
+
0% {
|
|
334
|
+
transform: translateX(-100%);
|
|
335
|
+
}
|
|
336
|
+
100% {
|
|
337
|
+
transform: translateX(0);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
@keyframes slide-in-right {
|
|
342
|
+
0% {
|
|
343
|
+
transform: translateX(100%);
|
|
344
|
+
}
|
|
345
|
+
100% {
|
|
346
|
+
transform: translateX(0);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
@keyframes slide-out-left {
|
|
351
|
+
0% {
|
|
352
|
+
transform: translateX(0);
|
|
353
|
+
}
|
|
354
|
+
100% {
|
|
355
|
+
transform: translateX(-100%);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
@keyframes slide-out-right {
|
|
360
|
+
0% {
|
|
361
|
+
transform: translateX(0);
|
|
362
|
+
}
|
|
363
|
+
100% {
|
|
364
|
+
transform: translateX(100%);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
@keyframes fade-in {
|
|
369
|
+
from {
|
|
370
|
+
opacity: 0;
|
|
371
|
+
}
|
|
372
|
+
to {
|
|
373
|
+
opacity: 1;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
@keyframes fade-out {
|
|
378
|
+
from {
|
|
379
|
+
opacity: 1;
|
|
380
|
+
}
|
|
381
|
+
to {
|
|
382
|
+
opacity: 0;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.components-calendar__weeks-before-enter,
|
|
387
|
+
.components-calendar__weeks-before-exit,
|
|
388
|
+
.components-calendar__weeks-after-enter,
|
|
389
|
+
.components-calendar__weeks-after-exit,
|
|
390
|
+
.components-calendar__caption-after-enter,
|
|
391
|
+
.components-calendar__caption-after-exit,
|
|
392
|
+
.components-calendar__caption-before-enter,
|
|
393
|
+
.components-calendar__caption-before-exit {
|
|
394
|
+
animation-duration: 0s;
|
|
395
|
+
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
396
|
+
animation-fill-mode: forwards;
|
|
397
|
+
|
|
398
|
+
@media not ( prefers-reduced-motion ) {
|
|
399
|
+
animation-duration: 0.3s;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.components-calendar__weeks-before-enter,
|
|
404
|
+
.components-calendar[dir="rtl"] .components-calendar__weeks-after-enter {
|
|
405
|
+
animation-name: slide-in-left;
|
|
406
|
+
}
|
|
407
|
+
.components-calendar__weeks-before-exit,
|
|
408
|
+
.components-calendar[dir="rtl"] .components-calendar__weeks-after-exit {
|
|
409
|
+
animation-name: slide-out-left;
|
|
410
|
+
}
|
|
411
|
+
.components-calendar__weeks-after-enter,
|
|
412
|
+
.components-calendar[dir="rtl"] .components-calendar__weeks-before-enter {
|
|
413
|
+
animation-name: slide-in-right;
|
|
414
|
+
}
|
|
415
|
+
.components-calendar__weeks-after-exit,
|
|
416
|
+
.components-calendar[dir="rtl"] .components-calendar__weeks-before-exit {
|
|
417
|
+
animation-name: slide-out-right;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.components-calendar__caption-after-enter {
|
|
421
|
+
animation-name: fade-in;
|
|
422
|
+
}
|
|
423
|
+
.components-calendar__caption-after-exit {
|
|
424
|
+
animation-name: fade-out;
|
|
425
|
+
}
|
|
426
|
+
.components-calendar__caption-before-enter {
|
|
427
|
+
animation-name: fade-in;
|
|
428
|
+
}
|
|
429
|
+
.components-calendar__caption-before-exit {
|
|
430
|
+
animation-name: fade-out;
|
|
431
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { screen } from '@testing-library/react';
|
|
5
|
+
|
|
6
|
+
export const monthNameFormatter = ( localeCode: string, timeZone?: string ) =>
|
|
7
|
+
new Intl.DateTimeFormat( localeCode, {
|
|
8
|
+
year: 'numeric',
|
|
9
|
+
month: 'long',
|
|
10
|
+
timeZone,
|
|
11
|
+
} );
|
|
12
|
+
|
|
13
|
+
const fullDateFormatter = ( localeCode: string, timeZone?: string ) =>
|
|
14
|
+
new Intl.DateTimeFormat( localeCode, {
|
|
15
|
+
weekday: 'long',
|
|
16
|
+
year: 'numeric',
|
|
17
|
+
month: 'long',
|
|
18
|
+
day: 'numeric',
|
|
19
|
+
timeZone,
|
|
20
|
+
} );
|
|
21
|
+
|
|
22
|
+
export const dateNumberFormatter = ( localeCode: string, timeZone?: string ) =>
|
|
23
|
+
new Intl.DateTimeFormat( localeCode, {
|
|
24
|
+
day: 'numeric',
|
|
25
|
+
timeZone,
|
|
26
|
+
} );
|
|
27
|
+
|
|
28
|
+
export const getDateButton = (
|
|
29
|
+
date: Date,
|
|
30
|
+
options?: Parameters< typeof screen.getByRole >[ 1 ],
|
|
31
|
+
locale = 'en-US'
|
|
32
|
+
) =>
|
|
33
|
+
screen.getByRole( 'button', {
|
|
34
|
+
name: new RegExp( fullDateFormatter( locale ).format( date ) ),
|
|
35
|
+
...options,
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
export const getDateCell = (
|
|
39
|
+
date: Date,
|
|
40
|
+
options?: Parameters< typeof screen.getByRole >[ 1 ],
|
|
41
|
+
locale = 'en-US'
|
|
42
|
+
) =>
|
|
43
|
+
screen.getByRole( 'gridcell', {
|
|
44
|
+
name: dateNumberFormatter( locale ).format( date ),
|
|
45
|
+
...options,
|
|
46
|
+
} );
|
|
47
|
+
|
|
48
|
+
export const queryDateCell = (
|
|
49
|
+
date: Date,
|
|
50
|
+
options?: Parameters< typeof screen.getByRole >[ 1 ],
|
|
51
|
+
locale = 'en-US'
|
|
52
|
+
) =>
|
|
53
|
+
screen.queryByRole( 'gridcell', {
|
|
54
|
+
name: dateNumberFormatter( locale ).format( date ),
|
|
55
|
+
...options,
|
|
56
|
+
} );
|