svelora 3.0.6 → 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.
Files changed (157) hide show
  1. package/dist/BentoGrid/BentoCard.svelte +45 -0
  2. package/dist/BentoGrid/BentoCard.svelte.d.ts +4 -0
  3. package/dist/BentoGrid/BentoGrid.svelte +9 -0
  4. package/dist/BentoGrid/BentoGrid.svelte.d.ts +4 -0
  5. package/dist/BentoGrid/bento-grid.types.d.ts +47 -0
  6. package/dist/BentoGrid/bento-grid.types.js +1 -0
  7. package/dist/BentoGrid/bento-grid.variants.d.ts +30 -0
  8. package/dist/BentoGrid/bento-grid.variants.js +16 -0
  9. package/dist/BentoGrid/index.d.ts +5 -0
  10. package/dist/BentoGrid/index.js +5 -0
  11. package/dist/Chart/Chart.svelte +47 -0
  12. package/dist/Chart/Chart.svelte.d.ts +4 -0
  13. package/dist/Chart/chart.types.d.ts +20 -0
  14. package/dist/Chart/chart.types.js +1 -0
  15. package/dist/Chart/chart.variants.d.ts +3 -0
  16. package/dist/Chart/chart.variants.js +4 -0
  17. package/dist/Chart/index.d.ts +4 -0
  18. package/dist/Chart/index.js +4 -0
  19. package/dist/Chat/ChatBubble.svelte +30 -0
  20. package/dist/Chat/ChatBubble.svelte.d.ts +4 -0
  21. package/dist/Chat/ChatInput.svelte +50 -0
  22. package/dist/Chat/ChatInput.svelte.d.ts +4 -0
  23. package/dist/Chat/ChatMessage.svelte +15 -0
  24. package/dist/Chat/ChatMessage.svelte.d.ts +4 -0
  25. package/dist/Chat/chat.types.d.ts +63 -0
  26. package/dist/Chat/chat.types.js +1 -0
  27. package/dist/Chat/chat.variants.d.ts +117 -0
  28. package/dist/Chat/chat.variants.js +47 -0
  29. package/dist/Chat/index.d.ts +6 -0
  30. package/dist/Chat/index.js +6 -0
  31. package/dist/ColorPicker/ColorPicker.svelte +109 -0
  32. package/dist/ColorPicker/ColorPicker.svelte.d.ts +4 -0
  33. package/dist/ColorPicker/color-picker.types.d.ts +26 -0
  34. package/dist/ColorPicker/color-picker.types.js +1 -0
  35. package/dist/ColorPicker/color-picker.variants.d.ts +69 -0
  36. package/dist/ColorPicker/color-picker.variants.js +13 -0
  37. package/dist/ColorPicker/index.d.ts +4 -0
  38. package/dist/ColorPicker/index.js +4 -0
  39. package/dist/DateRangePicker/DateRangePicker.svelte +59 -0
  40. package/dist/DateRangePicker/DateRangePicker.svelte.d.ts +4 -0
  41. package/dist/DateRangePicker/date-range-picker.types.d.ts +34 -0
  42. package/dist/DateRangePicker/date-range-picker.types.js +1 -0
  43. package/dist/DateRangePicker/date-range-picker.variants.d.ts +39 -0
  44. package/dist/DateRangePicker/date-range-picker.variants.js +20 -0
  45. package/dist/DateRangePicker/index.d.ts +4 -0
  46. package/dist/DateRangePicker/index.js +4 -0
  47. package/dist/List/List.svelte +14 -0
  48. package/dist/List/List.svelte.d.ts +4 -0
  49. package/dist/List/ListItem.svelte +64 -0
  50. package/dist/List/ListItem.svelte.d.ts +4 -0
  51. package/dist/List/index.d.ts +5 -0
  52. package/dist/List/index.js +5 -0
  53. package/dist/List/list.types.d.ts +62 -0
  54. package/dist/List/list.types.js +1 -0
  55. package/dist/List/list.variants.d.ts +99 -0
  56. package/dist/List/list.variants.js +42 -0
  57. package/dist/Marquee/Marquee.svelte +50 -0
  58. package/dist/Marquee/Marquee.svelte.d.ts +4 -0
  59. package/dist/Marquee/index.d.ts +4 -0
  60. package/dist/Marquee/index.js +4 -0
  61. package/dist/Marquee/marquee.types.d.ts +38 -0
  62. package/dist/Marquee/marquee.types.js +1 -0
  63. package/dist/Marquee/marquee.variants.d.ts +78 -0
  64. package/dist/Marquee/marquee.variants.js +28 -0
  65. package/dist/Menu/Menu.svelte +134 -0
  66. package/dist/Menu/Menu.svelte.d.ts +4 -0
  67. package/dist/Menu/index.d.ts +4 -0
  68. package/dist/Menu/index.js +4 -0
  69. package/dist/Menu/menu.types.d.ts +82 -0
  70. package/dist/Menu/menu.types.js +1 -0
  71. package/dist/Menu/menu.variants.d.ts +46 -0
  72. package/dist/Menu/menu.variants.js +32 -0
  73. package/dist/NumberTicker/NumberTicker.svelte +59 -0
  74. package/dist/NumberTicker/NumberTicker.svelte.d.ts +4 -0
  75. package/dist/NumberTicker/index.d.ts +4 -0
  76. package/dist/NumberTicker/index.js +4 -0
  77. package/dist/NumberTicker/number-ticker.types.d.ts +26 -0
  78. package/dist/NumberTicker/number-ticker.types.js +1 -0
  79. package/dist/NumberTicker/number-ticker.variants.d.ts +27 -0
  80. package/dist/NumberTicker/number-ticker.variants.js +6 -0
  81. package/dist/PasswordInput/PasswordInput.svelte +74 -0
  82. package/dist/PasswordInput/PasswordInput.svelte.d.ts +4 -0
  83. package/dist/PasswordInput/index.d.ts +4 -0
  84. package/dist/PasswordInput/index.js +4 -0
  85. package/dist/PasswordInput/password-input.types.d.ts +18 -0
  86. package/dist/PasswordInput/password-input.types.js +1 -0
  87. package/dist/PasswordInput/password-input.variants.d.ts +57 -0
  88. package/dist/PasswordInput/password-input.variants.js +11 -0
  89. package/dist/Prose/Prose.svelte +13 -0
  90. package/dist/Prose/Prose.svelte.d.ts +4 -0
  91. package/dist/Prose/index.d.ts +4 -0
  92. package/dist/Prose/index.js +4 -0
  93. package/dist/Prose/prose.types.d.ts +22 -0
  94. package/dist/Prose/prose.types.js +1 -0
  95. package/dist/Prose/prose.variants.d.ts +45 -0
  96. package/dist/Prose/prose.variants.js +45 -0
  97. package/dist/Rating/Rating.svelte +93 -0
  98. package/dist/Rating/Rating.svelte.d.ts +4 -0
  99. package/dist/Rating/index.d.ts +4 -0
  100. package/dist/Rating/index.js +4 -0
  101. package/dist/Rating/rating.types.d.ts +59 -0
  102. package/dist/Rating/rating.types.js +1 -0
  103. package/dist/Rating/rating.variants.d.ts +93 -0
  104. package/dist/Rating/rating.variants.js +32 -0
  105. package/dist/Resizable/Resizable.svelte +9 -0
  106. package/dist/Resizable/Resizable.svelte.d.ts +4 -0
  107. package/dist/Resizable/index.d.ts +4 -0
  108. package/dist/Resizable/index.js +4 -0
  109. package/dist/Resizable/resizable.types.d.ts +18 -0
  110. package/dist/Resizable/resizable.types.js +1 -0
  111. package/dist/Resizable/resizable.variants.d.ts +48 -0
  112. package/dist/Resizable/resizable.variants.js +17 -0
  113. package/dist/ScrollArea/ScrollArea.svelte +54 -0
  114. package/dist/ScrollArea/ScrollArea.svelte.d.ts +4 -0
  115. package/dist/ScrollArea/index.d.ts +4 -0
  116. package/dist/ScrollArea/index.js +4 -0
  117. package/dist/ScrollArea/scroll-area.types.d.ts +27 -0
  118. package/dist/ScrollArea/scroll-area.types.js +1 -0
  119. package/dist/ScrollArea/scroll-area.variants.d.ts +45 -0
  120. package/dist/ScrollArea/scroll-area.variants.js +27 -0
  121. package/dist/Sidebar/Sidebar.svelte +30 -0
  122. package/dist/Sidebar/Sidebar.svelte.d.ts +4 -0
  123. package/dist/Sidebar/index.d.ts +4 -0
  124. package/dist/Sidebar/index.js +4 -0
  125. package/dist/Sidebar/sidebar.types.d.ts +31 -0
  126. package/dist/Sidebar/sidebar.types.js +1 -0
  127. package/dist/Sidebar/sidebar.variants.d.ts +69 -0
  128. package/dist/Sidebar/sidebar.variants.js +23 -0
  129. package/dist/Spotlight/Spotlight.svelte +31 -0
  130. package/dist/Spotlight/Spotlight.svelte.d.ts +4 -0
  131. package/dist/Spotlight/index.d.ts +4 -0
  132. package/dist/Spotlight/index.js +4 -0
  133. package/dist/Spotlight/spotlight.types.d.ts +22 -0
  134. package/dist/Spotlight/spotlight.types.js +1 -0
  135. package/dist/Spotlight/spotlight.variants.d.ts +39 -0
  136. package/dist/Spotlight/spotlight.variants.js +8 -0
  137. package/dist/TagsInput/TagsInput.svelte +100 -0
  138. package/dist/TagsInput/TagsInput.svelte.d.ts +4 -0
  139. package/dist/TagsInput/index.d.ts +4 -0
  140. package/dist/TagsInput/index.js +4 -0
  141. package/dist/TagsInput/tags-input.types.d.ts +32 -0
  142. package/dist/TagsInput/tags-input.types.js +1 -0
  143. package/dist/TagsInput/tags-input.variants.d.ts +45 -0
  144. package/dist/TagsInput/tags-input.variants.js +22 -0
  145. package/dist/TreeView/TreeView.svelte +95 -0
  146. package/dist/TreeView/TreeView.svelte.d.ts +4 -0
  147. package/dist/TreeView/index.d.ts +4 -0
  148. package/dist/TreeView/index.js +4 -0
  149. package/dist/TreeView/tree-view.types.d.ts +68 -0
  150. package/dist/TreeView/tree-view.types.js +1 -0
  151. package/dist/TreeView/tree-view.variants.d.ts +69 -0
  152. package/dist/TreeView/tree-view.variants.js +30 -0
  153. package/dist/docs/navigation.js +108 -0
  154. package/dist/index.d.ts +18 -0
  155. package/dist/index.js +18 -0
  156. package/dist/mcp/svelora-docs.data.json +39 -3
  157. package/package.json +8 -6
@@ -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,4 @@
1
+ import type { MarqueeProps } from './marquee.types.js';
2
+ declare const Marquee: import("svelte").Component<MarqueeProps, {}, "">;
3
+ type Marquee = ReturnType<typeof Marquee>;
4
+ export default Marquee;
@@ -0,0 +1,4 @@
1
+ import Marquee from './Marquee.svelte';
2
+ export { Marquee };
3
+ export * from './marquee.types.js';
4
+ export * from './marquee.variants.js';
@@ -0,0 +1,4 @@
1
+ import Marquee from './Marquee.svelte';
2
+ export { Marquee };
3
+ export * from './marquee.types.js';
4
+ export * from './marquee.variants.js';
@@ -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>
@@ -0,0 +1,4 @@
1
+ import type { MenuProps } from './menu.types.js';
2
+ declare const Menu: import("svelte").Component<MenuProps, {}, "">;
3
+ type Menu = ReturnType<typeof Menu>;
4
+ export default Menu;
@@ -0,0 +1,4 @@
1
+ import Menu from './Menu.svelte';
2
+ export { Menu };
3
+ export * from './menu.types.js';
4
+ export * from './menu.variants.js';
@@ -0,0 +1,4 @@
1
+ import Menu from './Menu.svelte';
2
+ export { Menu };
3
+ export * from './menu.types.js';
4
+ export * from './menu.variants.js';
@@ -0,0 +1,82 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { ClassNameValue } from 'tailwind-merge';
3
+ import type { MenuVariantProps } from './menu.variants.js';
4
+ export interface MenuItemBase {
5
+ /**
6
+ * Text to display in the menu item.
7
+ */
8
+ label?: string;
9
+ /**
10
+ * Icon to display before the label.
11
+ */
12
+ icon?: string;
13
+ /**
14
+ * Whether the menu item is disabled.
15
+ */
16
+ disabled?: boolean;
17
+ /**
18
+ * Whether the menu item is active/selected.
19
+ */
20
+ active?: boolean;
21
+ /**
22
+ * Additional CSS classes.
23
+ */
24
+ class?: ClassNameValue;
25
+ }
26
+ export interface MenuActionItem extends MenuItemBase {
27
+ type?: 'action' | 'item';
28
+ /**
29
+ * The URL to navigate to when the item is clicked.
30
+ */
31
+ href?: string;
32
+ /**
33
+ * Click handler for the item.
34
+ */
35
+ onClick?: (event: MouseEvent) => void;
36
+ /**
37
+ * Target attribute for link items.
38
+ */
39
+ target?: string;
40
+ }
41
+ export interface MenuGroupItem extends MenuItemBase {
42
+ type: 'group';
43
+ /**
44
+ * Child items to display when the group is expanded.
45
+ */
46
+ items: MenuItems;
47
+ /**
48
+ * Whether the group is currently open/expanded.
49
+ */
50
+ open?: boolean;
51
+ }
52
+ export type MenuItemType = MenuActionItem | MenuGroupItem;
53
+ export type MenuItems = MenuItemType[];
54
+ export interface MenuProps {
55
+ /**
56
+ * The array of menu items to render.
57
+ */
58
+ items?: MenuItems;
59
+ /**
60
+ * Style variant of the menu.
61
+ */
62
+ variant?: MenuVariantProps['variant'];
63
+ /**
64
+ * Whether the menu allows multiple groups to be open at once (false)
65
+ * or acts as an accordion, closing other groups when one opens (true).
66
+ * @default false
67
+ */
68
+ accordion?: boolean;
69
+ /**
70
+ * Auto-detect active state from current URL if using SvelteKit.
71
+ * @default false
72
+ */
73
+ autoActive?: boolean;
74
+ /**
75
+ * Additional CSS classes.
76
+ */
77
+ class?: ClassNameValue;
78
+ /**
79
+ * Custom slot for completely custom rendering of items.
80
+ */
81
+ children?: Snippet;
82
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ import { type VariantProps } from 'tailwind-variants';
2
+ export declare const menuVariants: import("tailwind-variants").TVReturnType<{
3
+ variant: {
4
+ default: {};
5
+ };
6
+ }, {
7
+ base: string;
8
+ group: string;
9
+ groupTrigger: string[];
10
+ groupTriggerActive: string;
11
+ groupContent: string;
12
+ item: string[];
13
+ itemActive: string;
14
+ icon: string;
15
+ chevron: string;
16
+ }, undefined, {
17
+ variant: {
18
+ default: {};
19
+ };
20
+ }, {
21
+ base: string;
22
+ group: string;
23
+ groupTrigger: string[];
24
+ groupTriggerActive: string;
25
+ groupContent: string;
26
+ item: string[];
27
+ itemActive: string;
28
+ icon: string;
29
+ chevron: string;
30
+ }, import("tailwind-variants").TVReturnType<{
31
+ variant: {
32
+ default: {};
33
+ };
34
+ }, {
35
+ base: string;
36
+ group: string;
37
+ groupTrigger: string[];
38
+ groupTriggerActive: string;
39
+ groupContent: string;
40
+ item: string[];
41
+ itemActive: string;
42
+ icon: string;
43
+ chevron: string;
44
+ }, undefined, unknown, unknown, undefined>>;
45
+ export type MenuVariantProps = VariantProps<typeof menuVariants>;
46
+ export type MenuSlots = keyof typeof menuVariants.slots;
@@ -0,0 +1,32 @@
1
+ import { tv } from 'tailwind-variants';
2
+ export const menuVariants = tv({
3
+ slots: {
4
+ base: 'flex flex-col gap-1 w-full',
5
+ group: 'flex flex-col w-full',
6
+ groupTrigger: [
7
+ 'flex items-center justify-between w-full px-3 py-2 text-sm font-medium rounded-md',
8
+ 'transition-colors duration-200 outline-none focus-visible:ring-2 focus-visible:ring-outline',
9
+ 'text-on-surface hover:bg-surface-container-highest',
10
+ 'disabled:opacity-50 disabled:cursor-not-allowed'
11
+ ],
12
+ groupTriggerActive: 'bg-primary-container text-on-primary-container',
13
+ groupContent: 'flex flex-col gap-1 pl-4 mt-1',
14
+ item: [
15
+ 'flex items-center w-full px-3 py-2 text-sm font-medium rounded-md',
16
+ 'transition-colors duration-200 outline-none focus-visible:ring-2 focus-visible:ring-outline',
17
+ 'text-on-surface hover:bg-surface-container-highest',
18
+ 'disabled:opacity-50 disabled:cursor-not-allowed'
19
+ ],
20
+ itemActive: 'bg-primary-container text-on-primary-container hover:bg-primary-container/90',
21
+ icon: 'size-5 mr-3 shrink-0',
22
+ chevron: 'size-4 shrink-0 transition-transform duration-200'
23
+ },
24
+ variants: {
25
+ variant: {
26
+ default: {}
27
+ }
28
+ },
29
+ defaultVariants: {
30
+ variant: 'default'
31
+ }
32
+ });