anteriority-ui 1.0.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 (199) hide show
  1. package/.github/workflows/ci.yml +31 -0
  2. package/.github/workflows/publish.yml +45 -0
  3. package/.npmrc.bak +1 -0
  4. package/.storybook/main.js +15 -0
  5. package/.storybook/preview.jsx +26 -0
  6. package/AnteriorityUI.md +2400 -0
  7. package/CLAUDE.md +91 -0
  8. package/README.md +182 -0
  9. package/assets/anteriorityUI/AnteriorityUI.logo.jpeg +0 -0
  10. package/assets/favicon/anteriorityUI.ico +0 -0
  11. package/common/api/client.js +43 -0
  12. package/common/storage/LocalStorage.js +13 -0
  13. package/common/styles/typography.css +5 -0
  14. package/common/styles/variables.css +192 -0
  15. package/common/theme/muiTheme.js +9 -0
  16. package/features/password-reset/api.js +39 -0
  17. package/features/user-profile/api.js +5 -0
  18. package/hooks/useAdminPasswordReset.js +133 -0
  19. package/index.js +57 -0
  20. package/package.json +57 -0
  21. package/pnpm-workspace.yaml +3 -0
  22. package/screens/components/AlertModal/AlertModal.jsx +259 -0
  23. package/screens/components/AlertModal/AlertModal.module.css +185 -0
  24. package/screens/components/AlertModal/AlertModal.stories.jsx +87 -0
  25. package/screens/components/Avatar/index.jsx +0 -0
  26. package/screens/components/Avatar/index.module.css +0 -0
  27. package/screens/components/Avatar/utils.js +0 -0
  28. package/screens/components/Badge/index.jsx +33 -0
  29. package/screens/components/Badge/index.module.css +18 -0
  30. package/screens/components/Badge/index.stories.jsx +40 -0
  31. package/screens/components/Barnner/index.jsx +21 -0
  32. package/screens/components/Barnner/index.module.css +33 -0
  33. package/screens/components/Barnner/index.stories.jsx +39 -0
  34. package/screens/components/Barnner/utils.js +0 -0
  35. package/screens/components/BlueLink/index.jsx +27 -0
  36. package/screens/components/BlueLink/index.module.css +11 -0
  37. package/screens/components/BlueLink/index.stories.jsx +29 -0
  38. package/screens/components/Breadcrumbs/index.jsx +62 -0
  39. package/screens/components/Breadcrumbs/index.module.css +158 -0
  40. package/screens/components/Breadcrumbs/index.stories.jsx +37 -0
  41. package/screens/components/Button/index.jsx +169 -0
  42. package/screens/components/Button/index.module.css +168 -0
  43. package/screens/components/Button/index.stories.jsx +71 -0
  44. package/screens/components/Button/utils.js +28 -0
  45. package/screens/components/CalendarComponent/CustomDatePicker.jsx +248 -0
  46. package/screens/components/CalendarComponent/CustomDatePicker.module.css +323 -0
  47. package/screens/components/CalendarComponent/CustomDatePicker.stories.jsx +45 -0
  48. package/screens/components/CalendarPicker/Constants.js +12 -0
  49. package/screens/components/CalendarPicker/index.jsx +263 -0
  50. package/screens/components/CalendarPicker/index.module.css +147 -0
  51. package/screens/components/CalendarPicker/index.stories.jsx +45 -0
  52. package/screens/components/CalendarPicker/utils.js +42 -0
  53. package/screens/components/CardV1/index.jsx +165 -0
  54. package/screens/components/CardV1/index.module.css +232 -0
  55. package/screens/components/CardV1/index.stories.jsx +62 -0
  56. package/screens/components/CardV1/utils.js +49 -0
  57. package/screens/components/ChatWindow/index.jsx +251 -0
  58. package/screens/components/ChatWindow/index.module.css +311 -0
  59. package/screens/components/ChatWindow/index.stories.jsx +62 -0
  60. package/screens/components/Checks/index.jsx +31 -0
  61. package/screens/components/Checks/index.module.css +32 -0
  62. package/screens/components/Checks/index.stories.jsx +32 -0
  63. package/screens/components/Container/index.jsx +36 -0
  64. package/screens/components/Container/index.module.css +24 -0
  65. package/screens/components/Container/index.stories.jsx +32 -0
  66. package/screens/components/CopyText/index.jsx +42 -0
  67. package/screens/components/CopyText/index.module.css +52 -0
  68. package/screens/components/CopyText/index.stories.jsx +24 -0
  69. package/screens/components/CountdownBar/constants.js +3 -0
  70. package/screens/components/CountdownBar/index.jsx +81 -0
  71. package/screens/components/CountdownBar/index.module.css +45 -0
  72. package/screens/components/CountdownBar/index.stories.jsx +43 -0
  73. package/screens/components/CountdownBar/utils.js +119 -0
  74. package/screens/components/DateTag/index.jsx +33 -0
  75. package/screens/components/DateTag/index.module.css +12 -0
  76. package/screens/components/DateTag/index.stories.jsx +29 -0
  77. package/screens/components/DesplegablePanel/constants.js +0 -0
  78. package/screens/components/DesplegablePanel/index.jsx +61 -0
  79. package/screens/components/DesplegablePanel/index.module.css +120 -0
  80. package/screens/components/DesplegablePanel/index.stories.jsx +44 -0
  81. package/screens/components/DesplegablePanel/utils.js +0 -0
  82. package/screens/components/DrawPanel/index.jsx +217 -0
  83. package/screens/components/DrawPanel/index.module.css +252 -0
  84. package/screens/components/DrawPanel/index.stories.jsx +66 -0
  85. package/screens/components/DrawPanel/utils.js +0 -0
  86. package/screens/components/Filter/index.jsx +105 -0
  87. package/screens/components/Filter/index.module.css +91 -0
  88. package/screens/components/Filter/index.stories.jsx +46 -0
  89. package/screens/components/Filter/utils.js +0 -0
  90. package/screens/components/FormControls/FormControls.module.css +86 -0
  91. package/screens/components/FormControls/index.jsx +51 -0
  92. package/screens/components/FormControls/index.stories.jsx +36 -0
  93. package/screens/components/Frame/index.jsx +54 -0
  94. package/screens/components/Frame/index.module.css +102 -0
  95. package/screens/components/Frame/index.stories.jsx +37 -0
  96. package/screens/components/Frame/utils.js +0 -0
  97. package/screens/components/GreenHighlight/index.jsx +11 -0
  98. package/screens/components/GreenHighlight/index.module.css +7 -0
  99. package/screens/components/GreenHighlight/index.stories.jsx +26 -0
  100. package/screens/components/GreenHighlight/utils.jsx +45 -0
  101. package/screens/components/HoursPicker/Constants.js +26 -0
  102. package/screens/components/HoursPicker/index.jsx +350 -0
  103. package/screens/components/HoursPicker/index.module.css +99 -0
  104. package/screens/components/HoursPicker/index.stories.jsx +44 -0
  105. package/screens/components/HoursPicker/utils.js +48 -0
  106. package/screens/components/InfoTooltip/index.jsx +59 -0
  107. package/screens/components/InfoTooltip/index.module.css +98 -0
  108. package/screens/components/InfoTooltip/index.stories.jsx +35 -0
  109. package/screens/components/Input/index.jsx +36 -0
  110. package/screens/components/Input/index.module.css +49 -0
  111. package/screens/components/Input/index.stories.jsx +37 -0
  112. package/screens/components/Input/utils.js +0 -0
  113. package/screens/components/Loading/index.jsx +76 -0
  114. package/screens/components/Loading/index.module.css +193 -0
  115. package/screens/components/Loading/index.stories.jsx +38 -0
  116. package/screens/components/Loading/utils.js +0 -0
  117. package/screens/components/MarkdownContent/index.jsx +16 -0
  118. package/screens/components/MarkdownContent/index.module.css +149 -0
  119. package/screens/components/MarkdownContent/index.stories.jsx +30 -0
  120. package/screens/components/MarkdownEditor/index.jsx +430 -0
  121. package/screens/components/MarkdownEditor/index.module.css +192 -0
  122. package/screens/components/MarkdownEditor/index.stories.jsx +50 -0
  123. package/screens/components/Material-UI/Components/InputWithIcon/index.jsx +87 -0
  124. package/screens/components/Material-UI/Components/InputWithIcon/index.stories.jsx +49 -0
  125. package/screens/components/Material-UI/Components/MenuPopover/index.jsx +117 -0
  126. package/screens/components/Material-UI/Components/MenuPopover/index.stories.jsx +36 -0
  127. package/screens/components/Material-UI/Components/MultilinePlaceholder/index.jsx +44 -0
  128. package/screens/components/Material-UI/Components/MultilinePlaceholder/index.stories.jsx +45 -0
  129. package/screens/components/Material-UI/Components/Paginador/index.jsx +79 -0
  130. package/screens/components/Material-UI/Components/Paginador/index.stories.jsx +49 -0
  131. package/screens/components/Material-UI/Components/Search/index.jsx +81 -0
  132. package/screens/components/Material-UI/Components/Search/index.stories.jsx +68 -0
  133. package/screens/components/Material-UI/Components/Selector/index.jsx +100 -0
  134. package/screens/components/Material-UI/Components/Selector/index.module.css +0 -0
  135. package/screens/components/Material-UI/Components/Selector/index.stories.jsx +52 -0
  136. package/screens/components/Material-UI/Components/Selector/utils.js +0 -0
  137. package/screens/components/Material-UI/Components/TextField/index.jsx +61 -0
  138. package/screens/components/Material-UI/Components/TextField/index.stories.jsx +53 -0
  139. package/screens/components/ModalTooltip/ModalTooltip.jsx +122 -0
  140. package/screens/components/ModalTooltip/ModalTooltip.module.css +65 -0
  141. package/screens/components/ModalTooltip/ModalTooltip.stories.jsx +39 -0
  142. package/screens/components/Notification/Error/ErrorMessage.jsx +30 -0
  143. package/screens/components/Notification/Error/ErrorMessage.module.css +57 -0
  144. package/screens/components/Notification/Error/ErrorMessage.stories.jsx +37 -0
  145. package/screens/components/PasswordResetPanel/index.jsx +325 -0
  146. package/screens/components/PasswordResetPanel/index.stories.jsx +26 -0
  147. package/screens/components/PlaceholderButton/index.jsx +169 -0
  148. package/screens/components/PlaceholderButton/index.module.css +162 -0
  149. package/screens/components/PlaceholderButton/index.stories.jsx +69 -0
  150. package/screens/components/PlaceholderButton/utils.js +42 -0
  151. package/screens/components/Profile/Avatar/index.jsx +125 -0
  152. package/screens/components/Profile/Avatar/index.module.css +86 -0
  153. package/screens/components/Profile/Avatar/index.stories.jsx +48 -0
  154. package/screens/components/Profile/Avatar/utils.js +18 -0
  155. package/screens/components/Profile/index.jsx +58 -0
  156. package/screens/components/Profile/index.module.css +0 -0
  157. package/screens/components/Profile/index.stories.jsx +38 -0
  158. package/screens/components/Profile/utils.js +0 -0
  159. package/screens/components/ScrollBar/index.jsx +62 -0
  160. package/screens/components/ScrollBar/index.module.css +78 -0
  161. package/screens/components/ScrollBar/index.stories.jsx +64 -0
  162. package/screens/components/ScrollBar/utils.js +127 -0
  163. package/screens/components/Sidebar/constants.js +16 -0
  164. package/screens/components/Sidebar/index.jsx +399 -0
  165. package/screens/components/Sidebar/index.module.css +405 -0
  166. package/screens/components/Sidebar/index.stories.jsx +86 -0
  167. package/screens/components/Sidebar/utils.js +75 -0
  168. package/screens/components/Skeleton/index.jsx +11 -0
  169. package/screens/components/Skeleton/index.module.css +26 -0
  170. package/screens/components/Skeleton/index.stories.jsx +42 -0
  171. package/screens/components/SubSidebarLayout/index.jsx +44 -0
  172. package/screens/components/SubSidebarLayout/index.module.css +80 -0
  173. package/screens/components/SubSidebarLayout/index.stories.jsx +51 -0
  174. package/screens/components/SummaryCard/index.jsx +50 -0
  175. package/screens/components/SummaryCard/index.module.css +30 -0
  176. package/screens/components/SummaryCard/index.stories.jsx +29 -0
  177. package/screens/components/Swich/constants.js +4 -0
  178. package/screens/components/Swich/index.jsx +85 -0
  179. package/screens/components/Swich/index.module.css +68 -0
  180. package/screens/components/Swich/index.stories.jsx +44 -0
  181. package/screens/components/Swich/utils.js +0 -0
  182. package/screens/components/TableA/index.jsx +156 -0
  183. package/screens/components/TableA/index.module.css +105 -0
  184. package/screens/components/TableA/index.stories.jsx +116 -0
  185. package/screens/components/TableA/utils.js +11 -0
  186. package/screens/components/TableB/index.jsx +222 -0
  187. package/screens/components/TableB/index.module.css +295 -0
  188. package/screens/components/TableB/index.stories.jsx +110 -0
  189. package/screens/components/TableB/utils.js +11 -0
  190. package/screens/components/ToggleCard/index.jsx +64 -0
  191. package/screens/components/ToggleCard/index.module.css +111 -0
  192. package/screens/components/ToggleCard/index.stories.jsx +49 -0
  193. package/screens/components/UserEditPopover/index.jsx +102 -0
  194. package/screens/components/UserEditPopover/index.module.css +97 -0
  195. package/screens/components/UserEditPopover/index.stories.jsx +49 -0
  196. package/scripts/build.mjs +129 -0
  197. package/scripts/check-case.mjs +127 -0
  198. package/scripts/verify-dist.mjs +45 -0
  199. package/vitest.config.js +36 -0
@@ -0,0 +1,323 @@
1
+ .inputGroup {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 0.25rem;
5
+ width: 100%;
6
+ }
7
+
8
+ .label {
9
+ font-size: 0.8rem;
10
+ font-weight: 600;
11
+ color: #64748b;
12
+ }
13
+
14
+ .inputWrapper {
15
+ position: relative;
16
+ display: flex;
17
+ align-items: center;
18
+ background-color: #f8fafc;
19
+ border: 1px solid #e2e8f0;
20
+ border-radius: 6px;
21
+ transition: all 0.2s ease;
22
+ }
23
+
24
+ .inputWrapper:focus-within {
25
+ border-color: var(--cdp-accent, #10b981);
26
+ background-color: #fff;
27
+ box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
28
+ }
29
+
30
+ .inputIcon {
31
+ position: absolute;
32
+ left: 0.6rem;
33
+ color: #94a3b8;
34
+ pointer-events: none;
35
+ }
36
+
37
+ .inputWrapper:focus-within .inputIcon {
38
+ color: var(--cdp-accent, #10b981);
39
+ }
40
+
41
+ .dateInput {
42
+ width: 100%;
43
+ padding: 0.45rem 0.6rem 0.45rem 2rem;
44
+ border: none;
45
+ background: transparent;
46
+ outline: none;
47
+ font-size: 0.85rem;
48
+ color: #1e293b;
49
+ font-family: inherit;
50
+ cursor: pointer;
51
+ }
52
+
53
+ .modalBackdrop {
54
+ position: fixed;
55
+ top: 0;
56
+ left: 0;
57
+ width: 100vw;
58
+ height: 100vh;
59
+ background-color: rgba(15, 23, 42, 0.4);
60
+ backdrop-filter: blur(4px);
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: center;
64
+ z-index: 9999;
65
+ animation: fadeIn 0.2s ease-out;
66
+ }
67
+
68
+ .calendarModal {
69
+ background-color: #ffffff;
70
+ border-radius: 14px;
71
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
72
+ border: 1px solid #e2e8f0;
73
+ width: 330px;
74
+ padding: 1.25rem;
75
+ font-family: inherit;
76
+ animation: scaleIn 0.25s cubic-bezier(0.16, 1, 0.3, 1);
77
+ }
78
+
79
+ .header {
80
+ display: flex;
81
+ justify-content: space-between;
82
+ align-items: center;
83
+ margin-bottom: 1.25rem;
84
+ padding-bottom: 0.5rem;
85
+ border-bottom: 1px solid #f8fafc;
86
+ }
87
+
88
+ .headerTitleContainer {
89
+ display: flex;
90
+ align-items: center;
91
+ gap: 0.35rem;
92
+ cursor: pointer;
93
+ padding: 4px 8px;
94
+ border-radius: 6px;
95
+ transition: background-color 0.15s ease;
96
+ }
97
+
98
+ .headerTitleContainer:hover {
99
+ background-color: #f1f5f9;
100
+ }
101
+
102
+ .monthName {
103
+ font-size: 0.95rem;
104
+ font-weight: 700;
105
+ color: #0f172a;
106
+ text-transform: capitalize;
107
+ }
108
+
109
+ .dropdownChevron {
110
+ color: #64748b;
111
+ transition: transform 0.2s ease;
112
+ }
113
+
114
+ .chevronChevronOpen {
115
+ transform: rotate(180deg);
116
+ color: var(--cdp-accent, #10b981);
117
+ }
118
+
119
+ .navigation {
120
+ display: flex;
121
+ align-items: center;
122
+ gap: 0.25rem;
123
+ }
124
+
125
+ .navButton, .closeModalBtn {
126
+ background: none;
127
+ border: none;
128
+ color: #475569;
129
+ cursor: pointer;
130
+ padding: 6px;
131
+ border-radius: 8px;
132
+ display: flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+ transition: all 0.2s ease;
136
+ }
137
+
138
+ .navButton:hover {
139
+ background-color: #f1f5f9;
140
+ color: #1e293b;
141
+ }
142
+
143
+ .closeModalBtn {
144
+ color: #94a3b8;
145
+ }
146
+
147
+ .closeModalBtn:hover {
148
+ background-color: #fef2f2;
149
+ color: #ef4444;
150
+ }
151
+
152
+ .selectorsPanel {
153
+ display: flex;
154
+ flex-direction: column;
155
+ gap: 1rem;
156
+ padding: 0.5rem 0;
157
+ animation: fadeIn 0.2s ease;
158
+ }
159
+
160
+ .selectorGroup {
161
+ display: flex;
162
+ flex-direction: column;
163
+ gap: 0.35rem;
164
+ }
165
+
166
+ .selectorGroup label {
167
+ font-size: 0.75rem;
168
+ font-weight: 700;
169
+ color: #94a3b8;
170
+ text-transform: uppercase;
171
+ }
172
+
173
+ .elegantSelect {
174
+ width: 100%;
175
+ padding: 0.6rem 0.75rem;
176
+ border: 1px solid #e2e8f0;
177
+ border-radius: 8px;
178
+ background-color: #f8fafc;
179
+ font-size: 0.9rem;
180
+ font-weight: 600;
181
+ color: #1e293b;
182
+ outline: none;
183
+ cursor: pointer;
184
+ transition: border-color 0.2s;
185
+ }
186
+
187
+ .elegantSelect:focus {
188
+ border-color: var(--cdp-accent, #10b981);
189
+ }
190
+
191
+ .applySelectorsBtn {
192
+ margin-top: 0.5rem;
193
+ background-color: var(--cdp-selected, #0f172a);
194
+ color: white;
195
+ border: none;
196
+ padding: 0.65rem;
197
+ border-radius: 8px;
198
+ font-weight: 600;
199
+ font-size: 0.85rem;
200
+ cursor: pointer;
201
+ transition: background-color 0.2s;
202
+ }
203
+
204
+ .applySelectorsBtn:hover {
205
+ background-color: #1e293b;
206
+ }
207
+
208
+ .weekDaysGrid {
209
+ display: grid;
210
+ grid-template-columns: repeat(7, 1fr);
211
+ gap: 4px;
212
+ margin-bottom: 0.5rem;
213
+ text-align: center;
214
+ }
215
+
216
+ .weekDayName {
217
+ font-size: 0.80rem;
218
+ font-weight: 700;
219
+ color: #94a3b8;
220
+ width: 36px;
221
+ height: 36px;
222
+ display: flex;
223
+ align-items: center;
224
+ justify-content: center;
225
+ margin: auto;
226
+ }
227
+
228
+ .daysGrid {
229
+ display: grid;
230
+ grid-template-columns: repeat(7, 1fr);
231
+ gap: 4px;
232
+ text-align: center;
233
+ }
234
+
235
+ .dayCell {
236
+ font-size: 0.9rem;
237
+ font-weight: 500;
238
+ color: #334155;
239
+ width: 36px;
240
+ height: 36px;
241
+ display: flex;
242
+ align-items: center;
243
+ justify-content: center;
244
+ margin: auto;
245
+ border-radius: 50%;
246
+ cursor: pointer;
247
+ user-select: none;
248
+ transition: all 0.15s ease;
249
+ }
250
+
251
+ .dayCell:hover:not(.otherMonth) {
252
+ background-color: #f1f5f9;
253
+ color: #0f172a;
254
+ }
255
+
256
+ .todayDay {
257
+ font-weight: 700;
258
+ color: var(--cdp-accent, #10b981);
259
+ background-color: #ecfdf5;
260
+ }
261
+
262
+ .selectedDay {
263
+ background-color: var(--cdp-selected, #0f172a);
264
+ color: #ffffff;
265
+ font-weight: 700;
266
+ box-shadow: 0 4px 12px rgba(15, 23, 42, 0.25);
267
+ }
268
+
269
+ .selectedDay:hover {
270
+ background-color: #1e293b;
271
+ }
272
+
273
+ .otherMonth {
274
+ color: #cbd5e1;
275
+ opacity: 0.3;
276
+ cursor: not-allowed;
277
+ }
278
+
279
+ .footer {
280
+ display: flex;
281
+ justify-content: space-between;
282
+ margin-top: 1.25rem;
283
+ padding-top: 0.75rem;
284
+ border-top: 1px solid #f1f5f9;
285
+ }
286
+
287
+ .todayButton, .clearButton {
288
+ background: none;
289
+ border: none;
290
+ font-size: 0.85rem;
291
+ font-weight: 600;
292
+ cursor: pointer;
293
+ padding: 0.5rem 0.75rem;
294
+ border-radius: 6px;
295
+ transition: all 0.2s ease;
296
+ }
297
+
298
+ .todayButton {
299
+ color: var(--cdp-accent, #10b981);
300
+ }
301
+
302
+ .todayButton:hover {
303
+ background-color: #ecfdf5;
304
+ }
305
+
306
+ .clearButton {
307
+ color: #64748b;
308
+ }
309
+
310
+ .clearButton:hover {
311
+ background-color: #f8fafc;
312
+ color: #334155;
313
+ }
314
+
315
+ @keyframes fadeIn {
316
+ from { opacity: 0; }
317
+ to { opacity: 1; }
318
+ }
319
+
320
+ @keyframes scaleIn {
321
+ from { transform: scale(0.96); opacity: 0; }
322
+ to { transform: scale(1); opacity: 1; }
323
+ }
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import CustomDatePicker from './CustomDatePicker';
3
+
4
+ export default {
5
+ title: 'Components/CalendarComponent',
6
+ component: CustomDatePicker,
7
+ };
8
+
9
+ export const Default = {
10
+ args: {
11
+ label: 'Fecha de nacimiento',
12
+ name: 'birthDate',
13
+ value: '',
14
+ onChange: (e) => console.log('changed', e.target.value),
15
+ },
16
+ };
17
+
18
+ export const WithValue = {
19
+ args: {
20
+ label: 'Fecha de la cita',
21
+ name: 'appointmentDate',
22
+ value: '2024-06-15',
23
+ onChange: (e) => console.log('changed', e.target.value),
24
+ },
25
+ };
26
+
27
+ export const Required = {
28
+ args: {
29
+ label: 'Fecha requerida',
30
+ name: 'requiredDate',
31
+ value: '',
32
+ required: true,
33
+ onChange: (e) => console.log('changed', e.target.value),
34
+ },
35
+ };
36
+
37
+ export const Disabled = {
38
+ args: {
39
+ label: 'Fecha bloqueada',
40
+ name: 'disabledDate',
41
+ value: '2024-01-01',
42
+ disabled: true,
43
+ onChange: (e) => console.log('changed', e.target.value),
44
+ },
45
+ };
@@ -0,0 +1,12 @@
1
+ export const MONTHS = [
2
+ 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
3
+ 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'
4
+ ];
5
+
6
+ export const WEEKDAYS = ['L', 'M', 'X', 'J', 'V', 'S', 'D'];
7
+
8
+ export const BUTTONS = {
9
+ CLEAR: 'Borrar',
10
+ TODAY: 'Hoy',
11
+ CONFIRM: 'Confirmar Selección'
12
+ };
@@ -0,0 +1,263 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { format, addMonths, subMonths, isSameDay, isSameMonth, setMonth, setYear } from 'date-fns';
3
+ import { es } from 'date-fns/locale';
4
+ import { ChevronLeft, ChevronRight, CalendarDays, X, ChevronDown } from 'lucide-react';
5
+ import styles from './index.module.css';
6
+ import TextField from '../Material-UI/Components/TextField/index';
7
+ import Frame from '../Frame/index';
8
+ import Button from '../Button/index';
9
+ import Selector from '../Material-UI/Components/Selector/index';
10
+ import { MONTHS, WEEKDAYS, BUTTONS } from './Constants';
11
+ import { parseValueToDate, getDaysForMonth } from './utils';
12
+
13
+ const CalendarPicker = ({ label, name, value, onChange, required = false, disabled = false, inputSx, selectedColor, accentColor }) => {
14
+ const [currentDate, setCurrentDate] = useState(new Date());
15
+ const [isOpen, setIsOpen] = useState(false);
16
+ const [showSelectors, setShowSelectors] = useState(false);
17
+
18
+ let selectedDate = parseValueToDate(value);
19
+
20
+ useEffect(() => {
21
+ const handleKeyDown = (e) => {
22
+ if (e.key === 'Escape') {
23
+ setIsOpen(false);
24
+ setShowSelectors(false);
25
+ }
26
+ };
27
+ if (isOpen) {
28
+ document.body.style.overflow = 'hidden';
29
+ window.addEventListener('keydown', handleKeyDown);
30
+ }
31
+ return () => {
32
+ document.body.style.overflow = '';
33
+ window.removeEventListener('keydown', handleKeyDown);
34
+ };
35
+ }, [isOpen]);
36
+
37
+ const handleNextMonth = () => setCurrentDate(addMonths(currentDate, 1));
38
+ const handlePrevMonth = () => setCurrentDate(subMonths(currentDate, 1));
39
+
40
+ const handleDateClick = (day) => {
41
+ const yyyy = day.getFullYear();
42
+ const mm = String(day.getMonth() + 1).padStart(2, '0');
43
+ const dd = String(day.getDate()).padStart(2, '0');
44
+ const formattedDate = `${yyyy}-${mm}-${dd}`;
45
+
46
+ const event = {
47
+ target: {
48
+ name: name,
49
+ value: formattedDate,
50
+ type: 'date',
51
+ },
52
+ };
53
+ if (typeof onChange === 'function') {
54
+ onChange(event);
55
+ }
56
+ setIsOpen(false);
57
+ };
58
+
59
+ const handleSetToday = () => {
60
+ const today = new Date();
61
+ setCurrentDate(today);
62
+ handleDateClick(today);
63
+ };
64
+
65
+ const handleClear = () => {
66
+ const event = {
67
+ target: { name, value: '', type: 'date' },
68
+ };
69
+ if (typeof onChange === 'function') {
70
+ onChange(event);
71
+ }
72
+ setIsOpen(false);
73
+ };
74
+
75
+ const handleMonthChange = (e) => {
76
+ const val = parseInt(e.target.value);
77
+ if (!isNaN(val)) {
78
+ setCurrentDate(prev => setMonth(prev, val));
79
+ }
80
+ };
81
+
82
+ const handleYearChange = (e) => {
83
+ const val = parseInt(e.target.value);
84
+ if (!isNaN(val)) {
85
+ setCurrentDate(prev => setYear(prev, val));
86
+ }
87
+ };
88
+
89
+ const safeDate = currentDate instanceof Date && !isNaN(currentDate.getTime()) ? currentDate : new Date();
90
+
91
+ const currentYear = safeDate.getFullYear();
92
+ const years = Array.from({ length: 110 }, (_, i) => currentYear + 5 - i);
93
+
94
+ const { monthStart, days } = getDaysForMonth(safeDate);
95
+
96
+ const headerContent = (
97
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', borderBottom: '1px solid #f8fafc', paddingBottom: '0.5rem', marginBottom: '1rem' }}>
98
+ <div className={styles.headerTitleContainer} onClick={() => setShowSelectors(!showSelectors)}>
99
+ <span className={styles.monthName}>
100
+ {format(safeDate, 'MMMM yyyy', { locale: es })}
101
+ </span>
102
+ <ChevronDown size={14} className={`${styles.dropdownChevron} ${showSelectors ? styles.chevronChevronOpen : ''}`} />
103
+ </div>
104
+
105
+ <div className={styles.navigation}>
106
+ {!showSelectors && (
107
+ <>
108
+ <Button
109
+ variant="ghost"
110
+ size="small"
111
+ circle
112
+ onClick={handlePrevMonth}
113
+ icon={ChevronLeft}
114
+ color="inherit"
115
+ />
116
+ <Button
117
+ variant="ghost"
118
+ size="small"
119
+ circle
120
+ onClick={handleNextMonth}
121
+ icon={ChevronRight}
122
+ color="inherit"
123
+ />
124
+ </>
125
+ )}
126
+ <Button
127
+ variant="ghost"
128
+ size="small"
129
+ circle
130
+ onClick={() => { setIsOpen(false); setShowSelectors(false); }}
131
+ icon={X}
132
+ color="var(--cancel-button)"
133
+ />
134
+ </div>
135
+ </div>
136
+ );
137
+
138
+ return (
139
+ <div className={styles.inputGroup} onClick={(e) => e.stopPropagation()}>
140
+ <TextField
141
+ label={label}
142
+ value={selectedDate ? format(selectedDate, 'dd/MM/yyyy') : ''}
143
+ readOnly
144
+ placeholder="dd/mm/aaaa"
145
+ onClick={() => !disabled && setIsOpen(true)}
146
+ disabled={disabled}
147
+ required={required}
148
+ {...(inputSx ? { sx: inputSx } : {})}
149
+ slotProps={{
150
+ input: {
151
+ endAdornment: (
152
+ <CalendarDays
153
+ size={16}
154
+ style={{ cursor: 'pointer', color: '#64748b' }}
155
+ onClick={() => !disabled && setIsOpen(true)}
156
+ />
157
+ )
158
+ }
159
+ }}
160
+ />
161
+
162
+ {isOpen && (
163
+ <Frame
164
+ isModal={true}
165
+ onClose={() => { setIsOpen(false); setShowSelectors(false); }}
166
+ className={styles.calendarFrame}
167
+ >
168
+ <div
169
+ style={{
170
+ display: 'contents',
171
+ ...(selectedColor ? { '--cp-selected': selectedColor } : {}),
172
+ ...(accentColor ? { '--cp-accent': accentColor } : {}),
173
+ }}
174
+ >
175
+ {headerContent}
176
+
177
+ {showSelectors ? (
178
+ <div className={styles.selectorsPanel}>
179
+ <div className={styles.selectorGroup}>
180
+ <Selector
181
+ label="Mes"
182
+ value={currentDate.getMonth()}
183
+ onChange={handleMonthChange}
184
+ options={MONTHS.map((m, index) => ({ value: index, label: m }))}
185
+ />
186
+ </div>
187
+ <div className={styles.selectorGroup}>
188
+ <Selector
189
+ label="Año"
190
+ value={currentDate.getFullYear()}
191
+ onChange={handleYearChange}
192
+ options={years.map(y => ({ value: y, label: String(y) }))}
193
+ />
194
+ </div>
195
+ <Button
196
+ variant="primary"
197
+ fullWidth
198
+ onClick={() => setShowSelectors(false)}
199
+ color={selectedColor || '#0f172a'}
200
+ style={{ marginTop: '0.5rem' }}
201
+ >
202
+ {BUTTONS.CONFIRM}
203
+ </Button>
204
+ </div>
205
+ ) : (
206
+ <>
207
+ <div className={styles.weekDaysGrid}>
208
+ {WEEKDAYS.map(day => (
209
+ <div key={day} className={styles.weekDayName}>{day}</div>
210
+ ))}
211
+ </div>
212
+
213
+ <div className={styles.daysGrid}>
214
+ {days.map((day, index) => {
215
+ const isCurrentMonth = isSameMonth(day, monthStart);
216
+ const isSelected = selectedDate && isSameDay(day, selectedDate);
217
+ const isToday = isSameDay(day, new Date());
218
+
219
+ let dayClassName = styles.dayCell;
220
+ if (!isCurrentMonth) dayClassName += ` ${styles.otherMonth}`;
221
+ if (isSelected) dayClassName += ` ${styles.selectedDay}`;
222
+ if (isToday && !isSelected) dayClassName += ` ${styles.todayDay}`;
223
+
224
+ return (
225
+ <div
226
+ key={index}
227
+ className={dayClassName}
228
+ onClick={() => isCurrentMonth && handleDateClick(day)}
229
+ >
230
+ {format(day, 'd')}
231
+ </div>
232
+ );
233
+ })}
234
+ </div>
235
+ </>
236
+ )}
237
+
238
+ <div className={styles.footer}>
239
+ <Button
240
+ variant="ghost"
241
+ size="small"
242
+ onClick={handleClear}
243
+ color="inherit"
244
+ >
245
+ {BUTTONS.CLEAR}
246
+ </Button>
247
+ <Button
248
+ variant="ghost"
249
+ size="small"
250
+ onClick={handleSetToday}
251
+ color={accentColor || 'green'}
252
+ >
253
+ {BUTTONS.TODAY}
254
+ </Button>
255
+ </div>
256
+ </div>
257
+ </Frame>
258
+ )}
259
+ </div>
260
+ );
261
+ };
262
+
263
+ export default CalendarPicker;