sv5ui-plus 4.0.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.
Files changed (214) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/dist/adapters/notify.d.ts +29 -0
  4. package/dist/adapters/notify.js +88 -0
  5. package/dist/compat.d.ts +6 -0
  6. package/dist/compat.js +6 -0
  7. package/dist/components/BentoGrid/BentoCard.svelte +45 -0
  8. package/dist/components/BentoGrid/BentoCard.svelte.d.ts +4 -0
  9. package/dist/components/BentoGrid/BentoGrid.svelte +9 -0
  10. package/dist/components/BentoGrid/BentoGrid.svelte.d.ts +4 -0
  11. package/dist/components/BentoGrid/bento-grid.types.d.ts +47 -0
  12. package/dist/components/BentoGrid/bento-grid.types.js +1 -0
  13. package/dist/components/BentoGrid/bento-grid.variants.d.ts +30 -0
  14. package/dist/components/BentoGrid/bento-grid.variants.js +16 -0
  15. package/dist/components/BentoGrid/index.d.ts +5 -0
  16. package/dist/components/BentoGrid/index.js +5 -0
  17. package/dist/components/Chart/Chart.svelte +62 -0
  18. package/dist/components/Chart/Chart.svelte.d.ts +4 -0
  19. package/dist/components/Chart/chart.types.d.ts +16 -0
  20. package/dist/components/Chart/chart.types.js +1 -0
  21. package/dist/components/Chart/index.d.ts +2 -0
  22. package/dist/components/Chart/index.js +2 -0
  23. package/dist/components/Chat/ChatBubble.svelte +30 -0
  24. package/dist/components/Chat/ChatBubble.svelte.d.ts +4 -0
  25. package/dist/components/Chat/ChatInput.svelte +50 -0
  26. package/dist/components/Chat/ChatInput.svelte.d.ts +4 -0
  27. package/dist/components/Chat/ChatMessage.svelte +15 -0
  28. package/dist/components/Chat/ChatMessage.svelte.d.ts +4 -0
  29. package/dist/components/Chat/chat.types.d.ts +63 -0
  30. package/dist/components/Chat/chat.types.js +1 -0
  31. package/dist/components/Chat/chat.variants.d.ts +117 -0
  32. package/dist/components/Chat/chat.variants.js +47 -0
  33. package/dist/components/Chat/index.d.ts +6 -0
  34. package/dist/components/Chat/index.js +6 -0
  35. package/dist/components/CodeBlock/CodeBlock.svelte +66 -0
  36. package/dist/components/CodeBlock/CodeBlock.svelte.d.ts +5 -0
  37. package/dist/components/CodeBlock/code-block.types.d.ts +15 -0
  38. package/dist/components/CodeBlock/code-block.types.js +1 -0
  39. package/dist/components/CodeBlock/code-block.variants.d.ts +288 -0
  40. package/dist/components/CodeBlock/code-block.variants.js +69 -0
  41. package/dist/components/CodeBlock/index.d.ts +2 -0
  42. package/dist/components/CodeBlock/index.js +1 -0
  43. package/dist/components/ColorPicker/ColorPicker.svelte +109 -0
  44. package/dist/components/ColorPicker/ColorPicker.svelte.d.ts +4 -0
  45. package/dist/components/ColorPicker/color-picker.types.d.ts +26 -0
  46. package/dist/components/ColorPicker/color-picker.types.js +1 -0
  47. package/dist/components/ColorPicker/color-picker.variants.d.ts +69 -0
  48. package/dist/components/ColorPicker/color-picker.variants.js +13 -0
  49. package/dist/components/ColorPicker/index.d.ts +4 -0
  50. package/dist/components/ColorPicker/index.js +4 -0
  51. package/dist/components/ConfirmDialog/ConfirmDialog.svelte +175 -0
  52. package/dist/components/ConfirmDialog/ConfirmDialog.svelte.d.ts +10 -0
  53. package/dist/components/ConfirmDialog/confirm.d.ts +9 -0
  54. package/dist/components/ConfirmDialog/confirm.js +24 -0
  55. package/dist/components/ConfirmDialog/confirm.types.d.ts +21 -0
  56. package/dist/components/ConfirmDialog/confirm.types.js +1 -0
  57. package/dist/components/ConfirmDialog/index.d.ts +4 -0
  58. package/dist/components/ConfirmDialog/index.js +2 -0
  59. package/dist/components/Fonts/Fonts.svelte +32 -0
  60. package/dist/components/Fonts/Fonts.svelte.d.ts +5 -0
  61. package/dist/components/Fonts/fonts.d.ts +12 -0
  62. package/dist/components/Fonts/fonts.js +126 -0
  63. package/dist/components/Fonts/fonts.types.d.ts +40 -0
  64. package/dist/components/Fonts/fonts.types.js +1 -0
  65. package/dist/components/Fonts/index.d.ts +3 -0
  66. package/dist/components/Fonts/index.js +2 -0
  67. package/dist/components/List/List.svelte +14 -0
  68. package/dist/components/List/List.svelte.d.ts +4 -0
  69. package/dist/components/List/ListItem.svelte +64 -0
  70. package/dist/components/List/ListItem.svelte.d.ts +4 -0
  71. package/dist/components/List/index.d.ts +5 -0
  72. package/dist/components/List/index.js +5 -0
  73. package/dist/components/List/list.types.d.ts +62 -0
  74. package/dist/components/List/list.types.js +1 -0
  75. package/dist/components/List/list.variants.d.ts +99 -0
  76. package/dist/components/List/list.variants.js +42 -0
  77. package/dist/components/LocaleButton/LocaleButton.svelte +181 -0
  78. package/dist/components/LocaleButton/LocaleButton.svelte.d.ts +5 -0
  79. package/dist/components/LocaleButton/index.d.ts +2 -0
  80. package/dist/components/LocaleButton/index.js +1 -0
  81. package/dist/components/LocaleButton/locale-button.types.d.ts +208 -0
  82. package/dist/components/LocaleButton/locale-button.types.js +1 -0
  83. package/dist/components/LocaleButton/locale-button.variants.d.ts +245 -0
  84. package/dist/components/LocaleButton/locale-button.variants.js +98 -0
  85. package/dist/components/Marquee/Marquee.svelte +50 -0
  86. package/dist/components/Marquee/Marquee.svelte.d.ts +4 -0
  87. package/dist/components/Marquee/index.d.ts +4 -0
  88. package/dist/components/Marquee/index.js +4 -0
  89. package/dist/components/Marquee/marquee.types.d.ts +38 -0
  90. package/dist/components/Marquee/marquee.types.js +1 -0
  91. package/dist/components/Marquee/marquee.variants.d.ts +78 -0
  92. package/dist/components/Marquee/marquee.variants.js +28 -0
  93. package/dist/components/NavigationMenu/NavigationMenu.svelte +623 -0
  94. package/dist/components/NavigationMenu/NavigationMenu.svelte.d.ts +5 -0
  95. package/dist/components/NavigationMenu/index.d.ts +2 -0
  96. package/dist/components/NavigationMenu/index.js +1 -0
  97. package/dist/components/NavigationMenu/navigation-menu.types.d.ts +245 -0
  98. package/dist/components/NavigationMenu/navigation-menu.types.js +1 -0
  99. package/dist/components/NavigationMenu/navigation-menu.variants.d.ts +543 -0
  100. package/dist/components/NavigationMenu/navigation-menu.variants.js +287 -0
  101. package/dist/components/NumberTicker/NumberTicker.svelte +59 -0
  102. package/dist/components/NumberTicker/NumberTicker.svelte.d.ts +4 -0
  103. package/dist/components/NumberTicker/index.d.ts +4 -0
  104. package/dist/components/NumberTicker/index.js +4 -0
  105. package/dist/components/NumberTicker/number-ticker.types.d.ts +26 -0
  106. package/dist/components/NumberTicker/number-ticker.types.js +1 -0
  107. package/dist/components/NumberTicker/number-ticker.variants.d.ts +27 -0
  108. package/dist/components/NumberTicker/number-ticker.variants.js +6 -0
  109. package/dist/components/PasswordInput/PasswordInput.svelte +182 -0
  110. package/dist/components/PasswordInput/PasswordInput.svelte.d.ts +5 -0
  111. package/dist/components/PasswordInput/index.d.ts +2 -0
  112. package/dist/components/PasswordInput/index.js +1 -0
  113. package/dist/components/PasswordInput/password-input.types.d.ts +111 -0
  114. package/dist/components/PasswordInput/password-input.types.js +1 -0
  115. package/dist/components/PasswordInput/password-input.variants.d.ts +273 -0
  116. package/dist/components/PasswordInput/password-input.variants.js +105 -0
  117. package/dist/components/Prose/Prose.svelte +13 -0
  118. package/dist/components/Prose/Prose.svelte.d.ts +4 -0
  119. package/dist/components/Prose/index.d.ts +4 -0
  120. package/dist/components/Prose/index.js +4 -0
  121. package/dist/components/Prose/prose.types.d.ts +22 -0
  122. package/dist/components/Prose/prose.types.js +1 -0
  123. package/dist/components/Prose/prose.variants.d.ts +45 -0
  124. package/dist/components/Prose/prose.variants.js +45 -0
  125. package/dist/components/Resizable/Resizable.svelte +9 -0
  126. package/dist/components/Resizable/Resizable.svelte.d.ts +4 -0
  127. package/dist/components/Resizable/index.d.ts +4 -0
  128. package/dist/components/Resizable/index.js +4 -0
  129. package/dist/components/Resizable/resizable.types.d.ts +18 -0
  130. package/dist/components/Resizable/resizable.types.js +1 -0
  131. package/dist/components/Resizable/resizable.variants.d.ts +48 -0
  132. package/dist/components/Resizable/resizable.variants.js +17 -0
  133. package/dist/components/ScrollArea/ScrollArea.svelte +54 -0
  134. package/dist/components/ScrollArea/ScrollArea.svelte.d.ts +4 -0
  135. package/dist/components/ScrollArea/index.d.ts +4 -0
  136. package/dist/components/ScrollArea/index.js +4 -0
  137. package/dist/components/ScrollArea/scroll-area.types.d.ts +27 -0
  138. package/dist/components/ScrollArea/scroll-area.types.js +1 -0
  139. package/dist/components/ScrollArea/scroll-area.variants.d.ts +45 -0
  140. package/dist/components/ScrollArea/scroll-area.variants.js +27 -0
  141. package/dist/components/Search/Search.svelte +94 -0
  142. package/dist/components/Search/Search.svelte.d.ts +4 -0
  143. package/dist/components/Search/index.d.ts +2 -0
  144. package/dist/components/Search/index.js +1 -0
  145. package/dist/components/Search/search.types.d.ts +40 -0
  146. package/dist/components/Search/search.types.js +1 -0
  147. package/dist/components/SortableGroup/SortableGroup.svelte +53 -0
  148. package/dist/components/SortableGroup/SortableGroup.svelte.d.ts +13 -0
  149. package/dist/components/SortableGroup/index.d.ts +1 -0
  150. package/dist/components/SortableGroup/index.js +1 -0
  151. package/dist/components/SortableList/SortableList.svelte +81 -0
  152. package/dist/components/SortableList/SortableList.svelte.d.ts +26 -0
  153. package/dist/components/SortableList/index.d.ts +2 -0
  154. package/dist/components/SortableList/index.js +1 -0
  155. package/dist/components/SortableList/sortable-list.types.d.ts +21 -0
  156. package/dist/components/SortableList/sortable-list.types.js +1 -0
  157. package/dist/components/Spotlight/Spotlight.svelte +31 -0
  158. package/dist/components/Spotlight/Spotlight.svelte.d.ts +4 -0
  159. package/dist/components/Spotlight/index.d.ts +4 -0
  160. package/dist/components/Spotlight/index.js +4 -0
  161. package/dist/components/Spotlight/spotlight.types.d.ts +22 -0
  162. package/dist/components/Spotlight/spotlight.types.js +1 -0
  163. package/dist/components/Spotlight/spotlight.variants.d.ts +39 -0
  164. package/dist/components/Spotlight/spotlight.variants.js +8 -0
  165. package/dist/components/TableBulkActionBar/TableBulkActionBar.svelte +38 -0
  166. package/dist/components/TableBulkActionBar/TableBulkActionBar.svelte.d.ts +5 -0
  167. package/dist/components/TableBulkActionBar/index.d.ts +2 -0
  168. package/dist/components/TableBulkActionBar/index.js +1 -0
  169. package/dist/components/TableBulkActionBar/table-bulk-action-bar.types.d.ts +31 -0
  170. package/dist/components/TableBulkActionBar/table-bulk-action-bar.types.js +1 -0
  171. package/dist/components/TableBulkActionBar/table-bulk-action-bar.variants.d.ts +52 -0
  172. package/dist/components/TableBulkActionBar/table-bulk-action-bar.variants.js +10 -0
  173. package/dist/components/TreeView/TreeView.svelte +95 -0
  174. package/dist/components/TreeView/TreeView.svelte.d.ts +4 -0
  175. package/dist/components/TreeView/index.d.ts +4 -0
  176. package/dist/components/TreeView/index.js +3 -0
  177. package/dist/components/TreeView/tree-view.types.d.ts +68 -0
  178. package/dist/components/TreeView/tree-view.types.js +1 -0
  179. package/dist/components/TreeView/tree-view.variants.d.ts +69 -0
  180. package/dist/components/TreeView/tree-view.variants.js +30 -0
  181. package/dist/config.d.ts +91 -0
  182. package/dist/config.js +124 -0
  183. package/dist/editor.d.ts +2 -0
  184. package/dist/editor.js +2 -0
  185. package/dist/form/resolve-form-field-name.d.ts +5 -0
  186. package/dist/form/resolve-form-field-name.js +11 -0
  187. package/dist/hooks/internal/DragDropProviderScope.svelte +29 -0
  188. package/dist/hooks/internal/DragDropProviderScope.svelte.d.ts +7 -0
  189. package/dist/hooks/internal/SortableProvider.svelte +68 -0
  190. package/dist/hooks/internal/SortableProvider.svelte.d.ts +30 -0
  191. package/dist/hooks/internal/drag-drop-context.d.ts +12 -0
  192. package/dist/hooks/internal/drag-drop-context.js +1 -0
  193. package/dist/hooks/internal/sortable-context.d.ts +26 -0
  194. package/dist/hooks/internal/sortable-context.js +2 -0
  195. package/dist/hooks/useDragDrop/index.d.ts +1 -0
  196. package/dist/hooks/useDragDrop/index.js +1 -0
  197. package/dist/hooks/useDragDrop/useDragDrop.svelte.d.ts +40 -0
  198. package/dist/hooks/useDragDrop/useDragDrop.svelte.js +128 -0
  199. package/dist/hooks/useSortable/index.d.ts +2 -0
  200. package/dist/hooks/useSortable/index.js +2 -0
  201. package/dist/hooks/useSortable/sortable-utils.d.ts +1 -0
  202. package/dist/hooks/useSortable/sortable-utils.js +13 -0
  203. package/dist/hooks/useSortable/useSortable.svelte.d.ts +60 -0
  204. package/dist/hooks/useSortable/useSortable.svelte.js +151 -0
  205. package/dist/hooks/utils.d.ts +1 -0
  206. package/dist/hooks/utils.js +3 -0
  207. package/dist/index.d.ts +27 -0
  208. package/dist/index.js +30 -0
  209. package/dist/mcp/cursor.mcp.json +12 -0
  210. package/dist/mcp/install-template.mjs +55 -0
  211. package/dist/mcp/server.mjs +338 -0
  212. package/dist/mcp/sv5ui-plus-docs.data.json +17 -0
  213. package/dist/theme.css +64 -0
  214. package/package.json +176 -0
package/dist/config.js ADDED
@@ -0,0 +1,124 @@
1
+ /**
2
+ * SV5UI Plus Global Configuration
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { defineSV5UIPlusConfig } from 'sv5ui-plus'
7
+ *
8
+ * defineSV5UIPlusConfig({
9
+ * fonts: {
10
+ * families: [
11
+ * {
12
+ * name: 'Inter',
13
+ * variable: '--font-sans-family',
14
+ * weights: [400, 500, 600, 700]
15
+ * }
16
+ * ]
17
+ * },
18
+ * button: {
19
+ * defaultVariants: { variant: 'outline', color: 'secondary' },
20
+ * slots: { base: 'shadow-md', label: 'font-bold' }
21
+ * },
22
+ * avatar: {
23
+ * defaultVariants: { size: 'lg' },
24
+ * slots: { root: 'ring-2 ring-primary' }
25
+ * },
26
+ * icons: { loading: 'svg-spinners:ring-resize' }
27
+ * })
28
+ * ```
29
+ */
30
+ // ==================== ICONS DEFAULTS ====================
31
+ /**
32
+ * Default icons used across components
33
+ */
34
+ export const iconsDefaults = {
35
+ loading: 'lucide:loader-circle',
36
+ chevronDown: 'lucide:chevron-down',
37
+ chevronLeft: 'lucide:chevron-left',
38
+ chevronRight: 'lucide:chevron-right',
39
+ chevronsLeft: 'lucide:chevrons-left',
40
+ chevronsRight: 'lucide:chevrons-right',
41
+ ellipsis: 'lucide:ellipsis',
42
+ close: 'lucide:x',
43
+ menu: 'lucide:menu',
44
+ external: 'lucide:arrow-up-right',
45
+ check: 'lucide:check',
46
+ light: 'lucide:sun',
47
+ dark: 'lucide:moon',
48
+ upload: 'lucide:upload',
49
+ file: 'lucide:file',
50
+ zoomIn: 'lucide:zoom-in',
51
+ trash: 'lucide:trash-2',
52
+ search: 'lucide:search',
53
+ star: 'lucide:star',
54
+ folder: 'lucide:folder',
55
+ folderOpen: 'lucide:folder-open',
56
+ sortAsc: 'lucide:chevron-up',
57
+ sortDesc: 'lucide:chevron-down',
58
+ sortDefault: 'lucide:chevrons-up-down',
59
+ panelLeft: 'lucide:panel-left',
60
+ dragHandle: 'lucide:grip-vertical'
61
+ };
62
+ // ==================== GLOBAL STATE ====================
63
+ let globalConfig = {};
64
+ let cachedConfigs = {};
65
+ // ==================== PUBLIC API ====================
66
+ /**
67
+ * Define global configuration for SV5UI Plus components
68
+ */
69
+ export function defineConfig(config) {
70
+ globalConfig = config;
71
+ cachedConfigs = {};
72
+ }
73
+ /**
74
+ * Get the current global configuration
75
+ */
76
+ export function getConfig() {
77
+ return globalConfig;
78
+ }
79
+ /**
80
+ * Reset configuration to defaults
81
+ */
82
+ export function resetConfig() {
83
+ globalConfig = {};
84
+ cachedConfigs = {};
85
+ }
86
+ // ==================== COMPONENT CONFIG GETTER ====================
87
+ /**
88
+ * Deep merge utility for config objects
89
+ */
90
+ function deepMerge(target, source) {
91
+ const result = { ...target };
92
+ for (const key in source) {
93
+ const sourceValue = source[key];
94
+ const targetValue = target[key];
95
+ if (sourceValue !== undefined &&
96
+ typeof sourceValue === 'object' &&
97
+ sourceValue !== null &&
98
+ !Array.isArray(sourceValue) &&
99
+ typeof targetValue === 'object' &&
100
+ targetValue !== null &&
101
+ !Array.isArray(targetValue)) {
102
+ result[key] = deepMerge(targetValue, sourceValue);
103
+ }
104
+ else if (sourceValue !== undefined) {
105
+ result[key] = sourceValue;
106
+ }
107
+ }
108
+ return result;
109
+ }
110
+ /**
111
+ * Get merged config for a component (memoized).
112
+ * Each component passes its own defaults, so config.ts doesn't import any variant files.
113
+ * This enables proper tree-shaking: unused components are excluded from the bundle.
114
+ * @internal
115
+ */
116
+ export function getComponentConfig(component, defaults) {
117
+ if (!(component in cachedConfigs)) {
118
+ const userConfig = globalConfig[component];
119
+ cachedConfigs[component] = userConfig
120
+ ? deepMerge(defaults, userConfig)
121
+ : defaults;
122
+ }
123
+ return cachedConfigs[component];
124
+ }
@@ -0,0 +1,2 @@
1
+ /** Compatibility proxy for the SV5UI editor subpath. */
2
+ export * from 'sv5ui/editor';
package/dist/editor.js ADDED
@@ -0,0 +1,2 @@
1
+ /** Compatibility proxy for the SV5UI editor subpath. */
2
+ export * from 'sv5ui/editor';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * ชื่อฟิลด์สำหรับ form submission — ใส่ suffix `[]` เมื่อส่งหลายค่า
3
+ * เพื่อให้เข้ากับ SvelteKit `convert_formdata` และ HTML FormData
4
+ */
5
+ export declare function resolveFormFieldName(name: string | undefined, multiple: boolean): string | undefined;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * ชื่อฟิลด์สำหรับ form submission — ใส่ suffix `[]` เมื่อส่งหลายค่า
3
+ * เพื่อให้เข้ากับ SvelteKit `convert_formdata` และ HTML FormData
4
+ */
5
+ export function resolveFormFieldName(name, multiple) {
6
+ if (!name)
7
+ return undefined;
8
+ if (!multiple)
9
+ return name;
10
+ return name.endsWith('[]') ? name : `${name}[]`;
11
+ }
@@ -0,0 +1,29 @@
1
+ <script lang="ts">import { DragDropProvider } from "@dnd-kit/svelte";
2
+ import { getContext } from "svelte";
3
+ import { DRAG_DROP_CONTEXT_KEY } from "./drag-drop-context.js";
4
+ let { children } = $props();
5
+ const ctx = getContext(DRAG_DROP_CONTEXT_KEY);
6
+ function handleDragStart(event) {
7
+ const source = event.operation.source;
8
+ if (!source) return;
9
+ ctx.setDraggingId(String(source.id));
10
+ }
11
+ function handleDragEnd(event) {
12
+ const source = event.operation.source;
13
+ const target = event.operation.target;
14
+ ctx.setDraggingId(null);
15
+ if (!source || !target) return;
16
+ const zone = ctx.getDroppable(String(target.id));
17
+ if (!zone) return;
18
+ const payload = ctx.toPayload({
19
+ id: source.id,
20
+ data: source.data
21
+ });
22
+ if (zone.accept && !zone.accept(payload)) return;
23
+ zone.onDrop(payload);
24
+ }
25
+ </script>
26
+
27
+ <DragDropProvider onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
28
+ {@render children?.()}
29
+ </DragDropProvider>
@@ -0,0 +1,7 @@
1
+ import { type Snippet } from 'svelte';
2
+ interface Props {
3
+ children?: Snippet;
4
+ }
5
+ declare const DragDropProviderScope: import("svelte").Component<Props, {}, "">;
6
+ type DragDropProviderScope = ReturnType<typeof DragDropProviderScope>;
7
+ export default DragDropProviderScope;
@@ -0,0 +1,68 @@
1
+ <script lang="ts" generics="T">import { DragDropProvider, DragOverlay } from "@dnd-kit/svelte";
2
+ import { RestrictToHorizontalAxis, RestrictToVerticalAxis } from "@dnd-kit/abstract/modifiers";
3
+ import { isSortableOperation } from "@dnd-kit/dom/sortable";
4
+ import { getContext } from "svelte";
5
+ import { moveArrayItem } from "../useSortable/sortable-utils.js";
6
+ import { SORTABLE_CONTEXT_KEY, SORTABLE_GROUP_CONTEXT_KEY } from "./sortable-context.js";
7
+ let { children, overlay } = $props();
8
+ const ctx = getContext(SORTABLE_CONTEXT_KEY);
9
+ const groupCtx = getContext(SORTABLE_GROUP_CONTEXT_KEY);
10
+ const isGrouped = !!groupCtx;
11
+ // Register/unregister overlay snippet with the parent SortableGroup
12
+ $effect(() => {
13
+ if (groupCtx && overlay) {
14
+ groupCtx.registerOverlay(ctx.groupId, overlay);
15
+ return () => {
16
+ groupCtx.unregisterOverlay(ctx.groupId);
17
+ };
18
+ }
19
+ });
20
+ const modifiers = $derived(ctx.getAxis() === "horizontal" ? [RestrictToHorizontalAxis] : ctx.getAxis() === "vertical" ? [RestrictToVerticalAxis] : []);
21
+ function handleDragStart(event) {
22
+ const source = event.operation.source;
23
+ if (!source) return;
24
+ const items = ctx.getItems();
25
+ const ownsItem = items.some((entry) => String(ctx.getId(entry)) === String(source.id));
26
+ if (!ownsItem) return;
27
+ ctx.setDraggingId(source.id);
28
+ groupCtx?.setDraggingGroupId(ctx.groupId);
29
+ }
30
+ function handleDragOver(event) {
31
+ // During drag, reorder items optimistically so Svelte re-renders them
32
+ // in the new order — dnd-kit then animates the transition via WAAPI.
33
+ // Without this, items only reorder on drop and there is no push animation.
34
+ if (ctx.isDisabled() || !isSortableOperation(event.operation)) return;
35
+ const { source, target } = event.operation;
36
+ if (!source || !target || source.index === target.index) return;
37
+ // Only handle items that belong to this list
38
+ const items = ctx.getItems();
39
+ const sourceInList = items.some((entry) => String(ctx.getId(entry)) === String(source.id));
40
+ if (!sourceInList) return;
41
+ ctx.onReorder(moveArrayItem(items, source.index, target.index));
42
+ }
43
+ function handleDragEnd(event) {
44
+ const { source } = event.operation;
45
+ // Let the drop animation play (250ms default) before clearing draggingId
46
+ // Items are already in correct order from handleDragOver — nothing to reorder here.
47
+ setTimeout(() => {
48
+ if (ctx.getDraggingId() === source?.id) {
49
+ ctx.setDraggingId(null);
50
+ }
51
+ }, 250);
52
+ }
53
+ </script>
54
+
55
+ {#if isGrouped}
56
+ {@render children?.()}
57
+ {:else}
58
+ <DragDropProvider {modifiers} onDragStart={handleDragStart} onDragOver={handleDragOver} onDragEnd={handleDragEnd}>
59
+ {@render children?.()}
60
+ {#if overlay}
61
+ <DragOverlay>
62
+ {#snippet children(draggable)}
63
+ {@render overlay({ item: draggable.data as T })}
64
+ {/snippet}
65
+ </DragOverlay>
66
+ {/if}
67
+ </DragDropProvider>
68
+ {/if}
@@ -0,0 +1,30 @@
1
+ import { type Snippet } from 'svelte';
2
+ declare function $$render<T>(): {
3
+ props: {
4
+ children?: Snippet;
5
+ overlay?: Snippet<[{
6
+ item: T;
7
+ }]>;
8
+ };
9
+ exports: {};
10
+ bindings: "";
11
+ slots: {};
12
+ events: {};
13
+ };
14
+ declare class __sveltets_Render<T> {
15
+ props(): ReturnType<typeof $$render<T>>['props'];
16
+ events(): ReturnType<typeof $$render<T>>['events'];
17
+ slots(): ReturnType<typeof $$render<T>>['slots'];
18
+ bindings(): "";
19
+ exports(): {};
20
+ }
21
+ interface $$IsomorphicComponent {
22
+ new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
23
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
24
+ } & ReturnType<__sveltets_Render<T>['exports']>;
25
+ <T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
26
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
27
+ }
28
+ declare const SortableProvider: $$IsomorphicComponent;
29
+ type SortableProvider<T> = InstanceType<typeof SortableProvider<T>>;
30
+ export default SortableProvider;
@@ -0,0 +1,12 @@
1
+ import type { DragPayload, UseDroppableOptions } from '../useDragDrop/useDragDrop.svelte.js';
2
+ export declare const DRAG_DROP_CONTEXT_KEY: unique symbol;
3
+ export interface DragDropContextValue {
4
+ registerDroppable: <T>(id: string, options: UseDroppableOptions<T>) => void;
5
+ unregisterDroppable: (id: string) => void;
6
+ setDraggingId: (id: string | null) => void;
7
+ getDroppable: <T>(id: string) => UseDroppableOptions<T> | undefined;
8
+ toPayload: (source: {
9
+ id: string | number;
10
+ data?: unknown;
11
+ }) => DragPayload;
12
+ }
@@ -0,0 +1 @@
1
+ export const DRAG_DROP_CONTEXT_KEY = Symbol('sv5ui-plus-drag-drop');
@@ -0,0 +1,26 @@
1
+ import type { UseSortableOptions } from '../useSortable/useSortable.svelte.js';
2
+ import type { Snippet } from 'svelte';
3
+ export declare const SORTABLE_CONTEXT_KEY: unique symbol;
4
+ export declare const SORTABLE_GROUP_CONTEXT_KEY: unique symbol;
5
+ export interface SortableGroupContextValue {
6
+ draggingId: string | number | null;
7
+ registerOverlay: (groupId: string, snippet: Snippet<[{
8
+ item: unknown;
9
+ }]>) => void;
10
+ unregisterOverlay: (groupId: string) => void;
11
+ getOverlay: (groupId: string) => Snippet<[{
12
+ item: unknown;
13
+ }]> | undefined;
14
+ setDraggingGroupId: (groupId: string | null) => void;
15
+ }
16
+ export interface SortableContextValue<T> {
17
+ groupId: string;
18
+ getItems: UseSortableOptions<T>['getItems'];
19
+ getId: UseSortableOptions<T>['getId'];
20
+ onReorder: UseSortableOptions<T>['onReorder'];
21
+ isDisabled: () => boolean;
22
+ getAxis: () => 'vertical' | 'horizontal' | 'grid';
23
+ getHandle: () => string | undefined;
24
+ setDraggingId: (id: string | number | null) => void;
25
+ getDraggingId: () => string | number | null;
26
+ }
@@ -0,0 +1,2 @@
1
+ export const SORTABLE_CONTEXT_KEY = Symbol('sv5ui-plus-sortable');
2
+ export const SORTABLE_GROUP_CONTEXT_KEY = Symbol('sv5ui-plus-sortable-group');
@@ -0,0 +1 @@
1
+ export * from './useDragDrop.svelte.js';
@@ -0,0 +1 @@
1
+ export * from './useDragDrop.svelte.js';
@@ -0,0 +1,40 @@
1
+ import type { Action } from 'svelte/action';
2
+ import type { Component } from 'svelte';
3
+ import { type Snippet } from 'svelte';
4
+ export interface DragPayload<T = unknown> {
5
+ id: string;
6
+ data?: T;
7
+ }
8
+ export interface UseDraggableOptions<T = unknown> {
9
+ /** Unique id for the draggable element. */
10
+ id: string;
11
+ /** Source drop zone id — used as the draggable type for cross-container matching. */
12
+ container: string;
13
+ data?: T;
14
+ disabled?: boolean | (() => boolean);
15
+ handle?: string;
16
+ }
17
+ export interface UseDroppableOptions<T = unknown> {
18
+ id: string;
19
+ onDrop: (payload: DragPayload<T>) => void;
20
+ accept?: (payload: DragPayload<T>) => boolean;
21
+ disabled?: boolean | (() => boolean);
22
+ }
23
+ export interface UseDragDropReturn {
24
+ /**
25
+ * Wrap drag-and-drop markup with this provider.
26
+ * Required — [@dnd-kit/svelte](https://clauderic-dnd-kit.mintlify.app/frameworks/svelte) needs a DragDropProvider ancestor.
27
+ */
28
+ readonly Provider: Component<{
29
+ children?: Snippet;
30
+ }>;
31
+ readonly draggingId: string | null;
32
+ readonly draggable: Action<HTMLElement, UseDraggableOptions>;
33
+ readonly droppable: Action<HTMLElement, UseDroppableOptions>;
34
+ }
35
+ /**
36
+ * Cross-container drag and drop powered by [@dnd-kit/svelte](https://clauderic-dnd-kit.mintlify.app/frameworks/svelte).
37
+ *
38
+ * Wrap markup in `dragDrop.Provider`, then attach `draggable` and `droppable` actions.
39
+ */
40
+ export declare function useDragDrop(): UseDragDropReturn;
@@ -0,0 +1,128 @@
1
+ import { setContext } from 'svelte';
2
+ import { createDraggable, createDroppable } from '@dnd-kit/svelte';
3
+ import DragDropProviderScope from '../internal/DragDropProviderScope.svelte';
4
+ import { DRAG_DROP_CONTEXT_KEY } from '../internal/drag-drop-context.js';
5
+ /**
6
+ * Cross-container drag and drop powered by [@dnd-kit/svelte](https://clauderic-dnd-kit.mintlify.app/frameworks/svelte).
7
+ *
8
+ * Wrap markup in `dragDrop.Provider`, then attach `draggable` and `droppable` actions.
9
+ */
10
+ export function useDragDrop() {
11
+ let draggingId = $state(null);
12
+ const droppables = new Map();
13
+ const context = {
14
+ registerDroppable(id, options) {
15
+ droppables.set(id, options);
16
+ },
17
+ unregisterDroppable(id) {
18
+ droppables.delete(id);
19
+ },
20
+ setDraggingId(id) {
21
+ draggingId = id;
22
+ },
23
+ getDroppable(id) {
24
+ return droppables.get(id);
25
+ },
26
+ toPayload(source) {
27
+ return {
28
+ id: String(source.id),
29
+ data: source.data
30
+ };
31
+ }
32
+ };
33
+ setContext(DRAG_DROP_CONTEXT_KEY, context);
34
+ const draggableAction = (node, initialOptions) => {
35
+ let currentOptions = initialOptions;
36
+ function isDisabled() {
37
+ return typeof currentOptions.disabled === 'function'
38
+ ? currentOptions.disabled()
39
+ : (currentOptions.disabled ?? false);
40
+ }
41
+ const drag = createDraggable({
42
+ id: currentOptions.id,
43
+ type: currentOptions.container,
44
+ data: (currentOptions.data ?? {}),
45
+ disabled: isDisabled()
46
+ });
47
+ const detach = drag.attach(node);
48
+ let detachHandle;
49
+ function bindHandle() {
50
+ detachHandle?.();
51
+ const selector = currentOptions.handle;
52
+ if (!selector) {
53
+ drag.draggable.handle = undefined;
54
+ detachHandle = undefined;
55
+ return;
56
+ }
57
+ const handle = node.querySelector(selector);
58
+ if (!handle) {
59
+ drag.draggable.handle = undefined;
60
+ detachHandle = undefined;
61
+ return;
62
+ }
63
+ detachHandle = drag.attachHandle(handle);
64
+ }
65
+ bindHandle();
66
+ return {
67
+ update(newOptions) {
68
+ currentOptions = newOptions;
69
+ drag.draggable.id = newOptions.id;
70
+ drag.draggable.type = newOptions.container;
71
+ drag.draggable.data = (newOptions.data ?? {});
72
+ drag.draggable.disabled = isDisabled();
73
+ bindHandle();
74
+ },
75
+ destroy() {
76
+ detach();
77
+ detachHandle?.();
78
+ node.removeAttribute('data-dragging');
79
+ if (draggingId === currentOptions.id) {
80
+ draggingId = null;
81
+ }
82
+ }
83
+ };
84
+ };
85
+ const droppableAction = (node, initialOptions) => {
86
+ let currentOptions = initialOptions;
87
+ function isDisabled() {
88
+ return typeof currentOptions.disabled === 'function'
89
+ ? currentOptions.disabled()
90
+ : (currentOptions.disabled ?? false);
91
+ }
92
+ context.registerDroppable(currentOptions.id, currentOptions);
93
+ const drop = createDroppable({
94
+ id: currentOptions.id,
95
+ disabled: isDisabled(),
96
+ accept(source) {
97
+ const payload = context.toPayload({ id: source.id, data: source.data });
98
+ if (currentOptions.accept) {
99
+ return currentOptions.accept(payload);
100
+ }
101
+ return true;
102
+ }
103
+ });
104
+ const detach = drop.attach(node);
105
+ return {
106
+ update(newOptions) {
107
+ context.unregisterDroppable(currentOptions.id);
108
+ currentOptions = newOptions;
109
+ context.registerDroppable(currentOptions.id, currentOptions);
110
+ drop.droppable.id = newOptions.id;
111
+ drop.droppable.disabled = isDisabled();
112
+ },
113
+ destroy() {
114
+ detach();
115
+ context.unregisterDroppable(currentOptions.id);
116
+ node.removeAttribute('data-droppable-active');
117
+ }
118
+ };
119
+ };
120
+ return {
121
+ get draggingId() {
122
+ return draggingId;
123
+ },
124
+ Provider: DragDropProviderScope,
125
+ draggable: draggableAction,
126
+ droppable: droppableAction
127
+ };
128
+ }
@@ -0,0 +1,2 @@
1
+ export * from './useSortable.svelte.js';
2
+ export { moveArrayItem } from './sortable-utils.js';
@@ -0,0 +1,2 @@
1
+ export * from './useSortable.svelte.js';
2
+ export { moveArrayItem } from './sortable-utils.js';
@@ -0,0 +1 @@
1
+ export declare function moveArrayItem<T>(items: T[], fromIndex: number, toIndex: number): T[];
@@ -0,0 +1,13 @@
1
+ export function moveArrayItem(items, fromIndex, toIndex) {
2
+ if (fromIndex === toIndex ||
3
+ fromIndex < 0 ||
4
+ toIndex < 0 ||
5
+ fromIndex >= items.length ||
6
+ toIndex >= items.length) {
7
+ return items;
8
+ }
9
+ const next = [...items];
10
+ const [removed] = next.splice(fromIndex, 1);
11
+ next.splice(toIndex, 0, removed);
12
+ return next;
13
+ }
@@ -0,0 +1,60 @@
1
+ import type { Action } from 'svelte/action';
2
+ import type { Component } from 'svelte';
3
+ import { type Snippet } from 'svelte';
4
+ export interface UseSortableItemParams<T> {
5
+ index: number;
6
+ item: T;
7
+ }
8
+ export interface UseSortableOptions<T> {
9
+ /** Reactive getter for the current item array. */
10
+ getItems: () => T[];
11
+ /** Stable id for each item — used for keys and reorder tracking. */
12
+ getId: (item: T) => string | number;
13
+ /** Called with the reordered array after a successful drop. */
14
+ onReorder: (items: T[]) => void;
15
+ /**
16
+ * Drag axis.
17
+ * @default 'vertical'
18
+ */
19
+ axis?: 'vertical' | 'horizontal' | 'grid' | (() => 'vertical' | 'horizontal' | 'grid');
20
+ /**
21
+ * CSS selector for the drag handle, relative to each item.
22
+ * When omitted, the whole item is draggable.
23
+ * @example '[data-sortable-handle]'
24
+ */
25
+ handle?: string | (() => string | undefined);
26
+ /**
27
+ * Disable sorting.
28
+ * @default false
29
+ */
30
+ disabled?: boolean | (() => boolean);
31
+ /**
32
+ * Group ID for the sortable list. Used for cross-list drag and drop.
33
+ * If not provided, a unique ID is generated.
34
+ */
35
+ group?: string | (() => string | undefined);
36
+ }
37
+ export interface UseSortableReturn<T> {
38
+ /**
39
+ * Wrap sortable markup with this provider.
40
+ * Required — [@dnd-kit/svelte](https://clauderic-dnd-kit.mintlify.app/frameworks/svelte) needs a DragDropProvider ancestor.
41
+ */
42
+ readonly Provider: Component<{
43
+ children?: Snippet;
44
+ overlay?: Snippet<[{
45
+ item: T;
46
+ }]>;
47
+ }>;
48
+ /** Attach to the list container element (optional wrapper). */
49
+ readonly container: Action<HTMLElement>;
50
+ /** Attach to each sortable row with the current index and item. */
51
+ readonly item: Action<HTMLElement, UseSortableItemParams<T>>;
52
+ /** Id of the item currently being dragged, or null. */
53
+ readonly draggingId: string | number | null;
54
+ }
55
+ /**
56
+ * Sortable list hook powered by [@dnd-kit/svelte](https://clauderic-dnd-kit.mintlify.app/frameworks/svelte).
57
+ *
58
+ * Wrap markup in `sortable.Provider`, then attach `use:sortable.item` to each row.
59
+ */
60
+ export declare function useSortable<T>(options: UseSortableOptions<T>): UseSortableReturn<T>;