rizzo-css 0.0.1 → 0.0.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 +13 -7
- package/bin/rizzo-css.js +303 -0
- package/package.json +12 -4
- package/scaffold/astro/Accordion.astro +178 -0
- package/scaffold/astro/Alert.astro +131 -0
- package/scaffold/astro/Avatar.astro +59 -0
- package/scaffold/astro/Badge.astro +24 -0
- package/scaffold/astro/Breadcrumb.astro +61 -0
- package/scaffold/astro/Button.astro +3 -0
- package/scaffold/astro/Card.astro +18 -0
- package/scaffold/astro/Checkbox.astro +38 -0
- package/scaffold/astro/CopyToClipboard.astro +199 -0
- package/scaffold/astro/Divider.astro +37 -0
- package/scaffold/astro/Dropdown.astro +807 -0
- package/scaffold/astro/FormGroup.astro +51 -0
- package/scaffold/astro/Input.astro +59 -0
- package/scaffold/astro/Modal.astro +212 -0
- package/scaffold/astro/Pagination.astro +240 -0
- package/scaffold/astro/ProgressBar.astro +65 -0
- package/scaffold/astro/Radio.astro +38 -0
- package/scaffold/astro/Select.astro +49 -0
- package/scaffold/astro/Spinner.astro +30 -0
- package/scaffold/astro/Table.astro +181 -0
- package/scaffold/astro/Tabs.astro +223 -0
- package/scaffold/astro/Textarea.astro +58 -0
- package/scaffold/astro/Toast.astro +30 -0
- package/scaffold/astro/Tooltip.astro +32 -0
- package/scaffold/astro/icons/Brush.astro +11 -0
- package/scaffold/astro/icons/Cake.astro +12 -0
- package/scaffold/astro/icons/Check.astro +30 -0
- package/scaffold/astro/icons/Cherry.astro +12 -0
- package/scaffold/astro/icons/ChevronDown.astro +30 -0
- package/scaffold/astro/icons/Circle.astro +30 -0
- package/scaffold/astro/icons/Close.astro +31 -0
- package/scaffold/astro/icons/Copy.astro +31 -0
- package/scaffold/astro/icons/Eye.astro +31 -0
- package/scaffold/astro/icons/Filter.astro +30 -0
- package/scaffold/astro/icons/Flame.astro +29 -0
- package/scaffold/astro/icons/Flower.astro +12 -0
- package/scaffold/astro/icons/Gear.astro +31 -0
- package/scaffold/astro/icons/Heart.astro +29 -0
- package/scaffold/astro/icons/IceCream.astro +32 -0
- package/scaffold/astro/icons/Leaf.astro +30 -0
- package/scaffold/astro/icons/Lemon.astro +12 -0
- package/scaffold/astro/icons/Moon.astro +30 -0
- package/scaffold/astro/icons/Owl.astro +35 -0
- package/scaffold/astro/icons/Palette.astro +34 -0
- package/scaffold/astro/icons/Rainbow.astro +32 -0
- package/scaffold/astro/icons/Search.astro +31 -0
- package/scaffold/astro/icons/Shield.astro +29 -0
- package/scaffold/astro/icons/Snowflake.astro +35 -0
- package/scaffold/astro/icons/Sort.astro +31 -0
- package/scaffold/astro/icons/Sun.astro +30 -0
- package/scaffold/astro/icons/Sunset.astro +11 -0
- package/scaffold/astro/icons/Zap.astro +10 -0
- package/scaffold/astro/icons/devicons/Astro.astro +54 -0
- package/scaffold/astro/icons/devicons/Bash.astro +35 -0
- package/scaffold/astro/icons/devicons/Css3.astro +30 -0
- package/scaffold/astro/icons/devicons/Git.astro +25 -0
- package/scaffold/astro/icons/devicons/Html5.astro +28 -0
- package/scaffold/astro/icons/devicons/Javascript.astro +26 -0
- package/scaffold/astro/icons/devicons/Nodejs.astro +48 -0
- package/scaffold/astro/icons/devicons/Plaintext.astro +34 -0
- package/scaffold/svelte/.gitkeep +0 -0
- package/scaffold/svelte/Accordion.svelte +128 -0
- package/scaffold/svelte/Alert.svelte +79 -0
- package/scaffold/svelte/Avatar.svelte +39 -0
- package/scaffold/svelte/Badge.svelte +31 -0
- package/scaffold/svelte/Breadcrumb.svelte +46 -0
- package/scaffold/svelte/Button.svelte +23 -0
- package/scaffold/svelte/Card.svelte +14 -0
- package/scaffold/svelte/Checkbox.svelte +37 -0
- package/scaffold/svelte/CopyToClipboard.svelte +76 -0
- package/scaffold/svelte/Divider.svelte +28 -0
- package/scaffold/svelte/Dropdown.svelte +237 -0
- package/scaffold/svelte/FormGroup.svelte +41 -0
- package/scaffold/svelte/Input.svelte +57 -0
- package/scaffold/svelte/Modal.svelte +152 -0
- package/scaffold/svelte/Pagination.svelte +93 -0
- package/scaffold/svelte/ProgressBar.svelte +56 -0
- package/scaffold/svelte/Radio.svelte +38 -0
- package/scaffold/svelte/Select.svelte +47 -0
- package/scaffold/svelte/Spinner.svelte +14 -0
- package/scaffold/svelte/Table.svelte +155 -0
- package/scaffold/svelte/Tabs.svelte +109 -0
- package/scaffold/svelte/Textarea.svelte +57 -0
- package/scaffold/svelte/Toast.svelte +30 -0
- package/scaffold/svelte/Tooltip.svelte +19 -0
- package/scaffold/svelte/index.ts +33 -0
package/README.md
CHANGED
|
@@ -12,23 +12,29 @@ pnpm add rizzo-css
|
|
|
12
12
|
yarn add rizzo-css
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
**Quick start (no install):** `npx rizzo-css init` scaffolds a project (prompts for framework and optional Astro/Svelte components). `npx rizzo-css add` copies the CSS into the current project. `npx rizzo-css theme` lists themes.
|
|
16
|
+
|
|
15
17
|
## Use
|
|
16
18
|
|
|
17
|
-
Import the
|
|
19
|
+
Import or link the CSS **once** in your app (e.g. root layout or main entry).
|
|
18
20
|
|
|
19
|
-
**
|
|
21
|
+
**With a bundler (Vite, Astro, webpack, etc.):**
|
|
20
22
|
|
|
21
23
|
```js
|
|
22
24
|
import 'rizzo-css';
|
|
23
25
|
```
|
|
24
26
|
|
|
25
|
-
**
|
|
27
|
+
**Without a bundler (plain HTML):** Use a CDN (unpkg and jsDelivr both serve the package automatically):
|
|
26
28
|
|
|
27
29
|
```html
|
|
28
|
-
|
|
30
|
+
<!-- unpkg -->
|
|
31
|
+
<link rel="stylesheet" href="https://unpkg.com/rizzo-css@latest" />
|
|
32
|
+
|
|
33
|
+
<!-- or jsDelivr -->
|
|
34
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/rizzo-css@latest" />
|
|
29
35
|
```
|
|
30
36
|
|
|
31
|
-
|
|
37
|
+
Use the same class names and HTML structure as in the [component docs](https://rizzo-css.vercel.app/docs/components). For Astro or Svelte, reference components and examples are in the [documentation](https://rizzo-css.vercel.app/docs/getting-started).
|
|
32
38
|
|
|
33
39
|
## Themes
|
|
34
40
|
|
|
@@ -38,11 +44,11 @@ Set the theme via `data-theme` on `<html>`:
|
|
|
38
44
|
<html lang="en" data-theme="github-dark-classic">
|
|
39
45
|
```
|
|
40
46
|
|
|
41
|
-
Theme IDs and full docs: [Theming](https://
|
|
47
|
+
Theme IDs and full docs: [Theming](https://rizzo-css.vercel.app/docs/theming).
|
|
42
48
|
|
|
43
49
|
## Docs
|
|
44
50
|
|
|
45
|
-
Full documentation
|
|
51
|
+
Full documentation: **[rizzo-css.vercel.app](https://rizzo-css.vercel.app)** — Getting Started, Components, Themes, and usage for Astro & Svelte.
|
|
46
52
|
|
|
47
53
|
## License
|
|
48
54
|
|
package/bin/rizzo-css.js
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { copyFileSync, mkdirSync, writeFileSync, existsSync, readFileSync, readdirSync } = require('fs');
|
|
4
|
+
const { join, dirname } = require('path');
|
|
5
|
+
const readline = require('readline');
|
|
6
|
+
|
|
7
|
+
const COMMANDS = ['init', 'add', 'theme', 'help'];
|
|
8
|
+
const FRAMEWORKS = ['vanilla', 'astro', 'svelte'];
|
|
9
|
+
const THEMES = [
|
|
10
|
+
'github-dark-classic',
|
|
11
|
+
'github-light',
|
|
12
|
+
'shades-of-purple',
|
|
13
|
+
'sandstorm-classic',
|
|
14
|
+
'rocky-blood-orange',
|
|
15
|
+
'minimal-dark-neon-yellow',
|
|
16
|
+
'hack-the-box',
|
|
17
|
+
'pink-cat-boo',
|
|
18
|
+
'red-velvet-cupcake',
|
|
19
|
+
'orangy-one-light',
|
|
20
|
+
'sunflower',
|
|
21
|
+
'green-breeze-light',
|
|
22
|
+
'cute-pink',
|
|
23
|
+
'semi-light-purple',
|
|
24
|
+
];
|
|
25
|
+
// Components available for scaffold (must match scaffold/svelte and scaffold/astro)
|
|
26
|
+
const SVELTE_COMPONENTS = [
|
|
27
|
+
'Button', 'Badge', 'Card', 'Divider', 'Spinner', 'ProgressBar', 'Avatar', 'Alert',
|
|
28
|
+
'Breadcrumb', 'FormGroup', 'Input', 'Checkbox', 'Textarea', 'Select', 'Radio',
|
|
29
|
+
'CopyToClipboard', 'Tooltip', 'Pagination', 'Tabs', 'Accordion', 'Dropdown',
|
|
30
|
+
'Modal', 'Toast', 'Table',
|
|
31
|
+
];
|
|
32
|
+
const ASTRO_COMPONENTS = [
|
|
33
|
+
'Button', 'Badge', 'Card', 'Divider', 'Spinner', 'ProgressBar', 'Avatar', 'Alert',
|
|
34
|
+
'Breadcrumb', 'FormGroup', 'Input', 'Checkbox', 'Textarea', 'Select', 'Radio',
|
|
35
|
+
'CopyToClipboard', 'Tooltip', 'Pagination', 'Tabs', 'Accordion', 'Dropdown',
|
|
36
|
+
'Modal', 'Toast', 'Table',
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
// Resolve path to this package (works when run via npx or from repo)
|
|
40
|
+
function getPackageRoot() {
|
|
41
|
+
return dirname(require.resolve('../package.json'));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function getCssPath() {
|
|
45
|
+
return join(getPackageRoot(), 'dist', 'rizzo.min.css');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function question(prompt) {
|
|
49
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
rl.question(prompt, (answer) => {
|
|
52
|
+
rl.close();
|
|
53
|
+
resolve((answer || '').trim());
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function printHelp() {
|
|
59
|
+
console.log(`
|
|
60
|
+
rizzo-css CLI — Add Rizzo CSS to your project
|
|
61
|
+
|
|
62
|
+
Usage:
|
|
63
|
+
npx rizzo-css <command> [options]
|
|
64
|
+
|
|
65
|
+
Commands:
|
|
66
|
+
init Scaffold a new project (prompts: name, framework, theme; Astro/Svelte: optional component picker)
|
|
67
|
+
add Copy Rizzo CSS into the current project
|
|
68
|
+
theme List available themes
|
|
69
|
+
help Show this help
|
|
70
|
+
|
|
71
|
+
Examples:
|
|
72
|
+
npx rizzo-css init
|
|
73
|
+
npx rizzo-css add
|
|
74
|
+
npx rizzo-css add --path public/css
|
|
75
|
+
npx rizzo-css theme
|
|
76
|
+
|
|
77
|
+
Docs: https://rizzo-css.vercel.app
|
|
78
|
+
`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function cmdTheme() {
|
|
82
|
+
console.log('\nAvailable themes (set data-theme on <html>):\n');
|
|
83
|
+
THEMES.forEach((t) => console.log(' ' + t));
|
|
84
|
+
console.log('\nExample: <html lang="en" data-theme="github-dark-classic">\n');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function cmdAdd(argv) {
|
|
88
|
+
const pathIdx = argv.indexOf('--path');
|
|
89
|
+
const customPath = pathIdx !== -1 && argv[pathIdx + 1] ? argv[pathIdx + 1] : null;
|
|
90
|
+
const targetDir = customPath || 'css';
|
|
91
|
+
const targetFile = join(process.cwd(), targetDir, 'rizzo.min.css');
|
|
92
|
+
const cssSource = getCssPath();
|
|
93
|
+
|
|
94
|
+
if (!existsSync(cssSource)) {
|
|
95
|
+
console.error('Error: Rizzo CSS build not found. Run from repo root: pnpm build:css');
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
mkdirSync(join(process.cwd(), targetDir), { recursive: true });
|
|
100
|
+
copyFileSync(cssSource, targetFile);
|
|
101
|
+
const linkPath = targetDir + '/rizzo.min.css';
|
|
102
|
+
console.log('\n✓ Rizzo CSS copied to ' + targetFile);
|
|
103
|
+
console.log('\nAdd to your HTML or layout:\n');
|
|
104
|
+
console.log(' <link rel="stylesheet" href="' + linkPath + '" />');
|
|
105
|
+
console.log('\nSet a theme on <html>: data-theme="github-dark-classic" (see: npx rizzo-css theme)\n');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function parseComponentSelection(input, componentList, maxNum) {
|
|
109
|
+
const s = (input || '').trim().toLowerCase();
|
|
110
|
+
if (s === 'none' || s === 'n') return [];
|
|
111
|
+
if (s === 'all' || s === 'a') return componentList.slice();
|
|
112
|
+
const parts = s.split(/[\s,]+/).filter(Boolean);
|
|
113
|
+
const indices = new Set();
|
|
114
|
+
for (const p of parts) {
|
|
115
|
+
const n = parseInt(p, 10);
|
|
116
|
+
if (n >= 1 && n <= maxNum) indices.add(n - 1);
|
|
117
|
+
}
|
|
118
|
+
return indices.size === 0 ? [] : Array.from(indices).sort((a, b) => a - b).map((i) => componentList[i]);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function getScaffoldSvelteDir() {
|
|
122
|
+
return join(getPackageRoot(), 'scaffold', 'svelte');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function getScaffoldAstroDir() {
|
|
126
|
+
return join(getPackageRoot(), 'scaffold', 'astro');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function copyDirRecursive(src, dest) {
|
|
130
|
+
mkdirSync(dest, { recursive: true });
|
|
131
|
+
const entries = readdirSync(src, { withFileTypes: true });
|
|
132
|
+
for (const e of entries) {
|
|
133
|
+
const srcPath = join(src, e.name);
|
|
134
|
+
const destPath = join(dest, e.name);
|
|
135
|
+
if (e.isDirectory()) {
|
|
136
|
+
copyDirRecursive(srcPath, destPath);
|
|
137
|
+
} else {
|
|
138
|
+
copyFileSync(srcPath, destPath);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function copySvelteComponents(projectDir, selectedNames) {
|
|
144
|
+
const scaffoldDir = getScaffoldSvelteDir();
|
|
145
|
+
if (!existsSync(scaffoldDir)) {
|
|
146
|
+
console.log('\n Component templates not in this package; use CSS only or copy from repo: https://github.com/mingleusa/rizzo-css/tree/main/src/components/svelte');
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const files = readdirSync(scaffoldDir);
|
|
150
|
+
const available = files.filter((f) => f.endsWith('.svelte')).map((f) => f.replace('.svelte', ''));
|
|
151
|
+
const toCopy = selectedNames.filter((n) => available.includes(n));
|
|
152
|
+
if (toCopy.length === 0) {
|
|
153
|
+
console.log('\n No matching component files in scaffold; use CSS only or copy from repo.');
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const targetDir = join(projectDir, 'src', 'lib', 'rizzo');
|
|
157
|
+
mkdirSync(targetDir, { recursive: true });
|
|
158
|
+
const exports = [];
|
|
159
|
+
for (const name of toCopy) {
|
|
160
|
+
const src = join(scaffoldDir, name + '.svelte');
|
|
161
|
+
if (existsSync(src)) {
|
|
162
|
+
copyFileSync(src, join(targetDir, name + '.svelte'));
|
|
163
|
+
exports.push(`export { default as ${name} } from './${name}.svelte';`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (exports.length > 0) {
|
|
167
|
+
const indexContent = `/** Rizzo CSS Svelte components — selected via npx rizzo-css init */\n${exports.join('\n')}\n`;
|
|
168
|
+
writeFileSync(join(targetDir, 'index.ts'), indexContent, 'utf8');
|
|
169
|
+
console.log('\n ✓ ' + exports.length + ' Svelte components copied to ' + targetDir);
|
|
170
|
+
console.log(' Import in your app: import { Button, Badge, ... } from \'$lib/rizzo\';\n');
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function copyAstroComponents(projectDir, selectedNames) {
|
|
175
|
+
const scaffoldDir = getScaffoldAstroDir();
|
|
176
|
+
if (!existsSync(scaffoldDir)) {
|
|
177
|
+
console.log('\n Astro component templates not in this package; use CSS only or copy from repo: https://github.com/mingleusa/rizzo-css/tree/main/src/components');
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const files = readdirSync(scaffoldDir).filter((f) => f.endsWith('.astro'));
|
|
181
|
+
const available = files.map((f) => f.replace('.astro', ''));
|
|
182
|
+
const toCopy = selectedNames.filter((n) => available.includes(n));
|
|
183
|
+
if (toCopy.length === 0) {
|
|
184
|
+
console.log('\n No matching Astro components in scaffold; use CSS only or copy from repo.');
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const targetDir = join(projectDir, 'src', 'components', 'rizzo');
|
|
188
|
+
mkdirSync(targetDir, { recursive: true });
|
|
189
|
+
let count = 0;
|
|
190
|
+
for (const name of toCopy) {
|
|
191
|
+
const src = join(scaffoldDir, name + '.astro');
|
|
192
|
+
if (existsSync(src)) {
|
|
193
|
+
copyFileSync(src, join(targetDir, name + '.astro'));
|
|
194
|
+
count++;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const iconsSrc = join(scaffoldDir, 'icons');
|
|
198
|
+
if (existsSync(iconsSrc)) {
|
|
199
|
+
copyDirRecursive(iconsSrc, join(targetDir, 'icons'));
|
|
200
|
+
}
|
|
201
|
+
if (count > 0) {
|
|
202
|
+
console.log('\n ✓ ' + count + ' Astro components + icons copied to ' + targetDir);
|
|
203
|
+
console.log(' Import in your pages: import Button from \'../components/rizzo/Button.astro\';\n');
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function cmdInit() {
|
|
208
|
+
const name = await question('Project name (folder name, or leave blank for current directory): ');
|
|
209
|
+
let framework = await question('Framework: vanilla, astro, svelte (default: vanilla): ') || 'vanilla';
|
|
210
|
+
framework = framework.toLowerCase();
|
|
211
|
+
if (!FRAMEWORKS.includes(framework)) framework = 'vanilla';
|
|
212
|
+
|
|
213
|
+
const theme = await question('Theme (default: github-dark-classic, or run "npx rizzo-css theme" for list): ') || 'github-dark-classic';
|
|
214
|
+
|
|
215
|
+
let selectedComponents = [];
|
|
216
|
+
const componentList = framework === 'svelte' ? SVELTE_COMPONENTS : framework === 'astro' ? ASTRO_COMPONENTS : [];
|
|
217
|
+
if (componentList.length > 0) {
|
|
218
|
+
const label = framework === 'svelte' ? 'Svelte' : 'Astro';
|
|
219
|
+
const include = await question('Include ' + label + ' components? (y/n, default: n): ') || 'n';
|
|
220
|
+
if (include.toLowerCase() === 'y' || include.toLowerCase() === 'yes') {
|
|
221
|
+
console.log('\nComponents (enter numbers to include, e.g. 1 3 5, or "all" / "none"):');
|
|
222
|
+
componentList.forEach((c, i) => console.log(' ' + (i + 1) + '. ' + c));
|
|
223
|
+
const choice = await question('\nSelection (e.g. 1 2 3 or all): ');
|
|
224
|
+
selectedComponents = parseComponentSelection(choice, componentList, componentList.length);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const projectDir = name ? join(process.cwd(), name) : process.cwd();
|
|
229
|
+
const cssDir = framework === 'astro' ? join(projectDir, 'public', 'css') : join(projectDir, 'css');
|
|
230
|
+
const cssTarget = join(cssDir, 'rizzo.min.css');
|
|
231
|
+
const cssSource = getCssPath();
|
|
232
|
+
|
|
233
|
+
if (!existsSync(cssSource)) {
|
|
234
|
+
console.error('Error: Rizzo CSS build not found. Run from repo root: pnpm build:css');
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
mkdirSync(cssDir, { recursive: true });
|
|
239
|
+
copyFileSync(cssSource, cssTarget);
|
|
240
|
+
|
|
241
|
+
const linkHref = framework === 'astro' ? '/css/rizzo.min.css' : 'css/rizzo.min.css';
|
|
242
|
+
const indexHtml = `<!DOCTYPE html>
|
|
243
|
+
<html lang="en" data-theme="${theme}">
|
|
244
|
+
<head>
|
|
245
|
+
<meta charset="UTF-8" />
|
|
246
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
247
|
+
<title>${name || 'App'}</title>
|
|
248
|
+
<link rel="stylesheet" href="${linkHref}" />
|
|
249
|
+
</head>
|
|
250
|
+
<body>
|
|
251
|
+
<h1>Hello, Rizzo CSS</h1>
|
|
252
|
+
<p>Edit this file and add components. Docs: <a href="https://rizzo-css.vercel.app">rizzo-css.vercel.app</a></p>
|
|
253
|
+
</body>
|
|
254
|
+
</html>
|
|
255
|
+
`;
|
|
256
|
+
|
|
257
|
+
const indexPath = join(projectDir, 'index.html');
|
|
258
|
+
writeFileSync(indexPath, indexHtml, 'utf8');
|
|
259
|
+
|
|
260
|
+
if (framework === 'svelte' && selectedComponents.length > 0) {
|
|
261
|
+
copySvelteComponents(projectDir, selectedComponents);
|
|
262
|
+
} else if (framework === 'astro' && selectedComponents.length > 0) {
|
|
263
|
+
copyAstroComponents(projectDir, selectedComponents);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
console.log('\n✓ Project ready at ' + projectDir);
|
|
267
|
+
console.log(' - ' + cssTarget);
|
|
268
|
+
console.log(' - ' + indexPath);
|
|
269
|
+
console.log('\nRun a local server (e.g. npx serve .) or open index.html. Docs: https://rizzo-css.vercel.app\n');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function main() {
|
|
273
|
+
const argv = process.argv.slice(2);
|
|
274
|
+
const command = (argv[0] || 'help').toLowerCase().replace(/^--?/, '');
|
|
275
|
+
|
|
276
|
+
if (command === 'help' || command === 'h' || !COMMANDS.includes(command)) {
|
|
277
|
+
if (argv[0] && !COMMANDS.includes(command) && command !== 'h') {
|
|
278
|
+
console.error('Unknown command: ' + argv[0] + '\n');
|
|
279
|
+
}
|
|
280
|
+
printHelp();
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (command === 'theme') {
|
|
285
|
+
cmdTheme();
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (command === 'add') {
|
|
290
|
+
cmdAdd(argv);
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (command === 'init') {
|
|
295
|
+
cmdInit().catch((err) => {
|
|
296
|
+
console.error(err);
|
|
297
|
+
process.exit(1);
|
|
298
|
+
});
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rizzo-css",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"scripts": {
|
|
5
|
-
"prepublishOnly": "cd ../.. && pnpm build:css"
|
|
5
|
+
"prepublishOnly": "cd ../.. && pnpm build:css && node scripts/copy-scaffold.js"
|
|
6
6
|
},
|
|
7
7
|
"description": "A modern CSS design system with semantic theming, 14 themes, and accessible components (BEM). Use with Astro, Svelte, or any framework.",
|
|
8
8
|
"style": "dist/rizzo.min.css",
|
|
9
9
|
"main": "dist/rizzo.min.css",
|
|
10
|
+
"unpkg": "dist/rizzo.min.css",
|
|
11
|
+
"jsdelivr": "dist/rizzo.min.css",
|
|
10
12
|
"exports": {
|
|
11
13
|
".": {
|
|
12
14
|
"style": "./dist/rizzo.min.css",
|
|
@@ -14,9 +16,14 @@
|
|
|
14
16
|
"require": "./dist/rizzo.min.css"
|
|
15
17
|
}
|
|
16
18
|
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"rizzo-css": "./bin/rizzo-css.js"
|
|
21
|
+
},
|
|
17
22
|
"files": [
|
|
18
23
|
"dist",
|
|
19
|
-
"README.md"
|
|
24
|
+
"README.md",
|
|
25
|
+
"bin",
|
|
26
|
+
"scaffold"
|
|
20
27
|
],
|
|
21
28
|
"keywords": [
|
|
22
29
|
"css",
|
|
@@ -31,5 +38,6 @@
|
|
|
31
38
|
"type": "git",
|
|
32
39
|
"url": "https://github.com/mingleusa/rizzo-css.git"
|
|
33
40
|
},
|
|
34
|
-
"license": "MIT"
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"author": "mingleusa"
|
|
35
43
|
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
import ChevronDown from './icons/ChevronDown.astro';
|
|
3
|
+
|
|
4
|
+
interface AccordionItem {
|
|
5
|
+
id: string;
|
|
6
|
+
title: string;
|
|
7
|
+
content?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
items: AccordionItem[];
|
|
12
|
+
id?: string;
|
|
13
|
+
allowMultiple?: boolean;
|
|
14
|
+
defaultExpanded?: string | string[];
|
|
15
|
+
class?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
items,
|
|
20
|
+
id,
|
|
21
|
+
allowMultiple = false,
|
|
22
|
+
defaultExpanded,
|
|
23
|
+
class: className = '',
|
|
24
|
+
} = Astro.props;
|
|
25
|
+
|
|
26
|
+
const accordionId = id || `accordion-${Math.random().toString(36).substr(2, 9)}`;
|
|
27
|
+
|
|
28
|
+
const getDefaultExpanded = (): Set<string> => {
|
|
29
|
+
if (defaultExpanded === undefined) return new Set(items[0] ? [items[0].id] : []);
|
|
30
|
+
if (typeof defaultExpanded === 'string') return new Set([defaultExpanded]);
|
|
31
|
+
return new Set(defaultExpanded);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const defaultOpenIds = getDefaultExpanded();
|
|
35
|
+
const classes = `accordion ${className}`.trim();
|
|
36
|
+
let slotIndex = 0;
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
<div class={classes} data-accordion={accordionId} data-allow-multiple={allowMultiple ? 'true' : 'false'}>
|
|
40
|
+
{items.map((item) => {
|
|
41
|
+
const triggerId = `${accordionId}-trigger-${item.id}`;
|
|
42
|
+
const panelId = `${accordionId}-panel-${item.id}`;
|
|
43
|
+
const isExpanded = defaultOpenIds.has(item.id);
|
|
44
|
+
const useSlot = !item.content;
|
|
45
|
+
const currentSlotIndex = useSlot ? slotIndex++ : -1;
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div class="accordion__item" data-accordion-item data-item-id={item.id}>
|
|
49
|
+
<h3 class="accordion__heading">
|
|
50
|
+
<button
|
|
51
|
+
type="button"
|
|
52
|
+
class={`accordion__trigger ${isExpanded ? 'accordion__trigger--expanded' : ''}`}
|
|
53
|
+
id={triggerId}
|
|
54
|
+
aria-expanded={isExpanded}
|
|
55
|
+
aria-controls={panelId}
|
|
56
|
+
data-accordion-trigger
|
|
57
|
+
>
|
|
58
|
+
<span class="accordion__title">{item.title}</span>
|
|
59
|
+
<ChevronDown class="accordion__icon" width={16} height={16} aria-hidden="true" />
|
|
60
|
+
</button>
|
|
61
|
+
</h3>
|
|
62
|
+
<div
|
|
63
|
+
class={`accordion__panel ${isExpanded ? 'accordion__panel--expanded' : ''}`}
|
|
64
|
+
id={panelId}
|
|
65
|
+
role="region"
|
|
66
|
+
aria-labelledby={triggerId}
|
|
67
|
+
hidden={!isExpanded}
|
|
68
|
+
data-accordion-panel
|
|
69
|
+
>
|
|
70
|
+
<div class="accordion__panel-inner">
|
|
71
|
+
{item.content ? (
|
|
72
|
+
<div class="accordion__panel-content" set:html={item.content} />
|
|
73
|
+
) : (
|
|
74
|
+
<div class="accordion__panel-content accordion__panel-slot" data-accordion-slot-index={currentSlotIndex}>
|
|
75
|
+
<!-- Slot content distributed by script -->
|
|
76
|
+
</div>
|
|
77
|
+
)}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
})}
|
|
83
|
+
<!-- Slot content for distribution (same order as items) -->
|
|
84
|
+
<div class="accordion__slot-content" style="display: none;">
|
|
85
|
+
<slot />
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<script is:inline>
|
|
90
|
+
(function initAccordions() {
|
|
91
|
+
function initOne(accordion) {
|
|
92
|
+
if (accordion.dataset.accordionInit === 'true') return;
|
|
93
|
+
accordion.dataset.accordionInit = 'true';
|
|
94
|
+
|
|
95
|
+
const isMultiple = accordion.getAttribute('data-allow-multiple') === 'true';
|
|
96
|
+
const triggers = accordion.querySelectorAll('[data-accordion-trigger]');
|
|
97
|
+
|
|
98
|
+
const setExpanded = (trigger, expanded) => {
|
|
99
|
+
const panelId = trigger.getAttribute('aria-controls');
|
|
100
|
+
const panel = panelId ? accordion.querySelector('#' + CSS.escape(panelId)) : null;
|
|
101
|
+
trigger.setAttribute('aria-expanded', String(expanded));
|
|
102
|
+
trigger.classList.toggle('accordion__trigger--expanded', expanded);
|
|
103
|
+
if (panel) {
|
|
104
|
+
panel.classList.toggle('accordion__panel--expanded', expanded);
|
|
105
|
+
panel.hidden = !expanded;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const toggle = (trigger) => {
|
|
110
|
+
const expanded = trigger.getAttribute('aria-expanded') === 'true';
|
|
111
|
+
if (!isMultiple) {
|
|
112
|
+
triggers.forEach((t) => setExpanded(t, false));
|
|
113
|
+
}
|
|
114
|
+
setExpanded(trigger, !expanded);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
triggers.forEach((trigger) => {
|
|
118
|
+
trigger.addEventListener('click', () => toggle(trigger));
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
triggers.forEach((trigger, index) => {
|
|
122
|
+
trigger.addEventListener('keydown', (e) => {
|
|
123
|
+
let targetIndex = index;
|
|
124
|
+
switch (e.key) {
|
|
125
|
+
case 'ArrowDown':
|
|
126
|
+
e.preventDefault();
|
|
127
|
+
targetIndex = Math.min(index + 1, triggers.length - 1);
|
|
128
|
+
break;
|
|
129
|
+
case 'ArrowUp':
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
targetIndex = Math.max(index - 1, 0);
|
|
132
|
+
break;
|
|
133
|
+
case 'Home':
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
targetIndex = 0;
|
|
136
|
+
break;
|
|
137
|
+
case 'End':
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
targetIndex = triggers.length - 1;
|
|
140
|
+
break;
|
|
141
|
+
case 'Enter':
|
|
142
|
+
case ' ':
|
|
143
|
+
e.preventDefault();
|
|
144
|
+
toggle(trigger);
|
|
145
|
+
return;
|
|
146
|
+
default:
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (targetIndex !== index) {
|
|
150
|
+
triggers[targetIndex].focus();
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const slotContent = accordion.querySelector('.accordion__slot-content');
|
|
156
|
+
if (slotContent) {
|
|
157
|
+
const slotChildren = Array.from(slotContent.children);
|
|
158
|
+
slotChildren.forEach((child, index) => {
|
|
159
|
+
const slotPlaceholder = accordion.querySelector('[data-accordion-slot-index="' + index + '"]');
|
|
160
|
+
if (slotPlaceholder) {
|
|
161
|
+
slotPlaceholder.appendChild(child);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
slotContent.remove();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function init() {
|
|
169
|
+
document.querySelectorAll('[data-accordion]').forEach(initOne);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (document.readyState === 'loading') {
|
|
173
|
+
document.addEventListener('DOMContentLoaded', init);
|
|
174
|
+
} else {
|
|
175
|
+
init();
|
|
176
|
+
}
|
|
177
|
+
})();
|
|
178
|
+
</script>
|