From 2a506ba3c3f02806f23f14d2daf6be9702179e41 Mon Sep 17 00:00:00 2001 From: Hunter Johnston <64506580+huntabyte@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:15:26 -0400 Subject: [PATCH] next: update svelte and cleanup (#577) --- package.json | 2 +- packages/bits-ui/package.json | 2 +- .../src/lib/bits/dialog/dialog.svelte.ts | 3 +- .../src/lib/bits/label/label.svelte.ts | 2 +- .../bits-ui/src/lib/bits/menu/menu.svelte.ts | 2 +- .../navigation-menu/navigation-menu.svelte.ts | 2 +- .../src/lib/bits/popover/popover.svelte.ts | 2 +- .../src/lib/bits/progress/progress.svelte.ts | 2 +- .../select/components/select-arrow.svelte | 14 +- .../components/select-content-floating.svelte | 3 +- .../components/select-content-impl.svelte | 2 - .../select-content-item-aligned.svelte | 3 +- .../select/components/select-content.svelte | 8 +- .../components/select-group-label.svelte | 8 +- .../select/components/select-group.svelte | 21 +- .../bits/select/components/select-icon.svelte | 19 +- .../select/components/select-item-text.svelte | 8 +- .../bits/select/components/select-item.svelte | 8 +- .../select-scroll-down-button-mounted.svelte | 3 +- .../select-scroll-down-button.svelte | 8 +- .../select-scroll-up-button-mounted.svelte | 3 +- .../components/select-scroll-up-button.svelte | 8 +- .../select/components/select-separator.svelte | 21 +- .../select/components/select-trigger.svelte | 8 +- .../select/components/select-viewport.svelte | 8 +- .../src/lib/bits/select/select.svelte.ts | 314 ++++++++++++------ .../bits/tabs/components/tabs-content.svelte | 11 +- .../lib/bits/tabs/components/tabs-list.svelte | 21 +- .../bits/tabs/components/tabs-trigger.svelte | 8 +- .../src/lib/bits/tabs/components/tabs.svelte | 8 +- .../bits-ui/src/lib/bits/tabs/tabs.svelte.ts | 110 +++--- .../components/toggle-group-item.svelte | 6 +- .../components/toggle-group.svelte | 8 +- .../bits/toggle-group/toggle-group.svelte.ts | 78 +++-- .../toolbar/components/toolbar-button.svelte | 8 +- .../components/toolbar-group-item.svelte | 8 +- .../toolbar/components/toolbar-group.svelte | 8 +- .../toolbar/components/toolbar-link.svelte | 8 +- .../bits/toolbar/components/toolbar.svelte | 8 +- .../src/lib/bits/toolbar/toolbar.svelte.ts | 171 ++++++---- .../tooltip/components/tooltip-arrow.svelte | 2 +- .../tooltip/components/tooltip-content.svelte | 6 +- .../tooltip/components/tooltip-trigger.svelte | 8 +- .../src/lib/bits/tooltip/tooltip.svelte.ts | 64 ++-- .../src/lib/bits/utilities/arrow/arrow.svelte | 3 +- .../components/floating-layer-arrow.svelte | 8 +- .../floating-layer/useFloatingLayer.svelte.ts | 77 +++-- .../focus-scope/useFocusScope.svelte.ts | 15 +- .../useTextSelectionLayer.svelte.ts | 16 +- .../src/lib/internal/useFormControl.svelte.ts | 4 +- .../src/lib/internal/useGraceArea.svelte.ts | 22 +- ...odeById.svelte.ts => useRefById.svelte.ts} | 37 +-- pnpm-lock.yaml | 190 +++++------ sites/docs/package.json | 2 +- 54 files changed, 878 insertions(+), 521 deletions(-) rename packages/bits-ui/src/lib/internal/{useNodeById.svelte.ts => useRefById.svelte.ts} (53%) diff --git a/package.json b/package.json index c112d8947..e3e68255c 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.2", "prettier-plugin-tailwindcss": "0.5.13", - "svelte": "5.0.0-next.143", + "svelte": "^5.0.0-next.157", "svelte-eslint-parser": "^0.34.1", "wrangler": "^3.44.0" }, diff --git a/packages/bits-ui/package.json b/packages/bits-ui/package.json index d3c96cb5d..f0782f689 100644 --- a/packages/bits-ui/package.json +++ b/packages/bits-ui/package.json @@ -45,7 +45,7 @@ "jsdom": "^24.0.0", "publint": "^0.2.7", "resize-observer-polyfill": "^1.5.1", - "svelte": "5.0.0-next.143", + "svelte": "5.0.0-next.157", "svelte-check": "^3.6.9", "tslib": "^2.6.2", "typescript": "^5.3.3", diff --git a/packages/bits-ui/src/lib/bits/dialog/dialog.svelte.ts b/packages/bits-ui/src/lib/bits/dialog/dialog.svelte.ts index 93a42d113..a90d7e2ea 100644 --- a/packages/bits-ui/src/lib/bits/dialog/dialog.svelte.ts +++ b/packages/bits-ui/src/lib/bits/dialog/dialog.svelte.ts @@ -1,7 +1,6 @@ -import { box } from "svelte-toolbelt"; import { getAriaExpanded, getDataOpenClosed } from "$lib/internal/attrs.js"; import type { ReadableBoxedValues, WritableBoxedValues } from "$lib/internal/box.svelte.js"; -import { useRefById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; import { createContext } from "$lib/internal/createContext.js"; import type { WithRefProps } from "$lib/internal/types.js"; diff --git a/packages/bits-ui/src/lib/bits/label/label.svelte.ts b/packages/bits-ui/src/lib/bits/label/label.svelte.ts index 27cf5e8e7..a5f1b75ea 100644 --- a/packages/bits-ui/src/lib/bits/label/label.svelte.ts +++ b/packages/bits-ui/src/lib/bits/label/label.svelte.ts @@ -1,5 +1,5 @@ import type { WithRefProps } from "$lib/internal/types.js"; -import { useRefById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; const ROOT_ATTR = "data-label-root"; diff --git a/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts b/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts index 7a59d1ff8..5a009a99b 100644 --- a/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts +++ b/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts @@ -36,7 +36,7 @@ import { mergeProps } from "$lib/internal/mergeProps.js"; import { createContext } from "$lib/internal/createContext.js"; import type { Direction } from "$lib/shared/index.js"; import { afterTick } from "$lib/internal/afterTick.js"; -import { useRefById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; import { isPointerInGraceArea, makeHullFromElements } from "$lib/internal/polygon.js"; const TRIGGER_ATTR = "data-menu-trigger"; diff --git a/packages/bits-ui/src/lib/bits/navigation-menu/navigation-menu.svelte.ts b/packages/bits-ui/src/lib/bits/navigation-menu/navigation-menu.svelte.ts index c200e72dd..1915cd7b6 100644 --- a/packages/bits-ui/src/lib/bits/navigation-menu/navigation-menu.svelte.ts +++ b/packages/bits-ui/src/lib/bits/navigation-menu/navigation-menu.svelte.ts @@ -20,7 +20,7 @@ import { useId } from "$lib/internal/useId.svelte.js"; import { kbd } from "$lib/internal/kbd.js"; import { useArrowNavigation } from "$lib/internal/useArrowNavigation.js"; import { boxAutoReset } from "$lib/internal/boxAutoReset.svelte.js"; -import { useRefById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; import type { ElementRef } from "$lib/internal/types.js"; import { afterTick } from "$lib/internal/afterTick.js"; import { getTabbableCandidates } from "../utilities/focus-scope/utils.js"; diff --git a/packages/bits-ui/src/lib/bits/popover/popover.svelte.ts b/packages/bits-ui/src/lib/bits/popover/popover.svelte.ts index 0bef4599c..5b587117f 100644 --- a/packages/bits-ui/src/lib/bits/popover/popover.svelte.ts +++ b/packages/bits-ui/src/lib/bits/popover/popover.svelte.ts @@ -1,6 +1,6 @@ import { box } from "svelte-toolbelt"; import type { ReadableBoxedValues, WritableBoxedValues } from "$lib/internal/box.svelte.js"; -import { useRefById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; import { kbd } from "$lib/internal/kbd.js"; import { getAriaExpanded, getDataOpenClosed } from "$lib/internal/attrs.js"; import { createContext } from "$lib/internal/createContext.js"; diff --git a/packages/bits-ui/src/lib/bits/progress/progress.svelte.ts b/packages/bits-ui/src/lib/bits/progress/progress.svelte.ts index d0fcba11b..278a730fb 100644 --- a/packages/bits-ui/src/lib/bits/progress/progress.svelte.ts +++ b/packages/bits-ui/src/lib/bits/progress/progress.svelte.ts @@ -1,6 +1,6 @@ import type { ReadableBoxedValues } from "$lib/internal/box.svelte.js"; import type { WithRefProps } from "$lib/internal/types.js"; -import { useRefById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; const ROOT_ATTR = "data-progress-root"; diff --git a/packages/bits-ui/src/lib/bits/select/components/select-arrow.svelte b/packages/bits-ui/src/lib/bits/select/components/select-arrow.svelte index bf4f24ab6..0f3b154a0 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-arrow.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-arrow.svelte @@ -3,12 +3,20 @@ import { useSelectArrow } from "../select.svelte.js"; import { FloatingLayer } from "$lib/bits/utilities/floating-layer/index.js"; import { mergeProps } from "$lib/internal/mergeProps.js"; + import { useId } from "$lib/internal/useId.svelte.js"; + import { box } from "svelte-toolbelt"; - let { ref = $bindable(), ...restProps }: ArrowProps = $props(); + let { id = useId(), ref = $bindable(null), ...restProps }: ArrowProps = $props(); - const arrowState = useSelectArrow(); + const arrowState = useSelectArrow({ + id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), + }); const mergedProps = $derived(mergeProps(restProps, arrowState.props as any)); - + diff --git a/packages/bits-ui/src/lib/bits/select/components/select-content-floating.svelte b/packages/bits-ui/src/lib/bits/select/components/select-content-floating.svelte index 067f9c5dd..ddbdb69a7 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-content-floating.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-content-floating.svelte @@ -13,7 +13,6 @@ child, align = "start", collisionPadding = CONTENT_MARGIN, - ref = $bindable(), enabled = false, ...restProps }: WithoutChildren & @@ -32,7 +31,7 @@ {#if asChild} {@render child?.({ props: finalProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-content-impl.svelte b/packages/bits-ui/src/lib/bits/select/components/select-content-impl.svelte index 362fe85df..059faf015 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-content-impl.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-content-impl.svelte @@ -74,14 +74,12 @@ (contentState.isPositioned.value = true)} /> {:else} (contentState.isPositioned.value = true)} /> {/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-content-item-aligned.svelte b/packages/bits-ui/src/lib/bits/select/components/select-content-item-aligned.svelte index cf0d43d7a..4dc524946 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-content-item-aligned.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-content-item-aligned.svelte @@ -9,7 +9,6 @@ child, children, asChild, - ref = $bindable(), preventScroll = true, onPlaced, ...restProps @@ -32,7 +31,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-content.svelte b/packages/bits-ui/src/lib/bits/select/components/select-content.svelte index 9d4bfe261..aef3452f0 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-content.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-content.svelte @@ -10,17 +10,21 @@ let { id = useId(), - ref = $bindable(), + ref = $bindable(null), forceMount = false, position = "floating", ...restProps }: ContentProps = $props(); - const contentState = useSelectContentFrag({ id: box.with(() => id) }); + const contentState = useSelectContentFrag(); const contentContext = useSelectContent({ id: box.with(() => id), position: box.with(() => position), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const isPresent = $derived(contentState.root.open.value || forceMount); diff --git a/packages/bits-ui/src/lib/bits/select/components/select-group-label.svelte b/packages/bits-ui/src/lib/bits/select/components/select-group-label.svelte index 22b0c7b33..f6cdb88c3 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-group-label.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-group-label.svelte @@ -9,13 +9,17 @@ asChild, children, child, - ref = $bindable(), + ref = $bindable(null), id = useId(), ...restProps }: GroupLabelProps = $props(); const groupLabelState = useSelectGroupLabel({ id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, groupLabelState.props)); @@ -24,7 +28,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-group.svelte b/packages/bits-ui/src/lib/bits/select/components/select-group.svelte index 225aaa0ba..faafe2bb1 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-group.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-group.svelte @@ -2,17 +2,32 @@ import type { GroupProps } from "../index.js"; import { useSelectGroup } from "../select.svelte.js"; import { mergeProps } from "$lib/internal/mergeProps.js"; + import { useId } from "$lib/internal/useId.svelte.js"; + import { box } from "svelte-toolbelt"; - let { asChild, children, child, ref = $bindable(), ...restProps }: GroupProps = $props(); + let { + asChild, + children, + child, + id = useId(), + ref = $bindable(null), + ...restProps + }: GroupProps = $props(); - const groupState = useSelectGroup(); + const groupState = useSelectGroup({ + id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), + }); const mergedProps = $derived(mergeProps(restProps, groupState.props)); {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-icon.svelte b/packages/bits-ui/src/lib/bits/select/components/select-icon.svelte index 5d3d183bd..f4af0cfcc 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-icon.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-icon.svelte @@ -2,10 +2,25 @@ import type { IconProps } from "../index.js"; import { useSelectIcon } from "../select.svelte.js"; import { mergeProps } from "$lib/internal/mergeProps.js"; + import { useId } from "$lib/internal/useId.svelte.js"; + import { box } from "svelte-toolbelt"; - let { asChild, children, child, ref = $bindable(), ...restProps }: IconProps = $props(); + let { + asChild, + children, + child, + id = useId(), + ref = $bindable(null), + ...restProps + }: IconProps = $props(); - const iconState = useSelectIcon(); + const iconState = useSelectIcon({ + id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), + }); const mergedProps = $derived(mergeProps(restProps, iconState.props)); diff --git a/packages/bits-ui/src/lib/bits/select/components/select-item-text.svelte b/packages/bits-ui/src/lib/bits/select/components/select-item-text.svelte index d201bd566..8519927ff 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-item-text.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-item-text.svelte @@ -8,7 +8,7 @@ let { id = useId(), - ref = $bindable(), + ref = $bindable(null), asChild, children, child, @@ -17,6 +17,10 @@ const itemTextState = useSelectItemText({ id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, itemTextState.props)); @@ -31,7 +35,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} - + {@render children?.()} {/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-item.svelte b/packages/bits-ui/src/lib/bits/select/components/select-item.svelte index d038cffda..fe83ea42b 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-item.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-item.svelte @@ -9,7 +9,7 @@ id = useId(), value, textValue = "", - ref = $bindable(), + ref = $bindable(null), asChild, children, child, @@ -22,6 +22,10 @@ disabled: box.with(() => disabled), value: box.with(() => value), textValue: box.with(() => textValue), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, itemState.props)); @@ -30,7 +34,7 @@ {#if asChild} {@render child?.({ props: mergedProps, selected: itemState.isSelected })} {:else} -
+
{@render children?.({ selected: itemState.isSelected })}
{/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-scroll-down-button-mounted.svelte b/packages/bits-ui/src/lib/bits/select/components/select-scroll-down-button-mounted.svelte index ef4c79795..94d926cc4 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-scroll-down-button-mounted.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-scroll-down-button-mounted.svelte @@ -7,7 +7,6 @@ asChild, children, child, - ref = $bindable(), mounted, ...restProps }: ScrollDownButtonProps & { @@ -29,7 +28,7 @@ {#if asChild} {@render child?.({ props: restProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-scroll-down-button.svelte b/packages/bits-ui/src/lib/bits/select/components/select-scroll-down-button.svelte index 15462f129..7f1ac4bfc 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-scroll-down-button.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-scroll-down-button.svelte @@ -6,13 +6,17 @@ import { useId } from "$lib/internal/useId.svelte.js"; import { mergeProps } from "$lib/internal/mergeProps.js"; - let { id = useId(), ref = $bindable(), ...restProps }: ScrollUpButtonProps = $props(); + let { id = useId(), ref = $bindable(null), ...restProps }: ScrollUpButtonProps = $props(); const mounted = box(false); const scrollDownButtonState = useSelectScrollDownButton({ id: box.with(() => id), mounted: box.from(mounted), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); // eslint-disable-next-line unused-imports/no-unused-vars, ts/no-unused-vars @@ -23,5 +27,5 @@ {#if scrollDownButtonState.canScrollDown} - + {/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-scroll-up-button-mounted.svelte b/packages/bits-ui/src/lib/bits/select/components/select-scroll-up-button-mounted.svelte index 9c5987815..2261261ec 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-scroll-up-button-mounted.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-scroll-up-button-mounted.svelte @@ -7,7 +7,6 @@ asChild, children, child, - ref = $bindable(), mounted, ...restProps }: ScrollUpButtonProps & { @@ -29,7 +28,7 @@ {#if asChild} {@render child?.({ props: restProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-scroll-up-button.svelte b/packages/bits-ui/src/lib/bits/select/components/select-scroll-up-button.svelte index ada1abbc9..5e54eacdf 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-scroll-up-button.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-scroll-up-button.svelte @@ -6,13 +6,17 @@ import { useId } from "$lib/internal/useId.svelte.js"; import { mergeProps } from "$lib/internal/mergeProps.js"; - let { id = useId(), ref = $bindable(), ...restProps }: ScrollUpButtonProps = $props(); + let { id = useId(), ref = $bindable(null), ...restProps }: ScrollUpButtonProps = $props(); const mounted = box(false); const scrollUpButtonState = useSelectScrollUpButton({ id: box.with(() => id), mounted: box.from(mounted), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); // eslint-disable-next-line unused-imports/no-unused-vars, ts/no-unused-vars @@ -23,5 +27,5 @@ {#if scrollUpButtonState.canScrollUp} - + {/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-separator.svelte b/packages/bits-ui/src/lib/bits/select/components/select-separator.svelte index 4caa98001..e2f269d4b 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-separator.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-separator.svelte @@ -2,10 +2,25 @@ import type { SeparatorProps } from "../index.js"; import { useSelectSeparator } from "../select.svelte.js"; import { mergeProps } from "$lib/internal/mergeProps.js"; + import { useId } from "$lib/internal/useId.svelte.js"; + import { box } from "svelte-toolbelt"; - let { asChild, child, children, ref = $bindable(), ...restProps }: SeparatorProps = $props(); + let { + asChild, + child, + children, + id = useId(), + ref = $bindable(null), + ...restProps + }: SeparatorProps = $props(); - const separatorState = useSelectSeparator(); + const separatorState = useSelectSeparator({ + id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), + }); const mergedProps = $derived(mergeProps(restProps, separatorState.props)); @@ -13,7 +28,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-trigger.svelte b/packages/bits-ui/src/lib/bits/select/components/select-trigger.svelte index f5a8fa797..895b484a9 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-trigger.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-trigger.svelte @@ -9,7 +9,7 @@ let { id = useId(), disabled = false, - ref = $bindable(), + ref = $bindable(null), asChild, children, child, @@ -19,6 +19,10 @@ const triggerState = useSelectTrigger({ id: box.with(() => id), disabled: box.with(() => disabled), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, triggerState.props)); @@ -28,7 +32,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} - {/if} diff --git a/packages/bits-ui/src/lib/bits/select/components/select-viewport.svelte b/packages/bits-ui/src/lib/bits/select/components/select-viewport.svelte index 1f6fa1c45..f70a0fdae 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-viewport.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-viewport.svelte @@ -7,7 +7,7 @@ let { id = useId(), - ref = $bindable(), + ref = $bindable(null), asChild, children, child, @@ -16,6 +16,10 @@ const viewportState = useSelectViewport({ id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, viewportState.props)); @@ -24,7 +28,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/select/select.svelte.ts b/packages/bits-ui/src/lib/bits/select/select.svelte.ts index 4b1dffd03..88ffe67a0 100644 --- a/packages/bits-ui/src/lib/bits/select/select.svelte.ts +++ b/packages/bits-ui/src/lib/bits/select/select.svelte.ts @@ -7,7 +7,7 @@ import { useId } from "$lib/internal/useId.svelte.js"; import type { Direction } from "$lib/shared/index.js"; import { createContext } from "$lib/internal/createContext.js"; import { useFormControl } from "$lib/internal/useFormControl.svelte.js"; -import { useNodeById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; import { type Typeahead, useTypeahead } from "$lib/internal/useTypeahead.svelte.js"; import { getAriaDisabled, @@ -25,6 +25,7 @@ import { clamp } from "$lib/internal/clamp.js"; import { noop } from "$lib/internal/callbacks.js"; import { addEventListener } from "$lib/internal/events.js"; import { sleep } from "$lib/internal/sleep.js"; +import type { WithRefProps } from "$lib/internal/types.js"; export const OPEN_KEYS = [kbd.SPACE, kbd.ENTER, kbd.ARROW_UP, kbd.ARROW_DOWN]; export const SELECTION_KEYS = [" ", kbd.ENTER]; @@ -85,24 +86,24 @@ export class SelectRootState { dir: SelectRootStateProps["dir"]; disabled: SelectRootStateProps["disabled"]; required: SelectRootStateProps["required"]; - triggerId = $state(useId()); + triggerNode = $state(null); valueId = box(useId()); valueNodeHasChildren = box(false); - contentId = box(useId()); + contentNode = $state(null); triggerPointerDownPos = box<{ x: number; y: number } | null>({ x: 0, y: 0 }); contentFragment = $state(null); // A set of all the native options we'll use to render the native select element under the hood - nativeOptionsSet = new Set>(); + #nativeOptionsSet = new Set>(); // A key we'll use to rerender the native select when the options change to keep it in sync nativeSelectKey = $derived.by(() => { - return Array.from(this.nativeOptionsSet) + return Array.from(this.#nativeOptionsSet) .map((opt) => opt.value.value) .join(";"); }); - nativeOptionsArr = $derived.by(() => Array.from(this.nativeOptionsSet)); - isFormControl = useFormControl(() => this.triggerId); + nativeOptionsArr = $derived.by(() => Array.from(this.#nativeOptionsSet)); + isFormControl = useFormControl(() => this.triggerNode); constructor(props: SelectRootStateProps) { this.open = props.open; @@ -118,7 +119,7 @@ export class SelectRootState { } focusTriggerNode(preventScroll: boolean = true) { - const node = document.getElementById(this.triggerId); + const node = this.triggerNode; if (node) { sleep(1).then(() => { node.focus({ preventScroll }); @@ -127,11 +128,11 @@ export class SelectRootState { } onNativeOptionAdd(option: ReadableBox) { - this.nativeOptionsSet.add(option); + this.#nativeOptionsSet.add(option); } onNativeOptionRemove(option: ReadableBox) { - this.nativeOptionsSet.delete(option); + this.#nativeOptionsSet.delete(option); } getTriggerTypeaheadCandidateNodes() { @@ -144,7 +145,7 @@ export class SelectRootState { } getCandidateNodes() { - const node = document.getElementById(this.contentId.value); + const node = this.contentNode; if (!node) return []; const candidates = Array.from( node.querySelectorAll(`[${ITEM_ATTR}]:not([data-disabled])`) @@ -160,8 +161,8 @@ export class SelectRootState { return new SelectValueState(this); } - createContent(props: SelectContentFragStateProps) { - return new SelectContentFragState(props, this); + createContent() { + return new SelectContentFragState(this); } createContentImpl(props: SelectContentStateProps) { @@ -169,14 +170,16 @@ export class SelectRootState { } } -type SelectTriggerStateProps = ReadableBoxedValues<{ - id: string; - disabled: boolean; -}>; +type SelectTriggerStateProps = WithRefProps< + ReadableBoxedValues<{ + disabled: boolean; + }> +>; class SelectTriggerState { #root: SelectRootState; #id: SelectTriggerStateProps["id"]; + #ref: SelectTriggerStateProps["ref"]; #disabled: SelectTriggerStateProps["disabled"]; #typeahead: Typeahead; #isDisabled = $derived.by(() => { @@ -185,11 +188,16 @@ class SelectTriggerState { constructor(props: SelectTriggerStateProps, root: SelectRootState) { this.#id = props.id; + this.#ref = props.ref; this.#root = root; this.#disabled = props.disabled; - $effect(() => { - this.#root.triggerId = this.#id.value; + useRefById({ + id: this.#id, + ref: this.#ref, + onRefChange: (node) => { + this.#root.triggerNode = node; + }, }); this.#typeahead = useTypeahead(); @@ -268,7 +276,7 @@ class SelectTriggerState { }; #ariaControls = $derived.by(() => { - return this.#root.contentId.value ?? undefined; + return this.#root.contentNode?.id ?? undefined; }); props = $derived.by( @@ -318,20 +326,11 @@ class SelectValueState { ); } -type SelectContentFragStateProps = ReadableBoxedValues<{ - id: string; -}>; - class SelectContentFragState { root: SelectRootState; - constructor(props: SelectContentFragStateProps, root: SelectRootState) { + constructor(root: SelectRootState) { this.root = root; - this.root.contentId.value = props.id.value; - - $effect(() => { - this.root.contentId.value = props.id.value; - }); $effect(() => { this.root.contentFragment = new DocumentFragment(); @@ -339,16 +338,17 @@ class SelectContentFragState { } } -type SelectContentStateProps = ReadableBoxedValues<{ - id: string; - position: "item-aligned" | "floating"; -}>; +type SelectContentStateProps = WithRefProps< + ReadableBoxedValues<{ + position: "item-aligned" | "floating"; + }> +>; export class SelectContentState { id: SelectContentStateProps["id"]; + ref: SelectContentStateProps["ref"]; root: SelectRootState; - contentNode = box(null); - viewportId = $state(useId()); + viewportNode = $state(null); selectedItemId = box(useId()); selectedItemTextId = box(useId()); selectedItemText = box(null); @@ -361,9 +361,18 @@ export class SelectContentState { constructor(props: SelectContentStateProps, root: SelectRootState) { this.position = props.position; this.id = props.id; + this.ref = props.ref; this.root = root; this.typeahead = useTypeahead(); - this.contentNode = useNodeById(this.id); + + useRefById({ + id: this.id, + ref: this.ref, + condition: () => this.root.open.value, + onRefChange: (node) => { + this.root.contentNode = node; + }, + }); watch(this.root.open, () => { let cleanup = [noop]; @@ -391,7 +400,7 @@ export class SelectContentState { if (pointerMoveDelta.x <= 10 && pointerMoveDelta.y <= 10) { e.preventDefault(); } else { - if (!this.contentNode.value?.contains(e.target as HTMLElement)) { + if (!this.root.contentNode?.contains(e.target as HTMLElement)) { this.root.handleClose(); } } @@ -442,7 +451,7 @@ export class SelectContentState { if (candidate === PREV_FOCUSED_ELEMENT) return; candidate?.scrollIntoView({ block: "nearest" }); // viewport might have padding so scroll to the edge when focusing first/last - const viewport = document.getElementById(this.viewportId); + const viewport = this.viewportNode; if (candidate === firstItem && viewport) { viewport.scrollTop = 0; } @@ -457,7 +466,7 @@ export class SelectContentState { } onItemLeave() { - this.contentNode.value?.focus(); + this.root.contentNode?.focus(); } getSelectedItem() { @@ -596,15 +605,17 @@ export class SelectContentState { } } -type SelectItemStateProps = ReadableBoxedValues<{ - value: string; - disabled: boolean; - textValue?: string; - id: string; -}>; +type SelectItemStateProps = WithRefProps< + ReadableBoxedValues<{ + value: string; + disabled: boolean; + textValue?: string; + }> +>; class SelectItemState { #id: SelectItemStateProps["id"]; + #ref: SelectItemStateProps["ref"]; root: SelectRootState; content: SelectContentState; textId = box(undefined); @@ -618,14 +629,20 @@ class SelectItemState { constructor(props: SelectItemStateProps, content: SelectContentState) { this.#id = props.id; + this.#ref = props.ref; this.root = content.root; this.content = content; this.value = props.value; this.disabled = props.disabled; this.textValue = props.textValue; + useRefById({ + id: this.#id, + ref: this.#ref, + }); + $effect(() => { - const node = document.getElementById(this.#id.value); + const node = this.#ref.value; if (!node) return; this.content.itemRegister(this.value.value, this.disabled.value); }); @@ -731,13 +748,12 @@ class SelectItemState { } } -type SelectItemTextStateProps = ReadableBoxedValues<{ - id: string; -}>; +type SelectItemTextStateProps = WithRefProps; class SelectItemTextState { item: SelectItemState; #id: SelectItemTextStateProps["id"]; + #ref: SelectItemTextStateProps["ref"]; node = box(null); nativeOption = box.with( () => @@ -751,10 +767,15 @@ class SelectItemTextState { constructor(props: SelectItemTextStateProps, item: SelectItemState) { this.#id = props.id; - this.node = useNodeById(this.#id); + this.#ref = props.ref; this.item = item; this.item.setTextId(this.#id.value); + useRefById({ + id: this.#id, + ref: this.#ref, + }); + $effect(() => { this.item.setTextId(this.#id.value); }); @@ -829,10 +850,10 @@ class SelectItemAlignedPositionState { position() { afterTick(() => { const { selectedItemNode, selectedItemTextNode } = this.content.getSelectedItem(); - const contentNode = document.getElementById(this.content.id.value); + const contentNode = this.root.contentNode; const contentWrapperNode = document.getElementById(this.contentWrapperId); - const viewportNode = document.getElementById(this.content.viewportId); - const triggerNode = document.getElementById(this.root.triggerId); + const viewportNode = this.content.viewportNode; + const triggerNode = this.root.triggerNode; const valueNode = document.getElementById(this.root.valueId.value); if ( @@ -1016,23 +1037,26 @@ class SelectFloatingPositionState { } as const; } -type SelectViewportStateProps = ReadableBoxedValues<{ - id: string; -}>; +type SelectViewportStateProps = WithRefProps; class SelectViewportState { id: SelectViewportStateProps["id"]; + ref: SelectViewportStateProps["ref"]; content: SelectContentState; prevScrollTop = $state(0); constructor(props: SelectViewportStateProps, content: SelectContentState) { this.id = props.id; this.content = content; - this.content.viewportId = props.id.value; - $effect(() => { - if (this.content.viewportId !== props.id.value) { - this.content.viewportId = props.id.value; - } + this.ref = props.ref; + + useRefById({ + id: this.id, + ref: this.ref, + onRefChange: (node) => { + this.content.viewportNode = node; + }, + condition: () => this.content.root.open.value, }); } @@ -1090,13 +1114,15 @@ class SelectViewportState { ); } -type SelectScrollButtonImplStateProps = ReadableBoxedValues<{ - id: string; - mounted: boolean; -}>; +type SelectScrollButtonImplStateProps = WithRefProps< + ReadableBoxedValues<{ + mounted: boolean; + }> +>; class SelectScrollButtonImplState { id: SelectScrollButtonImplStateProps["id"]; + ref: SelectScrollButtonImplStateProps["ref"]; content: SelectContentState; alignedPositionState: SelectItemAlignedPositionState | null; autoScrollTimer = $state(null); @@ -1105,10 +1131,17 @@ class SelectScrollButtonImplState { constructor(props: SelectScrollButtonImplStateProps, content: SelectContentState) { this.content = content; + this.ref = props.ref; this.alignedPositionState = content.alignedPositionState; this.id = props.id; this.mounted = props.mounted; + useRefById({ + id: this.id, + ref: this.ref, + condition: () => this.mounted.value, + }); + $effect(() => { if (this.mounted.value) { const activeItem = this.content.root @@ -1170,7 +1203,6 @@ class SelectScrollDownButtonState { state: SelectScrollButtonImplState; content: SelectContentState; canScrollDown = $state(false); - node = $state(null); constructor(state: SelectScrollButtonImplState) { this.state = state; @@ -1178,7 +1210,7 @@ class SelectScrollDownButtonState { this.state.onAutoScroll = this.handleAutoScroll; $effect(() => { - const viewport = document.getElementById(this.content.viewportId); + const viewport = this.content.viewportNode; const isPositioned = this.content.isPositioned.value; if (!viewport || !isPositioned) return; @@ -1215,7 +1247,7 @@ class SelectScrollDownButtonState { handleAutoScroll() { afterTick(() => { - const viewport = document.getElementById(this.content.viewportId); + const viewport = this.content.viewportNode; const selectedItem = this.content.getSelectedItem().selectedItemNode; if (!viewport || !selectedItem) { return; @@ -1231,7 +1263,6 @@ class SelectScrollUpButtonState { state: SelectScrollButtonImplState; content: SelectContentState; canScrollUp = $state(false); - node = $state(null); constructor(state: SelectScrollButtonImplState) { this.state = state; @@ -1242,7 +1273,7 @@ class SelectScrollUpButtonState { let cleanup = noop; cleanup(); - const viewport = document.getElementById(this.content.viewportId); + const viewport = this.content.viewportNode; const isPositioned = this.content.isPositioned.value; if (!viewport || !isPositioned) return; @@ -1274,7 +1305,7 @@ class SelectScrollUpButtonState { handleAutoScroll() { afterTick(() => { - const viewport = document.getElementById(this.content.viewportId); + const viewport = this.content.viewportNode; const selectedItem = this.content.getSelectedItem().selectedItemNode; if (!viewport || !selectedItem) return; viewport.scrollTop = viewport.scrollTop - selectedItem.offsetHeight; @@ -1284,14 +1315,29 @@ class SelectScrollUpButtonState { props = $derived.by(() => ({ ...this.state.props, [SCROLL_UP_BUTTON_ATTR]: "" }) as const); } +type SelectGroupStateProps = WithRefProps; + class SelectGroupState { - labelId = box.with(() => undefined); + #id: SelectGroupStateProps["id"]; + #ref: SelectGroupStateProps["ref"]; + labelNode = $state(null); + + constructor(props: SelectGroupStateProps) { + this.#id = props.id; + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); + } props = $derived.by( () => ({ + id: this.#id.value, role: "group", - "aria-labelledby": this.labelId.value ?? undefined, + "aria-labelledby": this.labelNode?.id ?? undefined, [GROUP_ATTR]: "", }) as const ); @@ -1301,54 +1347,120 @@ class SelectGroupState { } } -type SelectGroupLabelStateProps = ReadableBoxedValues<{ - id: string; -}>; +type SelectGroupLabelStateProps = WithRefProps; class SelectGroupLabel { + #id: SelectGroupLabelStateProps["id"]; + #ref: SelectGroupLabelStateProps["ref"]; group: SelectGroupState; constructor(props: SelectGroupLabelStateProps, group: SelectGroupState) { + this.#ref = props.ref; + this.#id = props.id; this.group = group; - this.group.labelId = props.id; + + useRefById({ + id: this.#id, + ref: this.#ref, + onRefChange: (node) => { + this.group.labelNode = node; + }, + }); } props = $derived.by( () => ({ - id: this.group.labelId.value, + id: this.#id.value, [GROUP_LABEL_ATTR]: "", }) as const ); } +type SelectSeparatorStateProps = WithRefProps; + class SelectSeparatorState { - props = { - [SEPARATOR_ATTR]: "", - "aria-hidden": getAriaHidden(true), - } as const; + #id: SelectSeparatorStateProps["id"]; + #ref: SelectSeparatorStateProps["ref"]; + + constructor(props: SelectSeparatorStateProps) { + this.#id = props.id; + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); + } + + props = $derived.by( + () => + ({ + id: this.#id.value, + [SEPARATOR_ATTR]: "", + "aria-hidden": getAriaHidden(true), + }) as const + ); } +type SelectArrowStateProps = WithRefProps; + class SelectArrowState { - props = { - [ARROW_ATTR]: "", - "aria-hidden": getAriaHidden(true), - } as const; + #id: SelectArrowStateProps["id"]; + #ref: SelectArrowStateProps["ref"]; + + constructor(props: SelectArrowStateProps) { + this.#id = props.id; + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); + } + + props = $derived.by( + () => + ({ + id: this.#id.value, + [ARROW_ATTR]: "", + "aria-hidden": getAriaHidden(true), + }) as const + ); } +type SelectIconStateProps = WithRefProps; + class SelectIconState { - props = { - [ICON_ATTR]: "", - "aria-hidden": getAriaHidden(true), - } as const; + #id: SelectIconStateProps["id"]; + #ref: SelectIconStateProps["ref"]; + + constructor(props: SelectIconStateProps) { + this.#id = props.id; + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); + } + + props = $derived.by( + () => + ({ + id: this.#id.value, + [ICON_ATTR]: "", + "aria-hidden": getAriaHidden(true), + }) as const + ); } export function useSelectRoot(props: SelectRootStateProps) { return setSelectRootContext(new SelectRootState(props)); } -export function useSelectContentFrag(props: SelectContentFragStateProps) { - return getSelectRootContext().createContent(props); +export function useSelectContentFrag() { + return getSelectRootContext().createContent(); } export function useSelectContent(props: SelectContentStateProps) { @@ -1394,24 +1506,24 @@ export function useSelectScrollDownButton(props: SelectScrollButtonImplStateProp return getSelectContentContext().createScrollDownButton(props); } -export function useSelectGroup() { - return setSelectGroupContext(new SelectGroupState()); +export function useSelectGroup(props: SelectGroupStateProps) { + return setSelectGroupContext(new SelectGroupState(props)); } export function useSelectGroupLabel(props: SelectGroupLabelStateProps) { return getSelectGroupContext().createGroupLabel(props); } -export function useSelectArrow() { - return new SelectArrowState(); +export function useSelectArrow(props: SelectArrowStateProps) { + return new SelectArrowState(props); } -export function useSelectSeparator() { - return new SelectSeparatorState(); +export function useSelectSeparator(props: SelectSeparatorStateProps) { + return new SelectSeparatorState(props); } -export function useSelectIcon() { - return new SelectIconState(); +export function useSelectIcon(props: SelectIconStateProps) { + return new SelectIconState(props); } // diff --git a/packages/bits-ui/src/lib/bits/tabs/components/tabs-content.svelte b/packages/bits-ui/src/lib/bits/tabs/components/tabs-content.svelte index 39eba4026..68be68c50 100644 --- a/packages/bits-ui/src/lib/bits/tabs/components/tabs-content.svelte +++ b/packages/bits-ui/src/lib/bits/tabs/components/tabs-content.svelte @@ -3,18 +3,25 @@ import type { ContentProps } from "../index.js"; import { useTabsContent } from "../tabs.svelte.js"; import { mergeProps } from "$lib/internal/mergeProps.js"; + import { useId } from "$lib/internal/useId.svelte.js"; let { asChild, children, child, - ref = $bindable(), + id = useId(), + ref = $bindable(null), value, ...restProps }: ContentProps = $props(); const contentState = useTabsContent({ value: box.with(() => value), + id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, contentState.props)); @@ -23,7 +30,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/tabs/components/tabs-list.svelte b/packages/bits-ui/src/lib/bits/tabs/components/tabs-list.svelte index ac889d436..9bd649869 100644 --- a/packages/bits-ui/src/lib/bits/tabs/components/tabs-list.svelte +++ b/packages/bits-ui/src/lib/bits/tabs/components/tabs-list.svelte @@ -2,10 +2,25 @@ import type { ListProps } from "../index.js"; import { useTabsList } from "../tabs.svelte.js"; import { mergeProps } from "$lib/internal/mergeProps.js"; + import { useId } from "$lib/internal/useId.svelte.js"; + import { box } from "svelte-toolbelt"; - let { asChild, child, children, ref = $bindable(), ...restProps }: ListProps = $props(); + let { + asChild, + child, + children, + id = useId(), + ref = $bindable(null), + ...restProps + }: ListProps = $props(); - const listState = useTabsList(); + const listState = useTabsList({ + id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), + }); const mergedProps = $derived(mergeProps(restProps, listState.props)); @@ -13,7 +28,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/tabs/components/tabs-trigger.svelte b/packages/bits-ui/src/lib/bits/tabs/components/tabs-trigger.svelte index 4d6a9f880..b934ab316 100644 --- a/packages/bits-ui/src/lib/bits/tabs/components/tabs-trigger.svelte +++ b/packages/bits-ui/src/lib/bits/tabs/components/tabs-trigger.svelte @@ -13,7 +13,7 @@ id = useId(), type = "button", value, - ref = $bindable(), + ref = $bindable(null), ...restProps }: TriggerProps = $props(); @@ -21,6 +21,10 @@ id: box.with(() => id), disabled: box.with(() => disabled), value: box.with(() => value), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, triggerState.props, { type })); @@ -29,7 +33,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} - {/if} diff --git a/packages/bits-ui/src/lib/bits/tabs/components/tabs.svelte b/packages/bits-ui/src/lib/bits/tabs/components/tabs.svelte index 53f8e17d1..36c446332 100644 --- a/packages/bits-ui/src/lib/bits/tabs/components/tabs.svelte +++ b/packages/bits-ui/src/lib/bits/tabs/components/tabs.svelte @@ -9,7 +9,7 @@ asChild, children, child, - ref = $bindable(), + ref = $bindable(null), id = useId(), value = $bindable(""), onValueChange, @@ -35,6 +35,10 @@ loop: box.with(() => loop), activationMode: box.with(() => activationMode), disabled: box.with(() => disabled), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, rootState.props)); @@ -43,7 +47,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/tabs/tabs.svelte.ts b/packages/bits-ui/src/lib/bits/tabs/tabs.svelte.ts index 93abe21b0..79229da4f 100644 --- a/packages/bits-ui/src/lib/bits/tabs/tabs.svelte.ts +++ b/packages/bits-ui/src/lib/bits/tabs/tabs.svelte.ts @@ -3,6 +3,7 @@ import { untrack } from "svelte"; import type { TabsActivationMode } from "./types.js"; import { type ReadableBoxedValues, + type WithRefProps, type WritableBoxedValues, getAriaOrientation, getDataDisabled, @@ -11,7 +12,7 @@ import { getHiddenAttr, isBrowser, kbd, - useNodeById, + useRefById, } from "$lib/internal/index.js"; import type { Orientation } from "$lib/shared/index.js"; import { type UseRovingFocusReturn, useRovingFocus } from "$lib/internal/useRovingFocus.svelte.js"; @@ -22,20 +23,21 @@ const LIST_ATTR = "data-tabs-list"; const TRIGGER_ATTR = "data-tabs-trigger"; const CONTENT_ATTR = "data-tabs-content"; -type TabsRootStateProps = ReadableBoxedValues<{ - id: string; - orientation: Orientation; - loop: boolean; - activationMode: TabsActivationMode; - disabled: boolean; -}> & - WritableBoxedValues<{ - value: string; - }>; +type TabsRootStateProps = WithRefProps< + ReadableBoxedValues<{ + orientation: Orientation; + loop: boolean; + activationMode: TabsActivationMode; + disabled: boolean; + }> & + WritableBoxedValues<{ + value: string; + }> +>; class TabsRootState { - id: TabsRootStateProps["id"]; - node: WritableBox; + #id: TabsRootStateProps["id"]; + ref: TabsRootStateProps["ref"]; orientation: TabsRootStateProps["orientation"]; loop: TabsRootStateProps["loop"]; activationMode: TabsRootStateProps["activationMode"]; @@ -45,16 +47,22 @@ class TabsRootState { triggerIds = $state([]); constructor(props: TabsRootStateProps) { - this.id = props.id; + this.#id = props.id; + this.ref = props.ref; this.orientation = props.orientation; this.loop = props.loop; this.activationMode = props.activationMode; this.value = props.value; this.disabled = props.disabled; - this.node = useNodeById(this.id); + + useRefById({ + id: this.#id, + ref: this.ref, + }); + this.rovingFocusGroup = useRovingFocus({ candidateSelector: TRIGGER_ATTR, - rootNodeId: this.id, + rootNodeId: this.#id, loop: this.loop, orientation: this.orientation, }); @@ -72,8 +80,8 @@ class TabsRootState { this.value.value = v; } - createList() { - return new TabsListState(this); + createList(props: TabsListStateProps) { + return new TabsListState(props, this); } createTrigger(props: TabsTriggerStateProps) { @@ -87,7 +95,7 @@ class TabsRootState { props = $derived.by( () => ({ - id: this.id.value, + id: this.#id.value, "data-orientation": getDataOrientation(this.orientation.value), [ROOT_ATTR]: "", }) as const @@ -98,17 +106,29 @@ class TabsRootState { // LIST // +type TabsListStateProps = WithRefProps; + class TabsListState { + #id: TabsListStateProps["id"]; + #ref: TabsListStateProps["ref"]; #root: TabsRootState; #isDisabled = $derived.by(() => this.#root.disabled.value); - constructor(root: TabsRootState) { + constructor(props: TabsListStateProps, root: TabsRootState) { this.#root = root; + this.#id = props.id; + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); } props = $derived.by( () => ({ + id: this.#id.value, role: "tablist", "aria-orientation": getAriaOrientation(this.#root.orientation.value), "data-orientation": getDataOrientation(this.#root.orientation.value), @@ -122,15 +142,17 @@ class TabsListState { // TRIGGER // -type TabsTriggerStateProps = ReadableBoxedValues<{ - id: string; - value: string; - disabled: boolean; -}>; +type TabsTriggerStateProps = WithRefProps< + ReadableBoxedValues<{ + value: string; + disabled: boolean; + }> +>; class TabsTriggerState { #root: TabsRootState; #id: TabsTriggerStateProps["id"]; + #ref: TabsTriggerStateProps["ref"]; #disabled: TabsTriggerStateProps["disabled"]; #value: TabsTriggerStateProps["value"]; #isActive = $derived.by(() => this.#root.value.value === this.#value.value); @@ -140,9 +162,15 @@ class TabsTriggerState { constructor(props: TabsTriggerStateProps, root: TabsRootState) { this.#root = root; this.#id = props.id; + this.#ref = props.ref; this.#value = props.value; this.#disabled = props.disabled; + useRefById({ + id: this.#id, + ref: this.#ref, + }); + $effect(() => { // we want to track the value const id = this.#id.value; @@ -157,16 +185,11 @@ class TabsTriggerState { $effect(() => { if (this.#root.triggerIds.length) { - this.#tabIndex = this.#root.rovingFocusGroup.getTabIndex(this.#getNode()); + this.#tabIndex = this.#root.rovingFocusGroup.getTabIndex(this.#ref.value); } }); } - #getNode() { - if (!isBrowser) return null; - return document.getElementById(this.#id.value); - } - activate() { if (this.#root.value.value === this.#value.value) return; this.#root.setValue(this.#value.value); @@ -179,7 +202,7 @@ class TabsTriggerState { }; #onclick = (e: MouseEvent) => { - const node = document.getElementById(this.#id.value); + const node = this.#ref.value; if (!node || this.#isDisabled) return; e.preventDefault(); node.focus(); @@ -193,7 +216,7 @@ class TabsTriggerState { this.activate(); return; } - this.#root.rovingFocusGroup.handleKeydown(this.#getNode(), e); + this.#root.rovingFocusGroup.handleKeydown(this.#ref.value, e); }; props = $derived.by( @@ -219,18 +242,29 @@ class TabsTriggerState { // CONTENT // -type TabsContentStateProps = ReadableBoxedValues<{ - value: string; -}>; +type TabsContentStateProps = WithRefProps< + ReadableBoxedValues<{ + value: string; + }> +>; class TabsContentState { #root: TabsRootState; + #id: TabsContentStateProps["id"]; + #ref: TabsContentStateProps["ref"]; #value: TabsContentStateProps["value"]; #isActive = $derived.by(() => this.#root.value.value === this.#value.value); constructor(props: TabsContentStateProps, root: TabsRootState) { this.#root = root; this.#value = props.value; + this.#id = props.id; + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); } props = $derived.by( @@ -260,8 +294,8 @@ export function useTabsTrigger(props: TabsTriggerStateProps) { return getTabsRootContext().createTrigger(props); } -export function useTabsList() { - return getTabsRootContext().createList(); +export function useTabsList(props: TabsListStateProps) { + return getTabsRootContext().createList(props); } export function useTabsContent(props: TabsContentStateProps) { diff --git a/packages/bits-ui/src/lib/bits/toggle-group/components/toggle-group-item.svelte b/packages/bits-ui/src/lib/bits/toggle-group/components/toggle-group-item.svelte index 876256af6..3de67bac9 100644 --- a/packages/bits-ui/src/lib/bits/toggle-group/components/toggle-group-item.svelte +++ b/packages/bits-ui/src/lib/bits/toggle-group/components/toggle-group-item.svelte @@ -9,7 +9,7 @@ asChild, children, child, - ref = $bindable(), + ref = $bindable(null), value, disabled = false, id = useId(), @@ -21,6 +21,10 @@ id: box.with(() => id), value: box.with(() => value), disabled: box.with(() => disabled), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, itemState.props, { type })); diff --git a/packages/bits-ui/src/lib/bits/toggle-group/components/toggle-group.svelte b/packages/bits-ui/src/lib/bits/toggle-group/components/toggle-group.svelte index f8b2426ae..cb05ac12a 100644 --- a/packages/bits-ui/src/lib/bits/toggle-group/components/toggle-group.svelte +++ b/packages/bits-ui/src/lib/bits/toggle-group/components/toggle-group.svelte @@ -9,7 +9,7 @@ asChild, child, children, - ref = $bindable(), + ref = $bindable(null), id = useId(), value = $bindable(), onValueChange, @@ -37,6 +37,10 @@ orientation: box.with(() => orientation), rovingFocus: box.with(() => rovingFocus), type, + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, rootState.props)); @@ -45,7 +49,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/toggle-group/toggle-group.svelte.ts b/packages/bits-ui/src/lib/bits/toggle-group/toggle-group.svelte.ts index 9a7232271..9d368d6f7 100644 --- a/packages/bits-ui/src/lib/bits/toggle-group/toggle-group.svelte.ts +++ b/packages/bits-ui/src/lib/bits/toggle-group/toggle-group.svelte.ts @@ -8,25 +8,27 @@ import { } from "$lib/internal/attrs.js"; import type { ReadableBoxedValues, WritableBoxedValues } from "$lib/internal/box.svelte.js"; import { kbd } from "$lib/internal/kbd.js"; -import { useNodeById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; import type { Orientation } from "$lib/shared/index.js"; import { type UseRovingFocusReturn, useRovingFocus } from "$lib/internal/useRovingFocus.svelte.js"; import { createContext } from "$lib/internal/createContext.js"; +import type { WithRefProps } from "$lib/internal/types.js"; const ROOT_ATTR = "data-toggle-group-root"; const ITEM_ATTR = "data-toggle-group-item"; -type ToggleGroupBaseStateProps = ReadableBoxedValues<{ - id: string; - disabled: boolean; - rovingFocus: boolean; - loop: boolean; - orientation: Orientation; -}>; +type ToggleGroupBaseStateProps = WithRefProps< + ReadableBoxedValues<{ + disabled: boolean; + rovingFocus: boolean; + loop: boolean; + orientation: Orientation; + }> +>; class ToggleGroupBaseState { id: ToggleGroupBaseStateProps["id"]; - node: WritableBox; + ref: ToggleGroupBaseStateProps["ref"]; disabled: ToggleGroupBaseStateProps["disabled"]; rovingFocus: ToggleGroupBaseStateProps["rovingFocus"]; loop: ToggleGroupBaseStateProps["loop"]; @@ -35,7 +37,7 @@ class ToggleGroupBaseState { constructor(props: ToggleGroupBaseStateProps) { this.id = props.id; - this.node = useNodeById(this.id); + this.ref = props.ref; this.disabled = props.disabled; this.rovingFocus = props.rovingFocus; this.loop = props.loop; @@ -46,6 +48,11 @@ class ToggleGroupBaseState { loop: this.loop, orientation: this.orientation, }); + + useRefById({ + id: this.id, + ref: this.ref, + }); } props = $derived.by( @@ -132,19 +139,20 @@ type ToggleGroupState = ToggleGroupSingleState | ToggleGroupMultipleState; // ITEM // -type ToggleGroupItemStateProps = ReadableBoxedValues<{ - id: string; - value: string; - disabled: boolean; -}> & { - rootState: ToggleGroupState; -}; +type ToggleGroupItemStateProps = WithRefProps< + ReadableBoxedValues<{ + value: string; + disabled: boolean; + }> & { + rootState: ToggleGroupState; + } +>; class ToggleGroupItemState { #id: ToggleGroupItemStateProps["id"]; + #ref: ToggleGroupItemStateProps["ref"]; #root: ToggleGroupItemStateProps["rootState"]; #value: ToggleGroupItemStateProps["value"]; - #node = box(null); #disabled: ToggleGroupItemStateProps["disabled"]; #isDisabled = $derived.by(() => this.#disabled.value || this.#root.disabled.value); @@ -153,7 +161,12 @@ class ToggleGroupItemState { this.#disabled = props.disabled; this.#root = props.rootState; this.#id = props.id; - this.#node = useNodeById(this.#id); + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); } toggleItem() { @@ -174,7 +187,7 @@ class ToggleGroupItemState { } if (!this.#root.rovingFocus.value) return; - this.#root.rovingFocusGroup.handleKeydown(this.#node.value, e); + this.#root.rovingFocusGroup.handleKeydown(this.#ref.value, e); }; #isPressed = $derived.by(() => this.#root.includesItem(this.#value.value)); @@ -188,9 +201,7 @@ class ToggleGroupItemState { }); #tabIndex = $derived.by(() => - !this.#root.rovingFocus.value - ? 0 - : this.#root.rovingFocusGroup.getTabIndex(this.#node.value).value + !this.#root.rovingFocus.value ? 0 : this.#root.rovingFocusGroup.getTabIndex(this.#ref.value) ); props = $derived.by( @@ -229,16 +240,17 @@ function getToggleItemDataState(condition: boolean) { const [setToggleGroupRootContext, getToggleGroupRootContext] = createContext("ToggleGroup.Root"); -type InitToggleGroupProps = { - type: "single" | "multiple"; - value: WritableBox | WritableBox; -} & ReadableBoxedValues<{ - id: string; - disabled: boolean; - rovingFocus: boolean; - loop: boolean; - orientation: Orientation; -}>; +type InitToggleGroupProps = WithRefProps< + { + type: "single" | "multiple"; + value: WritableBox | WritableBox; + } & ReadableBoxedValues<{ + disabled: boolean; + rovingFocus: boolean; + loop: boolean; + orientation: Orientation; + }> +>; export function useToggleGroupRoot(props: InitToggleGroupProps) { const { type, ...rest } = props; diff --git a/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-button.svelte b/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-button.svelte index c663bca0b..99855bc08 100644 --- a/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-button.svelte +++ b/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-button.svelte @@ -12,13 +12,17 @@ disabled = false, type = "button", id = useId(), - ref = $bindable(), + ref = $bindable(null), ...restProps }: ButtonProps = $props(); const buttonState = useToolbarButton({ id: box.with(() => id), disabled: box.with(() => disabled), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, buttonState.props, { type })); @@ -27,7 +31,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} - {/if} diff --git a/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-group-item.svelte b/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-group-item.svelte index 950ae4ccc..201063a9c 100644 --- a/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-group-item.svelte +++ b/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-group-item.svelte @@ -13,7 +13,7 @@ disabled = false, type = "button", id = useId(), - ref = $bindable(), + ref = $bindable(null), ...restProps }: GroupItemProps = $props(); @@ -21,6 +21,10 @@ id: box.with(() => id), value: box.with(() => value), disabled: box.with(() => disabled), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, groupItemState.props, { type })); @@ -29,7 +33,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} - {/if} diff --git a/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-group.svelte b/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-group.svelte index b9e07fd96..12a5d06f8 100644 --- a/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-group.svelte +++ b/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-group.svelte @@ -9,7 +9,7 @@ asChild, child, children, - ref = $bindable(), + ref = $bindable(null), id = useId(), value = $bindable(), onValueChange, @@ -31,6 +31,10 @@ onValueChange?.(v as any); } ) as WritableBox | WritableBox, + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, groupState.props)); @@ -39,7 +43,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-link.svelte b/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-link.svelte index 86218229d..4abd1cb92 100644 --- a/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-link.svelte +++ b/packages/bits-ui/src/lib/bits/toolbar/components/toolbar-link.svelte @@ -10,13 +10,17 @@ children, href, child, - ref = $bindable(), + ref = $bindable(null), id = useId(), ...restProps }: LinkProps = $props(); const linkState = useToolbarLink({ id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, linkState.props)); @@ -25,7 +29,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} - + {@render children?.()} {/if} diff --git a/packages/bits-ui/src/lib/bits/toolbar/components/toolbar.svelte b/packages/bits-ui/src/lib/bits/toolbar/components/toolbar.svelte index 503e35e06..587bd3d4b 100644 --- a/packages/bits-ui/src/lib/bits/toolbar/components/toolbar.svelte +++ b/packages/bits-ui/src/lib/bits/toolbar/components/toolbar.svelte @@ -9,7 +9,7 @@ asChild, child, children, - ref = $bindable(), + ref = $bindable(null), id = useId(), orientation = "horizontal", loop = true, @@ -20,6 +20,10 @@ id: box.with(() => id), orientation: box.with(() => orientation), loop: box.with(() => loop), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, rootState.props)); @@ -28,7 +32,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/toolbar/toolbar.svelte.ts b/packages/bits-ui/src/lib/bits/toolbar/toolbar.svelte.ts index 39ae3d007..84157c882 100644 --- a/packages/bits-ui/src/lib/bits/toolbar/toolbar.svelte.ts +++ b/packages/bits-ui/src/lib/bits/toolbar/toolbar.svelte.ts @@ -8,10 +8,11 @@ import { } from "$lib/internal/attrs.js"; import type { ReadableBoxedValues, WritableBoxedValues } from "$lib/internal/box.svelte.js"; import { kbd } from "$lib/internal/kbd.js"; -import { useNodeById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; import { type UseRovingFocusReturn, useRovingFocus } from "$lib/internal/useRovingFocus.svelte.js"; import type { Orientation } from "$lib/shared/index.js"; import { createContext } from "$lib/internal/createContext.js"; +import type { WithRefProps } from "$lib/internal/types.js"; const ROOT_ATTR = "data-toolbar-root"; // all links, buttons, and items must have the ITEM_ATTR for roving focus @@ -21,24 +22,31 @@ const GROUP_ITEM_ATTR = "data-toolbar-group-item"; const LINK_ATTR = "data-toolbar-link"; const BUTTON_ATTR = "data-toolbar-button"; -type ToolbarRootStateProps = ReadableBoxedValues<{ - orientation: Orientation; - loop: boolean; - id: string; -}>; +type ToolbarRootStateProps = WithRefProps< + ReadableBoxedValues<{ + orientation: Orientation; + loop: boolean; + }> +>; class ToolbarRootState { #id: ToolbarRootStateProps["id"]; + #ref: ToolbarRootStateProps["ref"]; orientation: ToolbarRootStateProps["orientation"]; #loop: ToolbarRootStateProps["loop"]; - #node = box(null); rovingFocusGroup: UseRovingFocusReturn; constructor(props: ToolbarRootStateProps) { this.#id = props.id; this.orientation = props.orientation; this.#loop = props.loop; - this.#node = useNodeById(this.#id); + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); + this.rovingFocusGroup = useRovingFocus({ orientation: this.orientation, loop: this.#loop, @@ -75,22 +83,28 @@ class ToolbarRootState { ); } -type ToolbarGroupBaseStateProps = ReadableBoxedValues<{ - id: string; - disabled: boolean; -}>; +type ToolbarGroupBaseStateProps = WithRefProps< + ReadableBoxedValues<{ + disabled: boolean; + }> +>; class ToolbarGroupBaseState { id: ToolbarGroupBaseStateProps["id"]; - node = box(null); + ref: ToolbarGroupBaseStateProps["ref"]; disabled: ToolbarGroupBaseStateProps["disabled"]; root: ToolbarRootState; constructor(props: ToolbarGroupBaseStateProps, root: ToolbarRootState) { this.id = props.id; - this.node = useNodeById(this.id); + this.ref = props.ref; this.disabled = props.disabled; this.root = root; + + useRefById({ + id: this.id, + ref: this.ref, + }); } props = $derived.by( @@ -183,18 +197,19 @@ type ToolbarGroupState = ToolbarGroupSingleState | ToolbarGroupMultipleState; // ITEM // -type ToolbarGroupItemStateProps = ReadableBoxedValues<{ - id: string; - value: string; - disabled: boolean; -}>; +type ToolbarGroupItemStateProps = WithRefProps< + ReadableBoxedValues<{ + value: string; + disabled: boolean; + }> +>; class ToolbarGroupItemState { #id: ToolbarGroupItemStateProps["id"]; + #ref: ToolbarGroupSingleState["ref"]; #group: ToolbarGroupState; #root: ToolbarRootState; #value: ToolbarGroupItemStateProps["value"]; - #node = box(null); #disabled: ToolbarGroupItemStateProps["disabled"]; #isDisabled = $derived.by(() => this.#disabled.value || this.#group.disabled.value); @@ -208,7 +223,12 @@ class ToolbarGroupItemState { this.#group = group; this.#root = root; this.#id = props.id; - this.#node = useNodeById(this.#id); + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); } toggleItem() { @@ -228,7 +248,7 @@ class ToolbarGroupItemState { return; } - this.#root.rovingFocusGroup.handleKeydown(this.#node.value, e); + this.#root.rovingFocusGroup.handleKeydown(this.#ref.value, e); }; #isPressed = $derived.by(() => this.#group.includesItem(this.#value.value)); @@ -241,7 +261,7 @@ class ToolbarGroupItemState { return this.#group.isMulti ? getAriaPressed(this.#isPressed) : undefined; }); - #tabIndex = $derived.by(() => this.#root.rovingFocusGroup.getTabIndex(this.#node.value).value); + #tabIndex = $derived.by(() => this.#root.rovingFocusGroup.getTabIndex(this.#ref.value)); props = $derived.by( () => @@ -265,35 +285,38 @@ class ToolbarGroupItemState { ); } -type ToolbarLinkStateProps = ReadableBoxedValues<{ - id: string; -}>; +type ToolbarLinkStateProps = WithRefProps; class ToolbarLinkState { - #id = undefined as unknown as ToolbarLinkStateProps["id"]; - #node = box(null); - #root = undefined as unknown as ToolbarRootState; + #id: ToolbarLinkStateProps["id"]; + #ref: ToolbarLinkStateProps["ref"]; + #root: ToolbarRootState; constructor(props: ToolbarLinkStateProps, root: ToolbarRootState) { this.#root = root; this.#id = props.id; - this.#node = useNodeById(this.#id); + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); } #onkeydown = (e: KeyboardEvent) => { - this.#root.rovingFocusGroup.handleKeydown(this.#node.value, e); + this.#root.rovingFocusGroup.handleKeydown(this.#ref.value, e); }; #role = $derived.by(() => { - if (!this.#node.value) return undefined; - const tagName = this.#node.value.tagName; + if (!this.#ref.value) return undefined; + const tagName = this.#ref.value.tagName; if (tagName !== "A") return "link" as const; return undefined; }); - #tabIndex = $derived(this.#root.rovingFocusGroup.getTabIndex(this.#node.value).value); + #tabIndex = $derived.by(() => this.#root.rovingFocusGroup.getTabIndex(this.#ref.value)); - props = $derived({ + props = $derived.by(() => ({ id: this.#id.value, [LINK_ATTR]: "", [ITEM_ATTR]: "", @@ -302,52 +325,61 @@ class ToolbarLinkState { "data-orientation": getDataOrientation(this.#root.orientation.value), // onkeydown: this.#onkeydown, - }); + })); } -type ToolbarButtonStateProps = ReadableBoxedValues<{ - id: string; - disabled: boolean; -}>; +type ToolbarButtonStateProps = WithRefProps< + ReadableBoxedValues<{ + disabled: boolean; + }> +>; class ToolbarButtonState { - #id = undefined as unknown as ToolbarButtonStateProps["id"]; - #root = undefined as unknown as ToolbarRootState; - #node = box(null); - #disabled = undefined as unknown as ToolbarButtonStateProps["disabled"]; + #id: ToolbarButtonStateProps["id"]; + #ref: ToolbarButtonStateProps["ref"]; + #root: ToolbarRootState; + #disabled: ToolbarButtonStateProps["disabled"]; constructor(props: ToolbarButtonStateProps, root: ToolbarRootState) { this.#id = props.id; - this.#root = root; - this.#node = useNodeById(this.#id); + this.#ref = props.ref; this.#disabled = props.disabled; + this.#root = root; + + useRefById({ + id: this.#id, + ref: this.#ref, + }); } #onkeydown = (e: KeyboardEvent) => { - this.#root.rovingFocusGroup.handleKeydown(this.#node.value, e); + this.#root.rovingFocusGroup.handleKeydown(this.#ref.value, e); }; - #tabIndex = $derived(this.#root.rovingFocusGroup.getTabIndex(this.#node.value).value); + #tabIndex = $derived.by(() => this.#root.rovingFocusGroup.getTabIndex(this.#ref.value)); #role = $derived.by(() => { - if (!this.#node.value) return undefined; - const tagName = this.#node.value.tagName; + if (!this.#ref.value) return undefined; + const tagName = this.#ref.value.tagName; if (tagName !== "BUTTON") return "button" as const; return undefined; }); - props = $derived({ - id: this.#id.value, - [ITEM_ATTR]: "", - [BUTTON_ATTR]: "", - role: this.#role, - tabindex: this.#tabIndex, - "data-disabled": getDataDisabled(this.#disabled.value), - "data-orientation": getDataOrientation(this.#root.orientation.value), - disabled: getDisabledAttr(this.#disabled.value), - // - onkeydown: this.#onkeydown, - }); + props = $derived.by( + () => + ({ + id: this.#id.value, + [ITEM_ATTR]: "", + [BUTTON_ATTR]: "", + role: this.#role, + tabindex: this.#tabIndex, + "data-disabled": getDataDisabled(this.#disabled.value), + "data-orientation": getDataOrientation(this.#root.orientation.value), + disabled: getDisabledAttr(this.#disabled.value), + // + onkeydown: this.#onkeydown, + }) as const + ); } // @@ -371,13 +403,14 @@ export function useToolbarRoot(props: ToolbarRootStateProps) { return setToolbarRootContext(new ToolbarRootState(props)); } -type InitToolbarGroupProps = { - type: "single" | "multiple"; - value: WritableBox | WritableBox; -} & ReadableBoxedValues<{ - id: string; - disabled: boolean; -}>; +type InitToolbarGroupProps = WithRefProps< + { + type: "single" | "multiple"; + value: WritableBox | WritableBox; + } & ReadableBoxedValues<{ + disabled: boolean; + }> +>; export function useToolbarGroup(props: InitToolbarGroupProps) { return setToolbarGroupContext(getToolbarRootContext().createGroup(props)); diff --git a/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-arrow.svelte b/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-arrow.svelte index 3ea4de35b..cdc59e124 100644 --- a/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-arrow.svelte +++ b/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-arrow.svelte @@ -5,4 +5,4 @@ let { ref = $bindable(), ...restProps }: ArrowProps = $props(); - + diff --git a/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-content.svelte b/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-content.svelte index 75589f168..af0e78a2c 100644 --- a/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-content.svelte +++ b/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-content.svelte @@ -11,7 +11,7 @@ children, child, id = useId(), - ref = $bindable(), + ref = $bindable(null), side = "top", sideOffset = 0, align = "center", @@ -28,6 +28,10 @@ const contentState = useTooltipContent({ id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const floatingProps = $derived({ diff --git a/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-trigger.svelte b/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-trigger.svelte index aa249fa4f..df8c8cd64 100644 --- a/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-trigger.svelte +++ b/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-trigger.svelte @@ -13,13 +13,17 @@ id = useId(), disabled = false, type = "button", - ref = $bindable(), + ref = $bindable(null), ...restProps }: TriggerProps = $props(); const triggerState = useTooltipTrigger({ id: box.with(() => id), disabled: box.with(() => disabled), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); const mergedProps = $derived(mergeProps(restProps, triggerState.props, { type })); @@ -29,7 +33,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} - {/if} diff --git a/packages/bits-ui/src/lib/bits/tooltip/tooltip.svelte.ts b/packages/bits-ui/src/lib/bits/tooltip/tooltip.svelte.ts index 6169b09d4..67c59079e 100644 --- a/packages/bits-ui/src/lib/bits/tooltip/tooltip.svelte.ts +++ b/packages/bits-ui/src/lib/bits/tooltip/tooltip.svelte.ts @@ -4,11 +4,12 @@ import { TOOLTIP_OPEN_EVENT } from "./utils.js"; import { watch } from "$lib/internal/box.svelte.js"; import type { ReadableBoxedValues, WritableBoxedValues } from "$lib/internal/box.svelte.js"; import { useTimeoutFn } from "$lib/internal/useTimeoutFn.svelte.js"; -import { useNodeById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; import { isElement } from "$lib/internal/is.js"; import { useGraceArea } from "$lib/internal/useGraceArea.svelte.js"; import { createContext } from "$lib/internal/createContext.js"; import { getDataDisabled } from "$lib/internal/attrs.js"; +import type { WithRefProps } from "$lib/internal/types.js"; const CONTENT_ATTR = "data-tooltip-content"; const TRIGGER_ATTR = "data-tooltip-trigger"; @@ -29,7 +30,7 @@ class TooltipProviderState { disabled: TooltipProviderStateProps["disabled"]; ignoreNonKeyboardFocus: TooltipProviderStateProps["ignoreNonKeyboardFocus"]; skipDelayDuration: TooltipProviderStateProps["skipDelayDuration"]; - isOpenDelayed = box(true); + isOpenDelayed = $state(true); isPointerInTransit = box(false); #timerFn: ReturnType; @@ -42,7 +43,7 @@ class TooltipProviderState { this.skipDelayDuration = props.skipDelayDuration; this.#timerFn = useTimeoutFn( () => { - this.isOpenDelayed.value = true; + this.isOpenDelayed = true; }, this.skipDelayDuration.value, { immediate: false } @@ -59,7 +60,7 @@ class TooltipProviderState { onOpen() { this.#clearTimer(); - this.isOpenDelayed.value = false; + this.isOpenDelayed = false; } onClose() { @@ -104,10 +105,8 @@ class TooltipRootState { ignoreNonKeyboardFocus = $derived.by( () => this._ignoreNonKeyboardFocus.value ?? this.provider.ignoreNonKeyboardFocus.value ); - contentNode = box(null); - contentId: ReadableBox = box.with(() => ""); - triggerId: ReadableBox = box.with(() => ""); - triggerNode = box(null); + contentNode = $state(null); + triggerNode = $state(null); #wasOpenDelayed = $state(false); #timerFn: ReturnType; stateAttr = $derived.by(() => { @@ -180,13 +179,15 @@ class TooltipRootState { } } -type TooltipTriggerStateProps = ReadableBoxedValues<{ - id: string; - disabled: boolean; -}>; +type TooltipTriggerStateProps = WithRefProps< + ReadableBoxedValues<{ + disabled: boolean; + }> +>; class TooltipTriggerState { #id: TooltipTriggerStateProps["id"]; + #ref: TooltipTriggerStateProps["ref"]; #root: TooltipRootState; #isPointerDown = box(false); #hasPointerMoveOpened = $state(false); @@ -195,10 +196,17 @@ class TooltipTriggerState { constructor(props: TooltipTriggerStateProps, root: TooltipRootState) { this.#id = props.id; - this.#root = root; + this.#ref = props.ref; this.#disabled = props.disabled; - this.#root.triggerNode = useNodeById(this.#id); - this.#root.triggerId = props.id; + this.#root = root; + + useRefById({ + id: this.#id, + ref: this.#ref, + onRefChange: (node) => { + this.#root.triggerNode = node; + }, + }); } handlePointerUp() { @@ -263,7 +271,7 @@ class TooltipTriggerState { props = $derived.by(() => ({ id: this.#id.value, - "aria-describedby": this.#root.open.value ? this.#root.contentNode.value?.id : undefined, + "aria-describedby": this.#root.open.value ? this.#root.contentNode?.id : undefined, "data-state": this.#root.stateAttr, "data-disabled": getDataDisabled(this.#isDisabled), [TRIGGER_ATTR]: "", @@ -278,27 +286,33 @@ class TooltipTriggerState { })); } -type TooltipContentStateProps = ReadableBoxedValues<{ - id: string; -}>; +type TooltipContentStateProps = WithRefProps; class TooltipContentState { root: TooltipRootState; #id: TooltipContentStateProps["id"]; + #ref: TooltipContentStateProps["ref"]; constructor(props: TooltipContentStateProps, root: TooltipRootState) { this.root = root; this.#id = props.id; - const contentNode = useNodeById(this.#id); - this.root.contentNode = contentNode; - this.root.contentId = this.#id; + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + onRefChange: (node) => { + this.root.contentNode = node; + }, + condition: () => this.root.open.value, + }); $effect(() => { if (!this.root.open.value) return; if (this.root.disableHoverableContent) return; const { isPointerInTransit, onPointerExit } = useGraceArea( - box.with(() => this.root.triggerId?.value), - box.with(() => this.root.contentId?.value) + box.with(() => this.root.triggerNode), + box.with(() => this.root.contentNode) ); this.root.provider.isPointerInTransit = isPointerInTransit; @@ -311,7 +325,7 @@ class TooltipContentState { useEventListener(window, "scroll", (e) => { const target = e.target; if (!isElement(target)) return; - if (target.contains(this.root.triggerNode.value)) { + if (target.contains(this.root.triggerNode)) { this.root.handleClose(); } }); diff --git a/packages/bits-ui/src/lib/bits/utilities/arrow/arrow.svelte b/packages/bits-ui/src/lib/bits/utilities/arrow/arrow.svelte index 6e1ba18d5..f4b1ec235 100644 --- a/packages/bits-ui/src/lib/bits/utilities/arrow/arrow.svelte +++ b/packages/bits-ui/src/lib/bits/utilities/arrow/arrow.svelte @@ -4,7 +4,6 @@ let { id = useId(), - ref = $bindable(), children, asChild, child, @@ -19,7 +18,7 @@ {#if asChild} {@render child?.({ props: mergedProps })} {:else} - + {#if children} {@render children?.()} {:else} diff --git a/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-arrow.svelte b/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-arrow.svelte index 9ad470f68..b7630098b 100644 --- a/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-arrow.svelte +++ b/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-arrow.svelte @@ -4,14 +4,18 @@ import { Arrow, type ArrowProps } from "$lib/bits/utilities/arrow/index.js"; import { mergeProps, useId } from "$lib/internal/index.js"; - let { id = useId(), ref = $bindable(), ...restProps }: ArrowProps = $props(); + let { id = useId(), ref = $bindable(null), ...restProps }: ArrowProps = $props(); const arrowState = useFloatingArrowState({ id: box.with(() => id), + ref: box.with( + () => ref, + (v) => (ref = v) + ), }); // explicit any here because the `asChild` and `child` are causing this to never out const mergedProps = $derived(mergeProps(restProps, arrowState.props)); - + diff --git a/packages/bits-ui/src/lib/bits/utilities/floating-layer/useFloatingLayer.svelte.ts b/packages/bits-ui/src/lib/bits/utilities/floating-layer/useFloatingLayer.svelte.ts index b01c9d372..d8d39710f 100644 --- a/packages/bits-ui/src/lib/bits/utilities/floating-layer/useFloatingLayer.svelte.ts +++ b/packages/bits-ui/src/lib/bits/utilities/floating-layer/useFloatingLayer.svelte.ts @@ -18,7 +18,8 @@ import { type ReadableBoxedValues, styleToString, useId, - useNodeById, + useRefById, + type WithRefProps, } from "$lib/internal/index.js"; import { useSize } from "$lib/internal/useSize.svelte.js"; import { useFloating } from "$lib/internal/floating-svelte/useFloating.svelte.js"; @@ -42,7 +43,7 @@ export type Align = (typeof ALIGN_OPTIONS)[number]; export type Boundary = Element | null; class FloatingRootState { - anchorNode = undefined as unknown as ReadableBox; + anchorNode = box(null); createAnchor(props: FloatingAnchorStateProps) { return new FloatingAnchorState(props, this); @@ -79,9 +80,9 @@ class FloatingContentState { root: FloatingRootState; // nodes - contentNode: Box; - wrapperNode: Box; - arrowNode = box(null); + contentRef = box(null); + wrapperRef = box(null); + arrowRef = box(null); // ids arrowId: Box = box(useId()); @@ -169,8 +170,8 @@ class FloatingContentState { ); }, }), - this.arrowNode.value && - arrow({ element: this.arrowNode.value, padding: this.arrowPadding.value }), + this.arrowRef.value && + arrow({ element: this.arrowRef.value, padding: this.arrowPadding.value }), transformOrigin({ arrowWidth: this.arrowWidth, arrowHeight: this.arrowHeight }), this.hideWhenDetached.value && hide({ strategy: "referenceHidden", ...this.detectOverflowOptions }), @@ -261,10 +262,19 @@ class FloatingContentState { this.style = props.style; this.root = root; this.enabled = props.enabled; - this.arrowSize = useSize(this.arrowNode); + this.arrowSize = useSize(this.arrowRef); this.wrapperId = props.wrapperId; - this.wrapperNode = useNodeById(this.wrapperId); - this.contentNode = useNodeById(this.id); + + useRefById({ + id: this.wrapperId, + ref: this.wrapperRef, + }); + + useRefById({ + id: this.id, + ref: this.contentRef, + }); + this.floating = useFloating({ strategy: () => this.strategy.value, placement: () => this.desiredPlacement, @@ -285,7 +295,7 @@ class FloatingContentState { }); $effect(() => { - const contentNode = this.contentNode.value; + const contentNode = this.contentRef.value; if (!contentNode) return; untrack(() => { @@ -294,7 +304,7 @@ class FloatingContentState { }); $effect(() => { - this.floating.floating.value = this.wrapperNode.value; + this.floating.floating.value = this.wrapperRef.value; }); } @@ -303,24 +313,35 @@ class FloatingContentState { } } -type FloatingArrowStateProps = ReadableBoxedValues<{ - id: string; -}>; +type FloatingArrowStateProps = WithRefProps; class FloatingArrowState { - #content = undefined as unknown as FloatingContentState; - #id = undefined as unknown as FloatingArrowStateProps["id"]; - - props = $derived({ - id: this.#id.value, - style: this.#content.arrowStyle, - }); + #id: FloatingArrowStateProps["id"]; + #ref: FloatingArrowStateProps["ref"]; + #content: FloatingContentState; constructor(props: FloatingArrowStateProps, content: FloatingContentState) { this.#content = content; this.#id = props.id; - this.#content.arrowNode = useNodeById(this.#id); + this.#ref = props.ref; + + useRefById({ + id: this.#id, + ref: this.#ref, + onRefChange: (node) => { + this.#content.arrowRef.value = node; + }, + condition: () => this.#content.enabled.value, + }); } + + props = $derived.by( + () => + ({ + id: this.#id.value, + style: this.#content.arrowStyle, + }) as const + ); } type FloatingAnchorStateProps = ReadableBoxedValues<{ @@ -329,11 +350,19 @@ type FloatingAnchorStateProps = ReadableBoxedValues<{ }>; class FloatingAnchorState { + ref = box(null); + constructor(props: FloatingAnchorStateProps, root: FloatingRootState) { if (props.virtualEl && props.virtualEl.value) { root.anchorNode = box.from(props.virtualEl.value); } else { - root.anchorNode = useNodeById(props.id); + useRefById({ + id: props.id, + ref: this.ref, + onRefChange: (node) => { + root.anchorNode.value = node; + }, + }); } } } diff --git a/packages/bits-ui/src/lib/bits/utilities/focus-scope/useFocusScope.svelte.ts b/packages/bits-ui/src/lib/bits/utilities/focus-scope/useFocusScope.svelte.ts index aaf305288..57305e95c 100644 --- a/packages/bits-ui/src/lib/bits/utilities/focus-scope/useFocusScope.svelte.ts +++ b/packages/bits-ui/src/lib/bits/utilities/focus-scope/useFocusScope.svelte.ts @@ -15,11 +15,12 @@ import { } from "./utils.js"; import type { ReadableBoxedValues } from "$lib/internal/box.svelte.js"; import { type EventCallback, addEventListener } from "$lib/internal/events.js"; -import { useNodeById } from "$lib/internal/useNodeById.svelte.js"; +import { useRefById } from "$lib/internal/useRefById.svelte.js"; import { isHTMLElement } from "$lib/internal/is.js"; import { executeCallbacks } from "$lib/internal/callbacks.js"; import { kbd } from "$lib/internal/kbd.js"; import { afterTick } from "$lib/internal/afterTick.js"; +import { box } from "svelte-toolbelt"; type UseFocusScopeProps = ReadableBoxedValues<{ /** @@ -68,11 +69,15 @@ export function useFocusScope({ }: UseFocusScopeProps) { const focusScopeStack = createFocusScopeStack(); const focusScope = createFocusScopeAPI(); - const node = useNodeById(id); + const ref = box(null); + useRefById({ + id, + ref, + }); let lastFocusedElement = $state(null); $effect(() => { - const container = node.value; + const container = ref.value; if (!container) return; if (!trapped.value) return; @@ -138,7 +143,7 @@ export function useFocusScope({ }); $effect(() => { - let container = untrack(() => node.value); + let container = untrack(() => ref.value); const previouslyFocusedElement = document.activeElement as HTMLElement | null; untrack(() => { if (!container) { @@ -203,7 +208,7 @@ export function useFocusScope({ const focusedElement = document.activeElement as HTMLElement | null; if (!(isTabKey && focusedElement)) return; - const container = node.value; + const container = ref.value; if (!container) return; const [first, last] = getTabbableEdges(container); diff --git a/packages/bits-ui/src/lib/bits/utilities/text-selection-layer/useTextSelectionLayer.svelte.ts b/packages/bits-ui/src/lib/bits/utilities/text-selection-layer/useTextSelectionLayer.svelte.ts index fcce04011..979844d4f 100644 --- a/packages/bits-ui/src/lib/bits/utilities/text-selection-layer/useTextSelectionLayer.svelte.ts +++ b/packages/bits-ui/src/lib/bits/utilities/text-selection-layer/useTextSelectionLayer.svelte.ts @@ -1,5 +1,5 @@ import { untrack } from "svelte"; -import type { ReadableBox, WritableBox } from "svelte-toolbelt"; +import { box, type ReadableBox, type WritableBox } from "svelte-toolbelt"; import type { TextSelectionLayerImplProps, TextSelectionLayerProps } from "./types.js"; import { type EventCallback, @@ -10,7 +10,7 @@ import { isHTMLElement, isOrContainsTarget, noop, - useNodeById, + useRefById, } from "$lib/internal/index.js"; type StateProps = ReadableBoxedValues>>; @@ -18,17 +18,23 @@ type StateProps = ReadableBoxedValues>(); export class TextSelectionLayerState { + #id: StateProps["id"]; #onPointerDownProp: ReadableBox>; #onPointerUpProp: ReadableBox>; #enabled: ReadableBox; #unsubSelectionLock = noop; - #node: WritableBox; + #ref = box(null); constructor(props: StateProps) { - this.#node = useNodeById(props.id); + this.#id = props.id; this.#enabled = props.preventOverflowTextSelection; this.#onPointerDownProp = props.onPointerDown; this.#onPointerUpProp = props.onPointerUp; + useRefById({ + id: this.#id, + ref: this.#ref, + condition: () => this.#enabled.value, + }); let unsubEvents = noop; @@ -60,7 +66,7 @@ export class TextSelectionLayerState { } #pointerdown = (e: PointerEvent) => { - const node = this.#node.value; + const node = this.#ref.value; const target = e.target; if (!isHTMLElement(node) || !isHTMLElement(target) || !this.#enabled.value) return; /** diff --git a/packages/bits-ui/src/lib/internal/useFormControl.svelte.ts b/packages/bits-ui/src/lib/internal/useFormControl.svelte.ts index 99faa5587..99f8d0847 100644 --- a/packages/bits-ui/src/lib/internal/useFormControl.svelte.ts +++ b/packages/bits-ui/src/lib/internal/useFormControl.svelte.ts @@ -1,10 +1,10 @@ import type { Getter } from "svelte-toolbelt"; import { isBrowser } from "./is.js"; -export function useFormControl(id: Getter) { +export function useFormControl(getNode: Getter) { const isInForm = $derived.by(() => { if (!isBrowser) return false; - const node = document.getElementById(id()); + const node = getNode(); if (!node) return false; return Boolean(node.closest("form")); }); diff --git a/packages/bits-ui/src/lib/internal/useGraceArea.svelte.ts b/packages/bits-ui/src/lib/internal/useGraceArea.svelte.ts index 9a9a69fb7..26ded0bca 100644 --- a/packages/bits-ui/src/lib/internal/useGraceArea.svelte.ts +++ b/packages/bits-ui/src/lib/internal/useGraceArea.svelte.ts @@ -6,12 +6,12 @@ import { executeCallbacks } from "./callbacks.js"; import { addEventListener } from "./events.js"; import type { Side } from "$lib/bits/utilities/floating-layer/useFloatingLayer.svelte.js"; -export function useGraceArea(triggerId: ReadableBox, contentId: ReadableBox) { +export function useGraceArea( + triggerNode: ReadableBox, + contentNode: ReadableBox +) { const isPointerInTransit = boxAutoReset(false, 300); - let contentNode = $state((() => document.getElementById(contentId.value))()); - let triggerNode = $state((() => document.getElementById(triggerId.value))()); - let pointerGraceArea = $state(null); const pointerExit = createEventHook(); @@ -33,19 +33,18 @@ export function useGraceArea(triggerId: ReadableBox, contentId: Readable } $effect(() => { - contentNode = document.getElementById(contentId.value); - if (!triggerNode || !contentNode) return; + if (!triggerNode.value || !contentNode.value) return; const handleTriggerLeave = (e: PointerEvent) => { - handleCreateGraceArea(e, contentNode!); + handleCreateGraceArea(e, contentNode.value!); }; const handleContentLeave = (e: PointerEvent) => { - handleCreateGraceArea(e, triggerNode!); + handleCreateGraceArea(e, triggerNode.value!); }; return executeCallbacks( - addEventListener(triggerNode, "pointerleave", handleTriggerLeave), - addEventListener(contentNode, "pointerleave", handleContentLeave) + addEventListener(triggerNode.value, "pointerleave", handleTriggerLeave), + addEventListener(contentNode.value, "pointerleave", handleContentLeave) ); }); @@ -57,7 +56,8 @@ export function useGraceArea(triggerId: ReadableBox, contentId: Readable const target = e.target; if (!isElement(target)) return; const pointerPosition = { x: e.clientX, y: e.clientY }; - const hasEnteredTarget = triggerNode?.contains(target) || contentNode?.contains(target); + const hasEnteredTarget = + triggerNode.value?.contains(target) || contentNode.value?.contains(target); const isPointerOutsideGraceArea = !isPointInPolygon(pointerPosition, pointerGraceArea); if (hasEnteredTarget) { diff --git a/packages/bits-ui/src/lib/internal/useNodeById.svelte.ts b/packages/bits-ui/src/lib/internal/useRefById.svelte.ts similarity index 53% rename from packages/bits-ui/src/lib/internal/useNodeById.svelte.ts rename to packages/bits-ui/src/lib/internal/useRefById.svelte.ts index 45b574b69..1e92ab26d 100644 --- a/packages/bits-ui/src/lib/internal/useNodeById.svelte.ts +++ b/packages/bits-ui/src/lib/internal/useRefById.svelte.ts @@ -1,43 +1,8 @@ -import { type Getter, type ReadableBox, type WritableBox, box } from "svelte-toolbelt"; -import { afterTick } from "./afterTick.js"; +import { type Getter, type WritableBox } from "svelte-toolbelt"; import type { Box } from "./box.svelte.js"; import { untrack } from "svelte"; import { noop } from "./callbacks.js"; -/** - * Finds the node with that ID and sets it to the boxed node. - * Reactive using `$effect.pre` to ensure when the ID changes, an update is triggered and - * new node is found. - * - * @param id The boxed ID of the node to find. - */ -export function useNodeById( - id: ReadableBox | WritableBox, - mounted?: ReadableBox -) { - const node = box(null); - - if (mounted) { - $effect(() => { - // eslint-disable-next-line no-unused-expressions - mounted.value; - // eslint-disable-next-line no-unused-expressions - id.value; - afterTick(() => { - node.value = document.getElementById(id.value); - }); - }); - } else { - $effect(() => { - // eslint-disable-next-line no-unused-expressions - id.value; - node.value = document.getElementById(id.value); - }); - } - - return node; -} - type UseRefByIdProps = { /** * The ID of the node to find. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f2a12b7a3..8278438e7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: version: 2.27.5 '@huntabyte/eslint-config': specifier: ^0.3.1 - version: 0.3.1(@vue/compiler-sfc@3.4.27)(eslint-plugin-svelte@2.39.0(eslint@9.3.0)(svelte@5.0.0-next.143))(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.143))(svelte@5.0.0-next.143)(typescript@5.4.5)(vitest@1.6.0) + version: 0.3.1(@vue/compiler-sfc@3.4.27)(eslint-plugin-svelte@2.39.0(eslint@9.3.0)(svelte@5.0.0-next.157))(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.157))(svelte@5.0.0-next.157)(typescript@5.4.5)(vitest@1.6.0) '@huntabyte/eslint-plugin': specifier: ^0.1.0 version: 0.1.0(eslint@9.3.0) @@ -25,22 +25,22 @@ importers: version: 9.3.0 eslint-plugin-svelte: specifier: ^2.37.0 - version: 2.39.0(eslint@9.3.0)(svelte@5.0.0-next.143) + version: 2.39.0(eslint@9.3.0)(svelte@5.0.0-next.157) prettier: specifier: ^3.2.5 version: 3.2.5 prettier-plugin-svelte: specifier: ^3.2.2 - version: 3.2.3(prettier@3.2.5)(svelte@5.0.0-next.143) + version: 3.2.3(prettier@3.2.5)(svelte@5.0.0-next.157) prettier-plugin-tailwindcss: specifier: 0.5.13 - version: 0.5.13(prettier-plugin-svelte@3.2.3(prettier@3.2.5)(svelte@5.0.0-next.143))(prettier@3.2.5) + version: 0.5.13(prettier-plugin-svelte@3.2.3(prettier@3.2.5)(svelte@5.0.0-next.157))(prettier@3.2.5) svelte: - specifier: 5.0.0-next.143 - version: 5.0.0-next.143 + specifier: ^5.0.0-next.157 + version: 5.0.0-next.157 svelte-eslint-parser: specifier: ^0.34.1 - version: 0.34.1(svelte@5.0.0-next.143) + version: 0.34.1(svelte@5.0.0-next.157) wrangler: specifier: ^3.44.0 version: 3.57.2(@cloudflare/workers-types@4.20240524.0) @@ -58,7 +58,7 @@ importers: version: 3.5.4 '@melt-ui/svelte': specifier: 0.76.2 - version: 0.76.2(svelte@5.0.0-next.143) + version: 0.76.2(svelte@5.0.0-next.157) clsx: specifier: ^2.1.0 version: 2.1.1 @@ -70,7 +70,7 @@ importers: version: 5.0.7 runed: specifier: ^0.12.1 - version: 0.12.1(svelte@5.0.0-next.143) + version: 0.12.1(svelte@5.0.0-next.157) scule: specifier: ^1.3.0 version: 1.3.0 @@ -82,20 +82,20 @@ importers: version: 1.0.6 svelte-toolbelt: specifier: ^0.0.2 - version: 0.0.2(svelte@5.0.0-next.143) + version: 0.0.2(svelte@5.0.0-next.157) devDependencies: '@melt-ui/pp': specifier: ^0.3.0 - version: 0.3.2(@melt-ui/svelte@0.76.2(svelte@5.0.0-next.143))(svelte@5.0.0-next.143) + version: 0.3.2(@melt-ui/svelte@0.76.2(svelte@5.0.0-next.157))(svelte@5.0.0-next.157) '@sveltejs/kit': specifier: ^2.5.0 - version: 2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)) + version: 2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)) '@sveltejs/package': specifier: ^2.2.7 - version: 2.3.1(svelte@5.0.0-next.143)(typescript@5.4.5) + version: 2.3.1(svelte@5.0.0-next.157)(typescript@5.4.5) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.0 - version: 3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)) + version: 3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)) '@testing-library/dom': specifier: ^10.0.0 version: 10.1.0 @@ -104,7 +104,7 @@ importers: version: 6.4.5(@types/jest@29.5.12)(vitest@1.6.0(@types/node@20.12.13)(@vitest/ui@1.6.0)(jsdom@24.1.0)) '@testing-library/svelte': specifier: ^5.0.1 - version: 5.1.0(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13))(vitest@1.6.0(@types/node@20.12.13)(@vitest/ui@1.6.0)(jsdom@24.1.0)) + version: 5.1.0(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13))(vitest@1.6.0(@types/node@20.12.13)(@vitest/ui@1.6.0)(jsdom@24.1.0)) '@testing-library/user-event': specifier: ^14.5.2 version: 14.5.2(@testing-library/dom@10.1.0) @@ -139,11 +139,11 @@ importers: specifier: ^1.5.1 version: 1.5.1 svelte: - specifier: 5.0.0-next.143 - version: 5.0.0-next.143 + specifier: 5.0.0-next.157 + version: 5.0.0-next.157 svelte-check: specifier: ^3.6.9 - version: 3.8.0(postcss-load-config@5.1.0(jiti@1.21.0)(postcss@8.4.38))(postcss@8.4.38)(svelte@5.0.0-next.143) + version: 3.8.0(postcss-load-config@5.1.0(postcss@8.4.38))(postcss@8.4.38)(svelte@5.0.0-next.157) tslib: specifier: ^2.6.2 version: 2.6.2 @@ -164,26 +164,26 @@ importers: version: 3.5.4 '@melt-ui/svelte': specifier: 0.76.2 - version: 0.76.2(svelte@5.0.0-next.143) + version: 0.76.2(svelte@5.0.0-next.157) bits-ui: specifier: workspace:* version: link:../../packages/bits-ui devDependencies: '@melt-ui/pp': specifier: ^0.3.0 - version: 0.3.2(@melt-ui/svelte@0.76.2(svelte@5.0.0-next.143))(svelte@5.0.0-next.143) + version: 0.3.2(@melt-ui/svelte@0.76.2(svelte@5.0.0-next.157))(svelte@5.0.0-next.157) '@prettier/sync': specifier: 0.3.0 version: 0.3.0(prettier@3.2.5) '@sveltejs/adapter-cloudflare': specifier: ^4.2.0 - version: 4.4.0(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)))(wrangler@3.57.2(@cloudflare/workers-types@4.20240524.0)) + version: 4.4.0(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)))(wrangler@3.57.2(@cloudflare/workers-types@4.20240524.0)) '@sveltejs/kit': specifier: ^2.5.0 - version: 2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)) + version: 2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.0 - version: 3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)) + version: 3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)) '@tailwindcss/typography': specifier: ^0.5.10 version: 0.5.13(tailwindcss@3.4.3) @@ -216,13 +216,13 @@ importers: version: 3.0.1 mdsx: specifier: ^0.0.5 - version: 0.0.5(svelte@5.0.0-next.143) + version: 0.0.5(svelte@5.0.0-next.157) mode-watcher: specifier: ^0.2.0 - version: 0.2.2(svelte@5.0.0-next.143) + version: 0.2.2(svelte@5.0.0-next.157) phosphor-svelte: specifier: ^1.4.2 - version: 1.4.2(svelte@5.0.0-next.143) + version: 1.4.2(svelte@5.0.0-next.157) postcss: specifier: ^8.4.33 version: 8.4.38 @@ -242,11 +242,11 @@ importers: specifier: ^1.1.1 version: 1.6.1 svelte: - specifier: 5.0.0-next.143 - version: 5.0.0-next.143 + specifier: 5.0.0-next.157 + version: 5.0.0-next.157 svelte-check: specifier: ^3.6.9 - version: 3.8.0(postcss-load-config@5.1.0(jiti@1.21.0)(postcss@8.4.38))(postcss@8.4.38)(svelte@5.0.0-next.143) + version: 3.8.0(postcss-load-config@5.1.0(postcss@8.4.38))(postcss@8.4.38)(svelte@5.0.0-next.157) tailwind-merge: specifier: ^2.2.1 version: 2.3.0 @@ -4764,8 +4764,8 @@ packages: svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0 typescript: ^4.9.4 || ^5.0.0 - svelte@5.0.0-next.143: - resolution: {integrity: sha512-hRm52FjYUfd24eUlkBS41JSmqHOx6wt0cV+wMzgwqhhxIpJoz96eiMcnvcLqXx+gTxM1m0Pt/+7xP3vlm2QvPg==} + svelte@5.0.0-next.157: + resolution: {integrity: sha512-VSe9WEWUba/i4WXRl7/0qvoQvH15P91aHH+sq5prKaCpN0Up8dR8Boy9g8679v8yBSNREWWhyUiDMOOaRvV6ZA==} engines: {node: '>=18'} symbol-tree@3.2.4: @@ -5347,7 +5347,7 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@antfu/eslint-config@2.19.1(@vue/compiler-sfc@3.4.27)(eslint-plugin-svelte@2.39.0(eslint@9.3.0)(svelte@5.0.0-next.143))(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.143))(svelte@5.0.0-next.143)(typescript@5.4.5)(vitest@1.6.0)': + '@antfu/eslint-config@2.19.1(@vue/compiler-sfc@3.4.27)(eslint-plugin-svelte@2.39.0(eslint@9.3.0)(svelte@5.0.0-next.157))(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.157))(svelte@5.0.0-next.157)(typescript@5.4.5)(vitest@1.6.0)': dependencies: '@antfu/install-pkg': 0.3.3 '@clack/prompts': 0.7.0 @@ -5367,7 +5367,7 @@ snapshots: eslint-plugin-markdown: 5.0.0(eslint@9.3.0) eslint-plugin-n: 17.7.0(eslint@9.3.0) eslint-plugin-no-only-tests: 3.1.0 - eslint-plugin-perfectionist: 2.10.0(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.143))(svelte@5.0.0-next.143)(typescript@5.4.5)(vue-eslint-parser@9.4.2(eslint@9.3.0)) + eslint-plugin-perfectionist: 2.10.0(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.157))(svelte@5.0.0-next.157)(typescript@5.4.5)(vue-eslint-parser@9.4.2(eslint@9.3.0)) eslint-plugin-regexp: 2.6.0(eslint@9.3.0) eslint-plugin-toml: 0.11.0(eslint@9.3.0) eslint-plugin-unicorn: 53.0.0(eslint@9.3.0) @@ -5386,8 +5386,8 @@ snapshots: yaml-eslint-parser: 1.2.3 yargs: 17.7.2 optionalDependencies: - eslint-plugin-svelte: 2.39.0(eslint@9.3.0)(svelte@5.0.0-next.143) - svelte-eslint-parser: 0.34.1(svelte@5.0.0-next.143) + eslint-plugin-svelte: 2.39.0(eslint@9.3.0)(svelte@5.0.0-next.157) + svelte-eslint-parser: 0.34.1(svelte@5.0.0-next.157) transitivePeerDependencies: - '@vue/compiler-sfc' - supports-color @@ -6052,9 +6052,9 @@ snapshots: '@humanwhocodes/retry@0.3.0': {} - '@huntabyte/eslint-config@0.3.1(@vue/compiler-sfc@3.4.27)(eslint-plugin-svelte@2.39.0(eslint@9.3.0)(svelte@5.0.0-next.143))(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.143))(svelte@5.0.0-next.143)(typescript@5.4.5)(vitest@1.6.0)': + '@huntabyte/eslint-config@0.3.1(@vue/compiler-sfc@3.4.27)(eslint-plugin-svelte@2.39.0(eslint@9.3.0)(svelte@5.0.0-next.157))(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.157))(svelte@5.0.0-next.157)(typescript@5.4.5)(vitest@1.6.0)': dependencies: - '@antfu/eslint-config': 2.19.1(@vue/compiler-sfc@3.4.27)(eslint-plugin-svelte@2.39.0(eslint@9.3.0)(svelte@5.0.0-next.143))(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.143))(svelte@5.0.0-next.143)(typescript@5.4.5)(vitest@1.6.0) + '@antfu/eslint-config': 2.19.1(@vue/compiler-sfc@3.4.27)(eslint-plugin-svelte@2.39.0(eslint@9.3.0)(svelte@5.0.0-next.157))(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.157))(svelte@5.0.0-next.157)(typescript@5.4.5)(vitest@1.6.0) '@antfu/install-pkg': 0.3.3 '@clack/prompts': 0.7.0 '@huntabyte/eslint-plugin': 0.1.0(eslint@9.3.0) @@ -6063,10 +6063,10 @@ snapshots: chalk: 5.3.0 eslint: 9.3.0 eslint-flat-config-utils: 0.2.5 - eslint-plugin-svelte: 2.39.0(eslint@9.3.0)(svelte@5.0.0-next.143) + eslint-plugin-svelte: 2.39.0(eslint@9.3.0)(svelte@5.0.0-next.157) local-pkg: 0.5.0 parse-gitignore: 2.0.0 - svelte-eslint-parser: 0.34.1(svelte@5.0.0-next.143) + svelte-eslint-parser: 0.34.1(svelte@5.0.0-next.157) yargs: 17.7.2 transitivePeerDependencies: - '@eslint-react/eslint-plugin' @@ -6203,14 +6203,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@melt-ui/pp@0.3.2(@melt-ui/svelte@0.76.2(svelte@5.0.0-next.143))(svelte@5.0.0-next.143)': + '@melt-ui/pp@0.3.2(@melt-ui/svelte@0.76.2(svelte@5.0.0-next.157))(svelte@5.0.0-next.157)': dependencies: - '@melt-ui/svelte': 0.76.2(svelte@5.0.0-next.143) + '@melt-ui/svelte': 0.76.2(svelte@5.0.0-next.157) estree-walker: 3.0.3 magic-string: 0.30.10 - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 - '@melt-ui/svelte@0.76.2(svelte@5.0.0-next.143)': + '@melt-ui/svelte@0.76.2(svelte@5.0.0-next.157)': dependencies: '@floating-ui/core': 1.6.2 '@floating-ui/dom': 1.6.5 @@ -6218,7 +6218,7 @@ snapshots: dequal: 2.0.3 focus-trap: 7.5.4 nanoid: 5.0.7 - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 '@nodelib/fs.scandir@2.1.5': dependencies: @@ -6480,17 +6480,17 @@ snapshots: - supports-color - typescript - '@sveltejs/adapter-cloudflare@4.4.0(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)))(wrangler@3.57.2(@cloudflare/workers-types@4.20240524.0))': + '@sveltejs/adapter-cloudflare@4.4.0(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)))(wrangler@3.57.2(@cloudflare/workers-types@4.20240524.0))': dependencies: '@cloudflare/workers-types': 4.20240524.0 - '@sveltejs/kit': 2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)) + '@sveltejs/kit': 2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)) esbuild: 0.20.2 worktop: 0.8.0-next.18 wrangler: 3.57.2(@cloudflare/workers-types@4.20240524.0) - '@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13))': + '@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)) + '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -6502,39 +6502,39 @@ snapshots: sade: 1.8.1 set-cookie-parser: 2.6.0 sirv: 2.0.4 - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 tiny-glob: 0.2.9 vite: 5.2.12(@types/node@20.12.13) - '@sveltejs/package@2.3.1(svelte@5.0.0-next.143)(typescript@5.4.5)': + '@sveltejs/package@2.3.1(svelte@5.0.0-next.157)(typescript@5.4.5)': dependencies: chokidar: 3.6.0 kleur: 4.1.5 sade: 1.8.1 semver: 7.6.2 - svelte: 5.0.0-next.143 - svelte2tsx: 0.7.9(svelte@5.0.0-next.143)(typescript@5.4.5) + svelte: 5.0.0-next.157 + svelte2tsx: 0.7.9(svelte@5.0.0-next.157)(typescript@5.4.5) transitivePeerDependencies: - typescript - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)) + '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)) debug: 4.3.4 - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 vite: 5.2.12(@types/node@20.12.13) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13))': + '@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)))(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13)) debug: 4.3.4 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.10 - svelte: 5.0.0-next.143 - svelte-hmr: 0.16.0(svelte@5.0.0-next.143) + svelte: 5.0.0-next.157 + svelte-hmr: 0.16.0(svelte@5.0.0-next.157) vite: 5.2.12(@types/node@20.12.13) vitefu: 0.2.5(vite@5.2.12(@types/node@20.12.13)) transitivePeerDependencies: @@ -6595,10 +6595,10 @@ snapshots: '@types/jest': 29.5.12 vitest: 1.6.0(@types/node@20.12.13)(@vitest/ui@1.6.0)(jsdom@24.1.0) - '@testing-library/svelte@5.1.0(svelte@5.0.0-next.143)(vite@5.2.12(@types/node@20.12.13))(vitest@1.6.0(@types/node@20.12.13)(@vitest/ui@1.6.0)(jsdom@24.1.0))': + '@testing-library/svelte@5.1.0(svelte@5.0.0-next.157)(vite@5.2.12(@types/node@20.12.13))(vitest@1.6.0(@types/node@20.12.13)(@vitest/ui@1.6.0)(jsdom@24.1.0))': dependencies: '@testing-library/dom': 9.3.4 - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 optionalDependencies: vite: 5.2.12(@types/node@20.12.13) vitest: 1.6.0(@types/node@20.12.13)(@vitest/ui@1.6.0)(jsdom@24.1.0) @@ -7722,15 +7722,15 @@ snapshots: eslint-plugin-no-only-tests@3.1.0: {} - eslint-plugin-perfectionist@2.10.0(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.143))(svelte@5.0.0-next.143)(typescript@5.4.5)(vue-eslint-parser@9.4.2(eslint@9.3.0)): + eslint-plugin-perfectionist@2.10.0(eslint@9.3.0)(svelte-eslint-parser@0.34.1(svelte@5.0.0-next.157))(svelte@5.0.0-next.157)(typescript@5.4.5)(vue-eslint-parser@9.4.2(eslint@9.3.0)): dependencies: '@typescript-eslint/utils': 7.11.0(eslint@9.3.0)(typescript@5.4.5) eslint: 9.3.0 minimatch: 9.0.4 natural-compare-lite: 1.4.0 optionalDependencies: - svelte: 5.0.0-next.143 - svelte-eslint-parser: 0.34.1(svelte@5.0.0-next.143) + svelte: 5.0.0-next.157 + svelte-eslint-parser: 0.34.1(svelte@5.0.0-next.157) vue-eslint-parser: 9.4.2(eslint@9.3.0) transitivePeerDependencies: - supports-color @@ -7747,7 +7747,7 @@ snapshots: regexp-ast-analysis: 0.7.1 scslre: 0.3.0 - eslint-plugin-svelte@2.39.0(eslint@9.3.0)(svelte@5.0.0-next.143): + eslint-plugin-svelte@2.39.0(eslint@9.3.0)(svelte@5.0.0-next.157): dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.3.0) '@jridgewell/sourcemap-codec': 1.4.15 @@ -7761,9 +7761,9 @@ snapshots: postcss-safe-parser: 6.0.0(postcss@8.4.38) postcss-selector-parser: 6.1.0 semver: 7.6.2 - svelte-eslint-parser: 0.36.0(svelte@5.0.0-next.143) + svelte-eslint-parser: 0.36.0(svelte@5.0.0-next.157) optionalDependencies: - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 transitivePeerDependencies: - supports-color - ts-node @@ -9110,7 +9110,7 @@ snapshots: dependencies: '@types/mdast': 4.0.4 - mdsx@0.0.5(svelte@5.0.0-next.143): + mdsx@0.0.5(svelte@5.0.0-next.157): dependencies: esrap: 1.2.2 hast-util-to-html: 9.0.1 @@ -9119,7 +9119,7 @@ snapshots: rehype-stringify: 10.0.0 remark-parse: 11.0.0 remark-rehype: 11.1.0 - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 unified: 11.0.4 unist-util-visit: 5.0.0 vfile: 6.0.1 @@ -9647,9 +9647,9 @@ snapshots: pkg-types: 1.1.1 ufo: 1.5.3 - mode-watcher@0.2.2(svelte@5.0.0-next.143): + mode-watcher@0.2.2(svelte@5.0.0-next.157): dependencies: - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 mri@1.2.0: {} @@ -9886,9 +9886,9 @@ snapshots: estree-walker: 3.0.3 is-reference: 3.0.2 - phosphor-svelte@1.4.2(svelte@5.0.0-next.143): + phosphor-svelte@1.4.2(svelte@5.0.0-next.157): dependencies: - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 picocolors@1.0.1: {} @@ -9990,16 +9990,16 @@ snapshots: prelude-ls@1.2.1: {} - prettier-plugin-svelte@3.2.3(prettier@3.2.5)(svelte@5.0.0-next.143): + prettier-plugin-svelte@3.2.3(prettier@3.2.5)(svelte@5.0.0-next.157): dependencies: prettier: 3.2.5 - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 - prettier-plugin-tailwindcss@0.5.13(prettier-plugin-svelte@3.2.3(prettier@3.2.5)(svelte@5.0.0-next.143))(prettier@3.2.5): + prettier-plugin-tailwindcss@0.5.13(prettier-plugin-svelte@3.2.3(prettier@3.2.5)(svelte@5.0.0-next.157))(prettier@3.2.5): dependencies: prettier: 3.2.5 optionalDependencies: - prettier-plugin-svelte: 3.2.3(prettier@3.2.5)(svelte@5.0.0-next.143) + prettier-plugin-svelte: 3.2.3(prettier@3.2.5)(svelte@5.0.0-next.157) prettier@2.8.8: {} @@ -10297,11 +10297,11 @@ snapshots: dependencies: queue-microtask: 1.2.3 - runed@0.12.1(svelte@5.0.0-next.143): + runed@0.12.1(svelte@5.0.0-next.157): dependencies: esm-env: 1.0.0 nanoid: 5.0.7 - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 rxjs@7.8.1: dependencies: @@ -10598,7 +10598,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.0(postcss-load-config@5.1.0(jiti@1.21.0)(postcss@8.4.38))(postcss@8.4.38)(svelte@5.0.0-next.143): + svelte-check@3.8.0(postcss-load-config@5.1.0(postcss@8.4.38))(postcss@8.4.38)(svelte@5.0.0-next.157): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 @@ -10606,8 +10606,8 @@ snapshots: import-fresh: 3.3.0 picocolors: 1.0.1 sade: 1.8.1 - svelte: 5.0.0-next.143 - svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.0)(postcss@8.4.38))(postcss@8.4.38)(svelte@5.0.0-next.143)(typescript@5.4.5) + svelte: 5.0.0-next.157 + svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(postcss@8.4.38))(postcss@8.4.38)(svelte@5.0.0-next.157)(typescript@5.4.5) typescript: 5.4.5 transitivePeerDependencies: - '@babel/core' @@ -10620,7 +10620,7 @@ snapshots: - stylus - sugarss - svelte-eslint-parser@0.34.1(svelte@5.0.0-next.143): + svelte-eslint-parser@0.34.1(svelte@5.0.0-next.157): dependencies: eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 @@ -10628,9 +10628,9 @@ snapshots: postcss: 8.4.38 postcss-scss: 4.0.9(postcss@8.4.38) optionalDependencies: - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 - svelte-eslint-parser@0.36.0(svelte@5.0.0-next.143): + svelte-eslint-parser@0.36.0(svelte@5.0.0-next.157): dependencies: eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 @@ -10638,37 +10638,37 @@ snapshots: postcss: 8.4.38 postcss-scss: 4.0.9(postcss@8.4.38) optionalDependencies: - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 - svelte-hmr@0.16.0(svelte@5.0.0-next.143): + svelte-hmr@0.16.0(svelte@5.0.0-next.157): dependencies: - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 - svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.0)(postcss@8.4.38))(postcss@8.4.38)(svelte@5.0.0-next.143)(typescript@5.4.5): + svelte-preprocess@5.1.4(postcss-load-config@5.1.0(postcss@8.4.38))(postcss@8.4.38)(svelte@5.0.0-next.157)(typescript@5.4.5): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 magic-string: 0.30.10 sorcery: 0.11.0 strip-indent: 3.0.0 - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 optionalDependencies: postcss: 8.4.38 postcss-load-config: 5.1.0(jiti@1.21.0)(postcss@8.4.38) typescript: 5.4.5 - svelte-toolbelt@0.0.2(svelte@5.0.0-next.143): + svelte-toolbelt@0.0.2(svelte@5.0.0-next.157): dependencies: - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 - svelte2tsx@0.7.9(svelte@5.0.0-next.143)(typescript@5.4.5): + svelte2tsx@0.7.9(svelte@5.0.0-next.157)(typescript@5.4.5): dependencies: dedent-js: 1.0.1 pascal-case: 3.1.2 - svelte: 5.0.0-next.143 + svelte: 5.0.0-next.157 typescript: 5.4.5 - svelte@5.0.0-next.143: + svelte@5.0.0-next.157: dependencies: '@ampproject/remapping': 2.3.0 '@jridgewell/sourcemap-codec': 1.4.15 diff --git a/sites/docs/package.json b/sites/docs/package.json index b95c165ef..b61d6dec3 100644 --- a/sites/docs/package.json +++ b/sites/docs/package.json @@ -39,7 +39,7 @@ "rehype-slug": "^6.0.0", "remark-gfm": "^4.0.0", "shiki": "^1.1.1", - "svelte": "5.0.0-next.143", + "svelte": "5.0.0-next.157", "svelte-check": "^3.6.9", "tailwind-merge": "^2.2.1", "tailwind-variants": "^0.1.20",