hs-uix 1.4.0 → 1.4.1

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/form.js CHANGED
@@ -667,9 +667,10 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
667
667
  const inputDebounceRef = (0, import_react.useRef)(/* @__PURE__ */ new Map());
668
668
  const rowKeyRef = (0, import_react.useRef)(/* @__PURE__ */ new WeakMap());
669
669
  const rowKeyCounterRef = (0, import_react.useRef)(0);
670
+ const controlledBaselineLockedRef = (0, import_react.useRef)(false);
670
671
  const initialSnapshot = (0, import_react.useRef)(null);
671
672
  if (initialSnapshot.current === null) {
672
- initialSnapshot.current = deepClone(computeInitialValues());
673
+ initialSnapshot.current = deepClone(values != null ? values : computeInitialValues());
673
674
  }
674
675
  const formValues = values != null ? values : internalValues;
675
676
  const formErrors = controlledErrors != null ? controlledErrors : internalErrors;
@@ -681,6 +682,10 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
681
682
  const draftValuesRef = (0, import_react.useRef)(null);
682
683
  formValuesRef.current = formValues;
683
684
  formErrorsRef.current = formErrors;
685
+ const syncDirtyBaseline = (0, import_react.useCallback)((nextValues) => {
686
+ initialSnapshot.current = deepClone(nextValues || {});
687
+ prevAutoSaveValues.current = deepClone(nextValues || {});
688
+ }, []);
684
689
  const fieldByName = (0, import_react.useMemo)(() => {
685
690
  const map = /* @__PURE__ */ new Map();
686
691
  for (const field of fields) {
@@ -757,6 +762,11 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
757
762
  if (autoSaveTimerRef.current) clearTimeout(autoSaveTimerRef.current);
758
763
  };
759
764
  }, []);
765
+ (0, import_react.useEffect)(() => {
766
+ if (values == null) return;
767
+ if (controlledBaselineLockedRef.current) return;
768
+ syncDirtyBaseline(values);
769
+ }, [values, syncDirtyBaseline]);
760
770
  const isDirty = (0, import_react.useMemo)(() => {
761
771
  return !deepEqual(formValues, initialSnapshot.current);
762
772
  }, [formValues]);
@@ -875,6 +885,50 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
875
885
  },
876
886
  [fieldTypes]
877
887
  );
888
+ const setRepeaterSubFieldError = (0, import_react.useCallback)(
889
+ (fieldName, rowIdx, subFieldName, errorMessage) => {
890
+ const key = getRepeaterErrorKey(fieldName, rowIdx, subFieldName);
891
+ const merged = { ...formErrorsRef.current };
892
+ if (errorMessage) {
893
+ merged[key] = errorMessage;
894
+ } else {
895
+ delete merged[key];
896
+ }
897
+ const subErrors = Object.keys(merged).filter((k) => k.startsWith(`${fieldName}[`)).map((k) => {
898
+ const match = k.match(/\[(\d+)\]\./);
899
+ const row = match ? Number(match[1]) : Number.MAX_SAFE_INTEGER;
900
+ return { key: k, row };
901
+ }).sort((a, b) => a.row - b.row);
902
+ if (subErrors.length > 0) {
903
+ const first = subErrors[0];
904
+ merged[fieldName] = `Row ${first.row + 1}: ${merged[first.key]}`;
905
+ } else if (!merged[fieldName] || merged[fieldName].startsWith("Row ")) {
906
+ delete merged[fieldName];
907
+ }
908
+ replaceErrors(merged);
909
+ },
910
+ [replaceErrors]
911
+ );
912
+ const expandValidationFields = (0, import_react.useCallback)(
913
+ (fieldSubset) => {
914
+ const toValidate = fieldSubset || visibleFields;
915
+ const expanded = [];
916
+ for (const field of toValidate) {
917
+ if (field.type === "fieldGroup" && field.items && field.fields) {
918
+ for (const item of field.items) {
919
+ for (const subField of field.fields(item)) {
920
+ if (subField.visible && !subField.visible(formValues)) continue;
921
+ expanded.push(subField);
922
+ }
923
+ }
924
+ continue;
925
+ }
926
+ expanded.push(field);
927
+ }
928
+ return expanded;
929
+ },
930
+ [visibleFields, formValues]
931
+ );
878
932
  const validateField = (0, import_react.useCallback)(
879
933
  (name, value) => {
880
934
  const field = fieldByName.get(name);
@@ -894,7 +948,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
894
948
  );
895
949
  const validateVisibleFields = (0, import_react.useCallback)(
896
950
  (fieldSubset) => {
897
- const toValidate = fieldSubset || visibleFields;
951
+ const toValidate = expandValidationFields(fieldSubset);
898
952
  const errors = {};
899
953
  let hasErrors = false;
900
954
  for (const field of toValidate) {
@@ -914,52 +968,54 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
914
968
  }
915
969
  return { errors, hasErrors };
916
970
  },
917
- [visibleFields, formValues, validateRepeaterField, fieldTypes, validationMessages]
971
+ [expandValidationFields, formValues, validateRepeaterField, fieldTypes, validationMessages]
918
972
  );
919
- const runAsyncValidation = (0, import_react.useCallback)(
920
- (name, value) => {
921
- const field = fieldByName.get(name);
922
- if (!field || field.type === "repeater") return null;
923
- const val = value != null ? value : formValues[name];
924
- const syncError = runValidators(val, field, formValues, fieldTypes, { includeCustomValidators: false, messages: validationMessages });
925
- const prevController = asyncAbortRef.current.get(name);
973
+ const runAsyncValidationTarget = (0, import_react.useCallback)(
974
+ (target) => {
975
+ const { validationKey, field, value, allValues, applyError } = target || {};
976
+ if (!field || !validationKey || field.type === "repeater" || field.type === "fieldGroup") return null;
977
+ const syncError = runValidators(value, field, allValues, fieldTypes, {
978
+ includeCustomValidators: false,
979
+ messages: validationMessages
980
+ });
981
+ const prevController = asyncAbortRef.current.get(validationKey);
926
982
  if (prevController) prevController.abort();
927
- asyncAbortRef.current.delete(name);
983
+ asyncAbortRef.current.delete(validationKey);
928
984
  setValidatingFields((prev) => {
929
- if (!prev[name]) return prev;
985
+ if (!prev[validationKey]) return prev;
930
986
  const next = { ...prev };
931
- delete next[name];
987
+ delete next[validationKey];
932
988
  return next;
933
989
  });
934
990
  if (syncError) return null;
935
- const version = (asyncValidationVersionRef.current.get(name) || 0) + 1;
936
- asyncValidationVersionRef.current.set(name, version);
991
+ const version = (asyncValidationVersionRef.current.get(validationKey) || 0) + 1;
992
+ asyncValidationVersionRef.current.set(validationKey, version);
937
993
  const controller = typeof AbortController !== "undefined" ? new AbortController() : null;
938
- if (controller) asyncAbortRef.current.set(name, controller);
994
+ if (controller) asyncAbortRef.current.set(validationKey, controller);
939
995
  let asyncPromises;
940
996
  try {
941
997
  asyncPromises = collectAsyncValidatorPromises(
942
- val,
998
+ value,
943
999
  field,
944
- formValues,
1000
+ allValues,
945
1001
  controller ? { signal: controller.signal } : void 0
946
1002
  );
947
1003
  } catch (err) {
948
- updateErrors({ [name]: (err == null ? void 0 : err.message) || "Validation failed" });
1004
+ applyError((err == null ? void 0 : err.message) || "Validation failed");
949
1005
  return null;
950
1006
  }
951
1007
  if (asyncPromises.length === 0) {
952
- asyncAbortRef.current.delete(name);
1008
+ asyncAbortRef.current.delete(validationKey);
953
1009
  return null;
954
1010
  }
955
1011
  const validationPromise = Promise.all(asyncPromises).then(
956
1012
  (results) => {
957
- if (asyncValidationVersionRef.current.get(name) !== version) return;
958
- asyncValidationRef.current.delete(name);
959
- asyncAbortRef.current.delete(name);
1013
+ if (asyncValidationVersionRef.current.get(validationKey) !== version) return;
1014
+ asyncValidationRef.current.delete(validationKey);
1015
+ asyncAbortRef.current.delete(validationKey);
960
1016
  setValidatingFields((prev) => {
961
1017
  const next = { ...prev };
962
- delete next[name];
1018
+ delete next[validationKey];
963
1019
  return next;
964
1020
  });
965
1021
  let err = null;
@@ -970,50 +1026,128 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
970
1026
  break;
971
1027
  }
972
1028
  }
973
- updateErrors({ [name]: err });
1029
+ applyError(err);
974
1030
  },
975
1031
  (rejection) => {
976
- if (asyncValidationVersionRef.current.get(name) !== version) return;
977
- asyncValidationRef.current.delete(name);
978
- asyncAbortRef.current.delete(name);
1032
+ if (asyncValidationVersionRef.current.get(validationKey) !== version) return;
1033
+ asyncValidationRef.current.delete(validationKey);
1034
+ asyncAbortRef.current.delete(validationKey);
979
1035
  setValidatingFields((prev) => {
980
1036
  const next = { ...prev };
981
- delete next[name];
1037
+ delete next[validationKey];
982
1038
  return next;
983
1039
  });
984
1040
  if (rejection && rejection.name === "AbortError") return;
985
- updateErrors({ [name]: (rejection == null ? void 0 : rejection.message) || "Validation failed" });
1041
+ applyError((rejection == null ? void 0 : rejection.message) || "Validation failed");
986
1042
  }
987
1043
  );
988
- asyncValidationRef.current.set(name, validationPromise);
989
- setValidatingFields((prev) => ({ ...prev, [name]: true }));
1044
+ asyncValidationRef.current.set(validationKey, validationPromise);
1045
+ setValidatingFields((prev) => ({ ...prev, [validationKey]: true }));
990
1046
  return validationPromise;
991
1047
  },
992
- [fieldByName, formValues, fieldTypes, updateErrors]
1048
+ [fieldTypes, validationMessages]
993
1049
  );
994
- const triggerAsyncValidation = (0, import_react.useCallback)(
1050
+ const runAsyncValidation = (0, import_react.useCallback)(
995
1051
  (name, value) => {
996
1052
  const field = fieldByName.get(name);
997
- if (!field || field.type === "repeater") return;
998
- const debounceMs = field.validateDebounce;
1053
+ if (!field || field.type === "repeater" || field.type === "fieldGroup") return null;
1054
+ return runAsyncValidationTarget({
1055
+ validationKey: name,
1056
+ field,
1057
+ value: value != null ? value : formValues[name],
1058
+ allValues: formValues,
1059
+ applyError: (errorMessage) => updateErrors({ [name]: errorMessage })
1060
+ });
1061
+ },
1062
+ [fieldByName, formValues, runAsyncValidationTarget, updateErrors]
1063
+ );
1064
+ const triggerAsyncValidationTarget = (0, import_react.useCallback)(
1065
+ (target) => {
1066
+ if (!(target == null ? void 0 : target.field) || !target.validationKey) return;
1067
+ const debounceMs = target.field.validateDebounce;
999
1068
  if (debounceMs && debounceMs > 0) {
1000
- const existing = debounceTimersRef.current.get(name);
1069
+ const existing = debounceTimersRef.current.get(target.validationKey);
1001
1070
  if (existing) clearTimeout(existing);
1002
1071
  const timer = setTimeout(() => {
1003
- debounceTimersRef.current.delete(name);
1004
- runAsyncValidation(name, value);
1072
+ debounceTimersRef.current.delete(target.validationKey);
1073
+ runAsyncValidationTarget(target);
1005
1074
  }, debounceMs);
1006
- debounceTimersRef.current.set(name, timer);
1075
+ debounceTimersRef.current.set(target.validationKey, timer);
1007
1076
  } else {
1008
- runAsyncValidation(name, value);
1077
+ runAsyncValidationTarget(target);
1078
+ }
1079
+ },
1080
+ [runAsyncValidationTarget]
1081
+ );
1082
+ const triggerAsyncValidation = (0, import_react.useCallback)(
1083
+ (name, value) => {
1084
+ const field = fieldByName.get(name);
1085
+ if (!field || field.type === "repeater" || field.type === "fieldGroup") return;
1086
+ triggerAsyncValidationTarget({
1087
+ validationKey: name,
1088
+ field,
1089
+ value: value != null ? value : formValuesRef.current[name],
1090
+ allValues: formValuesRef.current,
1091
+ applyError: (errorMessage) => updateErrors({ [name]: errorMessage })
1092
+ });
1093
+ },
1094
+ [fieldByName, triggerAsyncValidationTarget, updateErrors]
1095
+ );
1096
+ const getAsyncValidationTargets = (0, import_react.useCallback)(
1097
+ (fieldSubset) => {
1098
+ const toValidate = fieldSubset || visibleFields;
1099
+ const targets = [];
1100
+ for (const field of toValidate) {
1101
+ if (field.type === "fieldGroup" && field.items && field.fields) {
1102
+ for (const item of field.items) {
1103
+ for (const subField of field.fields(item)) {
1104
+ if (subField.visible && !subField.visible(formValues)) continue;
1105
+ targets.push({
1106
+ validationKey: subField.name,
1107
+ field: subField,
1108
+ value: formValues[subField.name],
1109
+ allValues: formValues,
1110
+ applyError: (errorMessage) => updateErrors({ [subField.name]: errorMessage })
1111
+ });
1112
+ }
1113
+ }
1114
+ continue;
1115
+ }
1116
+ if (field.type === "repeater") {
1117
+ const rows = Array.isArray(formValues[field.name]) ? formValues[field.name] : [];
1118
+ const subFields = field.fields || [];
1119
+ rows.forEach((row, rowIdx) => {
1120
+ const rowValues = { ...formValues, [field.name]: rows };
1121
+ subFields.forEach((subField) => {
1122
+ if (subField.visible && !subField.visible(rowValues)) return;
1123
+ targets.push({
1124
+ validationKey: getRepeaterErrorKey(field.name, rowIdx, subField.name),
1125
+ field: subField,
1126
+ value: row == null ? void 0 : row[subField.name],
1127
+ allValues: rowValues,
1128
+ applyError: (errorMessage) => setRepeaterSubFieldError(field.name, rowIdx, subField.name, errorMessage)
1129
+ });
1130
+ });
1131
+ });
1132
+ continue;
1133
+ }
1134
+ targets.push({
1135
+ validationKey: field.name,
1136
+ field,
1137
+ value: formValues[field.name],
1138
+ allValues: formValues,
1139
+ applyError: (errorMessage) => updateErrors({ [field.name]: errorMessage })
1140
+ });
1009
1141
  }
1142
+ return targets;
1010
1143
  },
1011
- [fieldByName, runAsyncValidation]
1144
+ [visibleFields, formValues, setRepeaterSubFieldError, updateErrors]
1012
1145
  );
1013
1146
  const commitValues = (0, import_react.useCallback)(
1014
1147
  (nextValues) => {
1015
1148
  formValuesRef.current = nextValues;
1016
1149
  if (values != null) {
1150
+ controlledBaselineLockedRef.current = true;
1017
1151
  if (onChange) onChange(nextValues);
1018
1152
  } else {
1019
1153
  setInternalValues(nextValues);
@@ -1031,7 +1165,8 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1031
1165
  [commitValues]
1032
1166
  );
1033
1167
  const handleFieldChange = (0, import_react.useCallback)(
1034
- (name, value) => {
1168
+ (name, value, options = {}) => {
1169
+ const { clearNestedErrors = true } = options;
1035
1170
  const newValues = { ...formValuesRef.current, [name]: value };
1036
1171
  const queue = [name];
1037
1172
  const visited = /* @__PURE__ */ new Set();
@@ -1072,9 +1207,11 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1072
1207
  if (formErrorsRef.current[name] != null) {
1073
1208
  clearedErrors[name] = null;
1074
1209
  }
1075
- for (const key of Object.keys(formErrorsRef.current)) {
1076
- if (key.startsWith(`${name}[`)) {
1077
- clearedErrors[key] = null;
1210
+ if (clearNestedErrors) {
1211
+ for (const key of Object.keys(formErrorsRef.current)) {
1212
+ if (key.startsWith(`${name}[`)) {
1213
+ clearedErrors[key] = null;
1214
+ }
1078
1215
  }
1079
1216
  }
1080
1217
  draftValuesRef.current = newValues;
@@ -1143,7 +1280,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1143
1280
  replaceErrors(errors);
1144
1281
  return;
1145
1282
  }
1146
- const asyncSubmitValidations = allVisibleFields.map((field) => runAsyncValidation(field.name, formValues[field.name])).filter(Boolean);
1283
+ const asyncSubmitValidations = getAsyncValidationTargets(allVisibleFields).map((target) => runAsyncValidationTarget(target)).filter(Boolean);
1147
1284
  if (asyncSubmitValidations.length > 0 || asyncValidationRef.current.size > 0) {
1148
1285
  const pendingValidations = [
1149
1286
  .../* @__PURE__ */ new Set([
@@ -1158,6 +1295,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1158
1295
  const reset = () => {
1159
1296
  const fresh = computeInitialValues();
1160
1297
  if (values == null) setInternalValues(fresh);
1298
+ controlledBaselineLockedRef.current = false;
1161
1299
  replaceErrors({});
1162
1300
  initialSnapshot.current = deepClone(fresh);
1163
1301
  prevAutoSaveValues.current = deepClone(fresh);
@@ -1197,7 +1335,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1197
1335
  if (controlledLoading == null) setInternalLoading(false);
1198
1336
  }
1199
1337
  },
1200
- [validateOnSubmit, allVisibleFields, validateVisibleFields, replaceErrors, onSubmit, values, controlledLoading, transformValues, onBeforeSubmit, onSubmitSuccess, onSubmitError, resetOnSuccess, formValues, fieldByName, runAsyncValidation]
1338
+ [validateOnSubmit, allVisibleFields, validateVisibleFields, replaceErrors, onSubmit, values, controlledLoading, transformValues, onBeforeSubmit, onSubmitSuccess, onSubmitError, resetOnSuccess, formValues, fieldByName, getAsyncValidationTargets, runAsyncValidationTarget]
1201
1339
  );
1202
1340
  const handleNext = (0, import_react.useCallback)(async () => {
1203
1341
  if (!isMultiStep) return;
@@ -1209,7 +1347,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1209
1347
  replaceErrors({ ...formErrorsRef.current, ...errors });
1210
1348
  return;
1211
1349
  }
1212
- const asyncStepValidations = stepFields.map((field) => runAsyncValidation(field.name, formValues[field.name])).filter(Boolean);
1350
+ const asyncStepValidations = getAsyncValidationTargets(stepFields).map((target) => runAsyncValidationTarget(target)).filter(Boolean);
1213
1351
  if (asyncStepValidations.length > 0 || asyncValidationRef.current.size > 0) {
1214
1352
  const pendingValidations = [
1215
1353
  .../* @__PURE__ */ new Set([
@@ -1234,7 +1372,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1234
1372
  } else {
1235
1373
  setInternalStep(nextStep);
1236
1374
  }
1237
- }, [isMultiStep, validateStepOnNext, steps, currentStep, formValues, validateVisibleFields, controlledStep, onStepChange, replaceErrors, allVisibleFields, runAsyncValidation]);
1375
+ }, [isMultiStep, validateStepOnNext, steps, currentStep, formValues, validateVisibleFields, controlledStep, onStepChange, replaceErrors, allVisibleFields, getAsyncValidationTargets, runAsyncValidationTarget]);
1238
1376
  const handleBack = (0, import_react.useCallback)(() => {
1239
1377
  if (!isMultiStep) return;
1240
1378
  const prevStep = Math.max(currentStep - 1, 0);
@@ -1266,6 +1404,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1266
1404
  reset: () => {
1267
1405
  const fresh = computeInitialValues();
1268
1406
  if (values == null) setInternalValues(fresh);
1407
+ controlledBaselineLockedRef.current = false;
1269
1408
  replaceErrors({});
1270
1409
  initialSnapshot.current = deepClone(fresh);
1271
1410
  prevAutoSaveValues.current = deepClone(fresh);
@@ -1278,30 +1417,6 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1278
1417
  replaceErrors(errors);
1279
1418
  }
1280
1419
  }));
1281
- const setRepeaterSubFieldError = (0, import_react.useCallback)(
1282
- (fieldName, rowIdx, subFieldName, errorMessage) => {
1283
- const key = getRepeaterErrorKey(fieldName, rowIdx, subFieldName);
1284
- const merged = { ...formErrorsRef.current };
1285
- if (errorMessage) {
1286
- merged[key] = errorMessage;
1287
- } else {
1288
- delete merged[key];
1289
- }
1290
- const subErrors = Object.keys(merged).filter((k) => k.startsWith(`${fieldName}[`)).map((k) => {
1291
- const match = k.match(/\[(\d+)\]\./);
1292
- const row = match ? Number(match[1]) : Number.MAX_SAFE_INTEGER;
1293
- return { key: k, row };
1294
- }).sort((a, b) => a.row - b.row);
1295
- if (subErrors.length > 0) {
1296
- const first = subErrors[0];
1297
- merged[fieldName] = `Row ${first.row + 1}: ${merged[first.key]}`;
1298
- } else if (!merged[fieldName] || merged[fieldName].startsWith("Row ")) {
1299
- delete merged[fieldName];
1300
- }
1301
- replaceErrors(merged);
1302
- },
1303
- [replaceErrors]
1304
- );
1305
1420
  const renderField = (field) => {
1306
1421
  const fieldError = formErrors[field.name] || null;
1307
1422
  const rendered = renderFieldInner(field);
@@ -1781,12 +1896,13 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1781
1896
  const rowValues = { ...formValues, [field.name]: nextRows };
1782
1897
  const err = runValidators(subValue, subField, rowValues, fieldTypes, { messages: validationMessages });
1783
1898
  setRepeaterSubFieldError(field.name, rowIdx, subField.name, err);
1899
+ return err;
1784
1900
  };
1785
1901
  const handleSubFieldChange = (rowIdx, subField, subValue) => {
1786
1902
  const updated = rows.map(
1787
1903
  (row, i) => i === rowIdx ? { ...row, [subField.name]: subValue } : row
1788
1904
  );
1789
- handleFieldChange(field.name, updated);
1905
+ handleFieldChange(field.name, updated, { clearNestedErrors: false });
1790
1906
  if (validateOnChange) {
1791
1907
  validateSubField(rowIdx, subField, subValue, updated);
1792
1908
  }
@@ -1796,13 +1912,24 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1796
1912
  const nextRows = rows.map(
1797
1913
  (row, i) => i === rowIdx ? { ...row, [subField.name]: subValue } : row
1798
1914
  );
1799
- validateSubField(rowIdx, subField, subValue, nextRows);
1915
+ const err = validateSubField(rowIdx, subField, subValue, nextRows);
1916
+ if (err) return;
1917
+ const validationKey = getRepeaterErrorKey(field.name, rowIdx, subField.name);
1918
+ const rowValues = { ...formValues, [field.name]: nextRows };
1919
+ triggerAsyncValidationTarget({
1920
+ validationKey,
1921
+ field: subField,
1922
+ value: subValue,
1923
+ allValues: rowValues,
1924
+ applyError: (errorMessage) => setRepeaterSubFieldError(field.name, rowIdx, subField.name, errorMessage)
1925
+ });
1800
1926
  };
1801
1927
  return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "xs" }, field.label && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { format: { fontWeight: "demibold" } }, field.label, isRequired ? " *" : ""), field.description && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy" }, field.description), rows.map((row, rowIdx) => /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { key: getRowKey(field.name, row, rowIdx), direction: "row", gap: "xs", align: "end" }, subFields.map((sf) => {
1802
1928
  const sfValue = row[sf.name];
1803
1929
  const sfLabel = rowIdx === 0 ? sf.label : void 0;
1804
1930
  const sfOptions = resolveOptions(sf, { ...formValues, [field.name]: rows });
1805
1931
  const sfError = formErrors[getRepeaterErrorKey(field.name, rowIdx, sf.name)] || null;
1932
+ const validationKey = getRepeaterErrorKey(field.name, rowIdx, sf.name);
1806
1933
  const sfProps = {
1807
1934
  name: `${field.name}-${rowIdx}-${sf.name}`,
1808
1935
  label: sfLabel,
@@ -1811,6 +1938,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1811
1938
  disabled: resolveDisabled(sf, formValues) || isDisabled,
1812
1939
  error: !!sfError,
1813
1940
  validationMessage: sfError || void 0,
1941
+ ...validatingFields[validationKey] ? { loading: true } : {},
1814
1942
  ...sf.fieldProps || {}
1815
1943
  };
1816
1944
  let sfElement;