@wordpress/components 30.8.2-next.dc3f6d3c1.0 → 30.9.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 +5 -1
- package/build/date-time/date/index.js +5 -5
- package/build/date-time/date/index.js.map +2 -2
- package/build/date-time/utils.js +3 -1
- package/build/date-time/utils.js.map +2 -2
- package/build/external-link/index.js +1 -1
- package/build/external-link/index.js.map +2 -2
- package/build-module/date-time/date/index.js +6 -6
- package/build-module/date-time/date/index.js.map +2 -2
- package/build-module/date-time/utils.js +3 -1
- package/build-module/date-time/utils.js.map +2 -2
- package/build-module/external-link/index.js +2 -2
- package/build-module/external-link/index.js.map +2 -2
- package/build-style/style-rtl.css +8 -0
- package/build-style/style.css +8 -0
- package/build-types/alignment-matrix-control/stories/index.story.d.ts.map +1 -1
- package/build-types/angle-picker-control/stories/index.story.d.ts.map +1 -1
- package/build-types/box-control/stories/index.story.d.ts.map +1 -1
- package/build-types/circular-option-picker/stories/index.story.d.ts.map +1 -1
- package/build-types/color-picker/stories/index.story.d.ts.map +1 -1
- package/build-types/combobox-control/stories/index.story.d.ts.map +1 -1
- package/build-types/confirm-dialog/stories/index.story.d.ts.map +1 -1
- package/build-types/custom-gradient-picker/stories/index.story.d.ts.map +1 -1
- package/build-types/custom-select-control/stories/index.story.d.ts.map +1 -1
- package/build-types/custom-select-control-v2/stories/index.story.d.ts.map +1 -1
- package/build-types/date-time/date/index.d.ts.map +1 -1
- package/build-types/date-time/date-time/test/index.d.ts +2 -0
- package/build-types/date-time/date-time/test/index.d.ts.map +1 -0
- package/build-types/date-time/test/utils.test.d.ts +2 -0
- package/build-types/date-time/test/utils.test.d.ts.map +1 -0
- package/build-types/date-time/utils.d.ts +3 -2
- package/build-types/date-time/utils.d.ts.map +1 -1
- package/build-types/draggable/stories/index.story.d.ts.map +1 -1
- package/build-types/drop-zone/stories/index.story.d.ts.map +1 -1
- package/build-types/dropdown/stories/index.story.d.ts.map +1 -1
- package/build-types/dropdown-menu/stories/index.story.d.ts.map +1 -1
- package/build-types/focal-point-picker/stories/index.story.d.ts.map +1 -1
- package/build-types/font-size-picker/stories/index.story.d.ts.map +1 -1
- package/build-types/gradient-picker/stories/index.story.d.ts.map +1 -1
- package/build-types/input-control/stories/index.story.d.ts.map +1 -1
- package/build-types/menu/stories/index.story.d.ts.map +1 -1
- package/build-types/navigable-container/stories/navigable-menu.story.d.ts.map +1 -1
- package/build-types/navigable-container/stories/tabbable-container.story.d.ts.map +1 -1
- package/build-types/navigation/stories/index.story.d.ts.map +1 -1
- package/build-types/notice/stories/index.story.d.ts.map +1 -1
- package/build-types/palette-edit/stories/index.story.d.ts.map +1 -1
- package/build-types/query-controls/stories/index.story.d.ts.map +1 -1
- package/build-types/radio-group/stories/index.story.d.ts.map +1 -1
- package/build-types/range-control/stories/index.story.d.ts.map +1 -1
- package/build-types/sandbox/stories/index.story.d.ts.map +1 -1
- package/build-types/select-control/stories/index.story.d.ts.map +1 -1
- package/build-types/tab-panel/stories/index.story.d.ts.map +1 -1
- package/build-types/tabs/stories/index.story.d.ts.map +1 -1
- package/build-types/text/stories/index.story.d.ts.map +1 -1
- package/build-types/tools-panel/stories/index.story.d.ts.map +1 -1
- package/build-types/tree-grid/stories/index.story.d.ts.map +1 -1
- package/build-types/unit-control/stories/index.story.d.ts.map +1 -1
- package/package.json +24 -20
- package/src/alignment-matrix-control/stories/index.story.tsx +4 -1
- package/src/angle-picker-control/stories/index.story.tsx +4 -1
- package/src/box-control/stories/index.story.tsx +4 -1
- package/src/circular-option-picker/stories/index.story.tsx +0 -1
- package/src/color-picker/stories/index.story.tsx +4 -1
- package/src/combobox-control/stories/index.story.tsx +5 -1
- package/src/confirm-dialog/stories/index.story.tsx +5 -1
- package/src/custom-gradient-picker/stories/index.story.tsx +4 -1
- package/src/custom-select-control/stories/index.story.tsx +4 -1
- package/src/custom-select-control-v2/stories/index.story.tsx +0 -1
- package/src/date-time/date/index.tsx +6 -16
- package/src/date-time/date-time/test/index.tsx +206 -0
- package/src/date-time/test/utils.test.ts +128 -0
- package/src/date-time/utils.ts +12 -3
- package/src/draggable/stories/index.story.tsx +6 -1
- package/src/drop-zone/stories/index.story.tsx +6 -1
- package/src/dropdown/stories/index.story.tsx +5 -1
- package/src/dropdown-menu/stories/index.story.tsx +4 -1
- package/src/external-link/index.tsx +2 -2
- package/src/focal-point-picker/stories/index.story.tsx +7 -1
- package/src/font-size-picker/stories/index.story.tsx +4 -1
- package/src/gradient-picker/stories/index.story.tsx +5 -1
- package/src/input-control/stories/index.story.tsx +7 -1
- package/src/menu/stories/index.story.tsx +4 -1
- package/src/modal/style.scss +14 -0
- package/src/navigable-container/stories/navigable-menu.story.tsx +5 -1
- package/src/navigable-container/stories/tabbable-container.story.tsx +5 -1
- package/src/navigation/stories/index.story.tsx +4 -1
- package/src/notice/stories/index.story.tsx +5 -1
- package/src/palette-edit/stories/index.story.tsx +4 -1
- package/src/query-controls/stories/index.story.tsx +8 -1
- package/src/radio-group/stories/index.story.tsx +4 -1
- package/src/range-control/stories/index.story.tsx +8 -1
- package/src/sandbox/stories/index.story.tsx +4 -1
- package/src/select-control/stories/index.story.tsx +4 -1
- package/src/tab-panel/stories/index.story.tsx +0 -1
- package/src/tabs/stories/index.story.tsx +0 -1
- package/src/text/stories/index.story.tsx +0 -1
- package/src/tools-panel/stories/index.story.tsx +4 -1
- package/src/tree-grid/stories/index.story.tsx +6 -1
- package/src/unit-control/stories/index.story.tsx +7 -1
- package/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- /package/src/context/stories/{ComponentsProvider.stories.js → ComponentsProvider.stories.jsx} +0 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { render, screen } from '@testing-library/react';
|
|
5
|
+
import userEvent from '@testing-library/user-event';
|
|
6
|
+
import timezoneMock from 'timezone-mock';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* WordPress dependencies
|
|
10
|
+
*/
|
|
11
|
+
import { getSettings, setSettings, type DateSettings } from '@wordpress/date';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Internal dependencies
|
|
15
|
+
*/
|
|
16
|
+
import DateTimePicker from '..';
|
|
17
|
+
|
|
18
|
+
describe( 'DateTimePicker', () => {
|
|
19
|
+
let originalSettings: DateSettings;
|
|
20
|
+
beforeAll( () => {
|
|
21
|
+
originalSettings = getSettings();
|
|
22
|
+
setSettings( {
|
|
23
|
+
...originalSettings,
|
|
24
|
+
timezone: {
|
|
25
|
+
offset: -5,
|
|
26
|
+
offsetFormatted: '-5',
|
|
27
|
+
string: 'America/New_York',
|
|
28
|
+
abbr: 'EST',
|
|
29
|
+
},
|
|
30
|
+
} );
|
|
31
|
+
} );
|
|
32
|
+
|
|
33
|
+
afterEach( () => {
|
|
34
|
+
jest.restoreAllMocks();
|
|
35
|
+
timezoneMock.unregister();
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
afterAll( () => {
|
|
39
|
+
setSettings( originalSettings );
|
|
40
|
+
} );
|
|
41
|
+
|
|
42
|
+
it( 'should display and select dates correctly when timezones match', async () => {
|
|
43
|
+
const user = userEvent.setup();
|
|
44
|
+
const onChange = jest.fn();
|
|
45
|
+
|
|
46
|
+
timezoneMock.register( 'US/Eastern' );
|
|
47
|
+
|
|
48
|
+
const { rerender } = render(
|
|
49
|
+
<DateTimePicker
|
|
50
|
+
currentDate="2025-11-15T00:00:00"
|
|
51
|
+
onChange={ onChange }
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
expect(
|
|
56
|
+
screen.getByRole( 'button', {
|
|
57
|
+
name: 'November 15, 2025. Selected',
|
|
58
|
+
} )
|
|
59
|
+
).toBeVisible();
|
|
60
|
+
|
|
61
|
+
onChange.mockImplementation( ( newDate ) => {
|
|
62
|
+
rerender(
|
|
63
|
+
<DateTimePicker currentDate={ newDate } onChange={ onChange } />
|
|
64
|
+
);
|
|
65
|
+
} );
|
|
66
|
+
|
|
67
|
+
await user.click(
|
|
68
|
+
screen.getByRole( 'button', { name: 'November 20, 2025' } )
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
expect( onChange ).toHaveBeenCalledWith( '2025-11-20T00:00:00' );
|
|
72
|
+
expect(
|
|
73
|
+
screen.getByRole( 'button', {
|
|
74
|
+
name: 'November 20, 2025. Selected',
|
|
75
|
+
} )
|
|
76
|
+
).toBeVisible();
|
|
77
|
+
} );
|
|
78
|
+
|
|
79
|
+
describe( 'timezone differences between browser and site', () => {
|
|
80
|
+
describe.each( [
|
|
81
|
+
{
|
|
82
|
+
direction: 'browser behind site',
|
|
83
|
+
timezone: 'US/Pacific' as const,
|
|
84
|
+
time: '21:00:00', // Evening: shifts to next day UTC
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
// Test a scenario where local time is UTC time, to verify that
|
|
88
|
+
// using gmdateI18n (UTC) for formatting works correctly when
|
|
89
|
+
// the browser's timezone already has no offset from UTC.
|
|
90
|
+
direction: 'browser matches UTC (zero offset)',
|
|
91
|
+
timezone: 'UTC' as const,
|
|
92
|
+
time: '00:00:00',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
direction: 'browser ahead of site',
|
|
96
|
+
timezone: 'Australia/Adelaide' as const,
|
|
97
|
+
time: '00:00:00', // Midnight: shifts to previous day UTC
|
|
98
|
+
},
|
|
99
|
+
] )( '$direction', ( { timezone, time } ) => {
|
|
100
|
+
describe.each( [
|
|
101
|
+
{
|
|
102
|
+
period: 'DST start',
|
|
103
|
+
initialDate: `2025-03-10T${ time }`,
|
|
104
|
+
initialButton: 'March 10, 2025. Selected',
|
|
105
|
+
clickButton: 'March 11, 2025',
|
|
106
|
+
expectedDay: 11,
|
|
107
|
+
expectedDate: `2025-03-11T${ time }`,
|
|
108
|
+
selectedButton: 'March 11, 2025. Selected',
|
|
109
|
+
wrongMonthButton: 'February 28, 2025',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
period: 'DST end',
|
|
113
|
+
initialDate: `2025-11-01T${ time }`,
|
|
114
|
+
initialButton: 'November 1, 2025. Selected',
|
|
115
|
+
clickButton: 'November 2, 2025',
|
|
116
|
+
expectedDay: 2,
|
|
117
|
+
expectedDate: `2025-11-02T${ time }`,
|
|
118
|
+
selectedButton: 'November 2, 2025. Selected',
|
|
119
|
+
wrongMonthButton: 'October 31, 2025',
|
|
120
|
+
},
|
|
121
|
+
] )(
|
|
122
|
+
'$period',
|
|
123
|
+
( {
|
|
124
|
+
initialDate,
|
|
125
|
+
initialButton,
|
|
126
|
+
clickButton,
|
|
127
|
+
expectedDay,
|
|
128
|
+
expectedDate,
|
|
129
|
+
selectedButton,
|
|
130
|
+
wrongMonthButton,
|
|
131
|
+
} ) => {
|
|
132
|
+
it( 'should display and select dates correctly', async () => {
|
|
133
|
+
const user = userEvent.setup();
|
|
134
|
+
const onChange = jest.fn();
|
|
135
|
+
|
|
136
|
+
timezoneMock.register( timezone );
|
|
137
|
+
|
|
138
|
+
const { rerender } = render(
|
|
139
|
+
<DateTimePicker
|
|
140
|
+
currentDate={ initialDate }
|
|
141
|
+
onChange={ onChange }
|
|
142
|
+
/>
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// Calendar should not show dates from wrong month
|
|
146
|
+
expect(
|
|
147
|
+
screen.queryByRole( 'button', {
|
|
148
|
+
name: wrongMonthButton,
|
|
149
|
+
} )
|
|
150
|
+
).not.toBeInTheDocument();
|
|
151
|
+
|
|
152
|
+
// Should show correct initial date as selected
|
|
153
|
+
expect(
|
|
154
|
+
screen.getByRole( 'button', {
|
|
155
|
+
name: initialButton,
|
|
156
|
+
} )
|
|
157
|
+
).toBeVisible();
|
|
158
|
+
|
|
159
|
+
onChange.mockImplementation( ( newDate ) => {
|
|
160
|
+
rerender(
|
|
161
|
+
<DateTimePicker
|
|
162
|
+
currentDate={ newDate }
|
|
163
|
+
onChange={ onChange }
|
|
164
|
+
/>
|
|
165
|
+
);
|
|
166
|
+
} );
|
|
167
|
+
|
|
168
|
+
await user.click(
|
|
169
|
+
screen.getByRole( 'button', { name: clickButton } )
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
expect( screen.getByLabelText( 'Day' ) ).toHaveValue(
|
|
173
|
+
expectedDay
|
|
174
|
+
);
|
|
175
|
+
expect( onChange ).toHaveBeenCalledWith( expectedDate );
|
|
176
|
+
expect(
|
|
177
|
+
screen.getByRole( 'button', {
|
|
178
|
+
name: selectedButton,
|
|
179
|
+
} )
|
|
180
|
+
).toBeVisible();
|
|
181
|
+
} );
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
} );
|
|
185
|
+
} );
|
|
186
|
+
|
|
187
|
+
it( 'should preserve time when changing date', async () => {
|
|
188
|
+
const user = userEvent.setup();
|
|
189
|
+
const onChange = jest.fn();
|
|
190
|
+
|
|
191
|
+
timezoneMock.register( 'UTC' );
|
|
192
|
+
|
|
193
|
+
render(
|
|
194
|
+
<DateTimePicker
|
|
195
|
+
currentDate="2025-11-15T14:30:00"
|
|
196
|
+
onChange={ onChange }
|
|
197
|
+
/>
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
await user.click(
|
|
201
|
+
screen.getByRole( 'button', { name: 'November 20, 2025' } )
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
expect( onChange ).toHaveBeenCalledWith( '2025-11-20T14:30:00' );
|
|
205
|
+
} );
|
|
206
|
+
} );
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import timezoneMock from 'timezone-mock';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { inputToDate } from '../utils';
|
|
10
|
+
|
|
11
|
+
describe( 'inputToDate', () => {
|
|
12
|
+
describe( 'timezoneless strings parsed as UTC', () => {
|
|
13
|
+
describe.each( [
|
|
14
|
+
{
|
|
15
|
+
timezone: 'US/Pacific' as const,
|
|
16
|
+
description: 'Pacific time (behind UTC)',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
timezone: 'UTC' as const,
|
|
20
|
+
description: 'UTC (zero offset)',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
timezone: 'Australia/Adelaide' as const,
|
|
24
|
+
description: 'Adelaide (ahead of UTC)',
|
|
25
|
+
},
|
|
26
|
+
] )( 'in $description', ( { timezone } ) => {
|
|
27
|
+
beforeEach( () => {
|
|
28
|
+
timezoneMock.register( timezone );
|
|
29
|
+
} );
|
|
30
|
+
|
|
31
|
+
afterEach( () => {
|
|
32
|
+
timezoneMock.unregister();
|
|
33
|
+
} );
|
|
34
|
+
|
|
35
|
+
it( 'should parse midnight as UTC midnight, preventing day shifts', () => {
|
|
36
|
+
const result = inputToDate( '2025-11-01T00:00:00' );
|
|
37
|
+
|
|
38
|
+
// Should always be Nov 1 00:00 in UTC, regardless of browser timezone
|
|
39
|
+
expect( result.getUTCFullYear() ).toBe( 2025 );
|
|
40
|
+
expect( result.getUTCMonth() ).toBe( 10 ); // November (0-indexed)
|
|
41
|
+
expect( result.getUTCDate() ).toBe( 1 );
|
|
42
|
+
expect( result.getUTCHours() ).toBe( 0 );
|
|
43
|
+
expect( result.getUTCMinutes() ).toBe( 0 );
|
|
44
|
+
expect( result.getUTCSeconds() ).toBe( 0 );
|
|
45
|
+
} );
|
|
46
|
+
|
|
47
|
+
it( 'should preserve non-midnight times in UTC, preventing day shifts', () => {
|
|
48
|
+
const result = inputToDate( '2025-06-20T15:30:45' );
|
|
49
|
+
|
|
50
|
+
expect( result.getUTCFullYear() ).toBe( 2025 );
|
|
51
|
+
expect( result.getUTCMonth() ).toBe( 5 ); // June (0-indexed)
|
|
52
|
+
expect( result.getUTCDate() ).toBe( 20 );
|
|
53
|
+
expect( result.getUTCHours() ).toBe( 15 );
|
|
54
|
+
expect( result.getUTCMinutes() ).toBe( 30 );
|
|
55
|
+
expect( result.getUTCSeconds() ).toBe( 45 );
|
|
56
|
+
} );
|
|
57
|
+
|
|
58
|
+
it( 'should parse date-only strings as midnight UTC', () => {
|
|
59
|
+
const result = inputToDate( '2025-03-15' );
|
|
60
|
+
|
|
61
|
+
expect( result.getUTCFullYear() ).toBe( 2025 );
|
|
62
|
+
expect( result.getUTCMonth() ).toBe( 2 ); // March (0-indexed)
|
|
63
|
+
expect( result.getUTCDate() ).toBe( 15 );
|
|
64
|
+
expect( result.getUTCHours() ).toBe( 0 );
|
|
65
|
+
expect( result.getUTCMinutes() ).toBe( 0 );
|
|
66
|
+
expect( result.getUTCSeconds() ).toBe( 0 );
|
|
67
|
+
} );
|
|
68
|
+
} );
|
|
69
|
+
} );
|
|
70
|
+
|
|
71
|
+
describe( 'strings with timezone indicators', () => {
|
|
72
|
+
describe.each( [
|
|
73
|
+
{
|
|
74
|
+
input: '2025-11-01T00:00:00Z',
|
|
75
|
+
expectedHour: 0,
|
|
76
|
+
expectedMinute: 0,
|
|
77
|
+
description: 'Z suffix',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
input: '2025-11-01T10:00:00+05:30',
|
|
81
|
+
expectedHour: 4,
|
|
82
|
+
expectedMinute: 30,
|
|
83
|
+
description: '+HH:MM offset',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
input: '2025-11-01T10:00:00-08:00',
|
|
87
|
+
expectedHour: 18,
|
|
88
|
+
expectedMinute: 0,
|
|
89
|
+
description: '-HH:MM offset',
|
|
90
|
+
},
|
|
91
|
+
// There's a few other valid formats in ISO-8601 (HHMM, HH, etc.),
|
|
92
|
+
// but those aren't included in the ECMAScript specification, which
|
|
93
|
+
// only includes "Z"-suffixed or "HH:mm"-suffixed strings.
|
|
94
|
+
//
|
|
95
|
+
// See: https://tc39.es/ecma262/#sec-date-time-string-format
|
|
96
|
+
] )( '$description', ( { input, expectedHour, expectedMinute } ) => {
|
|
97
|
+
it( 'should respect explicit timezone offset', () => {
|
|
98
|
+
const result = inputToDate( input );
|
|
99
|
+
|
|
100
|
+
expect( result.getUTCFullYear() ).toBe( 2025 );
|
|
101
|
+
expect( result.getUTCMonth() ).toBe( 10 ); // November
|
|
102
|
+
expect( result.getUTCDate() ).toBe( 1 );
|
|
103
|
+
expect( result.getUTCHours() ).toBe( expectedHour );
|
|
104
|
+
expect( result.getUTCMinutes() ).toBe( expectedMinute );
|
|
105
|
+
} );
|
|
106
|
+
} );
|
|
107
|
+
} );
|
|
108
|
+
|
|
109
|
+
describe( 'non-string inputs', () => {
|
|
110
|
+
it( 'should handle Date objects', () => {
|
|
111
|
+
const input = new Date( '2025-11-01T00:00:00Z' );
|
|
112
|
+
const result = inputToDate( input );
|
|
113
|
+
|
|
114
|
+
expect( result.getUTCFullYear() ).toBe( 2025 );
|
|
115
|
+
expect( result.getUTCMonth() ).toBe( 10 );
|
|
116
|
+
expect( result.getUTCDate() ).toBe( 1 );
|
|
117
|
+
} );
|
|
118
|
+
|
|
119
|
+
it( 'should convert timestamps to Date', () => {
|
|
120
|
+
const timestamp = Date.UTC( 2025, 10, 1, 0, 0, 0 );
|
|
121
|
+
const result = inputToDate( timestamp );
|
|
122
|
+
|
|
123
|
+
expect( result.getUTCFullYear() ).toBe( 2025 );
|
|
124
|
+
expect( result.getUTCMonth() ).toBe( 10 );
|
|
125
|
+
expect( result.getUTCDate() ).toBe( 1 );
|
|
126
|
+
} );
|
|
127
|
+
} );
|
|
128
|
+
} );
|
package/src/date-time/utils.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { toDate } from 'date-fns';
|
|
5
|
+
import { UTCDateMini } from '@date-fns/utc';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Internal dependencies
|
|
@@ -11,14 +12,22 @@ import type { InputAction } from '../input-control/reducer/actions';
|
|
|
11
12
|
import { COMMIT, PRESS_DOWN, PRESS_UP } from '../input-control/reducer/actions';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
|
-
* Like date-
|
|
15
|
-
* given.
|
|
15
|
+
* Like date-fns's toDate, but tries to guess the format when a string is
|
|
16
|
+
* given. For timezoneless strings, parse it as UTC using `@date-fns/utc` to
|
|
17
|
+
* ensure calendar dates remain consistent across different browser timezones.
|
|
16
18
|
*
|
|
17
19
|
* @param input Value to turn into a date.
|
|
18
20
|
*/
|
|
19
21
|
export function inputToDate( input: Date | string | number ): Date {
|
|
20
22
|
if ( typeof input === 'string' ) {
|
|
21
|
-
|
|
23
|
+
// Strings without timezone indicators are parsed as UTC to prevent day-
|
|
24
|
+
// shift bugs across browser timezones. Note that JavaScript doesn't
|
|
25
|
+
// fully support ISO-8601 time strings, so the behavior of passing these
|
|
26
|
+
// through to the Date constructor is non-deterministic.
|
|
27
|
+
//
|
|
28
|
+
// See: https://tc39.es/ecma262/#sec-date-time-string-format
|
|
29
|
+
const hasTimezone = /Z|[+-]\d{2}(:?\d{2})?$/.test( input );
|
|
30
|
+
return hasTimezone ? new Date( input ) : new UTCDateMini( input + 'Z' );
|
|
22
31
|
}
|
|
23
32
|
return toDate( input );
|
|
24
33
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta, StoryFn } from '@storybook/react';
|
|
5
5
|
import type { DragEvent } from 'react';
|
|
6
|
+
import { fn } from '@storybook/test';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* WordPress dependencies
|
|
@@ -24,8 +25,12 @@ const meta: Meta< typeof Draggable > = {
|
|
|
24
25
|
elementId: { control: false },
|
|
25
26
|
__experimentalDragComponent: { control: false },
|
|
26
27
|
},
|
|
28
|
+
args: {
|
|
29
|
+
onDragStart: fn(),
|
|
30
|
+
onDragEnd: fn(),
|
|
31
|
+
onDragOver: fn(),
|
|
32
|
+
},
|
|
27
33
|
parameters: {
|
|
28
|
-
actions: { argTypesRegex: '^on.*' },
|
|
29
34
|
controls: { expanded: true },
|
|
30
35
|
docs: { source: { code: '' } },
|
|
31
36
|
},
|
|
@@ -7,6 +7,7 @@ import type { Meta, StoryFn } from '@storybook/react';
|
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
9
|
import { upload, media } from '@wordpress/icons';
|
|
10
|
+
import { fn } from '@storybook/test';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Internal dependencies
|
|
@@ -26,8 +27,12 @@ const meta: Meta< typeof DropZone > = {
|
|
|
26
27
|
mapping: ICONS,
|
|
27
28
|
},
|
|
28
29
|
},
|
|
30
|
+
args: {
|
|
31
|
+
onFilesDrop: fn(),
|
|
32
|
+
onHTMLDrop: fn(),
|
|
33
|
+
onDrop: fn(),
|
|
34
|
+
},
|
|
29
35
|
parameters: {
|
|
30
|
-
actions: { argTypesRegex: '^on.*' },
|
|
31
36
|
controls: { expanded: true },
|
|
32
37
|
docs: { canvas: { sourceState: 'shown' } },
|
|
33
38
|
},
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
5
|
+
import { fn } from '@storybook/test';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Internal dependencies
|
|
@@ -18,6 +19,10 @@ const meta: Meta< typeof Dropdown > = {
|
|
|
18
19
|
component: Dropdown,
|
|
19
20
|
// @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
|
|
20
21
|
subcomponents: { DropdownContentWrapper },
|
|
22
|
+
args: {
|
|
23
|
+
onClose: fn(),
|
|
24
|
+
onToggle: fn(),
|
|
25
|
+
},
|
|
21
26
|
argTypes: {
|
|
22
27
|
focusOnMount: {
|
|
23
28
|
options: [ 'firstElement', true, false ],
|
|
@@ -34,7 +39,6 @@ const meta: Meta< typeof Dropdown > = {
|
|
|
34
39
|
onClose: { control: false },
|
|
35
40
|
},
|
|
36
41
|
parameters: {
|
|
37
|
-
actions: { argTypesRegex: '^on.*' },
|
|
38
42
|
controls: {
|
|
39
43
|
expanded: true,
|
|
40
44
|
},
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
5
|
+
import { fn } from '@storybook/test';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Internal dependencies
|
|
@@ -27,10 +28,12 @@ const meta: Meta< typeof DropdownMenu > = {
|
|
|
27
28
|
component: DropdownMenu,
|
|
28
29
|
id: 'components-dropdownmenu',
|
|
29
30
|
parameters: {
|
|
30
|
-
actions: { argTypesRegex: '^on.*' },
|
|
31
31
|
controls: { expanded: true },
|
|
32
32
|
docs: { canvas: { sourceState: 'shown' } },
|
|
33
33
|
},
|
|
34
|
+
args: {
|
|
35
|
+
onToggle: fn(),
|
|
36
|
+
},
|
|
34
37
|
argTypes: {
|
|
35
38
|
icon: {
|
|
36
39
|
options: [ 'menu', 'chevronDown', 'more' ],
|
|
@@ -7,7 +7,7 @@ import type { ForwardedRef } from 'react';
|
|
|
7
7
|
/**
|
|
8
8
|
* WordPress dependencies
|
|
9
9
|
*/
|
|
10
|
-
import { __ } from '@wordpress/i18n';
|
|
10
|
+
import { __, isRTL } from '@wordpress/i18n';
|
|
11
11
|
import { forwardRef } from '@wordpress/element';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -73,7 +73,7 @@ function UnforwardedExternalLink(
|
|
|
73
73
|
__( '(opens in a new tab)' )
|
|
74
74
|
}
|
|
75
75
|
>
|
|
76
|
-
|
|
76
|
+
{ isRTL() ? '\u2196' : '\u2197' }
|
|
77
77
|
</span>
|
|
78
78
|
</a>
|
|
79
79
|
/* eslint-enable react/jsx-no-target-blank */
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta, StoryFn } from '@storybook/react';
|
|
5
|
+
import { fn } from '@storybook/test';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* WordPress dependencies
|
|
@@ -19,8 +20,13 @@ const meta: Meta< typeof FocalPointPicker > = {
|
|
|
19
20
|
help: { control: 'text' },
|
|
20
21
|
label: { control: 'text' },
|
|
21
22
|
},
|
|
23
|
+
args: {
|
|
24
|
+
onChange: fn(),
|
|
25
|
+
onDrag: fn(),
|
|
26
|
+
onDragEnd: fn(),
|
|
27
|
+
onDragStart: fn(),
|
|
28
|
+
},
|
|
22
29
|
parameters: {
|
|
23
|
-
actions: { argTypesRegex: '^on.*' },
|
|
24
30
|
controls: { expanded: true },
|
|
25
31
|
docs: { canvas: { sourceState: 'shown' } },
|
|
26
32
|
},
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta, StoryFn } from '@storybook/react';
|
|
5
|
+
import { fn } from '@storybook/test';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* WordPress dependencies
|
|
@@ -23,8 +24,10 @@ const meta: Meta< typeof FontSizePicker > = {
|
|
|
23
24
|
options: [ 'px', 'em', 'rem', 'vw', 'vh' ],
|
|
24
25
|
},
|
|
25
26
|
},
|
|
27
|
+
args: {
|
|
28
|
+
onChange: fn(),
|
|
29
|
+
},
|
|
26
30
|
parameters: {
|
|
27
|
-
actions: { argTypesRegex: '^on.*' },
|
|
28
31
|
controls: { expanded: true },
|
|
29
32
|
docs: { canvas: { sourceState: 'shown' } },
|
|
30
33
|
},
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta, StoryFn } from '@storybook/react';
|
|
5
|
+
import { fn } from '@storybook/test';
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* WordPress dependencies
|
|
7
9
|
*/
|
|
@@ -19,7 +21,9 @@ const meta: Meta< typeof GradientPicker > = {
|
|
|
19
21
|
parameters: {
|
|
20
22
|
controls: { expanded: true },
|
|
21
23
|
docs: { canvas: { sourceState: 'shown' } },
|
|
22
|
-
|
|
24
|
+
},
|
|
25
|
+
args: {
|
|
26
|
+
onChange: fn(),
|
|
23
27
|
},
|
|
24
28
|
argTypes: {
|
|
25
29
|
value: { control: false },
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta, StoryFn } from '@storybook/react';
|
|
5
|
+
import { fn } from '@storybook/test';
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* WordPress dependencies
|
|
7
9
|
*/
|
|
@@ -31,8 +33,12 @@ const meta: Meta< typeof InputControl > = {
|
|
|
31
33
|
value: { control: { disable: true } },
|
|
32
34
|
},
|
|
33
35
|
tags: [ 'status-experimental' ],
|
|
36
|
+
args: {
|
|
37
|
+
onChange: fn(),
|
|
38
|
+
onValidate: fn(),
|
|
39
|
+
onKeyDown: fn(),
|
|
40
|
+
},
|
|
34
41
|
parameters: {
|
|
35
|
-
actions: { argTypesRegex: '^on.*' },
|
|
36
42
|
controls: { expanded: true },
|
|
37
43
|
docs: { canvas: { sourceState: 'shown' } },
|
|
38
44
|
},
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { StoryObj, Meta } from '@storybook/react';
|
|
5
5
|
import { css } from '@emotion/react';
|
|
6
|
+
import { fn } from '@storybook/test';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* WordPress dependencies
|
|
@@ -52,12 +53,14 @@ const meta: Meta< typeof Menu > = {
|
|
|
52
53
|
// @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
|
|
53
54
|
Popover: Menu.Popover,
|
|
54
55
|
},
|
|
56
|
+
args: {
|
|
57
|
+
onOpenChange: fn(),
|
|
58
|
+
},
|
|
55
59
|
argTypes: {
|
|
56
60
|
children: { control: false },
|
|
57
61
|
},
|
|
58
62
|
tags: [ 'status-private' ],
|
|
59
63
|
parameters: {
|
|
60
|
-
actions: { argTypesRegex: '^on.*' },
|
|
61
64
|
controls: { expanded: true },
|
|
62
65
|
docs: {
|
|
63
66
|
canvas: { sourceState: 'shown' },
|
package/src/modal/style.scss
CHANGED
|
@@ -106,6 +106,20 @@
|
|
|
106
106
|
@include break-large() {
|
|
107
107
|
max-height: 70%;
|
|
108
108
|
}
|
|
109
|
+
|
|
110
|
+
&.is-full-screen {
|
|
111
|
+
// When full screen, make sure the children container is full height.
|
|
112
|
+
.components-modal__content {
|
|
113
|
+
display: flex;
|
|
114
|
+
// If this container is scrollable, bottom padding won't apply so we use margin instead.
|
|
115
|
+
margin-bottom: $grid-unit-40;
|
|
116
|
+
padding-bottom: 0;
|
|
117
|
+
|
|
118
|
+
> :last-child {
|
|
119
|
+
flex: 1;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
109
123
|
}
|
|
110
124
|
|
|
111
125
|
@keyframes components-modal__appear-animation {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta, StoryFn } from '@storybook/react';
|
|
5
|
+
import { fn } from '@storybook/test';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Internal dependencies
|
|
@@ -15,8 +16,11 @@ const meta: Meta< typeof NavigableMenu > = {
|
|
|
15
16
|
argTypes: {
|
|
16
17
|
children: { control: false },
|
|
17
18
|
},
|
|
19
|
+
args: {
|
|
20
|
+
onKeyDown: fn(),
|
|
21
|
+
onNavigate: fn(),
|
|
22
|
+
},
|
|
18
23
|
parameters: {
|
|
19
|
-
actions: { argTypesRegex: '^on.*' },
|
|
20
24
|
controls: {
|
|
21
25
|
expanded: true,
|
|
22
26
|
},
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta, StoryFn } from '@storybook/react';
|
|
5
|
+
import { fn } from '@storybook/test';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Internal dependencies
|
|
@@ -15,8 +16,11 @@ const meta: Meta< typeof TabbableContainer > = {
|
|
|
15
16
|
argTypes: {
|
|
16
17
|
children: { control: false },
|
|
17
18
|
},
|
|
19
|
+
args: {
|
|
20
|
+
onKeyDown: fn(),
|
|
21
|
+
onNavigate: fn(),
|
|
22
|
+
},
|
|
18
23
|
parameters: {
|
|
19
|
-
actions: { argTypesRegex: '^on.*' },
|
|
20
24
|
controls: {
|
|
21
25
|
expanded: true,
|
|
22
26
|
},
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta } from '@storybook/react';
|
|
5
|
+
import { fn } from '@storybook/test';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Internal dependencies
|
|
@@ -44,8 +45,10 @@ const meta: Meta< typeof Navigation > = {
|
|
|
44
45
|
children: { control: false },
|
|
45
46
|
onActivateMenu: { control: false },
|
|
46
47
|
},
|
|
48
|
+
args: {
|
|
49
|
+
onActivateMenu: fn(),
|
|
50
|
+
},
|
|
47
51
|
parameters: {
|
|
48
|
-
actions: { argTypesRegex: '^on.*' },
|
|
49
52
|
controls: {
|
|
50
53
|
expanded: true,
|
|
51
54
|
},
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import type { Meta, StoryFn } from '@storybook/react';
|
|
5
|
+
import { fn } from '@storybook/test';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* WordPress dependencies
|
|
@@ -22,8 +23,11 @@ const meta: Meta< typeof Notice > = {
|
|
|
22
23
|
component: Notice,
|
|
23
24
|
// @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
|
|
24
25
|
subcomponents: { NoticeList },
|
|
26
|
+
args: {
|
|
27
|
+
onDismiss: fn(),
|
|
28
|
+
onRemove: fn(),
|
|
29
|
+
},
|
|
25
30
|
parameters: {
|
|
26
|
-
actions: { argTypesRegex: '^on.*' },
|
|
27
31
|
controls: { expanded: true },
|
|
28
32
|
docs: { canvas: { sourceState: 'shown' } },
|
|
29
33
|
},
|