This commit is contained in:
eewing
2026-02-17 14:10:16 -06:00
parent 2bca5834c5
commit cf73cd3b4c
11246 changed files with 1690552 additions and 0 deletions
@@ -0,0 +1,94 @@
<script lang="ts">
import { boxWith, mergeProps } from "svelte-toolbelt";
import { untrack, type Snippet } from "svelte";
import type { NavigationMenuContentProps } from "../types.js";
import {
NavigationMenuItemContext,
NavigationMenuItemState,
NavigationMenuContentImplState,
} from "../navigation-menu.svelte.js";
import { noop } from "../../../internal/noop.js";
import { createId } from "../../../internal/create-id.js";
import DismissibleLayer from "../../utilities/dismissible-layer/dismissible-layer.svelte";
import EscapeLayer from "../../utilities/escape-layer/escape-layer.svelte";
const uid = $props.id();
let {
ref = $bindable(null),
id = createId(uid),
child: childProp,
children: childrenProp,
onInteractOutside = noop,
onFocusOutside = noop,
onEscapeKeydown = noop,
escapeKeydownBehavior = "close",
interactOutsideBehavior = "close",
itemState,
onRefChange,
...restProps
}: Omit<NavigationMenuContentProps, "child"> & {
itemState?: NavigationMenuItemState;
onRefChange?: (ref: HTMLElement | null) => void;
child?: Snippet<[{ props: Record<string, unknown> }]>;
} = $props();
const contentImplState = NavigationMenuContentImplState.create(
{
id: boxWith(() => id),
ref: boxWith(
() => ref,
(v) => {
ref = v;
untrack(() => onRefChange?.(v));
}
),
},
itemState
);
if (itemState) {
NavigationMenuItemContext.set(itemState);
}
const mergedProps = $derived(mergeProps(restProps, contentImplState.props));
</script>
<DismissibleLayer
{id}
ref={contentImplState.opts.ref}
enabled={true}
onInteractOutside={(e) => {
onInteractOutside(e);
if (e.defaultPrevented) return;
contentImplState.onInteractOutside(e);
}}
onFocusOutside={(e) => {
onFocusOutside(e);
if (e.defaultPrevented) return;
contentImplState.onFocusOutside(e);
}}
{interactOutsideBehavior}
>
{#snippet children({ props: dismissibleProps })}
<EscapeLayer
enabled={true}
ref={contentImplState.opts.ref}
onEscapeKeydown={(e) => {
onEscapeKeydown(e);
if (e.defaultPrevented) return;
contentImplState.onEscapeKeydown(e);
}}
{escapeKeydownBehavior}
>
{@const finalProps = mergeProps(mergedProps, dismissibleProps)}
{#if childProp}
{@render childProp({ props: finalProps })}
{:else}
<div {...finalProps}>
{@render childrenProp?.()}
</div>
{/if}
</EscapeLayer>
{/snippet}
</DismissibleLayer>
@@ -0,0 +1,13 @@
import { type Snippet } from "svelte";
import type { NavigationMenuContentProps } from "../types.js";
import { NavigationMenuItemState } from "../navigation-menu.svelte.js";
type $$ComponentProps = Omit<NavigationMenuContentProps, "child"> & {
itemState?: NavigationMenuItemState;
onRefChange?: (ref: HTMLElement | null) => void;
child?: Snippet<[{
props: Record<string, unknown>;
}]>;
};
declare const NavigationMenuContentImpl: import("svelte").Component<$$ComponentProps, {}, "ref">;
type NavigationMenuContentImpl = ReturnType<typeof NavigationMenuContentImpl>;
export default NavigationMenuContentImpl;
@@ -0,0 +1,46 @@
<script lang="ts">
import { boxWith, mergeProps } from "svelte-toolbelt";
import { NavigationMenuContentState } from "../navigation-menu.svelte.js";
import NavigationMenuContentImpl from "./navigation-menu-content-impl.svelte";
import { createId } from "../../../internal/create-id.js";
import type { NavigationMenuContentProps } from "../../../types.js";
import Portal from "../../utilities/portal/portal.svelte";
import PresenceLayer from "../../utilities/presence-layer/presence-layer.svelte";
import Mounted from "../../utilities/mounted.svelte";
const uid = $props.id();
let {
ref = $bindable(null),
id = createId(uid),
children,
child,
forceMount = false,
...restProps
}: NavigationMenuContentProps = $props();
const contentState = NavigationMenuContentState.create({
id: boxWith(() => id),
ref: boxWith(
() => ref,
(v) => (ref = v)
),
});
const mergedProps = $derived(mergeProps(restProps, contentState.props));
</script>
<Portal
to={contentState.context.viewportRef.current || undefined}
disabled={!contentState.context.viewportRef.current}
>
<PresenceLayer
open={forceMount || contentState.open || contentState.isLastActiveValue}
ref={contentState.opts.ref}
>
{#snippet presence()}
<NavigationMenuContentImpl {...mergedProps} {children} {child} />
<Mounted bind:mounted={contentState.mounted} />
{/snippet}
</PresenceLayer>
</Portal>
@@ -0,0 +1,4 @@
import type { NavigationMenuContentProps } from "../../../types.js";
declare const NavigationMenuContent: import("svelte").Component<NavigationMenuContentProps, {}, "ref">;
type NavigationMenuContent = ReturnType<typeof NavigationMenuContent>;
export default NavigationMenuContent;
@@ -0,0 +1,34 @@
<script lang="ts">
import { boxWith, mergeProps } from "svelte-toolbelt";
import type { NavigationMenuIndicatorProps } from "../types.js";
import { NavigationMenuIndicatorImplState } from "../navigation-menu.svelte.js";
import { createId } from "../../../internal/create-id.js";
const uid = $props.id();
let {
id = createId(uid),
ref = $bindable(null),
children,
child,
...restProps
}: NavigationMenuIndicatorProps = $props();
const indicatorState = NavigationMenuIndicatorImplState.create({
id: boxWith(() => id),
ref: boxWith(
() => ref,
(v) => (ref = v)
),
});
const mergedProps = $derived(mergeProps(restProps, indicatorState.props));
</script>
{#if child}
{@render child({ props: mergedProps })}
{:else}
<div {...mergedProps}>
{@render children?.()}
</div>
{/if}
@@ -0,0 +1,4 @@
import type { NavigationMenuIndicatorProps } from "../types.js";
declare const NavigationMenuIndicatorImpl: import("svelte").Component<NavigationMenuIndicatorProps, {}, "ref">;
type NavigationMenuIndicatorImpl = ReturnType<typeof NavigationMenuIndicatorImpl>;
export default NavigationMenuIndicatorImpl;
@@ -0,0 +1,33 @@
<script lang="ts">
import { boxWith, mergeProps } from "svelte-toolbelt";
import type { NavigationMenuIndicatorProps } from "../types.js";
import { NavigationMenuIndicatorState } from "../navigation-menu.svelte.js";
import NavigationMenuIndicatorImpl from "./navigation-menu-indicator-impl.svelte";
import { createId } from "../../../internal/create-id.js";
import PresenceLayer from "../../utilities/presence-layer/presence-layer.svelte";
import Portal from "../../utilities/portal/portal.svelte";
const uid = $props.id();
let {
id = createId(uid),
ref = $bindable(null),
children,
child,
forceMount = false,
...restProps
}: NavigationMenuIndicatorProps = $props();
const indicatorState = NavigationMenuIndicatorState.create();
const mergedProps = $derived(mergeProps(restProps));
</script>
{#if indicatorState.context.indicatorTrackRef.current}
<Portal to={indicatorState.context.indicatorTrackRef.current}>
<PresenceLayer open={forceMount || indicatorState.isVisible} ref={boxWith(() => ref)}>
{#snippet presence()}
<NavigationMenuIndicatorImpl {...mergedProps} {children} {child} {id} bind:ref />
{/snippet}
</PresenceLayer>
</Portal>
{/if}
@@ -0,0 +1,4 @@
import type { NavigationMenuIndicatorProps } from "../types.js";
declare const NavigationMenuIndicator: import("svelte").Component<NavigationMenuIndicatorProps, {}, "ref">;
type NavigationMenuIndicator = ReturnType<typeof NavigationMenuIndicator>;
export default NavigationMenuIndicator;
@@ -0,0 +1,39 @@
<script lang="ts">
import { boxWith, mergeProps } from "svelte-toolbelt";
import type { NavigationMenuItemProps } from "../types.js";
import { NavigationMenuItemState } from "../navigation-menu.svelte.js";
import { createId } from "../../../internal/create-id.js";
const uid = $props.id();
const defaultId = createId(uid);
let {
id = defaultId,
value = defaultId,
ref = $bindable(null),
child,
children,
openOnHover = true,
...restProps
}: NavigationMenuItemProps = $props();
const itemState = NavigationMenuItemState.create({
id: boxWith(() => id),
ref: boxWith(
() => ref,
(v) => (ref = v)
),
value: boxWith(() => value),
openOnHover: boxWith(() => openOnHover),
});
const mergedProps = $derived(mergeProps(restProps, itemState.props));
</script>
{#if child}
{@render child({ props: mergedProps })}
{:else}
<li {...mergedProps}>
{@render children?.()}
</li>
{/if}
@@ -0,0 +1,4 @@
import type { NavigationMenuItemProps } from "../types.js";
declare const NavigationMenuItem: import("svelte").Component<NavigationMenuItemProps, {}, "ref">;
type NavigationMenuItem = ReturnType<typeof NavigationMenuItem>;
export default NavigationMenuItem;
@@ -0,0 +1,40 @@
<script lang="ts">
import { boxWith, mergeProps } from "svelte-toolbelt";
import type { NavigationMenuLinkProps } from "../types.js";
import { NavigationMenuLinkState } from "../navigation-menu.svelte.js";
import { createId } from "../../../internal/create-id.js";
import { noop } from "../../../internal/noop.js";
const uid = $props.id();
let {
id = createId(uid),
ref = $bindable(null),
child,
children,
active = false,
onSelect = noop,
tabindex = 0,
...restProps
}: NavigationMenuLinkProps = $props();
const linkState = NavigationMenuLinkState.create({
id: boxWith(() => id),
ref: boxWith(
() => ref,
(v) => (ref = v)
),
active: boxWith(() => active),
onSelect: boxWith(() => onSelect),
});
const mergedProps = $derived(mergeProps(restProps, linkState.props, { tabindex }));
</script>
{#if child}
{@render child({ props: mergedProps })}
{:else}
<a {...mergedProps}>
{@render children?.()}
</a>
{/if}
@@ -0,0 +1,4 @@
import type { NavigationMenuLinkProps } from "../types.js";
declare const NavigationMenuLink: import("svelte").Component<NavigationMenuLinkProps, {}, "ref">;
type NavigationMenuLink = ReturnType<typeof NavigationMenuLink>;
export default NavigationMenuLink;
@@ -0,0 +1,40 @@
<script lang="ts">
import { boxWith, mergeProps } from "svelte-toolbelt";
import type { NavigationMenuListProps } from "../types.js";
import { NavigationMenuListState } from "../navigation-menu.svelte.js";
import { createId } from "../../../internal/create-id.js";
import Mounted from "../../utilities/mounted.svelte";
const uid = $props.id();
let {
id = createId(uid),
children,
child,
ref = $bindable(null),
...restProps
}: NavigationMenuListProps = $props();
const listState = NavigationMenuListState.create({
id: boxWith(() => id),
ref: boxWith(
() => ref,
(v) => (ref = v)
),
});
const mergedProps = $derived(mergeProps(restProps, listState.props));
const wrapperProps = $derived(mergeProps(listState.wrapperProps));
</script>
{#if child}
{@render child({ props: mergedProps, wrapperProps })}
<Mounted bind:mounted={listState.wrapperMounted} />
{:else}
<div {...wrapperProps}>
<ul {...mergedProps}>
{@render children?.()}
</ul>
</div>
<Mounted bind:mounted={listState.wrapperMounted} />
{/if}
@@ -0,0 +1,4 @@
import type { NavigationMenuListProps } from "../types.js";
declare const NavigationMenuList: import("svelte").Component<NavigationMenuListProps, {}, "ref">;
type NavigationMenuList = ReturnType<typeof NavigationMenuList>;
export default NavigationMenuList;
@@ -0,0 +1,46 @@
<script lang="ts">
import { boxWith, mergeProps } from "svelte-toolbelt";
import type { NavigationMenuSubProps } from "../types.js";
import { NavigationMenuSubState } from "../navigation-menu.svelte.js";
import { createId } from "../../../internal/create-id.js";
import { noop } from "../../../internal/noop.js";
const uid = $props.id();
let {
child,
children,
id = createId(uid),
ref = $bindable(null),
value = $bindable(""),
onValueChange = noop,
orientation = "horizontal",
...restProps
}: NavigationMenuSubProps = $props();
const rootState = NavigationMenuSubState.create({
id: boxWith(() => id),
value: boxWith(
() => value,
(v) => {
value = v;
onValueChange(v);
}
),
orientation: boxWith(() => orientation),
ref: boxWith(
() => ref,
(v) => (ref = v)
),
});
const mergedProps = $derived(mergeProps(restProps, rootState.props));
</script>
{#if child}
{@render child({ props: mergedProps })}
{:else}
<div {...mergedProps}>
{@render children?.()}
</div>
{/if}
@@ -0,0 +1,4 @@
import type { NavigationMenuSubProps } from "../types.js";
declare const NavigationMenuSub: import("svelte").Component<NavigationMenuSubProps, {}, "value" | "ref">;
type NavigationMenuSub = ReturnType<typeof NavigationMenuSub>;
export default NavigationMenuSub;
@@ -0,0 +1,47 @@
<script lang="ts">
import { boxWith, mergeProps } from "svelte-toolbelt";
import type { NavigationMenuTriggerProps } from "../types.js";
import { NavigationMenuTriggerState } from "../navigation-menu.svelte.js";
import { createId } from "../../../internal/create-id.js";
import VisuallyHidden from "../../utilities/visually-hidden/visually-hidden.svelte";
import Mounted from "../../utilities/mounted.svelte";
const uid = $props.id();
let {
id = createId(uid),
disabled = false,
children,
child,
ref = $bindable(null),
tabindex = 0,
...restProps
}: NavigationMenuTriggerProps = $props();
const triggerState = NavigationMenuTriggerState.create({
id: boxWith(() => id),
disabled: boxWith(() => disabled ?? false),
ref: boxWith(
() => ref,
(v) => (ref = v)
),
});
const mergedProps = $derived(mergeProps(restProps, triggerState.props, { tabindex }));
</script>
{#if child}
{@render child({ props: mergedProps })}
{:else}
<button {...mergedProps}>
{@render children?.()}
</button>
{/if}
{#if triggerState.open}
<VisuallyHidden {...triggerState.focusProxyProps} />
<Mounted bind:mounted={triggerState.focusProxyMounted} />
{#if triggerState.context.viewportRef.current}
<span aria-owns={triggerState.itemContext.contentId ?? undefined}></span>
{/if}
{/if}
@@ -0,0 +1,4 @@
import type { NavigationMenuTriggerProps } from "../types.js";
declare const NavigationMenuTrigger: import("svelte").Component<NavigationMenuTriggerProps, {}, "ref">;
type NavigationMenuTrigger = ReturnType<typeof NavigationMenuTrigger>;
export default NavigationMenuTrigger;
@@ -0,0 +1,42 @@
<script lang="ts">
import type { NavigationMenuViewportProps } from "../types.js";
import { NavigationMenuViewportState } from "../navigation-menu.svelte.js";
import { createId } from "../../../internal/create-id.js";
import PresenceLayer from "../../utilities/presence-layer/presence-layer.svelte";
import { boxWith, mergeProps } from "svelte-toolbelt";
import { Mounted } from "../../utilities/index.js";
const uid = $props.id();
let {
id = createId(uid),
ref = $bindable(null),
forceMount = false,
child,
children,
...restProps
}: NavigationMenuViewportProps = $props();
const viewportState = NavigationMenuViewportState.create({
id: boxWith(() => id),
ref: boxWith(
() => ref,
(v) => (ref = v)
),
});
const mergedProps = $derived(mergeProps(restProps, viewportState.props));
</script>
<PresenceLayer open={forceMount || viewportState.open} ref={viewportState.opts.ref}>
{#snippet presence()}
{#if child}
{@render child({ props: mergedProps })}
{:else}
<div {...mergedProps}>
{@render children?.()}
</div>
{/if}
<Mounted bind:mounted={viewportState.mounted} />
{/snippet}
</PresenceLayer>
@@ -0,0 +1,4 @@
import type { NavigationMenuViewportProps } from "../types.js";
declare const NavigationMenuViewport: import("svelte").Component<NavigationMenuViewportProps, {}, "ref">;
type NavigationMenuViewport = ReturnType<typeof NavigationMenuViewport>;
export default NavigationMenuViewport;
@@ -0,0 +1,52 @@
<script lang="ts">
import { boxWith, mergeProps } from "svelte-toolbelt";
import type { NavigationMenuRootProps } from "../types.js";
import { NavigationMenuRootState } from "../navigation-menu.svelte.js";
import { createId } from "../../../internal/create-id.js";
import { noop } from "../../../internal/noop.js";
const uid = $props.id();
let {
child,
children,
id = createId(uid),
ref = $bindable(null),
value = $bindable(""),
onValueChange = noop,
delayDuration = 200,
skipDelayDuration = 300,
dir = "ltr",
orientation = "horizontal",
...restProps
}: NavigationMenuRootProps = $props();
const rootState = NavigationMenuRootState.create({
id: boxWith(() => id),
value: boxWith(
() => value,
(v) => {
value = v;
onValueChange(v);
}
),
delayDuration: boxWith(() => delayDuration),
skipDelayDuration: boxWith(() => skipDelayDuration),
dir: boxWith(() => dir),
orientation: boxWith(() => orientation),
ref: boxWith(
() => ref,
(v) => (ref = v)
),
});
const mergedProps = $derived(mergeProps({ "aria-label": "main" }, restProps, rootState.props));
</script>
{#if child}
{@render child({ props: mergedProps })}
{:else}
<nav {...mergedProps}>
{@render children?.()}
</nav>
{/if}
@@ -0,0 +1,4 @@
import type { NavigationMenuRootProps } from "../types.js";
declare const NavigationMenu: import("svelte").Component<NavigationMenuRootProps, {}, "value" | "ref">;
type NavigationMenu = ReturnType<typeof NavigationMenu>;
export default NavigationMenu;