uikit-react-public 0.44.0 → 0.44.3
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/dist/components/Calendar/Calendar.d.ts +1 -1
- package/dist/components/Calendar/Calendar.stories.d.ts +6 -1
- package/dist/components/Calendar/Calendar.types.d.ts +9 -0
- package/dist/components/Calendar/index.d.ts +1 -1
- package/dist/components/Calendar/subcomponents/Day.d.ts +4 -2
- package/dist/components/Calendar/subcomponents/Day.stories.d.ts +1 -1
- package/dist/components/Calendar/subcomponents/EventDot.d.ts +3 -1
- package/dist/components/Calendar/subcomponents/Grid.d.ts +3 -2
- package/dist/components/Calendar/subcomponents/__tests__/Day.test.d.ts +1 -0
- package/dist/components/Calendar/subcomponents/__tests__/EventDot.test.d.ts +1 -0
- package/dist/components/Datepicker/Datepicker.stories.d.ts +5 -0
- package/dist/components/Datepicker/Datepicker.types.d.ts +3 -1
- package/dist/components/Datepicker/subcomponents/CustomDatepicker.d.ts +4 -2
- package/dist/components/index.d.ts +1 -1
- package/dist/index.js +1805 -1751
- package/lib/components/Calendar/Calendar.stories.tsx +60 -12
- package/lib/components/Calendar/Calendar.tsx +27 -20
- package/lib/components/Calendar/Calendar.types.ts +17 -1
- package/lib/components/Calendar/__tests__/Calendar.test.tsx +76 -2
- package/lib/components/Calendar/__tests__/__snapshots__/Calendar.test.tsx.snap +462 -231
- package/lib/components/Calendar/index.ts +6 -1
- package/lib/components/Calendar/subcomponents/Day.tsx +44 -5
- package/lib/components/Calendar/subcomponents/EventDot.tsx +42 -6
- package/lib/components/Calendar/subcomponents/Grid.tsx +4 -1
- package/lib/components/Calendar/subcomponents/__tests__/Day.test.tsx +139 -0
- package/lib/components/Calendar/subcomponents/__tests__/EventDot.test.tsx +78 -0
- package/lib/components/Datepicker/Datepicker.stories.tsx +55 -24
- package/lib/components/Datepicker/Datepicker.types.ts +7 -1
- package/lib/components/Datepicker/__tests__/Datepicker.test.tsx +90 -0
- package/lib/components/Datepicker/subcomponents/CustomDatepicker.tsx +16 -1
- package/lib/components/index.ts +1 -1
- package/package.json +1 -1
|
@@ -107,6 +107,55 @@ describe('Datepicker', () => {
|
|
|
107
107
|
);
|
|
108
108
|
});
|
|
109
109
|
|
|
110
|
+
test('Does not submit an enclosing form on ENTER key press', async () => {
|
|
111
|
+
const onValueChange = vi.fn();
|
|
112
|
+
const onSubmit = vi.fn((event: React.FormEvent) => event.preventDefault());
|
|
113
|
+
const user = userEvent.setup();
|
|
114
|
+
customRender(
|
|
115
|
+
<form onSubmit={onSubmit}>
|
|
116
|
+
<Datepicker onValueChange={onValueChange} />
|
|
117
|
+
</form>
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// Internal <input> (the user types into)
|
|
121
|
+
const datepickerInput = screen.getByRole('textbox');
|
|
122
|
+
await user.type(datepickerInput, '10/03/2025');
|
|
123
|
+
expect(datepickerInput).toHaveValue('10/03/2025');
|
|
124
|
+
|
|
125
|
+
// Trigger user-entered date parsing
|
|
126
|
+
await user.keyboard('{Enter}');
|
|
127
|
+
|
|
128
|
+
// The date is still parsed as normal...
|
|
129
|
+
expect(onValueChange).toHaveBeenCalledWith(
|
|
130
|
+
new Date('2025-03-10'),
|
|
131
|
+
expect.anything() // 2nd parameter is the event object (which we're not testing here)
|
|
132
|
+
);
|
|
133
|
+
// ...but the enclosing form is not submitted
|
|
134
|
+
expect(onSubmit).not.toHaveBeenCalled();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test('Does not bubble {Enter} key press to a parent element', async () => {
|
|
138
|
+
const onValueChange = vi.fn();
|
|
139
|
+
const parentKeyDown = vi.fn();
|
|
140
|
+
const user = userEvent.setup();
|
|
141
|
+
customRender(
|
|
142
|
+
<div onKeyDown={parentKeyDown}>
|
|
143
|
+
<Datepicker onValueChange={onValueChange} />
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const datepickerInput = screen.getByRole('textbox');
|
|
148
|
+
await user.type(datepickerInput, '10/03/2025');
|
|
149
|
+
// Typing the digits/slashes above also fires keydown events that
|
|
150
|
+
// correctly bubble (only Enter is stopped, to prevent it submitting an
|
|
151
|
+
// enclosing form) - clear those out so only Enter is captured below.
|
|
152
|
+
parentKeyDown.mockClear();
|
|
153
|
+
|
|
154
|
+
await user.keyboard('{Enter}');
|
|
155
|
+
|
|
156
|
+
expect(parentKeyDown).not.toHaveBeenCalled();
|
|
157
|
+
});
|
|
158
|
+
|
|
110
159
|
test('Input value reflects the date', () => {
|
|
111
160
|
// 10th March 2025 (2 is March, because month is 0-indexed in Date constructor)
|
|
112
161
|
customRender(<Datepicker value={new Date(2025, 2, 10)} />);
|
|
@@ -153,6 +202,21 @@ describe('Datepicker', () => {
|
|
|
153
202
|
expect(panel.parentElement).toHaveClass('ucl-overlay');
|
|
154
203
|
});
|
|
155
204
|
|
|
205
|
+
test('Forwards pickedMonth to the Calendar panel without affecting the input value', () => {
|
|
206
|
+
customRender(<Datepicker pickedMonth={new Date('2026-07-01')} />);
|
|
207
|
+
|
|
208
|
+
const input = screen.getByTestId('ucl-uikit-datepicker__input');
|
|
209
|
+
fireEvent.focus(input);
|
|
210
|
+
|
|
211
|
+
expect(screen.getByRole('combobox', { name: 'Month' })).toHaveTextContent(
|
|
212
|
+
'July'
|
|
213
|
+
);
|
|
214
|
+
expect(screen.getByRole('combobox', { name: 'Year' })).toHaveTextContent(
|
|
215
|
+
'2026'
|
|
216
|
+
);
|
|
217
|
+
expect(input).toHaveValue('');
|
|
218
|
+
});
|
|
219
|
+
|
|
156
220
|
test('Panel escapes a containing dialog via fixed positioning', () => {
|
|
157
221
|
customRender(
|
|
158
222
|
<dialog open>
|
|
@@ -383,6 +447,32 @@ describe('Datepicker', () => {
|
|
|
383
447
|
expect(screen.getByRole('button', { name: 'After' })).toHaveFocus();
|
|
384
448
|
});
|
|
385
449
|
|
|
450
|
+
test('Forwards the statuses prop to the underlying Calendar', () => {
|
|
451
|
+
customRender(
|
|
452
|
+
<Datepicker
|
|
453
|
+
value={new Date(2026, 2, 10)} // 10th March 2026 (2 is March, 0-indexed)
|
|
454
|
+
events={[{ date: '2026-03-10', status: 'pending' }]}
|
|
455
|
+
statuses={{
|
|
456
|
+
pending: { variant: 'warning', ariaLabel: 'Pending' },
|
|
457
|
+
}}
|
|
458
|
+
/>
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
const openCalendarButton = screen.getByTestId(
|
|
462
|
+
'ucl-uikit-datepicker__visible-field-icon-button'
|
|
463
|
+
);
|
|
464
|
+
fireEvent.click(openCalendarButton);
|
|
465
|
+
|
|
466
|
+
const days = screen.getAllByTestId('ucl-uikit-calendar__day');
|
|
467
|
+
// Pick 10th March 2026: 6 days of previous month + 10 days of current month - 1 for 0-indexing
|
|
468
|
+
const dateArrayIndex = 6 + 10 - 1;
|
|
469
|
+
|
|
470
|
+
expect(days[dateArrayIndex]).toHaveAttribute(
|
|
471
|
+
'aria-label',
|
|
472
|
+
expect.stringContaining('Pending')
|
|
473
|
+
);
|
|
474
|
+
});
|
|
475
|
+
|
|
386
476
|
test('Disabled Datepicker icon control is not tabbable and cannot open', async () => {
|
|
387
477
|
const user = userEvent.setup();
|
|
388
478
|
|
|
@@ -7,7 +7,11 @@ import { parseInputValue } from '../utils';
|
|
|
7
7
|
import announce from '../../../utils/announce';
|
|
8
8
|
import { useTheme } from '../../../theme';
|
|
9
9
|
import type { DatepickerValue } from '../Datepicker.types';
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
CalendarEvent,
|
|
12
|
+
CalendarStatuses,
|
|
13
|
+
AcademicWeek,
|
|
14
|
+
} from '../../Calendar';
|
|
11
15
|
import type { InputProps } from './DatepickerInput';
|
|
12
16
|
|
|
13
17
|
interface CustomDatepickerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
@@ -20,9 +24,11 @@ interface CustomDatepickerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
20
24
|
maxDate?: string | null; // ISO date string: YYYY-MM-DD
|
|
21
25
|
minYear?: number;
|
|
22
26
|
maxYear?: number;
|
|
27
|
+
pickedMonth?: Date | null; // Pre-selects a month to display when no value is set
|
|
23
28
|
disabled?: boolean;
|
|
24
29
|
clearable?: boolean;
|
|
25
30
|
events?: CalendarEvent[];
|
|
31
|
+
statuses?: CalendarStatuses;
|
|
26
32
|
showAcademicWeeks?: boolean;
|
|
27
33
|
academicWeeks?: AcademicWeek[];
|
|
28
34
|
testId?: string;
|
|
@@ -40,9 +46,11 @@ const CustomDatepicker = ({
|
|
|
40
46
|
maxDate,
|
|
41
47
|
minYear,
|
|
42
48
|
maxYear,
|
|
49
|
+
pickedMonth = null,
|
|
43
50
|
disabled = false,
|
|
44
51
|
clearable = false,
|
|
45
52
|
events,
|
|
53
|
+
statuses,
|
|
46
54
|
showAcademicWeeks,
|
|
47
55
|
academicWeeks = [],
|
|
48
56
|
testId = NAME,
|
|
@@ -116,6 +124,11 @@ const CustomDatepicker = ({
|
|
|
116
124
|
|
|
117
125
|
const handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
118
126
|
if (event.key === 'Enter') {
|
|
127
|
+
// Stop the native "Enter submits the enclosing form" behaviour.
|
|
128
|
+
event.preventDefault();
|
|
129
|
+
// Key events must not bubble out of the datepicker (e.g. so a parent
|
|
130
|
+
// form's own key handlers don't also see this Enter).
|
|
131
|
+
event.stopPropagation();
|
|
119
132
|
handleParseInput(event);
|
|
120
133
|
} else if (event.key === 'Escape') {
|
|
121
134
|
resetField();
|
|
@@ -260,12 +273,14 @@ const CustomDatepicker = ({
|
|
|
260
273
|
<Panel>
|
|
261
274
|
<Calendar
|
|
262
275
|
pickedDate={value}
|
|
276
|
+
pickedMonth={pickedMonth}
|
|
263
277
|
onDatePick={handlePickCalendarDate}
|
|
264
278
|
minDate={minDate}
|
|
265
279
|
maxDate={maxDate}
|
|
266
280
|
minYear={minYear}
|
|
267
281
|
maxYear={maxYear}
|
|
268
282
|
events={events}
|
|
283
|
+
statuses={statuses}
|
|
269
284
|
showAcademicWeeks={showAcademicWeeks}
|
|
270
285
|
academicWeeks={academicWeeks}
|
|
271
286
|
/>
|
package/lib/components/index.ts
CHANGED
|
@@ -211,7 +211,7 @@ export { default as NativeDatepicker } from './NativeDatepicker';
|
|
|
211
211
|
export type { NativeDatepickerProps } from './NativeDatepicker';
|
|
212
212
|
|
|
213
213
|
export { default as Calendar } from './Calendar';
|
|
214
|
-
export type { CalendarProps } from './Calendar';
|
|
214
|
+
export type { CalendarProps, CalendarStatuses } from './Calendar';
|
|
215
215
|
|
|
216
216
|
export { default as WeekPicker } from './WeekPicker';
|
|
217
217
|
|