sonance-brand-mcp 1.3.15 → 1.3.17

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.
@@ -0,0 +1,616 @@
1
+
2
+ import { Box, Image as ImageIcon, Type, Scan } from "lucide-react";
3
+ import { TabDefinition, ConfigSection } from "./types";
4
+ import { componentSnippets } from "../../lib/brand-system";
5
+
6
+ export const tabs: TabDefinition[] = [
7
+ { id: "components", label: "Components", icon: Box },
8
+ { id: "logos", label: "Logos", icon: ImageIcon },
9
+ { id: "text", label: "Text", icon: Type },
10
+ ];
11
+
12
+ // Quick action presets for common styling changes
13
+ export const QUICK_ACTIONS = [
14
+ { label: "Darker", prompt: "Make the background color darker and adjust text for contrast" },
15
+ { label: "Rounder", prompt: "Increase the border radius to make corners more rounded" },
16
+ { label: "Shadow", prompt: "Add a subtle shadow effect, and increase shadow on hover" },
17
+ { label: "Larger", prompt: "Increase padding and font size to make the component larger" },
18
+ { label: "Bolder", prompt: "Make the text bolder and more prominent" },
19
+ ];
20
+
21
+ // Style injection ID for cleanup
22
+ export const SONANCE_PREVIEW_STYLE_ID = "sonance-devtools-preview-styles";
23
+
24
+ // Component categories for scope behavior
25
+ export const UNIVERSAL_STYLE_CATEGORIES = ["buttons", "forms", "feedback", "typography"];
26
+ export const TARGETABLE_CATEGORIES = ["layout", "navigation", "data display", "overlays"];
27
+
28
+ /**
29
+ * Tailwind spacing scale helper
30
+ */
31
+ const spacingValue = (v: string): string => {
32
+ const scale: Record<string, string> = {
33
+ "0": "0", "px": "1px", "0.5": "0.125rem", "1": "0.25rem", "1.5": "0.375rem",
34
+ "2": "0.5rem", "2.5": "0.625rem", "3": "0.75rem", "3.5": "0.875rem",
35
+ "4": "1rem", "5": "1.25rem", "6": "1.5rem", "7": "1.75rem",
36
+ "8": "2rem", "9": "2.25rem", "10": "2.5rem", "11": "2.75rem",
37
+ "12": "3rem", "14": "3.5rem", "16": "4rem", "20": "5rem",
38
+ "24": "6rem", "28": "7rem", "32": "8rem", "36": "9rem",
39
+ "40": "10rem", "44": "11rem", "48": "12rem", "52": "13rem",
40
+ "56": "14rem", "60": "15rem", "64": "16rem", "72": "18rem",
41
+ "80": "20rem", "96": "24rem",
42
+ };
43
+ return scale[v] || (v.includes("[") ? v.replace(/\[|\]/g, "") : `${parseFloat(v) * 0.25}rem`);
44
+ };
45
+
46
+ /**
47
+ * Tailwind size value helper (for width/height)
48
+ */
49
+ const sizeValue = (v: string): string => {
50
+ const sizes: Record<string, string> = {
51
+ "auto": "auto", "full": "100%", "screen": "100vw", "min": "min-content",
52
+ "max": "max-content", "fit": "fit-content", "1/2": "50%", "1/3": "33.333333%",
53
+ "2/3": "66.666667%", "1/4": "25%", "2/4": "50%", "3/4": "75%",
54
+ "1/5": "20%", "2/5": "40%", "3/5": "60%", "4/5": "80%",
55
+ "1/6": "16.666667%", "5/6": "83.333333%",
56
+ };
57
+ if (sizes[v]) return sizes[v];
58
+ return spacingValue(v);
59
+ };
60
+
61
+ /**
62
+ * Comprehensive color map including all brand colors
63
+ */
64
+ const colorMap: Record<string, string> = {
65
+ // Semantic colors
66
+ "primary": "var(--primary)",
67
+ "primary-foreground": "var(--primary-foreground)",
68
+ "secondary": "var(--secondary)",
69
+ "secondary-foreground": "var(--secondary-foreground)",
70
+ "foreground": "var(--foreground)",
71
+ "foreground-secondary": "var(--foreground-secondary)",
72
+ "foreground-muted": "var(--foreground-muted)",
73
+ "muted": "var(--muted)",
74
+ "muted-foreground": "var(--muted-foreground)",
75
+ "accent": "var(--accent)",
76
+ "accent-foreground": "var(--accent-foreground)",
77
+ "destructive": "var(--destructive)",
78
+ "destructive-foreground": "var(--destructive-foreground)",
79
+ "card": "var(--card)",
80
+ "card-foreground": "var(--card-foreground)",
81
+ "popover": "var(--popover)",
82
+ "popover-foreground": "var(--popover-foreground)",
83
+ "background": "var(--background)",
84
+ "border": "var(--border)",
85
+ "input": "var(--input)",
86
+ "ring": "var(--ring)",
87
+ // Standard colors
88
+ "transparent": "transparent",
89
+ "current": "currentColor",
90
+ "white": "#ffffff",
91
+ "black": "#000000",
92
+ // Sonance brand
93
+ "sonance-charcoal": "#333F48",
94
+ "sonance-blue": "#00A3E1",
95
+ "sonance-light-gray": "#D9D9D6",
96
+ // IPORT brand
97
+ "iport-orange": "#FC4C02",
98
+ "iport-black": "#0E1114",
99
+ "iport-dark": "#0F161D",
100
+ "iport-dark-gray": "#1C1E20",
101
+ "iport-gray": "#3A3D3F",
102
+ "iport-light-gray": "#CED6DB",
103
+ // Blaze brand
104
+ "blaze-blue": "#00A3E1",
105
+ "blaze-red": "#C02B0A",
106
+ "blaze-dark-gray": "#28282B",
107
+ "blaze-gray": "#313131",
108
+ // Gray scale
109
+ "gray-50": "#f9fafb", "gray-100": "#f3f4f6", "gray-200": "#e5e7eb",
110
+ "gray-300": "#d1d5db", "gray-400": "#9ca3af", "gray-500": "#6b7280",
111
+ "gray-600": "#4b5563", "gray-700": "#374151", "gray-800": "#1f2937", "gray-900": "#111827",
112
+ // Slate
113
+ "slate-50": "#f8fafc", "slate-100": "#f1f5f9", "slate-200": "#e2e8f0",
114
+ "slate-300": "#cbd5e1", "slate-400": "#94a3b8", "slate-500": "#64748b",
115
+ "slate-600": "#475569", "slate-700": "#334155", "slate-800": "#1e293b", "slate-900": "#0f172a",
116
+ // Zinc
117
+ "zinc-50": "#fafafa", "zinc-100": "#f4f4f5", "zinc-200": "#e4e4e7",
118
+ "zinc-300": "#d4d4d8", "zinc-400": "#a1a1aa", "zinc-500": "#71717a",
119
+ "zinc-600": "#52525b", "zinc-700": "#3f3f46", "zinc-800": "#27272a", "zinc-900": "#18181b",
120
+ // Red
121
+ "red-50": "#fef2f2", "red-100": "#fee2e2", "red-200": "#fecaca",
122
+ "red-300": "#fca5a5", "red-400": "#f87171", "red-500": "#ef4444",
123
+ "red-600": "#dc2626", "red-700": "#b91c1c", "red-800": "#991b1b", "red-900": "#7f1d1d",
124
+ // Orange
125
+ "orange-50": "#fff7ed", "orange-100": "#ffedd5", "orange-200": "#fed7aa",
126
+ "orange-300": "#fdba74", "orange-400": "#fb923c", "orange-500": "#f97316",
127
+ "orange-600": "#ea580c", "orange-700": "#c2410c", "orange-800": "#9a3412", "orange-900": "#7c2d12",
128
+ // Green
129
+ "green-50": "#f0fdf4", "green-100": "#dcfce7", "green-200": "#bbf7d0",
130
+ "green-300": "#86efac", "green-400": "#4ade80", "green-500": "#22c55e",
131
+ "green-600": "#16a34a", "green-700": "#15803d", "green-800": "#166534", "green-900": "#14532d",
132
+ // Blue
133
+ "blue-50": "#eff6ff", "blue-100": "#dbeafe", "blue-200": "#bfdbfe",
134
+ "blue-300": "#93c5fd", "blue-400": "#60a5fa", "blue-500": "#3b82f6",
135
+ "blue-600": "#2563eb", "blue-700": "#1d4ed8", "blue-800": "#1e40af", "blue-900": "#1e3a8a",
136
+ // Cyan
137
+ "cyan-50": "#ecfeff", "cyan-100": "#cffafe", "cyan-200": "#a5f3fc",
138
+ "cyan-300": "#67e8f9", "cyan-400": "#22d3ee", "cyan-500": "#06b6d4",
139
+ "cyan-600": "#0891b2", "cyan-700": "#0e7490", "cyan-800": "#155e75", "cyan-900": "#164e63",
140
+ };
141
+
142
+ /**
143
+ * Tailwind class to CSS mapping for live preview
144
+ * Maps comprehensive Tailwind patterns to actual CSS properties
145
+ */
146
+ export const TAILWIND_TO_CSS: Record<string, (value: string) => string> = {
147
+ // ═══════════════════════════════════════════════════════════════════════════
148
+ // COLORS (Background, Text, Border)
149
+ // ═══════════════════════════════════════════════════════════════════════════
150
+ "bg-": (v) => colorMap[v] ? `background-color: ${colorMap[v]}` : "",
151
+ "text-": (v) => {
152
+ // Handle text size
153
+ const sizeMap: Record<string, string> = {
154
+ "xs": "0.75rem", "sm": "0.875rem", "base": "1rem",
155
+ "lg": "1.125rem", "xl": "1.25rem", "2xl": "1.5rem",
156
+ "3xl": "1.875rem", "4xl": "2.25rem", "5xl": "3rem",
157
+ "6xl": "3.75rem", "7xl": "4.5rem", "8xl": "6rem", "9xl": "8rem",
158
+ };
159
+ if (colorMap[v]) return `color: ${colorMap[v]}`;
160
+ if (sizeMap[v]) return `font-size: ${sizeMap[v]}`;
161
+ return "";
162
+ },
163
+ "border-": (v) => {
164
+ // Handle border width first (border-0, border-2, border-4, border-8)
165
+ if (/^\d+$/.test(v)) return `border-width: ${v}px`;
166
+ // Handle colors
167
+ if (colorMap[v]) return `border-color: ${colorMap[v]}`;
168
+ return "";
169
+ },
170
+ "outline-": (v) => colorMap[v] ? `outline-color: ${colorMap[v]}` : "",
171
+ "ring-": (v) => colorMap[v] ? `--tw-ring-color: ${colorMap[v]}` : "",
172
+ "fill-": (v) => colorMap[v] ? `fill: ${colorMap[v]}` : "",
173
+ "stroke-": (v) => colorMap[v] ? `stroke: ${colorMap[v]}` : "",
174
+
175
+ // ═══════════════════════════════════════════════════════════════════════════
176
+ // BORDER RADIUS
177
+ // ═══════════════════════════════════════════════════════════════════════════
178
+ "rounded": (v) => {
179
+ const radiusMap: Record<string, string> = {
180
+ "": "0.25rem", "-none": "0", "-sm": "0.125rem",
181
+ "-md": "0.375rem", "-lg": "0.5rem", "-xl": "0.75rem",
182
+ "-2xl": "1rem", "-3xl": "1.5rem", "-full": "9999px",
183
+ };
184
+ return radiusMap[v] !== undefined ? `border-radius: ${radiusMap[v]}` : "";
185
+ },
186
+ "rounded-t": (v) => {
187
+ const radiusMap: Record<string, string> = {
188
+ "": "0.25rem", "-none": "0", "-sm": "0.125rem", "-md": "0.375rem",
189
+ "-lg": "0.5rem", "-xl": "0.75rem", "-2xl": "1rem", "-3xl": "1.5rem", "-full": "9999px",
190
+ };
191
+ const val = radiusMap[v] || "0.25rem";
192
+ return `border-top-left-radius: ${val}; border-top-right-radius: ${val}`;
193
+ },
194
+ "rounded-b": (v) => {
195
+ const radiusMap: Record<string, string> = {
196
+ "": "0.25rem", "-none": "0", "-sm": "0.125rem", "-md": "0.375rem",
197
+ "-lg": "0.5rem", "-xl": "0.75rem", "-2xl": "1rem", "-3xl": "1.5rem", "-full": "9999px",
198
+ };
199
+ const val = radiusMap[v] || "0.25rem";
200
+ return `border-bottom-left-radius: ${val}; border-bottom-right-radius: ${val}`;
201
+ },
202
+ "rounded-l": (v) => {
203
+ const radiusMap: Record<string, string> = {
204
+ "": "0.25rem", "-none": "0", "-sm": "0.125rem", "-md": "0.375rem",
205
+ "-lg": "0.5rem", "-xl": "0.75rem", "-2xl": "1rem", "-3xl": "1.5rem", "-full": "9999px",
206
+ };
207
+ const val = radiusMap[v] || "0.25rem";
208
+ return `border-top-left-radius: ${val}; border-bottom-left-radius: ${val}`;
209
+ },
210
+ "rounded-r": (v) => {
211
+ const radiusMap: Record<string, string> = {
212
+ "": "0.25rem", "-none": "0", "-sm": "0.125rem", "-md": "0.375rem",
213
+ "-lg": "0.5rem", "-xl": "0.75rem", "-2xl": "1rem", "-3xl": "1.5rem", "-full": "9999px",
214
+ };
215
+ const val = radiusMap[v] || "0.25rem";
216
+ return `border-top-right-radius: ${val}; border-bottom-right-radius: ${val}`;
217
+ },
218
+
219
+ // ═══════════════════════════════════════════════════════════════════════════
220
+ // SHADOWS
221
+ // ═══════════════════════════════════════════════════════════════════════════
222
+ "shadow": (v) => {
223
+ const shadowMap: Record<string, string> = {
224
+ "": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
225
+ "-sm": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
226
+ "-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
227
+ "-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
228
+ "-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
229
+ "-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
230
+ "-inner": "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)",
231
+ "-none": "none",
232
+ };
233
+ return shadowMap[v] !== undefined ? `box-shadow: ${shadowMap[v]}` : "";
234
+ },
235
+
236
+ // ═══════════════════════════════════════════════════════════════════════════
237
+ // SPACING (Padding & Margin)
238
+ // ═══════════════════════════════════════════════════════════════════════════
239
+ "p-": (v) => `padding: ${spacingValue(v)}`,
240
+ "px-": (v) => `padding-left: ${spacingValue(v)}; padding-right: ${spacingValue(v)}`,
241
+ "py-": (v) => `padding-top: ${spacingValue(v)}; padding-bottom: ${spacingValue(v)}`,
242
+ "pt-": (v) => `padding-top: ${spacingValue(v)}`,
243
+ "pb-": (v) => `padding-bottom: ${spacingValue(v)}`,
244
+ "pl-": (v) => `padding-left: ${spacingValue(v)}`,
245
+ "pr-": (v) => `padding-right: ${spacingValue(v)}`,
246
+ "ps-": (v) => `padding-inline-start: ${spacingValue(v)}`,
247
+ "pe-": (v) => `padding-inline-end: ${spacingValue(v)}`,
248
+ "m-": (v) => `margin: ${spacingValue(v)}`,
249
+ "mx-": (v) => `margin-left: ${spacingValue(v)}; margin-right: ${spacingValue(v)}`,
250
+ "my-": (v) => `margin-top: ${spacingValue(v)}; margin-bottom: ${spacingValue(v)}`,
251
+ "mt-": (v) => `margin-top: ${spacingValue(v)}`,
252
+ "mb-": (v) => `margin-bottom: ${spacingValue(v)}`,
253
+ "ml-": (v) => `margin-left: ${spacingValue(v)}`,
254
+ "mr-": (v) => `margin-right: ${spacingValue(v)}`,
255
+ "ms-": (v) => `margin-inline-start: ${spacingValue(v)}`,
256
+ "me-": (v) => `margin-inline-end: ${spacingValue(v)}`,
257
+ "space-x-": (v) => `--tw-space-x-reverse: 0; margin-right: calc(${spacingValue(v)} * var(--tw-space-x-reverse)); margin-left: calc(${spacingValue(v)} * calc(1 - var(--tw-space-x-reverse)))`,
258
+ "space-y-": (v) => `--tw-space-y-reverse: 0; margin-bottom: calc(${spacingValue(v)} * var(--tw-space-y-reverse)); margin-top: calc(${spacingValue(v)} * calc(1 - var(--tw-space-y-reverse)))`,
259
+ "gap-": (v) => `gap: ${spacingValue(v)}`,
260
+ "gap-x-": (v) => `column-gap: ${spacingValue(v)}`,
261
+ "gap-y-": (v) => `row-gap: ${spacingValue(v)}`,
262
+
263
+ // ═══════════════════════════════════════════════════════════════════════════
264
+ // SIZING (Width & Height)
265
+ // ═══════════════════════════════════════════════════════════════════════════
266
+ "w-": (v) => `width: ${sizeValue(v)}`,
267
+ "h-": (v) => `height: ${sizeValue(v)}`,
268
+ "min-w-": (v) => `min-width: ${sizeValue(v)}`,
269
+ "max-w-": (v) => {
270
+ const maxWidths: Record<string, string> = {
271
+ "none": "none", "xs": "20rem", "sm": "24rem", "md": "28rem",
272
+ "lg": "32rem", "xl": "36rem", "2xl": "42rem", "3xl": "48rem",
273
+ "4xl": "56rem", "5xl": "64rem", "6xl": "72rem", "7xl": "80rem",
274
+ "full": "100%", "prose": "65ch", "screen-sm": "640px",
275
+ "screen-md": "768px", "screen-lg": "1024px", "screen-xl": "1280px",
276
+ };
277
+ return `max-width: ${maxWidths[v] || sizeValue(v)}`;
278
+ },
279
+ "min-h-": (v) => `min-height: ${sizeValue(v)}`,
280
+ "max-h-": (v) => `max-height: ${sizeValue(v)}`,
281
+ "size-": (v) => `width: ${sizeValue(v)}; height: ${sizeValue(v)}`,
282
+
283
+ // ═══════════════════════════════════════════════════════════════════════════
284
+ // BORDERS
285
+ // ═══════════════════════════════════════════════════════════════════════════
286
+ "border": (v) => {
287
+ if (v === "") return "border-width: 1px";
288
+ if (v === "-0" || v === "-none") return "border-width: 0";
289
+ if (v === "-2") return "border-width: 2px";
290
+ if (v === "-4") return "border-width: 4px";
291
+ if (v === "-8") return "border-width: 8px";
292
+ return "";
293
+ },
294
+ "border-t": (v) => v === "" ? "border-top-width: 1px" : `border-top-width: ${v.replace("-", "")}px`,
295
+ "border-b": (v) => v === "" ? "border-bottom-width: 1px" : `border-bottom-width: ${v.replace("-", "")}px`,
296
+ "border-l": (v) => v === "" ? "border-left-width: 1px" : `border-left-width: ${v.replace("-", "")}px`,
297
+ "border-r": (v) => v === "" ? "border-right-width: 1px" : `border-right-width: ${v.replace("-", "")}px`,
298
+ "border-x": (v) => v === "" ? "border-left-width: 1px; border-right-width: 1px" : `border-left-width: ${v.replace("-", "")}px; border-right-width: ${v.replace("-", "")}px`,
299
+ "border-y": (v) => v === "" ? "border-top-width: 1px; border-bottom-width: 1px" : `border-top-width: ${v.replace("-", "")}px; border-bottom-width: ${v.replace("-", "")}px`,
300
+
301
+ // ═══════════════════════════════════════════════════════════════════════════
302
+ // TYPOGRAPHY
303
+ // ═══════════════════════════════════════════════════════════════════════════
304
+ "font-": (v) => {
305
+ const weightMap: Record<string, string> = {
306
+ "thin": "100", "extralight": "200", "light": "300", "normal": "400",
307
+ "medium": "500", "semibold": "600", "bold": "700", "extrabold": "800", "black": "900",
308
+ };
309
+ const familyMap: Record<string, string> = {
310
+ "sans": "ui-sans-serif, system-ui, sans-serif",
311
+ "serif": "ui-serif, Georgia, serif",
312
+ "mono": "ui-monospace, monospace",
313
+ };
314
+ if (weightMap[v]) return `font-weight: ${weightMap[v]}`;
315
+ if (familyMap[v]) return `font-family: ${familyMap[v]}`;
316
+ return "";
317
+ },
318
+ "tracking-": (v) => {
319
+ const trackingMap: Record<string, string> = {
320
+ "tighter": "-0.05em", "tight": "-0.025em", "normal": "0",
321
+ "wide": "0.025em", "wider": "0.05em", "widest": "0.1em",
322
+ };
323
+ return trackingMap[v] ? `letter-spacing: ${trackingMap[v]}` : "";
324
+ },
325
+ "leading-": (v) => {
326
+ const lineHeightMap: Record<string, string> = {
327
+ "none": "1", "tight": "1.25", "snug": "1.375", "normal": "1.5",
328
+ "relaxed": "1.625", "loose": "2",
329
+ "3": "0.75rem", "4": "1rem", "5": "1.25rem", "6": "1.5rem",
330
+ "7": "1.75rem", "8": "2rem", "9": "2.25rem", "10": "2.5rem",
331
+ };
332
+ return lineHeightMap[v] ? `line-height: ${lineHeightMap[v]}` : "";
333
+ },
334
+ "text-left": () => "text-align: left",
335
+ "text-center": () => "text-align: center",
336
+ "text-right": () => "text-align: right",
337
+ "text-justify": () => "text-align: justify",
338
+ "uppercase": () => "text-transform: uppercase",
339
+ "lowercase": () => "text-transform: lowercase",
340
+ "capitalize": () => "text-transform: capitalize",
341
+ "normal-case": () => "text-transform: none",
342
+ "italic": () => "font-style: italic",
343
+ "not-italic": () => "font-style: normal",
344
+ "underline": () => "text-decoration-line: underline",
345
+ "overline": () => "text-decoration-line: overline",
346
+ "line-through": () => "text-decoration-line: line-through",
347
+ "no-underline": () => "text-decoration-line: none",
348
+ "truncate": () => "overflow: hidden; text-overflow: ellipsis; white-space: nowrap",
349
+ "antialiased": () => "-webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale",
350
+ "whitespace-": (v) => `white-space: ${v}`,
351
+ "break-": (v) => {
352
+ const breakMap: Record<string, string> = {
353
+ "normal": "overflow-wrap: normal; word-break: normal",
354
+ "words": "overflow-wrap: break-word",
355
+ "all": "word-break: break-all",
356
+ "keep": "word-break: keep-all",
357
+ };
358
+ return breakMap[v] || "";
359
+ },
360
+
361
+ // ═══════════════════════════════════════════════════════════════════════════
362
+ // FLEXBOX
363
+ // ═══════════════════════════════════════════════════════════════════════════
364
+ "flex": (v) => {
365
+ if (v === "") return "display: flex";
366
+ if (v === "-1") return "flex: 1 1 0%";
367
+ if (v === "-auto") return "flex: 1 1 auto";
368
+ if (v === "-initial") return "flex: 0 1 auto";
369
+ if (v === "-none") return "flex: none";
370
+ if (v === "-row") return "flex-direction: row";
371
+ if (v === "-row-reverse") return "flex-direction: row-reverse";
372
+ if (v === "-col") return "flex-direction: column";
373
+ if (v === "-col-reverse") return "flex-direction: column-reverse";
374
+ if (v === "-wrap") return "flex-wrap: wrap";
375
+ if (v === "-wrap-reverse") return "flex-wrap: wrap-reverse";
376
+ if (v === "-nowrap") return "flex-wrap: nowrap";
377
+ return "";
378
+ },
379
+ "items-": (v) => {
380
+ const map: Record<string, string> = {
381
+ "start": "flex-start", "end": "flex-end", "center": "center",
382
+ "baseline": "baseline", "stretch": "stretch",
383
+ };
384
+ return map[v] ? `align-items: ${map[v]}` : "";
385
+ },
386
+ "justify-": (v) => {
387
+ const map: Record<string, string> = {
388
+ "start": "flex-start", "end": "flex-end", "center": "center",
389
+ "between": "space-between", "around": "space-around", "evenly": "space-evenly",
390
+ };
391
+ return map[v] ? `justify-content: ${map[v]}` : "";
392
+ },
393
+ "self-": (v) => {
394
+ const map: Record<string, string> = {
395
+ "auto": "auto", "start": "flex-start", "end": "flex-end",
396
+ "center": "center", "stretch": "stretch", "baseline": "baseline",
397
+ };
398
+ return map[v] ? `align-self: ${map[v]}` : "";
399
+ },
400
+ "grow": (v) => v === "" ? "flex-grow: 1" : (v === "-0" ? "flex-grow: 0" : ""),
401
+ "shrink": (v) => v === "" ? "flex-shrink: 1" : (v === "-0" ? "flex-shrink: 0" : ""),
402
+ "order-": (v) => {
403
+ const orderMap: Record<string, string> = { "first": "-9999", "last": "9999", "none": "0" };
404
+ return `order: ${orderMap[v] || v}`;
405
+ },
406
+
407
+ // ═══════════════════════════════════════════════════════════════════════════
408
+ // GRID
409
+ // ═══════════════════════════════════════════════════════════════════════════
410
+ "grid": (v) => v === "" ? "display: grid" : "",
411
+ "grid-cols-": (v) => v === "none" ? "grid-template-columns: none" : `grid-template-columns: repeat(${v}, minmax(0, 1fr))`,
412
+ "grid-rows-": (v) => v === "none" ? "grid-template-rows: none" : `grid-template-rows: repeat(${v}, minmax(0, 1fr))`,
413
+ "col-span-": (v) => v === "full" ? "grid-column: 1 / -1" : `grid-column: span ${v} / span ${v}`,
414
+ "row-span-": (v) => v === "full" ? "grid-row: 1 / -1" : `grid-row: span ${v} / span ${v}`,
415
+
416
+ // ═══════════════════════════════════════════════════════════════════════════
417
+ // LAYOUT & DISPLAY
418
+ // ═══════════════════════════════════════════════════════════════════════════
419
+ "block": () => "display: block",
420
+ "inline-block": () => "display: inline-block",
421
+ "inline": () => "display: inline",
422
+ "hidden": () => "display: none",
423
+ "inline-flex": () => "display: inline-flex",
424
+ "inline-grid": () => "display: inline-grid",
425
+ "contents": () => "display: contents",
426
+ "flow-root": () => "display: flow-root",
427
+
428
+ // ═══════════════════════════════════════════════════════════════════════════
429
+ // POSITIONING
430
+ // ═══════════════════════════════════════════════════════════════════════════
431
+ "static": () => "position: static",
432
+ "fixed": () => "position: fixed",
433
+ "absolute": () => "position: absolute",
434
+ "relative": () => "position: relative",
435
+ "sticky": () => "position: sticky",
436
+ "inset-": (v) => `inset: ${spacingValue(v)}`,
437
+ "top-": (v) => `top: ${spacingValue(v)}`,
438
+ "right-": (v) => `right: ${spacingValue(v)}`,
439
+ "bottom-": (v) => `bottom: ${spacingValue(v)}`,
440
+ "left-": (v) => `left: ${spacingValue(v)}`,
441
+ "z-": (v) => {
442
+ const zMap: Record<string, string> = { "auto": "auto", "0": "0", "10": "10", "20": "20", "30": "30", "40": "40", "50": "50" };
443
+ return `z-index: ${zMap[v] || v}`;
444
+ },
445
+
446
+ // ═══════════════════════════════════════════════════════════════════════════
447
+ // OVERFLOW & VISIBILITY
448
+ // ═══════════════════════════════════════════════════════════════════════════
449
+ "overflow-": (v) => `overflow: ${v}`,
450
+ "overflow-x-": (v) => `overflow-x: ${v}`,
451
+ "overflow-y-": (v) => `overflow-y: ${v}`,
452
+ "visible": () => "visibility: visible",
453
+ "invisible": () => "visibility: hidden",
454
+ "collapse": () => "visibility: collapse",
455
+
456
+ // ═══════════════════════════════════════════════════════════════════════════
457
+ // OPACITY
458
+ // ═══════════════════════════════════════════════════════════════════════════
459
+ "opacity-": (v) => `opacity: ${parseFloat(v) / 100}`,
460
+
461
+ // ═══════════════════════════════════════════════════════════════════════════
462
+ // TRANSITIONS & ANIMATIONS
463
+ // ═══════════════════════════════════════════════════════════════════════════
464
+ "transition": (v) => {
465
+ const transitionMap: Record<string, string> = {
466
+ "": "transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms",
467
+ "-all": "transition-property: all; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms",
468
+ "-colors": "transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms",
469
+ "-opacity": "transition-property: opacity; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms",
470
+ "-shadow": "transition-property: box-shadow; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms",
471
+ "-transform": "transition-property: transform; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms",
472
+ "-none": "transition-property: none",
473
+ };
474
+ return transitionMap[v] || "";
475
+ },
476
+ "duration-": (v) => `transition-duration: ${v}ms`,
477
+ "delay-": (v) => `transition-delay: ${v}ms`,
478
+ "ease-": (v) => {
479
+ const easeMap: Record<string, string> = {
480
+ "linear": "linear", "in": "cubic-bezier(0.4, 0, 1, 1)",
481
+ "out": "cubic-bezier(0, 0, 0.2, 1)", "in-out": "cubic-bezier(0.4, 0, 0.2, 1)",
482
+ };
483
+ return easeMap[v] ? `transition-timing-function: ${easeMap[v]}` : "";
484
+ },
485
+
486
+ // ═══════════════════════════════════════════════════════════════════════════
487
+ // TRANSFORMS
488
+ // ═══════════════════════════════════════════════════════════════════════════
489
+ "scale-": (v) => `transform: scale(${parseFloat(v) / 100})`,
490
+ "rotate-": (v) => `transform: rotate(${v}deg)`,
491
+ "translate-x-": (v) => `transform: translateX(${spacingValue(v)})`,
492
+ "translate-y-": (v) => `transform: translateY(${spacingValue(v)})`,
493
+ "skew-x-": (v) => `transform: skewX(${v}deg)`,
494
+ "skew-y-": (v) => `transform: skewY(${v}deg)`,
495
+
496
+ // ═══════════════════════════════════════════════════════════════════════════
497
+ // CURSOR
498
+ // ═══════════════════════════════════════════════════════════════════════════
499
+ "cursor-": (v) => `cursor: ${v}`,
500
+
501
+ // ═══════════════════════════════════════════════════════════════════════════
502
+ // POINTER EVENTS
503
+ // ═══════════════════════════════════════════════════════════════════════════
504
+ "pointer-events-": (v) => `pointer-events: ${v}`,
505
+
506
+ // ═══════════════════════════════════════════════════════════════════════════
507
+ // USER SELECT
508
+ // ═══════════════════════════════════════════════════════════════════════════
509
+ "select-": (v) => `user-select: ${v}`,
510
+
511
+ // ═══════════════════════════════════════════════════════════════════════════
512
+ // OBJECT FIT
513
+ // ═══════════════════════════════════════════════════════════════════════════
514
+ "object-": (v) => {
515
+ const fitMap: Record<string, string> = {
516
+ "contain": "object-fit: contain", "cover": "object-fit: cover",
517
+ "fill": "object-fit: fill", "none": "object-fit: none", "scale-down": "object-fit: scale-down",
518
+ "bottom": "object-position: bottom", "center": "object-position: center",
519
+ "left": "object-position: left", "right": "object-position: right", "top": "object-position: top",
520
+ };
521
+ return fitMap[v] || "";
522
+ },
523
+
524
+ // ═══════════════════════════════════════════════════════════════════════════
525
+ // ASPECT RATIO
526
+ // ═══════════════════════════════════════════════════════════════════════════
527
+ "aspect-": (v) => {
528
+ const aspectMap: Record<string, string> = {
529
+ "auto": "auto", "square": "1 / 1", "video": "16 / 9",
530
+ };
531
+ return `aspect-ratio: ${aspectMap[v] || v}`;
532
+ },
533
+ };
534
+
535
+ export const COMPONENT_CONFIG_MAP: Record<string, ConfigSection[]> = {
536
+ // Default for "all" - show everything
537
+ "all": ["colors", "radius", "typography"],
538
+
539
+ // Categories
540
+ "buttons": ["colors", "radius", "typography"],
541
+ "forms": ["colors", "radius", "typography"],
542
+ "layout": ["colors", "radius"],
543
+ "typography": ["typography"],
544
+ "feedback": ["colors", "radius", "typography"],
545
+ "overlays": ["colors", "radius"],
546
+ "navigation": ["colors", "typography"],
547
+ "data display": ["colors", "radius"],
548
+
549
+ // Specific component overrides (these take precedence over category)
550
+ // Components with fixed radius (rounded-full)
551
+ "avatar": ["colors"],
552
+ "switch": ["colors"],
553
+ "spinner": ["colors"],
554
+
555
+ // Components that primarily use radius
556
+ "card": ["colors", "radius"],
557
+ "input": ["colors", "radius"],
558
+ "textarea": ["colors", "radius"],
559
+ "select": ["colors", "radius"],
560
+ "badge": ["colors", "radius"],
561
+ "alert": ["colors", "radius"],
562
+ "dialog": ["colors", "radius"],
563
+ "popover": ["colors", "radius"],
564
+ "toast": ["colors", "radius"],
565
+
566
+ // Button variants
567
+ "button-primary": ["colors", "radius", "typography"],
568
+ "button-secondary": ["colors", "radius", "typography"],
569
+ "button-ghost": ["colors", "radius", "typography"],
570
+ "button-destructive": ["colors", "radius", "typography"],
571
+
572
+ // Typography-focused components
573
+ "section-header": ["typography"],
574
+ "heading-display": ["typography"],
575
+ "body-text": ["typography"],
576
+ "link": ["colors", "typography"],
577
+
578
+ // Special cases
579
+ "separator": ["colors"],
580
+ "skeleton": ["colors"],
581
+ "progress": ["colors", "radius"],
582
+ "image": ["radius"],
583
+ "table": ["colors", "typography"],
584
+ };
585
+
586
+ /**
587
+ * Helper to check if a category should show scope options
588
+ */
589
+ export function shouldShowScopeOptions(category: string): boolean {
590
+ if (category === "all") return true; // Show for "all" selection
591
+ const lowerCategory = category.toLowerCase();
592
+ return TARGETABLE_CATEGORIES.includes(lowerCategory);
593
+ }
594
+
595
+ /**
596
+ * Get the visible config sections for a given component type
597
+ * First checks for specific component ID, then falls back to category
598
+ */
599
+ export function getVisibleSections(componentType: string): ConfigSection[] {
600
+ // Check for exact match first (specific component ID)
601
+ if (COMPONENT_CONFIG_MAP[componentType.toLowerCase()]) {
602
+ return COMPONENT_CONFIG_MAP[componentType.toLowerCase()];
603
+ }
604
+
605
+ // Try to find the component's category from snippets
606
+ const snippet = componentSnippets.find(s => s.id === componentType);
607
+ if (snippet) {
608
+ const categoryKey = snippet.category.toLowerCase();
609
+ if (COMPONENT_CONFIG_MAP[categoryKey]) {
610
+ return COMPONENT_CONFIG_MAP[categoryKey];
611
+ }
612
+ }
613
+
614
+ // Default: show all sections if unknown
615
+ return ["colors", "radius", "typography"];
616
+ }