diff --git a/frontend/package.json b/frontend/package.json
index 8d4695d1..c7845ba2 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -20,7 +20,6 @@
"@codemirror/lint": "^6.8.5",
"@codemirror/view": "^6.38.1",
"@dnd-kit/core": "^6.3.1",
- "@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@ebay/nice-modal-react": "^1.2.13",
"@git-diff-view/file": "^0.0.30",
@@ -31,26 +30,20 @@
"@lexical/markdown": "^0.36.2",
"@lexical/react": "^0.36.2",
"@lexical/rich-text": "^0.36.2",
- "@lexical/utils": "^0.36.2",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.0.3",
- "@radix-ui/react-tabs": "^1.1.12",
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.7",
"@rjsf/shadcn": "6.1.1",
"@sentry/react": "^9.34.0",
"@sentry/vite-plugin": "^3.5.0",
- "@tailwindcss/typography": "^0.5.16",
"@tanstack/electric-db-collection": "^0.2.6",
"@tanstack/react-db": "^0.1.50",
- "@tanstack/react-devtools": "^0.8.0",
"@tanstack/react-form": "^1.23.8",
- "@tanstack/react-form-devtools": "^0.1.8",
"@tanstack/react-query": "^5.85.5",
- "@types/react-window": "^1.8.8",
"@uiw/react-codemirror": "^4.25.1",
"@virtuoso.dev/message-list": "^1.13.3",
"class-variance-authority": "^0.7.0",
@@ -72,16 +65,13 @@
"react-i18next": "^15.7.3",
"react-resizable-panels": "^3.0.6",
"react-router-dom": "^6.8.1",
- "react-use-websocket": "^4.7.0",
"react-virtuoso": "^4.14.0",
- "react-window": "^1.8.11",
"rfc6902": "^5.1.2",
"simple-icons": "^15.16.0",
"tailwind-merge": "^2.2.0",
"tailwindcss-animate": "^1.0.7",
"vibe-kanban-web-companion": "^0.0.4",
"wa-sqlite": "^1.0.0",
- "zod": "^4.1.12",
"zustand": "^4.5.4"
},
"devDependencies": {
diff --git a/frontend/src/components/OrgMemberAvatars.tsx b/frontend/src/components/OrgMemberAvatars.tsx
deleted file mode 100644
index bef62a68..00000000
--- a/frontend/src/components/OrgMemberAvatars.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import { useOrganizationMembers } from '@/hooks/useOrganizationMembers';
-import { UserAvatar } from '@/components/tasks/UserAvatar';
-import { useTranslation } from 'react-i18next';
-
-interface OrgMemberAvatarsProps {
- limit?: number;
- className?: string;
- organizationId?: string;
-}
-
-export function OrgMemberAvatars({
- limit = 5,
- className = '',
- organizationId,
-}: OrgMemberAvatarsProps) {
- const { t } = useTranslation('common');
- const { data: members, isPending } = useOrganizationMembers(organizationId);
-
- if (!organizationId || isPending || !members || members.length === 0) {
- return null;
- }
-
- const displayMembers = members.slice(0, limit);
- const remainingCount = members.length - limit;
-
- return (
-
-
- {displayMembers.map((member) => (
-
- ))}
-
- {remainingCount > 0 && (
-
- {t('orgMembers.moreCount', { count: remainingCount })}
-
- )}
-
- );
-}
diff --git a/frontend/src/components/layout/ResponsiveTwoPane.tsx b/frontend/src/components/layout/ResponsiveTwoPane.tsx
deleted file mode 100644
index 365abd00..00000000
--- a/frontend/src/components/layout/ResponsiveTwoPane.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import React from 'react';
-
-interface ResponsiveTwoPaneProps {
- left: React.ReactNode;
- right: React.ReactNode;
- isRightOpen: boolean;
- variant?: 'sidebar' | 'split';
-}
-
-export function ResponsiveTwoPane({
- left,
- right,
- isRightOpen,
- variant = 'sidebar',
-}: ResponsiveTwoPaneProps) {
- if (variant === 'split') {
- return (
-
- );
- }
-
- return (
-
-
{left}
-
- {isRightOpen && (
-
- )}
-
-
-
- );
-}
-
-export default ResponsiveTwoPane;
diff --git a/frontend/src/components/tasks/FollowUpStatusRow.tsx b/frontend/src/components/tasks/FollowUpStatusRow.tsx
deleted file mode 100644
index 082fa650..00000000
--- a/frontend/src/components/tasks/FollowUpStatusRow.tsx
+++ /dev/null
@@ -1,126 +0,0 @@
-import { memo, useEffect, useRef, useState } from 'react';
-import { CheckCircle2, Clock, Loader2, Send, WifiOff } from 'lucide-react';
-import { cn } from '@/lib/utils';
-
-export type SaveStatus = 'idle' | 'saving' | 'saved' | 'offline' | 'sent';
-
-type Status = {
- save: { state: SaveStatus; isSaving: boolean };
- draft: { isLoaded: boolean; isSending: boolean };
- queue: { isUnqueuing: boolean; isQueued: boolean };
-};
-
-type Props = { status: Status; pillBgClass?: string };
-
-function FollowUpStatusRowImpl({ status, pillBgClass = 'bg-muted' }: Props) {
- const { save, draft, queue } = status;
-
- // Nonce keys to retrigger CSS animation; no JS timers.
- const [savedNonce, setSavedNonce] = useState(null);
- const [sentNonce, setSentNonce] = useState(null);
- const prevIsSendingRef = useRef(draft.isSending);
-
- // Show "Draft saved" by bumping key to restart CSS animation
- useEffect(() => {
- if (save.state === 'saved') setSavedNonce(Date.now());
- }, [save.state]);
-
- // Show "Follow-up sent" on isSending rising edge
- useEffect(() => {
- const now = draft.isSending;
- if (now && !prevIsSendingRef.current) {
- setSentNonce(Date.now());
- }
- prevIsSendingRef.current = now;
- }, [draft.isSending]);
- return (
-
-
- {save.state === 'saving' && save.isSaving ? (
-
- Saving…
-
- ) : save.state === 'offline' ? (
-
- Offline — changes pending
-
- ) : sentNonce ? (
- setSentNonce(null)}
- >
- Follow-up sent
-
- ) : savedNonce ? (
- setSavedNonce(null)}
- >
- Draft saved
-
- ) : null}
-
-
- {queue.isUnqueuing ? (
-
- Unlocking…
-
- ) : !draft.isLoaded ? (
-
- Loading draft…
-
- ) : draft.isSending ? (
-
- Sending follow-up…
-
- ) : queue.isQueued ? (
-
- Queued for next turn. Edits are
- locked.
-
- ) : null}
-
-
- );
-}
-
-export const FollowUpStatusRow = memo(FollowUpStatusRowImpl);
diff --git a/frontend/src/components/tasks/TaskRelationshipCard.tsx b/frontend/src/components/tasks/TaskRelationshipCard.tsx
deleted file mode 100644
index 471e5c06..00000000
--- a/frontend/src/components/tasks/TaskRelationshipCard.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-import { Card } from '@/components/ui/card';
-import { Badge } from '@/components/ui/badge';
-import { cn } from '@/lib/utils';
-import type { Task } from 'shared/types';
-
-interface TaskRelationshipCardProps {
- task: Task;
- isCurrentTask?: boolean;
- onClick?: () => void;
- className?: string;
-}
-
-export function TaskRelationshipCard({
- task,
- isCurrentTask = false,
- onClick,
- className,
-}: TaskRelationshipCardProps) {
- const getStatusBadgeVariant = (status: string) => {
- switch (status) {
- case 'todo':
- return 'secondary';
- case 'inprogress':
- return 'default';
- case 'inreview':
- return 'outline';
- case 'done':
- return 'default';
- case 'cancelled':
- return 'destructive';
- default:
- return 'secondary';
- }
- };
-
- const truncateTitle = (title: string, maxLength: number = 50) => {
- return title.length > maxLength
- ? `${title.substring(0, maxLength)}...`
- : title;
- };
-
- const truncateDescription = (
- description: string | null,
- maxLength: number = 120
- ) => {
- if (!description) return null;
- return description.length > maxLength
- ? `${description.substring(0, maxLength)}...`
- : description;
- };
-
- return (
-
-
- {/* Title and Status Row */}
-
-
- {truncateTitle(task.title)}
-
-
-
- {task.status}
-
-
-
-
- {/* Description */}
- {task.description && (
-
- {truncateDescription(task.description)}
-
- )}
-
- {/* Current task indicator */}
- {isCurrentTask && (
-
- )}
-
-
- );
-}
diff --git a/frontend/src/components/tasks/TaskRelationshipViewer.tsx b/frontend/src/components/tasks/TaskRelationshipViewer.tsx
deleted file mode 100644
index a31e6304..00000000
--- a/frontend/src/components/tasks/TaskRelationshipViewer.tsx
+++ /dev/null
@@ -1,169 +0,0 @@
-import { useEffect, useState } from 'react';
-import { Card } from '@/components/ui/card';
-import { TaskRelationshipCard } from './TaskRelationshipCard';
-import { attemptsApi } from '@/lib/api';
-import type {
- TaskAttempt,
- TaskRelationships,
- TaskWithAttemptStatus,
-} from 'shared/types';
-import { ChevronDown, ChevronRight } from 'lucide-react';
-
-interface TaskRelationshipViewerProps {
- selectedAttempt: TaskAttempt | null;
- onNavigateToTask?: (taskId: string) => void;
- task?: TaskWithAttemptStatus | null;
- tasksById?: Record;
-}
-
-export function TaskRelationshipViewer({
- selectedAttempt,
- onNavigateToTask,
- task,
- tasksById,
-}: TaskRelationshipViewerProps) {
- const [relationships, setRelationships] = useState(
- null
- );
- const [parentTask, setParentTask] = useState(
- null
- );
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState(null);
- const [childrenExpanded, setChildrenExpanded] = useState(true);
-
- // Effect for attempt-based relationships (existing behavior)
- useEffect(() => {
- if (!selectedAttempt?.id) {
- setRelationships(null);
- return;
- }
-
- const fetchRelationships = async () => {
- setLoading(true);
- setError(null);
- try {
- const relationshipData = await attemptsApi.getChildren(
- selectedAttempt.id
- );
- setRelationships(relationshipData);
- } catch (err) {
- console.error('Failed to fetch task relationships:', err);
- setError('Failed to load task relationships');
- } finally {
- setLoading(false);
- }
- };
-
- fetchRelationships();
- }, [selectedAttempt?.id]);
-
- // Effect for parent task when child has no attempts (one request + tasksById lookup)
- useEffect(() => {
- if (selectedAttempt?.id) {
- // If we have an attempt, clear parent task since relationships will handle it
- setParentTask(null);
- return;
- }
-
- if (task?.parent_task_attempt && tasksById) {
- attemptsApi
- .get(task.parent_task_attempt)
- .then((parentAttempt) => {
- // Use existing tasksById instead of second API call
- const parentTaskData = tasksById[parentAttempt.task_id];
- setParentTask(parentTaskData || null);
- })
- .catch(() => setParentTask(null));
- } else {
- setParentTask(null);
- }
- }, [selectedAttempt?.id, task?.parent_task_attempt, tasksById]);
-
- const displayParentTask = relationships?.parent_task || parentTask;
- const childTasks = relationships?.children || [];
- const hasParent = displayParentTask !== null;
- const hasChildren = childTasks.length > 0;
-
- // Don't render if no relationships and no current task
- if (!hasParent && !hasChildren && !loading && !error) {
- return null;
- }
-
- return (
-
-
- Task Relationships
-
-
- {loading ? (
-
- Loading relationships...
-
- ) : error ? (
-
- {error}
-
- ) : (
-
- {/* Parent Task Section */}
- {hasParent && displayParentTask && (
-
-
-
-
- onNavigateToTask?.(displayParentTask.id)}
- className="shadow-sm"
- />
-
-
-
- )}
-
- {/* Child Tasks Section */}
- {hasChildren && (
-
-
-
-
-
-
- {childrenExpanded && (
-
- {childTasks.map((childTask) => (
- onNavigateToTask?.(childTask.id)}
- className="shadow-sm hover:shadow-md transition-shadow"
- />
- ))}
-
- )}
-
- )}
-
- )}
-
-
- );
-}
diff --git a/frontend/src/components/ui/image-upload-section.tsx b/frontend/src/components/ui/image-upload-section.tsx
deleted file mode 100644
index 1c613e93..00000000
--- a/frontend/src/components/ui/image-upload-section.tsx
+++ /dev/null
@@ -1,352 +0,0 @@
-import {
- useState,
- useCallback,
- useRef,
- useImperativeHandle,
- useEffect,
- forwardRef,
-} from 'react';
-import {
- X,
- Image as ImageIcon,
- Upload,
- ChevronRight,
- AlertCircle,
-} from 'lucide-react';
-import { Button } from './button';
-import { Alert, AlertDescription } from './alert';
-import { cn, formatFileSize } from '@/lib/utils';
-import { imagesApi } from '@/lib/api';
-import type { ImageResponse } from 'shared/types';
-
-interface ImageUploadSectionProps {
- images: ImageResponse[];
- onImagesChange: (images: ImageResponse[]) => void;
- onUpload: (file: File) => Promise;
- onDelete?: (imageId: string) => Promise;
- onImageUploaded?: (image: ImageResponse) => void; // Custom callback for upload success
- isUploading?: boolean;
- disabled?: boolean;
- readOnly?: boolean;
- collapsible?: boolean;
- defaultExpanded?: boolean;
- hideDropZone?: boolean; // Hide the drag and drop area
- className?: string;
-}
-
-export interface ImageUploadSectionHandle {
- addFiles: (files: FileList | File[] | null) => Promise;
-}
-
-const MAX_SIZE_BYTES = 20 * 1024 * 1024; // 20MB
-const VALID_TYPES = [
- 'image/png',
- 'image/jpeg',
- 'image/jpg',
- 'image/gif',
- 'image/webp',
- 'image/bmp',
- 'image/svg+xml',
-];
-
-export const ImageUploadSection = forwardRef<
- ImageUploadSectionHandle,
- ImageUploadSectionProps
->(
- (
- {
- images,
- onImagesChange,
- onUpload,
- onDelete,
- onImageUploaded,
- isUploading = false,
- disabled = false,
- readOnly = false,
- collapsible = true,
- defaultExpanded = false,
- hideDropZone = false,
- className,
- },
- ref
- ) => {
- const [isExpanded, setIsExpanded] = useState(
- defaultExpanded || images.length > 0
- );
- const [isDragging, setIsDragging] = useState(false);
- const [uploadingFiles, setUploadingFiles] = useState>(
- new Set()
- );
- const [errorMessage, setErrorMessage] = useState(null);
- const fileInputRef = useRef(null);
- const latestImagesRef = useRef(images);
-
- useEffect(() => {
- latestImagesRef.current = images;
- }, [images]);
-
- useEffect(() => {
- if (collapsible && images.length > 0 && !isExpanded) {
- setIsExpanded(true);
- }
- }, [collapsible, images.length, isExpanded]);
-
- const handleFiles = useCallback(
- async (filesInput: FileList | File[] | null) => {
- if (!filesInput || disabled || readOnly) return;
-
- const files = Array.isArray(filesInput)
- ? filesInput
- : Array.from(filesInput);
-
- setErrorMessage(null);
-
- const invalidFiles: string[] = [];
- const oversizedFiles: string[] = [];
- const validFiles: File[] = [];
-
- files.forEach((file) => {
- if (!VALID_TYPES.includes(file.type.toLowerCase())) {
- invalidFiles.push(file.name);
- return;
- }
-
- if (file.size > MAX_SIZE_BYTES) {
- oversizedFiles.push(
- `${file.name} (${(file.size / 1048576).toFixed(1)} MB)`
- );
- return;
- }
-
- validFiles.push(file);
- });
-
- if (invalidFiles.length > 0 || oversizedFiles.length > 0) {
- const errors: string[] = [];
- if (invalidFiles.length > 0) {
- errors.push(`Unsupported file type: ${invalidFiles.join(', ')}`);
- }
- if (oversizedFiles.length > 0) {
- errors.push(
- `Files too large (max 20 MB): ${oversizedFiles.join(', ')}`
- );
- }
- setErrorMessage(errors.join('. '));
- }
-
- for (const file of validFiles) {
- const tempId = `uploading-${Date.now()}-${file.name}`;
- setUploadingFiles((prev) => new Set(prev).add(tempId));
-
- try {
- const uploadedImage = await onUpload(file);
-
- // Call custom upload callback if provided, otherwise use default behavior
- if (onImageUploaded) {
- onImageUploaded(uploadedImage);
- } else {
- const nextImages = [...latestImagesRef.current, uploadedImage];
- latestImagesRef.current = nextImages;
- onImagesChange(nextImages);
- }
-
- setErrorMessage(null);
- } catch (error: unknown) {
- console.error('Failed to upload image:', error);
- const message =
- error instanceof Error
- ? error.message
- : 'Failed to upload image. Please try again.';
- setErrorMessage(message);
- } finally {
- setUploadingFiles((prev) => {
- const next = new Set(prev);
- next.delete(tempId);
- return next;
- });
- }
- }
- },
- [disabled, readOnly, onUpload, onImageUploaded, onImagesChange]
- );
-
- useImperativeHandle(
- ref,
- () => ({
- addFiles: async (files: FileList | File[] | null) => {
- await handleFiles(files);
- },
- }),
- [handleFiles]
- );
-
- const handleDrop = useCallback(
- (e: React.DragEvent) => {
- e.preventDefault();
- setIsDragging(false);
- void handleFiles(e.dataTransfer.files);
- },
- [handleFiles]
- );
-
- const handleDragOver = useCallback((e: React.DragEvent) => {
- e.preventDefault();
- setIsDragging(true);
- }, []);
-
- const handleDragLeave = useCallback((e: React.DragEvent) => {
- e.preventDefault();
- setIsDragging(false);
- }, []);
-
- const handleRemoveImage = useCallback(
- async (imageId: string) => {
- if (onDelete) {
- try {
- await onDelete(imageId);
- } catch (error) {
- console.error('Failed to delete image:', error);
- }
- }
- onImagesChange(images.filter((img) => img.id !== imageId));
- },
- [images, onImagesChange, onDelete]
- );
-
- const content = (
-
- {/* Error message */}
- {errorMessage && (
-
-
- {errorMessage}
-
- )}
-
- {/* Read-only message */}
- {readOnly && images.length === 0 && (
-
No images attached
- )}
-
- {/* Drop zone - only show when not read-only and not hidden */}
- {!readOnly && !hideDropZone && (
-
-
-
- Drag and drop images here, or click to select
-
-
-
{
- void handleFiles(e.target.files);
- }}
- disabled={disabled}
- />
-
- )}
-
- {/* Image previews */}
- {images.length > 0 && (
-
- {images.map((image) => (
-
-
-
})
-
-
- {image.original_name}
-
-
- {formatFileSize(image.size_bytes)}
-
-
-
- {!disabled && !readOnly && (
-
- )}
-
- ))}
-
- )}
-
- {/* Uploading indicators */}
- {uploadingFiles.size > 0 && (
-
- {Array.from(uploadingFiles).map((tempId) => (
-
- ))}
-
- )}
-
- );
-
- if (!collapsible) {
- return content;
- }
-
- return (
-
-
- {isExpanded && content}
-
- );
- }
-);
-
-ImageUploadSection.displayName = 'ImageUploadSection';
diff --git a/frontend/src/components/ui/tabs.tsx b/frontend/src/components/ui/tabs.tsx
deleted file mode 100644
index 4a2b37f9..00000000
--- a/frontend/src/components/ui/tabs.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import * as React from 'react';
-import * as TabsPrimitive from '@radix-ui/react-tabs';
-
-import { cn } from '@/lib/utils';
-
-const Tabs = TabsPrimitive.Root;
-
-const TabsList = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-));
-TabsList.displayName = TabsPrimitive.List.displayName;
-
-const TabsTrigger = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-));
-TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
-
-const TabsContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-));
-TabsContent.displayName = TabsPrimitive.Content.displayName;
-
-export { Tabs, TabsList, TabsTrigger, TabsContent };
diff --git a/frontend/src/components/ui/title-description-editor.tsx b/frontend/src/components/ui/title-description-editor.tsx
deleted file mode 100644
index 338d3f0e..00000000
--- a/frontend/src/components/ui/title-description-editor.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import { Input } from './input';
-import WYSIWYGEditor from './wysiwyg';
-
-type Props = {
- title: string;
- description: string | null | undefined;
- onTitleChange: (v: string) => void;
- onDescriptionChange: (v: string) => void;
- projectId?: string;
-};
-
-const TitleDescriptionEditor = ({
- title,
- description,
- onTitleChange,
- onDescriptionChange,
- projectId,
-}: Props) => {
- return (
-
- onTitleChange(e.target.value)}
- />
-
-
- );
-};
-
-export default TitleDescriptionEditor;
diff --git a/frontend/src/contexts/TabNavigationContext.tsx b/frontend/src/contexts/TabNavigationContext.tsx
index 4062f576..caa53859 100644
--- a/frontend/src/contexts/TabNavigationContext.tsx
+++ b/frontend/src/contexts/TabNavigationContext.tsx
@@ -1,4 +1,4 @@
-import { createContext, useContext } from 'react';
+import { createContext } from 'react';
import type { TabType } from '@/types/tabs';
interface TabNavContextType {
@@ -7,11 +7,3 @@ interface TabNavContextType {
}
export const TabNavContext = createContext(null);
-
-export const useTabNavigation = () => {
- const context = useContext(TabNavContext);
- if (!context) {
- throw new Error('useTabNavigation must be used within TabNavContext');
- }
- return context;
-};
diff --git a/frontend/src/lib/caretPosition.ts b/frontend/src/lib/caretPosition.ts
deleted file mode 100644
index 0da92429..00000000
--- a/frontend/src/lib/caretPosition.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-const CARET_PROBE_CHARACTER = '\u200b';
-
-const mirrorStyleProperties = [
- 'boxSizing',
- 'fontFamily',
- 'fontSize',
- 'fontStyle',
- 'fontWeight',
- 'letterSpacing',
- 'lineHeight',
- 'paddingTop',
- 'paddingRight',
- 'paddingBottom',
- 'paddingLeft',
- 'textAlign',
- 'textTransform',
- 'borderTopWidth',
- 'borderRightWidth',
- 'borderBottomWidth',
- 'borderLeftWidth',
- 'borderTopStyle',
- 'borderRightStyle',
- 'borderBottomStyle',
- 'borderLeftStyle',
-] as const;
-
-type MirrorStyleProperty = (typeof mirrorStyleProperties)[number];
-
-export const getCaretClientRect = (
- textarea: HTMLTextAreaElement,
- targetIndex?: number
-) => {
- if (typeof window === 'undefined') return null;
-
- const selectionIndex =
- typeof targetIndex === 'number'
- ? Math.min(Math.max(targetIndex, 0), textarea.value.length)
- : (textarea.selectionEnd ?? textarea.value.length);
-
- const textBeforeCaret = textarea.value.slice(0, selectionIndex);
- const textareaRect = textarea.getBoundingClientRect();
- const computedStyle = window.getComputedStyle(textarea);
-
- const mirror = document.createElement('div');
- mirror.setAttribute('data-caret-mirror', 'true');
- mirror.style.position = 'absolute';
- mirror.style.top = `${textareaRect.top + window.scrollY}px`;
- mirror.style.left = `${textareaRect.left + window.scrollX}px`;
- mirror.style.visibility = 'hidden';
- mirror.style.whiteSpace = 'pre-wrap';
- mirror.style.wordBreak = 'break-word';
- mirror.style.overflow = 'hidden';
- mirror.style.width = `${textareaRect.width}px`;
-
- mirrorStyleProperties.forEach((property: MirrorStyleProperty) => {
- const value = computedStyle[property];
- if (value) {
- mirror.style[property] = value;
- }
- });
-
- mirror.textContent = textBeforeCaret;
-
- const probe = document.createElement('span');
- probe.textContent = CARET_PROBE_CHARACTER;
- mirror.appendChild(probe);
-
- document.body.appendChild(mirror);
- const caretRect = probe.getBoundingClientRect();
- document.body.removeChild(mirror);
-
- return caretRect;
-};
diff --git a/frontend/src/utils/markdownImages.ts b/frontend/src/utils/markdownImages.ts
deleted file mode 100644
index f2fc3027..00000000
--- a/frontend/src/utils/markdownImages.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { ImageResponse } from 'shared/types';
-
-export function imageToMarkdown(image: ImageResponse): string {
- return ``;
-}
-
-export function appendImageMarkdown(
- prev: string,
- image: ImageResponse
-): string {
- const markdownText = imageToMarkdown(image);
- if (prev.trim() === '') return markdownText + '\n';
- const needsNewline = !prev.endsWith('\n');
- return prev + (needsNewline ? '\n' : '') + markdownText + '\n';
-}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 52f211a2..b35200dc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -32,9 +32,6 @@ importers:
'@dnd-kit/core':
specifier: ^6.3.1
version: 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@dnd-kit/modifiers':
- specifier: ^9.0.0
- version: 9.0.0(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
'@dnd-kit/utilities':
specifier: ^3.2.2
version: 3.2.2(react@18.3.1)
@@ -65,9 +62,6 @@ importers:
'@lexical/rich-text':
specifier: ^0.36.2
version: 0.36.2
- '@lexical/utils':
- specifier: ^0.36.2
- version: 0.36.2
'@radix-ui/react-dropdown-menu':
specifier: ^2.1.15
version: 2.1.15(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -83,9 +77,6 @@ importers:
'@radix-ui/react-switch':
specifier: ^1.0.3
version: 1.2.6(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@radix-ui/react-tabs':
- specifier: ^1.1.12
- version: 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-toggle-group':
specifier: ^1.1.11
version: 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -101,30 +92,18 @@ importers:
'@sentry/vite-plugin':
specifier: ^3.5.0
version: 3.5.0
- '@tailwindcss/typography':
- specifier: ^0.5.16
- version: 0.5.16(tailwindcss@3.4.17)
'@tanstack/electric-db-collection':
specifier: ^0.2.6
version: 0.2.6(typescript@5.9.2)
'@tanstack/react-db':
specifier: ^0.1.50
version: 0.1.50(react@18.3.1)(typescript@5.9.2)
- '@tanstack/react-devtools':
- specifier: ^0.8.0
- version: 0.8.0(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(solid-js@1.9.10)
'@tanstack/react-form':
specifier: ^1.23.8
version: 1.23.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@tanstack/react-form-devtools':
- specifier: ^0.1.8
- version: 0.1.8(csstype@3.1.3)(react@18.3.1)(solid-js@1.9.10)
'@tanstack/react-query':
specifier: ^5.85.5
version: 5.85.5(react@18.3.1)
- '@types/react-window':
- specifier: ^1.8.8
- version: 1.8.8
'@uiw/react-codemirror':
specifier: ^4.25.1
version: 4.25.1(@babel/runtime@7.27.6)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.2)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.38.1)(codemirror@6.0.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -188,15 +167,9 @@ importers:
react-router-dom:
specifier: ^6.8.1
version: 6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- react-use-websocket:
- specifier: ^4.7.0
- version: 4.13.0
react-virtuoso:
specifier: ^4.14.0
version: 4.14.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- react-window:
- specifier: ^1.8.11
- version: 1.8.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
rfc6902:
specifier: ^5.1.2
version: 5.1.2
@@ -215,9 +188,6 @@ importers:
wa-sqlite:
specifier: ^1.0.0
version: 1.0.0
- zod:
- specifier: ^4.1.12
- version: 4.1.12
zustand:
specifier: ^4.5.4
version: 4.5.7(@types/react@18.3.23)(react@18.3.1)
@@ -466,12 +436,6 @@ packages:
react: '>=16.8.0'
react-dom: '>=16.8.0'
- '@dnd-kit/modifiers@9.0.0':
- resolution: {integrity: sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==}
- peerDependencies:
- '@dnd-kit/core': ^6.3.0
- react: '>=16.8.0'
-
'@dnd-kit/utilities@3.2.2':
resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
peerDependencies:
@@ -1414,19 +1378,6 @@ packages:
'@types/react-dom':
optional: true
- '@radix-ui/react-tabs@1.1.12':
- resolution: {integrity: sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
'@radix-ui/react-toggle-group@1.1.11':
resolution: {integrity: sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==}
peerDependencies:
@@ -1781,36 +1732,6 @@ packages:
resolution: {integrity: sha512-jUnpTdpicG8wefamw7eNo2uO+Q3KCbOAiF76xH4gfNHSW6TN2hBfOtmLu7J+ive4c0Al3+NEHz19bIPR0lkwWg==}
engines: {node: '>= 14'}
- '@solid-primitives/event-listener@2.4.3':
- resolution: {integrity: sha512-h4VqkYFv6Gf+L7SQj+Y6puigL/5DIi7x5q07VZET7AWcS+9/G3WfIE9WheniHWJs51OEkRB43w6lDys5YeFceg==}
- peerDependencies:
- solid-js: ^1.6.12
-
- '@solid-primitives/keyboard@1.3.3':
- resolution: {integrity: sha512-9dQHTTgLBqyAI7aavtO+HnpTVJgWQA1ghBSrmLtMu1SMxLPDuLfuNr+Tk5udb4AL4Ojg7h9JrKOGEEDqsJXWJA==}
- peerDependencies:
- solid-js: ^1.6.12
-
- '@solid-primitives/resize-observer@2.1.3':
- resolution: {integrity: sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ==}
- peerDependencies:
- solid-js: ^1.6.12
-
- '@solid-primitives/rootless@1.5.2':
- resolution: {integrity: sha512-9HULb0QAzL2r47CCad0M+NKFtQ+LrGGNHZfteX/ThdGvKIg2o2GYhBooZubTCd/RTu2l2+Nw4s+dEfiDGvdrrQ==}
- peerDependencies:
- solid-js: ^1.6.12
-
- '@solid-primitives/static-store@0.1.2':
- resolution: {integrity: sha512-ReK+5O38lJ7fT+L6mUFvUr6igFwHBESZF+2Ug842s7fvlVeBdIVEdTCErygff6w7uR6+jrr7J8jQo+cYrEq4Iw==}
- peerDependencies:
- solid-js: ^1.6.12
-
- '@solid-primitives/utils@6.3.2':
- resolution: {integrity: sha512-hZ/M/qr25QOCcwDPOHtGjxTD8w2mNyVAYvcfgwzBHq2RwNqHNdDNsMZYap20+ruRwW4A3Cdkczyoz0TSxLCAPQ==}
- peerDependencies:
- solid-js: ^1.6.12
-
'@standard-schema/spec@1.0.0':
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
@@ -1819,11 +1740,6 @@ packages:
peerDependencies:
tailwindcss: '>=3.2.0'
- '@tailwindcss/typography@0.5.16':
- resolution: {integrity: sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==}
- peerDependencies:
- tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
-
'@tanstack/db-ivm@0.1.13':
resolution: {integrity: sha512-sBOWGY4tqMEym2ewjdWrDb5c5c8akvgnEbGVPAtkfFS3QVV0zfVb5RJAkAc8GSxb3ByVfYjyaShVr0kMJhMuow==}
peerDependencies:
@@ -1834,41 +1750,16 @@ packages:
peerDependencies:
typescript: '>=4.7'
- '@tanstack/devtools-client@0.0.4':
- resolution: {integrity: sha512-LefnH9KE9uRDEWifc3QDcooskA8ikfs41bybDTgpYQpyTUspZnaEdUdya9Hry0KYxZ8nos0S3nNbsP79KHqr6Q==}
- engines: {node: '>=18'}
-
- '@tanstack/devtools-event-bus@0.3.3':
- resolution: {integrity: sha512-lWl88uLAz7ZhwNdLH6A3tBOSEuBCrvnY9Fzr5JPdzJRFdM5ZFdyNWz1Bf5l/F3GU57VodrN0KCFi9OA26H5Kpg==}
- engines: {node: '>=18'}
-
'@tanstack/devtools-event-client@0.3.4':
resolution: {integrity: sha512-eq+PpuutUyubXu+ycC1GIiVwBs86NF/8yYJJAKSpPcJLWl6R/761F1H4F/9ziX6zKezltFUH1ah3Cz8Ah+KJrw==}
engines: {node: '>=18'}
- '@tanstack/devtools-ui@0.4.4':
- resolution: {integrity: sha512-5xHXFyX3nom0UaNfiOM92o6ziaHjGo3mcSGe2HD5Xs8dWRZNpdZ0Smd0B9ddEhy0oB+gXyMzZgUJb9DmrZV0Mg==}
- engines: {node: '>=18'}
- peerDependencies:
- solid-js: '>=1.9.7'
-
- '@tanstack/devtools@0.8.0':
- resolution: {integrity: sha512-j6tBkMpAyTkiGH4ELiHzFSpV0f9fCYtAMEqTEiXEOVVfB57C36KR8LyIHtdeGzK6eQ5sKEdgLbHG9EU31L3Jng==}
- engines: {node: '>=18'}
- peerDependencies:
- solid-js: '>=1.9.7'
-
'@tanstack/electric-db-collection@0.2.6':
resolution: {integrity: sha512-3J5mLxQ+PWwAxwsJy3Paygfd8dwUcs/oy1RxWjkIowRkYc1JA9x2/KSzX7ovzmYWbD87juHeLb73leuaWmqhow==}
'@tanstack/form-core@1.24.4':
resolution: {integrity: sha512-+eIR7DiDamit1zvTVgaHxuIRA02YFgJaXMUGxsLRJoBpUjGl/g/nhUocQoNkRyfXqOlh8OCMTanjwDprWSRq6w==}
- '@tanstack/form-devtools@0.1.8':
- resolution: {integrity: sha512-r34PPx1f5QlkWMqFh8Vyw6ats+ValLrTJMhFTx66m1i0YZJ1D5vZ/1ZF62JWMUxsep0yJqDbXznr1629Qmrt8w==}
- peerDependencies:
- solid-js: '>=1.9.9'
-
'@tanstack/pacer-lite@0.1.0':
resolution: {integrity: sha512-a5A0PI0H4npUy7u3VOjOhdynXnRBna+mDvpt8ghDCVzS3Tgn8DlGzHlRqS2rKJP8ZcLuVO2qxlIIblhcoaiv8Q==}
engines: {node: '>=18'}
@@ -1885,20 +1776,6 @@ packages:
peerDependencies:
react: '>=16.8.0'
- '@tanstack/react-devtools@0.8.0':
- resolution: {integrity: sha512-0TsFICBPr68us3iWHFXCIBSEilTo8j1OdIJLW48LNQNjC/Puno82uqX4qFuaZWfZv6K37QnS6UeRxzWJItMFSA==}
- engines: {node: '>=18'}
- peerDependencies:
- '@types/react': '>=16.8'
- '@types/react-dom': '>=16.8'
- react: '>=16.8'
- react-dom: '>=16.8'
-
- '@tanstack/react-form-devtools@0.1.8':
- resolution: {integrity: sha512-FwXYLzLIGpqhHcg3sv81ioBBP+3+d2DPS8F+srXBZHuaJAHh6yhwDPAjhe5FlCK8X8+RlVtEbbD+4JXyWao8EQ==}
- peerDependencies:
- react: ^17.0.0 || ^18.0.0 || ^19.0.0
-
'@tanstack/react-form@1.23.8':
resolution: {integrity: sha512-ivfkiOHAI3aIWkCY4FnPWVAL6SkQWGWNVjtwIZpaoJE4ulukZWZ1KB8TQKs8f4STl+egjTsMHrWJuf2fv3Xh1w==}
peerDependencies:
@@ -1960,9 +1837,6 @@ packages:
peerDependencies:
'@types/react': ^18.0.0
- '@types/react-window@1.8.8':
- resolution: {integrity: sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==}
-
'@types/react@18.3.23':
resolution: {integrity: sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==}
@@ -2275,9 +2149,6 @@ packages:
resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
engines: {node: '>=0.11'}
- dayjs@1.11.19:
- resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==}
-
debug@4.4.1:
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
engines: {node: '>=6.0'}
@@ -2616,11 +2487,6 @@ packages:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
- goober@2.1.18:
- resolution: {integrity: sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==}
- peerDependencies:
- csstype: ^3.0.10
-
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
@@ -2789,12 +2655,6 @@ packages:
lodash-es@4.17.21:
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
- lodash.castarray@4.4.0:
- resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
-
- lodash.isplainobject@4.0.6:
- resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
-
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
@@ -2837,9 +2697,6 @@ packages:
react:
optional: true
- memoize-one@5.2.1:
- resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==}
-
merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
@@ -3016,10 +2873,6 @@ packages:
peerDependencies:
postcss: ^8.2.14
- postcss-selector-parser@6.0.10:
- resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
- engines: {node: '>=4'}
-
postcss-selector-parser@6.1.2:
resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
engines: {node: '>=4'}
@@ -3188,22 +3041,12 @@ packages:
'@types/react':
optional: true
- react-use-websocket@4.13.0:
- resolution: {integrity: sha512-anMuVoV//g2N76Wxqvqjjo1X48r9Np3y1/gMl7arX84tAPXdy5R7sB5lO5hvCzQRYjqXwV8XMAiEBOUbyrZFrw==}
-
react-virtuoso@4.14.0:
resolution: {integrity: sha512-fR+eiCvirSNIRvvCD7ueJPRsacGQvUbjkwgWzBZXVq+yWypoH7mRUvWJzGHIdoRaCZCT+6mMMMwIG2S1BW3uwA==}
peerDependencies:
react: '>=16 || >=17 || >= 18 || >= 19'
react-dom: '>=16 || >=17 || >= 18 || >=19'
- react-window@1.8.11:
- resolution: {integrity: sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ==}
- engines: {node: '>8.0.0'}
- peerDependencies:
- react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
- react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
-
react@18.3.1:
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
engines: {node: '>=0.10.0'}
@@ -3276,16 +3119,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
- seroval-plugins@1.3.3:
- resolution: {integrity: sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w==}
- engines: {node: '>=10'}
- peerDependencies:
- seroval: ^1.0
-
- seroval@1.3.2:
- resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==}
- engines: {node: '>=10'}
-
set-cookie-parser@2.7.2:
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
@@ -3313,9 +3146,6 @@ packages:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
- solid-js@1.9.10:
- resolution: {integrity: sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew==}
-
sorted-btree@1.8.1:
resolution: {integrity: sha512-395+XIP+wqNn3USkFSrNz7G3Ss/MXlZEqesxvzCRFwL14h6e8LukDHdLBePn5pwbm5OQ9vGu8mDyz2lLDIqamQ==}
@@ -3637,18 +3467,6 @@ packages:
wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
- ws@8.18.3:
- resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
- engines: {node: '>=10.0.0'}
- peerDependencies:
- bufferutil: ^4.0.1
- utf-8-validate: '>=5.0.2'
- peerDependenciesMeta:
- bufferutil:
- optional: true
- utf-8-validate:
- optional: true
-
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -3677,9 +3495,6 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
- zod@4.1.12:
- resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==}
-
zustand@4.5.7:
resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==}
engines: {node: '>=12.7.0'}
@@ -3887,13 +3702,6 @@ snapshots:
react-dom: 18.3.1(react@18.3.1)
tslib: 2.8.1
- '@dnd-kit/modifiers@9.0.0(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
- dependencies:
- '@dnd-kit/core': 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@dnd-kit/utilities': 3.2.2(react@18.3.1)
- react: 18.3.1
- tslib: 2.8.1
-
'@dnd-kit/utilities@3.2.2(react@18.3.1)':
dependencies:
react: 18.3.1
@@ -4869,22 +4677,6 @@ snapshots:
'@types/react': 18.3.23
'@types/react-dom': 18.3.7(@types/react@18.3.23)
- '@radix-ui/react-tabs@1.1.12(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
- dependencies:
- '@radix-ui/primitive': 1.1.2
- '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1)
- '@radix-ui/react-direction': 1.1.1(@types/react@18.3.23)(react@18.3.1)
- '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1)
- '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1)
- react: 18.3.1
- react-dom: 18.3.1(react@18.3.1)
- optionalDependencies:
- '@types/react': 18.3.23
- '@types/react-dom': 18.3.7(@types/react@18.3.23)
-
'@radix-ui/react-toggle-group@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.3
@@ -5221,54 +5013,12 @@ snapshots:
- encoding
- supports-color
- '@solid-primitives/event-listener@2.4.3(solid-js@1.9.10)':
- dependencies:
- '@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
- solid-js: 1.9.10
-
- '@solid-primitives/keyboard@1.3.3(solid-js@1.9.10)':
- dependencies:
- '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10)
- '@solid-primitives/rootless': 1.5.2(solid-js@1.9.10)
- '@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
- solid-js: 1.9.10
-
- '@solid-primitives/resize-observer@2.1.3(solid-js@1.9.10)':
- dependencies:
- '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10)
- '@solid-primitives/rootless': 1.5.2(solid-js@1.9.10)
- '@solid-primitives/static-store': 0.1.2(solid-js@1.9.10)
- '@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
- solid-js: 1.9.10
-
- '@solid-primitives/rootless@1.5.2(solid-js@1.9.10)':
- dependencies:
- '@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
- solid-js: 1.9.10
-
- '@solid-primitives/static-store@0.1.2(solid-js@1.9.10)':
- dependencies:
- '@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
- solid-js: 1.9.10
-
- '@solid-primitives/utils@6.3.2(solid-js@1.9.10)':
- dependencies:
- solid-js: 1.9.10
-
'@standard-schema/spec@1.0.0': {}
'@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.17)':
dependencies:
tailwindcss: 3.4.17
- '@tailwindcss/typography@0.5.16(tailwindcss@3.4.17)':
- dependencies:
- lodash.castarray: 4.4.0
- lodash.isplainobject: 4.0.6
- lodash.merge: 4.6.2
- postcss-selector-parser: 6.0.10
- tailwindcss: 3.4.17
-
'@tanstack/db-ivm@0.1.13(typescript@5.9.2)':
dependencies:
fractional-indexing: 3.2.0
@@ -5282,43 +5032,8 @@ snapshots:
'@tanstack/pacer-lite': 0.1.0
typescript: 5.9.2
- '@tanstack/devtools-client@0.0.4':
- dependencies:
- '@tanstack/devtools-event-client': 0.3.4
-
- '@tanstack/devtools-event-bus@0.3.3':
- dependencies:
- ws: 8.18.3
- transitivePeerDependencies:
- - bufferutil
- - utf-8-validate
-
'@tanstack/devtools-event-client@0.3.4': {}
- '@tanstack/devtools-ui@0.4.4(csstype@3.1.3)(solid-js@1.9.10)':
- dependencies:
- clsx: 2.1.1
- goober: 2.1.18(csstype@3.1.3)
- solid-js: 1.9.10
- transitivePeerDependencies:
- - csstype
-
- '@tanstack/devtools@0.8.0(csstype@3.1.3)(solid-js@1.9.10)':
- dependencies:
- '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10)
- '@solid-primitives/keyboard': 1.3.3(solid-js@1.9.10)
- '@solid-primitives/resize-observer': 2.1.3(solid-js@1.9.10)
- '@tanstack/devtools-client': 0.0.4
- '@tanstack/devtools-event-bus': 0.3.3
- '@tanstack/devtools-ui': 0.4.4(csstype@3.1.3)(solid-js@1.9.10)
- clsx: 2.1.1
- goober: 2.1.18(csstype@3.1.3)
- solid-js: 1.9.10
- transitivePeerDependencies:
- - bufferutil
- - csstype
- - utf-8-validate
-
'@tanstack/electric-db-collection@0.2.6(typescript@5.9.2)':
dependencies:
'@electric-sql/client': 1.2.0
@@ -5336,17 +5051,6 @@ snapshots:
'@tanstack/pacer': 0.15.4
'@tanstack/store': 0.7.7
- '@tanstack/form-devtools@0.1.8(csstype@3.1.3)(solid-js@1.9.10)':
- dependencies:
- '@tanstack/devtools-ui': 0.4.4(csstype@3.1.3)(solid-js@1.9.10)
- '@tanstack/form-core': 1.24.4
- clsx: 2.1.1
- dayjs: 1.11.19
- goober: 2.1.18(csstype@3.1.3)
- solid-js: 1.9.10
- transitivePeerDependencies:
- - csstype
-
'@tanstack/pacer-lite@0.1.0': {}
'@tanstack/pacer@0.15.4':
@@ -5364,27 +5068,6 @@ snapshots:
transitivePeerDependencies:
- typescript
- '@tanstack/react-devtools@0.8.0(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(solid-js@1.9.10)':
- dependencies:
- '@tanstack/devtools': 0.8.0(csstype@3.1.3)(solid-js@1.9.10)
- '@types/react': 18.3.23
- '@types/react-dom': 18.3.7(@types/react@18.3.23)
- react: 18.3.1
- react-dom: 18.3.1(react@18.3.1)
- transitivePeerDependencies:
- - bufferutil
- - csstype
- - solid-js
- - utf-8-validate
-
- '@tanstack/react-form-devtools@0.1.8(csstype@3.1.3)(react@18.3.1)(solid-js@1.9.10)':
- dependencies:
- '@tanstack/form-devtools': 0.1.8(csstype@3.1.3)(solid-js@1.9.10)
- react: 18.3.1
- transitivePeerDependencies:
- - csstype
- - solid-js
-
'@tanstack/react-form@1.23.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/form-core': 1.24.4
@@ -5453,10 +5136,6 @@ snapshots:
dependencies:
'@types/react': 18.3.23
- '@types/react-window@1.8.8':
- dependencies:
- '@types/react': 18.3.23
-
'@types/react@18.3.23':
dependencies:
'@types/prop-types': 15.7.15
@@ -5827,8 +5506,6 @@ snapshots:
dependencies:
'@babel/runtime': 7.27.6
- dayjs@1.11.19: {}
-
debug@4.4.1:
dependencies:
ms: 2.1.3
@@ -6197,10 +5874,6 @@ snapshots:
merge2: 1.4.1
slash: 3.0.0
- goober@2.1.18(csstype@3.1.3):
- dependencies:
- csstype: 3.1.3
-
graphemer@1.4.0: {}
has-flag@4.0.0: {}
@@ -6341,10 +6014,6 @@ snapshots:
lodash-es@4.17.21: {}
- lodash.castarray@4.4.0: {}
-
- lodash.isplainobject@4.0.6: {}
-
lodash.merge@4.6.2: {}
lodash@4.17.21: {}
@@ -6381,8 +6050,6 @@ snapshots:
optionalDependencies:
react: 18.3.1
- memoize-one@5.2.1: {}
-
merge2@1.4.1: {}
micromatch@4.0.8:
@@ -6520,11 +6187,6 @@ snapshots:
postcss: 8.5.6
postcss-selector-parser: 6.1.2
- postcss-selector-parser@6.0.10:
- dependencies:
- cssesc: 3.0.0
- util-deprecate: 1.0.2
-
postcss-selector-parser@6.1.2:
dependencies:
cssesc: 3.0.0
@@ -6671,20 +6333,11 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.23
- react-use-websocket@4.13.0: {}
-
react-virtuoso@4.14.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
- react-window@1.8.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
- dependencies:
- '@babel/runtime': 7.27.6
- memoize-one: 5.2.1
- react: 18.3.1
- react-dom: 18.3.1(react@18.3.1)
-
react@18.3.1:
dependencies:
loose-envify: 1.4.0
@@ -6768,12 +6421,6 @@ snapshots:
semver@7.7.2: {}
- seroval-plugins@1.3.3(seroval@1.3.2):
- dependencies:
- seroval: 1.3.2
-
- seroval@1.3.2: {}
-
set-cookie-parser@2.7.2: {}
shebang-command@2.0.0:
@@ -6790,12 +6437,6 @@ snapshots:
slash@3.0.0: {}
- solid-js@1.9.10:
- dependencies:
- csstype: 3.1.3
- seroval: 1.3.2
- seroval-plugins: 1.3.3(seroval@1.3.2)
-
sorted-btree@1.8.1: {}
source-map-js@1.2.1: {}
@@ -7066,8 +6707,6 @@ snapshots:
wrappy@1.0.2: {}
- ws@8.18.3: {}
-
y18n@5.0.8: {}
yallist@3.1.1: {}
@@ -7092,8 +6731,6 @@ snapshots:
yocto-queue@0.1.0: {}
- zod@4.1.12: {}
-
zustand@4.5.7(@types/react@18.3.23)(react@18.3.1):
dependencies:
use-sync-external-store: 1.5.0(react@18.3.1)