@openg2p/registry-widgets 1.0.0 → 1.0.2

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.
@@ -6,6 +6,7 @@ export interface SectionChanges {
6
6
  section_register_id?: string;
7
7
  records: unknown[];
8
8
  files?: unknown[];
9
+ image?: File | null;
9
10
  }
10
11
  export interface SectionRendererProps {
11
12
  section: SectionConfig;
@@ -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;AAM9D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMlD,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;CACnB;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,4CAq6CtB,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;AAM9D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AA0ClD,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,4CAm8CtB,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;AA4ED;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,yMAa/B,sBAAsB,4CA+RxB,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;AA4ED;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,yMAa/B,sBAAsB,4CAqSxB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -553,6 +553,7 @@ interface SectionChanges {
553
553
  section_register_id?: string;
554
554
  records: unknown[];
555
555
  files?: unknown[];
556
+ image?: File | null;
556
557
  }
557
558
  interface SectionRendererProps {
558
559
  section: SectionConfig;
package/dist/index.esm.js CHANGED
@@ -3515,6 +3515,39 @@ const sectionValidate = (section, currentSchemaData, dispatch) => {
3515
3515
  return isValid;
3516
3516
  };
3517
3517
 
3518
+ /** Root class on readonly label/value rows; SectionRenderer scopes overflow/ellipsis rules here. */
3519
+ const READONLY_VALUE_ROW_ROOT_CLASSES = [
3520
+ 'TextDisplayWidget',
3521
+ 'TextAreaDisplayWidget',
3522
+ 'SelectDisplayWidget',
3523
+ 'PhoneDisplayWidget',
3524
+ 'NumberDisplayWidget',
3525
+ 'CurrencyDisplayWidget',
3526
+ 'RadioDisplayWidget',
3527
+ 'DateDisplayWidget',
3528
+ 'DateTimeDisplayWidget',
3529
+ 'CheckboxDisplayWidget',
3530
+ 'BooleanDisplayWidget',
3531
+ 'FileDisplayWidget',
3532
+ 'DisplayFieldWidget',
3533
+ ];
3534
+ /** Rows whose value is one line in .flex-1 > .text-gray-900 (ellipsis; full string via title on the element). */
3535
+ const READONLY_SINGLE_LINE_VALUE_ROW_CLASSES = [
3536
+ 'TextDisplayWidget',
3537
+ 'SelectDisplayWidget',
3538
+ 'PhoneDisplayWidget',
3539
+ 'NumberDisplayWidget',
3540
+ 'CurrencyDisplayWidget',
3541
+ 'RadioDisplayWidget',
3542
+ 'DateDisplayWidget',
3543
+ 'DateTimeDisplayWidget',
3544
+ 'CheckboxDisplayWidget',
3545
+ 'BooleanDisplayWidget',
3546
+ 'DisplayFieldWidget',
3547
+ ];
3548
+ function scopedClassSelectors(sectionClassId, classNames) {
3549
+ return classNames.map((c) => `.${sectionClassId} .${c}`).join(',\n ');
3550
+ }
3518
3551
  /**
3519
3552
  * Renders a section with its panels
3520
3553
  *
@@ -3541,41 +3574,22 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
3541
3574
  }
3542
3575
  return section;
3543
3576
  }, [section, namespace]);
3544
- // Create namespaced schemaData if namespace is provided
3545
- // This ensures widgets can read initial values from schemaData at namespaced paths
3577
+ // Create namespaced schemaData if namespace is provided.
3578
+ // Widgets with namespaced data-paths (e.g. "rv-section-0.a1a4d25a.birth_date")
3579
+ // need a nested object at values[namespace] so getValueByPath can traverse it.
3546
3580
  const namespacedSchemaData = useMemo(() => {
3547
3581
  if (!namespace || !currentSchemaData) {
3548
3582
  return schemaData;
3549
3583
  }
3550
- // Create a namespaced version of schemaData by copying values to namespaced paths
3551
- const namespaced = { ...currentSchemaData };
3552
- // Copy all top-level keys to namespaced paths
3553
- Object.keys(currentSchemaData).forEach(key => {
3554
- const namespacedKey = `${namespace}.${key}`;
3555
- if (!(namespacedKey in namespaced)) {
3556
- namespaced[namespacedKey] = currentSchemaData[key];
3557
- }
3558
- });
3559
- // Also handle nested objects - copy nested values to namespaced paths
3560
- const copyNestedValues = (obj, prefix = '') => {
3561
- if (obj && typeof obj === 'object' && !Array.isArray(obj)) {
3562
- Object.keys(obj).forEach(key => {
3563
- const fullPath = prefix ? `${prefix}.${key}` : key;
3564
- const namespacedPath = `${namespace}.${fullPath}`;
3565
- if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
3566
- copyNestedValues(obj[key], fullPath);
3567
- // Also set the nested object at the namespaced path
3568
- setValueByPath(namespaced, namespacedPath, obj[key]);
3569
- }
3570
- else {
3571
- setValueByPath(namespaced, namespacedPath, obj[key]);
3572
- }
3573
- });
3574
- }
3575
- };
3576
- copyNestedValues(currentSchemaData);
3577
- return namespaced;
3584
+ return { ...currentSchemaData, [namespace]: currentSchemaData };
3578
3585
  }, [namespace, schemaData, currentSchemaData]);
3586
+ // Populate the store with namespaced schema data so that namespaced widgets
3587
+ // can read their initial values via getValueByPath on the namespaced paths.
3588
+ useEffect(() => {
3589
+ if (namespace && namespacedSchemaData) {
3590
+ dispatch(setValues(namespacedSchemaData));
3591
+ }
3592
+ }, [namespace, namespacedSchemaData, dispatch]);
3579
3593
  const crViewData = useMemo(() => {
3580
3594
  if (mode !== 'CRView')
3581
3595
  return null;
@@ -3598,6 +3612,9 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
3598
3612
  const sectionId = sectionToRender['section-id'];
3599
3613
  const gridId = `section-panels-${sectionId}`;
3600
3614
  const sectionClassId = `section-${sectionId}`;
3615
+ const readonlyValueRowRootsCss = useMemo(() => scopedClassSelectors(sectionClassId, READONLY_VALUE_ROW_ROOT_CLASSES), [sectionClassId]);
3616
+ const readonlyValueRowFlex1Css = useMemo(() => READONLY_VALUE_ROW_ROOT_CLASSES.map((c) => `.${sectionClassId} .${c} > .flex-1`).join(',\n '), [sectionClassId]);
3617
+ const readonlySingleLineValueTextCss = useMemo(() => READONLY_SINGLE_LINE_VALUE_ROW_CLASSES.map((c) => `.${sectionClassId} .${c} > .flex-1 > .text-gray-900`).join(',\n '), [sectionClassId]);
3601
3618
  // IntakeForm mode: accordion expand/collapse state (supports toggle)
3602
3619
  const [standaloneExpanded, setStandaloneExpanded] = useState(true); // For sectionIndex undefined (standalone use)
3603
3620
  const isExpandedFromContainer = typeof sectionIndex === 'number' && expandedSectionIndex === sectionIndex;
@@ -3937,6 +3954,8 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
3937
3954
  const baselineSnapshotRef = useRef(null);
3938
3955
  // IntakeForm only: increment when baseline is updated after save - forces badge to update (refs don't trigger re-renders)
3939
3956
  const [intakeFormBaselineTrigger, setIntakeFormBaselineTrigger] = useState(0);
3957
+ // IntakeForm only: tracks whether the user has actually saved this section (prevents "Saved" badge on initial load)
3958
+ const [hasBeenSavedByUser, setHasBeenSavedByUser] = useState(false);
3940
3959
  // IntakeForm: treat as edit mode for dirty tracking when isDraft. RegistryView: use isEditMode.
3941
3960
  const effectiveEditModeForDirty = mode === 'IntakeForm' ? (isDraft !== false) : isEditMode;
3942
3961
  // Compute isDirty: compare current store state to baseline (only when in edit mode)
@@ -3979,18 +3998,68 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
3979
3998
  const intakeFormSectionStatus = useMemo(() => {
3980
3999
  if (mode !== 'IntakeForm' || isDraft === false)
3981
4000
  return null;
3982
- const hasValue = (v) => v !== undefined && v !== null && (typeof v !== 'string' || v.trim().length > 0);
3983
- const currentSnapshot = buildSectionSnapshot(storeValues, namespace);
3984
- const record = currentSnapshot.records?.[0];
3985
- const hasData = record &&
3986
- typeof record === 'object' &&
3987
- Object.values(record).some((v) => hasValue(v));
3988
4001
  if (isDirty)
3989
4002
  return 'modified';
3990
- if (hasData)
4003
+ if (hasBeenSavedByUser)
3991
4004
  return 'saved';
3992
4005
  return null;
3993
- }, [mode, isDirty, storeValues, namespace, buildSectionSnapshot]);
4006
+ }, [mode, isDirty, hasBeenSavedByUser]);
4007
+ // Revert store values to the original schemaData for this section's widgets.
4008
+ // Used by both handleSave (RegistryView raises a CR, so values should not persist)
4009
+ // and handleCancel.
4010
+ const revertToOriginalValues = useCallback(() => {
4011
+ const sectionWidgets = collectWidgets(originalSection.panels);
4012
+ const oldSchemaData = schemaData || contextSchemaData;
4013
+ const currentStoreValues = store.getState().widget.values;
4014
+ let newStoreValues = currentStoreValues;
4015
+ sectionWidgets.forEach(widget => {
4016
+ const originalWidgetId = widget['widget-id'];
4017
+ const namespacedWidgetId = namespace ? `${namespace}__${originalWidgetId}` : originalWidgetId;
4018
+ const widgetId = namespacedWidgetId;
4019
+ const originalDataPath = widget['widget-data-path'];
4020
+ const storeDataPath = namespace && originalDataPath
4021
+ ? (typeof originalDataPath === 'string'
4022
+ ? `${namespace}.${originalDataPath}`
4023
+ : Object.fromEntries(Object.entries(originalDataPath).map(([key, path]) => [key, `${namespace}.${path}`])))
4024
+ : originalDataPath;
4025
+ if (widgetId && originalDataPath) {
4026
+ let oldValue;
4027
+ if (typeof originalDataPath === 'object') {
4028
+ oldValue = {};
4029
+ Object.entries(originalDataPath).forEach(([key, path]) => {
4030
+ if (typeof path === 'string') {
4031
+ oldValue[key] = getValueByPath(oldSchemaData, path);
4032
+ }
4033
+ });
4034
+ }
4035
+ else if (typeof originalDataPath === 'string') {
4036
+ oldValue = getValueByPath(oldSchemaData, originalDataPath);
4037
+ }
4038
+ if (oldValue !== undefined) {
4039
+ newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
4040
+ // Also revert the widgetId-based entry — useBaseWidget.handleChange
4041
+ // sets values[widgetId] during editing, and useBaseWidget.currentValue
4042
+ // reads values[widgetId] first before falling through to the dataPath.
4043
+ newStoreValues = { ...newStoreValues, [widgetId]: oldValue };
4044
+ }
4045
+ }
4046
+ });
4047
+ if (hasSupportingDocuments) {
4048
+ const originalSupportingDocuments = originalSection['section-supporting-documents'] || [];
4049
+ originalSupportingDocuments.forEach((doc, index) => {
4050
+ const widgetId = `supporting-doc-${sectionId}-${index}`;
4051
+ const originalDataPath = doc['document-data-path'];
4052
+ const storeDataPath = namespace && originalDataPath
4053
+ ? `${namespace}.${originalDataPath}`
4054
+ : originalDataPath;
4055
+ const oldValue = getValueByPath(oldSchemaData, originalDataPath);
4056
+ newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
4057
+ });
4058
+ }
4059
+ if (newStoreValues !== currentStoreValues) {
4060
+ dispatch(setValues(newStoreValues));
4061
+ }
4062
+ }, [originalSection, schemaData, contextSchemaData, store, namespace, hasSupportingDocuments, sectionId, dispatch]);
3994
4063
  // Handle save button click
3995
4064
  const handleSave = async () => {
3996
4065
  if (!store || !onSectionSave) {
@@ -4027,12 +4096,24 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4027
4096
  });
4028
4097
  }
4029
4098
  if (JSON.stringify(oldSchemaData) !== JSON.stringify(newSchemaData)) {
4099
+ let profileImage = null;
4100
+ for (const record of newSchemaData) {
4101
+ if (typeof record === 'object' && record !== null) {
4102
+ for (const [key, value] of Object.entries(record)) {
4103
+ if (value instanceof File) {
4104
+ profileImage = value;
4105
+ record[key] = '';
4106
+ }
4107
+ }
4108
+ }
4109
+ }
4030
4110
  try {
4031
4111
  const sectionchanges = {
4032
4112
  section_id: dbSectionId ?? originalSection['section-id'],
4033
4113
  section_register_id: sectionRegisterId,
4034
4114
  records: [...newSchemaData],
4035
- files: [...sectionFiles]
4115
+ files: [...sectionFiles],
4116
+ ...(profileImage ? { image: profileImage } : {}),
4036
4117
  };
4037
4118
  await onSectionSave(sectionchanges);
4038
4119
  }
@@ -4040,6 +4121,12 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4040
4121
  console.error('Section Changes Save failed', error);
4041
4122
  }
4042
4123
  }
4124
+ // In RegistryView, save raises a CR — the actual data update follows a
4125
+ // separate approval workflow, so revert the displayed values to the
4126
+ // originals so the view doesn't show unapproved edits.
4127
+ if (mode === 'RegistryView') {
4128
+ revertToOriginalValues();
4129
+ }
4043
4130
  setIsEditMode(false);
4044
4131
  onEditModeChange?.(originalSectionId, false);
4045
4132
  };
@@ -4069,12 +4156,24 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4069
4156
  });
4070
4157
  }
4071
4158
  if (JSON.stringify(oldSchemaData) !== JSON.stringify(newSchemaData)) {
4159
+ let profileImage = null;
4160
+ for (const record of newSchemaData) {
4161
+ if (typeof record === 'object' && record !== null) {
4162
+ for (const [key, value] of Object.entries(record)) {
4163
+ if (value instanceof File) {
4164
+ profileImage = value;
4165
+ record[key] = '';
4166
+ }
4167
+ }
4168
+ }
4169
+ }
4072
4170
  try {
4073
4171
  await onSectionSave({
4074
4172
  section_id: dbSectionId ?? originalSection['section-id'],
4075
4173
  section_register_id: sectionRegisterId,
4076
4174
  records: [...newSchemaData],
4077
4175
  files: [...sectionFiles],
4176
+ ...(profileImage ? { image: profileImage } : {}),
4078
4177
  });
4079
4178
  }
4080
4179
  catch (error) {
@@ -4085,6 +4184,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4085
4184
  if (mode === 'IntakeForm') {
4086
4185
  baselineSnapshotRef.current = buildSectionSnapshot(currentSchemaData, namespace);
4087
4186
  setIntakeFormBaselineTrigger((prev) => prev + 1);
4187
+ setHasBeenSavedByUser(true);
4088
4188
  }
4089
4189
  onSectionDirtyChange?.(sectionId, false);
4090
4190
  }
@@ -4093,64 +4193,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4093
4193
  }, [store, onSectionSave, onSectionSaveSuccess, sectionIndex, originalSection, schemaData, contextSchemaData, namespace, hasSupportingDocuments, dbSectionId, sectionRegisterId, dispatch, buildSectionSnapshot, sectionId, onSectionDirtyChange, mode, isDraft]);
4094
4194
  // Handle cancel button click
4095
4195
  const handleCancel = () => {
4096
- // Revert values in store to original schema data
4097
- // Use original section (without namespace) for collecting widgets
4098
- const sectionWidgets = collectWidgets(originalSection.panels);
4099
- const oldSchemaData = schemaData || contextSchemaData;
4100
- const currentStoreValues = store.getState().widget.values;
4101
- let newStoreValues = currentStoreValues;
4102
- sectionWidgets.forEach(widget => {
4103
- const originalWidgetId = widget['widget-id'];
4104
- // If namespace was used, we need to use namespaced widget ID and data path
4105
- const namespacedWidgetId = namespace ? `${namespace}__${originalWidgetId}` : originalWidgetId;
4106
- const widgetId = namespacedWidgetId;
4107
- const originalDataPath = widget['widget-data-path'];
4108
- // If namespace was used, data path in store is namespaced, but we read from original schema using original path
4109
- const storeDataPath = namespace && originalDataPath
4110
- ? (typeof originalDataPath === 'string'
4111
- ? `${namespace}.${originalDataPath}`
4112
- : Object.fromEntries(Object.entries(originalDataPath).map(([key, path]) => [key, `${namespace}.${path}`])))
4113
- : originalDataPath;
4114
- if (widgetId && originalDataPath) {
4115
- // Handle multi-path (object) or single path (string)
4116
- // Read from original schema data using original paths
4117
- let oldValue;
4118
- if (typeof originalDataPath === 'object') {
4119
- // Multi-path: get values for each path
4120
- oldValue = {};
4121
- Object.entries(originalDataPath).forEach(([key, path]) => {
4122
- if (typeof path === 'string') {
4123
- oldValue[key] = getValueByPath(oldSchemaData, path);
4124
- }
4125
- });
4126
- }
4127
- else if (typeof originalDataPath === 'string') {
4128
- oldValue = getValueByPath(oldSchemaData, originalDataPath);
4129
- }
4130
- // Set in store using namespaced data path (if namespace was used)
4131
- if (oldValue !== undefined) {
4132
- newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
4133
- }
4134
- }
4135
- });
4136
- // Also revert supporting documents if any
4137
- if (hasSupportingDocuments) {
4138
- // Use original section's supporting documents to get original data paths
4139
- const originalSupportingDocuments = originalSection['section-supporting-documents'] || [];
4140
- originalSupportingDocuments.forEach((doc, index) => {
4141
- const widgetId = `supporting-doc-${sectionId}-${index}`;
4142
- const originalDataPath = doc['document-data-path'];
4143
- // If namespace was used, data path in store is namespaced
4144
- const storeDataPath = namespace && originalDataPath
4145
- ? `${namespace}.${originalDataPath}`
4146
- : originalDataPath;
4147
- const oldValue = getValueByPath(oldSchemaData, originalDataPath);
4148
- newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
4149
- });
4150
- }
4151
- if (newStoreValues !== currentStoreValues) {
4152
- dispatch(setValues(newStoreValues));
4153
- }
4196
+ revertToOriginalValues();
4154
4197
  setIsEditMode(false);
4155
4198
  onEditModeChange?.(originalSectionId, false);
4156
4199
  };
@@ -4201,20 +4244,27 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4201
4244
  white-space: nowrap !important;
4202
4245
  }
4203
4246
  /* Readonly: prevent flex row from overflowing panel */
4204
- .${sectionClassId} .TextDisplayWidget {
4247
+ ${readonlyValueRowRootsCss} {
4205
4248
  min-width: 0 !important;
4206
4249
  overflow: hidden !important;
4207
4250
  }
4208
- .${sectionClassId} .TextDisplayWidget > .flex-1 {
4251
+ ${readonlyValueRowFlex1Css} {
4209
4252
  min-width: 0 !important;
4210
4253
  overflow: hidden !important;
4211
4254
  }
4212
- /* Readonly value text truncation */
4213
- .${sectionClassId} .TextDisplayWidget > .flex-1 > .text-gray-900 {
4255
+ /* Readonly value: single-line ellipsis; full value via title on the value node */
4256
+ ${readonlySingleLineValueTextCss} {
4214
4257
  overflow: hidden;
4215
4258
  text-overflow: ellipsis;
4216
4259
  white-space: nowrap;
4217
4260
  }
4261
+ /* Readonly textarea: break unbroken long tokens; title on pre keeps full text on hover */
4262
+ .${sectionClassId} .TextAreaDisplayWidget > .flex-1 > pre {
4263
+ min-width: 0;
4264
+ max-width: 100%;
4265
+ overflow-wrap: anywhere;
4266
+ word-break: break-word;
4267
+ }
4218
4268
 
4219
4269
  /* Only apply fixed height when in edit mode */
4220
4270
  .${sectionClassId}[data-edit-mode="true"] {
@@ -4716,6 +4766,9 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
4716
4766
  }, []);
4717
4767
  const safeSections = sections ?? [];
4718
4768
  const prevSectionsLengthRef = useRef(safeSections.length);
4769
+ // Stable ref for namespace so formHandle useMemo doesn't depend on the (possibly inline) function identity
4770
+ const namespaceRef = useRef(namespace);
4771
+ namespaceRef.current = namespace;
4719
4772
  // Track dirty (unsaved changes) per section for form handle validation
4720
4773
  const sectionDirtyMapRef = useRef({});
4721
4774
  const handleSectionDirtyChange = useCallback((sectionId, isDirty) => {
@@ -4761,11 +4814,14 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
4761
4814
  // Form handle for onFormReady - allows host to validate and get all section data from its own Submit button
4762
4815
  const formHandle = useMemo(() => {
4763
4816
  const getValues = () => store.getState().widget?.values || {};
4764
- const getNamespace = (section, index) => namespace
4765
- ? typeof namespace === 'string'
4766
- ? namespace
4767
- : namespace(section['section-id'], index)
4768
- : undefined;
4817
+ const getNamespace = (section, index) => {
4818
+ const ns = namespaceRef.current;
4819
+ return ns
4820
+ ? typeof ns === 'string'
4821
+ ? ns
4822
+ : ns(section['section-id'], index)
4823
+ : undefined;
4824
+ };
4769
4825
  const checkNoUnsavedChanges = () => {
4770
4826
  const hasDirty = Object.values(sectionDirtyMapRef.current).some(Boolean);
4771
4827
  if (hasDirty) {
@@ -4815,7 +4871,7 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
4815
4871
  return results;
4816
4872
  },
4817
4873
  };
4818
- }, [store, dispatch, safeSections, namespace]);
4874
+ }, [store, dispatch, safeSections]);
4819
4875
  // Call onFormReady when form is ready (sections loaded)
4820
4876
  useEffect(() => {
4821
4877
  if (onFormReady && safeSections.length > 0) {
@@ -8098,10 +8154,10 @@ const DisplayWidget = ({ config }) => {
8098
8154
  const label = translateConfig(widgetConfig['widget-label']);
8099
8155
  // If no label, render as paragraph text
8100
8156
  if (!label || label.trim() === '') {
8101
- return (jsxRuntimeExports.jsx("div", { className: "mb-3 text-base text-gray-700", title: String(displayValue ?? ''), children: displayValue }));
8157
+ return (jsxRuntimeExports.jsx("div", { className: "DisplayFieldWidget mb-3 min-w-0 w-full overflow-hidden text-ellipsis whitespace-nowrap text-base text-gray-700", title: String(displayValue ?? ''), children: displayValue }));
8102
8158
  }
8103
- // With label, render as key-value pair
8104
- return (jsxRuntimeExports.jsxs("div", { className: "mb-[10px] flex flex-col sm:flex-row sm:items-start", children: [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 text-base text-gray-900 font-medium", title: String(displayValue ?? ''), children: displayValue })] }));
8159
+ // With label, render as key-value pair (structure matches other readonly widgets for SectionRenderer ellipsis)
8160
+ return (jsxRuntimeExports.jsxs("div", { className: "mb-[10px] DisplayFieldWidget flex flex-col sm:flex-row sm:items-start", children: [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 min-w-0", children: jsxRuntimeExports.jsx("div", { className: "text-base text-gray-900 font-medium", title: String(displayValue ?? ''), children: displayValue }) })] }));
8105
8161
  };
8106
8162
 
8107
8163
  const TableCellSelect = ({ config, value, onValueChange }) => {
@@ -9069,7 +9125,18 @@ const HeaderSectionWidget = ({ config }) => {
9069
9125
  result = searchIn(schemaData);
9070
9126
  return result;
9071
9127
  }, [paths, values, schemaData]);
9072
- const imageUrl = findValue('image') || null;
9128
+ const imageVal = findValue('image');
9129
+ const imageUrlVal = findValue('imageUrl');
9130
+ const [previewUrl, setPreviewUrl] = useState(null);
9131
+ useEffect(() => {
9132
+ if (imageVal instanceof File) {
9133
+ const url = URL.createObjectURL(imageVal);
9134
+ setPreviewUrl(url);
9135
+ return () => URL.revokeObjectURL(url);
9136
+ }
9137
+ setPreviewUrl(null);
9138
+ }, [imageVal]);
9139
+ const displayImageUrl = previewUrl || (typeof imageUrlVal === 'string' && imageUrlVal ? imageUrlVal : null);
9073
9140
  const displayName = findValue('name') || '';
9074
9141
  const functionalId = findValue('functionalId') || '';
9075
9142
  const statusValue = findValue('status') || '';
@@ -9102,18 +9169,20 @@ const HeaderSectionWidget = ({ config }) => {
9102
9169
  return opt ? opt.label : String(statusValue);
9103
9170
  }, [statusValue, statusOptions]);
9104
9171
  const statusColor = statusColors[String(statusValue).toLowerCase()] || '#6B7280';
9172
+ // ── Image edit helpers ───────────────────────────────────────
9173
+ const fileInputRef = useRef(null);
9174
+ const handleImageUpload = useCallback((e) => {
9175
+ const file = e.target.files?.[0];
9176
+ if (!file)
9177
+ return;
9178
+ updateFieldValue('image', file);
9179
+ e.target.value = '';
9180
+ }, [updateFieldValue]);
9181
+ const handleImageDelete = useCallback(() => {
9182
+ updateFieldValue('image', '');
9183
+ }, [updateFieldValue]);
9105
9184
  // ── Scoped class for CSS isolation ────────────────────────────
9106
9185
  const cls = `header-section-widget-${widgetConfig['widget-id']}`;
9107
- // ── Indicator dot component ───────────────────────────────────
9108
- const Dot = ({ color }) => (jsxRuntimeExports.jsx("span", { style: {
9109
- display: 'inline-block',
9110
- width: 8,
9111
- height: 8,
9112
- borderRadius: '50%',
9113
- backgroundColor: color,
9114
- flexShrink: 0,
9115
- marginTop: 6,
9116
- } }));
9117
9186
  // ── RENDER ────────────────────────────────────────────────────
9118
9187
  return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
9119
9188
  .${cls} {
@@ -9172,6 +9241,56 @@ const HeaderSectionWidget = ({ config }) => {
9172
9241
  border-radius: 8px;
9173
9242
  }
9174
9243
 
9244
+ .${cls} .hdr-avatar-wrapper {
9245
+ position: relative;
9246
+ width: ${imageSize}px;
9247
+ height: ${imageSize}px;
9248
+ flex-shrink: 0;
9249
+ }
9250
+
9251
+ .${cls} .hdr-avatar-overlay {
9252
+ position: absolute;
9253
+ inset: 0;
9254
+ border-radius: 8px;
9255
+ background: rgba(0, 0, 0, 0.55);
9256
+ display: flex;
9257
+ flex-direction: column;
9258
+ align-items: center;
9259
+ justify-content: center;
9260
+ gap: 6px;
9261
+ opacity: 0;
9262
+ transition: opacity 0.2s;
9263
+ }
9264
+
9265
+ .${cls} .hdr-avatar-wrapper:hover .hdr-avatar-overlay {
9266
+ opacity: 1;
9267
+ }
9268
+
9269
+ .${cls} .hdr-avatar-action {
9270
+ display: flex;
9271
+ align-items: center;
9272
+ gap: 5px;
9273
+ padding: 5px 14px;
9274
+ border: none;
9275
+ border-radius: 4px;
9276
+ background: rgba(255, 255, 255, 0.92);
9277
+ color: #374151;
9278
+ font-size: 0.7rem;
9279
+ font-weight: 500;
9280
+ cursor: pointer;
9281
+ font-family: Roboto, sans-serif;
9282
+ transition: background 0.15s;
9283
+ white-space: nowrap;
9284
+ }
9285
+
9286
+ .${cls} .hdr-avatar-action:hover {
9287
+ background: #fff;
9288
+ }
9289
+
9290
+ .${cls} .hdr-avatar-action--delete {
9291
+ color: #DC2626;
9292
+ }
9293
+
9175
9294
  .${cls} .hdr-info {
9176
9295
  display: flex;
9177
9296
  flex-direction: column;
@@ -9276,13 +9395,13 @@ const HeaderSectionWidget = ({ config }) => {
9276
9395
  min-width: 0;
9277
9396
  }
9278
9397
  }
9279
- ` }), jsxRuntimeExports.jsxs("div", { className: cls, children: [jsxRuntimeExports.jsxs("div", { className: "hdr-left", children: [jsxRuntimeExports.jsxs("div", { children: [imageUrl ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: displayName || 'Profile', className: "hdr-avatar", onError: (e) => {
9398
+ ` }), jsxRuntimeExports.jsxs("div", { className: cls, children: [jsxRuntimeExports.jsxs("div", { className: "hdr-left", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-avatar-wrapper", children: [displayImageUrl ? (jsxRuntimeExports.jsx("img", { src: displayImageUrl, alt: displayName || 'Profile', className: "hdr-avatar", onError: (e) => {
9280
9399
  e.target.style.display = 'none';
9281
9400
  const placeholder = e.target
9282
9401
  .parentElement?.querySelector('.hdr-avatar-placeholder');
9283
9402
  if (placeholder)
9284
9403
  placeholder.style.display = 'flex';
9285
- } })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: imageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-info", children: [displayName && jsxRuntimeExports.jsx("div", { className: "hdr-name", children: displayName }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: "#9CA3AF" }), jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('functionalId'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: functionalId || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: isReadonly ? statusColor : '#F59E0B' }), jsxRuntimeExports.jsx("span", { className: "hdr-field-label", children: getLabel('status') }), isReadonly ? (statusLabel ? (jsxRuntimeExports.jsx("span", { className: "hdr-status-badge", style: { backgroundColor: statusColor }, children: statusLabel })) : (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: "-" }))) : (jsxRuntimeExports.jsxs("select", { className: "hdr-select", value: statusValue, onChange: (e) => updateFieldValue('status', e.target.value), children: [jsxRuntimeExports.jsx("option", { value: "", children: getLabel('select') }), statusOptions.map((opt) => (jsxRuntimeExports.jsx("option", { value: opt.value, children: opt.label }, opt.value)))] }))] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: isReadonly ? '#9CA3AF' : '#F59E0B' }), jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('statusReason'), " :"] }), isReadonly ? (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: statusReason || '-' })) : (jsxRuntimeExports.jsx("input", { type: "text", className: "hdr-input", value: statusReason, placeholder: getLabel('enterReason'), onChange: (e) => updateFieldValue('statusReason', e.target.value) }))] })] })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-right", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdAt || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedAt || '-' })] })] })] })] }));
9404
+ } })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: displayImageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) }), !isReadonly && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "hdr-avatar-overlay", children: [jsxRuntimeExports.jsxs("button", { type: "button", className: "hdr-avatar-action", onClick: () => fileInputRef.current?.click(), children: [jsxRuntimeExports.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), jsxRuntimeExports.jsx("polyline", { points: "17 8 12 3 7 8" }), jsxRuntimeExports.jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })] }), "Upload"] }), jsxRuntimeExports.jsxs("button", { type: "button", className: "hdr-avatar-action hdr-avatar-action--delete", onClick: handleImageDelete, children: [jsxRuntimeExports.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("polyline", { points: "3 6 5 6 21 6" }), jsxRuntimeExports.jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })] }), "Delete"] })] }), jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: 'none' }, onChange: handleImageUpload })] }))] }), jsxRuntimeExports.jsxs("div", { className: "hdr-info", children: [displayName && jsxRuntimeExports.jsx("div", { className: "hdr-name", children: displayName }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('functionalId'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: functionalId || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx("span", { className: "hdr-field-label", children: getLabel('status') }), isReadonly ? (statusLabel ? (jsxRuntimeExports.jsx("span", { className: "hdr-status-badge", style: { backgroundColor: statusColor }, children: statusLabel })) : (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: "-" }))) : (jsxRuntimeExports.jsxs("select", { className: "hdr-select", value: statusValue, onChange: (e) => updateFieldValue('status', e.target.value), children: [jsxRuntimeExports.jsx("option", { value: "", children: getLabel('select') }), statusOptions.map((opt) => (jsxRuntimeExports.jsx("option", { value: opt.value, children: opt.label }, opt.value)))] }))] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('statusReason'), " :"] }), isReadonly ? (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: statusReason || '-' })) : (jsxRuntimeExports.jsx("input", { type: "text", className: "hdr-input", value: statusReason, placeholder: getLabel('enterReason'), onChange: (e) => updateFieldValue('statusReason', e.target.value) }))] })] })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-right", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdAt || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedAt || '-' })] })] })] })] }));
9286
9405
  };
9287
9406
 
9288
9407
  /**