fluentui-svelte 0.1.2 → 0.2.1

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 (87) hide show
  1. package/README.md +0 -6
  2. package/dist/components/auto-suggest-box/auto-suggest-box.svelte +74 -56
  3. package/dist/components/auto-suggest-box/docs/llms.md +46 -13
  4. package/dist/components/auto-suggest-box/option.svelte +2 -1
  5. package/dist/components/auto-suggest-box/types.d.ts +5 -0
  6. package/dist/components/avatar/avatar.svelte +1 -1
  7. package/dist/components/avatar/docs/llms.md +20 -14
  8. package/dist/components/badge/badge-icon.svelte +5 -8
  9. package/dist/components/badge/badge.svelte +6 -2
  10. package/dist/components/badge/docs/llms.md +29 -16
  11. package/dist/components/button/button.svelte +13 -7
  12. package/dist/components/button/docs/llms.md +33 -24
  13. package/dist/components/button/types.d.ts +5 -1
  14. package/dist/components/calendar-date-picker/docs/llms.md +17 -7
  15. package/dist/components/calendar-view/calendar-view-header.svelte +2 -2
  16. package/dist/components/calendar-view/calendar-view-header.svelte.d.ts +2 -17
  17. package/dist/components/calendar-view/calendar-view-months.svelte +1 -1
  18. package/dist/components/calendar-view/calendar-view-years.svelte +1 -1
  19. package/dist/components/calendar-view/calendar-view.svelte +66 -52
  20. package/dist/components/calendar-view/docs/llms.md +42 -30
  21. package/dist/components/card/card-context.svelte.d.ts +2 -0
  22. package/dist/components/card/card-context.svelte.js +2 -0
  23. package/dist/components/card/card-footer.svelte +37 -0
  24. package/dist/components/card/card-footer.svelte.d.ts +4 -0
  25. package/dist/components/card/card-header.svelte +81 -0
  26. package/dist/components/card/card-header.svelte.d.ts +4 -0
  27. package/dist/components/card/card-preview.svelte +64 -0
  28. package/dist/components/card/card-preview.svelte.d.ts +4 -0
  29. package/dist/components/card/card.svelte +242 -0
  30. package/dist/components/card/card.svelte.d.ts +39 -0
  31. package/dist/components/card/docs/llms.md +226 -0
  32. package/dist/components/card/types.d.ts +129 -0
  33. package/dist/components/card/types.js +1 -0
  34. package/dist/components/checkbox/checkbox.svelte +5 -3
  35. package/dist/components/checkbox/docs/llms.md +18 -12
  36. package/dist/components/date-picker/docs/llms.md +25 -15
  37. package/dist/components/dialog/dialog-surface.svelte +8 -8
  38. package/dist/components/dialog/dialog.svelte +41 -39
  39. package/dist/components/dialog/docs/llms.md +59 -34
  40. package/dist/components/divider/docs/llms.md +14 -9
  41. package/dist/components/dropdown/docs/llms.md +34 -15
  42. package/dist/components/dropdown/dropdown.svelte +4 -2
  43. package/dist/components/dropdown-select/docs/llms.md +28 -14
  44. package/dist/components/expander/docs/llms.md +19 -12
  45. package/dist/components/flyout/docs/llms.md +17 -11
  46. package/dist/components/hyperlink/docs/llms.md +11 -7
  47. package/dist/components/info-bar/docs/llms.md +15 -9
  48. package/dist/components/label/docs/llms.md +15 -11
  49. package/dist/components/list-view/docs/llms.md +34 -24
  50. package/dist/components/list-view/list-view-item.svelte +10 -4
  51. package/dist/components/list-view/list-view.svelte +68 -63
  52. package/dist/components/menu/context-menu-trigger.svelte +45 -40
  53. package/dist/components/menu/docs/llms.md +63 -34
  54. package/dist/components/menu/menu-item-checkbox.svelte +4 -2
  55. package/dist/components/menu/menu-item-radio.svelte +4 -2
  56. package/dist/components/menu/menu-item-switch.svelte +4 -2
  57. package/dist/components/menu/menu-item.svelte +6 -2
  58. package/dist/components/menu/menu-popover.svelte +21 -10
  59. package/dist/components/menu/menu-trigger.svelte +22 -9
  60. package/dist/components/menu/menu.svelte +98 -87
  61. package/dist/components/number-box/docs/llms.md +10 -6
  62. package/dist/components/persona/docs/llms.md +19 -14
  63. package/dist/components/progress-bar/docs/llms.md +18 -10
  64. package/dist/components/progress-ring/docs/llms.md +19 -12
  65. package/dist/components/radio-button/docs/llms.md +13 -8
  66. package/dist/components/skeleton/docs/llms.md +13 -8
  67. package/dist/components/slider/docs/llms.md +33 -21
  68. package/dist/components/slider/slider.svelte +13 -11
  69. package/dist/components/text-box/docs/llms.md +23 -17
  70. package/dist/components/textarea/docs/llms.md +16 -7
  71. package/dist/components/time-picker/docs/llms.md +20 -10
  72. package/dist/components/toggle-switch/docs/llms.md +13 -9
  73. package/dist/components/tooltip/docs/llms.md +24 -10
  74. package/dist/components/tree-view/docs/llms.md +53 -35
  75. package/dist/components/tree-view/tree-view-item-content.svelte +1 -1
  76. package/dist/components/tree-view/tree-view-item.svelte +3 -3
  77. package/dist/components/tree-view/tree-view.svelte +89 -93
  78. package/dist/css/class-darkmode.css +3 -1
  79. package/dist/css/media-darkmode.css +3 -1
  80. package/dist/css/theme.css +3 -1
  81. package/dist/index.d.ts +4 -0
  82. package/dist/index.js +6 -0
  83. package/dist/internal/components/render-soc/render-soc.svelte +17 -23
  84. package/dist/internal/components/render-soc/render-soc.svelte.d.ts +16 -16
  85. package/dist/providers/fluentui-svelte/fluentui-svelte.svelte +15 -15
  86. package/dist/types/index.d.ts +1 -0
  87. package/package.json +1 -1
@@ -24,10 +24,14 @@ Disables the hyperlink and prevents navigation.
24
24
 
25
25
  ## Component Props
26
26
 
27
- | Name | Type | Description |
28
- | ------------------ | ------------------- | ----------------------------------------------------------------------- |
29
- | `href` | `string` | The URL to navigate to when the link is clicked. |
30
- | `disabled` | `boolean` | Disables the hyperlink and prevents navigation. |
31
- | `children` | `Snippet` | The content of the hyperlink. |
32
- | `ref` | `HTMLAnchorElement` | A bindable reference to the underlying anchor element. |
33
- | Element Attributes | | You can use any valid HTML anchor attributes (e.g., target, rel, etc.). |
27
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
28
+ <!-- props:HyperlinkProps -->
29
+
30
+ | Name | Type | Default | Description |
31
+ | ------------------------ | ------------------- | ------- | ---------------------------------------- |
32
+ | `href` | `string` | `'#'` | The URL the hyperlink points to. |
33
+ | `disabled` | `boolean` | | Disables the user interaction. |
34
+ | `ref` _bindable_ | `HTMLAnchorElement` | | The DOM reference of the anchor element. |
35
+ | Element Attributes (`a`) | | | |
36
+
37
+ <!-- /props:HyperlinkProps -->
@@ -70,12 +70,18 @@ The hideCloseButton prop allows you to hide the close button in the InfoBar.
70
70
 
71
71
  ## Component Props
72
72
 
73
- | Name | Type | Description |
74
- | ----------------- | ---------------------- | --------------------------------------------------------------------------------------------------------- |
75
- | `status` | `string` | The status of the InfoBar. Possible values: 'information', 'attention', 'warning', 'critical', 'success'. |
76
- | `style` | `string` | The style of the InfoBar. Possible values: 'inline', 'multiline'. |
77
- | `title` | `string` | The title of the InfoBar. |
78
- | `icon` | `Snippet \| Component` | The icon to display in the InfoBar. |
79
- | `iconSize` | `number` | The size of the icon in pixels. Default: 20. |
80
- | `hideCloseButton` | `boolean` | Whether to hide the close button. Default: false. |
81
- | `children` | `Snippet` | The child elements to render inside the InfoBar. |
73
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
74
+ <!-- props:InfoBarProps -->
75
+
76
+ | Name | Type | Default | Description |
77
+ | -------------------------- | ---------------------------------------------------------------------------------------------- | --------------- | ---------------------------------------------------------------------------- |
78
+ | `status` | `'information'` &#124; `'attention'` &#124; `'warning'` &#124; `'critical'` &#124; `'success'` | `'information'` | The severity of the message, which picks the icon and the colors. |
79
+ | `style` | `'inline'` &#124; `'multiline'` | `'inline'` | Lays the message out on a single line, or stacked below the title. |
80
+ | `title` | `string` | | The title of the InfoBar. |
81
+ | `icon` | `Snippet` &#124; `Component` | | Custom icon, rendered instead of the one the `status` would pick on its own. |
82
+ | `iconSize` | `number` | `20` | The size of the icon in pixels. |
83
+ | `hideCloseButton` | `boolean` | | Removes the button that dismisses the InfoBar. |
84
+ | `children` | `Snippet` | | The message of the InfoBar. |
85
+ | Element Attributes (`div`) | | | |
86
+
87
+ <!-- /props:InfoBarProps -->
@@ -54,14 +54,18 @@ Pass a `required` object to mark the label as required and render a required ind
54
54
 
55
55
  ## Component Props
56
56
 
57
- | Name | Type | Description |
58
- | --------------- | ------------------------------------------- | ------------------------------------------------------------------------------- |
59
- | `label` | `string` | The text content of the label. Default: `'Label Element'`. |
60
- | `size` | `'small' \| 'medium' \| 'large'` | The size of the label text. Default: `'medium'`. |
61
- | `weight` | `'regular' \| 'semibold'` | The font weight of the label. Default: `'regular'`. |
62
- | `labelPosition` | `'before' \| 'after' \| 'above' \| 'below'` | Position of the label text relative to the wrapped content. Default: `'after'`. |
63
- | `required` | `{ message?: string; abbr?: string }` | Marks the label as required and renders a required indicator (default `*`). |
64
- | `disabled` | `boolean` | Renders the label in a disabled style and disables pointer events. |
65
- | `class` | `string` | Additional classes applied to the label element. |
66
- | `ref` | bindable `HTMLLabelElement` | The DOM reference of the label element. |
67
- | `children` | `Snippet` | The content wrapped by the label (typically a form control). |
57
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
58
+ <!-- props:LabelProps -->
59
+
60
+ | Name | Type | Default | Description |
61
+ | ---------------------------- | ------------------------------------------------------------- | ----------------- | ------------------------------------------------------------------------- |
62
+ | `label` | `string` | `'Label Element'` | The text of the label. Falls back to the rendered children. |
63
+ | `size` | `'small'` &#124; `'medium'` &#124; `'large'` | `'medium'` | The size of the label text. |
64
+ | `weight` | `'regular'` &#124; `'semibold'` | `'regular'` | The weight of the label text. |
65
+ | `labelPosition` | `'before'` &#124; `'after'` &#124; `'above'` &#124; `'below'` | `'after'` | Where the label sits relative to the field it describes. |
66
+ | `required` | `{ abbr?: string; message: string; }` | | Marks the field as required, and describes why through the given message. |
67
+ | `disabled` | `boolean` | | Renders the label as disabled, to match the field it describes. |
68
+ | `ref` _bindable_ | `HTMLLabelElement` | | The DOM reference of the label element. |
69
+ | Element Attributes (`label`) | | | |
70
+
71
+ <!-- /props:LabelProps -->
@@ -81,30 +81,40 @@ Add and configure a checkbox for the element. You can use the same props for the
81
81
 
82
82
  ## ListView Props
83
83
 
84
- | Name | Type | Description |
85
- | ------------------- | --------------------------- | --------------------------------------------------------------------------------------------- |
86
- | `as` | `string` | The HTML tag to use for the list container. Possible values: ul, ol, div. |
87
- | `selectionMode` | `string` | Selection mode for the list. Possible values: single, multiselect, extended. |
88
- | `navigationMode` | `string` | Navigation mode for keyboard navigation. Possible values: items, composite. |
89
- | `selectedItems` | `string[]` | The currently selected item values. |
90
- | `shape` | `string` | The shape of the list items. Possible values: rounded, circular, square. |
91
- | `onSelectionChange` | `(Event, string[]) => void` | Callback fired when the selection changes. |
92
- | `element` | Dynamic | Reference to the list DOM element. Depends on the selected as value. |
93
- | `children` | Only `ListViewItem` | The ListViewItem children of the list. |
94
- | Element Attributes | Dynamic | Based on the chosen as value, you will have autocomplete for all HTML attributes of that tag. |
84
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
85
+ <!-- props:ListViewProps -->
86
+
87
+ | Name | Type | Default | Description |
88
+ | -------------------------- | --------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------- |
89
+ | `selectionMode` | `'none'` &#124; `'single'` &#124; `'multiselect'` &#124; `'extended'` | `'none'` | How many items can be selected, and how the selection is made. |
90
+ | `navigationMode` | `'items'` &#124; `'composite'` | `'items'` | Whether the list itself takes a single tab stop, or every item takes its own. |
91
+ | `selectedItems` _bindable_ | `string[]` | | The values of the selected items. |
92
+ | `shape` | `'circular'` &#124; `'rounded'` &#124; `'square'` | `'rounded'` | The items can have a circular, rounded or square shape. |
93
+ | `onSelectionChange` | `(e: Event, selectedItems: string[]` &#124; `[]) => void` | | Called whenever the selection changes. |
94
+ | `as` | `'ul'` &#124; `'ol'` &#124; `'div'` | `'ul'` | The HTML element to render the list as. |
95
+ | `ref` _bindable_ | `HTMLUListElement` &#124; `HTMLOListElement` &#124; `HTMLDivElement` | | The DOM reference of the list element. |
96
+ | `disableTabspot` | `boolean` | `false` | Opts the list out of the tabspot focus management, to wire your own. |
97
+ | HTML Attributes | | | |
98
+
99
+ <!-- /props:ListViewProps -->
95
100
 
96
101
  ## ListViewItem Props
97
102
 
98
- | Name | Type | Description |
99
- | ------------------ | ------------------------------ | --------------------------------------------------------------------------------------------- |
100
- | `as` | `string` | The HTML tag to use for the item container. Possible values: li, a, div. |
101
- | `active` | `boolean` | Whether the item is currently active or selected. |
102
- | `shape` | `string` | The shape of the item. Possible values: rounded, circular, square. |
103
- | `value` | `string` | The value of the item used for selection. |
104
- | `onAction` | `(MouseEvent, string) => void` | Callback fired when the item is activated. |
105
- | `onFocus` | `(Event, string) => void` | Callback fired when the item receives focus. |
106
- | `role` | `string` | ARIA role for the item. Possible values: treeitem, menuitem, option, row. |
107
- | `disabled` | `boolean` | Whether the item is disabled. |
108
- | `checkmark` | `object` | Props for the checkmark or checkbox. |
109
- | `children` | `Snippet` | The content of the item. |
110
- | Element Attributes | Dynamic | Based on the chosen as value, you will have autocomplete for all HTML attributes of that tag. |
103
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
104
+ <!-- props:ListViewItemProps -->
105
+
106
+ | Name | Type | Default | Description |
107
+ | ---------------- | ------------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------ |
108
+ | `as` | `'li'` &#124; `'a'` &#124; `'div'` | `'li'` | The HTML element to render the item as. |
109
+ | `shape` | `'circular'` &#124; `'rounded'` &#124; `'square'` | | The item can have a circular, rounded or square shape. Inherited from the list by default. |
110
+ | `value` | `string` | | The value reported to the list when the item is selected. Falls back to a generated id. |
111
+ | `active` | `boolean` | | Renders the item in its pressed state. |
112
+ | `role` | `'treeitem'` &#124; `'menuitem'` &#124; `'option'` &#124; `'row'` | | The ARIA role of the item. Derived from the list by default. |
113
+ | `disabled` | `boolean` | | Disables the user interaction. |
114
+ | `checkmark` | `CheckboxProps` | | The props to spread on the checkbox rendered when the list is multiselect. |
115
+ | `onAction` | `(e: MouseEvent, value: string) => void` | | Called when the item is clicked or activated with the keyboard. |
116
+ | `onfocus` | `(e: Event, value: string) => void` | | Called when the item receives the focus. |
117
+ | `ref` _bindable_ | `HTMLLIElement` &#124; `HTMLAnchorElement` &#124; `HTMLDivElement` | | The DOM reference of the item element. |
118
+ | HTML Attributes | | | |
119
+
120
+ <!-- /props:ListViewItemProps -->
@@ -24,14 +24,20 @@
24
24
  ...attributes
25
25
  }: ListViewItemProps<T> = $props();
26
26
 
27
- // svelte-ignore state_referenced_locally
28
- if (!ITEM_TAG.includes(as)) throw new Error(`Invalid tag: ${as}. Must be one of ${ITEM_TAG.join(', ')}`);
27
+ /**
28
+ * The tag the invariant rules over. The markup renders it through here, so it is checked
29
+ * during SSR and on every prop update rather than only once on mount.
30
+ */
31
+ const _as = $derived.by(() => {
32
+ if (!ITEM_TAG.includes(as)) throw new Error(`Invalid tag: ${as}. Must be one of ${ITEM_TAG.join(', ')}`);
33
+ return as;
34
+ });
29
35
 
30
36
  const CONTEXT = getListViewContext();
31
37
 
32
38
  if (!CONTEXT) throw new Error('ListViewItem must be used within a ListView');
33
39
 
34
- const { shape: _shape } = CONTEXT.config;
40
+ const _shape = $derived(CONTEXT.config.shape);
35
41
  const { state: _state } = CONTEXT;
36
42
  const { handleSelection, registerItem, unregisterItem, getChildrenRole } = CONTEXT.methods;
37
43
  const role = $derived(_role || getChildrenRole(as));
@@ -58,7 +64,7 @@
58
64
  </script>
59
65
 
60
66
  <svelte:element
61
- this={as}
67
+ this={_as}
62
68
  {role}
63
69
  data-value={value}
64
70
  aria-selected={role === 'option' ? active : undefined}
@@ -16,8 +16,14 @@
16
16
  ...attributes
17
17
  }: ListViewProps<Tag> = $props();
18
18
 
19
- // svelte-ignore state_referenced_locally
20
- if (!TAG.includes(as)) throw new Error(`Invalid tag: ${as}. Must be one of ${TAG.join(', ')}`);
19
+ /**
20
+ * The tag the invariant rules over. The markup renders it through here, so it is checked
21
+ * during SSR and on every prop update rather than only once on mount.
22
+ */
23
+ const _as = $derived.by(() => {
24
+ if (!TAG.includes(as)) throw new Error(`Invalid tag: ${as}. Must be one of ${TAG.join(', ')}`);
25
+ return as;
26
+ });
21
27
 
22
28
  const ROLE = $derived(getRole(as, selectionMode, navigationMode));
23
29
 
@@ -44,76 +50,75 @@
44
50
  disabled: boolean;
45
51
  }[] = $state([]);
46
52
 
47
- const config: ListViewContext['config'] = $derived({
48
- shape
49
- });
50
-
51
- const _state: ListViewContext['state'] = {
52
- get selectedItems() {
53
- return selectedItems;
54
- },
55
- set selectedItems(v) {
56
- selectedItems = v;
57
- },
58
- get anchorIndex() {
59
- return anchorIndex;
60
- },
61
- set anchorIndex(v) {
62
- anchorIndex = v;
63
- }
64
- };
65
-
66
- let methods: ListViewContext['methods'] = {
67
- handleSelection: (e: MouseEvent, value: string) => {
68
- if (selectionMode === 'none') return;
69
-
70
- const itemIndex = items.findIndex((item) => item.value === value);
71
- if (itemIndex === -1) return;
72
-
73
- const item = items[itemIndex];
74
- if (item.disabled) return;
75
-
76
- if (selectionMode === 'extended' && e.shiftKey && anchorIndex !== null) {
77
- const start = Math.min(anchorIndex, itemIndex);
78
- const end = Math.max(anchorIndex, itemIndex);
79
- const rangeValues = items
80
- .slice(start, end + 1)
81
- .filter((i) => !i.disabled)
82
- .map((i) => i.value);
83
- const newSelectedItems = Array.from(new Set([..._state.selectedItems, ...rangeValues]));
84
- _state.selectedItems = newSelectedItems;
85
- } else if (MULTISELECTABLE && (e.ctrlKey || e.metaKey)) {
86
- _state.selectedItems = _state.selectedItems.includes(value)
87
- ? _state.selectedItems.filter((v) => v !== value)
88
- : [..._state.selectedItems, value];
89
- _state.anchorIndex = itemIndex;
90
- } else {
91
- _state.selectedItems = [value];
92
- _state.anchorIndex = itemIndex;
53
+ const CONTEXT: ListViewContext = $state({
54
+ config: {
55
+ get shape() {
56
+ return shape;
93
57
  }
94
- onSelectionChange?.(e, _state.selectedItems);
95
58
  },
96
- registerItem: (id: string, value: string, disabled: boolean) => {
97
- items.push({ id, value, disabled });
98
- },
99
- unregisterItem: (id: string) => {
100
- items = items.filter((item) => item.id !== id);
59
+ state: {
60
+ get selectedItems() {
61
+ return selectedItems;
62
+ },
63
+ set selectedItems(v) {
64
+ selectedItems = v;
65
+ },
66
+ get anchorIndex() {
67
+ return anchorIndex;
68
+ },
69
+ set anchorIndex(v) {
70
+ anchorIndex = v;
71
+ }
101
72
  },
102
- getChildrenRole: (_tag: 'li' | 'a' | 'div') => {
103
- if (ROLE === 'grid') return 'row';
104
- if (ROLE === 'listbox') return 'option';
105
- return _tag !== 'li' ? 'listitem' : undefined;
73
+ events: null,
74
+ methods: {
75
+ handleSelection: (e: MouseEvent, value: string) => {
76
+ if (selectionMode === 'none') return;
77
+
78
+ const itemIndex = items.findIndex((item) => item.value === value);
79
+ if (itemIndex === -1) return;
80
+
81
+ const item = items[itemIndex];
82
+ if (item.disabled) return;
83
+
84
+ if (selectionMode === 'extended' && e.shiftKey && anchorIndex !== null) {
85
+ const start = Math.min(anchorIndex, itemIndex);
86
+ const end = Math.max(anchorIndex, itemIndex);
87
+ const rangeValues = items
88
+ .slice(start, end + 1)
89
+ .filter((i) => !i.disabled)
90
+ .map((i) => i.value);
91
+ selectedItems = Array.from(new Set([...selectedItems, ...rangeValues]));
92
+ } else if (MULTISELECTABLE && (e.ctrlKey || e.metaKey)) {
93
+ selectedItems = selectedItems.includes(value)
94
+ ? selectedItems.filter((v) => v !== value)
95
+ : [...selectedItems, value];
96
+ anchorIndex = itemIndex;
97
+ } else {
98
+ selectedItems = [value];
99
+ anchorIndex = itemIndex;
100
+ }
101
+ onSelectionChange?.(e, selectedItems);
102
+ },
103
+ registerItem: (id: string, value: string, disabled: boolean) => {
104
+ items.push({ id, value, disabled });
105
+ },
106
+ unregisterItem: (id: string) => {
107
+ items = items.filter((item) => item.id !== id);
108
+ },
109
+ getChildrenRole: (_tag: 'li' | 'a' | 'div') => {
110
+ if (ROLE === 'grid') return 'row';
111
+ if (ROLE === 'listbox') return 'option';
112
+ return _tag !== 'li' ? 'listitem' : undefined;
113
+ }
106
114
  }
107
- };
108
-
109
- // svelte-ignore state_referenced_locally
110
- const CONTEXT: ListViewContext = { config, state: _state, events: null, methods };
115
+ });
111
116
 
112
117
  setListViewContext(CONTEXT);
113
118
  </script>
114
119
 
115
120
  <svelte:element
116
- this={as}
121
+ this={_as}
117
122
  bind:this={ref as ListViewDOM[Tag]}
118
123
  class="fs-list-view"
119
124
  role={ROLE}
@@ -24,52 +24,57 @@
24
24
 
25
25
  const { toggle, close } = context.methods;
26
26
 
27
- const { id, openingDelay } = context.config;
27
+ const id = $derived(context.config.id);
28
28
 
29
- let offClick: (() => void) | null = $state(null);
30
-
31
- const debounced = useDebounce(async (e: MouseEvent) => {
32
- if (disabled) return;
33
-
34
- const { clientX, clientY } = e;
35
-
36
- _state.ref = {
37
- getBoundingClientRect() {
38
- return {
39
- width: 0,
40
- height: 0,
41
- x: clientX,
42
- y: clientY,
43
- top: clientY,
44
- right: clientX,
45
- bottom: clientY,
46
- left: clientX
47
- };
48
- }
49
- };
50
-
51
- // Add event to check if user click outside the menu to close it
52
- offClick ??= on(document, 'click', (e) => {
53
- const clickTarget = e.target as HTMLElement;
29
+ const openingDelay = $derived(context.config.openingDelay);
54
30
 
55
- if (!clickTarget.closest(`#fs-menu-popover-${id}`)) {
56
- _state.locked = false;
57
- close(e);
58
- offClick?.();
59
- offClick = null;
60
- }
61
- });
31
+ let offClick: (() => void) | null = $state(null);
62
32
 
63
- _state.locked = !_state.locked;
64
- toggle(e);
33
+ const debounced = useDebounce(
34
+ async (e: MouseEvent) => {
35
+ if (disabled) return;
36
+
37
+ const { clientX, clientY } = e;
38
+
39
+ _state.ref = {
40
+ getBoundingClientRect() {
41
+ return {
42
+ width: 0,
43
+ height: 0,
44
+ x: clientX,
45
+ y: clientY,
46
+ top: clientY,
47
+ right: clientX,
48
+ bottom: clientY,
49
+ left: clientX
50
+ };
51
+ }
52
+ };
53
+
54
+ // Add event to check if user click outside the menu to close it
55
+ offClick ??= on(document, 'click', (e) => {
56
+ const clickTarget = e.target as HTMLElement;
57
+
58
+ if (!clickTarget.closest(`#fs-menu-popover-${id}`)) {
59
+ _state.locked = false;
60
+ close(e);
61
+ offClick?.();
62
+ offClick = null;
63
+ }
64
+ });
65
65
 
66
- // When requesting to open the context menu when is already open, we need to wait for the toggle to finish before allowing it to be toggled again
67
- if (!_state.open) {
68
- await tick();
69
66
  _state.locked = !_state.locked;
70
67
  toggle(e);
71
- }
72
- }, openingDelay || 0);
68
+
69
+ // When requesting to open the context menu when is already open, we need to wait for the toggle to finish before allowing it to be toggled again
70
+ if (!_state.open) {
71
+ await tick();
72
+ _state.locked = !_state.locked;
73
+ toggle(e);
74
+ }
75
+ },
76
+ () => openingDelay || 0
77
+ );
73
78
 
74
79
  onMount(() => {
75
80
  _state.ref ??= VIRTUAL_ELEMENT;
@@ -121,49 +121,78 @@ This variant of the `MenuTrigger` component allows you to create context menus t
121
121
 
122
122
  ## Component Props (Menu)
123
123
 
124
- | Name | Type | Description |
125
- | ------------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
126
- | `checkedValues` | `Record<string, string[]>` | Map-like object of checked values, keyed by group name. |
127
- | `onCheckedValueChange` | `(e: Event, checkedValues: Record<string, string[]>) => void` | Callback fired when checked values change. |
128
- | `hasCheckmarks` | `boolean` | States that menu items can contain selectable items and reserve slots for item alignment. |
129
- | `hasIcons` | `boolean` | States that menu items can contain icons and reserve slots for item alignment. |
130
- | `openingDelay` | `number` | The delay in milliseconds before opening a submenu on hover. Default is 0. |
131
- | `open` | `boolean` | Controls the open state of the menu. |
132
- | `onOpenChange` | `(e: Event, open: boolean) => void` | Callback fired when the open state of the menu changes. |
133
- | `openOnHover` | `boolean` | If true, the menu will open when the trigger is hovered. |
134
- | `persistOnItemActivation` | `boolean` | If true, the menu will not close when a menu item is activated. |
135
- | `positionConfig` | `Partial<ComputePositionConfig>` | Configuration for the Floating UI positioning. It will be passed down to MenuPopover. |
124
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
125
+ <!-- props:MenuProps -->
126
+
127
+ | Name | Type | Default | Description |
128
+ | ------------------------- | ------------------------------------------------------------- | ------- | -------------------------------------------------------------------------- |
129
+ | `positionConfig` | `ComputePositionConfig` | | The position configuration handed over to floating-ui. |
130
+ | `hasIcons` | `boolean` | | Reserves the room every item needs for an icon, so the labels line up. |
131
+ | `hasCheckmarks` | `boolean` | | Reserves the room every item needs for a checkmark, so the labels line up. |
132
+ | `open` | `boolean` | | Controls the open state of the menu. |
133
+ | `onOpenChange` | `(e: Event, open: boolean) => void` | | Called whenever the menu opens or closes. |
134
+ | `checkedValues` | `Record<string, string[]>` | `{}` | The checked values of the menu, grouped by the `name` of each item. |
135
+ | `onCheckedValueChange` | `(e: Event, checkedValues: Record<string, string[]>) => void` | | Called whenever a checkbox or radio item changes. |
136
+ | `openOnHover` | `boolean` | `false` | Opens the menu on hover instead of on click. |
137
+ | `openingDelay` | `number` | `0` | How long to wait, in milliseconds, before opening the menu. |
138
+ | `persistOnItemActivation` | `boolean` | `false` | Keeps the menu open after an item is activated. |
139
+ | `children` | `Snippet` | | The parts of the menu: a trigger and a popover. |
140
+
141
+ <!-- /props:MenuProps -->
136
142
 
137
143
  ## Component Props (MenuTrigger)
138
144
 
139
- | Name | Type | Description |
140
- | ---------- | ------------------------------- | ------------------------------------------------------- |
141
- | `shape` | `rounded \| circular \| square` | The shape of the trigger element. Default is 'rounded'. |
142
- | `icon` | `Snippet \| Component` | An optional icon to display in the trigger element. |
143
- | `disabled` | `boolean` | If true, the trigger element will be disabled. |
145
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
146
+ <!-- props:MenuTriggerProps -->
147
+
148
+ | Name | Type | Default | Description |
149
+ | ---------- | ------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------- |
150
+ | `disabled` | `boolean` | | Disables the user interaction. |
151
+ | `shape` | `'circular'` &#124; `'rounded'` &#124; `'square'` | | The trigger can be rounded, circular, or square. |
152
+ | `icon` | `Snippet` &#124; `Component` | | An optional icon for the trigger. |
153
+ | `children` | `Snippet` | | A custom trigger. It receives the menu state and the props to spread on your own buttons. |
154
+
155
+ <!-- /props:MenuTriggerProps -->
144
156
 
145
157
  ## Component Props (MenuItem)
146
158
 
147
- | Name | Type | Description |
148
- | ------------------ | ---------------------- | -------------------------------------------------------------------- |
149
- | `icon` | `Snippet \| Component` | An optional icon to display in the menu item. |
150
- | `subText` | `string` | Optional subtext to display below the main content of the menu item. |
151
- | `secondaryContent` | `string` | Optional secondary content to display like a hint text. |
152
- | `href` | `string` | If provided, the menu item will render as an anchor element. |
153
- | `disabled` | `boolean` | If true, the menu item will be disabled. |
154
- | `onClick` | `(e: Event) => void` | Callback fired when the menu item is clicked. |
159
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
160
+ <!-- props:MenuItemProps -->
161
+
162
+ | Name | Type | Default | Description |
163
+ | ------------------ | ---------------------------- | ------- | ------------------------------------------------ |
164
+ | `icon` | `Snippet` &#124; `Component` | | The icon to display before the label. |
165
+ | `secondaryContent` | `string` | | Right aligned text, usually a keyboard shortcut. |
166
+ | `disabled` | `boolean` | | Disables the user interaction. |
167
+ | `subText` | `string` | | A second line of text below the label. |
168
+ | `href` | `string` | | Renders the item as a link pointing to this URL. |
169
+
170
+ <!-- /props:MenuItemProps -->
155
171
 
156
172
  ## Component Props (MenuItemCheckbox/Switch/Radio)
157
173
 
158
- | Name | Type | Description |
159
- | -------------------- | --------- | ------------------------------------------------------------------------------ |
160
- | All `MenuItem` props | | All props from the MenuItem component are compatible. |
161
- | `value` | `string` | The value of the checkbox item. This is required for the item to be checkable. |
162
- | `checked` | `boolean` | Controls the checked state of the checkbox item. (Bindable) |
163
- | `name` | `string` | The name of the checkbox item, used for grouping related checkboxes. |
174
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
175
+ <!-- props:MenuItemActionableProps -->
176
+
177
+ | Name | Type | Default | Description |
178
+ | -------------------------------------- | --------- | ------- | ------------------------------------------------------------------------------------------ |
179
+ | `checked` _bindable_ | `boolean` | | Whether the item is checked. |
180
+ | `value` | `string` | `id` | The value reported to the menu when the item is checked. Falls back to the id of the item. |
181
+ | `name` | `string` | `id` | The group of items this one belongs to. Falls back to the id of the item. |
182
+ | `MenuItemProps` without `href` | | | |
183
+ | `ComponentProps<typeof Button<'div'>>` | | | |
184
+
185
+ <!-- /props:MenuItemActionableProps -->
164
186
 
165
187
  ## Component Props (MenuGroup)
166
188
 
167
- | Name | Type | Description |
168
- | -------- | -------- | ------------------------------------------------ |
169
- | `header` | `string` | Optional header text to display above the group. |
189
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
190
+ <!-- props:MenuGroupProps -->
191
+
192
+ | Name | Type | Default | Description |
193
+ | ---------------- | ---------------- | ------- | --------------------------------------- |
194
+ | `ref` _bindable_ | `HTMLDivElement` | | The DOM reference of the group element. |
195
+ | `header` | `string` | | The label of the group. |
196
+ | `children` | `Snippet` | | The items of the group. |
197
+
198
+ <!-- /props:MenuGroupProps -->
@@ -31,7 +31,9 @@
31
31
 
32
32
  if (!context) throw new Error(`No MenuContext found for ${MENU_COMPONENT_NAME}.`);
33
33
 
34
- const { hasIcons, hasCheckmarks } = context.config;
34
+ const hasIcons = $derived(context.config.hasIcons);
35
+
36
+ const hasCheckmarks = $derived(context.config.hasCheckmarks);
35
37
 
36
38
  const { toggleCheckbox } = context.methods;
37
39
 
@@ -76,7 +78,7 @@
76
78
  <span class="label" aria-label="{secondaryContent}, Use {secondaryContent}">
77
79
  <CheckmarkFilled class="indicator" />
78
80
  {#if Icon}
79
- <RenderSoC SoC={Icon} class="menu-item-icon" args={[{ class: 'menu-item-icon' }]} />
81
+ <RenderSoC SoC={Icon} args={{ class: 'menu-item-icon' }} />
80
82
  {/if}
81
83
  {#if subText}
82
84
  <span class="sub-text">
@@ -31,7 +31,9 @@
31
31
 
32
32
  if (!context) throw new Error(`No MenuContext found for ${MENU_COMPONENT_NAME}.`);
33
33
 
34
- const { hasIcons, persistOnItemActivation } = context.config;
34
+ const hasIcons = $derived(context.config.hasIcons);
35
+
36
+ const persistOnItemActivation = $derived(context.config.persistOnItemActivation);
35
37
 
36
38
  const { toggleRadio, toggle } = context.methods;
37
39
 
@@ -80,7 +82,7 @@
80
82
  <span class="label" aria-label="{secondaryContent}, Use {secondaryContent}">
81
83
  <CheckmarkFilled class="indicator" />
82
84
  {#if Icon}
83
- <RenderSoC SoC={Icon} class="menu-item-icon" args={[{ class: 'menu-item-icon' }]} />
85
+ <RenderSoC SoC={Icon} args={{ class: 'menu-item-icon' }} />
84
86
  {/if}
85
87
  {#if subText}
86
88
  <span class="sub-text">