Skip to content

Commit

Permalink
we're in there
Browse files Browse the repository at this point in the history
  • Loading branch information
huntabyte committed Apr 20, 2024
1 parent 649edb8 commit d8c98fa
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@
</script>

<PopperLayer.Root
{...restProps}
forceMount={true}
present={state.root.open.value || forceMount}
{id}
{...restProps}
{style}
onInteractOutside={state.root.close}
onEscape={state.root.close}
>
{#snippet popper({ props })}
{@const mergedProps = {
...props,
...state.props,
...restProps,
...state.props,
...props,
}}
{#if asChild}
{@render child?.({ props: mergedProps })}
Expand Down
1 change: 1 addition & 0 deletions packages/bits-ui/src/lib/bits/popover/popover.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class PopoverTriggerState {

#onkeydown = (e: KeyboardEvent) => {
if (!(e.key === kbd.ENTER || e.key === kbd.SPACE)) return;
e.preventDefault();
this.root.toggleOpen();
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
strategy = "fixed",
dir = "ltr",
style = {},
present,
}: ContentProps = $props();
const state = setFloatingContentState({
Expand All @@ -40,6 +41,7 @@
strategy: readonlyBox(() => strategy),
dir: readonlyBox(() => dir),
style: readonlyBox(() => style),
present: readonlyBox(() => present),
});
</script>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
type Box,
type ReadonlyBox,
type ReadonlyBoxedValues,
afterTick,
boxedState,
generateId,
styleToString,
Expand Down Expand Up @@ -82,6 +83,7 @@ export type FloatingContentStateProps = ReadonlyBoxedValues<{
onPlaced: () => void;
dir: TextDirection;
style: StyleProperties;
present: boolean;
}>;

class FloatingContentState {
Expand All @@ -103,6 +105,7 @@ class FloatingContentState {
updatePositionStrategy =
undefined as unknown as FloatingContentStateProps["updatePositionStrategy"];
onPlaced = undefined as unknown as FloatingContentStateProps["onPlaced"];
present = undefined as unknown as FloatingContentStateProps["present"];
arrowSize: {
readonly value:
| {
Expand Down Expand Up @@ -200,7 +203,7 @@ class FloatingContentState {
...this.style.value,
// if the FloatingContent hasn't been placed yet (not all measurements done)
// we prevent animations so that users's animation don't kick in too early referring wrong sides
animation: !this.floating.isPositioned ? "none" : undefined,
// animation: !this.floating.isPositioned ? "none" : undefined,
}),
});

Expand All @@ -222,6 +225,9 @@ class FloatingContentState {
this.dir = props.dir;
this.style = props.style;
this.root = root;
this.present = props.present;
this.arrowSize = useSize(this.root.arrowNode);
this.root.contentNode = useNodeById(this.id);
this.floating = useFloating({
strategy: () => this.strategy.value,
placement: () => this.desiredPlacement,
Expand All @@ -233,12 +239,9 @@ class FloatingContentState {
});
return cleanup;
},
open: () => this.present.value,
});

this.arrowSize = useSize(this.root.arrowNode);

this.root.contentNode = useNodeById(this.id);

$effect(() => {
if (this.floating.isPositioned) {
this.onPlaced?.value();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ export type FloatingLayerContentProps = {
* The style properties to apply to the content.
*/
style?: StyleProperties;

/**
* Whether the floating layer is present.
*/
present: boolean;
};

export type FloatingLayerArrowProps = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<PresenceLayer.Root {...restProps}>
{#snippet presence({ present })}
<FloatingLayer.Content {...restProps}>
<FloatingLayer.Content {...restProps} present={present.value}>
{#snippet content({ props })}
<EscapeLayer.Root {...restProps} present={present.value}>
<DismissableLayer.Root {...restProps} present={present.value}>
Expand Down
1 change: 0 additions & 1 deletion packages/bits-ui/src/lib/internal/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ export function addEventListener(

// Return a function that removes the event listener from the target element(s).
return () => {
console.log("removing event listeners");
events.forEach((_event) => target.removeEventListener(_event, handler, options));
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { computePosition } from "@floating-ui/dom";
import { box, boxedState } from "../box.svelte.js";
import { afterTick } from "../after-tick.js";
import type { UseFloatingOptions, UseFloatingReturn } from "./types.js";
import { get, getDPR, roundByDPR } from "./utils.js";

Expand Down Expand Up @@ -59,7 +60,6 @@ export function useFloating(options: UseFloatingOptions): UseFloatingReturn {

function update() {
if (reference.value === null || floating.value === null) return;

computePosition(reference.value, floating.value, {
middleware: middlewareOption,
placement: placementOption,
Expand Down
39 changes: 18 additions & 21 deletions packages/bits-ui/src/lib/internal/use-presence.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { onDestroy } from "svelte";
import { onDestroy, untrack } from "svelte";
import { type Box, type ReadonlyBox, boxedState, watch } from "./box.svelte.js";
import { useNodeById, useStateMachine } from "$lib/internal/index.js";
import { afterTick, useNodeById, useStateMachine } from "$lib/internal/index.js";

export function usePresence(present: ReadonlyBox<boolean>, id: ReadonlyBox<string>) {
const styles = boxedState({}) as unknown as Box<CSSStyleDeclaration>;
Expand Down Expand Up @@ -34,7 +34,7 @@ export function usePresence(present: ReadonlyBox<boolean>, id: ReadonlyBox<strin

if (currPresent) {
dispatch("MOUNT");
} else if (currAnimationName === "none" || styles.value?.display === "none") {
} else if (currAnimationName === "none" || styles.value.display === "none") {
// If there is no exit animation or the element is hidden, animations won't run
// so we unmount instantly
dispatch("UNMOUNT");
Expand All @@ -46,14 +46,15 @@ export function usePresence(present: ReadonlyBox<boolean>, id: ReadonlyBox<strin
* fires after `animation-delay` has expired which would be too late.
*/
const isAnimating = prevAnimationName !== currAnimationName;

if (prevPresent && isAnimating) {
dispatch("ANIMATION_OUT");
} else {
dispatch("UNMOUNT");
}
}
},
{ immediate: false }
{ immediate: true }
);

/**
Expand Down Expand Up @@ -85,23 +86,19 @@ export function usePresence(present: ReadonlyBox<boolean>, id: ReadonlyBox<strin
prevAnimationNameState.value = state.value === "mounted" ? currAnimationName : "none";
});

const watcher = watch(
node,
(currNode, prevNode) => {
if (currNode) {
styles.value = getComputedStyle(currNode);
currNode.addEventListener("animationstart", handleAnimationStart);
currNode.addEventListener("animationcancel", handleAnimationEnd);
currNode.addEventListener("animationend", handleAnimationEnd);
} else {
dispatch("ANIMATION_END");
prevNode?.removeEventListener("animationstart", handleAnimationStart);
prevNode?.removeEventListener("animationcancel", handleAnimationEnd);
prevNode?.removeEventListener("animationend", handleAnimationEnd);
}
},
{ immediate: true }
);
const watcher = watch(node, (currNode, prevNode) => {
if (currNode) {
styles.value = getComputedStyle(currNode);
currNode.addEventListener("animationstart", handleAnimationStart);
currNode.addEventListener("animationcancel", handleAnimationEnd);
currNode.addEventListener("animationend", handleAnimationEnd);
} else {
dispatch("ANIMATION_END");
prevNode?.removeEventListener("animationstart", handleAnimationStart);
prevNode?.removeEventListener("animationcancel", handleAnimationEnd);
prevNode?.removeEventListener("animationend", handleAnimationEnd);
}
});

onDestroy(() => {
watcher();
Expand Down

0 comments on commit d8c98fa

Please sign in to comment.