velloo 0.0.0 → 0.2.0
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/BUN-LICENSE.md +91 -0
- package/LICENSE +202 -0
- package/NOTICE +9 -0
- package/README.md +288 -2
- package/THIRD-PARTY-NOTICES.md +467 -0
- package/assets/elsewhere-alps-9fqhv029.jpg +0 -0
- package/assets/elsewhere-bali-vp60g115.jpg +0 -0
- package/assets/elsewhere-forest-xgn23zrj.jpg +0 -0
- package/assets/elsewhere-japan-qs7qkbr2.jpg +0 -0
- package/assets/elsewhere-kyoto-map-n2bvkrya.svg +1 -0
- package/assets/elsewhere-kyoto-qemtn6nk.jpg +0 -0
- package/assets/elsewhere-room-g1gaw7cs.jpg +0 -0
- package/canvas/apple-touch-icon.png +0 -0
- package/canvas/assets/index-BCvDZiBo.css +2 -0
- package/canvas/assets/index-ClaBqcaS.js +28 -0
- package/canvas/assets/lucide-all-iIF-pmzN.js +1 -0
- package/canvas/assets/radix-C3HaOB-d.js +41 -0
- package/canvas/assets/react-D0Ec-185.js +9 -0
- package/canvas/assets/rolldown-runtime-hePW80VL.js +1 -0
- package/canvas/assets/vendor-CKmQ-Zst.js +53 -0
- package/canvas/favicon.ico +0 -0
- package/canvas/favicon.svg +12 -0
- package/canvas/fonts/OFL-1.1.txt +93 -0
- package/canvas/fonts/poppins-700.woff2 +0 -0
- package/canvas/icon-192.png +0 -0
- package/canvas/icon-512.png +0 -0
- package/canvas/index.html +22 -0
- package/canvas/site.webmanifest +11 -0
- package/chunk-08sv3k41.js +4 -0
- package/chunk-0fe83yzt.js +2 -0
- package/chunk-0t68szgr.js +3 -0
- package/chunk-1h55s5he.js +2 -0
- package/chunk-2c7jbx46.js +2 -0
- package/chunk-2smsg2ct.js +7 -0
- package/chunk-308ynsxd.js +2 -0
- package/chunk-3e8vez4d.js +1229 -0
- package/chunk-40xgcth8.js +63 -0
- package/chunk-4dn75m6t.js +3 -0
- package/chunk-4fj5tahv.js +3 -0
- package/chunk-6nqghjda.js +3 -0
- package/chunk-6tx68d90.js +3 -0
- package/chunk-6w6ch4ce.js +2 -0
- package/chunk-735ezz23.js +86 -0
- package/chunk-7eq7nx37.js +7 -0
- package/chunk-7eyb8yrf.js +6 -0
- package/chunk-80fjfyha.js +86 -0
- package/chunk-80r93t2e.js +4 -0
- package/chunk-94vx1yb0.js +3 -0
- package/chunk-9vg3yafz.js +3 -0
- package/chunk-a84n72m2.js +4 -0
- package/chunk-ampmdzz4.js +10 -0
- package/chunk-avns4dbf.js +2 -0
- package/chunk-ayrb3qnm.js +3 -0
- package/chunk-bwnvcncx.js +3 -0
- package/chunk-ccszg02q.js +5 -0
- package/chunk-cvn689d5.js +3 -0
- package/chunk-cxe6jjwj.js +3 -0
- package/chunk-dg6z4vdd.js +3 -0
- package/chunk-dgwjpbp9.js +3 -0
- package/chunk-dy41n60j.js +52 -0
- package/chunk-ek71z2fv.js +226 -0
- package/chunk-er1fxb7d.js +2 -0
- package/chunk-eyr8hrzf.js +2 -0
- package/chunk-fjbzk4sw.js +3 -0
- package/chunk-fsbsksga.js +3 -0
- package/chunk-h6gchare.js +3 -0
- package/chunk-hcb68zt7.js +85 -0
- package/chunk-hggap8fq.js +3 -0
- package/chunk-j11fyeqh.js +2 -0
- package/chunk-jb21jkp1.js +8 -0
- package/chunk-jfx9xjmr.js +18 -0
- package/chunk-jr0ss0mm.js +303 -0
- package/chunk-jrsknzjt.js +3 -0
- package/chunk-jv0xggh0.js +2 -0
- package/chunk-k17gfwq3.js +2 -0
- package/chunk-mh2pr7cq.js +5 -0
- package/chunk-mnapdp1y.js +2 -0
- package/chunk-mzhdrawd.js +3 -0
- package/chunk-n9gs6yx9.js +2 -0
- package/chunk-ngnymg2q.js +3 -0
- package/chunk-nwx5700b.js +3 -0
- package/chunk-pjtg3wnm.js +4 -0
- package/chunk-pp86v6m6.js +3 -0
- package/chunk-r22epxz2.js +3 -0
- package/chunk-rgasy862.js +5 -0
- package/chunk-rpwpeph5.js +3 -0
- package/chunk-s23gtejf.js +3 -0
- package/chunk-sjgqnykd.js +6 -0
- package/chunk-sn3x2m0m.js +6 -0
- package/chunk-t448rrfr.js +2 -0
- package/chunk-tdsk5wxa.js +451 -0
- package/chunk-v40fn08f.js +442 -0
- package/chunk-vbk1qhdz.js +3 -0
- package/chunk-vdkrbzh1.js +2 -0
- package/chunk-vgmr98cv.js +40 -0
- package/chunk-vsv8z729.js +6 -0
- package/chunk-x4f4k9pp.js +26 -0
- package/chunk-xt5ayg7g.js +4 -0
- package/chunk-ydhwv29b.js +244 -0
- package/chunk-zb6hc1y0.js +2 -0
- package/cli.js +3 -0
- package/launcher.cjs +97 -0
- package/package.json +58 -5
- package/pkgs/helpers/src/box.tsx +21 -0
- package/pkgs/helpers/src/cn.ts +32 -0
- package/pkgs/helpers/src/descriptors.ts +270 -0
- package/pkgs/helpers/src/divider.tsx +123 -0
- package/pkgs/helpers/src/gradient.tsx +90 -0
- package/pkgs/helpers/src/heading.tsx +20 -0
- package/pkgs/helpers/src/icon-data.ts +8009 -0
- package/pkgs/helpers/src/icon.tsx +53 -0
- package/pkgs/helpers/src/image.tsx +111 -0
- package/pkgs/helpers/src/index.ts +29 -0
- package/pkgs/helpers/src/layer.tsx +61 -0
- package/pkgs/helpers/src/lowering.ts +53 -0
- package/pkgs/helpers/src/paths.ts +47 -0
- package/pkgs/helpers/src/placeholder.tsx +88 -0
- package/pkgs/helpers/src/prose.tsx +42 -0
- package/pkgs/helpers/src/registry.ts +41 -0
- package/pkgs/helpers/src/svg.tsx +62 -0
- package/pkgs/helpers/src/text.tsx +16 -0
- package/pkgs/provider-antd/src/index.ts +78 -0
- package/pkgs/provider-antd/src/intro.ts +14 -0
- package/pkgs/provider-antd/src/manifest.ts +439 -0
- package/pkgs/provider-antd/src/overlays.ts +176 -0
- package/pkgs/provider-antd/src/registry.ts +104 -0
- package/pkgs/provider-antd/src/render-pass.ts +43 -0
- package/pkgs/provider-antd/src/tailwind-entry.css +21 -0
- package/pkgs/provider-antd/src/theme.ts +132 -0
- package/pkgs/provider-antd/src/version.ts +8 -0
- package/pkgs/provider-chakra/src/index.ts +80 -0
- package/pkgs/provider-chakra/src/intro.ts +14 -0
- package/pkgs/provider-chakra/src/manifest.ts +421 -0
- package/pkgs/provider-chakra/src/overlays.ts +246 -0
- package/pkgs/provider-chakra/src/registry.ts +227 -0
- package/pkgs/provider-chakra/src/render-pass.ts +55 -0
- package/pkgs/provider-chakra/src/tailwind-entry.css +21 -0
- package/pkgs/provider-chakra/src/theme.ts +180 -0
- package/pkgs/provider-chakra/src/version.ts +8 -0
- package/pkgs/provider-mui/src/index.ts +117 -0
- package/pkgs/provider-mui/src/intro.ts +12 -0
- package/pkgs/provider-mui/src/manifest.ts +263 -0
- package/pkgs/provider-mui/src/overlays.ts +124 -0
- package/pkgs/provider-mui/src/registry.ts +120 -0
- package/pkgs/provider-mui/src/render-pass.ts +36 -0
- package/pkgs/provider-mui/src/tailwind-entry.css +21 -0
- package/pkgs/provider-mui/src/theme.ts +129 -0
- package/pkgs/provider-mui/src/version.ts +8 -0
- package/pkgs/provider-none/src/components-inline.tsx +204 -0
- package/pkgs/provider-none/src/components.tsx +155 -0
- package/pkgs/provider-none/src/index.ts +57 -0
- package/pkgs/provider-none/src/intro.ts +18 -0
- package/pkgs/provider-none/src/manifest.ts +163 -0
- package/pkgs/provider-none/src/registry-inline.ts +36 -0
- package/pkgs/provider-none/src/registry.ts +39 -0
- package/pkgs/provider-none/src/tailwind-entry.css +57 -0
- package/pkgs/provider-none/src/version.ts +10 -0
- package/pkgs/schema/src/annotation.ts +120 -0
- package/pkgs/schema/src/asset.ts +66 -0
- package/pkgs/schema/src/board.ts +71 -0
- package/pkgs/schema/src/comment.ts +107 -0
- package/pkgs/schema/src/config.ts +185 -0
- package/pkgs/schema/src/css-sanitize.ts +56 -0
- package/pkgs/schema/src/extension.ts +105 -0
- package/pkgs/schema/src/fonts.ts +690 -0
- package/pkgs/schema/src/frame.ts +40 -0
- package/pkgs/schema/src/icon-name.ts +21 -0
- package/pkgs/schema/src/ids.ts +14 -0
- package/pkgs/schema/src/index.ts +169 -0
- package/pkgs/schema/src/migrate.ts +297 -0
- package/pkgs/schema/src/node.ts +229 -0
- package/pkgs/schema/src/paths.ts +28 -0
- package/pkgs/schema/src/repo.ts +134 -0
- package/pkgs/schema/src/screen.ts +30 -0
- package/pkgs/schema/src/snippet-resolve.ts +193 -0
- package/pkgs/schema/src/snippet.ts +104 -0
- package/pkgs/schema/src/svg-sanitize.ts +487 -0
- package/pkgs/schema/src/theme.ts +218 -0
- package/pkgs/schema/src/typeset.ts +693 -0
- package/pkgs/schema/src/validate-ids.ts +46 -0
- package/pkgs/schema/src/viewport.ts +8 -0
- package/pkgs/shadcn-snapshot/dist/manifest.json +8109 -0
- package/pkgs/shadcn-snapshot/src/components/canvas-portal.tsx +55 -0
- package/pkgs/shadcn-snapshot/src/components/ui/accordion.tsx +122 -0
- package/pkgs/shadcn-snapshot/src/components/ui/alert-dialog.tsx +164 -0
- package/pkgs/shadcn-snapshot/src/components/ui/alert.tsx +74 -0
- package/pkgs/shadcn-snapshot/src/components/ui/aspect-ratio.tsx +13 -0
- package/pkgs/shadcn-snapshot/src/components/ui/attachment.tsx +197 -0
- package/pkgs/shadcn-snapshot/src/components/ui/avatar.tsx +100 -0
- package/pkgs/shadcn-snapshot/src/components/ui/badge.tsx +50 -0
- package/pkgs/shadcn-snapshot/src/components/ui/breadcrumb.tsx +109 -0
- package/pkgs/shadcn-snapshot/src/components/ui/bubble.tsx +130 -0
- package/pkgs/shadcn-snapshot/src/components/ui/button-group.tsx +82 -0
- package/pkgs/shadcn-snapshot/src/components/ui/button.tsx +72 -0
- package/pkgs/shadcn-snapshot/src/components/ui/calendar.tsx +229 -0
- package/pkgs/shadcn-snapshot/src/components/ui/card.tsx +92 -0
- package/pkgs/shadcn-snapshot/src/components/ui/carousel.tsx +235 -0
- package/pkgs/shadcn-snapshot/src/components/ui/chart-option.ts +250 -0
- package/pkgs/shadcn-snapshot/src/components/ui/chart.tsx +177 -0
- package/pkgs/shadcn-snapshot/src/components/ui/checkbox.tsx +41 -0
- package/pkgs/shadcn-snapshot/src/components/ui/collapsible.tsx +32 -0
- package/pkgs/shadcn-snapshot/src/components/ui/combobox.tsx +196 -0
- package/pkgs/shadcn-snapshot/src/components/ui/context-menu.tsx +227 -0
- package/pkgs/shadcn-snapshot/src/components/ui/dialog.tsx +131 -0
- package/pkgs/shadcn-snapshot/src/components/ui/direction.tsx +24 -0
- package/pkgs/shadcn-snapshot/src/components/ui/drawer.tsx +112 -0
- package/pkgs/shadcn-snapshot/src/components/ui/dropdown-menu.tsx +205 -0
- package/pkgs/shadcn-snapshot/src/components/ui/empty.tsx +98 -0
- package/pkgs/shadcn-snapshot/src/components/ui/field.tsx +228 -0
- package/pkgs/shadcn-snapshot/src/components/ui/hover-card.tsx +51 -0
- package/pkgs/shadcn-snapshot/src/components/ui/input-group.tsx +148 -0
- package/pkgs/shadcn-snapshot/src/components/ui/input.tsx +43 -0
- package/pkgs/shadcn-snapshot/src/components/ui/item.tsx +187 -0
- package/pkgs/shadcn-snapshot/src/components/ui/kbd.tsx +30 -0
- package/pkgs/shadcn-snapshot/src/components/ui/label.tsx +25 -0
- package/pkgs/shadcn-snapshot/src/components/ui/marker.tsx +71 -0
- package/pkgs/shadcn-snapshot/src/components/ui/menubar.tsx +243 -0
- package/pkgs/shadcn-snapshot/src/components/ui/message.tsx +89 -0
- package/pkgs/shadcn-snapshot/src/components/ui/native-select.tsx +60 -0
- package/pkgs/shadcn-snapshot/src/components/ui/navigation-menu.tsx +165 -0
- package/pkgs/shadcn-snapshot/src/components/ui/pagination.tsx +117 -0
- package/pkgs/shadcn-snapshot/src/components/ui/popover.tsx +66 -0
- package/pkgs/shadcn-snapshot/src/components/ui/progress.tsx +35 -0
- package/pkgs/shadcn-snapshot/src/components/ui/radio-group.tsx +48 -0
- package/pkgs/shadcn-snapshot/src/components/ui/scroll-area.tsx +59 -0
- package/pkgs/shadcn-snapshot/src/components/ui/select.tsx +180 -0
- package/pkgs/shadcn-snapshot/src/components/ui/separator.tsx +32 -0
- package/pkgs/shadcn-snapshot/src/components/ui/sheet.tsx +107 -0
- package/pkgs/shadcn-snapshot/src/components/ui/skeleton.tsx +17 -0
- package/pkgs/shadcn-snapshot/src/components/ui/slider.tsx +68 -0
- package/pkgs/shadcn-snapshot/src/components/ui/sonner.tsx +91 -0
- package/pkgs/shadcn-snapshot/src/components/ui/spinner.tsx +21 -0
- package/pkgs/shadcn-snapshot/src/components/ui/switch.tsx +41 -0
- package/pkgs/shadcn-snapshot/src/components/ui/table.tsx +93 -0
- package/pkgs/shadcn-snapshot/src/components/ui/tabs.tsx +84 -0
- package/pkgs/shadcn-snapshot/src/components/ui/textarea.tsx +24 -0
- package/pkgs/shadcn-snapshot/src/components/ui/toggle-group.tsx +94 -0
- package/pkgs/shadcn-snapshot/src/components/ui/toggle.tsx +50 -0
- package/pkgs/shadcn-snapshot/src/components/ui/tooltip.tsx +47 -0
- package/pkgs/shadcn-snapshot/src/examples.ts +36 -0
- package/pkgs/shadcn-snapshot/src/groups.ts +87 -0
- package/pkgs/shadcn-snapshot/src/index.ts +43 -0
- package/pkgs/shadcn-snapshot/src/lib/utils.ts +4 -0
- package/pkgs/shadcn-snapshot/src/manifest.ts +12 -0
- package/pkgs/shadcn-snapshot/src/notes.ts +97 -0
- package/pkgs/shadcn-snapshot/src/paths.ts +47 -0
- package/pkgs/shadcn-snapshot/src/registry-files.ts +293 -0
- package/pkgs/shadcn-snapshot/src/registry.ts +631 -0
- package/pkgs/shadcn-snapshot/src/shadcn-tailwind.css +632 -0
- package/pkgs/shadcn-snapshot/src/tailwind-entry.css +159 -0
- package/pkgs/shadcn-snapshot/src/version.ts +8 -0
- package/plugins/claude/velloo/.claude-plugin/plugin.json +6 -0
- package/plugins/claude/velloo/agents/velloo-design-reviewer.md +33 -0
- package/plugins/claude/velloo/agents/velloo-designer.md +39 -0
- package/plugins/claude/velloo/commands/design.md +11 -0
- package/plugins/claude/velloo/commands/implement.md +10 -0
- package/plugins/claude/velloo/commands/review.md +8 -0
- package/plugins/gemini/GEMINI.md +31 -0
- package/plugins/gemini/commands/velloo/design.toml +10 -0
- package/plugins/gemini/commands/velloo/implement.toml +9 -0
- package/plugins/gemini/gemini-extension.json +9 -0
- package/skills/velloo-brand/SKILL.md +124 -0
- package/skills/velloo-design/SKILL.md +144 -0
- package/skills/velloo-design-system/SKILL.md +90 -0
- package/skills/velloo-implement/SKILL.md +101 -0
- package/skills/velloo-logo/SKILL.md +93 -0
- package/skills/velloo-setup/SKILL.md +156 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
const NumOrCssLen = z.union([z.number(), z.string().min(1)]);
|
|
4
|
+
|
|
5
|
+
/** Loose schema for user-extension token namespaces (`shadows`, future fields). */
|
|
6
|
+
const LooseTokenGroupSchema: z.ZodType<LooseTokenGroup> = z.lazy(() =>
|
|
7
|
+
z.record(z.string(), z.union([z.string(), z.number(), LooseTokenGroupSchema])),
|
|
8
|
+
);
|
|
9
|
+
/**
|
|
10
|
+
* Exported only so declaration emit can name it: a downstream schema built on
|
|
11
|
+
* `ThemeSchema` (`@velloo/protocol/publish`) inlines this type into its own
|
|
12
|
+
* `.d.ts`, which `tsc` refuses to do for a module-private name.
|
|
13
|
+
*/
|
|
14
|
+
export type LooseTokenGroup = { [key: string]: string | number | LooseTokenGroup };
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A color slot is either a single CSS color or a pair { DEFAULT, foreground }.
|
|
18
|
+
* Matches shadcn's CSS-variable convention (e.g. --primary, --primary-foreground).
|
|
19
|
+
*/
|
|
20
|
+
const ColorPairSchema = z.union([
|
|
21
|
+
z.string().min(1),
|
|
22
|
+
z.object({
|
|
23
|
+
DEFAULT: z.string().min(1),
|
|
24
|
+
foreground: z.string().min(1).optional(),
|
|
25
|
+
}),
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
export type ColorPair = z.infer<typeof ColorPairSchema>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Typed color slots. `background`, `foreground`, and `primary` are required —
|
|
32
|
+
* everything else is optional so existing themes don't regress.
|
|
33
|
+
*/
|
|
34
|
+
export const ColorsSchema = z.object({
|
|
35
|
+
background: z.string().min(1),
|
|
36
|
+
foreground: z.string().min(1),
|
|
37
|
+
primary: ColorPairSchema,
|
|
38
|
+
secondary: ColorPairSchema.optional(),
|
|
39
|
+
muted: ColorPairSchema.optional(),
|
|
40
|
+
accent: ColorPairSchema.optional(),
|
|
41
|
+
destructive: ColorPairSchema.optional(),
|
|
42
|
+
card: ColorPairSchema.optional(),
|
|
43
|
+
popover: ColorPairSchema.optional(),
|
|
44
|
+
border: z.string().min(1).optional(),
|
|
45
|
+
input: z.string().min(1).optional(),
|
|
46
|
+
ring: z.string().min(1).optional(),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export type Colors = z.infer<typeof ColorsSchema>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* A sparse color override: every slot optional and explicitly undefined-able,
|
|
53
|
+
* matching what zod's `.partial()` produces for `colorsDark`. `Partial<Colors>`
|
|
54
|
+
* is NOT the same thing under `exactOptionalPropertyTypes` — it adds `?` but
|
|
55
|
+
* still rejects an explicit `undefined`.
|
|
56
|
+
*/
|
|
57
|
+
export type ColorsOverride = { [K in keyof Colors]?: Colors[K] | undefined };
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The effective colors for a mode: `colors`, with `colorsDark` layered on when
|
|
61
|
+
* rendering dark.
|
|
62
|
+
*
|
|
63
|
+
* Every caller used to spread this inline, and the spread does not type as a
|
|
64
|
+
* complete `Colors`: `colorsDark` is a zod `.partial()`, so each of its fields
|
|
65
|
+
* is `T | undefined`, and spreading that over the full set widens even the
|
|
66
|
+
* required `background`/`foreground` to possibly-undefined. Callers coped by
|
|
67
|
+
* casting (codegen's dtcg) or by not noticing. Skipping undefined values keeps
|
|
68
|
+
* the result a real `Colors` — and matches the intent: an override that is not
|
|
69
|
+
* set must not blank the base color.
|
|
70
|
+
*/
|
|
71
|
+
export function resolveColors(theme: Theme, dark = false): Colors {
|
|
72
|
+
if (!dark || !theme.colorsDark) return theme.colors;
|
|
73
|
+
const merged: Colors = { ...theme.colors };
|
|
74
|
+
for (const [key, value] of Object.entries(theme.colorsDark)) {
|
|
75
|
+
if (value !== undefined) (merged as Record<string, unknown>)[key] = value;
|
|
76
|
+
}
|
|
77
|
+
return merged;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Numeric color scales + extra semantic roles captured verbatim from a host
|
|
82
|
+
* app — `primary-600`, `success-500`, `danger`, `border-primary-300`. Keyed by
|
|
83
|
+
* the Tailwind color name (no `--color-` prefix), values are CSS colors.
|
|
84
|
+
* Emitted as `--color-<name>` so `bg-<name>` / `text-<name>` / `border-<name>`
|
|
85
|
+
* resolve literally during a code-to-design port, instead of silently falling
|
|
86
|
+
* back to the default palette.
|
|
87
|
+
*
|
|
88
|
+
* Distinct from `colors`: those are the semantic single-token slots that
|
|
89
|
+
* theme-flip and drive the component snapshot; `palette` is a raw passthrough
|
|
90
|
+
* for an app's own scale so verbatim classes render. Keys are constrained to a
|
|
91
|
+
* CSS-safe ident so they can't inject into the emitted stylesheet.
|
|
92
|
+
*/
|
|
93
|
+
const PaletteSchema = z.record(
|
|
94
|
+
z.string().regex(/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/),
|
|
95
|
+
z.string().min(1),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* A typeset: three rhythm controls plus font roles. Everything visible —
|
|
100
|
+
* the h1..h6 ladder, body/lead/small copy, the space under a heading — derives
|
|
101
|
+
* from these through `TYPESET_RATIOS` (see `./typeset.ts`), which is why there
|
|
102
|
+
* is no size/weight/leading/tracking scale here to keep in sync.
|
|
103
|
+
*/
|
|
104
|
+
const TypesetSchema = z.object({
|
|
105
|
+
/** Base text size. `1em` (the default) follows the surrounding container. */
|
|
106
|
+
size: NumOrCssLen.optional(),
|
|
107
|
+
/** Body line-height, unitless. Heading leading derives from it. */
|
|
108
|
+
leading: z.number().positive().optional(),
|
|
109
|
+
/** Vertical space between blocks. Heading margins and rule spacing derive from it. */
|
|
110
|
+
flow: NumOrCssLen.optional(),
|
|
111
|
+
/** A `fontFamily` role name for body copy, e.g. "sans". */
|
|
112
|
+
fontBody: z.string().min(1).optional(),
|
|
113
|
+
/** A `fontFamily` role name for headings, e.g. "display". */
|
|
114
|
+
fontHeading: z.string().min(1).optional(),
|
|
115
|
+
/** A `fontFamily` role name for code. */
|
|
116
|
+
fontMono: z.string().min(1).optional(),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Typography: font roles, webfont loading, and the folder's typesets.
|
|
121
|
+
*
|
|
122
|
+
* `.strict()` on purpose. This shape once carried `fontSize` / `fontWeight` /
|
|
123
|
+
* `lineHeight` / `letterSpacing` records that no renderer, importer, or codegen
|
|
124
|
+
* path ever read — tokens you could set and that silently did nothing. Typesets
|
|
125
|
+
* replaced them, and strict validation means an attempt to write the old scale
|
|
126
|
+
* fails loudly instead of being quietly dropped.
|
|
127
|
+
*/
|
|
128
|
+
export const TypographySchema = z
|
|
129
|
+
.object({
|
|
130
|
+
/**
|
|
131
|
+
* Font stacks keyed by role. `sans` / `mono` / `serif` are the
|
|
132
|
+
* conventional roles, but any key works — `display: '"Unbounded",
|
|
133
|
+
* sans-serif'` becomes `--font-display`, which Tailwind v4 turns into
|
|
134
|
+
* a `font-display` utility. Roles are the lever for typographic
|
|
135
|
+
* personality: declare one per voice, not one per screen.
|
|
136
|
+
*/
|
|
137
|
+
fontFamily: z.record(z.string(), z.string().min(1)).optional(),
|
|
138
|
+
/**
|
|
139
|
+
* Google Fonts css2 family specs to load in design mode and emit as
|
|
140
|
+
* an @import in generated globals.css. Full spec syntax, e.g.
|
|
141
|
+
* "Unbounded:wght@400..900" or "Fraunces:ital,wght@0,300..900".
|
|
142
|
+
* Set via the `set_fonts` MCP tool rather than by hand.
|
|
143
|
+
*/
|
|
144
|
+
googleFonts: z.array(z.string().min(1)).optional(),
|
|
145
|
+
/**
|
|
146
|
+
* Named typesets. `default` is the folder baseline and projects onto
|
|
147
|
+
* `:root`, so it styles every screen; every other name becomes a
|
|
148
|
+
* `.typeset-<name>` preset class a Prose region can opt into. Keys are
|
|
149
|
+
* constrained to a CSS-safe ident because they are emitted as selectors.
|
|
150
|
+
* Set via the `set_typeset` MCP tool.
|
|
151
|
+
*/
|
|
152
|
+
typesets: z.record(z.string().regex(/^[A-Za-z0-9_-]+$/), TypesetSchema).optional(),
|
|
153
|
+
})
|
|
154
|
+
.strict();
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Structured radius slots. `md` is what emit_theme picks up as `--radius`.
|
|
158
|
+
* Additional named sizes go into the record without losing the named ones.
|
|
159
|
+
*/
|
|
160
|
+
const RadiusSchema = z
|
|
161
|
+
.object({
|
|
162
|
+
none: NumOrCssLen.optional(),
|
|
163
|
+
sm: NumOrCssLen.optional(),
|
|
164
|
+
md: NumOrCssLen.optional(),
|
|
165
|
+
lg: NumOrCssLen.optional(),
|
|
166
|
+
xl: NumOrCssLen.optional(),
|
|
167
|
+
"2xl": NumOrCssLen.optional(),
|
|
168
|
+
"3xl": NumOrCssLen.optional(),
|
|
169
|
+
full: NumOrCssLen.optional(),
|
|
170
|
+
})
|
|
171
|
+
.partial();
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* The host app's Tailwind `container` settings, captured so `class="container"`
|
|
175
|
+
* centers / pads / caps the same way it does in the app. Tailwind's stock
|
|
176
|
+
* `.container` does none of this (v4 dropped the `center`/`padding` options), so
|
|
177
|
+
* a code-to-design port's gutters drift until these are honored. Emitted as a
|
|
178
|
+
* `.container` override (render) / `@utility container` (codegen).
|
|
179
|
+
*/
|
|
180
|
+
const ContainerSchema = z.object({
|
|
181
|
+
center: z.boolean().optional(),
|
|
182
|
+
/** Horizontal padding, e.g. "1.5rem". */
|
|
183
|
+
padding: z.string().min(1).optional(),
|
|
184
|
+
/** Largest max-width cap, e.g. "1320px". */
|
|
185
|
+
maxWidth: z.string().min(1).optional(),
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
export const ThemeSchema = z.object({
|
|
189
|
+
name: z.string().min(1),
|
|
190
|
+
colors: ColorsSchema,
|
|
191
|
+
/** Dark-mode overrides — only the color slots that differ from `colors`.
|
|
192
|
+
* When present, emit_theme writes a `.dark { ... }` block and the canvas
|
|
193
|
+
* can preview both modes. Tokens missing here fall back to `colors`. */
|
|
194
|
+
colorsDark: ColorsSchema.partial().optional(),
|
|
195
|
+
/** Numeric scales + extra roles captured from a host app (see PaletteSchema).
|
|
196
|
+
* Light values; dark overrides go in `paletteDark`. Optional — themes
|
|
197
|
+
* without an imported app palette omit it. */
|
|
198
|
+
palette: PaletteSchema.optional(),
|
|
199
|
+
paletteDark: PaletteSchema.optional(),
|
|
200
|
+
typography: TypographySchema,
|
|
201
|
+
spacing: LooseTokenGroupSchema,
|
|
202
|
+
radius: RadiusSchema,
|
|
203
|
+
shadows: LooseTokenGroupSchema.optional(),
|
|
204
|
+
/** Host app's Tailwind container config — see ContainerSchema. */
|
|
205
|
+
container: ContainerSchema.optional(),
|
|
206
|
+
/**
|
|
207
|
+
* `@keyframes` captured from a host app's `tailwind.config`:
|
|
208
|
+
* name → selector ("0%" / "from") → CSS declarations. Paired with
|
|
209
|
+
* `animation` so the app's `animate-<name>` utilities render on the canvas.
|
|
210
|
+
*/
|
|
211
|
+
keyframes: z
|
|
212
|
+
.record(z.string(), z.record(z.string(), z.record(z.string(), z.string())))
|
|
213
|
+
.optional(),
|
|
214
|
+
/** Animation shorthands keyed by utility name → `--animate-<name>` (e.g. `"fade-in": "fadeIn .3s ease-out"`). */
|
|
215
|
+
animation: z.record(z.string(), z.string()).optional(),
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
export type Theme = z.infer<typeof ThemeSchema>;
|