gform-react 2.0.1 → 2.5.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.
- package/dist/cjs/gform-react.development.js +274 -205
- package/dist/cjs/gform-react.development.js.map +1 -1
- package/dist/cjs/gform-react.production.js +1 -1
- package/dist/cjs/gform-react.production.js.map +1 -1
- package/dist/esm/GForm.production.js +1 -1
- package/dist/esm/GForm.production.js.map +1 -1
- package/dist/esm/GInput.production.js +1 -1
- package/dist/esm/GInput.production.js.map +1 -1
- package/dist/esm/index.development.js +280 -210
- package/dist/esm/index.development.js.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/shared.production.js +1 -1
- package/dist/esm/shared.production.js.map +1 -1
- package/dist/index.d.ts +5 -12
- package/native/dist/cjs/gform-react-native.development.js +219 -281
- package/native/dist/cjs/gform-react-native.development.js.map +1 -1
- package/native/dist/cjs/gform-react-native.production.js +1 -1
- package/native/dist/cjs/gform-react-native.production.js.map +1 -1
- package/native/dist/esm/RNGForm.production.js +1 -1
- package/native/dist/esm/RNGForm.production.js.map +1 -1
- package/native/dist/esm/RNGInput.production.js +1 -1
- package/native/dist/esm/RNGInput.production.js.map +1 -1
- package/native/dist/esm/index.development.js +225 -285
- package/native/dist/esm/index.development.js.map +1 -1
- package/native/dist/esm/shared.production.js +1 -1
- package/native/dist/esm/shared.production.js.map +1 -1
- package/native/dist/index.d.ts +4 -8
- package/package.json +2 -2
|
@@ -72,10 +72,7 @@ const _buildFormInitialValues = (rows = []) => {
|
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
74
|
return {
|
|
75
|
-
|
|
76
|
-
fields,
|
|
77
|
-
loading: false
|
|
78
|
-
},
|
|
75
|
+
fields: fields,
|
|
79
76
|
key: generateId()
|
|
80
77
|
};
|
|
81
78
|
};
|
|
@@ -99,6 +96,26 @@ const _findValidityKey = validity => {
|
|
|
99
96
|
}
|
|
100
97
|
}
|
|
101
98
|
};
|
|
99
|
+
const _checkTypeMismatch = input => {
|
|
100
|
+
var _input$value;
|
|
101
|
+
const value = (_input$value = input.value) === null || _input$value === void 0 ? void 0 : _input$value.toString().trim();
|
|
102
|
+
if (!value) return false;
|
|
103
|
+
switch (input.type) {
|
|
104
|
+
case 'email':
|
|
105
|
+
return !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
106
|
+
case 'url':
|
|
107
|
+
try {
|
|
108
|
+
new URL(value);
|
|
109
|
+
return false;
|
|
110
|
+
} catch {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
case 'tel':
|
|
114
|
+
return !/^\+?[0-9\s\-().]{7,}$/.test(value);
|
|
115
|
+
default:
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
102
119
|
const hasSubmitter = form => {
|
|
103
120
|
if (!form) return false;
|
|
104
121
|
for (const element of form) {
|
|
@@ -106,14 +123,6 @@ const hasSubmitter = form => {
|
|
|
106
123
|
}
|
|
107
124
|
return false;
|
|
108
125
|
};
|
|
109
|
-
const _checkIfFormIsValid = fields => {
|
|
110
|
-
for (const f in fields) {
|
|
111
|
-
if (fields[f].error) {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return true;
|
|
116
|
-
};
|
|
117
126
|
const _toRawData = (fields, options = {}) => {
|
|
118
127
|
const data = {};
|
|
119
128
|
const {
|
|
@@ -314,39 +323,13 @@ class GValidator {
|
|
|
314
323
|
}
|
|
315
324
|
}
|
|
316
325
|
|
|
317
|
-
const
|
|
318
|
-
const initialValues = React.useMemo(() => {
|
|
319
|
-
const values = _buildFormInitialValues(typeof children === 'function' ? children({}) : children);
|
|
320
|
-
{
|
|
321
|
-
Object.keys(values.state.fields).forEach(key => {
|
|
322
|
-
const input = values.state.fields[key];
|
|
323
|
-
const validator = validators[key];
|
|
324
|
-
if (validator instanceof GValidator) {
|
|
325
|
-
var _validator$track;
|
|
326
|
-
const validityKeys = (_validator$track = validator.track) === null || _validator$track === void 0 ? void 0 : _validator$track.filter(key => validityMap[key]);
|
|
327
|
-
validityKeys === null || validityKeys === void 0 || validityKeys.forEach(vKey => {
|
|
328
|
-
if (typeof input[validityMap[vKey]] === 'undefined') {
|
|
329
|
-
console.warn(`[Missing Prop] - the input '${input.formKey}' has registered validator for the violation '${vKey}' but the input hasn't described the constraint '${validityMap[vKey]}'.\nadd '${validityMap[vKey]}' to the input props.\nexample:\n<GInput formKey='${input.formKey}' ${validityMap[vKey]}={...} />\n\nor either remove '.${handlersMap[validityMap[vKey]]}(...)' validation`);
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
Object.entries(validityMap).forEach(([validityKey, constraint]) => {
|
|
333
|
-
var _validator$track2;
|
|
334
|
-
if (typeof input[constraint] !== 'undefined' && !((_validator$track2 = validator.track) !== null && _validator$track2 !== void 0 && _validator$track2.some(trackKey => validityKey === trackKey))) {
|
|
335
|
-
console.warn(`[Missing Validator] - the input '${input.formKey}' has described the constraint '${constraint}' but the input hasn't registered a validator to handle it.\nregister a handler '${handlersMap[constraint]}' for the input validator to handle the '${validityKey}' violation.\nexample:\ncosnt validators = {\n\t${input.formKey}: new GValidator().${handlersMap[constraint]}(...)\n}`);
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
return values;
|
|
342
|
-
}, []);
|
|
343
|
-
const [state, setState] = React.useState(initialValues.state);
|
|
326
|
+
const useFormHandlers = (getState, setState, validators = {}, optimized = false) => {
|
|
344
327
|
const _viHandler = (input, e) => {
|
|
345
328
|
if (!input) return;
|
|
346
329
|
const element = e && e.target;
|
|
347
330
|
if (typeof document !== 'undefined' && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)) {
|
|
348
331
|
if (!input.checkValidity) input.checkValidity = () => element.checkValidity();
|
|
349
|
-
if (!input.dirty && input.value) {
|
|
332
|
+
if (!input.dirty && input.value && !input.touched) {
|
|
350
333
|
_checkInputManually(input);
|
|
351
334
|
_dispatchChanges(input, input.formKey);
|
|
352
335
|
return;
|
|
@@ -367,6 +350,7 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
367
350
|
const _checkInputManually = input => {
|
|
368
351
|
let validityKey = _findValidityKey({
|
|
369
352
|
valueMissing: input.required && !input.value || false,
|
|
353
|
+
typeMismatch: _checkTypeMismatch(input),
|
|
370
354
|
tooShort: input.minLength && input.value.toString().length < input.minLength || false,
|
|
371
355
|
tooLong: input.maxLength && input.value.toString().length > input.maxLength || false,
|
|
372
356
|
patternMismatch: input.pattern && _checkResult(input.pattern, input.value) || false,
|
|
@@ -379,22 +363,17 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
379
363
|
_validateInput(input, validityKey);
|
|
380
364
|
return !input.error;
|
|
381
365
|
};
|
|
382
|
-
const _updateInputHandler = (
|
|
383
|
-
|
|
384
|
-
const input = _updateInput(key, value);
|
|
366
|
+
const _updateInputHandler = (input, e, unknown) => {
|
|
367
|
+
input.value = _extractValue(e, unknown);
|
|
385
368
|
_viHandler(input, e);
|
|
386
369
|
};
|
|
387
370
|
const _validateInput = (input, validityKey, setValidity) => {
|
|
388
371
|
const inputValidator = validators[input.validatorKey || input.formKey] || validators['*'];
|
|
389
|
-
|
|
372
|
+
if (inputValidator) {
|
|
373
|
+
__validateInput(input, inputValidator, validityKey, setValidity);
|
|
374
|
+
}
|
|
390
375
|
input.touched = true;
|
|
391
376
|
};
|
|
392
|
-
const _updateInput = (key, value) => {
|
|
393
|
-
const input = state.fields[key];
|
|
394
|
-
input.value = value;
|
|
395
|
-
input.dirty = true;
|
|
396
|
-
return input;
|
|
397
|
-
};
|
|
398
377
|
const _dispatchChanges = (changes, key) => setState(prev => {
|
|
399
378
|
if (key) {
|
|
400
379
|
return {
|
|
@@ -414,13 +393,14 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
414
393
|
};
|
|
415
394
|
});
|
|
416
395
|
const __validateInput = (input, inputValidator, validityKey, setValidity) => {
|
|
396
|
+
const fields = getState().fields;
|
|
417
397
|
for (const index in inputValidator.constraintHandlers) {
|
|
418
398
|
const result = inputValidator.constraintHandlers[index](input, validityKey);
|
|
419
399
|
input.error = _checkResult(result, input.value);
|
|
420
400
|
if (input.error) return;
|
|
421
401
|
}
|
|
422
402
|
for (const index in inputValidator.handlers) {
|
|
423
|
-
const result = inputValidator.handlers[index](input,
|
|
403
|
+
const result = inputValidator.handlers[index](input, fields);
|
|
424
404
|
input.error = _checkResult(result, input.value);
|
|
425
405
|
if (input.error) return;
|
|
426
406
|
}
|
|
@@ -430,7 +410,7 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
430
410
|
_debounce(input.debounce || 300, `${input.gid}-async`).then(() => {
|
|
431
411
|
const validateAsync = async () => {
|
|
432
412
|
for (const index in inputValidator.asyncHandlers) {
|
|
433
|
-
const result = await inputValidator.asyncHandlers[index](input,
|
|
413
|
+
const result = await inputValidator.asyncHandlers[index](input, fields);
|
|
434
414
|
input.error = _checkResult(result, input.value);
|
|
435
415
|
if (input.error) break;
|
|
436
416
|
}
|
|
@@ -439,184 +419,260 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
439
419
|
error: input.error,
|
|
440
420
|
errorText: input.errorText
|
|
441
421
|
}, input.formKey);
|
|
442
|
-
|
|
422
|
+
if (setValidity) {
|
|
423
|
+
setValidity(input.errorText);
|
|
424
|
+
}
|
|
443
425
|
};
|
|
444
426
|
validateAsync();
|
|
445
427
|
});
|
|
446
428
|
}
|
|
447
429
|
};
|
|
448
430
|
return {
|
|
449
|
-
state,
|
|
450
431
|
_updateInputHandler,
|
|
451
432
|
_viHandler,
|
|
452
433
|
_dispatchChanges,
|
|
453
434
|
optimized,
|
|
454
|
-
key: initialValues.key,
|
|
455
435
|
_createInputChecker: _checkInputManually
|
|
456
436
|
};
|
|
457
437
|
};
|
|
458
438
|
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
439
|
+
const GFormContext = React.createContext({});
|
|
440
|
+
const GFormContextProvider = ({
|
|
441
|
+
children,
|
|
442
|
+
initialState,
|
|
443
|
+
validators,
|
|
444
|
+
optimized
|
|
445
|
+
}) => {
|
|
446
|
+
const stateRef = React.useRef(initialState);
|
|
447
|
+
const listeners = React.useRef(new Set());
|
|
448
|
+
const setState = React.useCallback(updater => {
|
|
449
|
+
stateRef.current = typeof updater === 'function' ? updater(stateRef.current) : updater;
|
|
450
|
+
listeners.current.forEach(l => l());
|
|
451
|
+
}, []);
|
|
452
|
+
const handlers = useFormHandlers(() => stateRef.current, setState, validators, optimized);
|
|
453
|
+
const getState = React.useCallback(() => stateRef.current, []);
|
|
454
|
+
const subscribe = React.useCallback(listener => {
|
|
455
|
+
listeners.current.add(listener);
|
|
456
|
+
return () => listeners.current.delete(listener);
|
|
457
|
+
}, []);
|
|
458
|
+
React.useEffect(() => {
|
|
459
|
+
for (const fieldKey in initialState.fields) {
|
|
460
|
+
initialState.fields[fieldKey].dispatchChanges = changes => handlers._dispatchChanges(changes, fieldKey);
|
|
461
|
+
}
|
|
462
|
+
}, []);
|
|
463
|
+
const store = React.useRef({
|
|
464
|
+
getState,
|
|
465
|
+
setState,
|
|
466
|
+
subscribe,
|
|
467
|
+
handlers
|
|
468
|
+
});
|
|
469
|
+
return React.createElement(GFormContext.Provider, {
|
|
470
|
+
value: store.current
|
|
471
|
+
}, children);
|
|
472
|
+
};
|
|
473
|
+
const useFormStore = () => {
|
|
474
|
+
const store = React.useContext(GFormContext);
|
|
475
|
+
if (!store) throw new Error('useGFormStore must be used within `GForm` component');
|
|
476
|
+
return store;
|
|
477
|
+
};
|
|
478
|
+
const useFormSelector = selector => {
|
|
479
|
+
const store = useFormStore();
|
|
480
|
+
return React.useSyncExternalStore(store.subscribe, () => selector(store.getState()), () => selector(store.getState()));
|
|
481
|
+
};
|
|
482
|
+
function createSelector(selectors, combiner) {
|
|
483
|
+
let lastArgs = [];
|
|
484
|
+
let lastResult;
|
|
485
|
+
return state => {
|
|
486
|
+
const args = selectors.map(fn => fn(state));
|
|
487
|
+
if (lastArgs.length === args.length && args.every((val, i) => val === lastArgs[i])) {
|
|
488
|
+
return lastResult;
|
|
489
|
+
}
|
|
490
|
+
lastArgs = args;
|
|
491
|
+
lastResult = combiner(...args);
|
|
492
|
+
return lastResult;
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const selectFields = [state => state.fields];
|
|
497
|
+
const selectFirstInvalidField = createSelector(selectFields, fields => {
|
|
498
|
+
for (const f in fields) {
|
|
499
|
+
if (fields[f].error) {
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return false;
|
|
504
|
+
});
|
|
505
|
+
const makeSelectFields = (keys = []) => createSelector(selectFields, fields => {
|
|
506
|
+
const selected = keys.map(key => fields[key]).filter(Boolean);
|
|
507
|
+
return selected.length ? selected : null;
|
|
470
508
|
});
|
|
471
|
-
const useGenericFormContext = () => React.useContext(gFormContext);
|
|
472
|
-
const GFormContextProvider = gFormContext.Provider;
|
|
473
509
|
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
if (ref) {
|
|
498
|
-
if (typeof ref === 'function') {
|
|
499
|
-
ref(element);
|
|
500
|
-
} else {
|
|
501
|
-
ref.current = element;
|
|
502
|
-
}
|
|
510
|
+
const FormRenderer = React.forwardRef(({
|
|
511
|
+
stateRef,
|
|
512
|
+
onSubmit,
|
|
513
|
+
onChange,
|
|
514
|
+
onPaste,
|
|
515
|
+
onKeyDown,
|
|
516
|
+
onKeyUp,
|
|
517
|
+
children,
|
|
518
|
+
onInit,
|
|
519
|
+
...rest
|
|
520
|
+
}, ref) => {
|
|
521
|
+
const formRef = React.useRef(null);
|
|
522
|
+
const {
|
|
523
|
+
getState,
|
|
524
|
+
handlers
|
|
525
|
+
} = useFormStore();
|
|
526
|
+
const isFormInvalid = useFormSelector(selectFirstInvalidField);
|
|
527
|
+
const refHandler = React.useCallback(element => {
|
|
528
|
+
if (ref) {
|
|
529
|
+
if (typeof ref === 'function') {
|
|
530
|
+
ref(element);
|
|
531
|
+
} else {
|
|
532
|
+
ref.current = element;
|
|
503
533
|
}
|
|
504
|
-
|
|
534
|
+
}
|
|
535
|
+
formRef.current = element;
|
|
536
|
+
}, [ref]);
|
|
537
|
+
const getFormState = React.useCallback(() => {
|
|
538
|
+
const fields = getState().fields;
|
|
539
|
+
const formState = {
|
|
540
|
+
...fields,
|
|
541
|
+
isValid: !isFormInvalid,
|
|
542
|
+
isInvalid: isFormInvalid,
|
|
543
|
+
toRawData: options => _toRawData(fields, options),
|
|
544
|
+
toFormData: () => _toFormData(formRef.current),
|
|
545
|
+
toURLSearchParams: _toURLSearchParams,
|
|
546
|
+
checkValidity: function () {
|
|
547
|
+
this.isValid = formRef.current && formRef.current.checkValidity() || false;
|
|
548
|
+
this.isInvalid = !this.isValid;
|
|
549
|
+
return this.isValid;
|
|
550
|
+
},
|
|
551
|
+
dispatchChanges: changes => handlers._dispatchChanges({
|
|
552
|
+
fields: _merge({}, fields, changes)
|
|
553
|
+
})
|
|
505
554
|
};
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
checkValidity: function () {
|
|
517
|
-
this.isValid = formRef.current && formRef.current.checkValidity() || false;
|
|
518
|
-
this.isInvalid = !this.isValid;
|
|
519
|
-
return this.isValid;
|
|
520
|
-
},
|
|
521
|
-
setLoading: p => _dispatchChanges({
|
|
522
|
-
loading: typeof p === 'function' ? p(state.loading) : p
|
|
523
|
-
}),
|
|
524
|
-
dispatchChanges: changes => _dispatchChanges({
|
|
525
|
-
fields: _merge({}, state.fields, changes)
|
|
526
|
-
})
|
|
527
|
-
};
|
|
528
|
-
if (stateRef) stateRef.current = formState;
|
|
529
|
-
return formState;
|
|
530
|
-
}, [state.fields]);
|
|
531
|
-
const formComponent = React.useMemo(() => {
|
|
532
|
-
const formChildren = typeof children === 'function' ? children(formState) : children;
|
|
533
|
-
const _onSubmit = e => {
|
|
534
|
-
if (formState.isValid && onSubmit) {
|
|
535
|
-
onSubmit(formState, e);
|
|
536
|
-
}
|
|
537
|
-
};
|
|
538
|
-
let _onPaste;
|
|
539
|
-
if (onPaste) {
|
|
540
|
-
_onPaste = e => onPaste(formState, e);
|
|
555
|
+
if (stateRef) stateRef.current = formState;
|
|
556
|
+
return formState;
|
|
557
|
+
}, [isFormInvalid]);
|
|
558
|
+
const formComponent = React.useMemo(() => {
|
|
559
|
+
const state = getFormState();
|
|
560
|
+
const formChildren = typeof children === 'function' ? children(state) : children;
|
|
561
|
+
const _onSubmit = e => {
|
|
562
|
+
const state = getFormState();
|
|
563
|
+
if (state.isValid && onSubmit) {
|
|
564
|
+
onSubmit(state, e);
|
|
541
565
|
}
|
|
542
|
-
|
|
566
|
+
};
|
|
567
|
+
let _onPaste, _onChange, _onKeyDown, _onKeyUp;
|
|
568
|
+
if (onPaste) {
|
|
569
|
+
_onPaste = e => onPaste(state, e);
|
|
570
|
+
}
|
|
571
|
+
if (onKeyDown) {
|
|
572
|
+
_onKeyDown = e => onKeyDown(state, e);
|
|
573
|
+
}
|
|
574
|
+
if (onKeyUp) {
|
|
575
|
+
_onKeyUp = e => onKeyUp(state, e);
|
|
576
|
+
}
|
|
577
|
+
if (handlers.optimized) {
|
|
578
|
+
if (onChange) {
|
|
579
|
+
_onChange = (e, unknown) => {
|
|
580
|
+
handlers._updateInputHandler(state[e.target.name], e, unknown);
|
|
581
|
+
onChange(state, e);
|
|
582
|
+
};
|
|
583
|
+
} else {
|
|
584
|
+
_onChange = (e, unknown) => {
|
|
585
|
+
handlers._updateInputHandler(state[e.target.name], e, unknown);
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
return React.createElement("form", _extends({}, rest, {
|
|
543
589
|
ref: refHandler,
|
|
544
590
|
onPaste: _onPaste,
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
591
|
+
onKeyDown: _onKeyDown,
|
|
592
|
+
onKeyUp: _onKeyUp,
|
|
593
|
+
onBlur: e => handlers._viHandler(state[e.target.name], e),
|
|
548
594
|
onInvalid: e => {
|
|
549
595
|
e.preventDefault();
|
|
550
|
-
_viHandler(state
|
|
551
|
-
},
|
|
552
|
-
onChange: (e, unknown) => {
|
|
553
|
-
_updateInputHandler(e.target.name, e, unknown);
|
|
554
|
-
onChange && onChange(formState, e);
|
|
596
|
+
handlers._viHandler(state[e.target.name], e);
|
|
555
597
|
},
|
|
598
|
+
onChange: _onChange,
|
|
556
599
|
onSubmit: _onSubmit
|
|
557
|
-
}), formChildren) : React.createElement("form", _extends({}, rest, {
|
|
558
|
-
onChange: e => onChange && onChange(formState, e),
|
|
559
|
-
ref: refHandler,
|
|
560
|
-
onSubmit: _onSubmit,
|
|
561
|
-
onPaste: _onPaste
|
|
562
600
|
}), formChildren);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
601
|
+
}
|
|
602
|
+
if (onChange) {
|
|
603
|
+
_onChange = e => onChange(state, e);
|
|
604
|
+
}
|
|
605
|
+
return React.createElement("form", _extends({}, rest, {
|
|
606
|
+
ref: refHandler,
|
|
607
|
+
onSubmit: _onSubmit,
|
|
608
|
+
onChange: _onChange,
|
|
609
|
+
onPaste: _onPaste,
|
|
610
|
+
onKeyDown: _onKeyDown,
|
|
611
|
+
onKeyUp: _onKeyUp
|
|
612
|
+
}), formChildren);
|
|
613
|
+
}, [children, getFormState]);
|
|
614
|
+
React.useEffect(() => {
|
|
615
|
+
const state = getFormState();
|
|
616
|
+
if (!hasSubmitter(formRef.current)) {
|
|
617
|
+
console.warn(`[No Submit Button] - you have created a form without a button type=submit, this will prevent the onSubmit event from being fired.\nif you have a button with onClick event that handle the submission of the form then ignore this warning\nbut don't forget to manually invoke the checkValidity() function to check if the form is valid before perfoming any action, for example:\nif (formState.checkValidity()) { \n\t//do somthing\n}\n`);
|
|
618
|
+
}
|
|
619
|
+
if (onInit) {
|
|
620
|
+
const changes = onInit(state);
|
|
621
|
+
if (changes) {
|
|
622
|
+
const _handler = _c => handlers._dispatchChanges({
|
|
623
|
+
fields: _merge({}, state, _c)
|
|
571
624
|
});
|
|
572
|
-
|
|
573
|
-
|
|
625
|
+
if (changes instanceof Promise) {
|
|
626
|
+
changes.then(_handler);
|
|
627
|
+
} else _handler(changes);
|
|
574
628
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
})
|
|
629
|
+
}
|
|
630
|
+
const fields = getState().fields;
|
|
631
|
+
for (const fieldKey in fields) {
|
|
632
|
+
const field = fields[fieldKey];
|
|
633
|
+
if (!field.value) continue;
|
|
634
|
+
handlers._viHandler(field);
|
|
635
|
+
}
|
|
636
|
+
}, [getFormState]);
|
|
637
|
+
return formComponent;
|
|
638
|
+
});
|
|
639
|
+
const GForm = React.forwardRef(({
|
|
640
|
+
children,
|
|
641
|
+
validators,
|
|
642
|
+
optimized,
|
|
643
|
+
...props
|
|
644
|
+
}, ref) => {
|
|
645
|
+
const initialState = React.useMemo(() => {
|
|
646
|
+
return _buildFormInitialValues(typeof children === 'function' ? children({}) : children);
|
|
647
|
+
}, [children]);
|
|
648
|
+
return React.createElement(GFormContextProvider, {
|
|
649
|
+
key: initialState.key,
|
|
650
|
+
initialState: initialState,
|
|
651
|
+
validators: validators,
|
|
652
|
+
optimized: optimized
|
|
653
|
+
}, React.createElement(FormRenderer, _extends({
|
|
654
|
+
ref: ref
|
|
655
|
+
}, props), children));
|
|
656
|
+
});
|
|
593
657
|
|
|
594
|
-
const
|
|
658
|
+
const _GInput = React.forwardRef(({
|
|
595
659
|
formKey,
|
|
596
660
|
element,
|
|
597
661
|
title,
|
|
598
|
-
type,
|
|
599
|
-
validatorKey,
|
|
662
|
+
type = 'text',
|
|
600
663
|
fetch,
|
|
601
|
-
fetchDeps
|
|
664
|
+
fetchDeps,
|
|
602
665
|
optimized,
|
|
666
|
+
debounce = 300,
|
|
603
667
|
defaultChecked,
|
|
604
668
|
defaultValue,
|
|
605
669
|
checked,
|
|
670
|
+
validatorKey,
|
|
606
671
|
value,
|
|
607
|
-
debounce = 300,
|
|
608
672
|
...rest
|
|
609
673
|
}, ref) => {
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
fields
|
|
613
|
-
},
|
|
614
|
-
_updateInputHandler,
|
|
615
|
-
_dispatchChanges,
|
|
616
|
-
optimized: formOptimized,
|
|
617
|
-
_viHandler
|
|
618
|
-
} = useGenericFormContext();
|
|
619
|
-
const inputState = fields[formKey];
|
|
674
|
+
const inputState = useFormSelector(state => state.fields[formKey]);
|
|
675
|
+
const store = useFormStore();
|
|
620
676
|
const _element = React.useMemo(() => {
|
|
621
677
|
let value, checked;
|
|
622
678
|
if (type === 'checkbox') checked = inputState.value || false;else value = inputState.value || '';
|
|
@@ -631,19 +687,26 @@ const GInput = React.forwardRef(({
|
|
|
631
687
|
'aria-required': inputState.required,
|
|
632
688
|
title: title || inputState.errorText
|
|
633
689
|
};
|
|
634
|
-
if (!
|
|
635
|
-
_props.onBlur = e => {
|
|
636
|
-
_viHandler(inputState, e);
|
|
637
|
-
rest.onBlur
|
|
690
|
+
if (!store.handlers.optimized || !optimized) {
|
|
691
|
+
_props.onBlur = rest.onBlur ? e => {
|
|
692
|
+
store.handlers._viHandler(inputState, e);
|
|
693
|
+
rest.onBlur(e);
|
|
694
|
+
} : e => {
|
|
695
|
+
store.handlers._viHandler(inputState, e);
|
|
638
696
|
};
|
|
639
|
-
_props.onInvalid = e => {
|
|
697
|
+
_props.onInvalid = rest.onInvalid ? e => {
|
|
640
698
|
e.preventDefault();
|
|
641
|
-
_viHandler(inputState, e);
|
|
642
|
-
rest.onInvalid
|
|
699
|
+
store.handlers._viHandler(inputState, e);
|
|
700
|
+
rest.onInvalid(e);
|
|
701
|
+
} : e => {
|
|
702
|
+
e.preventDefault();
|
|
703
|
+
store.handlers._viHandler(inputState, e);
|
|
643
704
|
};
|
|
644
|
-
_props.onChange = (e, unknown) => {
|
|
645
|
-
_updateInputHandler(
|
|
646
|
-
rest.onChange
|
|
705
|
+
_props.onChange = rest.onChange ? (e, unknown) => {
|
|
706
|
+
store.handlers._updateInputHandler(inputState, e, unknown);
|
|
707
|
+
rest.onChange(e);
|
|
708
|
+
} : (e, unknown) => {
|
|
709
|
+
store.handlers._updateInputHandler(inputState, e, unknown);
|
|
647
710
|
};
|
|
648
711
|
}
|
|
649
712
|
if (element) {
|
|
@@ -651,20 +714,26 @@ const GInput = React.forwardRef(({
|
|
|
651
714
|
}
|
|
652
715
|
return React.createElement("input", _props);
|
|
653
716
|
}, [inputState, element]);
|
|
654
|
-
const _fetchDeps =
|
|
717
|
+
const _fetchDeps = useFormSelector(makeSelectFields(fetchDeps));
|
|
718
|
+
const stableFetchDeps = React.useMemo(() => JSON.stringify(_fetchDeps), [_fetchDeps]);
|
|
655
719
|
React.useEffect(() => {
|
|
656
720
|
if (fetch) {
|
|
657
|
-
inputState.dispatchChanges = changes => _dispatchChanges(changes, formKey);
|
|
658
721
|
_debounce(debounce, `${inputState.gid}-fetch`).then(() => {
|
|
659
|
-
const res = fetch(inputState, fields);
|
|
660
|
-
res instanceof Promise
|
|
722
|
+
const res = fetch(inputState, store.getState().fields);
|
|
723
|
+
if (res instanceof Promise) {
|
|
724
|
+
res.then(state => state && store.handlers._dispatchChanges(state, formKey));
|
|
725
|
+
} else if (res) {
|
|
726
|
+
store.handlers._dispatchChanges(res, formKey);
|
|
727
|
+
}
|
|
661
728
|
});
|
|
662
729
|
}
|
|
663
|
-
},
|
|
730
|
+
}, [stableFetchDeps]);
|
|
664
731
|
return _element;
|
|
665
732
|
});
|
|
733
|
+
const GInput = React.memo(_GInput);
|
|
666
734
|
|
|
667
735
|
exports.GForm = GForm;
|
|
668
736
|
exports.GInput = GInput;
|
|
669
737
|
exports.GValidator = GValidator;
|
|
738
|
+
exports.useFormSelector = useFormSelector;
|
|
670
739
|
//# sourceMappingURL=gform-react.development.js.map
|