@openg2p/registry-widgets 1.0.1 → 1.1.0-dev.0

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
@@ -1676,6 +1676,158 @@ class WidgetEventBus {
1676
1676
  }
1677
1677
  }
1678
1678
 
1679
+ /**
1680
+ * Built-in default values (matches the original hardcoded colours).
1681
+ */
1682
+ const defaultTheme = {
1683
+ colors: {
1684
+ primary: '#F5BB1A',
1685
+ primaryDark: '#F07B1A',
1686
+ primaryLight: '#FBE6AA',
1687
+ primaryAccent: '#EE7C22',
1688
+ border: '#C4C4C4',
1689
+ borderLight: '#E4E4E4',
1690
+ background: '#FFFFFF',
1691
+ backgroundAlt: '#F6F6F6',
1692
+ text: '#011627',
1693
+ textMuted: '#727474',
1694
+ success: '#16A34A',
1695
+ successDark: '#047857',
1696
+ successLight: '#D1FAE5',
1697
+ error: '#B91C1C',
1698
+ errorLight: '#FEE2E2',
1699
+ warning: '#F59E0B',
1700
+ info: '#2563EB',
1701
+ },
1702
+ section: {
1703
+ borderRadius: '8px',
1704
+ borderColor: '#E4E4E4',
1705
+ backgroundColor: '#FFFFFF',
1706
+ titleColor: '#011627',
1707
+ dividerColor: '#F5BB1A',
1708
+ },
1709
+ panel: {
1710
+ dividerColor: '#C4C4C4',
1711
+ backgroundColor: 'transparent',
1712
+ },
1713
+ button: {
1714
+ primaryBg: '#FFFFFF',
1715
+ primaryColor: '#011627',
1716
+ primaryBorder: '#F07B1A',
1717
+ secondaryBg: '#FFFFFF',
1718
+ secondaryColor: '#011627',
1719
+ secondaryBorder: '#C4C4C4',
1720
+ borderRadius: '6px',
1721
+ },
1722
+ widget: {
1723
+ labelColor: '#011627',
1724
+ inputBorderColor: '#C4C4C4',
1725
+ inputFocusBorderColor: '#F5BB1A',
1726
+ inputBackground: '#FFFFFF',
1727
+ errorColor: '#B91C1C',
1728
+ helpTextColor: '#727474',
1729
+ tableHeaderBg: '#F6F6F6',
1730
+ tableHeaderColor: '#727474',
1731
+ tableBodyBg: '#FFFFFF',
1732
+ tableBorderColor: '#C4C4C4',
1733
+ tableRowDividerColor: '#E4E4E4',
1734
+ tableEditingRowBg: '#FBE6AA',
1735
+ tableDeletedRowBg: '#FEE2E2',
1736
+ tableEmptyTextColor: '#727474',
1737
+ tableBorderRadius: '15px',
1738
+ },
1739
+ };
1740
+ /**
1741
+ * Merge a user-supplied (partial) theme with the built-in defaults.
1742
+ */
1743
+ function resolveTheme(theme) {
1744
+ if (!theme)
1745
+ return defaultTheme;
1746
+ return {
1747
+ colors: { ...defaultTheme.colors, ...theme.colors },
1748
+ section: { ...defaultTheme.section, ...theme.section },
1749
+ panel: { ...defaultTheme.panel, ...theme.panel },
1750
+ button: { ...defaultTheme.button, ...theme.button },
1751
+ widget: { ...defaultTheme.widget, ...theme.widget },
1752
+ };
1753
+ }
1754
+ /**
1755
+ * Convert a resolved theme into a flat Record of CSS custom properties.
1756
+ * These are set on the provider wrapper element so every descendant can
1757
+ * reference them with `var(--owt-…)`.
1758
+ *
1759
+ * Prefix: `--owt-` (OpenG2P Widget Theme).
1760
+ */
1761
+ function themeToCSSVariables(resolved) {
1762
+ return {
1763
+ // --- colors ---
1764
+ '--owt-color-primary': resolved.colors.primary,
1765
+ '--owt-color-primary-dark': resolved.colors.primaryDark,
1766
+ '--owt-color-primary-light': resolved.colors.primaryLight,
1767
+ '--owt-color-primary-accent': resolved.colors.primaryAccent,
1768
+ '--owt-color-border': resolved.colors.border,
1769
+ '--owt-color-border-light': resolved.colors.borderLight,
1770
+ '--owt-color-bg': resolved.colors.background,
1771
+ '--owt-color-bg-alt': resolved.colors.backgroundAlt,
1772
+ '--owt-color-text': resolved.colors.text,
1773
+ '--owt-color-text-muted': resolved.colors.textMuted,
1774
+ '--owt-color-success': resolved.colors.success,
1775
+ '--owt-color-success-dark': resolved.colors.successDark,
1776
+ '--owt-color-success-light': resolved.colors.successLight,
1777
+ '--owt-color-error': resolved.colors.error,
1778
+ '--owt-color-error-light': resolved.colors.errorLight,
1779
+ '--owt-color-warning': resolved.colors.warning,
1780
+ '--owt-color-info': resolved.colors.info,
1781
+ // --- section ---
1782
+ '--owt-section-border-radius': resolved.section.borderRadius,
1783
+ '--owt-section-border-color': resolved.section.borderColor,
1784
+ '--owt-section-bg': resolved.section.backgroundColor,
1785
+ '--owt-section-title-color': resolved.section.titleColor,
1786
+ '--owt-section-divider-color': resolved.section.dividerColor,
1787
+ // --- panel ---
1788
+ '--owt-panel-divider-color': resolved.panel.dividerColor,
1789
+ '--owt-panel-bg': resolved.panel.backgroundColor,
1790
+ // --- button ---
1791
+ '--owt-btn-primary-bg': resolved.button.primaryBg,
1792
+ '--owt-btn-primary-color': resolved.button.primaryColor,
1793
+ '--owt-btn-primary-border': resolved.button.primaryBorder,
1794
+ '--owt-btn-secondary-bg': resolved.button.secondaryBg,
1795
+ '--owt-btn-secondary-color': resolved.button.secondaryColor,
1796
+ '--owt-btn-secondary-border': resolved.button.secondaryBorder,
1797
+ '--owt-btn-border-radius': resolved.button.borderRadius,
1798
+ // --- widget ---
1799
+ '--owt-widget-label-color': resolved.widget.labelColor,
1800
+ '--owt-widget-input-border': resolved.widget.inputBorderColor,
1801
+ '--owt-widget-input-focus-border': resolved.widget.inputFocusBorderColor,
1802
+ '--owt-widget-input-bg': resolved.widget.inputBackground,
1803
+ '--owt-widget-error-color': resolved.widget.errorColor,
1804
+ '--owt-widget-helptext-color': resolved.widget.helpTextColor,
1805
+ // --- widget / table ---
1806
+ '--owt-widget-table-header-bg': resolved.widget.tableHeaderBg,
1807
+ '--owt-widget-table-header-color': resolved.widget.tableHeaderColor,
1808
+ '--owt-widget-table-body-bg': resolved.widget.tableBodyBg,
1809
+ '--owt-widget-table-border-color': resolved.widget.tableBorderColor,
1810
+ '--owt-widget-table-row-divider': resolved.widget.tableRowDividerColor,
1811
+ '--owt-widget-table-editing-row-bg': resolved.widget.tableEditingRowBg,
1812
+ '--owt-widget-table-deleted-row-bg': resolved.widget.tableDeletedRowBg,
1813
+ '--owt-widget-table-empty-color': resolved.widget.tableEmptyTextColor,
1814
+ '--owt-widget-table-border-radius': resolved.widget.tableBorderRadius,
1815
+ };
1816
+ }
1817
+
1818
+ const ThemeContext = React.createContext(defaultTheme);
1819
+ /**
1820
+ * Access the resolved widget theme from any component inside `<WidgetProvider>`.
1821
+ *
1822
+ * ```tsx
1823
+ * const theme = useWidgetTheme();
1824
+ * // theme.colors.primary, theme.section.dividerColor, etc.
1825
+ * ```
1826
+ */
1827
+ function useWidgetTheme() {
1828
+ return React.useContext(ThemeContext);
1829
+ }
1830
+
1679
1831
  const WidgetContext = React.createContext({
1680
1832
  dataSourceRequestHandler: undefined,
1681
1833
  schemaData: undefined,
@@ -1684,10 +1836,13 @@ const WidgetContext = React.createContext({
1684
1836
  const useWidgetContext = () => {
1685
1837
  return React.useContext(WidgetContext);
1686
1838
  };
1687
- const WidgetProvider = ({ store, dataSourceRequestHandler, schemaData, translate, children, }) => {
1839
+ const WidgetProvider = ({ store, dataSourceRequestHandler, schemaData, translate, theme, children, }) => {
1688
1840
  const widgetStore = React.useMemo(() => store || createWidgetStore(), [store]);
1689
1841
  // Create event bus instance (one per provider)
1690
1842
  const eventBus = React.useMemo(() => new WidgetEventBus(), []);
1843
+ // Resolve theme: merge user-supplied overrides with defaults
1844
+ const resolvedTheme = React.useMemo(() => resolveTheme(theme), [theme]);
1845
+ const cssVariables = React.useMemo(() => themeToCSSVariables(resolvedTheme), [resolvedTheme]);
1691
1846
  // Memoize context value to prevent unnecessary re-renders
1692
1847
  const contextValue = React.useMemo(() => ({
1693
1848
  dataSourceRequestHandler,
@@ -1716,7 +1871,7 @@ const WidgetProvider = ({ store, dataSourceRequestHandler, schemaData, translate
1716
1871
  }
1717
1872
  // eslint-disable-next-line react-hooks/exhaustive-deps
1718
1873
  }, [schemaData, widgetStore]); // Only run on mount
1719
- const content = (jsxRuntimeExports.jsx(reactRedux.Provider, { store: widgetStore, children: jsxRuntimeExports.jsx(WidgetContext.Provider, { value: contextValue, children: jsxRuntimeExports.jsx(WidgetEventBusContext.Provider, { value: eventBus, children: children }) }) }));
1874
+ const content = (jsxRuntimeExports.jsx(reactRedux.Provider, { store: widgetStore, children: jsxRuntimeExports.jsx(ThemeContext.Provider, { value: resolvedTheme, children: jsxRuntimeExports.jsx(WidgetContext.Provider, { value: contextValue, children: jsxRuntimeExports.jsx(WidgetEventBusContext.Provider, { value: eventBus, children: jsxRuntimeExports.jsx("div", { className: "openg2p-widget-theme-root", style: cssVariables, children: children }) }) }) }) }));
1720
1875
  return content;
1721
1876
  };
1722
1877
 
@@ -2736,7 +2891,7 @@ const PanelRenderer = ({ panel, dataSourceRequestHandler, schemaData, onValueCha
2736
2891
  top: 0,
2737
2892
  bottom: '5px',
2738
2893
  width: '1px',
2739
- backgroundColor: isEditMode ? '#F2BA1A' : '#D1D5DB',
2894
+ backgroundColor: isEditMode ? 'var(--owt-color-primary, #F5BB1A)' : 'var(--owt-panel-divider-color, #C4C4C4)',
2740
2895
  } }))] }) }, nestedPanel['panel-id'] || `panel-${index}`));
2741
2896
  }), widgets.map((widgetConfig, index) => {
2742
2897
  // Don't use readonly state in key - it causes remounting which resets userHasSetValueRef
@@ -3298,10 +3453,10 @@ const FileInputWidget = ({ config }) => {
3298
3453
  return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("button", { type: "button", onClick: (e) => {
3299
3454
  console.log('Button clicked!', file);
3300
3455
  handleFileClick(file, e);
3301
- }, className: "text-sm hover:underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 rounded cursor-pointer", style: { color: isSupportingDocument ? '#000000' : '#2563eb' }, title: "Click to preview", children: fileName })] }));
3456
+ }, className: "text-sm hover:underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 rounded cursor-pointer", style: { color: isSupportingDocument ? 'var(--owt-color-text, #011627)' : 'var(--owt-color-info, #2563eb)' }, title: "Click to preview", children: fileName })] }));
3302
3457
  }
3303
3458
  else {
3304
- return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("span", { className: "text-sm", style: { color: isSupportingDocument ? '#000000' : '#4b5563' }, children: fileName })] }));
3459
+ return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("span", { className: "text-sm", style: { color: isSupportingDocument ? 'var(--owt-color-text, #011627)' : '#4b5563' }, children: fileName })] }));
3305
3460
  }
3306
3461
  }
3307
3462
  else {
@@ -3317,10 +3472,10 @@ const FileInputWidget = ({ config }) => {
3317
3472
  flexShrink: 0
3318
3473
  } }));
3319
3474
  if (canPreview) {
3320
- return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("button", { type: "button", onClick: (e) => handleFileClick(file, e), className: "text-sm hover:underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 rounded cursor-pointer", style: { color: isSupportingDocument ? '#000000' : '#2563eb' }, title: "Click to preview", children: fileName })] }, index));
3475
+ return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("button", { type: "button", onClick: (e) => handleFileClick(file, e), className: "text-sm hover:underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 rounded cursor-pointer", style: { color: isSupportingDocument ? 'var(--owt-color-text, #011627)' : 'var(--owt-color-info, #2563eb)' }, title: "Click to preview", children: fileName })] }, index));
3321
3476
  }
3322
3477
  else {
3323
- return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("span", { className: "text-sm", style: { color: isSupportingDocument ? '#000000' : '#4b5563' }, children: fileName })] }, index));
3478
+ return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("span", { className: "text-sm", style: { color: isSupportingDocument ? 'var(--owt-color-text, #011627)' : '#4b5563' }, children: fileName })] }, index));
3324
3479
  }
3325
3480
  }) }));
3326
3481
  }
@@ -3526,6 +3681,8 @@ const sectionValidate = (section, currentSchemaData, dispatch) => {
3526
3681
  */
3527
3682
  const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequestHandler, schemaData, onValueChange, gridColumnSpan, onSectionSave, hideEditButton = false, mode = 'RegistryView', namespace, changeRequestType, showChangeRequestLabel = true, dbSectionId, sectionRegisterId, onSectionDirtyChange, sectionIndex, sectionCount, expandedSectionIndex, onExpandSection, onSectionSaveSuccess, onPreviousSection, isDraft, onEditModeChange, forceExitEdit, }) => {
3528
3683
  const { translateConfig, translate } = useWidgetTranslation();
3684
+ const resolvedTheme = useWidgetTheme();
3685
+ const portalCSSVariables = React.useMemo(() => themeToCSSVariables(resolvedTheme), [resolvedTheme]);
3529
3686
  const { schemaData: contextSchemaData, dataSourceRequestHandler: contextDataSourceRequestHandler } = useWidgetContext();
3530
3687
  const store = reactRedux.useStore();
3531
3688
  const dispatch = reactRedux.useDispatch();
@@ -3542,22 +3699,41 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
3542
3699
  }
3543
3700
  return section;
3544
3701
  }, [section, namespace]);
3545
- // Create namespaced schemaData if namespace is provided.
3546
- // Widgets with namespaced data-paths (e.g. "rv-section-0.a1a4d25a.birth_date")
3547
- // need a nested object at values[namespace] so getValueByPath can traverse it.
3702
+ // Create namespaced schemaData if namespace is provided
3703
+ // This ensures widgets can read initial values from schemaData at namespaced paths
3548
3704
  const namespacedSchemaData = React.useMemo(() => {
3549
3705
  if (!namespace || !currentSchemaData) {
3550
3706
  return schemaData;
3551
3707
  }
3552
- return { ...currentSchemaData, [namespace]: currentSchemaData };
3708
+ // Create a namespaced version of schemaData by copying values to namespaced paths
3709
+ const namespaced = { ...currentSchemaData };
3710
+ // Copy all top-level keys to namespaced paths
3711
+ Object.keys(currentSchemaData).forEach(key => {
3712
+ const namespacedKey = `${namespace}.${key}`;
3713
+ if (!(namespacedKey in namespaced)) {
3714
+ namespaced[namespacedKey] = currentSchemaData[key];
3715
+ }
3716
+ });
3717
+ // Also handle nested objects - copy nested values to namespaced paths
3718
+ const copyNestedValues = (obj, prefix = '') => {
3719
+ if (obj && typeof obj === 'object' && !Array.isArray(obj)) {
3720
+ Object.keys(obj).forEach(key => {
3721
+ const fullPath = prefix ? `${prefix}.${key}` : key;
3722
+ const namespacedPath = `${namespace}.${fullPath}`;
3723
+ if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
3724
+ copyNestedValues(obj[key], fullPath);
3725
+ // Also set the nested object at the namespaced path
3726
+ setValueByPath(namespaced, namespacedPath, obj[key]);
3727
+ }
3728
+ else {
3729
+ setValueByPath(namespaced, namespacedPath, obj[key]);
3730
+ }
3731
+ });
3732
+ }
3733
+ };
3734
+ copyNestedValues(currentSchemaData);
3735
+ return namespaced;
3553
3736
  }, [namespace, schemaData, currentSchemaData]);
3554
- // Populate the store with namespaced schema data so that namespaced widgets
3555
- // can read their initial values via getValueByPath on the namespaced paths.
3556
- React.useEffect(() => {
3557
- if (namespace && namespacedSchemaData) {
3558
- dispatch(setValues(namespacedSchemaData));
3559
- }
3560
- }, [namespace, namespacedSchemaData, dispatch]);
3561
3737
  const crViewData = React.useMemo(() => {
3562
3738
  if (mode !== 'CRView')
3563
3739
  return null;
@@ -3803,9 +3979,10 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
3803
3979
  top: 0;
3804
3980
  bottom: 5px;
3805
3981
  width: 1px;
3806
- background-color: #F2BA1A;
3982
+ background-color: var(--owt-color-primary, #F5BB1A);
3807
3983
  }
3808
3984
  ` }), jsxRuntimeExports.jsxs("div", { className: `section ${sectionClassId} ${sectionClassId}-edit px-4 sm:px-6 lg:px-8`, "data-section-id": `${sectionId}-edit`, style: {
3985
+ ...portalCSSVariables,
3809
3986
  position: 'absolute',
3810
3987
  top: `${editSectionPosition.top}px`,
3811
3988
  left: `${editSectionPosition.left}px`,
@@ -3815,10 +3992,22 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
3815
3992
  }, children: [sectionToRender['section-title'] && (jsxRuntimeExports.jsx("h2", { className: "text-xl font-semibold mb-4", style: { fontFamily: 'Roboto, sans-serif', marginTop: '35px' }, children: translateConfig(sectionToRender['section-title']) })), jsxRuntimeExports.jsxs("div", { id: editGridId, className: "section-panels", children: [editableSection.panels.map((panel, index) => {
3816
3993
  const isLastPanel = index === editableSection.panels.length - 1;
3817
3994
  return (jsxRuntimeExports.jsx("div", { className: `panel-wrapper ${isLastPanel ? 'last-panel-wrapper' : ''}`, children: jsxRuntimeExports.jsx(PanelRenderer, { panel: panel, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: namespacedSchemaData, onValueChange: onValueChange, isEditMode: true }) }, panel['panel-id'] || `section-panel-${index}`));
3818
- }), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: '#F2BA1A', border: 'none', margin: '25px 0 0 0' } }), hasSupportingDocuments && (jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: jsxRuntimeExports.jsxs("div", { className: "supporting-documents-container", children: [jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setIsDocumentsExpanded(!isDocumentsExpanded), className: "supporting-documents-title-button w-full flex items-center text-left", children: [jsxRuntimeExports.jsx("span", { className: "font-semibold", style: { fontFamily: 'Roboto, sans-serif', fontSize: '16px' }, children: translate('common.supportedDocuments') || 'Supported Documents' }), jsxRuntimeExports.jsx("img", { src: isDocumentsExpanded ? img$7 : img$6, alt: "Toggle Documents", className: "w-4 h-2.25 transition-transform ml-2" })] }), isDocumentsExpanded && (jsxRuntimeExports.jsx("div", { className: "supporting-documents-grid mt-4", children: supportingDocuments.map((doc, index) => {
3995
+ }), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: 'var(--owt-section-divider-color, #F5BB1A)', border: 'none', margin: '25px 0 0 0' } }), hasSupportingDocuments && (jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: jsxRuntimeExports.jsxs("div", { className: "supporting-documents-container", children: [jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setIsDocumentsExpanded(!isDocumentsExpanded), className: "supporting-documents-title-button w-full flex items-center text-left", children: [jsxRuntimeExports.jsx("span", { className: "font-semibold", style: { fontFamily: 'Roboto, sans-serif', fontSize: '16px' }, children: translate('common.supportedDocuments') || 'Supported Documents' }), jsxRuntimeExports.jsx("img", { src: isDocumentsExpanded ? img$7 : img$6, alt: "Toggle Documents", className: "w-4 h-2.25 transition-transform ml-2" })] }), isDocumentsExpanded && (jsxRuntimeExports.jsx("div", { className: "supporting-documents-grid mt-4", children: supportingDocuments.map((doc, index) => {
3819
3996
  const docConfig = createDocumentWidgetConfig(doc, sectionId, index);
3820
3997
  return (jsxRuntimeExports.jsx("div", { className: "supporting-document-item", children: jsxRuntimeExports.jsx(FileInputWidget, { config: docConfig }) }, `${sectionId}-doc-${index}`));
3821
- }) }))] }) })), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: '#F2BA1A', border: 'none', marginTop: hasSupportingDocuments ? '20px' : 0, marginBottom: '20px' } }), jsxRuntimeExports.jsx("div", { className: "edit-controls-container", style: { marginBottom: '20px' }, children: jsxRuntimeExports.jsxs("div", { className: "edit-controls-buttons", children: [jsxRuntimeExports.jsx("button", { onClick: handleCancel, className: "bg-white hover:bg-gray-50 text-gray-900 text-sm font-medium px-6 py-2 transition-colors border border-gray-300", style: { fontFamily: 'Roboto, sans-serif', borderRadius: '10px' }, children: translate('common.cancel') || 'Cancel' }), jsxRuntimeExports.jsx("button", { onClick: handleSave, disabled: !isDirty, className: "bg-gray-900 hover:bg-gray-800 text-white text-sm font-medium px-6 py-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", style: { fontFamily: 'Roboto, sans-serif', borderRadius: '10px' }, children: translate('common.save') || 'Save' })] }) })] })] })] }), document.body);
3998
+ }) }))] }) })), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: 'var(--owt-section-divider-color, #F5BB1A)', border: 'none', marginTop: hasSupportingDocuments ? '20px' : 0, marginBottom: '20px' } }), jsxRuntimeExports.jsx("div", { className: "edit-controls-container", style: { marginBottom: '20px' }, children: jsxRuntimeExports.jsxs("div", { className: "edit-controls-buttons", children: [jsxRuntimeExports.jsx("button", { onClick: handleCancel, className: "text-sm font-medium px-6 py-2 transition-colors", style: {
3999
+ fontFamily: 'Roboto, sans-serif',
4000
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
4001
+ border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
4002
+ backgroundColor: 'var(--owt-btn-secondary-bg, #FFFFFF)',
4003
+ color: 'var(--owt-btn-secondary-color, #011627)',
4004
+ }, children: translate('common.cancel') || 'Cancel' }), jsxRuntimeExports.jsx("button", { onClick: handleSave, disabled: !isDirty, className: "text-sm font-medium px-6 py-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", style: {
4005
+ fontFamily: 'Roboto, sans-serif',
4006
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
4007
+ border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
4008
+ backgroundColor: 'var(--owt-color-primary, #F5BB1A)',
4009
+ color: 'var(--owt-color-bg, #FFFFFF)',
4010
+ }, children: translate('common.save') || 'Save' })] }) })] })] })] }), document.body);
3822
4011
  };
3823
4012
  const trackSectionChages = (widgets, sourceData, pathPrefix) => {
3824
4013
  if (!widgets || widgets.length === 0)
@@ -3919,8 +4108,6 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
3919
4108
  const baselineSnapshotRef = React.useRef(null);
3920
4109
  // IntakeForm only: increment when baseline is updated after save - forces badge to update (refs don't trigger re-renders)
3921
4110
  const [intakeFormBaselineTrigger, setIntakeFormBaselineTrigger] = React.useState(0);
3922
- // IntakeForm only: tracks whether the user has actually saved this section (prevents "Saved" badge on initial load)
3923
- const [hasBeenSavedByUser, setHasBeenSavedByUser] = React.useState(false);
3924
4111
  // IntakeForm: treat as edit mode for dirty tracking when isDraft. RegistryView: use isEditMode.
3925
4112
  const effectiveEditModeForDirty = mode === 'IntakeForm' ? (isDraft !== false) : isEditMode;
3926
4113
  // Compute isDirty: compare current store state to baseline (only when in edit mode)
@@ -3963,68 +4150,18 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
3963
4150
  const intakeFormSectionStatus = React.useMemo(() => {
3964
4151
  if (mode !== 'IntakeForm' || isDraft === false)
3965
4152
  return null;
4153
+ const hasValue = (v) => v !== undefined && v !== null && (typeof v !== 'string' || v.trim().length > 0);
4154
+ const currentSnapshot = buildSectionSnapshot(storeValues, namespace);
4155
+ const record = currentSnapshot.records?.[0];
4156
+ const hasData = record &&
4157
+ typeof record === 'object' &&
4158
+ Object.values(record).some((v) => hasValue(v));
3966
4159
  if (isDirty)
3967
4160
  return 'modified';
3968
- if (hasBeenSavedByUser)
4161
+ if (hasData)
3969
4162
  return 'saved';
3970
4163
  return null;
3971
- }, [mode, isDirty, hasBeenSavedByUser]);
3972
- // Revert store values to the original schemaData for this section's widgets.
3973
- // Used by both handleSave (RegistryView raises a CR, so values should not persist)
3974
- // and handleCancel.
3975
- const revertToOriginalValues = React.useCallback(() => {
3976
- const sectionWidgets = collectWidgets(originalSection.panels);
3977
- const oldSchemaData = schemaData || contextSchemaData;
3978
- const currentStoreValues = store.getState().widget.values;
3979
- let newStoreValues = currentStoreValues;
3980
- sectionWidgets.forEach(widget => {
3981
- const originalWidgetId = widget['widget-id'];
3982
- const namespacedWidgetId = namespace ? `${namespace}__${originalWidgetId}` : originalWidgetId;
3983
- const widgetId = namespacedWidgetId;
3984
- const originalDataPath = widget['widget-data-path'];
3985
- const storeDataPath = namespace && originalDataPath
3986
- ? (typeof originalDataPath === 'string'
3987
- ? `${namespace}.${originalDataPath}`
3988
- : Object.fromEntries(Object.entries(originalDataPath).map(([key, path]) => [key, `${namespace}.${path}`])))
3989
- : originalDataPath;
3990
- if (widgetId && originalDataPath) {
3991
- let oldValue;
3992
- if (typeof originalDataPath === 'object') {
3993
- oldValue = {};
3994
- Object.entries(originalDataPath).forEach(([key, path]) => {
3995
- if (typeof path === 'string') {
3996
- oldValue[key] = getValueByPath(oldSchemaData, path);
3997
- }
3998
- });
3999
- }
4000
- else if (typeof originalDataPath === 'string') {
4001
- oldValue = getValueByPath(oldSchemaData, originalDataPath);
4002
- }
4003
- if (oldValue !== undefined) {
4004
- newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
4005
- // Also revert the widgetId-based entry — useBaseWidget.handleChange
4006
- // sets values[widgetId] during editing, and useBaseWidget.currentValue
4007
- // reads values[widgetId] first before falling through to the dataPath.
4008
- newStoreValues = { ...newStoreValues, [widgetId]: oldValue };
4009
- }
4010
- }
4011
- });
4012
- if (hasSupportingDocuments) {
4013
- const originalSupportingDocuments = originalSection['section-supporting-documents'] || [];
4014
- originalSupportingDocuments.forEach((doc, index) => {
4015
- const widgetId = `supporting-doc-${sectionId}-${index}`;
4016
- const originalDataPath = doc['document-data-path'];
4017
- const storeDataPath = namespace && originalDataPath
4018
- ? `${namespace}.${originalDataPath}`
4019
- : originalDataPath;
4020
- const oldValue = getValueByPath(oldSchemaData, originalDataPath);
4021
- newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
4022
- });
4023
- }
4024
- if (newStoreValues !== currentStoreValues) {
4025
- dispatch(setValues(newStoreValues));
4026
- }
4027
- }, [originalSection, schemaData, contextSchemaData, store, namespace, hasSupportingDocuments, sectionId, dispatch]);
4164
+ }, [mode, isDirty, storeValues, namespace, buildSectionSnapshot]);
4028
4165
  // Handle save button click
4029
4166
  const handleSave = async () => {
4030
4167
  if (!store || !onSectionSave) {
@@ -4074,12 +4211,6 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4074
4211
  console.error('Section Changes Save failed', error);
4075
4212
  }
4076
4213
  }
4077
- // In RegistryView, save raises a CR — the actual data update follows a
4078
- // separate approval workflow, so revert the displayed values to the
4079
- // originals so the view doesn't show unapproved edits.
4080
- if (mode === 'RegistryView') {
4081
- revertToOriginalValues();
4082
- }
4083
4214
  setIsEditMode(false);
4084
4215
  onEditModeChange?.(originalSectionId, false);
4085
4216
  };
@@ -4125,7 +4256,6 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4125
4256
  if (mode === 'IntakeForm') {
4126
4257
  baselineSnapshotRef.current = buildSectionSnapshot(currentSchemaData, namespace);
4127
4258
  setIntakeFormBaselineTrigger((prev) => prev + 1);
4128
- setHasBeenSavedByUser(true);
4129
4259
  }
4130
4260
  onSectionDirtyChange?.(sectionId, false);
4131
4261
  }
@@ -4134,7 +4264,64 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4134
4264
  }, [store, onSectionSave, onSectionSaveSuccess, sectionIndex, originalSection, schemaData, contextSchemaData, namespace, hasSupportingDocuments, dbSectionId, sectionRegisterId, dispatch, buildSectionSnapshot, sectionId, onSectionDirtyChange, mode, isDraft]);
4135
4265
  // Handle cancel button click
4136
4266
  const handleCancel = () => {
4137
- revertToOriginalValues();
4267
+ // Revert values in store to original schema data
4268
+ // Use original section (without namespace) for collecting widgets
4269
+ const sectionWidgets = collectWidgets(originalSection.panels);
4270
+ const oldSchemaData = schemaData || contextSchemaData;
4271
+ const currentStoreValues = store.getState().widget.values;
4272
+ let newStoreValues = currentStoreValues;
4273
+ sectionWidgets.forEach(widget => {
4274
+ const originalWidgetId = widget['widget-id'];
4275
+ // If namespace was used, we need to use namespaced widget ID and data path
4276
+ const namespacedWidgetId = namespace ? `${namespace}__${originalWidgetId}` : originalWidgetId;
4277
+ const widgetId = namespacedWidgetId;
4278
+ const originalDataPath = widget['widget-data-path'];
4279
+ // If namespace was used, data path in store is namespaced, but we read from original schema using original path
4280
+ const storeDataPath = namespace && originalDataPath
4281
+ ? (typeof originalDataPath === 'string'
4282
+ ? `${namespace}.${originalDataPath}`
4283
+ : Object.fromEntries(Object.entries(originalDataPath).map(([key, path]) => [key, `${namespace}.${path}`])))
4284
+ : originalDataPath;
4285
+ if (widgetId && originalDataPath) {
4286
+ // Handle multi-path (object) or single path (string)
4287
+ // Read from original schema data using original paths
4288
+ let oldValue;
4289
+ if (typeof originalDataPath === 'object') {
4290
+ // Multi-path: get values for each path
4291
+ oldValue = {};
4292
+ Object.entries(originalDataPath).forEach(([key, path]) => {
4293
+ if (typeof path === 'string') {
4294
+ oldValue[key] = getValueByPath(oldSchemaData, path);
4295
+ }
4296
+ });
4297
+ }
4298
+ else if (typeof originalDataPath === 'string') {
4299
+ oldValue = getValueByPath(oldSchemaData, originalDataPath);
4300
+ }
4301
+ // Set in store using namespaced data path (if namespace was used)
4302
+ if (oldValue !== undefined) {
4303
+ newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
4304
+ }
4305
+ }
4306
+ });
4307
+ // Also revert supporting documents if any
4308
+ if (hasSupportingDocuments) {
4309
+ // Use original section's supporting documents to get original data paths
4310
+ const originalSupportingDocuments = originalSection['section-supporting-documents'] || [];
4311
+ originalSupportingDocuments.forEach((doc, index) => {
4312
+ const widgetId = `supporting-doc-${sectionId}-${index}`;
4313
+ const originalDataPath = doc['document-data-path'];
4314
+ // If namespace was used, data path in store is namespaced
4315
+ const storeDataPath = namespace && originalDataPath
4316
+ ? `${namespace}.${originalDataPath}`
4317
+ : originalDataPath;
4318
+ const oldValue = getValueByPath(oldSchemaData, originalDataPath);
4319
+ newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
4320
+ });
4321
+ }
4322
+ if (newStoreValues !== currentStoreValues) {
4323
+ dispatch(setValues(newStoreValues));
4324
+ }
4138
4325
  setIsEditMode(false);
4139
4326
  onEditModeChange?.(originalSectionId, false);
4140
4327
  };
@@ -4175,7 +4362,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4175
4362
  .${sectionClassId} label.text-gray-700,
4176
4363
  .${sectionClassId} .text-gray-600 {
4177
4364
  font-weight: 400 !important;
4178
- color: rgba(0, 0, 0, 0.5) !important;
4365
+ color: var(--owt-color-text-muted, #727474) !important;
4179
4366
  width: 50% !important;
4180
4367
  min-width: 50% !important;
4181
4368
  max-width: 50% !important;
@@ -4220,11 +4407,11 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4220
4407
  .${sectionClassId}-edit {
4221
4408
  box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.2),
4222
4409
  0 8px 10px -6px rgba(0, 0, 0, 0.1);
4223
- border-color: #ED7C22;
4410
+ border-color: var(--owt-color-primary-dark, #F07B1A);
4224
4411
  border-style: dashed;
4225
4412
  border-width: 1px;
4226
- background-color: #F3E6BC;
4227
- border-radius: 10px;
4413
+ background-color: var(--owt-color-primary-light, #FBE6AA);
4414
+ border-radius: var(--owt-section-border-radius, 10px);
4228
4415
  z-index: 10;
4229
4416
  position: absolute;
4230
4417
  }
@@ -4324,23 +4511,23 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4324
4511
 
4325
4512
  /* IntakeForm accordion */
4326
4513
  .${sectionClassId}.intake-form-accordion-item {
4327
- border-color: #E5E7EB;
4514
+ border-color: var(--owt-color-border-light, #E4E4E4);
4328
4515
  transition: box-shadow 0.2s ease, border-color 0.2s ease;
4329
4516
  }
4330
4517
  .${sectionClassId}.intake-form-accordion-item:hover {
4331
- border-color: #D1D5DB;
4518
+ border-color: var(--owt-color-border, #C4C4C4);
4332
4519
  }
4333
4520
  .${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header {
4334
4521
  transition: opacity 0.2s ease, background-color 0.2s ease;
4335
4522
  }
4336
4523
  .${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header h2 {
4337
- color: #ED7C22;
4524
+ color: var(--owt-color-primary-dark, #F07B1A);
4338
4525
  }
4339
4526
  .${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header:hover {
4340
4527
  opacity: 0.85;
4341
4528
  }
4342
4529
  .${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header:focus-visible {
4343
- outline: 2px solid #F2BA1A;
4530
+ outline: 2px solid var(--owt-color-primary, #F5BB1A);
4344
4531
  outline-offset: 2px;
4345
4532
  }
4346
4533
  .${sectionClassId}.intake-form-accordion-item .intake-form-accordion-content {
@@ -4352,27 +4539,27 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4352
4539
  width: 100%;
4353
4540
  }
4354
4541
  .${sectionClassId}.intake-form-accordion-item .intake-form-prev-btn {
4355
- color: rgba(0, 0, 0, 0.5) !important;
4542
+ color: var(--owt-color-text-muted, #727474) !important;
4356
4543
  }
4357
4544
  .${sectionClassId}.intake-form-accordion-item .intake-form-prev-btn:disabled {
4358
- color: rgba(0, 0, 0, 0.3) !important;
4545
+ color: var(--owt-color-border, #C4C4C4) !important;
4359
4546
  }
4360
4547
  .${sectionClassId}.intake-form-accordion-item .intake-form-prev-btn:hover:not(:disabled) {
4361
- background-color: #F3F4F6;
4362
- border-color: #FD8C3E;
4548
+ background-color: var(--owt-color-bg-alt, #F6F6F6);
4549
+ border-color: var(--owt-btn-primary-border, #F07B1A);
4363
4550
  }
4364
4551
  .${sectionClassId}.intake-form-accordion-item .intake-form-save-btn:hover:not(:disabled) {
4365
- background-color: #E5E7EB;
4552
+ background-color: var(--owt-color-border-light, #E4E4E4);
4366
4553
  }
4367
- ` }), jsxRuntimeExports.jsx("div", { ref: sectionRef, className: `section ${sectionClassId} px-4 sm:px-6 lg:px-8 border-2 border-white ${mode === 'IntakeForm' ? 'intake-form-accordion-item' : ''}`, "data-section-id": sectionId, "data-has-table": hasTableWidget ? 'true' : 'false', "data-has-explicit-span": hasExplicitTableSpan ? 'true' : 'false', "data-edit-mode": isEditMode ? 'true' : 'false', "data-section-dirty": isEditMode && isDirty ? 'true' : 'false', "data-column-span": columnSpan, "data-change-request-type": changeRequestType, "data-intake-form-expanded": mode === 'IntakeForm' ? (isExpanded ? 'true' : 'false') : undefined, style: {
4554
+ ` }), jsxRuntimeExports.jsx("div", { ref: sectionRef, className: `section ${sectionClassId} px-4 sm:px-6 lg:px-8 border-2 ${mode === 'IntakeForm' ? 'intake-form-accordion-item' : ''}`, "data-section-id": sectionId, "data-has-table": hasTableWidget ? 'true' : 'false', "data-has-explicit-span": hasExplicitTableSpan ? 'true' : 'false', "data-edit-mode": isEditMode ? 'true' : 'false', "data-section-dirty": isEditMode && isDirty ? 'true' : 'false', "data-column-span": columnSpan, "data-change-request-type": changeRequestType, "data-intake-form-expanded": mode === 'IntakeForm' ? (isExpanded ? 'true' : 'false') : undefined, style: {
4368
4555
  gridColumn: `span ${columnSpan}`,
4369
4556
  width: '100%',
4370
- borderRadius: '10px',
4371
- // IntakeForm expanded: edit-mode colors. Others: normal or faded for old CR
4557
+ borderRadius: 'var(--owt-section-border-radius, 10px)',
4558
+ borderColor: 'var(--owt-color-bg, #FFFFFF)',
4372
4559
  ...(mode === 'IntakeForm' && isExpanded
4373
- ? { backgroundColor: '#F3E6BC', border: '1px dashed #ED7C22' }
4560
+ ? { backgroundColor: 'var(--owt-color-primary-light, #FBE6AA)', border: '1px dashed var(--owt-color-primary-dark, #F07B1A)' }
4374
4561
  : {
4375
- backgroundColor: changeRequestType === 'old' ? '#F9F9F9' : '#FFFFFF',
4562
+ backgroundColor: changeRequestType === 'old' ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-section-bg, #FFFFFF)',
4376
4563
  opacity: changeRequestType === 'old' ? 0.95 : 1,
4377
4564
  }),
4378
4565
  ...(isEditMode && sectionHeight ? {
@@ -4406,17 +4593,17 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4406
4593
  borderRadius: '9999px',
4407
4594
  fontSize: '12px',
4408
4595
  fontWeight: 500,
4409
- backgroundColor: '#D1FAE5',
4410
- color: '#047857',
4596
+ backgroundColor: 'var(--owt-color-success-light, #D1FAE5)',
4597
+ color: 'var(--owt-color-success-dark, #047857)',
4411
4598
  }, children: translate('common.sectionSaved') || 'Saved' })), intakeFormSectionStatus === 'modified' && (jsxRuntimeExports.jsx("span", { style: {
4412
4599
  display: 'inline-block',
4413
4600
  padding: '4px 10px',
4414
4601
  borderRadius: '9999px',
4415
4602
  fontSize: '12px',
4416
4603
  fontWeight: 500,
4417
- backgroundColor: '#FEE2E2',
4418
- color: '#B91C1C',
4419
- }, children: translate('common.sectionModified') || 'Modified and not saved' }))] }), jsxRuntimeExports.jsx("img", { src: isExpanded ? img$7 : img$6, alt: isExpanded ? 'Collapse' : 'Expand', className: "w-5 h-5 transition-transform", style: { flexShrink: 0, marginLeft: '12px' }, "aria-hidden": true })] }), isExpanded && (jsxRuntimeExports.jsx("div", { id: `intake-form-accordion-content-${sectionId}`, className: "intake-form-accordion-content", role: "region", "aria-labelledby": `intake-form-accordion-header-${sectionId}`, children: jsxRuntimeExports.jsxs("div", { id: gridId, className: "section-panels", style: { paddingTop: '8px' }, children: [editableSection.panels.map((panel, index) => (jsxRuntimeExports.jsx("div", { className: "panel-wrapper", children: jsxRuntimeExports.jsx(PanelRenderer, { panel: panel, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: namespacedSchemaData, onValueChange: onValueChange, isEditMode: isDraft !== false }) }, panel['panel-id'] || `section-panel-${index}`))), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: '#F2BA1A', border: 'none', margin: '15px 0 0 0' } }), hasSupportingDocuments && (jsxRuntimeExports.jsxs("div", { className: "supporting-documents-container", children: [jsxRuntimeExports.jsx("span", { className: "font-semibold", style: { fontFamily: 'Roboto, sans-serif', fontSize: '16px' }, children: translate('common.supportedDocuments') || 'Supported Documents' }), jsxRuntimeExports.jsx("div", { className: "supporting-documents-grid mt-4", children: supportingDocuments.map((doc, docIndex) => {
4604
+ backgroundColor: 'var(--owt-color-error-light, #FEE2E2)',
4605
+ color: 'var(--owt-color-error, #B91C1C)',
4606
+ }, children: translate('common.sectionModified') || 'Modified and not saved' }))] }), jsxRuntimeExports.jsx("img", { src: isExpanded ? img$7 : img$6, alt: isExpanded ? 'Collapse' : 'Expand', className: "w-5 h-5 transition-transform", style: { flexShrink: 0, marginLeft: '12px' }, "aria-hidden": true })] }), isExpanded && (jsxRuntimeExports.jsx("div", { id: `intake-form-accordion-content-${sectionId}`, className: "intake-form-accordion-content", role: "region", "aria-labelledby": `intake-form-accordion-header-${sectionId}`, children: jsxRuntimeExports.jsxs("div", { id: gridId, className: "section-panels", style: { paddingTop: '8px' }, children: [editableSection.panels.map((panel, index) => (jsxRuntimeExports.jsx("div", { className: "panel-wrapper", children: jsxRuntimeExports.jsx(PanelRenderer, { panel: panel, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: namespacedSchemaData, onValueChange: onValueChange, isEditMode: isDraft !== false }) }, panel['panel-id'] || `section-panel-${index}`))), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: 'var(--owt-section-divider-color, #F5BB1A)', border: 'none', margin: '15px 0 0 0' } }), hasSupportingDocuments && (jsxRuntimeExports.jsxs("div", { className: "supporting-documents-container", children: [jsxRuntimeExports.jsx("span", { className: "font-semibold", style: { fontFamily: 'Roboto, sans-serif', fontSize: '16px' }, children: translate('common.supportedDocuments') || 'Supported Documents' }), jsxRuntimeExports.jsx("div", { className: "supporting-documents-grid mt-4", children: supportingDocuments.map((doc, docIndex) => {
4420
4607
  const docConfig = createDocumentWidgetConfig(doc, sectionId, docIndex);
4421
4608
  return (jsxRuntimeExports.jsx("div", { className: "supporting-document-item", children: jsxRuntimeExports.jsx(FileInputWidget, { config: docConfig }) }, `${sectionId}-doc-${docIndex}`));
4422
4609
  }) })] })), jsxRuntimeExports.jsxs("div", { className: "intake-form-edit-controls", style: {
@@ -4432,10 +4619,10 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4432
4619
  fontSize: '14px',
4433
4620
  fontWeight: 400,
4434
4621
  padding: '8px 24px',
4435
- borderRadius: '10px',
4436
- border: '1px solid #FD8C3E',
4437
- background: '#FFFFFF',
4438
- color: 'rgba(0, 0, 0, 0.5)',
4622
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
4623
+ border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
4624
+ background: 'var(--owt-btn-primary-bg, #FFFFFF)',
4625
+ color: 'var(--owt-color-text-muted, #727474)',
4439
4626
  cursor: 'pointer',
4440
4627
  display: 'inline-flex',
4441
4628
  alignItems: 'center',
@@ -4445,10 +4632,10 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4445
4632
  fontSize: '14px',
4446
4633
  fontWeight: 400,
4447
4634
  padding: '8px 24px',
4448
- borderRadius: '10px',
4449
- border: '1px solid #FD8C3E',
4450
- background: '#FFFFFF',
4451
- color: 'rgba(0, 0, 0, 0.5)',
4635
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
4636
+ border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
4637
+ background: 'var(--owt-btn-primary-bg, #FFFFFF)',
4638
+ color: 'var(--owt-color-text-muted, #727474)',
4452
4639
  cursor: 'pointer',
4453
4640
  display: 'inline-flex',
4454
4641
  alignItems: 'center',
@@ -4471,11 +4658,11 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4471
4658
  fontWeight: 600,
4472
4659
  textTransform: 'uppercase',
4473
4660
  letterSpacing: '0.5px',
4474
- backgroundColor: changeRequestType === 'new' ? '#28a745' : '#ffcccc', // Green for new, faded red for old
4475
- color: changeRequestType === 'new' ? '#FFFFFF' : '#cc0000',
4661
+ backgroundColor: changeRequestType === 'new' ? 'var(--owt-color-success, #16A34A)' : 'var(--owt-color-error-light, #FEE2E2)',
4662
+ color: changeRequestType === 'new' ? 'var(--owt-color-bg, #FFFFFF)' : 'var(--owt-color-error, #B91C1C)',
4476
4663
  whiteSpace: 'nowrap',
4477
4664
  boxShadow: changeRequestType === 'new' ? '0 2px 4px rgba(40, 167, 69, 0.3)' : 'none',
4478
- }, children: changeRequestType === 'new' ? 'New' : 'Old' }))] })), jsxRuntimeExports.jsxs("div", { id: gridId, className: "section-panels", style: mode === 'RegistryView' && hideEditButton ? { paddingBottom: '40px' } : {}, children: [editableSection.panels.map((panel, index) => (jsxRuntimeExports.jsx("div", { className: "panel-wrapper", children: jsxRuntimeExports.jsx(PanelRenderer, { panel: panel, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: namespacedSchemaData, onValueChange: onValueChange }) }, panel['panel-id'] || `section-panel-${index}`))), mode === 'CRView' && crViewData && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("hr", { className: "border-gray-300 w-full", style: { height: '1px', marginTop: '20px', marginBottom: '0px' } }), jsxRuntimeExports.jsxs("div", { className: "cr-view-container", style: {
4665
+ }, children: changeRequestType === 'new' ? 'New' : 'Old' }))] })), jsxRuntimeExports.jsxs("div", { id: gridId, className: "section-panels", style: mode === 'RegistryView' && hideEditButton ? { paddingBottom: '30px' } : {}, children: [editableSection.panels.map((panel, index) => (jsxRuntimeExports.jsx("div", { className: "panel-wrapper", children: jsxRuntimeExports.jsx(PanelRenderer, { panel: panel, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: namespacedSchemaData, onValueChange: onValueChange }) }, panel['panel-id'] || `section-panel-${index}`))), mode === 'CRView' && crViewData && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', marginTop: '20px', marginBottom: '0px', border: 'none', backgroundColor: 'var(--owt-color-border, #C4C4C4)' } }), jsxRuntimeExports.jsxs("div", { className: "cr-view-container", style: {
4479
4666
  marginTop: '20px',
4480
4667
  paddingBottom: '30px',
4481
4668
  display: 'flex',
@@ -4490,17 +4677,17 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4490
4677
  }, children: [jsxRuntimeExports.jsx("span", { style: {
4491
4678
  fontFamily: 'Roboto, sans-serif',
4492
4679
  fontSize: '14px',
4493
- color: '#000000',
4680
+ color: 'var(--owt-color-text, #011627)',
4494
4681
  fontWeight: 'normal',
4495
4682
  }, children: "Created by" }), jsxRuntimeExports.jsx("img", { src: img$a, alt: "Person", width: "16", height: "16", style: { filter: 'brightness(0) saturate(100%) invert(56%) sepia(45%) saturate(5139%) hue-rotate(348deg) brightness(96%) contrast(92%)' } }), crViewData?.createdBy && (jsxRuntimeExports.jsx("span", { style: {
4496
4683
  fontFamily: 'Roboto, sans-serif',
4497
4684
  fontSize: '14px',
4498
- color: '#000000',
4685
+ color: 'var(--owt-color-text, #011627)',
4499
4686
  fontWeight: 'normal',
4500
4687
  }, children: crViewData.createdBy })), jsxRuntimeExports.jsx("img", { src: img$9, alt: "Calendar", width: "16", height: "16", style: { marginLeft: '6px' } }), crViewData?.createdDate && (jsxRuntimeExports.jsx("span", { style: {
4501
4688
  fontFamily: 'Roboto, sans-serif',
4502
4689
  fontSize: '14px',
4503
- color: '#000000',
4690
+ color: 'var(--owt-color-text, #011627)',
4504
4691
  fontWeight: 'normal',
4505
4692
  }, children: crViewData.createdDate }))] }), jsxRuntimeExports.jsxs("div", { className: "approved-by-section", style: {
4506
4693
  display: 'flex',
@@ -4511,22 +4698,22 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
4511
4698
  }, children: [jsxRuntimeExports.jsx("span", { style: {
4512
4699
  fontFamily: 'Roboto, sans-serif',
4513
4700
  fontSize: '14px',
4514
- color: '#000000',
4701
+ color: 'var(--owt-color-text, #011627)',
4515
4702
  fontWeight: 'normal',
4516
4703
  }, children: "Approved by" }), jsxRuntimeExports.jsx("img", { src: img$a, alt: "Person", width: "16", height: "16", style: { filter: 'brightness(0) saturate(100%) invert(56%) sepia(45%) saturate(5139%) hue-rotate(348deg) brightness(96%) contrast(92%)' } }), crViewData?.approvedBy && (jsxRuntimeExports.jsx("span", { style: {
4517
4704
  fontFamily: 'Roboto, sans-serif',
4518
4705
  fontSize: '14px',
4519
- color: '#000000',
4706
+ color: 'var(--owt-color-text, #011627)',
4520
4707
  fontWeight: 'normal',
4521
4708
  }, children: crViewData.approvedBy })), jsxRuntimeExports.jsx("img", { src: img$9, alt: "Calendar", width: "16", height: "16", style: { marginLeft: '6px' } }), crViewData?.approvedDate && (jsxRuntimeExports.jsx("span", { style: {
4522
4709
  fontFamily: 'Roboto, sans-serif',
4523
4710
  fontSize: '14px',
4524
- color: '#000000',
4711
+ color: 'var(--owt-color-text, #011627)',
4525
4712
  fontWeight: 'normal',
4526
- }, children: crViewData.approvedDate }))] })] })] })), mode === 'RegistryView' && !hideEditButton && (jsxRuntimeExports.jsx("hr", { className: "border-gray-300 w-full", style: { height: '1px', marginTop: !isEditMode ? '10px' : 0, marginBottom: '14px' } })), mode === 'RegistryView' && !isEditMode && !hideEditButton && (jsxRuntimeExports.jsx("div", { className: "flex justify-center items-center", style: { marginBottom: '20px' }, children: jsxRuntimeExports.jsxs("button", { onClick: handleEdit, className: "font-normal inline-flex items-center gap-2 bg-transparent border-0 p-0 cursor-pointer hover:opacity-80", style: {
4713
+ }, children: crViewData.approvedDate }))] })] })] })), mode === 'RegistryView' && !hideEditButton && (jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', marginTop: !isEditMode ? '10px' : 0, marginBottom: '14px', border: 'none', backgroundColor: 'var(--owt-color-border, #C4C4C4)' } })), mode === 'RegistryView' && !isEditMode && !hideEditButton && (jsxRuntimeExports.jsx("div", { className: "flex justify-center items-center", style: { marginBottom: '20px' }, children: jsxRuntimeExports.jsxs("button", { onClick: handleEdit, className: "font-normal inline-flex items-center gap-2 bg-transparent border-0 p-0 cursor-pointer hover:opacity-80", style: {
4527
4714
  fontFamily: 'Roboto, sans-serif',
4528
4715
  fontSize: '16px',
4529
- color: 'rgba(0, 0, 0, 0.50)'
4716
+ color: 'var(--owt-color-text-muted, #727474)'
4530
4717
  }, children: [translate('common.editDetails') || 'Edit Details', jsxRuntimeExports.jsx("img", { src: img$8, alt: "right-arrow", className: "w-3.5 h-3.5 brightness-0 opacity-50" })] }) }))] })] })) })] }));
4531
4718
  };
4532
4719
 
@@ -4700,9 +4887,6 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
4700
4887
  }, []);
4701
4888
  const safeSections = sections ?? [];
4702
4889
  const prevSectionsLengthRef = React.useRef(safeSections.length);
4703
- // Stable ref for namespace so formHandle useMemo doesn't depend on the (possibly inline) function identity
4704
- const namespaceRef = React.useRef(namespace);
4705
- namespaceRef.current = namespace;
4706
4890
  // Track dirty (unsaved changes) per section for form handle validation
4707
4891
  const sectionDirtyMapRef = React.useRef({});
4708
4892
  const handleSectionDirtyChange = React.useCallback((sectionId, isDirty) => {
@@ -4748,14 +4932,11 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
4748
4932
  // Form handle for onFormReady - allows host to validate and get all section data from its own Submit button
4749
4933
  const formHandle = React.useMemo(() => {
4750
4934
  const getValues = () => store.getState().widget?.values || {};
4751
- const getNamespace = (section, index) => {
4752
- const ns = namespaceRef.current;
4753
- return ns
4754
- ? typeof ns === 'string'
4755
- ? ns
4756
- : ns(section['section-id'], index)
4757
- : undefined;
4758
- };
4935
+ const getNamespace = (section, index) => namespace
4936
+ ? typeof namespace === 'string'
4937
+ ? namespace
4938
+ : namespace(section['section-id'], index)
4939
+ : undefined;
4759
4940
  const checkNoUnsavedChanges = () => {
4760
4941
  const hasDirty = Object.values(sectionDirtyMapRef.current).some(Boolean);
4761
4942
  if (hasDirty) {
@@ -4805,7 +4986,7 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
4805
4986
  return results;
4806
4987
  },
4807
4988
  };
4808
- }, [store, dispatch, safeSections]);
4989
+ }, [store, dispatch, safeSections, namespace]);
4809
4990
  // Call onFormReady when form is ready (sections loaded)
4810
4991
  React.useEffect(() => {
4811
4992
  if (onFormReady && safeSections.length > 0) {
@@ -4878,6 +5059,7 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
4878
5059
  const sectionNamespace = namespace
4879
5060
  ? (typeof namespace === 'string' ? namespace : namespace(section['section-id'], index))
4880
5061
  : undefined;
5062
+ const hideEditForSection = hideEditButton || section['section-hide-edit-button'] === true;
4881
5063
  // IntakeForm mode: pass accordion state and handlers
4882
5064
  const intakeFormProps = mode === 'IntakeForm'
4883
5065
  ? {
@@ -4899,7 +5081,7 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
4899
5081
  : {};
4900
5082
  // Check if section has explicit column span
4901
5083
  if (section['section-column-span']) {
4902
- return (jsxRuntimeExports.jsx(SectionRenderer, { section: section, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: schemaData, onValueChange: onValueChange, gridColumnSpan: section['section-column-span'], onSectionSave: onSectionSave, hideEditButton: hideEditButton, mode: mode, namespace: sectionNamespace, onSectionDirtyChange: handleSectionDirtyChange, ...intakeFormProps, ...registryViewEditProps }, section['section-id']));
5084
+ return (jsxRuntimeExports.jsx(SectionRenderer, { section: section, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: schemaData, onValueChange: onValueChange, gridColumnSpan: section['section-column-span'], onSectionSave: onSectionSave, hideEditButton: hideEditForSection, mode: mode, namespace: sectionNamespace, onSectionDirtyChange: handleSectionDirtyChange, ...intakeFormProps, ...registryViewEditProps }, section['section-id']));
4903
5085
  }
4904
5086
  const verticalPanelsCount = countVerticalPanels(section.panels);
4905
5087
  const tableWidgetColumnSpan = getTableWidgetColumnSpan(section.panels);
@@ -4907,7 +5089,7 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
4907
5089
  const columnSpan = tableWidgetColumnSpan !== null
4908
5090
  ? tableWidgetColumnSpan
4909
5091
  : (containsTable ? Math.max(verticalPanelsCount, 2) : verticalPanelsCount);
4910
- return (jsxRuntimeExports.jsx(SectionRenderer, { section: section, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: schemaData, onValueChange: onValueChange, gridColumnSpan: columnSpan, onSectionSave: onSectionSave, hideEditButton: hideEditButton, mode: mode, namespace: sectionNamespace, onSectionDirtyChange: handleSectionDirtyChange, ...intakeFormProps, ...registryViewEditProps }, section['section-id']));
5092
+ return (jsxRuntimeExports.jsx(SectionRenderer, { section: section, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: schemaData, onValueChange: onValueChange, gridColumnSpan: columnSpan, onSectionSave: onSectionSave, hideEditButton: hideEditForSection, mode: mode, namespace: sectionNamespace, onSectionDirtyChange: handleSectionDirtyChange, ...intakeFormProps, ...registryViewEditProps }, section['section-id']));
4911
5093
  }) })] }));
4912
5094
  };
4913
5095
 
@@ -8099,7 +8281,11 @@ const TableCellSelect = ({ config, value, onValueChange }) => {
8099
8281
  // Use useBaseWidget to get data source options (it handles loading)
8100
8282
  const { dataSourceOptions, loading, config: widgetConfig, } = useBaseWidget({ config });
8101
8283
  const isReadonly = config['widget-readonly'] || false;
8102
- return (jsxRuntimeExports.jsxs("select", { value: value || '', onChange: (e) => onValueChange(e.target.value), disabled: isReadonly || loading, className: `w-full h-[28px] px-2 text-sm border focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 ${isReadonly || loading ? 'bg-gray-100 cursor-not-allowed' : 'bg-white'} border-gray-300`, style: { borderRadius: '10px' }, children: [jsxRuntimeExports.jsx("option", { value: "", children: translate('common.select') || 'Select' }), dataSourceOptions.map((option) => (jsxRuntimeExports.jsx("option", { value: option.value, children: option.label }, option.value)))] }));
8284
+ return (jsxRuntimeExports.jsxs("select", { value: value || '', onChange: (e) => onValueChange(e.target.value), disabled: isReadonly || loading, className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly || loading ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
8285
+ borderRadius: '10px',
8286
+ borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
8287
+ backgroundColor: isReadonly || loading ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
8288
+ }, children: [jsxRuntimeExports.jsx("option", { value: "", children: translate('common.select') || 'Select' }), dataSourceOptions.map((option) => (jsxRuntimeExports.jsx("option", { value: option.value, children: option.label }, option.value)))] }));
8103
8289
  };
8104
8290
  const SelectDisplayValue = ({ config, value }) => {
8105
8291
  const { dataSourceOptions, loading } = useBaseWidget({ config });
@@ -8118,7 +8304,11 @@ const TableCellText = ({ config, value, onValueChange }) => {
8118
8304
  config['widget-data-format'];
8119
8305
  const maxLength = config['widget-data-validation']?.maxLength;
8120
8306
  const displayValue = value !== null && value !== undefined ? String(value) : '';
8121
- return (jsxRuntimeExports.jsx("input", { type: "text", value: displayValue, onChange: (e) => onValueChange(e.target.value), disabled: isReadonly, placeholder: placeholder, maxLength: maxLength, className: `w-full h-[28px] px-2 text-sm border focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 ${isReadonly ? 'bg-gray-100 cursor-not-allowed' : 'bg-white'} border-gray-300`, style: { borderRadius: '10px' } }));
8307
+ return (jsxRuntimeExports.jsx("input", { type: "text", value: displayValue, onChange: (e) => onValueChange(e.target.value), disabled: isReadonly, placeholder: placeholder, maxLength: maxLength, className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
8308
+ borderRadius: '10px',
8309
+ borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
8310
+ backgroundColor: isReadonly ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
8311
+ } }));
8122
8312
  };
8123
8313
  const TableCellNumber = ({ config, value, onValueChange }) => {
8124
8314
  const isReadonly = config['widget-readonly'] || false;
@@ -8141,14 +8331,22 @@ const TableCellNumber = ({ config, value, onValueChange }) => {
8141
8331
  onValueChange(inputValue);
8142
8332
  }
8143
8333
  };
8144
- return (jsxRuntimeExports.jsx("input", { type: "number", value: displayValue, onChange: handleChange, disabled: isReadonly, placeholder: placeholder, min: validationConfig?.min, max: validationConfig?.max, step: formatConfig?.decimalPlaces ? Math.pow(0.1, formatConfig.decimalPlaces) : undefined, className: `w-full h-[28px] px-2 text-sm border focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 text-right ${isReadonly ? 'bg-gray-100 cursor-not-allowed' : 'bg-white'} border-gray-300`, style: { borderRadius: '10px' } }));
8334
+ return (jsxRuntimeExports.jsx("input", { type: "number", value: displayValue, onChange: handleChange, disabled: isReadonly, placeholder: placeholder, min: validationConfig?.min, max: validationConfig?.max, step: formatConfig?.decimalPlaces ? Math.pow(0.1, formatConfig.decimalPlaces) : undefined, className: `w-full h-[28px] px-2 text-sm border focus:outline-none text-right ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
8335
+ borderRadius: '10px',
8336
+ borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
8337
+ backgroundColor: isReadonly ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
8338
+ } }));
8145
8339
  };
8146
8340
  const TableCellDate = ({ config, value, onValueChange }) => {
8147
8341
  const isReadonly = config['widget-readonly'] || false;
8148
8342
  const placeholder = config['widget-data-placeholder'] || '';
8149
8343
  // input type="date" requires YYYY-MM-DD format
8150
8344
  const displayValue = value && typeof value === 'string' ? value.split('T')[0] : '';
8151
- return (jsxRuntimeExports.jsx("input", { type: "date", value: displayValue, onChange: (e) => onValueChange(e.target.value), disabled: isReadonly, placeholder: placeholder, className: `w-full h-[28px] px-2 text-sm border focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 ${isReadonly ? 'bg-gray-100 cursor-not-allowed' : 'bg-white'} border-gray-300`, style: { borderRadius: '10px' } }));
8345
+ return (jsxRuntimeExports.jsx("input", { type: "date", value: displayValue, onChange: (e) => onValueChange(e.target.value), disabled: isReadonly, placeholder: placeholder, className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
8346
+ borderRadius: '10px',
8347
+ borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
8348
+ backgroundColor: isReadonly ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
8349
+ } }));
8152
8350
  };
8153
8351
  const TableWidget = ({ config }) => {
8154
8352
  const { value, error, touched, isEnabled, onChange, config: widgetConfig, } = useBaseWidget({ config });
@@ -8555,13 +8753,13 @@ const TableWidget = ({ config }) => {
8555
8753
  return {}; // No special styling when editing
8556
8754
  const editAction = row?.edit_action;
8557
8755
  if (editAction === 'ADD') {
8558
- return { color: '#16a34a' }; // green-600
8756
+ return { color: 'var(--owt-color-success, #16A34A)' };
8559
8757
  }
8560
8758
  else if (editAction === 'DELETE') {
8561
- return { color: '#dc2626', textDecoration: 'line-through' }; // red-600 with strikethrough
8759
+ return { color: 'var(--owt-color-error, #B91C1C)', textDecoration: 'line-through' };
8562
8760
  }
8563
8761
  else if (editAction === 'UPDATE') {
8564
- return { color: '#ea580c' }; // orange-600
8762
+ return { color: 'var(--owt-color-warning, #F59E0B)' };
8565
8763
  }
8566
8764
  return {};
8567
8765
  };
@@ -8645,27 +8843,81 @@ const TableWidget = ({ config }) => {
8645
8843
  .${tableWidgetId} button {
8646
8844
  border-radius: 10px !important;
8647
8845
  }
8648
- ` }), jsxRuntimeExports.jsxs("div", { className: `table-widget-container ${tableWidgetId}`, children: [confirmationState?.show && (jsxRuntimeExports.jsx("div", { className: "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50", children: jsxRuntimeExports.jsxs("div", { className: "bg-white rounded-lg p-6 max-w-md w-full mx-4", children: [jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold mb-4", children: translate('table.confirm') || 'Confirm Action' }), jsxRuntimeExports.jsx("p", { className: "text-gray-700 mb-6", children: confirmationState.message }), jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-3", children: [jsxRuntimeExports.jsx("button", { onClick: confirmationState.onCancel, className: "px-4 py-2 text-sm font-medium text-gray-700 bg-gray-200 hover:bg-gray-300", style: { borderRadius: '15px' }, children: translate('common.cancel') || 'Cancel' }), jsxRuntimeExports.jsx("button", { onClick: confirmationState.onConfirm, className: "px-4 py-2 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700", style: { borderRadius: '15px' }, children: translate('table.discard') || 'Discard & Continue' })] })] }) })), operations.add && !isReadonly && isEnabled && (isSectionEditMode || !isAnyRowEditing) && (jsxRuntimeExports.jsx("div", { className: "flex justify-end mb-2", children: jsxRuntimeExports.jsx("button", { type: "button", onClick: startAdd, disabled: loadingRowIndex !== null, className: "px-3 py-1 text-sm bg-blue-500 text-white hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed", style: { borderRadius: '15px' }, children: translate('table.addRecord') || 'Add New Record' }) })), rows.length === 0 && !isAdding ? (jsxRuntimeExports.jsxs("div", { className: "text-gray-500 text-sm py-4 text-center border border-gray-300", style: { borderRadius: '15px' }, children: [translate('table.noData') || 'No records available.', operations.add && !isReadonly && ` ${translate('table.clickToAdd') || 'Click "Add New Record" to add one.'}`] })) : (jsxRuntimeExports.jsx("div", { className: "overflow-x-auto border border-gray-300", style: { borderRadius: '15px' }, children: jsxRuntimeExports.jsxs("table", { className: "min-w-full divide-y divide-gray-200", children: [jsxRuntimeExports.jsx("thead", { className: "bg-gray-50", children: jsxRuntimeExports.jsxs("tr", { children: [columns.map((col) => (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: translateConfig(col['widget-label']) }, col['column-key']))), ((operations.edit || operations.remove) && !isReadonly) || isAnyRowEditing || isSectionEditMode ? (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: translate('common.actions') || 'Actions' })) : null] }) }), jsxRuntimeExports.jsxs("tbody", { className: "bg-white divide-y divide-gray-200", children: [rows.map((row, rowIndex) => {
8846
+ /* Focus ring for table cell inputs */
8847
+ .${tableWidgetId} .table-cell-input:focus {
8848
+ box-shadow: 0 0 0 1px var(--owt-widget-input-focus-border, #F07B1A);
8849
+ border-color: var(--owt-widget-input-focus-border, #F07B1A);
8850
+ }
8851
+ ` }), jsxRuntimeExports.jsxs("div", { className: `table-widget-container ${tableWidgetId}`, children: [confirmationState?.show && (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 max-w-md w-full mx-4", style: { backgroundColor: 'var(--owt-color-bg, #FFFFFF)' }, children: [jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold mb-4", style: { color: 'var(--owt-color-text, #011627)' }, children: translate('table.confirm') || 'Confirm Action' }), jsxRuntimeExports.jsx("p", { className: "mb-6", style: { color: 'var(--owt-color-text, #011627)' }, children: confirmationState.message }), jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-3", children: [jsxRuntimeExports.jsx("button", { onClick: confirmationState.onCancel, className: "px-4 py-2 text-sm font-medium", style: {
8852
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
8853
+ border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
8854
+ backgroundColor: 'var(--owt-btn-secondary-bg, #FFFFFF)',
8855
+ color: 'var(--owt-btn-secondary-color, #011627)',
8856
+ }, children: translate('common.cancel') || 'Cancel' }), jsxRuntimeExports.jsx("button", { onClick: confirmationState.onConfirm, className: "px-4 py-2 text-sm font-medium", style: {
8857
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
8858
+ border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
8859
+ backgroundColor: 'var(--owt-color-primary, #F5BB1A)',
8860
+ color: 'var(--owt-color-bg, #FFFFFF)',
8861
+ }, children: translate('table.discard') || 'Discard & Continue' })] })] }) })), operations.add && !isReadonly && isEnabled && (isSectionEditMode || !isAnyRowEditing) && (jsxRuntimeExports.jsx("div", { className: "flex justify-end mb-2", children: jsxRuntimeExports.jsx("button", { type: "button", onClick: startAdd, disabled: loadingRowIndex !== null, className: "px-3 py-1 text-sm disabled:opacity-50 disabled:cursor-not-allowed", style: {
8862
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
8863
+ border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
8864
+ backgroundColor: 'var(--owt-color-primary, #F5BB1A)',
8865
+ color: 'var(--owt-color-bg, #FFFFFF)',
8866
+ }, children: translate('table.addRecord') || 'Add New Record' }) })), jsxRuntimeExports.jsx("div", { className: "overflow-x-auto border", style: { borderRadius: 'var(--owt-widget-table-border-radius, 15px)', borderColor: 'var(--owt-widget-table-border-color, #C4C4C4)' }, 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: [columns.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) || isAnyRowEditing || isSectionEditMode ? (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' })) : null] }) }), jsxRuntimeExports.jsxs("tbody", { style: { backgroundColor: 'var(--owt-widget-table-body-bg, #FFFFFF)' }, children: [rows.length === 0 && !isAdding && (jsxRuntimeExports.jsx("tr", { children: jsxRuntimeExports.jsxs("td", { colSpan: columns.length + (((operations.edit || operations.remove) && !isReadonly) || isSectionEditMode ? 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) => {
8649
8867
  const isEditing = isRowEditing(rowIndex);
8650
8868
  const isLoading = loadingRowIndex === rowIndex;
8651
- return (jsxRuntimeExports.jsxs("tr", { className: isEditing ? 'bg-blue-50' : isLoading ? 'opacity-50' : row.edit_action === 'DELETE' ? 'bg-red-50' : '', children: [columns.map((col) => {
8869
+ return (jsxRuntimeExports.jsxs("tr", { className: isLoading ? 'opacity-50' : '', style: {
8870
+ borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)',
8871
+ backgroundColor: isEditing
8872
+ ? 'var(--owt-widget-table-editing-row-bg, #FBE6AA)'
8873
+ : row.edit_action === 'DELETE'
8874
+ ? 'var(--owt-widget-table-deleted-row-bg, #FEE2E2)'
8875
+ : undefined,
8876
+ }, children: [columns.map((col) => {
8652
8877
  return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: renderCell(rowIndex, col, row) }, col['column-key']));
8653
8878
  }), ((operations.edit || operations.remove) && !isReadonly) || isEditing || isSectionEditMode ? (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", style: { minWidth: '120px' }, children: isEditing ? (
8654
8879
  // Show OK (Save)/Cancel buttons when row is being edited (works in both section edit mode and normal mode)
8655
- jsxRuntimeExports.jsxs("div", { className: "flex flex-row gap-2 items-center", style: { width: '100%' }, children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: saveEdit, disabled: isLoading, className: "px-3 py-1 text-xs font-medium hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap flex-shrink-0", style: {
8880
+ jsxRuntimeExports.jsxs("div", { className: "flex flex-row gap-2 items-center", style: { width: '100%' }, children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: saveEdit, disabled: isLoading, className: "px-3 py-1 text-xs font-medium disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap flex-shrink-0", style: {
8656
8881
  display: 'inline-block',
8657
8882
  minWidth: '60px',
8658
- backgroundColor: '#16a34a', // green-600
8659
- color: '#ffffff', // white text
8883
+ backgroundColor: 'var(--owt-color-success, #16A34A)',
8884
+ color: 'var(--owt-color-bg, #FFFFFF)',
8660
8885
  border: 'none',
8661
- borderRadius: '15px'
8662
- }, children: translate('common.ok') || 'OK' }), jsxRuntimeExports.jsx("button", { type: "button", onClick: cancelEdit, disabled: isLoading, className: "px-3 py-1 text-xs font-medium bg-gray-200 text-gray-700 hover:bg-gray-300 disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap flex-shrink-0", style: { display: 'inline-block', minWidth: '60px', borderRadius: '15px' }, children: translate('common.cancel') || 'Cancel' })] })) : (
8886
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
8887
+ }, children: translate('common.ok') || 'OK' }), jsxRuntimeExports.jsx("button", { type: "button", onClick: cancelEdit, disabled: isLoading, className: "px-3 py-1 text-xs font-medium disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap flex-shrink-0", style: {
8888
+ display: 'inline-block',
8889
+ minWidth: '60px',
8890
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
8891
+ border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
8892
+ backgroundColor: 'var(--owt-btn-secondary-bg, #FFFFFF)',
8893
+ color: 'var(--owt-btn-secondary-color, #011627)',
8894
+ }, children: translate('common.cancel') || 'Cancel' })] })) : (
8663
8895
  // Show Edit/Delete buttons when row is not being edited
8664
- jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [operations.edit && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => startEdit(rowIndex), disabled: isAnyRowEditing || isLoading, className: "px-3 py-1 text-xs text-blue-600 hover:text-blue-800 hover:bg-blue-50 disabled:opacity-50 disabled:cursor-not-allowed", style: { borderRadius: '15px' }, children: translate('common.edit') || 'Edit' })), operations.remove && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => deleteRow(rowIndex), disabled: isAnyRowEditing || isLoading, className: "px-3 py-1 text-xs text-red-600 hover:text-red-800 hover:bg-red-50 disabled:opacity-50 disabled:cursor-not-allowed", style: { borderRadius: '15px' }, children: translate('common.remove') || 'Delete' }))] })) })) : null] }, rowIndex));
8665
- }), isAdding && newRowData && (jsxRuntimeExports.jsxs("tr", { className: "bg-blue-50", children: [columns.map((col) => (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: renderCell(rows.length, col, { ...newRowData, edit_action: 'ADD' }) }, col['column-key']))), jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: saveAdd, disabled: loadingRowIndex === -1, className: "px-3 py-1 text-xs bg-green-600 text-white hover:bg-green-700 disabled:opacity-50", style: { borderRadius: '15px' }, children: translate('common.save') || 'Save' }), jsxRuntimeExports.jsx("button", { type: "button", onClick: () => {
8896
+ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [operations.edit && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => startEdit(rowIndex), disabled: isAnyRowEditing || isLoading, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
8897
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
8898
+ color: 'var(--owt-color-primary-dark, #F07B1A)',
8899
+ backgroundColor: 'transparent',
8900
+ border: 'none',
8901
+ }, children: translate('common.edit') || 'Edit' })), operations.remove && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => deleteRow(rowIndex), disabled: isAnyRowEditing || isLoading, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
8902
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
8903
+ color: 'var(--owt-color-error, #B91C1C)',
8904
+ backgroundColor: 'transparent',
8905
+ border: 'none',
8906
+ }, children: translate('common.remove') || 'Delete' }))] })) })) : null] }, rowIndex));
8907
+ }), isAdding && newRowData && (jsxRuntimeExports.jsxs("tr", { style: { backgroundColor: 'var(--owt-widget-table-editing-row-bg, #FBE6AA)' }, children: [columns.map((col) => (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: renderCell(rows.length, col, { ...newRowData, edit_action: 'ADD' }) }, col['column-key']))), jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: saveAdd, disabled: loadingRowIndex === -1, className: "px-3 py-1 text-xs disabled:opacity-50", style: {
8908
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
8909
+ backgroundColor: 'var(--owt-color-success, #16A34A)',
8910
+ color: 'var(--owt-color-bg, #FFFFFF)',
8911
+ border: 'none',
8912
+ }, children: translate('common.save') || 'Save' }), jsxRuntimeExports.jsx("button", { type: "button", onClick: () => {
8666
8913
  setIsAdding(false);
8667
8914
  setNewRowData(null);
8668
- }, disabled: loadingRowIndex === -1, className: "px-3 py-1 text-xs bg-gray-200 text-gray-700 hover:bg-gray-300 disabled:opacity-50", style: { borderRadius: '15px' }, children: translate('common.cancel') || 'Cancel' })] }) })] }))] })] }) })), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: error[0] }))] })] }));
8915
+ }, disabled: loadingRowIndex === -1, className: "px-3 py-1 text-xs disabled:opacity-50", style: {
8916
+ borderRadius: 'var(--owt-btn-border-radius, 10px)',
8917
+ border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
8918
+ backgroundColor: 'var(--owt-btn-secondary-bg, #FFFFFF)',
8919
+ color: 'var(--owt-btn-secondary-color, #011627)',
8920
+ }, 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] }))] })] }));
8669
8921
  };
8670
8922
 
8671
8923
  const ProfileWidget = ({ config }) => {
@@ -8754,7 +9006,7 @@ const ProfileWidget = ({ config }) => {
8754
9006
  // Get format options (using index access for widget-specific properties)
8755
9007
  const format = widgetConfig['widget-data-format'] || {};
8756
9008
  const imageSize = format.imageSize || 80;
8757
- const nameColor = format.nameColor || '#ED7C22';
9009
+ const nameColor = format.nameColor || 'var(--owt-color-primary-dark, #F07B1A)';
8758
9010
  const showIdLabel = format.showIdLabel !== false; // Default to true
8759
9011
  // Generate a unique class ID for this widget instance
8760
9012
  const widgetClassId = `profile-widget-${config['widget-id']}`;
@@ -8777,8 +9029,8 @@ const ProfileWidget = ({ config }) => {
8777
9029
  height: ${imageSize}px;
8778
9030
  border-radius: 8px;
8779
9031
  object-fit: cover;
8780
- background-color: #e5e7eb;
8781
- border: 2px solid #d1d5db;
9032
+ background-color: var(--owt-color-border-light, #e5e7eb);
9033
+ border: 2px solid var(--owt-color-border, #d1d5db);
8782
9034
  flex-shrink: 0;
8783
9035
  }
8784
9036
 
@@ -8786,8 +9038,8 @@ const ProfileWidget = ({ config }) => {
8786
9038
  width: ${imageSize}px;
8787
9039
  height: ${imageSize}px;
8788
9040
  border-radius: 8px;
8789
- background-color: #e5e7eb;
8790
- border: 2px solid #d1d5db;
9041
+ background-color: var(--owt-color-border-light, #e5e7eb);
9042
+ border: 2px solid var(--owt-color-border, #d1d5db);
8791
9043
  display: flex;
8792
9044
  align-items: center;
8793
9045
  justify-content: center;
@@ -8828,12 +9080,12 @@ const ProfileWidget = ({ config }) => {
8828
9080
  }
8829
9081
 
8830
9082
  .${widgetClassId} .profile-id-label {
8831
- color: #6b7280;
9083
+ color: var(--owt-color-text-muted, #6b7280);
8832
9084
  font-weight: 500;
8833
9085
  }
8834
9086
 
8835
9087
  .${widgetClassId} .profile-id-value {
8836
- color: #111827;
9088
+ color: var(--owt-color-text, #111827);
8837
9089
  font-weight: 400;
8838
9090
  }
8839
9091
  ` }), jsxRuntimeExports.jsxs("div", { className: widgetClassId, children: [jsxRuntimeExports.jsxs("div", { className: "profile-avatar-container", children: [imageUrl ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: displayName || 'Profile', className: "profile-avatar", onError: (e) => {
@@ -8924,7 +9176,7 @@ const TextAreaWidget = ({ config }) => {
8924
9176
  minHeight: `${rows * 1.5 * 14 + 16}px`, // Approximate height based on rows
8925
9177
  } }), showCharCounter && (jsxRuntimeExports.jsx("div", { className: "absolute bottom-2 right-2 text-xs px-1 rounded", style: {
8926
9178
  fontFamily: 'Roboto, sans-serif',
8927
- color: maxLength && currentLength > maxLength ? '#EF4444' : '#6B7280',
9179
+ color: maxLength && currentLength > maxLength ? 'var(--owt-widget-error-color, #EF4444)' : 'var(--owt-widget-helptext-color, #6B7280)',
8928
9180
  backgroundColor: 'rgba(255, 255, 255, 0.9)',
8929
9181
  }, children: charCounterText }))] }), hasError && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: errorMessage }))] })] }) }));
8930
9182
  };
@@ -9071,7 +9323,7 @@ const HeaderSectionWidget = ({ config }) => {
9071
9323
  // ── Format options ────────────────────────────────────────────
9072
9324
  const format = (widgetConfig['widget-data-format'] || {});
9073
9325
  const imageSize = format.imageSize || 120;
9074
- const nameColor = format.nameColor || '#ED7C22';
9326
+ const nameColor = format.nameColor || 'var(--owt-color-primary-dark, #F07B1A)';
9075
9327
  const statusColors = {
9076
9328
  ...DEFAULT_STATUS_COLORS,
9077
9329
  ...(format.statusColors || {}),
@@ -9091,9 +9343,19 @@ const HeaderSectionWidget = ({ config }) => {
9091
9343
  const opt = statusOptions.find((o) => String(o.value).toLowerCase() === String(statusValue).toLowerCase());
9092
9344
  return opt ? opt.label : String(statusValue);
9093
9345
  }, [statusValue, statusOptions]);
9094
- const statusColor = statusColors[String(statusValue).toLowerCase()] || '#6B7280';
9346
+ const statusColor = statusColors[String(statusValue).toLowerCase()] || 'var(--owt-color-text-muted, #6B7280)';
9095
9347
  // ── Scoped class for CSS isolation ────────────────────────────
9096
9348
  const cls = `header-section-widget-${widgetConfig['widget-id']}`;
9349
+ // ── Indicator dot component ───────────────────────────────────
9350
+ const Dot = ({ color }) => (jsxRuntimeExports.jsx("span", { style: {
9351
+ display: 'inline-block',
9352
+ width: 8,
9353
+ height: 8,
9354
+ borderRadius: '50%',
9355
+ backgroundColor: color,
9356
+ flexShrink: 0,
9357
+ marginTop: 6,
9358
+ } }));
9097
9359
  // ── RENDER ────────────────────────────────────────────────────
9098
9360
  return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
9099
9361
  .${cls} {
@@ -9127,8 +9389,8 @@ const HeaderSectionWidget = ({ config }) => {
9127
9389
  height: ${imageSize}px;
9128
9390
  border-radius: 8px;
9129
9391
  object-fit: cover;
9130
- background-color: #e5e7eb;
9131
- border: 2px solid #d1d5db;
9392
+ background-color: var(--owt-color-border-light, #e5e7eb);
9393
+ border: 2px solid var(--owt-color-border, #d1d5db);
9132
9394
  flex-shrink: 0;
9133
9395
  }
9134
9396
 
@@ -9136,8 +9398,8 @@ const HeaderSectionWidget = ({ config }) => {
9136
9398
  width: ${imageSize}px;
9137
9399
  height: ${imageSize}px;
9138
9400
  border-radius: 8px;
9139
- background-color: #e5e7eb;
9140
- border: 2px solid #d1d5db;
9401
+ background-color: var(--owt-color-border-light, #e5e7eb);
9402
+ border: 2px solid var(--owt-color-border, #d1d5db);
9141
9403
  display: flex;
9142
9404
  align-items: center;
9143
9405
  justify-content: center;
@@ -9183,7 +9445,7 @@ const HeaderSectionWidget = ({ config }) => {
9183
9445
  }
9184
9446
 
9185
9447
  .${cls} .hdr-field-value {
9186
- color: #111827;
9448
+ color: var(--owt-color-text, #111827);
9187
9449
  font-weight: 500;
9188
9450
  }
9189
9451
 
@@ -9210,41 +9472,41 @@ const HeaderSectionWidget = ({ config }) => {
9210
9472
  }
9211
9473
 
9212
9474
  .${cls} .hdr-meta-value {
9213
- color: #111827;
9475
+ color: var(--owt-color-text, #111827);
9214
9476
  font-weight: 500;
9215
9477
  }
9216
9478
 
9217
9479
  .${cls} .hdr-select {
9218
9480
  height: 32px;
9219
9481
  padding: 0 8px;
9220
- border: 1px solid #d1d5db;
9482
+ border: 1px solid var(--owt-widget-input-border, #d1d5db);
9221
9483
  border-radius: 6px;
9222
9484
  font-size: 0.875rem;
9223
9485
  font-family: Roboto, sans-serif;
9224
- background: #fff;
9486
+ background: var(--owt-widget-input-bg, #fff);
9225
9487
  min-width: 140px;
9226
- color: #374151;
9488
+ color: var(--owt-btn-primary-color, #374151);
9227
9489
  }
9228
9490
  .${cls} .hdr-select:focus {
9229
9491
  outline: none;
9230
- border-color: #ED7C22;
9492
+ border-color: var(--owt-widget-input-focus-border, #F07B1A);
9231
9493
  box-shadow: 0 0 0 2px rgba(237, 124, 34, 0.15);
9232
9494
  }
9233
9495
 
9234
9496
  .${cls} .hdr-input {
9235
9497
  height: 32px;
9236
9498
  padding: 0 8px;
9237
- border: 1px solid #d1d5db;
9499
+ border: 1px solid var(--owt-widget-input-border, #d1d5db);
9238
9500
  border-radius: 6px;
9239
9501
  font-size: 0.875rem;
9240
9502
  font-family: Roboto, sans-serif;
9241
- background: #fff;
9503
+ background: var(--owt-widget-input-bg, #fff);
9242
9504
  min-width: 140px;
9243
- color: #374151;
9505
+ color: var(--owt-btn-primary-color, #374151);
9244
9506
  }
9245
9507
  .${cls} .hdr-input:focus {
9246
9508
  outline: none;
9247
- border-color: #ED7C22;
9509
+ border-color: var(--owt-widget-input-focus-border, #F07B1A);
9248
9510
  box-shadow: 0 0 0 2px rgba(237, 124, 34, 0.15);
9249
9511
  }
9250
9512
 
@@ -9262,7 +9524,255 @@ const HeaderSectionWidget = ({ config }) => {
9262
9524
  .parentElement?.querySelector('.hdr-avatar-placeholder');
9263
9525
  if (placeholder)
9264
9526
  placeholder.style.display = 'flex';
9265
- } })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: imageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) })] }), 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.jsxs("div", { className: "hdr-right", 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 || '-' })] })] })] })] }));
9527
+ } })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: imageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) })] }), 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.jsx(Dot, { color: "#9CA3AF" }), 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(Dot, { color: isReadonly ? statusColor : '#F59E0B' }), 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.jsx(Dot, { color: isReadonly ? '#9CA3AF' : '#F59E0B' }), 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.jsxs("div", { className: "hdr-right", 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 || '-' })] })] })] })] }));
9528
+ };
9529
+
9530
+ function tryFormatDateTime(value) {
9531
+ if (typeof value !== 'string' || !value)
9532
+ return value ? String(value) : '-';
9533
+ const d = new Date(value);
9534
+ if (Number.isNaN(d.getTime()))
9535
+ return value;
9536
+ try {
9537
+ return d.toLocaleString(undefined, {
9538
+ year: 'numeric',
9539
+ month: 'short',
9540
+ day: '2-digit',
9541
+ hour: '2-digit',
9542
+ minute: '2-digit',
9543
+ });
9544
+ }
9545
+ catch {
9546
+ return value;
9547
+ }
9548
+ }
9549
+ function pickLatestScore(scores) {
9550
+ if (!scores || scores.length === 0)
9551
+ return null;
9552
+ const withTime = scores
9553
+ .map((s) => {
9554
+ const t = typeof s?.computed_at === 'string' ? new Date(s.computed_at).getTime() : NaN;
9555
+ return { s, t };
9556
+ })
9557
+ .filter((x) => !Number.isNaN(x.t));
9558
+ if (withTime.length === 0)
9559
+ return scores[0] || null;
9560
+ withTime.sort((a, b) => b.t - a.t);
9561
+ return withTime[0]?.s || null;
9562
+ }
9563
+ /**
9564
+ * Scores Display Widget - full-width, view-only widget
9565
+ *
9566
+ * Expected config (reference):
9567
+ * {
9568
+ * "widget": "scores-display",
9569
+ * "widget-type": "group",
9570
+ * "widget-id": "record-scores",
9571
+ * "widget-data-source": {
9572
+ * "type": "api",
9573
+ * "service": "staff-portal-api",
9574
+ * "endpoint": "get_scores",
9575
+ * "method": "POST",
9576
+ * "params": { "internal_record_id_path": "internal_record_id" }
9577
+ * }
9578
+ * }
9579
+ *
9580
+ * The host's `dataSourceRequestHandler` is invoked with:
9581
+ * - service: config.widget-data-source.service
9582
+ * - endpoint: config.widget-data-source.endpoint
9583
+ * - method: config.widget-data-source.method (default POST)
9584
+ * - params: { internal_record_id: <resolved from internal_record_id_path> }
9585
+ */
9586
+ const ScoresDisplayWidget = ({ config, dataSourceRequestHandler: propHandler, schemaData: propSchemaData, }) => {
9587
+ const { dataSourceRequestHandler: ctxHandler, schemaData: ctxSchemaData } = useWidgetContext();
9588
+ const handler = propHandler || ctxHandler;
9589
+ const schemaData = propSchemaData || ctxSchemaData || {};
9590
+ const values = reactRedux.useSelector((state) => state.widget.values);
9591
+ const api = config['widget-data-source'];
9592
+ const isApi = api?.type === 'api';
9593
+ const apiDs = isApi ? api : null;
9594
+ const internalIdPath = React.useMemo(() => {
9595
+ if (!apiDs)
9596
+ return undefined;
9597
+ const p = apiDs.params || {};
9598
+ const fromParams = p.internal_record_id_path || p.internalRecordIdPath;
9599
+ const fromConfig = typeof config.internal_record_id_path === 'string'
9600
+ ? config.internal_record_id_path
9601
+ : undefined;
9602
+ return fromParams || fromConfig;
9603
+ }, [apiDs, config]);
9604
+ const internalRecordId = React.useMemo(() => {
9605
+ if (!internalIdPath)
9606
+ return undefined;
9607
+ const fromValues = getValueByPath(values || {}, internalIdPath);
9608
+ if (fromValues !== undefined && fromValues !== null && String(fromValues).trim() !== '') {
9609
+ return String(fromValues);
9610
+ }
9611
+ const fromSchema = getValueByPath(schemaData || {}, internalIdPath);
9612
+ if (fromSchema !== undefined && fromSchema !== null && String(fromSchema).trim() !== '') {
9613
+ return String(fromSchema);
9614
+ }
9615
+ return undefined;
9616
+ }, [internalIdPath, values, schemaData]);
9617
+ const [loading, setLoading] = React.useState(false);
9618
+ const [error, setError] = React.useState(null);
9619
+ const [response, setResponse] = React.useState(null);
9620
+ React.useEffect(() => {
9621
+ let cancelled = false;
9622
+ const load = async () => {
9623
+ if (!apiDs) {
9624
+ setError('Scores widget requires an API data source.');
9625
+ setResponse(null);
9626
+ return;
9627
+ }
9628
+ if (!handler) {
9629
+ setError(null);
9630
+ setResponse(null);
9631
+ return;
9632
+ }
9633
+ const service = apiDs.service;
9634
+ const endpoint = apiDs.endpoint;
9635
+ const method = apiDs.method || 'POST';
9636
+ if (!service || !endpoint) {
9637
+ setError('Scores widget API data source is missing service/endpoint.');
9638
+ setResponse(null);
9639
+ return;
9640
+ }
9641
+ if (!internalRecordId) {
9642
+ setError(null);
9643
+ setResponse(null);
9644
+ return;
9645
+ }
9646
+ try {
9647
+ setLoading(true);
9648
+ setError(null);
9649
+ const rawParams = apiDs.params || {};
9650
+ // Never pass the path helper through to the API.
9651
+ const { internal_record_id_path, internalRecordIdPath, ...rest } = rawParams;
9652
+ void internal_record_id_path;
9653
+ void internalRecordIdPath;
9654
+ const params = {
9655
+ ...rest,
9656
+ internal_record_id: internalRecordId,
9657
+ };
9658
+ const res = await handler(service, endpoint, method, params, {
9659
+ headers: apiDs.headers,
9660
+ });
9661
+ if (cancelled)
9662
+ return;
9663
+ // Accept either direct payload or OpenG2P wrapper objects.
9664
+ const envelope = res && typeof res === 'object' ? res : null;
9665
+ const payload = envelope?.response_body?.response_payload ?? envelope?.data ?? res;
9666
+ if (payload && typeof payload === 'object' && !Array.isArray(payload)) {
9667
+ setResponse(payload);
9668
+ }
9669
+ else {
9670
+ setResponse({ scores: Array.isArray(payload) ? payload : [] });
9671
+ }
9672
+ }
9673
+ catch (e) {
9674
+ if (cancelled)
9675
+ return;
9676
+ const maybeErr = e;
9677
+ const msg = maybeErr && typeof maybeErr === 'object' && typeof maybeErr.message === 'string'
9678
+ ? maybeErr.message
9679
+ : 'Failed to load scores.';
9680
+ setError(msg);
9681
+ setResponse(null);
9682
+ }
9683
+ finally {
9684
+ if (!cancelled)
9685
+ setLoading(false);
9686
+ }
9687
+ };
9688
+ load();
9689
+ return () => {
9690
+ cancelled = true;
9691
+ };
9692
+ }, [apiDs, handler, internalRecordId]);
9693
+ const latest = React.useMemo(() => pickLatestScore(response?.scores), [response]);
9694
+ const cls = `scores-display-widget-${config['widget-id']}`;
9695
+ const scoreType = latest?.score_type ? String(latest.score_type) : '-';
9696
+ const scoreValue = latest?.computed_score !== undefined && latest?.computed_score !== null && String(latest.computed_score) !== ''
9697
+ ? String(latest.computed_score)
9698
+ : '-';
9699
+ const computedAt = tryFormatDateTime(latest?.computed_at);
9700
+ return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
9701
+ .${cls} {
9702
+ width: 100%;
9703
+ font-family: Roboto, sans-serif;
9704
+ padding: 0;
9705
+ display: flex;
9706
+ flex-direction: column;
9707
+ gap: 8px;
9708
+ }
9709
+
9710
+ .${cls} .scores-subtle {
9711
+ font-size: 13px;
9712
+ color: var(--owt-color-text-muted, #727474);
9713
+ font-weight: 400;
9714
+ }
9715
+
9716
+ .${cls} .scores-card {
9717
+ width: 100%;
9718
+ border: none;
9719
+ border-radius: 0;
9720
+ background: transparent;
9721
+ padding: 0;
9722
+ display: grid;
9723
+ grid-template-columns: 1fr 1fr 1fr;
9724
+ gap: 16px;
9725
+ align-items: center;
9726
+ }
9727
+
9728
+ .${cls} .scores-col {
9729
+ min-width: 0;
9730
+ display: flex;
9731
+ flex-direction: column;
9732
+ gap: 6px;
9733
+ }
9734
+
9735
+ .${cls} .scores-label {
9736
+ font-size: 12px;
9737
+ color: var(--owt-color-text-muted, #727474);
9738
+ font-weight: 600;
9739
+ letter-spacing: 0.25px;
9740
+ text-transform: uppercase;
9741
+ }
9742
+
9743
+ .${cls} .scores-value {
9744
+ font-size: 16px;
9745
+ font-weight: 600;
9746
+ color: var(--owt-color-text, #011627);
9747
+ line-height: 1.25;
9748
+ word-break: break-word;
9749
+ }
9750
+
9751
+ .${cls} .scores-value--highlight {
9752
+ font-weight: 800;
9753
+ color: var(--owt-color-primary-dark, #F07B1A);
9754
+ }
9755
+
9756
+ .${cls} .scores-value-wrap {
9757
+ display: inline-flex;
9758
+ align-items: baseline;
9759
+ gap: 10px;
9760
+ flex-wrap: wrap;
9761
+ }
9762
+
9763
+ .${cls} .scores-value-badge { display: inline; }
9764
+
9765
+ .${cls} .scores-statusline {
9766
+ grid-column: 1 / -1;
9767
+ margin-top: 2px;
9768
+ }
9769
+
9770
+ @media (max-width: 768px) {
9771
+ .${cls} .scores-card {
9772
+ grid-template-columns: 1fr;
9773
+ }
9774
+ }
9775
+ ` }), jsxRuntimeExports.jsx("div", { className: cls, children: jsxRuntimeExports.jsxs("div", { className: "scores-card", children: [jsxRuntimeExports.jsxs("div", { className: "scores-col", "aria-live": "polite", children: [jsxRuntimeExports.jsx("div", { className: "scores-label", children: "Score Type" }), jsxRuntimeExports.jsx("div", { className: "scores-value-wrap", children: jsxRuntimeExports.jsx("span", { className: "scores-value-badge", children: jsxRuntimeExports.jsx("span", { className: "scores-value scores-value--highlight", children: scoreType }) }) })] }), jsxRuntimeExports.jsxs("div", { className: "scores-col", children: [jsxRuntimeExports.jsx("div", { className: "scores-label", children: "Score" }), jsxRuntimeExports.jsx("div", { className: "scores-value-wrap", children: jsxRuntimeExports.jsx("span", { className: "scores-value-badge", children: jsxRuntimeExports.jsx("span", { className: "scores-value scores-value--highlight", children: scoreValue }) }) })] }), jsxRuntimeExports.jsxs("div", { className: "scores-col", children: [jsxRuntimeExports.jsx("div", { className: "scores-label", children: "Computed at" }), jsxRuntimeExports.jsx("div", { className: "scores-value", children: computedAt })] }), jsxRuntimeExports.jsx("div", { className: "scores-statusline", children: loading ? (jsxRuntimeExports.jsx("div", { className: "scores-subtle", children: "Loading scores\u2026" })) : error ? (jsxRuntimeExports.jsx("div", { className: "scores-subtle", style: { color: 'var(--owt-color-error, #B91C1C)' }, children: error })) : !latest ? (jsxRuntimeExports.jsx("div", { className: "scores-subtle", children: "No scores available." })) : null })] }) })] }));
9266
9776
  };
9267
9777
 
9268
9778
  /**
@@ -9306,6 +9816,8 @@ const registerDefaultWidgets = () => {
9306
9816
  widgetRegistry.register({ widget: 'profile', component: ProfileWidget });
9307
9817
  // Header section widget for full-width registry header with profile, status, and metadata
9308
9818
  widgetRegistry.register({ widget: 'header-section', component: HeaderSectionWidget });
9819
+ // Scores display widget for full-width computed scores display (view-only)
9820
+ widgetRegistry.register({ widget: 'scores-display', component: ScoresDisplayWidget });
9309
9821
  };
9310
9822
  // Auto-register on import
9311
9823
  registerDefaultWidgets();
@@ -9685,6 +10197,7 @@ exports.PhoneInputWidget = PhoneInputWidget;
9685
10197
  exports.ProfileWidget = ProfileWidget;
9686
10198
  exports.PropertyEditor = PropertyEditor;
9687
10199
  exports.RadioWidget = RadioWidget;
10200
+ exports.ScoresDisplayWidget = ScoresDisplayWidget;
9688
10201
  exports.SectionBuilder = SectionBuilder;
9689
10202
  exports.SectionRenderer = SectionRenderer;
9690
10203
  exports.SectionTree = SectionTree;
@@ -9703,6 +10216,7 @@ exports.applyDecimalPrecision = applyDecimalPrecision;
9703
10216
  exports.applyMask = applyMask;
9704
10217
  exports.createWidgetStore = createWidgetStore;
9705
10218
  exports.createZodSchema = createZodSchema;
10219
+ exports.defaultTheme = defaultTheme;
9706
10220
  exports.evaluateCondition = evaluateCondition;
9707
10221
  exports.filterByCharacterType = filterByCharacterType;
9708
10222
  exports.formatCurrency = formatCurrency;
@@ -9725,6 +10239,7 @@ exports.registerDefaultWidgets = registerDefaultWidgets;
9725
10239
  exports.removeMask = removeMask;
9726
10240
  exports.resetAll = resetAll;
9727
10241
  exports.resetWidget = resetWidget;
10242
+ exports.resolveTheme = resolveTheme;
9728
10243
  exports.setDataSource = setDataSource;
9729
10244
  exports.setError = setError;
9730
10245
  exports.setLoading = setLoading;
@@ -9744,6 +10259,7 @@ exports.useGeoWidgetCascade = useGeoWidgetCascade;
9744
10259
  exports.useWidgetCascade = useWidgetCascade;
9745
10260
  exports.useWidgetContext = useWidgetContext;
9746
10261
  exports.useWidgetEventBus = useWidgetEventBus;
10262
+ exports.useWidgetTheme = useWidgetTheme;
9747
10263
  exports.useWidgetTranslation = useWidgetTranslation;
9748
10264
  exports.validateNumericValue = validateNumericValue;
9749
10265
  exports.validateWidget = validateWidget;