canvas-ui-sdk 0.3.1 → 0.3.3
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/index.js +186 -138
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -27268,14 +27268,185 @@ function InputSizeGroup({
|
|
|
27268
27268
|
}
|
|
27269
27269
|
);
|
|
27270
27270
|
}
|
|
27271
|
+
|
|
27272
|
+
// src/components/theme-drawer/utils/generate-bake-prompt.ts
|
|
27273
|
+
var BASELINE_FONTS = /* @__PURE__ */ new Set(["Inter", "Geist", "Geist Mono"]);
|
|
27274
|
+
function fontToImportName(name) {
|
|
27275
|
+
return name.replace(/ /g, "_");
|
|
27276
|
+
}
|
|
27277
|
+
function fontToVarName(name) {
|
|
27278
|
+
return `--font-${name.toLowerCase().replace(/ /g, "-")}`;
|
|
27279
|
+
}
|
|
27280
|
+
function fontToInstanceName(name) {
|
|
27281
|
+
const words = name.split(/\s+/);
|
|
27282
|
+
return words.map(
|
|
27283
|
+
(w, i) => i === 0 ? w.toLowerCase() : w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()
|
|
27284
|
+
).join("");
|
|
27285
|
+
}
|
|
27286
|
+
function generateBakePrompt(theme) {
|
|
27287
|
+
const overrides = theme.overrides;
|
|
27288
|
+
const rootVars = [];
|
|
27289
|
+
const bodyVars = [];
|
|
27290
|
+
const fontVarsToRemoveFromRoot = [];
|
|
27291
|
+
for (const [name, value] of Object.entries(overrides)) {
|
|
27292
|
+
if (name.startsWith("--canvas-")) {
|
|
27293
|
+
rootVars.push([name, value]);
|
|
27294
|
+
} else if (name === "--typo-global-font") {
|
|
27295
|
+
const cssVar = fontToVarName(value);
|
|
27296
|
+
bodyVars.push([name, `var(${cssVar}), "${value}", sans-serif`]);
|
|
27297
|
+
} else if (/^--typo-.*-font$/.test(name)) {
|
|
27298
|
+
bodyVars.push([name, `"${value}", sans-serif`]);
|
|
27299
|
+
fontVarsToRemoveFromRoot.push(name);
|
|
27300
|
+
} else {
|
|
27301
|
+
bodyVars.push([name, value]);
|
|
27302
|
+
}
|
|
27303
|
+
}
|
|
27304
|
+
rootVars.sort(([a], [b]) => a.localeCompare(b));
|
|
27305
|
+
bodyVars.sort(([a], [b]) => a.localeCompare(b));
|
|
27306
|
+
fontVarsToRemoveFromRoot.sort();
|
|
27307
|
+
const fontNames = /* @__PURE__ */ new Set();
|
|
27308
|
+
for (const [name, value] of Object.entries(overrides)) {
|
|
27309
|
+
if ((name === "--typo-global-font" || /^--typo-.*-font$/.test(name)) && value && !BASELINE_FONTS.has(value)) {
|
|
27310
|
+
fontNames.add(value);
|
|
27311
|
+
}
|
|
27312
|
+
}
|
|
27313
|
+
const newFonts = Array.from(fontNames).sort();
|
|
27314
|
+
const sections = [];
|
|
27315
|
+
let sectionNum = 0;
|
|
27316
|
+
if (rootVars.length > 0 || bodyVars.length > 0) {
|
|
27317
|
+
sectionNum++;
|
|
27318
|
+
const lines = [];
|
|
27319
|
+
lines.push(`## ${sectionNum}. Update \`src/app/globals.css\``);
|
|
27320
|
+
lines.push("");
|
|
27321
|
+
if (rootVars.length > 0) {
|
|
27322
|
+
lines.push("In the `:root` block, update these variables:");
|
|
27323
|
+
lines.push("");
|
|
27324
|
+
lines.push("```css");
|
|
27325
|
+
for (const [name, value] of rootVars) {
|
|
27326
|
+
lines.push(`${name}: ${value};`);
|
|
27327
|
+
}
|
|
27328
|
+
lines.push("```");
|
|
27329
|
+
lines.push("");
|
|
27330
|
+
}
|
|
27331
|
+
if (bodyVars.length > 0) {
|
|
27332
|
+
lines.push(
|
|
27333
|
+
"In the `body` block inside `@layer base`, add these CSS variable declarations (before the existing `font-family` rule):"
|
|
27334
|
+
);
|
|
27335
|
+
lines.push("");
|
|
27336
|
+
lines.push("```css");
|
|
27337
|
+
for (const [name, value] of bodyVars) {
|
|
27338
|
+
lines.push(`${name}: ${value};`);
|
|
27339
|
+
}
|
|
27340
|
+
lines.push("```");
|
|
27341
|
+
lines.push("");
|
|
27342
|
+
}
|
|
27343
|
+
if (fontVarsToRemoveFromRoot.length > 0) {
|
|
27344
|
+
lines.push(
|
|
27345
|
+
"Remove these lines from the `:root` block (they are now overridden in `body`):"
|
|
27346
|
+
);
|
|
27347
|
+
lines.push("");
|
|
27348
|
+
for (const name of fontVarsToRemoveFromRoot) {
|
|
27349
|
+
lines.push(`- \`${name}: var(--typo-global-font);\``);
|
|
27350
|
+
}
|
|
27351
|
+
lines.push("");
|
|
27352
|
+
}
|
|
27353
|
+
sections.push(lines.join("\n"));
|
|
27354
|
+
}
|
|
27355
|
+
if (newFonts.length > 0) {
|
|
27356
|
+
sectionNum++;
|
|
27357
|
+
const lines = [];
|
|
27358
|
+
lines.push(`## ${sectionNum}. Update \`src/app/layout.tsx\``);
|
|
27359
|
+
lines.push("");
|
|
27360
|
+
const allImports = ["Inter", ...newFonts.map(fontToImportName)];
|
|
27361
|
+
lines.push("Update the `next/font/google` import:");
|
|
27362
|
+
lines.push("");
|
|
27363
|
+
lines.push("```typescript");
|
|
27364
|
+
lines.push(`import { ${allImports.join(", ")} } from "next/font/google";`);
|
|
27365
|
+
lines.push("```");
|
|
27366
|
+
lines.push("");
|
|
27367
|
+
lines.push("Add these font instances after the existing `inter` declaration:");
|
|
27368
|
+
lines.push("");
|
|
27369
|
+
lines.push("```typescript");
|
|
27370
|
+
for (let i = 0; i < newFonts.length; i++) {
|
|
27371
|
+
const font = newFonts[i];
|
|
27372
|
+
const importName = fontToImportName(font);
|
|
27373
|
+
const instanceName = fontToInstanceName(font);
|
|
27374
|
+
const varName = fontToVarName(font);
|
|
27375
|
+
lines.push(`const ${instanceName} = ${importName}({`);
|
|
27376
|
+
lines.push(` variable: "${varName}",`);
|
|
27377
|
+
lines.push(` subsets: ["latin"],`);
|
|
27378
|
+
lines.push(` weight: ["400", "500", "600", "700"],`);
|
|
27379
|
+
lines.push(`});`);
|
|
27380
|
+
if (i < newFonts.length - 1) lines.push("");
|
|
27381
|
+
}
|
|
27382
|
+
lines.push("```");
|
|
27383
|
+
lines.push("");
|
|
27384
|
+
const varRefs = newFonts.map((f) => `\${${fontToInstanceName(f)}.variable}`).join(" ");
|
|
27385
|
+
lines.push("Update the `<body>` className to include the new font variables:");
|
|
27386
|
+
lines.push("");
|
|
27387
|
+
lines.push("```tsx");
|
|
27388
|
+
lines.push(
|
|
27389
|
+
`<body className={\`\${inter.variable} ${varRefs} antialiased\`}>`
|
|
27390
|
+
);
|
|
27391
|
+
lines.push("```");
|
|
27392
|
+
lines.push("");
|
|
27393
|
+
sections.push(lines.join("\n"));
|
|
27394
|
+
}
|
|
27395
|
+
sectionNum++;
|
|
27396
|
+
{
|
|
27397
|
+
const lines = [];
|
|
27398
|
+
lines.push(`## ${sectionNum}. Update \`src/lib/theme-config.ts\``);
|
|
27399
|
+
lines.push("");
|
|
27400
|
+
lines.push("Create or replace this file with:");
|
|
27401
|
+
lines.push("");
|
|
27402
|
+
lines.push("```typescript");
|
|
27403
|
+
lines.push(`import type { BrandingState, ImageKey } from "canvas-ui-sdk";`);
|
|
27404
|
+
lines.push("");
|
|
27405
|
+
const b = theme.branding;
|
|
27406
|
+
lines.push(`export const savedBranding: BrandingState = {`);
|
|
27407
|
+
lines.push(` iconShape: "${b.iconShape}",`);
|
|
27408
|
+
lines.push(` iconName: "${b.iconName}",`);
|
|
27409
|
+
lines.push(` bgColor: "${b.bgColor}",`);
|
|
27410
|
+
lines.push(` iconColor: "${b.iconColor}",`);
|
|
27411
|
+
lines.push(` wordmark: "${b.wordmark}",`);
|
|
27412
|
+
lines.push(`};`);
|
|
27413
|
+
lines.push("");
|
|
27414
|
+
lines.push(`export const savedImages: Record<ImageKey, string> = {`);
|
|
27415
|
+
const imageKeys = ["logoLight", "logoDark", "faviconLight", "faviconDark"];
|
|
27416
|
+
for (const key of imageKeys) {
|
|
27417
|
+
lines.push(` ${key}: "${theme.images[key] || ""}",`);
|
|
27418
|
+
}
|
|
27419
|
+
lines.push(`};`);
|
|
27420
|
+
lines.push("```");
|
|
27421
|
+
lines.push("");
|
|
27422
|
+
sections.push(lines.join("\n"));
|
|
27423
|
+
}
|
|
27424
|
+
sectionNum++;
|
|
27425
|
+
{
|
|
27426
|
+
const lines = [];
|
|
27427
|
+
lines.push(`## ${sectionNum}. Delete \`.data/theme.json\``);
|
|
27428
|
+
lines.push("");
|
|
27429
|
+
lines.push("Remove the runtime overrides file:");
|
|
27430
|
+
lines.push("");
|
|
27431
|
+
lines.push("```bash");
|
|
27432
|
+
lines.push("rm .data/theme.json");
|
|
27433
|
+
lines.push("```");
|
|
27434
|
+
sections.push(lines.join("\n"));
|
|
27435
|
+
}
|
|
27436
|
+
const header = [
|
|
27437
|
+
"# Bake Theme Into Source Code",
|
|
27438
|
+
"",
|
|
27439
|
+
"Apply the following theme overrides as source-code defaults so the app loads with the correct styling on first paint \u2014 no flash of unstyled content.",
|
|
27440
|
+
""
|
|
27441
|
+
].join("\n");
|
|
27442
|
+
return header + sections.join("\n");
|
|
27443
|
+
}
|
|
27271
27444
|
function ExportPanel({ theme }) {
|
|
27272
|
-
const [importValue, setImportValue] = useState("");
|
|
27273
|
-
const [importStatus, setImportStatus] = useState("idle");
|
|
27274
27445
|
const [copyStatus, setCopyStatus] = useState(null);
|
|
27275
|
-
const handleCopy = async (content
|
|
27446
|
+
const handleCopy = async (content) => {
|
|
27276
27447
|
try {
|
|
27277
27448
|
await navigator.clipboard.writeText(content);
|
|
27278
|
-
setCopyStatus(
|
|
27449
|
+
setCopyStatus("bake");
|
|
27279
27450
|
setTimeout(() => setCopyStatus(null), 2e3);
|
|
27280
27451
|
} catch {
|
|
27281
27452
|
const textarea = document.createElement("textarea");
|
|
@@ -27284,16 +27455,10 @@ function ExportPanel({ theme }) {
|
|
|
27284
27455
|
textarea.select();
|
|
27285
27456
|
document.execCommand("copy");
|
|
27286
27457
|
document.body.removeChild(textarea);
|
|
27287
|
-
setCopyStatus(
|
|
27458
|
+
setCopyStatus("bake");
|
|
27288
27459
|
setTimeout(() => setCopyStatus(null), 2e3);
|
|
27289
27460
|
}
|
|
27290
27461
|
};
|
|
27291
|
-
const handleImport = () => {
|
|
27292
|
-
const success = theme.importJSON(importValue);
|
|
27293
|
-
setImportStatus(success ? "success" : "error");
|
|
27294
|
-
if (success) setImportValue("");
|
|
27295
|
-
setTimeout(() => setImportStatus("idle"), 3e3);
|
|
27296
|
-
};
|
|
27297
27462
|
const overrideCount = Object.keys(theme.overrides).length;
|
|
27298
27463
|
return /* @__PURE__ */ jsxs("div", { "data-theme-drawer-panel": true, className: "flex flex-col gap-5 p-4", children: [
|
|
27299
27464
|
/* @__PURE__ */ jsx(
|
|
@@ -27309,59 +27474,7 @@ function ExportPanel({ theme }) {
|
|
|
27309
27474
|
children: theme.isDirty ? `${overrideCount} variable${overrideCount !== 1 ? "s" : ""} modified` : "No modifications \u2014 using defaults"
|
|
27310
27475
|
}
|
|
27311
27476
|
),
|
|
27312
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
27313
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
27314
|
-
/* @__PURE__ */ jsx(
|
|
27315
|
-
"h3",
|
|
27316
|
-
{
|
|
27317
|
-
style: {
|
|
27318
|
-
fontSize: "13px",
|
|
27319
|
-
fontWeight: 600,
|
|
27320
|
-
color: "#374151",
|
|
27321
|
-
textTransform: "uppercase",
|
|
27322
|
-
letterSpacing: "0.05em"
|
|
27323
|
-
},
|
|
27324
|
-
children: "Export CSS"
|
|
27325
|
-
}
|
|
27326
|
-
),
|
|
27327
|
-
/* @__PURE__ */ jsx(
|
|
27328
|
-
"button",
|
|
27329
|
-
{
|
|
27330
|
-
onClick: () => handleCopy(theme.exportCSS(), "css"),
|
|
27331
|
-
style: {
|
|
27332
|
-
fontSize: "12px",
|
|
27333
|
-
color: copyStatus === "css" ? "#059669" : "#1165ef",
|
|
27334
|
-
background: "none",
|
|
27335
|
-
border: "none",
|
|
27336
|
-
cursor: "pointer",
|
|
27337
|
-
fontWeight: 500
|
|
27338
|
-
},
|
|
27339
|
-
children: copyStatus === "css" ? "Copied!" : "Copy"
|
|
27340
|
-
}
|
|
27341
|
-
)
|
|
27342
|
-
] }),
|
|
27343
|
-
/* @__PURE__ */ jsx(
|
|
27344
|
-
"pre",
|
|
27345
|
-
{
|
|
27346
|
-
style: {
|
|
27347
|
-
fontSize: "11px",
|
|
27348
|
-
fontFamily: "monospace",
|
|
27349
|
-
padding: "12px",
|
|
27350
|
-
background: "#f9fafb",
|
|
27351
|
-
border: "1px solid #e5e7eb",
|
|
27352
|
-
borderRadius: "6px",
|
|
27353
|
-
overflowX: "auto",
|
|
27354
|
-
maxHeight: "200px",
|
|
27355
|
-
overflowY: "auto",
|
|
27356
|
-
color: "#374151",
|
|
27357
|
-
whiteSpace: "pre-wrap",
|
|
27358
|
-
wordBreak: "break-all"
|
|
27359
|
-
},
|
|
27360
|
-
children: theme.exportCSS()
|
|
27361
|
-
}
|
|
27362
|
-
)
|
|
27363
|
-
] }),
|
|
27364
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
27477
|
+
overrideCount > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
27365
27478
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
27366
27479
|
/* @__PURE__ */ jsx(
|
|
27367
27480
|
"h3",
|
|
@@ -27373,102 +27486,37 @@ function ExportPanel({ theme }) {
|
|
|
27373
27486
|
textTransform: "uppercase",
|
|
27374
27487
|
letterSpacing: "0.05em"
|
|
27375
27488
|
},
|
|
27376
|
-
children: "
|
|
27489
|
+
children: "Bake into source code"
|
|
27377
27490
|
}
|
|
27378
27491
|
),
|
|
27379
27492
|
/* @__PURE__ */ jsx(
|
|
27380
27493
|
"button",
|
|
27381
27494
|
{
|
|
27382
|
-
onClick: () => handleCopy(theme
|
|
27495
|
+
onClick: () => handleCopy(generateBakePrompt(theme)),
|
|
27383
27496
|
style: {
|
|
27384
27497
|
fontSize: "12px",
|
|
27385
|
-
color: copyStatus === "
|
|
27498
|
+
color: copyStatus === "bake" ? "#059669" : "#1165ef",
|
|
27386
27499
|
background: "none",
|
|
27387
27500
|
border: "none",
|
|
27388
27501
|
cursor: "pointer",
|
|
27389
27502
|
fontWeight: 500
|
|
27390
27503
|
},
|
|
27391
|
-
children: copyStatus === "
|
|
27504
|
+
children: copyStatus === "bake" ? "Copied!" : "Copy prompt"
|
|
27392
27505
|
}
|
|
27393
27506
|
)
|
|
27394
27507
|
] }),
|
|
27395
27508
|
/* @__PURE__ */ jsx(
|
|
27396
|
-
"
|
|
27509
|
+
"p",
|
|
27397
27510
|
{
|
|
27398
27511
|
style: {
|
|
27399
|
-
fontSize: "
|
|
27400
|
-
|
|
27401
|
-
|
|
27402
|
-
background: "#f9fafb",
|
|
27403
|
-
border: "1px solid #e5e7eb",
|
|
27404
|
-
borderRadius: "6px",
|
|
27405
|
-
overflowX: "auto",
|
|
27406
|
-
maxHeight: "200px",
|
|
27407
|
-
overflowY: "auto",
|
|
27408
|
-
color: "#374151",
|
|
27409
|
-
whiteSpace: "pre-wrap",
|
|
27410
|
-
wordBreak: "break-all"
|
|
27512
|
+
fontSize: "12px",
|
|
27513
|
+
color: "#6b7280",
|
|
27514
|
+
lineHeight: "1.4"
|
|
27411
27515
|
},
|
|
27412
|
-
children: theme.
|
|
27516
|
+
children: "Copies a prompt for Claude Code that updates your source files with the current theme values."
|
|
27413
27517
|
}
|
|
27414
27518
|
)
|
|
27415
27519
|
] }),
|
|
27416
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
27417
|
-
/* @__PURE__ */ jsx(
|
|
27418
|
-
"h3",
|
|
27419
|
-
{
|
|
27420
|
-
style: {
|
|
27421
|
-
fontSize: "13px",
|
|
27422
|
-
fontWeight: 600,
|
|
27423
|
-
color: "#374151",
|
|
27424
|
-
textTransform: "uppercase",
|
|
27425
|
-
letterSpacing: "0.05em"
|
|
27426
|
-
},
|
|
27427
|
-
children: "Import JSON"
|
|
27428
|
-
}
|
|
27429
|
-
),
|
|
27430
|
-
/* @__PURE__ */ jsx(
|
|
27431
|
-
"textarea",
|
|
27432
|
-
{
|
|
27433
|
-
value: importValue,
|
|
27434
|
-
onChange: (e) => setImportValue(e.target.value),
|
|
27435
|
-
placeholder: "Paste exported JSON here...",
|
|
27436
|
-
rows: 5,
|
|
27437
|
-
style: {
|
|
27438
|
-
fontSize: "11px",
|
|
27439
|
-
fontFamily: "monospace",
|
|
27440
|
-
padding: "12px",
|
|
27441
|
-
border: "1px solid #e5e7eb",
|
|
27442
|
-
borderRadius: "6px",
|
|
27443
|
-
color: "#374151",
|
|
27444
|
-
background: "#ffffff",
|
|
27445
|
-
resize: "vertical"
|
|
27446
|
-
}
|
|
27447
|
-
}
|
|
27448
|
-
),
|
|
27449
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
27450
|
-
/* @__PURE__ */ jsx(
|
|
27451
|
-
"button",
|
|
27452
|
-
{
|
|
27453
|
-
onClick: handleImport,
|
|
27454
|
-
disabled: !importValue.trim(),
|
|
27455
|
-
style: {
|
|
27456
|
-
fontSize: "13px",
|
|
27457
|
-
fontWeight: 500,
|
|
27458
|
-
color: "#ffffff",
|
|
27459
|
-
background: importValue.trim() ? "#1165ef" : "#9ca3af",
|
|
27460
|
-
border: "none",
|
|
27461
|
-
cursor: importValue.trim() ? "pointer" : "not-allowed",
|
|
27462
|
-
padding: "8px 16px",
|
|
27463
|
-
borderRadius: "6px"
|
|
27464
|
-
},
|
|
27465
|
-
children: "Import"
|
|
27466
|
-
}
|
|
27467
|
-
),
|
|
27468
|
-
importStatus === "success" && /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "#059669" }, children: "Theme imported!" }),
|
|
27469
|
-
importStatus === "error" && /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "#dc2626" }, children: "Invalid JSON format" })
|
|
27470
|
-
] })
|
|
27471
|
-
] }),
|
|
27472
27520
|
theme.isDirty && /* @__PURE__ */ jsx(
|
|
27473
27521
|
"div",
|
|
27474
27522
|
{
|