@memori.ai/memori-react 8.11.0 → 8.13.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.
Files changed (243) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/dist/components/AgeVerificationModal/AgeVerificationModal.css +41 -14
  3. package/dist/components/AgeVerificationModal/AgeVerificationModal.js +2 -2
  4. package/dist/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
  5. package/dist/components/Auth/Auth.js +36 -8
  6. package/dist/components/Auth/Auth.js.map +1 -1
  7. package/dist/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +2 -2
  8. package/dist/components/Chat/Chat.css +37 -3
  9. package/dist/components/Chat/Chat.js +61 -23
  10. package/dist/components/Chat/Chat.js.map +1 -1
  11. package/dist/components/ChatBubble/ChatBubble.css +87 -15
  12. package/dist/components/ChatBubble/ChatBubble.js +129 -19
  13. package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
  14. package/dist/components/ChatHistoryDrawer/ChatHistory.css +5 -1
  15. package/dist/components/ChatInputs/ChatInputs.css +293 -17
  16. package/dist/components/ChatInputs/ChatInputs.d.ts +1 -0
  17. package/dist/components/ChatInputs/ChatInputs.js +48 -27
  18. package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
  19. package/dist/components/ChatTextArea/ChatTextArea.css +75 -31
  20. package/dist/components/ChatTextArea/ChatTextArea.js +47 -18
  21. package/dist/components/ChatTextArea/ChatTextArea.js.map +1 -1
  22. package/dist/components/DateSelector/DateSelector.css +125 -104
  23. package/dist/components/DateSelector/DateSelector.d.ts +1 -1
  24. package/dist/components/DateSelector/DateSelector.js +110 -52
  25. package/dist/components/DateSelector/DateSelector.js.map +1 -1
  26. package/dist/components/FilePreview/FilePreview.css +225 -146
  27. package/dist/components/FilePreview/FilePreview.d.ts +1 -2
  28. package/dist/components/FilePreview/FilePreview.js +20 -6
  29. package/dist/components/FilePreview/FilePreview.js.map +1 -1
  30. package/dist/components/Header/Header.css +2 -2
  31. package/dist/components/Header/Header.js +1 -1
  32. package/dist/components/Header/Header.js.map +1 -1
  33. package/dist/components/LoginDrawer/LoginDrawer.css +37 -5
  34. package/dist/components/LoginDrawer/LoginDrawer.d.ts +1 -2
  35. package/dist/components/LoginDrawer/LoginDrawer.js +2 -9
  36. package/dist/components/LoginDrawer/LoginDrawer.js.map +1 -1
  37. package/dist/components/MediaWidget/MediaItemWidget.js +2 -1
  38. package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
  39. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js +1 -1
  40. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js.map +1 -1
  41. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js +1 -1
  42. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js.map +1 -1
  43. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js +3 -0
  44. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js.map +1 -1
  45. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +2 -2
  46. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
  47. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +16 -7
  48. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +6 -4
  49. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -1
  50. package/dist/components/MemoriWidget/MemoriWidget.css +11 -2
  51. package/dist/components/MemoriWidget/MemoriWidget.js +105 -25
  52. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  53. package/dist/components/MicrophoneButton/MicrophoneButton.css +2 -2
  54. package/dist/components/StartPanel/StartPanel.css +8 -0
  55. package/dist/components/UploadButton/UploadButton.css +20 -17
  56. package/dist/components/UploadButton/UploadButton.js +218 -87
  57. package/dist/components/UploadButton/UploadButton.js.map +1 -1
  58. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +14 -4
  59. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  60. package/dist/components/UploadButton/UploadImages/UploadImages.js +143 -16
  61. package/dist/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  62. package/dist/components/layouts/chat.css +1 -1
  63. package/dist/components/ui/Drawer.css +8 -0
  64. package/dist/components/ui/Drawer.d.ts +2 -0
  65. package/dist/components/ui/Drawer.js +2 -2
  66. package/dist/components/ui/Drawer.js.map +1 -1
  67. package/dist/components/ui/Tooltip.css +49 -1
  68. package/dist/components/ui/Tooltip.d.ts +1 -1
  69. package/dist/helpers/constants.d.ts +1 -0
  70. package/dist/helpers/constants.js +2 -1
  71. package/dist/helpers/constants.js.map +1 -1
  72. package/dist/helpers/imageCompression.d.ts +7 -0
  73. package/dist/helpers/imageCompression.js +123 -0
  74. package/dist/helpers/imageCompression.js.map +1 -0
  75. package/dist/locales/de.json +13 -5
  76. package/dist/locales/en.json +17 -6
  77. package/dist/locales/es.json +13 -5
  78. package/dist/locales/fr.json +12 -5
  79. package/dist/locales/it.json +16 -6
  80. package/dist/styles.css +4 -4
  81. package/esm/components/AgeVerificationModal/AgeVerificationModal.css +41 -14
  82. package/esm/components/AgeVerificationModal/AgeVerificationModal.js +2 -2
  83. package/esm/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
  84. package/esm/components/Auth/Auth.js +36 -8
  85. package/esm/components/Auth/Auth.js.map +1 -1
  86. package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +2 -2
  87. package/esm/components/Chat/Chat.css +37 -3
  88. package/esm/components/Chat/Chat.js +61 -23
  89. package/esm/components/Chat/Chat.js.map +1 -1
  90. package/esm/components/ChatBubble/ChatBubble.css +87 -15
  91. package/esm/components/ChatBubble/ChatBubble.js +130 -20
  92. package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
  93. package/esm/components/ChatHistoryDrawer/ChatHistory.css +5 -1
  94. package/esm/components/ChatInputs/ChatInputs.css +293 -17
  95. package/esm/components/ChatInputs/ChatInputs.d.ts +1 -0
  96. package/esm/components/ChatInputs/ChatInputs.js +49 -28
  97. package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
  98. package/esm/components/ChatTextArea/ChatTextArea.css +75 -31
  99. package/esm/components/ChatTextArea/ChatTextArea.js +49 -20
  100. package/esm/components/ChatTextArea/ChatTextArea.js.map +1 -1
  101. package/esm/components/DateSelector/DateSelector.css +125 -104
  102. package/esm/components/DateSelector/DateSelector.d.ts +1 -1
  103. package/esm/components/DateSelector/DateSelector.js +111 -52
  104. package/esm/components/DateSelector/DateSelector.js.map +1 -1
  105. package/esm/components/FilePreview/FilePreview.css +225 -146
  106. package/esm/components/FilePreview/FilePreview.d.ts +1 -2
  107. package/esm/components/FilePreview/FilePreview.js +21 -7
  108. package/esm/components/FilePreview/FilePreview.js.map +1 -1
  109. package/esm/components/Header/Header.css +2 -2
  110. package/esm/components/Header/Header.js +1 -1
  111. package/esm/components/Header/Header.js.map +1 -1
  112. package/esm/components/LoginDrawer/LoginDrawer.css +37 -5
  113. package/esm/components/LoginDrawer/LoginDrawer.d.ts +1 -2
  114. package/esm/components/LoginDrawer/LoginDrawer.js +2 -9
  115. package/esm/components/LoginDrawer/LoginDrawer.js.map +1 -1
  116. package/esm/components/MediaWidget/MediaItemWidget.js +2 -1
  117. package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
  118. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js +1 -1
  119. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js.map +1 -1
  120. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js +1 -1
  121. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js.map +1 -1
  122. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js +3 -0
  123. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js.map +1 -1
  124. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +2 -2
  125. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
  126. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +16 -7
  127. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +6 -4
  128. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -1
  129. package/esm/components/MemoriWidget/MemoriWidget.css +11 -2
  130. package/esm/components/MemoriWidget/MemoriWidget.js +105 -25
  131. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  132. package/esm/components/MicrophoneButton/MicrophoneButton.css +2 -2
  133. package/esm/components/StartPanel/StartPanel.css +8 -0
  134. package/esm/components/UploadButton/UploadButton.css +20 -17
  135. package/esm/components/UploadButton/UploadButton.js +219 -88
  136. package/esm/components/UploadButton/UploadButton.js.map +1 -1
  137. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +14 -4
  138. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  139. package/esm/components/UploadButton/UploadImages/UploadImages.js +143 -16
  140. package/esm/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  141. package/esm/components/layouts/chat.css +1 -1
  142. package/esm/components/ui/Drawer.css +8 -0
  143. package/esm/components/ui/Drawer.d.ts +2 -0
  144. package/esm/components/ui/Drawer.js +2 -2
  145. package/esm/components/ui/Drawer.js.map +1 -1
  146. package/esm/components/ui/Tooltip.css +49 -1
  147. package/esm/components/ui/Tooltip.d.ts +1 -1
  148. package/esm/helpers/constants.d.ts +1 -0
  149. package/esm/helpers/constants.js +1 -0
  150. package/esm/helpers/constants.js.map +1 -1
  151. package/esm/helpers/imageCompression.d.ts +7 -0
  152. package/esm/helpers/imageCompression.js +119 -0
  153. package/esm/helpers/imageCompression.js.map +1 -0
  154. package/esm/locales/de.json +13 -5
  155. package/esm/locales/en.json +17 -6
  156. package/esm/locales/es.json +13 -5
  157. package/esm/locales/fr.json +12 -5
  158. package/esm/locales/it.json +16 -6
  159. package/esm/styles.css +4 -4
  160. package/package.json +2 -2
  161. package/src/components/AgeVerificationModal/AgeVerificationModal.css +41 -14
  162. package/src/components/AgeVerificationModal/AgeVerificationModal.tsx +3 -1
  163. package/src/components/Auth/Auth.tsx +55 -11
  164. package/src/components/Avatar/Avatar.stories.tsx +3 -0
  165. package/src/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +2 -2
  166. package/src/components/Chat/Chat.css +37 -3
  167. package/src/components/Chat/Chat.stories.tsx +16 -2
  168. package/src/components/Chat/Chat.tsx +90 -21
  169. package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +1752 -812
  170. package/src/components/ChatBubble/ChatBubble.css +87 -15
  171. package/src/components/ChatBubble/ChatBubble.stories.tsx +16 -2
  172. package/src/components/ChatBubble/ChatBubble.test.tsx +17 -0
  173. package/src/components/ChatBubble/ChatBubble.tsx +237 -33
  174. package/src/components/ChatBubble/__snapshots__/ChatBubble.test.tsx.snap +304 -8
  175. package/src/components/ChatHistoryDrawer/ChatHistory.css +5 -1
  176. package/src/components/ChatInputs/ChatInputs.css +293 -17
  177. package/src/components/ChatInputs/ChatInputs.tsx +156 -86
  178. package/src/components/ChatInputs/__snapshots__/ChatInputs.test.tsx.snap +430 -424
  179. package/src/components/ChatTextArea/ChatTextArea.css +75 -31
  180. package/src/components/ChatTextArea/ChatTextArea.test.tsx +1 -16
  181. package/src/components/ChatTextArea/ChatTextArea.tsx +51 -22
  182. package/src/components/ChatTextArea/__snapshots__/ChatTextArea.test.tsx.snap +9 -72
  183. package/src/components/DateSelector/DateSelector.css +125 -104
  184. package/src/components/DateSelector/DateSelector.stories.tsx +1 -1
  185. package/src/components/DateSelector/DateSelector.test.tsx +137 -23
  186. package/src/components/DateSelector/DateSelector.tsx +203 -177
  187. package/src/components/FilePreview/FilePreview.css +225 -146
  188. package/src/components/FilePreview/FilePreview.tsx +49 -36
  189. package/src/components/FilePreview/__snapshots__/FilePreview.test.tsx.snap +2 -2
  190. package/src/components/Header/Header.css +2 -2
  191. package/src/components/Header/Header.stories.tsx +5 -1
  192. package/src/components/Header/Header.tsx +1 -1
  193. package/src/components/Header/__snapshots__/Header.test.tsx.snap +1 -1
  194. package/src/components/LoginDrawer/LoginDrawer.css +37 -5
  195. package/src/components/LoginDrawer/LoginDrawer.stories.tsx +0 -1
  196. package/src/components/LoginDrawer/LoginDrawer.test.tsx +0 -1
  197. package/src/components/LoginDrawer/LoginDrawer.tsx +0 -19
  198. package/src/components/MediaWidget/MediaItemWidget.tsx +2 -1
  199. package/src/components/MemoriArtifactSystem/ArtifactDrawer.stories.tsx +996 -204
  200. package/src/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.tsx +2 -2
  201. package/src/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.tsx +1 -1
  202. package/src/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.tsx +3 -0
  203. package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.tsx +56 -54
  204. package/src/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +16 -7
  205. package/src/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.tsx +12 -3
  206. package/src/components/MemoriWidget/MemoriWidget.css +11 -2
  207. package/src/components/MemoriWidget/MemoriWidget.stories.tsx +6 -3
  208. package/src/components/MemoriWidget/MemoriWidget.tsx +173 -49
  209. package/src/components/MicrophoneButton/MicrophoneButton.css +2 -2
  210. package/src/components/StartPanel/StartPanel.css +8 -0
  211. package/src/components/UploadButton/UploadButton.css +20 -17
  212. package/src/components/UploadButton/UploadButton.stories.tsx +247 -35
  213. package/src/components/UploadButton/UploadButton.tsx +280 -173
  214. package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +19 -4
  215. package/src/components/UploadButton/UploadImages/UploadImages.tsx +196 -35
  216. package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +10 -1
  217. package/src/components/layouts/FullBody/FullBody.stories.tsx +9 -10
  218. package/src/components/layouts/Totem/Totem.stories.tsx +8 -9
  219. package/src/components/layouts/ZoomedFullBody/ZoomedFullBody.stories.tsx +8 -9
  220. package/src/components/layouts/chat.css +1 -1
  221. package/src/components/layouts/layouts.stories.tsx +10 -9
  222. package/src/components/ui/Drawer.css +8 -0
  223. package/src/components/ui/Drawer.tsx +16 -12
  224. package/src/components/ui/Tooltip.css +49 -1
  225. package/src/components/ui/Tooltip.tsx +1 -1
  226. package/src/helpers/constants.ts +1 -1
  227. package/src/helpers/imageCompression.ts +230 -0
  228. package/src/index.stories.tsx +18 -0
  229. package/src/locales/de.json +13 -5
  230. package/src/locales/en.json +17 -6
  231. package/src/locales/es.json +13 -5
  232. package/src/locales/fr.json +12 -5
  233. package/src/locales/it.json +16 -6
  234. package/src/mocks/data.ts +4 -2
  235. package/src/styles.css +4 -4
  236. package/src/components/SignupForm/SignupForm.test.tsx +0 -40
  237. package/src/components/SignupForm/SignupForm.tsx +0 -457
  238. package/src/components/SignupForm/__snapshots__/SignupForm.test.tsx.snap +0 -247
  239. package/src/components/UploadMenu/UploadMenu.css +0 -47
  240. package/src/components/UploadMenu/UploadMenu.stories.tsx +0 -66
  241. package/src/components/UploadMenu/UploadMenu.test.tsx +0 -34
  242. package/src/components/UploadMenu/UploadMenu.tsx +0 -68
  243. package/src/components/UploadMenu/__snapshots__/UploadMenu.test.tsx.snap +0 -137
@@ -1,200 +1,226 @@
1
- import { useEffect, useState, memo, Fragment } from 'react';
2
- import { Listbox, Transition } from '@headlessui/react';
1
+ import { useEffect, useState, memo, useMemo, useRef, ChangeEvent } from 'react';
3
2
  import { DateTime } from 'luxon';
4
3
  import { useTranslation } from 'react-i18next';
5
- import SelectIcon from '../icons/SelectIcon';
6
4
 
7
5
  export interface Props {
8
6
  defaultDate?: string | Date;
9
7
  disabled?: boolean;
10
- onChange: (date: DateTime) => void;
8
+ onChange: (date: DateTime | undefined) => void;
11
9
  }
12
10
 
13
- const months = {
14
- en: [
15
- 'January',
16
- 'February',
17
- 'March',
18
- 'April',
19
- 'May',
20
- 'June',
21
- 'July',
22
- 'August',
23
- 'September',
24
- 'October',
25
- 'November',
26
- 'December',
27
- ],
28
- it: [
29
- 'Gennaio',
30
- 'Febbraio',
31
- 'Marzo',
32
- 'Aprile',
33
- 'Maggio',
34
- 'Giugno',
35
- 'Luglio',
36
- 'Agosto',
37
- 'Settembre',
38
- 'Ottobre',
39
- 'Novembre',
40
- 'Dicembre',
41
- ],
42
- };
43
-
44
11
  const DateSelector = memo(
45
12
  ({ defaultDate, onChange, disabled = false }: Props) => {
46
- const { t, i18n } = useTranslation();
47
-
48
- const [date, setDate] = useState(
49
- !defaultDate
50
- ? DateTime.now()
51
- : typeof defaultDate === 'string'
52
- ? DateTime.fromISO(defaultDate)
53
- : DateTime.fromJSDate(defaultDate)
54
- );
13
+ const { t } = useTranslation();
14
+
15
+ // Calculate constraints for birth date (18 years ago to 1900)
16
+ const maxDate = useMemo(() => DateTime.now().minus({ years: 18 }), []);
17
+ const minDate = useMemo(() => DateTime.fromObject({ year: 1900, month: 1, day: 1 }), []);
18
+
19
+ // State for individual fields as strings to allow empty values
20
+ const [day, setDay] = useState<string>('');
21
+ const [month, setMonth] = useState<string>('');
22
+ const [year, setYear] = useState<string>('');
23
+
24
+ // Initialize from defaultDate if provided
55
25
  useEffect(() => {
56
- onChange(date);
57
- }, [date, onChange]);
26
+ if (defaultDate) {
27
+ const dt = typeof defaultDate === 'string'
28
+ ? DateTime.fromISO(defaultDate)
29
+ : DateTime.fromJSDate(defaultDate);
30
+
31
+ if (dt.isValid) {
32
+ setDay(dt.day.toString());
33
+ setMonth(dt.month.toString());
34
+ setYear(dt.year.toString());
35
+ }
36
+ }
37
+ }, [defaultDate]);
38
+
39
+ const [isMobile, setIsMobile] = useState(false);
40
+
41
+ // Refs for auto-focus
42
+ const dayRef = useRef<HTMLInputElement>(null);
43
+ const monthRef = useRef<HTMLInputElement>(null);
44
+ const yearRef = useRef<HTMLInputElement>(null);
45
+
46
+ // Detect mobile viewport
47
+ useEffect(() => {
48
+ const checkMobile = () => {
49
+ setIsMobile(window.innerWidth < 768);
50
+ };
51
+
52
+ checkMobile();
53
+ window.addEventListener('resize', checkMobile);
54
+ return () => window.removeEventListener('resize', checkMobile);
55
+ }, []);
56
+
57
+ // Validate and propagate changes
58
+ useEffect(() => {
59
+ if (!day || !month || !year) {
60
+ onChange(undefined);
61
+ return;
62
+ }
63
+
64
+ const d = parseInt(day);
65
+ const m = parseInt(month);
66
+ const y = parseInt(year);
67
+
68
+ if (isNaN(d) || isNaN(m) || isNaN(y)) {
69
+ onChange(undefined);
70
+ return;
71
+ }
72
+
73
+ const newDate = DateTime.fromObject({ year: y, month: m, day: d });
74
+
75
+ // Basic validation: check if it's a valid date (e.g. not Feb 30)
76
+ // and within range.
77
+ if (newDate.isValid && newDate >= minDate && newDate <= maxDate) {
78
+ onChange(newDate);
79
+ } else {
80
+ onChange(undefined);
81
+ }
82
+ }, [day, month, year, onChange, minDate, maxDate]);
83
+
84
+ // Handle mobile native input change
85
+ const handleMobileChange = (e: ChangeEvent<HTMLInputElement>) => {
86
+ const value = e.target.value;
87
+ if (value) {
88
+ const newDate = DateTime.fromISO(value);
89
+ if (newDate.isValid) {
90
+ setDay(newDate.day.toString());
91
+ setMonth(newDate.month.toString());
92
+ setYear(newDate.year.toString());
93
+ // The useEffect will handle calling onChange
94
+ }
95
+ } else {
96
+ setDay('');
97
+ setMonth('');
98
+ setYear('');
99
+ }
100
+ };
101
+
102
+ const handleDayChange = (e: ChangeEvent<HTMLInputElement>) => {
103
+ const val = e.target.value;
104
+ // Allow empty or numbers only
105
+ if (val === '' || /^\d+$/.test(val)) {
106
+ // Limit length to 2
107
+ if (val.length > 2) return;
108
+
109
+ // Limit value to 31
110
+ const numVal = parseInt(val);
111
+ if (numVal > 31) return;
112
+
113
+ setDay(val);
114
+ if (val.length >= 2) {
115
+ monthRef.current?.focus();
116
+ }
117
+ }
118
+ };
119
+
120
+ const handleMonthChange = (e: ChangeEvent<HTMLInputElement>) => {
121
+ const val = e.target.value;
122
+ if (val === '' || /^\d+$/.test(val)) {
123
+ // Limit length to 2
124
+ if (val.length > 2) return;
125
+
126
+ // Limit value to 12
127
+ const numVal = parseInt(val);
128
+ if (numVal > 12) return;
129
+
130
+ setMonth(val);
131
+ if (val.length >= 2) {
132
+ yearRef.current?.focus();
133
+ }
134
+ }
135
+ };
136
+
137
+ const handleYearChange = (e: ChangeEvent<HTMLInputElement>) => {
138
+ const val = e.target.value;
139
+ if (val === '' || /^\d+$/.test(val)) {
140
+ // Limit length to 4
141
+ if (val.length > 4) return;
142
+
143
+ setYear(val);
144
+ }
145
+ };
146
+
147
+ // Mobile native input
148
+ if (isMobile) {
149
+ const currentDate = (day && month && year)
150
+ ? DateTime.fromObject({ year: parseInt(year), month: parseInt(month), day: parseInt(day) })
151
+ : null;
152
+
153
+ return (
154
+ <div className="memori--date-selector memori--date-selector--mobile">
155
+ <label className="memori--date-selector__mobile-label">
156
+ {t('birthDate') || 'Birth Date'}:
157
+ </label>
158
+ <input
159
+ type="date"
160
+ className="memori--date-selector__mobile-input"
161
+ value={currentDate?.isValid ? currentDate.toISODate() || '' : ''}
162
+ onChange={handleMobileChange}
163
+ disabled={disabled}
164
+ min={minDate.toISODate() || '1900-01-01'}
165
+ max={maxDate.toISODate() || ''}
166
+ aria-label={String(t('dateOfBirth') || t('date'))}
167
+ />
168
+ </div>
169
+ );
170
+ }
58
171
 
172
+ // Desktop simple inputs
59
173
  return (
60
- <div className="memori--date-selector">
61
- <div className="memori--date-selector__select">
62
- <Listbox
63
- value={date}
64
- onChange={value => {
65
- setDate(value);
66
- }}
174
+ <div className="memori--date-selector memori--date-selector--desktop">
175
+ <div className="memori--date-selector__input-group">
176
+ <label className="memori--date-selector__label">
177
+ {t('day') || 'Day'}
178
+ </label>
179
+ <input
180
+ ref={dayRef}
181
+ type="number"
182
+ className="memori--date-selector__input"
183
+ value={day}
184
+ onChange={handleDayChange}
185
+ placeholder={t('dayPlaceholder') || 'DD'}
186
+ min={1}
187
+ max={31}
67
188
  disabled={disabled}
68
- name="day"
69
- >
70
- <Listbox.Label className="memori--date-selector__select-label">
71
- {t('day')}:
72
- </Listbox.Label>
73
- <Listbox.Button
74
- aria-label={t('day')}
75
- className="memori--date-selector__select-button"
76
- >
77
- <span className="memori--date-selector__select--value">
78
- {date.day}
79
- </span>
80
- <span className="memori--date-selector__select--icon">
81
- <SelectIcon />
82
- </span>
83
- </Listbox.Button>
84
- <Transition
85
- as={Fragment}
86
- leave="transition ease-in duration-100"
87
- leaveFrom="opacity-100"
88
- leaveTo="opacity-0"
89
- >
90
- <Listbox.Options className="memori--date-selector__select-options">
91
- {[...Array(31).keys()].map(day => (
92
- <Listbox.Option
93
- key={day}
94
- value={date.set({ day: day + 1 })}
95
- className="memori--date-selector__select-option"
96
- >
97
- {day + 1}
98
- </Listbox.Option>
99
- ))}
100
- </Listbox.Options>
101
- </Transition>
102
- </Listbox>
189
+ />
103
190
  </div>
104
191
 
105
- <div className="memori--date-selector__select">
106
- <Listbox
107
- value={date}
108
- onChange={value => {
109
- setDate(value);
110
- }}
192
+ <div className="memori--date-selector__input-group">
193
+ <label className="memori--date-selector__label">
194
+ {t('month') || 'Month'}
195
+ </label>
196
+ <input
197
+ ref={monthRef}
198
+ type="number"
199
+ className="memori--date-selector__input"
200
+ value={month}
201
+ onChange={handleMonthChange}
202
+ placeholder={t('monthPlaceholder') || 'MM'}
203
+ min={1}
204
+ max={12}
111
205
  disabled={disabled}
112
- name="month"
113
- >
114
- <Listbox.Label className="memori--date-selector__select-label">
115
- {t('month')}:
116
- </Listbox.Label>
117
- <Listbox.Button
118
- aria-label={t('month')}
119
- className="memori--date-selector__select-button"
120
- >
121
- <span className="memori--date-selector__select--value">
122
- {months[i18n.language === 'it' ? 'it' : 'en'][date.month - 1]}
123
- </span>
124
- <span className="memori--date-selector__select--icon">
125
- <SelectIcon />
126
- </span>
127
- </Listbox.Button>
128
- <Transition
129
- as={Fragment}
130
- leave="transition ease-in duration-100"
131
- leaveFrom="opacity-100"
132
- leaveTo="opacity-0"
133
- >
134
- <Listbox.Options className="memori--date-selector__select-options">
135
- {months[i18n.language === 'it' ? 'it' : 'en'].map(month => (
136
- <Listbox.Option
137
- key={month}
138
- className="memori--date-selector__select-option"
139
- value={date.set({
140
- month:
141
- months[i18n.language === 'it' ? 'it' : 'en'].findIndex(
142
- m => m === month
143
- ) + 1,
144
- })}
145
- >
146
- {month}
147
- </Listbox.Option>
148
- ))}
149
- </Listbox.Options>
150
- </Transition>
151
- </Listbox>
206
+ />
152
207
  </div>
153
208
 
154
- <div className="memori--date-selector__select">
155
- <Listbox
156
- value={date}
157
- onChange={value => {
158
- setDate(value);
159
- }}
209
+ <div className="memori--date-selector__input-group memori--date-selector__input-group--year">
210
+ <label className="memori--date-selector__label">
211
+ {t('year') || 'Year'}
212
+ </label>
213
+ <input
214
+ ref={yearRef}
215
+ type="number"
216
+ className="memori--date-selector__input"
217
+ value={year}
218
+ onChange={handleYearChange}
219
+ placeholder={t('yearPlaceholder') || 'YYYY'}
220
+ min={minDate.year}
221
+ max={maxDate.year}
160
222
  disabled={disabled}
161
- name="year"
162
- >
163
- <Listbox.Label className="memori--date-selector__select-label">
164
- {t('year')}:
165
- </Listbox.Label>
166
- <Listbox.Button
167
- aria-label={t('year')}
168
- className="memori--date-selector__select-button"
169
- >
170
- <span className="memori--date-selector__select--value">
171
- {date.year}
172
- </span>
173
- <span className="memori--date-selector__select--icon">
174
- <SelectIcon />
175
- </span>
176
- </Listbox.Button>
177
- <Transition
178
- as={Fragment}
179
- leave="transition ease-in duration-100"
180
- leaveFrom="opacity-100"
181
- leaveTo="opacity-0"
182
- >
183
- <Listbox.Options className="memori--date-selector__select-options">
184
- {[...Array(DateTime.now().year - 1899).keys()]
185
- .sort((a, b) => b - a)
186
- .map(year => (
187
- <Listbox.Option
188
- key={year}
189
- value={date.set({ year: year + 1900 })}
190
- className="memori--date-selector__select-option"
191
- >
192
- {year + 1900}
193
- </Listbox.Option>
194
- ))}
195
- </Listbox.Options>
196
- </Transition>
197
- </Listbox>
223
+ />
198
224
  </div>
199
225
  </div>
200
226
  );