@openg2p/registry-widgets 1.1.0-dev.10 → 1.1.0-dev.12

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.
@@ -38,6 +38,12 @@ export interface SectionRendererProps {
38
38
  onPreviousSection?: (index: number) => void;
39
39
  /** IntakeForm mode: when true or undefined, sections are editable; when false, sections are readonly */
40
40
  isDraft?: boolean;
41
+ /**
42
+ * IntakeForm mode: when true the accordion header is clickable so the user can open/close this
43
+ * section freely. False (default) locks the header — navigation is only via Next/Previous.
44
+ * SectionsContainer sets this to true for every visited section plus the one immediately after.
45
+ */
46
+ isAccessible?: boolean;
41
47
  /** RegistryView: called when this section enters or exits edit mode. Used by SectionsContainer to enforce single-edit. */
42
48
  onEditModeChange?: (sectionId: string, editing: boolean) => void;
43
49
  /** RegistryView: when true, forces this section out of edit mode (another section took over). */
@@ -51,5 +57,5 @@ export interface SectionRendererProps {
51
57
  * - Panels wrap when they exceed available width
52
58
  * - Sections can sit side-by-side if there's space
53
59
  */
54
- export declare const SectionRenderer: ({ section, dataSourceRequestHandler: propDataSourceRequestHandler, schemaData, onValueChange, gridColumnSpan, onSectionSave, hideEditButton, mode, namespace, changeRequestType, showChangeRequestLabel, dbSectionId, sectionRegisterId, onSectionDirtyChange, sectionIndex, sectionCount, expandedSectionIndex, onExpandSection, onSectionSaveSuccess, onPreviousSection, isDraft, onEditModeChange, forceExitEdit, }: SectionRendererProps) => import("react/jsx-runtime").JSX.Element;
60
+ export declare const SectionRenderer: ({ section, dataSourceRequestHandler: propDataSourceRequestHandler, schemaData, onValueChange, gridColumnSpan, onSectionSave, hideEditButton, mode, namespace, changeRequestType, showChangeRequestLabel, dbSectionId, sectionRegisterId, onSectionDirtyChange, sectionIndex, sectionCount, expandedSectionIndex, onExpandSection, onSectionSaveSuccess, onPreviousSection, isDraft, isAccessible, onEditModeChange, forceExitEdit, }: SectionRendererProps) => import("react/jsx-runtime").JSX.Element;
55
61
  //# sourceMappingURL=SectionRenderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SectionRenderer.d.ts","sourceRoot":"","sources":["../../src/components/SectionRenderer.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAyC,MAAM,UAAU,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAQ9D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AA2ClD,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,aAAa,CAAC;IACvB,wBAAwB,CAAC,EAAE,oBAAoB,CAAC,0BAA0B,CAAC,CAAC;IAC5E,UAAU,CAAC,EAAE,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAChD,aAAa,CAAC,EAAE,oBAAoB,CAAC,eAAe,CAAC,CAAC;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAClC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAGjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,2GAA2G;IAC3G,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAErE,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sFAAsF;IACtF,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,oGAAoG;IACpG,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,uGAAuG;IACvG,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,4FAA4F;IAC5F,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,wGAAwG;IACxG,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,0HAA0H;IAC1H,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACjE,iGAAiG;IACjG,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAGD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAAI,wZAwB7B,oBAAoB,4CA09CtB,CAAC"}
1
+ {"version":3,"file":"SectionRenderer.d.ts","sourceRoot":"","sources":["../../src/components/SectionRenderer.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAyC,MAAM,UAAU,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAQ9D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AA2ClD,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,aAAa,CAAC;IACvB,wBAAwB,CAAC,EAAE,oBAAoB,CAAC,0BAA0B,CAAC,CAAC;IAC5E,UAAU,CAAC,EAAE,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAChD,aAAa,CAAC,EAAE,oBAAoB,CAAC,eAAe,CAAC,CAAC;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAClC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAGjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,2GAA2G;IAC3G,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAErE,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sFAAsF;IACtF,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,oGAAoG;IACpG,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,uGAAuG;IACvG,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,4FAA4F;IAC5F,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,wGAAwG;IACxG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,0HAA0H;IAC1H,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACjE,iGAAiG;IACjG,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAGD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAAI,saAyB7B,oBAAoB,4CAo+CtB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"SectionsContainer.d.ts","sourceRoot":"","sources":["../../src/components/SectionsContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAmB,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAOpE,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEnE,uHAAuH;AACvH,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,qEAAqE;IACrE,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,qFAAqF;IACrF,kBAAkB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAClD;;;OAGG;IACD,iBAAiB,IAAI,cAAc,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IACpD,UAAU,CAAC,EAAE,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAChD,aAAa,CAAC,EAAE,oBAAoB,CAAC,eAAe,CAAC,CAAC;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,wGAAwG;IACxG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAEpE,wHAAwH;IACxH,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrE,0JAA0J;IAC1J,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACpD;AAoFD;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,yMAa/B,sBAAsB,4CA4TxB,CAAC"}
1
+ {"version":3,"file":"SectionsContainer.d.ts","sourceRoot":"","sources":["../../src/components/SectionsContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAmB,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAOpE,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEnE,uHAAuH;AACvH,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,qEAAqE;IACrE,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,qFAAqF;IACrF,kBAAkB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAClD;;;OAGG;IACD,iBAAiB,IAAI,cAAc,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IACpD,UAAU,CAAC,EAAE,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAChD,aAAa,CAAC,EAAE,oBAAoB,CAAC,eAAe,CAAC,CAAC;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,wGAAwG;IACxG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAEpE,wHAAwH;IACxH,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrE,0JAA0J;IAC1J,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACpD;AAoFD;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,yMAa/B,sBAAsB,4CAkVxB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -707,6 +707,12 @@ interface SectionRendererProps {
707
707
  onPreviousSection?: (index: number) => void;
708
708
  /** IntakeForm mode: when true or undefined, sections are editable; when false, sections are readonly */
709
709
  isDraft?: boolean;
710
+ /**
711
+ * IntakeForm mode: when true the accordion header is clickable so the user can open/close this
712
+ * section freely. False (default) locks the header — navigation is only via Next/Previous.
713
+ * SectionsContainer sets this to true for every visited section plus the one immediately after.
714
+ */
715
+ isAccessible?: boolean;
710
716
  /** RegistryView: called when this section enters or exits edit mode. Used by SectionsContainer to enforce single-edit. */
711
717
  onEditModeChange?: (sectionId: string, editing: boolean) => void;
712
718
  /** RegistryView: when true, forces this section out of edit mode (another section took over). */
@@ -720,7 +726,7 @@ interface SectionRendererProps {
720
726
  * - Panels wrap when they exceed available width
721
727
  * - Sections can sit side-by-side if there's space
722
728
  */
723
- declare const SectionRenderer: ({ section, dataSourceRequestHandler: propDataSourceRequestHandler, schemaData, onValueChange, gridColumnSpan, onSectionSave, hideEditButton, mode, namespace, changeRequestType, showChangeRequestLabel, dbSectionId, sectionRegisterId, onSectionDirtyChange, sectionIndex, sectionCount, expandedSectionIndex, onExpandSection, onSectionSaveSuccess, onPreviousSection, isDraft, onEditModeChange, forceExitEdit, }: SectionRendererProps) => react_jsx_runtime.JSX.Element;
729
+ declare const SectionRenderer: ({ section, dataSourceRequestHandler: propDataSourceRequestHandler, schemaData, onValueChange, gridColumnSpan, onSectionSave, hideEditButton, mode, namespace, changeRequestType, showChangeRequestLabel, dbSectionId, sectionRegisterId, onSectionDirtyChange, sectionIndex, sectionCount, expandedSectionIndex, onExpandSection, onSectionSaveSuccess, onPreviousSection, isDraft, isAccessible, onEditModeChange, forceExitEdit, }: SectionRendererProps) => react_jsx_runtime.JSX.Element;
724
730
 
725
731
  interface SectionBuilderProps {
726
732
  initialSection?: SectionConfig;
package/dist/index.esm.js CHANGED
@@ -3946,7 +3946,7 @@ function scopedClassSelectors(sectionClassId, classNames) {
3946
3946
  * - Panels wrap when they exceed available width
3947
3947
  * - Sections can sit side-by-side if there's space
3948
3948
  */
3949
- const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequestHandler, schemaData, onValueChange, gridColumnSpan, onSectionSave, hideEditButton = false, mode = 'RegistryView', namespace, changeRequestType, showChangeRequestLabel = true, dbSectionId, sectionRegisterId, onSectionDirtyChange, sectionIndex, sectionCount, expandedSectionIndex, onExpandSection, onSectionSaveSuccess, onPreviousSection, isDraft, onEditModeChange, forceExitEdit, }) => {
3949
+ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequestHandler, schemaData, onValueChange, gridColumnSpan, onSectionSave, hideEditButton = false, mode = 'RegistryView', namespace, changeRequestType, showChangeRequestLabel = true, dbSectionId, sectionRegisterId, onSectionDirtyChange, sectionIndex, sectionCount, expandedSectionIndex, onExpandSection, onSectionSaveSuccess, onPreviousSection, isDraft, isAccessible = false, onEditModeChange, forceExitEdit, }) => {
3950
3950
  const { translateConfig, translate } = useWidgetTranslation();
3951
3951
  const resolvedTheme = useWidgetTheme();
3952
3952
  const portalCSSVariables = useMemo(() => themeToCSSVariables(resolvedTheme), [resolvedTheme]);
@@ -4012,17 +4012,25 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4012
4012
  const isExpandedFromContainer = typeof sectionIndex === 'number' && expandedSectionIndex === sectionIndex;
4013
4013
  const isExpandedStandalone = sectionIndex === undefined && standaloneExpanded;
4014
4014
  const isExpanded = mode === 'IntakeForm' && (isExpandedFromContainer || isExpandedStandalone);
4015
- // When the section is managed by SectionsContainer (sectionIndex is set), header clicks are
4016
- // disabled navigation is only allowed via the Next / Previous buttons.
4017
- // Standalone usage (sectionIndex undefined) keeps the classic toggle behaviour.
4015
+ // IntakeForm only: tracks whether the user has clicked Next on this section at least once.
4016
+ // Used to unlock the accordion header so the user can navigate back to a visited section.
4017
+ const [hasBeenSavedByUser, setHasBeenSavedByUser] = useState(false);
4018
+ // Accordion header click behaviour in IntakeForm mode:
4019
+ // - Standalone (no sectionIndex): always toggleable.
4020
+ // - Managed by SectionsContainer: toggleable only when isAccessible is true
4021
+ // (i.e. the section has been visited OR is the immediate next one).
4022
+ // Sections beyond that remain locked.
4018
4023
  const handleAccordionToggle = useCallback(() => {
4019
4024
  if (mode !== 'IntakeForm')
4020
4025
  return;
4021
4026
  if (sectionIndex === undefined) {
4022
4027
  setStandaloneExpanded(prev => !prev);
4023
4028
  }
4024
- // Intentionally no-op when sectionIndex is set (managed by SectionsContainer)
4025
- }, [mode, sectionIndex]);
4029
+ else if (isAccessible && onExpandSection) {
4030
+ onExpandSection(sectionIndex);
4031
+ }
4032
+ // Intentionally no-op for locked sections (isAccessible === false)
4033
+ }, [mode, sectionIndex, isAccessible, onExpandSection]);
4026
4034
  // Recursively count all vertical panels, especially those nested inside horizontal panels
4027
4035
  // Typically: horizontal panels at first level contain vertical panels at second level
4028
4036
  // Accounts for panel-column-span: a panel with column-span 3 counts as 3 columns
@@ -4357,8 +4365,6 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4357
4365
  const baselineSnapshotRef = useRef(null);
4358
4366
  // IntakeForm only: increment when baseline is updated after save - forces badge to update (refs don't trigger re-renders)
4359
4367
  const [intakeFormBaselineTrigger, setIntakeFormBaselineTrigger] = useState(0);
4360
- // IntakeForm only: tracks whether the user has actually saved this section (prevents "Saved" badge on initial load)
4361
- const [hasBeenSavedByUser, setHasBeenSavedByUser] = useState(false);
4362
4368
  // IntakeForm: treat as edit mode for dirty tracking when isDraft. RegistryView: use isEditMode.
4363
4369
  const effectiveEditModeForDirty = mode === 'IntakeForm' ? (isDraft !== false) : isEditMode;
4364
4370
  // Compute isDirty: compare current store state to baseline (only when in edit mode)
@@ -4591,6 +4597,11 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4591
4597
  }
4592
4598
  onSectionDirtyChange?.(sectionId, false);
4593
4599
  }
4600
+ else if (mode === 'IntakeForm') {
4601
+ // No onSectionSave provided, but still mark section as visited so the
4602
+ // user can navigate back to it by clicking the accordion header.
4603
+ setHasBeenSavedByUser(true);
4604
+ }
4594
4605
  // Always navigate to the next section
4595
4606
  onSectionSaveSuccess?.(sectionIndex);
4596
4607
  }, [store, onSectionSave, onSectionSaveSuccess, sectionIndex, originalSection, schemaData, contextSchemaData, namespace, hasSupportingDocuments, dbSectionId, sectionRegisterId, dispatch, buildSectionSnapshot, sectionId, onSectionDirtyChange, mode, isDraft]);
@@ -4862,7 +4873,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4862
4873
  }),
4863
4874
  }, children: mode === 'IntakeForm' ? (
4864
4875
  /* IntakeForm: accordion layout - header always visible, content only when expanded */
4865
- jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("button", { type: "button", id: `intake-form-accordion-header-${sectionId}`, className: "intake-form-accordion-header", onClick: handleAccordionToggle, "aria-expanded": isExpanded, "aria-controls": isExpanded ? `intake-form-accordion-content-${sectionId}` : undefined, "data-interactive": sectionIndex === undefined ? 'true' : 'false', style: {
4876
+ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("button", { type: "button", id: `intake-form-accordion-header-${sectionId}`, className: "intake-form-accordion-header", onClick: handleAccordionToggle, "aria-expanded": isExpanded, "aria-controls": isExpanded ? `intake-form-accordion-content-${sectionId}` : undefined, "data-interactive": sectionIndex === undefined || isAccessible ? 'true' : 'false', style: {
4866
4877
  width: '100%',
4867
4878
  display: 'flex',
4868
4879
  alignItems: 'flex-start',
@@ -4872,7 +4883,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4872
4883
  marginBottom: 0,
4873
4884
  background: 'none',
4874
4885
  border: 'none',
4875
- cursor: sectionIndex === undefined ? 'pointer' : 'default',
4886
+ cursor: sectionIndex === undefined || isAccessible ? 'pointer' : 'default',
4876
4887
  textAlign: 'left',
4877
4888
  fontFamily: 'Roboto, sans-serif',
4878
4889
  }, children: [jsxRuntimeExports.jsxs("div", { style: { flex: 1, display: 'flex', alignItems: 'center', gap: '12px', minWidth: 0 }, children: [jsxRuntimeExports.jsx("h2", { className: "text-xl font-semibold", style: { margin: 0 }, children: sectionToRender['section-title']
@@ -5170,6 +5181,11 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
5170
5181
  const dataSourceRequestHandler = propDataSourceRequestHandler || contextDataSourceRequestHandler;
5171
5182
  // IntakeForm mode: accordion state - which section is expanded (null = none; first expanded by default)
5172
5183
  const [expandedSectionIndex, setExpandedSectionIndex] = useState(0);
5184
+ // IntakeForm mode: high-water mark of the furthest section the user has clicked Next on.
5185
+ // A section at index i is accessible when i <= maxVisitedIndex + 1
5186
+ // (i.e. every visited section plus the one immediately after it).
5187
+ // Starts at -1 so only section 0 is accessible before any Next is clicked.
5188
+ const [maxVisitedIndex, setMaxVisitedIndex] = useState(-1);
5173
5189
  // RegistryView: track which section is currently in edit mode (by section-id); null = none
5174
5190
  const [editingSectionId, setEditingSectionId] = useState(null);
5175
5191
  const handleEditModeChange = useCallback((sectionId, editing) => {
@@ -5180,6 +5196,11 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
5180
5196
  // Stable ref for namespace so formHandle useMemo doesn't depend on the (possibly inline) function identity
5181
5197
  const namespaceRef = useRef(namespace);
5182
5198
  namespaceRef.current = namespace;
5199
+ // Stable ref for sections so formHandle useMemo doesn't depend on the (possibly unstable) array reference.
5200
+ // Without this, an inline sections={[...]} prop would recreate formHandle every render, causing
5201
+ // onFormReady to fire every render → host setState → infinite re-render loop.
5202
+ const safeSectionsRef = useRef(safeSections);
5203
+ safeSectionsRef.current = safeSections;
5183
5204
  // Stable refs so formHandle closure can access current mode and accordion setter without stale captures
5184
5205
  const modeRef = useRef(mode);
5185
5206
  modeRef.current = mode;
@@ -5194,8 +5215,9 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
5194
5215
  const handleExpandSection = useCallback((index) => {
5195
5216
  setExpandedSectionIndex(prev => (prev === index ? null : index));
5196
5217
  }, []);
5197
- // IntakeForm mode: called after section save - collapse current, expand next
5218
+ // IntakeForm mode: called after section save - advance high-water mark, collapse current, expand next
5198
5219
  const handleSectionSaveSuccess = useCallback((index) => {
5220
+ setMaxVisitedIndex(prev => Math.max(prev, index));
5199
5221
  if (index + 1 < safeSections.length) {
5200
5222
  setExpandedSectionIndex(index + 1);
5201
5223
  }
@@ -5227,6 +5249,9 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
5227
5249
  }, [mode, safeSections.length, expandedSectionIndex]);
5228
5250
  const UNSAVED_CHANGES_ERROR = 'Unsaved changes detected. Please save all sections before submitting.';
5229
5251
  // Form handle for onFormReady - allows host to validate and get all section data from its own Submit button
5252
+ // IMPORTANT: safeSections is intentionally accessed via safeSectionsRef.current (not closed over directly)
5253
+ // so that this memo never depends on the sections array reference. This prevents an infinite re-render
5254
+ // loop when the host passes an unstable sections prop (e.g. inline array or derived state).
5230
5255
  const formHandle = useMemo(() => {
5231
5256
  const getValues = () => store.getState().widget?.values || {};
5232
5257
  const getNamespace = (section, index) => {
@@ -5248,10 +5273,11 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
5248
5273
  if (modeRef.current !== 'IntakeForm')
5249
5274
  checkNoUnsavedChanges();
5250
5275
  const values = getValues();
5276
+ const sections = safeSectionsRef.current;
5251
5277
  let allValid = true;
5252
5278
  let firstInvalidIndex = null;
5253
- for (let i = 0; i < safeSections.length; i++) {
5254
- const section = safeSections[i];
5279
+ for (let i = 0; i < sections.length; i++) {
5280
+ const section = sections[i];
5255
5281
  const ns = getNamespace(section, i);
5256
5282
  const sectionToValidate = ns ? namespaceSectionConfig(section, ns) : section;
5257
5283
  const valid = sectionValidate(sectionToValidate, values, dispatch);
@@ -5271,10 +5297,11 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
5271
5297
  if (modeRef.current !== 'IntakeForm')
5272
5298
  checkNoUnsavedChanges();
5273
5299
  const values = getValues();
5300
+ const sections = safeSectionsRef.current;
5274
5301
  const results = [];
5275
5302
  let firstInvalidIndex = null;
5276
- for (let i = 0; i < safeSections.length; i++) {
5277
- const section = safeSections[i];
5303
+ for (let i = 0; i < sections.length; i++) {
5304
+ const section = sections[i];
5278
5305
  const ns = getNamespace(section, i);
5279
5306
  const sectionToValidate = ns ? namespaceSectionConfig(section, ns) : section;
5280
5307
  const valid = sectionValidate(sectionToValidate, values, dispatch);
@@ -5296,16 +5323,18 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
5296
5323
  },
5297
5324
  getStructuredData: () => {
5298
5325
  const values = getValues();
5326
+ const sections = safeSectionsRef.current;
5299
5327
  const results = [];
5300
- for (let i = 0; i < safeSections.length; i++) {
5301
- const section = safeSections[i];
5328
+ for (let i = 0; i < sections.length; i++) {
5329
+ const section = sections[i];
5302
5330
  const ns = getNamespace(section, i);
5303
5331
  results.push(buildSectionChanges(section, values, ns));
5304
5332
  }
5305
5333
  return results;
5306
5334
  },
5307
5335
  };
5308
- }, [store, dispatch, safeSections]);
5336
+ // eslint-disable-next-line react-hooks/exhaustive-deps
5337
+ }, [store, dispatch]); // safeSections intentionally omitted — accessed via safeSectionsRef
5309
5338
  // Call onFormReady when form is ready (sections loaded)
5310
5339
  useEffect(() => {
5311
5340
  if (onFormReady && safeSections.length > 0) {
@@ -5389,6 +5418,8 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
5389
5418
  onSectionSaveSuccess: handleSectionSaveSuccess,
5390
5419
  onPreviousSection: handlePreviousSection,
5391
5420
  isDraft,
5421
+ // Accessible = every visited section + the one immediately after
5422
+ isAccessible: index <= maxVisitedIndex + 1,
5392
5423
  }
5393
5424
  : {};
5394
5425
  // RegistryView: single-edit coordination props