gform-react 2.0.1 → 2.5.2
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 +314 -213
- 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/GValidator.production.js +1 -1
- package/dist/esm/GValidator.production.js.map +1 -1
- package/dist/esm/index.development.js +320 -218
- 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 +13 -13
- package/native/dist/cjs/gform-react-native.development.js +254 -264
- 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 +260 -268
- 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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _extends from '@babel/runtime/helpers/esm/extends';
|
|
2
2
|
import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
|
|
3
3
|
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
|
|
4
|
-
import React, {
|
|
4
|
+
import React, { useSyncExternalStore, useRef, useCallback, useEffect, createContext, useContext, forwardRef, useMemo, memo } from 'react';
|
|
5
5
|
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
|
|
6
6
|
|
|
7
7
|
const isObject = o => o && typeof o === 'object' && !Array.isArray(o);
|
|
@@ -28,7 +28,7 @@ const _buildFormInitialValues = (rows = []) => {
|
|
|
28
28
|
const inputConfigs = _findInputs(row);
|
|
29
29
|
inputConfigs.forEach(config => {
|
|
30
30
|
if (fields[config.formKey]) {
|
|
31
|
-
console.warn(`[Duplicate Keys] - field with key '${config.formKey}' has already been defined.`);
|
|
31
|
+
console.warn(`DEV ONLY - [Duplicate Keys] - field with key '${config.formKey}' has already been defined.`);
|
|
32
32
|
}
|
|
33
33
|
const {
|
|
34
34
|
required = false,
|
|
@@ -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
|
};
|
|
@@ -92,13 +89,34 @@ const _findInputs = (root, total = []) => {
|
|
|
92
89
|
}
|
|
93
90
|
return _findInputs((_root$props2 = root.props) === null || _root$props2 === void 0 ? void 0 : _root$props2.children, total);
|
|
94
91
|
};
|
|
95
|
-
const _findValidityKey = validity => {
|
|
92
|
+
const _findValidityKey = (validity, exclude = []) => {
|
|
96
93
|
for (const key in validity) {
|
|
94
|
+
if (exclude.includes(key)) continue;
|
|
97
95
|
if (key !== 'valid' && validity[key]) {
|
|
98
96
|
return key;
|
|
99
97
|
}
|
|
100
98
|
}
|
|
101
99
|
};
|
|
100
|
+
const _checkTypeMismatch = input => {
|
|
101
|
+
var _input$value;
|
|
102
|
+
const value = (_input$value = input.value) === null || _input$value === void 0 ? void 0 : _input$value.toString().trim();
|
|
103
|
+
if (!value) return false;
|
|
104
|
+
switch (input.type) {
|
|
105
|
+
case 'email':
|
|
106
|
+
return !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
107
|
+
case 'url':
|
|
108
|
+
try {
|
|
109
|
+
new URL(value);
|
|
110
|
+
return false;
|
|
111
|
+
} catch (_unused) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
case 'tel':
|
|
115
|
+
return !/^\+?[0-9\s\-().]{7,}$/.test(value);
|
|
116
|
+
default:
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
102
120
|
const hasSubmitter = form => {
|
|
103
121
|
if (!form) return false;
|
|
104
122
|
for (const element of form) {
|
|
@@ -106,14 +124,6 @@ const hasSubmitter = form => {
|
|
|
106
124
|
}
|
|
107
125
|
return false;
|
|
108
126
|
};
|
|
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
127
|
const _toRawData = (fields, options = {}) => {
|
|
118
128
|
const data = {};
|
|
119
129
|
const {
|
|
@@ -213,7 +223,8 @@ let validityMap;
|
|
|
213
223
|
pattern: 'withPatternMismatchMessage',
|
|
214
224
|
min: 'withRangeUnderflowMessage',
|
|
215
225
|
max: 'withRangeOverflowMessage',
|
|
216
|
-
step: 'withStepMismatchMessage'
|
|
226
|
+
step: 'withStepMismatchMessage',
|
|
227
|
+
type: 'withTypeMismatchMessage'
|
|
217
228
|
};
|
|
218
229
|
validityMap = {
|
|
219
230
|
tooShort: 'minLength',
|
|
@@ -222,7 +233,8 @@ let validityMap;
|
|
|
222
233
|
patternMismatch: 'pattern',
|
|
223
234
|
rangeOverflow: 'max',
|
|
224
235
|
rangeUnderflow: 'min',
|
|
225
|
-
stepMismatch: 'step'
|
|
236
|
+
stepMismatch: 'step',
|
|
237
|
+
typeMismatch: 'type'
|
|
226
238
|
};
|
|
227
239
|
}
|
|
228
240
|
class GValidator {
|
|
@@ -253,6 +265,10 @@ class GValidator {
|
|
|
253
265
|
}
|
|
254
266
|
}
|
|
255
267
|
}
|
|
268
|
+
hasConstraint(constraint) {
|
|
269
|
+
var _this$track;
|
|
270
|
+
return ((_this$track = this.track) === null || _this$track === void 0 ? void 0 : _this$track.includes(constraint)) || false;
|
|
271
|
+
}
|
|
256
272
|
withRequiredMessage(message) {
|
|
257
273
|
return this.__addConstraintValidationHandler('valueMissing', message);
|
|
258
274
|
}
|
|
@@ -291,14 +307,14 @@ class GValidator {
|
|
|
291
307
|
__addConstraintValidationHandler(validityKey, message) {
|
|
292
308
|
if (this.track) {
|
|
293
309
|
if (this.track.includes(validityKey)) {
|
|
294
|
-
console.warn(`[Duplicate Handlers] - handler for '${validityKey}' has already been defined`);
|
|
310
|
+
console.warn(`DEV ONLY - [Duplicate Handlers] - handler for '${validityKey}' has already been defined`);
|
|
295
311
|
}
|
|
296
312
|
this.track.push(validityKey);
|
|
297
313
|
}
|
|
298
314
|
this._constraintHandlers.push((input, key) => {
|
|
299
315
|
{
|
|
300
316
|
if (validityKey && validityMap[validityKey] && typeof input[validityMap[validityKey]] === 'undefined') {
|
|
301
|
-
console.warn(`[Missing Prop] - the input '${input.formKey}' has registered validator for the violation '${validityKey}' but the input hasn't described the constraint '${validityMap[validityKey]}'.\nadd '${validityMap[validityKey]}' to the input props.\nexample:\n<GInput formKey='${input.formKey}' ${validityMap[validityKey]}={...} />\n\nor either remove '.${handlersMap[validityMap[validityKey]]}(...)' validation`);
|
|
317
|
+
console.warn(`DEV ONLY - [Missing Prop] - the input '${input.formKey}' has registered validator for the violation '${validityKey}' but the input hasn't described the constraint '${validityMap[validityKey]}'.\nadd '${validityMap[validityKey]}' to the input props.\nexample:\n<GInput formKey='${input.formKey}' ${validityMap[validityKey]}={...} />\n\nor either remove '.${handlersMap[validityMap[validityKey]]}(...)' validation`);
|
|
302
318
|
}
|
|
303
319
|
}
|
|
304
320
|
if (key === validityKey) {
|
|
@@ -311,45 +327,22 @@ class GValidator {
|
|
|
311
327
|
}
|
|
312
328
|
}
|
|
313
329
|
|
|
314
|
-
const
|
|
315
|
-
const initialValues = useMemo(() => {
|
|
316
|
-
const values = _buildFormInitialValues(typeof children === 'function' ? children({}) : children);
|
|
317
|
-
{
|
|
318
|
-
Object.keys(values.state.fields).forEach(key => {
|
|
319
|
-
const input = values.state.fields[key];
|
|
320
|
-
const validator = validators[key];
|
|
321
|
-
if (validator instanceof GValidator) {
|
|
322
|
-
var _validator$track;
|
|
323
|
-
const validityKeys = (_validator$track = validator.track) === null || _validator$track === void 0 ? void 0 : _validator$track.filter(key => validityMap[key]);
|
|
324
|
-
validityKeys === null || validityKeys === void 0 || validityKeys.forEach(vKey => {
|
|
325
|
-
if (typeof input[validityMap[vKey]] === 'undefined') {
|
|
326
|
-
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`);
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
Object.entries(validityMap).forEach(([validityKey, constraint]) => {
|
|
330
|
-
var _validator$track2;
|
|
331
|
-
if (typeof input[constraint] !== 'undefined' && !((_validator$track2 = validator.track) !== null && _validator$track2 !== void 0 && _validator$track2.some(trackKey => validityKey === trackKey))) {
|
|
332
|
-
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}`);
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
return values;
|
|
339
|
-
}, []);
|
|
340
|
-
const [state, setState] = useState(initialValues.state);
|
|
330
|
+
const useFormHandlers = (getState, setState, validators = {}, optimized = false) => {
|
|
341
331
|
const _viHandler = (input, e) => {
|
|
342
332
|
if (!input) return;
|
|
343
333
|
const element = e && e.target;
|
|
334
|
+
const hasInitialValue = !input.dirty && input.value && !input.touched;
|
|
335
|
+
if (!element && !hasInitialValue) return;
|
|
344
336
|
if (typeof document !== 'undefined' && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)) {
|
|
345
337
|
if (!input.checkValidity) input.checkValidity = () => element.checkValidity();
|
|
346
|
-
if (
|
|
338
|
+
if (hasInitialValue) {
|
|
347
339
|
_checkInputManually(input);
|
|
348
340
|
_dispatchChanges(input, input.formKey);
|
|
349
341
|
return;
|
|
350
342
|
}
|
|
351
343
|
element.setCustomValidity('');
|
|
352
|
-
const
|
|
344
|
+
const exclude = input.type && (input.pattern || hasCustomValidation(input)) ? ['typeMismatch'] : [];
|
|
345
|
+
const validityKey = _findValidityKey(element.validity, exclude);
|
|
353
346
|
_validateInput(input, validityKey, v => element.setCustomValidity(v));
|
|
354
347
|
if (!validityKey && input.error) {
|
|
355
348
|
element.setCustomValidity(input.errorText || 'error');
|
|
@@ -362,36 +355,38 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
362
355
|
}
|
|
363
356
|
};
|
|
364
357
|
const _checkInputManually = input => {
|
|
358
|
+
const exclude = input.type && (input.pattern || hasCustomValidation(input)) ? ['typeMismatch'] : [];
|
|
365
359
|
let validityKey = _findValidityKey({
|
|
366
360
|
valueMissing: input.required && !input.value || false,
|
|
361
|
+
typeMismatch: _checkTypeMismatch(input),
|
|
367
362
|
tooShort: input.minLength && input.value.toString().length < input.minLength || false,
|
|
368
363
|
tooLong: input.maxLength && input.value.toString().length > input.maxLength || false,
|
|
369
364
|
patternMismatch: input.pattern && _checkResult(input.pattern, input.value) || false,
|
|
370
365
|
rangeUnderflow: input.min && Number(input.value) < Number(input.min) || false,
|
|
371
366
|
rangeOverflow: input.max && Number(input.value) > Number(input.max) || false
|
|
372
|
-
});
|
|
367
|
+
}, exclude);
|
|
373
368
|
if (!validityKey && input.error) {
|
|
374
369
|
validityKey = 'customError';
|
|
375
370
|
}
|
|
376
371
|
_validateInput(input, validityKey);
|
|
377
372
|
return !input.error;
|
|
378
373
|
};
|
|
379
|
-
const _updateInputHandler = (
|
|
380
|
-
|
|
381
|
-
const input = _updateInput(key, value);
|
|
374
|
+
const _updateInputHandler = (input, e, unknown) => {
|
|
375
|
+
input.value = _extractValue(e, unknown);
|
|
382
376
|
_viHandler(input, e);
|
|
383
377
|
};
|
|
384
378
|
const _validateInput = (input, validityKey, setValidity) => {
|
|
385
379
|
const inputValidator = validators[input.validatorKey || input.formKey] || validators['*'];
|
|
386
|
-
|
|
380
|
+
{
|
|
381
|
+
if (validityKey && !(inputValidator !== null && inputValidator !== void 0 && inputValidator.hasConstraint(validityKey))) {
|
|
382
|
+
if (validityKey === 'typeMismatch') console.warn(`DEV ONLY - [Missing Validator] - the input '${input.formKey}' has described the constraint '${validityMap[validityKey]}' however, a correspond validator / custom validation / pattern validator are missing.\nadd '${handlersMap[validityMap[validityKey]]}' or 'withCustomValidation' or '${handlersMap[validityMap.patternMismatch]}' to the input validator.\nexample:\nconst validators: GValidators = {\n\temail: new GValidator().withPatternMismatchMessage('pattern mismatch'),\n\t...\n}\n\nor either remove the constraint '${validityMap[validityKey]}' from the input props`);else console.warn(`DEV ONLY - [Missing Validator] - the input '${input.formKey}' has described the constraint '${validityMap[validityKey]}' however, a correspond validator is missing.\nadd '${handlersMap[validityMap[validityKey]]}' to the input validator.\nexample:\nconst validators: GValidators = {\n\temail: new GValidator().withPatternMismatchMessage('pattern mismatch'),\n\t...\n}\n\nor either remove the constraint '${validityMap[validityKey]}' from the input props`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (inputValidator) {
|
|
386
|
+
__validateInput(input, inputValidator, validityKey, setValidity);
|
|
387
|
+
}
|
|
387
388
|
input.touched = true;
|
|
388
389
|
};
|
|
389
|
-
const _updateInput = (key, value) => {
|
|
390
|
-
const input = state.fields[key];
|
|
391
|
-
input.value = value;
|
|
392
|
-
input.dirty = true;
|
|
393
|
-
return input;
|
|
394
|
-
};
|
|
395
390
|
const _dispatchChanges = (changes, key) => setState(prev => {
|
|
396
391
|
if (key) {
|
|
397
392
|
return _objectSpread(_objectSpread({}, prev), {}, {
|
|
@@ -403,13 +398,14 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
403
398
|
return _objectSpread(_objectSpread({}, prev), changes);
|
|
404
399
|
});
|
|
405
400
|
const __validateInput = (input, inputValidator, validityKey, setValidity) => {
|
|
401
|
+
const fields = getState().fields;
|
|
406
402
|
for (const index in inputValidator.constraintHandlers) {
|
|
407
403
|
const result = inputValidator.constraintHandlers[index](input, validityKey);
|
|
408
404
|
input.error = _checkResult(result, input.value);
|
|
409
405
|
if (input.error) return;
|
|
410
406
|
}
|
|
411
407
|
for (const index in inputValidator.handlers) {
|
|
412
|
-
const result = inputValidator.handlers[index](input,
|
|
408
|
+
const result = inputValidator.handlers[index](input, fields);
|
|
413
409
|
input.error = _checkResult(result, input.value);
|
|
414
410
|
if (input.error) return;
|
|
415
411
|
}
|
|
@@ -419,7 +415,7 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
419
415
|
_debounce(input.debounce || 300, `${input.gid}-async`).then(() => {
|
|
420
416
|
const validateAsync = async () => {
|
|
421
417
|
for (const index in inputValidator.asyncHandlers) {
|
|
422
|
-
const result = await inputValidator.asyncHandlers[index](input,
|
|
418
|
+
const result = await inputValidator.asyncHandlers[index](input, fields);
|
|
423
419
|
input.error = _checkResult(result, input.value);
|
|
424
420
|
if (input.error) break;
|
|
425
421
|
}
|
|
@@ -428,187 +424,269 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
428
424
|
error: input.error,
|
|
429
425
|
errorText: input.errorText
|
|
430
426
|
}, input.formKey);
|
|
431
|
-
|
|
427
|
+
if (setValidity) {
|
|
428
|
+
setValidity(input.errorText);
|
|
429
|
+
}
|
|
432
430
|
};
|
|
433
431
|
validateAsync();
|
|
434
432
|
});
|
|
435
433
|
}
|
|
436
434
|
};
|
|
435
|
+
const hasCustomValidation = input => {
|
|
436
|
+
const validator = validators[input.validatorKey || input.formKey] || validators['*'];
|
|
437
|
+
return validator && (validator.asyncHandlers.length > 0 || validator.handlers.length > 0);
|
|
438
|
+
};
|
|
437
439
|
return {
|
|
438
|
-
state,
|
|
439
440
|
_updateInputHandler,
|
|
440
441
|
_viHandler,
|
|
441
442
|
_dispatchChanges,
|
|
442
443
|
optimized,
|
|
443
|
-
key: initialValues.key,
|
|
444
444
|
_createInputChecker: _checkInputManually
|
|
445
445
|
};
|
|
446
446
|
};
|
|
447
447
|
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
448
|
+
const GFormContext = createContext({});
|
|
449
|
+
const GFormContextProvider = ({
|
|
450
|
+
children,
|
|
451
|
+
initialState,
|
|
452
|
+
validators,
|
|
453
|
+
optimized
|
|
454
|
+
}) => {
|
|
455
|
+
const stateRef = useRef(initialState);
|
|
456
|
+
const listeners = useRef(new Set());
|
|
457
|
+
const setState = useCallback(updater => {
|
|
458
|
+
stateRef.current = typeof updater === 'function' ? updater(stateRef.current) : updater;
|
|
459
|
+
listeners.current.forEach(l => l());
|
|
460
|
+
}, []);
|
|
461
|
+
const handlers = useFormHandlers(() => stateRef.current, setState, validators, optimized);
|
|
462
|
+
const getState = useCallback(() => stateRef.current, []);
|
|
463
|
+
const subscribe = useCallback(listener => {
|
|
464
|
+
listeners.current.add(listener);
|
|
465
|
+
return () => listeners.current.delete(listener);
|
|
466
|
+
}, []);
|
|
467
|
+
useEffect(() => {
|
|
468
|
+
for (const fieldKey in initialState.fields) {
|
|
469
|
+
initialState.fields[fieldKey].dispatchChanges = changes => handlers._dispatchChanges(changes, fieldKey);
|
|
470
|
+
}
|
|
471
|
+
}, []);
|
|
472
|
+
const store = useRef({
|
|
473
|
+
getState,
|
|
474
|
+
setState,
|
|
475
|
+
subscribe,
|
|
476
|
+
handlers
|
|
477
|
+
});
|
|
478
|
+
return React.createElement(GFormContext.Provider, {
|
|
479
|
+
value: store.current
|
|
480
|
+
}, children);
|
|
481
|
+
};
|
|
482
|
+
const useFormStore = () => {
|
|
483
|
+
const store = useContext(GFormContext);
|
|
484
|
+
if (!store) throw new Error('useGFormStore must be used within `GForm` component');
|
|
485
|
+
return store;
|
|
486
|
+
};
|
|
487
|
+
const useFormSelector = selector => {
|
|
488
|
+
const store = useFormStore();
|
|
489
|
+
return useSyncExternalStore(store.subscribe, () => selector(store.getState()), () => selector(store.getState()));
|
|
490
|
+
};
|
|
491
|
+
function createSelector(selectors, combiner) {
|
|
492
|
+
let lastArgs = [];
|
|
493
|
+
let lastResult;
|
|
494
|
+
return state => {
|
|
495
|
+
const args = selectors.map(fn => fn(state));
|
|
496
|
+
if (lastArgs.length === args.length && args.every((val, i) => val === lastArgs[i])) {
|
|
497
|
+
return lastResult;
|
|
498
|
+
}
|
|
499
|
+
lastArgs = args;
|
|
500
|
+
lastResult = combiner(...args);
|
|
501
|
+
return lastResult;
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const selectFields = [state => state.fields];
|
|
506
|
+
const selectFirstInvalidField = createSelector(selectFields, fields => {
|
|
507
|
+
for (const f in fields) {
|
|
508
|
+
if (fields[f].error) {
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return false;
|
|
513
|
+
});
|
|
514
|
+
const makeSelectFields = (keys = []) => createSelector(selectFields, fields => {
|
|
515
|
+
const selected = keys.map(key => fields[key]).filter(Boolean);
|
|
516
|
+
return selected.length ? selected : null;
|
|
459
517
|
});
|
|
460
|
-
const useGenericFormContext = () => useContext(gFormContext);
|
|
461
|
-
const GFormContextProvider = gFormContext.Provider;
|
|
462
518
|
|
|
463
|
-
const _excluded$1 = ["
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
519
|
+
const _excluded$1 = ["stateRef", "onSubmit", "onChange", "onPaste", "onKeyDown", "onKeyUp", "children", "onInit"],
|
|
520
|
+
_excluded2 = ["children", "validators", "optimized"];
|
|
521
|
+
const FormRenderer = forwardRef((_ref, ref) => {
|
|
522
|
+
let {
|
|
523
|
+
stateRef,
|
|
524
|
+
onSubmit,
|
|
525
|
+
onChange,
|
|
526
|
+
onPaste,
|
|
527
|
+
onKeyDown,
|
|
528
|
+
onKeyUp,
|
|
529
|
+
children,
|
|
530
|
+
onInit
|
|
531
|
+
} = _ref,
|
|
532
|
+
rest = _objectWithoutProperties(_ref, _excluded$1);
|
|
533
|
+
const formRef = useRef(null);
|
|
534
|
+
const {
|
|
535
|
+
getState,
|
|
536
|
+
handlers
|
|
537
|
+
} = useFormStore();
|
|
538
|
+
const isFormInvalid = useFormSelector(selectFirstInvalidField);
|
|
539
|
+
const refHandler = useCallback(element => {
|
|
540
|
+
if (ref) {
|
|
541
|
+
if (typeof ref === 'function') {
|
|
542
|
+
ref(element);
|
|
543
|
+
} else {
|
|
544
|
+
ref.current = element;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
formRef.current = element;
|
|
548
|
+
}, [ref]);
|
|
549
|
+
const getFormState = useCallback(() => {
|
|
550
|
+
const fields = getState().fields;
|
|
551
|
+
const formState = _objectSpread(_objectSpread({}, fields), {}, {
|
|
552
|
+
isValid: !isFormInvalid,
|
|
553
|
+
isInvalid: isFormInvalid,
|
|
554
|
+
toRawData: options => _toRawData(fields, options),
|
|
555
|
+
toFormData: () => _toFormData(formRef.current),
|
|
556
|
+
toURLSearchParams: _toURLSearchParams,
|
|
557
|
+
checkValidity: function () {
|
|
558
|
+
this.isValid = formRef.current && formRef.current.checkValidity() || false;
|
|
559
|
+
this.isInvalid = !this.isValid;
|
|
560
|
+
return this.isValid;
|
|
561
|
+
},
|
|
562
|
+
dispatchChanges: changes => handlers._dispatchChanges({
|
|
563
|
+
fields: _merge({}, fields, changes)
|
|
564
|
+
})
|
|
565
|
+
});
|
|
566
|
+
if (stateRef) stateRef.current = formState;
|
|
567
|
+
return formState;
|
|
568
|
+
}, [isFormInvalid]);
|
|
569
|
+
const formComponent = useMemo(() => {
|
|
570
|
+
const state = getFormState();
|
|
571
|
+
const formChildren = typeof children === 'function' ? children(state) : children;
|
|
572
|
+
const _onSubmit = e => {
|
|
573
|
+
const state = getFormState();
|
|
574
|
+
if (state.isValid && onSubmit) {
|
|
575
|
+
onSubmit(state, e);
|
|
494
576
|
}
|
|
495
|
-
formRef.current = element;
|
|
496
577
|
};
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
}
|
|
517
|
-
});
|
|
518
|
-
if (stateRef) stateRef.current = formState;
|
|
519
|
-
return formState;
|
|
520
|
-
}, [state.fields]);
|
|
521
|
-
const formComponent = useMemo(() => {
|
|
522
|
-
const formChildren = typeof children === 'function' ? children(formState) : children;
|
|
523
|
-
const _onSubmit = e => {
|
|
524
|
-
if (formState.isValid && onSubmit) {
|
|
525
|
-
onSubmit(formState, e);
|
|
526
|
-
}
|
|
527
|
-
};
|
|
528
|
-
let _onPaste;
|
|
529
|
-
if (onPaste) {
|
|
530
|
-
_onPaste = e => onPaste(formState, e);
|
|
578
|
+
let _onPaste, _onChange, _onKeyDown, _onKeyUp;
|
|
579
|
+
if (onPaste) {
|
|
580
|
+
_onPaste = e => onPaste(state, e);
|
|
581
|
+
}
|
|
582
|
+
if (onKeyDown) {
|
|
583
|
+
_onKeyDown = e => onKeyDown(state, e);
|
|
584
|
+
}
|
|
585
|
+
if (onKeyUp) {
|
|
586
|
+
_onKeyUp = e => onKeyUp(state, e);
|
|
587
|
+
}
|
|
588
|
+
if (handlers.optimized) {
|
|
589
|
+
if (onChange) {
|
|
590
|
+
_onChange = (e, unknown) => {
|
|
591
|
+
handlers._updateInputHandler(state[e.target.name], e, unknown);
|
|
592
|
+
onChange(state, e);
|
|
593
|
+
};
|
|
594
|
+
} else {
|
|
595
|
+
_onChange = (e, unknown) => {
|
|
596
|
+
handlers._updateInputHandler(state[e.target.name], e, unknown);
|
|
597
|
+
};
|
|
531
598
|
}
|
|
532
|
-
return
|
|
599
|
+
return React.createElement("form", _extends({}, rest, {
|
|
533
600
|
ref: refHandler,
|
|
534
601
|
onPaste: _onPaste,
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
602
|
+
onKeyDown: _onKeyDown,
|
|
603
|
+
onKeyUp: _onKeyUp,
|
|
604
|
+
onBlur: e => handlers._viHandler(state[e.target.name], e),
|
|
538
605
|
onInvalid: e => {
|
|
539
606
|
e.preventDefault();
|
|
540
|
-
_viHandler(state
|
|
541
|
-
},
|
|
542
|
-
onChange: (e, unknown) => {
|
|
543
|
-
_updateInputHandler(e.target.name, e, unknown);
|
|
544
|
-
onChange && onChange(formState, e);
|
|
607
|
+
handlers._viHandler(state[e.target.name], e);
|
|
545
608
|
},
|
|
609
|
+
onChange: _onChange,
|
|
546
610
|
onSubmit: _onSubmit
|
|
547
|
-
}), formChildren) : React.createElement("form", _extends({}, rest, {
|
|
548
|
-
onChange: e => onChange && onChange(formState, e),
|
|
549
|
-
ref: refHandler,
|
|
550
|
-
onSubmit: _onSubmit,
|
|
551
|
-
onPaste: _onPaste
|
|
552
611
|
}), formChildren);
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
612
|
+
}
|
|
613
|
+
if (onChange) {
|
|
614
|
+
_onChange = e => onChange(state, e);
|
|
615
|
+
}
|
|
616
|
+
return React.createElement("form", _extends({}, rest, {
|
|
617
|
+
ref: refHandler,
|
|
618
|
+
onSubmit: _onSubmit,
|
|
619
|
+
onChange: _onChange,
|
|
620
|
+
onPaste: _onPaste,
|
|
621
|
+
onKeyDown: _onKeyDown,
|
|
622
|
+
onKeyUp: _onKeyUp
|
|
623
|
+
}), formChildren);
|
|
624
|
+
}, [children, getFormState]);
|
|
625
|
+
useEffect(() => {
|
|
626
|
+
const state = getFormState();
|
|
627
|
+
if (!hasSubmitter(formRef.current)) {
|
|
628
|
+
console.warn(`DEV ONLY - [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`);
|
|
629
|
+
}
|
|
630
|
+
if (onInit) {
|
|
631
|
+
const changes = onInit(state);
|
|
632
|
+
if (changes) {
|
|
633
|
+
const _handler = _c => handlers._dispatchChanges({
|
|
634
|
+
fields: _merge({}, state, _c)
|
|
561
635
|
});
|
|
562
|
-
|
|
563
|
-
|
|
636
|
+
if (changes instanceof Promise) {
|
|
637
|
+
changes.then(_handler);
|
|
638
|
+
} else _handler(changes);
|
|
564
639
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
|
|
640
|
+
}
|
|
641
|
+
const fields = getState().fields;
|
|
642
|
+
for (const fieldKey in fields) {
|
|
643
|
+
const field = fields[fieldKey];
|
|
644
|
+
if (!field.value) continue;
|
|
645
|
+
handlers._viHandler(field);
|
|
646
|
+
}
|
|
647
|
+
}, [getFormState]);
|
|
648
|
+
return formComponent;
|
|
649
|
+
});
|
|
650
|
+
const GForm = forwardRef((_ref2, ref) => {
|
|
651
|
+
let {
|
|
652
|
+
children,
|
|
653
|
+
validators,
|
|
654
|
+
optimized
|
|
655
|
+
} = _ref2,
|
|
656
|
+
props = _objectWithoutProperties(_ref2, _excluded2);
|
|
657
|
+
const initialState = useMemo(() => {
|
|
658
|
+
return _buildFormInitialValues(typeof children === 'function' ? children({}) : children);
|
|
659
|
+
}, [children]);
|
|
660
|
+
return React.createElement(GFormContextProvider, {
|
|
661
|
+
key: initialState.key,
|
|
662
|
+
initialState: initialState,
|
|
663
|
+
validators: validators,
|
|
664
|
+
optimized: optimized
|
|
665
|
+
}, React.createElement(FormRenderer, _extends({
|
|
666
|
+
ref: ref
|
|
667
|
+
}, props), children));
|
|
668
|
+
});
|
|
583
669
|
|
|
584
|
-
const _excluded = ["formKey", "element", "title", "type", "
|
|
585
|
-
const
|
|
670
|
+
const _excluded = ["formKey", "element", "title", "type", "fetch", "fetchDeps", "optimized", "debounce", "defaultChecked", "defaultValue", "checked", "validatorKey", "value"];
|
|
671
|
+
const _GInput = forwardRef((_ref, ref) => {
|
|
586
672
|
let {
|
|
587
673
|
formKey,
|
|
588
674
|
element,
|
|
589
675
|
title,
|
|
590
|
-
type,
|
|
591
|
-
validatorKey,
|
|
676
|
+
type = 'text',
|
|
592
677
|
fetch,
|
|
593
|
-
fetchDeps
|
|
678
|
+
fetchDeps,
|
|
594
679
|
optimized,
|
|
680
|
+
debounce = 300,
|
|
595
681
|
defaultChecked,
|
|
596
682
|
defaultValue,
|
|
597
683
|
checked,
|
|
598
|
-
|
|
599
|
-
|
|
684
|
+
validatorKey,
|
|
685
|
+
value
|
|
600
686
|
} = _ref,
|
|
601
687
|
rest = _objectWithoutProperties(_ref, _excluded);
|
|
602
|
-
const
|
|
603
|
-
|
|
604
|
-
fields
|
|
605
|
-
},
|
|
606
|
-
_updateInputHandler,
|
|
607
|
-
_dispatchChanges,
|
|
608
|
-
optimized: formOptimized,
|
|
609
|
-
_viHandler
|
|
610
|
-
} = useGenericFormContext();
|
|
611
|
-
const inputState = fields[formKey];
|
|
688
|
+
const inputState = useFormSelector(state => state.fields[formKey]);
|
|
689
|
+
const store = useFormStore();
|
|
612
690
|
const _element = useMemo(() => {
|
|
613
691
|
let value, checked;
|
|
614
692
|
if (type === 'checkbox') checked = inputState.value || false;else value = inputState.value || '';
|
|
@@ -622,38 +700,62 @@ const GInput = forwardRef((_ref, ref) => {
|
|
|
622
700
|
'aria-required': inputState.required,
|
|
623
701
|
title: title || inputState.errorText
|
|
624
702
|
});
|
|
625
|
-
if (!
|
|
626
|
-
_props.onBlur = e => {
|
|
627
|
-
_viHandler(inputState, e);
|
|
628
|
-
rest.onBlur
|
|
703
|
+
if (!store.handlers.optimized || !optimized) {
|
|
704
|
+
_props.onBlur = rest.onBlur ? e => {
|
|
705
|
+
store.handlers._viHandler(inputState, e);
|
|
706
|
+
rest.onBlur(e);
|
|
707
|
+
} : e => {
|
|
708
|
+
store.handlers._viHandler(inputState, e);
|
|
629
709
|
};
|
|
630
|
-
_props.onInvalid = e => {
|
|
710
|
+
_props.onInvalid = rest.onInvalid ? e => {
|
|
711
|
+
e.preventDefault();
|
|
712
|
+
store.handlers._viHandler(inputState, e);
|
|
713
|
+
rest.onInvalid(e);
|
|
714
|
+
} : e => {
|
|
631
715
|
e.preventDefault();
|
|
632
|
-
_viHandler(inputState, e);
|
|
633
|
-
rest.onInvalid && rest.onInvalid(e);
|
|
716
|
+
store.handlers._viHandler(inputState, e);
|
|
634
717
|
};
|
|
635
|
-
_props.onChange = (e, unknown) => {
|
|
636
|
-
_updateInputHandler(
|
|
637
|
-
rest.onChange
|
|
718
|
+
_props.onChange = rest.onChange ? (e, unknown) => {
|
|
719
|
+
store.handlers._updateInputHandler(inputState, e, unknown);
|
|
720
|
+
rest.onChange(e);
|
|
721
|
+
} : (e, unknown) => {
|
|
722
|
+
store.handlers._updateInputHandler(inputState, e, unknown);
|
|
638
723
|
};
|
|
724
|
+
if (!inputState.touched) {
|
|
725
|
+
_props.onFocus = rest.onFocus ? e => {
|
|
726
|
+
rest.onFocus(e);
|
|
727
|
+
inputState.dispatchChanges({
|
|
728
|
+
touched: true
|
|
729
|
+
});
|
|
730
|
+
} : () => {
|
|
731
|
+
inputState.dispatchChanges({
|
|
732
|
+
touched: true
|
|
733
|
+
});
|
|
734
|
+
};
|
|
735
|
+
}
|
|
639
736
|
}
|
|
640
737
|
if (element) {
|
|
641
738
|
return element(inputState, _props);
|
|
642
739
|
}
|
|
643
740
|
return React.createElement("input", _props);
|
|
644
741
|
}, [inputState, element]);
|
|
645
|
-
const _fetchDeps =
|
|
742
|
+
const _fetchDeps = useFormSelector(makeSelectFields(fetchDeps));
|
|
743
|
+
const stableFetchDeps = useMemo(() => JSON.stringify(_fetchDeps), [_fetchDeps]);
|
|
646
744
|
useEffect(() => {
|
|
647
745
|
if (fetch) {
|
|
648
|
-
inputState.dispatchChanges = changes => _dispatchChanges(changes, formKey);
|
|
649
746
|
_debounce(debounce, `${inputState.gid}-fetch`).then(() => {
|
|
650
|
-
const res = fetch(inputState, fields);
|
|
651
|
-
res instanceof Promise
|
|
747
|
+
const res = fetch(inputState, store.getState().fields);
|
|
748
|
+
if (res instanceof Promise) {
|
|
749
|
+
res.then(state => state && store.handlers._dispatchChanges(state, formKey));
|
|
750
|
+
} else if (res) {
|
|
751
|
+
store.handlers._dispatchChanges(res, formKey);
|
|
752
|
+
}
|
|
652
753
|
});
|
|
653
754
|
}
|
|
654
|
-
},
|
|
755
|
+
}, [stableFetchDeps]);
|
|
655
756
|
return _element;
|
|
656
757
|
});
|
|
758
|
+
const GInput = memo(_GInput);
|
|
657
759
|
|
|
658
|
-
export { GForm, GInput, GValidator };
|
|
760
|
+
export { GForm, GInput, GValidator, useFormSelector };
|
|
659
761
|
//# sourceMappingURL=index.development.js.map
|