oh-my-design-cli 0.1.3 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/post-edit-watch.cjs +99 -0
- package/.claude/hooks/session-end-foldin.cjs +96 -0
- package/.claude/hooks/session-state-loader.cjs +64 -0
- package/.claude/hooks/skill-activation.cjs +75 -0
- package/.claude/settings.json +55 -0
- package/AGENTS.md +111 -0
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +76 -203
- package/README.zh-TW.md +1 -1
- package/agents/AGENT.md +53 -0
- package/agents/omd-3d-blender.md +269 -0
- package/agents/omd-a11y-auditor.md +97 -0
- package/agents/omd-asset-curator.md +260 -0
- package/agents/omd-critic.md +181 -0
- package/agents/omd-master.md +548 -0
- package/agents/omd-microcopy.md +63 -0
- package/agents/omd-persona-tester.md +118 -0
- package/agents/omd-ui-junior.md +129 -0
- package/agents/omd-ux-engineer.md +265 -0
- package/agents/omd-ux-researcher.md +62 -0
- package/agents/omd-ux-writer.md +181 -0
- package/data/opt-out-corpus.json +141 -0
- package/data/reference-fingerprints.json +1495 -0
- package/dist/bin/oh-my-design.js +3 -818
- package/dist/bin/oh-my-design.js.map +1 -1
- package/dist/install-skills-GQPTQF5S.js +420 -0
- package/dist/install-skills-GQPTQF5S.js.map +1 -0
- package/package.json +22 -21
- package/scripts/context.cjs +91 -0
- package/scripts/postinstall.cjs +54 -0
- package/skills/omd-apply/SKILL.md +64 -53
- package/skills/omd-harness/SKILL.md +271 -0
- package/skills/omd-init/SKILL.md +1 -1
- package/skills/omd-learn/SKILL.md +56 -36
- package/skills/omd-remember/SKILL.md +94 -16
- package/skills/omd-sync/SKILL.md +141 -17
- package/dist/chunk-6YNSV3VY.js +0 -35
- package/dist/chunk-6YNSV3VY.js.map +0 -1
- package/dist/chunk-MHFYGZSO.js +0 -337
- package/dist/chunk-MHFYGZSO.js.map +0 -1
- package/dist/chunk-N2JG6N4Q.js +0 -264
- package/dist/chunk-N2JG6N4Q.js.map +0 -1
- package/dist/chunk-OOQQEUGX.js +0 -46
- package/dist/chunk-OOQQEUGX.js.map +0 -1
- package/dist/chunk-OR5DHENY.js +0 -250
- package/dist/chunk-OR5DHENY.js.map +0 -1
- package/dist/customizer-CM76752R.js +0 -8
- package/dist/customizer-CM76752R.js.map +0 -1
- package/dist/index.d.ts +0 -559
- package/dist/index.js +0 -3113
- package/dist/index.js.map +0 -1
- package/dist/init-UMM4XIV5.js +0 -675
- package/dist/init-UMM4XIV5.js.map +0 -1
- package/dist/install-skills-CM6VXFZJ.js +0 -152
- package/dist/install-skills-CM6VXFZJ.js.map +0 -1
- package/dist/learn-33LHKEJA.js +0 -140
- package/dist/learn-33LHKEJA.js.map +0 -1
- package/dist/reference-YMNAOXJQ.js +0 -47
- package/dist/reference-YMNAOXJQ.js.map +0 -1
- package/dist/reference-parser-TM3CJPNE.js +0 -10
- package/dist/reference-parser-TM3CJPNE.js.map +0 -1
- package/dist/remember-UAFA5B2O.js +0 -78
- package/dist/remember-UAFA5B2O.js.map +0 -1
- package/dist/sync-FDYRKNFE.js +0 -417
- package/dist/sync-FDYRKNFE.js.map +0 -1
- package/dist/templates/templates/design-md.hbs +0 -44
- package/dist/templates/templates/partials/agent-prompt-guide.hbs +0 -28
- package/dist/templates/templates/partials/color-palette.hbs +0 -49
- package/dist/templates/templates/partials/component-stylings.hbs +0 -28
- package/dist/templates/templates/partials/depth-elevation.hbs +0 -31
- package/dist/templates/templates/partials/dos-donts.hbs +0 -13
- package/dist/templates/templates/partials/layout.hbs +0 -30
- package/dist/templates/templates/partials/responsive.hbs +0 -25
- package/dist/templates/templates/partials/shadcn-tokens.hbs +0 -64
- package/dist/templates/templates/partials/typography.hbs +0 -43
- package/dist/templates/templates/partials/visual-theme.hbs +0 -26
package/dist/chunk-MHFYGZSO.js
DELETED
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/utils/color.ts
|
|
4
|
-
function hexToRgb(hex) {
|
|
5
|
-
const h = hex.replace("#", "");
|
|
6
|
-
return [
|
|
7
|
-
parseInt(h.slice(0, 2), 16),
|
|
8
|
-
parseInt(h.slice(2, 4), 16),
|
|
9
|
-
parseInt(h.slice(4, 6), 16)
|
|
10
|
-
];
|
|
11
|
-
}
|
|
12
|
-
function rgbToHex(r, g, b) {
|
|
13
|
-
return "#" + [r, g, b].map((v) => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, "0")).join("");
|
|
14
|
-
}
|
|
15
|
-
function hexToHsl(hex) {
|
|
16
|
-
const [r, g, b] = hexToRgb(hex).map((v) => v / 255);
|
|
17
|
-
const max = Math.max(r, g, b);
|
|
18
|
-
const min = Math.min(r, g, b);
|
|
19
|
-
const l = (max + min) / 2;
|
|
20
|
-
let h = 0;
|
|
21
|
-
let s = 0;
|
|
22
|
-
if (max !== min) {
|
|
23
|
-
const d = max - min;
|
|
24
|
-
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
25
|
-
switch (max) {
|
|
26
|
-
case r:
|
|
27
|
-
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
28
|
-
break;
|
|
29
|
-
case g:
|
|
30
|
-
h = ((b - r) / d + 2) / 6;
|
|
31
|
-
break;
|
|
32
|
-
case b:
|
|
33
|
-
h = ((r - g) / d + 4) / 6;
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
|
|
38
|
-
}
|
|
39
|
-
function hslToHex(h, s, l) {
|
|
40
|
-
const sn = s / 100;
|
|
41
|
-
const ln = l / 100;
|
|
42
|
-
const a = sn * Math.min(ln, 1 - ln);
|
|
43
|
-
const f = (n) => {
|
|
44
|
-
const k = (n + h / 30) % 12;
|
|
45
|
-
const color = ln - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
46
|
-
return Math.round(255 * color);
|
|
47
|
-
};
|
|
48
|
-
return rgbToHex(f(0), f(8), f(4));
|
|
49
|
-
}
|
|
50
|
-
function hslString(hex) {
|
|
51
|
-
const [h, s, l] = hexToHsl(hex);
|
|
52
|
-
return `${h} ${s}% ${l}%`;
|
|
53
|
-
}
|
|
54
|
-
function generateColorScale(hex) {
|
|
55
|
-
const [h, s] = hexToHsl(hex);
|
|
56
|
-
const lightnesses = {
|
|
57
|
-
50: 97,
|
|
58
|
-
100: 94,
|
|
59
|
-
200: 86,
|
|
60
|
-
300: 77,
|
|
61
|
-
400: 66,
|
|
62
|
-
500: 55,
|
|
63
|
-
600: 47,
|
|
64
|
-
700: 39,
|
|
65
|
-
800: 32,
|
|
66
|
-
900: 24,
|
|
67
|
-
950: 14
|
|
68
|
-
};
|
|
69
|
-
const scale = {};
|
|
70
|
-
for (const [key, l] of Object.entries(lightnesses)) {
|
|
71
|
-
scale[key] = hslToHex(h, s, l);
|
|
72
|
-
}
|
|
73
|
-
return scale;
|
|
74
|
-
}
|
|
75
|
-
function isLight(hex) {
|
|
76
|
-
const [, , l] = hexToHsl(hex);
|
|
77
|
-
return l > 55;
|
|
78
|
-
}
|
|
79
|
-
function contrastForeground(bgHex) {
|
|
80
|
-
return isLight(bgHex) ? "#09090b" : "#fafafa";
|
|
81
|
-
}
|
|
82
|
-
function lighten(hex, amount) {
|
|
83
|
-
const [h, s, l] = hexToHsl(hex);
|
|
84
|
-
return hslToHex(h, s, Math.min(100, l + amount));
|
|
85
|
-
}
|
|
86
|
-
function darken(hex, amount) {
|
|
87
|
-
const [h, s, l] = hexToHsl(hex);
|
|
88
|
-
return hslToHex(h, s, Math.max(0, l - amount));
|
|
89
|
-
}
|
|
90
|
-
function generateChartColors(primaryHex) {
|
|
91
|
-
const [h, s, l] = hexToHsl(primaryHex);
|
|
92
|
-
return [
|
|
93
|
-
primaryHex,
|
|
94
|
-
hslToHex((h + 40) % 360, s, l),
|
|
95
|
-
hslToHex((h + 80) % 360, s, l),
|
|
96
|
-
hslToHex((h + 160) % 360, s, l),
|
|
97
|
-
hslToHex((h + 220) % 360, s, l)
|
|
98
|
-
];
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// src/core/customizer.ts
|
|
102
|
-
function applyOverrides(ref, overrides, mode, components) {
|
|
103
|
-
let md = ref.designMd;
|
|
104
|
-
const effectivePrimary = overrides.primaryColor || ref.colors.primary;
|
|
105
|
-
const effectiveFont = overrides.fontFamily || ref.typography.primary;
|
|
106
|
-
const effectiveWeight = overrides.headingWeight || ref.typography.headingWeight;
|
|
107
|
-
const effectiveRadius = overrides.borderRadius || ref.radius.replace(/[-–].*/, "").trim();
|
|
108
|
-
const effectiveBg = ref.colors.background;
|
|
109
|
-
const effectiveFg = ref.colors.foreground;
|
|
110
|
-
md = md.replace(/[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE00}-\u{FE0F}\u{1FA00}-\u{1FAFF}\u{200D}\u{20E3}\u{E0020}-\u{E007F}]/gu, "");
|
|
111
|
-
if (mode === "customized") {
|
|
112
|
-
md = md.replace(/^# .+$/m, `# Custom Design System (based on ${ref.name})`);
|
|
113
|
-
if (overrides.primaryColor && overrides.primaryColor !== ref.colors.primary) {
|
|
114
|
-
const re = new RegExp(ref.colors.primary.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
|
|
115
|
-
md = re[Symbol.replace](md, overrides.primaryColor);
|
|
116
|
-
}
|
|
117
|
-
if (overrides.fontFamily && overrides.fontFamily !== ref.typography.primary) {
|
|
118
|
-
md = md.replaceAll(ref.typography.primary, overrides.fontFamily);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
if (components && components.length > 0) {
|
|
122
|
-
md += `
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## Included Components
|
|
127
|
-
|
|
128
|
-
The following components are part of this design system:
|
|
129
|
-
|
|
130
|
-
`;
|
|
131
|
-
md += components.map((c) => `- ${c.charAt(0).toUpperCase() + c.slice(1).replace(/-/g, " ")}`).join("\n");
|
|
132
|
-
md += "\n";
|
|
133
|
-
}
|
|
134
|
-
md += buildIconographySection();
|
|
135
|
-
const shadcnCss = generateShadcnCss(effectivePrimary, effectiveBg, effectiveFg, effectiveRadius, ref, overrides);
|
|
136
|
-
md += buildDocumentPolicies();
|
|
137
|
-
const previewData = buildPreviewData(ref, overrides, effectivePrimary, effectiveBg, effectiveFg, effectiveFont, effectiveWeight, effectiveRadius);
|
|
138
|
-
return { designMd: md, shadcnCss, previewData };
|
|
139
|
-
}
|
|
140
|
-
function generateShadcnCss(primary, background, foreground, radius, ref, overrides) {
|
|
141
|
-
const scale = generateColorScale(primary);
|
|
142
|
-
const accent = ref.colors.accent || hslToHex((hexToHsl(primary)[0] + 30) % 360, 60, 55);
|
|
143
|
-
const border = ref.colors.border || lighten(foreground, 75);
|
|
144
|
-
const muted = lighten(background === "#ffffff" ? "#f5f5f5" : background, 5);
|
|
145
|
-
const destructive = "#ef4444";
|
|
146
|
-
const chart = generateChartColors(primary);
|
|
147
|
-
const radiusRem = radius === "9999px" ? "9999px" : `${parseInt(radius) / 16}rem`;
|
|
148
|
-
const vars = {
|
|
149
|
-
"--background": hslString(background),
|
|
150
|
-
"--foreground": hslString(foreground),
|
|
151
|
-
"--card": hslString(background === "#ffffff" ? "#ffffff" : lighten(background, 3)),
|
|
152
|
-
"--card-foreground": hslString(foreground),
|
|
153
|
-
"--popover": hslString(background === "#ffffff" ? "#ffffff" : lighten(background, 5)),
|
|
154
|
-
"--popover-foreground": hslString(foreground),
|
|
155
|
-
"--primary": hslString(primary),
|
|
156
|
-
"--primary-foreground": hslString(contrastForeground(primary)),
|
|
157
|
-
"--secondary": hslString(scale[100]),
|
|
158
|
-
"--secondary-foreground": hslString(foreground),
|
|
159
|
-
"--muted": hslString(muted),
|
|
160
|
-
"--muted-foreground": hslString(lighten(foreground, 40)),
|
|
161
|
-
"--accent": hslString(accent),
|
|
162
|
-
"--accent-foreground": hslString(contrastForeground(accent)),
|
|
163
|
-
"--destructive": hslString(destructive),
|
|
164
|
-
"--destructive-foreground": hslString(contrastForeground(destructive)),
|
|
165
|
-
"--border": hslString(border),
|
|
166
|
-
"--input": hslString(border),
|
|
167
|
-
"--ring": hslString(primary),
|
|
168
|
-
"--radius": radiusRem,
|
|
169
|
-
"--chart-1": hslString(chart[0]),
|
|
170
|
-
"--chart-2": hslString(chart[1]),
|
|
171
|
-
"--chart-3": hslString(chart[2]),
|
|
172
|
-
"--chart-4": hslString(chart[3]),
|
|
173
|
-
"--chart-5": hslString(chart[4])
|
|
174
|
-
};
|
|
175
|
-
const lines = ["@layer base {", " :root {"];
|
|
176
|
-
for (const [k, v] of Object.entries(vars)) {
|
|
177
|
-
lines.push(` ${k}: ${v};`);
|
|
178
|
-
}
|
|
179
|
-
lines.push(" }");
|
|
180
|
-
if (overrides.darkMode) {
|
|
181
|
-
const darkBg = hslToHex(hexToHsl(primary)[0], 15, 7);
|
|
182
|
-
const darkFg = "#fafafa";
|
|
183
|
-
const darkBorder = hslToHex(hexToHsl(primary)[0], 10, 18);
|
|
184
|
-
const darkMuted = hslToHex(hexToHsl(primary)[0], 10, 15);
|
|
185
|
-
lines.push("", " .dark {");
|
|
186
|
-
const darkVars = {
|
|
187
|
-
"--background": hslString(darkBg),
|
|
188
|
-
"--foreground": hslString(darkFg),
|
|
189
|
-
"--card": hslString(lighten(darkBg, 3)),
|
|
190
|
-
"--card-foreground": hslString(darkFg),
|
|
191
|
-
"--popover": hslString(lighten(darkBg, 5)),
|
|
192
|
-
"--popover-foreground": hslString(darkFg),
|
|
193
|
-
"--primary": hslString(primary),
|
|
194
|
-
"--primary-foreground": hslString(contrastForeground(primary)),
|
|
195
|
-
"--secondary": hslString(hslToHex(hexToHsl(primary)[0], 15, 20)),
|
|
196
|
-
"--secondary-foreground": hslString(darkFg),
|
|
197
|
-
"--muted": hslString(darkMuted),
|
|
198
|
-
"--muted-foreground": hslString(darken(darkFg, 35)),
|
|
199
|
-
"--accent": hslString(accent),
|
|
200
|
-
"--accent-foreground": hslString(contrastForeground(accent)),
|
|
201
|
-
"--destructive": hslString(destructive),
|
|
202
|
-
"--destructive-foreground": hslString(contrastForeground(destructive)),
|
|
203
|
-
"--border": hslString(darkBorder),
|
|
204
|
-
"--input": hslString(lighten(darkBorder, 5)),
|
|
205
|
-
"--ring": hslString(primary),
|
|
206
|
-
"--chart-1": hslString(chart[0]),
|
|
207
|
-
"--chart-2": hslString(chart[1]),
|
|
208
|
-
"--chart-3": hslString(chart[2]),
|
|
209
|
-
"--chart-4": hslString(chart[3]),
|
|
210
|
-
"--chart-5": hslString(chart[4])
|
|
211
|
-
};
|
|
212
|
-
for (const [k, v] of Object.entries(darkVars)) {
|
|
213
|
-
lines.push(` ${k}: ${v};`);
|
|
214
|
-
}
|
|
215
|
-
lines.push(" }");
|
|
216
|
-
}
|
|
217
|
-
lines.push("}");
|
|
218
|
-
return lines.join("\n");
|
|
219
|
-
}
|
|
220
|
-
function buildPreviewData(ref, overrides, primary, background, foreground, font, headingWeight, radius) {
|
|
221
|
-
const scale = generateColorScale(primary);
|
|
222
|
-
const accent = ref.colors.accent || hslToHex((hexToHsl(primary)[0] + 30) % 360, 60, 55);
|
|
223
|
-
const border = ref.colors.border || lighten(foreground, 75);
|
|
224
|
-
const chart = generateChartColors(primary);
|
|
225
|
-
return {
|
|
226
|
-
name: overrides.primaryColor || overrides.fontFamily ? `Custom (based on ${ref.name})` : ref.name,
|
|
227
|
-
basedOn: ref.name,
|
|
228
|
-
primary,
|
|
229
|
-
background,
|
|
230
|
-
foreground,
|
|
231
|
-
font,
|
|
232
|
-
headingWeight,
|
|
233
|
-
radius,
|
|
234
|
-
shadcnCss: "",
|
|
235
|
-
// filled later
|
|
236
|
-
designMd: "",
|
|
237
|
-
// filled later
|
|
238
|
-
colors: {
|
|
239
|
-
primary,
|
|
240
|
-
accent,
|
|
241
|
-
muted: lighten(background === "#ffffff" ? "#f5f5f5" : background, 5),
|
|
242
|
-
destructive: "#ef4444",
|
|
243
|
-
border,
|
|
244
|
-
scale,
|
|
245
|
-
chart
|
|
246
|
-
},
|
|
247
|
-
darkMode: overrides.darkMode
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
function buildIconographySection() {
|
|
251
|
-
return `
|
|
252
|
-
|
|
253
|
-
---
|
|
254
|
-
|
|
255
|
-
## Iconography & SVG Guidelines
|
|
256
|
-
|
|
257
|
-
### Icon Library
|
|
258
|
-
|
|
259
|
-
Use a single, consistent icon library throughout the project. Recommended options:
|
|
260
|
-
|
|
261
|
-
- **Lucide React** (\`lucide-react\`): Default for shadcn/ui projects. 1,400+ icons, tree-shakeable, consistent 24x24 grid.
|
|
262
|
-
- **Radix Icons** (\`@radix-ui/react-icons\`): 300+ icons, 15x15 grid, minimal and geometric.
|
|
263
|
-
- **Heroicons** (\`@heroicons/react\`): 300+ icons by Tailwind team, outline and solid variants.
|
|
264
|
-
|
|
265
|
-
Pick ONE library and use it everywhere. Do not mix icon libraries within the same project.
|
|
266
|
-
|
|
267
|
-
### SVG Usage Rules
|
|
268
|
-
|
|
269
|
-
- All icons must be inline SVG components (not \`<img>\` tags) for color and size control.
|
|
270
|
-
- Icon size follows the type scale: 16px (inline), 20px (buttons), 24px (standalone).
|
|
271
|
-
- Icon color inherits from \`currentColor\` -- never hard-code fill/stroke colors.
|
|
272
|
-
- For custom/brand icons, export as SVG components with \`currentColor\` fills.
|
|
273
|
-
- Stroke width: 1.5px-2px for outline icons. Keep consistent across the project.
|
|
274
|
-
|
|
275
|
-
### Icon Sizing Scale
|
|
276
|
-
|
|
277
|
-
| Context | Size | Usage |
|
|
278
|
-
|---------|------|-------|
|
|
279
|
-
| Inline text | 16px (1rem) | Badges, labels, breadcrumbs |
|
|
280
|
-
| Button icon | 18px (1.125rem) | Icon buttons, CTA icons |
|
|
281
|
-
| Standalone | 24px (1.5rem) | Navigation, card icons |
|
|
282
|
-
| Feature | 32-48px | Hero sections, empty states |
|
|
283
|
-
|
|
284
|
-
### SVG Optimization
|
|
285
|
-
|
|
286
|
-
- Run all custom SVGs through SVGO before committing.
|
|
287
|
-
- Remove unnecessary attributes: \`xmlns\`, \`xml:space\`, editor metadata.
|
|
288
|
-
- Use \`viewBox\` instead of fixed \`width\`/\`height\` for scalability.
|
|
289
|
-
`;
|
|
290
|
-
}
|
|
291
|
-
function buildDocumentPolicies() {
|
|
292
|
-
return `
|
|
293
|
-
|
|
294
|
-
---
|
|
295
|
-
|
|
296
|
-
## Document Policies
|
|
297
|
-
|
|
298
|
-
### No Emojis
|
|
299
|
-
|
|
300
|
-
This design system must not use emojis in any UI element, component, label, status indicator, or documentation.
|
|
301
|
-
Use SVG icons from the chosen icon library instead. Emojis render inconsistently across platforms and break visual coherence.
|
|
302
|
-
|
|
303
|
-
- Status indicators: use colored dots or icon components, not emoji.
|
|
304
|
-
- Section markers: use text prefixes ("DO:" / "DON'T:") or icons, not checkmark/cross emojis.
|
|
305
|
-
- Navigation: use icon components, not emoji.
|
|
306
|
-
|
|
307
|
-
### Format Compliance
|
|
308
|
-
|
|
309
|
-
This document follows the Google Stitch DESIGN.md 9-section format:
|
|
310
|
-
1. Visual Theme & Atmosphere
|
|
311
|
-
2. Color Palette & Roles
|
|
312
|
-
3. Typography Rules
|
|
313
|
-
4. Component Stylings
|
|
314
|
-
5. Layout Principles
|
|
315
|
-
6. Depth & Elevation
|
|
316
|
-
7. Do's and Don'ts
|
|
317
|
-
8. Responsive Behavior
|
|
318
|
-
9. Agent Prompt Guide
|
|
319
|
-
|
|
320
|
-
Extended with:
|
|
321
|
-
- Iconography & SVG Guidelines
|
|
322
|
-
- Document Policies
|
|
323
|
-
|
|
324
|
-
Total target length: 250-400 lines. Keep sections concise and actionable.
|
|
325
|
-
`;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
export {
|
|
329
|
-
hexToHsl,
|
|
330
|
-
hslToHex,
|
|
331
|
-
generateColorScale,
|
|
332
|
-
contrastForeground,
|
|
333
|
-
lighten,
|
|
334
|
-
darken,
|
|
335
|
-
applyOverrides
|
|
336
|
-
};
|
|
337
|
-
//# sourceMappingURL=chunk-MHFYGZSO.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/color.ts","../src/core/customizer.ts"],"sourcesContent":["import type { ColorScale, SemanticColor } from '../core/types.js';\n\n// ── Hex ↔ HSL conversions ────────────────────────────────────────\n\nexport function hexToRgb(hex: string): [number, number, number] {\n const h = hex.replace('#', '');\n return [\n parseInt(h.slice(0, 2), 16),\n parseInt(h.slice(2, 4), 16),\n parseInt(h.slice(4, 6), 16),\n ];\n}\n\nexport function rgbToHex(r: number, g: number, b: number): string {\n return (\n '#' +\n [r, g, b]\n .map((v) => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, '0'))\n .join('')\n );\n}\n\nexport function hexToHsl(hex: string): [number, number, number] {\n const [r, g, b] = hexToRgb(hex).map((v) => v / 255);\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n let h = 0;\n let s = 0;\n\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;\n case g: h = ((b - r) / d + 2) / 6; break;\n case b: h = ((r - g) / d + 4) / 6; break;\n }\n }\n\n return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];\n}\n\nexport function hslToHex(h: number, s: number, l: number): string {\n const sn = s / 100;\n const ln = l / 100;\n const a = sn * Math.min(ln, 1 - ln);\n const f = (n: number) => {\n const k = (n + h / 30) % 12;\n const color = ln - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);\n return Math.round(255 * color);\n };\n return rgbToHex(f(0), f(8), f(4));\n}\n\n/** Format HSL for shadcn CSS variables: \"210 40% 98%\" */\nexport function hslString(hex: string): string {\n const [h, s, l] = hexToHsl(hex);\n return `${h} ${s}% ${l}%`;\n}\n\n// ── Palette generation ───────────────────────────────────────────\n\n/** Generate a full 11-stop color scale from a single hex */\nexport function generateColorScale(hex: string): ColorScale {\n const [h, s] = hexToHsl(hex);\n\n const lightnesses: Record<keyof ColorScale, number> = {\n 50: 97, 100: 94, 200: 86, 300: 77,\n 400: 66, 500: 55, 600: 47, 700: 39,\n 800: 32, 900: 24, 950: 14,\n };\n\n const scale = {} as ColorScale;\n for (const [key, l] of Object.entries(lightnesses)) {\n (scale as unknown as Record<string, string>)[key] = hslToHex(h, s, l);\n }\n return scale;\n}\n\n/** Determine if a color is \"light\" (needs dark foreground) */\nexport function isLight(hex: string): boolean {\n const [, , l] = hexToHsl(hex);\n return l > 55;\n}\n\n/** Pick a contrasting foreground for a given background */\nexport function contrastForeground(bgHex: string): string {\n return isLight(bgHex) ? '#09090b' : '#fafafa';\n}\n\n/** Create a semantic color pair (base + auto-contrast foreground) */\nexport function semanticColor(base: string): SemanticColor {\n return { base, foreground: contrastForeground(base) };\n}\n\n/** Lighten a hex color by a percentage (0-100) */\nexport function lighten(hex: string, amount: number): string {\n const [h, s, l] = hexToHsl(hex);\n return hslToHex(h, s, Math.min(100, l + amount));\n}\n\n/** Darken a hex color by a percentage (0-100) */\nexport function darken(hex: string, amount: number): string {\n const [h, s, l] = hexToHsl(hex);\n return hslToHex(h, s, Math.max(0, l - amount));\n}\n\n/** Desaturate a color */\nexport function desaturate(hex: string, amount: number): string {\n const [h, s, l] = hexToHsl(hex);\n return hslToHex(h, Math.max(0, s - amount), l);\n}\n\n/** Generate chart colors from primary by rotating hue */\nexport function generateChartColors(primaryHex: string): [string, string, string, string, string] {\n const [h, s, l] = hexToHsl(primaryHex);\n return [\n primaryHex,\n hslToHex((h + 40) % 360, s, l),\n hslToHex((h + 80) % 360, s, l),\n hslToHex((h + 160) % 360, s, l),\n hslToHex((h + 220) % 360, s, l),\n ];\n}\n","import type { ReferenceEntry } from './reference-parser.js';\nimport type { CustomOverrides } from '../cli/prompts.js';\nimport {\n generateColorScale,\n contrastForeground,\n hslString,\n hexToHsl,\n hslToHex,\n lighten,\n darken,\n generateChartColors,\n} from '../utils/color.js';\n\n/**\n * Apply user overrides to a reference DESIGN.md.\n *\n * Strategy:\n * - \"as-is\": return the original DESIGN.md content with minimal additions\n * - \"customized\": perform text-level replacements for color/font/radius/weight\n * and append a customization summary + shadcn CSS variables block\n *\n * This is intentionally NOT an AI call. It's deterministic string transformation.\n */\nexport function applyOverrides(\n ref: ReferenceEntry,\n overrides: CustomOverrides,\n mode: 'as-is' | 'customized',\n components?: string[],\n): { designMd: string; shadcnCss: string; previewData: PreviewData } {\n let md = ref.designMd;\n\n const effectivePrimary = overrides.primaryColor || ref.colors.primary;\n const effectiveFont = overrides.fontFamily || ref.typography.primary;\n const effectiveWeight = overrides.headingWeight || ref.typography.headingWeight;\n const effectiveRadius = overrides.borderRadius || ref.radius.replace(/[-–].*/, '').trim();\n const effectiveBg = ref.colors.background;\n const effectiveFg = ref.colors.foreground;\n\n // Strip emojis. The unicode range covers ✅ (U+2705) and ❌ (U+274C) too,\n // so any DO:/DON'T: prefix conversion would never match — references use\n // explicit \"**DO**\" / \"**DON'T**\" markdown instead.\n md = md.replace(/[\\u{1F300}-\\u{1F9FF}\\u{2600}-\\u{26FF}\\u{2700}-\\u{27BF}\\u{FE00}-\\u{FE0F}\\u{1FA00}-\\u{1FAFF}\\u{200D}\\u{20E3}\\u{E0020}-\\u{E007F}]/gu, '');\n\n if (mode === 'customized') {\n // Direct replacement — one source of truth for AI agents\n md = md.replace(/^# .+$/m, `# Custom Design System (based on ${ref.name})`);\n\n if (overrides.primaryColor && overrides.primaryColor !== ref.colors.primary) {\n const re = new RegExp(ref.colors.primary.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'gi');\n md = re[Symbol.replace](md, overrides.primaryColor);\n }\n if (overrides.fontFamily && overrides.fontFamily !== ref.typography.primary) {\n md = md.replaceAll(ref.typography.primary, overrides.fontFamily);\n }\n }\n\n // Append component list\n if (components && components.length > 0) {\n md += `\\n\\n---\\n\\n## Included Components\\n\\nThe following components are part of this design system:\\n\\n`;\n md += components.map(c => `- ${c.charAt(0).toUpperCase() + c.slice(1).replace(/-/g, ' ')}`).join('\\n');\n md += '\\n';\n }\n\n // Append iconography section\n md += buildIconographySection();\n\n // Generate shadcn CSS for preview data only (no longer appended to DESIGN.md)\n const shadcnCss = generateShadcnCss(effectivePrimary, effectiveBg, effectiveFg, effectiveRadius, ref, overrides);\n\n // Append document policies\n md += buildDocumentPolicies();\n\n // Build preview data\n const previewData = buildPreviewData(ref, overrides, effectivePrimary, effectiveBg, effectiveFg, effectiveFont, effectiveWeight, effectiveRadius);\n\n return { designMd: md, shadcnCss, previewData };\n}\n\n// ── Text replacements ────────────────────────────────────────────\n\nfunction replaceColor(md: string, oldHex: string, newHex: string): string {\n // Replace the exact hex (case-insensitive)\n const regex = new RegExp(escapeRegex(oldHex), 'gi');\n return md.replace(regex, newHex);\n}\n\nfunction replaceFont(md: string, oldFont: string, newFont: string): string {\n const regex = new RegExp(escapeRegex(oldFont), 'g');\n return md.replace(regex, newFont);\n}\n\nfunction replaceWeight(md: string, oldWeight: string, newWeight: string): string {\n // Only replace weight in Display/Heading rows and key characteristics\n // Be careful not to replace all numbers\n const regex = new RegExp(`(Display.*?\\\\|\\\\s*)${oldWeight}(\\\\s*\\\\|)`, 'g');\n let result = md.replace(regex, `$1${newWeight}$2`);\n // Also replace \"weight X\" patterns\n result = result.replace(\n new RegExp(`weight ${oldWeight}`, 'g'),\n `weight ${newWeight}`,\n );\n return result;\n}\n\nfunction replaceRadius(md: string, oldRadius: string, newRadius: string): string {\n // Replace \"Xpx\" radius patterns\n const oldBase = oldRadius.replace(/[-–].*/, '').trim();\n if (oldBase === newRadius) return md;\n const regex = new RegExp(`${escapeRegex(oldBase)}`, 'g');\n return md.replace(regex, newRadius);\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n// ── Customization summary section ────────────────────────────────\n\nfunction buildCustomizationSummary(ref: ReferenceEntry, overrides: CustomOverrides): string {\n const changes: string[] = [];\n if (overrides.primaryColor) {\n changes.push(`- **Primary color**: ${ref.colors.primary} → ${overrides.primaryColor}`);\n }\n if (overrides.fontFamily) {\n changes.push(`- **Font**: ${ref.typography.primary} → ${overrides.fontFamily}`);\n }\n if (overrides.headingWeight) {\n changes.push(`- **Heading weight**: ${ref.typography.headingWeight} → ${overrides.headingWeight}`);\n }\n if (overrides.borderRadius) {\n changes.push(`- **Border radius**: ${ref.radius} → ${overrides.borderRadius}`);\n }\n if (overrides.additionalNotes) {\n changes.push(`- **Additional notes**: ${overrides.additionalNotes}`);\n }\n\n if (changes.length === 0) return '';\n\n return `\n\n---\n\n## Customization Applied\n\n> Based on **${ref.name}** design system with the following modifications:\n\n${changes.join('\\n')}\n`;\n}\n\n// ── shadcn CSS generation ────────────────────────────────────────\n\nfunction generateShadcnCss(\n primary: string,\n background: string,\n foreground: string,\n radius: string,\n ref: ReferenceEntry,\n overrides: CustomOverrides,\n): string {\n const scale = generateColorScale(primary);\n const accent = ref.colors.accent || hslToHex((hexToHsl(primary)[0] + 30) % 360, 60, 55);\n const border = ref.colors.border || lighten(foreground, 75);\n const muted = lighten(background === '#ffffff' ? '#f5f5f5' : background, 5);\n const destructive = '#ef4444';\n const chart = generateChartColors(primary);\n\n const radiusRem = radius === '9999px' ? '9999px' : `${parseInt(radius) / 16}rem`;\n\n const vars: Record<string, string> = {\n '--background': hslString(background),\n '--foreground': hslString(foreground),\n '--card': hslString(background === '#ffffff' ? '#ffffff' : lighten(background, 3)),\n '--card-foreground': hslString(foreground),\n '--popover': hslString(background === '#ffffff' ? '#ffffff' : lighten(background, 5)),\n '--popover-foreground': hslString(foreground),\n '--primary': hslString(primary),\n '--primary-foreground': hslString(contrastForeground(primary)),\n '--secondary': hslString(scale[100]),\n '--secondary-foreground': hslString(foreground),\n '--muted': hslString(muted),\n '--muted-foreground': hslString(lighten(foreground, 40)),\n '--accent': hslString(accent),\n '--accent-foreground': hslString(contrastForeground(accent)),\n '--destructive': hslString(destructive),\n '--destructive-foreground': hslString(contrastForeground(destructive)),\n '--border': hslString(border),\n '--input': hslString(border),\n '--ring': hslString(primary),\n '--radius': radiusRem,\n '--chart-1': hslString(chart[0]),\n '--chart-2': hslString(chart[1]),\n '--chart-3': hslString(chart[2]),\n '--chart-4': hslString(chart[3]),\n '--chart-5': hslString(chart[4]),\n };\n\n const lines = ['@layer base {', ' :root {'];\n for (const [k, v] of Object.entries(vars)) {\n lines.push(` ${k}: ${v};`);\n }\n lines.push(' }');\n\n // Dark mode\n if (overrides.darkMode) {\n const darkBg = hslToHex(hexToHsl(primary)[0], 15, 7);\n const darkFg = '#fafafa';\n const darkBorder = hslToHex(hexToHsl(primary)[0], 10, 18);\n const darkMuted = hslToHex(hexToHsl(primary)[0], 10, 15);\n\n lines.push('', ' .dark {');\n const darkVars: Record<string, string> = {\n '--background': hslString(darkBg),\n '--foreground': hslString(darkFg),\n '--card': hslString(lighten(darkBg, 3)),\n '--card-foreground': hslString(darkFg),\n '--popover': hslString(lighten(darkBg, 5)),\n '--popover-foreground': hslString(darkFg),\n '--primary': hslString(primary),\n '--primary-foreground': hslString(contrastForeground(primary)),\n '--secondary': hslString(hslToHex(hexToHsl(primary)[0], 15, 20)),\n '--secondary-foreground': hslString(darkFg),\n '--muted': hslString(darkMuted),\n '--muted-foreground': hslString(darken(darkFg, 35)),\n '--accent': hslString(accent),\n '--accent-foreground': hslString(contrastForeground(accent)),\n '--destructive': hslString(destructive),\n '--destructive-foreground': hslString(contrastForeground(destructive)),\n '--border': hslString(darkBorder),\n '--input': hslString(lighten(darkBorder, 5)),\n '--ring': hslString(primary),\n '--chart-1': hslString(chart[0]),\n '--chart-2': hslString(chart[1]),\n '--chart-3': hslString(chart[2]),\n '--chart-4': hslString(chart[3]),\n '--chart-5': hslString(chart[4]),\n };\n for (const [k, v] of Object.entries(darkVars)) {\n lines.push(` ${k}: ${v};`);\n }\n lines.push(' }');\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\nfunction buildShadcnSection(css: string): string {\n return `\n\n---\n\n## 10. shadcn/ui Theme\n\nCopy this CSS block into your \\`globals.css\\` to apply this design system to shadcn/ui components.\n\n\\`\\`\\`css\n${css}\n\\`\\`\\`\n`;\n}\n\n// ── Preview Data ─────────────────────────────────────────────────\n\nexport interface PreviewData {\n name: string;\n basedOn: string;\n primary: string;\n background: string;\n foreground: string;\n font: string;\n headingWeight: string;\n radius: string;\n shadcnCss: string;\n designMd: string;\n colors: {\n primary: string;\n accent: string;\n muted: string;\n destructive: string;\n border: string;\n scale: Record<string, string>;\n chart: string[];\n };\n darkMode: boolean;\n}\n\nfunction buildPreviewData(\n ref: ReferenceEntry,\n overrides: CustomOverrides,\n primary: string,\n background: string,\n foreground: string,\n font: string,\n headingWeight: string,\n radius: string,\n): PreviewData {\n const scale = generateColorScale(primary);\n const accent = ref.colors.accent || hslToHex((hexToHsl(primary)[0] + 30) % 360, 60, 55);\n const border = ref.colors.border || lighten(foreground, 75);\n const chart = generateChartColors(primary);\n\n return {\n name: overrides.primaryColor || overrides.fontFamily ? `Custom (based on ${ref.name})` : ref.name,\n basedOn: ref.name,\n primary,\n background,\n foreground,\n font,\n headingWeight,\n radius,\n shadcnCss: '', // filled later\n designMd: '', // filled later\n colors: {\n primary,\n accent,\n muted: lighten(background === '#ffffff' ? '#f5f5f5' : background, 5),\n destructive: '#ef4444',\n border,\n scale: scale as unknown as Record<string, string>,\n chart,\n },\n darkMode: overrides.darkMode,\n };\n}\n\n// ── Iconography section ──────────────────────────────────────────\n\nfunction buildIconographySection(): string {\n return `\n\n---\n\n## Iconography & SVG Guidelines\n\n### Icon Library\n\nUse a single, consistent icon library throughout the project. Recommended options:\n\n- **Lucide React** (\\`lucide-react\\`): Default for shadcn/ui projects. 1,400+ icons, tree-shakeable, consistent 24x24 grid.\n- **Radix Icons** (\\`@radix-ui/react-icons\\`): 300+ icons, 15x15 grid, minimal and geometric.\n- **Heroicons** (\\`@heroicons/react\\`): 300+ icons by Tailwind team, outline and solid variants.\n\nPick ONE library and use it everywhere. Do not mix icon libraries within the same project.\n\n### SVG Usage Rules\n\n- All icons must be inline SVG components (not \\`<img>\\` tags) for color and size control.\n- Icon size follows the type scale: 16px (inline), 20px (buttons), 24px (standalone).\n- Icon color inherits from \\`currentColor\\` -- never hard-code fill/stroke colors.\n- For custom/brand icons, export as SVG components with \\`currentColor\\` fills.\n- Stroke width: 1.5px-2px for outline icons. Keep consistent across the project.\n\n### Icon Sizing Scale\n\n| Context | Size | Usage |\n|---------|------|-------|\n| Inline text | 16px (1rem) | Badges, labels, breadcrumbs |\n| Button icon | 18px (1.125rem) | Icon buttons, CTA icons |\n| Standalone | 24px (1.5rem) | Navigation, card icons |\n| Feature | 32-48px | Hero sections, empty states |\n\n### SVG Optimization\n\n- Run all custom SVGs through SVGO before committing.\n- Remove unnecessary attributes: \\`xmlns\\`, \\`xml:space\\`, editor metadata.\n- Use \\`viewBox\\` instead of fixed \\`width\\`/\\`height\\` for scalability.\n`;\n}\n\n// ── Document policies ────────────────────────────────────────────\n\nfunction buildDocumentPolicies(): string {\n return `\n\n---\n\n## Document Policies\n\n### No Emojis\n\nThis design system must not use emojis in any UI element, component, label, status indicator, or documentation.\nUse SVG icons from the chosen icon library instead. Emojis render inconsistently across platforms and break visual coherence.\n\n- Status indicators: use colored dots or icon components, not emoji.\n- Section markers: use text prefixes (\"DO:\" / \"DON'T:\") or icons, not checkmark/cross emojis.\n- Navigation: use icon components, not emoji.\n\n### Format Compliance\n\nThis document follows the Google Stitch DESIGN.md 9-section format:\n1. Visual Theme & Atmosphere\n2. Color Palette & Roles\n3. Typography Rules\n4. Component Stylings\n5. Layout Principles\n6. Depth & Elevation\n7. Do's and Don'ts\n8. Responsive Behavior\n9. Agent Prompt Guide\n\nExtended with:\n- Iconography & SVG Guidelines\n- Document Policies\n\nTotal target length: 250-400 lines. Keep sections concise and actionable.\n`;\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-N2JG6N4Q.js
DELETED
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/core/reference-parser.ts
|
|
4
|
-
import { readFileSync, readdirSync, existsSync } from "fs";
|
|
5
|
-
import { join, dirname } from "path";
|
|
6
|
-
import { fileURLToPath } from "url";
|
|
7
|
-
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
var CATEGORIES = {
|
|
9
|
-
stripe: "Fintech",
|
|
10
|
-
coinbase: "Fintech",
|
|
11
|
-
revolut: "Fintech",
|
|
12
|
-
wise: "Fintech",
|
|
13
|
-
kraken: "Fintech",
|
|
14
|
-
vercel: "Developer Tools",
|
|
15
|
-
cursor: "Developer Tools",
|
|
16
|
-
warp: "Developer Tools",
|
|
17
|
-
expo: "Developer Tools",
|
|
18
|
-
lovable: "Developer Tools",
|
|
19
|
-
raycast: "Developer Tools",
|
|
20
|
-
superhuman: "Developer Tools",
|
|
21
|
-
supabase: "Backend & DevOps",
|
|
22
|
-
mongodb: "Backend & DevOps",
|
|
23
|
-
sentry: "Backend & DevOps",
|
|
24
|
-
posthog: "Backend & DevOps",
|
|
25
|
-
hashicorp: "Backend & DevOps",
|
|
26
|
-
clickhouse: "Backend & DevOps",
|
|
27
|
-
composio: "Backend & DevOps",
|
|
28
|
-
sanity: "Backend & DevOps",
|
|
29
|
-
notion: "Productivity",
|
|
30
|
-
"linear.app": "Productivity",
|
|
31
|
-
"cal": "Productivity",
|
|
32
|
-
zapier: "Productivity",
|
|
33
|
-
intercom: "Productivity",
|
|
34
|
-
resend: "Productivity",
|
|
35
|
-
mintlify: "Productivity",
|
|
36
|
-
figma: "Design Tools",
|
|
37
|
-
framer: "Design Tools",
|
|
38
|
-
miro: "Design Tools",
|
|
39
|
-
webflow: "Design Tools",
|
|
40
|
-
airtable: "Design Tools",
|
|
41
|
-
clay: "Design Tools",
|
|
42
|
-
claude: "AI & LLM",
|
|
43
|
-
cohere: "AI & LLM",
|
|
44
|
-
mistral: "AI & LLM",
|
|
45
|
-
"mistral.ai": "AI & LLM",
|
|
46
|
-
ollama: "AI & LLM",
|
|
47
|
-
"opencode.ai": "AI & LLM",
|
|
48
|
-
replicate: "AI & LLM",
|
|
49
|
-
"together.ai": "AI & LLM",
|
|
50
|
-
"x.ai": "AI & LLM",
|
|
51
|
-
elevenlabs: "AI & LLM",
|
|
52
|
-
minimax: "AI & LLM",
|
|
53
|
-
runwayml: "AI & LLM",
|
|
54
|
-
voltagent: "AI & LLM",
|
|
55
|
-
apple: "Consumer Tech",
|
|
56
|
-
spotify: "Consumer Tech",
|
|
57
|
-
uber: "Consumer Tech",
|
|
58
|
-
airbnb: "Consumer Tech",
|
|
59
|
-
pinterest: "Consumer Tech",
|
|
60
|
-
nvidia: "Consumer Tech",
|
|
61
|
-
ibm: "Consumer Tech",
|
|
62
|
-
spacex: "Consumer Tech",
|
|
63
|
-
shopify: "E-commerce",
|
|
64
|
-
semrush: "Marketing",
|
|
65
|
-
tesla: "Automotive",
|
|
66
|
-
bmw: "Automotive",
|
|
67
|
-
ferrari: "Automotive",
|
|
68
|
-
lamborghini: "Automotive",
|
|
69
|
-
renault: "Automotive",
|
|
70
|
-
bugatti: "Automotive",
|
|
71
|
-
karrot: "Korean Tech",
|
|
72
|
-
toss: "Korean Tech",
|
|
73
|
-
baemin: "Korean Tech",
|
|
74
|
-
kakao: "Korean Tech"
|
|
75
|
-
};
|
|
76
|
-
var CATEGORY_ORDER = [
|
|
77
|
-
"Korean Tech",
|
|
78
|
-
"AI & LLM",
|
|
79
|
-
"Design Tools",
|
|
80
|
-
"Developer Tools",
|
|
81
|
-
"Productivity",
|
|
82
|
-
"Consumer Tech",
|
|
83
|
-
"Fintech",
|
|
84
|
-
"Backend & DevOps",
|
|
85
|
-
"E-commerce",
|
|
86
|
-
"Automotive",
|
|
87
|
-
"Marketing"
|
|
88
|
-
];
|
|
89
|
-
function extractHexColors(text) {
|
|
90
|
-
const matches = text.match(/#[0-9a-fA-F]{6}\b/g) || [];
|
|
91
|
-
return [...new Set(matches)];
|
|
92
|
-
}
|
|
93
|
-
function extractPrimaryColor(md) {
|
|
94
|
-
const section2Match = md.match(/## 2\. Color Palette.*?\n([\s\S]*?)(?=## 3\.)/);
|
|
95
|
-
if (section2Match) {
|
|
96
|
-
const section2 = section2Match[1];
|
|
97
|
-
const primaryMatch = section2.match(/\*\*([^*]+)\*\*\s*\(`(#[0-9a-fA-F]{6})`\).*?(?:primary|brand|CTA|main)/i);
|
|
98
|
-
if (primaryMatch) {
|
|
99
|
-
return { hex: primaryMatch[2], name: primaryMatch[1] };
|
|
100
|
-
}
|
|
101
|
-
const firstHex = section2.match(/`(#[0-9a-fA-F]{6})`/);
|
|
102
|
-
if (firstHex) {
|
|
103
|
-
return { hex: firstHex[1], name: "Primary" };
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
const allHex = extractHexColors(md);
|
|
107
|
-
return { hex: allHex[0] || "#6366f1", name: "Primary" };
|
|
108
|
-
}
|
|
109
|
-
function extractBackground(md) {
|
|
110
|
-
const patterns = [
|
|
111
|
-
/(?:page|canvas|marketing)\s+background.*?`(#[0-9a-fA-F]{6})`/i,
|
|
112
|
-
/(?:Pure White|White).*?`(#[0-9a-fA-F]{6})`.*?(?:page background|background)/i,
|
|
113
|
-
/Background:.*?Pure White.*?\(`(#[0-9a-fA-F]{6})`\)/i,
|
|
114
|
-
/(?:Page|Site)\s+background.*?`(#[0-9a-fA-F]{6})`/i,
|
|
115
|
-
// Match "hex: The primary page background" pattern (hex before description)
|
|
116
|
-
/`(#[0-9a-fA-F]{6})`[^.]*?(?:primary\s+)?page\s+background/i
|
|
117
|
-
];
|
|
118
|
-
for (const pattern of patterns) {
|
|
119
|
-
const match = md.match(pattern);
|
|
120
|
-
if (match) return match[1];
|
|
121
|
-
}
|
|
122
|
-
const section2 = md.match(/## 2\. Color.*?\n([\s\S]*?)(?=## 3\.)/);
|
|
123
|
-
if (section2) {
|
|
124
|
-
const surfaceBg = section2[1].match(/(?:Pure White|Pure Black|page background|Background\b).*?`(#[0-9a-fA-F]{6})`/i);
|
|
125
|
-
if (surfaceBg) return surfaceBg[1];
|
|
126
|
-
}
|
|
127
|
-
const quickRef = md.match(/Quick Color Reference[\s\S]*?(?:Page\s+)?Background.*?[(`](#[0-9a-fA-F]{6})[)`]/i);
|
|
128
|
-
if (quickRef) return quickRef[1];
|
|
129
|
-
if (md.match(/dark.mode.(?:native|first)/i)) {
|
|
130
|
-
const darkBg = md.match(/(?:marketing|deepest|canvas).*?`(#[0-9a-fA-F]{6})`/i);
|
|
131
|
-
if (darkBg) return darkBg[1];
|
|
132
|
-
}
|
|
133
|
-
return "#ffffff";
|
|
134
|
-
}
|
|
135
|
-
function extractForeground(md) {
|
|
136
|
-
const fgMatch = md.match(/(?:heading|primary text).*?`(#[0-9a-fA-F]{6})`/i);
|
|
137
|
-
return fgMatch ? fgMatch[1] : "#09090b";
|
|
138
|
-
}
|
|
139
|
-
function extractAccent(md) {
|
|
140
|
-
const accentMatch = md.match(/(?:accent|secondary).*?`(#[0-9a-fA-F]{6})`/i);
|
|
141
|
-
return accentMatch ? accentMatch[1] : void 0;
|
|
142
|
-
}
|
|
143
|
-
function extractBorder(md) {
|
|
144
|
-
const borderMatch = md.match(/(?:border.*?default|border.*?standard).*?`(#[0-9a-fA-F]{6})`/i);
|
|
145
|
-
return borderMatch ? borderMatch[1] : void 0;
|
|
146
|
-
}
|
|
147
|
-
function extractTypography(md) {
|
|
148
|
-
const section3 = md.match(/## 3\. Typography.*?\n([\s\S]*?)(?=## 4\.)/);
|
|
149
|
-
let primary = "Inter";
|
|
150
|
-
let mono;
|
|
151
|
-
let headingWeight = "600";
|
|
152
|
-
if (section3) {
|
|
153
|
-
const text = section3[1];
|
|
154
|
-
const primaryMatch = text.match(/\*\*Primary\*\*:\s*`([^`]+)`/i);
|
|
155
|
-
if (primaryMatch) primary = primaryMatch[1].split(",")[0].trim();
|
|
156
|
-
const monoMatch = text.match(/\*\*Monospace\*\*:\s*`([^`]+)`/i);
|
|
157
|
-
if (monoMatch) mono = monoMatch[1].split(",")[0].trim();
|
|
158
|
-
const weightMatch = text.match(/Display.*?\|\s*(\d{3})\s*\|/);
|
|
159
|
-
if (weightMatch) headingWeight = weightMatch[1];
|
|
160
|
-
}
|
|
161
|
-
return { primary, mono, headingWeight };
|
|
162
|
-
}
|
|
163
|
-
function extractRadius(md) {
|
|
164
|
-
const radiusMatch = md.match(/(?:border-radius|radius).*?(\d+px(?:\s*[-–]\s*\d+px)?)/i);
|
|
165
|
-
return radiusMatch ? radiusMatch[1] : "6px";
|
|
166
|
-
}
|
|
167
|
-
function extractMood(md) {
|
|
168
|
-
const section1 = md.match(/## 1\. Visual Theme.*?\n([\s\S]*?)(?=## 2\.)/);
|
|
169
|
-
if (!section1) return "";
|
|
170
|
-
const text = section1[1].trim();
|
|
171
|
-
const firstParagraph = text.split("\n\n")[0];
|
|
172
|
-
return firstParagraph.slice(0, 300);
|
|
173
|
-
}
|
|
174
|
-
function toDisplayName(id) {
|
|
175
|
-
const special = {
|
|
176
|
-
"linear.app": "Linear",
|
|
177
|
-
"cal": "Cal.com",
|
|
178
|
-
"mistral.ai": "Mistral AI",
|
|
179
|
-
"opencode.ai": "OpenCode AI",
|
|
180
|
-
"together.ai": "Together AI",
|
|
181
|
-
"x.ai": "xAI",
|
|
182
|
-
ibm: "IBM",
|
|
183
|
-
bmw: "BMW",
|
|
184
|
-
nvidia: "NVIDIA",
|
|
185
|
-
posthog: "PostHog",
|
|
186
|
-
supabase: "Supabase",
|
|
187
|
-
voltagent: "VoltAgent",
|
|
188
|
-
elevenlabs: "ElevenLabs",
|
|
189
|
-
runwayml: "RunwayML",
|
|
190
|
-
spacex: "SpaceX",
|
|
191
|
-
coinbase: "Coinbase",
|
|
192
|
-
airbnb: "Airbnb",
|
|
193
|
-
clickhouse: "ClickHouse",
|
|
194
|
-
karrot: "Karrot",
|
|
195
|
-
toss: "Toss",
|
|
196
|
-
baemin: "Baemin",
|
|
197
|
-
kakao: "Kakao"
|
|
198
|
-
};
|
|
199
|
-
return special[id] || id.charAt(0).toUpperCase() + id.slice(1);
|
|
200
|
-
}
|
|
201
|
-
function getReferencesDir() {
|
|
202
|
-
const candidates = [
|
|
203
|
-
join(process.cwd(), "references"),
|
|
204
|
-
join(__dirname, "..", "..", "references"),
|
|
205
|
-
join(__dirname, "..", "references")
|
|
206
|
-
];
|
|
207
|
-
for (const dir of candidates) {
|
|
208
|
-
if (existsSync(dir)) return dir;
|
|
209
|
-
}
|
|
210
|
-
throw new Error("references/ directory not found. Searched: " + candidates.join(", "));
|
|
211
|
-
}
|
|
212
|
-
function loadReference(id) {
|
|
213
|
-
const dir = getReferencesDir();
|
|
214
|
-
const mdPath = join(dir, id, "DESIGN.md");
|
|
215
|
-
if (!existsSync(mdPath)) {
|
|
216
|
-
throw new Error(`Reference not found: ${id}`);
|
|
217
|
-
}
|
|
218
|
-
const designMd = readFileSync(mdPath, "utf-8");
|
|
219
|
-
const primary = extractPrimaryColor(designMd);
|
|
220
|
-
return {
|
|
221
|
-
id,
|
|
222
|
-
name: toDisplayName(id),
|
|
223
|
-
category: CATEGORIES[id] || "Other",
|
|
224
|
-
designMd,
|
|
225
|
-
colors: {
|
|
226
|
-
primary: primary.hex,
|
|
227
|
-
primaryName: primary.name,
|
|
228
|
-
background: extractBackground(designMd),
|
|
229
|
-
foreground: extractForeground(designMd),
|
|
230
|
-
accent: extractAccent(designMd),
|
|
231
|
-
border: extractBorder(designMd)
|
|
232
|
-
},
|
|
233
|
-
typography: extractTypography(designMd),
|
|
234
|
-
radius: extractRadius(designMd),
|
|
235
|
-
mood: extractMood(designMd)
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
function listReferences() {
|
|
239
|
-
const dir = getReferencesDir();
|
|
240
|
-
const entries = readdirSync(dir, { withFileTypes: true }).filter((d) => d.isDirectory() && existsSync(join(dir, d.name, "DESIGN.md"))).map((d) => {
|
|
241
|
-
const mdPath = join(dir, d.name, "DESIGN.md");
|
|
242
|
-
const md = readFileSync(mdPath, "utf-8");
|
|
243
|
-
const primary = extractPrimaryColor(md);
|
|
244
|
-
return {
|
|
245
|
-
id: d.name,
|
|
246
|
-
name: toDisplayName(d.name),
|
|
247
|
-
category: CATEGORIES[d.name] || "Other",
|
|
248
|
-
primaryColor: primary.hex
|
|
249
|
-
};
|
|
250
|
-
});
|
|
251
|
-
return entries.sort((a, b) => {
|
|
252
|
-
const ai = CATEGORY_ORDER.indexOf(a.category);
|
|
253
|
-
const bi = CATEGORY_ORDER.indexOf(b.category);
|
|
254
|
-
const oa = ai === -1 ? 999 : ai;
|
|
255
|
-
const ob = bi === -1 ? 999 : bi;
|
|
256
|
-
return oa - ob || a.name.localeCompare(b.name);
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
export {
|
|
261
|
-
loadReference,
|
|
262
|
-
listReferences
|
|
263
|
-
};
|
|
264
|
-
//# sourceMappingURL=chunk-N2JG6N4Q.js.map
|