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
@@ -0,0 +1,623 @@
1
+ <script lang="ts" module>export {};
2
+ </script>
3
+
4
+ <script lang="ts">import { NavigationMenu as Bits } from "bits-ui";
5
+ import { tick, untrack } from "svelte";
6
+ import { SvelteSet } from "svelte/reactivity";
7
+ import { slide } from "svelte/transition";
8
+ import { page } from "$app/state";
9
+ import { useMediaQuery, useResizeObserver } from "sv5ui";
10
+ import { navigationMenuVariants, navigationMenuDefaults } from "./navigation-menu.variants.js";
11
+ import { getComponentConfig, iconsDefaults } from "../../config.js";
12
+ import { Icon } from "sv5ui";
13
+ import { Link } from "sv5ui";
14
+ import { Badge } from "sv5ui";
15
+ import { Chip } from "sv5ui";
16
+ import { Avatar } from "sv5ui";
17
+ import { Tooltip } from "sv5ui";
18
+ import { Popover } from "sv5ui";
19
+ import { Drawer } from "sv5ui";
20
+ import { Button } from "sv5ui";
21
+ const config = getComponentConfig("navigationMenu", navigationMenuDefaults);
22
+ const icons = getComponentConfig("icons", iconsDefaults);
23
+ let { ref = $bindable(null), as = "nav", type = "multiple", value = $bindable(), defaultValue, onValueChange, items = [], orientation = "horizontal", collapsed = false, collapsible = true, highlight = false, stacked = false, variant = config.defaultVariants.variant ?? "pill", color = config.defaultVariants.color ?? "primary", trailingIcon = icons.chevronDown, externalIcon = true, arrow = false, tooltip = false, popover = false, contentOrientation = "horizontal", labelKey = "label", exact = true, delayDuration = 0, skipDelayDuration, disableClickTrigger = false, disableHoverTrigger = false, unmountOnHide = true, disabled = false, drawer = false, drawerOpen = $bindable(false), mobileBreakpoint = "(max-width: 767px)", drawerWidth = "min(20rem, 80vw)", drawerProps, class: className, ui, item: itemSlot, itemLeading, itemLabel, itemTrailing, itemActions, itemContent, listLeading, listTrailing, ...restProps } = $props();
24
+ const groups = $derived(Array.isArray(items[0]) ? items : [items]);
25
+ function itemValue(item, groupIndex, index) {
26
+ return item.value ?? `${groupIndex}-${index}`;
27
+ }
28
+ function itemLabelText(item) {
29
+ const label = item[labelKey];
30
+ return typeof label === "string" ? label : item.label ?? "";
31
+ }
32
+ function isExternal(href) {
33
+ return !!href && /^(https?:)?\/\//.test(href);
34
+ }
35
+ const UNSAFE_SCHEMES = [
36
+ "javascript:",
37
+ "data:",
38
+ "vbscript:"
39
+ ];
40
+ function safeHref(href) {
41
+ if (!href) return undefined;
42
+ const normalized = href.replaceAll(" ", "").replaceAll("\n", "").replaceAll("\r", "").trim().toLowerCase();
43
+ if (UNSAFE_SCHEMES.some((scheme) => normalized.startsWith(scheme))) return undefined;
44
+ return href;
45
+ }
46
+ function isItemActive(active, href, itemExact) {
47
+ if (active !== undefined) return active;
48
+ if (!href || isExternal(href) || !page.url) return false;
49
+ const useExact = itemExact ?? exact;
50
+ return useExact ? page.url.pathname === href : page.url.pathname === href || page.url.pathname.startsWith(`${href}/`);
51
+ }
52
+ function hasChildren(item) {
53
+ return Array.isArray(item.children) && item.children.length > 0;
54
+ }
55
+ function asProps(v) {
56
+ return v && typeof v === "object" ? v : {};
57
+ }
58
+ function blockClick(e) {
59
+ e.preventDefault();
60
+ }
61
+ let flyoutKey = $state(null);
62
+ let flyoutTimer;
63
+ function openFlyout(key) {
64
+ clearTimeout(flyoutTimer);
65
+ flyoutKey = key;
66
+ }
67
+ function closeFlyoutSoon() {
68
+ clearTimeout(flyoutTimer);
69
+ flyoutTimer = setTimeout(() => flyoutKey = null, 150);
70
+ }
71
+ function handleFlyoutChange(open, key) {
72
+ if (open) openFlyout(key);
73
+ else if (flyoutKey === key) flyoutKey = null;
74
+ }
75
+ function resolvedType(item) {
76
+ if (item.type) return item.type;
77
+ return hasChildren(item) ? "trigger" : "link";
78
+ }
79
+ function isDropdown(item) {
80
+ return resolvedType(item) === "trigger" && (hasChildren(item) || !!itemContent);
81
+ }
82
+ if (value === undefined) {
83
+ value = untrack(() => {
84
+ if (defaultValue !== undefined) return defaultValue;
85
+ const open = [];
86
+ groups.forEach((group, gi) => group.forEach((item, i) => {
87
+ if ((item.defaultOpen || item.open) && hasChildren(item)) {
88
+ open.push(itemValue(item, gi, i));
89
+ }
90
+ }));
91
+ return type === "multiple" ? open : open[0];
92
+ });
93
+ }
94
+ const openSet = $derived(new Set(Array.isArray(value) ? value : value !== undefined ? [value] : []));
95
+ function emit(next) {
96
+ value = next;
97
+ onValueChange?.(next);
98
+ }
99
+ function toggleOpen(v) {
100
+ if (type === "single") {
101
+ emit(openSet.has(v) ? undefined : v);
102
+ } else {
103
+ const next = new SvelteSet(openSet);
104
+ if (next.has(v)) next.delete(v);
105
+ else next.add(v);
106
+ emit([...next]);
107
+ }
108
+ }
109
+ const horizontalValue = $derived(typeof value === "string" ? value : Array.isArray(value) ? value[0] : undefined);
110
+ const isMobile = useMediaQuery(() => mobileBreakpoint);
111
+ const showDrawer = $derived(drawer && isMobile.matches);
112
+ const effectiveOrientation = $derived(showDrawer ? "vertical" : orientation);
113
+ const effectiveCollapsed = $derived(collapsed && !showDrawer);
114
+ let previousPath = page.url?.pathname;
115
+ $effect(() => {
116
+ const path = page.url?.pathname;
117
+ if (path !== previousPath) {
118
+ previousPath = path;
119
+ drawerOpen = false;
120
+ }
121
+ });
122
+ const variantSlots = $derived(navigationMenuVariants({
123
+ variant,
124
+ color,
125
+ orientation: effectiveOrientation,
126
+ highlight,
127
+ collapsed: effectiveCollapsed,
128
+ stacked,
129
+ contentOrientation,
130
+ disabled
131
+ }));
132
+ const classes = $derived({
133
+ root: variantSlots.root({ class: [
134
+ config.slots.root,
135
+ ui?.root,
136
+ className
137
+ ] }),
138
+ list: variantSlots.list({ class: [config.slots.list, ui?.list] }),
139
+ highlight: variantSlots.highlight({ class: [config.slots.highlight, ui?.highlight] }),
140
+ item: variantSlots.item({ class: [config.slots.item, ui?.item] }),
141
+ label: variantSlots.label({ class: [config.slots.label, ui?.label] }),
142
+ separator: variantSlots.separator({ class: [config.slots.separator, ui?.separator] }),
143
+ link: variantSlots.link({ class: [config.slots.link, ui?.link] }),
144
+ linkLeadingIcon: variantSlots.linkLeadingIcon({ class: [config.slots.linkLeadingIcon, ui?.linkLeadingIcon] }),
145
+ linkLeadingAvatar: variantSlots.linkLeadingAvatar({ class: [config.slots.linkLeadingAvatar, ui?.linkLeadingAvatar] }),
146
+ linkLabel: variantSlots.linkLabel({ class: [config.slots.linkLabel, ui?.linkLabel] }),
147
+ linkLabelExternalIcon: variantSlots.linkLabelExternalIcon({ class: [config.slots.linkLabelExternalIcon, ui?.linkLabelExternalIcon] }),
148
+ linkTrailing: variantSlots.linkTrailing({ class: [config.slots.linkTrailing, ui?.linkTrailing] }),
149
+ linkTrailingBadge: variantSlots.linkTrailingBadge({ class: [config.slots.linkTrailingBadge, ui?.linkTrailingBadge] }),
150
+ linkTrailingIcon: variantSlots.linkTrailingIcon({ class: [config.slots.linkTrailingIcon, ui?.linkTrailingIcon] }),
151
+ childList: variantSlots.childList({ class: [config.slots.childList, ui?.childList] }),
152
+ childLabel: variantSlots.childLabel({ class: [config.slots.childLabel, ui?.childLabel] }),
153
+ childItem: variantSlots.childItem({ class: [config.slots.childItem, ui?.childItem] }),
154
+ childLink: variantSlots.childLink({ class: [config.slots.childLink, ui?.childLink] }),
155
+ childLinkWrapper: variantSlots.childLinkWrapper({ class: [config.slots.childLinkWrapper, ui?.childLinkWrapper] }),
156
+ childLinkIcon: variantSlots.childLinkIcon({ class: [config.slots.childLinkIcon, ui?.childLinkIcon] }),
157
+ childLinkLabel: variantSlots.childLinkLabel({ class: [config.slots.childLinkLabel, ui?.childLinkLabel] }),
158
+ childLinkDescription: variantSlots.childLinkDescription({ class: [config.slots.childLinkDescription, ui?.childLinkDescription] }),
159
+ childGroup: variantSlots.childGroup({ class: [config.slots.childGroup, ui?.childGroup] }),
160
+ childGroupLabel: variantSlots.childGroupLabel({ class: [config.slots.childGroupLabel, ui?.childGroupLabel] }),
161
+ childGroupList: variantSlots.childGroupList({ class: [config.slots.childGroupList, ui?.childGroupList] }),
162
+ linkBadgeDot: variantSlots.linkBadgeDot({ class: [config.slots.linkBadgeDot, ui?.linkBadgeDot] }),
163
+ itemActions: variantSlots.itemActions({ class: [config.slots.itemActions, ui?.itemActions] }),
164
+ labelActions: variantSlots.labelActions({ class: [config.slots.labelActions, ui?.labelActions] }),
165
+ content: variantSlots.content({ class: [config.slots.content, ui?.content] }),
166
+ viewportWrapper: variantSlots.viewportWrapper({ class: [config.slots.viewportWrapper, ui?.viewportWrapper] }),
167
+ viewport: variantSlots.viewport({ class: [config.slots.viewport, ui?.viewport] }),
168
+ indicator: variantSlots.indicator({ class: [config.slots.indicator, ui?.indicator] }),
169
+ arrow: variantSlots.arrow({ class: [config.slots.arrow, ui?.arrow] }),
170
+ childTrigger: variantSlots.childTrigger({ class: [config.slots.childTrigger, ui?.childTrigger] })
171
+ });
172
+ function linkClass(item) {
173
+ if (!item.ui?.link && item.class === undefined) return classes.link;
174
+ return variantSlots.link({ class: [
175
+ config.slots.link,
176
+ ui?.link,
177
+ item.ui?.link,
178
+ item.class
179
+ ] });
180
+ }
181
+ const contentProps = $derived({ forceMount: !unmountOnHide || undefined });
182
+ let listEl = $state(null);
183
+ let highlightStyle = $state("");
184
+ let rafId = 0;
185
+ const showHighlight = $derived(highlight && variant !== "pill");
186
+ function updateIndicator() {
187
+ if (!showHighlight || !listEl) return;
188
+ const activeEl = listEl.querySelector("[data-active]");
189
+ if (!activeEl) {
190
+ highlightStyle = "opacity:0";
191
+ return;
192
+ }
193
+ highlightStyle = effectiveOrientation === "horizontal" ? `left:${activeEl.offsetLeft}px;width:${activeEl.offsetWidth}px` : `top:${activeEl.offsetTop}px;height:${activeEl.offsetHeight}px`;
194
+ }
195
+ function scheduleIndicator() {
196
+ cancelAnimationFrame(rafId);
197
+ rafId = requestAnimationFrame(updateIndicator);
198
+ }
199
+ useResizeObserver(() => listEl, scheduleIndicator);
200
+ $effect(() => {
201
+ void value;
202
+ void page.url;
203
+ void items;
204
+ void effectiveOrientation;
205
+ void showHighlight;
206
+ if (showHighlight) tick().then(updateIndicator);
207
+ });
208
+ $effect(() => () => cancelAnimationFrame(rafId));
209
+ $effect(() => () => clearTimeout(flyoutTimer));
210
+ </script>
211
+
212
+ {#snippet leading(item: NavigationMenuItem, index: number, open: boolean)}
213
+ {#if itemLeading}
214
+ {@render itemLeading({ item, index, active: !!item.active, open })}
215
+ {:else if item.avatar}
216
+ {#if item.chip}
217
+ <Chip
218
+ inset
219
+ {...typeof item.chip === 'object' ? item.chip : {}}
220
+ class={classes.linkLeadingAvatar}
221
+ >
222
+ <Avatar size="2xs" {...item.avatar} />
223
+ </Chip>
224
+ {:else}
225
+ <Avatar size="2xs" {...item.avatar} class={classes.linkLeadingAvatar} />
226
+ {/if}
227
+ {:else if item.icon}
228
+ <Icon name={item.icon} class={classes.linkLeadingIcon} />
229
+ {/if}
230
+ {/snippet}
231
+
232
+ {#snippet label(item: NavigationMenuItem, index: number, open: boolean)}
233
+ {#if itemLabel}
234
+ {@render itemLabel({ item, index, active: !!item.active, open })}
235
+ {:else}
236
+ <span class={classes.linkLabel}>{itemLabelText(item)}</span>
237
+ {#if externalIcon !== false && isExternal(item.href)}
238
+ <Icon
239
+ name={typeof externalIcon === 'string' ? externalIcon : icons.external}
240
+ class={classes.linkLabelExternalIcon}
241
+ />
242
+ {/if}
243
+ {/if}
244
+ {/snippet}
245
+
246
+ {#snippet trailing(item: NavigationMenuItem, index: number, open: boolean, isTrigger: boolean)}
247
+ {#if itemTrailing}
248
+ {@render itemTrailing({ item, index, active: !!item.active, open })}
249
+ {:else}
250
+ <span class={classes.linkTrailing}>
251
+ {#if item.badge !== undefined}
252
+ <Badge
253
+ size="sm"
254
+ color="surface"
255
+ variant="soft"
256
+ {...typeof item.badge === 'object' ? item.badge : { label: item.badge }}
257
+ class={classes.linkTrailingBadge}
258
+ />
259
+ {/if}
260
+ {#if isTrigger}
261
+ <Icon
262
+ name={item.trailingIcon ?? trailingIcon}
263
+ class={[classes.linkTrailingIcon, open ? 'rotate-180' : '']}
264
+ />
265
+ {/if}
266
+ </span>
267
+ {/if}
268
+ {/snippet}
269
+
270
+ {#snippet linkBody(item: NavigationMenuItem, index: number, open: boolean, isTrigger: boolean)}
271
+ {@render leading(item, index, open)}
272
+ {@render label(item, index, open)}
273
+ {@render trailing(item, index, open, isTrigger)}
274
+ {#if (effectiveCollapsed || stacked) && item.badge !== undefined}
275
+ <span class={classes.linkBadgeDot} data-navigation-menu-badge-dot="" aria-hidden="true"
276
+ ></span>
277
+ {/if}
278
+ {/snippet}
279
+
280
+ {#snippet childLink(sub: NavigationMenuChildItem)}
281
+ {#if sub.children?.length}
282
+ <li class={classes.childGroup}>
283
+ <p class={classes.childGroupLabel}>{sub.label}</p>
284
+ <ul class={classes.childGroupList}>
285
+ {#each sub.children as grandchild, gi (grandchild.href ?? gi)}
286
+ {@render childLink(grandchild)}
287
+ {/each}
288
+ </ul>
289
+ </li>
290
+ {:else}
291
+ {@const active = isItemActive(sub.active, sub.href, sub.exact)}
292
+ <li class={classes.childItem}>
293
+ <Link
294
+ href={safeHref(sub.href)}
295
+ target={sub.target}
296
+ raw
297
+ exact={sub.exact ?? exact}
298
+ {active}
299
+ onclick={sub.onSelect}
300
+ data-active={active ? '' : undefined}
301
+ class={[classes.childLink, sub.class]}
302
+ >
303
+ {#if sub.icon}
304
+ <Icon name={sub.icon} class={classes.childLinkIcon} />
305
+ {/if}
306
+ <span class={classes.childLinkWrapper}>
307
+ <span class="inline-flex items-center gap-1">
308
+ <span class={classes.childLinkLabel}>{sub.label}</span>
309
+ {#if externalIcon !== false && isExternal(sub.href)}
310
+ <Icon
311
+ name={typeof externalIcon === 'string'
312
+ ? externalIcon
313
+ : icons.external}
314
+ class={classes.linkLabelExternalIcon}
315
+ />
316
+ {/if}
317
+ </span>
318
+ {#if sub.description}
319
+ <span class={classes.childLinkDescription}>{sub.description}</span>
320
+ {/if}
321
+ </span>
322
+ </Link>
323
+ </li>
324
+ {/if}
325
+ {/snippet}
326
+
327
+ {#snippet megaContent(item: NavigationMenuItem, index: number)}
328
+ {#if itemContent}
329
+ {@render itemContent({ item, index })}
330
+ {:else}
331
+ <ul class={classes.childList}>
332
+ {#each item.children ?? [] as child, ci (child.href ?? ci)}
333
+ {@render childLink(child)}
334
+ {/each}
335
+ </ul>
336
+ {/if}
337
+ {/snippet}
338
+
339
+ {#snippet horizontalMenu()}
340
+ <Bits.Root
341
+ bind:ref
342
+ value={horizontalValue}
343
+ onValueChange={(v) => emit(v || undefined)}
344
+ orientation="horizontal"
345
+ {delayDuration}
346
+ {skipDelayDuration}
347
+ class={classes.root}
348
+ {...restProps as Record<string, unknown>}
349
+ >
350
+ <Bits.List bind:ref={listEl} class={classes.list}>
351
+ {#if showHighlight}
352
+ <div
353
+ class={classes.highlight}
354
+ style={highlightStyle}
355
+ data-navigation-menu-highlight=""
356
+ aria-hidden="true"
357
+ ></div>
358
+ {/if}
359
+ {#if listLeading}{@render listLeading()}{/if}
360
+ {#each groups as group, gi (gi)}
361
+ {#each group as item, index (itemValue(item, gi, index))}
362
+ {@const iv = itemValue(item, gi, index)}
363
+ {@const kind = resolvedType(item)}
364
+ {@const open = openSet.has(iv)}
365
+ {#if itemSlot}
366
+ <Bits.Item value={iv} class={classes.item}>
367
+ {@render itemSlot({ item, index, active: !!item.active, open })}
368
+ </Bits.Item>
369
+ {:else if kind === 'label'}
370
+ <li class={classes.label}>{itemLabelText(item)}</li>
371
+ {:else if isDropdown(item)}
372
+ <Bits.Item
373
+ value={iv}
374
+ openOnHover={!disableHoverTrigger}
375
+ class={classes.item}
376
+ >
377
+ <Bits.Trigger disabled={disabled || item.disabled}>
378
+ {#snippet child({ props }: { props: Record<string, unknown> })}
379
+ <button
380
+ {...disableClickTrigger
381
+ ? { ...props, onclick: blockClick }
382
+ : props}
383
+ class={linkClass(item)}
384
+ data-active={item.active ? '' : undefined}
385
+ >
386
+ {@render linkBody(item, index, open, true)}
387
+ </button>
388
+ {/snippet}
389
+ </Bits.Trigger>
390
+ <Bits.Content {...contentProps} class={classes.content}>
391
+ {@render megaContent(item, index)}
392
+ </Bits.Content>
393
+ </Bits.Item>
394
+ {:else}
395
+ {@const active = isItemActive(item.active, item.href, item.exact)}
396
+ {@const href = safeHref(item.href)}
397
+ <Bits.Item value={iv} class={classes.item}>
398
+ <Bits.Link {href} {active} onSelect={item.onSelect}>
399
+ {#snippet child({ props }: { props: Record<string, unknown> })}
400
+ <Link
401
+ {href}
402
+ target={item.target}
403
+ raw
404
+ exact={item.exact ?? exact}
405
+ {active}
406
+ disabled={disabled || item.disabled}
407
+ {...props}
408
+ class={linkClass(item)}
409
+ >
410
+ {@render linkBody(item, index, open, false)}
411
+ </Link>
412
+ {/snippet}
413
+ </Bits.Link>
414
+ </Bits.Item>
415
+ {/if}
416
+ {/each}
417
+ {#if gi < groups.length - 1}
418
+ <li role="separator" aria-orientation="vertical" class={classes.separator}></li>
419
+ {/if}
420
+ {/each}
421
+ {#if listTrailing}{@render listTrailing()}{/if}
422
+ {#if arrow}
423
+ <Bits.Indicator class={classes.indicator}>
424
+ <div class={classes.arrow}></div>
425
+ </Bits.Indicator>
426
+ {/if}
427
+ </Bits.List>
428
+ <div class={classes.viewportWrapper}>
429
+ <Bits.Viewport {...contentProps} class={classes.viewport} />
430
+ </div>
431
+ </Bits.Root>
432
+ {/snippet}
433
+
434
+ {#snippet verticalLeaf(item: NavigationMenuItem, index: number)}
435
+ {@const active = isItemActive(item.active, item.href, item.exact)}
436
+ {@const collapsedTip = effectiveCollapsed && !stacked && (item.tooltip ?? tooltip)}
437
+ {#if collapsedTip}
438
+ <Tooltip text={itemLabelText(item)} side="right" {...asProps(item.tooltip ?? tooltip)}>
439
+ <Link
440
+ href={safeHref(item.href)}
441
+ target={item.target}
442
+ raw
443
+ exact={item.exact ?? exact}
444
+ {active}
445
+ disabled={disabled || item.disabled}
446
+ onclick={item.onSelect}
447
+ data-active={active ? '' : undefined}
448
+ class={linkClass(item)}
449
+ >
450
+ {@render linkBody(item, index, false, false)}
451
+ </Link>
452
+ </Tooltip>
453
+ {:else}
454
+ <Link
455
+ href={safeHref(item.href)}
456
+ target={item.target}
457
+ raw
458
+ exact={item.exact ?? exact}
459
+ {active}
460
+ disabled={disabled || item.disabled}
461
+ onclick={item.onSelect}
462
+ data-active={active ? '' : undefined}
463
+ class={linkClass(item)}
464
+ >
465
+ {@render linkBody(item, index, false, false)}
466
+ </Link>
467
+ {/if}
468
+ {/snippet}
469
+
470
+ {#snippet verticalItem(item: NavigationMenuItem, index: number, groupIndex: number)}
471
+ {@const iv = itemValue(item, groupIndex, index)}
472
+ {@const kind = resolvedType(item)}
473
+ {@const open = openSet.has(iv)}
474
+ <li class={[classes.item, itemActions ? 'group/nav-row relative' : '']}>
475
+ {#if itemSlot}
476
+ {@render itemSlot({ item, index, active: !!item.active, open })}
477
+ {:else if kind === 'label'}
478
+ <div class={classes.label}>
479
+ {itemLabelText(item)}
480
+ {#if itemActions}
481
+ <span class={classes.labelActions}>
482
+ {@render itemActions({ item, index, active: !!item.active, open })}
483
+ </span>
484
+ {/if}
485
+ </div>
486
+ {:else if isDropdown(item)}
487
+ {#if effectiveCollapsed}
488
+ <Popover
489
+ side="right"
490
+ sideOffset={8}
491
+ {...asProps(item.popover ?? popover)}
492
+ open={flyoutKey === iv}
493
+ onOpenChange={(open) => handleFlyoutChange(open, iv)}
494
+ ui={{
495
+ content:
496
+ 'origin-left data-[state=open]:animate-[zoom-in_150ms_ease] data-[state=closed]:animate-[zoom-out_150ms_ease]'
497
+ }}
498
+ >
499
+ <span
500
+ role="button"
501
+ tabindex={disabled || item.disabled ? undefined : 0}
502
+ aria-expanded={flyoutKey === iv}
503
+ class={linkClass(item)}
504
+ onpointerenter={() => openFlyout(iv)}
505
+ onpointerleave={closeFlyoutSoon}
506
+ onclickcapture={(e) => {
507
+ e.stopPropagation()
508
+ openFlyout(iv)
509
+ }}
510
+ onkeydown={(e) => {
511
+ if (e.key !== 'Enter' && e.key !== ' ') return
512
+ e.preventDefault()
513
+ openFlyout(iv)
514
+ }}
515
+ >
516
+ {@render linkBody(item, index, false, false)}
517
+ </span>
518
+ {#snippet content()}
519
+ <div
520
+ role="presentation"
521
+ class="min-w-52 p-1"
522
+ onpointerenter={() => clearTimeout(flyoutTimer)}
523
+ onpointerleave={closeFlyoutSoon}
524
+ >
525
+ {#if itemContent}
526
+ {@render itemContent({ item, index })}
527
+ {:else}
528
+ <p class={classes.childLabel}>{itemLabelText(item)}</p>
529
+ <ul class="grid gap-0.5">
530
+ {#each item.children ?? [] as child, ci (child.href ?? ci)}
531
+ {@render childLink(child)}
532
+ {/each}
533
+ </ul>
534
+ {/if}
535
+ </div>
536
+ {/snippet}
537
+ </Popover>
538
+ {:else}
539
+ <button
540
+ type="button"
541
+ class={linkClass(item)}
542
+ aria-expanded={open}
543
+ disabled={disabled || item.disabled || !collapsible}
544
+ data-state={open ? 'open' : 'closed'}
545
+ onclick={() => toggleOpen(iv)}
546
+ >
547
+ {@render linkBody(item, index, open, true)}
548
+ </button>
549
+ {#if open}
550
+ <ul class={classes.childList} transition:slide={{ duration: 200 }}>
551
+ {#each item.children ?? [] as child, ci (child.href ?? ci)}
552
+ {@render childLink(child)}
553
+ {/each}
554
+ </ul>
555
+ {/if}
556
+ {/if}
557
+ {:else}
558
+ {@render verticalLeaf(item, index)}
559
+ {#if itemActions}
560
+ <div class={classes.itemActions}>
561
+ {@render itemActions({ item, index, active: !!item.active, open })}
562
+ </div>
563
+ {/if}
564
+ {/if}
565
+ </li>
566
+ {/snippet}
567
+
568
+ {#snippet verticalMenu()}
569
+ <svelte:element
570
+ this={as}
571
+ bind:this={ref}
572
+ aria-label="Navigation"
573
+ class={classes.root}
574
+ {...restProps}
575
+ >
576
+ <ul bind:this={listEl} class={classes.list}>
577
+ {#if showHighlight}
578
+ <div
579
+ class={classes.highlight}
580
+ style={highlightStyle}
581
+ data-navigation-menu-highlight=""
582
+ aria-hidden="true"
583
+ ></div>
584
+ {/if}
585
+ {#if listLeading}{@render listLeading()}{/if}
586
+ {#each groups as group, gi (gi)}
587
+ {#each group as item, index (itemValue(item, gi, index))}
588
+ {@render verticalItem(item, index, gi)}
589
+ {/each}
590
+ {#if gi < groups.length - 1}
591
+ <li
592
+ role="separator"
593
+ aria-orientation="horizontal"
594
+ class={classes.separator}
595
+ ></li>
596
+ {/if}
597
+ {/each}
598
+ {#if listTrailing}{@render listTrailing()}{/if}
599
+ </ul>
600
+ </svelte:element>
601
+ {/snippet}
602
+
603
+ {#if showDrawer}
604
+ <Button
605
+ icon={drawerOpen ? icons.close : icons.menu}
606
+ variant="ghost"
607
+ color="surface"
608
+ aria-label="Toggle navigation"
609
+ aria-expanded={drawerOpen}
610
+ onclick={() => (drawerOpen = !drawerOpen)}
611
+ />
612
+ <Drawer bind:open={drawerOpen} direction="left" {...drawerProps}>
613
+ {#snippet body()}
614
+ <div style="width: {drawerWidth}">
615
+ {@render verticalMenu()}
616
+ </div>
617
+ {/snippet}
618
+ </Drawer>
619
+ {:else if orientation === 'horizontal'}
620
+ {@render horizontalMenu()}
621
+ {:else}
622
+ {@render verticalMenu()}
623
+ {/if}
@@ -0,0 +1,5 @@
1
+ import type { NavigationMenuProps } from './navigation-menu.types.js';
2
+ export type Props = NavigationMenuProps;
3
+ declare const NavigationMenu: import("svelte").Component<NavigationMenuProps, {}, "value" | "ref" | "drawerOpen">;
4
+ type NavigationMenu = ReturnType<typeof NavigationMenu>;
5
+ export default NavigationMenu;
@@ -0,0 +1,2 @@
1
+ export { default as SvelteKitNavigationMenu } from './NavigationMenu.svelte';
2
+ export type { NavigationMenuProps as SvelteKitNavigationMenuProps, NavigationMenuItem as SvelteKitNavigationMenuItem, NavigationMenuChildItem as SvelteKitNavigationMenuChildItem, NavigationMenuValue as SvelteKitNavigationMenuValue } from './navigation-menu.types.js';
@@ -0,0 +1 @@
1
+ export { default as SvelteKitNavigationMenu } from './NavigationMenu.svelte';