create-vizcraft-playground 0.1.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.
Files changed (49) hide show
  1. package/index.js +171 -0
  2. package/package.json +44 -0
  3. package/template/.github/skills/vizcraft-playground/SKILL.md +573 -0
  4. package/template/README.md +59 -0
  5. package/template/eslint.config.js +23 -0
  6. package/template/index.html +13 -0
  7. package/template/package.json +37 -0
  8. package/template/public/vite.svg +1 -0
  9. package/template/scripts/generate-plugin.js +594 -0
  10. package/template/scripts/init-playground.js +119 -0
  11. package/template/src/App.scss +137 -0
  12. package/template/src/App.tsx +72 -0
  13. package/template/src/assets/react.svg +1 -0
  14. package/template/src/components/InfoModal/InfoModal.scss +211 -0
  15. package/template/src/components/InfoModal/InfoModal.tsx +85 -0
  16. package/template/src/components/Landing/Landing.scss +85 -0
  17. package/template/src/components/Landing/Landing.tsx +55 -0
  18. package/template/src/components/Shell.tsx +144 -0
  19. package/template/src/components/StepIndicator/StepIndicator.scss +151 -0
  20. package/template/src/components/StepIndicator/StepIndicator.tsx +73 -0
  21. package/template/src/components/VizInfoBeacon/VizInfoBeacon.scss +41 -0
  22. package/template/src/components/VizInfoBeacon/VizInfoBeacon.tsx +157 -0
  23. package/template/src/components/plugin-kit/CanvasStage.tsx +30 -0
  24. package/template/src/components/plugin-kit/ConceptPills.tsx +55 -0
  25. package/template/src/components/plugin-kit/PluginLayout.tsx +41 -0
  26. package/template/src/components/plugin-kit/SidePanel.tsx +69 -0
  27. package/template/src/components/plugin-kit/StageHeader.tsx +35 -0
  28. package/template/src/components/plugin-kit/StatBadge.tsx +35 -0
  29. package/template/src/components/plugin-kit/index.ts +42 -0
  30. package/template/src/components/plugin-kit/plugin-kit.scss +241 -0
  31. package/template/src/components/plugin-kit/useConceptModal.tsx +51 -0
  32. package/template/src/index.scss +81 -0
  33. package/template/src/main.tsx +14 -0
  34. package/template/src/playground.config.ts +27 -0
  35. package/template/src/plugins/hello-world/concepts.tsx +70 -0
  36. package/template/src/plugins/hello-world/helloWorldSlice.ts +29 -0
  37. package/template/src/plugins/hello-world/index.ts +48 -0
  38. package/template/src/plugins/hello-world/main.scss +32 -0
  39. package/template/src/plugins/hello-world/main.tsx +144 -0
  40. package/template/src/plugins/hello-world/useHelloWorldAnimation.ts +99 -0
  41. package/template/src/registry.ts +73 -0
  42. package/template/src/store/slices/simulationSlice.ts +47 -0
  43. package/template/src/store/store.ts +13 -0
  44. package/template/src/types/ModelPlugin.ts +55 -0
  45. package/template/src/utils/random.ts +11 -0
  46. package/template/tsconfig.app.json +35 -0
  47. package/template/tsconfig.json +7 -0
  48. package/template/tsconfig.node.json +26 -0
  49. package/template/vite.config.ts +7 -0
package/index.js ADDED
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import readline from "readline";
6
+ import { fileURLToPath } from "url";
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ const templateDir = path.join(__dirname, "template");
11
+
12
+ // ── Readline helpers ───────────────────────────────────────
13
+ const rl = readline.createInterface({
14
+ input: process.stdin,
15
+ output: process.stdout,
16
+ });
17
+
18
+ const ask = (question, fallback) =>
19
+ new Promise((resolve) => {
20
+ const suffix = fallback ? ` (${fallback}): ` : ": ";
21
+ rl.question(question + suffix, (answer) => {
22
+ resolve(answer.trim() || fallback || "");
23
+ });
24
+ });
25
+
26
+ // ── Helpers ────────────────────────────────────────────────
27
+ const toSlug = (str) =>
28
+ str
29
+ .toLowerCase()
30
+ .replace(/[^a-z0-9]+/g, "-")
31
+ .replace(/(^-|-$)/g, "");
32
+
33
+ function copyDirSync(src, dest) {
34
+ fs.mkdirSync(dest, { recursive: true });
35
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
36
+ const srcPath = path.join(src, entry.name);
37
+ const destPath = path.join(dest, entry.name);
38
+ if (entry.isDirectory()) {
39
+ copyDirSync(srcPath, destPath);
40
+ } else {
41
+ fs.copyFileSync(srcPath, destPath);
42
+ }
43
+ }
44
+ }
45
+
46
+ // ── Main ───────────────────────────────────────────────────
47
+ async function main() {
48
+ const projectArg = process.argv[2];
49
+
50
+ console.log("");
51
+ console.log("╔═══════════════════════════════════════════════╗");
52
+ console.log("║ create-vizcraft-playground ║");
53
+ console.log("║ Scaffold a new interactive playground ║");
54
+ console.log("╚═══════════════════════════════════════════════╝");
55
+ console.log("");
56
+
57
+ // ── Project directory ──────────────────────────────────
58
+ const projectName =
59
+ projectArg || (await ask(" Project directory name", "my-playground"));
60
+ const targetDir = path.resolve(process.cwd(), projectName);
61
+
62
+ if (fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0) {
63
+ console.error(`\n ✖ Directory "${projectName}" already exists and is not empty.\n`);
64
+ rl.close();
65
+ process.exit(1);
66
+ }
67
+
68
+ // ── Prompts ────────────────────────────────────────────
69
+ const title = await ask(" Playground title", projectName.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()));
70
+ const subtitle = await ask(
71
+ " Subtitle (one-liner for the landing page)",
72
+ "Explore interactive visualizations.",
73
+ );
74
+ const accent = await ask(" Primary accent colour (hex)", "#3b82f6");
75
+ const slug = toSlug(title);
76
+
77
+ console.log("");
78
+ console.log(" ─── Summary ───────────────────────────────");
79
+ console.log(" Directory : " + projectName);
80
+ console.log(" Title : " + title);
81
+ console.log(" Subtitle : " + subtitle);
82
+ console.log(" Accent : " + accent);
83
+ console.log(" ────────────────────────────────────────────");
84
+ console.log("");
85
+
86
+ // ── 1. Copy template ──────────────────────────────────
87
+ console.log(" Scaffolding project…");
88
+ copyDirSync(templateDir, targetDir);
89
+ console.log(" ✔ Copied template");
90
+
91
+ // ── 2. Write playground.config.ts ──────────────────────
92
+ const configContent = `/* ═══════════════════════════════════════════════════════
93
+ * Playground Configuration
94
+ *
95
+ * Single source of truth for branding & metadata.
96
+ * Run \`npm run init\` to regenerate this file interactively,
97
+ * or edit the values below directly.
98
+ * ═══════════════════════════════════════════════════════ */
99
+
100
+ export interface PlaygroundConfig {
101
+ /** Project slug (kebab-case), used in package.json name */
102
+ name: string;
103
+ /** Display title shown on the landing page */
104
+ title: string;
105
+ /** One-liner shown below the title on the landing page */
106
+ subtitle: string;
107
+ /** Primary accent colour (hex) */
108
+ accent: string;
109
+ }
110
+
111
+ const playgroundConfig: PlaygroundConfig = {
112
+ name: "${slug}",
113
+ title: "${title.replace(/"/g, '\\"')}",
114
+ subtitle:
115
+ "${subtitle.replace(/"/g, '\\"')}",
116
+ accent: "${accent}",
117
+ };
118
+
119
+ export default playgroundConfig;
120
+ `;
121
+ fs.writeFileSync(path.join(targetDir, "src/playground.config.ts"), configContent);
122
+ console.log(" ✔ Configured playground.config.ts");
123
+
124
+ // ── 3. Update package.json ─────────────────────────────
125
+ const pkgPath = path.join(targetDir, "package.json");
126
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
127
+ pkg.name = slug;
128
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
129
+ console.log(" ✔ Set package.json name → " + slug);
130
+
131
+ // ── 4. Update index.html <title> ──────────────────────
132
+ const htmlPath = path.join(targetDir, "index.html");
133
+ let html = fs.readFileSync(htmlPath, "utf-8");
134
+ html = html.replace(/<title>.*<\/title>/, "<title>" + title + "</title>");
135
+ fs.writeFileSync(htmlPath, html);
136
+ console.log(" ✔ Set index.html title → " + title);
137
+
138
+ // ── 5. Update README ──────────────────────────────────
139
+ const readmePath = path.join(targetDir, "README.md");
140
+ let readme = fs.readFileSync(readmePath, "utf-8");
141
+ readme = readme.replace(/^# .*$/m, "# " + title);
142
+ readme = readme.replace(
143
+ /^Explore interactive visualizations\.$/m,
144
+ subtitle,
145
+ );
146
+ fs.writeFileSync(readmePath, readme);
147
+ console.log(" ✔ Updated README.md");
148
+
149
+ // ── Done ──────────────────────────────────────────────
150
+ console.log("");
151
+ console.log(" ✔ Project ready at ./" + projectName);
152
+ console.log("");
153
+ console.log(" Next steps:");
154
+ console.log("");
155
+ console.log(" cd " + projectName);
156
+ console.log(" npm install");
157
+ console.log(" npm run dev");
158
+ console.log("");
159
+ console.log(" Then scaffold your first plugin:");
160
+ console.log("");
161
+ console.log(' npm run generate my-concept --category "My Category"');
162
+ console.log("");
163
+
164
+ rl.close();
165
+ }
166
+
167
+ main().catch((err) => {
168
+ console.error(err);
169
+ rl.close();
170
+ process.exit(1);
171
+ });
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "create-vizcraft-playground",
3
+ "version": "0.1.0",
4
+ "description": "Scaffold a new VizCraft interactive visualization playground",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-vizcraft-playground": "./index.js"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "template"
12
+ ],
13
+ "scripts": {
14
+ "changeset": "changeset"
15
+ },
16
+ "keywords": [
17
+ "vizcraft",
18
+ "playground",
19
+ "visualization",
20
+ "scaffold",
21
+ "create"
22
+ ],
23
+ "author": {
24
+ "name": "Chipili Kafwilo",
25
+ "email": "ckafwilo@gmail.com",
26
+ "url": "https://chipilidev.com"
27
+ },
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/ChipiKaf/create-vizcraft-playground.git"
32
+ },
33
+ "devDependencies": {
34
+ "@changesets/changelog-github": "^0.5.2",
35
+ "@changesets/cli": "^2.29.6"
36
+ },
37
+ "engines": {
38
+ "node": ">=20"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public",
42
+ "provenance": true
43
+ }
44
+ }