fluentui-svelte 0.5.0 → 0.7.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 (259) hide show
  1. package/dist/components/app-surface/app-surface.svelte +96 -0
  2. package/dist/components/app-surface/app-surface.svelte.d.ts +22 -0
  3. package/dist/components/app-surface/docs/llms.md +73 -0
  4. package/dist/components/app-surface/types.d.ts +19 -0
  5. package/dist/components/app-surface/types.js +1 -0
  6. package/dist/components/app-window/app-window.d.ts +3 -0
  7. package/dist/components/app-window/app-window.js +3 -0
  8. package/dist/components/app-window/app-window.svelte +193 -0
  9. package/dist/components/app-window/app-window.svelte.d.ts +25 -0
  10. package/dist/components/app-window/docs/llms.md +119 -0
  11. package/dist/components/app-window/types.d.ts +66 -0
  12. package/dist/components/app-window/types.js +1 -0
  13. package/dist/components/auto-suggest-box/auto-suggest-box.svelte +47 -31
  14. package/dist/components/auto-suggest-box/auto-suggest-box.svelte.d.ts +2 -2
  15. package/dist/components/auto-suggest-box/docs/llms.md +34 -33
  16. package/dist/components/auto-suggest-box/option.svelte +6 -4
  17. package/dist/components/auto-suggest-box/types.d.ts +13 -16
  18. package/dist/components/avatar/avatar.svelte +4 -3
  19. package/dist/components/avatar/docs/llms.md +1 -1
  20. package/dist/components/avatar/type.d.ts +1 -1
  21. package/dist/components/badge/badge-icon.svelte +2 -2
  22. package/dist/components/badge/badge.svelte +2 -2
  23. package/dist/components/badge/docs/llms.md +2 -2
  24. package/dist/components/badge/types.d.ts +2 -2
  25. package/dist/components/breadcrumb/breadcrumb-button.svelte +2 -2
  26. package/dist/components/breadcrumb/breadcrumb-divider.svelte +2 -2
  27. package/dist/components/breadcrumb/breadcrumb-item.svelte +2 -2
  28. package/dist/components/breadcrumb/breadcrumb.svelte +10 -5
  29. package/dist/components/breadcrumb/docs/llms.md +11 -11
  30. package/dist/components/breadcrumb/types.d.ts +7 -7
  31. package/dist/components/button/button.svelte +2 -2
  32. package/dist/components/button/docs/llms.md +17 -17
  33. package/dist/components/button/split-button.svelte +7 -7
  34. package/dist/components/button/types.d.ts +5 -5
  35. package/dist/components/calendar-date-picker/calendar-date-picker.svelte +98 -10
  36. package/dist/components/calendar-date-picker/calendar-date-picker.svelte.d.ts +1 -1
  37. package/dist/components/calendar-date-picker/docs/llms.md +19 -14
  38. package/dist/components/calendar-date-picker/types.d.ts +22 -8
  39. package/dist/components/calendar-view/calendar-view-days.svelte +3 -2
  40. package/dist/components/calendar-view/calendar-view-grid.js +8 -3
  41. package/dist/components/calendar-view/calendar-view-item.svelte +10 -4
  42. package/dist/components/calendar-view/calendar-view-months.svelte +3 -2
  43. package/dist/components/calendar-view/calendar-view-years.svelte +3 -2
  44. package/dist/components/calendar-view/calendar-view.svelte +11 -4
  45. package/dist/components/calendar-view/calendar-view.svelte.js +5 -0
  46. package/dist/components/calendar-view/docs/llms.md +20 -19
  47. package/dist/components/calendar-view/types.d.ts +6 -1
  48. package/dist/components/card/card-footer.svelte +2 -2
  49. package/dist/components/card/card-header.svelte +5 -4
  50. package/dist/components/card/card-preview.svelte +13 -2
  51. package/dist/components/card/card.svelte +5 -5
  52. package/dist/components/card/docs/llms.md +22 -21
  53. package/dist/components/card/types.d.ts +8 -4
  54. package/dist/components/checkbox/checkbox.svelte +47 -26
  55. package/dist/components/checkbox/checkbox.svelte.d.ts +3 -24
  56. package/dist/components/checkbox/docs/llms.md +24 -23
  57. package/dist/components/checkbox/types.d.ts +10 -23
  58. package/dist/components/date-picker/date-picker.svelte +98 -27
  59. package/dist/components/date-picker/date-picker.svelte.d.ts +1 -1
  60. package/dist/components/date-picker/docs/llms.md +23 -20
  61. package/dist/components/date-picker/types.d.ts +24 -15
  62. package/dist/components/dialog/dialog-actions.svelte +17 -2
  63. package/dist/components/dialog/dialog-content.svelte +2 -2
  64. package/dist/components/dialog/dialog-content.svelte.d.ts +1 -1
  65. package/dist/components/dialog/dialog-surface.svelte +130 -8
  66. package/dist/components/dialog/dialog-title.svelte +23 -6
  67. package/dist/components/dialog/dialog-trigger.svelte +8 -2
  68. package/dist/components/dialog/dialog-trigger.svelte.d.ts +1 -1
  69. package/dist/components/dialog/dialog.svelte +22 -11
  70. package/dist/components/dialog/docs/llms.md +56 -19
  71. package/dist/components/dialog/types.d.ts +31 -9
  72. package/dist/components/dialog/utils.d.ts +2 -0
  73. package/dist/components/dialog/utils.js +1 -0
  74. package/dist/components/divider/divider.svelte +6 -4
  75. package/dist/components/divider/types.d.ts +1 -1
  76. package/dist/components/dropdown/docs/llms.md +30 -28
  77. package/dist/components/dropdown/dropdown-option.svelte +17 -5
  78. package/dist/components/dropdown/dropdown.svelte +182 -84
  79. package/dist/components/dropdown/dropdown.svelte.d.ts +1 -1
  80. package/dist/components/dropdown/types.d.ts +26 -20
  81. package/dist/components/dropdown-select/docs/llms.md +24 -22
  82. package/dist/components/dropdown-select/dropdown-select-option.svelte +2 -2
  83. package/dist/components/dropdown-select/dropdown-select.svelte +42 -7
  84. package/dist/components/dropdown-select/types.d.ts +4 -4
  85. package/dist/components/expander/docs/llms.md +3 -3
  86. package/dist/components/expander/expander.svelte +13 -8
  87. package/dist/components/expander/types.d.ts +5 -5
  88. package/dist/components/flyout/docs/llms.md +1 -1
  89. package/dist/components/flyout/flyout.svelte +17 -6
  90. package/dist/components/flyout/types.d.ts +1 -1
  91. package/dist/components/hyperlink/docs/llms.md +6 -6
  92. package/dist/components/hyperlink/hyperlink.svelte +13 -4
  93. package/dist/components/hyperlink/types.d.ts +1 -1
  94. package/dist/components/info-bar/docs/llms.md +11 -10
  95. package/dist/components/info-bar/info-bar.svelte +3 -2
  96. package/dist/components/info-bar/types.d.ts +4 -0
  97. package/dist/components/label/docs/llms.md +75 -22
  98. package/dist/components/label/label-context.d.ts +14 -0
  99. package/dist/components/label/label-context.js +10 -0
  100. package/dist/components/label/label.svelte +153 -30
  101. package/dist/components/label/label.svelte.d.ts +1 -1
  102. package/dist/components/label/types.d.ts +48 -4
  103. package/dist/components/list-view/docs/llms.md +103 -33
  104. package/dist/components/list-view/list-view-item-branch.svelte +257 -0
  105. package/dist/components/list-view/list-view-item-branch.svelte.d.ts +4 -0
  106. package/dist/components/list-view/list-view-item.svelte +164 -46
  107. package/dist/components/list-view/list-view-item.svelte.d.ts +5 -5
  108. package/dist/components/list-view/list-view.svelte +73 -25
  109. package/dist/components/list-view/types.d.ts +71 -8
  110. package/dist/components/list-view/utils.d.ts +10 -0
  111. package/dist/components/list-view/utils.js +17 -1
  112. package/dist/components/menu/docs/llms.md +98 -15
  113. package/dist/components/menu/menu-command-bar-item.svelte +61 -0
  114. package/dist/components/menu/menu-command-bar-item.svelte.d.ts +14 -0
  115. package/dist/components/menu/menu-command-bar.svelte +218 -0
  116. package/dist/components/menu/menu-command-bar.svelte.d.ts +21 -0
  117. package/dist/components/menu/menu-group.svelte +6 -3
  118. package/dist/components/menu/menu-item-checkbox.svelte +5 -4
  119. package/dist/components/menu/menu-item-radio.svelte +5 -4
  120. package/dist/components/menu/menu-item-switch.svelte +5 -4
  121. package/dist/components/menu/menu-item.svelte +5 -5
  122. package/dist/components/menu/menu-item.svelte.d.ts +2 -3
  123. package/dist/components/menu/menu-list.svelte +10 -1
  124. package/dist/components/menu/menu-popover.svelte +9 -5
  125. package/dist/components/menu/menu-trigger.svelte +2 -1
  126. package/dist/components/menu/menu.svelte.js +1 -0
  127. package/dist/components/menu/types.d.ts +62 -7
  128. package/dist/components/number-box/docs/llms.md +6 -4
  129. package/dist/components/number-box/number-box.svelte +35 -29
  130. package/dist/components/number-box/number-box.svelte.d.ts +1 -1
  131. package/dist/components/number-box/types.d.ts +1 -1
  132. package/dist/components/persona/docs/llms.md +29 -25
  133. package/dist/components/persona/persona.svelte +8 -6
  134. package/dist/components/persona/types.d.ts +4 -3
  135. package/dist/components/progress-bar/docs/llms.md +13 -13
  136. package/dist/components/progress-bar/progress-bar.svelte +6 -6
  137. package/dist/components/progress-bar/types.d.ts +4 -4
  138. package/dist/components/progress-ring/docs/llms.md +14 -14
  139. package/dist/components/progress-ring/progress-ring.svelte +5 -5
  140. package/dist/components/progress-ring/types.d.ts +3 -3
  141. package/dist/components/radio-button/docs/llms.md +11 -8
  142. package/dist/components/radio-button/radio-button.svelte +38 -12
  143. package/dist/components/radio-button/radio-button.svelte.d.ts +1 -1
  144. package/dist/components/radio-button/types.d.ts +11 -8
  145. package/dist/components/rating/docs/llms.md +111 -0
  146. package/dist/components/rating/rating.svelte +247 -0
  147. package/dist/components/rating/rating.svelte.d.ts +19 -0
  148. package/dist/components/rating/types.d.ts +44 -0
  149. package/dist/components/rating/types.js +1 -0
  150. package/dist/components/side-nav/docs/llms.md +110 -0
  151. package/dist/components/side-nav/side-nav-branch.svelte +43 -0
  152. package/dist/components/side-nav/side-nav-branch.svelte.d.ts +4 -0
  153. package/dist/components/side-nav/side-nav-item.svelte +75 -0
  154. package/dist/components/side-nav/side-nav-item.svelte.d.ts +25 -0
  155. package/dist/components/side-nav/side-nav-list.svelte +32 -0
  156. package/dist/components/side-nav/side-nav-list.svelte.d.ts +7 -0
  157. package/dist/components/side-nav/side-nav.d.ts +2 -0
  158. package/dist/components/side-nav/side-nav.js +2 -0
  159. package/dist/components/side-nav/side-nav.svelte +355 -0
  160. package/dist/components/side-nav/side-nav.svelte.d.ts +24 -0
  161. package/dist/components/side-nav/types.d.ts +149 -0
  162. package/dist/components/side-nav/types.js +1 -0
  163. package/dist/components/skeleton/docs/llms.md +1 -1
  164. package/dist/components/skeleton/skeleton.svelte +2 -2
  165. package/dist/components/skeleton/types.d.ts +1 -1
  166. package/dist/components/slider/docs/llms.md +31 -28
  167. package/dist/components/slider/slider.svelte +126 -61
  168. package/dist/components/slider/slider.svelte.d.ts +1 -3
  169. package/dist/components/slider/types.d.ts +21 -14
  170. package/dist/components/tab-view/docs/llms.md +7 -7
  171. package/dist/components/tab-view/tab-view-tab.svelte +16 -14
  172. package/dist/components/tab-view/tab-view.svelte +16 -9
  173. package/dist/components/tab-view/types.d.ts +6 -6
  174. package/dist/components/table/docs/llms.md +38 -33
  175. package/dist/components/table/table-body.svelte +2 -2
  176. package/dist/components/table/table-cell-actions.svelte +8 -2
  177. package/dist/components/table/table-cell-layout.svelte +2 -2
  178. package/dist/components/table/table-cell.svelte +2 -2
  179. package/dist/components/table/table-header-cell.svelte +2 -2
  180. package/dist/components/table/table-header.svelte +2 -2
  181. package/dist/components/table/table-row.svelte +2 -2
  182. package/dist/components/table/table-selection-cell.svelte +6 -6
  183. package/dist/components/table/table.svelte +2 -2
  184. package/dist/components/table/types.d.ts +11 -11
  185. package/dist/components/tag/docs/llms.md +383 -0
  186. package/dist/components/tag/tag-group.d.ts +2 -0
  187. package/dist/components/tag/tag-group.js +2 -0
  188. package/dist/components/tag/tag-group.svelte +117 -0
  189. package/dist/components/tag/tag-group.svelte.d.ts +20 -0
  190. package/dist/components/tag/tag.svelte +459 -0
  191. package/dist/components/tag/tag.svelte.d.ts +19 -0
  192. package/dist/components/tag/types.d.ts +137 -0
  193. package/dist/components/tag/types.js +1 -0
  194. package/dist/components/tag-picker/docs/llms.md +298 -0
  195. package/dist/components/tag-picker/option-group.svelte +51 -0
  196. package/dist/components/tag-picker/option-group.svelte.d.ts +4 -0
  197. package/dist/components/tag-picker/option.svelte +82 -0
  198. package/dist/components/tag-picker/option.svelte.d.ts +4 -0
  199. package/dist/components/tag-picker/tag-picker.d.ts +2 -0
  200. package/dist/components/tag-picker/tag-picker.js +2 -0
  201. package/dist/components/tag-picker/tag-picker.svelte +716 -0
  202. package/dist/components/tag-picker/tag-picker.svelte.d.ts +21 -0
  203. package/dist/components/tag-picker/types.d.ts +142 -0
  204. package/dist/components/tag-picker/types.js +1 -0
  205. package/dist/components/text-box/docs/llms.md +31 -4
  206. package/dist/components/text-box/text-box-button.svelte +3 -3
  207. package/dist/components/text-box/text-box-button.svelte.d.ts +1 -1
  208. package/dist/components/text-box/text-box.svelte +41 -14
  209. package/dist/components/text-box/types.d.ts +5 -5
  210. package/dist/components/textarea/docs/llms.md +4 -3
  211. package/dist/components/textarea/textarea.svelte +14 -6
  212. package/dist/components/textarea/types.d.ts +2 -4
  213. package/dist/components/time-picker/docs/llms.md +18 -15
  214. package/dist/components/time-picker/time-picker.svelte +133 -33
  215. package/dist/components/time-picker/time-picker.svelte.d.ts +1 -1
  216. package/dist/components/time-picker/types.d.ts +23 -13
  217. package/dist/components/title-bar/docs/llms.md +382 -0
  218. package/dist/components/title-bar/title-bar-left-controls.svelte +215 -0
  219. package/dist/components/title-bar/title-bar-left-controls.svelte.d.ts +22 -0
  220. package/dist/components/title-bar/title-bar-right-controls.svelte +190 -0
  221. package/dist/components/title-bar/title-bar-right-controls.svelte.d.ts +27 -0
  222. package/dist/components/title-bar/title-bar.d.ts +3 -0
  223. package/dist/components/title-bar/title-bar.js +4 -0
  224. package/dist/components/title-bar/title-bar.svelte +224 -0
  225. package/dist/components/title-bar/title-bar.svelte.d.ts +26 -0
  226. package/dist/components/title-bar/types.d.ts +165 -0
  227. package/dist/components/title-bar/types.js +1 -0
  228. package/dist/components/toggle-switch/docs/llms.md +11 -9
  229. package/dist/components/toggle-switch/toggle-switch.svelte +23 -14
  230. package/dist/components/toggle-switch/toggle-switch.svelte.d.ts +1 -1
  231. package/dist/components/toggle-switch/types.d.ts +12 -10
  232. package/dist/components/tooltip/docs/llms.md +1 -1
  233. package/dist/components/tooltip/tooltip.svelte +5 -4
  234. package/dist/components/tooltip/types.d.ts +1 -1
  235. package/dist/components/top-nav/docs/llms.md +1 -1
  236. package/dist/components/top-nav/top-nav-item.svelte +2 -2
  237. package/dist/components/top-nav/top-nav.svelte +2 -2
  238. package/dist/components/top-nav/types.d.ts +2 -2
  239. package/dist/components/tree-view/docs/llms.md +11 -11
  240. package/dist/components/tree-view/tree-view-item-content.svelte +3 -3
  241. package/dist/components/tree-view/tree-view-item.svelte +13 -5
  242. package/dist/components/tree-view/tree-view.svelte +20 -5
  243. package/dist/components/tree-view/tree-view.svelte.d.ts +1 -1
  244. package/dist/components/tree-view/tree-view.svelte.js +31 -3
  245. package/dist/components/tree-view/types.d.ts +7 -3
  246. package/dist/index.d.ts +25 -0
  247. package/dist/index.js +32 -0
  248. package/dist/internal/components/dynamic-carousel/dynamic-carousel.svelte +26 -5
  249. package/dist/internal/components/dynamic-carousel/dynamic-carousel.svelte.d.ts +2 -0
  250. package/dist/internal/constants.d.ts +0 -4
  251. package/dist/internal/constants.js +0 -4002
  252. package/dist/internal/index.d.ts +1 -0
  253. package/dist/internal/index.js +1 -0
  254. package/dist/internal/native-field.svelte.d.ts +44 -0
  255. package/dist/internal/native-field.svelte.js +85 -0
  256. package/dist/internal/utils.d.ts +16 -2
  257. package/dist/internal/utils.js +25 -3
  258. package/dist/types/index.d.ts +3 -3
  259. package/package.json +51 -37
@@ -0,0 +1,75 @@
1
+ <script lang="ts" generics="T extends 'li' | 'a' | 'button' | 'div' = 'a'">
2
+ import ListViewItem from '../list-view/list-view-item.svelte';
3
+ import { RenderSoC } from '../../internal/index.js';
4
+ import { getSideNavContext } from './side-nav.js';
5
+ import type { SideNavItemProps } from './types.js';
6
+ import type { ListViewItemProps } from '../list-view/types.js';
7
+
8
+ let {
9
+ as = 'a' as T,
10
+ ref = $bindable(null),
11
+ label,
12
+ icon,
13
+ children,
14
+ onAction,
15
+ ...attributes
16
+ }: SideNavItemProps<T> = $props();
17
+
18
+ // Outside a SideNav the item is a plain, expanded one: it has no rail to fit and no panel to close.
19
+ const context = getSideNavContext();
20
+ const Item = ListViewItem<T>;
21
+ const compact = $derived(context?.state.compact ?? false);
22
+
23
+ function handleAction(event: MouseEvent, value: string) {
24
+ onAction?.(event, value);
25
+ context?.methods.activate(event);
26
+ }
27
+ </script>
28
+
29
+ <Item
30
+ {as}
31
+ bind:ref
32
+ aria-label={label}
33
+ title={compact ? label : undefined}
34
+ {...attributes as unknown as ListViewItemProps<T>}
35
+ onAction={as === 'a' || as === 'button' || onAction ? handleAction : undefined}
36
+ >
37
+ {#if icon}
38
+ <span class="fs-side-nav-item-icon" aria-hidden="true">
39
+ <RenderSoC SoC={icon} />
40
+ </span>
41
+ {:else if compact}
42
+ <span class="fs-side-nav-item-icon" aria-hidden="true">
43
+ {label.slice(0, 1)}
44
+ </span>
45
+ {/if}
46
+ <span class="fs-side-nav-item-label" hidden={compact}>
47
+ {#if children}
48
+ {@render children()}
49
+ {:else}
50
+ {label}
51
+ {/if}
52
+ </span>
53
+ </Item>
54
+
55
+ <style>
56
+ .fs-side-nav-item-icon {
57
+ display: inline-flex;
58
+ align-items: center;
59
+ justify-content: center;
60
+ flex: none;
61
+ inline-size: 1rem;
62
+ /* As tall as a line of text, so an item is as tall with its label as without it. */
63
+ block-size: 1lh;
64
+ & :global(svg) {
65
+ inline-size: 1rem;
66
+ block-size: 1rem;
67
+ }
68
+ }
69
+ .fs-side-nav-item-label {
70
+ min-inline-size: 0;
71
+ overflow: hidden;
72
+ text-overflow: ellipsis;
73
+ white-space: nowrap;
74
+ }
75
+ </style>
@@ -0,0 +1,25 @@
1
+ import type { SideNavItemProps } from './types.ts';
2
+ declare function $$render<T extends 'li' | 'a' | 'button' | 'div' = 'a'>(): {
3
+ props: SideNavItemProps<T>;
4
+ exports: {};
5
+ bindings: "ref";
6
+ slots: {};
7
+ events: {};
8
+ };
9
+ declare class __sveltets_Render<T extends 'li' | 'a' | 'button' | 'div' = 'a'> {
10
+ props(): ReturnType<typeof $$render<T>>['props'];
11
+ events(): ReturnType<typeof $$render<T>>['events'];
12
+ slots(): ReturnType<typeof $$render<T>>['slots'];
13
+ bindings(): "ref";
14
+ exports(): {};
15
+ }
16
+ interface $$IsomorphicComponent {
17
+ new <T extends 'li' | 'a' | 'button' | 'div' = 'a'>(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']>> & {
18
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
19
+ } & ReturnType<__sveltets_Render<T>['exports']>;
20
+ <T extends 'li' | 'a' | 'button' | 'div' = 'a'>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
21
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
22
+ }
23
+ declare const SideNavItem: $$IsomorphicComponent;
24
+ type SideNavItem<T extends 'li' | 'a' | 'button' | 'div' = 'a'> = InstanceType<typeof SideNavItem<T>>;
25
+ export default SideNavItem;
@@ -0,0 +1,32 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import ListView from '../list-view/list-view.svelte';
4
+ import { getSideNavContext } from './side-nav.js';
5
+
6
+ let { children }: { children?: Snippet } = $props();
7
+
8
+ const context = getSideNavContext();
9
+
10
+ // Escape belongs to the enclosing panel: ListView keeps its other navigation keys.
11
+ const MANAGED_KEYS = { Home: true, End: true, PageUp: true, PageDown: true };
12
+
13
+ // Outside a SideNav, a branch keeps the selection of its own list.
14
+ let ownSelectedItems = $state<string[]>([]);
15
+ </script>
16
+
17
+ <ListView
18
+ role="list"
19
+ selectionMode="none"
20
+ navigationMode="items"
21
+ manageSpecialKeys={MANAGED_KEYS}
22
+ {...context?.config.listViewProps}
23
+ bind:selectedItems={
24
+ () => context?.state.selectedItems ?? ownSelectedItems,
25
+ (value) => {
26
+ if (context) context.state.selectedItems = value;
27
+ else ownSelectedItems = value;
28
+ }
29
+ }
30
+ >
31
+ {@render children?.()}
32
+ </ListView>
@@ -0,0 +1,7 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ children?: Snippet;
4
+ };
5
+ declare const SideNavList: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type SideNavList = ReturnType<typeof SideNavList>;
7
+ export default SideNavList;
@@ -0,0 +1,2 @@
1
+ import type { SideNavContext } from './types.ts';
2
+ export declare const getSideNavContext: () => SideNavContext | null, setSideNavContext: (context: SideNavContext) => void;
@@ -0,0 +1,2 @@
1
+ import { createFSContext } from '../../internal/index.js';
2
+ export const [getSideNavContext, setSideNavContext] = createFSContext();
@@ -0,0 +1,355 @@
1
+ <script lang="ts">
2
+ import { onDestroy } from 'svelte';
3
+ import { onClickOutside } from 'runed';
4
+ import NavigationRegular from 'fluentui-icons-svelte/NavigationRegular.svelte';
5
+ import Button from '../button/button.svelte';
6
+ import { getAppWindowContext } from '../app-window/app-window.js';
7
+ import { invokeHandlers, RenderSoC, toLength } from '../../internal/index.js';
8
+ import { PREFIX } from '../../internal/constants.js';
9
+ import SideNavList from './side-nav-list.svelte';
10
+ import { setSideNavContext } from './side-nav.js';
11
+ import type { SideNavContent, SideNavContext, SideNavProps } from './types.js';
12
+
13
+ const FALLBACK_ID = $props.id();
14
+ const COMPONENT_NAME = 'side-nav';
15
+ const BODY_ID = `${PREFIX}-${COMPONENT_NAME}-${FALLBACK_ID}`;
16
+
17
+ let {
18
+ ref = $bindable(null),
19
+ label = 'Main navigation',
20
+ collapsed = $bindable(false),
21
+ position = 'left',
22
+ showToggle,
23
+ floating = false,
24
+ width = 200,
25
+ expandLabel = 'Expand navigation',
26
+ collapseLabel = 'Collapse navigation',
27
+ closeOnSelect = true,
28
+ onCollapsedChange,
29
+ selectedItems = $bindable([]),
30
+ listViewProps,
31
+ header,
32
+ topContent,
33
+ footerContent,
34
+ footer,
35
+ children,
36
+ onkeydown,
37
+ onfocusout,
38
+ class: classes,
39
+ ...attributes
40
+ }: SideNavProps = $props();
41
+
42
+ let toggleRef = $state<HTMLButtonElement | null>(null);
43
+
44
+ /** Docked, a collapsed navigation is a rail of icons. Floating, it is only the toggle. */
45
+ const compact = $derived(collapsed && !floating);
46
+ const toggleLabel = $derived(collapsed ? expandLabel : collapseLabel);
47
+
48
+ function setCollapsed(event: Event, value: boolean) {
49
+ if (collapsed === value) return;
50
+ collapsed = value;
51
+ onCollapsedChange?.(event, value);
52
+ }
53
+
54
+ const context: SideNavContext = {
55
+ config: {
56
+ get floating() {
57
+ return floating;
58
+ },
59
+ get listViewProps() {
60
+ return listViewProps;
61
+ }
62
+ },
63
+ state: {
64
+ get collapsed() {
65
+ return collapsed;
66
+ },
67
+ get compact() {
68
+ return compact;
69
+ },
70
+ get selectedItems() {
71
+ return selectedItems;
72
+ },
73
+ set selectedItems(value) {
74
+ selectedItems = value;
75
+ }
76
+ },
77
+ events: null,
78
+ methods: {
79
+ setCollapsed,
80
+ activate: (event) => {
81
+ if (floating && closeOnSelect && !event.defaultPrevented) setCollapsed(event, true);
82
+ }
83
+ }
84
+ };
85
+ setSideNavContext(context);
86
+
87
+ const appWindow = getAppWindowContext();
88
+ // The global navigation button of the title bar controls the navigation, and takes the place of its own toggle.
89
+ const globalNav = $derived(appWindow?.state.globalNav);
90
+ const toggleVisible = $derived(showToggle ?? !globalNav?.enabled);
91
+ // Without a toggle, the navigation itself is where the focus lands when a floating one closes: it takes focus, but is not a tab stop.
92
+ const focusTarget = $derived(toggleVisible ? {} : { tabindex: -1 });
93
+
94
+ const unregister = appWindow?.methods.registerSideNav({
95
+ get ref() {
96
+ return ref;
97
+ },
98
+ get collapsed() {
99
+ return collapsed;
100
+ },
101
+ get floating() {
102
+ return floating;
103
+ },
104
+ get position() {
105
+ return position;
106
+ },
107
+ setCollapsed
108
+ });
109
+ onDestroy(() => unregister?.());
110
+
111
+ // The body of a floating navigation hides when it closes, so the focus moves to the button that opens it first.
112
+ $effect.pre(() => {
113
+ if (floating && collapsed && ref?.contains(ref.ownerDocument.activeElement))
114
+ (toggleRef ?? globalNav?.ref ?? ref)?.focus();
115
+ });
116
+
117
+ /** The button of the title bar that opens and closes the navigation is not outside it: its own click toggles it. */
118
+ const isGlobalNav = (target: EventTarget | null) => target instanceof Node && !!globalNav?.ref?.contains(target);
119
+
120
+ // A floating navigation is not modal: it closes with an outside press, with Escape and when the focus leaves it.
121
+ onClickOutside(
122
+ () => ref,
123
+ (event) => {
124
+ if (floating && !collapsed && !isGlobalNav(event.target)) setCollapsed(event, true);
125
+ }
126
+ );
127
+
128
+ function handleKeydown(event: KeyboardEvent) {
129
+ // Escape belongs to a nested disclosure or menu first: they cancel it when they handle it.
130
+ if (event.defaultPrevented || !floating || collapsed || event.key !== 'Escape') return;
131
+ event.preventDefault();
132
+ event.stopPropagation();
133
+ setCollapsed(event, true);
134
+ }
135
+
136
+ function handleFocusout(event: FocusEvent) {
137
+ const next = event.relatedTarget;
138
+ if (floating && !collapsed && next instanceof Node && !ref?.contains(next) && !isGlobalNav(next))
139
+ setCollapsed(event, true);
140
+ }
141
+ </script>
142
+
143
+ {#snippet region(value?: SideNavContent)}
144
+ {#if value && !(compact && typeof value === 'string')}
145
+ <div class="fs-side-nav-content">
146
+ {#if typeof value === 'string'}
147
+ {value}
148
+ {:else}
149
+ <RenderSoC SoC={value} args={{ collapsed, floating }} />
150
+ {/if}
151
+ </div>
152
+ {/if}
153
+ {/snippet}
154
+
155
+ <!--
156
+ @component
157
+ Collapsible app navigation. Place it directly inside AppWindow next to AppSurface.
158
+ AppWindow handles docked layout and the floating overlay below its title bar.
159
+ Use SideNavItem for links and SideNavBranch for nested navigation.
160
+
161
+ - Usage:
162
+ ```tsx
163
+ <script>
164
+ import { AppSurface, AppWindow, SideNav, SideNavItem } from 'fluentui-svelte';
165
+ import { HomeRegular } from 'fluentui-icons-svelte';
166
+ </script>
167
+
168
+ <AppWindow width={480} height={320}>
169
+ <SideNav header="My app">
170
+ <SideNavItem href="/" label="Home" icon={HomeRegular} />
171
+ </SideNav>
172
+ <AppSurface>The content of the app.</AppSurface>
173
+ </AppWindow>
174
+ ```
175
+ -->
176
+ <nav
177
+ aria-label={label}
178
+ {...focusTarget}
179
+ {...attributes}
180
+ bind:this={ref}
181
+ class={[
182
+ 'fs-side-nav',
183
+ { collapsed, floating, compact, 'no-toggle': !toggleVisible, 'position-right': position === 'right' },
184
+ classes
185
+ ]}
186
+ style:--fs-side-nav-width={toLength(width)}
187
+ onkeydown={(e) => invokeHandlers(e, [], [onkeydown, handleKeydown])}
188
+ onfocusout={(e) => invokeHandlers(e, [], [onfocusout, handleFocusout])}
189
+ >
190
+ {#if toggleVisible || (header && !collapsed)}
191
+ <div class={['fs-side-nav-header', { 'no-toggle': !toggleVisible }]}>
192
+ {#if toggleVisible}
193
+ <Button
194
+ bind:ref={toggleRef}
195
+ type="button"
196
+ appearance="subtle"
197
+ class="fs-side-nav-toggle"
198
+ aria-label={toggleLabel}
199
+ title={toggleLabel}
200
+ aria-controls={BODY_ID}
201
+ aria-expanded={!collapsed}
202
+ onclick={(event) => setCollapsed(event, !collapsed)}
203
+ >
204
+ <NavigationRegular aria-hidden="true" />
205
+ </Button>
206
+ {/if}
207
+ {#if header && !collapsed}
208
+ <span class="fs-side-nav-heading">{header}</span>
209
+ {/if}
210
+ </div>
211
+ {/if}
212
+ <div id={BODY_ID} class="fs-side-nav-body" hidden={floating && collapsed}>
213
+ {@render region(topContent)}
214
+
215
+ <div class="fs-side-nav-items">
216
+ <SideNavList>
217
+ {@render children?.()}
218
+ </SideNavList>
219
+ </div>
220
+
221
+ {#if footerContent || footer}
222
+ <div class="fs-side-nav-footer">
223
+ {@render region(footerContent)}
224
+
225
+ {#if footer}
226
+ <SideNavList>
227
+ {@render footer()}
228
+ </SideNavList>
229
+ {/if}
230
+ </div>
231
+ {/if}
232
+ </div>
233
+ </nav>
234
+
235
+ <style>
236
+ .fs-side-nav {
237
+ box-sizing: border-box;
238
+ position: relative;
239
+ display: flex;
240
+ flex-direction: column;
241
+ flex: none;
242
+ inline-size: var(--fs-side-nav-width);
243
+ max-inline-size: 100%;
244
+ min-block-size: 0;
245
+ color: var(--fs-text-primary);
246
+ font-family: var(--fs-font-family-base);
247
+ font-size: var(--fs-body-font-size);
248
+ /* The line of its items and toggle, which the buttons of a TitleBar share. */
249
+ line-height: 1.4;
250
+ padding-top: 0.25rem;
251
+ /* Without its own toggle the list sits right under the title bar, which already has its button. */
252
+ &.no-toggle:not(.floating) {
253
+ padding-top: 0;
254
+ }
255
+ &.collapsed {
256
+ /* The rail is one item wide: its icon (1rem) and the padding of the item (0.5rem) and of the list (0.25rem). */
257
+ inline-size: 2.5rem;
258
+ & .fs-side-nav-content {
259
+ padding-bottom: 0;
260
+ }
261
+ }
262
+ &.floating {
263
+ position: absolute;
264
+ inset-block: 0;
265
+ inset-inline-start: 0;
266
+ z-index: 3;
267
+ &.position-right {
268
+ inset-inline: auto 0;
269
+ }
270
+ &:not(.collapsed) {
271
+ background: var(--fs-acrylic-background-default);
272
+ border: 1px solid var(--fs-control-surface-stroke-flyout);
273
+ border-radius: var(--fs-control-overlay-border-radius);
274
+ box-shadow: var(--fs-shadow-flyout);
275
+ }
276
+ &.collapsed {
277
+ /* Only the toggle is left, and the content below it stays reachable. */
278
+ pointer-events: none;
279
+ }
280
+ }
281
+ /* The icons keep their place in the rail and out of it, aligned with the toggle. */
282
+ & :global(.fs-list-view-item),
283
+ & :global(.fs-list-view-item-branch-trigger) {
284
+ padding-inline: 0.5rem;
285
+ margin: 0.2rem 0;
286
+ }
287
+ &.compact {
288
+ & :global(.fs-list-view-item-branch-region),
289
+ & :global(.branch-chevron) {
290
+ display: none;
291
+ }
292
+ /* The label still names the branch for assistive technology. */
293
+ & :global(.fs-list-view-branch-label) {
294
+ position: absolute;
295
+ inline-size: 1px;
296
+ block-size: 1px;
297
+ clip-path: inset(50%);
298
+ overflow: hidden;
299
+ }
300
+ & .fs-side-nav-content {
301
+ padding-inline: 0.25rem;
302
+ }
303
+ }
304
+ }
305
+ .fs-side-nav-header {
306
+ display: flex;
307
+ align-items: center;
308
+ flex: none;
309
+ gap: 0.5rem;
310
+ padding-inline: 0.25rem;
311
+ box-sizing: border-box;
312
+ &.no-toggle {
313
+ padding-inline: 0.75rem;
314
+ }
315
+ /* The toggle is the size of an item: the same padding around an icon, and the same line of text under it. */
316
+ & :global(.fs-side-nav-toggle) {
317
+ flex: none;
318
+ padding: 0.275rem 0.5rem 0.4rem;
319
+ font-size: var(--fs-body2-font-size);
320
+ line-height: inherit;
321
+ min-block-size: calc(1lh + 0.675rem);
322
+ pointer-events: auto;
323
+ & :global(svg) {
324
+ inline-size: 1rem;
325
+ block-size: 1rem;
326
+ }
327
+ }
328
+ }
329
+ .fs-side-nav-heading {
330
+ min-inline-size: 0;
331
+ font-weight: 600;
332
+ }
333
+ .fs-side-nav-body {
334
+ display: flex;
335
+ flex-direction: column;
336
+ flex: 1;
337
+ min-block-size: 0;
338
+ &[hidden] {
339
+ display: none;
340
+ }
341
+ }
342
+ .fs-side-nav-content {
343
+ padding: 0.125rem 0.25rem 0.125rem 0.75rem;
344
+ }
345
+ .fs-side-nav-items {
346
+ flex: 1;
347
+ min-block-size: 0;
348
+ overflow: auto;
349
+ padding-inline: 0.25rem;
350
+ }
351
+ .fs-side-nav-footer {
352
+ flex: none;
353
+ padding: 0.125rem 0.25rem;
354
+ }
355
+ </style>
@@ -0,0 +1,24 @@
1
+ import type { SideNavProps } from './types.ts';
2
+ /**
3
+ * Collapsible app navigation. Place it directly inside AppWindow next to AppSurface.
4
+ * AppWindow handles docked layout and the floating overlay below its title bar.
5
+ * Use SideNavItem for links and SideNavBranch for nested navigation.
6
+ *
7
+ * - Usage:
8
+ * ```tsx
9
+ * <script>
10
+ * import { AppSurface, AppWindow, SideNav, SideNavItem } from 'fluentui-svelte';
11
+ * import { HomeRegular } from 'fluentui-icons-svelte';
12
+ * </script>
13
+ *
14
+ * <AppWindow width={480} height={320}>
15
+ * <SideNav header="My app">
16
+ * <SideNavItem href="/" label="Home" icon={HomeRegular} />
17
+ * </SideNav>
18
+ * <AppSurface>The content of the app.</AppSurface>
19
+ * </AppWindow>
20
+ * ```
21
+ */
22
+ declare const SideNav: import("svelte").Component<SideNavProps, {}, "ref" | "selectedItems" | "collapsed">;
23
+ type SideNav = ReturnType<typeof SideNav>;
24
+ export default SideNav;
@@ -0,0 +1,149 @@
1
+ import type { Component, Snippet } from 'svelte';
2
+ import type { HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
3
+ import type { FSContext } from '../../internal/index.js';
4
+ import type { PolymorphicProps } from '../../types/index.js';
5
+ import type { ListViewItemBranchProps, ListViewItemDOM, ListViewItemProps, ListViewProps } from '../list-view/types.ts';
6
+ export type SideNavRenderState = {
7
+ collapsed: boolean;
8
+ floating: boolean;
9
+ };
10
+ export type SideNavContent = string | Snippet<[SideNavRenderState]> | Component<SideNavRenderState>;
11
+ export type SideNavListViewProps = Omit<ListViewProps<'ul'>, 'children' | 'ref' | 'selectedItems'>;
12
+ /** @propsmith SideNavProps */
13
+ export type SideNavProps = {
14
+ /** The DOM reference of the navigation landmark.
15
+ * @bindable
16
+ */
17
+ ref?: HTMLElement | null;
18
+ /** The accessible name of the navigation landmark.
19
+ * @default 'Main navigation'
20
+ */
21
+ label?: string;
22
+ /** Shows an icon rail when docked, or only the toggle when floating.
23
+ * @default false
24
+ * @bindable
25
+ */
26
+ collapsed?: boolean;
27
+ /** The side of the window the navigation is on. It mirrors in right-to-left layouts, and AppSurface rounds the corners that face it.
28
+ * @default 'left'
29
+ */
30
+ position?: 'left' | 'right';
31
+ /** Whether the navigation shows its own hamburger toggle. By default it hides it when the title bar of its window has a global navigation button, which then controls the navigation. Set it to true to keep both, or to false to control the navigation yourself.
32
+ * @default Automatic
33
+ */
34
+ showToggle?: boolean;
35
+ /** Overlays the content of a positioned parent instead of taking layout space. The overlay is non-modal.
36
+ * @default false
37
+ */
38
+ floating?: boolean;
39
+ /** The expanded width. Numbers are pixels converted to rem; strings are CSS lengths.
40
+ * @default 200
41
+ */
42
+ width?: number | string;
43
+ /** The accessible label of the toggle while collapsed.
44
+ * @default 'Expand navigation'
45
+ */
46
+ expandLabel?: string;
47
+ /** The accessible label of the toggle while expanded.
48
+ * @default 'Collapse navigation'
49
+ */
50
+ collapseLabel?: string;
51
+ /** Closes a floating panel after activating a SideNavItem.
52
+ * @default true
53
+ */
54
+ closeOnSelect?: boolean;
55
+ /** Called when the user expands or collapses the navigation. */
56
+ onCollapsedChange?: (event: Event, collapsed: boolean) => void;
57
+ /** The selection shared by every list in the navigation. Selection is off by default.
58
+ * @bindable
59
+ */
60
+ selectedItems?: string[];
61
+ /** Overrides the defaults of every list in the navigation, the main one, the footer and the ones inside a SideNavBranch: native list semantics, no selection and one tab stop per item.
62
+ * @type SideNavListViewProps
63
+ */
64
+ listViewProps?: SideNavListViewProps;
65
+ /** The text heading beside the hamburger button. Hidden in the compact rail. */
66
+ header?: string;
67
+ /** Custom content between the hamburger section and the list. Text, snippets and components are supported. Renderers receive collapsed and floating; strings are hidden in the compact rail.
68
+ * @type string | Snippet | Component
69
+ */
70
+ topContent?: SideNavContent;
71
+ /** Custom content after the scrolling list and before the pinned footer. Text, snippets and components are supported. Renderers receive collapsed and floating; strings are hidden in the compact rail.
72
+ * @type string | Snippet | Component
73
+ */
74
+ footerContent?: SideNavContent;
75
+ /** Footer list items pinned to the bottom, outside the main list's scroll area. */
76
+ footer?: Snippet;
77
+ /** Main navigation items. Use SideNavItem and SideNavBranch. */
78
+ children?: Snippet;
79
+ } & Omit<HTMLAttributes<HTMLElement>, 'children'>;
80
+ /** @propsmith SideNavItemProps */
81
+ export type SideNavItemProps<T extends 'li' | 'a' | 'button' | 'div' = 'a'> = {
82
+ /** The HTML tag. Links are the default; use button for actions and li or div for custom controls.
83
+ * @type 'li' | 'a' | 'button' | 'div'
84
+ * @default 'a'
85
+ */
86
+ as?: T;
87
+ /** The DOM reference of the item.
88
+ * @type HTMLLIElement | HTMLAnchorElement | HTMLButtonElement | HTMLDivElement
89
+ * @bindable
90
+ */
91
+ ref?: ListViewItemDOM[T] | null;
92
+ /** The accessible label, also used as visible content when children are absent. */
93
+ label: string;
94
+ /** The decorative icon shown in both expanded and collapsed modes.
95
+ * @type Snippet | Component
96
+ */
97
+ icon?: Snippet | Component;
98
+ /** Optional item markup, following ListViewItem. The label is rendered when children are absent. */
99
+ children?: Snippet;
100
+ } & Pick<ListViewItemProps, 'shape' | 'value' | 'active' | 'role' | 'disabled' | 'checkmark' | 'onAction' | 'onfocus'> & PolymorphicProps<T, 'children' | 'ref' | 'onfocus'>;
101
+ /** @propsmith SideNavBranchProps */
102
+ export type SideNavBranchProps = {
103
+ /** The accessible label of the disclosure button. In the compact rail, its initial stands in when there is no icon. */
104
+ label: string;
105
+ /** The decorative icon before the label.
106
+ * @type Snippet | Component
107
+ */
108
+ icon?: Snippet | Component;
109
+ /** Whether the nested items are visible. Branches only expand or collapse and are never selectable. The compact rail reports a branch as collapsed, and opens the navigation when one is pressed.
110
+ * @default false
111
+ * @bindable
112
+ */
113
+ expanded?: boolean;
114
+ /** Called when a user expands or collapses the branch. */
115
+ onExpandedChange?: (e: Event, expanded: boolean) => void;
116
+ /** Disables the disclosure button.
117
+ * @default false
118
+ */
119
+ disabled?: boolean;
120
+ /** The DOM reference of the native disclosure button. Additional HTML attributes, including class and id, also target this button.
121
+ * @type HTMLButtonElement
122
+ * @bindable
123
+ */
124
+ ref?: HTMLButtonElement | null;
125
+ /** The DOM reference of the wrapper element, the list item that holds the button and the nested list.
126
+ * @type HTMLLIElement | HTMLDivElement
127
+ * @bindable
128
+ */
129
+ wrapperRef?: HTMLLIElement | HTMLDivElement | null;
130
+ /** The attributes to spread on the wrapper element.
131
+ * @type HTMLAttributes
132
+ */
133
+ wrapperAttributes?: HTMLAttributes<HTMLLIElement | HTMLDivElement>;
134
+ /** The disclosure button shape. Inherited from the list by default. */
135
+ shape?: ListViewItemBranchProps['shape'];
136
+ /** The nested SideNavItem and SideNavBranch content. */
137
+ children?: Snippet;
138
+ } & Omit<HTMLButtonAttributes, 'children' | 'role' | 'type' | 'value' | 'aria-expanded' | 'aria-controls'>;
139
+ export type SideNavContext = FSContext<{
140
+ readonly floating: boolean;
141
+ readonly listViewProps: SideNavListViewProps | undefined;
142
+ }, {
143
+ readonly collapsed: boolean;
144
+ readonly compact: boolean;
145
+ selectedItems: string[];
146
+ }, null, {
147
+ setCollapsed: (event: Event, collapsed: boolean) => void;
148
+ activate: (event: Event) => void;
149
+ }>;
@@ -0,0 +1 @@
1
+ export {};