bits-ui 1.0.0-next.41 → 1.0.0-next.42
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.
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
onEscapeKeydown = noop,
|
|
17
17
|
children,
|
|
18
18
|
child,
|
|
19
|
+
preventScroll = false,
|
|
19
20
|
...restProps
|
|
20
21
|
}: SelectContentProps = $props();
|
|
21
22
|
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
onCloseAutoFocus={(e) => e.preventDefault()}
|
|
57
58
|
trapFocus={false}
|
|
58
59
|
loop={false}
|
|
59
|
-
preventScroll
|
|
60
|
+
{preventScroll}
|
|
60
61
|
onPlaced={() => (contentState.isPositioned = true)}
|
|
61
62
|
forceMount={true}
|
|
62
63
|
>
|
|
@@ -83,7 +84,7 @@
|
|
|
83
84
|
onCloseAutoFocus={(e) => e.preventDefault()}
|
|
84
85
|
trapFocus={false}
|
|
85
86
|
loop={false}
|
|
86
|
-
preventScroll
|
|
87
|
+
{preventScroll}
|
|
87
88
|
onPlaced={() => (contentState.isPositioned = true)}
|
|
88
89
|
forceMount={false}
|
|
89
90
|
>
|
|
@@ -48,6 +48,8 @@ export class DismissibleLayerState {
|
|
|
48
48
|
$effect(() => {
|
|
49
49
|
if (this.#enabled.current && this.currNode) {
|
|
50
50
|
afterSleep(1, () => {
|
|
51
|
+
if (!this.currNode)
|
|
52
|
+
return;
|
|
51
53
|
globalThis.bitsDismissableLayers.set(this, untrack(() => this.#behaviorType));
|
|
52
54
|
unsubEvents();
|
|
53
55
|
unsubEvents = this.#addEventListeners();
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { afterTick } from "svelte-toolbelt";
|
|
2
|
+
import { Previous } from "runed";
|
|
3
|
+
import { untrack } from "svelte";
|
|
2
4
|
import { useStateMachine } from "../../../internal/use-state-machine.svelte.js";
|
|
3
|
-
import { watch } from "../../../internal/box.svelte.js";
|
|
4
5
|
export function usePresence(present, id) {
|
|
5
6
|
let styles = $state({});
|
|
6
7
|
let prevAnimationNameState = $state("none");
|
|
7
8
|
const initialState = present.current ? "mounted" : "unmounted";
|
|
8
9
|
let node = $state(null);
|
|
10
|
+
const prevPresent = new Previous(() => present.current);
|
|
9
11
|
$effect(() => {
|
|
10
12
|
if (!id.current)
|
|
11
13
|
return;
|
|
@@ -28,40 +30,43 @@ export function usePresence(present, id) {
|
|
|
28
30
|
MOUNT: "mounted",
|
|
29
31
|
},
|
|
30
32
|
});
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return;
|
|
37
|
-
const hasPresentChanged = currPresent !== prevPresent;
|
|
38
|
-
if (!hasPresentChanged)
|
|
39
|
-
return;
|
|
40
|
-
const prevAnimationName = prevAnimationNameState;
|
|
41
|
-
const currAnimationName = getAnimationName(node);
|
|
42
|
-
if (currPresent) {
|
|
43
|
-
dispatch("MOUNT");
|
|
44
|
-
}
|
|
45
|
-
else if (currAnimationName === "none" || styles.display === "none") {
|
|
46
|
-
// If there is no exit animation or the element is hidden, animations won't run
|
|
47
|
-
// so we unmount instantly
|
|
48
|
-
dispatch("UNMOUNT");
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
/**
|
|
52
|
-
* When `present` changes to `false`, we check changes to animation-name to
|
|
53
|
-
* determine whether an animation has started. We chose this approach (reading
|
|
54
|
-
* computed styles) because there is no `animationrun` event and `animationstart`
|
|
55
|
-
* fires after `animation-delay` has expired which would be too late.
|
|
56
|
-
*/
|
|
57
|
-
const isAnimating = prevAnimationName !== currAnimationName;
|
|
58
|
-
if (prevPresent && isAnimating) {
|
|
59
|
-
dispatch("ANIMATION_OUT");
|
|
33
|
+
$effect(() => {
|
|
34
|
+
const currPresent = present.current;
|
|
35
|
+
untrack(() => {
|
|
36
|
+
if (!node) {
|
|
37
|
+
node = document.getElementById(id.current);
|
|
60
38
|
}
|
|
61
|
-
|
|
39
|
+
if (!node)
|
|
40
|
+
return;
|
|
41
|
+
const hasPresentChanged = currPresent !== prevPresent.current;
|
|
42
|
+
if (!hasPresentChanged)
|
|
43
|
+
return;
|
|
44
|
+
const prevAnimationName = prevAnimationNameState;
|
|
45
|
+
const currAnimationName = getAnimationName(node);
|
|
46
|
+
if (currPresent) {
|
|
47
|
+
dispatch("MOUNT");
|
|
48
|
+
}
|
|
49
|
+
else if (currAnimationName === "none" || styles.display === "none") {
|
|
50
|
+
// If there is no exit animation or the element is hidden, animations won't run
|
|
51
|
+
// so we unmount instantly
|
|
62
52
|
dispatch("UNMOUNT");
|
|
63
53
|
}
|
|
64
|
-
|
|
54
|
+
else {
|
|
55
|
+
/**
|
|
56
|
+
* When `present` changes to `false`, we check changes to animation-name to
|
|
57
|
+
* determine whether an animation has started. We chose this approach (reading
|
|
58
|
+
* computed styles) because there is no `animationrun` event and `animationstart`
|
|
59
|
+
* fires after `animation-delay` has expired which would be too late.
|
|
60
|
+
*/
|
|
61
|
+
const isAnimating = prevAnimationName !== currAnimationName;
|
|
62
|
+
if (prevPresent && isAnimating) {
|
|
63
|
+
dispatch("ANIMATION_OUT");
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
dispatch("UNMOUNT");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
65
70
|
});
|
|
66
71
|
/**
|
|
67
72
|
* Triggering an ANIMATION_OUT during an ANIMATION_IN will fire an `animationcancel`
|
|
@@ -90,14 +95,17 @@ export function usePresence(present, id) {
|
|
|
90
95
|
prevAnimationNameState = getAnimationName(node);
|
|
91
96
|
}
|
|
92
97
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
$effect(() => {
|
|
99
|
+
state.current;
|
|
100
|
+
untrack(() => {
|
|
101
|
+
if (!node) {
|
|
102
|
+
node = document.getElementById(id.current);
|
|
103
|
+
}
|
|
104
|
+
if (!node)
|
|
105
|
+
return;
|
|
106
|
+
const currAnimationName = getAnimationName(node);
|
|
107
|
+
prevAnimationNameState = state.current === "mounted" ? currAnimationName : "none";
|
|
108
|
+
});
|
|
101
109
|
});
|
|
102
110
|
$effect(() => {
|
|
103
111
|
if (!node)
|