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,8 +1,8 @@
|
|
|
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, {
|
|
5
|
-
import
|
|
4
|
+
import React, { useContext, createContext, useSyncExternalStore, useRef, useCallback, useEffect, forwardRef, useMemo, memo } from 'react';
|
|
5
|
+
import '@babel/runtime/helpers/esm/defineProperty';
|
|
6
6
|
import { TextInput } from 'react-native';
|
|
7
7
|
|
|
8
8
|
const isObject = o => o && typeof o === 'object' && !Array.isArray(o);
|
|
@@ -29,7 +29,7 @@ const _buildFormInitialValues = (rows = []) => {
|
|
|
29
29
|
const inputConfigs = _findInputs(row);
|
|
30
30
|
inputConfigs.forEach(config => {
|
|
31
31
|
if (fields[config.formKey]) {
|
|
32
|
-
console.warn(`[Duplicate Keys] - field with key '${config.formKey}' has already been defined.`);
|
|
32
|
+
console.warn(`DEV ONLY - [Duplicate Keys] - field with key '${config.formKey}' has already been defined.`);
|
|
33
33
|
}
|
|
34
34
|
const {
|
|
35
35
|
required = false,
|
|
@@ -73,10 +73,7 @@ const _buildFormInitialValues = (rows = []) => {
|
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
return {
|
|
76
|
-
|
|
77
|
-
fields,
|
|
78
|
-
loading: false
|
|
79
|
-
},
|
|
76
|
+
fields: fields,
|
|
80
77
|
key: generateId()
|
|
81
78
|
};
|
|
82
79
|
};
|
|
@@ -93,20 +90,33 @@ const _findInputs = (root, total = []) => {
|
|
|
93
90
|
}
|
|
94
91
|
return _findInputs((_root$props2 = root.props) === null || _root$props2 === void 0 ? void 0 : _root$props2.children, total);
|
|
95
92
|
};
|
|
96
|
-
const _findValidityKey = validity => {
|
|
93
|
+
const _findValidityKey = (validity, exclude = []) => {
|
|
97
94
|
for (const key in validity) {
|
|
95
|
+
if (exclude.includes(key)) continue;
|
|
98
96
|
if (key !== 'valid' && validity[key]) {
|
|
99
97
|
return key;
|
|
100
98
|
}
|
|
101
99
|
}
|
|
102
100
|
};
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
const _checkTypeMismatch = input => {
|
|
102
|
+
var _input$value;
|
|
103
|
+
const value = (_input$value = input.value) === null || _input$value === void 0 ? void 0 : _input$value.toString().trim();
|
|
104
|
+
if (!value) return false;
|
|
105
|
+
switch (input.type) {
|
|
106
|
+
case 'email':
|
|
107
|
+
return !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
108
|
+
case 'url':
|
|
109
|
+
try {
|
|
110
|
+
new URL(value);
|
|
111
|
+
return false;
|
|
112
|
+
} catch (_unused) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
case 'tel':
|
|
116
|
+
return !/^\+?[0-9\s\-().]{7,}$/.test(value);
|
|
117
|
+
default:
|
|
106
118
|
return false;
|
|
107
|
-
}
|
|
108
119
|
}
|
|
109
|
-
return true;
|
|
110
120
|
};
|
|
111
121
|
const _toRawData = (fields, options = {}) => {
|
|
112
122
|
const data = {};
|
|
@@ -203,7 +213,8 @@ let validityMap;
|
|
|
203
213
|
pattern: 'withPatternMismatchMessage',
|
|
204
214
|
min: 'withRangeUnderflowMessage',
|
|
205
215
|
max: 'withRangeOverflowMessage',
|
|
206
|
-
step: 'withStepMismatchMessage'
|
|
216
|
+
step: 'withStepMismatchMessage',
|
|
217
|
+
type: 'withTypeMismatchMessage'
|
|
207
218
|
};
|
|
208
219
|
validityMap = {
|
|
209
220
|
tooShort: 'minLength',
|
|
@@ -212,134 +223,27 @@ let validityMap;
|
|
|
212
223
|
patternMismatch: 'pattern',
|
|
213
224
|
rangeOverflow: 'max',
|
|
214
225
|
rangeUnderflow: 'min',
|
|
215
|
-
stepMismatch: 'step'
|
|
226
|
+
stepMismatch: 'step',
|
|
227
|
+
typeMismatch: 'type'
|
|
216
228
|
};
|
|
217
229
|
}
|
|
218
|
-
class GValidator {
|
|
219
|
-
get handlers() {
|
|
220
|
-
return this._handlers;
|
|
221
|
-
}
|
|
222
|
-
get constraintHandlers() {
|
|
223
|
-
return this._constraintHandlers;
|
|
224
|
-
}
|
|
225
|
-
get asyncHandlers() {
|
|
226
|
-
return this._asyncHandlers;
|
|
227
|
-
}
|
|
228
|
-
constructor(baseValidator) {
|
|
229
|
-
_defineProperty(this, "_handlers", void 0);
|
|
230
|
-
_defineProperty(this, "_constraintHandlers", void 0);
|
|
231
|
-
_defineProperty(this, "_asyncHandlers", void 0);
|
|
232
|
-
_defineProperty(this, "track", void 0);
|
|
233
|
-
const baseHandlers = (baseValidator === null || baseValidator === void 0 ? void 0 : baseValidator.handlers) || [];
|
|
234
|
-
const baseConstraintHandlers = (baseValidator === null || baseValidator === void 0 ? void 0 : baseValidator.constraintHandlers) || [];
|
|
235
|
-
const baseHandlersAsync = (baseValidator === null || baseValidator === void 0 ? void 0 : baseValidator.asyncHandlers) || [];
|
|
236
|
-
this._handlers = [].concat(baseHandlers);
|
|
237
|
-
this._constraintHandlers = [].concat(baseConstraintHandlers);
|
|
238
|
-
this._asyncHandlers = [].concat(baseHandlersAsync);
|
|
239
|
-
{
|
|
240
|
-
this.track = [];
|
|
241
|
-
if (baseValidator !== null && baseValidator !== void 0 && baseValidator.track) {
|
|
242
|
-
this.track = this.track.concat(baseValidator.track);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
withRequiredMessage(message) {
|
|
247
|
-
return this.__addConstraintValidationHandler('valueMissing', message);
|
|
248
|
-
}
|
|
249
|
-
withMaxLengthMessage(message) {
|
|
250
|
-
return this.__addConstraintValidationHandler('tooLong', message);
|
|
251
|
-
}
|
|
252
|
-
withMinLengthMessage(message) {
|
|
253
|
-
return this.__addConstraintValidationHandler('tooShort', message);
|
|
254
|
-
}
|
|
255
|
-
withPatternMismatchMessage(message) {
|
|
256
|
-
return this.__addConstraintValidationHandler('patternMismatch', message);
|
|
257
|
-
}
|
|
258
|
-
withBadInputMessage(message) {
|
|
259
|
-
return this.__addConstraintValidationHandler('badInput', message);
|
|
260
|
-
}
|
|
261
|
-
withRangeUnderflowMessage(message) {
|
|
262
|
-
return this.__addConstraintValidationHandler('rangeUnderflow', message);
|
|
263
|
-
}
|
|
264
|
-
withRangeOverflowMessage(message) {
|
|
265
|
-
return this.__addConstraintValidationHandler('rangeOverflow', message);
|
|
266
|
-
}
|
|
267
|
-
withTypeMismatchMessage(message) {
|
|
268
|
-
return this.__addConstraintValidationHandler('typeMismatch', message);
|
|
269
|
-
}
|
|
270
|
-
withStepMismatchMessage(message) {
|
|
271
|
-
return this.__addConstraintValidationHandler('stepMismatch', message);
|
|
272
|
-
}
|
|
273
|
-
withCustomValidation(handler) {
|
|
274
|
-
this._handlers.push(handler);
|
|
275
|
-
return this;
|
|
276
|
-
}
|
|
277
|
-
withCustomValidationAsync(handler) {
|
|
278
|
-
this._asyncHandlers.push(handler);
|
|
279
|
-
return this;
|
|
280
|
-
}
|
|
281
|
-
__addConstraintValidationHandler(validityKey, message) {
|
|
282
|
-
if (this.track) {
|
|
283
|
-
if (this.track.includes(validityKey)) {
|
|
284
|
-
console.warn(`[Duplicate Handlers] - handler for '${validityKey}' has already been defined`);
|
|
285
|
-
}
|
|
286
|
-
this.track.push(validityKey);
|
|
287
|
-
}
|
|
288
|
-
this._constraintHandlers.push((input, key) => {
|
|
289
|
-
{
|
|
290
|
-
if (validityKey && validityMap[validityKey] && typeof input[validityMap[validityKey]] === 'undefined') {
|
|
291
|
-
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`);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
if (key === validityKey) {
|
|
295
|
-
input.errorText = typeof message === 'string' ? message : message(input);
|
|
296
|
-
return true;
|
|
297
|
-
}
|
|
298
|
-
return false;
|
|
299
|
-
});
|
|
300
|
-
return this;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
230
|
|
|
304
|
-
const
|
|
305
|
-
const initialValues = useMemo(() => {
|
|
306
|
-
const values = _buildFormInitialValues(typeof children === 'function' ? children({}) : children);
|
|
307
|
-
{
|
|
308
|
-
Object.keys(values.state.fields).forEach(key => {
|
|
309
|
-
const input = values.state.fields[key];
|
|
310
|
-
const validator = validators[key];
|
|
311
|
-
if (validator instanceof GValidator) {
|
|
312
|
-
var _validator$track;
|
|
313
|
-
const validityKeys = (_validator$track = validator.track) === null || _validator$track === void 0 ? void 0 : _validator$track.filter(key => validityMap[key]);
|
|
314
|
-
validityKeys === null || validityKeys === void 0 || validityKeys.forEach(vKey => {
|
|
315
|
-
if (typeof input[validityMap[vKey]] === 'undefined') {
|
|
316
|
-
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`);
|
|
317
|
-
}
|
|
318
|
-
});
|
|
319
|
-
Object.entries(validityMap).forEach(([validityKey, constraint]) => {
|
|
320
|
-
var _validator$track2;
|
|
321
|
-
if (typeof input[constraint] !== 'undefined' && !((_validator$track2 = validator.track) !== null && _validator$track2 !== void 0 && _validator$track2.some(trackKey => validityKey === trackKey))) {
|
|
322
|
-
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}`);
|
|
323
|
-
}
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
return values;
|
|
329
|
-
}, []);
|
|
330
|
-
const [state, setState] = useState(initialValues.state);
|
|
231
|
+
const useFormHandlers = (getState, setState, validators = {}, optimized = false) => {
|
|
331
232
|
const _viHandler = (input, e) => {
|
|
332
233
|
if (!input) return;
|
|
333
234
|
const element = e && e.target;
|
|
235
|
+
const hasInitialValue = !input.dirty && input.value && !input.touched;
|
|
236
|
+
if (!element && !hasInitialValue) return;
|
|
334
237
|
if (typeof document !== 'undefined' && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)) {
|
|
335
238
|
if (!input.checkValidity) input.checkValidity = () => element.checkValidity();
|
|
336
|
-
if (
|
|
239
|
+
if (hasInitialValue) {
|
|
337
240
|
_checkInputManually(input);
|
|
338
241
|
_dispatchChanges(input, input.formKey);
|
|
339
242
|
return;
|
|
340
243
|
}
|
|
341
244
|
element.setCustomValidity('');
|
|
342
|
-
const
|
|
245
|
+
const exclude = input.type && (input.pattern || hasCustomValidation(input)) ? ['typeMismatch'] : [];
|
|
246
|
+
const validityKey = _findValidityKey(element.validity, exclude);
|
|
343
247
|
_validateInput(input, validityKey, v => element.setCustomValidity(v));
|
|
344
248
|
if (!validityKey && input.error) {
|
|
345
249
|
element.setCustomValidity(input.errorText || 'error');
|
|
@@ -352,36 +256,38 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
352
256
|
}
|
|
353
257
|
};
|
|
354
258
|
const _checkInputManually = input => {
|
|
259
|
+
const exclude = input.type && (input.pattern || hasCustomValidation(input)) ? ['typeMismatch'] : [];
|
|
355
260
|
let validityKey = _findValidityKey({
|
|
356
261
|
valueMissing: input.required && !input.value || false,
|
|
262
|
+
typeMismatch: _checkTypeMismatch(input),
|
|
357
263
|
tooShort: input.minLength && input.value.toString().length < input.minLength || false,
|
|
358
264
|
tooLong: input.maxLength && input.value.toString().length > input.maxLength || false,
|
|
359
265
|
patternMismatch: input.pattern && _checkResult(input.pattern, input.value) || false,
|
|
360
266
|
rangeUnderflow: input.min && Number(input.value) < Number(input.min) || false,
|
|
361
267
|
rangeOverflow: input.max && Number(input.value) > Number(input.max) || false
|
|
362
|
-
});
|
|
268
|
+
}, exclude);
|
|
363
269
|
if (!validityKey && input.error) {
|
|
364
270
|
validityKey = 'customError';
|
|
365
271
|
}
|
|
366
272
|
_validateInput(input, validityKey);
|
|
367
273
|
return !input.error;
|
|
368
274
|
};
|
|
369
|
-
const _updateInputHandler = (
|
|
370
|
-
|
|
371
|
-
const input = _updateInput(key, value);
|
|
275
|
+
const _updateInputHandler = (input, e, unknown) => {
|
|
276
|
+
input.value = _extractValue(e, unknown);
|
|
372
277
|
_viHandler(input, e);
|
|
373
278
|
};
|
|
374
279
|
const _validateInput = (input, validityKey, setValidity) => {
|
|
375
280
|
const inputValidator = validators[input.validatorKey || input.formKey] || validators['*'];
|
|
376
|
-
|
|
281
|
+
{
|
|
282
|
+
if (validityKey && !(inputValidator !== null && inputValidator !== void 0 && inputValidator.hasConstraint(validityKey))) {
|
|
283
|
+
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`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (inputValidator) {
|
|
287
|
+
__validateInput(input, inputValidator, validityKey, setValidity);
|
|
288
|
+
}
|
|
377
289
|
input.touched = true;
|
|
378
290
|
};
|
|
379
|
-
const _updateInput = (key, value) => {
|
|
380
|
-
const input = state.fields[key];
|
|
381
|
-
input.value = value;
|
|
382
|
-
input.dirty = true;
|
|
383
|
-
return input;
|
|
384
|
-
};
|
|
385
291
|
const _dispatchChanges = (changes, key) => setState(prev => {
|
|
386
292
|
if (key) {
|
|
387
293
|
return _objectSpread(_objectSpread({}, prev), {}, {
|
|
@@ -393,13 +299,14 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
393
299
|
return _objectSpread(_objectSpread({}, prev), changes);
|
|
394
300
|
});
|
|
395
301
|
const __validateInput = (input, inputValidator, validityKey, setValidity) => {
|
|
302
|
+
const fields = getState().fields;
|
|
396
303
|
for (const index in inputValidator.constraintHandlers) {
|
|
397
304
|
const result = inputValidator.constraintHandlers[index](input, validityKey);
|
|
398
305
|
input.error = _checkResult(result, input.value);
|
|
399
306
|
if (input.error) return;
|
|
400
307
|
}
|
|
401
308
|
for (const index in inputValidator.handlers) {
|
|
402
|
-
const result = inputValidator.handlers[index](input,
|
|
309
|
+
const result = inputValidator.handlers[index](input, fields);
|
|
403
310
|
input.error = _checkResult(result, input.value);
|
|
404
311
|
if (input.error) return;
|
|
405
312
|
}
|
|
@@ -409,7 +316,7 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
409
316
|
_debounce(input.debounce || 300, `${input.gid}-async`).then(() => {
|
|
410
317
|
const validateAsync = async () => {
|
|
411
318
|
for (const index in inputValidator.asyncHandlers) {
|
|
412
|
-
const result = await inputValidator.asyncHandlers[index](input,
|
|
319
|
+
const result = await inputValidator.asyncHandlers[index](input, fields);
|
|
413
320
|
input.error = _checkResult(result, input.value);
|
|
414
321
|
if (input.error) break;
|
|
415
322
|
}
|
|
@@ -418,141 +325,211 @@ const useForm = (children, validators = {}, optimized = false) => {
|
|
|
418
325
|
error: input.error,
|
|
419
326
|
errorText: input.errorText
|
|
420
327
|
}, input.formKey);
|
|
421
|
-
|
|
328
|
+
if (setValidity) {
|
|
329
|
+
setValidity(input.errorText);
|
|
330
|
+
}
|
|
422
331
|
};
|
|
423
332
|
validateAsync();
|
|
424
333
|
});
|
|
425
334
|
}
|
|
426
335
|
};
|
|
336
|
+
const hasCustomValidation = input => {
|
|
337
|
+
const validator = validators[input.validatorKey || input.formKey] || validators['*'];
|
|
338
|
+
return validator && (validator.asyncHandlers.length > 0 || validator.handlers.length > 0);
|
|
339
|
+
};
|
|
427
340
|
return {
|
|
428
|
-
state,
|
|
429
341
|
_updateInputHandler,
|
|
430
342
|
_viHandler,
|
|
431
343
|
_dispatchChanges,
|
|
432
344
|
optimized,
|
|
433
|
-
key: initialValues.key,
|
|
434
345
|
_createInputChecker: _checkInputManually
|
|
435
346
|
};
|
|
436
347
|
};
|
|
437
348
|
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
349
|
+
const GFormContext = createContext({});
|
|
350
|
+
const GFormContextProvider = ({
|
|
351
|
+
children,
|
|
352
|
+
initialState,
|
|
353
|
+
validators,
|
|
354
|
+
optimized
|
|
355
|
+
}) => {
|
|
356
|
+
const stateRef = useRef(initialState);
|
|
357
|
+
const listeners = useRef(new Set());
|
|
358
|
+
const setState = useCallback(updater => {
|
|
359
|
+
stateRef.current = typeof updater === 'function' ? updater(stateRef.current) : updater;
|
|
360
|
+
listeners.current.forEach(l => l());
|
|
361
|
+
}, []);
|
|
362
|
+
const handlers = useFormHandlers(() => stateRef.current, setState, validators, optimized);
|
|
363
|
+
const getState = useCallback(() => stateRef.current, []);
|
|
364
|
+
const subscribe = useCallback(listener => {
|
|
365
|
+
listeners.current.add(listener);
|
|
366
|
+
return () => listeners.current.delete(listener);
|
|
367
|
+
}, []);
|
|
368
|
+
useEffect(() => {
|
|
369
|
+
for (const fieldKey in initialState.fields) {
|
|
370
|
+
initialState.fields[fieldKey].dispatchChanges = changes => handlers._dispatchChanges(changes, fieldKey);
|
|
371
|
+
}
|
|
372
|
+
}, []);
|
|
373
|
+
const store = useRef({
|
|
374
|
+
getState,
|
|
375
|
+
setState,
|
|
376
|
+
subscribe,
|
|
377
|
+
handlers
|
|
378
|
+
});
|
|
379
|
+
return React.createElement(GFormContext.Provider, {
|
|
380
|
+
value: store.current
|
|
381
|
+
}, children);
|
|
382
|
+
};
|
|
383
|
+
const useFormStore = () => {
|
|
384
|
+
const store = useContext(GFormContext);
|
|
385
|
+
if (!store) throw new Error('useGFormStore must be used within `GForm` component');
|
|
386
|
+
return store;
|
|
387
|
+
};
|
|
388
|
+
const useFormSelector = selector => {
|
|
389
|
+
const store = useFormStore();
|
|
390
|
+
return useSyncExternalStore(store.subscribe, () => selector(store.getState()), () => selector(store.getState()));
|
|
391
|
+
};
|
|
392
|
+
function createSelector(selectors, combiner) {
|
|
393
|
+
let lastArgs = [];
|
|
394
|
+
let lastResult;
|
|
395
|
+
return state => {
|
|
396
|
+
const args = selectors.map(fn => fn(state));
|
|
397
|
+
if (lastArgs.length === args.length && args.every((val, i) => val === lastArgs[i])) {
|
|
398
|
+
return lastResult;
|
|
399
|
+
}
|
|
400
|
+
lastArgs = args;
|
|
401
|
+
lastResult = combiner(...args);
|
|
402
|
+
return lastResult;
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const selectFields = [state => state.fields];
|
|
407
|
+
const selectFirstInvalidField = createSelector(selectFields, fields => {
|
|
408
|
+
for (const f in fields) {
|
|
409
|
+
if (fields[f].error) {
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return false;
|
|
414
|
+
});
|
|
415
|
+
const makeSelectFields = (keys = []) => createSelector(selectFields, fields => {
|
|
416
|
+
const selected = keys.map(key => fields[key]).filter(Boolean);
|
|
417
|
+
return selected.length ? selected : null;
|
|
449
418
|
});
|
|
450
|
-
const useGenericFormContext = () => useContext(gFormContext);
|
|
451
|
-
const GFormContextProvider = gFormContext.Provider;
|
|
452
419
|
|
|
453
|
-
const _excluded$1 = ["
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
checkValidity: () => {
|
|
481
|
-
for (const i in state.fields) {
|
|
482
|
-
const valid = state.fields[i].checkValidity();
|
|
483
|
-
if (!valid) {
|
|
484
|
-
return false;
|
|
485
|
-
}
|
|
420
|
+
const _excluded$1 = ["stateRef", "children", "onInit", "el"],
|
|
421
|
+
_excluded2 = ["children", "validators"];
|
|
422
|
+
const FormRenderer = forwardRef((_ref, ref) => {
|
|
423
|
+
let {
|
|
424
|
+
stateRef,
|
|
425
|
+
children,
|
|
426
|
+
onInit,
|
|
427
|
+
el: El
|
|
428
|
+
} = _ref,
|
|
429
|
+
rest = _objectWithoutProperties(_ref, _excluded$1);
|
|
430
|
+
const {
|
|
431
|
+
getState,
|
|
432
|
+
handlers
|
|
433
|
+
} = useFormStore();
|
|
434
|
+
const isFormInvalid = useFormSelector(selectFirstInvalidField);
|
|
435
|
+
const getFormState = useCallback(() => {
|
|
436
|
+
const fields = getState().fields;
|
|
437
|
+
const formState = _objectSpread(_objectSpread({}, fields), {}, {
|
|
438
|
+
isValid: !isFormInvalid,
|
|
439
|
+
isInvalid: isFormInvalid,
|
|
440
|
+
toRawData: options => _toRawData(fields, options),
|
|
441
|
+
toURLSearchParams: _toURLSearchParams,
|
|
442
|
+
checkValidity: () => {
|
|
443
|
+
for (const i in fields) {
|
|
444
|
+
const valid = fields[i].checkValidity();
|
|
445
|
+
if (!valid) {
|
|
446
|
+
return false;
|
|
486
447
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
})
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
448
|
+
}
|
|
449
|
+
return true;
|
|
450
|
+
},
|
|
451
|
+
dispatchChanges: changes => handlers._dispatchChanges({
|
|
452
|
+
fields: _merge({}, fields, changes)
|
|
453
|
+
})
|
|
454
|
+
});
|
|
455
|
+
if (stateRef) stateRef.current = formState;
|
|
456
|
+
return formState;
|
|
457
|
+
}, [isFormInvalid]);
|
|
458
|
+
const formComponent = useMemo(() => {
|
|
459
|
+
const state = getFormState();
|
|
460
|
+
const formChildren = typeof children === 'function' ? children(state) : children;
|
|
461
|
+
return React.createElement(El, _extends({}, rest, {
|
|
462
|
+
ref: ref
|
|
463
|
+
}), formChildren);
|
|
464
|
+
}, [getFormState, children]);
|
|
465
|
+
useEffect(() => {
|
|
466
|
+
const state = getFormState();
|
|
467
|
+
if (onInit) {
|
|
468
|
+
const changes = onInit(state);
|
|
469
|
+
if (changes) {
|
|
470
|
+
const _handler = _c => handlers._dispatchChanges({
|
|
471
|
+
fields: _merge({}, state, _c)
|
|
503
472
|
});
|
|
504
|
-
|
|
505
|
-
|
|
473
|
+
if (changes instanceof Promise) {
|
|
474
|
+
changes.then(_handler);
|
|
475
|
+
} else _handler(changes);
|
|
506
476
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
477
|
+
}
|
|
478
|
+
const dispatchers = {};
|
|
479
|
+
const fields = getState().fields;
|
|
480
|
+
for (const fieldKey in fields) {
|
|
481
|
+
dispatchers[fieldKey] = {
|
|
482
|
+
dispatchChanges: changes => handlers._dispatchChanges(changes, fieldKey),
|
|
483
|
+
checkValidity: () => {
|
|
484
|
+
const result = handlers._createInputChecker(state[fieldKey]);
|
|
485
|
+
handlers._dispatchChanges(state[fieldKey], fieldKey);
|
|
486
|
+
return result;
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
const field = fields[fieldKey];
|
|
490
|
+
if (!field.value) continue;
|
|
491
|
+
handlers._viHandler(field);
|
|
492
|
+
}
|
|
493
|
+
handlers._dispatchChanges({
|
|
494
|
+
fields: _merge(dispatchers, state)
|
|
495
|
+
});
|
|
496
|
+
}, [getFormState]);
|
|
497
|
+
return formComponent;
|
|
498
|
+
});
|
|
499
|
+
const RNGForm = forwardRef((_ref2, ref) => {
|
|
500
|
+
let {
|
|
501
|
+
children,
|
|
502
|
+
validators
|
|
503
|
+
} = _ref2,
|
|
504
|
+
props = _objectWithoutProperties(_ref2, _excluded2);
|
|
505
|
+
const initialState = useMemo(() => {
|
|
506
|
+
return _buildFormInitialValues(typeof children === 'function' ? children({}) : children);
|
|
507
|
+
}, [children]);
|
|
508
|
+
return React.createElement(GFormContextProvider, {
|
|
509
|
+
key: initialState.key,
|
|
510
|
+
initialState: initialState,
|
|
511
|
+
validators: validators
|
|
512
|
+
}, React.createElement(FormRenderer, _extends({
|
|
513
|
+
ref: ref
|
|
514
|
+
}, props), children));
|
|
515
|
+
});
|
|
531
516
|
|
|
532
|
-
const _excluded = ["formKey", "element", "type", "
|
|
533
|
-
const
|
|
517
|
+
const _excluded = ["formKey", "element", "type", "fetch", "fetchDeps", "debounce", "defaultValue", "validatorKey", "value"];
|
|
518
|
+
const _RNGInput = forwardRef((_ref, ref) => {
|
|
534
519
|
let {
|
|
535
520
|
formKey,
|
|
536
521
|
element,
|
|
537
522
|
type,
|
|
538
|
-
validatorKey,
|
|
539
523
|
fetch,
|
|
540
|
-
fetchDeps
|
|
524
|
+
fetchDeps,
|
|
525
|
+
debounce = 300,
|
|
541
526
|
defaultValue,
|
|
542
|
-
|
|
543
|
-
|
|
527
|
+
validatorKey,
|
|
528
|
+
value
|
|
544
529
|
} = _ref,
|
|
545
530
|
rest = _objectWithoutProperties(_ref, _excluded);
|
|
546
|
-
const
|
|
547
|
-
|
|
548
|
-
fields
|
|
549
|
-
},
|
|
550
|
-
_updateInputHandler,
|
|
551
|
-
_dispatchChanges,
|
|
552
|
-
_viHandler,
|
|
553
|
-
_createInputChecker
|
|
554
|
-
} = useGenericFormContext();
|
|
555
|
-
const inputState = fields[formKey];
|
|
531
|
+
const inputState = useFormSelector(state => state.fields[formKey]);
|
|
532
|
+
const store = useFormStore();
|
|
556
533
|
const _element = useMemo(() => {
|
|
557
534
|
const value = inputState.value || '';
|
|
558
535
|
const _props = _objectSpread(_objectSpread({}, rest), {}, {
|
|
@@ -560,41 +537,56 @@ const RNGInput = forwardRef((_ref, ref) => {
|
|
|
560
537
|
inputMode: type,
|
|
561
538
|
ref
|
|
562
539
|
});
|
|
563
|
-
_props.onEndEditing = e => {
|
|
564
|
-
_viHandler(inputState);
|
|
565
|
-
rest.onEndEditing
|
|
540
|
+
_props.onEndEditing = rest.onEndEditing ? e => {
|
|
541
|
+
store.handlers._viHandler(inputState);
|
|
542
|
+
rest.onEndEditing(e);
|
|
543
|
+
} : () => {
|
|
544
|
+
store.handlers._viHandler(inputState);
|
|
566
545
|
};
|
|
567
|
-
_props.onChangeText = e => {
|
|
568
|
-
_updateInputHandler(
|
|
546
|
+
_props.onChangeText = rest.onChangeText ? e => {
|
|
547
|
+
store.handlers._updateInputHandler(inputState, undefined, {
|
|
548
|
+
value: e
|
|
549
|
+
});
|
|
550
|
+
rest.onChangeText(e);
|
|
551
|
+
} : e => {
|
|
552
|
+
store.handlers._updateInputHandler(inputState, undefined, {
|
|
569
553
|
value: e
|
|
570
554
|
});
|
|
571
|
-
rest.onChangeText && rest.onChangeText(e);
|
|
572
555
|
};
|
|
556
|
+
if (!inputState.touched) {
|
|
557
|
+
_props.onFocus = rest.onFocus ? e => {
|
|
558
|
+
rest.onFocus(e);
|
|
559
|
+
inputState.dispatchChanges({
|
|
560
|
+
touched: true
|
|
561
|
+
});
|
|
562
|
+
} : () => {
|
|
563
|
+
inputState.dispatchChanges({
|
|
564
|
+
touched: true
|
|
565
|
+
});
|
|
566
|
+
};
|
|
567
|
+
}
|
|
573
568
|
if (element) {
|
|
574
569
|
return element(inputState, _props);
|
|
575
570
|
}
|
|
576
571
|
return React.createElement(TextInput, _props);
|
|
577
572
|
}, [inputState, element]);
|
|
578
|
-
const _fetchDeps =
|
|
579
|
-
|
|
580
|
-
inputState.checkValidity = () => {
|
|
581
|
-
const result = _createInputChecker(inputState);
|
|
582
|
-
_dispatchChanges(inputState, formKey);
|
|
583
|
-
return result;
|
|
584
|
-
};
|
|
585
|
-
inputState.dispatchChanges = changes => _dispatchChanges(changes, formKey);
|
|
586
|
-
_dispatchChanges(inputState, formKey);
|
|
587
|
-
}, []);
|
|
573
|
+
const _fetchDeps = useFormSelector(makeSelectFields(fetchDeps));
|
|
574
|
+
const stableFetchDeps = useMemo(() => JSON.stringify(_fetchDeps), [_fetchDeps]);
|
|
588
575
|
useEffect(() => {
|
|
589
576
|
if (fetch) {
|
|
590
577
|
_debounce(debounce, `${inputState.gid}-fetch`).then(() => {
|
|
591
|
-
const res = fetch(inputState, fields);
|
|
592
|
-
res instanceof Promise
|
|
578
|
+
const res = fetch(inputState, store.getState().fields);
|
|
579
|
+
if (res instanceof Promise) {
|
|
580
|
+
res.then(state => state && store.handlers._dispatchChanges(state, formKey));
|
|
581
|
+
} else if (res) {
|
|
582
|
+
store.handlers._dispatchChanges(res, formKey);
|
|
583
|
+
}
|
|
593
584
|
});
|
|
594
585
|
}
|
|
595
|
-
},
|
|
586
|
+
}, [stableFetchDeps]);
|
|
596
587
|
return _element;
|
|
597
588
|
});
|
|
589
|
+
const RNGInput = memo(_RNGInput);
|
|
598
590
|
|
|
599
591
|
export { RNGForm, RNGInput };
|
|
600
592
|
//# sourceMappingURL=index.development.js.map
|