@openg2p/registry-widgets 1.1.2-dev.9 → 1.1.3-dev.1

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.
@@ -437,6 +437,10 @@ export declare const panelSchema: {
437
437
  'column-key': {
438
438
  type: "string";
439
439
  };
440
+ 'column-group': {
441
+ type: "string";
442
+ description: string;
443
+ };
440
444
  'widget-label': {
441
445
  type: "string";
442
446
  };
@@ -964,6 +968,10 @@ export declare const panelSchema: {
964
968
  'column-key': {
965
969
  type: "string";
966
970
  };
971
+ 'column-group': {
972
+ type: "string";
973
+ description: string;
974
+ };
967
975
  'widget-label': {
968
976
  type: "string";
969
977
  };
@@ -1554,6 +1562,10 @@ export declare const sectionSchema: {
1554
1562
  'column-key': {
1555
1563
  type: "string";
1556
1564
  };
1565
+ 'column-group': {
1566
+ type: "string";
1567
+ description: string;
1568
+ };
1557
1569
  'widget-label': {
1558
1570
  type: "string";
1559
1571
  };
@@ -2081,6 +2093,10 @@ export declare const sectionSchema: {
2081
2093
  'column-key': {
2082
2094
  type: "string";
2083
2095
  };
2096
+ 'column-group': {
2097
+ type: "string";
2098
+ description: string;
2099
+ };
2084
2100
  'widget-label': {
2085
2101
  type: "string";
2086
2102
  };
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/components/SectionBuilder/schemas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/components/SectionBuilder/schemas.ts"],"names":[],"mappings":"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"}
@@ -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';
@@ -405,9 +405,8 @@ const createZodSchema = (validation, required = false) => {
405
405
  const normalizeBooleanLike = (val) => {
406
406
  if (val === true || val === 1)
407
407
  return true;
408
- if (val === false || val === 0 || val === null || val === undefined || val === '') {
408
+ if (val === false || val === 0)
409
409
  return false;
410
- }
411
410
  if (typeof val === 'string') {
412
411
  const normalized = val.trim().toLowerCase();
413
412
  return normalized === 'true' || normalized === 'yes' || normalized === '1';
@@ -422,8 +421,11 @@ const evaluateCondition = (condition, allValues) => {
422
421
  const { operator, value } = condition;
423
422
  switch (operator) {
424
423
  case 'equals':
425
- if (typeof value === 'boolean' || typeof fieldValue === 'boolean') {
426
- return normalizeBooleanLike(fieldValue) === normalizeBooleanLike(value);
424
+ if (typeof value === 'boolean') {
425
+ return typeof fieldValue === 'boolean' && fieldValue === value;
426
+ }
427
+ if (typeof fieldValue === 'boolean') {
428
+ return fieldValue === normalizeBooleanLike(value);
427
429
  }
428
430
  return fieldValue === value;
429
431
  case 'notEquals':
@@ -2813,6 +2815,8 @@ const useBaseWidget = (options) => {
2813
2815
  const apiService = dataSource?.type === 'api' ? dataSource.service : '';
2814
2816
  const apiEndpoint = dataSource?.type === 'api' ? dataSource.endpoint : '';
2815
2817
  const configKey = `${widgetId}-${isReadonly}-${dataSource?.type || 'none'}-${apiService}-${apiEndpoint}`;
2818
+ // Stable key so inline schemaData objects (e.g. dialog-table fields) don't retrigger loads every render
2819
+ const schemaDataKey = useMemo(() => (schemaData ? JSON.stringify(schemaData) : ''), [schemaData]);
2816
2820
  // Extract dependency value using a granular selector to prevent unnecessary re-renders
2817
2821
  // and infinite loops when other unrelated values in the state change.
2818
2822
  const dependencyValue = useSelector((state) => {
@@ -2930,7 +2934,7 @@ const useBaseWidget = (options) => {
2930
2934
  loadDataSource();
2931
2935
  // Use configKey and dependencyValue to ensure effect runs only when relevant state changes
2932
2936
  // eslint-disable-next-line react-hooks/exhaustive-deps
2933
- }, [configKey, dependencyValue, dataSourceRequestHandler, schemaData, widgetId, dispatch]);
2937
+ }, [configKey, dependencyValue, dataSourceRequestHandler, schemaDataKey, widgetId, dispatch]);
2934
2938
  const geoDisplayLabel = useMemo(() => {
2935
2939
  if (!geoConfig) {
2936
2940
  return undefined;
@@ -10086,6 +10090,56 @@ const TableWidget = ({ config }) => {
10086
10090
  };
10087
10091
 
10088
10092
  const isUnsetRowValue = (value) => value === null || value === undefined || value === '';
10093
+ const buildDialogConditionValues = (row, columns) => {
10094
+ let context = { ...row };
10095
+ columns.forEach((col) => {
10096
+ const columnKey = col['column-key'];
10097
+ if (!columnKey || row[columnKey] === undefined) {
10098
+ return;
10099
+ }
10100
+ const dataPath = col['widget-data-path'];
10101
+ if (typeof dataPath === 'string' && dataPath) {
10102
+ context = setValueByPath(context, dataPath, row[columnKey]);
10103
+ }
10104
+ });
10105
+ return context;
10106
+ };
10107
+ const buildDialogColumnSegments = (columns) => {
10108
+ const segments = [];
10109
+ let index = 0;
10110
+ while (index < columns.length) {
10111
+ const group = columns[index]['column-group'];
10112
+ if (group) {
10113
+ const groupCols = [];
10114
+ while (index < columns.length && columns[index]['column-group'] === group) {
10115
+ groupCols.push(columns[index]);
10116
+ index += 1;
10117
+ }
10118
+ segments.push({ type: 'group', group, cols: groupCols });
10119
+ }
10120
+ else {
10121
+ segments.push({ type: 'single', col: columns[index] });
10122
+ index += 1;
10123
+ }
10124
+ }
10125
+ return segments;
10126
+ };
10127
+ /** Match TableWidget cell styling for add / update / delete rows */
10128
+ const getRowCellStyle = (editAction) => {
10129
+ if (editAction === 'ADD') {
10130
+ return { color: 'var(--owt-color-success, #16A34A)' };
10131
+ }
10132
+ if (editAction === 'DELETE') {
10133
+ return {
10134
+ color: 'var(--owt-color-error, #B91C1C)',
10135
+ textDecoration: 'line-through',
10136
+ };
10137
+ }
10138
+ if (editAction === 'UPDATE') {
10139
+ return { color: 'var(--owt-color-warning, #F59E0B)' };
10140
+ }
10141
+ return {};
10142
+ };
10089
10143
  // Display select value label in view mode
10090
10144
  const SelectDisplayValue = ({ config, value }) => {
10091
10145
  const { dataSourceOptions, loading } = useBaseWidget({ config });
@@ -10096,23 +10150,29 @@ const SelectDisplayValue = ({ config, value }) => {
10096
10150
  const selectedOption = dataSourceOptions.find((option) => option.value === value || String(option.value) === String(value));
10097
10151
  return jsxRuntimeExports.jsx("span", { children: selectedOption ? selectedOption.label : String(value) });
10098
10152
  };
10153
+ /** Isolated dialog field — avoids re-running data-source effects when sibling fields update. */
10154
+ const DialogTableField = memo(function DialogTableField({ col, cellWidgetId, dialogConditionValues, isReadonly, }) {
10155
+ const widgetType = col.widget || 'text';
10156
+ const fieldConfig = useMemo(() => {
10157
+ return {
10158
+ ...col,
10159
+ widget: widgetType,
10160
+ 'widget-type': col['widget-type'] || 'input',
10161
+ 'widget-id': cellWidgetId,
10162
+ 'widget-label': col['widget-label'],
10163
+ 'widget-readonly': isReadonly || col['widget-readonly'] === true,
10164
+ 'widget-data-path': undefined,
10165
+ 'widget-data-default': col['widget-data-default'],
10166
+ 'widget-data-options': undefined,
10167
+ 'widget-required': shouldRequireWidget(col['widget-data-options'], dialogConditionValues, col['widget-required']),
10168
+ };
10169
+ }, [col, cellWidgetId, dialogConditionValues, isReadonly, widgetType]);
10170
+ return (jsxRuntimeExports.jsx("div", { className: "min-w-0", children: jsxRuntimeExports.jsx(WidgetRenderer, { config: fieldConfig }) }));
10171
+ });
10099
10172
  /**
10100
10173
  * Dialog table widget:
10101
10174
  * - Table displays a subset of columns (n out of x)
10102
10175
  * - 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
10176
  */
10117
10177
  const DialogTableWidget = ({ config }) => {
10118
10178
  const { value, error, touched, isEnabled, onChange, config: widgetConfig } = useBaseWidget({ config });
@@ -10122,23 +10182,22 @@ const DialogTableWidget = ({ config }) => {
10122
10182
  const columns = widgetConfig['widget-data-columns'] || [];
10123
10183
  const operations = widgetConfig['widget-data-operations'] || {};
10124
10184
  const isReadonly = widgetConfig['widget-readonly'] || false;
10185
+ // Soft-delete (keep row, red + strikethrough) whenever remove is allowed — matches TableWidget
10186
+ const shouldSoftDeleteOnRemove = !isReadonly && !!operations.remove;
10125
10187
  const visibleColumnKeys = widgetConfig['widget-data-visible-columns'];
10126
10188
  const visibleColumns = useMemo(() => {
10127
- // 1) If explicit list provided, it wins
10128
10189
  if (Array.isArray(visibleColumnKeys) && visibleColumnKeys.length > 0) {
10129
10190
  const keySet = new Set(visibleColumnKeys);
10130
10191
  return columns.filter((c) => keySet.has(c['column-key']));
10131
10192
  }
10132
- // 2) Otherwise decide per column (default = visible)
10133
10193
  return columns.filter((c) => c['column-visible-in-table'] !== false);
10134
10194
  }, [columns, visibleColumnKeys]);
10135
10195
  const [dialogOpen, setDialogOpen] = useState(false);
10136
10196
  const [dialogMode, setDialogMode] = useState('add');
10137
10197
  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
10198
  const dialogSessionRef = useRef(0);
10141
10199
  const [dialogSessionId, setDialogSessionId] = useState(0);
10200
+ const membersWidgetId = widgetConfig['widget-id'];
10142
10201
  const addDialogTitle = translateConfig(widgetConfig['widget-data-dialog-title-add']) ||
10143
10202
  translate('table.addRecordDialog') ||
10144
10203
  'Add record';
@@ -10158,15 +10217,26 @@ const DialogTableWidget = ({ config }) => {
10158
10217
  });
10159
10218
  return emptyRow;
10160
10219
  }, [columns]);
10161
- const dialogFieldWidgetId = useCallback((columnKey) => `${widgetConfig['widget-id']}-dlg-${dialogSessionId}-${columnKey}`, [widgetConfig, dialogSessionId]);
10220
+ const dialogFieldWidgetId = useCallback((sessionId, columnKey) => `${membersWidgetId}-dlg-${sessionId}-${columnKey}`, [membersWidgetId]);
10162
10221
  const resetDialogWidgets = useCallback((sessionId) => {
10163
10222
  if (sessionId <= 0)
10164
10223
  return;
10165
10224
  columns.forEach((col) => {
10166
- const wid = `${widgetConfig['widget-id']}-dlg-${sessionId}-${col['column-key']}`;
10167
- dispatch(resetWidget(wid));
10225
+ dispatch(resetWidget(dialogFieldWidgetId(sessionId, col['column-key'])));
10168
10226
  });
10169
- }, [columns, widgetConfig, dispatch]);
10227
+ }, [columns, dialogFieldWidgetId, dispatch]);
10228
+ const seedDialogReduxValues = useCallback((sessionId, rowData) => {
10229
+ const seeds = {};
10230
+ columns.forEach((col) => {
10231
+ const key = col['column-key'];
10232
+ if (rowData[key] !== undefined) {
10233
+ seeds[dialogFieldWidgetId(sessionId, key)] = rowData[key];
10234
+ }
10235
+ });
10236
+ if (Object.keys(seeds).length > 0) {
10237
+ dispatch(setValues(seeds));
10238
+ }
10239
+ }, [columns, dialogFieldWidgetId, dispatch]);
10170
10240
  const beginDialogSession = useCallback(() => {
10171
10241
  dialogSessionRef.current += 1;
10172
10242
  const nextSession = dialogSessionRef.current;
@@ -10175,15 +10245,21 @@ const DialogTableWidget = ({ config }) => {
10175
10245
  }, []);
10176
10246
  const openAddDialog = useCallback(() => {
10177
10247
  resetDialogWidgets(dialogSessionId);
10178
- beginDialogSession();
10248
+ const sessionId = beginDialogSession();
10249
+ seedDialogReduxValues(sessionId, buildEmptyRow());
10179
10250
  setDialogMode('add');
10180
10251
  setActiveRowIndex(null);
10181
- setFormData(buildEmptyRow());
10182
10252
  setDialogOpen(true);
10183
- }, [buildEmptyRow, beginDialogSession, resetDialogWidgets, dialogSessionId]);
10253
+ }, [
10254
+ buildEmptyRow,
10255
+ beginDialogSession,
10256
+ resetDialogWidgets,
10257
+ dialogSessionId,
10258
+ seedDialogReduxValues,
10259
+ ]);
10184
10260
  const openEditDialog = useCallback((rowIndex) => {
10185
10261
  resetDialogWidgets(dialogSessionId);
10186
- beginDialogSession();
10262
+ const sessionId = beginDialogSession();
10187
10263
  const row = rows[rowIndex] || {};
10188
10264
  const nextFormData = buildEmptyRow();
10189
10265
  columns.forEach((col) => {
@@ -10191,23 +10267,26 @@ const DialogTableWidget = ({ config }) => {
10191
10267
  if (row[key] !== undefined)
10192
10268
  nextFormData[key] = row[key];
10193
10269
  });
10270
+ seedDialogReduxValues(sessionId, nextFormData);
10194
10271
  setDialogMode('edit');
10195
10272
  setActiveRowIndex(rowIndex);
10196
- setFormData(nextFormData);
10197
10273
  setDialogOpen(true);
10198
- }, [rows, columns, buildEmptyRow, resetDialogWidgets, dialogSessionId, beginDialogSession]);
10274
+ }, [
10275
+ rows,
10276
+ columns,
10277
+ buildEmptyRow,
10278
+ resetDialogWidgets,
10279
+ dialogSessionId,
10280
+ beginDialogSession,
10281
+ seedDialogReduxValues,
10282
+ ]);
10199
10283
  const closeDialog = useCallback(() => {
10200
10284
  const sessionToClear = dialogSessionId;
10201
10285
  setDialogOpen(false);
10202
10286
  setActiveRowIndex(null);
10203
- setFormData({});
10204
10287
  resetDialogWidgets(sessionToClear);
10205
10288
  setDialogSessionId(0);
10206
10289
  }, [dialogSessionId, resetDialogWidgets]);
10207
- const updateField = useCallback((columnKey, newValue) => {
10208
- setFormData((prev) => ({ ...prev, [columnKey]: newValue }));
10209
- }, []);
10210
- const membersWidgetId = widgetConfig['widget-id'];
10211
10290
  const dialogStoreValues = useSelector((state) => {
10212
10291
  if (dialogSessionId <= 0) {
10213
10292
  return {};
@@ -10216,30 +10295,22 @@ const DialogTableWidget = ({ config }) => {
10216
10295
  const row = {};
10217
10296
  columns.forEach((col) => {
10218
10297
  const k = col['column-key'];
10219
- const wid = `${membersWidgetId}-dlg-${dialogSessionId}-${k}`;
10298
+ const wid = dialogFieldWidgetId(dialogSessionId, k);
10220
10299
  if (values[wid] !== undefined) {
10221
10300
  row[k] = values[wid];
10222
10301
  }
10223
10302
  });
10224
10303
  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]);
10304
+ });
10305
+ const dialogRowValues = dialogStoreValues;
10306
+ const dialogConditionValues = useMemo(() => buildDialogConditionValues(dialogRowValues, columns), [dialogRowValues, columns]);
10307
+ const collectMergedRowPayload = useCallback(() => dialogStoreValues, [dialogStoreValues]);
10238
10308
  const finalizeDialogRowPayload = useCallback((raw) => {
10309
+ const conditionValues = buildDialogConditionValues(raw, columns);
10239
10310
  const result = {};
10240
10311
  columns.forEach((col) => {
10241
10312
  const key = col['column-key'];
10242
- if (!shouldShowWidget(col['widget-data-options'], raw)) {
10313
+ if (!shouldShowWidget(col['widget-data-options'], conditionValues)) {
10243
10314
  return;
10244
10315
  }
10245
10316
  const val = raw[key];
@@ -10251,17 +10322,18 @@ const DialogTableWidget = ({ config }) => {
10251
10322
  }, [columns]);
10252
10323
  const saveDialog = useCallback(() => {
10253
10324
  const payload = collectMergedRowPayload();
10325
+ const conditionValues = buildDialogConditionValues(payload, columns);
10254
10326
  let hasErrors = false;
10255
10327
  columns.forEach((col) => {
10256
10328
  const key = col['column-key'];
10257
- const cellWidgetId = dialogFieldWidgetId(key);
10329
+ const cellWidgetId = dialogFieldWidgetId(dialogSessionId, key);
10258
10330
  const isColReadonly = isReadonly || col['widget-readonly'] === true;
10259
10331
  if (isColReadonly)
10260
10332
  return;
10261
- if (!shouldShowWidget(col['widget-data-options'], payload))
10333
+ if (!shouldShowWidget(col['widget-data-options'], conditionValues))
10262
10334
  return;
10263
10335
  const cellValue = payload[key];
10264
- const isRequired = shouldRequireWidget(col['widget-data-options'], payload, col['widget-required']);
10336
+ const isRequired = shouldRequireWidget(col['widget-data-options'], conditionValues, col['widget-required']);
10265
10337
  const validationErrors = validateWidget(cellValue, col['widget-data-validation'], isRequired);
10266
10338
  if (validationErrors && validationErrors.length > 0) {
10267
10339
  hasErrors = true;
@@ -10298,11 +10370,32 @@ const DialogTableWidget = ({ config }) => {
10298
10370
  onChange(newRows);
10299
10371
  closeDialog();
10300
10372
  }
10301
- }, [collectMergedRowPayload, finalizeDialogRowPayload, dialogMode, onChange, rows, closeDialog, activeRowIndex, columns, dialogFieldWidgetId, isReadonly, dispatch]);
10373
+ }, [
10374
+ collectMergedRowPayload,
10375
+ finalizeDialogRowPayload,
10376
+ dialogMode,
10377
+ onChange,
10378
+ rows,
10379
+ closeDialog,
10380
+ activeRowIndex,
10381
+ columns,
10382
+ dialogSessionId,
10383
+ dialogFieldWidgetId,
10384
+ isReadonly,
10385
+ dispatch,
10386
+ ]);
10302
10387
  const deleteRow = useCallback((rowIndex) => {
10303
- const newRows = rows.filter((_, i) => i !== rowIndex);
10304
- onChange(newRows);
10305
- }, [rows, onChange]);
10388
+ if (shouldSoftDeleteOnRemove) {
10389
+ const newRows = [...rows];
10390
+ newRows[rowIndex] = {
10391
+ ...newRows[rowIndex],
10392
+ edit_action: 'DELETE',
10393
+ };
10394
+ onChange(newRows);
10395
+ return;
10396
+ }
10397
+ onChange(rows.filter((_, i) => i !== rowIndex));
10398
+ }, [rows, onChange, shouldSoftDeleteOnRemove]);
10306
10399
  const getDisplayValue = useCallback((rowIndex, column) => {
10307
10400
  const key = column['column-key'];
10308
10401
  const cellValue = rows[rowIndex]?.[key];
@@ -10310,11 +10403,33 @@ const DialogTableWidget = ({ config }) => {
10310
10403
  if (cellValue === null || cellValue === undefined || cellValue === '')
10311
10404
  return '-';
10312
10405
  if (widgetType === 'select')
10313
- return null; // handled by SelectDisplayValue
10406
+ return null;
10314
10407
  if (column['widget-data-format'])
10315
10408
  return formatValue(cellValue, column['widget-data-format'], column.widget);
10316
10409
  return String(cellValue);
10317
10410
  }, [rows]);
10411
+ const dialogColumnSegments = useMemo(() => {
10412
+ return buildDialogColumnSegments(columns)
10413
+ .map((segment) => {
10414
+ if (segment.type === 'single') {
10415
+ if (!shouldShowWidget(segment.col['widget-data-options'], dialogConditionValues)) {
10416
+ return null;
10417
+ }
10418
+ return segment;
10419
+ }
10420
+ const visibleCols = segment.cols.filter((col) => shouldShowWidget(col['widget-data-options'], dialogConditionValues));
10421
+ if (visibleCols.length === 0) {
10422
+ return null;
10423
+ }
10424
+ return { type: 'group', group: segment.group, cols: visibleCols };
10425
+ })
10426
+ .filter((segment) => segment !== null);
10427
+ }, [columns, dialogConditionValues]);
10428
+ const renderDialogField = (col) => {
10429
+ const key = col['column-key'];
10430
+ const cellWidgetId = dialogFieldWidgetId(dialogSessionId, key);
10431
+ return (jsxRuntimeExports.jsx(DialogTableField, { col: col, cellWidgetId: cellWidgetId, dialogConditionValues: dialogConditionValues, isReadonly: isReadonly }, `${dialogSessionId}-${key}`));
10432
+ };
10318
10433
  const tableWidgetId = `dialog-table-widget-${widgetConfig['widget-id']}`;
10319
10434
  const columnSpan = widgetConfig['widget-column-span'] || 2;
10320
10435
  const minWidth = columnSpan * 200;
@@ -10342,37 +10457,40 @@ const DialogTableWidget = ({ config }) => {
10342
10457
  }, children: translate('table.addRecord') || 'Add New Record' }) })), jsxRuntimeExports.jsx("div", { className: "overflow-x-auto border", style: {
10343
10458
  borderRadius: 'var(--owt-widget-table-border-radius, 15px)',
10344
10459
  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: {
10460
+ }, 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) => {
10461
+ const cellStyle = getRowCellStyle(row?.edit_action);
10462
+ return (jsxRuntimeExports.jsxs("tr", { style: {
10463
+ borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)',
10464
+ backgroundColor: row?.edit_action === 'DELETE'
10465
+ ? 'var(--owt-widget-table-deleted-row-bg, #FEE2E2)'
10466
+ : undefined,
10467
+ }, children: [visibleColumns.map((col) => {
10468
+ const key = col['column-key'];
10469
+ const widgetType = col.widget || 'text';
10470
+ const displayValue = getDisplayValue(rowIndex, col);
10471
+ if (widgetType === 'select' && displayValue === null) {
10472
+ const displayConfig = {
10473
+ ...col,
10474
+ 'widget-id': `${widgetConfig['widget-id']}-view-row-${rowIndex}-col-${key}`,
10475
+ 'widget-label': '',
10476
+ 'widget-readonly': true,
10477
+ 'widget-data-path': undefined,
10478
+ };
10479
+ 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));
10480
+ }
10481
+ return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsx("div", { className: "text-sm", style: cellStyle, children: displayValue }) }, key));
10482
+ }), ((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: {
10483
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
10484
+ color: 'var(--owt-color-primary-dark, #F07B1A)',
10485
+ backgroundColor: 'transparent',
10486
+ border: 'none',
10487
+ }, 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: {
10488
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
10489
+ color: 'var(--owt-color-error, #B91C1C)',
10490
+ backgroundColor: 'transparent',
10491
+ border: 'none',
10492
+ }, children: translate('common.remove') || 'Delete' }))] }) }))] }, rowIndex));
10493
+ })] })] }) }), 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
10494
  maxWidth: '900px',
10377
10495
  backgroundColor: 'var(--owt-color-bg, #FFFFFF)',
10378
10496
  borderRadius: 'var(--owt-widget-card-border-radius, 20px)',
@@ -10383,27 +10501,11 @@ const DialogTableWidget = ({ config }) => {
10383
10501
  cursor: 'pointer',
10384
10502
  fontSize: '20px',
10385
10503
  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) => {
10387
- const key = col['column-key'];
10388
- if (!shouldShowWidget(col['widget-data-options'], dialogRowValues)) {
10389
- return null;
10504
+ }, "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: dialogColumnSegments.map((segment) => {
10505
+ if (segment.type === 'single') {
10506
+ return renderDialogField(segment.col);
10390
10507
  }
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}`));
10508
+ return (jsxRuntimeExports.jsx("div", { className: "md:col-span-2 grid grid-cols-1 md:grid-cols-2 gap-4", children: segment.cols.map((col) => renderDialogField(col)) }, `${dialogSessionId}-group-${segment.group}`));
10407
10509
  }) }, `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
10510
  borderRadius: 'var(--owt-btn-border-radius, 10px)',
10409
10511
  border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',