chore: downgrade @lucide/svelte version and remove custom chat width component

This commit is contained in:
Imad Saddik 2026-03-15 16:43:18 +00:00
parent c55533a706
commit 89647d5daf
16 changed files with 2 additions and 489 deletions

View File

@ -28,7 +28,7 @@
"@eslint/compat": "^1.2.5",
"@eslint/js": "^9.18.0",
"@internationalized/date": "^3.10.1",
"@lucide/svelte": "^0.561.0",
"@lucide/svelte": "^0.515.0",
"@playwright/test": "^1.49.1",
"@storybook/addon-a11y": "^10.2.4",
"@storybook/addon-docs": "^10.2.4",

View File

@ -27,7 +27,7 @@
"@eslint/compat": "^1.2.5",
"@eslint/js": "^9.18.0",
"@internationalized/date": "^3.10.1",
"@lucide/svelte": "^0.561.0",
"@lucide/svelte": "^0.515.0",
"@playwright/test": "^1.49.1",
"@storybook/addon-a11y": "^10.2.4",
"@storybook/addon-docs": "^10.2.4",

View File

@ -1,178 +0,0 @@
<script lang="ts">
import { Check, ChevronsUpDown } from '@lucide/svelte';
import * as Command from '$lib/components/ui/command';
import * as Popover from '$lib/components/ui/popover';
import { Button } from '$lib/components/ui/button';
import { Input } from '$lib/components/ui/input';
import { cn } from '$lib/components/ui/utils';
import { tick } from 'svelte';
import {
CUSTOM_WIDTH_PRESETS,
MIN_CUSTOM_WIDTH,
MAX_CUSTOM_WIDTH
} from '$lib/constants/chat-width';
interface Props {
value: string;
onChange: (value: string) => void;
disabled?: boolean;
}
let { value = $bindable(''), onChange, disabled = false }: Props = $props();
let open = $state(false);
let isEditing = $state(false);
let inputValue = $state('');
let isError = $state(false);
let triggerRef = $state<HTMLButtonElement>(null!);
let inputRef = $state<HTMLInputElement>(null!);
const presets = Object.entries(CUSTOM_WIDTH_PRESETS).map(([key, pixelValue]) => ({
value: key,
label: `${key} (${pixelValue}px)`
}));
const displayLabel = $derived.by(() => {
if (isEditing) return 'Set pixel value';
const foundPreset = presets.find((p) => p.value === value);
if (foundPreset) return foundPreset.label;
const number = Number(value);
if (!isNaN(number) && number > 0) {
return `Custom (${number}px)`;
}
return 'Select width...';
});
function closePopover() {
open = false;
tick().then(() => triggerRef?.focus());
}
function selectPreset(newValue: string) {
value = newValue;
isEditing = false;
isError = false;
onChange(newValue);
closePopover();
}
function startEditing() {
open = false;
isEditing = true;
inputValue = '';
isError = false;
tick().then(() => inputRef?.focus());
}
function cancelEditing() {
isEditing = false;
inputValue = '';
isError = false;
}
function submitCustomValue() {
if (!inputValue) {
isError = true;
return;
}
const number = Number(inputValue);
const isValid = !isNaN(number) && number >= MIN_CUSTOM_WIDTH && number <= MAX_CUSTOM_WIDTH;
if (isValid) {
value = String(number);
onChange(String(number));
isEditing = false;
isError = false;
} else {
isError = true;
}
}
function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Enter') {
e.preventDefault();
submitCustomValue();
}
}
</script>
<div class="flex w-full flex-col gap-2">
<Popover.Root bind:open>
<Popover.Trigger bind:ref={triggerRef}>
{#snippet child({ props })}
<Button
{...props}
variant="outline"
class="w-full justify-between font-normal"
role="combobox"
aria-expanded={open}
{disabled}
>
{displayLabel}
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
{/snippet}
</Popover.Trigger>
<Popover.Content class="z-[1000000] w-[var(--bits-popover-anchor-width)] p-0">
<Command.Root>
<Command.Input placeholder="Search presets" />
<Command.List>
<Command.Empty>No presets found.</Command.Empty>
<Command.Group>
<Command.Item value="custom-input-trigger" onSelect={startEditing}>
<Check class={cn('mr-2 h-4 w-4', isEditing ? 'opacity-100' : 'opacity-0')} />
Set pixel value
</Command.Item>
<Command.Separator class="my-1" />
{#each presets as preset (preset.value)}
<Command.Item value={preset.value} onSelect={() => selectPreset(preset.value)}>
<Check
class={cn(
'mr-2 h-4 w-4',
value === preset.value && !isEditing ? 'opacity-100' : 'opacity-0'
)}
/>
{preset.label}
</Command.Item>
{/each}
</Command.Group>
</Command.List>
</Command.Root>
</Popover.Content>
</Popover.Root>
{#if isEditing}
<div class="flex animate-in items-start gap-2 duration-200 fade-in slide-in-from-top-1">
<div class="flex-1 space-y-1">
<Input
bind:ref={inputRef}
bind:value={inputValue}
onkeydown={handleKeydown}
type="number"
placeholder="e.g. 800"
class={cn(isError && 'border-destructive focus-visible:ring-destructive')}
min={MIN_CUSTOM_WIDTH}
max={MAX_CUSTOM_WIDTH}
/>
<p class={cn('text-[0.8rem]', isError ? 'text-destructive' : 'text-muted-foreground')}>
Enter a value between {MIN_CUSTOM_WIDTH} and {MAX_CUSTOM_WIDTH}.
</p>
</div>
<div class="flex gap-2">
<Button size="sm" onclick={submitCustomValue}>Save</Button>
<Button size="sm" variant="outline" onclick={cancelEditing}>Cancel</Button>
</div>
</div>
{/if}
</div>

View File

@ -9,7 +9,6 @@
import { SettingsFieldType } from '$lib/enums/settings';
import { settingsStore } from '$lib/stores/settings.svelte';
import { ChatSettingsParameterSourceIndicator } from '$lib/components/app';
import ChatSettingsComboboxCustomWidth from './ChatSettingsComboboxCustomWidth.svelte';
import type { Component } from 'svelte';
interface Props {
@ -224,35 +223,6 @@
{field.help || SETTING_CONFIG_INFO[field.key]}
</p>
{/if}
{:else if field.type === SettingsFieldType.COMBOBOX}
{#if field.key === SETTINGS_KEYS.CUSTOM_CHAT_WIDTH}
{@const isDisabled = localConfig.autoChatWidth}
<div class="space-y-2">
<Label
for={field.key}
class="text-sm font-medium {isDisabled ? 'text-muted-foreground' : ''}"
>
{field.label}
</Label>
<div class="w-full md:max-w-md">
<ChatSettingsComboboxCustomWidth
bind:value={localConfig[field.key]}
onChange={(value) => onConfigChange(field.key, value)}
disabled={isDisabled}
/>
</div>
{#if isDisabled}
<p class="text-xs text-muted-foreground">Disabled when automatic width is enabled.</p>
{:else if field.help || SETTING_CONFIG_INFO[field.key]}
<p class="text-xs text-muted-foreground">
{field.help || SETTING_CONFIG_INFO[field.key]}
</p>
{/if}
</div>
{/if}
{:else if field.type === SettingsFieldType.CHECKBOX}
<div class="flex items-start space-x-3">
<Checkbox

View File

@ -1,40 +0,0 @@
<script lang="ts">
import type { Command as CommandPrimitive, Dialog as DialogPrimitive } from 'bits-ui';
import type { Snippet } from 'svelte';
import Command from './command.svelte';
import * as Dialog from '$lib/components/ui/dialog/index.js';
import type { WithoutChildrenOrChild } from '$lib/components/ui/utils.js';
let {
open = $bindable(false),
ref = $bindable(null),
value = $bindable(''),
title = 'Command Palette',
description = 'Search for a command to run',
portalProps,
children,
...restProps
}: WithoutChildrenOrChild<DialogPrimitive.RootProps> &
WithoutChildrenOrChild<CommandPrimitive.RootProps> & {
portalProps?: DialogPrimitive.PortalProps;
children: Snippet;
title?: string;
description?: string;
} = $props();
</script>
<Dialog.Root bind:open {...restProps}>
<Dialog.Header class="sr-only">
<Dialog.Title>{title}</Dialog.Title>
<Dialog.Description>{description}</Dialog.Description>
</Dialog.Header>
<Dialog.Content class="overflow-hidden p-0" {portalProps}>
<Command
class="**:data-[slot=command-input-wrapper]:h-12 [&_[data-command-group]]:px-2 [&_[data-command-group]:not([hidden])_~[data-command-group]]:pt-0 [&_[data-command-input-wrapper]_svg]:h-5 [&_[data-command-input-wrapper]_svg]:w-5 [&_[data-command-input]]:h-12 [&_[data-command-item]]:px-2 [&_[data-command-item]]:py-3 [&_[data-command-item]_svg]:h-5 [&_[data-command-item]_svg]:w-5"
{...restProps}
bind:value
bind:ref
{children}
/>
</Dialog.Content>
</Dialog.Root>

View File

@ -1,17 +0,0 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import { cn } from '$lib/components/ui/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: CommandPrimitive.EmptyProps = $props();
</script>
<CommandPrimitive.Empty
bind:ref
data-slot="command-empty"
class={cn('py-6 text-center text-sm', className)}
{...restProps}
/>

View File

@ -1,30 +0,0 @@
<script lang="ts">
import { Command as CommandPrimitive, useId } from 'bits-ui';
import { cn } from '$lib/components/ui/utils.js';
let {
ref = $bindable(null),
class: className,
children,
heading,
value,
...restProps
}: CommandPrimitive.GroupProps & {
heading?: string;
} = $props();
</script>
<CommandPrimitive.Group
bind:ref
data-slot="command-group"
class={cn('overflow-hidden p-1 text-foreground', className)}
value={value ?? heading ?? `----${useId()}`}
{...restProps}
>
{#if heading}
<CommandPrimitive.GroupHeading class="px-2 py-1.5 text-xs font-medium text-muted-foreground">
{heading}
</CommandPrimitive.GroupHeading>
{/if}
<CommandPrimitive.GroupItems {children} />
</CommandPrimitive.Group>

View File

@ -1,26 +0,0 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import SearchIcon from '@lucide/svelte/icons/search';
import { cn } from '$lib/components/ui/utils.js';
let {
ref = $bindable(null),
class: className,
value = $bindable(''),
...restProps
}: CommandPrimitive.InputProps = $props();
</script>
<div class="flex h-9 items-center gap-2 border-b ps-3 pe-8" data-slot="command-input-wrapper">
<SearchIcon class="size-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
data-slot="command-input"
class={cn(
'flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
className
)}
bind:ref
{...restProps}
bind:value
/>
</div>

View File

@ -1,20 +0,0 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import { cn } from '$lib/components/ui/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: CommandPrimitive.ItemProps = $props();
</script>
<CommandPrimitive.Item
bind:ref
data-slot="command-item"
class={cn(
"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none aria-selected:bg-accent aria-selected: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 [&_svg:not([class*='text-'])]:text-muted-foreground",
className
)}
{...restProps}
/>

View File

@ -1,20 +0,0 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import { cn } from '$lib/components/ui/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: CommandPrimitive.LinkItemProps = $props();
</script>
<CommandPrimitive.LinkItem
bind:ref
data-slot="command-item"
class={cn(
"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
className
)}
{...restProps}
/>

View File

@ -1,17 +0,0 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import { cn } from '$lib/components/ui/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: CommandPrimitive.ListProps = $props();
</script>
<CommandPrimitive.List
bind:ref
data-slot="command-list"
class={cn('max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto', className)}
{...restProps}
/>

View File

@ -1,7 +0,0 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
let { ref = $bindable(null), ...restProps }: CommandPrimitive.LoadingProps = $props();
</script>
<CommandPrimitive.Loading bind:ref {...restProps} />

View File

@ -1,17 +0,0 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import { cn } from '$lib/components/ui/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: CommandPrimitive.SeparatorProps = $props();
</script>
<CommandPrimitive.Separator
bind:ref
data-slot="command-separator"
class={cn('-mx-1 h-px bg-border', className)}
{...restProps}
/>

View File

@ -1,20 +0,0 @@
<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<HTMLSpanElement>> = $props();
</script>
<span
bind:this={ref}
data-slot="command-shortcut"
class={cn('ms-auto text-xs tracking-widest text-muted-foreground', className)}
{...restProps}
>
{@render children?.()}
</span>

View File

@ -1,28 +0,0 @@
<script lang="ts">
import { cn } from '$lib/components/ui/utils.js';
import { Command as CommandPrimitive } from 'bits-ui';
export type CommandRootApi = CommandPrimitive.Root;
let {
api = $bindable(null),
ref = $bindable(null),
value = $bindable(''),
class: className,
...restProps
}: CommandPrimitive.RootProps & {
api?: CommandRootApi | null;
} = $props();
</script>
<CommandPrimitive.Root
bind:this={api}
bind:value
bind:ref
data-slot="command"
class={cn(
'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
className
)}
{...restProps}
/>

View File

@ -1,37 +0,0 @@
import Root from './command.svelte';
import Loading from './command-loading.svelte';
import Dialog from './command-dialog.svelte';
import Empty from './command-empty.svelte';
import Group from './command-group.svelte';
import Item from './command-item.svelte';
import Input from './command-input.svelte';
import List from './command-list.svelte';
import Separator from './command-separator.svelte';
import Shortcut from './command-shortcut.svelte';
import LinkItem from './command-link-item.svelte';
export {
Root,
Dialog,
Empty,
Group,
Item,
LinkItem,
Input,
List,
Separator,
Shortcut,
Loading,
//
Root as Command,
Dialog as CommandDialog,
Empty as CommandEmpty,
Group as CommandGroup,
Item as CommandItem,
LinkItem as CommandLinkItem,
Input as CommandInput,
List as CommandList,
Separator as CommandSeparator,
Shortcut as CommandShortcut,
Loading as CommandLoading
};