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,129 @@
|
|
|
1
|
+
import { createTheme, type Theme as MuiTheme, type ThemeOptions } from "@mui/material/styles";
|
|
2
|
+
import {
|
|
3
|
+
type ColorPair,
|
|
4
|
+
DEFAULT_TYPESET_NAME,
|
|
5
|
+
resolveColors,
|
|
6
|
+
typesetScale,
|
|
7
|
+
type Theme as VellooTheme,
|
|
8
|
+
} from "@velloo/schema";
|
|
9
|
+
import { formatRgb, parse } from "culori";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* MUI's color manipulator (lighten/darken in createPalette) only parses
|
|
13
|
+
* `#hex`, `rgb()/rgba()`, `hsl()/hsla()`, `color()` — NOT `oklch()`, which is
|
|
14
|
+
* exactly what velloo themes store. Convert anything outside MUI's set to
|
|
15
|
+
* `rgb(...)` via culori; pass MUI-native formats through untouched so a hex
|
|
16
|
+
* theme stays hex (and round-trips identically in codegen).
|
|
17
|
+
*/
|
|
18
|
+
function muiColor(css: string): string {
|
|
19
|
+
const s = css.trim();
|
|
20
|
+
if (/^(#|rgb|hsl)/i.test(s)) return s;
|
|
21
|
+
return formatRgb(parse(s)) ?? s;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** A color slot is a CSS string or a { DEFAULT, foreground } pair — pull the base color (MUI-safe). */
|
|
25
|
+
function base(slot: ColorPair | undefined, fallback: string): string {
|
|
26
|
+
if (typeof slot === "string") return muiColor(slot);
|
|
27
|
+
if (slot && typeof slot === "object" && typeof slot.DEFAULT === "string")
|
|
28
|
+
return muiColor(slot.DEFAULT);
|
|
29
|
+
return muiColor(fallback);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** The `foreground` half of a pair (the on-color, MUI-safe), or a fallback. */
|
|
33
|
+
function fg(slot: ColorPair | undefined, fallback: string): string {
|
|
34
|
+
if (slot && typeof slot === "object" && typeof slot.foreground === "string")
|
|
35
|
+
return muiColor(slot.foreground);
|
|
36
|
+
return muiColor(fallback);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** MUI's shape.borderRadius is a px number; coerce velloo's radius.md (number or CSS len). */
|
|
40
|
+
function radiusPx(theme: VellooTheme): number {
|
|
41
|
+
const md = (theme.radius as Record<string, unknown> | undefined)?.md;
|
|
42
|
+
if (typeof md === "number") return md;
|
|
43
|
+
if (typeof md === "string") {
|
|
44
|
+
const n = Number.parseFloat(md);
|
|
45
|
+
return Number.isFinite(n) ? (md.includes("rem") ? n * 16 : n) : 8;
|
|
46
|
+
}
|
|
47
|
+
return 8;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Project velloo's unified token tree onto MUI `ThemeOptions` (the input POJO
|
|
52
|
+
* for `createTheme`) — the adapter's `themeToNative`. This is the SINGLE source
|
|
53
|
+
* of the velloo→MUI mapping: `muiThemeFrom` wraps it for the canvas render
|
|
54
|
+
* pass, and codegen serializes the same POJO to a `createTheme(...)` artifact,
|
|
55
|
+
* so the preview and the emitted theme never diverge. velloo colors are
|
|
56
|
+
* arbitrary CSS strings (oklch/hsl/hex); MUI's palette accepts any CSS color.
|
|
57
|
+
*/
|
|
58
|
+
export function muiThemeOptions(theme: VellooTheme, dark = false): ThemeOptions {
|
|
59
|
+
// In dark mode, overlay the theme's dark color slots — otherwise flipping
|
|
60
|
+
// palette.mode to "dark" would keep the light color values.
|
|
61
|
+
const c = resolveColors(theme, dark);
|
|
62
|
+
return {
|
|
63
|
+
palette: {
|
|
64
|
+
mode: dark ? "dark" : "light",
|
|
65
|
+
primary: { main: base(c.primary, "#4f46e5"), contrastText: fg(c.primary, "#ffffff") },
|
|
66
|
+
secondary: { main: base(c.secondary, "#64748b"), contrastText: fg(c.secondary, "#ffffff") },
|
|
67
|
+
error: { main: base(c.destructive, "#dc2626"), contrastText: fg(c.destructive, "#ffffff") },
|
|
68
|
+
background: { default: muiColor(c.background), paper: base(c.card, c.background) },
|
|
69
|
+
text: { primary: muiColor(c.foreground), secondary: base(c.muted, c.foreground) },
|
|
70
|
+
divider: c.border ? muiColor(c.border) : "rgba(0,0,0,0.12)",
|
|
71
|
+
},
|
|
72
|
+
shape: { borderRadius: radiusPx(theme) },
|
|
73
|
+
typography: muiTypography(theme),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Project the default typeset onto MUI's typography variants.
|
|
79
|
+
*
|
|
80
|
+
* MUI's theme is a serialized POJO — it ends up inside a `createTheme(...)`
|
|
81
|
+
* artifact where no CSS variables exist — so this reads `typesetScale`, the
|
|
82
|
+
* concrete-value form of the same ratio table `typesetCss` uses symbolically.
|
|
83
|
+
* The canvas render pass and the emitted artifact both come through here, so a
|
|
84
|
+
* preview cannot disagree with generated code.
|
|
85
|
+
*/
|
|
86
|
+
function muiTypography(theme: VellooTheme): NonNullable<ThemeOptions["typography"]> {
|
|
87
|
+
const typography = theme.typography;
|
|
88
|
+
const typeset = typography.typesets?.[DEFAULT_TYPESET_NAME];
|
|
89
|
+
const scale = typesetScale(typeset, {
|
|
90
|
+
...(typography.fontFamily ? { fontFamily: typography.fontFamily } : {}),
|
|
91
|
+
});
|
|
92
|
+
// The body face, falling back to the `sans` role then the system stack.
|
|
93
|
+
const bodyFamily =
|
|
94
|
+
scale.body.fontFamily ?? typography.fontFamily?.sans ?? "system-ui, -apple-system, sans-serif";
|
|
95
|
+
|
|
96
|
+
const variant = (role: keyof typeof scale) => {
|
|
97
|
+
const r = scale[role];
|
|
98
|
+
return {
|
|
99
|
+
// Only override the family when the typeset names a *different* face for
|
|
100
|
+
// this role; otherwise inherit the theme's own fontFamily.
|
|
101
|
+
...(r.fontFamily && r.fontFamily !== bodyFamily ? { fontFamily: r.fontFamily } : {}),
|
|
102
|
+
fontSize: `${r.fontSize}px`,
|
|
103
|
+
lineHeight: r.lineHeight,
|
|
104
|
+
letterSpacing: r.letterSpacing,
|
|
105
|
+
fontWeight: r.fontWeight,
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
fontFamily: bodyFamily,
|
|
111
|
+
fontSize: scale.body.fontSize,
|
|
112
|
+
h1: variant("h1"),
|
|
113
|
+
h2: variant("h2"),
|
|
114
|
+
h3: variant("h3"),
|
|
115
|
+
h4: variant("h4"),
|
|
116
|
+
h5: variant("h5"),
|
|
117
|
+
h6: variant("h6"),
|
|
118
|
+
subtitle1: variant("lead"),
|
|
119
|
+
subtitle2: variant("small"),
|
|
120
|
+
body1: variant("body"),
|
|
121
|
+
body2: variant("caption"),
|
|
122
|
+
caption: variant("caption"),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** The MUI `Theme` for the render pass — `createTheme` over {@link muiThemeOptions}. */
|
|
127
|
+
export function muiThemeFrom(theme: VellooTheme, dark = false): MuiTheme {
|
|
128
|
+
return createTheme(muiThemeOptions(theme, dark));
|
|
129
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lives in its own module (exported as `@velloo/provider-mui/version`) so
|
|
3
|
+
* version-only consumers — the CLI init wizard — don't pull the provider's
|
|
4
|
+
* registry (and with it all of @mui/material) into their import graph. The
|
|
5
|
+
* bundled CLI lazy-loads the full provider per folder config; see
|
|
6
|
+
* `packages/server/src/providers.ts`.
|
|
7
|
+
*/
|
|
8
|
+
export const MUI_VERSION = "6" as const;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { headingInlineStyle, textInlineStyle } from "@velloo/schema/typeset";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import type { ButtonProps, ContainerProps, InputProps, StackProps } from "./components.tsx";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Inline-styled variants of the no-library primitives, for a `none`-CSS folder
|
|
7
|
+
* (`config.styling.framework === "none"`). Identical props + structural defaults
|
|
8
|
+
* to the Tailwind set in `components.tsx`, but every default is a plain `style`
|
|
9
|
+
* object instead of a Tailwind class — so they paint with the JIT off. Theme
|
|
10
|
+
* tokens reach them as the CSS variables `themeToCss` injects
|
|
11
|
+
* (`var(--color-foreground)`, `var(--radius)`, …), so a `none/none` folder still
|
|
12
|
+
* themes. The node's authored `style` (set via `update_props`) merges last and wins.
|
|
13
|
+
*
|
|
14
|
+
* Typography is the same story one level deeper: Heading/Text reference the
|
|
15
|
+
* typeset's `var(--text-*)` / `var(--leading-*)` tokens rather than hardcoded
|
|
16
|
+
* rem values, so a `none/none` folder's type follows its typeset — and moves
|
|
17
|
+
* live when one changes — exactly like every other channel.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** Merge structural defaults with the node's authored inline style (author wins). */
|
|
21
|
+
function merge(
|
|
22
|
+
defaults: React.CSSProperties,
|
|
23
|
+
authored: React.CSSProperties | undefined,
|
|
24
|
+
): React.CSSProperties {
|
|
25
|
+
return authored ? { ...defaults, ...authored } : defaults;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Tailwind's spacing scale is 0.25rem per step (gap-4 ⇒ 1rem). */
|
|
29
|
+
const space = (n: number) => `${n * 0.25}rem`;
|
|
30
|
+
|
|
31
|
+
export const Box = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
32
|
+
({ style, ...rest }, ref) => <div ref={ref} style={style} {...rest} />,
|
|
33
|
+
);
|
|
34
|
+
Box.displayName = "Box";
|
|
35
|
+
|
|
36
|
+
const alignStyle: Record<NonNullable<StackProps["align"]>, string> = {
|
|
37
|
+
start: "flex-start",
|
|
38
|
+
center: "center",
|
|
39
|
+
end: "flex-end",
|
|
40
|
+
stretch: "stretch",
|
|
41
|
+
};
|
|
42
|
+
const justifyStyle: Record<NonNullable<StackProps["justify"]>, string> = {
|
|
43
|
+
start: "flex-start",
|
|
44
|
+
center: "center",
|
|
45
|
+
end: "flex-end",
|
|
46
|
+
between: "space-between",
|
|
47
|
+
around: "space-around",
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const Stack = React.forwardRef<HTMLDivElement, StackProps>(
|
|
51
|
+
({ direction = "col", gap = 4, align, justify, style, ...rest }, ref) => (
|
|
52
|
+
<div
|
|
53
|
+
ref={ref}
|
|
54
|
+
style={merge(
|
|
55
|
+
{
|
|
56
|
+
display: "flex",
|
|
57
|
+
flexDirection: direction === "row" ? "row" : "column",
|
|
58
|
+
gap: space(gap),
|
|
59
|
+
...(align ? { alignItems: alignStyle[align] } : {}),
|
|
60
|
+
...(justify ? { justifyContent: justifyStyle[justify] } : {}),
|
|
61
|
+
},
|
|
62
|
+
style,
|
|
63
|
+
)}
|
|
64
|
+
{...rest}
|
|
65
|
+
/>
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
Stack.displayName = "Stack";
|
|
69
|
+
|
|
70
|
+
const containerMaxWidth: Record<NonNullable<ContainerProps["size"]>, string> = {
|
|
71
|
+
sm: "640px",
|
|
72
|
+
md: "768px",
|
|
73
|
+
lg: "1024px",
|
|
74
|
+
xl: "1280px",
|
|
75
|
+
full: "100%",
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const Container = React.forwardRef<HTMLDivElement, ContainerProps>(
|
|
79
|
+
({ size = "md", style, ...rest }, ref) => (
|
|
80
|
+
<div
|
|
81
|
+
ref={ref}
|
|
82
|
+
style={merge(
|
|
83
|
+
{
|
|
84
|
+
marginInline: "auto",
|
|
85
|
+
width: "100%",
|
|
86
|
+
paddingInline: "1rem",
|
|
87
|
+
maxWidth: containerMaxWidth[size],
|
|
88
|
+
},
|
|
89
|
+
style,
|
|
90
|
+
)}
|
|
91
|
+
{...rest}
|
|
92
|
+
/>
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
Container.displayName = "Container";
|
|
96
|
+
|
|
97
|
+
const buttonVariantStyle: Record<NonNullable<ButtonProps["variant"]>, React.CSSProperties> = {
|
|
98
|
+
default: { background: "var(--color-foreground)", color: "var(--color-background)" },
|
|
99
|
+
ghost: { background: "transparent", color: "var(--color-foreground)" },
|
|
100
|
+
outline: {
|
|
101
|
+
background: "transparent",
|
|
102
|
+
color: "var(--color-foreground)",
|
|
103
|
+
border: "1px solid var(--color-border)",
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
108
|
+
({ variant = "default", type, style, ...rest }, ref) => (
|
|
109
|
+
<button
|
|
110
|
+
ref={ref}
|
|
111
|
+
type={type ?? "button"}
|
|
112
|
+
style={merge(
|
|
113
|
+
{
|
|
114
|
+
display: "inline-flex",
|
|
115
|
+
alignItems: "center",
|
|
116
|
+
justifyContent: "center",
|
|
117
|
+
gap: "0.5rem",
|
|
118
|
+
borderRadius: "var(--radius)",
|
|
119
|
+
padding: "0.5rem 1rem",
|
|
120
|
+
fontSize: "0.875rem",
|
|
121
|
+
fontWeight: 500,
|
|
122
|
+
cursor: "pointer",
|
|
123
|
+
...buttonVariantStyle[variant],
|
|
124
|
+
},
|
|
125
|
+
style,
|
|
126
|
+
)}
|
|
127
|
+
{...rest}
|
|
128
|
+
/>
|
|
129
|
+
),
|
|
130
|
+
);
|
|
131
|
+
Button.displayName = "Button";
|
|
132
|
+
|
|
133
|
+
export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
134
|
+
({ type = "text", value, onChange, style, ...rest }, ref) => {
|
|
135
|
+
const isStatic = value !== undefined && onChange === undefined;
|
|
136
|
+
return (
|
|
137
|
+
<input
|
|
138
|
+
ref={ref}
|
|
139
|
+
type={type}
|
|
140
|
+
value={value}
|
|
141
|
+
onChange={onChange}
|
|
142
|
+
readOnly={isStatic || rest.readOnly}
|
|
143
|
+
style={merge(
|
|
144
|
+
{
|
|
145
|
+
display: "block",
|
|
146
|
+
width: "100%",
|
|
147
|
+
borderRadius: "var(--radius)",
|
|
148
|
+
border: "1px solid var(--color-input)",
|
|
149
|
+
background: "var(--color-background)",
|
|
150
|
+
padding: "0.5rem 0.75rem",
|
|
151
|
+
fontSize: "0.875rem",
|
|
152
|
+
},
|
|
153
|
+
style,
|
|
154
|
+
)}
|
|
155
|
+
{...rest}
|
|
156
|
+
/>
|
|
157
|
+
);
|
|
158
|
+
},
|
|
159
|
+
);
|
|
160
|
+
Input.displayName = "Input";
|
|
161
|
+
|
|
162
|
+
export const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
163
|
+
({ style, ...rest }, ref) => (
|
|
164
|
+
<div
|
|
165
|
+
ref={ref}
|
|
166
|
+
style={merge(
|
|
167
|
+
{
|
|
168
|
+
borderRadius: "var(--radius)",
|
|
169
|
+
border: "1px solid var(--color-border)",
|
|
170
|
+
background: "var(--color-card)",
|
|
171
|
+
color: "var(--color-card-foreground)",
|
|
172
|
+
padding: "1.5rem",
|
|
173
|
+
boxShadow: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
|
|
174
|
+
},
|
|
175
|
+
style,
|
|
176
|
+
)}
|
|
177
|
+
{...rest}
|
|
178
|
+
/>
|
|
179
|
+
),
|
|
180
|
+
);
|
|
181
|
+
Card.displayName = "Card";
|
|
182
|
+
|
|
183
|
+
interface HeadingProps extends React.HTMLAttributes<HTMLHeadingElement> {
|
|
184
|
+
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export const Heading = React.forwardRef<HTMLHeadingElement, HeadingProps>(
|
|
188
|
+
({ level = 1, style, ...rest }, ref) => {
|
|
189
|
+
const Tag = `h${level}` as const;
|
|
190
|
+
return <Tag ref={ref} style={merge(headingInlineStyle(level), style)} {...rest} />;
|
|
191
|
+
},
|
|
192
|
+
);
|
|
193
|
+
Heading.displayName = "Heading";
|
|
194
|
+
|
|
195
|
+
interface TextProps extends React.HTMLAttributes<HTMLParagraphElement> {
|
|
196
|
+
variant?: "default" | "muted" | "small" | "lead";
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export const Text = React.forwardRef<HTMLParagraphElement, TextProps>(
|
|
200
|
+
({ variant = "default", style, ...rest }, ref) => (
|
|
201
|
+
<p ref={ref} style={merge(textInlineStyle(variant), style)} {...rest} />
|
|
202
|
+
),
|
|
203
|
+
);
|
|
204
|
+
Text.displayName = "Text";
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { clsx } from "clsx";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The no-library provider's primitives — thin wrappers over plain HTML
|
|
6
|
+
* elements. Anything that needs visual styling does it through Tailwind
|
|
7
|
+
* classes the user (or agent) supplies via the `className` prop. No
|
|
8
|
+
* portals, no providers, no internal state. This is intentionally the
|
|
9
|
+
* lowest-rope primitive set: ideal for throwaway prototypes, designs
|
|
10
|
+
* that haven't picked a UI library yet, and as the proof that the
|
|
11
|
+
* `ComponentProvider` abstraction works at the trivial end of the
|
|
12
|
+
* spectrum.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
interface DivProps extends React.HTMLAttributes<HTMLDivElement> {}
|
|
16
|
+
|
|
17
|
+
export const Box = React.forwardRef<HTMLDivElement, DivProps>(({ className, ...rest }, ref) => (
|
|
18
|
+
<div ref={ref} className={clsx(className)} {...rest} />
|
|
19
|
+
));
|
|
20
|
+
Box.displayName = "Box";
|
|
21
|
+
|
|
22
|
+
export interface StackProps extends DivProps {
|
|
23
|
+
/** Layout direction. Defaults to "col" (flex-column). */
|
|
24
|
+
direction?: "row" | "col";
|
|
25
|
+
/** Tailwind gap scale (2, 4, 6, …). Defaults to 4. */
|
|
26
|
+
gap?: number;
|
|
27
|
+
/** Cross-axis alignment. */
|
|
28
|
+
align?: "start" | "center" | "end" | "stretch";
|
|
29
|
+
/** Main-axis justification. */
|
|
30
|
+
justify?: "start" | "center" | "end" | "between" | "around";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const alignClass: Record<NonNullable<StackProps["align"]>, string> = {
|
|
34
|
+
start: "items-start",
|
|
35
|
+
center: "items-center",
|
|
36
|
+
end: "items-end",
|
|
37
|
+
stretch: "items-stretch",
|
|
38
|
+
};
|
|
39
|
+
const justifyClass: Record<NonNullable<StackProps["justify"]>, string> = {
|
|
40
|
+
start: "justify-start",
|
|
41
|
+
center: "justify-center",
|
|
42
|
+
end: "justify-end",
|
|
43
|
+
between: "justify-between",
|
|
44
|
+
around: "justify-around",
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const Stack = React.forwardRef<HTMLDivElement, StackProps>(
|
|
48
|
+
({ direction = "col", gap = 4, align, justify, className, ...rest }, ref) => (
|
|
49
|
+
<div
|
|
50
|
+
ref={ref}
|
|
51
|
+
className={clsx(
|
|
52
|
+
"flex",
|
|
53
|
+
direction === "row" ? "flex-row" : "flex-col",
|
|
54
|
+
`gap-${gap}`,
|
|
55
|
+
align ? alignClass[align] : undefined,
|
|
56
|
+
justify ? justifyClass[justify] : undefined,
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
{...rest}
|
|
60
|
+
/>
|
|
61
|
+
),
|
|
62
|
+
);
|
|
63
|
+
Stack.displayName = "Stack";
|
|
64
|
+
|
|
65
|
+
export interface ContainerProps extends DivProps {
|
|
66
|
+
/** Max-width preset. Defaults to "md". */
|
|
67
|
+
size?: "sm" | "md" | "lg" | "xl" | "full";
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const containerWidth: Record<NonNullable<ContainerProps["size"]>, string> = {
|
|
71
|
+
sm: "max-w-screen-sm",
|
|
72
|
+
md: "max-w-screen-md",
|
|
73
|
+
lg: "max-w-screen-lg",
|
|
74
|
+
xl: "max-w-screen-xl",
|
|
75
|
+
full: "max-w-full",
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const Container = React.forwardRef<HTMLDivElement, ContainerProps>(
|
|
79
|
+
({ size = "md", className, ...rest }, ref) => (
|
|
80
|
+
<div
|
|
81
|
+
ref={ref}
|
|
82
|
+
className={clsx("mx-auto w-full px-4", containerWidth[size], className)}
|
|
83
|
+
{...rest}
|
|
84
|
+
/>
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
Container.displayName = "Container";
|
|
88
|
+
|
|
89
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
90
|
+
variant?: "default" | "ghost" | "outline";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const buttonVariant: Record<NonNullable<ButtonProps["variant"]>, string> = {
|
|
94
|
+
default: "bg-foreground text-background hover:bg-foreground/90",
|
|
95
|
+
ghost: "bg-transparent text-foreground hover:bg-muted",
|
|
96
|
+
outline: "bg-transparent text-foreground border border-border hover:bg-muted",
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
100
|
+
({ variant = "default", className, type, ...rest }, ref) => (
|
|
101
|
+
<button
|
|
102
|
+
ref={ref}
|
|
103
|
+
type={type ?? "button"}
|
|
104
|
+
className={clsx(
|
|
105
|
+
"inline-flex items-center justify-center gap-2 rounded-md px-4 py-2 text-sm font-medium",
|
|
106
|
+
"focus-visible:outline-2 focus-visible:outline-offset-2",
|
|
107
|
+
buttonVariant[variant],
|
|
108
|
+
className,
|
|
109
|
+
)}
|
|
110
|
+
{...rest}
|
|
111
|
+
/>
|
|
112
|
+
),
|
|
113
|
+
);
|
|
114
|
+
Button.displayName = "Button";
|
|
115
|
+
|
|
116
|
+
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
|
|
117
|
+
|
|
118
|
+
export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
119
|
+
({ className, type = "text", value, onChange, ...rest }, ref) => {
|
|
120
|
+
// Same canvas-safe pattern as the shadcn snapshot's Input: if a
|
|
121
|
+
// static `value` is supplied without `onChange`, switch to
|
|
122
|
+
// `readOnly` so React doesn't warn about uncontrolled→controlled.
|
|
123
|
+
const isStatic = value !== undefined && onChange === undefined;
|
|
124
|
+
return (
|
|
125
|
+
<input
|
|
126
|
+
ref={ref}
|
|
127
|
+
type={type}
|
|
128
|
+
value={value}
|
|
129
|
+
onChange={onChange}
|
|
130
|
+
readOnly={isStatic || rest.readOnly}
|
|
131
|
+
className={clsx(
|
|
132
|
+
"block w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
133
|
+
"placeholder:text-muted-foreground focus-visible:outline-2 focus-visible:outline-offset-2",
|
|
134
|
+
className,
|
|
135
|
+
)}
|
|
136
|
+
{...rest}
|
|
137
|
+
/>
|
|
138
|
+
);
|
|
139
|
+
},
|
|
140
|
+
);
|
|
141
|
+
Input.displayName = "Input";
|
|
142
|
+
|
|
143
|
+
export interface CardProps extends DivProps {}
|
|
144
|
+
|
|
145
|
+
export const Card = React.forwardRef<HTMLDivElement, CardProps>(({ className, ...rest }, ref) => (
|
|
146
|
+
<div
|
|
147
|
+
ref={ref}
|
|
148
|
+
className={clsx(
|
|
149
|
+
"rounded-lg border border-border bg-card p-6 text-card-foreground shadow-sm",
|
|
150
|
+
className,
|
|
151
|
+
)}
|
|
152
|
+
{...rest}
|
|
153
|
+
/>
|
|
154
|
+
));
|
|
155
|
+
Card.displayName = "Card";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { dirname, join } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { type FrameworkAdapter, type Manifest, TAILWIND_CLASSNAME } from "@velloo/provider";
|
|
4
|
+
import { resolveProviderSrcDir } from "@velloo/provider/src-dir";
|
|
5
|
+
import { NONE_INLINE_INTRO, NONE_INTRO } from "./intro.ts";
|
|
6
|
+
import { NONE_MANIFEST } from "./manifest.ts";
|
|
7
|
+
import { registry } from "./registry.ts";
|
|
8
|
+
import { inlineRegistry } from "./registry-inline.ts";
|
|
9
|
+
|
|
10
|
+
export { Box, Button, Card, Container, Input, Stack } from "./components.tsx";
|
|
11
|
+
export { NONE_MANIFEST } from "./manifest.ts";
|
|
12
|
+
export { registry } from "./registry.ts";
|
|
13
|
+
|
|
14
|
+
export { noLibVersion } from "./version.ts";
|
|
15
|
+
|
|
16
|
+
import { noLibVersion } from "./version.ts";
|
|
17
|
+
|
|
18
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
|
|
20
|
+
/** Component sources + Tailwind entry CSS. Resolves from source and from the
|
|
21
|
+
* bundled CLI (build.ts copies them to `<dist>/pkgs/provider-none/src`). */
|
|
22
|
+
const srcDir = resolveProviderSrcDir(here, "provider-none", process.env.VELLOO_NOLIB_SRC);
|
|
23
|
+
|
|
24
|
+
/** Absolute path to the Tailwind entry CSS shipped with the no-library provider. */
|
|
25
|
+
export const entryCssPath: string = join(srcDir, "tailwind-entry.css");
|
|
26
|
+
|
|
27
|
+
/** Absolute path to the no-library provider's component sources for JIT scanning. */
|
|
28
|
+
export const componentsDir: string = srcDir;
|
|
29
|
+
|
|
30
|
+
export async function loadManifest(): Promise<Manifest> {
|
|
31
|
+
return NONE_MANIFEST;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Build the no-library `ComponentProvider`. Identical interface shape
|
|
36
|
+
* to the shadcn provider — the renderer / JIT / codegen / canvas don't
|
|
37
|
+
* know which one is active; they just consume the contract.
|
|
38
|
+
*/
|
|
39
|
+
export function createProvider(): FrameworkAdapter {
|
|
40
|
+
return {
|
|
41
|
+
id: "none",
|
|
42
|
+
version: noLibVersion,
|
|
43
|
+
componentsDir,
|
|
44
|
+
styleEntryPath: entryCssPath,
|
|
45
|
+
registry,
|
|
46
|
+
loadManifest,
|
|
47
|
+
label: `none ${noLibVersion}`,
|
|
48
|
+
// Default to Tailwind (existing folders); a folder whose `config.styling`
|
|
49
|
+
// is `none` resolves to the inline-`style` channel instead.
|
|
50
|
+
styleChannel: TAILWIND_CLASSNAME,
|
|
51
|
+
styleChannels: ["tailwind-classname", "style"],
|
|
52
|
+
mcpIntro: (channel) => [...(channel === "style" ? NONE_INLINE_INTRO : NONE_INTRO)],
|
|
53
|
+
// Inline-styled primitives for the `style` channel; Tailwind-classed for
|
|
54
|
+
// every other channel. Lets a `none/none` folder paint with the JIT off.
|
|
55
|
+
registryForChannel: (kind) => (kind === "style" ? inlineRegistry : registry),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP instruction framing for a no-framework folder
|
|
3
|
+
* (`FrameworkAdapter.mcpIntro`), one variant per style channel.
|
|
4
|
+
*
|
|
5
|
+
* The server's base brief is framework-neutral, so these state the (small)
|
|
6
|
+
* vocabulary positively rather than correcting a shadcn claim.
|
|
7
|
+
*/
|
|
8
|
+
export const NONE_INTRO: readonly string[] = [
|
|
9
|
+
"**This folder has no component library** — only bare primitives wrapping plain HTML: `Box`/`Stack`/`Container` for layout, `Card`, `Button`, `Input`, plus the velloo helpers (`Heading`/`Text`, `Image`, `Gradient`, `Layer`, `SVG`, `Divider`, `Placeholder`, `Icon`). There is no `Badge`/`Avatar`/`Tabs`/`Dialog` — build those from primitives or define snippets. Call `list_components` for the exact set. Styling is **Tailwind classes**.",
|
|
10
|
+
"",
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
export const NONE_INLINE_INTRO: readonly string[] = [
|
|
14
|
+
"**This folder has no component library and no CSS framework** — bare primitives wrapping plain HTML (`Box`/`Stack`/`Container`, `Card`, `Button`, `Input`) plus the velloo helpers (`Heading`/`Text`, `Image`, `Icon`, `SVG`, `Divider`, `Gradient`, `Layer`, `Placeholder`). There is no `Badge`/`Avatar`/`Tabs`/`Dialog` — build those from primitives or snippets. Call `list_components` for the exact set.",
|
|
15
|
+
"",
|
|
16
|
+
'**Style through inline `style` objects.** `update_props { style: { display: "flex", gap: "16px", padding: "24px", borderRadius: "8px", color: "var(--color-foreground)" } }` — a plain React style object (merges shallowly; an inner `null` drops a key, `style: null` clears). Reference theme tokens as CSS variables (`var(--color-primary)`, `var(--radius)`) from `get_theme` so the design stays themable. `emit_code` emits `style={{…}}` on plain elements — no imports, no Tailwind. Tailwind utility diagnostics do not apply.',
|
|
17
|
+
"",
|
|
18
|
+
];
|