@openg2p/registry-widgets 1.1.0-dev.8 → 1.1.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/components/SectionRenderer.d.ts +7 -1
- package/dist/components/SectionRenderer.d.ts.map +1 -1
- package/dist/components/SectionsContainer.d.ts.map +1 -1
- package/dist/hooks/useBaseWidget.d.ts.map +1 -1
- package/dist/index.d.ts +13 -3
- package/dist/index.esm.js +105 -48
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +105 -48
- package/dist/index.js.map +1 -1
- package/dist/utils/dataSource.d.ts.map +1 -1
- package/dist/utils/sectionValidate.d.ts +9 -1
- package/dist/utils/sectionValidate.d.ts.map +1 -1
- package/dist/utils/validation.d.ts +6 -2
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/widgets/TextAreaWidget.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -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;
|
|
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,
|
|
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,4CAqUxB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBaseWidget.d.ts","sourceRoot":"","sources":["../../src/hooks/useBaseWidget.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAgBtE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,gBAAgB,CAAC;IACzB,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACxD;AAMD,eAAO,MAAM,aAAa,GAAI,SAAS,oBAAoB;;;;;;;;;yBAsM5C,GAAG,aAAY,OAAO;;
|
|
1
|
+
{"version":3,"file":"useBaseWidget.d.ts","sourceRoot":"","sources":["../../src/hooks/useBaseWidget.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAgBtE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,gBAAgB,CAAC;IACzB,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACxD;AAMD,eAAO,MAAM,aAAa,GAAI,SAAS,oBAAoB;;;;;;;;;yBAsM5C,GAAG,aAAY,OAAO;;uBAgUd,MAAM,EAAE;;;;;;;0BArMpB,MAAM;;;CA0MhB,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;
|
|
@@ -1523,9 +1529,13 @@ declare const getWidgetValue: (values: Record<string, any>, dataPath: string | R
|
|
|
1523
1529
|
declare const setWidgetValue: (currentValues: Record<string, any>, dataPath: string | Record<string, string> | undefined, widgetId: string, value: any) => Record<string, any>;
|
|
1524
1530
|
|
|
1525
1531
|
/**
|
|
1526
|
-
* Validate value against validation rules
|
|
1532
|
+
* Validate value against validation rules.
|
|
1533
|
+
*
|
|
1534
|
+
* @param skipRequired - When true, required-field checks are skipped (used by
|
|
1535
|
+
* per-section Save/Next buttons so the user can move between sections without
|
|
1536
|
+
* filling every mandatory field; only format/range checks still run).
|
|
1527
1537
|
*/
|
|
1528
|
-
declare const validateWidget: (value: any, validation: WidgetValidation | undefined, required?: boolean) => string[];
|
|
1538
|
+
declare const validateWidget: (value: any, validation: WidgetValidation | undefined, required?: boolean, skipRequired?: boolean) => string[];
|
|
1529
1539
|
/**
|
|
1530
1540
|
* Create Zod schema from validation config
|
|
1531
1541
|
*/
|
package/dist/index.esm.js
CHANGED
|
@@ -245,24 +245,27 @@ const getValidationPattern = (validationType) => {
|
|
|
245
245
|
};
|
|
246
246
|
|
|
247
247
|
/**
|
|
248
|
-
* Validate value against validation rules
|
|
248
|
+
* Validate value against validation rules.
|
|
249
|
+
*
|
|
250
|
+
* @param skipRequired - When true, required-field checks are skipped (used by
|
|
251
|
+
* per-section Save/Next buttons so the user can move between sections without
|
|
252
|
+
* filling every mandatory field; only format/range checks still run).
|
|
249
253
|
*/
|
|
250
|
-
const validateWidget = (value, validation, required = false) => {
|
|
254
|
+
const validateWidget = (value, validation, required = false, skipRequired = false) => {
|
|
251
255
|
const errors = [];
|
|
252
256
|
if (!validation && !required) {
|
|
253
257
|
return errors;
|
|
254
258
|
}
|
|
255
|
-
// Check required
|
|
256
|
-
const isRequired = validation?.required ?? required;
|
|
259
|
+
// Check required (skipped when navigating between sections)
|
|
260
|
+
const isRequired = !skipRequired && (validation?.required ?? required);
|
|
257
261
|
// For boolean, false is a valid value, so only check for null/undefined/empty string
|
|
258
262
|
const isEmpty = value === null || value === undefined || value === '';
|
|
259
263
|
if (isRequired && isEmpty) {
|
|
260
264
|
errors.push('This field is required');
|
|
261
265
|
return errors; // Return early if required field is empty
|
|
262
266
|
}
|
|
263
|
-
// Skip
|
|
264
|
-
|
|
265
|
-
if (isEmpty && !isRequired) {
|
|
267
|
+
// Skip format/range validations if value is empty
|
|
268
|
+
if (isEmpty) {
|
|
266
269
|
return errors;
|
|
267
270
|
}
|
|
268
271
|
if (!validation) {
|
|
@@ -1074,16 +1077,12 @@ const getApiDataSource = async (dataSource, allValues, dataSourceRequestHandler,
|
|
|
1074
1077
|
console.error('[getApiDataSource] API data source missing endpoint. Use "endpoint" field to specify the operation (e.g., "get_g2p_geo_level_values")');
|
|
1075
1078
|
return [];
|
|
1076
1079
|
}
|
|
1077
|
-
let
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
}
|
|
1083
|
-
catch (error) {
|
|
1084
|
-
console.error('[getApiDataSource] Handler error:', error);
|
|
1085
|
-
throw error;
|
|
1086
|
-
}
|
|
1080
|
+
// Call handler — let any throw propagate to the outer catch so it is logged once
|
|
1081
|
+
// by useBaseWidget rather than double-logged here (which can cascade when
|
|
1082
|
+
// intercept-console-error.js converts console.error calls into thrown errors).
|
|
1083
|
+
const response = await dataSourceRequestHandler(service, endpoint, method, requestParams, {
|
|
1084
|
+
headers: dataSource.headers,
|
|
1085
|
+
});
|
|
1087
1086
|
// Handle OpenG2P response format (response_body.response_payload)
|
|
1088
1087
|
if (response && typeof response === 'object') {
|
|
1089
1088
|
if (response.response_body?.response_payload && Array.isArray(response.response_body.response_payload)) {
|
|
@@ -1106,8 +1105,8 @@ const getApiDataSource = async (dataSource, allValues, dataSourceRequestHandler,
|
|
|
1106
1105
|
return [];
|
|
1107
1106
|
}
|
|
1108
1107
|
catch (error) {
|
|
1109
|
-
|
|
1110
|
-
|
|
1108
|
+
// Rethrow so useBaseWidget's catch can log it with full widget context
|
|
1109
|
+
throw error;
|
|
1111
1110
|
}
|
|
1112
1111
|
};
|
|
1113
1112
|
/**
|
|
@@ -2301,7 +2300,7 @@ const useBaseWidget = (options) => {
|
|
|
2301
2300
|
dispatch(setDataSource({ widgetId, data: transformed }));
|
|
2302
2301
|
}
|
|
2303
2302
|
catch (error) {
|
|
2304
|
-
console.error(`[useBaseWidget] ERROR loading data source for ${widgetId}:`, error);
|
|
2303
|
+
console.error(`[useBaseWidget] ERROR loading data source for widget "${widgetId}" (type="${dataSource.type}"):`, error, '\nWidget config:', config, '\ndataSourceRequestHandler provided:', Boolean(dataSourceRequestHandler));
|
|
2305
2304
|
dispatch(setDataSource({ widgetId, data: [] }));
|
|
2306
2305
|
}
|
|
2307
2306
|
finally {
|
|
@@ -3806,7 +3805,15 @@ const collectWidgets = (panels) => {
|
|
|
3806
3805
|
});
|
|
3807
3806
|
return widgets;
|
|
3808
3807
|
};
|
|
3809
|
-
|
|
3808
|
+
/**
|
|
3809
|
+
* Validate all widgets in a section and dispatch errors to the store.
|
|
3810
|
+
*
|
|
3811
|
+
* @param skipRequired - When true, required-field checks (widget-required,
|
|
3812
|
+
* validation.required, document-required) are skipped. Use this for
|
|
3813
|
+
* per-section Save/Next navigation so the user can advance without filling
|
|
3814
|
+
* every mandatory field; only format/range errors are reported.
|
|
3815
|
+
*/
|
|
3816
|
+
const sectionValidate = (section, currentSchemaData, dispatch, skipRequired = false) => {
|
|
3810
3817
|
const allWidgets = collectWidgets(section.panels);
|
|
3811
3818
|
let isValid = true;
|
|
3812
3819
|
for (const widget of allWidgets) {
|
|
@@ -3815,7 +3822,7 @@ const sectionValidate = (section, currentSchemaData, dispatch) => {
|
|
|
3815
3822
|
continue;
|
|
3816
3823
|
const widgetId = widget['widget-id'];
|
|
3817
3824
|
const value = getWidgetValue(currentSchemaData, widget['widget-data-path'], widgetId);
|
|
3818
|
-
const errors = validateWidget(value, widget['widget-data-validation'], widget['widget-required']);
|
|
3825
|
+
const errors = validateWidget(value, widget['widget-data-validation'], widget['widget-required'], skipRequired);
|
|
3819
3826
|
if (errors.length > 0) {
|
|
3820
3827
|
isValid = false;
|
|
3821
3828
|
dispatch(setTouched({ widgetId, touched: true }));
|
|
@@ -3826,10 +3833,10 @@ const sectionValidate = (section, currentSchemaData, dispatch) => {
|
|
|
3826
3833
|
dispatch(setError({ widgetId, errors: [] }));
|
|
3827
3834
|
}
|
|
3828
3835
|
}
|
|
3829
|
-
// Supporting Documents
|
|
3836
|
+
// Supporting Documents — only check required when not skipping required validation
|
|
3830
3837
|
section['section-supporting-documents']?.forEach((doc, index) => {
|
|
3831
3838
|
const widgetId = `supporting-doc-${section['section-id']}-${index}`;
|
|
3832
|
-
if (doc['document-required']) {
|
|
3839
|
+
if (!skipRequired && doc['document-required']) {
|
|
3833
3840
|
const file = getValueByPath(currentSchemaData, doc['document-data-path']);
|
|
3834
3841
|
if (!file) {
|
|
3835
3842
|
isValid = false;
|
|
@@ -3935,7 +3942,7 @@ function scopedClassSelectors(sectionClassId, classNames) {
|
|
|
3935
3942
|
* - Panels wrap when they exceed available width
|
|
3936
3943
|
* - Sections can sit side-by-side if there's space
|
|
3937
3944
|
*/
|
|
3938
|
-
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, }) => {
|
|
3945
|
+
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, }) => {
|
|
3939
3946
|
const { translateConfig, translate } = useWidgetTranslation();
|
|
3940
3947
|
const resolvedTheme = useWidgetTheme();
|
|
3941
3948
|
const portalCSSVariables = useMemo(() => themeToCSSVariables(resolvedTheme), [resolvedTheme]);
|
|
@@ -4001,16 +4008,25 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4001
4008
|
const isExpandedFromContainer = typeof sectionIndex === 'number' && expandedSectionIndex === sectionIndex;
|
|
4002
4009
|
const isExpandedStandalone = sectionIndex === undefined && standaloneExpanded;
|
|
4003
4010
|
const isExpanded = mode === 'IntakeForm' && (isExpandedFromContainer || isExpandedStandalone);
|
|
4011
|
+
// IntakeForm only: tracks whether the user has clicked Next on this section at least once.
|
|
4012
|
+
// Used to unlock the accordion header so the user can navigate back to a visited section.
|
|
4013
|
+
const [hasBeenSavedByUser, setHasBeenSavedByUser] = useState(false);
|
|
4014
|
+
// Accordion header click behaviour in IntakeForm mode:
|
|
4015
|
+
// - Standalone (no sectionIndex): always toggleable.
|
|
4016
|
+
// - Managed by SectionsContainer: toggleable only when isAccessible is true
|
|
4017
|
+
// (i.e. the section has been visited OR is the immediate next one).
|
|
4018
|
+
// Sections beyond that remain locked.
|
|
4004
4019
|
const handleAccordionToggle = useCallback(() => {
|
|
4005
4020
|
if (mode !== 'IntakeForm')
|
|
4006
4021
|
return;
|
|
4007
|
-
if (
|
|
4008
|
-
onExpandSection(sectionIndex);
|
|
4009
|
-
}
|
|
4010
|
-
else if (sectionIndex === undefined) {
|
|
4022
|
+
if (sectionIndex === undefined) {
|
|
4011
4023
|
setStandaloneExpanded(prev => !prev);
|
|
4012
4024
|
}
|
|
4013
|
-
|
|
4025
|
+
else if (isAccessible && onExpandSection) {
|
|
4026
|
+
onExpandSection(sectionIndex);
|
|
4027
|
+
}
|
|
4028
|
+
// Intentionally no-op for locked sections (isAccessible === false)
|
|
4029
|
+
}, [mode, sectionIndex, isAccessible, onExpandSection]);
|
|
4014
4030
|
// Recursively count all vertical panels, especially those nested inside horizontal panels
|
|
4015
4031
|
// Typically: horizontal panels at first level contain vertical panels at second level
|
|
4016
4032
|
// Accounts for panel-column-span: a panel with column-span 3 counts as 3 columns
|
|
@@ -4345,8 +4361,6 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4345
4361
|
const baselineSnapshotRef = useRef(null);
|
|
4346
4362
|
// IntakeForm only: increment when baseline is updated after save - forces badge to update (refs don't trigger re-renders)
|
|
4347
4363
|
const [intakeFormBaselineTrigger, setIntakeFormBaselineTrigger] = useState(0);
|
|
4348
|
-
// IntakeForm only: tracks whether the user has actually saved this section (prevents "Saved" badge on initial load)
|
|
4349
|
-
const [hasBeenSavedByUser, setHasBeenSavedByUser] = useState(false);
|
|
4350
4364
|
// IntakeForm: treat as edit mode for dirty tracking when isDraft. RegistryView: use isEditMode.
|
|
4351
4365
|
const effectiveEditModeForDirty = mode === 'IntakeForm' ? (isDraft !== false) : isEditMode;
|
|
4352
4366
|
// Compute isDirty: compare current store state to baseline (only when in edit mode)
|
|
@@ -4464,7 +4478,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4464
4478
|
const sectionWidgets = collectWidgets(originalSection.panels);
|
|
4465
4479
|
const currentState = store.getState().widget;
|
|
4466
4480
|
const currentSchemaData = currentState.values || {};
|
|
4467
|
-
const isSectionValid = sectionValidate(originalSection, currentSchemaData, dispatch);
|
|
4481
|
+
const isSectionValid = sectionValidate(originalSection, currentSchemaData, dispatch, true);
|
|
4468
4482
|
if (!isSectionValid) {
|
|
4469
4483
|
return;
|
|
4470
4484
|
}
|
|
@@ -4530,7 +4544,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4530
4544
|
const sectionWidgets = collectWidgets(originalSection.panels);
|
|
4531
4545
|
const currentState = store.getState().widget;
|
|
4532
4546
|
const currentSchemaData = currentState.values || {};
|
|
4533
|
-
const isSectionValid = sectionValidate(originalSection, currentSchemaData, dispatch);
|
|
4547
|
+
const isSectionValid = sectionValidate(originalSection, currentSchemaData, dispatch, true);
|
|
4534
4548
|
if (!isSectionValid)
|
|
4535
4549
|
return;
|
|
4536
4550
|
const oldSchemaData = schemaData || contextSchemaData;
|
|
@@ -4579,6 +4593,11 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4579
4593
|
}
|
|
4580
4594
|
onSectionDirtyChange?.(sectionId, false);
|
|
4581
4595
|
}
|
|
4596
|
+
else if (mode === 'IntakeForm') {
|
|
4597
|
+
// No onSectionSave provided, but still mark section as visited so the
|
|
4598
|
+
// user can navigate back to it by clicking the accordion header.
|
|
4599
|
+
setHasBeenSavedByUser(true);
|
|
4600
|
+
}
|
|
4582
4601
|
// Always navigate to the next section
|
|
4583
4602
|
onSectionSaveSuccess?.(sectionIndex);
|
|
4584
4603
|
}, [store, onSectionSave, onSectionSaveSuccess, sectionIndex, originalSection, schemaData, contextSchemaData, namespace, hasSupportingDocuments, dbSectionId, sectionRegisterId, dispatch, buildSectionSnapshot, sectionId, onSectionDirtyChange, mode, isDraft]);
|
|
@@ -4797,13 +4816,17 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4797
4816
|
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header h2 {
|
|
4798
4817
|
color: var(--owt-color-primary-dark, #F07B1A);
|
|
4799
4818
|
}
|
|
4800
|
-
|
|
4819
|
+
/* Hover / focus only shown when the header is actually interactive (standalone mode) */
|
|
4820
|
+
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header[data-interactive="true"]:hover {
|
|
4801
4821
|
opacity: 0.85;
|
|
4802
4822
|
}
|
|
4803
|
-
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header:focus-visible {
|
|
4823
|
+
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header[data-interactive="true"]:focus-visible {
|
|
4804
4824
|
outline: 2px solid var(--owt-color-primary, #F5BB1A);
|
|
4805
4825
|
outline-offset: 2px;
|
|
4806
4826
|
}
|
|
4827
|
+
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header[data-interactive="false"]:focus-visible {
|
|
4828
|
+
outline: none;
|
|
4829
|
+
}
|
|
4807
4830
|
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-content {
|
|
4808
4831
|
padding-top: 8px;
|
|
4809
4832
|
padding-bottom: 0px;
|
|
@@ -4846,7 +4869,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4846
4869
|
}),
|
|
4847
4870
|
}, children: mode === 'IntakeForm' ? (
|
|
4848
4871
|
/* IntakeForm: accordion layout - header always visible, content only when expanded */
|
|
4849
|
-
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, style: {
|
|
4872
|
+
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: {
|
|
4850
4873
|
width: '100%',
|
|
4851
4874
|
display: 'flex',
|
|
4852
4875
|
alignItems: 'flex-start',
|
|
@@ -4856,7 +4879,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4856
4879
|
marginBottom: 0,
|
|
4857
4880
|
background: 'none',
|
|
4858
4881
|
border: 'none',
|
|
4859
|
-
cursor: 'pointer',
|
|
4882
|
+
cursor: sectionIndex === undefined || isAccessible ? 'pointer' : 'default',
|
|
4860
4883
|
textAlign: 'left',
|
|
4861
4884
|
fontFamily: 'Roboto, sans-serif',
|
|
4862
4885
|
}, 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']
|
|
@@ -5154,6 +5177,11 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
5154
5177
|
const dataSourceRequestHandler = propDataSourceRequestHandler || contextDataSourceRequestHandler;
|
|
5155
5178
|
// IntakeForm mode: accordion state - which section is expanded (null = none; first expanded by default)
|
|
5156
5179
|
const [expandedSectionIndex, setExpandedSectionIndex] = useState(0);
|
|
5180
|
+
// IntakeForm mode: high-water mark of the furthest section the user has clicked Next on.
|
|
5181
|
+
// A section at index i is accessible when i <= maxVisitedIndex + 1
|
|
5182
|
+
// (i.e. every visited section plus the one immediately after it).
|
|
5183
|
+
// Starts at -1 so only section 0 is accessible before any Next is clicked.
|
|
5184
|
+
const [maxVisitedIndex, setMaxVisitedIndex] = useState(-1);
|
|
5157
5185
|
// RegistryView: track which section is currently in edit mode (by section-id); null = none
|
|
5158
5186
|
const [editingSectionId, setEditingSectionId] = useState(null);
|
|
5159
5187
|
const handleEditModeChange = useCallback((sectionId, editing) => {
|
|
@@ -5164,6 +5192,10 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
5164
5192
|
// Stable ref for namespace so formHandle useMemo doesn't depend on the (possibly inline) function identity
|
|
5165
5193
|
const namespaceRef = useRef(namespace);
|
|
5166
5194
|
namespaceRef.current = namespace;
|
|
5195
|
+
// Stable refs so formHandle closure can access current mode and accordion setter without stale captures
|
|
5196
|
+
const modeRef = useRef(mode);
|
|
5197
|
+
modeRef.current = mode;
|
|
5198
|
+
const setExpandedSectionIndexRef = useRef(setExpandedSectionIndex);
|
|
5167
5199
|
// Track dirty (unsaved changes) per section for form handle validation
|
|
5168
5200
|
const sectionDirtyMapRef = useRef({});
|
|
5169
5201
|
const handleSectionDirtyChange = useCallback((sectionId, isDirty) => {
|
|
@@ -5174,8 +5206,9 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
5174
5206
|
const handleExpandSection = useCallback((index) => {
|
|
5175
5207
|
setExpandedSectionIndex(prev => (prev === index ? null : index));
|
|
5176
5208
|
}, []);
|
|
5177
|
-
// IntakeForm mode: called after section save - collapse current, expand next
|
|
5209
|
+
// IntakeForm mode: called after section save - advance high-water mark, collapse current, expand next
|
|
5178
5210
|
const handleSectionSaveSuccess = useCallback((index) => {
|
|
5211
|
+
setMaxVisitedIndex(prev => Math.max(prev, index));
|
|
5179
5212
|
if (index + 1 < safeSections.length) {
|
|
5180
5213
|
setExpandedSectionIndex(index + 1);
|
|
5181
5214
|
}
|
|
@@ -5225,33 +5258,52 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
5225
5258
|
};
|
|
5226
5259
|
return {
|
|
5227
5260
|
validate: async () => {
|
|
5228
|
-
|
|
5261
|
+
if (modeRef.current !== 'IntakeForm')
|
|
5262
|
+
checkNoUnsavedChanges();
|
|
5229
5263
|
const values = getValues();
|
|
5230
5264
|
let allValid = true;
|
|
5265
|
+
let firstInvalidIndex = null;
|
|
5231
5266
|
for (let i = 0; i < safeSections.length; i++) {
|
|
5232
5267
|
const section = safeSections[i];
|
|
5233
5268
|
const ns = getNamespace(section, i);
|
|
5234
5269
|
const sectionToValidate = ns ? namespaceSectionConfig(section, ns) : section;
|
|
5235
5270
|
const valid = sectionValidate(sectionToValidate, values, dispatch);
|
|
5236
|
-
if (!valid)
|
|
5271
|
+
if (!valid) {
|
|
5272
|
+
if (firstInvalidIndex === null)
|
|
5273
|
+
firstInvalidIndex = i;
|
|
5237
5274
|
allValid = false;
|
|
5275
|
+
}
|
|
5276
|
+
}
|
|
5277
|
+
if (!allValid && modeRef.current === 'IntakeForm' && firstInvalidIndex !== null) {
|
|
5278
|
+
setExpandedSectionIndexRef.current(firstInvalidIndex);
|
|
5238
5279
|
}
|
|
5239
5280
|
return allValid;
|
|
5240
5281
|
},
|
|
5241
5282
|
getFormData: () => getValues(),
|
|
5242
5283
|
validateAndGetData: async () => {
|
|
5243
|
-
|
|
5284
|
+
if (modeRef.current !== 'IntakeForm')
|
|
5285
|
+
checkNoUnsavedChanges();
|
|
5244
5286
|
const values = getValues();
|
|
5245
5287
|
const results = [];
|
|
5288
|
+
let firstInvalidIndex = null;
|
|
5246
5289
|
for (let i = 0; i < safeSections.length; i++) {
|
|
5247
5290
|
const section = safeSections[i];
|
|
5248
5291
|
const ns = getNamespace(section, i);
|
|
5249
5292
|
const sectionToValidate = ns ? namespaceSectionConfig(section, ns) : section;
|
|
5250
5293
|
const valid = sectionValidate(sectionToValidate, values, dispatch);
|
|
5251
5294
|
if (!valid) {
|
|
5252
|
-
|
|
5295
|
+
if (firstInvalidIndex === null)
|
|
5296
|
+
firstInvalidIndex = i;
|
|
5297
|
+
}
|
|
5298
|
+
else {
|
|
5299
|
+
results.push(buildSectionChanges(section, values, ns));
|
|
5253
5300
|
}
|
|
5254
|
-
|
|
5301
|
+
}
|
|
5302
|
+
if (firstInvalidIndex !== null) {
|
|
5303
|
+
if (modeRef.current === 'IntakeForm') {
|
|
5304
|
+
setExpandedSectionIndexRef.current(firstInvalidIndex);
|
|
5305
|
+
}
|
|
5306
|
+
throw new Error('Validation failed. Please fix the errors and try again.');
|
|
5255
5307
|
}
|
|
5256
5308
|
return results;
|
|
5257
5309
|
},
|
|
@@ -5350,6 +5402,8 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
5350
5402
|
onSectionSaveSuccess: handleSectionSaveSuccess,
|
|
5351
5403
|
onPreviousSection: handlePreviousSection,
|
|
5352
5404
|
isDraft,
|
|
5405
|
+
// Accessible = every visited section + the one immediately after
|
|
5406
|
+
isAccessible: index <= maxVisitedIndex + 1,
|
|
5353
5407
|
}
|
|
5354
5408
|
: {};
|
|
5355
5409
|
// RegistryView: single-edit coordination props
|
|
@@ -7332,7 +7386,7 @@ const NumberInputWidget = ({ config }) => {
|
|
|
7332
7386
|
if (parsed === null) {
|
|
7333
7387
|
// Allow empty input or partial input (e.g., "-", ".")
|
|
7334
7388
|
if (inputValue === '' || inputValue === '-' || inputValue === '.') {
|
|
7335
|
-
onChange(
|
|
7389
|
+
onChange(null);
|
|
7336
7390
|
}
|
|
7337
7391
|
// Don't update if invalid - let user continue typing
|
|
7338
7392
|
return;
|
|
@@ -9696,10 +9750,13 @@ const TextAreaWidget = ({ config }) => {
|
|
|
9696
9750
|
// For readonly mode, render as preformatted text using <pre> tag
|
|
9697
9751
|
if (isReadonly) {
|
|
9698
9752
|
const displayValue = getStringValue() || '-';
|
|
9699
|
-
return (jsxRuntimeExports.jsxs("div", { className: "mb-[10px] TextAreaDisplayWidget flex flex-col sm:flex-row sm:items-start", children: [label && (jsxRuntimeExports.jsxs("div", { className: "text-base text-gray-600 font-medium md:min-w-[120px] sm:pr-4 mb-1 sm:mb-0", style: { fontFamily: 'Roboto, sans-serif' }, title: label, children: [label, ":"] })), jsxRuntimeExports.jsx("div", { className: "flex-1", children: jsxRuntimeExports.jsx("
|
|
9753
|
+
return (jsxRuntimeExports.jsxs("div", { className: "mb-[10px] TextAreaDisplayWidget flex flex-col sm:flex-row sm:items-start", children: [label && (jsxRuntimeExports.jsxs("div", { className: "text-base text-gray-600 font-medium md:min-w-[120px] sm:pr-4 mb-1 sm:mb-0", style: { fontFamily: 'Roboto, sans-serif' }, title: label, children: [label, ":"] })), jsxRuntimeExports.jsx("div", { className: "flex-1", children: jsxRuntimeExports.jsx("div", { title: String(displayValue), className: "text-base text-gray-900 font-medium overflow-y-auto whitespace-pre-wrap break-words", style: {
|
|
9700
9754
|
fontFamily: 'Roboto, sans-serif',
|
|
9701
|
-
|
|
9702
|
-
|
|
9755
|
+
height: '56px',
|
|
9756
|
+
minHeight: '56px',
|
|
9757
|
+
maxHeight: '56px',
|
|
9758
|
+
lineHeight: '20px',
|
|
9759
|
+
padding: '8px 0',
|
|
9703
9760
|
backgroundColor: 'transparent',
|
|
9704
9761
|
border: 'none',
|
|
9705
9762
|
}, children: displayValue }) })] }));
|