@pzerelles/headlessui-svelte 2.1.2-next.6 → 2.1.2-next.8
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 +54 -84
- package/dist/checkbox/Checkbox.svelte +120 -174
- package/dist/close-button/CloseButton.svelte +6 -12
- package/dist/combobox/Combobox.svelte +3 -50
- package/dist/data-interactive/DataInteractive.svelte +29 -57
- package/dist/description/Description.svelte +21 -32
- package/dist/dialog/Dialog.svelte +34 -69
- package/dist/dialog/DialogBackdrop.svelte +12 -29
- package/dist/dialog/DialogPanel.svelte +26 -49
- package/dist/dialog/DialogTitle.svelte +23 -38
- package/dist/dialog/InternalDialog.svelte +202 -263
- package/dist/field/Field.svelte +26 -49
- package/dist/fieldset/Fieldset.svelte +29 -50
- package/dist/focus-trap/FocusTrap.svelte +283 -419
- package/dist/input/Input.svelte +53 -85
- package/dist/input/Input.svelte.d.ts +4 -6
- package/dist/internal/FocusSentinel.svelte +8 -16
- package/dist/internal/ForcePortalRoot.svelte +3 -7
- package/dist/internal/FormFields.svelte +20 -31
- package/dist/internal/FormResolver.svelte +15 -20
- package/dist/internal/Hidden.svelte +23 -44
- package/dist/internal/HoistFormFields.svelte +4 -7
- package/dist/internal/MainTreeProvider.svelte +36 -89
- package/dist/internal/Portal.svelte +14 -18
- package/dist/label/Label.svelte +57 -91
- package/dist/legend/Legend.svelte +3 -18
- package/dist/listbox/Listbox.svelte +396 -588
- package/dist/listbox/ListboxButton.svelte +127 -176
- package/dist/listbox/ListboxOption.svelte +125 -166
- package/dist/listbox/ListboxOptions.svelte +244 -340
- package/dist/listbox/ListboxSelectedOption.svelte +15 -38
- package/dist/menu/Menu.svelte +218 -307
- package/dist/menu/MenuButton.svelte +115 -157
- package/dist/menu/MenuHeading.svelte +14 -34
- package/dist/menu/MenuItem.svelte +107 -145
- package/dist/menu/MenuItems.svelte +224 -298
- package/dist/menu/MenuSection.svelte +9 -26
- package/dist/menu/MenuSeparator.svelte +4 -20
- package/dist/portal/InternalPortal.svelte +85 -141
- package/dist/portal/Portal.svelte +2 -5
- package/dist/portal/PortalGroup.svelte +9 -30
- package/dist/switch/Switch.svelte +132 -179
- package/dist/switch/SwitchGroup.svelte +31 -44
- package/dist/tabs/Tab.svelte +143 -195
- package/dist/tabs/TabGroup.svelte +205 -292
- package/dist/tabs/TabList.svelte +11 -31
- package/dist/tabs/TabPanel.svelte +43 -68
- package/dist/tabs/TabPanels.svelte +7 -18
- package/dist/textarea/Textarea.svelte +53 -83
- package/dist/textarea/Textarea.svelte.d.ts +14 -11
- package/dist/transition/InternalTransitionChild.svelte +170 -259
- package/dist/transition/Transition.svelte +66 -96
- package/dist/transition/TransitionChild.svelte +11 -31
- package/dist/utils/ElementOrComponent.svelte +23 -44
- package/dist/utils/Generic.svelte +17 -29
- package/dist/utils/StableCollection.svelte +36 -54
- package/package.json +1 -1
package/dist/input/Input.svelte
CHANGED
|
@@ -1,91 +1,59 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { ElementType, Props } from "../utils/types.js"
|
|
3
|
-
|
|
4
|
-
const DEFAULT_INPUT_TAG = "input" as const
|
|
5
|
-
|
|
6
|
-
type InputRenderPropArg = {
|
|
7
|
-
disabled: boolean
|
|
8
|
-
hover: boolean
|
|
9
|
-
focus: boolean
|
|
10
|
-
autofocus: boolean
|
|
11
|
-
invalid: boolean
|
|
12
|
-
}
|
|
13
|
-
type InputPropsWeControl = "aria-labelledby" | "aria-describedby"
|
|
14
|
-
|
|
15
|
-
export type InputProps<TTag extends ElementType = typeof DEFAULT_INPUT_TAG, TValue = string> = Props<
|
|
16
|
-
TTag,
|
|
17
|
-
InputRenderPropArg,
|
|
18
|
-
InputPropsWeControl,
|
|
19
|
-
{
|
|
20
|
-
id?: string
|
|
21
|
-
value?: TValue
|
|
22
|
-
disabled?: boolean
|
|
23
|
-
invalid?: boolean
|
|
24
|
-
autofocus?: boolean
|
|
25
|
-
}
|
|
26
|
-
>
|
|
1
|
+
<script lang="ts" module>const DEFAULT_INPUT_TAG = "input";
|
|
27
2
|
</script>
|
|
28
3
|
|
|
29
|
-
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_INPUT_TAG, TValue = string">
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"aria-invalid": invalid ? "" : undefined,
|
|
80
|
-
disabled: disabled || undefined,
|
|
81
|
-
autofocus,
|
|
82
|
-
},
|
|
83
|
-
focusProps,
|
|
84
|
-
hoverProps
|
|
85
|
-
)
|
|
4
|
+
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_INPUT_TAG, TValue = string">import { htmlid } from "../utils/id.js";
|
|
5
|
+
import { useDisabled } from "../hooks/use-disabled.js";
|
|
6
|
+
import { useProvidedId } from "../internal/id.js";
|
|
7
|
+
import { useLabelledBy } from "../label/context.svelte.js";
|
|
8
|
+
import { useDescribedBy } from "../description/context.svelte.js";
|
|
9
|
+
import { useHover } from "../hooks/use-hover.svelte.js";
|
|
10
|
+
import { useFocusRing } from "../hooks/use-focus-ring.svelte.js";
|
|
11
|
+
import { mergeProps } from "../utils/render.js";
|
|
12
|
+
import ElementOrComponent from "../utils/ElementOrComponent.svelte";
|
|
13
|
+
const internalId = htmlid();
|
|
14
|
+
const providedId = useProvidedId();
|
|
15
|
+
const providedDisabled = useDisabled();
|
|
16
|
+
let {
|
|
17
|
+
ref = $bindable(),
|
|
18
|
+
value = $bindable(),
|
|
19
|
+
id = providedId?.value || `headlessui-input-${internalId}`,
|
|
20
|
+
disabled: theirDisabled = false,
|
|
21
|
+
autofocus = false,
|
|
22
|
+
invalid = false,
|
|
23
|
+
...theirProps
|
|
24
|
+
} = $props();
|
|
25
|
+
const disabled = $derived(providedDisabled?.value ?? theirDisabled);
|
|
26
|
+
const labelledBy = useLabelledBy();
|
|
27
|
+
const describedBy = useDescribedBy();
|
|
28
|
+
const { isHovered: hover, hoverProps } = $derived(
|
|
29
|
+
useHover({
|
|
30
|
+
get disabled() {
|
|
31
|
+
return disabled;
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
const { isFocusVisible: focus, focusProps } = $derived(
|
|
36
|
+
useFocusRing({
|
|
37
|
+
get autofocus() {
|
|
38
|
+
return autofocus;
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
);
|
|
42
|
+
const ourProps = $derived(
|
|
43
|
+
mergeProps(
|
|
44
|
+
{
|
|
45
|
+
id,
|
|
46
|
+
"aria-labelledby": labelledBy?.value,
|
|
47
|
+
"aria-describedby": describedBy?.value,
|
|
48
|
+
"aria-invalid": invalid ? "" : void 0,
|
|
49
|
+
disabled: disabled || void 0,
|
|
50
|
+
autofocus
|
|
51
|
+
},
|
|
52
|
+
focusProps,
|
|
53
|
+
hoverProps
|
|
86
54
|
)
|
|
87
|
-
|
|
88
|
-
|
|
55
|
+
);
|
|
56
|
+
const slot = $derived({ disabled, invalid, hover, focus, autofocus });
|
|
89
57
|
</script>
|
|
90
58
|
|
|
91
59
|
<ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_INPUT_TAG} name="Input" bind:ref bind:value />
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ElementType, Props } from "../utils/types.js";
|
|
1
|
+
import type { ElementType, Props, PropsOf } from "../utils/types.js";
|
|
2
2
|
declare const DEFAULT_INPUT_TAG: "input";
|
|
3
3
|
type InputRenderPropArg = {
|
|
4
4
|
disabled: boolean;
|
|
@@ -9,7 +9,6 @@ type InputRenderPropArg = {
|
|
|
9
9
|
};
|
|
10
10
|
type InputPropsWeControl = "aria-labelledby" | "aria-describedby";
|
|
11
11
|
export type InputProps<TTag extends ElementType = typeof DEFAULT_INPUT_TAG, TValue = string> = Props<TTag, InputRenderPropArg, InputPropsWeControl, {
|
|
12
|
-
id?: string;
|
|
13
12
|
value?: TValue;
|
|
14
13
|
disabled?: boolean;
|
|
15
14
|
invalid?: boolean;
|
|
@@ -19,13 +18,12 @@ declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_INPUT_
|
|
|
19
18
|
props(): {
|
|
20
19
|
as?: TTag | undefined;
|
|
21
20
|
value?: TValue | undefined;
|
|
22
|
-
} & (Exclude<keyof
|
|
21
|
+
} & (Exclude<keyof PropsOf<TTag>, ("as" | "children" | "refName" | "class") | "invalid" | "disabled" | "autofocus" | "value" | InputPropsWeControl> extends infer T extends keyof PropsOf<TTag> ? { [P in T]: PropsOf<TTag>[P]; } : never) & {
|
|
23
22
|
children?: import("../utils/types.js").Children<InputRenderPropArg> | undefined;
|
|
24
23
|
ref?: HTMLElement;
|
|
25
|
-
} & (true extends (
|
|
26
|
-
class?:
|
|
24
|
+
} & (true extends (PropsOf<TTag> extends infer T_1 ? T_1 extends PropsOf<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) ? {
|
|
25
|
+
class?: PropsOf<TTag>["class"] | ((bag: InputRenderPropArg) => string) | undefined;
|
|
27
26
|
} : {}) & {
|
|
28
|
-
id?: string;
|
|
29
27
|
value?: TValue | undefined;
|
|
30
28
|
disabled?: boolean;
|
|
31
29
|
invalid?: boolean;
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
let { onfocus }: FocusSentinelProps = $props()
|
|
10
|
-
|
|
11
|
-
let enabled = $state(true)
|
|
12
|
-
let mounted = $state(false)
|
|
13
|
-
|
|
14
|
-
onMount(() => {
|
|
15
|
-
mounted = true
|
|
16
|
-
})
|
|
1
|
+
<script lang="ts">import { onMount } from "svelte";
|
|
2
|
+
import Hidden, { HiddenFeatures } from "./Hidden.svelte";
|
|
3
|
+
let { onfocus } = $props();
|
|
4
|
+
let enabled = $state(true);
|
|
5
|
+
let mounted = $state(false);
|
|
6
|
+
onMount(() => {
|
|
7
|
+
mounted = true;
|
|
8
|
+
});
|
|
17
9
|
</script>
|
|
18
10
|
|
|
19
11
|
{#if enabled}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
let { force, children }: { force: boolean; children: Snippet } = $props()
|
|
6
|
-
|
|
7
|
-
createPortalRoot({ force })
|
|
1
|
+
<script lang="ts">import { createPortalRoot } from "./portal-force-root.svelte.js";
|
|
2
|
+
let { force, children } = $props();
|
|
3
|
+
createPortalRoot({ force });
|
|
8
4
|
</script>
|
|
9
5
|
|
|
10
6
|
{#if children}{@render children()}{/if}
|
|
@@ -1,34 +1,23 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} = $props()
|
|
22
|
-
|
|
23
|
-
let form = $state<HTMLFormElement | null>(null)
|
|
24
|
-
const d = disposables()
|
|
25
|
-
|
|
26
|
-
$effect(() => {
|
|
27
|
-
if (!onReset) return
|
|
28
|
-
if (!form) return
|
|
29
|
-
|
|
30
|
-
return d.addEventListener(form, "reset", onReset)
|
|
31
|
-
})
|
|
1
|
+
<script lang="ts">import { disposables } from "../utils/disposables.js";
|
|
2
|
+
import { objectToFormEntries } from "../utils/form.js";
|
|
3
|
+
import FormResolver from "./FormResolver.svelte";
|
|
4
|
+
import HoistFormFields from "./HoistFormFields.svelte";
|
|
5
|
+
import Hidden, { HiddenFeatures } from "./Hidden.svelte";
|
|
6
|
+
import { compact } from "../utils/object.js";
|
|
7
|
+
let {
|
|
8
|
+
data,
|
|
9
|
+
form: formId,
|
|
10
|
+
disabled,
|
|
11
|
+
onReset,
|
|
12
|
+
overrides
|
|
13
|
+
} = $props();
|
|
14
|
+
let form = $state(null);
|
|
15
|
+
const d = disposables();
|
|
16
|
+
$effect(() => {
|
|
17
|
+
if (!onReset) return;
|
|
18
|
+
if (!form) return;
|
|
19
|
+
return d.addEventListener(form, "reset", onReset);
|
|
20
|
+
});
|
|
32
21
|
</script>
|
|
33
22
|
|
|
34
23
|
<HoistFormFields>
|
|
@@ -1,23 +1,18 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
onMount(() => {
|
|
17
|
-
if (!element) return
|
|
18
|
-
const resolvedForm = element.closest("form")
|
|
19
|
-
if (resolvedForm) setForm(resolvedForm)
|
|
20
|
-
})
|
|
1
|
+
<script lang="ts">import { onMount } from "svelte";
|
|
2
|
+
import Hidden, { HiddenFeatures } from "./Hidden.svelte";
|
|
3
|
+
let { setForm, formId } = $props();
|
|
4
|
+
$effect(() => {
|
|
5
|
+
if (formId) {
|
|
6
|
+
const resolvedForm = document.getElementById(formId);
|
|
7
|
+
if (resolvedForm) setForm(resolvedForm);
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
let element = $state();
|
|
11
|
+
onMount(() => {
|
|
12
|
+
if (!element) return;
|
|
13
|
+
const resolvedForm = element.closest("form");
|
|
14
|
+
if (resolvedForm) setForm(resolvedForm);
|
|
15
|
+
});
|
|
21
16
|
</script>
|
|
22
17
|
|
|
23
18
|
{#if !formId}
|
|
@@ -1,49 +1,28 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export * from "./HiddenFeatures.js"
|
|
7
|
-
|
|
8
|
-
const DEFAULT_VISUALLY_HIDDEN_TAG = "span" as const
|
|
9
|
-
|
|
10
|
-
type HiddenRenderPropArg = {}
|
|
11
|
-
type HiddenPropsWeControl = never
|
|
12
|
-
export type HiddenProps<TTag extends ElementType = typeof DEFAULT_VISUALLY_HIDDEN_TAG> = Props<
|
|
13
|
-
TTag,
|
|
14
|
-
HiddenRenderPropArg,
|
|
15
|
-
HiddenPropsWeControl,
|
|
16
|
-
{ features?: HiddenFeatures }
|
|
17
|
-
>
|
|
1
|
+
<script lang="ts" module>import ElementOrComponent from "../utils/ElementOrComponent.svelte";
|
|
2
|
+
import { HiddenFeatures } from "./HiddenFeatures.js";
|
|
3
|
+
export * from "./HiddenFeatures.js";
|
|
4
|
+
const DEFAULT_VISUALLY_HIDDEN_TAG = "span";
|
|
18
5
|
</script>
|
|
19
6
|
|
|
20
|
-
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_VISUALLY_HIDDEN_TAG">
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"whiteSpace: nowrap",
|
|
40
|
-
"borderWidth: 0",
|
|
41
|
-
...((features & HiddenFeatures.Hidden) === HiddenFeatures.Hidden &&
|
|
42
|
-
!((features & HiddenFeatures.Focusable) === HiddenFeatures.Focusable)
|
|
43
|
-
? ["display: none"]
|
|
44
|
-
: []),
|
|
45
|
-
].join("; "),
|
|
46
|
-
}
|
|
7
|
+
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_VISUALLY_HIDDEN_TAG">let { ref = $bindable(), features = HiddenFeatures.None, ...theirProps } = $props();
|
|
8
|
+
let ourProps = {
|
|
9
|
+
"aria-hidden": (features & HiddenFeatures.Focusable) === HiddenFeatures.Focusable ? true : theirProps["aria-hidden"] ?? void 0,
|
|
10
|
+
hidden: (features & HiddenFeatures.Hidden) === HiddenFeatures.Hidden ? true : void 0,
|
|
11
|
+
style: [
|
|
12
|
+
"position: fixed",
|
|
13
|
+
"top: 1px",
|
|
14
|
+
"left: 1px",
|
|
15
|
+
"width: 1px",
|
|
16
|
+
"height: 0",
|
|
17
|
+
"padding: 0",
|
|
18
|
+
"margin: -1px",
|
|
19
|
+
"overflow: hidden",
|
|
20
|
+
"clip: rect(0, 0, 0, 0)",
|
|
21
|
+
"whiteSpace: nowrap",
|
|
22
|
+
"borderWidth: 0",
|
|
23
|
+
...(features & HiddenFeatures.Hidden) === HiddenFeatures.Hidden && !((features & HiddenFeatures.Focusable) === HiddenFeatures.Focusable) ? ["display: none"] : []
|
|
24
|
+
].join("; ")
|
|
25
|
+
};
|
|
47
26
|
</script>
|
|
48
27
|
|
|
49
28
|
<ElementOrComponent {ourProps} {theirProps} defaultTag={DEFAULT_VISUALLY_HIDDEN_TAG} name="Hidden" bind:ref />
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
let { children }: { children: Snippet } = $props()
|
|
6
|
-
|
|
7
|
-
const formFieldsContext = getContext<{ target?: HTMLElement }>("FormFieldsContext")
|
|
1
|
+
<script lang="ts">import { getContext } from "svelte";
|
|
2
|
+
import Portal from "./Portal.svelte";
|
|
3
|
+
let { children } = $props();
|
|
4
|
+
const formFieldsContext = getContext("FormFieldsContext");
|
|
8
5
|
</script>
|
|
9
6
|
|
|
10
7
|
{#if !formFieldsContext}
|
|
@@ -1,95 +1,42 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Get the main tree node from context or fallback to the optionally provided node.
|
|
8
|
-
*/
|
|
9
|
-
export function useMainTreeNode(options: { fallbackMainTreeNode?: HTMLElement | null } = {}) {
|
|
10
|
-
const { fallbackMainTreeNode = null } = $derived(options)
|
|
11
|
-
|
|
12
|
-
// Prefer the main tree node from context, but fallback to the provided node.
|
|
13
|
-
return (
|
|
14
|
-
getContext<MainTreeContext>("MainTreeContext") ?? {
|
|
15
|
-
get node() {
|
|
16
|
-
return fallbackMainTreeNode
|
|
17
|
-
},
|
|
18
|
-
}
|
|
19
|
-
)
|
|
20
|
-
}
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
<script lang="ts">
|
|
24
|
-
import { setContext, type Snippet } from "svelte"
|
|
25
|
-
import Hidden, { HiddenFeatures } from "./Hidden.svelte"
|
|
26
|
-
import { getOwnerDocument } from "../utils/owner.js"
|
|
27
|
-
/**
|
|
28
|
-
* A provider for the main tree node.
|
|
29
|
-
*
|
|
30
|
-
* When a component is rendered in a `Portal`, it is no longer part of the main
|
|
31
|
-
* tree. This provider helps to find the main tree node and pass it along to the
|
|
32
|
-
* components that need it.
|
|
33
|
-
*
|
|
34
|
-
* The main tree node is used for features such as outside click behavior, where
|
|
35
|
-
* we allow clicks in 3rd party containers, but not in the parent of the "main
|
|
36
|
-
* tree".
|
|
37
|
-
*
|
|
38
|
-
* In case of a `Popover`, we can use the `PopoverButton` as a marker in the
|
|
39
|
-
* "main tree", the `PopoverPanel` can't be used because it could be rendered in
|
|
40
|
-
* a `Portal` (e.g. when using the `anchor` props).
|
|
41
|
-
*
|
|
42
|
-
* However, we can't use the `PopoverButton` when it's nested inside of another
|
|
43
|
-
* `Popover`'s `PopoverPanel` component if the parent `PopoverPanel` is
|
|
44
|
-
* rendered in a `Portal`.
|
|
45
|
-
*
|
|
46
|
-
* This is where the `MainTreeProvider` comes in. It will find the "main tree"
|
|
47
|
-
* node and pass it on. The top-level `PopoverButton` will be used as a marker
|
|
48
|
-
* in the "main tree" and nested `Popover` will use this button as well.
|
|
49
|
-
*/
|
|
50
|
-
let { node, children }: { children: Snippet; node?: HTMLElement | null } = $props()
|
|
51
|
-
|
|
52
|
-
let mainTreeNode = $state<HTMLElement | null>(null)
|
|
53
|
-
|
|
54
|
-
// 1. Prefer the main tree node from context
|
|
55
|
-
// 2. Prefer the provided node
|
|
56
|
-
// 3. Create a new node at this point, and find the main tree node
|
|
57
|
-
const resolvedMainTreeNode = useMainTreeNode({
|
|
58
|
-
get fallbackMainTreeNode() {
|
|
59
|
-
return node ?? mainTreeNode
|
|
60
|
-
},
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
setContext("MainTreeContext", {
|
|
1
|
+
<script lang="ts" module>import { getContext, onMount } from "svelte";
|
|
2
|
+
export function useMainTreeNode(options = {}) {
|
|
3
|
+
const { fallbackMainTreeNode = null } = $derived(options);
|
|
4
|
+
return getContext("MainTreeContext") ?? {
|
|
64
5
|
get node() {
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
* If no main tree node is found at this point, then we briefly render an
|
|
71
|
-
* element to find the main tree node and pass it along.
|
|
72
|
-
*/
|
|
73
|
-
let el = $state<HTMLElement>()
|
|
74
|
-
onMount(() => {
|
|
75
|
-
if (!el) return
|
|
6
|
+
return fallbackMainTreeNode;
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
</script>
|
|
76
11
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
12
|
+
<script lang="ts">import { setContext } from "svelte";
|
|
13
|
+
import Hidden, { HiddenFeatures } from "./Hidden.svelte";
|
|
14
|
+
import { getOwnerDocument } from "../utils/owner.js";
|
|
15
|
+
let { node, children } = $props();
|
|
16
|
+
let mainTreeNode = $state(null);
|
|
17
|
+
const resolvedMainTreeNode = useMainTreeNode({
|
|
18
|
+
get fallbackMainTreeNode() {
|
|
19
|
+
return node ?? mainTreeNode;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
setContext("MainTreeContext", {
|
|
23
|
+
get node() {
|
|
24
|
+
return resolvedMainTreeNode.node;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
let el = $state();
|
|
28
|
+
onMount(() => {
|
|
29
|
+
if (!el) return;
|
|
30
|
+
for (let container of getOwnerDocument(el)?.querySelectorAll("html > *, body > *") ?? []) {
|
|
31
|
+
if (container === document.body) continue;
|
|
32
|
+
if (container === document.head) continue;
|
|
33
|
+
if (!(container instanceof HTMLElement)) continue;
|
|
34
|
+
if (container?.contains(el)) {
|
|
35
|
+
mainTreeNode = container;
|
|
36
|
+
break;
|
|
91
37
|
}
|
|
92
|
-
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
93
40
|
</script>
|
|
94
41
|
|
|
95
42
|
{#if children}{@render children()}{/if}
|
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
_ref.parentNode?.removeChild(_ref)
|
|
16
|
-
}
|
|
17
|
-
})
|
|
18
|
-
})
|
|
1
|
+
<script lang="ts">import { onDestroy, onMount } from "svelte";
|
|
2
|
+
let { target, children } = $props();
|
|
3
|
+
let ref = $state();
|
|
4
|
+
onMount(() => {
|
|
5
|
+
target.appendChild(ref);
|
|
6
|
+
});
|
|
7
|
+
onDestroy(() => {
|
|
8
|
+
const _ref = ref;
|
|
9
|
+
setTimeout(() => {
|
|
10
|
+
if (_ref?.parentNode) {
|
|
11
|
+
_ref.parentNode?.removeChild(_ref);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
});
|
|
19
15
|
</script>
|
|
20
16
|
|
|
21
17
|
<div bind:this={ref}>{@render children()}</div>
|