Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

next: initial floating stuff #485

Merged
merged 9 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/bits-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@testing-library/user-event": "^14.5.2",
"@types/jest-axe": "^3.5.9",
"@types/node": "^20.12.2",
"@types/resize-observer-browser": "^0.1.11",
"@types/testing-library__jest-dom": "^5.14.9",
"csstype": "^3.1.3",
"jest-axe": "^8.0.0",
Expand All @@ -54,6 +55,8 @@
"types": "./dist/index.d.ts",
"type": "module",
"dependencies": {
"@floating-ui/core": "^1.6.0",
"@floating-ui/dom": "^1.6.3",
"@internationalized/date": "^3.5.1",
"@melt-ui/svelte": "0.76.2",
"esm-env": "^1.0.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/bits-ui/src/lib/bits/accordion/accordion.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import {
getDataOpenClosed,
kbd,
styleToString,
useNodeById,
verifyContextDeps,
} from "$lib/internal/index.js";
import type { StyleProperties } from "$lib/shared/index.js";
import { withTick } from "$lib/internal/with-tick.js";
import { useNodeById } from "$lib/internal/elements.svelte.js";
import { afterTick } from "$lib/internal/after-tick.js";

/**
* BASE
Expand Down Expand Up @@ -284,7 +284,7 @@ class AccordionContentState {
const node = this.node.value;
if (!node) return;

withTick(() => {
afterTick(() => {
if (!this.node) return;
// get the dimensions of the element
this.#originalStyles = this.#originalStyles || {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { getAccordionContentState } from "../accordion.svelte.js";
import type { AccordionContentProps } from "../types.js";
import Presence from "$lib/bits/utilities/presence.svelte";
import Presence from "$lib/bits/utilities/presence-layer/presence-layer.svelte";
import { readonlyBox } from "$lib/internal/box.svelte.js";
import { generateId } from "$lib/internal/id.js";

Expand All @@ -23,7 +23,7 @@
});
</script>

<Presence forceMount={true} present={content.present} node={content.node}>
<Presence forceMount={true} present={content.present} {id}>
{#snippet presence({ present })}
{@const mergedProps = {
...restProps,
Expand Down
22 changes: 12 additions & 10 deletions packages/bits-ui/src/lib/bits/collapsible/collapsible.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { getContext, setContext } from "svelte";
import { getAriaExpanded, getDataDisabled, getDataOpenClosed } from "$lib/internal/attrs.js";
import {
type Box,
type BoxedValues,
type EventCallback,
type ReadonlyBox,
type ReadonlyBoxedValues,
afterTick,
boxedState,
readonlyBox,
composeHandlers,
generateId,
getAriaExpanded,
getDataDisabled,
getDataOpenClosed,
readonlyBoxedState,
} from "$lib/internal/box.svelte.js";
import { generateId } from "$lib/internal/id.js";
import { styleToString } from "$lib/internal/style.js";
import { type EventCallback, composeHandlers } from "$lib/internal/events.js";
styleToString,
useNodeById,
verifyContextDeps,
} from "$lib/internal/index.js";
import type { StyleProperties } from "$lib/shared/index.js";
import { withTick } from "$lib/internal/with-tick.js";
import { useNodeById } from "$lib/internal/elements.svelte.js";
import { verifyContextDeps } from "$lib/internal/context.js";

type CollapsibleRootStateProps = BoxedValues<{
open: boolean;
Expand Down Expand Up @@ -105,7 +107,7 @@ class CollapsibleContentState {
const node = this.node.value;
if (!node) return;

withTick(() => {
afterTick(() => {
if (!this.node) return;
// get the dimensions of the element
this.#originalStyles = this.#originalStyles || {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { getCollapsibleContentState } from "../collapsible.svelte.js";
import type { CollapsibleContentProps } from "../types.js";
import Presence from "$lib/bits/utilities/presence.svelte";
import Presence from "$lib/bits/utilities/presence-layer/presence-layer.svelte";
import { generateId } from "$lib/internal/id.js";
import { readonlyBox } from "$lib/internal/box.svelte.js";

Expand All @@ -23,7 +23,7 @@
});
</script>

<Presence forceMount={true} present={content.present} node={content.node}>
<Presence forceMount={true} present={content.present} {id}>
{#snippet presence({ present })}
{@const mergedProps = {
...restProps,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +0,0 @@
<script lang="ts">
import { melt } from "@melt-ui/svelte";
import { setArrow } from "../ctx.js";
import type { ArrowProps } from "../index.js";

type $$Props = ArrowProps;

export let asChild: $$Props["asChild"] = false;
export let el: $$Props["el"] = undefined;
export let size = 8;

const {
elements: { arrow },
getAttrs,
} = setArrow(size);

const attrs = getAttrs("arrow");

$: builder = $arrow;
$: Object.assign(builder, attrs);
</script>

{#if asChild}
<slot {builder} />
{:else}
<div bind:this={el} use:melt={builder} {...$$restProps} />
{/if}
Original file line number Diff line number Diff line change
@@ -1,38 +0,0 @@
<script lang="ts">
import { melt } from "@melt-ui/svelte";
import { getCtx } from "../ctx.js";
import type { CloseEvents, CloseProps } from "../index.js";
import { createDispatcher } from "$lib/internal/events.js";

type $$Props = CloseProps;
type $$Events = CloseEvents;

export let asChild: $$Props["asChild"] = false;
export let el: $$Props["el"] = undefined;

const {
elements: { close },
getAttrs,
} = getCtx();

const dispatch = createDispatcher();
const attrs = getAttrs("close");

$: builder = $close;
$: Object.assign(builder, attrs);
</script>

{#if asChild}
<slot {builder} />
{:else}
<button
bind:this={el}
use:melt={builder}
type="button"
{...$$restProps}
on:m-click={dispatch}
on:m-keydown={dispatch}
>
<slot {builder} />
</button>
{/if}
Original file line number Diff line number Diff line change
@@ -1,99 +1,44 @@
<script lang="ts">
import { melt } from "@melt-ui/svelte";
import { getCtx, updatePositioning } from "../ctx.js";
import type { ContentProps } from "../index.js";
import type { Transition } from "$lib/internal/index.js";

type T = $$Generic<Transition>;
type In = $$Generic<Transition>;
type Out = $$Generic<Transition>;

type $$Props = ContentProps<T, In, Out>;

export let transition: $$Props["transition"] = undefined;
export let transitionConfig: $$Props["transitionConfig"] = undefined;
export let inTransition: $$Props["inTransition"] = undefined;
export let inTransitionConfig: $$Props["inTransitionConfig"] = undefined;
export let outTransition: $$Props["outTransition"] = undefined;
export let outTransitionConfig: $$Props["outTransitionConfig"] = undefined;
export let asChild: $$Props["asChild"] = false;
export let id: $$Props["id"] = undefined;
export let side: $$Props["side"] = "bottom";
export let align: $$Props["align"] = "center";
export let sideOffset: $$Props["sideOffset"] = 0;
export let alignOffset: $$Props["alignOffset"] = 0;
export let collisionPadding: $$Props["collisionPadding"] = 8;
export let avoidCollisions: $$Props["avoidCollisions"] = true;
export let collisionBoundary: $$Props["collisionBoundary"] = undefined;
export let sameWidth: $$Props["sameWidth"] = false;
export let fitViewport: $$Props["fitViewport"] = false;
export let strategy: $$Props["strategy"] = "absolute";
export let overlap: $$Props["overlap"] = false;
export let el: $$Props["el"] = undefined;

const {
elements: { content },
states: { open },
ids,
getAttrs,
} = getCtx();

const attrs = getAttrs("content");

$: if (id) {
ids.content.set(id);
}
$: builder = $content;
$: Object.assign(builder, attrs);

$: if ($open) {
updatePositioning({
side,
align,
sideOffset,
alignOffset,
collisionPadding,
avoidCollisions,
collisionBoundary,
sameWidth,
fitViewport,
strategy,
overlap,
});
}
import { setPopoverContentState } from "../popover.svelte.js";
import { FloatingLayer, PresenceLayer } from "$lib/bits/utilities/index.js";
import { readonlyBox } from "$lib/internal/box.svelte.js";
import { generateId } from "$lib/internal/id.js";

let {
asChild,
child,
children,
el = $bindable(),
style = {},
id = generateId(),
forceMount = false,
...restProps
}: ContentProps = $props();

const state = setPopoverContentState({
id: readonlyBox(() => id),
});
</script>

{#if asChild && $open}
<slot {builder} />
{:else if transition && $open}
<div
bind:this={el}
transition:transition={transitionConfig}
use:melt={builder}
{...$$restProps}
>
<slot {builder} />
</div>
{:else if inTransition && outTransition && $open}
<div
bind:this={el}
in:inTransition={inTransitionConfig}
out:outTransition={outTransitionConfig}
use:melt={builder}
{...$$restProps}
>
<slot {builder} />
</div>
{:else if inTransition && $open}
<div bind:this={el} in:inTransition={inTransitionConfig} use:melt={builder} {...$$restProps}>
<slot {builder} />
</div>
{:else if outTransition && $open}
<div bind:this={el} out:outTransition={outTransitionConfig} use:melt={builder} {...$$restProps}>
<slot {builder} />
</div>
{:else if $open}
<div bind:this={el} use:melt={builder} {...$$restProps}>
<slot {builder} />
</div>
{/if}
<PresenceLayer.Root forceMount={true} present={state.root.open.value || forceMount} {id}>
{#snippet presence({ present })}
<FloatingLayer.Content {id} {style} {...restProps}>
{#snippet content({ props })}
{@const mergedProps = {
...state.props,
...props,
hidden: present.value ? undefined : true,
...restProps,
}}
{#if asChild}
{@render child?.({ props: mergedProps })}
{:else}
<div {...mergedProps} bind:this={el}>
{@render children?.()}
</div>
{/if}
{/snippet}
</FloatingLayer.Content>
{/snippet}
</PresenceLayer.Root>
Loading
Loading