From ab6f5328b454c4f022c92415242c273e80f5239b Mon Sep 17 00:00:00 2001 From: Toddyclipsgg Date: Sun, 23 Feb 2025 07:55:38 -0300 Subject: [PATCH 1/5] feat: Add Diff View and File History Tracking - Implemented a new Diff View in the Workbench to visualize file changes - Added file history tracking with detailed change information - Enhanced FileTree and FileModifiedDropdown to show line additions and deletions - Integrated file history saving and retrieval in ActionRunner - Updated Workbench view types to include 'diff' option - Added support for inline and side-by-side diff view modes --- .github/actions/setup-and-build/action.yaml | 4 + .tool-versions | 2 +- README.md | 7 +- app/components/chat/BaseChat.tsx | 76 +- app/components/ui/Slider.tsx | 22 +- app/components/workbench/DiffView.tsx | 647 ++++++++++++++++++ app/components/workbench/EditorPanel.tsx | 4 + app/components/workbench/FileTree.tsx | 59 +- app/components/workbench/Workbench.client.tsx | 274 +++++++- app/lib/runtime/action-runner.ts | 35 +- app/lib/stores/workbench.ts | 24 +- app/styles/diff-view.css | 72 ++ app/types/actions.ts | 14 + app/utils/getLanguageFromExtension.ts | 24 + package.json | 2 + vite.config.ts | 1 + wrangler.toml | 2 +- 17 files changed, 1192 insertions(+), 77 deletions(-) create mode 100644 app/components/workbench/DiffView.tsx create mode 100644 app/styles/diff-view.css create mode 100644 app/utils/getLanguageFromExtension.ts diff --git a/.github/actions/setup-and-build/action.yaml b/.github/actions/setup-and-build/action.yaml index b27bc6fb..b4f27b73 100644 --- a/.github/actions/setup-and-build/action.yaml +++ b/.github/actions/setup-and-build/action.yaml @@ -30,3 +30,7 @@ runs: run: | pnpm install pnpm run build + + - name: Create history directory + shell: bash + run: mkdir -p .history diff --git a/.tool-versions b/.tool-versions index 427253d3..74c88f6a 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ nodejs 20.15.1 -pnpm 9.4.0 +pnpm 9.4.0 \ No newline at end of file diff --git a/README.md b/README.md index 0a4e77e0..3071fcee 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,10 @@ Welcome to bolt.diy, the official open source version of Bolt.new (previously known as oTToDev and bolt.new ANY LLM), which allows you to choose the LLM that you use for each prompt! Currently, you can use OpenAI, Anthropic, Ollama, OpenRouter, Gemini, LMStudio, Mistral, xAI, HuggingFace, DeepSeek, or Groq models - and it is easily extended to use any other model supported by the Vercel AI SDK! See the instructions below for running this locally and extending it to include more models. ---- - +----- Check the [bolt.diy Docs](https://stackblitz-labs.github.io/bolt.diy/) for more offical installation instructions and more informations. ---- - +----- Also [this pinned post in our community](https://thinktank.ottomator.ai/t/videos-tutorial-helpful-content/3243) has a bunch of incredible resources for running and deploying bolt.diy yourself! We have also launched an experimental agent called the "bolt.diy Expert" that can answer common questions about bolt.diy. Find it here on the [oTTomator Live Agent Studio](https://studio.ottomator.ai/). @@ -81,6 +79,7 @@ project, please check the [project management guide](./PROJECT.md) to get starte - ✅ Add Starter Template Options (@thecodacus) - ✅ Perplexity Integration (@meetpateltech) - ✅ AWS Bedrock Integration (@kunjabijukchhe) +- ✅ Add a "Diff View" to see the changes (@toddyclipsgg) - ⬜ **HIGH PRIORITY** - Prevent bolt from rewriting files as often (file locking and diffs) - ⬜ **HIGH PRIORITY** - Better prompting for smaller LLMs (code window sometimes doesn't start) - ⬜ **HIGH PRIORITY** - Run agents in the backend as opposed to a single model call diff --git a/app/components/chat/BaseChat.tsx b/app/components/chat/BaseChat.tsx index ff1f4184..f38a5ccf 100644 --- a/app/components/chat/BaseChat.tsx +++ b/app/components/chat/BaseChat.tsx @@ -34,6 +34,7 @@ import ChatAlert from './ChatAlert'; import type { ModelInfo } from '~/lib/modules/llm/types'; import ProgressCompilation from './ProgressCompilation'; import type { ProgressAnnotation } from '~/types/context'; +import type { ActionRunner } from '~/lib/runtime/action-runner'; import { LOCAL_PROVIDERS } from '~/lib/stores/settings'; const TEXTAREA_MIN_HEIGHT = 76; @@ -68,6 +69,7 @@ interface BaseChatProps { actionAlert?: ActionAlert; clearAlert?: () => void; data?: JSONValue[] | undefined; + actionRunner?: ActionRunner; } export const BaseChat = React.forwardRef( @@ -102,6 +104,7 @@ export const BaseChat = React.forwardRef( actionAlert, clearAlert, data, + actionRunner, }, ref, ) => { @@ -304,7 +307,7 @@ export const BaseChat = React.forwardRef( data-chat-visible={showChat} > {() => } -
+
{!chatStarted && (
@@ -318,40 +321,39 @@ export const BaseChat = React.forwardRef( )}
{() => { return chatStarted ? ( -
- -
+ ) : null; }}
- {actionAlert && ( - clearAlert?.()} - postMessage={(message) => { - sendMessage?.({} as any, message); - clearAlert?.(); - }} - /> - )} +
+ {actionAlert && ( + clearAlert?.()} + postMessage={(message) => { + sendMessage?.({} as any, message); + clearAlert?.(); + }} + /> + )} +
{progressAnnotations && }
(
- {!chatStarted && ( -
+
+ {!chatStarted && (
-
- {ImportButtons(importChat)} - -
+ {ImportButtons(importChat)} +
- - {ExamplePrompts((event, messageInput) => { + )} + {!chatStarted && + ExamplePrompts((event, messageInput) => { if (isStreaming) { handleStop?.(); return; @@ -602,11 +603,18 @@ export const BaseChat = React.forwardRef( handleSendMessage?.(event, messageInput); })} - -
- )} + {!chatStarted && } +
- {() => } + + {() => ( + + )} +
); diff --git a/app/components/ui/Slider.tsx b/app/components/ui/Slider.tsx index f332a6af..d5e9b000 100644 --- a/app/components/ui/Slider.tsx +++ b/app/components/ui/Slider.tsx @@ -9,10 +9,11 @@ interface SliderOption { text: string; } -export interface SliderOptions { - left: SliderOption; - right: SliderOption; -} +export type SliderOptions = { + left: { value: T; text: string }; + middle?: { value: T; text: string }; + right: { value: T; text: string }; +}; interface SliderProps { selected: T; @@ -21,14 +22,23 @@ interface SliderProps { } export const Slider = genericMemo(({ selected, options, setSelected }: SliderProps) => { - const isLeftSelected = selected === options.left.value; + const hasMiddle = !!options.middle; + const isLeftSelected = hasMiddle ? selected === options.left.value : selected === options.left.value; + const isMiddleSelected = hasMiddle && options.middle ? selected === options.middle.value : false; return (
setSelected?.(options.left.value)}> {options.left.text} - setSelected?.(options.right.value)}> + + {options.middle && ( + setSelected?.(options.middle!.value)}> + {options.middle.text} + + )} + + setSelected?.(options.right.value)}> {options.right.text}
diff --git a/app/components/workbench/DiffView.tsx b/app/components/workbench/DiffView.tsx new file mode 100644 index 00000000..26b7e260 --- /dev/null +++ b/app/components/workbench/DiffView.tsx @@ -0,0 +1,647 @@ +import { memo, useMemo, useState, useEffect, useCallback } from 'react'; +import { useStore } from '@nanostores/react'; +import { workbenchStore } from '~/lib/stores/workbench'; +import type { FileMap } from '~/lib/stores/files'; +import type { EditorDocument } from '~/components/editor/codemirror/CodeMirrorEditor'; +import { diffLines, type Change } from 'diff'; +import { getHighlighter } from 'shiki'; +import '~/styles/diff-view.css'; +import { diffFiles, extractRelativePath } from '~/utils/diff'; +import { ActionRunner } from '~/lib/runtime/action-runner'; +import type { FileHistory } from '~/types/actions'; +import { getLanguageFromExtension } from '~/utils/getLanguageFromExtension'; + +interface CodeComparisonProps { + beforeCode: string; + afterCode: string; + language: string; + filename: string; + lightTheme: string; + darkTheme: string; +} + +interface DiffBlock { + lineNumber: number; + content: string; + type: 'added' | 'removed' | 'unchanged'; + correspondingLine?: number; +} + +interface FullscreenButtonProps { + onClick: () => void; + isFullscreen: boolean; +} + +const FullscreenButton = memo(({ onClick, isFullscreen }: FullscreenButtonProps) => ( + +)); + +const FullscreenOverlay = memo(({ isFullscreen, children }: { isFullscreen: boolean; children: React.ReactNode }) => { + if (!isFullscreen) return <>{children}; + + return ( +
+
+ {children} +
+
+ ); +}); + +const MAX_FILE_SIZE = 1024 * 1024; // 1MB +const BINARY_REGEX = /[\x00-\x08\x0E-\x1F]/; + +const isBinaryFile = (content: string) => { + return content.length > MAX_FILE_SIZE || BINARY_REGEX.test(content); +}; + +const processChanges = (beforeCode: string, afterCode: string) => { + try { + if (isBinaryFile(beforeCode) || isBinaryFile(afterCode)) { + return { + beforeLines: [], + afterLines: [], + hasChanges: false, + lineChanges: { before: new Set(), after: new Set() }, + unifiedBlocks: [], + isBinary: true + }; + } + + // Normalizar quebras de linha para evitar falsos positivos + const normalizedBefore = beforeCode.replace(/\r\n/g, '\n'); + const normalizedAfter = afterCode.replace(/\r\n/g, '\n'); + + // Dividir em linhas preservando linhas vazias + const beforeLines = normalizedBefore.split('\n'); + const afterLines = normalizedAfter.split('\n'); + + // Se os conteúdos são idênticos após normalização, não há mudanças + if (normalizedBefore === normalizedAfter) { + return { + beforeLines, + afterLines, + hasChanges: false, + lineChanges: { before: new Set(), after: new Set() }, + unifiedBlocks: [] + }; + } + + // Processar as diferenças com configurações otimizadas para detecção por linha + const changes = diffLines(normalizedBefore, normalizedAfter, { + newlineIsToken: false, // Não tratar quebras de linha como tokens separados + ignoreWhitespace: true, // Ignorar diferenças de espaços em branco + ignoreCase: false // Manter sensibilidade a maiúsculas/minúsculas + }); + + const lineChanges = { + before: new Set(), + after: new Set() + }; + + let beforeLineNumber = 0; + let afterLineNumber = 0; + + const unifiedBlocks = changes.reduce((blocks: DiffBlock[], change) => { + // Dividir o conteúdo em linhas preservando linhas vazias + const lines = change.value.split('\n'); + + if (change.added) { + // Processar linhas adicionadas + const addedBlocks = lines.map((line, i) => { + lineChanges.after.add(afterLineNumber + i); + return { + lineNumber: afterLineNumber + i, + content: line, + type: 'added' as const + }; + }); + afterLineNumber += lines.length; + return [...blocks, ...addedBlocks]; + } + + if (change.removed) { + // Processar linhas removidas + const removedBlocks = lines.map((line, i) => { + lineChanges.before.add(beforeLineNumber + i); + return { + lineNumber: beforeLineNumber + i, + content: line, + type: 'removed' as const + }; + }); + beforeLineNumber += lines.length; + return [...blocks, ...removedBlocks]; + } + + // Processar linhas não modificadas + const unchangedBlocks = lines.map((line, i) => { + const block = { + lineNumber: afterLineNumber + i, + content: line, + type: 'unchanged' as const, + correspondingLine: beforeLineNumber + i + }; + return block; + }); + beforeLineNumber += lines.length; + afterLineNumber += lines.length; + return [...blocks, ...unchangedBlocks]; + }, []); + + return { + beforeLines, + afterLines, + hasChanges: lineChanges.before.size > 0 || lineChanges.after.size > 0, + lineChanges, + unifiedBlocks, + isBinary: false + }; + } catch (error) { + console.error('Error processing changes:', error); + return { + beforeLines: [], + afterLines: [], + hasChanges: false, + lineChanges: { before: new Set(), after: new Set() }, + unifiedBlocks: [], + error: true, + isBinary: false + }; + } +}; + +const lineNumberStyles = "w-12 shrink-0 pl-2 py-0.5 text-left font-mono text-bolt-elements-textTertiary border-r border-bolt-elements-borderColor bg-bolt-elements-background-depth-1"; +const lineContentStyles = "px-4 py-0.5 font-mono whitespace-pre flex-1 group-hover:bg-bolt-elements-background-depth-2 text-bolt-elements-textPrimary"; + +const renderContentWarning = (type: 'binary' | 'error') => ( +
+
+
+

+ {type === 'binary' ? 'Binary file detected' : 'Error processing file'} +

+

+ {type === 'binary' + ? 'Diff view is not available for binary files' + : 'Could not generate diff preview'} +

+
+
+); + +const NoChangesView = memo(({ beforeCode, language, highlighter }: { + beforeCode: string; + language: string; + highlighter: any; +}) => ( +
+
+
+

Files are identical

+

Both versions match exactly

+
+
+
+ Current Content +
+
+ {beforeCode.split('\n').map((line, index) => ( +
+
{index + 1}
+
+ + ]*>/g, '') + .replace(/<\/?code[^>]*>/g, '') + : line + }} /> +
+
+ ))} +
+
+
+)); + +// Otimização do processamento de diferenças com memoização +const useProcessChanges = (beforeCode: string, afterCode: string) => { + return useMemo(() => processChanges(beforeCode, afterCode), [beforeCode, afterCode]); +}; + +// Componente otimizado para renderização de linhas de código +const CodeLine = memo(({ + lineNumber, + content, + type, + highlighter, + language +}: { + lineNumber: number; + content: string; + type: 'added' | 'removed' | 'unchanged'; + highlighter: any; + language: string; +}) => { + const bgColor = { + added: 'bg-green-500/20 border-l-4 border-green-500', + removed: 'bg-red-500/20 border-l-4 border-red-500', + unchanged: '' + }[type]; + + const highlightedCode = useMemo(() => { + if (!highlighter) return content; + return highlighter.codeToHtml(content, { + lang: language, + theme: 'github-dark' + }).replace(/<\/?pre[^>]*>/g, '').replace(/<\/?code[^>]*>/g, ''); + }, [content, highlighter, language]); + + return ( +
+
{lineNumber + 1}
+
+ + {type === 'added' && '+'} + {type === 'removed' && '-'} + {type === 'unchanged' && ' '} + + +
+
+ ); +}); + +// Componente para exibir informações sobre o arquivo +const FileInfo = memo(({ + filename, + hasChanges, + onToggleFullscreen, + isFullscreen, + beforeCode, + afterCode +}: { + filename: string; + hasChanges: boolean; + onToggleFullscreen: () => void; + isFullscreen: boolean; + beforeCode: string; + afterCode: string; +}) => { + // Calculate additions and deletions from the current document + const { additions, deletions } = useMemo(() => { + if (!hasChanges) return { additions: 0, deletions: 0 }; + + const changes = diffLines(beforeCode, afterCode, { + newlineIsToken: false, + ignoreWhitespace: true, + ignoreCase: false + }); + + return changes.reduce((acc: { additions: number; deletions: number }, change: Change) => { + if (change.added) { + acc.additions += change.value.split('\n').length; + } + if (change.removed) { + acc.deletions += change.value.split('\n').length; + } + return acc; + }, { additions: 0, deletions: 0 }); + }, [hasChanges, beforeCode, afterCode]); + + const showStats = additions > 0 || deletions > 0; + + return ( +
+
+ {filename} + + {hasChanges ? ( + <> + {showStats && ( +
+ {additions > 0 && ( + +{additions} + )} + {deletions > 0 && ( + -{deletions} + )} +
+ )} + Modified + + {new Date().toLocaleTimeString()} + + + ) : ( + No Changes + )} + +
+
+ ); +}); + +const InlineDiffComparison = memo(({ beforeCode, afterCode, filename, language, lightTheme, darkTheme }: CodeComparisonProps) => { + const [isFullscreen, setIsFullscreen] = useState(false); + const [highlighter, setHighlighter] = useState(null); + + const toggleFullscreen = useCallback(() => { + setIsFullscreen(prev => !prev); + }, []); + + const { unifiedBlocks, hasChanges, isBinary, error } = useProcessChanges(beforeCode, afterCode); + + useEffect(() => { + getHighlighter({ + themes: ['github-dark'], + langs: ['typescript', 'javascript', 'json', 'html', 'css', 'jsx', 'tsx'] + }).then(setHighlighter); + }, []); + + if (isBinary || error) return renderContentWarning(isBinary ? 'binary' : 'error'); + + return ( + +
+ +
+ {hasChanges ? ( +
+ {unifiedBlocks.map((block, index) => ( + + ))} +
+ ) : ( + + )} +
+
+
+ ); +}); + +const SideBySideComparison = memo(({ + beforeCode, + afterCode, + language, + filename, + lightTheme, + darkTheme, +}: CodeComparisonProps) => { + const [isFullscreen, setIsFullscreen] = useState(false); + const [highlighter, setHighlighter] = useState(null); + + const toggleFullscreen = useCallback(() => { + setIsFullscreen(prev => !prev); + }, []); + + const { beforeLines, afterLines, hasChanges, lineChanges, isBinary, error } = useProcessChanges(beforeCode, afterCode); + + useEffect(() => { + getHighlighter({ + themes: ['github-dark'], + langs: ['typescript', 'javascript', 'json', 'html', 'css', 'jsx', 'tsx'] + }).then(setHighlighter); + }, []); + + if (isBinary || error) return renderContentWarning(isBinary ? 'binary' : 'error'); + + const renderCode = (code: string) => { + if (!highlighter) return code; + const highlightedCode = highlighter.codeToHtml(code, { + lang: language, + theme: 'github-dark' + }); + return highlightedCode.replace(/<\/?pre[^>]*>/g, '').replace(/<\/?code[^>]*>/g, ''); + }; + + return ( + +
+ +
+ {hasChanges ? ( +
+
+ {beforeLines.map((line, index) => ( +
+
{index + 1}
+
+ + {lineChanges.before.has(index) ? '-' : ' '} + + +
+
+ ))} +
+
+ {afterLines.map((line, index) => ( +
+
{index + 1}
+
+ + {lineChanges.after.has(index) ? '+' : ' '} + + +
+
+ ))} +
+
+ ) : ( + + )} +
+
+
+ ); +}); + +interface DiffViewProps { + fileHistory: Record; + setFileHistory: React.Dispatch>>; + diffViewMode: 'inline' | 'side'; + actionRunner: ActionRunner; +} + +export const DiffView = memo(({ fileHistory, setFileHistory, diffViewMode, actionRunner }: DiffViewProps) => { + const files = useStore(workbenchStore.files) as FileMap; + const selectedFile = useStore(workbenchStore.selectedFile); + const currentDocument = useStore(workbenchStore.currentDocument) as EditorDocument; + const unsavedFiles = useStore(workbenchStore.unsavedFiles); + + useEffect(() => { + if (selectedFile && currentDocument) { + const file = files[selectedFile]; + if (!file || !('content' in file)) return; + + const existingHistory = fileHistory[selectedFile]; + const currentContent = currentDocument.value; + + // Normalizar o conteúdo para comparação + const normalizedCurrentContent = currentContent.replace(/\r\n/g, '\n').trim(); + const normalizedOriginalContent = (existingHistory?.originalContent || file.content).replace(/\r\n/g, '\n').trim(); + + // Se não há histórico existente, criar um novo apenas se houver diferenças + if (!existingHistory) { + if (normalizedCurrentContent !== normalizedOriginalContent) { + const newChanges = diffLines(file.content, currentContent); + setFileHistory(prev => ({ + ...prev, + [selectedFile]: { + originalContent: file.content, + lastModified: Date.now(), + changes: newChanges, + versions: [{ + timestamp: Date.now(), + content: currentContent + }], + changeSource: 'auto-save' + } + })); + } + return; + } + + // Se já existe histórico, verificar se há mudanças reais desde a última versão + const lastVersion = existingHistory.versions[existingHistory.versions.length - 1]; + const normalizedLastContent = lastVersion?.content.replace(/\r\n/g, '\n').trim(); + + if (normalizedCurrentContent === normalizedLastContent) { + return; // Não criar novo histórico se o conteúdo é o mesmo + } + + // Verificar se há mudanças significativas usando diffFiles + const relativePath = extractRelativePath(selectedFile); + const unifiedDiff = diffFiles( + relativePath, + existingHistory.originalContent, + currentContent + ); + + if (unifiedDiff) { + const newChanges = diffLines( + existingHistory.originalContent, + currentContent + ); + + // Verificar se as mudanças são significativas + const hasSignificantChanges = newChanges.some(change => + (change.added || change.removed) && change.value.trim().length > 0 + ); + + if (hasSignificantChanges) { + const newHistory: FileHistory = { + originalContent: existingHistory.originalContent, + lastModified: Date.now(), + changes: [ + ...existingHistory.changes, + ...newChanges + ].slice(-100), // Limitar histórico de mudanças + versions: [ + ...existingHistory.versions, + { + timestamp: Date.now(), + content: currentContent + } + ].slice(-10), // Manter apenas as 10 últimas versões + changeSource: 'auto-save' + }; + + setFileHistory(prev => ({ ...prev, [selectedFile]: newHistory })); + } + } + } + }, [selectedFile, currentDocument?.value, files, setFileHistory, unsavedFiles]); + + if (!selectedFile || !currentDocument) { + return ( +
+ Select a file to view differences +
+ ); + } + + const file = files[selectedFile]; + const originalContent = file && 'content' in file ? file.content : ''; + const currentContent = currentDocument.value; + + const history = fileHistory[selectedFile]; + const effectiveOriginalContent = history?.originalContent || originalContent; + const language = getLanguageFromExtension(selectedFile.split('.').pop() || ''); + + try { + return ( +
+ {diffViewMode === 'inline' ? ( + + ) : ( + + )} +
+ ); + } catch (error) { + console.error('DiffView render error:', error); + return ( +
+
+
+

Failed to render diff view

+
+
+ ); + } +}); diff --git a/app/components/workbench/EditorPanel.tsx b/app/components/workbench/EditorPanel.tsx index f68e030e..ef9e018b 100644 --- a/app/components/workbench/EditorPanel.tsx +++ b/app/components/workbench/EditorPanel.tsx @@ -12,6 +12,7 @@ import { import { PanelHeader } from '~/components/ui/PanelHeader'; import { PanelHeaderButton } from '~/components/ui/PanelHeaderButton'; import type { FileMap } from '~/lib/stores/files'; +import type { FileHistory } from '~/types/actions'; import { themeStore } from '~/lib/stores/theme'; import { WORK_DIR } from '~/utils/constants'; import { renderLogger } from '~/utils/logger'; @@ -27,6 +28,7 @@ interface EditorPanelProps { editorDocument?: EditorDocument; selectedFile?: string | undefined; isStreaming?: boolean; + fileHistory?: Record; onEditorChange?: OnEditorChange; onEditorScroll?: OnEditorScroll; onFileSelect?: (value?: string) => void; @@ -45,6 +47,7 @@ export const EditorPanel = memo( editorDocument, selectedFile, isStreaming, + fileHistory, onFileSelect, onEditorChange, onEditorScroll, @@ -83,6 +86,7 @@ export const EditorPanel = memo( files={files} hideRoot unsavedFiles={unsavedFiles} + fileHistory={fileHistory} rootFolder={WORK_DIR} selectedFile={selectedFile} onFileSelect={onFileSelect} diff --git a/app/components/workbench/FileTree.tsx b/app/components/workbench/FileTree.tsx index eb185cbb..08d323e5 100644 --- a/app/components/workbench/FileTree.tsx +++ b/app/components/workbench/FileTree.tsx @@ -3,6 +3,8 @@ import type { FileMap } from '~/lib/stores/files'; import { classNames } from '~/utils/classNames'; import { createScopedLogger, renderLogger } from '~/utils/logger'; import * as ContextMenu from '@radix-ui/react-context-menu'; +import type { FileHistory } from '~/types/actions'; +import { diffLines, type Change } from 'diff'; const logger = createScopedLogger('FileTree'); @@ -19,6 +21,7 @@ interface Props { allowFolderSelection?: boolean; hiddenFiles?: Array; unsavedFiles?: Set; + fileHistory?: Record; className?: string; } @@ -34,6 +37,7 @@ export const FileTree = memo( hiddenFiles, className, unsavedFiles, + fileHistory = {}, }: Props) => { renderLogger.trace('FileTree'); @@ -138,6 +142,7 @@ export const FileTree = memo( selected={selectedFile === fileOrFolder.fullPath} file={fileOrFolder} unsavedChanges={unsavedFiles?.has(fileOrFolder.fullPath)} + fileHistory={fileHistory} onCopyPath={() => { onCopyPath(fileOrFolder); }} @@ -253,19 +258,55 @@ interface FileProps { file: FileNode; selected: boolean; unsavedChanges?: boolean; + fileHistory?: Record; onCopyPath: () => void; onCopyRelativePath: () => void; onClick: () => void; } function File({ - file: { depth, name }, + file: { depth, name, fullPath }, onClick, onCopyPath, onCopyRelativePath, selected, unsavedChanges = false, + fileHistory = {}, }: FileProps) { + const fileModifications = fileHistory[fullPath]; + const hasModifications = fileModifications !== undefined; + + // Calculate added and removed lines from the most recent changes + const { additions, deletions } = useMemo(() => { + if (!fileModifications?.originalContent) return { additions: 0, deletions: 0 }; + + // Usar a mesma lógica do DiffView para processar as mudanças + const normalizedOriginal = fileModifications.originalContent.replace(/\r\n/g, '\n'); + const normalizedCurrent = fileModifications.versions[fileModifications.versions.length - 1]?.content.replace(/\r\n/g, '\n') || ''; + + if (normalizedOriginal === normalizedCurrent) { + return { additions: 0, deletions: 0 }; + } + + const changes = diffLines(normalizedOriginal, normalizedCurrent, { + newlineIsToken: false, + ignoreWhitespace: true, + ignoreCase: false + }); + + return changes.reduce((acc: { additions: number; deletions: number }, change: Change) => { + if (change.added) { + acc.additions += change.value.split('\n').length; + } + if (change.removed) { + acc.deletions += change.value.split('\n').length; + } + return acc; + }, { additions: 0, deletions: 0 }); + }, [fileModifications]); + + const showStats = additions > 0 || deletions > 0; + return (
{name}
- {unsavedChanges && } +
+ {showStats && ( +
+ {additions > 0 && ( + +{additions} + )} + {deletions > 0 && ( + -{deletions} + )} +
+ )} + {unsavedChanges && ( + + )} +
diff --git a/app/components/workbench/Workbench.client.tsx b/app/components/workbench/Workbench.client.tsx index 5fdcda75..39d10b9d 100644 --- a/app/components/workbench/Workbench.client.tsx +++ b/app/components/workbench/Workbench.client.tsx @@ -1,8 +1,15 @@ import { useStore } from '@nanostores/react'; import { motion, type HTMLMotionProps, type Variants } from 'framer-motion'; import { computed } from 'nanostores'; -import { memo, useCallback, useEffect, useState } from 'react'; +import { memo, useCallback, useEffect, useState, useMemo } from 'react'; import { toast } from 'react-toastify'; +import { Popover, Transition } from '@headlessui/react'; +import { diffLines, type Change } from 'diff'; +import { formatDistanceToNow as formatDistance } from 'date-fns'; +import { ActionRunner } from '~/lib/runtime/action-runner'; +import { getLanguageFromExtension } from '~/utils/getLanguageFromExtension'; +import type { FileHistory } from '~/types/actions'; +import { DiffView } from './DiffView'; import { type OnChangeCallback as OnEditorChange, type OnScrollCallback as OnEditorScroll, @@ -18,10 +25,16 @@ import { EditorPanel } from './EditorPanel'; import { Preview } from './Preview'; import useViewport from '~/lib/hooks'; import { PushToGitHubDialog } from '~/components/@settings/tabs/connections/components/PushToGitHubDialog'; +import Cookies from 'js-cookie'; interface WorkspaceProps { chatStarted?: boolean; isStreaming?: boolean; + actionRunner: ActionRunner; + metadata?: { + gitUrl?: string; + }; + updateChatMestaData?: (metadata: any) => void; } const viewTransition = { ease: cubicEasingFn }; @@ -31,6 +44,10 @@ const sliderOptions: SliderOptions = { value: 'code', text: 'Code', }, + middle: { + value: 'diff', + text: 'Diff', + }, right: { value: 'preview', text: 'Preview', @@ -54,11 +71,211 @@ const workbenchVariants = { }, } satisfies Variants; -export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) => { +const FileModifiedDropdown = memo(({ + fileHistory, + onSelectFile, + diffViewMode, + toggleDiffViewMode, +}: { + fileHistory: Record, + onSelectFile: (filePath: string) => void, + diffViewMode: 'inline' | 'side', + toggleDiffViewMode: () => void, +}) => { + const modifiedFiles = Object.entries(fileHistory); + const hasChanges = modifiedFiles.length > 0; + const [searchQuery, setSearchQuery] = useState(''); + + const filteredFiles = useMemo(() => { + return modifiedFiles.filter(([filePath]) => + filePath.toLowerCase().includes(searchQuery.toLowerCase()) + ); + }, [modifiedFiles, searchQuery]); + + return ( +
+ + {({ open }: { open: boolean }) => ( + <> + + File Changes + {hasChanges && ( + + {modifiedFiles.length} + + )} + + + +
+
+ setSearchQuery(e.target.value)} + className="w-full pl-8 pr-3 py-1.5 text-sm rounded-lg bg-bolt-elements-background-depth-1 border border-bolt-elements-borderColor focus:outline-none focus:ring-2 focus:ring-blue-500/50" + /> +
+
+
+
+ +
+ {filteredFiles.length > 0 ? ( + filteredFiles.map(([filePath, history]) => { + const extension = filePath.split('.').pop() || ''; + const language = getLanguageFromExtension(extension); + + return ( + + ); + }) + ) : ( +
+
+
+
+

+ {searchQuery ? 'No matching files' : 'No modified files'} +

+

+ {searchQuery ? 'Try another search' : 'Changes will appear here as you edit'} +

+
+ )} +
+
+ + {hasChanges && ( +
+ +
+ )} + + + + )} + + +
+ ); +}); + +export const Workbench = memo(({ + chatStarted, + isStreaming, + actionRunner, + metadata, + updateChatMestaData +}: WorkspaceProps) => { renderLogger.trace('Workbench'); const [isSyncing, setIsSyncing] = useState(false); const [isPushDialogOpen, setIsPushDialogOpen] = useState(false); + const [diffViewMode, setDiffViewMode] = useState<'inline' | 'side'>('inline'); + const [fileHistory, setFileHistory] = useState>({}); + + const modifiedFiles = Array.from(useStore(workbenchStore.unsavedFiles).keys()); const hasPreview = useStore(computed(workbenchStore.previews, (previews) => previews.length > 0)); const showWorkbench = useStore(workbenchStore.showWorkbench); @@ -121,6 +338,15 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) => } }, []); + const handleSelectFile = useCallback((filePath: string) => { + workbenchStore.setSelectedFile(filePath); + workbenchStore.currentView.set('diff'); + }, []); + + const toggleDiffViewMode = useCallback(() => { + setDiffViewMode(prev => prev === 'inline' ? 'side' : 'inline'); + }, []); + return ( chatStarted && (
)} + {selectedView === 'diff' && ( + + )}
selectedFile={selectedFile} files={files} unsavedFiles={unsavedFiles} + fileHistory={fileHistory} onFileSelect={onFileSelect} onEditorScroll={onEditorScroll} onEditorChange={onEditorChange} @@ -203,8 +438,19 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) => /> + + + @@ -215,14 +461,24 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) => setIsPushDialogOpen(false)} - onPush={async (repoName, username, token, isPrivate) => { + onPush={async (repoName, username, token) => { try { - const repoUrl = await workbenchStore.pushToGitHub(repoName, undefined, username, token, isPrivate); + const commitMessage = prompt('Please enter a commit message:', 'Initial commit') || 'Initial commit'; + await workbenchStore.pushToGitHub(repoName, commitMessage, username, token); + const repoUrl = `https://github.com/${username}/${repoName}`; + + if (updateChatMestaData && !metadata?.gitUrl) { + updateChatMestaData({ + ...(metadata || {}), + gitUrl: repoUrl, + }); + } + return repoUrl; } catch (error) { console.error('Error pushing to GitHub:', error); toast.error('Failed to push to GitHub'); - throw error; // Rethrow to let PushToGitHubDialog handle the error state + throw error; } }} /> diff --git a/app/lib/runtime/action-runner.ts b/app/lib/runtime/action-runner.ts index 250dff79..d6150286 100644 --- a/app/lib/runtime/action-runner.ts +++ b/app/lib/runtime/action-runner.ts @@ -1,7 +1,7 @@ import type { WebContainer } from '@webcontainer/api'; -import { path } from '~/utils/path'; +import { path as nodePath } from '~/utils/path'; import { atom, map, type MapStore } from 'nanostores'; -import type { ActionAlert, BoltAction } from '~/types/actions'; +import type { ActionAlert, BoltAction, FileHistory } from '~/types/actions'; import { createScopedLogger } from '~/utils/logger'; import { unreachable } from '~/utils/unreachable'; import type { ActionCallbackData } from './message-parser'; @@ -276,9 +276,9 @@ export class ActionRunner { } const webcontainer = await this.#webcontainer; - const relativePath = path.relative(webcontainer.workdir, action.filePath); + const relativePath = nodePath.relative(webcontainer.workdir, action.filePath); - let folder = path.dirname(relativePath); + let folder = nodePath.dirname(relativePath); // remove trailing slashes folder = folder.replace(/\/+$/g, ''); @@ -304,4 +304,31 @@ export class ActionRunner { this.actions.setKey(id, { ...actions[id], ...newState }); } + + async getFileHistory(filePath: string): Promise { + try { + const webcontainer = await this.#webcontainer; + const historyPath = this.#getHistoryPath(filePath); + const content = await webcontainer.fs.readFile(historyPath, 'utf-8'); + return JSON.parse(content); + } catch (error) { + return null; + } + } + + async saveFileHistory(filePath: string, history: FileHistory) { + const webcontainer = await this.#webcontainer; + const historyPath = this.#getHistoryPath(filePath); + + await this.#runFileAction({ + type: 'file', + filePath: historyPath, + content: JSON.stringify(history), + changeSource: 'auto-save' + } as any); + } + + #getHistoryPath(filePath: string) { + return nodePath.join('.history', filePath); + } } diff --git a/app/lib/stores/workbench.ts b/app/lib/stores/workbench.ts index e410e768..84d38efa 100644 --- a/app/lib/stores/workbench.ts +++ b/app/lib/stores/workbench.ts @@ -10,18 +10,16 @@ import { FilesStore, type FileMap } from './files'; import { PreviewsStore } from './previews'; import { TerminalStore } from './terminal'; import JSZip from 'jszip'; -import fileSaver from 'file-saver'; +import pkg from 'file-saver'; +const { saveAs } = pkg; import { Octokit, type RestEndpointMethodTypes } from '@octokit/rest'; -import { path } from '~/utils/path'; +import * as nodePath from 'node:path'; import { extractRelativePath } from '~/utils/diff'; import { description } from '~/lib/persistence'; import Cookies from 'js-cookie'; import { createSampler } from '~/utils/sampler'; import type { ActionAlert } from '~/types/actions'; -// Destructure saveAs from the CommonJS module -const { saveAs } = fileSaver; - export interface ArtifactState { id: string; title: string; @@ -34,7 +32,7 @@ export type ArtifactUpdateState = Pick; type Artifacts = MapStore>; -export type WorkbenchViewType = 'code' | 'preview'; +export type WorkbenchViewType = 'code' | 'diff' | 'preview'; export class WorkbenchStore { #previewsStore = new PreviewsStore(webcontainer); @@ -332,7 +330,7 @@ export class WorkbenchStore { if (data.action.type === 'file') { const wc = await webcontainer; - const fullPath = path.join(wc.workdir, data.action.filePath); + const fullPath = nodePath.join(wc.workdir, data.action.filePath); if (this.selectedFile.value !== fullPath) { this.setSelectedFile(fullPath); @@ -437,13 +435,7 @@ export class WorkbenchStore { return syncedFiles; } - async pushToGitHub( - repoName: string, - commitMessage?: string, - githubUsername?: string, - ghToken?: string, - isPrivate: boolean = false, - ) { + async pushToGitHub(repoName: string, commitMessage?: string, githubUsername?: string, ghToken?: string) { try { // Use cookies if username and token are not provided const githubToken = ghToken || Cookies.get('githubToken'); @@ -467,7 +459,7 @@ export class WorkbenchStore { // Repository doesn't exist, so create a new one const { data: newRepo } = await octokit.repos.createForAuthenticatedUser({ name: repoName, - private: isPrivate, + private: false, auto_init: true, }); repo = newRepo; @@ -545,7 +537,7 @@ export class WorkbenchStore { sha: newCommit.sha, }); - return repo.html_url; // Return the URL instead of showing alert + alert(`Repository created and code pushed: ${repo.html_url}`); } catch (error) { console.error('Error pushing to GitHub:', error); throw error; // Rethrow the error for further handling diff --git a/app/styles/diff-view.css b/app/styles/diff-view.css new file mode 100644 index 00000000..e99e8be7 --- /dev/null +++ b/app/styles/diff-view.css @@ -0,0 +1,72 @@ +.diff-panel-content { + scrollbar-width: thin; + scrollbar-color: rgba(155, 155, 155, 0.5) transparent; +} + +.diff-panel-content::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +.diff-panel-content::-webkit-scrollbar-track { + background: transparent; +} + +.diff-panel-content::-webkit-scrollbar-thumb { + background-color: rgba(155, 155, 155, 0.5); + border-radius: 4px; + border: 2px solid transparent; +} + +.diff-panel-content::-webkit-scrollbar-thumb:hover { + background-color: rgba(155, 155, 155, 0.7); +} + +/* Hide scrollbar for the left panel when not hovered */ +.diff-panel:not(:hover) .diff-panel-content::-webkit-scrollbar { + display: none; +} + +.diff-panel:not(:hover) .diff-panel-content { + scrollbar-width: none; +} + +/* Estilos para as linhas de diff */ +.diff-block-added { + @apply bg-green-500/20 border-l-4 border-green-500; +} + +.diff-block-removed { + @apply bg-red-500/20 border-l-4 border-red-500; +} + +/* Melhorar contraste para mudanças */ +.diff-panel-content .group:hover .diff-block-added { + @apply bg-green-500/30; +} + +.diff-panel-content .group:hover .diff-block-removed { + @apply bg-red-500/30; +} + +/* Estilos unificados para ambas as visualizações */ +.diff-line { + @apply flex group min-w-fit transition-colors duration-150; +} + +.diff-line-number { + @apply w-12 shrink-0 pl-2 py-0.5 text-left font-mono text-bolt-elements-textTertiary border-r border-bolt-elements-borderColor bg-bolt-elements-background-depth-1; +} + +.diff-line-content { + @apply px-4 py-0.5 font-mono whitespace-pre flex-1 group-hover:bg-bolt-elements-background-depth-2 text-bolt-elements-textPrimary; +} + +/* Cores específicas para adições/remoções */ +.diff-added { + @apply bg-green-500/20 border-l-4 border-green-500; +} + +.diff-removed { + @apply bg-red-500/20 border-l-4 border-red-500; +} \ No newline at end of file diff --git a/app/types/actions.ts b/app/types/actions.ts index 3543ac7e..cf13abde 100644 --- a/app/types/actions.ts +++ b/app/types/actions.ts @@ -1,3 +1,5 @@ +import type { Change } from 'diff'; + export type ActionType = 'file' | 'shell'; export interface BaseAction { @@ -28,3 +30,15 @@ export interface ActionAlert { content: string; source?: 'terminal' | 'preview'; // Add source to differentiate between terminal and preview errors } + +export interface FileHistory { + originalContent: string; + lastModified: number; + changes: Change[]; + versions: { + timestamp: number; + content: string; + }[]; + // Novo campo para rastrear a origem das mudanças + changeSource?: 'user' | 'auto-save' | 'external'; +} diff --git a/app/utils/getLanguageFromExtension.ts b/app/utils/getLanguageFromExtension.ts new file mode 100644 index 00000000..1dd5d0fd --- /dev/null +++ b/app/utils/getLanguageFromExtension.ts @@ -0,0 +1,24 @@ +export const getLanguageFromExtension = (ext: string): string => { + const map: Record = { + js: "javascript", + jsx: "jsx", + ts: "typescript", + tsx: "tsx", + json: "json", + html: "html", + css: "css", + py: "python", + java: "java", + rb: "ruby", + cpp: "cpp", + c: "c", + cs: "csharp", + go: "go", + rs: "rust", + php: "php", + swift: "swift", + md: "plaintext", + sh: "bash", + }; + return map[ext] || "typescript"; +}; \ No newline at end of file diff --git a/package.json b/package.json index 6bbc999a..f797859d 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,8 @@ "@radix-ui/react-switch": "^1.1.1", "@radix-ui/react-tabs": "^1.1.2", "@radix-ui/react-tooltip": "^1.1.4", + "lucide-react": "^0.474.0", + "next-themes": "^0.4.4", "@remix-run/cloudflare": "^2.15.2", "@remix-run/cloudflare-pages": "^2.15.2", "@remix-run/node": "^2.15.2", diff --git a/vite.config.ts b/vite.config.ts index 01fb3b2e..59ac01cd 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -89,6 +89,7 @@ export default defineConfig((config) => { __PKG_DEV_DEPENDENCIES: JSON.stringify(pkg.devDependencies), __PKG_PEER_DEPENDENCIES: JSON.stringify(pkg.peerDependencies), __PKG_OPTIONAL_DEPENDENCIES: JSON.stringify(pkg.optionalDependencies), + module: {}, }, build: { target: 'esnext', diff --git a/wrangler.toml b/wrangler.toml index 93c41604..addd1007 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -3,4 +3,4 @@ name = "bolt" compatibility_flags = ["nodejs_compat"] compatibility_date = "2024-07-01" pages_build_output_dir = "./build/client" -send_metrics = false +send_metrics = false \ No newline at end of file From 36872ee6a0f688c24674d727f287b69548d99063 Mon Sep 17 00:00:00 2001 From: Toddyclipsgg Date: Sun, 23 Feb 2025 19:34:27 -0300 Subject: [PATCH 2/5] refactor: Enhance Diff View with advanced line and character-level change detection - Improved diff algorithm to detect more granular line and character-level changes - Added support for character-level highlighting in diff view - Simplified diff view mode by removing side-by-side option - Updated component rendering to support more detailed change visualization - Optimized line change detection with improved matching strategy --- app/components/workbench/DiffView.tsx | 429 +++--- app/components/workbench/Workbench.client.tsx | 18 - package.json | 9 +- pnpm-lock.yaml | 1250 +++++++++++++---- 4 files changed, 1199 insertions(+), 507 deletions(-) diff --git a/app/components/workbench/DiffView.tsx b/app/components/workbench/DiffView.tsx index 26b7e260..447eac83 100644 --- a/app/components/workbench/DiffView.tsx +++ b/app/components/workbench/DiffView.tsx @@ -25,6 +25,10 @@ interface DiffBlock { content: string; type: 'added' | 'removed' | 'unchanged'; correspondingLine?: number; + charChanges?: Array<{ + value: string; + type: 'added' | 'removed' | 'unchanged'; + }>; } interface FullscreenButtonProps { @@ -74,93 +78,211 @@ const processChanges = (beforeCode: string, afterCode: string) => { }; } - // Normalizar quebras de linha para evitar falsos positivos - const normalizedBefore = beforeCode.replace(/\r\n/g, '\n'); - const normalizedAfter = afterCode.replace(/\r\n/g, '\n'); + // Normalize line endings and content + const normalizeContent = (content: string): string[] => { + return content + .replace(/\r\n/g, '\n') + .split('\n') + .map(line => line.trimEnd()); + }; - // Dividir em linhas preservando linhas vazias - const beforeLines = normalizedBefore.split('\n'); - const afterLines = normalizedAfter.split('\n'); + const beforeLines = normalizeContent(beforeCode); + const afterLines = normalizeContent(afterCode); - // Se os conteúdos são idênticos após normalização, não há mudanças - if (normalizedBefore === normalizedAfter) { + // Early return if files are identical + if (beforeLines.join('\n') === afterLines.join('\n')) { return { beforeLines, afterLines, hasChanges: false, lineChanges: { before: new Set(), after: new Set() }, - unifiedBlocks: [] + unifiedBlocks: [], + isBinary: false }; } - // Processar as diferenças com configurações otimizadas para detecção por linha - const changes = diffLines(normalizedBefore, normalizedAfter, { - newlineIsToken: false, // Não tratar quebras de linha como tokens separados - ignoreWhitespace: true, // Ignorar diferenças de espaços em branco - ignoreCase: false // Manter sensibilidade a maiúsculas/minúsculas - }); - const lineChanges = { before: new Set(), after: new Set() }; - let beforeLineNumber = 0; - let afterLineNumber = 0; + const unifiedBlocks: DiffBlock[] = []; - const unifiedBlocks = changes.reduce((blocks: DiffBlock[], change) => { - // Dividir o conteúdo em linhas preservando linhas vazias - const lines = change.value.split('\n'); - - if (change.added) { - // Processar linhas adicionadas - const addedBlocks = lines.map((line, i) => { - lineChanges.after.add(afterLineNumber + i); - return { - lineNumber: afterLineNumber + i, - content: line, - type: 'added' as const - }; + // Compare lines directly for more accurate diff + let i = 0, j = 0; + while (i < beforeLines.length || j < afterLines.length) { + if (i < beforeLines.length && j < afterLines.length && beforeLines[i] === afterLines[j]) { + // Unchanged line + unifiedBlocks.push({ + lineNumber: j, + content: afterLines[j], + type: 'unchanged', + correspondingLine: i }); - afterLineNumber += lines.length; - return [...blocks, ...addedBlocks]; - } + i++; + j++; + } else { + // Look ahead for potential matches + let matchFound = false; + const lookAhead = 3; // Number of lines to look ahead - if (change.removed) { - // Processar linhas removidas - const removedBlocks = lines.map((line, i) => { - lineChanges.before.add(beforeLineNumber + i); - return { - lineNumber: beforeLineNumber + i, - content: line, - type: 'removed' as const - }; - }); - beforeLineNumber += lines.length; - return [...blocks, ...removedBlocks]; - } + // Try to find matching lines ahead + for (let k = 1; k <= lookAhead && i + k < beforeLines.length && j + k < afterLines.length; k++) { + if (beforeLines[i + k] === afterLines[j]) { + // Found match in after lines - mark lines as removed + for (let l = 0; l < k; l++) { + lineChanges.before.add(i + l); + unifiedBlocks.push({ + lineNumber: i + l, + content: beforeLines[i + l], + type: 'removed', + correspondingLine: j, + charChanges: [{ value: beforeLines[i + l], type: 'removed' }] + }); + } + i += k; + matchFound = true; + break; + } else if (beforeLines[i] === afterLines[j + k]) { + // Found match in before lines - mark lines as added + for (let l = 0; l < k; l++) { + lineChanges.after.add(j + l); + unifiedBlocks.push({ + lineNumber: j + l, + content: afterLines[j + l], + type: 'added', + correspondingLine: i, + charChanges: [{ value: afterLines[j + l], type: 'added' }] + }); + } + j += k; + matchFound = true; + break; + } + } - // Processar linhas não modificadas - const unchangedBlocks = lines.map((line, i) => { - const block = { - lineNumber: afterLineNumber + i, - content: line, - type: 'unchanged' as const, - correspondingLine: beforeLineNumber + i - }; - return block; - }); - beforeLineNumber += lines.length; - afterLineNumber += lines.length; - return [...blocks, ...unchangedBlocks]; - }, []); + if (!matchFound) { + // No match found - try to find character-level changes + if (i < beforeLines.length && j < afterLines.length) { + const beforeLine = beforeLines[i]; + const afterLine = afterLines[j]; + + // Find common prefix and suffix + let prefixLength = 0; + while (prefixLength < beforeLine.length && + prefixLength < afterLine.length && + beforeLine[prefixLength] === afterLine[prefixLength]) { + prefixLength++; + } + + let suffixLength = 0; + while (suffixLength < beforeLine.length - prefixLength && + suffixLength < afterLine.length - prefixLength && + beforeLine[beforeLine.length - 1 - suffixLength] === + afterLine[afterLine.length - 1 - suffixLength]) { + suffixLength++; + } + + const prefix = beforeLine.slice(0, prefixLength); + const beforeMiddle = beforeLine.slice(prefixLength, beforeLine.length - suffixLength); + const afterMiddle = afterLine.slice(prefixLength, afterLine.length - suffixLength); + const suffix = beforeLine.slice(beforeLine.length - suffixLength); + + if (beforeMiddle || afterMiddle) { + // There are character-level changes + if (beforeMiddle) { + lineChanges.before.add(i); + unifiedBlocks.push({ + lineNumber: i, + content: beforeLine, + type: 'removed', + correspondingLine: j, + charChanges: [ + { value: prefix, type: 'unchanged' }, + { value: beforeMiddle, type: 'removed' }, + { value: suffix, type: 'unchanged' } + ] + }); + i++; + } + if (afterMiddle) { + lineChanges.after.add(j); + unifiedBlocks.push({ + lineNumber: j, + content: afterLine, + type: 'added', + correspondingLine: i - 1, + charChanges: [ + { value: prefix, type: 'unchanged' }, + { value: afterMiddle, type: 'added' }, + { value: suffix, type: 'unchanged' } + ] + }); + j++; + } + } else { + // No character-level changes found, treat as regular line changes + if (i < beforeLines.length) { + lineChanges.before.add(i); + unifiedBlocks.push({ + lineNumber: i, + content: beforeLines[i], + type: 'removed', + correspondingLine: j, + charChanges: [{ value: beforeLines[i], type: 'removed' }] + }); + i++; + } + if (j < afterLines.length) { + lineChanges.after.add(j); + unifiedBlocks.push({ + lineNumber: j, + content: afterLines[j], + type: 'added', + correspondingLine: i - 1, + charChanges: [{ value: afterLines[j], type: 'added' }] + }); + j++; + } + } + } else { + // Handle remaining lines + if (i < beforeLines.length) { + lineChanges.before.add(i); + unifiedBlocks.push({ + lineNumber: i, + content: beforeLines[i], + type: 'removed', + correspondingLine: j, + charChanges: [{ value: beforeLines[i], type: 'removed' }] + }); + i++; + } + if (j < afterLines.length) { + lineChanges.after.add(j); + unifiedBlocks.push({ + lineNumber: j, + content: afterLines[j], + type: 'added', + correspondingLine: i - 1, + charChanges: [{ value: afterLines[j], type: 'added' }] + }); + j++; + } + } + } + } + } + + // Sort blocks by line number + const processedBlocks = unifiedBlocks.sort((a, b) => a.lineNumber - b.lineNumber); return { beforeLines, afterLines, hasChanges: lineChanges.before.size > 0 || lineChanges.after.size > 0, lineChanges, - unifiedBlocks, + unifiedBlocks: processedBlocks, isBinary: false }; } catch (error) { @@ -177,8 +299,14 @@ const processChanges = (beforeCode: string, afterCode: string) => { } }; -const lineNumberStyles = "w-12 shrink-0 pl-2 py-0.5 text-left font-mono text-bolt-elements-textTertiary border-r border-bolt-elements-borderColor bg-bolt-elements-background-depth-1"; -const lineContentStyles = "px-4 py-0.5 font-mono whitespace-pre flex-1 group-hover:bg-bolt-elements-background-depth-2 text-bolt-elements-textPrimary"; +const lineNumberStyles = "w-9 shrink-0 pl-2 py-1 text-left font-mono text-bolt-elements-textTertiary border-r border-bolt-elements-borderColor bg-bolt-elements-background-depth-1"; +const lineContentStyles = "px-1 py-1 font-mono whitespace-pre flex-1 group-hover:bg-bolt-elements-background-depth-2 text-bolt-elements-textPrimary"; +const diffPanelStyles = "h-full overflow-auto diff-panel-content"; +const diffLineStyles = { + added: 'bg-green-500/20 border-l-4 border-green-500', + removed: 'bg-red-500/20 border-l-4 border-red-500', + unchanged: '' +}; const renderContentWarning = (type: 'binary' | 'error') => (
@@ -243,13 +371,15 @@ const CodeLine = memo(({ content, type, highlighter, - language + language, + block }: { lineNumber: number; content: string; type: 'added' | 'removed' | 'unchanged'; highlighter: any; language: string; + block: DiffBlock; }) => { const bgColor = { added: 'bg-green-500/20 border-l-4 border-green-500', @@ -257,13 +387,42 @@ const CodeLine = memo(({ unchanged: '' }[type]; - const highlightedCode = useMemo(() => { - if (!highlighter) return content; - return highlighter.codeToHtml(content, { - lang: language, - theme: 'github-dark' - }).replace(/<\/?pre[^>]*>/g, '').replace(/<\/?code[^>]*>/g, ''); - }, [content, highlighter, language]); + const renderContent = () => { + if (type === 'unchanged' || !block.charChanges) { + const highlightedCode = highlighter ? + highlighter.codeToHtml(content, { lang: language, theme: 'github-dark' }) + .replace(/<\/?pre[^>]*>/g, '') + .replace(/<\/?code[^>]*>/g, '') + : content; + return ; + } + + return ( + <> + {block.charChanges.map((change, index) => { + const changeClass = { + added: 'text-green-500 bg-green-500/20', + removed: 'text-red-500 bg-red-500/20', + unchanged: '' + }[change.type]; + + const highlightedCode = highlighter ? + highlighter.codeToHtml(change.value, { lang: language, theme: 'github-dark' }) + .replace(/<\/?pre[^>]*>/g, '') + .replace(/<\/?code[^>]*>/g, '') + : change.value; + + return ( + + ); + })} + + ); + }; return (
@@ -274,7 +433,7 @@ const CodeLine = memo(({ {type === 'removed' && '-'} {type === 'unchanged' && ' '} - + {renderContent()}
); @@ -380,9 +539,9 @@ const InlineDiffComparison = memo(({ beforeCode, afterCode, filename, language, beforeCode={beforeCode} afterCode={afterCode} /> -
+
{hasChanges ? ( -
+
{unifiedBlocks.map((block, index) => ( ))}
@@ -407,103 +567,13 @@ const InlineDiffComparison = memo(({ beforeCode, afterCode, filename, language, ); }); -const SideBySideComparison = memo(({ - beforeCode, - afterCode, - language, - filename, - lightTheme, - darkTheme, -}: CodeComparisonProps) => { - const [isFullscreen, setIsFullscreen] = useState(false); - const [highlighter, setHighlighter] = useState(null); - - const toggleFullscreen = useCallback(() => { - setIsFullscreen(prev => !prev); - }, []); - - const { beforeLines, afterLines, hasChanges, lineChanges, isBinary, error } = useProcessChanges(beforeCode, afterCode); - - useEffect(() => { - getHighlighter({ - themes: ['github-dark'], - langs: ['typescript', 'javascript', 'json', 'html', 'css', 'jsx', 'tsx'] - }).then(setHighlighter); - }, []); - - if (isBinary || error) return renderContentWarning(isBinary ? 'binary' : 'error'); - - const renderCode = (code: string) => { - if (!highlighter) return code; - const highlightedCode = highlighter.codeToHtml(code, { - lang: language, - theme: 'github-dark' - }); - return highlightedCode.replace(/<\/?pre[^>]*>/g, '').replace(/<\/?code[^>]*>/g, ''); - }; - - return ( - -
- -
- {hasChanges ? ( -
-
- {beforeLines.map((line, index) => ( -
-
{index + 1}
-
- - {lineChanges.before.has(index) ? '-' : ' '} - - -
-
- ))} -
-
- {afterLines.map((line, index) => ( -
-
{index + 1}
-
- - {lineChanges.after.has(index) ? '+' : ' '} - - -
-
- ))} -
-
- ) : ( - - )} -
-
-
- ); -}); - interface DiffViewProps { fileHistory: Record; setFileHistory: React.Dispatch>>; - diffViewMode: 'inline' | 'side'; actionRunner: ActionRunner; } -export const DiffView = memo(({ fileHistory, setFileHistory, diffViewMode, actionRunner }: DiffViewProps) => { +export const DiffView = memo(({ fileHistory, setFileHistory, actionRunner }: DiffViewProps) => { const files = useStore(workbenchStore.files) as FileMap; const selectedFile = useStore(workbenchStore.selectedFile); const currentDocument = useStore(workbenchStore.currentDocument) as EditorDocument; @@ -612,25 +682,14 @@ export const DiffView = memo(({ fileHistory, setFileHistory, diffViewMode, actio try { return (
- {diffViewMode === 'inline' ? ( - - ) : ( - - )} +
); } catch (error) { diff --git a/app/components/workbench/Workbench.client.tsx b/app/components/workbench/Workbench.client.tsx index 39d10b9d..e5edfcec 100644 --- a/app/components/workbench/Workbench.client.tsx +++ b/app/components/workbench/Workbench.client.tsx @@ -74,13 +74,9 @@ const workbenchVariants = { const FileModifiedDropdown = memo(({ fileHistory, onSelectFile, - diffViewMode, - toggleDiffViewMode, }: { fileHistory: Record, onSelectFile: (filePath: string) => void, - diffViewMode: 'inline' | 'side', - toggleDiffViewMode: () => void, }) => { const modifiedFiles = Object.entries(fileHistory); const hasChanges = modifiedFiles.length > 0; @@ -251,12 +247,6 @@ const FileModifiedDropdown = memo(({ )} -
); }); @@ -272,7 +262,6 @@ export const Workbench = memo(({ const [isSyncing, setIsSyncing] = useState(false); const [isPushDialogOpen, setIsPushDialogOpen] = useState(false); - const [diffViewMode, setDiffViewMode] = useState<'inline' | 'side'>('inline'); const [fileHistory, setFileHistory] = useState>({}); const modifiedFiles = Array.from(useStore(workbenchStore.unsavedFiles).keys()); @@ -343,10 +332,6 @@ export const Workbench = memo(({ workbenchStore.currentView.set('diff'); }, []); - const toggleDiffViewMode = useCallback(() => { - setDiffViewMode(prev => prev === 'inline' ? 'side' : 'inline'); - }, []); - return ( chatStarted && ( )} diff --git a/package.json b/package.json index f797859d..d7dc2b5b 100644 --- a/package.json +++ b/package.json @@ -74,12 +74,11 @@ "@radix-ui/react-switch": "^1.1.1", "@radix-ui/react-tabs": "^1.1.2", "@radix-ui/react-tooltip": "^1.1.4", - "lucide-react": "^0.474.0", - "next-themes": "^0.4.4", "@remix-run/cloudflare": "^2.15.2", "@remix-run/cloudflare-pages": "^2.15.2", "@remix-run/node": "^2.15.2", "@remix-run/react": "^2.15.2", + "@tanstack/react-virtual": "^3.13.0", "@types/react-beautiful-dnd": "^13.1.8", "@uiw/codemirror-theme-vscode": "^4.23.6", "@unocss/reset": "^0.61.9", @@ -105,7 +104,9 @@ "js-cookie": "^3.0.5", "jspdf": "^2.5.2", "jszip": "^3.10.1", + "lucide-react": "^0.474.0", "nanostores": "^0.10.3", + "next-themes": "^0.4.4", "ollama-ai-provider": "^0.15.2", "path-browserify": "^1.0.1", "react": "^18.3.1", @@ -135,6 +136,8 @@ "@iconify-json/ph": "^1.2.1", "@iconify/types": "^2.0.0", "@remix-run/dev": "^2.15.2", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.2.0", "@types/diff": "^5.2.3", "@types/dom-speech-recognition": "^0.0.4", "@types/file-saver": "^2.0.7", @@ -142,9 +145,11 @@ "@types/path-browserify": "^1.0.3", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", + "@vitejs/plugin-react": "^4.3.4", "fast-glob": "^3.3.2", "husky": "9.1.7", "is-ci": "^3.0.1", + "jsdom": "^26.0.0", "node-fetch": "^3.3.2", "pnpm": "^9.14.4", "prettier": "^3.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1bbe2c76..d2ee571c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,7 +82,7 @@ importers: version: 6.36.2 '@headlessui/react': specifier: ^2.2.0 - version: 2.2.0(react-dom@18.3.1)(react@18.3.1) + version: 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@iconify-json/svg-spinners': specifier: ^1.2.1 version: 1.2.2 @@ -103,43 +103,43 @@ importers: version: 0.0.5(zod@3.24.1) '@phosphor-icons/react': specifier: ^2.1.7 - version: 2.1.7(react-dom@18.3.1)(react@18.3.1) + version: 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-collapsible': specifier: ^1.0.3 - version: 1.1.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-context-menu': specifier: ^2.2.2 - version: 2.2.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 2.2.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-dialog': specifier: ^1.1.5 - version: 1.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-dropdown-menu': specifier: ^2.1.6 - version: 2.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 2.1.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-label': specifier: ^2.1.1 - version: 2.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 2.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-popover': specifier: ^1.1.5 - version: 1.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-progress': specifier: ^1.0.3 - version: 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-scroll-area': specifier: ^1.2.2 - version: 1.2.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 1.2.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-separator': specifier: ^1.1.0 - version: 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-switch': specifier: ^1.1.1 - version: 1.1.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tabs': specifier: ^1.1.2 - version: 1.1.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tooltip': specifier: ^1.1.4 - version: 1.1.8(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + version: 1.1.8(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@remix-run/cloudflare': specifier: ^2.15.2 version: 2.15.3(@cloudflare/workers-types@4.20250204.0)(typescript@5.7.3) @@ -151,7 +151,10 @@ importers: version: 2.15.3(typescript@5.7.3) '@remix-run/react': specifier: ^2.15.2 - version: 2.15.3(react-dom@18.3.1)(react@18.3.1)(typescript@5.7.3) + version: 2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3) + '@tanstack/react-virtual': + specifier: ^3.13.0 + version: 3.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/react-beautiful-dnd': specifier: ^13.1.8 version: 13.1.8 @@ -202,7 +205,7 @@ importers: version: 2.0.5 framer-motion: specifier: ^11.12.0 - version: 11.18.2(react-dom@18.3.1)(react@18.3.1) + version: 11.18.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) ignore: specifier: ^6.0.2 version: 6.0.2 @@ -227,9 +230,15 @@ importers: jszip: specifier: ^3.10.1 version: 3.10.1 + lucide-react: + specifier: ^0.474.0 + version: 0.474.0(react@18.3.1) nanostores: specifier: ^0.10.3 version: 0.10.3 + next-themes: + specifier: ^0.4.4 + version: 0.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) ollama-ai-provider: specifier: ^0.15.2 version: 0.15.2(zod@3.24.1) @@ -241,13 +250,13 @@ importers: version: 18.3.1 react-beautiful-dnd: specifier: ^13.1.1 - version: 13.1.1(react-dom@18.3.1)(react@18.3.1) + version: 13.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-chartjs-2: specifier: ^5.3.0 version: 5.3.0(chart.js@4.4.7)(react@18.3.1) react-dnd: specifier: ^16.0.1 - version: 16.0.1(@types/react@18.3.18)(react@18.3.1) + version: 16.0.1(@types/hoist-non-react-statics@3.3.6)(@types/node@22.13.1)(@types/react@18.3.18)(react@18.3.1) react-dnd-html5-backend: specifier: ^16.0.1 version: 16.0.1 @@ -256,7 +265,7 @@ importers: version: 18.3.1(react@18.3.1) react-hotkeys-hook: specifier: ^4.6.1 - version: 4.6.1(react-dom@18.3.1)(react@18.3.1) + version: 4.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-icons: specifier: ^5.4.0 version: 5.4.0(react@18.3.1) @@ -265,10 +274,10 @@ importers: version: 9.0.3(@types/react@18.3.18)(react@18.3.1) react-resizable-panels: specifier: ^2.1.7 - version: 2.1.7(react-dom@18.3.1)(react@18.3.1) + version: 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-toastify: specifier: ^10.0.6 - version: 10.0.6(react-dom@18.3.1)(react@18.3.1) + version: 10.0.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rehype-raw: specifier: ^7.0.0 version: 7.0.0 @@ -280,10 +289,10 @@ importers: version: 4.0.1 remix-island: specifier: ^0.2.0 - version: 0.2.0(@remix-run/react@2.15.3)(@remix-run/server-runtime@2.15.3)(react-dom@18.3.1)(react@18.3.1) + version: 0.2.0(@remix-run/react@2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3))(@remix-run/server-runtime@2.15.3(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) remix-utils: specifier: ^7.7.0 - version: 7.7.0(@remix-run/cloudflare@2.15.3)(@remix-run/node@2.15.3)(@remix-run/react@2.15.3)(react@18.3.1)(zod@3.24.1) + version: 7.7.0(@remix-run/cloudflare@2.15.3(@cloudflare/workers-types@4.20250204.0)(typescript@5.7.3))(@remix-run/node@2.15.3(typescript@5.7.3))(@remix-run/react@2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3))(@remix-run/router@1.22.0)(react@18.3.1)(zod@3.24.1) shiki: specifier: ^1.24.0 version: 1.29.2 @@ -295,11 +304,11 @@ importers: version: 5.0.0 zustand: specifier: ^5.0.3 - version: 5.0.3(@types/react@18.3.18)(react@18.3.1) + version: 5.0.3(@types/react@18.3.18)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)) devDependencies: '@blitz/eslint-plugin': specifier: 0.1.0 - version: 0.1.0(prettier@3.5.0)(typescript@5.7.3) + version: 0.1.0(jiti@1.21.7)(prettier@3.5.0)(typescript@5.7.3) '@cloudflare/workers-types': specifier: ^4.20241127.0 version: 4.20250204.0 @@ -311,7 +320,13 @@ importers: version: 2.0.0 '@remix-run/dev': specifier: ^2.15.2 - version: 2.15.3(@remix-run/react@2.15.3)(sass-embedded@1.83.4)(typescript@5.7.3)(vite@5.4.14)(wrangler@3.108.0) + version: 2.15.3(@remix-run/react@2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3))(@types/node@22.13.1)(sass-embedded@1.83.4)(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4))(wrangler@3.108.0(@cloudflare/workers-types@4.20250204.0)) + '@testing-library/jest-dom': + specifier: ^6.6.3 + version: 6.6.3 + '@testing-library/react': + specifier: ^16.2.0 + version: 16.2.0(@testing-library/dom@10.4.0)(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/diff': specifier: ^5.2.3 version: 5.2.3 @@ -333,6 +348,9 @@ importers: '@types/react-dom': specifier: ^18.3.1 version: 18.3.5(@types/react@18.3.18) + '@vitejs/plugin-react': + specifier: ^4.3.4 + version: 4.3.4(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)) fast-glob: specifier: ^3.3.2 version: 3.3.3 @@ -342,6 +360,9 @@ importers: is-ci: specifier: ^3.0.1 version: 3.0.1 + jsdom: + specifier: ^26.0.0 + version: 26.0.0 node-fetch: specifier: ^3.3.2 version: 3.3.2 @@ -362,22 +383,22 @@ importers: version: 11.0.5 unocss: specifier: ^0.61.9 - version: 0.61.9(postcss@8.5.2)(rollup@3.29.5)(vite@5.4.14) + version: 0.61.9(postcss@8.5.2)(rollup@3.29.5)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)) vite: specifier: ^5.4.11 - version: 5.4.14(sass-embedded@1.83.4) + version: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) vite-plugin-node-polyfills: specifier: ^0.22.0 - version: 0.22.0(rollup@3.29.5)(vite@5.4.14) + version: 0.22.0(rollup@3.29.5)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)) vite-plugin-optimize-css-modules: specifier: ^1.1.0 - version: 1.2.0(vite@5.4.14) + version: 1.2.0(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)) vite-tsconfig-paths: specifier: ^4.3.2 - version: 4.3.2(typescript@5.7.3)(vite@5.4.14) + version: 4.3.2(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)) vitest: specifier: ^2.1.7 - version: 2.1.9(sass-embedded@1.83.4) + version: 2.1.9(@types/node@22.13.1)(jsdom@26.0.0)(sass-embedded@1.83.4) wrangler: specifier: ^3.91.0 version: 3.108.0(@cloudflare/workers-types@4.20250204.0) @@ -387,6 +408,9 @@ importers: packages: + '@adobe/css-tools@4.4.2': + resolution: {integrity: sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==} + '@ai-sdk/amazon-bedrock@1.0.6': resolution: {integrity: sha512-EdbLjy/r9W6ds5/xbkfklr5C9y3PmGh2eXqhd3xyURq0oSoB9ukoOa9jvPTb4b3jS6l4R7yXYJvTZiAkkefUeQ==} engines: {node: '>=18'} @@ -534,6 +558,9 @@ packages: '@antfu/utils@8.1.0': resolution: {integrity: sha512-XPR7Jfwp0FFl/dFYPX8ZjpmU4/1mIXTjnZ1ba48BLMyKOV62/tiRjdsFcPs2hsYcSud4tzk7w3a3LjX8Fu3huA==} + '@asamuzakjp/css-color@2.8.3': + resolution: {integrity: sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw==} + '@aws-crypto/crc32@5.2.0': resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} engines: {node: '>=16.0.0'} @@ -750,6 +777,18 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-jsx-self@7.25.9': + resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.25.9': + resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-typescript@7.26.8': resolution: {integrity: sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==} engines: {node: '>=6.9.0'} @@ -880,6 +919,34 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} + '@csstools/color-helpers@5.0.2': + resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.2': + resolution: {integrity: sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.4 + '@csstools/css-tokenizer': ^3.0.3 + + '@csstools/css-color-parser@3.0.8': + resolution: {integrity: sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.4 + '@csstools/css-tokenizer': ^3.0.3 + + '@csstools/css-parser-algorithms@3.0.4': + resolution: {integrity: sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.3 + + '@csstools/css-tokenizer@3.0.3': + resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} + engines: {node: '>=18'} + '@emnapi/runtime@1.3.1': resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} @@ -2734,9 +2801,47 @@ packages: '@tanstack/virtual-core@3.13.0': resolution: {integrity: sha512-NBKJP3OIdmZY3COJdWkSonr50FMVIi+aj5ZJ7hI/DTpEKg2RMfo/KvP8A3B/zOSpMgIe52B5E2yn7rryULzA6g==} + '@testing-library/dom@10.4.0': + resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.6.3': + resolution: {integrity: sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/react@16.2.0': + resolution: {integrity: sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@types/acorn@4.0.6': resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} @@ -2987,6 +3092,12 @@ packages: '@vanilla-extract/private@1.0.6': resolution: {integrity: sha512-ytsG/JLweEjw7DBuZ/0JCN4WAQgM9erfSTdS1NQY778hFQSZ6cfCDEZZ0sgVm4k54uNz6ImKB33AYvSR//fjxw==} + '@vitejs/plugin-react@4.3.4': + resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + '@vitest/expect@2.1.9': resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==} @@ -3064,6 +3175,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@7.1.3: + resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + engines: {node: '>= 14'} + aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} @@ -3095,6 +3210,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} @@ -3113,6 +3232,13 @@ packages: resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} engines: {node: '>=10'} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} @@ -3136,6 +3262,9 @@ packages: async-lock@1.4.1: resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + atob@2.1.2: resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} engines: {node: '>= 4.5.0'} @@ -3300,6 +3429,10 @@ packages: resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} engines: {node: '>=12'} + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -3393,6 +3526,10 @@ packages: colorjs.io@0.5.2: resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -3494,11 +3631,18 @@ packages: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true + cssstyle@4.2.1: + resolution: {integrity: sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==} + engines: {node: '>=18'} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -3513,6 +3657,10 @@ packages: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + date-fns@3.6.0: resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==} @@ -3533,6 +3681,9 @@ packages: supports-color: optional: true + decimal.js@10.5.0: + resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} + decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} @@ -3576,6 +3727,10 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -3620,6 +3775,12 @@ packages: dnd-core@16.0.1: resolution: {integrity: sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + domain-browser@4.22.0: resolution: {integrity: sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==} engines: {node: '>=10'} @@ -3699,6 +3860,10 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + esbuild-plugins-node-modules-polyfill@1.6.8: resolution: {integrity: sha512-bRB4qbgUDWrdY1eMk123KiaCSW9VzQ+QLZrmU7D//cCFkmksPd9mUMpmWoFK/rxjIeTfTSOpKCoGoimlvI+AWw==} engines: {node: '>=14.0.0'} @@ -3979,6 +4144,10 @@ packages: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + format@0.2.2: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} @@ -4182,6 +4351,10 @@ packages: resolution: {integrity: sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + html-url-attributes@3.0.1: resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} @@ -4196,9 +4369,17 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + https-browserify@1.0.0: resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -4212,6 +4393,10 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + icss-utils@5.1.0: resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} engines: {node: ^10 || ^12 || >= 14} @@ -4345,6 +4530,9 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-reference@3.0.3: resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} @@ -4415,6 +4603,15 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + jsdom@26.0.0: + resolution: {integrity: sha512-BZYDGVAIriBWTpIxYzrXjv3E/4u8+/pSG5bQdIYCbNCGOvsPkDQfTVLAIXAf9ETdCpduCVTkDe2NNZ8NIwUVzw==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} @@ -4536,6 +4733,15 @@ packages: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} + lucide-react@0.474.0: + resolution: {integrity: sha512-CmghgHkh0OJNmxGKWc0qfPJCYHASPMVSyGY8fj3xgk4v84ItqDg64JNKFZn5hC6E0vHi6gxnbCgwhyVB09wQtA==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} @@ -4871,6 +5077,10 @@ packages: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + miniflare@3.20250204.0: resolution: {integrity: sha512-f7tezEkOvVRVHIVul2EbTyKvWJCXpTDRAOxTxtD4N92+YI8PC2P8AvO4Z30vlN61r5Pje33fTBG8G1fEwSZIqQ==} engines: {node: '>=16.13'} @@ -4986,6 +5196,12 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} + next-themes@0.4.4: + resolution: {integrity: sha512-LDQ2qIOJF0VnuVrrMSMLrWGjRMkq+0mpgl6e0juCLqdJ+oo8Q84JRWT6Wh11VDQKkMMe+dVzDKLWs5n87T+PkQ==} + peerDependencies: + react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc + react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc + node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -5032,6 +5248,9 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} + nwsapi@2.2.16: + resolution: {integrity: sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -5306,6 +5525,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-ms@7.0.1: resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==} engines: {node: '>=10'} @@ -5545,6 +5768,10 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + redux@4.2.1: resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} @@ -5703,6 +5930,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -5851,6 +6081,10 @@ packages: engines: {node: '>=16.0.0'} hasBin: true + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -6052,6 +6286,10 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -6089,6 +6327,9 @@ packages: peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + sync-child-process@1.0.2: resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==} engines: {node: '>=16.0.0'} @@ -6161,6 +6402,13 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} + tldts-core@6.1.78: + resolution: {integrity: sha512-jS0svNsB99jR6AJBmfmEWuKIgz91Haya91Z43PATaeHJ24BkMoNRb/jlaD37VYjb0mYf6gRL/HOnvS1zEnYBiw==} + + tldts@6.1.78: + resolution: {integrity: sha512-fSgYrW0ITH0SR/CqKMXIruYIPpNu5aDgUp22UhYoSrnUQwc7SBqifEBFNce7AAcygUPBo6a/gbtcguWdmko4RQ==} + hasBin: true + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -6176,6 +6424,14 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tough-cookie@5.1.1: + resolution: {integrity: sha512-Ek7HndSVkp10hmHP9V4qZO1u+pn1RU5sI0Fw+jCU3lyvuMZcgqsNgc6CmJJZyByK4Vm/qotGRJlfgAX8q+4JiA==} + engines: {node: '>=16'} + + tr46@5.0.0: + resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} + engines: {node: '>=18'} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -6532,6 +6788,10 @@ packages: w3c-keyname@2.2.8: resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} @@ -6545,6 +6805,22 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.1.1: + resolution: {integrity: sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ==} + engines: {node: '>=18'} + which-typed-array@1.1.18: resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} engines: {node: '>= 0.4'} @@ -6618,6 +6894,13 @@ packages: utf-8-validate: optional: true + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -6674,6 +6957,8 @@ packages: snapshots: + '@adobe/css-tools@4.4.2': {} + '@ai-sdk/amazon-bedrock@1.0.6(zod@3.24.1)': dependencies: '@ai-sdk/provider': 1.0.3 @@ -6733,6 +7018,7 @@ snapshots: eventsource-parser: 1.1.2 nanoid: 3.3.6 secure-json-parse: 2.7.0 + optionalDependencies: zod: 3.24.1 '@ai-sdk/provider-utils@1.0.20(zod@3.24.1)': @@ -6741,6 +7027,7 @@ snapshots: eventsource-parser: 1.1.2 nanoid: 3.3.6 secure-json-parse: 2.7.0 + optionalDependencies: zod: 3.24.1 '@ai-sdk/provider-utils@1.0.9(zod@3.24.1)': @@ -6749,6 +7036,7 @@ snapshots: eventsource-parser: 1.1.2 nanoid: 3.3.6 secure-json-parse: 2.7.0 + optionalDependencies: zod: 3.24.1 '@ai-sdk/provider-utils@2.0.5(zod@3.24.1)': @@ -6757,6 +7045,7 @@ snapshots: eventsource-parser: 3.0.0 nanoid: 3.3.8 secure-json-parse: 2.7.0 + optionalDependencies: zod: 3.24.1 '@ai-sdk/provider-utils@2.1.6(zod@3.24.1)': @@ -6765,6 +7054,7 @@ snapshots: eventsource-parser: 3.0.0 nanoid: 3.3.8 secure-json-parse: 2.7.0 + optionalDependencies: zod: 3.24.1 '@ai-sdk/provider@0.0.12': @@ -6791,17 +7081,19 @@ snapshots: dependencies: '@ai-sdk/provider-utils': 2.1.6(zod@3.24.1) '@ai-sdk/ui-utils': 1.1.11(zod@3.24.1) - react: 18.3.1 swr: 2.3.2(react@18.3.1) throttleit: 2.1.0 + optionalDependencies: + react: 18.3.1 zod: 3.24.1 '@ai-sdk/ui-utils@1.1.11(zod@3.24.1)': dependencies: '@ai-sdk/provider': 1.0.7 '@ai-sdk/provider-utils': 2.1.6(zod@3.24.1) - zod: 3.24.1 zod-to-json-schema: 3.24.1(zod@3.24.1) + optionalDependencies: + zod: 3.24.1 '@ampproject/remapping@2.3.0': dependencies: @@ -6817,6 +7109,14 @@ snapshots: '@antfu/utils@8.1.0': {} + '@asamuzakjp/css-color@2.8.3': + dependencies: + '@csstools/css-calc': 2.1.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-color-parser': 3.0.8(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + lru-cache: 10.4.3 + '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 @@ -7314,6 +7614,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-transform-typescript@7.26.8(@babel/core@7.26.8)': dependencies: '@babel/core': 7.26.8 @@ -7363,19 +7673,19 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@blitz/eslint-plugin@0.1.0(prettier@3.5.0)(typescript@5.7.3)': + '@blitz/eslint-plugin@0.1.0(jiti@1.21.7)(prettier@3.5.0)(typescript@5.7.3)': dependencies: - '@stylistic/eslint-plugin-ts': 2.13.0(eslint@9.20.1)(typescript@5.7.3) - '@typescript-eslint/eslint-plugin': 8.24.0(@typescript-eslint/parser@8.24.0)(eslint@9.20.1)(typescript@5.7.3) - '@typescript-eslint/parser': 8.24.0(eslint@9.20.1)(typescript@5.7.3) - '@typescript-eslint/utils': 8.24.0(eslint@9.20.1)(typescript@5.7.3) + '@stylistic/eslint-plugin-ts': 2.13.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) + '@typescript-eslint/eslint-plugin': 8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3))(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) + '@typescript-eslint/parser': 8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) common-tags: 1.8.2 - eslint: 9.20.1 - eslint-config-prettier: 9.1.0(eslint@9.20.1) - eslint-plugin-jsonc: 2.19.1(eslint@9.20.1) - eslint-plugin-prettier: 5.2.3(eslint-config-prettier@9.1.0)(eslint@9.20.1)(prettier@3.5.0) + eslint: 9.20.1(jiti@1.21.7) + eslint-config-prettier: 9.1.0(eslint@9.20.1(jiti@1.21.7)) + eslint-plugin-jsonc: 2.19.1(eslint@9.20.1(jiti@1.21.7)) + eslint-plugin-prettier: 5.2.3(eslint-config-prettier@9.1.0(eslint@9.20.1(jiti@1.21.7)))(eslint@9.20.1(jiti@1.21.7))(prettier@3.5.0) globals: 15.14.0 - typescript-eslint: 8.24.0(eslint@9.20.1)(typescript@5.7.3) + typescript-eslint: 8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) transitivePeerDependencies: - '@eslint/json' - '@types/eslint' @@ -7542,6 +7852,26 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 + '@csstools/color-helpers@5.0.2': {} + + '@csstools/css-calc@2.1.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + + '@csstools/css-color-parser@3.0.8(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': + dependencies: + '@csstools/color-helpers': 5.0.2 + '@csstools/css-calc': 2.1.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + + '@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3)': + dependencies: + '@csstools/css-tokenizer': 3.0.3 + + '@csstools/css-tokenizer@3.0.3': {} + '@emnapi/runtime@1.3.1': dependencies: tslib: 2.8.1 @@ -7832,9 +8162,9 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true - '@eslint-community/eslint-utils@4.4.1(eslint@9.20.1)': + '@eslint-community/eslint-utils@4.4.1(eslint@9.20.1(jiti@1.21.7))': dependencies: - eslint: 9.20.1 + eslint: 9.20.1(jiti@1.21.7) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -7889,15 +8219,15 @@ snapshots: '@floating-ui/core': 1.6.9 '@floating-ui/utils': 0.2.9 - '@floating-ui/react-dom@2.1.2(react-dom@18.3.1)(react@18.3.1)': + '@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/dom': 1.6.13 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@floating-ui/react@0.26.28(react-dom@18.3.1)(react@18.3.1)': + '@floating-ui/react@0.26.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1)(react@18.3.1) + '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@floating-ui/utils': 0.2.9 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -7905,12 +8235,12 @@ snapshots: '@floating-ui/utils@0.2.9': {} - '@headlessui/react@2.2.0(react-dom@18.3.1)(react@18.3.1)': + '@headlessui/react@2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/react': 0.26.28(react-dom@18.3.1)(react@18.3.1) - '@react-aria/focus': 3.19.1(react-dom@18.3.1)(react@18.3.1) - '@react-aria/interactions': 3.23.0(react-dom@18.3.1)(react@18.3.1) - '@tanstack/react-virtual': 3.13.0(react-dom@18.3.1)(react@18.3.1) + '@floating-ui/react': 0.26.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-aria/focus': 3.19.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-aria/interactions': 3.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/react-virtual': 3.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -8271,7 +8601,7 @@ snapshots: '@opentelemetry/api@1.9.0': {} - '@phosphor-icons/react@2.1.7(react-dom@18.3.1)(react@18.3.1)': + '@phosphor-icons/react@2.1.7(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) @@ -8287,400 +8617,436 @@ snapshots: '@radix-ui/primitive@1.1.1': {} - '@radix-ui/react-arrow@1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-arrow@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-collapsible@1.1.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-collapsible@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-id': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-collection@1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-collection@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.1.2(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) '@radix-ui/react-compose-refs@1.1.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 - '@radix-ui/react-context-menu@2.2.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-context-menu@2.2.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-menu': 2.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-menu': 2.1.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) '@radix-ui/react-context@1.1.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 - '@radix-ui/react-dialog@1.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-dialog@1.1.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-id': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.1.2(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-remove-scroll: 2.6.3(@types/react@18.3.18)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) '@radix-ui/react-direction@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 - '@radix-ui/react-dismissable-layer@1.1.5(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-dismissable-layer@1.1.5(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-dropdown-menu@2.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-dropdown-menu@2.1.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-id': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-menu': 2.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-menu': 2.1.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) '@radix-ui/react-focus-guards@1.1.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 - '@radix-ui/react-focus-scope@1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-focus-scope@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) '@radix-ui/react-id@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 react: 18.3.1 - - '@radix-ui/react-label@2.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': - dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + optionalDependencies: '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) + + '@radix-ui/react-label@2.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-menu@2.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-menu@2.1.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-direction': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-id': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.1.2(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-remove-scroll: 2.6.3(@types/react@18.3.18)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-popover@1.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-popover@1.1.6(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-id': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.1.2(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-remove-scroll: 2.6.3(@types/react@18.3.18)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-popper@1.2.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-popper@1.2.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-arrow': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-rect': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/rect': 1.1.0 - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-portal@1.1.4(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-portal@1.1.4(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-presence@1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-presence@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-primitive@2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-primitive@2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-slot': 1.1.2(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-progress@1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-progress@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-roving-focus@1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-roving-focus@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-direction': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-id': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-scroll-area@1.2.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-scroll-area@1.2.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.0 '@radix-ui/primitive': 1.1.1 '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-direction': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-separator@1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-separator@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) '@radix-ui/react-slot@1.1.2(@types/react@18.3.18)(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 - '@radix-ui/react-switch@1.1.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-switch@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-tabs@1.1.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-tabs@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-direction': 1.1.0(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-id': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-tooltip@1.1.8(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-tooltip@1.1.8(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-id': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.1.2(@types/react@18.3.18)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) + '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 '@radix-ui/react-use-previous@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 '@radix-ui/react-use-rect@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: '@radix-ui/rect': 1.1.0 - '@types/react': 18.3.18 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 '@radix-ui/react-use-size@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 react: 18.3.1 - - '@radix-ui/react-visually-hidden@1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)': - dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + optionalDependencies: '@types/react': 18.3.18 - '@types/react-dom': 18.3.5(@types/react@18.3.18) + + '@radix-ui/react-visually-hidden@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) '@radix-ui/rect@1.1.0': {} - '@react-aria/focus@3.19.1(react-dom@18.3.1)(react@18.3.1)': + '@react-aria/focus@3.19.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@react-aria/interactions': 3.23.0(react-dom@18.3.1)(react@18.3.1) - '@react-aria/utils': 3.27.0(react-dom@18.3.1)(react@18.3.1) + '@react-aria/interactions': 3.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-aria/utils': 3.27.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/shared': 3.27.0(react@18.3.1) '@swc/helpers': 0.5.15 clsx: 2.1.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@react-aria/interactions@3.23.0(react-dom@18.3.1)(react@18.3.1)': + '@react-aria/interactions@3.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/ssr': 3.9.7(react@18.3.1) - '@react-aria/utils': 3.27.0(react-dom@18.3.1)(react@18.3.1) + '@react-aria/utils': 3.27.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/shared': 3.27.0(react@18.3.1) '@swc/helpers': 0.5.15 react: 18.3.1 @@ -8691,7 +9057,7 @@ snapshots: '@swc/helpers': 0.5.15 react: 18.3.1 - '@react-aria/utils@3.27.0(react-dom@18.3.1)(react@18.3.1)': + '@react-aria/utils@3.27.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/ssr': 3.9.7(react@18.3.1) '@react-stately/utils': 3.10.5(react@18.3.1) @@ -8720,6 +9086,7 @@ snapshots: dependencies: '@cloudflare/workers-types': 4.20250204.0 '@remix-run/cloudflare': 2.15.3(@cloudflare/workers-types@4.20250204.0)(typescript@5.7.3) + optionalDependencies: typescript: 5.7.3 '@remix-run/cloudflare@2.15.3(@cloudflare/workers-types@4.20250204.0)(typescript@5.7.3)': @@ -8727,9 +9094,10 @@ snapshots: '@cloudflare/kv-asset-handler': 0.1.3 '@cloudflare/workers-types': 4.20250204.0 '@remix-run/server-runtime': 2.15.3(typescript@5.7.3) + optionalDependencies: typescript: 5.7.3 - '@remix-run/dev@2.15.3(@remix-run/react@2.15.3)(sass-embedded@1.83.4)(typescript@5.7.3)(vite@5.4.14)(wrangler@3.108.0)': + '@remix-run/dev@2.15.3(@remix-run/react@2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3))(@types/node@22.13.1)(sass-embedded@1.83.4)(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4))(wrangler@3.108.0(@cloudflare/workers-types@4.20250204.0))': dependencies: '@babel/core': 7.26.8 '@babel/generator': 7.26.8 @@ -8742,11 +9110,11 @@ snapshots: '@mdx-js/mdx': 2.3.0 '@npmcli/package-json': 4.0.1 '@remix-run/node': 2.15.3(typescript@5.7.3) - '@remix-run/react': 2.15.3(react-dom@18.3.1)(react@18.3.1)(typescript@5.7.3) + '@remix-run/react': 2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3) '@remix-run/router': 1.22.0 '@remix-run/server-runtime': 2.15.3(typescript@5.7.3) '@types/mdx': 2.0.13 - '@vanilla-extract/integration': 6.5.0(sass-embedded@1.83.4) + '@vanilla-extract/integration': 6.5.0(@types/node@22.13.1)(sass-embedded@1.83.4) arg: 5.0.2 cacache: 17.1.4 chalk: 4.1.2 @@ -8784,12 +9152,13 @@ snapshots: set-cookie-parser: 2.7.1 tar-fs: 2.1.2 tsconfig-paths: 4.2.0 - typescript: 5.7.3 valibot: 0.41.0(typescript@5.7.3) - vite: 5.4.14(sass-embedded@1.83.4) - vite-node: 1.6.1(sass-embedded@1.83.4) - wrangler: 3.108.0(@cloudflare/workers-types@4.20250204.0) + vite-node: 1.6.1(@types/node@22.13.1)(sass-embedded@1.83.4) ws: 7.5.10 + optionalDependencies: + typescript: 5.7.3 + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) + wrangler: 3.108.0(@cloudflare/workers-types@4.20250204.0) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -8814,18 +9183,20 @@ snapshots: cookie-signature: 1.2.2 source-map-support: 0.5.21 stream-slice: 0.1.2 - typescript: 5.7.3 undici: 6.21.1 + optionalDependencies: + typescript: 5.7.3 - '@remix-run/react@2.15.3(react-dom@18.3.1)(react@18.3.1)(typescript@5.7.3)': + '@remix-run/react@2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3)': dependencies: '@remix-run/router': 1.22.0 '@remix-run/server-runtime': 2.15.3(typescript@5.7.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-router: 6.29.0(react@18.3.1) - react-router-dom: 6.29.0(react-dom@18.3.1)(react@18.3.1) + react-router-dom: 6.29.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) turbo-stream: 2.4.0 + optionalDependencies: typescript: 5.7.3 '@remix-run/router@1.22.0': {} @@ -8839,6 +9210,7 @@ snapshots: set-cookie-parser: 2.7.1 source-map: 0.7.4 turbo-stream: 2.4.0 + optionalDependencies: typescript: 5.7.3 '@remix-run/web-blob@3.1.0': @@ -8874,6 +9246,7 @@ snapshots: '@rollup/pluginutils': 5.1.4(rollup@3.29.5) estree-walker: 2.0.2 magic-string: 0.30.17 + optionalDependencies: rollup: 3.29.5 '@rollup/pluginutils@5.1.4(rollup@3.29.5)': @@ -8881,6 +9254,7 @@ snapshots: '@types/estree': 1.0.6 estree-walker: 2.0.2 picomatch: 4.0.2 + optionalDependencies: rollup: 3.29.5 '@rollup/rollup-android-arm-eabi@4.34.6': @@ -9272,10 +9646,10 @@ snapshots: '@smithy/util-buffer-from': 4.0.0 tslib: 2.8.1 - '@stylistic/eslint-plugin-ts@2.13.0(eslint@9.20.1)(typescript@5.7.3)': + '@stylistic/eslint-plugin-ts@2.13.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3)': dependencies: - '@typescript-eslint/utils': 8.24.0(eslint@9.20.1)(typescript@5.7.3) - eslint: 9.20.1 + '@typescript-eslint/utils': 8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) + eslint: 9.20.1(jiti@1.21.7) eslint-visitor-keys: 4.2.0 espree: 10.3.0 transitivePeerDependencies: @@ -9286,7 +9660,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@tanstack/react-virtual@3.13.0(react-dom@18.3.1)(react@18.3.1)': + '@tanstack/react-virtual@3.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@tanstack/virtual-core': 3.13.0 react: 18.3.1 @@ -9294,10 +9668,64 @@ snapshots: '@tanstack/virtual-core@3.13.0': {} + '@testing-library/dom@10.4.0': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/runtime': 7.26.7 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.6.3': + dependencies: + '@adobe/css-tools': 4.4.2 + aria-query: 5.3.2 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.17.21 + redent: 3.0.0 + + '@testing-library/react@16.2.0(@testing-library/dom@10.4.0)(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.26.7 + '@testing-library/dom': 10.4.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) + '@types/acorn@4.0.6': dependencies: '@types/estree': 1.0.6 + '@types/aria-query@5.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.26.8 + '@babel/types': 7.26.8 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.26.8 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.26.8 + '@babel/types': 7.26.8 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.26.8 + '@types/cookie@0.6.0': {} '@types/debug@4.1.12': @@ -9388,15 +9816,15 @@ snapshots: '@types/uuid@9.0.8': {} - '@typescript-eslint/eslint-plugin@8.24.0(@typescript-eslint/parser@8.24.0)(eslint@9.20.1)(typescript@5.7.3)': + '@typescript-eslint/eslint-plugin@8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3))(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.24.0(eslint@9.20.1)(typescript@5.7.3) + '@typescript-eslint/parser': 8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) '@typescript-eslint/scope-manager': 8.24.0 - '@typescript-eslint/type-utils': 8.24.0(eslint@9.20.1)(typescript@5.7.3) - '@typescript-eslint/utils': 8.24.0(eslint@9.20.1)(typescript@5.7.3) + '@typescript-eslint/type-utils': 8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) '@typescript-eslint/visitor-keys': 8.24.0 - eslint: 9.20.1 + eslint: 9.20.1(jiti@1.21.7) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -9405,14 +9833,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3)': + '@typescript-eslint/parser@8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3)': dependencies: '@typescript-eslint/scope-manager': 8.24.0 '@typescript-eslint/types': 8.24.0 '@typescript-eslint/typescript-estree': 8.24.0(typescript@5.7.3) '@typescript-eslint/visitor-keys': 8.24.0 debug: 4.4.0 - eslint: 9.20.1 + eslint: 9.20.1(jiti@1.21.7) typescript: 5.7.3 transitivePeerDependencies: - supports-color @@ -9422,12 +9850,12 @@ snapshots: '@typescript-eslint/types': 8.24.0 '@typescript-eslint/visitor-keys': 8.24.0 - '@typescript-eslint/type-utils@8.24.0(eslint@9.20.1)(typescript@5.7.3)': + '@typescript-eslint/type-utils@8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3)': dependencies: '@typescript-eslint/typescript-estree': 8.24.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.24.0(eslint@9.20.1)(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) debug: 4.4.0 - eslint: 9.20.1 + eslint: 9.20.1(jiti@1.21.7) ts-api-utils: 2.0.1(typescript@5.7.3) typescript: 5.7.3 transitivePeerDependencies: @@ -9449,13 +9877,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.24.0(eslint@9.20.1)(typescript@5.7.3)': + '@typescript-eslint/utils@8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1) + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@1.21.7)) '@typescript-eslint/scope-manager': 8.24.0 '@typescript-eslint/types': 8.24.0 '@typescript-eslint/typescript-estree': 8.24.0(typescript@5.7.3) - eslint: 9.20.1 + eslint: 9.20.1(jiti@1.21.7) typescript: 5.7.3 transitivePeerDependencies: - supports-color @@ -9481,12 +9909,13 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@unocss/astro@0.61.9(rollup@3.29.5)(vite@5.4.14)': + '@unocss/astro@0.61.9(rollup@3.29.5)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4))': dependencies: '@unocss/core': 0.61.9 '@unocss/reset': 0.61.9 - '@unocss/vite': 0.61.9(rollup@3.29.5)(vite@5.4.14) - vite: 5.4.14(sass-embedded@1.83.4) + '@unocss/vite': 0.61.9(rollup@3.29.5)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)) + optionalDependencies: + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) transitivePeerDependencies: - rollup - supports-color @@ -9623,7 +10052,7 @@ snapshots: dependencies: '@unocss/core': 0.61.9 - '@unocss/vite@0.61.9(rollup@3.29.5)(vite@5.4.14)': + '@unocss/vite@0.61.9(rollup@3.29.5)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4))': dependencies: '@ampproject/remapping': 2.3.0 '@rollup/pluginutils': 5.1.4(rollup@3.29.5) @@ -9635,7 +10064,7 @@ snapshots: chokidar: 3.6.0 fast-glob: 3.3.3 magic-string: 0.30.17 - vite: 5.4.14(sass-embedded@1.83.4) + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) transitivePeerDependencies: - rollup - supports-color @@ -9663,7 +10092,7 @@ snapshots: transitivePeerDependencies: - babel-plugin-macros - '@vanilla-extract/integration@6.5.0(sass-embedded@1.83.4)': + '@vanilla-extract/integration@6.5.0(@types/node@22.13.1)(sass-embedded@1.83.4)': dependencies: '@babel/core': 7.26.8 '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.8) @@ -9676,8 +10105,8 @@ snapshots: lodash: 4.17.21 mlly: 1.7.4 outdent: 0.8.0 - vite: 5.4.14(sass-embedded@1.83.4) - vite-node: 1.6.1(sass-embedded@1.83.4) + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) + vite-node: 1.6.1(@types/node@22.13.1)(sass-embedded@1.83.4) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -9692,6 +10121,17 @@ snapshots: '@vanilla-extract/private@1.0.6': {} + '@vitejs/plugin-react@4.3.4(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4))': + dependencies: + '@babel/core': 7.26.8 + '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.8) + '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.8) + '@types/babel__core': 7.20.5 + react-refresh: 0.14.2 + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) + transitivePeerDependencies: + - supports-color + '@vitest/expect@2.1.9': dependencies: '@vitest/spy': 2.1.9 @@ -9699,12 +10139,13 @@ snapshots: chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.9(vite@5.4.14)': + '@vitest/mocker@2.1.9(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4))': dependencies: '@vitest/spy': 2.1.9 estree-walker: 3.0.3 magic-string: 0.30.17 - vite: 5.4.14(sass-embedded@1.83.4) + optionalDependencies: + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) '@vitest/pretty-format@2.1.9': dependencies: @@ -9769,6 +10210,8 @@ snapshots: acorn@8.14.0: {} + agent-base@7.1.3: {} + aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 @@ -9782,6 +10225,7 @@ snapshots: '@ai-sdk/ui-utils': 1.1.11(zod@3.24.1) '@opentelemetry/api': 1.9.0 jsondiffpatch: 0.6.0 + optionalDependencies: react: 18.3.1 zod: 3.24.1 @@ -9800,6 +10244,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.1: {} anymatch@3.1.3: @@ -9815,6 +10261,12 @@ snapshots: dependencies: tslib: 2.8.1 + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + array-flatten@1.1.1: {} as-table@1.0.55: @@ -9841,6 +10293,8 @@ snapshots: async-lock@1.4.1: {} + asynckit@0.4.0: {} + atob@2.1.2: {} available-typed-arrays@1.0.7: @@ -10052,6 +10506,11 @@ snapshots: loupe: 3.1.3 pathval: 2.0.0 + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -10136,6 +10595,10 @@ snapshots: colorjs.io@0.5.2: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + comma-separated-tokens@2.0.3: {} common-tags@1.8.2: {} @@ -10238,8 +10701,15 @@ snapshots: css-what@6.1.0: {} + css.escape@1.5.1: {} + cssesc@3.0.0: {} + cssstyle@4.2.1: + dependencies: + '@asamuzakjp/css-color': 2.8.3 + rrweb-cssom: 0.8.0 + csstype@3.1.3: {} data-uri-to-buffer@2.0.2: {} @@ -10248,6 +10718,11 @@ snapshots: data-uri-to-buffer@4.0.1: {} + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.1.1 + date-fns@3.6.0: {} debug@2.6.9: @@ -10258,6 +10733,8 @@ snapshots: dependencies: ms: 2.1.3 + decimal.js@10.5.0: {} + decode-named-character-reference@1.0.2: dependencies: character-entities: 2.0.2 @@ -10294,6 +10771,8 @@ snapshots: defu@6.1.4: {} + delayed-stream@1.0.0: {} + depd@2.0.0: {} dequal@2.0.3: {} @@ -10334,6 +10813,10 @@ snapshots: '@react-dnd/invariant': 4.0.2 redux: 4.2.1 + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + domain-browser@4.22.0: {} dompurify@2.5.8: @@ -10404,6 +10887,13 @@ snapshots: dependencies: es-errors: 1.3.0 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + esbuild-plugins-node-modules-polyfill@1.6.8(esbuild@0.17.6): dependencies: '@jspm/core': 2.0.1 @@ -10522,27 +11012,27 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-compat-utils@0.6.4(eslint@9.20.1): + eslint-compat-utils@0.6.4(eslint@9.20.1(jiti@1.21.7)): dependencies: - eslint: 9.20.1 + eslint: 9.20.1(jiti@1.21.7) semver: 7.7.1 - eslint-config-prettier@9.1.0(eslint@9.20.1): + eslint-config-prettier@9.1.0(eslint@9.20.1(jiti@1.21.7)): dependencies: - eslint: 9.20.1 + eslint: 9.20.1(jiti@1.21.7) - eslint-json-compat-utils@0.2.1(eslint@9.20.1)(jsonc-eslint-parser@2.4.0): + eslint-json-compat-utils@0.2.1(eslint@9.20.1(jiti@1.21.7))(jsonc-eslint-parser@2.4.0): dependencies: - eslint: 9.20.1 + eslint: 9.20.1(jiti@1.21.7) esquery: 1.6.0 jsonc-eslint-parser: 2.4.0 - eslint-plugin-jsonc@2.19.1(eslint@9.20.1): + eslint-plugin-jsonc@2.19.1(eslint@9.20.1(jiti@1.21.7)): dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1) - eslint: 9.20.1 - eslint-compat-utils: 0.6.4(eslint@9.20.1) - eslint-json-compat-utils: 0.2.1(eslint@9.20.1)(jsonc-eslint-parser@2.4.0) + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@1.21.7)) + eslint: 9.20.1(jiti@1.21.7) + eslint-compat-utils: 0.6.4(eslint@9.20.1(jiti@1.21.7)) + eslint-json-compat-utils: 0.2.1(eslint@9.20.1(jiti@1.21.7))(jsonc-eslint-parser@2.4.0) espree: 9.6.1 graphemer: 1.4.0 jsonc-eslint-parser: 2.4.0 @@ -10551,13 +11041,14 @@ snapshots: transitivePeerDependencies: - '@eslint/json' - eslint-plugin-prettier@5.2.3(eslint-config-prettier@9.1.0)(eslint@9.20.1)(prettier@3.5.0): + eslint-plugin-prettier@5.2.3(eslint-config-prettier@9.1.0(eslint@9.20.1(jiti@1.21.7)))(eslint@9.20.1(jiti@1.21.7))(prettier@3.5.0): dependencies: - eslint: 9.20.1 - eslint-config-prettier: 9.1.0(eslint@9.20.1) + eslint: 9.20.1(jiti@1.21.7) prettier: 3.5.0 prettier-linter-helpers: 1.0.0 synckit: 0.9.2 + optionalDependencies: + eslint-config-prettier: 9.1.0(eslint@9.20.1(jiti@1.21.7)) eslint-scope@8.2.0: dependencies: @@ -10568,9 +11059,9 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.20.1: + eslint@9.20.1(jiti@1.21.7): dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1) + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@1.21.7)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.19.2 '@eslint/core': 0.11.0 @@ -10604,6 +11095,8 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 1.21.7 transitivePeerDependencies: - supports-color @@ -10824,6 +11317,13 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + format@0.2.2: {} formdata-polyfill@4.0.10: @@ -10832,13 +11332,14 @@ snapshots: forwarded@0.2.0: {} - framer-motion@11.18.2(react-dom@18.3.1)(react@18.3.1): + framer-motion@11.18.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: motion-dom: 11.18.1 motion-utils: 11.18.1 + tslib: 2.8.1 + optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - tslib: 2.8.1 fresh@0.5.2: {} @@ -11103,6 +11604,10 @@ snapshots: dependencies: lru-cache: 7.18.3 + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + html-url-attributes@3.0.1: {} html-void-elements@3.0.0: {} @@ -11121,8 +11626,22 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + https-browserify@1.0.0: {} + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + human-signals@2.1.0: {} husky@9.1.7: {} @@ -11131,6 +11650,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + icss-utils@5.1.0(postcss@8.5.2): dependencies: postcss: 8.5.2 @@ -11241,6 +11764,8 @@ snapshots: is-plain-obj@4.1.0: {} + is-potential-custom-element-name@1.0.1: {} + is-reference@3.0.3: dependencies: '@types/estree': 1.0.6 @@ -11311,6 +11836,34 @@ snapshots: dependencies: argparse: 2.0.1 + jsdom@26.0.0: + dependencies: + cssstyle: 4.2.1 + data-urls: 5.0.0 + decimal.js: 10.5.0 + form-data: 4.0.2 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.16 + parse5: 7.2.1 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.1 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.1.1 + ws: 8.18.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jsesc@3.0.2: {} json-buffer@3.0.1: {} @@ -11429,6 +11982,12 @@ snapshots: lru-cache@7.18.3: {} + lucide-react@0.474.0(react@18.3.1): + dependencies: + react: 18.3.1 + + lz-string@1.5.0: {} + magic-string@0.25.9: dependencies: sourcemap-codec: 1.4.8 @@ -12157,6 +12716,8 @@ snapshots: mimic-response@3.1.0: {} + min-indent@1.0.1: {} + miniflare@3.20250204.0: dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -12258,6 +12819,11 @@ snapshots: negotiator@0.6.3: {} + next-themes@0.4.4(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) + node-domexception@1.0.0: {} node-fetch-native@1.6.6: {} @@ -12333,6 +12899,8 @@ snapshots: dependencies: path-key: 3.1.1 + nwsapi@2.2.16: {} + object-assign@4.1.1: {} object-inspect@1.13.4: {} @@ -12366,6 +12934,7 @@ snapshots: '@ai-sdk/provider': 0.0.24 '@ai-sdk/provider-utils': 1.0.20(zod@3.24.1) partial-json: 0.1.7 + optionalDependencies: zod: 3.24.1 on-finished@2.4.1: @@ -12543,8 +13112,9 @@ snapshots: postcss-load-config@4.0.2(postcss@8.5.2): dependencies: lilconfig: 3.1.3 - postcss: 8.5.2 yaml: 2.7.0 + optionalDependencies: + postcss: 8.5.2 postcss-modules-extract-imports@3.1.0(postcss@8.5.2): dependencies: @@ -12602,6 +13172,12 @@ snapshots: prettier@3.5.0: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + pretty-ms@7.0.1: dependencies: parse-ms: 2.1.0 @@ -12700,7 +13276,7 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 - react-beautiful-dnd@13.1.1(react-dom@18.3.1)(react@18.3.1): + react-beautiful-dnd@13.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.7 css-box-model: 1.2.1 @@ -12708,7 +13284,7 @@ snapshots: raf-schd: 4.0.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-redux: 7.2.9(react-dom@18.3.1)(react@18.3.1) + react-redux: 7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) redux: 4.2.1 use-memo-one: 1.1.3(react@18.3.1) transitivePeerDependencies: @@ -12723,15 +13299,18 @@ snapshots: dependencies: dnd-core: 16.0.1 - react-dnd@16.0.1(@types/react@18.3.18)(react@18.3.1): + react-dnd@16.0.1(@types/hoist-non-react-statics@3.3.6)(@types/node@22.13.1)(@types/react@18.3.18)(react@18.3.1): dependencies: '@react-dnd/invariant': 4.0.2 '@react-dnd/shallowequal': 4.0.2 - '@types/react': 18.3.18 dnd-core: 16.0.1 fast-deep-equal: 3.1.3 hoist-non-react-statics: 3.3.2 react: 18.3.1 + optionalDependencies: + '@types/hoist-non-react-statics': 3.3.6 + '@types/node': 22.13.1 + '@types/react': 18.3.18 react-dom@18.3.1(react@18.3.1): dependencies: @@ -12739,7 +13318,7 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-hotkeys-hook@4.6.1(react-dom@18.3.1)(react@18.3.1): + react-hotkeys-hook@4.6.1(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) @@ -12769,7 +13348,7 @@ snapshots: transitivePeerDependencies: - supports-color - react-redux@7.2.9(react-dom@18.3.1)(react@18.3.1): + react-redux@7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.7 '@types/react-redux': 7.1.34 @@ -12777,34 +13356,37 @@ snapshots: loose-envify: 1.4.0 prop-types: 15.8.1 react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) react-is: 17.0.2 + optionalDependencies: + react-dom: 18.3.1(react@18.3.1) react-refresh@0.14.2: {} react-remove-scroll-bar@2.3.8(@types/react@18.3.18)(react@18.3.1): dependencies: - '@types/react': 18.3.18 react: 18.3.1 react-style-singleton: 2.2.3(@types/react@18.3.18)(react@18.3.1) tslib: 2.8.1 + optionalDependencies: + '@types/react': 18.3.18 react-remove-scroll@2.6.3(@types/react@18.3.18)(react@18.3.1): dependencies: - '@types/react': 18.3.18 react: 18.3.1 react-remove-scroll-bar: 2.3.8(@types/react@18.3.18)(react@18.3.1) react-style-singleton: 2.2.3(@types/react@18.3.18)(react@18.3.1) tslib: 2.8.1 use-callback-ref: 1.3.3(@types/react@18.3.18)(react@18.3.1) use-sidecar: 1.1.3(@types/react@18.3.18)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 - react-resizable-panels@2.1.7(react-dom@18.3.1)(react@18.3.1): + react-resizable-panels@2.1.7(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-router-dom@6.29.0(react-dom@18.3.1)(react@18.3.1): + react-router-dom@6.29.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@remix-run/router': 1.22.0 react: 18.3.1 @@ -12818,12 +13400,13 @@ snapshots: react-style-singleton@2.2.3(@types/react@18.3.18)(react@18.3.1): dependencies: - '@types/react': 18.3.18 get-nonce: 1.0.1 react: 18.3.1 tslib: 2.8.1 + optionalDependencies: + '@types/react': 18.3.18 - react-toastify@10.0.6(react-dom@18.3.1)(react@18.3.1): + react-toastify@10.0.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: clsx: 2.1.1 react: 18.3.1 @@ -12853,6 +13436,11 @@ snapshots: dependencies: picomatch: 2.3.1 + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + redux@4.2.1: dependencies: '@babel/runtime': 7.26.7 @@ -12954,20 +13542,22 @@ snapshots: mdast-util-to-markdown: 2.1.2 unified: 11.0.5 - remix-island@0.2.0(@remix-run/react@2.15.3)(@remix-run/server-runtime@2.15.3)(react-dom@18.3.1)(react@18.3.1): + remix-island@0.2.0(@remix-run/react@2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3))(@remix-run/server-runtime@2.15.3(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@remix-run/react': 2.15.3(react-dom@18.3.1)(react@18.3.1)(typescript@5.7.3) + '@remix-run/react': 2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3) '@remix-run/server-runtime': 2.15.3(typescript@5.7.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - remix-utils@7.7.0(@remix-run/cloudflare@2.15.3)(@remix-run/node@2.15.3)(@remix-run/react@2.15.3)(react@18.3.1)(zod@3.24.1): + remix-utils@7.7.0(@remix-run/cloudflare@2.15.3(@cloudflare/workers-types@4.20250204.0)(typescript@5.7.3))(@remix-run/node@2.15.3(typescript@5.7.3))(@remix-run/react@2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3))(@remix-run/router@1.22.0)(react@18.3.1)(zod@3.24.1): dependencies: + type-fest: 4.34.1 + optionalDependencies: '@remix-run/cloudflare': 2.15.3(@cloudflare/workers-types@4.20250204.0)(typescript@5.7.3) '@remix-run/node': 2.15.3(typescript@5.7.3) - '@remix-run/react': 2.15.3(react-dom@18.3.1)(react@18.3.1)(typescript@5.7.3) + '@remix-run/react': 2.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3) + '@remix-run/router': 1.22.0 react: 18.3.1 - type-fest: 4.34.1 zod: 3.24.1 require-like@0.1.2: {} @@ -13052,6 +13642,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.34.6 fsevents: 2.3.3 + rrweb-cssom@0.8.0: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -13168,6 +13760,10 @@ snapshots: sass-embedded-win32-ia32: 1.83.4 sass-embedded-win32-x64: 1.83.4 + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 @@ -13426,6 +14022,10 @@ snapshots: strip-final-newline@2.0.0: {} + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + strip-json-comments@3.1.1: {} strnum@1.0.5: {} @@ -13459,6 +14059,8 @@ snapshots: react: 18.3.1 use-sync-external-store: 1.4.0(react@18.3.1) + symbol-tree@3.2.4: {} + sync-child-process@1.0.2: dependencies: sync-message-port: 1.1.3 @@ -13534,6 +14136,12 @@ snapshots: tinyspy@3.0.2: {} + tldts-core@6.1.78: {} + + tldts@6.1.78: + dependencies: + tldts-core: 6.1.78 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -13544,6 +14152,14 @@ snapshots: totalist@3.0.1: {} + tough-cookie@5.1.1: + dependencies: + tldts: 6.1.78 + + tr46@5.0.0: + dependencies: + punycode: 2.3.1 + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -13553,7 +14169,7 @@ snapshots: typescript: 5.7.3 tsconfck@3.1.5(typescript@5.7.3): - dependencies: + optionalDependencies: typescript: 5.7.3 tsconfig-paths@4.2.0: @@ -13586,12 +14202,12 @@ snapshots: media-typer: 0.3.0 mime-types: 2.1.35 - typescript-eslint@8.24.0(eslint@9.20.1)(typescript@5.7.3): + typescript-eslint@8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.24.0(@typescript-eslint/parser@8.24.0)(eslint@9.20.1)(typescript@5.7.3) - '@typescript-eslint/parser': 8.24.0(eslint@9.20.1)(typescript@5.7.3) - '@typescript-eslint/utils': 8.24.0(eslint@9.20.1)(typescript@5.7.3) - eslint: 9.20.1 + '@typescript-eslint/eslint-plugin': 8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3))(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) + '@typescript-eslint/parser': 8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.0(eslint@9.20.1(jiti@1.21.7))(typescript@5.7.3) + eslint: 9.20.1(jiti@1.21.7) typescript: 5.7.3 transitivePeerDependencies: - supports-color @@ -13713,9 +14329,9 @@ snapshots: universalify@2.0.1: {} - unocss@0.61.9(postcss@8.5.2)(rollup@3.29.5)(vite@5.4.14): + unocss@0.61.9(postcss@8.5.2)(rollup@3.29.5)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)): dependencies: - '@unocss/astro': 0.61.9(rollup@3.29.5)(vite@5.4.14) + '@unocss/astro': 0.61.9(rollup@3.29.5)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)) '@unocss/cli': 0.61.9(rollup@3.29.5) '@unocss/core': 0.61.9 '@unocss/extractor-arbitrary-variants': 0.61.9 @@ -13734,8 +14350,9 @@ snapshots: '@unocss/transformer-compile-class': 0.61.9 '@unocss/transformer-directives': 0.61.9 '@unocss/transformer-variant-group': 0.61.9 - '@unocss/vite': 0.61.9(rollup@3.29.5)(vite@5.4.14) - vite: 5.4.14(sass-embedded@1.83.4) + '@unocss/vite': 0.61.9(rollup@3.29.5)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)) + optionalDependencies: + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) transitivePeerDependencies: - postcss - rollup @@ -13760,9 +14377,10 @@ snapshots: use-callback-ref@1.3.3(@types/react@18.3.18)(react@18.3.1): dependencies: - '@types/react': 18.3.18 react: 18.3.1 tslib: 2.8.1 + optionalDependencies: + '@types/react': 18.3.18 use-memo-one@1.1.3(react@18.3.1): dependencies: @@ -13770,10 +14388,11 @@ snapshots: use-sidecar@1.1.3(@types/react@18.3.18)(react@18.3.1): dependencies: - '@types/react': 18.3.18 detect-node-es: 1.1.0 react: 18.3.1 tslib: 2.8.1 + optionalDependencies: + '@types/react': 18.3.18 use-sync-external-store@1.4.0(react@18.3.1): dependencies: @@ -13806,7 +14425,7 @@ snapshots: sade: 1.8.1 valibot@0.41.0(typescript@5.7.3): - dependencies: + optionalDependencies: typescript: 5.7.3 validate-npm-package-license@3.0.4: @@ -13849,13 +14468,13 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-node@1.6.1(sass-embedded@1.83.4): + vite-node@1.6.1(@types/node@22.13.1)(sass-embedded@1.83.4): dependencies: cac: 6.7.14 debug: 4.4.0 pathe: 1.1.2 picocolors: 1.1.1 - vite: 5.4.14(sass-embedded@1.83.4) + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) transitivePeerDependencies: - '@types/node' - less @@ -13867,13 +14486,13 @@ snapshots: - supports-color - terser - vite-node@2.1.9(sass-embedded@1.83.4): + vite-node@2.1.9(@types/node@22.13.1)(sass-embedded@1.83.4): dependencies: cac: 6.7.14 debug: 4.4.0 es-module-lexer: 1.6.0 pathe: 1.1.2 - vite: 5.4.14(sass-embedded@1.83.4) + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) transitivePeerDependencies: - '@types/node' - less @@ -13885,41 +14504,43 @@ snapshots: - supports-color - terser - vite-plugin-node-polyfills@0.22.0(rollup@3.29.5)(vite@5.4.14): + vite-plugin-node-polyfills@0.22.0(rollup@3.29.5)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)): dependencies: '@rollup/plugin-inject': 5.0.5(rollup@3.29.5) node-stdlib-browser: 1.3.1 - vite: 5.4.14(sass-embedded@1.83.4) + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) transitivePeerDependencies: - rollup - vite-plugin-optimize-css-modules@1.2.0(vite@5.4.14): + vite-plugin-optimize-css-modules@1.2.0(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)): dependencies: - vite: 5.4.14(sass-embedded@1.83.4) + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) - vite-tsconfig-paths@4.3.2(typescript@5.7.3)(vite@5.4.14): + vite-tsconfig-paths@4.3.2(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)): dependencies: debug: 4.4.0 globrex: 0.1.2 tsconfck: 3.1.5(typescript@5.7.3) - vite: 5.4.14(sass-embedded@1.83.4) + optionalDependencies: + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) transitivePeerDependencies: - supports-color - typescript - vite@5.4.14(sass-embedded@1.83.4): + vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4): dependencies: esbuild: 0.21.5 postcss: 8.5.2 rollup: 4.34.6 - sass-embedded: 1.83.4 optionalDependencies: + '@types/node': 22.13.1 fsevents: 2.3.3 + sass-embedded: 1.83.4 - vitest@2.1.9(sass-embedded@1.83.4): + vitest@2.1.9(@types/node@22.13.1)(jsdom@26.0.0)(sass-embedded@1.83.4): dependencies: '@vitest/expect': 2.1.9 - '@vitest/mocker': 2.1.9(vite@5.4.14) + '@vitest/mocker': 2.1.9(vite@5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4)) '@vitest/pretty-format': 2.1.9 '@vitest/runner': 2.1.9 '@vitest/snapshot': 2.1.9 @@ -13935,9 +14556,12 @@ snapshots: tinyexec: 0.3.2 tinypool: 1.0.2 tinyrainbow: 1.2.0 - vite: 5.4.14(sass-embedded@1.83.4) - vite-node: 2.1.9(sass-embedded@1.83.4) + vite: 5.4.14(@types/node@22.13.1)(sass-embedded@1.83.4) + vite-node: 2.1.9(@types/node@22.13.1)(sass-embedded@1.83.4) why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.13.1 + jsdom: 26.0.0 transitivePeerDependencies: - less - lightningcss @@ -13953,6 +14577,10 @@ snapshots: w3c-keyname@2.2.8: {} + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + wcwidth@1.0.1: dependencies: defaults: 1.0.4 @@ -13967,6 +14595,19 @@ snapshots: web-streams-polyfill@3.3.3: {} + webidl-conversions@7.0.0: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@14.1.1: + dependencies: + tr46: 5.0.0 + webidl-conversions: 7.0.0 + which-typed-array@1.1.18: dependencies: available-typed-arrays: 1.0.7 @@ -14002,7 +14643,6 @@ snapshots: wrangler@3.108.0(@cloudflare/workers-types@4.20250204.0): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 - '@cloudflare/workers-types': 4.20250204.0 '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) blake3-wasm: 2.1.5 @@ -14012,6 +14652,7 @@ snapshots: unenv: 2.0.0-rc.1 workerd: 1.20250204.0 optionalDependencies: + '@cloudflare/workers-types': 4.20250204.0 fsevents: 2.3.3 sharp: 0.33.5 transitivePeerDependencies: @@ -14036,6 +14677,10 @@ snapshots: ws@8.18.0: {} + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + xtend@4.0.2: {} yallist@3.1.1: {} @@ -14060,9 +14705,10 @@ snapshots: zod@3.24.1: {} - zustand@5.0.3(@types/react@18.3.18)(react@18.3.1): - dependencies: + zustand@5.0.3(@types/react@18.3.18)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)): + optionalDependencies: '@types/react': 18.3.18 react: 18.3.1 + use-sync-external-store: 1.4.0(react@18.3.1) zwitch@2.0.4: {} From 056a446f0f4befe5873f77f68daeaa8428051ec8 Mon Sep 17 00:00:00 2001 From: Toddyclipsgg Date: Sun, 23 Feb 2025 20:00:17 -0300 Subject: [PATCH 3/5] chore: Remove unused dependencies and clean up imports - Removed lucide-react and next-themes from package dependencies - Simplified import in workbench store for path and file-saver - Removed unnecessary module definition in Vite config --- app/lib/stores/workbench.ts | 9 +++++---- package.json | 2 -- pnpm-lock.yaml | 26 -------------------------- vite.config.ts | 1 - 4 files changed, 5 insertions(+), 33 deletions(-) diff --git a/app/lib/stores/workbench.ts b/app/lib/stores/workbench.ts index 84d38efa..80111079 100644 --- a/app/lib/stores/workbench.ts +++ b/app/lib/stores/workbench.ts @@ -10,16 +10,17 @@ import { FilesStore, type FileMap } from './files'; import { PreviewsStore } from './previews'; import { TerminalStore } from './terminal'; import JSZip from 'jszip'; -import pkg from 'file-saver'; -const { saveAs } = pkg; +import fileSaver from 'file-saver'; import { Octokit, type RestEndpointMethodTypes } from '@octokit/rest'; -import * as nodePath from 'node:path'; +import { path } from '~/utils/path'; import { extractRelativePath } from '~/utils/diff'; import { description } from '~/lib/persistence'; import Cookies from 'js-cookie'; import { createSampler } from '~/utils/sampler'; import type { ActionAlert } from '~/types/actions'; +const { saveAs } = fileSaver; + export interface ArtifactState { id: string; title: string; @@ -330,7 +331,7 @@ export class WorkbenchStore { if (data.action.type === 'file') { const wc = await webcontainer; - const fullPath = nodePath.join(wc.workdir, data.action.filePath); + const fullPath = path.join(wc.workdir, data.action.filePath); if (this.selectedFile.value !== fullPath) { this.setSelectedFile(fullPath); diff --git a/package.json b/package.json index d7dc2b5b..d8ed37e3 100644 --- a/package.json +++ b/package.json @@ -104,9 +104,7 @@ "js-cookie": "^3.0.5", "jspdf": "^2.5.2", "jszip": "^3.10.1", - "lucide-react": "^0.474.0", "nanostores": "^0.10.3", - "next-themes": "^0.4.4", "ollama-ai-provider": "^0.15.2", "path-browserify": "^1.0.1", "react": "^18.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d2ee571c..fc491791 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -230,15 +230,9 @@ importers: jszip: specifier: ^3.10.1 version: 3.10.1 - lucide-react: - specifier: ^0.474.0 - version: 0.474.0(react@18.3.1) nanostores: specifier: ^0.10.3 version: 0.10.3 - next-themes: - specifier: ^0.4.4 - version: 0.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) ollama-ai-provider: specifier: ^0.15.2 version: 0.15.2(zod@3.24.1) @@ -4733,11 +4727,6 @@ packages: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} - lucide-react@0.474.0: - resolution: {integrity: sha512-CmghgHkh0OJNmxGKWc0qfPJCYHASPMVSyGY8fj3xgk4v84ItqDg64JNKFZn5hC6E0vHi6gxnbCgwhyVB09wQtA==} - peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -5196,12 +5185,6 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} - next-themes@0.4.4: - resolution: {integrity: sha512-LDQ2qIOJF0VnuVrrMSMLrWGjRMkq+0mpgl6e0juCLqdJ+oo8Q84JRWT6Wh11VDQKkMMe+dVzDKLWs5n87T+PkQ==} - peerDependencies: - react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -11982,10 +11965,6 @@ snapshots: lru-cache@7.18.3: {} - lucide-react@0.474.0(react@18.3.1): - dependencies: - react: 18.3.1 - lz-string@1.5.0: {} magic-string@0.25.9: @@ -12819,11 +12798,6 @@ snapshots: negotiator@0.6.3: {} - next-themes@0.4.4(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) - node-domexception@1.0.0: {} node-fetch-native@1.6.6: {} diff --git a/vite.config.ts b/vite.config.ts index 59ac01cd..01fb3b2e 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -89,7 +89,6 @@ export default defineConfig((config) => { __PKG_DEV_DEPENDENCIES: JSON.stringify(pkg.devDependencies), __PKG_PEER_DEPENDENCIES: JSON.stringify(pkg.peerDependencies), __PKG_OPTIONAL_DEPENDENCIES: JSON.stringify(pkg.optionalDependencies), - module: {}, }, build: { target: 'esnext', From afb82e2cf934d75a62a864307908eb206b996cd3 Mon Sep 17 00:00:00 2001 From: Toddyclipsgg Date: Sun, 23 Feb 2025 20:46:18 -0300 Subject: [PATCH 4/5] chore: Remove unnecessary history directory creation in GitHub Actions --- .github/actions/setup-and-build/action.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/actions/setup-and-build/action.yaml b/.github/actions/setup-and-build/action.yaml index b4f27b73..b27bc6fb 100644 --- a/.github/actions/setup-and-build/action.yaml +++ b/.github/actions/setup-and-build/action.yaml @@ -30,7 +30,3 @@ runs: run: | pnpm install pnpm run build - - - name: Create history directory - shell: bash - run: mkdir -p .history From 109818842772aec7d81e701bf2cf716e24f8f9f7 Mon Sep 17 00:00:00 2001 From: Toddyclipsgg Date: Mon, 24 Feb 2025 20:06:15 -0300 Subject: [PATCH 5/5] feat: Improve DiffView theme and color consistency - Added dark/light theme support for syntax highlighting - Enhanced color styles for added/removed lines and characters - Integrated theme store to dynamically adjust syntax highlighter theme - Refined color contrast for better readability across themes --- app/components/workbench/DiffView.tsx | 55 +++++++++++++++------------ 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/app/components/workbench/DiffView.tsx b/app/components/workbench/DiffView.tsx index 447eac83..e1cb843d 100644 --- a/app/components/workbench/DiffView.tsx +++ b/app/components/workbench/DiffView.tsx @@ -10,6 +10,7 @@ import { diffFiles, extractRelativePath } from '~/utils/diff'; import { ActionRunner } from '~/lib/runtime/action-runner'; import type { FileHistory } from '~/types/actions'; import { getLanguageFromExtension } from '~/utils/getLanguageFromExtension'; +import { themeStore } from '~/lib/stores/theme'; interface CodeComparisonProps { beforeCode: string; @@ -302,12 +303,20 @@ const processChanges = (beforeCode: string, afterCode: string) => { const lineNumberStyles = "w-9 shrink-0 pl-2 py-1 text-left font-mono text-bolt-elements-textTertiary border-r border-bolt-elements-borderColor bg-bolt-elements-background-depth-1"; const lineContentStyles = "px-1 py-1 font-mono whitespace-pre flex-1 group-hover:bg-bolt-elements-background-depth-2 text-bolt-elements-textPrimary"; const diffPanelStyles = "h-full overflow-auto diff-panel-content"; + +// Updated color styles for better consistency const diffLineStyles = { - added: 'bg-green-500/20 border-l-4 border-green-500', - removed: 'bg-red-500/20 border-l-4 border-red-500', + added: 'bg-green-500/10 dark:bg-green-500/20 border-l-4 border-green-500', + removed: 'bg-red-500/10 dark:bg-red-500/20 border-l-4 border-red-500', unchanged: '' }; +const changeColorStyles = { + added: 'text-green-700 dark:text-green-500 bg-green-500/10 dark:bg-green-500/20', + removed: 'text-red-700 dark:text-red-500 bg-red-500/10 dark:bg-red-500/20', + unchanged: 'text-bolt-elements-textPrimary' +}; + const renderContentWarning = (type: 'binary' | 'error') => (
@@ -324,10 +333,11 @@ const renderContentWarning = (type: 'binary' | 'error') => (
); -const NoChangesView = memo(({ beforeCode, language, highlighter }: { +const NoChangesView = memo(({ beforeCode, language, highlighter, theme }: { beforeCode: string; language: string; highlighter: any; + theme: string; }) => (
@@ -347,7 +357,7 @@ const NoChangesView = memo(({ beforeCode, language, highlighter }: { ]*>/g, '') .replace(/<\/?code[^>]*>/g, '') : line @@ -372,7 +382,8 @@ const CodeLine = memo(({ type, highlighter, language, - block + block, + theme }: { lineNumber: number; content: string; @@ -380,17 +391,14 @@ const CodeLine = memo(({ highlighter: any; language: string; block: DiffBlock; + theme: string; }) => { - const bgColor = { - added: 'bg-green-500/20 border-l-4 border-green-500', - removed: 'bg-red-500/20 border-l-4 border-red-500', - unchanged: '' - }[type]; + const bgColor = diffLineStyles[type]; const renderContent = () => { if (type === 'unchanged' || !block.charChanges) { const highlightedCode = highlighter ? - highlighter.codeToHtml(content, { lang: language, theme: 'github-dark' }) + highlighter.codeToHtml(content, { lang: language, theme: theme === 'dark' ? 'github-dark' : 'github-light' }) .replace(/<\/?pre[^>]*>/g, '') .replace(/<\/?code[^>]*>/g, '') : content; @@ -400,14 +408,10 @@ const CodeLine = memo(({ return ( <> {block.charChanges.map((change, index) => { - const changeClass = { - added: 'text-green-500 bg-green-500/20', - removed: 'text-red-500 bg-red-500/20', - unchanged: '' - }[change.type]; + const changeClass = changeColorStyles[change.type]; const highlightedCode = highlighter ? - highlighter.codeToHtml(change.value, { lang: language, theme: 'github-dark' }) + highlighter.codeToHtml(change.value, { lang: language, theme: theme === 'dark' ? 'github-dark' : 'github-light' }) .replace(/<\/?pre[^>]*>/g, '') .replace(/<\/?code[^>]*>/g, '') : change.value; @@ -429,8 +433,8 @@ const CodeLine = memo(({
{lineNumber + 1}
- {type === 'added' && '+'} - {type === 'removed' && '-'} + {type === 'added' && +} + {type === 'removed' && -} {type === 'unchanged' && ' '} {renderContent()} @@ -488,20 +492,20 @@ const FileInfo = memo(({ {showStats && (
{additions > 0 && ( - +{additions} + +{additions} )} {deletions > 0 && ( - -{deletions} + -{deletions} )}
)} - Modified + Modified {new Date().toLocaleTimeString()} ) : ( - No Changes + No Changes )} @@ -512,6 +516,7 @@ const FileInfo = memo(({ const InlineDiffComparison = memo(({ beforeCode, afterCode, filename, language, lightTheme, darkTheme }: CodeComparisonProps) => { const [isFullscreen, setIsFullscreen] = useState(false); const [highlighter, setHighlighter] = useState(null); + const theme = useStore(themeStore); const toggleFullscreen = useCallback(() => { setIsFullscreen(prev => !prev); @@ -521,7 +526,7 @@ const InlineDiffComparison = memo(({ beforeCode, afterCode, filename, language, useEffect(() => { getHighlighter({ - themes: ['github-dark'], + themes: ['github-dark', 'github-light'], langs: ['typescript', 'javascript', 'json', 'html', 'css', 'jsx', 'tsx'] }).then(setHighlighter); }, []); @@ -551,6 +556,7 @@ const InlineDiffComparison = memo(({ beforeCode, afterCode, filename, language, highlighter={highlighter} language={language} block={block} + theme={theme} /> ))}
@@ -559,6 +565,7 @@ const InlineDiffComparison = memo(({ beforeCode, afterCode, filename, language, beforeCode={beforeCode} language={language} highlighter={highlighter} + theme={theme} /> )}