@formality-ui/react 0.2.2 → 0.2.3

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/index.js CHANGED
@@ -430,22 +430,15 @@ function Form({
430
430
  await handleSubmit(values);
431
431
  }, [methods, handleSubmit, waitForFieldValidation]);
432
432
  executeAutoSaveRef.current = executeAutoSave;
433
- const getOrCreateDebounced = useCallback(
434
- (ms) => {
435
- const cached = fieldDebouncersRef.current.get(ms);
436
- if (cached) return cached;
437
- const debouncedFn = debounce(() => {
438
- executeAutoSaveRef.current?.();
439
- }, ms);
440
- const fn = Object.assign(debouncedFn, {
441
- pending: () => false
442
- // lodash debounce tracks pending internally
443
- });
444
- fieldDebouncersRef.current.set(ms, fn);
445
- return fn;
446
- },
447
- []
448
- );
433
+ const getOrCreateDebounced = useCallback((ms) => {
434
+ const cached = fieldDebouncersRef.current.get(ms);
435
+ if (cached) return cached;
436
+ const fn = wrapDebounced(() => {
437
+ executeAutoSaveRef.current?.();
438
+ }, ms);
439
+ fieldDebouncersRef.current.set(ms, fn);
440
+ return fn;
441
+ }, []);
449
442
  getOrCreateDebouncedRef.current = getOrCreateDebounced;
450
443
  useEffect(() => {
451
444
  return () => {
@@ -470,13 +463,9 @@ function Form({
470
463
  }
471
464
  );
472
465
  }
473
- const debouncedFn = debounce(() => {
466
+ return wrapDebounced(() => {
474
467
  executeAutoSaveRef.current?.();
475
468
  }, debounceMs);
476
- return Object.assign(debouncedFn, {
477
- pending: () => false
478
- // lodash debounce handles this internally
479
- });
480
469
  }, [debounceMs]);
481
470
  debouncedSubmitRef.current = debouncedSubmit;
482
471
  useEffect(() => {
@@ -485,7 +474,11 @@ function Form({
485
474
  };
486
475
  }, [debouncedSubmit]);
487
476
  const submitImmediate = useCallback(() => {
488
- debouncedSubmitRef.current?.flush();
477
+ const anyPending = debouncedSubmitRef.current?.pending() === true || [...fieldDebouncersRef.current.values()].some((fn) => fn.pending());
478
+ if (!anyPending) return;
479
+ debouncedSubmitRef.current?.cancel();
480
+ fieldDebouncersRef.current.forEach((fn) => fn.cancel());
481
+ executeAutoSaveRef.current?.();
489
482
  }, []);
490
483
  const unusedFields = useMemo(() => {
491
484
  const allFields = Object.keys(config);
@@ -559,6 +552,30 @@ function Form({
559
552
  resolvedTitle
560
553
  }) : children }) }) });
561
554
  }
555
+ function wrapDebounced(callback, ms) {
556
+ let isPending = false;
557
+ const debounced = debounce(() => {
558
+ isPending = false;
559
+ callback();
560
+ }, ms);
561
+ return Object.assign(
562
+ () => {
563
+ isPending = true;
564
+ debounced();
565
+ },
566
+ {
567
+ cancel: () => {
568
+ isPending = false;
569
+ debounced.cancel();
570
+ },
571
+ flush: () => {
572
+ isPending = false;
573
+ debounced.flush();
574
+ },
575
+ pending: () => isPending
576
+ }
577
+ );
578
+ }
562
579
  function transformValuesForSubmit(values, config, inputs) {
563
580
  const result = {};
564
581
  for (const [name, value] of Object.entries(values)) {
@@ -1006,18 +1023,52 @@ function Field({
1006
1023
  }
1007
1024
  }
1008
1025
  }, [effectiveSetValue.hasCondition, effectiveSetValue.value, name]);
1026
+ const { providerSelectProps, formSelectProps, fieldSelectProps } = usePropsEvaluation({
1027
+ selectProps: fieldConfig.selectProps,
1028
+ formDefaultFieldProps: formConfig.selectDefaultFieldProps,
1029
+ providerDefaultFieldProps: providerConfig.selectDefaultFieldProps,
1030
+ subscribesTo: fieldConfig.subscribesTo,
1031
+ fieldName: name
1032
+ });
1009
1033
  const isDisabled = useMemo(() => {
1010
1034
  if (disabledProp !== void 0) return disabledProp;
1011
1035
  if (fieldConfig.disabled !== void 0) return fieldConfig.disabled;
1012
1036
  if (conditionResult.hasDisabledCondition)
1013
1037
  return conditionResult.disabled ?? false;
1014
1038
  if (groupContext.state.isDisabled) return true;
1039
+ const propsLayers = [
1040
+ fieldSelectProps,
1041
+ // layer 2: field-level selectProps
1042
+ formSelectProps,
1043
+ // layer 5: form-level selectDefaultFieldProps
1044
+ providerSelectProps,
1045
+ // layer 7: provider-level selectDefaultFieldProps
1046
+ inputConfig.props,
1047
+ // layer 4: input config props
1048
+ fieldConfig.props,
1049
+ // layer 3: field config props
1050
+ formConfig.defaultFieldProps,
1051
+ // layer 6: form-level defaultFieldProps
1052
+ providerConfig.defaultFieldProps
1053
+ // layer 8: provider-level defaultFieldProps
1054
+ ];
1055
+ for (const layer of propsLayers) {
1056
+ const layerDisabled = layer?.disabled;
1057
+ if (layerDisabled !== void 0) return Boolean(layerDisabled);
1058
+ }
1015
1059
  return false;
1016
1060
  }, [
1017
1061
  disabledProp,
1018
1062
  fieldConfig.disabled,
1063
+ fieldConfig.props,
1019
1064
  conditionResult,
1020
- groupContext.state.isDisabled
1065
+ groupContext.state.isDisabled,
1066
+ fieldSelectProps,
1067
+ formSelectProps,
1068
+ providerSelectProps,
1069
+ inputConfig.props,
1070
+ formConfig.defaultFieldProps,
1071
+ providerConfig.defaultFieldProps
1021
1072
  ]);
1022
1073
  const isVisible = useMemo(() => {
1023
1074
  if (hiddenProp !== void 0) return !hiddenProp;
@@ -1032,13 +1083,6 @@ function Field({
1032
1083
  conditionResult,
1033
1084
  groupContext.state.isVisible
1034
1085
  ]);
1035
- const { providerSelectProps, formSelectProps, fieldSelectProps } = usePropsEvaluation({
1036
- selectProps: fieldConfig.selectProps,
1037
- formDefaultFieldProps: formConfig.selectDefaultFieldProps,
1038
- providerDefaultFieldProps: providerConfig.selectDefaultFieldProps,
1039
- subscribesTo: fieldConfig.subscribesTo,
1040
- fieldName: name
1041
- });
1042
1086
  const label = useMemo(() => {
1043
1087
  return resolveLabel(name, fieldConfig, fieldSelectProps, restProps);
1044
1088
  }, [name, fieldConfig, fieldSelectProps, restProps]);