rizzo-css 0.0.50 → 0.0.51
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 +1 -1
- package/bin/rizzo-css.js +4 -4
- package/dist/sfx/click.wav +0 -0
- package/package.json +1 -1
- package/scaffold/astro-core/.astro/content-assets.mjs +1 -0
- package/scaffold/astro-core/.astro/content-modules.mjs +1 -0
- package/scaffold/astro-core/.astro/content.d.ts +199 -0
- package/scaffold/astro-core/.astro/types.d.ts +2 -0
- package/scaffold/astro-core/dist/.gitkeep +0 -0
- package/scaffold/astro-core/dist/_noop-middleware.mjs +3 -0
- package/scaffold/astro-core/dist/chunks/astro/server_9Mzx7luy.mjs +6023 -0
- package/scaffold/astro-core/dist/chunks/astro_BOYUKg7r.mjs +1 -0
- package/scaffold/astro-core/dist/favicon.svg +18 -0
- package/scaffold/astro-core/dist/manifest_DXpJmqSX.mjs +154 -0
- package/scaffold/astro-core/dist/noop-entrypoint.mjs +3 -0
- package/scaffold/astro-core/dist/pages/index.astro.mjs +87 -0
- package/scaffold/astro-core/dist/renderers.mjs +3 -0
- package/scaffold/astro-core/node_modules/.astro/data-store.json +1 -0
- package/scaffold/astro-core/node_modules/.vite/deps/_metadata.json +31 -0
- package/scaffold/astro-core/node_modules/.vite/deps/astro___aria-query.js +6776 -0
- package/scaffold/astro-core/node_modules/.vite/deps/astro___aria-query.js.map +7 -0
- package/scaffold/astro-core/node_modules/.vite/deps/astro___axobject-query.js +3754 -0
- package/scaffold/astro-core/node_modules/.vite/deps/astro___axobject-query.js.map +7 -0
- package/scaffold/astro-core/node_modules/.vite/deps/astro___cssesc.js +99 -0
- package/scaffold/astro-core/node_modules/.vite/deps/astro___cssesc.js.map +7 -0
- package/scaffold/astro-core/node_modules/.vite/deps/chunk-BUSYA2B4.js +8 -0
- package/scaffold/astro-core/node_modules/.vite/deps/chunk-BUSYA2B4.js.map +7 -0
- package/scaffold/astro-core/node_modules/.vite/deps/package.json +3 -0
- package/scaffold/astro-core/src/components/rizzo/CopyToClipboard.astro +157 -0
- package/scaffold/astro-core/src/components/rizzo/icons/Check.astro +29 -0
- package/scaffold/astro-core/src/components/rizzo/icons/Copy.astro +30 -0
- package/scaffold/astro-core/src/pages/index.astro +3 -15
- package/scaffold/shared/sound-effects-inline.js +3 -3
- package/scaffold/svelte/theme.ts +16 -2
- package/scaffold/svelte-core/src/routes/+page.svelte +2 -9
- package/scaffold/utils/theme.ts +16 -2
- package/scaffold/vanilla/README-RIZZO.md +2 -2
- package/scaffold/vanilla/components/accordion.html +14 -0
- package/scaffold/vanilla/components/alert.html +14 -0
- package/scaffold/vanilla/components/avatar.html +14 -0
- package/scaffold/vanilla/components/badge.html +14 -0
- package/scaffold/vanilla/components/breadcrumb.html +14 -0
- package/scaffold/vanilla/components/button.html +14 -0
- package/scaffold/vanilla/components/cards.html +14 -0
- package/scaffold/vanilla/components/copy-to-clipboard.html +14 -0
- package/scaffold/vanilla/components/divider.html +14 -0
- package/scaffold/vanilla/components/docs-sidebar.html +14 -0
- package/scaffold/vanilla/components/dropdown.html +14 -0
- package/scaffold/vanilla/components/font-switcher.html +14 -0
- package/scaffold/vanilla/components/footer.html +14 -0
- package/scaffold/vanilla/components/forms.html +14 -0
- package/scaffold/vanilla/components/icons.html +14 -0
- package/scaffold/vanilla/components/index.html +14 -0
- package/scaffold/vanilla/components/modal.html +14 -0
- package/scaffold/vanilla/components/navbar.html +14 -0
- package/scaffold/vanilla/components/pagination.html +14 -0
- package/scaffold/vanilla/components/progress-bar.html +14 -0
- package/scaffold/vanilla/components/search.html +14 -0
- package/scaffold/vanilla/components/settings.html +14 -0
- package/scaffold/vanilla/components/sound-effects.html +14 -0
- package/scaffold/vanilla/components/spinner.html +14 -0
- package/scaffold/vanilla/components/table.html +14 -0
- package/scaffold/vanilla/components/tabs.html +14 -0
- package/scaffold/vanilla/components/theme-switcher.html +14 -0
- package/scaffold/vanilla/components/toast.html +14 -0
- package/scaffold/vanilla/components/tooltip.html +14 -0
- package/scaffold/vanilla/index.html +22 -4
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Copy from './icons/Copy.astro';
|
|
3
|
+
import Check from './icons/Check.astro';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
value: string;
|
|
7
|
+
label?: string;
|
|
8
|
+
format?: string;
|
|
9
|
+
/** When true, only the copy/check icons are shown (e.g. in code blocks). */
|
|
10
|
+
iconOnly?: boolean;
|
|
11
|
+
/** For icon-only: accessible label for the hidden text (e.g. "Copy code"). */
|
|
12
|
+
buttonLabel?: string;
|
|
13
|
+
class?: string;
|
|
14
|
+
id?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
value,
|
|
19
|
+
label,
|
|
20
|
+
format,
|
|
21
|
+
iconOnly = false,
|
|
22
|
+
buttonLabel,
|
|
23
|
+
class: className = '',
|
|
24
|
+
id,
|
|
25
|
+
} = Astro.props;
|
|
26
|
+
|
|
27
|
+
const buttonId = id || `copy-btn-${Math.random().toString(36).substr(2, 9)}`;
|
|
28
|
+
const defaultTooltip = label || (iconOnly ? (buttonLabel || 'Copy') : 'Copy to clipboard');
|
|
29
|
+
const ariaLabel = label || (iconOnly ? (buttonLabel || 'Copy to clipboard') : `Copy ${value} to clipboard`);
|
|
30
|
+
const displayText = iconOnly ? (buttonLabel || 'Copy') : value;
|
|
31
|
+
const buttonClass = ['copy-to-clipboard', iconOnly ? 'copy-to-clipboard--icon-only' : '', className].filter(Boolean).join(' ').trim();
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
<span class="tooltip-host" data-tooltip={defaultTooltip}>
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
class={buttonClass}
|
|
38
|
+
data-copy-value={value}
|
|
39
|
+
data-copy-format={format}
|
|
40
|
+
aria-label={ariaLabel}
|
|
41
|
+
id={buttonId}
|
|
42
|
+
data-copy-icon-only={iconOnly ? 'true' : undefined}
|
|
43
|
+
data-copy-button-label={iconOnly ? (buttonLabel || 'Copy') : undefined}
|
|
44
|
+
>
|
|
45
|
+
<span class="copy-to-clipboard__text">{displayText}</span>
|
|
46
|
+
<span class="copy-to-clipboard__icon copy-to-clipboard__icon--copy" aria-hidden="true">
|
|
47
|
+
<Copy width={16} height={16} />
|
|
48
|
+
</span>
|
|
49
|
+
<span class="copy-to-clipboard__icon copy-to-clipboard__icon--check" aria-hidden="true">
|
|
50
|
+
<Check width={16} height={16} />
|
|
51
|
+
</span>
|
|
52
|
+
<span class="copy-to-clipboard__feedback" aria-live="polite"></span>
|
|
53
|
+
</button>
|
|
54
|
+
</span>
|
|
55
|
+
|
|
56
|
+
<script>
|
|
57
|
+
(function initCopyToClipboard() {
|
|
58
|
+
const init = () => {
|
|
59
|
+
const buttons = document.querySelectorAll('.copy-to-clipboard');
|
|
60
|
+
buttons.forEach((button) => {
|
|
61
|
+
if (button.hasAttribute('data-copy-initialized')) return;
|
|
62
|
+
button.setAttribute('data-copy-initialized', 'true');
|
|
63
|
+
const tooltipHost = button.closest('.tooltip-host');
|
|
64
|
+
const defaultTooltip = tooltipHost ? (tooltipHost.getAttribute('data-tooltip') || 'Copy to clipboard') : 'Copy to clipboard';
|
|
65
|
+
const defaultAriaLabel = button.getAttribute('aria-label') || 'Copy to clipboard';
|
|
66
|
+
if (tooltipHost) tooltipHost.setAttribute('data-tooltip', defaultTooltip);
|
|
67
|
+
button.setAttribute('data-copy-aria-label', defaultAriaLabel);
|
|
68
|
+
if (tooltipHost) tooltipHost.setAttribute('data-copy-default-tooltip', defaultTooltip);
|
|
69
|
+
const getValue = () => button.getAttribute('data-copy-value') || '';
|
|
70
|
+
const getFormat = () => button.getAttribute('data-copy-format') || '';
|
|
71
|
+
const feedback = button.querySelector('.copy-to-clipboard__feedback');
|
|
72
|
+
const copyIcon = button.querySelector('.copy-to-clipboard__icon--copy');
|
|
73
|
+
const checkIcon = button.querySelector('.copy-to-clipboard__icon--check');
|
|
74
|
+
const textSpan = button.querySelector('.copy-to-clipboard__text');
|
|
75
|
+
const updateDisplay = () => {
|
|
76
|
+
if (button.hasAttribute('data-copy-icon-only')) {
|
|
77
|
+
if (textSpan) textSpan.textContent = button.getAttribute('data-copy-button-label') || 'Copy';
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const value = getValue();
|
|
81
|
+
if (textSpan) textSpan.textContent = value || '';
|
|
82
|
+
};
|
|
83
|
+
updateDisplay();
|
|
84
|
+
const observer = new MutationObserver((mutations) => {
|
|
85
|
+
let shouldUpdate = false;
|
|
86
|
+
mutations.forEach((mutation) => {
|
|
87
|
+
if (mutation.type === 'attributes' && (mutation.attributeName === 'data-copy-value' || mutation.attributeName === 'data-copy-format')) shouldUpdate = true;
|
|
88
|
+
});
|
|
89
|
+
if (shouldUpdate) requestAnimationFrame(updateDisplay);
|
|
90
|
+
});
|
|
91
|
+
observer.observe(button, { attributes: true, attributeFilter: ['data-copy-value', 'data-copy-format'], attributeOldValue: false });
|
|
92
|
+
button.addEventListener('value-updated', () => updateDisplay());
|
|
93
|
+
let lastValue = getValue();
|
|
94
|
+
const intervalId = setInterval(() => {
|
|
95
|
+
const currentValue = getValue();
|
|
96
|
+
if (currentValue !== lastValue) { lastValue = currentValue; updateDisplay(); }
|
|
97
|
+
}, 300);
|
|
98
|
+
button.setAttribute('data-copy-interval-id', intervalId.toString());
|
|
99
|
+
const copyToClipboard = async () => {
|
|
100
|
+
let value = getValue();
|
|
101
|
+
const format = getFormat();
|
|
102
|
+
if (!value && textSpan) value = textSpan.textContent || '';
|
|
103
|
+
if (!value) return;
|
|
104
|
+
try {
|
|
105
|
+
await navigator.clipboard.writeText(value);
|
|
106
|
+
if (copyIcon) copyIcon.classList.add('copy-to-clipboard__icon--hidden');
|
|
107
|
+
if (checkIcon) checkIcon.classList.remove('copy-to-clipboard__icon--hidden');
|
|
108
|
+
if (feedback) feedback.textContent = format ? `Copied ${format}!` : 'Copied!';
|
|
109
|
+
const th = button.closest('.tooltip-host');
|
|
110
|
+
if (th) th.setAttribute('data-tooltip', format ? `Copied ${format}!` : 'Copied!');
|
|
111
|
+
button.setAttribute('aria-label', format ? `Copied ${format}!` : 'Copied!');
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
if (copyIcon) copyIcon.classList.remove('copy-to-clipboard__icon--hidden');
|
|
114
|
+
if (checkIcon) checkIcon.classList.add('copy-to-clipboard__icon--hidden');
|
|
115
|
+
if (feedback) feedback.textContent = '';
|
|
116
|
+
if (th) th.setAttribute('data-tooltip', th.getAttribute('data-copy-default-tooltip') || defaultTooltip);
|
|
117
|
+
button.setAttribute('aria-label', defaultAriaLabel);
|
|
118
|
+
}, 2000);
|
|
119
|
+
} catch (err) {
|
|
120
|
+
const textArea = document.createElement('textarea');
|
|
121
|
+
textArea.value = value;
|
|
122
|
+
textArea.style.position = 'fixed';
|
|
123
|
+
textArea.style.left = '-999999px';
|
|
124
|
+
document.body.appendChild(textArea);
|
|
125
|
+
textArea.focus();
|
|
126
|
+
textArea.select();
|
|
127
|
+
try {
|
|
128
|
+
document.execCommand('copy');
|
|
129
|
+
if (copyIcon) copyIcon.classList.add('copy-to-clipboard__icon--hidden');
|
|
130
|
+
if (checkIcon) checkIcon.classList.remove('copy-to-clipboard__icon--hidden');
|
|
131
|
+
if (feedback) feedback.textContent = format ? `Copied ${format}!` : 'Copied!';
|
|
132
|
+
const thf = button.closest('.tooltip-host');
|
|
133
|
+
if (thf) thf.setAttribute('data-tooltip', format ? `Copied ${format}!` : 'Copied!');
|
|
134
|
+
button.setAttribute('aria-label', format ? `Copied ${format}!` : 'Copied!');
|
|
135
|
+
setTimeout(() => {
|
|
136
|
+
if (copyIcon) copyIcon.classList.remove('copy-to-clipboard__icon--hidden');
|
|
137
|
+
if (checkIcon) checkIcon.classList.add('copy-to-clipboard__icon--hidden');
|
|
138
|
+
if (feedback) feedback.textContent = '';
|
|
139
|
+
if (thf) thf.setAttribute('data-tooltip', thf.getAttribute('data-copy-default-tooltip') || defaultTooltip);
|
|
140
|
+
button.setAttribute('aria-label', defaultAriaLabel);
|
|
141
|
+
}, 2000);
|
|
142
|
+
} catch (fallbackErr) {
|
|
143
|
+
if (feedback) feedback.textContent = 'Failed to copy';
|
|
144
|
+
}
|
|
145
|
+
document.body.removeChild(textArea);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
button.addEventListener('click', copyToClipboard);
|
|
149
|
+
button.addEventListener('keydown', (e) => {
|
|
150
|
+
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); copyToClipboard(); }
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|
|
155
|
+
else init();
|
|
156
|
+
})();
|
|
157
|
+
</script>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Tabler Icons - Check
|
|
3
|
+
// Source: https://tabler.io/icons/icon/check
|
|
4
|
+
// License: MIT
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
width?: number;
|
|
8
|
+
height?: number;
|
|
9
|
+
class?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { width = 16, height = 16, class: className = '' } = Astro.props;
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<svg
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
width={width}
|
|
18
|
+
height={height}
|
|
19
|
+
viewBox="0 0 24 24"
|
|
20
|
+
fill="none"
|
|
21
|
+
stroke="currentColor"
|
|
22
|
+
stroke-width="2"
|
|
23
|
+
stroke-linecap="round"
|
|
24
|
+
stroke-linejoin="round"
|
|
25
|
+
class={`icon ${className}`.trim()}
|
|
26
|
+
aria-hidden="true"
|
|
27
|
+
>
|
|
28
|
+
<path d="M20 6L9 17l-5-5" />
|
|
29
|
+
</svg>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Tabler Icons - Copy
|
|
3
|
+
// Source: https://tabler.io/icons/icon/copy
|
|
4
|
+
// License: MIT
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
width?: number;
|
|
8
|
+
height?: number;
|
|
9
|
+
class?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { width = 16, height = 16, class: className = '' } = Astro.props;
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<svg
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
width={width}
|
|
18
|
+
height={height}
|
|
19
|
+
viewBox="0 0 24 24"
|
|
20
|
+
fill="none"
|
|
21
|
+
stroke="currentColor"
|
|
22
|
+
stroke-width="2"
|
|
23
|
+
stroke-linecap="round"
|
|
24
|
+
stroke-linejoin="round"
|
|
25
|
+
class={`icon ${className}`.trim()}
|
|
26
|
+
aria-hidden="true"
|
|
27
|
+
>
|
|
28
|
+
<rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
|
|
29
|
+
<path d="M4 16c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2h8c1.1 0 2 .9 2 2" />
|
|
30
|
+
</svg>
|
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
import Layout from '../layouts/Layout.astro';
|
|
3
|
+
import CopyToClipboard from '../components/rizzo/CopyToClipboard.astro';
|
|
3
4
|
const TITLE = '{{TITLE}}';
|
|
4
5
|
const DOCS_BASE = 'https://rizzo-css.vercel.app';
|
|
6
|
+
const ADD_COMMAND = 'npx rizzo-css add <ComponentName>';
|
|
5
7
|
---
|
|
6
8
|
<Layout title={TITLE}>
|
|
7
|
-
<script is:inline>
|
|
8
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
9
|
-
document.querySelectorAll('[data-copy-command]').forEach(function(btn) {
|
|
10
|
-
btn.addEventListener('click', function() {
|
|
11
|
-
var c = btn.getAttribute('data-copy-command');
|
|
12
|
-
if (c && navigator.clipboard && navigator.clipboard.writeText) {
|
|
13
|
-
navigator.clipboard.writeText(c);
|
|
14
|
-
btn.setAttribute('aria-label', 'Copied');
|
|
15
|
-
setTimeout(function() { btn.setAttribute('aria-label', 'Copy command'); }, 2000);
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
</script>
|
|
21
9
|
<div class="home">
|
|
22
10
|
<div class="home__container">
|
|
23
11
|
<header class="home__hero">
|
|
@@ -75,7 +63,7 @@ const DOCS_BASE = 'https://rizzo-css.vercel.app';
|
|
|
75
63
|
<p class="home__features-intro" style="margin-bottom: var(--spacing-4);">Add any component from the CLI:</p>
|
|
76
64
|
<div class="home__add-command-block">
|
|
77
65
|
<pre><code>npx rizzo-css add <ComponentName></code></pre>
|
|
78
|
-
<
|
|
66
|
+
<CopyToClipboard value={ADD_COMMAND} iconOnly buttonLabel="Copy" format="command" label="Copy command" class="home__add-command-copy" />
|
|
79
67
|
</div>
|
|
80
68
|
</section>
|
|
81
69
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
// Sound effects: play on click/tap when user has enabled (localStorage soundEffects === 'true'). Uses /assets/sfx/click.mp3 (or relative assets/sfx for Vanilla), else Web Audio fallback. Single source for main site (Layout.astro) and all shipped scaffolds (Astro, Svelte, Vanilla); keep behavior in sync. Supports touch (touchend) so mobile plays like desktop.
|
|
1
|
+
// Sound effects: play on click/tap when user has enabled (localStorage soundEffects === 'true'). Uses /assets/sfx/click.mp3 (or relative assets/sfx for Vanilla), then click.wav fallback, else Web Audio fallback. Single source for main site (Layout.astro) and all shipped scaffolds (Astro, Svelte, Vanilla); keep behavior in sync. Includes nav links and logo (a[href], .navbar__link, .navbar__brand-link). Supports touch (touchend) so mobile plays like desktop.
|
|
2
2
|
(function() {
|
|
3
3
|
var SOUND_KEY = 'soundEffects';
|
|
4
4
|
var THROTTLE_MS = 120;
|
|
5
|
-
var clickableSelector = 'a[href], area[href], button, input[type="submit"], input[type="button"], input[type="checkbox"], input[type="radio"], input[type="reset"], select, summary, [role="button"], [role="link"], [role="menuitem"], [role="menuitemradio"], [role="tab"], [role="option"], [role="switch"], .btn, .tabs__tab, .dropdown__trigger, .accordion__trigger, [data-accordion-trigger], .navbar__link, .navbar__brand-link, .pagination__link, .breadcrumb__link, .search__trigger, .theme-switcher__option, .font-switcher__option, .framework-switcher__segment, .modal__close, .alert__close, .copy-btn, [data-copy-btn]';
|
|
5
|
+
var clickableSelector = 'a[href], area[href], button, input[type="submit"], input[type="button"], input[type="checkbox"], input[type="radio"], input[type="reset"], select, summary, [role="button"], [role="link"], [role="menuitem"], [role="menuitemradio"], [role="tab"], [role="option"], [role="switch"], .btn, .tabs__tab, .dropdown__trigger, .accordion__trigger, [data-accordion-trigger], .navbar__link, .navbar__brand-link, .pagination__link, .breadcrumb__link, .search__trigger, .theme-switcher__option, .font-switcher__option, .framework-switcher__segment, .modal__close, .alert__close, .copy-btn, [data-copy-btn], [data-sound-on-click]';
|
|
6
6
|
var audioContext = null;
|
|
7
7
|
var soundBase = '/assets/sfx';
|
|
8
|
-
var soundUrls = [soundBase + '/click.mp3'];
|
|
8
|
+
var soundUrls = [soundBase + '/click.mp3', soundBase + '/click.wav'];
|
|
9
9
|
var cachedAudio = null;
|
|
10
10
|
var soundLoadTried = false;
|
|
11
11
|
var lastPlayedAt = 0;
|
package/scaffold/svelte/theme.ts
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { ALL_THEMES } from './themes';
|
|
6
6
|
|
|
7
|
+
/** Detail payload for the 'rizzo-theme-change' custom event. */
|
|
8
|
+
export interface RizzoThemeChangeDetail {
|
|
9
|
+
themeValue: string;
|
|
10
|
+
effective: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
export const THEME_SYSTEM = 'system';
|
|
8
14
|
export const DEFAULT_THEME_DARK = 'github-dark-classic';
|
|
9
15
|
export const DEFAULT_THEME_LIGHT = 'github-light';
|
|
@@ -33,8 +39,14 @@ export function getResolvedTheme(): string {
|
|
|
33
39
|
return stored;
|
|
34
40
|
}
|
|
35
41
|
|
|
42
|
+
/** Theme display info returned by getThemeInfo. */
|
|
43
|
+
export interface ThemeInfo {
|
|
44
|
+
value: string;
|
|
45
|
+
label: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
36
48
|
/** Get { value, label } for a theme (for UI display). */
|
|
37
|
-
export function getThemeInfo(themeValue: string):
|
|
49
|
+
export function getThemeInfo(themeValue: string): ThemeInfo {
|
|
38
50
|
if (themeValue === THEME_SYSTEM) return { value: THEME_SYSTEM, label: 'System' };
|
|
39
51
|
const entry = ALL_THEMES.find((t) => t.value === themeValue);
|
|
40
52
|
return entry ? { value: entry.value, label: entry.label } : { value: themeValue, label: 'Theme' };
|
|
@@ -60,6 +72,8 @@ export function applyTheme(themeValue: string): void {
|
|
|
60
72
|
}
|
|
61
73
|
// Allow listeners to sync UI (e.g. ThemeSwitcher)
|
|
62
74
|
try {
|
|
63
|
-
window.dispatchEvent(
|
|
75
|
+
window.dispatchEvent(
|
|
76
|
+
new CustomEvent<RizzoThemeChangeDetail>('rizzo-theme-change', { detail: { themeValue, effective } })
|
|
77
|
+
);
|
|
64
78
|
} catch (_) {}
|
|
65
79
|
}
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import CopyToClipboard from '$lib/rizzo/CopyToClipboard.svelte';
|
|
2
3
|
const DOCS_BASE = 'https://rizzo-css.vercel.app';
|
|
3
4
|
const ADD_COMMAND = 'npx rizzo-css add <ComponentName>';
|
|
4
|
-
|
|
5
|
-
async function copyAddCommand() {
|
|
6
|
-
try {
|
|
7
|
-
if (navigator.clipboard?.writeText) {
|
|
8
|
-
await navigator.clipboard.writeText(ADD_COMMAND);
|
|
9
|
-
}
|
|
10
|
-
} catch (_) {}
|
|
11
|
-
}
|
|
12
5
|
</script>
|
|
13
6
|
|
|
14
7
|
<a href="#main-content" class="skip-link">Skip to main content</a>
|
|
@@ -69,7 +62,7 @@
|
|
|
69
62
|
<p class="home__features-intro" style="margin-bottom: var(--spacing-4);">Add any component from the CLI:</p>
|
|
70
63
|
<div class="home__add-command-block">
|
|
71
64
|
<pre><code>npx rizzo-css add <ComponentName></code></pre>
|
|
72
|
-
<
|
|
65
|
+
<CopyToClipboard value={ADD_COMMAND} iconOnly buttonLabel="Copy" format="command" label="Copy command" class="home__add-command-copy" />
|
|
73
66
|
</div>
|
|
74
67
|
</section>
|
|
75
68
|
|
package/scaffold/utils/theme.ts
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { ALL_THEMES } from '../astro/themes';
|
|
6
6
|
|
|
7
|
+
/** Detail payload for the 'rizzo-theme-change' custom event. */
|
|
8
|
+
export interface RizzoThemeChangeDetail {
|
|
9
|
+
themeValue: string;
|
|
10
|
+
effective: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
export const THEME_SYSTEM = 'system';
|
|
8
14
|
export const DEFAULT_THEME_DARK = 'github-dark-classic';
|
|
9
15
|
export const DEFAULT_THEME_LIGHT = 'github-light';
|
|
@@ -33,8 +39,14 @@ export function getResolvedTheme(): string {
|
|
|
33
39
|
return stored;
|
|
34
40
|
}
|
|
35
41
|
|
|
42
|
+
/** Theme display info returned by getThemeInfo. */
|
|
43
|
+
export interface ThemeInfo {
|
|
44
|
+
value: string;
|
|
45
|
+
label: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
36
48
|
/** Get { value, label } for a theme (for UI display). */
|
|
37
|
-
export function getThemeInfo(themeValue: string):
|
|
49
|
+
export function getThemeInfo(themeValue: string): ThemeInfo {
|
|
38
50
|
if (themeValue === THEME_SYSTEM) return { value: THEME_SYSTEM, label: 'System' };
|
|
39
51
|
const entry = ALL_THEMES.find((t) => t.value === themeValue);
|
|
40
52
|
return entry ? { value: entry.value, label: entry.label } : { value: themeValue, label: 'Theme' };
|
|
@@ -60,6 +72,8 @@ export function applyTheme(themeValue: string): void {
|
|
|
60
72
|
}
|
|
61
73
|
// Allow listeners to sync UI (e.g. ThemeSwitcher)
|
|
62
74
|
try {
|
|
63
|
-
window.dispatchEvent(
|
|
75
|
+
window.dispatchEvent(
|
|
76
|
+
new CustomEvent<RizzoThemeChangeDetail>('rizzo-theme-change', { detail: { themeValue, effective } })
|
|
77
|
+
);
|
|
64
78
|
} catch (_) {}
|
|
65
79
|
}
|
|
@@ -27,7 +27,7 @@ If you prefer to load CSS from a CDN instead of the local file, replace the `<li
|
|
|
27
27
|
- `<link rel="stylesheet" href="https://unpkg.com/rizzo-css@latest/dist/rizzo.min.css" />`
|
|
28
28
|
- Or jsDelivr: `https://cdn.jsdelivr.net/npm/rizzo-css@latest/dist/rizzo.min.css`
|
|
29
29
|
|
|
30
|
-
(Replace `@latest` with a specific version, e.g. `@0.0.
|
|
30
|
+
(Replace `@latest` with a specific version, e.g. `@0.0.51`, in production.)
|
|
31
31
|
|
|
32
32
|
The CLI replaces placeholders in `index.html` (e.g. `{{DATA_THEME}}`, `{{TITLE}}`) when you run `rizzo-css init`. The theme selected during init is used on first load when you have no saved preference in the browser.
|
|
33
33
|
|
|
@@ -53,7 +53,7 @@ The CLI replaces placeholders in `index.html` (e.g. `{{DATA_THEME}}`, `{{TITLE}}
|
|
|
53
53
|
- **Navbar** — Mobile menu: `.navbar__toggle` toggles `.navbar__menu`; Escape closes.
|
|
54
54
|
- **Copy to clipboard** — Buttons with `.copy-to-clipboard` and `data-copy-value`, or `[data-copy]` with `value` or `data-copy-value`; click copies text and shows feedback (icons/aria-label). Optional `data-copy-format` for “Copied {format}!”.
|
|
55
55
|
- **Tooltips** — Use `.tooltip-wrapper` with a `.tooltip` child, or `[data-tooltip]` on the trigger; no JS required (CSS :hover and :focus-within).
|
|
56
|
-
- **Sound effects** — When "Play sound on click" is enabled in Settings, a short click sound plays on interactive elements. The script is injected by the CLI when **Core** or when **Settings**/**SoundEffects** are included; sound files are in **`assets/sfx/`** (e.g. `click.mp3`). Off by default; persists as `soundEffects` in localStorage.
|
|
56
|
+
- **Sound effects** — When "Play sound on click" is enabled in Settings, a short click sound plays on interactive elements. The script is injected by the CLI when **Core** or when **Settings**/**SoundEffects** are included; sound files are in **`assets/sfx/`** (e.g. `click.mp3` or `click.wav`). Off by default; persists as `soundEffects` in localStorage.
|
|
57
57
|
|
|
58
58
|
## Commands
|
|
59
59
|
|