@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
|
@@ -13,12 +13,13 @@
|
|
|
13
13
|
// Original licensing for the following can be found in the
|
|
14
14
|
// NOTICE file in the root directory of this source tree.
|
|
15
15
|
// See https://github.com/facebook/react/tree/cc7c1aece46a6b69b41958d731e0fd27c94bfc6c/packages/react-interactions
|
|
16
|
-
import {
|
|
16
|
+
import { getOwnerWindow } from "./dom.js";
|
|
17
17
|
import { isVirtualClick } from "./isVirtualEvent.js";
|
|
18
|
+
import { getOwnerDocument } from "./owner.js";
|
|
18
19
|
import { isMac } from "./platform.js";
|
|
19
20
|
let currentModality = null;
|
|
20
|
-
|
|
21
|
-
export
|
|
21
|
+
const changeHandlers = new Set();
|
|
22
|
+
export const hasSetupGlobalListeners = new Map(); // We use a map here to support setting event listeners across multiple document objects.
|
|
22
23
|
let hasEventBeforeFocus = false;
|
|
23
24
|
let hasBlurredWindowRecently = false;
|
|
24
25
|
// Only Tab or Esc keys will make focus visible on text input elements
|
|
@@ -27,7 +28,7 @@ const FOCUS_VISIBLE_INPUT_KEYS = {
|
|
|
27
28
|
Escape: true,
|
|
28
29
|
};
|
|
29
30
|
function triggerChangeHandlers(modality, e) {
|
|
30
|
-
for (
|
|
31
|
+
for (const handler of changeHandlers) {
|
|
31
32
|
handler(modality, e);
|
|
32
33
|
}
|
|
33
34
|
}
|
|
@@ -98,27 +99,31 @@ function setupGlobalFocusEvents(element) {
|
|
|
98
99
|
// However, we need to detect other cases when a focus event occurs without
|
|
99
100
|
// a preceding user event (e.g. screen reader focus). Overriding the focus
|
|
100
101
|
// method on HTMLElement.prototype is a bit hacky, but works.
|
|
101
|
-
|
|
102
|
-
windowObject.HTMLElement.prototype.focus = function () {
|
|
102
|
+
const focus = windowObject.HTMLElement.prototype.focus;
|
|
103
|
+
windowObject.HTMLElement.prototype.focus = function (...args) {
|
|
103
104
|
hasEventBeforeFocus = true;
|
|
104
|
-
focus.apply(this,
|
|
105
|
+
focus.apply(this, args);
|
|
105
106
|
};
|
|
106
|
-
documentObject
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
if (documentObject) {
|
|
108
|
+
documentObject.addEventListener("keydown", handleKeyboardEvent, true);
|
|
109
|
+
documentObject.addEventListener("keyup", handleKeyboardEvent, true);
|
|
110
|
+
documentObject.addEventListener("click", handleClickEvent, true);
|
|
111
|
+
}
|
|
109
112
|
// Register focus events on the window so they are sure to happen
|
|
110
113
|
// before React's event listeners (registered on the document).
|
|
111
114
|
windowObject.addEventListener("focus", handleFocusEvent, true);
|
|
112
115
|
windowObject.addEventListener("blur", handleWindowBlur, false);
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
if (documentObject) {
|
|
117
|
+
if (typeof PointerEvent !== "undefined") {
|
|
118
|
+
documentObject.addEventListener("pointerdown", handlePointerEvent, true);
|
|
119
|
+
documentObject.addEventListener("pointermove", handlePointerEvent, true);
|
|
120
|
+
documentObject.addEventListener("pointerup", handlePointerEvent, true);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
documentObject.addEventListener("mousedown", handlePointerEvent, true);
|
|
124
|
+
documentObject.addEventListener("mousemove", handlePointerEvent, true);
|
|
125
|
+
documentObject.addEventListener("mouseup", handlePointerEvent, true);
|
|
126
|
+
}
|
|
122
127
|
}
|
|
123
128
|
// Add unmount handler
|
|
124
129
|
windowObject.addEventListener("beforeunload", () => {
|
|
@@ -129,27 +134,31 @@ function setupGlobalFocusEvents(element) {
|
|
|
129
134
|
const tearDownWindowFocusTracking = (element, loadListener) => {
|
|
130
135
|
const windowObject = getOwnerWindow(element);
|
|
131
136
|
const documentObject = getOwnerDocument(element);
|
|
132
|
-
if (loadListener) {
|
|
137
|
+
if (loadListener && documentObject) {
|
|
133
138
|
documentObject.removeEventListener("DOMContentLoaded", loadListener);
|
|
134
139
|
}
|
|
135
140
|
if (!hasSetupGlobalListeners.has(windowObject)) {
|
|
136
141
|
return;
|
|
137
142
|
}
|
|
138
143
|
windowObject.HTMLElement.prototype.focus = hasSetupGlobalListeners.get(windowObject).focus;
|
|
139
|
-
documentObject
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
if (documentObject) {
|
|
145
|
+
documentObject.removeEventListener("keydown", handleKeyboardEvent, true);
|
|
146
|
+
documentObject.removeEventListener("keyup", handleKeyboardEvent, true);
|
|
147
|
+
documentObject.removeEventListener("click", handleClickEvent, true);
|
|
148
|
+
}
|
|
142
149
|
windowObject.removeEventListener("focus", handleFocusEvent, true);
|
|
143
150
|
windowObject.removeEventListener("blur", handleWindowBlur, false);
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
if (documentObject) {
|
|
152
|
+
if (typeof PointerEvent !== "undefined") {
|
|
153
|
+
documentObject.removeEventListener("pointerdown", handlePointerEvent, true);
|
|
154
|
+
documentObject.removeEventListener("pointermove", handlePointerEvent, true);
|
|
155
|
+
documentObject.removeEventListener("pointerup", handlePointerEvent, true);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
documentObject.removeEventListener("mousedown", handlePointerEvent, true);
|
|
159
|
+
documentObject.removeEventListener("mousemove", handlePointerEvent, true);
|
|
160
|
+
documentObject.removeEventListener("mouseup", handlePointerEvent, true);
|
|
161
|
+
}
|
|
153
162
|
}
|
|
154
163
|
hasSetupGlobalListeners.delete(windowObject);
|
|
155
164
|
};
|
|
@@ -173,14 +182,16 @@ const tearDownWindowFocusTracking = (element, loadListener) => {
|
|
|
173
182
|
export function addWindowFocusTracking(element) {
|
|
174
183
|
const documentObject = getOwnerDocument(element);
|
|
175
184
|
let loadListener;
|
|
176
|
-
if (documentObject
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
loadListener = () => {
|
|
185
|
+
if (documentObject) {
|
|
186
|
+
if (documentObject.readyState !== "loading") {
|
|
181
187
|
setupGlobalFocusEvents(element);
|
|
182
|
-
}
|
|
183
|
-
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
loadListener = () => {
|
|
191
|
+
setupGlobalFocusEvents(element);
|
|
192
|
+
};
|
|
193
|
+
documentObject.addEventListener("DOMContentLoaded", loadListener);
|
|
194
|
+
}
|
|
184
195
|
}
|
|
185
196
|
return () => tearDownWindowFocusTracking(element, loadListener);
|
|
186
197
|
}
|
|
@@ -246,8 +257,8 @@ function isKeyboardFocusEvent(isTextInput, modality, e) {
|
|
|
246
257
|
* Manages focus visible state for the page, and subscribes individual components for updates.
|
|
247
258
|
*/
|
|
248
259
|
/*export function useFocusVisible(props: FocusVisibleProps = {}): FocusVisibleResult {
|
|
249
|
-
let { isTextInput,
|
|
250
|
-
let [isFocusVisibleState, setFocusVisible] = useState(
|
|
260
|
+
let { isTextInput, autofocus } = props
|
|
261
|
+
let [isFocusVisibleState, setFocusVisible] = useState(autofocus || isFocusVisible())
|
|
251
262
|
useFocusVisibleListener(
|
|
252
263
|
(isFocusVisible) => {
|
|
253
264
|
setFocusVisible(isFocusVisible)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getTextValue(element: HTMLElement): string;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
let emojiRegex = /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;
|
|
2
|
+
function getTextContents(element) {
|
|
3
|
+
// Using innerText instead of textContent because:
|
|
4
|
+
//
|
|
5
|
+
// > textContent gets the content of all elements, including <script> and <style> elements. In
|
|
6
|
+
// > contrast, innerText only shows "human-readable" elements.
|
|
7
|
+
// >
|
|
8
|
+
// > — https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent#differences_from_innertext
|
|
9
|
+
let currentInnerText = element.innerText ?? "";
|
|
10
|
+
// Remove all the elements that shouldn't be there.
|
|
11
|
+
//
|
|
12
|
+
// [hidden] — The user doesn't see it
|
|
13
|
+
// [aria-hidden] — The screen reader doesn't see it
|
|
14
|
+
// [role="img"] — Even if it is text, it is used as an image
|
|
15
|
+
//
|
|
16
|
+
// This is probably the slowest part, but if you want complete control over the text value, then
|
|
17
|
+
// it is better to set an `aria-label` instead.
|
|
18
|
+
let copy = element.cloneNode(true);
|
|
19
|
+
if (!(copy instanceof HTMLElement)) {
|
|
20
|
+
return currentInnerText;
|
|
21
|
+
}
|
|
22
|
+
let dropped = false;
|
|
23
|
+
// Drop the elements that shouldn't be there.
|
|
24
|
+
for (let child of copy.querySelectorAll('[hidden],[aria-hidden],[role="img"]')) {
|
|
25
|
+
child.remove();
|
|
26
|
+
dropped = true;
|
|
27
|
+
}
|
|
28
|
+
// Now that the elements are removed, we can get the innerText such that we can strip the emojis.
|
|
29
|
+
let value = dropped ? copy.innerText ?? "" : currentInnerText;
|
|
30
|
+
// Check if it contains some emojis or not, if so, we need to remove them
|
|
31
|
+
// because ideally we work with simple text values.
|
|
32
|
+
//
|
|
33
|
+
// Ideally we can use the much simpler RegEx: /\p{Extended_Pictographic}/u
|
|
34
|
+
// but we can't rely on this yet, so we use the more complex one.
|
|
35
|
+
if (emojiRegex.test(value)) {
|
|
36
|
+
value = value.replace(emojiRegex, "");
|
|
37
|
+
}
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
export function getTextValue(element) {
|
|
41
|
+
// Try to use the `aria-label` first
|
|
42
|
+
let label = element.getAttribute("aria-label");
|
|
43
|
+
if (typeof label === "string")
|
|
44
|
+
return label.trim();
|
|
45
|
+
// Try to use the `aria-labelledby` second
|
|
46
|
+
let labelledby = element.getAttribute("aria-labelledby");
|
|
47
|
+
if (labelledby) {
|
|
48
|
+
// aria-labelledby can be a space-separated list of IDs, so we need to split them up and
|
|
49
|
+
// combine them into a single string.
|
|
50
|
+
let labels = labelledby
|
|
51
|
+
.split(" ")
|
|
52
|
+
.map((labelledby) => {
|
|
53
|
+
let labelEl = document.getElementById(labelledby);
|
|
54
|
+
if (labelEl) {
|
|
55
|
+
let label = labelEl.getAttribute("aria-label");
|
|
56
|
+
// Try to use the `aria-label` first (of the referenced element)
|
|
57
|
+
if (typeof label === "string")
|
|
58
|
+
return label.trim();
|
|
59
|
+
// This time, the `aria-labelledby` isn't used anymore (in Safari), so we just have to
|
|
60
|
+
// look at the contents itself.
|
|
61
|
+
return getTextContents(labelEl).trim();
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
})
|
|
65
|
+
.filter(Boolean);
|
|
66
|
+
if (labels.length > 0)
|
|
67
|
+
return labels.join(", ");
|
|
68
|
+
}
|
|
69
|
+
// Try to use the text contents of the element itself
|
|
70
|
+
return getTextContents(element).trim();
|
|
71
|
+
}
|
package/dist/utils/id.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const alphaid: (size?: number
|
|
1
|
+
export declare const alphaid: (size?: number) => string;
|
|
2
2
|
export declare const htmlid: (size?: number) => string;
|
|
3
3
|
export declare const getIdContext: () => string | undefined;
|
|
4
4
|
export declare const createIdContext: (id: string) => string | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function match<TValue extends string | number = string, TReturnValue = unknown>(value: TValue, lookup: Record<TValue, TReturnValue | ((...args: any[]) => TReturnValue)>, ...args: any[]): TReturnValue;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
export function match(value, lookup, ...args) {
|
|
3
|
+
if (value in lookup) {
|
|
4
|
+
const returnValue = lookup[value];
|
|
5
|
+
return typeof returnValue === "function" ? returnValue(...args) : returnValue;
|
|
6
|
+
}
|
|
7
|
+
const error = new Error(`Tried to handle "${value}" but there is no handler defined. Only defined handlers are: ${Object.keys(lookup)
|
|
8
|
+
.map((key) => `"${key}"`)
|
|
9
|
+
.join(", ")}.`);
|
|
10
|
+
if (Error.captureStackTrace)
|
|
11
|
+
Error.captureStackTrace(error, match);
|
|
12
|
+
throw error;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function once<T>(cb: (...args: T[]) => void): (...args: T[]) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getOwnerDocument<T extends Element>(element: T | null | undefined): Document | null;
|
package/dist/utils/platform.d.ts
CHANGED
|
@@ -2,3 +2,5 @@ export declare function testUserAgent(re: RegExp): any;
|
|
|
2
2
|
export declare function testPlatform(re: RegExp): boolean;
|
|
3
3
|
export declare const isMac: () => boolean;
|
|
4
4
|
export declare const isAndroid: () => boolean;
|
|
5
|
+
export declare function isIOS(): any;
|
|
6
|
+
export declare function isMobile(): any;
|
package/dist/utils/platform.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
export function testUserAgent(re) {
|
|
2
3
|
if (typeof window === "undefined" || window.navigator == null) {
|
|
3
4
|
return false;
|
|
@@ -27,3 +28,19 @@ export const isMac = cached(function () {
|
|
|
27
28
|
export const isAndroid = cached(function () {
|
|
28
29
|
return testUserAgent(/Android/i);
|
|
29
30
|
});
|
|
31
|
+
export function isIOS() {
|
|
32
|
+
// TODO: This is not a great way to detect iOS, but it's the best I can do for now.
|
|
33
|
+
// - `window.platform` is deprecated
|
|
34
|
+
// - `window.userAgentData.platform` is still experimental (https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData/platform)
|
|
35
|
+
// - `window.userAgent` also doesn't contain the required information
|
|
36
|
+
return (
|
|
37
|
+
// Check if it is an iPhone
|
|
38
|
+
testUserAgent(/iPhone/i) ||
|
|
39
|
+
// Check if it is an iPad. iPad reports itself as "MacIntel", but we can check if it is a touch
|
|
40
|
+
// screen. Let's hope that Apple doesn't release a touch screen Mac (or maybe this would then
|
|
41
|
+
// work as expected 🤔).
|
|
42
|
+
(isMac() && typeof window !== "undefined" && window.navigator != null && window.navigator.maxTouchPoints > 0));
|
|
43
|
+
}
|
|
44
|
+
export function isMobile() {
|
|
45
|
+
return isIOS() || isAndroid();
|
|
46
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Props } from "./types.js";
|
|
2
|
+
export declare enum RenderFeatures {
|
|
3
|
+
/** No features at all */
|
|
4
|
+
None = 0,
|
|
5
|
+
/**
|
|
6
|
+
* When used, this will allow us to use one of the render strategies.
|
|
7
|
+
*
|
|
8
|
+
* **The render strategies are:**
|
|
9
|
+
* - **Unmount** _(Will unmount the component.)_
|
|
10
|
+
* - **Hidden** _(Will hide the component using the [hidden] attribute.)_
|
|
11
|
+
*/
|
|
12
|
+
RenderStrategy = 1,
|
|
13
|
+
/**
|
|
14
|
+
* When used, this will allow the user of our component to be in control. This can be used when
|
|
15
|
+
* you want to transition based on some state.
|
|
16
|
+
*/
|
|
17
|
+
Static = 2
|
|
18
|
+
}
|
|
19
|
+
export declare enum RenderStrategy {
|
|
20
|
+
Unmount = 0,
|
|
21
|
+
Hidden = 1
|
|
22
|
+
}
|
|
23
|
+
type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never;
|
|
24
|
+
type PropsForFeature<TPassedInFeatures extends RenderFeatures, TForFeature extends RenderFeatures, TProps> = TPassedInFeatures extends TForFeature ? TProps : {};
|
|
25
|
+
export type PropsForFeatures<T extends RenderFeatures> = Expand<UnionToIntersection<PropsForFeature<T, RenderFeatures.Static, {
|
|
26
|
+
static?: boolean;
|
|
27
|
+
}> | PropsForFeature<T, RenderFeatures.RenderStrategy, {
|
|
28
|
+
unmount?: boolean;
|
|
29
|
+
}>>>;
|
|
30
|
+
export declare function mergeProps<T extends Props<any, any>[]>(...listOfProps: T): Props<any, any>;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export var RenderFeatures;
|
|
2
|
+
(function (RenderFeatures) {
|
|
3
|
+
/** No features at all */
|
|
4
|
+
RenderFeatures[RenderFeatures["None"] = 0] = "None";
|
|
5
|
+
/**
|
|
6
|
+
* When used, this will allow us to use one of the render strategies.
|
|
7
|
+
*
|
|
8
|
+
* **The render strategies are:**
|
|
9
|
+
* - **Unmount** _(Will unmount the component.)_
|
|
10
|
+
* - **Hidden** _(Will hide the component using the [hidden] attribute.)_
|
|
11
|
+
*/
|
|
12
|
+
RenderFeatures[RenderFeatures["RenderStrategy"] = 1] = "RenderStrategy";
|
|
13
|
+
/**
|
|
14
|
+
* When used, this will allow the user of our component to be in control. This can be used when
|
|
15
|
+
* you want to transition based on some state.
|
|
16
|
+
*/
|
|
17
|
+
RenderFeatures[RenderFeatures["Static"] = 2] = "Static";
|
|
18
|
+
})(RenderFeatures || (RenderFeatures = {}));
|
|
19
|
+
export var RenderStrategy;
|
|
20
|
+
(function (RenderStrategy) {
|
|
21
|
+
RenderStrategy[RenderStrategy["Unmount"] = 0] = "Unmount";
|
|
22
|
+
RenderStrategy[RenderStrategy["Hidden"] = 1] = "Hidden";
|
|
23
|
+
})(RenderStrategy || (RenderStrategy = {}));
|
|
24
|
+
export function mergeProps(...listOfProps) {
|
|
25
|
+
if (listOfProps.length === 0)
|
|
26
|
+
return {};
|
|
27
|
+
if (listOfProps.length === 1)
|
|
28
|
+
return listOfProps[0];
|
|
29
|
+
let target = {};
|
|
30
|
+
let eventHandlers = {};
|
|
31
|
+
for (let props of listOfProps) {
|
|
32
|
+
for (let prop in props) {
|
|
33
|
+
// Merge event listeners
|
|
34
|
+
if (prop.startsWith("on") && typeof props[prop] === "function") {
|
|
35
|
+
eventHandlers[prop] ??= [];
|
|
36
|
+
eventHandlers[prop].push(props[prop]);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// Override incoming prop
|
|
40
|
+
target[prop] = props[prop];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Merge event handlers
|
|
45
|
+
for (let eventName in eventHandlers) {
|
|
46
|
+
Object.assign(target, {
|
|
47
|
+
[eventName](...args) {
|
|
48
|
+
let handlers = eventHandlers[eventName];
|
|
49
|
+
for (let handler of handlers) {
|
|
50
|
+
handler?.(...args);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return target;
|
|
56
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type ChangeFn = () => void;
|
|
2
|
+
type UnsubscribeFn = () => void;
|
|
3
|
+
type ActionFn<T> = (this: T, ...args: any[]) => T | void;
|
|
4
|
+
type StoreActions<Key extends string, T> = Record<Key, ActionFn<T>>;
|
|
5
|
+
export interface Store<T, ActionKey extends string> {
|
|
6
|
+
getSnapshot(): T;
|
|
7
|
+
subscribe(onChange: ChangeFn): UnsubscribeFn;
|
|
8
|
+
dispatch(action: ActionKey, ...args: any[]): void;
|
|
9
|
+
}
|
|
10
|
+
export declare function createStore<T, ActionKey extends string>(initial: () => T, actions: StoreActions<ActionKey, T>): Store<T, ActionKey>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function createStore(initial, actions) {
|
|
2
|
+
let state = initial();
|
|
3
|
+
let listeners = new Set();
|
|
4
|
+
return {
|
|
5
|
+
getSnapshot() {
|
|
6
|
+
return state;
|
|
7
|
+
},
|
|
8
|
+
subscribe(onChange) {
|
|
9
|
+
listeners.add(onChange);
|
|
10
|
+
return () => listeners.delete(onChange);
|
|
11
|
+
},
|
|
12
|
+
dispatch(key, ...args) {
|
|
13
|
+
let newState = actions[key].call(state, ...args);
|
|
14
|
+
if (newState) {
|
|
15
|
+
state = newState;
|
|
16
|
+
listeners.forEach((listener) => listener());
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAttributes, SvelteHTMLElements } from "svelte/elements";
|
|
3
|
+
declare const __: "1D45E01E-AF44-47C4-988A-19A94EBAF55C";
|
|
4
|
+
export type __ = typeof __;
|
|
5
|
+
export type ElementType = keyof SvelteHTMLElements;
|
|
6
|
+
export type HTMLElementType<T extends keyof SvelteHTMLElements> = SvelteHTMLElements[T] extends HTMLAttributes<infer U> ? (U extends HTMLElement ? U : never) : never;
|
|
7
|
+
export type Expand<T> = T extends infer O ? {
|
|
8
|
+
[K in keyof O]: O[K];
|
|
9
|
+
} : never;
|
|
10
|
+
export type PropsOf<TTag extends keyof SvelteHTMLElements> = TTag extends keyof SvelteHTMLElements ? SvelteHTMLElements[TTag] : never;
|
|
11
|
+
type PropsWeControl = "as" | "children" | "class";
|
|
12
|
+
type CleanProps<TTag extends keyof SvelteHTMLElements, TOmittableProps extends PropertyKey = never> = Omit<SvelteHTMLElements[TTag], TOmittableProps | PropsWeControl>;
|
|
13
|
+
type OurProps<TTag extends keyof SvelteHTMLElements, TSlot> = {
|
|
14
|
+
as?: TTag;
|
|
15
|
+
children?: Snippet<[TSlot]>;
|
|
16
|
+
};
|
|
17
|
+
type HasProperty<T extends object, K extends PropertyKey> = T extends never ? never : K extends keyof T ? true : never;
|
|
18
|
+
type ClassNameOverride<TTag extends keyof SvelteHTMLElements, TSlot = {}> = true extends HasProperty<PropsOf<TTag>, "class"> ? {
|
|
19
|
+
class?: PropsOf<TTag>["class"] | ((bag: TSlot) => string);
|
|
20
|
+
} : {};
|
|
21
|
+
export type Props<TTag extends keyof SvelteHTMLElements, TSlot = {}, TOmittableProps extends PropertyKey = never, Overrides = {}> = CleanProps<TTag, TOmittableProps | keyof Overrides> & OurProps<TTag, TSlot> & ClassNameOverride<TTag, TSlot> & Overrides;
|
|
22
|
+
type Without<T, U> = {
|
|
23
|
+
[P in Exclude<keyof T, keyof U>]?: never;
|
|
24
|
+
};
|
|
25
|
+
export type XOR<T, U> = T | U extends __ ? never : T extends __ ? U : U extends __ ? T : T | U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;
|
|
26
|
+
export type EnsureArray<T> = T extends any[] ? T : Expand<T>[];
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
2
|
+
// A unique placeholder we can use as a default. This is nice because we can use this instead of
|
|
3
|
+
// defaulting to null / never / ... and possibly collide with actual data.
|
|
4
|
+
// Ideally we use a unique symbol here.
|
|
5
|
+
const __ = "1D45E01E-AF44-47C4-988A-19A94EBAF55C";
|
|
6
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pzerelles/headlessui-svelte",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1-next.1",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": {
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -16,38 +16,44 @@
|
|
|
16
16
|
"svelte": "^5.0.0-next.1"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@changesets/cli": "^2.27.
|
|
19
|
+
"@changesets/cli": "^2.27.7",
|
|
20
20
|
"@changesets/types": "^6.0.0",
|
|
21
|
-
"@playwright/test": "^1.
|
|
22
|
-
"@
|
|
23
|
-
"@sveltejs/
|
|
24
|
-
"@sveltejs/
|
|
21
|
+
"@playwright/test": "^1.45.2",
|
|
22
|
+
"@pzerelles/heroicons-svelte": "^2.1.5",
|
|
23
|
+
"@sveltejs/adapter-auto": "^3.2.2",
|
|
24
|
+
"@sveltejs/kit": "^2.5.18",
|
|
25
|
+
"@sveltejs/package": "^2.3.2",
|
|
25
26
|
"@sveltejs/vite-plugin-svelte": "^3.1.1",
|
|
27
|
+
"@testing-library/jest-dom": "^6.4.6",
|
|
28
|
+
"@testing-library/svelte": "^5.2.0",
|
|
26
29
|
"@types/eslint": "^8.56.10",
|
|
27
|
-
"@types/node": "^20.14.
|
|
30
|
+
"@types/node": "^20.14.10",
|
|
28
31
|
"autoprefixer": "^10.4.19",
|
|
29
|
-
"
|
|
32
|
+
"clsx": "^2.1.1",
|
|
33
|
+
"eslint": "^9.7.0",
|
|
30
34
|
"eslint-config-prettier": "^9.1.0",
|
|
31
|
-
"eslint-plugin-svelte": "^2.
|
|
32
|
-
"globals": "^15.
|
|
35
|
+
"eslint-plugin-svelte": "^2.42.0",
|
|
36
|
+
"globals": "^15.8.0",
|
|
37
|
+
"jsdom": "^24.1.0",
|
|
33
38
|
"outdent": "^0.8.0",
|
|
34
|
-
"postcss": "^8.4.
|
|
35
|
-
"prettier": "^3.3.
|
|
36
|
-
"prettier-plugin-svelte": "^3.2.
|
|
39
|
+
"postcss": "^8.4.39",
|
|
40
|
+
"prettier": "^3.3.3",
|
|
41
|
+
"prettier-plugin-svelte": "^3.2.5",
|
|
37
42
|
"prettier-plugin-tailwindcss": "^0.5.14",
|
|
38
43
|
"publint": "^0.1.16",
|
|
39
|
-
"svelte": "5.0.0-next.
|
|
40
|
-
"svelte-check": "^3.8.
|
|
41
|
-
"tailwindcss": "^3.4.
|
|
44
|
+
"svelte": "5.0.0-next.184",
|
|
45
|
+
"svelte-check": "^3.8.4",
|
|
46
|
+
"tailwindcss": "^3.4.5",
|
|
42
47
|
"tslib": "^2.6.3",
|
|
43
|
-
"typescript": "^5.
|
|
48
|
+
"typescript": "^5.5.3",
|
|
44
49
|
"typescript-eslint": "8.0.0-alpha.28",
|
|
45
|
-
"vite": "^5.
|
|
46
|
-
"vitest": "^
|
|
50
|
+
"vite": "^5.3.4",
|
|
51
|
+
"vitest": "^2.0.3"
|
|
47
52
|
},
|
|
48
53
|
"dependencies": {
|
|
49
|
-
"
|
|
50
|
-
"
|
|
54
|
+
"@skeletonlabs/floating-ui-svelte": "^0.3.1",
|
|
55
|
+
"esm-env": "^1.0.0",
|
|
56
|
+
"nanoid": "^5.0.7"
|
|
51
57
|
},
|
|
52
58
|
"svelte": "./dist/index.js",
|
|
53
59
|
"types": "./dist/index.d.ts",
|
|
@@ -57,6 +63,7 @@
|
|
|
57
63
|
"build": "vite build && npm run package",
|
|
58
64
|
"preview": "vite preview",
|
|
59
65
|
"package": "svelte-kit sync && svelte-package && publint",
|
|
66
|
+
"package:watch": "svelte-package --watch",
|
|
60
67
|
"test": "npm run test:integration && npm run test:unit",
|
|
61
68
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
62
69
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
|
-
import type { Action } from "svelte/action";
|
|
3
|
-
export declare const createActivePress: ({ disabled }: {
|
|
4
|
-
disabled?: boolean;
|
|
5
|
-
}) => {
|
|
6
|
-
activePressAction: Action<HTMLElement, undefined, Record<never, any>>;
|
|
7
|
-
readonly pressed: boolean;
|
|
8
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
|
-
import type { Action } from "svelte/action";
|
|
3
|
-
export declare const createFocusRing: ({ autoFocus, within }?: {
|
|
4
|
-
autoFocus?: boolean;
|
|
5
|
-
within?: boolean;
|
|
6
|
-
}) => {
|
|
7
|
-
focusRingAction: Action<HTMLElement, undefined, Record<never, any>>;
|
|
8
|
-
readonly focusVisible: boolean;
|
|
9
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { isFocusVisible, useFocusVisibleListener } from "../utils/focusVisible.svelte.js";
|
|
2
|
-
export const createFocusRing = ({ autoFocus = false, within } = {}) => {
|
|
3
|
-
let focused = $state(false);
|
|
4
|
-
let focusVisible = $state(autoFocus || isFocusVisible());
|
|
5
|
-
useFocusVisibleListener((isFocusVisible) => {
|
|
6
|
-
focusVisible = isFocusVisible;
|
|
7
|
-
});
|
|
8
|
-
const focusRingAction = (node) => {
|
|
9
|
-
const handleFocus = (e) => {
|
|
10
|
-
focused = true;
|
|
11
|
-
};
|
|
12
|
-
const handleBlur = (e) => {
|
|
13
|
-
focused = false;
|
|
14
|
-
};
|
|
15
|
-
if (!within) {
|
|
16
|
-
node.addEventListener("focus", handleFocus);
|
|
17
|
-
node.addEventListener("blur", handleBlur);
|
|
18
|
-
}
|
|
19
|
-
return {
|
|
20
|
-
destroy: () => {
|
|
21
|
-
if (!within) {
|
|
22
|
-
node.removeEventListener("focus", handleFocus);
|
|
23
|
-
node.removeEventListener("blur", handleBlur);
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
return {
|
|
29
|
-
focusRingAction,
|
|
30
|
-
get focusVisible() {
|
|
31
|
-
return focusVisible && focused;
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
};
|
package/dist/utils/disabled.d.ts
DELETED
package/dist/utils/disabled.js
DELETED