velloo 0.5.0 → 0.7.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/README.md +116 -227
- package/THIRD-PARTY-NOTICES.md +3 -3
- package/canvas/assets/index-BQ5710lu.js +29 -0
- package/canvas/assets/index-GNLd0pCG.css +2 -0
- package/canvas/assets/lucide-all-DIRZdJPK.js +1 -0
- package/canvas/index.html +2 -2
- package/{chunk-qpv28z8d.js → chunk-0e5j6nqs.js} +1 -1
- package/{chunk-vrvkvb0v.js → chunk-0pxm5v0b.js} +3 -3
- package/{chunk-a16mz9zf.js → chunk-0vaff40g.js} +1 -1
- package/{chunk-42bj6r30.js → chunk-3m28pvzr.js} +1 -1
- package/{chunk-33t0csxs.js → chunk-4y2xy1kf.js} +2 -2
- package/{chunk-d4r0myxr.js → chunk-531xzfq5.js} +1 -1
- package/{chunk-1h3gqy7w.js → chunk-5s1wjhtj.js} +1 -1
- package/{chunk-4pkw6d9n.js → chunk-5x4nw0zz.js} +5 -5
- package/{chunk-b3x80jc1.js → chunk-5yhnnhkd.js} +1 -1
- package/{chunk-675tr675.js → chunk-64pex3mw.js} +1 -1
- package/chunk-667ag8ts.js +2 -0
- package/chunk-7gyzh0vq.js +5 -0
- package/{chunk-4sjvdakg.js → chunk-82x2jkfq.js} +1 -1
- package/{chunk-5y9hem1j.js → chunk-84n18xgx.js} +257 -3
- package/{chunk-edgwx026.js → chunk-abr2hgay.js} +1 -1
- package/{chunk-cqt1dpxd.js → chunk-acsv6m3n.js} +1 -1
- package/{chunk-j7tzbt3d.js → chunk-asfgvzse.js} +1 -1
- package/{chunk-0wqxb8r9.js → chunk-b8vcbbrg.js} +1 -1
- package/chunk-bms1sg4c.js +2 -0
- package/chunk-brnkprt5.js +723 -0
- package/{chunk-afe25dpr.js → chunk-bys7pqdb.js} +1 -1
- package/chunk-d0j8dg1e.js +3 -0
- package/chunk-d93kpv7s.js +12 -0
- package/chunk-dvh0b2r4.js +3 -0
- package/{chunk-5ma8zbty.js → chunk-eh2xp4v6.js} +1 -1
- package/{chunk-z78c1kf8.js → chunk-ejppcfa5.js} +1 -1
- package/{chunk-ngbqd7kb.js → chunk-ex36z3b3.js} +317 -119
- package/{chunk-6ytv1v2r.js → chunk-fmcm06xb.js} +1 -1
- package/{chunk-3ffs39e8.js → chunk-fvezyap4.js} +1 -1
- package/chunk-g7d065ek.js +2 -0
- package/{chunk-tw4kw4ps.js → chunk-g8xrwjvq.js} +2 -2
- package/{chunk-df557bn4.js → chunk-gbq5wv7x.js} +1 -1
- package/chunk-gcce587w.js +3 -0
- package/{chunk-cdqah1hy.js → chunk-gfppsgvv.js} +1 -1
- package/{chunk-5f0xv80x.js → chunk-j306gr0c.js} +1 -1
- package/chunk-j4fn2a2b.js +2 -0
- package/chunk-jbgde2v9.js +2 -0
- package/{chunk-wkqrb2tz.js → chunk-kkvf0xk2.js} +1 -1
- package/{chunk-d9kx7v12.js → chunk-md4mpvqc.js} +1 -1
- package/{chunk-vryadew3.js → chunk-mdgwdqnq.js} +2 -2
- package/chunk-p93x4pn2.js +3 -0
- package/chunk-pjkkp7xa.js +2 -0
- package/chunk-qp3wahg4.js +2 -0
- package/{chunk-f45p6kcb.js → chunk-qqrac4va.js} +1 -1
- package/chunk-qrnkrkkt.js +2 -0
- package/chunk-rqd4swxx.js +2 -0
- package/{chunk-xzkczmgg.js → chunk-rxkvjyst.js} +1 -1
- package/chunk-s84vxcdv.js +4 -0
- package/chunk-sjjnm4a1.js +2 -0
- package/chunk-skk6yvnw.js +3 -0
- package/{chunk-ahm4zd56.js → chunk-sme6hv6f.js} +1 -1
- package/chunk-snak5zpr.js +5 -0
- package/{chunk-gn9wcc1b.js → chunk-srp5gyr1.js} +1 -1
- package/{chunk-rd65xm6r.js → chunk-vdbr81a3.js} +1 -1
- package/chunk-vs8j3x6t.js +3 -0
- package/{chunk-hr3gbak5.js → chunk-xg71h7nb.js} +1 -1
- package/chunk-xzf52wvn.js +6 -0
- package/chunk-ykpctq15.js +6 -0
- package/chunk-zv17t1n7.js +3 -0
- package/cli.js +1 -1
- package/launcher.cjs +3 -1
- package/package.json +1 -1
- package/pkgs/helpers/src/box.tsx +12 -6
- package/pkgs/helpers/src/descriptors.ts +7 -0
- package/pkgs/helpers/src/icon.tsx +5 -3
- package/pkgs/helpers/src/index.ts +9 -6
- package/pkgs/helpers/src/lowering.ts +0 -24
- package/pkgs/helpers/src/primitive-classes.tsx +43 -0
- package/pkgs/helpers/src/text.tsx +29 -5
- package/pkgs/provider-antd/src/intro.ts +3 -3
- package/pkgs/provider-antd/src/manifest.ts +479 -57
- package/pkgs/provider-antd/src/registry.ts +8 -5
- package/pkgs/provider-antd/src/render-pass.ts +10 -4
- package/pkgs/provider-antd/src/reset-css.d.ts +5 -0
- package/pkgs/provider-antd/src/theme.ts +54 -11
- package/pkgs/provider-chakra/src/manifest.ts +6 -1
- package/pkgs/provider-mui/src/index.ts +4 -2
- package/pkgs/provider-mui/src/manifest.ts +11 -1
- package/pkgs/provider-mui/src/render-pass.ts +15 -1
- package/pkgs/provider-mui/src/theme.ts +10 -4
- package/pkgs/provider-none/src/components-inline.tsx +20 -14
- package/pkgs/provider-none/src/components.tsx +17 -54
- package/pkgs/provider-none/src/manifest.ts +1 -0
- package/pkgs/schema/src/annotation.ts +6 -3
- package/pkgs/schema/src/comment.ts +10 -1
- package/pkgs/schema/src/config.ts +4 -1
- package/pkgs/schema/src/index.ts +16 -1
- package/pkgs/schema/src/node-identity.ts +97 -0
- package/pkgs/schema/src/node.ts +49 -23
- package/pkgs/schema/src/snippet-resolve.ts +18 -12
- package/pkgs/schema/src/svg-sanitize.ts +3 -0
- package/pkgs/schema/src/theme.ts +6 -1
- package/pkgs/schema/src/typeset.ts +45 -21
- package/pkgs/shadcn-snapshot/dist/manifest.json +7 -0
- package/pkgs/shadcn-snapshot/src/components/ui/alert.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/aspect-ratio.tsx +2 -3
- package/pkgs/shadcn-snapshot/src/components/ui/attachment.tsx +3 -4
- package/pkgs/shadcn-snapshot/src/components/ui/avatar.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/badge.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/breadcrumb.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/bubble.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/button-group.tsx +3 -4
- package/pkgs/shadcn-snapshot/src/components/ui/button.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/card.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/carousel.tsx +3 -4
- package/pkgs/shadcn-snapshot/src/components/ui/chart.tsx +1 -1
- package/pkgs/shadcn-snapshot/src/components/ui/direction.tsx +2 -3
- package/pkgs/shadcn-snapshot/src/components/ui/empty.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/field.tsx +3 -4
- package/pkgs/shadcn-snapshot/src/components/ui/input-group.tsx +3 -4
- package/pkgs/shadcn-snapshot/src/components/ui/item.tsx +3 -4
- package/pkgs/shadcn-snapshot/src/components/ui/kbd.tsx +2 -3
- package/pkgs/shadcn-snapshot/src/components/ui/label.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/marker.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/message.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/native-select.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/navigation-menu.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/pagination.tsx +3 -4
- package/pkgs/shadcn-snapshot/src/components/ui/progress.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/radio-group.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/scroll-area.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/separator.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/skeleton.tsx +2 -3
- package/pkgs/shadcn-snapshot/src/components/ui/spinner.tsx +2 -3
- package/pkgs/shadcn-snapshot/src/components/ui/table.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/tabs.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/components/ui/toggle.tsx +2 -4
- package/pkgs/shadcn-snapshot/src/shadcn-tailwind.css +1 -1
- package/pkgs/shadcn-snapshot/src/tailwind-entry.css +1 -1
- package/canvas/assets/index-BDBBHdHH.css +0 -2
- package/canvas/assets/index-QdsLJNY9.js +0 -29
- package/canvas/assets/lucide-all-R8DUyY-B.js +0 -1
- package/chunk-0rdf6trc.js +0 -2
- package/chunk-0wafc9aw.js +0 -4
- package/chunk-10hap8kc.js +0 -6
- package/chunk-18eqh3s1.js +0 -2
- package/chunk-19xyzep8.js +0 -2
- package/chunk-49w26e94.js +0 -5
- package/chunk-66qgm91k.js +0 -708
- package/chunk-6cgvzwec.js +0 -3
- package/chunk-75sc3adm.js +0 -2
- package/chunk-7cexzg71.js +0 -2
- package/chunk-98rann8t.js +0 -2
- package/chunk-asvdqkdp.js +0 -6
- package/chunk-emv1j50t.js +0 -2
- package/chunk-ewgdcgrk.js +0 -2
- package/chunk-mm8wv3bg.js +0 -3
- package/chunk-nkqtnwzz.js +0 -2
- package/chunk-q3kf8243.js +0 -3
- package/chunk-ryga3ny1.js +0 -3
- package/chunk-sb5h27w9.js +0 -3
- package/chunk-vgx47anc.js +0 -3
- package/chunk-w6f40y2x.js +0 -11
- package/chunk-we8hvy6e.js +0 -2
- package/chunk-ycrddh47.js +0 -5
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ComponentNode,
|
|
3
|
+
type EmitAsRef,
|
|
4
|
+
isComponentNode,
|
|
5
|
+
isParamRef,
|
|
6
|
+
isSnippetInstance,
|
|
7
|
+
isTextNode,
|
|
8
|
+
type Node,
|
|
9
|
+
type ParamRef,
|
|
10
|
+
type RepoComponentRef,
|
|
11
|
+
type SnippetInstance,
|
|
12
|
+
type TextNode,
|
|
13
|
+
} from "./node.ts";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A `$ref` the renderer resolves itself rather than through any registry.
|
|
17
|
+
* Synthetic refs are never persisted — a preview synthesizes them — and every
|
|
18
|
+
* provider has to be able to draw them, so they can't be library components
|
|
19
|
+
* (a `none` folder has no `Badge` to draw a param slot with).
|
|
20
|
+
*/
|
|
21
|
+
export const PARAM_TAG_REF = "velloo:param-tag";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The ref a node serializes to when the canvas bundle has no browser source
|
|
25
|
+
* for it and the client must drop in its server render instead.
|
|
26
|
+
*/
|
|
27
|
+
export const STATIC_REF = "velloo:static";
|
|
28
|
+
|
|
29
|
+
export type SyntheticRef = typeof PARAM_TAG_REF | typeof STATIC_REF;
|
|
30
|
+
|
|
31
|
+
const SYNTHETIC_REFS: readonly SyntheticRef[] = [PARAM_TAG_REF, STATIC_REF];
|
|
32
|
+
|
|
33
|
+
export function isSyntheticRef(ref: string): ref is SyntheticRef {
|
|
34
|
+
return (SYNTHETIC_REFS as readonly string[]).includes(ref);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** A component node carrying a repository identity (see {@link ComponentNode.$repo}). */
|
|
38
|
+
export type RepoNode = ComponentNode & { $repo: RepoComponentRef };
|
|
39
|
+
|
|
40
|
+
/** A component node carrying an emit-time host facade (see {@link ComponentNode.$emitAs}). */
|
|
41
|
+
export type EmitAsNode = ComponentNode & { $emitAs: EmitAsRef };
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* What a node's own fields say it is. Purely structural: no registry, no
|
|
45
|
+
* catalog, no I/O — a `named` shape is as far as the node alone can go, and
|
|
46
|
+
* `resolveNodeIdentity` in `@velloo/provider` takes it from there.
|
|
47
|
+
*
|
|
48
|
+
* The order of the `$`-keys is the contract, stated here once and nowhere
|
|
49
|
+
* else: `$snippet`, then `$param`, then a component — where an identity
|
|
50
|
+
* (`$repo`) beats an emit-time facade (`$emitAs`) beats a synthetic ref beats
|
|
51
|
+
* a plain name — then `$text`. A malformed value carrying both `$snippet` and `$ref` is a
|
|
52
|
+
* snippet instance, as every walker has always read it.
|
|
53
|
+
*/
|
|
54
|
+
export type NodeShape =
|
|
55
|
+
| { kind: "repo"; node: RepoNode; ref: string; repo: RepoComponentRef }
|
|
56
|
+
| { kind: "emit-as"; node: EmitAsNode; ref: string; emitAs: EmitAsRef }
|
|
57
|
+
| { kind: "synthetic"; node: ComponentNode; ref: SyntheticRef }
|
|
58
|
+
| { kind: "named"; node: ComponentNode; ref: string }
|
|
59
|
+
| { kind: "snippet"; node: SnippetInstance }
|
|
60
|
+
| { kind: "param"; node: ParamRef }
|
|
61
|
+
/** A run of text beside elements: a bare text node, no element of its own. */
|
|
62
|
+
| { kind: "text"; node: TextNode; text: string }
|
|
63
|
+
/** Not a node at all — a raw scalar or object sitting in a node position. */
|
|
64
|
+
| { kind: "invalid"; value: unknown };
|
|
65
|
+
|
|
66
|
+
/** Discriminate a value by its own fields. Accepts `unknown`: node positions are a trust boundary. */
|
|
67
|
+
export function nodeShape(value: unknown): NodeShape {
|
|
68
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
69
|
+
return { kind: "invalid", value };
|
|
70
|
+
}
|
|
71
|
+
const node = value as Node;
|
|
72
|
+
if (isSnippetInstance(node)) return { kind: "snippet", node };
|
|
73
|
+
if (isParamRef(node)) return { kind: "param", node };
|
|
74
|
+
if (isComponentNode(node)) {
|
|
75
|
+
if (node.$repo !== undefined) {
|
|
76
|
+
return { kind: "repo", node: node as RepoNode, ref: node.$ref, repo: node.$repo };
|
|
77
|
+
}
|
|
78
|
+
if (node.$emitAs !== undefined) {
|
|
79
|
+
return { kind: "emit-as", node: node as EmitAsNode, ref: node.$ref, emitAs: node.$emitAs };
|
|
80
|
+
}
|
|
81
|
+
if (isSyntheticRef(node.$ref)) {
|
|
82
|
+
return { kind: "synthetic", node, ref: node.$ref };
|
|
83
|
+
}
|
|
84
|
+
return { kind: "named", node, ref: node.$ref };
|
|
85
|
+
}
|
|
86
|
+
if (isTextNode(node)) return { kind: "text", node, text: node.$text };
|
|
87
|
+
return { kind: "invalid", value };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Whether a raw JSON value is itself a node. The check every walker needs when
|
|
92
|
+
* it meets a *prop* value — a `children` prop carrying inline rich text, a slot
|
|
93
|
+
* prop holding an icon — where a node and a plain value are both legal.
|
|
94
|
+
*/
|
|
95
|
+
export function isNode(value: unknown): value is Node {
|
|
96
|
+
return nodeShape(value).kind !== "invalid";
|
|
97
|
+
}
|
package/pkgs/schema/src/node.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* A node tree is a discriminated union over
|
|
4
|
+
* A node tree is a discriminated union over four shapes, distinguished by
|
|
5
5
|
* which `$`-prefixed key is present:
|
|
6
6
|
*
|
|
7
7
|
* - `ComponentNode` — a real shadcn / velloo component (`{ $ref }`).
|
|
@@ -13,6 +13,11 @@ import { z } from "zod";
|
|
|
13
13
|
* substituted with the corresponding instance arg at render time. May
|
|
14
14
|
* appear as a child node OR anywhere inside a `props` value via the
|
|
15
15
|
* normal JSON walk during substitution.
|
|
16
|
+
* - `TextNode` — `{ $text }`. A run of text sitting beside elements
|
|
17
|
+
* (`<li>Remote <a>Apply</a></li>`). It renders as a bare text node, with no
|
|
18
|
+
* element of its own, so no selector in the app's stylesheet can tell the
|
|
19
|
+
* design's DOM from the app's. Text that is a component's *whole* content
|
|
20
|
+
* stays in `props.children`.
|
|
16
21
|
*
|
|
17
22
|
* Optional fields are spelled `?: T | undefined` rather than `?: T`. Under
|
|
18
23
|
* `exactOptionalPropertyTypes` those differ, but not for a shape that round-
|
|
@@ -46,18 +51,27 @@ export type ComponentNode = {
|
|
|
46
51
|
* subtree — preserving the app's real component identity through
|
|
47
52
|
* capture → design → emit. Absent ⇒ the node emits as itself.
|
|
48
53
|
*/
|
|
49
|
-
$emitAs?:
|
|
54
|
+
$emitAs?: EmitAsRef | undefined;
|
|
50
55
|
/**
|
|
51
56
|
* Repository component identity: this node IS a component the host app
|
|
52
57
|
* imports (a package export such as Mantine's `Tabs`, or the app's own
|
|
53
58
|
* `StatCard`), not a library component. `$ref` stays the JSX name codegen
|
|
54
|
-
* prints; the identity decides rendering and imports.
|
|
55
|
-
*
|
|
56
|
-
* explicit on the node rather than a registry-order accident.
|
|
59
|
+
* prints; the identity decides rendering and imports. Where it sits against
|
|
60
|
+
* the node's other keys is `nodeShape`'s to say (`./node-identity.ts`).
|
|
57
61
|
*/
|
|
58
62
|
$repo?: RepoComponentRef | undefined;
|
|
59
63
|
};
|
|
60
64
|
|
|
65
|
+
/**
|
|
66
|
+
* A host component a node emits *as*, in place of its own subtree. Superseded
|
|
67
|
+
* in practice by {@link RepoComponentRef}, which renders for real; kept because
|
|
68
|
+
* design folders carry it.
|
|
69
|
+
*/
|
|
70
|
+
export type EmitAsRef = {
|
|
71
|
+
name: string;
|
|
72
|
+
importPath: string;
|
|
73
|
+
};
|
|
74
|
+
|
|
61
75
|
/**
|
|
62
76
|
* Where a repository component comes from. The import form is kept exactly as
|
|
63
77
|
* code generation must print it; the resolved file is runtime cache data and
|
|
@@ -107,7 +121,11 @@ export type ParamRef = {
|
|
|
107
121
|
$param: string;
|
|
108
122
|
};
|
|
109
123
|
|
|
110
|
-
export type
|
|
124
|
+
export type TextNode = {
|
|
125
|
+
$text: string;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export type Node = ComponentNode | SnippetInstance | ParamRef | TextNode;
|
|
111
129
|
|
|
112
130
|
export function isComponentNode(n: Node): n is ComponentNode {
|
|
113
131
|
return typeof (n as { $ref?: unknown }).$ref === "string";
|
|
@@ -121,6 +139,10 @@ export function isParamRef(n: Node): n is ParamRef {
|
|
|
121
139
|
return typeof (n as { $param?: unknown }).$param === "string";
|
|
122
140
|
}
|
|
123
141
|
|
|
142
|
+
export function isTextNode(n: Node): n is TextNode {
|
|
143
|
+
return typeof (n as { $text?: unknown }).$text === "string";
|
|
144
|
+
}
|
|
145
|
+
|
|
124
146
|
/**
|
|
125
147
|
* Format constraint for `$id` values. Must start with a letter; the rest
|
|
126
148
|
* is letters / digits / dashes / underscores. Matches typical anchor
|
|
@@ -138,18 +160,16 @@ export const NodeIdSchema = z
|
|
|
138
160
|
|
|
139
161
|
/**
|
|
140
162
|
* A bare string/number in a `children` array is a common first-try shape
|
|
141
|
-
* ("just put the label here")
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* `children` typed `Node[]` for every downstream consumer. The styled-run
|
|
145
|
-
* idiom (a mixed array in the `children` *prop*) is still preferred for rich
|
|
146
|
-
* text; this just removes a needless failure.
|
|
163
|
+
* ("just put the label here"), and it means what it says: text. It becomes a
|
|
164
|
+
* text node rather than being rejected, which keeps `children` typed `Node[]`
|
|
165
|
+
* for every downstream consumer. An empty string is nothing to hold.
|
|
147
166
|
*/
|
|
148
|
-
function
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
167
|
+
function scalarChildren(items: (string | number | Node)[]): Node[] {
|
|
168
|
+
return items.flatMap((item): Node[] => {
|
|
169
|
+
if (typeof item !== "string" && typeof item !== "number") return [item];
|
|
170
|
+
const text = String(item);
|
|
171
|
+
return text === "" ? [] : [{ $text: text }];
|
|
172
|
+
});
|
|
153
173
|
}
|
|
154
174
|
|
|
155
175
|
const EmitAsSchema = z.object({
|
|
@@ -200,7 +220,7 @@ const ComponentNodeSchema: z.ZodType<ComponentNode> = z.lazy(() =>
|
|
|
200
220
|
props: z.record(z.string(), z.unknown()).optional(),
|
|
201
221
|
children: z
|
|
202
222
|
.array(z.union([z.string(), z.number(), NodeSchema]))
|
|
203
|
-
.transform(
|
|
223
|
+
.transform(scalarChildren)
|
|
204
224
|
.optional(),
|
|
205
225
|
$emitAs: EmitAsSchema.optional(),
|
|
206
226
|
$repo: RepoComponentRefSchema.optional(),
|
|
@@ -258,10 +278,14 @@ const ParamRefSchema: z.ZodType<ParamRef> = z.object({
|
|
|
258
278
|
$param: z.string().min(1),
|
|
259
279
|
});
|
|
260
280
|
|
|
281
|
+
const TextNodeSchema: z.ZodType<TextNode> = z.strictObject({
|
|
282
|
+
$text: z.string().min(1),
|
|
283
|
+
});
|
|
284
|
+
|
|
261
285
|
/**
|
|
262
286
|
* Key-routed parse instead of `z.union`: a malformed node yields the
|
|
263
287
|
* issues of the *one* branch its `$`-key selects (with a full path),
|
|
264
|
-
* not a
|
|
288
|
+
* not a four-branch union explosion. The MCP layer surfaces these
|
|
265
289
|
* issues verbatim to agents, so error shape is part of the tool UX.
|
|
266
290
|
*/
|
|
267
291
|
export const NodeSchema: z.ZodType<Node> = z
|
|
@@ -271,7 +295,7 @@ export const NodeSchema: z.ZodType<Node> = z
|
|
|
271
295
|
ctx.addIssue({
|
|
272
296
|
code: "custom",
|
|
273
297
|
message:
|
|
274
|
-
'node must be an object with one of "$ref" (component), "$snippet" (instance),
|
|
298
|
+
'node must be an object with one of "$ref" (component), "$snippet" (instance), "$param" (param ref), or "$text" (text beside elements)',
|
|
275
299
|
});
|
|
276
300
|
return z.NEVER;
|
|
277
301
|
}
|
|
@@ -283,12 +307,14 @@ export const NodeSchema: z.ZodType<Node> = z
|
|
|
283
307
|
? SnippetInstanceSchema
|
|
284
308
|
: typeof v.$param === "string"
|
|
285
309
|
? ParamRefSchema
|
|
286
|
-
:
|
|
310
|
+
: typeof v.$text === "string"
|
|
311
|
+
? TextNodeSchema
|
|
312
|
+
: null;
|
|
287
313
|
if (!branch) {
|
|
288
314
|
ctx.addIssue({
|
|
289
315
|
code: "custom",
|
|
290
316
|
message:
|
|
291
|
-
'node needs exactly one of "$ref" (component), "$snippet" (snippet instance),
|
|
317
|
+
'node needs exactly one of "$ref" (component), "$snippet" (snippet instance), "$param" (param ref, snippet bodies only), or "$text" (text beside elements)',
|
|
292
318
|
});
|
|
293
319
|
return z.NEVER;
|
|
294
320
|
}
|
|
@@ -323,6 +349,6 @@ export const NodeSchema: z.ZodType<Node> = z
|
|
|
323
349
|
* have to narrow by node kind first.
|
|
324
350
|
*/
|
|
325
351
|
export function nodeId(n: Node): string | undefined {
|
|
326
|
-
if (isParamRef(n)) return undefined;
|
|
352
|
+
if (isParamRef(n) || isTextNode(n)) return undefined;
|
|
327
353
|
return (n as { $id?: string }).$id;
|
|
328
354
|
}
|
|
@@ -48,7 +48,7 @@ function isTruthy(v: unknown): boolean {
|
|
|
48
48
|
return true;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
/** A `$param` that substituted to a
|
|
51
|
+
/** A `$param` that substituted to a boolean or null where a child node was expected. */
|
|
52
52
|
export interface InvalidParamPlacement {
|
|
53
53
|
param: string;
|
|
54
54
|
/** typeof the resolved value (or "null") — for a precise error message. */
|
|
@@ -63,13 +63,17 @@ export interface InvalidParamPlacement {
|
|
|
63
63
|
* Unknown param names are collected in `missing` (the offending
|
|
64
64
|
* substitution resolves to undefined) rather than thrown.
|
|
65
65
|
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* the
|
|
71
|
-
*
|
|
72
|
-
*
|
|
66
|
+
* A string or number param in a *node* position — a component node's own
|
|
67
|
+
* `children` array — is the text it holds, and becomes a text node, exactly
|
|
68
|
+
* as a bare string written there does (`scalarChildren` in node.ts). It was a
|
|
69
|
+
* refusal before text nodes existed, and one that only surfaced at the next
|
|
70
|
+
* render: the write was accepted, and the screenshot after it failed. An
|
|
71
|
+
* empty string is nothing to hold.
|
|
72
|
+
*
|
|
73
|
+
* `invalid` collects what is left: a boolean or null param in a node position,
|
|
74
|
+
* which is a flag wired where content goes. A `children` *prop* value
|
|
75
|
+
* (`props.children`) is plain content, not a node position, so any scalar
|
|
76
|
+
* param there is correct and never flagged.
|
|
73
77
|
*/
|
|
74
78
|
export function substituteSnippetParams(
|
|
75
79
|
value: unknown,
|
|
@@ -92,11 +96,13 @@ export function substituteSnippetParams(
|
|
|
92
96
|
const resolved = args[name];
|
|
93
97
|
// An omitted optional param resolves to nothing — never a mis-wire.
|
|
94
98
|
if (resolved === OMITTED) return DROP;
|
|
95
|
-
if (inNodePosition
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
if (!inNodePosition || (resolved !== null && typeof resolved === "object")) return resolved;
|
|
100
|
+
if (typeof resolved === "string" || typeof resolved === "number") {
|
|
101
|
+
const text = String(resolved);
|
|
102
|
+
return text === "" ? DROP : { $text: text };
|
|
98
103
|
}
|
|
99
|
-
|
|
104
|
+
invalid.push({ param: name, valueType: resolved === null ? "null" : typeof resolved });
|
|
105
|
+
return undefined;
|
|
100
106
|
}
|
|
101
107
|
if (typeof (v as { $if?: unknown }).$if === "string") {
|
|
102
108
|
const cond = v as { $if: string; eq?: unknown; then?: unknown; else?: unknown };
|
|
@@ -76,6 +76,9 @@ const ALLOWED_ELEMENTS: ReadonlyMap<string, string> = new Map(
|
|
|
76
76
|
].map((name) => [name.toLowerCase(), name]),
|
|
77
77
|
);
|
|
78
78
|
|
|
79
|
+
/** The static SVG elements, by their canonical (camelCase) names. */
|
|
80
|
+
export const SVG_ELEMENT_NAMES: ReadonlySet<string> = new Set(ALLOWED_ELEMENTS.values());
|
|
81
|
+
|
|
79
82
|
/**
|
|
80
83
|
* Elements whose presence means the input tried to run or load something.
|
|
81
84
|
* They are dropped like any unknown element; naming them is what lets
|
package/pkgs/schema/src/theme.ts
CHANGED
|
@@ -131,7 +131,12 @@ export function resolveColors(theme: Theme, dark = false): Colors {
|
|
|
131
131
|
* CSS-safe ident so they can't inject into the emitted stylesheet.
|
|
132
132
|
*/
|
|
133
133
|
const PaletteSchema = z.record(
|
|
134
|
-
z
|
|
134
|
+
z
|
|
135
|
+
.string()
|
|
136
|
+
.regex(
|
|
137
|
+
/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,
|
|
138
|
+
'palette keys are lowercase kebab-case, letter first — "primary-soft", "success-500", "border-primary-300"',
|
|
139
|
+
),
|
|
135
140
|
z.string().min(1),
|
|
136
141
|
);
|
|
137
142
|
|
|
@@ -231,8 +231,21 @@ export function headingClasses(level: unknown): string {
|
|
|
231
231
|
return TYPESET_CLASSES[role];
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
/**
|
|
235
|
-
|
|
234
|
+
/**
|
|
235
|
+
* A `Text` inside a `Text` with no variant of its own is that paragraph's
|
|
236
|
+
* text: a run changes a word's colour or weight, and restating the body rung
|
|
237
|
+
* on it would resize `12 km` inside a 17px line to the default 14.
|
|
238
|
+
*/
|
|
239
|
+
function inheritsItsParagraph(variant: unknown, run: boolean): boolean {
|
|
240
|
+
return run && variant === undefined;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* The Tailwind classes a `Text` of this variant renders with, tone included.
|
|
245
|
+
* `run` is true beneath another `Text`.
|
|
246
|
+
*/
|
|
247
|
+
export function textClasses(variant: unknown, run = false): string {
|
|
248
|
+
if (inheritsItsParagraph(variant, run)) return "";
|
|
236
249
|
const v = textVariant(variant);
|
|
237
250
|
const tone = TEXT_TONE_BY_VARIANT[v];
|
|
238
251
|
return tone
|
|
@@ -246,8 +259,12 @@ export function headingInlineStyle(level: unknown): Record<string, string | numb
|
|
|
246
259
|
return { ...TYPESET_INLINE_STYLE[role] };
|
|
247
260
|
}
|
|
248
261
|
|
|
249
|
-
/**
|
|
250
|
-
|
|
262
|
+
/**
|
|
263
|
+
* The inline `style` a `Text` of this variant renders with, on the `none`-CSS
|
|
264
|
+
* channel. `run` is true beneath another `Text`.
|
|
265
|
+
*/
|
|
266
|
+
export function textInlineStyle(variant: unknown, run = false): Record<string, string | number> {
|
|
267
|
+
if (inheritsItsParagraph(variant, run)) return {};
|
|
251
268
|
const v = textVariant(variant);
|
|
252
269
|
const tone = TEXT_TONE_BY_VARIANT[v];
|
|
253
270
|
return {
|
|
@@ -287,24 +304,31 @@ export function typesetUtilityClasses(): string[] {
|
|
|
287
304
|
}
|
|
288
305
|
|
|
289
306
|
/**
|
|
290
|
-
* The scale as
|
|
291
|
-
* paired leading and tracking
|
|
292
|
-
*
|
|
293
|
-
*
|
|
307
|
+
* The scale as Tailwind v3 `theme.extend` maps. `fontSize` carries each role's
|
|
308
|
+
* paired leading and tracking (so `text-h1` alone sets all three), and
|
|
309
|
+
* `lineHeight` / `letterSpacing` make the standalone `leading-<role>` /
|
|
310
|
+
* `tracking-<role>` utilities exist — v3 derives no utility from a fontSize
|
|
311
|
+
* tuple's extras, and `TYPESET_CLASSES` spells all three. Every value is a
|
|
312
|
+
* `var()` into the typeset sheet, so a v3 app re-derives inside a
|
|
313
|
+
* `.typeset-<preset>` region exactly like a v4 one.
|
|
294
314
|
*/
|
|
295
|
-
export function
|
|
296
|
-
string,
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
315
|
+
export function typesetV3Theme(): {
|
|
316
|
+
fontSize: Record<string, [string, { lineHeight: string; letterSpacing: string }]>;
|
|
317
|
+
lineHeight: Record<string, string>;
|
|
318
|
+
letterSpacing: Record<string, string>;
|
|
319
|
+
} {
|
|
320
|
+
const fontSize: Record<string, [string, { lineHeight: string; letterSpacing: string }]> = {};
|
|
321
|
+
const lineHeight: Record<string, string> = {};
|
|
322
|
+
const letterSpacing: Record<string, string> = {};
|
|
323
|
+
for (const role of TYPESET_SCALE_NAMES) {
|
|
324
|
+
fontSize[role] = [
|
|
325
|
+
`var(--text-${role})`,
|
|
326
|
+
{ lineHeight: `var(--leading-${role})`, letterSpacing: `var(--tracking-${role})` },
|
|
327
|
+
];
|
|
328
|
+
lineHeight[role] = `var(--leading-${role})`;
|
|
329
|
+
letterSpacing[role] = `var(--tracking-${role})`;
|
|
330
|
+
}
|
|
331
|
+
return { fontSize, lineHeight, letterSpacing };
|
|
308
332
|
}
|
|
309
333
|
|
|
310
334
|
/**
|
|
@@ -460,6 +460,7 @@
|
|
|
460
460
|
"group": "layout",
|
|
461
461
|
"family": "Box",
|
|
462
462
|
"source": "velloo",
|
|
463
|
+
"plainElement": true,
|
|
463
464
|
"props": [
|
|
464
465
|
{
|
|
465
466
|
"name": "as",
|
|
@@ -7477,6 +7478,12 @@
|
|
|
7477
7478
|
"optional": true,
|
|
7478
7479
|
"control": "string"
|
|
7479
7480
|
},
|
|
7481
|
+
{
|
|
7482
|
+
"name": "preserveAspectRatio",
|
|
7483
|
+
"type": "string | undefined",
|
|
7484
|
+
"optional": true,
|
|
7485
|
+
"control": "string"
|
|
7486
|
+
},
|
|
7480
7487
|
{
|
|
7481
7488
|
"name": "color",
|
|
7482
7489
|
"type": "string | undefined",
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/alert).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
|
|
6
5
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
7
6
|
import type * as React from "react";
|
|
8
|
-
|
|
9
7
|
import { cn } from "../../lib/utils.ts";
|
|
10
8
|
|
|
11
9
|
const alertVariants = cva(
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/aspect-ratio).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
"use client";
|
|
6
5
|
|
|
7
6
|
import { AspectRatio as AspectRatioPrimitive } from "radix-ui";
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/attachment).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
|
|
6
5
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
7
6
|
import { Slot } from "radix-ui";
|
|
8
7
|
import type * as React from "react";
|
|
9
|
-
|
|
10
8
|
import { cn } from "../../lib/utils.ts";
|
|
9
|
+
|
|
11
10
|
import { Button } from "./button.tsx";
|
|
12
11
|
|
|
13
12
|
const attachmentVariants = cva(
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/avatar).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
"use client";
|
|
6
5
|
|
|
7
6
|
import { Avatar as AvatarPrimitive } from "radix-ui";
|
|
8
7
|
import type * as React from "react";
|
|
9
|
-
|
|
10
8
|
import { cn } from "../../lib/utils.ts";
|
|
11
9
|
|
|
12
10
|
function Avatar({
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/badge).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
|
|
6
5
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
7
6
|
import { Slot } from "radix-ui";
|
|
8
7
|
import type * as React from "react";
|
|
9
|
-
|
|
10
8
|
import { cn } from "../../lib/utils.ts";
|
|
11
9
|
|
|
12
10
|
const badgeVariants = cva(
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/breadcrumb).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
|
|
6
5
|
import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react";
|
|
7
6
|
import { Slot } from "radix-ui";
|
|
8
7
|
import type * as React from "react";
|
|
9
|
-
|
|
10
8
|
import { cn } from "../../lib/utils.ts";
|
|
11
9
|
|
|
12
10
|
function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/bubble).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
|
|
6
5
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
7
6
|
import { Slot } from "radix-ui";
|
|
8
7
|
import type * as React from "react";
|
|
9
|
-
|
|
10
8
|
import { cn } from "../../lib/utils.ts";
|
|
11
9
|
|
|
12
10
|
function BubbleGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/button-group).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
6
5
|
import { Slot } from "radix-ui";
|
|
7
|
-
|
|
8
6
|
import { cn } from "../../lib/utils.ts";
|
|
7
|
+
|
|
9
8
|
import { Separator } from "./separator.tsx";
|
|
10
9
|
|
|
11
10
|
const buttonGroupVariants = cva(
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/button).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
|
|
6
5
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
7
6
|
import { Slot } from "radix-ui";
|
|
8
7
|
import type * as React from "react";
|
|
9
|
-
|
|
10
8
|
import { cn } from "../../lib/utils.ts";
|
|
11
9
|
|
|
12
10
|
const buttonVariants = cva(
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/card).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
import type * as React from "react";
|
|
6
|
-
|
|
7
5
|
import { cn } from "../../lib/utils.ts";
|
|
8
6
|
|
|
9
7
|
function Card({
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/carousel).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
"use client";
|
|
6
5
|
|
|
7
6
|
import useEmblaCarousel, { type UseEmblaCarouselType } from "embla-carousel-react";
|
|
8
7
|
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
|
|
9
8
|
import * as React from "react";
|
|
10
|
-
|
|
11
9
|
import { cn } from "../../lib/utils.ts";
|
|
10
|
+
|
|
12
11
|
import { Button } from "./button.tsx";
|
|
13
12
|
|
|
14
13
|
type CarouselApi = UseEmblaCarouselType[1];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Velloo-flavored Chart. shadcn's `chart` is a recharts wrapper that needs a
|
|
1
|
+
// Canvas-safe: Velloo-flavored Chart. shadcn's `chart` is a recharts wrapper that needs a
|
|
2
2
|
// measured DOM (ResponsiveContainer), so it renders nothing under the
|
|
3
3
|
// renderer's static SSR. We render a realistic preview server-side via
|
|
4
4
|
// echarts' headless SSR-to-SVG mode (see chart-option.ts) — bar/line/area/
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/direction).
|
|
2
|
-
//
|
|
3
|
-
// Regenerate with `bun run vendor` —
|
|
4
|
-
// canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
|
|
2
|
+
// Design-mode fork for the Velloo canvas — not the shadcn the IDE chrome renders.
|
|
3
|
+
// Regenerate with `bun run vendor` — the pipeline is scripts/vendor-shadcn/.
|
|
5
4
|
"use client";
|
|
6
5
|
|
|
7
6
|
import { Direction } from "radix-ui";
|