combo-ui-vue 0.1.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.mjs ADDED
@@ -0,0 +1,2693 @@
1
+ import { onMounted, onUnmounted, readonly, ref } from "vue";
2
+ //#region src/core/dark-mode.ts
3
+ var DarkMode = class {
4
+ mode = "auto";
5
+ mediaQuery = null;
6
+ callbacks = /* @__PURE__ */ new Set();
7
+ storageKey = "cux-dark-mode";
8
+ persist = true;
9
+ constructor(options) {
10
+ if (options?.persist !== void 0) this.persist = options.persist;
11
+ if (options?.storageKey) this.storageKey = options.storageKey;
12
+ }
13
+ /**
14
+ * Initialize dark mode system
15
+ */
16
+ init(mode = "auto") {
17
+ this.mode = mode;
18
+ this.setupMediaQuery();
19
+ if (mode === "auto") {
20
+ const stored = this.getStoredPreference();
21
+ if (stored !== null) this.applyDarkMode(stored);
22
+ else this.applyDarkMode(this.getSystemPreference());
23
+ } else this.applyDarkMode(mode === "dark");
24
+ }
25
+ /**
26
+ * Set up media query listener for system preference changes
27
+ */
28
+ setupMediaQuery() {
29
+ if (typeof window === "undefined") return;
30
+ this.mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
31
+ this.mediaQuery.addEventListener("change", this.handleMediaQueryChange);
32
+ }
33
+ /**
34
+ * Handle system preference changes
35
+ */
36
+ handleMediaQueryChange = (e) => {
37
+ if (this.mode === "auto") this.applyDarkMode(e.matches);
38
+ };
39
+ /**
40
+ * Get system preference for dark mode
41
+ */
42
+ getSystemPreference() {
43
+ if (typeof window === "undefined") return false;
44
+ return window.matchMedia("(prefers-color-scheme: dark)").matches;
45
+ }
46
+ /**
47
+ * Get stored preference from localStorage
48
+ */
49
+ getStoredPreference() {
50
+ if (!this.persist || typeof localStorage === "undefined") return null;
51
+ const stored = localStorage.getItem(this.storageKey);
52
+ if (stored === "dark") return true;
53
+ if (stored === "light") return false;
54
+ return null;
55
+ }
56
+ /**
57
+ * Store preference in localStorage
58
+ */
59
+ storePreference(isDark) {
60
+ if (!this.persist || typeof localStorage === "undefined") return;
61
+ localStorage.setItem(this.storageKey, isDark ? "dark" : "light");
62
+ }
63
+ /**
64
+ * Apply dark mode by toggling class on document element
65
+ */
66
+ applyDarkMode(isDark) {
67
+ if (typeof document === "undefined") return;
68
+ document.documentElement.classList.toggle("dark", isDark);
69
+ this.storePreference(isDark);
70
+ this.notifyCallbacks(isDark);
71
+ }
72
+ /**
73
+ * Notify all registered callbacks
74
+ */
75
+ notifyCallbacks(isDark) {
76
+ this.callbacks.forEach((callback) => callback(isDark));
77
+ }
78
+ /**
79
+ * Get current dark mode state
80
+ */
81
+ get isDark() {
82
+ if (typeof document === "undefined") return false;
83
+ return document.documentElement.classList.contains("dark");
84
+ }
85
+ /**
86
+ * Get current mode setting
87
+ */
88
+ get currentMode() {
89
+ return this.mode;
90
+ }
91
+ /**
92
+ * Set dark mode
93
+ */
94
+ setDarkMode(value) {
95
+ if (value === "auto") {
96
+ this.mode = "auto";
97
+ this.applyDarkMode(this.getSystemPreference());
98
+ if (this.persist && typeof localStorage !== "undefined") localStorage.removeItem(this.storageKey);
99
+ } else {
100
+ this.mode = "light";
101
+ this.applyDarkMode(value);
102
+ }
103
+ }
104
+ /**
105
+ * Toggle dark mode
106
+ */
107
+ toggle() {
108
+ this.setDarkMode(!this.isDark);
109
+ }
110
+ /**
111
+ * Register a callback for dark mode changes
112
+ */
113
+ onChange(callback) {
114
+ this.callbacks.add(callback);
115
+ return () => this.callbacks.delete(callback);
116
+ }
117
+ /**
118
+ * Clean up event listeners
119
+ */
120
+ destroy() {
121
+ if (this.mediaQuery) this.mediaQuery.removeEventListener("change", this.handleMediaQueryChange);
122
+ this.callbacks.clear();
123
+ }
124
+ };
125
+ //#endregion
126
+ //#region src/core/css-generator.ts
127
+ /**
128
+ * CSS Injector - Manages style element injection
129
+ */
130
+ const STYLE_ID = "cux-styles";
131
+ var CSSInjector = class {
132
+ styleElement = null;
133
+ /**
134
+ * Get or create the style element in the document head
135
+ */
136
+ getStyleElement() {
137
+ if (this.styleElement) return this.styleElement;
138
+ let element = document.getElementById(STYLE_ID);
139
+ if (!element) {
140
+ element = document.createElement("style");
141
+ element.id = STYLE_ID;
142
+ document.head.appendChild(element);
143
+ }
144
+ this.styleElement = element;
145
+ return element;
146
+ }
147
+ /**
148
+ * Inject CSS into the document
149
+ */
150
+ inject(css) {
151
+ this.getStyleElement().textContent = css;
152
+ }
153
+ /**
154
+ * Remove injected styles from the document
155
+ */
156
+ destroy() {
157
+ if (this.styleElement?.parentNode) this.styleElement.parentNode.removeChild(this.styleElement);
158
+ this.styleElement = null;
159
+ }
160
+ };
161
+ //#endregion
162
+ //#region src/core/theme-loader.ts
163
+ var ThemeLoader = class {
164
+ callbacks = /* @__PURE__ */ new Set();
165
+ /**
166
+ * Load theme from URL or object
167
+ */
168
+ async load(theme) {
169
+ let themeData;
170
+ if (typeof theme === "string") themeData = await this.loadFromURL(theme);
171
+ else themeData = theme;
172
+ this.notifyCallbacks(themeData);
173
+ return themeData;
174
+ }
175
+ /**
176
+ * Load theme from URL
177
+ */
178
+ async loadFromURL(url) {
179
+ try {
180
+ const response = await fetch(url);
181
+ if (!response.ok) throw new Error(`Failed to load theme: ${response.status} ${response.statusText}`);
182
+ return await response.json();
183
+ } catch (error) {
184
+ console.error("Error loading theme:", error);
185
+ throw error;
186
+ }
187
+ }
188
+ /**
189
+ * Load theme from File object (for file picker)
190
+ */
191
+ async loadFromFile(file) {
192
+ return new Promise((resolve, reject) => {
193
+ const reader = new FileReader();
194
+ reader.onload = (e) => {
195
+ try {
196
+ const content = e.target?.result;
197
+ const themeData = JSON.parse(content);
198
+ this.notifyCallbacks(themeData);
199
+ resolve(themeData);
200
+ } catch {
201
+ reject(/* @__PURE__ */ new Error("Invalid JSON file"));
202
+ }
203
+ };
204
+ reader.onerror = () => {
205
+ reject(/* @__PURE__ */ new Error("Failed to read file"));
206
+ };
207
+ reader.readAsText(file);
208
+ });
209
+ }
210
+ /**
211
+ * Open file picker and load theme
212
+ */
213
+ async openFilePicker() {
214
+ return new Promise((resolve) => {
215
+ const input = document.createElement("input");
216
+ input.type = "file";
217
+ input.accept = ".json";
218
+ input.onchange = async (e) => {
219
+ const file = e.target.files?.[0];
220
+ if (file) try {
221
+ resolve(await this.loadFromFile(file));
222
+ } catch (error) {
223
+ console.error("Error loading theme from file:", error);
224
+ resolve(null);
225
+ }
226
+ else resolve(null);
227
+ };
228
+ input.click();
229
+ });
230
+ }
231
+ /**
232
+ * Register a callback for theme load events
233
+ */
234
+ onLoad(callback) {
235
+ this.callbacks.add(callback);
236
+ return () => this.callbacks.delete(callback);
237
+ }
238
+ /**
239
+ * Notify all registered callbacks
240
+ */
241
+ notifyCallbacks(theme) {
242
+ this.callbacks.forEach((callback) => callback(theme));
243
+ }
244
+ /**
245
+ * Clean up
246
+ */
247
+ destroy() {
248
+ this.callbacks.clear();
249
+ }
250
+ };
251
+ //#endregion
252
+ //#region src/core/theme-sync.ts
253
+ var ThemeSync = class {
254
+ url;
255
+ ws = null;
256
+ reconnect;
257
+ reconnectInterval;
258
+ maxReconnectAttempts;
259
+ reconnectAttempts = 0;
260
+ reconnectTimeout = null;
261
+ isIntentionallyClosed = false;
262
+ connectCallbacks = /* @__PURE__ */ new Set();
263
+ disconnectCallbacks = /* @__PURE__ */ new Set();
264
+ errorCallbacks = /* @__PURE__ */ new Set();
265
+ themeUpdateCallbacks = /* @__PURE__ */ new Set();
266
+ applyTheme;
267
+ constructor(applyTheme, options) {
268
+ this.applyTheme = applyTheme;
269
+ this.url = options.url;
270
+ this.reconnect = options.reconnect ?? true;
271
+ this.reconnectInterval = options.reconnectInterval ?? 3e3;
272
+ this.maxReconnectAttempts = options.maxReconnectAttempts ?? 10;
273
+ if (options.onConnect) this.connectCallbacks.add(options.onConnect);
274
+ if (options.onDisconnect) this.disconnectCallbacks.add(options.onDisconnect);
275
+ if (options.onError) this.errorCallbacks.add(options.onError);
276
+ if (options.onThemeUpdate) this.themeUpdateCallbacks.add(options.onThemeUpdate);
277
+ }
278
+ /**
279
+ * Connect to WebSocket server
280
+ */
281
+ connect() {
282
+ if (this.ws?.readyState === WebSocket.OPEN || this.ws?.readyState === WebSocket.CONNECTING) return;
283
+ this.isIntentionallyClosed = false;
284
+ try {
285
+ this.ws = new WebSocket(this.url);
286
+ this.setupEventListeners();
287
+ } catch (error) {
288
+ this.notifyErrorCallbacks(error);
289
+ }
290
+ }
291
+ /**
292
+ * Set up WebSocket event listeners
293
+ */
294
+ setupEventListeners() {
295
+ if (!this.ws) return;
296
+ this.ws.onopen = () => {
297
+ this.reconnectAttempts = 0;
298
+ this.notifyConnectCallbacks();
299
+ };
300
+ this.ws.onmessage = (event) => {
301
+ try {
302
+ const message = JSON.parse(event.data);
303
+ if (message.type === "theme-update" && message.payload) {
304
+ console.log("[ThemeSync] Received theme with keys:", Object.keys(message.payload));
305
+ this.applyTheme(message.payload);
306
+ this.notifyThemeUpdateCallbacks(message.payload);
307
+ }
308
+ } catch (error) {
309
+ console.error("[ThemeSync] Error parsing message:", error);
310
+ }
311
+ };
312
+ this.ws.onclose = () => {
313
+ this.notifyDisconnectCallbacks();
314
+ if (!this.isIntentionallyClosed && this.reconnect) this.scheduleReconnect();
315
+ };
316
+ this.ws.onerror = (event) => {
317
+ const error = /* @__PURE__ */ new Error("WebSocket connection error");
318
+ this.notifyErrorCallbacks(error);
319
+ };
320
+ }
321
+ /**
322
+ * Schedule reconnection attempt
323
+ */
324
+ scheduleReconnect() {
325
+ if (this.reconnectAttempts >= this.maxReconnectAttempts) {
326
+ console.warn(`[ThemeSync] Max reconnection attempts (${this.maxReconnectAttempts}) reached`);
327
+ return;
328
+ }
329
+ this.reconnectAttempts++;
330
+ this.reconnectTimeout = setTimeout(() => {
331
+ this.connect();
332
+ }, this.reconnectInterval);
333
+ }
334
+ /**
335
+ * Disconnect from WebSocket server
336
+ */
337
+ disconnect() {
338
+ this.isIntentionallyClosed = true;
339
+ this.clearReconnectTimeout();
340
+ if (this.ws) {
341
+ this.ws.close();
342
+ this.ws = null;
343
+ }
344
+ }
345
+ /**
346
+ * Check if connected
347
+ */
348
+ get isConnected() {
349
+ return this.ws?.readyState === WebSocket.OPEN;
350
+ }
351
+ /**
352
+ * Clear reconnection timeout
353
+ */
354
+ clearReconnectTimeout() {
355
+ if (this.reconnectTimeout) {
356
+ clearTimeout(this.reconnectTimeout);
357
+ this.reconnectTimeout = null;
358
+ }
359
+ }
360
+ onConnect(callback) {
361
+ this.connectCallbacks.add(callback);
362
+ return () => this.connectCallbacks.delete(callback);
363
+ }
364
+ onDisconnect(callback) {
365
+ this.disconnectCallbacks.add(callback);
366
+ return () => this.disconnectCallbacks.delete(callback);
367
+ }
368
+ onError(callback) {
369
+ this.errorCallbacks.add(callback);
370
+ return () => this.errorCallbacks.delete(callback);
371
+ }
372
+ onThemeUpdate(callback) {
373
+ this.themeUpdateCallbacks.add(callback);
374
+ return () => this.themeUpdateCallbacks.delete(callback);
375
+ }
376
+ notifyConnectCallbacks() {
377
+ this.connectCallbacks.forEach((cb) => cb());
378
+ }
379
+ notifyDisconnectCallbacks() {
380
+ this.disconnectCallbacks.forEach((cb) => cb());
381
+ }
382
+ notifyErrorCallbacks(error) {
383
+ this.errorCallbacks.forEach((cb) => cb(error));
384
+ }
385
+ notifyThemeUpdateCallbacks(theme) {
386
+ this.themeUpdateCallbacks.forEach((cb) => cb(theme));
387
+ }
388
+ /**
389
+ * Destroy instance and clean up
390
+ */
391
+ destroy() {
392
+ this.disconnect();
393
+ this.connectCallbacks.clear();
394
+ this.disconnectCallbacks.clear();
395
+ this.errorCallbacks.clear();
396
+ this.themeUpdateCallbacks.clear();
397
+ }
398
+ };
399
+ //#endregion
400
+ //#region src/core/google-fonts.ts
401
+ /**
402
+ * Google Fonts loader for vanilla library
403
+ */
404
+ const injectedFamilies = /* @__PURE__ */ new Set();
405
+ /**
406
+ * Generate Google Fonts URL for the given family and variants
407
+ */
408
+ function generateFontUrl(family, variants) {
409
+ const regulars = [];
410
+ const italics = [];
411
+ for (const v of variants) {
412
+ if (v === "regular") {
413
+ regulars.push(400);
414
+ continue;
415
+ }
416
+ if (v === "italic") {
417
+ italics.push(400);
418
+ continue;
419
+ }
420
+ if (v.endsWith("italic")) {
421
+ italics.push(parseInt(v) || 400);
422
+ continue;
423
+ }
424
+ const n = parseInt(v);
425
+ if (!isNaN(n)) regulars.push(n);
426
+ }
427
+ let url;
428
+ if (italics.length === 0) {
429
+ const wghtParam = regulars.map((w) => `0,${w}`).join(";");
430
+ url = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(family)}:ital,wght@${wghtParam}&display=swap`;
431
+ } else if (regulars.length === 0) {
432
+ const wghtParam = italics.map((w) => `1,${w}`).join(";");
433
+ url = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(family)}:ital,wght@${wghtParam}&display=swap`;
434
+ } else {
435
+ const pairs = [...regulars.map((w) => `0,${w}`), ...italics.map((w) => `1,${w}`)].join(";");
436
+ url = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(family)}:ital,wght@${pairs}&display=swap`;
437
+ }
438
+ return url;
439
+ }
440
+ /**
441
+ * Load a Google Font by injecting a <link> in the <head>
442
+ */
443
+ function loadGoogleFont(family, style = "normal", weight = "400") {
444
+ if (injectedFamilies.has(family)) return;
445
+ const variants = [];
446
+ if (style === "italic") variants.push(weight.endsWith("italic") ? weight : `${weight}italic`);
447
+ else variants.push(weight === "regular" ? "regular" : weight);
448
+ const url = generateFontUrl(family, variants);
449
+ const link = document.createElement("link");
450
+ link.rel = "stylesheet";
451
+ link.href = url;
452
+ document.head.appendChild(link);
453
+ injectedFamilies.add(family);
454
+ }
455
+ /**
456
+ * Load fonts from button variants
457
+ */
458
+ function loadFontsFromButtonVariants(variants) {
459
+ for (const variant of variants) if (variant.fontFamily) loadGoogleFont(variant.fontFamily, variant.fontStyle || "normal", variant.fontWeight || "400");
460
+ }
461
+ /**
462
+ * Load fonts from typography global config
463
+ */
464
+ function loadFontsFromTypography(typography) {
465
+ if (typography.globalConfig?.fontFamily) loadGoogleFont(typography.globalConfig.fontFamily);
466
+ if (typography.variants) {
467
+ for (const variant of typography.variants) if (variant.fontFamily) loadGoogleFont(variant.fontFamily, variant.fontStyle || "normal", variant.fontWeight || "400");
468
+ }
469
+ }
470
+ /**
471
+ * Load fonts from forms global config
472
+ */
473
+ function loadFontsFromForms(forms) {
474
+ if (forms.globalConfig?.fontFamily) loadGoogleFont(forms.globalConfig.fontFamily);
475
+ if (forms.globalConfig?.optionFontFamily) loadGoogleFont(forms.globalConfig.optionFontFamily);
476
+ }
477
+ /**
478
+ * Load fonts from avatar variants
479
+ */
480
+ function loadFontsFromAvatarVariants(variants) {
481
+ for (const variant of variants) if (variant.fontFamily) loadGoogleFont(variant.fontFamily, variant.fontStyle || "normal", variant.fontWeight || "400");
482
+ }
483
+ //#endregion
484
+ //#region src/basscss/index.ts
485
+ /**
486
+ * Basscss utilities - included in bundle
487
+ */
488
+ const BASSCSS_ID = "cux-basscss";
489
+ const BASSCSS_CSS = `.inline{display:inline}.block{display:block}.inline-block{display:inline-block}.table{display:table}.table-cell{display:table-cell}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-auto{overflow:auto}.clearfix:after,.clearfix:before{content:" ";display:table}.clearfix:after{clear:both}.left{float:left}.right{float:right}.fit{max-width:100%}.max-width-1{max-width:var(--width-1)}.max-width-2{max-width:var(--width-2)}.max-width-3{max-width:var(--width-3)}.max-width-4{max-width:var(--width-4)}.border-box{box-sizing:border-box}:root{--width-1:24rem;--width-2:32rem;--width-3:48rem;--width-4:64rem}.align-baseline{vertical-align:baseline}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.m0{margin:0}.mt0{margin-top:0}.mr0{margin-right:0}.mb0{margin-bottom:0}.ml0,.mx0{margin-left:0}.mx0{margin-right:0}.my0{margin-bottom:0;margin-top:0}.m1{margin:var(--space-1)}.mt1{margin-top:var(--space-1)}.mr1{margin-right:var(--space-1)}.mb1{margin-bottom:var(--space-1)}.ml1,.mx1{margin-left:var(--space-1)}.mx1{margin-right:var(--space-1)}.my1{margin-bottom:var(--space-1);margin-top:var(--space-1)}.m2{margin:var(--space-2)}.mt2{margin-top:var(--space-2)}.mr2{margin-right:var(--space-2)}.mb2{margin-bottom:var(--space-2)}.ml2,.mx2{margin-left:var(--space-2)}.mx2{margin-right:var(--space-2)}.my2{margin-bottom:var(--space-2);margin-top:var(--space-2)}.m3{margin:var(--space-3)}.mt3{margin-top:var(--space-3)}.mr3{margin-right:var(--space-3)}.mb3{margin-bottom:var(--space-3)}.ml3,.mx3{margin-left:var(--space-3)}.mx3{margin-right:var(--space-3)}.my3{margin-bottom:var(--space-3);margin-top:var(--space-3)}.m4{margin:var(--space-4)}.mt4{margin-top:var(--space-4)}.mr4{margin-right:var(--space-4)}.mb4{margin-bottom:var(--space-4)}.ml4,.mx4{margin-left:var(--space-4)}.mx4{margin-right:var(--space-4)}.my4{margin-bottom:var(--space-4);margin-top:var(--space-4)}.mxn1{margin-left:calc(var(--space-1)*-1);margin-right:calc(var(--space-1)*-1)}.mxn2{margin-left:calc(var(--space-2)*-1);margin-right:calc(var(--space-2)*-1)}.mxn3{margin-left:calc(var(--space-3)*-1);margin-right:calc(var(--space-3)*-1)}.mxn4{margin-left:calc(var(--space-4)*-1);margin-right:calc(var(--space-4)*-1)}.m-auto{margin:auto}.mt-auto{margin-top:auto}.mr-auto{margin-right:auto}.mb-auto{margin-bottom:auto}.ml-auto,.mx-auto{margin-left:auto}.mx-auto{margin-right:auto}.my-auto{margin-bottom:auto;margin-top:auto}.p0{padding:0}.pt0{padding-top:0}.pr0{padding-right:0}.pb0{padding-bottom:0}.pl0,.px0{padding-left:0}.px0{padding-right:0}.py0{padding-bottom:0;padding-top:0}.p1{padding:var(--space-1)}.pt1{padding-top:var(--space-1)}.pr1{padding-right:var(--space-1)}.pb1{padding-bottom:var(--space-1)}.pl1{padding-left:var(--space-1)}.py1{padding-bottom:var(--space-1);padding-top:var(--space-1)}.px1{padding-left:var(--space-1);padding-right:var(--space-1)}.p2{padding:var(--space-2)}.pt2{padding-top:var(--space-2)}.pr2{padding-right:var(--space-2)}.pb2{padding-bottom:var(--space-2)}.pl2{padding-left:var(--space-2)}.py2{padding-bottom:var(--space-2);padding-top:var(--space-2)}.px2{padding-left:var(--space-2);padding-right:var(--space-2)}.p3{padding:var(--space-3)}.pt3{padding-top:var(--space-3)}.pr3{padding-right:var(--space-3)}.pb3{padding-bottom:var(--space-3)}.pl3{padding-left:var(--space-3)}.py3{padding-bottom:var(--space-3);padding-top:var(--space-3)}.px3{padding-left:var(--space-3);padding-right:var(--space-3)}.p4{padding:var(--space-4)}.pt4{padding-top:var(--space-4)}.pr4{padding-right:var(--space-4)}.pb4{padding-bottom:var(--space-4)}.pl4{padding-left:var(--space-4)}.py4{padding-bottom:var(--space-4);padding-top:var(--space-4)}.px4{padding-left:var(--space-4);padding-right:var(--space-4)}:root{--space-1:.5rem;--space-2:1rem;--space-3:2rem;--space-4:4rem}.col{float:left}.col,.col-right{box-sizing:border-box}.col-right{float:right}.col-1{width:8.33333%}.col-2{width:16.66667%}.col-3{width:25%}.col-4{width:33.33333%}.col-5{width:41.66667%}.col-6{width:50%}.col-7{width:58.33333%}.col-8{width:66.66667%}.col-9{width:75%}.col-10{width:83.33333%}.col-11{width:91.66667%}.col-12{width:100%}.flex{display:flex}.flex-column{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.self-start{align-self:flex-start}.self-end{align-self:flex-end}.self-center{align-self:center}.self-baseline{align-self:baseline}.self-stretch{align-self:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.justify-evenly{justify-content:space-evenly}.content-start{align-content:flex-start}.content-end{align-content:flex-end}.content-center{align-content:center}.content-between{align-content:space-between}.content-around{align-content:space-around}.content-stretch{align-content:stretch}.flex-auto{flex:1 1 auto;min-height:0;min-width:0}.flex-none{flex:none}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-last{order:99999}.relative{position:relative}.absolute{position:absolute}.fixed{position:fixed}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.z1{z-index:var(--z1)}.z2{z-index:var(--z2)}.z3{z-index:var(--z3)}.z4{z-index:var(--z4)}:root{--z1:1;--z2:2;--z3:3;--z4:4}.border{border-style:solid;border-width:var(--border-width)}.border-top{border-top-style:solid;border-top-width:var(--border-width)}.border-right{border-right-style:solid;border-right-width:var(--border-width)}.border-bottom{border-bottom-style:solid;border-bottom-width:var(--border-width)}.border-left{border-left-style:solid;border-left-width:var(--border-width)}.border-none{border:0}.rounded{border-radius:var(--border-radius)}.circle{border-radius:50%}.rounded-top{border-radius:var(--border-radius) var(--border-radius) 0 0}.rounded-right{border-radius:0 var(--border-radius) var(--border-radius) 0}.rounded-bottom{border-radius:0 0 var(--border-radius) var(--border-radius)}.rounded-left{border-radius:var(--border-radius) 0 0 var(--border-radius)}.not-rounded{border-radius:0}:root{--border-width:1px;--border-radius:3px}.hide{height:1px;overflow:hidden;position:absolute!important;width:1px;clip:rect(1px,1px,1px,1px)}.display-none{display:none!important}`;
490
+ let injected = false;
491
+ /**
492
+ * Inject Basscss utilities into the page
493
+ */
494
+ function injectBasscss() {
495
+ if (injected) return;
496
+ if (typeof document === "undefined") return;
497
+ if (document.getElementById(BASSCSS_ID)) {
498
+ injected = true;
499
+ return;
500
+ }
501
+ const style = document.createElement("style");
502
+ style.id = BASSCSS_ID;
503
+ style.textContent = BASSCSS_CSS;
504
+ document.head.appendChild(style);
505
+ injected = true;
506
+ }
507
+ //#endregion
508
+ //#region src/core/base-styles.ts
509
+ /**
510
+ * Base styles for ComboUX
511
+ */
512
+ const BASE_STYLES_ID = "cux-base-styles";
513
+ const DEFAULT_OPTIONS = {
514
+ backgroundColor: "#ffffff",
515
+ darkBackgroundColor: "#333333",
516
+ textColor: "#212529",
517
+ darkTextColor: "#f8f9fa"
518
+ };
519
+ /**
520
+ * Build base CSS with dynamic colors
521
+ */
522
+ function buildBaseCSS(options = DEFAULT_OPTIONS) {
523
+ const bgColor = options.backgroundColor ?? DEFAULT_OPTIONS.backgroundColor;
524
+ const darkBgColor = options.darkBackgroundColor ?? DEFAULT_OPTIONS.darkBackgroundColor;
525
+ return `
526
+ /* Base styles */
527
+ :root {
528
+ --cux-bg: ${bgColor};
529
+ --cux-text: ${options.textColor ?? DEFAULT_OPTIONS.textColor};
530
+ --cux-text-muted: #6c757d;
531
+ --cux-border: #dee2e6;
532
+ --cux-surface: #f8f9fa;
533
+ }
534
+
535
+ .dark {
536
+ --cux-bg: ${darkBgColor};
537
+ --cux-text: ${options.darkTextColor ?? DEFAULT_OPTIONS.darkTextColor};
538
+ --cux-text-muted: #adb5bd;
539
+ --cux-border: #495057;
540
+ --cux-surface: #222222;
541
+ }
542
+
543
+ body {
544
+ background-color: var(--cux-bg);
545
+ color: var(--cux-text);
546
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
547
+ transition: background-color 0.2s ease, color 0.2s ease;
548
+ }
549
+ `;
550
+ }
551
+ /**
552
+ * Inject base styles with dynamic colors
553
+ */
554
+ function injectBaseStyles(options) {
555
+ if (typeof document === "undefined") return;
556
+ const existing = document.getElementById(BASE_STYLES_ID);
557
+ if (existing) {
558
+ if (options) existing.textContent = buildBaseCSS(options);
559
+ return;
560
+ }
561
+ const style = document.createElement("style");
562
+ style.id = BASE_STYLES_ID;
563
+ style.textContent = buildBaseCSS(options);
564
+ document.head.insertBefore(style, document.head.firstChild);
565
+ }
566
+ /**
567
+ * Update base styles (for theme updates)
568
+ */
569
+ function updateBaseStyles(options) {
570
+ if (typeof document === "undefined") return;
571
+ const existing = document.getElementById(BASE_STYLES_ID);
572
+ if (existing) existing.textContent = buildBaseCSS(options);
573
+ else injectBaseStyles(options);
574
+ }
575
+ //#endregion
576
+ //#region src/core/utils.ts
577
+ /**
578
+ * Convert a string to kebab-case for CSS class names
579
+ * Removes accents and special characters
580
+ */
581
+ function toKebabCase(str) {
582
+ return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
583
+ }
584
+ /**
585
+ * Build a CSS border string from BorderValue
586
+ */
587
+ function buildBorder(border) {
588
+ if (!border) return "";
589
+ return `${border.width}${border.unit} ${border.style} ${border.color}`;
590
+ }
591
+ /**
592
+ * Build a CSS border-radius string from BorderRadiusValue
593
+ */
594
+ function buildBorderRadius(radius) {
595
+ if (!radius) return "";
596
+ if (radius.linked) return `${radius.tl}${radius.unit}`;
597
+ return `${radius.tl}${radius.unit} ${radius.tr}${radius.unit} ${radius.br}${radius.unit} ${radius.bl}${radius.unit}`;
598
+ }
599
+ /**
600
+ * Build a CSS padding string from PaddingValue
601
+ */
602
+ function buildPadding(padding) {
603
+ if (!padding) return "";
604
+ const { top, right, bottom, left, unit } = padding;
605
+ if (top === right && right === bottom && bottom === left) return `${top}${unit}`;
606
+ if (top === bottom && right === left) return `${top}${unit} ${right}${unit}`;
607
+ return `${top}${unit} ${right}${unit} ${bottom}${unit} ${left}${unit}`;
608
+ }
609
+ /**
610
+ * Build a CSS font-size string from UnitNumber
611
+ */
612
+ function buildFontSize(fontSize) {
613
+ if (!fontSize) return "";
614
+ return `${fontSize.value}${fontSize.unit}`;
615
+ }
616
+ /**
617
+ * Build a CSS letter-spacing string
618
+ */
619
+ function buildLetterSpacing(value) {
620
+ if (!value) return "";
621
+ if (typeof value === "object" && "value" in value) return `${value.value}${value.unit}`;
622
+ if (typeof value === "string") {
623
+ if (value.endsWith("px") || value.endsWith("em") || value.endsWith("rem")) return value;
624
+ return `${value}px`;
625
+ }
626
+ return "";
627
+ }
628
+ /**
629
+ * Build a CSS border string from BorderValue | string
630
+ */
631
+ function buildBorderOptional(border) {
632
+ if (!border) return "";
633
+ if (typeof border === "string") return border;
634
+ return `${border.width}${border.unit} ${border.style} ${border.color}`;
635
+ }
636
+ /**
637
+ * Build a CSS offset string from UnitNumber | number
638
+ */
639
+ function buildOffset(offset) {
640
+ if (offset === void 0) return "";
641
+ if (typeof offset === "number") return `${offset}px`;
642
+ return `${offset.value}${offset.unit}`;
643
+ }
644
+ /**
645
+ * Deep merge objects (for dark mode overrides)
646
+ */
647
+ function deepMerge(target, source) {
648
+ if (!source) return target;
649
+ const result = { ...target };
650
+ for (const key in source) {
651
+ const sourceValue = source[key];
652
+ const targetValue = target[key];
653
+ if (sourceValue !== void 0 && sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) result[key] = deepMerge(targetValue, sourceValue);
654
+ else if (sourceValue !== void 0) result[key] = sourceValue;
655
+ }
656
+ return result;
657
+ }
658
+ /**
659
+ * Get effective font family (fallback to global config)
660
+ * Shared utility used by all component generators
661
+ */
662
+ function getEffectiveFontFamily$2(variantFontFamily, globalFontFamily) {
663
+ if (variantFontFamily !== null && variantFontFamily !== void 0) return variantFontFamily;
664
+ return globalFontFamily || null;
665
+ }
666
+ //#endregion
667
+ //#region src/core/typography-generator.ts
668
+ /**
669
+ * Build CSS value from UnitNumber or string
670
+ */
671
+ function buildUnitValue$1(value, defaultUnit = "px") {
672
+ if (!value) return "";
673
+ if (typeof value === "string") return value;
674
+ return `${value.value}${value.unit || defaultUnit}`;
675
+ }
676
+ /**
677
+ * Get effective font family (fallback to global)
678
+ */
679
+ function getEffectiveFontFamily$1(variant, globalConfig) {
680
+ return variant.fontFamily || globalConfig?.fontFamily || "system-ui, sans-serif";
681
+ }
682
+ /**
683
+ * Get effective color (fallback to global)
684
+ */
685
+ function getEffectiveColor(variant, globalConfig, isDark = false) {
686
+ const darkOverride = isDark ? variant.dark?.color : null;
687
+ const globalDarkOverride = isDark ? globalConfig?.dark?.color : null;
688
+ if (darkOverride) return darkOverride;
689
+ if (variant.color) return variant.color;
690
+ if (globalDarkOverride) return globalDarkOverride;
691
+ if (globalConfig?.color) return globalConfig.color;
692
+ return isDark ? "#f8f9fa" : "#212529";
693
+ }
694
+ /**
695
+ * Get line height as CSS value
696
+ */
697
+ function buildLineHeight(value) {
698
+ if (!value) return "1.5";
699
+ return `${value.value}${value.unit || ""}`;
700
+ }
701
+ /**
702
+ * Generate CSS for a single typography variant
703
+ */
704
+ function generateTypographyVariantCSS(variant, globalConfig) {
705
+ const fontFamily = getEffectiveFontFamily$1(variant, globalConfig);
706
+ const color = getEffectiveColor(variant, globalConfig, false);
707
+ const css = [];
708
+ css.push(` font-family: '${fontFamily}', sans-serif;`);
709
+ css.push(` font-style: ${variant.fontStyle || "normal"};`);
710
+ css.push(` font-weight: ${variant.fontWeight || "400"};`);
711
+ if (variant.fontSize) css.push(` font-size: ${buildFontSize(variant.fontSize)};`);
712
+ if (variant.letterSpacing) css.push(` letter-spacing: ${buildUnitValue$1(variant.letterSpacing)};`);
713
+ if (variant.lineHeight) css.push(` line-height: ${buildLineHeight(variant.lineHeight)};`);
714
+ if (variant.textTransform) css.push(` text-transform: ${variant.textTransform};`);
715
+ if (variant.textDecoration) css.push(` text-decoration: ${variant.textDecoration};`);
716
+ css.push(` color: ${color};`);
717
+ return css.join("\n");
718
+ }
719
+ /**
720
+ * Generate complete typography CSS
721
+ */
722
+ function generateTypographyCSS(typography) {
723
+ const css = [];
724
+ const globalConfig = typography.globalConfig;
725
+ const variants = typography.variants || [];
726
+ css.push(`/* Typography Base */`);
727
+ css.push(`.cux-typography {`);
728
+ if (globalConfig?.fontFamily) css.push(` font-family: '${globalConfig.fontFamily}', sans-serif;`);
729
+ if (globalConfig?.color) css.push(` color: ${globalConfig.color};`);
730
+ css.push(`}`);
731
+ css.push("");
732
+ const headingVariants = variants.filter((v) => [
733
+ "h1",
734
+ "h2",
735
+ "h3",
736
+ "h4",
737
+ "h5",
738
+ "h6"
739
+ ].includes(v.id));
740
+ const displayVariants = variants.filter((v) => v.id?.startsWith("display"));
741
+ const bodyVariants = variants.filter((v) => [
742
+ "body",
743
+ "small",
744
+ "caption",
745
+ "link"
746
+ ].includes(v.id));
747
+ if (headingVariants.length > 0) {
748
+ css.push(`/* Headings */`);
749
+ headingVariants.forEach((variant) => {
750
+ css.push(`.cux-${variant.id} {`);
751
+ css.push(generateTypographyVariantCSS(variant, globalConfig));
752
+ css.push(`}`);
753
+ css.push(`.dark .cux-${variant.id} {`);
754
+ css.push(` color: ${getEffectiveColor(variant, globalConfig, true)};`);
755
+ css.push(`}`);
756
+ });
757
+ css.push("");
758
+ }
759
+ if (displayVariants.length > 0) {
760
+ css.push(`/* Display */`);
761
+ displayVariants.forEach((variant) => {
762
+ css.push(`.cux-${variant.id} {`);
763
+ css.push(generateTypographyVariantCSS(variant, globalConfig));
764
+ css.push(`}`);
765
+ css.push(`.dark .cux-${variant.id} {`);
766
+ css.push(` color: ${getEffectiveColor(variant, globalConfig, true)};`);
767
+ css.push(`}`);
768
+ });
769
+ css.push("");
770
+ }
771
+ if (bodyVariants.length > 0) {
772
+ css.push(`/* Body Text */`);
773
+ bodyVariants.forEach((variant) => {
774
+ css.push(`.cux-${variant.id} {`);
775
+ css.push(generateTypographyVariantCSS(variant, globalConfig));
776
+ css.push(`}`);
777
+ css.push(`.dark .cux-${variant.id} {`);
778
+ css.push(` color: ${getEffectiveColor(variant, globalConfig, true)};`);
779
+ css.push(`}`);
780
+ });
781
+ }
782
+ return css.join("\n");
783
+ }
784
+ //#endregion
785
+ //#region src/core/forms-generator.ts
786
+ /**
787
+ * Build CSS value from UnitNumber
788
+ */
789
+ function buildUnitValue(value, defaultUnit = "px") {
790
+ if (!value) return "";
791
+ return `${value.value}${value.unit || defaultUnit}`;
792
+ }
793
+ /**
794
+ * Get effective font family (fallback to typography)
795
+ */
796
+ function getEffectiveFontFamily(formsFontFamily, typography) {
797
+ if (formsFontFamily) return formsFontFamily;
798
+ if (typography?.globalConfig?.fontFamily) return typography.globalConfig.fontFamily;
799
+ return "system-ui, sans-serif";
800
+ }
801
+ /**
802
+ * Generate complete forms CSS
803
+ */
804
+ function generateFormsCSS(forms, typography) {
805
+ const css = [];
806
+ const config = forms.globalConfig;
807
+ if (!config) return "";
808
+ const effectiveFontFamily = getEffectiveFontFamily(config.fontFamily, typography);
809
+ css.push(`/* Forms Base Styles */`);
810
+ css.push(`.cux-field {`);
811
+ css.push(` position: relative;`);
812
+ css.push(` margin-bottom: ${config.fieldHeight || 95}px;`);
813
+ css.push(`}`);
814
+ if (config.showLabel) {
815
+ css.push(`.cux-label {`);
816
+ css.push(` display: block;`);
817
+ css.push(` font-family: '${effectiveFontFamily}', sans-serif;`);
818
+ css.push(` color: ${config.labelColor || "#212529"};`);
819
+ if (config.labelFontSize) css.push(` font-size: ${buildFontSize(config.labelFontSize)};`);
820
+ css.push(` font-weight: ${config.labelFontWeight || "500"};`);
821
+ css.push(` margin-bottom: ${config.labelMarginBottom || 4}px;`);
822
+ css.push(`}`);
823
+ css.push(`.dark .cux-label {`);
824
+ css.push(` color: ${config.dark?.labelColor || "#f8f9fa"};`);
825
+ css.push(`}`);
826
+ }
827
+ css.push(`.cux-input {`);
828
+ css.push(` width: 100%;`);
829
+ css.push(` font-family: '${effectiveFontFamily}', sans-serif;`);
830
+ css.push(` font-size: ${buildFontSize(config.fontSize || {
831
+ value: 14,
832
+ unit: "px"
833
+ })};`);
834
+ css.push(` color: ${config.color || "#212529"};`);
835
+ css.push(` background: ${config.background || "#ffffff"};`);
836
+ css.push(` border: ${buildBorder(config.border)};`);
837
+ css.push(` border-radius: ${buildBorderRadius(config.borderRadius)};`);
838
+ css.push(` padding: ${buildPadding(config.padding)};`);
839
+ css.push(` transition: border-color 0.15s ease, box-shadow 0.15s ease;`);
840
+ css.push(`}`);
841
+ css.push(`.dark .cux-input {`);
842
+ css.push(` color: ${config.dark?.color || "#f8f9fa"};`);
843
+ css.push(` background: ${config.dark?.background || "#222222"};`);
844
+ css.push(` border-color: ${config.dark?.borderColor || "#495057"};`);
845
+ css.push(`}`);
846
+ if (config.showPlaceholder) {
847
+ css.push(`.cux-input::placeholder {`);
848
+ css.push(` color: ${config.placeholderColor || "#6c757d"};`);
849
+ css.push(` opacity: 1;`);
850
+ css.push(`}`);
851
+ css.push(`.dark .cux-input::placeholder {`);
852
+ css.push(` color: ${config.dark?.placeholderColor || "#adb5bd"};`);
853
+ css.push(`}`);
854
+ }
855
+ css.push(`.cux-input:focus {`);
856
+ css.push(` outline: none;`);
857
+ css.push(` border-color: ${config.border?.color || "#ced4da"};`);
858
+ css.push(` box-shadow: 0 0 0 ${config.focusOutlineWidth || 3}px ${config.focusOutlineColor || "rgba(13, 110, 253, 0.16)"};`);
859
+ css.push(`}`);
860
+ css.push(`.dark .cux-input:focus {`);
861
+ css.push(` border-color: ${config.dark?.borderColor || "#495057"};`);
862
+ css.push(` box-shadow: 0 0 0 ${config.focusOutlineWidth || 3}px ${config.dark?.focusOutlineColor || "rgba(117, 149, 194, 0.4)"};`);
863
+ css.push(`}`);
864
+ css.push(`.cux-input.cux-error,`);
865
+ css.push(`.cux-input[aria-invalid="true"] {`);
866
+ css.push(` border-color: ${config.errorBorderColor || "#dc3545"};`);
867
+ css.push(`}`);
868
+ css.push(`.dark .cux-input.cux-error,`);
869
+ css.push(`.dark .cux-input[aria-invalid="true"] {`);
870
+ css.push(` border-color: ${config.dark?.errorBorderColor || "#ea868f"};`);
871
+ css.push(`}`);
872
+ css.push(`.cux-error-message {`);
873
+ css.push(` font-family: '${effectiveFontFamily}', sans-serif;`);
874
+ css.push(` color: ${config.errorColor || "#dc3545"};`);
875
+ if (config.errorFontSize) css.push(` font-size: ${buildFontSize(config.errorFontSize)};`);
876
+ css.push(` margin-top: ${config.errorMarginTop || 4}px;`);
877
+ css.push(`}`);
878
+ css.push(`.dark .cux-error-message {`);
879
+ css.push(` color: ${config.dark?.errorColor || "#ea868f"};`);
880
+ css.push(`}`);
881
+ css.push(`.cux-input:disabled {`);
882
+ css.push(` opacity: ${config.disabledOpacity || .65};`);
883
+ css.push(` color: ${config.disabledColor || "#6c757d"};`);
884
+ css.push(` background: ${config.disabledBackground || "#e9ecef"};`);
885
+ css.push(` border-color: ${config.disabledBorderColor || "#ced4da"};`);
886
+ css.push(` cursor: not-allowed;`);
887
+ css.push(`}`);
888
+ css.push(`.dark .cux-input:disabled {`);
889
+ css.push(` color: ${config.dark?.disabledColor || "#6c757d"};`);
890
+ css.push(` background: ${config.dark?.disabledBackground || "#222222"};`);
891
+ css.push(` border-color: ${config.dark?.disabledBorderColor || "#495057"};`);
892
+ css.push(`}`);
893
+ css.push(``);
894
+ css.push(`/* Checkbox & Radio */`);
895
+ const checkSize = config.checkRadioSize || 18;
896
+ css.push(`.cux-checkbox,`);
897
+ css.push(`.cux-radio {`);
898
+ css.push(` display: inline-flex;`);
899
+ css.push(` align-items: center;`);
900
+ css.push(` gap: 8px;`);
901
+ css.push(` cursor: pointer;`);
902
+ css.push(`}`);
903
+ css.push(`.cux-checkbox input,`);
904
+ css.push(`.cux-radio input {`);
905
+ css.push(` width: ${checkSize}px;`);
906
+ css.push(` height: ${checkSize}px;`);
907
+ css.push(` accent-color: ${config.checkRadioColor || "#0d6efd"};`);
908
+ css.push(` cursor: pointer;`);
909
+ css.push(`}`);
910
+ css.push(`.dark .cux-checkbox input,`);
911
+ css.push(`.dark .cux-radio input {`);
912
+ css.push(` accent-color: ${config.dark?.checkRadioColor || "#6ea8fe"};`);
913
+ css.push(`}`);
914
+ css.push(`.cux-option-label {`);
915
+ css.push(` font-family: '${config.optionFontFamily || effectiveFontFamily}', sans-serif;`);
916
+ css.push(` color: ${config.optionColor || "#212529"};`);
917
+ if (config.optionFontSize) css.push(` font-size: ${buildFontSize(config.optionFontSize)};`);
918
+ css.push(` font-weight: ${config.optionFontWeight || "400"};`);
919
+ css.push(`}`);
920
+ css.push(`.dark .cux-option-label {`);
921
+ css.push(` color: ${config.dark?.optionColor || "#f8f9fa"};`);
922
+ css.push(`}`);
923
+ const spacingH = config.optionSpacingHorizontal;
924
+ const spacingV = config.optionSpacingVertical;
925
+ css.push(`.cux-option-group {`);
926
+ css.push(` display: flex;`);
927
+ if (config.optionOrientation === "vertical") {
928
+ css.push(` flex-direction: column;`);
929
+ if (spacingV) css.push(` gap: ${buildUnitValue(spacingV)};`);
930
+ } else {
931
+ css.push(` flex-direction: row;`);
932
+ css.push(` flex-wrap: wrap;`);
933
+ if (spacingH) css.push(` gap: ${buildUnitValue(spacingH)};`);
934
+ }
935
+ css.push(`}`);
936
+ css.push(``);
937
+ css.push(`/* Select */`);
938
+ css.push(`.cux-select {`);
939
+ css.push(` width: 100%;`);
940
+ css.push(` font-family: '${effectiveFontFamily}', sans-serif;`);
941
+ css.push(` font-size: ${buildFontSize(config.fontSize || {
942
+ value: 14,
943
+ unit: "px"
944
+ })};`);
945
+ css.push(` color: ${config.color || "#212529"};`);
946
+ css.push(` background: ${config.background || "#ffffff"};`);
947
+ css.push(` border: ${buildBorder(config.border)};`);
948
+ css.push(` border-radius: ${buildBorderRadius(config.borderRadius)};`);
949
+ css.push(` padding: ${buildPadding(config.padding)};`);
950
+ css.push(` cursor: pointer;`);
951
+ css.push(` appearance: none;`);
952
+ css.push(` background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236c757d' d='M6 8L1 3h10z'/%3E%3C/svg%3E");`);
953
+ css.push(` background-repeat: no-repeat;`);
954
+ css.push(` background-position: right 12px center;`);
955
+ css.push(` padding-right: 36px;`);
956
+ css.push(`}`);
957
+ css.push(`.dark .cux-select {`);
958
+ css.push(` color: ${config.dark?.color || "#f8f9fa"};`);
959
+ css.push(` background: ${config.dark?.background || "#222222"};`);
960
+ css.push(` border-color: ${config.dark?.borderColor || "#495057"};`);
961
+ css.push(`}`);
962
+ css.push(``);
963
+ css.push(`/* Textarea */`);
964
+ css.push(`.cux-textarea {`);
965
+ css.push(` width: 100%;`);
966
+ css.push(` min-height: 100px;`);
967
+ css.push(` font-family: '${effectiveFontFamily}', sans-serif;`);
968
+ css.push(` font-size: ${buildFontSize(config.fontSize || {
969
+ value: 14,
970
+ unit: "px"
971
+ })};`);
972
+ css.push(` color: ${config.color || "#212529"};`);
973
+ css.push(` background: ${config.background || "#ffffff"};`);
974
+ css.push(` border: ${buildBorder(config.border)};`);
975
+ css.push(` border-radius: ${buildBorderRadius(config.borderRadius)};`);
976
+ css.push(` padding: ${buildPadding(config.padding)};`);
977
+ css.push(` resize: vertical;`);
978
+ css.push(`}`);
979
+ css.push(`.dark .cux-textarea {`);
980
+ css.push(` color: ${config.dark?.color || "#f8f9fa"};`);
981
+ css.push(` background: ${config.dark?.background || "#222222"};`);
982
+ css.push(` border-color: ${config.dark?.borderColor || "#495057"};`);
983
+ css.push(`}`);
984
+ css.push(``);
985
+ css.push(`/* File / Dropzone */`);
986
+ css.push(`.cux-dropzone {`);
987
+ css.push(` display: flex;`);
988
+ css.push(` flex-direction: column;`);
989
+ css.push(` align-items: center;`);
990
+ css.push(` justify-content: center;`);
991
+ css.push(` padding: ${buildPadding(config.padding)};`);
992
+ css.push(` min-height: 120px;`);
993
+ css.push(` font-family: '${effectiveFontFamily}', sans-serif;`);
994
+ css.push(` background: ${config.dropzoneBackground || "#f8f9fa"};`);
995
+ css.push(` color: ${config.dropzoneColor || "#6c757d"};`);
996
+ if (config.dropzoneBorder) css.push(` border: ${buildBorder(config.dropzoneBorder)};`);
997
+ if (config.dropzoneBorderRadius) css.push(` border-radius: ${buildBorderRadius(config.dropzoneBorderRadius)};`);
998
+ css.push(` cursor: pointer;`);
999
+ css.push(` transition: background-color 0.15s ease, border-color 0.15s ease;`);
1000
+ css.push(`}`);
1001
+ css.push(`.dark .cux-dropzone {`);
1002
+ css.push(` background: ${config.dark?.dropzoneBackground || "#222222"};`);
1003
+ css.push(` color: ${config.dark?.dropzoneColor || "#adb5bd"};`);
1004
+ css.push(` border-color: ${config.dark?.dropzoneBorderColor || "#495057"};`);
1005
+ css.push(`}`);
1006
+ css.push(`.cux-dropzone:hover {`);
1007
+ css.push(` background: ${config.dropzoneBackground || "#f8f9fa"}dd;`);
1008
+ css.push(`}`);
1009
+ return css.join("\n");
1010
+ }
1011
+ //#endregion
1012
+ //#region src/core/button-generator.ts
1013
+ /**
1014
+ * Generate complete CSS for button component
1015
+ */
1016
+ function generateButtonCSS(variants, globalTypography) {
1017
+ const css = [];
1018
+ css.push(generateButtonBase(globalTypography));
1019
+ variants.forEach((variant) => {
1020
+ const variantName = toKebabCase(variant.name);
1021
+ css.push(generateButtonVariant(variant, variantName, globalTypography));
1022
+ if (variant.dark) {
1023
+ const mergedVariant = deepMerge({ ...variant }, variant.dark);
1024
+ css.push(generateButtonVariantDark(mergedVariant, variantName, globalTypography));
1025
+ }
1026
+ });
1027
+ return css.join("\n\n");
1028
+ }
1029
+ /**
1030
+ * Generate base button styles
1031
+ */
1032
+ function generateButtonBase(_globalTypography) {
1033
+ return `/* Button Base Styles */
1034
+ .cux-button {
1035
+ /* CSS Custom Properties (set by variants) */
1036
+ --cux-btn-bg: transparent;
1037
+ --cux-btn-color: inherit;
1038
+ --cux-btn-border: none;
1039
+ --cux-btn-radius: 0;
1040
+ --cux-btn-padding: 0;
1041
+ --cux-btn-font: inherit;
1042
+ --cux-btn-font-size: inherit;
1043
+ --cux-btn-font-weight: inherit;
1044
+ --cux-btn-font-style: inherit;
1045
+ --cux-btn-letter-spacing: inherit;
1046
+ --cux-btn-shadow: none;
1047
+
1048
+ /* Hover state variables */
1049
+ --cux-btn-hover-bg: var(--cux-btn-bg);
1050
+ --cux-btn-hover-color: var(--cux-btn-color);
1051
+ --cux-btn-hover-border: var(--cux-btn-border);
1052
+
1053
+ /* Active state variables */
1054
+ --cux-btn-active-bg: var(--cux-btn-bg);
1055
+ --cux-btn-active-color: var(--cux-btn-color);
1056
+ --cux-btn-active-border: var(--cux-btn-border);
1057
+
1058
+ /* Focus state variables */
1059
+ --cux-btn-focus-color: #3b82f6;
1060
+ --cux-btn-focus-offset: 2px;
1061
+
1062
+ /* Disabled state variables */
1063
+ --cux-btn-disabled-bg: var(--cux-btn-bg);
1064
+ --cux-btn-disabled-color: var(--cux-btn-color);
1065
+ --cux-btn-disabled-border: var(--cux-btn-border);
1066
+ --cux-btn-disabled-opacity: 0.5;
1067
+
1068
+ /* Base styles */
1069
+ background: var(--cux-btn-bg);
1070
+ color: var(--cux-btn-color);
1071
+ border: var(--cux-btn-border);
1072
+ border-radius: var(--cux-btn-radius);
1073
+ padding: var(--cux-btn-padding);
1074
+ font-family: var(--cux-btn-font);
1075
+ font-size: var(--cux-btn-font-size);
1076
+ font-weight: var(--cux-btn-font-weight);
1077
+ font-style: var(--cux-btn-font-style);
1078
+ letter-spacing: var(--cux-btn-letter-spacing);
1079
+ box-shadow: var(--cux-btn-shadow);
1080
+
1081
+ cursor: pointer;
1082
+ display: inline-flex;
1083
+ align-items: center;
1084
+ justify-content: center;
1085
+ gap: 8px;
1086
+ text-decoration: none;
1087
+ transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
1088
+ }
1089
+
1090
+ /* Hover state */
1091
+ .cux-button:hover:not(:disabled) {
1092
+ background: var(--cux-btn-hover-bg);
1093
+ color: var(--cux-btn-hover-color);
1094
+ border: var(--cux-btn-hover-border);
1095
+ }
1096
+
1097
+ /* Active state */
1098
+ .cux-button:active:not(:disabled) {
1099
+ background: var(--cux-btn-active-bg);
1100
+ color: var(--cux-btn-active-color);
1101
+ border: var(--cux-btn-active-border);
1102
+ }
1103
+
1104
+ /* Focus state */
1105
+ .cux-button:focus-visible {
1106
+ outline: 2px solid var(--cux-btn-focus-color);
1107
+ outline-offset: var(--cux-btn-focus-offset);
1108
+ }
1109
+
1110
+ /* Disabled state */
1111
+ .cux-button:disabled {
1112
+ background: var(--cux-btn-disabled-bg);
1113
+ color: var(--cux-btn-disabled-color);
1114
+ border: var(--cux-btn-disabled-border);
1115
+ opacity: var(--cux-btn-disabled-opacity);
1116
+ cursor: not-allowed;
1117
+ }`;
1118
+ }
1119
+ /**
1120
+ * Generate CSS for a specific button variant
1121
+ */
1122
+ function generateButtonVariant(variant, variantName, globalTypography) {
1123
+ const lines = [];
1124
+ lines.push(`/* Variant: ${variant.name} */`);
1125
+ lines.push(`.cux-button.--${variantName} {`);
1126
+ lines.push(` --cux-btn-bg: ${variant.background};`);
1127
+ lines.push(` --cux-btn-color: ${variant.color};`);
1128
+ if (variant.border) lines.push(` --cux-btn-border: ${buildBorder(variant.border)};`);
1129
+ if (variant.borderRadius) lines.push(` --cux-btn-radius: ${buildBorderRadius(variant.borderRadius)};`);
1130
+ if (variant.padding) lines.push(` --cux-btn-padding: ${buildPadding(variant.padding)};`);
1131
+ const fontFamily = variant.fontFamily ?? globalTypography?.fontFamily;
1132
+ if (fontFamily) lines.push(` --cux-btn-font: '${fontFamily}', sans-serif;`);
1133
+ if (variant.fontSize) lines.push(` --cux-btn-font-size: ${buildFontSize(variant.fontSize)};`);
1134
+ if (variant.fontWeight) lines.push(` --cux-btn-font-weight: ${variant.fontWeight};`);
1135
+ if (variant.fontStyle) lines.push(` --cux-btn-font-style: ${variant.fontStyle};`);
1136
+ if (variant.letterSpacing) lines.push(` --cux-btn-letter-spacing: ${buildLetterSpacing(variant.letterSpacing)};`);
1137
+ if (variant.shadows) {
1138
+ const shadowValue = buildShadows(variant.shadows);
1139
+ if (shadowValue) lines.push(` --cux-btn-shadow: ${shadowValue};`);
1140
+ }
1141
+ if (variant.hoverBackground) lines.push(` --cux-btn-hover-bg: ${variant.hoverBackground};`);
1142
+ if (variant.hoverColor) lines.push(` --cux-btn-hover-color: ${variant.hoverColor};`);
1143
+ if (variant.hoverBorder) lines.push(` --cux-btn-hover-border: ${buildBorderOptional(variant.hoverBorder)};`);
1144
+ if (variant.activeBackground) lines.push(` --cux-btn-active-bg: ${variant.activeBackground};`);
1145
+ if (variant.activeColor) lines.push(` --cux-btn-active-color: ${variant.activeColor};`);
1146
+ if (variant.activeBorder) lines.push(` --cux-btn-active-border: ${buildBorderOptional(variant.activeBorder)};`);
1147
+ if (variant.focusColor) lines.push(` --cux-btn-focus-color: ${variant.focusColor};`);
1148
+ if (variant.focusOffset !== void 0) lines.push(` --cux-btn-focus-offset: ${buildOffset(variant.focusOffset)};`);
1149
+ if (variant.disabledBackground) lines.push(` --cux-btn-disabled-bg: ${variant.disabledBackground};`);
1150
+ if (variant.disabledColor) lines.push(` --cux-btn-disabled-color: ${variant.disabledColor};`);
1151
+ if (variant.disabledBorder) lines.push(` --cux-btn-disabled-border: ${buildBorderOptional(variant.disabledBorder)};`);
1152
+ if (variant.disabledOpacity !== void 0) lines.push(` --cux-btn-disabled-opacity: ${variant.disabledOpacity};`);
1153
+ lines.push("}");
1154
+ return lines.join("\n");
1155
+ }
1156
+ /**
1157
+ * Generate dark mode CSS for a button variant
1158
+ */
1159
+ function generateButtonVariantDark(variant, variantName, globalTypography) {
1160
+ const lines = [];
1161
+ lines.push(`/* Dark Mode Variant: ${variant.name} */`);
1162
+ lines.push(`.dark .cux-button.--${variantName} {`);
1163
+ if (variant.background) lines.push(` --cux-btn-bg: ${variant.background};`);
1164
+ if (variant.color) lines.push(` --cux-btn-color: ${variant.color};`);
1165
+ if (variant.border) lines.push(` --cux-btn-border: ${buildBorder(variant.border)};`);
1166
+ const fontFamily = variant.fontFamily ?? globalTypography?.fontFamily;
1167
+ if (fontFamily) lines.push(` --cux-btn-font: '${fontFamily}', sans-serif;`);
1168
+ if (variant.shadows) {
1169
+ const shadowValue = buildShadowsDark(variant.shadows, variant.dark);
1170
+ if (shadowValue) lines.push(` --cux-btn-shadow: ${shadowValue};`);
1171
+ }
1172
+ if (variant.hoverBackground) lines.push(` --cux-btn-hover-bg: ${variant.hoverBackground};`);
1173
+ if (variant.hoverColor) lines.push(` --cux-btn-hover-color: ${variant.hoverColor};`);
1174
+ if (variant.hoverBorder) lines.push(` --cux-btn-hover-border: ${buildBorderOptional(variant.hoverBorder)};`);
1175
+ if (variant.activeBackground) lines.push(` --cux-btn-active-bg: ${variant.activeBackground};`);
1176
+ if (variant.activeColor) lines.push(` --cux-btn-active-color: ${variant.activeColor};`);
1177
+ lines.push("}");
1178
+ return lines.join("\n");
1179
+ }
1180
+ /**
1181
+ * Build a CSS box-shadow string from ComponentShadows (handles offset, inset, and insetHighlight)
1182
+ */
1183
+ function buildShadows(shadows) {
1184
+ if (!shadows) return "";
1185
+ const shadowParts = [];
1186
+ if (shadows.offset?.enabled) {
1187
+ const { offsetX, offsetY, blur, spread, color } = shadows.offset;
1188
+ shadowParts.push(`${offsetX}px ${offsetY}px ${blur}px ${spread}px ${color}`);
1189
+ }
1190
+ if (shadows.inset?.enabled) {
1191
+ const { offsetX, offsetY, blur, spread, color } = shadows.inset;
1192
+ shadowParts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${color}`);
1193
+ }
1194
+ if (shadows.insetHighlight?.enabled) {
1195
+ const { offsetX, offsetY, blur, spread, color } = shadows.insetHighlight;
1196
+ shadowParts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${color}`);
1197
+ }
1198
+ return shadowParts.join(", ");
1199
+ }
1200
+ /**
1201
+ * Build shadows with dark mode color overrides
1202
+ */
1203
+ function buildShadowsDark(shadows, dark) {
1204
+ const shadowParts = [];
1205
+ if (shadows.offset?.enabled) {
1206
+ const { offsetX, offsetY, blur, spread, color } = shadows.offset;
1207
+ const darkColor = dark?.shadowColor || color;
1208
+ shadowParts.push(`${offsetX}px ${offsetY}px ${blur}px ${spread}px ${darkColor}`);
1209
+ }
1210
+ if (shadows.inset?.enabled) {
1211
+ const { offsetX, offsetY, blur, spread, color } = shadows.inset;
1212
+ const darkColor = dark?.shadowInsetColor || color;
1213
+ shadowParts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${darkColor}`);
1214
+ }
1215
+ if (shadows.insetHighlight?.enabled) {
1216
+ const { offsetX, offsetY, blur, spread, color } = shadows.insetHighlight;
1217
+ const darkColor = dark?.shadowInsetHighlightColor || color;
1218
+ shadowParts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${darkColor}`);
1219
+ }
1220
+ return shadowParts.join(", ");
1221
+ }
1222
+ //#endregion
1223
+ //#region src/core/css-generator-base.ts
1224
+ /**
1225
+ * Generate dark mode border override CSS
1226
+ * Used by: badge, avatar, card, alert, chip, progress generators
1227
+ */
1228
+ function generateDarkBorderOverride(componentName, border, darkBorderColor) {
1229
+ if (!darkBorderColor || !border) return "";
1230
+ return ` --cux-${componentName}-border: ${border.width}${border.unit} ${border.style} ${darkBorderColor};`;
1231
+ }
1232
+ /**
1233
+ * Generate shadow CSS variable for a component
1234
+ * Returns empty string if no shadow
1235
+ */
1236
+ function generateShadowVar(componentName, shadows) {
1237
+ if (!shadows) return "";
1238
+ const parts = [];
1239
+ if (shadows.offset?.enabled) {
1240
+ const { offsetX, offsetY, blur, spread, color } = shadows.offset;
1241
+ parts.push(`${offsetX}px ${offsetY}px ${blur}px ${spread}px ${color}`);
1242
+ }
1243
+ if (shadows.inset?.enabled) {
1244
+ const { offsetX, offsetY, blur, spread, color } = shadows.inset;
1245
+ parts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${color}`);
1246
+ }
1247
+ if (shadows.insetHighlight?.enabled) {
1248
+ const { offsetX, offsetY, blur, spread, color } = shadows.insetHighlight;
1249
+ parts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${color}`);
1250
+ }
1251
+ return parts.length > 0 ? ` --cux-${componentName}-shadow: ${parts.join(", ")};` : "";
1252
+ }
1253
+ /**
1254
+ * Generate dark mode shadow CSS variable
1255
+ */
1256
+ function generateDarkShadowVar(componentName, shadows, darkColors) {
1257
+ if (!shadows) return "";
1258
+ const parts = [];
1259
+ if (shadows.offset?.enabled) {
1260
+ const { offsetX, offsetY, blur, spread, color } = shadows.offset;
1261
+ const darkColor = darkColors?.shadowColor || color;
1262
+ parts.push(`${offsetX}px ${offsetY}px ${blur}px ${spread}px ${darkColor}`);
1263
+ }
1264
+ if (shadows.inset?.enabled) {
1265
+ const { offsetX, offsetY, blur, spread, color } = shadows.inset;
1266
+ const darkColor = darkColors?.shadowInsetColor || color;
1267
+ parts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${darkColor}`);
1268
+ }
1269
+ if (shadows.insetHighlight?.enabled) {
1270
+ const { offsetX, offsetY, blur, spread, color } = shadows.insetHighlight;
1271
+ const darkColor = darkColors?.shadowInsetHighlightColor || color;
1272
+ parts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${darkColor}`);
1273
+ }
1274
+ return parts.length > 0 ? ` --cux-${componentName}-shadow: ${parts.join(", ")};` : "";
1275
+ }
1276
+ /**
1277
+ * Generate offset shadow for components that separate offset from inset shadows
1278
+ * Used by: card, alert, progress (overlay pattern)
1279
+ */
1280
+ function generateOffsetShadowVar(componentName, shadows) {
1281
+ if (!shadows?.offset?.enabled) return "";
1282
+ const { offsetX, offsetY, blur, spread, color } = shadows.offset;
1283
+ return ` --cux-${componentName}-shadow: ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${color};`;
1284
+ }
1285
+ /**
1286
+ * Generate inset shadow variable for overlay pattern
1287
+ */
1288
+ function generateInsetShadowVar(componentName, shadows) {
1289
+ if (!shadows) return "";
1290
+ const parts = [];
1291
+ if (shadows.inset?.enabled) {
1292
+ const { offsetX, offsetY, blur, spread, color } = shadows.inset;
1293
+ parts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${color}`);
1294
+ }
1295
+ if (shadows.insetHighlight?.enabled) {
1296
+ const { offsetX, offsetY, blur, spread, color } = shadows.insetHighlight;
1297
+ parts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${color}`);
1298
+ }
1299
+ return parts.length > 0 ? ` --cux-${componentName}-inset-shadow: ${parts.join(", ")};` : "";
1300
+ }
1301
+ /**
1302
+ * Generate dark mode offset shadow
1303
+ */
1304
+ function generateDarkOffsetShadowVar(componentName, shadows, shadowColor) {
1305
+ if (!shadows?.offset?.enabled) return "";
1306
+ const { offsetX, offsetY, blur, spread, color } = shadows.offset;
1307
+ return ` --cux-${componentName}-shadow: ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${shadowColor || color};`;
1308
+ }
1309
+ /**
1310
+ * Generate dark mode inset shadow
1311
+ */
1312
+ function generateDarkInsetShadowVar(componentName, shadows, shadowInsetColor, shadowInsetHighlightColor) {
1313
+ if (!shadows) return "";
1314
+ const parts = [];
1315
+ if (shadows.inset?.enabled) {
1316
+ const { offsetX, offsetY, blur, spread, color } = shadows.inset;
1317
+ parts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${shadowInsetColor || color}`);
1318
+ }
1319
+ if (shadows.insetHighlight?.enabled) {
1320
+ const { offsetX, offsetY, blur, spread, color } = shadows.insetHighlight;
1321
+ parts.push(`inset ${offsetX}px ${offsetY}px ${blur}px ${spread}px ${shadowInsetHighlightColor || color}`);
1322
+ }
1323
+ return parts.length > 0 ? ` --cux-${componentName}-inset-shadow: ${parts.join(", ")};` : "";
1324
+ }
1325
+ /**
1326
+ * Generate typography CSS lines for a component
1327
+ * Returns array of CSS lines (without selector)
1328
+ */
1329
+ function generateTypographyLines(options, globalConfig) {
1330
+ const lines = [];
1331
+ const effectiveFontFamily = getEffectiveFontFamily$2(options.fontFamily, globalConfig?.fontFamily);
1332
+ if (effectiveFontFamily) lines.push(` font-family: '${effectiveFontFamily}', sans-serif;`);
1333
+ if (options.fontSize) lines.push(` font-size: ${buildFontSize(options.fontSize)};`);
1334
+ if (options.fontWeight) lines.push(` font-weight: ${options.fontWeight};`);
1335
+ if (options.fontStyle) lines.push(` font-style: ${options.fontStyle};`);
1336
+ if (options.letterSpacing) lines.push(` letter-spacing: ${buildLetterSpacing(options.letterSpacing)};`);
1337
+ if (options.textAlign) lines.push(` text-align: ${options.textAlign};`);
1338
+ return lines;
1339
+ }
1340
+ /**
1341
+ * Generate typography CSS block with selector
1342
+ */
1343
+ function generateTypographyBlock(selector, options, globalConfig) {
1344
+ const lines = generateTypographyLines(options, globalConfig);
1345
+ if (lines.length === 0) return "";
1346
+ return `${selector} {
1347
+ ${lines.join("\n")}
1348
+ }`;
1349
+ }
1350
+ /**
1351
+ * Generate base variant CSS properties (background, color, border, radius, padding)
1352
+ */
1353
+ function generateBaseProperties(componentName, variant) {
1354
+ const lines = [];
1355
+ lines.push(` --cux-${componentName}-bg: ${variant.background};`);
1356
+ lines.push(` --cux-${componentName}-color: ${variant.color};`);
1357
+ if (variant.border) lines.push(` --cux-${componentName}-border: ${buildBorder(variant.border)};`);
1358
+ if (variant.borderRadius) lines.push(` --cux-${componentName}-radius: ${buildBorderRadius(variant.borderRadius)};`);
1359
+ if (variant.padding) lines.push(` --cux-${componentName}-padding: ${buildPadding(variant.padding)};`);
1360
+ return lines;
1361
+ }
1362
+ /**
1363
+ * Generate dark mode base properties
1364
+ */
1365
+ function generateDarkBaseProperties(componentName, dark) {
1366
+ const lines = [];
1367
+ if (dark.background) lines.push(` --cux-${componentName}-bg: ${dark.background};`);
1368
+ if (dark.color) lines.push(` --cux-${componentName}-color: ${dark.color};`);
1369
+ return lines;
1370
+ }
1371
+ //#endregion
1372
+ //#region src/core/card-generator.ts
1373
+ const COMPONENT$6 = "card";
1374
+ /**
1375
+ * Generate complete CSS for card component
1376
+ */
1377
+ function generateCardCSS(variants, globalConfig) {
1378
+ const css = [];
1379
+ css.push(generateCardBase());
1380
+ variants.forEach((variant) => {
1381
+ const variantName = toKebabCase(variant.name);
1382
+ css.push(generateCardVariant(variant, variantName, globalConfig));
1383
+ if (variant.dark) css.push(generateCardVariantDark(variant, variantName));
1384
+ });
1385
+ return css.join("\n\n");
1386
+ }
1387
+ /**
1388
+ * Generate base card styles
1389
+ */
1390
+ function generateCardBase() {
1391
+ return `/* Card Base Styles */
1392
+ .cux-${COMPONENT$6} {
1393
+ --cux-${COMPONENT$6}-bg: #ffffff;
1394
+ --cux-${COMPONENT$6}-color: inherit;
1395
+ --cux-${COMPONENT$6}-border: none;
1396
+ --cux-${COMPONENT$6}-radius: 0;
1397
+ --cux-${COMPONENT$6}-padding: 0;
1398
+ --cux-${COMPONENT$6}-shadow: none;
1399
+ --cux-${COMPONENT$6}-inset-shadow: none;
1400
+
1401
+ /* Header properties */
1402
+ --cux-${COMPONENT$6}-header-bg: transparent;
1403
+ --cux-${COMPONENT$6}-header-color: inherit;
1404
+ --cux-${COMPONENT$6}-header-padding: 0;
1405
+ --cux-${COMPONENT$6}-header-border-bottom: none;
1406
+
1407
+ position: relative;
1408
+ background: var(--cux-${COMPONENT$6}-bg);
1409
+ color: var(--cux-${COMPONENT$6}-color);
1410
+ border: var(--cux-${COMPONENT$6}-border);
1411
+ border-radius: var(--cux-${COMPONENT$6}-radius);
1412
+ box-shadow: var(--cux-${COMPONENT$6}-shadow);
1413
+ overflow: hidden;
1414
+ }
1415
+
1416
+ .cux-${COMPONENT$6}-inset-overlay {
1417
+ position: absolute;
1418
+ inset: 0;
1419
+ z-index: 2;
1420
+ border-radius: var(--cux-${COMPONENT$6}-radius);
1421
+ box-shadow: var(--cux-${COMPONENT$6}-inset-shadow);
1422
+ pointer-events: none;
1423
+ }
1424
+
1425
+ .cux-${COMPONENT$6}-header {
1426
+ position: relative;
1427
+ z-index: 1;
1428
+ background: var(--cux-${COMPONENT$6}-header-bg);
1429
+ color: var(--cux-${COMPONENT$6}-header-color);
1430
+ padding: var(--cux-${COMPONENT$6}-header-padding);
1431
+ border-bottom: var(--cux-${COMPONENT$6}-header-border-bottom);
1432
+ }
1433
+
1434
+ .cux-${COMPONENT$6}-body {
1435
+ position: relative;
1436
+ z-index: 1;
1437
+ padding: var(--cux-${COMPONENT$6}-padding);
1438
+ }
1439
+
1440
+ .cux-${COMPONENT$6}-footer {
1441
+ position: relative;
1442
+ z-index: 1;
1443
+ padding: var(--cux-${COMPONENT$6}-padding);
1444
+ border-top: var(--cux-${COMPONENT$6}-header-border-bottom);
1445
+ }`;
1446
+ }
1447
+ /**
1448
+ * Generate CSS for a specific card variant
1449
+ */
1450
+ function generateCardVariant(variant, variantName, globalConfig) {
1451
+ const lines = [];
1452
+ lines.push(`/* Variant: ${variant.name} */`);
1453
+ lines.push(`.cux-${COMPONENT$6}.--${variantName} {`);
1454
+ lines.push(` --cux-${COMPONENT$6}-bg: ${variant.background};`);
1455
+ lines.push(` --cux-${COMPONENT$6}-color: ${variant.color};`);
1456
+ if (variant.border) lines.push(` --cux-${COMPONENT$6}-border: ${buildBorder(variant.border)};`);
1457
+ if (variant.borderRadius) lines.push(` --cux-${COMPONENT$6}-radius: ${variant.borderRadius.tl}${variant.borderRadius.unit};`);
1458
+ if (variant.padding) lines.push(` --cux-${COMPONENT$6}-padding: ${buildPadding(variant.padding)};`);
1459
+ const offsetShadow = generateOffsetShadowVar(COMPONENT$6, variant.shadows);
1460
+ if (offsetShadow) lines.push(offsetShadow);
1461
+ const insetShadow = generateInsetShadowVar(COMPONENT$6, variant.shadows);
1462
+ if (insetShadow) lines.push(insetShadow);
1463
+ lines.push(` --cux-${COMPONENT$6}-header-bg: ${variant.headerBackground};`);
1464
+ lines.push(` --cux-${COMPONENT$6}-header-color: ${variant.headerColor};`);
1465
+ if (variant.headerPadding) lines.push(` --cux-${COMPONENT$6}-header-padding: ${buildPadding(variant.headerPadding)};`);
1466
+ if (variant.headerBorderBottom) lines.push(` --cux-${COMPONENT$6}-header-border-bottom: ${buildBorder(variant.headerBorderBottom)};`);
1467
+ lines.push("}");
1468
+ const bodyTypography = generateTypographyLines({
1469
+ fontFamily: variant.fontFamily,
1470
+ fontSize: variant.fontSize,
1471
+ fontWeight: variant.fontWeight,
1472
+ fontStyle: variant.fontStyle,
1473
+ letterSpacing: variant.letterSpacing,
1474
+ textAlign: variant.textAlign
1475
+ }, globalConfig);
1476
+ if (bodyTypography.length > 0) {
1477
+ lines.push("");
1478
+ lines.push(`.cux-${COMPONENT$6}.--${variantName} .cux-${COMPONENT$6}-body {`);
1479
+ lines.push(...bodyTypography);
1480
+ lines.push("}");
1481
+ }
1482
+ const headerTypography = generateTypographyLines({
1483
+ fontFamily: variant.headerFontFamily,
1484
+ fontSize: variant.headerFontSize,
1485
+ fontWeight: variant.headerFontWeight,
1486
+ fontStyle: variant.headerFontStyle,
1487
+ letterSpacing: variant.headerLetterSpacing,
1488
+ textAlign: variant.headerTextAlign
1489
+ }, globalConfig);
1490
+ if (headerTypography.length > 0) {
1491
+ lines.push("");
1492
+ lines.push(`.cux-${COMPONENT$6}.--${variantName} .cux-${COMPONENT$6}-header {`);
1493
+ lines.push(...headerTypography);
1494
+ lines.push("}");
1495
+ }
1496
+ return lines.join("\n");
1497
+ }
1498
+ /**
1499
+ * Generate dark mode CSS for a card variant
1500
+ */
1501
+ function generateCardVariantDark(variant, variantName) {
1502
+ const dark = variant.dark;
1503
+ if (!dark) return "";
1504
+ const lines = [];
1505
+ lines.push(`/* Dark Mode Variant: ${variant.name} */`);
1506
+ lines.push(`.dark .cux-${COMPONENT$6}.--${variantName} {`);
1507
+ lines.push(...generateDarkBaseProperties(COMPONENT$6, dark));
1508
+ const borderOverride = generateDarkBorderOverride(COMPONENT$6, variant.border, dark.borderColor);
1509
+ if (borderOverride) lines.push(borderOverride);
1510
+ if (dark.headerBackground) lines.push(` --cux-${COMPONENT$6}-header-bg: ${dark.headerBackground};`);
1511
+ if (dark.headerColor) lines.push(` --cux-${COMPONENT$6}-header-color: ${dark.headerColor};`);
1512
+ if (dark.headerBorderBottomColor && variant.headerBorderBottom) lines.push(` --cux-${COMPONENT$6}-header-border-bottom: ${variant.headerBorderBottom.width}${variant.headerBorderBottom.unit} ${variant.headerBorderBottom.style} ${dark.headerBorderBottomColor};`);
1513
+ const offsetShadow = generateDarkOffsetShadowVar(COMPONENT$6, variant.shadows, dark.shadowColor);
1514
+ if (offsetShadow) lines.push(offsetShadow);
1515
+ const insetShadow = generateDarkInsetShadowVar(COMPONENT$6, variant.shadows, dark.shadowInsetColor, dark.shadowInsetHighlightColor);
1516
+ if (insetShadow) lines.push(insetShadow);
1517
+ lines.push("}");
1518
+ return lines.join("\n");
1519
+ }
1520
+ //#endregion
1521
+ //#region src/core/alert-generator.ts
1522
+ const COMPONENT$5 = "alert";
1523
+ /**
1524
+ * Generate complete CSS for alert component
1525
+ */
1526
+ function generateAlertCSS(variants, globalConfig) {
1527
+ const css = [];
1528
+ css.push(generateAlertBase());
1529
+ variants.forEach((variant) => {
1530
+ const variantName = toKebabCase(variant.name);
1531
+ css.push(generateAlertVariant(variant, variantName, globalConfig));
1532
+ if (variant.dark) css.push(generateAlertVariantDark(variant, variantName));
1533
+ });
1534
+ return css.join("\n\n");
1535
+ }
1536
+ /**
1537
+ * Generate base alert styles
1538
+ */
1539
+ function generateAlertBase() {
1540
+ return `/* Alert Base Styles */
1541
+ .cux-${COMPONENT$5} {
1542
+ --cux-${COMPONENT$5}-bg: transparent;
1543
+ --cux-${COMPONENT$5}-color: inherit;
1544
+ --cux-${COMPONENT$5}-border: none;
1545
+ --cux-${COMPONENT$5}-radius: 0;
1546
+ --cux-${COMPONENT$5}-padding: 0;
1547
+ --cux-${COMPONENT$5}-shadow: none;
1548
+ --cux-${COMPONENT$5}-inset-shadow: none;
1549
+
1550
+ /* Header properties */
1551
+ --cux-${COMPONENT$5}-header-bg: transparent;
1552
+ --cux-${COMPONENT$5}-header-color: inherit;
1553
+ --cux-${COMPONENT$5}-header-padding: 0;
1554
+ --cux-${COMPONENT$5}-header-border-bottom: none;
1555
+
1556
+ /* Close button properties */
1557
+ --cux-${COMPONENT$5}-close-size: 20px;
1558
+ --cux-${COMPONENT$5}-close-color: #6c757d;
1559
+ --cux-${COMPONENT$5}-close-hover-color: #495057;
1560
+ --cux-${COMPONENT$5}-close-active-color: #212529;
1561
+
1562
+ /* Layout */
1563
+ --cux-${COMPONENT$5}-max-width: 500px;
1564
+ --cux-${COMPONENT$5}-offset: 16px;
1565
+
1566
+ position: relative;
1567
+ background: var(--cux-${COMPONENT$5}-bg);
1568
+ color: var(--cux-${COMPONENT$5}-color);
1569
+ border: var(--cux-${COMPONENT$5}-border);
1570
+ border-radius: var(--cux-${COMPONENT$5}-radius);
1571
+ box-shadow: var(--cux-${COMPONENT$5}-shadow);
1572
+ max-width: var(--cux-${COMPONENT$5}-max-width);
1573
+ overflow: hidden;
1574
+ }
1575
+
1576
+ .cux-${COMPONENT$5}-inset-overlay {
1577
+ position: absolute;
1578
+ inset: 0;
1579
+ z-index: 2;
1580
+ border-radius: var(--cux-${COMPONENT$5}-radius);
1581
+ box-shadow: var(--cux-${COMPONENT$5}-inset-shadow);
1582
+ pointer-events: none;
1583
+ }
1584
+
1585
+ .cux-${COMPONENT$5}-header {
1586
+ position: relative;
1587
+ z-index: 1;
1588
+ display: flex;
1589
+ align-items: center;
1590
+ justify-content: space-between;
1591
+ gap: 8px;
1592
+ background: var(--cux-${COMPONENT$5}-header-bg);
1593
+ color: var(--cux-${COMPONENT$5}-header-color);
1594
+ padding: var(--cux-${COMPONENT$5}-header-padding);
1595
+ border-bottom: var(--cux-${COMPONENT$5}-header-border-bottom);
1596
+ }
1597
+
1598
+ .cux-${COMPONENT$5}-body {
1599
+ position: relative;
1600
+ z-index: 1;
1601
+ padding: var(--cux-${COMPONENT$5}-padding);
1602
+ }
1603
+
1604
+ .cux-${COMPONENT$5}-close {
1605
+ flex-shrink: 0;
1606
+ width: var(--cux-${COMPONENT$5}-close-size);
1607
+ height: var(--cux-${COMPONENT$5}-close-size);
1608
+ background: transparent;
1609
+ border: none;
1610
+ color: var(--cux-${COMPONENT$5}-close-color);
1611
+ cursor: pointer;
1612
+ display: flex;
1613
+ align-items: center;
1614
+ justify-content: center;
1615
+ padding: 0;
1616
+ border-radius: 4px;
1617
+ transition: color 0.15s ease;
1618
+ }
1619
+
1620
+ .cux-${COMPONENT$5}-close:hover { color: var(--cux-${COMPONENT$5}-close-hover-color); }
1621
+ .cux-${COMPONENT$5}-close:active { color: var(--cux-${COMPONENT$5}-close-active-color); }
1622
+ .cux-${COMPONENT$5}-close svg { width: 100%; height: 100%; }
1623
+
1624
+ /* Position modifiers */
1625
+ .cux-${COMPONENT$5}.--top-left { position: fixed; top: var(--cux-${COMPONENT$5}-offset); left: var(--cux-${COMPONENT$5}-offset); z-index: 9999; }
1626
+ .cux-${COMPONENT$5}.--top-center { position: fixed; top: var(--cux-${COMPONENT$5}-offset); left: 50%; transform: translateX(-50%); z-index: 9999; }
1627
+ .cux-${COMPONENT$5}.--top-right { position: fixed; top: var(--cux-${COMPONENT$5}-offset); right: var(--cux-${COMPONENT$5}-offset); z-index: 9999; }
1628
+ .cux-${COMPONENT$5}.--center-left { position: fixed; top: 50%; left: var(--cux-${COMPONENT$5}-offset); transform: translateY(-50%); z-index: 9999; }
1629
+ .cux-${COMPONENT$5}.--center-center { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 9999; }
1630
+ .cux-${COMPONENT$5}.--center-right { position: fixed; top: 50%; right: var(--cux-${COMPONENT$5}-offset); transform: translateY(-50%); z-index: 9999; }
1631
+ .cux-${COMPONENT$5}.--bottom-left { position: fixed; bottom: var(--cux-${COMPONENT$5}-offset); left: var(--cux-${COMPONENT$5}-offset); z-index: 9999; }
1632
+ .cux-${COMPONENT$5}.--bottom-center { position: fixed; bottom: var(--cux-${COMPONENT$5}-offset); left: 50%; transform: translateX(-50%); z-index: 9999; }
1633
+ .cux-${COMPONENT$5}.--bottom-right { position: fixed; bottom: var(--cux-${COMPONENT$5}-offset); right: var(--cux-${COMPONENT$5}-offset); z-index: 9999; }`;
1634
+ }
1635
+ /**
1636
+ * Generate CSS for a specific alert variant
1637
+ */
1638
+ function generateAlertVariant(variant, variantName, globalConfig) {
1639
+ const lines = [];
1640
+ lines.push(`/* Variant: ${variant.name} */`);
1641
+ lines.push(`.cux-${COMPONENT$5}.--${variantName} {`);
1642
+ lines.push(` --cux-${COMPONENT$5}-bg: ${variant.background};`);
1643
+ lines.push(` --cux-${COMPONENT$5}-color: ${variant.color};`);
1644
+ if (variant.border) lines.push(` --cux-${COMPONENT$5}-border: ${buildBorder(variant.border)};`);
1645
+ if (variant.borderRadius) lines.push(` --cux-${COMPONENT$5}-radius: ${variant.borderRadius.tl}${variant.borderRadius.unit};`);
1646
+ if (variant.padding) lines.push(` --cux-${COMPONENT$5}-padding: ${buildPadding(variant.padding)};`);
1647
+ const offsetShadow = generateOffsetShadowVar(COMPONENT$5, variant.shadows);
1648
+ if (offsetShadow) lines.push(offsetShadow);
1649
+ const insetShadow = generateInsetShadowVar(COMPONENT$5, variant.shadows);
1650
+ if (insetShadow) lines.push(insetShadow);
1651
+ lines.push(` --cux-${COMPONENT$5}-header-bg: ${variant.headerBackground};`);
1652
+ lines.push(` --cux-${COMPONENT$5}-header-color: ${variant.headerColor};`);
1653
+ if (variant.headerPadding) lines.push(` --cux-${COMPONENT$5}-header-padding: ${buildPadding(variant.headerPadding)};`);
1654
+ if (variant.headerBorderBottom) lines.push(` --cux-${COMPONENT$5}-header-border-bottom: ${buildBorder(variant.headerBorderBottom)};`);
1655
+ if (variant.closeSize) lines.push(` --cux-${COMPONENT$5}-close-size: ${variant.closeSize.value}${variant.closeSize.unit};`);
1656
+ lines.push(` --cux-${COMPONENT$5}-close-color: ${variant.closeColor};`);
1657
+ lines.push(` --cux-${COMPONENT$5}-close-hover-color: ${variant.closeHoverColor};`);
1658
+ lines.push(` --cux-${COMPONENT$5}-close-active-color: ${variant.closeActiveColor};`);
1659
+ lines.push(` --cux-${COMPONENT$5}-max-width: ${variant.maxWidth.value}${variant.maxWidth.unit};`);
1660
+ lines.push(` --cux-${COMPONENT$5}-offset: ${variant.offset.value}${variant.offset.unit};`);
1661
+ lines.push("}");
1662
+ const bodyTypography = generateTypographyLines({
1663
+ fontFamily: variant.fontFamily,
1664
+ fontSize: variant.fontSize,
1665
+ fontWeight: variant.fontWeight,
1666
+ fontStyle: variant.fontStyle,
1667
+ letterSpacing: variant.letterSpacing,
1668
+ textAlign: variant.textAlign
1669
+ }, globalConfig);
1670
+ if (bodyTypography.length > 0) {
1671
+ lines.push("");
1672
+ lines.push(`.cux-${COMPONENT$5}.--${variantName} .cux-${COMPONENT$5}-body {`);
1673
+ lines.push(...bodyTypography);
1674
+ lines.push("}");
1675
+ }
1676
+ const headerTypography = generateTypographyLines({
1677
+ fontFamily: variant.headerFontFamily,
1678
+ fontSize: variant.headerFontSize,
1679
+ fontWeight: variant.headerFontWeight,
1680
+ fontStyle: variant.headerFontStyle,
1681
+ letterSpacing: variant.headerLetterSpacing,
1682
+ textAlign: variant.headerTextAlign
1683
+ }, globalConfig);
1684
+ if (headerTypography.length > 0) {
1685
+ lines.push("");
1686
+ lines.push(`.cux-${COMPONENT$5}.--${variantName} .cux-${COMPONENT$5}-header {`);
1687
+ lines.push(...headerTypography);
1688
+ lines.push("}");
1689
+ }
1690
+ return lines.join("\n");
1691
+ }
1692
+ /**
1693
+ * Generate dark mode CSS for an alert variant
1694
+ */
1695
+ function generateAlertVariantDark(variant, variantName) {
1696
+ const dark = variant.dark;
1697
+ if (!dark) return "";
1698
+ const lines = [];
1699
+ lines.push(`/* Dark Mode Variant: ${variant.name} */`);
1700
+ lines.push(`.dark .cux-${COMPONENT$5}.--${variantName} {`);
1701
+ lines.push(...generateDarkBaseProperties(COMPONENT$5, dark));
1702
+ const borderOverride = generateDarkBorderOverride(COMPONENT$5, variant.border, dark.borderColor);
1703
+ if (borderOverride) lines.push(borderOverride);
1704
+ if (dark.headerBackground) lines.push(` --cux-${COMPONENT$5}-header-bg: ${dark.headerBackground};`);
1705
+ if (dark.headerColor) lines.push(` --cux-${COMPONENT$5}-header-color: ${dark.headerColor};`);
1706
+ if (dark.headerBorderBottomColor && variant.headerBorderBottom) lines.push(` --cux-${COMPONENT$5}-header-border-bottom: ${variant.headerBorderBottom.width}${variant.headerBorderBottom.unit} ${variant.headerBorderBottom.style} ${dark.headerBorderBottomColor};`);
1707
+ if (dark.closeColor) lines.push(` --cux-${COMPONENT$5}-close-color: ${dark.closeColor};`);
1708
+ if (dark.closeHoverColor) lines.push(` --cux-${COMPONENT$5}-close-hover-color: ${dark.closeHoverColor};`);
1709
+ if (dark.closeActiveColor) lines.push(` --cux-${COMPONENT$5}-close-active-color: ${dark.closeActiveColor};`);
1710
+ const offsetShadow = generateDarkOffsetShadowVar(COMPONENT$5, variant.shadows, dark.shadowColor);
1711
+ if (offsetShadow) lines.push(offsetShadow);
1712
+ const insetShadow = generateDarkInsetShadowVar(COMPONENT$5, variant.shadows, dark.shadowInsetColor, dark.shadowInsetHighlightColor);
1713
+ if (insetShadow) lines.push(insetShadow);
1714
+ lines.push("}");
1715
+ return lines.join("\n");
1716
+ }
1717
+ //#endregion
1718
+ //#region src/core/avatar-generator.ts
1719
+ const COMPONENT$4 = "avatar";
1720
+ /**
1721
+ * Generate complete CSS for avatar component
1722
+ */
1723
+ function generateAvatarCSS(variants, globalConfig) {
1724
+ const css = [];
1725
+ css.push(generateAvatarBase());
1726
+ variants.forEach((variant) => {
1727
+ const variantName = toKebabCase(variant.name);
1728
+ css.push(generateAvatarVariant(variant, variantName, globalConfig));
1729
+ if (variant.dark) css.push(generateAvatarVariantDark(variant, variantName));
1730
+ });
1731
+ return css.join("\n\n");
1732
+ }
1733
+ /**
1734
+ * Generate base avatar styles
1735
+ */
1736
+ function generateAvatarBase() {
1737
+ return `/* Avatar Base Styles */
1738
+ .cux-${COMPONENT$4} {
1739
+ --cux-${COMPONENT$4}-bg: transparent;
1740
+ --cux-${COMPONENT$4}-color: inherit;
1741
+ --cux-${COMPONENT$4}-border: none;
1742
+ --cux-${COMPONENT$4}-radius: 50%;
1743
+ --cux-${COMPONENT$4}-padding: 0;
1744
+ --cux-${COMPONENT$4}-shadow: none;
1745
+
1746
+ background: var(--cux-${COMPONENT$4}-bg);
1747
+ color: var(--cux-${COMPONENT$4}-color);
1748
+ border: var(--cux-${COMPONENT$4}-border);
1749
+ border-radius: var(--cux-${COMPONENT$4}-radius);
1750
+ padding: var(--cux-${COMPONENT$4}-padding);
1751
+ box-shadow: var(--cux-${COMPONENT$4}-shadow);
1752
+ display: inline-flex;
1753
+ align-items: center;
1754
+ justify-content: center;
1755
+ overflow: hidden;
1756
+ vertical-align: middle;
1757
+ position: relative;
1758
+ }
1759
+
1760
+ .cux-${COMPONENT$4} img {
1761
+ width: 100%;
1762
+ height: 100%;
1763
+ object-fit: cover;
1764
+ }
1765
+
1766
+ .cux-${COMPONENT$4}-initials {
1767
+ text-transform: uppercase;
1768
+ user-select: none;
1769
+ }
1770
+
1771
+ /* Size modifiers */
1772
+ .cux-${COMPONENT$4}.--xs { width: 24px; height: 24px; }
1773
+ .cux-${COMPONENT$4}.--sm { width: 32px; height: 32px; }
1774
+ .cux-${COMPONENT$4}.--md { width: 40px; height: 40px; }
1775
+ .cux-${COMPONENT$4}.--lg { width: 48px; height: 48px; }
1776
+ .cux-${COMPONENT$4}.--xl { width: 64px; height: 64px; }
1777
+ .cux-${COMPONENT$4}.--xxl { width: 96px; height: 96px; }
1778
+
1779
+ /* Status indicator */
1780
+ .cux-${COMPONENT$4}-status {
1781
+ position: absolute;
1782
+ bottom: 0;
1783
+ right: 0;
1784
+ width: 25%;
1785
+ height: 25%;
1786
+ min-width: 8px;
1787
+ min-height: 8px;
1788
+ border-radius: 50%;
1789
+ border: 2px solid white;
1790
+ background: #6c757d;
1791
+ }
1792
+
1793
+ .cux-${COMPONENT$4}-status.--online { background: #28a745; }
1794
+ .cux-${COMPONENT$4}-status.--offline { background: #6c757d; }
1795
+ .cux-${COMPONENT$4}-status.--busy { background: #dc3545; }
1796
+ .cux-${COMPONENT$4}-status.--away { background: #ffc107; }`;
1797
+ }
1798
+ /**
1799
+ * Generate CSS for a specific avatar variant
1800
+ */
1801
+ function generateAvatarVariant(variant, variantName, globalConfig) {
1802
+ const lines = [];
1803
+ lines.push(`/* Variant: ${variant.name} */`);
1804
+ lines.push(`.cux-${COMPONENT$4}.--${variantName} {`);
1805
+ lines.push(...generateBaseProperties(COMPONENT$4, variant));
1806
+ const shadowVar = generateShadowVar(COMPONENT$4, variant.shadows);
1807
+ if (shadowVar) lines.push(shadowVar);
1808
+ lines.push("}");
1809
+ const typographyLines = generateTypographyLines({
1810
+ fontFamily: variant.fontFamily,
1811
+ fontSize: variant.fontSize,
1812
+ fontWeight: variant.fontWeight,
1813
+ fontStyle: variant.fontStyle,
1814
+ letterSpacing: variant.letterSpacing
1815
+ }, globalConfig);
1816
+ if (typographyLines.length > 0) {
1817
+ lines.push("");
1818
+ lines.push(`.cux-${COMPONENT$4}.--${variantName} .cux-${COMPONENT$4}-initials {`);
1819
+ lines.push(...typographyLines);
1820
+ lines.push("}");
1821
+ }
1822
+ return lines.join("\n");
1823
+ }
1824
+ /**
1825
+ * Generate dark mode CSS for an avatar variant
1826
+ */
1827
+ function generateAvatarVariantDark(variant, variantName) {
1828
+ const dark = variant.dark;
1829
+ if (!dark) return "";
1830
+ const lines = [];
1831
+ lines.push(`/* Dark Mode Variant: ${variant.name} */`);
1832
+ lines.push(`.dark .cux-${COMPONENT$4}.--${variantName} {`);
1833
+ lines.push(...generateDarkBaseProperties(COMPONENT$4, dark));
1834
+ const borderOverride = generateDarkBorderOverride(COMPONENT$4, variant.border, dark.borderColor);
1835
+ if (borderOverride) lines.push(borderOverride);
1836
+ const shadowVar = generateDarkShadowVar(COMPONENT$4, variant.shadows, dark);
1837
+ if (shadowVar) lines.push(shadowVar);
1838
+ lines.push("}");
1839
+ return lines.join("\n");
1840
+ }
1841
+ //#endregion
1842
+ //#region src/core/progress-generator.ts
1843
+ const COMPONENT$3 = "progress";
1844
+ /**
1845
+ * Generate complete CSS for progress component
1846
+ */
1847
+ function generateProgressCSS(variants, globalConfig) {
1848
+ const css = [];
1849
+ css.push(generateProgressBase());
1850
+ variants.forEach((variant) => {
1851
+ const variantName = toKebabCase(variant.name);
1852
+ css.push(generateProgressVariant(variant, variantName, globalConfig));
1853
+ if (variant.dark) css.push(generateProgressVariantDark(variant, variantName));
1854
+ });
1855
+ return css.join("\n\n");
1856
+ }
1857
+ /**
1858
+ * Generate base progress styles
1859
+ */
1860
+ function generateProgressBase() {
1861
+ return `/* Progress Base Styles */
1862
+ .cux-${COMPONENT$3} {
1863
+ --cux-${COMPONENT$3}-track-color: #e9ecef;
1864
+ --cux-${COMPONENT$3}-fill-color: #0d6efd;
1865
+ --cux-${COMPONENT$3}-stripe-color: rgba(255, 255, 255, 0.15);
1866
+ --cux-${COMPONENT$3}-height: 16px;
1867
+ --cux-${COMPONENT$3}-radius: 4px;
1868
+ --cux-${COMPONENT$3}-border: none;
1869
+ --cux-${COMPONENT$3}-shadow: none;
1870
+ --cux-${COMPONENT$3}-inset-shadow: none;
1871
+ --cux-${COMPONENT$3}-stripe-speed: 1s;
1872
+
1873
+ /* Label properties */
1874
+ --cux-${COMPONENT$3}-label-color: #212529;
1875
+ --cux-${COMPONENT$3}-label-font-size: 12px;
1876
+
1877
+ position: relative;
1878
+ display: flex;
1879
+ align-items: center;
1880
+ justify-content: center;
1881
+ background-color: var(--cux-${COMPONENT$3}-track-color);
1882
+ height: var(--cux-${COMPONENT$3}-height);
1883
+ border-radius: var(--cux-${COMPONENT$3}-radius);
1884
+ border: var(--cux-${COMPONENT$3}-border);
1885
+ box-shadow: var(--cux-${COMPONENT$3}-shadow);
1886
+ overflow: hidden;
1887
+ }
1888
+
1889
+ .cux-${COMPONENT$3}-inset-overlay {
1890
+ position: absolute;
1891
+ inset: 0;
1892
+ z-index: 2;
1893
+ border-radius: var(--cux-${COMPONENT$3}-radius);
1894
+ box-shadow: var(--cux-${COMPONENT$3}-inset-shadow);
1895
+ pointer-events: none;
1896
+ }
1897
+
1898
+ .cux-${COMPONENT$3}-fill {
1899
+ position: absolute;
1900
+ top: 0;
1901
+ left: 0;
1902
+ bottom: 0;
1903
+ height: 100%;
1904
+ background-color: var(--cux-${COMPONENT$3}-fill-color);
1905
+ transition: width 0.3s ease;
1906
+ }
1907
+
1908
+ .cux-${COMPONENT$3}-fill.--striped {
1909
+ background-image: linear-gradient(
1910
+ 45deg,
1911
+ var(--cux-${COMPONENT$3}-stripe-color) 25%,
1912
+ transparent 25%,
1913
+ transparent 50%,
1914
+ var(--cux-${COMPONENT$3}-stripe-color) 50%,
1915
+ var(--cux-${COMPONENT$3}-stripe-color) 75%,
1916
+ transparent 75%,
1917
+ transparent
1918
+ );
1919
+ background-size: calc(var(--cux-${COMPONENT$3}-height) * 2) calc(var(--cux-${COMPONENT$3}-height) * 2);
1920
+ background-color: var(--cux-${COMPONENT$3}-fill-color);
1921
+ }
1922
+
1923
+ .cux-${COMPONENT$3}-fill.--animated {
1924
+ animation: cux-${COMPONENT$3}-stripes var(--cux-${COMPONENT$3}-stripe-speed) linear infinite;
1925
+ }
1926
+
1927
+ @keyframes cux-${COMPONENT$3}-stripes {
1928
+ 0% { background-position: 0 0; }
1929
+ 100% { background-position: calc(var(--cux-${COMPONENT$3}-height) * -2) 0; }
1930
+ }
1931
+
1932
+ .cux-${COMPONENT$3}-label {
1933
+ position: absolute;
1934
+ top: 50%;
1935
+ left: 50%;
1936
+ transform: translate(-50%, -50%);
1937
+ z-index: 10;
1938
+ color: var(--cux-${COMPONENT$3}-label-color);
1939
+ font-size: var(--cux-${COMPONENT$3}-label-font-size);
1940
+ pointer-events: none;
1941
+ }`;
1942
+ }
1943
+ /**
1944
+ * Generate CSS for a specific progress variant
1945
+ */
1946
+ function generateProgressVariant(variant, variantName, globalConfig) {
1947
+ const lines = [];
1948
+ lines.push(`/* Variant: ${variant.name} */`);
1949
+ lines.push(`.cux-${COMPONENT$3}.--${variantName} {`);
1950
+ lines.push(` --cux-${COMPONENT$3}-track-color: ${variant.trackColor};`);
1951
+ lines.push(` --cux-${COMPONENT$3}-fill-color: ${variant.fillColor};`);
1952
+ lines.push(` --cux-${COMPONENT$3}-stripe-color: ${variant.stripeColor};`);
1953
+ if (variant.height) lines.push(` --cux-${COMPONENT$3}-height: ${variant.height.value}${variant.height.unit};`);
1954
+ if (variant.borderRadius) lines.push(` --cux-${COMPONENT$3}-radius: ${buildBorderRadius(variant.borderRadius)};`);
1955
+ if (variant.border) lines.push(` --cux-${COMPONENT$3}-border: ${buildBorder(variant.border)};`);
1956
+ lines.push(` --cux-${COMPONENT$3}-stripe-speed: ${variant.speed}s;`);
1957
+ const offsetShadow = generateOffsetShadowVar(COMPONENT$3, variant.shadows);
1958
+ if (offsetShadow) lines.push(offsetShadow);
1959
+ const insetShadow = generateInsetShadowVar(COMPONENT$3, variant.shadows);
1960
+ if (insetShadow) lines.push(insetShadow);
1961
+ lines.push("}");
1962
+ lines.push("");
1963
+ lines.push(`.cux-${COMPONENT$3}.--${variantName} .cux-${COMPONENT$3}-label {`);
1964
+ const labelTypography = generateTypographyLines({
1965
+ fontFamily: variant.fontFamily,
1966
+ fontSize: variant.labelFontSize,
1967
+ fontWeight: variant.fontWeight,
1968
+ fontStyle: variant.fontStyle
1969
+ }, globalConfig);
1970
+ lines.push(` color: ${variant.labelColor};`);
1971
+ lines.push(` font-size: ${buildFontSize(variant.labelFontSize)};`);
1972
+ lines.push(...labelTypography.filter((l) => !l.includes("font-size")));
1973
+ lines.push(` display: ${variant.showLabel ? "block" : "none"};`);
1974
+ lines.push("}");
1975
+ return lines.join("\n");
1976
+ }
1977
+ /**
1978
+ * Generate dark mode CSS for a progress variant
1979
+ */
1980
+ function generateProgressVariantDark(variant, variantName) {
1981
+ const dark = variant.dark;
1982
+ if (!dark) return "";
1983
+ const lines = [];
1984
+ lines.push(`/* Dark Mode Variant: ${variant.name} */`);
1985
+ lines.push(`.dark .cux-${COMPONENT$3}.--${variantName} {`);
1986
+ if (dark.trackColor) lines.push(` --cux-${COMPONENT$3}-track-color: ${dark.trackColor};`);
1987
+ if (dark.fillColor) lines.push(` --cux-${COMPONENT$3}-fill-color: ${dark.fillColor};`);
1988
+ if (dark.stripeColor) lines.push(` --cux-${COMPONENT$3}-stripe-color: ${dark.stripeColor};`);
1989
+ const borderOverride = generateDarkBorderOverride(COMPONENT$3, variant.border, dark.borderColor);
1990
+ if (borderOverride) lines.push(borderOverride);
1991
+ const offsetShadow = generateDarkOffsetShadowVar(COMPONENT$3, variant.shadows, dark.shadowColor);
1992
+ if (offsetShadow) lines.push(offsetShadow);
1993
+ const insetShadow = generateDarkInsetShadowVar(COMPONENT$3, variant.shadows, dark.shadowInsetColor, dark.shadowInsetHighlightColor);
1994
+ if (insetShadow) lines.push(insetShadow);
1995
+ lines.push("}");
1996
+ if (dark.labelColor) {
1997
+ lines.push("");
1998
+ lines.push(`.dark .cux-${COMPONENT$3}.--${variantName} .cux-${COMPONENT$3}-label {`);
1999
+ lines.push(` color: ${dark.labelColor};`);
2000
+ lines.push("}");
2001
+ }
2002
+ return lines.join("\n");
2003
+ }
2004
+ //#endregion
2005
+ //#region src/core/spinner-generator.ts
2006
+ const COMPONENT$2 = "spinner";
2007
+ /**
2008
+ * Generate complete CSS for spinner component
2009
+ */
2010
+ function generateSpinnerCSS(variants) {
2011
+ const css = [];
2012
+ css.push(generateSpinnerBase());
2013
+ css.push(generateSpinnerAnimations());
2014
+ variants.forEach((variant) => {
2015
+ const variantName = toKebabCase(variant.name);
2016
+ css.push(generateSpinnerVariant(variant, variantName));
2017
+ if (variant.dark) css.push(generateSpinnerVariantDark(variant, variantName));
2018
+ });
2019
+ return css.join("\n\n");
2020
+ }
2021
+ /**
2022
+ * Generate base spinner styles (shared across all types)
2023
+ */
2024
+ function generateSpinnerBase() {
2025
+ return `/* Spinner Base Styles */
2026
+ .cux-${COMPONENT$2} {
2027
+ --cux-${COMPONENT$2}-color: #0d6efd;
2028
+ --cux-${COMPONENT$2}-track: #95b6d8;
2029
+ --cux-${COMPONENT$2}-size: 40px;
2030
+ --cux-${COMPONENT$2}-speed: 1s;
2031
+ --cux-${COMPONENT$2}-delay2: 0.2s;
2032
+ --cux-${COMPONENT$2}-delay3: 0.4s;
2033
+ --cux-${COMPONENT$2}-delay4: 0.6s;
2034
+ --cux-${COMPONENT$2}-delay5: 0.8s;
2035
+
2036
+ display: inline-flex;
2037
+ align-items: center;
2038
+ justify-content: center;
2039
+ }`;
2040
+ }
2041
+ /**
2042
+ * Generate all spinner animations
2043
+ */
2044
+ function generateSpinnerAnimations() {
2045
+ return `/* Spinner Animations */
2046
+ @keyframes cux-${COMPONENT$2}-ring-spin {
2047
+ to { transform: rotate(360deg); }
2048
+ }
2049
+
2050
+ @keyframes cux-${COMPONENT$2}-pulse-scale {
2051
+ 0%, 100% {
2052
+ transform: scale(0.5);
2053
+ opacity: 0.3;
2054
+ }
2055
+ 50% {
2056
+ transform: scale(1);
2057
+ opacity: 1;
2058
+ }
2059
+ }
2060
+
2061
+ @keyframes cux-${COMPONENT$2}-dots-bounce {
2062
+ 0%, 100% {
2063
+ transform: translateY(0);
2064
+ opacity: 0.3;
2065
+ }
2066
+ 50% {
2067
+ transform: translateY(calc(var(--cux-${COMPONENT$2}-size) * -0.25));
2068
+ opacity: 1;
2069
+ }
2070
+ }
2071
+
2072
+ @keyframes cux-${COMPONENT$2}-bars-stretch {
2073
+ 0%, 100% {
2074
+ transform: scaleY(0.3);
2075
+ opacity: 0.3;
2076
+ }
2077
+ 50% {
2078
+ transform: scaleY(1);
2079
+ opacity: 1;
2080
+ }
2081
+ }
2082
+
2083
+ @keyframes cux-${COMPONENT$2}-dual-spin {
2084
+ to { transform: rotate(360deg); }
2085
+ }
2086
+
2087
+ /* Ring Spinner */
2088
+ .cux-${COMPONENT$2}-ring {
2089
+ width: var(--cux-${COMPONENT$2}-size);
2090
+ height: var(--cux-${COMPONENT$2}-size);
2091
+ }
2092
+
2093
+ .cux-${COMPONENT$2}-ring-track {
2094
+ stroke: var(--cux-${COMPONENT$2}-track);
2095
+ fill: none;
2096
+ }
2097
+
2098
+ .cux-${COMPONENT$2}-ring-arc {
2099
+ stroke: var(--cux-${COMPONENT$2}-color);
2100
+ fill: none;
2101
+ stroke-linecap: round;
2102
+ animation: cux-${COMPONENT$2}-ring-spin var(--cux-${COMPONENT$2}-speed) linear infinite;
2103
+ transform-origin: center;
2104
+ transform-box: fill-box;
2105
+ }
2106
+
2107
+ /* Pulse Spinner */
2108
+ .cux-${COMPONENT$2}-pulse {
2109
+ width: var(--cux-${COMPONENT$2}-size);
2110
+ height: var(--cux-${COMPONENT$2}-size);
2111
+ }
2112
+
2113
+ .cux-${COMPONENT$2}-pulse-bg {
2114
+ fill: var(--cux-${COMPONENT$2}-track);
2115
+ opacity: 0.3;
2116
+ animation: cux-${COMPONENT$2}-pulse-scale var(--cux-${COMPONENT$2}-speed) ease-in-out infinite;
2117
+ transform-origin: center;
2118
+ transform-box: fill-box;
2119
+ }
2120
+
2121
+ .cux-${COMPONENT$2}-pulse-fg {
2122
+ fill: var(--cux-${COMPONENT$2}-color);
2123
+ animation: cux-${COMPONENT$2}-pulse-scale var(--cux-${COMPONENT$2}-speed) ease-in-out infinite reverse;
2124
+ transform-origin: center;
2125
+ transform-box: fill-box;
2126
+ }
2127
+
2128
+ /* Dots Spinner */
2129
+ .cux-${COMPONENT$2}-dots {
2130
+ display: flex;
2131
+ gap: calc(var(--cux-${COMPONENT$2}-size) * 0.15);
2132
+ align-items: center;
2133
+ }
2134
+
2135
+ .cux-${COMPONENT$2}-dot {
2136
+ width: calc(var(--cux-${COMPONENT$2}-size) * 0.2);
2137
+ height: calc(var(--cux-${COMPONENT$2}-size) * 0.2);
2138
+ background: var(--cux-${COMPONENT$2}-color);
2139
+ border-radius: 50%;
2140
+ animation: cux-${COMPONENT$2}-dots-bounce var(--cux-${COMPONENT$2}-speed) ease-in-out infinite;
2141
+ }
2142
+
2143
+ .cux-${COMPONENT$2}-dot:nth-child(1) { animation-delay: 0s; }
2144
+ .cux-${COMPONENT$2}-dot:nth-child(2) { animation-delay: var(--cux-${COMPONENT$2}-delay2); }
2145
+ .cux-${COMPONENT$2}-dot:nth-child(3) { animation-delay: var(--cux-${COMPONENT$2}-delay3); }
2146
+
2147
+ /* Bars Spinner */
2148
+ .cux-${COMPONENT$2}-bars {
2149
+ display: flex;
2150
+ gap: calc(var(--cux-${COMPONENT$2}-size) * 0.1);
2151
+ align-items: center;
2152
+ }
2153
+
2154
+ .cux-${COMPONENT$2}-bar {
2155
+ width: calc(var(--cux-${COMPONENT$2}-size) * 0.15);
2156
+ height: calc(var(--cux-${COMPONENT$2}-size) * 0.4);
2157
+ background: var(--cux-${COMPONENT$2}-color);
2158
+ border-radius: 2px;
2159
+ animation: cux-${COMPONENT$2}-bars-stretch var(--cux-${COMPONENT$2}-speed) ease-in-out infinite;
2160
+ }
2161
+
2162
+ .cux-${COMPONENT$2}-bar:nth-child(1) { animation-delay: 0s; }
2163
+ .cux-${COMPONENT$2}-bar:nth-child(2) { animation-delay: var(--cux-${COMPONENT$2}-delay2); }
2164
+ .cux-${COMPONENT$2}-bar:nth-child(3) { animation-delay: var(--cux-${COMPONENT$2}-delay3); }
2165
+ .cux-${COMPONENT$2}-bar:nth-child(4) { animation-delay: var(--cux-${COMPONENT$2}-delay4); }
2166
+ .cux-${COMPONENT$2}-bar:nth-child(5) { animation-delay: var(--cux-${COMPONENT$2}-delay5); }
2167
+
2168
+ /* Dual Spinner */
2169
+ .cux-${COMPONENT$2}-dual {
2170
+ width: var(--cux-${COMPONENT$2}-size);
2171
+ height: var(--cux-${COMPONENT$2}-size);
2172
+ }
2173
+
2174
+ .cux-${COMPONENT$2}-dual-outer,
2175
+ .cux-${COMPONENT$2}-dual-inner {
2176
+ animation: cux-${COMPONENT$2}-dual-spin var(--cux-${COMPONENT$2}-speed) linear infinite;
2177
+ transform-origin: center;
2178
+ transform-box: fill-box;
2179
+ }
2180
+
2181
+ .cux-${COMPONENT$2}-dual-outer circle {
2182
+ stroke: var(--cux-${COMPONENT$2}-color);
2183
+ fill: none;
2184
+ stroke-linecap: round;
2185
+ }
2186
+
2187
+ .cux-${COMPONENT$2}-dual-inner circle {
2188
+ stroke: var(--cux-${COMPONENT$2}-track);
2189
+ fill: none;
2190
+ stroke-linecap: round;
2191
+ }
2192
+
2193
+ .cux-${COMPONENT$2}-dual-inner {
2194
+ animation-direction: reverse;
2195
+ opacity: 0.6;
2196
+ }`;
2197
+ }
2198
+ /**
2199
+ * Generate CSS for a specific spinner variant
2200
+ */
2201
+ function generateSpinnerVariant(variant, variantName) {
2202
+ const size = variant.size ? `${variant.size.value}${variant.size.unit}` : "40px";
2203
+ const speed = `${variant.speed}s`;
2204
+ const delay2 = `${Math.round(variant.speed * .2 * 100) / 100}s`;
2205
+ const delay3 = `${Math.round(variant.speed * .4 * 100) / 100}s`;
2206
+ const delay4 = `${Math.round(variant.speed * .6 * 100) / 100}s`;
2207
+ const delay5 = `${Math.round(variant.speed * .8 * 100) / 100}s`;
2208
+ const lines = [];
2209
+ lines.push(`/* Variant: ${variant.name} */`);
2210
+ lines.push(`.cux-${COMPONENT$2}.--${variantName} {`);
2211
+ lines.push(` --cux-${COMPONENT$2}-color: ${variant.color};`);
2212
+ lines.push(` --cux-${COMPONENT$2}-track: ${variant.trackColor};`);
2213
+ lines.push(` --cux-${COMPONENT$2}-size: ${size};`);
2214
+ lines.push(` --cux-${COMPONENT$2}-speed: ${speed};`);
2215
+ lines.push(` --cux-${COMPONENT$2}-delay2: ${delay2};`);
2216
+ lines.push(` --cux-${COMPONENT$2}-delay3: ${delay3};`);
2217
+ lines.push(` --cux-${COMPONENT$2}-delay4: ${delay4};`);
2218
+ lines.push(` --cux-${COMPONENT$2}-delay5: ${delay5};`);
2219
+ lines.push("}");
2220
+ return lines.join("\n");
2221
+ }
2222
+ /**
2223
+ * Generate dark mode CSS for a spinner variant
2224
+ */
2225
+ function generateSpinnerVariantDark(variant, variantName) {
2226
+ const dark = variant.dark;
2227
+ if (!dark) return "";
2228
+ const lines = [];
2229
+ lines.push(`/* Dark Mode Variant: ${variant.name} */`);
2230
+ lines.push(`.dark .cux-${COMPONENT$2}.--${variantName} {`);
2231
+ if (dark.color) lines.push(` --cux-${COMPONENT$2}-color: ${dark.color};`);
2232
+ if (dark.trackColor) lines.push(` --cux-${COMPONENT$2}-track: ${dark.trackColor};`);
2233
+ lines.push("}");
2234
+ return lines.join("\n");
2235
+ }
2236
+ //#endregion
2237
+ //#region src/core/badge-generator.ts
2238
+ const COMPONENT$1 = "badge";
2239
+ /**
2240
+ * Generate complete CSS for badge component
2241
+ */
2242
+ function generateBadgeCSS(variants, globalConfig) {
2243
+ const css = [];
2244
+ css.push(generateBadgeBase());
2245
+ variants.forEach((variant) => {
2246
+ const variantName = toKebabCase(variant.name);
2247
+ css.push(generateBadgeVariant(variant, variantName, globalConfig));
2248
+ if (variant.dark) css.push(generateBadgeVariantDark(variant, variantName));
2249
+ });
2250
+ return css.join("\n\n");
2251
+ }
2252
+ /**
2253
+ * Generate base badge styles
2254
+ */
2255
+ function generateBadgeBase() {
2256
+ return `/* Badge Base Styles */
2257
+ .cux-${COMPONENT$1} {
2258
+ --cux-${COMPONENT$1}-bg: #6c757d;
2259
+ --cux-${COMPONENT$1}-color: #ffffff;
2260
+ --cux-${COMPONENT$1}-border: none;
2261
+ --cux-${COMPONENT$1}-radius: 4px;
2262
+ --cux-${COMPONENT$1}-padding: 4px 8px;
2263
+ --cux-${COMPONENT$1}-shadow: none;
2264
+
2265
+ display: inline-flex;
2266
+ align-items: center;
2267
+ justify-content: center;
2268
+ background: var(--cux-${COMPONENT$1}-bg);
2269
+ color: var(--cux-${COMPONENT$1}-color);
2270
+ border: var(--cux-${COMPONENT$1}-border);
2271
+ border-radius: var(--cux-${COMPONENT$1}-radius);
2272
+ padding: var(--cux-${COMPONENT$1}-padding);
2273
+ box-shadow: var(--cux-${COMPONENT$1}-shadow);
2274
+ white-space: nowrap;
2275
+ vertical-align: middle;
2276
+ }`;
2277
+ }
2278
+ /**
2279
+ * Generate CSS for a specific badge variant
2280
+ */
2281
+ function generateBadgeVariant(variant, variantName, globalConfig) {
2282
+ const lines = [];
2283
+ lines.push(`/* Variant: ${variant.name} */`);
2284
+ lines.push(`.cux-${COMPONENT$1}.--${variantName} {`);
2285
+ lines.push(...generateBaseProperties(COMPONENT$1, variant));
2286
+ const shadowVar = generateShadowVar(COMPONENT$1, variant.shadows);
2287
+ if (shadowVar) lines.push(shadowVar);
2288
+ lines.push("}");
2289
+ const typographyBlock = generateTypographyBlock(`.cux-${COMPONENT$1}.--${variantName}`, {
2290
+ fontFamily: variant.fontFamily,
2291
+ fontSize: variant.fontSize,
2292
+ fontWeight: variant.fontWeight,
2293
+ fontStyle: variant.fontStyle,
2294
+ letterSpacing: variant.letterSpacing
2295
+ }, globalConfig);
2296
+ if (typographyBlock) {
2297
+ lines.push("");
2298
+ lines.push(typographyBlock);
2299
+ }
2300
+ return lines.join("\n");
2301
+ }
2302
+ /**
2303
+ * Generate dark mode CSS for a badge variant
2304
+ */
2305
+ function generateBadgeVariantDark(variant, variantName) {
2306
+ const dark = variant.dark;
2307
+ if (!dark) return "";
2308
+ const lines = [];
2309
+ lines.push(`/* Dark Mode Variant: ${variant.name} */`);
2310
+ lines.push(`.dark .cux-${COMPONENT$1}.--${variantName} {`);
2311
+ lines.push(...generateDarkBaseProperties(COMPONENT$1, dark));
2312
+ const borderOverride = generateDarkBorderOverride(COMPONENT$1, variant.border, dark.borderColor);
2313
+ if (borderOverride) lines.push(borderOverride);
2314
+ const shadowVar = generateDarkShadowVar(COMPONENT$1, variant.shadows, dark);
2315
+ if (shadowVar) lines.push(shadowVar);
2316
+ lines.push("}");
2317
+ return lines.join("\n");
2318
+ }
2319
+ //#endregion
2320
+ //#region src/core/chip-generator.ts
2321
+ const COMPONENT = "chip";
2322
+ /**
2323
+ * Generate complete CSS for chip component
2324
+ */
2325
+ function generateChipCSS(variants, globalConfig) {
2326
+ const css = [];
2327
+ css.push(generateChipBase());
2328
+ variants.forEach((variant) => {
2329
+ const variantName = toKebabCase(variant.name);
2330
+ css.push(generateChipVariant(variant, variantName, globalConfig));
2331
+ if (variant.dark) css.push(generateChipVariantDark(variant, variantName));
2332
+ });
2333
+ return css.join("\n\n");
2334
+ }
2335
+ /**
2336
+ * Generate base chip styles
2337
+ */
2338
+ function generateChipBase() {
2339
+ return `/* Chip Base Styles */
2340
+ .cux-${COMPONENT} {
2341
+ --cux-${COMPONENT}-bg: #e9ecef;
2342
+ --cux-${COMPONENT}-color: #212529;
2343
+ --cux-${COMPONENT}-border: none;
2344
+ --cux-${COMPONENT}-radius: 16px;
2345
+ --cux-${COMPONENT}-padding: 4px 12px;
2346
+ --cux-${COMPONENT}-shadow: none;
2347
+
2348
+ /* Close button properties */
2349
+ --cux-${COMPONENT}-close-size: 16px;
2350
+ --cux-${COMPONENT}-close-color: #495057;
2351
+ --cux-${COMPONENT}-close-hover-color: #212529;
2352
+ --cux-${COMPONENT}-close-active-color: #000000;
2353
+
2354
+ display: inline-flex;
2355
+ align-items: center;
2356
+ justify-content: center;
2357
+ gap: 6px;
2358
+ background: var(--cux-${COMPONENT}-bg);
2359
+ color: var(--cux-${COMPONENT}-color);
2360
+ border: var(--cux-${COMPONENT}-border);
2361
+ border-radius: var(--cux-${COMPONENT}-radius);
2362
+ padding: var(--cux-${COMPONENT}-padding);
2363
+ box-shadow: var(--cux-${COMPONENT}-shadow);
2364
+ white-space: nowrap;
2365
+ vertical-align: middle;
2366
+ }
2367
+
2368
+ .cux-${COMPONENT}-close {
2369
+ display: inline-flex;
2370
+ align-items: center;
2371
+ justify-content: center;
2372
+ width: var(--cux-${COMPONENT}-close-size);
2373
+ height: var(--cux-${COMPONENT}-close-size);
2374
+ background: transparent;
2375
+ border: none;
2376
+ color: var(--cux-${COMPONENT}-close-color);
2377
+ cursor: pointer;
2378
+ border-radius: 4px;
2379
+ transition: color 0.15s ease;
2380
+ padding: 0;
2381
+ flex-shrink: 0;
2382
+ }
2383
+
2384
+ .cux-${COMPONENT}-close:hover {
2385
+ color: var(--cux-${COMPONENT}-close-hover-color);
2386
+ }
2387
+
2388
+ .cux-${COMPONENT}-close:active {
2389
+ color: var(--cux-${COMPONENT}-close-active-color);
2390
+ }
2391
+
2392
+ .cux-${COMPONENT}-close svg {
2393
+ width: 100%;
2394
+ height: 100%;
2395
+ }`;
2396
+ }
2397
+ /**
2398
+ * Generate CSS for a specific chip variant
2399
+ */
2400
+ function generateChipVariant(variant, variantName, globalConfig) {
2401
+ const lines = [];
2402
+ lines.push(`/* Variant: ${variant.name} */`);
2403
+ lines.push(`.cux-${COMPONENT}.--${variantName} {`);
2404
+ lines.push(...generateBaseProperties(COMPONENT, variant));
2405
+ const shadowVar = generateShadowVar(COMPONENT, variant.shadows);
2406
+ if (shadowVar) lines.push(shadowVar);
2407
+ if (variant.closeSize) lines.push(` --cux-${COMPONENT}-close-size: ${variant.closeSize.value}${variant.closeSize.unit};`);
2408
+ lines.push(` --cux-${COMPONENT}-close-color: ${variant.closeColor};`);
2409
+ lines.push(` --cux-${COMPONENT}-close-hover-color: ${variant.closeHoverColor};`);
2410
+ lines.push(` --cux-${COMPONENT}-close-active-color: ${variant.closeActiveColor};`);
2411
+ lines.push("}");
2412
+ const typographyLines = generateTypographyLines({
2413
+ fontFamily: variant.fontFamily,
2414
+ fontSize: variant.fontSize,
2415
+ fontWeight: variant.fontWeight,
2416
+ fontStyle: variant.fontStyle,
2417
+ letterSpacing: variant.letterSpacing
2418
+ }, globalConfig);
2419
+ if (typographyLines.length > 0) {
2420
+ lines.push("");
2421
+ lines.push(`.cux-${COMPONENT}.--${variantName} {`);
2422
+ lines.push(...typographyLines);
2423
+ lines.push("}");
2424
+ }
2425
+ return lines.join("\n");
2426
+ }
2427
+ /**
2428
+ * Generate dark mode CSS for a chip variant
2429
+ */
2430
+ function generateChipVariantDark(variant, variantName) {
2431
+ const dark = variant.dark;
2432
+ if (!dark) return "";
2433
+ const lines = [];
2434
+ lines.push(`/* Dark Mode Variant: ${variant.name} */`);
2435
+ lines.push(`.dark .cux-${COMPONENT}.--${variantName} {`);
2436
+ lines.push(...generateDarkBaseProperties(COMPONENT, dark));
2437
+ const borderOverride = generateDarkBorderOverride(COMPONENT, variant.border, dark.borderColor);
2438
+ if (borderOverride) lines.push(borderOverride);
2439
+ if (dark.closeColor) lines.push(` --cux-${COMPONENT}-close-color: ${dark.closeColor};`);
2440
+ if (dark.closeHoverColor) lines.push(` --cux-${COMPONENT}-close-hover-color: ${dark.closeHoverColor};`);
2441
+ if (dark.closeActiveColor) lines.push(` --cux-${COMPONENT}-close-active-color: ${dark.closeActiveColor};`);
2442
+ const shadowVar = generateDarkShadowVar(COMPONENT, variant.shadows, dark);
2443
+ if (shadowVar) lines.push(shadowVar);
2444
+ lines.push("}");
2445
+ return lines.join("\n");
2446
+ }
2447
+ //#endregion
2448
+ //#region src/combo-ux.ts
2449
+ var ComboUX = class {
2450
+ options;
2451
+ darkMode;
2452
+ cssInjector;
2453
+ themeLoader;
2454
+ themeSync = null;
2455
+ currentTheme = null;
2456
+ constructor(options) {
2457
+ this.options = {
2458
+ theme: options.theme,
2459
+ darkMode: options.darkMode ?? "auto",
2460
+ persistDarkMode: options.persistDarkMode ?? true,
2461
+ darkModeStorageKey: options.darkModeStorageKey ?? "cux-dark-mode"
2462
+ };
2463
+ this.darkMode = new DarkMode({
2464
+ persist: this.options.persistDarkMode,
2465
+ storageKey: this.options.darkModeStorageKey
2466
+ });
2467
+ this.cssInjector = new CSSInjector();
2468
+ this.themeLoader = new ThemeLoader();
2469
+ if (options.ws && options.ws !== false) this.themeSync = new ThemeSync((theme) => this.updateTheme(theme), typeof options.ws === "string" ? { url: options.ws } : options.ws);
2470
+ }
2471
+ /**
2472
+ * Initialize the library (must be called manually or via composable)
2473
+ */
2474
+ async init() {
2475
+ injectBasscss();
2476
+ this.darkMode.init(this.options.darkMode);
2477
+ try {
2478
+ await this.loadTheme(this.options.theme);
2479
+ } catch (error) {
2480
+ console.error("Failed to load theme:", error);
2481
+ }
2482
+ if (this.themeSync) this.themeSync.connect();
2483
+ }
2484
+ /**
2485
+ * Inject base styles with theme colors
2486
+ */
2487
+ injectBaseStylesFromTheme(theme) {
2488
+ const backgroundColor = theme.typography?.globalConfig?.backgroundColor;
2489
+ const darkBackgroundColor = theme.typography?.globalConfig?.dark?.backgroundColor;
2490
+ const textColor = theme.typography?.globalConfig?.color;
2491
+ const darkTextColor = theme.typography?.globalConfig?.dark?.color;
2492
+ if (backgroundColor || darkBackgroundColor || textColor || darkTextColor) updateBaseStyles({
2493
+ backgroundColor,
2494
+ darkBackgroundColor,
2495
+ textColor,
2496
+ darkTextColor
2497
+ });
2498
+ else injectBaseStyles();
2499
+ }
2500
+ /**
2501
+ * Load theme from URL or object
2502
+ */
2503
+ async loadTheme(theme) {
2504
+ const themeData = await this.themeLoader.load(theme);
2505
+ this.currentTheme = themeData;
2506
+ this.applyTheme(themeData);
2507
+ }
2508
+ /**
2509
+ * Apply theme by generating and injecting CSS
2510
+ */
2511
+ applyTheme(theme) {
2512
+ this.injectBaseStylesFromTheme(theme);
2513
+ const cssParts = [];
2514
+ if (theme.typography) {
2515
+ loadFontsFromTypography(theme.typography);
2516
+ const typographyCSS = generateTypographyCSS(theme.typography);
2517
+ if (typographyCSS) cssParts.push(typographyCSS);
2518
+ }
2519
+ if (theme.forms?.globalConfig) {
2520
+ loadFontsFromForms(theme.forms);
2521
+ const formsCSS = generateFormsCSS(theme.forms, theme.typography);
2522
+ if (formsCSS) cssParts.push(formsCSS);
2523
+ }
2524
+ if (theme.buttons?.variants?.length) {
2525
+ loadFontsFromButtonVariants(theme.buttons.variants);
2526
+ cssParts.push(generateButtonCSS(theme.buttons.variants, theme.typography?.globalConfig));
2527
+ }
2528
+ if (theme.cards?.variants?.length) cssParts.push(generateCardCSS(theme.cards.variants, theme.typography?.globalConfig));
2529
+ if (theme.alerts?.variants?.length) cssParts.push(generateAlertCSS(theme.alerts.variants, theme.typography?.globalConfig));
2530
+ if (theme.avatars?.variants?.length) {
2531
+ loadFontsFromAvatarVariants(theme.avatars.variants);
2532
+ cssParts.push(generateAvatarCSS(theme.avatars.variants, theme.typography?.globalConfig));
2533
+ }
2534
+ if (theme.progress?.variants?.length) cssParts.push(generateProgressCSS(theme.progress.variants, theme.typography?.globalConfig));
2535
+ if (theme.spinners?.variants?.length) cssParts.push(generateSpinnerCSS(theme.spinners.variants));
2536
+ if (theme.badges?.variants?.length) cssParts.push(generateBadgeCSS(theme.badges.variants, theme.typography?.globalConfig));
2537
+ if (theme.chips?.variants?.length) cssParts.push(generateChipCSS(theme.chips.variants, theme.typography?.globalConfig));
2538
+ if (cssParts.length > 0) this.cssInjector.inject(cssParts.join("\n\n"));
2539
+ }
2540
+ /**
2541
+ * Update theme (for real-time updates via websockets)
2542
+ */
2543
+ updateTheme(theme) {
2544
+ this.currentTheme = theme;
2545
+ this.applyTheme(theme);
2546
+ }
2547
+ /**
2548
+ * Update a specific button variant
2549
+ */
2550
+ updateButtonVariant(variantName, updates) {
2551
+ if (!this.currentTheme?.buttons?.variants) return;
2552
+ const variant = this.currentTheme.buttons.variants.find((v) => v.name.toLowerCase() === variantName.toLowerCase());
2553
+ if (variant) {
2554
+ Object.assign(variant, updates);
2555
+ this.applyTheme(this.currentTheme);
2556
+ }
2557
+ }
2558
+ /** Check if dark mode is active */
2559
+ get isDark() {
2560
+ return this.darkMode.isDark;
2561
+ }
2562
+ /** Set dark mode */
2563
+ setDarkMode(value) {
2564
+ this.darkMode.setDarkMode(value);
2565
+ }
2566
+ /** Toggle dark mode */
2567
+ toggleDarkMode() {
2568
+ this.darkMode.toggle();
2569
+ }
2570
+ /** Register callback for dark mode changes */
2571
+ onDarkModeChange(callback) {
2572
+ return this.darkMode.onChange(callback);
2573
+ }
2574
+ /** Check if WebSocket is connected */
2575
+ get isSyncConnected() {
2576
+ return this.themeSync?.isConnected ?? false;
2577
+ }
2578
+ /** Connect to WebSocket server */
2579
+ connectSync() {
2580
+ this.themeSync?.connect();
2581
+ }
2582
+ /** Disconnect from WebSocket server */
2583
+ disconnectSync() {
2584
+ this.themeSync?.disconnect();
2585
+ }
2586
+ /** Register callback for sync connection */
2587
+ onSyncConnect(callback) {
2588
+ if (!this.themeSync) return () => {};
2589
+ return this.themeSync.onConnect(callback);
2590
+ }
2591
+ /** Register callback for sync disconnection */
2592
+ onSyncDisconnect(callback) {
2593
+ if (!this.themeSync) return () => {};
2594
+ return this.themeSync.onDisconnect(callback);
2595
+ }
2596
+ /** Register callback for sync errors */
2597
+ onSyncError(callback) {
2598
+ if (!this.themeSync) return () => {};
2599
+ return this.themeSync.onError(callback);
2600
+ }
2601
+ /** Register callback for theme updates from sync */
2602
+ onSyncThemeUpdate(callback) {
2603
+ if (!this.themeSync) return () => {};
2604
+ return this.themeSync.onThemeUpdate(callback);
2605
+ }
2606
+ /** Register callback for theme load events */
2607
+ onThemeLoad(callback) {
2608
+ return this.themeLoader.onLoad(callback);
2609
+ }
2610
+ /** Destroy instance and clean up */
2611
+ destroy() {
2612
+ this.darkMode.destroy();
2613
+ this.cssInjector.destroy();
2614
+ this.themeLoader.destroy();
2615
+ if (this.themeSync) {
2616
+ this.themeSync.destroy();
2617
+ this.themeSync = null;
2618
+ }
2619
+ }
2620
+ };
2621
+ //#endregion
2622
+ //#region src/composables/useComboUX.ts
2623
+ /**
2624
+ * Vue composable for ComboUX
2625
+ */
2626
+ let comboUXInstance = null;
2627
+ const isInitialized = ref(false);
2628
+ const isDark = ref(false);
2629
+ const subscribers = /* @__PURE__ */ new Set();
2630
+ function notifySubscribers() {
2631
+ subscribers.forEach((cb) => cb(isDark.value));
2632
+ }
2633
+ /**
2634
+ * Initialize ComboUX with options
2635
+ * Should be called once in your app entry point
2636
+ */
2637
+ async function initComboUX(options) {
2638
+ if (comboUXInstance) {
2639
+ console.warn("[ComboUX] Already initialized, returning existing instance");
2640
+ return comboUXInstance;
2641
+ }
2642
+ comboUXInstance = new ComboUX(options);
2643
+ await comboUXInstance.init();
2644
+ isInitialized.value = true;
2645
+ isDark.value = comboUXInstance.isDark;
2646
+ comboUXInstance.onDarkModeChange((dark) => {
2647
+ isDark.value = dark;
2648
+ notifySubscribers();
2649
+ });
2650
+ return comboUXInstance;
2651
+ }
2652
+ /**
2653
+ * Get the current ComboUX instance
2654
+ */
2655
+ function getComboUX() {
2656
+ return comboUXInstance;
2657
+ }
2658
+ /**
2659
+ * Vue composable to use ComboUX in components
2660
+ */
2661
+ function useComboUX() {
2662
+ onMounted(() => {
2663
+ subscribers.add(() => {});
2664
+ });
2665
+ onUnmounted(() => {
2666
+ subscribers.delete(() => {});
2667
+ });
2668
+ return {
2669
+ isInitialized: readonly(isInitialized),
2670
+ isDark: readonly(isDark),
2671
+ instance: comboUXInstance,
2672
+ toggleDarkMode: () => comboUXInstance?.toggleDarkMode(),
2673
+ setDarkMode: (value) => comboUXInstance?.setDarkMode(value),
2674
+ updateTheme: (theme) => comboUXInstance?.updateTheme(theme)
2675
+ };
2676
+ }
2677
+ /**
2678
+ * Destroy the ComboUX instance
2679
+ */
2680
+ function destroyComboUX() {
2681
+ if (comboUXInstance) {
2682
+ comboUXInstance.destroy();
2683
+ comboUXInstance = null;
2684
+ isInitialized.value = false;
2685
+ }
2686
+ }
2687
+ //#endregion
2688
+ //#region src/index.ts
2689
+ const ComboUXPlugin = { async install(app, options) {
2690
+ if (options.autoInit !== false) await initComboUX(options);
2691
+ } };
2692
+ //#endregion
2693
+ export { ComboUX, ComboUXPlugin, ComboUXPlugin as default, destroyComboUX, getComboUX, initComboUX, useComboUX };