svelora 3.0.5 → 3.0.7
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/BentoGrid/BentoCard.svelte +45 -0
- package/dist/BentoGrid/BentoCard.svelte.d.ts +4 -0
- package/dist/BentoGrid/BentoGrid.svelte +9 -0
- package/dist/BentoGrid/BentoGrid.svelte.d.ts +4 -0
- package/dist/BentoGrid/bento-grid.types.d.ts +47 -0
- package/dist/BentoGrid/bento-grid.types.js +1 -0
- package/dist/BentoGrid/bento-grid.variants.d.ts +30 -0
- package/dist/BentoGrid/bento-grid.variants.js +16 -0
- package/dist/BentoGrid/index.d.ts +5 -0
- package/dist/BentoGrid/index.js +5 -0
- package/dist/Chart/Chart.svelte +47 -0
- package/dist/Chart/Chart.svelte.d.ts +4 -0
- package/dist/Chart/chart.types.d.ts +20 -0
- package/dist/Chart/chart.types.js +1 -0
- package/dist/Chart/chart.variants.d.ts +3 -0
- package/dist/Chart/chart.variants.js +4 -0
- package/dist/Chart/index.d.ts +4 -0
- package/dist/Chart/index.js +4 -0
- package/dist/Chat/ChatBubble.svelte +30 -0
- package/dist/Chat/ChatBubble.svelte.d.ts +4 -0
- package/dist/Chat/ChatInput.svelte +50 -0
- package/dist/Chat/ChatInput.svelte.d.ts +4 -0
- package/dist/Chat/ChatMessage.svelte +15 -0
- package/dist/Chat/ChatMessage.svelte.d.ts +4 -0
- package/dist/Chat/chat.types.d.ts +63 -0
- package/dist/Chat/chat.types.js +1 -0
- package/dist/Chat/chat.variants.d.ts +117 -0
- package/dist/Chat/chat.variants.js +47 -0
- package/dist/Chat/index.d.ts +6 -0
- package/dist/Chat/index.js +6 -0
- package/dist/ColorPicker/ColorPicker.svelte +109 -0
- package/dist/ColorPicker/ColorPicker.svelte.d.ts +4 -0
- package/dist/ColorPicker/color-picker.types.d.ts +26 -0
- package/dist/ColorPicker/color-picker.types.js +1 -0
- package/dist/ColorPicker/color-picker.variants.d.ts +69 -0
- package/dist/ColorPicker/color-picker.variants.js +13 -0
- package/dist/ColorPicker/index.d.ts +4 -0
- package/dist/ColorPicker/index.js +4 -0
- package/dist/DateRangePicker/DateRangePicker.svelte +59 -0
- package/dist/DateRangePicker/DateRangePicker.svelte.d.ts +4 -0
- package/dist/DateRangePicker/date-range-picker.types.d.ts +34 -0
- package/dist/DateRangePicker/date-range-picker.types.js +1 -0
- package/dist/DateRangePicker/date-range-picker.variants.d.ts +39 -0
- package/dist/DateRangePicker/date-range-picker.variants.js +20 -0
- package/dist/DateRangePicker/index.d.ts +4 -0
- package/dist/DateRangePicker/index.js +4 -0
- package/dist/Fonts/fonts.js +3 -1
- package/dist/Link/Link.context-harness.svelte +8 -0
- package/dist/Link/Link.context-harness.svelte.d.ts +7 -0
- package/dist/Link/Link.svelte +57 -30
- package/dist/Link/index.d.ts +2 -0
- package/dist/Link/index.js +1 -0
- package/dist/Link/location-context.d.ts +4 -0
- package/dist/Link/location-context.js +1 -0
- package/dist/List/List.svelte +14 -0
- package/dist/List/List.svelte.d.ts +4 -0
- package/dist/List/ListItem.svelte +64 -0
- package/dist/List/ListItem.svelte.d.ts +4 -0
- package/dist/List/index.d.ts +5 -0
- package/dist/List/index.js +5 -0
- package/dist/List/list.types.d.ts +62 -0
- package/dist/List/list.types.js +1 -0
- package/dist/List/list.variants.d.ts +99 -0
- package/dist/List/list.variants.js +42 -0
- package/dist/Marquee/Marquee.svelte +50 -0
- package/dist/Marquee/Marquee.svelte.d.ts +4 -0
- package/dist/Marquee/index.d.ts +4 -0
- package/dist/Marquee/index.js +4 -0
- package/dist/Marquee/marquee.types.d.ts +38 -0
- package/dist/Marquee/marquee.types.js +1 -0
- package/dist/Marquee/marquee.variants.d.ts +78 -0
- package/dist/Marquee/marquee.variants.js +28 -0
- package/dist/Menu/Menu.svelte +134 -0
- package/dist/Menu/Menu.svelte.d.ts +4 -0
- package/dist/Menu/index.d.ts +4 -0
- package/dist/Menu/index.js +4 -0
- package/dist/Menu/menu.types.d.ts +82 -0
- package/dist/Menu/menu.types.js +1 -0
- package/dist/Menu/menu.variants.d.ts +46 -0
- package/dist/Menu/menu.variants.js +32 -0
- package/dist/NumberTicker/NumberTicker.svelte +59 -0
- package/dist/NumberTicker/NumberTicker.svelte.d.ts +4 -0
- package/dist/NumberTicker/index.d.ts +4 -0
- package/dist/NumberTicker/index.js +4 -0
- package/dist/NumberTicker/number-ticker.types.d.ts +26 -0
- package/dist/NumberTicker/number-ticker.types.js +1 -0
- package/dist/NumberTicker/number-ticker.variants.d.ts +27 -0
- package/dist/NumberTicker/number-ticker.variants.js +6 -0
- package/dist/PasswordInput/PasswordInput.svelte +74 -0
- package/dist/PasswordInput/PasswordInput.svelte.d.ts +4 -0
- package/dist/PasswordInput/index.d.ts +4 -0
- package/dist/PasswordInput/index.js +4 -0
- package/dist/PasswordInput/password-input.types.d.ts +18 -0
- package/dist/PasswordInput/password-input.types.js +1 -0
- package/dist/PasswordInput/password-input.variants.d.ts +57 -0
- package/dist/PasswordInput/password-input.variants.js +11 -0
- package/dist/Prose/Prose.svelte +13 -0
- package/dist/Prose/Prose.svelte.d.ts +4 -0
- package/dist/Prose/index.d.ts +4 -0
- package/dist/Prose/index.js +4 -0
- package/dist/Prose/prose.types.d.ts +22 -0
- package/dist/Prose/prose.types.js +1 -0
- package/dist/Prose/prose.variants.d.ts +45 -0
- package/dist/Prose/prose.variants.js +45 -0
- package/dist/Rating/Rating.svelte +93 -0
- package/dist/Rating/Rating.svelte.d.ts +4 -0
- package/dist/Rating/index.d.ts +4 -0
- package/dist/Rating/index.js +4 -0
- package/dist/Rating/rating.types.d.ts +59 -0
- package/dist/Rating/rating.types.js +1 -0
- package/dist/Rating/rating.variants.d.ts +93 -0
- package/dist/Rating/rating.variants.js +32 -0
- package/dist/Resizable/Resizable.svelte +9 -0
- package/dist/Resizable/Resizable.svelte.d.ts +4 -0
- package/dist/Resizable/index.d.ts +4 -0
- package/dist/Resizable/index.js +4 -0
- package/dist/Resizable/resizable.types.d.ts +18 -0
- package/dist/Resizable/resizable.types.js +1 -0
- package/dist/Resizable/resizable.variants.d.ts +48 -0
- package/dist/Resizable/resizable.variants.js +17 -0
- package/dist/ScrollArea/ScrollArea.svelte +54 -0
- package/dist/ScrollArea/ScrollArea.svelte.d.ts +4 -0
- package/dist/ScrollArea/index.d.ts +4 -0
- package/dist/ScrollArea/index.js +4 -0
- package/dist/ScrollArea/scroll-area.types.d.ts +27 -0
- package/dist/ScrollArea/scroll-area.types.js +1 -0
- package/dist/ScrollArea/scroll-area.variants.d.ts +45 -0
- package/dist/ScrollArea/scroll-area.variants.js +27 -0
- package/dist/SelectMenu/SelectMenu.svelte +46 -14
- package/dist/Sidebar/Sidebar.svelte +30 -0
- package/dist/Sidebar/Sidebar.svelte.d.ts +4 -0
- package/dist/Sidebar/index.d.ts +4 -0
- package/dist/Sidebar/index.js +4 -0
- package/dist/Sidebar/sidebar.types.d.ts +31 -0
- package/dist/Sidebar/sidebar.types.js +1 -0
- package/dist/Sidebar/sidebar.variants.d.ts +69 -0
- package/dist/Sidebar/sidebar.variants.js +23 -0
- package/dist/Spotlight/Spotlight.svelte +31 -0
- package/dist/Spotlight/Spotlight.svelte.d.ts +4 -0
- package/dist/Spotlight/index.d.ts +4 -0
- package/dist/Spotlight/index.js +4 -0
- package/dist/Spotlight/spotlight.types.d.ts +22 -0
- package/dist/Spotlight/spotlight.types.js +1 -0
- package/dist/Spotlight/spotlight.variants.d.ts +39 -0
- package/dist/Spotlight/spotlight.variants.js +8 -0
- package/dist/Stepper/Stepper.svelte +12 -9
- package/dist/TagsInput/TagsInput.svelte +100 -0
- package/dist/TagsInput/TagsInput.svelte.d.ts +4 -0
- package/dist/TagsInput/index.d.ts +4 -0
- package/dist/TagsInput/index.js +4 -0
- package/dist/TagsInput/tags-input.types.d.ts +32 -0
- package/dist/TagsInput/tags-input.types.js +1 -0
- package/dist/TagsInput/tags-input.variants.d.ts +45 -0
- package/dist/TagsInput/tags-input.variants.js +22 -0
- package/dist/TreeView/TreeView.svelte +95 -0
- package/dist/TreeView/TreeView.svelte.d.ts +4 -0
- package/dist/TreeView/index.d.ts +4 -0
- package/dist/TreeView/index.js +4 -0
- package/dist/TreeView/tree-view.types.d.ts +68 -0
- package/dist/TreeView/tree-view.types.js +1 -0
- package/dist/TreeView/tree-view.variants.d.ts +69 -0
- package/dist/TreeView/tree-view.variants.js +30 -0
- package/dist/docs/navigation.js +162 -0
- package/dist/hooks/index.d.ts +14 -0
- package/dist/hooks/index.js +9 -0
- package/dist/hooks/useDebouncedState.svelte.d.ts +30 -0
- package/dist/hooks/useDebouncedState.svelte.js +45 -0
- package/dist/hooks/useEventListener.svelte.d.ts +30 -0
- package/dist/hooks/useEventListener.svelte.js +16 -0
- package/dist/hooks/useFocusTrap.svelte.d.ts +42 -0
- package/dist/hooks/useFocusTrap.svelte.js +87 -0
- package/dist/hooks/useIntersectionObserver.svelte.d.ts +30 -0
- package/dist/hooks/useIntersectionObserver.svelte.js +46 -0
- package/dist/hooks/useLocalStorage.svelte.d.ts +39 -0
- package/dist/hooks/useLocalStorage.svelte.js +73 -0
- package/dist/hooks/useResizeObserver.svelte.d.ts +50 -0
- package/dist/hooks/useResizeObserver.svelte.js +71 -0
- package/dist/hooks/useScrollLock.svelte.d.ts +28 -0
- package/dist/hooks/useScrollLock.svelte.js +79 -0
- package/dist/hooks/useThrottle.svelte.d.ts +37 -0
- package/dist/hooks/useThrottle.svelte.js +72 -0
- package/dist/hooks/useTimers.svelte.d.ts +62 -0
- package/dist/hooks/useTimers.svelte.js +90 -0
- package/dist/hooks/utils.d.ts +1 -0
- package/dist/hooks/utils.js +3 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +18 -0
- package/dist/mcp/svelora-docs.data.json +59 -5
- package/package.json +8 -6
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script lang="ts">import { twMerge } from "tailwind-merge";
|
|
2
|
+
import { getContext } from "svelte";
|
|
3
|
+
import { listVariants } from "./list.variants.js";
|
|
4
|
+
let { title, description, interactive = false, disabled = false, href, target, class: className, leading, trailing, children, ...restProps } = $props();
|
|
5
|
+
// Get the parent list variant, default to 'default' if used outside a List
|
|
6
|
+
const getListVariant = getContext("list-variant");
|
|
7
|
+
let parentVariant = $derived(getListVariant ? getListVariant() : "default");
|
|
8
|
+
// Determine if it should be interactive automatically if it's a link
|
|
9
|
+
let isInteractive = $derived(interactive || !!href);
|
|
10
|
+
let styles = $derived(listVariants({
|
|
11
|
+
variant: parentVariant,
|
|
12
|
+
interactive: isInteractive,
|
|
13
|
+
disabled
|
|
14
|
+
}));
|
|
15
|
+
// Using svelte:element with conditional tags and spreading restProps causes TS errors.
|
|
16
|
+
// We use a snippet to keep the markup DRY while using explicit if/else tags.
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
{#snippet contentWrapper()}
|
|
20
|
+
{#if leading}
|
|
21
|
+
<div class={styles.leading()}>
|
|
22
|
+
{@render leading()}
|
|
23
|
+
</div>
|
|
24
|
+
{/if}
|
|
25
|
+
|
|
26
|
+
<div class={styles.itemContent()}>
|
|
27
|
+
{#if children}
|
|
28
|
+
{@render children()}
|
|
29
|
+
{:else}
|
|
30
|
+
{#if title}
|
|
31
|
+
<div class={styles.itemTitle()}>{title}</div>
|
|
32
|
+
{/if}
|
|
33
|
+
{#if description}
|
|
34
|
+
<div class={styles.itemDescription()}>{description}</div>
|
|
35
|
+
{/if}
|
|
36
|
+
{/if}
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
{#if trailing}
|
|
40
|
+
<div class={styles.trailing()}>
|
|
41
|
+
{@render trailing()}
|
|
42
|
+
</div>
|
|
43
|
+
{/if}
|
|
44
|
+
{/snippet}
|
|
45
|
+
|
|
46
|
+
<li>
|
|
47
|
+
{#if href}
|
|
48
|
+
<a
|
|
49
|
+
{href}
|
|
50
|
+
{target}
|
|
51
|
+
class={twMerge(styles.item(), className)}
|
|
52
|
+
{...restProps as any}
|
|
53
|
+
>
|
|
54
|
+
{@render contentWrapper()}
|
|
55
|
+
</a>
|
|
56
|
+
{:else}
|
|
57
|
+
<div
|
|
58
|
+
class={twMerge(styles.item(), className)}
|
|
59
|
+
{...restProps as any}
|
|
60
|
+
>
|
|
61
|
+
{@render contentWrapper()}
|
|
62
|
+
</div>
|
|
63
|
+
{/if}
|
|
64
|
+
</li>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes, HTMLLiAttributes } from 'svelte/elements';
|
|
3
|
+
import type { ListVariantProps } from './list.variants.js';
|
|
4
|
+
export interface ListProps extends HTMLAttributes<HTMLUListElement> {
|
|
5
|
+
/**
|
|
6
|
+
* The variant of the list.
|
|
7
|
+
* @default 'default'
|
|
8
|
+
*/
|
|
9
|
+
variant?: ListVariantProps['variant'];
|
|
10
|
+
/**
|
|
11
|
+
* Additional CSS classes.
|
|
12
|
+
*/
|
|
13
|
+
class?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Content of the list.
|
|
16
|
+
*/
|
|
17
|
+
children?: Snippet;
|
|
18
|
+
}
|
|
19
|
+
export interface ListItemProps extends HTMLLiAttributes {
|
|
20
|
+
/**
|
|
21
|
+
* Title of the list item.
|
|
22
|
+
*/
|
|
23
|
+
title?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Description below the title.
|
|
26
|
+
*/
|
|
27
|
+
description?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Whether the item is interactive (hover/active states).
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
32
|
+
interactive?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Whether the item is disabled.
|
|
35
|
+
* @default false
|
|
36
|
+
*/
|
|
37
|
+
disabled?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Optional href. If provided, the item renders as an anchor tag `<a>`.
|
|
40
|
+
*/
|
|
41
|
+
href?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Target attribute for the anchor tag if `href` is provided.
|
|
44
|
+
*/
|
|
45
|
+
target?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Additional CSS classes.
|
|
48
|
+
*/
|
|
49
|
+
class?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Snippet for the leading section (e.g., Avatar, Icon).
|
|
52
|
+
*/
|
|
53
|
+
leading?: Snippet;
|
|
54
|
+
/**
|
|
55
|
+
* Snippet for the trailing section (e.g., Badge, Chevron, Switch).
|
|
56
|
+
*/
|
|
57
|
+
trailing?: Snippet;
|
|
58
|
+
/**
|
|
59
|
+
* Snippet to replace the default title/description content completely.
|
|
60
|
+
*/
|
|
61
|
+
children?: Snippet;
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { type VariantProps } from 'tailwind-variants';
|
|
2
|
+
export declare const listVariants: import("tailwind-variants").TVReturnType<{
|
|
3
|
+
variant: {
|
|
4
|
+
default: {
|
|
5
|
+
base: string;
|
|
6
|
+
};
|
|
7
|
+
bordered: {
|
|
8
|
+
base: string;
|
|
9
|
+
item: string;
|
|
10
|
+
};
|
|
11
|
+
separated: {
|
|
12
|
+
base: string;
|
|
13
|
+
item: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
interactive: {
|
|
17
|
+
true: {
|
|
18
|
+
item: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
disabled: {
|
|
22
|
+
true: {
|
|
23
|
+
item: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
}, {
|
|
27
|
+
base: string;
|
|
28
|
+
item: string;
|
|
29
|
+
itemContent: string;
|
|
30
|
+
itemTitle: string;
|
|
31
|
+
itemDescription: string;
|
|
32
|
+
leading: string;
|
|
33
|
+
trailing: string;
|
|
34
|
+
}, undefined, {
|
|
35
|
+
variant: {
|
|
36
|
+
default: {
|
|
37
|
+
base: string;
|
|
38
|
+
};
|
|
39
|
+
bordered: {
|
|
40
|
+
base: string;
|
|
41
|
+
item: string;
|
|
42
|
+
};
|
|
43
|
+
separated: {
|
|
44
|
+
base: string;
|
|
45
|
+
item: string;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
interactive: {
|
|
49
|
+
true: {
|
|
50
|
+
item: string;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
disabled: {
|
|
54
|
+
true: {
|
|
55
|
+
item: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
}, {
|
|
59
|
+
base: string;
|
|
60
|
+
item: string;
|
|
61
|
+
itemContent: string;
|
|
62
|
+
itemTitle: string;
|
|
63
|
+
itemDescription: string;
|
|
64
|
+
leading: string;
|
|
65
|
+
trailing: string;
|
|
66
|
+
}, import("tailwind-variants").TVReturnType<{
|
|
67
|
+
variant: {
|
|
68
|
+
default: {
|
|
69
|
+
base: string;
|
|
70
|
+
};
|
|
71
|
+
bordered: {
|
|
72
|
+
base: string;
|
|
73
|
+
item: string;
|
|
74
|
+
};
|
|
75
|
+
separated: {
|
|
76
|
+
base: string;
|
|
77
|
+
item: string;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
interactive: {
|
|
81
|
+
true: {
|
|
82
|
+
item: string;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
disabled: {
|
|
86
|
+
true: {
|
|
87
|
+
item: string;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
}, {
|
|
91
|
+
base: string;
|
|
92
|
+
item: string;
|
|
93
|
+
itemContent: string;
|
|
94
|
+
itemTitle: string;
|
|
95
|
+
itemDescription: string;
|
|
96
|
+
leading: string;
|
|
97
|
+
trailing: string;
|
|
98
|
+
}, undefined, unknown, unknown, undefined>>;
|
|
99
|
+
export type ListVariantProps = VariantProps<typeof listVariants>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const listVariants = tv({
|
|
3
|
+
slots: {
|
|
4
|
+
base: 'flex flex-col w-full text-surface-900 dark:text-surface-50',
|
|
5
|
+
item: 'flex items-center justify-between w-full px-4 py-3',
|
|
6
|
+
itemContent: 'flex flex-col flex-1 min-w-0',
|
|
7
|
+
itemTitle: 'text-sm font-medium truncate',
|
|
8
|
+
itemDescription: 'text-xs text-surface-500 dark:text-surface-400 truncate mt-0.5',
|
|
9
|
+
leading: 'mr-3 shrink-0 flex items-center justify-center',
|
|
10
|
+
trailing: 'ml-3 shrink-0 flex items-center justify-center text-surface-500 dark:text-surface-400'
|
|
11
|
+
},
|
|
12
|
+
variants: {
|
|
13
|
+
variant: {
|
|
14
|
+
default: {
|
|
15
|
+
base: ''
|
|
16
|
+
},
|
|
17
|
+
bordered: {
|
|
18
|
+
base: 'border border-outline-variant rounded-lg overflow-hidden',
|
|
19
|
+
item: 'border-b border-outline-variant last:border-b-0'
|
|
20
|
+
},
|
|
21
|
+
separated: {
|
|
22
|
+
base: 'gap-2',
|
|
23
|
+
item: 'rounded-lg border border-outline-variant'
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
interactive: {
|
|
27
|
+
true: {
|
|
28
|
+
item: 'transition-colors hover:bg-surface-100 dark:hover:bg-surface-800 cursor-pointer active:bg-surface-200 dark:active:bg-surface-700'
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
disabled: {
|
|
32
|
+
true: {
|
|
33
|
+
item: 'opacity-50 cursor-not-allowed hover:bg-transparent dark:hover:bg-transparent active:bg-transparent dark:active:bg-transparent'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
variant: 'default',
|
|
39
|
+
interactive: false,
|
|
40
|
+
disabled: false
|
|
41
|
+
}
|
|
42
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script lang="ts">import { twMerge } from "tailwind-merge";
|
|
2
|
+
import { marqueeVariants } from "./marquee.variants.js";
|
|
3
|
+
let { direction = "left", pauseOnHover = false, duration = "40s", gap = "1rem", repeat = 2, class: className, children, ...restProps } = $props();
|
|
4
|
+
let styles = $derived(marqueeVariants({
|
|
5
|
+
direction,
|
|
6
|
+
pauseOnHover
|
|
7
|
+
}));
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<div
|
|
11
|
+
class={twMerge(styles.root() as string, className)}
|
|
12
|
+
style:--gap={gap}
|
|
13
|
+
style:--duration={duration}
|
|
14
|
+
{...restProps}
|
|
15
|
+
>
|
|
16
|
+
{#each Array(Math.max(2, repeat)) as _}
|
|
17
|
+
<div class={styles.content() as string}>
|
|
18
|
+
{@render children?.()}
|
|
19
|
+
</div>
|
|
20
|
+
{/each}
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<style>
|
|
24
|
+
/* Injected keyframes for marquee animation since it might not be in tailwind config */
|
|
25
|
+
:global(.animate-marquee) {
|
|
26
|
+
animation: marquee var(--duration) linear infinite;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
:global(.animate-marquee-vertical) {
|
|
30
|
+
animation: marquee-vertical var(--duration) linear infinite;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@keyframes marquee {
|
|
34
|
+
0% {
|
|
35
|
+
transform: translateX(0);
|
|
36
|
+
}
|
|
37
|
+
100% {
|
|
38
|
+
transform: translateX(calc(-100% - var(--gap)));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@keyframes marquee-vertical {
|
|
43
|
+
0% {
|
|
44
|
+
transform: translateY(0);
|
|
45
|
+
}
|
|
46
|
+
100% {
|
|
47
|
+
transform: translateY(calc(-100% - var(--gap)));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import type { MarqueeVariantProps } from './marquee.variants.js';
|
|
4
|
+
export interface MarqueeProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
/**
|
|
6
|
+
* Direction of the marquee animation.
|
|
7
|
+
* @default 'left'
|
|
8
|
+
*/
|
|
9
|
+
direction?: MarqueeVariantProps['direction'];
|
|
10
|
+
/**
|
|
11
|
+
* Whether to pause the animation when hovered.
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
pauseOnHover?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Duration of the animation loop (e.g. '20s', '40s').
|
|
17
|
+
* @default '40s'
|
|
18
|
+
*/
|
|
19
|
+
duration?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Gap between items.
|
|
22
|
+
* @default '1rem'
|
|
23
|
+
*/
|
|
24
|
+
gap?: string;
|
|
25
|
+
/**
|
|
26
|
+
* How many times to repeat the content. To ensure smooth looping, it should be at least 2.
|
|
27
|
+
* @default 2
|
|
28
|
+
*/
|
|
29
|
+
repeat?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Additional CSS classes.
|
|
32
|
+
*/
|
|
33
|
+
class?: string;
|
|
34
|
+
/**
|
|
35
|
+
* The content to scroll.
|
|
36
|
+
*/
|
|
37
|
+
children?: Snippet;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type VariantProps } from 'tailwind-variants';
|
|
2
|
+
export declare const marqueeVariants: import("tailwind-variants").TVReturnType<{
|
|
3
|
+
direction: {
|
|
4
|
+
left: {
|
|
5
|
+
content: string;
|
|
6
|
+
};
|
|
7
|
+
right: {
|
|
8
|
+
content: string;
|
|
9
|
+
};
|
|
10
|
+
up: {
|
|
11
|
+
root: string;
|
|
12
|
+
content: string;
|
|
13
|
+
};
|
|
14
|
+
down: {
|
|
15
|
+
root: string;
|
|
16
|
+
content: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
pauseOnHover: {
|
|
20
|
+
true: {
|
|
21
|
+
content: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
}, {
|
|
25
|
+
root: string;
|
|
26
|
+
content: string;
|
|
27
|
+
}, undefined, {
|
|
28
|
+
direction: {
|
|
29
|
+
left: {
|
|
30
|
+
content: string;
|
|
31
|
+
};
|
|
32
|
+
right: {
|
|
33
|
+
content: string;
|
|
34
|
+
};
|
|
35
|
+
up: {
|
|
36
|
+
root: string;
|
|
37
|
+
content: string;
|
|
38
|
+
};
|
|
39
|
+
down: {
|
|
40
|
+
root: string;
|
|
41
|
+
content: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
pauseOnHover: {
|
|
45
|
+
true: {
|
|
46
|
+
content: string;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
}, {
|
|
50
|
+
root: string;
|
|
51
|
+
content: string;
|
|
52
|
+
}, import("tailwind-variants").TVReturnType<{
|
|
53
|
+
direction: {
|
|
54
|
+
left: {
|
|
55
|
+
content: string;
|
|
56
|
+
};
|
|
57
|
+
right: {
|
|
58
|
+
content: string;
|
|
59
|
+
};
|
|
60
|
+
up: {
|
|
61
|
+
root: string;
|
|
62
|
+
content: string;
|
|
63
|
+
};
|
|
64
|
+
down: {
|
|
65
|
+
root: string;
|
|
66
|
+
content: string;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
pauseOnHover: {
|
|
70
|
+
true: {
|
|
71
|
+
content: string;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
}, {
|
|
75
|
+
root: string;
|
|
76
|
+
content: string;
|
|
77
|
+
}, undefined, unknown, unknown, undefined>>;
|
|
78
|
+
export type MarqueeVariantProps = VariantProps<typeof marqueeVariants>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const marqueeVariants = tv({
|
|
3
|
+
slots: {
|
|
4
|
+
root: 'group flex overflow-hidden p-2 [--gap:1rem] [gap:var(--gap)]',
|
|
5
|
+
content: 'flex shrink-0 justify-around [gap:var(--gap)] animate-marquee'
|
|
6
|
+
},
|
|
7
|
+
variants: {
|
|
8
|
+
direction: {
|
|
9
|
+
left: { content: '[animation-direction:normal]' },
|
|
10
|
+
right: { content: '[animation-direction:reverse]' },
|
|
11
|
+
up: {
|
|
12
|
+
root: 'flex-col',
|
|
13
|
+
content: 'flex-col animate-marquee-vertical [animation-direction:normal]'
|
|
14
|
+
},
|
|
15
|
+
down: {
|
|
16
|
+
root: 'flex-col',
|
|
17
|
+
content: 'flex-col animate-marquee-vertical [animation-direction:reverse]'
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
pauseOnHover: {
|
|
21
|
+
true: { content: 'group-hover:[animation-play-state:paused]' }
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
direction: 'left',
|
|
26
|
+
pauseOnHover: false
|
|
27
|
+
}
|
|
28
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<script lang="ts">import { twMerge } from "tailwind-merge";
|
|
2
|
+
import Icon from "../Icon/Icon.svelte";
|
|
3
|
+
import { menuVariants } from "./menu.variants.js";
|
|
4
|
+
let { items = [], variant = "default", accordion = false, autoActive = false, class: className, children } = $props();
|
|
5
|
+
let styles = $derived(menuVariants({ variant }));
|
|
6
|
+
// Track open state for groups
|
|
7
|
+
let openGroupLabel = $state(null);
|
|
8
|
+
let openGroups = $state(new Set());
|
|
9
|
+
// Initialize open groups based on prop
|
|
10
|
+
$effect(() => {
|
|
11
|
+
if (!accordion) {
|
|
12
|
+
items.forEach((item) => {
|
|
13
|
+
if (item.type === "group" && item.open && item.label) {
|
|
14
|
+
openGroups.add(item.label);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
openGroups = new Set(openGroups);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
function handleGroupToggle(groupItem) {
|
|
21
|
+
if (accordion) {
|
|
22
|
+
if (openGroupLabel === groupItem.label) {
|
|
23
|
+
openGroupLabel = null;
|
|
24
|
+
} else {
|
|
25
|
+
openGroupLabel = groupItem.label || null;
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
toggleGroup(groupItem);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function toggleGroup(groupItem) {
|
|
32
|
+
if (!groupItem.label) return;
|
|
33
|
+
if (openGroups.has(groupItem.label)) {
|
|
34
|
+
openGroups.delete(groupItem.label);
|
|
35
|
+
} else {
|
|
36
|
+
openGroups.add(groupItem.label);
|
|
37
|
+
}
|
|
38
|
+
openGroups = new Set(openGroups);
|
|
39
|
+
}
|
|
40
|
+
function isGroupOpen(groupItem) {
|
|
41
|
+
if (accordion) {
|
|
42
|
+
return openGroupLabel === groupItem.label;
|
|
43
|
+
}
|
|
44
|
+
if (!groupItem.label) return false;
|
|
45
|
+
return openGroups.has(groupItem.label);
|
|
46
|
+
}
|
|
47
|
+
// Auto active logic
|
|
48
|
+
let currentPath = $state("");
|
|
49
|
+
$effect(() => {
|
|
50
|
+
if (autoActive && typeof window !== "undefined") {
|
|
51
|
+
currentPath = window.location.pathname;
|
|
52
|
+
// Optionally listen to popstate for SPA navigation if not using SvelteKit stores
|
|
53
|
+
const onPopState = () => {
|
|
54
|
+
currentPath = window.location.pathname;
|
|
55
|
+
};
|
|
56
|
+
window.addEventListener("popstate", onPopState);
|
|
57
|
+
return () => window.removeEventListener("popstate", onPopState);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
function isActive(item) {
|
|
61
|
+
if (item.active) return true;
|
|
62
|
+
if (autoActive && item.type !== "group" && item.href) {
|
|
63
|
+
return currentPath === item.href || currentPath.startsWith(item.href + "/");
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
{#snippet renderActionItem(item: MenuItemType)}
|
|
70
|
+
<li>
|
|
71
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
72
|
+
<svelte:element
|
|
73
|
+
this={item.type !== 'group' && item.href ? 'a' : 'button'}
|
|
74
|
+
href={item.type !== 'group' ? item.href : undefined}
|
|
75
|
+
type={item.type !== 'group' && !item.href ? 'button' : undefined}
|
|
76
|
+
target={item.type !== 'group' ? item.target : undefined}
|
|
77
|
+
class={twMerge(styles.item(), isActive(item) ? styles.itemActive() : '', item.class)}
|
|
78
|
+
disabled={item.disabled}
|
|
79
|
+
onclick={item.type !== 'group' ? item.onClick : undefined}
|
|
80
|
+
>
|
|
81
|
+
{#if item.icon}
|
|
82
|
+
<Icon name={item.icon} class={styles.icon()} />
|
|
83
|
+
{/if}
|
|
84
|
+
<span class="truncate">{item.label}</span>
|
|
85
|
+
</svelte:element>
|
|
86
|
+
</li>
|
|
87
|
+
{/snippet}
|
|
88
|
+
|
|
89
|
+
{#snippet renderGroupItem(item: MenuGroupItem)}
|
|
90
|
+
<li class={styles.group()}>
|
|
91
|
+
<button
|
|
92
|
+
type="button"
|
|
93
|
+
class={twMerge(styles.groupTrigger(), isGroupOpen(item) ? styles.groupTriggerActive() : '', item.class)}
|
|
94
|
+
disabled={item.disabled}
|
|
95
|
+
onclick={() => handleGroupToggle(item)}
|
|
96
|
+
>
|
|
97
|
+
<div class="flex items-center truncate">
|
|
98
|
+
{#if item.icon}
|
|
99
|
+
<Icon name={item.icon} class={styles.icon()} />
|
|
100
|
+
{/if}
|
|
101
|
+
<span class="truncate">{item.label}</span>
|
|
102
|
+
</div>
|
|
103
|
+
<Icon
|
|
104
|
+
name="lucide:chevron-down"
|
|
105
|
+
class={twMerge(styles.chevron(), isGroupOpen(item) ? 'rotate-180' : '')}
|
|
106
|
+
/>
|
|
107
|
+
</button>
|
|
108
|
+
{#if isGroupOpen(item)}
|
|
109
|
+
<ul class={styles.groupContent()}>
|
|
110
|
+
{#each item.items as subItem}
|
|
111
|
+
{#if subItem.type === 'group'}
|
|
112
|
+
{@render renderGroupItem(subItem)}
|
|
113
|
+
{:else}
|
|
114
|
+
{@render renderActionItem(subItem)}
|
|
115
|
+
{/if}
|
|
116
|
+
{/each}
|
|
117
|
+
</ul>
|
|
118
|
+
{/if}
|
|
119
|
+
</li>
|
|
120
|
+
{/snippet}
|
|
121
|
+
|
|
122
|
+
<ul class={twMerge(styles.base(), className)}>
|
|
123
|
+
{#if children}
|
|
124
|
+
{@render children()}
|
|
125
|
+
{:else}
|
|
126
|
+
{#each items as item}
|
|
127
|
+
{#if item.type === 'group'}
|
|
128
|
+
{@render renderGroupItem(item)}
|
|
129
|
+
{:else}
|
|
130
|
+
{@render renderActionItem(item)}
|
|
131
|
+
{/if}
|
|
132
|
+
{/each}
|
|
133
|
+
{/if}
|
|
134
|
+
</ul>
|