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