@openg2p/registry-widgets 1.1.0-dev.11 → 1.1.0-dev.13

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/index.js CHANGED
@@ -1078,16 +1078,12 @@ const getApiDataSource = async (dataSource, allValues, dataSourceRequestHandler,
1078
1078
  console.error('[getApiDataSource] API data source missing endpoint. Use "endpoint" field to specify the operation (e.g., "get_g2p_geo_level_values")');
1079
1079
  return [];
1080
1080
  }
1081
- let response;
1082
- try {
1083
- response = await dataSourceRequestHandler(service, endpoint, method, requestParams, {
1084
- headers: dataSource.headers,
1085
- });
1086
- }
1087
- catch (error) {
1088
- console.error('[getApiDataSource] Handler error:', error);
1089
- throw error;
1090
- }
1081
+ // Call handler — let any throw propagate to the outer catch so it is logged once
1082
+ // by useBaseWidget rather than double-logged here (which can cascade when
1083
+ // intercept-console-error.js converts console.error calls into thrown errors).
1084
+ const response = await dataSourceRequestHandler(service, endpoint, method, requestParams, {
1085
+ headers: dataSource.headers,
1086
+ });
1091
1087
  // Handle OpenG2P response format (response_body.response_payload)
1092
1088
  if (response && typeof response === 'object') {
1093
1089
  if (response.response_body?.response_payload && Array.isArray(response.response_body.response_payload)) {
@@ -1110,8 +1106,8 @@ const getApiDataSource = async (dataSource, allValues, dataSourceRequestHandler,
1110
1106
  return [];
1111
1107
  }
1112
1108
  catch (error) {
1113
- console.error('Error fetching API data source:', error);
1114
- return [];
1109
+ // Rethrow so useBaseWidget's catch can log it with full widget context
1110
+ throw error;
1115
1111
  }
1116
1112
  };
1117
1113
  /**
@@ -2305,7 +2301,7 @@ const useBaseWidget = (options) => {
2305
2301
  dispatch(setDataSource({ widgetId, data: transformed }));
2306
2302
  }
2307
2303
  catch (error) {
2308
- console.error(`[useBaseWidget] ERROR loading data source for ${widgetId}:`, error);
2304
+ console.error(`[useBaseWidget] ERROR loading data source for widget "${widgetId}" (type="${dataSource.type}"):`, error, '\nWidget config:', config, '\ndataSourceRequestHandler provided:', Boolean(dataSourceRequestHandler));
2309
2305
  dispatch(setDataSource({ widgetId, data: [] }));
2310
2306
  }
2311
2307
  finally {
@@ -3798,6 +3794,116 @@ const namespaceSectionConfig = (section, namespace) => {
3798
3794
  return namespaced;
3799
3795
  };
3800
3796
 
3797
+ /** Table-style widgets that bind to an array path in the store / schema. */
3798
+ function isTableLikeWidget(widget) {
3799
+ const w = widget.widget;
3800
+ /** widget-type union in types omits legacy values like simple-table still used at runtime */
3801
+ const t = widget['widget-type'];
3802
+ return (w === 'table' ||
3803
+ w === 'dialog-table' ||
3804
+ w === 'simple-table' ||
3805
+ t === 'table' ||
3806
+ t === 'simple-table');
3807
+ }
3808
+ /**
3809
+ * Resolve `records` for section save payloads.
3810
+ * - Back-compat: path ending in `.records` (e.g. `regId.records`)
3811
+ * - Else: first array snapshot at a string `widget-data-path` on a table-like widget
3812
+ * (e.g. `household.members` for dialog-table)
3813
+ */
3814
+ function extractTableRecordsFromSnapshot(snapshot, sectionWidgets) {
3815
+ const convention = Object.entries(snapshot).find(([key, value]) => key.endsWith('.records') && Array.isArray(value));
3816
+ if (convention) {
3817
+ return convention[1];
3818
+ }
3819
+ const tablePaths = [];
3820
+ sectionWidgets.forEach((widget) => {
3821
+ if (!isTableLikeWidget(widget))
3822
+ return;
3823
+ const p = widget['widget-data-path'];
3824
+ if (typeof p === 'string' && p.length > 0) {
3825
+ tablePaths.push(p);
3826
+ }
3827
+ else if (p && typeof p === 'object') {
3828
+ Object.values(p).forEach((sub) => {
3829
+ if (typeof sub === 'string' && sub.length > 0)
3830
+ tablePaths.push(sub);
3831
+ });
3832
+ }
3833
+ });
3834
+ for (const path of tablePaths) {
3835
+ const val = snapshot[path];
3836
+ if (Array.isArray(val)) {
3837
+ return val;
3838
+ }
3839
+ }
3840
+ return [];
3841
+ }
3842
+
3843
+ const isColumnRequired = (column, skipRequired) => {
3844
+ if (skipRequired)
3845
+ return false;
3846
+ const validation = column['widget-data-validation'];
3847
+ return !!(column['widget-required'] || validation?.required);
3848
+ };
3849
+ const validateTableLikeWidget = (widget, currentSchemaData, dispatch, skipRequired) => {
3850
+ const widgetId = widget['widget-id'];
3851
+ if (!widgetId)
3852
+ return true;
3853
+ const columns = (widget['widget-data-columns'] || []);
3854
+ const value = getWidgetValue(currentSchemaData, widget['widget-data-path'], widgetId);
3855
+ const rows = Array.isArray(value)
3856
+ ? value
3857
+ : [];
3858
+ const activeRows = rows.filter((row) => row?.edit_action !== 'DELETE');
3859
+ const rowErrors = [];
3860
+ let isValid = true;
3861
+ if (!skipRequired && widget['widget-required'] && activeRows.length === 0) {
3862
+ dispatch(setTouched({ widgetId, touched: true }));
3863
+ dispatch(setError({ widgetId, errors: ['At least one record is required'] }));
3864
+ return false;
3865
+ }
3866
+ const hasRequiredColumns = columns.some((col) => isColumnRequired(col, skipRequired));
3867
+ if (!skipRequired && hasRequiredColumns && activeRows.length === 0) {
3868
+ dispatch(setTouched({ widgetId, touched: true }));
3869
+ dispatch(setError({
3870
+ widgetId,
3871
+ errors: ['Add at least one record and fill all required fields'],
3872
+ }));
3873
+ return false;
3874
+ }
3875
+ activeRows.forEach((row, rowIndex) => {
3876
+ columns.forEach((col) => {
3877
+ if (col['widget-readonly'])
3878
+ return;
3879
+ const key = col['column-key'];
3880
+ if (!key)
3881
+ return;
3882
+ const required = isColumnRequired(col, skipRequired);
3883
+ const cellValue = row[key];
3884
+ const errors = validateWidget(cellValue, col['widget-data-validation'], required, skipRequired);
3885
+ if (errors.length > 0) {
3886
+ isValid = false;
3887
+ const label = col['widget-label'] || key;
3888
+ rowErrors.push(`Row ${rowIndex + 1}, ${label}: ${errors[0]}`);
3889
+ }
3890
+ });
3891
+ });
3892
+ if (!isValid) {
3893
+ dispatch(setTouched({ widgetId, touched: true }));
3894
+ dispatch(setError({
3895
+ widgetId,
3896
+ errors: rowErrors.length > 0
3897
+ ? rowErrors.slice(0, 5)
3898
+ : ['Please fix required fields in the table'],
3899
+ }));
3900
+ }
3901
+ else {
3902
+ dispatch(setTouched({ widgetId, touched: false }));
3903
+ dispatch(setError({ widgetId, errors: [] }));
3904
+ }
3905
+ return isValid;
3906
+ };
3801
3907
  const collectWidgets = (panels) => {
3802
3908
  let widgets = [];
3803
3909
  panels.forEach((panel) => {
@@ -3826,6 +3932,13 @@ const sectionValidate = (section, currentSchemaData, dispatch, skipRequired = fa
3826
3932
  if (!isVisible)
3827
3933
  continue;
3828
3934
  const widgetId = widget['widget-id'];
3935
+ if (isTableLikeWidget(widget)) {
3936
+ const tableValid = validateTableLikeWidget(widget, currentSchemaData, dispatch, skipRequired);
3937
+ if (!tableValid) {
3938
+ isValid = false;
3939
+ }
3940
+ continue;
3941
+ }
3829
3942
  const value = getWidgetValue(currentSchemaData, widget['widget-data-path'], widgetId);
3830
3943
  const errors = validateWidget(value, widget['widget-data-validation'], widget['widget-required'], skipRequired);
3831
3944
  if (errors.length > 0) {
@@ -3860,52 +3973,6 @@ const sectionValidate = (section, currentSchemaData, dispatch, skipRequired = fa
3860
3973
  return isValid;
3861
3974
  };
3862
3975
 
3863
- /** Table-style widgets that bind to an array path in the store / schema. */
3864
- function isTableLikeWidget(widget) {
3865
- const w = widget.widget;
3866
- /** widget-type union in types omits legacy values like simple-table still used at runtime */
3867
- const t = widget['widget-type'];
3868
- return (w === 'table' ||
3869
- w === 'dialog-table' ||
3870
- w === 'simple-table' ||
3871
- t === 'table' ||
3872
- t === 'simple-table');
3873
- }
3874
- /**
3875
- * Resolve `records` for section save payloads.
3876
- * - Back-compat: path ending in `.records` (e.g. `regId.records`)
3877
- * - Else: first array snapshot at a string `widget-data-path` on a table-like widget
3878
- * (e.g. `household.members` for dialog-table)
3879
- */
3880
- function extractTableRecordsFromSnapshot(snapshot, sectionWidgets) {
3881
- const convention = Object.entries(snapshot).find(([key, value]) => key.endsWith('.records') && Array.isArray(value));
3882
- if (convention) {
3883
- return convention[1];
3884
- }
3885
- const tablePaths = [];
3886
- sectionWidgets.forEach((widget) => {
3887
- if (!isTableLikeWidget(widget))
3888
- return;
3889
- const p = widget['widget-data-path'];
3890
- if (typeof p === 'string' && p.length > 0) {
3891
- tablePaths.push(p);
3892
- }
3893
- else if (p && typeof p === 'object') {
3894
- Object.values(p).forEach((sub) => {
3895
- if (typeof sub === 'string' && sub.length > 0)
3896
- tablePaths.push(sub);
3897
- });
3898
- }
3899
- });
3900
- for (const path of tablePaths) {
3901
- const val = snapshot[path];
3902
- if (Array.isArray(val)) {
3903
- return val;
3904
- }
3905
- }
3906
- return [];
3907
- }
3908
-
3909
3976
  /** Root class on readonly label/value rows; SectionRenderer scopes overflow/ellipsis rules here. */
3910
3977
  const READONLY_VALUE_ROW_ROOT_CLASSES = [
3911
3978
  'TextDisplayWidget',
@@ -7391,7 +7458,7 @@ const NumberInputWidget = ({ config }) => {
7391
7458
  if (parsed === null) {
7392
7459
  // Allow empty input or partial input (e.g., "-", ".")
7393
7460
  if (inputValue === '' || inputValue === '-' || inputValue === '.') {
7394
- onChange('');
7461
+ onChange(null);
7395
7462
  }
7396
7463
  // Don't update if invalid - let user continue typing
7397
7464
  return;
@@ -7515,6 +7582,8 @@ const BooleanWidget = ({ config }) => {
7515
7582
  return labels[representation];
7516
7583
  }, [representation, formatConfig, translateConfig]);
7517
7584
  const { trueLabel, falseLabel } = getLabels();
7585
+ const unsetLabel = React.useMemo(() => translateConfig(formatConfig?.booleanUnsetLabel || 'Not set'), [formatConfig?.booleanUnsetLabel, translateConfig]);
7586
+ const radioGroupName = `${widgetConfig['widget-id'] ?? 'boolean'}__${React.useId().replace(/:/g, '')}`;
7518
7587
  // Determine current value (handle null/undefined)
7519
7588
  const currentValue = React.useMemo(() => {
7520
7589
  if (value === null || value === undefined) {
@@ -7546,7 +7615,7 @@ const BooleanWidget = ({ config }) => {
7546
7615
  const label = translateConfig(widgetConfig['widget-label']);
7547
7616
  let displayValue = '';
7548
7617
  if (currentValue === null) {
7549
- displayValue = '-';
7618
+ displayValue = '';
7550
7619
  }
7551
7620
  else if (currentValue === true) {
7552
7621
  displayValue = trueLabel;
@@ -7558,18 +7627,20 @@ const BooleanWidget = ({ config }) => {
7558
7627
  }
7559
7628
  // Render based on control type
7560
7629
  if (controlType === 'checkbox') {
7561
- return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-start", children: [jsxRuntimeExports.jsxs("label", { className: "text-base font-medium text-gray-700 md:min-w-[120px] sm:pr-4 sm:pt-1 mb-1 sm:mb-0", style: { fontFamily: 'Roboto, sans-serif' }, title: translateConfig(widgetConfig['widget-label']), children: [translateConfig(widgetConfig['widget-label']), widgetConfig['widget-required'] && (jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsxs("label", { className: "flex items-center cursor-pointer", children: [jsxRuntimeExports.jsx("input", { type: "checkbox", checked: currentValue === true, onChange: handleCheckboxChange, onBlur: onBlur, disabled: !isEnabled || widgetConfig['widget-readonly'], className: "mr-2 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" }), jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-700", children: currentValue === true ? trueLabel : (currentValue === false ? falseLabel : '-') })] }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: error[0] }))] })] }) }));
7630
+ return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-baseline", children: [jsxRuntimeExports.jsxs("label", { className: "text-base font-medium leading-normal text-gray-700 md:min-w-[120px] sm:pr-4 mb-1 sm:mb-0 sm:pt-0.5", style: { fontFamily: 'Roboto, sans-serif' }, title: translateConfig(widgetConfig['widget-label']), children: [translateConfig(widgetConfig['widget-label']), widgetConfig['widget-required'] && (jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsxs("label", { className: "inline-flex items-baseline cursor-pointer gap-2", children: [jsxRuntimeExports.jsx("input", { type: "checkbox", checked: currentValue === true, onChange: handleCheckboxChange, onBlur: onBlur, disabled: !isEnabled || widgetConfig['widget-readonly'], className: "relative top-[0.2em] h-4 w-4 shrink-0 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" }), (currentValue === true || currentValue === false) && (jsxRuntimeExports.jsx("span", { className: "text-base text-gray-700 leading-normal", children: currentValue === true ? trueLabel : falseLabel }))] }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: error[0] }))] })] }) }));
7562
7631
  }
7563
7632
  if (controlType === 'radio') {
7564
7633
  const containerClass = orientation === 'horizontal'
7565
- ? 'flex flex-row space-x-4'
7566
- : 'flex flex-col space-y-2';
7567
- return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-start", children: [jsxRuntimeExports.jsxs("label", { className: "text-base font-medium text-gray-700 md:min-w-[120px] sm:pr-4 sm:pt-1 mb-1 sm:mb-0", style: { fontFamily: 'Roboto, sans-serif' }, title: translateConfig(widgetConfig['widget-label']), children: [translateConfig(widgetConfig['widget-label']), widgetConfig['widget-required'] && (jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsxs("div", { className: containerClass, onBlur: onBlur, children: [allowUnset && (jsxRuntimeExports.jsxs("label", { className: `flex items-center cursor-pointer ${!isEnabled || widgetConfig['widget-readonly'] ? 'opacity-50 cursor-not-allowed' : ''}`, children: [jsxRuntimeExports.jsx("input", { type: "radio", name: widgetConfig['widget-id'], checked: currentValue === null, onChange: () => handleRadioChange(null), disabled: !isEnabled || widgetConfig['widget-readonly'], className: "mr-2 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300" }), jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-700", children: "-" })] })), jsxRuntimeExports.jsxs("label", { className: `flex items-center cursor-pointer ${!isEnabled || widgetConfig['widget-readonly'] ? 'opacity-50 cursor-not-allowed' : ''}`, children: [jsxRuntimeExports.jsx("input", { type: "radio", name: widgetConfig['widget-id'], checked: currentValue === true, onChange: () => handleRadioChange(true), disabled: !isEnabled || widgetConfig['widget-readonly'], className: "mr-2 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300" }), jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-700", children: trueLabel })] }), jsxRuntimeExports.jsxs("label", { className: `flex items-center cursor-pointer ${!isEnabled || widgetConfig['widget-readonly'] ? 'opacity-50 cursor-not-allowed' : ''}`, children: [jsxRuntimeExports.jsx("input", { type: "radio", name: widgetConfig['widget-id'], checked: currentValue === false, onChange: () => handleRadioChange(false), disabled: !isEnabled || widgetConfig['widget-readonly'], className: "mr-2 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300" }), jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-700", children: falseLabel })] })] }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: error[0] }))] })] }) }));
7634
+ ? 'flex flex-row flex-wrap items-baseline gap-x-4 gap-y-2'
7635
+ : 'flex flex-col items-start gap-2';
7636
+ const radioDisabled = !isEnabled || widgetConfig['widget-readonly'];
7637
+ const optionDisabledClass = radioDisabled ? 'opacity-50 cursor-not-allowed' : '';
7638
+ return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-baseline", children: [jsxRuntimeExports.jsxs("label", { className: "text-base font-medium leading-normal text-gray-700 md:min-w-[120px] sm:pr-4 mb-1 sm:mb-0 sm:pt-0.5", style: { fontFamily: 'Roboto, sans-serif' }, title: translateConfig(widgetConfig['widget-label']), children: [translateConfig(widgetConfig['widget-label']), widgetConfig['widget-required'] && (jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsxs("div", { className: containerClass, onBlur: onBlur, children: [allowUnset && (jsxRuntimeExports.jsxs("label", { className: `inline-flex items-baseline gap-2 cursor-pointer ${optionDisabledClass}`, children: [jsxRuntimeExports.jsx("input", { type: "radio", name: radioGroupName, checked: currentValue === null, onChange: () => handleRadioChange(null), disabled: radioDisabled, className: "relative top-[0.2em] h-4 w-4 shrink-0 text-blue-600 focus:ring-blue-500 border-gray-300" }), jsxRuntimeExports.jsx("span", { className: "text-base text-gray-700 leading-normal", children: unsetLabel })] })), jsxRuntimeExports.jsxs("label", { className: `inline-flex items-baseline gap-2 cursor-pointer ${optionDisabledClass}`, children: [jsxRuntimeExports.jsx("input", { type: "radio", name: radioGroupName, checked: currentValue === true, onChange: () => handleRadioChange(true), disabled: radioDisabled, className: "relative top-[0.2em] h-4 w-4 shrink-0 text-blue-600 focus:ring-blue-500 border-gray-300" }), jsxRuntimeExports.jsx("span", { className: "text-base text-gray-700 leading-normal", children: trueLabel })] }), jsxRuntimeExports.jsxs("label", { className: `inline-flex items-baseline gap-2 cursor-pointer ${optionDisabledClass}`, children: [jsxRuntimeExports.jsx("input", { type: "radio", name: radioGroupName, checked: currentValue === false, onChange: () => handleRadioChange(false), disabled: radioDisabled, className: "relative top-[0.2em] h-4 w-4 shrink-0 text-blue-600 focus:ring-blue-500 border-gray-300" }), jsxRuntimeExports.jsx("span", { className: "text-base text-gray-700 leading-normal", children: falseLabel })] })] }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: error[0] }))] })] }) }));
7568
7639
  }
7569
7640
  // Toggle/switch control type
7570
- return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-start", children: [jsxRuntimeExports.jsxs("label", { className: "text-base font-medium text-gray-700 sm:min-w-[150px] sm:pr-4 sm:pt-1 mb-1 sm:mb-0", style: { fontFamily: 'Roboto, sans-serif' }, title: translateConfig(widgetConfig['widget-label']), children: [translateConfig(widgetConfig['widget-label']), widgetConfig['widget-required'] && (jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-3", onBlur: onBlur, children: [allowUnset && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => handleChange(null), disabled: !isEnabled || widgetConfig['widget-readonly'], className: `px-3 py-1 text-sm border ${currentValue === null
7641
+ return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-baseline", children: [jsxRuntimeExports.jsxs("label", { className: "text-base font-medium leading-normal text-gray-700 sm:min-w-[150px] sm:pr-4 mb-1 sm:mb-0 sm:pt-0.5", style: { fontFamily: 'Roboto, sans-serif' }, title: translateConfig(widgetConfig['widget-label']), children: [translateConfig(widgetConfig['widget-label']), widgetConfig['widget-required'] && (jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-3", onBlur: onBlur, children: [allowUnset && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => handleChange(null), disabled: !isEnabled || widgetConfig['widget-readonly'], className: `px-3 py-1 text-sm border ${currentValue === null
7571
7642
  ? 'bg-blue-600 text-white border-blue-600'
7572
- : 'bg-white text-gray-700 border-gray-300'} ${!isEnabled || widgetConfig['widget-readonly'] ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50'}`, style: { borderRadius: '15px' }, children: "-" })), jsxRuntimeExports.jsx("button", { type: "button", onClick: () => handleChange(true), disabled: !isEnabled || widgetConfig['widget-readonly'], className: `px-3 py-1 text-sm border ${currentValue === true
7643
+ : 'bg-white text-gray-700 border-gray-300'} ${!isEnabled || widgetConfig['widget-readonly'] ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50'}`, style: { borderRadius: '15px' }, children: unsetLabel })), jsxRuntimeExports.jsx("button", { type: "button", onClick: () => handleChange(true), disabled: !isEnabled || widgetConfig['widget-readonly'], className: `px-3 py-1 text-sm border ${currentValue === true
7573
7644
  ? 'bg-blue-600 text-white border-blue-600'
7574
7645
  : 'bg-white text-gray-700 border-gray-300'} ${!isEnabled || widgetConfig['widget-readonly'] ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50'}`, style: { borderRadius: '15px' }, children: trueLabel }), jsxRuntimeExports.jsx("button", { type: "button", onClick: () => handleChange(false), disabled: !isEnabled || widgetConfig['widget-readonly'], className: `px-3 py-1 text-sm border ${currentValue === false
7575
7646
  ? 'bg-blue-600 text-white border-blue-600'
@@ -8280,7 +8351,7 @@ const CheckboxWidget = ({ config }) => {
8280
8351
  const displayValue = isChecked ? 'Yes' : 'No';
8281
8352
  return (jsxRuntimeExports.jsxs("div", { className: "mb-[10px] CheckboxDisplayWidget 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", { className: "text-base text-gray-900 font-medium", title: String(displayValue ?? ''), children: displayValue }) })] }));
8282
8353
  }
8283
- return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-start", children: [jsxRuntimeExports.jsxs("label", { className: "text-base font-medium text-gray-700 md:min-w-[120px] sm:pr-4 sm:pt-1 mb-1 sm:mb-0", style: { fontFamily: 'Roboto, sans-serif' }, title: translateConfig(widgetConfig['widget-label']), children: [translateConfig(widgetConfig['widget-label']), widgetConfig['widget-required'] && (jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsxs("label", { className: "flex items-center cursor-pointer", children: [jsxRuntimeExports.jsx("input", { type: "checkbox", checked: isChecked, onChange: (e) => onChange(e.target.checked), onBlur: onBlur, disabled: !isEnabled || widgetConfig['widget-readonly'], className: "mr-2 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" }), jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-700", children: isChecked ? 'Yes' : 'No' })] }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: error[0] }))] })] }) }));
8354
+ return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-baseline", children: [jsxRuntimeExports.jsxs("label", { className: "text-base font-medium leading-normal text-gray-700 md:min-w-[120px] sm:pr-4 mb-1 sm:mb-0 sm:pt-0.5", style: { fontFamily: 'Roboto, sans-serif' }, title: translateConfig(widgetConfig['widget-label']), children: [translateConfig(widgetConfig['widget-label']), widgetConfig['widget-required'] && (jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsxs("label", { className: "inline-flex cursor-pointer items-baseline gap-2", children: [jsxRuntimeExports.jsx("input", { type: "checkbox", checked: isChecked, onChange: (e) => onChange(e.target.checked), onBlur: onBlur, disabled: !isEnabled || widgetConfig['widget-readonly'], className: "relative top-[0.2em] h-4 w-4 shrink-0 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" }), jsxRuntimeExports.jsx("span", { className: "text-base leading-normal text-gray-700", children: isChecked ? 'Yes' : 'No' })] }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: error[0] }))] })] }) }));
8284
8355
  }
8285
8356
  // Multiple checkboxes (with data source) - for array values
8286
8357
  // Process and sort options if needed
@@ -8323,7 +8394,7 @@ const CheckboxWidget = ({ config }) => {
8323
8394
  switch (layout) {
8324
8395
  case 'horizontal':
8325
8396
  return {
8326
- className: 'flex flex-row flex-wrap gap-4',
8397
+ className: 'flex flex-row flex-wrap items-baseline gap-4',
8327
8398
  style: undefined,
8328
8399
  };
8329
8400
  case 'grid':
@@ -8336,7 +8407,7 @@ const CheckboxWidget = ({ config }) => {
8336
8407
  case 'vertical':
8337
8408
  default:
8338
8409
  return {
8339
- className: 'flex flex-col space-y-2',
8410
+ className: 'flex flex-col gap-2',
8340
8411
  style: undefined,
8341
8412
  };
8342
8413
  }
@@ -8350,7 +8421,7 @@ const CheckboxWidget = ({ config }) => {
8350
8421
  : '-';
8351
8422
  return (jsxRuntimeExports.jsxs("div", { className: "mb-3 CheckboxDisplayWidget flex flex-col sm:flex-row sm:items-start", children: [label && (jsxRuntimeExports.jsxs("div", { className: "text-sm text-gray-600 font-medium md:min-w-[120px] sm:pr-4 mb-1 sm:mb-0", title: label, children: [label, ":"] })), jsxRuntimeExports.jsx("div", { className: "flex-1", children: jsxRuntimeExports.jsx("div", { className: "text-base text-gray-900 font-medium", title: String(displayValue ?? ''), children: displayValue }) })] }));
8352
8423
  }
8353
- return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-start", children: [jsxRuntimeExports.jsxs("label", { className: "text-base font-medium text-gray-700 md:min-w-[120px] sm:pr-4 sm:pt-1 mb-1 sm:mb-0", style: { fontFamily: 'Roboto, sans-serif' }, title: translateConfig(widgetConfig['widget-label']), children: [translateConfig(widgetConfig['widget-label']), widgetConfig['widget-required'] && (jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsx("div", { className: layoutConfig.className, style: layoutConfig.style, onBlur: onBlur, children: loading ? (jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-500", children: translate('common.loading') })) : (processedOptions.map((option) => (jsxRuntimeExports.jsxs("label", { className: `flex items-center cursor-pointer ${!isEnabled || widgetConfig['widget-readonly'] ? 'opacity-50 cursor-not-allowed' : ''}`, children: [jsxRuntimeExports.jsx("input", { type: "checkbox", value: option.value, checked: selectedValues.includes(option.value), onChange: (e) => handleCheckboxChange(option.value, e.target.checked), disabled: !isEnabled || widgetConfig['widget-readonly'], className: "mr-2 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" }), jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-700", children: translateConfig(option.label) })] }, option.value)))) }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: error[0] }))] })] }) }));
8424
+ return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-baseline", children: [jsxRuntimeExports.jsxs("label", { className: "text-base font-medium leading-normal text-gray-700 md:min-w-[120px] sm:pr-4 mb-1 sm:mb-0 sm:pt-0.5", style: { fontFamily: 'Roboto, sans-serif' }, title: translateConfig(widgetConfig['widget-label']), children: [translateConfig(widgetConfig['widget-label']), widgetConfig['widget-required'] && (jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" }))] }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsx("div", { className: layoutConfig.className, style: layoutConfig.style, onBlur: onBlur, children: loading ? (jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-500", children: translate('common.loading') })) : (processedOptions.map((option) => (jsxRuntimeExports.jsxs("label", { className: `inline-flex cursor-pointer items-baseline gap-2 ${!isEnabled || widgetConfig['widget-readonly'] ? 'opacity-50 cursor-not-allowed' : ''}`, children: [jsxRuntimeExports.jsx("input", { type: "checkbox", value: option.value, checked: selectedValues.includes(option.value), onChange: (e) => handleCheckboxChange(option.value, e.target.checked), disabled: !isEnabled || widgetConfig['widget-readonly'], className: "relative top-[0.2em] h-4 w-4 shrink-0 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" }), jsxRuntimeExports.jsx("span", { className: "text-base leading-normal text-gray-700", children: translateConfig(option.label) })] }, option.value)))) }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: error[0] }))] })] }) }));
8354
8425
  };
8355
8426
 
8356
8427
  const SimpleTableWidget = ({ config }) => {
@@ -9389,6 +9460,27 @@ const DialogTableWidget = ({ config }) => {
9389
9460
  }, [formData, columns, storeValues, dialogFieldWidgetId]);
9390
9461
  const saveDialog = React.useCallback(() => {
9391
9462
  const payload = collectMergedRowPayload();
9463
+ let hasErrors = false;
9464
+ columns.forEach((col) => {
9465
+ const key = col['column-key'];
9466
+ const cellWidgetId = dialogFieldWidgetId(key);
9467
+ const isColReadonly = isReadonly || col['widget-readonly'] === true;
9468
+ if (isColReadonly)
9469
+ return;
9470
+ const cellValue = payload[key];
9471
+ const validationErrors = validateWidget(cellValue, col['widget-data-validation'], col['widget-required']);
9472
+ if (validationErrors && validationErrors.length > 0) {
9473
+ hasErrors = true;
9474
+ dispatch(setError({ widgetId: cellWidgetId, errors: validationErrors }));
9475
+ dispatch(setTouched({ widgetId: cellWidgetId, touched: true }));
9476
+ }
9477
+ else {
9478
+ dispatch(setError({ widgetId: cellWidgetId, errors: [] }));
9479
+ }
9480
+ });
9481
+ if (hasErrors) {
9482
+ return;
9483
+ }
9392
9484
  if (dialogMode === 'add') {
9393
9485
  const savedRow = { ...payload, edit_action: 'ADD' };
9394
9486
  onChange([...rows, savedRow]);
@@ -9404,7 +9496,7 @@ const DialogTableWidget = ({ config }) => {
9404
9496
  onChange(newRows);
9405
9497
  closeDialog();
9406
9498
  }
9407
- }, [collectMergedRowPayload, dialogMode, onChange, rows, closeDialog, activeRowIndex]);
9499
+ }, [collectMergedRowPayload, dialogMode, onChange, rows, closeDialog, activeRowIndex, columns, dialogFieldWidgetId, isReadonly, dispatch]);
9408
9500
  const deleteRow = React.useCallback((rowIndex) => {
9409
9501
  const newRows = rows.filter((_, i) => i !== rowIndex);
9410
9502
  onChange(newRows);
@@ -9755,10 +9847,13 @@ const TextAreaWidget = ({ config }) => {
9755
9847
  // For readonly mode, render as preformatted text using <pre> tag
9756
9848
  if (isReadonly) {
9757
9849
  const displayValue = getStringValue() || '-';
9758
- 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("pre", { className: "text-base text-gray-900 font-medium whitespace-pre-wrap", title: String(displayValue), style: {
9850
+ 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: {
9759
9851
  fontFamily: 'Roboto, sans-serif',
9760
- margin: 0,
9761
- padding: 0,
9852
+ height: '56px',
9853
+ minHeight: '56px',
9854
+ maxHeight: '56px',
9855
+ lineHeight: '20px',
9856
+ padding: '8px 0',
9762
9857
  backgroundColor: 'transparent',
9763
9858
  border: 'none',
9764
9859
  }, children: displayValue }) })] }));
@@ -10227,20 +10322,29 @@ const HeaderSectionWidget = ({ config }) => {
10227
10322
  .${cls} .hdr-field-row {
10228
10323
  display: flex;
10229
10324
  align-items: flex-start;
10230
- gap: 0.5rem;
10231
10325
  font-size: 1rem;
10232
10326
  line-height: 1.6;
10233
10327
  }
10234
10328
 
10235
10329
  .${cls} .hdr-field-label {
10330
+ width: 50%;
10331
+ flex: 0 0 50%;
10236
10332
  color: rgba(0, 0, 0, 0.5);
10237
10333
  font-weight: 400;
10238
10334
  white-space: nowrap;
10335
+ overflow: hidden;
10336
+ text-overflow: ellipsis;
10337
+ padding-right: 4px;
10239
10338
  }
10240
10339
 
10241
10340
  .${cls} .hdr-field-value {
10341
+ width: 50%;
10342
+ flex: 0 0 50%;
10242
10343
  color: var(--owt-color-text, #111827);
10243
10344
  font-weight: 500;
10345
+ white-space: nowrap;
10346
+ overflow: hidden;
10347
+ text-overflow: ellipsis;
10244
10348
  }
10245
10349
 
10246
10350
  .${cls} .hdr-status-badge {
@@ -10250,24 +10354,38 @@ const HeaderSectionWidget = ({ config }) => {
10250
10354
  font-size: 0.75rem;
10251
10355
  font-weight: 600;
10252
10356
  color: #fff;
10357
+ max-width: 100%;
10358
+ overflow: hidden;
10359
+ text-overflow: ellipsis;
10360
+ white-space: nowrap;
10253
10361
  }
10254
10362
 
10255
10363
  .${cls} .hdr-meta-row {
10256
10364
  display: flex;
10257
10365
  align-items: baseline;
10258
- gap: 0.35rem;
10259
10366
  font-size: 1rem;
10260
10367
  line-height: 1.6;
10261
10368
  }
10262
10369
 
10263
10370
  .${cls} .hdr-meta-label {
10371
+ width: 50%;
10372
+ flex: 0 0 50%;
10264
10373
  color: rgba(0, 0, 0, 0.5);
10265
10374
  font-weight: 400;
10375
+ white-space: nowrap;
10376
+ overflow: hidden;
10377
+ text-overflow: ellipsis;
10378
+ padding-right: 4px;
10266
10379
  }
10267
10380
 
10268
10381
  .${cls} .hdr-meta-value {
10382
+ width: 50%;
10383
+ flex: 0 0 50%;
10269
10384
  color: var(--owt-color-text, #111827);
10270
10385
  font-weight: 500;
10386
+ white-space: nowrap;
10387
+ overflow: hidden;
10388
+ text-overflow: ellipsis;
10271
10389
  }
10272
10390
 
10273
10391
  .${cls} .hdr-select {
@@ -10331,7 +10449,7 @@ const HeaderSectionWidget = ({ config }) => {
10331
10449
  .parentElement?.querySelector('.hdr-avatar-placeholder');
10332
10450
  if (placeholder)
10333
10451
  placeholder.style.display = 'flex';
10334
- } })) : 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.jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [jsxRuntimeExports.jsx("input", { type: "text", className: `hdr-input ${(!isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing) ? 'hdr-input--error' : ''}`, value: statusReason, placeholder: getLabel('enterReason'), required: isStatusChanged, "aria-required": isStatusChanged, "aria-invalid": !isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing, onBlur: () => {
10452
+ } })) : 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", title: `${getLabel('functionalId')} :`, children: [getLabel('functionalId'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-field-value", title: functionalId || '-', children: functionalId || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx("span", { className: "hdr-field-label", title: getLabel('status'), children: getLabel('status') }), isReadonly ? (statusLabel ? (jsxRuntimeExports.jsx("span", { className: "hdr-status-badge", style: { backgroundColor: statusColor }, title: statusLabel, children: statusLabel })) : (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", title: "-", 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", title: `${getLabel('statusReason')} :`, children: [getLabel('statusReason'), " :"] }), isReadonly ? (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", title: statusReason || '-', children: statusReason || '-' })) : (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [jsxRuntimeExports.jsx("input", { type: "text", className: `hdr-input ${(!isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing) ? 'hdr-input--error' : ''}`, value: statusReason, placeholder: getLabel('enterReason'), required: isStatusChanged, "aria-required": isStatusChanged, "aria-invalid": !isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing, onBlur: () => {
10335
10453
  if (isReasonMissing)
10336
10454
  setShowReasonRequired(true);
10337
10455
  }, onChange: (e) => {
@@ -10339,7 +10457,7 @@ const HeaderSectionWidget = ({ config }) => {
10339
10457
  if (showReasonRequired && String(e.target.value || '').trim().length > 0) {
10340
10458
  setShowReasonRequired(false);
10341
10459
  }
10342
- } }), !isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing ? (jsxRuntimeExports.jsx("div", { className: "hdr-error-text", children: getLabel('enterReason') })) : null] }))] })] })] }), jsxRuntimeExports.jsx("div", { className: "hdr-right", children: jsxRuntimeExports.jsxs("div", { className: "hdr-right-top", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-col", 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 || '-' })] })] }), score ? (jsxRuntimeExports.jsx("div", { className: "hdr-score-ring", style: { ['--pct']: score.percent }, "aria-label": `Completion score ${score.completionDisplay} of ${score.idealDisplay} (${score.percent}%)`, title: `${score.completionDisplay} / ${score.idealDisplay} (${score.percent}%)`, children: jsxRuntimeExports.jsx("div", { className: "hdr-score-value", children: String(score.completionDisplay) }) })) : null] }) })] })] }));
10460
+ } }), !isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing ? (jsxRuntimeExports.jsx("div", { className: "hdr-error-text", children: getLabel('enterReason') })) : null] }))] })] })] }), jsxRuntimeExports.jsx("div", { className: "hdr-right", children: jsxRuntimeExports.jsxs("div", { className: "hdr-right-top", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-col", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", title: `${getLabel('createdBy')} :`, children: [getLabel('createdBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", title: createdBy || '-', children: createdBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", title: `${getLabel('createdAt')} :`, children: [getLabel('createdAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", title: createdAt || '-', children: createdAt || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", title: `${getLabel('lastApprovedBy')} :`, children: [getLabel('lastApprovedBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", title: lastApprovedBy || '-', children: lastApprovedBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", title: `${getLabel('lastApprovedAt')} :`, children: [getLabel('lastApprovedAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", title: lastApprovedAt || '-', children: lastApprovedAt || '-' })] })] }), score ? (jsxRuntimeExports.jsx("div", { className: "hdr-score-ring", style: { ['--pct']: score.percent }, "aria-label": `Completion score ${score.completionDisplay} of ${score.idealDisplay} (${score.percent}%)`, title: `${score.completionDisplay} / ${score.idealDisplay} (${score.percent}%)`, children: jsxRuntimeExports.jsx("div", { className: "hdr-score-value", children: String(score.completionDisplay) }) })) : null] }) })] })] }));
10343
10461
  };
10344
10462
 
10345
10463
  function getValueByPathOrKey(obj, path) {