fluentui-svelte 0.1.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 (283) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +201 -0
  3. package/dist/components/auto-suggest-box/auto-suggest-box.d.ts +2 -0
  4. package/dist/components/auto-suggest-box/auto-suggest-box.js +2 -0
  5. package/dist/components/auto-suggest-box/auto-suggest-box.svelte +457 -0
  6. package/dist/components/auto-suggest-box/auto-suggest-box.svelte.d.ts +4 -0
  7. package/dist/components/auto-suggest-box/docs/llms.md +73 -0
  8. package/dist/components/auto-suggest-box/option.svelte +82 -0
  9. package/dist/components/auto-suggest-box/option.svelte.d.ts +4 -0
  10. package/dist/components/auto-suggest-box/types.d.ts +140 -0
  11. package/dist/components/auto-suggest-box/types.js +1 -0
  12. package/dist/components/avatar/avatar.svelte +269 -0
  13. package/dist/components/avatar/avatar.svelte.d.ts +20 -0
  14. package/dist/components/avatar/docs/llms.md +92 -0
  15. package/dist/components/avatar/type.d.ts +63 -0
  16. package/dist/components/avatar/type.js +1 -0
  17. package/dist/components/badge/badge-icon.svelte +103 -0
  18. package/dist/components/badge/badge-icon.svelte.d.ts +25 -0
  19. package/dist/components/badge/badge.svelte +163 -0
  20. package/dist/components/badge/badge.svelte.d.ts +20 -0
  21. package/dist/components/badge/docs/llms.md +133 -0
  22. package/dist/components/badge/types.d.ts +70 -0
  23. package/dist/components/badge/types.js +1 -0
  24. package/dist/components/badge/utils.svelte.d.ts +16 -0
  25. package/dist/components/badge/utils.svelte.js +35 -0
  26. package/dist/components/button/button.svelte +203 -0
  27. package/dist/components/button/button.svelte.d.ts +38 -0
  28. package/dist/components/button/docs/llms.md +102 -0
  29. package/dist/components/button/split-button.svelte +66 -0
  30. package/dist/components/button/split-button.svelte.d.ts +4 -0
  31. package/dist/components/button/types.d.ts +84 -0
  32. package/dist/components/button/types.js +1 -0
  33. package/dist/components/calendar-date-picker/calendar-date-picker.svelte +119 -0
  34. package/dist/components/calendar-date-picker/calendar-date-picker.svelte.d.ts +4 -0
  35. package/dist/components/calendar-date-picker/docs/llms.md +33 -0
  36. package/dist/components/calendar-date-picker/types.d.ts +36 -0
  37. package/dist/components/calendar-date-picker/types.js +1 -0
  38. package/dist/components/calendar-view/calendar-view-controls.svelte +115 -0
  39. package/dist/components/calendar-view/calendar-view-controls.svelte.d.ts +3 -0
  40. package/dist/components/calendar-view/calendar-view-days.svelte +210 -0
  41. package/dist/components/calendar-view/calendar-view-days.svelte.d.ts +3 -0
  42. package/dist/components/calendar-view/calendar-view-grid.d.ts +38 -0
  43. package/dist/components/calendar-view/calendar-view-grid.js +140 -0
  44. package/dist/components/calendar-view/calendar-view-header.svelte +66 -0
  45. package/dist/components/calendar-view/calendar-view-header.svelte.d.ts +18 -0
  46. package/dist/components/calendar-view/calendar-view-item.svelte +181 -0
  47. package/dist/components/calendar-view/calendar-view-item.svelte.d.ts +4 -0
  48. package/dist/components/calendar-view/calendar-view-months.svelte +165 -0
  49. package/dist/components/calendar-view/calendar-view-months.svelte.d.ts +3 -0
  50. package/dist/components/calendar-view/calendar-view-years.svelte +161 -0
  51. package/dist/components/calendar-view/calendar-view-years.svelte.d.ts +3 -0
  52. package/dist/components/calendar-view/calendar-view.svelte +451 -0
  53. package/dist/components/calendar-view/calendar-view.svelte.d.ts +9 -0
  54. package/dist/components/calendar-view/calendar-view.svelte.js +196 -0
  55. package/dist/components/calendar-view/docs/llms.md +121 -0
  56. package/dist/components/calendar-view/index.d.ts +1 -0
  57. package/dist/components/calendar-view/index.js +1 -0
  58. package/dist/components/calendar-view/types.d.ts +174 -0
  59. package/dist/components/calendar-view/types.js +1 -0
  60. package/dist/components/checkbox/checkbox.svelte +171 -0
  61. package/dist/components/checkbox/checkbox.svelte.d.ts +40 -0
  62. package/dist/components/checkbox/docs/llms.md +78 -0
  63. package/dist/components/checkbox/types.d.ts +50 -0
  64. package/dist/components/checkbox/types.js +1 -0
  65. package/dist/components/date-picker/date-picker.svelte +381 -0
  66. package/dist/components/date-picker/date-picker.svelte.d.ts +4 -0
  67. package/dist/components/date-picker/docs/llms.md +52 -0
  68. package/dist/components/date-picker/index.d.ts +1 -0
  69. package/dist/components/date-picker/index.js +1 -0
  70. package/dist/components/date-picker/types.d.ts +74 -0
  71. package/dist/components/date-picker/types.js +1 -0
  72. package/dist/components/dialog/dialog-actions.svelte +37 -0
  73. package/dist/components/dialog/dialog-actions.svelte.d.ts +4 -0
  74. package/dist/components/dialog/dialog-content.svelte +17 -0
  75. package/dist/components/dialog/dialog-content.svelte.d.ts +4 -0
  76. package/dist/components/dialog/dialog-surface.svelte +95 -0
  77. package/dist/components/dialog/dialog-surface.svelte.d.ts +4 -0
  78. package/dist/components/dialog/dialog-title.svelte +33 -0
  79. package/dist/components/dialog/dialog-title.svelte.d.ts +25 -0
  80. package/dist/components/dialog/dialog-trigger.svelte +23 -0
  81. package/dist/components/dialog/dialog-trigger.svelte.d.ts +4 -0
  82. package/dist/components/dialog/dialog.svelte +64 -0
  83. package/dist/components/dialog/dialog.svelte.d.ts +7 -0
  84. package/dist/components/dialog/dialog.svelte.js +2 -0
  85. package/dist/components/dialog/docs/llms.md +131 -0
  86. package/dist/components/dialog/types.d.ts +92 -0
  87. package/dist/components/dialog/types.js +1 -0
  88. package/dist/components/divider/divider.svelte +120 -0
  89. package/dist/components/divider/divider.svelte.d.ts +39 -0
  90. package/dist/components/divider/docs/llms.md +83 -0
  91. package/dist/components/divider/types.d.ts +32 -0
  92. package/dist/components/divider/types.js +1 -0
  93. package/dist/components/dropdown/docs/llms.md +70 -0
  94. package/dist/components/dropdown/dropdown-context.d.ts +2 -0
  95. package/dist/components/dropdown/dropdown-context.js +2 -0
  96. package/dist/components/dropdown/dropdown-option.svelte +31 -0
  97. package/dist/components/dropdown/dropdown-option.svelte.d.ts +4 -0
  98. package/dist/components/dropdown/dropdown.svelte +309 -0
  99. package/dist/components/dropdown/dropdown.svelte.d.ts +4 -0
  100. package/dist/components/dropdown/types.d.ts +82 -0
  101. package/dist/components/dropdown/types.js +1 -0
  102. package/dist/components/dropdown-select/docs/llms.md +72 -0
  103. package/dist/components/dropdown-select/dropdown-select-option.svelte +87 -0
  104. package/dist/components/dropdown-select/dropdown-select-option.svelte.d.ts +4 -0
  105. package/dist/components/dropdown-select/dropdown-select.svelte +165 -0
  106. package/dist/components/dropdown-select/dropdown-select.svelte.d.ts +4 -0
  107. package/dist/components/dropdown-select/dropdown-select.svelte.js +48 -0
  108. package/dist/components/dropdown-select/index.d.ts +2 -0
  109. package/dist/components/dropdown-select/index.js +2 -0
  110. package/dist/components/dropdown-select/types.d.ts +46 -0
  111. package/dist/components/dropdown-select/types.js +1 -0
  112. package/dist/components/expander/docs/llms.md +88 -0
  113. package/dist/components/expander/expander.svelte +249 -0
  114. package/dist/components/expander/expander.svelte.d.ts +21 -0
  115. package/dist/components/expander/types.d.ts +47 -0
  116. package/dist/components/expander/types.js +1 -0
  117. package/dist/components/flyout/docs/llms.md +31 -0
  118. package/dist/components/flyout/flyout.svelte +148 -0
  119. package/dist/components/flyout/flyout.svelte.d.ts +19 -0
  120. package/dist/components/flyout/types.d.ts +36 -0
  121. package/dist/components/flyout/types.js +1 -0
  122. package/dist/components/hyperlink/docs/llms.md +33 -0
  123. package/dist/components/hyperlink/hyperlink.svelte +66 -0
  124. package/dist/components/hyperlink/hyperlink.svelte.d.ts +16 -0
  125. package/dist/components/hyperlink/types.d.ts +14 -0
  126. package/dist/components/hyperlink/types.js +1 -0
  127. package/dist/components/info-bar/docs/llms.md +81 -0
  128. package/dist/components/info-bar/info-bar.svelte +140 -0
  129. package/dist/components/info-bar/info-bar.svelte.d.ts +19 -0
  130. package/dist/components/info-bar/types.d.ts +27 -0
  131. package/dist/components/info-bar/types.js +1 -0
  132. package/dist/components/label/docs/llms.md +67 -0
  133. package/dist/components/label/label.svelte +95 -0
  134. package/dist/components/label/label.svelte.d.ts +4 -0
  135. package/dist/components/label/types.d.ts +32 -0
  136. package/dist/components/label/types.js +1 -0
  137. package/dist/components/list-view/docs/llms.md +110 -0
  138. package/dist/components/list-view/list-view-item.svelte +168 -0
  139. package/dist/components/list-view/list-view-item.svelte.d.ts +25 -0
  140. package/dist/components/list-view/list-view.svelte +137 -0
  141. package/dist/components/list-view/list-view.svelte.d.ts +25 -0
  142. package/dist/components/list-view/types.d.ts +95 -0
  143. package/dist/components/list-view/types.js +1 -0
  144. package/dist/components/list-view/utils.d.ts +6 -0
  145. package/dist/components/list-view/utils.js +12 -0
  146. package/dist/components/menu/context-menu-trigger.svelte +84 -0
  147. package/dist/components/menu/context-menu-trigger.svelte.d.ts +9 -0
  148. package/dist/components/menu/docs/llms.md +169 -0
  149. package/dist/components/menu/menu-divider.svelte +9 -0
  150. package/dist/components/menu/menu-divider.svelte.d.ts +26 -0
  151. package/dist/components/menu/menu-group.svelte +31 -0
  152. package/dist/components/menu/menu-group.svelte.d.ts +4 -0
  153. package/dist/components/menu/menu-item-checkbox.svelte +143 -0
  154. package/dist/components/menu/menu-item-checkbox.svelte.d.ts +15 -0
  155. package/dist/components/menu/menu-item-radio.svelte +147 -0
  156. package/dist/components/menu/menu-item-radio.svelte.d.ts +15 -0
  157. package/dist/components/menu/menu-item-switch.svelte +194 -0
  158. package/dist/components/menu/menu-item-switch.svelte.d.ts +15 -0
  159. package/dist/components/menu/menu-item.svelte +124 -0
  160. package/dist/components/menu/menu-item.svelte.d.ts +18 -0
  161. package/dist/components/menu/menu-list.svelte +38 -0
  162. package/dist/components/menu/menu-list.svelte.d.ts +5 -0
  163. package/dist/components/menu/menu-popover.svelte +125 -0
  164. package/dist/components/menu/menu-popover.svelte.d.ts +12 -0
  165. package/dist/components/menu/menu-trigger.svelte +121 -0
  166. package/dist/components/menu/menu-trigger.svelte.d.ts +4 -0
  167. package/dist/components/menu/menu.svelte +124 -0
  168. package/dist/components/menu/menu.svelte.d.ts +4 -0
  169. package/dist/components/menu/menu.svelte.js +77 -0
  170. package/dist/components/menu/types.d.ts +127 -0
  171. package/dist/components/menu/types.js +1 -0
  172. package/dist/components/number-box/docs/llms.md +37 -0
  173. package/dist/components/number-box/number-box.svelte +115 -0
  174. package/dist/components/number-box/number-box.svelte.d.ts +15 -0
  175. package/dist/components/number-box/types.d.ts +16 -0
  176. package/dist/components/number-box/types.js +1 -0
  177. package/dist/components/persona/docs/llms.md +107 -0
  178. package/dist/components/persona/persona.svelte +79 -0
  179. package/dist/components/persona/persona.svelte.d.ts +4 -0
  180. package/dist/components/persona/types.d.ts +42 -0
  181. package/dist/components/persona/types.js +1 -0
  182. package/dist/components/progress-bar/docs/llms.md +67 -0
  183. package/dist/components/progress-bar/progress-bar.svelte +167 -0
  184. package/dist/components/progress-bar/progress-bar.svelte.d.ts +15 -0
  185. package/dist/components/progress-bar/types.d.ts +39 -0
  186. package/dist/components/progress-bar/types.js +1 -0
  187. package/dist/components/progress-ring/docs/llms.md +76 -0
  188. package/dist/components/progress-ring/progress-ring.svelte +145 -0
  189. package/dist/components/progress-ring/progress-ring.svelte.d.ts +15 -0
  190. package/dist/components/progress-ring/types.d.ts +42 -0
  191. package/dist/components/progress-ring/types.js +1 -0
  192. package/dist/components/radio-button/docs/llms.md +64 -0
  193. package/dist/components/radio-button/radio-button.svelte +129 -0
  194. package/dist/components/radio-button/radio-button.svelte.d.ts +19 -0
  195. package/dist/components/radio-button/types.d.ts +24 -0
  196. package/dist/components/radio-button/types.js +1 -0
  197. package/dist/components/skeleton/docs/llms.md +67 -0
  198. package/dist/components/skeleton/skeleton.svelte +106 -0
  199. package/dist/components/skeleton/skeleton.svelte.d.ts +39 -0
  200. package/dist/components/skeleton/types.d.ts +24 -0
  201. package/dist/components/skeleton/types.js +1 -0
  202. package/dist/components/slider/docs/llms.md +75 -0
  203. package/dist/components/slider/slider.svelte +486 -0
  204. package/dist/components/slider/slider.svelte.d.ts +19 -0
  205. package/dist/components/slider/types.d.ts +102 -0
  206. package/dist/components/slider/types.js +1 -0
  207. package/dist/components/text-box/docs/llms.md +86 -0
  208. package/dist/components/text-box/text-box-button.svelte +65 -0
  209. package/dist/components/text-box/text-box-button.svelte.d.ts +9 -0
  210. package/dist/components/text-box/text-box.svelte +299 -0
  211. package/dist/components/text-box/text-box.svelte.d.ts +16 -0
  212. package/dist/components/text-box/types.d.ts +60 -0
  213. package/dist/components/text-box/types.js +1 -0
  214. package/dist/components/textarea/docs/llms.md +55 -0
  215. package/dist/components/textarea/textarea.svelte +151 -0
  216. package/dist/components/textarea/textarea.svelte.d.ts +17 -0
  217. package/dist/components/textarea/types.d.ts +33 -0
  218. package/dist/components/textarea/types.js +1 -0
  219. package/dist/components/time-picker/docs/llms.md +47 -0
  220. package/dist/components/time-picker/index.d.ts +1 -0
  221. package/dist/components/time-picker/index.js +1 -0
  222. package/dist/components/time-picker/time-picker.svelte +336 -0
  223. package/dist/components/time-picker/time-picker.svelte.d.ts +4 -0
  224. package/dist/components/time-picker/types.d.ts +54 -0
  225. package/dist/components/time-picker/types.js +1 -0
  226. package/dist/components/toggle-switch/docs/llms.md +39 -0
  227. package/dist/components/toggle-switch/toggle-switch.svelte +151 -0
  228. package/dist/components/toggle-switch/toggle-switch.svelte.d.ts +17 -0
  229. package/dist/components/toggle-switch/types.d.ts +20 -0
  230. package/dist/components/toggle-switch/types.js +1 -0
  231. package/dist/components/tooltip/docs/llms.md +74 -0
  232. package/dist/components/tooltip/tooltip.svelte +246 -0
  233. package/dist/components/tooltip/tooltip.svelte.d.ts +18 -0
  234. package/dist/components/tooltip/types.d.ts +67 -0
  235. package/dist/components/tooltip/types.js +1 -0
  236. package/dist/components/tree-view/docs/llms.md +117 -0
  237. package/dist/components/tree-view/tree-view-item-content.svelte +158 -0
  238. package/dist/components/tree-view/tree-view-item-content.svelte.d.ts +4 -0
  239. package/dist/components/tree-view/tree-view-item.svelte +197 -0
  240. package/dist/components/tree-view/tree-view-item.svelte.d.ts +4 -0
  241. package/dist/components/tree-view/tree-view.svelte +220 -0
  242. package/dist/components/tree-view/tree-view.svelte.d.ts +4 -0
  243. package/dist/components/tree-view/tree-view.svelte.js +111 -0
  244. package/dist/components/tree-view/types.d.ts +185 -0
  245. package/dist/components/tree-view/types.js +1 -0
  246. package/dist/css/class-darkmode.css +186 -0
  247. package/dist/css/media-darkmode.css +189 -0
  248. package/dist/css/reset.css +53 -0
  249. package/dist/css/theme.css +276 -0
  250. package/dist/css/typography.css +67 -0
  251. package/dist/css/utils.d.ts +1 -0
  252. package/dist/css/utils.js +153 -0
  253. package/dist/index.d.ts +63 -0
  254. package/dist/index.js +129 -0
  255. package/dist/internal/components/dynamic-carousel/dynamic-carousel.svelte +449 -0
  256. package/dist/internal/components/dynamic-carousel/dynamic-carousel.svelte.d.ts +22 -0
  257. package/dist/internal/components/render-soc/render-soc.svelte +29 -0
  258. package/dist/internal/components/render-soc/render-soc.svelte.d.ts +30 -0
  259. package/dist/internal/constants.d.ts +26 -0
  260. package/dist/internal/constants.js +4036 -0
  261. package/dist/internal/context.d.ts +14 -0
  262. package/dist/internal/context.js +13 -0
  263. package/dist/internal/dom-utils.svelte.d.ts +6 -0
  264. package/dist/internal/dom-utils.svelte.js +46 -0
  265. package/dist/internal/floating-ui/floating.svelte.d.ts +15 -0
  266. package/dist/internal/floating-ui/floating.svelte.js +26 -0
  267. package/dist/internal/floating-ui/utils.d.ts +3 -0
  268. package/dist/internal/floating-ui/utils.js +30 -0
  269. package/dist/internal/index.d.ts +9 -0
  270. package/dist/internal/index.js +9 -0
  271. package/dist/internal/polyfills/expander.svelte.d.ts +21 -0
  272. package/dist/internal/polyfills/expander.svelte.js +96 -0
  273. package/dist/internal/transitions.d.ts +32 -0
  274. package/dist/internal/transitions.js +37 -0
  275. package/dist/internal/utils.d.ts +22 -0
  276. package/dist/internal/utils.js +63 -0
  277. package/dist/providers/fluentui-svelte/fluentui-svelte.d.ts +19 -0
  278. package/dist/providers/fluentui-svelte/fluentui-svelte.js +11 -0
  279. package/dist/providers/fluentui-svelte/fluentui-svelte.svelte +68 -0
  280. package/dist/providers/fluentui-svelte/fluentui-svelte.svelte.d.ts +9 -0
  281. package/dist/types/index.d.ts +117 -0
  282. package/dist/types/index.js +1 -0
  283. package/package.json +142 -0
@@ -0,0 +1,70 @@
1
+ # Dropdown
2
+
3
+ The Dropdown lets users select one or more options from a list of `DropdownOption` children. Options can render rich content, such as a `Persona`, and the current selection is exposed through a bindable `value`.
4
+
5
+ ## Usage
6
+
7
+ ```svelte
8
+ <script>
9
+ import { Dropdown, DropdownOption } from 'fluentui-svelte';
10
+ </script>
11
+
12
+ <Dropdown>
13
+ <DropdownOption value="A" text="Option A">Option A</DropdownOption>
14
+ <DropdownOption value="B" text="Option B">Option B</DropdownOption>
15
+ </Dropdown>
16
+ ```
17
+
18
+ ## Examples
19
+
20
+ ### Custom Option Content
21
+
22
+ Options can render any content, such as a `Persona`. Pass a `text` prop so the closed dropdown can still display the selection.
23
+
24
+ ```svelte
25
+ <Dropdown>
26
+ <DropdownOption value="John Doe" text="John Doe">
27
+ <Persona
28
+ name="John Doe"
29
+ primaryText="Software Engineer"
30
+ presence={{ status: 'available' }}
31
+ avatar={{ color: 'colorful', idForColor: '' }}
32
+ />
33
+ </DropdownOption>
34
+ <DropdownOption value="B" text="Option B">Option B</DropdownOption>
35
+ <DropdownOption value="C" text="Option C">Option C</DropdownOption>
36
+ </Dropdown>
37
+ ```
38
+
39
+ ### Multiple Selection
40
+
41
+ Set the `multiple` prop to allow selecting more than one option.
42
+
43
+ ```svelte
44
+ <Dropdown multiple>
45
+ <DropdownOption value="A" text="Option A">Option A</DropdownOption>
46
+ <DropdownOption value="B" text="Option B">Option B</DropdownOption>
47
+ <DropdownOption value="C" text="Option C">Option C</DropdownOption>
48
+ </Dropdown>
49
+ ```
50
+
51
+ ## Component Props
52
+
53
+ | Name | Type | Description |
54
+ | ----------------- | ----------------------------- | --------------------------------------------------------------------- |
55
+ | `value` | bindable `string \| string[]` | The selected value, or an array of values when `multiple` is set. |
56
+ | `multiple` | `boolean` | Allow selecting more than one option. |
57
+ | `placeholder` | `string` | Text shown when no option is selected. Default: `'Select an option'`. |
58
+ | `disabled` | `boolean` | Disables user interaction. |
59
+ | `flyoutMaxHeight` | `number` | Maximum height of the options flyout before it scrolls. |
60
+ | `name` | `string` | Name of the underlying form control. |
61
+ | `ref` | bindable `HTMLElement` | The DOM reference of the dropdown element. |
62
+ | `children` | `Snippet` | The `DropdownOption` items to render. |
63
+
64
+ ## DropdownOption Props
65
+
66
+ | Name | Type | Description |
67
+ | ---------- | --------- | ------------------------------------------------------------------------------ |
68
+ | `value` | `string` | The value of the option, used for selection. |
69
+ | `text` | `string` | Plain-text label used to display the selection when the flyout is closed. |
70
+ | `children` | `Snippet` | The content rendered for the option (can be rich content such as a `Persona`). |
@@ -0,0 +1,2 @@
1
+ import type { DropdownContext } from './types.ts';
2
+ export declare const getDropdownContext: () => DropdownContext | null, setDropdownContext: (context: DropdownContext) => void;
@@ -0,0 +1,2 @@
1
+ import { createFSContext } from '../../internal/index.js';
2
+ export const [getDropdownContext, setDropdownContext] = createFSContext();
@@ -0,0 +1,31 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import { ListViewItem } from '../../index.js';
4
+ import { PREFIX } from '../../internal/constants.js';
5
+ import { getDropdownContext } from './dropdown-context.js';
6
+ import type { DropdownOptionProps } from './types.js';
7
+
8
+ const FALLBACK_ID = $props.id();
9
+ const ID = `${PREFIX}-dropdown-option-${FALLBACK_ID}`;
10
+
11
+ let { value, text, disabled, id = ID, ref = $bindable(), children }: DropdownOptionProps = $props();
12
+
13
+ const context = getDropdownContext();
14
+
15
+ if (!context) throw new Error('DropdownOption must be used within a Dropdown');
16
+
17
+ // Report the option's label so the trigger can show text instead of the raw value.
18
+ onMount(() => {
19
+ if (value == null) return;
20
+ const label = text ?? (ref?.textContent?.trim() || String(value));
21
+ context.methods?.registerOption(String(value), label);
22
+ });
23
+ </script>
24
+
25
+ <ListViewItem role="option" {value} {id} bind:ref {disabled}>
26
+ {#if children}
27
+ {@render children?.()}
28
+ {:else}
29
+ {text}
30
+ {/if}
31
+ </ListViewItem>
@@ -0,0 +1,4 @@
1
+ import type { DropdownOptionProps } from './types.ts';
2
+ declare const DropdownOption: import("svelte").Component<DropdownOptionProps, {}, "ref">;
3
+ type DropdownOption = ReturnType<typeof DropdownOption>;
4
+ export default DropdownOption;
@@ -0,0 +1,309 @@
1
+ <script lang="ts">
2
+ import { onClickOutside } from 'runed';
3
+ import ChevronDownFilled from 'fluentui-icons-svelte/ChevronDownFilled.svelte';
4
+ import { Flyout, ListView, ListViewItem } from '../../index.js';
5
+ import type { DropdownProps } from './types.js';
6
+ import { tick } from 'svelte';
7
+ import { SvelteMap } from 'svelte/reactivity';
8
+ import { setTabspotAttributes, unsetTabspotSection } from 'tabspot';
9
+ import { PREFIX } from '../../internal/constants.js';
10
+ import { getGlobalFSContext } from '../../providers/fluentui-svelte/fluentui-svelte.js';
11
+ import { setDropdownContext } from './dropdown-context.js';
12
+
13
+ const FALLBACK_ID = $props.id();
14
+ const ID = `${PREFIX}-dropdown-${FALLBACK_ID}`;
15
+
16
+ let {
17
+ id = ID,
18
+ name = id,
19
+ placeholder = 'Select an option',
20
+ multiple,
21
+ value = $bindable(multiple ? [] : ''),
22
+ disabled,
23
+ flyoutMaxHeight,
24
+ ref = $bindable(),
25
+ wrapperProps,
26
+ buttonRef = $bindable(),
27
+ buttonProps,
28
+ flyoutRef = $bindable(),
29
+ flyoutProps,
30
+ listboxRef = $bindable(),
31
+ listboxProps,
32
+ onclick,
33
+ children
34
+ }: DropdownProps = $props();
35
+
36
+ let open = $state(false);
37
+
38
+ let roundClass = $state('bottom');
39
+
40
+ const globalFSContext = getGlobalFSContext();
41
+
42
+ const OPEN_KEYS = ['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight', 'Enter', ' '];
43
+
44
+ // Options only mount while the flyout is open, so we cache the last-known text
45
+ // for every value here to keep rendering the selection once the list is closed.
46
+ const optionLabels = new SvelteMap<string, string>();
47
+
48
+ setDropdownContext({
49
+ config: null,
50
+ state: null,
51
+ events: null,
52
+ methods: {
53
+ registerOption: (optionValue: string, text: string) => optionLabels.set(optionValue, text)
54
+ }
55
+ });
56
+
57
+ const selectedValues = $derived(multiple ? (Array.isArray(value) ? value : []) : value ? [value as string] : []);
58
+
59
+ const hasValue = $derived(selectedValues.length > 0);
60
+
61
+ const displayLabel = $derived(
62
+ hasValue ? selectedValues.map((v) => optionLabels.get(v) ?? v).join(', ') : placeholder
63
+ );
64
+
65
+ onClickOutside(
66
+ () => ref,
67
+ () => closeDropdown()
68
+ );
69
+
70
+ function handlePlacementChange(newPlacement: string) {
71
+ roundClass = newPlacement.includes('-') ? newPlacement.split('-')[0] : newPlacement;
72
+ }
73
+
74
+ async function openDropdown() {
75
+ if (disabled || open) return;
76
+ open = true;
77
+ await tick();
78
+ globalFSContext?.state?.tabspotInstance?.rebuild(ref);
79
+ }
80
+
81
+ function closeDropdown() {
82
+ if (!open) return;
83
+ open = false;
84
+ globalFSContext?.state?.tabspotInstance?.update({});
85
+ }
86
+
87
+ async function handleKeyDown(e: KeyboardEvent) {
88
+ if (disabled) return;
89
+
90
+ const { key } = e;
91
+
92
+ if (OPEN_KEYS.includes(key)) {
93
+ e.preventDefault();
94
+ await openDropdown();
95
+ return;
96
+ }
97
+
98
+ if (key === 'Escape' && open) {
99
+ e.preventDefault();
100
+ closeDropdown();
101
+ }
102
+ }
103
+
104
+ async function handleClick(e: MouseEvent) {
105
+ if (open) closeDropdown();
106
+ else await openDropdown();
107
+ onclick?.(e);
108
+ }
109
+
110
+ // Force rebuild of tabspot handling tree
111
+ $effect(() => {
112
+ if (!ref) return;
113
+
114
+ if (!open) {
115
+ unsetTabspotSection(ref, 'root');
116
+ return;
117
+ }
118
+
119
+ setTabspotAttributes({
120
+ config: {
121
+ root: {
122
+ manageSpecialKeys: true
123
+ },
124
+ mover: {
125
+ axis: 'vertical',
126
+ items: '.fs-list-view-item',
127
+ activation: {
128
+ controller: `#${id}-button`,
129
+ mode: 'activedescendant',
130
+ mark: {
131
+ attribute: 'data-active'
132
+ }
133
+ }
134
+ }
135
+ },
136
+ element: ref,
137
+ merge: true
138
+ });
139
+ });
140
+ </script>
141
+
142
+ <div class={['fs-dropdown', `square-${roundClass}`, { open, disabled }]} bind:this={ref} {...wrapperProps}>
143
+ <ChevronDownFilled class="indicator" />
144
+ <button
145
+ bind:this={buttonRef}
146
+ type="button"
147
+ role="combobox"
148
+ onclick={handleClick}
149
+ onkeydown={handleKeyDown}
150
+ aria-controls={`${id}-listbox`}
151
+ aria-expanded={open}
152
+ id={`${id}-button`}
153
+ aria-haspopup="listbox"
154
+ {disabled}
155
+ class={['fs-dropdown-button', hasValue && 'has-value']}
156
+ {...buttonProps}
157
+ >
158
+ {displayLabel}
159
+ </button>
160
+
161
+ <input type="hidden" {name} {value} {id} {disabled} />
162
+
163
+ {#if open}
164
+ <Flyout
165
+ style={flyoutMaxHeight ? `max-height: ${flyoutMaxHeight};` : ''}
166
+ offset={0}
167
+ bind:ref={flyoutRef}
168
+ {...flyoutProps}
169
+ floating
170
+ roundCorners="bottom"
171
+ reference={ref}
172
+ id={`${id}-flyout`}
173
+ onPlacementChange={(place) => handlePlacementChange(place)}
174
+ placementConfig={{ allowedPlacements: ['bottom', 'top'] }}
175
+ class="fs-dropdown-flyout {roundClass === 'top' ? 'top-shadow' : ''} {flyoutProps?.class}"
176
+ >
177
+ <ListView
178
+ bind:ref={listboxRef}
179
+ bind:selectedItems={
180
+ () => {
181
+ if (multiple) {
182
+ return (value as string[]) || [];
183
+ } else {
184
+ return value ? [value as string] : [];
185
+ }
186
+ },
187
+ (v) => {
188
+ if (multiple) {
189
+ value = v || [];
190
+ } else {
191
+ value = v?.[0] || '';
192
+ }
193
+ }
194
+ }
195
+ selectionMode={multiple ? 'multiselect' : 'single'}
196
+ onSelectionChange={() => {
197
+ if (!multiple) closeDropdown();
198
+ }}
199
+ navigationMode="items"
200
+ id={`${id}-listbox`}
201
+ role="listbox"
202
+ disableTabspot
203
+ {...listboxProps}
204
+ >
205
+ {#if !children}
206
+ <ListViewItem disabled>No options available</ListViewItem>
207
+ {:else}
208
+ {@render children?.()}
209
+ {/if}
210
+ </ListView>
211
+ </Flyout>
212
+ {/if}
213
+ </div>
214
+
215
+ <style>
216
+ .fs-dropdown {
217
+ display: flex;
218
+ align-items: center;
219
+ position: relative;
220
+ border-radius: var(--fs-control-border-radius);
221
+ background: var(--fs-control-fill-default);
222
+ min-width: 10rem;
223
+ cursor: pointer;
224
+ &:before {
225
+ content: '';
226
+ pointer-events: none;
227
+ width: calc(100% + 0.1rem);
228
+ height: calc(100% + 0.1rem);
229
+ position: absolute;
230
+ top: -0.05rem;
231
+ left: -0.05rem;
232
+ padding: 0.05rem;
233
+ border-radius: 0.313rem;
234
+ mask:
235
+ linear-gradient(#fff 0 0) content-box,
236
+ linear-gradient(#fff 0 0);
237
+ mask-composite: exclude;
238
+ background: var(--fs-elevation-text-border);
239
+ z-index: 1;
240
+ }
241
+ &:after {
242
+ content: '';
243
+ pointer-events: none;
244
+ width: 0;
245
+ height: 10px;
246
+ border-radius: 0px 0px 5px 5px;
247
+ position: absolute;
248
+ bottom: -0.063rem;
249
+ left: calc(50% - 0.063rem);
250
+ clip-path: polygon(0 75%, 100% 75%, 100% 100%, 0% 100%);
251
+ background: transparent;
252
+ transition:
253
+ width var(--fs-normal-duration) var(--fs-point-to-point),
254
+ left var(--fs-normal-duration) var(--fs-point-to-point);
255
+ z-index: 2;
256
+ }
257
+ & .fs-dropdown-button {
258
+ all: unset;
259
+ width: 100%;
260
+ padding: 0.275rem 2.2rem 0.4rem 0.713rem;
261
+ border-radius: var(--fs-control-border-radius);
262
+ font-size: var(--fs-body-font-size);
263
+ color: var(--fs-text-primary);
264
+ display: flex;
265
+ align-items: center;
266
+ gap: 0.5rem;
267
+ color: var(--fs-text-secondary);
268
+ }
269
+ &.open.square-top {
270
+ border-top-left-radius: 0;
271
+ border-top-right-radius: 0;
272
+ &::after,
273
+ &::before {
274
+ border-top-left-radius: 0;
275
+ border-top-right-radius: 0;
276
+ }
277
+ }
278
+ &.open.square-bottom {
279
+ border-bottom-left-radius: 0;
280
+ border-bottom-right-radius: 0;
281
+ &::after,
282
+ &::before {
283
+ border-bottom-left-radius: 0;
284
+ border-bottom-right-radius: 0;
285
+ }
286
+ }
287
+ & :global(.fs-flyout) {
288
+ padding: 0 5px;
289
+ width: calc(100% + 2px);
290
+ z-index: 1;
291
+ &:global(.top-shadow) {
292
+ box-shadow: 0 -0.5rem 0.8rem #00000024;
293
+ }
294
+ }
295
+ &:has(:focus-visible):after,
296
+ &.open:after {
297
+ width: calc(100% + 0.125rem);
298
+ left: -0.063rem;
299
+ background-color: var(--fs-accent-fill-default);
300
+ }
301
+ & :global(> .indicator) {
302
+ width: 1rem;
303
+ position: absolute;
304
+ right: 0.6rem;
305
+ pointer-events: none;
306
+ color: var(--fs-text-secondary);
307
+ }
308
+ }
309
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { DropdownProps } from './types.ts';
2
+ declare const Dropdown: import("svelte").Component<DropdownProps, {}, "ref" | "value" | "flyoutRef" | "buttonRef" | "listboxRef">;
3
+ type Dropdown = ReturnType<typeof Dropdown>;
4
+ export default Dropdown;
@@ -0,0 +1,82 @@
1
+ import type { HTMLAttributes, HTMLButtonAttributes, HTMLInputAttributes } from 'svelte/elements';
2
+ import type { ListViewProps, ListViewItemProps } from '../list-view/types.ts';
3
+ import type { FlyoutProps } from '../flyout/types.ts';
4
+ import type { FSContext } from '../../internal/index.js';
5
+ /** The value shape of a dropdown that allows more than one selection. */
6
+ export type DropdownMultipleValue = {
7
+ multiple: true;
8
+ value?: string[];
9
+ };
10
+ /** The value shape of a dropdown that allows a single selection. */
11
+ export type DropdownSingleValue = {
12
+ multiple?: false;
13
+ value?: string;
14
+ };
15
+ /** @propsmith DropdownProps */
16
+ export type DropdownProps = {
17
+ /** The selected value. An array of values when `multiple` is set.
18
+ * @type string | string[]
19
+ * @default multiple ? [] : ''
20
+ * @bindable
21
+ */
22
+ value?: string | string[];
23
+ /** Allows more than one option to be selected at a time. */
24
+ multiple?: boolean;
25
+ /** The text shown by the trigger while no option is selected.
26
+ * @default 'Select an option'
27
+ */
28
+ placeholder?: string;
29
+ /** Disables the user interaction. */
30
+ disabled?: boolean;
31
+ /** The name submitted with the form. Falls back to the id of the dropdown.
32
+ * @default id
33
+ */
34
+ name?: string | null;
35
+ /** The DOM reference of the dropdown element.
36
+ * @bindable
37
+ */
38
+ ref?: HTMLDivElement;
39
+ /** Called when the dropdown is clicked. */
40
+ onclick?: (e: MouseEvent) => void;
41
+ /** The attributes to spread on the wrapper element.
42
+ * @type HTMLAttributes
43
+ */
44
+ wrapperProps?: HTMLAttributes<HTMLDivElement>;
45
+ /** The DOM reference of the button that opens the dropdown.
46
+ * @bindable
47
+ */
48
+ buttonRef?: HTMLButtonElement;
49
+ /** The attributes to spread on the button that opens the dropdown.
50
+ * @type HTMLButtonAttributes
51
+ */
52
+ buttonProps?: HTMLButtonAttributes;
53
+ /** The DOM reference of the hidden input holding the value. */
54
+ inputRef?: HTMLInputElement;
55
+ /** The DOM reference of the flyout element.
56
+ * @bindable
57
+ */
58
+ flyoutRef?: HTMLDivElement;
59
+ /** The props to spread on the flyout.
60
+ * @type FlyoutProps
61
+ */
62
+ flyoutProps?: FlyoutProps;
63
+ /** The maximum height of the flyout, as a CSS length. */
64
+ flyoutMaxHeight?: string;
65
+ /** The DOM reference of the listbox element.
66
+ * @bindable
67
+ */
68
+ listboxRef?: HTMLUListElement;
69
+ /** The props to spread on the listbox rendered inside the flyout.
70
+ * @type ListViewProps
71
+ */
72
+ listboxProps?: Omit<ListViewProps<'ul'>, 'ref' | 'children' | 'selectedItems' | 'selectionMode'>;
73
+ } & (DropdownMultipleValue | DropdownSingleValue) & Omit<HTMLInputAttributes, 'value' | 'onclick'>;
74
+ /** @propsmith DropdownOptionProps */
75
+ export type DropdownOptionProps = {
76
+ /** The text shown by the dropdown once the option is selected. Falls back to the rendered children. */
77
+ text?: string;
78
+ } & ListViewItemProps<'li'>;
79
+ export type DropdownContext = FSContext<null, null, null, {
80
+ /** Options report their display text so the trigger can show a label instead of the raw value. */
81
+ registerOption: (value: string, text: string) => void;
82
+ }>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,72 @@
1
+ # Dropdown Select
2
+
3
+ The Dropdown Select is a dropdown built on the native `<select>` element. It lets users choose one option, or several with the `multiple` prop, from a list of `DropdownSelectOption` children.
4
+
5
+ > **Early access:** The API, features, and behavior of the component are subject to significant changes. This component will be rebuilt using the FloatingUI Svelte package, which is still under active development. We strongly advise against using this component in production environments at this time.
6
+
7
+ ## Usage
8
+
9
+ ```svelte
10
+ <script>
11
+ import { DropdownSelect, DropdownSelectOption } from 'fluentui-svelte';
12
+ </script>
13
+
14
+ <DropdownSelect>
15
+ <DropdownSelectOption value="A">Option A</DropdownSelectOption>
16
+ <DropdownSelectOption value="B">Option B</DropdownSelectOption>
17
+ <DropdownSelectOption value="C">Option C</DropdownSelectOption>
18
+ </DropdownSelect>
19
+ ```
20
+
21
+ ## Examples
22
+
23
+ ### Custom Option Content
24
+
25
+ Options can render rich content such as a `Persona`. Provide a `text` prop for the plain-text selection label.
26
+
27
+ ```svelte
28
+ <DropdownSelect>
29
+ <DropdownSelectOption value="John Doe" text="John Doe">
30
+ <Persona
31
+ name="John Doe"
32
+ primaryText="Software Engineer"
33
+ presence={{ status: 'available' }}
34
+ avatar={{ color: 'colorful', idForColor: '' }}
35
+ />
36
+ </DropdownSelectOption>
37
+ <DropdownSelectOption value="B">Option B</DropdownSelectOption>
38
+ <DropdownSelectOption value="C">Option C</DropdownSelectOption>
39
+ </DropdownSelect>
40
+ ```
41
+
42
+ ### Multiple Selection
43
+
44
+ Set the `multiple` prop to allow selecting more than one option.
45
+
46
+ ```svelte
47
+ <DropdownSelect multiple>
48
+ <DropdownSelectOption value="A">Option A</DropdownSelectOption>
49
+ <DropdownSelectOption value="B">Option B</DropdownSelectOption>
50
+ <DropdownSelectOption value="C">Option C</DropdownSelectOption>
51
+ </DropdownSelect>
52
+ ```
53
+
54
+ ## Component Props
55
+
56
+ | Name | Type | Description |
57
+ | ----------------- | ----------------------------- | --------------------------------------------------------------------------- |
58
+ | `value` | bindable `string \| string[]` | The selected value, or an array of values when `multiple` is set. |
59
+ | `multiple` | `boolean` | Allow selecting more than one option. |
60
+ | `placeholder` | `string` | Text shown when no option is selected. Default: `'Native Select Dropdown'`. |
61
+ | `hidePlaceholder` | `boolean` | Hides the placeholder option. |
62
+ | `ref` | bindable `HTMLSelectElement` | The DOM reference of the underlying `<select>` element. |
63
+ | `wrapperRef` | bindable `HTMLDivElement` | The DOM reference of the wrapper element. |
64
+ | `children` | `Snippet` | The `DropdownSelectOption` items to render. |
65
+
66
+ ## DropdownSelectOption Props
67
+
68
+ | Name | Type | Description |
69
+ | ---------- | --------- | ----------------------------------------------------------------------- |
70
+ | `value` | `string` | The value of the option, used for selection. |
71
+ | `text` | `string` | Plain-text label used to display the selection when the list is closed. |
72
+ | `children` | `Snippet` | The content rendered for the option. |
@@ -0,0 +1,87 @@
1
+ <script lang="ts">
2
+ import type { DropdownSelectOptionProps } from './types.js';
3
+ import CheckmarkFilled from 'fluentui-icons-svelte/CheckmarkFilled.svelte';
4
+
5
+ let {
6
+ value,
7
+ text,
8
+ disabled,
9
+ ref = $bindable(),
10
+ class: classes,
11
+ children,
12
+ ...attributes
13
+ }: DropdownSelectOptionProps = $props();
14
+ </script>
15
+
16
+ <option class="fs-dropdown-select-option {classes}" {value} {disabled} bind:this={ref} {...attributes}>
17
+ <span class="option-content">
18
+ <CheckmarkFilled class="checkmark" width="16" height="16" />
19
+ {#if text}
20
+ <span class="value-text">{text}</span>
21
+ {/if}
22
+ <span>
23
+ {@render children?.()}
24
+ </span>
25
+ </span>
26
+ </option>
27
+
28
+ <style>
29
+ .fs-dropdown-select-option {
30
+ padding: 0 !important;
31
+ display: flex;
32
+ border-radius: var(--fs-control-border-radius);
33
+
34
+ /* User-Agent Override Styles Hack */
35
+ transition: background calc(infinity * 1s) !important;
36
+
37
+ &::checkmark,
38
+ & :global(.checkmark),
39
+ & .value-text {
40
+ display: none;
41
+ }
42
+ & .option-content {
43
+ border-radius: var(--fs-control-border-radius);
44
+ font-size: var(--fs-body2-font-size);
45
+ color: var(--fs-text-primary);
46
+ border: none;
47
+ padding: 0.275rem 0.5rem 0.4rem 0.5rem;
48
+ position: relative;
49
+ outline: none;
50
+ display: flex;
51
+ width: 100%;
52
+ gap: 0.5rem;
53
+ align-items: center;
54
+ text-decoration: none;
55
+ user-select: none;
56
+ max-height: unset;
57
+ }
58
+ &:not(:last-child) {
59
+ margin-bottom: 0.25rem;
60
+ }
61
+ &[disabled] {
62
+ cursor: not-allowed;
63
+ background: var(--fs-subtle-fill-transparent) !important;
64
+ color: var(--fs-text-disabled) !important;
65
+ }
66
+ &[hidden] {
67
+ display: none;
68
+ }
69
+ &:checked {
70
+ background: var(--fs-subtle-fill-secondary);
71
+ padding: 0.275rem 0.5rem 0.4rem 0.5rem;
72
+ & :global(.checkmark) {
73
+ display: flex;
74
+ }
75
+ &::after {
76
+ opacity: 1;
77
+ }
78
+ }
79
+ &:hover .option-content {
80
+ background: var(--fs-subtle-fill-secondary);
81
+ }
82
+ &:focus-visible {
83
+ outline: 0.125rem var(--fs-focus-stroke-outer) solid;
84
+ outline-offset: 0.063rem;
85
+ }
86
+ }
87
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { DropdownSelectOptionProps } from './types.ts';
2
+ declare const DropdownSelectOption: import("svelte").Component<DropdownSelectOptionProps, {}, "ref">;
3
+ type DropdownSelectOption = ReturnType<typeof DropdownSelectOption>;
4
+ export default DropdownSelectOption;