@openg2p/registry-widgets 1.1.0-dev.2 → 1.1.0-dev.3

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.esm.js CHANGED
@@ -8524,7 +8524,7 @@ const TableCellSelect = ({ config, value, onValueChange }) => {
8524
8524
  backgroundColor: isReadonly || loading ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
8525
8525
  }, children: [jsxRuntimeExports.jsx("option", { value: "", children: translate('common.select') || 'Select' }), dataSourceOptions.map((option) => (jsxRuntimeExports.jsx("option", { value: option.value, children: option.label }, option.value)))] }));
8526
8526
  };
8527
- const SelectDisplayValue = ({ config, value }) => {
8527
+ const SelectDisplayValue$1 = ({ config, value }) => {
8528
8528
  const { dataSourceOptions, loading } = useBaseWidget({ config });
8529
8529
  if (loading) {
8530
8530
  return jsxRuntimeExports.jsx("span", { children: "-" });
@@ -9018,7 +9018,7 @@ const TableWidget = ({ config }) => {
9018
9018
  'widget-readonly': true,
9019
9019
  'widget-data-path': undefined,
9020
9020
  };
9021
- return (jsxRuntimeExports.jsx("div", { className: "text-sm", style: getCellStyle(), children: jsxRuntimeExports.jsx(SelectDisplayValue, { config: cellConfig, value: cellValue }) }));
9021
+ return (jsxRuntimeExports.jsx("div", { className: "text-sm", style: getCellStyle(), children: jsxRuntimeExports.jsx(SelectDisplayValue$1, { config: cellConfig, value: cellValue }) }));
9022
9022
  }
9023
9023
  return (jsxRuntimeExports.jsx("div", { className: "text-sm", style: getCellStyle(), children: displayValue }));
9024
9024
  }
@@ -9157,6 +9157,225 @@ const TableWidget = ({ config }) => {
9157
9157
  }, children: translate('common.cancel') || 'Cancel' })] }) })] }))] })] }) }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-sm mt-1", style: { color: 'var(--owt-widget-error-color, #B91C1C)' }, children: error[0] }))] })] }));
9158
9158
  };
9159
9159
 
9160
+ // Display select value label in view mode
9161
+ const SelectDisplayValue = ({ config, value }) => {
9162
+ const { dataSourceOptions, loading } = useBaseWidget({ config });
9163
+ if (loading)
9164
+ return jsxRuntimeExports.jsx("span", { children: "-" });
9165
+ if (value === null || value === undefined || value === '')
9166
+ return jsxRuntimeExports.jsx("span", { children: "-" });
9167
+ const selectedOption = dataSourceOptions.find((option) => option.value === value);
9168
+ return jsxRuntimeExports.jsx("span", { children: selectedOption ? selectedOption.label : String(value) });
9169
+ };
9170
+ /**
9171
+ * Dialog table widget:
9172
+ * - Table displays a subset of columns (n out of x)
9173
+ * - Add/Edit happens in a modal dialog that shows ALL columns as a form
9174
+ *
9175
+ * Usage in schema:
9176
+ * {
9177
+ * "widget": "dialog-table",
9178
+ * "widget-type": "table",
9179
+ * "widget-label": "Household Members",
9180
+ * "widget-id": "householdMembers",
9181
+ * "widget-data-path": "household.members",
9182
+ * "widget-data-columns": [ ...all columns... ],
9183
+ * "widget-data-visible-columns": ["firstName", "lastName", "dob"], // optional override; default = by column flag
9184
+ * // Per-column control (recommended): set "column-visible-in-table": false to hide it in the table
9185
+ * "widget-data-operations": { "add": true, "edit": true, "remove": true }
9186
+ * }
9187
+ */
9188
+ const DialogTableWidget = ({ config }) => {
9189
+ const { value, error, touched, isEnabled, onChange, config: widgetConfig } = useBaseWidget({ config });
9190
+ const { translate, translateConfig } = useWidgetTranslation();
9191
+ const rows = Array.isArray(value) ? value : [];
9192
+ const columns = widgetConfig['widget-data-columns'] || [];
9193
+ const operations = widgetConfig['widget-data-operations'] || {};
9194
+ const isReadonly = widgetConfig['widget-readonly'] || false;
9195
+ const visibleColumnKeys = widgetConfig['widget-data-visible-columns'];
9196
+ const visibleColumns = useMemo(() => {
9197
+ // 1) If explicit list provided, it wins
9198
+ if (Array.isArray(visibleColumnKeys) && visibleColumnKeys.length > 0) {
9199
+ const keySet = new Set(visibleColumnKeys);
9200
+ return columns.filter((c) => keySet.has(c['column-key']));
9201
+ }
9202
+ // 2) Otherwise decide per column (default = visible)
9203
+ return columns.filter((c) => c['column-visible-in-table'] !== false);
9204
+ }, [columns, visibleColumnKeys]);
9205
+ const [dialogOpen, setDialogOpen] = useState(false);
9206
+ const [dialogMode, setDialogMode] = useState('add');
9207
+ const [activeRowIndex, setActiveRowIndex] = useState(null);
9208
+ const [formData, setFormData] = useState({});
9209
+ const addDialogTitle = translateConfig(widgetConfig['widget-data-dialog-title-add']) ||
9210
+ translate('table.addRecordDialog') ||
9211
+ 'Add record';
9212
+ const editDialogTitle = translateConfig(widgetConfig['widget-data-dialog-title-edit']) ||
9213
+ translate('table.editRecordDialog') ||
9214
+ 'Edit record';
9215
+ const buildEmptyRow = useCallback(() => {
9216
+ const emptyRow = {};
9217
+ columns.forEach((col) => {
9218
+ const key = col['column-key'];
9219
+ emptyRow[key] = col['widget-data-default'] ?? '';
9220
+ });
9221
+ return emptyRow;
9222
+ }, [columns]);
9223
+ const openAddDialog = useCallback(() => {
9224
+ setDialogMode('add');
9225
+ setActiveRowIndex(null);
9226
+ setFormData(buildEmptyRow());
9227
+ setDialogOpen(true);
9228
+ }, [buildEmptyRow]);
9229
+ const openEditDialog = useCallback((rowIndex) => {
9230
+ const row = rows[rowIndex] || {};
9231
+ const nextFormData = buildEmptyRow();
9232
+ columns.forEach((col) => {
9233
+ const key = col['column-key'];
9234
+ if (row[key] !== undefined)
9235
+ nextFormData[key] = row[key];
9236
+ });
9237
+ setDialogMode('edit');
9238
+ setActiveRowIndex(rowIndex);
9239
+ setFormData(nextFormData);
9240
+ setDialogOpen(true);
9241
+ }, [rows, columns, buildEmptyRow]);
9242
+ const closeDialog = useCallback(() => {
9243
+ setDialogOpen(false);
9244
+ setActiveRowIndex(null);
9245
+ setFormData({});
9246
+ }, []);
9247
+ const updateField = useCallback((columnKey, newValue) => {
9248
+ setFormData((prev) => ({ ...prev, [columnKey]: newValue }));
9249
+ }, []);
9250
+ const saveDialog = useCallback(() => {
9251
+ if (dialogMode === 'add') {
9252
+ const savedRow = { ...formData, edit_action: 'ADD' };
9253
+ onChange([...rows, savedRow]);
9254
+ closeDialog();
9255
+ return;
9256
+ }
9257
+ if (dialogMode === 'edit' && activeRowIndex !== null) {
9258
+ const newRows = [...rows];
9259
+ const currentRow = newRows[activeRowIndex] || {};
9260
+ const wasDeleted = currentRow.edit_action === 'DELETE';
9261
+ const editAction = wasDeleted ? 'UPDATE' : (currentRow.edit_action ?? 'UPDATE');
9262
+ newRows[activeRowIndex] = { ...currentRow, ...formData, edit_action: editAction };
9263
+ onChange(newRows);
9264
+ closeDialog();
9265
+ }
9266
+ }, [dialogMode, formData, onChange, rows, closeDialog, activeRowIndex]);
9267
+ const deleteRow = useCallback((rowIndex) => {
9268
+ const newRows = rows.filter((_, i) => i !== rowIndex);
9269
+ onChange(newRows);
9270
+ }, [rows, onChange]);
9271
+ const getDisplayValue = useCallback((rowIndex, column) => {
9272
+ const key = column['column-key'];
9273
+ const cellValue = rows[rowIndex]?.[key];
9274
+ const widgetType = column.widget || 'text';
9275
+ if (cellValue === null || cellValue === undefined || cellValue === '')
9276
+ return '-';
9277
+ if (widgetType === 'select')
9278
+ return null; // handled by SelectDisplayValue
9279
+ if (column['widget-data-format'])
9280
+ return formatValue(cellValue, column['widget-data-format'], column.widget);
9281
+ return String(cellValue);
9282
+ }, [rows]);
9283
+ const tableWidgetId = `dialog-table-widget-${widgetConfig['widget-id']}`;
9284
+ const columnSpan = widgetConfig['widget-column-span'] || 2;
9285
+ const minWidth = columnSpan * 200;
9286
+ return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
9287
+ .${tableWidgetId} {
9288
+ width: 100%;
9289
+ min-width: ${minWidth}px;
9290
+ }
9291
+
9292
+ .widget-container[data-widget-id="${widgetConfig['widget-id']}"] {
9293
+ min-width: ${minWidth}px;
9294
+ width: 100%;
9295
+ flex: none;
9296
+ }
9297
+
9298
+ .panel-horizontal .widget-container[data-widget-id="${widgetConfig['widget-id']}"],
9299
+ [data-panel-orientation="horizontal"] .widget-container[data-widget-id="${widgetConfig['widget-id']}"] {
9300
+ grid-column: span ${columnSpan};
9301
+ }
9302
+ ` }), jsxRuntimeExports.jsxs("div", { className: `table-widget-container ${tableWidgetId}`, children: [operations.add && !isReadonly && isEnabled && (jsxRuntimeExports.jsx("div", { className: "flex justify-end mb-2", children: jsxRuntimeExports.jsx("button", { type: "button", onClick: openAddDialog, className: "px-3 py-1 text-sm disabled:opacity-50 disabled:cursor-not-allowed", style: {
9303
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
9304
+ border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
9305
+ backgroundColor: 'var(--owt-color-primary, #F5BB1A)',
9306
+ color: 'var(--owt-color-bg, #FFFFFF)',
9307
+ }, children: translate('table.addRecord') || 'Add New Record' }) })), jsxRuntimeExports.jsx("div", { className: "overflow-x-auto border", style: {
9308
+ borderRadius: 'var(--owt-widget-table-border-radius, 15px)',
9309
+ borderColor: 'var(--owt-widget-table-border-color, #C4C4C4)',
9310
+ }, 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: {
9311
+ borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)',
9312
+ backgroundColor: row?.edit_action === 'DELETE'
9313
+ ? 'var(--owt-widget-table-deleted-row-bg, #FEE2E2)'
9314
+ : undefined,
9315
+ }, children: [visibleColumns.map((col) => {
9316
+ const key = col['column-key'];
9317
+ const widgetType = col.widget || 'text';
9318
+ const displayValue = getDisplayValue(rowIndex, col);
9319
+ if (widgetType === 'select' && displayValue === null) {
9320
+ const displayConfig = {
9321
+ ...col,
9322
+ 'widget-id': `${widgetConfig['widget-id']}-view-row-${rowIndex}-col-${key}`,
9323
+ 'widget-label': '',
9324
+ 'widget-readonly': true,
9325
+ 'widget-data-path': undefined,
9326
+ };
9327
+ 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));
9328
+ }
9329
+ return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsx("div", { className: "text-sm", children: displayValue }) }, key));
9330
+ }), ((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: {
9331
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
9332
+ color: 'var(--owt-color-primary-dark, #F07B1A)',
9333
+ backgroundColor: 'transparent',
9334
+ border: 'none',
9335
+ }, 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: {
9336
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
9337
+ color: 'var(--owt-color-error, #B91C1C)',
9338
+ backgroundColor: 'transparent',
9339
+ border: 'none',
9340
+ }, 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: {
9341
+ maxWidth: '900px',
9342
+ backgroundColor: 'var(--owt-color-bg, #FFFFFF)',
9343
+ borderRadius: 'var(--owt-widget-card-border-radius, 20px)',
9344
+ }, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-4 mb-4", children: [jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold", style: { color: 'var(--owt-color-text, #011627)' }, children: dialogMode === 'add' ? addDialogTitle : editDialogTitle }), jsxRuntimeExports.jsx("button", { type: "button", onClick: closeDialog, style: {
9345
+ border: 'none',
9346
+ background: 'transparent',
9347
+ color: 'var(--owt-color-text-muted, #727474)',
9348
+ cursor: 'pointer',
9349
+ fontSize: '20px',
9350
+ lineHeight: 1,
9351
+ }, "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) => {
9352
+ const key = col['column-key'];
9353
+ const widgetType = col.widget || 'text';
9354
+ const cellWidgetId = `${widgetConfig['widget-id']}-dialog-${dialogMode}-${key}`;
9355
+ const fieldConfig = {
9356
+ ...col,
9357
+ widget: widgetType,
9358
+ 'widget-type': col['widget-type'] || 'input',
9359
+ 'widget-id': cellWidgetId,
9360
+ 'widget-label': col['widget-label'],
9361
+ 'widget-readonly': isReadonly || col['widget-readonly'] === true,
9362
+ 'widget-data-path': undefined,
9363
+ 'widget-data-default': formData[key] ?? col['widget-data-default'] ?? '',
9364
+ };
9365
+ return (jsxRuntimeExports.jsx("div", { className: "min-w-0", children: jsxRuntimeExports.jsx(WidgetRenderer, { config: fieldConfig, schemaData: { [cellWidgetId]: formData[key] ?? col['widget-data-default'] ?? '' }, onValueChange: (_widgetId, newValue) => updateField(key, newValue) }) }, key));
9366
+ }) }), 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: {
9367
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
9368
+ border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
9369
+ backgroundColor: 'var(--owt-btn-secondary-bg, #FFFFFF)',
9370
+ color: 'var(--owt-btn-secondary-color, #011627)',
9371
+ }, children: translate('common.cancel') || 'Cancel' }), jsxRuntimeExports.jsx("button", { type: "button", onClick: saveDialog, disabled: isReadonly || !isEnabled, className: "px-4 py-2 text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed", style: {
9372
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
9373
+ border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
9374
+ backgroundColor: 'var(--owt-color-primary, #F5BB1A)',
9375
+ color: 'var(--owt-color-bg, #FFFFFF)',
9376
+ }, children: translate('common.save') || 'Save' })] })] }) }))] }));
9377
+ };
9378
+
9160
9379
  const ProfileWidget = ({ config }) => {
9161
9380
  const { value, config: widgetConfig, getFieldValue, } = useBaseWidget({ config });
9162
9381
  const { translateConfig } = useWidgetTranslation();
@@ -9570,6 +9789,68 @@ const HeaderSectionWidget = ({ config }) => {
9570
9789
  const createdAt = findValue('createdAt') || '';
9571
9790
  const lastApprovedBy = findValue('lastApprovedBy') || '';
9572
9791
  const lastApprovedAt = findValue('lastApprovedAt') || '';
9792
+ // ── Validation: status change requires reason ──────────────────
9793
+ // Behavior:
9794
+ // - When status changes away from its initial value, clear reason and require it.
9795
+ // - When status returns to initial value (or a parent "Cancel" restores it), restore initial reason.
9796
+ const initialStatusRef = useRef(null);
9797
+ const initialReasonRef = useRef(null);
9798
+ const prevStatusRef = useRef(null);
9799
+ const [showReasonRequired, setShowReasonRequired] = useState(false);
9800
+ useEffect(() => {
9801
+ // Capture initial status once when it becomes available.
9802
+ if (initialStatusRef.current === null) {
9803
+ const v = statusValue === undefined || statusValue === null ? '' : String(statusValue);
9804
+ initialStatusRef.current = v;
9805
+ }
9806
+ }, [statusValue]);
9807
+ useEffect(() => {
9808
+ // Capture initial reason once when it becomes available.
9809
+ if (initialReasonRef.current === null) {
9810
+ const v = statusReason === undefined || statusReason === null ? '' : String(statusReason);
9811
+ initialReasonRef.current = v;
9812
+ }
9813
+ }, [statusReason]);
9814
+ const isStatusChanged = useMemo(() => {
9815
+ const initial = initialStatusRef.current;
9816
+ if (initial === null)
9817
+ return false;
9818
+ return String(statusValue) !== initial;
9819
+ }, [statusValue]);
9820
+ const isReasonMissing = useMemo(() => {
9821
+ if (!isStatusChanged)
9822
+ return false;
9823
+ return String(statusReason || '').trim().length === 0;
9824
+ }, [isStatusChanged, statusReason]);
9825
+ useEffect(() => {
9826
+ // When status changes:
9827
+ // - If moved away from initial → clear reason.
9828
+ // - If returned to initial → restore initial reason.
9829
+ if (isReadonly)
9830
+ return;
9831
+ if (initialStatusRef.current === null)
9832
+ return;
9833
+ const currentStatus = String(statusValue || '');
9834
+ if (prevStatusRef.current === currentStatus)
9835
+ return;
9836
+ prevStatusRef.current = currentStatus;
9837
+ const initialStatus = initialStatusRef.current;
9838
+ const initialReason = initialReasonRef.current ?? '';
9839
+ if (currentStatus === initialStatus) {
9840
+ // Reverted / cancelled back to original
9841
+ if (String(statusReason || '') !== String(initialReason || '')) {
9842
+ updateFieldValue('statusReason', initialReason);
9843
+ }
9844
+ setShowReasonRequired(false);
9845
+ return;
9846
+ }
9847
+ // Status changed to a new value: clear reason (so user must re-enter)
9848
+ if (String(statusReason || '').trim().length > 0) {
9849
+ updateFieldValue('statusReason', '');
9850
+ }
9851
+ setShowReasonRequired(true);
9852
+ // eslint-disable-next-line react-hooks/exhaustive-deps
9853
+ }, [statusValue, isReadonly]);
9573
9854
  const score = useMemo(() => {
9574
9855
  const toNum = (v) => {
9575
9856
  if (v === null || v === undefined || String(v).trim() === '')
@@ -9879,6 +10160,19 @@ const HeaderSectionWidget = ({ config }) => {
9879
10160
  box-shadow: 0 0 0 2px rgba(237, 124, 34, 0.15);
9880
10161
  }
9881
10162
 
10163
+ .${cls} .hdr-input--error {
10164
+ border-color: var(--owt-color-danger, #DC2626);
10165
+ box-shadow: 0 0 0 2px rgba(220, 38, 38, 0.12);
10166
+ }
10167
+
10168
+ .${cls} .hdr-error-text {
10169
+ margin-left: calc(0px);
10170
+ color: var(--owt-color-danger, #DC2626);
10171
+ font-size: 0.75rem;
10172
+ line-height: 1.2;
10173
+ font-weight: 500;
10174
+ }
10175
+
9882
10176
  @media (max-width: 768px) {
9883
10177
  .${cls} {
9884
10178
  flex-direction: column;
@@ -9893,7 +10187,15 @@ const HeaderSectionWidget = ({ config }) => {
9893
10187
  .parentElement?.querySelector('.hdr-avatar-placeholder');
9894
10188
  if (placeholder)
9895
10189
  placeholder.style.display = 'flex';
9896
- } })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: displayImageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) }), !isReadonly && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "hdr-avatar-overlay", children: [jsxRuntimeExports.jsxs("button", { type: "button", className: "hdr-avatar-action", onClick: () => fileInputRef.current?.click(), children: [jsxRuntimeExports.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), jsxRuntimeExports.jsx("polyline", { points: "17 8 12 3 7 8" }), jsxRuntimeExports.jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })] }), "Upload"] }), jsxRuntimeExports.jsxs("button", { type: "button", className: "hdr-avatar-action hdr-avatar-action--delete", onClick: handleImageDelete, children: [jsxRuntimeExports.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("polyline", { points: "3 6 5 6 21 6" }), jsxRuntimeExports.jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })] }), "Delete"] })] }), jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: 'none' }, onChange: handleImageUpload })] }))] }), jsxRuntimeExports.jsxs("div", { className: "hdr-info", children: [displayName && jsxRuntimeExports.jsx("div", { className: "hdr-name", children: displayName }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('functionalId'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: functionalId || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx("span", { className: "hdr-field-label", children: getLabel('status') }), isReadonly ? (statusLabel ? (jsxRuntimeExports.jsx("span", { className: "hdr-status-badge", style: { backgroundColor: statusColor }, children: statusLabel })) : (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: "-" }))) : (jsxRuntimeExports.jsxs("select", { className: "hdr-select", value: statusValue, onChange: (e) => updateFieldValue('status', e.target.value), children: [jsxRuntimeExports.jsx("option", { value: "", children: getLabel('select') }), statusOptions.map((opt) => (jsxRuntimeExports.jsx("option", { value: opt.value, children: opt.label }, opt.value)))] }))] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('statusReason'), " :"] }), isReadonly ? (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: statusReason || '-' })) : (jsxRuntimeExports.jsx("input", { type: "text", className: "hdr-input", value: statusReason, placeholder: getLabel('enterReason'), onChange: (e) => updateFieldValue('statusReason', e.target.value) }))] })] })] }), jsxRuntimeExports.jsx("div", { className: "hdr-right", children: jsxRuntimeExports.jsxs("div", { className: "hdr-right-top", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-col", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdAt || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedAt || '-' })] })] }), score ? (jsxRuntimeExports.jsx("div", { className: "hdr-score-ring", style: { ['--pct']: score.percent }, "aria-label": `Completion score ${score.completion} of ${score.ideal} (${score.percent}%)`, title: `${score.completion} / ${score.ideal} (${score.percent}%)`, children: jsxRuntimeExports.jsx("div", { className: "hdr-score-value", children: String(score.completion) }) })) : null] }) })] })] }));
10190
+ } })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: displayImageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) }), !isReadonly && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "hdr-avatar-overlay", children: [jsxRuntimeExports.jsxs("button", { type: "button", className: "hdr-avatar-action", onClick: () => fileInputRef.current?.click(), children: [jsxRuntimeExports.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), jsxRuntimeExports.jsx("polyline", { points: "17 8 12 3 7 8" }), jsxRuntimeExports.jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })] }), "Upload"] }), jsxRuntimeExports.jsxs("button", { type: "button", className: "hdr-avatar-action hdr-avatar-action--delete", onClick: handleImageDelete, children: [jsxRuntimeExports.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("polyline", { points: "3 6 5 6 21 6" }), jsxRuntimeExports.jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })] }), "Delete"] })] }), jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: 'none' }, onChange: handleImageUpload })] }))] }), jsxRuntimeExports.jsxs("div", { className: "hdr-info", children: [displayName && jsxRuntimeExports.jsx("div", { className: "hdr-name", children: displayName }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('functionalId'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: functionalId || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx("span", { className: "hdr-field-label", children: getLabel('status') }), isReadonly ? (statusLabel ? (jsxRuntimeExports.jsx("span", { className: "hdr-status-badge", style: { backgroundColor: statusColor }, children: statusLabel })) : (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: "-" }))) : (jsxRuntimeExports.jsxs("select", { className: "hdr-select", value: statusValue, onChange: (e) => updateFieldValue('status', e.target.value), children: [jsxRuntimeExports.jsx("option", { value: "", children: getLabel('select') }), statusOptions.map((opt) => (jsxRuntimeExports.jsx("option", { value: opt.value, children: opt.label }, opt.value)))] }))] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('statusReason'), " :"] }), isReadonly ? (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: statusReason || '-' })) : (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [jsxRuntimeExports.jsx("input", { type: "text", className: `hdr-input ${(!isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing) ? 'hdr-input--error' : ''}`, value: statusReason, placeholder: getLabel('enterReason'), required: isStatusChanged, "aria-required": isStatusChanged, "aria-invalid": !isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing, onBlur: () => {
10191
+ if (isReasonMissing)
10192
+ setShowReasonRequired(true);
10193
+ }, onChange: (e) => {
10194
+ updateFieldValue('statusReason', e.target.value);
10195
+ if (showReasonRequired && String(e.target.value || '').trim().length > 0) {
10196
+ setShowReasonRequired(false);
10197
+ }
10198
+ } }), !isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing ? (jsxRuntimeExports.jsx("div", { className: "hdr-error-text", children: getLabel('enterReason') })) : null] }))] })] })] }), jsxRuntimeExports.jsx("div", { className: "hdr-right", children: jsxRuntimeExports.jsxs("div", { className: "hdr-right-top", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-col", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdAt || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedAt || '-' })] })] }), score ? (jsxRuntimeExports.jsx("div", { className: "hdr-score-ring", style: { ['--pct']: score.percent }, "aria-label": `Completion score ${score.completion} of ${score.ideal} (${score.percent}%)`, title: `${score.completion} / ${score.ideal} (${score.percent}%)`, children: jsxRuntimeExports.jsx("div", { className: "hdr-score-value", children: String(score.completion) }) })) : null] }) })] })] }));
9897
10199
  };
9898
10200
 
9899
10201
  function getValueByPathOrKey(obj, path) {
@@ -10194,7 +10496,8 @@ function pickAuthorizationUrl(resp, explicitKey) {
10194
10496
  if (v)
10195
10497
  return v;
10196
10498
  }
10197
- return (tryKey('authorization_url') ||
10499
+ return (tryKey('authentication_url') ||
10500
+ tryKey('authorization_url') ||
10198
10501
  tryKey('authorizationUrl') ||
10199
10502
  tryKey('auth_url') ||
10200
10503
  tryKey('authUrl') ||
@@ -10209,12 +10512,14 @@ function resolveValueFromSources(path, values, schemaData) {
10209
10512
  return fromValues;
10210
10513
  return getValueByPath(schemaData, path);
10211
10514
  }
10212
- async function fetchProviderAuthorizationUrl(authConfig, dataSourceRequestHandler, _values, _schemaData) {
10213
- const response = await dataSourceRequestHandler(authConfig.service, authConfig.endpoint, authConfig.method || 'GET', {});
10214
- const payload = response?.response_body?.response_payload && typeof response.response_body.response_payload === 'object'
10215
- ? response.response_body.response_payload
10216
- : response;
10217
- return pickAuthorizationUrl(payload, authConfig.authorizationUrlKey);
10515
+ function unwrapPayload(response) {
10516
+ if (response && typeof response === 'object') {
10517
+ if (response.response_body?.response_payload !== undefined)
10518
+ return response.response_body.response_payload;
10519
+ if (response.response_payload !== undefined)
10520
+ return response.response_payload;
10521
+ }
10522
+ return response;
10218
10523
  }
10219
10524
  const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10220
10525
  const { dataSourceRequestHandler, schemaData: ctxSchemaData } = useWidgetContext();
@@ -10228,6 +10533,11 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10228
10533
  return dataPath;
10229
10534
  }, [dataPath]);
10230
10535
  const authConfig = config['widget-auth-config'];
10536
+ const registerId = resolveValueFromSources(paths.registerId, values, schemaData);
10537
+ const internalRecordId = resolveValueFromSources(paths.internalRecordId, values, schemaData);
10538
+ const initiatedByStaffId = resolveValueFromSources(paths.initiatedByStaffId, values, schemaData);
10539
+ const providerId = authConfig?.providerId;
10540
+ const providerName = authConfig?.providerName;
10231
10541
  const foundationalId = resolveValueFromSources(paths.foundationalId, values, schemaData);
10232
10542
  const lastAuthenticatedOn = resolveValueFromSources(paths.lastAuthenticatedOn, values, schemaData);
10233
10543
  const lastAuthStatusRaw = resolveValueFromSources(paths.lastAuthenticationStatus, values, schemaData);
@@ -10236,11 +10546,11 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10236
10546
  const status = useMemo(() => normalizeStatus(lastAuthStatusRaw), [lastAuthStatusRaw]);
10237
10547
  /** URL from prefetch (or default); used when opening the OIDC / eSignet popup */
10238
10548
  const [resolvedAuthUrl, setResolvedAuthUrl] = useState(null);
10239
- const [providerLoading, setProviderLoading] = useState(false);
10240
10549
  const [authActionLoading, setAuthActionLoading] = useState(false);
10241
10550
  const [authError, setAuthError] = useState(null);
10242
10551
  const popupRef = useRef(null);
10243
10552
  const pollTimerRef = useRef(null);
10553
+ const [overlayUrl, setOverlayUrl] = useState(null);
10244
10554
  const emitHostEvent = useCallback((detail) => {
10245
10555
  if (typeof window === 'undefined')
10246
10556
  return;
@@ -10269,72 +10579,16 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10269
10579
  }
10270
10580
  };
10271
10581
  }, [cleanupPopup]);
10272
- const prefetchKey = useMemo(() => {
10273
- if (!authConfig)
10274
- return 'no-config';
10275
- return JSON.stringify({
10276
- s: authConfig.service,
10277
- e: authConfig.endpoint,
10278
- m: authConfig.method,
10279
- def: authConfig.defaultAuthorizationUrl,
10280
- prefetch: authConfig.prefetchOnMount,
10281
- });
10282
- }, [authConfig]);
10283
- // Prefetch provider login URL on mount (and when params / config change)
10582
+ // Provider details are supplied by host; clear any previous resolved URL on provider change.
10284
10583
  useEffect(() => {
10285
- if (!authConfig) {
10286
- setResolvedAuthUrl(null);
10287
- setProviderLoading(false);
10288
- return;
10289
- }
10290
- if (authConfig.prefetchOnMount === false) {
10291
- setResolvedAuthUrl(authConfig.defaultAuthorizationUrl || null);
10292
- setProviderLoading(false);
10293
- return;
10294
- }
10295
- const def = authConfig.defaultAuthorizationUrl;
10296
- if (def) {
10297
- setResolvedAuthUrl(def);
10298
- }
10299
- const canCallApi = Boolean(dataSourceRequestHandler && authConfig.service && authConfig.endpoint);
10300
- if (!canCallApi) {
10301
- setProviderLoading(false);
10302
- if (!def) {
10303
- setResolvedAuthUrl(null);
10304
- }
10584
+ setResolvedAuthUrl(null);
10585
+ }, [providerId, providerName]);
10586
+ const openAuthPopup = useCallback((authUrl) => {
10587
+ if (authConfig?.useIframeOverlay !== false) {
10588
+ setOverlayUrl(authUrl);
10589
+ emitHostEvent({ type: 'overlay_opened' });
10305
10590
  return;
10306
10591
  }
10307
- let cancelled = false;
10308
- setProviderLoading(true);
10309
- (async () => {
10310
- try {
10311
- const url = await fetchProviderAuthorizationUrl(authConfig, dataSourceRequestHandler, values, schemaData);
10312
- if (cancelled)
10313
- return;
10314
- if (url) {
10315
- setResolvedAuthUrl(url);
10316
- }
10317
- else if (!def) {
10318
- setResolvedAuthUrl(null);
10319
- }
10320
- }
10321
- catch {
10322
- if (cancelled)
10323
- return;
10324
- if (!def) {
10325
- setResolvedAuthUrl(null);
10326
- }
10327
- }
10328
- finally {
10329
- if (!cancelled)
10330
- setProviderLoading(false);
10331
- }
10332
- })();
10333
- return () => {
10334
- cancelled = true;
10335
- };
10336
- }, [authConfig, dataSourceRequestHandler, prefetchKey, values, schemaData]);
10337
- const openAuthPopup = useCallback((authUrl) => {
10338
10592
  const pw = authConfig?.popupWidth ?? 1024;
10339
10593
  const ph = authConfig?.popupHeight ?? 800;
10340
10594
  const features = getCenteredPopupFeatures(pw, ph);
@@ -10370,20 +10624,24 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10370
10624
  setAuthError('Missing widget-auth-config.');
10371
10625
  return;
10372
10626
  }
10373
- const def = authConfig.defaultAuthorizationUrl;
10374
- const canCallApi = Boolean(dataSourceRequestHandler && authConfig.service && authConfig.endpoint);
10627
+ const canCallAuthApi = Boolean(dataSourceRequestHandler && authConfig.service && authConfig.authenticateEndpoint);
10375
10628
  let url = resolvedAuthUrl;
10376
- if (!url && canCallApi) {
10629
+ if (!url && canCallAuthApi) {
10377
10630
  setAuthActionLoading(true);
10378
10631
  try {
10379
- const fetched = await fetchProviderAuthorizationUrl(authConfig, dataSourceRequestHandler, values, schemaData);
10380
- url = fetched || def || null;
10381
- if (fetched) {
10382
- setResolvedAuthUrl(fetched);
10383
- }
10632
+ const resp = await dataSourceRequestHandler(authConfig.service, authConfig.authenticateEndpoint, authConfig.authenticateMethod || 'POST', {
10633
+ register_id: registerId,
10634
+ internal_record_id: internalRecordId,
10635
+ provider_id: authConfig.providerId,
10636
+ initiated_by_staff_id: initiatedByStaffId,
10637
+ });
10638
+ const payload = unwrapPayload(resp);
10639
+ const authUrl = pickAuthorizationUrl(payload, authConfig.authorizationUrlKey);
10640
+ url = authUrl || null;
10641
+ if (authUrl)
10642
+ setResolvedAuthUrl(authUrl);
10384
10643
  }
10385
10644
  catch (e) {
10386
- url = def || null;
10387
10645
  if (!url) {
10388
10646
  setAuthError(e?.message || 'Could not load provider URL.');
10389
10647
  return;
@@ -10393,15 +10651,20 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10393
10651
  setAuthActionLoading(false);
10394
10652
  }
10395
10653
  }
10396
- else if (!url) {
10397
- url = def || null;
10398
- }
10399
10654
  if (!url) {
10400
- setAuthError('No authorization URL. Set widget-auth-config (service + endpoint, or defaultAuthorizationUrl) and dataSourceRequestHandler on WidgetProvider if using the API.');
10655
+ setAuthError('No authorization URL returned from authenticate_registrant.');
10401
10656
  return;
10402
10657
  }
10403
10658
  openAuthPopup(url);
10404
- }, [authConfig, dataSourceRequestHandler, openAuthPopup, resolvedAuthUrl, values, schemaData]);
10659
+ }, [
10660
+ authConfig,
10661
+ dataSourceRequestHandler,
10662
+ openAuthPopup,
10663
+ registerId,
10664
+ internalRecordId,
10665
+ initiatedByStaffId,
10666
+ resolvedAuthUrl,
10667
+ ]);
10405
10668
  useEffect(() => {
10406
10669
  const successType = authConfig?.successMessageType || 'openg2p:oidc:success';
10407
10670
  const handler = (event) => {
@@ -10446,8 +10709,7 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10446
10709
  return 'var(--owt-color-warning, #D97706)';
10447
10710
  return 'var(--owt-color-text-muted, #6B7280)';
10448
10711
  }, [status]);
10449
- const buttonBusy = authActionLoading ||
10450
- (providerLoading && !resolvedAuthUrl && !authConfig?.defaultAuthorizationUrl);
10712
+ const buttonBusy = authActionLoading;
10451
10713
  const buttonDisabled = !authConfig || buttonBusy;
10452
10714
  return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
10453
10715
  .${cls} {
@@ -10483,6 +10745,14 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10483
10745
  grid-column: 1 / -1;
10484
10746
  }
10485
10747
 
10748
+ /* Action cell: no left label spacer, align button to column start */
10749
+ .${cls} .auth-cell.auth-cell--action .auth-label {
10750
+ display: none;
10751
+ }
10752
+ .${cls} .auth-cell.auth-cell--action .auth-value {
10753
+ flex: 1 1 auto;
10754
+ }
10755
+
10486
10756
  .${cls} .auth-label {
10487
10757
  flex: 0 0 auto;
10488
10758
  min-width: 200px;
@@ -10505,17 +10775,15 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10505
10775
  word-break: break-word;
10506
10776
  }
10507
10777
 
10508
- .${cls} .auth-bottom-actions {
10509
- display: flex;
10510
- flex-direction: column;
10511
- align-items: flex-start;
10512
- justify-content: flex-start;
10513
- gap: 8px;
10514
- width: 100%;
10515
- margin-top: 20px;
10516
- margin-bottom: 0;
10778
+ .${cls} .auth-value--foundational {
10779
+ font-size: 18px;
10780
+ font-weight: 700;
10781
+ color: var(--owt-color-primary-dark, #F07B1A);
10782
+ letter-spacing: 0.1px;
10517
10783
  }
10518
10784
 
10785
+ /* Button is placed inside the grid (next to PSUT) */
10786
+
10519
10787
  .${cls} .auth-status {
10520
10788
  display: inline-flex;
10521
10789
  align-items: center;
@@ -10556,8 +10824,8 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10556
10824
  padding: 8px 24px;
10557
10825
  line-height: 1.5;
10558
10826
  border-radius: var(--owt-btn-border-radius, 10px);
10559
- border: 1px solid var(--owt-btn-primary-border, #F07B1A);
10560
- background-color: var(--owt-color-primary, #F5BB1A);
10827
+ border: 1px solid rgb(237, 124, 34);
10828
+ background-color: rgb(237, 124, 34);
10561
10829
  color: var(--owt-color-bg, #FFFFFF);
10562
10830
  font-family: Roboto, sans-serif;
10563
10831
  cursor: pointer;
@@ -10578,6 +10846,63 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10578
10846
  max-width: 100%;
10579
10847
  }
10580
10848
 
10849
+ .${cls} .overlay-backdrop {
10850
+ position: fixed;
10851
+ inset: 0;
10852
+ background: rgba(17, 24, 39, 0.55);
10853
+ z-index: 9999;
10854
+ display: flex;
10855
+ align-items: center;
10856
+ justify-content: center;
10857
+ padding: 24px;
10858
+ }
10859
+
10860
+ .${cls} .overlay-panel {
10861
+ width: min(1100px, 92vw);
10862
+ height: min(820px, 92vh);
10863
+ background: var(--owt-color-bg, #FFFFFF);
10864
+ border-radius: 12px;
10865
+ box-shadow: 0 10px 30px rgba(0,0,0,0.25);
10866
+ overflow: hidden;
10867
+ display: flex;
10868
+ flex-direction: column;
10869
+ }
10870
+
10871
+ .${cls} .overlay-header {
10872
+ display: flex;
10873
+ align-items: center;
10874
+ justify-content: space-between;
10875
+ padding: 10px 14px;
10876
+ border-bottom: 1px solid var(--owt-color-border-light, #E4E4E4);
10877
+ font-family: Roboto, sans-serif;
10878
+ }
10879
+
10880
+ .${cls} .overlay-title {
10881
+ font-size: 14px;
10882
+ color: var(--owt-color-text, #011627);
10883
+ font-weight: 600;
10884
+ min-width: 0;
10885
+ overflow: hidden;
10886
+ text-overflow: ellipsis;
10887
+ white-space: nowrap;
10888
+ }
10889
+
10890
+ .${cls} .overlay-close {
10891
+ border: 1px solid var(--owt-btn-secondary-border, #C4C4C4);
10892
+ background: var(--owt-btn-secondary-bg, #FFFFFF);
10893
+ color: var(--owt-btn-secondary-color, #011627);
10894
+ border-radius: var(--owt-btn-border-radius, 10px);
10895
+ padding: 6px 10px;
10896
+ font-size: 12px;
10897
+ cursor: pointer;
10898
+ }
10899
+
10900
+ .${cls} .overlay-iframe {
10901
+ flex: 1 1 auto;
10902
+ width: 100%;
10903
+ border: none;
10904
+ }
10905
+
10581
10906
  @media (max-width: 640px) {
10582
10907
  .${cls} .auth-grid {
10583
10908
  grid-template-columns: 1fr;
@@ -10592,7 +10917,15 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
10592
10917
  max-width: none;
10593
10918
  }
10594
10919
  }
10595
- ` }), jsxRuntimeExports.jsx("div", { className: cls, children: jsxRuntimeExports.jsxs("div", { className: "auth-content", children: [jsxRuntimeExports.jsxs("div", { className: "auth-grid", children: [jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Foundational ID:" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: displayText(foundationalId) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Last authenticated on:" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: tryFormatDateTime(lastAuthenticatedOn) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Last authentication status:" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: jsxRuntimeExports.jsxs("div", { className: "auth-status", "aria-label": `Authentication status: ${statusLabel}`, children: [jsxRuntimeExports.jsx("span", { className: "auth-dot" }), jsxRuntimeExports.jsx("span", { children: statusLabel })] }) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Expiry date:" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: tryFormatDate(expiryDate) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell auth-cell--full", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Authentication token (PSUT):" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: jsxRuntimeExports.jsx("div", { className: "auth-token", children: psut ? String(psut) : '-' }) })] })] }), jsxRuntimeExports.jsxs("div", { className: "auth-bottom-actions", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "auth-button", onClick: onAuthenticate, disabled: buttonDisabled, children: buttonBusy ? 'Loading…' : 'Authenticate' }), authError ? jsxRuntimeExports.jsx("div", { className: "auth-error", children: authError }) : null] })] }) })] }));
10920
+ ` }), jsxRuntimeExports.jsxs("div", { className: cls, children: [overlayUrl ? (jsxRuntimeExports.jsx("div", { className: "overlay-backdrop", role: "dialog", "aria-modal": "true", "aria-label": "Authentication", onClick: (e) => {
10921
+ if (e.target === e.currentTarget) {
10922
+ setOverlayUrl(null);
10923
+ emitHostEvent({ type: 'overlay_closed' });
10924
+ }
10925
+ }, children: jsxRuntimeExports.jsxs("div", { className: "overlay-panel", children: [jsxRuntimeExports.jsxs("div", { className: "overlay-header", children: [jsxRuntimeExports.jsx("div", { className: "overlay-title", children: providerName ? `Authenticate via ${providerName}` : 'Authenticate' }), jsxRuntimeExports.jsx("button", { type: "button", className: "overlay-close", onClick: () => {
10926
+ setOverlayUrl(null);
10927
+ emitHostEvent({ type: 'overlay_closed' });
10928
+ }, children: "Close" })] }), jsxRuntimeExports.jsx("iframe", { className: "overlay-iframe", src: overlayUrl, title: "Authentication" })] }) })) : null, jsxRuntimeExports.jsx("div", { className: "auth-content", children: jsxRuntimeExports.jsxs("div", { className: "auth-grid", children: [jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Foundational ID:" }), jsxRuntimeExports.jsx("div", { className: "auth-value auth-value--foundational", children: displayText(foundationalId) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Last authenticated on:" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: tryFormatDateTime(lastAuthenticatedOn) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Expiry date:" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: tryFormatDate(expiryDate) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Last authentication status:" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: jsxRuntimeExports.jsxs("div", { className: "auth-status", "aria-label": `Authentication status: ${statusLabel}`, children: [jsxRuntimeExports.jsx("span", { className: "auth-dot" }), jsxRuntimeExports.jsx("span", { children: statusLabel })] }) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Authentication token (PSUT):" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: jsxRuntimeExports.jsx("div", { className: "auth-token", children: psut ? String(psut) : '-' }) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell auth-cell--action", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", "aria-hidden": true }), jsxRuntimeExports.jsxs("div", { className: "auth-value", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "auth-button", onClick: onAuthenticate, disabled: buttonDisabled, children: buttonBusy ? 'Loading…' : 'Authenticate' }), authError ? (jsxRuntimeExports.jsx("div", { className: "auth-error", style: { marginTop: 8 }, children: authError })) : null] })] })] }) })] })] }));
10596
10929
  };
10597
10930
 
10598
10931
  /**
@@ -10624,6 +10957,8 @@ const registerDefaultWidgets = () => {
10624
10957
  widgetRegistry.register({ widget: 'simple-table', component: SimpleTableWidget });
10625
10958
  // Table widget with record-level editing
10626
10959
  widgetRegistry.register({ widget: 'table', component: TableWidget });
10960
+ // Table widget with add/edit popup dialog
10961
+ widgetRegistry.register({ widget: 'dialog-table', component: DialogTableWidget });
10627
10962
  // Group widgets
10628
10963
  widgetRegistry.register({ widget: 'array-widget', component: ArrayWidget });
10629
10964
  widgetRegistry.register({ widget: 'iterable-accordion', component: IterableAccordionWidget });
@@ -11001,5 +11336,5 @@ const translateUISchema = (schema, translate) => {
11001
11336
  };
11002
11337
  };
11003
11338
 
11004
- export { ArrayWidget, BooleanWidget, CheckboxWidget, CurrencyInputWidget, DateInputWidget, DateTimeInputWidget, DisplayWidget, FileInputWidget, HeaderSectionWidget, IdAuthenticationWidget, IterableAccordionWidget, JSONEditorPanel, NumberInputWidget, PanelRenderer, PhoneInputWidget, ProfileWidget, PropertyEditor, RadioWidget, ScoresDisplayWidget, SectionBuilder, SectionRenderer, SectionTree, SectionsContainer, SelectWidget, SimpleTableWidget, TableWidget, TextAreaWidget, TextInputWidget, VisualBuilderPanel, WidgetEventBus, WidgetProvider, WidgetRenderer, applyCaseControl, applyDecimalPrecision, applyMask, createWidgetStore, createZodSchema, defaultTheme, evaluateCondition, filterByCharacterType, formatCurrency, formatDate, formatNumber, formatPhone, formatValue, geoHierarchyBuilder, getApiDataSource, getFormattedNumberLength, getSchemaDataSource, getStaticDataSource, getValueByPath, getWidgetValue, initI18n, isAllowedKey, parseDataPath, parseNumber, registerDefaultWidgets, removeMask, resetAll, resetWidget, resolveTheme, setDataSource, setError, setLoading, setTouched, setValue, setValueByPath, setValues, setWidgetValue, shouldEnableWidget, shouldShowWidget, transformDataSourceOptions, translatePanelConfig, translateUISchema, translateWidgetConfig, useBaseWidget, useGeoWidgetCascade, useWidgetCascade, useWidgetContext, useWidgetEventBus, useWidgetTheme, useWidgetTranslation, validateNumericValue, validateWidget, widgetRegistry };
11339
+ export { ArrayWidget, BooleanWidget, CheckboxWidget, CurrencyInputWidget, DateInputWidget, DateTimeInputWidget, DialogTableWidget, DisplayWidget, FileInputWidget, HeaderSectionWidget, IdAuthenticationWidget, IterableAccordionWidget, JSONEditorPanel, NumberInputWidget, PanelRenderer, PhoneInputWidget, ProfileWidget, PropertyEditor, RadioWidget, ScoresDisplayWidget, SectionBuilder, SectionRenderer, SectionTree, SectionsContainer, SelectWidget, SimpleTableWidget, TableWidget, TextAreaWidget, TextInputWidget, VisualBuilderPanel, WidgetEventBus, WidgetProvider, WidgetRenderer, applyCaseControl, applyDecimalPrecision, applyMask, createWidgetStore, createZodSchema, defaultTheme, evaluateCondition, filterByCharacterType, formatCurrency, formatDate, formatNumber, formatPhone, formatValue, geoHierarchyBuilder, getApiDataSource, getFormattedNumberLength, getSchemaDataSource, getStaticDataSource, getValueByPath, getWidgetValue, initI18n, isAllowedKey, parseDataPath, parseNumber, registerDefaultWidgets, removeMask, resetAll, resetWidget, resolveTheme, setDataSource, setError, setLoading, setTouched, setValue, setValueByPath, setValues, setWidgetValue, shouldEnableWidget, shouldShowWidget, transformDataSourceOptions, translatePanelConfig, translateUISchema, translateWidgetConfig, useBaseWidget, useGeoWidgetCascade, useWidgetCascade, useWidgetContext, useWidgetEventBus, useWidgetTheme, useWidgetTranslation, validateNumericValue, validateWidget, widgetRegistry };
11005
11340
  //# sourceMappingURL=index.esm.js.map