indas-ui 0.1.8 → 0.1.9

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.
Files changed (41) hide show
  1. package/dist/cjs/components/dashboard/charts/BoxPlot.js +5 -5
  2. package/dist/cjs/components/dashboard/charts/Gantt.js +30 -30
  3. package/dist/cjs/components/dashboard/charts/Pareto.js +2 -2
  4. package/dist/cjs/components/datagrid/DataGrid.js +10 -10
  5. package/dist/cjs/components/datagrid/controls/menu/view/CardView.js +6 -6
  6. package/dist/cjs/components/modals/Modal.js +30 -6
  7. package/dist/cjs/components/ui/chart.js +4 -4
  8. package/dist/cjs/contexts/ThemeContext.js +52 -52
  9. package/dist/cjs/lib/api/activity/email/templates.js +218 -218
  10. package/dist/cjs/lib/theme/utils.js +26 -26
  11. package/dist/cjs/lib/vision/dieline-extractor.js +76 -76
  12. package/dist/cjs/locales/de.json +78 -78
  13. package/dist/cjs/locales/en.json +2217 -2217
  14. package/dist/cjs/locales/es.json +78 -78
  15. package/dist/cjs/locales/fr.json +77 -77
  16. package/dist/cjs/locales/hi.json +1599 -1599
  17. package/dist/cjs/services/GlobalLoadingService.js +37 -37
  18. package/dist/cjs/styles/grid-themes.css +345 -345
  19. package/dist/cjs/styles/sidebar-scrollbar.css +45 -45
  20. package/dist/cjs/styles/tokens.css +712 -712
  21. package/dist/components/dashboard/charts/BoxPlot.js +5 -5
  22. package/dist/components/dashboard/charts/Gantt.js +30 -30
  23. package/dist/components/dashboard/charts/Pareto.js +2 -2
  24. package/dist/components/datagrid/DataGrid.js +10 -10
  25. package/dist/components/datagrid/controls/menu/view/CardView.js +6 -6
  26. package/dist/components/modals/Modal.js +30 -6
  27. package/dist/components/ui/chart.js +4 -4
  28. package/dist/contexts/ThemeContext.js +52 -52
  29. package/dist/lib/api/activity/email/templates.js +218 -218
  30. package/dist/lib/theme/utils.js +26 -26
  31. package/dist/lib/vision/dieline-extractor.js +76 -76
  32. package/dist/locales/de.json +78 -78
  33. package/dist/locales/en.json +2217 -2217
  34. package/dist/locales/es.json +78 -78
  35. package/dist/locales/fr.json +77 -77
  36. package/dist/locales/hi.json +1599 -1599
  37. package/dist/services/GlobalLoadingService.js +37 -37
  38. package/dist/styles/grid-themes.css +345 -345
  39. package/dist/styles/sidebar-scrollbar.css +45 -45
  40. package/dist/styles/tokens.css +712 -712
  41. package/package.json +196 -196
@@ -62,11 +62,11 @@ function BoxPlotChart({ data, height = 300, showLegend = false, color = '#5470c6
62
62
  formatter: (params) => {
63
63
  if (params.seriesType === 'boxplot') {
64
64
  const [min, q1, median, q3, max] = params.data;
65
- return `<strong>${categories[params.dataIndex]}</strong><br/>
66
- Max: ${max}<br/>
67
- Q3: ${q3}<br/>
68
- Median: ${median}<br/>
69
- Q1: ${q1}<br/>
65
+ return `<strong>${categories[params.dataIndex]}</strong><br/>
66
+ Max: ${max}<br/>
67
+ Q3: ${q3}<br/>
68
+ Median: ${median}<br/>
69
+ Q1: ${q1}<br/>
70
70
  Min: ${min}`;
71
71
  }
72
72
  return `Outlier: ${params.data[1]}`;
@@ -103,36 +103,36 @@ function GanttChart({ tasks, height = 400, showProgress = true, showToday = true
103
103
  return '';
104
104
  const duration = getDuration(task.startDate, task.endDate);
105
105
  const progress = task.progress ?? 0;
106
- return `
107
- <div style="padding: 8px; min-width: 180px;">
108
- <div style="font-weight: 600; margin-bottom: 6px; color: ${theme.textColorStrong};">${task.name}</div>
109
- <div style="display: grid; gap: 4px; font-size: 12px;">
110
- <div style="display: flex; justify-content: space-between;">
111
- <span style="color: ${theme.textColor};">Start:</span>
112
- <span style="font-weight: 500;">${formatDate(task.startDate)}</span>
113
- </div>
114
- <div style="display: flex; justify-content: space-between;">
115
- <span style="color: ${theme.textColor};">End:</span>
116
- <span style="font-weight: 500;">${formatDate(task.endDate)}</span>
117
- </div>
118
- <div style="display: flex; justify-content: space-between;">
119
- <span style="color: ${theme.textColor};">Duration:</span>
120
- <span style="font-weight: 500;">${duration} day${duration !== 1 ? 's' : ''}</span>
121
- </div>
122
- ${showProgress ? `
123
- <div style="display: flex; justify-content: space-between;">
124
- <span style="color: ${theme.textColor};">Progress:</span>
125
- <span style="font-weight: 500; color: ${progress >= 100 ? theme.success : progress >= 50 ? theme.warning : theme.info};">${progress}%</span>
126
- </div>
127
- ` : ''}
128
- ${task.category ? `
129
- <div style="display: flex; justify-content: space-between;">
130
- <span style="color: ${theme.textColor};">Category:</span>
131
- <span style="font-weight: 500;">${task.category}</span>
132
- </div>
133
- ` : ''}
134
- </div>
135
- </div>
106
+ return `
107
+ <div style="padding: 8px; min-width: 180px;">
108
+ <div style="font-weight: 600; margin-bottom: 6px; color: ${theme.textColorStrong};">${task.name}</div>
109
+ <div style="display: grid; gap: 4px; font-size: 12px;">
110
+ <div style="display: flex; justify-content: space-between;">
111
+ <span style="color: ${theme.textColor};">Start:</span>
112
+ <span style="font-weight: 500;">${formatDate(task.startDate)}</span>
113
+ </div>
114
+ <div style="display: flex; justify-content: space-between;">
115
+ <span style="color: ${theme.textColor};">End:</span>
116
+ <span style="font-weight: 500;">${formatDate(task.endDate)}</span>
117
+ </div>
118
+ <div style="display: flex; justify-content: space-between;">
119
+ <span style="color: ${theme.textColor};">Duration:</span>
120
+ <span style="font-weight: 500;">${duration} day${duration !== 1 ? 's' : ''}</span>
121
+ </div>
122
+ ${showProgress ? `
123
+ <div style="display: flex; justify-content: space-between;">
124
+ <span style="color: ${theme.textColor};">Progress:</span>
125
+ <span style="font-weight: 500; color: ${progress >= 100 ? theme.success : progress >= 50 ? theme.warning : theme.info};">${progress}%</span>
126
+ </div>
127
+ ` : ''}
128
+ ${task.category ? `
129
+ <div style="display: flex; justify-content: space-between;">
130
+ <span style="color: ${theme.textColor};">Category:</span>
131
+ <span style="font-weight: 500;">${task.category}</span>
132
+ </div>
133
+ ` : ''}
134
+ </div>
135
+ </div>
136
136
  `;
137
137
  }
138
138
  },
@@ -34,8 +34,8 @@ function ParetoChart({ data, height = 300, showLegend = true, barColor = '#5470c
34
34
  formatter: (params) => {
35
35
  const bar = params.find((p) => p.seriesType === 'bar');
36
36
  const line = params.find((p) => p.seriesType === 'line');
37
- return `${bar?.name}<br/>
38
- Value: ${(0, number_format_1.formatNumber)(bar?.value)}<br/>
37
+ return `${bar?.name}<br/>
38
+ Value: ${(0, number_format_1.formatNumber)(bar?.value)}<br/>
39
39
  Cumulative: ${line?.value}%`;
40
40
  }
41
41
  },
@@ -1566,15 +1566,15 @@ enableFilterRow = false, initialColumnFilters, }) {
1566
1566
  e.preventDefault();
1567
1567
  onRowContextMenu(row.original, e);
1568
1568
  }
1569
- }, style: getRowProps?.(row.original)?.style, className: `
1570
- cursor-pointer group
1571
- transition-colors duration-150 ease-out
1569
+ }, style: getRowProps?.(row.original)?.style, className: `
1570
+ cursor-pointer group
1571
+ transition-colors duration-150 ease-out
1572
1572
  ${isHighlighted
1573
1573
  ? 'border-2 border-[rgb(var(--color-primary))] bg-gradient-to-r from-[rgb(var(--color-primary))]/10 to-[rgb(var(--color-primary))]/20 shadow-lg relative'
1574
1574
  : isSelected
1575
1575
  ? 'bg-[color-mix(in_srgb,rgb(var(--color-primary))_8%,rgb(var(--bg-surface)))] shadow-sm hover:bg-[color-mix(in_srgb,rgb(var(--color-primary))_15%,rgb(var(--bg-surface)))]'
1576
- : 'hover:bg-[color-mix(in_srgb,rgb(var(--color-primary))_5%,rgb(var(--bg-surface)))]'}
1577
- ${getRowProps?.(row.original)?.className ?? ''}
1576
+ : 'hover:bg-[color-mix(in_srgb,rgb(var(--color-primary))_5%,rgb(var(--bg-surface)))]'}
1577
+ ${getRowProps?.(row.original)?.className ?? ''}
1578
1578
  `, children: row.getVisibleCells().map((cell, cellIndex) => ((0, jsx_runtime_1.jsx)(CellRenderer_1.CellRenderer, { cell: cell, cellIndex: cellIndex, row: row, enableBacchaSearch: enableBacchaSearch, mainColumnsArray: mainColumnsArray, frozenColumnsState: frozenColumnsState, navigationState: navigationState, columnSearches: columnSearches, isColumnSearchActive: isColumnSearchActive, onColumnSearch: handleColumnSearch, onClearColumnSearch: handleClearColumnSearch, SearchHighlighter: SearchHighlighter_1.SearchHighlighter, InlineSearchCell: InlineSearchCell_1.InlineSearchCell, isSelected: isSelected }, cell.id))) }, row.id));
1579
1579
  }), rowVirtualizer.getVirtualItems().length > 0 && ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { colSpan: table.getVisibleFlatColumns().length, style: {
1580
1580
  height: `${rowVirtualizer.getTotalSize() -
@@ -1590,15 +1590,15 @@ enableFilterRow = false, initialColumnFilters, }) {
1590
1590
  e.preventDefault();
1591
1591
  onRowContextMenu(row.original, e);
1592
1592
  }
1593
- }, rowHeight: rowHeight, style: getRowProps?.(row.original)?.style, className: `
1594
- cursor-pointer group
1595
- transition-colors duration-150 ease-out
1593
+ }, rowHeight: rowHeight, style: getRowProps?.(row.original)?.style, className: `
1594
+ cursor-pointer group
1595
+ transition-colors duration-150 ease-out
1596
1596
  ${isHighlighted
1597
1597
  ? 'border-2 border-primary bg-gradient-to-r from-primary/10 to-primary/20 shadow-lg relative z-10'
1598
1598
  : isSelected
1599
1599
  ? 'bg-[rgb(var(--bg-selected))] shadow-sm hover:bg-[rgb(var(--bg-hover))]'
1600
- : 'hover:bg-[rgb(var(--bg-hover))]'}
1601
- ${getRowProps?.(row.original)?.className ?? ''}
1600
+ : 'hover:bg-[rgb(var(--bg-hover))]'}
1601
+ ${getRowProps?.(row.original)?.className ?? ''}
1602
1602
  `, children: row.getVisibleCells().map((cell, cellIndex) => ((0, jsx_runtime_1.jsx)(CellRenderer_1.CellRenderer, { cell: cell, cellIndex: cellIndex, row: row, enableBacchaSearch: enableBacchaSearch, mainColumnsArray: mainColumnsArray, frozenColumnsState: frozenColumnsState, navigationState: navigationState, columnSearches: columnSearches, isColumnSearchActive: isColumnSearchActive, onColumnSearch: handleColumnSearch, onClearColumnSearch: handleClearColumnSearch, SearchHighlighter: SearchHighlighter_1.SearchHighlighter, InlineSearchCell: InlineSearchCell_1.InlineSearchCell, isSelected: isSelected }, cell.id))) }, row.id));
1603
1603
  })) })) }));
1604
1604
  })() }), enableSummary && summaryConfig && ((0, jsx_runtime_1.jsx)(SummaryRow_1.SummaryRow, { table: table, data: processedData, config: summaryConfig, enableRowSelection: enableRowSelection, showDragHandle: isRowReorderingActive }))] }), !loading && table.getRowModel().rows.length === 0 && ((0, jsx_runtime_1.jsx)("div", { className: "absolute left-0 right-0 bottom-0 flex items-center justify-center pointer-events-none z-10", style: { top: '44px' }, children: (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))] text-sm", children: "No data available" }) }))] }) }));
@@ -155,14 +155,14 @@ function CardView({ data, columns, onRowClick, selectedRows, onRowSelect, isLoad
155
155
  return ((0, jsx_runtime_1.jsxs)("div", { ref: containerRef, className: "outline-none", tabIndex: 0, onKeyDown: handleKeyDown, children: [(0, jsx_runtime_1.jsx)("div", { className: cfg.pad, children: (0, jsx_runtime_1.jsx)("div", { className: `grid ${cfg.grid} ${cfg.gap}`, children: (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { initial: false, children: data.map((item, index) => {
156
156
  const isFocused = focusedIndex === index;
157
157
  const itemSelected = isSelected(item);
158
- return ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { ref: (el) => { cardRefs.current[index] = el; }, initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -6 }, transition: { duration: 0.12, delay: Math.min(index * 0.015, 0.15) }, className: "group/card outline-none", tabIndex: -1, onClick: () => setFocusedIndex(index), onDoubleClick: () => handleCardClick(item), children: (0, jsx_runtime_1.jsxs)("div", { className: `
159
- relative rounded-lg border bg-[rgb(var(--bg-surface))] overflow-hidden h-full
160
- transition-all duration-150
158
+ return ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { ref: (el) => { cardRefs.current[index] = el; }, initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -6 }, transition: { duration: 0.12, delay: Math.min(index * 0.015, 0.15) }, className: "group/card outline-none", tabIndex: -1, onClick: () => setFocusedIndex(index), onDoubleClick: () => handleCardClick(item), children: (0, jsx_runtime_1.jsxs)("div", { className: `
159
+ relative rounded-lg border bg-[rgb(var(--bg-surface))] overflow-hidden h-full
160
+ transition-all duration-150
161
161
  ${itemSelected
162
162
  ? 'border-[rgb(var(--color-primary))] shadow-sm'
163
- : 'border-[rgb(var(--bd-default))] hover:border-[rgb(var(--color-primary))]/40 hover:shadow-sm'}
164
- ${isFocused ? 'ring-2 ring-[rgb(var(--color-primary))]/30 ring-offset-1' : ''}
165
- ${getCardClassName?.(item) ?? ''}
163
+ : 'border-[rgb(var(--bd-default))] hover:border-[rgb(var(--color-primary))]/40 hover:shadow-sm'}
164
+ ${isFocused ? 'ring-2 ring-[rgb(var(--color-primary))]/30 ring-offset-1' : ''}
165
+ ${getCardClassName?.(item) ?? ''}
166
166
  `, children: [(0, jsx_runtime_1.jsx)("div", { className: `absolute left-0 top-0 bottom-0 w-[2px] transition-colors duration-150 ${itemSelected ? 'bg-[rgb(var(--color-primary))]' : 'bg-transparent group-hover/card:bg-[rgb(var(--color-primary))]/30'}` }), (0, jsx_runtime_1.jsxs)("div", { className: "pl-3 pr-2.5 py-2.5", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [onRowSelect && ((0, jsx_runtime_1.jsx)("div", { className: "flex-shrink-0", onClick: (e) => e.stopPropagation(), children: (0, jsx_runtime_1.jsx)(SelectionCell_1.SelectionCheckbox, { checked: itemSelected, onChange: (checked) => handleCheckboxChange(item, checked), circular: circularCheckboxes, mode: "checkbox" }) })), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0 flex items-baseline gap-1.5", children: [(0, jsx_runtime_1.jsx)("p", { className: `${cfg.titleText} font-semibold text-[rgb(var(--fg-default))] truncate leading-tight`, children: displayColumns.length > 0 && getDisplayValue(item, displayColumns[0].accessorKey) }), displayColumns.length > 1 && ((0, jsx_runtime_1.jsx)("p", { className: `${cfg.subtitleText} text-[rgb(var(--color-primary))] font-medium truncate flex-shrink-0`, children: getDisplayValue(item, displayColumns[1].accessorKey) }))] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-shrink-0 opacity-0 group-hover/card:opacity-100 transition-opacity duration-150", onClick: (e) => e.stopPropagation(), children: actionsColumn && actionsColumn.cell?.({
167
167
  row: { original: item },
168
168
  getValue: () => null,
@@ -154,6 +154,12 @@ function Modal({ open, onOpenChange, ...props }) {
154
154
  const childRegistry = React.useCallback((delta) => {
155
155
  childOpenCountRef.current += delta;
156
156
  }, []);
157
+ // The sentinel outlives one run of the effect below: React Strict Mode runs it, cleans it up and
158
+ // runs it again at once in development. Retracting in that cleanup meant a `history.back()` that
159
+ // landed after the replay had pushed a new sentinel, popped that one, and read as a back press:
160
+ // every modal on a phone closed itself a moment after opening. So the cleanup only marks it for
161
+ // retraction, a replay in the same tick takes it back, and the retraction happens a microtask later.
162
+ const sentinelRef = React.useRef(null);
157
163
  React.useEffect(() => {
158
164
  if (!open)
159
165
  return;
@@ -164,8 +170,17 @@ function Modal({ open, onOpenChange, ...props }) {
164
170
  // Push a sentinel tagged with THIS modal's identity, so we can tell our own
165
171
  // dismissal apart from a nested child retracting its entry. Without the id
166
172
  // the parent closes too when a child modal applies or cancels.
167
- const id = ++modalSentinelSeq;
168
- window.history.pushState({ __modal: true, __modalId: id }, '');
173
+ let sentinel = sentinelRef.current;
174
+ if (sentinel?.retracting) {
175
+ sentinel.retracting = false;
176
+ }
177
+ else {
178
+ sentinel = { id: ++modalSentinelSeq, retracting: false };
179
+ sentinelRef.current = sentinel;
180
+ window.history.pushState({ __modal: true, __modalId: sentinel.id }, '');
181
+ }
182
+ const mine = sentinel;
183
+ const id = mine.id;
169
184
  let selfPopped = false;
170
185
  const onPopState = () => {
171
186
  // React only when OUR sentinel is the one that just left the stack.
@@ -189,12 +204,21 @@ function Modal({ open, onOpenChange, ...props }) {
189
204
  // Closing normally (Apply / Cancel / X) — retract our own sentinel so the
190
205
  // history stack doesn't grow. If the back button already popped it,
191
206
  // calling back() again would navigate the real page away.
192
- if (selfPopped)
207
+ if (selfPopped) {
208
+ sentinelRef.current = null;
193
209
  return;
194
- const state = window.history.state;
195
- if (state && state.__modal && state.__modalId === id) {
196
- window.history.back();
197
210
  }
211
+ mine.retracting = true;
212
+ queueMicrotask(() => {
213
+ if (!mine.retracting)
214
+ return;
215
+ if (sentinelRef.current === mine)
216
+ sentinelRef.current = null;
217
+ const state = window.history.state;
218
+ if (state && state.__modal && state.__modalId === id) {
219
+ window.history.back();
220
+ }
221
+ });
198
222
  };
199
223
  }, [open]);
200
224
  return ((0, jsx_runtime_1.jsx)(ModalHasOpenChildContext.Provider, { value: childOpenCountRef, children: (0, jsx_runtime_1.jsx)(ModalDepthContext.Provider, { value: depth, children: (0, jsx_runtime_1.jsx)(ModalChildRegistryContext.Provider, { value: childRegistry, children: (0, jsx_runtime_1.jsx)(DialogPrimitive.Root, { open: open, onOpenChange: handleOpenChange, ...props }) }) }) }));
@@ -69,16 +69,16 @@ const ChartStyle = ({ id, config }) => {
69
69
  }
70
70
  return ((0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: {
71
71
  __html: Object.entries(THEMES)
72
- .map(([theme, prefix]) => `
73
- ${prefix} [data-chart=${id}] {
72
+ .map(([theme, prefix]) => `
73
+ ${prefix} [data-chart=${id}] {
74
74
  ${colorConfig
75
75
  .map(([key, itemConfig]) => {
76
76
  const color = itemConfig.theme?.[theme] ||
77
77
  itemConfig.color;
78
78
  return color ? ` --color-${key}: ${color};` : null;
79
79
  })
80
- .join('\n')}
81
- }
80
+ .join('\n')}
81
+ }
82
82
  `)
83
83
  .join('\n'),
84
84
  } }));
@@ -90,58 +90,58 @@ function ThemeProvider({ children, defaultTheme = { variant: 'default', mode: 'l
90
90
  * ```
91
91
  */
92
92
  function ThemeScript({ storageKey = types_1.THEME_CONFIG.storageKey, defaultTheme = 'default', defaultMode = 'light' }) {
93
- const script = `
94
- (function() {
95
- try {
96
- // Get saved theme or use default - no system detection
97
- var savedTheme;
98
- try {
99
- savedTheme = JSON.parse(localStorage.getItem('${storageKey}'));
100
- } catch (e) {
101
- savedTheme = null;
102
- }
103
-
104
- // Force light theme with default variant - this is hardcoded
105
- var mode = 'light';
106
- var variant = 'default';
107
-
108
- // Always use default light theme, no exceptions
109
-
110
- // Remove any existing theme classes
111
- var html = document.documentElement;
112
- var classList = html.classList;
113
- var classesToRemove = [];
114
- for (var i = 0; i < classList.length; i++) {
115
- var className = classList[i];
116
- if (className.startsWith('theme-') || className === 'light' || className === 'dark') {
117
- classesToRemove.push(className);
118
- }
119
- }
120
- classesToRemove.forEach(function(className) {
121
- html.classList.remove(className);
122
- });
123
-
124
- // Add new theme classes
125
- html.classList.add('theme-' + variant, mode);
126
-
127
- // CSS variables are handled by CSS classes, no need to set them here
128
- } catch (e) {
129
- // Fallback: ensure we have default classes
130
- var html = document.documentElement;
131
- var classList = html.classList;
132
- var classesToRemove = [];
133
- for (var i = 0; i < classList.length; i++) {
134
- var className = classList[i];
135
- if (className.startsWith('theme-') || className === 'light' || className === 'dark') {
136
- classesToRemove.push(className);
137
- }
138
- }
139
- classesToRemove.forEach(function(className) {
140
- html.classList.remove(className);
141
- });
142
- html.classList.add('theme-${defaultTheme}', '${defaultMode}');
143
- }
144
- })()
93
+ const script = `
94
+ (function() {
95
+ try {
96
+ // Get saved theme or use default - no system detection
97
+ var savedTheme;
98
+ try {
99
+ savedTheme = JSON.parse(localStorage.getItem('${storageKey}'));
100
+ } catch (e) {
101
+ savedTheme = null;
102
+ }
103
+
104
+ // Force light theme with default variant - this is hardcoded
105
+ var mode = 'light';
106
+ var variant = 'default';
107
+
108
+ // Always use default light theme, no exceptions
109
+
110
+ // Remove any existing theme classes
111
+ var html = document.documentElement;
112
+ var classList = html.classList;
113
+ var classesToRemove = [];
114
+ for (var i = 0; i < classList.length; i++) {
115
+ var className = classList[i];
116
+ if (className.startsWith('theme-') || className === 'light' || className === 'dark') {
117
+ classesToRemove.push(className);
118
+ }
119
+ }
120
+ classesToRemove.forEach(function(className) {
121
+ html.classList.remove(className);
122
+ });
123
+
124
+ // Add new theme classes
125
+ html.classList.add('theme-' + variant, mode);
126
+
127
+ // CSS variables are handled by CSS classes, no need to set them here
128
+ } catch (e) {
129
+ // Fallback: ensure we have default classes
130
+ var html = document.documentElement;
131
+ var classList = html.classList;
132
+ var classesToRemove = [];
133
+ for (var i = 0; i < classList.length; i++) {
134
+ var className = classList[i];
135
+ if (className.startsWith('theme-') || className === 'light' || className === 'dark') {
136
+ classesToRemove.push(className);
137
+ }
138
+ }
139
+ classesToRemove.forEach(function(className) {
140
+ html.classList.remove(className);
141
+ });
142
+ html.classList.add('theme-${defaultTheme}', '${defaultMode}');
143
+ }
144
+ })()
145
145
  `;
146
146
  // suppressHydrationWarning: this inline head script is a known target for
147
147
  // browser extensions (e.g. ad/popup blockers) that overwrite its content or