gform-react 1.11.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/README.md +4 -3
- package/dist/cjs/gform-react.development.js +280 -238
- 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 +286 -243
- 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 +25 -12
- package/native/dist/cjs/gform-react-native.development.js +222 -284
- 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 +228 -288
- 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 +27 -24
|
@@ -24,7 +24,7 @@ const generateId = () => (+new Date()).toString(36) + (1 - Math.random()).toStri
|
|
|
24
24
|
const _buildFormInitialValues = (rows = []) => {
|
|
25
25
|
const fields = {};
|
|
26
26
|
if (!Array.isArray(rows)) rows = [rows];
|
|
27
|
-
|
|
27
|
+
for (const row of rows) {
|
|
28
28
|
const inputConfigs = _findInputs(row);
|
|
29
29
|
inputConfigs.forEach(config => {
|
|
30
30
|
if (fields[config.formKey]) {
|
|
@@ -70,12 +70,9 @@ const _buildFormInitialValues = (rows = []) => {
|
|
|
70
70
|
if (typeof fields[config.formKey][key] === 'undefined') delete fields[config.formKey][key];
|
|
71
71
|
});
|
|
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 {
|
|
@@ -134,39 +143,13 @@ const _toRawData = (fields, options = {}) => {
|
|
|
134
143
|
for (const key in transform) {
|
|
135
144
|
var _fields$key2;
|
|
136
145
|
const set = transform[key];
|
|
137
|
-
data[key] = set((_fields$key2 = fields[key]) === null || _fields$key2 === void 0 ? void 0 : _fields$key2.value);
|
|
146
|
+
data[key] = set(((_fields$key2 = fields[key]) === null || _fields$key2 === void 0 ? void 0 : _fields$key2.value) || fields[key]);
|
|
138
147
|
}
|
|
139
148
|
}
|
|
140
149
|
return data;
|
|
141
150
|
};
|
|
142
151
|
const _toFormData = (form, options) => {
|
|
143
152
|
if (!form) return new FormData();
|
|
144
|
-
if (options) {
|
|
145
|
-
const {
|
|
146
|
-
exclude,
|
|
147
|
-
include,
|
|
148
|
-
transform
|
|
149
|
-
} = options;
|
|
150
|
-
let formData;
|
|
151
|
-
if (include) {
|
|
152
|
-
formData = new FormData();
|
|
153
|
-
include.forEach(key => {
|
|
154
|
-
var _form;
|
|
155
|
-
return formData.set(key, (_form = form[key]) === null || _form === void 0 ? void 0 : _form.value);
|
|
156
|
-
});
|
|
157
|
-
} else {
|
|
158
|
-
formData = new FormData(form);
|
|
159
|
-
exclude === null || exclude === void 0 || exclude.forEach(key => formData.delete(key));
|
|
160
|
-
}
|
|
161
|
-
if (transform) {
|
|
162
|
-
for (const key in transform) {
|
|
163
|
-
var _form$key;
|
|
164
|
-
const set = transform[key];
|
|
165
|
-
formData.set(key, set((_form$key = form[key]) === null || _form$key === void 0 ? void 0 : _form$key.value));
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return formData;
|
|
169
|
-
}
|
|
170
153
|
return new FormData(form);
|
|
171
154
|
};
|
|
172
155
|
function _toURLSearchParams(options) {
|
|
@@ -272,9 +255,9 @@ class GValidator {
|
|
|
272
255
|
const baseHandlers = (baseValidator === null || baseValidator === void 0 ? void 0 : baseValidator.handlers) || [];
|
|
273
256
|
const baseConstraintHandlers = (baseValidator === null || baseValidator === void 0 ? void 0 : baseValidator.constraintHandlers) || [];
|
|
274
257
|
const baseHandlersAsync = (baseValidator === null || baseValidator === void 0 ? void 0 : baseValidator.asyncHandlers) || [];
|
|
275
|
-
this._handlers =
|
|
276
|
-
this._constraintHandlers =
|
|
277
|
-
this._asyncHandlers =
|
|
258
|
+
this._handlers = [].concat(baseHandlers);
|
|
259
|
+
this._constraintHandlers = [].concat(baseConstraintHandlers);
|
|
260
|
+
this._asyncHandlers = [].concat(baseHandlersAsync);
|
|
278
261
|
{
|
|
279
262
|
this.track = [];
|
|
280
263
|
if (baseValidator !== null && baseValidator !== void 0 && baseValidator.track) {
|
|
@@ -340,39 +323,13 @@ class GValidator {
|
|
|
340
323
|
}
|
|
341
324
|
}
|
|
342
325
|
|
|
343
|
-
const
|
|
344
|
-
const initialValues = React.useMemo(() => {
|
|
345
|
-
const values = _buildFormInitialValues(typeof children === 'function' ? children({}) : children);
|
|
346
|
-
{
|
|
347
|
-
Object.keys(values.state.fields).forEach(key => {
|
|
348
|
-
const input = values.state.fields[key];
|
|
349
|
-
const validator = validators[key];
|
|
350
|
-
if (validator instanceof GValidator) {
|
|
351
|
-
var _validator$track;
|
|
352
|
-
const validityKeys = (_validator$track = validator.track) === null || _validator$track === void 0 ? void 0 : _validator$track.filter(key => validityMap[key]);
|
|
353
|
-
validityKeys === null || validityKeys === void 0 || validityKeys.forEach(vKey => {
|
|
354
|
-
if (typeof input[validityMap[vKey]] === 'undefined') {
|
|
355
|
-
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`);
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
Object.entries(validityMap).forEach(([validityKey, constraint]) => {
|
|
359
|
-
var _validator$track2;
|
|
360
|
-
if (typeof input[constraint] !== 'undefined' && !((_validator$track2 = validator.track) !== null && _validator$track2 !== void 0 && _validator$track2.some(trackKey => validityKey === trackKey))) {
|
|
361
|
-
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}`);
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
return values;
|
|
368
|
-
}, []);
|
|
369
|
-
const [state, setState] = React.useState(initialValues.state);
|
|
326
|
+
const useFormHandlers = (getState, setState, validators = {}, optimized = false) => {
|
|
370
327
|
const _viHandler = (input, e) => {
|
|
371
328
|
if (!input) return;
|
|
372
329
|
const element = e && e.target;
|
|
373
330
|
if (typeof document !== 'undefined' && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)) {
|
|
374
331
|
if (!input.checkValidity) input.checkValidity = () => element.checkValidity();
|
|
375
|
-
if (!input.dirty && input.value) {
|
|
332
|
+
if (!input.dirty && input.value && !input.touched) {
|
|
376
333
|
_checkInputManually(input);
|
|
377
334
|
_dispatchChanges(input, input.formKey);
|
|
378
335
|
return;
|
|
@@ -393,6 +350,7 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
393
350
|
const _checkInputManually = input => {
|
|
394
351
|
let validityKey = _findValidityKey({
|
|
395
352
|
valueMissing: input.required && !input.value || false,
|
|
353
|
+
typeMismatch: _checkTypeMismatch(input),
|
|
396
354
|
tooShort: input.minLength && input.value.toString().length < input.minLength || false,
|
|
397
355
|
tooLong: input.maxLength && input.value.toString().length > input.maxLength || false,
|
|
398
356
|
patternMismatch: input.pattern && _checkResult(input.pattern, input.value) || false,
|
|
@@ -405,22 +363,17 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
405
363
|
_validateInput(input, validityKey);
|
|
406
364
|
return !input.error;
|
|
407
365
|
};
|
|
408
|
-
const _updateInputHandler = (
|
|
409
|
-
|
|
410
|
-
const input = _updateInput(key, value);
|
|
366
|
+
const _updateInputHandler = (input, e, unknown) => {
|
|
367
|
+
input.value = _extractValue(e, unknown);
|
|
411
368
|
_viHandler(input, e);
|
|
412
369
|
};
|
|
413
370
|
const _validateInput = (input, validityKey, setValidity) => {
|
|
414
371
|
const inputValidator = validators[input.validatorKey || input.formKey] || validators['*'];
|
|
415
|
-
|
|
372
|
+
if (inputValidator) {
|
|
373
|
+
__validateInput(input, inputValidator, validityKey, setValidity);
|
|
374
|
+
}
|
|
416
375
|
input.touched = true;
|
|
417
376
|
};
|
|
418
|
-
const _updateInput = (key, value) => {
|
|
419
|
-
const input = state.fields[key];
|
|
420
|
-
input.value = value;
|
|
421
|
-
input.dirty = true;
|
|
422
|
-
return input;
|
|
423
|
-
};
|
|
424
377
|
const _dispatchChanges = (changes, key) => setState(prev => {
|
|
425
378
|
if (key) {
|
|
426
379
|
return {
|
|
@@ -440,13 +393,14 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
440
393
|
};
|
|
441
394
|
});
|
|
442
395
|
const __validateInput = (input, inputValidator, validityKey, setValidity) => {
|
|
396
|
+
const fields = getState().fields;
|
|
443
397
|
for (const index in inputValidator.constraintHandlers) {
|
|
444
398
|
const result = inputValidator.constraintHandlers[index](input, validityKey);
|
|
445
399
|
input.error = _checkResult(result, input.value);
|
|
446
400
|
if (input.error) return;
|
|
447
401
|
}
|
|
448
402
|
for (const index in inputValidator.handlers) {
|
|
449
|
-
const result = inputValidator.handlers[index](input,
|
|
403
|
+
const result = inputValidator.handlers[index](input, fields);
|
|
450
404
|
input.error = _checkResult(result, input.value);
|
|
451
405
|
if (input.error) return;
|
|
452
406
|
}
|
|
@@ -456,7 +410,7 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
456
410
|
_debounce(input.debounce || 300, `${input.gid}-async`).then(() => {
|
|
457
411
|
const validateAsync = async () => {
|
|
458
412
|
for (const index in inputValidator.asyncHandlers) {
|
|
459
|
-
const result = await inputValidator.asyncHandlers[index](input,
|
|
413
|
+
const result = await inputValidator.asyncHandlers[index](input, fields);
|
|
460
414
|
input.error = _checkResult(result, input.value);
|
|
461
415
|
if (input.error) break;
|
|
462
416
|
}
|
|
@@ -465,185 +419,260 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
465
419
|
error: input.error,
|
|
466
420
|
errorText: input.errorText
|
|
467
421
|
}, input.formKey);
|
|
468
|
-
|
|
422
|
+
if (setValidity) {
|
|
423
|
+
setValidity(input.errorText);
|
|
424
|
+
}
|
|
469
425
|
};
|
|
470
426
|
validateAsync();
|
|
471
427
|
});
|
|
472
428
|
}
|
|
473
429
|
};
|
|
474
430
|
return {
|
|
475
|
-
state,
|
|
476
431
|
_updateInputHandler,
|
|
477
432
|
_viHandler,
|
|
478
433
|
_dispatchChanges,
|
|
479
434
|
optimized,
|
|
480
|
-
key: initialValues.key,
|
|
481
435
|
_createInputChecker: _checkInputManually
|
|
482
436
|
};
|
|
483
437
|
};
|
|
484
438
|
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
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;
|
|
496
508
|
});
|
|
497
|
-
const useGenericFormContext = () => React.useContext(gFormContext);
|
|
498
|
-
const GFormContextProvider = gFormContext.Provider;
|
|
499
509
|
|
|
500
|
-
const
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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;
|
|
533
|
+
}
|
|
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
|
+
})
|
|
554
|
+
};
|
|
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);
|
|
529
565
|
}
|
|
530
|
-
formRef.current = element;
|
|
531
566
|
};
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
})
|
|
553
|
-
};
|
|
554
|
-
if (stateRef) stateRef.current = formState;
|
|
555
|
-
return formState;
|
|
556
|
-
}, [state.fields]);
|
|
557
|
-
const formComponent = React.useMemo(() => {
|
|
558
|
-
const formChildren = typeof children === 'function' ? children(formState) : children;
|
|
559
|
-
const _onSubmit = e => {
|
|
560
|
-
e.preventDefault();
|
|
561
|
-
if (formState.isValid && onSubmit) {
|
|
562
|
-
onSubmit(formState, e);
|
|
563
|
-
}
|
|
564
|
-
};
|
|
565
|
-
let _onPaste;
|
|
566
|
-
if (onPaste) {
|
|
567
|
-
_onPaste = e => onPaste(formState, e);
|
|
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
|
+
};
|
|
568
587
|
}
|
|
569
|
-
return
|
|
588
|
+
return React.createElement("form", _extends({}, rest, {
|
|
570
589
|
ref: refHandler,
|
|
571
590
|
onPaste: _onPaste,
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
591
|
+
onKeyDown: _onKeyDown,
|
|
592
|
+
onKeyUp: _onKeyUp,
|
|
593
|
+
onBlur: e => handlers._viHandler(state[e.target.name], e),
|
|
575
594
|
onInvalid: e => {
|
|
576
595
|
e.preventDefault();
|
|
577
|
-
_viHandler(state
|
|
578
|
-
},
|
|
579
|
-
onChange: (e, unknown) => {
|
|
580
|
-
_updateInputHandler(e.target.name, e, unknown);
|
|
581
|
-
onChange && onChange(formState, e);
|
|
596
|
+
handlers._viHandler(state[e.target.name], e);
|
|
582
597
|
},
|
|
598
|
+
onChange: _onChange,
|
|
583
599
|
onSubmit: _onSubmit
|
|
584
|
-
}), formChildren) : React.createElement("form", _extends({}, rest, {
|
|
585
|
-
onChange: e => onChange && onChange(formState, e),
|
|
586
|
-
ref: refHandler,
|
|
587
|
-
onSubmit: _onSubmit,
|
|
588
|
-
onPaste: _onPaste
|
|
589
600
|
}), formChildren);
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
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)
|
|
598
624
|
});
|
|
599
|
-
|
|
600
|
-
|
|
625
|
+
if (changes instanceof Promise) {
|
|
626
|
+
changes.then(_handler);
|
|
627
|
+
} else _handler(changes);
|
|
601
628
|
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
})
|
|
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
|
+
});
|
|
620
657
|
|
|
621
|
-
const
|
|
658
|
+
const _GInput = React.forwardRef(({
|
|
622
659
|
formKey,
|
|
623
660
|
element,
|
|
624
661
|
title,
|
|
625
|
-
type,
|
|
626
|
-
validatorKey,
|
|
662
|
+
type = 'text',
|
|
627
663
|
fetch,
|
|
628
|
-
fetchDeps
|
|
664
|
+
fetchDeps,
|
|
629
665
|
optimized,
|
|
666
|
+
debounce = 300,
|
|
630
667
|
defaultChecked,
|
|
631
668
|
defaultValue,
|
|
632
669
|
checked,
|
|
670
|
+
validatorKey,
|
|
633
671
|
value,
|
|
634
|
-
debounce = 300,
|
|
635
672
|
...rest
|
|
636
673
|
}, ref) => {
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
fields
|
|
640
|
-
},
|
|
641
|
-
_updateInputHandler,
|
|
642
|
-
_dispatchChanges,
|
|
643
|
-
optimized: formOptimized,
|
|
644
|
-
_viHandler
|
|
645
|
-
} = useGenericFormContext();
|
|
646
|
-
const inputState = fields[formKey];
|
|
674
|
+
const inputState = useFormSelector(state => state.fields[formKey]);
|
|
675
|
+
const store = useFormStore();
|
|
647
676
|
const _element = React.useMemo(() => {
|
|
648
677
|
let value, checked;
|
|
649
678
|
if (type === 'checkbox') checked = inputState.value || false;else value = inputState.value || '';
|
|
@@ -658,19 +687,26 @@ const GInput = React.forwardRef(({
|
|
|
658
687
|
'aria-required': inputState.required,
|
|
659
688
|
title: title || inputState.errorText
|
|
660
689
|
};
|
|
661
|
-
if (!
|
|
662
|
-
_props.onBlur = e => {
|
|
663
|
-
_viHandler(inputState, e);
|
|
664
|
-
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);
|
|
665
696
|
};
|
|
666
|
-
_props.onInvalid = e => {
|
|
697
|
+
_props.onInvalid = rest.onInvalid ? e => {
|
|
698
|
+
e.preventDefault();
|
|
699
|
+
store.handlers._viHandler(inputState, e);
|
|
700
|
+
rest.onInvalid(e);
|
|
701
|
+
} : e => {
|
|
667
702
|
e.preventDefault();
|
|
668
|
-
_viHandler(inputState, e);
|
|
669
|
-
rest.onInvalid && rest.onInvalid(e);
|
|
703
|
+
store.handlers._viHandler(inputState, e);
|
|
670
704
|
};
|
|
671
|
-
_props.onChange = (e, unknown) => {
|
|
672
|
-
_updateInputHandler(
|
|
673
|
-
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);
|
|
674
710
|
};
|
|
675
711
|
}
|
|
676
712
|
if (element) {
|
|
@@ -678,20 +714,26 @@ const GInput = React.forwardRef(({
|
|
|
678
714
|
}
|
|
679
715
|
return React.createElement("input", _props);
|
|
680
716
|
}, [inputState, element]);
|
|
681
|
-
const _fetchDeps =
|
|
717
|
+
const _fetchDeps = useFormSelector(makeSelectFields(fetchDeps));
|
|
718
|
+
const stableFetchDeps = React.useMemo(() => JSON.stringify(_fetchDeps), [_fetchDeps]);
|
|
682
719
|
React.useEffect(() => {
|
|
683
720
|
if (fetch) {
|
|
684
|
-
inputState.dispatchChanges = changes => _dispatchChanges(changes, formKey);
|
|
685
721
|
_debounce(debounce, `${inputState.gid}-fetch`).then(() => {
|
|
686
|
-
const res = fetch(inputState, fields);
|
|
687
|
-
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
|
+
}
|
|
688
728
|
});
|
|
689
729
|
}
|
|
690
|
-
},
|
|
730
|
+
}, [stableFetchDeps]);
|
|
691
731
|
return _element;
|
|
692
732
|
});
|
|
733
|
+
const GInput = React.memo(_GInput);
|
|
693
734
|
|
|
694
735
|
exports.GForm = GForm;
|
|
695
736
|
exports.GInput = GInput;
|
|
696
737
|
exports.GValidator = GValidator;
|
|
738
|
+
exports.useFormSelector = useFormSelector;
|
|
697
739
|
//# sourceMappingURL=gform-react.development.js.map
|