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