build: Update to ShadCN-Svelte V5
This commit is contained in:
parent
36837843c0
commit
07ce8dea90
@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "https://shadcn-svelte.com/schema.json",
|
||||
"$schema": "https://next.shadcn-svelte.com/schema.json",
|
||||
"style": "new-york",
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
@ -8,7 +8,10 @@
|
||||
},
|
||||
"aliases": {
|
||||
"components": "$lib/components",
|
||||
"utils": "$lib/utils"
|
||||
"utils": "$lib/utils",
|
||||
"ui": "$lib/components/ui",
|
||||
"hooks": "$lib/hooks"
|
||||
},
|
||||
"typescript": true
|
||||
"typescript": true,
|
||||
"registry": "https://next.shadcn-svelte.com/registry"
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"typescript": "^5.0.0",
|
||||
"typescript-eslint": "^8.20.0"
|
||||
},
|
||||
@ -49,11 +50,11 @@
|
||||
"autoprefixer": "^10.4.20",
|
||||
"better-auth": "^1.1.16",
|
||||
"better-sqlite3": "^11.8.1",
|
||||
"bits-ui": "0.22.0",
|
||||
"bits-ui": "^1.3.5",
|
||||
"cassandra-driver": "^4.7.2",
|
||||
"dotenv": "^16.4.7",
|
||||
"express": "^4.21.2",
|
||||
"lucide-svelte": "^0.474.0",
|
||||
"lucide-svelte": "^0.477.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"markdown-it-highlightjs": "^4.2.0",
|
||||
"markdown-it-link-attributes": "^4.0.1",
|
||||
@ -63,7 +64,7 @@
|
||||
"socket.io-client": "^4.8.1",
|
||||
"svelte-radix": "^2.0.1",
|
||||
"sveltekit-superforms": "^2.23.1",
|
||||
"tailwind-merge": "^3.0.1",
|
||||
"tailwind-merge": "^3.0.2",
|
||||
"tailwind-variants": "^0.3.1",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"tsm": "^2.3.0",
|
||||
|
55
src/app.css
55
src/app.css
@ -1,5 +1,3 @@
|
||||
@import '../node_modules/highlight.js/styles/github-dark.min.css';
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@ -15,45 +13,62 @@
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 20 14.3% 4.1%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 20 14.3% 4.1%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 20 14.3% 4.1%;
|
||||
--primary: 24 9.8% 10%;
|
||||
--primary-foreground: 60 9.1% 97.8%;
|
||||
--secondary: 240 6% 90%;
|
||||
--secondary-foreground: 24 9.8% 10%;
|
||||
--muted: 60 4.8% 95.9%;
|
||||
--muted-foreground: 25 5.3% 44.7%;
|
||||
--accent: 60 4.8% 95.9%;
|
||||
--accent-foreground: 24 9.8% 10%;
|
||||
--destructive: 0 72.22% 50.59%;
|
||||
--destructive-foreground: 60 9.1% 97.8%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 20 14.3% 4.1%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 20 14.3% 4.1%;
|
||||
--border: 20 5.9% 90%;
|
||||
--input: 20 5.9% 90%;
|
||||
--primary: 24 9.8% 10%;
|
||||
--primary-foreground: 60 9.1% 97.8%;
|
||||
--secondary: 60 4.8% 95.9%;
|
||||
--secondary-foreground: 24 9.8% 10%;
|
||||
--accent: 60 4.8% 95.9%;
|
||||
--accent-foreground: 24 9.8% 10%;
|
||||
--destructive: 0 72.2% 50.6%;
|
||||
--destructive-foreground: 60 9.1% 97.8%;
|
||||
--ring: 20 14.3% 4.1%;
|
||||
--radius: 0.5rem;
|
||||
--sidebar-background: 0 0% 98%;
|
||||
--sidebar-foreground: 240 5.3% 26.1%;
|
||||
--sidebar-primary: 240 5.9% 10%;
|
||||
--sidebar-primary-foreground: 0 0% 98%;
|
||||
--sidebar-accent: 240 4.8% 95.9%;
|
||||
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||
--sidebar-border: 220 13% 91%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 20 14.3% 4.1%;
|
||||
--foreground: 60 9.1% 97.8%;
|
||||
--card: 20 14.3% 4.1%;
|
||||
--card-foreground: 60 9.1% 97.8%;
|
||||
--muted: 12 6.5% 15.1%;
|
||||
--muted-foreground: 24 5.4% 63.9%;
|
||||
--popover: 20 14.3% 4.1%;
|
||||
--popover-foreground: 60 9.1% 97.8%;
|
||||
--card: 20 14.3% 4.1%;
|
||||
--card-foreground: 60 9.1% 97.8%;
|
||||
--border: 12 6.5% 15.1%;
|
||||
--input: 12 6.5% 15.1%;
|
||||
--primary: 60 9.1% 97.8%;
|
||||
--primary-foreground: 24 9.8% 10%;
|
||||
--secondary: 12 6.5% 15.1%;
|
||||
--secondary-foreground: 60 9.1% 97.8%;
|
||||
--muted: 12 6.5% 15.1%;
|
||||
--muted-foreground: 24 5.4% 63.9%;
|
||||
--accent: 12 6.5% 15.1%;
|
||||
--accent-foreground: 60 9.1% 97.8%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 60 9.1% 97.8%;
|
||||
--border: 12 6.5% 15.1%;
|
||||
--input: 12 6.5% 15.1%;
|
||||
--ring: 24 5.7% 82.9%;
|
||||
--sidebar-background: 240 5.9% 10%;
|
||||
--sidebar-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-primary: 224.3 76.3% 48%;
|
||||
--sidebar-primary-foreground: 0 0% 100%;
|
||||
--sidebar-accent: 240 3.7% 15.9%;
|
||||
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-border: 240 3.7% 15.9%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
i: number;
|
||||
}
|
||||
|
||||
let { message, imageSrc, user, timestamp, uid, open = $bindable(), closeDialogs, i }: TypeMessage & Props = $props();
|
||||
let { message, imageSrc, user, timestamp, uid, open = $bindable(false), closeDialogs, i }: TypeMessage & Props = $props();
|
||||
|
||||
function copy(itemName: string, content: string | number) {
|
||||
navigator.clipboard
|
||||
|
@ -6,14 +6,16 @@
|
||||
import { toggleMode } from 'mode-watcher';
|
||||
</script>
|
||||
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger class="ml-auto" onclick={toggleMode}>
|
||||
<div class="size-9 {buttonVariants({ variant: 'secondary' })}" style="padding: 0;">
|
||||
<Sun class="size-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon class="absolute size-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
</div>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content>
|
||||
<p>Toggle theme</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
<Tooltip.Provider>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger class="ml-auto" onclick={toggleMode}>
|
||||
<div class="size-9 {buttonVariants({ variant: 'secondary' })}" style="padding: 0;">
|
||||
<Sun class="size-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon class="absolute size-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
</div>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content>
|
||||
<p>Toggle theme</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Provider>
|
||||
|
@ -9,6 +9,6 @@
|
||||
const { children, class: className = '' }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="{className} prose prose-stone prose-blue !max-w-full dark:prose-invert prose-pre:w-fit prose-pre:max-w-[95%]">
|
||||
<div class="{className} prose prose-stone prose-blue dark:prose-invert prose-pre:w-fit prose-pre:max-w-[95%] !max-w-full">
|
||||
{@render children()}
|
||||
</div>
|
||||
|
@ -1,13 +1,40 @@
|
||||
<script lang="ts">
|
||||
import { type Variant, badgeVariants } from './index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
<script lang="ts" module>
|
||||
import { type VariantProps, tv } from 'tailwind-variants';
|
||||
export const badgeVariants = tv({
|
||||
base: 'focus:ring-ring inline-flex select-none items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2',
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'bg-primary text-primary-foreground hover:bg-primary/80 border-transparent shadow',
|
||||
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent',
|
||||
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent shadow',
|
||||
outline: 'text-foreground',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
},
|
||||
});
|
||||
|
||||
let className: string | undefined | null = undefined;
|
||||
export let href: string | undefined = undefined;
|
||||
export let variant: Variant = 'default';
|
||||
export { className as class };
|
||||
export type BadgeVariant = VariantProps<typeof badgeVariants>['variant'];
|
||||
</script>
|
||||
|
||||
<svelte:element this={href ? 'a' : 'span'} {href} class={cn(badgeVariants({ variant, className }))} {...$$restProps}>
|
||||
<slot />
|
||||
<script lang="ts">
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
href,
|
||||
class: className,
|
||||
variant = 'default',
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAnchorAttributes> & {
|
||||
variant?: BadgeVariant;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<svelte:element this={href ? 'a' : 'span'} bind:this={ref} {href} class={cn(badgeVariants({ variant }), className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</svelte:element>
|
||||
|
@ -1,19 +1,2 @@
|
||||
import { type VariantProps, tv } from 'tailwind-variants';
|
||||
|
||||
export { default as Badge } from './badge.svelte';
|
||||
export const badgeVariants = tv({
|
||||
base: 'focus:ring-ring inline-flex select-none items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2',
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'bg-primary text-primary-foreground hover:bg-primary/80 border-transparent shadow',
|
||||
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent',
|
||||
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent shadow',
|
||||
outline: 'text-foreground',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
},
|
||||
});
|
||||
|
||||
export type Variant = VariantProps<typeof badgeVariants>['variant'];
|
||||
export { badgeVariants, type BadgeVariant } from './badge.svelte';
|
||||
|
@ -1,18 +1,63 @@
|
||||
<script lang="ts">
|
||||
import { Button as ButtonPrimitive } from 'bits-ui';
|
||||
import { type Events, type Props, buttonVariants } from './index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
<script lang="ts" module>
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
||||
import { type VariantProps, tv } from 'tailwind-variants';
|
||||
|
||||
type $$Props = Props;
|
||||
type $$Events = Events;
|
||||
export const buttonVariants = tv({
|
||||
base: 'focus-visible:ring-ring inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow',
|
||||
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm',
|
||||
outline: 'border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-sm',
|
||||
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-sm',
|
||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||
link: 'text-primary underline-offset-4 hover:underline',
|
||||
},
|
||||
size: {
|
||||
default: 'h-9 px-4 py-2',
|
||||
sm: 'h-8 rounded-md px-3 text-xs',
|
||||
lg: 'h-10 rounded-md px-8',
|
||||
icon: 'h-9 w-9',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
size: 'default',
|
||||
},
|
||||
});
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let variant: $$Props['variant'] = 'default';
|
||||
export let size: $$Props['size'] = 'default';
|
||||
export let builders: $$Props['builders'] = [];
|
||||
export { className as class };
|
||||
export type ButtonVariant = VariantProps<typeof buttonVariants>['variant'];
|
||||
export type ButtonSize = VariantProps<typeof buttonVariants>['size'];
|
||||
|
||||
export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
|
||||
WithElementRef<HTMLAnchorAttributes> & {
|
||||
variant?: ButtonVariant;
|
||||
size?: ButtonSize;
|
||||
};
|
||||
</script>
|
||||
|
||||
<ButtonPrimitive.Root {builders} class={cn(buttonVariants({ variant, size, className }))} type="button" {...$$restProps} on:click on:keydown>
|
||||
<slot />
|
||||
</ButtonPrimitive.Root>
|
||||
<script lang="ts">
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
class: className,
|
||||
variant = 'default',
|
||||
size = 'default',
|
||||
ref = $bindable(null),
|
||||
href = undefined,
|
||||
type = 'button',
|
||||
children,
|
||||
...restProps
|
||||
}: ButtonProps = $props();
|
||||
</script>
|
||||
|
||||
{#if href}
|
||||
<a bind:this={ref} class={cn(buttonVariants({ variant, size }), className)} {href} {...restProps}>
|
||||
{@render children?.()}
|
||||
</a>
|
||||
{:else}
|
||||
<button bind:this={ref} class={cn(buttonVariants({ variant, size }), className)} {type} {...restProps}>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
{/if}
|
||||
|
@ -1,48 +1,12 @@
|
||||
import type { Button as ButtonPrimitive } from 'bits-ui';
|
||||
import { type VariantProps, tv } from 'tailwind-variants';
|
||||
import Root from './button.svelte';
|
||||
|
||||
const buttonVariants = tv({
|
||||
base: 'focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50',
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow',
|
||||
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm',
|
||||
outline: 'border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-sm',
|
||||
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-sm',
|
||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||
link: 'text-primary underline-offset-4 hover:underline',
|
||||
},
|
||||
size: {
|
||||
default: 'h-9 px-4 py-2',
|
||||
sm: 'h-8 rounded-md px-3 text-xs',
|
||||
lg: 'h-10 rounded-md px-8',
|
||||
icon: 'h-9 w-9',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
size: 'default',
|
||||
},
|
||||
});
|
||||
|
||||
type Variant = VariantProps<typeof buttonVariants>['variant'];
|
||||
type Size = VariantProps<typeof buttonVariants>['size'];
|
||||
|
||||
type Props = ButtonPrimitive.Props & {
|
||||
variant?: Variant;
|
||||
size?: Size;
|
||||
};
|
||||
|
||||
type Events = ButtonPrimitive.Events;
|
||||
import Root, { type ButtonProps, type ButtonSize, type ButtonVariant, buttonVariants } from './button.svelte';
|
||||
|
||||
export {
|
||||
Root,
|
||||
type Props,
|
||||
type Events,
|
||||
type ButtonProps as Props,
|
||||
//
|
||||
Root as Button,
|
||||
type Props as ButtonProps,
|
||||
type Events as ButtonEvents,
|
||||
buttonVariants,
|
||||
type ButtonProps,
|
||||
type ButtonSize,
|
||||
type ButtonVariant,
|
||||
};
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div class={cn('p-6', className)} {...$$restProps}>
|
||||
<slot />
|
||||
<div bind:this={ref} class={cn('p-6', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLParagraphElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
|
||||
</script>
|
||||
|
||||
<p class={cn('text-sm text-muted-foreground', className)} {...$$restProps}>
|
||||
<slot />
|
||||
<p bind:this={ref} class={cn('text-sm text-muted-foreground', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</p>
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div class={cn('flex items-center p-6 pt-0', className)} {...$$restProps}>
|
||||
<slot />
|
||||
<div bind:this={ref} class={cn('flex items-center p-6 pt-0', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div class={cn('flex flex-col space-y-1.5 p-6 pb-0', className)} {...$$restProps}>
|
||||
<slot />
|
||||
<div bind:this={ref} class={cn('flex flex-col space-y-1.5 p-6 pb-0', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
@ -1,17 +1,19 @@
|
||||
<script lang="ts">
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import type { HeadingLevel } from './index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLHeadingElement> & {
|
||||
tag?: HeadingLevel;
|
||||
};
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let tag: $$Props['tag'] = 'h3';
|
||||
export { className as class };
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
level = 3,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<svelte:element this={tag} class={cn('font-semibold leading-none tracking-tight', className)} {...$$restProps}>
|
||||
<slot />
|
||||
</svelte:element>
|
||||
<div role="heading" aria-level={level} bind:this={ref} class={cn('font-semibold leading-none tracking-tight', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
@ -1,22 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class={cn('rounded-xl border bg-card text-card-foreground shadow', className)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:mouseenter
|
||||
on:mouseleave
|
||||
>
|
||||
<slot />
|
||||
<div bind:this={ref} class={cn('rounded-xl border bg-card text-card-foreground shadow', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
@ -20,5 +20,3 @@ export {
|
||||
Header as CardHeader,
|
||||
Title as CardTitle,
|
||||
};
|
||||
|
||||
export type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
||||
|
@ -1,35 +1,40 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||
import Check from 'svelte-radix/Check.svelte';
|
||||
import { ContextMenu as ContextMenuPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
|
||||
import Check from 'lucide-svelte/icons/check';
|
||||
import Minus from 'lucide-svelte/icons/minus';
|
||||
import type { Snippet } from 'svelte';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = ContextMenuPrimitive.CheckboxItemProps;
|
||||
type $$Events = ContextMenuPrimitive.CheckboxItemEvents;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
export let checked: $$Props['checked'] = undefined;
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
checked = $bindable(false),
|
||||
indeterminate = $bindable(false),
|
||||
children: childrenProp,
|
||||
...restProps
|
||||
}: WithoutChildrenOrChild<ContextMenuPrimitive.CheckboxItemProps> & {
|
||||
children?: Snippet;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.CheckboxItem
|
||||
bind:ref
|
||||
bind:checked
|
||||
bind:indeterminate
|
||||
class={cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerdown
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
{...restProps}
|
||||
>
|
||||
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<ContextMenuPrimitive.CheckboxIndicator>
|
||||
<Check class="h-4 w-4" />
|
||||
</ContextMenuPrimitive.CheckboxIndicator>
|
||||
</span>
|
||||
<slot />
|
||||
{#snippet children({ checked, indeterminate })}
|
||||
<span class="absolute left-2 flex size-3.5 items-center justify-center">
|
||||
{#if indeterminate}
|
||||
<Minus class="size-4" />
|
||||
{:else}
|
||||
<Check class={cn('size-4', !checked && 'text-transparent')} />
|
||||
{/if}
|
||||
</span>
|
||||
{@render childrenProp?.()}
|
||||
{/snippet}
|
||||
</ContextMenuPrimitive.CheckboxItem>
|
||||
|
@ -1,21 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||
import { cn, flyAndScale } from '$lib/utils.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = ContextMenuPrimitive.ContentProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let transition: $$Props['transition'] = flyAndScale;
|
||||
export let transitionConfig: $$Props['transitionConfig'] = undefined;
|
||||
export { className as class };
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
portalProps,
|
||||
...restProps
|
||||
}: ContextMenuPrimitive.ContentProps & {
|
||||
portalProps?: ContextMenuPrimitive.PortalProps;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.Content
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn('z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-md focus:outline-none', className)}
|
||||
{...$$restProps}
|
||||
on:keydown
|
||||
>
|
||||
<slot />
|
||||
</ContextMenuPrimitive.Content>
|
||||
<ContextMenuPrimitive.Portal {...portalProps}>
|
||||
<ContextMenuPrimitive.Content
|
||||
class={cn('z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-md focus:outline-none', className)}
|
||||
{...restProps}
|
||||
bind:ref
|
||||
/>
|
||||
</ContextMenuPrimitive.Portal>
|
||||
|
@ -0,0 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
inset,
|
||||
...restProps
|
||||
}: ContextMenuPrimitive.GroupHeadingProps & {
|
||||
inset?: boolean;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.GroupHeading
|
||||
bind:ref
|
||||
class={cn('px-2 py-1.5 text-sm font-semibold text-foreground', inset && 'pl-8', className)}
|
||||
{...restProps}
|
||||
/>
|
@ -2,14 +2,14 @@
|
||||
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = ContextMenuPrimitive.ItemProps & {
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
inset,
|
||||
...restProps
|
||||
}: ContextMenuPrimitive.ItemProps & {
|
||||
inset?: boolean;
|
||||
};
|
||||
type $$Events = ContextMenuPrimitive.ItemEvents;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let inset: $$Props['inset'] = undefined;
|
||||
export { className as class };
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.Item
|
||||
@ -18,14 +18,6 @@
|
||||
inset && 'pl-8',
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerdown
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
>
|
||||
<slot />
|
||||
</ContextMenuPrimitive.Item>
|
||||
bind:ref
|
||||
{...restProps}
|
||||
/>
|
||||
|
@ -1,35 +1,25 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||
import DotFilled from 'svelte-radix/DotFilled.svelte';
|
||||
import { ContextMenu as ContextMenuPrimitive, type WithoutChild } from 'bits-ui';
|
||||
import Circle from 'lucide-svelte/icons/circle';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = ContextMenuPrimitive.RadioItemProps;
|
||||
type $$Events = ContextMenuPrimitive.RadioItemEvents;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let value: $$Props['value'];
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children: childrenProp, ...restProps }: WithoutChild<ContextMenuPrimitive.RadioItemProps> = $props();
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.RadioItem
|
||||
bind:ref
|
||||
class={cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{value}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerdown
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
{...restProps}
|
||||
>
|
||||
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<ContextMenuPrimitive.RadioIndicator>
|
||||
<DotFilled class="h-4 w-4 fill-current" />
|
||||
</ContextMenuPrimitive.RadioIndicator>
|
||||
</span>
|
||||
<slot />
|
||||
{#snippet children({ checked })}
|
||||
<span class="absolute left-2 flex size-3.5 items-center justify-center">
|
||||
{#if checked}
|
||||
<Circle class="size-2 fill-current" />
|
||||
{/if}
|
||||
</span>
|
||||
{@render childrenProp?.({ checked })}
|
||||
{/snippet}
|
||||
</ContextMenuPrimitive.RadioItem>
|
||||
|
@ -2,10 +2,7 @@
|
||||
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = ContextMenuPrimitive.SeparatorProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: ContextMenuPrimitive.SeparatorProps = $props();
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.Separator class={cn('-mx-1 my-1 h-px bg-border', className)} {...$$restProps} />
|
||||
<ContextMenuPrimitive.Separator bind:ref class={cn('-mx-1 my-1 h-px bg-border', className)} {...restProps} />
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLSpanElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
|
||||
</script>
|
||||
|
||||
<span class={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)} {...$$restProps}>
|
||||
<slot />
|
||||
<span bind:this={ref} class={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</span>
|
||||
|
@ -1,23 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||
import { cn, flyAndScale } from '$lib/utils.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = ContextMenuPrimitive.SubContentProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let transition: $$Props['transition'] = flyAndScale;
|
||||
export let transitionConfig: $$Props['transitionConfig'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: ContextMenuPrimitive.SubContentProps = $props();
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.SubContent
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
bind:ref
|
||||
class={cn('z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-lg focus:outline-none', className)}
|
||||
{...$$restProps}
|
||||
on:keydown
|
||||
on:focusout
|
||||
on:pointermove
|
||||
>
|
||||
<slot />
|
||||
</ContextMenuPrimitive.SubContent>
|
||||
{...restProps}
|
||||
/>
|
||||
|
@ -1,32 +1,28 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||
import ChevronRight from 'svelte-radix/ChevronRight.svelte';
|
||||
import { ContextMenu as ContextMenuPrimitive, type WithoutChild } from 'bits-ui';
|
||||
import ChevronRight from 'lucide-svelte/icons/chevron-right';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = ContextMenuPrimitive.SubTriggerProps & {
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
inset,
|
||||
...restProps
|
||||
}: WithoutChild<ContextMenuPrimitive.SubTriggerProps> & {
|
||||
inset?: boolean;
|
||||
};
|
||||
type $$Events = ContextMenuPrimitive.SubTriggerEvents;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let inset: $$Props['inset'] = undefined;
|
||||
export { className as class };
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.SubTrigger
|
||||
bind:ref
|
||||
class={cn(
|
||||
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[state=open]:bg-accent data-[highlighted]:text-accent-foreground data-[state=open]:text-accent-foreground',
|
||||
inset && 'pl-8',
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
{...restProps}
|
||||
>
|
||||
<slot />
|
||||
<ChevronRight class="ml-auto h-4 w-4" />
|
||||
{@render children?.()}
|
||||
<ChevronRight class="ml-auto size-4" />
|
||||
</ContextMenuPrimitive.SubTrigger>
|
||||
|
@ -1,32 +1,32 @@
|
||||
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||
|
||||
import Item from './context-menu-item.svelte';
|
||||
import Label from './context-menu-label.svelte';
|
||||
import GroupHeading from './context-menu-group-heading.svelte';
|
||||
import Content from './context-menu-content.svelte';
|
||||
import Shortcut from './context-menu-shortcut.svelte';
|
||||
import RadioItem from './context-menu-radio-item.svelte';
|
||||
import Separator from './context-menu-separator.svelte';
|
||||
import RadioGroup from './context-menu-radio-group.svelte';
|
||||
import SubContent from './context-menu-sub-content.svelte';
|
||||
import SubTrigger from './context-menu-sub-trigger.svelte';
|
||||
import CheckboxItem from './context-menu-checkbox-item.svelte';
|
||||
|
||||
const Sub = ContextMenuPrimitive.Sub;
|
||||
const Root = ContextMenuPrimitive.Root;
|
||||
const Trigger = ContextMenuPrimitive.Trigger;
|
||||
const Group = ContextMenuPrimitive.Group;
|
||||
const Sub: typeof ContextMenuPrimitive.Sub = ContextMenuPrimitive.Sub;
|
||||
const Root: typeof ContextMenuPrimitive.Root = ContextMenuPrimitive.Root;
|
||||
const Trigger: typeof ContextMenuPrimitive.Trigger = ContextMenuPrimitive.Trigger;
|
||||
const Group: typeof ContextMenuPrimitive.Group = ContextMenuPrimitive.Group;
|
||||
const RadioGroup: typeof ContextMenuPrimitive.RadioGroup = ContextMenuPrimitive.RadioGroup;
|
||||
|
||||
export {
|
||||
Sub,
|
||||
Root,
|
||||
Item,
|
||||
Label,
|
||||
Group,
|
||||
Trigger,
|
||||
Content,
|
||||
Shortcut,
|
||||
Separator,
|
||||
RadioItem,
|
||||
GroupHeading,
|
||||
SubContent,
|
||||
SubTrigger,
|
||||
RadioGroup,
|
||||
@ -35,13 +35,13 @@ export {
|
||||
Root as ContextMenu,
|
||||
Sub as ContextMenuSub,
|
||||
Item as ContextMenuItem,
|
||||
Label as ContextMenuLabel,
|
||||
Group as ContextMenuGroup,
|
||||
Content as ContextMenuContent,
|
||||
Trigger as ContextMenuTrigger,
|
||||
Shortcut as ContextMenuShortcut,
|
||||
RadioItem as ContextMenuRadioItem,
|
||||
Separator as ContextMenuSeparator,
|
||||
GroupHeading as ContextMenuGroupHeading,
|
||||
RadioGroup as ContextMenuRadioGroup,
|
||||
SubContent as ContextMenuSubContent,
|
||||
SubTrigger as ContextMenuSubTrigger,
|
||||
|
@ -1,35 +1,37 @@
|
||||
<script lang="ts">
|
||||
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||
import Cross2 from 'svelte-radix/Cross2.svelte';
|
||||
import { Dialog as DialogPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
|
||||
import X from 'lucide-svelte/icons/x';
|
||||
import type { Snippet } from 'svelte';
|
||||
import * as Dialog from './index.js';
|
||||
import { cn, flyAndScale } from '$lib/utils.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = DialogPrimitive.ContentProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let transition: $$Props['transition'] = flyAndScale;
|
||||
export let transitionConfig: $$Props['transitionConfig'] = {
|
||||
duration: 200,
|
||||
};
|
||||
export { className as class };
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
portalProps,
|
||||
children,
|
||||
...restProps
|
||||
}: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
|
||||
portalProps?: DialogPrimitive.PortalProps;
|
||||
children: Snippet;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<Dialog.Portal>
|
||||
<Dialog.Portal {...portalProps}>
|
||||
<Dialog.Overlay />
|
||||
<DialogPrimitive.Content
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
bind:ref
|
||||
class={cn(
|
||||
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg sm:rounded-lg md:w-full',
|
||||
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
{...restProps}
|
||||
>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
<DialogPrimitive.Close
|
||||
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
|
||||
>
|
||||
<Cross2 class="h-4 w-4" />
|
||||
<X class="size-4" />
|
||||
<span class="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
|
@ -2,12 +2,7 @@
|
||||
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = DialogPrimitive.DescriptionProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: DialogPrimitive.DescriptionProps = $props();
|
||||
</script>
|
||||
|
||||
<DialogPrimitive.Description class={cn('text-sm text-muted-foreground', className)} {...$$restProps}>
|
||||
<slot />
|
||||
</DialogPrimitive.Description>
|
||||
<DialogPrimitive.Description bind:ref class={cn('text-sm text-muted-foreground', className)} {...restProps} />
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div class={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)} {...$$restProps}>
|
||||
<slot />
|
||||
<div bind:this={ref} class={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div class={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)} {...$$restProps}>
|
||||
<slot />
|
||||
<div bind:this={ref} class={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
@ -1,21 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = DialogPrimitive.OverlayProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let transition: $$Props['transition'] = fade;
|
||||
export let transitionConfig: $$Props['transitionConfig'] = {
|
||||
duration: 150,
|
||||
};
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: DialogPrimitive.OverlayProps = $props();
|
||||
</script>
|
||||
|
||||
<DialogPrimitive.Overlay
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn('fixed inset-0 z-50 bg-background/80 backdrop-blur-sm ', className)}
|
||||
{...$$restProps}
|
||||
bind:ref
|
||||
class={cn(
|
||||
'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
||||
className,
|
||||
)}
|
||||
{...restProps}
|
||||
/>
|
||||
|
@ -2,12 +2,7 @@
|
||||
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = DialogPrimitive.TitleProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: DialogPrimitive.TitleProps = $props();
|
||||
</script>
|
||||
|
||||
<DialogPrimitive.Title class={cn('text-lg font-semibold leading-none tracking-tight', className)} {...$$restProps}>
|
||||
<slot />
|
||||
</DialogPrimitive.Title>
|
||||
<DialogPrimitive.Title bind:ref class={cn('text-lg font-semibold leading-none tracking-tight', className)} {...restProps} />
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||
|
||||
import Title from './dialog-title.svelte';
|
||||
import Portal from './dialog-portal.svelte';
|
||||
import Footer from './dialog-footer.svelte';
|
||||
import Header from './dialog-header.svelte';
|
||||
import Overlay from './dialog-overlay.svelte';
|
||||
import Content from './dialog-content.svelte';
|
||||
import Description from './dialog-description.svelte';
|
||||
|
||||
const Root = DialogPrimitive.Root;
|
||||
const Trigger = DialogPrimitive.Trigger;
|
||||
const Close = DialogPrimitive.Close;
|
||||
const Root: typeof DialogPrimitive.Root = DialogPrimitive.Root;
|
||||
const Trigger: typeof DialogPrimitive.Trigger = DialogPrimitive.Trigger;
|
||||
const Close: typeof DialogPrimitive.Close = DialogPrimitive.Close;
|
||||
const Portal: typeof DialogPrimitive.Portal = DialogPrimitive.Portal;
|
||||
|
||||
export {
|
||||
Root,
|
||||
|
@ -1,35 +1,40 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import Check from 'svelte-radix/Check.svelte';
|
||||
import { DropdownMenu as DropdownMenuPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
|
||||
import Check from 'lucide-svelte/icons/check';
|
||||
import Minus from 'lucide-svelte/icons/minus';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.CheckboxItemProps;
|
||||
type $$Events = DropdownMenuPrimitive.CheckboxItemEvents;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let checked: $$Props['checked'] = undefined;
|
||||
export { className as class };
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children: childrenProp,
|
||||
checked = $bindable(false),
|
||||
indeterminate = $bindable(false),
|
||||
...restProps
|
||||
}: WithoutChildrenOrChild<DropdownMenuPrimitive.CheckboxItemProps> & {
|
||||
children?: Snippet;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<DropdownMenuPrimitive.CheckboxItem
|
||||
bind:ref
|
||||
bind:checked
|
||||
bind:indeterminate
|
||||
class={cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerdown
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
{...restProps}
|
||||
>
|
||||
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.CheckboxIndicator>
|
||||
<Check class="h-4 w-4" />
|
||||
</DropdownMenuPrimitive.CheckboxIndicator>
|
||||
</span>
|
||||
<slot />
|
||||
{#snippet children({ checked, indeterminate })}
|
||||
<span class="absolute left-2 flex size-3.5 items-center justify-center">
|
||||
{#if indeterminate}
|
||||
<Minus class="size-4" />
|
||||
{:else}
|
||||
<Check class={cn('size-4', !checked && 'text-transparent')} />
|
||||
{/if}
|
||||
</span>
|
||||
{@render childrenProp?.()}
|
||||
{/snippet}
|
||||
</DropdownMenuPrimitive.CheckboxItem>
|
||||
|
@ -1,23 +1,27 @@
|
||||
<script lang="ts">
|
||||
import { cn } from '$lib/utils.js';
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import { cn, flyAndScale } from '$lib/utils.js';
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.ContentProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let sideOffset: $$Props['sideOffset'] = 4;
|
||||
export let transition: $$Props['transition'] = flyAndScale;
|
||||
export let transitionConfig: $$Props['transitionConfig'] = undefined;
|
||||
export { className as class };
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
sideOffset = 4,
|
||||
portalProps,
|
||||
...restProps
|
||||
}: DropdownMenuPrimitive.ContentProps & {
|
||||
portalProps?: DropdownMenuPrimitive.PortalProps;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<DropdownMenuPrimitive.Content
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
{sideOffset}
|
||||
class={cn('z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-md focus:outline-none', className)}
|
||||
{...$$restProps}
|
||||
on:keydown
|
||||
>
|
||||
<slot />
|
||||
</DropdownMenuPrimitive.Content>
|
||||
<DropdownMenuPrimitive.Portal {...portalProps}>
|
||||
<DropdownMenuPrimitive.Content
|
||||
bind:ref
|
||||
{sideOffset}
|
||||
class={cn(
|
||||
'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',
|
||||
'outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||
className,
|
||||
)}
|
||||
{...restProps}
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
|
@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
inset,
|
||||
...restProps
|
||||
}: DropdownMenuPrimitive.GroupHeadingProps & {
|
||||
inset?: boolean;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<DropdownMenuPrimitive.GroupHeading bind:ref class={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)} {...restProps} />
|
@ -1,31 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.ItemProps & {
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
inset,
|
||||
...restProps
|
||||
}: DropdownMenuPrimitive.ItemProps & {
|
||||
inset?: boolean;
|
||||
};
|
||||
type $$Events = DropdownMenuPrimitive.ItemEvents;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let inset: $$Props['inset'] = undefined;
|
||||
export { className as class };
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<DropdownMenuPrimitive.Item
|
||||
bind:ref
|
||||
class={cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50',
|
||||
'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
inset && 'pl-8',
|
||||
className,
|
||||
)}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerdown
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</DropdownMenuPrimitive.Item>
|
||||
{...restProps}
|
||||
/>
|
||||
|
@ -1,16 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import { type WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.LabelProps & {
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
inset,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||
inset?: boolean;
|
||||
};
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let inset: $$Props['inset'] = undefined;
|
||||
export { className as class };
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<DropdownMenuPrimitive.Label class={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)} {...$$restProps}>
|
||||
<slot />
|
||||
</DropdownMenuPrimitive.Label>
|
||||
<div bind:this={ref} class={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
@ -1,35 +1,30 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import DotFilled from 'svelte-radix/DotFilled.svelte';
|
||||
import { DropdownMenu as DropdownMenuPrimitive, type WithoutChild } from 'bits-ui';
|
||||
import Circle from 'lucide-svelte/icons/circle';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.RadioItemProps;
|
||||
type $$Events = DropdownMenuPrimitive.RadioItemEvents;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let value: DropdownMenuPrimitive.RadioItemProps['value'];
|
||||
export { className as class };
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children: childrenProp,
|
||||
...restProps
|
||||
}: WithoutChild<DropdownMenuPrimitive.RadioItemProps> = $props();
|
||||
</script>
|
||||
|
||||
<DropdownMenuPrimitive.RadioItem
|
||||
bind:ref
|
||||
class={cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{value}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerdown
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
{...restProps}
|
||||
>
|
||||
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.RadioIndicator>
|
||||
<DotFilled class="h-4 w-4 fill-current" />
|
||||
</DropdownMenuPrimitive.RadioIndicator>
|
||||
</span>
|
||||
<slot />
|
||||
{#snippet children({ checked })}
|
||||
<span class="absolute left-2 flex size-3.5 items-center justify-center">
|
||||
{#if checked}
|
||||
<Circle class="size-2 fill-current" />
|
||||
{/if}
|
||||
</span>
|
||||
{@render childrenProp?.({ checked })}
|
||||
{/snippet}
|
||||
</DropdownMenuPrimitive.RadioItem>
|
||||
|
@ -2,10 +2,7 @@
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.SeparatorProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: DropdownMenuPrimitive.SeparatorProps = $props();
|
||||
</script>
|
||||
|
||||
<DropdownMenuPrimitive.Separator class={cn('-mx-1 my-1 h-px bg-muted', className)} {...$$restProps} />
|
||||
<DropdownMenuPrimitive.Separator bind:ref class={cn('-mx-1 my-1 h-px bg-muted', className)} {...restProps} />
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { type WithElementRef } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLSpanElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
|
||||
</script>
|
||||
|
||||
<span class={cn('ml-auto text-xs tracking-widest opacity-60', className)} {...$$restProps}>
|
||||
<slot />
|
||||
<span bind:this={ref} class={cn('ml-auto text-xs tracking-widest opacity-60', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</span>
|
||||
|
@ -1,26 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import { cn, flyAndScale } from '$lib/utils.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.SubContentProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let transition: $$Props['transition'] = flyAndScale;
|
||||
export let transitionConfig: $$Props['transitionConfig'] = {
|
||||
x: -10,
|
||||
y: 0,
|
||||
};
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: DropdownMenuPrimitive.SubContentProps = $props();
|
||||
</script>
|
||||
|
||||
<DropdownMenuPrimitive.SubContent
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
bind:ref
|
||||
class={cn('z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-lg focus:outline-none', className)}
|
||||
{...$$restProps}
|
||||
on:keydown
|
||||
on:focusout
|
||||
on:pointermove
|
||||
>
|
||||
<slot />
|
||||
</DropdownMenuPrimitive.SubContent>
|
||||
{...restProps}
|
||||
/>
|
||||
|
@ -1,32 +1,28 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import ChevronRight from 'svelte-radix/ChevronRight.svelte';
|
||||
import { DropdownMenu as DropdownMenuPrimitive, type WithoutChild } from 'bits-ui';
|
||||
import ChevronRight from 'lucide-svelte/icons/chevron-right';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.SubTriggerProps & {
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
inset,
|
||||
children,
|
||||
...restProps
|
||||
}: WithoutChild<DropdownMenuPrimitive.SubTriggerProps> & {
|
||||
inset?: boolean;
|
||||
};
|
||||
type $$Events = DropdownMenuPrimitive.SubTriggerEvents;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let inset: $$Props['inset'] = undefined;
|
||||
export { className as class };
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
bind:ref
|
||||
class={cn(
|
||||
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[state=open]:bg-accent data-[highlighted]:text-accent-foreground data-[state=open]:text-accent-foreground',
|
||||
'flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
inset && 'pl-8',
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
{...restProps}
|
||||
>
|
||||
<slot />
|
||||
<ChevronRight class="ml-auto h-4 w-4" />
|
||||
{@render children?.()}
|
||||
<ChevronRight class="ml-auto" />
|
||||
</DropdownMenuPrimitive.SubTrigger>
|
||||
|
@ -1,48 +1,50 @@
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import CheckboxItem from './dropdown-menu-checkbox-item.svelte';
|
||||
import Content from './dropdown-menu-content.svelte';
|
||||
import GroupHeading from './dropdown-menu-group-heading.svelte';
|
||||
import Item from './dropdown-menu-item.svelte';
|
||||
import Label from './dropdown-menu-label.svelte';
|
||||
import Content from './dropdown-menu-content.svelte';
|
||||
import Shortcut from './dropdown-menu-shortcut.svelte';
|
||||
import RadioItem from './dropdown-menu-radio-item.svelte';
|
||||
import Separator from './dropdown-menu-separator.svelte';
|
||||
import RadioGroup from './dropdown-menu-radio-group.svelte';
|
||||
import Shortcut from './dropdown-menu-shortcut.svelte';
|
||||
import SubContent from './dropdown-menu-sub-content.svelte';
|
||||
import SubTrigger from './dropdown-menu-sub-trigger.svelte';
|
||||
import CheckboxItem from './dropdown-menu-checkbox-item.svelte';
|
||||
|
||||
const Sub = DropdownMenuPrimitive.Sub;
|
||||
const Root = DropdownMenuPrimitive.Root;
|
||||
const Trigger = DropdownMenuPrimitive.Trigger;
|
||||
const Group = DropdownMenuPrimitive.Group;
|
||||
const RadioGroup = DropdownMenuPrimitive.RadioGroup;
|
||||
|
||||
export {
|
||||
Sub,
|
||||
Root,
|
||||
Item,
|
||||
Label,
|
||||
Group,
|
||||
Trigger,
|
||||
Content,
|
||||
Shortcut,
|
||||
Separator,
|
||||
RadioItem,
|
||||
SubContent,
|
||||
SubTrigger,
|
||||
RadioGroup,
|
||||
CheckboxItem,
|
||||
//
|
||||
Content,
|
||||
Root as DropdownMenu,
|
||||
Sub as DropdownMenuSub,
|
||||
CheckboxItem as DropdownMenuCheckboxItem,
|
||||
Content as DropdownMenuContent,
|
||||
Group as DropdownMenuGroup,
|
||||
GroupHeading as DropdownMenuGroupHeading,
|
||||
Item as DropdownMenuItem,
|
||||
Label as DropdownMenuLabel,
|
||||
Group as DropdownMenuGroup,
|
||||
Content as DropdownMenuContent,
|
||||
Trigger as DropdownMenuTrigger,
|
||||
Shortcut as DropdownMenuShortcut,
|
||||
RadioGroup as DropdownMenuRadioGroup,
|
||||
RadioItem as DropdownMenuRadioItem,
|
||||
Separator as DropdownMenuSeparator,
|
||||
RadioGroup as DropdownMenuRadioGroup,
|
||||
Shortcut as DropdownMenuShortcut,
|
||||
Sub as DropdownMenuSub,
|
||||
SubContent as DropdownMenuSubContent,
|
||||
SubTrigger as DropdownMenuSubTrigger,
|
||||
CheckboxItem as DropdownMenuCheckboxItem,
|
||||
Trigger as DropdownMenuTrigger,
|
||||
Group,
|
||||
GroupHeading,
|
||||
Item,
|
||||
Label,
|
||||
RadioGroup,
|
||||
RadioItem,
|
||||
Root,
|
||||
Separator,
|
||||
Shortcut,
|
||||
Sub,
|
||||
SubContent,
|
||||
SubTrigger,
|
||||
Trigger,
|
||||
};
|
||||
|
@ -1,27 +1,5 @@
|
||||
import Root from './input.svelte';
|
||||
|
||||
export type FormInputEvent<T extends Event = Event> = T & {
|
||||
currentTarget: EventTarget & HTMLInputElement;
|
||||
};
|
||||
export type InputEvents = {
|
||||
blur: FormInputEvent<FocusEvent>;
|
||||
change: FormInputEvent<Event>;
|
||||
click: FormInputEvent<MouseEvent>;
|
||||
focus: FormInputEvent<FocusEvent>;
|
||||
focusin: FormInputEvent<FocusEvent>;
|
||||
focusout: FormInputEvent<FocusEvent>;
|
||||
keydown: FormInputEvent<KeyboardEvent>;
|
||||
keypress: FormInputEvent<KeyboardEvent>;
|
||||
keyup: FormInputEvent<KeyboardEvent>;
|
||||
mouseover: FormInputEvent<MouseEvent>;
|
||||
mouseenter: FormInputEvent<MouseEvent>;
|
||||
mouseleave: FormInputEvent<MouseEvent>;
|
||||
mousemove: FormInputEvent<MouseEvent>;
|
||||
paste: FormInputEvent<ClipboardEvent>;
|
||||
input: FormInputEvent<InputEvent>;
|
||||
wheel: FormInputEvent<WheelEvent>;
|
||||
};
|
||||
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
|
@ -1,42 +1,36 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLInputAttributes } from 'svelte/elements';
|
||||
import type { InputEvents } from './index.js';
|
||||
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from 'svelte/elements';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLInputAttributes;
|
||||
type $$Events = InputEvents;
|
||||
type InputType = Exclude<HTMLInputTypeAttribute, 'file'>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let value: $$Props['value'] = undefined;
|
||||
export { className as class };
|
||||
type Props = WithElementRef<Omit<HTMLInputAttributes, 'type'> & ({ type: 'file'; files?: FileList } | { type?: InputType; files?: undefined })>;
|
||||
|
||||
// Workaround for https://github.com/sveltejs/svelte/issues/9305
|
||||
// Fixed in Svelte 5, but not backported to 4.x.
|
||||
export let readonly: $$Props['readonly'] = undefined;
|
||||
let { ref = $bindable(null), value = $bindable(), type, files = $bindable(), class: className, ...restProps }: Props = $props();
|
||||
</script>
|
||||
|
||||
<input
|
||||
class={cn(
|
||||
'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className,
|
||||
)}
|
||||
bind:value
|
||||
{readonly}
|
||||
on:blur
|
||||
on:change
|
||||
on:click
|
||||
on:focus
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:keydown
|
||||
on:keypress
|
||||
on:keyup
|
||||
on:mouseover
|
||||
on:mouseenter
|
||||
on:mouseleave
|
||||
on:mousemove
|
||||
on:paste
|
||||
on:input
|
||||
on:wheel|passive
|
||||
{...$$restProps}
|
||||
/>
|
||||
{#if type === 'file'}
|
||||
<input
|
||||
bind:this={ref}
|
||||
class={cn(
|
||||
'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
className,
|
||||
)}
|
||||
type="file"
|
||||
bind:files
|
||||
bind:value
|
||||
{...restProps}
|
||||
/>
|
||||
{:else}
|
||||
<input
|
||||
bind:this={ref}
|
||||
class={cn(
|
||||
'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
className,
|
||||
)}
|
||||
{type}
|
||||
bind:value
|
||||
{...restProps}
|
||||
/>
|
||||
{/if}
|
||||
|
@ -2,15 +2,11 @@
|
||||
import { Label as LabelPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = LabelPrimitive.Props;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: LabelPrimitive.RootProps = $props();
|
||||
</script>
|
||||
|
||||
<LabelPrimitive.Root
|
||||
bind:ref
|
||||
class={cn('text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</LabelPrimitive.Root>
|
||||
{...restProps}
|
||||
/>
|
||||
|
@ -1,34 +1,34 @@
|
||||
import { Select as SelectPrimitive } from 'bits-ui';
|
||||
|
||||
import Label from './select-label.svelte';
|
||||
import GroupHeading from './select-group-heading.svelte';
|
||||
import Item from './select-item.svelte';
|
||||
import Content from './select-content.svelte';
|
||||
import Trigger from './select-trigger.svelte';
|
||||
import Separator from './select-separator.svelte';
|
||||
import ScrollDownButton from './select-scroll-down-button.svelte';
|
||||
import ScrollUpButton from './select-scroll-up-button.svelte';
|
||||
|
||||
const Root = SelectPrimitive.Root;
|
||||
const Group = SelectPrimitive.Group;
|
||||
const Input = SelectPrimitive.Input;
|
||||
const Value = SelectPrimitive.Value;
|
||||
|
||||
export {
|
||||
Root,
|
||||
Item,
|
||||
Group,
|
||||
Input,
|
||||
Label,
|
||||
Value,
|
||||
GroupHeading,
|
||||
Content,
|
||||
Trigger,
|
||||
Separator,
|
||||
ScrollDownButton,
|
||||
ScrollUpButton,
|
||||
//
|
||||
Root as Select,
|
||||
Item as SelectItem,
|
||||
Group as SelectGroup,
|
||||
Input as SelectInput,
|
||||
Label as SelectLabel,
|
||||
Value as SelectValue,
|
||||
GroupHeading as SelectGroupHeading,
|
||||
Content as SelectContent,
|
||||
Trigger as SelectTrigger,
|
||||
Separator as SelectSeparator,
|
||||
ScrollDownButton as SelectScrollDownButton,
|
||||
ScrollUpButton as SelectScrollUpButton,
|
||||
};
|
||||
|
@ -1,36 +1,34 @@
|
||||
<script lang="ts">
|
||||
import { Select as SelectPrimitive } from 'bits-ui';
|
||||
import { scale } from 'svelte/transition';
|
||||
import { cn, flyAndScale } from '$lib/utils.js';
|
||||
import { Select as SelectPrimitive, type WithoutChild } from 'bits-ui';
|
||||
import * as Select from './index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = SelectPrimitive.ContentProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let sideOffset: $$Props['sideOffset'] = 4;
|
||||
export let inTransition: $$Props['inTransition'] = flyAndScale;
|
||||
export let inTransitionConfig: $$Props['inTransitionConfig'] = undefined;
|
||||
export let outTransition: $$Props['outTransition'] = scale;
|
||||
export let outTransitionConfig: $$Props['outTransitionConfig'] = {
|
||||
start: 0.95,
|
||||
opacity: 0,
|
||||
duration: 50,
|
||||
};
|
||||
export { className as class };
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
sideOffset = 4,
|
||||
portalProps,
|
||||
children,
|
||||
...restProps
|
||||
}: WithoutChild<SelectPrimitive.ContentProps> & {
|
||||
portalProps?: SelectPrimitive.PortalProps;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<SelectPrimitive.Content
|
||||
{inTransition}
|
||||
{inTransitionConfig}
|
||||
{outTransition}
|
||||
{outTransitionConfig}
|
||||
{sideOffset}
|
||||
class={cn(
|
||||
'relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md focus:outline-none',
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<div class="w-full p-1">
|
||||
<slot />
|
||||
</div>
|
||||
</SelectPrimitive.Content>
|
||||
<SelectPrimitive.Portal {...portalProps}>
|
||||
<SelectPrimitive.Content
|
||||
bind:ref
|
||||
{sideOffset}
|
||||
class={cn(
|
||||
'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||
className,
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
<Select.ScrollUpButton />
|
||||
<SelectPrimitive.Viewport class={cn('h-[var(--bits-select-anchor-height)] w-full min-w-[var(--bits-select-anchor-width)] p-1')}>
|
||||
{@render children?.()}
|
||||
</SelectPrimitive.Viewport>
|
||||
<Select.ScrollDownButton />
|
||||
</SelectPrimitive.Content>
|
||||
</SelectPrimitive.Portal>
|
||||
|
8
src/lib/components/ui/select/select-group-heading.svelte
Normal file
8
src/lib/components/ui/select/select-group-heading.svelte
Normal file
@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { Select as SelectPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let { ref = $bindable(null), class: className, ...restProps }: SelectPrimitive.GroupHeadingProps = $props();
|
||||
</script>
|
||||
|
||||
<SelectPrimitive.GroupHeading bind:ref class={cn('px-2 py-1.5 text-sm font-semibold', className)} {...restProps} />
|
@ -1,37 +1,37 @@
|
||||
<script lang="ts">
|
||||
import { Select as SelectPrimitive } from 'bits-ui';
|
||||
import Check from 'svelte-radix/Check.svelte';
|
||||
import { Select as SelectPrimitive, type WithoutChild } from 'bits-ui';
|
||||
import Check from 'lucide-svelte/icons/check';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = SelectPrimitive.ItemProps;
|
||||
type $$Events = Required<SelectPrimitive.ItemEvents>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let value: $$Props['value'];
|
||||
export let label: $$Props['label'] = undefined;
|
||||
export let disabled: $$Props['disabled'] = undefined;
|
||||
export { className as class };
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
value,
|
||||
label,
|
||||
children: childrenProp,
|
||||
...restProps
|
||||
}: WithoutChild<SelectPrimitive.ItemProps> = $props();
|
||||
</script>
|
||||
|
||||
<SelectPrimitive.Item
|
||||
bind:ref
|
||||
{value}
|
||||
{disabled}
|
||||
{label}
|
||||
class={cn(
|
||||
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:pointermove
|
||||
on:focusin
|
||||
{...restProps}
|
||||
>
|
||||
<span class="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<SelectPrimitive.ItemIndicator>
|
||||
<Check class="h-4 w-4" />
|
||||
</SelectPrimitive.ItemIndicator>
|
||||
</span>
|
||||
<slot>
|
||||
{label || value}
|
||||
</slot>
|
||||
{#snippet children({ selected, highlighted })}
|
||||
<span class="absolute right-2 flex size-3.5 items-center justify-center">
|
||||
{#if selected}
|
||||
<Check class="size-4" />
|
||||
{/if}
|
||||
</span>
|
||||
{#if childrenProp}
|
||||
{@render childrenProp({ selected, highlighted })}
|
||||
{:else}
|
||||
{label || value}
|
||||
{/if}
|
||||
{/snippet}
|
||||
</SelectPrimitive.Item>
|
||||
|
@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
import ChevronDown from 'lucide-svelte/icons/chevron-down';
|
||||
import { Select as SelectPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let { ref = $bindable(null), class: className, ...restProps }: WithoutChildrenOrChild<SelectPrimitive.ScrollDownButtonProps> = $props();
|
||||
</script>
|
||||
|
||||
<SelectPrimitive.ScrollDownButton bind:ref class={cn('flex cursor-default items-center justify-center py-1', className)} {...restProps}>
|
||||
<ChevronDown class="size-4" />
|
||||
</SelectPrimitive.ScrollDownButton>
|
11
src/lib/components/ui/select/select-scroll-up-button.svelte
Normal file
11
src/lib/components/ui/select/select-scroll-up-button.svelte
Normal file
@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
import ChevronUp from 'lucide-svelte/icons/chevron-up';
|
||||
import { Select as SelectPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let { ref = $bindable(null), class: className, ...restProps }: WithoutChildrenOrChild<SelectPrimitive.ScrollDownButtonProps> = $props();
|
||||
</script>
|
||||
|
||||
<SelectPrimitive.ScrollUpButton bind:ref class={cn('flex cursor-default items-center justify-center py-1', className)} {...restProps}>
|
||||
<ChevronUp class="size-4" />
|
||||
</SelectPrimitive.ScrollUpButton>
|
@ -1,11 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { Select as SelectPrimitive } from 'bits-ui';
|
||||
import type { Separator as SeparatorPrimitive } from 'bits-ui';
|
||||
import { Separator } from '$lib/components/ui/separator/index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = SelectPrimitive.SeparatorProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: SeparatorPrimitive.RootProps = $props();
|
||||
</script>
|
||||
|
||||
<SelectPrimitive.Separator class={cn('-mx-1 my-1 h-px bg-muted', className)} {...$$restProps} />
|
||||
<Separator bind:ref class={cn('-mx-1 my-1 h-px bg-muted', className)} {...restProps} />
|
||||
|
@ -1,24 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { Select as SelectPrimitive } from 'bits-ui';
|
||||
import CaretSort from 'svelte-radix/CaretSort.svelte';
|
||||
import { Select as SelectPrimitive, type WithoutChild } from 'bits-ui';
|
||||
import ChevronDown from 'lucide-svelte/icons/chevron-down';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = SelectPrimitive.TriggerProps;
|
||||
type $$Events = SelectPrimitive.TriggerEvents;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithoutChild<SelectPrimitive.TriggerProps> = $props();
|
||||
</script>
|
||||
|
||||
<SelectPrimitive.Trigger
|
||||
bind:ref
|
||||
class={cn(
|
||||
'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid]:border-destructive [&>span]:line-clamp-1 data-[placeholder]:[&>span]:text-muted-foreground',
|
||||
'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[placeholder]:text-muted-foreground [&>span]:line-clamp-1',
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
{...restProps}
|
||||
>
|
||||
<slot />
|
||||
<div>
|
||||
<CaretSort class="h-4 w-4 opacity-50" />
|
||||
</div>
|
||||
{@render children?.()}
|
||||
<ChevronDown class="size-4 opacity-50" />
|
||||
</SelectPrimitive.Trigger>
|
||||
|
7
src/lib/components/ui/separator/index.ts
Normal file
7
src/lib/components/ui/separator/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import Root from './separator.svelte';
|
||||
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Separator,
|
||||
};
|
13
src/lib/components/ui/separator/separator.svelte
Normal file
13
src/lib/components/ui/separator/separator.svelte
Normal file
@ -0,0 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { Separator as SeparatorPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let { ref = $bindable(null), class: className, orientation = 'horizontal', ...restProps }: SeparatorPrimitive.RootProps = $props();
|
||||
</script>
|
||||
|
||||
<SeparatorPrimitive.Root
|
||||
bind:ref
|
||||
class={cn('shrink-0 bg-border', orientation === 'horizontal' ? 'h-[1px] w-full' : 'min-h-full w-[1px]', className)}
|
||||
{orientation}
|
||||
{...restProps}
|
||||
/>
|
@ -1,7 +1,5 @@
|
||||
import { Dialog as SheetPrimitive } from 'bits-ui';
|
||||
import { type VariantProps, tv } from 'tailwind-variants';
|
||||
|
||||
import Portal from './sheet-portal.svelte';
|
||||
import Overlay from './sheet-overlay.svelte';
|
||||
import Content from './sheet-content.svelte';
|
||||
import Header from './sheet-header.svelte';
|
||||
@ -12,6 +10,7 @@ import Description from './sheet-description.svelte';
|
||||
const Root = SheetPrimitive.Root;
|
||||
const Close = SheetPrimitive.Close;
|
||||
const Trigger = SheetPrimitive.Trigger;
|
||||
const Portal = SheetPrimitive.Portal;
|
||||
|
||||
export {
|
||||
Root,
|
||||
@ -36,71 +35,3 @@ export {
|
||||
Title as SheetTitle,
|
||||
Description as SheetDescription,
|
||||
};
|
||||
|
||||
export const sheetVariants = tv({
|
||||
base: 'bg-background fixed z-50 gap-4 p-6 shadow-lg',
|
||||
variants: {
|
||||
side: {
|
||||
top: 'inset-x-0 top-0 border-b ',
|
||||
bottom: 'inset-x-0 bottom-0 border-t',
|
||||
left: 'inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',
|
||||
right: 'inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
side: 'right',
|
||||
},
|
||||
});
|
||||
|
||||
export const sheetTransitions = {
|
||||
top: {
|
||||
in: {
|
||||
y: '-100%',
|
||||
duration: 500,
|
||||
opacity: 1,
|
||||
},
|
||||
out: {
|
||||
y: '-100%',
|
||||
duration: 300,
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
bottom: {
|
||||
in: {
|
||||
y: '100%',
|
||||
duration: 500,
|
||||
opacity: 1,
|
||||
},
|
||||
out: {
|
||||
y: '100%',
|
||||
duration: 300,
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
left: {
|
||||
in: {
|
||||
x: '-100%',
|
||||
duration: 500,
|
||||
opacity: 1,
|
||||
},
|
||||
out: {
|
||||
x: '-100%',
|
||||
duration: 300,
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
right: {
|
||||
in: {
|
||||
x: '100%',
|
||||
duration: 500,
|
||||
opacity: 1,
|
||||
},
|
||||
out: {
|
||||
x: '100%',
|
||||
duration: 300,
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export type Side = VariantProps<typeof sheetVariants>['side'];
|
||||
|
@ -1,39 +1,54 @@
|
||||
<script lang="ts">
|
||||
import { Dialog as SheetPrimitive } from 'bits-ui';
|
||||
import Cross2 from 'svelte-radix/Cross2.svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { SheetOverlay, SheetPortal, type Side, sheetTransitions, sheetVariants } from './index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
<script lang="ts" module>
|
||||
import { tv, type VariantProps } from 'tailwind-variants';
|
||||
|
||||
type $$Props = SheetPrimitive.ContentProps & {
|
||||
side?: Side;
|
||||
};
|
||||
export const sheetVariants = tv({
|
||||
base: 'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 gap-4 p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
|
||||
variants: {
|
||||
side: {
|
||||
top: 'data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 border-b',
|
||||
bottom: 'data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 border-t',
|
||||
left: 'data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',
|
||||
right: 'data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
side: 'right',
|
||||
},
|
||||
});
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let side: $$Props['side'] = 'right';
|
||||
export { className as class };
|
||||
export let inTransition: $$Props['inTransition'] = fly;
|
||||
export let inTransitionConfig: $$Props['inTransitionConfig'] = sheetTransitions[side ?? 'right'].in;
|
||||
export let outTransition: $$Props['outTransition'] = fly;
|
||||
export let outTransitionConfig: $$Props['outTransitionConfig'] = sheetTransitions[side ?? 'right'].out;
|
||||
export type Side = VariantProps<typeof sheetVariants>['side'];
|
||||
</script>
|
||||
|
||||
<SheetPortal>
|
||||
<script lang="ts">
|
||||
import { Dialog as SheetPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
|
||||
import X from 'lucide-svelte/icons/x';
|
||||
import type { Snippet } from 'svelte';
|
||||
import SheetOverlay from './sheet-overlay.svelte';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
portalProps,
|
||||
side = 'right',
|
||||
children,
|
||||
...restProps
|
||||
}: WithoutChildrenOrChild<SheetPrimitive.ContentProps> & {
|
||||
portalProps?: SheetPrimitive.PortalProps;
|
||||
side?: Side;
|
||||
children: Snippet;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<SheetPrimitive.Portal {...portalProps}>
|
||||
<SheetOverlay />
|
||||
<SheetPrimitive.Content
|
||||
{inTransition}
|
||||
{inTransitionConfig}
|
||||
{outTransition}
|
||||
{outTransitionConfig}
|
||||
class={cn(sheetVariants({ side }), className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
<SheetPrimitive.Content bind:ref class={cn(sheetVariants({ side }), className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
<SheetPrimitive.Close
|
||||
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"
|
||||
>
|
||||
<Cross2 class="h-4 w-4" />
|
||||
<X class="size-4" />
|
||||
<span class="sr-only">Close</span>
|
||||
</SheetPrimitive.Close>
|
||||
</SheetPrimitive.Content>
|
||||
</SheetPortal>
|
||||
</SheetPrimitive.Portal>
|
||||
|
@ -2,12 +2,7 @@
|
||||
import { Dialog as SheetPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = SheetPrimitive.DescriptionProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: SheetPrimitive.DescriptionProps = $props();
|
||||
</script>
|
||||
|
||||
<SheetPrimitive.Description class={cn('text-sm text-muted-foreground', className)} {...$$restProps}>
|
||||
<slot />
|
||||
</SheetPrimitive.Description>
|
||||
<SheetPrimitive.Description bind:ref class={cn('text-sm text-muted-foreground', className)} {...restProps} />
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div class={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)} {...$$restProps}>
|
||||
<slot />
|
||||
<div bind:this={ref} class={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import type { WithElementRef } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div class={cn('flex flex-col space-y-2 text-center sm:text-left', className)} {...$$restProps}>
|
||||
<slot />
|
||||
<div bind:this={ref} class={cn('flex flex-col space-y-2 text-center sm:text-left', className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
@ -1,21 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { Dialog as SheetPrimitive } from 'bits-ui';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = SheetPrimitive.OverlayProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
export let transition: $$Props['transition'] = fade;
|
||||
export let transitionConfig: $$Props['transitionConfig'] = {
|
||||
duration: 150,
|
||||
};
|
||||
let { ref = $bindable(null), class: className, ...restProps }: SheetPrimitive.OverlayProps = $props();
|
||||
</script>
|
||||
|
||||
<SheetPrimitive.Overlay
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn('fixed inset-0 z-50 bg-background/80 backdrop-blur-sm', className)}
|
||||
{...$$restProps}
|
||||
bind:ref
|
||||
class={cn(
|
||||
'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
||||
className,
|
||||
)}
|
||||
{...restProps}
|
||||
/>
|
||||
|
@ -2,12 +2,7 @@
|
||||
import { Dialog as SheetPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = SheetPrimitive.TitleProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, ...restProps }: SheetPrimitive.TitleProps = $props();
|
||||
</script>
|
||||
|
||||
<SheetPrimitive.Title class={cn('text-lg font-semibold text-foreground', className)} {...$$restProps}>
|
||||
<slot />
|
||||
</SheetPrimitive.Title>
|
||||
<SheetPrimitive.Title bind:ref class={cn('text-lg font-semibold text-foreground', className)} {...restProps} />
|
||||
|
@ -3,13 +3,16 @@ import Content from './tooltip-content.svelte';
|
||||
|
||||
const Root = TooltipPrimitive.Root;
|
||||
const Trigger = TooltipPrimitive.Trigger;
|
||||
const Provider = TooltipPrimitive.Provider;
|
||||
|
||||
export {
|
||||
Root,
|
||||
Trigger,
|
||||
Content,
|
||||
Provider,
|
||||
//
|
||||
Root as Tooltip,
|
||||
Content as TooltipContent,
|
||||
Trigger as TooltipTrigger,
|
||||
Provider as TooltipProvider,
|
||||
};
|
||||
|
@ -1,25 +1,16 @@
|
||||
<script lang="ts">
|
||||
import { Tooltip as TooltipPrimitive } from 'bits-ui';
|
||||
import { cn, flyAndScale } from '$lib/utils.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
type $$Props = TooltipPrimitive.ContentProps;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let sideOffset: $$Props['sideOffset'] = 4;
|
||||
export let transition: $$Props['transition'] = flyAndScale;
|
||||
export let transitionConfig: $$Props['transitionConfig'] = {
|
||||
y: 8,
|
||||
duration: 150,
|
||||
};
|
||||
export { className as class };
|
||||
let { ref = $bindable(null), class: className, sideOffset = 4, ...restProps }: TooltipPrimitive.ContentProps = $props();
|
||||
</script>
|
||||
|
||||
<TooltipPrimitive.Content
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
bind:ref
|
||||
{sideOffset}
|
||||
class={cn('z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground', className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</TooltipPrimitive.Content>
|
||||
class={cn(
|
||||
'z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||
className,
|
||||
)}
|
||||
{...restProps}
|
||||
/>
|
||||
|
@ -18,13 +18,15 @@
|
||||
<div class="flex w-full items-center align-middle">
|
||||
<p class="font-bold" id="currentuser-username">{data.user.username}</p>
|
||||
</div>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<Button size="icon" href="/account"><Cog /></Button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content>
|
||||
<p>Account Settings</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
<Tooltip.Provider>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<Button size="icon" href="/account"><Cog /></Button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content>
|
||||
<p>Account Settings</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Provider>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -1,53 +1,6 @@
|
||||
import { type ClassValue, clsx } from 'clsx';
|
||||
import { cubicOut } from 'svelte/easing';
|
||||
import type { TransitionConfig } from 'svelte/transition';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
type FlyAndScaleParams = {
|
||||
y?: number;
|
||||
x?: number;
|
||||
start?: number;
|
||||
duration?: number;
|
||||
};
|
||||
|
||||
export const flyAndScale = (node: Element, params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 }): TransitionConfig => {
|
||||
const style = getComputedStyle(node);
|
||||
const transform = style.transform === 'none' ? '' : style.transform;
|
||||
|
||||
const scaleConversion = (valueA: number, scaleA: [number, number], scaleB: [number, number]) => {
|
||||
const [minA, maxA] = scaleA;
|
||||
const [minB, maxB] = scaleB;
|
||||
|
||||
const percentage = (valueA - minA) / (maxA - minA);
|
||||
const valueB = percentage * (maxB - minB) + minB;
|
||||
|
||||
return valueB;
|
||||
};
|
||||
|
||||
const styleToString = (style: Record<string, number | string | undefined>): string => {
|
||||
return Object.keys(style).reduce((str, key) => {
|
||||
if (style[key] === undefined) return str;
|
||||
return str + `${key}:${style[key]};`;
|
||||
}, '');
|
||||
};
|
||||
|
||||
return {
|
||||
duration: params.duration ?? 200,
|
||||
delay: 0,
|
||||
css: (t) => {
|
||||
const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]);
|
||||
const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]);
|
||||
const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]);
|
||||
|
||||
return styleToString({
|
||||
transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`,
|
||||
opacity: t,
|
||||
});
|
||||
},
|
||||
easing: cubicOut,
|
||||
};
|
||||
};
|
||||
|
@ -20,7 +20,14 @@
|
||||
const channel: string = $derived(page.params.channel);
|
||||
let textareaRef: HTMLTextAreaElement | undefined = $state();
|
||||
let formref: HTMLFormElement | undefined = $state();
|
||||
let contextMenus: boolean[] = $state([]);
|
||||
let contextMenus: boolean[] = $state(Array(data.messages.length).fill(false));
|
||||
|
||||
$effect(() => {
|
||||
const totalMessages = (socket?.messages?.length || 0) + data.messages.length;
|
||||
if (contextMenus.length !== totalMessages) {
|
||||
contextMenus = Array(totalMessages).fill(false);
|
||||
}
|
||||
});
|
||||
|
||||
function askNotificationPermission() {
|
||||
// Check if the browser supports notifications
|
||||
@ -84,19 +91,21 @@
|
||||
<div class="relative flex size-full h-full w-full flex-auto flex-grow flex-col-reverse overflow-x-hidden overflow-y-scroll rounded-lg border">
|
||||
{#if data.messages.length != 0 || socket?.messages.length != 0}
|
||||
<div class="flex flex-col-reverse">
|
||||
<!-- Concatenate the two arrays together -->
|
||||
{#each [...(socket?.messages ?? []), ...data.messages] as message, i}
|
||||
<Message
|
||||
bind:open={contextMenus[i]}
|
||||
imageSrc={message.imageSrc}
|
||||
user={message.user}
|
||||
message={message.message}
|
||||
timestamp={message.timestamp}
|
||||
uid={message.uid}
|
||||
{closeDialogs}
|
||||
{i}
|
||||
/>
|
||||
{/each}
|
||||
{#if contextMenus.length === (socket?.messages?.length || 0) + data.messages.length}
|
||||
<!-- Concatenate the two arrays together -->
|
||||
{#each [...(socket?.messages ?? []), ...data.messages] as message, i}
|
||||
<Message
|
||||
bind:open={contextMenus[i]}
|
||||
imageSrc={message.imageSrc}
|
||||
user={message.user}
|
||||
message={message.message}
|
||||
timestamp={message.timestamp}
|
||||
uid={message.uid}
|
||||
{closeDialogs}
|
||||
{i}
|
||||
/>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<EmptyChannel />
|
||||
@ -112,13 +121,15 @@
|
||||
shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1
|
||||
focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
|
||||
></textarea>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger class="h-full min-h-10 w-14 {buttonVariants({ variant: 'default' })}" type="submit">
|
||||
<Send class="size-full" />
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content>
|
||||
<p>Send</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
<Tooltip.Provider>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger class="h-full min-h-10 w-14 {buttonVariants({ variant: 'default' })}" type="submit">
|
||||
<Send class="size-full" />
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content>
|
||||
<p>Send</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Provider>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { fontFamily } from 'tailwindcss/defaultTheme';
|
||||
import type { Config } from 'tailwindcss';
|
||||
import typography from '@tailwindcss/typography';
|
||||
import tailwindcssAnimate from 'tailwindcss-animate';
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ['class'],
|
||||
@ -49,31 +49,48 @@ const config: Config = {
|
||||
DEFAULT: 'hsl(var(--card) / <alpha-value>)',
|
||||
foreground: 'hsl(var(--card-foreground) / <alpha-value>)',
|
||||
},
|
||||
sidebar: {
|
||||
DEFAULT: 'hsl(var(--sidebar-background))',
|
||||
foreground: 'hsl(var(--sidebar-foreground))',
|
||||
primary: 'hsl(var(--sidebar-primary))',
|
||||
'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
|
||||
accent: 'hsl(var(--sidebar-accent))',
|
||||
'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
|
||||
border: 'hsl(var(--sidebar-border))',
|
||||
ring: 'hsl(var(--sidebar-ring))',
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
xl: 'calc(var(--radius) + 4px)',
|
||||
lg: 'var(--radius)',
|
||||
md: 'calc(var(--radius) - 2px)',
|
||||
'background-color': '#22272E',
|
||||
sm: 'calc(var(--radius) - 4px)',
|
||||
},
|
||||
fontFamily: {
|
||||
sans: [...fontFamily.sans],
|
||||
},
|
||||
typography: () => ({
|
||||
DEFAULT: {
|
||||
css: {
|
||||
pre: {
|
||||
'background-color': '#22272E',
|
||||
code: {
|
||||
'background-color': '#22272E',
|
||||
},
|
||||
},
|
||||
},
|
||||
keyframes: {
|
||||
'accordion-down': {
|
||||
from: { height: '0' },
|
||||
to: { height: 'var(--bits-accordion-content-height)' },
|
||||
},
|
||||
}),
|
||||
'accordion-up': {
|
||||
from: { height: 'var(--bits-accordion-content-height)' },
|
||||
to: { height: '0' },
|
||||
},
|
||||
'caret-blink': {
|
||||
'0%,70%,100%': { opacity: '1' },
|
||||
'20%,50%': { opacity: '0' },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||
'caret-blink': 'caret-blink 1.25s ease-out infinite',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [typography],
|
||||
plugins: [tailwindcssAnimate],
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
Loading…
Reference in New Issue
Block a user