feat(*): init

This commit is contained in:
hh committed 2026-10-16 03:41:12 +02:00
commit d7626fd483
184 files changed
+5558

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};
+13
View File
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1" name="viewport">
<meta content="scale" name="text-scale">
<link href="%sveltekit.assets%/favicon.svg" rel="icon" type="image/svg+xml">
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
+5
View File
@@ -0,0 +1,5 @@
import { defineEnvVars } from "@sveltejs/kit/env";
export const variables = defineEnvVars({
PUBLIC_API_BASE_URL: { public: true, schema: (input) => input ?? "/api" },
});
+56
View File
@@ -0,0 +1,56 @@
import { PUBLIC_API_BASE_URL } from "$app/env/public";
const BASE = PUBLIC_API_BASE_URL;
export class ApiError extends Error {
status: number;
constructor(status: number, message: string) {
super(message);
this.status = status;
this.name = "ApiError";
}
}
type Json = Record<string, unknown> | unknown[];
async function handle<T>(res: Response): Promise<T> {
if (res.status === 204) {
return undefined as T;
}
if (res.ok) {
return (await res.json()) as T;
}
let detail = res.statusText;
try {
const { detail: parsed } = (await res.json()) as { detail?: string };
if (parsed) {
detail = parsed;
}
} catch {
detail = res.statusText;
}
throw new ApiError(res.status, detail);
}
async function request<T>(
method: string,
path: string,
body?: Json
): Promise<T> {
const init: RequestInit = { credentials: "include", method };
if (body !== undefined) {
init.headers = { "Content-Type": "application/json" };
init.body = JSON.stringify(body);
}
const res = await fetch(BASE + path, init);
return handle<T>(res);
}
export const api = {
del: <T>(path: string) => request<T>("DELETE", path),
get: <T>(path: string) => request<T>("GET", path),
patch: <T>(path: string, body?: Json) => request<T>("PATCH", path, body),
post: <T>(path: string, body?: Json) => request<T>("POST", path, body),
put: <T>(path: string, body?: Json) => request<T>("PUT", path, body),
};
@@ -0,0 +1,20 @@
<script lang="ts">
import { Avatar as AvatarPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: AvatarPrimitive.FallbackProps = $props();
</script>
<AvatarPrimitive.Fallback
bind:ref
data-slot="avatar-fallback"
class={cn(
"flex size-full items-center justify-center rounded-full font-semibold text-cladd-fg-soft text-cladd-xs uppercase",
className
)}
{...restProps}
/>
@@ -0,0 +1,17 @@
<script lang="ts">
import { Avatar as AvatarPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: AvatarPrimitive.ImageProps = $props();
</script>
<AvatarPrimitive.Image
bind:ref
data-slot="avatar-image"
class={cn("aspect-square size-full", className)}
{...restProps}
/>
@@ -0,0 +1,22 @@
<script lang="ts">
import { Avatar as AvatarPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
loadingStatus = $bindable("loading"),
class: className,
...restProps
}: AvatarPrimitive.RootProps = $props();
</script>
<AvatarPrimitive.Root
bind:ref
bind:loadingStatus
data-slot="avatar"
class={cn(
"cladd-surface cladd-gradient cladd-outline relative flex size-cladd-lg shrink-0 overflow-hidden rounded-full",
className
)}
{...restProps}
/>
+13
View File
@@ -0,0 +1,13 @@
import Root from "./avatar.svelte";
import Image from "./avatar-image.svelte";
import Fallback from "./avatar-fallback.svelte";
export {
Root,
Image,
Fallback,
//
Root as Avatar,
Image as AvatarImage,
Fallback as AvatarFallback,
};
+61
View File
@@ -0,0 +1,61 @@
<script lang="ts" module>
import { type VariantProps, tv } from "tailwind-variants";
export const badgeVariants = tv({
base: "cladd-surface inline-flex h-cladd-nested-md w-fit shrink-0 select-none items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-cladd-sm px-2 font-semibold text-cladd-xs leading-none has-[>svg:first-child]:ps-1.5 has-[>svg:last-child]:pe-1.5 [&>svg]:pointer-events-none [&>svg]:size-3",
variants: {
variant: {
default:
"cladd-gradient cladd-outline cladd-color-brand text-cladd-primary",
secondary: "cladd-gradient cladd-outline text-cladd-fg",
destructive:
"cladd-gradient cladd-outline cladd-color-red text-cladd-primary",
success:
"cladd-gradient cladd-outline cladd-color-green text-cladd-primary",
warning:
"cladd-gradient cladd-outline cladd-color-yellow text-cladd-primary",
outline: "cladd-ghost text-cladd-fg shadow-cladd-outline",
fill: "cladd-gradient-fill cladd-outline cladd-color-brand",
},
},
defaultVariants: {
variant: "default",
},
});
export type BadgeVariant = VariantProps<typeof badgeVariants>["variant"];
</script>
<script lang="ts">
import type { HTMLAnchorAttributes } from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
import { withColor, type CladdColor } from "../button/button.svelte";
let {
ref = $bindable(null),
href,
class: className,
variant = "default",
color,
children,
...restProps
}: WithElementRef<HTMLAnchorAttributes> & {
variant?: BadgeVariant;
color?: CladdColor;
} = $props();
</script>
<svelte:element
this={href ? "a" : "span"}
bind:this={ref}
data-slot="badge"
{href}
class={cn(
withColor(badgeVariants({ variant }), color),
href && "cladd-hoverable cladd-focusable",
className
)}
{...restProps}
>
{@render children?.()}
</svelte:element>
+2
View File
@@ -0,0 +1,2 @@
export { default as Badge } from "./badge.svelte";
export { badgeVariants, type BadgeVariant } from "./badge.svelte";
@@ -0,0 +1,25 @@
<script lang="ts">
import EllipsisIcon from "@lucide/svelte/icons/ellipsis";
import type { HTMLAttributes } from "svelte/elements";
import { cn, type WithElementRef, type WithoutChildren } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: WithoutChildren<
WithElementRef<HTMLAttributes<HTMLSpanElement>>
> = $props();
</script>
<span
bind:this={ref}
data-slot="breadcrumb-ellipsis"
role="presentation"
aria-hidden="true"
class={cn("flex size-9 items-center justify-center", className)}
{...restProps}
>
<EllipsisIcon class="size-4" />
<span class="sr-only">More</span>
</span>
@@ -0,0 +1,20 @@
<script lang="ts">
import type { HTMLLiAttributes } from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLLiAttributes> = $props();
</script>
<li
bind:this={ref}
data-slot="breadcrumb-item"
class={cn("inline-flex items-center gap-1.5", className)}
{...restProps}
>
{@render children?.()}
</li>
@@ -0,0 +1,29 @@
<script lang="ts">
import type { HTMLAnchorAttributes } from "svelte/elements";
import type { Snippet } from "svelte";
import { cn, type WithElementRef } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
href,
child,
children,
...restProps
}: WithElementRef<HTMLAnchorAttributes> & {
child?: Snippet<[{ props: HTMLAnchorAttributes }]>;
} = $props();
const attrs = $derived({
"data-slot": "breadcrumb-link",
class: cn("transition-colors hover:text-foreground", className),
href,
...restProps,
});
</script>
{#if child}
{@render child({ props: attrs })}
{:else}
<a bind:this={ref} {...attrs}> {@render children?.()} </a>
{/if}
@@ -0,0 +1,23 @@
<script lang="ts">
import type { HTMLOlAttributes } from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLOlAttributes> = $props();
</script>
<ol
bind:this={ref}
data-slot="breadcrumb-list"
class={cn(
"flex flex-wrap items-center gap-1.5 break-words font-medium text-cladd-fg-soft text-cladd-xs sm:gap-2.5",
className
)}
{...restProps}
>
{@render children?.()}
</ol>
@@ -0,0 +1,23 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
</script>
<span
bind:this={ref}
data-slot="breadcrumb-page"
role="link"
aria-disabled="true"
aria-current="page"
class={cn("font-medium text-cladd-fg", className)}
{...restProps}
>
{@render children?.()}
</span>
@@ -0,0 +1,27 @@
<script lang="ts">
import ChevronRightIcon from "@lucide/svelte/icons/chevron-right";
import { cn, type WithElementRef } from "#lib/utils.js";
import type { HTMLLiAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLLiAttributes> = $props();
</script>
<li
bind:this={ref}
data-slot="breadcrumb-separator"
role="presentation"
aria-hidden="true"
class={cn("[&>svg]:size-3.5", className)}
{...restProps}
>
{#if children}
{@render children?.()}
{:else}
<ChevronRightIcon />
{/if}
</li>
@@ -0,0 +1,21 @@
<script lang="ts">
import type { WithElementRef } from "#lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
</script>
<nav
bind:this={ref}
data-slot="breadcrumb"
class={className}
aria-label="хлебные крошки"
{...restProps}
>
{@render children?.()}
</nav>
+25
View File
@@ -0,0 +1,25 @@
import Root from "./breadcrumb.svelte";
import Ellipsis from "./breadcrumb-ellipsis.svelte";
import Item from "./breadcrumb-item.svelte";
import Separator from "./breadcrumb-separator.svelte";
import Link from "./breadcrumb-link.svelte";
import List from "./breadcrumb-list.svelte";
import Page from "./breadcrumb-page.svelte";
export {
Root,
Ellipsis,
Item,
Separator,
Link,
List,
Page,
//
Root as Breadcrumb,
Ellipsis as BreadcrumbEllipsis,
Item as BreadcrumbItem,
Separator as BreadcrumbSeparator,
Link as BreadcrumbLink,
List as BreadcrumbList,
Page as BreadcrumbPage,
};
+131
View File
@@ -0,0 +1,131 @@
<script lang="ts" module>
import { cn, type WithElementRef } from "#lib/utils.js";
import type {
HTMLAnchorAttributes,
HTMLButtonAttributes,
} from "svelte/elements";
import { type VariantProps, tv } from "tailwind-variants";
export type CladdColor =
| "neutral"
| "brand"
| "red"
| "pink"
| "purple"
| "blue"
| "cyan"
| "lime"
| "green"
| "yellow"
| "orange";
export const buttonVariants = tv({
base: "cladd-clickable cladd-focusable relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap font-semibold disabled:pointer-events-none disabled:*:opacity-40 aria-disabled:pointer-events-none aria-disabled:*:opacity-40 aria-invalid:outline-destructive [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
variants: {
variant: {
default:
"cladd-surface cladd-gradient cladd-outline cladd-hoverable cladd-color-brand text-cladd-primary",
destructive:
"cladd-surface cladd-gradient cladd-outline cladd-hoverable cladd-color-red text-cladd-primary",
outline:
"cladd-surface cladd-gradient cladd-outline cladd-hoverable text-cladd-fg",
secondary: "cladd-surface cladd-gradient cladd-hoverable text-cladd-fg",
ghost: "cladd-ghost cladd-hoverable text-cladd-fg",
fill: "cladd-surface cladd-gradient-fill cladd-outline cladd-hoverable",
link: "cladd-color-brand text-cladd-primary underline-offset-4 hover:underline",
},
size: {
default: "h-cladd-md rounded-cladd-md px-2.5 text-cladd-xs",
xs: "h-cladd-xs gap-1.5 rounded-cladd-xs px-2 text-cladd-xs [&_svg:not([class*=size-])]:size-3",
sm: "h-cladd-sm gap-1.5 rounded-cladd-sm px-2.5 text-cladd-xs",
lg: "h-cladd-lg rounded-cladd-lg px-3 text-cladd-xs",
xl: "h-cladd-xl rounded-cladd-xl px-3.5 text-cladd-sm",
icon: "size-cladd-md rounded-cladd-md",
"icon-xs":
"size-cladd-xs rounded-cladd-xs [&_svg:not([class*=size-])]:size-3",
"icon-sm": "size-cladd-sm rounded-cladd-sm",
"icon-lg": "size-cladd-lg rounded-cladd-lg",
},
rounded: {
true: "rounded-full",
false: "",
},
},
compoundVariants: [{ variant: "link", class: "h-auto rounded-none px-0" }],
defaultVariants: {
variant: "default",
size: "default",
rounded: false,
},
});
/** Swaps the variant's accent for an explicit one: `<Button color="green">`. */
export function withColor(classes: string, color?: CladdColor) {
if (!color) {
return classes;
}
return `${classes.replace(/\bcladd-color-\w+/g, "")} cladd-color-${color}`;
}
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;
rounded?: boolean;
color?: CladdColor;
};
</script>
<script lang="ts">
let {
class: className,
variant = "default",
size = "default",
rounded = false,
color,
ref = $bindable(null),
href,
type = "button",
disabled,
children,
...restProps
}: ButtonProps = $props();
const classes = $derived(
cn(withColor(buttonVariants({ variant, size, rounded }), color), className)
);
</script>
<!-- Content sits in its own box so the press can shrink it while the surface stays put. -->
{#if href}
<a
bind:this={ref}
data-slot="button"
class={classes}
href={disabled ? undefined : href}
aria-disabled={disabled}
role={disabled ? "link" : undefined}
tabindex={disabled ? -1 : undefined}
{...restProps}
>
<span data-slot="button-content" class="cladd-button-content"
>{@render children?.()}</span
>
</a>
{:else}
<button
bind:this={ref}
data-slot="button"
class={classes}
{type}
{disabled}
{...restProps}
>
<span data-slot="button-content" class="cladd-button-content"
>{@render children?.()}</span
>
</button>
{/if}
+21
View File
@@ -0,0 +1,21 @@
import Root, {
type ButtonProps,
type ButtonSize,
type ButtonVariant,
type CladdColor,
buttonVariants,
withColor,
} from "./button.svelte";
export {
Root,
type ButtonProps as Props,
//
Root as Button,
buttonVariants,
withColor,
type CladdColor,
type ButtonProps,
type ButtonSize,
type ButtonVariant,
};
@@ -0,0 +1,23 @@
<script lang="ts">
import { cn, type WithElementRef } from "#lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="card-action"
class={cn(
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
className
)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,20 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="card-content"
class={cn("px-4", className)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,20 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
</script>
<p
bind:this={ref}
data-slot="card-description"
class={cn("text-cladd-fg-soft text-cladd-xs leading-relaxed", className)}
{...restProps}
>
{@render children?.()}
</p>
@@ -0,0 +1,20 @@
<script lang="ts">
import { cn, type WithElementRef } from "#lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="card-footer"
class={cn("flex items-center gap-2 px-4 [.border-t]:pt-4", className)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,23 @@
<script lang="ts">
import { cn, type WithElementRef } from "#lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="card-header"
class={cn(
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-4",
className
)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,20 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="card-title"
class={cn("font-semibold text-cladd-sm leading-tight", className)}
{...restProps}
>
{@render children?.()}
</div>
+23
View File
@@ -0,0 +1,23 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="card"
class={cn(
"cladd-surface cladd-outline flex flex-col gap-4 rounded-cladd-panel py-4 text-cladd-fg *:[form]:flex *:[form]:flex-col *:[form]:gap-4",
className
)}
{...restProps}
>
{@render children?.()}
</div>
+25
View File
@@ -0,0 +1,25 @@
import Root from "./card.svelte";
import Content from "./card-content.svelte";
import Description from "./card-description.svelte";
import Footer from "./card-footer.svelte";
import Header from "./card-header.svelte";
import Title from "./card-title.svelte";
import Action from "./card-action.svelte";
export {
Root,
Content,
Description,
Footer,
Header,
Title,
Action,
//
Root as Card,
Content as CardContent,
Description as CardDescription,
Footer as CardFooter,
Header as CardHeader,
Title as CardTitle,
Action as CardAction,
};
@@ -0,0 +1,49 @@
<script lang="ts">
import { Checkbox as CheckboxPrimitive } from "bits-ui";
import CheckIcon from "@lucide/svelte/icons/check";
import MinusIcon from "@lucide/svelte/icons/minus";
import { cn, type WithoutChildrenOrChild } from "#lib/utils.js";
let {
ref = $bindable(null),
checked = $bindable(false),
indeterminate = $bindable(false),
class: className,
...restProps
}: WithoutChildrenOrChild<CheckboxPrimitive.RootProps> = $props();
</script>
<CheckboxPrimitive.Root
bind:ref
data-slot="checkbox"
class={cn(
"peer group/checkbox cladd-surface cladd-gradient cladd-outline cladd-hoverable cladd-clickable cladd-focusable relative flex size-cladd-thumb-sm shrink-0 items-center justify-center rounded-full text-cladd-fg-soft disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:outline-destructive",
"cladd-fill-checked",
(checked || indeterminate) && "cladd-color-brand",
className
)}
bind:checked
bind:indeterminate
{...restProps}
>
{#snippet children({
checked,
indeterminate,
})}
<span
data-slot="checkbox-indicator"
class={cn(
"flex items-center justify-center transition-[scale,color] duration-200",
checked || indeterminate
? "text-cladd-on-primary group-active/checkbox:scale-90"
: "scale-75 group-active/checkbox:scale-65"
)}
>
{#if indeterminate}
<MinusIcon class="size-3" strokeWidth={3} />
{:else}
<CheckIcon class="size-3" strokeWidth={3} />
{/if}
</span>
{/snippet}
</CheckboxPrimitive.Root>
+6
View File
@@ -0,0 +1,6 @@
import Root from "./checkbox.svelte";
export {
Root,
//
Root as Checkbox,
};
@@ -0,0 +1,14 @@
<script lang="ts">
import { Collapsible as CollapsiblePrimitive } from "bits-ui";
let {
ref = $bindable(null),
...restProps
}: CollapsiblePrimitive.ContentProps = $props();
</script>
<CollapsiblePrimitive.Content
bind:ref
data-slot="collapsible-content"
{...restProps}
/>
@@ -0,0 +1,14 @@
<script lang="ts">
import { Collapsible as CollapsiblePrimitive } from "bits-ui";
let {
ref = $bindable(null),
...restProps
}: CollapsiblePrimitive.TriggerProps = $props();
</script>
<CollapsiblePrimitive.Trigger
bind:ref
data-slot="collapsible-trigger"
{...restProps}
/>
@@ -0,0 +1,16 @@
<script lang="ts">
import { Collapsible as CollapsiblePrimitive } from "bits-ui";
let {
ref = $bindable(null),
open = $bindable(false),
...restProps
}: CollapsiblePrimitive.RootProps = $props();
</script>
<CollapsiblePrimitive.Root
bind:ref
bind:open
data-slot="collapsible"
{...restProps}
/>
@@ -0,0 +1,13 @@
import Root from "./collapsible.svelte";
import Trigger from "./collapsible-trigger.svelte";
import Content from "./collapsible-content.svelte";
export {
Root,
Content,
Trigger,
//
Root as Collapsible,
Content as CollapsibleContent,
Trigger as CollapsibleTrigger,
};
@@ -0,0 +1,42 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import CheckIcon from "@lucide/svelte/icons/check";
import { cn, type WithoutChildrenOrChild } from "#lib/utils.js";
import type { Snippet } from "svelte";
let {
ref = $bindable(null),
checked = $bindable(false),
indeterminate = $bindable(false),
class: className,
children: childrenProp,
...restProps
}: WithoutChildrenOrChild<ContextMenuPrimitive.CheckboxItemProps> & {
children?: Snippet;
} = $props();
</script>
<ContextMenuPrimitive.CheckboxItem
bind:ref
bind:checked
bind:indeterminate
data-slot="context-menu-checkbox-item"
class={cn(
"relative flex min-h-cladd-lg cursor-default select-none items-center gap-2 rounded-full py-1 ps-9 pe-3 font-medium text-cladd-xs outline-hidden transition-[background-color,box-shadow] duration-200 data-[disabled]:pointer-events-none data-highlighted:bg-cladd-surface-next data-[disabled]:opacity-40 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...restProps}
>
{#snippet children({
checked,
})}
<span
class="pointer-events-none absolute start-3 flex size-4 items-center justify-center"
>
{#if checked}
<CheckIcon class="size-4" />
{/if}
</span>
{@render childrenProp?.()}
{/snippet}
</ContextMenuPrimitive.CheckboxItem>
@@ -0,0 +1,30 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
import ContextMenuPortal from "./context-menu-portal.svelte";
import type { ComponentProps } from "svelte";
import type { WithoutChildrenOrChild } from "#lib/utils.js";
let {
ref = $bindable(null),
portalProps,
class: className,
...restProps
}: ContextMenuPrimitive.ContentProps & {
portalProps?: WithoutChildrenOrChild<
ComponentProps<typeof ContextMenuPortal>
>;
} = $props();
</script>
<ContextMenuPortal {...portalProps}>
<ContextMenuPrimitive.Content
bind:ref
data-slot="context-menu-content"
class={cn(
"cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-popover z-50 max-h-(--bits-context-menu-content-available-height) min-w-[10rem] origin-(--bits-context-menu-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-cladd-popover p-2 text-cladd-fg shadow-cladd-popover outline-none",
className
)}
{...restProps}
/>
</ContextMenuPortal>
@@ -0,0 +1,24 @@
<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
data-slot="context-menu-group-heading"
data-inset={inset}
class={cn(
"cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-8 data-[inset]:ps-9",
className
)}
{...restProps}
/>
@@ -0,0 +1,12 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
let { ref = $bindable(null), ...restProps }: ContextMenuPrimitive.GroupProps =
$props();
</script>
<ContextMenuPrimitive.Group
bind:ref
data-slot="context-menu-group"
{...restProps}
/>
@@ -0,0 +1,27 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
inset,
variant = "default",
...restProps
}: ContextMenuPrimitive.ItemProps & {
inset?: boolean;
variant?: "default" | "destructive";
} = $props();
</script>
<ContextMenuPrimitive.Item
bind:ref
data-slot="context-menu-item"
data-inset={inset}
data-variant={variant}
class={cn(
"data-[variant=destructive]:*:[svg]:!text-destructive relative flex min-h-cladd-lg cursor-default select-none items-center gap-2 rounded-full px-3 py-1 font-medium text-cladd-xs outline-hidden transition-[background-color,box-shadow] duration-200 data-[variant=destructive]:data-highlighted:bg-destructive/12 data-[disabled]:pointer-events-none data-highlighted:bg-cladd-surface-next data-[inset]:ps-8 data-[inset]:ps-9 data-[variant=destructive]:text-destructive data-[disabled]:opacity-40 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...restProps}
/>
@@ -0,0 +1,27 @@
<script lang="ts">
import { cn, type WithElementRef } from "#lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
inset,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
inset?: boolean;
} = $props();
</script>
<div
bind:this={ref}
data-slot="context-menu-label"
data-inset={inset}
class={cn(
"cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-8 data-[inset]:ps-9",
className
)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,7 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
let { ...restProps }: ContextMenuPrimitive.PortalProps = $props();
</script>
<ContextMenuPrimitive.Portal {...restProps} />
@@ -0,0 +1,16 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
let {
ref = $bindable(null),
value = $bindable(""),
...restProps
}: ContextMenuPrimitive.RadioGroupProps = $props();
</script>
<ContextMenuPrimitive.RadioGroup
bind:ref
bind:value
data-slot="context-menu-radio-group"
{...restProps}
/>
@@ -0,0 +1,35 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import CircleIcon from "@lucide/svelte/icons/circle";
import { cn, type WithoutChild } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children: childrenProp,
...restProps
}: WithoutChild<ContextMenuPrimitive.RadioItemProps> = $props();
</script>
<ContextMenuPrimitive.RadioItem
bind:ref
data-slot="context-menu-radio-item"
class={cn(
"relative flex min-h-cladd-lg cursor-default select-none items-center gap-2 rounded-full py-1 ps-9 pe-3 font-medium text-cladd-xs outline-hidden transition-[background-color,box-shadow] duration-200 data-[disabled]:pointer-events-none data-highlighted:bg-cladd-surface-next data-[disabled]:opacity-40 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...restProps}
>
{#snippet children({
checked,
})}
<span
class="pointer-events-none absolute start-3 flex size-4 items-center justify-center"
>
{#if checked}
<CircleIcon class="size-2 fill-current" />
{/if}
</span>
{@render childrenProp?.({ checked })}
{/snippet}
</ContextMenuPrimitive.RadioItem>
@@ -0,0 +1,17 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: ContextMenuPrimitive.SeparatorProps = $props();
</script>
<ContextMenuPrimitive.Separator
bind:ref
data-slot="context-menu-separator"
class={cn("-mx-2 my-2 h-px bg-cladd-bg-outline", className)}
{...restProps}
/>
@@ -0,0 +1,23 @@
<script lang="ts">
import { cn, type WithElementRef } from "#lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
</script>
<span
bind:this={ref}
data-slot="context-menu-shortcut"
class={cn(
"ms-auto font-mono text-cladd-2xs text-cladd-fg-softer tracking-widest",
className
)}
{...restProps}
>
{@render children?.()}
</span>
@@ -0,0 +1,20 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: ContextMenuPrimitive.SubContentProps = $props();
</script>
<ContextMenuPrimitive.SubContent
bind:ref
data-slot="context-menu-sub-content"
class={cn(
"cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-popover z-50 min-w-[10rem] origin-(--bits-context-menu-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-cladd-popover p-2 text-cladd-fg shadow-cladd-popover outline-none",
className
)}
{...restProps}
/>
@@ -0,0 +1,29 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import ChevronRightIcon from "@lucide/svelte/icons/chevron-right";
import { cn, type WithoutChild } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
inset,
children,
...restProps
}: WithoutChild<ContextMenuPrimitive.SubTriggerProps> & {
inset?: boolean;
} = $props();
</script>
<ContextMenuPrimitive.SubTrigger
bind:ref
data-slot="context-menu-sub-trigger"
data-inset={inset}
class={cn(
"relative flex min-h-cladd-lg cursor-default select-none items-center gap-2 rounded-full px-3 py-1 font-medium text-cladd-xs outline-hidden transition-[background-color,box-shadow] duration-200 data-[disabled]:pointer-events-none data-[state=open]:bg-cladd-surface-next data-highlighted:bg-cladd-surface-next data-[inset]:ps-8 data-[inset]:ps-9 data-[disabled]:opacity-40 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...restProps}
>
{@render children?.()}
<ChevronRightIcon class="ms-auto" />
</ContextMenuPrimitive.SubTrigger>
@@ -0,0 +1,8 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
let { open = $bindable(false), ...restProps }: ContextMenuPrimitive.SubProps =
$props();
</script>
<ContextMenuPrimitive.Sub bind:open {...restProps} />
@@ -0,0 +1,14 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
let {
ref = $bindable(null),
...restProps
}: ContextMenuPrimitive.TriggerProps = $props();
</script>
<ContextMenuPrimitive.Trigger
bind:ref
data-slot="context-menu-trigger"
{...restProps}
/>
@@ -0,0 +1,10 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
let {
open = $bindable(false),
...restProps
}: ContextMenuPrimitive.RootProps = $props();
</script>
<ContextMenuPrimitive.Root bind:open {...restProps} />
@@ -0,0 +1,52 @@
import Root from "./context-menu.svelte";
import Sub from "./context-menu-sub.svelte";
import Portal from "./context-menu-portal.svelte";
import Trigger from "./context-menu-trigger.svelte";
import Group from "./context-menu-group.svelte";
import RadioGroup from "./context-menu-radio-group.svelte";
import Item from "./context-menu-item.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 SubContent from "./context-menu-sub-content.svelte";
import SubTrigger from "./context-menu-sub-trigger.svelte";
import CheckboxItem from "./context-menu-checkbox-item.svelte";
import Label from "./context-menu-label.svelte";
export {
Root,
Sub,
Portal,
Item,
GroupHeading,
Label,
Group,
Trigger,
Content,
Shortcut,
Separator,
RadioItem,
SubContent,
SubTrigger,
RadioGroup,
CheckboxItem,
//
Root as ContextMenu,
Sub as ContextMenuSub,
Portal as ContextMenuPortal,
Item as ContextMenuItem,
GroupHeading as ContextMenuGroupHeading,
Group as ContextMenuGroup,
Content as ContextMenuContent,
Trigger as ContextMenuTrigger,
Shortcut as ContextMenuShortcut,
RadioItem as ContextMenuRadioItem,
Separator as ContextMenuSeparator,
RadioGroup as ContextMenuRadioGroup,
SubContent as ContextMenuSubContent,
SubTrigger as ContextMenuSubTrigger,
CheckboxItem as ContextMenuCheckboxItem,
Label as ContextMenuLabel,
};
@@ -0,0 +1,8 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from "bits-ui";
let { ref = $bindable(null), ...restProps }: DialogPrimitive.CloseProps =
$props();
</script>
<DialogPrimitive.Close bind:ref data-slot="dialog-close" {...restProps} />
@@ -0,0 +1,45 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from "bits-ui";
import DialogPortal from "./dialog-portal.svelte";
import XIcon from "@lucide/svelte/icons/x";
import type { Snippet } from "svelte";
import * as Dialog from "./index.js";
import { cn, type WithoutChildrenOrChild } from "#lib/utils.js";
import type { ComponentProps } from "svelte";
let {
ref = $bindable(null),
class: className,
portalProps,
children,
showCloseButton = true,
...restProps
}: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof DialogPortal>>;
children: Snippet;
showCloseButton?: boolean;
} = $props();
</script>
<DialogPortal {...portalProps}>
<Dialog.Overlay />
<DialogPrimitive.Content
bind:ref
data-slot="dialog-content"
class={cn(
"cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-dialog fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-cladd-dialog p-4 text-cladd-fg shadow-cladd-popover outline-none sm:max-w-lg",
className
)}
{...restProps}
>
{@render children?.()}
{#if showCloseButton}
<DialogPrimitive.Close
class="cladd-ghost cladd-hoverable cladd-clickable cladd-focusable absolute end-3 top-3 flex size-cladd-md items-center justify-center rounded-full text-cladd-fg-soft disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
>
<XIcon />
<span class="sr-only">Close</span>
</DialogPrimitive.Close>
{/if}
</DialogPrimitive.Content>
</DialogPortal>
@@ -0,0 +1,17 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: DialogPrimitive.DescriptionProps = $props();
</script>
<DialogPrimitive.Description
bind:ref
data-slot="dialog-description"
class={cn("text-cladd-fg-soft text-cladd-sm leading-relaxed", className)}
{...restProps}
/>
@@ -0,0 +1,23 @@
<script lang="ts">
import { cn, type WithElementRef } from "#lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="dialog-footer"
class={cn(
"mt-2 flex flex-col-reverse gap-2 sm:flex-row sm:flex-wrap sm:items-center sm:justify-end",
className
)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,20 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="dialog-header"
class={cn("flex flex-col gap-1.5 text-start", className)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,17 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: DialogPrimitive.OverlayProps = $props();
</script>
<DialogPrimitive.Overlay
bind:ref
data-slot="dialog-overlay"
class={cn("cladd-backdrop cladd-anim-fade fixed inset-0 z-50", className)}
{...restProps}
/>
@@ -0,0 +1,7 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from "bits-ui";
let { ...restProps }: DialogPrimitive.PortalProps = $props();
</script>
<DialogPrimitive.Portal {...restProps} />
@@ -0,0 +1,17 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: DialogPrimitive.TitleProps = $props();
</script>
<DialogPrimitive.Title
bind:ref
data-slot="dialog-title"
class={cn("pe-8 font-semibold text-cladd-md leading-tight", className)}
{...restProps}
/>
@@ -0,0 +1,8 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from "bits-ui";
let { ref = $bindable(null), ...restProps }: DialogPrimitive.TriggerProps =
$props();
</script>
<DialogPrimitive.Trigger bind:ref data-slot="dialog-trigger" {...restProps} />
@@ -0,0 +1,8 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from "bits-ui";
let { open = $bindable(false), ...restProps }: DialogPrimitive.RootProps =
$props();
</script>
<DialogPrimitive.Root bind:open {...restProps} />
+34
View File
@@ -0,0 +1,34 @@
import Root from "./dialog.svelte";
import Portal from "./dialog-portal.svelte";
import Title from "./dialog-title.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";
import Trigger from "./dialog-trigger.svelte";
import Close from "./dialog-close.svelte";
export {
Root,
Title,
Portal,
Footer,
Header,
Trigger,
Overlay,
Content,
Description,
Close,
//
Root as Dialog,
Title as DialogTitle,
Portal as DialogPortal,
Footer as DialogFooter,
Header as DialogHeader,
Trigger as DialogTrigger,
Overlay as DialogOverlay,
Content as DialogContent,
Description as DialogDescription,
Close as DialogClose,
};
@@ -0,0 +1,16 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
let {
ref = $bindable(null),
value = $bindable([]),
...restProps
}: DropdownMenuPrimitive.CheckboxGroupProps = $props();
</script>
<DropdownMenuPrimitive.CheckboxGroup
bind:ref
bind:value
data-slot="dropdown-menu-checkbox-group"
{...restProps}
/>
@@ -0,0 +1,46 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
import CheckIcon from "@lucide/svelte/icons/check";
import MinusIcon from "@lucide/svelte/icons/minus";
import { cn, type WithoutChildrenOrChild } from "#lib/utils.js";
import type { Snippet } from "svelte";
let {
ref = $bindable(null),
checked = $bindable(false),
indeterminate = $bindable(false),
class: className,
children: childrenProp,
...restProps
}: WithoutChildrenOrChild<DropdownMenuPrimitive.CheckboxItemProps> & {
children?: Snippet;
} = $props();
</script>
<DropdownMenuPrimitive.CheckboxItem
bind:ref
bind:checked
bind:indeterminate
data-slot="dropdown-menu-checkbox-item"
class={cn(
"relative flex min-h-cladd-lg cursor-default select-none items-center gap-2 rounded-full py-1 ps-9 pe-3 font-medium text-cladd-xs outline-hidden transition-[background-color,box-shadow] duration-200 data-[disabled]:pointer-events-none data-highlighted:bg-cladd-surface-next data-[disabled]:opacity-40 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...restProps}
>
{#snippet children({
checked,
indeterminate,
})}
<span
class="pointer-events-none absolute start-3 flex size-4 items-center justify-center"
>
{#if indeterminate}
<MinusIcon class="size-4" />
{:else}
<CheckIcon class={cn("size-4", !checked && "text-transparent")} />
{/if}
</span>
{@render childrenProp?.()}
{/snippet}
</DropdownMenuPrimitive.CheckboxItem>
@@ -0,0 +1,31 @@
<script lang="ts">
import { cn, type WithoutChildrenOrChild } from "#lib/utils.js";
import DropdownMenuPortal from "./dropdown-menu-portal.svelte";
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
import type { ComponentProps } from "svelte";
let {
ref = $bindable(null),
sideOffset = 4,
portalProps,
class: className,
...restProps
}: DropdownMenuPrimitive.ContentProps & {
portalProps?: WithoutChildrenOrChild<
ComponentProps<typeof DropdownMenuPortal>
>;
} = $props();
</script>
<DropdownMenuPortal {...portalProps}>
<DropdownMenuPrimitive.Content
bind:ref
data-slot="dropdown-menu-content"
{sideOffset}
class={cn(
"cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-popover z-50 max-h-(--bits-dropdown-menu-content-available-height) min-w-[10rem] origin-(--bits-dropdown-menu-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-cladd-popover p-2 text-cladd-fg shadow-cladd-popover outline-none",
className
)}
{...restProps}
/>
</DropdownMenuPortal>
@@ -0,0 +1,25 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
import type { ComponentProps } from "svelte";
let {
ref = $bindable(null),
class: className,
inset,
...restProps
}: ComponentProps<typeof DropdownMenuPrimitive.GroupHeading> & {
inset?: boolean;
} = $props();
</script>
<DropdownMenuPrimitive.GroupHeading
bind:ref
data-slot="dropdown-menu-group-heading"
data-inset={inset}
class={cn(
"cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-8 data-[inset]:ps-9",
className
)}
{...restProps}
/>
@@ -0,0 +1,14 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
let {
ref = $bindable(null),
...restProps
}: DropdownMenuPrimitive.GroupProps = $props();
</script>
<DropdownMenuPrimitive.Group
bind:ref
data-slot="dropdown-menu-group"
{...restProps}
/>
@@ -0,0 +1,28 @@
<script lang="ts">
import { cn } from "#lib/utils.js";
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
let {
ref = $bindable(null),
class: className,
inset,
variant = "default",
...restProps
}: DropdownMenuPrimitive.ItemProps & {
inset?: boolean;
variant?: "default" | "destructive";
asChild?: boolean;
} = $props();
</script>
<DropdownMenuPrimitive.Item
bind:ref
data-slot="dropdown-menu-item"
data-inset={inset}
data-variant={variant}
class={cn(
"data-[variant=destructive]:*:[svg]:!text-destructive relative flex min-h-cladd-lg cursor-default select-none items-center gap-2 rounded-full px-3 py-1 font-medium text-cladd-xs outline-hidden transition-[background-color,box-shadow] duration-200 data-[variant=destructive]:data-highlighted:bg-destructive/12 data-[disabled]:pointer-events-none data-highlighted:bg-cladd-surface-next data-[inset]:ps-8 data-[inset]:ps-9 data-[variant=destructive]:text-destructive data-[disabled]:opacity-40 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...restProps}
/>
@@ -0,0 +1,27 @@
<script lang="ts">
import { cn, type WithElementRef } from "#lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
inset,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
inset?: boolean;
} = $props();
</script>
<div
bind:this={ref}
data-slot="dropdown-menu-label"
data-inset={inset}
class={cn(
"cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-8 data-[inset]:ps-9",
className
)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,7 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
let { ...restProps }: DropdownMenuPrimitive.PortalProps = $props();
</script>
<DropdownMenuPrimitive.Portal {...restProps} />
@@ -0,0 +1,16 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
let {
ref = $bindable(null),
value = $bindable(),
...restProps
}: DropdownMenuPrimitive.RadioGroupProps = $props();
</script>
<DropdownMenuPrimitive.RadioGroup
bind:ref
bind:value
data-slot="dropdown-menu-radio-group"
{...restProps}
/>
@@ -0,0 +1,35 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
import CircleIcon from "@lucide/svelte/icons/circle";
import { cn, type WithoutChild } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children: childrenProp,
...restProps
}: WithoutChild<DropdownMenuPrimitive.RadioItemProps> = $props();
</script>
<DropdownMenuPrimitive.RadioItem
bind:ref
data-slot="dropdown-menu-radio-item"
class={cn(
"relative flex min-h-cladd-lg cursor-default select-none items-center gap-2 rounded-full py-1 ps-9 pe-3 font-medium text-cladd-xs outline-hidden transition-[background-color,box-shadow] duration-200 data-[disabled]:pointer-events-none data-highlighted:bg-cladd-surface-next data-[disabled]:opacity-40 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...restProps}
>
{#snippet children({
checked,
})}
<span
class="pointer-events-none absolute start-3 flex size-4 items-center justify-center"
>
{#if checked}
<CircleIcon class="size-2 fill-current" />
{/if}
</span>
{@render childrenProp?.({ checked })}
{/snippet}
</DropdownMenuPrimitive.RadioItem>
@@ -0,0 +1,17 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: DropdownMenuPrimitive.SeparatorProps = $props();
</script>
<DropdownMenuPrimitive.Separator
bind:ref
data-slot="dropdown-menu-separator"
class={cn("-mx-2 my-2 h-px bg-cladd-bg-outline", className)}
{...restProps}
/>
@@ -0,0 +1,23 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
</script>
<span
bind:this={ref}
data-slot="dropdown-menu-shortcut"
class={cn(
"ms-auto font-mono text-cladd-2xs text-cladd-fg-softer tracking-widest",
className
)}
{...restProps}
>
{@render children?.()}
</span>
@@ -0,0 +1,20 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: DropdownMenuPrimitive.SubContentProps = $props();
</script>
<DropdownMenuPrimitive.SubContent
bind:ref
data-slot="dropdown-menu-sub-content"
class={cn(
"cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-popover z-50 min-w-[10rem] origin-(--bits-dropdown-menu-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-cladd-popover p-2 text-cladd-fg shadow-cladd-popover outline-none",
className
)}
{...restProps}
/>
@@ -0,0 +1,29 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
import ChevronRightIcon from "@lucide/svelte/icons/chevron-right";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
inset,
children,
...restProps
}: DropdownMenuPrimitive.SubTriggerProps & {
inset?: boolean;
} = $props();
</script>
<DropdownMenuPrimitive.SubTrigger
bind:ref
data-slot="dropdown-menu-sub-trigger"
data-inset={inset}
class={cn(
"relative flex min-h-cladd-lg cursor-default select-none items-center gap-2 rounded-full px-3 py-1 font-medium text-cladd-xs outline-hidden transition-[background-color,box-shadow] duration-200 data-[disabled]:pointer-events-none data-[state=open]:bg-cladd-surface-next data-highlighted:bg-cladd-surface-next data-[inset]:ps-8 data-[inset]:ps-9 data-[disabled]:opacity-40 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...restProps}
>
{@render children?.()}
<ChevronRightIcon class="ms-auto size-4" />
</DropdownMenuPrimitive.SubTrigger>
@@ -0,0 +1,10 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
let {
open = $bindable(false),
...restProps
}: DropdownMenuPrimitive.SubProps = $props();
</script>
<DropdownMenuPrimitive.Sub bind:open {...restProps} />
@@ -0,0 +1,14 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
let {
ref = $bindable(null),
...restProps
}: DropdownMenuPrimitive.TriggerProps = $props();
</script>
<DropdownMenuPrimitive.Trigger
bind:ref
data-slot="dropdown-menu-trigger"
{...restProps}
/>
@@ -0,0 +1,10 @@
<script lang="ts">
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
let {
open = $bindable(false),
...restProps
}: DropdownMenuPrimitive.RootProps = $props();
</script>
<DropdownMenuPrimitive.Root bind:open {...restProps} />
@@ -0,0 +1,54 @@
import Root from "./dropdown-menu.svelte";
import Sub from "./dropdown-menu-sub.svelte";
import CheckboxGroup from "./dropdown-menu-checkbox-group.svelte";
import CheckboxItem from "./dropdown-menu-checkbox-item.svelte";
import Content from "./dropdown-menu-content.svelte";
import Group from "./dropdown-menu-group.svelte";
import Item from "./dropdown-menu-item.svelte";
import Label from "./dropdown-menu-label.svelte";
import RadioGroup from "./dropdown-menu-radio-group.svelte";
import RadioItem from "./dropdown-menu-radio-item.svelte";
import Separator from "./dropdown-menu-separator.svelte";
import Shortcut from "./dropdown-menu-shortcut.svelte";
import Trigger from "./dropdown-menu-trigger.svelte";
import SubContent from "./dropdown-menu-sub-content.svelte";
import SubTrigger from "./dropdown-menu-sub-trigger.svelte";
import GroupHeading from "./dropdown-menu-group-heading.svelte";
import Portal from "./dropdown-menu-portal.svelte";
export {
CheckboxGroup,
CheckboxItem,
Content,
Portal,
Root as DropdownMenu,
CheckboxGroup as DropdownMenuCheckboxGroup,
CheckboxItem as DropdownMenuCheckboxItem,
Content as DropdownMenuContent,
Portal as DropdownMenuPortal,
Group as DropdownMenuGroup,
Item as DropdownMenuItem,
Label as DropdownMenuLabel,
RadioGroup as DropdownMenuRadioGroup,
RadioItem as DropdownMenuRadioItem,
Separator as DropdownMenuSeparator,
Shortcut as DropdownMenuShortcut,
Sub as DropdownMenuSub,
SubContent as DropdownMenuSubContent,
SubTrigger as DropdownMenuSubTrigger,
Trigger as DropdownMenuTrigger,
GroupHeading as DropdownMenuGroupHeading,
Group,
GroupHeading,
Item,
Label,
RadioGroup,
RadioItem,
Root,
Separator,
Shortcut,
Sub,
SubContent,
SubTrigger,
Trigger,
};
+7
View File
@@ -0,0 +1,7 @@
import Root from "./input.svelte";
export {
Root,
//
Root as Input,
};
+54
View File
@@ -0,0 +1,54 @@
<script lang="ts">
import type {
HTMLInputAttributes,
HTMLInputTypeAttribute,
} from "svelte/elements";
import { cn, type WithElementRef } from "#lib/utils.js";
type InputType = Exclude<HTMLInputTypeAttribute, "file">;
type Props = WithElementRef<
Omit<HTMLInputAttributes, "type"> &
(
| { type: "file"; files?: FileList }
| { type?: InputType; files?: undefined }
)
>;
let {
ref = $bindable(null),
value = $bindable(),
type,
files = $bindable(),
class: className,
"data-slot": dataSlot = "input",
...restProps
}: Props = $props();
</script>
{#if type === "file"}
<input
bind:this={ref}
data-slot={dataSlot}
class={cn(
"cladd-cut cladd-hoverable cladd-focusable-input flex h-cladd-md w-full min-w-0 rounded-cladd-md px-2.5 pt-1.5 font-medium text-cladd-fg text-cladd-xs selection:bg-brand/30 file:me-2 file:font-semibold file:text-cladd-fg placeholder:text-cladd-fg-softer disabled:cursor-not-allowed disabled:opacity-50",
className
)}
type="file"
bind:files
bind:value
{...restProps}
>
{:else}
<input
bind:this={ref}
data-slot={dataSlot}
class={cn(
"cladd-cut cladd-hoverable cladd-focusable-input flex h-cladd-md w-full min-w-0 rounded-cladd-md px-2.5 py-1 font-medium text-cladd-fg text-cladd-xs selection:bg-brand/30 placeholder:text-cladd-fg-softer disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{type}
bind:value
{...restProps}
>
{/if}
+3
View File
@@ -0,0 +1,3 @@
import Label from "./label.svelte";
export { Label };
+27
View File
@@ -0,0 +1,27 @@
<script lang="ts">
import { Label as LabelPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: {
ref?: any;
class?: string;
children?: any;
[key: string]: any;
} = $props();
</script>
<LabelPrimitive.Root
bind:ref
class={cn(
"font-medium text-cladd-fg-soft text-cladd-xs leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
className
)}
{...restProps}
>
{@render children?.()}
</LabelPrimitive.Root>
+7
View File
@@ -0,0 +1,7 @@
import Root from "./progress.svelte";
export {
Root,
//
Root as Progress,
};
@@ -0,0 +1,30 @@
<script lang="ts">
import { Progress as ProgressPrimitive } from "bits-ui";
import { cn, type WithoutChildrenOrChild } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
max = 100,
value,
...restProps
}: WithoutChildrenOrChild<ProgressPrimitive.RootProps> = $props();
</script>
<ProgressPrimitive.Root
bind:ref
data-slot="progress"
class={cn(
"cladd-cut relative h-2 w-full overflow-hidden rounded-full",
className
)}
{value}
{max}
{...restProps}
>
<div
data-slot="progress-indicator"
class="cladd-surface cladd-gradient-fill cladd-color-brand h-full w-full flex-1 rounded-full transition-all duration-300 ease-out"
style="transform: translateX(-{100 - (100 * (value ?? 0)) / (max ?? 1)}%)"
></div>
</ProgressPrimitive.Root>
+37
View File
@@ -0,0 +1,37 @@
import Root from "./select.svelte";
import Group from "./select-group.svelte";
import Label from "./select-label.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";
import GroupHeading from "./select-group-heading.svelte";
import Portal from "./select-portal.svelte";
export {
Root,
Group,
Label,
Item,
Content,
Trigger,
Separator,
ScrollDownButton,
ScrollUpButton,
GroupHeading,
Portal,
//
Root as Select,
Group as SelectGroup,
Label as SelectLabel,
Item as SelectItem,
Content as SelectContent,
Trigger as SelectTrigger,
Separator as SelectSeparator,
ScrollDownButton as SelectScrollDownButton,
ScrollUpButton as SelectScrollUpButton,
GroupHeading as SelectGroupHeading,
Portal as SelectPortal,
};
@@ -0,0 +1,45 @@
<script lang="ts">
import { Select as SelectPrimitive } from "bits-ui";
import SelectPortal from "./select-portal.svelte";
import SelectScrollUpButton from "./select-scroll-up-button.svelte";
import SelectScrollDownButton from "./select-scroll-down-button.svelte";
import { cn, type WithoutChild } from "#lib/utils.js";
import type { ComponentProps } from "svelte";
import type { WithoutChildrenOrChild } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
sideOffset = 4,
portalProps,
children,
preventScroll = true,
...restProps
}: WithoutChild<SelectPrimitive.ContentProps> & {
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof SelectPortal>>;
} = $props();
</script>
<SelectPortal {...portalProps}>
<SelectPrimitive.Content
bind:ref
{sideOffset}
{preventScroll}
data-slot="select-content"
class={cn(
"cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-popover z-50 max-h-(--bits-select-content-available-height) min-w-[10rem] origin-(--bits-select-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-cladd-popover text-cladd-fg shadow-cladd-popover outline-none",
className
)}
{...restProps}
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
class={cn(
"h-(--bits-select-anchor-height) w-full min-w-(--bits-select-anchor-width) scroll-my-2 p-2"
)}
>
{@render children?.()}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPortal>
@@ -0,0 +1,24 @@
<script lang="ts">
import { Select as SelectPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
import type { ComponentProps } from "svelte";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: ComponentProps<typeof SelectPrimitive.GroupHeading> = $props();
</script>
<SelectPrimitive.GroupHeading
bind:ref
data-slot="select-group-heading"
class={cn(
"cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-9",
className
)}
{...restProps}
>
{@render children?.()}
</SelectPrimitive.GroupHeading>
@@ -0,0 +1,8 @@
<script lang="ts">
import { Select as SelectPrimitive } from "bits-ui";
let { ref = $bindable(null), ...restProps }: SelectPrimitive.GroupProps =
$props();
</script>
<SelectPrimitive.Group bind:ref data-slot="select-group" {...restProps} />
@@ -0,0 +1,41 @@
<script lang="ts">
import CheckIcon from "@lucide/svelte/icons/check";
import { Select as SelectPrimitive } from "bits-ui";
import { cn, type WithoutChild } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
value,
label,
children: childrenProp,
...restProps
}: WithoutChild<SelectPrimitive.ItemProps> = $props();
</script>
<SelectPrimitive.Item
bind:ref
{value}
data-slot="select-item"
class={cn(
"relative flex min-h-cladd-lg cursor-default select-none items-center gap-2 rounded-full py-1 ps-3 pe-9 font-medium text-cladd-xs outline-hidden transition-[background-color,box-shadow] duration-200 data-[disabled]:pointer-events-none data-[selected]:bg-cladd-surface-next data-highlighted:bg-cladd-surface-next data-[disabled]:opacity-40 data-[selected]:shadow-cladd-outline [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft [&_svg]:pointer-events-none [&_svg]:shrink-0 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
className
)}
{...restProps}
>
{#snippet children({
selected,
highlighted,
})}
<span class="absolute end-3 flex size-4 items-center justify-center">
{#if selected}
<CheckIcon class="size-4 text-cladd-fg" />
{/if}
</span>
{#if childrenProp}
{@render childrenProp({ selected, highlighted })}
{:else}
{label || value}
{/if}
{/snippet}
</SelectPrimitive.Item>
@@ -0,0 +1,23 @@
<script lang="ts">
import { cn, type WithElementRef } from "#lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {} = $props();
</script>
<div
bind:this={ref}
data-slot="select-label"
class={cn(
"cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-9",
className
)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,7 @@
<script lang="ts">
import { Select as SelectPrimitive } from "bits-ui";
let { ...restProps }: SelectPrimitive.PortalProps = $props();
</script>
<SelectPrimitive.Portal {...restProps} />
@@ -0,0 +1,23 @@
<script lang="ts">
import ChevronDownIcon from "@lucide/svelte/icons/chevron-down";
import { Select as SelectPrimitive } from "bits-ui";
import { cn, type WithoutChildrenOrChild } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: WithoutChildrenOrChild<SelectPrimitive.ScrollDownButtonProps> = $props();
</script>
<SelectPrimitive.ScrollDownButton
bind:ref
data-slot="select-scroll-down-button"
class={cn(
"flex cursor-default items-center justify-center py-1 text-cladd-fg-softer",
className
)}
{...restProps}
>
<ChevronDownIcon class="size-4" />
</SelectPrimitive.ScrollDownButton>
@@ -0,0 +1,23 @@
<script lang="ts">
import ChevronUpIcon from "@lucide/svelte/icons/chevron-up";
import { Select as SelectPrimitive } from "bits-ui";
import { cn, type WithoutChildrenOrChild } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: WithoutChildrenOrChild<SelectPrimitive.ScrollUpButtonProps> = $props();
</script>
<SelectPrimitive.ScrollUpButton
bind:ref
data-slot="select-scroll-up-button"
class={cn(
"flex cursor-default items-center justify-center py-1 text-cladd-fg-softer",
className
)}
{...restProps}
>
<ChevronUpIcon class="size-4" />
</SelectPrimitive.ScrollUpButton>
@@ -0,0 +1,21 @@
<script lang="ts">
import type { Separator as SeparatorPrimitive } from "bits-ui";
import { Separator } from "#lib/components/ui/separator/index.js";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: SeparatorPrimitive.RootProps = $props();
</script>
<Separator
bind:ref
data-slot="select-separator"
class={cn(
"pointer-events-none -mx-2 my-2 h-px bg-cladd-bg-outline",
className
)}
{...restProps}
/>
@@ -0,0 +1,29 @@
<script lang="ts">
import { Select as SelectPrimitive } from "bits-ui";
import ChevronsUpDownIcon from "@lucide/svelte/icons/chevrons-up-down";
import { cn, type WithoutChild } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
size = "default",
...restProps
}: WithoutChild<SelectPrimitive.TriggerProps> & {
size?: "sm" | "default";
} = $props();
</script>
<SelectPrimitive.Trigger
bind:ref
data-slot="select-trigger"
data-size={size}
class={cn(
"cladd-surface cladd-gradient cladd-outline cladd-hoverable cladd-clickable cladd-focusable flex w-fit select-none items-center justify-between gap-2 whitespace-nowrap rounded-cladd-md px-2.5 font-semibold text-cladd-fg text-cladd-xs disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:outline-destructive data-[size=default]:h-cladd-md data-[size=sm]:h-cladd-sm data-[placeholder]:text-cladd-fg-softer *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-softer [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...restProps}
>
{@render children?.()}
<ChevronsUpDownIcon class="size-3.5 text-cladd-fg-softer" />
</SelectPrimitive.Trigger>
@@ -0,0 +1,11 @@
<script lang="ts">
import { Select as SelectPrimitive } from "bits-ui";
let {
open = $bindable(false),
value = $bindable(),
...restProps
}: SelectPrimitive.RootProps = $props();
</script>
<SelectPrimitive.Root bind:open bind:value={value as never} {...restProps} />
+7
View File
@@ -0,0 +1,7 @@
import Root from "./separator.svelte";
export {
Root,
//
Root as Separator,
};
@@ -0,0 +1,21 @@
<script lang="ts">
import { Separator as SeparatorPrimitive } from "bits-ui";
import { cn } from "#lib/utils.js";
let {
ref = $bindable(null),
class: className,
"data-slot": dataSlot = "separator",
...restProps
}: SeparatorPrimitive.RootProps = $props();
</script>
<SeparatorPrimitive.Root
bind:ref
data-slot={dataSlot}
class={cn(
"shrink-0 bg-cladd-bg-outline data-[orientation=horizontal]:h-px data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px",
className
)}
{...restProps}
/>
Loaded 100 of 184 files, more files were not shown because too many files have changed in this diff. Show more