uikit-react-public 0.44.2 → 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.
Files changed (31) hide show
  1. package/dist/components/Calendar/Calendar.d.ts +1 -1
  2. package/dist/components/Calendar/Calendar.stories.d.ts +1 -1
  3. package/dist/components/Calendar/Calendar.types.d.ts +8 -0
  4. package/dist/components/Calendar/index.d.ts +1 -1
  5. package/dist/components/Calendar/subcomponents/Day.d.ts +4 -2
  6. package/dist/components/Calendar/subcomponents/Day.stories.d.ts +1 -1
  7. package/dist/components/Calendar/subcomponents/EventDot.d.ts +3 -1
  8. package/dist/components/Calendar/subcomponents/Grid.d.ts +3 -2
  9. package/dist/components/Calendar/subcomponents/__tests__/Day.test.d.ts +1 -0
  10. package/dist/components/Calendar/subcomponents/__tests__/EventDot.test.d.ts +1 -0
  11. package/dist/components/Datepicker/Datepicker.types.d.ts +2 -1
  12. package/dist/components/Datepicker/subcomponents/CustomDatepicker.d.ts +3 -2
  13. package/dist/components/index.d.ts +1 -1
  14. package/dist/index.js +2230 -2180
  15. package/lib/components/Calendar/Calendar.stories.tsx +47 -12
  16. package/lib/components/Calendar/Calendar.tsx +2 -0
  17. package/lib/components/Calendar/Calendar.types.ts +15 -0
  18. package/lib/components/Calendar/__tests__/Calendar.test.tsx +37 -2
  19. package/lib/components/Calendar/__tests__/__snapshots__/Calendar.test.tsx.snap +462 -231
  20. package/lib/components/Calendar/index.ts +6 -1
  21. package/lib/components/Calendar/subcomponents/Day.tsx +44 -5
  22. package/lib/components/Calendar/subcomponents/EventDot.tsx +42 -6
  23. package/lib/components/Calendar/subcomponents/Grid.tsx +4 -1
  24. package/lib/components/Calendar/subcomponents/__tests__/Day.test.tsx +139 -0
  25. package/lib/components/Calendar/subcomponents/__tests__/EventDot.test.tsx +78 -0
  26. package/lib/components/Datepicker/Datepicker.stories.tsx +29 -6
  27. package/lib/components/Datepicker/Datepicker.types.ts +6 -1
  28. package/lib/components/Datepicker/__tests__/Datepicker.test.tsx +26 -0
  29. package/lib/components/Datepicker/subcomponents/CustomDatepicker.tsx +8 -1
  30. package/lib/components/index.ts +1 -1
  31. package/package.json +1 -1
@@ -61,22 +61,57 @@ export const WithEvents: Story = {
61
61
  const currentYear = currentDate.getFullYear();
62
62
  const currentMonth = currentDate.getMonth();
63
63
  return [
64
- // Grey event dots
64
+ // Events outside the current month are always shown as disabled, regardless of status
65
65
  { date: dateToISOString(new Date(currentYear, currentMonth, -2)) },
66
- { date: dateToISOString(new Date(currentYear, currentMonth, -1)) },
67
- { date: dateToISOString(new Date(currentYear, currentMonth, -1)) },
68
- { date: dateToISOString(new Date(currentYear, currentMonth, 0)) },
69
- { date: dateToISOString(new Date(currentYear, currentMonth, 0)) },
70
- { date: dateToISOString(new Date(currentYear, currentMonth, 0)) },
71
- // Blue event dots
66
+ {
67
+ date: dateToISOString(new Date(currentYear, currentMonth, -1)),
68
+ status: 'pending',
69
+ },
70
+ {
71
+ date: dateToISOString(new Date(currentYear, currentMonth, -1)),
72
+ status: 'pending',
73
+ },
74
+ {
75
+ date: dateToISOString(new Date(currentYear, currentMonth, 0)),
76
+ status: 'approved',
77
+ },
78
+ {
79
+ date: dateToISOString(new Date(currentYear, currentMonth, 0)),
80
+ status: 'approved',
81
+ },
82
+ {
83
+ date: dateToISOString(new Date(currentYear, currentMonth, 0)),
84
+ status: 'approved',
85
+ },
86
+ // Events within the current month show variant colours: brand (default), warning (pending), success (approved)
72
87
  { date: dateToISOString(new Date(currentYear, currentMonth, 1)) },
73
- { date: dateToISOString(new Date(currentYear, currentMonth, 2)) },
74
- { date: dateToISOString(new Date(currentYear, currentMonth, 2)) },
75
- { date: dateToISOString(new Date(currentYear, currentMonth, 3)) },
76
- { date: dateToISOString(new Date(currentYear, currentMonth, 3)) },
77
- { date: dateToISOString(new Date(currentYear, currentMonth, 3)) },
88
+ {
89
+ date: dateToISOString(new Date(currentYear, currentMonth, 2)),
90
+ status: 'pending',
91
+ },
92
+ {
93
+ date: dateToISOString(new Date(currentYear, currentMonth, 2)),
94
+ status: 'pending',
95
+ },
96
+ {
97
+ date: dateToISOString(new Date(currentYear, currentMonth, 3)),
98
+ status: 'approved',
99
+ },
100
+ {
101
+ date: dateToISOString(new Date(currentYear, currentMonth, 3)),
102
+ status: 'pending',
103
+ },
104
+ {
105
+ date: dateToISOString(new Date(currentYear, currentMonth, 3)),
106
+ status: 'rejected',
107
+ },
78
108
  ];
79
109
  })(),
110
+ statuses: {
111
+ pending: { variant: 'warning', ariaLabel: 'Pending' },
112
+ approved: { variant: 'success', ariaLabel: 'Approved' },
113
+ rejected: { variant: 'critical', ariaLabel: 'Rejected' },
114
+ },
80
115
  },
81
116
  render: () => {
82
117
  const [args, updateArgs] = useArgs();
@@ -18,6 +18,7 @@ const Calendar = ({
18
18
  minYear = DEFAULT_MIN_YEAR,
19
19
  maxYear = DEFAULT_MAX_YEAR,
20
20
  events = [],
21
+ statuses = {},
21
22
  showAcademicWeeks = false,
22
23
  academicWeeks = [],
23
24
  testId = NAME,
@@ -166,6 +167,7 @@ const Calendar = ({
166
167
  minDate={minDateParsed}
167
168
  maxDate={maxDateParsed}
168
169
  events={events}
170
+ statuses={statuses}
169
171
  />
170
172
  </div>
171
173
  </div>
@@ -1,6 +1,20 @@
1
+ // Used to determine the colour of the EventDot
2
+ export type CalendarEventVariant =
3
+ 'critical' | 'success' | 'caution' | 'warning' | 'info';
4
+
5
+ // Maps a status key to the EventDot variant and Day aria-label it should apply
6
+ export type CalendarStatusConfig = {
7
+ variant: CalendarEventVariant;
8
+ ariaLabel: string;
9
+ };
10
+
11
+ // Keyed by the status names referenced by `CalendarEvent.status`
12
+ export type CalendarStatuses = Record<string, CalendarStatusConfig>;
13
+
1
14
  // Used to display EventDots inside `<Day>` component
2
15
  export type CalendarEvent = {
3
16
  date: string; // Date string in YYYY-MM-DD format
17
+ status?: string; // Key into the `statuses` prop on `<Calendar>`
4
18
  };
5
19
 
6
20
  export type AcademicWeek = {
@@ -17,6 +31,7 @@ export interface CalendarProps {
17
31
  minYear?: number;
18
32
  maxYear?: number;
19
33
  events?: CalendarEvent[];
34
+ statuses?: CalendarStatuses;
20
35
  showAcademicWeeks?: boolean;
21
36
  academicWeeks?: AcademicWeek[];
22
37
  testId?: string;
@@ -1,10 +1,19 @@
1
1
  import { describe, test, expect, vi, beforeAll } from 'vitest';
2
- import { fireEvent, render, screen } from '@testing-library/react';
3
- import { ThemeContextProvider } from '../../../theme';
2
+ import { fireEvent, render, screen, within } from '@testing-library/react';
3
+ import { ThemeContextProvider, theme } from '../../../theme';
4
4
  import Calendar from '../Calendar';
5
5
 
6
6
  const defaultTestId = 'ucl-uikit-calendar';
7
7
 
8
+ const hexToRgb = (hex: string) => {
9
+ const value = hex.replace('#', '');
10
+ const red = parseInt(value.slice(0, 2), 16);
11
+ const green = parseInt(value.slice(2, 4), 16);
12
+ const blue = parseInt(value.slice(4, 6), 16);
13
+
14
+ return `rgb(${red}, ${green}, ${blue})`;
15
+ };
16
+
8
17
  const customRender = (ui: React.ReactElement) => {
9
18
  return render(ui, {
10
19
  wrapper: ({ children }) => (
@@ -181,6 +190,32 @@ describe('Calendar', () => {
181
190
  ).not.toBeInTheDocument();
182
191
  });
183
192
 
193
+ test('Applies EventDot colours and Day aria-labels from the statuses prop', () => {
194
+ customRender(
195
+ <Calendar
196
+ pickedDate={new Date('2025-03-01')} // To ensure the calendar is displayed for March 2025
197
+ events={[
198
+ { date: '2025-03-15', status: 'pending' },
199
+ { date: '2025-03-15', status: 'pending' },
200
+ ]}
201
+ statuses={{
202
+ pending: { variant: 'warning', ariaLabel: 'Pending' },
203
+ }}
204
+ />
205
+ );
206
+
207
+ const day = screen
208
+ .getByText('15')
209
+ .closest('[data-testid="ucl-uikit-calendar__day"]') as HTMLElement;
210
+
211
+ expect(day).toHaveAttribute('aria-label', '15 March 2025, 2 Pending');
212
+
213
+ const dot = within(day).getAllByTestId('ucl-uikit-calendar__event-dot')[0];
214
+ expect(getComputedStyle(dot).backgroundColor).toBe(
215
+ hexToRgb(theme.colour.icon.warning)
216
+ );
217
+ });
218
+
184
219
  test('Year select uses minDate and maxDate years when provided', () => {
185
220
  customRender(
186
221
  <Calendar