bits-ui 2.16.3 → 2.16.4
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.
|
@@ -183,6 +183,10 @@ export class MenuContentState {
|
|
|
183
183
|
this.opts.onCloseAutoFocus.current?.(e);
|
|
184
184
|
if (e.defaultPrevented || this.#isSub)
|
|
185
185
|
return;
|
|
186
|
+
if (this.parentMenu.root.ignoreCloseAutoFocus) {
|
|
187
|
+
e.preventDefault();
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
186
190
|
if (this.parentMenu.triggerNode && isTabbable(this.parentMenu.triggerNode)) {
|
|
187
191
|
e.preventDefault();
|
|
188
192
|
this.parentMenu.triggerNode.focus();
|
|
@@ -306,7 +310,17 @@ export class MenuContentState {
|
|
|
306
310
|
}
|
|
307
311
|
if (e.target.closest(`#${triggerId}`)) {
|
|
308
312
|
e.preventDefault();
|
|
313
|
+
return;
|
|
309
314
|
}
|
|
315
|
+
/**
|
|
316
|
+
* when the menu closes due to an outside pointer interaction (for example,
|
|
317
|
+
* clicking another dropdown trigger), avoid focusing this menu's trigger
|
|
318
|
+
* to prevent stealing focus from the new interaction target.
|
|
319
|
+
*/
|
|
320
|
+
this.parentMenu.root.ignoreCloseAutoFocus = true;
|
|
321
|
+
afterTick(() => {
|
|
322
|
+
this.parentMenu.root.ignoreCloseAutoFocus = false;
|
|
323
|
+
});
|
|
310
324
|
}
|
|
311
325
|
get shouldRender() {
|
|
312
326
|
return this.parentMenu.contentPresence.shouldRender;
|
|
@@ -52,6 +52,11 @@
|
|
|
52
52
|
enabled: boolean;
|
|
53
53
|
contentPointerEvents?: "auto" | "none";
|
|
54
54
|
} = $props();
|
|
55
|
+
|
|
56
|
+
const resolvedPreventScroll = $derived(preventScroll ?? true);
|
|
57
|
+
const effectiveStrategy = $derived(
|
|
58
|
+
strategy ?? (resolvedPreventScroll ? "fixed" : "absolute")
|
|
59
|
+
);
|
|
55
60
|
</script>
|
|
56
61
|
|
|
57
62
|
<PopperContent
|
|
@@ -68,7 +73,7 @@
|
|
|
68
73
|
{sticky}
|
|
69
74
|
{hideWhenDetached}
|
|
70
75
|
{updatePositionStrategy}
|
|
71
|
-
{
|
|
76
|
+
strategy={effectiveStrategy}
|
|
72
77
|
{dir}
|
|
73
78
|
{wrapperId}
|
|
74
79
|
{style}
|
|
@@ -79,9 +84,9 @@
|
|
|
79
84
|
>
|
|
80
85
|
{#snippet content({ props: floatingProps, wrapperProps })}
|
|
81
86
|
{#if restProps.forceMount && enabled}
|
|
82
|
-
<ScrollLock {
|
|
87
|
+
<ScrollLock preventScroll={resolvedPreventScroll} />
|
|
83
88
|
{:else if !restProps.forceMount}
|
|
84
|
-
<ScrollLock {
|
|
89
|
+
<ScrollLock preventScroll={resolvedPreventScroll} />
|
|
85
90
|
{/if}
|
|
86
91
|
<FocusScope
|
|
87
92
|
{onOpenAutoFocus}
|
|
@@ -23,6 +23,7 @@ export function useFloating(options) {
|
|
|
23
23
|
let middlewareData = $state({});
|
|
24
24
|
let isPositioned = $state(false);
|
|
25
25
|
let hasWhileMountedPosition = false;
|
|
26
|
+
let updateRequestId = 0;
|
|
26
27
|
const floatingStyles = $derived.by(() => {
|
|
27
28
|
// preserve last known position when floating ref is null (during transitions)
|
|
28
29
|
const xVal = floating.current ? roundByDPR(floating.current, x) : x;
|
|
@@ -50,12 +51,20 @@ export function useFloating(options) {
|
|
|
50
51
|
function update() {
|
|
51
52
|
if (reference.current === null || floating.current === null)
|
|
52
53
|
return;
|
|
53
|
-
|
|
54
|
+
const referenceNode = reference.current;
|
|
55
|
+
const floatingNode = floating.current;
|
|
56
|
+
const requestId = ++updateRequestId;
|
|
57
|
+
computePosition(referenceNode, floatingNode, {
|
|
54
58
|
middleware: middlewareOption,
|
|
55
59
|
placement: placementOption,
|
|
56
60
|
strategy: strategyOption,
|
|
57
61
|
}).then((position) => {
|
|
58
|
-
|
|
62
|
+
// ignore stale async resolutions when newer updates were requested.
|
|
63
|
+
if (requestId !== updateRequestId)
|
|
64
|
+
return;
|
|
65
|
+
// ignore stale resolutions after ref replacement.
|
|
66
|
+
if (reference.current !== referenceNode || floating.current !== floatingNode)
|
|
67
|
+
return;
|
|
59
68
|
const referenceHidden = isReferenceHidden(referenceNode);
|
|
60
69
|
if (referenceHidden) {
|
|
61
70
|
// keep last good coordinates when the anchor disappears to avoid
|
|
@@ -91,6 +100,7 @@ export function useFloating(options) {
|
|
|
91
100
|
whileElementsMountedCleanup();
|
|
92
101
|
whileElementsMountedCleanup = undefined;
|
|
93
102
|
}
|
|
103
|
+
updateRequestId++;
|
|
94
104
|
}
|
|
95
105
|
function attach() {
|
|
96
106
|
cleanup();
|