@pauldvlp/vp-pkg-shadcn 0.4.1 → 0.5.1
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 +7 -8
- package/dist/index.js +219 -99
- package/package.json +2 -4
package/README.md
CHANGED
|
@@ -9,10 +9,10 @@ A [Vite+](https://viteplus.dev) **package generator** that drops a shared, fully
|
|
|
9
9
|
|
|
10
10
|
- `packages/ui` — a shared shadcn design system (Tailwind v4, fonts, `lib/utils`, `components/ui/*`)
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
Options can be passed on the `vp create` command line (anything after `--`) or answered interactively,
|
|
13
|
+
and the **shadcn theme is materialized at create time** from the preset you choose. Unlike
|
|
14
|
+
[`@pauldvlp/vp-react-ts-shadcn`](../vp-react-ts-shadcn) (which scaffolds a whole monorepo), this only
|
|
15
|
+
emits `packages/ui` and leaves the rest of your repo untouched.
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
@@ -27,9 +27,8 @@ vp create @pauldvlp:vp-pkg-shadcn -- \
|
|
|
27
27
|
--scope @acme --base base --preset vega --iconLibrary lucide --components button,card,dialog
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
>
|
|
31
|
-
>
|
|
32
|
-
> Bingo's CLI does not accept `--no-x` / `--x=false` cleanly. Omit them and answer the prompt.
|
|
30
|
+
> **Boolean** options (`--cssVariables`, `--rtl`, `--pointer`, `--install`) accept both forms: pass
|
|
31
|
+
> `--rtl` to enable or `--no-rtl` to disable. Omit any option to answer it at the interactive prompt.
|
|
33
32
|
|
|
34
33
|
### Requirements
|
|
35
34
|
|
|
@@ -40,7 +39,7 @@ generator does **not** edit your `pnpm-workspace.yaml` or any app — wiring a c
|
|
|
40
39
|
|
|
41
40
|
### Where it lands (the `--directory`)
|
|
42
41
|
|
|
43
|
-
The generator emits the package contents at the **root** of its file tree, and
|
|
42
|
+
The generator emits the package contents at the **root** of its file tree, and the runtime writes them under
|
|
44
43
|
the target directory — which **defaults to `ui`** (so within `vp create`'s monorepo flow it lands at
|
|
45
44
|
`<chosen-parent>/ui`, e.g. `packages/ui`). Pass `--directory <path>` to place it elsewhere. `--scope`
|
|
46
45
|
defaults to the **surrounding monorepo's scope** (read from the nearest `pnpm-workspace.yaml`'s
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// bin/index.ts
|
|
4
|
-
import
|
|
5
|
-
import path3 from "node:path";
|
|
6
|
-
import * as prompts from "@clack/prompts";
|
|
4
|
+
import * as prompts2 from "@clack/prompts";
|
|
7
5
|
|
|
8
6
|
// ../template-kit/src/index.ts
|
|
7
|
+
import { execFileSync } from "node:child_process";
|
|
9
8
|
import fs from "node:fs";
|
|
10
9
|
import path from "node:path";
|
|
10
|
+
import * as prompts from "@clack/prompts";
|
|
11
11
|
var RENAME = {
|
|
12
|
-
_gitignore: ".gitignore"
|
|
12
|
+
_gitignore: ".gitignore",
|
|
13
|
+
_dockerignore: ".dockerignore",
|
|
14
|
+
"_env.example": ".env.example"
|
|
13
15
|
};
|
|
14
16
|
var DEFAULT_PRESET = "b30557okNu";
|
|
15
17
|
var ICON_LIBS = {
|
|
@@ -99,6 +101,16 @@ function addIconDeps(pkg, iconLibrary) {
|
|
|
99
101
|
const iconDeps = ICON_LIBS[iconLibrary] ?? ICON_LIBS.hugeicons;
|
|
100
102
|
pkg.dependencies = { ...pkg.dependencies, ...iconDeps };
|
|
101
103
|
}
|
|
104
|
+
function validateScope(value) {
|
|
105
|
+
return /^@?[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(value.trim()) ? void 0 : "must be a package scope/name, e.g. @acme";
|
|
106
|
+
}
|
|
107
|
+
function validatePreset(value) {
|
|
108
|
+
return /^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(value.trim()) ? void 0 : "must be a style name or ui.shadcn.com code";
|
|
109
|
+
}
|
|
110
|
+
function validateComponents(value) {
|
|
111
|
+
const parts = value.split(",").map((c) => c.trim()).filter(Boolean);
|
|
112
|
+
return parts.every((c) => /^[a-z0-9][a-z0-9-]*$/.test(c)) ? void 0 : "comma-separated component names, e.g. button,card,dialog";
|
|
113
|
+
}
|
|
102
114
|
function withRequiredComponents(csv, required = ["button", "badge"]) {
|
|
103
115
|
const requested = csv.split(",").map((c) => c.trim()).filter(Boolean);
|
|
104
116
|
return Array.from(/* @__PURE__ */ new Set([...required, ...requested]));
|
|
@@ -123,105 +135,217 @@ function uiComponentsJson(theme) {
|
|
|
123
135
|
}
|
|
124
136
|
};
|
|
125
137
|
}
|
|
126
|
-
function
|
|
138
|
+
function shadcnInitArgs(opts) {
|
|
127
139
|
return [
|
|
128
|
-
|
|
129
|
-
|
|
140
|
+
"--base",
|
|
141
|
+
opts.base,
|
|
142
|
+
"--preset",
|
|
143
|
+
opts.preset,
|
|
130
144
|
opts.cssVariables ? "--css-variables" : "--no-css-variables",
|
|
131
145
|
opts.rtl ? "--rtl" : "--no-rtl",
|
|
132
146
|
opts.pointer ? "--pointer" : "--no-pointer",
|
|
133
147
|
"--no-reinstall",
|
|
134
148
|
"-y",
|
|
135
149
|
"-f"
|
|
136
|
-
]
|
|
150
|
+
];
|
|
151
|
+
}
|
|
152
|
+
function defineTemplate(config) {
|
|
153
|
+
return config;
|
|
154
|
+
}
|
|
155
|
+
function writeTree(node, dir, root = path.resolve(dir)) {
|
|
156
|
+
for (const [name, value] of Object.entries(node)) {
|
|
157
|
+
const p = path.resolve(dir, name);
|
|
158
|
+
const rel = path.relative(root, p);
|
|
159
|
+
if (rel === "" || rel === ".." || rel.startsWith(`..${path.sep}`) || path.isAbsolute(rel)) {
|
|
160
|
+
throw new Error(`Refusing to write outside the target directory: ${name}`);
|
|
161
|
+
}
|
|
162
|
+
if (typeof value === "string") {
|
|
163
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
164
|
+
fs.writeFileSync(p, value);
|
|
165
|
+
} else {
|
|
166
|
+
fs.mkdirSync(p, { recursive: true });
|
|
167
|
+
writeTree(value, p, root);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function parseArgv(argv2, descriptors) {
|
|
172
|
+
const booleanKeys = new Set(descriptors.filter((d) => d.type === "boolean").map((d) => d.key));
|
|
173
|
+
const values = {};
|
|
174
|
+
let directory;
|
|
175
|
+
for (let i = 0; i < argv2.length; i++) {
|
|
176
|
+
const arg = argv2[i];
|
|
177
|
+
if (!arg.startsWith("--")) continue;
|
|
178
|
+
let body = arg.slice(2);
|
|
179
|
+
if (body.startsWith("no-") && booleanKeys.has(body.slice(3))) {
|
|
180
|
+
values[body.slice(3)] = false;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
let inline;
|
|
184
|
+
const eq = body.indexOf("=");
|
|
185
|
+
if (eq !== -1) {
|
|
186
|
+
inline = body.slice(eq + 1);
|
|
187
|
+
body = body.slice(0, eq);
|
|
188
|
+
}
|
|
189
|
+
if (body === "directory") {
|
|
190
|
+
directory = inline ?? argv2[++i];
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (booleanKeys.has(body)) {
|
|
194
|
+
values[body] = inline === void 0 ? true : inline !== "false";
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
values[body] = inline ?? argv2[++i] ?? "";
|
|
198
|
+
}
|
|
199
|
+
return { values, directory };
|
|
200
|
+
}
|
|
201
|
+
function resolveDefault(d, options, directory) {
|
|
202
|
+
return typeof d.default === "function" ? d.default({ options, directory }) : d.default;
|
|
203
|
+
}
|
|
204
|
+
async function promptForOption(d, def) {
|
|
205
|
+
if (d.type === "boolean") {
|
|
206
|
+
return prompts.confirm({ message: d.message, initialValue: def === void 0 ? false : Boolean(def) });
|
|
207
|
+
}
|
|
208
|
+
if (d.type === "select") {
|
|
209
|
+
return prompts.select({
|
|
210
|
+
message: d.message,
|
|
211
|
+
options: (d.choices ?? []).map((c) => ({ value: c, label: c })),
|
|
212
|
+
initialValue: def
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const fallback = def === void 0 ? void 0 : String(def);
|
|
216
|
+
return prompts.text({
|
|
217
|
+
message: d.message,
|
|
218
|
+
placeholder: fallback,
|
|
219
|
+
defaultValue: fallback,
|
|
220
|
+
// When a default exists, an empty submit means "use the default" — don't run validation on it,
|
|
221
|
+
// otherwise a rule like the port check would reject pressing Enter to accept 3000.
|
|
222
|
+
validate: d.validate ? (value) => !value && fallback !== void 0 ? void 0 : d.validate(value ?? "") : void 0
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
function printHelp(template) {
|
|
226
|
+
const lines = [];
|
|
227
|
+
if (template.about?.name) lines.push(template.about.name);
|
|
228
|
+
if (template.about?.description) lines.push(template.about.description);
|
|
229
|
+
lines.push("", "Options:", " --directory <dir> Where to scaffold");
|
|
230
|
+
for (const d of template.options) {
|
|
231
|
+
const hint = d.type === "select" && d.choices ? ` <${d.choices.join("|")}>` : d.type === "boolean" ? ` / --no-${d.key}` : " <value>";
|
|
232
|
+
lines.push(` --${d.key}${hint} ${d.message}`);
|
|
233
|
+
}
|
|
234
|
+
console.log(lines.join("\n"));
|
|
235
|
+
}
|
|
236
|
+
function initGit(dir) {
|
|
237
|
+
try {
|
|
238
|
+
execFileSync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: dir, stdio: "ignore" });
|
|
239
|
+
return;
|
|
240
|
+
} catch {
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
execFileSync("git", ["init"], { cwd: dir, stdio: "ignore" });
|
|
244
|
+
execFileSync("git", ["add", "-A"], { cwd: dir, stdio: "ignore" });
|
|
245
|
+
let identity = [];
|
|
246
|
+
try {
|
|
247
|
+
execFileSync("git", ["config", "user.email"], { cwd: dir, stdio: "ignore" });
|
|
248
|
+
} catch {
|
|
249
|
+
identity = ["-c", "user.name=create", "-c", "user.email=create@users.noreply.github.com"];
|
|
250
|
+
}
|
|
251
|
+
execFileSync("git", [...identity, "commit", "-m", "feat: initialize project", "--no-gpg-sign"], { cwd: dir, stdio: "ignore" });
|
|
252
|
+
} catch {
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async function runTemplateCLI(template) {
|
|
256
|
+
const argv2 = process.argv.slice(2);
|
|
257
|
+
if (argv2.includes("--help") || argv2.includes("-h")) {
|
|
258
|
+
printHelp(template);
|
|
259
|
+
return 0;
|
|
260
|
+
}
|
|
261
|
+
const interactive = Boolean(process.stdout.isTTY) && !argv2.includes("--no-interactive");
|
|
262
|
+
const { values, directory: dirArg } = parseArgv(argv2, template.options);
|
|
263
|
+
prompts.intro(template.about?.name ?? "create");
|
|
264
|
+
let directory = dirArg;
|
|
265
|
+
if (!directory) {
|
|
266
|
+
if (interactive) {
|
|
267
|
+
const answer = await prompts.text({ message: "Where should we create your project?", placeholder: "my-app", defaultValue: "my-app" });
|
|
268
|
+
if (prompts.isCancel(answer)) {
|
|
269
|
+
prompts.cancel("Cancelled.");
|
|
270
|
+
return 2;
|
|
271
|
+
}
|
|
272
|
+
directory = answer || "my-app";
|
|
273
|
+
} else {
|
|
274
|
+
directory = "my-app";
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const options = {};
|
|
278
|
+
for (const d of template.options) {
|
|
279
|
+
const def = resolveDefault(d, options, directory);
|
|
280
|
+
if (d.key in values) {
|
|
281
|
+
const value = values[d.key];
|
|
282
|
+
if (d.validate && typeof value === "string") {
|
|
283
|
+
const error = d.validate(value);
|
|
284
|
+
if (error) {
|
|
285
|
+
prompts.cancel(`Invalid --${d.key}: ${error}`);
|
|
286
|
+
return 1;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
options[d.key] = value;
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (interactive) {
|
|
293
|
+
const answer = await promptForOption(d, def);
|
|
294
|
+
if (prompts.isCancel(answer)) {
|
|
295
|
+
prompts.cancel("Cancelled.");
|
|
296
|
+
return 2;
|
|
297
|
+
}
|
|
298
|
+
options[d.key] = answer === "" && def !== void 0 ? def : answer;
|
|
299
|
+
} else {
|
|
300
|
+
options[d.key] = def;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const creation = await template.produce({ options });
|
|
304
|
+
writeTree(creation.files, directory);
|
|
305
|
+
if (creation.scripts?.length) {
|
|
306
|
+
for (const step of [...creation.scripts].sort((a, b) => a.phase - b.phase)) {
|
|
307
|
+
for (const [program, ...commandArgs] of step.commands) {
|
|
308
|
+
if (!program) continue;
|
|
309
|
+
execFileSync(program, commandArgs, { cwd: directory, stdio: "inherit" });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (template.git !== false) initGit(directory);
|
|
314
|
+
if (creation.suggestions?.length) {
|
|
315
|
+
prompts.note(creation.suggestions.join("\n"), "Next steps");
|
|
316
|
+
}
|
|
317
|
+
prompts.outro("Done!");
|
|
318
|
+
return 0;
|
|
137
319
|
}
|
|
138
|
-
|
|
139
|
-
// bin/index.ts
|
|
140
|
-
import { runTemplateCLI } from "bingo";
|
|
141
320
|
|
|
142
321
|
// src/template.ts
|
|
322
|
+
import { readFileSync } from "node:fs";
|
|
143
323
|
import path2 from "node:path";
|
|
144
324
|
import { fileURLToPath } from "node:url";
|
|
145
|
-
import { createTemplate } from "bingo";
|
|
146
|
-
import { z } from "zod";
|
|
147
|
-
|
|
148
|
-
// package.json
|
|
149
|
-
var package_default = {
|
|
150
|
-
name: "@pauldvlp/vp-pkg-shadcn",
|
|
151
|
-
version: "0.4.1",
|
|
152
|
-
description: "Add a shared, fully customizable shadcn UI package (packages/ui) into an existing Vite+ monorepo, themeable via shadcn presets.",
|
|
153
|
-
author: "pauldvlp (https://github.com/pauldvlp/vp-templates)",
|
|
154
|
-
license: "MIT",
|
|
155
|
-
homepage: "https://github.com/pauldvlp/vp-templates",
|
|
156
|
-
repository: {
|
|
157
|
-
type: "git",
|
|
158
|
-
url: "git+https://github.com/pauldvlp/vp-templates.git",
|
|
159
|
-
directory: "packages/vp-pkg-shadcn"
|
|
160
|
-
},
|
|
161
|
-
bugs: "https://github.com/pauldvlp/vp-templates/issues",
|
|
162
|
-
keywords: [
|
|
163
|
-
"vite-plus-generator",
|
|
164
|
-
"vite-plus",
|
|
165
|
-
"shadcn",
|
|
166
|
-
"react",
|
|
167
|
-
"template"
|
|
168
|
-
],
|
|
169
|
-
bin: "./dist/index.js",
|
|
170
|
-
type: "module",
|
|
171
|
-
files: [
|
|
172
|
-
"dist",
|
|
173
|
-
"template"
|
|
174
|
-
],
|
|
175
|
-
scripts: {
|
|
176
|
-
build: "esbuild bin/index.ts --bundle --outfile=dist/index.js --format=esm --platform=node --target=node22 --packages=external",
|
|
177
|
-
dev: "node bin/index.ts",
|
|
178
|
-
prepack: "pnpm run build"
|
|
179
|
-
},
|
|
180
|
-
dependencies: {
|
|
181
|
-
"@clack/prompts": "^0.11.0",
|
|
182
|
-
bingo: "^0.9.3",
|
|
183
|
-
zod: "^3.25.76"
|
|
184
|
-
},
|
|
185
|
-
devDependencies: {
|
|
186
|
-
"@pauldvlp/template-kit": "workspace:*",
|
|
187
|
-
"@types/node": "^24",
|
|
188
|
-
esbuild: "^0.25.0",
|
|
189
|
-
typescript: "^5"
|
|
190
|
-
},
|
|
191
|
-
engines: {
|
|
192
|
-
node: ">=22.18.0"
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
// src/template.ts
|
|
197
325
|
var TEMPLATE_DIR = path2.join(path2.dirname(fileURLToPath(import.meta.url)), "..", "template");
|
|
198
|
-
var
|
|
326
|
+
var { name: pkgName, description: pkgDescription } = JSON.parse(
|
|
327
|
+
readFileSync(new URL("../package.json", import.meta.url), "utf8")
|
|
328
|
+
);
|
|
329
|
+
var template_default = defineTemplate({
|
|
199
330
|
about: {
|
|
200
|
-
name:
|
|
201
|
-
description:
|
|
202
|
-
},
|
|
203
|
-
options: {
|
|
204
|
-
scope: z.string().describe("npm scope for the workspace package, e.g. @acme").default("@app"),
|
|
205
|
-
// Unions of literals (not z.enum) so the value is settable on Bingo's CLI: bingo's arg parser
|
|
206
|
-
// handles ZodUnion/ZodLiteral but not ZodEnum (a bare `--base radix` would otherwise mis-parse to
|
|
207
|
-
// `base: true`). Both still render as an interactive `select`.
|
|
208
|
-
base: z.union([z.literal("radix"), z.literal("base")]).describe("shadcn component library base (radix-ui or @base-ui)").default("radix"),
|
|
209
|
-
preset: z.string().describe("shadcn preset: a style name (nova, vega, maia, lyra, mira, luma, sera, rhea) or a code from ui.shadcn.com").default(DEFAULT_PRESET),
|
|
210
|
-
iconLibrary: z.union([z.literal("lucide"), z.literal("hugeicons"), z.literal("radix"), z.literal("tabler")]).describe("Icon library").default("hugeicons"),
|
|
211
|
-
cssVariables: z.boolean().describe("Use CSS variables for theming").default(true),
|
|
212
|
-
rtl: z.boolean().describe("Enable RTL support").default(false),
|
|
213
|
-
pointer: z.boolean().describe("Use pointer cursor on interactive elements").default(false),
|
|
214
|
-
components: z.string().describe("Comma-separated shadcn components to pre-install, e.g. button,card,dialog").default("button,badge"),
|
|
215
|
-
install: z.boolean().describe("Install deps and apply the shadcn theme after scaffolding").default(true)
|
|
216
|
-
},
|
|
217
|
-
// Default the scope to the surrounding monorepo's scope (e.g. `@acme`) so it tracks the repo
|
|
218
|
-
// instead of a fixed `@app`. Falls back to `@app` when run outside a pnpm workspace.
|
|
219
|
-
prepare() {
|
|
220
|
-
const monorepoScope = detectMonorepoScope();
|
|
221
|
-
return {
|
|
222
|
-
scope: () => monorepoScope ?? "@app"
|
|
223
|
-
};
|
|
331
|
+
name: pkgName,
|
|
332
|
+
description: pkgDescription
|
|
224
333
|
},
|
|
334
|
+
// This generator drops a package into an *existing* repo, so it must never create a git repo of its own.
|
|
335
|
+
git: false,
|
|
336
|
+
options: [
|
|
337
|
+
// Default the scope to the surrounding monorepo's scope (e.g. `@acme`) so it tracks the repo
|
|
338
|
+
// instead of a fixed `@app`. Falls back to `@app` when run outside a pnpm workspace.
|
|
339
|
+
{ key: "scope", type: "string", message: "npm scope for the workspace package, e.g. @acme", default: () => detectMonorepoScope() ?? "@app", validate: validateScope },
|
|
340
|
+
{ key: "base", type: "select", message: "shadcn component library base (radix-ui or @base-ui)", choices: ["radix", "base"], default: "radix" },
|
|
341
|
+
{ key: "preset", type: "string", message: "shadcn preset: a style name (nova, vega, maia, lyra, mira, luma, sera, rhea) or a code from ui.shadcn.com", default: DEFAULT_PRESET, validate: validatePreset },
|
|
342
|
+
{ key: "iconLibrary", type: "select", message: "Icon library", choices: ["lucide", "hugeicons", "radix", "tabler"], default: "hugeicons" },
|
|
343
|
+
{ key: "cssVariables", type: "boolean", message: "Use CSS variables for theming", default: true },
|
|
344
|
+
{ key: "rtl", type: "boolean", message: "Enable RTL support", default: false },
|
|
345
|
+
{ key: "pointer", type: "boolean", message: "Use pointer cursor on interactive elements", default: false },
|
|
346
|
+
{ key: "components", type: "string", message: "Comma-separated shadcn components to pre-install, e.g. button,card,dialog", default: "button,badge", validate: validateComponents },
|
|
347
|
+
{ key: "install", type: "boolean", message: "Install deps and apply the shadcn theme after scaffolding", default: true }
|
|
348
|
+
],
|
|
225
349
|
async produce({ options }) {
|
|
226
350
|
const scope = toScope(options.scope || "app");
|
|
227
351
|
const files = readTree(TEMPLATE_DIR, (_rel, content) => content.split("@app").join(scope));
|
|
@@ -233,11 +357,11 @@ var template_default = createTemplate({
|
|
|
233
357
|
`);
|
|
234
358
|
const adds = withRequiredComponents(options.components);
|
|
235
359
|
const ui = `${scope}/ui`;
|
|
236
|
-
const
|
|
360
|
+
const initArgs = shadcnInitArgs(options);
|
|
237
361
|
const scripts = options.install ? [
|
|
238
|
-
{ commands: ["pnpm install --silent"], phase: 0 },
|
|
239
|
-
{ commands: [
|
|
240
|
-
{ commands: [
|
|
362
|
+
{ commands: [["pnpm", "install", "--silent"]], phase: 0 },
|
|
363
|
+
{ commands: [["pnpm", "--filter", ui, "exec", "shadcn", "init", ...initArgs]], phase: 1 },
|
|
364
|
+
{ commands: [["pnpm", "--filter", ui, "exec", "shadcn", "add", ...adds, "-y"]], phase: 2 }
|
|
241
365
|
] : [];
|
|
242
366
|
return {
|
|
243
367
|
files,
|
|
@@ -265,13 +389,9 @@ if (!getArg(argv, "directory") && !isHelp) {
|
|
|
265
389
|
var status = await runTemplateCLI(template_default);
|
|
266
390
|
process.exitCode = status;
|
|
267
391
|
var finalArgv = process.argv.slice(2);
|
|
268
|
-
var targetDir = getArg(finalArgv, "directory");
|
|
269
|
-
if (!isHelp && targetDir && targetDir !== "." && path3.resolve(targetDir) !== process.cwd()) {
|
|
270
|
-
fs2.rmSync(path3.join(targetDir, ".git"), { recursive: true, force: true });
|
|
271
|
-
}
|
|
272
392
|
if (!isHelp && (status === 0 || status === void 0)) {
|
|
273
393
|
const ui = `${toScope(getArg(finalArgv, "scope") || detectMonorepoScope() || "app")}/ui`;
|
|
274
|
-
|
|
394
|
+
prompts2.note(
|
|
275
395
|
[
|
|
276
396
|
`1. Workspace glob the dir you chose (e.g. packages/*) so ${ui} is linked`,
|
|
277
397
|
`2. Depend on it ${'"' + ui + '": "workspace:*"'} in your app's package.json`,
|
|
@@ -285,7 +405,7 @@ if (!isHelp && (status === 0 || status === void 0)) {
|
|
|
285
405
|
`Wire ${ui} into your app`
|
|
286
406
|
);
|
|
287
407
|
if (isInteractive) {
|
|
288
|
-
const ack = await
|
|
289
|
-
if (
|
|
408
|
+
const ack = await prompts2.confirm({ message: "Got it \u2014 continue?", initialValue: true });
|
|
409
|
+
if (prompts2.isCancel(ack)) prompts2.cancel("Okay \u2014 see the docs link above when you\u2019re ready.");
|
|
290
410
|
}
|
|
291
411
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pauldvlp/vp-pkg-shadcn",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Add a shared, fully customizable shadcn UI package (packages/ui) into an existing Vite+ monorepo, themeable via shadcn presets.",
|
|
5
5
|
"author": "pauldvlp (https://github.com/pauldvlp/vp-templates)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,9 +24,7 @@
|
|
|
24
24
|
"template"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@clack/prompts": "^
|
|
28
|
-
"bingo": "^0.9.3",
|
|
29
|
-
"zod": "^3.25.76"
|
|
27
|
+
"@clack/prompts": "^1.6.0"
|
|
30
28
|
},
|
|
31
29
|
"devDependencies": {
|
|
32
30
|
"@types/node": "^24",
|