@pzerelles/headlessui-svelte 2.1.2-next.29 → 2.1.2-next.30

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 (67) hide show
  1. package/dist/button/Button.svelte +54 -84
  2. package/dist/checkbox/Checkbox.svelte +120 -173
  3. package/dist/checkbox/Checkbox.svelte.d.ts +1 -1
  4. package/dist/close-button/CloseButton.svelte +6 -12
  5. package/dist/combobox/Combobox.svelte +3 -50
  6. package/dist/data-interactive/DataInteractive.svelte +29 -55
  7. package/dist/description/Description.svelte +21 -31
  8. package/dist/dialog/Dialog.svelte +228 -320
  9. package/dist/dialog/DialogBackdrop.svelte +12 -29
  10. package/dist/dialog/DialogPanel.svelte +25 -48
  11. package/dist/dialog/DialogTitle.svelte +23 -38
  12. package/dist/field/Field.svelte +25 -47
  13. package/dist/fieldset/Fieldset.svelte +29 -50
  14. package/dist/focus-trap/FocusTrap.svelte +283 -419
  15. package/dist/input/Input.svelte +53 -84
  16. package/dist/internal/FloatingProvider.svelte +9 -14
  17. package/dist/internal/FocusSentinel.svelte +8 -16
  18. package/dist/internal/ForcePortalRoot.svelte +3 -7
  19. package/dist/internal/FormFields.svelte +34 -47
  20. package/dist/internal/FormFieldsProvider.svelte +5 -9
  21. package/dist/internal/FormResolver.svelte +15 -20
  22. package/dist/internal/Hidden.svelte +29 -50
  23. package/dist/internal/MainTreeProvider.svelte +36 -89
  24. package/dist/internal/Portal.svelte +14 -18
  25. package/dist/label/Label.svelte +58 -93
  26. package/dist/legend/Legend.svelte +3 -12
  27. package/dist/listbox/Listbox.svelte +387 -525
  28. package/dist/listbox/Listbox.svelte.d.ts +1 -1
  29. package/dist/listbox/ListboxButton.svelte +127 -173
  30. package/dist/listbox/ListboxOption.svelte +129 -170
  31. package/dist/listbox/ListboxOptions.svelte +304 -400
  32. package/dist/listbox/ListboxSelectedOption.svelte +15 -38
  33. package/dist/menu/Menu.svelte +51 -78
  34. package/dist/menu/MenuButton.svelte +117 -157
  35. package/dist/menu/MenuHeading.svelte +14 -32
  36. package/dist/menu/MenuItem.svelte +107 -142
  37. package/dist/menu/MenuItems.svelte +229 -301
  38. package/dist/menu/MenuSection.svelte +9 -24
  39. package/dist/menu/MenuSeparator.svelte +4 -17
  40. package/dist/popover/Popover.svelte +150 -216
  41. package/dist/popover/PopoverBackdrop.svelte +41 -67
  42. package/dist/popover/PopoverButton.svelte +212 -292
  43. package/dist/popover/PopoverGroup.svelte +35 -62
  44. package/dist/popover/PopoverPanel.svelte +229 -311
  45. package/dist/portal/InternalPortal.svelte +85 -141
  46. package/dist/portal/Portal.svelte +2 -5
  47. package/dist/portal/PortalGroup.svelte +9 -30
  48. package/dist/select/Select.svelte +68 -98
  49. package/dist/switch/Switch.svelte +132 -179
  50. package/dist/switch/SwitchGroup.svelte +31 -44
  51. package/dist/tabs/Tab.svelte +142 -194
  52. package/dist/tabs/TabGroup.svelte +56 -86
  53. package/dist/tabs/TabGroup.svelte.d.ts +1 -1
  54. package/dist/tabs/TabList.svelte +11 -31
  55. package/dist/tabs/TabPanel.svelte +42 -67
  56. package/dist/tabs/TabPanels.svelte +7 -18
  57. package/dist/textarea/Textarea.svelte +53 -84
  58. package/dist/transition/InternalTransitionChild.svelte +170 -259
  59. package/dist/transition/Transition.svelte +66 -96
  60. package/dist/transition/TransitionChild.svelte +11 -31
  61. package/dist/utils/DisabledProvider.svelte +3 -7
  62. package/dist/utils/ElementOrComponent.svelte +23 -43
  63. package/dist/utils/Generic.svelte +16 -27
  64. package/dist/utils/StableCollection.svelte +36 -54
  65. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +12 -27
  66. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +44 -88
  67. package/package.json +4 -4
@@ -26,7 +26,7 @@ export * from "./context.svelte.js";
26
26
  declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_LISTBOX_TAG, TType = string, TActualType = TType extends (infer U)[] ? U : TType> {
27
27
  props(): {
28
28
  as?: TTag | undefined;
29
- } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, "form" | ("slot" | "as" | "children" | "class" | "ref") | "invalid" | "disabled" | "value" | "name" | "onchange" | "__demoMode" | "horizontal" | "defaultValue" | "by" | "multiple" | "closeOnSelect"> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
29
+ } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, "form" | ("slot" | "as" | "children" | "class" | "ref") | "invalid" | "disabled" | "value" | "name" | "onchange" | "multiple" | "__demoMode" | "horizontal" | "defaultValue" | "by" | "closeOnSelect"> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
30
30
  children?: Snippet<[{
31
31
  slot: ListboxRenderPropArg<TType>;
32
32
  props: Record<string, any>;
@@ -1,185 +1,139 @@
1
- <script lang="ts" module>
2
- import { useId } from "../hooks/use-id.js"
3
- import { useProvidedId } from "../utils/id.js"
4
- import type { ElementType, Props, PropsOf } from "../utils/types.js"
5
- import { ListboxStates, useActions, useData } from "./Listbox.svelte"
6
- import { attemptSubmit } from "../utils/form.js"
7
- import { Focus } from "../utils/calculate-active-index.js"
8
- import { useFocusRing } from "../hooks/use-focus-ring.svelte.js"
9
- import { useActivePress } from "../hooks/use-active-press.svelte.js"
10
- import { useResolveButtonType } from "../hooks/use-resolve-button-type.svelte.js"
11
- import { useFloatingReference, useFloatingReferenceProps } from "../internal/floating.svelte.js"
12
- import { stateFromSlot } from "../utils/state.js"
13
- import type { Snippet } from "svelte"
14
- import { useLabelledBy } from "../label/context.svelte.js"
15
- import { useDescribedBy } from "../description/context.svelte.js"
16
- import { useHover } from "../hooks/use-hover.svelte.js"
17
- import { mergeProps } from "../utils/render.js"
18
- import ElementOrComponent from "../utils/ElementOrComponent.svelte"
1
+ <script lang="ts" module>import { useId } from "../hooks/use-id.js";
2
+ import { useProvidedId } from "../utils/id.js";
3
+ import { ListboxStates, useActions, useData } from "./Listbox.svelte";
4
+ import { attemptSubmit } from "../utils/form.js";
5
+ import { Focus } from "../utils/calculate-active-index.js";
6
+ import { useFocusRing } from "../hooks/use-focus-ring.svelte.js";
7
+ import { useActivePress } from "../hooks/use-active-press.svelte.js";
8
+ import { useResolveButtonType } from "../hooks/use-resolve-button-type.svelte.js";
9
+ import { useFloatingReference, useFloatingReferenceProps } from "../internal/floating.svelte.js";
10
+ import { stateFromSlot } from "../utils/state.js";
11
+ import { useLabelledBy } from "../label/context.svelte.js";
12
+ import { useDescribedBy } from "../description/context.svelte.js";
13
+ import { useHover } from "../hooks/use-hover.svelte.js";
14
+ import { mergeProps } from "../utils/render.js";
15
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte";
16
+ const DEFAULT_BUTTON_TAG = "button";
17
+ </script>
19
18
 
20
- const DEFAULT_BUTTON_TAG = "button" as const
21
- type ButtonRenderPropArg = {
22
- disabled: boolean
23
- invalid: boolean
24
- hover: boolean
25
- focus: boolean
26
- autofocus: boolean
27
- open: boolean
28
- active: boolean
29
- value: any
19
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_BUTTON_TAG">const data = useData("ListboxButton");
20
+ const actions = useActions("ListboxButton");
21
+ const internalId = useId();
22
+ const providedId = useProvidedId();
23
+ let {
24
+ ref = $bindable(),
25
+ id = providedId || `headlessui-listbox-button-${internalId}`,
26
+ disabled: ownDisabled = false,
27
+ autofocus = false,
28
+ ...theirProps
29
+ } = $props();
30
+ const { setReference } = useFloatingReference();
31
+ const { getReferenceProps: getFloatingReferenceProps } = useFloatingReferenceProps();
32
+ $effect(() => {
33
+ data.buttonElement = ref || null;
34
+ setReference(ref);
35
+ });
36
+ const disabled = $derived(data.disabled || ownDisabled);
37
+ const handleKeyDown = (event) => {
38
+ switch (event.key) {
39
+ case "Enter":
40
+ if (event.currentTarget) attemptSubmit(event.currentTarget);
41
+ break;
42
+ case " ":
43
+ case "ArrowDown":
44
+ event.preventDefault();
45
+ actions.openListbox();
46
+ if (!data.value) actions.goToOption(Focus.First);
47
+ break;
48
+ case "ArrowUp":
49
+ event.preventDefault();
50
+ actions.openListbox();
51
+ if (!data.value) actions.goToOption(Focus.Last);
52
+ break;
30
53
  }
31
- type ButtonPropsWeControl = "aria-controls" | "aria-expanded" | "aria-haspopup" | "aria-labelledby" | "disabled"
32
-
33
- export type ListboxButtonProps<TTag extends ElementType = typeof DEFAULT_BUTTON_TAG> = Props<
34
- TTag,
35
- ButtonRenderPropArg,
36
- ButtonPropsWeControl,
37
- {
38
- autofocus?: boolean
39
- disabled?: boolean
54
+ };
55
+ const handleKeyUp = (event) => {
56
+ switch (event.key) {
57
+ case " ":
58
+ event.preventDefault();
59
+ break;
60
+ }
61
+ };
62
+ const handleClick = (event) => {
63
+ if (data.listboxState === ListboxStates.Open) {
64
+ actions.closeListbox();
65
+ data.buttonElement?.focus({ preventScroll: true });
66
+ } else {
67
+ event.preventDefault();
68
+ actions.openListbox();
69
+ }
70
+ };
71
+ const handleKeyPress = (event) => event.preventDefault();
72
+ const labelledBy = useLabelledBy();
73
+ const describedBy = useDescribedBy();
74
+ const { isHovered: hover, hoverProps } = $derived(
75
+ useHover({
76
+ get disabled() {
77
+ return disabled;
40
78
  }
41
- >
42
- </script>
43
-
44
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_BUTTON_TAG">
45
- const data = useData("ListboxButton")
46
- const actions = useActions("ListboxButton")
47
-
48
- const internalId = useId()
49
- const providedId = useProvidedId()
50
- let {
51
- ref = $bindable(),
52
- id = (providedId || `headlessui-listbox-button-${internalId}`) as PropsOf<TTag>["id"],
53
- disabled: ownDisabled = false,
54
- autofocus = false,
55
- ...theirProps
56
- }: { as?: TTag } & ListboxButtonProps<TTag> = $props()
57
- const { setReference } = useFloatingReference()
58
- const { getReferenceProps: getFloatingReferenceProps } = useFloatingReferenceProps()
59
- $effect(() => {
60
- data.buttonElement = ref || null
61
- setReference(ref)
62
79
  })
63
-
64
- const disabled = $derived(data.disabled || ownDisabled)
65
-
66
- const handleKeyDown = (event: KeyboardEvent) => {
67
- switch (event.key) {
68
- // Ref: https://www.w3.org/WAI/ARIA/apg/patterns/menubutton/#keyboard-interaction-13
69
-
70
- case "Enter":
71
- if (event.currentTarget) attemptSubmit(event.currentTarget as HTMLElement)
72
- break
73
-
74
- case " ":
75
- case "ArrowDown":
76
- event.preventDefault()
77
- actions.openListbox()
78
- if (!data.value) actions.goToOption(Focus.First)
79
- break
80
-
81
- case "ArrowUp":
82
- event.preventDefault()
83
- actions.openListbox()
84
- if (!data.value) actions.goToOption(Focus.Last)
85
- break
86
- }
87
- }
88
-
89
- const handleKeyUp = (event: KeyboardEvent) => {
90
- switch (event.key) {
91
- case " ":
92
- // Required for firefox, event.preventDefault() in handleKeyDown for
93
- // the Space key doesn't cancel the handleKeyUp, which in turn
94
- // triggers a *click*.
95
- event.preventDefault()
96
- break
80
+ );
81
+ const { pressed: active, pressProps } = $derived(
82
+ useActivePress({
83
+ get disabled() {
84
+ return disabled;
97
85
  }
98
- }
99
-
100
- const handleClick = (event: MouseEvent) => {
101
- //if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()
102
- if (data.listboxState === ListboxStates.Open) {
103
- actions.closeListbox()
104
- data.buttonElement?.focus({ preventScroll: true })
105
- } else {
106
- event.preventDefault()
107
- actions.openListbox()
86
+ })
87
+ );
88
+ const { isFocusVisible: focus, focusProps } = $derived(
89
+ useFocusRing({
90
+ get autofocus() {
91
+ return autofocus;
108
92
  }
93
+ })
94
+ );
95
+ const slot = $derived({
96
+ open: data.listboxState === ListboxStates.Open,
97
+ active: active || data.listboxState === ListboxStates.Open,
98
+ disabled,
99
+ invalid: data.invalid,
100
+ value: data.value,
101
+ hover,
102
+ focus,
103
+ autofocus: autofocus ?? false
104
+ });
105
+ const buttonType = useResolveButtonType({
106
+ get props() {
107
+ return { type: theirProps.type, as: theirProps.as };
108
+ },
109
+ get ref() {
110
+ return { current: data.buttonElement };
109
111
  }
110
-
111
- // This is needed so that we can "cancel" the click event when we use the `Enter` key on a button.
112
- const handleKeyPress = (event: KeyboardEvent) => event.preventDefault()
113
-
114
- const labelledBy = useLabelledBy()
115
- const describedBy = useDescribedBy()
116
-
117
- const { isHovered: hover, hoverProps } = $derived(
118
- useHover({
119
- get disabled() {
120
- return disabled
121
- },
122
- })
123
- )
124
- const { pressed: active, pressProps } = $derived(
125
- useActivePress({
126
- get disabled() {
127
- return disabled
128
- },
129
- })
130
- )
131
- const { isFocusVisible: focus, focusProps } = $derived(
132
- useFocusRing({
133
- get autofocus() {
134
- return autofocus
135
- },
136
- })
137
- )
138
-
139
- const slot = $derived({
140
- open: data.listboxState === ListboxStates.Open,
141
- active: active || data.listboxState === ListboxStates.Open,
142
- disabled,
143
- invalid: data.invalid,
144
- value: data.value,
145
- hover,
146
- focus,
147
- autofocus: autofocus ?? false,
148
- } satisfies ButtonRenderPropArg)
149
-
150
- const buttonType = useResolveButtonType({
151
- get props() {
152
- return { type: theirProps.type, as: theirProps.as }
153
- },
154
- get ref() {
155
- return { current: data.buttonElement }
112
+ });
113
+ const ourProps = $derived(
114
+ mergeProps(
115
+ {
116
+ ...getFloatingReferenceProps(),
117
+ id,
118
+ type: buttonType.type,
119
+ "aria-haspopup": "listbox",
120
+ "aria-controls": data.optionsElement?.id,
121
+ "aria-expanded": data.listboxState === ListboxStates.Open,
122
+ "aria-labelledby": labelledBy.value,
123
+ "aria-describedby": describedBy.value,
124
+ disabled: disabled || void 0,
125
+ autofocus,
126
+ onkeydown: handleKeyDown,
127
+ onkeyup: handleKeyUp,
128
+ onkeypress: handleKeyPress,
129
+ onclick: handleClick
156
130
  },
157
- })
158
-
159
- const ourProps = $derived(
160
- mergeProps(
161
- {
162
- ...getFloatingReferenceProps(),
163
- id,
164
- type: buttonType.type,
165
- "aria-haspopup": "listbox",
166
- "aria-controls": data.optionsElement?.id,
167
- "aria-expanded": data.listboxState === ListboxStates.Open,
168
- "aria-labelledby": labelledBy.value,
169
- "aria-describedby": describedBy.value,
170
- disabled: disabled || undefined,
171
- autofocus,
172
- onkeydown: handleKeyDown,
173
- onkeyup: handleKeyUp,
174
- onkeypress: handleKeyPress,
175
- onclick: handleClick,
176
- },
177
- focusProps,
178
- hoverProps,
179
- pressProps,
180
- stateFromSlot(slot)
181
- )
131
+ focusProps,
132
+ hoverProps,
133
+ pressProps,
134
+ stateFromSlot(slot)
182
135
  )
136
+ );
183
137
  </script>
184
138
 
185
139
  <ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_BUTTON_TAG} name="ListboxButton" bind:ref />
@@ -1,179 +1,138 @@
1
- <script lang="ts" module>
2
- import type { ElementType, Props } from "../utils/types.js"
3
-
4
- const DEFAULT_OPTION_TAG = "div" as const
5
- type OptionRenderPropArg = {
6
- /** @deprecated use `focus` instead */
7
- active: boolean
8
- focus: boolean
9
- selected: boolean
10
- disabled: boolean
11
-
12
- selectedOption: boolean
13
- }
14
- type OptionPropsWeControl = "aria-disabled" | "aria-selected" | "role" | "tabIndex"
15
-
16
- export type ListboxOptionProps<TTag extends ElementType = typeof DEFAULT_OPTION_TAG, TType = string> = Props<
17
- TTag,
18
- OptionRenderPropArg,
19
- OptionPropsWeControl,
20
- {
21
- id?: string
22
- disabled?: boolean
23
- value: TType
24
- }
25
- >
1
+ <script lang="ts" module>const DEFAULT_OPTION_TAG = "div";
26
2
  </script>
27
3
 
28
- <script lang="ts" generics="TType, TTag extends ElementType = typeof DEFAULT_OPTION_TAG">
29
- import { useId } from "../hooks/use-id.js"
30
- import {
31
- ActivationTrigger,
32
- ListboxStates,
33
- useActions,
34
- useData,
35
- ValueMode,
36
- type ListboxOptionDataRef,
37
- } from "./Listbox.svelte"
38
- import { disposables } from "../utils/disposables.js"
39
- import { Focus } from "../utils/calculate-active-index.js"
40
- import { getContext, onMount, type Snippet } from "svelte"
41
- import { useTextValue } from "../hooks/use-text-value.svelte.js"
42
- import { useTrackedPointer } from "../hooks/use-tracked-pointer.js"
43
- import { stateFromSlot } from "../utils/state.js"
44
- import ElementOrComponent from "../utils/ElementOrComponent.svelte"
45
-
46
- const internalId = useId()
47
- let {
48
- ref = $bindable(),
49
- id = `headlessui-listbox-option-${internalId}`,
50
- disabled = false,
51
- value,
52
- ...theirProps
53
- }: { as?: TTag } & ListboxOptionProps<TTag, TType> = $props()
54
- const usedInSelectedOption = getContext<boolean>("SelectedOptionContext") === true
55
- const data = useData("ListboxOption")
56
- const actions = useActions("ListboxOption")
57
-
58
- const { activeOptionIndex, options } = $derived(data)
59
-
60
- const active = $derived(activeOptionIndex !== null ? options[activeOptionIndex].id === id : false)
61
-
62
- const selected = $derived(data.isSelected(value))
63
- const getTextValue = useTextValue({
64
- get element() {
65
- return ref as HTMLElement
66
- },
67
- })
68
- const bag: ListboxOptionDataRef<TType>["current"] = $derived({
69
- disabled,
70
- value,
71
- domRef: { current: ref || null },
72
- get textValue() {
73
- return getTextValue()
74
- },
75
- })
76
-
77
- $effect(() => {
78
- if (usedInSelectedOption) return
79
- if (!ref) {
80
- data.listElements.delete(id)
81
- } else {
82
- data.listElements.set(id, ref)
83
- }
84
-
85
- return () => {
86
- if (ref) data.listElements.delete(id)
87
- }
88
- })
89
-
90
- $effect(() => {
91
- if (data.__demoMode) return
92
- if (data.listboxState !== ListboxStates.Open) return
93
- if (!active) return
94
- if (data.activationTrigger === ActivationTrigger.Pointer) return
95
- return disposables().requestAnimationFrame(() => {
96
- ;(ref as HTMLElement)?.scrollIntoView?.({ block: "nearest" })
97
- })
98
- })
99
-
100
- onMount(() => {
101
- if (usedInSelectedOption) return
102
- return actions.registerOption(id, {
103
- get current() {
104
- return bag
105
- },
106
- })
107
- })
108
-
109
- const handleClick = (event: { preventDefault: Function }) => {
110
- if (disabled) return event.preventDefault()
111
- actions.onChange(value)
112
- if (data.closeOnSelect === true || (data.closeOnSelect === undefined && data.mode === ValueMode.Single)) {
113
- actions.closeListbox()
114
- data.buttonElement?.focus({ preventScroll: true })
115
- }
116
- }
117
-
118
- const handleFocus = () => {
119
- if (disabled) return actions.goToOption(Focus.Nothing)
120
- actions.goToOption(Focus.Specific, id)
4
+ <script lang="ts" generics="TType, TTag extends ElementType = typeof DEFAULT_OPTION_TAG">import { useId } from "../hooks/use-id.js";
5
+ import {
6
+ ActivationTrigger,
7
+ ListboxStates,
8
+ useActions,
9
+ useData,
10
+ ValueMode
11
+ } from "./Listbox.svelte";
12
+ import { disposables } from "../utils/disposables.js";
13
+ import { Focus } from "../utils/calculate-active-index.js";
14
+ import { getContext, onMount } from "svelte";
15
+ import { useTextValue } from "../hooks/use-text-value.svelte.js";
16
+ import { useTrackedPointer } from "../hooks/use-tracked-pointer.js";
17
+ import { stateFromSlot } from "../utils/state.js";
18
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte";
19
+ const internalId = useId();
20
+ let {
21
+ ref = $bindable(),
22
+ id = `headlessui-listbox-option-${internalId}`,
23
+ disabled = false,
24
+ value,
25
+ ...theirProps
26
+ } = $props();
27
+ const usedInSelectedOption = getContext("SelectedOptionContext") === true;
28
+ const data = useData("ListboxOption");
29
+ const actions = useActions("ListboxOption");
30
+ const { activeOptionIndex, options } = $derived(data);
31
+ const active = $derived(activeOptionIndex !== null ? options[activeOptionIndex].id === id : false);
32
+ const selected = $derived(data.isSelected(value));
33
+ const getTextValue = useTextValue({
34
+ get element() {
35
+ return ref;
121
36
  }
122
-
123
- const pointer = useTrackedPointer()
124
-
125
- const handleEnter = (evt: PointerEvent) => {
126
- pointer.update(evt)
127
- if (disabled) return
128
- if (active) return
129
- actions.goToOption(Focus.Specific, id, ActivationTrigger.Pointer)
37
+ });
38
+ const bag = $derived({
39
+ disabled,
40
+ value,
41
+ domRef: { current: ref || null },
42
+ get textValue() {
43
+ return getTextValue();
130
44
  }
131
-
132
- const handleMove = (evt: PointerEvent) => {
133
- if (!pointer.wasMoved(evt)) return
134
- if (disabled) return
135
- if (active) return
136
- actions.goToOption(Focus.Specific, id, ActivationTrigger.Pointer)
45
+ });
46
+ $effect(() => {
47
+ if (usedInSelectedOption) return;
48
+ if (!ref) {
49
+ data.listElements.delete(id);
50
+ } else {
51
+ data.listElements.set(id, ref);
137
52
  }
138
-
139
- const handleLeave = (evt: PointerEvent) => {
140
- if (!pointer.wasMoved(evt)) return
141
- if (disabled) return
142
- if (!active) return
143
- actions.goToOption(Focus.Nothing)
53
+ return () => {
54
+ if (ref) data.listElements.delete(id);
55
+ };
56
+ });
57
+ $effect(() => {
58
+ if (data.__demoMode) return;
59
+ if (data.listboxState !== ListboxStates.Open) return;
60
+ if (!active) return;
61
+ if (data.activationTrigger === ActivationTrigger.Pointer) return;
62
+ return disposables().requestAnimationFrame(() => {
63
+ ;
64
+ ref?.scrollIntoView?.({ block: "nearest" });
65
+ });
66
+ });
67
+ onMount(() => {
68
+ if (usedInSelectedOption) return;
69
+ return actions.registerOption(id, {
70
+ get current() {
71
+ return bag;
72
+ }
73
+ });
74
+ });
75
+ const handleClick = (event) => {
76
+ if (disabled) return event.preventDefault();
77
+ actions.onChange(value);
78
+ if (data.closeOnSelect === true || data.closeOnSelect === void 0 && data.mode === ValueMode.Single) {
79
+ actions.closeListbox();
80
+ data.buttonElement?.focus({ preventScroll: true });
144
81
  }
145
-
146
- const slot = $derived({
147
- active,
148
- focus: active,
149
- selected,
150
- disabled,
151
- selectedOption: selected && usedInSelectedOption,
152
- } satisfies OptionRenderPropArg)
153
- const ourProps = $derived(
154
- !usedInSelectedOption
155
- ? {
156
- id,
157
- role: "option",
158
- tabIndex: disabled === true ? undefined : -1,
159
- "aria-disabled": disabled === true ? true : undefined,
160
- // According to the WAI-ARIA best practices, we should use aria-checked for
161
- // multi-select,but Voice-Over disagrees. So we use aria-checked instead for
162
- // both single and multi-select.
163
- "aria-selected": selected,
164
- disabled: undefined, // Never forward the `disabled` prop
165
- onclick: handleClick,
166
- onfocus: handleFocus,
167
- onpointerenter: handleEnter,
168
- onmouseenter: handleEnter,
169
- onpointermove: handleMove,
170
- onmousemove: handleMove,
171
- onpointerleave: handleLeave,
172
- onmouseleave: handleLeave,
173
- ...stateFromSlot(slot),
174
- }
175
- : {}
176
- )
82
+ };
83
+ const handleFocus = () => {
84
+ if (disabled) return actions.goToOption(Focus.Nothing);
85
+ actions.goToOption(Focus.Specific, id);
86
+ };
87
+ const pointer = useTrackedPointer();
88
+ const handleEnter = (evt) => {
89
+ pointer.update(evt);
90
+ if (disabled) return;
91
+ if (active) return;
92
+ actions.goToOption(Focus.Specific, id, ActivationTrigger.Pointer);
93
+ };
94
+ const handleMove = (evt) => {
95
+ if (!pointer.wasMoved(evt)) return;
96
+ if (disabled) return;
97
+ if (active) return;
98
+ actions.goToOption(Focus.Specific, id, ActivationTrigger.Pointer);
99
+ };
100
+ const handleLeave = (evt) => {
101
+ if (!pointer.wasMoved(evt)) return;
102
+ if (disabled) return;
103
+ if (!active) return;
104
+ actions.goToOption(Focus.Nothing);
105
+ };
106
+ const slot = $derived({
107
+ active,
108
+ focus: active,
109
+ selected,
110
+ disabled,
111
+ selectedOption: selected && usedInSelectedOption
112
+ });
113
+ const ourProps = $derived(
114
+ !usedInSelectedOption ? {
115
+ id,
116
+ role: "option",
117
+ tabIndex: disabled === true ? void 0 : -1,
118
+ "aria-disabled": disabled === true ? true : void 0,
119
+ // According to the WAI-ARIA best practices, we should use aria-checked for
120
+ // multi-select,but Voice-Over disagrees. So we use aria-checked instead for
121
+ // both single and multi-select.
122
+ "aria-selected": selected,
123
+ disabled: void 0,
124
+ // Never forward the `disabled` prop
125
+ onclick: handleClick,
126
+ onfocus: handleFocus,
127
+ onpointerenter: handleEnter,
128
+ onmouseenter: handleEnter,
129
+ onpointermove: handleMove,
130
+ onmousemove: handleMove,
131
+ onpointerleave: handleLeave,
132
+ onmouseleave: handleLeave,
133
+ ...stateFromSlot(slot)
134
+ } : {}
135
+ );
177
136
  </script>
178
137
 
179
138
  {#if selected || !usedInSelectedOption}