@pzerelles/headlessui-svelte 2.0.0-next.1

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 (64) hide show
  1. package/README.md +58 -0
  2. package/dist/actions/activePress.svelte.d.ts +8 -0
  3. package/dist/actions/activePress.svelte.js +84 -0
  4. package/dist/actions/focusRing.svelte.d.ts +9 -0
  5. package/dist/actions/focusRing.svelte.js +34 -0
  6. package/dist/checkbox/Checkbox.svelte +114 -0
  7. package/dist/checkbox/Checkbox.svelte.d.ts +48 -0
  8. package/dist/checkbox/index.d.ts +1 -0
  9. package/dist/checkbox/index.js +1 -0
  10. package/dist/description/Description.svelte +53 -0
  11. package/dist/description/Description.svelte.d.ts +39 -0
  12. package/dist/description/index.d.ts +1 -0
  13. package/dist/description/index.js +1 -0
  14. package/dist/field/Field.svelte +33 -0
  15. package/dist/field/Field.svelte.d.ts +33 -0
  16. package/dist/field/index.d.ts +1 -0
  17. package/dist/field/index.js +1 -0
  18. package/dist/fieldset/Fieldset.svelte +32 -0
  19. package/dist/fieldset/Fieldset.svelte.d.ts +33 -0
  20. package/dist/fieldset/index.d.ts +1 -0
  21. package/dist/fieldset/index.js +1 -0
  22. package/dist/index.d.ts +6 -0
  23. package/dist/index.js +6 -0
  24. package/dist/internal/FormFields.svelte +44 -0
  25. package/dist/internal/FormFields.svelte.d.ts +22 -0
  26. package/dist/internal/FormResolver.svelte +25 -0
  27. package/dist/internal/FormResolver.svelte.d.ts +19 -0
  28. package/dist/internal/Hidden.svelte +36 -0
  29. package/dist/internal/Hidden.svelte.d.ts +26 -0
  30. package/dist/internal/HoistFormFields.svelte +11 -0
  31. package/dist/internal/HoistFormFields.svelte.d.ts +18 -0
  32. package/dist/internal/Portal.svelte +17 -0
  33. package/dist/internal/Portal.svelte.d.ts +19 -0
  34. package/dist/label/Label.svelte +99 -0
  35. package/dist/label/Label.svelte.d.ts +41 -0
  36. package/dist/label/index.d.ts +1 -0
  37. package/dist/label/index.js +1 -0
  38. package/dist/legend/Legend.svelte +7 -0
  39. package/dist/legend/Legend.svelte.d.ts +18 -0
  40. package/dist/legend/index.d.ts +1 -0
  41. package/dist/legend/index.js +1 -0
  42. package/dist/utils/disabled.d.ts +3 -0
  43. package/dist/utils/disabled.js +2 -0
  44. package/dist/utils/disposables.d.ts +24 -0
  45. package/dist/utils/disposables.js +78 -0
  46. package/dist/utils/dom.d.ts +3 -0
  47. package/dist/utils/dom.js +10 -0
  48. package/dist/utils/focusVisible.svelte.d.ts +50 -0
  49. package/dist/utils/focusVisible.svelte.js +278 -0
  50. package/dist/utils/form.d.ts +4 -0
  51. package/dist/utils/form.js +57 -0
  52. package/dist/utils/id.d.ts +4 -0
  53. package/dist/utils/id.js +6 -0
  54. package/dist/utils/isVirtualEvent.d.ts +2 -0
  55. package/dist/utils/isVirtualEvent.js +48 -0
  56. package/dist/utils/microTask.d.ts +1 -0
  57. package/dist/utils/microTask.js +13 -0
  58. package/dist/utils/object.d.ts +1 -0
  59. package/dist/utils/object.js +8 -0
  60. package/dist/utils/platform.d.ts +4 -0
  61. package/dist/utils/platform.js +29 -0
  62. package/dist/utils/state.d.ts +1 -0
  63. package/dist/utils/state.js +20 -0
  64. package/package.json +69 -0
@@ -0,0 +1,44 @@
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)
18
+ return;
19
+ if (!form)
20
+ return;
21
+ return d.addEventListener(form, "reset", onReset);
22
+ });
23
+ </script>
24
+
25
+ <HoistFormFields>
26
+ <FormResolver setForm={(value) => (form = value)} {formId} />
27
+ {#each objectToFormEntries(data) as [name, value]}
28
+ <Hidden
29
+ features={HiddenFeatures.Hidden}
30
+ {...compact({
31
+ key: name,
32
+ as: "input",
33
+ type: "hidden",
34
+ hidden: true,
35
+ readOnly: true,
36
+ form: formId,
37
+ disabled,
38
+ name,
39
+ value,
40
+ ...overrides,
41
+ })}
42
+ />
43
+ {/each}
44
+ </HoistFormFields>
@@ -0,0 +1,22 @@
1
+ /// <reference types="svelte" />
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: Props & {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports;
10
+ z_$$bindings?: Bindings;
11
+ }
12
+ declare const FormFields: $$__sveltets_2_IsomorphicComponent<{
13
+ data: Record<string, any>;
14
+ overrides?: Record<string, any> | undefined;
15
+ form?: string | undefined;
16
+ disabled?: boolean | undefined;
17
+ onReset?: ((e: Event) => void) | undefined;
18
+ }, {
19
+ [evt: string]: CustomEvent<any>;
20
+ }, {}, Record<string, any>, "">;
21
+ type FormFields = InstanceType<typeof FormFields>;
22
+ export default FormFields;
@@ -0,0 +1,25 @@
1
+ <script lang="ts">import Hidden, { HiddenFeatures } from "./Hidden.svelte";
2
+ let { setForm, formId } = $props();
3
+ $effect(() => {
4
+ if (formId) {
5
+ let resolvedForm = document.getElementById(formId);
6
+ if (resolvedForm)
7
+ setForm(resolvedForm);
8
+ }
9
+ });
10
+ </script>
11
+
12
+ {#if !formId}
13
+ <Hidden
14
+ features={HiddenFeatures.Hidden}
15
+ as="input"
16
+ type="hidden"
17
+ hidden
18
+ readonly
19
+ ref={(el) => {
20
+ if (!el) return
21
+ let resolvedForm = el.closest("form")
22
+ if (resolvedForm) setForm(resolvedForm)
23
+ }}
24
+ />
25
+ {/if}
@@ -0,0 +1,19 @@
1
+ /// <reference types="svelte" />
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: Props & {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports;
10
+ z_$$bindings?: Bindings;
11
+ }
12
+ declare const FormResolver: $$__sveltets_2_IsomorphicComponent<{
13
+ setForm: (form: HTMLFormElement) => void;
14
+ formId?: string | undefined;
15
+ }, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, Record<string, any>, "">;
18
+ type FormResolver = InstanceType<typeof FormResolver>;
19
+ export default FormResolver;
@@ -0,0 +1,36 @@
1
+ <script lang="ts" context="module">export var HiddenFeatures = /* @__PURE__ */ ((HiddenFeatures2) => {
2
+ HiddenFeatures2[HiddenFeatures2["None"] = 1] = "None";
3
+ HiddenFeatures2[HiddenFeatures2["Focusable"] = 2] = "Focusable";
4
+ HiddenFeatures2[HiddenFeatures2["Hidden"] = 4] = "Hidden";
5
+ return HiddenFeatures2;
6
+ })(HiddenFeatures || {});
7
+ </script>
8
+
9
+ <script lang="ts">import { onMount } from "svelte";
10
+ const DEFAULT_VISUALLY_HIDDEN_TAG = "div";
11
+ let { as = "div", features = HiddenFeatures.None, ref: applyRef, ...theirProps } = $props();
12
+ let ref = $state();
13
+ onMount(() => {
14
+ applyRef?.(ref);
15
+ });
16
+ let ourProps = {
17
+ "aria-hidden": (features & HiddenFeatures.Focusable) === HiddenFeatures.Focusable ? true : theirProps["aria-hidden"] ?? void 0,
18
+ hidden: (features & HiddenFeatures.Hidden) === HiddenFeatures.Hidden ? true : void 0,
19
+ style: [
20
+ "position: fixed",
21
+ "top: 1px",
22
+ "left: 1px",
23
+ "width: 1px",
24
+ "height: 0",
25
+ "padding: 0",
26
+ "margin: -1px",
27
+ "overflow: hidden",
28
+ "clip: rect(0, 0, 0, 0)",
29
+ "whiteSpace: nowrap",
30
+ "borderWidth: 0",
31
+ ...(features & HiddenFeatures.Hidden) === HiddenFeatures.Hidden && !((features & HiddenFeatures.Focusable) === HiddenFeatures.Focusable) ? ["display: none"] : []
32
+ ].join("; ")
33
+ };
34
+ </script>
35
+
36
+ <svelte:element this={as} {...theirProps} {...ourProps} bind:this={ref} />
@@ -0,0 +1,26 @@
1
+ /// <reference types="svelte" />
2
+ export declare enum HiddenFeatures {
3
+ None = 1,
4
+ Focusable = 2,
5
+ Hidden = 4
6
+ }
7
+ import type { HTMLInputAttributes } from "svelte/elements";
8
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
9
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
10
+ $$bindings?: Bindings;
11
+ } & Exports;
12
+ (internal: unknown, props: Props & {
13
+ $$events?: Events;
14
+ $$slots?: Slots;
15
+ }): Exports;
16
+ z_$$bindings?: Bindings;
17
+ }
18
+ declare const Hidden: $$__sveltets_2_IsomorphicComponent<Omit<HTMLInputAttributes, "style"> & {
19
+ as?: string | undefined;
20
+ features?: HiddenFeatures | undefined;
21
+ ref?: ((el: HTMLElement) => void) | undefined;
22
+ }, {
23
+ [evt: string]: CustomEvent<any>;
24
+ }, {}, Record<string, any>, "">;
25
+ type Hidden = InstanceType<typeof Hidden>;
26
+ export default Hidden;
@@ -0,0 +1,11 @@
1
+ <script lang="ts">import { getContext } from "svelte";
2
+ import Portal from "./Portal.svelte";
3
+ let { children } = $props();
4
+ const formFieldsContext = getContext("FormFieldsContext");
5
+ </script>
6
+
7
+ {#if !formFieldsContext}
8
+ {@render children()}
9
+ {:else if formFieldsContext.target}
10
+ <Portal target={formFieldsContext.target}>{@render children()}</Portal>
11
+ {/if}
@@ -0,0 +1,18 @@
1
+ import { type Snippet } from "svelte";
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: Props & {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports;
10
+ z_$$bindings?: Bindings;
11
+ }
12
+ declare const HoistFormFields: $$__sveltets_2_IsomorphicComponent<{
13
+ children: Snippet;
14
+ }, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, Record<string, any>, "">;
17
+ type HoistFormFields = InstanceType<typeof HoistFormFields>;
18
+ export default HoistFormFields;
@@ -0,0 +1,17 @@
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
+ });
15
+ </script>
16
+
17
+ <div bind:this={ref}>{@render children()}</div>
@@ -0,0 +1,19 @@
1
+ import { type Snippet } from "svelte";
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: Props & {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports;
10
+ z_$$bindings?: Bindings;
11
+ }
12
+ declare const Portal: $$__sveltets_2_IsomorphicComponent<{
13
+ target: HTMLElement;
14
+ children: Snippet;
15
+ }, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, Record<string, any>, "">;
18
+ type Portal = InstanceType<typeof Portal>;
19
+ export default Portal;
@@ -0,0 +1,99 @@
1
+ <script lang="ts" context="module">import { setContext, untrack } from "svelte";
2
+ const DEFAULT_LABEL_TAG = "label";
3
+ export const createLabelContext = () => {
4
+ let labelledBy = $state();
5
+ const context = {
6
+ get labelledBy() {
7
+ return labelledBy;
8
+ },
9
+ register(id) {
10
+ labelledBy = untrack(() => labelledBy === void 0 ? id : `${labelledBy} ${id}`.trim());
11
+ },
12
+ unregister(id) {
13
+ labelledBy = untrack(
14
+ () => labelledBy?.split(" ").filter((value) => value !== id).join(" ")
15
+ );
16
+ }
17
+ };
18
+ return setContext("Label", context);
19
+ };
20
+ export const getLabelContext = () => getContext("Label");
21
+ const validateLabelContext = () => {
22
+ const context = getLabelContext();
23
+ if (context === void 0) {
24
+ const err = new Error("You used a <Label /> component, but it is not inside a relevant parent.");
25
+ if (Error.captureStackTrace)
26
+ Error.captureStackTrace(err, validateLabelContext);
27
+ throw err;
28
+ }
29
+ return context;
30
+ };
31
+ </script>
32
+
33
+ <script lang="ts" generics="TTag extends keyof SvelteHTMLElements">import { getContext } from "svelte";
34
+ import { getIdContext, htmlid } from "../utils/id.js";
35
+ import { getDisabledContext } from "../utils/disabled.js";
36
+ import { stateFromSlot } from "../utils/state.js";
37
+ const internalId = htmlid();
38
+ const context = validateLabelContext();
39
+ const providedHtmlFor = getIdContext();
40
+ const providedDisabled = getDisabledContext();
41
+ let {
42
+ as,
43
+ id = `headlessui-label-${internalId}`,
44
+ htmlFor = providedHtmlFor,
45
+ passive = false,
46
+ children,
47
+ ...theirOriginalProps
48
+ } = $props();
49
+ $effect(() => {
50
+ context.register(id);
51
+ const registeredId = id;
52
+ return () => {
53
+ context.unregister(registeredId);
54
+ };
55
+ });
56
+ let handleClick = (e) => {
57
+ let current = e.currentTarget;
58
+ if (current instanceof HTMLLabelElement) {
59
+ e.preventDefault();
60
+ }
61
+ if (current instanceof HTMLLabelElement) {
62
+ let target = document.getElementById(current.getAttribute("htmlFor") ?? "");
63
+ if (target) {
64
+ let actuallyDisabled = target.getAttribute("disabled");
65
+ if (actuallyDisabled === "true" || actuallyDisabled === "") {
66
+ return;
67
+ }
68
+ let ariaDisabled = target.getAttribute("aria-disabled");
69
+ if (ariaDisabled === "true" || ariaDisabled === "") {
70
+ return;
71
+ }
72
+ if (target instanceof HTMLInputElement && (target.type === "radio" || target.type === "checkbox") || target.role === "radio" || target.role === "checkbox" || target.role === "switch") {
73
+ target.click();
74
+ }
75
+ target.focus({ preventScroll: true });
76
+ }
77
+ }
78
+ };
79
+ const disabled = $derived(providedDisabled?.disabled ?? false);
80
+ const slot = $derived({ disabled });
81
+ const ourProps = $derived({
82
+ id,
83
+ htmlFor: passive ? void 0 : htmlFor,
84
+ onclick: passive ? void 0 : handleClick,
85
+ ...stateFromSlot(slot)
86
+ });
87
+ const theirProps = $derived.by(() => {
88
+ if (passive) {
89
+ const { onclick: _, ...props } = theirOriginalProps;
90
+ return props;
91
+ } else {
92
+ return theirOriginalProps;
93
+ }
94
+ });
95
+ </script>
96
+
97
+ <svelte:element this={as ?? (htmlFor ? DEFAULT_LABEL_TAG : "div")} {...ourProps} {...theirProps}>
98
+ {#if children}{@render children(slot)}{/if}
99
+ </svelte:element>
@@ -0,0 +1,41 @@
1
+ import type { SvelteHTMLElements } from "svelte/elements";
2
+ export type LabelProps<TTag extends keyof SvelteHTMLElements = typeof DEFAULT_LABEL_TAG> = SvelteHTMLElements[TTag] & {
3
+ as?: TTag;
4
+ passive?: boolean;
5
+ htmlFor?: string;
6
+ children?: Snippet<[
7
+ {
8
+ disabled: boolean;
9
+ }
10
+ ]>;
11
+ };
12
+ declare const DEFAULT_LABEL_TAG: "label";
13
+ export type LabelContext = {
14
+ labelledBy?: string;
15
+ register: (id: string) => void;
16
+ unregister: (id: string) => void;
17
+ };
18
+ export declare const createLabelContext: () => LabelContext;
19
+ export declare const getLabelContext: () => LabelContext | undefined;
20
+ import { type Snippet } from "svelte";
21
+ declare class __sveltets_Render<TTag extends keyof SvelteHTMLElements> {
22
+ props(): LabelProps<TTag>;
23
+ events(): {} & {
24
+ [evt: string]: CustomEvent<any>;
25
+ };
26
+ slots(): {};
27
+ bindings(): "";
28
+ exports(): {};
29
+ }
30
+ interface $$IsomorphicComponent {
31
+ new <TTag extends keyof SvelteHTMLElements>(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']>> & {
32
+ $$bindings?: ReturnType<__sveltets_Render<TTag>['bindings']>;
33
+ } & ReturnType<__sveltets_Render<TTag>['exports']>;
34
+ <TTag extends keyof SvelteHTMLElements>(internal: unknown, props: ReturnType<__sveltets_Render<TTag>['props']> & {
35
+ $$events?: ReturnType<__sveltets_Render<TTag>['events']>;
36
+ }): ReturnType<__sveltets_Render<TTag>['exports']>;
37
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
38
+ }
39
+ declare const Label: $$IsomorphicComponent;
40
+ type Label<TTag extends keyof SvelteHTMLElements> = InstanceType<typeof Label<TTag>>;
41
+ export default Label;
@@ -0,0 +1 @@
1
+ export { default as Label, type LabelProps } from "./Label.svelte";
@@ -0,0 +1 @@
1
+ export { default as Label } from "./Label.svelte";
@@ -0,0 +1,7 @@
1
+ <script lang="ts" context="module"></script>
2
+
3
+ <script lang="ts">import Label from "../label/Label.svelte";
4
+ let { ...props } = $props();
5
+ </script>
6
+
7
+ <Label as="div" {...props} />
@@ -0,0 +1,18 @@
1
+ /// <reference types="svelte" />
2
+ export type LegendProps = SvelteHTMLElements["div"];
3
+ import type { SvelteHTMLElements } from "svelte/elements";
4
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
5
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
6
+ $$bindings?: Bindings;
7
+ } & Exports;
8
+ (internal: unknown, props: Props & {
9
+ $$events?: Events;
10
+ $$slots?: Slots;
11
+ }): Exports;
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const Legend: $$__sveltets_2_IsomorphicComponent<import("svelte/elements").HTMLAttributes<HTMLDivElement>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, Record<string, any>, "">;
17
+ type Legend = InstanceType<typeof Legend>;
18
+ export default Legend;
@@ -0,0 +1 @@
1
+ export { default as Legend, type LegendProps } from "./Legend.svelte";
@@ -0,0 +1 @@
1
+ export { default as Legend } from "./Legend.svelte";
@@ -0,0 +1,3 @@
1
+ export declare const getDisabledContext: () => {
2
+ readonly disabled: boolean;
3
+ } | undefined;
@@ -0,0 +1,2 @@
1
+ import { getContext } from "svelte";
2
+ export const getDisabledContext = () => getContext("Disabled");
@@ -0,0 +1,24 @@
1
+ export type Disposables = ReturnType<typeof disposables>;
2
+ /**
3
+ * Disposables are a way to manage event handlers and functions like
4
+ * `setTimeout` and `requestAnimationFrame` that need to be cleaned up when they
5
+ * are no longer needed.
6
+ *
7
+ *
8
+ * When you register a disposable function, it is added to a collection of
9
+ * disposables. Each disposable in the collection provides a `dispose` clean up
10
+ * function that can be called when it's no longer needed. There is also a
11
+ * `dispose` function on the collection itself that can be used to clean up all
12
+ * pending disposables in that collection.
13
+ */
14
+ export declare function disposables(): {
15
+ addEventListener<TEventName extends keyof WindowEventMap>(element: HTMLElement | Window | Document, name: TEventName, listener: (event: WindowEventMap[TEventName]) => any, options?: boolean | AddEventListenerOptions): () => void;
16
+ requestAnimationFrame(callback: FrameRequestCallback): () => void;
17
+ nextFrame(callback: FrameRequestCallback): () => void;
18
+ setTimeout(callback: (args: void) => void, ms?: number | undefined): () => void;
19
+ microTask(cb: () => void): () => void;
20
+ style(node: HTMLElement, property: string, value: string): () => void;
21
+ group(cb: (d: typeof this) => void): () => void;
22
+ add(cb: () => void): () => void;
23
+ dispose(): void;
24
+ };
@@ -0,0 +1,78 @@
1
+ import { microTask } from "./microTask.js";
2
+ /**
3
+ * Disposables are a way to manage event handlers and functions like
4
+ * `setTimeout` and `requestAnimationFrame` that need to be cleaned up when they
5
+ * are no longer needed.
6
+ *
7
+ *
8
+ * When you register a disposable function, it is added to a collection of
9
+ * disposables. Each disposable in the collection provides a `dispose` clean up
10
+ * function that can be called when it's no longer needed. There is also a
11
+ * `dispose` function on the collection itself that can be used to clean up all
12
+ * pending disposables in that collection.
13
+ */
14
+ export function disposables() {
15
+ let _disposables = [];
16
+ let api = {
17
+ addEventListener(element, name, listener, options) {
18
+ element.addEventListener(name, listener, options);
19
+ return api.add(() => element.removeEventListener(name, listener, options));
20
+ },
21
+ requestAnimationFrame(...args) {
22
+ let raf = requestAnimationFrame(...args);
23
+ return api.add(() => cancelAnimationFrame(raf));
24
+ },
25
+ nextFrame(...args) {
26
+ return api.requestAnimationFrame(() => {
27
+ return api.requestAnimationFrame(...args);
28
+ });
29
+ },
30
+ setTimeout(...args) {
31
+ let timer = setTimeout(...args);
32
+ return api.add(() => clearTimeout(timer));
33
+ },
34
+ microTask(...args) {
35
+ let task = { current: true };
36
+ microTask(() => {
37
+ if (task.current) {
38
+ args[0]();
39
+ }
40
+ });
41
+ return api.add(() => {
42
+ task.current = false;
43
+ });
44
+ },
45
+ style(node, property, value) {
46
+ let previous = node.style.getPropertyValue(property);
47
+ Object.assign(node.style, { [property]: value });
48
+ return this.add(() => {
49
+ Object.assign(node.style, { [property]: previous });
50
+ });
51
+ },
52
+ group(cb) {
53
+ let d = disposables();
54
+ cb(d);
55
+ return this.add(() => d.dispose());
56
+ },
57
+ add(cb) {
58
+ // Ensure we don't add the same callback twice
59
+ if (!_disposables.includes(cb)) {
60
+ _disposables.push(cb);
61
+ }
62
+ return () => {
63
+ let idx = _disposables.indexOf(cb);
64
+ if (idx >= 0) {
65
+ for (let dispose of _disposables.splice(idx, 1)) {
66
+ dispose();
67
+ }
68
+ }
69
+ };
70
+ },
71
+ dispose() {
72
+ for (let dispose of _disposables.splice(0)) {
73
+ dispose();
74
+ }
75
+ },
76
+ };
77
+ return api;
78
+ }
@@ -0,0 +1,3 @@
1
+ /// <reference types="node" />
2
+ export declare const getOwnerDocument: (el: Element | null | undefined) => Document;
3
+ export declare const getOwnerWindow: (el: (Window & typeof global) | Element | null | undefined) => Window & typeof global;
@@ -0,0 +1,10 @@
1
+ export const getOwnerDocument = (el) => {
2
+ return el?.ownerDocument ?? document;
3
+ };
4
+ export const getOwnerWindow = (el) => {
5
+ if (el && "window" in el && el.window === el) {
6
+ return el;
7
+ }
8
+ const doc = getOwnerDocument(el);
9
+ return doc.defaultView || window;
10
+ };
@@ -0,0 +1,50 @@
1
+ export type Modality = "keyboard" | "pointer" | "virtual";
2
+ export type FocusVisibleHandler = (isFocusVisible: boolean) => void;
3
+ export interface FocusVisibleProps {
4
+ /** Whether the element is a text input. */
5
+ isTextInput?: boolean;
6
+ /** Whether the element will be auto focused. */
7
+ autoFocus?: boolean;
8
+ }
9
+ export interface FocusVisibleResult {
10
+ /** Whether keyboard focus is visible globally. */
11
+ isFocusVisible: boolean;
12
+ }
13
+ interface GlobalListenerData {
14
+ focus: () => void;
15
+ }
16
+ export declare let hasSetupGlobalListeners: Map<Window, GlobalListenerData>;
17
+ /**
18
+ * EXPERIMENTAL
19
+ * Adds a window (i.e. iframe) to the list of windows that are being tracked for focus visible.
20
+ *
21
+ * Sometimes apps render portions of their tree into an iframe. In this case, we cannot accurately track if the focus
22
+ * is visible because we cannot see interactions inside the iframe. If you have this in your application's architecture,
23
+ * then this function will attach event listeners inside the iframe. You should call `addWindowFocusTracking` with an
24
+ * element from inside the window you wish to add. We'll retrieve the relevant elements based on that.
25
+ * Note, you do not need to call this for the default window, as we call it for you.
26
+ *
27
+ * When you are ready to stop listening, but you do not wish to unmount the iframe, you may call the cleanup function
28
+ * returned by `addWindowFocusTracking`. Otherwise, when you unmount the iframe, all listeners and state will be cleaned
29
+ * up automatically for you.
30
+ *
31
+ * @param element @default document.body - The element provided will be used to get the window to add.
32
+ * @returns A function to remove the event listeners and cleanup the state.
33
+ */
34
+ export declare function addWindowFocusTracking(element?: HTMLElement | null): () => void;
35
+ /**
36
+ * If true, keyboard focus is visible.
37
+ */
38
+ export declare function isFocusVisible(): boolean;
39
+ export declare function getInteractionModality(): Modality | null;
40
+ export declare function setInteractionModality(modality: Modality): void;
41
+ /**
42
+ * Manages focus visible state for the page, and subscribes individual components for updates.
43
+ */
44
+ /**
45
+ * Listens for trigger change and reports if focus is visible (i.e., modality is not pointer).
46
+ */
47
+ export declare function useFocusVisibleListener(fn: FocusVisibleHandler, opts?: {
48
+ isTextInput?: boolean;
49
+ }): void;
50
+ export {};