@pzerelles/headlessui-svelte 2.1.2-next.31 → 2.1.2-next.33

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 (123) hide show
  1. package/dist/button/Button.svelte +84 -55
  2. package/dist/button/Button.svelte.d.ts +4 -32
  3. package/dist/checkbox/Checkbox.svelte +177 -121
  4. package/dist/checkbox/Checkbox.svelte.d.ts +14 -32
  5. package/dist/close-button/CloseButton.svelte +10 -7
  6. package/dist/close-button/CloseButton.svelte.d.ts +2 -44
  7. package/dist/data-interactive/DataInteractive.svelte +49 -37
  8. package/dist/data-interactive/DataInteractive.svelte.d.ts +7 -30
  9. package/dist/description/Description.svelte +35 -22
  10. package/dist/description/Description.svelte.d.ts +7 -28
  11. package/dist/dialog/Dialog.svelte +326 -232
  12. package/dist/dialog/Dialog.svelte.d.ts +4 -42
  13. package/dist/dialog/DialogBackdrop.svelte +33 -16
  14. package/dist/dialog/DialogBackdrop.svelte.d.ts +4 -29
  15. package/dist/dialog/DialogPanel.svelte +60 -29
  16. package/dist/dialog/DialogPanel.svelte.d.ts +4 -30
  17. package/dist/dialog/DialogTitle.svelte +51 -24
  18. package/dist/dialog/DialogTitle.svelte.d.ts +6 -27
  19. package/dist/field/Field.svelte +44 -28
  20. package/dist/field/Field.svelte.d.ts +4 -30
  21. package/dist/fieldset/Fieldset.svelte +48 -30
  22. package/dist/fieldset/Fieldset.svelte.d.ts +5 -31
  23. package/dist/focus-trap/FocusTrap.svelte +430 -298
  24. package/dist/focus-trap/FocusTrap.svelte.d.ts +5 -34
  25. package/dist/hooks/use-inert-others.svelte.js +10 -10
  26. package/dist/hooks/use-resolve-button-type.svelte.js +0 -1
  27. package/dist/input/Input.svelte +95 -54
  28. package/dist/input/Input.svelte.d.ts +13 -27
  29. package/dist/internal/FloatingProvider.svelte +14 -9
  30. package/dist/internal/FocusSentinel.svelte +49 -40
  31. package/dist/internal/ForcePortalRoot.svelte +7 -3
  32. package/dist/internal/FormFields.svelte +47 -34
  33. package/dist/internal/FormFieldsProvider.svelte +9 -5
  34. package/dist/internal/FormResolver.svelte +25 -16
  35. package/dist/internal/Hidden.svelte +45 -38
  36. package/dist/internal/Hidden.svelte.d.ts +4 -30
  37. package/dist/internal/MainTreeProvider.svelte +90 -37
  38. package/dist/internal/Portal.svelte +18 -14
  39. package/dist/label/Label.svelte +100 -59
  40. package/dist/label/Label.svelte.d.ts +7 -32
  41. package/dist/legend/Legend.svelte +27 -4
  42. package/dist/legend/Legend.svelte.d.ts +4 -3
  43. package/dist/listbox/Listbox.svelte +518 -391
  44. package/dist/listbox/Listbox.svelte.d.ts +11 -35
  45. package/dist/listbox/ListboxButton.svelte +175 -128
  46. package/dist/listbox/ListboxButton.svelte.d.ts +5 -32
  47. package/dist/listbox/ListboxOption.svelte +171 -130
  48. package/dist/listbox/ListboxOption.svelte.d.ts +12 -26
  49. package/dist/listbox/ListboxOptions.svelte +403 -305
  50. package/dist/listbox/ListboxOptions.svelte.d.ts +4 -38
  51. package/dist/listbox/ListboxSelectedOption.svelte +40 -19
  52. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +8 -33
  53. package/dist/menu/Menu.svelte +76 -52
  54. package/dist/menu/Menu.svelte.d.ts +3 -31
  55. package/dist/menu/MenuButton.svelte +158 -118
  56. package/dist/menu/MenuButton.svelte.d.ts +4 -34
  57. package/dist/menu/MenuHeading.svelte +34 -15
  58. package/dist/menu/MenuHeading.svelte.d.ts +4 -31
  59. package/dist/menu/MenuItem.svelte +143 -108
  60. package/dist/menu/MenuItem.svelte.d.ts +5 -32
  61. package/dist/menu/MenuItems.svelte +301 -230
  62. package/dist/menu/MenuItems.svelte.d.ts +4 -38
  63. package/dist/menu/MenuSection.svelte +26 -10
  64. package/dist/menu/MenuSection.svelte.d.ts +5 -29
  65. package/dist/menu/MenuSeparator.svelte +20 -5
  66. package/dist/menu/MenuSeparator.svelte.d.ts +5 -28
  67. package/dist/popover/Popover.svelte +217 -151
  68. package/dist/popover/Popover.svelte.d.ts +4 -30
  69. package/dist/popover/PopoverBackdrop.svelte +71 -42
  70. package/dist/popover/PopoverBackdrop.svelte.d.ts +6 -34
  71. package/dist/popover/PopoverButton.svelte +302 -222
  72. package/dist/popover/PopoverButton.svelte.d.ts +6 -29
  73. package/dist/popover/PopoverGroup.svelte +64 -36
  74. package/dist/popover/PopoverGroup.svelte.d.ts +5 -28
  75. package/dist/popover/PopoverPanel.svelte +335 -248
  76. package/dist/popover/PopoverPanel.svelte.d.ts +5 -36
  77. package/dist/popover/index.d.ts +1 -1
  78. package/dist/portal/InternalPortal.svelte +143 -86
  79. package/dist/portal/InternalPortal.svelte.d.ts +4 -30
  80. package/dist/portal/Portal.svelte +8 -4
  81. package/dist/portal/Portal.svelte.d.ts +2 -18
  82. package/dist/portal/PortalGroup.svelte +23 -10
  83. package/dist/portal/PortalGroup.svelte.d.ts +3 -31
  84. package/dist/select/Select.svelte +100 -69
  85. package/dist/select/Select.svelte.d.ts +5 -32
  86. package/dist/switch/Switch.svelte +181 -133
  87. package/dist/switch/Switch.svelte.d.ts +5 -38
  88. package/dist/switch/SwitchGroup.svelte +45 -32
  89. package/dist/switch/SwitchGroup.svelte.d.ts +7 -28
  90. package/dist/tabs/Tab.svelte +195 -143
  91. package/dist/tabs/Tab.svelte.d.ts +4 -32
  92. package/dist/tabs/TabGroup.svelte +87 -57
  93. package/dist/tabs/TabGroup.svelte.d.ts +4 -34
  94. package/dist/tabs/TabList.svelte +31 -12
  95. package/dist/tabs/TabList.svelte.d.ts +5 -28
  96. package/dist/tabs/TabPanel.svelte +69 -44
  97. package/dist/tabs/TabPanel.svelte.d.ts +4 -34
  98. package/dist/tabs/TabPanels.svelte +19 -8
  99. package/dist/tabs/TabPanels.svelte.d.ts +5 -27
  100. package/dist/textarea/Textarea.svelte +87 -54
  101. package/dist/textarea/Textarea.svelte.d.ts +13 -27
  102. package/dist/transition/InternalTransitionChild.svelte +267 -171
  103. package/dist/transition/InternalTransitionChild.svelte.d.ts +3 -33
  104. package/dist/transition/Transition.svelte +88 -67
  105. package/dist/transition/Transition.svelte.d.ts +3 -36
  106. package/dist/transition/TransitionChild.svelte +31 -12
  107. package/dist/transition/TransitionChild.svelte.d.ts +8 -35
  108. package/dist/transition/context.svelte.js +7 -7
  109. package/dist/utils/DisabledProvider.svelte +7 -3
  110. package/dist/utils/ElementOrComponent.svelte +88 -24
  111. package/dist/utils/ElementOrComponent.svelte.d.ts +32 -27
  112. package/dist/utils/StableCollection.svelte +54 -36
  113. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +27 -12
  114. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +88 -44
  115. package/dist/utils/state.js +4 -4
  116. package/dist/utils/types.d.ts +14 -12
  117. package/package.json +12 -12
  118. package/dist/combobox/Combobox.svelte +0 -6
  119. package/dist/combobox/Combobox.svelte.d.ts +0 -50
  120. package/dist/utils/Generic.svelte +0 -46
  121. package/dist/utils/Generic.svelte.d.ts +0 -32
  122. package/dist/utils/alternative-types.d.ts +0 -20
  123. package/dist/utils/alternative-types.js +0 -1
@@ -1,228 +1,306 @@
1
- <script lang="ts" module>const DEFAULT_BUTTON_TAG = "button";
1
+ <script lang="ts" module>
2
+ import type { Props } from "../utils/types.js"
3
+
4
+ const DEFAULT_BUTTON_TAG = "button" as const
5
+ export type PopoverButtonSlot = {
6
+ open: boolean
7
+ active: boolean
8
+ hover: boolean
9
+ focus: boolean
10
+ disabled: boolean
11
+ autofocus: boolean
12
+ }
13
+ export type PopoverButtonPropsWeControl = "aria-controls" | "aria-expanded"
14
+
15
+ export type PopoverButtonProps = Props<
16
+ typeof DEFAULT_BUTTON_TAG,
17
+ PopoverButtonSlot,
18
+ {
19
+ element?: HTMLElement
20
+ id?: string
21
+ disabled?: boolean
22
+ autofocus?: boolean
23
+ }
24
+ >
2
25
  </script>
3
26
 
4
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_BUTTON_TAG">import { useId } from "../hooks/use-id.js";
5
- import {
6
- PopoverStates,
7
- usePopoverAPIContext,
8
- usePopoverContext,
9
- usePopoverGroupContext,
10
- usePopoverPanelContext
11
- } from "./context.svelte.js";
12
- import { useFloatingReference } from "../internal/floating.svelte.js";
13
- import { untrack } from "svelte";
14
- import { getOwnerDocument } from "../utils/owner.js";
15
- import { useFocusRing } from "../hooks/use-focus-ring.svelte.js";
16
- import { useHover } from "../hooks/use-hover.svelte.js";
17
- import { useActivePress } from "../hooks/use-active-press.svelte.js";
18
- import { useResolveButtonType } from "../hooks/use-resolve-button-type.svelte.js";
19
- import { mergeProps } from "../utils/render.js";
20
- import { useTabDirection, Direction as TabDirection } from "../hooks/use-tab-direction.svelte.js";
21
- import { match } from "../utils/match.js";
22
- import { Focus, focusIn, FocusResult, getFocusableElements } from "../utils/focus-management.js";
23
- import { microTask } from "../utils/microTask.js";
24
- import Hidden, { HiddenFeatures } from "../internal/Hidden.svelte";
25
- import ElementOrComponent from "../utils/ElementOrComponent.svelte";
26
- const internalId = useId();
27
- let {
28
- ref = $bindable(),
29
- id = `headlessui-popover-button-${internalId}`,
30
- disabled = false,
31
- autofocus = false,
32
- ...theirProps
33
- } = $props();
34
- const context = usePopoverContext("PopoverButton");
35
- const api = usePopoverAPIContext("PopoverButton");
36
- const { isPortalled } = $derived(api);
37
- const sentinelId = `headlessui-focus-sentinel-${useId()}`;
38
- const groupContext = usePopoverGroupContext();
39
- const closeOthers = $derived(groupContext?.closeOthers);
40
- const panelContext = usePopoverPanelContext();
41
- const isWithinPanel = panelContext !== void 0;
42
- $effect(() => {
43
- if (isWithinPanel) return;
44
- id;
45
- return untrack(() => {
46
- context.setButtonId(id);
47
- return () => {
48
- context.setButtonId(void 0);
49
- };
50
- });
51
- });
52
- const uniqueIdentifier = Symbol();
53
- const floatingReference = useFloatingReference();
54
- const { setReference } = $derived(floatingReference);
55
- $effect(() => {
56
- setReference(ref);
57
- });
58
- $effect(() => {
59
- if (isWithinPanel) return;
60
- ref;
61
- untrack(() => {
62
- if (ref) {
63
- context.buttons.push(uniqueIdentifier);
27
+ <script lang="ts">
28
+ import { useId } from "../hooks/use-id.js"
29
+ import {
30
+ PopoverStates,
31
+ usePopoverAPIContext,
32
+ usePopoverContext,
33
+ usePopoverGroupContext,
34
+ usePopoverPanelContext,
35
+ } from "./context.svelte.js"
36
+ import { useFloatingReference } from "../internal/floating.svelte.js"
37
+ import { untrack } from "svelte"
38
+ import { getOwnerDocument } from "../utils/owner.js"
39
+ import { useFocusRing } from "../hooks/use-focus-ring.svelte.js"
40
+ import { useHover } from "../hooks/use-hover.svelte.js"
41
+ import { useActivePress } from "../hooks/use-active-press.svelte.js"
42
+ import { useResolveButtonType } from "../hooks/use-resolve-button-type.svelte.js"
43
+ import { mergeProps } from "../utils/render.js"
44
+ import { useTabDirection, Direction as TabDirection } from "../hooks/use-tab-direction.svelte.js"
45
+ import { match } from "../utils/match.js"
46
+ import { Focus, focusIn, FocusResult, getFocusableElements } from "../utils/focus-management.js"
47
+ import { microTask } from "../utils/microTask.js"
48
+ import Hidden, { HiddenFeatures } from "../internal/Hidden.svelte"
49
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte"
50
+
51
+ const internalId = useId()
52
+ let {
53
+ element = $bindable(),
54
+ id = `headlessui-popover-button-${internalId}`,
55
+ disabled = false,
56
+ autofocus = false,
57
+ ...theirProps
58
+ }: PopoverButtonProps = $props()
59
+ const context = usePopoverContext("PopoverButton")
60
+ const api = usePopoverAPIContext("PopoverButton")
61
+ const { isPortalled } = $derived(api)
62
+
63
+ const sentinelId = `headlessui-focus-sentinel-${useId()}`
64
+
65
+ const groupContext = usePopoverGroupContext()
66
+ const closeOthers = $derived(groupContext?.closeOthers)
67
+
68
+ const panelContext = usePopoverPanelContext()
69
+
70
+ // A button inside a panel will just have "close" functionality, no "open" functionality. However,
71
+ // if a `PopoverButton` is rendered inside a `Popover` which in turn is rendered inside a
72
+ // `PopoverPanel` (aka nested popovers), then we need to make sure that the button is able to
73
+ // open the nested popover.
74
+ //
75
+ // The `Popover` itself will also render a `PopoverPanelContext` but with a value of `null`. That
76
+ // way we don't need to keep track of _which_ `PopoverPanel` (if at all) we are in, we can just
77
+ // check if we are in a `PopoverPanel` or not since this will always point to the nearest one and
78
+ // won't pierce through `Popover` components themselves.
79
+ const isWithinPanel = panelContext !== undefined
80
+
81
+ $effect(() => {
82
+ // [isWithinPanel, id, dispatch]
83
+ if (isWithinPanel) return
84
+ id
85
+ return untrack(() => {
86
+ context.setButtonId(id)
87
+ return () => {
88
+ context.setButtonId(undefined)
89
+ }
90
+ })
91
+ })
92
+
93
+ // This is a little bit different compared to the `id` we already have. The goal is to have a very
94
+ // unique identifier for this specific component. This can be achieved with the `id` from above.
95
+ //
96
+ // However, the difference is for React 17 and lower where the `useId` hook doesn't exist yet.
97
+ // There we will generate a unique ID based on a simple counter, but for SSR this will result in
98
+ // `undefined` first, later it is patched to be a unique ID. The problem is that this patching
99
+ // happens after the component is rendered and therefore there is a moment in time where multiple
100
+ // buttons have the exact same ID and the `state.buttons` would result in something like:
101
+ //
102
+ // ```js
103
+ // ['headlessui-popover-button-undefined', 'headlessui-popover-button-1']
104
+ // ```
105
+ //
106
+ // With this approach we guarantee that there is a unique value for each button.
107
+ const uniqueIdentifier = Symbol()
108
+
109
+ const floatingReference = useFloatingReference()
110
+ const { setReference } = $derived(floatingReference)
111
+ $effect(() => {
112
+ setReference(element)
113
+ })
114
+ $effect(() => {
115
+ if (isWithinPanel) return
116
+ element
117
+ untrack(() => {
118
+ if (element) {
119
+ context.buttons.push(uniqueIdentifier)
120
+ } else {
121
+ let idx = context.buttons.indexOf(uniqueIdentifier)
122
+ if (idx !== -1) context.buttons.splice(idx, 1)
123
+ }
124
+
125
+ if (context.buttons.length > 1) {
126
+ console.warn("You are already using a <PopoverButton /> but only 1 <PopoverButton /> is supported.")
127
+ }
128
+
129
+ if (element) context.setButton(element)
130
+ })
131
+ })
132
+ const ownerDocument = $derived(getOwnerDocument(element))
133
+
134
+ const handleKeyDown = (event: KeyboardEvent) => {
135
+ if (isWithinPanel) {
136
+ if (context.popoverState === PopoverStates.Closed) return
137
+ switch (event.key) {
138
+ case "Space":
139
+ case "Enter":
140
+ event.preventDefault() // Prevent triggering a *click* event
141
+ // @ts-expect-error
142
+ event.target.click?.()
143
+ context.closePopover()
144
+ context.button?.focus() // Re-focus the original opening Button
145
+ break
146
+ }
64
147
  } else {
65
- let idx = context.buttons.indexOf(uniqueIdentifier);
66
- if (idx !== -1) context.buttons.splice(idx, 1);
67
- }
68
- if (context.buttons.length > 1) {
69
- console.warn("You are already using a <PopoverButton /> but only 1 <PopoverButton /> is supported.");
70
- }
71
- if (ref) context.setButton(ref);
72
- });
73
- });
74
- const ownerDocument = $derived(getOwnerDocument(ref));
75
- const handleKeyDown = (event) => {
76
- if (isWithinPanel) {
77
- if (context.popoverState === PopoverStates.Closed) return;
78
- switch (event.key) {
79
- case "Space":
80
- case "Enter":
81
- event.preventDefault();
82
- event.target.click?.();
83
- context.closePopover();
84
- context.button?.focus();
85
- break;
86
- }
87
- } else {
88
- switch (event.key) {
89
- case "Space":
90
- case "Enter":
91
- event.preventDefault();
92
- event.stopPropagation();
93
- if (context.popoverState === PopoverStates.Closed) closeOthers?.(context.buttonId);
94
- context.togglePopover();
95
- break;
96
- case "Escape":
97
- if (context.popoverState !== PopoverStates.Open) return closeOthers?.(context.buttonId);
98
- if (!ref) return;
99
- if (ownerDocument?.activeElement && !ref.contains(ownerDocument.activeElement)) {
100
- return;
101
- }
102
- event.preventDefault();
103
- event.stopPropagation();
104
- context.closePopover();
105
- break;
148
+ switch (event.key) {
149
+ case "Space":
150
+ case "Enter":
151
+ event.preventDefault() // Prevent triggering a *click* event
152
+ event.stopPropagation()
153
+ if (context.popoverState === PopoverStates.Closed) closeOthers?.(context.buttonId!)
154
+ context.togglePopover()
155
+ break
156
+
157
+ case "Escape":
158
+ if (context.popoverState !== PopoverStates.Open) return closeOthers?.(context.buttonId!)
159
+ if (!element) return
160
+ if (ownerDocument?.activeElement && !element.contains(ownerDocument.activeElement)) {
161
+ return
162
+ }
163
+ event.preventDefault()
164
+ event.stopPropagation()
165
+ context.closePopover()
166
+ break
167
+ }
106
168
  }
107
169
  }
108
- };
109
- const handleKeyUp = (event) => {
110
- if (isWithinPanel) return;
111
- if (event.key === "Space") {
112
- event.preventDefault();
113
- }
114
- };
115
- const handleClick = (event) => {
116
- if (disabled) return;
117
- if (isWithinPanel) {
118
- context.closePopover();
119
- context.button?.focus();
120
- } else {
121
- event.preventDefault();
122
- event.stopPropagation();
123
- if (context.popoverState === PopoverStates.Closed) closeOthers?.(context.buttonId);
124
- context.togglePopover();
125
- context.button?.focus();
126
- }
127
- };
128
- const handleMouseDown = (event) => {
129
- event.preventDefault();
130
- event.stopPropagation();
131
- };
132
- const { isFocusVisible: focus, focusProps } = $derived(
133
- useFocusRing({
134
- get autofocus() {
135
- return autofocus;
136
- }
137
- })
138
- );
139
- const { isHovered: hover, hoverProps } = $derived(
140
- useHover({
141
- get disabled() {
142
- return disabled;
170
+
171
+ const handleKeyUp = (event: KeyboardEvent) => {
172
+ if (isWithinPanel) return
173
+ if (event.key === "Space") {
174
+ // Required for firefox, event.preventDefault() in handleKeyDown for
175
+ // the Space key doesn't cancel the handleKeyUp, which in turn
176
+ // triggers a *click*.
177
+ event.preventDefault()
143
178
  }
144
- })
145
- );
146
- const { pressed: active, pressProps } = $derived(
147
- useActivePress({
148
- get disabled() {
149
- return disabled;
179
+ }
180
+
181
+ const handleClick = (event: MouseEvent) => {
182
+ //if (isDisabledReactIssue7711(event.currentTarget)) return
183
+ if (disabled) return
184
+ if (isWithinPanel) {
185
+ context.closePopover()
186
+ context.button?.focus() // Re-focus the original opening Button
187
+ } else {
188
+ event.preventDefault()
189
+ event.stopPropagation()
190
+ if (context.popoverState === PopoverStates.Closed) closeOthers?.(context.buttonId!)
191
+ context.togglePopover()
192
+ context.button?.focus()
150
193
  }
151
- })
152
- );
153
- const visible = $derived(context.popoverState === PopoverStates.Open);
154
- const slot = $derived({
155
- open: visible,
156
- active: active || visible,
157
- disabled,
158
- hover,
159
- focus,
160
- autofocus
161
- });
162
- const type = useResolveButtonType({
163
- get props() {
164
- return { type: theirProps.type, as: theirProps.as };
165
- },
166
- get ref() {
167
- return { current: context.button };
168
194
  }
169
- });
170
- const ourProps = $derived(
171
- isWithinPanel ? mergeProps(
172
- {
173
- type,
174
- onkeydown: handleKeyDown,
175
- onclick: handleClick,
176
- disabled: disabled || void 0,
177
- autofocus
195
+
196
+ const handleMouseDown = (event: MouseEvent) => {
197
+ event.preventDefault()
198
+ event.stopPropagation()
199
+ }
200
+
201
+ const { isFocusVisible: focus, focusProps } = $derived(
202
+ useFocusRing({
203
+ get autofocus() {
204
+ return autofocus
205
+ },
206
+ })
207
+ )
208
+ const { isHovered: hover, hoverProps } = $derived(
209
+ useHover({
210
+ get disabled() {
211
+ return disabled
212
+ },
213
+ })
214
+ )
215
+ const { pressed: active, pressProps } = $derived(
216
+ useActivePress({
217
+ get disabled() {
218
+ return disabled
219
+ },
220
+ })
221
+ )
222
+
223
+ const visible = $derived(context.popoverState === PopoverStates.Open)
224
+ const slot = $derived({
225
+ open: visible,
226
+ active: active || visible,
227
+ disabled,
228
+ hover,
229
+ focus,
230
+ autofocus,
231
+ } satisfies PopoverButtonSlot)
232
+
233
+ const type = useResolveButtonType({
234
+ get props() {
235
+ return { type: theirProps.type ?? undefined, as: element ? element.tagName.toLowerCase() : DEFAULT_BUTTON_TAG }
178
236
  },
179
- focusProps,
180
- hoverProps,
181
- pressProps
182
- ) : mergeProps(
183
- {
184
- id: context.buttonId,
185
- type,
186
- "aria-expanded": context.popoverState === PopoverStates.Open,
187
- "aria-controls": context.panel ? context.panelId : void 0,
188
- disabled: disabled || void 0,
189
- autofocus,
190
- onkeydown: handleKeyDown,
191
- onkeyup: handleKeyUp,
192
- onclick: handleClick,
193
- onmousedown: handleMouseDown
237
+ get ref() {
238
+ return { current: context.button }
194
239
  },
195
- focusProps,
196
- hoverProps,
197
- pressProps
240
+ })
241
+ const ourProps = $derived(
242
+ isWithinPanel
243
+ ? mergeProps(
244
+ {
245
+ type,
246
+ onkeydown: handleKeyDown,
247
+ onclick: handleClick,
248
+ disabled: disabled || undefined,
249
+ autofocus,
250
+ },
251
+ focusProps,
252
+ hoverProps,
253
+ pressProps
254
+ )
255
+ : mergeProps(
256
+ {
257
+ id: context.buttonId,
258
+ type,
259
+ "aria-expanded": context.popoverState === PopoverStates.Open,
260
+ "aria-controls": context.panel ? context.panelId : undefined,
261
+ disabled: disabled || undefined,
262
+ autofocus,
263
+ onkeydown: handleKeyDown,
264
+ onkeyup: handleKeyUp,
265
+ onclick: handleClick,
266
+ onmousedown: handleMouseDown,
267
+ },
268
+ focusProps,
269
+ hoverProps,
270
+ pressProps
271
+ )
198
272
  )
199
- );
200
- const direction = useTabDirection();
201
- const handleFocus = () => {
202
- const el = context.panel;
203
- if (!el) return;
204
- function run() {
205
- let result = match(direction.current, {
206
- [TabDirection.Forwards]: () => focusIn(el, Focus.First),
207
- [TabDirection.Backwards]: () => focusIn(el, Focus.Last)
208
- });
209
- if (result === FocusResult.Error) {
210
- focusIn(
211
- getFocusableElements().filter((el2) => el2.dataset.headlessuiFocusGuard !== "true"),
212
- match(direction.current, {
213
- [TabDirection.Forwards]: Focus.Next,
214
- [TabDirection.Backwards]: Focus.Previous
215
- }),
216
- { relativeTo: context.button }
217
- );
273
+
274
+ const direction = useTabDirection()
275
+ const handleFocus = () => {
276
+ const el = context.panel as HTMLElement
277
+ if (!el) return
278
+
279
+ function run() {
280
+ let result = match(direction.current, {
281
+ [TabDirection.Forwards]: () => focusIn(el, Focus.First),
282
+ [TabDirection.Backwards]: () => focusIn(el, Focus.Last),
283
+ })
284
+
285
+ if (result === FocusResult.Error) {
286
+ focusIn(
287
+ getFocusableElements().filter((el) => el.dataset.headlessuiFocusGuard !== "true"),
288
+ match(direction.current, {
289
+ [TabDirection.Forwards]: Focus.Next,
290
+ [TabDirection.Backwards]: Focus.Previous,
291
+ }),
292
+ { relativeTo: context.button }
293
+ )
294
+ }
295
+ }
296
+
297
+ // TODO: Cleanup once we are using real browser tests
298
+ if (process.env.NODE_ENV === "test") {
299
+ microTask(run)
300
+ } else {
301
+ run()
218
302
  }
219
303
  }
220
- if (process.env.NODE_ENV === "test") {
221
- microTask(run);
222
- } else {
223
- run();
224
- }
225
- };
226
304
  </script>
227
305
 
228
306
  <ElementOrComponent
@@ -231,16 +309,18 @@ const handleFocus = () => {
231
309
  slots={slot}
232
310
  defaultTag={DEFAULT_BUTTON_TAG}
233
311
  name="PopoverButton"
234
- bind:ref
312
+ bind:element
235
313
  />
236
314
  {#if visible && !isWithinPanel && isPortalled}
237
- <Hidden
238
- id={sentinelId}
239
- bind:ref={context.afterButtonSentinel as HTMLElement}
240
- features={HiddenFeatures.Focusable}
241
- data-headlessui-focus-guard
242
- as="button"
243
- type="button"
244
- onfocus={handleFocus}
245
- />
315
+ <Hidden id={sentinelId} features={HiddenFeatures.Focusable} asChild>
316
+ {#snippet children({ props })}
317
+ <button
318
+ {...props}
319
+ type="button"
320
+ data-headlessui-focus-guard
321
+ onfocus={handleFocus}
322
+ bind:this={context.afterButtonSentinel}>&zwnj;</button
323
+ >
324
+ {/snippet}
325
+ </Hidden>
246
326
  {/if}
@@ -1,4 +1,4 @@
1
- import type { ElementType, Props, PropsOf } from "../utils/types.js";
1
+ import type { Props } from "../utils/types.js";
2
2
  declare const DEFAULT_BUTTON_TAG: "button";
3
3
  export type PopoverButtonSlot = {
4
4
  open: boolean;
@@ -9,34 +9,11 @@ export type PopoverButtonSlot = {
9
9
  autofocus: boolean;
10
10
  };
11
11
  export type PopoverButtonPropsWeControl = "aria-controls" | "aria-expanded";
12
- export type PopoverButtonComponentProps = {
12
+ export type PopoverButtonProps = Props<typeof DEFAULT_BUTTON_TAG, PopoverButtonSlot, {
13
+ element?: HTMLElement;
14
+ id?: string;
13
15
  disabled?: boolean;
14
16
  autofocus?: boolean;
15
- };
16
- export type PopoverButtonProps<TTag extends ElementType = typeof DEFAULT_BUTTON_TAG> = Props<TTag, PopoverButtonSlot, PopoverButtonPropsWeControl, PopoverButtonComponentProps>;
17
- declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_BUTTON_TAG> {
18
- props(): {
19
- as?: TTag | undefined;
20
- } & (Exclude<keyof PropsOf<TTag>, ("slot" | "as" | "children" | "class" | "ref") | PopoverButtonPropsWeControl | keyof PopoverButtonComponentProps> extends infer T extends keyof PropsOf<TTag> ? { [P in T]: PropsOf<TTag>[P]; } : never) & {
21
- children?: import("svelte").Snippet<[{
22
- slot: PopoverButtonSlot;
23
- props: Record<string, any>;
24
- }]> | undefined;
25
- class?: string | ((bag: PopoverButtonSlot) => string) | null | undefined;
26
- ref?: HTMLElement;
27
- } & PopoverButtonComponentProps;
28
- events(): {};
29
- slots(): {};
30
- bindings(): "ref";
31
- exports(): {};
32
- }
33
- interface $$IsomorphicComponent {
34
- new <TTag extends ElementType = typeof DEFAULT_BUTTON_TAG>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TTag>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TTag>['props']>, ReturnType<__sveltets_Render<TTag>['events']>, ReturnType<__sveltets_Render<TTag>['slots']>> & {
35
- $$bindings?: ReturnType<__sveltets_Render<TTag>['bindings']>;
36
- } & ReturnType<__sveltets_Render<TTag>['exports']>;
37
- <TTag extends ElementType = typeof DEFAULT_BUTTON_TAG>(internal: unknown, props: ReturnType<__sveltets_Render<TTag>['props']> & {}): ReturnType<__sveltets_Render<TTag>['exports']>;
38
- z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
39
- }
40
- declare const PopoverButton: $$IsomorphicComponent;
41
- type PopoverButton<TTag extends ElementType = typeof DEFAULT_BUTTON_TAG> = InstanceType<typeof PopoverButton<TTag>>;
17
+ }>;
18
+ declare const PopoverButton: import("svelte").Component<PopoverButtonProps, {}, "element">;
42
19
  export default PopoverButton;