bits-ui 2.8.0 → 2.8.2

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 (99) hide show
  1. package/dist/bits/accordion/accordion.svelte.d.ts +6 -1
  2. package/dist/bits/accordion/accordion.svelte.js +15 -5
  3. package/dist/bits/alert-dialog/components/alert-dialog-content.svelte +6 -9
  4. package/dist/bits/aspect-ratio/aspect-ratio.svelte.d.ts +2 -1
  5. package/dist/bits/aspect-ratio/aspect-ratio.svelte.js +3 -1
  6. package/dist/bits/avatar/avatar.svelte.d.ts +4 -1
  7. package/dist/bits/avatar/avatar.svelte.js +9 -3
  8. package/dist/bits/calendar/calendar.svelte.d.ts +15 -1
  9. package/dist/bits/calendar/calendar.svelte.js +42 -14
  10. package/dist/bits/calendar/components/calendar-next-button.svelte +3 -1
  11. package/dist/bits/calendar/components/calendar-prev-button.svelte +3 -1
  12. package/dist/bits/checkbox/checkbox.svelte.d.ts +4 -1
  13. package/dist/bits/checkbox/checkbox.svelte.js +9 -3
  14. package/dist/bits/collapsible/collapsible.svelte.d.ts +4 -1
  15. package/dist/bits/collapsible/collapsible.svelte.js +9 -3
  16. package/dist/bits/command/command.svelte.d.ts +13 -1
  17. package/dist/bits/command/command.svelte.js +36 -12
  18. package/dist/bits/context-menu/components/context-menu-content.svelte +1 -1
  19. package/dist/bits/date-field/date-field.svelte.d.ts +8 -2
  20. package/dist/bits/date-field/date-field.svelte.js +18 -6
  21. package/dist/bits/date-range-field/date-range-field.svelte.d.ts +3 -1
  22. package/dist/bits/date-range-field/date-range-field.svelte.js +6 -2
  23. package/dist/bits/dialog/components/dialog-content.svelte +5 -7
  24. package/dist/bits/dialog/dialog.svelte.d.ts +9 -1
  25. package/dist/bits/dialog/dialog.svelte.js +33 -18
  26. package/dist/bits/dropdown-menu/components/dropdown-menu-content.svelte +3 -2
  27. package/dist/bits/label/label.svelte.d.ts +2 -1
  28. package/dist/bits/label/label.svelte.js +3 -1
  29. package/dist/bits/link-preview/link-preview.svelte.d.ts +3 -1
  30. package/dist/bits/link-preview/link-preview.svelte.js +6 -2
  31. package/dist/bits/menu/menu.svelte.d.ts +12 -1
  32. package/dist/bits/menu/menu.svelte.js +38 -26
  33. package/dist/bits/menubar/components/menubar-trigger.svelte +4 -3
  34. package/dist/bits/menubar/menubar.svelte.d.ts +4 -3
  35. package/dist/bits/menubar/menubar.svelte.js +9 -6
  36. package/dist/bits/meter/meter.svelte.d.ts +2 -1
  37. package/dist/bits/meter/meter.svelte.js +3 -1
  38. package/dist/bits/navigation-menu/components/navigation-menu-link.svelte +2 -1
  39. package/dist/bits/navigation-menu/components/navigation-menu-trigger.svelte +2 -1
  40. package/dist/bits/navigation-menu/navigation-menu.svelte.d.ts +14 -3
  41. package/dist/bits/navigation-menu/navigation-menu.svelte.js +33 -13
  42. package/dist/bits/pagination/pagination.svelte.d.ts +4 -1
  43. package/dist/bits/pagination/pagination.svelte.js +9 -3
  44. package/dist/bits/pin-input/pin-input.svelte.d.ts +4 -1
  45. package/dist/bits/pin-input/pin-input.svelte.js +8 -3
  46. package/dist/bits/popover/popover.svelte.d.ts +4 -1
  47. package/dist/bits/popover/popover.svelte.js +9 -3
  48. package/dist/bits/progress/progress.svelte.d.ts +2 -1
  49. package/dist/bits/progress/progress.svelte.js +3 -1
  50. package/dist/bits/radio-group/radio-group.svelte.d.ts +3 -1
  51. package/dist/bits/radio-group/radio-group.svelte.js +6 -2
  52. package/dist/bits/range-calendar/range-calendar.svelte.d.ts +4 -1
  53. package/dist/bits/range-calendar/range-calendar.svelte.js +9 -3
  54. package/dist/bits/rating-group/rating-group.svelte.d.ts +3 -1
  55. package/dist/bits/rating-group/rating-group.svelte.js +6 -2
  56. package/dist/bits/scroll-area/scroll-area.svelte.d.ts +8 -1
  57. package/dist/bits/scroll-area/scroll-area.svelte.js +20 -7
  58. package/dist/bits/select/select.svelte.d.ts +10 -1
  59. package/dist/bits/select/select.svelte.js +27 -9
  60. package/dist/bits/separator/separator.svelte.d.ts +2 -1
  61. package/dist/bits/separator/separator.svelte.js +3 -1
  62. package/dist/bits/slider/slider.svelte.d.ts +7 -1
  63. package/dist/bits/slider/slider.svelte.js +18 -6
  64. package/dist/bits/switch/switch.svelte.d.ts +3 -1
  65. package/dist/bits/switch/switch.svelte.js +6 -2
  66. package/dist/bits/tabs/tabs.svelte.d.ts +5 -1
  67. package/dist/bits/tabs/tabs.svelte.js +12 -4
  68. package/dist/bits/time-field/time-field.svelte.d.ts +7 -1
  69. package/dist/bits/time-field/time-field.svelte.js +18 -6
  70. package/dist/bits/time-range-field/time-range-field.svelte.d.ts +3 -1
  71. package/dist/bits/time-range-field/time-range-field.svelte.js +6 -2
  72. package/dist/bits/toggle/toggle.svelte.d.ts +2 -1
  73. package/dist/bits/toggle/toggle.svelte.js +3 -1
  74. package/dist/bits/toggle-group/toggle-group.svelte.d.ts +3 -1
  75. package/dist/bits/toggle-group/toggle-group.svelte.js +6 -2
  76. package/dist/bits/toolbar/toolbar.svelte.d.ts +6 -1
  77. package/dist/bits/toolbar/toolbar.svelte.js +15 -5
  78. package/dist/bits/tooltip/tooltip.svelte.d.ts +3 -1
  79. package/dist/bits/tooltip/tooltip.svelte.js +6 -2
  80. package/dist/bits/utilities/floating-layer/use-floating-layer.svelte.d.ts +9 -0
  81. package/dist/bits/utilities/floating-layer/use-floating-layer.svelte.js +6 -3
  82. package/dist/bits/utilities/focus-scope/focus-scope-manager.d.ts +12 -0
  83. package/dist/bits/utilities/focus-scope/focus-scope-manager.js +40 -0
  84. package/dist/bits/utilities/focus-scope/focus-scope.svelte +6 -8
  85. package/dist/bits/utilities/focus-scope/focus-scope.svelte.d.ts +1 -0
  86. package/dist/bits/utilities/focus-scope/focus-scope.svelte.js +204 -0
  87. package/dist/bits/utilities/focus-scope/types.d.ts +2 -6
  88. package/dist/bits/utilities/popper-layer/popper-layer-inner.svelte +2 -2
  89. package/dist/internal/focus.js +1 -1
  90. package/dist/internal/should-enable-focus-trap.d.ts +5 -0
  91. package/dist/internal/should-enable-focus-trap.js +5 -0
  92. package/dist/internal/types.d.ts +2 -1
  93. package/package.json +2 -2
  94. package/dist/bits/utilities/focus-scope/focus-scope-stack.svelte.d.ts +0 -14
  95. package/dist/bits/utilities/focus-scope/focus-scope-stack.svelte.js +0 -50
  96. package/dist/bits/utilities/focus-scope/use-focus-scope.svelte.d.ts +0 -49
  97. package/dist/bits/utilities/focus-scope/use-focus-scope.svelte.js +0 -218
  98. package/dist/internal/should-trap-focus.d.ts +0 -6
  99. package/dist/internal/should-trap-focus.js +0 -5
@@ -2,7 +2,6 @@ import { attachRef, box, } from "svelte-toolbelt";
2
2
  import { Context } from "runed";
3
3
  import { createBitsAttrs, getAriaExpanded, getDataOpenClosed } from "../../internal/attrs.js";
4
4
  import { kbd } from "../../internal/kbd.js";
5
- import { untrack } from "svelte";
6
5
  import { OpenChangeComplete } from "../../internal/open-change-complete.js";
7
6
  const dialogAttrs = createBitsAttrs({
8
7
  component: "dialog",
@@ -58,9 +57,14 @@ export class DialogTriggerState {
58
57
  }
59
58
  opts;
60
59
  root;
60
+ attachment;
61
61
  constructor(opts, root) {
62
62
  this.opts = opts;
63
63
  this.root = root;
64
+ this.attachment = attachRef(this.opts.ref, (v) => {
65
+ this.root.triggerNode = v;
66
+ this.root.triggerId = v?.id;
67
+ });
64
68
  this.onclick = this.onclick.bind(this);
65
69
  this.onkeydown = this.onkeydown.bind(this);
66
70
  }
@@ -89,10 +93,7 @@ export class DialogTriggerState {
89
93
  onclick: this.onclick,
90
94
  disabled: this.opts.disabled.current ? true : undefined,
91
95
  ...this.root.sharedProps,
92
- ...attachRef(this.opts.ref, (v) => untrack(() => {
93
- this.root.triggerNode = v;
94
- this.root.triggerId = v?.id;
95
- })),
96
+ ...this.attachment,
96
97
  }));
97
98
  }
98
99
  export class DialogCloseState {
@@ -101,9 +102,11 @@ export class DialogCloseState {
101
102
  }
102
103
  opts;
103
104
  root;
105
+ attachment;
104
106
  constructor(opts, root) {
105
107
  this.opts = opts;
106
108
  this.root = root;
109
+ this.attachment = attachRef(this.opts.ref);
107
110
  this.onclick = this.onclick.bind(this);
108
111
  this.onkeydown = this.onkeydown.bind(this);
109
112
  }
@@ -130,7 +133,7 @@ export class DialogCloseState {
130
133
  disabled: this.opts.disabled.current ? true : undefined,
131
134
  tabindex: 0,
132
135
  ...this.root.sharedProps,
133
- ...attachRef(this.opts.ref),
136
+ ...this.attachment,
134
137
  }));
135
138
  }
136
139
  export class DialogActionState {
@@ -139,15 +142,17 @@ export class DialogActionState {
139
142
  }
140
143
  opts;
141
144
  root;
145
+ attachment;
142
146
  constructor(opts, root) {
143
147
  this.opts = opts;
144
148
  this.root = root;
149
+ this.attachment = attachRef(this.opts.ref);
145
150
  }
146
151
  props = $derived.by(() => ({
147
152
  id: this.opts.id.current,
148
153
  [this.root.getBitsAttr("action")]: "",
149
154
  ...this.root.sharedProps,
150
- ...attachRef(this.opts.ref),
155
+ ...this.attachment,
151
156
  }));
152
157
  }
153
158
  export class DialogTitleState {
@@ -156,9 +161,11 @@ export class DialogTitleState {
156
161
  }
157
162
  opts;
158
163
  root;
164
+ attachment;
159
165
  constructor(opts, root) {
160
166
  this.opts = opts;
161
167
  this.root = root;
168
+ this.attachment = attachRef(this.opts.ref, (v) => (this.root.titleId = v?.id));
162
169
  }
163
170
  props = $derived.by(() => ({
164
171
  id: this.opts.id.current,
@@ -166,7 +173,7 @@ export class DialogTitleState {
166
173
  "aria-level": this.opts.level.current,
167
174
  [this.root.getBitsAttr("title")]: "",
168
175
  ...this.root.sharedProps,
169
- ...attachRef(this.opts.ref, (v) => (this.root.titleId = v?.id)),
176
+ ...this.attachment,
170
177
  }));
171
178
  }
172
179
  export class DialogDescriptionState {
@@ -175,18 +182,20 @@ export class DialogDescriptionState {
175
182
  }
176
183
  opts;
177
184
  root;
185
+ attachment;
178
186
  constructor(opts, root) {
179
187
  this.opts = opts;
180
188
  this.root = root;
189
+ this.attachment = attachRef(this.opts.ref, (v) => {
190
+ this.root.descriptionNode = v;
191
+ this.root.descriptionId = v?.id;
192
+ });
181
193
  }
182
194
  props = $derived.by(() => ({
183
195
  id: this.opts.id.current,
184
196
  [this.root.getBitsAttr("description")]: "",
185
197
  ...this.root.sharedProps,
186
- ...attachRef(this.opts.ref, (v) => {
187
- this.root.descriptionNode = v;
188
- this.root.descriptionId = v?.id;
189
- }),
198
+ ...this.attachment,
190
199
  }));
191
200
  }
192
201
  export class DialogContentState {
@@ -195,9 +204,14 @@ export class DialogContentState {
195
204
  }
196
205
  opts;
197
206
  root;
207
+ attachment;
198
208
  constructor(opts, root) {
199
209
  this.opts = opts;
200
210
  this.root = root;
211
+ this.attachment = attachRef(this.opts.ref, (v) => {
212
+ this.root.contentNode = v;
213
+ this.root.contentId = v?.id;
214
+ });
201
215
  }
202
216
  snippetProps = $derived.by(() => ({ open: this.root.opts.open.current }));
203
217
  props = $derived.by(() => ({
@@ -213,10 +227,7 @@ export class DialogContentState {
213
227
  },
214
228
  tabindex: this.root.opts.variant.current === "alert-dialog" ? -1 : undefined,
215
229
  ...this.root.sharedProps,
216
- ...attachRef(this.opts.ref, (v) => {
217
- this.root.contentNode = v;
218
- this.root.contentId = v?.id;
219
- }),
230
+ ...this.attachment,
220
231
  }));
221
232
  }
222
233
  export class DialogOverlayState {
@@ -225,9 +236,11 @@ export class DialogOverlayState {
225
236
  }
226
237
  opts;
227
238
  root;
239
+ attachment;
228
240
  constructor(opts, root) {
229
241
  this.opts = opts;
230
242
  this.root = root;
243
+ this.attachment = attachRef(this.opts.ref);
231
244
  }
232
245
  snippetProps = $derived.by(() => ({ open: this.root.opts.open.current }));
233
246
  props = $derived.by(() => ({
@@ -237,7 +250,7 @@ export class DialogOverlayState {
237
250
  pointerEvents: "auto",
238
251
  },
239
252
  ...this.root.sharedProps,
240
- ...attachRef(this.opts.ref),
253
+ ...this.attachment,
241
254
  }));
242
255
  }
243
256
  export class AlertDialogCancelState {
@@ -246,9 +259,11 @@ export class AlertDialogCancelState {
246
259
  }
247
260
  opts;
248
261
  root;
262
+ attachment;
249
263
  constructor(opts, root) {
250
264
  this.opts = opts;
251
265
  this.root = root;
266
+ this.attachment = attachRef(this.opts.ref, (v) => (this.root.cancelNode = v));
252
267
  this.onclick = this.onclick.bind(this);
253
268
  this.onkeydown = this.onkeydown.bind(this);
254
269
  }
@@ -274,6 +289,6 @@ export class AlertDialogCancelState {
274
289
  onkeydown: this.onkeydown,
275
290
  tabindex: 0,
276
291
  ...this.root.sharedProps,
277
- ...attachRef(this.opts.ref, (v) => (this.root.cancelNode = v)),
292
+ ...this.attachment,
278
293
  }));
279
294
  }
@@ -20,6 +20,7 @@
20
20
  onEscapeKeydown = noop,
21
21
  onCloseAutoFocus = noop,
22
22
  forceMount = false,
23
+ trapFocus = false,
23
24
  ...restProps
24
25
  }: DropdownMenuContentProps = $props();
25
26
 
@@ -57,7 +58,7 @@
57
58
  enabled={contentState.parentMenu.opts.open.current}
58
59
  onInteractOutside={handleInteractOutside}
59
60
  onEscapeKeydown={handleEscapeKeydown}
60
- trapFocus
61
+ {trapFocus}
61
62
  {loop}
62
63
  forceMount={true}
63
64
  {id}
@@ -85,7 +86,7 @@
85
86
  open={contentState.parentMenu.opts.open.current}
86
87
  onInteractOutside={handleInteractOutside}
87
88
  onEscapeKeydown={handleEscapeKeydown}
88
- trapFocus
89
+ {trapFocus}
89
90
  {loop}
90
91
  forceMount={false}
91
92
  {id}
@@ -1,9 +1,10 @@
1
- import type { BitsMouseEvent, WithRefOpts } from "../../internal/types.js";
1
+ import type { BitsMouseEvent, RefAttachment, WithRefOpts } from "../../internal/types.js";
2
2
  interface LabelRootStateOpts extends WithRefOpts {
3
3
  }
4
4
  export declare class LabelRootState {
5
5
  static create(opts: LabelRootStateOpts): LabelRootState;
6
6
  readonly opts: LabelRootStateOpts;
7
+ readonly attachment: RefAttachment;
7
8
  constructor(opts: LabelRootStateOpts);
8
9
  onmousedown(e: BitsMouseEvent): void;
9
10
  readonly props: {
@@ -9,8 +9,10 @@ export class LabelRootState {
9
9
  return new LabelRootState(opts);
10
10
  }
11
11
  opts;
12
+ attachment;
12
13
  constructor(opts) {
13
14
  this.opts = opts;
15
+ this.attachment = attachRef(this.opts.ref);
14
16
  this.onmousedown = this.onmousedown.bind(this);
15
17
  }
16
18
  onmousedown(e) {
@@ -21,6 +23,6 @@ export class LabelRootState {
21
23
  id: this.opts.id.current,
22
24
  [labelAttrs.root]: "",
23
25
  onmousedown: this.onmousedown,
24
- ...attachRef(this.opts.ref),
26
+ ...this.attachment,
25
27
  }));
26
28
  }
@@ -1,5 +1,5 @@
1
1
  import { DOMContext, type ReadableBoxedValues, type WritableBoxedValues } from "svelte-toolbelt";
2
- import type { BitsFocusEvent, BitsPointerEvent, OnChangeFn, WithRefOpts } from "../../internal/types.js";
2
+ import type { BitsFocusEvent, BitsPointerEvent, OnChangeFn, RefAttachment, WithRefOpts } from "../../internal/types.js";
3
3
  interface LinkPreviewRootStateOpts extends WritableBoxedValues<{
4
4
  open: boolean;
5
5
  }>, ReadableBoxedValues<{
@@ -32,6 +32,7 @@ export declare class LinkPreviewTriggerState {
32
32
  static create(opts: LinkPreviewTriggerStateOpts): LinkPreviewTriggerState;
33
33
  readonly opts: LinkPreviewTriggerStateOpts;
34
34
  readonly root: LinkPreviewRootState;
35
+ readonly attachment: RefAttachment;
35
36
  constructor(opts: LinkPreviewTriggerStateOpts, root: LinkPreviewRootState);
36
37
  onpointerenter(e: BitsPointerEvent): void;
37
38
  onpointerleave(e: BitsPointerEvent): void;
@@ -59,6 +60,7 @@ export declare class LinkPreviewContentState {
59
60
  static create(opts: LinkPreviewContentStateOpts): LinkPreviewContentState;
60
61
  readonly opts: LinkPreviewContentStateOpts;
61
62
  readonly root: LinkPreviewRootState;
63
+ readonly attachment: RefAttachment;
62
64
  constructor(opts: LinkPreviewContentStateOpts, root: LinkPreviewRootState);
63
65
  onpointerdown(e: BitsPointerEvent): void;
64
66
  onpointerenter(e: BitsPointerEvent): void;
@@ -107,9 +107,11 @@ export class LinkPreviewTriggerState {
107
107
  }
108
108
  opts;
109
109
  root;
110
+ attachment;
110
111
  constructor(opts, root) {
111
112
  this.opts = opts;
112
113
  this.root = root;
114
+ this.attachment = attachRef(this.opts.ref, (v) => (this.root.triggerNode = v));
113
115
  this.root.domContext = new DOMContext(opts.ref);
114
116
  this.onpointerenter = this.onpointerenter.bind(this);
115
117
  this.onpointerleave = this.onpointerleave.bind(this);
@@ -148,7 +150,7 @@ export class LinkPreviewTriggerState {
148
150
  onfocus: this.onfocus,
149
151
  onblur: this.onblur,
150
152
  onpointerleave: this.onpointerleave,
151
- ...attachRef(this.opts.ref, (v) => (this.root.triggerNode = v)),
153
+ ...this.attachment,
152
154
  }));
153
155
  }
154
156
  export class LinkPreviewContentState {
@@ -157,9 +159,11 @@ export class LinkPreviewContentState {
157
159
  }
158
160
  opts;
159
161
  root;
162
+ attachment;
160
163
  constructor(opts, root) {
161
164
  this.opts = opts;
162
165
  this.root = root;
166
+ this.attachment = attachRef(this.opts.ref, (v) => (this.root.contentNode = v));
163
167
  this.root.domContext = new DOMContext(opts.ref);
164
168
  this.onpointerdown = this.onpointerdown.bind(this);
165
169
  this.onpointerenter = this.onpointerenter.bind(this);
@@ -221,7 +225,7 @@ export class LinkPreviewContentState {
221
225
  onpointerdown: this.onpointerdown,
222
226
  onpointerenter: this.onpointerenter,
223
227
  onfocusout: this.onfocusout,
224
- ...attachRef(this.opts.ref, (v) => (this.root.contentNode = v)),
228
+ ...this.attachment,
225
229
  }));
226
230
  popperProps = {
227
231
  onInteractOutside: this.onInteractOutside,
@@ -1,7 +1,7 @@
1
1
  import { DOMContext, type ReadableBoxedValues, type WritableBoxedValues } from "svelte-toolbelt";
2
2
  import { Context } from "runed";
3
3
  import { CustomEventDispatcher } from "../../internal/events.js";
4
- import type { AnyFn, BitsFocusEvent, BitsKeyboardEvent, BitsMouseEvent, BitsPointerEvent, OnChangeFn, WithRefOpts } from "../../internal/types.js";
4
+ import type { AnyFn, BitsFocusEvent, BitsKeyboardEvent, BitsMouseEvent, BitsPointerEvent, OnChangeFn, RefAttachment, WithRefOpts } from "../../internal/types.js";
5
5
  import type { Direction } from "../../shared/index.js";
6
6
  import { IsUsingKeyboard } from "../../index.js";
7
7
  import type { KeyboardEventHandler, PointerEventHandler } from "svelte/elements";
@@ -58,6 +58,7 @@ export declare class MenuContentState {
58
58
  readonly parentMenu: MenuMenuState;
59
59
  readonly rovingFocusGroup: RovingFocusGroup;
60
60
  readonly domContext: DOMContext;
61
+ readonly attachment: RefAttachment;
61
62
  search: string;
62
63
  mounted: boolean;
63
64
  constructor(opts: MenuContentStateOpts, parentMenu: MenuMenuState);
@@ -99,6 +100,7 @@ declare class MenuItemSharedState {
99
100
  #private;
100
101
  readonly opts: MenuItemSharedStateOpts;
101
102
  readonly content: MenuContentState;
103
+ readonly attachment: RefAttachment;
102
104
  constructor(opts: MenuItemSharedStateOpts, content: MenuContentState);
103
105
  onpointermove(e: BitsPointerEvent): void;
104
106
  onpointerleave(e: BitsPointerEvent): void;
@@ -163,6 +165,7 @@ export declare class MenuSubTriggerState {
163
165
  readonly item: MenuItemSharedState;
164
166
  readonly content: MenuContentState;
165
167
  readonly submenu: MenuMenuState;
168
+ readonly attachment: RefAttachment;
166
169
  constructor(opts: MenuSubTriggerStateOpts, item: MenuItemSharedState, content: MenuContentState, submenu: MenuMenuState);
167
170
  onpointermove(e: BitsPointerEvent): void;
168
171
  onpointerleave(e: BitsPointerEvent): void;
@@ -236,6 +239,7 @@ export declare class MenuGroupState {
236
239
  static create(opts: MenuGroupStateOpts): MenuGroupState | MenuRadioGroupState;
237
240
  readonly opts: MenuGroupStateOpts;
238
241
  readonly root: MenuRootState;
242
+ readonly attachment: RefAttachment;
239
243
  groupHeadingId: string | undefined;
240
244
  constructor(opts: MenuGroupStateOpts, root: MenuRootState);
241
245
  readonly props: {
@@ -250,6 +254,7 @@ export declare class MenuGroupHeadingState {
250
254
  static create(opts: MenuGroupHeadingStateOpts): MenuGroupHeadingState;
251
255
  readonly opts: MenuGroupHeadingStateOpts;
252
256
  readonly group: MenuGroupState | MenuRadioGroupState | MenuCheckboxGroupState;
257
+ readonly attachment: RefAttachment;
253
258
  constructor(opts: MenuGroupHeadingStateOpts, group: MenuGroupState | MenuRadioGroupState | MenuCheckboxGroupState);
254
259
  readonly props: {
255
260
  readonly id: string;
@@ -262,6 +267,7 @@ export declare class MenuSeparatorState {
262
267
  static create(opts: MenuSeparatorStateOpts): MenuSeparatorState;
263
268
  readonly opts: MenuSeparatorStateOpts;
264
269
  readonly root: MenuRootState;
270
+ readonly attachment: RefAttachment;
265
271
  constructor(opts: MenuSeparatorStateOpts, root: MenuRootState);
266
272
  readonly props: {
267
273
  readonly id: string;
@@ -284,6 +290,7 @@ export declare class MenuRadioGroupState {
284
290
  static create(opts: MenuRadioGroupStateOpts): MenuGroupState | MenuRadioGroupState;
285
291
  readonly opts: MenuRadioGroupStateOpts;
286
292
  readonly content: MenuContentState;
293
+ readonly attachment: RefAttachment;
287
294
  groupHeadingId: string | null;
288
295
  root: MenuRootState;
289
296
  constructor(opts: MenuRadioGroupStateOpts, content: MenuContentState);
@@ -304,6 +311,7 @@ export declare class MenuRadioItemState {
304
311
  readonly opts: MenuRadioItemStateOpts;
305
312
  readonly item: MenuItemState;
306
313
  readonly group: MenuRadioGroupState;
314
+ readonly attachment: RefAttachment;
307
315
  readonly isChecked: boolean;
308
316
  constructor(opts: MenuRadioItemStateOpts, item: MenuItemState, group: MenuRadioGroupState);
309
317
  selectValue(): void;
@@ -336,6 +344,7 @@ export declare class DropdownMenuTriggerState {
336
344
  static create(opts: DropdownMenuTriggerStateOpts): DropdownMenuTriggerState;
337
345
  readonly opts: DropdownMenuTriggerStateOpts;
338
346
  readonly parentMenu: MenuMenuState;
347
+ readonly attachment: RefAttachment;
339
348
  constructor(opts: DropdownMenuTriggerStateOpts, parentMenu: MenuMenuState);
340
349
  onpointerdown: PointerEventHandler<HTMLElement>;
341
350
  onpointerup: PointerEventHandler<HTMLElement>;
@@ -362,6 +371,7 @@ export declare class ContextMenuTriggerState {
362
371
  static create(opts: ContextMenuTriggerStateOpts): ContextMenuTriggerState;
363
372
  readonly opts: ContextMenuTriggerStateOpts;
364
373
  readonly parentMenu: MenuMenuState;
374
+ readonly attachment: RefAttachment;
365
375
  virtualElement: import("svelte-toolbelt").WritableBox<{
366
376
  getBoundingClientRect: () => DOMRect;
367
377
  }>;
@@ -396,6 +406,7 @@ export declare class MenuCheckboxGroupState {
396
406
  readonly opts: MenuCheckboxGroupStateOpts;
397
407
  readonly content: MenuContentState;
398
408
  readonly root: MenuRootState;
409
+ readonly attachment: RefAttachment;
399
410
  groupHeadingId: string | null;
400
411
  constructor(opts: MenuCheckboxGroupStateOpts, content: MenuContentState);
401
412
  addValue(checkboxValue: string | undefined): void;
@@ -8,9 +8,7 @@ import { kbd } from "../../internal/kbd.js";
8
8
  import { createBitsAttrs, getAriaChecked, getAriaDisabled, getAriaExpanded, getAriaOrientation, getDataDisabled, getDataOpenClosed, } from "../../internal/attrs.js";
9
9
  import { IsUsingKeyboard } from "../../index.js";
10
10
  import { getTabbableFrom } from "../../internal/tabbable.js";
11
- import { FocusScopeContext } from "../utilities/focus-scope/use-focus-scope.svelte.js";
12
11
  import { isTabbable } from "tabbable";
13
- import { untrack } from "svelte";
14
12
  import { DOMTypeahead } from "../../internal/dom-typeahead.svelte.js";
15
13
  import { RovingFocusGroup } from "../../internal/roving-focus-group.js";
16
14
  import { GraceArea } from "../../internal/grace-area.svelte.js";
@@ -47,11 +45,6 @@ export const menuAttrs = createBitsAttrs({
47
45
  export class MenuRootState {
48
46
  static create(opts) {
49
47
  const root = new MenuRootState(opts);
50
- FocusScopeContext.set({
51
- get ignoreCloseAutoFocus() {
52
- return root.ignoreCloseAutoFocus;
53
- },
54
- });
55
48
  return MenuRootContext.set(root);
56
49
  }
57
50
  opts;
@@ -112,6 +105,7 @@ export class MenuContentState {
112
105
  parentMenu;
113
106
  rovingFocusGroup;
114
107
  domContext;
108
+ attachment;
115
109
  search = $state("");
116
110
  #timer = 0;
117
111
  #handleTypeaheadSearch;
@@ -121,6 +115,11 @@ export class MenuContentState {
121
115
  this.opts = opts;
122
116
  this.parentMenu = parentMenu;
123
117
  this.domContext = new DOMContext(opts.ref);
118
+ this.attachment = attachRef(this.opts.ref, (v) => {
119
+ if (this.parentMenu.contentNode !== v) {
120
+ this.parentMenu.contentNode = v;
121
+ }
122
+ });
124
123
  parentMenu.contentId = opts.id;
125
124
  this.#isSub = opts.isSub ?? false;
126
125
  this.onkeydown = this.onkeydown.bind(this);
@@ -196,9 +195,8 @@ export class MenuContentState {
196
195
  rootMenu = rootMenu.parentMenu;
197
196
  }
198
197
  // if for some unforeseen reason the root menu has no trigger, we bail
199
- if (!rootMenu.triggerNode) {
198
+ if (!rootMenu.triggerNode)
200
199
  return;
201
- }
202
200
  // cancel default tab behavior
203
201
  e.preventDefault();
204
202
  // find the next/previous tabbable
@@ -327,13 +325,7 @@ export class MenuContentState {
327
325
  style: {
328
326
  pointerEvents: "auto",
329
327
  },
330
- ...attachRef(this.opts.ref, (v) => {
331
- untrack(() => {
332
- if (this.parentMenu.contentNode !== v) {
333
- this.parentMenu.contentNode = v;
334
- }
335
- });
336
- }),
328
+ ...this.attachment,
337
329
  }));
338
330
  popperProps = {
339
331
  onCloseAutoFocus: (e) => this.onCloseAutoFocus(e),
@@ -342,10 +334,12 @@ export class MenuContentState {
342
334
  class MenuItemSharedState {
343
335
  opts;
344
336
  content;
337
+ attachment;
345
338
  #isFocused = $state(false);
346
339
  constructor(opts, content) {
347
340
  this.opts = opts;
348
341
  this.content = content;
342
+ this.attachment = attachRef(this.opts.ref);
349
343
  this.onpointermove = this.onpointermove.bind(this);
350
344
  this.onpointerleave = this.onpointerleave.bind(this);
351
345
  this.onfocus = this.onfocus.bind(this);
@@ -403,7 +397,7 @@ class MenuItemSharedState {
403
397
  onpointerleave: this.onpointerleave,
404
398
  onfocus: this.onfocus,
405
399
  onblur: this.onblur,
406
- ...attachRef(this.opts.ref),
400
+ ...this.attachment,
407
401
  }));
408
402
  }
409
403
  export class MenuItemState {
@@ -491,12 +485,14 @@ export class MenuSubTriggerState {
491
485
  item;
492
486
  content;
493
487
  submenu;
488
+ attachment;
494
489
  #openTimer = null;
495
490
  constructor(opts, item, content, submenu) {
496
491
  this.opts = opts;
497
492
  this.item = item;
498
493
  this.content = content;
499
494
  this.submenu = submenu;
495
+ this.attachment = attachRef(this.opts.ref, (v) => (this.submenu.triggerNode = v));
500
496
  this.onpointerleave = this.onpointerleave.bind(this);
501
497
  this.onpointermove = this.onpointermove.bind(this);
502
498
  this.onkeydown = this.onkeydown.bind(this);
@@ -576,7 +572,7 @@ export class MenuSubTriggerState {
576
572
  onpointermove: this.onpointermove,
577
573
  onpointerleave: this.onpointerleave,
578
574
  onkeydown: this.onkeydown,
579
- ...attachRef(this.opts.ref, (v) => (this.submenu.triggerNode = v)),
575
+ ...this.attachment,
580
576
  }, this.item.props));
581
577
  }
582
578
  export class MenuCheckboxItemState {
@@ -634,17 +630,19 @@ export class MenuGroupState {
634
630
  }
635
631
  opts;
636
632
  root;
633
+ attachment;
637
634
  groupHeadingId = $state(undefined);
638
635
  constructor(opts, root) {
639
636
  this.opts = opts;
640
637
  this.root = root;
638
+ this.attachment = attachRef(this.opts.ref);
641
639
  }
642
640
  props = $derived.by(() => ({
643
641
  id: this.opts.id.current,
644
642
  role: "group",
645
643
  "aria-labelledby": this.groupHeadingId,
646
644
  [this.root.getBitsAttr("group")]: "",
647
- ...attachRef(this.opts.ref),
645
+ ...this.attachment,
648
646
  }));
649
647
  }
650
648
  export class MenuGroupHeadingState {
@@ -660,15 +658,17 @@ export class MenuGroupHeadingState {
660
658
  }
661
659
  opts;
662
660
  group;
661
+ attachment;
663
662
  constructor(opts, group) {
664
663
  this.opts = opts;
665
664
  this.group = group;
665
+ this.attachment = attachRef(this.opts.ref, (v) => (this.group.groupHeadingId = v?.id));
666
666
  }
667
667
  props = $derived.by(() => ({
668
668
  id: this.opts.id.current,
669
669
  role: "group",
670
670
  [this.group.root.getBitsAttr("group-heading")]: "",
671
- ...attachRef(this.opts.ref, (v) => (this.group.groupHeadingId = v?.id)),
671
+ ...this.attachment,
672
672
  }));
673
673
  }
674
674
  export class MenuSeparatorState {
@@ -677,15 +677,17 @@ export class MenuSeparatorState {
677
677
  }
678
678
  opts;
679
679
  root;
680
+ attachment;
680
681
  constructor(opts, root) {
681
682
  this.opts = opts;
682
683
  this.root = root;
684
+ this.attachment = attachRef(this.opts.ref);
683
685
  }
684
686
  props = $derived.by(() => ({
685
687
  id: this.opts.id.current,
686
688
  role: "group",
687
689
  [this.root.getBitsAttr("separator")]: "",
688
- ...attachRef(this.opts.ref),
690
+ ...this.attachment,
689
691
  }));
690
692
  }
691
693
  export class MenuArrowState {
@@ -706,12 +708,14 @@ export class MenuRadioGroupState {
706
708
  }
707
709
  opts;
708
710
  content;
711
+ attachment;
709
712
  groupHeadingId = $state(null);
710
713
  root;
711
714
  constructor(opts, content) {
712
715
  this.opts = opts;
713
716
  this.content = content;
714
717
  this.root = content.parentMenu.root;
718
+ this.attachment = attachRef(this.opts.ref);
715
719
  }
716
720
  setValue(v) {
717
721
  this.opts.value.current = v;
@@ -721,7 +725,7 @@ export class MenuRadioGroupState {
721
725
  [this.root.getBitsAttr("radio-group")]: "",
722
726
  role: "group",
723
727
  "aria-labelledby": this.groupHeadingId,
724
- ...attachRef(this.opts.ref),
728
+ ...this.attachment,
725
729
  }));
726
730
  }
727
731
  export class MenuRadioItemState {
@@ -734,11 +738,13 @@ export class MenuRadioItemState {
734
738
  opts;
735
739
  item;
736
740
  group;
741
+ attachment;
737
742
  isChecked = $derived.by(() => this.group.opts.value.current === this.opts.value.current);
738
743
  constructor(opts, item, group) {
739
744
  this.opts = opts;
740
745
  this.item = item;
741
746
  this.group = group;
747
+ this.attachment = attachRef(this.opts.ref);
742
748
  }
743
749
  selectValue() {
744
750
  this.group.setValue(this.opts.value.current);
@@ -749,7 +755,7 @@ export class MenuRadioItemState {
749
755
  role: "menuitemradio",
750
756
  "aria-checked": getAriaChecked(this.isChecked, false),
751
757
  "data-state": getCheckedState(this.isChecked),
752
- ...attachRef(this.opts.ref),
758
+ ...this.attachment,
753
759
  }));
754
760
  }
755
761
  export class DropdownMenuTriggerState {
@@ -758,9 +764,11 @@ export class DropdownMenuTriggerState {
758
764
  }
759
765
  opts;
760
766
  parentMenu;
767
+ attachment;
761
768
  constructor(opts, parentMenu) {
762
769
  this.opts = opts;
763
770
  this.parentMenu = parentMenu;
771
+ this.attachment = attachRef(this.opts.ref, (v) => (this.parentMenu.triggerNode = v));
764
772
  }
765
773
  onpointerdown = (e) => {
766
774
  if (this.opts.disabled.current)
@@ -814,7 +822,7 @@ export class DropdownMenuTriggerState {
814
822
  onpointerdown: this.onpointerdown,
815
823
  onpointerup: this.onpointerup,
816
824
  onkeydown: this.onkeydown,
817
- ...attachRef(this.opts.ref, (v) => (this.parentMenu.triggerNode = v)),
825
+ ...this.attachment,
818
826
  }));
819
827
  }
820
828
  export class ContextMenuTriggerState {
@@ -823,6 +831,7 @@ export class ContextMenuTriggerState {
823
831
  }
824
832
  opts;
825
833
  parentMenu;
834
+ attachment;
826
835
  #point = $state({ x: 0, y: 0 });
827
836
  virtualElement = box({
828
837
  getBoundingClientRect: () => DOMRect.fromRect({ width: 0, height: 0, ...this.#point }),
@@ -831,6 +840,7 @@ export class ContextMenuTriggerState {
831
840
  constructor(opts, parentMenu) {
832
841
  this.opts = opts;
833
842
  this.parentMenu = parentMenu;
843
+ this.attachment = attachRef(this.opts.ref, (v) => (this.parentMenu.triggerNode = v));
834
844
  this.oncontextmenu = this.oncontextmenu.bind(this);
835
845
  this.onpointerdown = this.onpointerdown.bind(this);
836
846
  this.onpointermove = this.onpointermove.bind(this);
@@ -899,7 +909,7 @@ export class ContextMenuTriggerState {
899
909
  onpointercancel: this.onpointercancel,
900
910
  onpointerup: this.onpointerup,
901
911
  oncontextmenu: this.oncontextmenu,
902
- ...attachRef(this.opts.ref, (v) => (this.parentMenu.triggerNode = v)),
912
+ ...this.attachment,
903
913
  }));
904
914
  }
905
915
  export class MenuCheckboxGroupState {
@@ -909,11 +919,13 @@ export class MenuCheckboxGroupState {
909
919
  opts;
910
920
  content;
911
921
  root;
922
+ attachment;
912
923
  groupHeadingId = $state(null);
913
924
  constructor(opts, content) {
914
925
  this.opts = opts;
915
926
  this.content = content;
916
927
  this.root = content.parentMenu.root;
928
+ this.attachment = attachRef(this.opts.ref);
917
929
  }
918
930
  addValue(checkboxValue) {
919
931
  if (!checkboxValue)
@@ -939,7 +951,7 @@ export class MenuCheckboxGroupState {
939
951
  [this.root.getBitsAttr("checkbox-group")]: "",
940
952
  role: "group",
941
953
  "aria-labelledby": this.groupHeadingId,
942
- ...attachRef(this.opts.ref),
954
+ ...this.attachment,
943
955
  }));
944
956
  }
945
957
  export class MenuSubmenuState {