@arquimedes.co/eureka-forms 3.0.50-test → 3.0.52-new-steps

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 (102) hide show
  1. package/dist/@Types/AvailabilityFormStep.d.ts +48 -0
  2. package/dist/@Types/AvailabilityFormStep.js +24 -0
  3. package/dist/@Types/BankAccountFormStep.d.ts +67 -0
  4. package/dist/@Types/BankAccountFormStep.js +14 -0
  5. package/dist/@Types/BookingFormStep.d.ts +166 -0
  6. package/dist/@Types/BookingFormStep.js +44 -0
  7. package/dist/@Types/CalendarFormStep.d.ts +192 -0
  8. package/dist/@Types/CalendarFormStep.js +48 -0
  9. package/dist/@Types/CommunicationChannelFormStep.d.ts +51 -0
  10. package/dist/@Types/CommunicationChannelFormStep.js +15 -0
  11. package/dist/@Types/ConsentFormStep.d.ts +36 -0
  12. package/dist/@Types/ConsentFormStep.js +8 -0
  13. package/dist/@Types/EntityFormFormStep.d.ts +66 -0
  14. package/dist/@Types/EntityFormFormStep.js +20 -0
  15. package/dist/@Types/EventFormStep.d.ts +52 -0
  16. package/dist/@Types/EventFormStep.js +13 -0
  17. package/dist/@Types/ExternalReferenceFormStep.d.ts +74 -0
  18. package/dist/@Types/ExternalReferenceFormStep.js +20 -0
  19. package/dist/@Types/FormStep.d.ts +7 -2
  20. package/dist/@Types/FormStep.js +2 -1
  21. package/dist/@Types/LocationFormStep.d.ts +159 -0
  22. package/dist/@Types/LocationFormStep.js +46 -0
  23. package/dist/@Types/NumericFormSteps.d.ts +108 -0
  24. package/dist/@Types/NumericFormSteps.js +20 -0
  25. package/dist/@Types/PredefinedSelectorFormStep.d.ts +51 -0
  26. package/dist/@Types/PredefinedSelectorFormStep.js +39 -0
  27. package/dist/@Types/StepRef.d.ts +135 -0
  28. package/dist/@Types/StepRef.js +49 -0
  29. package/dist/App/App.stories.d.ts +30 -0
  30. package/dist/App/App.stories.js +298 -0
  31. package/dist/App/App.stories.test.d.ts +1 -0
  32. package/dist/App/App.stories.test.js +56 -0
  33. package/dist/FormSteps/BookingStep/BookingStep.d.ts +17 -0
  34. package/dist/FormSteps/BookingStep/BookingStep.js +14 -0
  35. package/dist/FormSteps/BookingStep/MaterialBookingStep/MaterialBookingStep.d.ts +7 -0
  36. package/dist/FormSteps/BookingStep/MaterialBookingStep/MaterialBookingStep.js +31 -0
  37. package/dist/FormSteps/CalendarStep/CalendarStep.d.ts +7 -0
  38. package/dist/FormSteps/CalendarStep/CalendarStep.js +14 -0
  39. package/dist/FormSteps/CalendarStep/MaterialCalendarStep/MaterialCalendarStep.d.ts +3 -0
  40. package/dist/FormSteps/CalendarStep/MaterialCalendarStep/MaterialCalendarStep.js +269 -0
  41. package/dist/FormSteps/CalendarStep/MaterialCalendarStep/MaterialCalendarStep.module.css +531 -0
  42. package/dist/FormSteps/DatePickerStep/DatePickerStep.required.test.d.ts +1 -0
  43. package/dist/FormSteps/DatePickerStep/DatePickerStep.required.test.js +94 -0
  44. package/dist/FormSteps/LocationStep/LocationStep.d.ts +10 -0
  45. package/dist/FormSteps/LocationStep/LocationStep.js +14 -0
  46. package/dist/FormSteps/LocationStep/MaterialLocationStep/MaterialLocationStep.d.ts +3 -0
  47. package/dist/FormSteps/LocationStep/MaterialLocationStep/MaterialLocationStep.js +47 -0
  48. package/dist/FormSteps/LocationStep/MaterialLocationStep/MaterialLocationStep.module.css +18 -0
  49. package/dist/FormSteps/NumberStep/MaterialNumberStep/MaterialNumberStep.d.ts +3 -0
  50. package/dist/FormSteps/NumberStep/MaterialNumberStep/MaterialNumberStep.js +168 -0
  51. package/dist/FormSteps/NumberStep/MaterialNumberStep/MaterialNumberStep.module.css +94 -0
  52. package/dist/FormSteps/NumberStep/NumberStep.d.ts +10 -0
  53. package/dist/FormSteps/NumberStep/NumberStep.js +14 -0
  54. package/dist/FormSteps/Step.js +16 -0
  55. package/dist/FormSteps/StepFunctions.js +14 -0
  56. package/dist/FormSteps/StepFunctions.test.js +54 -0
  57. package/dist/FormSteps/TitleStep/MaterialTitleStep/MaterialTitleStep.js +3 -1
  58. package/dist/Icons/AddIcon.d.ts +3 -0
  59. package/dist/Icons/AddIcon.js +7 -0
  60. package/dist/Icons/EditIcon.d.ts +3 -0
  61. package/dist/Icons/EditIcon.js +7 -0
  62. package/dist/Icons/RemoveIcon.d.ts +3 -0
  63. package/dist/Icons/RemoveIcon.js +7 -0
  64. package/dist/Icons/ViewDayIcon.d.ts +3 -0
  65. package/dist/Icons/ViewDayIcon.js +7 -0
  66. package/dist/Icons/ViewWeekIcon.d.ts +3 -0
  67. package/dist/Icons/ViewWeekIcon.js +7 -0
  68. package/dist/Shared/ErkAddressAutocomplete/ErkAddressAutocomplete.d.ts +19 -0
  69. package/dist/Shared/ErkAddressAutocomplete/ErkAddressAutocomplete.js +80 -0
  70. package/dist/Shared/ErkAddressAutocomplete/ErkAddressAutocomplete.module.css +82 -0
  71. package/dist/Shared/ErkAddressAutocomplete/googlePlaces.d.ts +29 -0
  72. package/dist/Shared/ErkAddressAutocomplete/googlePlaces.js +139 -0
  73. package/dist/Shared/ErkAutocompleteOption.d.ts +12 -0
  74. package/dist/Shared/ErkAutocompleteOption.js +37 -0
  75. package/dist/Shared/ErkBookingPicker/ErkBookingPicker.d.ts +28 -0
  76. package/dist/Shared/ErkBookingPicker/ErkBookingPicker.js +149 -0
  77. package/dist/Shared/ErkBookingPicker/ErkBookingPicker.module.css +113 -0
  78. package/dist/Shared/ErkDatePicker/ErkDatePicker.js +3 -10
  79. package/dist/Shared/ErkDatePicker/ErkDatePicker.required.test.d.ts +1 -0
  80. package/dist/Shared/ErkDatePicker/ErkDatePicker.required.test.js +30 -0
  81. package/dist/Shared/ErkDateRangePicker/ErkDateRangePicker.d.ts +2 -3
  82. package/dist/Shared/ErkDateRangePicker/ErkDateRangePicker.js +1 -2
  83. package/dist/Shared/ErkLocationField/ErkLocationField.d.ts +23 -0
  84. package/dist/Shared/ErkLocationField/ErkLocationField.js +73 -0
  85. package/dist/Shared/ErkLocationField/ErkLocationField.module.css +29 -0
  86. package/dist/Shared/ErkLocationField/addressFields.d.ts +12 -0
  87. package/dist/Shared/ErkLocationField/addressFields.js +34 -0
  88. package/dist/Shared/ErkLocationField/locationRestrictions.d.ts +6 -0
  89. package/dist/Shared/ErkLocationField/locationRestrictions.js +51 -0
  90. package/dist/Shared/ErkLocationInput/ErkLocationInput.d.ts +15 -0
  91. package/dist/Shared/ErkLocationInput/ErkLocationInput.js +502 -0
  92. package/dist/Shared/ErkLocationInput/ErkLocationInput.module.css +115 -0
  93. package/dist/Shared/ErkNumberField/ErkNumberField.d.ts +42 -0
  94. package/dist/Shared/ErkNumberField/ErkNumberField.js +170 -0
  95. package/dist/Shared/ErkSmartSelect/ErkSmartSelect.js +2 -1
  96. package/dist/Shared/ErkSmartSelect/ErkSmartSelect.test.d.ts +1 -0
  97. package/dist/Shared/ErkSmartSelect/ErkSmartSelect.test.js +33 -0
  98. package/dist/Shared/SmartDraftRenderer/SmartDraftRenderer.d.ts +7 -1
  99. package/dist/Shared/SmartDraftRenderer/SmartDraftRenderer.js +2 -2
  100. package/dist/constants/FormStepTypes.d.ts +5 -1
  101. package/dist/constants/FormStepTypes.js +4 -0
  102. package/package.json +2 -1
@@ -0,0 +1,531 @@
1
+ /* =========================================================================
2
+ MaterialCalendarStep
3
+ ========================================================================= */
4
+
5
+ .container {
6
+ display: flex;
7
+ flex-direction: column;
8
+ padding: 10px;
9
+ padding-top: 5px;
10
+ padding-bottom: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ /* =========================================================================
15
+ Toolbar
16
+ ========================================================================= */
17
+
18
+ .toolbar {
19
+ display: flex;
20
+ align-items: center;
21
+ gap: 10px;
22
+ padding: 6px 2px 8px;
23
+ flex-wrap: wrap;
24
+ }
25
+
26
+ /* View switcher */
27
+
28
+ .viewSwitcher {
29
+ display: flex;
30
+ border: 1px solid var(--eureka-outline, #ddd);
31
+ border-radius: 8px;
32
+ overflow: hidden;
33
+ }
34
+
35
+ .viewBtn {
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ padding: 5px 10px;
40
+ border: none;
41
+ border-right: 1px solid var(--eureka-outline, #ddd);
42
+ background: transparent;
43
+ cursor: pointer;
44
+ color: var(--eureka-text, #555);
45
+ opacity: 0.55;
46
+ transition: background 0.15s, opacity 0.15s;
47
+ }
48
+
49
+ .viewBtn:last-child {
50
+ border-right: none;
51
+ }
52
+
53
+ .viewBtn:hover {
54
+ background: rgba(0, 0, 0, 0.04);
55
+ opacity: 0.85;
56
+ }
57
+
58
+ .viewBtnActive {
59
+ background: var(--eureka-primary, #1976d2) !important;
60
+ color: #fff !important;
61
+ opacity: 1 !important;
62
+ }
63
+
64
+ /* Nav */
65
+
66
+ .navGroup {
67
+ display: flex;
68
+ align-items: center;
69
+ gap: 4px;
70
+ flex: 1;
71
+ min-width: 0;
72
+ }
73
+
74
+ .navBtn {
75
+ display: flex;
76
+ align-items: center;
77
+ justify-content: center;
78
+ padding: 4px;
79
+ border: none;
80
+ border-radius: 6px;
81
+ background: transparent;
82
+ cursor: pointer;
83
+ color: var(--eureka-text, #555);
84
+ opacity: 0.55;
85
+ transition: opacity 0.15s, background 0.15s;
86
+ }
87
+
88
+ .navBtn:hover {
89
+ background: rgba(0, 0, 0, 0.05);
90
+ opacity: 1;
91
+ }
92
+
93
+ .navLabel {
94
+ font-weight: 600;
95
+ font-size: 14px;
96
+ white-space: nowrap;
97
+ overflow: hidden;
98
+ text-overflow: ellipsis;
99
+ text-transform: capitalize;
100
+ }
101
+
102
+ .eventBadge {
103
+ font-size: 11px;
104
+ padding: 3px 8px;
105
+ border-radius: 100px;
106
+ background: var(--eureka-primary, #1976d2);
107
+ color: #fff;
108
+ font-weight: 500;
109
+ white-space: nowrap;
110
+ }
111
+
112
+ .hintText {
113
+ font-size: 11px;
114
+ opacity: 0.4;
115
+ white-space: nowrap;
116
+ margin-left: auto;
117
+ }
118
+
119
+ /* =========================================================================
120
+ Calendar card container
121
+ ========================================================================= */
122
+
123
+ .calendarCard {
124
+ border: 1px solid var(--eureka-outline, #e0e0e0);
125
+ border-radius: 12px;
126
+ overflow: hidden;
127
+ background: var(--eureka-bg, #fff);
128
+ }
129
+
130
+ /* =========================================================================
131
+ Time grid (week / day)
132
+ ========================================================================= */
133
+
134
+ .gridWrapper {
135
+ display: flex;
136
+ flex-direction: column;
137
+ }
138
+
139
+ /* Header */
140
+
141
+ .gridHeader {
142
+ display: grid;
143
+ border-bottom: 2px solid var(--eureka-outline, #e0e0e0);
144
+ position: sticky;
145
+ top: 0;
146
+ z-index: 2;
147
+ background: var(--eureka-bg, #fff);
148
+ }
149
+
150
+ .cornerCell {
151
+ width: 48px;
152
+ border-right: 1px solid var(--eureka-outline, #e0e0e0);
153
+ }
154
+
155
+ .dayHeader {
156
+ display: flex;
157
+ flex-direction: column;
158
+ align-items: center;
159
+ justify-content: center;
160
+ padding: 8px 4px;
161
+ cursor: pointer;
162
+ border-right: 1px solid var(--eureka-outline, #e0e0e0);
163
+ transition: background 0.1s;
164
+ }
165
+
166
+ .dayHeader:last-child {
167
+ border-right: none;
168
+ }
169
+
170
+ .dayHeader:hover {
171
+ background: rgba(0, 0, 0, 0.03);
172
+ }
173
+
174
+ .dayHeaderToday {
175
+ color: var(--eureka-primary, #1976d2);
176
+ }
177
+
178
+ .dayHeaderDow {
179
+ font-size: 11px;
180
+ text-transform: capitalize;
181
+ opacity: 0.6;
182
+ }
183
+
184
+ .dayHeaderNum {
185
+ font-size: 18px;
186
+ font-weight: 700;
187
+ line-height: 1.1;
188
+ }
189
+
190
+ .todayCircle {
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: center;
194
+ width: 30px;
195
+ height: 30px;
196
+ border-radius: 50%;
197
+ background: var(--eureka-primary, #1976d2);
198
+ color: #fff !important;
199
+ }
200
+
201
+ /* Body */
202
+
203
+ .gridBody {
204
+ overflow-y: auto;
205
+ max-height: 520px;
206
+ }
207
+
208
+ .gridInner {
209
+ display: grid;
210
+ }
211
+
212
+ /* Hour labels */
213
+
214
+ .hourLabels {
215
+ border-right: 1px solid var(--eureka-outline, #e0e0e0);
216
+ }
217
+
218
+ .hourLabel {
219
+ display: flex;
220
+ align-items: flex-start;
221
+ justify-content: flex-end;
222
+ padding-right: 6px;
223
+ padding-top: 2px;
224
+ font-size: 10px;
225
+ opacity: 0.45;
226
+ box-sizing: border-box;
227
+ border-bottom: 1px solid rgba(0, 0, 0, 0.04);
228
+ }
229
+
230
+ /* Day columns */
231
+
232
+ .dayColumn {
233
+ position: relative;
234
+ border-right: 1px solid var(--eureka-outline, #e0e0e0);
235
+ cursor: crosshair;
236
+ box-sizing: border-box;
237
+ }
238
+
239
+ .dayColumn:last-child {
240
+ border-right: none;
241
+ }
242
+
243
+ .hourLine {
244
+ position: absolute;
245
+ left: 0;
246
+ right: 0;
247
+ height: 1px;
248
+ background: rgba(0, 0, 0, 0.05);
249
+ }
250
+
251
+ /* =========================================================================
252
+ Event blocks
253
+ ========================================================================= */
254
+
255
+ .eventBlock {
256
+ position: absolute;
257
+ left: 2px;
258
+ right: 2px;
259
+ border-radius: 4px;
260
+ padding: 2px 4px;
261
+ cursor: default;
262
+ overflow: hidden;
263
+ display: flex;
264
+ flex-direction: column;
265
+ z-index: 1;
266
+ opacity: 0.9;
267
+ transition: opacity 0.1s;
268
+ box-sizing: border-box;
269
+ }
270
+
271
+ .eventBlock:hover {
272
+ opacity: 1;
273
+ z-index: 2;
274
+ }
275
+
276
+ .eventLabel {
277
+ font-size: 11px;
278
+ font-weight: 600;
279
+ color: #fff;
280
+ white-space: nowrap;
281
+ overflow: hidden;
282
+ text-overflow: ellipsis;
283
+ line-height: 1.3;
284
+ }
285
+
286
+ .eventTime {
287
+ font-size: 10px;
288
+ color: rgba(255, 255, 255, 0.8);
289
+ white-space: nowrap;
290
+ }
291
+
292
+ .eventDeleteBtn {
293
+ position: absolute;
294
+ top: 2px;
295
+ right: 2px;
296
+ background: rgba(0, 0, 0, 0.25);
297
+ border: none;
298
+ border-radius: 3px;
299
+ cursor: pointer;
300
+ color: #fff;
301
+ display: none;
302
+ align-items: center;
303
+ justify-content: center;
304
+ padding: 1px;
305
+ line-height: 1;
306
+ }
307
+
308
+ .eventBlock:hover .eventDeleteBtn {
309
+ display: flex;
310
+ }
311
+
312
+ /* =========================================================================
313
+ Month view
314
+ ========================================================================= */
315
+
316
+ .monthGrid {
317
+ display: grid;
318
+ grid-template-columns: repeat(7, 1fr);
319
+ }
320
+
321
+ .monthDowHeader {
322
+ padding: 8px 4px;
323
+ font-size: 11px;
324
+ font-weight: 600;
325
+ text-align: center;
326
+ opacity: 0.5;
327
+ text-transform: uppercase;
328
+ letter-spacing: 0.4px;
329
+ border-bottom: 1px solid var(--eureka-outline, #e0e0e0);
330
+ }
331
+
332
+ .monthCell {
333
+ min-height: 80px;
334
+ padding: 4px;
335
+ border-right: 1px solid var(--eureka-outline, #e0e0e0);
336
+ border-bottom: 1px solid var(--eureka-outline, #e0e0e0);
337
+ cursor: pointer;
338
+ transition: background 0.1s;
339
+ overflow: hidden;
340
+ }
341
+
342
+ .monthCell:nth-child(7n) {
343
+ border-right: none;
344
+ }
345
+
346
+ .monthCell:hover {
347
+ background: rgba(0, 0, 0, 0.02);
348
+ }
349
+
350
+ .monthCellOutside {
351
+ opacity: 0.3;
352
+ }
353
+
354
+ .monthCellToday .monthCellNum {
355
+ color: var(--eureka-primary, #1976d2);
356
+ }
357
+
358
+ .monthCellNum {
359
+ font-size: 13px;
360
+ font-weight: 600;
361
+ display: inline-flex;
362
+ align-items: center;
363
+ justify-content: center;
364
+ width: 24px;
365
+ height: 24px;
366
+ margin-bottom: 2px;
367
+ border-radius: 50%;
368
+ }
369
+
370
+ .monthEventDot {
371
+ font-size: 10px;
372
+ color: #fff;
373
+ border-radius: 3px;
374
+ padding: 1px 4px;
375
+ margin-bottom: 2px;
376
+ white-space: nowrap;
377
+ overflow: hidden;
378
+ text-overflow: ellipsis;
379
+ }
380
+
381
+ .monthMoreLabel {
382
+ font-size: 10px;
383
+ opacity: 0.5;
384
+ padding-left: 2px;
385
+ }
386
+
387
+ /* =========================================================================
388
+ Create popover
389
+ ========================================================================= */
390
+
391
+ .popoverPaper {
392
+ border-radius: 12px !important;
393
+ box-shadow: 0 8px 32px rgba(0,0,0,0.15) !important;
394
+ min-width: 260px;
395
+ max-width: 300px;
396
+ }
397
+
398
+ .popoverHeader {
399
+ display: flex;
400
+ align-items: center;
401
+ justify-content: space-between;
402
+ padding: 12px 14px 8px;
403
+ border-bottom: 1px solid rgba(0, 0, 0, 0.07);
404
+ }
405
+
406
+ .popoverTitle {
407
+ font-weight: 600;
408
+ font-size: 14px;
409
+ }
410
+
411
+ .popoverClose {
412
+ background: none;
413
+ border: none;
414
+ cursor: pointer;
415
+ display: flex;
416
+ align-items: center;
417
+ opacity: 0.5;
418
+ padding: 2px;
419
+ border-radius: 4px;
420
+ }
421
+
422
+ .popoverClose:hover { opacity: 1; }
423
+
424
+ .popoverBody {
425
+ padding: 12px 14px 14px;
426
+ display: flex;
427
+ flex-direction: column;
428
+ gap: 8px;
429
+ }
430
+
431
+ .popoverLabel {
432
+ font-size: 11px;
433
+ font-weight: 600;
434
+ text-transform: uppercase;
435
+ letter-spacing: 0.4px;
436
+ opacity: 0.5;
437
+ margin-bottom: -4px;
438
+ }
439
+
440
+ .categoryGrid {
441
+ display: flex;
442
+ flex-wrap: wrap;
443
+ gap: 6px;
444
+ }
445
+
446
+ .categoryChip {
447
+ display: flex;
448
+ align-items: center;
449
+ gap: 5px;
450
+ padding: 4px 10px;
451
+ border: 1px solid var(--eureka-outline, #ddd);
452
+ border-radius: 100px;
453
+ background: transparent;
454
+ cursor: pointer;
455
+ font-size: 12px;
456
+ transition: border-color 0.15s, background 0.15s;
457
+ }
458
+
459
+ .categoryChip:hover {
460
+ border-color: var(--eureka-primary, #1976d2);
461
+ }
462
+
463
+ .categoryChipActive {
464
+ border-color: transparent !important;
465
+ }
466
+
467
+ .categoryDot {
468
+ width: 8px;
469
+ height: 8px;
470
+ border-radius: 50%;
471
+ flex-shrink: 0;
472
+ }
473
+
474
+ .popoverInput {
475
+ width: 100%;
476
+ padding: 7px 10px;
477
+ border: 1px solid var(--eureka-outline, #ccc);
478
+ border-radius: 6px;
479
+ font-size: 13px;
480
+ font-family: inherit;
481
+ box-sizing: border-box;
482
+ background: transparent;
483
+ color: inherit;
484
+ outline: none;
485
+ transition: border-color 0.15s;
486
+ }
487
+
488
+ .popoverInput:focus {
489
+ border-color: var(--eureka-primary, #1976d2);
490
+ }
491
+
492
+ .timeRow {
493
+ display: flex;
494
+ align-items: flex-end;
495
+ gap: 8px;
496
+ }
497
+
498
+ .timeRow > div {
499
+ flex: 1;
500
+ display: flex;
501
+ flex-direction: column;
502
+ gap: 4px;
503
+ }
504
+
505
+ .timeDash {
506
+ font-size: 16px;
507
+ font-weight: 300;
508
+ opacity: 0.4;
509
+ padding-bottom: 6px;
510
+ }
511
+
512
+ .createBtn {
513
+ display: flex;
514
+ align-items: center;
515
+ justify-content: center;
516
+ gap: 6px;
517
+ padding: 9px 16px;
518
+ border: none;
519
+ border-radius: 8px;
520
+ color: #fff;
521
+ font-size: 13px;
522
+ font-weight: 600;
523
+ cursor: pointer;
524
+ margin-top: 4px;
525
+ transition: opacity 0.15s;
526
+ font-family: inherit;
527
+ }
528
+
529
+ .createBtn:hover {
530
+ opacity: 0.9;
531
+ }
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,94 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect } from 'react';
3
+ import { render, screen, waitFor } from '@testing-library/react';
4
+ import userEvent from '@testing-library/user-event';
5
+ import { describe, expect, it, vi } from 'vitest';
6
+ import '@testing-library/jest-dom';
7
+ import { Provider } from 'react-redux';
8
+ import { useForm, FormProvider } from 'react-hook-form';
9
+ import { configureStore } from '@reduxjs/toolkit';
10
+ import { EurekaFormsReducer, defaultRootState } from '../../Utils/store';
11
+ import { RootApi } from '../../Utils/_api';
12
+ import FormStepTypes from '../../constants/FormStepTypes';
13
+ import { StoreContext } from '../../Utils/StoreContext';
14
+ import { IdFormContext } from '../../Contexts/FormContext';
15
+ import FormContext from '../../Contexts/FormContext';
16
+ import SectionContext from '../../Contexts/SectionContext';
17
+ import MaterialProviders from '../../Utils/MaterialProviders';
18
+ import InternalFormStyle from '../../constants/InternalFormStyle';
19
+ import DatePickerStep from './DatePickerStep';
20
+ const STORY_FORM_ID = 'STORY_FORM';
21
+ const requiredDateStep = {
22
+ id: 'datepicker-step',
23
+ idSection: 'SECTION_1',
24
+ stepPath: ['datepicker-step'],
25
+ type: FormStepTypes.DATEPICKER,
26
+ label: 'Fecha de nacimiento',
27
+ description: null,
28
+ required: true,
29
+ pickTime: false,
30
+ size: 4,
31
+ editable: true,
32
+ };
33
+ const form = {
34
+ firstSection: 'SECTION_1',
35
+ sections: {
36
+ SECTION_1: { id: 'SECTION_1', name: 'Sección 1', steps: [], nextSection: null },
37
+ },
38
+ steps: { 'datepicker-step': { ...requiredDateStep } },
39
+ confirmationMessage: { blocks: [], entityMap: {} },
40
+ showLink: false,
41
+ size: { blockSize: 200, blockNum: 4, spacingSize: 10 },
42
+ };
43
+ function makeStore() {
44
+ return configureStore({
45
+ reducer: { forms: EurekaFormsReducer, [RootApi.reducerPath]: RootApi.reducer },
46
+ preloadedState: { forms: { [STORY_FORM_ID]: defaultRootState } },
47
+ middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(RootApi.middleware),
48
+ });
49
+ }
50
+ function Harness({ onValid, pickTime, required = true, onReady, }) {
51
+ const methods = useForm({ mode: 'onTouched' });
52
+ const step = { ...requiredDateStep, required, pickTime: !!pickTime };
53
+ useEffect(() => {
54
+ onReady?.(methods);
55
+ }, [methods, onReady]);
56
+ return (_jsx(MaterialProviders, { formStyle: InternalFormStyle, children: _jsx(Provider, { store: makeStore(), context: StoreContext, children: _jsx(IdFormContext.Provider, { value: STORY_FORM_ID, children: _jsx(FormContext.Provider, { value: form, children: _jsx(SectionContext.Provider, { value: "SECTION_1", children: _jsx(FormProvider, { ...methods, children: _jsxs("form", { onSubmit: (e) => void methods.handleSubmit(onValid)(e), children: [_jsx(DatePickerStep, { step: step, editable: true }), _jsx("button", { type: "submit", children: "Enviar" })] }) }) }) }) }) }) }));
57
+ }
58
+ describe('DatePickerStep required validation', () => {
59
+ it('does not leak a defaultValue Date into the form value on mount', () => {
60
+ let methods;
61
+ render(_jsx(Harness, { onValid: vi.fn(), onReady: (m) => (methods = m) }));
62
+ expect(methods?.getValues('datepicker-step') ?? null).toBeNull();
63
+ });
64
+ it('blocks submit and shows the obligatorio error when a required date is left empty (handleSubmit)', async () => {
65
+ const onValid = vi.fn();
66
+ render(_jsx(Harness, { onValid: onValid }));
67
+ await userEvent.click(screen.getByRole('button', { name: 'Enviar' }));
68
+ await waitFor(() => {
69
+ expect(screen.getByText('Este campo es obligatorio')).toBeInTheDocument();
70
+ });
71
+ expect(onValid).not.toHaveBeenCalled();
72
+ });
73
+ it('reports invalid via trigger() like the real ColumnForm submit path', async () => {
74
+ let methods;
75
+ render(_jsx(Harness, { onValid: vi.fn(), onReady: (m) => (methods = m) }));
76
+ const valid = await methods.trigger(undefined, { shouldFocus: true });
77
+ expect(valid).toBe(false);
78
+ });
79
+ it('pickTime required: trigger() reports invalid when empty', async () => {
80
+ let methods;
81
+ render(_jsx(Harness, { onValid: vi.fn(), pickTime: true, onReady: (m) => (methods = m) }));
82
+ const valid = await methods.trigger(undefined, { shouldFocus: true });
83
+ expect(valid).toBe(false);
84
+ });
85
+ it('control: a NON-required empty date submits (proves the required flag is the deciding factor)', async () => {
86
+ const onValid = vi.fn();
87
+ render(_jsx(Harness, { onValid: onValid, required: false }));
88
+ await userEvent.click(screen.getByRole('button', { name: 'Enviar' }));
89
+ await waitFor(() => {
90
+ expect(onValid).toHaveBeenCalledTimes(1);
91
+ });
92
+ expect(screen.queryByText('Este campo es obligatorio')).not.toBeInTheDocument();
93
+ });
94
+ });
@@ -0,0 +1,10 @@
1
+ import { LocationStep } from '../../@Types/LocationFormStep';
2
+ import { StepProps } from '../Step';
3
+ export interface LocationStepProps extends StepProps {
4
+ /** The LocationStep to display */
5
+ step: LocationStep;
6
+ /** The icon to display */
7
+ IconComponent?: React.ElementType;
8
+ }
9
+ declare function LocationStepComponent(props: LocationStepProps): JSX.Element;
10
+ export default LocationStepComponent;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { FormStyleTypes } from '../../constants/FormStepTypes';
3
+ import MaterialLocationStep from './MaterialLocationStep/MaterialLocationStep';
4
+ import { useAppSelector } from '../../hooks';
5
+ function LocationStepComponent(props) {
6
+ const { formStyle } = useAppSelector((state) => state.global);
7
+ switch (formStyle.type) {
8
+ case FormStyleTypes.MATERIAL:
9
+ default: {
10
+ return _jsx(MaterialLocationStep, { ...props });
11
+ }
12
+ }
13
+ }
14
+ export default LocationStepComponent;
@@ -0,0 +1,3 @@
1
+ import { LocationStepProps } from '../LocationStep';
2
+ declare function MaterialLocationStep({ step, editable }: LocationStepProps): JSX.Element;
3
+ export default MaterialLocationStep;
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useContext } from 'react';
3
+ import { AddressFieldMode, LocationInputMode } from '../../../@Types/LocationFormStep';
4
+ import { useFormStep } from '../../StepHooks';
5
+ import FormContext from '../../../Contexts/FormContext';
6
+ import { selectBreakPoint, useAppSelector } from '../../../hooks';
7
+ import { calcStepWidth } from '../../StepFunctions';
8
+ import ErkLocationField from '../../../Shared/ErkLocationField/ErkLocationField';
9
+ import { fieldConfig } from '../../../Shared/ErkLocationField/addressFields';
10
+ import { validateRestrictions } from '../../../Shared/ErkLocationField/locationRestrictions';
11
+ import styles from './MaterialLocationStep.module.css';
12
+ function MaterialLocationStep({ step, editable }) {
13
+ const currentBreakPoint = useAppSelector(selectBreakPoint);
14
+ const { postview } = useAppSelector((state) => state.global);
15
+ const form = useContext(FormContext);
16
+ const isReadOnly = !editable || postview;
17
+ const widthStyle = currentBreakPoint <= step.size ? '100%' : calcStepWidth(step.size, form.size);
18
+ const { ref, value, onChange, error } = useFormStep(step, {
19
+ defaultValue: step.defaultValue ?? null,
20
+ rules: {
21
+ required: step.required ? 'La ubicación es obligatoria' : undefined,
22
+ validate: (val) => {
23
+ if (!val)
24
+ return step.required ? 'La ubicación es obligatoria' : true;
25
+ if (val.source === LocationInputMode.MANUAL) {
26
+ // Un campo es obligatorio en manual solo si no está omitido (FIXED lo llena solo).
27
+ const detail = val.addressDetail;
28
+ const isRequired = (key) => fieldConfig(step.addressFields, key).mode !== AddressFieldMode.OMIT;
29
+ if (step.required && isRequired('street') && !detail?.street)
30
+ return 'Por favor completa la calle en el formulario manual.';
31
+ if (step.required && isRequired('city') && !detail?.city)
32
+ return 'Por favor completa la ciudad en el formulario manual.';
33
+ if (step.required && isRequired('country') && !detail?.country)
34
+ return 'Por favor completa el país en el formulario manual.';
35
+ return true;
36
+ }
37
+ if (val.latitude === undefined || val.longitude === undefined) {
38
+ return step.required ? 'Coordenadas geográficas no capturadas.' : true;
39
+ }
40
+ // Restricciones geográficas (radio / geofence).
41
+ return validateRestrictions(val.latitude, val.longitude, step.restrictions) ?? true;
42
+ },
43
+ },
44
+ });
45
+ return (_jsxs("div", { className: styles.container, style: { width: widthStyle }, children: [step.label && _jsxs("div", { className: styles.label, children: [step.label, step.required && _jsx("span", { className: styles.required, children: " *" })] }), _jsx(ErkLocationField, { value: value, onChange: onChange, allowedModes: step.allowedModes, defaultMode: step.defaultMode, addressFields: step.addressFields, helperText: error?.message ?? step.description, required: step.required, error: !!error, readOnly: isReadOnly, inputRef: ref })] }));
46
+ }
47
+ export default MaterialLocationStep;