fancy-ui-svelte 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/cameleon/FancyProvider.svelte +63 -0
- package/dist/cameleon/FancyProvider.svelte.d.ts +14 -0
- package/dist/cameleon/cameleon.css +27 -0
- package/dist/cameleon/context.d.ts +14 -0
- package/dist/cameleon/context.js +15 -0
- package/dist/cameleon/index.d.ts +23 -0
- package/dist/cameleon/index.js +22 -0
- package/dist/cameleon/primitives/Badge.svelte +23 -0
- package/dist/cameleon/primitives/Badge.svelte.d.ts +12 -0
- package/dist/cameleon/primitives/Button.svelte +60 -0
- package/dist/cameleon/primitives/Button.svelte.d.ts +15 -0
- package/dist/cameleon/primitives/Checkbox.svelte +56 -0
- package/dist/cameleon/primitives/Checkbox.svelte.d.ts +14 -0
- package/dist/cameleon/primitives/Input.svelte +37 -0
- package/dist/cameleon/primitives/Input.svelte.d.ts +13 -0
- package/dist/cameleon/primitives/Radio.svelte +53 -0
- package/dist/cameleon/primitives/Radio.svelte.d.ts +15 -0
- package/dist/cameleon/primitives/Select.svelte +49 -0
- package/dist/cameleon/primitives/Select.svelte.d.ts +14 -0
- package/dist/cameleon/primitives/Slider.svelte +34 -0
- package/dist/cameleon/primitives/Slider.svelte.d.ts +10 -0
- package/dist/cameleon/primitives/Switch.svelte +43 -0
- package/dist/cameleon/primitives/Switch.svelte.d.ts +12 -0
- package/dist/cameleon/primitives/Textarea.svelte +36 -0
- package/dist/cameleon/primitives/Textarea.svelte.d.ts +12 -0
- package/dist/cameleon/primitives/Tooltip.svelte +32 -0
- package/dist/cameleon/primitives/Tooltip.svelte.d.ts +16 -0
- package/dist/cameleon/primitives/index.d.ts +10 -0
- package/dist/cameleon/primitives/index.js +10 -0
- package/dist/cameleon/skins/aurora/aurora.css +41 -0
- package/dist/cameleon/skins/aurora/index.d.ts +3 -0
- package/dist/cameleon/skins/aurora/index.js +12 -0
- package/dist/cameleon/skins/aurora/meta.d.ts +3 -0
- package/dist/cameleon/skins/aurora/meta.js +58 -0
- package/dist/cameleon/skins/aurora/recipes.d.ts +24 -0
- package/dist/cameleon/skins/aurora/recipes.js +163 -0
- package/dist/cameleon/skins/aurora/tokens.d.ts +6 -0
- package/dist/cameleon/skins/aurora/tokens.js +19 -0
- package/dist/cameleon/skins/brutal/brutal.css +35 -0
- package/dist/cameleon/skins/brutal/index.d.ts +3 -0
- package/dist/cameleon/skins/brutal/index.js +31 -0
- package/dist/cameleon/skins/brutal/meta.d.ts +3 -0
- package/dist/cameleon/skins/brutal/meta.js +70 -0
- package/dist/cameleon/skins/brutal/ornaments.d.ts +2 -0
- package/dist/cameleon/skins/brutal/ornaments.js +13 -0
- package/dist/cameleon/skins/brutal/recipes.d.ts +23 -0
- package/dist/cameleon/skins/brutal/recipes.js +147 -0
- package/dist/cameleon/skins/brutal/tokens.d.ts +8 -0
- package/dist/cameleon/skins/brutal/tokens.js +26 -0
- package/dist/cameleon/skins/default.d.ts +2 -0
- package/dist/cameleon/skins/default.js +95 -0
- package/dist/cameleon/skins/glass/glass.css +55 -0
- package/dist/cameleon/skins/glass/index.d.ts +3 -0
- package/dist/cameleon/skins/glass/index.js +12 -0
- package/dist/cameleon/skins/glass/meta.d.ts +3 -0
- package/dist/cameleon/skins/glass/meta.js +60 -0
- package/dist/cameleon/skins/glass/recipes.d.ts +24 -0
- package/dist/cameleon/skins/glass/recipes.js +155 -0
- package/dist/cameleon/skins/glass/tokens.d.ts +5 -0
- package/dist/cameleon/skins/glass/tokens.js +18 -0
- package/dist/cameleon/skins/retro-os/index.d.ts +3 -0
- package/dist/cameleon/skins/retro-os/index.js +20 -0
- package/dist/cameleon/skins/retro-os/kit/AppWindow.svelte +88 -0
- package/dist/cameleon/skins/retro-os/kit/AppWindow.svelte.d.ts +10 -0
- package/dist/cameleon/skins/retro-os/kit/Chip.svelte +43 -0
- package/dist/cameleon/skins/retro-os/kit/Chip.svelte.d.ts +17 -0
- package/dist/cameleon/skins/retro-os/kit/EmptyMediaFrame.svelte +56 -0
- package/dist/cameleon/skins/retro-os/kit/EmptyMediaFrame.svelte.d.ts +10 -0
- package/dist/cameleon/skins/retro-os/kit/HeaderBar.svelte +62 -0
- package/dist/cameleon/skins/retro-os/kit/HeaderBar.svelte.d.ts +15 -0
- package/dist/cameleon/skins/retro-os/kit/IconTile.svelte +44 -0
- package/dist/cameleon/skins/retro-os/kit/IconTile.svelte.d.ts +13 -0
- package/dist/cameleon/skins/retro-os/kit/InlineIndexLabel.svelte +27 -0
- package/dist/cameleon/skins/retro-os/kit/InlineIndexLabel.svelte.d.ts +11 -0
- package/dist/cameleon/skins/retro-os/kit/Led.svelte +29 -0
- package/dist/cameleon/skins/retro-os/kit/Led.svelte.d.ts +9 -0
- package/dist/cameleon/skins/retro-os/kit/NotchedFrame.svelte +83 -0
- package/dist/cameleon/skins/retro-os/kit/NotchedFrame.svelte.d.ts +11 -0
- package/dist/cameleon/skins/retro-os/kit/NumChip.svelte +25 -0
- package/dist/cameleon/skins/retro-os/kit/NumChip.svelte.d.ts +9 -0
- package/dist/cameleon/skins/retro-os/kit/PixelGlyph.svelte +38 -0
- package/dist/cameleon/skins/retro-os/kit/PixelGlyph.svelte.d.ts +13 -0
- package/dist/cameleon/skins/retro-os/kit/PlayBadge.svelte +46 -0
- package/dist/cameleon/skins/retro-os/kit/PlayBadge.svelte.d.ts +7 -0
- package/dist/cameleon/skins/retro-os/kit/RetroButton.svelte +76 -0
- package/dist/cameleon/skins/retro-os/kit/RetroButton.svelte.d.ts +21 -0
- package/dist/cameleon/skins/retro-os/kit/RetroCard.svelte +92 -0
- package/dist/cameleon/skins/retro-os/kit/RetroCard.svelte.d.ts +16 -0
- package/dist/cameleon/skins/retro-os/kit/RetroTag.svelte +35 -0
- package/dist/cameleon/skins/retro-os/kit/RetroTag.svelte.d.ts +13 -0
- package/dist/cameleon/skins/retro-os/kit/SectionWindow.svelte +125 -0
- package/dist/cameleon/skins/retro-os/kit/SectionWindow.svelte.d.ts +23 -0
- package/dist/cameleon/skins/retro-os/kit/StatusPill.svelte +32 -0
- package/dist/cameleon/skins/retro-os/kit/StatusPill.svelte.d.ts +13 -0
- package/dist/cameleon/skins/retro-os/kit/Swatches.svelte +33 -0
- package/dist/cameleon/skins/retro-os/kit/Swatches.svelte.d.ts +9 -0
- package/dist/cameleon/skins/retro-os/kit/VideoFrame.svelte +177 -0
- package/dist/cameleon/skins/retro-os/kit/VideoFrame.svelte.d.ts +20 -0
- package/dist/cameleon/skins/retro-os/kit/accents.d.ts +25 -0
- package/dist/cameleon/skins/retro-os/kit/accents.js +28 -0
- package/dist/cameleon/skins/retro-os/kit/index.d.ts +41 -0
- package/dist/cameleon/skins/retro-os/kit/index.js +41 -0
- package/dist/cameleon/skins/retro-os/kit/kit-windows.test.d.ts +1 -0
- package/dist/cameleon/skins/retro-os/kit/kit-windows.test.js +159 -0
- package/dist/cameleon/skins/retro-os/kit/kit.css +247 -0
- package/dist/cameleon/skins/retro-os/kit/kit.test.d.ts +1 -0
- package/dist/cameleon/skins/retro-os/kit/kit.test.js +123 -0
- package/dist/cameleon/skins/retro-os/meta.d.ts +3 -0
- package/dist/cameleon/skins/retro-os/meta.js +58 -0
- package/dist/cameleon/skins/retro-os/ornaments.d.ts +2 -0
- package/dist/cameleon/skins/retro-os/ornaments.js +17 -0
- package/dist/cameleon/skins/retro-os/recipes.d.ts +35 -0
- package/dist/cameleon/skins/retro-os/recipes.js +160 -0
- package/dist/cameleon/skins/retro-os/retro-os.css +107 -0
- package/dist/cameleon/skins/retro-os/tokens.d.ts +16 -0
- package/dist/cameleon/skins/retro-os/tokens.js +34 -0
- package/dist/cameleon/skins/terminal/index.d.ts +3 -0
- package/dist/cameleon/skins/terminal/index.js +20 -0
- package/dist/cameleon/skins/terminal/meta.d.ts +3 -0
- package/dist/cameleon/skins/terminal/meta.js +67 -0
- package/dist/cameleon/skins/terminal/ornaments.d.ts +2 -0
- package/dist/cameleon/skins/terminal/ornaments.js +11 -0
- package/dist/cameleon/skins/terminal/recipes.d.ts +25 -0
- package/dist/cameleon/skins/terminal/recipes.js +154 -0
- package/dist/cameleon/skins/terminal/terminal.css +52 -0
- package/dist/cameleon/skins/terminal/tokens.d.ts +5 -0
- package/dist/cameleon/skins/terminal/tokens.js +18 -0
- package/dist/cameleon/types.d.ts +132 -0
- package/dist/cameleon/types.js +1 -0
- package/dist/fancy-ui/blur-reveal/BlurReveal.svelte +16 -1
- package/dist/fancy-ui/blur-reveal/BlurReveal.svelte.d.ts +2 -0
- package/dist/fancy-ui/blur-reveal/BlurReveal.test.js +15 -0
- package/dist/fancy-ui/blur-reveal/README.md +22 -11
- package/dist/fancy-ui/button/Button.svelte +8 -0
- package/dist/fancy-ui/button/Button.svelte.d.ts +5 -0
- package/dist/fancy-ui/button/Button.test.js +61 -1
- package/dist/fancy-ui/button/README.md +11 -0
- package/dist/fancy-ui/checkbox/Checkbox.svelte +8 -0
- package/dist/fancy-ui/checkbox/Checkbox.svelte.d.ts +5 -0
- package/dist/fancy-ui/checkbox/Checkbox.test.js +93 -0
- package/dist/fancy-ui/checkbox/CheckboxFieldHarness.test.svelte +3 -2
- package/dist/fancy-ui/checkbox/CheckboxFieldHarness.test.svelte.d.ts +1 -0
- package/dist/fancy-ui/checkbox/README.md +10 -0
- package/dist/fancy-ui/copy-button/CopyButton.svelte +13 -0
- package/dist/fancy-ui/copy-button/CopyButton.svelte.d.ts +5 -0
- package/dist/fancy-ui/copy-button/CopyButton.test.js +78 -0
- package/dist/fancy-ui/copy-button/README.md +25 -14
- package/dist/fancy-ui/dropdown-menu/DropdownMenu.svelte +18 -3
- package/dist/fancy-ui/dropdown-menu/DropdownMenu.svelte.d.ts +5 -0
- package/dist/fancy-ui/dropdown-menu/DropdownMenu.test.js +182 -0
- package/dist/fancy-ui/dropdown-menu/DropdownMenuContent.svelte +3 -0
- package/dist/fancy-ui/dropdown-menu/DropdownMenuHarness.test.svelte +3 -1
- package/dist/fancy-ui/dropdown-menu/DropdownMenuHarness.test.svelte.d.ts +1 -0
- package/dist/fancy-ui/dropdown-menu/DropdownMenuItem.svelte +6 -1
- package/dist/fancy-ui/dropdown-menu/DropdownMenuSub.svelte +10 -2
- package/dist/fancy-ui/dropdown-menu/DropdownMenuSubContent.svelte +6 -0
- package/dist/fancy-ui/dropdown-menu/README.md +26 -0
- package/dist/fancy-ui/dropdown-menu/index.d.ts +1 -1
- package/dist/fancy-ui/dropdown-menu/types.d.ts +30 -7
- package/dist/fancy-ui/image-trail-cursor/ImageTrailCursor.test.js +17 -0
- package/dist/fancy-ui/image-trail-cursor/README.md +20 -18
- package/dist/fancy-ui/image-trail-cursor/trail-variants.d.ts +6 -1
- package/dist/fancy-ui/image-trail-cursor/trail-variants.js +33 -0
- package/dist/fancy-ui/image-trail-cursor/trail-variants.test.d.ts +1 -0
- package/dist/fancy-ui/image-trail-cursor/trail-variants.test.js +14 -0
- package/dist/fancy-ui/index.d.ts +1 -0
- package/dist/fancy-ui/index.js +2 -0
- package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.svelte +10 -3
- package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.svelte.d.ts +4 -0
- package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.test.js +37 -1
- package/dist/fancy-ui/interactive-grid-pattern/README.md +20 -9
- package/dist/fancy-ui/line-hover-link/LineHoverLink.svelte +18 -1
- package/dist/fancy-ui/line-hover-link/LineHoverLink.svelte.d.ts +2 -1
- package/dist/fancy-ui/line-hover-link/LineHoverLink.test.js +12 -0
- package/dist/fancy-ui/line-hover-link/README.md +3 -2
- package/dist/fancy-ui/liquid-glass/README.md +4 -0
- package/dist/fancy-ui/logo-cloud/README.md +47 -14
- package/dist/fancy-ui/logo-cloud/StaticLogoCloud.svelte +43 -6
- package/dist/fancy-ui/logo-cloud/StaticLogoCloud.svelte.d.ts +18 -0
- package/dist/fancy-ui/logo-cloud/StaticLogoCloud.test.d.ts +1 -0
- package/dist/fancy-ui/logo-cloud/StaticLogoCloud.test.js +57 -0
- package/dist/fancy-ui/logo-cloud/index.d.ts +2 -2
- package/dist/fancy-ui/radio-group/README.md +9 -0
- package/dist/fancy-ui/radio-group/RadioGroup.svelte +9 -0
- package/dist/fancy-ui/radio-group/RadioGroup.svelte.d.ts +5 -0
- package/dist/fancy-ui/radio-group/RadioGroup.test.js +68 -0
- package/dist/fancy-ui/radio-group/RadioGroupHarness.test.svelte +13 -1
- package/dist/fancy-ui/radio-group/RadioGroupHarness.test.svelte.d.ts +1 -0
- package/dist/fancy-ui/registry.js +176 -4
- package/dist/fancy-ui/select/README.md +19 -0
- package/dist/fancy-ui/select/Select.svelte +33 -11
- package/dist/fancy-ui/select/Select.svelte.d.ts +5 -0
- package/dist/fancy-ui/select/Select.test.js +114 -0
- package/dist/fancy-ui/sound/README.md +288 -0
- package/dist/fancy-ui/sound/SoundToggle.svelte +185 -0
- package/dist/fancy-ui/sound/SoundToggle.svelte.d.ts +27 -0
- package/dist/fancy-ui/sound/SoundToggle.test.d.ts +1 -0
- package/dist/fancy-ui/sound/SoundToggle.test.js +251 -0
- package/dist/fancy-ui/sound/SoundToggleHarness.test.svelte +18 -0
- package/dist/fancy-ui/sound/SoundToggleHarness.test.svelte.d.ts +3 -0
- package/dist/fancy-ui/sound/engine.d.ts +67 -0
- package/dist/fancy-ui/sound/engine.js +440 -0
- package/dist/fancy-ui/sound/engine.test.d.ts +1 -0
- package/dist/fancy-ui/sound/engine.test.js +638 -0
- package/dist/fancy-ui/sound/index.d.ts +7 -0
- package/dist/fancy-ui/sound/index.js +7 -0
- package/dist/fancy-ui/sound/sound-feedback.d.ts +50 -0
- package/dist/fancy-ui/sound/sound-feedback.js +144 -0
- package/dist/fancy-ui/sound/sound-feedback.test.d.ts +1 -0
- package/dist/fancy-ui/sound/sound-feedback.test.js +272 -0
- package/dist/fancy-ui/sound/sound.barrel.test.d.ts +1 -0
- package/dist/fancy-ui/sound/sound.barrel.test.js +161 -0
- package/dist/fancy-ui/sound/sound.integration.test.d.ts +1 -0
- package/dist/fancy-ui/sound/sound.integration.test.js +541 -0
- package/dist/fancy-ui/sound/sound.ssr.test.d.ts +1 -0
- package/dist/fancy-ui/sound/sound.ssr.test.js +128 -0
- package/dist/fancy-ui/sound/sound.svelte.d.ts +54 -0
- package/dist/fancy-ui/sound/sound.svelte.js +349 -0
- package/dist/fancy-ui/sound/sound.test.d.ts +1 -0
- package/dist/fancy-ui/sound/sound.test.js +318 -0
- package/dist/fancy-ui/sound/themes.d.ts +19 -0
- package/dist/fancy-ui/sound/themes.js +367 -0
- package/dist/fancy-ui/sound/themes.test.d.ts +1 -0
- package/dist/fancy-ui/sound/themes.test.js +188 -0
- package/dist/fancy-ui/sound/types.d.ts +125 -0
- package/dist/fancy-ui/sound/types.js +59 -0
- package/dist/fancy-ui/sound/web-audio-mock.d.ts +144 -0
- package/dist/fancy-ui/sound/web-audio-mock.js +274 -0
- package/dist/fancy-ui/switch/README.md +9 -0
- package/dist/fancy-ui/switch/Switch.svelte +8 -0
- package/dist/fancy-ui/switch/Switch.svelte.d.ts +5 -0
- package/dist/fancy-ui/switch/Switch.test.js +81 -0
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Beautiful animation and UI components for **Svelte 5**.
|
|
|
9
9
|

|
|
10
10
|

|
|
11
11
|

|
|
12
|
-

|
|
13
13
|

|
|
14
14
|
|
|
15
15
|
<p align="center">
|
|
@@ -36,8 +36,9 @@ Beautiful animation and UI components for **Svelte 5**.
|
|
|
36
36
|
- **Svelte 5 Runes** — Built with `$state`, `$derived`, `$effect`, and `$props`
|
|
37
37
|
- **Tailwind CSS 4** — Utility-first styling with theme tokens
|
|
38
38
|
- **TypeScript** — Fully typed props and events
|
|
39
|
-
- **
|
|
39
|
+
- **133 Components** — Core primitives (forms, navigation, overlays) alongside buttons, text animations, backgrounds and effects
|
|
40
40
|
- **Dark Mode** — All components support light and dark themes
|
|
41
|
+
- **Opt-in Sound** — Eleven synthesised interface cues, a `SoundToggle` switch and a `soundFeedback` action; silent until the user turns it on
|
|
41
42
|
- **Tested** — 2,900+ unit tests with Vitest and Testing Library
|
|
42
43
|
|
|
43
44
|
## Quick Start
|
|
@@ -151,7 +152,7 @@ Component tests are colocated with their component (see `RainbowButton.test.ts`
|
|
|
151
152
|
|
|
152
153
|
## Contributing
|
|
153
154
|
|
|
154
|
-
Contributions are welcome!
|
|
155
|
+
Contributions are welcome! 133 components and counting — PRs for new components, bug fixes, and improvements are appreciated.
|
|
155
156
|
|
|
156
157
|
### Adding a new component
|
|
157
158
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export interface FancyProviderProps {
|
|
3
|
+
/** The active skin. Changing it re-flows the whole subtree live. */
|
|
4
|
+
skin: Skin;
|
|
5
|
+
/** Scope `.dark` to this subtree for skins whose colorScheme is "dark". */
|
|
6
|
+
manageColorScheme?: boolean;
|
|
7
|
+
class?: string;
|
|
8
|
+
children?: Snippet;
|
|
9
|
+
}
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<script lang="ts">
|
|
13
|
+
import type { Snippet } from "svelte";
|
|
14
|
+
import { browser } from "$app/environment";
|
|
15
|
+
import { cn } from "../utils.js";
|
|
16
|
+
import type { Skin } from "./types.js";
|
|
17
|
+
import { setSkinContext } from "./context.js";
|
|
18
|
+
import "./cameleon.css";
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
skin,
|
|
22
|
+
manageColorScheme = false,
|
|
23
|
+
class: className = "",
|
|
24
|
+
children,
|
|
25
|
+
}: FancyProviderProps = $props();
|
|
26
|
+
|
|
27
|
+
// Getter, not a plain value — this is what makes a live skin switch reactive.
|
|
28
|
+
setSkinContext({
|
|
29
|
+
get skin() {
|
|
30
|
+
return skin;
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Skin tokens as scoped inline CSS variables. Overriding these var names on
|
|
35
|
+
// this element re-flows every utility that reads them, for THIS subtree only.
|
|
36
|
+
// The provider never touches <html>, so it can't fight the global theme store.
|
|
37
|
+
const styleVars = $derived(
|
|
38
|
+
Object.entries(skin.tokens)
|
|
39
|
+
.map(([k, v]) => `${k}:${v}`)
|
|
40
|
+
.join(";")
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// Inject skin webfonts once (deduped by id), client-only so SSR stays clean.
|
|
44
|
+
$effect(() => {
|
|
45
|
+
if (!browser || !skin.fonts) return;
|
|
46
|
+
for (const font of skin.fonts) {
|
|
47
|
+
if (document.getElementById(font.id)) continue;
|
|
48
|
+
const link = document.createElement("link");
|
|
49
|
+
link.id = font.id;
|
|
50
|
+
link.rel = "stylesheet";
|
|
51
|
+
link.href = font.href;
|
|
52
|
+
document.head.appendChild(link);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<div
|
|
58
|
+
data-skin={skin.name}
|
|
59
|
+
class={cn("cameleon-root", manageColorScheme && skin.colorScheme === "dark" && "dark", className)}
|
|
60
|
+
style={styleVars}
|
|
61
|
+
>
|
|
62
|
+
{@render children?.()}
|
|
63
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface FancyProviderProps {
|
|
2
|
+
/** The active skin. Changing it re-flows the whole subtree live. */
|
|
3
|
+
skin: Skin;
|
|
4
|
+
/** Scope `.dark` to this subtree for skins whose colorScheme is "dark". */
|
|
5
|
+
manageColorScheme?: boolean;
|
|
6
|
+
class?: string;
|
|
7
|
+
children?: Snippet;
|
|
8
|
+
}
|
|
9
|
+
import type { Snippet } from "svelte";
|
|
10
|
+
import type { Skin } from "./types.js";
|
|
11
|
+
import "./cameleon.css";
|
|
12
|
+
declare const FancyProvider: import("svelte").Component<FancyProviderProps, {}, "">;
|
|
13
|
+
type FancyProvider = ReturnType<typeof FancyProvider>;
|
|
14
|
+
export default FancyProvider;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base styles for the Cameleon provider root. The skin's tokens are set as
|
|
3
|
+
* inline CSS variables on the same element; these rules consume them so the
|
|
4
|
+
* whole "world" (page background, text color, base font) changes per skin.
|
|
5
|
+
*/
|
|
6
|
+
.cameleon-root {
|
|
7
|
+
background: var(--skin-page-bg, transparent);
|
|
8
|
+
color: var(--skin-page-fg, inherit);
|
|
9
|
+
font-family: var(--skin-font-sans, inherit);
|
|
10
|
+
-webkit-font-smoothing: antialiased;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@media (prefers-reduced-motion: reduce) {
|
|
14
|
+
.cameleon-root * {
|
|
15
|
+
transition-duration: 0.01ms !important;
|
|
16
|
+
animation-duration: 0.01ms !important;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Skin-agnostic error affordance for the native range slider: the per-skin
|
|
21
|
+
.cam-range CSS styles the track/thumb but not the invalid state, so give
|
|
22
|
+
<Slider error> a consistent red outline driven by the skin's red token. */
|
|
23
|
+
.cam-range[aria-invalid="true"] {
|
|
24
|
+
outline: 2px solid var(--skin-red, #e5372b);
|
|
25
|
+
outline-offset: 3px;
|
|
26
|
+
border-radius: 2px;
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Skin } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The context value is a GETTER object, not the skin itself. This is what makes
|
|
4
|
+
* a live skin switch reactive: consumers read `ctx.skin` inside a `$derived`, so
|
|
5
|
+
* changing the provider's `skin` prop re-runs their recipe resolution. (Same
|
|
6
|
+
* pattern as src/lib/fancy-ui/dock/Dock.svelte and card-3d — a plain value would
|
|
7
|
+
* be captured once and never update.)
|
|
8
|
+
*/
|
|
9
|
+
export interface SkinContext {
|
|
10
|
+
readonly skin: Skin;
|
|
11
|
+
}
|
|
12
|
+
export declare function setSkinContext(ctx: SkinContext): void;
|
|
13
|
+
/** Read the active skin. Falls back to the default skin with no provider. */
|
|
14
|
+
export declare function useSkin(): SkinContext;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getContext, setContext } from "svelte";
|
|
2
|
+
import { defaultSkin } from "./skins/default.js";
|
|
3
|
+
const SKIN_KEY = Symbol("cameleon-skin");
|
|
4
|
+
export function setSkinContext(ctx) {
|
|
5
|
+
setContext(SKIN_KEY, ctx);
|
|
6
|
+
}
|
|
7
|
+
const FALLBACK = {
|
|
8
|
+
get skin() {
|
|
9
|
+
return defaultSkin;
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
/** Read the active skin. Falls back to the default skin with no provider. */
|
|
13
|
+
export function useSkin() {
|
|
14
|
+
return getContext(SKIN_KEY) ?? FALLBACK;
|
|
15
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cameleon Engine — multi-skin UI primitives for fancy-ui.
|
|
3
|
+
*
|
|
4
|
+
* Same component API, radically different art directions ("skins"): each skin
|
|
5
|
+
* carries tokens (CSS custom properties), recipes (pure functions returning
|
|
6
|
+
* class strings per primitive), optional ornaments and per-skin CSS.
|
|
7
|
+
*
|
|
8
|
+
* Published as `fancy-ui-svelte/cameleon` (with the retro-os component kit at
|
|
9
|
+
* `fancy-ui-svelte/cameleon/retro-kit`). Consumers wrap a subtree:
|
|
10
|
+
*
|
|
11
|
+
* import { FancyProvider, Button, brutalSkin } from "fancy-ui-svelte/cameleon";
|
|
12
|
+
* <FancyProvider skin={brutalSkin}> ... </FancyProvider>
|
|
13
|
+
*/
|
|
14
|
+
export { default as FancyProvider, type FancyProviderProps } from "./FancyProvider.svelte";
|
|
15
|
+
export { useSkin, setSkinContext, type SkinContext } from "./context.js";
|
|
16
|
+
export type { Skin, SkinRecipes, SkinOrnaments, SkinFont, SkinMeta, RecipeFn, RecipeArgs, RecipeResult, PartState, } from "./types.js";
|
|
17
|
+
export * from "./primitives/index.js";
|
|
18
|
+
export { defaultSkin } from "./skins/default.js";
|
|
19
|
+
export { auroraSkin } from "./skins/aurora/index.js";
|
|
20
|
+
export { brutalSkin } from "./skins/brutal/index.js";
|
|
21
|
+
export { glassSkin } from "./skins/glass/index.js";
|
|
22
|
+
export { terminalSkin } from "./skins/terminal/index.js";
|
|
23
|
+
export { retroOsSkin } from "./skins/retro-os/index.js";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cameleon Engine — multi-skin UI primitives for fancy-ui.
|
|
3
|
+
*
|
|
4
|
+
* Same component API, radically different art directions ("skins"): each skin
|
|
5
|
+
* carries tokens (CSS custom properties), recipes (pure functions returning
|
|
6
|
+
* class strings per primitive), optional ornaments and per-skin CSS.
|
|
7
|
+
*
|
|
8
|
+
* Published as `fancy-ui-svelte/cameleon` (with the retro-os component kit at
|
|
9
|
+
* `fancy-ui-svelte/cameleon/retro-kit`). Consumers wrap a subtree:
|
|
10
|
+
*
|
|
11
|
+
* import { FancyProvider, Button, brutalSkin } from "fancy-ui-svelte/cameleon";
|
|
12
|
+
* <FancyProvider skin={brutalSkin}> ... </FancyProvider>
|
|
13
|
+
*/
|
|
14
|
+
export { default as FancyProvider } from "./FancyProvider.svelte";
|
|
15
|
+
export { useSkin, setSkinContext } from "./context.js";
|
|
16
|
+
export * from "./primitives/index.js";
|
|
17
|
+
export { defaultSkin } from "./skins/default.js";
|
|
18
|
+
export { auroraSkin } from "./skins/aurora/index.js";
|
|
19
|
+
export { brutalSkin } from "./skins/brutal/index.js";
|
|
20
|
+
export { glassSkin } from "./skins/glass/index.js";
|
|
21
|
+
export { terminalSkin } from "./skins/terminal/index.js";
|
|
22
|
+
export { retroOsSkin } from "./skins/retro-os/index.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { PartState } from "../types.js";
|
|
4
|
+
export interface BadgeProps {
|
|
5
|
+
variant?: "default" | "solid" | "blue" | "red" | "yellow" | "green" | "purple";
|
|
6
|
+
/** Force a visual state for the /skins state matrix. */
|
|
7
|
+
demoState?: PartState;
|
|
8
|
+
class?: string;
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
}
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<script lang="ts">
|
|
14
|
+
import { cn } from "../../utils.js";
|
|
15
|
+
import { useSkin } from "../context.js";
|
|
16
|
+
|
|
17
|
+
let { variant = "default", demoState, class: className, children }: BadgeProps = $props();
|
|
18
|
+
|
|
19
|
+
const ctx = useSkin();
|
|
20
|
+
const parts = $derived(ctx.skin.recipes.badge({ variant, state: demoState }));
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<span class={cn(parts.root, className)}>{@render children?.()}</span>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { PartState } from "../types.js";
|
|
3
|
+
export interface BadgeProps {
|
|
4
|
+
variant?: "default" | "solid" | "blue" | "red" | "yellow" | "green" | "purple";
|
|
5
|
+
/** Force a visual state for the /skins state matrix. */
|
|
6
|
+
demoState?: PartState;
|
|
7
|
+
class?: string;
|
|
8
|
+
children?: Snippet;
|
|
9
|
+
}
|
|
10
|
+
declare const Badge: import("svelte").Component<BadgeProps, {}, "">;
|
|
11
|
+
type Badge = ReturnType<typeof Badge>;
|
|
12
|
+
export default Badge;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
4
|
+
|
|
5
|
+
export interface ButtonProps extends Omit<HTMLButtonAttributes, "class"> {
|
|
6
|
+
variant?: "primary" | "secondary" | "destructive";
|
|
7
|
+
size?: "sm" | "md" | "lg";
|
|
8
|
+
loading?: boolean;
|
|
9
|
+
/** Force a visual state for the /skins state matrix (non-interactive). */
|
|
10
|
+
demoState?: "hover" | "active" | "focus";
|
|
11
|
+
class?: string;
|
|
12
|
+
children?: Snippet;
|
|
13
|
+
ref?: HTMLButtonElement | null;
|
|
14
|
+
}
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<script lang="ts">
|
|
18
|
+
import { cn } from "../../utils.js";
|
|
19
|
+
import { useSkin } from "../context.js";
|
|
20
|
+
import type { RecipeArgs } from "../types.js";
|
|
21
|
+
|
|
22
|
+
let {
|
|
23
|
+
variant = "primary",
|
|
24
|
+
size = "md",
|
|
25
|
+
loading = false,
|
|
26
|
+
disabled = false,
|
|
27
|
+
type = "button",
|
|
28
|
+
demoState,
|
|
29
|
+
class: className,
|
|
30
|
+
children,
|
|
31
|
+
ref = $bindable(null),
|
|
32
|
+
...rest
|
|
33
|
+
}: ButtonProps = $props();
|
|
34
|
+
|
|
35
|
+
const ctx = useSkin();
|
|
36
|
+
const args = $derived<RecipeArgs>({
|
|
37
|
+
variant,
|
|
38
|
+
size,
|
|
39
|
+
state: demoState ?? (loading ? "loading" : disabled ? "disabled" : "default"),
|
|
40
|
+
});
|
|
41
|
+
// Re-runs whenever the active skin changes → live art-direction swap.
|
|
42
|
+
const parts = $derived(ctx.skin.recipes.button(args));
|
|
43
|
+
const trailing = $derived(ctx.skin.ornaments?.buttonTrailing);
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<button
|
|
47
|
+
bind:this={ref}
|
|
48
|
+
{type}
|
|
49
|
+
class={cn("cam-btn", parts.root, className)}
|
|
50
|
+
disabled={disabled || loading}
|
|
51
|
+
data-variant={variant}
|
|
52
|
+
{...rest}
|
|
53
|
+
>
|
|
54
|
+
{#if parts.label !== undefined}
|
|
55
|
+
<span class={parts.label}>{@render children?.()}</span>
|
|
56
|
+
{:else}
|
|
57
|
+
{@render children?.()}
|
|
58
|
+
{/if}
|
|
59
|
+
{#if trailing}{@render trailing(args)}{/if}
|
|
60
|
+
</button>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
3
|
+
export interface ButtonProps extends Omit<HTMLButtonAttributes, "class"> {
|
|
4
|
+
variant?: "primary" | "secondary" | "destructive";
|
|
5
|
+
size?: "sm" | "md" | "lg";
|
|
6
|
+
loading?: boolean;
|
|
7
|
+
/** Force a visual state for the /skins state matrix (non-interactive). */
|
|
8
|
+
demoState?: "hover" | "active" | "focus";
|
|
9
|
+
class?: string;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
ref?: HTMLButtonElement | null;
|
|
12
|
+
}
|
|
13
|
+
declare const Button: import("svelte").Component<ButtonProps, {}, "ref">;
|
|
14
|
+
type Button = ReturnType<typeof Button>;
|
|
15
|
+
export default Button;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
4
|
+
import type { PartState } from "../types.js";
|
|
5
|
+
export interface CheckboxProps extends Omit<HTMLInputAttributes, "class" | "type"> {
|
|
6
|
+
checked?: boolean;
|
|
7
|
+
error?: boolean;
|
|
8
|
+
demoState?: PartState;
|
|
9
|
+
class?: string;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
ref?: HTMLInputElement | null;
|
|
12
|
+
}
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<script lang="ts">
|
|
16
|
+
import { cn } from "../../utils.js";
|
|
17
|
+
import { useSkin } from "../context.js";
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
checked = $bindable(false),
|
|
21
|
+
error = false,
|
|
22
|
+
demoState,
|
|
23
|
+
class: className,
|
|
24
|
+
children,
|
|
25
|
+
ref = $bindable(null),
|
|
26
|
+
...rest
|
|
27
|
+
}: CheckboxProps = $props();
|
|
28
|
+
|
|
29
|
+
const ctx = useSkin();
|
|
30
|
+
const parts = $derived(ctx.skin.recipes.checkbox({ state: demoState }));
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<label class={cn(parts.root, className)}>
|
|
34
|
+
<input
|
|
35
|
+
type="checkbox"
|
|
36
|
+
class="peer sr-only"
|
|
37
|
+
bind:this={ref}
|
|
38
|
+
bind:checked
|
|
39
|
+
aria-invalid={error}
|
|
40
|
+
{...rest}
|
|
41
|
+
/>
|
|
42
|
+
<span class={parts.box}>
|
|
43
|
+
<svg
|
|
44
|
+
width="12"
|
|
45
|
+
height="12"
|
|
46
|
+
viewBox="0 0 24 24"
|
|
47
|
+
fill="none"
|
|
48
|
+
stroke="currentColor"
|
|
49
|
+
stroke-width="3.5"
|
|
50
|
+
aria-hidden="true"
|
|
51
|
+
>
|
|
52
|
+
<path d="M5 13l4 4L19 7" stroke-linecap="round" stroke-linejoin="round" />
|
|
53
|
+
</svg>
|
|
54
|
+
</span>
|
|
55
|
+
{#if children}{@render children()}{/if}
|
|
56
|
+
</label>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
3
|
+
import type { PartState } from "../types.js";
|
|
4
|
+
export interface CheckboxProps extends Omit<HTMLInputAttributes, "class" | "type"> {
|
|
5
|
+
checked?: boolean;
|
|
6
|
+
error?: boolean;
|
|
7
|
+
demoState?: PartState;
|
|
8
|
+
class?: string;
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
ref?: HTMLInputElement | null;
|
|
11
|
+
}
|
|
12
|
+
declare const Checkbox: import("svelte").Component<CheckboxProps, {}, "ref" | "checked">;
|
|
13
|
+
type Checkbox = ReturnType<typeof Checkbox>;
|
|
14
|
+
export default Checkbox;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
3
|
+
import type { PartState } from "../types.js";
|
|
4
|
+
export interface InputProps extends Omit<HTMLInputAttributes, "class"> {
|
|
5
|
+
error?: boolean;
|
|
6
|
+
/** Force a visual state for the /skins state matrix. */
|
|
7
|
+
demoState?: PartState;
|
|
8
|
+
class?: string;
|
|
9
|
+
value?: string;
|
|
10
|
+
ref?: HTMLInputElement | null;
|
|
11
|
+
}
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { cn } from "../../utils.js";
|
|
16
|
+
import { useSkin } from "../context.js";
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
error = false,
|
|
20
|
+
demoState,
|
|
21
|
+
class: className,
|
|
22
|
+
value = $bindable(""),
|
|
23
|
+
ref = $bindable(null),
|
|
24
|
+
...rest
|
|
25
|
+
}: InputProps = $props();
|
|
26
|
+
|
|
27
|
+
const ctx = useSkin();
|
|
28
|
+
const parts = $derived(ctx.skin.recipes.input({ state: demoState }));
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<input
|
|
32
|
+
bind:this={ref}
|
|
33
|
+
bind:value
|
|
34
|
+
class={cn(parts.root, className)}
|
|
35
|
+
aria-invalid={error}
|
|
36
|
+
{...rest}
|
|
37
|
+
/>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
2
|
+
import type { PartState } from "../types.js";
|
|
3
|
+
export interface InputProps extends Omit<HTMLInputAttributes, "class"> {
|
|
4
|
+
error?: boolean;
|
|
5
|
+
/** Force a visual state for the /skins state matrix. */
|
|
6
|
+
demoState?: PartState;
|
|
7
|
+
class?: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
ref?: HTMLInputElement | null;
|
|
10
|
+
}
|
|
11
|
+
declare const Input: import("svelte").Component<InputProps, {}, "ref" | "value">;
|
|
12
|
+
type Input = ReturnType<typeof Input>;
|
|
13
|
+
export default Input;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
4
|
+
import type { PartState } from "../types.js";
|
|
5
|
+
export interface RadioProps extends Omit<HTMLInputAttributes, "class" | "type"> {
|
|
6
|
+
group?: string;
|
|
7
|
+
value?: string;
|
|
8
|
+
error?: boolean;
|
|
9
|
+
demoState?: PartState;
|
|
10
|
+
class?: string;
|
|
11
|
+
children?: Snippet;
|
|
12
|
+
ref?: HTMLInputElement | null;
|
|
13
|
+
}
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<script lang="ts">
|
|
17
|
+
import { cn } from "../../utils.js";
|
|
18
|
+
import { useSkin } from "../context.js";
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
group = $bindable(),
|
|
22
|
+
value,
|
|
23
|
+
name,
|
|
24
|
+
error = false,
|
|
25
|
+
demoState,
|
|
26
|
+
class: className,
|
|
27
|
+
children,
|
|
28
|
+
ref = $bindable(null),
|
|
29
|
+
...rest
|
|
30
|
+
}: RadioProps = $props();
|
|
31
|
+
|
|
32
|
+
const ctx = useSkin();
|
|
33
|
+
const parts = $derived(ctx.skin.recipes.radio({ state: demoState }));
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<label class={cn(parts.root, className)}>
|
|
37
|
+
<!-- radio invalidity belongs on the group, not the input; drive the demo
|
|
38
|
+
error visual off a data-attribute so we don't misuse aria-invalid.
|
|
39
|
+
name defaults to the group so same-group radios stay mutually exclusive
|
|
40
|
+
natively even when the parent doesn't share a bound group variable. -->
|
|
41
|
+
<input
|
|
42
|
+
type="radio"
|
|
43
|
+
class="peer sr-only"
|
|
44
|
+
bind:this={ref}
|
|
45
|
+
bind:group
|
|
46
|
+
name={name ?? group}
|
|
47
|
+
{value}
|
|
48
|
+
data-invalid={error ? "true" : undefined}
|
|
49
|
+
{...rest}
|
|
50
|
+
/>
|
|
51
|
+
<span class={parts.box}></span>
|
|
52
|
+
{#if children}{@render children()}{/if}
|
|
53
|
+
</label>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
3
|
+
import type { PartState } from "../types.js";
|
|
4
|
+
export interface RadioProps extends Omit<HTMLInputAttributes, "class" | "type"> {
|
|
5
|
+
group?: string;
|
|
6
|
+
value?: string;
|
|
7
|
+
error?: boolean;
|
|
8
|
+
demoState?: PartState;
|
|
9
|
+
class?: string;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
ref?: HTMLInputElement | null;
|
|
12
|
+
}
|
|
13
|
+
declare const Radio: import("svelte").Component<RadioProps, {}, "ref" | "group">;
|
|
14
|
+
type Radio = ReturnType<typeof Radio>;
|
|
15
|
+
export default Radio;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLSelectAttributes } from "svelte/elements";
|
|
4
|
+
import type { PartState } from "../types.js";
|
|
5
|
+
export interface SelectProps extends Omit<HTMLSelectAttributes, "class"> {
|
|
6
|
+
error?: boolean;
|
|
7
|
+
demoState?: PartState;
|
|
8
|
+
class?: string;
|
|
9
|
+
value?: string;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
ref?: HTMLSelectElement | null;
|
|
12
|
+
}
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<script lang="ts">
|
|
16
|
+
import { cn } from "../../utils.js";
|
|
17
|
+
import { useSkin } from "../context.js";
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
error = false,
|
|
21
|
+
demoState,
|
|
22
|
+
class: className,
|
|
23
|
+
value = $bindable(""),
|
|
24
|
+
children,
|
|
25
|
+
ref = $bindable(null),
|
|
26
|
+
...rest
|
|
27
|
+
}: SelectProps = $props();
|
|
28
|
+
|
|
29
|
+
const ctx = useSkin();
|
|
30
|
+
const parts = $derived(ctx.skin.recipes.select({ state: demoState }));
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<div class={cn(parts.root, className)}>
|
|
34
|
+
<select bind:this={ref} bind:value class={parts.field} aria-invalid={error} {...rest}>
|
|
35
|
+
{@render children?.()}
|
|
36
|
+
</select>
|
|
37
|
+
<span class={parts.chevron} aria-hidden="true">
|
|
38
|
+
<svg
|
|
39
|
+
width="14"
|
|
40
|
+
height="14"
|
|
41
|
+
viewBox="0 0 24 24"
|
|
42
|
+
fill="none"
|
|
43
|
+
stroke="currentColor"
|
|
44
|
+
stroke-width="2.5"
|
|
45
|
+
>
|
|
46
|
+
<path d="M6 9l6 6 6-6" stroke-linecap="round" stroke-linejoin="round" />
|
|
47
|
+
</svg>
|
|
48
|
+
</span>
|
|
49
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLSelectAttributes } from "svelte/elements";
|
|
3
|
+
import type { PartState } from "../types.js";
|
|
4
|
+
export interface SelectProps extends Omit<HTMLSelectAttributes, "class"> {
|
|
5
|
+
error?: boolean;
|
|
6
|
+
demoState?: PartState;
|
|
7
|
+
class?: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
ref?: HTMLSelectElement | null;
|
|
11
|
+
}
|
|
12
|
+
declare const Select: import("svelte").Component<SelectProps, {}, "ref" | "value">;
|
|
13
|
+
type Select = ReturnType<typeof Select>;
|
|
14
|
+
export default Select;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
3
|
+
export interface SliderProps extends Omit<HTMLInputAttributes, "class" | "type"> {
|
|
4
|
+
error?: boolean;
|
|
5
|
+
class?: string;
|
|
6
|
+
value?: number;
|
|
7
|
+
ref?: HTMLInputElement | null;
|
|
8
|
+
}
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<script lang="ts">
|
|
12
|
+
import { cn } from "../../utils.js";
|
|
13
|
+
import { useSkin } from "../context.js";
|
|
14
|
+
|
|
15
|
+
let {
|
|
16
|
+
error = false,
|
|
17
|
+
class: className,
|
|
18
|
+
value = $bindable(50),
|
|
19
|
+
ref = $bindable(null),
|
|
20
|
+
...rest
|
|
21
|
+
}: SliderProps = $props();
|
|
22
|
+
|
|
23
|
+
const ctx = useSkin();
|
|
24
|
+
const parts = $derived(ctx.skin.recipes.slider({ state: error ? "error" : undefined }));
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<input
|
|
28
|
+
type="range"
|
|
29
|
+
bind:this={ref}
|
|
30
|
+
bind:value
|
|
31
|
+
class={cn(parts.root, className)}
|
|
32
|
+
aria-invalid={error || undefined}
|
|
33
|
+
{...rest}
|
|
34
|
+
/>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
2
|
+
export interface SliderProps extends Omit<HTMLInputAttributes, "class" | "type"> {
|
|
3
|
+
error?: boolean;
|
|
4
|
+
class?: string;
|
|
5
|
+
value?: number;
|
|
6
|
+
ref?: HTMLInputElement | null;
|
|
7
|
+
}
|
|
8
|
+
declare const Slider: import("svelte").Component<SliderProps, {}, "ref" | "value">;
|
|
9
|
+
type Slider = ReturnType<typeof Slider>;
|
|
10
|
+
export default Slider;
|