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