@pzerelles/headlessui-svelte 2.0.0-next.1 → 2.1.1-next.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.
- package/dist/button/Button.svelte +65 -0
- package/dist/button/Button.svelte.d.ts +39 -0
- package/dist/button/index.d.ts +1 -0
- package/dist/button/index.js +1 -0
- package/dist/checkbox/Checkbox.svelte +60 -46
- package/dist/checkbox/Checkbox.svelte.d.ts +1 -1
- package/dist/close-button/CloseButton.svelte +10 -0
- package/dist/close-button/CloseButton.svelte.d.ts +25 -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/description/Description.svelte +50 -32
- package/dist/description/Description.svelte.d.ts +14 -5
- package/dist/field/Field.svelte +9 -9
- package/dist/fieldset/Fieldset.svelte +9 -9
- 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-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-top-layer.svelte.d.ts +29 -0
- package/dist/hooks/use-is-top-layer.svelte.js +82 -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-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-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 +252 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/internal/FocusSentinel.svelte +45 -0
- package/dist/internal/FocusSentinel.svelte.d.ts +17 -0
- package/dist/internal/FormFields.svelte +2 -4
- package/dist/internal/FormFields.svelte.d.ts +5 -6
- package/dist/internal/FormResolver.svelte +11 -16
- package/dist/internal/FormResolver.svelte.d.ts +2 -3
- package/dist/internal/Hidden.svelte +8 -8
- package/dist/internal/Hidden.svelte.d.ts +28 -19
- package/dist/internal/HoistFormFields.svelte.d.ts +1 -1
- package/dist/internal/Portal.svelte.d.ts +1 -1
- package/dist/internal/floating.svelte.d.ts +57 -0
- package/dist/internal/floating.svelte.js +477 -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 +53 -32
- package/dist/label/Label.svelte.d.ts +14 -5
- package/dist/legend/Legend.svelte.d.ts +1 -2
- package/dist/listbox/Listbox.svelte +451 -0
- package/dist/listbox/Listbox.svelte.d.ts +107 -0
- package/dist/listbox/ListboxButton.svelte +141 -0
- package/dist/listbox/ListboxButton.svelte.d.ts +41 -0
- package/dist/listbox/ListboxOption.svelte +138 -0
- package/dist/listbox/ListboxOption.svelte.d.ts +39 -0
- package/dist/listbox/ListboxOptions.svelte +267 -0
- package/dist/listbox/ListboxOptions.svelte.d.ts +39 -0
- package/dist/listbox/ListboxSelectedOption.svelte +25 -0
- package/dist/listbox/ListboxSelectedOption.svelte.d.ts +30 -0
- package/dist/listbox/index.d.ts +5 -0
- package/dist/listbox/index.js +5 -0
- package/dist/portal/InternalPortal.svelte +108 -0
- package/dist/portal/InternalPortal.svelte.d.ts +34 -0
- package/dist/portal/Portal.svelte +11 -0
- package/dist/portal/Portal.svelte.d.ts +23 -0
- package/dist/portal/PortalGroup.svelte +15 -0
- package/dist/portal/PortalGroup.svelte.d.ts +31 -0
- package/dist/switch/Switch.svelte +149 -0
- package/dist/switch/Switch.svelte.d.ts +44 -0
- package/dist/switch/SwitchGroup.svelte +38 -0
- package/dist/switch/SwitchGroup.svelte.d.ts +27 -0
- package/dist/switch/index.d.ts +2 -0
- package/dist/switch/index.js +2 -0
- package/dist/tabs/Button.svelte +65 -0
- package/dist/tabs/Button.svelte.d.ts +39 -0
- package/dist/tabs/Tab.svelte +161 -0
- package/dist/tabs/Tab.svelte.d.ts +36 -0
- package/dist/tabs/TabGroup.svelte +244 -0
- package/dist/tabs/TabGroup.svelte.d.ts +54 -0
- package/dist/tabs/TabList.svelte +18 -0
- package/dist/tabs/TabList.svelte.d.ts +28 -0
- package/dist/tabs/TabPanel.svelte +63 -0
- package/dist/tabs/TabPanel.svelte.d.ts +34 -0
- package/dist/tabs/TabPanels.svelte +13 -0
- package/dist/tabs/TabPanels.svelte.d.ts +27 -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/utils/StableCollection.svelte +43 -0
- package/dist/utils/StableCollection.svelte.d.ts +19 -0
- package/dist/utils/calculate-active-index.d.ts +25 -0
- package/dist/utils/calculate-active-index.js +74 -0
- package/dist/utils/close.d.ts +2 -0
- package/dist/utils/close.js +3 -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 +44 -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/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 +31 -0
- package/dist/utils/render.js +56 -0
- package/dist/utils/store.d.ts +11 -0
- package/dist/utils/store.js +20 -0
- package/dist/utils/types.d.ts +27 -0
- package/dist/utils/types.js +6 -0
- package/package.json +28 -21
- 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,24 @@
|
|
|
1
|
+
import { useDocumentOverflowLockedEffect } from "./document-overflow/use-document-overflow.svelte.js";
|
|
2
|
+
import { useIsTopLayer } from "./use-is-top-layer.svelte.js";
|
|
3
|
+
export function useScrollLock(options) {
|
|
4
|
+
const { enabled, ownerDocument, resolveAllowedContainers = () => [document.body] } = $derived(options);
|
|
5
|
+
const isTopLayer = useIsTopLayer({
|
|
6
|
+
get enabled() {
|
|
7
|
+
return enabled;
|
|
8
|
+
},
|
|
9
|
+
scope: "scroll-lock",
|
|
10
|
+
});
|
|
11
|
+
useDocumentOverflowLockedEffect({
|
|
12
|
+
get shouldBeLocked() {
|
|
13
|
+
return isTopLayer.value;
|
|
14
|
+
},
|
|
15
|
+
get doc() {
|
|
16
|
+
return ownerDocument;
|
|
17
|
+
},
|
|
18
|
+
get meta() {
|
|
19
|
+
return (meta) => ({
|
|
20
|
+
containers: [...(meta.containers ?? []), resolveAllowedContainers()],
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type MutableRefObject } from "../utils/ref.svelte.js";
|
|
2
|
+
declare const Optional: unique symbol;
|
|
3
|
+
export declare function optionalRef<T>(cb: (ref: T) => void, isOptional?: boolean): ((ref: T) => void) & {
|
|
4
|
+
[Optional]: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare function useSyncRefs<TType>(...refs: (MutableRefObject<TType | null> | ((instance: TType) => void) | null)[]): ((value: TType) => void) | undefined;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useRef } from "../utils/ref.svelte.js";
|
|
2
|
+
const Optional = Symbol();
|
|
3
|
+
export function optionalRef(cb, isOptional = true) {
|
|
4
|
+
return Object.assign(cb, { [Optional]: isOptional });
|
|
5
|
+
}
|
|
6
|
+
export function useSyncRefs(...refs) {
|
|
7
|
+
let syncRefs = (value) => {
|
|
8
|
+
for (let ref of refs) {
|
|
9
|
+
if (ref == null)
|
|
10
|
+
continue;
|
|
11
|
+
if (typeof ref === "function")
|
|
12
|
+
ref(value);
|
|
13
|
+
else
|
|
14
|
+
ref.current = value;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
return refs.every((ref) => ref == null ||
|
|
18
|
+
// @ts-expect-error
|
|
19
|
+
ref?.[Optional])
|
|
20
|
+
? undefined
|
|
21
|
+
: syncRefs;
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getTextValue } from "../utils/get-text-value.js";
|
|
2
|
+
export function useTextValue(options) {
|
|
3
|
+
const { element } = $derived(options);
|
|
4
|
+
let cacheKey = $state("");
|
|
5
|
+
let cacheValue = $state("");
|
|
6
|
+
return () => {
|
|
7
|
+
if (!element)
|
|
8
|
+
return "";
|
|
9
|
+
// Check for a cached version
|
|
10
|
+
let currentKey = element.innerText;
|
|
11
|
+
if (cacheKey === currentKey) {
|
|
12
|
+
return cacheValue;
|
|
13
|
+
}
|
|
14
|
+
// Calculate the value
|
|
15
|
+
let value = getTextValue(element).trim().toLowerCase();
|
|
16
|
+
cacheKey = currentKey;
|
|
17
|
+
cacheValue = value;
|
|
18
|
+
return value;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BROWSER } from "esm-env";
|
|
2
|
+
function eventToPosition(evt) {
|
|
3
|
+
return [evt.screenX, evt.screenY];
|
|
4
|
+
}
|
|
5
|
+
export function useTrackedPointer() {
|
|
6
|
+
let lastPos = [-1, -1];
|
|
7
|
+
return {
|
|
8
|
+
wasMoved(evt) {
|
|
9
|
+
// FIXME: Remove this once we use browser testing in all the relevant places.
|
|
10
|
+
// NOTE: This is replaced with a compile-time define during the build process
|
|
11
|
+
// This hack exists to work around a few failing tests caused by our inability to "move" the virtual pointer in JSDOM pointer events.
|
|
12
|
+
if (!BROWSER && process.env.TEST_BYPASS_TRACKED_POINTER) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
let newPos = eventToPosition(evt);
|
|
16
|
+
if (lastPos[0] === newPos[0] && lastPos[1] === newPos[1]) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
lastPos = newPos;
|
|
20
|
+
return true;
|
|
21
|
+
},
|
|
22
|
+
update(evt) {
|
|
23
|
+
lastPos = eventToPosition(evt);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
type TransitionData = {
|
|
2
|
+
closed?: boolean;
|
|
3
|
+
enter?: boolean;
|
|
4
|
+
leave?: boolean;
|
|
5
|
+
transition?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function transitionDataAttributes(data: TransitionData): Record<string, string>;
|
|
8
|
+
export declare function useTransition(options: {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
element: HTMLElement | null | undefined;
|
|
11
|
+
show: boolean;
|
|
12
|
+
events?: {
|
|
13
|
+
start?(show: boolean): void;
|
|
14
|
+
end?(show: boolean): void;
|
|
15
|
+
};
|
|
16
|
+
}): {
|
|
17
|
+
readonly visible: boolean;
|
|
18
|
+
readonly data: TransitionData;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { disposables, useDisposables } from "../utils/disposables.js";
|
|
2
|
+
import { once } from "../utils/once.js";
|
|
3
|
+
import { untrack } from "svelte";
|
|
4
|
+
import { useFlags } from "./use-flags.svelte.js";
|
|
5
|
+
/**
|
|
6
|
+
* ```
|
|
7
|
+
* ┌──────┐ │ ┌──────────────┐
|
|
8
|
+
* │Closed│ │ │Closed │
|
|
9
|
+
* └──────┘ │ └──────────────┘
|
|
10
|
+
* ┌──────┐┌──────┐┌──────┐│┌──────┐┌──────┐┌──────┐
|
|
11
|
+
* │Frame ││Frame ││Frame │││Frame ││Frame ││Frame │
|
|
12
|
+
* └──────┘└──────┘└──────┘│└──────┘└──────┘└──────┘
|
|
13
|
+
* ┌──────────────────────┐│┌──────────────────────┐
|
|
14
|
+
* │Enter │││Leave │
|
|
15
|
+
* └──────────────────────┘│└──────────────────────┘
|
|
16
|
+
* ┌──────────────────────┐│┌──────────────────────┐
|
|
17
|
+
* │Transition │││Transition │
|
|
18
|
+
* ├──────────────────────┘│└──────────────────────┘
|
|
19
|
+
* │
|
|
20
|
+
* └─ Applied when `Enter` or `Leave` is applied.
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
var TransitionState;
|
|
24
|
+
(function (TransitionState) {
|
|
25
|
+
TransitionState[TransitionState["None"] = 0] = "None";
|
|
26
|
+
TransitionState[TransitionState["Closed"] = 1] = "Closed";
|
|
27
|
+
TransitionState[TransitionState["Enter"] = 2] = "Enter";
|
|
28
|
+
TransitionState[TransitionState["Leave"] = 4] = "Leave";
|
|
29
|
+
})(TransitionState || (TransitionState = {}));
|
|
30
|
+
export function transitionDataAttributes(data) {
|
|
31
|
+
let attributes = {};
|
|
32
|
+
for (let key in data) {
|
|
33
|
+
if (data[key] === true) {
|
|
34
|
+
attributes[`data-${key}`] = "";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return attributes;
|
|
38
|
+
}
|
|
39
|
+
export function useTransition(options) {
|
|
40
|
+
const { enabled, element, show, events } = $derived(options);
|
|
41
|
+
let visible = $state(show);
|
|
42
|
+
let flags = $state(enabled && visible ? TransitionState.Enter | TransitionState.Closed : TransitionState.None);
|
|
43
|
+
let inFlight = $state(false);
|
|
44
|
+
let cancelled = $state(false);
|
|
45
|
+
const d = useDisposables();
|
|
46
|
+
function retry(enabled, show, node, d) {
|
|
47
|
+
if (!enabled)
|
|
48
|
+
return;
|
|
49
|
+
if (show) {
|
|
50
|
+
visible = true;
|
|
51
|
+
}
|
|
52
|
+
if (!node) {
|
|
53
|
+
// Retry if the DOM node isn't available yet
|
|
54
|
+
if (show) {
|
|
55
|
+
flags |= TransitionState.Enter | TransitionState.Closed;
|
|
56
|
+
return d.nextFrame(() => retry(enabled, show, node, d));
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
events?.start?.(show);
|
|
61
|
+
return transition(node, {
|
|
62
|
+
inFlight,
|
|
63
|
+
prepare() {
|
|
64
|
+
if (cancelled) {
|
|
65
|
+
// Cancelled a cancellation, we're back to the original state.
|
|
66
|
+
cancelled = false;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// If we were already in-flight, then we want to cancel the current
|
|
70
|
+
// transition.
|
|
71
|
+
cancelled = inFlight;
|
|
72
|
+
}
|
|
73
|
+
inFlight = true;
|
|
74
|
+
if (cancelled)
|
|
75
|
+
return;
|
|
76
|
+
if (show) {
|
|
77
|
+
flags = TransitionState.Enter | TransitionState.Closed;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
flags = TransitionState.Leave | (flags & TransitionState.Closed);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
run() {
|
|
84
|
+
if (cancelled) {
|
|
85
|
+
// If we cancelled a transition, then the `show` state is going to
|
|
86
|
+
// be inverted already, but that doesn't mean we have to go to that
|
|
87
|
+
// new state.
|
|
88
|
+
//
|
|
89
|
+
// What we actually want is to revert to the "idle" state (the
|
|
90
|
+
// stable state where an `Enter` transitions to, and a `Leave`
|
|
91
|
+
// transitions from.)
|
|
92
|
+
//
|
|
93
|
+
// Because of this, it might look like we are swapping the flags in
|
|
94
|
+
// the following branches, but that's not the case.
|
|
95
|
+
if (!show) {
|
|
96
|
+
flags = TransitionState.Leave | TransitionState.Closed;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
flags = TransitionState.Enter | TransitionState.Closed;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
if (show) {
|
|
104
|
+
flags = flags & ~TransitionState.Closed;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
flags |= TransitionState.Closed;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
done() {
|
|
112
|
+
if (cancelled) {
|
|
113
|
+
if (typeof node.getAnimations === "function" && node.getAnimations().length > 0) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
inFlight = false;
|
|
118
|
+
flags = 0;
|
|
119
|
+
if (!show) {
|
|
120
|
+
visible = false;
|
|
121
|
+
}
|
|
122
|
+
events?.end?.(show);
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
$effect(() => {
|
|
127
|
+
;
|
|
128
|
+
[enabled, show, element, d];
|
|
129
|
+
return untrack(() => retry(enabled, show, element, d));
|
|
130
|
+
});
|
|
131
|
+
const data = $derived({
|
|
132
|
+
closed: enabled ? !!(flags & TransitionState.Closed) : undefined,
|
|
133
|
+
enter: enabled ? !!(flags & TransitionState.Enter) : undefined,
|
|
134
|
+
leave: enabled ? !!(flags & TransitionState.Leave) : undefined,
|
|
135
|
+
transition: enabled ? !!(flags & (TransitionState.Enter | TransitionState.Leave)) : undefined,
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
get visible() {
|
|
139
|
+
return enabled ? visible : show;
|
|
140
|
+
},
|
|
141
|
+
get data() {
|
|
142
|
+
return data;
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function transition(node, { prepare, run, done, inFlight, }) {
|
|
147
|
+
const d = disposables();
|
|
148
|
+
// Prepare the transitions by ensuring that all the "before" classes are
|
|
149
|
+
// applied and flushed to the DOM.
|
|
150
|
+
prepareTransition(node, {
|
|
151
|
+
prepare,
|
|
152
|
+
inFlight,
|
|
153
|
+
});
|
|
154
|
+
// This is a workaround for a bug in all major browsers.
|
|
155
|
+
//
|
|
156
|
+
// 1. When an element is just mounted
|
|
157
|
+
// 2. And you apply a transition to it (e.g.: via a class)
|
|
158
|
+
// 3. And you're using `getComputedStyle` and read any returned value
|
|
159
|
+
// 4. Then the `transition` immediately jumps to the end state
|
|
160
|
+
//
|
|
161
|
+
// This means that no transition happens at all. To fix this, we delay the
|
|
162
|
+
// actual transition by one frame.
|
|
163
|
+
d.nextFrame(() => {
|
|
164
|
+
// Wait for the transition, once the transition is complete we can cleanup.
|
|
165
|
+
// This is registered first to prevent race conditions, otherwise it could
|
|
166
|
+
// happen that the transition is already done before we start waiting for
|
|
167
|
+
// the actual event.
|
|
168
|
+
d.add(waitForTransition(node, done));
|
|
169
|
+
// Initiate the transition by applying the new classes.
|
|
170
|
+
run();
|
|
171
|
+
});
|
|
172
|
+
return d.dispose;
|
|
173
|
+
}
|
|
174
|
+
function waitForTransition(node, _done) {
|
|
175
|
+
let done = once(_done);
|
|
176
|
+
let d = disposables();
|
|
177
|
+
if (!node)
|
|
178
|
+
return d.dispose;
|
|
179
|
+
// Safari returns a comma separated list of values, so let's sort them and take the highest value.
|
|
180
|
+
let { transitionDuration, transitionDelay } = getComputedStyle(node);
|
|
181
|
+
let [durationMs, delayMs] = [transitionDuration, transitionDelay].map((value) => {
|
|
182
|
+
let [resolvedValue = 0] = value
|
|
183
|
+
.split(",")
|
|
184
|
+
// Remove falsy we can't work with
|
|
185
|
+
.filter(Boolean)
|
|
186
|
+
// Values are returned as `0.3s` or `75ms`
|
|
187
|
+
.map((v) => (v.includes("ms") ? parseFloat(v) : parseFloat(v) * 1000))
|
|
188
|
+
.sort((a, z) => z - a);
|
|
189
|
+
return resolvedValue;
|
|
190
|
+
});
|
|
191
|
+
let totalDuration = durationMs + delayMs;
|
|
192
|
+
if (totalDuration !== 0) {
|
|
193
|
+
if (process.env.NODE_ENV === "test") {
|
|
194
|
+
let dispose = d.setTimeout(() => {
|
|
195
|
+
done();
|
|
196
|
+
dispose();
|
|
197
|
+
}, totalDuration);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
let disposeGroup = d.group((d) => {
|
|
201
|
+
// Mark the transition as done when the timeout is reached. This is a fallback in case the
|
|
202
|
+
// transitionrun event is not fired.
|
|
203
|
+
let cancelTimeout = d.setTimeout(() => {
|
|
204
|
+
done();
|
|
205
|
+
d.dispose();
|
|
206
|
+
}, totalDuration);
|
|
207
|
+
// The moment the transitionrun event fires, we should cleanup the timeout fallback, because
|
|
208
|
+
// then we know that we can use the native transition events because something is
|
|
209
|
+
// transitioning.
|
|
210
|
+
d.addEventListener(node, "transitionrun", (event) => {
|
|
211
|
+
if (event.target !== event.currentTarget)
|
|
212
|
+
return;
|
|
213
|
+
cancelTimeout();
|
|
214
|
+
d.addEventListener(node, "transitioncancel", (event) => {
|
|
215
|
+
if (event.target !== event.currentTarget)
|
|
216
|
+
return;
|
|
217
|
+
done();
|
|
218
|
+
disposeGroup();
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
d.addEventListener(node, "transitionend", (event) => {
|
|
223
|
+
if (event.target !== event.currentTarget)
|
|
224
|
+
return;
|
|
225
|
+
done();
|
|
226
|
+
d.dispose();
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
// No transition is happening, so we should cleanup already. Otherwise we have to wait until we
|
|
232
|
+
// get disposed.
|
|
233
|
+
done();
|
|
234
|
+
}
|
|
235
|
+
return d.dispose;
|
|
236
|
+
}
|
|
237
|
+
function prepareTransition(node, { inFlight, prepare }) {
|
|
238
|
+
// If we are already transitioning, then we don't need to force cancel the
|
|
239
|
+
// current transition (by triggering a reflow).
|
|
240
|
+
if (inFlight) {
|
|
241
|
+
prepare();
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
let previous = node.style.transition;
|
|
245
|
+
// Force cancel current transition
|
|
246
|
+
node.style.transition = "none";
|
|
247
|
+
prepare();
|
|
248
|
+
// Trigger a reflow, flushing the CSS changes
|
|
249
|
+
node.offsetHeight;
|
|
250
|
+
// Reset the transition to what it was before
|
|
251
|
+
node.style.transition = previous;
|
|
252
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
export * from "./button/index.js";
|
|
1
2
|
export * from "./checkbox/index.js";
|
|
2
3
|
export * from "./description/index.js";
|
|
3
4
|
export * from "./field/index.js";
|
|
4
5
|
export * from "./fieldset/index.js";
|
|
5
6
|
export * from "./label/index.js";
|
|
6
7
|
export * from "./legend/index.js";
|
|
8
|
+
export * from "./listbox/index.js";
|
|
9
|
+
export * from "./switch/index.js";
|
|
10
|
+
export * from "./tabs/index.js";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
export * from "./button/index.js";
|
|
1
2
|
export * from "./checkbox/index.js";
|
|
2
3
|
export * from "./description/index.js";
|
|
3
4
|
export * from "./field/index.js";
|
|
4
5
|
export * from "./fieldset/index.js";
|
|
5
6
|
export * from "./label/index.js";
|
|
6
7
|
export * from "./legend/index.js";
|
|
8
|
+
export * from "./listbox/index.js";
|
|
9
|
+
export * from "./switch/index.js";
|
|
10
|
+
export * from "./tabs/index.js";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">import { onMount } from "svelte";
|
|
2
|
+
import Hidden, { HiddenFeatures } from "./Hidden.svelte";
|
|
3
|
+
let { onfocus } = $props();
|
|
4
|
+
let enabled = $state(true);
|
|
5
|
+
let mounted = $state(false);
|
|
6
|
+
onMount(() => {
|
|
7
|
+
mounted = true;
|
|
8
|
+
});
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
{#if enabled}
|
|
12
|
+
<Hidden
|
|
13
|
+
as="button"
|
|
14
|
+
type="button"
|
|
15
|
+
features={HiddenFeatures.Focusable}
|
|
16
|
+
onfocus={(event: FocusEvent) => {
|
|
17
|
+
event.preventDefault()
|
|
18
|
+
let frame: ReturnType<typeof requestAnimationFrame>
|
|
19
|
+
|
|
20
|
+
let tries = 50
|
|
21
|
+
function forwardFocus() {
|
|
22
|
+
// Prevent infinite loops
|
|
23
|
+
if (tries-- <= 0) {
|
|
24
|
+
if (frame) cancelAnimationFrame(frame)
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Try to move focus to the correct element. This depends on the implementation
|
|
29
|
+
// of `onFocus` of course since it would be different for each place we use it in.
|
|
30
|
+
if (onfocus?.()) {
|
|
31
|
+
cancelAnimationFrame(frame)
|
|
32
|
+
if (!mounted) return
|
|
33
|
+
|
|
34
|
+
enabled = false
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Retry
|
|
39
|
+
frame = requestAnimationFrame(forwardFocus)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
frame = requestAnimationFrame(forwardFocus)
|
|
43
|
+
}}
|
|
44
|
+
/>
|
|
45
|
+
{/if}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: Props & {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports;
|
|
9
|
+
z_$$bindings?: Bindings;
|
|
10
|
+
}
|
|
11
|
+
declare const FocusSentinel: $$__sveltets_2_IsomorphicComponent<{
|
|
12
|
+
onfocus: () => boolean;
|
|
13
|
+
}, {
|
|
14
|
+
[evt: string]: CustomEvent<any>;
|
|
15
|
+
}, {}, {}, "">;
|
|
16
|
+
type FocusSentinel = InstanceType<typeof FocusSentinel>;
|
|
17
|
+
export default FocusSentinel;
|
|
@@ -14,10 +14,8 @@ let {
|
|
|
14
14
|
let form = $state(null);
|
|
15
15
|
const d = disposables();
|
|
16
16
|
$effect(() => {
|
|
17
|
-
if (!onReset)
|
|
18
|
-
|
|
19
|
-
if (!form)
|
|
20
|
-
return;
|
|
17
|
+
if (!onReset) return;
|
|
18
|
+
if (!form) return;
|
|
21
19
|
return d.addEventListener(form, "reset", onReset);
|
|
22
20
|
});
|
|
23
21
|
</script>
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
1
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
2
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
3
|
$$bindings?: Bindings;
|
|
@@ -11,12 +10,12 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
11
10
|
}
|
|
12
11
|
declare const FormFields: $$__sveltets_2_IsomorphicComponent<{
|
|
13
12
|
data: Record<string, any>;
|
|
14
|
-
overrides?: Record<string, any
|
|
15
|
-
form?: string
|
|
16
|
-
disabled?: boolean
|
|
17
|
-
onReset?: (
|
|
13
|
+
overrides?: Record<string, any>;
|
|
14
|
+
form?: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
onReset?: (e: Event) => void;
|
|
18
17
|
}, {
|
|
19
18
|
[evt: string]: CustomEvent<any>;
|
|
20
|
-
}, {},
|
|
19
|
+
}, {}, {}, "">;
|
|
21
20
|
type FormFields = InstanceType<typeof FormFields>;
|
|
22
21
|
export default FormFields;
|
|
@@ -1,25 +1,20 @@
|
|
|
1
|
-
<script lang="ts">import
|
|
1
|
+
<script lang="ts">import { onMount } from "svelte";
|
|
2
|
+
import Hidden, { HiddenFeatures } from "./Hidden.svelte";
|
|
2
3
|
let { setForm, formId } = $props();
|
|
3
4
|
$effect(() => {
|
|
4
5
|
if (formId) {
|
|
5
|
-
|
|
6
|
-
if (resolvedForm)
|
|
7
|
-
setForm(resolvedForm);
|
|
6
|
+
const resolvedForm = document.getElementById(formId);
|
|
7
|
+
if (resolvedForm) setForm(resolvedForm);
|
|
8
8
|
}
|
|
9
9
|
});
|
|
10
|
+
let element = $state();
|
|
11
|
+
onMount(() => {
|
|
12
|
+
if (!element) return;
|
|
13
|
+
const resolvedForm = element.closest("form");
|
|
14
|
+
if (resolvedForm) setForm(resolvedForm);
|
|
15
|
+
});
|
|
10
16
|
</script>
|
|
11
17
|
|
|
12
18
|
{#if !formId}
|
|
13
|
-
<Hidden
|
|
14
|
-
features={HiddenFeatures.Hidden}
|
|
15
|
-
as="input"
|
|
16
|
-
type="hidden"
|
|
17
|
-
hidden
|
|
18
|
-
readonly
|
|
19
|
-
ref={(el) => {
|
|
20
|
-
if (!el) return
|
|
21
|
-
let resolvedForm = el.closest("form")
|
|
22
|
-
if (resolvedForm) setForm(resolvedForm)
|
|
23
|
-
}}
|
|
24
|
-
/>
|
|
19
|
+
<Hidden features={HiddenFeatures.Hidden} as="input" type="hidden" hidden readonly bind:ref={element} />
|
|
25
20
|
{/if}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
1
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
2
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
3
|
$$bindings?: Bindings;
|
|
@@ -11,9 +10,9 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
11
10
|
}
|
|
12
11
|
declare const FormResolver: $$__sveltets_2_IsomorphicComponent<{
|
|
13
12
|
setForm: (form: HTMLFormElement) => void;
|
|
14
|
-
formId?: string
|
|
13
|
+
formId?: string;
|
|
15
14
|
}, {
|
|
16
15
|
[evt: string]: CustomEvent<any>;
|
|
17
|
-
}, {},
|
|
16
|
+
}, {}, {}, "">;
|
|
18
17
|
type FormResolver = InstanceType<typeof FormResolver>;
|
|
19
18
|
export default FormResolver;
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
HiddenFeatures2[HiddenFeatures2["Hidden"] = 4] = "Hidden";
|
|
5
5
|
return HiddenFeatures2;
|
|
6
6
|
})(HiddenFeatures || {});
|
|
7
|
+
const DEFAULT_VISUALLY_HIDDEN_TAG = "div";
|
|
7
8
|
</script>
|
|
8
9
|
|
|
9
|
-
<script lang="ts"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
});
|
|
10
|
+
<script lang="ts" generics="TTag extends keyof SvelteHTMLElements">let {
|
|
11
|
+
as = DEFAULT_VISUALLY_HIDDEN_TAG,
|
|
12
|
+
ref = $bindable(),
|
|
13
|
+
features = HiddenFeatures.None,
|
|
14
|
+
...theirProps
|
|
15
|
+
} = $props();
|
|
16
16
|
let ourProps = {
|
|
17
17
|
"aria-hidden": (features & HiddenFeatures.Focusable) === HiddenFeatures.Focusable ? true : theirProps["aria-hidden"] ?? void 0,
|
|
18
18
|
hidden: (features & HiddenFeatures.Hidden) === HiddenFeatures.Hidden ? true : void 0,
|
|
@@ -33,4 +33,4 @@ let ourProps = {
|
|
|
33
33
|
};
|
|
34
34
|
</script>
|
|
35
35
|
|
|
36
|
-
<svelte:element this={as} {
|
|
36
|
+
<svelte:element this={as} bind:this={ref} {...ourProps} {...theirProps} />
|
|
@@ -1,26 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
import type { HTMLElementType, Props } from "../utils/types.js";
|
|
2
|
+
import type { SvelteHTMLElements } from "svelte/elements";
|
|
2
3
|
export declare enum HiddenFeatures {
|
|
3
4
|
None = 1,
|
|
4
5
|
Focusable = 2,
|
|
5
6
|
Hidden = 4
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
declare const DEFAULT_VISUALLY_HIDDEN_TAG: "div";
|
|
9
|
+
type HiddenRenderPropArg = {};
|
|
10
|
+
type HiddenPropsWeControl = never;
|
|
11
|
+
export type HiddenProps<TTag extends keyof SvelteHTMLElements = typeof DEFAULT_VISUALLY_HIDDEN_TAG> = Props<TTag, HiddenRenderPropArg, HiddenPropsWeControl, {
|
|
12
|
+
features?: HiddenFeatures;
|
|
13
|
+
ref?: HTMLElementType<TTag> | null;
|
|
14
|
+
}>;
|
|
15
|
+
declare class __sveltets_Render<TTag extends keyof SvelteHTMLElements> {
|
|
16
|
+
props(): HiddenProps<TTag>;
|
|
17
|
+
events(): {} & {
|
|
18
|
+
[evt: string]: CustomEvent<any>;
|
|
19
|
+
};
|
|
20
|
+
slots(): {};
|
|
21
|
+
bindings(): "ref";
|
|
22
|
+
exports(): {};
|
|
17
23
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
24
|
+
interface $$IsomorphicComponent {
|
|
25
|
+
new <TTag extends keyof SvelteHTMLElements>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TTag>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TTag>['props']>, ReturnType<__sveltets_Render<TTag>['events']>, ReturnType<__sveltets_Render<TTag>['slots']>> & {
|
|
26
|
+
$$bindings?: ReturnType<__sveltets_Render<TTag>['bindings']>;
|
|
27
|
+
} & ReturnType<__sveltets_Render<TTag>['exports']>;
|
|
28
|
+
<TTag extends keyof SvelteHTMLElements>(internal: unknown, props: ReturnType<__sveltets_Render<TTag>['props']> & {
|
|
29
|
+
$$events?: ReturnType<__sveltets_Render<TTag>['events']>;
|
|
30
|
+
}): ReturnType<__sveltets_Render<TTag>['exports']>;
|
|
31
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
32
|
+
}
|
|
33
|
+
declare const Hidden: $$IsomorphicComponent;
|
|
34
|
+
type Hidden<TTag extends keyof SvelteHTMLElements> = InstanceType<typeof Hidden<TTag>>;
|
|
26
35
|
export default Hidden;
|
|
@@ -13,6 +13,6 @@ declare const HoistFormFields: $$__sveltets_2_IsomorphicComponent<{
|
|
|
13
13
|
children: Snippet;
|
|
14
14
|
}, {
|
|
15
15
|
[evt: string]: CustomEvent<any>;
|
|
16
|
-
}, {},
|
|
16
|
+
}, {}, {}, "">;
|
|
17
17
|
type HoistFormFields = InstanceType<typeof HoistFormFields>;
|
|
18
18
|
export default HoistFormFields;
|