@easybits.cloud/html-tailwind-generator 0.2.141 → 0.2.142
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ViewportToggle-Dszv1gsL.d.ts → ViewportToggle-Gns9NOvf.d.ts} +1 -1
- package/dist/buildHtmlV4.js +2 -2
- package/dist/{chunk-7XHJJBGN.js → chunk-7MGKYJTI.js} +2 -2
- package/dist/{chunk-VV5I53WR.js → chunk-DCAQAHSU.js} +39 -2
- package/dist/chunk-DCAQAHSU.js.map +1 -0
- package/dist/{chunk-YKZSLVPV.js → chunk-EIZRTLU6.js} +10 -8
- package/dist/chunk-EIZRTLU6.js.map +1 -0
- package/dist/{chunk-3I6UJ7UH.js → chunk-EP65R6DE.js} +3 -3
- package/dist/{chunk-KXOAEC33.js → chunk-ETWQS7IQ.js} +2 -2
- package/dist/{chunk-CDEB4EHT.js → chunk-GL74S2H4.js} +39 -16
- package/dist/chunk-GL74S2H4.js.map +1 -0
- package/dist/{chunk-IDJWYC4U.js → chunk-H2YYYKUI.js} +108 -5
- package/dist/chunk-H2YYYKUI.js.map +1 -0
- package/dist/{chunk-6OJXDEL2.js → chunk-QFT3PN3L.js} +18 -10
- package/dist/chunk-QFT3PN3L.js.map +1 -0
- package/dist/{chunk-4I5FFYHG.js → chunk-SJJZEW5W.js} +2 -2
- package/dist/{chunk-QHKJJI4K.js → chunk-ULAQDD23.js} +2 -2
- package/dist/components.d.ts +2 -2
- package/dist/components.js +3 -3
- package/dist/components4.js +1 -1
- package/dist/deploy.d.ts +1 -1
- package/dist/deploy.js +3 -3
- package/dist/directions.js +2 -2
- package/dist/generate.d.ts +5 -3
- package/dist/generate.js +3 -3
- package/dist/generateDocument.js +3 -3
- package/dist/images.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +10 -10
- package/dist/refine.d.ts +6 -3
- package/dist/refine.js +3 -3
- package/dist/{themes-DNTBHJUH.d.ts → themes-df34nq2_.d.ts} +6 -0
- package/package.json +1 -1
- package/dist/chunk-6OJXDEL2.js.map +0 -1
- package/dist/chunk-CDEB4EHT.js.map +0 -1
- package/dist/chunk-IDJWYC4U.js.map +0 -1
- package/dist/chunk-VV5I53WR.js.map +0 -1
- package/dist/chunk-YKZSLVPV.js.map +0 -1
- /package/dist/{chunk-7XHJJBGN.js.map → chunk-7MGKYJTI.js.map} +0 -0
- /package/dist/{chunk-3I6UJ7UH.js.map → chunk-EP65R6DE.js.map} +0 -0
- /package/dist/{chunk-KXOAEC33.js.map → chunk-ETWQS7IQ.js.map} +0 -0
- /package/dist/{chunk-4I5FFYHG.js.map → chunk-SJJZEW5W.js.map} +0 -0
- /package/dist/{chunk-QHKJJI4K.js.map → chunk-ULAQDD23.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React__default from 'react';
|
|
2
2
|
import { S as Section3, I as IframeMessage } from './types-BIpbpCJr.js';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
-
import { C as CustomColors, a as LandingTheme } from './themes-
|
|
4
|
+
import { C as CustomColors, a as LandingTheme } from './themes-df34nq2_.js';
|
|
5
5
|
|
|
6
6
|
interface CanvasHandle {
|
|
7
7
|
scrollToSection: (id: string) => void;
|
package/dist/buildHtmlV4.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
buildCustomTheme,
|
|
3
3
|
buildSingleThemeCss,
|
|
4
4
|
buildThemeCss
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DCAQAHSU.js";
|
|
6
6
|
|
|
7
7
|
// src/iframeScript.ts
|
|
8
8
|
function getIframeScript() {
|
|
@@ -633,4 +633,4 @@ export {
|
|
|
633
633
|
buildPreviewHtml,
|
|
634
634
|
buildDeployHtml
|
|
635
635
|
};
|
|
636
|
-
//# sourceMappingURL=chunk-
|
|
636
|
+
//# sourceMappingURL=chunk-7MGKYJTI.js.map
|
|
@@ -11,8 +11,10 @@ var LANDING_THEMES = [
|
|
|
11
11
|
accent: "#2563eb",
|
|
12
12
|
surface: "#ffffff",
|
|
13
13
|
"surface-alt": "#f4f4f5",
|
|
14
|
+
"surface-deep": "#18181b",
|
|
14
15
|
"on-surface": "#18181b",
|
|
15
16
|
"on-surface-muted": "#71717a",
|
|
17
|
+
"on-surface-deep": "#fafafa",
|
|
16
18
|
"on-primary": "#ffffff",
|
|
17
19
|
"on-secondary": "#ffffff",
|
|
18
20
|
"on-accent": "#ffffff"
|
|
@@ -29,8 +31,10 @@ var LANDING_THEMES = [
|
|
|
29
31
|
accent: "#d97706",
|
|
30
32
|
surface: "#fafaf9",
|
|
31
33
|
"surface-alt": "#f5f5f4",
|
|
34
|
+
"surface-deep": "#1c1917",
|
|
32
35
|
"on-surface": "#1c1917",
|
|
33
36
|
"on-surface-muted": "#78716c",
|
|
37
|
+
"on-surface-deep": "#fafaf9",
|
|
34
38
|
"on-primary": "#ffffff",
|
|
35
39
|
"on-secondary": "#ffffff",
|
|
36
40
|
"on-accent": "#111827"
|
|
@@ -47,8 +51,10 @@ var LANDING_THEMES = [
|
|
|
47
51
|
accent: "#0d9488",
|
|
48
52
|
surface: "#ffffff",
|
|
49
53
|
"surface-alt": "#f0fdfa",
|
|
54
|
+
"surface-deep": "#0f172a",
|
|
50
55
|
"on-surface": "#0f172a",
|
|
51
56
|
"on-surface-muted": "#64748b",
|
|
57
|
+
"on-surface-deep": "#ffffff",
|
|
52
58
|
"on-primary": "#ffffff",
|
|
53
59
|
"on-secondary": "#ffffff",
|
|
54
60
|
"on-accent": "#ffffff"
|
|
@@ -65,8 +71,10 @@ var LANDING_THEMES = [
|
|
|
65
71
|
accent: "#f472b6",
|
|
66
72
|
surface: "#111827",
|
|
67
73
|
"surface-alt": "#1f2937",
|
|
74
|
+
"surface-deep": "#030712",
|
|
68
75
|
"on-surface": "#f9fafb",
|
|
69
76
|
"on-surface-muted": "#9ca3af",
|
|
77
|
+
"on-surface-deep": "#f9fafb",
|
|
70
78
|
"on-primary": "#111827",
|
|
71
79
|
"on-secondary": "#111827",
|
|
72
80
|
"on-accent": "#111827"
|
|
@@ -83,8 +91,10 @@ var LANDING_THEMES = [
|
|
|
83
91
|
accent: "#f59e0b",
|
|
84
92
|
surface: "#0a0a0a",
|
|
85
93
|
"surface-alt": "#171717",
|
|
94
|
+
"surface-deep": "#000000",
|
|
86
95
|
"on-surface": "#fafafa",
|
|
87
96
|
"on-surface-muted": "#a3a3a3",
|
|
97
|
+
"on-surface-deep": "#fafafa",
|
|
88
98
|
"on-primary": "#ffffff",
|
|
89
99
|
"on-secondary": "#111827",
|
|
90
100
|
"on-accent": "#111827"
|
|
@@ -101,8 +111,10 @@ var LANDING_THEMES = [
|
|
|
101
111
|
accent: "#8b5cf6",
|
|
102
112
|
surface: "#ffffff",
|
|
103
113
|
"surface-alt": "#fdf2f8",
|
|
114
|
+
"surface-deep": "#1f2937",
|
|
104
115
|
"on-surface": "#1f2937",
|
|
105
116
|
"on-surface-muted": "#6b7280",
|
|
117
|
+
"on-surface-deep": "#ffffff",
|
|
106
118
|
"on-primary": "#ffffff",
|
|
107
119
|
"on-secondary": "#ffffff",
|
|
108
120
|
"on-accent": "#ffffff"
|
|
@@ -119,8 +131,10 @@ var LANDING_THEMES = [
|
|
|
119
131
|
accent: "#ec4899",
|
|
120
132
|
surface: "#faf5ff",
|
|
121
133
|
"surface-alt": "#f3e8ff",
|
|
134
|
+
"surface-deep": "#1e1b4b",
|
|
122
135
|
"on-surface": "#1e1b4b",
|
|
123
136
|
"on-surface-muted": "#6b7280",
|
|
137
|
+
"on-surface-deep": "#ffffff",
|
|
124
138
|
"on-primary": "#ffffff",
|
|
125
139
|
"on-secondary": "#1e1b4b",
|
|
126
140
|
"on-accent": "#ffffff"
|
|
@@ -137,8 +151,10 @@ var LANDING_THEMES = [
|
|
|
137
151
|
accent: "#0ea5e9",
|
|
138
152
|
surface: "#ffffff",
|
|
139
153
|
"surface-alt": "#f1f5f9",
|
|
154
|
+
"surface-deep": "#0f172a",
|
|
140
155
|
"on-surface": "#0f172a",
|
|
141
156
|
"on-surface-muted": "#64748b",
|
|
157
|
+
"on-surface-deep": "#ffffff",
|
|
142
158
|
"on-primary": "#ffffff",
|
|
143
159
|
"on-secondary": "#ffffff",
|
|
144
160
|
"on-accent": "#ffffff"
|
|
@@ -155,8 +171,10 @@ var LANDING_THEMES = [
|
|
|
155
171
|
accent: "#f97316",
|
|
156
172
|
surface: "#ffffff",
|
|
157
173
|
"surface-alt": "#ecfdf5",
|
|
174
|
+
"surface-deep": "#064e3b",
|
|
158
175
|
"on-surface": "#064e3b",
|
|
159
176
|
"on-surface-muted": "#6b7280",
|
|
177
|
+
"on-surface-deep": "#ffffff",
|
|
160
178
|
"on-primary": "#ffffff",
|
|
161
179
|
"on-secondary": "#ffffff",
|
|
162
180
|
"on-accent": "#ffffff"
|
|
@@ -173,8 +191,10 @@ var LANDING_THEMES = [
|
|
|
173
191
|
accent: "#facc15",
|
|
174
192
|
surface: "#0f172a",
|
|
175
193
|
"surface-alt": "#1e293b",
|
|
194
|
+
"surface-deep": "#020617",
|
|
176
195
|
"on-surface": "#f1f5f9",
|
|
177
196
|
"on-surface-muted": "#94a3b8",
|
|
197
|
+
"on-surface-deep": "#f1f5f9",
|
|
178
198
|
"on-primary": "#ffffff",
|
|
179
199
|
"on-secondary": "#0f172a",
|
|
180
200
|
"on-accent": "#0f172a"
|
|
@@ -193,7 +213,7 @@ var THEME_DESCRIPTIONS = {
|
|
|
193
213
|
esmeralda: "Emerald green \u2014 fresh, trustworthy, white surfaces with warm orange accent",
|
|
194
214
|
medianoche: "DARK blue theme \u2014 deep navy surfaces, bright blue primary, gold accent. Surfaces are dark, text is light."
|
|
195
215
|
};
|
|
196
|
-
function buildThemePromptContext(themeName) {
|
|
216
|
+
function buildThemePromptContext(themeName, customColors) {
|
|
197
217
|
const desc = THEME_DESCRIPTIONS[themeName] || themeName;
|
|
198
218
|
const lines = [];
|
|
199
219
|
lines.push(`Active theme: "${themeName}" \u2014 ${desc}`);
|
|
@@ -205,6 +225,19 @@ function buildThemePromptContext(themeName) {
|
|
|
205
225
|
lines.push(` - ${key}: ${hex}`);
|
|
206
226
|
}
|
|
207
227
|
lines.push("Use these values to understand the visual mood. Generate designs that COMPLEMENT these specific colors.");
|
|
228
|
+
return lines.join("\n");
|
|
229
|
+
}
|
|
230
|
+
if (customColors) {
|
|
231
|
+
const present = Object.entries(customColors).filter(
|
|
232
|
+
([, v]) => typeof v === "string" && /^#[0-9a-fA-F]{3,8}$/.test(v)
|
|
233
|
+
);
|
|
234
|
+
if (present.length > 0) {
|
|
235
|
+
lines.push("Actual color values for this CUSTOM theme (user-picked):");
|
|
236
|
+
for (const [key, hex] of present) {
|
|
237
|
+
lines.push(` - ${key}: ${hex}`);
|
|
238
|
+
}
|
|
239
|
+
lines.push("These are the EXACT hex values that the semantic classes resolve to. Use the SEMANTIC CLASS (bg-primary), NEVER the hex (bg-[" + present[0][1] + "]) \u2014 the class system handles the mapping.");
|
|
240
|
+
}
|
|
208
241
|
}
|
|
209
242
|
return lines.join("\n");
|
|
210
243
|
}
|
|
@@ -248,8 +281,12 @@ function buildCustomTheme(colors) {
|
|
|
248
281
|
accent,
|
|
249
282
|
surface,
|
|
250
283
|
"surface-alt": isDarkSurface ? lighten(surface, 20) : darken(surface, 5),
|
|
284
|
+
// surface-deep is the high-contrast dark surface, independent of brand.
|
|
285
|
+
// For light themes: a near-black neutral. For dark themes: even darker than surface.
|
|
286
|
+
"surface-deep": isDarkSurface ? darken(surface, 40) : "#18181b",
|
|
251
287
|
"on-surface": isDarkSurface ? "#f1f5f9" : "#111827",
|
|
252
288
|
"on-surface-muted": isDarkSurface ? "#94a3b8" : "#6b7280",
|
|
289
|
+
"on-surface-deep": isDarkSurface ? "#f1f5f9" : "#fafafa",
|
|
253
290
|
"on-primary": onPrimary,
|
|
254
291
|
"on-secondary": onSecondary,
|
|
255
292
|
"on-accent": onAccent
|
|
@@ -305,4 +342,4 @@ export {
|
|
|
305
342
|
buildThemeCss,
|
|
306
343
|
buildSingleThemeCss
|
|
307
344
|
};
|
|
308
|
-
//# sourceMappingURL=chunk-
|
|
345
|
+
//# sourceMappingURL=chunk-DCAQAHSU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/themes.ts"],"sourcesContent":["export interface LandingTheme {\n id: string;\n label: string;\n colors: {\n primary: string;\n \"primary-light\": string;\n \"primary-dark\": string;\n secondary: string;\n accent: string;\n surface: string;\n /** Slight tint of `surface` (almost-same lightness) — used for cards and\n * alternating row backgrounds on a light page. NOT a dark contrast surface. */\n \"surface-alt\": string;\n /** A high-contrast dark surface that's INDEPENDENT of brand colors. Use\n * for dark cards/footers/sidebars on light themes. Pairs with text-on-surface-deep. */\n \"surface-deep\": string;\n \"on-surface\": string;\n \"on-surface-muted\": string;\n \"on-surface-deep\": string;\n \"on-primary\": string;\n \"on-secondary\": string;\n \"on-accent\": string;\n };\n}\n\nexport const LANDING_THEMES: LandingTheme[] = [\n {\n id: \"minimal\",\n label: \"Minimal\",\n colors: {\n primary: \"#18181b\",\n \"primary-light\": \"#3f3f46\",\n \"primary-dark\": \"#09090b\",\n secondary: \"#71717a\",\n accent: \"#2563eb\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#f4f4f5\",\n \"surface-deep\": \"#18181b\",\n \"on-surface\": \"#18181b\",\n \"on-surface-muted\": \"#71717a\",\n \"on-surface-deep\": \"#fafafa\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"calido\",\n label: \"Cálido\",\n colors: {\n primary: \"#9a3412\",\n \"primary-light\": \"#c2410c\",\n \"primary-dark\": \"#7c2d12\",\n secondary: \"#78716c\",\n accent: \"#d97706\",\n surface: \"#fafaf9\",\n \"surface-alt\": \"#f5f5f4\",\n \"surface-deep\": \"#1c1917\",\n \"on-surface\": \"#1c1917\",\n \"on-surface-muted\": \"#78716c\",\n \"on-surface-deep\": \"#fafaf9\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#111827\",\n },\n },\n {\n id: \"oceano\",\n label: \"Océano\",\n colors: {\n primary: \"#0f4c75\",\n \"primary-light\": \"#1a6fa0\",\n \"primary-dark\": \"#0a3555\",\n secondary: \"#6b7280\",\n accent: \"#0d9488\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#f0fdfa\",\n \"surface-deep\": \"#0f172a\",\n \"on-surface\": \"#0f172a\",\n \"on-surface-muted\": \"#64748b\",\n \"on-surface-deep\": \"#ffffff\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"noche\",\n label: \"Noche\",\n colors: {\n primary: \"#a78bfa\",\n \"primary-light\": \"#c4b5fd\",\n \"primary-dark\": \"#7c3aed\",\n secondary: \"#9ca3af\",\n accent: \"#f472b6\",\n surface: \"#111827\",\n \"surface-alt\": \"#1f2937\",\n \"surface-deep\": \"#030712\",\n \"on-surface\": \"#f9fafb\",\n \"on-surface-muted\": \"#9ca3af\",\n \"on-surface-deep\": \"#f9fafb\",\n \"on-primary\": \"#111827\",\n \"on-secondary\": \"#111827\",\n \"on-accent\": \"#111827\",\n },\n },\n {\n id: \"bosque\",\n label: \"Bosque\",\n colors: {\n primary: \"#16a34a\",\n \"primary-light\": \"#22c55e\",\n \"primary-dark\": \"#15803d\",\n secondary: \"#a3a3a3\",\n accent: \"#f59e0b\",\n surface: \"#0a0a0a\",\n \"surface-alt\": \"#171717\",\n \"surface-deep\": \"#000000\",\n \"on-surface\": \"#fafafa\",\n \"on-surface-muted\": \"#a3a3a3\",\n \"on-surface-deep\": \"#fafafa\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#111827\",\n \"on-accent\": \"#111827\",\n },\n },\n {\n id: \"rosa\",\n label: \"Rosa\",\n colors: {\n primary: \"#be185d\",\n \"primary-light\": \"#db2777\",\n \"primary-dark\": \"#9d174d\",\n secondary: \"#6b7280\",\n accent: \"#8b5cf6\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#fdf2f8\",\n \"surface-deep\": \"#1f2937\",\n \"on-surface\": \"#1f2937\",\n \"on-surface-muted\": \"#6b7280\",\n \"on-surface-deep\": \"#ffffff\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"lavanda\",\n label: \"Lavanda\",\n colors: {\n primary: \"#7c3aed\",\n \"primary-light\": \"#8b5cf6\",\n \"primary-dark\": \"#6d28d9\",\n secondary: \"#a78bfa\",\n accent: \"#ec4899\",\n surface: \"#faf5ff\",\n \"surface-alt\": \"#f3e8ff\",\n \"surface-deep\": \"#1e1b4b\",\n \"on-surface\": \"#1e1b4b\",\n \"on-surface-muted\": \"#6b7280\",\n \"on-surface-deep\": \"#ffffff\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#1e1b4b\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"corporativo\",\n label: \"Corporativo\",\n colors: {\n primary: \"#1e3a5f\",\n \"primary-light\": \"#2d5986\",\n \"primary-dark\": \"#0f2440\",\n secondary: \"#64748b\",\n accent: \"#0ea5e9\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#f1f5f9\",\n \"surface-deep\": \"#0f172a\",\n \"on-surface\": \"#0f172a\",\n \"on-surface-muted\": \"#64748b\",\n \"on-surface-deep\": \"#ffffff\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"esmeralda\",\n label: \"Esmeralda\",\n colors: {\n primary: \"#059669\",\n \"primary-light\": \"#10b981\",\n \"primary-dark\": \"#047857\",\n secondary: \"#6b7280\",\n accent: \"#f97316\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#ecfdf5\",\n \"surface-deep\": \"#064e3b\",\n \"on-surface\": \"#064e3b\",\n \"on-surface-muted\": \"#6b7280\",\n \"on-surface-deep\": \"#ffffff\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"medianoche\",\n label: \"Medianoche\",\n colors: {\n primary: \"#3b82f6\",\n \"primary-light\": \"#60a5fa\",\n \"primary-dark\": \"#2563eb\",\n secondary: \"#94a3b8\",\n accent: \"#facc15\",\n surface: \"#0f172a\",\n \"surface-alt\": \"#1e293b\",\n \"surface-deep\": \"#020617\",\n \"on-surface\": \"#f1f5f9\",\n \"on-surface-muted\": \"#94a3b8\",\n \"on-surface-deep\": \"#f1f5f9\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#0f172a\",\n \"on-accent\": \"#0f172a\",\n },\n },\n];\n\nexport const THEME_DESCRIPTIONS: Record<string, string> = {\n minimal: \"Clean, light, professional — white surfaces, subtle grays, minimal decoration\",\n calido: \"Warm tones — amber/orange primary, cream surfaces, cozy and inviting feel\",\n oceano: \"Cool blue tones — deep ocean blues, clean white surfaces, professional and fresh\",\n noche: \"DARK theme — very dark surfaces, purple/violet accents, moody and modern. Surfaces are dark, text is light.\",\n bosque: \"DARK nature theme — black surfaces, vibrant green primary, amber accents. Surfaces are dark, text is light.\",\n rosa: \"Soft pink/rose tones — delicate, feminine, elegant with light surfaces\",\n lavanda: \"Purple/violet tones — creative, dreamy, soft purple surfaces with pink accent\",\n corporativo: \"Navy blue professional — classic corporate feel, slate grays, sky blue accent\",\n esmeralda: \"Emerald green — fresh, trustworthy, white surfaces with warm orange accent\",\n medianoche: \"DARK blue theme — deep navy surfaces, bright blue primary, gold accent. Surfaces are dark, text is light.\",\n};\n\n/**\n * Build a prompt context string describing the active theme + its hex values.\n * Used by both generate and refine to give the AI concrete color awareness.\n *\n * For built-in themes (modern, brutalist, etc.) the palette is looked up in\n * LANDING_THEMES. For custom themes, pass customColors so the AI sees the\n * user-picked hex values — otherwise the AI generates \"blind\" against custom\n * palettes and tends to emit arbitrary `bg-[#hex]` classes.\n */\nexport function buildThemePromptContext(\n themeName: string,\n customColors?: Partial<CustomColors> | Record<string, string>\n): string {\n const desc = THEME_DESCRIPTIONS[themeName] || themeName;\n const lines: string[] = [];\n lines.push(`Active theme: \"${themeName}\" — ${desc}`);\n lines.push(\"The CSS variables for this theme are already loaded. Just use the semantic classes (bg-primary, text-on-surface, bg-accent, etc.). The theme handles the actual color values.\");\n\n const themeObj = LANDING_THEMES.find(t => t.id === themeName);\n if (themeObj) {\n lines.push(\"Actual color values for this theme:\");\n for (const [key, hex] of Object.entries(themeObj.colors)) {\n lines.push(` - ${key}: ${hex}`);\n }\n lines.push(\"Use these values to understand the visual mood. Generate designs that COMPLEMENT these specific colors.\");\n return lines.join(\"\\n\");\n }\n\n // Custom theme — emit user-picked hex values so the AI knows the actual palette.\n // Without this, the model has zero color context and routinely emits arbitrary\n // `bg-[#hex]` classes (which the sanitizer then has to scrub).\n if (customColors) {\n const present = Object.entries(customColors).filter(\n ([, v]) => typeof v === \"string\" && /^#[0-9a-fA-F]{3,8}$/.test(v as string)\n );\n if (present.length > 0) {\n lines.push(\"Actual color values for this CUSTOM theme (user-picked):\");\n for (const [key, hex] of present) {\n lines.push(` - ${key}: ${hex}`);\n }\n lines.push(\"These are the EXACT hex values that the semantic classes resolve to. Use the SEMANTIC CLASS (bg-primary), NEVER the hex (bg-[\" + (present[0][1] as string) + \"]) — the class system handles the mapping.\");\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport interface CustomColors {\n primary: string;\n secondary?: string;\n accent?: string;\n surface?: string;\n}\n\nfunction parseHex(hex: string) {\n return {\n r: parseInt(hex.slice(1, 3), 16),\n g: parseInt(hex.slice(3, 5), 16),\n b: parseInt(hex.slice(5, 7), 16),\n };\n}\n\nfunction toHex(r: number, g: number, b: number) {\n return `#${[r, g, b].map((c) => Math.max(0, Math.min(255, c)).toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\nfunction luminance(hex: string) {\n const { r, g, b } = parseHex(hex);\n return (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n}\n\nfunction lighten(hex: string, amount = 40) {\n const { r, g, b } = parseHex(hex);\n return toHex(r + amount, g + amount, b + amount);\n}\n\nfunction darken(hex: string, amount = 40) {\n const { r, g, b } = parseHex(hex);\n return toHex(r - amount, g - amount, b - amount);\n}\n\nexport function buildCustomTheme(colors: CustomColors): LandingTheme {\n const { primary, secondary = \"#f59e0b\", accent = \"#06b6d4\", surface = \"#ffffff\" } = colors;\n\n const onPrimary = luminance(primary) > 0.5 ? \"#111827\" : \"#ffffff\";\n const onSecondary = luminance(secondary) > 0.5 ? \"#111827\" : \"#ffffff\";\n const onAccent = luminance(accent) > 0.5 ? \"#111827\" : \"#ffffff\";\n const surfaceLum = luminance(surface);\n const isDarkSurface = surfaceLum < 0.5;\n\n return {\n id: \"custom\",\n label: \"Custom\",\n colors: {\n primary,\n \"primary-light\": lighten(primary),\n \"primary-dark\": darken(primary),\n secondary,\n accent,\n surface,\n \"surface-alt\": isDarkSurface ? lighten(surface, 20) : darken(surface, 5),\n // surface-deep is the high-contrast dark surface, independent of brand.\n // For light themes: a near-black neutral. For dark themes: even darker than surface.\n \"surface-deep\": isDarkSurface ? darken(surface, 40) : \"#18181b\",\n \"on-surface\": isDarkSurface ? \"#f1f5f9\" : \"#111827\",\n \"on-surface-muted\": isDarkSurface ? \"#94a3b8\" : \"#6b7280\",\n \"on-surface-deep\": isDarkSurface ? \"#f1f5f9\" : \"#fafafa\",\n \"on-primary\": onPrimary,\n \"on-secondary\": onSecondary,\n \"on-accent\": onAccent,\n },\n };\n}\n\nexport function buildCustomThemeCss(colors: CustomColors): string {\n const theme = buildCustomTheme(colors);\n return `[data-theme=\"custom\"] {\\n${buildCssVars(theme.colors)}\\n}`;\n}\n\n/** CSS custom properties for a theme */\nfunction buildCssVars(colors: LandingTheme[\"colors\"]): string {\n return Object.entries(colors)\n .map(([k, v]) => ` --color-${k}: ${v};`)\n .join(\"\\n\");\n}\n\n/** Build the tailwind.config JS object string for TW v3 CDN */\nfunction buildTailwindConfig(): string {\n const colorEntries = Object.keys(LANDING_THEMES[0].colors)\n .map((k) => ` '${k}': 'var(--color-${k})'`)\n .join(\",\\n\");\n\n return `{\n theme: {\n extend: {\n colors: {\n${colorEntries}\n }\n }\n }\n }`;\n}\n\nexport function buildThemeCss(): { css: string; tailwindConfig: string } {\n const defaultTheme = LANDING_THEMES[0];\n\n const overrides = LANDING_THEMES.slice(1)\n .map((t) => `[data-theme=\"${t.id}\"] {\\n${buildCssVars(t.colors)}\\n}`)\n .join(\"\\n\\n\");\n\n const css = `:root {\\n${buildCssVars(defaultTheme.colors)}\\n}\\n\\n${overrides}`;\n return { css, tailwindConfig: buildTailwindConfig() };\n}\n\nexport function buildSingleThemeCss(themeId: string): { css: string; tailwindConfig: string } {\n const theme = LANDING_THEMES.find((t) => t.id === themeId) || LANDING_THEMES[0];\n const css = `:root {\\n${buildCssVars(theme.colors)}\\n}`;\n return { css, tailwindConfig: buildTailwindConfig() };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
enrichImages,
|
|
4
4
|
resolveModel,
|
|
5
5
|
sanitizeSemanticColors
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-H2YYYKUI.js";
|
|
7
7
|
import {
|
|
8
8
|
buildThemePromptContext
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DCAQAHSU.js";
|
|
10
10
|
|
|
11
11
|
// src/refine.ts
|
|
12
12
|
import { streamText } from "ai";
|
|
@@ -22,8 +22,10 @@ RULES:
|
|
|
22
22
|
- Return raw HTML only \u2014 no markdown fences, no explanations
|
|
23
23
|
|
|
24
24
|
COLOR SYSTEM \u2014 CRITICAL:
|
|
25
|
-
- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted, bg-secondary, text-secondary, bg-accent, text-accent
|
|
25
|
+
- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, bg-surface-deep, text-on-surface, text-on-surface-muted, text-on-surface-deep, bg-secondary, text-secondary, bg-accent, text-accent
|
|
26
|
+
- POLARITY (critical): bg-surface-alt = LIGHT TINT of surface (cards on light pages \u2014 pair with text-on-surface). bg-surface-deep = HIGH-CONTRAST DARK surface (dark cards/footers on light themes \u2014 pair with text-on-surface-deep). bg-secondary = the brand's secondary color. NEVER use bg-surface-alt + text-on-primary for "dark cards" \u2014 that produces invisible white-on-white. For dark cards use bg-surface-deep, bg-primary, or bg-secondary.
|
|
26
27
|
- NEVER use hardcoded colors: NO bg-gray-*, bg-black, bg-white, text-gray-*, text-black, text-white, etc.
|
|
28
|
+
- NEVER use Tailwind JIT arbitrary value syntax for colors: bg-[#abc123], text-[#fff], from-[#hex], border-[#hex], ring-[#hex], shadow-[#hex] are STRICTLY FORBIDDEN. Tailwind accepts them but they bypass the theme/brandkit system and break when the user swaps colors. The semantic class IS the brand color \u2014 use bg-primary, not bg-[#userhex].
|
|
27
29
|
- The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.
|
|
28
30
|
- ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary \u2014 invisible on primary backgrounds).
|
|
29
31
|
- CONTRAST RULE: on bg-primary or bg-primary-dark \u2192 use ONLY text-on-primary. On bg-surface or bg-surface-alt \u2192 use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary \u2014 they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface.
|
|
@@ -74,7 +76,7 @@ async function refineLanding(options) {
|
|
|
74
76
|
onChunk,
|
|
75
77
|
onDone,
|
|
76
78
|
onError,
|
|
77
|
-
themeColors
|
|
79
|
+
themeColors,
|
|
78
80
|
themeName,
|
|
79
81
|
brandKit
|
|
80
82
|
} = options;
|
|
@@ -112,11 +114,11 @@ Return the updated HTML.`
|
|
|
112
114
|
});
|
|
113
115
|
}
|
|
114
116
|
let finalSystem = systemPrompt + currentDateLine();
|
|
115
|
-
if (themeName
|
|
117
|
+
if (themeName) {
|
|
116
118
|
finalSystem += `
|
|
117
119
|
|
|
118
120
|
## Active Theme
|
|
119
|
-
${buildThemePromptContext(themeName)}`;
|
|
121
|
+
${buildThemePromptContext(themeName, themeColors)}`;
|
|
120
122
|
}
|
|
121
123
|
if (brandKit) {
|
|
122
124
|
const bkLines = [];
|
|
@@ -145,7 +147,7 @@ ${bkLines.join("\n")}`;
|
|
|
145
147
|
if (html.startsWith("```")) {
|
|
146
148
|
html = html.replace(/^```(?:html|xml)?\s*/, "").replace(/\s*```$/, "");
|
|
147
149
|
}
|
|
148
|
-
html = sanitizeSemanticColors(html);
|
|
150
|
+
html = sanitizeSemanticColors(html, themeColors);
|
|
149
151
|
html = await enrichImages(html, { pexelsApiKey, openaiApiKey, persistImage });
|
|
150
152
|
onDone?.(html);
|
|
151
153
|
return html;
|
|
@@ -161,4 +163,4 @@ export {
|
|
|
161
163
|
extractSectionDescription,
|
|
162
164
|
refineLanding
|
|
163
165
|
};
|
|
164
|
-
//# sourceMappingURL=chunk-
|
|
166
|
+
//# sourceMappingURL=chunk-EIZRTLU6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/refine.ts"],"sourcesContent":["import { streamText } from \"ai\";\nimport { enrichImages } from \"./images/enrichImages\";\nimport { sanitizeSemanticColors } from \"./sanitizeColors\";\nimport { resolveModel, currentDateLine } from \"./streamCore\";\nimport { buildThemePromptContext } from \"./themes\";\n\nexport const REFINE_SYSTEM = `You are an expert HTML/Tailwind CSS developer. You receive the current HTML of a landing page section and a user instruction.\n\nRULES:\n- Return ONLY the modified HTML — no full page, no <html>/<head>/<body> tags\n- Use Tailwind CSS classes (CDN loaded)\n- You may use inline styles for specific adjustments\n- Images: use data-image-query=\"english search query\" for new images\n- Keep all text in its original language unless asked to translate\n- Be creative — don't just make minimal changes, improve the design\n- Return raw HTML only — no markdown fences, no explanations\n\nCOLOR SYSTEM — CRITICAL:\n- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, bg-surface-deep, text-on-surface, text-on-surface-muted, text-on-surface-deep, bg-secondary, text-secondary, bg-accent, text-accent\n- POLARITY (critical): bg-surface-alt = LIGHT TINT of surface (cards on light pages — pair with text-on-surface). bg-surface-deep = HIGH-CONTRAST DARK surface (dark cards/footers on light themes — pair with text-on-surface-deep). bg-secondary = the brand's secondary color. NEVER use bg-surface-alt + text-on-primary for \"dark cards\" — that produces invisible white-on-white. For dark cards use bg-surface-deep, bg-primary, or bg-secondary.\n- NEVER use hardcoded colors: NO bg-gray-*, bg-black, bg-white, text-gray-*, text-black, text-white, etc.\n- NEVER use Tailwind JIT arbitrary value syntax for colors: bg-[#abc123], text-[#fff], from-[#hex], border-[#hex], ring-[#hex], shadow-[#hex] are STRICTLY FORBIDDEN. Tailwind accepts them but they bypass the theme/brandkit system and break when the user swaps colors. The semantic class IS the brand color — use bg-primary, not bg-[#userhex].\n- The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.\n- ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary — invisible on primary backgrounds).\n- CONTRAST RULE: on bg-primary or bg-primary-dark → use ONLY text-on-primary. On bg-surface or bg-surface-alt → use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary — they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface.\n- Use bg-accent, bg-secondary, text-accent, text-secondary for visual variety — not everything should be primary.\n\nIMAGE OVERLAYS:\n- When placing text over images, ALWAYS add a gradient overlay for readability\n- Pattern: <div class=\"relative\"><img .../><div class=\"absolute inset-0 bg-gradient-to-r from-primary/80 to-transparent\"></div><div class=\"relative z-10\">...text...</div></div>\n- NEVER place text directly on images without an overlay\n\nTAILWIND v3 NOTES:\n- Standard Tailwind v3 classes (shadow-sm, shadow-md, rounded-md, etc.)\n- Borders: border + border-gray-200 for visible borders`;\n\n/**\n * Extract a text description from HTML for variant generation.\n * Instead of sending full HTML to the model, we send a content summary\n * so the model generates a completely new layout rather than tweaking colors.\n */\nexport function extractSectionDescription(html: string, label?: string): { content: string; layoutHint: string } {\n // Extract headings\n const headings = [...html.matchAll(/<h[1-6][^>]*>([\\s\\S]*?)<\\/h[1-6]>/gi)]\n .map(m => m[1].replace(/<[^>]+>/g, \"\").trim())\n .filter(Boolean);\n\n // Extract paragraphs\n const paragraphs = [...html.matchAll(/<p[^>]*>([\\s\\S]*?)<\\/p>/gi)]\n .map(m => m[1].replace(/<[^>]+>/g, \"\").trim())\n .filter(Boolean);\n\n // Extract button/CTA text\n const buttons = [...html.matchAll(/<(?:button|a)[^>]*>([\\s\\S]*?)<\\/(?:button|a)>/gi)]\n .map(m => m[1].replace(/<[^>]+>/g, \"\").trim())\n .filter(t => t.length > 0 && t.length < 60);\n\n // Count items (cards, list items, grid children)\n const listItems = (html.match(/<li[\\s>]/gi) || []).length;\n const gridMatch = html.match(/grid-cols-(\\d)/);\n const gridCols = gridMatch ? parseInt(gridMatch[1]) : 0;\n\n // Detect layout patterns for negative prompt\n const layouts: string[] = [];\n if (html.includes(\"grid\")) layouts.push(\"grid\");\n if (html.includes(\"flex-col\")) layouts.push(\"vertical-stack\");\n if (html.includes(\"flex-row\") || html.includes(\"md:flex-row\")) layouts.push(\"horizontal-flex\");\n if (html.includes(\"text-center\") && !html.includes(\"text-left\")) layouts.push(\"centered\");\n if (gridCols) layouts.push(`${gridCols}-column-grid`);\n\n const content = [\n label ? `Section: ${label}` : \"\",\n headings.length ? `Headings: ${headings.join(\" | \")}` : \"\",\n paragraphs.length ? `Text: ${paragraphs.slice(0, 3).join(\" \")}` : \"\",\n buttons.length ? `CTAs: ${buttons.join(\", \")}` : \"\",\n listItems > 0 ? `${listItems} list/card items` : \"\",\n ].filter(Boolean).join(\"\\n\");\n\n return { content, layoutHint: layouts.join(\", \") };\n}\n\nexport interface RefineOptions {\n /** Anthropic API key. Falls back to ANTHROPIC_API_KEY env var */\n anthropicApiKey?: string;\n /** OpenAI API key. If provided, uses GPT-4o-mini instead of Claude */\n openaiApiKey?: string;\n /** Current HTML of the section being refined */\n currentHtml: string;\n /** User instruction for refinement */\n instruction: string;\n /** Reference image (base64 data URI) for vision-based refinement */\n referenceImage?: string;\n /** When true, generates a completely new layout variant instead of refining */\n isVariant?: boolean;\n /** Custom system prompt (overrides default REFINE_SYSTEM) */\n systemPrompt?: string;\n /** Model ID (default: gpt-4o-mini/gpt-4o for OpenAI, claude-haiku/claude-sonnet for Anthropic) */\n model?: string;\n /** Pexels API key for image enrichment. Falls back to PEXELS_API_KEY env var */\n pexelsApiKey?: string;\n /** Called with temp DALL-E URL + query, returns permanent URL. Use to persist to S3/etc. */\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n /** Called with accumulated HTML as it streams */\n onChunk?: (html: string) => void;\n /** Called when refinement is complete with final enriched HTML */\n onDone?: (html: string) => void;\n /** Called on error */\n onError?: (error: Error) => void;\n /** Custom-theme palette (hex map: primary, secondary, accent, surface).\n * Required when themeName === \"custom\"; optional otherwise (built-in themes\n * resolve their hex values via LANDING_THEMES). Used both for prompt context\n * AND for theme-aware sanitization of arbitrary `bg-[#hex]` classes. */\n themeColors?: Record<string, string>;\n /** Theme name (e.g. \"minimal\", \"noche\", \"custom\") — tells the AI the design mood */\n themeName?: string;\n /** Brand kit info for AI context */\n brandKit?: {\n fonts?: { heading?: string; body?: string };\n mood?: string;\n logoUrl?: string;\n };\n}\n\n/**\n * Refine a landing page section with streaming AI.\n * Returns the final enriched HTML.\n */\nexport async function refineLanding(options: RefineOptions): Promise<string> {\n const {\n anthropicApiKey,\n openaiApiKey: _openaiApiKey,\n currentHtml,\n instruction,\n referenceImage,\n isVariant,\n systemPrompt = REFINE_SYSTEM,\n model: modelId,\n pexelsApiKey,\n persistImage,\n onChunk,\n onDone,\n onError,\n themeColors,\n themeName,\n brandKit,\n } = options;\n\n const openaiApiKey = _openaiApiKey || process.env.OPENAI_API_KEY;\n const useVision = !!referenceImage;\n const defaultOpenai = useVision ? \"gpt-4o\" : \"gpt-4o-mini\";\n const defaultAnthropic = useVision ? \"claude-sonnet-4-6\" : \"claude-haiku-4-5-20251001\";\n const model = await resolveModel({ openaiApiKey, anthropicApiKey, modelId, defaultOpenai, defaultAnthropic });\n\n // Build content (supports multimodal with reference image)\n const content: any[] = [];\n if (referenceImage) {\n content.push({ type: \"image\", image: referenceImage });\n }\n\n if (isVariant && !referenceImage) {\n // Variant mode: send description instead of HTML to force creative layout\n const { content: desc, layoutHint } = extractSectionDescription(currentHtml);\n content.push({\n type: \"text\",\n text: `Generate a COMPLETELY NEW section with the following content. Create an original, creative layout.\\n\\nContent:\\n${desc}\\n\\n${layoutHint ? `DO NOT use these layout patterns (the current design already uses them): ${layoutHint}. Choose a radically different structure.` : \"\"}\\n\\nReturn ONLY the <section>...</section> HTML with Tailwind classes.`,\n });\n } else {\n content.push({\n type: \"text\",\n text: `Current HTML:\\n${currentHtml}\\n\\nInstruction: ${instruction}\\n\\nReturn the updated HTML.`,\n });\n }\n\n // Inject theme + brand kit context\n let finalSystem = systemPrompt + currentDateLine();\n\n if (themeName) {\n // Custom themes get their palette from themeColors; built-in themes look it up by name.\n finalSystem += `\\n\\n## Active Theme\\n${buildThemePromptContext(themeName, themeColors)}`;\n }\n\n if (brandKit) {\n const bkLines: string[] = [];\n if (brandKit.fonts?.heading) bkLines.push(`- Heading font: use font-family: '${brandKit.fonts.heading}' via inline style on h1-h6`);\n if (brandKit.fonts?.body) bkLines.push(`- Body font: use font-family: '${brandKit.fonts.body}' via inline style on p, li, span`);\n if (brandKit.mood) bkLines.push(`- Design mood: ${brandKit.mood} — adapt spacing, imagery style, and visual weight to match`);\n if (brandKit.logoUrl) bkLines.push(`- Brand logo: include <img src=\"${brandKit.logoUrl}\" alt=\"Logo\" class=\"h-8 w-auto\" /> in the navbar/hero area`);\n if (bkLines.length) finalSystem += `\\n\\n## Brand Kit\\n${bkLines.join(\"\\n\")}`;\n }\n\n const result = streamText({\n model,\n system: finalSystem,\n messages: [{ role: \"user\", content }],\n ...(isVariant && !referenceImage ? { temperature: 1.2 } : {}),\n });\n\n try {\n let accumulated = \"\";\n\n for await (const chunk of result.textStream) {\n accumulated += chunk;\n onChunk?.(accumulated);\n }\n\n // Clean up markdown fences if present\n let html = accumulated.trim();\n if (html.startsWith(\"```\")) {\n html = html.replace(/^```(?:html|xml)?\\s*/, \"\").replace(/\\s*```$/, \"\");\n }\n\n // Sanitize hardcoded colors to semantic classes. themeColors lets the\n // sanitizer map arbitrary `bg-[#hex]` to the nearest semantic role using\n // RGB distance against the active palette (instead of HSL hue fallback).\n html = sanitizeSemanticColors(html, themeColors);\n\n // Enrich images (DALL-E if openaiApiKey, otherwise Pexels)\n html = await enrichImages(html, { pexelsApiKey, openaiApiKey, persistImage });\n\n onDone?.(html);\n return html;\n } catch (err: any) {\n const error = err instanceof Error ? err : new Error(err?.message || \"Refine failed\");\n onError?.(error);\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildPreviewHtml
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7MGKYJTI.js";
|
|
4
4
|
import {
|
|
5
5
|
LANDING_THEMES
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DCAQAHSU.js";
|
|
7
7
|
|
|
8
8
|
// src/components/Canvas.tsx
|
|
9
9
|
import { useRef, useEffect, useCallback, useState, forwardRef, useImperativeHandle } from "react";
|
|
@@ -1368,4 +1368,4 @@ export {
|
|
|
1368
1368
|
ViewportToggle,
|
|
1369
1369
|
useUndoStack
|
|
1370
1370
|
};
|
|
1371
|
-
//# sourceMappingURL=chunk-
|
|
1371
|
+
//# sourceMappingURL=chunk-EP65R6DE.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildCustomTheme,
|
|
3
3
|
buildSingleThemeCss
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DCAQAHSU.js";
|
|
5
5
|
|
|
6
6
|
// src/buildHtmlV4.ts
|
|
7
7
|
function buildDeployHtmlV4(sections, opts) {
|
|
@@ -64,4 +64,4 @@ ${branding}
|
|
|
64
64
|
export {
|
|
65
65
|
buildDeployHtmlV4
|
|
66
66
|
};
|
|
67
|
-
//# sourceMappingURL=chunk-
|
|
67
|
+
//# sourceMappingURL=chunk-ETWQS7IQ.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GAMMA_LAYOUTS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ULAQDD23.js";
|
|
4
4
|
import {
|
|
5
5
|
addLoadingPlaceholders,
|
|
6
6
|
addSvgLoadingPlaceholders,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
resolveModel,
|
|
14
14
|
sanitizeSemanticColors,
|
|
15
15
|
streamGenerate
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-H2YYYKUI.js";
|
|
17
17
|
|
|
18
18
|
// src/generateDocument.ts
|
|
19
19
|
import { generateObject, streamText } from "ai";
|
|
@@ -87,10 +87,17 @@ RULES:
|
|
|
87
87
|
- Sections can have ANY background \u2014 full-bleed color, gradients, or white. Not limited to white paper.
|
|
88
88
|
|
|
89
89
|
STRICT PROHIBITIONS:
|
|
90
|
+
0. **NO ARBITRARY HEX COLORS** \u2014 Tailwind JIT arbitrary value syntax for colors is STRICTLY FORBIDDEN: bg-[#abc123], text-[#fff], from-[#hex], to-[#hex], via-[#hex], border-[#hex], ring-[#hex], shadow-[#hex] are ALL banned. Tailwind accepts them but they bypass the theme/brandkit system and break when the user swaps colors. Even if a hex value is mentioned in this prompt, NEVER write it as a class \u2014 use the semantic class (bg-primary, text-on-surface, etc.) which resolves to the right hex automatically.
|
|
90
91
|
1. **NO EMOJI** \u2014 Never use emoji characters (\u{1F680}\u274C\u2705\u{1F4CA} etc.). Instead use inline SVG icons or colored divs. For bullet decorators use small colored circles (<span class="w-2 h-2 rounded-full bg-primary inline-block"></span>) or simple SVG.
|
|
91
92
|
2. **NO Chart.js / NO JavaScript** \u2014 Never reference Chart.js, canvas, or any JS library. For data visualization use pure CSS: progress bars (div with percentage width + bg-primary), horizontal bars, styled tables with colored cells. Never use <canvas> or <script>.
|
|
92
93
|
3. **NO buttons or CTAs** \u2014 This is a ${isWeb ? "document" : "print document"}, not a ${isWeb ? "landing page" : "web page"}. No "Contactar", "Ver m\xE1s", "Comprar" buttons. Use text with contact info instead.
|
|
93
|
-
4. **CONTRAST IS MANDATORY** \u2014
|
|
94
|
+
4. **CONTRAST IS MANDATORY** \u2014 Each bg has ONE valid text family:
|
|
95
|
+
\u2022 bg-primary / bg-primary-dark / dark gradients \u2192 text-on-primary
|
|
96
|
+
\u2022 bg-secondary \u2192 text-on-secondary
|
|
97
|
+
\u2022 bg-accent \u2192 text-on-accent
|
|
98
|
+
\u2022 bg-surface or bg-surface-alt \u2192 text-on-surface, text-on-surface-muted (DO NOT use text-on-primary here \u2014 surface-alt is a LIGHT TINT, not dark)
|
|
99
|
+
\u2022 bg-surface-deep \u2192 text-on-surface-deep (a HIGH-CONTRAST DARK surface; light text required)
|
|
100
|
+
Common mistake: pairing bg-surface-alt with text-on-primary thinking surface-alt is "the dark card variant" \u2014 it's a LIGHT tint and produces invisible white-on-white. For dark cards use bg-surface-deep, bg-primary, or bg-secondary. NEVER use dark text on dark backgrounds or light text on light backgrounds.
|
|
94
101
|
5. **Max 2 font weights per page** \u2014 Pick 2 (e.g. font-semibold + font-normal, or font-bold + font-light). Don't mix 4-5 weights.
|
|
95
102
|
6. **Generous whitespace** \u2014 Don't fill every centimeter. Leave breathing room. Use py-8, py-12, gap-6, gap-8 liberally. Less content per page = more professional.
|
|
96
103
|
|
|
@@ -142,8 +149,9 @@ CSS PROGRESS BARS \u2014 use this pattern for data visualization:
|
|
|
142
149
|
|
|
143
150
|
COLOR SYSTEM \u2014 use semantic classes:
|
|
144
151
|
- bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary
|
|
145
|
-
- bg-surface, bg-surface-alt,
|
|
146
|
-
-
|
|
152
|
+
- bg-surface (page bg), bg-surface-alt (LIGHT TINT for cards/rows \u2014 NOT dark), bg-surface-deep (HIGH-CONTRAST DARK surface for dark cards on light themes)
|
|
153
|
+
- text-on-surface, text-on-surface-muted, text-on-surface-deep (light text \u2014 for use on bg-surface-deep)
|
|
154
|
+
- bg-secondary (brand's secondary color), text-secondary, bg-accent, text-accent
|
|
147
155
|
- Cover pages should use bold full-bleed backgrounds (bg-primary, gradients from-primary to-primary-dark)
|
|
148
156
|
- CONTRAST: bg-primary/bg-primary-dark/bg-secondary \u2192 text-white or text-on-primary. White/bg-surface \u2192 text-gray-900 or text-on-surface
|
|
149
157
|
|
|
@@ -289,10 +297,11 @@ TYPOGRAPHY: Use these Google Fonts via <link href="${fontsUrl}" rel="stylesheet"
|
|
|
289
297
|
- Body: font-family: '${direction.bodyFont}', sans-serif (via inline style)
|
|
290
298
|
COLORS \u2014 use ONLY semantic Tailwind classes (the editor injects CSS variables that resolve these):
|
|
291
299
|
- bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary
|
|
292
|
-
- bg-surface, bg-surface-alt,
|
|
293
|
-
-
|
|
294
|
-
-
|
|
295
|
-
-
|
|
300
|
+
- bg-surface (page bg), bg-surface-alt (LIGHT TINT for cards/rows \u2014 NOT dark), bg-surface-deep (HIGH-CONTRAST DARK surface for dark cards on light themes)
|
|
301
|
+
- text-on-surface, text-on-surface-muted, text-on-surface-deep (light text \u2014 for use on bg-surface-deep)
|
|
302
|
+
- bg-secondary (brand's secondary color), text-secondary, bg-accent, text-accent
|
|
303
|
+
- NEVER use hardcoded hex colors like bg-[#xxx], text-[#xxx], from-[#xxx], border-[#xxx] \u2014 these are STRICTLY FORBIDDEN. Even when a hex value is mentioned below, NEVER write it as a class. Tailwind JIT accepts arbitrary values but they bypass the theme system and break on brandkit swaps.
|
|
304
|
+
- The active palette resolves bg-primary \u2192 ${direction.colors.primary}, bg-accent \u2192 ${direction.colors.accent}, bg-surface \u2192 ${direction.colors.surface}. Use the SEMANTIC CLASS (bg-primary), NEVER the hex (bg-[${direction.colors.primary}]).
|
|
296
305
|
Mood: ${direction.mood}
|
|
297
306
|
Layout approach: ${direction.layoutHint}${appendDirectionExtras(direction)}
|
|
298
307
|
IMPORTANT: Apply inline style="font-family: '${direction.headingFont}'" on ALL heading elements and style="font-family: '${direction.bodyFont}'" on ALL body text elements. Include the Google Fonts <link> tag inside the FIRST <section> only.`;
|
|
@@ -320,10 +329,17 @@ Use this exact <img> tag with this exact src URL \u2014 do NOT invent a differen
|
|
|
320
329
|
text: `Create a professional document for: ${safePrompt}${logoInstruction}${directionInstruction}${extra}${DOCUMENT_PROMPT_SUFFIX}`
|
|
321
330
|
});
|
|
322
331
|
}
|
|
332
|
+
const themeColors = direction ? {
|
|
333
|
+
primary: direction.colors.primary,
|
|
334
|
+
accent: direction.colors.accent,
|
|
335
|
+
surface: direction.colors.surface,
|
|
336
|
+
...direction.colors
|
|
337
|
+
} : void 0;
|
|
323
338
|
return streamGenerate({
|
|
324
339
|
...rest,
|
|
325
340
|
systemPrompt: DOCUMENT_SYSTEM_PROMPT,
|
|
326
|
-
userContent: content
|
|
341
|
+
userContent: content,
|
|
342
|
+
themeColors
|
|
327
343
|
});
|
|
328
344
|
}
|
|
329
345
|
var DocumentOutlineSchema = z.object({
|
|
@@ -365,10 +381,11 @@ TYPOGRAPHY: Use these Google Fonts via <link href="${fontsUrl}" rel="stylesheet"
|
|
|
365
381
|
- Body: font-family: '${direction.bodyFont}', sans-serif (via inline style)
|
|
366
382
|
COLORS \u2014 use ONLY semantic Tailwind classes (the editor injects CSS variables that resolve these):
|
|
367
383
|
- bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary
|
|
368
|
-
- bg-surface, bg-surface-alt,
|
|
369
|
-
-
|
|
370
|
-
-
|
|
371
|
-
-
|
|
384
|
+
- bg-surface (page bg), bg-surface-alt (LIGHT TINT for cards/rows \u2014 NOT dark), bg-surface-deep (HIGH-CONTRAST DARK surface for dark cards on light themes)
|
|
385
|
+
- text-on-surface, text-on-surface-muted, text-on-surface-deep (light text \u2014 for use on bg-surface-deep)
|
|
386
|
+
- bg-secondary (brand's secondary color), text-secondary, bg-accent, text-accent
|
|
387
|
+
- NEVER use hardcoded hex colors like bg-[#xxx], text-[#xxx], from-[#xxx], border-[#xxx] \u2014 these are STRICTLY FORBIDDEN. Even when a hex value is mentioned below, NEVER write it as a class. Tailwind JIT accepts arbitrary values but they bypass the theme system and break on brandkit swaps.
|
|
388
|
+
- The active palette resolves bg-primary \u2192 ${direction.colors.primary}, bg-accent \u2192 ${direction.colors.accent}, bg-surface \u2192 ${direction.colors.surface}. Use the SEMANTIC CLASS (bg-primary), NEVER the hex (bg-[${direction.colors.primary}]).
|
|
372
389
|
Mood: ${direction.mood}
|
|
373
390
|
Layout approach: ${direction.layoutHint}${appendDirectionExtras(direction)}
|
|
374
391
|
IMPORTANT: Apply inline style="font-family: '${direction.headingFont}'" on ALL heading elements and style="font-family: '${direction.bodyFont}'" on ALL body text elements. Include the Google Fonts <link> tag inside the FIRST <section> only.`;
|
|
@@ -534,10 +551,16 @@ OUTPUT: A single JSON object on ONE line, no markdown fences:
|
|
|
534
551
|
const [objects] = extractJsonObjects(cleaned);
|
|
535
552
|
const obj = objects[0];
|
|
536
553
|
if (!obj?.html) throw new Error(`No valid HTML output for page ${page.pageNumber}`);
|
|
554
|
+
const themeColors = direction ? {
|
|
555
|
+
primary: direction.colors.primary,
|
|
556
|
+
accent: direction.colors.accent,
|
|
557
|
+
surface: direction.colors.surface,
|
|
558
|
+
...direction.colors
|
|
559
|
+
} : void 0;
|
|
537
560
|
const section = {
|
|
538
561
|
id: nanoid(8),
|
|
539
562
|
order: pageIdx,
|
|
540
|
-
html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html))),
|
|
563
|
+
html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html)), themeColors),
|
|
541
564
|
label: obj.label || page.label
|
|
542
565
|
};
|
|
543
566
|
onPageComplete?.(pageIdx, section);
|
|
@@ -607,4 +630,4 @@ export {
|
|
|
607
630
|
generateDocument,
|
|
608
631
|
generateDocumentParallel
|
|
609
632
|
};
|
|
610
|
-
//# sourceMappingURL=chunk-
|
|
633
|
+
//# sourceMappingURL=chunk-GL74S2H4.js.map
|