summaryrefslogtreecommitdiff
path: root/llama.cpp/tools/server/webui/src/lib/components/ui
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2026-02-12 20:57:17 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2026-02-12 20:57:17 +0100
commitb333b06772c89d96aacb5490d6a219fba7c09cc6 (patch)
tree211df60083a5946baa2ed61d33d8121b7e251b06 /llama.cpp/tools/server/webui/src/lib/components/ui
downloadllmnpc-b333b06772c89d96aacb5490d6a219fba7c09cc6.tar.gz
Engage!
Diffstat (limited to 'llama.cpp/tools/server/webui/src/lib/components/ui')
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte18
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte18
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte35
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte17
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte23
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte17
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/index.ts39
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert-description.svelte23
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert-title.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert.svelte44
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/alert/index.ts14
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/badge/badge.svelte49
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/badge/index.ts2
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/button/button.svelte87
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/button/index.ts17
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/card/card-action.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/card/card-content.svelte15
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/card/card-description.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/card/card-footer.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/card/card-header.svelte23
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/card/card-title.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/card/card.svelte23
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/card/index.ts25
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/checkbox/checkbox.svelte36
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/checkbox/index.ts6
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible-content.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible-trigger.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible.svelte11
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/index.ts13
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-close.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-content.svelte43
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-description.svelte17
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-footer.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-header.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-overlay.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-title.svelte17
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-trigger.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dialog/index.ts37
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte41
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte27
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte22
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte27
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte24
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte16
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte31
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte17
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte29
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/index.ts49
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/input/index.ts7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/input/input.svelte51
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/label/index.ts7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/label/label.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/popover/index.ts19
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-close.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-content.svelte37
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-portal.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-trigger.svelte17
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/index.ts10
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte31
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/scroll-area.svelte40
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/select/index.ts37
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/select/select-content.svelte111
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/select/select-group-heading.svelte21
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/select/select-group.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/select/select-item.svelte38
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/select/select-label.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/select/select-scroll-down-button.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/select/select-scroll-up-button.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/select/select-separator.svelte18
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/select/select-trigger.svelte40
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/separator/index.ts7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/separator/separator.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sheet/index.ts36
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-close.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-content.svelte60
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-description.svelte17
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-footer.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-header.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-overlay.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-title.svelte17
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-trigger.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/constants.ts6
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/context.svelte.ts79
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/index.ts75
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-content.svelte24
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-footer.svelte21
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-action.svelte36
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-content.svelte21
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-label.svelte34
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group.svelte21
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-header.svelte21
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-input.svelte21
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-inset.svelte24
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-action.svelte43
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte29
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-button.svelte106
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-item.svelte21
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte36
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte43
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte21
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte25
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu.svelte21
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-provider.svelte50
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-rail.svelte36
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-separator.svelte19
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-trigger.svelte35
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar.svelte101
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/skeleton/index.ts7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/skeleton/skeleton.svelte17
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/switch/index.ts7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/switch/switch.svelte29
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/table/index.ts28
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/table/table-body.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/table/table-caption.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/table/table-cell.svelte23
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/table/table-footer.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/table/table-head.svelte23
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/table/table-header.svelte20
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/table/table-row.svelte23
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/table/table.svelte22
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/textarea/index.ts7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/textarea/textarea.svelte22
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/index.ts21
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/tooltip-content.svelte47
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/tooltip-trigger.svelte7
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/ui/utils.ts13
134 files changed, 3409 insertions, 0 deletions
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte
new file mode 100644
index 0000000..162107e
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte
@@ -0,0 +1,18 @@
+<script lang="ts">
+ import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
+ import { buttonVariants } from '$lib/components/ui/button/index.js';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: AlertDialogPrimitive.ActionProps = $props();
+</script>
+
+<AlertDialogPrimitive.Action
+ bind:ref
+ data-slot="alert-dialog-action"
+ class={cn(buttonVariants(), className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte
new file mode 100644
index 0000000..6b3f354
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte
@@ -0,0 +1,18 @@
+<script lang="ts">
+ import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
+ import { buttonVariants } from '$lib/components/ui/button/index.js';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: AlertDialogPrimitive.CancelProps = $props();
+</script>
+
+<AlertDialogPrimitive.Cancel
+ bind:ref
+ data-slot="alert-dialog-cancel"
+ class={cn(buttonVariants({ variant: 'outline' }), className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte
new file mode 100644
index 0000000..2398dae
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte
@@ -0,0 +1,35 @@
+<script lang="ts">
+ import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
+ import AlertDialogOverlay from './alert-dialog-overlay.svelte';
+ import { cn, type WithoutChild, type WithoutChildrenOrChild } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ portalProps,
+ ...restProps
+ }: WithoutChild<AlertDialogPrimitive.ContentProps> & {
+ portalProps?: WithoutChildrenOrChild<AlertDialogPrimitive.PortalProps>;
+ } = $props();
+</script>
+
+<AlertDialogPrimitive.Portal {...portalProps}>
+ <AlertDialogOverlay />
+ <AlertDialogPrimitive.Content
+ bind:ref
+ data-slot="alert-dialog-content"
+ class={cn(
+ 'fixed z-[999999] grid w-full gap-4 border bg-background p-6 shadow-lg duration-200',
+ // Mobile: Bottom sheet behavior
+ 'right-0 bottom-0 left-0 max-h-[100dvh] translate-x-0 translate-y-0 overflow-y-auto rounded-t-lg',
+ 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-bottom-full',
+ 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-bottom-full',
+ // Desktop: Centered dialog behavior
+ 'sm:top-[50%] sm:right-auto sm:bottom-auto sm:left-[50%] sm:max-h-[100vh] sm:max-w-lg sm:translate-x-[-50%] sm:translate-y-[-50%] sm:rounded-lg',
+ 'sm:data-[state=closed]:slide-out-to-bottom-0 sm:data-[state=closed]:zoom-out-95',
+ 'sm:data-[state=open]:slide-in-from-bottom-0 sm:data-[state=open]:zoom-in-95',
+ className
+ )}
+ {...restProps}
+ />
+</AlertDialogPrimitive.Portal>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte
new file mode 100644
index 0000000..84735d8
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+ import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: AlertDialogPrimitive.DescriptionProps = $props();
+</script>
+
+<AlertDialogPrimitive.Description
+ bind:ref
+ data-slot="alert-dialog-description"
+ class={cn('text-sm text-muted-foreground', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte
new file mode 100644
index 0000000..da0f7be
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte
@@ -0,0 +1,23 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/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="alert-dialog-footer"
+ class={cn(
+ 'mt-6 flex flex-row gap-2 sm:mt-0 sm:justify-end [&>*]:flex-1 sm:[&>*]:flex-none',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte
new file mode 100644
index 0000000..fa6539d
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="alert-dialog-header"
+ class={cn('flex flex-col gap-2 text-center sm:text-left', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte
new file mode 100644
index 0000000..71f166d
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: AlertDialogPrimitive.OverlayProps = $props();
+</script>
+
+<AlertDialogPrimitive.Overlay
+ bind:ref
+ data-slot="alert-dialog-overlay"
+ class={cn(
+ 'fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',
+ className
+ )}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte
new file mode 100644
index 0000000..4c610aa
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+ import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: AlertDialogPrimitive.TitleProps = $props();
+</script>
+
+<AlertDialogPrimitive.Title
+ bind:ref
+ data-slot="alert-dialog-title"
+ class={cn('text-lg font-semibold', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte
new file mode 100644
index 0000000..51a3da1
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte
@@ -0,0 +1,7 @@
+<script lang="ts">
+ import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
+
+ let { ref = $bindable(null), ...restProps }: AlertDialogPrimitive.TriggerProps = $props();
+</script>
+
+<AlertDialogPrimitive.Trigger bind:ref data-slot="alert-dialog-trigger" {...restProps} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/index.ts
new file mode 100644
index 0000000..a4439bc
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert-dialog/index.ts
@@ -0,0 +1,39 @@
+import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
+import Trigger from './alert-dialog-trigger.svelte';
+import Title from './alert-dialog-title.svelte';
+import Action from './alert-dialog-action.svelte';
+import Cancel from './alert-dialog-cancel.svelte';
+import Footer from './alert-dialog-footer.svelte';
+import Header from './alert-dialog-header.svelte';
+import Overlay from './alert-dialog-overlay.svelte';
+import Content from './alert-dialog-content.svelte';
+import Description from './alert-dialog-description.svelte';
+
+const Root = AlertDialogPrimitive.Root;
+const Portal = AlertDialogPrimitive.Portal;
+
+export {
+ Root,
+ Title,
+ Action,
+ Cancel,
+ Portal,
+ Footer,
+ Header,
+ Trigger,
+ Overlay,
+ Content,
+ Description,
+ //
+ Root as AlertDialog,
+ Title as AlertDialogTitle,
+ Action as AlertDialogAction,
+ Cancel as AlertDialogCancel,
+ Portal as AlertDialogPortal,
+ Footer as AlertDialogFooter,
+ Header as AlertDialogHeader,
+ Trigger as AlertDialogTrigger,
+ Overlay as AlertDialogOverlay,
+ Content as AlertDialogContent,
+ Description as AlertDialogDescription
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert-description.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert-description.svelte
new file mode 100644
index 0000000..440d006
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert-description.svelte
@@ -0,0 +1,23 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="alert-description"
+ class={cn(
+ 'col-start-2 grid justify-items-start gap-1 text-sm text-muted-foreground [&_p]:leading-relaxed',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert-title.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert-title.svelte
new file mode 100644
index 0000000..0721aeb
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert-title.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="alert-title"
+ class={cn('col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert.svelte
new file mode 100644
index 0000000..7d79e4b
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert/alert.svelte
@@ -0,0 +1,44 @@
+<script lang="ts" module>
+ import { type VariantProps, tv } from 'tailwind-variants';
+
+ export const alertVariants = tv({
+ base: 'relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-lg border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current',
+ variants: {
+ variant: {
+ default: 'bg-card text-card-foreground',
+ destructive:
+ 'text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-current'
+ }
+ },
+ defaultVariants: {
+ variant: 'default'
+ }
+ });
+
+ export type AlertVariant = VariantProps<typeof alertVariants>['variant'];
+</script>
+
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ variant = 'default',
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
+ variant?: AlertVariant;
+ } = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="alert"
+ class={cn(alertVariants({ variant }), className)}
+ {...restProps}
+ role="alert"
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/alert/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/alert/index.ts
new file mode 100644
index 0000000..5e0f854
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/alert/index.ts
@@ -0,0 +1,14 @@
+import Root from './alert.svelte';
+import Description from './alert-description.svelte';
+import Title from './alert-title.svelte';
+export { alertVariants, type AlertVariant } from './alert.svelte';
+
+export {
+ Root,
+ Description,
+ Title,
+ //
+ Root as Alert,
+ Description as AlertDescription,
+ Title as AlertTitle
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/badge/badge.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/badge/badge.svelte
new file mode 100644
index 0000000..4d15145
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/badge/badge.svelte
@@ -0,0 +1,49 @@
+<script lang="ts" module>
+ import { type VariantProps, tv } from 'tailwind-variants';
+
+ export const badgeVariants = tv({
+ base: 'focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-md border px-2 py-0.5 text-xs font-medium transition-[color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none [&>svg]:size-3',
+ variants: {
+ variant: {
+ default: 'bg-primary text-primary-foreground [a&]:hover:bg-primary/90 border-transparent',
+ secondary:
+ 'bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90 border-transparent',
+ destructive:
+ 'bg-destructive [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/70 border-transparent text-white',
+ outline: 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground'
+ }
+ },
+ 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/components/ui/utils';
+
+ 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}
+ data-slot="badge"
+ {href}
+ class={cn(badgeVariants({ variant }), className)}
+ {...restProps}
+>
+ {@render children?.()}
+</svelte:element>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/badge/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/badge/index.ts
new file mode 100644
index 0000000..f05fb87
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/badge/index.ts
@@ -0,0 +1,2 @@
+export { default as Badge } from './badge.svelte';
+export { badgeVariants, type BadgeVariant } from './badge.svelte';
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/button/button.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/button/button.svelte
new file mode 100644
index 0000000..d12c8de
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/button/button.svelte
@@ -0,0 +1,87 @@
+<script lang="ts" module>
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
+ import { type VariantProps, tv } from 'tailwind-variants';
+
+ export const buttonVariants = tv({
+ base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-all focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
+ variants: {
+ variant: {
+ default: 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
+ destructive:
+ 'bg-destructive shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white',
+ outline:
+ 'bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border',
+ secondary: 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
+ ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
+ link: 'text-primary underline-offset-4 hover:underline'
+ },
+ size: {
+ default: 'h-9 px-4 py-2 has-[>svg]:px-3',
+ sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5',
+ lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
+ icon: 'size-9'
+ }
+ },
+ defaultVariants: {
+ variant: 'default',
+ size: 'default'
+ }
+ });
+
+ 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>
+
+<script lang="ts">
+ let {
+ class: className,
+ variant = 'default',
+ size = 'default',
+ ref = $bindable(null),
+ href = undefined,
+ type = 'button',
+ disabled,
+ children,
+ ...restProps
+ }: ButtonProps = $props();
+</script>
+
+{#if href}
+ <a
+ bind:this={ref}
+ data-slot="button"
+ class={cn(buttonVariants({ variant, size }), className)}
+ href={disabled ? undefined : href}
+ aria-disabled={disabled}
+ role={disabled ? 'link' : undefined}
+ tabindex={disabled ? -1 : undefined}
+ {...restProps}
+ >
+ {@render children?.()}
+ </a>
+{:else}
+ <button
+ bind:this={ref}
+ data-slot="button"
+ class={cn(buttonVariants({ variant, size }), className)}
+ {type}
+ {disabled}
+ {...restProps}
+ >
+ {@render children?.()}
+ </button>
+{/if}
+
+<style>
+ a,
+ button {
+ cursor: pointer;
+ }
+</style>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/button/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/button/index.ts
new file mode 100644
index 0000000..5414d9d
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/button/index.ts
@@ -0,0 +1,17 @@
+import Root, {
+ type ButtonProps,
+ type ButtonSize,
+ type ButtonVariant,
+ buttonVariants
+} from './button.svelte';
+
+export {
+ Root,
+ type ButtonProps as Props,
+ //
+ Root as Button,
+ buttonVariants,
+ type ButtonProps,
+ type ButtonSize,
+ type ButtonVariant
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-action.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-action.svelte
new file mode 100644
index 0000000..0d4e965
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-action.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+ 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>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-content.svelte
new file mode 100644
index 0000000..c68f613
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-content.svelte
@@ -0,0 +1,15 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
+</script>
+
+<div bind:this={ref} data-slot="card-content" class={cn('px-6', className)} {...restProps}>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-description.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-description.svelte
new file mode 100644
index 0000000..81578df
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-description.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
+</script>
+
+<p
+ bind:this={ref}
+ data-slot="card-description"
+ class={cn('text-sm text-muted-foreground', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</p>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-footer.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-footer.svelte
new file mode 100644
index 0000000..0366459
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-footer.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+ 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 px-6 [.border-t]:pt-6', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-header.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-header.svelte
new file mode 100644
index 0000000..74ab163
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-header.svelte
@@ -0,0 +1,23 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+ 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.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-title.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-title.svelte
new file mode 100644
index 0000000..8dfc062
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card-title.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="card-title"
+ class={cn('leading-none font-semibold', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/card/card.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card.svelte
new file mode 100644
index 0000000..c40d143
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/card/card.svelte
@@ -0,0 +1,23 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="card"
+ class={cn(
+ 'flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/card/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/card/index.ts
new file mode 100644
index 0000000..77d3674
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/card/index.ts
@@ -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
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/checkbox/checkbox.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/checkbox/checkbox.svelte
new file mode 100644
index 0000000..aafa071
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/checkbox/checkbox.svelte
@@ -0,0 +1,36 @@
+<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/components/ui/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 flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input shadow-xs transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary',
+ className
+ )}
+ bind:checked
+ bind:indeterminate
+ {...restProps}
+>
+ {#snippet children({ checked, indeterminate })}
+ <div data-slot="checkbox-indicator" class="text-current transition-none">
+ {#if checked}
+ <CheckIcon class="size-3.5" />
+ {:else if indeterminate}
+ <MinusIcon class="size-3.5" />
+ {/if}
+ </div>
+ {/snippet}
+</CheckboxPrimitive.Root>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/checkbox/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/checkbox/index.ts
new file mode 100644
index 0000000..5c27671
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/checkbox/index.ts
@@ -0,0 +1,6 @@
+import Root from './checkbox.svelte';
+export {
+ Root,
+ //
+ Root as Checkbox
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible-content.svelte
new file mode 100644
index 0000000..59b068c
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible-content.svelte
@@ -0,0 +1,7 @@
+<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} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible-trigger.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible-trigger.svelte
new file mode 100644
index 0000000..c88ceba
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible-trigger.svelte
@@ -0,0 +1,7 @@
+<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} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible.svelte
new file mode 100644
index 0000000..7a8c5da
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/collapsible.svelte
@@ -0,0 +1,11 @@
+<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} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/index.ts
new file mode 100644
index 0000000..8181f64
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/collapsible/index.ts
@@ -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
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-close.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-close.svelte
new file mode 100644
index 0000000..e8a96a7
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-close.svelte
@@ -0,0 +1,7 @@
+<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} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-content.svelte
new file mode 100644
index 0000000..74df0ea
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-content.svelte
@@ -0,0 +1,43 @@
+<script lang="ts">
+ import { Dialog as DialogPrimitive } from 'bits-ui';
+ import XIcon from '@lucide/svelte/icons/x';
+ import type { Snippet } from 'svelte';
+ import * as Dialog from './index.js';
+ import { cn, type WithoutChildrenOrChild } from '$lib/components/ui/utils';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ portalProps,
+ children,
+ showCloseButton = true,
+ ...restProps
+ }: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
+ portalProps?: DialogPrimitive.PortalProps;
+ children: Snippet;
+ showCloseButton?: boolean;
+ } = $props();
+</script>
+
+<Dialog.Portal {...portalProps}>
+ <Dialog.Overlay />
+ <DialogPrimitive.Content
+ bind:ref
+ data-slot="dialog-content"
+ class={cn(
+ `fixed top-[50%] left-[50%] z-50 grid max-h-[100dvh] w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 overflow-y-auto rounded-lg border border-border/30 bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg md:max-h-[100vh]`,
+ className
+ )}
+ {...restProps}
+ >
+ {@render children?.()}
+ {#if showCloseButton}
+ <DialogPrimitive.Close
+ class="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden 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>
+</Dialog.Portal>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-description.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-description.svelte
new file mode 100644
index 0000000..6c0c192
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-description.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+ import { Dialog as DialogPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: DialogPrimitive.DescriptionProps = $props();
+</script>
+
+<DialogPrimitive.Description
+ bind:ref
+ data-slot="dialog-description"
+ class={cn('text-sm text-muted-foreground', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-footer.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-footer.svelte
new file mode 100644
index 0000000..abf948f
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-footer.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+ 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('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-header.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-header.svelte
new file mode 100644
index 0000000..7ba9ba1
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-header.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+
+ 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-2 text-center sm:text-left', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-overlay.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-overlay.svelte
new file mode 100644
index 0000000..a6e9a10
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-overlay.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { Dialog as DialogPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: DialogPrimitive.OverlayProps = $props();
+</script>
+
+<DialogPrimitive.Overlay
+ bind:ref
+ data-slot="dialog-overlay"
+ class={cn(
+ 'fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',
+ className
+ )}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-title.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-title.svelte
new file mode 100644
index 0000000..e8c99c5
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-title.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+ import { Dialog as DialogPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: DialogPrimitive.TitleProps = $props();
+</script>
+
+<DialogPrimitive.Title
+ bind:ref
+ data-slot="dialog-title"
+ class={cn('text-lg leading-none font-semibold', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-trigger.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-trigger.svelte
new file mode 100644
index 0000000..ac04d9f
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/dialog-trigger.svelte
@@ -0,0 +1,7 @@
+<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} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/index.ts
new file mode 100644
index 0000000..d9e5fb8
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dialog/index.ts
@@ -0,0 +1,37 @@
+import { Dialog as DialogPrimitive } from 'bits-ui';
+
+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';
+
+const Root = DialogPrimitive.Root;
+const Portal = DialogPrimitive.Portal;
+
+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
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte
new file mode 100644
index 0000000..e71acef
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte
@@ -0,0 +1,41 @@
+<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/components/ui/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 cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
+ className
+ )}
+ {...restProps}
+>
+ {#snippet children({ checked, indeterminate })}
+ <span class="pointer-events-none absolute left-2 flex size-3.5 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>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte
new file mode 100644
index 0000000..869c38e
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte
@@ -0,0 +1,27 @@
+<script lang="ts">
+ import { cn } from '$lib/components/ui/utils.js';
+ import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
+
+ let {
+ ref = $bindable(null),
+ sideOffset = 4,
+ portalProps,
+ class: className,
+ ...restProps
+ }: DropdownMenuPrimitive.ContentProps & {
+ portalProps?: DropdownMenuPrimitive.PortalProps;
+ } = $props();
+</script>
+
+<DropdownMenuPrimitive.Portal {...portalProps}>
+ <DropdownMenuPrimitive.Content
+ bind:ref
+ data-slot="dropdown-menu-content"
+ {sideOffset}
+ class={cn(
+ 'z-50 max-h-(--bits-dropdown-menu-content-available-height) min-w-[8rem] origin-(--bits-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md outline-none 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 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 dark:border-border/20',
+ className
+ )}
+ {...restProps}
+ />
+</DropdownMenuPrimitive.Portal>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte
new file mode 100644
index 0000000..f217966
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte
@@ -0,0 +1,22 @@
+<script lang="ts">
+ import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/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('px-2 py-1.5 text-sm font-semibold data-[inset]:pl-8', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte
new file mode 100644
index 0000000..261ab7e
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte
@@ -0,0 +1,7 @@
+<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} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte
new file mode 100644
index 0000000..1ac5615
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte
@@ -0,0 +1,27 @@
+<script lang="ts">
+ import { cn } from '$lib/components/ui/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';
+ } = $props();
+</script>
+
+<DropdownMenuPrimitive.Item
+ bind:ref
+ data-slot="dropdown-menu-item"
+ data-inset={inset}
+ data-variant={variant}
+ class={cn(
+ "relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:data-highlighted:bg-destructive/10 data-[variant=destructive]:data-highlighted:text-destructive dark:data-[variant=destructive]:data-highlighted:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:!text-destructive",
+ className
+ )}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte
new file mode 100644
index 0000000..15b546e
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte
@@ -0,0 +1,24 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/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('px-2 py-1.5 text-sm font-semibold data-[inset]:pl-8', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte
new file mode 100644
index 0000000..3e98749
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte
@@ -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}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte
new file mode 100644
index 0000000..97ba772
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte
@@ -0,0 +1,31 @@
+<script lang="ts">
+ import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
+ import CircleIcon from '@lucide/svelte/icons/circle';
+ import { cn, type WithoutChild } from '$lib/components/ui/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 cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
+ className
+ )}
+ {...restProps}
+>
+ {#snippet children({ checked })}
+ <span class="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
+ {#if checked}
+ <CircleIcon class="size-2 fill-current" />
+ {/if}
+ </span>
+ {@render childrenProp?.({ checked })}
+ {/snippet}
+</DropdownMenuPrimitive.RadioItem>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte
new file mode 100644
index 0000000..17b64ac
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+ import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/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-1 my-1 h-px bg-border/20', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte
new file mode 100644
index 0000000..c3ccc21
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/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('ml-auto text-xs tracking-widest text-muted-foreground', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</span>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte
new file mode 100644
index 0000000..3ceb165
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/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(
+ 'z-50 min-w-[8rem] origin-(--bits-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
+ className
+ )}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte
new file mode 100644
index 0000000..550a789
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte
@@ -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/components/ui/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(
+ "flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+ <ChevronRightIcon class="ml-auto size-4" />
+</DropdownMenuPrimitive.SubTrigger>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte
new file mode 100644
index 0000000..032b645
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte
@@ -0,0 +1,7 @@
+<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} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/index.ts
new file mode 100644
index 0000000..aeb398e
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/dropdown-menu/index.ts
@@ -0,0 +1,49 @@
+import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
+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';
+const Sub = DropdownMenuPrimitive.Sub;
+const Root = DropdownMenuPrimitive.Root;
+
+export {
+ CheckboxItem,
+ Content,
+ Root as DropdownMenu,
+ CheckboxItem as DropdownMenuCheckboxItem,
+ Content as DropdownMenuContent,
+ 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
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/input/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/input/index.ts
new file mode 100644
index 0000000..15c0933
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/input/index.ts
@@ -0,0 +1,7 @@
+import Root from './input.svelte';
+
+export {
+ Root,
+ //
+ Root as Input
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/input/input.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/input/input.svelte
new file mode 100644
index 0000000..889b720
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/input/input.svelte
@@ -0,0 +1,51 @@
+<script lang="ts">
+ import type { HTMLInputAttributes, HTMLInputTypeAttribute } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils';
+
+ 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,
+ ...restProps
+ }: Props = $props();
+</script>
+
+{#if type === 'file'}
+ <input
+ bind:this={ref}
+ data-slot="input"
+ class={cn(
+ 'flex h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 pt-1.5 text-sm font-medium shadow-xs ring-offset-background transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30',
+ 'focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50',
+ 'aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40',
+ className
+ )}
+ type="file"
+ bind:files
+ bind:value
+ {...restProps}
+ />
+{:else}
+ <input
+ bind:this={ref}
+ data-slot="input"
+ class={cn(
+ 'flex h-9 w-full min-w-0 rounded-md border border-input bg-background px-3 py-1 text-base shadow-xs ring-offset-background transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30',
+ 'focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50',
+ 'aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40',
+ className
+ )}
+ {type}
+ bind:value
+ {...restProps}
+ />
+{/if}
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/label/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/label/index.ts
new file mode 100644
index 0000000..808d141
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/label/index.ts
@@ -0,0 +1,7 @@
+import Root from './label.svelte';
+
+export {
+ Root,
+ //
+ Root as Label
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/label/label.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/label/label.svelte
new file mode 100644
index 0000000..9da4ae3
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/label/label.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { Label as LabelPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: LabelPrimitive.RootProps = $props();
+</script>
+
+<LabelPrimitive.Root
+ bind:ref
+ data-slot="label"
+ class={cn(
+ 'flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
+ className
+ )}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/popover/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/index.ts
new file mode 100644
index 0000000..c5937fb
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/index.ts
@@ -0,0 +1,19 @@
+import Root from './popover.svelte';
+import Close from './popover-close.svelte';
+import Content from './popover-content.svelte';
+import Trigger from './popover-trigger.svelte';
+import Portal from './popover-portal.svelte';
+
+export {
+ Root,
+ Content,
+ Trigger,
+ Close,
+ Portal,
+ //
+ Root as Popover,
+ Content as PopoverContent,
+ Trigger as PopoverTrigger,
+ Close as PopoverClose,
+ Portal as PopoverPortal
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-close.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-close.svelte
new file mode 100644
index 0000000..dc4dec4
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-close.svelte
@@ -0,0 +1,7 @@
+<script lang="ts">
+ import { Popover as PopoverPrimitive } from 'bits-ui';
+
+ let { ref = $bindable(null), ...restProps }: PopoverPrimitive.CloseProps = $props();
+</script>
+
+<PopoverPrimitive.Close bind:ref data-slot="popover-close" {...restProps} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-content.svelte
new file mode 100644
index 0000000..2d3513d
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-content.svelte
@@ -0,0 +1,37 @@
+<script lang="ts">
+ import { Popover as PopoverPrimitive } from 'bits-ui';
+ import PopoverPortal from './popover-portal.svelte';
+ import { cn, type WithoutChildrenOrChild } from '$lib/components/ui/utils.js';
+ import type { ComponentProps } from 'svelte';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ sideOffset = 4,
+ side,
+ align = 'center',
+ collisionPadding = 8,
+ avoidCollisions = true,
+ portalProps,
+ ...restProps
+ }: PopoverPrimitive.ContentProps & {
+ portalProps?: WithoutChildrenOrChild<ComponentProps<typeof PopoverPortal>>;
+ } = $props();
+</script>
+
+<PopoverPortal {...portalProps}>
+ <PopoverPrimitive.Content
+ bind:ref
+ data-slot="popover-content"
+ {sideOffset}
+ {side}
+ {align}
+ {collisionPadding}
+ {avoidCollisions}
+ class={cn(
+ 'z-50 w-72 origin-(--bits-popover-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-end-2 data-[side=right]:slide-in-from-start-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
+ className
+ )}
+ {...restProps}
+ />
+</PopoverPortal>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-portal.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-portal.svelte
new file mode 100644
index 0000000..25efb87
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-portal.svelte
@@ -0,0 +1,7 @@
+<script lang="ts">
+ import { Popover as PopoverPrimitive } from 'bits-ui';
+
+ let { ...restProps }: PopoverPrimitive.PortalProps = $props();
+</script>
+
+<PopoverPrimitive.Portal {...restProps} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-trigger.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-trigger.svelte
new file mode 100644
index 0000000..5ef3d0e
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover-trigger.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+ import { cn } from '$lib/components/ui/utils.js';
+ import { Popover as PopoverPrimitive } from 'bits-ui';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: PopoverPrimitive.TriggerProps = $props();
+</script>
+
+<PopoverPrimitive.Trigger
+ bind:ref
+ data-slot="popover-trigger"
+ class={cn('', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover.svelte
new file mode 100644
index 0000000..f39b867
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/popover/popover.svelte
@@ -0,0 +1,7 @@
+<script lang="ts">
+ import { Popover as PopoverPrimitive } from 'bits-ui';
+
+ let { open = $bindable(false), ...restProps }: PopoverPrimitive.RootProps = $props();
+</script>
+
+<PopoverPrimitive.Root bind:open {...restProps} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/index.ts
new file mode 100644
index 0000000..d546806
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/index.ts
@@ -0,0 +1,10 @@
+import Scrollbar from './scroll-area-scrollbar.svelte';
+import Root from './scroll-area.svelte';
+
+export {
+ Root,
+ Scrollbar,
+ //,
+ Root as ScrollArea,
+ Scrollbar as ScrollAreaScrollbar
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte
new file mode 100644
index 0000000..3f0d00d
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte
@@ -0,0 +1,31 @@
+<script lang="ts">
+ import { ScrollArea as ScrollAreaPrimitive } from 'bits-ui';
+ import { cn, type WithoutChild } from '$lib/components/ui/utils';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ orientation = 'vertical',
+ children,
+ ...restProps
+ }: WithoutChild<ScrollAreaPrimitive.ScrollbarProps> = $props();
+</script>
+
+<ScrollAreaPrimitive.Scrollbar
+ bind:ref
+ data-slot="scroll-area-scrollbar"
+ {orientation}
+ class={cn(
+ 'flex touch-none p-px transition-colors select-none',
+ orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent',
+ orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+ <ScrollAreaPrimitive.Thumb
+ data-slot="scroll-area-thumb"
+ class="relative flex-1 rounded-full bg-border"
+ />
+</ScrollAreaPrimitive.Scrollbar>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/scroll-area.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/scroll-area.svelte
new file mode 100644
index 0000000..ba6f838
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/scroll-area/scroll-area.svelte
@@ -0,0 +1,40 @@
+<script lang="ts">
+ import { ScrollArea as ScrollAreaPrimitive } from 'bits-ui';
+ import { Scrollbar } from './index.js';
+ import { cn, type WithoutChild } from '$lib/components/ui/utils';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ orientation = 'vertical',
+ scrollbarXClasses = '',
+ scrollbarYClasses = '',
+ children,
+ ...restProps
+ }: WithoutChild<ScrollAreaPrimitive.RootProps> & {
+ orientation?: 'vertical' | 'horizontal' | 'both' | undefined;
+ scrollbarXClasses?: string | undefined;
+ scrollbarYClasses?: string | undefined;
+ } = $props();
+</script>
+
+<ScrollAreaPrimitive.Root
+ bind:ref
+ data-slot="scroll-area"
+ class={cn('relative', className)}
+ {...restProps}
+>
+ <ScrollAreaPrimitive.Viewport
+ data-slot="scroll-area-viewport"
+ class="size-full rounded-[inherit] ring-ring/10 outline-ring/50 transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1 dark:ring-ring/20 dark:outline-ring/40"
+ >
+ {@render children?.()}
+ </ScrollAreaPrimitive.Viewport>
+ {#if orientation === 'vertical' || orientation === 'both'}
+ <Scrollbar orientation="vertical" class={scrollbarYClasses} />
+ {/if}
+ {#if orientation === 'horizontal' || orientation === 'both'}
+ <Scrollbar orientation="horizontal" class={scrollbarXClasses} />
+ {/if}
+ <ScrollAreaPrimitive.Corner />
+</ScrollAreaPrimitive.Root>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/select/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/select/index.ts
new file mode 100644
index 0000000..bfa73d9
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/select/index.ts
@@ -0,0 +1,37 @@
+import { Select as SelectPrimitive } from 'bits-ui';
+
+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';
+
+const Root = SelectPrimitive.Root;
+
+export {
+ Root,
+ Group,
+ Label,
+ Item,
+ Content,
+ Trigger,
+ Separator,
+ ScrollDownButton,
+ ScrollUpButton,
+ GroupHeading,
+ //
+ 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
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-content.svelte
new file mode 100644
index 0000000..4050628
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-content.svelte
@@ -0,0 +1,111 @@
+<script lang="ts">
+ import { onDestroy, onMount } from 'svelte';
+ import { Select as SelectPrimitive } from 'bits-ui';
+ import SelectScrollUpButton from './select-scroll-up-button.svelte';
+ import SelectScrollDownButton from './select-scroll-down-button.svelte';
+ import { cn, type WithoutChild } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ sideOffset = 4,
+ portalProps,
+ children,
+ ...restProps
+ }: WithoutChild<SelectPrimitive.ContentProps> & {
+ portalProps?: SelectPrimitive.PortalProps;
+ } = $props();
+
+ let cleanupInternalListeners: (() => void) | undefined;
+
+ onMount(() => {
+ const listenerOptions: AddEventListenerOptions = { passive: false };
+
+ const blockOutsideWheel = (event: WheelEvent) => {
+ if (!ref) {
+ return;
+ }
+
+ const target = event.target as Node | null;
+
+ if (!target || !ref.contains(target)) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ };
+
+ const blockOutsideTouchMove = (event: TouchEvent) => {
+ if (!ref) {
+ return;
+ }
+
+ const target = event.target as Node | null;
+
+ if (!target || !ref.contains(target)) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ };
+
+ document.addEventListener('wheel', blockOutsideWheel, listenerOptions);
+ document.addEventListener('touchmove', blockOutsideTouchMove, listenerOptions);
+
+ return () => {
+ document.removeEventListener('wheel', blockOutsideWheel, listenerOptions);
+ document.removeEventListener('touchmove', blockOutsideTouchMove, listenerOptions);
+ };
+ });
+
+ $effect(() => {
+ const element = ref;
+
+ cleanupInternalListeners?.();
+
+ if (!element) {
+ return;
+ }
+
+ const stopWheelPropagation = (event: WheelEvent) => {
+ event.stopPropagation();
+ };
+
+ const stopTouchPropagation = (event: TouchEvent) => {
+ event.stopPropagation();
+ };
+
+ element.addEventListener('wheel', stopWheelPropagation);
+ element.addEventListener('touchmove', stopTouchPropagation);
+
+ cleanupInternalListeners = () => {
+ element.removeEventListener('wheel', stopWheelPropagation);
+ element.removeEventListener('touchmove', stopTouchPropagation);
+ };
+ });
+
+ onDestroy(() => {
+ cleanupInternalListeners?.();
+ });
+</script>
+
+<SelectPrimitive.Portal {...portalProps}>
+ <SelectPrimitive.Content
+ bind:ref
+ {sideOffset}
+ data-slot="select-content"
+ class={cn(
+ 'relative z-[var(--layer-popover,1000000)] max-h-(--bits-select-content-available-height) min-w-[8rem] origin-(--bits-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:translate-y-1 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:-translate-x-1 data-[side=left]:slide-in-from-right-2 data-[side=right]:translate-x-1 data-[side=right]:slide-in-from-left-2 data-[side=top]:-translate-y-1 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
+ className
+ )}
+ {...restProps}
+ >
+ <SelectScrollUpButton />
+ <SelectPrimitive.Viewport
+ class={cn(
+ 'h-(--bits-select-anchor-height) w-full min-w-(--bits-select-anchor-width) scroll-my-1 p-1'
+ )}
+ >
+ {@render children?.()}
+ </SelectPrimitive.Viewport>
+ <SelectScrollDownButton />
+ </SelectPrimitive.Content>
+</SelectPrimitive.Portal>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-group-heading.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-group-heading.svelte
new file mode 100644
index 0000000..77c2042
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-group-heading.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+ import { Select as SelectPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/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('px-2 py-1.5 text-xs text-muted-foreground', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</SelectPrimitive.GroupHeading>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-group.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-group.svelte
new file mode 100644
index 0000000..2520795
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-group.svelte
@@ -0,0 +1,7 @@
+<script lang="ts">
+ import { Select as SelectPrimitive } from 'bits-ui';
+
+ let { ref = $bindable(null), ...restProps }: SelectPrimitive.GroupProps = $props();
+</script>
+
+<SelectPrimitive.Group data-slot="select-group" {...restProps} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-item.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-item.svelte
new file mode 100644
index 0000000..02543c1
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-item.svelte
@@ -0,0 +1,38 @@
+<script lang="ts">
+ import CheckIcon from '@lucide/svelte/icons/check';
+ import { Select as SelectPrimitive } from 'bits-ui';
+ import { cn, type WithoutChild } from '$lib/components/ui/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 w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
+ className
+ )}
+ {...restProps}
+>
+ {#snippet children({ selected, highlighted })}
+ <span class="absolute right-2 flex size-3.5 items-center justify-center">
+ {#if selected}
+ <CheckIcon class="size-4" />
+ {/if}
+ </span>
+ {#if childrenProp}
+ {@render childrenProp({ selected, highlighted })}
+ {:else}
+ {label || value}
+ {/if}
+ {/snippet}
+</SelectPrimitive.Item>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-label.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-label.svelte
new file mode 100644
index 0000000..e2b830c
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-label.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/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('px-2 py-1.5 text-xs text-muted-foreground', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-scroll-down-button.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-scroll-down-button.svelte
new file mode 100644
index 0000000..9256dd8
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-scroll-down-button.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import ChevronDownIcon from '@lucide/svelte/icons/chevron-down';
+ import { Select as SelectPrimitive } from 'bits-ui';
+ import { cn, type WithoutChildrenOrChild } from '$lib/components/ui/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', className)}
+ {...restProps}
+>
+ <ChevronDownIcon class="size-4" />
+</SelectPrimitive.ScrollDownButton>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-scroll-up-button.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-scroll-up-button.svelte
new file mode 100644
index 0000000..552e527
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-scroll-up-button.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import ChevronUpIcon from '@lucide/svelte/icons/chevron-up';
+ import { Select as SelectPrimitive } from 'bits-ui';
+ import { cn, type WithoutChildrenOrChild } from '$lib/components/ui/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', className)}
+ {...restProps}
+>
+ <ChevronUpIcon class="size-4" />
+</SelectPrimitive.ScrollUpButton>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-separator.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-separator.svelte
new file mode 100644
index 0000000..7daaa8d
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-separator.svelte
@@ -0,0 +1,18 @@
+<script lang="ts">
+ import type { Separator as SeparatorPrimitive } from 'bits-ui';
+ import { Separator } from '$lib/components/ui/separator/index.js';
+ import { cn } from '$lib/components/ui/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-1 my-1 h-px bg-border', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-trigger.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-trigger.svelte
new file mode 100644
index 0000000..5bc28ee
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/select/select-trigger.svelte
@@ -0,0 +1,40 @@
+<script lang="ts">
+ import { Select as SelectPrimitive } from 'bits-ui';
+ import ChevronDownIcon from '@lucide/svelte/icons/chevron-down';
+ import { cn, type WithoutChild } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ size = 'default',
+ variant = 'default',
+ ...restProps
+ }: WithoutChild<SelectPrimitive.TriggerProps> & {
+ size?: 'sm' | 'default';
+ variant?: 'default' | 'plain';
+ } = $props();
+
+ const baseClasses = $derived(
+ variant === 'plain'
+ ? "group inline-flex w-full items-center justify-end gap-2 whitespace-nowrap px-0 py-0 text-sm font-medium text-muted-foreground transition-colors focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3 [&_svg:not([class*='text-'])]:text-muted-foreground"
+ : "flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground"
+ );
+
+ const chevronClasses = $derived(
+ variant === 'plain'
+ ? 'size-3 opacity-60 transition-transform group-data-[state=open]:-rotate-180'
+ : 'size-4 opacity-50'
+ );
+</script>
+
+<SelectPrimitive.Trigger
+ bind:ref
+ data-slot="select-trigger"
+ data-size={size}
+ class={cn(baseClasses, className)}
+ {...restProps}
+>
+ {@render children?.()}
+ <ChevronDownIcon class={chevronClasses} />
+</SelectPrimitive.Trigger>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/separator/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/separator/index.ts
new file mode 100644
index 0000000..768efac
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/separator/index.ts
@@ -0,0 +1,7 @@
+import Root from './separator.svelte';
+
+export {
+ Root,
+ //
+ Root as Separator
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/separator/separator.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/separator/separator.svelte
new file mode 100644
index 0000000..00307fd
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/separator/separator.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { Separator as SeparatorPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: SeparatorPrimitive.RootProps = $props();
+</script>
+
+<SeparatorPrimitive.Root
+ bind:ref
+ data-slot="separator"
+ class={cn(
+ 'shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
+ className
+ )}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/index.ts
new file mode 100644
index 0000000..139e2d2
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/index.ts
@@ -0,0 +1,36 @@
+import { Dialog as SheetPrimitive } from 'bits-ui';
+import Trigger from './sheet-trigger.svelte';
+import Close from './sheet-close.svelte';
+import Overlay from './sheet-overlay.svelte';
+import Content from './sheet-content.svelte';
+import Header from './sheet-header.svelte';
+import Footer from './sheet-footer.svelte';
+import Title from './sheet-title.svelte';
+import Description from './sheet-description.svelte';
+
+const Root = SheetPrimitive.Root;
+const Portal = SheetPrimitive.Portal;
+
+export {
+ Root,
+ Close,
+ Trigger,
+ Portal,
+ Overlay,
+ Content,
+ Header,
+ Footer,
+ Title,
+ Description,
+ //
+ Root as Sheet,
+ Close as SheetClose,
+ Trigger as SheetTrigger,
+ Portal as SheetPortal,
+ Overlay as SheetOverlay,
+ Content as SheetContent,
+ Header as SheetHeader,
+ Footer as SheetFooter,
+ Title as SheetTitle,
+ Description as SheetDescription
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-close.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-close.svelte
new file mode 100644
index 0000000..b0180c0
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-close.svelte
@@ -0,0 +1,7 @@
+<script lang="ts">
+ import { Dialog as SheetPrimitive } from 'bits-ui';
+
+ let { ref = $bindable(null), ...restProps }: SheetPrimitive.CloseProps = $props();
+</script>
+
+<SheetPrimitive.Close bind:ref data-slot="sheet-close" {...restProps} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-content.svelte
new file mode 100644
index 0000000..f16a0e0
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-content.svelte
@@ -0,0 +1,60 @@
+<script lang="ts" module>
+ import { tv, type VariantProps } from 'tailwind-variants';
+ export const sheetVariants = tv({
+ base: 'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 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 h-auto border-b',
+ bottom:
+ 'data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto 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'
+ }
+ });
+
+ export type Side = VariantProps<typeof sheetVariants>['side'];
+</script>
+
+<script lang="ts">
+ import { Dialog as SheetPrimitive } from 'bits-ui';
+ import XIcon from '@lucide/svelte/icons/x';
+ import type { Snippet } from 'svelte';
+ import SheetOverlay from './sheet-overlay.svelte';
+ import { cn, type WithoutChildrenOrChild } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ side = 'right',
+ portalProps,
+ children,
+ ...restProps
+ }: WithoutChildrenOrChild<SheetPrimitive.ContentProps> & {
+ portalProps?: SheetPrimitive.PortalProps;
+ side?: Side;
+ children: Snippet;
+ } = $props();
+</script>
+
+<SheetPrimitive.Portal {...portalProps}>
+ <SheetOverlay />
+ <SheetPrimitive.Content
+ bind:ref
+ data-slot="sheet-content"
+ class={cn(sheetVariants({ side }), className)}
+ {...restProps}
+ >
+ {@render children?.()}
+ <SheetPrimitive.Close
+ class="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:pointer-events-none"
+ >
+ <XIcon class="size-4" />
+ <span class="sr-only">Close</span>
+ </SheetPrimitive.Close>
+ </SheetPrimitive.Content>
+</SheetPrimitive.Portal>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-description.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-description.svelte
new file mode 100644
index 0000000..ef4d58f
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-description.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+ import { Dialog as SheetPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: SheetPrimitive.DescriptionProps = $props();
+</script>
+
+<SheetPrimitive.Description
+ bind:ref
+ data-slot="sheet-description"
+ class={cn('text-sm text-muted-foreground', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-footer.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-footer.svelte
new file mode 100644
index 0000000..4e1b927
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-footer.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/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="sheet-footer"
+ class={cn('mt-auto flex flex-col gap-2 p-4', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-header.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-header.svelte
new file mode 100644
index 0000000..6c6c1ec
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-header.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="sheet-header"
+ class={cn('flex flex-col gap-1.5 p-4', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-overlay.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-overlay.svelte
new file mode 100644
index 0000000..a6a064f
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-overlay.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { Dialog as SheetPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: SheetPrimitive.OverlayProps = $props();
+</script>
+
+<SheetPrimitive.Overlay
+ bind:ref
+ data-slot="sheet-overlay"
+ class={cn(
+ 'fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',
+ className
+ )}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-title.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-title.svelte
new file mode 100644
index 0000000..0efcc7a
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-title.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+ import { Dialog as SheetPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: SheetPrimitive.TitleProps = $props();
+</script>
+
+<SheetPrimitive.Title
+ bind:ref
+ data-slot="sheet-title"
+ class={cn('font-semibold text-foreground', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-trigger.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-trigger.svelte
new file mode 100644
index 0000000..d95719a
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sheet/sheet-trigger.svelte
@@ -0,0 +1,7 @@
+<script lang="ts">
+ import { Dialog as SheetPrimitive } from 'bits-ui';
+
+ let { ref = $bindable(null), ...restProps }: SheetPrimitive.TriggerProps = $props();
+</script>
+
+<SheetPrimitive.Trigger bind:ref data-slot="sheet-trigger" {...restProps} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/constants.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/constants.ts
new file mode 100644
index 0000000..c7e827b
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/constants.ts
@@ -0,0 +1,6 @@
+export const SIDEBAR_COOKIE_NAME = 'sidebar:state';
+export const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
+export const SIDEBAR_WIDTH = '18rem';
+export const SIDEBAR_WIDTH_MOBILE = '18rem';
+export const SIDEBAR_WIDTH_ICON = '3rem';
+export const SIDEBAR_KEYBOARD_SHORTCUT = 'b';
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/context.svelte.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/context.svelte.ts
new file mode 100644
index 0000000..6fa2aa3
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/context.svelte.ts
@@ -0,0 +1,79 @@
+import { IsMobile } from '$lib/hooks/is-mobile.svelte.js';
+import { getContext, setContext } from 'svelte';
+import { SIDEBAR_KEYBOARD_SHORTCUT } from './constants.js';
+
+type Getter<T> = () => T;
+
+export type SidebarStateProps = {
+ /**
+ * A getter function that returns the current open state of the sidebar.
+ * We use a getter function here to support `bind:open` on the `Sidebar.Provider`
+ * component.
+ */
+ open: Getter<boolean>;
+
+ /**
+ * A function that sets the open state of the sidebar. To support `bind:open`, we need
+ * a source of truth for changing the open state to ensure it will be synced throughout
+ * the sub-components and any `bind:` references.
+ */
+ setOpen: (open: boolean) => void;
+};
+
+class SidebarState {
+ readonly props: SidebarStateProps;
+ open = $derived.by(() => this.props.open());
+ openMobile = $state(false);
+ setOpen: SidebarStateProps['setOpen'];
+ #isMobile: IsMobile;
+ state = $derived.by(() => (this.open ? 'expanded' : 'collapsed'));
+
+ constructor(props: SidebarStateProps) {
+ this.setOpen = props.setOpen;
+ this.#isMobile = new IsMobile();
+ this.props = props;
+ }
+
+ // Convenience getter for checking if the sidebar is mobile
+ // without this, we would need to use `sidebar.isMobile.current` everywhere
+ get isMobile() {
+ return this.#isMobile.current;
+ }
+
+ // Event handler to apply to the `<svelte:window>`
+ handleShortcutKeydown = (e: KeyboardEvent) => {
+ if (e.key === SIDEBAR_KEYBOARD_SHORTCUT && (e.metaKey || e.ctrlKey)) {
+ e.preventDefault();
+ this.toggle();
+ }
+ };
+
+ setOpenMobile = (value: boolean) => {
+ this.openMobile = value;
+ };
+
+ toggle = () => {
+ return this.#isMobile.current ? (this.openMobile = !this.openMobile) : this.setOpen(!this.open);
+ };
+}
+
+const SYMBOL_KEY = 'scn-sidebar';
+
+/**
+ * Instantiates a new `SidebarState` instance and sets it in the context.
+ *
+ * @param props The constructor props for the `SidebarState` class.
+ * @returns The `SidebarState` instance.
+ */
+export function setSidebar(props: SidebarStateProps): SidebarState {
+ return setContext(Symbol.for(SYMBOL_KEY), new SidebarState(props));
+}
+
+/**
+ * Retrieves the `SidebarState` instance from the context. This is a class instance,
+ * so you cannot destructure it.
+ * @returns The `SidebarState` instance.
+ */
+export function useSidebar(): SidebarState {
+ return getContext(Symbol.for(SYMBOL_KEY));
+}
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/index.ts
new file mode 100644
index 0000000..280e640
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/index.ts
@@ -0,0 +1,75 @@
+import { useSidebar } from './context.svelte.js';
+import Content from './sidebar-content.svelte';
+import Footer from './sidebar-footer.svelte';
+import GroupAction from './sidebar-group-action.svelte';
+import GroupContent from './sidebar-group-content.svelte';
+import GroupLabel from './sidebar-group-label.svelte';
+import Group from './sidebar-group.svelte';
+import Header from './sidebar-header.svelte';
+import Input from './sidebar-input.svelte';
+import Inset from './sidebar-inset.svelte';
+import MenuAction from './sidebar-menu-action.svelte';
+import MenuBadge from './sidebar-menu-badge.svelte';
+import MenuButton from './sidebar-menu-button.svelte';
+import MenuItem from './sidebar-menu-item.svelte';
+import MenuSkeleton from './sidebar-menu-skeleton.svelte';
+import MenuSubButton from './sidebar-menu-sub-button.svelte';
+import MenuSubItem from './sidebar-menu-sub-item.svelte';
+import MenuSub from './sidebar-menu-sub.svelte';
+import Menu from './sidebar-menu.svelte';
+import Provider from './sidebar-provider.svelte';
+import Rail from './sidebar-rail.svelte';
+import Separator from './sidebar-separator.svelte';
+import Trigger from './sidebar-trigger.svelte';
+import Root from './sidebar.svelte';
+
+export {
+ Content,
+ Footer,
+ Group,
+ GroupAction,
+ GroupContent,
+ GroupLabel,
+ Header,
+ Input,
+ Inset,
+ Menu,
+ MenuAction,
+ MenuBadge,
+ MenuButton,
+ MenuItem,
+ MenuSkeleton,
+ MenuSub,
+ MenuSubButton,
+ MenuSubItem,
+ Provider,
+ Rail,
+ Root,
+ Separator,
+ //
+ Root as Sidebar,
+ Content as SidebarContent,
+ Footer as SidebarFooter,
+ Group as SidebarGroup,
+ GroupAction as SidebarGroupAction,
+ GroupContent as SidebarGroupContent,
+ GroupLabel as SidebarGroupLabel,
+ Header as SidebarHeader,
+ Input as SidebarInput,
+ Inset as SidebarInset,
+ Menu as SidebarMenu,
+ MenuAction as SidebarMenuAction,
+ MenuBadge as SidebarMenuBadge,
+ MenuButton as SidebarMenuButton,
+ MenuItem as SidebarMenuItem,
+ MenuSkeleton as SidebarMenuSkeleton,
+ MenuSub as SidebarMenuSub,
+ MenuSubButton as SidebarMenuSubButton,
+ MenuSubItem as SidebarMenuSubItem,
+ Provider as SidebarProvider,
+ Rail as SidebarRail,
+ Separator as SidebarSeparator,
+ Trigger as SidebarTrigger,
+ Trigger,
+ useSidebar
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-content.svelte
new file mode 100644
index 0000000..0e5f75e
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-content.svelte
@@ -0,0 +1,24 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="sidebar-content"
+ data-sidebar="content"
+ class={cn(
+ 'flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-footer.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-footer.svelte
new file mode 100644
index 0000000..67be0a4
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-footer.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="sidebar-footer"
+ data-sidebar="footer"
+ class={cn('flex flex-col gap-2 p-2', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-action.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-action.svelte
new file mode 100644
index 0000000..027a711
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-action.svelte
@@ -0,0 +1,36 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { Snippet } from 'svelte';
+ import type { HTMLButtonAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ child,
+ ...restProps
+ }: WithElementRef<HTMLButtonAttributes> & {
+ child?: Snippet<[{ props: Record<string, unknown> }]>;
+ } = $props();
+
+ const mergedProps = $derived({
+ class: cn(
+ 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground outline-hidden absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
+ // Increases the hit area of the button on mobile.
+ 'after:absolute after:-inset-2 md:after:hidden',
+ 'group-data-[collapsible=icon]:hidden',
+ className
+ ),
+ 'data-slot': 'sidebar-group-action',
+ 'data-sidebar': 'group-action',
+ ...restProps
+ });
+</script>
+
+{#if child}
+ {@render child({ props: mergedProps })}
+{:else}
+ <button bind:this={ref} {...mergedProps}>
+ {@render children?.()}
+ </button>
+{/if}
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-content.svelte
new file mode 100644
index 0000000..9e018fb
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-content.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/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="sidebar-group-content"
+ data-sidebar="group-content"
+ class={cn('w-full text-sm', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-label.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-label.svelte
new file mode 100644
index 0000000..79f47d7
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group-label.svelte
@@ -0,0 +1,34 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { Snippet } from 'svelte';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ children,
+ child,
+ class: className,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLElement>> & {
+ child?: Snippet<[{ props: Record<string, unknown> }]>;
+ } = $props();
+
+ const mergedProps = $derived({
+ class: cn(
+ 'text-sidebar-foreground/70 ring-sidebar-ring outline-hidden flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
+ 'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',
+ className
+ ),
+ 'data-slot': 'sidebar-group-label',
+ 'data-sidebar': 'group-label',
+ ...restProps
+ });
+</script>
+
+{#if child}
+ {@render child({ props: mergedProps })}
+{:else}
+ <div bind:this={ref} {...mergedProps}>
+ {@render children?.()}
+ </div>
+{/if}
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group.svelte
new file mode 100644
index 0000000..eed5ace
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-group.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="sidebar-group"
+ data-sidebar="group"
+ class={cn('relative flex w-full min-w-0 flex-col p-2', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-header.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-header.svelte
new file mode 100644
index 0000000..0651550
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-header.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="sidebar-header"
+ data-sidebar="header"
+ class={cn('flex flex-col gap-2 p-2', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-input.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-input.svelte
new file mode 100644
index 0000000..fa57473
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-input.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+ import type { ComponentProps } from 'svelte';
+ import { Input } from '$lib/components/ui/input/index.js';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ value = $bindable(''),
+ class: className,
+ ...restProps
+ }: ComponentProps<typeof Input> = $props();
+</script>
+
+<Input
+ bind:ref
+ bind:value
+ data-slot="sidebar-input"
+ data-sidebar="input"
+ class={cn('h-8 w-full bg-background shadow-none', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-inset.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-inset.svelte
new file mode 100644
index 0000000..f55d2f4
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-inset.svelte
@@ -0,0 +1,24 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
+</script>
+
+<main
+ bind:this={ref}
+ data-slot="sidebar-inset"
+ class={cn(
+ 'relative flex w-full flex-1 flex-col',
+ 'md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</main>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-action.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-action.svelte
new file mode 100644
index 0000000..ded1ffd
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-action.svelte
@@ -0,0 +1,43 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { Snippet } from 'svelte';
+ import type { HTMLButtonAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ showOnHover = false,
+ children,
+ child,
+ ...restProps
+ }: WithElementRef<HTMLButtonAttributes> & {
+ child?: Snippet<[{ props: Record<string, unknown> }]>;
+ showOnHover?: boolean;
+ } = $props();
+
+ const mergedProps = $derived({
+ class: cn(
+ 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground outline-hidden absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
+ // Increases the hit area of the button on mobile.
+ 'after:absolute after:-inset-2 md:after:hidden',
+ 'peer-data-[size=sm]/menu-button:top-1',
+ 'peer-data-[size=default]/menu-button:top-1.5',
+ 'peer-data-[size=lg]/menu-button:top-2.5',
+ 'group-data-[collapsible=icon]:hidden',
+ showOnHover &&
+ 'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0',
+ className
+ ),
+ 'data-slot': 'sidebar-menu-action',
+ 'data-sidebar': 'menu-action',
+ ...restProps
+ });
+</script>
+
+{#if child}
+ {@render child({ props: mergedProps })}
+{:else}
+ <button bind:this={ref} {...mergedProps}>
+ {@render children?.()}
+ </button>
+{/if}
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte
new file mode 100644
index 0000000..f4525a1
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte
@@ -0,0 +1,29 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="sidebar-menu-badge"
+ data-sidebar="menu-badge"
+ class={cn(
+ 'pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none',
+ 'peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground',
+ 'peer-data-[size=sm]/menu-button:top-1',
+ 'peer-data-[size=default]/menu-button:top-1.5',
+ 'peer-data-[size=lg]/menu-button:top-2.5',
+ 'group-data-[collapsible=icon]:hidden',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-button.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-button.svelte
new file mode 100644
index 0000000..2ce0305
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-button.svelte
@@ -0,0 +1,106 @@
+<script lang="ts" module>
+ import { tv, type VariantProps } from 'tailwind-variants';
+
+ export const sidebarMenuButtonVariants = tv({
+ base: 'peer/menu-button outline-hidden ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground group-has-data-[sidebar=menu-action]/menu-item:pr-8 data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm transition-[width,height,padding] focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:font-medium [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
+ variants: {
+ variant: {
+ default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
+ outline:
+ 'bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_var(--sidebar-border)] hover:shadow-[0_0_0_1px_var(--sidebar-accent)]'
+ },
+ size: {
+ default: 'h-8 text-sm',
+ sm: 'h-7 text-xs',
+ lg: 'group-data-[collapsible=icon]:p-0! h-12 text-sm'
+ }
+ },
+ defaultVariants: {
+ variant: 'default',
+ size: 'default'
+ }
+ });
+
+ export type SidebarMenuButtonVariant = VariantProps<typeof sidebarMenuButtonVariants>['variant'];
+ export type SidebarMenuButtonSize = VariantProps<typeof sidebarMenuButtonVariants>['size'];
+</script>
+
+<script lang="ts">
+ import * as Tooltip from '$lib/components/ui/tooltip/index.js';
+ import {
+ cn,
+ type WithElementRef,
+ type WithoutChildrenOrChild
+ } from '$lib/components/ui/utils.js';
+ import { mergeProps } from 'bits-ui';
+ import type { ComponentProps, Snippet } from 'svelte';
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { useSidebar } from './context.svelte.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ child,
+ variant = 'default',
+ size = 'default',
+ isActive = false,
+ tooltipContent,
+ tooltipContentProps,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement> & {
+ isActive?: boolean;
+ variant?: SidebarMenuButtonVariant;
+ size?: SidebarMenuButtonSize;
+ tooltipContent?: Snippet | string;
+ tooltipContentProps?: WithoutChildrenOrChild<ComponentProps<typeof Tooltip.Content>>;
+ child?: Snippet<[{ props: Record<string, unknown> }]>;
+ } = $props();
+
+ const sidebar = useSidebar();
+
+ const buttonProps = $derived({
+ class: cn(sidebarMenuButtonVariants({ variant, size }), className),
+ 'data-slot': 'sidebar-menu-button',
+ 'data-sidebar': 'menu-button',
+ 'data-size': size,
+ 'data-active': isActive,
+ ...restProps
+ });
+</script>
+
+{#snippet Button({ props }: { props?: Record<string, unknown> })}
+ {@const mergedProps = mergeProps(buttonProps, props)}
+ {#if child}
+ {@render child({ props: mergedProps })}
+ {:else}
+ <button bind:this={ref} {...mergedProps}>
+ {@render children?.()}
+ </button>
+ {/if}
+{/snippet}
+
+{#if !tooltipContent}
+ {@render Button({})}
+{:else}
+ <Tooltip.Root>
+ <Tooltip.Trigger>
+ {#snippet child({ props })}
+ {@render Button({ props })}
+ {/snippet}
+ </Tooltip.Trigger>
+
+ <Tooltip.Content
+ side="right"
+ align="center"
+ hidden={sidebar.state !== 'collapsed' || sidebar.isMobile}
+ {...tooltipContentProps}
+ >
+ {#if typeof tooltipContent === 'string'}
+ {tooltipContent}
+ {:else if tooltipContent}
+ {@render tooltipContent()}
+ {/if}
+ </Tooltip.Content>
+ </Tooltip.Root>
+{/if}
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-item.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-item.svelte
new file mode 100644
index 0000000..5adbedd
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-item.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLLIElement>, HTMLLIElement> = $props();
+</script>
+
+<li
+ bind:this={ref}
+ data-slot="sidebar-menu-item"
+ data-sidebar="menu-item"
+ class={cn('group/menu-item relative', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</li>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte
new file mode 100644
index 0000000..2b2acd6
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte
@@ -0,0 +1,36 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import { Skeleton } from '$lib/components/ui/skeleton/index.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ showIcon = false,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLElement>> & {
+ showIcon?: boolean;
+ } = $props();
+
+ // Random width between 50% and 90%
+ const width = `${Math.floor(Math.random() * 40) + 50}%`;
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="sidebar-menu-skeleton"
+ data-sidebar="menu-skeleton"
+ class={cn('flex h-8 items-center gap-2 rounded-md px-2', className)}
+ {...restProps}
+>
+ {#if showIcon}
+ <Skeleton class="size-4 rounded-md" data-sidebar="menu-skeleton-icon" />
+ {/if}
+ <Skeleton
+ class="h-4 max-w-(--skeleton-width) flex-1"
+ data-sidebar="menu-skeleton-text"
+ style="--skeleton-width: {width};"
+ />
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte
new file mode 100644
index 0000000..dabfe0f
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte
@@ -0,0 +1,43 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { Snippet } from 'svelte';
+ import type { HTMLAnchorAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ children,
+ child,
+ class: className,
+ size = 'md',
+ isActive = false,
+ ...restProps
+ }: WithElementRef<HTMLAnchorAttributes> & {
+ child?: Snippet<[{ props: Record<string, unknown> }]>;
+ size?: 'sm' | 'md';
+ isActive?: boolean;
+ } = $props();
+
+ const mergedProps = $derived({
+ class: cn(
+ 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground outline-hidden flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
+ 'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',
+ size === 'sm' && 'text-xs',
+ size === 'md' && 'text-sm',
+ 'group-data-[collapsible=icon]:hidden',
+ className
+ ),
+ 'data-slot': 'sidebar-menu-sub-button',
+ 'data-sidebar': 'menu-sub-button',
+ 'data-size': size,
+ 'data-active': isActive,
+ ...restProps
+ });
+</script>
+
+{#if child}
+ {@render child({ props: mergedProps })}
+{:else}
+ <a bind:this={ref} {...mergedProps}>
+ {@render children?.()}
+ </a>
+{/if}
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte
new file mode 100644
index 0000000..cca870e
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ children,
+ class: className,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLLIElement>> = $props();
+</script>
+
+<li
+ bind:this={ref}
+ data-slot="sidebar-menu-sub-item"
+ data-sidebar="menu-sub-item"
+ class={cn('group/menu-sub-item relative', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</li>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte
new file mode 100644
index 0000000..5458ced
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte
@@ -0,0 +1,25 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLUListElement>> = $props();
+</script>
+
+<ul
+ bind:this={ref}
+ data-slot="sidebar-menu-sub"
+ data-sidebar="menu-sub"
+ class={cn(
+ 'mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5',
+ 'group-data-[collapsible=icon]:hidden',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</ul>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu.svelte
new file mode 100644
index 0000000..fee96ed
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLUListElement>, HTMLUListElement> = $props();
+</script>
+
+<ul
+ bind:this={ref}
+ data-slot="sidebar-menu"
+ data-sidebar="menu"
+ class={cn('flex w-full min-w-0 flex-col gap-1', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</ul>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-provider.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-provider.svelte
new file mode 100644
index 0000000..364235a
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-provider.svelte
@@ -0,0 +1,50 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+ import {
+ SIDEBAR_COOKIE_MAX_AGE,
+ SIDEBAR_COOKIE_NAME,
+ SIDEBAR_WIDTH,
+ SIDEBAR_WIDTH_ICON
+ } from './constants.js';
+ import { setSidebar } from './context.svelte.js';
+
+ let {
+ ref = $bindable(null),
+ open = $bindable(true),
+ onOpenChange = () => {},
+ class: className,
+ style,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
+ open?: boolean;
+ onOpenChange?: (open: boolean) => void;
+ } = $props();
+
+ const sidebar = setSidebar({
+ open: () => open,
+ setOpen: (value: boolean) => {
+ open = value;
+ onOpenChange(value);
+
+ // This sets the cookie to keep the sidebar state.
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
+ }
+ });
+</script>
+
+<svelte:window onkeydown={sidebar.handleShortcutKeydown} />
+
+<div
+ data-slot="sidebar-wrapper"
+ style="--sidebar-width: {SIDEBAR_WIDTH}; --sidebar-width-icon: {SIDEBAR_WIDTH_ICON}; {style}"
+ class={cn(
+ 'group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar',
+ className
+ )}
+ bind:this={ref}
+ {...restProps}
+>
+ {@render children?.()}
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-rail.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-rail.svelte
new file mode 100644
index 0000000..cde9307
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-rail.svelte
@@ -0,0 +1,36 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { useSidebar } from './context.svelte.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement> = $props();
+
+ const sidebar = useSidebar();
+</script>
+
+<button
+ bind:this={ref}
+ data-sidebar="rail"
+ data-slot="sidebar-rail"
+ aria-label="Toggle Sidebar"
+ tabIndex={-1}
+ onclick={sidebar.toggle}
+ title="Toggle Sidebar"
+ class={cn(
+ 'absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-[calc(1/2*100%-1px)] after:w-[2px] hover:after:bg-sidebar-border sm:flex',
+ 'in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize',
+ '[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize',
+ 'group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar',
+ '[[data-side=left][data-collapsible=offcanvas]_&]:-right-2',
+ '[[data-side=right][data-collapsible=offcanvas]_&]:-left-2',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</button>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-separator.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-separator.svelte
new file mode 100644
index 0000000..8fc2065
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-separator.svelte
@@ -0,0 +1,19 @@
+<script lang="ts">
+ import { Separator } from '$lib/components/ui/separator/index.js';
+ import { cn } from '$lib/components/ui/utils.js';
+ import type { ComponentProps } from 'svelte';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: ComponentProps<typeof Separator> = $props();
+</script>
+
+<Separator
+ bind:ref
+ data-slot="sidebar-separator"
+ data-sidebar="separator"
+ class={cn('bg-sidebar-border', className)}
+ {...restProps}
+/>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-trigger.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-trigger.svelte
new file mode 100644
index 0000000..29d3a9c
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-trigger.svelte
@@ -0,0 +1,35 @@
+<script lang="ts">
+ import { Button } from '$lib/components/ui/button/index.js';
+ import { cn } from '$lib/components/ui/utils.js';
+ import PanelLeftIcon from '@lucide/svelte/icons/panel-left';
+ import type { ComponentProps } from 'svelte';
+ import { useSidebar } from './context.svelte.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ onclick,
+ ...restProps
+ }: ComponentProps<typeof Button> & {
+ onclick?: (e: MouseEvent) => void;
+ } = $props();
+
+ const sidebar = useSidebar();
+</script>
+
+<Button
+ data-sidebar="trigger"
+ data-slot="sidebar-trigger"
+ variant="ghost"
+ size="icon"
+ class={cn('size-7', className)}
+ type="button"
+ onclick={(e) => {
+ onclick?.(e);
+ sidebar.toggle();
+ }}
+ {...restProps}
+>
+ <PanelLeftIcon />
+ <span class="sr-only">Toggle Sidebar</span>
+</Button>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar.svelte
new file mode 100644
index 0000000..e2c4a75
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar.svelte
@@ -0,0 +1,101 @@
+<script lang="ts">
+ import * as Sheet from '$lib/components/ui/sheet/index.js';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+ import { SIDEBAR_WIDTH_MOBILE } from './constants.js';
+ import { useSidebar } from './context.svelte.js';
+
+ let {
+ ref = $bindable(null),
+ side = 'left',
+ variant = 'sidebar',
+ collapsible = 'offcanvas',
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
+ side?: 'left' | 'right';
+ variant?: 'sidebar' | 'floating' | 'inset';
+ collapsible?: 'offcanvas' | 'icon' | 'none';
+ } = $props();
+
+ const sidebar = useSidebar();
+</script>
+
+{#if collapsible === 'none'}
+ <div
+ class={cn(
+ 'flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground',
+ className
+ )}
+ bind:this={ref}
+ {...restProps}
+ >
+ {@render children?.()}
+ </div>
+{:else if sidebar.isMobile}
+ <Sheet.Root bind:open={() => sidebar.openMobile, (v) => sidebar.setOpenMobile(v)} {...restProps}>
+ <Sheet.Content
+ data-sidebar="sidebar"
+ data-slot="sidebar"
+ data-mobile="true"
+ class="z-99999 w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground sm:z-99 [&>button]:hidden"
+ style="--sidebar-width: {SIDEBAR_WIDTH_MOBILE};"
+ {side}
+ >
+ <Sheet.Header class="sr-only">
+ <Sheet.Title>Sidebar</Sheet.Title>
+ <Sheet.Description>Displays the mobile sidebar.</Sheet.Description>
+ </Sheet.Header>
+ <div class="flex h-full w-full flex-col">
+ {@render children?.()}
+ </div>
+ </Sheet.Content>
+ </Sheet.Root>
+{:else}
+ <div
+ bind:this={ref}
+ class="group peer hidden text-sidebar-foreground md:block"
+ data-state={sidebar.state}
+ data-collapsible={sidebar.state === 'collapsed' ? collapsible : ''}
+ data-variant={variant}
+ data-side={side}
+ data-slot="sidebar"
+ >
+ <!-- This is what handles the sidebar gap on desktop -->
+ <div
+ data-slot="sidebar-gap"
+ class={cn(
+ 'relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear',
+ 'group-data-[collapsible=offcanvas]:w-0',
+ 'group-data-[side=right]:rotate-180',
+ variant === 'floating' || variant === 'inset'
+ ? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'
+ : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)'
+ )}
+ ></div>
+ <div
+ data-slot="sidebar-container"
+ class={cn(
+ 'fixed inset-y-0 z-999 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:z-0 md:flex',
+ side === 'left'
+ ? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
+ : 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
+ // Adjust the padding for floating and inset variants.
+ variant === 'floating' || variant === 'inset'
+ ? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'
+ : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)',
+ className
+ )}
+ {...restProps}
+ >
+ <div
+ data-sidebar="sidebar"
+ data-slot="sidebar-inner"
+ class="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm"
+ >
+ {@render children?.()}
+ </div>
+ </div>
+ </div>
+{/if}
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/skeleton/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/skeleton/index.ts
new file mode 100644
index 0000000..3120ce1
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/skeleton/index.ts
@@ -0,0 +1,7 @@
+import Root from './skeleton.svelte';
+
+export {
+ Root,
+ //
+ Root as Skeleton
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/skeleton/skeleton.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/skeleton/skeleton.svelte
new file mode 100644
index 0000000..62b6f80
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/skeleton/skeleton.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+ import { cn, type WithElementRef, type WithoutChildren } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ ...restProps
+ }: WithoutChildren<WithElementRef<HTMLAttributes<HTMLDivElement>>> = $props();
+</script>
+
+<div
+ bind:this={ref}
+ data-slot="skeleton"
+ class={cn('animate-pulse rounded-md bg-accent', className)}
+ {...restProps}
+></div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/switch/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/switch/index.ts
new file mode 100644
index 0000000..129f8f5
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/switch/index.ts
@@ -0,0 +1,7 @@
+import Root from './switch.svelte';
+
+export {
+ Root,
+ //
+ Root as Switch
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/switch/switch.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/switch/switch.svelte
new file mode 100644
index 0000000..5a5975e
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/switch/switch.svelte
@@ -0,0 +1,29 @@
+<script lang="ts">
+ import { Switch as SwitchPrimitive } from 'bits-ui';
+ import { cn, type WithoutChildrenOrChild } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ checked = $bindable(false),
+ ...restProps
+ }: WithoutChildrenOrChild<SwitchPrimitive.RootProps> = $props();
+</script>
+
+<SwitchPrimitive.Root
+ bind:ref
+ bind:checked
+ data-slot="switch"
+ class={cn(
+ 'peer inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80',
+ className
+ )}
+ {...restProps}
+>
+ <SwitchPrimitive.Thumb
+ data-slot="switch-thumb"
+ class={cn(
+ 'pointer-events-none block size-4 rounded-full bg-background ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0 dark:data-[state=checked]:bg-primary-foreground dark:data-[state=unchecked]:bg-foreground'
+ )}
+ />
+</SwitchPrimitive.Root>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/table/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/table/index.ts
new file mode 100644
index 0000000..99239ae
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/table/index.ts
@@ -0,0 +1,28 @@
+import Root from './table.svelte';
+import Body from './table-body.svelte';
+import Caption from './table-caption.svelte';
+import Cell from './table-cell.svelte';
+import Footer from './table-footer.svelte';
+import Head from './table-head.svelte';
+import Header from './table-header.svelte';
+import Row from './table-row.svelte';
+
+export {
+ Root,
+ Body,
+ Caption,
+ Cell,
+ Footer,
+ Head,
+ Header,
+ Row,
+ //
+ Root as Table,
+ Body as TableBody,
+ Caption as TableCaption,
+ Cell as TableCell,
+ Footer as TableFooter,
+ Head as TableHead,
+ Header as TableHeader,
+ Row as TableRow
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-body.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-body.svelte
new file mode 100644
index 0000000..f8df65c
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-body.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
+</script>
+
+<tbody
+ bind:this={ref}
+ data-slot="table-body"
+ class={cn('[&_tr:last-child]:border-0', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</tbody>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-caption.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-caption.svelte
new file mode 100644
index 0000000..0fdcc64
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-caption.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
+</script>
+
+<caption
+ bind:this={ref}
+ data-slot="table-caption"
+ class={cn('mt-4 text-sm text-muted-foreground', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</caption>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-cell.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-cell.svelte
new file mode 100644
index 0000000..4506fdf
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-cell.svelte
@@ -0,0 +1,23 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLTdAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLTdAttributes> = $props();
+</script>
+
+<td
+ bind:this={ref}
+ data-slot="table-cell"
+ class={cn(
+ 'bg-clip-padding p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pe-0',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</td>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-footer.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-footer.svelte
new file mode 100644
index 0000000..77e4a64
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-footer.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
+</script>
+
+<tfoot
+ bind:this={ref}
+ data-slot="table-footer"
+ class={cn('border-t bg-muted/50 font-medium [&>tr]:last:border-b-0', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</tfoot>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-head.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-head.svelte
new file mode 100644
index 0000000..c1c57ad
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-head.svelte
@@ -0,0 +1,23 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLThAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLThAttributes> = $props();
+</script>
+
+<th
+ bind:this={ref}
+ data-slot="table-head"
+ class={cn(
+ 'h-10 bg-clip-padding px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pe-0',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</th>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-header.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-header.svelte
new file mode 100644
index 0000000..eb36673
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-header.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
+</script>
+
+<thead
+ bind:this={ref}
+ data-slot="table-header"
+ class={cn('[&_tr]:border-b', className)}
+ {...restProps}
+>
+ {@render children?.()}
+</thead>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-row.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-row.svelte
new file mode 100644
index 0000000..4131d36
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table-row.svelte
@@ -0,0 +1,23 @@
+<script lang="ts">
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+ import type { HTMLAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLAttributes<HTMLTableRowElement>> = $props();
+</script>
+
+<tr
+ bind:this={ref}
+ data-slot="table-row"
+ class={cn(
+ 'border-b transition-colors data-[state=selected]:bg-muted hover:[&,&>svelte-css-wrapper]:[&>th,td]:bg-muted/50',
+ className
+ )}
+ {...restProps}
+>
+ {@render children?.()}
+</tr>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/table/table.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table.svelte
new file mode 100644
index 0000000..c11a6a6
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/table/table.svelte
@@ -0,0 +1,22 @@
+<script lang="ts">
+ import type { HTMLTableAttributes } from 'svelte/elements';
+ import { cn, type WithElementRef } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ children,
+ ...restProps
+ }: WithElementRef<HTMLTableAttributes> = $props();
+</script>
+
+<div data-slot="table-container" class="relative w-full overflow-x-auto">
+ <table
+ bind:this={ref}
+ data-slot="table"
+ class={cn('w-full caption-bottom text-sm', className)}
+ {...restProps}
+ >
+ {@render children?.()}
+ </table>
+</div>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/textarea/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/textarea/index.ts
new file mode 100644
index 0000000..9ccb3bf
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/textarea/index.ts
@@ -0,0 +1,7 @@
+import Root from './textarea.svelte';
+
+export {
+ Root,
+ //
+ Root as Textarea
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/textarea/textarea.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/textarea/textarea.svelte
new file mode 100644
index 0000000..bf83882
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/textarea/textarea.svelte
@@ -0,0 +1,22 @@
+<script lang="ts">
+ import { cn, type WithElementRef, type WithoutChildren } from '$lib/components/ui/utils';
+ import type { HTMLTextareaAttributes } from 'svelte/elements';
+
+ let {
+ ref = $bindable(null),
+ value = $bindable(),
+ class: className,
+ ...restProps
+ }: WithoutChildren<WithElementRef<HTMLTextareaAttributes>> = $props();
+</script>
+
+<textarea
+ bind:this={ref}
+ data-slot="textarea"
+ class={cn(
+ 'flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:ring-destructive/40',
+ className
+ )}
+ bind:value
+ {...restProps}
+></textarea>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/index.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/index.ts
new file mode 100644
index 0000000..273d831
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/index.ts
@@ -0,0 +1,21 @@
+import { Tooltip as TooltipPrimitive } from 'bits-ui';
+import Trigger from './tooltip-trigger.svelte';
+import Content from './tooltip-content.svelte';
+
+const Root = TooltipPrimitive.Root;
+const Provider = TooltipPrimitive.Provider;
+const Portal = TooltipPrimitive.Portal;
+
+export {
+ Root,
+ Trigger,
+ Content,
+ Provider,
+ Portal,
+ //
+ Root as Tooltip,
+ Content as TooltipContent,
+ Trigger as TooltipTrigger,
+ Provider as TooltipProvider,
+ Portal as TooltipPortal
+};
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/tooltip-content.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/tooltip-content.svelte
new file mode 100644
index 0000000..72ea93a
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/tooltip-content.svelte
@@ -0,0 +1,47 @@
+<script lang="ts">
+ import { Tooltip as TooltipPrimitive } from 'bits-ui';
+ import { cn } from '$lib/components/ui/utils.js';
+
+ let {
+ ref = $bindable(null),
+ class: className,
+ sideOffset = 0,
+ side = 'top',
+ children,
+ arrowClasses,
+ ...restProps
+ }: TooltipPrimitive.ContentProps & {
+ arrowClasses?: string;
+ } = $props();
+</script>
+
+<TooltipPrimitive.Portal>
+ <TooltipPrimitive.Content
+ bind:ref
+ data-slot="tooltip-content"
+ {sideOffset}
+ {side}
+ class={cn(
+ 'z-50 w-fit origin-(--bits-tooltip-content-transform-origin) animate-in rounded-md bg-primary px-3 py-1.5 text-xs text-balance text-primary-foreground fade-in-0 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 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',
+ className
+ )}
+ {...restProps}
+ >
+ {@render children?.()}
+ <TooltipPrimitive.Arrow>
+ {#snippet child({ props })}
+ <div
+ class={cn(
+ 'z-50 size-2.5 rotate-45 rounded-[2px] bg-primary',
+ 'data-[side=top]:translate-x-1/2 data-[side=top]:translate-y-[calc(-50%_+_2px)]',
+ 'data-[side=bottom]:-translate-x-1/2 data-[side=bottom]:-translate-y-[calc(-50%_+_1px)]',
+ 'data-[side=right]:translate-x-[calc(50%_+_2px)] data-[side=right]:translate-y-1/2',
+ 'data-[side=left]:-translate-y-[calc(50%_-_3px)]',
+ arrowClasses
+ )}
+ {...props}
+ ></div>
+ {/snippet}
+ </TooltipPrimitive.Arrow>
+ </TooltipPrimitive.Content>
+</TooltipPrimitive.Portal>
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/tooltip-trigger.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/tooltip-trigger.svelte
new file mode 100644
index 0000000..5631d1b
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/tooltip/tooltip-trigger.svelte
@@ -0,0 +1,7 @@
+<script lang="ts">
+ import { Tooltip as TooltipPrimitive } from 'bits-ui';
+
+ let { ref = $bindable(null), ...restProps }: TooltipPrimitive.TriggerProps = $props();
+</script>
+
+<TooltipPrimitive.Trigger bind:ref data-slot="tooltip-trigger" {...restProps} />
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/utils.ts b/llama.cpp/tools/server/webui/src/lib/components/ui/utils.ts
new file mode 100644
index 0000000..f92bfcb
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/ui/utils.ts
@@ -0,0 +1,13 @@
+import { clsx, type ClassValue } from 'clsx';
+import { twMerge } from 'tailwind-merge';
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type WithoutChild<T> = T extends { child?: any } ? Omit<T, 'child'> : T;
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, 'children'> : T;
+export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
+export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };