@hai3/uikit 0.3.0-alpha.1 → 0.4.0-alpha.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hai3/uikit",
3
- "version": "0.3.0-alpha.1",
3
+ "version": "0.4.0-alpha.0",
4
4
  "description": "HAI3 UI Kit - Reusable React components built on shadcn/ui",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -109,3 +109,105 @@ export const applyTheme = (theme: Theme, themeName?: string): void => {
109
109
  root.style.fontSize = '';
110
110
  }
111
111
  };
112
+
113
+ /**
114
+ * Apply theme to a shadow root by injecting CSS variables
115
+ * Uses :host selector instead of document.documentElement
116
+ * Idempotent - reuses existing style element with id __hai3-theme-vars__
117
+ *
118
+ * @param shadowRoot - The shadow root to inject theme variables into
119
+ * @param theme - Theme object to apply
120
+ * @param themeName - Optional theme name for data attribute
121
+ */
122
+ export const applyThemeToShadowRoot = (
123
+ shadowRoot: ShadowRoot,
124
+ theme: Theme,
125
+ themeName?: string
126
+ ): void => {
127
+ // Get or create style element
128
+ let styleElement = shadowRoot.getElementById('__hai3-theme-vars__') as HTMLStyleElement | null;
129
+ if (!styleElement) {
130
+ styleElement = document.createElement('style');
131
+ styleElement.id = '__hai3-theme-vars__';
132
+ shadowRoot.appendChild(styleElement);
133
+ }
134
+
135
+ // Set data-theme attribute for debugging
136
+ if (themeName) {
137
+ styleElement.setAttribute('data-theme', themeName);
138
+ }
139
+
140
+ // Generate CSS variable declarations
141
+ const cssVars: string[] = [];
142
+
143
+ // Shadcn color variables
144
+ cssVars.push(`--background: ${hslToVar(theme.colors.background)};`);
145
+ cssVars.push(`--foreground: ${hslToVar(theme.colors.foreground)};`);
146
+ cssVars.push(`--card: ${hslToVar(theme.colors.background)};`);
147
+ cssVars.push(`--card-foreground: ${hslToVar(theme.colors.foreground)};`);
148
+ cssVars.push(`--popover: ${hslToVar(theme.colors.background)};`);
149
+ cssVars.push(`--popover-foreground: ${hslToVar(theme.colors.foreground)};`);
150
+ cssVars.push(`--primary: ${hslToVar(theme.colors.primary)};`);
151
+ cssVars.push(`--primary-foreground: ${hslToVar(theme.colors.background)};`);
152
+ cssVars.push(`--secondary: ${hslToVar(theme.colors.secondary)};`);
153
+ cssVars.push(`--secondary-foreground: ${hslToVar(theme.colors.foreground)};`);
154
+ cssVars.push(`--muted: ${hslToVar(theme.colors.muted)};`);
155
+ cssVars.push(`--muted-foreground: ${hslToVar(theme.colors.foreground)};`);
156
+ cssVars.push(`--accent: ${hslToVar(theme.colors.accent)};`);
157
+ cssVars.push(`--accent-foreground: ${hslToVar(theme.colors.background)};`);
158
+ cssVars.push(`--destructive: ${hslToVar(theme.colors.error)};`);
159
+ cssVars.push(`--destructive-foreground: ${hslToVar(theme.colors.foreground)};`);
160
+ cssVars.push(`--border: ${hslToVar(theme.colors.border)};`);
161
+ cssVars.push(`--input: ${hslToVar(theme.colors.border)};`);
162
+ cssVars.push(`--ring: ${hslToVar(theme.colors.primary)};`);
163
+
164
+ // State colors
165
+ cssVars.push(`--error: ${hslToVar(theme.colors.error)};`);
166
+ cssVars.push(`--warning: ${hslToVar(theme.colors.warning)};`);
167
+ cssVars.push(`--success: ${hslToVar(theme.colors.success)};`);
168
+ cssVars.push(`--info: ${hslToVar(theme.colors.info)};`);
169
+
170
+ // Chart colors (OKLCH format - pass as-is)
171
+ cssVars.push(`--chart-1: ${theme.colors.chart[1]};`);
172
+ cssVars.push(`--chart-2: ${theme.colors.chart[2]};`);
173
+ cssVars.push(`--chart-3: ${theme.colors.chart[3]};`);
174
+ cssVars.push(`--chart-4: ${theme.colors.chart[4]};`);
175
+ cssVars.push(`--chart-5: ${theme.colors.chart[5]};`);
176
+
177
+ // Left menu colors
178
+ cssVars.push(`--left-menu: ${hslToVar(theme.colors.mainMenu.DEFAULT)};`);
179
+ cssVars.push(`--left-menu-foreground: ${hslToVar(theme.colors.mainMenu.foreground)};`);
180
+ cssVars.push(`--left-menu-hover: ${hslToVar(theme.colors.mainMenu.hover)};`);
181
+ cssVars.push(`--left-menu-selected: ${hslToVar(theme.colors.mainMenu.selected)};`);
182
+ cssVars.push(`--left-menu-border: ${hslToVar(theme.colors.mainMenu.border)};`);
183
+
184
+ // Spacing
185
+ Object.entries(theme.spacing).forEach(([key, value]) => {
186
+ cssVars.push(`--spacing-${key}: ${value};`);
187
+ });
188
+
189
+ // Border radius
190
+ Object.entries(theme.borderRadius).forEach(([key, value]) => {
191
+ cssVars.push(`--radius-${key}: ${value};`);
192
+ });
193
+
194
+ // Shadows
195
+ Object.entries(theme.shadows).forEach(([key, value]) => {
196
+ cssVars.push(`--shadow-${key}: ${value};`);
197
+ });
198
+
199
+ // Transitions
200
+ Object.entries(theme.transitions).forEach(([key, value]) => {
201
+ cssVars.push(`--transition-${key}: ${value};`);
202
+ });
203
+
204
+ // Build CSS content
205
+ let cssContent = `:host {\n ${cssVars.join('\n ')}\n}`;
206
+
207
+ // For -large themes: add font-size rule
208
+ if (themeName?.endsWith('-large')) {
209
+ cssContent += '\n\n:host {\n font-size: 125%;\n}';
210
+ }
211
+
212
+ styleElement.textContent = cssContent;
213
+ };