mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-04-19 21:54:15 +02:00
turns out intellij formats the code before committing which causes the ci/cd checks to fail
This commit is contained in:
@@ -1,60 +1,60 @@
|
||||
import {IsMobile} from '$lib/hooks/is-mobile.svelte.js';
|
||||
import {getContext, setContext} from 'svelte';
|
||||
import {SIDEBAR_KEYBOARD_SHORTCUT} from './constants.js';
|
||||
import { IsMobile } from '$lib/hooks/is-mobile.svelte.js';
|
||||
import { getContext, setContext } from 'svelte';
|
||||
import { SIDEBAR_KEYBOARD_SHORTCUT } from './constants.js';
|
||||
|
||||
type Getter<T> = () => T;
|
||||
|
||||
export type SidebarStateProps = {
|
||||
/**
|
||||
* A getter function that returns the current open state of the sidebar.
|
||||
* We use a getter function here to support `bind:open` on the `Sidebar.Provider`
|
||||
* component.
|
||||
*/
|
||||
open: Getter<boolean>;
|
||||
/**
|
||||
* A getter function that returns the current open state of the sidebar.
|
||||
* We use a getter function here to support `bind:open` on the `Sidebar.Provider`
|
||||
* component.
|
||||
*/
|
||||
open: Getter<boolean>;
|
||||
|
||||
/**
|
||||
* A function that sets the open state of the sidebar. To support `bind:open`, we need
|
||||
* a source of truth for changing the open state to ensure it will be synced throughout
|
||||
* the sub-components and any `bind:` references.
|
||||
*/
|
||||
setOpen: (open: boolean) => void;
|
||||
/**
|
||||
* A function that sets the open state of the sidebar. To support `bind:open`, we need
|
||||
* a source of truth for changing the open state to ensure it will be synced throughout
|
||||
* the sub-components and any `bind:` references.
|
||||
*/
|
||||
setOpen: (open: boolean) => void;
|
||||
};
|
||||
|
||||
class SidebarState {
|
||||
readonly props: SidebarStateProps;
|
||||
open = $derived.by(() => this.props.open());
|
||||
openMobile = $state(false);
|
||||
setOpen: SidebarStateProps['setOpen'];
|
||||
#isMobile: IsMobile;
|
||||
state = $derived.by(() => (this.open ? 'expanded' : 'collapsed'));
|
||||
readonly props: SidebarStateProps;
|
||||
open = $derived.by(() => this.props.open());
|
||||
openMobile = $state(false);
|
||||
setOpen: SidebarStateProps['setOpen'];
|
||||
#isMobile: IsMobile;
|
||||
state = $derived.by(() => (this.open ? 'expanded' : 'collapsed'));
|
||||
|
||||
constructor(props: SidebarStateProps) {
|
||||
this.setOpen = props.setOpen;
|
||||
this.#isMobile = new IsMobile();
|
||||
this.props = props;
|
||||
}
|
||||
constructor(props: SidebarStateProps) {
|
||||
this.setOpen = props.setOpen;
|
||||
this.#isMobile = new IsMobile();
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
// Convenience getter for checking if the sidebar is mobile
|
||||
// without this, we would need to use `sidebar.isMobile.current` everywhere
|
||||
get isMobile() {
|
||||
return this.#isMobile.current;
|
||||
}
|
||||
// Convenience getter for checking if the sidebar is mobile
|
||||
// without this, we would need to use `sidebar.isMobile.current` everywhere
|
||||
get isMobile() {
|
||||
return this.#isMobile.current;
|
||||
}
|
||||
|
||||
// Event handler to apply to the `<svelte:window>`
|
||||
handleShortcutKeydown = (e: KeyboardEvent) => {
|
||||
if (e.key === SIDEBAR_KEYBOARD_SHORTCUT && (e.metaKey || e.ctrlKey)) {
|
||||
e.preventDefault();
|
||||
this.toggle();
|
||||
}
|
||||
};
|
||||
// Event handler to apply to the `<svelte:window>`
|
||||
handleShortcutKeydown = (e: KeyboardEvent) => {
|
||||
if (e.key === SIDEBAR_KEYBOARD_SHORTCUT && (e.metaKey || e.ctrlKey)) {
|
||||
e.preventDefault();
|
||||
this.toggle();
|
||||
}
|
||||
};
|
||||
|
||||
setOpenMobile = (value: boolean) => {
|
||||
this.openMobile = value;
|
||||
};
|
||||
setOpenMobile = (value: boolean) => {
|
||||
this.openMobile = value;
|
||||
};
|
||||
|
||||
toggle = () => {
|
||||
return this.#isMobile.current ? (this.openMobile = !this.openMobile) : this.setOpen(!this.open);
|
||||
};
|
||||
toggle = () => {
|
||||
return this.#isMobile.current ? (this.openMobile = !this.openMobile) : this.setOpen(!this.open);
|
||||
};
|
||||
}
|
||||
|
||||
const SYMBOL_KEY = 'scn-sidebar';
|
||||
@@ -66,7 +66,7 @@ const SYMBOL_KEY = 'scn-sidebar';
|
||||
* @returns The `SidebarState` instance.
|
||||
*/
|
||||
export function setSidebar(props: SidebarStateProps): SidebarState {
|
||||
return setContext(Symbol.for(SYMBOL_KEY), new SidebarState(props));
|
||||
return setContext(Symbol.for(SYMBOL_KEY), new SidebarState(props));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,5 +75,5 @@ export function setSidebar(props: SidebarStateProps): SidebarState {
|
||||
* @returns The `SidebarState` instance.
|
||||
*/
|
||||
export function useSidebar(): SidebarState {
|
||||
return getContext(Symbol.for(SYMBOL_KEY));
|
||||
return getContext(Symbol.for(SYMBOL_KEY));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {useSidebar} from './context.svelte.js';
|
||||
import { useSidebar } from './context.svelte.js';
|
||||
import Content from './sidebar-content.svelte';
|
||||
import Footer from './sidebar-footer.svelte';
|
||||
import GroupAction from './sidebar-group-action.svelte';
|
||||
@@ -24,52 +24,52 @@ import Trigger from './sidebar-trigger.svelte';
|
||||
import Root from './sidebar.svelte';
|
||||
|
||||
export {
|
||||
Content,
|
||||
Footer,
|
||||
Group,
|
||||
GroupAction,
|
||||
GroupContent,
|
||||
GroupLabel,
|
||||
Header,
|
||||
Input,
|
||||
Inset,
|
||||
Menu,
|
||||
MenuAction,
|
||||
MenuBadge,
|
||||
MenuButton,
|
||||
MenuItem,
|
||||
MenuSkeleton,
|
||||
MenuSub,
|
||||
MenuSubButton,
|
||||
MenuSubItem,
|
||||
Provider,
|
||||
Rail,
|
||||
Root,
|
||||
Separator,
|
||||
//
|
||||
Root as Sidebar,
|
||||
Content as SidebarContent,
|
||||
Footer as SidebarFooter,
|
||||
Group as SidebarGroup,
|
||||
GroupAction as SidebarGroupAction,
|
||||
GroupContent as SidebarGroupContent,
|
||||
GroupLabel as SidebarGroupLabel,
|
||||
Header as SidebarHeader,
|
||||
Input as SidebarInput,
|
||||
Inset as SidebarInset,
|
||||
Menu as SidebarMenu,
|
||||
MenuAction as SidebarMenuAction,
|
||||
MenuBadge as SidebarMenuBadge,
|
||||
MenuButton as SidebarMenuButton,
|
||||
MenuItem as SidebarMenuItem,
|
||||
MenuSkeleton as SidebarMenuSkeleton,
|
||||
MenuSub as SidebarMenuSub,
|
||||
MenuSubButton as SidebarMenuSubButton,
|
||||
MenuSubItem as SidebarMenuSubItem,
|
||||
Provider as SidebarProvider,
|
||||
Rail as SidebarRail,
|
||||
Separator as SidebarSeparator,
|
||||
Trigger as SidebarTrigger,
|
||||
Trigger,
|
||||
useSidebar
|
||||
Content,
|
||||
Footer,
|
||||
Group,
|
||||
GroupAction,
|
||||
GroupContent,
|
||||
GroupLabel,
|
||||
Header,
|
||||
Input,
|
||||
Inset,
|
||||
Menu,
|
||||
MenuAction,
|
||||
MenuBadge,
|
||||
MenuButton,
|
||||
MenuItem,
|
||||
MenuSkeleton,
|
||||
MenuSub,
|
||||
MenuSubButton,
|
||||
MenuSubItem,
|
||||
Provider,
|
||||
Rail,
|
||||
Root,
|
||||
Separator,
|
||||
//
|
||||
Root as Sidebar,
|
||||
Content as SidebarContent,
|
||||
Footer as SidebarFooter,
|
||||
Group as SidebarGroup,
|
||||
GroupAction as SidebarGroupAction,
|
||||
GroupContent as SidebarGroupContent,
|
||||
GroupLabel as SidebarGroupLabel,
|
||||
Header as SidebarHeader,
|
||||
Input as SidebarInput,
|
||||
Inset as SidebarInset,
|
||||
Menu as SidebarMenu,
|
||||
MenuAction as SidebarMenuAction,
|
||||
MenuBadge as SidebarMenuBadge,
|
||||
MenuButton as SidebarMenuButton,
|
||||
MenuItem as SidebarMenuItem,
|
||||
MenuSkeleton as SidebarMenuSkeleton,
|
||||
MenuSub as SidebarMenuSub,
|
||||
MenuSubButton as SidebarMenuSubButton,
|
||||
MenuSubItem as SidebarMenuSubItem,
|
||||
Provider as SidebarProvider,
|
||||
Rail as SidebarRail,
|
||||
Separator as SidebarSeparator,
|
||||
Trigger as SidebarTrigger,
|
||||
Trigger,
|
||||
useSidebar
|
||||
};
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
<script lang="ts">
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-sidebar="content"
|
||||
class={cn(
|
||||
bind:this={ref}
|
||||
data-sidebar="content"
|
||||
class={cn(
|
||||
'flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<script lang="ts">
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-sidebar="footer"
|
||||
class={cn('flex flex-col gap-2 p-2', className)}
|
||||
{...restProps}
|
||||
bind:this={ref}
|
||||
data-sidebar="footer"
|
||||
class={cn('flex flex-col gap-2 p-2', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {Snippet} from 'svelte';
|
||||
import type {HTMLButtonAttributes} from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { Snippet } from 'svelte';
|
||||
import type { HTMLButtonAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
child,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLButtonAttributes> & {
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
} = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
child,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLButtonAttributes> & {
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
} = $props();
|
||||
|
||||
const propObj = $derived({
|
||||
class: cn(
|
||||
'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
// Increases the hit area of the button on mobile.
|
||||
'after:absolute after:-inset-2 after:md:hidden',
|
||||
'group-data-[collapsible=icon]:hidden',
|
||||
className
|
||||
),
|
||||
'data-sidebar': 'group-action',
|
||||
...restProps
|
||||
});
|
||||
const propObj = $derived({
|
||||
class: cn(
|
||||
'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
// Increases the hit area of the button on mobile.
|
||||
'after:absolute after:-inset-2 after:md:hidden',
|
||||
'group-data-[collapsible=icon]:hidden',
|
||||
className
|
||||
),
|
||||
'data-sidebar': 'group-action',
|
||||
...restProps
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if child}
|
||||
{@render child({props: propObj})}
|
||||
{@render child({ props: propObj })}
|
||||
{:else}
|
||||
<button bind:this={ref} {...propObj}>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
<button bind:this={ref} {...propObj}>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-sidebar="group-content"
|
||||
class={cn('w-full text-sm', className)}
|
||||
{...restProps}
|
||||
bind:this={ref}
|
||||
data-sidebar="group-content"
|
||||
class={cn('w-full text-sm', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {Snippet} from 'svelte';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { Snippet } from 'svelte';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
children,
|
||||
child,
|
||||
class: className,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> & {
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
} = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
children,
|
||||
child,
|
||||
class: className,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> & {
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
} = $props();
|
||||
|
||||
const mergedProps = $derived({
|
||||
class: cn(
|
||||
'text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-none transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',
|
||||
className
|
||||
),
|
||||
'data-sidebar': 'group-label',
|
||||
...restProps
|
||||
});
|
||||
const mergedProps = $derived({
|
||||
class: cn(
|
||||
'text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-none transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',
|
||||
className
|
||||
),
|
||||
'data-sidebar': 'group-label',
|
||||
...restProps
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if child}
|
||||
{@render child({props: mergedProps})}
|
||||
{@render child({ props: mergedProps })}
|
||||
{:else}
|
||||
<div bind:this={ref} {...mergedProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
<div bind:this={ref} {...mergedProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<script lang="ts">
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-sidebar="group"
|
||||
class={cn('relative flex w-full min-w-0 flex-col p-2', className)}
|
||||
{...restProps}
|
||||
bind:this={ref}
|
||||
data-sidebar="group"
|
||||
class={cn('relative flex w-full min-w-0 flex-col p-2', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<script lang="ts">
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-sidebar="header"
|
||||
class={cn('flex flex-col gap-2 p-2', className)}
|
||||
{...restProps}
|
||||
bind:this={ref}
|
||||
data-sidebar="header"
|
||||
class={cn('flex flex-col gap-2 p-2', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
<script lang="ts">
|
||||
import {Input} from '$lib/components/ui/input/index.js';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {ComponentProps} from 'svelte';
|
||||
import { Input } from '$lib/components/ui/input/index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { ComponentProps } from 'svelte';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
value = $bindable(''),
|
||||
class: className,
|
||||
...restProps
|
||||
}: ComponentProps<typeof Input> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
value = $bindable(''),
|
||||
class: className,
|
||||
...restProps
|
||||
}: ComponentProps<typeof Input> = $props();
|
||||
</script>
|
||||
|
||||
<Input
|
||||
bind:ref
|
||||
bind:value
|
||||
data-sidebar="input"
|
||||
class={cn(
|
||||
bind:ref
|
||||
bind:value
|
||||
data-sidebar="input"
|
||||
class={cn(
|
||||
'h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
{...restProps}
|
||||
/>
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
</script>
|
||||
|
||||
<main
|
||||
bind:this={ref}
|
||||
class={cn(
|
||||
bind:this={ref}
|
||||
class={cn(
|
||||
'relative flex min-h-svh flex-1 flex-col bg-background',
|
||||
'peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</main>
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {Snippet} from 'svelte';
|
||||
import type {HTMLButtonAttributes} from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { Snippet } from 'svelte';
|
||||
import type { HTMLButtonAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
showOnHover = false,
|
||||
children,
|
||||
child,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLButtonAttributes> & {
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
showOnHover?: boolean;
|
||||
} = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
showOnHover = false,
|
||||
children,
|
||||
child,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLButtonAttributes> & {
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
showOnHover?: boolean;
|
||||
} = $props();
|
||||
|
||||
const mergedProps = $derived({
|
||||
class: cn(
|
||||
'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
// Increases the hit area of the button on mobile.
|
||||
'after:absolute after:-inset-2 after:md:hidden',
|
||||
'peer-data-[size=sm]/menu-button:top-1',
|
||||
'peer-data-[size=default]/menu-button:top-1.5',
|
||||
'peer-data-[size=lg]/menu-button:top-2.5',
|
||||
'group-data-[collapsible=icon]:hidden',
|
||||
showOnHover &&
|
||||
'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0',
|
||||
className
|
||||
),
|
||||
'data-sidebar': 'menu-action',
|
||||
...restProps
|
||||
});
|
||||
const mergedProps = $derived({
|
||||
class: cn(
|
||||
'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
// Increases the hit area of the button on mobile.
|
||||
'after:absolute after:-inset-2 after:md:hidden',
|
||||
'peer-data-[size=sm]/menu-button:top-1',
|
||||
'peer-data-[size=default]/menu-button:top-1.5',
|
||||
'peer-data-[size=lg]/menu-button:top-2.5',
|
||||
'group-data-[collapsible=icon]:hidden',
|
||||
showOnHover &&
|
||||
'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0',
|
||||
className
|
||||
),
|
||||
'data-sidebar': 'menu-action',
|
||||
...restProps
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if child}
|
||||
{@render child({props: mergedProps})}
|
||||
{@render child({ props: mergedProps })}
|
||||
{:else}
|
||||
<button bind:this={ref} {...mergedProps}>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
<button bind:this={ref} {...mergedProps}>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-sidebar="menu-badge"
|
||||
class={cn(
|
||||
bind:this={ref}
|
||||
data-sidebar="menu-badge"
|
||||
class={cn(
|
||||
'pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground',
|
||||
'peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground',
|
||||
'peer-data-[size=sm]/menu-button:top-1',
|
||||
@@ -23,7 +23,7 @@
|
||||
'group-data-[collapsible=icon]:hidden',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
<script lang="ts" module>
|
||||
import {type VariantProps, tv} from 'tailwind-variants';
|
||||
import { type VariantProps, tv } from 'tailwind-variants';
|
||||
|
||||
export const sidebarMenuButtonVariants = tv({
|
||||
base: 'peer/menu-button ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none transition-[width,height,padding] focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:font-medium group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
|
||||
outline:
|
||||
'bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]'
|
||||
},
|
||||
size: {
|
||||
default: 'h-8 text-sm',
|
||||
sm: 'h-7 text-xs',
|
||||
lg: 'h-12 text-sm group-data-[collapsible=icon]:!p-0'
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
size: 'default'
|
||||
}
|
||||
});
|
||||
export const sidebarMenuButtonVariants = tv({
|
||||
base: 'peer/menu-button ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none transition-[width,height,padding] focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:font-medium group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
|
||||
outline:
|
||||
'bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]'
|
||||
},
|
||||
size: {
|
||||
default: 'h-8 text-sm',
|
||||
sm: 'h-7 text-xs',
|
||||
lg: 'h-12 text-sm group-data-[collapsible=icon]:!p-0'
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
size: 'default'
|
||||
}
|
||||
});
|
||||
|
||||
export type SidebarMenuButtonVariant = VariantProps<typeof sidebarMenuButtonVariants>['variant'];
|
||||
export type SidebarMenuButtonSize = VariantProps<typeof sidebarMenuButtonVariants>['size'];
|
||||
export type SidebarMenuButtonVariant = VariantProps<typeof sidebarMenuButtonVariants>['variant'];
|
||||
export type SidebarMenuButtonSize = VariantProps<typeof sidebarMenuButtonVariants>['size'];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import * as Tooltip from '$lib/components/ui/tooltip/index.js';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import {type WithElementRef, type WithoutChildrenOrChild, mergeProps} from 'bits-ui';
|
||||
import type {ComponentProps, Snippet} from 'svelte';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import {useSidebar} from './context.svelte.js';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip/index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import { type WithElementRef, type WithoutChildrenOrChild, mergeProps } from 'bits-ui';
|
||||
import type { ComponentProps, Snippet } from 'svelte';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { useSidebar } from './context.svelte.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
child,
|
||||
variant = 'default',
|
||||
size = 'default',
|
||||
isActive = false,
|
||||
tooltipContent,
|
||||
tooltipContentProps,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement> & {
|
||||
isActive?: boolean;
|
||||
variant?: SidebarMenuButtonVariant;
|
||||
size?: SidebarMenuButtonSize;
|
||||
tooltipContent?: Snippet;
|
||||
tooltipContentProps?: WithoutChildrenOrChild<ComponentProps<typeof Tooltip.Content>>;
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
} = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
child,
|
||||
variant = 'default',
|
||||
size = 'default',
|
||||
isActive = false,
|
||||
tooltipContent,
|
||||
tooltipContentProps,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement> & {
|
||||
isActive?: boolean;
|
||||
variant?: SidebarMenuButtonVariant;
|
||||
size?: SidebarMenuButtonSize;
|
||||
tooltipContent?: Snippet;
|
||||
tooltipContentProps?: WithoutChildrenOrChild<ComponentProps<typeof Tooltip.Content>>;
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
} = $props();
|
||||
|
||||
const sidebar = useSidebar();
|
||||
const sidebar = useSidebar();
|
||||
|
||||
const buttonProps = $derived({
|
||||
class: cn(sidebarMenuButtonVariants({variant, size}), className),
|
||||
'data-sidebar': 'menu-button',
|
||||
'data-size': size,
|
||||
'data-active': isActive,
|
||||
...restProps
|
||||
});
|
||||
const buttonProps = $derived({
|
||||
class: cn(sidebarMenuButtonVariants({ variant, size }), className),
|
||||
'data-sidebar': 'menu-button',
|
||||
'data-size': size,
|
||||
'data-active': isActive,
|
||||
...restProps
|
||||
});
|
||||
</script>
|
||||
|
||||
{#snippet Button({props}: { props?: Record<string, unknown> })}
|
||||
{@const mergedProps = mergeProps(buttonProps, props)}
|
||||
{#if child}
|
||||
{@render child({props: mergedProps})}
|
||||
{:else}
|
||||
<button bind:this={ref} {...mergedProps}>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
{/if}
|
||||
{#snippet Button({ props }: { props?: Record<string, unknown> })}
|
||||
{@const mergedProps = mergeProps(buttonProps, props)}
|
||||
{#if child}
|
||||
{@render child({ props: mergedProps })}
|
||||
{:else}
|
||||
<button bind:this={ref} {...mergedProps}>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
{/if}
|
||||
{/snippet}
|
||||
|
||||
{#if !tooltipContent}
|
||||
{@render Button({})}
|
||||
{@render Button({})}
|
||||
{:else}
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
{#snippet child({props})}
|
||||
{@render Button({props})}
|
||||
{/snippet}
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content
|
||||
side="right"
|
||||
align="center"
|
||||
hidden={sidebar.state !== 'collapsed' || sidebar.isMobile}
|
||||
children={tooltipContent}
|
||||
{...tooltipContentProps}
|
||||
/>
|
||||
</Tooltip.Root>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
{#snippet child({ props })}
|
||||
{@render Button({ props })}
|
||||
{/snippet}
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content
|
||||
side="right"
|
||||
align="center"
|
||||
hidden={sidebar.state !== 'collapsed' || sidebar.isMobile}
|
||||
children={tooltipContent}
|
||||
{...tooltipContentProps}
|
||||
/>
|
||||
</Tooltip.Root>
|
||||
{/if}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLLIElement>, HTMLLIElement> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLLIElement>, HTMLLIElement> = $props();
|
||||
</script>
|
||||
|
||||
<li
|
||||
bind:this={ref}
|
||||
data-sidebar="menu-item"
|
||||
class={cn('group/menu-item relative', className)}
|
||||
{...restProps}
|
||||
bind:this={ref}
|
||||
data-sidebar="menu-item"
|
||||
class={cn('group/menu-item relative', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</li>
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
<script lang="ts">
|
||||
import {Skeleton} from '$lib/components/ui/skeleton/index.js';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import { Skeleton } from '$lib/components/ui/skeleton/index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
showIcon = false,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> & {
|
||||
showIcon?: boolean;
|
||||
} = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
showIcon = false,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> & {
|
||||
showIcon?: boolean;
|
||||
} = $props();
|
||||
|
||||
// Random width between 50% and 90%
|
||||
const width = `${Math.floor(Math.random() * 40) + 50}%`;
|
||||
// Random width between 50% and 90%
|
||||
const width = `${Math.floor(Math.random() * 40) + 50}%`;
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-sidebar="menu-skeleton"
|
||||
class={cn('flex h-8 items-center gap-2 rounded-md px-2', className)}
|
||||
{...restProps}
|
||||
bind:this={ref}
|
||||
data-sidebar="menu-skeleton"
|
||||
class={cn('flex h-8 items-center gap-2 rounded-md px-2', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{#if showIcon}
|
||||
<Skeleton class="size-4 rounded-md" data-sidebar="menu-skeleton-icon"/>
|
||||
{/if}
|
||||
<Skeleton
|
||||
class="h-4 max-w-[var(--skeleton-width)] flex-1"
|
||||
data-sidebar="menu-skeleton-text"
|
||||
style="--skeleton-width: {width};"
|
||||
/>
|
||||
{@render children?.()}
|
||||
{#if showIcon}
|
||||
<Skeleton class="size-4 rounded-md" data-sidebar="menu-skeleton-icon" />
|
||||
{/if}
|
||||
<Skeleton
|
||||
class="h-4 max-w-[var(--skeleton-width)] flex-1"
|
||||
data-sidebar="menu-skeleton-text"
|
||||
style="--skeleton-width: {width};"
|
||||
/>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {Snippet} from 'svelte';
|
||||
import type {HTMLAnchorAttributes} from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { Snippet } from 'svelte';
|
||||
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
children,
|
||||
child,
|
||||
class: className,
|
||||
size = 'md',
|
||||
isActive,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAnchorAttributes> & {
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
size?: 'sm' | 'md';
|
||||
isActive?: boolean;
|
||||
} = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
children,
|
||||
child,
|
||||
class: className,
|
||||
size = 'md',
|
||||
isActive,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAnchorAttributes> & {
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
size?: 'sm' | 'md';
|
||||
isActive?: boolean;
|
||||
} = $props();
|
||||
|
||||
const mergedProps = $derived({
|
||||
class: cn(
|
||||
'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',
|
||||
size === 'sm' && 'text-xs',
|
||||
size === 'md' && 'text-sm',
|
||||
'group-data-[collapsible=icon]:hidden',
|
||||
className
|
||||
),
|
||||
'data-sidebar': 'menu-sub-button',
|
||||
'data-size': size,
|
||||
'data-active': isActive,
|
||||
...restProps
|
||||
});
|
||||
const mergedProps = $derived({
|
||||
class: cn(
|
||||
'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',
|
||||
size === 'sm' && 'text-xs',
|
||||
size === 'md' && 'text-sm',
|
||||
'group-data-[collapsible=icon]:hidden',
|
||||
className
|
||||
),
|
||||
'data-sidebar': 'menu-sub-button',
|
||||
'data-size': size,
|
||||
'data-active': isActive,
|
||||
...restProps
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if child}
|
||||
{@render child({props: mergedProps})}
|
||||
{@render child({ props: mergedProps })}
|
||||
{:else}
|
||||
<a bind:this={ref} {...mergedProps}>
|
||||
{@render children?.()}
|
||||
</a>
|
||||
<a bind:this={ref} {...mergedProps}>
|
||||
{@render children?.()}
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<script lang="ts">
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLLIElement>> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLLIElement>> = $props();
|
||||
</script>
|
||||
|
||||
<li bind:this={ref} data-sidebar="menu-sub-item" {...restProps}>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</li>
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLUListElement>> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLUListElement>> = $props();
|
||||
</script>
|
||||
|
||||
<ul
|
||||
bind:this={ref}
|
||||
data-sidebar="menu-sub"
|
||||
class={cn(
|
||||
bind:this={ref}
|
||||
data-sidebar="menu-sub"
|
||||
class={cn(
|
||||
'mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5',
|
||||
'group-data-[collapsible=icon]:hidden',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</ul>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLUListElement>, HTMLUListElement> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLUListElement>, HTMLUListElement> = $props();
|
||||
</script>
|
||||
|
||||
<ul
|
||||
bind:this={ref}
|
||||
data-sidebar="menu"
|
||||
class={cn('flex w-full min-w-0 flex-col gap-1', className)}
|
||||
{...restProps}
|
||||
bind:this={ref}
|
||||
data-sidebar="menu"
|
||||
class={cn('flex w-full min-w-0 flex-col gap-1', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</ul>
|
||||
|
||||
@@ -1,54 +1,53 @@
|
||||
<script lang="ts">
|
||||
import * as Tooltip from '$lib/components/ui/tooltip/index.js';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import {
|
||||
SIDEBAR_COOKIE_MAX_AGE,
|
||||
SIDEBAR_COOKIE_NAME,
|
||||
SIDEBAR_WIDTH,
|
||||
SIDEBAR_WIDTH_ICON
|
||||
} from './constants.js';
|
||||
import {setSidebar} from './context.svelte.js';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip/index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import {
|
||||
SIDEBAR_COOKIE_MAX_AGE,
|
||||
SIDEBAR_COOKIE_NAME,
|
||||
SIDEBAR_WIDTH,
|
||||
SIDEBAR_WIDTH_ICON
|
||||
} from './constants.js';
|
||||
import { setSidebar } from './context.svelte.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
open = $bindable(true),
|
||||
onOpenChange = () => {
|
||||
},
|
||||
class: className,
|
||||
style,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||
open?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
} = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
open = $bindable(true),
|
||||
onOpenChange = () => {},
|
||||
class: className,
|
||||
style,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||
open?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
} = $props();
|
||||
|
||||
const sidebar = setSidebar({
|
||||
open: () => open,
|
||||
setOpen: (value: boolean) => {
|
||||
open = value;
|
||||
onOpenChange(value);
|
||||
const sidebar = setSidebar({
|
||||
open: () => open,
|
||||
setOpen: (value: boolean) => {
|
||||
open = value;
|
||||
onOpenChange(value);
|
||||
|
||||
// This sets the cookie to keep the sidebar state.
|
||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
||||
}
|
||||
});
|
||||
// This sets the cookie to keep the sidebar state.
|
||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:window onkeydown={sidebar.handleShortcutKeydown}/>
|
||||
<svelte:window onkeydown={sidebar.handleShortcutKeydown} />
|
||||
|
||||
<Tooltip.Provider delayDuration={0}>
|
||||
<div
|
||||
style="--sidebar-width: {SIDEBAR_WIDTH}; --sidebar-width-icon: {SIDEBAR_WIDTH_ICON}; {style}"
|
||||
class={cn(
|
||||
<div
|
||||
style="--sidebar-width: {SIDEBAR_WIDTH}; --sidebar-width-icon: {SIDEBAR_WIDTH_ICON}; {style}"
|
||||
class={cn(
|
||||
'group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar',
|
||||
className
|
||||
)}
|
||||
bind:this={ref}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
bind:this={ref}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</Tooltip.Provider>
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
<script lang="ts">
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import {useSidebar} from './context.svelte.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { useSidebar } from './context.svelte.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement> = $props();
|
||||
|
||||
const sidebar = useSidebar();
|
||||
const sidebar = useSidebar();
|
||||
</script>
|
||||
|
||||
<button
|
||||
bind:this={ref}
|
||||
data-sidebar="rail"
|
||||
aria-label="Toggle Sidebar"
|
||||
tabIndex={-1}
|
||||
onclick={() => sidebar.toggle()}
|
||||
title="Toggle Sidebar"
|
||||
class={cn(
|
||||
bind:this={ref}
|
||||
data-sidebar="rail"
|
||||
aria-label="Toggle Sidebar"
|
||||
tabIndex={-1}
|
||||
onclick={() => sidebar.toggle()}
|
||||
title="Toggle Sidebar"
|
||||
class={cn(
|
||||
'absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex',
|
||||
'[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize',
|
||||
'[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize',
|
||||
@@ -30,7 +30,7 @@
|
||||
'[[data-side=right][data-collapsible=offcanvas]_&]:-left-2',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
{@render children?.()}
|
||||
</button>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<script lang="ts">
|
||||
import {Separator} from '$lib/components/ui/separator/index.js';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {ComponentProps} from 'svelte';
|
||||
import { Separator } from '$lib/components/ui/separator/index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { ComponentProps } from 'svelte';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
...restProps
|
||||
}: ComponentProps<typeof Separator> = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
...restProps
|
||||
}: ComponentProps<typeof Separator> = $props();
|
||||
</script>
|
||||
|
||||
<Separator
|
||||
bind:ref
|
||||
data-sidebar="separator"
|
||||
class={cn('mx-2 w-auto bg-sidebar-border', className)}
|
||||
{...restProps}
|
||||
bind:ref
|
||||
data-sidebar="separator"
|
||||
class={cn('mx-2 w-auto bg-sidebar-border', className)}
|
||||
{...restProps}
|
||||
/>
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
<script lang="ts">
|
||||
import {Button} from '$lib/components/ui/button/index.js';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import PanelLeft from '@lucide/svelte/icons/panel-left';
|
||||
import type {ComponentProps} from 'svelte';
|
||||
import {useSidebar} from './context.svelte.js';
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import PanelLeft from '@lucide/svelte/icons/panel-left';
|
||||
import type { ComponentProps } from 'svelte';
|
||||
import { useSidebar } from './context.svelte.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
onclick,
|
||||
...restProps
|
||||
}: ComponentProps<typeof Button> & {
|
||||
onclick?: (e: MouseEvent) => void;
|
||||
} = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
onclick,
|
||||
...restProps
|
||||
}: ComponentProps<typeof Button> & {
|
||||
onclick?: (e: MouseEvent) => void;
|
||||
} = $props();
|
||||
|
||||
const sidebar = useSidebar();
|
||||
const sidebar = useSidebar();
|
||||
</script>
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
onclick={(e) => {
|
||||
type="button"
|
||||
onclick={(e) => {
|
||||
onclick?.(e);
|
||||
sidebar.toggle();
|
||||
}}
|
||||
data-sidebar="trigger"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
class={cn('h-7 w-7', className)}
|
||||
{...restProps}
|
||||
data-sidebar="trigger"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
class={cn('h-7 w-7', className)}
|
||||
{...restProps}
|
||||
>
|
||||
<PanelLeft/>
|
||||
<span class="sr-only">Toggle Sidebar</span>
|
||||
<PanelLeft />
|
||||
<span class="sr-only">Toggle Sidebar</span>
|
||||
</Button>
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
<script lang="ts">
|
||||
import * as Sheet from '$lib/components/ui/sheet/index.js';
|
||||
import {cn} from '$lib/utils.js';
|
||||
import type {WithElementRef} from 'bits-ui';
|
||||
import type {HTMLAttributes} from 'svelte/elements';
|
||||
import {SIDEBAR_WIDTH_MOBILE} from './constants.js';
|
||||
import {useSidebar} from './context.svelte.js';
|
||||
import * as Sheet from '$lib/components/ui/sheet/index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { SIDEBAR_WIDTH_MOBILE } from './constants.js';
|
||||
import { useSidebar } from './context.svelte.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
side = 'left',
|
||||
variant = 'sidebar',
|
||||
collapsible = 'offcanvas',
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||
side?: 'left' | 'right';
|
||||
variant?: 'sidebar' | 'floating' | 'inset';
|
||||
collapsible?: 'offcanvas' | 'icon' | 'none';
|
||||
} = $props();
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
side = 'left',
|
||||
variant = 'sidebar',
|
||||
collapsible = 'offcanvas',
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||
side?: 'left' | 'right';
|
||||
variant?: 'sidebar' | 'floating' | 'inset';
|
||||
collapsible?: 'offcanvas' | 'icon' | 'none';
|
||||
} = $props();
|
||||
|
||||
const sidebar = useSidebar();
|
||||
const sidebar = useSidebar();
|
||||
</script>
|
||||
|
||||
{#if collapsible === 'none'}
|
||||
<div
|
||||
class={cn(
|
||||
<div
|
||||
class={cn(
|
||||
'flex h-full w-[var(--sidebar-width)] flex-col bg-sidebar text-sidebar-foreground',
|
||||
className
|
||||
)}
|
||||
bind:this={ref}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
bind:this={ref}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
{:else if sidebar.isMobile}
|
||||
<Sheet.Root bind:open={() => sidebar.openMobile, (v) => sidebar.setOpenMobile(v)} {...restProps}>
|
||||
<Sheet.Content
|
||||
data-sidebar="sidebar"
|
||||
data-mobile="true"
|
||||
class="w-[var(--sidebar-width)] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
|
||||
style="--sidebar-width: {SIDEBAR_WIDTH_MOBILE};"
|
||||
{side}
|
||||
>
|
||||
<div class="flex h-full w-full flex-col">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</Sheet.Content>
|
||||
</Sheet.Root>
|
||||
<Sheet.Root bind:open={() => sidebar.openMobile, (v) => sidebar.setOpenMobile(v)} {...restProps}>
|
||||
<Sheet.Content
|
||||
data-sidebar="sidebar"
|
||||
data-mobile="true"
|
||||
class="w-[var(--sidebar-width)] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
|
||||
style="--sidebar-width: {SIDEBAR_WIDTH_MOBILE};"
|
||||
{side}
|
||||
>
|
||||
<div class="flex h-full w-full flex-col">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</Sheet.Content>
|
||||
</Sheet.Root>
|
||||
{:else}
|
||||
<div
|
||||
bind:this={ref}
|
||||
class="group peer hidden text-sidebar-foreground md:block"
|
||||
data-state={sidebar.state}
|
||||
data-collapsible={sidebar.state === 'collapsed' ? collapsible : ''}
|
||||
data-variant={variant}
|
||||
data-side={side}
|
||||
>
|
||||
<!-- This is what handles the sidebar gap on desktop -->
|
||||
<div
|
||||
class={cn(
|
||||
<div
|
||||
bind:this={ref}
|
||||
class="group peer hidden text-sidebar-foreground md:block"
|
||||
data-state={sidebar.state}
|
||||
data-collapsible={sidebar.state === 'collapsed' ? collapsible : ''}
|
||||
data-variant={variant}
|
||||
data-side={side}
|
||||
>
|
||||
<!-- This is what handles the sidebar gap on desktop -->
|
||||
<div
|
||||
class={cn(
|
||||
'relative h-svh w-[var(--sidebar-width)] bg-transparent transition-[width] duration-200 ease-linear',
|
||||
'group-data-[collapsible=offcanvas]:w-0',
|
||||
'group-data-[side=right]:rotate-180',
|
||||
@@ -67,9 +67,9 @@
|
||||
? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]'
|
||||
: 'group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)]'
|
||||
)}
|
||||
></div>
|
||||
<div
|
||||
class={cn(
|
||||
></div>
|
||||
<div
|
||||
class={cn(
|
||||
'fixed inset-y-0 z-10 hidden h-svh w-[var(--sidebar-width)] transition-[left,right,width] duration-200 ease-linear md:flex',
|
||||
side === 'left'
|
||||
? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
|
||||
@@ -80,14 +80,14 @@
|
||||
: 'group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)] group-data-[side=left]:border-r group-data-[side=right]:border-l',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
<div
|
||||
data-sidebar="sidebar"
|
||||
class="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{...restProps}
|
||||
>
|
||||
<div
|
||||
data-sidebar="sidebar"
|
||||
class="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user