@rokkit/ui 1.0.0-next.124 → 1.0.0-next.127

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 (146) hide show
  1. package/README.md +198 -101
  2. package/package.json +52 -34
  3. package/src/components/BreadCrumbs.svelte +82 -0
  4. package/src/components/Button.svelte +87 -0
  5. package/src/components/ButtonGroup.svelte +18 -0
  6. package/src/components/Card.svelte +61 -0
  7. package/src/components/Carousel.svelte +169 -0
  8. package/src/components/Code.svelte +185 -0
  9. package/src/components/Connector.svelte +46 -0
  10. package/src/components/FloatingAction.svelte +331 -0
  11. package/src/components/FloatingNavigation.svelte +228 -0
  12. package/src/components/ItemContent.svelte +24 -0
  13. package/src/components/List.svelte +476 -0
  14. package/src/components/Menu.svelte +421 -0
  15. package/src/components/MultiSelect.svelte +521 -0
  16. package/src/components/PaletteManager.svelte +354 -0
  17. package/src/components/Pill.svelte +78 -0
  18. package/src/components/ProgressBar.svelte +31 -0
  19. package/src/components/Range.svelte +325 -0
  20. package/src/components/Rating.svelte +91 -0
  21. package/src/components/Reveal.svelte +58 -0
  22. package/src/components/SearchFilter.svelte +80 -0
  23. package/src/components/Select.svelte +585 -0
  24. package/src/{Shine.svelte → components/Shine.svelte} +29 -21
  25. package/src/components/Stepper.svelte +169 -0
  26. package/src/components/Switch.svelte +75 -0
  27. package/src/components/Table.svelte +243 -0
  28. package/src/components/Tabs.svelte +268 -0
  29. package/src/components/Tilt.svelte +68 -0
  30. package/src/components/Timeline.svelte +61 -0
  31. package/src/components/Toggle.svelte +157 -0
  32. package/src/components/Toolbar.svelte +307 -0
  33. package/src/components/ToolbarGroup.svelte +17 -0
  34. package/src/components/Tree.svelte +613 -0
  35. package/src/components/index.ts +33 -0
  36. package/src/index.ts +41 -0
  37. package/src/types/button.ts +83 -0
  38. package/src/types/code.ts +46 -0
  39. package/src/types/floating-action.ts +118 -0
  40. package/src/types/floating-navigation.ts +68 -0
  41. package/src/types/index.ts +53 -0
  42. package/src/types/item-proxy.ts +358 -0
  43. package/src/types/list.ts +196 -0
  44. package/src/types/menu.ts +195 -0
  45. package/src/types/palette.ts +143 -0
  46. package/src/types/range.ts +51 -0
  47. package/src/types/search-filter.ts +67 -0
  48. package/src/types/select.ts +206 -0
  49. package/src/types/switch.ts +64 -0
  50. package/src/types/table.ts +210 -0
  51. package/src/types/tabs.ts +124 -0
  52. package/src/types/timeline.ts +51 -0
  53. package/src/types/toggle.ts +109 -0
  54. package/src/types/toolbar.ts +164 -0
  55. package/src/types/tree.ts +259 -0
  56. package/src/utils/palette.ts +582 -0
  57. package/src/utils/shiki.ts +122 -0
  58. package/dist/constants.d.ts +0 -2
  59. package/dist/index.d.ts +0 -41
  60. package/dist/lib/fields.d.ts +0 -16
  61. package/dist/lib/form.d.ts +0 -95
  62. package/dist/lib/index.d.ts +0 -6
  63. package/dist/lib/layout.d.ts +0 -7
  64. package/dist/lib/nested.d.ts +0 -48
  65. package/dist/lib/schema.d.ts +0 -7
  66. package/dist/lib/select.d.ts +0 -8
  67. package/dist/lib/tree.d.ts +0 -9
  68. package/dist/tree/List.spec.svelte.d.ts +0 -1
  69. package/dist/tree/Node.spec.svelte.d.ts +0 -1
  70. package/dist/tree/Root.spec.svelte.d.ts +0 -1
  71. package/dist/types.d.ts +0 -5
  72. package/dist/wrappers/index.d.ts +0 -3
  73. package/src/Accordion.svelte +0 -118
  74. package/src/BreadCrumbs.svelte +0 -32
  75. package/src/Button.svelte +0 -57
  76. package/src/Calendar.svelte +0 -93
  77. package/src/Card.svelte +0 -45
  78. package/src/Carousel.svelte +0 -49
  79. package/src/CheckBox.svelte +0 -56
  80. package/src/Connector.svelte +0 -40
  81. package/src/DropDown.svelte +0 -68
  82. package/src/DropSearch.svelte +0 -37
  83. package/src/Fillable.svelte +0 -19
  84. package/src/GraphPaper.svelte +0 -43
  85. package/src/Icon.svelte +0 -81
  86. package/src/Item.svelte +0 -25
  87. package/src/Link.svelte +0 -21
  88. package/src/List.svelte +0 -89
  89. package/src/ListBody.svelte +0 -43
  90. package/src/Message.svelte +0 -11
  91. package/src/MultiSelect.svelte +0 -48
  92. package/src/NestedList.svelte +0 -78
  93. package/src/NestedPaginator.svelte +0 -63
  94. package/src/Node.svelte +0 -76
  95. package/src/Overlay.svelte +0 -21
  96. package/src/PageNavigator.svelte +0 -94
  97. package/src/PickOne.svelte +0 -60
  98. package/src/Pill.svelte +0 -41
  99. package/src/ProgressBar.svelte +0 -21
  100. package/src/ProgressDots.svelte +0 -53
  101. package/src/RadioGroup.svelte +0 -52
  102. package/src/Range.svelte +0 -45
  103. package/src/RangeMinMax.svelte +0 -124
  104. package/src/RangeSlider.svelte +0 -79
  105. package/src/RangeTick.svelte +0 -28
  106. package/src/Rating.svelte +0 -95
  107. package/src/ResponsiveGrid.svelte +0 -88
  108. package/src/Scrollable.svelte +0 -7
  109. package/src/Select.svelte +0 -114
  110. package/src/Separator.svelte +0 -1
  111. package/src/Slider.svelte +0 -14
  112. package/src/SlidingColumns.svelte +0 -50
  113. package/src/Stage.svelte +0 -41
  114. package/src/Stepper.svelte +0 -66
  115. package/src/Summary.svelte +0 -22
  116. package/src/Switch.svelte +0 -106
  117. package/src/TableCell.svelte +0 -51
  118. package/src/TableHeaderCell.svelte +0 -54
  119. package/src/Tabs.svelte +0 -176
  120. package/src/Tilt.svelte +0 -66
  121. package/src/Toggle.svelte +0 -58
  122. package/src/ToggleThemeMode.svelte +0 -23
  123. package/src/Tree.svelte +0 -80
  124. package/src/TreeTable.svelte +0 -171
  125. package/src/ValidationReport.svelte +0 -23
  126. package/src/constants.js +0 -4
  127. package/src/index.js +0 -48
  128. package/src/lib/fields.js +0 -118
  129. package/src/lib/form.js +0 -72
  130. package/src/lib/index.js +0 -13
  131. package/src/lib/layout.js +0 -63
  132. package/src/lib/nested.js +0 -192
  133. package/src/lib/schema.js +0 -32
  134. package/src/lib/select.js +0 -38
  135. package/src/lib/tree.js +0 -22
  136. package/src/tree/List.spec.svelte.js +0 -84
  137. package/src/tree/List.svelte +0 -78
  138. package/src/tree/Node.spec.svelte.js +0 -104
  139. package/src/tree/Node.svelte +0 -80
  140. package/src/tree/Root.spec.svelte.js +0 -63
  141. package/src/tree/Root.svelte +0 -81
  142. package/src/types.js +0 -9
  143. package/src/wrappers/Category.svelte +0 -27
  144. package/src/wrappers/Section.svelte +0 -16
  145. package/src/wrappers/Wrapper.svelte +0 -12
  146. package/src/wrappers/index.js +0 -3
@@ -0,0 +1,582 @@
1
+ /**
2
+ * Palette Utilities
3
+ *
4
+ * Functions for color manipulation, shade generation, and runtime palette application.
5
+ */
6
+
7
+ // =============================================================================
8
+ // Types
9
+ // =============================================================================
10
+
11
+ export interface RGB {
12
+ r: number
13
+ g: number
14
+ b: number
15
+ }
16
+
17
+ export interface HSL {
18
+ h: number
19
+ s: number
20
+ l: number
21
+ }
22
+
23
+ export type ShadeKey = '50' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | '950'
24
+
25
+ export type Shades = Record<ShadeKey, string>
26
+
27
+ export type ColorRole =
28
+ | 'primary'
29
+ | 'secondary'
30
+ | 'accent'
31
+ | 'surface'
32
+ | 'success'
33
+ | 'warning'
34
+ | 'danger'
35
+ | 'info'
36
+
37
+ /**
38
+ * Mapping of color roles to Tailwind color names or hex values
39
+ */
40
+ export type ColorMapping = Partial<Record<ColorRole, string>>
41
+
42
+ // =============================================================================
43
+ // Color Conversion Utilities
44
+ // =============================================================================
45
+
46
+ /**
47
+ * Convert hex color to RGB
48
+ */
49
+ export function hexToRgb(hex: string): RGB {
50
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
51
+ if (!result) {
52
+ throw new Error(`Invalid hex color: ${hex}`)
53
+ }
54
+ return {
55
+ r: parseInt(result[1], 16),
56
+ g: parseInt(result[2], 16),
57
+ b: parseInt(result[3], 16)
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Convert RGB to hex color
63
+ */
64
+ export function rgbToHex(rgb: RGB): string {
65
+ const toHex = (n: number) => {
66
+ const hex = Math.round(Math.max(0, Math.min(255, n))).toString(16)
67
+ return hex.length === 1 ? `0${ hex}` : hex
68
+ }
69
+ return `#${toHex(rgb.r)}${toHex(rgb.g)}${toHex(rgb.b)}`
70
+ }
71
+
72
+ /**
73
+ * Convert RGB to HSL
74
+ */
75
+ export function rgbToHsl(rgb: RGB): HSL {
76
+ const r = rgb.r / 255
77
+ const g = rgb.g / 255
78
+ const b = rgb.b / 255
79
+
80
+ const max = Math.max(r, g, b)
81
+ const min = Math.min(r, g, b)
82
+ const l = (max + min) / 2
83
+
84
+ if (max === min) {
85
+ return { h: 0, s: 0, l: l * 100 }
86
+ }
87
+
88
+ const d = max - min
89
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
90
+
91
+ let h = 0
92
+ switch (max) {
93
+ case r:
94
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6
95
+ break
96
+ case g:
97
+ h = ((b - r) / d + 2) / 6
98
+ break
99
+ case b:
100
+ h = ((r - g) / d + 4) / 6
101
+ break
102
+ }
103
+
104
+ return { h: h * 360, s: s * 100, l: l * 100 }
105
+ }
106
+
107
+ /**
108
+ * Convert HSL to RGB
109
+ */
110
+ export function hslToRgb(hsl: HSL): RGB {
111
+ const h = hsl.h / 360
112
+ const s = hsl.s / 100
113
+ const l = hsl.l / 100
114
+
115
+ if (s === 0) {
116
+ const val = Math.round(l * 255)
117
+ return { r: val, g: val, b: val }
118
+ }
119
+
120
+ const hue2rgb = (p: number, q: number, t: number) => {
121
+ if (t < 0) t += 1
122
+ if (t > 1) t -= 1
123
+ if (t < 1 / 6) return p + (q - p) * 6 * t
124
+ if (t < 1 / 2) return q
125
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
126
+ return p
127
+ }
128
+
129
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s
130
+ const p = 2 * l - q
131
+
132
+ return {
133
+ r: Math.round(hue2rgb(p, q, h + 1 / 3) * 255),
134
+ g: Math.round(hue2rgb(p, q, h) * 255),
135
+ b: Math.round(hue2rgb(p, q, h - 1 / 3) * 255)
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Convert hex to HSL
141
+ */
142
+ export function hexToHsl(hex: string): HSL {
143
+ return rgbToHsl(hexToRgb(hex))
144
+ }
145
+
146
+ /**
147
+ * Convert HSL to hex
148
+ */
149
+ export function hslToHex(hsl: HSL): string {
150
+ return rgbToHex(hslToRgb(hsl))
151
+ }
152
+
153
+ // =============================================================================
154
+ // Shade Generation
155
+ // =============================================================================
156
+
157
+ /**
158
+ * Generate Tailwind-like shades from a base hex color
159
+ * The input color is used as the 500 shade
160
+ */
161
+ export function generateShades(hex: string): Shades {
162
+ const hsl = hexToHsl(hex)
163
+
164
+ // Shade configuration: [saturation multiplier, target lightness]
165
+ // Lighter shades have higher lightness, lower saturation
166
+ // Darker shades have lower lightness, slightly higher saturation
167
+ const shadeConfig: Record<ShadeKey, [number, number]> = {
168
+ '50': [0.9, 97],
169
+ '100': [0.92, 94],
170
+ '200': [0.94, 86],
171
+ '300': [0.96, 75],
172
+ '400': [0.98, 60],
173
+ '500': [1.0, hsl.l], // Keep original lightness
174
+ '600': [1.02, Math.max(hsl.l * 0.82, 25)],
175
+ '700': [1.04, Math.max(hsl.l * 0.65, 20)],
176
+ '800': [1.06, Math.max(hsl.l * 0.50, 15)],
177
+ '900': [1.08, Math.max(hsl.l * 0.35, 12)],
178
+ '950': [1.12, Math.max(hsl.l * 0.22, 8)]
179
+ }
180
+
181
+ const shades: Partial<Shades> = {}
182
+
183
+ for (const [shade, [satMult, lightness]] of Object.entries(shadeConfig)) {
184
+ const newHsl: HSL = {
185
+ h: hsl.h,
186
+ s: Math.min(100, hsl.s * satMult),
187
+ l: lightness
188
+ }
189
+ shades[shade as ShadeKey] = hslToHex(newHsl)
190
+ }
191
+
192
+ return shades as Shades
193
+ }
194
+
195
+ /**
196
+ * Check if a string is a valid hex color
197
+ */
198
+ export function isHexColor(value: string): boolean {
199
+ return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(value)
200
+ }
201
+
202
+ // =============================================================================
203
+ // Tailwind Colors (Built-in Presets)
204
+ // =============================================================================
205
+
206
+ export const tailwindColors: Record<string, Shades> = {
207
+ slate: {
208
+ '50': '#f8fafc',
209
+ '100': '#f1f5f9',
210
+ '200': '#e2e8f0',
211
+ '300': '#cbd5e1',
212
+ '400': '#94a3b8',
213
+ '500': '#64748b',
214
+ '600': '#475569',
215
+ '700': '#334155',
216
+ '800': '#1e293b',
217
+ '900': '#0f172a',
218
+ '950': '#020617'
219
+ },
220
+ gray: {
221
+ '50': '#f9fafb',
222
+ '100': '#f3f4f6',
223
+ '200': '#e5e7eb',
224
+ '300': '#d1d5db',
225
+ '400': '#9ca3af',
226
+ '500': '#6b7280',
227
+ '600': '#4b5563',
228
+ '700': '#374151',
229
+ '800': '#1f2937',
230
+ '900': '#111827',
231
+ '950': '#030712'
232
+ },
233
+ zinc: {
234
+ '50': '#fafafa',
235
+ '100': '#f4f4f5',
236
+ '200': '#e4e4e7',
237
+ '300': '#d4d4d8',
238
+ '400': '#a1a1aa',
239
+ '500': '#71717a',
240
+ '600': '#52525b',
241
+ '700': '#3f3f46',
242
+ '800': '#27272a',
243
+ '900': '#18181b',
244
+ '950': '#09090b'
245
+ },
246
+ neutral: {
247
+ '50': '#fafafa',
248
+ '100': '#f5f5f5',
249
+ '200': '#e5e5e5',
250
+ '300': '#d4d4d4',
251
+ '400': '#a3a3a3',
252
+ '500': '#737373',
253
+ '600': '#525252',
254
+ '700': '#404040',
255
+ '800': '#262626',
256
+ '900': '#171717',
257
+ '950': '#0a0a0a'
258
+ },
259
+ stone: {
260
+ '50': '#fafaf9',
261
+ '100': '#f5f5f4',
262
+ '200': '#e7e5e4',
263
+ '300': '#d6d3d1',
264
+ '400': '#a8a29e',
265
+ '500': '#78716c',
266
+ '600': '#57534e',
267
+ '700': '#44403c',
268
+ '800': '#292524',
269
+ '900': '#1c1917',
270
+ '950': '#0c0a09'
271
+ },
272
+ red: {
273
+ '50': '#fef2f2',
274
+ '100': '#fee2e2',
275
+ '200': '#fecaca',
276
+ '300': '#fca5a5',
277
+ '400': '#f87171',
278
+ '500': '#ef4444',
279
+ '600': '#dc2626',
280
+ '700': '#b91c1c',
281
+ '800': '#991b1b',
282
+ '900': '#7f1d1d',
283
+ '950': '#450a0a'
284
+ },
285
+ orange: {
286
+ '50': '#fff7ed',
287
+ '100': '#ffedd5',
288
+ '200': '#fed7aa',
289
+ '300': '#fdba74',
290
+ '400': '#fb923c',
291
+ '500': '#f97316',
292
+ '600': '#ea580c',
293
+ '700': '#c2410c',
294
+ '800': '#9a3412',
295
+ '900': '#7c2d12',
296
+ '950': '#431407'
297
+ },
298
+ amber: {
299
+ '50': '#fffbeb',
300
+ '100': '#fef3c7',
301
+ '200': '#fde68a',
302
+ '300': '#fcd34d',
303
+ '400': '#fbbf24',
304
+ '500': '#f59e0b',
305
+ '600': '#d97706',
306
+ '700': '#b45309',
307
+ '800': '#92400e',
308
+ '900': '#78350f',
309
+ '950': '#451a03'
310
+ },
311
+ yellow: {
312
+ '50': '#fefce8',
313
+ '100': '#fef9c3',
314
+ '200': '#fef08a',
315
+ '300': '#fde047',
316
+ '400': '#facc15',
317
+ '500': '#eab308',
318
+ '600': '#ca8a04',
319
+ '700': '#a16207',
320
+ '800': '#854d0e',
321
+ '900': '#713f12',
322
+ '950': '#422006'
323
+ },
324
+ lime: {
325
+ '50': '#f7fee7',
326
+ '100': '#ecfccb',
327
+ '200': '#d9f99d',
328
+ '300': '#bef264',
329
+ '400': '#a3e635',
330
+ '500': '#84cc16',
331
+ '600': '#65a30d',
332
+ '700': '#4d7c0f',
333
+ '800': '#3f6212',
334
+ '900': '#365314',
335
+ '950': '#1a2e05'
336
+ },
337
+ green: {
338
+ '50': '#f0fdf4',
339
+ '100': '#dcfce7',
340
+ '200': '#bbf7d0',
341
+ '300': '#86efac',
342
+ '400': '#4ade80',
343
+ '500': '#22c55e',
344
+ '600': '#16a34a',
345
+ '700': '#15803d',
346
+ '800': '#166534',
347
+ '900': '#14532d',
348
+ '950': '#052e16'
349
+ },
350
+ emerald: {
351
+ '50': '#ecfdf5',
352
+ '100': '#d1fae5',
353
+ '200': '#a7f3d0',
354
+ '300': '#6ee7b7',
355
+ '400': '#34d399',
356
+ '500': '#10b981',
357
+ '600': '#059669',
358
+ '700': '#047857',
359
+ '800': '#065f46',
360
+ '900': '#064e3b',
361
+ '950': '#022c22'
362
+ },
363
+ teal: {
364
+ '50': '#f0fdfa',
365
+ '100': '#ccfbf1',
366
+ '200': '#99f6e4',
367
+ '300': '#5eead4',
368
+ '400': '#2dd4bf',
369
+ '500': '#14b8a6',
370
+ '600': '#0d9488',
371
+ '700': '#0f766e',
372
+ '800': '#115e59',
373
+ '900': '#134e4a',
374
+ '950': '#042f2e'
375
+ },
376
+ cyan: {
377
+ '50': '#ecfeff',
378
+ '100': '#cffafe',
379
+ '200': '#a5f3fc',
380
+ '300': '#67e8f9',
381
+ '400': '#22d3ee',
382
+ '500': '#06b6d4',
383
+ '600': '#0891b2',
384
+ '700': '#0e7490',
385
+ '800': '#155e75',
386
+ '900': '#164e63',
387
+ '950': '#083344'
388
+ },
389
+ sky: {
390
+ '50': '#f0f9ff',
391
+ '100': '#e0f2fe',
392
+ '200': '#bae6fd',
393
+ '300': '#7dd3fc',
394
+ '400': '#38bdf8',
395
+ '500': '#0ea5e9',
396
+ '600': '#0284c7',
397
+ '700': '#0369a1',
398
+ '800': '#075985',
399
+ '900': '#0c4a6e',
400
+ '950': '#082f49'
401
+ },
402
+ blue: {
403
+ '50': '#eff6ff',
404
+ '100': '#dbeafe',
405
+ '200': '#bfdbfe',
406
+ '300': '#93c5fd',
407
+ '400': '#60a5fa',
408
+ '500': '#3b82f6',
409
+ '600': '#2563eb',
410
+ '700': '#1d4ed8',
411
+ '800': '#1e40af',
412
+ '900': '#1e3a8a',
413
+ '950': '#172554'
414
+ },
415
+ indigo: {
416
+ '50': '#eef2ff',
417
+ '100': '#e0e7ff',
418
+ '200': '#c7d2fe',
419
+ '300': '#a5b4fc',
420
+ '400': '#818cf8',
421
+ '500': '#6366f1',
422
+ '600': '#4f46e5',
423
+ '700': '#4338ca',
424
+ '800': '#3730a3',
425
+ '900': '#312e81',
426
+ '950': '#1e1b4b'
427
+ },
428
+ violet: {
429
+ '50': '#f5f3ff',
430
+ '100': '#ede9fe',
431
+ '200': '#ddd6fe',
432
+ '300': '#c4b5fd',
433
+ '400': '#a78bfa',
434
+ '500': '#8b5cf6',
435
+ '600': '#7c3aed',
436
+ '700': '#6d28d9',
437
+ '800': '#5b21b6',
438
+ '900': '#4c1d95',
439
+ '950': '#2e1065'
440
+ },
441
+ purple: {
442
+ '50': '#faf5ff',
443
+ '100': '#f3e8ff',
444
+ '200': '#e9d5ff',
445
+ '300': '#d8b4fe',
446
+ '400': '#c084fc',
447
+ '500': '#a855f7',
448
+ '600': '#9333ea',
449
+ '700': '#7e22ce',
450
+ '800': '#6b21a8',
451
+ '900': '#581c87',
452
+ '950': '#3b0764'
453
+ },
454
+ fuchsia: {
455
+ '50': '#fdf4ff',
456
+ '100': '#fae8ff',
457
+ '200': '#f5d0fe',
458
+ '300': '#f0abfc',
459
+ '400': '#e879f9',
460
+ '500': '#d946ef',
461
+ '600': '#c026d3',
462
+ '700': '#a21caf',
463
+ '800': '#86198f',
464
+ '900': '#701a75',
465
+ '950': '#4a044e'
466
+ },
467
+ pink: {
468
+ '50': '#fdf2f8',
469
+ '100': '#fce7f3',
470
+ '200': '#fbcfe8',
471
+ '300': '#f9a8d4',
472
+ '400': '#f472b6',
473
+ '500': '#ec4899',
474
+ '600': '#db2777',
475
+ '700': '#be185d',
476
+ '800': '#9d174d',
477
+ '900': '#831843',
478
+ '950': '#500724'
479
+ },
480
+ rose: {
481
+ '50': '#fff1f2',
482
+ '100': '#ffe4e6',
483
+ '200': '#fecdd3',
484
+ '300': '#fda4af',
485
+ '400': '#fb7185',
486
+ '500': '#f43f5e',
487
+ '600': '#e11d48',
488
+ '700': '#be123c',
489
+ '800': '#9f1239',
490
+ '900': '#881337',
491
+ '950': '#4c0519'
492
+ }
493
+ }
494
+
495
+ /**
496
+ * Get shades for a color (either Tailwind preset or custom hex)
497
+ */
498
+ export function getShades(color: string): Shades {
499
+ if (isHexColor(color)) {
500
+ return generateShades(color)
501
+ }
502
+ const preset = tailwindColors[color.toLowerCase()]
503
+ if (preset) {
504
+ return preset
505
+ }
506
+ throw new Error(`Unknown color: ${color}. Must be a hex color or Tailwind color name.`)
507
+ }
508
+
509
+ // =============================================================================
510
+ // Runtime Palette Application
511
+ // =============================================================================
512
+
513
+ /**
514
+ * Apply a color palette to the document root
515
+ * Sets CSS variables for each color role and shade
516
+ */
517
+ export function applyPalette(
518
+ mapping: Partial<Record<ColorRole, string>>,
519
+ element: HTMLElement = document.documentElement
520
+ ): void {
521
+ for (const [role, color] of Object.entries(mapping)) {
522
+ if (!color) continue
523
+
524
+ const shades = getShades(color)
525
+
526
+ for (const [shade, hex] of Object.entries(shades)) {
527
+ const rgb = hexToRgb(hex)
528
+ // Store as RGB values (comma-separated) for rgba() compatibility
529
+ element.style.setProperty(`--color-${role}-${shade}`, `${rgb.r},${rgb.g},${rgb.b}`)
530
+ }
531
+
532
+ // Also set the default (500) as the base color variable
533
+ const baseRgb = hexToRgb(shades['500'])
534
+ element.style.setProperty(`--color-${role}`, `${baseRgb.r},${baseRgb.g},${baseRgb.b}`)
535
+ }
536
+ }
537
+
538
+ /**
539
+ * Remove custom palette CSS variables (reset to theme defaults)
540
+ */
541
+ export function resetPalette(
542
+ roles: ColorRole[] = ['primary', 'secondary', 'accent', 'surface', 'success', 'warning', 'danger', 'info'],
543
+ element: HTMLElement = document.documentElement
544
+ ): void {
545
+ const shadeKeys: ShadeKey[] = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950']
546
+
547
+ for (const role of roles) {
548
+ element.style.removeProperty(`--color-${role}`)
549
+ for (const shade of shadeKeys) {
550
+ element.style.removeProperty(`--color-${role}-${shade}`)
551
+ }
552
+ }
553
+ }
554
+
555
+ /**
556
+ * Save palette to localStorage
557
+ */
558
+ export function savePalette(key: string, mapping: Partial<Record<ColorRole, string>>): void {
559
+ localStorage.setItem(key, JSON.stringify(mapping))
560
+ }
561
+
562
+ /**
563
+ * Load palette from localStorage
564
+ */
565
+ export function loadPalette(key: string): Partial<Record<ColorRole, string>> | null {
566
+ const stored = localStorage.getItem(key)
567
+ if (stored) {
568
+ try {
569
+ return JSON.parse(stored)
570
+ } catch {
571
+ return null
572
+ }
573
+ }
574
+ return null
575
+ }
576
+
577
+ /**
578
+ * Get list of available Tailwind color names
579
+ */
580
+ export function getTailwindColorNames(): string[] {
581
+ return Object.keys(tailwindColors)
582
+ }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Shiki syntax highlighting utility
3
+ */
4
+
5
+ import { createHighlighter, type Highlighter, type BundledLanguage, type BundledTheme } from 'shiki'
6
+
7
+ let highlighter: Highlighter | null = null
8
+ let isInitializing = false
9
+ let initPromise: Promise<Highlighter> | null = null
10
+
11
+ // Supported languages for the application
12
+ const SUPPORTED_LANGUAGES: BundledLanguage[] = [
13
+ 'svelte',
14
+ 'javascript',
15
+ 'typescript',
16
+ 'css',
17
+ 'html',
18
+ 'json',
19
+ 'bash',
20
+ 'shell',
21
+ 'markdown',
22
+ 'yaml',
23
+ 'sql'
24
+ ]
25
+
26
+ // Available themes
27
+ const THEMES: BundledTheme[] = ['github-light', 'github-dark']
28
+
29
+ /**
30
+ * Initialize Shiki highlighter (singleton)
31
+ */
32
+ function initializeHighlighter(): Promise<Highlighter> {
33
+ if (highlighter) return Promise.resolve(highlighter)
34
+
35
+ if (isInitializing && initPromise) {
36
+ return initPromise
37
+ }
38
+
39
+ isInitializing = true
40
+
41
+ initPromise = createHighlighter({
42
+ themes: THEMES,
43
+ langs: SUPPORTED_LANGUAGES
44
+ })
45
+ .then((hl: Highlighter) => {
46
+ highlighter = hl
47
+ isInitializing = false
48
+ return hl
49
+ })
50
+ .catch((error: Error) => {
51
+ isInitializing = false
52
+ initPromise = null
53
+ throw error
54
+ })
55
+
56
+ return initPromise
57
+ }
58
+
59
+ export interface HighlightOptions {
60
+ /** Language for syntax highlighting */
61
+ lang?: BundledLanguage | string
62
+ /** Theme to use (defaults based on user preference) */
63
+ theme?: BundledTheme | 'light' | 'dark'
64
+ }
65
+
66
+ /**
67
+ * Highlight code using Shiki
68
+ *
69
+ * @param code - The code to highlight
70
+ * @param options - Highlighting options
71
+ * @returns The highlighted code as HTML
72
+ */
73
+ export async function highlightCode(code: string, options: HighlightOptions = {}): Promise<string> {
74
+ if (!code || typeof code !== 'string') {
75
+ throw new Error('Invalid code provided for highlighting')
76
+ }
77
+
78
+ const hl = await initializeHighlighter()
79
+ const lang = (options.lang || 'text') as BundledLanguage
80
+ let theme: BundledTheme = 'github-dark'
81
+
82
+ if (options.theme === 'light') {
83
+ theme = 'github-light'
84
+ } else if (options.theme === 'dark') {
85
+ theme = 'github-dark'
86
+ } else if (options.theme) {
87
+ theme = options.theme
88
+ }
89
+
90
+ // Check if language is supported, fallback to text
91
+ const loadedLangs = hl.getLoadedLanguages()
92
+ const effectiveLang = loadedLangs.includes(lang) ? lang : 'text'
93
+
94
+ return (
95
+ hl
96
+ .codeToHtml(code, {
97
+ lang: effectiveLang,
98
+ theme
99
+ })
100
+ // Remove inline styles from pre tag to allow CSS theming
101
+ .replace(/(<pre[^>]+) style="[^"]*"/, '$1')
102
+ )
103
+ }
104
+
105
+ /**
106
+ * Preload the syntax highlighter for faster initial rendering
107
+ * Errors are silently ignored since preloading is optional
108
+ */
109
+ export async function preloadHighlighter(): Promise<void> {
110
+ try {
111
+ await initializeHighlighter()
112
+ } catch {
113
+ // Preload failures are non-critical - highlighting will still work on demand
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Get list of supported languages
119
+ */
120
+ export function getSupportedLanguages(): readonly string[] {
121
+ return SUPPORTED_LANGUAGES
122
+ }
@@ -1,2 +0,0 @@
1
- export const defaultMapping: FieldMapper;
2
- import { FieldMapper } from '@rokkit/core';