uikit-react-public 0.11.24 → 0.17.4

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 (301) hide show
  1. package/README.md +4 -2
  2. package/dist/components/Accordion/Accordion.Heading.d.ts +4 -4
  3. package/dist/components/Accordion/Accordion.Panel.d.ts +2 -2
  4. package/dist/components/Accordion/Accordion.d.ts +1 -1
  5. package/dist/components/Accordion/Accordion.stories.d.ts +57 -0
  6. package/dist/components/Accordion/index.d.ts +2 -0
  7. package/dist/components/Avatar/Avatar.stories.d.ts +107 -1
  8. package/dist/components/Badge/Badge.d.ts +6 -0
  9. package/dist/components/Badge/Badge.stories.d.ts +15 -0
  10. package/dist/components/Badge/index.d.ts +2 -0
  11. package/dist/components/Button/Button.d.ts +3 -1
  12. package/dist/components/Calendar/index.d.ts +1 -1
  13. package/dist/components/CookieNotice/CookieNotice.d.ts +16 -0
  14. package/dist/components/CookieNotice/index.d.ts +2 -0
  15. package/dist/components/Datepicker/Datepicker.d.ts +1 -1
  16. package/dist/components/Datepicker/Datepicker.stories.d.ts +4 -3
  17. package/dist/components/Datepicker/Datepicker.types.d.ts +4 -5
  18. package/dist/components/Datepicker/subcomponents/CustomDatepicker.d.ts +4 -1
  19. package/dist/components/Datepicker/subcomponents/DatepickerInput.d.ts +15 -2
  20. package/dist/components/Datepicker/subcomponents/Panel.d.ts +1 -1
  21. package/dist/components/Datepicker/subcomponents/VisibleField.d.ts +6 -1
  22. package/dist/components/Datepicker/subcomponents/index.d.ts +0 -1
  23. package/dist/components/Datepicker/utils/index.d.ts +0 -1
  24. package/dist/components/Dialog/BaseDialog.d.ts +8 -2
  25. package/dist/components/Dialog/Dialog.d.ts +2 -0
  26. package/dist/components/FileInput/FileInput.d.ts +8 -0
  27. package/dist/components/FileInput/FileInput.stories.d.ts +16 -0
  28. package/dist/components/FileInput/index.d.ts +2 -0
  29. package/dist/components/Header/Header.d.ts +7 -1
  30. package/dist/components/Header/Header.stories.d.ts +40 -0
  31. package/dist/components/Heading/Heading.d.ts +1 -1
  32. package/dist/components/Link/BaseLink.d.ts +10 -0
  33. package/dist/components/Link/Link.d.ts +5 -10
  34. package/dist/components/Link/Link.stories.d.ts +1 -1
  35. package/dist/components/Link/index.d.ts +1 -1
  36. package/dist/components/Main/Main.d.ts +21 -0
  37. package/dist/components/Main/Main.stories.d.ts +15 -0
  38. package/dist/components/Main/__tests__/Main.test.d.ts +1 -0
  39. package/dist/components/Main/index.d.ts +2 -0
  40. package/dist/components/Menu/MenuContent.d.ts +1 -1
  41. package/dist/components/Menu/MenuItem.d.ts +2 -0
  42. package/dist/components/Menu/MenuSection.d.ts +1 -1
  43. package/dist/components/NativeDatepicker/NativeDatepicker.d.ts +3 -0
  44. package/dist/components/NativeDatepicker/NativeDatepicker.stories.d.ts +36 -0
  45. package/dist/components/NativeDatepicker/NativeDatepicker.types.d.ts +10 -0
  46. package/dist/components/NativeDatepicker/index.d.ts +2 -0
  47. package/dist/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.d.ts +1 -1
  48. package/dist/components/NativeDatepicker/utils/dateToLocaleISOString/dateToLocaleISOString.test.d.ts +1 -0
  49. package/dist/components/NativeDatepicker/utils/index.d.ts +1 -0
  50. package/dist/components/Search/Search.d.ts +16 -0
  51. package/dist/components/Search/Search.stories.d.ts +34 -0
  52. package/dist/components/Search/__tests__/Search.test.d.ts +1 -0
  53. package/dist/components/Search/index.d.ts +2 -0
  54. package/dist/components/Select/Select.d.ts +1 -1
  55. package/dist/components/Select/Select.stories.d.ts +157 -9
  56. package/dist/components/Select/Select.types.d.ts +66 -32
  57. package/dist/components/Select/subcomponents/CustomOption.d.ts +1 -1
  58. package/dist/components/Select/subcomponents/CustomSelect.d.ts +3 -3
  59. package/dist/components/Select/subcomponents/FilterInput.d.ts +14 -0
  60. package/dist/components/Select/subcomponents/NativeSelect.d.ts +5 -1
  61. package/dist/components/Select/subcomponents/Panel.d.ts +1 -1
  62. package/dist/components/Select/subcomponents/VisibleField.d.ts +6 -4
  63. package/dist/components/Select/subcomponents/index.d.ts +1 -0
  64. package/dist/components/StandaloneLink/StandaloneLink.d.ts +12 -0
  65. package/dist/components/StandaloneLink/StandaloneLink.stories.d.ts +13 -0
  66. package/dist/components/StandaloneLink/__tests__/StandaloneLink.test.d.ts +1 -0
  67. package/dist/components/StandaloneLink/index.d.ts +2 -0
  68. package/dist/components/Table/Table.d.ts +10 -8
  69. package/dist/components/Table/Table.stories.d.ts +21 -0
  70. package/dist/components/Table/Table.types.d.ts +11 -0
  71. package/dist/components/Table/__tests__/Table.test.d.ts +1 -0
  72. package/dist/components/Table/index.d.ts +2 -1
  73. package/dist/components/Table/subcomponents/Body.d.ts +4 -0
  74. package/dist/components/Table/subcomponents/Cell/Cell.d.ts +12 -0
  75. package/dist/components/Table/subcomponents/Cell/Cell.stories.d.ts +313 -0
  76. package/dist/components/Table/subcomponents/Cell/CellContent.d.ts +10 -0
  77. package/dist/components/Table/subcomponents/Cell/__tests__/Cell.test.d.ts +1 -0
  78. package/dist/components/Table/subcomponents/Head.d.ts +4 -0
  79. package/dist/components/Table/subcomponents/HeadCell/HeadCell.d.ts +13 -0
  80. package/dist/components/Table/subcomponents/HeadCell/HeadCell.stories.d.ts +312 -0
  81. package/dist/components/Table/subcomponents/HeadCell/HeadCellContent.d.ts +10 -0
  82. package/dist/components/Table/subcomponents/HeadCell/__tests__/HeadCell.test.d.ts +1 -0
  83. package/dist/components/Table/subcomponents/Row.d.ts +5 -0
  84. package/dist/components/Table/subcomponents/SortIcon.d.ts +7 -0
  85. package/dist/components/Table/subcomponents/index.d.ts +10 -0
  86. package/dist/components/Tabs/Tab.d.ts +1 -1
  87. package/dist/components/Tabs/TabContext.d.ts +1 -0
  88. package/dist/components/Tabs/Tabs.d.ts +3 -1
  89. package/dist/components/Tabs/Tabs.stories.d.ts +3 -0
  90. package/dist/components/Timepicker/Timepicker.d.ts +10 -0
  91. package/dist/components/Timepicker/Timepicker.stories.d.ts +7 -0
  92. package/dist/components/Timepicker/__tests__/Timepicker.test.d.ts +1 -0
  93. package/dist/components/Timepicker/index.d.ts +2 -0
  94. package/dist/components/Timepicker/utils/convertDateToTimeString.d.ts +2 -0
  95. package/dist/components/Timepicker/utils/convertDateToTimeString.test.d.ts +1 -0
  96. package/dist/components/Timepicker/utils/index.d.ts +1 -0
  97. package/dist/components/WeekPicker/WeekPicker.d.ts +3 -0
  98. package/dist/components/WeekPicker/WeekPicker.stories.d.ts +41 -0
  99. package/dist/components/WeekPicker/WeekPicker.types.d.ts +16 -0
  100. package/dist/components/WeekPicker/index.d.ts +2 -0
  101. package/dist/components/WeekPicker/subcomponents/CustomDatepicker.d.ts +17 -0
  102. package/dist/components/WeekPicker/subcomponents/DatepickerInput.d.ts +13 -0
  103. package/dist/components/WeekPicker/subcomponents/VisibleField.d.ts +15 -0
  104. package/dist/components/WeekPicker/subcomponents/index.d.ts +3 -0
  105. package/dist/components/index.d.ts +19 -0
  106. package/dist/hooks/index.d.ts +2 -0
  107. package/dist/hooks/useFocusTrap.d.ts +10 -0
  108. package/dist/index.d.ts +2 -0
  109. package/dist/index.js +6460 -4607
  110. package/dist/theme/defaultTheme.d.ts +7 -0
  111. package/dist/theme/useTheme.d.ts +14 -0
  112. package/dist/utils/__tests__/announce.test.d.ts +1 -0
  113. package/dist/utils/__tests__/capitalise.test.d.ts +1 -0
  114. package/dist/utils/announce.d.ts +6 -0
  115. package/dist/utils/capitalise.d.ts +2 -0
  116. package/dist/utils/index.d.ts +1 -0
  117. package/lib/components/Accordion/Accordion.Heading.tsx +27 -8
  118. package/lib/components/Accordion/Accordion.Panel.tsx +11 -3
  119. package/lib/components/Accordion/Accordion.stories.tsx +139 -0
  120. package/lib/components/Accordion/Accordion.tsx +10 -8
  121. package/lib/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap +7 -7
  122. package/lib/components/Accordion/index.ts +2 -0
  123. package/lib/components/Alert/Alert.stories.tsx +1 -1
  124. package/lib/components/Alert/Alert.tsx +7 -1
  125. package/lib/components/Alert/__tests__/__snapshots__/Alert.test.tsx.snap +4 -0
  126. package/lib/components/Avatar/Avatar.mdx +117 -0
  127. package/lib/components/Avatar/Avatar.stories.tsx +110 -2
  128. package/lib/components/Badge/Badge.stories.tsx +19 -0
  129. package/lib/components/Badge/Badge.tsx +48 -0
  130. package/lib/components/Badge/index.ts +2 -0
  131. package/lib/components/Blanket/Blanket.stories.tsx +1 -1
  132. package/lib/components/Breadcrumbs/__tests__/__snapshots__/Breadcrumbs.test.tsx.snap +4 -4
  133. package/lib/components/Button/Button.stories.tsx +1 -1
  134. package/lib/components/Button/Button.tsx +6 -2
  135. package/lib/components/Calendar/Calendar.stories.tsx +12 -32
  136. package/lib/components/Calendar/__tests__/Calendar.test.tsx +23 -15
  137. package/lib/components/Calendar/index.ts +1 -5
  138. package/lib/components/Calendar/subcomponents/AcademicWeeks.tsx +2 -1
  139. package/lib/components/Calendar/subcomponents/ColumnHeading.tsx +5 -1
  140. package/lib/components/Calendar/subcomponents/EventDot.tsx +2 -1
  141. package/lib/components/Calendar/subcomponents/Grid.tsx +0 -1
  142. package/lib/components/Calendar/subcomponents/index.ts +1 -1
  143. package/lib/components/Calendar/utils/getDatesForCalendarGrid/getDatesForCalendarGrid.ts +43 -11
  144. package/lib/components/Calendar/utils/normaliseMonth/normaliseMonth.test.ts +5 -5
  145. package/lib/components/CookieNotice/CookieNotice.tsx +114 -0
  146. package/lib/components/CookieNotice/index.ts +2 -0
  147. package/lib/components/Datepicker/Datepicker.lld.md +108 -0
  148. package/lib/components/Datepicker/Datepicker.stories.tsx +44 -5
  149. package/lib/components/Datepicker/Datepicker.tsx +14 -36
  150. package/lib/components/Datepicker/Datepicker.types.ts +5 -14
  151. package/lib/components/Datepicker/__tests__/Datepicker.test.tsx +150 -8
  152. package/lib/components/Datepicker/__tests__/__snapshots__/Datepicker.test.tsx.snap +10 -4
  153. package/lib/components/Datepicker/subcomponents/CustomDatepicker.tsx +39 -5
  154. package/lib/components/Datepicker/subcomponents/DatepickerInput.tsx +30 -17
  155. package/lib/components/Datepicker/subcomponents/Panel.tsx +6 -2
  156. package/lib/components/Datepicker/subcomponents/VisibleField.tsx +40 -3
  157. package/lib/components/Datepicker/subcomponents/index.ts +0 -1
  158. package/lib/components/Datepicker/utils/index.ts +0 -1
  159. package/lib/components/Dialog/BaseDialog.tsx +55 -4
  160. package/lib/components/Dialog/Dialog.tsx +8 -1
  161. package/lib/components/Dialog/DialogBody.tsx +5 -1
  162. package/lib/components/Dialog/DialogHeader.tsx +2 -1
  163. package/lib/components/Divider/Divider.stories.tsx +1 -1
  164. package/lib/components/Field/ErrorText.tsx +1 -0
  165. package/lib/components/Field/Field.stories.tsx +1 -1
  166. package/lib/components/Field/__tests__/Field.test.tsx +161 -148
  167. package/lib/components/FileInput/FileInput.stories.tsx +70 -0
  168. package/lib/components/FileInput/FileInput.tsx +68 -0
  169. package/lib/components/FileInput/__tests__/FileInput.test.tsx +99 -0
  170. package/lib/components/FileInput/__tests__/__snapshots__/FileInput.test.tsx.snap +91 -0
  171. package/lib/components/FileInput/index.ts +2 -0
  172. package/lib/components/Footer/Footer.stories.tsx +1 -1
  173. package/lib/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +28 -28
  174. package/lib/components/Header/Header.mdx +52 -0
  175. package/lib/components/Header/Header.stories.tsx +98 -0
  176. package/lib/components/Header/Header.tsx +65 -3
  177. package/lib/components/Header/__tests__/Header.test.tsx +17 -1
  178. package/lib/components/Header/__tests__/__snapshots__/Header.test.tsx.snap +4 -4
  179. package/lib/components/Heading/Documentation.mdx +1 -1
  180. package/lib/components/Heading/Heading.stories.tsx +1 -1
  181. package/lib/components/Heading/Heading.tsx +1 -1
  182. package/lib/components/Heading/__tests__/Heading.test.tsx +7 -19
  183. package/lib/components/Heading/__tests__/__snapshots__/Heading.test.tsx.snap +7 -7
  184. package/lib/components/Icon/Icon.stories.tsx +1 -1
  185. package/lib/components/IconButton/IconButton.stories.tsx +1 -1
  186. package/lib/components/Input/Input.stories.tsx +1 -1
  187. package/lib/components/Label/Label.stories.tsx +1 -1
  188. package/lib/components/Label/Label.tsx +0 -2
  189. package/lib/components/Label/__tests__/__snapshots__/Label.test.tsx.snap +7 -7
  190. package/lib/components/Link/BaseLink.tsx +84 -0
  191. package/lib/components/Link/Link.tsx +72 -32
  192. package/lib/components/Link/__tests__/__snapshots__/link.test.tsx.snap +3 -3
  193. package/lib/components/Link/__tests__/link.test.tsx +6 -13
  194. package/lib/components/Link/index.ts +1 -1
  195. package/lib/components/Main/Main.stories.tsx +36 -0
  196. package/lib/components/Main/Main.tsx +46 -0
  197. package/lib/components/Main/__tests__/Main.test.tsx +80 -0
  198. package/lib/components/Main/__tests__/__snapshots__/Main.test.tsx.snap +33 -0
  199. package/lib/components/Main/index.ts +2 -0
  200. package/lib/components/Menu/Menu.context.tsx +3 -1
  201. package/lib/components/Menu/Menu.tsx +2 -2
  202. package/lib/components/Menu/MenuContent.tsx +5 -5
  203. package/lib/components/Menu/MenuItem.tsx +20 -3
  204. package/lib/components/Menu/MenuSection.tsx +4 -3
  205. package/lib/components/NativeDatepicker/NativeDatepicker.stories.tsx +100 -0
  206. package/lib/components/{Datepicker/subcomponents → NativeDatepicker}/NativeDatepicker.tsx +14 -15
  207. package/lib/components/NativeDatepicker/NativeDatepicker.types.ts +19 -0
  208. package/lib/components/NativeDatepicker/index.ts +2 -0
  209. package/lib/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.ts +1 -1
  210. package/lib/components/NativeDatepicker/utils/index.ts +1 -0
  211. package/lib/components/Pagination/PaginationControls.tsx +56 -15
  212. package/lib/components/Pagination/PaginationInfo.tsx +5 -1
  213. package/lib/components/Paragraph/Paragraph.stories.tsx +1 -1
  214. package/lib/components/Search/Search.stories.tsx +41 -0
  215. package/lib/components/Search/Search.tsx +170 -0
  216. package/lib/components/Search/__tests__/Search.test.tsx +112 -0
  217. package/lib/components/Search/__tests__/__snapshots__/Search.test.tsx.snap +179 -0
  218. package/lib/components/Search/index.ts +2 -0
  219. package/lib/components/Select/Select.mdx +169 -0
  220. package/lib/components/Select/Select.stories.tsx +198 -77
  221. package/lib/components/Select/Select.tsx +37 -13
  222. package/lib/components/Select/Select.types.ts +77 -54
  223. package/lib/components/Select/__tests__/Select.test.tsx +448 -7
  224. package/lib/components/Select/__tests__/__snapshots__/Select.test.tsx.snap +3 -3
  225. package/lib/components/Select/subcomponents/CustomOption.tsx +24 -10
  226. package/lib/components/Select/subcomponents/CustomSelect.tsx +333 -52
  227. package/lib/components/Select/subcomponents/FilterInput.tsx +80 -0
  228. package/lib/components/Select/subcomponents/NativeSelect.tsx +13 -1
  229. package/lib/components/Select/subcomponents/Panel.tsx +4 -5
  230. package/lib/components/Select/subcomponents/VisibleField.tsx +36 -24
  231. package/lib/components/Select/subcomponents/index.tsx +1 -0
  232. package/lib/components/Snackbar/Snackbar.stories.tsx +1 -1
  233. package/lib/components/Spinner/Spinner.stories.tsx +1 -1
  234. package/lib/components/StandaloneLink/StandaloneLink.stories.tsx +32 -0
  235. package/lib/components/StandaloneLink/StandaloneLink.tsx +183 -0
  236. package/lib/components/StandaloneLink/__tests__/StandaloneLink.test.tsx +57 -0
  237. package/lib/components/StandaloneLink/__tests__/__snapshots__/StandaloneLink.test.tsx.snap +19 -0
  238. package/lib/components/StandaloneLink/index.ts +2 -0
  239. package/lib/components/Table/Table.stories.tsx +337 -0
  240. package/lib/components/Table/Table.tsx +42 -67
  241. package/lib/components/Table/Table.types.ts +14 -0
  242. package/lib/components/Table/__tests__/Table.test.tsx +121 -0
  243. package/lib/components/Table/__tests__/__snapshots__/Table.test.tsx.snap +210 -0
  244. package/lib/components/Table/index.ts +8 -1
  245. package/lib/components/Table/subcomponents/Body.tsx +18 -0
  246. package/lib/components/Table/subcomponents/Cell/Cell.stories.tsx +151 -0
  247. package/lib/components/Table/subcomponents/Cell/Cell.tsx +72 -0
  248. package/lib/components/Table/subcomponents/Cell/CellContent.tsx +91 -0
  249. package/lib/components/Table/subcomponents/Cell/__tests__/Cell.test.tsx +115 -0
  250. package/lib/components/Table/subcomponents/Cell/__tests__/__snapshots__/Cell.test.tsx.snap +107 -0
  251. package/lib/components/Table/subcomponents/Head.tsx +34 -0
  252. package/lib/components/Table/subcomponents/HeadCell/HeadCell.stories.tsx +85 -0
  253. package/lib/components/Table/subcomponents/HeadCell/HeadCell.tsx +99 -0
  254. package/lib/components/Table/subcomponents/HeadCell/HeadCellContent.tsx +61 -0
  255. package/lib/components/Table/subcomponents/HeadCell/__tests__/HeadCell.test.tsx +137 -0
  256. package/lib/components/Table/subcomponents/HeadCell/__tests__/__snapshots__/HeadCell.test.tsx.snap +110 -0
  257. package/lib/components/Table/subcomponents/Row.tsx +49 -0
  258. package/lib/components/Table/subcomponents/SortIcon.tsx +63 -0
  259. package/lib/components/Table/subcomponents/index.ts +14 -0
  260. package/lib/components/Tabs/Tab.tsx +3 -3
  261. package/lib/components/Tabs/TabContext.tsx +1 -0
  262. package/lib/components/Tabs/Tabs.stories.tsx +9 -3
  263. package/lib/components/Tabs/Tabs.tsx +10 -32
  264. package/lib/components/Tabs/__tests__/Tabs.test.tsx +10 -4
  265. package/lib/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap +32 -32
  266. package/lib/components/Textarea/Textarea.stories.tsx +1 -1
  267. package/lib/components/Timepicker/Timepicker.stories.tsx +43 -0
  268. package/lib/components/Timepicker/Timepicker.tsx +100 -0
  269. package/lib/components/Timepicker/__tests__/Timepicker.test.tsx +55 -0
  270. package/lib/components/Timepicker/__tests__/__snapshots__/Timepicker.test.tsx.snap +19 -0
  271. package/lib/components/Timepicker/index.tsx +2 -0
  272. package/lib/components/Timepicker/utils/convertDateToTimeString.test.ts +54 -0
  273. package/lib/components/Timepicker/utils/convertDateToTimeString.ts +10 -0
  274. package/lib/components/Timepicker/utils/index.ts +1 -0
  275. package/lib/components/Toggle/Toggle.stories.tsx +1 -1
  276. package/lib/components/Tooltip/Tooltip.stories.tsx +1 -1
  277. package/lib/components/WeekPicker/WeekPicker.stories.tsx +147 -0
  278. package/lib/components/WeekPicker/WeekPicker.tsx +26 -0
  279. package/lib/components/WeekPicker/WeekPicker.types.ts +21 -0
  280. package/lib/components/WeekPicker/index.ts +2 -0
  281. package/lib/components/WeekPicker/subcomponents/CustomDatepicker.tsx +298 -0
  282. package/lib/components/WeekPicker/subcomponents/DatepickerInput.tsx +111 -0
  283. package/lib/components/WeekPicker/subcomponents/VisibleField.tsx +126 -0
  284. package/lib/components/WeekPicker/subcomponents/index.ts +3 -0
  285. package/lib/components/common/Common.mdx +1 -1
  286. package/lib/components/index.ts +28 -2
  287. package/lib/hooks/index.ts +2 -0
  288. package/lib/hooks/useFocusTrap.ts +159 -0
  289. package/lib/index.ts +2 -0
  290. package/lib/theme/defaultTheme.ts +7 -0
  291. package/lib/utils/__tests__/announce.test.ts +121 -0
  292. package/lib/utils/__tests__/capitalise.test.ts +40 -0
  293. package/lib/utils/announce.ts +134 -0
  294. package/lib/utils/capitalise.ts +4 -0
  295. package/lib/utils/index.ts +1 -0
  296. package/package.json +3 -6
  297. package/dist/components/Datepicker/subcomponents/NativeDatepicker.d.ts +0 -6
  298. package/lib/components/Accordion/Accordion.stories.tsx.NOT_READY +0 -93
  299. package/lib/components/Field/__tests__/__snapshots__/Field.test.tsx.snap +0 -300
  300. /package/dist/components/{Datepicker/utils/dateToLocaleISOString/dateToLocaleISOString.test.d.ts → FileInput/__tests__/FileInput.test.d.ts} +0 -0
  301. /package/lib/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.test.ts +0 -0
@@ -0,0 +1,54 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import convertDatetoTimeString from './convertDateToTimeString';
3
+
4
+ describe('convertDatetoTimeString', () => {
5
+ it('should return a formatted time string for a valid Date object', () => {
6
+ const date = new Date();
7
+ date.setHours(9);
8
+ date.setMinutes(5);
9
+
10
+ const result = convertDatetoTimeString(date);
11
+ expect(result).toBe('09:05');
12
+ });
13
+
14
+ it('should handle single-digit hours and minutes correctly', () => {
15
+ const date = new Date();
16
+ date.setHours(3);
17
+ date.setMinutes(7);
18
+
19
+ const result = convertDatetoTimeString(date);
20
+ expect(result).toBe('03:07');
21
+ });
22
+
23
+ it('should handle double-digit hours and minutes correctly', () => {
24
+ const date = new Date();
25
+ date.setHours(12);
26
+ date.setMinutes(30);
27
+
28
+ const result = convertDatetoTimeString(date);
29
+ expect(result).toBe('12:30');
30
+ });
31
+
32
+ it('should return an empty string for null input', () => {
33
+ const result = convertDatetoTimeString(null);
34
+ expect(result).toBe('');
35
+ });
36
+
37
+ it('should handle midnight (00:00) correctly', () => {
38
+ const date = new Date();
39
+ date.setHours(0);
40
+ date.setMinutes(0);
41
+
42
+ const result = convertDatetoTimeString(date);
43
+ expect(result).toBe('00:00');
44
+ });
45
+
46
+ it('should handle the last minute of the day (23:59) correctly', () => {
47
+ const date = new Date();
48
+ date.setHours(23);
49
+ date.setMinutes(59);
50
+
51
+ const result = convertDatetoTimeString(date);
52
+ expect(result).toBe('23:59');
53
+ });
54
+ });
@@ -0,0 +1,10 @@
1
+ const convertDatetoTimeString = (time: Date | null): string => {
2
+ if (!time) {
3
+ return '';
4
+ }
5
+ const hours = time.getHours().toString().padStart(2, '0');
6
+ const minutes = time.getMinutes().toString().padStart(2, '0');
7
+ return `${hours}:${minutes}`;
8
+ };
9
+
10
+ export default convertDatetoTimeString;
@@ -0,0 +1 @@
1
+ export { default as convertDatetoTimeString } from './convertDateToTimeString';
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
3
3
  import Toggle from './Toggle';
4
4
 
5
5
  const meta = {
6
- title: 'Components/Ready to use/Toggle',
6
+ title: 'Components/Toggle',
7
7
  component: Toggle,
8
8
  parameters: {
9
9
  layout: 'centered',
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
3
3
  import Tooltip from './Tooltip';
4
4
 
5
5
  const meta = {
6
- title: 'Components/Ready to use/Tooltip',
6
+ title: 'Components/Tooltip',
7
7
  component: Tooltip,
8
8
  args: {
9
9
  children: 'Default tooltip text',
@@ -0,0 +1,147 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { useArgs } from '@storybook/preview-api';
3
+ import WeekPicker from './WeekPicker';
4
+
5
+ const meta = {
6
+ title: 'Components/Work in progress/WeekPicker',
7
+ component: WeekPicker,
8
+ parameters: { layout: 'padded' },
9
+ argTypes: {
10
+ value: { control: { type: 'date' } },
11
+ minDate: { control: { type: 'date' } },
12
+ maxDate: { control: { type: 'date' } },
13
+ disabled: { control: { type: 'boolean' } },
14
+ showAcademicWeeks: { control: { type: 'boolean' } },
15
+ },
16
+ tags: ['autodocs'],
17
+ } satisfies Meta<typeof WeekPicker>;
18
+
19
+ export default meta;
20
+ type Story = StoryObj<typeof meta>;
21
+
22
+ export const Default: Story = {
23
+ render: () => {
24
+ const [args, updateArgs] = useArgs();
25
+
26
+ // Storybook controls provide UNIX timestamps for dates, need to convert
27
+ // https://storybook.js.org/docs/essentials/controls#annotation
28
+ args.value = args.value ? new Date(args.value) : null;
29
+ args.minDate = args.minDate
30
+ ? new Date(args.minDate).toLocaleDateString('sv-SE')
31
+ : null;
32
+ args.maxDate = args.maxDate
33
+ ? new Date(args.maxDate).toLocaleDateString('sv-SE')
34
+ : null;
35
+
36
+ const onValueChange = (value: Date | null) =>
37
+ updateArgs({ value: value });
38
+ return (
39
+ <WeekPicker
40
+ {...args}
41
+ onValueChange={onValueChange}
42
+ />
43
+ );
44
+ },
45
+ };
46
+
47
+ const academicWeeks = [
48
+ { start: '2025-08-25', number: 1 },
49
+ { start: '2025-09-01', number: 2 },
50
+ { start: '2025-09-08', number: 3 },
51
+ { start: '2025-09-15', number: 4 },
52
+ { start: '2025-09-22', number: 5 },
53
+ { start: '2025-09-29', number: 6 },
54
+ { start: '2025-10-06', number: 7 },
55
+ { start: '2025-10-13', number: 8 },
56
+ { start: '2025-10-20', number: 9 },
57
+ { start: '2025-10-27', number: 10 },
58
+ { start: '2025-11-03', number: 11 },
59
+ { start: '2025-11-10', number: 12 },
60
+ { start: '2025-11-17', number: 13 },
61
+ { start: '2025-11-24', number: 14 },
62
+ { start: '2025-12-01', number: 15 },
63
+ { start: '2025-12-08', number: 16 },
64
+ { start: '2025-12-15', number: 17 },
65
+ { start: '2025-12-22', number: 18 },
66
+ { start: '2025-12-29', number: 19 },
67
+ { start: '2026-01-05', number: 20 },
68
+ { start: '2026-01-12', number: 21 },
69
+ { start: '2026-01-19', number: 22 },
70
+ { start: '2026-01-26', number: 23 },
71
+ { start: '2026-02-02', number: 24 },
72
+ { start: '2026-02-09', number: 25 },
73
+ { start: '2026-02-16', number: 26 },
74
+ { start: '2026-02-23', number: 27 },
75
+ { start: '2026-03-02', number: 28 },
76
+ { start: '2026-03-09', number: 29 },
77
+ { start: '2026-03-16', number: 30 },
78
+ { start: '2026-03-23', number: 31 },
79
+ { start: '2026-03-30', number: 32 },
80
+ { start: '2026-04-06', number: 33 },
81
+ { start: '2026-04-13', number: 34 },
82
+ { start: '2026-04-20', number: 35 },
83
+ { start: '2026-04-27', number: 36 },
84
+ { start: '2026-05-04', number: 37 },
85
+ { start: '2026-05-11', number: 38 },
86
+ { start: '2026-05-18', number: 39 },
87
+ { start: '2026-05-25', number: 40 },
88
+ { start: '2026-06-01', number: 41 },
89
+ { start: '2026-06-08', number: 42 },
90
+ { start: '2026-06-15', number: 43 },
91
+ { start: '2026-06-22', number: 44 },
92
+ { start: '2026-06-29', number: 45 },
93
+ { start: '2026-07-06', number: 46 },
94
+ { start: '2026-07-13', number: 47 },
95
+ { start: '2026-07-20', number: 48 },
96
+ { start: '2026-07-27', number: 49 },
97
+ { start: '2026-08-03', number: 50 },
98
+ { start: '2026-08-10', number: 51 },
99
+ { start: '2026-08-17', number: 52 },
100
+ { start: '2026-08-24', number: 53 },
101
+ ];
102
+
103
+ export const WithAcademicWeeks: Story = {
104
+ name: 'With academic weeks',
105
+ args: {
106
+ showAcademicWeeks: true,
107
+ academicWeeks: academicWeeks,
108
+ value: new Date(academicWeeks[0].start), // So the week numbers appear on story mount
109
+ },
110
+ render: () => {
111
+ const [args, updateArgs] = useArgs();
112
+
113
+ // Storybook controls provide UNIX timestamps for dates, need to convert
114
+ // https://storybook.js.org/docs/essentials/controls#annotation
115
+ args.value = args.value ? new Date(args.value) : null;
116
+ args.minDate = args.minDate
117
+ ? new Date(args.minDate).toLocaleDateString('sv-SE')
118
+ : null;
119
+ args.maxDate = args.maxDate
120
+ ? new Date(args.maxDate).toLocaleDateString('sv-SE')
121
+ : null;
122
+
123
+ const onValueChange = (value: Date | null) =>
124
+ updateArgs({ value: value });
125
+ return (
126
+ <WeekPicker
127
+ {...args}
128
+ onValueChange={onValueChange}
129
+ />
130
+ );
131
+ },
132
+ };
133
+
134
+ export const Disabled: Story = {
135
+ name: 'Disabled',
136
+ args: {
137
+ disabled: true,
138
+ value: new Date(),
139
+ },
140
+ render: () => {
141
+ const [args] = useArgs();
142
+
143
+ args.value = args.value ? new Date(args.value) : null;
144
+
145
+ return <WeekPicker {...args} />;
146
+ },
147
+ };
@@ -0,0 +1,26 @@
1
+ import { CustomDatepicker } from './subcomponents';
2
+ import type { WeekPickerProps } from './WeekPicker.types';
3
+
4
+ const WeekPicker = ({
5
+ value,
6
+ onValueChange,
7
+ minDate,
8
+ maxDate,
9
+ disabled,
10
+ className,
11
+ ...props
12
+ }: WeekPickerProps) => {
13
+ return (
14
+ <CustomDatepicker
15
+ value={value}
16
+ onValueChange={onValueChange}
17
+ minDate={minDate}
18
+ maxDate={maxDate}
19
+ className={className}
20
+ disabled={disabled}
21
+ {...props}
22
+ />
23
+ );
24
+ };
25
+
26
+ export default WeekPicker;
@@ -0,0 +1,21 @@
1
+ import type { HTMLAttributes, RefObject } from 'react';
2
+ import type { CalendarEvent, AcademicWeek } from '../Calendar';
3
+
4
+ export type DatepickerValue = Date | null;
5
+
6
+ export interface WeekPickerProps extends HTMLAttributes<HTMLDivElement> {
7
+ value?: DatepickerValue;
8
+ onValueChange?: (
9
+ value: DatepickerValue,
10
+ event?: React.SyntheticEvent
11
+ ) => void;
12
+ minDate?: string | null;
13
+ maxDate?: string | null;
14
+ disabled?: boolean;
15
+ events?: CalendarEvent[];
16
+ showAcademicWeeks?: boolean;
17
+ academicWeeks?: AcademicWeek[];
18
+ testId?: string;
19
+ ref?: RefObject<HTMLDivElement>;
20
+ inputRef?: RefObject<HTMLInputElement>;
21
+ }
@@ -0,0 +1,2 @@
1
+ export { default } from './WeekPicker';
2
+ export type { WeekPickerProps, DatepickerValue } from './WeekPicker.types';
@@ -0,0 +1,298 @@
1
+ import { useRef, useEffect, useState, useCallback } from 'react';
2
+ import { css, cx } from '@emotion/css';
3
+ import { VisibleField } from './';
4
+ import { Panel } from '../../Datepicker/subcomponents';
5
+ import { Calendar, Icon, IconButton } from '../..';
6
+ import { parseInputValue } from '../../Datepicker/utils';
7
+ import type { DatepickerValue } from '../WeekPicker.types';
8
+ import type { CalendarEvent, AcademicWeek } from '../../Calendar';
9
+
10
+ interface CustomDatepickerProps extends React.HTMLAttributes<HTMLDivElement> {
11
+ value?: DatepickerValue;
12
+ onValueChange?: (
13
+ value: DatepickerValue,
14
+ event?: React.SyntheticEvent
15
+ ) => void;
16
+ minDate?: string | null; // ISO date string: YYYY-MM-DD
17
+ maxDate?: string | null; // ISO date string: YYYY-MM-DD
18
+ disabled?: boolean;
19
+ events?: CalendarEvent[];
20
+ showAcademicWeeks?: boolean;
21
+ academicWeeks?: AcademicWeek[];
22
+ testId?: string;
23
+ ref?: React.RefObject<HTMLDivElement>;
24
+ inputRef?: React.RefObject<HTMLInputElement>;
25
+ }
26
+
27
+ const NAME = 'ucl-uikit-weekpicker';
28
+
29
+ const CustomDatepicker = ({
30
+ value = null,
31
+ onValueChange = () => {},
32
+ minDate,
33
+ maxDate,
34
+ disabled = false,
35
+ events,
36
+ showAcademicWeeks,
37
+ academicWeeks = [],
38
+ testId = NAME,
39
+ className,
40
+ ref,
41
+ inputRef,
42
+ ...props
43
+ }: CustomDatepickerProps) => {
44
+ if (value && isNaN(value.getTime())) {
45
+ console.warn('CustomDatepicker: value is invalid, defaulting to null');
46
+ value = null;
47
+ }
48
+
49
+ function parseDateFromInput(input: string): Date | null {
50
+ if (!input) return null;
51
+ const parts = input.split('/');
52
+ if (parts.length !== 3) return null;
53
+
54
+ const day = parseInt(parts[0]);
55
+ const month = parseInt(parts[1]) - 1;
56
+ const year = parseInt(parts[2]);
57
+
58
+ const date = new Date(year, month, day);
59
+ return isNaN(date.getTime()) ? null : date;
60
+ }
61
+
62
+ function getWeekRange(date: Date, startOnMonday = true) {
63
+ const input = new Date(date);
64
+ input.setHours(0, 0, 0, 0);
65
+
66
+ const day = input.getDay();
67
+
68
+ const diffToMonday = startOnMonday ? (day === 0 ? -6 : 1 - day) : -day;
69
+
70
+ const start = new Date(input);
71
+ start.setDate(input.getDate() + diffToMonday);
72
+
73
+ const end = new Date(start);
74
+ end.setDate(start.getDate() + 6);
75
+
76
+ return { start, end };
77
+ }
78
+
79
+ const internalRef = useRef<HTMLDivElement>(null);
80
+ const effectiveRef = ref || internalRef;
81
+ const internalInputRef = useRef<HTMLInputElement>(null);
82
+ const effectiveInputRef = inputRef || internalInputRef;
83
+
84
+ const [panelOpen, setPanelOpen] = useState(false);
85
+
86
+ // Derived props (tidier than using `date?.getDate()`, etc, everywhere.)
87
+ const day = value?.getDate().toString().padStart(2, '0') ?? '';
88
+ const month = value ? (value.getMonth() + 1).toString().padStart(2, '0') : '';
89
+ const year = value?.getFullYear().toString() ?? '';
90
+ const formattedDateString = value ? `${day}/${month}/${year}` : '';
91
+
92
+ const [inputValue, setInputValue] = useState(formattedDateString);
93
+
94
+ const resetField = useCallback(() => {
95
+ setInputValue(formattedDateString);
96
+ }, [setInputValue, formattedDateString]);
97
+
98
+ useEffect(() => {
99
+ // Reset the input field when the value changes.
100
+ resetField();
101
+ }, [value, resetField]);
102
+
103
+ const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
104
+ setInputValue(event.target.value);
105
+ };
106
+
107
+ const handleParseInput = (event: React.SyntheticEvent) => {
108
+ // `parseInputValue` checks the date is valid and within min/max range.
109
+ const parseDate = parseInputValue(inputValue, minDate, maxDate);
110
+ if (parseDate) {
111
+ onValueChange(parseDate, event);
112
+ } else {
113
+ resetField();
114
+ }
115
+ };
116
+
117
+ const handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
118
+ if (event.key === 'Enter') {
119
+ handleParseInput(event);
120
+ } else if (event.key === 'Escape') {
121
+ resetField();
122
+ effectiveInputRef.current?.blur();
123
+ setPanelOpen(false);
124
+ } else if (event.key === 'Tab') {
125
+ resetField();
126
+ setPanelOpen(false);
127
+ }
128
+ };
129
+
130
+ // If `value` is out of range, automatically set it to null.
131
+ // This is validation to prevent parent components passing invalid dates.
132
+ useEffect(() => {
133
+ const isDateOutOfRange = (date: Date | null): boolean => {
134
+ if (!date) return false;
135
+
136
+ const normaliseDate = (date: Date) => {
137
+ date.setHours(0, 0, 0, 0); // Normalize to UTC midnight to avoid time zone issues
138
+ return date;
139
+ };
140
+
141
+ const parsedMinDate = minDate ? normaliseDate(new Date(minDate)) : null;
142
+ const parsedMaxDate = maxDate ? normaliseDate(new Date(maxDate)) : null;
143
+ const normalisedDate = normaliseDate(date);
144
+
145
+ if (parsedMinDate && normalisedDate < parsedMinDate) return true;
146
+ if (parsedMaxDate && normalisedDate > parsedMaxDate) return true;
147
+ return false;
148
+ };
149
+
150
+ if (value && isDateOutOfRange(value)) {
151
+ console.warn('CustomDatepicker: value is out of range, setting to null');
152
+ onValueChange(null);
153
+ }
154
+ }, [value, minDate, maxDate, onValueChange]);
155
+
156
+ // Close the panel & reset the input field if we click away.
157
+ useEffect(() => {
158
+ const handleClickOutside = (event: MouseEvent) => {
159
+ if (
160
+ effectiveRef.current &&
161
+ !effectiveRef.current.contains(event.target as Node)
162
+ ) {
163
+ setPanelOpen(false);
164
+ resetField();
165
+ }
166
+ };
167
+ document.addEventListener('mousedown', handleClickOutside);
168
+ return () => {
169
+ document.removeEventListener('mousedown', handleClickOutside);
170
+ };
171
+ }, [effectiveRef, setPanelOpen, resetField]);
172
+
173
+ useEffect(() => {
174
+ // Close the panel if the <Datepicker> becomes disabled
175
+ if (disabled && panelOpen) setPanelOpen(false);
176
+ }, [disabled, panelOpen]);
177
+
178
+ const handlePickCalendarDate = (
179
+ date: Date | null,
180
+ event?: React.SyntheticEvent
181
+ ) => {
182
+ if (onValueChange) {
183
+ onValueChange(date, event);
184
+ }
185
+ setPanelOpen(false);
186
+ };
187
+
188
+ const handleShowPanel = () => {
189
+ if (disabled) return;
190
+ setPanelOpen(true);
191
+ };
192
+
193
+ const handleTogglePanel = () => {
194
+ if (disabled) return;
195
+ setPanelOpen((prev) => !prev);
196
+ };
197
+
198
+ const baseStyle = css`
199
+ box-sizing: border-box;
200
+ position: relative;
201
+ display: flex;
202
+ align-items: center;
203
+ justify-content: space-between;
204
+ gap: 16px;
205
+ `;
206
+
207
+ const style = cx(NAME, className, baseStyle);
208
+
209
+ const parsedDate = parseDateFromInput(inputValue);
210
+ const weekRange = parsedDate ? getWeekRange(parsedDate) : null;
211
+
212
+ let academicWeekNumber: number | null = null;
213
+ if (parsedDate) {
214
+ for (let i = 0; i < academicWeeks.length; i++) {
215
+ const weekStart = new Date(academicWeeks[i].start);
216
+ const nextWeekStart =
217
+ i + 1 < academicWeeks.length
218
+ ? new Date(academicWeeks[i + 1].start)
219
+ : null;
220
+
221
+ weekStart.setHours(0, 0, 0, 0);
222
+ if (nextWeekStart) nextWeekStart.setHours(0, 0, 0, 0);
223
+
224
+ if (
225
+ parsedDate >= weekStart &&
226
+ (!nextWeekStart || parsedDate < nextWeekStart)
227
+ ) {
228
+ academicWeekNumber = academicWeeks[i].number;
229
+ break;
230
+ }
231
+ }
232
+ }
233
+
234
+ const handlePrevWeek = () => {
235
+ if (!parsedDate) return;
236
+ const newDate = new Date(parsedDate);
237
+ newDate.setDate(parsedDate.getDate() - 7);
238
+ onValueChange(newDate);
239
+ };
240
+
241
+ const handleNextWeek = () => {
242
+ if (!parsedDate) return;
243
+ const newDate = new Date(parsedDate);
244
+ newDate.setDate(parsedDate.getDate() + 7);
245
+ onValueChange(newDate);
246
+ };
247
+
248
+ return (
249
+ <div
250
+ className={style}
251
+ data-testid={testId}
252
+ ref={effectiveRef}
253
+ {...props}
254
+ >
255
+ <IconButton
256
+ onClick={handlePrevWeek}
257
+ disabled={disabled}
258
+ aria-label='Go to previous week'
259
+ >
260
+ <Icon.ChevronLeft />
261
+ </IconButton>
262
+ <VisibleField
263
+ inputValue={inputValue}
264
+ onInputChange={handleInputChange}
265
+ onInputKeyDown={handleInputKeyDown}
266
+ onInputFocus={handleShowPanel}
267
+ onButtonClick={handleTogglePanel}
268
+ disabled={disabled}
269
+ inputRef={effectiveInputRef}
270
+ beginningOfWeek={weekRange ? weekRange.start.toDateString() : ''}
271
+ endOfWeek={weekRange ? weekRange.end.toDateString() : ''}
272
+ academicWeekNumber={academicWeekNumber ?? undefined}
273
+ />
274
+ <IconButton
275
+ onClick={handleNextWeek}
276
+ disabled={disabled}
277
+ aria-label='Go to next week'
278
+ >
279
+ <Icon.ChevronRight />
280
+ </IconButton>
281
+ {panelOpen && (
282
+ <Panel>
283
+ <Calendar
284
+ pickedDate={value}
285
+ onDatePick={handlePickCalendarDate}
286
+ minDate={minDate}
287
+ maxDate={maxDate}
288
+ events={events}
289
+ showAcademicWeeks={showAcademicWeeks}
290
+ academicWeeks={academicWeeks}
291
+ />
292
+ </Panel>
293
+ )}
294
+ </div>
295
+ );
296
+ };
297
+
298
+ export default CustomDatepicker;
@@ -0,0 +1,111 @@
1
+ import { css, cx } from '@emotion/css';
2
+ import { useTheme } from '../../../theme';
3
+ import { useState } from 'react';
4
+
5
+ interface DatepickerInputProps {
6
+ value: string;
7
+ onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
8
+ onKeyDown: (event: React.KeyboardEvent<HTMLInputElement>) => void;
9
+ onFocus: () => void;
10
+ disabled: boolean;
11
+ ref: React.RefObject<HTMLInputElement | null>;
12
+ beginningOfWeek?: string;
13
+ endOfWeek?: string;
14
+ academicWeekNumber?: number;
15
+ }
16
+
17
+ const NAME = 'ucl-uikit-weekpicker__input';
18
+
19
+ const DatepickerInput = ({
20
+ value,
21
+ onChange,
22
+ onKeyDown,
23
+ onFocus,
24
+ disabled,
25
+ beginningOfWeek,
26
+ endOfWeek,
27
+ academicWeekNumber,
28
+ ref,
29
+ }: DatepickerInputProps) => {
30
+ const [theme] = useTheme();
31
+
32
+ const [isFocused, setIsFocused] = useState(false);
33
+
34
+ const baseStyle = css`
35
+ width: 100%;
36
+ height: 100%;
37
+ border: none;
38
+ color: ${theme.color.text.primary};
39
+ font-family: ${theme.font.family.primary};
40
+ font-size: ${theme.font.size.f16};
41
+ letter-spacing: 1px;
42
+ caret-color: ${theme.color.text.primary};
43
+ padding: 0px;
44
+
45
+ &:focus {
46
+ outline: none;
47
+ }
48
+
49
+ &::placeholder {
50
+ color: #8c8c8c; // TODO: Needs a design token -- Figma says 'color/text/tertiary'
51
+ }
52
+ `;
53
+
54
+ const disabledStyle = css`
55
+ color: ${theme.color.text.disabled};
56
+ background-color: ${theme.color.neutral.white};
57
+
58
+ &::placeholder {
59
+ color: ${theme.color.text.disabled};
60
+ }
61
+ `;
62
+
63
+ const style = cx(NAME, baseStyle, disabled && disabledStyle);
64
+
65
+ const formatStart = (dateString: string) => {
66
+ const date = new Date(dateString);
67
+ return date.toLocaleDateString('en-GB', {
68
+ day: '2-digit',
69
+ month: 'short',
70
+ });
71
+ };
72
+
73
+ const formatEnd = (dateString: string) => {
74
+ const date = new Date(dateString);
75
+ return date.toLocaleDateString('en-GB', {
76
+ day: '2-digit',
77
+ month: 'short',
78
+ year: 'numeric',
79
+ });
80
+ };
81
+
82
+ const formattedLabel =
83
+ beginningOfWeek && endOfWeek
84
+ ? `${formatStart(beginningOfWeek)} - ${formatEnd(endOfWeek)}`
85
+ : '';
86
+
87
+ const displayValue = isFocused ? value : formattedLabel;
88
+
89
+ return (
90
+ <input
91
+ value={displayValue}
92
+ onChange={onChange}
93
+ onKeyDown={onKeyDown}
94
+ onFocus={() => {
95
+ setIsFocused(true);
96
+ onFocus();
97
+ }}
98
+ onBlur={() => setIsFocused(false)}
99
+ disabled={disabled}
100
+ type='text'
101
+ inputMode='numeric'
102
+ placeholder='DD/MM/YYYY'
103
+ className={style}
104
+ data-testid={NAME}
105
+ ref={ref}
106
+ aria-label={`Currently selected date: ${value} - Week from ${formattedLabel}. ${academicWeekNumber ? `(Academic Week ${academicWeekNumber})` : ''}`}
107
+ />
108
+ );
109
+ };
110
+
111
+ export default DatepickerInput;