gform-react 2.0.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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, { useMemo, useState, createContext, useContext, forwardRef, useRef, useEffect } from '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);
@@ -72,10 +72,7 @@ const _buildFormInitialValues = (rows = []) => {
72
72
  });
73
73
  }
74
74
  return {
75
- state: {
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 (_unused) {
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 {
@@ -311,39 +320,13 @@ class GValidator {
311
320
  }
312
321
  }
313
322
 
314
- const useForm = (children, validators = {}, optimized = false) => {
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);
323
+ const useFormHandlers = (getState, setState, validators = {}, optimized = false) => {
341
324
  const _viHandler = (input, e) => {
342
325
  if (!input) return;
343
326
  const element = e && e.target;
344
327
  if (typeof document !== 'undefined' && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)) {
345
328
  if (!input.checkValidity) input.checkValidity = () => element.checkValidity();
346
- if (!input.dirty && input.value) {
329
+ if (!input.dirty && input.value && !input.touched) {
347
330
  _checkInputManually(input);
348
331
  _dispatchChanges(input, input.formKey);
349
332
  return;
@@ -364,6 +347,7 @@ const useForm = (children, validators = {}, optimized = false) => {
364
347
  const _checkInputManually = input => {
365
348
  let validityKey = _findValidityKey({
366
349
  valueMissing: input.required && !input.value || false,
350
+ typeMismatch: _checkTypeMismatch(input),
367
351
  tooShort: input.minLength && input.value.toString().length < input.minLength || false,
368
352
  tooLong: input.maxLength && input.value.toString().length > input.maxLength || false,
369
353
  patternMismatch: input.pattern && _checkResult(input.pattern, input.value) || false,
@@ -376,22 +360,17 @@ const useForm = (children, validators = {}, optimized = false) => {
376
360
  _validateInput(input, validityKey);
377
361
  return !input.error;
378
362
  };
379
- const _updateInputHandler = (key, e, unknown) => {
380
- const value = _extractValue(e, unknown);
381
- const input = _updateInput(key, value);
363
+ const _updateInputHandler = (input, e, unknown) => {
364
+ input.value = _extractValue(e, unknown);
382
365
  _viHandler(input, e);
383
366
  };
384
367
  const _validateInput = (input, validityKey, setValidity) => {
385
368
  const inputValidator = validators[input.validatorKey || input.formKey] || validators['*'];
386
- inputValidator && __validateInput(input, inputValidator, validityKey, setValidity);
369
+ if (inputValidator) {
370
+ __validateInput(input, inputValidator, validityKey, setValidity);
371
+ }
387
372
  input.touched = true;
388
373
  };
389
- const _updateInput = (key, value) => {
390
- const input = state.fields[key];
391
- input.value = value;
392
- input.dirty = true;
393
- return input;
394
- };
395
374
  const _dispatchChanges = (changes, key) => setState(prev => {
396
375
  if (key) {
397
376
  return _objectSpread(_objectSpread({}, prev), {}, {
@@ -403,13 +382,14 @@ const useForm = (children, validators = {}, optimized = false) => {
403
382
  return _objectSpread(_objectSpread({}, prev), changes);
404
383
  });
405
384
  const __validateInput = (input, inputValidator, validityKey, setValidity) => {
385
+ const fields = getState().fields;
406
386
  for (const index in inputValidator.constraintHandlers) {
407
387
  const result = inputValidator.constraintHandlers[index](input, validityKey);
408
388
  input.error = _checkResult(result, input.value);
409
389
  if (input.error) return;
410
390
  }
411
391
  for (const index in inputValidator.handlers) {
412
- const result = inputValidator.handlers[index](input, state.fields);
392
+ const result = inputValidator.handlers[index](input, fields);
413
393
  input.error = _checkResult(result, input.value);
414
394
  if (input.error) return;
415
395
  }
@@ -419,7 +399,7 @@ const useForm = (children, validators = {}, optimized = false) => {
419
399
  _debounce(input.debounce || 300, `${input.gid}-async`).then(() => {
420
400
  const validateAsync = async () => {
421
401
  for (const index in inputValidator.asyncHandlers) {
422
- const result = await inputValidator.asyncHandlers[index](input, state.fields);
402
+ const result = await inputValidator.asyncHandlers[index](input, fields);
423
403
  input.error = _checkResult(result, input.value);
424
404
  if (input.error) break;
425
405
  }
@@ -428,187 +408,265 @@ const useForm = (children, validators = {}, optimized = false) => {
428
408
  error: input.error,
429
409
  errorText: input.errorText
430
410
  }, input.formKey);
431
- setValidity && setValidity(input.errorText);
411
+ if (setValidity) {
412
+ setValidity(input.errorText);
413
+ }
432
414
  };
433
415
  validateAsync();
434
416
  });
435
417
  }
436
418
  };
437
419
  return {
438
- state,
439
420
  _updateInputHandler,
440
421
  _viHandler,
441
422
  _dispatchChanges,
442
423
  optimized,
443
- key: initialValues.key,
444
424
  _createInputChecker: _checkInputManually
445
425
  };
446
426
  };
447
427
 
448
- const gFormContext = createContext({
449
- state: {
450
- fields: {},
451
- loading: false
452
- },
453
- _updateInputHandler: () => null,
454
- _viHandler: () => null,
455
- _dispatchChanges: () => null,
456
- _createInputChecker: () => false,
457
- optimized: false,
458
- key: ''
428
+ const GFormContext = createContext({});
429
+ const GFormContextProvider = ({
430
+ children,
431
+ initialState,
432
+ validators,
433
+ optimized
434
+ }) => {
435
+ const stateRef = useRef(initialState);
436
+ const listeners = useRef(new Set());
437
+ const setState = useCallback(updater => {
438
+ stateRef.current = typeof updater === 'function' ? updater(stateRef.current) : updater;
439
+ listeners.current.forEach(l => l());
440
+ }, []);
441
+ const handlers = useFormHandlers(() => stateRef.current, setState, validators, optimized);
442
+ const getState = useCallback(() => stateRef.current, []);
443
+ const subscribe = useCallback(listener => {
444
+ listeners.current.add(listener);
445
+ return () => listeners.current.delete(listener);
446
+ }, []);
447
+ useEffect(() => {
448
+ for (const fieldKey in initialState.fields) {
449
+ initialState.fields[fieldKey].dispatchChanges = changes => handlers._dispatchChanges(changes, fieldKey);
450
+ }
451
+ }, []);
452
+ const store = useRef({
453
+ getState,
454
+ setState,
455
+ subscribe,
456
+ handlers
457
+ });
458
+ return React.createElement(GFormContext.Provider, {
459
+ value: store.current
460
+ }, children);
461
+ };
462
+ const useFormStore = () => {
463
+ const store = useContext(GFormContext);
464
+ if (!store) throw new Error('useGFormStore must be used within `GForm` component');
465
+ return store;
466
+ };
467
+ const useFormSelector = selector => {
468
+ const store = useFormStore();
469
+ return useSyncExternalStore(store.subscribe, () => selector(store.getState()), () => selector(store.getState()));
470
+ };
471
+ function createSelector(selectors, combiner) {
472
+ let lastArgs = [];
473
+ let lastResult;
474
+ return state => {
475
+ const args = selectors.map(fn => fn(state));
476
+ if (lastArgs.length === args.length && args.every((val, i) => val === lastArgs[i])) {
477
+ return lastResult;
478
+ }
479
+ lastArgs = args;
480
+ lastResult = combiner(...args);
481
+ return lastResult;
482
+ };
483
+ }
484
+
485
+ const selectFields = [state => state.fields];
486
+ const selectFirstInvalidField = createSelector(selectFields, fields => {
487
+ for (const f in fields) {
488
+ if (fields[f].error) {
489
+ return true;
490
+ }
491
+ }
492
+ return false;
493
+ });
494
+ const makeSelectFields = (keys = []) => createSelector(selectFields, fields => {
495
+ const selected = keys.map(key => fields[key]).filter(Boolean);
496
+ return selected.length ? selected : null;
459
497
  });
460
- const useGenericFormContext = () => useContext(gFormContext);
461
- const GFormContextProvider = gFormContext.Provider;
462
498
 
463
- const _excluded$1 = ["loader", "stateRef", "onSubmit", "onChange", "onPaste", "children", "validators", "onInit", "optimized"];
464
- const GForm = (() => {
465
- return forwardRef((_ref, ref) => {
466
- let {
467
- loader = React.createElement("div", null, "loading"),
468
- stateRef,
469
- onSubmit,
470
- onChange,
471
- onPaste,
472
- children,
473
- validators,
474
- onInit,
475
- optimized
476
- } = _ref,
477
- rest = _objectWithoutProperties(_ref, _excluded$1);
478
- const formRef = useRef(null);
479
- const values = useForm(children, validators, optimized);
480
- const {
481
- state,
482
- _updateInputHandler,
483
- _viHandler,
484
- _dispatchChanges,
485
- key
486
- } = values;
487
- const refHandler = element => {
488
- if (ref) {
489
- if (typeof ref === 'function') {
490
- ref(element);
491
- } else {
492
- ref.current = element;
493
- }
499
+ const _excluded$1 = ["stateRef", "onSubmit", "onChange", "onPaste", "onKeyDown", "onKeyUp", "children", "onInit"],
500
+ _excluded2 = ["children", "validators", "optimized"];
501
+ const FormRenderer = forwardRef((_ref, ref) => {
502
+ let {
503
+ stateRef,
504
+ onSubmit,
505
+ onChange,
506
+ onPaste,
507
+ onKeyDown,
508
+ onKeyUp,
509
+ children,
510
+ onInit
511
+ } = _ref,
512
+ rest = _objectWithoutProperties(_ref, _excluded$1);
513
+ const formRef = useRef(null);
514
+ const {
515
+ getState,
516
+ handlers
517
+ } = useFormStore();
518
+ const isFormInvalid = useFormSelector(selectFirstInvalidField);
519
+ const refHandler = useCallback(element => {
520
+ if (ref) {
521
+ if (typeof ref === 'function') {
522
+ ref(element);
523
+ } else {
524
+ ref.current = element;
525
+ }
526
+ }
527
+ formRef.current = element;
528
+ }, [ref]);
529
+ const getFormState = useCallback(() => {
530
+ const fields = getState().fields;
531
+ const formState = _objectSpread(_objectSpread({}, fields), {}, {
532
+ isValid: !isFormInvalid,
533
+ isInvalid: isFormInvalid,
534
+ toRawData: options => _toRawData(fields, options),
535
+ toFormData: () => _toFormData(formRef.current),
536
+ toURLSearchParams: _toURLSearchParams,
537
+ checkValidity: function () {
538
+ this.isValid = formRef.current && formRef.current.checkValidity() || false;
539
+ this.isInvalid = !this.isValid;
540
+ return this.isValid;
541
+ },
542
+ dispatchChanges: changes => handlers._dispatchChanges({
543
+ fields: _merge({}, fields, changes)
544
+ })
545
+ });
546
+ if (stateRef) stateRef.current = formState;
547
+ return formState;
548
+ }, [isFormInvalid]);
549
+ const formComponent = useMemo(() => {
550
+ const state = getFormState();
551
+ const formChildren = typeof children === 'function' ? children(state) : children;
552
+ const _onSubmit = e => {
553
+ const state = getFormState();
554
+ if (state.isValid && onSubmit) {
555
+ onSubmit(state, e);
494
556
  }
495
- formRef.current = element;
496
557
  };
497
- const formState = useMemo(() => {
498
- const _isFormValid = _checkIfFormIsValid(state.fields);
499
- const formState = _objectSpread(_objectSpread({}, state.fields), {}, {
500
- isValid: _isFormValid,
501
- isInvalid: !_isFormValid,
502
- loading: state.loading,
503
- toRawData: options => _toRawData(state.fields, options),
504
- toFormData: () => _toFormData(formRef.current),
505
- toURLSearchParams: _toURLSearchParams,
506
- checkValidity: function () {
507
- this.isValid = formRef.current && formRef.current.checkValidity() || false;
508
- this.isInvalid = !this.isValid;
509
- return this.isValid;
510
- },
511
- setLoading: p => _dispatchChanges({
512
- loading: typeof p === 'function' ? p(state.loading) : p
513
- }),
514
- dispatchChanges: changes => _dispatchChanges({
515
- fields: _merge({}, state.fields, changes)
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);
558
+ let _onPaste, _onChange, _onKeyDown, _onKeyUp;
559
+ if (onPaste) {
560
+ _onPaste = e => onPaste(state, e);
561
+ }
562
+ if (onKeyDown) {
563
+ _onKeyDown = e => onKeyDown(state, e);
564
+ }
565
+ if (onKeyUp) {
566
+ _onKeyUp = e => onKeyUp(state, e);
567
+ }
568
+ if (handlers.optimized) {
569
+ if (onChange) {
570
+ _onChange = (e, unknown) => {
571
+ handlers._updateInputHandler(state[e.target.name], e, unknown);
572
+ onChange(state, e);
573
+ };
574
+ } else {
575
+ _onChange = (e, unknown) => {
576
+ handlers._updateInputHandler(state[e.target.name], e, unknown);
577
+ };
531
578
  }
532
- return optimized ? React.createElement("form", _extends({}, rest, {
579
+ return React.createElement("form", _extends({}, rest, {
533
580
  ref: refHandler,
534
581
  onPaste: _onPaste,
535
- onBlur: e => {
536
- _viHandler(state.fields[e.target.name], e);
537
- },
582
+ onKeyDown: _onKeyDown,
583
+ onKeyUp: _onKeyUp,
584
+ onBlur: e => handlers._viHandler(state[e.target.name], e),
538
585
  onInvalid: e => {
539
586
  e.preventDefault();
540
- _viHandler(state.fields[e.target.name], e);
541
- },
542
- onChange: (e, unknown) => {
543
- _updateInputHandler(e.target.name, e, unknown);
544
- onChange && onChange(formState, e);
587
+ handlers._viHandler(state[e.target.name], e);
545
588
  },
589
+ onChange: _onChange,
546
590
  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
591
  }), formChildren);
553
- }, [formState, children]);
554
- useEffect(() => {
555
- if (!hasSubmitter(formRef.current)) {
556
- 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`);
557
- }
558
- if (onInit) {
559
- const _handler = _c => _dispatchChanges({
560
- fields: _merge({}, state.fields, _c)
592
+ }
593
+ if (onChange) {
594
+ _onChange = e => onChange(state, e);
595
+ }
596
+ return React.createElement("form", _extends({}, rest, {
597
+ ref: refHandler,
598
+ onSubmit: _onSubmit,
599
+ onChange: _onChange,
600
+ onPaste: _onPaste,
601
+ onKeyDown: _onKeyDown,
602
+ onKeyUp: _onKeyUp
603
+ }), formChildren);
604
+ }, [children, getFormState]);
605
+ useEffect(() => {
606
+ const state = getFormState();
607
+ if (!hasSubmitter(formRef.current)) {
608
+ 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`);
609
+ }
610
+ if (onInit) {
611
+ const changes = onInit(state);
612
+ if (changes) {
613
+ const _handler = _c => handlers._dispatchChanges({
614
+ fields: _merge({}, state, _c)
561
615
  });
562
- const changes = onInit(formState);
563
- changes instanceof Promise ? changes.then(_handler) : _handler(changes);
616
+ if (changes instanceof Promise) {
617
+ changes.then(_handler);
618
+ } else _handler(changes);
564
619
  }
565
- const dipatchers = {};
566
- Object.values(state.fields).forEach(field => {
567
- dipatchers[field.formKey] = {
568
- dispatchChanges: changes => _dispatchChanges(changes, field.formKey)
569
- };
570
- if (!field.value) return;
571
- _viHandler(field);
572
- });
573
- _dispatchChanges({
574
- fields: _merge(dipatchers, state.fields)
575
- });
576
- }, []);
577
- return React.createElement(GFormContextProvider, {
578
- value: values,
579
- key: key
580
- }, state.loading ? loader : formComponent);
581
- });
582
- })();
620
+ }
621
+ const fields = getState().fields;
622
+ for (const fieldKey in fields) {
623
+ const field = fields[fieldKey];
624
+ if (!field.value) continue;
625
+ handlers._viHandler(field);
626
+ }
627
+ }, [getFormState]);
628
+ return formComponent;
629
+ });
630
+ const GForm = forwardRef((_ref2, ref) => {
631
+ let {
632
+ children,
633
+ validators,
634
+ optimized
635
+ } = _ref2,
636
+ props = _objectWithoutProperties(_ref2, _excluded2);
637
+ const initialState = useMemo(() => {
638
+ return _buildFormInitialValues(typeof children === 'function' ? children({}) : children);
639
+ }, [children]);
640
+ return React.createElement(GFormContextProvider, {
641
+ key: initialState.key,
642
+ initialState: initialState,
643
+ validators: validators,
644
+ optimized: optimized
645
+ }, React.createElement(FormRenderer, _extends({
646
+ ref: ref
647
+ }, props), children));
648
+ });
583
649
 
584
- const _excluded = ["formKey", "element", "title", "type", "validatorKey", "fetch", "fetchDeps", "optimized", "defaultChecked", "defaultValue", "checked", "value", "debounce"];
585
- const GInput = forwardRef((_ref, ref) => {
650
+ const _excluded = ["formKey", "element", "title", "type", "fetch", "fetchDeps", "optimized", "debounce", "defaultChecked", "defaultValue", "checked", "validatorKey", "value"];
651
+ const _GInput = forwardRef((_ref, ref) => {
586
652
  let {
587
653
  formKey,
588
654
  element,
589
655
  title,
590
- type,
591
- validatorKey,
656
+ type = 'text',
592
657
  fetch,
593
- fetchDeps = [],
658
+ fetchDeps,
594
659
  optimized,
660
+ debounce = 300,
595
661
  defaultChecked,
596
662
  defaultValue,
597
663
  checked,
598
- value,
599
- debounce = 300
664
+ validatorKey,
665
+ value
600
666
  } = _ref,
601
667
  rest = _objectWithoutProperties(_ref, _excluded);
602
- const {
603
- state: {
604
- fields
605
- },
606
- _updateInputHandler,
607
- _dispatchChanges,
608
- optimized: formOptimized,
609
- _viHandler
610
- } = useGenericFormContext();
611
- const inputState = fields[formKey];
668
+ const inputState = useFormSelector(state => state.fields[formKey]);
669
+ const store = useFormStore();
612
670
  const _element = useMemo(() => {
613
671
  let value, checked;
614
672
  if (type === 'checkbox') checked = inputState.value || false;else value = inputState.value || '';
@@ -622,19 +680,26 @@ const GInput = forwardRef((_ref, ref) => {
622
680
  'aria-required': inputState.required,
623
681
  title: title || inputState.errorText
624
682
  });
625
- if (!formOptimized || !optimized) {
626
- _props.onBlur = e => {
627
- _viHandler(inputState, e);
628
- rest.onBlur && rest.onBlur(e);
683
+ if (!store.handlers.optimized || !optimized) {
684
+ _props.onBlur = rest.onBlur ? e => {
685
+ store.handlers._viHandler(inputState, e);
686
+ rest.onBlur(e);
687
+ } : e => {
688
+ store.handlers._viHandler(inputState, e);
629
689
  };
630
- _props.onInvalid = e => {
690
+ _props.onInvalid = rest.onInvalid ? e => {
631
691
  e.preventDefault();
632
- _viHandler(inputState, e);
633
- rest.onInvalid && rest.onInvalid(e);
692
+ store.handlers._viHandler(inputState, e);
693
+ rest.onInvalid(e);
694
+ } : e => {
695
+ e.preventDefault();
696
+ store.handlers._viHandler(inputState, e);
634
697
  };
635
- _props.onChange = (e, unknown) => {
636
- _updateInputHandler(formKey, e, unknown);
637
- rest.onChange && rest.onChange(e);
698
+ _props.onChange = rest.onChange ? (e, unknown) => {
699
+ store.handlers._updateInputHandler(inputState, e, unknown);
700
+ rest.onChange(e);
701
+ } : (e, unknown) => {
702
+ store.handlers._updateInputHandler(inputState, e, unknown);
638
703
  };
639
704
  }
640
705
  if (element) {
@@ -642,18 +707,23 @@ const GInput = forwardRef((_ref, ref) => {
642
707
  }
643
708
  return React.createElement("input", _props);
644
709
  }, [inputState, element]);
645
- const _fetchDeps = useMemo(() => fetchDeps.map(key => fields[key].value), [fields]);
710
+ const _fetchDeps = useFormSelector(makeSelectFields(fetchDeps));
711
+ const stableFetchDeps = useMemo(() => JSON.stringify(_fetchDeps), [_fetchDeps]);
646
712
  useEffect(() => {
647
713
  if (fetch) {
648
- inputState.dispatchChanges = changes => _dispatchChanges(changes, formKey);
649
714
  _debounce(debounce, `${inputState.gid}-fetch`).then(() => {
650
- const res = fetch(inputState, fields);
651
- res instanceof Promise ? res.then(state => state && _dispatchChanges(state, formKey)) : res && _dispatchChanges(res, formKey);
715
+ const res = fetch(inputState, store.getState().fields);
716
+ if (res instanceof Promise) {
717
+ res.then(state => state && store.handlers._dispatchChanges(state, formKey));
718
+ } else if (res) {
719
+ store.handlers._dispatchChanges(res, formKey);
720
+ }
652
721
  });
653
722
  }
654
- }, _fetchDeps);
723
+ }, [stableFetchDeps]);
655
724
  return _element;
656
725
  });
726
+ const GInput = memo(_GInput);
657
727
 
658
- export { GForm, GInput, GValidator };
728
+ export { GForm, GInput, GValidator, useFormSelector };
659
729
  //# sourceMappingURL=index.development.js.map