diff --git a/packages/floating-ui-svelte/src/hooks/use-click.svelte.ts b/packages/floating-ui-svelte/src/hooks/use-click.svelte.ts index 0c0758e..4a5de2d 100644 --- a/packages/floating-ui-svelte/src/hooks/use-click.svelte.ts +++ b/packages/floating-ui-svelte/src/hooks/use-click.svelte.ts @@ -51,7 +51,7 @@ interface UseClickOptions { * reference element for the first time. * @default true */ - stickIfOpen?: boolean; + stickIfOpen?: MaybeGetter; } function isButtonTarget(event: KeyboardEvent) { diff --git a/packages/floating-ui-svelte/src/hooks/use-floating-root-context.svelte.ts b/packages/floating-ui-svelte/src/hooks/use-floating-root-context.svelte.ts index e664d2f..c283298 100644 --- a/packages/floating-ui-svelte/src/hooks/use-floating-root-context.svelte.ts +++ b/packages/floating-ui-svelte/src/hooks/use-floating-root-context.svelte.ts @@ -2,6 +2,7 @@ import type { ReferenceElement } from "@floating-ui/dom"; import type { ContextData, MaybeGetter, + OnOpenChange, OpenChangeReason, ReferenceType, } from "../types.js"; @@ -21,11 +22,7 @@ import { noop } from "../internal/noop.js"; interface UseFloatingRootContextOptions { open?: MaybeGetter; - onOpenChange?: ( - open: boolean, - event?: Event, - reason?: OpenChangeReason, - ) => void; + onOpenChange?: OnOpenChange; reference: MaybeGetter; floating: MaybeGetter; onReferenceChange?: (node: Element | null) => void; @@ -34,11 +31,7 @@ interface UseFloatingRootContextOptions { class FloatingRootContextOptions { open: ReadableBox; - onOpenChange: ( - open: boolean, - event?: Event, - reason?: OpenChangeReason, - ) => void; + onOpenChange: OnOpenChange; onReferenceChange: (node: Element | null) => void; onFloatingChange: (node: HTMLElement | null) => void; #stableReference = $state(null); @@ -113,6 +106,7 @@ class FloatingRootContext { } this.#positionReference = this.options.reference.current; this.onOpenChange = this.onOpenChange.bind(this); + this.setPositionReference = this.setPositionReference.bind(this); } onOpenChange(open: boolean, event?: Event, reason?: OpenChangeReason) { diff --git a/packages/floating-ui-svelte/src/hooks/use-floating.svelte.ts b/packages/floating-ui-svelte/src/hooks/use-floating.svelte.ts index f407233..b25882b 100644 --- a/packages/floating-ui-svelte/src/hooks/use-floating.svelte.ts +++ b/packages/floating-ui-svelte/src/hooks/use-floating.svelte.ts @@ -5,8 +5,10 @@ import type { FloatingTreeType, MaybeGetter, NarrowedElement, + OnOpenChange, OpenChangeReason, ReferenceType, + WhileElementsMounted, } from "../types.js"; import { type FloatingRootContext, @@ -60,11 +62,7 @@ interface UseFloatingOptions { * Callback to handle mounting/unmounting of the elements. * @default undefined */ - whileElementsMounted?: ( - reference: ReferenceType, - floating: HTMLElement, - update: () => void, - ) => () => void; + whileElementsMounted?: WhileElementsMounted; rootContext?: MaybeGetter>; /** @@ -97,22 +95,19 @@ interface UseFloatingOptions { } /** - * Reactive options for the `useFloating` hook. + * An instance of `FloatingOptions` is created for each call to `useFloating`, + * and is used to store the reactive state of the various options passed to + * `useFloating`. */ -// This enables us to not have to pass around a bunch of getters and setters internally. +// This enables us to not have to pass around a bunch of getters and setters internally +// and can instead rely on the reactive state of the `FloatingOptions` instance. class FloatingOptions { open: ReadableBox; placement: ReadableBox; strategy: ReadableBox; middleware: ReadableBox>; transform: ReadableBox; - whileElementsMounted: - | (( - reference: ReferenceType, - floating: HTMLElement, - update: () => void, - ) => () => void) - | undefined; + whileElementsMounted: WhileElementsMounted | undefined; rootContext: ReadableBox | undefined>; onReferenceChange: (node: Element | null) => void; onFloatingChange: (node: HTMLElement | null) => void; @@ -122,13 +117,18 @@ class FloatingOptions { reason?: OpenChangeReason, ) => void; nodeId: ReadableBox; - floatingProp = $derived.by(() => extract(this.options.floating, null)); - referenceProp = $derived.by(() => extract(this.options.reference, null)); + #stableReference = $state(null); #stableFloating = $state(null); reference: WritableBox; floating: WritableBox; constructor(private readonly options: UseFloatingOptions) { + const floatingProp = $derived.by(() => + extract(this.options.floating, null), + ); + const referenceProp = $derived.by(() => + extract(this.options.reference, null), + ); this.open = box.with(() => extract(options.open, true)); this.placement = box.with(() => extract(options.placement, "bottom")); this.strategy = box.with(() => extract(options.strategy, "absolute")); @@ -160,14 +160,14 @@ class FloatingOptions { this.floating.current = extract(this.options.floating, null); $effect.pre(() => { - if (this.floatingProp) { - this.floating.current = this.floatingProp; + if (floatingProp) { + this.floating.current = floatingProp; } }); $effect.pre(() => { - if (this.referenceProp) { - this.reference.current = this.referenceProp; + if (referenceProp) { + this.reference.current = referenceProp; } }); } @@ -191,11 +191,7 @@ interface FloatingContextData { isPositioned: boolean; update: () => Promise; floatingStyles: string; - onOpenChange: ( - open: boolean, - event?: Event, - reason?: OpenChangeReason, - ) => void; + onOpenChange: OnOpenChange; open: boolean; data: ContextData; floatingId: string; @@ -206,11 +202,7 @@ interface FloatingContextData { class FloatingContext implements FloatingContextData { - onOpenChange: ( - open: boolean, - event?: Event, - reason?: OpenChangeReason, - ) => void; + onOpenChange: OnOpenChange; update: () => Promise; constructor(private readonly opts: FloatingContextOptions) { @@ -296,8 +288,6 @@ class FloatingState { context: FloatingContext; constructor(private readonly options: FloatingOptions) { - console.log(options.reference.current); - const internalRootContext = useFloatingRootContext({ open: () => options.open.current ?? true, reference: () => options.reference.current, diff --git a/packages/floating-ui-svelte/src/hooks/use-position.svelte.ts b/packages/floating-ui-svelte/src/hooks/use-position.svelte.ts index 635b9bf..2382d1d 100644 --- a/packages/floating-ui-svelte/src/hooks/use-position.svelte.ts +++ b/packages/floating-ui-svelte/src/hooks/use-position.svelte.ts @@ -8,7 +8,7 @@ import { } from "@floating-ui/dom"; import { getDPR, roundByDPR } from "../internal/dpr.js"; import { styleObjectToString } from "../internal/style-object-to-string.js"; -import type { ReferenceType } from "../types.js"; +import type { ReferenceType, WhileElementsMounted } from "../types.js"; import type { FloatingOptions } from "./use-floating.svelte.js"; import type { FloatingRootContext } from "./use-floating-root-context.svelte.js"; @@ -66,11 +66,7 @@ interface UsePositionOptions { * Callback to handle mounting/unmounting of the elements. * @default undefined */ - whileElementsMounted?: ( - reference: RT, - floating: HTMLElement, - update: () => void, - ) => () => void; + whileElementsMounted?: WhileElementsMounted; } interface UsePositionData { diff --git a/packages/floating-ui-svelte/src/types.ts b/packages/floating-ui-svelte/src/types.ts index 832bfef..c9b66c4 100644 --- a/packages/floating-ui-svelte/src/types.ts +++ b/packages/floating-ui-svelte/src/types.ts @@ -25,26 +25,6 @@ interface FloatingEvents { off(event: string, handler: (data: any) => void): void; } -interface FloatingElements { - /** - * The reference element. - */ - reference?: ReferenceType | null; - - /** - * The floating element. - */ - floating?: FloatingElement | null; -} - -interface ExtendedElements extends Required { - /** - * Some hooks require the reference element to be a DOM element, - * not a VirtualElement. - */ - domReference: NarrowedElement | null; -} - interface ContextData { /** * The latest even that caused the open state to change. @@ -89,15 +69,19 @@ interface FloatingTreeType { removeNode(node: FloatingNodeType): void; } +type WhileElementsMounted = ( + reference: RT, + floating: HTMLElement, + update: () => void, +) => () => void; + type Getter = () => T; type MaybeGetter = T | Getter; export type { OpenChangeReason, FloatingEvents, - FloatingElements, ContextData, - ExtendedElements, FloatingNodeType, FloatingTreeType, ReferenceType, @@ -105,4 +89,5 @@ export type { OnOpenChange, Getter, MaybeGetter, + WhileElementsMounted, };