@pzerelles/headlessui-svelte 2.0.0-next.1 → 2.1.2-next.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.
- package/dist/button/Button.svelte +61 -0
- package/dist/button/Button.svelte.d.ts +47 -0
- package/dist/button/index.d.ts +1 -0
- package/dist/button/index.js +1 -0
- package/dist/checkbox/Checkbox.svelte +93 -61
- package/dist/checkbox/Checkbox.svelte.d.ts +45 -29
- package/dist/close-button/CloseButton.svelte +11 -0
- package/dist/close-button/CloseButton.svelte.d.ts +48 -0
- package/dist/close-button/index.d.ts +1 -0
- package/dist/close-button/index.js +1 -0
- package/dist/combobox/Combobox.svelte +6 -0
- package/dist/combobox/Combobox.svelte.d.ts +50 -0
- package/dist/data-interactive/DataInteractive.svelte +41 -0
- package/dist/data-interactive/DataInteractive.svelte.d.ts +39 -0
- package/dist/data-interactive/index.d.ts +1 -0
- package/dist/data-interactive/index.js +1 -0
- package/dist/description/Description.svelte +16 -41
- package/dist/description/Description.svelte.d.ts +15 -23
- package/dist/description/context.svelte.d.ts +17 -0
- package/dist/description/context.svelte.js +51 -0
- package/dist/dialog/Dialog.svelte +51 -0
- package/dist/dialog/Dialog.svelte.d.ts +60 -0
- package/dist/dialog/DialogBackdrop.svelte +39 -0
- package/dist/dialog/DialogBackdrop.svelte.d.ts +38 -0
- package/dist/dialog/DialogPanel.svelte +46 -0
- package/dist/dialog/DialogPanel.svelte.d.ts +40 -0
- package/dist/dialog/DialogTitle.svelte +29 -0
- package/dist/dialog/DialogTitle.svelte.d.ts +34 -0
- package/dist/dialog/InternalDialog.svelte +233 -0
- package/dist/dialog/InternalDialog.svelte.d.ts +42 -0
- package/dist/dialog/context.svelte.d.ts +15 -0
- package/dist/dialog/context.svelte.js +16 -0
- package/dist/dialog/index.d.ts +4 -0
- package/dist/dialog/index.js +4 -0
- package/dist/field/Field.svelte +14 -16
- package/dist/field/Field.svelte.d.ts +21 -17
- package/dist/fieldset/Fieldset.svelte +19 -17
- package/dist/fieldset/Fieldset.svelte.d.ts +21 -17
- package/dist/focus-trap/FocusTrap.svelte +332 -0
- package/dist/focus-trap/FocusTrap.svelte.d.ts +58 -0
- package/dist/hooks/document-overflow/adjust-scrollbar-padding.d.ts +2 -0
- package/dist/hooks/document-overflow/adjust-scrollbar-padding.js +18 -0
- package/dist/hooks/document-overflow/handle-ios-locking.d.ts +6 -0
- package/dist/hooks/document-overflow/handle-ios-locking.js +134 -0
- package/dist/hooks/document-overflow/overflow-store.d.ts +19 -0
- package/dist/hooks/document-overflow/overflow-store.js +76 -0
- package/dist/hooks/document-overflow/prevent-scroll.d.ts +2 -0
- package/dist/hooks/document-overflow/prevent-scroll.js +7 -0
- package/dist/hooks/document-overflow/use-document-overflow.svelte.d.ts +7 -0
- package/dist/hooks/document-overflow/use-document-overflow.svelte.js +27 -0
- package/dist/hooks/use-active-press.svelte.d.ts +14 -0
- package/dist/{actions/activePress.svelte.js → hooks/use-active-press.svelte.js} +33 -39
- package/dist/hooks/use-by-comparator.d.ts +2 -0
- package/dist/hooks/use-by-comparator.js +15 -0
- package/dist/hooks/use-controllable.svelte.d.ts +6 -0
- package/dist/hooks/use-controllable.svelte.js +34 -0
- package/dist/hooks/use-did-element-move.svelte.d.ts +6 -0
- package/dist/hooks/use-did-element-move.svelte.js +27 -0
- package/dist/hooks/use-disabled.d.ts +3 -0
- package/dist/hooks/use-disabled.js +9 -0
- package/dist/hooks/use-element-size.svelte.d.ts +7 -0
- package/dist/hooks/use-element-size.svelte.js +36 -0
- package/dist/hooks/use-escape.svelte.d.ts +5 -0
- package/dist/hooks/use-escape.svelte.js +26 -0
- package/dist/hooks/use-event-listener.svelte.d.ts +6 -0
- package/dist/hooks/use-event-listener.svelte.js +12 -0
- package/dist/hooks/use-flags.svelte.d.ts +8 -0
- package/dist/hooks/use-flags.svelte.js +18 -0
- package/dist/hooks/use-focus-ring.svelte.d.ts +10 -0
- package/dist/hooks/use-focus-ring.svelte.js +24 -0
- package/dist/hooks/use-hover.svelte.d.ts +26 -0
- package/dist/hooks/use-hover.svelte.js +124 -0
- package/dist/hooks/use-id.d.ts +1 -0
- package/dist/hooks/use-id.js +1 -0
- package/dist/hooks/use-inert-others.svelte.d.ts +32 -0
- package/dist/hooks/use-inert-others.svelte.js +114 -0
- package/dist/hooks/use-is-mounted.svelte.d.ts +3 -0
- package/dist/hooks/use-is-mounted.svelte.js +14 -0
- package/dist/hooks/use-is-top-layer.svelte.d.ts +29 -0
- package/dist/hooks/use-is-top-layer.svelte.js +82 -0
- package/dist/hooks/use-is-touch-device.svelte.d.ts +3 -0
- package/dist/hooks/use-is-touch-device.svelte.js +20 -0
- package/dist/hooks/use-on-disappear.svelte.d.ts +12 -0
- package/dist/hooks/use-on-disappear.svelte.js +38 -0
- package/dist/hooks/use-outside-click.svelte.d.ts +10 -0
- package/dist/hooks/use-outside-click.svelte.js +150 -0
- package/dist/hooks/use-reducer.d.ts +4 -0
- package/dist/hooks/use-reducer.js +11 -0
- package/dist/hooks/use-resolve-button-type.svelte.d.ts +10 -0
- package/dist/hooks/use-resolve-button-type.svelte.js +19 -0
- package/dist/hooks/use-root-containers.svelte.d.ts +9 -0
- package/dist/hooks/use-root-containers.svelte.js +50 -0
- package/dist/hooks/use-scroll-lock.svelte.d.ts +5 -0
- package/dist/hooks/use-scroll-lock.svelte.js +24 -0
- package/dist/hooks/use-sync-refs.d.ts +7 -0
- package/dist/hooks/use-sync-refs.js +22 -0
- package/dist/hooks/use-tab-direction.svelte.d.ts +7 -0
- package/dist/hooks/use-tab-direction.svelte.js +25 -0
- package/dist/hooks/use-text-value.svelte.d.ts +3 -0
- package/dist/hooks/use-text-value.svelte.js +20 -0
- package/dist/hooks/use-tracked-pointer.d.ts +4 -0
- package/dist/hooks/use-tracked-pointer.js +26 -0
- package/dist/hooks/use-transition.svelte.d.ts +20 -0
- package/dist/hooks/use-transition.svelte.js +253 -0
- package/dist/hooks/use-tree-walker.svelte.d.ts +8 -0
- package/dist/hooks/use-tree-walker.svelte.js +19 -0
- package/dist/hooks/use-watch.svelte.d.ts +4 -0
- package/dist/hooks/use-watch.svelte.js +16 -0
- package/dist/hooks/use-window-event.svelte.d.ts +6 -0
- package/dist/hooks/use-window-event.svelte.js +12 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -0
- package/dist/input/Input.svelte +59 -0
- package/dist/input/Input.svelte.d.ts +52 -0
- package/dist/input/index.d.ts +1 -0
- package/dist/input/index.js +1 -0
- package/dist/internal/FocusSentinel.svelte +45 -0
- package/dist/internal/FocusSentinel.svelte.d.ts +20 -0
- package/dist/internal/ForcePortalRoot.svelte +6 -0
- package/dist/internal/ForcePortalRoot.svelte.d.ts +22 -0
- package/dist/internal/FormFields.svelte +2 -4
- package/dist/internal/FormFields.svelte.d.ts +9 -7
- package/dist/internal/FormResolver.svelte +11 -16
- package/dist/internal/FormResolver.svelte.d.ts +6 -4
- package/dist/internal/Hidden.svelte +5 -9
- package/dist/internal/Hidden.svelte.d.ts +35 -19
- package/dist/internal/HoistFormFields.svelte.d.ts +5 -2
- package/dist/internal/MainTreeProvider.svelte +45 -0
- package/dist/internal/MainTreeProvider.svelte.d.ts +31 -0
- package/dist/internal/Portal.svelte.d.ts +5 -2
- package/dist/internal/close-provider.d.ts +7 -0
- package/dist/internal/close-provider.js +7 -0
- package/dist/internal/floating.svelte.d.ts +62 -0
- package/dist/internal/floating.svelte.js +488 -0
- package/dist/internal/frozen.svelte.d.ts +6 -0
- package/dist/internal/frozen.svelte.js +18 -0
- package/dist/internal/id.d.ts +8 -0
- package/dist/internal/id.js +11 -0
- package/dist/internal/open-closed.d.ts +14 -0
- package/dist/internal/open-closed.js +17 -0
- package/dist/internal/portal-force-root.svelte.d.ts +6 -0
- package/dist/internal/portal-force-root.svelte.js +11 -0
- package/dist/label/Label.svelte +17 -45
- package/dist/label/Label.svelte.d.ts +19 -23
- package/dist/label/context.svelte.d.ts +17 -0
- package/dist/label/context.svelte.js +56 -0
- package/dist/legend/Legend.svelte +4 -3
- package/dist/legend/Legend.svelte.d.ts +33 -16
- package/dist/listbox/Listbox.svelte +448 -0
- package/dist/listbox/Listbox.svelte.d.ts +126 -0
- package/dist/listbox/ListboxButton.svelte +139 -0
- package/dist/listbox/ListboxButton.svelte.d.ts +52 -0
- package/dist/listbox/ListboxOption.svelte +136 -0
- package/dist/listbox/ListboxOption.svelte.d.ts +50 -0
- package/dist/listbox/ListboxOptions.svelte +269 -0
- package/dist/listbox/ListboxOptions.svelte.d.ts +55 -0
- package/dist/listbox/ListboxSelectedOption.svelte +35 -0
- package/dist/listbox/ListboxSelectedOption.svelte.d.ts +40 -0
- package/dist/listbox/index.d.ts +5 -0
- package/dist/listbox/index.js +5 -0
- package/dist/menu/Menu.svelte +235 -0
- package/dist/menu/Menu.svelte.d.ts +42 -0
- package/dist/menu/MenuButton.svelte +127 -0
- package/dist/menu/MenuButton.svelte.d.ts +52 -0
- package/dist/menu/MenuHeading.svelte +19 -0
- package/dist/menu/MenuHeading.svelte.d.ts +39 -0
- package/dist/menu/MenuItem.svelte +114 -0
- package/dist/menu/MenuItem.svelte.d.ts +49 -0
- package/dist/menu/MenuItems.svelte +244 -0
- package/dist/menu/MenuItems.svelte.d.ts +55 -0
- package/dist/menu/MenuSection.svelte +14 -0
- package/dist/menu/MenuSection.svelte.d.ts +35 -0
- package/dist/menu/MenuSeparator.svelte +9 -0
- package/dist/menu/MenuSeparator.svelte.d.ts +35 -0
- package/dist/menu/context.svelte.d.ts +47 -0
- package/dist/menu/context.svelte.js +21 -0
- package/dist/menu/index.d.ts +7 -0
- package/dist/menu/index.js +7 -0
- package/dist/portal/InternalPortal.svelte +97 -0
- package/dist/portal/InternalPortal.svelte.d.ts +43 -0
- package/dist/portal/Portal.svelte +7 -0
- package/dist/portal/Portal.svelte.d.ts +23 -0
- package/dist/portal/PortalGroup.svelte +14 -0
- package/dist/portal/PortalGroup.svelte.d.ts +40 -0
- package/dist/switch/Switch.svelte +143 -0
- package/dist/switch/Switch.svelte.d.ts +61 -0
- package/dist/switch/SwitchGroup.svelte +37 -0
- package/dist/switch/SwitchGroup.svelte.d.ts +34 -0
- package/dist/switch/index.d.ts +2 -0
- package/dist/switch/index.js +2 -0
- package/dist/tabs/Tab.svelte +156 -0
- package/dist/tabs/Tab.svelte.d.ts +48 -0
- package/dist/tabs/TabGroup.svelte +241 -0
- package/dist/tabs/TabGroup.svelte.d.ts +67 -0
- package/dist/tabs/TabList.svelte +16 -0
- package/dist/tabs/TabList.svelte.d.ts +35 -0
- package/dist/tabs/TabPanel.svelte +61 -0
- package/dist/tabs/TabPanel.svelte.d.ts +47 -0
- package/dist/tabs/TabPanels.svelte +12 -0
- package/dist/tabs/TabPanels.svelte.d.ts +34 -0
- package/dist/tabs/index.d.ts +5 -0
- package/dist/tabs/index.js +5 -0
- package/dist/test-utils/accessability-assertions.d.ts +271 -0
- package/dist/test-utils/accessability-assertions.js +1572 -0
- package/dist/test-utils/fake-pointer.d.ts +24 -0
- package/dist/test-utils/fake-pointer.js +48 -0
- package/dist/test-utils/interactions.d.ts +61 -0
- package/dist/test-utils/interactions.js +453 -0
- package/dist/test-utils/suppress-console-logs.d.ts +7 -0
- package/dist/test-utils/suppress-console-logs.js +17 -0
- package/dist/transition/InternalTransitionChild.svelte +178 -0
- package/dist/transition/InternalTransitionChild.svelte.d.ts +55 -0
- package/dist/transition/Transition.svelte +89 -0
- package/dist/transition/Transition.svelte.d.ts +42 -0
- package/dist/transition/TransitionChild.svelte +16 -0
- package/dist/transition/TransitionChild.svelte.d.ts +44 -0
- package/dist/transition/context.svelte.d.ts +64 -0
- package/dist/transition/context.svelte.js +120 -0
- package/dist/transition/index.d.ts +2 -0
- package/dist/transition/index.js +2 -0
- package/dist/utils/ElementOrComponent.svelte +26 -0
- package/dist/utils/ElementOrComponent.svelte.d.ts +56 -0
- package/dist/utils/Generic.svelte +44 -0
- package/dist/utils/Generic.svelte.d.ts +35 -0
- package/dist/utils/StableCollection.svelte +43 -0
- package/dist/utils/StableCollection.svelte.d.ts +22 -0
- package/dist/utils/active-element-history.d.ts +1 -0
- package/dist/utils/active-element-history.js +35 -0
- package/dist/utils/alternative-types.d.ts +21 -0
- package/dist/utils/alternative-types.js +1 -0
- package/dist/utils/calculate-active-index.d.ts +25 -0
- package/dist/utils/calculate-active-index.js +74 -0
- package/dist/utils/class-names.d.ts +1 -0
- package/dist/utils/class-names.js +10 -0
- package/dist/utils/default-map.d.ts +5 -0
- package/dist/utils/default-map.js +15 -0
- package/dist/utils/disposables.d.ts +14 -12
- package/dist/utils/disposables.js +13 -10
- package/dist/utils/dom.d.ts +0 -2
- package/dist/utils/dom.js +2 -4
- package/dist/utils/env.d.ts +17 -0
- package/dist/utils/env.js +39 -0
- package/dist/utils/focus-management.d.ts +45 -0
- package/dist/utils/focus-management.js +242 -0
- package/dist/utils/focusVisible.svelte.d.ts +3 -3
- package/dist/utils/focusVisible.svelte.js +52 -41
- package/dist/utils/get-text-value.d.ts +1 -0
- package/dist/utils/get-text-value.js +71 -0
- package/dist/utils/id.d.ts +1 -1
- package/dist/utils/match.d.ts +1 -0
- package/dist/utils/match.js +13 -0
- package/dist/utils/on-document-ready.d.ts +1 -0
- package/dist/utils/on-document-ready.js +12 -0
- package/dist/utils/once.d.ts +1 -0
- package/dist/utils/once.js +9 -0
- package/dist/utils/owner.d.ts +1 -0
- package/dist/utils/owner.js +8 -0
- package/dist/utils/platform.d.ts +2 -0
- package/dist/utils/platform.js +17 -0
- package/dist/utils/ref.svelte.d.ts +4 -0
- package/dist/utils/ref.svelte.js +4 -0
- package/dist/utils/render.d.ts +34 -0
- package/dist/utils/render.js +119 -0
- package/dist/utils/state.d.ts +7 -1
- package/dist/utils/state.js +10 -6
- package/dist/utils/store.d.ts +11 -0
- package/dist/utils/store.js +20 -0
- package/dist/utils/types.d.ts +24 -0
- package/dist/utils/types.js +1 -0
- package/package.json +33 -25
- package/dist/actions/activePress.svelte.d.ts +0 -8
- package/dist/actions/focusRing.svelte.d.ts +0 -9
- package/dist/actions/focusRing.svelte.js +0 -34
- package/dist/utils/disabled.d.ts +0 -3
- package/dist/utils/disabled.js +0 -2
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { overflows } from "./overflow-store.js";
|
|
2
|
+
export function useDocumentOverflowLockedEffect(options) {
|
|
3
|
+
const { shouldBeLocked, doc, meta = () => ({ containers: [] }) } = $derived(options);
|
|
4
|
+
let store = $state(overflows.getSnapshot());
|
|
5
|
+
$effect(() => {
|
|
6
|
+
const unsubscribe = overflows.subscribe(() => {
|
|
7
|
+
store = overflows.getSnapshot();
|
|
8
|
+
});
|
|
9
|
+
return unsubscribe;
|
|
10
|
+
});
|
|
11
|
+
const entry = $derived(doc ? store.get(doc) : undefined);
|
|
12
|
+
const locked = $derived(entry ? entry.count > 0 : false);
|
|
13
|
+
$effect(() => {
|
|
14
|
+
if (!doc || !shouldBeLocked) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
// Prevent the document from scrolling
|
|
18
|
+
overflows.dispatch("PUSH", doc, meta);
|
|
19
|
+
// Allow document to scroll
|
|
20
|
+
return () => overflows.dispatch("POP", doc, meta);
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
get locked() {
|
|
24
|
+
return locked;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const useActivePress: (options: {
|
|
2
|
+
disabled?: boolean;
|
|
3
|
+
}) => {
|
|
4
|
+
readonly pressed: boolean;
|
|
5
|
+
readonly pressProps: {
|
|
6
|
+
onpointerdown?: undefined;
|
|
7
|
+
onpointerup?: undefined;
|
|
8
|
+
onclick?: undefined;
|
|
9
|
+
} | {
|
|
10
|
+
onpointerdown: (event: PointerEvent) => void;
|
|
11
|
+
onpointerup: () => void;
|
|
12
|
+
onclick: () => void;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { disposables } from "../utils/disposables.js";
|
|
2
|
-
import { getOwnerDocument } from "../utils/
|
|
2
|
+
import { getOwnerDocument } from "../utils/owner.js";
|
|
3
3
|
function pointerRectFromPointerEvent(event) {
|
|
4
4
|
// Center of the pointer geometry
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const offsetX = event.width / 2;
|
|
6
|
+
const offsetY = event.height / 2;
|
|
7
7
|
return {
|
|
8
8
|
top: event.clientY - offsetY,
|
|
9
9
|
right: event.clientX + offsetX,
|
|
@@ -23,27 +23,28 @@ function areRectsOverlapping(a, b) {
|
|
|
23
23
|
}
|
|
24
24
|
return true;
|
|
25
25
|
}
|
|
26
|
-
export const
|
|
26
|
+
export const useActivePress = (options) => {
|
|
27
|
+
const { disabled } = $derived(options);
|
|
27
28
|
let currentTarget = $state(null);
|
|
28
29
|
let pressed = $state(false);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
30
|
+
const d = disposables();
|
|
31
|
+
const reset = () => {
|
|
32
|
+
currentTarget = null;
|
|
33
|
+
pressed = false;
|
|
34
|
+
d.dispose();
|
|
35
|
+
};
|
|
36
|
+
const handlePointerDown = (event) => {
|
|
37
|
+
d.dispose(); // Cancel any scheduled tasks
|
|
38
|
+
if (currentTarget !== null)
|
|
39
|
+
return;
|
|
40
|
+
// Keep track of the current element
|
|
41
|
+
currentTarget = event.currentTarget;
|
|
42
|
+
// We are definitely pressing the element now
|
|
43
|
+
pressed = true;
|
|
44
|
+
// Setup global handlers to catch events on elements that are not the current element
|
|
45
|
+
{
|
|
46
|
+
const owner = getOwnerDocument(event.currentTarget);
|
|
47
|
+
if (owner) {
|
|
47
48
|
// `pointerup` on any element means that we are no longer pressing the current element
|
|
48
49
|
d.addEventListener(owner, "pointerup", reset, false);
|
|
49
50
|
// `pointerleave` isn't called consistently (if at all) on iOS Safari, so we use `pointermove` instead
|
|
@@ -51,34 +52,27 @@ export const createActivePress = ({ disabled }) => {
|
|
|
51
52
|
// so that we can tell if the pointer is still over the element or not.
|
|
52
53
|
d.addEventListener(owner, "pointermove", (event) => {
|
|
53
54
|
if (currentTarget) {
|
|
54
|
-
|
|
55
|
+
const pointerRect = pointerRectFromPointerEvent(event);
|
|
55
56
|
pressed = areRectsOverlapping(pointerRect, currentTarget.getBoundingClientRect());
|
|
56
57
|
}
|
|
57
58
|
}, false);
|
|
58
59
|
// Whenever the browser decides to fire a `pointercancel` event, we should abort
|
|
59
60
|
d.addEventListener(owner, "pointercancel", reset, false);
|
|
60
61
|
}
|
|
61
|
-
};
|
|
62
|
-
if (!disabled) {
|
|
63
|
-
node.addEventListener("pointerdown", handlePointerDown);
|
|
64
|
-
node.addEventListener("pointerup", reset);
|
|
65
|
-
node.addEventListener("click", reset);
|
|
66
62
|
}
|
|
67
|
-
return {
|
|
68
|
-
destroy: () => {
|
|
69
|
-
if (!disabled) {
|
|
70
|
-
node.removeEventListener("pointerdown", handlePointerDown);
|
|
71
|
-
node.removeEventListener("pointerup", reset);
|
|
72
|
-
node.removeEventListener("click", reset);
|
|
73
|
-
}
|
|
74
|
-
d.dispose();
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
63
|
};
|
|
78
64
|
return {
|
|
79
|
-
activePressAction,
|
|
80
65
|
get pressed() {
|
|
81
66
|
return pressed;
|
|
82
67
|
},
|
|
68
|
+
get pressProps() {
|
|
69
|
+
return disabled
|
|
70
|
+
? {}
|
|
71
|
+
: {
|
|
72
|
+
onpointerdown: handlePointerDown,
|
|
73
|
+
onpointerup: reset,
|
|
74
|
+
onclick: reset,
|
|
75
|
+
};
|
|
76
|
+
},
|
|
83
77
|
};
|
|
84
78
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function defaultBy(a, z) {
|
|
2
|
+
if (a !== null && z !== null && typeof a === "object" && typeof z === "object" && "id" in a && "id" in z) {
|
|
3
|
+
return a.id === z.id;
|
|
4
|
+
}
|
|
5
|
+
return a === z;
|
|
6
|
+
}
|
|
7
|
+
export function useByComparator(by = defaultBy) {
|
|
8
|
+
return (a, z) => {
|
|
9
|
+
if (typeof by === "string") {
|
|
10
|
+
const property = by;
|
|
11
|
+
return a?.[property] === z?.[property];
|
|
12
|
+
}
|
|
13
|
+
return by(a, z);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function useControllable(input, onchange, defaultValue) {
|
|
2
|
+
let internalValue = $state(defaultValue);
|
|
3
|
+
const isControlled = $derived(input.controlledValue !== undefined);
|
|
4
|
+
let wasControlled = isControlled;
|
|
5
|
+
let didWarnOnUncontrolledToControlled = false;
|
|
6
|
+
let didWarnOnControlledToUncontrolled = false;
|
|
7
|
+
$effect(() => {
|
|
8
|
+
if (isControlled && !wasControlled && !didWarnOnUncontrolledToControlled) {
|
|
9
|
+
didWarnOnUncontrolledToControlled = true;
|
|
10
|
+
wasControlled = isControlled;
|
|
11
|
+
console.error("A component is changing from uncontrolled to controlled. This may be caused by the value changing from undefined to a defined value, which should not happen.");
|
|
12
|
+
}
|
|
13
|
+
else if (!isControlled && wasControlled && !didWarnOnControlledToUncontrolled) {
|
|
14
|
+
didWarnOnControlledToUncontrolled = true;
|
|
15
|
+
wasControlled = isControlled;
|
|
16
|
+
console.error("A component is changing from controlled to uncontrolled. This may be caused by the value changing from a defined value to undefined, which should not happen.");
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const value = $derived(isControlled ? input.controlledValue : internalValue);
|
|
20
|
+
return {
|
|
21
|
+
get value() {
|
|
22
|
+
return value;
|
|
23
|
+
},
|
|
24
|
+
onchange: (value) => {
|
|
25
|
+
if (isControlled && onchange) {
|
|
26
|
+
onchange?.(value);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
internalValue = value;
|
|
30
|
+
input.controlledValue = value;
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function useDidElementMove(options) {
|
|
2
|
+
const { enabled, element } = $derived(options);
|
|
3
|
+
let elementPosition = $state({ left: 0, top: 0 });
|
|
4
|
+
$effect(() => {
|
|
5
|
+
if (!element)
|
|
6
|
+
return;
|
|
7
|
+
let DOMRect = element.getBoundingClientRect();
|
|
8
|
+
if (DOMRect)
|
|
9
|
+
elementPosition = DOMRect;
|
|
10
|
+
});
|
|
11
|
+
const value = $derived.by(() => {
|
|
12
|
+
if (element == null)
|
|
13
|
+
return false;
|
|
14
|
+
if (!enabled)
|
|
15
|
+
return false;
|
|
16
|
+
if (element === document.activeElement)
|
|
17
|
+
return false;
|
|
18
|
+
let buttonRect = element.getBoundingClientRect();
|
|
19
|
+
let didElementMove = buttonRect.top !== elementPosition.top || buttonRect.left !== elementPosition.left;
|
|
20
|
+
return didElementMove;
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
get value() {
|
|
24
|
+
return value;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
function computeSize(element) {
|
|
2
|
+
if (element === null)
|
|
3
|
+
return { width: 0, height: 0 };
|
|
4
|
+
const { width, height } = element.getBoundingClientRect();
|
|
5
|
+
return { width, height };
|
|
6
|
+
}
|
|
7
|
+
export function useElementSize(options) {
|
|
8
|
+
const { element, unit = false } = $derived(options);
|
|
9
|
+
// When the element changes during a re-render, we want to make sure we
|
|
10
|
+
// compute the correct size as soon as possible. However, once the element is
|
|
11
|
+
// stable, we also want to watch for changes to the element. The `identity`
|
|
12
|
+
// state can be used to recompute the size.
|
|
13
|
+
let size = $state(computeSize(element));
|
|
14
|
+
const observeSize = (element) => {
|
|
15
|
+
if (!element)
|
|
16
|
+
return;
|
|
17
|
+
const observer = new ResizeObserver(() => {
|
|
18
|
+
const { width, height } = computeSize(element);
|
|
19
|
+
if (width !== size.width || height !== size.height)
|
|
20
|
+
size = { width, height };
|
|
21
|
+
});
|
|
22
|
+
observer.observe(element);
|
|
23
|
+
return () => {
|
|
24
|
+
observer.disconnect();
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
$effect(() => observeSize(element));
|
|
28
|
+
return {
|
|
29
|
+
get width() {
|
|
30
|
+
return unit ? `${size.width}px` : size.width;
|
|
31
|
+
},
|
|
32
|
+
get height() {
|
|
33
|
+
return unit ? `${size.height}px` : size.height;
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useEventListener } from "./use-event-listener.svelte.js";
|
|
2
|
+
import { useIsTopLayer } from "./use-is-top-layer.svelte.js";
|
|
3
|
+
export function useEscape(options) {
|
|
4
|
+
const { enabled, view = typeof document !== "undefined" ? document.defaultView : null, cb } = $derived(options);
|
|
5
|
+
let isTopLayer = useIsTopLayer({
|
|
6
|
+
get enabled() {
|
|
7
|
+
return enabled;
|
|
8
|
+
},
|
|
9
|
+
scope: "escape",
|
|
10
|
+
});
|
|
11
|
+
useEventListener({
|
|
12
|
+
get element() {
|
|
13
|
+
return view;
|
|
14
|
+
},
|
|
15
|
+
type: "keydown",
|
|
16
|
+
listener: (event) => {
|
|
17
|
+
if (!isTopLayer.value)
|
|
18
|
+
return;
|
|
19
|
+
if (event.defaultPrevented)
|
|
20
|
+
return;
|
|
21
|
+
if (event.key !== "Escape")
|
|
22
|
+
return;
|
|
23
|
+
cb(event);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function useEventListener<TType extends keyof WindowEventMap>(params: {
|
|
2
|
+
element: HTMLElement | Document | Window | EventTarget | null | undefined;
|
|
3
|
+
type: TType;
|
|
4
|
+
listener: (event: WindowEventMap[TType]) => any;
|
|
5
|
+
options?: boolean | AddEventListenerOptions;
|
|
6
|
+
}): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function useEventListener(params) {
|
|
2
|
+
let { element = window, type, listener, options } = $derived(params);
|
|
3
|
+
$effect(() => {
|
|
4
|
+
if (!element)
|
|
5
|
+
return;
|
|
6
|
+
function handler(event) {
|
|
7
|
+
listener(event);
|
|
8
|
+
}
|
|
9
|
+
element.addEventListener(type, handler, options);
|
|
10
|
+
return () => element.removeEventListener(type, handler, options);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function useFlags(initialFlags?: number): {
|
|
2
|
+
readonly flags: number;
|
|
3
|
+
setFlag: (flag: number) => number;
|
|
4
|
+
addFlag: (flag: number) => number;
|
|
5
|
+
hasFlag: (flag: number) => boolean;
|
|
6
|
+
removeFlag: (flag: number) => number;
|
|
7
|
+
toggleFlag: (flag: number) => number;
|
|
8
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function useFlags(initialFlags = 0) {
|
|
2
|
+
let flags = $state(initialFlags);
|
|
3
|
+
let setFlag = (flag) => (flags = flag);
|
|
4
|
+
let addFlag = (flag) => (flags = flags | flag);
|
|
5
|
+
let hasFlag = (flag) => (flags & flag) === flag;
|
|
6
|
+
let removeFlag = (flag) => (flags = flags & ~flag);
|
|
7
|
+
let toggleFlag = (flag) => (flags = flags ^ flag);
|
|
8
|
+
return {
|
|
9
|
+
get flags() {
|
|
10
|
+
return flags;
|
|
11
|
+
},
|
|
12
|
+
setFlag,
|
|
13
|
+
addFlag,
|
|
14
|
+
hasFlag,
|
|
15
|
+
removeFlag,
|
|
16
|
+
toggleFlag,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { isFocusVisible, useFocusVisibleListener } from "../utils/focusVisible.svelte.js";
|
|
2
|
+
export const useFocusRing = (options = {}) => {
|
|
3
|
+
const { autofocus, within } = $derived(options);
|
|
4
|
+
let focused = $state(false);
|
|
5
|
+
let _isFocusVisible = $state(autofocus || isFocusVisible());
|
|
6
|
+
useFocusVisibleListener((isFocusVisible) => {
|
|
7
|
+
_isFocusVisible = isFocusVisible;
|
|
8
|
+
});
|
|
9
|
+
return {
|
|
10
|
+
get isFocusVisible() {
|
|
11
|
+
return _isFocusVisible && focused;
|
|
12
|
+
},
|
|
13
|
+
focusProps: {
|
|
14
|
+
onfocus: () => {
|
|
15
|
+
if (!within)
|
|
16
|
+
focused = true;
|
|
17
|
+
},
|
|
18
|
+
onblur: () => {
|
|
19
|
+
if (!within)
|
|
20
|
+
focused = false;
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface HoverEvent {
|
|
2
|
+
/** The type of hover event being fired. */
|
|
3
|
+
type: "hoverstart" | "hoverend";
|
|
4
|
+
/** The pointer type that triggered the hover event. */
|
|
5
|
+
pointerType: "mouse" | "pen";
|
|
6
|
+
/** The target element of the hover event. */
|
|
7
|
+
target: Element;
|
|
8
|
+
}
|
|
9
|
+
export declare const useHover: (options?: {
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}) => {
|
|
12
|
+
readonly isHovered: boolean;
|
|
13
|
+
hoverProps: {
|
|
14
|
+
onpointerenter: (e: PointerEvent) => void;
|
|
15
|
+
onpointerleave: (e: PointerEvent) => void;
|
|
16
|
+
onmouseenter?: undefined;
|
|
17
|
+
onmouseleave?: undefined;
|
|
18
|
+
ontouchstart?: undefined;
|
|
19
|
+
} | {
|
|
20
|
+
onmouseenter: (e: MouseEvent) => void;
|
|
21
|
+
onmouseleave: (e: MouseEvent) => void;
|
|
22
|
+
ontouchstart: () => void;
|
|
23
|
+
onpointerenter?: undefined;
|
|
24
|
+
onpointerleave?: undefined;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// let { isHovered: hover, hoverProps } = useHover({ isDisabled: disabled })
|
|
2
|
+
import { disposables } from "../utils/disposables.js";
|
|
3
|
+
let globalIgnoreEmulatedMouseEvents = false;
|
|
4
|
+
let hoverCount = 0;
|
|
5
|
+
const d = disposables();
|
|
6
|
+
function setGlobalIgnoreEmulatedMouseEvents() {
|
|
7
|
+
globalIgnoreEmulatedMouseEvents = true;
|
|
8
|
+
// Clear globalIgnoreEmulatedMouseEvents after a short timeout. iOS fires onPointerEnter
|
|
9
|
+
// with pointerType="mouse" immediately after onPointerUp and before onFocus. On other
|
|
10
|
+
// devices that don't have this quirk, we don't want to ignore a mouse hover sometime in
|
|
11
|
+
// the distant future because a user previously touched the element.
|
|
12
|
+
setTimeout(() => { });
|
|
13
|
+
}
|
|
14
|
+
function handleGlobalPointerEvent(e) {
|
|
15
|
+
if (e.pointerType === "touch") {
|
|
16
|
+
setGlobalIgnoreEmulatedMouseEvents();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function isHoverPointerType(pointerType) {
|
|
20
|
+
return pointerType === "mouse" || pointerType === "pen" || pointerType === "touch";
|
|
21
|
+
}
|
|
22
|
+
function setupGlobalTouchEvents() {
|
|
23
|
+
if (typeof document === "undefined" || !document)
|
|
24
|
+
return;
|
|
25
|
+
if (hoverCount === 0) {
|
|
26
|
+
if (typeof PointerEvent !== "undefined") {
|
|
27
|
+
d.addEventListener(document, "pointerup", handleGlobalPointerEvent);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
d.addEventListener(document, "touchend", setGlobalIgnoreEmulatedMouseEvents);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
hoverCount++;
|
|
34
|
+
return () => {
|
|
35
|
+
hoverCount--;
|
|
36
|
+
if (hoverCount === 0)
|
|
37
|
+
d.dispose();
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export const useHover = (options = {}) => {
|
|
41
|
+
const { disabled } = $derived(options);
|
|
42
|
+
const _state = $state({
|
|
43
|
+
isHovered: false,
|
|
44
|
+
ignoreEmulatedMouseEvents: false,
|
|
45
|
+
pointerType: "",
|
|
46
|
+
target: null,
|
|
47
|
+
});
|
|
48
|
+
$effect(() => setupGlobalTouchEvents());
|
|
49
|
+
$effect(() => {
|
|
50
|
+
if (disabled) {
|
|
51
|
+
_state.pointerType = "";
|
|
52
|
+
_state.target = null;
|
|
53
|
+
_state.isHovered = false;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
function triggerHoverStart(originalEvent, pointerType) {
|
|
57
|
+
_state.pointerType = pointerType ?? undefined;
|
|
58
|
+
const target = originalEvent.currentTarget;
|
|
59
|
+
if (!(target instanceof HTMLElement || target instanceof SVGElement))
|
|
60
|
+
return;
|
|
61
|
+
if (disabled || pointerType === "touch" || _state.isHovered || !target.contains(originalEvent.target)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
_state.isHovered = true;
|
|
65
|
+
_state.target = target;
|
|
66
|
+
}
|
|
67
|
+
function triggerHoverEnd(originalEvent, pointerType) {
|
|
68
|
+
_state.pointerType = "";
|
|
69
|
+
_state.target = null;
|
|
70
|
+
const currentTarget = originalEvent.currentTarget;
|
|
71
|
+
if (pointerType === "touch" || !_state.isHovered || !(currentTarget instanceof HTMLElement))
|
|
72
|
+
return;
|
|
73
|
+
_state.isHovered = false;
|
|
74
|
+
}
|
|
75
|
+
function handlePointerEnter(e) {
|
|
76
|
+
const pointerType = e.pointerType;
|
|
77
|
+
if (!isHoverPointerType(pointerType))
|
|
78
|
+
return;
|
|
79
|
+
if (globalIgnoreEmulatedMouseEvents && e.pointerType === "mouse")
|
|
80
|
+
return;
|
|
81
|
+
triggerHoverStart(e, pointerType);
|
|
82
|
+
}
|
|
83
|
+
function handlePointerLeave(e) {
|
|
84
|
+
const pointerType = e.pointerType;
|
|
85
|
+
const currentTarget = e.currentTarget;
|
|
86
|
+
if (disabled ||
|
|
87
|
+
!(currentTarget instanceof HTMLElement) ||
|
|
88
|
+
!currentTarget.contains(e.target) ||
|
|
89
|
+
!isHoverPointerType(pointerType)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
triggerHoverEnd(e, pointerType);
|
|
93
|
+
}
|
|
94
|
+
function handleTouchStart() {
|
|
95
|
+
_state.ignoreEmulatedMouseEvents = true;
|
|
96
|
+
}
|
|
97
|
+
function handleMouseEnter(e) {
|
|
98
|
+
if (!_state.ignoreEmulatedMouseEvents && !globalIgnoreEmulatedMouseEvents) {
|
|
99
|
+
triggerHoverStart(e, "mouse");
|
|
100
|
+
}
|
|
101
|
+
_state.ignoreEmulatedMouseEvents = false;
|
|
102
|
+
}
|
|
103
|
+
function handleMouseLeave(e) {
|
|
104
|
+
const currentTarget = e.currentTarget;
|
|
105
|
+
if (disabled || !(currentTarget instanceof HTMLElement) || !currentTarget.contains(e.target))
|
|
106
|
+
return;
|
|
107
|
+
triggerHoverEnd(e, "mouse");
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
get isHovered() {
|
|
111
|
+
return _state.isHovered;
|
|
112
|
+
},
|
|
113
|
+
hoverProps: typeof PointerEvent !== "undefined"
|
|
114
|
+
? {
|
|
115
|
+
onpointerenter: handlePointerEnter,
|
|
116
|
+
onpointerleave: handlePointerLeave,
|
|
117
|
+
}
|
|
118
|
+
: {
|
|
119
|
+
onmouseenter: handleMouseEnter,
|
|
120
|
+
onmouseleave: handleMouseLeave,
|
|
121
|
+
ontouchstart: handleTouchStart,
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { htmlid as useId } from "../utils/id.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { htmlid as useId } from "../utils/id.js";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mark all elements on the page as inert, except for the ones that are allowed.
|
|
3
|
+
*
|
|
4
|
+
* We move up the tree from the allowed elements, and mark all their siblings as
|
|
5
|
+
* inert. If any of the children happens to be a parent of one of the elements,
|
|
6
|
+
* then that child will not be marked as inert.
|
|
7
|
+
*
|
|
8
|
+
* E.g.:
|
|
9
|
+
*
|
|
10
|
+
* ```html
|
|
11
|
+
* <body> <!-- Stop at body -->
|
|
12
|
+
* <header></header> <!-- Inert, sibling of parent -->
|
|
13
|
+
* <main> <!-- Not inert, parent of allowed element -->
|
|
14
|
+
* <div>Sidebar</div> <!-- Inert, sibling of parent -->
|
|
15
|
+
* <div> <!-- Not inert, parent of allowed element -->
|
|
16
|
+
* <listbox> <!-- Not inert, parent of allowed element -->
|
|
17
|
+
* <button></button> <!-- Not inert, allowed element -->
|
|
18
|
+
* <options></options> <!-- Not inert, allowed element -->
|
|
19
|
+
* </listbox>
|
|
20
|
+
* </div>
|
|
21
|
+
* </main>
|
|
22
|
+
* <footer></footer> <!-- Inert, sibling of parent -->
|
|
23
|
+
* </body>
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function useInertOthers(options: {
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
elements?: {
|
|
29
|
+
allowed?: (HTMLElement | null)[];
|
|
30
|
+
disallowed?: (HTMLElement | null)[];
|
|
31
|
+
};
|
|
32
|
+
}): void;
|