@memori.ai/memori-react 8.10.1 → 8.12.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 (177) hide show
  1. package/CHANGELOG.md +66 -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.js +2 -2
  9. package/dist/components/Chat/Chat.js.map +1 -1
  10. package/dist/components/ChatBubble/ChatBubble.css +81 -13
  11. package/dist/components/ChatBubble/ChatBubble.js +86 -19
  12. package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
  13. package/dist/components/ChatHistoryDrawer/ChatHistory.css +5 -1
  14. package/dist/components/ChatInputs/ChatInputs.d.ts +1 -0
  15. package/dist/components/ChatInputs/ChatInputs.js +8 -3
  16. package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
  17. package/dist/components/DateSelector/DateSelector.css +125 -104
  18. package/dist/components/DateSelector/DateSelector.d.ts +1 -1
  19. package/dist/components/DateSelector/DateSelector.js +110 -52
  20. package/dist/components/DateSelector/DateSelector.js.map +1 -1
  21. package/dist/components/Header/Header.js +1 -1
  22. package/dist/components/Header/Header.js.map +1 -1
  23. package/dist/components/LoginDrawer/LoginDrawer.css +37 -5
  24. package/dist/components/LoginDrawer/LoginDrawer.d.ts +1 -2
  25. package/dist/components/LoginDrawer/LoginDrawer.js +2 -9
  26. package/dist/components/LoginDrawer/LoginDrawer.js.map +1 -1
  27. package/dist/components/MediaWidget/MediaItemWidget.js +40 -5
  28. package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
  29. package/dist/components/MediaWidget/MediaWidget.css +4 -0
  30. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js +1 -1
  31. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js.map +1 -1
  32. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js +1 -1
  33. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js.map +1 -1
  34. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js +3 -0
  35. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js.map +1 -1
  36. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +2 -2
  37. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
  38. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +16 -7
  39. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +6 -4
  40. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -1
  41. package/dist/components/MemoriWidget/MemoriWidget.js +69 -25
  42. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  43. package/dist/components/UploadButton/UploadButton.js +2 -0
  44. package/dist/components/UploadButton/UploadButton.js.map +1 -1
  45. package/dist/components/UploadButton/UploadImages/UploadImages.js +2 -2
  46. package/dist/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  47. package/dist/components/ui/Drawer.css +8 -0
  48. package/dist/components/ui/Drawer.d.ts +2 -0
  49. package/dist/components/ui/Drawer.js +2 -2
  50. package/dist/components/ui/Drawer.js.map +1 -1
  51. package/dist/components/ui/Tooltip.css +49 -1
  52. package/dist/components/ui/Tooltip.d.ts +1 -1
  53. package/dist/locales/de.json +6 -1
  54. package/dist/locales/en.json +9 -1
  55. package/dist/locales/es.json +6 -1
  56. package/dist/locales/fr.json +5 -1
  57. package/dist/locales/it.json +8 -1
  58. package/dist/styles.css +3 -2
  59. package/esm/components/AgeVerificationModal/AgeVerificationModal.css +41 -14
  60. package/esm/components/AgeVerificationModal/AgeVerificationModal.js +2 -2
  61. package/esm/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
  62. package/esm/components/Auth/Auth.js +36 -8
  63. package/esm/components/Auth/Auth.js.map +1 -1
  64. package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +2 -2
  65. package/esm/components/Chat/Chat.js +2 -2
  66. package/esm/components/Chat/Chat.js.map +1 -1
  67. package/esm/components/ChatBubble/ChatBubble.css +81 -13
  68. package/esm/components/ChatBubble/ChatBubble.js +87 -20
  69. package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
  70. package/esm/components/ChatHistoryDrawer/ChatHistory.css +5 -1
  71. package/esm/components/ChatInputs/ChatInputs.d.ts +1 -0
  72. package/esm/components/ChatInputs/ChatInputs.js +8 -3
  73. package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
  74. package/esm/components/DateSelector/DateSelector.css +125 -104
  75. package/esm/components/DateSelector/DateSelector.d.ts +1 -1
  76. package/esm/components/DateSelector/DateSelector.js +111 -52
  77. package/esm/components/DateSelector/DateSelector.js.map +1 -1
  78. package/esm/components/Header/Header.js +1 -1
  79. package/esm/components/Header/Header.js.map +1 -1
  80. package/esm/components/LoginDrawer/LoginDrawer.css +37 -5
  81. package/esm/components/LoginDrawer/LoginDrawer.d.ts +1 -2
  82. package/esm/components/LoginDrawer/LoginDrawer.js +2 -9
  83. package/esm/components/LoginDrawer/LoginDrawer.js.map +1 -1
  84. package/esm/components/MediaWidget/MediaItemWidget.js +40 -5
  85. package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
  86. package/esm/components/MediaWidget/MediaWidget.css +4 -0
  87. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js +1 -1
  88. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js.map +1 -1
  89. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js +1 -1
  90. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js.map +1 -1
  91. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js +3 -0
  92. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js.map +1 -1
  93. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +2 -2
  94. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
  95. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +16 -7
  96. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +6 -4
  97. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -1
  98. package/esm/components/MemoriWidget/MemoriWidget.js +69 -25
  99. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  100. package/esm/components/UploadButton/UploadButton.js +2 -0
  101. package/esm/components/UploadButton/UploadButton.js.map +1 -1
  102. package/esm/components/UploadButton/UploadImages/UploadImages.js +2 -2
  103. package/esm/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  104. package/esm/components/ui/Drawer.css +8 -0
  105. package/esm/components/ui/Drawer.d.ts +2 -0
  106. package/esm/components/ui/Drawer.js +2 -2
  107. package/esm/components/ui/Drawer.js.map +1 -1
  108. package/esm/components/ui/Tooltip.css +49 -1
  109. package/esm/components/ui/Tooltip.d.ts +1 -1
  110. package/esm/locales/de.json +6 -1
  111. package/esm/locales/en.json +9 -1
  112. package/esm/locales/es.json +6 -1
  113. package/esm/locales/fr.json +5 -1
  114. package/esm/locales/it.json +8 -1
  115. package/esm/styles.css +3 -2
  116. package/package.json +2 -2
  117. package/src/components/AgeVerificationModal/AgeVerificationModal.css +41 -14
  118. package/src/components/AgeVerificationModal/AgeVerificationModal.tsx +3 -1
  119. package/src/components/Auth/Auth.tsx +55 -11
  120. package/src/components/Avatar/Avatar.stories.tsx +3 -0
  121. package/src/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +2 -2
  122. package/src/components/Chat/Chat.stories.tsx +16 -2
  123. package/src/components/Chat/Chat.tsx +2 -1
  124. package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +1036 -36
  125. package/src/components/ChatBubble/ChatBubble.css +81 -13
  126. package/src/components/ChatBubble/ChatBubble.stories.tsx +16 -2
  127. package/src/components/ChatBubble/ChatBubble.test.tsx +17 -0
  128. package/src/components/ChatBubble/ChatBubble.tsx +144 -31
  129. package/src/components/ChatBubble/__snapshots__/ChatBubble.test.tsx.snap +304 -8
  130. package/src/components/ChatHistoryDrawer/ChatHistory.css +5 -1
  131. package/src/components/ChatInputs/ChatInputs.tsx +14 -1
  132. package/src/components/DateSelector/DateSelector.css +125 -104
  133. package/src/components/DateSelector/DateSelector.stories.tsx +1 -1
  134. package/src/components/DateSelector/DateSelector.test.tsx +137 -23
  135. package/src/components/DateSelector/DateSelector.tsx +203 -177
  136. package/src/components/Header/Header.stories.tsx +5 -1
  137. package/src/components/Header/Header.tsx +1 -1
  138. package/src/components/Header/__snapshots__/Header.test.tsx.snap +1 -1
  139. package/src/components/LoginDrawer/LoginDrawer.css +37 -5
  140. package/src/components/LoginDrawer/LoginDrawer.stories.tsx +0 -1
  141. package/src/components/LoginDrawer/LoginDrawer.test.tsx +0 -1
  142. package/src/components/LoginDrawer/LoginDrawer.tsx +0 -19
  143. package/src/components/MediaWidget/MediaItemWidget.stories.tsx +69 -0
  144. package/src/components/MediaWidget/MediaItemWidget.tsx +66 -18
  145. package/src/components/MediaWidget/MediaWidget.css +4 -0
  146. package/src/components/MediaWidget/__snapshots__/MediaItemWidget.test.tsx.snap +10 -10
  147. package/src/components/MediaWidget/__snapshots__/MediaWidget.test.tsx.snap +2 -2
  148. package/src/components/MemoriArtifactSystem/ArtifactDrawer.stories.tsx +996 -204
  149. package/src/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.tsx +2 -2
  150. package/src/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.tsx +1 -1
  151. package/src/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.tsx +3 -0
  152. package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.tsx +56 -54
  153. package/src/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +16 -7
  154. package/src/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.tsx +12 -3
  155. package/src/components/MemoriWidget/MemoriWidget.stories.tsx +6 -3
  156. package/src/components/MemoriWidget/MemoriWidget.tsx +123 -48
  157. package/src/components/UploadButton/UploadButton.tsx +2 -0
  158. package/src/components/UploadButton/UploadImages/UploadImages.tsx +3 -2
  159. package/src/components/layouts/FullBody/FullBody.stories.tsx +110 -0
  160. package/src/components/layouts/Totem/Totem.stories.tsx +131 -0
  161. package/src/components/layouts/ZoomedFullBody/ZoomedFullBody.stories.tsx +131 -0
  162. package/src/components/layouts/layouts.stories.tsx +55 -508
  163. package/src/components/ui/Drawer.css +8 -0
  164. package/src/components/ui/Drawer.tsx +16 -12
  165. package/src/components/ui/Tooltip.css +49 -1
  166. package/src/components/ui/Tooltip.tsx +1 -1
  167. package/src/index.stories.tsx +13 -320
  168. package/src/locales/de.json +6 -1
  169. package/src/locales/en.json +9 -1
  170. package/src/locales/es.json +6 -1
  171. package/src/locales/fr.json +5 -1
  172. package/src/locales/it.json +8 -1
  173. package/src/mocks/data.ts +4 -2
  174. package/src/styles.css +3 -2
  175. package/src/components/SignupForm/SignupForm.test.tsx +0 -40
  176. package/src/components/SignupForm/SignupForm.tsx +0 -457
  177. package/src/components/SignupForm/__snapshots__/SignupForm.test.tsx.snap +0 -247
@@ -1,137 +1,158 @@
1
+ /* Screen reader only - visually hidden but accessible */
2
+ .sr-only {
3
+ position: absolute;
4
+ overflow: hidden;
5
+ width: 1px;
6
+ height: 1px;
7
+ padding: 0;
8
+ border-width: 0;
9
+ margin: -1px;
10
+ clip: rect(0, 0, 0, 0);
11
+ white-space: nowrap;
12
+ }
13
+
14
+ /* Base Container */
1
15
  .memori--date-selector {
2
- display: flex;
3
- flex-wrap: nowrap;
16
+ width: 100%;
17
+ /* margin-top: 1.5rem; */
4
18
  }
5
19
 
6
- .memori--date-selector__select {
7
- width: 30%;
20
+ /* Mobile Styles */
21
+ .memori--date-selector--mobile {
22
+ display: flex;
23
+ width: 100%;
8
24
  max-width: 100%;
9
- margin: 1.5rem 1.5% 0;
25
+ box-sizing: border-box;
26
+ flex-direction: column;
27
+ padding: 0;
28
+ margin: 1rem 0;
10
29
  }
11
30
 
12
- .memori--date-selector__select-button {
13
- position: relative;
31
+ .memori--date-selector__mobile-label {
32
+ display: block;
14
33
  width: 100%;
15
- padding-top: 0.5rem;
16
- padding-right: 2.5rem;
17
- padding-bottom: 0.5rem;
18
- padding-left: 0.75rem;
19
- border: 1px solid #e5e7eb;
20
- border-radius: 0.5rem;
21
- background: #fff;
22
- box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 4px 6px -1px,
23
- rgba(0, 0, 0, 0.1) 0px 2px 4px -2px;
24
- cursor: pointer;
34
+ margin-bottom: 0.5rem;
35
+ color: #374151;
36
+ font-size: 0.95rem;
37
+ font-weight: 500;
25
38
  text-align: left;
26
39
  }
27
40
 
28
- .memori--date-selector__select-button:focus {
29
- border-color: #cbd5e0;
30
- box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
31
- }
32
-
33
- .memori--date-selector__select-button:focus-visible {
34
- border-color: #63b3ed;
35
- box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
41
+ .memori--date-selector__mobile-input {
42
+ width: 100%;
43
+ max-width: 100%;
44
+ min-height: 48px;
45
+ box-sizing: border-box;
46
+ padding: 0.875rem 1rem;
47
+ border: 1px solid #e5e7eb;
48
+ border-radius: 0.5rem;
49
+ -webkit-appearance: none;
50
+ appearance: none;
51
+ background: #ffffff;
52
+ /* Touch-friendly */
53
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
54
+ color: #1f2937;
55
+ font-size: 1rem;
56
+ transition: all 0.2s ease;
36
57
  }
37
58
 
38
- .memori--date-selector__select-button:hover {
39
- border-color: #e2e8f0;
59
+ .memori--date-selector__mobile-input:focus {
60
+ border-color: var(--memori-primary, #9333ea);
61
+ box-shadow: 0 0 0 3px rgba(147, 51, 234, 0.1);
62
+ outline: none;
40
63
  }
41
64
 
42
- .memori--date-selector__select-button:active {
43
- border-color: #e2e8f0;
65
+ .memori--date-selector__mobile-input:active {
66
+ border-color: var(--memori-primary, #9333ea);
44
67
  }
45
68
 
46
- .memori--date-selector__select-button:disabled {
47
- border-color: #e2e8f0;
48
- background-color: #f7fafc;
49
- color: #a0aec0;
69
+ .memori--date-selector__mobile-input:disabled {
70
+ background-color: #f9fafb;
71
+ color: #9ca3af;
50
72
  cursor: not-allowed;
73
+ opacity: 0.6;
51
74
  }
52
75
 
53
- @media (min-width: 640px) {
54
- .memori--date-selector__select-button {
55
- font-size: 0.875rem;
56
- line-height: 1.25rem;
57
- }
58
- }
59
-
60
- .memori--date-selector__select-label {
61
- display: inline-block;
62
- margin-bottom: 0.25rem;
76
+ /* Desktop Styles */
77
+ .memori--date-selector--desktop {
78
+ display: flex;
79
+ flex-wrap: wrap;
80
+ justify-content: center;
81
+ gap: 1rem;
63
82
  }
64
83
 
65
- .memori--date-selector__select--value {
66
- display: block;
67
- overflow: hidden;
68
- text-overflow: ellipsis;
69
- white-space: nowrap;
84
+ .memori--date-selector__input-group {
85
+ display: flex;
86
+ min-width: 80px;
87
+ /* flex: 1; */
88
+ flex-direction: column;
70
89
  }
71
90
 
72
- .memori--date-selector__select--icon {
73
- position: absolute;
74
- top: 0;
75
- right: 0;
76
- bottom: 0;
77
- display: flex;
78
- align-items: center;
79
- padding-right: 0.5rem;
80
- pointer-events: none;
91
+ .memori--date-selector__input-group--year {
92
+ min-width: 100px;
81
93
  }
82
94
 
83
- .memori--date-selector__select--icon svg {
84
- width: 1.25rem;
85
- height: 1.25rem;
86
- color: rgb(156 163 175/1);
95
+ .memori--date-selector__label {
96
+ display: inline-block;
97
+ margin-bottom: 0.5rem;
98
+ color: #4b5563;
99
+ font-size: 0.875rem;
100
+ font-weight: 500;
101
+ letter-spacing: 0.01em;
87
102
  }
88
103
 
89
- ul.memori--date-selector__select-options {
90
- position: absolute;
91
- z-index: 1;
92
- overflow: auto;
104
+ .memori--date-selector__input {
93
105
  width: 100%;
94
- max-width: min(18rem, 30%);
95
- max-height: 15rem;
96
- padding-top: 0.25rem;
97
- padding-right: 0;
98
- padding-bottom: 0.25rem;
99
- padding-left: 0;
100
- border-radius: 0.375rem;
101
- margin-top: 0.25rem;
102
- margin-right: 0;
103
- margin-bottom: 0;
104
- margin-left: 0;
105
- background: #fff;
106
- box-shadow: rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px,
107
- rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.1) 0px 4px 6px -4px;
108
- list-style: none;
109
- }
110
-
111
- @media (min-width: 640px) {
112
- .memori--date-selector__select-options {
113
- font-size: 0.875rem;
114
- line-height: 1.25rem;
115
- }
106
+ padding: 0.75rem 1rem;
107
+ border: 2px solid #e5e7eb;
108
+ border-radius: 0.75rem;
109
+ -moz-appearance: textfield;
110
+ appearance: textfield;
111
+ /* Remove spinner buttons */
112
+ background: #ffffff;
113
+ color: #1f2937;
114
+ font-size: 0.95rem;
115
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
116
+ }
117
+
118
+ .memori--date-selector__input::-webkit-outer-spin-button,
119
+ .memori--date-selector__input::-webkit-inner-spin-button {
120
+ margin: 0;
121
+ -webkit-appearance: none;
122
+ }
123
+
124
+ .memori--date-selector__input:focus {
125
+ border-color: var(--memori-primary);
126
+ box-shadow: 0 0 0 4px rgba(var(--memori-primary-rgb), 0.1);
127
+ outline: none;
128
+ transform: translateY(-1px);
129
+ }
130
+
131
+ .memori--date-selector__input:disabled {
132
+ border-color: #e5e7eb;
133
+ background: #f9fafb;
134
+ color: #9ca3af;
135
+ cursor: not-allowed;
136
+ opacity: 0.6;
116
137
  }
117
138
 
118
- li.memori--date-selector__select-option {
119
- position: relative;
120
- padding-top: 0.5rem;
121
- padding-right: 1rem;
122
- padding-bottom: 0.5rem;
123
- padding-left: 1rem;
124
- color: rgb(17 24 39/1);
125
- cursor: pointer;
126
- user-select: none;
139
+ .memori--date-selector__input::placeholder {
140
+ color: #9ca3af;
127
141
  }
128
142
 
129
- li.memori--date-selector__select-option:hover,
130
- li.memori--date-selector__select-option:focus {
131
- background-color: #f7fafc;
132
- }
143
+ /* Responsive adjustments */
144
+ @media (max-width: 767px) {
145
+ .memori--date-selector--desktop {
146
+ display: none;
147
+ /* Hide desktop version on mobile if both are rendered for some reason */
148
+ }
133
149
 
134
- li.memori--date-selector__select-option:focus {
135
- outline: 2px solid #63b3ed;
136
- outline-offset: 2px;
137
- }
150
+ .memori--date-selector--mobile {
151
+ margin: 0.75rem 0;
152
+ }
153
+
154
+ .memori--date-selector__mobile-input {
155
+ min-height: 44px;
156
+ font-size: 16px; /* Prevents zoom on iOS */
157
+ }
158
+ }
@@ -34,5 +34,5 @@ export const Disabled = Template.bind({});
34
34
  Disabled.args = {
35
35
  defaultDate: new Date(Date.now()),
36
36
  onChange: () => {},
37
- disabled: false,
37
+ disabled: true,
38
38
  };
@@ -1,6 +1,5 @@
1
- import { render } from '@testing-library/react';
1
+ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
2
2
  import DateSelector from './DateSelector';
3
- import { DateTime } from 'luxon';
4
3
 
5
4
  const dateMock = new Date(Date.UTC(2022, 8, 24, 0, 0, 0, 0));
6
5
 
@@ -9,27 +8,142 @@ Date.now = jest.fn(() => dateMock.valueOf());
9
8
 
10
9
  jest.spyOn(Date, 'now').mockImplementation(() => dateMock.valueOf());
11
10
 
12
- it('renders DateSelector unchanged', () => {
13
- const { container } = render(
14
- <DateSelector defaultDate={new Date(Date.now())} onChange={jest.fn()} />
15
- );
16
- expect(container).toMatchSnapshot();
17
- });
11
+ describe('DateSelector', () => {
12
+ const mockOnChange = jest.fn();
18
13
 
19
- it('renders DateSelector with default value unchanged', () => {
20
- const { container } = render(
21
- <DateSelector defaultDate="2023-12-14T08:48:06.977Z" onChange={jest.fn()} />
22
- );
23
- expect(container).toMatchSnapshot();
24
- });
14
+ beforeEach(() => {
15
+ mockOnChange.mockClear();
16
+ });
17
+
18
+ it('renders DateSelector with empty inputs when no defaultDate provided', () => {
19
+ render(<DateSelector onChange={mockOnChange} />);
20
+
21
+ const dayInput = screen.getByLabelText(/day/i);
22
+ const monthInput = screen.getByLabelText(/month/i);
23
+ const yearInput = screen.getByLabelText(/year/i);
24
+
25
+ expect(dayInput).toHaveValue(null); // number input value is null/empty string
26
+ expect(monthInput).toHaveValue(null);
27
+ expect(yearInput).toHaveValue(null);
28
+
29
+ // Should call onChange with undefined initially or not at all if we want strict behavior
30
+ // Based on implementation: useEffect triggers on mount. If empty, calls onChange(undefined).
31
+ expect(mockOnChange).toHaveBeenCalledWith(undefined);
32
+ });
33
+
34
+ it('renders DateSelector with default value correctly', () => {
35
+ const defaultDate = new Date(Date.now());
36
+ render(
37
+ <DateSelector defaultDate={defaultDate} onChange={mockOnChange} />
38
+ );
39
+
40
+ const dayInput = screen.getByLabelText(/day/i);
41
+ const monthInput = screen.getByLabelText(/month/i);
42
+ const yearInput = screen.getByLabelText(/year/i);
43
+
44
+ expect(dayInput).toHaveValue(defaultDate.getDate());
45
+ expect(monthInput).toHaveValue(defaultDate.getMonth() + 1);
46
+ expect(yearInput).toHaveValue(defaultDate.getFullYear());
47
+ });
48
+
49
+ describe('Desktop View', () => {
50
+ it('updates day and calls onChange with undefined if incomplete', () => {
51
+ render(<DateSelector onChange={mockOnChange} />);
52
+ const dayInput = screen.getByLabelText(/day/i);
53
+
54
+ fireEvent.change(dayInput, { target: { value: '15' } });
55
+
56
+ expect(dayInput).toHaveValue(15);
57
+ expect(mockOnChange).toHaveBeenCalledWith(undefined);
58
+ });
59
+
60
+ it('calls onChange with valid date when all fields are filled', () => {
61
+ render(<DateSelector onChange={mockOnChange} />);
62
+ const dayInput = screen.getByLabelText(/day/i);
63
+ const monthInput = screen.getByLabelText(/month/i);
64
+ const yearInput = screen.getByLabelText(/year/i);
65
+
66
+ fireEvent.change(dayInput, { target: { value: '15' } });
67
+ fireEvent.change(monthInput, { target: { value: '5' } });
68
+ fireEvent.change(yearInput, { target: { value: '1990' } });
69
+
70
+ expect(mockOnChange).toHaveBeenCalledWith(
71
+ expect.objectContaining({
72
+ year: 1990,
73
+ month: 5,
74
+ day: 15,
75
+ })
76
+ );
77
+ });
78
+
79
+ it('auto-focuses month after day is filled', () => {
80
+ render(<DateSelector onChange={mockOnChange} />);
81
+ const dayInput = screen.getByLabelText(/day/i);
82
+ const monthInput = screen.getByLabelText(/month/i);
83
+
84
+ fireEvent.change(dayInput, { target: { value: '12' } });
85
+
86
+ expect(monthInput).toHaveFocus();
87
+ });
88
+
89
+ it('auto-focuses year after month is filled', () => {
90
+ render(<DateSelector onChange={mockOnChange} />);
91
+ const monthInput = screen.getByLabelText(/month/i);
92
+ const yearInput = screen.getByLabelText(/year/i);
93
+
94
+ fireEvent.change(monthInput, { target: { value: '12' } });
95
+
96
+ expect(yearInput).toHaveFocus();
97
+ });
98
+
99
+ it('disables all inputs when disabled prop is true', () => {
100
+ render(<DateSelector disabled onChange={mockOnChange} />);
101
+
102
+ const dayInput = screen.getByLabelText(/day/i);
103
+ const monthInput = screen.getByLabelText(/month/i);
104
+ const yearInput = screen.getByLabelText(/year/i);
105
+
106
+ expect(dayInput).toBeDisabled();
107
+ expect(monthInput).toBeDisabled();
108
+ expect(yearInput).toBeDisabled();
109
+ });
110
+ });
111
+
112
+ describe('Mobile View', () => {
113
+ it('renders native date input on mobile', () => {
114
+ render(<DateSelector onChange={mockOnChange} />);
115
+
116
+ const dateInput = screen.getByLabelText(/date/i);
117
+ expect(dateInput).toBeInTheDocument();
118
+ expect(dateInput).toHaveAttribute('type', 'date');
119
+ });
120
+
121
+ it('calls onChange when mobile date input changes', async () => {
122
+ render(<DateSelector onChange={mockOnChange} />);
123
+
124
+ const dateInput = screen.getByLabelText(/date/i);
125
+ fireEvent.change(dateInput, { target: { value: '1995-06-15' } });
126
+
127
+ await waitFor(() => {
128
+ expect(mockOnChange).toHaveBeenCalledWith(
129
+ expect.objectContaining({
130
+ year: 1995,
131
+ month: 6,
132
+ day: 15
133
+ })
134
+ );
135
+ });
136
+ });
137
+
138
+ it('calls onChange with undefined when mobile input is cleared', async () => {
139
+ render(<DateSelector defaultDate="1995-06-15" onChange={mockOnChange} />);
140
+
141
+ const dateInput = screen.getByLabelText(/date/i);
142
+ fireEvent.change(dateInput, { target: { value: '' } });
25
143
 
26
- it('renders DateSelector disabled unchanged', () => {
27
- const { container } = render(
28
- <DateSelector
29
- disabled
30
- defaultDate={new Date(Date.now())}
31
- onChange={jest.fn()}
32
- />
33
- );
34
- expect(container).toMatchSnapshot();
144
+ await waitFor(() => {
145
+ expect(mockOnChange).toHaveBeenCalledWith(undefined);
146
+ });
147
+ });
148
+ });
35
149
  });