@autumnsgrove/groveengine 0.3.3 → 0.4.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/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +5 -0
- package/dist/components/admin/GutterManager.svelte +4 -4
- package/dist/components/admin/MarkdownEditor.svelte +381 -1311
- package/dist/components/admin/MarkdownEditor.svelte.d.ts +2 -8
- package/dist/components/admin/composables/index.d.ts +7 -0
- package/dist/components/admin/composables/index.js +12 -0
- package/dist/components/admin/composables/useAmbientSounds.svelte.d.ts +53 -0
- package/dist/components/admin/composables/useAmbientSounds.svelte.js +192 -0
- package/dist/components/admin/composables/useCommandPalette.svelte.d.ts +17 -0
- package/dist/components/admin/composables/useCommandPalette.svelte.js +118 -0
- package/dist/components/admin/composables/useDraftManager.svelte.d.ts +17 -0
- package/dist/components/admin/composables/useDraftManager.svelte.js +154 -0
- package/dist/components/admin/composables/useEditorTheme.svelte.d.ts +195 -0
- package/dist/components/admin/composables/useEditorTheme.svelte.js +182 -0
- package/dist/components/admin/composables/useSlashCommands.svelte.d.ts +32 -0
- package/dist/components/admin/composables/useSlashCommands.svelte.js +166 -0
- package/dist/components/admin/composables/useSnippets.svelte.d.ts +5 -0
- package/dist/components/admin/composables/useSnippets.svelte.js +122 -0
- package/dist/components/admin/composables/useWritingSession.svelte.d.ts +13 -0
- package/dist/components/admin/composables/useWritingSession.svelte.js +100 -0
- package/dist/components/custom/ContentWithGutter.svelte +1 -1
- package/dist/components/custom/GutterItem.svelte +2 -2
- package/dist/config/ai-models.d.ts +25 -0
- package/dist/config/ai-models.js +50 -0
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.js +4 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +6 -6
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +4 -0
- package/dist/ui/components/charts/ActivityOverview.svelte +293 -0
- package/dist/ui/components/charts/ActivityOverview.svelte.d.ts +12 -0
- package/dist/ui/components/charts/LOCBar.svelte +129 -0
- package/dist/ui/components/charts/LOCBar.svelte.d.ts +21 -0
- package/dist/ui/components/charts/RepoBreakdown.svelte +136 -0
- package/dist/ui/components/charts/RepoBreakdown.svelte.d.ts +16 -0
- package/dist/ui/components/charts/Sparkline.svelte +139 -0
- package/dist/ui/components/charts/Sparkline.svelte.d.ts +6 -0
- package/dist/ui/components/charts/index.d.ts +5 -0
- package/dist/ui/components/charts/index.js +11 -0
- package/dist/ui/components/content/PlanCard.svelte +91 -0
- package/dist/ui/components/content/PlanCard.svelte.d.ts +13 -0
- package/dist/ui/components/content/ProductCard.svelte +125 -0
- package/dist/ui/components/content/ProductCard.svelte.d.ts +14 -0
- package/dist/ui/components/content/SearchCard.svelte +60 -0
- package/dist/ui/components/content/SearchCard.svelte.d.ts +10 -0
- package/dist/ui/components/content/index.d.ts +4 -0
- package/dist/ui/components/content/index.js +10 -0
- package/dist/ui/components/forms/SearchInput.svelte +89 -0
- package/dist/ui/components/forms/SearchInput.svelte.d.ts +11 -0
- package/dist/ui/components/forms/index.d.ts +2 -0
- package/dist/ui/components/forms/index.js +8 -0
- package/dist/ui/components/gallery/index.d.ts +5 -0
- package/dist/ui/components/gallery/index.js +13 -0
- package/dist/ui/components/icons/IconLegend.svelte +83 -0
- package/dist/ui/components/icons/IconLegend.svelte.d.ts +11 -0
- package/dist/ui/components/icons/Icons.svelte +115 -0
- package/dist/ui/components/icons/Icons.svelte.d.ts +8 -0
- package/dist/ui/components/icons/index.d.ts +3 -0
- package/dist/ui/components/icons/index.js +9 -0
- package/dist/ui/components/indicators/CreditBalance.svelte +67 -0
- package/dist/ui/components/indicators/CreditBalance.svelte.d.ts +9 -0
- package/dist/ui/components/indicators/ScoreBar.svelte +63 -0
- package/dist/ui/components/indicators/ScoreBar.svelte.d.ts +9 -0
- package/dist/ui/components/indicators/StatusBadge.svelte +46 -0
- package/dist/ui/components/indicators/StatusBadge.svelte.d.ts +7 -0
- package/dist/ui/components/indicators/index.d.ts +4 -0
- package/dist/ui/components/indicators/index.js +10 -0
- package/dist/{components/ui → ui/components/primitives}/accordion/accordion-content.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/accordion/accordion-item.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/accordion/accordion-trigger.svelte +1 -1
- package/dist/ui/components/primitives/badge/badge.svelte +50 -0
- package/dist/ui/components/primitives/badge/badge.svelte.d.ts +60 -0
- package/dist/ui/components/primitives/badge/index.d.ts +2 -0
- package/dist/ui/components/primitives/badge/index.js +2 -0
- package/dist/ui/components/primitives/button/button.svelte +82 -0
- package/dist/ui/components/primitives/button/button.svelte.d.ts +132 -0
- package/dist/ui/components/primitives/button/index.d.ts +2 -0
- package/dist/ui/components/primitives/button/index.js +4 -0
- package/dist/ui/components/primitives/card/card-content.svelte +16 -0
- package/dist/ui/components/primitives/card/card-content.svelte.d.ts +5 -0
- package/dist/ui/components/primitives/card/card-description.svelte +16 -0
- package/dist/ui/components/primitives/card/card-description.svelte.d.ts +5 -0
- package/dist/ui/components/primitives/card/card-footer.svelte +16 -0
- package/dist/ui/components/primitives/card/card-footer.svelte.d.ts +5 -0
- package/dist/ui/components/primitives/card/card-header.svelte +16 -0
- package/dist/ui/components/primitives/card/card-header.svelte.d.ts +5 -0
- package/dist/ui/components/primitives/card/card-title.svelte +25 -0
- package/dist/ui/components/primitives/card/card-title.svelte.d.ts +8 -0
- package/dist/ui/components/primitives/card/card.svelte +20 -0
- package/dist/ui/components/primitives/card/card.svelte.d.ts +5 -0
- package/dist/ui/components/primitives/card/index.d.ts +7 -0
- package/dist/ui/components/primitives/card/index.js +9 -0
- package/dist/{components/ui → ui/components/primitives}/dialog/dialog-content.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/dialog/dialog-description.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/dialog/dialog-footer.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/dialog/dialog-header.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/dialog/dialog-overlay.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/dialog/dialog-title.svelte +1 -1
- package/dist/ui/components/primitives/input/index.d.ts +2 -0
- package/dist/ui/components/primitives/input/index.js +4 -0
- package/dist/ui/components/primitives/input/input.svelte +46 -0
- package/dist/ui/components/primitives/input/input.svelte.d.ts +13 -0
- package/dist/{components/ui → ui/components/primitives}/select/select-content.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/select/select-group-heading.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/select/select-item.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/select/select-scroll-down-button.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/select/select-scroll-up-button.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/select/select-separator.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/select/select-trigger.svelte +1 -1
- package/dist/ui/components/primitives/separator/index.d.ts +2 -0
- package/dist/ui/components/primitives/separator/index.js +4 -0
- package/dist/ui/components/primitives/separator/separator.svelte +22 -0
- package/dist/ui/components/primitives/separator/separator.svelte.d.ts +4 -0
- package/dist/{components/ui → ui/components/primitives}/sheet/sheet-content.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/sheet/sheet-description.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/sheet/sheet-footer.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/sheet/sheet-header.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/sheet/sheet-overlay.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/sheet/sheet-title.svelte +1 -1
- package/dist/ui/components/primitives/skeleton/index.d.ts +2 -0
- package/dist/ui/components/primitives/skeleton/index.js +4 -0
- package/dist/ui/components/primitives/skeleton/skeleton.svelte +17 -0
- package/dist/ui/components/primitives/skeleton/skeleton.svelte.d.ts +5 -0
- package/dist/{components/ui → ui/components/primitives}/table/table-body.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/table/table-caption.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/table/table-cell.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/table/table-footer.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/table/table-head.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/table/table-header.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/table/table-row.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/table/table.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/tabs/tabs-content.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/tabs/tabs-list.svelte +1 -1
- package/dist/{components/ui → ui/components/primitives}/tabs/tabs-trigger.svelte +1 -1
- package/dist/ui/components/primitives/textarea/index.d.ts +2 -0
- package/dist/ui/components/primitives/textarea/index.js +4 -0
- package/dist/ui/components/primitives/textarea/textarea.svelte +24 -0
- package/dist/ui/components/primitives/textarea/textarea.svelte.d.ts +6 -0
- package/dist/ui/components/states/EmptyState.svelte +28 -0
- package/dist/ui/components/states/EmptyState.svelte.d.ts +10 -0
- package/dist/ui/components/states/Loading.svelte +62 -0
- package/dist/ui/components/states/Loading.svelte.d.ts +7 -0
- package/dist/ui/components/states/LoadingSkeleton.svelte +46 -0
- package/dist/ui/components/states/LoadingSkeleton.svelte.d.ts +8 -0
- package/dist/ui/components/states/ThemeToggle.svelte +138 -0
- package/dist/ui/components/states/ThemeToggle.svelte.d.ts +6 -0
- package/dist/ui/components/states/index.d.ts +5 -0
- package/dist/ui/components/states/index.js +11 -0
- package/dist/{components → ui/components}/ui/Accordion.svelte +1 -1
- package/dist/ui/components/ui/Badge.svelte +52 -0
- package/dist/ui/components/ui/Badge.svelte.d.ts +28 -0
- package/dist/ui/components/ui/Button.svelte +77 -0
- package/dist/ui/components/ui/Button.svelte.d.ts +34 -0
- package/dist/ui/components/ui/Card.svelte +102 -0
- package/dist/ui/components/ui/Card.svelte.d.ts +46 -0
- package/dist/ui/components/ui/CollapsibleSection.svelte +65 -0
- package/dist/ui/components/ui/CollapsibleSection.svelte.d.ts +10 -0
- package/dist/{components → ui/components}/ui/Dialog.svelte +1 -1
- package/dist/ui/components/ui/Input.svelte +81 -0
- package/dist/ui/components/ui/Input.svelte.d.ts +35 -0
- package/dist/{components → ui/components}/ui/Select.svelte +1 -1
- package/dist/{components → ui/components}/ui/Sheet.svelte +1 -1
- package/dist/ui/components/ui/Skeleton.svelte +31 -0
- package/dist/ui/components/ui/Skeleton.svelte.d.ts +26 -0
- package/dist/ui/components/ui/Spinner.svelte +45 -0
- package/dist/ui/components/ui/Spinner.svelte.d.ts +15 -0
- package/dist/{components → ui/components}/ui/Table.svelte +2 -2
- package/dist/{components → ui/components}/ui/Table.svelte.d.ts +1 -1
- package/dist/{components → ui/components}/ui/Tabs.svelte +2 -2
- package/dist/ui/components/ui/Textarea.svelte +81 -0
- package/dist/ui/components/ui/Textarea.svelte.d.ts +35 -0
- package/dist/{components → ui/components}/ui/Toast.svelte +1 -1
- package/dist/ui/components/ui/index.d.ts +18 -0
- package/dist/ui/components/ui/index.js +28 -0
- package/dist/{components → ui/components}/ui/toast.d.ts +1 -1
- package/dist/{components → ui/components}/ui/toast.js +2 -2
- package/dist/ui/index.d.ts +10 -0
- package/dist/ui/index.js +22 -0
- package/dist/ui/stores/theme.d.ts +12 -0
- package/dist/ui/stores/theme.js +52 -0
- package/dist/ui/styles/content.css +514 -0
- package/dist/ui/styles/grove.css +715 -0
- package/dist/ui/styles/tokens.css +429 -0
- package/dist/ui/tailwind.preset.d.ts +340 -0
- package/dist/ui/tailwind.preset.js +441 -0
- package/dist/ui/tokens/animation.d.ts +417 -0
- package/dist/ui/tokens/animation.js +139 -0
- package/dist/ui/tokens/colors.d.ts +183 -0
- package/dist/ui/tokens/colors.js +97 -0
- package/dist/ui/tokens/effects.d.ts +111 -0
- package/dist/ui/tokens/effects.js +61 -0
- package/dist/ui/tokens/index.d.ts +6 -0
- package/dist/ui/tokens/index.js +19 -0
- package/dist/ui/tokens/spacing.d.ts +89 -0
- package/dist/ui/tokens/spacing.js +49 -0
- package/dist/ui/tokens/typography.d.ts +85 -0
- package/dist/ui/tokens/typography.js +68 -0
- package/dist/ui/utils/cn.d.ts +13 -0
- package/dist/ui/utils/cn.js +24 -0
- package/dist/ui/utils/index.d.ts +2 -0
- package/dist/ui/utils/index.js +8 -0
- package/dist/utils/index.d.ts +11 -0
- package/dist/utils/index.js +14 -0
- package/dist/utils/markdown.d.ts +11 -0
- package/dist/utils/markdown.js +25 -0
- package/dist/utils/sanitize.js +2 -3
- package/package.json +73 -10
- package/dist/components/ui/index.d.ts +0 -14
- package/dist/components/ui/index.js +0 -18
- /package/dist/{components → ui/components}/gallery/ImageGallery.svelte +0 -0
- /package/dist/{components → ui/components}/gallery/ImageGallery.svelte.d.ts +0 -0
- /package/dist/{components → ui/components}/gallery/Lightbox.svelte +0 -0
- /package/dist/{components → ui/components}/gallery/Lightbox.svelte.d.ts +0 -0
- /package/dist/{components → ui/components}/gallery/LightboxCaption.svelte +0 -0
- /package/dist/{components → ui/components}/gallery/LightboxCaption.svelte.d.ts +0 -0
- /package/dist/{components → ui/components}/gallery/ZoomableImage.svelte +0 -0
- /package/dist/{components → ui/components}/gallery/ZoomableImage.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/accordion/accordion-content.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/accordion/accordion-item.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/accordion/accordion-trigger.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/accordion/index.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/accordion/index.js +0 -0
- /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-content.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-description.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-footer.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-header.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-overlay.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-title.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/dialog/index.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/dialog/index.js +0 -0
- /package/dist/{components/ui → ui/components/primitives}/select/index.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/select/index.js +0 -0
- /package/dist/{components/ui → ui/components/primitives}/select/select-content.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/select/select-group-heading.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/select/select-item.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/select/select-scroll-down-button.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/select/select-scroll-up-button.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/select/select-separator.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/select/select-trigger.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/sheet/index.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/sheet/index.js +0 -0
- /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-content.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-description.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-footer.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-header.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-overlay.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-title.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/table/index.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/table/index.js +0 -0
- /package/dist/{components/ui → ui/components/primitives}/table/table-body.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/table/table-caption.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/table/table-cell.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/table/table-footer.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/table/table-head.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/table/table-header.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/table/table-row.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/table/table.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/tabs/index.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/tabs/index.js +0 -0
- /package/dist/{components/ui → ui/components/primitives}/tabs/tabs-content.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/tabs/tabs-list.svelte.d.ts +0 -0
- /package/dist/{components/ui → ui/components/primitives}/tabs/tabs-trigger.svelte.d.ts +0 -0
- /package/dist/{components → ui/components}/ui/Accordion.svelte.d.ts +0 -0
- /package/dist/{components → ui/components}/ui/Dialog.svelte.d.ts +0 -0
- /package/dist/{components → ui/components}/ui/Select.svelte.d.ts +0 -0
- /package/dist/{components → ui/components}/ui/Sheet.svelte.d.ts +0 -0
- /package/dist/{components → ui/components}/ui/Tabs.svelte.d.ts +0 -0
- /package/dist/{components → ui/components}/ui/Toast.svelte.d.ts +0 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { themeStore } from '../../stores/theme';
|
|
3
|
+
|
|
4
|
+
let { compact = false }: { compact?: boolean } = $props();
|
|
5
|
+
|
|
6
|
+
// Subscribe to stores
|
|
7
|
+
const { theme, resolvedTheme: resolvedThemeStore, toggle, setTheme } = themeStore;
|
|
8
|
+
|
|
9
|
+
// Derive title from resolved theme
|
|
10
|
+
let toggleTitle = $derived($resolvedThemeStore === 'dark' ? 'Switch to light mode' : 'Switch to dark mode');
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
{#if compact}
|
|
14
|
+
<button
|
|
15
|
+
class="theme-toggle-compact"
|
|
16
|
+
onclick={() => toggle()}
|
|
17
|
+
aria-label="Toggle theme"
|
|
18
|
+
title={toggleTitle}
|
|
19
|
+
>
|
|
20
|
+
{#if $resolvedThemeStore === 'dark'}
|
|
21
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
22
|
+
<circle cx="12" cy="12" r="5" />
|
|
23
|
+
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
|
|
24
|
+
</svg>
|
|
25
|
+
{:else}
|
|
26
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
27
|
+
<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" />
|
|
28
|
+
</svg>
|
|
29
|
+
{/if}
|
|
30
|
+
</button>
|
|
31
|
+
{:else}
|
|
32
|
+
<div class="theme-selector">
|
|
33
|
+
<div class="theme-label">Theme</div>
|
|
34
|
+
<div class="theme-options">
|
|
35
|
+
<button
|
|
36
|
+
class="theme-option"
|
|
37
|
+
class:active={$theme === 'light'}
|
|
38
|
+
onclick={() => setTheme('light')}
|
|
39
|
+
>
|
|
40
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
41
|
+
<circle cx="12" cy="12" r="5" />
|
|
42
|
+
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
|
|
43
|
+
</svg>
|
|
44
|
+
Light
|
|
45
|
+
</button>
|
|
46
|
+
<button
|
|
47
|
+
class="theme-option"
|
|
48
|
+
class:active={$theme === 'dark'}
|
|
49
|
+
onclick={() => setTheme('dark')}
|
|
50
|
+
>
|
|
51
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
52
|
+
<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" />
|
|
53
|
+
</svg>
|
|
54
|
+
Dark
|
|
55
|
+
</button>
|
|
56
|
+
<button
|
|
57
|
+
class="theme-option"
|
|
58
|
+
class:active={$theme === 'system'}
|
|
59
|
+
onclick={() => setTheme('system')}
|
|
60
|
+
>
|
|
61
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
62
|
+
<rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
|
|
63
|
+
<path d="M8 21h8M12 17v4" />
|
|
64
|
+
</svg>
|
|
65
|
+
System
|
|
66
|
+
</button>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
{/if}
|
|
70
|
+
|
|
71
|
+
<style>
|
|
72
|
+
.theme-toggle-compact {
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
justify-content: center;
|
|
76
|
+
width: 36px;
|
|
77
|
+
height: 36px;
|
|
78
|
+
border: none;
|
|
79
|
+
background: transparent;
|
|
80
|
+
color: var(--color-text-secondary);
|
|
81
|
+
border-radius: var(--radius-md);
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
transition: all var(--transition-fast);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.theme-toggle-compact:hover {
|
|
87
|
+
background: var(--color-bg-secondary);
|
|
88
|
+
color: var(--color-text);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.theme-selector {
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-direction: column;
|
|
94
|
+
gap: 0.5rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.theme-label {
|
|
98
|
+
font-size: 0.875rem;
|
|
99
|
+
font-weight: 500;
|
|
100
|
+
color: var(--color-text-secondary);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.theme-options {
|
|
104
|
+
display: flex;
|
|
105
|
+
gap: 0.5rem;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.theme-option {
|
|
109
|
+
display: flex;
|
|
110
|
+
align-items: center;
|
|
111
|
+
gap: 0.5rem;
|
|
112
|
+
padding: 0.5rem 1rem;
|
|
113
|
+
border: 1px solid var(--color-border);
|
|
114
|
+
background: var(--color-bg);
|
|
115
|
+
color: var(--color-text-secondary);
|
|
116
|
+
border-radius: var(--radius-md);
|
|
117
|
+
font-size: 0.875rem;
|
|
118
|
+
cursor: pointer;
|
|
119
|
+
transition: all var(--transition-fast);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.theme-option:hover {
|
|
123
|
+
border-color: var(--color-primary);
|
|
124
|
+
color: var(--color-text);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.theme-option.active {
|
|
128
|
+
border-color: var(--color-primary);
|
|
129
|
+
background: var(--color-primary-light);
|
|
130
|
+
color: var(--color-primary);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@media (max-width: 480px) {
|
|
134
|
+
.theme-options {
|
|
135
|
+
flex-direction: column;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
</style>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as LoadingSkeleton } from './LoadingSkeleton.svelte';
|
|
2
|
+
export { default as EmptyState } from './EmptyState.svelte';
|
|
3
|
+
export { default as Loading } from './Loading.svelte';
|
|
4
|
+
export { default as ThemeToggle } from './ThemeToggle.svelte';
|
|
5
|
+
export declare const STATES_VERSION = "0.2.0";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// GroveUI - State Components
|
|
2
|
+
//
|
|
3
|
+
// This module exports loading, empty, and theme state components
|
|
4
|
+
//
|
|
5
|
+
// Usage:
|
|
6
|
+
// import { LoadingSkeleton, EmptyState, Loading, ThemeToggle } from '@groveengine/ui/states';
|
|
7
|
+
export { default as LoadingSkeleton } from './LoadingSkeleton.svelte';
|
|
8
|
+
export { default as EmptyState } from './EmptyState.svelte';
|
|
9
|
+
export { default as Loading } from './Loading.svelte';
|
|
10
|
+
export { default as ThemeToggle } from './ThemeToggle.svelte';
|
|
11
|
+
export const STATES_VERSION = '0.2.0';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Badge as ShadcnBadge } from "../primitives/badge";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
|
|
5
|
+
type BadgeVariant = "default" | "secondary" | "destructive" | "tag";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Badge component wrapper for displaying small labels, tags, or status indicators
|
|
9
|
+
*
|
|
10
|
+
* @prop {BadgeVariant} [variant="default"] - Badge style variant (default|secondary|destructive|tag)
|
|
11
|
+
* @prop {string} [class] - Additional CSS classes to apply
|
|
12
|
+
* @prop {Snippet} [children] - Badge content (typically short text)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* <Badge variant="default">New</Badge>
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* <Badge variant="destructive">Error</Badge>
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* <Badge variant="tag">TypeScript</Badge>
|
|
22
|
+
*/
|
|
23
|
+
interface Props {
|
|
24
|
+
variant?: BadgeVariant;
|
|
25
|
+
class?: string;
|
|
26
|
+
children?: Snippet;
|
|
27
|
+
onclick?: (e: MouseEvent) => void;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let {
|
|
32
|
+
variant = "default",
|
|
33
|
+
class: className,
|
|
34
|
+
children,
|
|
35
|
+
onclick,
|
|
36
|
+
...restProps
|
|
37
|
+
}: Props = $props();
|
|
38
|
+
|
|
39
|
+
// Map tag variant to secondary styling
|
|
40
|
+
const variantMap: Record<BadgeVariant, "default" | "secondary" | "destructive"> = {
|
|
41
|
+
default: "default",
|
|
42
|
+
secondary: "secondary",
|
|
43
|
+
destructive: "destructive",
|
|
44
|
+
tag: "secondary"
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const shadcnVariant = $derived(variantMap[variant]);
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<ShadcnBadge variant={shadcnVariant} class={className} {onclick} {...restProps}>
|
|
51
|
+
{@render children?.()}
|
|
52
|
+
</ShadcnBadge>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
type BadgeVariant = "default" | "secondary" | "destructive" | "tag";
|
|
3
|
+
/**
|
|
4
|
+
* Badge component wrapper for displaying small labels, tags, or status indicators
|
|
5
|
+
*
|
|
6
|
+
* @prop {BadgeVariant} [variant="default"] - Badge style variant (default|secondary|destructive|tag)
|
|
7
|
+
* @prop {string} [class] - Additional CSS classes to apply
|
|
8
|
+
* @prop {Snippet} [children] - Badge content (typically short text)
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* <Badge variant="default">New</Badge>
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* <Badge variant="destructive">Error</Badge>
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* <Badge variant="tag">TypeScript</Badge>
|
|
18
|
+
*/
|
|
19
|
+
interface Props {
|
|
20
|
+
variant?: BadgeVariant;
|
|
21
|
+
class?: string;
|
|
22
|
+
children?: Snippet;
|
|
23
|
+
onclick?: (e: MouseEvent) => void;
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
}
|
|
26
|
+
declare const Badge: import("svelte").Component<Props, {}, "">;
|
|
27
|
+
type Badge = ReturnType<typeof Badge>;
|
|
28
|
+
export default Badge;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Button as ShadcnButton } from "../primitives/button";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
5
|
+
|
|
6
|
+
type ButtonVariant = "primary" | "secondary" | "danger" | "ghost" | "link" | "default" | "outline";
|
|
7
|
+
type ButtonSize = "sm" | "md" | "lg" | "icon";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Button component wrapper around shadcn-svelte Button
|
|
11
|
+
*
|
|
12
|
+
* @prop {ButtonVariant} [variant="primary"] - Button style variant (primary|secondary|danger|ghost|link)
|
|
13
|
+
* @prop {ButtonSize} [size="md"] - Button size (sm|md|lg)
|
|
14
|
+
* @prop {boolean} [disabled=false] - Whether button is disabled
|
|
15
|
+
* @prop {Function} [onclick] - Click handler function
|
|
16
|
+
* @prop {string} [href] - Optional link href (renders as anchor element)
|
|
17
|
+
* @prop {string} [class] - Additional CSS classes to apply
|
|
18
|
+
* @prop {Snippet} [children] - Button content (text/icons/etc)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* <Button variant="primary" size="lg">Save Changes</Button>
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* <Button variant="danger" onclick={() => handleDelete()}>Delete</Button>
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* <Button variant="ghost" href="/settings">Settings</Button>
|
|
28
|
+
*/
|
|
29
|
+
interface Props extends Omit<HTMLButtonAttributes, "class"> {
|
|
30
|
+
variant?: ButtonVariant;
|
|
31
|
+
size?: ButtonSize;
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
class?: string;
|
|
34
|
+
children?: Snippet;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let {
|
|
38
|
+
variant = "primary",
|
|
39
|
+
size = "md",
|
|
40
|
+
disabled = false,
|
|
41
|
+
class: className,
|
|
42
|
+
children,
|
|
43
|
+
...restProps
|
|
44
|
+
}: Props = $props();
|
|
45
|
+
|
|
46
|
+
// Map our simplified variants to shadcn variants
|
|
47
|
+
const variantMap: Record<ButtonVariant, "default" | "secondary" | "destructive" | "ghost" | "link" | "outline"> = {
|
|
48
|
+
primary: "default",
|
|
49
|
+
secondary: "secondary",
|
|
50
|
+
danger: "destructive",
|
|
51
|
+
ghost: "ghost",
|
|
52
|
+
link: "link",
|
|
53
|
+
default: "default",
|
|
54
|
+
outline: "outline"
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Map our size variants to shadcn sizes
|
|
58
|
+
const sizeMap: Record<ButtonSize, "sm" | "default" | "lg" | "icon"> = {
|
|
59
|
+
sm: "sm",
|
|
60
|
+
md: "default",
|
|
61
|
+
lg: "lg",
|
|
62
|
+
icon: "icon"
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const shadcnVariant = $derived(variantMap[variant]);
|
|
66
|
+
const shadcnSize = $derived(sizeMap[size]);
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<ShadcnButton
|
|
70
|
+
variant={shadcnVariant}
|
|
71
|
+
size={shadcnSize}
|
|
72
|
+
disabled={disabled}
|
|
73
|
+
class={className}
|
|
74
|
+
{...restProps}
|
|
75
|
+
>
|
|
76
|
+
{@render children?.()}
|
|
77
|
+
</ShadcnButton>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
3
|
+
type ButtonVariant = "primary" | "secondary" | "danger" | "ghost" | "link" | "default" | "outline";
|
|
4
|
+
type ButtonSize = "sm" | "md" | "lg" | "icon";
|
|
5
|
+
/**
|
|
6
|
+
* Button component wrapper around shadcn-svelte Button
|
|
7
|
+
*
|
|
8
|
+
* @prop {ButtonVariant} [variant="primary"] - Button style variant (primary|secondary|danger|ghost|link)
|
|
9
|
+
* @prop {ButtonSize} [size="md"] - Button size (sm|md|lg)
|
|
10
|
+
* @prop {boolean} [disabled=false] - Whether button is disabled
|
|
11
|
+
* @prop {Function} [onclick] - Click handler function
|
|
12
|
+
* @prop {string} [href] - Optional link href (renders as anchor element)
|
|
13
|
+
* @prop {string} [class] - Additional CSS classes to apply
|
|
14
|
+
* @prop {Snippet} [children] - Button content (text/icons/etc)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* <Button variant="primary" size="lg">Save Changes</Button>
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* <Button variant="danger" onclick={() => handleDelete()}>Delete</Button>
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* <Button variant="ghost" href="/settings">Settings</Button>
|
|
24
|
+
*/
|
|
25
|
+
interface Props extends Omit<HTMLButtonAttributes, "class"> {
|
|
26
|
+
variant?: ButtonVariant;
|
|
27
|
+
size?: ButtonSize;
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
class?: string;
|
|
30
|
+
children?: Snippet;
|
|
31
|
+
}
|
|
32
|
+
declare const Button: import("svelte").Component<Props, {}, "">;
|
|
33
|
+
type Button = ReturnType<typeof Button>;
|
|
34
|
+
export default Button;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
Card as ShadcnCard,
|
|
4
|
+
CardHeader,
|
|
5
|
+
CardTitle,
|
|
6
|
+
CardDescription,
|
|
7
|
+
CardContent,
|
|
8
|
+
CardFooter
|
|
9
|
+
} from "../primitives/card";
|
|
10
|
+
import type { Snippet } from "svelte";
|
|
11
|
+
import { cn } from "../../utils";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Card component wrapper providing structured layout with header, content, and footer
|
|
15
|
+
*
|
|
16
|
+
* @prop {string} [title] - Card title (renders in CardHeader with CardTitle)
|
|
17
|
+
* @prop {string} [description] - Card description (renders in CardHeader with CardDescription)
|
|
18
|
+
* @prop {boolean} [hoverable=false] - Enable hover shadow effect for interactive cards
|
|
19
|
+
* @prop {Snippet} [header] - Custom header content (overrides title/description)
|
|
20
|
+
* @prop {Snippet} [footer] - Footer content (rendered in CardFooter)
|
|
21
|
+
* @prop {Snippet} [children] - Main card content (rendered in CardContent)
|
|
22
|
+
* @prop {string} [class] - Additional CSS classes for Card root
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* <Card title="Profile" description="Update your profile settings">
|
|
26
|
+
* <p>Card content here</p>
|
|
27
|
+
* </Card>
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* <Card hoverable>
|
|
31
|
+
* {#snippet header()}
|
|
32
|
+
* <CustomHeader />
|
|
33
|
+
* {/snippet}
|
|
34
|
+
* Content here
|
|
35
|
+
* </Card>
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* <Card title="Actions">
|
|
39
|
+
* {#snippet footer()}
|
|
40
|
+
* <Button>Save</Button>
|
|
41
|
+
* {/snippet}
|
|
42
|
+
* Form content
|
|
43
|
+
* </Card>
|
|
44
|
+
*/
|
|
45
|
+
interface Props {
|
|
46
|
+
title?: string;
|
|
47
|
+
description?: string;
|
|
48
|
+
hoverable?: boolean;
|
|
49
|
+
class?: string;
|
|
50
|
+
header?: Snippet;
|
|
51
|
+
footer?: Snippet;
|
|
52
|
+
children?: Snippet;
|
|
53
|
+
[key: string]: any; // Allow any additional props to be forwarded
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let {
|
|
57
|
+
title,
|
|
58
|
+
description,
|
|
59
|
+
hoverable = false,
|
|
60
|
+
class: className,
|
|
61
|
+
header,
|
|
62
|
+
footer,
|
|
63
|
+
children,
|
|
64
|
+
...restProps
|
|
65
|
+
}: Props = $props();
|
|
66
|
+
|
|
67
|
+
const cardClass = $derived(
|
|
68
|
+
cn(
|
|
69
|
+
hoverable && "hover:shadow-lg transition-shadow cursor-pointer",
|
|
70
|
+
className
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<ShadcnCard class={cardClass} {...restProps}>
|
|
76
|
+
{#if header || title || description}
|
|
77
|
+
<CardHeader>
|
|
78
|
+
{#if header}
|
|
79
|
+
{@render header()}
|
|
80
|
+
{:else}
|
|
81
|
+
{#if title}
|
|
82
|
+
<CardTitle>{title}</CardTitle>
|
|
83
|
+
{/if}
|
|
84
|
+
{#if description}
|
|
85
|
+
<CardDescription>{description}</CardDescription>
|
|
86
|
+
{/if}
|
|
87
|
+
{/if}
|
|
88
|
+
</CardHeader>
|
|
89
|
+
{/if}
|
|
90
|
+
|
|
91
|
+
{#if children}
|
|
92
|
+
<CardContent>
|
|
93
|
+
{@render children()}
|
|
94
|
+
</CardContent>
|
|
95
|
+
{/if}
|
|
96
|
+
|
|
97
|
+
{#if footer}
|
|
98
|
+
<CardFooter>
|
|
99
|
+
{@render footer()}
|
|
100
|
+
</CardFooter>
|
|
101
|
+
{/if}
|
|
102
|
+
</ShadcnCard>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
/**
|
|
3
|
+
* Card component wrapper providing structured layout with header, content, and footer
|
|
4
|
+
*
|
|
5
|
+
* @prop {string} [title] - Card title (renders in CardHeader with CardTitle)
|
|
6
|
+
* @prop {string} [description] - Card description (renders in CardHeader with CardDescription)
|
|
7
|
+
* @prop {boolean} [hoverable=false] - Enable hover shadow effect for interactive cards
|
|
8
|
+
* @prop {Snippet} [header] - Custom header content (overrides title/description)
|
|
9
|
+
* @prop {Snippet} [footer] - Footer content (rendered in CardFooter)
|
|
10
|
+
* @prop {Snippet} [children] - Main card content (rendered in CardContent)
|
|
11
|
+
* @prop {string} [class] - Additional CSS classes for Card root
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* <Card title="Profile" description="Update your profile settings">
|
|
15
|
+
* <p>Card content here</p>
|
|
16
|
+
* </Card>
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* <Card hoverable>
|
|
20
|
+
* {#snippet header()}
|
|
21
|
+
* <CustomHeader />
|
|
22
|
+
* {/snippet}
|
|
23
|
+
* Content here
|
|
24
|
+
* </Card>
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* <Card title="Actions">
|
|
28
|
+
* {#snippet footer()}
|
|
29
|
+
* <Button>Save</Button>
|
|
30
|
+
* {/snippet}
|
|
31
|
+
* Form content
|
|
32
|
+
* </Card>
|
|
33
|
+
*/
|
|
34
|
+
interface Props {
|
|
35
|
+
title?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
hoverable?: boolean;
|
|
38
|
+
class?: string;
|
|
39
|
+
header?: Snippet;
|
|
40
|
+
footer?: Snippet;
|
|
41
|
+
children?: Snippet;
|
|
42
|
+
[key: string]: any;
|
|
43
|
+
}
|
|
44
|
+
declare const Card: import("svelte").Component<Props, {}, "">;
|
|
45
|
+
type Card = ReturnType<typeof Card>;
|
|
46
|
+
export default Card;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
title: string;
|
|
6
|
+
defaultOpen?: boolean;
|
|
7
|
+
children?: Snippet;
|
|
8
|
+
class?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
title,
|
|
13
|
+
defaultOpen = false,
|
|
14
|
+
children,
|
|
15
|
+
class: className = '',
|
|
16
|
+
...restProps
|
|
17
|
+
}: Props = $props();
|
|
18
|
+
|
|
19
|
+
let isOpen = $state(defaultOpen);
|
|
20
|
+
|
|
21
|
+
function toggle() {
|
|
22
|
+
isOpen = !isOpen;
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<div class="collapsible-section {className}" {...restProps}>
|
|
27
|
+
<button
|
|
28
|
+
type="button"
|
|
29
|
+
class="collapsible-trigger w-full flex items-center justify-between px-4 py-3 text-left font-medium border-b hover:bg-muted/50 transition-colors"
|
|
30
|
+
onclick={toggle}
|
|
31
|
+
aria-expanded={isOpen}
|
|
32
|
+
>
|
|
33
|
+
<span>{title}</span>
|
|
34
|
+
<svg
|
|
35
|
+
class="w-5 h-5 transition-transform {isOpen ? 'rotate-180' : ''}"
|
|
36
|
+
fill="none"
|
|
37
|
+
stroke="currentColor"
|
|
38
|
+
viewBox="0 0 24 24"
|
|
39
|
+
>
|
|
40
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
|
41
|
+
</svg>
|
|
42
|
+
</button>
|
|
43
|
+
|
|
44
|
+
{#if isOpen}
|
|
45
|
+
<div class="collapsible-content px-4 py-4">
|
|
46
|
+
{@render children?.()}
|
|
47
|
+
</div>
|
|
48
|
+
{/if}
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<style>
|
|
52
|
+
.collapsible-section {
|
|
53
|
+
border: 1px solid hsl(var(--border));
|
|
54
|
+
border-radius: var(--radius);
|
|
55
|
+
overflow: hidden;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.collapsible-trigger {
|
|
59
|
+
background: hsl(var(--background));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.collapsible-content {
|
|
63
|
+
background: hsl(var(--card));
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
title: string;
|
|
4
|
+
defaultOpen?: boolean;
|
|
5
|
+
children?: Snippet;
|
|
6
|
+
class?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const CollapsibleSection: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type CollapsibleSection = ReturnType<typeof CollapsibleSection>;
|
|
10
|
+
export default CollapsibleSection;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Input as ShadcnInput } from "../primitives/input";
|
|
3
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
4
|
+
import { cn } from "../../utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Input component wrapper with label, error handling, and validation
|
|
8
|
+
*
|
|
9
|
+
* @prop {string} [label] - Input label text (renders above input)
|
|
10
|
+
* @prop {string} [error] - Error message to display (turns border red)
|
|
11
|
+
* @prop {string|number} [value] - Input value (bindable for two-way binding)
|
|
12
|
+
* @prop {string} [placeholder] - Placeholder text
|
|
13
|
+
* @prop {string} [type="text"] - Input type (text|email|password|number)
|
|
14
|
+
* @prop {boolean} [required=false] - Whether input is required (shows asterisk)
|
|
15
|
+
* @prop {boolean} [disabled=false] - Whether input is disabled
|
|
16
|
+
* @prop {string} [class] - Additional CSS classes to apply
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* <Input label="Email" type="email" bind:value={email} required />
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* <Input label="Password" type="password" bind:value={password} error={passwordError} />
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* <Input placeholder="Search..." bind:value={searchQuery} />
|
|
26
|
+
*/
|
|
27
|
+
interface Props extends Omit<HTMLInputAttributes, "class"> {
|
|
28
|
+
label?: string;
|
|
29
|
+
error?: string;
|
|
30
|
+
value?: string | number;
|
|
31
|
+
placeholder?: string;
|
|
32
|
+
type?: "text" | "email" | "password" | "number";
|
|
33
|
+
required?: boolean;
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
class?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let {
|
|
39
|
+
label,
|
|
40
|
+
error,
|
|
41
|
+
value = $bindable(""),
|
|
42
|
+
placeholder,
|
|
43
|
+
type = "text",
|
|
44
|
+
required = false,
|
|
45
|
+
disabled = false,
|
|
46
|
+
class: className,
|
|
47
|
+
...restProps
|
|
48
|
+
}: Props = $props();
|
|
49
|
+
|
|
50
|
+
const inputClass = $derived(
|
|
51
|
+
cn(
|
|
52
|
+
error && "border-destructive focus-visible:ring-destructive/20",
|
|
53
|
+
className
|
|
54
|
+
)
|
|
55
|
+
);
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<div class="flex flex-col gap-1.5">
|
|
59
|
+
{#if label}
|
|
60
|
+
<label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
|
|
61
|
+
{label}
|
|
62
|
+
{#if required}
|
|
63
|
+
<span class="text-destructive">*</span>
|
|
64
|
+
{/if}
|
|
65
|
+
</label>
|
|
66
|
+
{/if}
|
|
67
|
+
|
|
68
|
+
<ShadcnInput
|
|
69
|
+
bind:value
|
|
70
|
+
{type}
|
|
71
|
+
{placeholder}
|
|
72
|
+
{required}
|
|
73
|
+
{disabled}
|
|
74
|
+
class={inputClass}
|
|
75
|
+
{...restProps}
|
|
76
|
+
/>
|
|
77
|
+
|
|
78
|
+
{#if error}
|
|
79
|
+
<p class="text-sm text-destructive">{error}</p>
|
|
80
|
+
{/if}
|
|
81
|
+
</div>
|