rizzo-css 0.0.18 → 0.0.19

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 (33) hide show
  1. package/README.md +4 -4
  2. package/bin/rizzo-css.js +252 -89
  3. package/dist/rizzo.min.css +3 -3
  4. package/package.json +1 -1
  5. package/scaffold/astro-minimal/README.md +1 -1
  6. package/scaffold/svelte-minimal/README.md +1 -1
  7. package/scaffold/vanilla/README.md +2 -2
  8. package/scaffold/vanilla/components/accordion.html +10 -0
  9. package/scaffold/vanilla/components/alert.html +10 -0
  10. package/scaffold/vanilla/components/avatar.html +10 -0
  11. package/scaffold/vanilla/components/badge.html +10 -0
  12. package/scaffold/vanilla/components/breadcrumb.html +10 -0
  13. package/scaffold/vanilla/components/button.html +10 -0
  14. package/scaffold/vanilla/components/cards.html +10 -0
  15. package/scaffold/vanilla/components/copy-to-clipboard.html +10 -0
  16. package/scaffold/vanilla/components/divider.html +10 -0
  17. package/scaffold/vanilla/components/dropdown.html +10 -0
  18. package/scaffold/vanilla/components/forms.html +10 -0
  19. package/scaffold/vanilla/components/icons.html +10 -0
  20. package/scaffold/vanilla/components/index.html +10 -0
  21. package/scaffold/vanilla/components/modal.html +10 -0
  22. package/scaffold/vanilla/components/navbar.html +10 -0
  23. package/scaffold/vanilla/components/pagination.html +10 -0
  24. package/scaffold/vanilla/components/progress-bar.html +10 -0
  25. package/scaffold/vanilla/components/search.html +10 -0
  26. package/scaffold/vanilla/components/settings.html +10 -0
  27. package/scaffold/vanilla/components/spinner.html +10 -0
  28. package/scaffold/vanilla/components/table.html +10 -0
  29. package/scaffold/vanilla/components/tabs.html +10 -0
  30. package/scaffold/vanilla/components/theme-switcher.html +10 -0
  31. package/scaffold/vanilla/components/toast.html +10 -0
  32. package/scaffold/vanilla/components/tooltip.html +10 -0
  33. package/scaffold/vanilla/index.html +10 -0
package/README.md CHANGED
@@ -12,7 +12,7 @@ pnpm add rizzo-css
12
12
  yarn add rizzo-css
13
13
  ```
14
14
 
15
- **Quick start (no install):** `npx rizzo-css init` — choose **framework** (Vanilla, Astro, or Svelte), then **add to existing** or **create new**. **Existing** (or `npx rizzo-css add`) → drop in CSS + hand-pick components; you must add the `<link>` yourself (CLI prints the exact tag). **New** → choose **template** (Vanilla: full or minimal; Astro/Svelte: minimal) or **no template** (minimal base + hand-pick components), then package manager. Non-interactive: `npx rizzo-css init --yes --framework vanilla|astro|svelte`. Optional **rizzo-css.json** and `add --install-package`. All get the **same CSS and component styles**. To use the **official Svelte or Astro create command** plus Rizzo, create the app first, then run `npx rizzo-css add`:
15
+ **Quick start (no install):** `npx rizzo-css init` — choose **framework** (Vanilla, Astro, or Svelte), then **add to existing** or **create new**. **Existing** (or `npx rizzo-css add`) → drop in CSS + hand-pick components; you must add the `<link>` yourself (CLI prints the exact tag). **New** → choose **Full** (everything) | **Minimal** (recommended) | **Manual** (pick components), then package manager. Non-interactive: `npx rizzo-css init --yes --framework vanilla|astro|svelte`. Optional **rizzo-css.json** and `add --install-package`. All get the **same CSS and component styles**. To use the **official Svelte or Astro create command** plus Rizzo, create the app first, then run `npx rizzo-css add`:
16
16
 
17
17
  ```bash
18
18
  npm create svelte@latest my-app && cd my-app && npx rizzo-css add
@@ -41,7 +41,7 @@ You install **the same package** for every framework: `npm install rizzo-css`. N
41
41
 
42
42
  With `npx rizzo-css add --path <dir>`, the CLI still suggests the correct href for your framework (e.g. Astro/Svelte get a leading `/` path).
43
43
 
44
- Scaffolds in the package: `scaffold/vanilla/` (full or minimal template), `scaffold/astro-minimal/`, `scaffold/svelte-minimal/`, plus `scaffold/astro/` and `scaffold/svelte/` (component templates for hand-pick). Use `npx rizzo-css init` and choose **Create new project** to get a template-based scaffold or minimal base + hand-picked components; the stylesheet link is in the layout. **Add to existing** (or `add` command) drops in CSS + hand-pick components; **you must add the stylesheet `<link>` yourself** — the CLI prints the exact tag. Every scaffold includes LICENSE and README; Astro/Svelte minimal include package.json and .env.example.
44
+ Scaffolds in the package: `scaffold/vanilla/` (Full or Manual), `scaffold/astro-minimal/`, `scaffold/svelte-minimal/`, plus `scaffold/astro/` and `scaffold/svelte/` (component templates for hand-pick). Use `npx rizzo-css init` and choose **Create new project** to get a **Full** or **Manual** scaffold; the stylesheet link is in the layout. **Add to existing** (or `add` command) drops in CSS + hand-pick components; **you must add the stylesheet `<link>` yourself** — the CLI prints the exact tag. Every scaffold includes LICENSE and README; Astro/Svelte minimal include package.json and .env.example.
45
45
 
46
46
  ## Use
47
47
 
@@ -56,7 +56,7 @@ import 'rizzo-css';
56
56
  **Without a bundler (plain HTML):** Use a CDN. Both unpkg and jsDelivr resolve the package root to the built CSS (via the `unpkg` / `jsdelivr` fields in this package). For reliability or to pin a version, use the explicit path:
57
57
 
58
58
  ```html
59
- <!-- unpkg (pin version: replace @latest with @0.0.18 or any version) -->
59
+ <!-- unpkg (pin version: replace @latest with @0.0.19 or any version) -->
60
60
  <link rel="stylesheet" href="https://unpkg.com/rizzo-css@latest/dist/rizzo.min.css" />
61
61
 
62
62
  <!-- or jsDelivr -->
@@ -65,7 +65,7 @@ import 'rizzo-css';
65
65
 
66
66
  Short URLs also work: `https://unpkg.com/rizzo-css@latest` and `https://cdn.jsdelivr.net/npm/rizzo-css@latest` (CDNs serve the default file from package.json). To verify after publish: open the URL in a browser or run `curl -I https://unpkg.com/rizzo-css@latest/dist/rizzo.min.css` and expect `200 OK`.
67
67
 
68
- Use the same class names and HTML structure as in the [component docs](https://rizzo-css.vercel.app/docs/components). **Vanilla JS**, Astro, and Svelte all use the same CSS and BEM markup; Astro/Svelte add framework component files when you hand-pick. Each scaffold has a README; every install includes LICENSE. The **Vanilla** full template includes a Settings panel and toast; **Astro** and **Svelte** minimal layouts include theme persistence and toast (`showToast`, `removeToast`, `removeAllToasts`).
68
+ Use the same class names and HTML structure as in the [component docs](https://rizzo-css.vercel.app/docs/components). **Vanilla JS**, Astro, and Svelte all use the same CSS and BEM markup; Astro/Svelte add framework component files when you hand-pick. Each scaffold has a README; every install includes LICENSE. The **Vanilla** Full includes a Settings panel and toast; **Astro** and **Svelte** Full scaffolds include theme persistence and toast (`showToast`, `removeToast`, `removeAllToasts`).
69
69
 
70
70
  ## Themes
71
71
 
package/bin/rizzo-css.js CHANGED
@@ -10,28 +10,48 @@ const RIZZO_CONFIG_FILE = 'rizzo-css.json';
10
10
  const COMMANDS = ['init', 'add', 'theme', 'help'];
11
11
  const FRAMEWORKS = ['vanilla', 'astro', 'svelte'];
12
12
 
13
- /** Template options for "create new" when user chooses "Use a template". When they choose "No template" they get minimal base + hand-pick components. */
13
+ /** Full = everything we ship. Minimal = recommended starting set. Manual = you choose. */
14
14
  const TEMPLATES = {
15
15
  vanilla: [
16
- { value: 'full', label: 'Full — index.html + theme switcher, js/main.js, icons, README' },
17
- { value: 'minimal', label: 'Minimal — index.html + CSS link only' },
16
+ { value: 'full', label: 'Full — index.html + theme switcher, js/main.js, icons, component showcase, README' },
17
+ { value: 'minimal', label: 'Minimal — index.html + CSS + js/main.js (recommended starter; no showcase)' },
18
+ { value: 'manual', label: 'Manual — index.html + CSS; pick components to add their pages + js/main.js' },
18
19
  ],
19
20
  astro: [
20
- { value: 'minimal', label: 'Minimal — Astro with config, one page, README, LICENSE, .env.example' },
21
+ { value: 'full', label: 'Full — Astro app + all 25 components (config, one page, README, LICENSE, .env.example)' },
22
+ { value: 'minimal', label: 'Minimal — Astro app + recommended components (Button, Badge, Card, Modal, Tabs, ThemeSwitcher, FormGroup, Alert, Toast, Dropdown)' },
23
+ { value: 'manual', label: 'Manual — minimal base + pick the components you want' },
21
24
  ],
22
25
  svelte: [
23
- { value: 'minimal', label: 'Minimal — SvelteKit with config, one page, README, LICENSE, .env.example' },
26
+ { value: 'full', label: 'Full — SvelteKit app + all 25 components (config, one page, README, LICENSE, .env.example)' },
27
+ { value: 'minimal', label: 'Minimal — SvelteKit app + recommended components (Button, Badge, Card, Modal, Tabs, ThemeSwitcher, FormGroup, Alert, Toast, Dropdown)' },
28
+ { value: 'manual', label: 'Manual — minimal base + pick the components you want' },
24
29
  ],
25
30
  };
26
31
 
27
32
  const VANILLA_MINIMAL_README = `# Vanilla + Rizzo CSS (minimal)
28
33
 
29
- Minimal HTML + Rizzo CSS. Scaffolded with \`npx rizzo-css init --framework vanilla --template minimal\`.
34
+ Minimal starter: HTML + CSS + js/main.js + recommended component pages. Scaffolded with \`npx rizzo-css init --framework vanilla --template minimal\`.
35
+
36
+ - Open \`index.html\` in a browser or serve the folder. Edit \`index.html\` and add your content. CSS: \`css/rizzo.min.css\`. Script: \`js/main.js\` (already linked).
37
+ - \`components/\` contains HTML pages for the recommended set (Button, Badge, Card, Modal, Tabs, ThemeSwitcher, FormGroup, Alert, Toast, Dropdown). Open \`components/index.html\` to browse them.
38
+ - Set a theme: \`<html data-theme="github-dark-classic">\` (see \`npx rizzo-css theme\` for all themes).
39
+ - For the full component showcase and icons, use template **Full** or copy from a Full scaffold.
40
+
41
+ Docs: [rizzo-css.vercel.app](https://rizzo-css.vercel.app)
42
+ `;
43
+
44
+ const VANILLA_MANUAL_README = `# Vanilla + Rizzo CSS (manual)
45
+
46
+ Manual setup: HTML + CSS, plus any component pages you chose. Scaffolded with \`npx rizzo-css init --framework vanilla --template manual\`.
30
47
 
31
48
  - Open \`index.html\` in a browser or serve the folder with any static server.
32
49
  - Edit \`index.html\` and add your content. CSS: \`css/rizzo.min.css\`.
50
+ - If you picked components, \`components/\` has their HTML pages and \`js/main.js\` is included (open \`components/index.html\` to browse).
33
51
  - Set a theme: \`<html data-theme="github-dark-classic">\` (see \`npx rizzo-css theme\` for all themes).
34
52
 
53
+ **If you chose no components:** To add component JavaScript (modal, dropdown, tabs, toast, theme switcher, etc.), use the [Vanilla component docs](https://rizzo-css.vercel.app/docs/vanilla/components) or run \`npx rizzo-css init\` with Vanilla → **Full** in a temp folder and copy \`js/main.js\` and \`icons/\` into this project.
54
+
35
55
  Docs: [rizzo-css.vercel.app](https://rizzo-css.vercel.app)
36
56
  `;
37
57
 
@@ -79,11 +99,20 @@ const ASTRO_COMPONENTS = [
79
99
  'Modal', 'Toast', 'Table', 'ThemeSwitcher',
80
100
  ];
81
101
 
82
- // Recommended subset for "Recommended set" option (keeps CLI simple; power users can pick)
102
+ // Recommended subset for Full/Minimal (same for Astro, Svelte, Vanilla)
83
103
  const RECOMMENDED_COMPONENTS = [
84
104
  'Button', 'Badge', 'Card', 'Modal', 'Tabs', 'ThemeSwitcher', 'FormGroup', 'Alert', 'Toast', 'Dropdown',
85
105
  ];
86
106
 
107
+ // Vanilla scaffold: component name (same as ASTRO_COMPONENTS) -> components/*.html slug
108
+ const VANILLA_COMPONENT_SLUGS = {
109
+ Button: 'button', Badge: 'badge', Card: 'cards', Divider: 'divider', Spinner: 'spinner', ProgressBar: 'progress-bar',
110
+ Avatar: 'avatar', Alert: 'alert', Breadcrumb: 'breadcrumb', FormGroup: 'forms', Input: 'forms', Checkbox: 'forms',
111
+ Textarea: 'forms', Select: 'forms', Radio: 'forms', CopyToClipboard: 'copy-to-clipboard', Tooltip: 'tooltip',
112
+ Pagination: 'pagination', Tabs: 'tabs', Accordion: 'accordion', Dropdown: 'dropdown', Modal: 'modal',
113
+ Toast: 'toast', Table: 'table', ThemeSwitcher: 'theme-switcher',
114
+ };
115
+
87
116
  // ANSI colors for CLI (framework logo colors)
88
117
  const C = {
89
118
  reset: '\u001b[0m',
@@ -155,6 +184,19 @@ function getFlagValue(argv, flag) {
155
184
  return i !== -1 && argv[i + 1] != null ? argv[i + 1] : null;
156
185
  }
157
186
 
187
+ /** Get positional args for a command (excludes --flag and --flag value). Used for e.g. add Button ThemeSwitcher. */
188
+ function getPositionalArgs(argv) {
189
+ const positionals = [];
190
+ for (let i = 1; i < argv.length; i++) {
191
+ if (argv[i].startsWith('--')) {
192
+ if (!argv[i].includes('=')) i++;
193
+ continue;
194
+ }
195
+ positionals.push(argv[i]);
196
+ }
197
+ return positionals;
198
+ }
199
+
158
200
  /** Package manager detection (manual: lockfiles + packageManager field). Returns { agent, command } or null if none found. */
159
201
  function detectPackageManager(cwd) {
160
202
  if (!cwd || !existsSync(cwd)) return null;
@@ -217,10 +259,10 @@ async function promptPackageManager(projectDir) {
217
259
  return selectMenu(options, '? Package manager (for install and run commands)');
218
260
  }
219
261
 
220
- /** Prompt user to select template for the chosen framework. Returns template value (full or minimal for Vanilla; minimal for Astro/Svelte). */
262
+ /** Prompt user to select Full or Manual for the chosen framework. Returns 'full' or 'manual'. */
221
263
  async function promptTemplate(framework) {
222
264
  const options = TEMPLATES[framework] || TEMPLATES.vanilla;
223
- return selectMenu(options, '? Template');
265
+ return selectMenu(options, '? Full or Manual?');
224
266
  }
225
267
 
226
268
  function question(prompt) {
@@ -504,15 +546,15 @@ Usage (use your package manager):
504
546
  bunx rizzo-css <command> [options]
505
547
 
506
548
  Commands:
507
- init New project = template (or no template hand-pick components). Existing = drop in CSS + hand-pick. First: framework, then existing vs new.
549
+ init New project = Full (everything) | Minimal (recommended set) | Manual (pick what you want). Existing = drop in CSS + hand-pick. First: framework, then existing vs new.
508
550
  add Same as init → existing: drop in CSS + hand-pick components (framework detected or from rizzo-css.json)
509
551
  theme List all available themes (use in init or set data-theme on <html>)
510
552
  help Show this help
511
553
 
512
554
  Options (init):
513
- --yes Non-interactive: scaffold new in cwd with defaults (framework: astro, template: minimal)
555
+ --yes Non-interactive: scaffold new in cwd with defaults (framework: astro, template: full)
514
556
  --framework <fw> vanilla | astro | svelte (with --yes; otherwise first prompt)
515
- --template <t> full | minimal (Vanilla); minimal only (Astro/Svelte); with --yes defaults to full or minimal
557
+ --template <t> full | minimal | manual (all frameworks); with --yes defaults to full
516
558
  --install After scaffolding, run package manager install (new project)
517
559
  --no-install Do not run install
518
560
  --write-config Write rizzo-css.json (targetDir, framework, packageManager) in the project
@@ -542,10 +584,11 @@ Examples:
542
584
  npx rizzo-css init
543
585
  npx rizzo-css init --yes --framework astro --install --write-config
544
586
  npx rizzo-css init --yes --framework vanilla
545
- npx rizzo-css init --yes --framework svelte --template minimal
587
+ npx rizzo-css init --yes --framework svelte --template full
546
588
  npx rizzo-css add
589
+ npx rizzo-css add Button
590
+ npx rizzo-css add Button ThemeSwitcher --path public/css --framework svelte
547
591
  npx rizzo-css add --install-package
548
- npx rizzo-css add --path public/css --framework svelte
549
592
  npx rizzo-css theme
550
593
 
551
594
  Docs: https://rizzo-css.vercel.app
@@ -652,10 +695,15 @@ async function cmdAdd(argv) {
652
695
  const explicitFramework = explicitFrameworkRaw && FRAMEWORKS.includes(explicitFrameworkRaw.toLowerCase()) ? explicitFrameworkRaw.toLowerCase() : null;
653
696
  const installPackage = hasFlag(argv, '--install-package');
654
697
  const noInstall = hasFlag(argv, '--no-install');
698
+ const positionals = getPositionalArgs(argv);
655
699
 
656
700
  const cwd = process.cwd();
657
701
  const config = readRizzoConfig(cwd);
658
- const options = { config, targetDir: customPath || (config && config.targetDir) || undefined };
702
+ const options = {
703
+ config,
704
+ targetDir: customPath || (config && config.targetDir) || undefined,
705
+ preselectedComponents: positionals.length > 0 ? positionals : undefined,
706
+ };
659
707
  await runAddToExisting(explicitFramework, options);
660
708
  if (installPackage && !noInstall) {
661
709
  const pm = (config && config.packageManager)
@@ -686,6 +734,61 @@ function getScaffoldVanillaIconsDir() {
686
734
  return join(getPackageRoot(), 'scaffold', 'vanilla', 'icons');
687
735
  }
688
736
 
737
+ function getScaffoldVanillaComponentsDir() {
738
+ return join(getPackageRoot(), 'scaffold', 'vanilla', 'components');
739
+ }
740
+
741
+ /** Copy selected Vanilla component HTML files into projectDir/components/, with replacements. Writes a simple components/index.html. */
742
+ function copyVanillaComponents(projectDir, selectedNames, replacements) {
743
+ const srcDir = getScaffoldVanillaComponentsDir();
744
+ if (!existsSync(srcDir)) return;
745
+ const linkHref = replacements['{{LINK_HREF}}'] || 'css/rizzo.min.css';
746
+ const slugsToCopy = [];
747
+ const seen = new Set();
748
+ for (const name of selectedNames) {
749
+ const slug = VANILLA_COMPONENT_SLUGS[name];
750
+ if (slug && !seen.has(slug)) {
751
+ seen.add(slug);
752
+ slugsToCopy.push(slug);
753
+ }
754
+ }
755
+ if (slugsToCopy.length === 0) return;
756
+ const destDir = join(projectDir, 'components');
757
+ mkdirSync(destDir, { recursive: true });
758
+ for (const slug of slugsToCopy) {
759
+ const src = join(srcDir, slug + '.html');
760
+ if (existsSync(src)) {
761
+ let content = readFileSync(src, 'utf8');
762
+ for (const [key, value] of Object.entries(replacements)) {
763
+ content = content.split(key).join(value);
764
+ }
765
+ writeFileSync(join(destDir, slug + '.html'), content, 'utf8');
766
+ }
767
+ }
768
+ const indexLinks = slugsToCopy.map((s) => ' <li><a href="' + s + '.html">' + s + '</a></li>').join('\n');
769
+ const indexHtml = `<!DOCTYPE html>
770
+ <html lang="en" data-theme="${replacements['{{DATA_THEME}}'] || 'github-dark-classic'}">
771
+ <head>
772
+ <meta charset="UTF-8" />
773
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
774
+ <title>Components</title>
775
+ <link rel="stylesheet" href="../${linkHref}" />
776
+ </head>
777
+ <body>
778
+ <main style="padding: var(--spacing-6); max-width: 60ch;">
779
+ <h1>Components</h1>
780
+ <ul>
781
+ ${indexLinks}
782
+ </ul>
783
+ <p><a href="../index.html">Back to index</a></p>
784
+ </main>
785
+ <script src="../js/main.js"></script>
786
+ </body>
787
+ </html>
788
+ `;
789
+ writeFileSync(join(destDir, 'index.html'), indexHtml, 'utf8');
790
+ }
791
+
689
792
  /** Copy Rizzo icons into the project for the given framework. */
690
793
  function copyRizzoIcons(projectDir, framework) {
691
794
  if (framework === 'astro') {
@@ -855,14 +958,31 @@ async function runAddToExisting(frameworkOverride, options) {
855
958
  framework = await selectMenu(frameworkOptions, frameworkPrompt);
856
959
  }
857
960
 
858
- const componentList = framework === 'svelte' ? SVELTE_COMPONENTS : framework === 'astro' ? ASTRO_COMPONENTS : [];
859
- const selectedComponents = componentList.length > 0
860
- ? await promptComponentChoice(componentList, framework)
861
- : [];
961
+ const componentList = framework === 'svelte' ? SVELTE_COMPONENTS : framework === 'astro' ? ASTRO_COMPONENTS : framework === 'vanilla' ? Object.keys(VANILLA_COMPONENT_SLUGS) : [];
962
+ const preselected = options.preselectedComponents && options.preselectedComponents.length > 0 ? options.preselectedComponents : null;
963
+ let selectedComponents;
964
+ if (preselected && componentList.length > 0) {
965
+ const valid = preselected.filter((c) => componentList.includes(c));
966
+ const invalid = preselected.filter((c) => !componentList.includes(c));
967
+ if (invalid.length > 0) {
968
+ console.log('Unknown or unsupported component name(s) (skipped): ' + invalid.join(', '));
969
+ }
970
+ selectedComponents = valid;
971
+ if (selectedComponents.length > 0) {
972
+ const n = selectedComponents.length;
973
+ console.log('Adding ' + n + ' component' + (n === 1 ? '' : 's') + ': ' + selectedComponents.join(', '));
974
+ }
975
+ } else if (preselected && componentList.length === 0) {
976
+ selectedComponents = [];
977
+ } else {
978
+ selectedComponents = componentList.length > 0
979
+ ? await promptComponentChoice(componentList, framework)
980
+ : [];
981
+ }
862
982
 
863
983
  let theme, defaultDark, defaultLight;
864
984
  const wantsThemeSwitcher = selectedComponents.includes('ThemeSwitcher');
865
- if (wantsThemeSwitcher) {
985
+ if (wantsThemeSwitcher && !preselected) {
866
986
  const setDefaults = await selectMenu(
867
987
  [
868
988
  { value: true, label: 'Yes — choose default dark, default light, and initial theme' },
@@ -904,6 +1024,10 @@ async function runAddToExisting(frameworkOverride, options) {
904
1024
  copySvelteComponents(cwd, selectedComponents);
905
1025
  } else if (framework === 'astro' && selectedComponents.length > 0) {
906
1026
  copyAstroComponents(cwd, selectedComponents);
1027
+ } else if (framework === 'vanilla' && selectedComponents.length > 0) {
1028
+ const linkHrefForVanilla = (options && options.targetDir) ? getLinkHrefForTargetDir(framework, options.targetDir) : paths.linkHref;
1029
+ const vanillaRepl = { '{{LINK_HREF}}': linkHrefForVanilla, '{{DATA_THEME}}': theme };
1030
+ copyVanillaComponents(cwd, selectedComponents, vanillaRepl);
907
1031
  }
908
1032
 
909
1033
  const linkHref = (options && options.targetDir) ? getLinkHrefForTargetDir(framework, options.targetDir) : paths.linkHref;
@@ -935,6 +1059,9 @@ async function runAddToExisting(frameworkOverride, options) {
935
1059
  console.log(' <link rel="stylesheet" href="' + linkHref + '" />');
936
1060
  console.log('\nSet a theme on <html>: data-theme="' + theme + '" (see: ' + cliExample + ')');
937
1061
  console.log(' For theme "system": default dark ' + defaultDark + ', default light ' + defaultLight);
1062
+ if (selectedComponents.length > 0) {
1063
+ console.log(' Component HTML files are in components/.');
1064
+ }
938
1065
  }
939
1066
  console.log('\nTo install the package (CLI + components): ' + pm.add('rizzo-css'));
940
1067
  console.log('\nDocs: https://rizzo-css.vercel.app\n');
@@ -962,8 +1089,13 @@ async function cmdInit(argv) {
962
1089
  framework = (frameworkArg && FRAMEWORKS.includes(frameworkArg.toLowerCase())) ? frameworkArg.toLowerCase() : (config && config.framework) || 'astro';
963
1090
  initMode = 'new';
964
1091
  const templateArg = getFlagValue(argv, '--template');
965
- const rawTemplate = (templateArg && (templateArg === 'full' || templateArg === 'minimal')) ? templateArg : (framework === 'vanilla' ? 'full' : 'minimal');
966
- selectedTemplate = rawTemplate;
1092
+ selectedTemplate = (templateArg && (templateArg === 'full' || templateArg === 'minimal' || templateArg === 'manual')) ? templateArg : 'full';
1093
+ if (selectedTemplate === 'full' && (framework === 'astro' || framework === 'svelte')) {
1094
+ selectedComponents = framework === 'svelte' ? [...SVELTE_COMPONENTS] : [...ASTRO_COMPONENTS];
1095
+ } else if (selectedTemplate === 'minimal' && (framework === 'astro' || framework === 'svelte')) {
1096
+ const componentList = framework === 'svelte' ? SVELTE_COMPONENTS : ASTRO_COMPONENTS;
1097
+ selectedComponents = RECOMMENDED_COMPONENTS.filter((c) => componentList.includes(c));
1098
+ }
967
1099
  const projectDir = cwd;
968
1100
  const resolved = resolvePackageManager(projectDir, cwd);
969
1101
  selectedPm = (config && config.packageManager) || resolved.agent || 'npm';
@@ -1002,44 +1134,28 @@ async function cmdInit(argv) {
1002
1134
  );
1003
1135
  name = projectChoice === 'name' ? await question('Project name (folder name): ') : '';
1004
1136
 
1005
- const templateOrHandpick = await selectMenu(
1006
- [
1007
- { value: 'template', label: 'Use a template (Full or Minimal — ready-made scaffold)' },
1008
- { value: 'handpick', label: 'No template — minimal base + hand-pick components' },
1009
- ],
1010
- '? Template or hand-pick components?'
1011
- );
1137
+ selectedTemplate = await selectMenu(TEMPLATES[framework] || TEMPLATES.vanilla, '? Full, Minimal, or Manual?');
1012
1138
 
1013
- if (templateOrHandpick === 'template') {
1014
- selectedTemplate = await promptTemplate(framework);
1015
- const templateHasThemeSwitcher = framework === 'vanilla' && selectedTemplate === 'full';
1016
- if (templateHasThemeSwitcher) {
1017
- const themeOut = await promptThemes();
1018
- theme = themeOut.theme;
1019
- defaultDark = themeOut.defaultDark;
1020
- defaultLight = themeOut.defaultLight;
1021
- } else {
1022
- theme = 'system';
1023
- defaultDark = DARK_THEMES[0];
1024
- defaultLight = LIGHT_THEMES[0];
1025
- }
1139
+ if (selectedTemplate === 'full' && (framework === 'astro' || framework === 'svelte')) {
1140
+ selectedComponents = framework === 'svelte' ? [...SVELTE_COMPONENTS] : [...ASTRO_COMPONENTS];
1141
+ } else if (selectedTemplate === 'minimal' && (framework === 'astro' || framework === 'svelte')) {
1142
+ const componentList = framework === 'svelte' ? SVELTE_COMPONENTS : ASTRO_COMPONENTS;
1143
+ selectedComponents = RECOMMENDED_COMPONENTS.filter((c) => componentList.includes(c));
1144
+ } else if (selectedTemplate === 'manual') {
1145
+ const componentList = framework === 'svelte' ? SVELTE_COMPONENTS : ASTRO_COMPONENTS;
1146
+ selectedComponents = await promptComponentChoice(componentList, framework);
1147
+ }
1148
+
1149
+ const wantsThemeSwitcher = (framework === 'vanilla' && (selectedTemplate === 'full' || selectedTemplate === 'minimal')) || selectedComponents.includes('ThemeSwitcher');
1150
+ if (wantsThemeSwitcher) {
1151
+ const themeOut = await promptThemes();
1152
+ theme = themeOut.theme;
1153
+ defaultDark = themeOut.defaultDark;
1154
+ defaultLight = themeOut.defaultLight;
1026
1155
  } else {
1027
- selectedTemplate = 'handpick';
1028
- const componentList = framework === 'svelte' ? SVELTE_COMPONENTS : framework === 'astro' ? ASTRO_COMPONENTS : [];
1029
- selectedComponents = componentList.length > 0
1030
- ? await promptComponentChoice(componentList, framework)
1031
- : [];
1032
- const wantsThemeSwitcher = selectedComponents.includes('ThemeSwitcher');
1033
- if (wantsThemeSwitcher) {
1034
- const themeOut = await promptThemes();
1035
- theme = themeOut.theme;
1036
- defaultDark = themeOut.defaultDark;
1037
- defaultLight = themeOut.defaultLight;
1038
- } else {
1039
- theme = 'system';
1040
- defaultDark = DARK_THEMES[0];
1041
- defaultLight = LIGHT_THEMES[0];
1042
- }
1156
+ theme = 'system';
1157
+ defaultDark = DARK_THEMES[0];
1158
+ defaultLight = LIGHT_THEMES[0];
1043
1159
  }
1044
1160
 
1045
1161
  const projectDirForPm = name ? join(cwd, name) : cwd;
@@ -1070,11 +1186,12 @@ async function cmdInit(argv) {
1070
1186
  const astroMinimalDir = getScaffoldAstroMinimalDir();
1071
1187
  const svelteMinimalDir = getScaffoldSvelteMinimalDir();
1072
1188
  const pathsForScaffold = getFrameworkCssPaths(framework);
1073
- const useHandpickAstro = selectedTemplate === 'handpick' && framework === 'astro' && existsSync(astroMinimalDir);
1074
- const useHandpickSvelte = selectedTemplate === 'handpick' && framework === 'svelte' && existsSync(svelteMinimalDir);
1075
- const useAstroMinimal = framework === 'astro' && selectedTemplate === 'minimal' && existsSync(astroMinimalDir);
1076
- const useSvelteMinimal = framework === 'svelte' && selectedTemplate === 'minimal' && existsSync(svelteMinimalDir);
1077
- const useVanillaFull = framework === 'vanilla' && selectedTemplate === 'full' && existsSync(getScaffoldVanillaIndex());
1189
+ const useHandpickAstro = selectedTemplate === 'manual' && framework === 'astro' && existsSync(astroMinimalDir);
1190
+ const useHandpickSvelte = selectedTemplate === 'manual' && framework === 'svelte' && existsSync(svelteMinimalDir);
1191
+ const useAstroBase = (selectedTemplate === 'full' || selectedTemplate === 'minimal') && framework === 'astro' && existsSync(astroMinimalDir);
1192
+ const useSvelteBase = (selectedTemplate === 'full' || selectedTemplate === 'minimal') && framework === 'svelte' && existsSync(svelteMinimalDir);
1193
+ const useVanillaFull = selectedTemplate === 'full' && framework === 'vanilla' && existsSync(getScaffoldVanillaIndex());
1194
+ const useVanillaMinimal = selectedTemplate === 'minimal' && framework === 'vanilla';
1078
1195
 
1079
1196
  let cssTarget;
1080
1197
  let indexPath;
@@ -1108,31 +1225,35 @@ async function cmdInit(argv) {
1108
1225
  copyRizzoIcons(projectDir, 'astro');
1109
1226
  copyAstroComponents(projectDir, selectedComponents);
1110
1227
  }
1111
- } else if (useHandpickSvelte) {
1228
+ } else if (useAstroBase) {
1112
1229
  mkdirSync(projectDir, { recursive: true });
1113
- copyDirRecursiveWithReplacements(svelteMinimalDir, projectDir, replacements);
1114
- mkdirSync(join(projectDir, 'static', 'css'), { recursive: true });
1115
- cssTarget = join(projectDir, 'static', 'css', 'rizzo.min.css');
1230
+ copyDirRecursiveWithReplacements(astroMinimalDir, projectDir, replacements);
1231
+ mkdirSync(join(projectDir, 'public', 'css'), { recursive: true });
1232
+ cssTarget = join(projectDir, 'public', 'css', 'rizzo.min.css');
1116
1233
  copyFileSync(cssSource, cssTarget);
1117
1234
  if (statSync(cssTarget).size < 5000) {
1118
1235
  console.warn('\nWarning: rizzo.min.css is very small. From repo root run: pnpm build:css');
1119
1236
  }
1120
1237
  copyPackageLicense(projectDir);
1121
1238
  if (selectedComponents.length > 0) {
1122
- copyRizzoIcons(projectDir, 'svelte');
1123
- copySvelteComponents(projectDir, selectedComponents);
1239
+ copyRizzoIcons(projectDir, 'astro');
1240
+ copyAstroComponents(projectDir, selectedComponents);
1124
1241
  }
1125
- } else if (useAstroMinimal) {
1242
+ } else if (useHandpickSvelte) {
1126
1243
  mkdirSync(projectDir, { recursive: true });
1127
- copyDirRecursiveWithReplacements(astroMinimalDir, projectDir, replacements);
1128
- mkdirSync(join(projectDir, 'public', 'css'), { recursive: true });
1129
- cssTarget = join(projectDir, 'public', 'css', 'rizzo.min.css');
1244
+ copyDirRecursiveWithReplacements(svelteMinimalDir, projectDir, replacements);
1245
+ mkdirSync(join(projectDir, 'static', 'css'), { recursive: true });
1246
+ cssTarget = join(projectDir, 'static', 'css', 'rizzo.min.css');
1130
1247
  copyFileSync(cssSource, cssTarget);
1131
1248
  if (statSync(cssTarget).size < 5000) {
1132
1249
  console.warn('\nWarning: rizzo.min.css is very small. From repo root run: pnpm build:css');
1133
1250
  }
1134
1251
  copyPackageLicense(projectDir);
1135
- } else if (useSvelteMinimal) {
1252
+ if (selectedComponents.length > 0) {
1253
+ copyRizzoIcons(projectDir, 'svelte');
1254
+ copySvelteComponents(projectDir, selectedComponents);
1255
+ }
1256
+ } else if (useSvelteBase) {
1136
1257
  mkdirSync(projectDir, { recursive: true });
1137
1258
  copyDirRecursiveWithReplacements(svelteMinimalDir, projectDir, replacements);
1138
1259
  mkdirSync(join(projectDir, 'static', 'css'), { recursive: true });
@@ -1142,6 +1263,10 @@ async function cmdInit(argv) {
1142
1263
  console.warn('\nWarning: rizzo.min.css is very small. From repo root run: pnpm build:css');
1143
1264
  }
1144
1265
  copyPackageLicense(projectDir);
1266
+ if (selectedComponents.length > 0) {
1267
+ copyRizzoIcons(projectDir, 'svelte');
1268
+ copySvelteComponents(projectDir, selectedComponents);
1269
+ }
1145
1270
  } else if (useVanillaFull) {
1146
1271
  const cssDir = join(projectDir, pathsForScaffold.targetDir);
1147
1272
  cssTarget = join(cssDir, 'rizzo.min.css');
@@ -1175,6 +1300,29 @@ async function cmdInit(argv) {
1175
1300
  writeFileSync(join(projectDir, 'js', 'main.js'), mainJs, 'utf8');
1176
1301
  }
1177
1302
  copyPackageLicense(projectDir);
1303
+ } else if (useVanillaMinimal) {
1304
+ const cssDir = join(projectDir, pathsForScaffold.targetDir);
1305
+ cssTarget = join(cssDir, 'rizzo.min.css');
1306
+ mkdirSync(cssDir, { recursive: true });
1307
+ copyFileSync(cssSource, cssTarget);
1308
+ if (statSync(cssTarget).size < 5000) {
1309
+ console.warn('\nWarning: rizzo.min.css is very small. From repo root run: pnpm build:css');
1310
+ }
1311
+ mkdirSync(join(projectDir, 'js'), { recursive: true });
1312
+ const vanillaJs = join(getPackageRoot(), 'scaffold', 'vanilla', 'js', 'main.js');
1313
+ if (existsSync(vanillaJs)) {
1314
+ let mainJs = readFileSync(vanillaJs, 'utf8');
1315
+ mainJs = mainJs.replace(/\{\{DEFAULT_DARK\}\}/g, defaultDark).replace(/\{\{DEFAULT_LIGHT\}\}/g, defaultLight);
1316
+ writeFileSync(join(projectDir, 'js', 'main.js'), mainJs, 'utf8');
1317
+ }
1318
+ const vanillaRepl = { ...replacements, '{{LINK_HREF}}': 'css/rizzo.min.css' };
1319
+ copyVanillaComponents(projectDir, RECOMMENDED_COMPONENTS, vanillaRepl);
1320
+ copyRizzoIcons(projectDir, 'vanilla');
1321
+ const minimalIndexWithScript = minimalHtml.replace('</body>', ' <script src="js/main.js"></script>\n</body>');
1322
+ indexPath = join(projectDir, 'index.html');
1323
+ writeFileSync(indexPath, minimalIndexWithScript, 'utf8');
1324
+ writeFileSync(join(projectDir, 'README.md'), VANILLA_MINIMAL_README, 'utf8');
1325
+ copyPackageLicense(projectDir);
1178
1326
  } else {
1179
1327
  const cssDir = join(projectDir, pathsForScaffold.targetDir);
1180
1328
  cssTarget = join(cssDir, 'rizzo.min.css');
@@ -1183,10 +1331,24 @@ async function cmdInit(argv) {
1183
1331
  if (statSync(cssTarget).size < 5000) {
1184
1332
  console.warn('\nWarning: rizzo.min.css is very small. From repo root run: pnpm build:css');
1185
1333
  }
1186
- if (framework === 'vanilla') {
1334
+ if (framework === 'vanilla' && selectedTemplate === 'manual') {
1187
1335
  indexPath = join(projectDir, 'index.html');
1188
- writeFileSync(indexPath, minimalHtml, 'utf8');
1189
- writeFileSync(join(projectDir, 'README.md'), VANILLA_MINIMAL_README, 'utf8');
1336
+ let indexContent = minimalHtml;
1337
+ if (selectedComponents.length > 0) {
1338
+ mkdirSync(join(projectDir, 'js'), { recursive: true });
1339
+ const vanillaJs = join(getPackageRoot(), 'scaffold', 'vanilla', 'js', 'main.js');
1340
+ if (existsSync(vanillaJs)) {
1341
+ let mainJs = readFileSync(vanillaJs, 'utf8');
1342
+ mainJs = mainJs.replace(/\{\{DEFAULT_DARK\}\}/g, defaultDark).replace(/\{\{DEFAULT_LIGHT\}\}/g, defaultLight);
1343
+ writeFileSync(join(projectDir, 'js', 'main.js'), mainJs, 'utf8');
1344
+ }
1345
+ const vanillaRepl = { ...replacements, '{{LINK_HREF}}': 'css/rizzo.min.css' };
1346
+ copyVanillaComponents(projectDir, selectedComponents, vanillaRepl);
1347
+ copyRizzoIcons(projectDir, 'vanilla');
1348
+ indexContent = minimalHtml.replace('</body>', ' <script src="js/main.js"></script>\n</body>');
1349
+ }
1350
+ writeFileSync(indexPath, indexContent, 'utf8');
1351
+ writeFileSync(join(projectDir, 'README.md'), VANILLA_MANUAL_README, 'utf8');
1190
1352
  } else if (framework === 'astro') {
1191
1353
  indexPath = join(projectDir, 'public', 'index.html');
1192
1354
  mkdirSync(join(projectDir, 'public'), { recursive: true });
@@ -1206,16 +1368,18 @@ async function cmdInit(argv) {
1206
1368
  if (indexPath) console.log(' - ' + indexPath);
1207
1369
  if (framework === 'vanilla') {
1208
1370
  if (useVanillaFull) {
1209
- console.log(' - Vanilla JS (full): theme switcher, js/main.js, icons, README.');
1371
+ console.log(' - Vanilla JS (full): theme switcher, js/main.js, icons, component showcase, README.');
1372
+ } else if (useVanillaMinimal) {
1373
+ console.log(' - Vanilla JS (minimal): index.html + CSS + js/main.js. Add components from docs or use Full for showcase.');
1210
1374
  } else {
1211
- console.log(' - Vanilla JS (minimal): index.html + CSS link. Open index.html in a browser or add your own app.');
1375
+ console.log(' - Vanilla JS (manual): index.html + CSS only. Add JS from docs or copy from Full.');
1212
1376
  }
1213
1377
  }
1214
1378
  const pm = getPackageManagerCommands({ agent: selectedPm, command: selectedPm });
1215
1379
  const nextStep = pm.install + ' && ' + pm.run('dev');
1216
1380
  const runPrefix = name ? 'cd ' + name + ' && ' : '';
1217
1381
 
1218
- if (runInstallAfterScaffold && !noInstall && (useHandpickAstro || useHandpickSvelte || useAstroMinimal || useSvelteMinimal)) {
1382
+ if (runInstallAfterScaffold && !noInstall && (useHandpickAstro || useHandpickSvelte || useAstroBase || useSvelteBase)) {
1219
1383
  console.log('\nRunning: ' + pm.install);
1220
1384
  const code = runInDir(projectDir, pm.install);
1221
1385
  if (code !== 0) {
@@ -1231,18 +1395,17 @@ async function cmdInit(argv) {
1231
1395
 
1232
1396
  if (useHandpickAstro || useHandpickSvelte) {
1233
1397
  const fw = useHandpickAstro ? 'Astro' : 'SvelteKit';
1234
- console.log(' - Minimal ' + fw + ' base + ' + selectedComponents.length + ' hand-picked component(s). Run: ' + runPrefix + nextStep);
1235
- }
1236
- if (useAstroMinimal) {
1237
- console.log(' - Minimal Astro project (config, README, LICENSE, .env.example). Run: ' + runPrefix + nextStep);
1398
+ console.log(' - ' + fw + ' (manual): base + ' + selectedComponents.length + ' component(s). Run: ' + runPrefix + nextStep);
1238
1399
  }
1239
- if (useSvelteMinimal) {
1240
- console.log(' - Minimal SvelteKit project (config, README, LICENSE, .env.example). Run: ' + runPrefix + nextStep);
1400
+ if (useAstroBase) {
1401
+ const label = selectedTemplate === 'full' ? 'Full' : 'Minimal';
1402
+ console.log(' - Astro (' + label.toLowerCase() + '): app + ' + selectedComponents.length + ' component(s). Run: ' + runPrefix + nextStep);
1241
1403
  }
1242
- if (selectedTemplate === 'handpick' && framework === 'vanilla') {
1243
- console.log(' - Vanilla minimal base (index.html + CSS, README, LICENSE). No component files for Vanilla; use BEM markup from docs.');
1404
+ if (useSvelteBase) {
1405
+ const label = selectedTemplate === 'full' ? 'Full' : 'Minimal';
1406
+ console.log(' - SvelteKit (' + label.toLowerCase() + '): app + ' + selectedComponents.length + ' component(s). Run: ' + runPrefix + nextStep);
1244
1407
  }
1245
- if ((framework === 'astro' || framework === 'svelte') && !useAstroMinimal && !useSvelteMinimal && !useHandpickAstro && !useHandpickSvelte) {
1408
+ if ((framework === 'astro' || framework === 'svelte') && !useAstroBase && !useSvelteBase && !useHandpickAstro && !useHandpickSvelte) {
1246
1409
  const fw = framework === 'svelte' ? 'Svelte' : 'Astro';
1247
1410
  const createExample = getCreateProjectExample(pm, framework);
1248
1411
  console.log('\n - Minimal template (CSS + index). To get a full app: ' + createExample + ', then cd into the project and run ' + pm.dlx('rizzo-css add') + '.');