@openg2p/registry-widgets 1.1.2-dev.9 → 1.1.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.
package/dist/index.js CHANGED
@@ -2814,6 +2814,8 @@ const useBaseWidget = (options) => {
2814
2814
  const apiService = dataSource?.type === 'api' ? dataSource.service : '';
2815
2815
  const apiEndpoint = dataSource?.type === 'api' ? dataSource.endpoint : '';
2816
2816
  const configKey = `${widgetId}-${isReadonly}-${dataSource?.type || 'none'}-${apiService}-${apiEndpoint}`;
2817
+ // Stable key so inline schemaData objects (e.g. dialog-table fields) don't retrigger loads every render
2818
+ const schemaDataKey = React.useMemo(() => (schemaData ? JSON.stringify(schemaData) : ''), [schemaData]);
2817
2819
  // Extract dependency value using a granular selector to prevent unnecessary re-renders
2818
2820
  // and infinite loops when other unrelated values in the state change.
2819
2821
  const dependencyValue = reactRedux.useSelector((state) => {
@@ -2931,7 +2933,7 @@ const useBaseWidget = (options) => {
2931
2933
  loadDataSource();
2932
2934
  // Use configKey and dependencyValue to ensure effect runs only when relevant state changes
2933
2935
  // eslint-disable-next-line react-hooks/exhaustive-deps
2934
- }, [configKey, dependencyValue, dataSourceRequestHandler, schemaData, widgetId, dispatch]);
2936
+ }, [configKey, dependencyValue, dataSourceRequestHandler, schemaDataKey, widgetId, dispatch]);
2935
2937
  const geoDisplayLabel = React.useMemo(() => {
2936
2938
  if (!geoConfig) {
2937
2939
  return undefined;
@@ -10087,6 +10089,22 @@ const TableWidget = ({ config }) => {
10087
10089
  };
10088
10090
 
10089
10091
  const isUnsetRowValue = (value) => value === null || value === undefined || value === '';
10092
+ /** Match TableWidget cell styling for add / update / delete rows */
10093
+ const getRowCellStyle = (editAction) => {
10094
+ if (editAction === 'ADD') {
10095
+ return { color: 'var(--owt-color-success, #16A34A)' };
10096
+ }
10097
+ if (editAction === 'DELETE') {
10098
+ return {
10099
+ color: 'var(--owt-color-error, #B91C1C)',
10100
+ textDecoration: 'line-through',
10101
+ };
10102
+ }
10103
+ if (editAction === 'UPDATE') {
10104
+ return { color: 'var(--owt-color-warning, #F59E0B)' };
10105
+ }
10106
+ return {};
10107
+ };
10090
10108
  // Display select value label in view mode
10091
10109
  const SelectDisplayValue = ({ config, value }) => {
10092
10110
  const { dataSourceOptions, loading } = useBaseWidget({ config });
@@ -10097,23 +10115,29 @@ const SelectDisplayValue = ({ config, value }) => {
10097
10115
  const selectedOption = dataSourceOptions.find((option) => option.value === value || String(option.value) === String(value));
10098
10116
  return jsxRuntimeExports.jsx("span", { children: selectedOption ? selectedOption.label : String(value) });
10099
10117
  };
10118
+ /** Isolated dialog field — avoids re-running data-source effects when sibling fields update. */
10119
+ const DialogTableField = React.memo(function DialogTableField({ col, cellWidgetId, dialogRowValues, isReadonly, }) {
10120
+ const widgetType = col.widget || 'text';
10121
+ const fieldConfig = React.useMemo(() => {
10122
+ return {
10123
+ ...col,
10124
+ widget: widgetType,
10125
+ 'widget-type': col['widget-type'] || 'input',
10126
+ 'widget-id': cellWidgetId,
10127
+ 'widget-label': col['widget-label'],
10128
+ 'widget-readonly': isReadonly || col['widget-readonly'] === true,
10129
+ 'widget-data-path': undefined,
10130
+ 'widget-data-default': col['widget-data-default'],
10131
+ 'widget-data-options': undefined,
10132
+ 'widget-required': shouldRequireWidget(col['widget-data-options'], dialogRowValues, col['widget-required']),
10133
+ };
10134
+ }, [col, cellWidgetId, dialogRowValues, isReadonly, widgetType]);
10135
+ return (jsxRuntimeExports.jsx("div", { className: "min-w-0", children: jsxRuntimeExports.jsx(WidgetRenderer, { config: fieldConfig }) }));
10136
+ });
10100
10137
  /**
10101
10138
  * Dialog table widget:
10102
10139
  * - Table displays a subset of columns (n out of x)
10103
10140
  * - Add/Edit happens in a modal dialog that shows ALL columns as a form
10104
- *
10105
- * Usage in schema:
10106
- * {
10107
- * "widget": "dialog-table",
10108
- * "widget-type": "table",
10109
- * "widget-label": "Household Members",
10110
- * "widget-id": "householdMembers",
10111
- * "widget-data-path": "household.members",
10112
- * "widget-data-columns": [ ...all columns... ],
10113
- * "widget-data-visible-columns": ["firstName", "lastName", "dob"], // optional override; default = by column flag
10114
- * // Per-column control (recommended): set "column-visible-in-table": false to hide it in the table
10115
- * "widget-data-operations": { "add": true, "edit": true, "remove": true }
10116
- * }
10117
10141
  */
10118
10142
  const DialogTableWidget = ({ config }) => {
10119
10143
  const { value, error, touched, isEnabled, onChange, config: widgetConfig } = useBaseWidget({ config });
@@ -10123,23 +10147,22 @@ const DialogTableWidget = ({ config }) => {
10123
10147
  const columns = widgetConfig['widget-data-columns'] || [];
10124
10148
  const operations = widgetConfig['widget-data-operations'] || {};
10125
10149
  const isReadonly = widgetConfig['widget-readonly'] || false;
10150
+ // Soft-delete (keep row, red + strikethrough) whenever remove is allowed — matches TableWidget
10151
+ const shouldSoftDeleteOnRemove = !isReadonly && !!operations.remove;
10126
10152
  const visibleColumnKeys = widgetConfig['widget-data-visible-columns'];
10127
10153
  const visibleColumns = React.useMemo(() => {
10128
- // 1) If explicit list provided, it wins
10129
10154
  if (Array.isArray(visibleColumnKeys) && visibleColumnKeys.length > 0) {
10130
10155
  const keySet = new Set(visibleColumnKeys);
10131
10156
  return columns.filter((c) => keySet.has(c['column-key']));
10132
10157
  }
10133
- // 2) Otherwise decide per column (default = visible)
10134
10158
  return columns.filter((c) => c['column-visible-in-table'] !== false);
10135
10159
  }, [columns, visibleColumnKeys]);
10136
10160
  const [dialogOpen, setDialogOpen] = React.useState(false);
10137
10161
  const [dialogMode, setDialogMode] = React.useState('add');
10138
10162
  const [activeRowIndex, setActiveRowIndex] = React.useState(null);
10139
- const [formData, setFormData] = React.useState({});
10140
- /** Unique per dialog open so Redux widget ids don't reuse stale values across rows/add sessions */
10141
10163
  const dialogSessionRef = React.useRef(0);
10142
10164
  const [dialogSessionId, setDialogSessionId] = React.useState(0);
10165
+ const membersWidgetId = widgetConfig['widget-id'];
10143
10166
  const addDialogTitle = translateConfig(widgetConfig['widget-data-dialog-title-add']) ||
10144
10167
  translate('table.addRecordDialog') ||
10145
10168
  'Add record';
@@ -10159,15 +10182,26 @@ const DialogTableWidget = ({ config }) => {
10159
10182
  });
10160
10183
  return emptyRow;
10161
10184
  }, [columns]);
10162
- const dialogFieldWidgetId = React.useCallback((columnKey) => `${widgetConfig['widget-id']}-dlg-${dialogSessionId}-${columnKey}`, [widgetConfig, dialogSessionId]);
10185
+ const dialogFieldWidgetId = React.useCallback((sessionId, columnKey) => `${membersWidgetId}-dlg-${sessionId}-${columnKey}`, [membersWidgetId]);
10163
10186
  const resetDialogWidgets = React.useCallback((sessionId) => {
10164
10187
  if (sessionId <= 0)
10165
10188
  return;
10166
10189
  columns.forEach((col) => {
10167
- const wid = `${widgetConfig['widget-id']}-dlg-${sessionId}-${col['column-key']}`;
10168
- dispatch(resetWidget(wid));
10190
+ dispatch(resetWidget(dialogFieldWidgetId(sessionId, col['column-key'])));
10191
+ });
10192
+ }, [columns, dialogFieldWidgetId, dispatch]);
10193
+ const seedDialogReduxValues = React.useCallback((sessionId, rowData) => {
10194
+ const seeds = {};
10195
+ columns.forEach((col) => {
10196
+ const key = col['column-key'];
10197
+ if (rowData[key] !== undefined) {
10198
+ seeds[dialogFieldWidgetId(sessionId, key)] = rowData[key];
10199
+ }
10169
10200
  });
10170
- }, [columns, widgetConfig, dispatch]);
10201
+ if (Object.keys(seeds).length > 0) {
10202
+ dispatch(setValues(seeds));
10203
+ }
10204
+ }, [columns, dialogFieldWidgetId, dispatch]);
10171
10205
  const beginDialogSession = React.useCallback(() => {
10172
10206
  dialogSessionRef.current += 1;
10173
10207
  const nextSession = dialogSessionRef.current;
@@ -10176,15 +10210,21 @@ const DialogTableWidget = ({ config }) => {
10176
10210
  }, []);
10177
10211
  const openAddDialog = React.useCallback(() => {
10178
10212
  resetDialogWidgets(dialogSessionId);
10179
- beginDialogSession();
10213
+ const sessionId = beginDialogSession();
10214
+ seedDialogReduxValues(sessionId, buildEmptyRow());
10180
10215
  setDialogMode('add');
10181
10216
  setActiveRowIndex(null);
10182
- setFormData(buildEmptyRow());
10183
10217
  setDialogOpen(true);
10184
- }, [buildEmptyRow, beginDialogSession, resetDialogWidgets, dialogSessionId]);
10218
+ }, [
10219
+ buildEmptyRow,
10220
+ beginDialogSession,
10221
+ resetDialogWidgets,
10222
+ dialogSessionId,
10223
+ seedDialogReduxValues,
10224
+ ]);
10185
10225
  const openEditDialog = React.useCallback((rowIndex) => {
10186
10226
  resetDialogWidgets(dialogSessionId);
10187
- beginDialogSession();
10227
+ const sessionId = beginDialogSession();
10188
10228
  const row = rows[rowIndex] || {};
10189
10229
  const nextFormData = buildEmptyRow();
10190
10230
  columns.forEach((col) => {
@@ -10192,23 +10232,26 @@ const DialogTableWidget = ({ config }) => {
10192
10232
  if (row[key] !== undefined)
10193
10233
  nextFormData[key] = row[key];
10194
10234
  });
10235
+ seedDialogReduxValues(sessionId, nextFormData);
10195
10236
  setDialogMode('edit');
10196
10237
  setActiveRowIndex(rowIndex);
10197
- setFormData(nextFormData);
10198
10238
  setDialogOpen(true);
10199
- }, [rows, columns, buildEmptyRow, resetDialogWidgets, dialogSessionId, beginDialogSession]);
10239
+ }, [
10240
+ rows,
10241
+ columns,
10242
+ buildEmptyRow,
10243
+ resetDialogWidgets,
10244
+ dialogSessionId,
10245
+ beginDialogSession,
10246
+ seedDialogReduxValues,
10247
+ ]);
10200
10248
  const closeDialog = React.useCallback(() => {
10201
10249
  const sessionToClear = dialogSessionId;
10202
10250
  setDialogOpen(false);
10203
10251
  setActiveRowIndex(null);
10204
- setFormData({});
10205
10252
  resetDialogWidgets(sessionToClear);
10206
10253
  setDialogSessionId(0);
10207
10254
  }, [dialogSessionId, resetDialogWidgets]);
10208
- const updateField = React.useCallback((columnKey, newValue) => {
10209
- setFormData((prev) => ({ ...prev, [columnKey]: newValue }));
10210
- }, []);
10211
- const membersWidgetId = widgetConfig['widget-id'];
10212
10255
  const dialogStoreValues = reactRedux.useSelector((state) => {
10213
10256
  if (dialogSessionId <= 0) {
10214
10257
  return {};
@@ -10217,25 +10260,15 @@ const DialogTableWidget = ({ config }) => {
10217
10260
  const row = {};
10218
10261
  columns.forEach((col) => {
10219
10262
  const k = col['column-key'];
10220
- const wid = `${membersWidgetId}-dlg-${dialogSessionId}-${k}`;
10263
+ const wid = dialogFieldWidgetId(dialogSessionId, k);
10221
10264
  if (values[wid] !== undefined) {
10222
10265
  row[k] = values[wid];
10223
10266
  }
10224
10267
  });
10225
10268
  return row;
10226
- }, (a, b) => JSON.stringify(a) === JSON.stringify(b));
10227
- const buildDialogRowValues = React.useCallback((storeSlice) => {
10228
- const row = { ...formData };
10229
- columns.forEach((col) => {
10230
- const k = col['column-key'];
10231
- if (storeSlice[k] !== undefined) {
10232
- row[k] = storeSlice[k];
10233
- }
10234
- });
10235
- return row;
10236
- }, [formData, columns]);
10237
- const dialogRowValues = React.useMemo(() => buildDialogRowValues(dialogStoreValues), [buildDialogRowValues, dialogStoreValues]);
10238
- const collectMergedRowPayload = React.useCallback(() => buildDialogRowValues(dialogStoreValues), [buildDialogRowValues, dialogStoreValues]);
10269
+ });
10270
+ const dialogRowValues = dialogStoreValues;
10271
+ const collectMergedRowPayload = React.useCallback(() => dialogStoreValues, [dialogStoreValues]);
10239
10272
  const finalizeDialogRowPayload = React.useCallback((raw) => {
10240
10273
  const result = {};
10241
10274
  columns.forEach((col) => {
@@ -10255,7 +10288,7 @@ const DialogTableWidget = ({ config }) => {
10255
10288
  let hasErrors = false;
10256
10289
  columns.forEach((col) => {
10257
10290
  const key = col['column-key'];
10258
- const cellWidgetId = dialogFieldWidgetId(key);
10291
+ const cellWidgetId = dialogFieldWidgetId(dialogSessionId, key);
10259
10292
  const isColReadonly = isReadonly || col['widget-readonly'] === true;
10260
10293
  if (isColReadonly)
10261
10294
  return;
@@ -10299,11 +10332,32 @@ const DialogTableWidget = ({ config }) => {
10299
10332
  onChange(newRows);
10300
10333
  closeDialog();
10301
10334
  }
10302
- }, [collectMergedRowPayload, finalizeDialogRowPayload, dialogMode, onChange, rows, closeDialog, activeRowIndex, columns, dialogFieldWidgetId, isReadonly, dispatch]);
10335
+ }, [
10336
+ collectMergedRowPayload,
10337
+ finalizeDialogRowPayload,
10338
+ dialogMode,
10339
+ onChange,
10340
+ rows,
10341
+ closeDialog,
10342
+ activeRowIndex,
10343
+ columns,
10344
+ dialogSessionId,
10345
+ dialogFieldWidgetId,
10346
+ isReadonly,
10347
+ dispatch,
10348
+ ]);
10303
10349
  const deleteRow = React.useCallback((rowIndex) => {
10304
- const newRows = rows.filter((_, i) => i !== rowIndex);
10305
- onChange(newRows);
10306
- }, [rows, onChange]);
10350
+ if (shouldSoftDeleteOnRemove) {
10351
+ const newRows = [...rows];
10352
+ newRows[rowIndex] = {
10353
+ ...newRows[rowIndex],
10354
+ edit_action: 'DELETE',
10355
+ };
10356
+ onChange(newRows);
10357
+ return;
10358
+ }
10359
+ onChange(rows.filter((_, i) => i !== rowIndex));
10360
+ }, [rows, onChange, shouldSoftDeleteOnRemove]);
10307
10361
  const getDisplayValue = React.useCallback((rowIndex, column) => {
10308
10362
  const key = column['column-key'];
10309
10363
  const cellValue = rows[rowIndex]?.[key];
@@ -10311,11 +10365,12 @@ const DialogTableWidget = ({ config }) => {
10311
10365
  if (cellValue === null || cellValue === undefined || cellValue === '')
10312
10366
  return '-';
10313
10367
  if (widgetType === 'select')
10314
- return null; // handled by SelectDisplayValue
10368
+ return null;
10315
10369
  if (column['widget-data-format'])
10316
10370
  return formatValue(cellValue, column['widget-data-format'], column.widget);
10317
10371
  return String(cellValue);
10318
10372
  }, [rows]);
10373
+ const visibleDialogColumns = React.useMemo(() => columns.filter((col) => shouldShowWidget(col['widget-data-options'], dialogRowValues)), [columns, dialogRowValues]);
10319
10374
  const tableWidgetId = `dialog-table-widget-${widgetConfig['widget-id']}`;
10320
10375
  const columnSpan = widgetConfig['widget-column-span'] || 2;
10321
10376
  const minWidth = columnSpan * 200;
@@ -10343,37 +10398,40 @@ const DialogTableWidget = ({ config }) => {
10343
10398
  }, children: translate('table.addRecord') || 'Add New Record' }) })), jsxRuntimeExports.jsx("div", { className: "overflow-x-auto border", style: {
10344
10399
  borderRadius: 'var(--owt-widget-table-border-radius, 15px)',
10345
10400
  borderColor: 'var(--owt-widget-table-border-color, #C4C4C4)',
10346
- }, children: jsxRuntimeExports.jsxs("table", { className: "min-w-full", style: { borderCollapse: 'separate', borderSpacing: 0 }, children: [jsxRuntimeExports.jsx("thead", { style: { backgroundColor: 'var(--owt-widget-table-header-bg, #F6F6F6)' }, children: jsxRuntimeExports.jsxs("tr", { style: { borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)' }, children: [visibleColumns.map((col) => (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translateConfig(col['widget-label']) }, col['column-key']))), ((operations.edit || operations.remove) && !isReadonly) && (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translate('common.actions') || 'Actions' }))] }) }), jsxRuntimeExports.jsxs("tbody", { style: { backgroundColor: 'var(--owt-widget-table-body-bg, #FFFFFF)' }, children: [rows.length === 0 && (jsxRuntimeExports.jsx("tr", { children: jsxRuntimeExports.jsxs("td", { colSpan: visibleColumns.length + (((operations.edit || operations.remove) && !isReadonly) ? 1 : 0), className: "px-4 py-6 text-center text-sm", style: { color: 'var(--owt-widget-table-empty-color, #727474)' }, children: [translate('table.noData') || 'No records available.', operations.add && !isReadonly && ` ${translate('table.clickToAdd') || 'Click "Add New Record" to add one.'}`] }) })), rows.map((row, rowIndex) => (jsxRuntimeExports.jsxs("tr", { style: {
10347
- borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)',
10348
- backgroundColor: row?.edit_action === 'DELETE'
10349
- ? 'var(--owt-widget-table-deleted-row-bg, #FEE2E2)'
10350
- : undefined,
10351
- }, children: [visibleColumns.map((col) => {
10352
- const key = col['column-key'];
10353
- const widgetType = col.widget || 'text';
10354
- const displayValue = getDisplayValue(rowIndex, col);
10355
- if (widgetType === 'select' && displayValue === null) {
10356
- const displayConfig = {
10357
- ...col,
10358
- 'widget-id': `${widgetConfig['widget-id']}-view-row-${rowIndex}-col-${key}`,
10359
- 'widget-label': '',
10360
- 'widget-readonly': true,
10361
- 'widget-data-path': undefined,
10362
- };
10363
- return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsx("div", { className: "text-sm", children: jsxRuntimeExports.jsx(SelectDisplayValue, { config: displayConfig, value: row?.[key] }) }) }, key));
10364
- }
10365
- return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsx("div", { className: "text-sm", children: displayValue }) }, key));
10366
- }), ((operations.edit || operations.remove) && !isReadonly) && (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", style: { minWidth: '120px' }, children: jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [operations.edit && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => openEditDialog(rowIndex), disabled: !isEnabled, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
10367
- borderRadius: 'var(--owt-btn-border-radius, 10px)',
10368
- color: 'var(--owt-color-primary-dark, #F07B1A)',
10369
- backgroundColor: 'transparent',
10370
- border: 'none',
10371
- }, children: translate('common.edit') || 'Edit' })), operations.remove && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => deleteRow(rowIndex), disabled: !isEnabled, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
10372
- borderRadius: 'var(--owt-btn-border-radius, 10px)',
10373
- color: 'var(--owt-color-error, #B91C1C)',
10374
- backgroundColor: 'transparent',
10375
- border: 'none',
10376
- }, children: translate('common.remove') || 'Delete' }))] }) }))] }, rowIndex)))] })] }) }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-sm mt-1", style: { color: 'var(--owt-widget-error-color, #B91C1C)' }, children: error[0] }))] }), dialogOpen && (jsxRuntimeExports.jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50", style: { backgroundColor: 'rgba(0,0,0,0.5)' }, children: jsxRuntimeExports.jsxs("div", { className: "rounded-lg p-6 w-full mx-4", style: {
10401
+ }, children: jsxRuntimeExports.jsxs("table", { className: "min-w-full", style: { borderCollapse: 'separate', borderSpacing: 0 }, children: [jsxRuntimeExports.jsx("thead", { style: { backgroundColor: 'var(--owt-widget-table-header-bg, #F6F6F6)' }, children: jsxRuntimeExports.jsxs("tr", { style: { borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)' }, children: [visibleColumns.map((col) => (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translateConfig(col['widget-label']) }, col['column-key']))), ((operations.edit || operations.remove) && !isReadonly) && (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translate('common.actions') || 'Actions' }))] }) }), jsxRuntimeExports.jsxs("tbody", { style: { backgroundColor: 'var(--owt-widget-table-body-bg, #FFFFFF)' }, children: [rows.length === 0 && (jsxRuntimeExports.jsx("tr", { children: jsxRuntimeExports.jsxs("td", { colSpan: visibleColumns.length + (((operations.edit || operations.remove) && !isReadonly) ? 1 : 0), className: "px-4 py-6 text-center text-sm", style: { color: 'var(--owt-widget-table-empty-color, #727474)' }, children: [translate('table.noData') || 'No records available.', operations.add && !isReadonly && ` ${translate('table.clickToAdd') || 'Click "Add New Record" to add one.'}`] }) })), rows.map((row, rowIndex) => {
10402
+ const cellStyle = getRowCellStyle(row?.edit_action);
10403
+ return (jsxRuntimeExports.jsxs("tr", { style: {
10404
+ borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)',
10405
+ backgroundColor: row?.edit_action === 'DELETE'
10406
+ ? 'var(--owt-widget-table-deleted-row-bg, #FEE2E2)'
10407
+ : undefined,
10408
+ }, children: [visibleColumns.map((col) => {
10409
+ const key = col['column-key'];
10410
+ const widgetType = col.widget || 'text';
10411
+ const displayValue = getDisplayValue(rowIndex, col);
10412
+ if (widgetType === 'select' && displayValue === null) {
10413
+ const displayConfig = {
10414
+ ...col,
10415
+ 'widget-id': `${widgetConfig['widget-id']}-view-row-${rowIndex}-col-${key}`,
10416
+ 'widget-label': '',
10417
+ 'widget-readonly': true,
10418
+ 'widget-data-path': undefined,
10419
+ };
10420
+ return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsx("div", { className: "text-sm", style: cellStyle, children: jsxRuntimeExports.jsx(SelectDisplayValue, { config: displayConfig, value: row?.[key] }) }) }, key));
10421
+ }
10422
+ return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsx("div", { className: "text-sm", style: cellStyle, children: displayValue }) }, key));
10423
+ }), ((operations.edit || operations.remove) && !isReadonly) && (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", style: { minWidth: '120px' }, children: jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [operations.edit && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => openEditDialog(rowIndex), disabled: !isEnabled, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
10424
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
10425
+ color: 'var(--owt-color-primary-dark, #F07B1A)',
10426
+ backgroundColor: 'transparent',
10427
+ border: 'none',
10428
+ }, children: translate('common.edit') || 'Edit' })), operations.remove && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => deleteRow(rowIndex), disabled: !isEnabled, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
10429
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
10430
+ color: 'var(--owt-color-error, #B91C1C)',
10431
+ backgroundColor: 'transparent',
10432
+ border: 'none',
10433
+ }, children: translate('common.remove') || 'Delete' }))] }) }))] }, rowIndex));
10434
+ })] })] }) }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-sm mt-1", style: { color: 'var(--owt-widget-error-color, #B91C1C)' }, children: error[0] }))] }), dialogOpen && (jsxRuntimeExports.jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50", style: { backgroundColor: 'rgba(0,0,0,0.5)' }, children: jsxRuntimeExports.jsxs("div", { className: "rounded-lg p-6 w-full mx-4", style: {
10377
10435
  maxWidth: '900px',
10378
10436
  backgroundColor: 'var(--owt-color-bg, #FFFFFF)',
10379
10437
  borderRadius: 'var(--owt-widget-card-border-radius, 20px)',
@@ -10384,27 +10442,10 @@ const DialogTableWidget = ({ config }) => {
10384
10442
  cursor: 'pointer',
10385
10443
  fontSize: '20px',
10386
10444
  lineHeight: 1,
10387
- }, "aria-label": "Close", children: "\u00D7" })] }), jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", style: { maxHeight: '70vh', overflow: 'auto' }, children: columns.map((col) => {
10445
+ }, "aria-label": "Close", children: "\u00D7" })] }), jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", style: { maxHeight: '70vh', overflow: 'auto' }, children: visibleDialogColumns.map((col) => {
10388
10446
  const key = col['column-key'];
10389
- if (!shouldShowWidget(col['widget-data-options'], dialogRowValues)) {
10390
- return null;
10391
- }
10392
- const widgetType = col.widget || 'text';
10393
- const cellWidgetId = dialogFieldWidgetId(key);
10394
- const initialValue = formData[key] ?? col['widget-data-default'];
10395
- const fieldConfig = {
10396
- ...col,
10397
- widget: widgetType,
10398
- 'widget-type': col['widget-type'] || 'input',
10399
- 'widget-id': cellWidgetId,
10400
- 'widget-label': col['widget-label'],
10401
- 'widget-readonly': isReadonly || col['widget-readonly'] === true,
10402
- 'widget-data-path': undefined,
10403
- 'widget-data-default': initialValue,
10404
- 'widget-data-options': undefined,
10405
- 'widget-required': shouldRequireWidget(col['widget-data-options'], dialogRowValues, col['widget-required']),
10406
- };
10407
- return (jsxRuntimeExports.jsx("div", { className: "min-w-0", children: jsxRuntimeExports.jsx(WidgetRenderer, { config: fieldConfig, schemaData: { [cellWidgetId]: initialValue }, onValueChange: (_widgetId, newValue) => updateField(key, newValue) }) }, `${dialogSessionId}-${key}`));
10447
+ const cellWidgetId = dialogFieldWidgetId(dialogSessionId, key);
10448
+ return (jsxRuntimeExports.jsx(DialogTableField, { col: col, cellWidgetId: cellWidgetId, dialogRowValues: dialogRowValues, isReadonly: isReadonly }, `${dialogSessionId}-${key}`));
10408
10449
  }) }, `dialog-fields-${dialogSessionId}`), jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-3 mt-6", children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: closeDialog, className: "px-4 py-2 text-sm font-medium", style: {
10409
10450
  borderRadius: 'var(--owt-btn-border-radius, 10px)',
10410
10451
  border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',