rizzo-css 0.0.7 → 0.0.9

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 CHANGED
@@ -41,7 +41,7 @@ import 'rizzo-css';
41
41
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/rizzo-css@latest" />
42
42
  ```
43
43
 
44
- 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 for convenience.
44
+ 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 for convenience. The **Vanilla** scaffold includes a full Settings panel and toast; **Astro** and **Svelte** scaffold layouts include theme persistence and toast (`showToast`, `removeToast`, `removeAllToasts`).
45
45
 
46
46
  ## Themes
47
47
 
package/bin/rizzo-css.js CHANGED
@@ -154,13 +154,28 @@ function selectMenu(options, title) {
154
154
  });
155
155
  }
156
156
 
157
- /** Multi-select menu: circles ○/●, Space toggles, Enter confirms. Returns array of selected values. */
157
+ /** Index of first "real" option when using all/none sentinels (0=Select all, 1=Select none, 2+=real). */
158
+ const SENTINEL_ALL = '__all__';
159
+ const SENTINEL_NONE = '__none__';
160
+
161
+ function hasAllNoneSentinels(items) {
162
+ return items.length >= 2 && items[0].value === SENTINEL_ALL && items[1].value === SENTINEL_NONE;
163
+ }
164
+
165
+ function getRealValues(items) {
166
+ if (hasAllNoneSentinels(items)) return items.slice(2).map((i) => i.value);
167
+ return items.map((i) => i.value);
168
+ }
169
+
170
+ /** Multi-select menu: circles ○/●, Space toggles, Enter confirms. Optional first two options: Select all / Select none (value __all__ / __none__). Returns array of selected values. */
158
171
  function multiSelectMenu(options, title) {
159
172
  const items = options.map((o) => (typeof o === 'string' ? { value: o, label: o } : o));
160
173
  const isTty = process.stdin.isTTY && process.stdout.isTTY;
174
+ const withSentinels = hasAllNoneSentinels(items);
175
+ const realValues = getRealValues(items);
161
176
 
162
177
  if (!isTty) {
163
- console.log('\n' + (title || 'Choose (space to toggle, enter when done') + ':');
178
+ console.log('\n' + (title || 'Choose (space to toggle, enter when done)') + ':');
164
179
  items.forEach((item, i) => console.log(' ' + (i + 1) + '. ' + (item.label || item.value)));
165
180
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
166
181
  return new Promise((resolve) => {
@@ -168,7 +183,15 @@ function multiSelectMenu(options, title) {
168
183
  rl.close();
169
184
  const s = (answer || '').trim().toLowerCase();
170
185
  if (s === 'all' || s === 'a') {
171
- resolve(items.map((i) => i.value));
186
+ resolve(realValues);
187
+ return;
188
+ }
189
+ if (withSentinels && s === '1') {
190
+ resolve(realValues);
191
+ return;
192
+ }
193
+ if (withSentinels && (s === '2' || s === 'none' || s === 'n')) {
194
+ resolve([]);
172
195
  return;
173
196
  }
174
197
  const parts = s.split(/[\s,]+/).filter(Boolean);
@@ -177,7 +200,19 @@ function multiSelectMenu(options, title) {
177
200
  const n = parseInt(p, 10);
178
201
  if (n >= 1 && n <= items.length) indices.add(n - 1);
179
202
  }
180
- resolve(Array.from(indices).sort((a, b) => a - b).map((i) => items[i].value));
203
+ if (withSentinels && indices.has(0)) {
204
+ resolve(realValues);
205
+ return;
206
+ }
207
+ if (withSentinels && indices.has(1)) {
208
+ resolve([]);
209
+ return;
210
+ }
211
+ const result = Array.from(indices)
212
+ .sort((a, b) => a - b)
213
+ .filter((i) => !withSentinels || (i !== 0 && i !== 1))
214
+ .map((i) => items[i].value);
215
+ resolve(result);
181
216
  });
182
217
  });
183
218
  }
@@ -186,11 +221,30 @@ function multiSelectMenu(options, title) {
186
221
  let index = 0;
187
222
  const selected = new Set();
188
223
  const lineCount = (title ? 1 : 0) + items.length + 1;
224
+ const realStart = withSentinels ? 2 : 0;
225
+
226
+ const finish = () => {
227
+ if (withSentinels && index === 0) {
228
+ resolve(realValues);
229
+ return;
230
+ }
231
+ if (withSentinels && index === 1) {
232
+ resolve([]);
233
+ return;
234
+ }
235
+ resolve(
236
+ Array.from(selected)
237
+ .filter((i) => i >= realStart)
238
+ .sort((a, b) => a - b)
239
+ .map((i) => items[i].value)
240
+ );
241
+ };
189
242
 
190
243
  const render = (first) => {
191
244
  const lines = (title ? [title] : []).concat(
192
245
  items.map((item, i) => {
193
- const circle = selected.has(i) ? CIRCLE_FILLED : CIRCLE_EMPTY;
246
+ const isAction = withSentinels && (i === 0 || i === 1);
247
+ const circle = isAction ? CIRCLE_EMPTY : selected.has(i) ? CIRCLE_FILLED : CIRCLE_EMPTY;
194
248
  const prefix = i === index ? C.cyan + '>' + C.reset + ' ' : ' ';
195
249
  return prefix + circle + formatLabel(item);
196
250
  })
@@ -222,25 +276,36 @@ function multiSelectMenu(options, title) {
222
276
  process.stdin.removeListener('data', onData);
223
277
  process.stdin.pause();
224
278
  process.stdout.write('\n');
225
- resolve(Array.from(selected).sort((a, b) => a - b).map((i) => items[i].value));
279
+ if (withSentinels && (index === 0 || index === 1)) {
280
+ if (index === 0) resolve(realValues);
281
+ else resolve([]);
282
+ } else {
283
+ finish();
284
+ }
226
285
  return;
227
286
  }
228
287
  if (ch === ' ') {
229
288
  buf = '';
230
- if (selected.has(index)) selected.delete(index);
231
- else selected.add(index);
289
+ if (withSentinels && index === 0) {
290
+ for (let i = realStart; i < items.length; i++) selected.add(i);
291
+ } else if (withSentinels && index === 1) {
292
+ for (let i = realStart; i < items.length; i++) selected.delete(i);
293
+ } else {
294
+ if (selected.has(index)) selected.delete(index);
295
+ else selected.add(index);
296
+ }
232
297
  render(false);
233
298
  return;
234
299
  }
235
300
  if (ch === 'a' || ch === 'A') {
236
301
  buf = '';
237
- for (let i = 0; i < items.length; i++) selected.add(i);
302
+ for (let i = realStart; i < items.length; i++) selected.add(i);
238
303
  render(false);
239
304
  return;
240
305
  }
241
306
  if (ch === 'n' || ch === 'N') {
242
307
  buf = '';
243
- selected.clear();
308
+ for (let i = realStart; i < items.length; i++) selected.delete(i);
244
309
  render(false);
245
310
  return;
246
311
  }
@@ -532,12 +597,11 @@ async function runAddToExisting() {
532
597
  }
533
598
  const framework = await selectMenu(frameworkOptions, frameworkPrompt);
534
599
 
535
- const selectedThemes = await multiSelectMenu(
600
+ const defaultTheme = await selectMenu(
536
601
  THEMES.map((t) => ({ value: t, label: t })),
537
- '? Themes (Space to toggle, Enter to confirm) we\'ll suggest the first as default data-theme'
602
+ '? Default theme (all 14 themes are included in the CSS; this sets the initial data-theme)'
538
603
  );
539
- const themeList = selectedThemes.length > 0 ? selectedThemes : [THEMES[0]];
540
- const suggestedTheme = THEMES.includes(themeList[0]) ? themeList[0] : THEMES[0];
604
+ const theme = THEMES.includes(defaultTheme) ? defaultTheme : THEMES[0];
541
605
 
542
606
  let selectedComponents = [];
543
607
  const componentList = framework === 'svelte' ? SVELTE_COMPONENTS : framework === 'astro' ? ASTRO_COMPONENTS : [];
@@ -552,8 +616,12 @@ async function runAddToExisting() {
552
616
  );
553
617
  if (includeChoice === 'pick') {
554
618
  selectedComponents = await multiSelectMenu(
555
- componentList.map((c) => ({ value: c, label: c })),
556
- '? Components (Space to toggle, Enter to confirm)'
619
+ [
620
+ { value: SENTINEL_ALL, label: 'Select all components' },
621
+ { value: SENTINEL_NONE, label: 'Select no components' },
622
+ ...componentList.map((c) => ({ value: c, label: c })),
623
+ ],
624
+ '? Components — pick individuals (Space to toggle) or choose Select all/none below. Enter=confirm'
557
625
  );
558
626
  }
559
627
  }
@@ -583,21 +651,21 @@ async function runAddToExisting() {
583
651
  if (framework === 'svelte') {
584
652
  console.log('\nAdd to your root layout (e.g. src/app.html):');
585
653
  console.log(' <link rel="stylesheet" href="' + linkHref + '" />');
586
- console.log('\nSet a theme on <html>: data-theme="' + suggestedTheme + '" (see: npx rizzo-css theme)');
654
+ console.log('\nSet a theme on <html>: data-theme="' + theme + '" (see: npx rizzo-css theme)');
587
655
  if (selectedComponents.length > 0) {
588
656
  console.log(' Components are in src/lib/rizzo — import from \'$lib/rizzo\'.');
589
657
  }
590
658
  } else if (framework === 'astro') {
591
659
  console.log('\nAdd to your layout (e.g. src/layouts/Layout.astro):');
592
660
  console.log(' <link rel="stylesheet" href="' + linkHref + '" />');
593
- console.log('\nSet a theme on <html>: data-theme="' + suggestedTheme + '" (see: npx rizzo-css theme)');
661
+ console.log('\nSet a theme on <html>: data-theme="' + theme + '" (see: npx rizzo-css theme)');
594
662
  if (selectedComponents.length > 0) {
595
663
  console.log(' Components are in src/components/rizzo — import from there.');
596
664
  }
597
665
  } else {
598
666
  console.log('\nAdd to your HTML or layout:');
599
667
  console.log(' <link rel="stylesheet" href="' + linkHref + '" />');
600
- console.log('\nSet a theme on <html>: data-theme="' + suggestedTheme + '" (see: npx rizzo-css theme)');
668
+ console.log('\nSet a theme on <html>: data-theme="' + theme + '" (see: npx rizzo-css theme)');
601
669
  }
602
670
  console.log('\nDocs: https://rizzo-css.vercel.app\n');
603
671
  }
@@ -634,12 +702,11 @@ async function cmdInit() {
634
702
  '? Framework (arrows, Enter to select) — all get the same CSS and component styles'
635
703
  );
636
704
 
637
- const selectedThemes = await multiSelectMenu(
705
+ const defaultTheme = await selectMenu(
638
706
  THEMES.map((t) => ({ value: t, label: t })),
639
- '? Themes (Space to toggle, Enter to confirm)'
707
+ '? Default theme (all 14 themes are included in the CSS; this sets the initial data-theme)'
640
708
  );
641
- const themeList = selectedThemes.length > 0 ? selectedThemes : [THEMES[0]];
642
- const theme = THEMES.includes(themeList[0]) ? themeList[0] : THEMES[0];
709
+ const theme = THEMES.includes(defaultTheme) ? defaultTheme : THEMES[0];
643
710
 
644
711
  let selectedComponents = [];
645
712
  const componentList = framework === 'svelte' ? SVELTE_COMPONENTS : framework === 'astro' ? ASTRO_COMPONENTS : [];
@@ -654,8 +721,12 @@ async function cmdInit() {
654
721
  );
655
722
  if (includeChoice === 'pick') {
656
723
  selectedComponents = await multiSelectMenu(
657
- componentList.map((c) => ({ value: c, label: c })),
658
- '? Components (Space to toggle, Enter to confirm)'
724
+ [
725
+ { value: SENTINEL_ALL, label: 'Select all components' },
726
+ { value: SENTINEL_NONE, label: 'Select no components' },
727
+ ...componentList.map((c) => ({ value: c, label: c })),
728
+ ],
729
+ '? Components — pick individuals (Space to toggle) or choose Select all/none below. Enter=confirm'
659
730
  );
660
731
  }
661
732
  }
@@ -668,9 +739,7 @@ async function cmdInit() {
668
739
  process.exit(1);
669
740
  }
670
741
 
671
- const themeComment = themeList.length > 0
672
- ? '\n <!-- Selected themes: ' + themeList.join(', ') + ' -->'
673
- : '';
742
+ const themeComment = '\n <!-- Default theme: ' + theme + ' (all 14 themes included in CSS) -->';
674
743
  const projectNamePkg = name
675
744
  ? name.replace(/\s+/g, '-').toLowerCase()
676
745
  : (framework === 'astro' ? 'my-astro-app' : framework === 'svelte' ? 'my-svelte-app' : 'my-app');
@@ -765,13 +834,14 @@ async function cmdInit() {
765
834
  console.log(' - Vanilla JS: same CSS and component styles; index includes theme switcher and sample components.');
766
835
  console.log(' - Icons: ' + join(projectDir, 'icons') + ' (SVG files)');
767
836
  }
837
+ const runPrefix = name ? 'cd ' + name + ' && ' : '';
768
838
  if (framework === 'astro' && existsSync(astroAppDir)) {
769
- console.log(' - Default Astro project with Rizzo CSS. Run: pnpm install && pnpm dev');
839
+ console.log(' - Default Astro project with Rizzo CSS. Run: ' + runPrefix + 'pnpm install && pnpm dev');
770
840
  console.log(' - Icons: src/components/rizzo/icons/ (Astro components)');
771
841
  }
772
842
  if (framework === 'svelte' && existsSync(svelteAppDir)) {
773
- console.log(' - Default SvelteKit project with Rizzo CSS. Run: pnpm install && pnpm dev');
774
- console.log(' - Icons: src/lib/rizzo/icons/ (Svelte components)');
843
+ console.log(' - Default SvelteKit project with Rizzo CSS. Run: ' + runPrefix + 'pnpm install && pnpm dev');
844
+ console.log(' - Install dependencies first (required before dev). Icons: src/lib/rizzo/icons/ (Svelte components)');
775
845
  }
776
846
  if ((framework === 'svelte' || framework === 'astro') && !existsSync(framework === 'astro' ? astroAppDir : svelteAppDir)) {
777
847
  const fw = framework === 'svelte' ? 'Svelte' : 'Astro';