Skip to content

Commit

Permalink
next: menu (#522)
Browse files Browse the repository at this point in the history
Co-authored-by: Anatol Zakrividoroga <53095479+anatolzak@users.noreply.github.com>
fix: tooltip & grace area (#521)
  • Loading branch information
huntabyte and anatolzak authored May 30, 2024
1 parent 8478fbf commit b2e5b50
Show file tree
Hide file tree
Showing 137 changed files with 3,948 additions and 2,913 deletions.
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"tabWidth": 4,
"singleQuote": false,
"trailingComma": "es5",
"semi": true,
"printWidth": 100,
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
"overrides": [
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.115",
"svelte": "5.0.0-next.139",
"svelte-eslint-parser": "^0.34.1",
"wrangler": "^3.44.0"
},
Expand Down
7 changes: 4 additions & 3 deletions packages/bits-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"jsdom": "^24.0.0",
"publint": "^0.2.7",
"resize-observer-polyfill": "^1.5.1",
"svelte": "5.0.0-next.115",
"svelte": "5.0.0-next.139",
"svelte-check": "^3.6.9",
"tslib": "^2.6.2",
"typescript": "^5.3.3",
Expand All @@ -63,10 +63,11 @@
"clsx": "^2.1.0",
"esm-env": "^1.0.0",
"nanoid": "^5.0.5",
"runed": "^0.4.1",
"runed": "^0.5.0",
"scule": "^1.3.0",
"style-object-to-css-string": "^1.1.3",
"style-to-object": "^1.0.6"
"style-to-object": "^1.0.6",
"svelte-toolbelt": "^0.0.2"
},
"peerDependencies": {
"svelte": "^5.0.0"
Expand Down
4 changes: 2 additions & 2 deletions packages/bits-ui/src/lib/bits/accordion/accordion.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { WritableBox } from "runed";
import type { WritableBox } from "svelte-toolbelt";
import {
type Box,
type ReadableBoxedValues,
Expand Down Expand Up @@ -40,7 +40,7 @@ class AccordionBaseState {
disabled = undefined as unknown as AccordionBaseStateProps["disabled"];
#loop = undefined as unknown as AccordionBaseStateProps["loop"];
orientation = undefined as unknown as AccordionBaseStateProps["orientation"];
rovingFocusGroup = undefined as unknown as UseRovingFocusReturn;
rovingFocusGroup: UseRovingFocusReturn;

constructor(props: AccordionBaseStateProps) {
this.id = props.id;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { box } from "runed";
import { box } from "svelte-toolbelt";
import { useAccordionContent } from "../accordion.svelte.js";
import type { AccordionContentProps } from "../types.js";
import { PresenceLayer } from "$lib/bits/utilities/presence-layer/index.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { box } from "runed";
import { box } from "svelte-toolbelt";
import type { AccordionHeaderProps } from "../types.js";
import { useAccordionHeader } from "../accordion.svelte.js";
import { mergeProps } from "$lib/internal/mergeProps.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { box } from "runed";
import { box } from "svelte-toolbelt";
import type { AccordionItemProps } from "../types.js";
import { useAccordionItem } from "../accordion.svelte.js";
import { mergeProps } from "$lib/internal/mergeProps.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { box } from "runed";
import { box } from "svelte-toolbelt";
import type { AccordionTriggerProps } from "../types.js";
import { useAccordionTrigger } from "../accordion.svelte.js";
import { mergeProps, useId } from "$lib/internal/index.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { type WritableBox, box } from "runed";
import { type WritableBox, box } from "svelte-toolbelt";
import { useAccordionRoot } from "../accordion.svelte.js";
import type { RootProps } from "../index.js";
import { mergeProps } from "$lib/internal/mergeProps.js";
Expand Down
2 changes: 1 addition & 1 deletion packages/bits-ui/src/lib/bits/avatar/avatar.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { untrack } from "svelte";
import type { ReadableBox, WritableBox } from "runed";
import type { ReadableBox, WritableBox } from "svelte-toolbelt";
import type { AvatarImageLoadingStatus } from "./types.js";
import { createContext } from "$lib/internal/createContext.js";
import type { ReadableBoxedValues } from "$lib/internal/box.svelte.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { box } from "runed";
import { box } from "svelte-toolbelt";
import type { ImageProps } from "../index.js";
import { useAvatarImage } from "../avatar.svelte.js";
import { mergeProps } from "$lib/internal/mergeProps.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { box } from "runed";
import { box } from "svelte-toolbelt";
import type { RootProps } from "../index.js";
import { useAvatarRoot } from "../avatar.svelte.js";
import { mergeProps } from "$lib/internal/mergeProps.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { box } from "runed";
import { box } from "svelte-toolbelt";
import type { RootProps } from "../index.js";
import { useCheckboxRoot } from "../checkbox.svelte.js";
import CheckboxInput from "./checkbox-input.svelte";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { box } from "runed";
import { box } from "svelte-toolbelt";
import {
type ReadableBoxedValues,
type WritableBoxedValues,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { box } from "runed";
import { box } from "svelte-toolbelt";
import { useCollapsibleContent } from "../collapsible.svelte.js";
import type { CollapsibleContentProps } from "../types.js";
import { PresenceLayer } from "$lib/bits/utilities/presence-layer/index.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { box } from "runed";
import { box } from "svelte-toolbelt";
import type { RootProps } from "../index.js";
import { useCollapsibleRoot } from "../collapsible.svelte.js";
import { mergeProps } from "$lib/internal/mergeProps.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,105 +1,88 @@
<script lang="ts">
import { melt } from "@melt-ui/svelte";
import { getCtx, updatePositioning } from "../ctx.js";
import type { ContentEvents, ContentProps } from "../index.js";
import type { Transition } from "$lib/internal/types.js";
import { createDispatcher } from "$lib/internal/events.js";
import { box } from "svelte-toolbelt";
import type { ContentProps } from "../index.js";
import { useMenuContent } from "$lib/bits/menu/menu.svelte.js";
import { useId } from "$lib/internal/useId.svelte.js";
import { mergeProps } from "$lib/internal/mergeProps.js";
import { noop } from "$lib/internal/callbacks.js";
import PopperLayer from "$lib/bits/utilities/popper-layer/popper-layer.svelte";
import { isElement } from "$lib/internal/is.js";
import type { InteractOutsideEvent } from "$lib/bits/utilities/dismissable-layer/types.js";
type T = $$Generic<Transition>;
type In = $$Generic<Transition>;
type Out = $$Generic<Transition>;
type $$Props = ContentProps<T, In, Out>;
type $$Events = ContentEvents;
let {
id = useId(),
asChild,
child,
children,
el = $bindable(),
loop = true,
onInteractOutside = noop,
onEscapeKeydown = noop,
forceMount = false,
...restProps
}: ContentProps = $props();
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 alignOffset: $$Props["alignOffset"] = 0;
export let collisionPadding: $$Props["collisionPadding"] = 8;
export let avoidCollisions: $$Props["avoidCollisions"] = true;
export let collisionBoundary: $$Props["collisionBoundary"] = undefined;
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: { menu },
states: { open },
ids,
getAttrs,
} = getCtx();
const dispatch = createDispatcher();
const attrs = getAttrs("content");
const state = useMenuContent({
id: box.with(() => id),
loop: box.with(() => loop),
});
$: if (id) {
ids.menu.set(id);
function handleInteractOutsideStart(e: InteractOutsideEvent) {
if (!isElement(e.target)) return;
if (e.target.id === state.parentMenu.triggerId.value) {
e.preventDefault();
return;
}
if (e.target.closest(`#${state.parentMenu.triggerId.value}`)) {
e.preventDefault();
}
}
$: builder = $menu;
$: Object.assign(builder, attrs);
$: updatePositioning({
alignOffset,
collisionPadding,
avoidCollisions,
collisionBoundary,
fitViewport,
strategy,
overlap,
});
const mergedProps = $derived(
mergeProps(restProps, state.props, {
onInteractOutsideStart: handleInteractOutsideStart,
style: {
outline: "none",
"--bits-context-menu-content-transform-origin":
"var(--bits-floating-transform-origin)",
"--bits-context-menu-content-available-width":
"var(--bits-floating-available-width)",
"--bits-context-menu-content-available-height":
"var(--bits-floating-available-height)",
"--bits-context-menu-trigger-width": "var(--bits-floating-anchor-width)",
"--bits-context-menu-trigger-height": "var(--bits-floating-anchor-height)",
},
})
);
</script>

{#if asChild && $open}
<slot {builder} />
{:else if transition && $open}
<div
bind:this={el}
transition:transition={transitionConfig}
use:melt={builder}
{...$$restProps}
on:m-keydown={dispatch}
>
<slot {builder} />
</div>
{:else if inTransition && outTransition && $open}
<div
bind:this={el}
in:inTransition={inTransitionConfig}
out:outTransition={outTransitionConfig}
use:melt={builder}
{...$$restProps}
on:m-keydown={dispatch}
>
<slot {builder} />
</div>
{:else if inTransition && $open}
<div
bind:this={el}
in:inTransition={inTransitionConfig}
use:melt={builder}
{...$$restProps}
on:m-keydown={dispatch}
>
<slot {builder} />
</div>
{:else if outTransition && $open}
<div
bind:this={el}
out:outTransition={outTransitionConfig}
use:melt={builder}
{...$$restProps}
on:m-keydown={dispatch}
>
<slot {builder} />
</div>
{:else if $open}
<div bind:this={el} use:melt={builder} {...$$restProps} on:m-keydown={dispatch}>
<slot {builder} />
</div>
{/if}
<PopperLayer
{...mergedProps}
side="right"
sideOffset={2}
align="start"
present={state.parentMenu.open.value || forceMount}
onInteractOutside={(e) => {
onInteractOutside(e);
if (e.defaultPrevented) return;
state.parentMenu.onClose();
}}
onEscapeKeydown={(e) => {
// TODO: users should be able to cancel this
onEscapeKeydown(e);
state.parentMenu.onClose();
}}
trapped
{loop}
>
{#snippet popper({ props })}
{@const finalProps = mergeProps(props, mergedProps)}
{#if asChild}
{@render child?.({ props: finalProps })}
{:else}
<div {...finalProps} bind:this={el}>
{@render children?.()}
</div>
{/if}
{/snippet}
</PopperLayer>
Loading

0 comments on commit b2e5b50

Please sign in to comment.