@rolster/react-forms 19.4.12 → 19.4.14

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.
@@ -0,0 +1,904 @@
1
+ import { createFormArrayOptions, controlsToValue, hasError, someErrors, formArrayIsValid, verifyAllTrueInGroups, createFormControlOptions, formControlIsValid, createFormGroupOptions, formGroupIsValid, verifyAllTrueInControls, verifyAnyTrueInControls, reduceControlsToArray } from '@rolster/forms/helpers';
2
+ import { useRef, useState, useCallback, useEffect, useMemo } from 'react';
3
+ import { v4 } from 'uuid';
4
+
5
+ function refactorForValid$2(groups, validators) {
6
+ const errors = validators ? formArrayIsValid({ groups, validators }) : [];
7
+ return {
8
+ errors,
9
+ valid: errors.length === 0 && verifyAllTrueInGroups(groups, 'valid')
10
+ };
11
+ }
12
+ function refactorForGroups(groups, validators) {
13
+ return {
14
+ ...refactorForValid$2(groups, validators),
15
+ groups,
16
+ controls: groups.map(({ controls }) => controls),
17
+ value: groups.map(({ controls }) => controlsToValue(controls))
18
+ };
19
+ }
20
+ function refactorForControls$1(action, state, groups) {
21
+ switch (action) {
22
+ case 'validators':
23
+ return refactorForValid$2(groups, state.validators);
24
+ case 'reset':
25
+ case 'list':
26
+ case 'value':
27
+ return refactorForGroups(groups, state.validators);
28
+ default:
29
+ return { groups };
30
+ }
31
+ }
32
+ function useFormArray(options, validators) {
33
+ const formArray = createFormArrayOptions(options, validators);
34
+ const refArrayValue = useRef(formArray.groups || []);
35
+ const refArrayGroups = useRef(new Map());
36
+ const [state, setState] = useState(() => {
37
+ return {
38
+ ...refactorForValid$2(refArrayValue.current, formArray.validators),
39
+ controls: refArrayValue.current.map(({ controls }) => controls),
40
+ dirty: false,
41
+ dirties: false,
42
+ disabled: false,
43
+ groups: refArrayValue.current,
44
+ touched: false,
45
+ toucheds: false,
46
+ value: refArrayValue.current.map(({ controls }) => controlsToValue(controls)),
47
+ validators: formArray.validators
48
+ };
49
+ });
50
+ const subscriber = useCallback((action, group) => {
51
+ setState((state) => {
52
+ const groups = state.groups.map((currentGroup) => {
53
+ return currentGroup.uuid === group.uuid ? group : currentGroup;
54
+ });
55
+ return {
56
+ ...state,
57
+ ...refactorForControls$1(action, state, groups)
58
+ };
59
+ });
60
+ }, []);
61
+ useEffect(() => {
62
+ const previousGroups = refArrayGroups.current;
63
+ const currentGroups = new Map();
64
+ state.groups.forEach((group) => {
65
+ currentGroups.set(group.uuid, group);
66
+ if (previousGroups.get(group.uuid) !== group) {
67
+ group.subscribe(subscriber);
68
+ }
69
+ });
70
+ refArrayGroups.current = currentGroups;
71
+ }, [state.groups]);
72
+ const disable = useCallback(() => {
73
+ setState((state) => ({ ...state, disabled: true }));
74
+ }, []);
75
+ const enable = useCallback(() => {
76
+ setState((state) => ({ ...state, disabled: false }));
77
+ }, []);
78
+ const setValue = useCallback((groups) => {
79
+ setState((state) => ({
80
+ ...state,
81
+ ...refactorForGroups(groups, state.validators)
82
+ }));
83
+ }, []);
84
+ const setStartValue = useCallback((groups) => {
85
+ setState((state) => ({
86
+ ...state,
87
+ ...refactorForGroups(groups, state.validators)
88
+ }));
89
+ }, []);
90
+ const setDefaultValue = useCallback((groups) => {
91
+ setState((state) => ({
92
+ ...state,
93
+ ...refactorForGroups(groups, state.validators)
94
+ }));
95
+ refArrayValue.current = groups;
96
+ }, []);
97
+ const push = useCallback((group) => {
98
+ refArrayGroups.current.set(group.uuid, group);
99
+ group.subscribe(subscriber);
100
+ setState((state) => ({
101
+ ...state,
102
+ ...refactorForGroups([...state.groups, group], state.validators)
103
+ }));
104
+ }, []);
105
+ const merge = useCallback((groups) => {
106
+ groups.forEach((group) => {
107
+ group.subscribe(subscriber);
108
+ refArrayGroups.current.set(group.uuid, group);
109
+ });
110
+ setState((state) => ({
111
+ ...state,
112
+ ...refactorForGroups([...state.groups, ...groups], state.validators)
113
+ }));
114
+ }, []);
115
+ const remove = useCallback(({ uuid }) => {
116
+ refArrayGroups.current.delete(uuid);
117
+ setState((state) => ({
118
+ ...state,
119
+ ...refactorForGroups(state.groups.filter((group) => group.uuid !== uuid), state.validators)
120
+ }));
121
+ }, []);
122
+ const findByUuid = useCallback((uuid) => {
123
+ return refArrayGroups.current.get(uuid);
124
+ }, []);
125
+ const setValidators = useCallback((validators) => {
126
+ setState((state) => ({
127
+ ...state,
128
+ ...refactorForValid$2(state.groups, validators),
129
+ validators
130
+ }));
131
+ }, []);
132
+ const formArrayHasError = useCallback((key) => {
133
+ return hasError(state.errors, key);
134
+ }, [state.errors]);
135
+ const formArraySomeErrors = useCallback((keys) => {
136
+ return someErrors(state.errors, keys);
137
+ }, [state.errors]);
138
+ const reset = useCallback(() => {
139
+ refArrayValue.current.forEach((group) => group.reset());
140
+ refArrayGroups.current = new Map();
141
+ setState((state) => ({
142
+ ...state,
143
+ ...refactorForGroups(refArrayValue.current, state.validators)
144
+ }));
145
+ }, []);
146
+ return {
147
+ ...state,
148
+ disable,
149
+ enable,
150
+ enabled: !state.disabled,
151
+ error: state.errors[0],
152
+ findByUuid,
153
+ hasError: formArrayHasError,
154
+ invalid: !state.valid,
155
+ merge,
156
+ pristine: !state.dirty,
157
+ pristines: !state.dirties,
158
+ push,
159
+ remove,
160
+ reset,
161
+ setDefaultValue,
162
+ setStartValue,
163
+ setValidators,
164
+ setValue,
165
+ someErrors: formArraySomeErrors,
166
+ untouched: !state.touched,
167
+ untoucheds: !state.toucheds,
168
+ wrong: state.touched && !state.valid
169
+ };
170
+ }
171
+
172
+ class RolsterArrayControl {
173
+ constructor(options) {
174
+ this.uuid = options.uuid;
175
+ this.defaultValue = options.defaultValue;
176
+ this.value = options.value;
177
+ this.focused = !!options.focused;
178
+ this.unfocused = !this.focused;
179
+ this.touched = !!options.touched;
180
+ this.untouched = !this.touched;
181
+ this.dirty = !!options.dirty;
182
+ this.pristine = !this.dirty;
183
+ this.disabled = !!options.disabled;
184
+ this.enabled = !this.disabled;
185
+ this.valid = this.isValid(options.errors);
186
+ this.invalid = !this.valid;
187
+ this.wrong = this.touched && this.invalid;
188
+ this.errors = options.errors;
189
+ this.error = this.errors[0];
190
+ this.validators = options.validators;
191
+ }
192
+ focus() {
193
+ if (this.unfocused) {
194
+ this.refresh('focused', { focused: true });
195
+ }
196
+ }
197
+ blur() {
198
+ if (this.focused) {
199
+ this.refresh('focused', { focused: false, touched: true });
200
+ }
201
+ }
202
+ disable() {
203
+ if (this.enabled) {
204
+ this.refresh('disabled', { disabled: true });
205
+ }
206
+ }
207
+ enable() {
208
+ if (this.disabled) {
209
+ this.refresh('disabled', { disabled: false });
210
+ }
211
+ }
212
+ touch() {
213
+ if (this.untouched) {
214
+ this.refresh('touched', { touched: true });
215
+ }
216
+ }
217
+ setDefaultValue(value) {
218
+ if (value !== this.defaultValue) {
219
+ const errors = this.validators
220
+ ? formControlIsValid({ value, validators: this.validators })
221
+ : [];
222
+ this.refresh('value', { errors, defaultValue: value, value });
223
+ }
224
+ }
225
+ setStartValue(value) {
226
+ if (value !== this.value) {
227
+ const errors = this.validators
228
+ ? formControlIsValid({ value, validators: this.validators })
229
+ : [];
230
+ this.refresh('value', { errors, value });
231
+ }
232
+ }
233
+ setValue(value) {
234
+ if (value !== this.value) {
235
+ const errors = this.validators
236
+ ? formControlIsValid({ value, validators: this.validators })
237
+ : [];
238
+ this.refresh('value', { dirty: true, errors, value });
239
+ }
240
+ }
241
+ setValidators(validators) {
242
+ const errors = validators
243
+ ? formControlIsValid({ value: this.value, validators })
244
+ : [];
245
+ this.refresh('validators', { errors, validators });
246
+ }
247
+ subscribe(subscriber) {
248
+ this.subscriber = subscriber;
249
+ }
250
+ hasError(key) {
251
+ return hasError(this.errors, key);
252
+ }
253
+ someErrors(keys) {
254
+ return someErrors(this.errors, keys);
255
+ }
256
+ reset() {
257
+ const errors = this.validators
258
+ ? formControlIsValid({
259
+ value: this.defaultValue,
260
+ validators: this.validators
261
+ })
262
+ : [];
263
+ this.refresh('reset', {
264
+ dirty: false,
265
+ errors,
266
+ touched: false,
267
+ value: this.defaultValue
268
+ });
269
+ }
270
+ isValid(errors) {
271
+ return errors.length === 0;
272
+ }
273
+ builder(options) {
274
+ return new RolsterArrayControl({ ...this, ...options });
275
+ }
276
+ refresh(action, options) {
277
+ this.subscriber?.(action, this.builder(options));
278
+ }
279
+ }
280
+ class ReactRolsterArrayControl extends RolsterArrayControl {
281
+ constructor(options) {
282
+ const { value, validators } = options;
283
+ const errors = validators ? formControlIsValid({ value, validators }) : [];
284
+ super({ ...options, errors });
285
+ }
286
+ }
287
+ function rolsterArrayControl(options, validators) {
288
+ const formControl = createFormControlOptions(options, validators);
289
+ return new ReactRolsterArrayControl({
290
+ ...formControl,
291
+ defaultValue: formControl.value,
292
+ uuid: v4()
293
+ });
294
+ }
295
+ function reactArrayControl(options, validators) {
296
+ return rolsterArrayControl(options, validators);
297
+ }
298
+ function formArrayControl(options, validators) {
299
+ return rolsterArrayControl(options, validators);
300
+ }
301
+ function inputArrayControl(options, validators) {
302
+ return rolsterArrayControl(options, validators);
303
+ }
304
+ function areaArrayControl(options, validators) {
305
+ return rolsterArrayControl(options, validators);
306
+ }
307
+
308
+ function replaceControl(controls, control) {
309
+ return Object.entries(controls).reduce((controls, [key, _control]) => {
310
+ if (_control.uuid === control.uuid) {
311
+ controls[key] = control;
312
+ }
313
+ return controls;
314
+ }, { ...controls });
315
+ }
316
+
317
+ function refactorForValid$1(controls, validators) {
318
+ const errors = validators ? formGroupIsValid({ controls, validators }) : [];
319
+ return {
320
+ errors,
321
+ valid: errors.length === 0 && verifyAllTrueInControls(controls, 'valid')
322
+ };
323
+ }
324
+ function refactorForControls(action, group, controls) {
325
+ switch (action) {
326
+ case 'focused':
327
+ case 'touched':
328
+ return {
329
+ touched: verifyAnyTrueInControls(controls, 'touched'),
330
+ toucheds: verifyAllTrueInControls(controls, 'touched')
331
+ };
332
+ case 'validators':
333
+ return refactorForValid$1(controls, group.validators);
334
+ case 'reset':
335
+ return {
336
+ ...refactorForValid$1(controls, group.validators),
337
+ dirty: verifyAnyTrueInControls(controls, 'dirty'),
338
+ dirties: verifyAllTrueInControls(controls, 'dirty'),
339
+ touched: verifyAnyTrueInControls(controls, 'touched'),
340
+ toucheds: verifyAllTrueInControls(controls, 'touched'),
341
+ value: controlsToValue(controls)
342
+ };
343
+ case 'list':
344
+ case 'value':
345
+ return {
346
+ ...refactorForValid$1(controls, group.validators),
347
+ dirty: verifyAnyTrueInControls(controls, 'dirty'),
348
+ dirties: verifyAllTrueInControls(controls, 'dirty'),
349
+ value: controlsToValue(controls)
350
+ };
351
+ default:
352
+ return {};
353
+ }
354
+ }
355
+ class RolsterArrayGroup {
356
+ constructor(options) {
357
+ this.uuid = options.uuid;
358
+ this._controls = options.controls;
359
+ this.value = options.value;
360
+ this.resource = options.resource;
361
+ this.dirty = !!options.dirty;
362
+ this.dirties = !!options.dirties;
363
+ this.pristine = !this.dirty;
364
+ this.pristines = !this.dirties;
365
+ this.touched = !!options.touched;
366
+ this.toucheds = !!options.toucheds;
367
+ this.untouched = !this.touched;
368
+ this.untoucheds = !this.toucheds;
369
+ this.valid = !!options.valid;
370
+ this.invalid = !this.valid;
371
+ this.wrong = this.touched && this.invalid;
372
+ this.errors = options.errors;
373
+ this.error = this.errors[0];
374
+ this.validators = options.validators;
375
+ this.subscriberControl = (action, control) => {
376
+ const controls = replaceControl(this._controls, control);
377
+ this._controls = controls;
378
+ this.refresh(action, {
379
+ ...refactorForControls(action, this, controls),
380
+ controls
381
+ });
382
+ };
383
+ }
384
+ get controls() {
385
+ return this._controls;
386
+ }
387
+ subscribe(subscriber) {
388
+ this.subscriber = subscriber;
389
+ Object.values(this._controls).forEach((control) => {
390
+ control.subscribe(this.subscriberControl);
391
+ });
392
+ }
393
+ setValidators(validators) {
394
+ this.refresh('validators', {
395
+ ...refactorForValid$1(this._controls, validators),
396
+ validators
397
+ });
398
+ }
399
+ setResource(resource) {
400
+ this.refresh('resource', { resource });
401
+ }
402
+ reset() {
403
+ Object.values(this._controls).forEach((control) => {
404
+ control.reset();
405
+ });
406
+ }
407
+ refresh(action, options) {
408
+ if (this.subscriber) {
409
+ this.subscriber(action, new RolsterArrayGroup({
410
+ ...this,
411
+ ...options,
412
+ controls: this._controls
413
+ }));
414
+ }
415
+ }
416
+ }
417
+ class ReactRolsterArrayGroup extends RolsterArrayGroup {
418
+ constructor(options) {
419
+ const { controls, validators } = options;
420
+ const errors = validators ? formGroupIsValid({ controls, validators }) : [];
421
+ super({
422
+ ...options,
423
+ errors,
424
+ dirties: verifyAllTrueInControls(controls, 'dirty'),
425
+ dirty: verifyAnyTrueInControls(controls, 'dirty'),
426
+ touched: verifyAnyTrueInControls(controls, 'touched'),
427
+ toucheds: verifyAllTrueInControls(controls, 'touched'),
428
+ valid: errors.length === 0 && verifyAllTrueInControls(controls, 'valid'),
429
+ value: controlsToValue(controls)
430
+ });
431
+ }
432
+ }
433
+ function valueIsGroupOptions(options) {
434
+ return typeof options === 'object' && 'controls' in options;
435
+ }
436
+ function formArrayGroup(options, validators) {
437
+ const _uuid = valueIsGroupOptions(options) ? options.uuid || v4() : v4();
438
+ return new ReactRolsterArrayGroup({
439
+ ...createFormGroupOptions(options, validators),
440
+ uuid: _uuid
441
+ });
442
+ }
443
+
444
+ class RolsterArrayList extends RolsterArrayControl {
445
+ constructor(options) {
446
+ const { controls, controlsUuid, valueToControls, valueToUuid, validators } = options;
447
+ const value = controls.map(controlsToValue);
448
+ const errors = validators ? formControlIsValid({ value, validators }) : [];
449
+ super({ ...options, errors, value });
450
+ this.valueToControls = valueToControls;
451
+ this.valueToUuid = valueToUuid;
452
+ this._controls = controls;
453
+ this.controlsUuid = controlsUuid ?? controls.map(() => v4());
454
+ this.valid =
455
+ errors.length === 0 &&
456
+ controls.reduce((valid, controls) => valid && verifyAllTrueInControls(controls, 'valid'), true);
457
+ this.invalid = !this.valid;
458
+ this.wrong = this.touched && this.invalid;
459
+ controls.forEach((reactControls) => {
460
+ this._subscribe(reactControls);
461
+ });
462
+ }
463
+ get controls() {
464
+ return this._controls;
465
+ }
466
+ setDefaultValue(value) {
467
+ this.refresh('list', {
468
+ controls: value.map(this.valueToControls),
469
+ controlsUuid: this.generateControlsUuid(value),
470
+ defaultValue: value
471
+ });
472
+ }
473
+ setStartValue(value) {
474
+ this.refresh('list', {
475
+ controls: value.map(this.valueToControls),
476
+ controlsUuid: this.generateControlsUuid(value)
477
+ });
478
+ }
479
+ setValue(value) {
480
+ this.refresh('list', {
481
+ controls: value.map(this.valueToControls),
482
+ controlsUuid: this.generateControlsUuid(value),
483
+ dirty: true
484
+ });
485
+ }
486
+ reset() {
487
+ this.refresh('list', {
488
+ controls: this.defaultValue.map(this.valueToControls),
489
+ controlsUuid: this.generateControlsUuid(this.defaultValue),
490
+ dirty: false,
491
+ touched: false
492
+ });
493
+ }
494
+ push(controls) {
495
+ const _uuid = this.valueToUuid?.(controlsToValue(controls)) ?? v4();
496
+ this.refresh('list', {
497
+ controls: [...this._controls, controls],
498
+ controlsUuid: [...this.controlsUuid, _uuid]
499
+ });
500
+ }
501
+ remove(controls) {
502
+ const _controls = [];
503
+ const _controlsUuid = [];
504
+ this._controls.forEach((currentControls, index) => {
505
+ if (currentControls !== controls) {
506
+ _controls.push(currentControls);
507
+ _controlsUuid.push(this.controlsUuid[index]);
508
+ }
509
+ });
510
+ this.refresh('list', {
511
+ controls: _controls,
512
+ controlsUuid: _controlsUuid
513
+ });
514
+ }
515
+ findControlsByUuid(uuid) {
516
+ const index = this.controlsUuid.indexOf(uuid);
517
+ return index >= 0 ? this._controls[index] : undefined;
518
+ }
519
+ builder(options) {
520
+ return new RolsterArrayList({
521
+ ...this,
522
+ ...options,
523
+ valueToControls: this.valueToControls,
524
+ valueToUuid: this.valueToUuid
525
+ });
526
+ }
527
+ refresh(action, options) {
528
+ super.refresh(action, options);
529
+ }
530
+ generateControlsUuid(values) {
531
+ return values.map((value) => this.valueToUuid?.(value) ?? v4());
532
+ }
533
+ _subscribe(controls) {
534
+ Object.values(controls).forEach((control) => {
535
+ control.subscribe((action, _control) => {
536
+ const _controls = this._controls.map((_controls) => {
537
+ const currentControl = Object.values(_controls).some((currentControl) => currentControl.uuid === _control.uuid);
538
+ return currentControl
539
+ ? replaceControl(_controls, _control)
540
+ : _controls;
541
+ });
542
+ this._controls = _controls;
543
+ this.refresh(action, { controls: _controls });
544
+ });
545
+ });
546
+ }
547
+ }
548
+ function formArrayList(options) {
549
+ const { valueToControls, valueToUuid } = options;
550
+ const value = options?.value || [];
551
+ return new RolsterArrayList({
552
+ ...options,
553
+ controls: value.map(valueToControls),
554
+ controlsUuid: value.map((v) => valueToUuid?.(v) ?? v4()),
555
+ defaultValue: value,
556
+ uuid: v4()
557
+ });
558
+ }
559
+
560
+ function errorsInControl(value, validators) {
561
+ return validators ? formControlIsValid({ value, validators }) : [];
562
+ }
563
+
564
+ function useControl(options, validators) {
565
+ const formControl = createFormControlOptions(options, validators);
566
+ const defaultValue = useRef(formControl.value);
567
+ const [state, setState] = useState(() => {
568
+ return {
569
+ dirty: false,
570
+ disabled: false,
571
+ errors: errorsInControl(formControl.value, formControl.validators),
572
+ focused: false,
573
+ touched: !!formControl.touched,
574
+ value: formControl.value,
575
+ validators: formControl.validators
576
+ };
577
+ });
578
+ const elementRef = useRef(null);
579
+ const focus = useCallback(() => {
580
+ setState((state) => ({ ...state, focused: true }));
581
+ }, []);
582
+ const blur = useCallback(() => {
583
+ setState((state) => ({ ...state, focused: false, touched: true }));
584
+ }, []);
585
+ const disable = useCallback(() => {
586
+ setState((state) => ({ ...state, disabled: true }));
587
+ }, []);
588
+ const enable = useCallback(() => {
589
+ setState((state) => ({ ...state, disabled: false }));
590
+ }, []);
591
+ const touch = useCallback(() => {
592
+ setState((state) => ({ ...state, touched: true }));
593
+ }, []);
594
+ const setDefaultValue = useCallback((value) => {
595
+ defaultValue.current = value;
596
+ setState((state) => ({
597
+ ...state,
598
+ errors: errorsInControl(value, state.validators),
599
+ value
600
+ }));
601
+ }, []);
602
+ const setStartValue = useCallback((value) => {
603
+ setState((state) => ({
604
+ ...state,
605
+ errors: errorsInControl(value, state.validators),
606
+ value
607
+ }));
608
+ }, []);
609
+ const setValue = useCallback((value) => {
610
+ setState((state) => ({
611
+ ...state,
612
+ dirty: true,
613
+ errors: errorsInControl(value, state.validators),
614
+ value
615
+ }));
616
+ }, []);
617
+ const setValidators = useCallback((validators) => {
618
+ setState((state) => ({
619
+ ...state,
620
+ errors: errorsInControl(state.value, validators),
621
+ validators
622
+ }));
623
+ }, []);
624
+ const reset = useCallback(() => {
625
+ setState((state) => ({
626
+ ...state,
627
+ dirty: false,
628
+ errors: errorsInControl(defaultValue.current, state.validators),
629
+ value: defaultValue.current,
630
+ touched: false
631
+ }));
632
+ }, []);
633
+ const formControlHasError = useCallback((key) => {
634
+ return hasError(state.errors, key);
635
+ }, [state.errors]);
636
+ const formControlSomeErrors = useCallback((keys) => {
637
+ return someErrors(state.errors, keys);
638
+ }, [state.errors]);
639
+ const valid = state.errors.length === 0;
640
+ return {
641
+ ...state,
642
+ blur,
643
+ disable,
644
+ elementRef,
645
+ enable,
646
+ enabled: !state.disabled,
647
+ error: state.errors[0],
648
+ focus,
649
+ hasError: formControlHasError,
650
+ invalid: !valid,
651
+ pristine: !state.dirty,
652
+ reset,
653
+ setDefaultValue,
654
+ setStartValue,
655
+ setValidators,
656
+ setValue,
657
+ someErrors: formControlSomeErrors,
658
+ touch,
659
+ unfocused: !state.focused,
660
+ untouched: !state.touched,
661
+ valid,
662
+ wrong: state.touched && !valid
663
+ };
664
+ }
665
+ function useReactControl(options, validators) {
666
+ return useControl(options, validators);
667
+ }
668
+ function useFormControl(options, validators) {
669
+ return useControl(options, validators);
670
+ }
671
+ function useInputControl(options, validators) {
672
+ return useControl(options, validators);
673
+ }
674
+ function useAreaControl(options, validators) {
675
+ return useControl(options, validators);
676
+ }
677
+
678
+ function refactorForValid(controls, validators) {
679
+ const errors = validators ? formGroupIsValid({ controls, validators }) : [];
680
+ return {
681
+ errors,
682
+ valid: errors.length === 0 && verifyAllTrueInControls(controls, 'valid')
683
+ };
684
+ }
685
+ function checkAllSuccess(status) {
686
+ return status.every((value) => value);
687
+ }
688
+ function checkPartialSuccess(status) {
689
+ return status.some((value) => value);
690
+ }
691
+ function arraysShallowEqual(a, b) {
692
+ if (a === b) {
693
+ return true;
694
+ }
695
+ if (a.length !== b.length) {
696
+ return false;
697
+ }
698
+ for (let i = 0; i < a.length; i++) {
699
+ if (a[i] !== b[i]) {
700
+ return false;
701
+ }
702
+ }
703
+ return true;
704
+ }
705
+ function useFormGroup(options, validators) {
706
+ const formGroup = createFormGroupOptions(options, validators);
707
+ const refControls = useRef(formGroup.controls);
708
+ refControls.current = formGroup.controls;
709
+ const formGroupStatus = useMemo(() => {
710
+ const dirty = [];
711
+ const disabled = [];
712
+ const focused = [];
713
+ const touched = [];
714
+ const value = [];
715
+ Object.values(formGroup.controls).forEach((control) => {
716
+ dirty.push(control.dirty);
717
+ disabled.push(control.disabled);
718
+ focused.push(control.focused);
719
+ touched.push(control.touched);
720
+ value.push(control.value);
721
+ });
722
+ return {
723
+ dirty,
724
+ disabled,
725
+ focused,
726
+ touched,
727
+ value
728
+ };
729
+ }, [formGroup.controls]);
730
+ const [state, setState] = useState(() => {
731
+ return {
732
+ ...refactorForValid(formGroup.controls, formGroup.validators),
733
+ dirties: checkAllSuccess(formGroupStatus.dirty),
734
+ dirty: checkPartialSuccess(formGroupStatus.dirty),
735
+ touched: checkPartialSuccess(formGroupStatus.touched),
736
+ toucheds: checkAllSuccess(formGroupStatus.touched),
737
+ validators: formGroup.validators,
738
+ value: controlsToValue(formGroup.controls)
739
+ };
740
+ });
741
+ const refPrevFormGroupStatus = useRef(null);
742
+ useEffect(() => {
743
+ const formGroupPrev = refPrevFormGroupStatus.current;
744
+ refPrevFormGroupStatus.current = formGroupStatus;
745
+ if (!formGroupPrev) {
746
+ return;
747
+ }
748
+ const valueChanged = !arraysShallowEqual(formGroupPrev.value, formGroupStatus.value);
749
+ const dirtyChanged = !arraysShallowEqual(formGroupPrev.dirty, formGroupStatus.dirty);
750
+ const touchedChanged = !arraysShallowEqual(formGroupPrev.touched, formGroupStatus.touched);
751
+ const disabledChanged = !arraysShallowEqual(formGroupPrev.disabled, formGroupStatus.disabled);
752
+ const focusedChanged = !arraysShallowEqual(formGroupPrev.focused, formGroupStatus.focused);
753
+ if (!valueChanged &&
754
+ !dirtyChanged &&
755
+ !touchedChanged &&
756
+ !disabledChanged &&
757
+ !focusedChanged) {
758
+ return;
759
+ }
760
+ setState((state) => {
761
+ const next = { ...state };
762
+ if (valueChanged) {
763
+ const validResult = refactorForValid(refControls.current, state.validators);
764
+ next.errors = validResult.errors;
765
+ next.valid = validResult.valid;
766
+ next.value = controlsToValue(refControls.current);
767
+ }
768
+ if (dirtyChanged) {
769
+ next.dirty = checkPartialSuccess(formGroupStatus.dirty);
770
+ next.dirties = checkAllSuccess(formGroupStatus.dirty);
771
+ }
772
+ if (touchedChanged) {
773
+ next.touched = checkPartialSuccess(formGroupStatus.touched);
774
+ next.toucheds = checkAllSuccess(formGroupStatus.touched);
775
+ }
776
+ return next;
777
+ });
778
+ });
779
+ const setValidators = useCallback((validators) => {
780
+ setState((state) => ({
781
+ ...state,
782
+ ...refactorForValid(refControls.current, validators),
783
+ validators
784
+ }));
785
+ }, []);
786
+ const setValue = useCallback((value) => {
787
+ Object.entries(value).forEach(([key, valueControl]) => {
788
+ const formControl = refControls.current[key];
789
+ formControl?.setValue(valueControl);
790
+ });
791
+ }, []);
792
+ const reset = useCallback(() => {
793
+ Object.values(refControls.current).forEach((control) => {
794
+ control.reset();
795
+ });
796
+ }, []);
797
+ return {
798
+ ...state,
799
+ controls: formGroup.controls,
800
+ error: state.errors[0],
801
+ invalid: !state.valid,
802
+ pristine: !state.dirty,
803
+ pristines: !state.dirties,
804
+ reset,
805
+ setValidators,
806
+ setValue,
807
+ untouched: !state.touched,
808
+ untoucheds: !state.toucheds,
809
+ wrong: state.touched && !state.valid
810
+ };
811
+ }
812
+
813
+ function useReactList(value, validators) {
814
+ const control = useReactControl(value || [], validators);
815
+ const push = useCallback((item) => {
816
+ control.setValue([...control.value, item]);
817
+ }, [control.value, control.setValue]);
818
+ const remove = useCallback((item) => {
819
+ const value = control.value.filter((current) => current !== item);
820
+ if (value.length !== control.value.length) {
821
+ control.setValue(value);
822
+ }
823
+ }, [control.value, control.setValue]);
824
+ const clear = useCallback(() => {
825
+ if (control.value.length > 0) {
826
+ control.setValue([]);
827
+ }
828
+ }, [control.value, control.setValue]);
829
+ return {
830
+ ...control,
831
+ clear,
832
+ push,
833
+ remove
834
+ };
835
+ }
836
+ function useFormList(value, validators) {
837
+ return useReactList(value, validators);
838
+ }
839
+
840
+ function useInputRefControl(options) {
841
+ const formRef = useInputControl(options);
842
+ const setValueRef = useRef(options.setValue);
843
+ setValueRef.current = options.setValue;
844
+ useEffect(() => {
845
+ const element = formRef.elementRef?.current;
846
+ if (!element) {
847
+ return;
848
+ }
849
+ const handleFocus = () => {
850
+ formRef.focus();
851
+ };
852
+ const handleBlur = () => {
853
+ formRef.blur();
854
+ };
855
+ const handleChange = (event) => {
856
+ const target = event.target;
857
+ setValueRef.current(formRef, target.value);
858
+ };
859
+ element.addEventListener('focus', handleFocus);
860
+ element.addEventListener('blur', handleBlur);
861
+ element.addEventListener('change', handleChange);
862
+ return () => {
863
+ element.removeEventListener('focus', handleFocus);
864
+ element.removeEventListener('blur', handleBlur);
865
+ element.removeEventListener('change', handleChange);
866
+ };
867
+ }, []);
868
+ return formRef;
869
+ }
870
+ function useTextRefControl(options, validators) {
871
+ return useInputRefControl({
872
+ ...createFormControlOptions(options, validators),
873
+ setValue: (control, value) => {
874
+ control.setValue(value);
875
+ }
876
+ });
877
+ }
878
+ function useNumberRefControl(options, validators) {
879
+ return useInputRefControl({
880
+ ...createFormControlOptions(options, validators),
881
+ setValue: (control, value) => {
882
+ control.setValue(+value);
883
+ }
884
+ });
885
+ }
886
+
887
+ function reduceControlsToValues(controls) {
888
+ return reduceControlsToArray(controls, 'value');
889
+ }
890
+ function reduceGroupToValues(group) {
891
+ return reduceControlsToValues(group.controls);
892
+ }
893
+
894
+ function useFormArrayGroupSelect({ formArray }) {
895
+ const [formSelect, setFormGroup] = useState();
896
+ const formGroup = useMemo(() => {
897
+ return (formSelect &&
898
+ formArray.groups.find(({ uuid }) => formSelect.uuid === uuid));
899
+ }, [formArray.value, formSelect]);
900
+ return { formGroup, setFormGroup };
901
+ }
902
+
903
+ export { areaArrayControl, formArrayControl, formArrayGroup, formArrayList, inputArrayControl, reactArrayControl, reduceControlsToValues, reduceGroupToValues, useAreaControl, useFormArray, useFormArrayGroupSelect, useFormControl, useFormGroup, useFormList, useInputControl, useNumberRefControl, useReactControl, useReactList, useTextRefControl };
904
+ //# sourceMappingURL=index.mjs.map