@marver-design/marver 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/{build-D0GnIR4G.mjs → build-CNoXE13J.mjs} +3 -3
- package/dist/cli.mjs +23 -7
- package/dist/{dev-BK4x3PBr.mjs → dev-Blyy4jOL.mjs} +24 -5
- package/dist/init-3h9pXEzp.mjs +337 -0
- package/dist/manifest-CHmKAAtG.mjs +298 -0
- package/dist/{plugin-DB5t2WUl.mjs → plugin-DiDJA9n-.mjs} +157 -120
- package/dist/{serve-BPNmWeJx.mjs → serve-BvbAbWeK.mjs} +8 -1
- package/package.json +4 -3
- package/src/client/frame-host/bridge.js +8 -2
- package/src/client/frame-host/main.tsx +7 -1
- package/src/client/shell/App.tsx +69 -8
- package/src/client/shell/canvas/FrameNode.tsx +9 -0
- package/src/client/shell/store.ts +58 -8
- package/src/client/shell/styles.css +21 -2
- package/templates/AGENTS-embedded.md +38 -26
- package/templates/AGENTS-studio.md +38 -26
- package/templates/instructions/boards.md +38 -0
- package/templates/instructions/brand.md +60 -0
- package/templates/instructions/components.md +52 -0
- package/templates/instructions/configure.md +44 -0
- package/templates/instructions/craft.md +90 -0
- package/templates/instructions/discover.md +52 -0
- package/templates/instructions/reference/color.md +53 -0
- package/templates/instructions/reference/concepts.md +68 -0
- package/templates/instructions/reference/copy.md +57 -0
- package/templates/instructions/reference/critique.md +53 -0
- package/templates/instructions/reference/delight.md +35 -0
- package/templates/instructions/reference/layout.md +51 -0
- package/templates/instructions/reference/motion.md +66 -0
- package/templates/instructions/reference/operate.md +38 -0
- package/templates/instructions/reference/slop.md +76 -0
- package/templates/instructions/reference/states.md +48 -0
- package/templates/instructions/reference/tune.md +61 -0
- package/templates/instructions/reference/typography.md +45 -0
- package/templates/instructions/review.md +51 -0
- package/templates/instructions/wireframe.md +49 -0
- package/dist/config-DMBEpdEN.mjs +0 -132
- package/dist/init-DcOy1krf.mjs +0 -168
package/dist/init-DcOy1krf.mjs
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { t as NAME } from "./cli.mjs";
|
|
2
|
-
import { r as detectHost, t as DEFAULTS } from "./config-DMBEpdEN.mjs";
|
|
3
|
-
import { dirname, join, relative } from "node:path";
|
|
4
|
-
import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
//#region src/cli/init.ts
|
|
7
|
-
const pkgDir = () => join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
8
|
-
/** Idempotent scaffolder: never overwrites existing files; every host-repo touch prints a diff. */
|
|
9
|
-
function init(root, opts) {
|
|
10
|
-
const host = detectHost(root);
|
|
11
|
-
const design = join(root, "design");
|
|
12
|
-
const templates = join(pkgDir(), "templates");
|
|
13
|
-
const created = [];
|
|
14
|
-
const write = (rel, content) => {
|
|
15
|
-
const file = join(design, rel);
|
|
16
|
-
if (existsSync(file)) return;
|
|
17
|
-
mkdirSync(dirname(file), { recursive: true });
|
|
18
|
-
writeFileSync(file, content);
|
|
19
|
-
created.push(`design/${rel}`);
|
|
20
|
-
};
|
|
21
|
-
write("config.ts", configTemplate(opts.mode));
|
|
22
|
-
if (host.themeCss) {
|
|
23
|
-
const relCss = relative(design, join(root, host.themeCss)).split("\\").join("/");
|
|
24
|
-
write("theme.css", themeWrapper(relCss, host.tailwind === 4));
|
|
25
|
-
} else console.warn(`[${NAME}] no theme CSS detected - set \`theme\` in design/config.ts when you have one.`);
|
|
26
|
-
write("providers.tsx", providersTemplate(host.router, host.toaster, host.routerPkg));
|
|
27
|
-
write("AGENTS.md", readFileSync(join(templates, `AGENTS-${opts.mode}.md`), "utf8").replaceAll("{{UI_ALIAS}}", host.shadcn?.uiAlias ?? "@/components/ui"));
|
|
28
|
-
write("tsconfig.json", readFileSync(join(templates, "design-tsconfig.json"), "utf8"));
|
|
29
|
-
write(".gitignore", ".local/\n.dist/\n");
|
|
30
|
-
write("scenes/_layout.tsx", readFileSync(join(templates, "root-layout.tsx"), "utf8"));
|
|
31
|
-
if (!existsSync(join(design, "boards"))) {
|
|
32
|
-
mkdirSync(join(design, "boards"), { recursive: true });
|
|
33
|
-
writeFileSync(join(design, "boards", ".gitkeep"), "");
|
|
34
|
-
created.push("design/boards/");
|
|
35
|
-
}
|
|
36
|
-
if (opts.demo && !existsSync(join(design, "scenes", "demo"))) {
|
|
37
|
-
cpSync(join(templates, "demo"), join(design, "scenes", "demo"), { recursive: true });
|
|
38
|
-
created.push("design/scenes/demo/ (3 frames)");
|
|
39
|
-
}
|
|
40
|
-
if (host.tsconfigSweepsDesign) patchTsconfigExclude(root);
|
|
41
|
-
console.log(`\n${NAME} initialized (${opts.mode} mode). Created:`);
|
|
42
|
-
for (const f of created) console.log(` + ${f}`);
|
|
43
|
-
if (host.router === "next") console.log(`\n note: Next.js support is partial until M3 - HTML frames and next-free components work today.`);
|
|
44
|
-
console.log(`\n commit design/ - only .local/ is ignored`);
|
|
45
|
-
console.log(` uninstall = delete design/, remove the ${NAME} dependency${host.tsconfigSweepsDesign ? ", revert the \"design\" line in tsconfig exclude" : ""}`);
|
|
46
|
-
console.log(`\n next: npx ${NAME} dev (canvas on http://localhost:${DEFAULTS.port} by default)\n`);
|
|
47
|
-
console.log(` then, to your agent: "Read design/AGENTS.md. Build an onboarding scene - welcome, form, done - mobile-first, using our components."\n`);
|
|
48
|
-
}
|
|
49
|
-
function patchTsconfigExclude(root) {
|
|
50
|
-
const file = join(root, "tsconfig.json");
|
|
51
|
-
if (!existsSync(file)) return;
|
|
52
|
-
const raw = readFileSync(file, "utf8");
|
|
53
|
-
try {
|
|
54
|
-
let next;
|
|
55
|
-
if (/"exclude"\s*:/.test(raw)) next = raw.replace(/("exclude"\s*:\s*\[)/, "$1\"design\", ");
|
|
56
|
-
else {
|
|
57
|
-
const at = firstJsonBrace(raw);
|
|
58
|
-
if (at < 0) throw new Error("no object brace found");
|
|
59
|
-
next = raw.slice(0, at + 1) + "\n \"exclude\": [\"design\"]," + raw.slice(at + 1);
|
|
60
|
-
}
|
|
61
|
-
if (next === raw) throw new Error("no anchor matched");
|
|
62
|
-
writeFileSync(file, next);
|
|
63
|
-
console.log(`\n patched tsconfig.json (the only host file touched):`);
|
|
64
|
-
console.log(` + "design" added to "exclude" (revert this line to fully uninstall)`);
|
|
65
|
-
} catch {
|
|
66
|
-
console.warn(` could not patch tsconfig.json - add "design" to its "exclude" yourself.`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/** Index of the first `{` outside //, /* *\/ comments and strings (tsconfig is JSONC). */
|
|
70
|
-
function firstJsonBrace(src) {
|
|
71
|
-
let inLine = false, inBlock = false, inStr = false;
|
|
72
|
-
for (let i = 0; i < src.length; i++) {
|
|
73
|
-
const c = src[i], n = src[i + 1];
|
|
74
|
-
if (inLine) {
|
|
75
|
-
if (c === "\n") inLine = false;
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
if (inBlock) {
|
|
79
|
-
if (c === "*" && n === "/") {
|
|
80
|
-
inBlock = false;
|
|
81
|
-
i++;
|
|
82
|
-
}
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
if (inStr) {
|
|
86
|
-
if (c === "\\") i++;
|
|
87
|
-
else if (c === "\"") inStr = false;
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (c === "/" && n === "/") {
|
|
91
|
-
inLine = true;
|
|
92
|
-
i++;
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
if (c === "/" && n === "*") {
|
|
96
|
-
inBlock = true;
|
|
97
|
-
i++;
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
if (c === "\"") {
|
|
101
|
-
inStr = true;
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
if (c === "{") return i;
|
|
105
|
-
}
|
|
106
|
-
return -1;
|
|
107
|
-
}
|
|
108
|
-
const configTemplate = (mode) => `// ${NAME} config - OPTIONAL. Delete this file and everything still works on defaults.
|
|
109
|
-
// Theme lives in design/theme.css (it imports your app's real stylesheet) - not here.
|
|
110
|
-
// Sharp edges (native Node TS import): erasable syntax only (no enums/namespaces),
|
|
111
|
-
// relative imports need extensions, tsconfig paths are ignored here.
|
|
112
|
-
export default {
|
|
113
|
-
mode: ${JSON.stringify(mode)},
|
|
114
|
-
// Device widths for frames and the Devices view. Rename, retune, or uncomment tv.
|
|
115
|
-
viewports: {
|
|
116
|
-
mobile: { width: 390, height: 844 },
|
|
117
|
-
tablet: { width: 768, height: 1024 },
|
|
118
|
-
laptop: { width: 1280, height: 800 },
|
|
119
|
-
monitor: { width: 1920, height: 1080 },
|
|
120
|
-
// tv: { width: 3840, height: 2160 },
|
|
121
|
-
},
|
|
122
|
-
themes: ["light", "dark"],
|
|
123
|
-
port: ${DEFAULTS.port},
|
|
124
|
-
// Canvas zoom feel: 1 = default, 1.2 = 20% faster, 0.8 = 20% slower.
|
|
125
|
-
// zoomSpeed: 1,
|
|
126
|
-
// Publishing (\`${NAME} build\` + \`${NAME} serve\`): gate identity + branding footer.
|
|
127
|
-
// name/logo default to the host package.json name and design/logo.svg (then public/).
|
|
128
|
-
// branding is the small "Powered by Marver.design" line under the gate. Marver is
|
|
129
|
-
// free, and that line is how it spreads - we'd love it if you leave it on, but it
|
|
130
|
-
// is yours to remove, no strings: share: { branding: false }.
|
|
131
|
-
// share: { name: "My App", logo: "design/logo.svg", branding: true },
|
|
132
|
-
}
|
|
133
|
-
`;
|
|
134
|
-
const themeWrapper = (relCss, v4) => `/* ${NAME} theme wrapper - imports the app's real theme; the app's own build never sees design/. */
|
|
135
|
-
@import "${relCss}";
|
|
136
|
-
${v4 ? `@source "./";\n` : ""}`;
|
|
137
|
-
function providersTemplate(router, toaster, routerPkg = "react-router-dom") {
|
|
138
|
-
const imports = [`import type { ReactNode } from 'react'`];
|
|
139
|
-
let open = "", close = "";
|
|
140
|
-
if (router === "react-router") {
|
|
141
|
-
imports.push(`import { MemoryRouter } from '${routerPkg}'`);
|
|
142
|
-
open += "<MemoryRouter>";
|
|
143
|
-
close = "</MemoryRouter>" + close;
|
|
144
|
-
}
|
|
145
|
-
let toasterEl = "";
|
|
146
|
-
if (toaster === "sonner") {
|
|
147
|
-
imports.push(`import { Toaster } from 'sonner'`);
|
|
148
|
-
toasterEl = "<Toaster />";
|
|
149
|
-
}
|
|
150
|
-
if (toaster === "react-hot-toast") {
|
|
151
|
-
imports.push(`import { Toaster } from 'react-hot-toast'`);
|
|
152
|
-
toasterEl = "<Toaster />";
|
|
153
|
-
}
|
|
154
|
-
return `// Mock contexts wrapped around every frame. Scaffolded by ${NAME} init from what it detected - yours to edit.
|
|
155
|
-
${imports.join("\n")}
|
|
156
|
-
|
|
157
|
-
export default function Providers({ children }: { children: ReactNode }) {
|
|
158
|
-
return (
|
|
159
|
-
${open || "<>"}
|
|
160
|
-
{children}
|
|
161
|
-
${toasterEl}
|
|
162
|
-
${close || "</>"}
|
|
163
|
-
)
|
|
164
|
-
}
|
|
165
|
-
`;
|
|
166
|
-
}
|
|
167
|
-
//#endregion
|
|
168
|
-
export { init };
|