svelora 3.0.6 → 3.0.8

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 (161) 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 +48 -0
  12. package/dist/Chart/Chart.svelte.d.ts +4 -0
  13. package/dist/Chart/chart.types.d.ts +16 -0
  14. package/dist/Chart/chart.types.js +1 -0
  15. package/dist/Chart/index.d.ts +2 -0
  16. package/dist/Chart/index.js +2 -0
  17. package/dist/Chat/ChatBubble.svelte +30 -0
  18. package/dist/Chat/ChatBubble.svelte.d.ts +4 -0
  19. package/dist/Chat/ChatInput.svelte +50 -0
  20. package/dist/Chat/ChatInput.svelte.d.ts +4 -0
  21. package/dist/Chat/ChatMessage.svelte +15 -0
  22. package/dist/Chat/ChatMessage.svelte.d.ts +4 -0
  23. package/dist/Chat/chat.types.d.ts +63 -0
  24. package/dist/Chat/chat.types.js +1 -0
  25. package/dist/Chat/chat.variants.d.ts +117 -0
  26. package/dist/Chat/chat.variants.js +47 -0
  27. package/dist/Chat/index.d.ts +6 -0
  28. package/dist/Chat/index.js +6 -0
  29. package/dist/ColorPicker/ColorPicker.svelte +109 -0
  30. package/dist/ColorPicker/ColorPicker.svelte.d.ts +4 -0
  31. package/dist/ColorPicker/color-picker.types.d.ts +26 -0
  32. package/dist/ColorPicker/color-picker.types.js +1 -0
  33. package/dist/ColorPicker/color-picker.variants.d.ts +69 -0
  34. package/dist/ColorPicker/color-picker.variants.js +13 -0
  35. package/dist/ColorPicker/index.d.ts +4 -0
  36. package/dist/ColorPicker/index.js +4 -0
  37. package/dist/DateRangePicker/DateRangePicker.svelte +59 -0
  38. package/dist/DateRangePicker/DateRangePicker.svelte.d.ts +4 -0
  39. package/dist/DateRangePicker/date-range-picker.types.d.ts +34 -0
  40. package/dist/DateRangePicker/date-range-picker.types.js +1 -0
  41. package/dist/DateRangePicker/date-range-picker.variants.d.ts +39 -0
  42. package/dist/DateRangePicker/date-range-picker.variants.js +20 -0
  43. package/dist/DateRangePicker/index.d.ts +4 -0
  44. package/dist/DateRangePicker/index.js +4 -0
  45. package/dist/List/List.svelte +14 -0
  46. package/dist/List/List.svelte.d.ts +4 -0
  47. package/dist/List/ListItem.svelte +64 -0
  48. package/dist/List/ListItem.svelte.d.ts +4 -0
  49. package/dist/List/index.d.ts +5 -0
  50. package/dist/List/index.js +5 -0
  51. package/dist/List/list.types.d.ts +62 -0
  52. package/dist/List/list.types.js +1 -0
  53. package/dist/List/list.variants.d.ts +99 -0
  54. package/dist/List/list.variants.js +42 -0
  55. package/dist/Marquee/Marquee.svelte +50 -0
  56. package/dist/Marquee/Marquee.svelte.d.ts +4 -0
  57. package/dist/Marquee/index.d.ts +4 -0
  58. package/dist/Marquee/index.js +4 -0
  59. package/dist/Marquee/marquee.types.d.ts +38 -0
  60. package/dist/Marquee/marquee.types.js +1 -0
  61. package/dist/Marquee/marquee.variants.d.ts +78 -0
  62. package/dist/Marquee/marquee.variants.js +28 -0
  63. package/dist/NavigationMenu/NavigationMenu.svelte +212 -0
  64. package/dist/NavigationMenu/NavigationMenu.svelte.d.ts +4 -0
  65. package/dist/NavigationMenu/index.d.ts +3 -0
  66. package/dist/NavigationMenu/index.js +3 -0
  67. package/dist/NavigationMenu/navigation-menu.types.d.ts +104 -0
  68. package/dist/NavigationMenu/navigation-menu.types.js +1 -0
  69. package/dist/NavigationMenu/navigation-menu.variants.d.ts +121 -0
  70. package/dist/NavigationMenu/navigation-menu.variants.js +64 -0
  71. package/dist/NumberTicker/NumberTicker.svelte +59 -0
  72. package/dist/NumberTicker/NumberTicker.svelte.d.ts +4 -0
  73. package/dist/NumberTicker/index.d.ts +4 -0
  74. package/dist/NumberTicker/index.js +4 -0
  75. package/dist/NumberTicker/number-ticker.types.d.ts +26 -0
  76. package/dist/NumberTicker/number-ticker.types.js +1 -0
  77. package/dist/NumberTicker/number-ticker.variants.d.ts +27 -0
  78. package/dist/NumberTicker/number-ticker.variants.js +6 -0
  79. package/dist/PasswordInput/PasswordInput.svelte +74 -0
  80. package/dist/PasswordInput/PasswordInput.svelte.d.ts +4 -0
  81. package/dist/PasswordInput/index.d.ts +4 -0
  82. package/dist/PasswordInput/index.js +4 -0
  83. package/dist/PasswordInput/password-input.types.d.ts +18 -0
  84. package/dist/PasswordInput/password-input.types.js +1 -0
  85. package/dist/PasswordInput/password-input.variants.d.ts +57 -0
  86. package/dist/PasswordInput/password-input.variants.js +11 -0
  87. package/dist/Prose/Prose.svelte +13 -0
  88. package/dist/Prose/Prose.svelte.d.ts +4 -0
  89. package/dist/Prose/index.d.ts +4 -0
  90. package/dist/Prose/index.js +4 -0
  91. package/dist/Prose/prose.types.d.ts +22 -0
  92. package/dist/Prose/prose.types.js +1 -0
  93. package/dist/Prose/prose.variants.d.ts +45 -0
  94. package/dist/Prose/prose.variants.js +45 -0
  95. package/dist/Rating/Rating.svelte +93 -0
  96. package/dist/Rating/Rating.svelte.d.ts +4 -0
  97. package/dist/Rating/index.d.ts +4 -0
  98. package/dist/Rating/index.js +4 -0
  99. package/dist/Rating/rating.types.d.ts +59 -0
  100. package/dist/Rating/rating.types.js +1 -0
  101. package/dist/Rating/rating.variants.d.ts +93 -0
  102. package/dist/Rating/rating.variants.js +32 -0
  103. package/dist/Resizable/Resizable.svelte +9 -0
  104. package/dist/Resizable/Resizable.svelte.d.ts +4 -0
  105. package/dist/Resizable/index.d.ts +4 -0
  106. package/dist/Resizable/index.js +4 -0
  107. package/dist/Resizable/resizable.types.d.ts +18 -0
  108. package/dist/Resizable/resizable.types.js +1 -0
  109. package/dist/Resizable/resizable.variants.d.ts +48 -0
  110. package/dist/Resizable/resizable.variants.js +17 -0
  111. package/dist/ScrollArea/ScrollArea.svelte +54 -0
  112. package/dist/ScrollArea/ScrollArea.svelte.d.ts +4 -0
  113. package/dist/ScrollArea/index.d.ts +4 -0
  114. package/dist/ScrollArea/index.js +4 -0
  115. package/dist/ScrollArea/scroll-area.types.d.ts +27 -0
  116. package/dist/ScrollArea/scroll-area.types.js +1 -0
  117. package/dist/ScrollArea/scroll-area.variants.d.ts +45 -0
  118. package/dist/ScrollArea/scroll-area.variants.js +27 -0
  119. package/dist/Search/Search.svelte +94 -0
  120. package/dist/Search/Search.svelte.d.ts +4 -0
  121. package/dist/Search/index.d.ts +2 -0
  122. package/dist/Search/index.js +1 -0
  123. package/dist/Search/search.types.d.ts +40 -0
  124. package/dist/Search/search.types.js +1 -0
  125. package/dist/Sidebar/Sidebar.svelte +30 -0
  126. package/dist/Sidebar/Sidebar.svelte.d.ts +4 -0
  127. package/dist/Sidebar/index.d.ts +4 -0
  128. package/dist/Sidebar/index.js +4 -0
  129. package/dist/Sidebar/sidebar.types.d.ts +31 -0
  130. package/dist/Sidebar/sidebar.types.js +1 -0
  131. package/dist/Sidebar/sidebar.variants.d.ts +69 -0
  132. package/dist/Sidebar/sidebar.variants.js +23 -0
  133. package/dist/Spotlight/Spotlight.svelte +31 -0
  134. package/dist/Spotlight/Spotlight.svelte.d.ts +4 -0
  135. package/dist/Spotlight/index.d.ts +4 -0
  136. package/dist/Spotlight/index.js +4 -0
  137. package/dist/Spotlight/spotlight.types.d.ts +22 -0
  138. package/dist/Spotlight/spotlight.types.js +1 -0
  139. package/dist/Spotlight/spotlight.variants.d.ts +39 -0
  140. package/dist/Spotlight/spotlight.variants.js +8 -0
  141. package/dist/TagsInput/TagsInput.svelte +100 -0
  142. package/dist/TagsInput/TagsInput.svelte.d.ts +4 -0
  143. package/dist/TagsInput/index.d.ts +4 -0
  144. package/dist/TagsInput/index.js +4 -0
  145. package/dist/TagsInput/tags-input.types.d.ts +32 -0
  146. package/dist/TagsInput/tags-input.types.js +1 -0
  147. package/dist/TagsInput/tags-input.variants.d.ts +45 -0
  148. package/dist/TagsInput/tags-input.variants.js +22 -0
  149. package/dist/TreeView/TreeView.svelte +95 -0
  150. package/dist/TreeView/TreeView.svelte.d.ts +4 -0
  151. package/dist/TreeView/index.d.ts +4 -0
  152. package/dist/TreeView/index.js +4 -0
  153. package/dist/TreeView/tree-view.types.d.ts +68 -0
  154. package/dist/TreeView/tree-view.types.js +1 -0
  155. package/dist/TreeView/tree-view.variants.d.ts +69 -0
  156. package/dist/TreeView/tree-view.variants.js +30 -0
  157. package/dist/docs/navigation.js +119 -0
  158. package/dist/index.d.ts +19 -2
  159. package/dist/index.js +19 -1
  160. package/dist/mcp/svelora-docs.data.json +44 -6
  161. package/package.json +9 -8
@@ -0,0 +1,94 @@
1
+ <script lang="ts">import { twMerge } from "tailwind-merge";
2
+ import Input from "../Input/Input.svelte";
3
+ import Button from "../Button/Button.svelte";
4
+ import Modal from "../Modal/Modal.svelte";
5
+ import Command from "../Command/Command.svelte";
6
+ import Kbd from "../Kbd/Kbd.svelte";
7
+ import { onMount } from "svelte";
8
+ let { variant = "input", value = $bindable(""), kbd = [], groups = [], onSelect, placeholder = "Search...", class: className, ...rest } = $props();
9
+ let open = $state(false);
10
+ onMount(() => {
11
+ if (kbd.length > 0 && (variant === "modal" || variant === "button")) {
12
+ const handleKeydown = (e) => {
13
+ const isMac = navigator.userAgent.toLowerCase().includes("mac");
14
+ const isMeta = kbd.includes("meta") || kbd.includes("ctrl");
15
+ const key = kbd.find((k) => k.length === 1)?.toLowerCase();
16
+ if (isMeta && key) {
17
+ if ((isMac ? e.metaKey : e.ctrlKey) && e.key.toLowerCase() === key) {
18
+ e.preventDefault();
19
+ open = true;
20
+ }
21
+ }
22
+ };
23
+ window.addEventListener("keydown", handleKeydown);
24
+ return () => window.removeEventListener("keydown", handleKeydown);
25
+ }
26
+ });
27
+ </script>
28
+
29
+ {#if variant === 'input'}
30
+ <Input
31
+ type="search"
32
+ {placeholder}
33
+ bind:value
34
+ leadingIcon="lucide:search"
35
+ class={className}
36
+ {...(rest as any)}
37
+ >
38
+ {#snippet trailingSlot()}
39
+ {#if kbd.length > 0}
40
+ <div class="pointer-events-none flex items-center gap-1">
41
+ {#each kbd as key}
42
+ <Kbd value={key} size="sm" />
43
+ {/each}
44
+ </div>
45
+ {/if}
46
+ {/snippet}
47
+ </Input>
48
+ {:else if variant === 'modal'}
49
+ <button
50
+ type="button"
51
+ class={twMerge(
52
+ 'flex h-10 w-full items-center justify-between rounded-md border border-outline-variant bg-surface px-3 py-2 text-sm text-on-surface-variant shadow-sm transition-colors hover:bg-surface-container hover:text-on-surface focus:outline-none focus:ring-2 focus:ring-primary',
53
+ className
54
+ )}
55
+ onclick={() => (open = true)}
56
+ {...(rest as any)}
57
+ >
58
+ <span class="flex items-center gap-2">
59
+ <span class="iconify lucide--search text-lg"></span>
60
+ <span>{placeholder}</span>
61
+ </span>
62
+ {#if kbd.length > 0}
63
+ <span class="flex items-center gap-1">
64
+ {#each kbd as key}
65
+ <Kbd value={key} size="sm" />
66
+ {/each}
67
+ </span>
68
+ {/if}
69
+ </button>
70
+ {:else if variant === 'button'}
71
+ <Button
72
+ variant="ghost"
73
+ color="surface"
74
+ leadingIcon="lucide:search"
75
+ class={className}
76
+ onclick={() => (open = true)}
77
+ {...(rest as any)}
78
+ />
79
+ {/if}
80
+
81
+ {#if variant === 'modal' || variant === 'button'}
82
+ <Modal bind:open size="lg">
83
+ {#snippet content()}
84
+ <Command
85
+ {groups}
86
+ bind:search={value}
87
+ placeholder="Type a command or search..."
88
+ ui={{
89
+ root: 'border-0 shadow-none'
90
+ }}
91
+ />
92
+ {/snippet}
93
+ </Modal>
94
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { SearchProps } from './search.types.js';
2
+ declare const Search: import("svelte").Component<SearchProps, {}, "value">;
3
+ type Search = ReturnType<typeof Search>;
4
+ export default Search;
@@ -0,0 +1,2 @@
1
+ export { default as Search } from './Search.svelte';
2
+ export type * from './search.types.js';
@@ -0,0 +1 @@
1
+ export { default as Search } from './Search.svelte';
@@ -0,0 +1,40 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { ClassNameValue } from 'tailwind-merge';
3
+ import type { CommandGroup } from '../Command/command.types.js';
4
+ export type SearchVariant = 'input' | 'modal' | 'button';
5
+ export interface SearchProps extends Omit<HTMLAttributes<HTMLInputElement | HTMLButtonElement>, 'class'> {
6
+ /**
7
+ * Determines the visual style and behavior of the search component.
8
+ * - `input`: A standard input box.
9
+ * - `modal`: A fake input that opens a modal containing a Command palette when clicked.
10
+ * - `button`: A simple icon button that opens a modal containing a Command palette.
11
+ * @default 'input'
12
+ */
13
+ variant?: SearchVariant;
14
+ /**
15
+ * The value of the search input (when variant is 'input' or internal modal search).
16
+ */
17
+ value?: string;
18
+ /**
19
+ * Keyboard shortcut to display (and listen to) for opening the modal.
20
+ * E.g. `['meta', 'K']` or `['ctrl', '/']`
21
+ */
22
+ kbd?: string[];
23
+ /**
24
+ * Data groups to display in the Command palette (used when variant is 'modal' or 'button').
25
+ */
26
+ groups?: CommandGroup[];
27
+ /**
28
+ * Callback fired when an item is selected from the Command palette.
29
+ */
30
+ onSelect?: (value: string) => void;
31
+ /**
32
+ * Placeholder text for the input or fake input.
33
+ * @default 'Search...'
34
+ */
35
+ placeholder?: string;
36
+ /**
37
+ * Additional CSS classes for the root element.
38
+ */
39
+ class?: ClassNameValue;
40
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
1
+ <script lang="ts">import { twMerge } from "tailwind-merge";
2
+ import { setContext } from "svelte";
3
+ import { sidebarVariants } from "./sidebar.variants.js";
4
+ let { collapsed = false, position = "left", class: className, header, footer, children, ...restProps } = $props();
5
+ let styles = $derived(sidebarVariants({
6
+ collapsed,
7
+ position
8
+ }));
9
+ // Provide context to children (like Menu) so they know if sidebar is collapsed
10
+ // Useful if we want the Menu to hide labels when collapsed
11
+ setContext("sidebar-collapsed", () => collapsed);
12
+ </script>
13
+
14
+ <aside class={twMerge(styles.base(), className)} {...restProps}>
15
+ {#if header}
16
+ <div class={styles.header()}>
17
+ {@render header()}
18
+ </div>
19
+ {/if}
20
+
21
+ <div class={styles.content()}>
22
+ {@render children?.()}
23
+ </div>
24
+
25
+ {#if footer}
26
+ <div class={styles.footer()}>
27
+ {@render footer()}
28
+ </div>
29
+ {/if}
30
+ </aside>
@@ -0,0 +1,4 @@
1
+ import type { SidebarProps } from './sidebar.types.js';
2
+ declare const Sidebar: import("svelte").Component<SidebarProps, {}, "">;
3
+ type Sidebar = ReturnType<typeof Sidebar>;
4
+ export default Sidebar;
@@ -0,0 +1,4 @@
1
+ import Sidebar from './Sidebar.svelte';
2
+ export { Sidebar };
3
+ export * from './sidebar.types.js';
4
+ export * from './sidebar.variants.js';
@@ -0,0 +1,4 @@
1
+ import Sidebar from './Sidebar.svelte';
2
+ export { Sidebar };
3
+ export * from './sidebar.types.js';
4
+ export * from './sidebar.variants.js';
@@ -0,0 +1,31 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { SidebarVariantProps } from './sidebar.variants.js';
4
+ export interface SidebarProps extends HTMLAttributes<HTMLElement> {
5
+ /**
6
+ * Whether the sidebar is collapsed (icons only).
7
+ * @default false
8
+ */
9
+ collapsed?: boolean;
10
+ /**
11
+ * Position of the sidebar.
12
+ * @default 'left'
13
+ */
14
+ position?: SidebarVariantProps['position'];
15
+ /**
16
+ * Additional CSS classes.
17
+ */
18
+ class?: string;
19
+ /**
20
+ * Snippet for the top header section (e.g. Logo).
21
+ */
22
+ header?: Snippet;
23
+ /**
24
+ * Snippet for the main content (e.g. Navigation Menu).
25
+ */
26
+ children?: Snippet;
27
+ /**
28
+ * Snippet for the bottom footer section (e.g. User Profile).
29
+ */
30
+ footer?: Snippet;
31
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,69 @@
1
+ import { type VariantProps } from 'tailwind-variants';
2
+ export declare const sidebarVariants: import("tailwind-variants").TVReturnType<{
3
+ position: {
4
+ left: {
5
+ base: string;
6
+ };
7
+ right: {
8
+ base: string;
9
+ };
10
+ };
11
+ collapsed: {
12
+ true: {
13
+ base: string;
14
+ };
15
+ false: {
16
+ base: string;
17
+ };
18
+ };
19
+ }, {
20
+ base: string;
21
+ header: string;
22
+ content: string;
23
+ footer: string;
24
+ }, undefined, {
25
+ position: {
26
+ left: {
27
+ base: string;
28
+ };
29
+ right: {
30
+ base: string;
31
+ };
32
+ };
33
+ collapsed: {
34
+ true: {
35
+ base: string;
36
+ };
37
+ false: {
38
+ base: string;
39
+ };
40
+ };
41
+ }, {
42
+ base: string;
43
+ header: string;
44
+ content: string;
45
+ footer: string;
46
+ }, import("tailwind-variants").TVReturnType<{
47
+ position: {
48
+ left: {
49
+ base: string;
50
+ };
51
+ right: {
52
+ base: string;
53
+ };
54
+ };
55
+ collapsed: {
56
+ true: {
57
+ base: string;
58
+ };
59
+ false: {
60
+ base: string;
61
+ };
62
+ };
63
+ }, {
64
+ base: string;
65
+ header: string;
66
+ content: string;
67
+ footer: string;
68
+ }, undefined, unknown, unknown, undefined>>;
69
+ export type SidebarVariantProps = VariantProps<typeof sidebarVariants>;
@@ -0,0 +1,23 @@
1
+ import { tv } from 'tailwind-variants';
2
+ export const sidebarVariants = tv({
3
+ slots: {
4
+ base: 'flex flex-col h-full bg-surface-50 dark:bg-surface-900 border-outline-variant text-surface-900 dark:text-surface-50 transition-all duration-300',
5
+ header: 'flex items-center px-4 h-16 shrink-0 border-b border-outline-variant',
6
+ content: 'flex-1 overflow-y-auto px-3 py-4',
7
+ footer: 'p-4 mt-auto border-t border-outline-variant shrink-0'
8
+ },
9
+ variants: {
10
+ position: {
11
+ left: { base: 'border-r' },
12
+ right: { base: 'border-l' }
13
+ },
14
+ collapsed: {
15
+ true: { base: 'w-16' },
16
+ false: { base: 'w-64' }
17
+ }
18
+ },
19
+ defaultVariants: {
20
+ position: 'left',
21
+ collapsed: false
22
+ }
23
+ });
@@ -0,0 +1,31 @@
1
+ <script lang="ts">import { twMerge } from "tailwind-merge";
2
+ import { spotlightVariants } from "./spotlight.variants.js";
3
+ let { size = 400, color = "rgba(255, 255, 255, 0.1)", class: className, children, ...restProps } = $props();
4
+ let styles = $derived(spotlightVariants());
5
+ let mouseX = $state(0);
6
+ let mouseY = $state(0);
7
+ function handleMouseMove(e) {
8
+ const target = e.currentTarget;
9
+ const rect = target.getBoundingClientRect();
10
+ mouseX = e.clientX - rect.left;
11
+ mouseY = e.clientY - rect.top;
12
+ }
13
+ </script>
14
+
15
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
16
+ <div
17
+ class={twMerge(styles.root() as string, className)}
18
+ onmousemove={handleMouseMove}
19
+ {...restProps}
20
+ >
21
+ <!-- Spotlight Effect Background -->
22
+ <div
23
+ class={styles.spotlight() as string}
24
+ style:background={`radial-gradient(${size}px circle at ${mouseX}px ${mouseY}px, ${color}, transparent 80%)`}
25
+ ></div>
26
+
27
+ <!-- Content -->
28
+ <div class={styles.content() as string}>
29
+ {@render children?.()}
30
+ </div>
31
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { SpotlightProps } from './spotlight.types.js';
2
+ declare const Spotlight: import("svelte").Component<SpotlightProps, {}, "">;
3
+ type Spotlight = ReturnType<typeof Spotlight>;
4
+ export default Spotlight;
@@ -0,0 +1,4 @@
1
+ import Spotlight from './Spotlight.svelte';
2
+ export { Spotlight };
3
+ export * from './spotlight.types.js';
4
+ export * from './spotlight.variants.js';
@@ -0,0 +1,4 @@
1
+ import Spotlight from './Spotlight.svelte';
2
+ export { Spotlight };
3
+ export * from './spotlight.types.js';
4
+ export * from './spotlight.variants.js';
@@ -0,0 +1,22 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ export interface SpotlightProps extends HTMLAttributes<HTMLDivElement> {
4
+ /**
5
+ * Size of the spotlight in pixels.
6
+ * @default 400
7
+ */
8
+ size?: number;
9
+ /**
10
+ * Color of the spotlight in rgba, hex, or CSS variable.
11
+ * @default 'rgba(255, 255, 255, 0.1)'
12
+ */
13
+ color?: string;
14
+ /**
15
+ * Additional CSS classes.
16
+ */
17
+ class?: string;
18
+ /**
19
+ * Content to render inside the spotlight container.
20
+ */
21
+ children?: Snippet;
22
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,39 @@
1
+ import { type VariantProps } from 'tailwind-variants';
2
+ export declare const spotlightVariants: import("tailwind-variants").TVReturnType<{
3
+ [key: string]: {
4
+ [key: string]: import("tailwind-merge").ClassNameValue | {
5
+ content?: import("tailwind-merge").ClassNameValue;
6
+ root?: import("tailwind-merge").ClassNameValue;
7
+ spotlight?: import("tailwind-merge").ClassNameValue;
8
+ };
9
+ };
10
+ } | {
11
+ [x: string]: {
12
+ [x: string]: import("tailwind-merge").ClassNameValue | {
13
+ content?: import("tailwind-merge").ClassNameValue;
14
+ root?: import("tailwind-merge").ClassNameValue;
15
+ spotlight?: import("tailwind-merge").ClassNameValue;
16
+ };
17
+ };
18
+ } | {}, {
19
+ root: string;
20
+ spotlight: string;
21
+ content: string;
22
+ }, undefined, {
23
+ [key: string]: {
24
+ [key: string]: import("tailwind-merge").ClassNameValue | {
25
+ content?: import("tailwind-merge").ClassNameValue;
26
+ root?: import("tailwind-merge").ClassNameValue;
27
+ spotlight?: import("tailwind-merge").ClassNameValue;
28
+ };
29
+ };
30
+ } | {}, {
31
+ root: string;
32
+ spotlight: string;
33
+ content: string;
34
+ }, import("tailwind-variants").TVReturnType<unknown, {
35
+ root: string;
36
+ spotlight: string;
37
+ content: string;
38
+ }, undefined, unknown, unknown, undefined>>;
39
+ export type SpotlightVariantProps = VariantProps<typeof spotlightVariants>;
@@ -0,0 +1,8 @@
1
+ import { tv } from 'tailwind-variants';
2
+ export const spotlightVariants = tv({
3
+ slots: {
4
+ root: 'relative overflow-hidden group',
5
+ spotlight: 'pointer-events-none absolute -inset-px rounded-xl opacity-0 transition-opacity duration-300 group-hover:opacity-100',
6
+ content: 'relative z-10 h-full w-full'
7
+ }
8
+ });
@@ -0,0 +1,100 @@
1
+ <script lang="ts">import { twMerge } from "tailwind-merge";
2
+ import Icon from "../Icon/Icon.svelte";
3
+ import { tagsInputVariants } from "./tags-input.variants.js";
4
+ let { value = $bindable([]), placeholder = "Add a tag...", disabled = false, maxTags, separators = [",", "Enter"], class: className, onchange, ...restProps } = $props();
5
+ let styles = $derived(tagsInputVariants({ disabled }));
6
+ let inputValue = $state("");
7
+ let inputRef = $state(null);
8
+ function addTag(tag) {
9
+ const t = tag.trim();
10
+ if (!t) return;
11
+ if (maxTags && value.length >= maxTags) return;
12
+ if (value.includes(t)) return;
13
+ value = [...value, t];
14
+ inputValue = "";
15
+ onchange?.(value);
16
+ }
17
+ function removeTag(index) {
18
+ if (disabled) return;
19
+ value = value.filter((_, i) => i !== index);
20
+ onchange?.(value);
21
+ }
22
+ function handleKeyDown(e) {
23
+ if (disabled) return;
24
+ // Backspace to remove last tag if input is empty
25
+ if (e.key === "Backspace" && inputValue === "" && value.length > 0) {
26
+ removeTag(value.length - 1);
27
+ return;
28
+ }
29
+ // Add tag on separator
30
+ if (separators.includes(e.key)) {
31
+ e.preventDefault();
32
+ addTag(inputValue);
33
+ }
34
+ }
35
+ // Also handle pasting comma-separated values
36
+ function handlePaste(e) {
37
+ if (disabled) return;
38
+ const pasteData = e.clipboardData?.getData("text");
39
+ if (pasteData) {
40
+ e.preventDefault();
41
+ const tags = pasteData.split(separators.includes(",") ? "," : "\n").map((t) => t.trim()).filter(Boolean);
42
+ let newTags = [...value];
43
+ for (const t of tags) {
44
+ if (maxTags && newTags.length >= maxTags) break;
45
+ if (!newTags.includes(t)) {
46
+ newTags.push(t);
47
+ }
48
+ }
49
+ if (newTags.length !== value.length) {
50
+ value = newTags;
51
+ onchange?.(value);
52
+ }
53
+ }
54
+ }
55
+ function handleContainerClick() {
56
+ if (!disabled && inputRef) {
57
+ inputRef.focus();
58
+ }
59
+ }
60
+ </script>
61
+
62
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
63
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
64
+ <div
65
+ class={twMerge(styles.base() as any, className)}
66
+ onclick={handleContainerClick}
67
+ {...restProps}
68
+ >
69
+ {#each value as tag, i}
70
+ <span class={styles.tag() as any}>
71
+ <span class={styles.tagText() as any}>{tag}</span>
72
+ <button
73
+ type="button"
74
+ class={styles.removeButton() as any}
75
+ onclick={(e) => {
76
+ e.stopPropagation()
77
+ removeTag(i)
78
+ }}
79
+ {disabled}
80
+ aria-label={`Remove tag ${tag}`}
81
+ >
82
+ <Icon name="lucide:x" class="w-3 h-3" />
83
+ </button>
84
+ </span>
85
+ {/each}
86
+
87
+ {#if !maxTags || value.length < maxTags}
88
+ <input
89
+ bind:this={inputRef}
90
+ bind:value={inputValue}
91
+ type="text"
92
+ {placeholder}
93
+ {disabled}
94
+ class={styles.input() as any}
95
+ onkeydown={handleKeyDown}
96
+ onpaste={handlePaste}
97
+ onblur={() => addTag(inputValue)}
98
+ />
99
+ {/if}
100
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { TagsInputProps } from './tags-input.types.js';
2
+ declare const TagsInput: import("svelte").Component<TagsInputProps, {}, "value">;
3
+ type TagsInput = ReturnType<typeof TagsInput>;
4
+ export default TagsInput;
@@ -0,0 +1,4 @@
1
+ import TagsInput from './TagsInput.svelte';
2
+ export { TagsInput };
3
+ export * from './tags-input.types.js';
4
+ export * from './tags-input.variants.js';
@@ -0,0 +1,4 @@
1
+ import TagsInput from './TagsInput.svelte';
2
+ export { TagsInput };
3
+ export * from './tags-input.types.js';
4
+ export * from './tags-input.variants.js';
@@ -0,0 +1,32 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ export interface TagsInputProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onchange'> {
3
+ /**
4
+ * Array of tag strings.
5
+ */
6
+ value?: string[];
7
+ /**
8
+ * Placeholder text for the input field.
9
+ */
10
+ placeholder?: string;
11
+ /**
12
+ * Whether the input is disabled.
13
+ */
14
+ disabled?: boolean;
15
+ /**
16
+ * Maximum number of tags allowed.
17
+ */
18
+ maxTags?: number;
19
+ /**
20
+ * Array of characters that trigger tag creation.
21
+ * @default [',', 'Enter']
22
+ */
23
+ separators?: string[];
24
+ /**
25
+ * Additional CSS classes.
26
+ */
27
+ class?: string;
28
+ /**
29
+ * Event fired when tags change.
30
+ */
31
+ onchange?: (tags: string[]) => void;
32
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ import { type VariantProps } from 'tailwind-variants';
2
+ export declare const tagsInputVariants: import("tailwind-variants").TVReturnType<{
3
+ disabled: {
4
+ true: {
5
+ base: string;
6
+ input: string;
7
+ removeButton: string;
8
+ };
9
+ };
10
+ }, {
11
+ base: string;
12
+ tag: string;
13
+ tagText: string;
14
+ removeButton: string;
15
+ input: string;
16
+ }, undefined, {
17
+ disabled: {
18
+ true: {
19
+ base: string;
20
+ input: string;
21
+ removeButton: string;
22
+ };
23
+ };
24
+ }, {
25
+ base: string;
26
+ tag: string;
27
+ tagText: string;
28
+ removeButton: string;
29
+ input: string;
30
+ }, import("tailwind-variants").TVReturnType<{
31
+ disabled: {
32
+ true: {
33
+ base: string;
34
+ input: string;
35
+ removeButton: string;
36
+ };
37
+ };
38
+ }, {
39
+ base: string;
40
+ tag: string;
41
+ tagText: string;
42
+ removeButton: string;
43
+ input: string;
44
+ }, undefined, unknown, unknown, undefined>>;
45
+ export type TagsInputVariantProps = VariantProps<typeof tagsInputVariants>;