hs-uix 1.6.4 → 1.7.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.
package/dist/form.js CHANGED
@@ -38,6 +38,9 @@ module.exports = __toCommonJS(form_exports);
38
38
  var import_react = __toESM(require("react"));
39
39
  var import_ui_extensions = require("@hubspot/ui-extensions");
40
40
  var import_crm = require("@hubspot/ui-extensions/crm");
41
+
42
+ // packages/form/src/formValues.js
43
+ var isPlainObject = (value) => Object.prototype.toString.call(value) === "[object Object]";
41
44
  var getEmptyValue = (field) => {
42
45
  switch (field.type) {
43
46
  case "toggle":
@@ -73,12 +76,6 @@ var isValueEmpty = (value, field) => {
73
76
  if ((field.type === "toggle" || field.type === "checkbox") && value === false) return true;
74
77
  return false;
75
78
  };
76
- var isPromise = (value) => value && typeof value.then === "function";
77
- var isAsyncFunction = (fn) => fn && fn.constructor && fn.constructor.name === "AsyncFunction";
78
- var normalizeValidatorResult = (result) => {
79
- if (result === true || result === void 0 || result === null || result === false) return null;
80
- return String(result);
81
- };
82
79
  var isDateValueObject = (value) => isPlainObject(value) && Number.isInteger(value.year) && Number.isInteger(value.month) && Number.isInteger(value.date);
83
80
  var isTimeValueObject = (value) => isPlainObject(value) && Number.isInteger(value.hours) && Number.isInteger(value.minutes);
84
81
  var compareDateValues = (a, b) => {
@@ -90,6 +87,64 @@ var compareTimeValues = (a, b) => {
90
87
  if (a.hours !== b.hours) return a.hours - b.hours;
91
88
  return a.minutes - b.minutes;
92
89
  };
90
+ var deepEqual = (a, b) => {
91
+ if (Object.is(a, b)) return true;
92
+ if (typeof a !== typeof b) return false;
93
+ if (a == null || b == null) return false;
94
+ if (Array.isArray(a)) {
95
+ if (!Array.isArray(b) || a.length !== b.length) return false;
96
+ for (let i = 0; i < a.length; i++) {
97
+ if (!deepEqual(a[i], b[i])) return false;
98
+ }
99
+ return true;
100
+ }
101
+ if (a instanceof Date && b instanceof Date) {
102
+ return a.getTime() === b.getTime();
103
+ }
104
+ if (isPlainObject(a) && isPlainObject(b)) {
105
+ const aKeys = Object.keys(a);
106
+ const bKeys = Object.keys(b);
107
+ if (aKeys.length !== bKeys.length) return false;
108
+ for (const key of aKeys) {
109
+ if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
110
+ if (!deepEqual(a[key], b[key])) return false;
111
+ }
112
+ return true;
113
+ }
114
+ return false;
115
+ };
116
+ var deepClone = (value) => {
117
+ if (Array.isArray(value)) return value.map(deepClone);
118
+ if (value instanceof Date) return new Date(value.getTime());
119
+ if (isPlainObject(value)) {
120
+ const next = {};
121
+ for (const key of Object.keys(value)) {
122
+ next[key] = deepClone(value[key]);
123
+ }
124
+ return next;
125
+ }
126
+ return value;
127
+ };
128
+
129
+ // packages/form/src/formValidation.js
130
+ var isPromise = (value) => value && typeof value.then === "function";
131
+ var isAsyncFunction = (fn) => fn && fn.constructor && fn.constructor.name === "AsyncFunction";
132
+ var normalizeValidatorResult = (result) => {
133
+ if (result === true || result === void 0 || result === null || result === false) return null;
134
+ return String(result);
135
+ };
136
+ var resolveRequired = (field, allValues) => {
137
+ if (typeof field.required === "function") return field.required(allValues);
138
+ return !!field.required;
139
+ };
140
+ var resolveDisabled = (field, allValues) => {
141
+ if (typeof field.disabled === "function") return field.disabled(allValues);
142
+ return !!field.disabled;
143
+ };
144
+ var resolveOptions = (field, allValues) => {
145
+ if (typeof field.options === "function") return field.options(allValues);
146
+ return field.options || [];
147
+ };
93
148
  var runDefaultFieldValidator = (value, field, allValues) => {
94
149
  const errorPrefix = field.label || field.name;
95
150
  switch (field.type) {
@@ -259,50 +314,53 @@ var runValidators = (value, field, allValues, fieldTypes, options = {}) => {
259
314
  }
260
315
  return null;
261
316
  };
262
- var resolveRequired = (field, allValues) => {
263
- if (typeof field.required === "function") return field.required(allValues);
264
- return !!field.required;
265
- };
266
- var resolveDisabled = (field, allValues) => {
267
- if (typeof field.disabled === "function") return field.disabled(allValues);
268
- return !!field.disabled;
269
- };
270
- var resolveOptions = (field, allValues) => {
271
- if (typeof field.options === "function") return field.options(allValues);
272
- return field.options || [];
273
- };
317
+
318
+ // packages/form/src/formDependencies.js
274
319
  var getDependsOnName = (field) => field.dependsOnConfig && field.dependsOnConfig.field;
275
320
  var getDependsOnDisplay = (field) => field.dependsOnConfig && field.dependsOnConfig.display || "grouped";
276
321
  var getDependsOnLabel = (field) => field.dependsOnConfig && field.dependsOnConfig.label;
277
322
  var getDependsOnMessage = (field) => field.dependsOnConfig && field.dependsOnConfig.message;
278
- var getRepeaterErrorKey = (fieldName, rowIdx, subFieldName) => `${fieldName}[${rowIdx}].${subFieldName}`;
279
- var isPlainObject = (value) => Object.prototype.toString.call(value) === "[object Object]";
280
- var deepEqual = (a, b) => {
281
- if (Object.is(a, b)) return true;
282
- if (typeof a !== typeof b) return false;
283
- if (a == null || b == null) return false;
284
- if (Array.isArray(a)) {
285
- if (!Array.isArray(b) || a.length !== b.length) return false;
286
- for (let i = 0; i < a.length; i++) {
287
- if (!deepEqual(a[i], b[i])) return false;
288
- }
289
- return true;
290
- }
291
- if (a instanceof Date && b instanceof Date) {
292
- return a.getTime() === b.getTime();
293
- }
294
- if (isPlainObject(a) && isPlainObject(b)) {
295
- const aKeys = Object.keys(a);
296
- const bKeys = Object.keys(b);
297
- if (aKeys.length !== bKeys.length) return false;
298
- for (const key of aKeys) {
299
- if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
300
- if (!deepEqual(a[key], b[key])) return false;
301
- }
302
- return true;
323
+ var resolveDependentCascade = ({ name, value, fields, values, getEmptyValueForField }) => {
324
+ const newValues = { ...values, [name]: value };
325
+ const queue = [name];
326
+ const visited = /* @__PURE__ */ new Set();
327
+ const changedDependents = [];
328
+ while (queue.length > 0) {
329
+ const current = queue.shift();
330
+ if (!current || visited.has(current)) continue;
331
+ visited.add(current);
332
+ fields.forEach((dep) => {
333
+ const parentName = getDependsOnName(dep);
334
+ if (parentName !== current || dep.name === current) return;
335
+ if (!dep.options) return;
336
+ const depOptions = resolveOptions(dep, newValues);
337
+ const depValue = newValues[dep.name];
338
+ if (depValue == null || depValue === "") return;
339
+ const validValues = new Set(depOptions.map((o) => o.value));
340
+ let nextDepValue = depValue;
341
+ let changed = false;
342
+ if (Array.isArray(depValue)) {
343
+ const filtered = depValue.filter((v) => validValues.has(v));
344
+ if (filtered.length !== depValue.length) {
345
+ nextDepValue = filtered;
346
+ changed = true;
347
+ }
348
+ } else if (!validValues.has(depValue)) {
349
+ nextDepValue = getEmptyValueForField(dep);
350
+ changed = true;
351
+ }
352
+ if (changed) {
353
+ newValues[dep.name] = nextDepValue;
354
+ queue.push(dep.name);
355
+ changedDependents.push(dep.name);
356
+ }
357
+ });
303
358
  }
304
- return false;
359
+ return { newValues, changedDependents };
305
360
  };
361
+
362
+ // packages/form/src/FormBuilder.jsx
363
+ var getRepeaterErrorKey = (fieldName, rowIdx, subFieldName) => `${fieldName}[${rowIdx}].${subFieldName}`;
306
364
  var fieldSetHasErrors = (errors, fields) => {
307
365
  if (!errors || !fields || fields.length === 0) return false;
308
366
  const names = new Set(fields.map((field) => field.name));
@@ -311,18 +369,6 @@ var fieldSetHasErrors = (errors, fields) => {
311
369
  return names.has(base);
312
370
  });
313
371
  };
314
- var deepClone = (value) => {
315
- if (Array.isArray(value)) return value.map(deepClone);
316
- if (value instanceof Date) return new Date(value.getTime());
317
- if (isPlainObject(value)) {
318
- const next = {};
319
- for (const key of Object.keys(value)) {
320
- next[key] = deepClone(value[key]);
321
- }
322
- return next;
323
- }
324
- return value;
325
- };
326
372
  var useFormPrefill = (properties, mapping) => {
327
373
  return (0, import_react.useMemo)(() => {
328
374
  if (!properties) return {};
@@ -378,8 +424,12 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
378
424
  // validate on blur
379
425
  validateOnSubmit = true,
380
426
  // validate all before onSubmit
381
- onValidationChange
427
+ onValidationChange,
382
428
  // (errors) => void
429
+ onValidationFail,
430
+ // ({ errors, fields, firstInvalidField }) => void — called when submit-time validation blocks submission
431
+ openSectionOnValidationFail = false
432
+ // auto-open accordion section containing first invalid field on submit failure
383
433
  } = props;
384
434
  const {
385
435
  steps,
@@ -528,6 +578,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
528
578
  "tooltip",
529
579
  "required",
530
580
  "readOnly",
581
+ "alwaysEditable",
531
582
  "disabled",
532
583
  "defaultValue",
533
584
  "fieldProps",
@@ -700,6 +751,17 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
700
751
  }
701
752
  return map;
702
753
  }, [fields]);
754
+ const sectionIdByFieldName = (0, import_react.useMemo)(() => {
755
+ const map = /* @__PURE__ */ new Map();
756
+ if (Array.isArray(sections)) {
757
+ for (const sec of sections) {
758
+ if (!sec || !Array.isArray(sec.fields)) continue;
759
+ for (const name of sec.fields) map.set(name, sec.id);
760
+ }
761
+ }
762
+ return map;
763
+ }, [sections]);
764
+ const [validationOpenSection, setValidationOpenSection] = (0, import_react.useState)(null);
703
765
  const isDev = typeof process === "undefined" || !process.env || process.env.NODE_ENV !== "production";
704
766
  const configWarningsRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
705
767
  const warnConfig = (0, import_react.useCallback)((message) => {
@@ -1173,42 +1235,18 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1173
1235
  const handleFieldChange = (0, import_react.useCallback)(
1174
1236
  (name, value, options = {}) => {
1175
1237
  const { clearNestedErrors = true } = options;
1176
- const newValues = { ...formValuesRef.current, [name]: value };
1177
- const queue = [name];
1178
- const visited = /* @__PURE__ */ new Set();
1238
+ const { newValues, changedDependents } = resolveDependentCascade({
1239
+ name,
1240
+ value,
1241
+ fields,
1242
+ values: formValuesRef.current,
1243
+ getEmptyValueForField: getFieldEmptyValue
1244
+ });
1179
1245
  const clearedErrors = {};
1180
- while (queue.length > 0) {
1181
- const current = queue.shift();
1182
- if (!current || visited.has(current)) continue;
1183
- visited.add(current);
1184
- fields.forEach((dep) => {
1185
- const parentName = getDependsOnName(dep);
1186
- if (parentName !== current || dep.name === current) return;
1187
- if (!dep.options) return;
1188
- const depOptions = resolveOptions(dep, newValues);
1189
- const depValue = newValues[dep.name];
1190
- if (depValue == null || depValue === "") return;
1191
- const validValues = new Set(depOptions.map((o) => o.value));
1192
- let nextDepValue = depValue;
1193
- let changed = false;
1194
- if (Array.isArray(depValue)) {
1195
- const filtered = depValue.filter((v) => validValues.has(v));
1196
- if (filtered.length !== depValue.length) {
1197
- nextDepValue = filtered;
1198
- changed = true;
1199
- }
1200
- } else if (!validValues.has(depValue)) {
1201
- nextDepValue = getFieldEmptyValue(dep);
1202
- changed = true;
1203
- }
1204
- if (changed) {
1205
- newValues[dep.name] = nextDepValue;
1206
- queue.push(dep.name);
1207
- if (formErrorsRef.current[dep.name] != null) {
1208
- clearedErrors[dep.name] = null;
1209
- }
1210
- }
1211
- });
1246
+ for (const depName of changedDependents) {
1247
+ if (formErrorsRef.current[depName] != null) {
1248
+ clearedErrors[depName] = null;
1249
+ }
1212
1250
  }
1213
1251
  if (formErrorsRef.current[name] != null) {
1214
1252
  clearedErrors[name] = null;
@@ -1280,10 +1318,35 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1280
1318
  const handleSubmit = (0, import_react.useCallback)(
1281
1319
  async (e) => {
1282
1320
  if (e && e.preventDefault) e.preventDefault();
1321
+ const reportValidationFailure = (errors) => {
1322
+ const errorNames = Object.keys(errors).filter((n) => !!errors[n]);
1323
+ if (errorNames.length === 0) return;
1324
+ const orderedNames = allVisibleFields.map((f) => f.name).filter((n) => errorNames.includes(n));
1325
+ for (const n of errorNames) if (!orderedNames.includes(n)) orderedNames.push(n);
1326
+ const fieldInfos = orderedNames.map((name) => {
1327
+ const f = fieldByName.get(name);
1328
+ return {
1329
+ name,
1330
+ label: f == null ? void 0 : f.label,
1331
+ sectionId: sectionIdByFieldName.get(name)
1332
+ };
1333
+ });
1334
+ const firstInvalidField = fieldInfos[0];
1335
+ if (openSectionOnValidationFail && (firstInvalidField == null ? void 0 : firstInvalidField.sectionId)) {
1336
+ setValidationOpenSection({
1337
+ id: firstInvalidField.sectionId,
1338
+ nonce: ((validationOpenSection == null ? void 0 : validationOpenSection.nonce) || 0) + 1
1339
+ });
1340
+ }
1341
+ if (onValidationFail) {
1342
+ onValidationFail({ errors, fields: fieldInfos, firstInvalidField });
1343
+ }
1344
+ };
1283
1345
  if (validateOnSubmit) {
1284
1346
  const { errors, hasErrors } = validateVisibleFields(allVisibleFields);
1285
1347
  if (hasErrors) {
1286
1348
  replaceErrors(errors);
1349
+ reportValidationFailure(errors);
1287
1350
  return;
1288
1351
  }
1289
1352
  const asyncSubmitValidations = getAsyncValidationTargets(allVisibleFields).map((target) => runAsyncValidationTarget(target)).filter(Boolean);
@@ -1295,7 +1358,10 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1295
1358
  ])
1296
1359
  ];
1297
1360
  await Promise.all(pendingValidations);
1298
- if (fieldSetHasErrors(formErrorsRef.current, allVisibleFields)) return;
1361
+ if (fieldSetHasErrors(formErrorsRef.current, allVisibleFields)) {
1362
+ reportValidationFailure(formErrorsRef.current);
1363
+ return;
1364
+ }
1299
1365
  }
1300
1366
  }
1301
1367
  const reset = () => {
@@ -1341,7 +1407,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1341
1407
  if (controlledLoading == null) setInternalLoading(false);
1342
1408
  }
1343
1409
  },
1344
- [validateOnSubmit, allVisibleFields, validateVisibleFields, replaceErrors, onSubmit, values, controlledLoading, transformValues, onBeforeSubmit, onSubmitSuccess, onSubmitError, resetOnSuccess, formValues, fieldByName, getAsyncValidationTargets, runAsyncValidationTarget]
1410
+ [validateOnSubmit, allVisibleFields, validateVisibleFields, replaceErrors, onSubmit, values, controlledLoading, transformValues, onBeforeSubmit, onSubmitSuccess, onSubmitError, resetOnSuccess, formValues, fieldByName, getAsyncValidationTargets, runAsyncValidationTarget, onValidationFail, openSectionOnValidationFail, sectionIdByFieldName, validationOpenSection]
1345
1411
  );
1346
1412
  const handleNext = (0, import_react.useCallback)(async () => {
1347
1413
  if (!isMultiStep) return;
@@ -1434,8 +1500,9 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1434
1500
  const fieldError = formErrors[field.name] || null;
1435
1501
  const hasError = !!fieldError;
1436
1502
  const isRequired = showRequiredIndicator && resolveRequired(field, formValues);
1437
- const isReadOnly = field.readOnly || formReadOnly;
1438
- const isDisabled = disabled || resolveDisabled(field, formValues) || formReadOnly;
1503
+ const fieldFormReadOnly = field.alwaysEditable ? false : formReadOnly;
1504
+ const isReadOnly = field.readOnly || fieldFormReadOnly;
1505
+ const isDisabled = disabled || resolveDisabled(field, formValues) || fieldFormReadOnly;
1439
1506
  const fieldOnChange = field.debounce ? (v) => handleDebouncedFieldChange(field.name, v) : (v) => handleFieldChange(field.name, v);
1440
1507
  if (field.type === "display" || field.type === "slot") {
1441
1508
  if (field.render) {
@@ -1478,8 +1545,9 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1478
1545
  const sfValue = formValues[sf.name];
1479
1546
  const sfError = formErrors[sf.name] || null;
1480
1547
  const sfLabel = itemIdx === 0 ? sf.label : void 0;
1481
- const sfReadOnly = sf.readOnly || formReadOnly;
1482
- const sfDisabled = disabled || resolveDisabled(sf, formValues) || formReadOnly;
1548
+ const sfFormReadOnly = sf.alwaysEditable ? false : formReadOnly;
1549
+ const sfReadOnly = sf.readOnly || sfFormReadOnly;
1550
+ const sfDisabled = disabled || resolveDisabled(sf, formValues) || sfFormReadOnly;
1483
1551
  const sfOnChange = sf.debounce ? (v) => handleDebouncedFieldChange(sf.name, v) : (v) => handleFieldChange(sf.name, v);
1484
1552
  const sfProps = {
1485
1553
  name: sf.name,
@@ -1996,7 +2064,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
1996
2064
  );
1997
2065
  }
1998
2066
  return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { key: sf.name, flex: 1 }, sfElement);
1999
- }), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Inline, { gap: "xs" }, canReorder && rowIdx > 0 && (renderMoveUpControl ? renderMoveUpControl({ index: rowIdx, onClick: () => moveRow(rowIdx, rowIdx - 1) }) : /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Button, { variant: "secondary", size: "sm", onClick: () => moveRow(rowIdx, rowIdx - 1) }, moveUpLabel)), canReorder && rowIdx < rows.length - 1 && (renderMoveDownControl ? renderMoveDownControl({ index: rowIdx, onClick: () => moveRow(rowIdx, rowIdx + 1) }) : /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Button, { variant: "secondary", size: "sm", onClick: () => moveRow(rowIdx, rowIdx + 1) }, moveDownLabel)), canRemove && (renderRemoveControl ? renderRemoveControl({ index: rowIdx, onClick: () => removeRow(rowIdx) }) : /* @__PURE__ */ import_react.default.createElement(
2067
+ }), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Inline, { gap: "xs" }, canReorder && (renderMoveUpControl ? renderMoveUpControl({ index: rowIdx, disabled: rowIdx === 0, onClick: () => moveRow(rowIdx, rowIdx - 1) }) : /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Button, { variant: "secondary", size: "sm", disabled: rowIdx === 0, onClick: () => moveRow(rowIdx, rowIdx - 1) }, moveUpLabel)), canReorder && (renderMoveDownControl ? renderMoveDownControl({ index: rowIdx, disabled: rowIdx === rows.length - 1, onClick: () => moveRow(rowIdx, rowIdx + 1) }) : /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Button, { variant: "secondary", size: "sm", disabled: rowIdx === rows.length - 1, onClick: () => moveRow(rowIdx, rowIdx + 1) }, moveDownLabel)), canRemove && (renderRemoveControl ? renderRemoveControl({ index: rowIdx, onClick: () => removeRow(rowIdx) }) : /* @__PURE__ */ import_react.default.createElement(
2000
2068
  import_ui_extensions.Button,
2001
2069
  {
2002
2070
  variant: "secondary",
@@ -2004,7 +2072,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
2004
2072
  onClick: () => removeRow(rowIdx)
2005
2073
  },
2006
2074
  removeLabel
2007
- ))))), canAdd && (renderAddControl ? renderAddControl({ onClick: addRow, count: rows.length }) : /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Link, { onClick: addRow }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "flush" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Icon, { name: "add" }), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { format: { fontWeight: "demibold" } }, addLabel)))), repeaterHasError && repeaterErrorMessage && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy" }, repeaterErrorMessage));
2075
+ ))))), canAdd && (renderAddControl ? renderAddControl({ onClick: addRow, count: rows.length }) : /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Link, { onClick: addRow }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Icon, { name: "add" }), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { format: { fontWeight: "demibold" } }, addLabel)))), repeaterHasError && repeaterErrorMessage && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy" }, repeaterErrorMessage));
2008
2076
  }
2009
2077
  default:
2010
2078
  return /* @__PURE__ */ import_react.default.createElement(
@@ -2276,13 +2344,16 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
2276
2344
  const sectionContext = { values: formValues, errors: formErrors };
2277
2345
  const sectionOverrides = sec.columns ? { columns: sec.columns } : void 0;
2278
2346
  const accordionContent = /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap }, sec.renderBefore && sec.renderBefore(sectionContext), renderFieldSubset(sectionFields, sectionOverrides), sec.renderAfter && sec.renderAfter(sectionContext));
2347
+ const isValidationOverrideTarget = validationOpenSection && validationOpenSection.id === sec.id;
2348
+ const accordionKey = isValidationOverrideTarget ? `${sec.id}::open::${validationOpenSection.nonce}` : sec.id;
2349
+ const accordionDefaultOpen = isValidationOverrideTarget ? true : sec.defaultOpen !== false;
2279
2350
  const accordion = /* @__PURE__ */ import_react.default.createElement(
2280
2351
  import_ui_extensions.Accordion,
2281
2352
  {
2282
- key: sec.id,
2353
+ key: accordionKey,
2283
2354
  title: sec.label,
2284
2355
  size: "sm",
2285
- defaultOpen: sec.defaultOpen !== false
2356
+ defaultOpen: accordionDefaultOpen
2286
2357
  },
2287
2358
  accordionContent
2288
2359
  );