@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.
Files changed (182) hide show
  1. package/dist/button/Button.svelte +65 -0
  2. package/dist/button/Button.svelte.d.ts +39 -0
  3. package/dist/button/index.d.ts +1 -0
  4. package/dist/button/index.js +1 -0
  5. package/dist/checkbox/Checkbox.svelte +60 -46
  6. package/dist/checkbox/Checkbox.svelte.d.ts +1 -1
  7. package/dist/close-button/CloseButton.svelte +10 -0
  8. package/dist/close-button/CloseButton.svelte.d.ts +25 -0
  9. package/dist/close-button/index.d.ts +1 -0
  10. package/dist/close-button/index.js +1 -0
  11. package/dist/combobox/Combobox.svelte +6 -0
  12. package/dist/combobox/Combobox.svelte.d.ts +50 -0
  13. package/dist/description/Description.svelte +50 -32
  14. package/dist/description/Description.svelte.d.ts +14 -5
  15. package/dist/field/Field.svelte +9 -9
  16. package/dist/fieldset/Fieldset.svelte +9 -9
  17. package/dist/hooks/document-overflow/adjust-scrollbar-padding.d.ts +2 -0
  18. package/dist/hooks/document-overflow/adjust-scrollbar-padding.js +18 -0
  19. package/dist/hooks/document-overflow/handle-ios-locking.d.ts +6 -0
  20. package/dist/hooks/document-overflow/handle-ios-locking.js +134 -0
  21. package/dist/hooks/document-overflow/overflow-store.d.ts +19 -0
  22. package/dist/hooks/document-overflow/overflow-store.js +76 -0
  23. package/dist/hooks/document-overflow/prevent-scroll.d.ts +2 -0
  24. package/dist/hooks/document-overflow/prevent-scroll.js +7 -0
  25. package/dist/hooks/document-overflow/use-document-overflow.svelte.d.ts +7 -0
  26. package/dist/hooks/document-overflow/use-document-overflow.svelte.js +27 -0
  27. package/dist/hooks/use-active-press.svelte.d.ts +14 -0
  28. package/dist/{actions/activePress.svelte.js → hooks/use-active-press.svelte.js} +33 -39
  29. package/dist/hooks/use-by-comparator.d.ts +2 -0
  30. package/dist/hooks/use-by-comparator.js +15 -0
  31. package/dist/hooks/use-controllable.svelte.d.ts +6 -0
  32. package/dist/hooks/use-controllable.svelte.js +34 -0
  33. package/dist/hooks/use-did-element-move.svelte.d.ts +6 -0
  34. package/dist/hooks/use-did-element-move.svelte.js +27 -0
  35. package/dist/hooks/use-disabled.d.ts +3 -0
  36. package/dist/hooks/use-disabled.js +9 -0
  37. package/dist/hooks/use-element-size.svelte.d.ts +7 -0
  38. package/dist/hooks/use-element-size.svelte.js +36 -0
  39. package/dist/hooks/use-flags.svelte.d.ts +8 -0
  40. package/dist/hooks/use-flags.svelte.js +18 -0
  41. package/dist/hooks/use-focus-ring.svelte.d.ts +10 -0
  42. package/dist/hooks/use-focus-ring.svelte.js +24 -0
  43. package/dist/hooks/use-hover.svelte.d.ts +26 -0
  44. package/dist/hooks/use-hover.svelte.js +124 -0
  45. package/dist/hooks/use-id.d.ts +1 -0
  46. package/dist/hooks/use-id.js +1 -0
  47. package/dist/hooks/use-inert-others.svelte.d.ts +32 -0
  48. package/dist/hooks/use-inert-others.svelte.js +114 -0
  49. package/dist/hooks/use-is-top-layer.svelte.d.ts +29 -0
  50. package/dist/hooks/use-is-top-layer.svelte.js +82 -0
  51. package/dist/hooks/use-on-disappear.svelte.d.ts +12 -0
  52. package/dist/hooks/use-on-disappear.svelte.js +38 -0
  53. package/dist/hooks/use-outside-click.svelte.d.ts +10 -0
  54. package/dist/hooks/use-outside-click.svelte.js +150 -0
  55. package/dist/hooks/use-reducer.d.ts +4 -0
  56. package/dist/hooks/use-reducer.js +11 -0
  57. package/dist/hooks/use-resolve-button-type.svelte.d.ts +10 -0
  58. package/dist/hooks/use-resolve-button-type.svelte.js +19 -0
  59. package/dist/hooks/use-scroll-lock.svelte.d.ts +5 -0
  60. package/dist/hooks/use-scroll-lock.svelte.js +24 -0
  61. package/dist/hooks/use-sync-refs.d.ts +7 -0
  62. package/dist/hooks/use-sync-refs.js +22 -0
  63. package/dist/hooks/use-text-value.svelte.d.ts +3 -0
  64. package/dist/hooks/use-text-value.svelte.js +20 -0
  65. package/dist/hooks/use-tracked-pointer.d.ts +4 -0
  66. package/dist/hooks/use-tracked-pointer.js +26 -0
  67. package/dist/hooks/use-transition.svelte.d.ts +20 -0
  68. package/dist/hooks/use-transition.svelte.js +252 -0
  69. package/dist/index.d.ts +4 -0
  70. package/dist/index.js +4 -0
  71. package/dist/internal/FocusSentinel.svelte +45 -0
  72. package/dist/internal/FocusSentinel.svelte.d.ts +17 -0
  73. package/dist/internal/FormFields.svelte +2 -4
  74. package/dist/internal/FormFields.svelte.d.ts +5 -6
  75. package/dist/internal/FormResolver.svelte +11 -16
  76. package/dist/internal/FormResolver.svelte.d.ts +2 -3
  77. package/dist/internal/Hidden.svelte +8 -8
  78. package/dist/internal/Hidden.svelte.d.ts +28 -19
  79. package/dist/internal/HoistFormFields.svelte.d.ts +1 -1
  80. package/dist/internal/Portal.svelte.d.ts +1 -1
  81. package/dist/internal/floating.svelte.d.ts +57 -0
  82. package/dist/internal/floating.svelte.js +477 -0
  83. package/dist/internal/frozen.svelte.d.ts +6 -0
  84. package/dist/internal/frozen.svelte.js +18 -0
  85. package/dist/internal/id.d.ts +8 -0
  86. package/dist/internal/id.js +11 -0
  87. package/dist/internal/open-closed.d.ts +14 -0
  88. package/dist/internal/open-closed.js +17 -0
  89. package/dist/internal/portal-force-root.svelte.d.ts +6 -0
  90. package/dist/internal/portal-force-root.svelte.js +11 -0
  91. package/dist/label/Label.svelte +53 -32
  92. package/dist/label/Label.svelte.d.ts +14 -5
  93. package/dist/legend/Legend.svelte.d.ts +1 -2
  94. package/dist/listbox/Listbox.svelte +451 -0
  95. package/dist/listbox/Listbox.svelte.d.ts +107 -0
  96. package/dist/listbox/ListboxButton.svelte +141 -0
  97. package/dist/listbox/ListboxButton.svelte.d.ts +41 -0
  98. package/dist/listbox/ListboxOption.svelte +138 -0
  99. package/dist/listbox/ListboxOption.svelte.d.ts +39 -0
  100. package/dist/listbox/ListboxOptions.svelte +267 -0
  101. package/dist/listbox/ListboxOptions.svelte.d.ts +39 -0
  102. package/dist/listbox/ListboxSelectedOption.svelte +25 -0
  103. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +30 -0
  104. package/dist/listbox/index.d.ts +5 -0
  105. package/dist/listbox/index.js +5 -0
  106. package/dist/portal/InternalPortal.svelte +108 -0
  107. package/dist/portal/InternalPortal.svelte.d.ts +34 -0
  108. package/dist/portal/Portal.svelte +11 -0
  109. package/dist/portal/Portal.svelte.d.ts +23 -0
  110. package/dist/portal/PortalGroup.svelte +15 -0
  111. package/dist/portal/PortalGroup.svelte.d.ts +31 -0
  112. package/dist/switch/Switch.svelte +149 -0
  113. package/dist/switch/Switch.svelte.d.ts +44 -0
  114. package/dist/switch/SwitchGroup.svelte +38 -0
  115. package/dist/switch/SwitchGroup.svelte.d.ts +27 -0
  116. package/dist/switch/index.d.ts +2 -0
  117. package/dist/switch/index.js +2 -0
  118. package/dist/tabs/Button.svelte +65 -0
  119. package/dist/tabs/Button.svelte.d.ts +39 -0
  120. package/dist/tabs/Tab.svelte +161 -0
  121. package/dist/tabs/Tab.svelte.d.ts +36 -0
  122. package/dist/tabs/TabGroup.svelte +244 -0
  123. package/dist/tabs/TabGroup.svelte.d.ts +54 -0
  124. package/dist/tabs/TabList.svelte +18 -0
  125. package/dist/tabs/TabList.svelte.d.ts +28 -0
  126. package/dist/tabs/TabPanel.svelte +63 -0
  127. package/dist/tabs/TabPanel.svelte.d.ts +34 -0
  128. package/dist/tabs/TabPanels.svelte +13 -0
  129. package/dist/tabs/TabPanels.svelte.d.ts +27 -0
  130. package/dist/tabs/index.d.ts +5 -0
  131. package/dist/tabs/index.js +5 -0
  132. package/dist/test-utils/accessability-assertions.d.ts +271 -0
  133. package/dist/test-utils/accessability-assertions.js +1572 -0
  134. package/dist/test-utils/fake-pointer.d.ts +24 -0
  135. package/dist/test-utils/fake-pointer.js +48 -0
  136. package/dist/test-utils/interactions.d.ts +61 -0
  137. package/dist/test-utils/interactions.js +453 -0
  138. package/dist/test-utils/suppress-console-logs.d.ts +7 -0
  139. package/dist/test-utils/suppress-console-logs.js +17 -0
  140. package/dist/utils/StableCollection.svelte +43 -0
  141. package/dist/utils/StableCollection.svelte.d.ts +19 -0
  142. package/dist/utils/calculate-active-index.d.ts +25 -0
  143. package/dist/utils/calculate-active-index.js +74 -0
  144. package/dist/utils/close.d.ts +2 -0
  145. package/dist/utils/close.js +3 -0
  146. package/dist/utils/default-map.d.ts +5 -0
  147. package/dist/utils/default-map.js +15 -0
  148. package/dist/utils/disposables.d.ts +14 -12
  149. package/dist/utils/disposables.js +13 -10
  150. package/dist/utils/dom.d.ts +0 -2
  151. package/dist/utils/dom.js +2 -4
  152. package/dist/utils/env.d.ts +17 -0
  153. package/dist/utils/env.js +39 -0
  154. package/dist/utils/focus-management.d.ts +44 -0
  155. package/dist/utils/focus-management.js +242 -0
  156. package/dist/utils/focusVisible.svelte.d.ts +3 -3
  157. package/dist/utils/focusVisible.svelte.js +52 -41
  158. package/dist/utils/get-text-value.d.ts +1 -0
  159. package/dist/utils/get-text-value.js +71 -0
  160. package/dist/utils/id.d.ts +1 -1
  161. package/dist/utils/match.d.ts +1 -0
  162. package/dist/utils/match.js +13 -0
  163. package/dist/utils/once.d.ts +1 -0
  164. package/dist/utils/once.js +9 -0
  165. package/dist/utils/owner.d.ts +1 -0
  166. package/dist/utils/owner.js +8 -0
  167. package/dist/utils/platform.d.ts +2 -0
  168. package/dist/utils/platform.js +17 -0
  169. package/dist/utils/ref.svelte.d.ts +4 -0
  170. package/dist/utils/ref.svelte.js +4 -0
  171. package/dist/utils/render.d.ts +31 -0
  172. package/dist/utils/render.js +56 -0
  173. package/dist/utils/store.d.ts +11 -0
  174. package/dist/utils/store.js +20 -0
  175. package/dist/utils/types.d.ts +27 -0
  176. package/dist/utils/types.js +6 -0
  177. package/package.json +28 -21
  178. package/dist/actions/activePress.svelte.d.ts +0 -8
  179. package/dist/actions/focusRing.svelte.d.ts +0 -9
  180. package/dist/actions/focusRing.svelte.js +0 -34
  181. package/dist/utils/disabled.d.ts +0 -3
  182. 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 { getOwnerDocument, getOwnerWindow } from "./dom.js";
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
- let changeHandlers = new Set();
21
- export let hasSetupGlobalListeners = new Map(); // We use a map here to support setting event listeners across multiple document objects.
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 (let handler of changeHandlers) {
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
- let focus = windowObject.HTMLElement.prototype.focus;
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, arguments);
105
+ focus.apply(this, args);
105
106
  };
106
- documentObject.addEventListener("keydown", handleKeyboardEvent, true);
107
- documentObject.addEventListener("keyup", handleKeyboardEvent, true);
108
- documentObject.addEventListener("click", handleClickEvent, true);
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 (typeof PointerEvent !== "undefined") {
114
- documentObject.addEventListener("pointerdown", handlePointerEvent, true);
115
- documentObject.addEventListener("pointermove", handlePointerEvent, true);
116
- documentObject.addEventListener("pointerup", handlePointerEvent, true);
117
- }
118
- else {
119
- documentObject.addEventListener("mousedown", handlePointerEvent, true);
120
- documentObject.addEventListener("mousemove", handlePointerEvent, true);
121
- documentObject.addEventListener("mouseup", handlePointerEvent, true);
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.removeEventListener("keydown", handleKeyboardEvent, true);
140
- documentObject.removeEventListener("keyup", handleKeyboardEvent, true);
141
- documentObject.removeEventListener("click", handleClickEvent, true);
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 (typeof PointerEvent !== "undefined") {
145
- documentObject.removeEventListener("pointerdown", handlePointerEvent, true);
146
- documentObject.removeEventListener("pointermove", handlePointerEvent, true);
147
- documentObject.removeEventListener("pointerup", handlePointerEvent, true);
148
- }
149
- else {
150
- documentObject.removeEventListener("mousedown", handlePointerEvent, true);
151
- documentObject.removeEventListener("mousemove", handlePointerEvent, true);
152
- documentObject.removeEventListener("mouseup", handlePointerEvent, true);
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.readyState !== "loading") {
177
- setupGlobalFocusEvents(element);
178
- }
179
- else {
180
- loadListener = () => {
185
+ if (documentObject) {
186
+ if (documentObject.readyState !== "loading") {
181
187
  setupGlobalFocusEvents(element);
182
- };
183
- documentObject.addEventListener("DOMContentLoaded", loadListener);
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, autoFocus } = props
250
- let [isFocusVisibleState, setFocusVisible] = useState(autoFocus || isFocusVisible())
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
+ }
@@ -1,4 +1,4 @@
1
- export declare const alphaid: (size?: number | undefined) => string;
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,9 @@
1
+ export function once(cb) {
2
+ let state = { called: false };
3
+ return (...args) => {
4
+ if (state.called)
5
+ return;
6
+ state.called = true;
7
+ return cb(...args);
8
+ };
9
+ }
@@ -0,0 +1 @@
1
+ export declare function getOwnerDocument<T extends Element>(element: T | null | undefined): Document | null;
@@ -0,0 +1,8 @@
1
+ import { BROWSER } from "esm-env";
2
+ export function getOwnerDocument(element) {
3
+ if (!BROWSER)
4
+ return null;
5
+ if (element instanceof Node)
6
+ return element.ownerDocument;
7
+ return document;
8
+ }
@@ -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;
@@ -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,4 @@
1
+ export type MutableRefObject<T> = {
2
+ current: T;
3
+ };
4
+ export declare const useRef: <T>(current: T) => MutableRefObject<T>;
@@ -0,0 +1,4 @@
1
+ export const useRef = (current) => {
2
+ const ref = $state({ current });
3
+ return ref;
4
+ };
@@ -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.0.0-next.1",
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.5",
19
+ "@changesets/cli": "^2.27.7",
20
20
  "@changesets/types": "^6.0.0",
21
- "@playwright/test": "^1.44.1",
22
- "@sveltejs/adapter-auto": "^3.2.1",
23
- "@sveltejs/kit": "^2.5.10",
24
- "@sveltejs/package": "^2.3.1",
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.2",
30
+ "@types/node": "^20.14.10",
28
31
  "autoprefixer": "^10.4.19",
29
- "eslint": "^9.4.0",
32
+ "clsx": "^2.1.1",
33
+ "eslint": "^9.7.0",
30
34
  "eslint-config-prettier": "^9.1.0",
31
- "eslint-plugin-svelte": "^2.39.0",
32
- "globals": "^15.3.0",
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.38",
35
- "prettier": "^3.3.1",
36
- "prettier-plugin-svelte": "^3.2.3",
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.150",
40
- "svelte-check": "^3.8.0",
41
- "tailwindcss": "^3.4.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.4.5",
48
+ "typescript": "^5.5.3",
44
49
  "typescript-eslint": "8.0.0-alpha.28",
45
- "vite": "^5.2.12",
46
- "vitest": "^1.6.0"
50
+ "vite": "^5.3.4",
51
+ "vitest": "^2.0.3"
47
52
  },
48
53
  "dependencies": {
49
- "nanoid": "^5.0.7",
50
- "svelte-interactions": "^0.2.0"
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
- };
@@ -1,3 +0,0 @@
1
- export declare const getDisabledContext: () => {
2
- readonly disabled: boolean;
3
- } | undefined;
@@ -1,2 +0,0 @@
1
- import { getContext } from "svelte";
2
- export const getDisabledContext = () => getContext("Disabled");