canvas-ui-sdk 0.3.1 → 0.3.2

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 CHANGED
@@ -27268,6 +27268,179 @@ 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
27445
  const [importValue, setImportValue] = useState("");
27273
27446
  const [importStatus, setImportStatus] = useState("idle");
@@ -27469,6 +27642,58 @@ function ExportPanel({ theme }) {
27469
27642
  importStatus === "error" && /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "#dc2626" }, children: "Invalid JSON format" })
27470
27643
  ] })
27471
27644
  ] }),
27645
+ overrideCount > 0 && /* @__PURE__ */ jsx(
27646
+ "div",
27647
+ {
27648
+ style: {
27649
+ borderTop: "1px solid #e5e7eb",
27650
+ paddingTop: "16px"
27651
+ },
27652
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
27653
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
27654
+ /* @__PURE__ */ jsx(
27655
+ "h3",
27656
+ {
27657
+ style: {
27658
+ fontSize: "13px",
27659
+ fontWeight: 600,
27660
+ color: "#374151",
27661
+ textTransform: "uppercase",
27662
+ letterSpacing: "0.05em"
27663
+ },
27664
+ children: "Bake into source code"
27665
+ }
27666
+ ),
27667
+ /* @__PURE__ */ jsx(
27668
+ "button",
27669
+ {
27670
+ onClick: () => handleCopy(generateBakePrompt(theme), "bake"),
27671
+ style: {
27672
+ fontSize: "12px",
27673
+ color: copyStatus === "bake" ? "#059669" : "#1165ef",
27674
+ background: "none",
27675
+ border: "none",
27676
+ cursor: "pointer",
27677
+ fontWeight: 500
27678
+ },
27679
+ children: copyStatus === "bake" ? "Copied!" : "Copy prompt"
27680
+ }
27681
+ )
27682
+ ] }),
27683
+ /* @__PURE__ */ jsx(
27684
+ "p",
27685
+ {
27686
+ style: {
27687
+ fontSize: "12px",
27688
+ color: "#6b7280",
27689
+ lineHeight: "1.4"
27690
+ },
27691
+ children: "Copies a prompt for Claude Code that updates your source files with the current theme values."
27692
+ }
27693
+ )
27694
+ ] })
27695
+ }
27696
+ ),
27472
27697
  theme.isDirty && /* @__PURE__ */ jsx(
27473
27698
  "div",
27474
27699
  {