uikit-react-public 0.11.16 → 0.11.24

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.
Files changed (142) hide show
  1. package/dist/components/Calendar/Calendar.d.ts +3 -0
  2. package/dist/components/Calendar/Calendar.stories.d.ts +42 -0
  3. package/dist/components/Calendar/Calendar.types.d.ts +18 -0
  4. package/dist/components/Calendar/index.d.ts +2 -0
  5. package/dist/components/Calendar/subcomponents/AcademicWeek.d.ts +5 -0
  6. package/dist/components/Calendar/subcomponents/AcademicWeeks.d.ts +7 -0
  7. package/dist/components/Calendar/subcomponents/ColumnHeading.d.ts +7 -0
  8. package/dist/components/Calendar/subcomponents/Controls.d.ts +6 -0
  9. package/dist/components/Calendar/subcomponents/Day.d.ts +12 -0
  10. package/dist/components/{Datepicker/subcomponents/Day → Calendar/subcomponents}/Day.stories.d.ts +9 -1
  11. package/dist/components/Calendar/subcomponents/EventDot.d.ts +6 -0
  12. package/dist/components/Calendar/subcomponents/Grid.d.ts +11 -0
  13. package/dist/components/Calendar/subcomponents/index.d.ts +7 -0
  14. package/dist/components/Calendar/utils/getAcademicWeekNumbers/getAcademicWeekNumbers.d.ts +24 -0
  15. package/dist/components/Calendar/utils/index.d.ts +4 -0
  16. package/dist/components/Calendar/utils/normaliseMonth/normaliseMonth.d.ts +9 -0
  17. package/dist/components/Calendar/utils/normaliseMonth/normaliseMonth.test.d.ts +1 -0
  18. package/dist/components/Calendar/utils/parseDateFromString/parseDateFromString.d.ts +9 -0
  19. package/dist/components/Calendar/utils/parseDateFromString/parseDateFromString.test.d.ts +1 -0
  20. package/dist/components/Datepicker/Datepicker.d.ts +3 -12
  21. package/dist/components/Datepicker/Datepicker.stories.d.ts +16 -3
  22. package/dist/components/Datepicker/Datepicker.types.d.ts +23 -0
  23. package/dist/components/Datepicker/index.d.ts +1 -1
  24. package/dist/components/Datepicker/subcomponents/CustomDatepicker.d.ts +17 -0
  25. package/dist/components/Datepicker/subcomponents/DatepickerInput.d.ts +10 -0
  26. package/dist/components/Datepicker/subcomponents/NativeDatepicker.d.ts +6 -0
  27. package/dist/components/Datepicker/subcomponents/Panel.d.ts +6 -0
  28. package/dist/components/Datepicker/subcomponents/VisibleField.d.ts +12 -0
  29. package/dist/components/Datepicker/subcomponents/index.d.ts +5 -7
  30. package/dist/components/Datepicker/utils/dateToLocaleISOString/dateToLocaleISOString.d.ts +17 -0
  31. package/dist/components/Datepicker/utils/dateToLocaleISOString/dateToLocaleISOString.test.d.ts +1 -0
  32. package/dist/components/Datepicker/utils/index.d.ts +2 -2
  33. package/dist/components/Datepicker/utils/parseInputValue/parseInputValue.d.ts +11 -0
  34. package/dist/components/Datepicker/utils/parseInputValue/parseInputValue.test.d.ts +1 -0
  35. package/dist/components/Footer/Footer.d.ts +1 -1
  36. package/dist/components/Header/Header.d.ts +5 -4
  37. package/dist/components/Header/index.d.ts +1 -1
  38. package/dist/components/Menu/Menu.d.ts +2 -1
  39. package/dist/components/Menu/MenuContent.d.ts +1 -0
  40. package/dist/components/Select/Select.stories.d.ts +1 -1
  41. package/dist/components/Select/Select.types.d.ts +10 -50
  42. package/dist/components/Select/index.d.ts +1 -1
  43. package/dist/components/Select/subcomponents/CustomSelect.d.ts +2 -1
  44. package/dist/components/index.d.ts +2 -0
  45. package/dist/index.js +3332 -3063
  46. package/lib/components/Calendar/Calendar.stories.tsx +209 -0
  47. package/lib/components/Calendar/Calendar.tsx +121 -0
  48. package/lib/components/Calendar/Calendar.types.ts +21 -0
  49. package/lib/components/Calendar/__tests__/Calendar.test.tsx +71 -0
  50. package/lib/components/Calendar/__tests__/__snapshots__/Calendar.test.tsx.snap +1218 -0
  51. package/lib/components/Calendar/index.ts +6 -0
  52. package/lib/components/Calendar/subcomponents/AcademicWeek.tsx +36 -0
  53. package/lib/components/Calendar/subcomponents/AcademicWeeks.tsx +46 -0
  54. package/lib/components/Calendar/subcomponents/ColumnHeading.tsx +40 -0
  55. package/lib/components/{Datepicker/subcomponents/MonthSelector/MonthSelector.tsx → Calendar/subcomponents/Controls.tsx} +17 -17
  56. package/lib/components/{Datepicker/subcomponents/Day → Calendar/subcomponents}/Day.stories.tsx +30 -7
  57. package/lib/components/Calendar/subcomponents/Day.tsx +130 -0
  58. package/lib/components/Calendar/subcomponents/EventDot.tsx +40 -0
  59. package/lib/components/Calendar/subcomponents/Grid.tsx +117 -0
  60. package/lib/components/Calendar/subcomponents/index.ts +7 -0
  61. package/lib/components/Calendar/utils/getAcademicWeekNumbers/getAcademicWeekNumbers.test.ts +104 -0
  62. package/lib/components/Calendar/utils/getAcademicWeekNumbers/getAcademicWeekNumbers.ts +85 -0
  63. package/lib/components/{Datepicker → Calendar}/utils/getDatesForCalendarGrid/getDatesForCalendarGrid.test.ts +29 -65
  64. package/lib/components/{Datepicker → Calendar}/utils/getDatesForCalendarGrid/getDatesForCalendarGrid.ts +11 -43
  65. package/lib/components/Calendar/utils/index.ts +4 -0
  66. package/lib/components/Calendar/utils/normaliseMonth/normaliseMonth.test.ts +40 -0
  67. package/lib/components/Calendar/utils/normaliseMonth/normaliseMonth.ts +16 -0
  68. package/lib/components/Calendar/utils/parseDateFromString/parseDateFromString.test.ts +15 -0
  69. package/lib/components/Calendar/utils/parseDateFromString/parseDateFromString.ts +19 -0
  70. package/lib/components/Datepicker/Datepicker.stories.tsx +220 -23
  71. package/lib/components/Datepicker/Datepicker.tsx +34 -137
  72. package/lib/components/Datepicker/Datepicker.types.ts +38 -0
  73. package/lib/components/Datepicker/__tests__/Datepicker.test.tsx +53 -112
  74. package/lib/components/Datepicker/__tests__/__snapshots__/Datepicker.test.tsx.snap +92 -638
  75. package/lib/components/Datepicker/index.ts +1 -1
  76. package/lib/components/Datepicker/subcomponents/CustomDatepicker.tsx +209 -0
  77. package/lib/components/Datepicker/subcomponents/DatepickerInput.tsx +74 -0
  78. package/lib/components/Datepicker/subcomponents/NativeDatepicker.tsx +70 -0
  79. package/lib/components/Datepicker/subcomponents/Panel.tsx +32 -0
  80. package/lib/components/Datepicker/subcomponents/VisibleField.tsx +104 -0
  81. package/lib/components/Datepicker/subcomponents/index.ts +5 -7
  82. package/lib/components/Datepicker/utils/dateToLocaleISOString/dateToLocaleISOString.test.ts +32 -0
  83. package/lib/components/Datepicker/utils/dateToLocaleISOString/dateToLocaleISOString.ts +23 -0
  84. package/lib/components/Datepicker/utils/index.ts +2 -2
  85. package/lib/components/Datepicker/utils/parseInputValue/parseInputValue.test.ts +110 -0
  86. package/lib/components/Datepicker/utils/parseInputValue/parseInputValue.ts +57 -0
  87. package/lib/components/Footer/Footer.tsx +3 -3
  88. package/lib/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +6 -6
  89. package/lib/components/Header/Header.tsx +32 -33
  90. package/lib/components/Header/HeaderMenu.tsx +9 -2
  91. package/lib/components/Header/__tests__/__snapshots__/Header.test.tsx.snap +40 -48
  92. package/lib/components/Header/index.ts +5 -1
  93. package/lib/components/Menu/Menu.tsx +3 -0
  94. package/lib/components/Menu/MenuContent.tsx +4 -1
  95. package/lib/components/Select/Select.stories.tsx +38 -39
  96. package/lib/components/Select/Select.tsx +4 -18
  97. package/lib/components/Select/Select.types.ts +30 -69
  98. package/lib/components/Select/__tests__/Select.test.tsx +6 -6
  99. package/lib/components/Select/__tests__/__snapshots__/Select.test.tsx.snap +1 -1
  100. package/lib/components/Select/index.ts +1 -1
  101. package/lib/components/Select/subcomponents/CustomSelect.tsx +22 -12
  102. package/lib/components/Select/subcomponents/NativeSelect.tsx +7 -3
  103. package/lib/components/Select/subcomponents/Panel.tsx +4 -4
  104. package/lib/components/Select/subcomponents/VisibleField.tsx +1 -1
  105. package/lib/components/index.ts +3 -0
  106. package/package.json +4 -4
  107. package/LICENSE +0 -9
  108. package/dist/components/Datepicker/subcomponents/CalendarGrid/CalendarGrid.d.ts +0 -6
  109. package/dist/components/Datepicker/subcomponents/CalendarGrid/index.d.ts +0 -1
  110. package/dist/components/Datepicker/subcomponents/CalendarMenu/CalendarMenu.d.ts +0 -8
  111. package/dist/components/Datepicker/subcomponents/CalendarMenu/index.d.ts +0 -1
  112. package/dist/components/Datepicker/subcomponents/ColumnHeadings/ColumnHeadings.d.ts +0 -2
  113. package/dist/components/Datepicker/subcomponents/ColumnHeadings/index.d.ts +0 -1
  114. package/dist/components/Datepicker/subcomponents/DateField/DateField.d.ts +0 -7
  115. package/dist/components/Datepicker/subcomponents/DateField/index.d.ts +0 -1
  116. package/dist/components/Datepicker/subcomponents/Day/Day.d.ts +0 -10
  117. package/dist/components/Datepicker/subcomponents/Day/index.d.ts +0 -1
  118. package/dist/components/Datepicker/subcomponents/MonthSelector/MonthSelector.d.ts +0 -6
  119. package/dist/components/Datepicker/subcomponents/MonthSelector/index.d.ts +0 -1
  120. package/dist/components/Datepicker/subcomponents/Native/Native.d.ts +0 -9
  121. package/dist/components/Datepicker/subcomponents/Native/index.d.ts +0 -1
  122. package/dist/components/Datepicker/utils/parseDateForDateField/parseDateForDateField.d.ts +0 -20
  123. package/lib/components/Datepicker/subcomponents/CalendarGrid/CalendarGrid.tsx +0 -59
  124. package/lib/components/Datepicker/subcomponents/CalendarGrid/index.ts +0 -1
  125. package/lib/components/Datepicker/subcomponents/CalendarMenu/CalendarMenu.tsx +0 -64
  126. package/lib/components/Datepicker/subcomponents/CalendarMenu/index.ts +0 -1
  127. package/lib/components/Datepicker/subcomponents/ColumnHeadings/ColumnHeadings.tsx +0 -35
  128. package/lib/components/Datepicker/subcomponents/ColumnHeadings/index.ts +0 -1
  129. package/lib/components/Datepicker/subcomponents/DateField/DateField.tsx +0 -155
  130. package/lib/components/Datepicker/subcomponents/DateField/__tests__/DateField.test.tsx +0 -191
  131. package/lib/components/Datepicker/subcomponents/DateField/index.ts +0 -1
  132. package/lib/components/Datepicker/subcomponents/Day/Day.tsx +0 -94
  133. package/lib/components/Datepicker/subcomponents/Day/index.ts +0 -1
  134. package/lib/components/Datepicker/subcomponents/MonthSelector/index.ts +0 -1
  135. package/lib/components/Datepicker/subcomponents/Native/Native.tsx +0 -59
  136. package/lib/components/Datepicker/subcomponents/Native/index.ts +0 -1
  137. package/lib/components/Datepicker/utils/parseDateForDateField/parseDateForDateField.test.ts +0 -41
  138. package/lib/components/Datepicker/utils/parseDateForDateField/parseDateForDateField.ts +0 -48
  139. /package/dist/components/{Datepicker/subcomponents/DateField/__tests__/DateField.test.d.ts → Calendar/__tests__/Calendar.test.d.ts} +0 -0
  140. /package/dist/components/{Datepicker/utils/getDatesForCalendarGrid/getDatesForCalendarGrid.test.d.ts → Calendar/utils/getAcademicWeekNumbers/getAcademicWeekNumbers.test.d.ts} +0 -0
  141. /package/dist/components/{Datepicker → Calendar}/utils/getDatesForCalendarGrid/getDatesForCalendarGrid.d.ts +0 -0
  142. /package/dist/components/{Datepicker/utils/parseDateForDateField/parseDateForDateField.test.d.ts → Calendar/utils/getDatesForCalendarGrid/getDatesForCalendarGrid.test.d.ts} +0 -0
@@ -1 +0,0 @@
1
- export { default } from './CalendarMenu';
@@ -1,2 +0,0 @@
1
- declare const ColumnHeadings: () => import("react/jsx-runtime").JSX.Element;
2
- export default ColumnHeadings;
@@ -1 +0,0 @@
1
- export { default } from './ColumnHeadings';
@@ -1,7 +0,0 @@
1
- interface DateFieldProps {
2
- date: Date | null | undefined;
3
- onChange: (date: Date | null | undefined) => void;
4
- testId?: string;
5
- }
6
- declare const DateField: ({ date, onChange, testId, }: DateFieldProps) => import("react/jsx-runtime").JSX.Element;
7
- export default DateField;
@@ -1 +0,0 @@
1
- export { default } from './DateField';
@@ -1,10 +0,0 @@
1
- export interface DayProps {
2
- date: Date | null | undefined;
3
- isSelected?: boolean;
4
- isToday?: boolean;
5
- isInCurrentMonth?: boolean;
6
- isDisabled?: boolean;
7
- onPick?: (date: Date) => void;
8
- }
9
- declare const Day: ({ date, isSelected, isToday, isInCurrentMonth, isDisabled, onPick, }: DayProps) => import("react/jsx-runtime").JSX.Element;
10
- export default Day;
@@ -1 +0,0 @@
1
- export { default } from './Day';
@@ -1,6 +0,0 @@
1
- interface MonthSelectorProps {
2
- date: Date | null | undefined;
3
- changeMonth: (change: number) => void;
4
- }
5
- declare const MonthSelector: ({ date, changeMonth, }: MonthSelectorProps) => import("react/jsx-runtime").JSX.Element;
6
- export default MonthSelector;
@@ -1 +0,0 @@
1
- export { default } from './MonthSelector';
@@ -1,9 +0,0 @@
1
- interface NativeProps {
2
- date?: Date | null | undefined;
3
- minDate?: Date | null | undefined;
4
- maxDate?: Date | null | undefined;
5
- onDateChange?: (date: Date | null | undefined) => void;
6
- testId?: string;
7
- }
8
- declare const Native: ({ date, minDate, maxDate, onDateChange, testId, ...props }: NativeProps) => import("react/jsx-runtime").JSX.Element;
9
- export default Native;
@@ -1 +0,0 @@
1
- export { default } from './Native';
@@ -1,20 +0,0 @@
1
- /**
2
- * Parses a date string and returns a `Date` object.
3
- *
4
- * Can handle date strings entered by the user as "day/month/year", "day month year", or "day-month-year".
5
- * If the date is not in the expected format or contains invalid numbers, it returns `null`.
6
- *
7
- * Used solely by `<DateField>` component.
8
- *
9
- * - A one-digit or two-digit year is assumed to be in the 21st century (e.g., '21' becomes '2021').
10
- *
11
- * @param {string} dateString - The date string to be parsed.
12
- *
13
- * @future Any additional validation logic for dates entered by the user should be added here.
14
- * For example, supporting formats like "day / month / year" (separated with a space and a slash)
15
- * or "daymonthyear" (without spaces or separators).
16
- *
17
- * @returns {void}
18
- */
19
- declare const parseDate: (dateString: string) => Date | null;
20
- export default parseDate;
@@ -1,59 +0,0 @@
1
- import { css } from '@emotion/css';
2
- import { ColumnHeadings, Day } from '../';
3
- import useTheme from '../../../../theme/useTheme';
4
- import { getDatesForCalendarGrid } from '../../utils';
5
-
6
- interface CalendarGridProps {
7
- date: Date | null | undefined;
8
- onDatePick: (date: Date) => void;
9
- }
10
-
11
- const CalendarGrid = ({
12
- date,
13
- onDatePick,
14
- }: CalendarGridProps) => {
15
- const [theme] = useTheme();
16
-
17
- const dates = date
18
- ? getDatesForCalendarGrid(date)
19
- : getDatesForCalendarGrid(new Date());
20
-
21
- const gridStyle = css`
22
- display: grid;
23
- grid-template-columns: repeat(7, 1fr);
24
- gap: 0;
25
- text-align: center;
26
- font-family: ${theme.font.family.primary};
27
- font-weight: 400;
28
- user-select: none;
29
- `;
30
-
31
- return (
32
- <div className={gridStyle}>
33
- <ColumnHeadings />
34
- {dates.map((mappedDate) => (
35
- <Day
36
- key={mappedDate.toISOString()}
37
- date={mappedDate}
38
- isSelected={
39
- date?.toDateString() ===
40
- mappedDate.toDateString()
41
- }
42
- isToday={
43
- mappedDate.toDateString() ===
44
- new Date().toDateString()
45
- }
46
- isInCurrentMonth={
47
- date
48
- ? mappedDate.getMonth() === date?.getMonth()
49
- : mappedDate.getMonth() ===
50
- new Date().getMonth()
51
- }
52
- onPick={onDatePick}
53
- />
54
- ))}
55
- </div>
56
- );
57
- };
58
-
59
- export default CalendarGrid;
@@ -1 +0,0 @@
1
- export { default } from './CalendarGrid';
@@ -1,64 +0,0 @@
1
- import { css } from '@emotion/css';
2
- import MonthSelector from '../MonthSelector';
3
- import CalendarGrid from '../CalendarGrid';
4
- import useTheme from '../../../../theme/useTheme';
5
-
6
- interface CalendarMenuProps {
7
- date: Date | null | undefined;
8
- setDate: (date: Date) => void;
9
- onDatePick: () => void;
10
- testId?: string;
11
- }
12
-
13
- const CalendarMenu = ({
14
- date,
15
- setDate,
16
- onDatePick,
17
- testId = 'ucl',
18
- }: CalendarMenuProps) => {
19
- const [theme] = useTheme();
20
-
21
- const onMonthChange = (change: number) => {
22
- const newDate = date ? new Date(date) : new Date();
23
- newDate.setMonth(newDate.getMonth() + change);
24
- setDate(newDate);
25
- };
26
-
27
- const style = css`
28
- display: flex;
29
- flex-direction: column;
30
- align-items: center;
31
- gap: 16px;
32
- width: 280px;
33
- height: 320px;
34
- z-index: 10;
35
- position: absolute;
36
- top: 60px;
37
- border: 1px solid ${theme.color.neutral.grey20};
38
- padding: 16px;
39
- background-color: ${theme.color.neutral.white};
40
- `;
41
-
42
- const handlePick = (pickedDate: Date) => {
43
- setDate(pickedDate);
44
- onDatePick();
45
- };
46
-
47
- return (
48
- <div
49
- className={style}
50
- data-testid={testId + '-calendar-menu'}
51
- >
52
- <MonthSelector
53
- date={date}
54
- changeMonth={onMonthChange}
55
- />
56
- <CalendarGrid
57
- date={date}
58
- onDatePick={handlePick}
59
- />
60
- </div>
61
- );
62
- };
63
-
64
- export default CalendarMenu;
@@ -1 +0,0 @@
1
- export { default } from './CalendarMenu';
@@ -1,35 +0,0 @@
1
- import { css } from '@emotion/css';
2
- import { useTheme } from '../../../../theme';
3
-
4
- const ColumnHeadings = () => {
5
- const [theme] = useTheme();
6
-
7
- const days = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
8
-
9
- const headingStyle = (isWeekend: boolean) => css`
10
- display: flex;
11
- align-items: center;
12
- justify-content: center;
13
- width: 40px;
14
- height: 32px;
15
- color: ${isWeekend
16
- ? theme.color.system.orange100
17
- : theme.color.neutral.grey60};
18
- font-weight: 700;
19
- `;
20
-
21
- return (
22
- <>
23
- {days.map((day, index) => (
24
- <div
25
- key={index}
26
- className={headingStyle(index >= 5)}
27
- >
28
- {day}
29
- </div>
30
- ))}
31
- </>
32
- );
33
- };
34
-
35
- export default ColumnHeadings;
@@ -1 +0,0 @@
1
- export { default } from './ColumnHeadings';
@@ -1,155 +0,0 @@
1
- import { css } from '@emotion/css';
2
- import { Icon } from '../../..';
3
- import { useTheme } from '../../../../theme';
4
- import { useState, useRef, useEffect } from 'react';
5
- import { parseDate } from '../../utils';
6
-
7
- interface DateFieldProps {
8
- date: Date | null | undefined;
9
- onChange: (date: Date | null | undefined) => void;
10
- testId?: string;
11
- }
12
-
13
- const DateField = ({
14
- date,
15
- onChange,
16
- testId,
17
- }: DateFieldProps) => {
18
- const [theme] = useTheme();
19
-
20
- // Derived props (tidier than using `date?.getDate()`, etc, everywhere.)
21
- const day =
22
- date?.getDate().toString().padStart(2, '0') ?? '';
23
- const month = date
24
- ? (date.getMonth() + 1).toString().padStart(2, '0')
25
- : '';
26
- const year = date?.getFullYear().toString() ?? '';
27
-
28
- const [displayDate, setDisplayDate] = useState('');
29
- const inputRef = useRef<HTMLInputElement>(null);
30
-
31
- useEffect(() => {
32
- // Format: DD/MM/YYYY
33
- setDisplayDate(date ? `${day}/${month}/${year}` : '');
34
- }, [date, day, month, year]);
35
-
36
- /**
37
- * Handles the change event for the date input field.
38
- *
39
- * This function ensures that only valid characters for a date are accepted
40
- * in the input field. The accepted characters include digits (0-9), slashes (/),
41
- * spaces, and hyphens (-). If the input contains any other characters, the function
42
- * will not update the display date.
43
- *
44
- * @param event - The change event triggered by the input field.
45
- */
46
- const handleInputChange = (
47
- event: React.ChangeEvent<HTMLInputElement>
48
- ) => {
49
- // Accepted characters: 0-9, /, space, hyphen
50
- const regex = new RegExp('^[0123456789\\/ \\-]*$');
51
- if (!regex.test(event.target.value)) return;
52
-
53
- setDisplayDate(event.target.value);
54
- };
55
-
56
- const resetDate = () => {
57
- setDisplayDate(date ? `${day}/${month}/${year}` : '');
58
- };
59
-
60
- const handleParseDate = () => {
61
- const parsedDate = parseDate(displayDate);
62
- if (parsedDate) onChange(parsedDate);
63
- else resetDate();
64
- };
65
-
66
- const handleInputKeyDown = (
67
- event: React.KeyboardEvent<HTMLDivElement>
68
- ) => {
69
- if (event.key === 'Enter') handleParseDate();
70
- else if (event.key === 'Escape') resetDate();
71
- };
72
-
73
- const handleKeyDownEventPropagation = (
74
- event: React.KeyboardEvent<HTMLDivElement>
75
- ) => {
76
- // Prevent event bubbling any further, so arrow keys presses don't affect `<CalendarGrid>`
77
- event.stopPropagation();
78
- };
79
-
80
- const containerStyle = css`
81
- display: flex;
82
- align-items: center;
83
- justify-content: space-between;
84
- width: 200px;
85
- height: 48px;
86
- padding: 0 16px;
87
- border: 1px solid ${theme.color.neutral.grey60};
88
- color: ${theme.color.neutral.black};
89
- background-color: ${theme.color.neutral.white};
90
- cursor: pointer;
91
-
92
- &:focus-visible {
93
- outline: none;
94
- box-shadow: ${theme.boxShadow.focus};
95
- }
96
- `;
97
-
98
- const inputStyle = css`
99
- width: 150px;
100
- font-family: ${theme.font.family.primary};
101
- font-size: 16px;
102
- text-align: left;
103
- border: none;
104
- padding: 6px;
105
- letter-spacing: 1px;
106
- color: ${theme.color.text.primary};
107
- caret-color: ${theme.color.text.primary};
108
-
109
- &::placeholder {
110
- color: ${theme.color.neutral.grey40};
111
- }
112
-
113
- &::selection {
114
- background-color: ${theme.color.neutral.grey60};
115
- color: ${theme.color.neutral.white};
116
- }
117
-
118
- &:focus {
119
- outline: none;
120
- background-color: ${theme.color.interaction.blue10};
121
- }
122
- `;
123
-
124
- return (
125
- <div
126
- className={containerStyle}
127
- role='group'
128
- aria-label='Date input'
129
- onBlur={handleParseDate}
130
- onClick={() => inputRef.current?.focus()}
131
- data-testid={testId + '-date-field'}
132
- >
133
- <div onKeyDown={handleKeyDownEventPropagation}>
134
- <input
135
- className={inputStyle}
136
- value={displayDate}
137
- placeholder='DD/MM/YYYY'
138
- onChange={handleInputChange}
139
- onKeyDown={handleInputKeyDown}
140
- type='text'
141
- inputMode='numeric'
142
- ref={inputRef}
143
- aria-label='Date'
144
- data-testid={testId + '-input'}
145
- />
146
- </div>
147
- <Icon.Calendar
148
- onClick={handleParseDate}
149
- data-testid={testId + '-calendar-icon'}
150
- />
151
- </div>
152
- );
153
- };
154
-
155
- export default DateField;
@@ -1,191 +0,0 @@
1
- import {
2
- describe,
3
- test,
4
- expect,
5
- vi,
6
- afterEach,
7
- } from 'vitest';
8
- import {
9
- render,
10
- screen,
11
- fireEvent,
12
- cleanup,
13
- } from '@testing-library/react';
14
- import { ThemeContextProvider } from '../../../../../theme';
15
- import DateField from '../DateField';
16
-
17
- const customRender = (ui: React.ReactElement) => {
18
- return render(ui, {
19
- wrapper: ({ children }) => (
20
- <ThemeContextProvider>
21
- {children}
22
- </ThemeContextProvider>
23
- ),
24
- });
25
- };
26
-
27
- describe('DateField', () => {
28
- // Run cleanup after each test
29
- afterEach(() => {
30
- cleanup();
31
- vi.resetAllMocks();
32
- });
33
-
34
- test('Renders without crashing', () => {
35
- const testId = 'abc';
36
- customRender(
37
- <DateField
38
- date={null}
39
- onChange={vi.fn()}
40
- testId={testId}
41
- />
42
- );
43
- const dateField = screen.getByTestId(
44
- testId + '-date-field'
45
- );
46
- expect(dateField).toBeInTheDocument();
47
- });
48
-
49
- test('Displays placeholder text when `date` prop is null', () => {
50
- const testId = 'abc';
51
- customRender(
52
- <DateField
53
- date={null}
54
- onChange={vi.fn()}
55
- testId={testId}
56
- />
57
- );
58
- const inputField = screen.getByTestId(
59
- testId + '-input'
60
- ) as HTMLInputElement;
61
- expect(inputField.placeholder).toBe('DD/MM/YYYY');
62
- });
63
-
64
- test('Displays the correct date values when a date is present', () => {
65
- const testId = 'abc';
66
- const date = new Date('2025-02-01');
67
- customRender(
68
- <DateField
69
- date={date}
70
- onChange={vi.fn()}
71
- testId={testId}
72
- />
73
- );
74
- const inputField = screen.getByTestId(
75
- testId + '-input'
76
- ) as HTMLInputElement;
77
- expect(inputField.value).toBe('01/02/2025');
78
- });
79
-
80
- test('Updates date value (from null)', () => {
81
- const testId = 'abc';
82
- const date = new Date('2025-02-01');
83
- const onChange = vi.fn();
84
- customRender(
85
- <DateField
86
- date={null}
87
- onChange={onChange}
88
- testId={testId}
89
- />
90
- );
91
- const inputField = screen.getByTestId(
92
- testId + '-input'
93
- ) as HTMLInputElement;
94
-
95
- fireEvent.change(inputField, {
96
- target: { value: '01/02/2025' },
97
- });
98
- fireEvent.keyDown(inputField, { key: 'Enter' });
99
- expect(onChange).toHaveBeenCalledWith(date);
100
- });
101
-
102
- test('Updates date value (from existing date)', () => {
103
- const testId = 'abc';
104
- const date = new Date('2025-01-01');
105
- const onChange = vi.fn();
106
- customRender(
107
- <DateField
108
- date={date}
109
- onChange={onChange}
110
- testId={testId}
111
- />
112
- );
113
- const inputField = screen.getByTestId(
114
- testId + '-input'
115
- ) as HTMLInputElement;
116
-
117
- fireEvent.change(inputField, {
118
- target: { value: '01/02/2025' },
119
- });
120
- fireEvent.keyDown(inputField, { key: 'Enter' });
121
- expect(onChange).toHaveBeenCalledWith(
122
- new Date('2025-02-01')
123
- );
124
- });
125
-
126
- test('Handles alternative date formats', () => {
127
- const testId = 'abc';
128
- const onChange = vi.fn();
129
- customRender(
130
- <DateField
131
- date={null}
132
- onChange={onChange}
133
- testId={testId}
134
- />
135
- );
136
- const inputField = screen.getByTestId(
137
- testId + '-input'
138
- ) as HTMLInputElement;
139
-
140
- // With 1 digit for day and month, and 2 digits for year
141
- fireEvent.change(inputField, {
142
- target: { value: '3/2/25' },
143
- });
144
- fireEvent.keyDown(inputField, { key: 'Enter' });
145
- expect(onChange).toHaveBeenCalledWith(
146
- new Date('2025-02-03')
147
- );
148
-
149
- // With hyphens
150
- fireEvent.change(inputField, {
151
- target: { value: '20-03-2026' },
152
- });
153
- fireEvent.keyDown(inputField, { key: 'Enter' });
154
- expect(onChange).toHaveBeenCalledWith(
155
- new Date('2026-03-20')
156
- );
157
-
158
- // With spaces
159
- fireEvent.change(inputField, {
160
- target: { value: '10 11 27' },
161
- });
162
- fireEvent.keyDown(inputField, { key: 'Enter' });
163
- expect(onChange).toHaveBeenCalledWith(
164
- new Date('2027-11-10')
165
- );
166
- });
167
-
168
- test('Resets date value on ESCAPE key press', () => {
169
- const testId = 'abc';
170
- const date = new Date('2025-01-01');
171
- const onChange = vi.fn();
172
- customRender(
173
- <DateField
174
- date={date}
175
- onChange={onChange}
176
- testId={testId}
177
- />
178
- );
179
- const inputField = screen.getByTestId(
180
- testId + '-input'
181
- ) as HTMLInputElement;
182
-
183
- fireEvent.change(inputField, {
184
- target: { value: '10/10/2026' },
185
- });
186
- fireEvent.keyDown(inputField, { key: 'Escape' });
187
- expect(inputField.value).toBe('01/01/2025');
188
- });
189
-
190
- // Any further tests can be added here
191
- });
@@ -1 +0,0 @@
1
- export { default } from './DateField';
@@ -1,94 +0,0 @@
1
- import { css } from '@emotion/css';
2
- import { useTheme } from '../../../../theme/';
3
-
4
- export interface DayProps {
5
- date: Date | null | undefined;
6
- isSelected?: boolean;
7
- isToday?: boolean;
8
- isInCurrentMonth?: boolean;
9
- isDisabled?: boolean;
10
- onPick?: (date: Date) => void;
11
- }
12
-
13
- const Day = ({
14
- date,
15
- isSelected,
16
- isToday = false,
17
- isInCurrentMonth = true,
18
- isDisabled = false,
19
- onPick,
20
- }: DayProps) => {
21
- const [theme] = useTheme();
22
-
23
- const onClick = () => {
24
- if (date && onPick) onPick(date);
25
- };
26
-
27
- const backgroundStyle = css`
28
- display: flex;
29
- justify-content: center;
30
- align-items: center;
31
- width: 40px;
32
- height: 40px;
33
- background-color: ${theme.color.neutral.white};
34
- cursor: pointer;
35
- outline: none;
36
-
37
- &:hover {
38
- background-color: ${theme.color.neutral.grey10};
39
- }
40
-
41
- ${isSelected &&
42
- css`
43
- background-color: ${theme.color.interaction.blue70};
44
- color: ${theme.color.text.inverted};
45
-
46
- &:hover {
47
- background-color: ${theme.color.interaction
48
- .blue100};
49
- }
50
- `}
51
- ${isDisabled &&
52
- css`
53
- cursor: not-allowed;
54
-
55
- &:hover {
56
- background-color: ${theme.color.neutral.white};
57
- }
58
- `}
59
- `;
60
-
61
- const foregroundStyle = css`
62
- font-family: ${theme.font.family.primary};
63
- user-select: none;
64
- font-size: 16px;
65
-
66
- ${!isInCurrentMonth &&
67
- css`
68
- color: ${theme.color.neutral.grey40};
69
- `}
70
- ${isToday &&
71
- css`
72
- font-weight: 700;
73
- `}
74
- ${isDisabled &&
75
- css`
76
- color: ${theme.color.neutral.grey40};
77
- `}
78
- `;
79
-
80
- return (
81
- <div
82
- className={backgroundStyle}
83
- role='button'
84
- aria-label={`Select ${date?.toDateString()}`}
85
- onClick={onClick}
86
- >
87
- <div className={foregroundStyle}>
88
- {date?.getDate()}
89
- </div>
90
- </div>
91
- );
92
- };
93
-
94
- export default Day;