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.
Files changed (30) hide show
  1. package/dist/cjs/gform-react.development.js +314 -213
  2. package/dist/cjs/gform-react.development.js.map +1 -1
  3. package/dist/cjs/gform-react.production.js +1 -1
  4. package/dist/cjs/gform-react.production.js.map +1 -1
  5. package/dist/esm/GForm.production.js +1 -1
  6. package/dist/esm/GForm.production.js.map +1 -1
  7. package/dist/esm/GInput.production.js +1 -1
  8. package/dist/esm/GInput.production.js.map +1 -1
  9. package/dist/esm/GValidator.production.js +1 -1
  10. package/dist/esm/GValidator.production.js.map +1 -1
  11. package/dist/esm/index.development.js +320 -218
  12. package/dist/esm/index.development.js.map +1 -1
  13. package/dist/esm/index.js +2 -1
  14. package/dist/esm/shared.production.js +1 -1
  15. package/dist/esm/shared.production.js.map +1 -1
  16. package/dist/index.d.ts +13 -13
  17. package/native/dist/cjs/gform-react-native.development.js +254 -264
  18. package/native/dist/cjs/gform-react-native.development.js.map +1 -1
  19. package/native/dist/cjs/gform-react-native.production.js +1 -1
  20. package/native/dist/cjs/gform-react-native.production.js.map +1 -1
  21. package/native/dist/esm/RNGForm.production.js +1 -1
  22. package/native/dist/esm/RNGForm.production.js.map +1 -1
  23. package/native/dist/esm/RNGInput.production.js +1 -1
  24. package/native/dist/esm/RNGInput.production.js.map +1 -1
  25. package/native/dist/esm/index.development.js +260 -268
  26. package/native/dist/esm/index.development.js.map +1 -1
  27. package/native/dist/esm/shared.production.js +1 -1
  28. package/native/dist/esm/shared.production.js.map +1 -1
  29. package/native/dist/index.d.ts +4 -8
  30. 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, { useMemo, useState, createContext, useContext, forwardRef, useEffect } from 'react';
5
- import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
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
- state: {
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 _checkIfFormIsValid = fields => {
104
- for (const f in fields) {
105
- if (fields[f].error) {
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 useForm = (children, validators = {}, optimized = false) => {
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 (!input.dirty && input.value) {
239
+ if (hasInitialValue) {
337
240
  _checkInputManually(input);
338
241
  _dispatchChanges(input, input.formKey);
339
242
  return;
340
243
  }
341
244
  element.setCustomValidity('');
342
- const validityKey = _findValidityKey(element.validity);
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 = (key, e, unknown) => {
370
- const value = _extractValue(e, unknown);
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
- inputValidator && __validateInput(input, inputValidator, validityKey, setValidity);
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, state.fields);
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, state.fields);
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
- setValidity && setValidity(input.errorText);
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 gFormContext = createContext({
439
- state: {
440
- fields: {},
441
- loading: false
442
- },
443
- _updateInputHandler: () => null,
444
- _viHandler: () => null,
445
- _dispatchChanges: () => null,
446
- _createInputChecker: () => false,
447
- optimized: false,
448
- key: ''
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 = ["loader", "stateRef", "children", "validators", "onInit", "el"];
454
- const RNGForm = (() => {
455
- return forwardRef((_ref, ref) => {
456
- let {
457
- loader = React.createElement("div", null, "loading"),
458
- stateRef,
459
- children,
460
- validators,
461
- onInit,
462
- el: El
463
- } = _ref,
464
- rest = _objectWithoutProperties(_ref, _excluded$1);
465
- const values = useForm(children, validators);
466
- const {
467
- state,
468
- _dispatchChanges,
469
- key,
470
- _viHandler
471
- } = values;
472
- const formState = useMemo(() => {
473
- const _isFormValid = _checkIfFormIsValid(state.fields);
474
- const formState = _objectSpread(_objectSpread({}, state.fields), {}, {
475
- isValid: _isFormValid,
476
- isInvalid: !_isFormValid,
477
- loading: state.loading,
478
- toRawData: options => _toRawData(state.fields, options),
479
- toURLSearchParams: _toURLSearchParams,
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
- return true;
488
- },
489
- setLoading: p => _dispatchChanges({
490
- loading: typeof p === 'function' ? p(state.loading) : p
491
- }),
492
- dispatchChanges: changes => _dispatchChanges({
493
- fields: _merge({}, state.fields, changes)
494
- })
495
- });
496
- if (stateRef) stateRef.current = formState;
497
- return formState;
498
- }, [state.fields]);
499
- useEffect(() => {
500
- if (onInit) {
501
- const _handler = _c => _dispatchChanges({
502
- fields: _merge({}, state.fields, _c)
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
- const changes = onInit(formState);
505
- changes instanceof Promise ? changes.then(_handler) : _handler(changes);
473
+ if (changes instanceof Promise) {
474
+ changes.then(_handler);
475
+ } else _handler(changes);
506
476
  }
507
- const dipatchers = {};
508
- Object.values(state.fields).forEach(field => {
509
- dipatchers[field.formKey] = {
510
- dispatchChanges: changes => _dispatchChanges(changes, field.formKey)
511
- };
512
- if (!field.value) return;
513
- _viHandler(field);
514
- });
515
- _dispatchChanges({
516
- fields: _merge(dipatchers, state.fields)
517
- });
518
- }, []);
519
- const formComponent = useMemo(() => {
520
- const formChildren = typeof children === 'function' ? children(formState) : children;
521
- return React.createElement(El, _extends({}, rest, {
522
- ref: ref
523
- }), formChildren);
524
- }, [formState, children]);
525
- return React.createElement(GFormContextProvider, {
526
- value: values,
527
- key: key
528
- }, state.loading ? loader : formComponent);
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", "validatorKey", "fetch", "fetchDeps", "defaultValue", "value", "debounce"];
533
- const RNGInput = forwardRef((_ref, ref) => {
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
- value,
543
- debounce = 300
527
+ validatorKey,
528
+ value
544
529
  } = _ref,
545
530
  rest = _objectWithoutProperties(_ref, _excluded);
546
- const {
547
- state: {
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 && rest.onEndEditing(e);
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(formKey, undefined, {
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 = useMemo(() => fetchDeps.map(key => fields[key].value), [fields]);
579
- useEffect(() => {
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 ? res.then(state => state && _dispatchChanges(state, formKey)) : res && _dispatchChanges(res, formKey);
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
- }, _fetchDeps);
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