a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4 [[data-slot=empty-title]+&]:mt-1",
+ className,
+ )}
+ data-slot="empty-description"
+ {...props}
+ />
+ );
+}
+
+function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ );
+}
+
+export {
+ Empty,
+ EmptyHeader,
+ EmptyTitle,
+ EmptyDescription,
+ EmptyContent,
+ EmptyMedia,
+};
diff --git a/apps/renderer/src/components/ui/field.tsx b/apps/renderer/src/components/ui/field.tsx
new file mode 100644
index 0000000000..71f3352e33
--- /dev/null
+++ b/apps/renderer/src/components/ui/field.tsx
@@ -0,0 +1,72 @@
+import { Field as FieldPrimitive } from "@base-ui/react/field";
+
+import { cn } from "#/lib/utils";
+
+function Field({ className, ...props }: FieldPrimitive.Root.Props) {
+ return (
+
+ );
+}
+
+function FieldLabel({ className, ...props }: FieldPrimitive.Label.Props) {
+ return (
+
+ );
+}
+
+function FieldItem({ className, ...props }: FieldPrimitive.Item.Props) {
+ return (
+
+ );
+}
+
+function FieldDescription({
+ className,
+ ...props
+}: FieldPrimitive.Description.Props) {
+ return (
+
+ );
+}
+
+function FieldError({ className, ...props }: FieldPrimitive.Error.Props) {
+ return (
+
+ );
+}
+
+const FieldControl = FieldPrimitive.Control;
+const FieldValidity = FieldPrimitive.Validity;
+
+export {
+ Field,
+ FieldLabel,
+ FieldDescription,
+ FieldError,
+ FieldControl,
+ FieldItem,
+ FieldValidity,
+};
diff --git a/apps/renderer/src/components/ui/fieldset.tsx b/apps/renderer/src/components/ui/fieldset.tsx
new file mode 100644
index 0000000000..90e51b412f
--- /dev/null
+++ b/apps/renderer/src/components/ui/fieldset.tsx
@@ -0,0 +1,27 @@
+import { Fieldset as FieldsetPrimitive } from "@base-ui/react/fieldset";
+
+import { cn } from "#/lib/utils";
+
+function Fieldset({ className, ...props }: FieldsetPrimitive.Root.Props) {
+ return (
+
+ );
+}
+function FieldsetLegend({
+ className,
+ ...props
+}: FieldsetPrimitive.Legend.Props) {
+ return (
+
+ );
+}
+
+export { Fieldset, FieldsetLegend };
diff --git a/apps/renderer/src/components/ui/form.tsx b/apps/renderer/src/components/ui/form.tsx
new file mode 100644
index 0000000000..aae0a49970
--- /dev/null
+++ b/apps/renderer/src/components/ui/form.tsx
@@ -0,0 +1,15 @@
+import { Form as FormPrimitive } from "@base-ui/react/form";
+
+import { cn } from "#/lib/utils";
+
+function Form({ className, ...props }: FormPrimitive.Props) {
+ return (
+
+ );
+}
+
+export { Form };
diff --git a/apps/renderer/src/components/ui/input-group.tsx b/apps/renderer/src/components/ui/input-group.tsx
new file mode 100644
index 0000000000..82759ef821
--- /dev/null
+++ b/apps/renderer/src/components/ui/input-group.tsx
@@ -0,0 +1,99 @@
+import { type VariantProps, cva } from "class-variance-authority";
+import type * as React from "react";
+
+import { Input, type InputProps } from "#/components/ui/input";
+import { Textarea, type TextareaProps } from "#/components/ui/textarea";
+import { cn } from "#/lib/utils";
+
+function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ );
+}
+
+const inputGroupAddonVariants = cva(
+ "[&_svg]:-mx-0.5 flex h-auto cursor-text select-none items-center justify-center gap-2 leading-none [&>kbd]:rounded-[calc(var(--radius)-5px)] in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 not-has-[button]:**:[svg:not([class*='opacity-'])]:opacity-80",
+ {
+ defaultVariants: {
+ align: "inline-start",
+ },
+ variants: {
+ align: {
+ "block-end":
+ "order-last w-full justify-start px-[calc(--spacing(3)-1px)] pb-[calc(--spacing(3)-1px)] [.border-t]:pt-[calc(--spacing(3)-1px)] [[data-size=sm]+&]:px-[calc(--spacing(2.5)-1px)]",
+ "block-start":
+ "order-first w-full justify-start px-[calc(--spacing(3)-1px)] pt-[calc(--spacing(3)-1px)] [.border-b]:pb-[calc(--spacing(3)-1px)] [[data-size=sm]+&]:px-[calc(--spacing(2.5)-1px)]",
+ "inline-end":
+ "has-[>:last-child[data-slot=badge]]:-me-1.5 has-[>button]:-me-2 order-last pe-[calc(--spacing(3)-1px)] has-[>kbd:last-child]:me-[-0.35rem] [[data-size=sm]+&]:pe-[calc(--spacing(2.5)-1px)]",
+ "inline-start":
+ "has-[>:last-child[data-slot=badge]]:-ms-1.5 has-[>button]:-ms-2 order-first ps-[calc(--spacing(3)-1px)] has-[>kbd:last-child]:ms-[-0.35rem] [[data-size=sm]+&]:ps-[calc(--spacing(2.5)-1px)]",
+ },
+ },
+ },
+);
+
+function InputGroupAddon({
+ className,
+ align = "inline-start",
+ ...props
+}: React.ComponentProps<"div"> & VariantProps
) {
+ return (
+ {
+ const target = e.target as HTMLElement;
+ const isInteractive = target.closest(
+ "button, a, input, select, textarea, [role='button'], [role='combobox'], [role='listbox'], [data-slot='select-trigger']",
+ );
+ if (isInteractive) return;
+ e.preventDefault();
+ const parent = e.currentTarget.parentElement;
+ const input = parent?.querySelector<
+ HTMLInputElement | HTMLTextAreaElement
+ >("input, textarea");
+ if (input && !parent?.querySelector("input:focus, textarea:focus")) {
+ input.focus();
+ }
+ }}
+ {...props}
+ />
+ );
+}
+
+function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
+ return (
+
+ );
+}
+
+function InputGroupInput({ className, ...props }: InputProps) {
+ return
;
+}
+
+function InputGroupTextarea({ className, ...props }: TextareaProps) {
+ return
;
+}
+
+export {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupText,
+ InputGroupInput,
+ InputGroupTextarea,
+};
diff --git a/apps/renderer/src/components/ui/input.tsx b/apps/renderer/src/components/ui/input.tsx
new file mode 100644
index 0000000000..348aab81cb
--- /dev/null
+++ b/apps/renderer/src/components/ui/input.tsx
@@ -0,0 +1,64 @@
+import { Input as InputPrimitive } from "@base-ui/react/input";
+import type * as React from "react";
+
+import { cn } from "#/lib/utils";
+
+type InputProps = Omit<
+ InputPrimitive.Props & React.RefAttributes
,
+ "size"
+> & {
+ size?: "sm" | "default" | "lg" | number;
+ unstyled?: boolean;
+ nativeInput?: boolean;
+};
+
+function Input({
+ className,
+ size = "default",
+ unstyled = false,
+ nativeInput = false,
+ ...props
+}: InputProps) {
+ const inputClassName = cn(
+ "h-8.5 w-full min-w-0 rounded-[inherit] px-[calc(--spacing(3)-1px)] leading-8.5 outline-none placeholder:text-muted-foreground/72 sm:h-7.5 sm:leading-7.5 [transition:background-color_5000000s_ease-in-out_0s]",
+ size === "sm" &&
+ "h-7.5 px-[calc(--spacing(2.5)-1px)] leading-7.5 sm:h-6.5 sm:leading-6.5",
+ size === "lg" && "h-9.5 leading-9.5 sm:h-8.5 sm:leading-8.5",
+ props.type === "search" &&
+ "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none",
+ props.type === "file" &&
+ "text-muted-foreground file:me-3 file:bg-transparent file:font-medium file:text-foreground file:text-sm",
+ );
+
+ return (
+
+ {nativeInput ? (
+
+ ) : (
+
+ )}
+
+ );
+}
+
+export { Input, type InputProps };
diff --git a/apps/renderer/src/components/ui/kbd.tsx b/apps/renderer/src/components/ui/kbd.tsx
new file mode 100644
index 0000000000..0bd1401a09
--- /dev/null
+++ b/apps/renderer/src/components/ui/kbd.tsx
@@ -0,0 +1,28 @@
+import type * as React from "react";
+
+import { cn } from "#/lib/utils";
+
+function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
+ return (
+
+ );
+}
+
+function KbdGroup({ className, ...props }: React.ComponentProps<"kbd">) {
+ return (
+
+ );
+}
+
+export { Kbd, KbdGroup };
diff --git a/apps/renderer/src/components/ui/label.tsx b/apps/renderer/src/components/ui/label.tsx
new file mode 100644
index 0000000000..d8ce1c7a87
--- /dev/null
+++ b/apps/renderer/src/components/ui/label.tsx
@@ -0,0 +1,26 @@
+import { mergeProps } from "@base-ui/react/merge-props";
+import { useRender } from "@base-ui/react/use-render";
+
+import { cn } from "#/lib/utils";
+
+function Label({
+ className,
+ render,
+ ...props
+}: useRender.ComponentProps<"label">) {
+ const defaultProps = {
+ className: cn(
+ "inline-flex items-center gap-2 text-base/4.5 sm:text-sm/4 font-medium text-foreground",
+ className,
+ ),
+ "data-slot": "label",
+ };
+
+ return useRender({
+ defaultTagName: "label",
+ props: mergeProps<"label">(defaultProps, props),
+ render,
+ });
+}
+
+export { Label };
diff --git a/apps/renderer/src/components/ui/menu.tsx b/apps/renderer/src/components/ui/menu.tsx
new file mode 100644
index 0000000000..48c5b44515
--- /dev/null
+++ b/apps/renderer/src/components/ui/menu.tsx
@@ -0,0 +1,308 @@
+import { Menu as MenuPrimitive } from "@base-ui/react/menu";
+import { ChevronRightIcon } from "lucide-react";
+import type * as React from "react";
+import { cn } from "#/lib/utils";
+
+const MenuCreateHandle = MenuPrimitive.createHandle;
+
+const Menu = MenuPrimitive.Root;
+
+const MenuPortal = MenuPrimitive.Portal;
+
+function MenuTrigger(props: MenuPrimitive.Trigger.Props) {
+ return ;
+}
+
+function MenuPopup({
+ children,
+ className,
+ sideOffset = 4,
+ align = "center",
+ alignOffset,
+ side = "bottom",
+ ...props
+}: MenuPrimitive.Popup.Props & {
+ align?: MenuPrimitive.Positioner.Props["align"];
+ sideOffset?: MenuPrimitive.Positioner.Props["sideOffset"];
+ alignOffset?: MenuPrimitive.Positioner.Props["alignOffset"];
+ side?: MenuPrimitive.Positioner.Props["side"];
+}) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+}
+
+function MenuGroup(props: MenuPrimitive.Group.Props) {
+ return ;
+}
+
+function MenuItem({
+ className,
+ inset,
+ variant = "default",
+ ...props
+}: MenuPrimitive.Item.Props & {
+ inset?: boolean;
+ variant?: "default" | "destructive";
+}) {
+ return (
+ svg]:-mx-0.5 flex min-h-8 cursor-default select-none items-center gap-2 rounded-sm px-2 py-1 text-base text-foreground outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-inset:ps-8 data-[variant=destructive]:text-destructive-foreground data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&>svg:not([class*='opacity-'])]:opacity-80 [&>svg:not([class*='size-'])]:size-4.5 sm:[&>svg:not([class*='size-'])]:size-4 [&>svg]:pointer-events-none [&>svg]:shrink-0",
+ className,
+ )}
+ data-inset={inset}
+ data-slot="menu-item"
+ data-variant={variant}
+ {...props}
+ />
+ );
+}
+
+function MenuCheckboxItem({
+ className,
+ children,
+ checked,
+ variant = "default",
+ ...props
+}: MenuPrimitive.CheckboxItem.Props & {
+ variant?: "default" | "switch";
+}) {
+ return (
+
+ {variant === "switch" ? (
+ <>
+ {children}
+
+
+
+ >
+ ) : (
+ <>
+
+
+
+ {children}
+ >
+ )}
+
+ );
+}
+
+function MenuRadioGroup(props: MenuPrimitive.RadioGroup.Props) {
+ return ;
+}
+
+function MenuRadioItem({
+ className,
+ children,
+ ...props
+}: MenuPrimitive.RadioItem.Props) {
+ return (
+
+
+
+
+ {children}
+
+ );
+}
+
+function MenuGroupLabel({
+ className,
+ inset,
+ ...props
+}: MenuPrimitive.GroupLabel.Props & {
+ inset?: boolean;
+}) {
+ return (
+
+ );
+}
+
+function MenuSeparator({ className, ...props }: MenuPrimitive.Separator.Props) {
+ return (
+
+ );
+}
+
+function MenuShortcut({ className, ...props }: React.ComponentProps<"kbd">) {
+ return (
+
+ );
+}
+
+function MenuSub(props: MenuPrimitive.SubmenuRoot.Props) {
+ return ;
+}
+
+function MenuSubTrigger({
+ className,
+ inset,
+ children,
+ ...props
+}: MenuPrimitive.SubmenuTrigger.Props & {
+ inset?: boolean;
+}) {
+ return (
+
+ {children}
+
+
+ );
+}
+
+function MenuSubPopup({
+ className,
+ sideOffset = 0,
+ alignOffset,
+ align = "start",
+ ...props
+}: MenuPrimitive.Popup.Props & {
+ align?: MenuPrimitive.Positioner.Props["align"];
+ sideOffset?: MenuPrimitive.Positioner.Props["sideOffset"];
+ alignOffset?: MenuPrimitive.Positioner.Props["alignOffset"];
+}) {
+ const defaultAlignOffset = align !== "center" ? -5 : undefined;
+
+ return (
+
+ );
+}
+
+export {
+ MenuCreateHandle,
+ MenuCreateHandle as DropdownMenuCreateHandle,
+ Menu,
+ Menu as DropdownMenu,
+ MenuPortal,
+ MenuPortal as DropdownMenuPortal,
+ MenuTrigger,
+ MenuTrigger as DropdownMenuTrigger,
+ MenuPopup,
+ MenuPopup as DropdownMenuContent,
+ MenuGroup,
+ MenuGroup as DropdownMenuGroup,
+ MenuItem,
+ MenuItem as DropdownMenuItem,
+ MenuCheckboxItem,
+ MenuCheckboxItem as DropdownMenuCheckboxItem,
+ MenuRadioGroup,
+ MenuRadioGroup as DropdownMenuRadioGroup,
+ MenuRadioItem,
+ MenuRadioItem as DropdownMenuRadioItem,
+ MenuGroupLabel,
+ MenuGroupLabel as DropdownMenuLabel,
+ MenuSeparator,
+ MenuSeparator as DropdownMenuSeparator,
+ MenuShortcut,
+ MenuShortcut as DropdownMenuShortcut,
+ MenuSub,
+ MenuSub as DropdownMenuSub,
+ MenuSubTrigger,
+ MenuSubTrigger as DropdownMenuSubTrigger,
+ MenuSubPopup,
+ MenuSubPopup as DropdownMenuSubContent,
+};
diff --git a/apps/renderer/src/components/ui/popover.tsx b/apps/renderer/src/components/ui/popover.tsx
new file mode 100644
index 0000000000..df0f9beda4
--- /dev/null
+++ b/apps/renderer/src/components/ui/popover.tsx
@@ -0,0 +1,102 @@
+import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
+
+import { cn } from "#/lib/utils";
+
+const PopoverCreateHandle = PopoverPrimitive.createHandle;
+
+const Popover = PopoverPrimitive.Root;
+
+function PopoverTrigger(props: PopoverPrimitive.Trigger.Props) {
+ return ;
+}
+
+function PopoverPopup({
+ children,
+ className,
+ side = "bottom",
+ align = "center",
+ sideOffset = 4,
+ alignOffset = 0,
+ tooltipStyle = false,
+ ...props
+}: PopoverPrimitive.Popup.Props & {
+ side?: PopoverPrimitive.Positioner.Props["side"];
+ align?: PopoverPrimitive.Positioner.Props["align"];
+ sideOffset?: PopoverPrimitive.Positioner.Props["sideOffset"];
+ alignOffset?: PopoverPrimitive.Positioner.Props["alignOffset"];
+ tooltipStyle?: boolean;
+}) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+}
+
+function PopoverClose({ ...props }: PopoverPrimitive.Close.Props) {
+ return ;
+}
+
+function PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {
+ return (
+
+ );
+}
+
+function PopoverDescription({
+ className,
+ ...props
+}: PopoverPrimitive.Description.Props) {
+ return (
+
+ );
+}
+
+export {
+ PopoverCreateHandle,
+ Popover,
+ PopoverTrigger,
+ PopoverPopup,
+ PopoverPopup as PopoverContent,
+ PopoverTitle,
+ PopoverDescription,
+ PopoverClose,
+};
diff --git a/apps/renderer/src/components/ui/progress.tsx b/apps/renderer/src/components/ui/progress.tsx
new file mode 100644
index 0000000000..382aa0bd3b
--- /dev/null
+++ b/apps/renderer/src/components/ui/progress.tsx
@@ -0,0 +1,79 @@
+import { Progress as ProgressPrimitive } from "@base-ui/react/progress";
+
+import { cn } from "#/lib/utils";
+
+function Progress({
+ className,
+ children,
+ ...props
+}: ProgressPrimitive.Root.Props) {
+ return (
+
+ {children ? (
+ children
+ ) : (
+
+
+
+ )}
+
+ );
+}
+
+function ProgressLabel({ className, ...props }: ProgressPrimitive.Label.Props) {
+ return (
+
+ );
+}
+
+function ProgressTrack({ className, ...props }: ProgressPrimitive.Track.Props) {
+ return (
+
+ );
+}
+
+function ProgressIndicator({
+ className,
+ ...props
+}: ProgressPrimitive.Indicator.Props) {
+ return (
+
+ );
+}
+
+function ProgressValue({ className, ...props }: ProgressPrimitive.Value.Props) {
+ return (
+
+ );
+}
+
+export {
+ Progress,
+ ProgressLabel,
+ ProgressTrack,
+ ProgressIndicator,
+ ProgressValue,
+};
diff --git a/apps/renderer/src/components/ui/radio-group.tsx b/apps/renderer/src/components/ui/radio-group.tsx
new file mode 100644
index 0000000000..af65edd364
--- /dev/null
+++ b/apps/renderer/src/components/ui/radio-group.tsx
@@ -0,0 +1,34 @@
+import { Radio as RadioPrimitive } from "@base-ui/react/radio";
+import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group";
+
+import { cn } from "#/lib/utils";
+
+function RadioGroup({ className, ...props }: RadioGroupPrimitive.Props) {
+ return (
+
+ );
+}
+
+function Radio({ className, ...props }: RadioPrimitive.Root.Props) {
+ return (
+
+
+
+ );
+}
+
+export { RadioGroup, Radio, Radio as RadioGroupItem };
diff --git a/apps/renderer/src/components/ui/scroll-area.tsx b/apps/renderer/src/components/ui/scroll-area.tsx
new file mode 100644
index 0000000000..e4b1a887b6
--- /dev/null
+++ b/apps/renderer/src/components/ui/scroll-area.tsx
@@ -0,0 +1,62 @@
+import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area";
+
+import { cn } from "#/lib/utils";
+
+function ScrollArea({
+ className,
+ children,
+ scrollFade = false,
+ scrollbarGutter = false,
+ ...props
+}: ScrollAreaPrimitive.Root.Props & {
+ scrollFade?: boolean;
+ scrollbarGutter?: boolean;
+}) {
+ return (
+
+
+ {children}
+
+
+
+
+
+ );
+}
+
+function ScrollBar({
+ className,
+ orientation = "vertical",
+ ...props
+}: ScrollAreaPrimitive.Scrollbar.Props) {
+ return (
+
+
+
+ );
+}
+
+export { ScrollArea, ScrollBar };
diff --git a/apps/renderer/src/components/ui/select.tsx b/apps/renderer/src/components/ui/select.tsx
new file mode 100644
index 0000000000..f7662719a5
--- /dev/null
+++ b/apps/renderer/src/components/ui/select.tsx
@@ -0,0 +1,187 @@
+import { Select as SelectPrimitive } from "@base-ui/react/select";
+import {
+ ChevronDownIcon,
+ ChevronUpIcon,
+ ChevronsUpDownIcon,
+} from "lucide-react";
+
+import { cn } from "#/lib/utils";
+
+const Select = SelectPrimitive.Root;
+
+function SelectTrigger({
+ className,
+ size = "default",
+ children,
+ ...props
+}: SelectPrimitive.Trigger.Props & {
+ size?: "sm" | "default" | "lg";
+}) {
+ return (
+
+ {children}
+
+
+
+
+ );
+}
+
+function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
+ return (
+
+ );
+}
+
+function SelectPopup({
+ className,
+ children,
+ side = "bottom",
+ sideOffset = 4,
+ align = "start",
+ alignOffset = 0,
+ alignItemWithTrigger = true,
+ ...props
+}: SelectPrimitive.Popup.Props & {
+ side?: SelectPrimitive.Positioner.Props["side"];
+ sideOffset?: SelectPrimitive.Positioner.Props["sideOffset"];
+ align?: SelectPrimitive.Positioner.Props["align"];
+ alignOffset?: SelectPrimitive.Positioner.Props["alignOffset"];
+ alignItemWithTrigger?: SelectPrimitive.Positioner.Props["alignItemWithTrigger"];
+}) {
+ return (
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+
+
+ );
+}
+
+function SelectItem({
+ className,
+ children,
+ ...props
+}: SelectPrimitive.Item.Props) {
+ return (
+
+
+
+
+
+ {children}
+
+
+ );
+}
+
+function SelectSeparator({
+ className,
+ ...props
+}: SelectPrimitive.Separator.Props) {
+ return (
+
+ );
+}
+
+function SelectGroup(props: SelectPrimitive.Group.Props) {
+ return ;
+}
+
+function SelectGroupLabel(props: SelectPrimitive.GroupLabel.Props) {
+ return (
+
+ );
+}
+
+export {
+ Select,
+ SelectTrigger,
+ SelectValue,
+ SelectPopup,
+ SelectPopup as SelectContent,
+ SelectItem,
+ SelectSeparator,
+ SelectGroup,
+ SelectGroupLabel,
+};
diff --git a/apps/renderer/src/components/ui/separator.tsx b/apps/renderer/src/components/ui/separator.tsx
new file mode 100644
index 0000000000..6a16d92b25
--- /dev/null
+++ b/apps/renderer/src/components/ui/separator.tsx
@@ -0,0 +1,23 @@
+import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
+
+import { cn } from "#/lib/utils";
+
+function Separator({
+ className,
+ orientation = "horizontal",
+ ...props
+}: SeparatorPrimitive.Props) {
+ return (
+
+ );
+}
+
+export { Separator };
diff --git a/apps/renderer/src/components/ui/sheet.tsx b/apps/renderer/src/components/ui/sheet.tsx
new file mode 100644
index 0000000000..a90c12709f
--- /dev/null
+++ b/apps/renderer/src/components/ui/sheet.tsx
@@ -0,0 +1,201 @@
+import { Dialog as SheetPrimitive } from "@base-ui/react/dialog";
+import { XIcon } from "lucide-react";
+import { Button } from "#/components/ui/button";
+import { ScrollArea } from "#/components/ui/scroll-area";
+import { cn } from "#/lib/utils";
+
+const Sheet = SheetPrimitive.Root;
+
+const SheetPortal = SheetPrimitive.Portal;
+
+function SheetTrigger(props: SheetPrimitive.Trigger.Props) {
+ return ;
+}
+
+function SheetClose(props: SheetPrimitive.Close.Props) {
+ return ;
+}
+
+function SheetBackdrop({ className, ...props }: SheetPrimitive.Backdrop.Props) {
+ return (
+
+ );
+}
+
+function SheetViewport({
+ className,
+ side,
+ variant = "default",
+ ...props
+}: SheetPrimitive.Viewport.Props & {
+ side?: "right" | "left" | "top" | "bottom";
+ variant?: "default" | "inset";
+}) {
+ return (
+
+ );
+}
+
+function SheetPopup({
+ className,
+ children,
+ showCloseButton = true,
+ side = "right",
+ variant = "default",
+ ...props
+}: SheetPrimitive.Popup.Props & {
+ showCloseButton?: boolean;
+ side?: "right" | "left" | "top" | "bottom";
+ variant?: "default" | "inset";
+}) {
+ return (
+
+
+
+
+ {children}
+ {showCloseButton && (
+ }
+ >
+
+
+ )}
+
+
+
+ );
+}
+
+function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ );
+}
+
+function SheetFooter({
+ className,
+ variant = "default",
+ ...props
+}: React.ComponentProps<"div"> & {
+ variant?: "default" | "bare";
+}) {
+ return (
+
+ );
+}
+
+function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
+ return (
+
+ );
+}
+
+function SheetDescription({
+ className,
+ ...props
+}: SheetPrimitive.Description.Props) {
+ return (
+
+ );
+}
+
+function SheetPanel({
+ className,
+ scrollFade = true,
+ ...props
+}: React.ComponentProps<"div"> & { scrollFade?: boolean }) {
+ return (
+
+
+
+ );
+}
+
+export {
+ Sheet,
+ SheetTrigger,
+ SheetPortal,
+ SheetClose,
+ SheetBackdrop,
+ SheetBackdrop as SheetOverlay,
+ SheetPopup,
+ SheetPopup as SheetContent,
+ SheetHeader,
+ SheetFooter,
+ SheetTitle,
+ SheetDescription,
+ SheetPanel,
+};
diff --git a/apps/renderer/src/components/ui/skeleton.tsx b/apps/renderer/src/components/ui/skeleton.tsx
new file mode 100644
index 0000000000..7651288751
--- /dev/null
+++ b/apps/renderer/src/components/ui/skeleton.tsx
@@ -0,0 +1,16 @@
+import { cn } from "#/lib/utils";
+
+function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ );
+}
+
+export { Skeleton };
diff --git a/apps/renderer/src/components/ui/spinner.tsx b/apps/renderer/src/components/ui/spinner.tsx
new file mode 100644
index 0000000000..51cf5c4503
--- /dev/null
+++ b/apps/renderer/src/components/ui/spinner.tsx
@@ -0,0 +1,18 @@
+import { Loader2Icon } from "lucide-react";
+import { cn } from "#/lib/utils";
+
+function Spinner({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+export { Spinner };
diff --git a/apps/renderer/src/components/ui/switch.tsx b/apps/renderer/src/components/ui/switch.tsx
new file mode 100644
index 0000000000..fa8346c38a
--- /dev/null
+++ b/apps/renderer/src/components/ui/switch.tsx
@@ -0,0 +1,25 @@
+import { Switch as SwitchPrimitive } from "@base-ui/react/switch";
+
+import { cn } from "#/lib/utils";
+
+function Switch({ className, ...props }: SwitchPrimitive.Root.Props) {
+ return (
+
+
+
+ );
+}
+
+export { Switch };
diff --git a/apps/renderer/src/components/ui/table.tsx b/apps/renderer/src/components/ui/table.tsx
new file mode 100644
index 0000000000..e498f1a785
--- /dev/null
+++ b/apps/renderer/src/components/ui/table.tsx
@@ -0,0 +1,126 @@
+import type * as React from "react";
+
+import { cn } from "#/lib/utils";
+
+function Table({ className, ...props }: React.ComponentProps<"table">) {
+ return (
+
+ );
+}
+
+function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
+ return (
+
+ );
+}
+
+function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
+ return (
+
+ );
+}
+
+function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
+ return (
+ tr]:last:border-b-0 in-data-[slot=frame]:*:[tr]:hover:bg-transparent",
+ className,
+ )}
+ data-slot="table-footer"
+ {...props}
+ />
+ );
+}
+
+function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
+ return (
+
+ );
+}
+
+function TableHead({ className, ...props }: React.ComponentProps<"th">) {
+ return (
+ |
+ );
+}
+
+function TableCell({ className, ...props }: React.ComponentProps<"td">) {
+ return (
+ |
+ );
+}
+
+function TableCaption({
+ className,
+ ...props
+}: React.ComponentProps<"caption">) {
+ return (
+
+ );
+}
+
+export {
+ Table,
+ TableHeader,
+ TableBody,
+ TableFooter,
+ TableHead,
+ TableRow,
+ TableCell,
+ TableCaption,
+};
diff --git a/apps/renderer/src/components/ui/tabs.tsx b/apps/renderer/src/components/ui/tabs.tsx
new file mode 100644
index 0000000000..e0485a6b06
--- /dev/null
+++ b/apps/renderer/src/components/ui/tabs.tsx
@@ -0,0 +1,85 @@
+import { Tabs as TabsPrimitive } from "@base-ui/react/tabs";
+
+import { cn } from "#/lib/utils";
+
+type TabsVariant = "default" | "underline";
+
+function Tabs({ className, ...props }: TabsPrimitive.Root.Props) {
+ return (
+
+ );
+}
+
+function TabsList({
+ variant = "default",
+ className,
+ children,
+ ...props
+}: TabsPrimitive.List.Props & {
+ variant?: TabsVariant;
+}) {
+ return (
+
+ {children}
+
+
+ );
+}
+
+function TabsTab({ className, ...props }: TabsPrimitive.Tab.Props) {
+ return (
+
+ );
+}
+
+function TabsPanel({ className, ...props }: TabsPrimitive.Panel.Props) {
+ return (
+
+ );
+}
+
+export {
+ Tabs,
+ TabsList,
+ TabsTab,
+ TabsTab as TabsTrigger,
+ TabsPanel,
+ TabsPanel as TabsContent,
+};
diff --git a/apps/renderer/src/components/ui/textarea.tsx b/apps/renderer/src/components/ui/textarea.tsx
new file mode 100644
index 0000000000..92934060fc
--- /dev/null
+++ b/apps/renderer/src/components/ui/textarea.tsx
@@ -0,0 +1,49 @@
+import { Field as FieldPrimitive } from "@base-ui/react/field";
+import { mergeProps } from "@base-ui/react/merge-props";
+import type * as React from "react";
+
+import { cn } from "#/lib/utils";
+
+type TextareaProps = React.ComponentProps<"textarea"> & {
+ size?: "sm" | "default" | "lg" | number;
+ unstyled?: boolean;
+};
+
+function Textarea({
+ className,
+ size = "default",
+ unstyled = false,
+ ...props
+}: TextareaProps) {
+ return (
+
+ (
+
+ )}
+ />
+
+ );
+}
+
+export { Textarea, type TextareaProps };
diff --git a/apps/renderer/src/components/ui/toast.tsx b/apps/renderer/src/components/ui/toast.tsx
new file mode 100644
index 0000000000..c7503b3584
--- /dev/null
+++ b/apps/renderer/src/components/ui/toast.tsx
@@ -0,0 +1,267 @@
+import { Toast } from "@base-ui/react/toast";
+import {
+ CircleAlertIcon,
+ CircleCheckIcon,
+ InfoIcon,
+ LoaderCircleIcon,
+ TriangleAlertIcon,
+} from "lucide-react";
+
+import { buttonVariants } from "#/components/ui/button";
+import { cn } from "#/lib/utils";
+
+const toastManager = Toast.createToastManager();
+const anchoredToastManager = Toast.createToastManager();
+
+const TOAST_ICONS = {
+ error: CircleAlertIcon,
+ info: InfoIcon,
+ loading: LoaderCircleIcon,
+ success: CircleCheckIcon,
+ warning: TriangleAlertIcon,
+} as const;
+
+type ToastPosition =
+ | "top-left"
+ | "top-center"
+ | "top-right"
+ | "bottom-left"
+ | "bottom-center"
+ | "bottom-right";
+
+interface ToastProviderProps extends Toast.Provider.Props {
+ position?: ToastPosition;
+}
+
+function ToastProvider({
+ children,
+ position = "bottom-right",
+ ...props
+}: ToastProviderProps) {
+ return (
+
+ {children}
+
+
+ );
+}
+
+function Toasts({ position = "bottom-right" }: { position: ToastPosition }) {
+ const { toasts } = Toast.useToastManager();
+ const isTop = position.startsWith("top");
+
+ return (
+
+
+ {toasts.map((toast) => {
+ const Icon = toast.type
+ ? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS]
+ : null;
+
+ return (
+
+
+
+ {Icon && (
+
+
+
+ )}
+
+
+
+
+
+
+ {toast.actionProps && (
+
+ {toast.actionProps.children}
+
+ )}
+
+
+ );
+ })}
+
+
+ );
+}
+
+function AnchoredToastProvider({ children, ...props }: Toast.Provider.Props) {
+ return (
+
+ {children}
+
+
+ );
+}
+
+function AnchoredToasts() {
+ const { toasts } = Toast.useToastManager();
+
+ return (
+
+
+ {toasts.map((toast) => {
+ const Icon = toast.type
+ ? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS]
+ : null;
+ const tooltipStyle =
+ (toast.data as { tooltipStyle?: boolean })?.tooltipStyle ?? false;
+ const positionerProps = toast.positionerProps;
+
+ if (!positionerProps?.anchor) {
+ return null;
+ }
+
+ return (
+
+
+ {tooltipStyle ? (
+
+
+
+ ) : (
+
+
+ {Icon && (
+
+
+
+ )}
+
+
+
+
+
+
+ {toast.actionProps && (
+
+ {toast.actionProps.children}
+
+ )}
+
+ )}
+
+
+ );
+ })}
+
+
+ );
+}
+
+export {
+ ToastProvider,
+ type ToastPosition,
+ toastManager,
+ AnchoredToastProvider,
+ anchoredToastManager,
+};
diff --git a/apps/renderer/src/hooks/useTheme.ts b/apps/renderer/src/hooks/useTheme.ts
new file mode 100644
index 0000000000..dd3e3c24fd
--- /dev/null
+++ b/apps/renderer/src/hooks/useTheme.ts
@@ -0,0 +1,90 @@
+import { useCallback, useEffect, useSyncExternalStore } from "react";
+
+type Theme = "light" | "dark" | "system";
+
+const STORAGE_KEY = "codething:theme";
+const MEDIA_QUERY = "(prefers-color-scheme: dark)";
+
+let listeners: Array<() => void> = [];
+function emitChange() {
+ for (const listener of listeners) listener();
+}
+
+function getSystemDark(): boolean {
+ return window.matchMedia(MEDIA_QUERY).matches;
+}
+
+function getStored(): Theme {
+ const raw = localStorage.getItem(STORAGE_KEY);
+ if (raw === "light" || raw === "dark" || raw === "system") return raw;
+ return "system";
+}
+
+function applyTheme(theme: Theme, suppressTransitions = false) {
+ if (suppressTransitions) {
+ document.documentElement.classList.add("no-transitions");
+ }
+ const isDark = theme === "dark" || (theme === "system" && getSystemDark());
+ document.documentElement.classList.toggle("dark", isDark);
+ if (suppressTransitions) {
+ // Force a reflow so the no-transitions class takes effect before removal
+ document.documentElement.offsetHeight;
+ requestAnimationFrame(() => {
+ document.documentElement.classList.remove("no-transitions");
+ });
+ }
+}
+
+// Apply immediately on module load to prevent flash
+applyTheme(getStored());
+
+function getSnapshot(): Theme {
+ return getStored();
+}
+
+function subscribe(listener: () => void): () => void {
+ listeners.push(listener);
+
+ // Listen for system preference changes
+ const mq = window.matchMedia(MEDIA_QUERY);
+ const handleChange = () => {
+ if (getStored() === "system") applyTheme("system", true);
+ emitChange();
+ };
+ mq.addEventListener("change", handleChange);
+
+ // Listen for storage changes from other tabs
+ const handleStorage = (e: StorageEvent) => {
+ if (e.key === STORAGE_KEY) {
+ applyTheme(getStored(), true);
+ emitChange();
+ }
+ };
+ window.addEventListener("storage", handleStorage);
+
+ return () => {
+ listeners = listeners.filter((l) => l !== listener);
+ mq.removeEventListener("change", handleChange);
+ window.removeEventListener("storage", handleStorage);
+ };
+}
+
+export function useTheme() {
+ const theme = useSyncExternalStore(subscribe, getSnapshot);
+
+ const resolvedTheme: "light" | "dark" =
+ theme === "system" ? (getSystemDark() ? "dark" : "light") : theme;
+
+ const setTheme = useCallback((next: Theme) => {
+ localStorage.setItem(STORAGE_KEY, next);
+ applyTheme(next, true);
+ emitChange();
+ }, []);
+
+ // Keep DOM in sync on mount/change
+ useEffect(() => {
+ applyTheme(theme);
+ }, [theme]);
+
+ return { theme, setTheme, resolvedTheme } as const;
+}
diff --git a/apps/renderer/src/index.css b/apps/renderer/src/index.css
index f393ff72a6..f0cc6c48dc 100644
--- a/apps/renderer/src/index.css
+++ b/apps/renderer/src/index.css
@@ -1,7 +1,178 @@
@import "tailwindcss";
+@custom-variant dark (&:is(.dark, .dark *));
+
+@theme inline {
+ --animate-skeleton: skeleton 2s -1s infinite linear;
+ --color-warning-foreground: var(--warning-foreground);
+ --color-warning: var(--warning);
+ --color-success-foreground: var(--success-foreground);
+ --color-success: var(--success);
+ --color-info-foreground: var(--info-foreground);
+ --color-info: var(--info);
+ --color-destructive-foreground: var(--destructive-foreground);
+ --color-sidebar-ring: var(--sidebar-ring);
+ --color-sidebar-border: var(--sidebar-border);
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
+ --color-sidebar-accent: var(--sidebar-accent);
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
+ --color-sidebar-primary: var(--sidebar-primary);
+ --color-sidebar-foreground: var(--sidebar-foreground);
+ --color-sidebar: var(--sidebar);
+ --color-chart-5: var(--chart-5);
+ --color-chart-4: var(--chart-4);
+ --color-chart-3: var(--chart-3);
+ --color-chart-2: var(--chart-2);
+ --color-chart-1: var(--chart-1);
+ --color-ring: var(--ring);
+ --color-input: var(--input);
+ --color-border: var(--border);
+ --color-destructive: var(--destructive);
+ --color-accent-foreground: var(--accent-foreground);
+ --color-accent: var(--accent);
+ --color-muted-foreground: var(--muted-foreground);
+ --color-muted: var(--muted);
+ --color-secondary-foreground: var(--secondary-foreground);
+ --color-secondary: var(--secondary);
+ --color-primary-foreground: var(--primary-foreground);
+ --color-primary: var(--primary);
+ --color-popover-foreground: var(--popover-foreground);
+ --color-popover: var(--popover);
+ --color-card-foreground: var(--card-foreground);
+ --color-card: var(--card);
+ --color-foreground: var(--foreground);
+ --color-background: var(--background);
+ --radius-sm: calc(var(--radius) - 4px);
+ --radius-md: calc(var(--radius) - 2px);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) + 4px);
+ --radius-2xl: calc(var(--radius) + 8px);
+ --radius-3xl: calc(var(--radius) + 12px);
+ --radius-4xl: calc(var(--radius) + 16px);
+ @keyframes skeleton {
+ to {
+ background-position: -200% 0;
+ }
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
+
+/* Suppress all transitions during theme changes */
+.no-transitions,
+.no-transitions *,
+.no-transitions *::before,
+.no-transitions *::after {
+ transition-duration: 0s !important;
+ animation-duration: 0s !important;
+}
+
:root {
- color-scheme: dark;
+ color-scheme: light;
+ --radius: 0.625rem;
+ --background: var(--color-white);
+ --foreground: var(--color-neutral-800);
+ --card: var(--color-white);
+ --card-foreground: var(--color-neutral-800);
+ --popover: var(--color-white);
+ --popover-foreground: var(--color-neutral-800);
+ --primary: var(--color-neutral-800);
+ --primary-foreground: var(--color-neutral-50);
+ --secondary: --alpha(var(--color-black) / 4%);
+ --secondary-foreground: var(--color-neutral-800);
+ --muted: --alpha(var(--color-black) / 4%);
+ --muted-foreground: color-mix(
+ in srgb,
+ var(--color-neutral-500) 90%,
+ var(--color-black)
+ );
+ --accent: --alpha(var(--color-black) / 4%);
+ --accent-foreground: var(--color-neutral-800);
+ --destructive: var(--color-red-500);
+ --border: --alpha(var(--color-black) / 8%);
+ --input: --alpha(var(--color-black) / 10%);
+ --ring: var(--color-neutral-400);
+ --chart-1: oklch(0.646 0.222 41.116);
+ --chart-2: oklch(0.6 0.118 184.704);
+ --chart-3: oklch(0.398 0.07 227.392);
+ --chart-4: oklch(0.828 0.189 84.429);
+ --chart-5: oklch(0.769 0.188 70.08);
+ --sidebar: oklch(0.985 0 0);
+ --sidebar-foreground: oklch(0.141 0.005 285.823);
+ --sidebar-primary: oklch(0.21 0.006 285.885);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.967 0.001 286.375);
+ --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
+ --sidebar-border: oklch(0.92 0.004 286.32);
+ --sidebar-ring: oklch(0.705 0.015 286.067);
+ --destructive-foreground: var(--color-red-700);
+ --info: var(--color-blue-500);
+ --info-foreground: var(--color-blue-700);
+ --success: var(--color-emerald-500);
+ --success-foreground: var(--color-emerald-700);
+ --warning: var(--color-amber-500);
+ --warning-foreground: var(--color-amber-700);
+
+ @variant dark {
+ color-scheme: dark;
+ --background: color-mix(
+ in srgb,
+ var(--color-neutral-950) 95%,
+ var(--color-white)
+ );
+ --foreground: var(--color-neutral-100);
+ --card: color-mix(in srgb, var(--background) 98%, var(--color-white));
+ --card-foreground: var(--color-neutral-100);
+ --popover: color-mix(in srgb, var(--background) 98%, var(--color-white));
+ --popover-foreground: var(--color-neutral-100);
+ --primary: var(--color-neutral-100);
+ --primary-foreground: var(--color-neutral-800);
+ --secondary: --alpha(var(--color-white) / 4%);
+ --secondary-foreground: var(--color-neutral-100);
+ --muted: --alpha(var(--color-white) / 4%);
+ --muted-foreground: color-mix(
+ in srgb,
+ var(--color-neutral-500) 90%,
+ var(--color-white)
+ );
+ --accent: --alpha(var(--color-white) / 4%);
+ --accent-foreground: var(--color-neutral-100);
+ --destructive: color-mix(
+ in srgb,
+ var(--color-red-500) 90%,
+ var(--color-white)
+ );
+ --border: --alpha(var(--color-white) / 6%);
+ --input: --alpha(var(--color-white) / 8%);
+ --ring: var(--color-neutral-500);
+ --chart-1: oklch(0.488 0.243 264.376);
+ --chart-2: oklch(0.696 0.17 162.48);
+ --chart-3: oklch(0.769 0.188 70.08);
+ --chart-4: oklch(0.627 0.265 303.9);
+ --chart-5: oklch(0.645 0.246 16.439);
+ --sidebar: oklch(0.21 0.006 285.885);
+ --sidebar-foreground: oklch(0.985 0 0);
+ --sidebar-primary: oklch(0.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.274 0.006 286.033);
+ --sidebar-accent-foreground: oklch(0.985 0 0);
+ --sidebar-border: oklch(1 0 0 / 10%);
+ --sidebar-ring: oklch(0.552 0.016 285.938);
+ --destructive-foreground: var(--color-red-400);
+ --info: var(--color-blue-500);
+ --info-foreground: var(--color-blue-400);
+ --success: var(--color-emerald-500);
+ --success-foreground: var(--color-emerald-400);
+ --warning: var(--color-amber-500);
+ --warning-foreground: var(--color-amber-400);
+ }
}
body {
@@ -10,8 +181,6 @@ body {
margin: 0;
padding: 0;
min-height: 100vh;
- color: #e0e0e0;
- background: #0c0c0c;
}
body::after {
@@ -55,25 +224,20 @@ input {
}
::-webkit-scrollbar-thumb {
- background: rgba(255, 255, 255, 0.1);
+ background: rgba(0, 0, 0, 0.15);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
- background: rgba(255, 255, 255, 0.18);
+ background: rgba(0, 0, 0, 0.25);
}
-/* Reasoning select — clickable label surface */
-label:has(> select#reasoning-effort) {
- position: relative;
+.dark ::-webkit-scrollbar-thumb {
+ background: rgba(255, 255, 255, 0.1);
}
-label:has(> select#reasoning-effort) select {
- position: absolute;
- inset: 0;
- opacity: 0;
- cursor: pointer;
- width: 100%;
- height: 100%;
+
+.dark ::-webkit-scrollbar-thumb:hover {
+ background: rgba(255, 255, 255, 0.18);
}
/* Chat markdown rendering */
@@ -108,34 +272,38 @@ label:has(> select#reasoning-effort) select {
}
.chat-markdown a {
- color: #93c5fd;
+ color: var(--info-foreground);
text-decoration: underline;
- text-decoration-color: rgba(147, 197, 253, 0.4);
+ text-decoration-color: color-mix(
+ in srgb,
+ var(--info-foreground) 40%,
+ transparent
+ );
}
.chat-markdown a:hover {
- color: #bfdbfe;
+ opacity: 0.8;
}
.chat-markdown blockquote {
- border-left: 2px solid rgba(255, 255, 255, 0.2);
+ border-left: 2px solid var(--border);
padding-left: 0.8rem;
- color: rgba(224, 224, 224, 0.75);
+ color: var(--muted-foreground);
}
.chat-markdown :not(pre) > code {
- border: 1px solid rgba(255, 255, 255, 0.12);
+ border: 1px solid var(--border);
border-radius: 0.375rem;
- background: rgba(255, 255, 255, 0.07);
+ background: var(--muted);
padding: 0.1rem 0.35rem;
- color: #f4f4f5;
+ color: var(--foreground);
}
.chat-markdown pre {
overflow-x: auto;
- border: 1px solid rgba(255, 255, 255, 0.12);
+ border: 1px solid var(--border);
border-radius: 0.75rem;
- background: rgba(0, 0, 0, 0.3);
+ background: var(--muted);
padding: 0.8rem 0.9rem;
}
@@ -153,7 +321,7 @@ label:has(> select#reasoning-effort) select {
.chat-markdown th,
.chat-markdown td {
- border: 1px solid rgba(255, 255, 255, 0.12);
+ border: 1px solid var(--border);
padding: 0.35rem 0.45rem;
text-align: left;
}
diff --git a/apps/renderer/src/lib/utils.ts b/apps/renderer/src/lib/utils.ts
new file mode 100644
index 0000000000..365058cebd
--- /dev/null
+++ b/apps/renderer/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { type ClassValue, clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/apps/renderer/tsconfig.json b/apps/renderer/tsconfig.json
index 86307ececc..8eca70ea2a 100644
--- a/apps/renderer/tsconfig.json
+++ b/apps/renderer/tsconfig.json
@@ -4,7 +4,11 @@
"composite": true,
"jsx": "react-jsx",
"lib": ["ES2023", "DOM", "DOM.Iterable"],
- "types": ["vite/client"]
+ "exactOptionalPropertyTypes": false,
+ "types": ["vite/client"],
+ "paths": {
+ "#/*": ["./src/*"]
+ }
},
"include": ["src", "vite.config.ts"]
}
diff --git a/apps/renderer/vite.config.ts b/apps/renderer/vite.config.ts
index e57fcd856a..037f941e92 100644
--- a/apps/renderer/vite.config.ts
+++ b/apps/renderer/vite.config.ts
@@ -1,3 +1,4 @@
+import path from "node:path";
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
@@ -11,6 +12,11 @@ export default defineConfig({
}),
tailwindcss(),
],
+ resolve: {
+ alias: {
+ "#": path.resolve(__dirname, "src"),
+ },
+ },
server: {
port: Number(process.env.ELECTRON_RENDERER_PORT ?? 5173),
strictPort: true,
diff --git a/bun.lock b/bun.lock
index 68e4a9c638..e53dc841d1 100644
--- a/bun.lock
+++ b/bun.lock
@@ -34,12 +34,17 @@
"version": "0.0.0",
"dependencies": {
"@acme/contracts": "workspace:*",
+ "@base-ui/react": "^1.1.0",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
"highlight.js": "^11.11.1",
+ "lucide-react": "^0.563.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-markdown": "^10.1.0",
"rehype-highlight": "^7.0.2",
"remark-gfm": "^4.0.1",
+ "tailwind-merge": "^3.4.0",
"zod": "^3.24.1",
},
"devDependencies": {
@@ -104,12 +109,18 @@
"@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
+ "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="],
+
"@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="],
"@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="],
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
+ "@base-ui/react": ["@base-ui/react@1.1.0", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@base-ui/utils": "0.2.4", "@floating-ui/react-dom": "^2.1.6", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "tabbable": "^6.4.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-ikcJRNj1mOiF2HZ5jQHrXoVoHcNHdBU5ejJljcBl+VTLoYXR6FidjTN86GjO6hyshi6TZFuNvv0dEOgaOFv6Lw=="],
+
+ "@base-ui/utils": ["@base-ui/utils@0.2.4", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-smZwpMhjO29v+jrZusBSc5T+IJ3vBb9cjIiBjtKcvWmRj9Z4DWGVR3efr1eHR56/bqY5a4qyY9ElkOY5ljo3ng=="],
+
"@electron/get": ["@electron/get@2.0.3", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="],
"@electron/node-gyp": ["@electron/node-gyp@github:electron/node-gyp#06b29aa", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^8.1.0", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.2.1", "nopt": "^6.0.0", "proc-log": "^2.0.1", "semver": "^7.3.5", "tar": "^6.2.1", "which": "^2.0.2" }, "bin": "./bin/node-gyp.js" }, "electron-node-gyp-06b29aa"],
@@ -168,6 +179,14 @@
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="],
+ "@floating-ui/core": ["@floating-ui/core@1.7.4", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg=="],
+
+ "@floating-ui/dom": ["@floating-ui/dom@1.7.5", "", { "dependencies": { "@floating-ui/core": "^1.7.4", "@floating-ui/utils": "^0.2.10" } }, "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg=="],
+
+ "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.7", "", { "dependencies": { "@floating-ui/dom": "^1.7.5" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg=="],
+
+ "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
+
"@gar/promisify": ["@gar/promisify@1.1.3", "", {}, "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw=="],
"@hapi/address": ["@hapi/address@5.1.1", "", { "dependencies": { "@hapi/hoek": "^11.0.2" } }, "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA=="],
@@ -182,6 +201,16 @@
"@hapi/topo": ["@hapi/topo@6.0.2", "", { "dependencies": { "@hapi/hoek": "^11.0.2" } }, "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg=="],
+ "@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="],
+
+ "@inquirer/confirm": ["@inquirer/confirm@5.1.21", "", { "dependencies": { "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ=="],
+
+ "@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="],
+
+ "@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="],
+
+ "@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="],
+
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
@@ -194,10 +223,18 @@
"@malept/cross-spawn-promise": ["@malept/cross-spawn-promise@2.0.0", "", { "dependencies": { "cross-spawn": "^7.0.1" } }, "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg=="],
+ "@mswjs/interceptors": ["@mswjs/interceptors@0.41.2", "", { "dependencies": { "@open-draft/deferred-promise": "^2.2.0", "@open-draft/logger": "^0.3.0", "@open-draft/until": "^2.0.0", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "strict-event-emitter": "^0.5.1" } }, "sha512-7G0Uf0yK3f2bjElBLGHIQzgRgMESczOMyYVasq1XK8P5HaXtlW4eQhz9MBL+TQILZLaruq+ClGId+hH0w4jvWw=="],
+
"@npmcli/fs": ["@npmcli/fs@2.1.2", "", { "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" } }, "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ=="],
"@npmcli/move-file": ["@npmcli/move-file@2.0.1", "", { "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ=="],
+ "@open-draft/deferred-promise": ["@open-draft/deferred-promise@2.2.0", "", {}, "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA=="],
+
+ "@open-draft/logger": ["@open-draft/logger@0.3.0", "", { "dependencies": { "is-node-process": "^1.2.0", "outvariant": "^1.4.0" } }, "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ=="],
+
+ "@open-draft/until": ["@open-draft/until@2.1.0", "", {}, "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg=="],
+
"@oxfmt/darwin-arm64": ["@oxfmt/darwin-arm64@0.28.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-jmUfF7cNJPw57bEK7sMIqrYRgn4LH428tSgtgLTCtjuGuu1ShREyrkeB7y8HtkXRfhBs4lVY+HMLhqElJvZ6ww=="],
"@oxfmt/darwin-x64": ["@oxfmt/darwin-x64@0.28.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-S6vlV8S7jbjzJOSjfVg2CimUC0r7/aHDLdUm/3+/B/SU/s1jV7ivqWkMv1/8EB43d1BBwT9JQ60ZMTkBqeXSFA=="],
@@ -358,6 +395,8 @@
"@types/responselike": ["@types/responselike@1.0.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw=="],
+ "@types/statuses": ["@types/statuses@2.0.6", "", {}, "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA=="],
+
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
"@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="],
@@ -460,18 +499,24 @@
"chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
+ "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
+
"clean-stack": ["clean-stack@2.2.0", "", {}, "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="],
"cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
+ "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],
+
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
"clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="],
"clone-response": ["clone-response@1.0.3", "", { "dependencies": { "mimic-response": "^1.0.0" } }, "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA=="],
+ "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
+
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
@@ -490,6 +535,8 @@
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
+ "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
+
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
@@ -614,6 +661,8 @@
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
+ "graphql": ["graphql@16.12.0", "", {}, "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ=="],
+
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
"has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
@@ -632,6 +681,8 @@
"hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
+ "headers-polyfill": ["headers-polyfill@4.0.3", "", {}, "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ=="],
+
"highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="],
"html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],
@@ -680,6 +731,8 @@
"is-lambda": ["is-lambda@1.0.1", "", {}, "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ=="],
+ "is-node-process": ["is-node-process@1.2.0", "", {}, "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw=="],
+
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
"is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
@@ -754,6 +807,8 @@
"lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
+ "lucide-react": ["lucide-react@0.563.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-8dXPB2GI4dI8jV4MgUDGBeLdGk8ekfqVZ0BdLcrRzocGgG75ltNEmWS+gE7uokKF/0oSUuczNDT+g9hFJ23FkA=="],
+
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
"make-fetch-happen": ["make-fetch-happen@10.2.1", "", { "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", "ssri": "^9.0.0" } }, "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w=="],
@@ -884,6 +939,10 @@
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
+ "msw": ["msw@2.12.9", "", { "dependencies": { "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.41.2", "@open-draft/deferred-promise": "^2.2.0", "@types/statuses": "^2.0.6", "cookie": "^1.0.2", "graphql": "^16.12.0", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "rettime": "^0.10.1", "statuses": "^2.0.2", "strict-event-emitter": "^0.5.1", "tough-cookie": "^6.0.0", "type-fest": "^5.2.0", "until-async": "^3.0.2", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": ">= 4.8.x" }, "optionalPeers": ["typescript"], "bin": { "msw": "cli/index.js" } }, "sha512-NYbi51C6M3dujGmcmuGemu68jy12KqQPoVWGeroKToLGsBgrwG5ErM8WctoIIg49/EV49SEvYM9WSqO4G7kNeQ=="],
+
+ "mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="],
+
"mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
@@ -916,6 +975,8 @@
"ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="],
+ "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="],
+
"oxfmt": ["oxfmt@0.28.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/darwin-arm64": "0.28.0", "@oxfmt/darwin-x64": "0.28.0", "@oxfmt/linux-arm64-gnu": "0.28.0", "@oxfmt/linux-arm64-musl": "0.28.0", "@oxfmt/linux-x64-gnu": "0.28.0", "@oxfmt/linux-x64-musl": "0.28.0", "@oxfmt/win32-arm64": "0.28.0", "@oxfmt/win32-x64": "0.28.0" }, "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-3+hhBqPE6Kp22KfJmnstrZbl+KdOVSEu1V0ABaFIg1rYLtrMgrupx9znnHgHLqKxAVHebjTdiCJDk30CXOt6cw=="],
"oxlint": ["oxlint@1.43.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.43.0", "@oxlint/darwin-x64": "1.43.0", "@oxlint/linux-arm64-gnu": "1.43.0", "@oxlint/linux-arm64-musl": "1.43.0", "@oxlint/linux-x64-gnu": "1.43.0", "@oxlint/linux-x64-musl": "1.43.0", "@oxlint/win32-arm64": "1.43.0", "@oxlint/win32-x64": "1.43.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.11.2" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-xiqTCsKZch+R61DPCjyqUVP2MhkQlRRYxLRBeBDi+dtQJ90MOgdcjIktvDCgXz0bgtx94EQzHEndsizZjMX2OA=="],
@@ -930,6 +991,8 @@
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
+ "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
+
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
"pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="],
@@ -994,6 +1057,8 @@
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
+ "reselect": ["reselect@5.1.1", "", {}, "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="],
+
"resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="],
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
@@ -1004,6 +1069,8 @@
"retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="],
+ "rettime": ["rettime@0.10.1", "", {}, "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw=="],
+
"rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
"roarr": ["roarr@2.15.4", "", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="],
@@ -1052,8 +1119,12 @@
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
+ "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
+
"std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
+ "strict-event-emitter": ["strict-event-emitter@0.5.1", "", {}, "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ=="],
+
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
@@ -1074,6 +1145,12 @@
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+ "tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],
+
+ "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
+
+ "tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="],
+
"tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="],
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
@@ -1096,8 +1173,14 @@
"tinyspy": ["tinyspy@4.0.4", "", {}, "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q=="],
+ "tldts": ["tldts@7.0.23", "", { "dependencies": { "tldts-core": "^7.0.23" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw=="],
+
+ "tldts-core": ["tldts-core@7.0.23", "", {}, "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ=="],
+
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
+ "tough-cookie": ["tough-cookie@6.0.0", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w=="],
+
"tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="],
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
@@ -1124,7 +1207,7 @@
"turbo-windows-arm64": ["turbo-windows-arm64@2.8.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-afTUGKBRmOJU1smQSBnFGcbq0iabAPwh1uXu2BVk7BREg30/1gMnJh9DFEQTah+UD3n3ru8V55J83RQNFfqoyw=="],
- "type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
+ "type-fest": ["type-fest@5.4.4", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw=="],
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
@@ -1154,8 +1237,12 @@
"unixify": ["unixify@1.0.0", "", { "dependencies": { "normalize-path": "^2.1.1" } }, "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg=="],
+ "until-async": ["until-async@3.0.2", "", {}, "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw=="],
+
"update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
+ "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
+
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
@@ -1192,6 +1279,8 @@
"yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="],
+ "yoctocolors-cjs": ["yoctocolors-cjs@2.1.3", "", {}, "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw=="],
+
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
@@ -1208,6 +1297,10 @@
"@electron/get/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+ "@inquirer/core/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
+
+ "@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
+
"@tailwindcss/node/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
@@ -1254,6 +1347,8 @@
"rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
+ "serialize-error/type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
+
"ssri/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
"vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],