@wireweave/core 1.0.0-beta.20260107130355

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +351 -0
  2. package/dist/index.cjs +56106 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +252 -0
  5. package/dist/index.d.ts +252 -0
  6. package/dist/index.js +55985 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/parser.cjs +5417 -0
  9. package/dist/parser.cjs.map +1 -0
  10. package/dist/parser.d.cts +89 -0
  11. package/dist/parser.d.ts +89 -0
  12. package/dist/parser.js +5387 -0
  13. package/dist/parser.js.map +1 -0
  14. package/dist/renderer.cjs +50244 -0
  15. package/dist/renderer.cjs.map +1 -0
  16. package/dist/renderer.d.cts +497 -0
  17. package/dist/renderer.d.ts +497 -0
  18. package/dist/renderer.js +50202 -0
  19. package/dist/renderer.js.map +1 -0
  20. package/dist/types-DtovIYS6.d.cts +419 -0
  21. package/dist/types-DtovIYS6.d.ts +419 -0
  22. package/package.json +59 -0
  23. package/src/ast/guards.ts +361 -0
  24. package/src/ast/index.ts +9 -0
  25. package/src/ast/types.ts +661 -0
  26. package/src/ast/utils.ts +238 -0
  27. package/src/grammar/wireframe.peggy +677 -0
  28. package/src/icons/lucide-icons.ts +46422 -0
  29. package/src/index.ts +20 -0
  30. package/src/parser/generated-parser.js +5199 -0
  31. package/src/parser/index.ts +214 -0
  32. package/src/renderer/html/base.ts +186 -0
  33. package/src/renderer/html/components.ts +1092 -0
  34. package/src/renderer/html/index.ts +1608 -0
  35. package/src/renderer/html/layout.ts +392 -0
  36. package/src/renderer/index.ts +143 -0
  37. package/src/renderer/styles-components.ts +1232 -0
  38. package/src/renderer/styles.ts +382 -0
  39. package/src/renderer/svg/index.ts +1050 -0
  40. package/src/renderer/types.ts +173 -0
  41. package/src/types/index.ts +138 -0
  42. package/src/viewport/index.ts +17 -0
  43. package/src/viewport/presets.ts +181 -0
@@ -0,0 +1,1232 @@
1
+ /**
2
+ * Component-specific CSS styles for wireweave
3
+ *
4
+ * Detailed styles for all UI components with:
5
+ * - Wireframe aesthetic (black/white/gray)
6
+ * - Accessibility considerations
7
+ * - Responsive design
8
+ */
9
+
10
+ import type { ThemeConfig } from './types';
11
+
12
+ /**
13
+ * Generate all component-specific CSS styles
14
+ */
15
+ export function generateComponentStyles(_theme: ThemeConfig, prefix: string = 'wf'): string {
16
+ const parts: string[] = [
17
+ generateContainerStyles(prefix),
18
+ generateTextStyles(prefix),
19
+ generateInputStyles(_theme, prefix),
20
+ generateButtonStyles(_theme, prefix),
21
+ generateDisplayStyles(_theme, prefix),
22
+ generateDataStyles(_theme, prefix),
23
+ generateFeedbackStyles(_theme, prefix),
24
+ generateOverlayStyles(_theme, prefix),
25
+ generateNavigationStyles(_theme, prefix),
26
+ generateSemanticMarkerStyles(_theme, prefix),
27
+ generateAccessibilityStyles(prefix),
28
+ ];
29
+
30
+ return parts.join('\n\n');
31
+ }
32
+
33
+ /**
34
+ * Container component styles (Card, Modal, Drawer, Accordion)
35
+ */
36
+ function generateContainerStyles(prefix: string): string {
37
+ return `/* Container Components */
38
+ .${prefix}-card {
39
+ border: 1px solid var(--${prefix}-border);
40
+ border-radius: var(--${prefix}-radius);
41
+ background: var(--${prefix}-bg);
42
+ padding: 16px;
43
+ }
44
+
45
+ /* Cards in flex rows should expand equally */
46
+ .${prefix}-row > .${prefix}-card {
47
+ flex: 1 1 0%;
48
+ min-width: 0;
49
+ }
50
+
51
+ .${prefix}-card-title {
52
+ margin: 0 0 12px 0;
53
+ font-size: 18px;
54
+ font-weight: 600;
55
+ }
56
+
57
+ .${prefix}-card-shadow-sm { box-shadow: var(--${prefix}-shadow-sm); }
58
+ .${prefix}-card-shadow-md { box-shadow: var(--${prefix}-shadow-md); }
59
+ .${prefix}-card-shadow-lg { box-shadow: var(--${prefix}-shadow-lg); }
60
+ .${prefix}-card-shadow-xl { box-shadow: var(--${prefix}-shadow-xl); }
61
+
62
+ .${prefix}-modal-backdrop {
63
+ position: absolute;
64
+ inset: 0;
65
+ background: rgba(0, 0, 0, 0.5);
66
+ backdrop-filter: blur(4px);
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ padding: 24px;
71
+ z-index: 100;
72
+ }
73
+
74
+ .${prefix}-modal {
75
+ background: var(--${prefix}-bg);
76
+ border: 1px solid var(--${prefix}-border);
77
+ border-radius: var(--${prefix}-radius);
78
+ box-shadow: var(--${prefix}-shadow-xl);
79
+ padding: 24px;
80
+ min-width: 320px;
81
+ max-width: 90vw;
82
+ max-height: 90vh;
83
+ overflow: auto;
84
+ }
85
+
86
+ .${prefix}-modal-title {
87
+ margin: 0 0 16px 0;
88
+ font-size: 20px;
89
+ font-weight: 600;
90
+ }
91
+
92
+ .${prefix}-drawer {
93
+ position: fixed;
94
+ background: var(--${prefix}-bg);
95
+ border: 1px solid var(--${prefix}-border);
96
+ box-shadow: var(--${prefix}-shadow-xl);
97
+ padding: 16px;
98
+ overflow: auto;
99
+ z-index: 1000;
100
+ }
101
+
102
+ .${prefix}-drawer-left {
103
+ top: 0;
104
+ left: 0;
105
+ bottom: 0;
106
+ width: 280px;
107
+ border-right: 1px solid var(--${prefix}-border);
108
+ }
109
+
110
+ .${prefix}-drawer-right {
111
+ top: 0;
112
+ right: 0;
113
+ bottom: 0;
114
+ width: 280px;
115
+ border-left: 1px solid var(--${prefix}-border);
116
+ }
117
+
118
+ .${prefix}-drawer-top {
119
+ top: 0;
120
+ left: 0;
121
+ right: 0;
122
+ height: auto;
123
+ max-height: 50vh;
124
+ border-bottom: 1px solid var(--${prefix}-border);
125
+ }
126
+
127
+ .${prefix}-drawer-bottom {
128
+ bottom: 0;
129
+ left: 0;
130
+ right: 0;
131
+ height: auto;
132
+ max-height: 50vh;
133
+ border-top: 1px solid var(--${prefix}-border);
134
+ }
135
+
136
+ .${prefix}-drawer-title {
137
+ margin: 0 0 16px 0;
138
+ font-size: 18px;
139
+ font-weight: 600;
140
+ }
141
+
142
+ .${prefix}-accordion {
143
+ border: 1px solid var(--${prefix}-border);
144
+ border-radius: var(--${prefix}-radius);
145
+ }
146
+
147
+ .${prefix}-accordion-header {
148
+ display: flex;
149
+ align-items: center;
150
+ justify-content: space-between;
151
+ width: 100%;
152
+ padding: 12px 16px;
153
+ background: transparent;
154
+ border: none;
155
+ border-bottom: 1px solid var(--${prefix}-border);
156
+ font-size: 16px;
157
+ font-weight: 500;
158
+ cursor: pointer;
159
+ text-align: left;
160
+ }
161
+
162
+ .${prefix}-accordion-header:hover {
163
+ background: rgba(0, 0, 0, 0.02);
164
+ }
165
+
166
+ .${prefix}-accordion-content {
167
+ padding: 16px;
168
+ }`;
169
+ }
170
+
171
+ /**
172
+ * Text component styles
173
+ */
174
+ function generateTextStyles(prefix: string): string {
175
+ return `/* Text Components */
176
+ .${prefix}-text {
177
+ margin: 0;
178
+ line-height: 1.5;
179
+ }
180
+
181
+ .${prefix}-text-xs { font-size: 12px; }
182
+ .${prefix}-text-sm { font-size: 14px; }
183
+ .${prefix}-text-base { font-size: 16px; }
184
+ .${prefix}-text-md { font-size: 16px; }
185
+ .${prefix}-text-lg { font-size: 18px; }
186
+ .${prefix}-text-xl { font-size: 20px; }
187
+ .${prefix}-text-2xl { font-size: 24px; }
188
+ .${prefix}-text-3xl { font-size: 30px; }
189
+
190
+ .${prefix}-text-normal { font-weight: 400; }
191
+ .${prefix}-text-medium { font-weight: 500; }
192
+ .${prefix}-text-semibold { font-weight: 600; }
193
+ .${prefix}-text-bold { font-weight: 700; }
194
+
195
+ .${prefix}-text-left { text-align: left; }
196
+ .${prefix}-text-center { text-align: center; }
197
+ .${prefix}-text-right { text-align: right; }
198
+ .${prefix}-text-justify { text-align: justify; }
199
+
200
+ .${prefix}-text-muted { color: var(--${prefix}-muted); }
201
+
202
+ .${prefix}-title {
203
+ margin: 0 0 8px 0;
204
+ font-weight: 600;
205
+ line-height: 1.25;
206
+ }
207
+
208
+ h1.${prefix}-title { font-size: 36px; }
209
+ h2.${prefix}-title { font-size: 30px; }
210
+ h3.${prefix}-title { font-size: 24px; }
211
+ h4.${prefix}-title { font-size: 20px; }
212
+ h5.${prefix}-title { font-size: 18px; }
213
+ h6.${prefix}-title { font-size: 16px; }
214
+
215
+ .${prefix}-link {
216
+ color: var(--${prefix}-fg);
217
+ text-decoration: underline;
218
+ cursor: pointer;
219
+ }
220
+
221
+ .${prefix}-link:hover {
222
+ opacity: 0.7;
223
+ }`;
224
+ }
225
+
226
+ /**
227
+ * Input component styles
228
+ */
229
+ function generateInputStyles(_theme: ThemeConfig, prefix: string): string {
230
+ return `/* Input Components */
231
+ .${prefix}-form-field {
232
+ margin-bottom: 16px;
233
+ }
234
+
235
+ .${prefix}-input-label {
236
+ display: block;
237
+ margin-bottom: 4px;
238
+ font-size: 14px;
239
+ font-weight: 500;
240
+ }
241
+
242
+ .${prefix}-input,
243
+ .${prefix}-textarea,
244
+ .${prefix}-select {
245
+ display: block;
246
+ width: 100%;
247
+ padding: 8px 12px;
248
+ border: 1px solid var(--${prefix}-border);
249
+ border-radius: var(--${prefix}-radius);
250
+ font-family: inherit;
251
+ font-size: 14px;
252
+ background: var(--${prefix}-bg);
253
+ color: var(--${prefix}-fg);
254
+ transition: border-color 0.15s ease;
255
+ }
256
+
257
+ /* Inputs in flex rows should not take full width */
258
+ .${prefix}-row > .${prefix}-input,
259
+ .${prefix}-row > .${prefix}-select {
260
+ width: auto;
261
+ flex: 1 1 auto;
262
+ min-width: 120px;
263
+ }
264
+
265
+ .${prefix}-input:focus,
266
+ .${prefix}-textarea:focus,
267
+ .${prefix}-select:focus {
268
+ outline: none;
269
+ border-color: var(--${prefix}-fg);
270
+ box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1);
271
+ }
272
+
273
+ .${prefix}-input:disabled,
274
+ .${prefix}-textarea:disabled,
275
+ .${prefix}-select:disabled {
276
+ opacity: 0.5;
277
+ cursor: not-allowed;
278
+ background: rgba(0, 0, 0, 0.03);
279
+ }
280
+
281
+ .${prefix}-input::placeholder,
282
+ .${prefix}-textarea::placeholder {
283
+ color: var(--${prefix}-muted);
284
+ }
285
+
286
+ .${prefix}-input-error {
287
+ border-color: var(--${prefix}-danger);
288
+ }
289
+
290
+ /* Input with icon */
291
+ .${prefix}-input-wrapper {
292
+ position: relative;
293
+ display: flex;
294
+ align-items: center;
295
+ }
296
+
297
+ .${prefix}-input-wrapper .${prefix}-input {
298
+ padding-left: 36px;
299
+ }
300
+
301
+ .${prefix}-input-icon {
302
+ position: absolute;
303
+ left: 12px;
304
+ color: var(--${prefix}-muted);
305
+ pointer-events: none;
306
+ display: flex;
307
+ align-items: center;
308
+ justify-content: center;
309
+ width: 16px;
310
+ height: 16px;
311
+ }
312
+
313
+ .${prefix}-input-icon svg {
314
+ width: 16px;
315
+ height: 16px;
316
+ }
317
+
318
+ /* Input wrapper in flex rows */
319
+ .${prefix}-row > .${prefix}-input-wrapper {
320
+ flex: 1 1 auto;
321
+ min-width: 120px;
322
+ }
323
+
324
+ .${prefix}-textarea {
325
+ min-height: 80px;
326
+ resize: vertical;
327
+ }
328
+
329
+ .${prefix}-select {
330
+ appearance: none;
331
+ 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='%23333' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
332
+ background-repeat: no-repeat;
333
+ background-position: right 12px center;
334
+ padding-right: 36px;
335
+ }
336
+
337
+ .${prefix}-checkbox,
338
+ .${prefix}-radio {
339
+ display: flex;
340
+ align-items: center;
341
+ gap: 8px;
342
+ cursor: pointer;
343
+ }
344
+
345
+ .${prefix}-checkbox input,
346
+ .${prefix}-radio input {
347
+ width: 18px;
348
+ height: 18px;
349
+ margin: 0;
350
+ cursor: pointer;
351
+ }
352
+
353
+ .${prefix}-checkbox-label,
354
+ .${prefix}-radio-label {
355
+ font-size: 14px;
356
+ }
357
+
358
+ .${prefix}-switch {
359
+ display: inline-flex;
360
+ align-items: center;
361
+ gap: 8px;
362
+ cursor: pointer;
363
+ }
364
+
365
+ .${prefix}-switch input[type="checkbox"] {
366
+ appearance: none;
367
+ width: 40px;
368
+ height: 22px;
369
+ background: var(--${prefix}-muted);
370
+ border-radius: 11px;
371
+ position: relative;
372
+ cursor: pointer;
373
+ transition: background-color 0.2s ease;
374
+ }
375
+
376
+ .${prefix}-switch input[type="checkbox"]::after {
377
+ content: '';
378
+ position: absolute;
379
+ top: 2px;
380
+ left: 2px;
381
+ width: 18px;
382
+ height: 18px;
383
+ background: white;
384
+ border-radius: 50%;
385
+ transition: transform 0.2s ease;
386
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
387
+ }
388
+
389
+ .${prefix}-switch input[type="checkbox"]:checked {
390
+ background: var(--${prefix}-fg);
391
+ }
392
+
393
+ .${prefix}-switch input[type="checkbox"]:checked::after {
394
+ transform: translateX(18px);
395
+ }
396
+
397
+ .${prefix}-switch-label {
398
+ font-size: 14px;
399
+ }
400
+
401
+ .${prefix}-slider {
402
+ appearance: none;
403
+ width: 100%;
404
+ height: 6px;
405
+ background: var(--${prefix}-border);
406
+ border-radius: 3px;
407
+ outline: none;
408
+ }
409
+
410
+ .${prefix}-slider::-webkit-slider-thumb {
411
+ appearance: none;
412
+ width: 18px;
413
+ height: 18px;
414
+ background: var(--${prefix}-fg);
415
+ border-radius: 50%;
416
+ cursor: pointer;
417
+ }
418
+
419
+ .${prefix}-slider::-moz-range-thumb {
420
+ width: 18px;
421
+ height: 18px;
422
+ background: var(--${prefix}-fg);
423
+ border: none;
424
+ border-radius: 50%;
425
+ cursor: pointer;
426
+ }`;
427
+ }
428
+
429
+ /**
430
+ * Button component styles
431
+ */
432
+ function generateButtonStyles(_theme: ThemeConfig, prefix: string): string {
433
+ return `/* Button Components */
434
+ .${prefix}-button {
435
+ display: inline-flex;
436
+ align-items: center;
437
+ justify-content: center;
438
+ gap: 8px;
439
+ padding: 8px 16px;
440
+ border: 1px solid var(--${prefix}-border);
441
+ border-radius: var(--${prefix}-radius);
442
+ background: var(--${prefix}-bg);
443
+ color: var(--${prefix}-fg);
444
+ font-family: inherit;
445
+ font-size: 14px;
446
+ font-weight: 500;
447
+ cursor: pointer;
448
+ transition: all 0.15s ease;
449
+ white-space: nowrap;
450
+ }
451
+
452
+ .${prefix}-button:hover:not(:disabled) {
453
+ background: rgba(0, 0, 0, 0.05);
454
+ }
455
+
456
+ .${prefix}-button:active:not(:disabled) {
457
+ transform: translateY(1px);
458
+ }
459
+
460
+ .${prefix}-button:focus {
461
+ outline: none;
462
+ box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.2);
463
+ }
464
+
465
+ .${prefix}-button-primary {
466
+ background: var(--${prefix}-fg);
467
+ color: var(--${prefix}-bg);
468
+ border-color: var(--${prefix}-fg);
469
+ }
470
+
471
+ .${prefix}-button-primary:hover:not(:disabled) {
472
+ opacity: 0.9;
473
+ background: var(--${prefix}-fg);
474
+ }
475
+
476
+ .${prefix}-button-secondary {
477
+ background: var(--${prefix}-muted);
478
+ color: var(--${prefix}-bg);
479
+ border-color: var(--${prefix}-muted);
480
+ }
481
+
482
+ .${prefix}-button-outline {
483
+ background: transparent;
484
+ }
485
+
486
+ .${prefix}-button-outline:hover:not(:disabled) {
487
+ background: var(--${prefix}-fg);
488
+ color: var(--${prefix}-bg);
489
+ }
490
+
491
+ .${prefix}-button-ghost {
492
+ border-color: transparent;
493
+ background: transparent;
494
+ }
495
+
496
+ .${prefix}-button-ghost:hover:not(:disabled) {
497
+ background: rgba(0, 0, 0, 0.05);
498
+ }
499
+
500
+ .${prefix}-button-danger {
501
+ color: var(--${prefix}-danger);
502
+ border-color: var(--${prefix}-danger);
503
+ }
504
+
505
+ .${prefix}-button-danger:hover:not(:disabled) {
506
+ background: var(--${prefix}-danger);
507
+ color: white;
508
+ }
509
+
510
+ .${prefix}-button-xs { padding: 4px 8px; font-size: 12px; }
511
+ .${prefix}-button-sm { padding: 6px 12px; font-size: 13px; }
512
+ .${prefix}-button-md { padding: 8px 16px; font-size: 14px; }
513
+ .${prefix}-button-lg { padding: 10px 20px; font-size: 16px; }
514
+ .${prefix}-button-xl { padding: 12px 24px; font-size: 18px; }
515
+
516
+ /* Icon-only button (square padding) */
517
+ .${prefix}-button-icon-only { padding: 8px; }
518
+ .${prefix}-button-icon-only.${prefix}-button-xs { padding: 4px; }
519
+ .${prefix}-button-icon-only.${prefix}-button-sm { padding: 6px; }
520
+ .${prefix}-button-icon-only.${prefix}-button-md { padding: 8px; }
521
+ .${prefix}-button-icon-only.${prefix}-button-lg { padding: 10px; }
522
+ .${prefix}-button-icon-only.${prefix}-button-xl { padding: 12px; }
523
+
524
+ /* Button icon sizes - scale icon based on button size */
525
+ .${prefix}-button svg.${prefix}-icon { width: 16px; height: 16px; }
526
+ .${prefix}-button-xs svg.${prefix}-icon { width: 12px; height: 12px; }
527
+ .${prefix}-button-sm svg.${prefix}-icon { width: 14px; height: 14px; }
528
+ .${prefix}-button-md svg.${prefix}-icon { width: 16px; height: 16px; }
529
+ .${prefix}-button-lg svg.${prefix}-icon { width: 20px; height: 20px; }
530
+ .${prefix}-button-xl svg.${prefix}-icon { width: 24px; height: 24px; }
531
+
532
+ .${prefix}-button-disabled,
533
+ .${prefix}-button:disabled {
534
+ opacity: 0.5;
535
+ cursor: not-allowed;
536
+ }
537
+
538
+ .${prefix}-button-loading {
539
+ position: relative;
540
+ color: transparent;
541
+ }
542
+
543
+ .${prefix}-button-loading::after {
544
+ content: '';
545
+ position: absolute;
546
+ width: 16px;
547
+ height: 16px;
548
+ border: 2px solid currentColor;
549
+ border-top-color: transparent;
550
+ border-radius: 50%;
551
+ animation: ${prefix}-spin 0.6s linear infinite;
552
+ }
553
+
554
+ /* Button justify overrides - higher specificity to override default center */
555
+ .${prefix}-button.${prefix}-justify-start { justify-content: flex-start; }
556
+ .${prefix}-button.${prefix}-justify-end { justify-content: flex-end; }
557
+ .${prefix}-button.${prefix}-justify-between { justify-content: space-between; }`;
558
+ }
559
+
560
+ /**
561
+ * Display component styles
562
+ */
563
+ function generateDisplayStyles(_theme: ThemeConfig, prefix: string): string {
564
+ return `/* Display Components */
565
+ .${prefix}-image {
566
+ display: flex;
567
+ flex-direction: column;
568
+ align-items: center;
569
+ justify-content: center;
570
+ gap: 12px;
571
+ min-height: 120px;
572
+ max-width: 100%;
573
+ background: repeating-linear-gradient(
574
+ 45deg,
575
+ transparent,
576
+ transparent 10px,
577
+ rgba(128, 128, 128, 0.05) 10px,
578
+ rgba(128, 128, 128, 0.05) 20px
579
+ );
580
+ border: 1px dashed var(--${prefix}-border);
581
+ border-radius: var(--${prefix}-radius);
582
+ color: var(--${prefix}-muted);
583
+ font-size: 14px;
584
+ }
585
+
586
+ .${prefix}-image svg {
587
+ opacity: 0.5;
588
+ }
589
+
590
+ img.${prefix}-image {
591
+ display: block;
592
+ border-style: solid;
593
+ background: none;
594
+ }
595
+
596
+ .${prefix}-placeholder {
597
+ display: flex;
598
+ align-items: center;
599
+ justify-content: center;
600
+ min-height: 100px;
601
+ background: repeating-linear-gradient(
602
+ 45deg,
603
+ transparent,
604
+ transparent 10px,
605
+ rgba(0, 0, 0, 0.03) 10px,
606
+ rgba(0, 0, 0, 0.03) 20px
607
+ );
608
+ border: 1px dashed var(--${prefix}-border);
609
+ border-radius: var(--${prefix}-radius);
610
+ color: var(--${prefix}-muted);
611
+ font-size: 14px;
612
+ }
613
+
614
+ .${prefix}-avatar {
615
+ display: inline-flex;
616
+ align-items: center;
617
+ justify-content: center;
618
+ width: 40px;
619
+ height: 40px;
620
+ background: var(--${prefix}-fg);
621
+ border-radius: 50%;
622
+ font-size: 14px;
623
+ font-weight: 600;
624
+ color: var(--${prefix}-bg);
625
+ overflow: hidden;
626
+ }
627
+
628
+ .${prefix}-avatar img {
629
+ width: 100%;
630
+ height: 100%;
631
+ object-fit: cover;
632
+ }
633
+
634
+ .${prefix}-avatar-xs { width: 24px; height: 24px; font-size: 10px; }
635
+ .${prefix}-avatar-sm { width: 32px; height: 32px; font-size: 12px; }
636
+ .${prefix}-avatar-md { width: 40px; height: 40px; font-size: 14px; }
637
+ .${prefix}-avatar-lg { width: 48px; height: 48px; font-size: 16px; }
638
+ .${prefix}-avatar-xl { width: 64px; height: 64px; font-size: 20px; }
639
+
640
+ .${prefix}-badge {
641
+ display: inline-flex;
642
+ align-items: center;
643
+ padding: 2px 8px;
644
+ font-size: 12px;
645
+ font-weight: 500;
646
+ border: 1px solid var(--${prefix}-border);
647
+ border-radius: var(--${prefix}-radius);
648
+ background: var(--${prefix}-bg);
649
+ }
650
+
651
+ .${prefix}-badge-pill {
652
+ border-radius: 9999px;
653
+ }
654
+
655
+ /* Dot badge - circular status indicator (for empty badges) */
656
+ .${prefix}-badge-dot {
657
+ width: 8px;
658
+ height: 8px;
659
+ padding: 0;
660
+ border-radius: 50%;
661
+ background: var(--${prefix}-border);
662
+ }
663
+ .${prefix}-badge-dot.${prefix}-badge-success { background: var(--${prefix}-success); border-color: var(--${prefix}-success); }
664
+ .${prefix}-badge-dot.${prefix}-badge-warning { background: var(--${prefix}-warning); border-color: var(--${prefix}-warning); }
665
+ .${prefix}-badge-dot.${prefix}-badge-danger { background: var(--${prefix}-danger); border-color: var(--${prefix}-danger); }
666
+ .${prefix}-badge-dot.${prefix}-badge-primary { background: var(--${prefix}-primary); border-color: var(--${prefix}-primary); }
667
+
668
+ .${prefix}-badge-default { }
669
+ .${prefix}-badge-primary { background: var(--${prefix}-primary); color: white; border-color: var(--${prefix}-primary); }
670
+ .${prefix}-badge-secondary { background: var(--${prefix}-muted); color: white; border-color: var(--${prefix}-muted); }
671
+ .${prefix}-badge-success { border-color: var(--${prefix}-success); }
672
+ .${prefix}-badge-warning { border-color: var(--${prefix}-warning); }
673
+ .${prefix}-badge-danger { border-color: var(--${prefix}-danger); }
674
+ .${prefix}-badge-info { border-color: var(--${prefix}-primary); }
675
+
676
+ /* Icon badge - circular background with icon */
677
+ .${prefix}-badge-icon {
678
+ display: inline-flex;
679
+ align-items: center;
680
+ justify-content: center;
681
+ width: 40px;
682
+ height: 40px;
683
+ border-radius: 50%;
684
+ background: rgba(0, 0, 0, 0.05);
685
+ color: var(--${prefix}-fg);
686
+ }
687
+
688
+ .${prefix}-badge-icon svg {
689
+ width: 20px;
690
+ height: 20px;
691
+ }
692
+
693
+ /* Icon badge sizes - use higher specificity to override svg.wf-icon */
694
+ .${prefix}-badge-icon-xs { width: 24px; height: 24px; }
695
+ .${prefix}-badge-icon-xs svg.${prefix}-icon { width: 12px; height: 12px; }
696
+ .${prefix}-badge-icon-sm { width: 32px; height: 32px; }
697
+ .${prefix}-badge-icon-sm svg.${prefix}-icon { width: 16px; height: 16px; }
698
+ .${prefix}-badge-icon-md { width: 40px; height: 40px; }
699
+ .${prefix}-badge-icon-md svg.${prefix}-icon { width: 20px; height: 20px; }
700
+ .${prefix}-badge-icon-lg { width: 48px; height: 48px; }
701
+ .${prefix}-badge-icon-lg svg.${prefix}-icon { width: 24px; height: 24px; }
702
+ .${prefix}-badge-icon-xl { width: 64px; height: 64px; }
703
+ .${prefix}-badge-icon-xl svg.${prefix}-icon { width: 32px; height: 32px; }
704
+
705
+ .${prefix}-badge-icon-primary,
706
+ .${prefix}-badge-icon-success,
707
+ .${prefix}-badge-icon-warning,
708
+ .${prefix}-badge-icon-danger {
709
+ background: rgba(0, 0, 0, 0.05);
710
+ color: var(--${prefix}-fg);
711
+ }
712
+
713
+ .${prefix}-icon {
714
+ display: inline-flex;
715
+ align-items: center;
716
+ justify-content: center;
717
+ font-style: normal;
718
+ vertical-align: middle;
719
+ flex-shrink: 0;
720
+ }
721
+
722
+ /* SVG icons - size is controlled by CSS, not HTML attributes */
723
+ svg.${prefix}-icon {
724
+ width: 16px;
725
+ height: 16px;
726
+ display: block;
727
+ }
728
+
729
+ /* Icon size tokens */
730
+ svg.${prefix}-icon-xs { width: 12px; height: 12px; }
731
+ svg.${prefix}-icon-sm { width: 14px; height: 14px; }
732
+ svg.${prefix}-icon-md { width: 16px; height: 16px; }
733
+ svg.${prefix}-icon-lg { width: 20px; height: 20px; }
734
+ svg.${prefix}-icon-xl { width: 24px; height: 24px; }
735
+
736
+ .${prefix}-icon svg {
737
+ display: block;
738
+ }
739
+
740
+ .${prefix}-icon-wrapper {
741
+ display: inline-flex;
742
+ align-items: center;
743
+ justify-content: center;
744
+ }`;
745
+ }
746
+
747
+ /**
748
+ * Data component styles
749
+ */
750
+ function generateDataStyles(_theme: ThemeConfig, prefix: string): string {
751
+ return `/* Data Components */
752
+ .${prefix}-table {
753
+ width: 100%;
754
+ border-collapse: collapse;
755
+ border: 1px solid var(--${prefix}-border);
756
+ font-size: 14px;
757
+ }
758
+
759
+ .${prefix}-table th,
760
+ .${prefix}-table td {
761
+ padding: 10px 12px;
762
+ text-align: left;
763
+ border-bottom: 1px solid var(--${prefix}-border);
764
+ }
765
+
766
+ .${prefix}-table th {
767
+ background: rgba(0, 0, 0, 0.02);
768
+ font-weight: 600;
769
+ }
770
+
771
+ .${prefix}-table-bordered th,
772
+ .${prefix}-table-bordered td {
773
+ border: 1px solid var(--${prefix}-border);
774
+ }
775
+
776
+ .${prefix}-table-striped tbody tr:nth-child(odd) {
777
+ background: rgba(0, 0, 0, 0.02);
778
+ }
779
+
780
+ .${prefix}-table-hover tbody tr:hover {
781
+ background: rgba(0, 0, 0, 0.04);
782
+ }
783
+
784
+ .${prefix}-list {
785
+ list-style: none;
786
+ padding: 0;
787
+ margin: 0;
788
+ }
789
+
790
+ .${prefix}-list-ordered {
791
+ list-style: decimal;
792
+ padding-left: 24px;
793
+ }
794
+
795
+ .${prefix}-list-none {
796
+ list-style: none;
797
+ }
798
+
799
+ .${prefix}-list-item {
800
+ padding: 8px 0;
801
+ border-bottom: 1px solid var(--${prefix}-border);
802
+ }
803
+
804
+ .${prefix}-list-item:last-child {
805
+ border-bottom: none;
806
+ }`;
807
+ }
808
+
809
+ /**
810
+ * Feedback component styles
811
+ */
812
+ function generateFeedbackStyles(_theme: ThemeConfig, prefix: string): string {
813
+ return `/* Feedback Components */
814
+ .${prefix}-alert {
815
+ padding: 12px 16px;
816
+ border: 1px solid var(--${prefix}-border);
817
+ border-radius: var(--${prefix}-radius);
818
+ margin-bottom: 16px;
819
+ font-size: 14px;
820
+ display: flex;
821
+ align-items: flex-start;
822
+ gap: 8px;
823
+ }
824
+
825
+ .${prefix}-alert-info { border-left: 3px solid var(--${prefix}-primary); }
826
+ .${prefix}-alert-success { border-left: 3px solid var(--${prefix}-success); }
827
+ .${prefix}-alert-warning { border-left: 3px solid var(--${prefix}-warning); }
828
+ .${prefix}-alert-danger { border-left: 3px solid var(--${prefix}-danger); }
829
+
830
+ .${prefix}-alert-close {
831
+ margin-left: auto;
832
+ background: transparent;
833
+ border: none;
834
+ font-size: 18px;
835
+ cursor: pointer;
836
+ opacity: 0.5;
837
+ }
838
+
839
+ .${prefix}-alert-close:hover {
840
+ opacity: 1;
841
+ }
842
+
843
+ .${prefix}-toast {
844
+ padding: 12px 16px;
845
+ background: var(--${prefix}-fg);
846
+ color: var(--${prefix}-bg);
847
+ border-radius: var(--${prefix}-radius);
848
+ box-shadow: var(--${prefix}-shadow-lg);
849
+ font-size: 14px;
850
+ }
851
+
852
+ .${prefix}-progress {
853
+ height: 8px;
854
+ background: var(--${prefix}-border);
855
+ border-radius: 4px;
856
+ overflow: hidden;
857
+ }
858
+
859
+ .${prefix}-progress-bar {
860
+ height: 100%;
861
+ background: var(--${prefix}-fg);
862
+ border-radius: 4px;
863
+ transition: width 0.3s ease;
864
+ }
865
+
866
+ .${prefix}-progress-indeterminate .${prefix}-progress-bar {
867
+ width: 30%;
868
+ animation: ${prefix}-progress-indeterminate 1.5s ease-in-out infinite;
869
+ }
870
+
871
+ @keyframes ${prefix}-progress-indeterminate {
872
+ 0% { transform: translateX(-100%); }
873
+ 100% { transform: translateX(400%); }
874
+ }
875
+
876
+ .${prefix}-progress-label {
877
+ display: block;
878
+ margin-bottom: 4px;
879
+ font-size: 12px;
880
+ color: var(--${prefix}-muted);
881
+ }
882
+
883
+ .${prefix}-spinner {
884
+ display: inline-block;
885
+ width: 20px;
886
+ height: 20px;
887
+ border: 2px solid var(--${prefix}-border);
888
+ border-top-color: var(--${prefix}-fg);
889
+ border-radius: 50%;
890
+ animation: ${prefix}-spin 0.6s linear infinite;
891
+ }
892
+
893
+ .${prefix}-spinner-xs { width: 12px; height: 12px; border-width: 2px; }
894
+ .${prefix}-spinner-sm { width: 16px; height: 16px; border-width: 2px; }
895
+ .${prefix}-spinner-md { width: 24px; height: 24px; border-width: 2px; }
896
+ .${prefix}-spinner-lg { width: 32px; height: 32px; border-width: 3px; }
897
+ .${prefix}-spinner-xl { width: 48px; height: 48px; border-width: 4px; }
898
+
899
+ @keyframes ${prefix}-spin {
900
+ to { transform: rotate(360deg); }
901
+ }`;
902
+ }
903
+
904
+ /**
905
+ * Overlay component styles
906
+ */
907
+ function generateOverlayStyles(_theme: ThemeConfig, prefix: string): string {
908
+ return `/* Overlay Components */
909
+ .${prefix}-tooltip-wrapper {
910
+ position: relative;
911
+ display: inline-block;
912
+ }
913
+
914
+ .${prefix}-tooltip {
915
+ position: absolute;
916
+ padding: 6px 10px;
917
+ background: var(--${prefix}-fg);
918
+ color: var(--${prefix}-bg);
919
+ font-size: 12px;
920
+ border-radius: var(--${prefix}-radius);
921
+ white-space: nowrap;
922
+ z-index: 1000;
923
+ pointer-events: none;
924
+ }
925
+
926
+ .${prefix}-tooltip-top {
927
+ bottom: 100%;
928
+ left: 50%;
929
+ transform: translateX(-50%);
930
+ margin-bottom: 8px;
931
+ }
932
+
933
+ .${prefix}-tooltip-bottom {
934
+ top: 100%;
935
+ left: 50%;
936
+ transform: translateX(-50%);
937
+ margin-top: 8px;
938
+ }
939
+
940
+ .${prefix}-tooltip-left {
941
+ right: 100%;
942
+ top: 50%;
943
+ transform: translateY(-50%);
944
+ margin-right: 8px;
945
+ }
946
+
947
+ .${prefix}-tooltip-right {
948
+ left: 100%;
949
+ top: 50%;
950
+ transform: translateY(-50%);
951
+ margin-left: 8px;
952
+ }
953
+
954
+ .${prefix}-popover {
955
+ background: var(--${prefix}-bg);
956
+ border: 1px solid var(--${prefix}-border);
957
+ border-radius: var(--${prefix}-radius);
958
+ box-shadow: var(--${prefix}-shadow-lg);
959
+ min-width: 200px;
960
+ }
961
+
962
+ .${prefix}-popover-header {
963
+ padding: 12px 16px;
964
+ border-bottom: 1px solid var(--${prefix}-border);
965
+ font-weight: 600;
966
+ }
967
+
968
+ .${prefix}-popover-body {
969
+ padding: 16px;
970
+ }
971
+
972
+ .${prefix}-dropdown {
973
+ background: var(--${prefix}-bg);
974
+ border: 1px solid var(--${prefix}-border);
975
+ border-radius: var(--${prefix}-radius);
976
+ box-shadow: var(--${prefix}-shadow-md);
977
+ min-width: 160px;
978
+ padding: 4px 0;
979
+ }
980
+
981
+ .${prefix}-dropdown-item {
982
+ display: block;
983
+ width: 100%;
984
+ padding: 8px 16px;
985
+ background: transparent;
986
+ border: none;
987
+ text-align: left;
988
+ font-size: 14px;
989
+ cursor: pointer;
990
+ }
991
+
992
+ .${prefix}-dropdown-item:hover:not(:disabled) {
993
+ background: rgba(0, 0, 0, 0.05);
994
+ }
995
+
996
+ .${prefix}-dropdown-item-danger {
997
+ color: var(--${prefix}-danger);
998
+ }
999
+
1000
+ .${prefix}-dropdown-item-disabled {
1001
+ opacity: 0.5;
1002
+ cursor: not-allowed;
1003
+ }`;
1004
+ }
1005
+
1006
+ /**
1007
+ * Navigation component styles
1008
+ */
1009
+ function generateNavigationStyles(_theme: ThemeConfig, prefix: string): string {
1010
+ return `/* Navigation Components */
1011
+ .${prefix}-nav {
1012
+ display: flex;
1013
+ gap: 4px;
1014
+ }
1015
+
1016
+ .${prefix}-nav-vertical {
1017
+ flex-direction: column;
1018
+ }
1019
+
1020
+ .${prefix}-nav-link {
1021
+ display: inline-flex;
1022
+ align-items: center;
1023
+ gap: 8px;
1024
+ padding: 8px 16px;
1025
+ color: var(--${prefix}-fg);
1026
+ text-decoration: none;
1027
+ border-radius: var(--${prefix}-radius);
1028
+ font-size: 14px;
1029
+ transition: background-color 0.15s ease;
1030
+ }
1031
+
1032
+ .${prefix}-nav-link:hover {
1033
+ background: rgba(0, 0, 0, 0.05);
1034
+ }
1035
+
1036
+ .${prefix}-nav-link-active {
1037
+ background: rgba(0, 0, 0, 0.08);
1038
+ font-weight: 500;
1039
+ }
1040
+
1041
+ .${prefix}-nav-link-disabled {
1042
+ opacity: 0.5;
1043
+ cursor: not-allowed;
1044
+ }
1045
+
1046
+ .${prefix}-tabs {
1047
+ border-bottom: 1px solid var(--${prefix}-border);
1048
+ }
1049
+
1050
+ .${prefix}-tab-list {
1051
+ display: flex;
1052
+ gap: 0;
1053
+ margin-bottom: -1px;
1054
+ }
1055
+
1056
+ .${prefix}-tab {
1057
+ padding: 10px 16px;
1058
+ background: transparent;
1059
+ border: none;
1060
+ border-bottom: 2px solid transparent;
1061
+ font-size: 14px;
1062
+ color: var(--${prefix}-fg);
1063
+ cursor: pointer;
1064
+ transition: all 0.15s ease;
1065
+ }
1066
+
1067
+ .${prefix}-tab:hover {
1068
+ background: rgba(128, 128, 128, 0.1);
1069
+ }
1070
+
1071
+ .${prefix}-tab-active {
1072
+ border-bottom-color: var(--${prefix}-fg);
1073
+ font-weight: 500;
1074
+ }
1075
+
1076
+ .${prefix}-breadcrumb {
1077
+ display: flex;
1078
+ align-items: center;
1079
+ font-size: 14px;
1080
+ }
1081
+
1082
+ .${prefix}-breadcrumb-item {
1083
+ color: var(--${prefix}-fg);
1084
+ text-decoration: none;
1085
+ }
1086
+
1087
+ .${prefix}-breadcrumb-item:hover {
1088
+ text-decoration: underline;
1089
+ }
1090
+
1091
+ .${prefix}-breadcrumb-item[aria-current="page"] {
1092
+ color: var(--${prefix}-muted);
1093
+ }
1094
+
1095
+ .${prefix}-breadcrumb-separator {
1096
+ margin: 0 8px;
1097
+ color: var(--${prefix}-muted);
1098
+ }`;
1099
+ }
1100
+
1101
+ /**
1102
+ * Semantic marker styles
1103
+ *
1104
+ * Styles for [component:variant] placeholders in table cells and text
1105
+ * These help visualize semantic meaning while being readable by LLMs
1106
+ */
1107
+ function generateSemanticMarkerStyles(_theme: ThemeConfig, prefix: string): string {
1108
+ return `/* Semantic Markers */
1109
+
1110
+ /* Avatar marker - small circle placeholder */
1111
+ .${prefix}-semantic-avatar {
1112
+ display: inline-flex;
1113
+ align-items: center;
1114
+ justify-content: center;
1115
+ border-radius: 50%;
1116
+ background: var(--${prefix}-muted);
1117
+ color: var(--${prefix}-bg);
1118
+ font-size: 10px;
1119
+ font-weight: 600;
1120
+ vertical-align: middle;
1121
+ margin-right: 8px;
1122
+ }
1123
+
1124
+ .${prefix}-semantic-avatar-xs { width: 16px; height: 16px; }
1125
+ .${prefix}-semantic-avatar-sm { width: 24px; height: 24px; }
1126
+ .${prefix}-semantic-avatar-md { width: 32px; height: 32px; }
1127
+ .${prefix}-semantic-avatar-lg { width: 40px; height: 40px; }
1128
+
1129
+ /* Badge marker - inline status indicator (wireframe style: black/white only) */
1130
+ .${prefix}-semantic-badge {
1131
+ display: inline-block;
1132
+ padding: 2px 8px;
1133
+ font-size: 11px;
1134
+ font-weight: 500;
1135
+ border-radius: 9999px;
1136
+ vertical-align: middle;
1137
+ background: var(--${prefix}-fg);
1138
+ color: var(--${prefix}-bg);
1139
+ }
1140
+
1141
+ /* Dot marker - status dot (wireframe style: black/gray only) */
1142
+ .${prefix}-semantic-dot {
1143
+ display: inline-block;
1144
+ width: 8px;
1145
+ height: 8px;
1146
+ border-radius: 50%;
1147
+ vertical-align: middle;
1148
+ margin-right: 6px;
1149
+ background: var(--${prefix}-fg);
1150
+ }
1151
+
1152
+ /* Inactive/default state uses gray */
1153
+ .${prefix}-semantic-dot-default { background: var(--${prefix}-muted); }
1154
+
1155
+ /* Icon marker placeholder */
1156
+ .${prefix}-semantic-icon {
1157
+ display: inline-block;
1158
+ font-size: 12px;
1159
+ color: var(--${prefix}-muted);
1160
+ vertical-align: middle;
1161
+ }
1162
+
1163
+ /* Unknown marker - fallback */
1164
+ .${prefix}-semantic-unknown {
1165
+ display: inline-block;
1166
+ font-size: 11px;
1167
+ color: var(--${prefix}-muted);
1168
+ font-style: italic;
1169
+ }
1170
+
1171
+ /* Avatar + text layout in table cells */
1172
+ .${prefix}-cell-avatar-layout {
1173
+ display: flex;
1174
+ align-items: center;
1175
+ gap: 10px;
1176
+ }
1177
+
1178
+ .${prefix}-cell-avatar-text {
1179
+ display: flex;
1180
+ flex-direction: column;
1181
+ line-height: 1.4;
1182
+ }
1183
+
1184
+ .${prefix}-cell-avatar-text span:first-child {
1185
+ font-weight: 500;
1186
+ }
1187
+
1188
+ .${prefix}-cell-avatar-text span:last-child:not(:first-child) {
1189
+ font-size: 12px;
1190
+ color: var(--${prefix}-muted);
1191
+ }`;
1192
+ }
1193
+
1194
+ /**
1195
+ * Accessibility utility styles
1196
+ */
1197
+ function generateAccessibilityStyles(prefix: string): string {
1198
+ return `/* Accessibility Utilities */
1199
+ .sr-only {
1200
+ position: absolute;
1201
+ width: 1px;
1202
+ height: 1px;
1203
+ padding: 0;
1204
+ margin: -1px;
1205
+ overflow: hidden;
1206
+ clip: rect(0, 0, 0, 0);
1207
+ white-space: nowrap;
1208
+ border: 0;
1209
+ }
1210
+
1211
+ /* Focus visible for keyboard navigation */
1212
+ .${prefix}-button:focus-visible,
1213
+ .${prefix}-input:focus-visible,
1214
+ .${prefix}-select:focus-visible,
1215
+ .${prefix}-textarea:focus-visible,
1216
+ .${prefix}-nav-link:focus-visible,
1217
+ .${prefix}-tab:focus-visible {
1218
+ outline: 2px solid var(--${prefix}-fg);
1219
+ outline-offset: 2px;
1220
+ }
1221
+
1222
+ /* Reduced motion support */
1223
+ @media (prefers-reduced-motion: reduce) {
1224
+ *,
1225
+ *::before,
1226
+ *::after {
1227
+ animation-duration: 0.01ms !important;
1228
+ animation-iteration-count: 1 !important;
1229
+ transition-duration: 0.01ms !important;
1230
+ }
1231
+ }`;
1232
+ }