@pzerelles/headlessui-svelte 2.1.1-next.1 → 2.1.2-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/dist/button/Button.svelte +6 -10
  2. package/dist/button/Button.svelte.d.ts +34 -26
  3. package/dist/checkbox/Checkbox.svelte +40 -22
  4. package/dist/checkbox/Checkbox.svelte.d.ts +44 -28
  5. package/dist/close-button/CloseButton.svelte +5 -4
  6. package/dist/close-button/CloseButton.svelte.d.ts +36 -13
  7. package/dist/combobox/Combobox.svelte +2 -2
  8. package/dist/combobox/Combobox.svelte.d.ts +9 -9
  9. package/dist/data-interactive/DataInteractive.svelte +41 -0
  10. package/dist/data-interactive/DataInteractive.svelte.d.ts +39 -0
  11. package/dist/data-interactive/index.d.ts +1 -0
  12. package/dist/data-interactive/index.js +1 -0
  13. package/dist/description/Description.svelte +10 -53
  14. package/dist/description/Description.svelte.d.ts +15 -32
  15. package/dist/description/context.svelte.d.ts +17 -0
  16. package/dist/description/context.svelte.js +51 -0
  17. package/dist/dialog/Dialog.svelte +51 -0
  18. package/dist/dialog/Dialog.svelte.d.ts +60 -0
  19. package/dist/dialog/DialogBackdrop.svelte +39 -0
  20. package/dist/dialog/DialogBackdrop.svelte.d.ts +38 -0
  21. package/dist/dialog/DialogPanel.svelte +46 -0
  22. package/dist/dialog/DialogPanel.svelte.d.ts +40 -0
  23. package/dist/dialog/DialogTitle.svelte +29 -0
  24. package/dist/dialog/DialogTitle.svelte.d.ts +34 -0
  25. package/dist/dialog/InternalDialog.svelte +233 -0
  26. package/dist/dialog/InternalDialog.svelte.d.ts +42 -0
  27. package/dist/dialog/context.svelte.d.ts +15 -0
  28. package/dist/dialog/context.svelte.js +16 -0
  29. package/dist/dialog/index.d.ts +4 -0
  30. package/dist/dialog/index.js +4 -0
  31. package/dist/field/Field.svelte +8 -10
  32. package/dist/field/Field.svelte.d.ts +21 -17
  33. package/dist/fieldset/Fieldset.svelte +11 -9
  34. package/dist/fieldset/Fieldset.svelte.d.ts +21 -17
  35. package/dist/focus-trap/FocusTrap.svelte +332 -0
  36. package/dist/focus-trap/FocusTrap.svelte.d.ts +58 -0
  37. package/dist/hooks/use-controllable.svelte.d.ts +1 -1
  38. package/dist/hooks/use-controllable.svelte.js +3 -3
  39. package/dist/hooks/use-escape.svelte.d.ts +5 -0
  40. package/dist/hooks/use-escape.svelte.js +26 -0
  41. package/dist/hooks/use-event-listener.svelte.d.ts +6 -0
  42. package/dist/hooks/use-event-listener.svelte.js +12 -0
  43. package/dist/hooks/use-inert-others.svelte.d.ts +2 -2
  44. package/dist/hooks/use-inert-others.svelte.js +3 -3
  45. package/dist/hooks/use-is-mounted.svelte.d.ts +3 -0
  46. package/dist/hooks/use-is-mounted.svelte.js +14 -0
  47. package/dist/hooks/use-is-touch-device.svelte.d.ts +3 -0
  48. package/dist/hooks/use-is-touch-device.svelte.js +20 -0
  49. package/dist/hooks/use-root-containers.svelte.d.ts +9 -0
  50. package/dist/hooks/use-root-containers.svelte.js +50 -0
  51. package/dist/hooks/use-tab-direction.svelte.d.ts +7 -0
  52. package/dist/hooks/use-tab-direction.svelte.js +25 -0
  53. package/dist/hooks/use-transition.svelte.js +14 -13
  54. package/dist/hooks/use-tree-walker.svelte.d.ts +8 -0
  55. package/dist/hooks/use-tree-walker.svelte.js +19 -0
  56. package/dist/hooks/use-watch.svelte.d.ts +4 -0
  57. package/dist/hooks/use-watch.svelte.js +16 -0
  58. package/dist/hooks/use-window-event.svelte.d.ts +6 -0
  59. package/dist/hooks/use-window-event.svelte.js +12 -0
  60. package/dist/index.d.ts +9 -0
  61. package/dist/index.js +9 -0
  62. package/dist/input/Input.svelte +59 -0
  63. package/dist/input/Input.svelte.d.ts +52 -0
  64. package/dist/input/index.d.ts +1 -0
  65. package/dist/input/index.js +1 -0
  66. package/dist/internal/FocusSentinel.svelte.d.ts +4 -1
  67. package/dist/internal/ForcePortalRoot.svelte +6 -0
  68. package/dist/internal/ForcePortalRoot.svelte.d.ts +22 -0
  69. package/dist/internal/FormFields.svelte.d.ts +4 -1
  70. package/dist/internal/FormResolver.svelte.d.ts +4 -1
  71. package/dist/internal/Hidden.svelte +5 -9
  72. package/dist/internal/Hidden.svelte.d.ts +17 -10
  73. package/dist/internal/HoistFormFields.svelte.d.ts +4 -1
  74. package/dist/internal/MainTreeProvider.svelte +45 -0
  75. package/dist/internal/MainTreeProvider.svelte.d.ts +31 -0
  76. package/dist/internal/Portal.svelte.d.ts +4 -1
  77. package/dist/internal/close-provider.d.ts +7 -0
  78. package/dist/internal/close-provider.js +7 -0
  79. package/dist/internal/floating.svelte.d.ts +13 -8
  80. package/dist/internal/floating.svelte.js +197 -186
  81. package/dist/internal/id.d.ts +1 -1
  82. package/dist/internal/open-closed.d.ts +1 -1
  83. package/dist/internal/open-closed.js +1 -1
  84. package/dist/label/Label.svelte +12 -61
  85. package/dist/label/Label.svelte.d.ts +19 -32
  86. package/dist/label/context.svelte.d.ts +17 -0
  87. package/dist/label/context.svelte.js +56 -0
  88. package/dist/legend/Legend.svelte +4 -3
  89. package/dist/legend/Legend.svelte.d.ts +33 -15
  90. package/dist/listbox/Listbox.svelte +6 -9
  91. package/dist/listbox/Listbox.svelte.d.ts +29 -10
  92. package/dist/listbox/ListboxButton.svelte +6 -8
  93. package/dist/listbox/ListboxButton.svelte.d.ts +18 -7
  94. package/dist/listbox/ListboxOption.svelte +4 -6
  95. package/dist/listbox/ListboxOption.svelte.d.ts +22 -11
  96. package/dist/listbox/ListboxOptions.svelte +21 -19
  97. package/dist/listbox/ListboxOptions.svelte.d.ts +23 -7
  98. package/dist/listbox/ListboxSelectedOption.svelte +17 -7
  99. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +23 -13
  100. package/dist/menu/Menu.svelte +235 -0
  101. package/dist/menu/Menu.svelte.d.ts +42 -0
  102. package/dist/menu/MenuButton.svelte +127 -0
  103. package/dist/menu/MenuButton.svelte.d.ts +52 -0
  104. package/dist/menu/MenuHeading.svelte +19 -0
  105. package/dist/menu/MenuHeading.svelte.d.ts +39 -0
  106. package/dist/menu/MenuItem.svelte +114 -0
  107. package/dist/menu/MenuItem.svelte.d.ts +49 -0
  108. package/dist/menu/MenuItems.svelte +244 -0
  109. package/dist/menu/MenuItems.svelte.d.ts +55 -0
  110. package/dist/menu/MenuSection.svelte +14 -0
  111. package/dist/menu/MenuSection.svelte.d.ts +35 -0
  112. package/dist/menu/MenuSeparator.svelte +9 -0
  113. package/dist/menu/MenuSeparator.svelte.d.ts +35 -0
  114. package/dist/menu/context.svelte.d.ts +47 -0
  115. package/dist/menu/context.svelte.js +21 -0
  116. package/dist/menu/index.d.ts +7 -0
  117. package/dist/menu/index.js +7 -0
  118. package/dist/portal/InternalPortal.svelte +22 -33
  119. package/dist/portal/InternalPortal.svelte.d.ts +16 -7
  120. package/dist/portal/Portal.svelte +4 -8
  121. package/dist/portal/Portal.svelte.d.ts +6 -6
  122. package/dist/portal/PortalGroup.svelte +5 -6
  123. package/dist/portal/PortalGroup.svelte.d.ts +16 -7
  124. package/dist/switch/Switch.svelte +11 -17
  125. package/dist/switch/Switch.svelte.d.ts +23 -6
  126. package/dist/switch/SwitchGroup.svelte +7 -8
  127. package/dist/switch/SwitchGroup.svelte.d.ts +14 -7
  128. package/dist/tabs/Tab.svelte +9 -14
  129. package/dist/tabs/Tab.svelte.d.ts +18 -6
  130. package/dist/tabs/TabGroup.svelte +20 -23
  131. package/dist/tabs/TabGroup.svelte.d.ts +19 -6
  132. package/dist/tabs/TabList.svelte +5 -7
  133. package/dist/tabs/TabList.svelte.d.ts +13 -6
  134. package/dist/tabs/TabPanel.svelte +30 -32
  135. package/dist/tabs/TabPanel.svelte.d.ts +19 -6
  136. package/dist/tabs/TabPanels.svelte +5 -6
  137. package/dist/tabs/TabPanels.svelte.d.ts +13 -6
  138. package/dist/transition/InternalTransitionChild.svelte +178 -0
  139. package/dist/transition/InternalTransitionChild.svelte.d.ts +55 -0
  140. package/dist/transition/Transition.svelte +89 -0
  141. package/dist/transition/Transition.svelte.d.ts +42 -0
  142. package/dist/transition/TransitionChild.svelte +16 -0
  143. package/dist/transition/TransitionChild.svelte.d.ts +44 -0
  144. package/dist/transition/context.svelte.d.ts +64 -0
  145. package/dist/transition/context.svelte.js +120 -0
  146. package/dist/transition/index.d.ts +2 -0
  147. package/dist/transition/index.js +2 -0
  148. package/dist/utils/ElementOrComponent.svelte +26 -0
  149. package/dist/utils/ElementOrComponent.svelte.d.ts +56 -0
  150. package/dist/utils/Generic.svelte +44 -0
  151. package/dist/utils/Generic.svelte.d.ts +35 -0
  152. package/dist/utils/StableCollection.svelte +1 -1
  153. package/dist/utils/StableCollection.svelte.d.ts +4 -1
  154. package/dist/utils/active-element-history.d.ts +1 -0
  155. package/dist/utils/active-element-history.js +35 -0
  156. package/dist/utils/alternative-types.d.ts +21 -0
  157. package/dist/utils/alternative-types.js +1 -0
  158. package/dist/utils/class-names.d.ts +1 -0
  159. package/dist/utils/class-names.js +10 -0
  160. package/dist/utils/focus-management.d.ts +2 -1
  161. package/dist/utils/focus-management.js +13 -13
  162. package/dist/utils/on-document-ready.d.ts +1 -0
  163. package/dist/utils/on-document-ready.js +12 -0
  164. package/dist/utils/render.d.ts +3 -0
  165. package/dist/utils/render.js +63 -0
  166. package/dist/utils/state.d.ts +7 -1
  167. package/dist/utils/state.js +10 -6
  168. package/dist/utils/types.d.ts +14 -17
  169. package/dist/utils/types.js +0 -5
  170. package/package.json +26 -25
  171. package/dist/tabs/Button.svelte +0 -65
  172. package/dist/tabs/Button.svelte.d.ts +0 -39
  173. package/dist/utils/close.d.ts +0 -2
  174. package/dist/utils/close.js +0 -3
@@ -1,11 +1,20 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ /* eslint-disable prefer-const */
1
4
  import { useDisposables } from "../utils/disposables.js";
2
- import { useRef } from "../utils/ref.svelte.js";
3
- import { autoUpdate, flip as flipMiddleware,
5
+ import { computePosition } from "@floating-ui/dom";
6
+ import { flip as flipMiddleware,
4
7
  //inner as innerMiddleware,
5
- offset as offsetMiddleware, shift as shiftMiddleware, size as sizeMiddleware, useFloating as _useFloating,
6
- //useInnerOffset,
7
- useInteractions, } from "@skeletonlabs/floating-ui-svelte";
8
- import { getContext, setContext } from "svelte";
8
+ offset as offsetMiddleware, shift as shiftMiddleware, size as sizeMiddleware, } from "@floating-ui/core";
9
+ /*import {
10
+ autoUpdate,
11
+ useFloating as _useFloating,
12
+ //useInnerOffset,
13
+ useInteractions,
14
+ //type InnerProps,
15
+ type UseFloatingReturn,
16
+ } from "@skeletonlabs/floating-ui-svelte"*/
17
+ import { getContext, setContext, untrack } from "svelte";
9
18
  export function useResolvedAnchor(anchor) {
10
19
  if (!anchor)
11
20
  return null; // Disable entirely
@@ -17,36 +26,37 @@ export function useFloating() {
17
26
  return getContext("FloatingContext");
18
27
  }
19
28
  export function useFloatingPanelProps() {
20
- let { getFloatingProps, slot } = getContext("FloatingContext");
29
+ const { getFloatingProps, slot } = getContext("FloatingContext");
21
30
  return (...args) => {
22
31
  return Object.assign({}, getFloatingProps(...args), {
23
32
  "data-anchor": slot.anchor,
24
33
  });
25
34
  };
26
35
  }
27
- export function useFloatingPanel(placement = null) {
28
- if (placement === false)
29
- placement = null; // Disable entirely
30
- if (typeof placement === "string")
31
- placement = { to: placement }; // Simple string based value
36
+ export function useFloatingPanel(options) {
37
+ const placement = $derived.by(() => {
38
+ if (options.placement === false)
39
+ return null; // Disable entirely
40
+ if (typeof options.placement === "string")
41
+ return { to: options.placement }; // Simple string based value
42
+ return options.placement;
43
+ });
32
44
  const updatePlacementConfig = getContext("PlacementContext");
33
- /*let stablePlacement = useMemo(
34
- () => placement,
35
- [
36
- JSON.stringify(
37
- placement,
38
- typeof HTMLElement !== 'undefined'
39
- ? (_, v) => {
40
- if (v instanceof HTMLElement) {
41
- return v.outerHTML
42
- }
43
- return v
44
- }
45
- : undefined
46
- ),
47
- ]
48
- )*/
49
- updatePlacementConfig?.(placement ?? null);
45
+ const trigger = $derived(JSON.stringify(placement, typeof HTMLElement !== "undefined"
46
+ ? (_, v) => {
47
+ if (v instanceof HTMLElement) {
48
+ return v.outerHTML;
49
+ }
50
+ return v;
51
+ }
52
+ : undefined));
53
+ const stablePlacement = $derived.by(() => {
54
+ trigger;
55
+ return untrack(() => placement);
56
+ });
57
+ $effect(() => {
58
+ updatePlacementConfig?.(stablePlacement ?? null);
59
+ });
50
60
  const context = getContext("FloatingContext");
51
61
  return {
52
62
  get setFloating() {
@@ -58,152 +68,164 @@ export function useFloatingPanel(placement = null) {
58
68
  };
59
69
  }
60
70
  // TODO: Make this a config part of the `config`. Just need to decide on a name.
61
- let MINIMUM_ITEMS_VISIBLE = 4;
71
+ //let MINIMUM_ITEMS_VISIBLE = 4
62
72
  export const createFloatingContext = ({ enabled = true } = {}) => {
63
73
  let config = $state(null);
64
- let innerOffset = $state(0);
65
- let overflowRef = useRef(null);
74
+ //let innerOffset = $state(0)
75
+ //let overflowRef = $state<HTMLElement | null>(null)
76
+ let referenceEl = $state(null);
66
77
  let floatingEl = $state(null);
67
78
  $effect(() => useFixScrollingPixel(floatingEl));
68
79
  const isEnabled = $derived(enabled && config !== null && floatingEl !== null);
69
- let { to: placement = "bottom", gap = 0, offset = 0, padding = 0, inner, } = useResolvedConfig({
80
+ const { to: placement = "bottom", gap = 0, offset = 0, padding = 0, inner, } = $derived(useResolvedConfig({
70
81
  get config() {
71
82
  return config;
72
83
  },
73
84
  get element() {
74
85
  return floatingEl;
75
86
  },
76
- });
77
- let [to, align = "center"] = placement.split(" ");
87
+ }));
88
+ const [to, align = "center"] = $derived(placement.split(" "));
78
89
  // Reset
79
90
  $effect(() => {
80
91
  if (!isEnabled)
81
92
  return;
82
- innerOffset = 0;
93
+ //innerOffset = 0
83
94
  });
84
- const { elements, floatingStyles, context } = $derived(_useFloating({
85
- open: isEnabled,
86
- placement: to === "selection"
87
- ? align === "center"
88
- ? "bottom"
89
- : `bottom-${align}`
90
- : align === "center"
91
- ? `${to}`
92
- : `${to}-${align}`,
93
- // This component will be used in combination with a `Portal`, which means the floating
94
- // element will be rendered outside of the current DOM tree.
95
- strategy: "absolute",
96
- // We use the panel in a `Dialog` which is making the page inert, therefore no re-positioning is
97
- // needed when scrolling changes.
98
- transform: false,
99
- middleware: [
100
- // - The `mainAxis` is set to `gap` which defines the gap between the panel and the
101
- // trigger/reference.
102
- // - The `crossAxis` is set to `offset` which nudges the panel from its original position.
103
- //
104
- // When we are showing the panel on top of the selected item, we don't want a gap between the
105
- // reference and the panel, therefore setting the `mainAxis` to `0`.
106
- offsetMiddleware({
107
- mainAxis: to === "selection" ? 0 : gap,
108
- crossAxis: offset,
109
- }),
110
- // When the panel overflows the viewport, we will try to nudge the panel to the other side to
111
- // ensure it's not clipped. We use the `padding` to define the minimum space between the
112
- // panel and the viewport.
113
- shiftMiddleware({ padding }),
114
- // The `flip` middleware will swap the `placement` of the panel if there is not enough room.
115
- // This is not compatible with the `inner` middleware (which is only enabled when `to` is set
116
- // to "selection").
117
- to !== "selection" && flipMiddleware({ padding }),
118
- // The `inner` middleware will ensure the panel is always fully visible on screen and
119
- // positioned on top of the reference and moved to the currently selected item.
120
- to === "selection" && inner
121
- ? null /* TODO: use inner when available: innerMiddleware({
122
- ...inner,
123
- padding, // For overflow detection
124
- overflowRef,
125
- offset: innerOffset,
126
- minItemsVisible: MINIMUM_ITEMS_VISIBLE,
127
- referenceOverflowThreshold: padding,
128
- onFallbackChange(fallback) {
129
- if (!fallback) return
130
- let parent = context.elements.floating
131
- if (!parent) return
132
- let scrollPaddingBottom =
133
- parseFloat(getComputedStyle(parent!).scrollPaddingBottom) || 0
134
-
135
- // We want at least X visible items, but if there are less than X items in the list,
136
- // we want to show as many as possible.
137
- let missing = Math.min(MINIMUM_ITEMS_VISIBLE, parent.childElementCount)
138
-
139
- let elementHeight = 0
140
- let elementAmountVisible = 0
141
-
142
- for (let child of context.elements.floating?.childNodes ?? []) {
143
- if (child instanceof HTMLElement) {
144
- let childTop = child.offsetTop
145
- // It can be that the child is fully visible, but we also want to keep the scroll
146
- // padding into account to ensure the UI looks good. Therefore we fake that the
147
- // bottom of the child is actually `scrollPaddingBottom` amount of pixels lower.
148
- let childBottom = childTop + child.clientHeight + scrollPaddingBottom
149
-
150
- let parentTop = parent.scrollTop
151
- let parentBottom = parentTop + parent.clientHeight
152
-
153
- // Figure out if the child is fully visible in the scroll parent.
154
- if (childTop >= parentTop && childBottom <= parentBottom) {
155
- missing--
156
- } else {
157
- // Not fully visible, so we will use this child to calculate the height of
158
- // each item. We will also use this to calculate how much of the item is
159
- // already visible.
160
- elementAmountVisible = Math.max(
161
- 0,
162
- Math.min(childBottom, parentBottom) - Math.max(childTop, parentTop)
163
- )
164
- elementHeight = child.clientHeight
165
- break
166
- }
167
- }
168
- }
169
-
170
- // There are fewer visible items than we want, so we will try to nudge the offset
171
- // to show more items.
172
- if (missing >= 1) {
173
- setInnerOffset((existingOffset) => {
174
- let newInnerOffset =
175
- elementHeight * missing - // `missing` amount of `elementHeight`
176
- elementAmountVisible + // The amount of the last item that is visible
177
- scrollPaddingBottom // The scroll padding to ensure the UI looks good
178
-
179
- // Nudged enough already, no need to continue
180
- if (existingOffset >= newInnerOffset) {
181
- return existingOffset
182
- }
183
-
184
- return newInnerOffset
185
- })
186
- }
95
+ let floatingStyles = $state();
96
+ let context = $state();
97
+ let currentComputeId = $state(0);
98
+ $effect(() => {
99
+ if (!referenceEl || !floatingEl)
100
+ return;
101
+ const computeId = untrack(() => currentComputeId + 1);
102
+ currentComputeId = computeId;
103
+ computePosition(referenceEl, floatingEl, {
104
+ placement: to === "selection"
105
+ ? align === "center"
106
+ ? "bottom"
107
+ : `bottom-${align}`
108
+ : align === "center"
109
+ ? `${to}`
110
+ : `${to}-${align}`,
111
+ // This component will be used in combination with a `Portal`, which means the floating
112
+ // element will be rendered outside of the current DOM tree.
113
+ strategy: "absolute",
114
+ middleware: [
115
+ // - The `mainAxis` is set to `gap` which defines the gap between the panel and the
116
+ // trigger/reference.
117
+ // - The `crossAxis` is set to `offset` which nudges the panel from its original position.
118
+ //
119
+ // When we are showing the panel on top of the selected item, we don't want a gap between the
120
+ // reference and the panel, therefore setting the `mainAxis` to `0`.
121
+ offsetMiddleware({
122
+ mainAxis: to === "selection" ? 0 : gap,
123
+ crossAxis: offset,
124
+ }),
125
+ // When the panel overflows the viewport, we will try to nudge the panel to the other side to
126
+ // ensure it's not clipped. We use the `padding` to define the minimum space between the
127
+ // panel and the viewport.
128
+ shiftMiddleware({ padding }),
129
+ // The `flip` middleware will swap the `placement` of the panel if there is not enough room.
130
+ // This is not compatible with the `inner` middleware (which is only enabled when `to` is set
131
+ // to "selection").
132
+ to !== "selection" && flipMiddleware({ padding }),
133
+ // The `inner` middleware will ensure the panel is always fully visible on screen and
134
+ // positioned on top of the reference and moved to the currently selected item.
135
+ to === "selection" && inner
136
+ ? null /* TODO: use inner when available: innerMiddleware({
137
+ ...inner,
138
+ padding, // For overflow detection
139
+ overflowRef,
140
+ offset: innerOffset,
141
+ minItemsVisible: MINIMUM_ITEMS_VISIBLE,
142
+ referenceOverflowThreshold: padding,
143
+ onFallbackChange(fallback) {
144
+ if (!fallback) return
145
+ let parent = context.elements.floating
146
+ if (!parent) return
147
+ let scrollPaddingBottom =
148
+ parseFloat(getComputedStyle(parent!).scrollPaddingBottom) || 0
149
+
150
+ // We want at least X visible items, but if there are less than X items in the list,
151
+ // we want to show as many as possible.
152
+ let missing = Math.min(MINIMUM_ITEMS_VISIBLE, parent.childElementCount)
153
+
154
+ let elementHeight = 0
155
+ let elementAmountVisible = 0
156
+
157
+ for (let child of context.elements.floating?.childNodes ?? []) {
158
+ if (child instanceof HTMLElement) {
159
+ let childTop = child.offsetTop
160
+ // It can be that the child is fully visible, but we also want to keep the scroll
161
+ // padding into account to ensure the UI looks good. Therefore we fake that the
162
+ // bottom of the child is actually `scrollPaddingBottom` amount of pixels lower.
163
+ let childBottom = childTop + child.clientHeight + scrollPaddingBottom
164
+
165
+ let parentTop = parent.scrollTop
166
+ let parentBottom = parentTop + parent.clientHeight
167
+
168
+ // Figure out if the child is fully visible in the scroll parent.
169
+ if (childTop >= parentTop && childBottom <= parentBottom) {
170
+ missing--
171
+ } else {
172
+ // Not fully visible, so we will use this child to calculate the height of
173
+ // each item. We will also use this to calculate how much of the item is
174
+ // already visible.
175
+ elementAmountVisible = Math.max(
176
+ 0,
177
+ Math.min(childBottom, parentBottom) - Math.max(childTop, parentTop)
178
+ )
179
+ elementHeight = child.clientHeight
180
+ break
181
+ }
182
+ }
183
+ }
184
+
185
+ // There are fewer visible items than we want, so we will try to nudge the offset
186
+ // to show more items.
187
+ if (missing >= 1) {
188
+ setInnerOffset((existingOffset) => {
189
+ let newInnerOffset =
190
+ elementHeight * missing - // `missing` amount of `elementHeight`
191
+ elementAmountVisible + // The amount of the last item that is visible
192
+ scrollPaddingBottom // The scroll padding to ensure the UI looks good
193
+
194
+ // Nudged enough already, no need to continue
195
+ if (existingOffset >= newInnerOffset) {
196
+ return existingOffset
197
+ }
198
+
199
+ return newInnerOffset
200
+ })
201
+ }
202
+ },
203
+ })*/
204
+ : null,
205
+ // The `size` middleware will ensure the panel is never bigger than the viewport minus the
206
+ // provided `padding` that we want.
207
+ sizeMiddleware({
208
+ padding,
209
+ apply({ availableWidth, availableHeight, elements }) {
210
+ Object.assign(elements.floating.style, {
211
+ overflow: "auto",
212
+ maxWidth: `${availableWidth}px`,
213
+ maxHeight: `min(var(--anchor-max-height, 100vh), ${availableHeight}px)`,
214
+ });
187
215
  },
188
- })*/
189
- : null,
190
- // The `size` middleware will ensure the panel is never bigger than the viewport minus the
191
- // provided `padding` that we want.
192
- sizeMiddleware({
193
- padding,
194
- apply({ availableWidth, availableHeight, elements }) {
195
- Object.assign(elements.floating.style, {
196
- overflow: "auto",
197
- maxWidth: `${availableWidth}px`,
198
- maxHeight: `min(var(--anchor-max-height, 100vh), ${availableHeight}px)`,
199
- });
200
- },
201
- }),
202
- ].filter(Boolean),
203
- whileElementsMounted: autoUpdate,
204
- }));
216
+ }),
217
+ ].filter(Boolean),
218
+ }).then((res) => {
219
+ if (currentComputeId === computeId) {
220
+ // Ensure only the last compute updates the context if multiple are running in parallel
221
+ context = res;
222
+ const { x, y } = res;
223
+ floatingStyles = `position: absolute; left: ${x}px; top: ${y}px;`;
224
+ }
225
+ });
226
+ });
205
227
  // Calculate placement information to expose as data attributes
206
- let [exposedTo = to, exposedAlign = align] = context.placement.split("-");
228
+ let [exposedTo = to, exposedAlign = align] = context?.placement.split("-") ?? [];
207
229
  // If user-land code is using custom styles specifically for `bottom`, but
208
230
  // they chose `selection`, then we want to make sure to map it to selection
209
231
  // again otherwise styles could be wrong.
@@ -216,35 +238,17 @@ export const createFloatingContext = ({ enabled = true } = {}) => {
216
238
  overflowRef,
217
239
  onChange: setInnerOffset,
218
240
  })*/
219
- let { getReferenceProps, getFloatingProps } = useInteractions([
220
- /*innerOffsetConfig*/
221
- ]);
222
- let setFloatingRef = (el) => {
223
- floatingEl = el || null;
224
- elements.floating = el;
225
- };
226
- /*
227
-
228
- return (
229
- <PlacementContext.Provider value={setConfig}>
230
- <FloatingContext.Provider
231
- value={{
232
- setFloating: setFloatingRef,
233
- setReference: refs.setReference,
234
- styles: floatingStyles,
235
- getReferenceProps,
236
- getFloatingProps,
237
- slot: data,
238
- }}
239
- >
240
- {children}
241
- </FloatingContext.Provider>
242
- </PlacementContext.Provider>
243
- )*/
241
+ const getReferenceProps = () => ({});
242
+ const getFloatingProps = () => ({});
243
+ /*let { getReferenceProps, getFloatingProps } = useInteractions([
244
+ innerOffsetConfig
245
+ ])*/
244
246
  const floatingContext = {
245
- setFloating: setFloatingRef,
247
+ setFloating: (floating) => {
248
+ floatingEl = floating || null;
249
+ },
246
250
  setReference: (reference) => {
247
- elements.reference = reference;
251
+ referenceEl = reference || null;
248
252
  },
249
253
  get styles() {
250
254
  return floatingStyles;
@@ -256,7 +260,9 @@ export const createFloatingContext = ({ enabled = true } = {}) => {
256
260
  },
257
261
  };
258
262
  setContext("FloatingContext", floatingContext);
259
- setContext("PlacementContext", null);
263
+ setContext("PlacementContext", (value) => {
264
+ config = value;
265
+ });
260
266
  return floatingContext;
261
267
  };
262
268
  function useFixScrollingPixel(element) {
@@ -308,7 +314,9 @@ function useResolvedConfig({ config, element, }) {
308
314
  },
309
315
  });
310
316
  return {
311
- ...config,
317
+ get to() {
318
+ return config?.to;
319
+ },
312
320
  get gap() {
313
321
  return gap.value;
314
322
  },
@@ -318,6 +326,9 @@ function useResolvedConfig({ config, element, }) {
318
326
  get padding() {
319
327
  return padding.value;
320
328
  },
329
+ get inner() {
330
+ return config?.inner;
331
+ },
321
332
  };
322
333
  }
323
334
  function useResolvePxValue({ input, element, defaultValue, }) {
@@ -1,7 +1,7 @@
1
1
  type IdContext = {
2
2
  value?: string;
3
3
  };
4
- export declare function useProvidedId(): IdContext;
4
+ export declare function useProvidedId(): IdContext | undefined;
5
5
  export declare function useIdContext(options: {
6
6
  id?: string;
7
7
  }): void;
@@ -7,7 +7,7 @@ export declare enum State {
7
7
  export type OpenClosedContext = {
8
8
  readonly value: State;
9
9
  };
10
- export declare function useOpenClosed(): OpenClosedContext;
10
+ export declare function useOpenClosed(): OpenClosedContext | null;
11
11
  export declare function createOpenClosedContext(options: {
12
12
  readonly value: State;
13
13
  }): void;
@@ -7,7 +7,7 @@ export var State;
7
7
  State[State["Opening"] = 8] = "Opening";
8
8
  })(State || (State = {}));
9
9
  export function useOpenClosed() {
10
- return getContext("OpenClosedContext");
10
+ return getContext("OpenClosedContext") ?? null;
11
11
  }
12
12
  export function createOpenClosedContext(options) {
13
13
  setContext("OpenClosedContext", options);
@@ -1,74 +1,21 @@
1
- <script lang="ts" context="module">import { setContext } from "svelte";
2
- const DEFAULT_LABEL_TAG = "label";
3
- export function useLabelContext() {
4
- let context = getContext("LabelContext");
5
- if (context === null) {
6
- let err = new Error("You used a <Label /> component, but it is not inside a relevant parent.");
7
- if (Error.captureStackTrace) Error.captureStackTrace(err, useLabelContext);
8
- throw err;
9
- }
10
- return context;
11
- }
12
- export function useLabelledBy(alwaysAvailableIds) {
13
- const context = getContext("LabelContext");
14
- const value = $derived(
15
- (alwaysAvailableIds?.length ?? 0) > 0 ? [context?.value, ...alwaysAvailableIds].filter(Boolean).join(" ") : context?.value
16
- );
17
- return {
18
- get value() {
19
- return value;
20
- }
21
- };
22
- }
23
- export const useLabels = (options = {}) => {
24
- const { slot, name, props, inherit } = $derived(options);
25
- const parentLabelledBy = useLabelledBy();
26
- let labelIds = $state([]);
27
- const allLabelIds = $derived(inherit && parentLabelledBy.value ? [parentLabelledBy.value, ...labelIds] : labelIds);
28
- const value = $derived(allLabelIds.length > 0 ? allLabelIds.join(" ") : void 0);
29
- const context = {
30
- get slot() {
31
- return slot;
32
- },
33
- get name() {
34
- return name;
35
- },
36
- get props() {
37
- return props;
38
- },
39
- get value() {
40
- return value;
41
- },
42
- register(value2) {
43
- labelIds.push(value2);
44
- return () => {
45
- const clone = labelIds.slice();
46
- const idx = clone.indexOf(value2);
47
- if (idx !== -1) clone.splice(idx, 1);
48
- labelIds = clone;
49
- return labelIds;
50
- };
51
- }
52
- };
53
- setContext("LabelContext", context);
54
- return context;
55
- };
1
+ <script lang="ts" module>let DEFAULT_LABEL_TAG = "label";
56
2
  </script>
57
3
 
58
- <script lang="ts" generics="TTag extends keyof SvelteHTMLElements">import { getContext, onMount } from "svelte";
4
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_LABEL_TAG">import { onMount } from "svelte";
59
5
  import { getIdContext, htmlid } from "../utils/id.js";
60
6
  import { useDisabled } from "../hooks/use-disabled.js";
61
7
  import { stateFromSlot } from "../utils/state.js";
8
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte";
9
+ import { useLabelContext } from "./context.svelte.js";
62
10
  const internalId = htmlid();
63
11
  const context = useLabelContext();
64
12
  const providedHtmlFor = getIdContext();
65
13
  const providedDisabled = useDisabled();
66
14
  let {
67
- as,
15
+ ref = $bindable(),
68
16
  id = `headlessui-label-${internalId}`,
69
17
  htmlFor = providedHtmlFor,
70
18
  passive = false,
71
- children,
72
19
  ...theirOriginalProps
73
20
  } = $props();
74
21
  onMount(() => {
@@ -115,6 +62,10 @@ const theirProps = $derived.by(() => {
115
62
  });
116
63
  </script>
117
64
 
118
- <svelte:element this={as ?? (htmlFor ? DEFAULT_LABEL_TAG : "div")} {...ourProps} {...theirProps}>
119
- {#if children}{@render children(slot)}{/if}
120
- </svelte:element>
65
+ <ElementOrComponent
66
+ {ourProps}
67
+ {theirProps}
68
+ defaultTag={htmlFor ? DEFAULT_LABEL_TAG : "div"}
69
+ name={context.name || "Label"}
70
+ bind:ref
71
+ />