feat: add file tree breadcrumb (#40)

This commit is contained in:
Dominic Elm 2024-08-20 18:35:44 +02:00 committed by GitHub
parent f55b4e5ab9
commit fcfef742d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 863 additions and 25 deletions

View File

@ -2,6 +2,7 @@ import { memo, useEffect, useState } from 'react';
import { bundledLanguages, codeToHtml, isSpecialLang, type BundledLanguage, type SpecialLanguage } from 'shiki'; import { bundledLanguages, codeToHtml, isSpecialLang, type BundledLanguage, type SpecialLanguage } from 'shiki';
import { classNames } from '~/utils/classNames'; import { classNames } from '~/utils/classNames';
import { createScopedLogger } from '~/utils/logger'; import { createScopedLogger } from '~/utils/logger';
import styles from './CodeBlock.module.scss'; import styles from './CodeBlock.module.scss';
const logger = createScopedLogger('CodeBlock'); const logger = createScopedLogger('CodeBlock');

View File

@ -20,6 +20,7 @@ import { classNames } from '~/utils/classNames';
import { WORK_DIR } from '~/utils/constants'; import { WORK_DIR } from '~/utils/constants';
import { renderLogger } from '~/utils/logger'; import { renderLogger } from '~/utils/logger';
import { isMobile } from '~/utils/mobile'; import { isMobile } from '~/utils/mobile';
import { FileBreadcrumb } from './FileBreadcrumb';
import { FileTree } from './FileTree'; import { FileTree } from './FileTree';
import { Terminal, type TerminalRef } from './terminal/Terminal'; import { Terminal, type TerminalRef } from './terminal/Terminal';
@ -67,12 +68,12 @@ export const EditorPanel = memo(
const [activeTerminal, setActiveTerminal] = useState(0); const [activeTerminal, setActiveTerminal] = useState(0);
const [terminalCount, setTerminalCount] = useState(1); const [terminalCount, setTerminalCount] = useState(1);
const activeFile = useMemo(() => { const activeFileSegments = useMemo(() => {
if (!editorDocument) { if (!editorDocument) {
return ''; return undefined;
} }
return editorDocument.filePath.split('/').at(-1); return editorDocument.filePath.split('/');
}, [editorDocument]); }, [editorDocument]);
const activeFileUnsaved = useMemo(() => { const activeFileUnsaved = useMemo(() => {
@ -134,6 +135,7 @@ export const EditorPanel = memo(
<FileTree <FileTree
className="h-full" className="h-full"
files={files} files={files}
hideRoot
unsavedFiles={unsavedFiles} unsavedFiles={unsavedFiles}
rootFolder={WORK_DIR} rootFolder={WORK_DIR}
selectedFile={selectedFile} selectedFile={selectedFile}
@ -143,11 +145,10 @@ export const EditorPanel = memo(
</Panel> </Panel>
<PanelResizeHandle /> <PanelResizeHandle />
<Panel className="flex flex-col" defaultSize={80} minSize={20}> <Panel className="flex flex-col" defaultSize={80} minSize={20}>
<PanelHeader> <PanelHeader className="overflow-x-auto">
{activeFile && ( {activeFileSegments?.length && (
<div className="flex items-center flex-1 text-sm"> <div className="flex items-center flex-1 text-sm">
<div className="i-ph:file-duotone mr-2" /> <FileBreadcrumb pathSegments={activeFileSegments} files={files} onFileSelect={onFileSelect} />
{activeFile}
{activeFileUnsaved && ( {activeFileUnsaved && (
<div className="flex gap-1 ml-auto -mr-1.5"> <div className="flex gap-1 ml-auto -mr-1.5">
<PanelHeaderButton onClick={onFileSave}> <PanelHeaderButton onClick={onFileSave}>

View File

@ -0,0 +1,148 @@
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import { AnimatePresence, motion, type Variants } from 'framer-motion';
import { memo, useEffect, useRef, useState } from 'react';
import type { FileMap } from '~/lib/stores/files';
import { classNames } from '~/utils/classNames';
import { WORK_DIR } from '~/utils/constants';
import { cubicEasingFn } from '~/utils/easings';
import { renderLogger } from '~/utils/logger';
import FileTree from './FileTree';
const WORK_DIR_REGEX = new RegExp(`^${WORK_DIR.split('/').slice(0, -1).join('/').replaceAll('/', '\\/')}/`);
interface FileBreadcrumbProps {
files?: FileMap;
pathSegments?: string[];
onFileSelect?: (filePath: string) => void;
}
const contextMenuVariants = {
open: {
y: 0,
opacity: 1,
transition: {
duration: 0.15,
ease: cubicEasingFn,
},
},
close: {
y: 6,
opacity: 0,
transition: {
duration: 0.15,
ease: cubicEasingFn,
},
},
} satisfies Variants;
export const FileBreadcrumb = memo<FileBreadcrumbProps>(({ files, pathSegments = [], onFileSelect }) => {
renderLogger.trace('FileBreadcrumb');
const [activeIndex, setActiveIndex] = useState<number | null>(null);
const contextMenuRef = useRef<HTMLDivElement | null>(null);
const segmentRefs = useRef<(HTMLSpanElement | null)[]>([]);
const handleSegmentClick = (index: number) => {
setActiveIndex((prevIndex) => (prevIndex === index ? null : index));
};
useEffect(() => {
const handleOutsideClick = (event: MouseEvent) => {
if (
activeIndex !== null &&
!contextMenuRef.current?.contains(event.target as Node) &&
!segmentRefs.current.some((ref) => ref?.contains(event.target as Node))
) {
setActiveIndex(null);
}
};
document.addEventListener('mousedown', handleOutsideClick);
return () => {
document.removeEventListener('mousedown', handleOutsideClick);
};
}, [activeIndex]);
if (files === undefined || pathSegments.length === 0) {
return null;
}
return (
<div className="flex">
{pathSegments.map((segment, index) => {
const isLast = index === pathSegments.length - 1;
const path = pathSegments.slice(0, index).join('/');
if (!WORK_DIR_REGEX.test(path)) {
return null;
}
const isActive = activeIndex === index;
return (
<div key={index} className="relative flex items-center">
<DropdownMenu.Root open={isActive} modal={false}>
<DropdownMenu.Trigger asChild>
<span
ref={(ref) => (segmentRefs.current[index] = ref)}
className={classNames('flex items-center gap-1.5 cursor-pointer shrink-0', {
'text-bolt-elements-textTertiary hover:text-bolt-elements-textPrimary': !isActive,
'text-bolt-elements-textPrimary underline': isActive,
'pr-4': isLast,
})}
onClick={() => handleSegmentClick(index)}
>
{isLast && <div className="i-ph:file-duotone" />}
{segment}
</span>
</DropdownMenu.Trigger>
{index > 0 && !isLast && <span className="i-ph:caret-right inline-block mx-1" />}
<AnimatePresence>
{isActive && (
<DropdownMenu.Portal>
<DropdownMenu.Content
className="z-file-tree-breadcrumb"
asChild
align="start"
side="bottom"
avoidCollisions={false}
>
<motion.div
ref={contextMenuRef}
initial="close"
animate="open"
exit="close"
variants={contextMenuVariants}
>
<div className="rounded-lg overflow-hidden">
<div className="max-h-[50vh] min-w-[300px] overflow-scroll bg-bolt-elements-background-depth-1 border border-bolt-elements-borderColor shadow-sm rounded-lg">
<FileTree
files={files}
hideRoot
rootFolder={path}
collapsed
allowFolderSelection
selectedFile={`${path}/${segment}`}
onFileSelect={(filePath) => {
setActiveIndex(null);
onFileSelect?.(filePath);
}}
/>
</div>
</div>
<DropdownMenu.Arrow className="fill-bolt-elements-borderColor" />
</motion.div>
</DropdownMenu.Content>
</DropdownMenu.Portal>
)}
</AnimatePresence>
</DropdownMenu.Root>
</div>
);
})}
</div>
);
});

View File

@ -13,24 +13,47 @@ interface Props {
selectedFile?: string; selectedFile?: string;
onFileSelect?: (filePath: string) => void; onFileSelect?: (filePath: string) => void;
rootFolder?: string; rootFolder?: string;
hideRoot?: boolean;
collapsed?: boolean;
allowFolderSelection?: boolean;
hiddenFiles?: Array<string | RegExp>; hiddenFiles?: Array<string | RegExp>;
unsavedFiles?: Set<string>; unsavedFiles?: Set<string>;
className?: string; className?: string;
} }
export const FileTree = memo( export const FileTree = memo(
({ files = {}, onFileSelect, selectedFile, rootFolder, hiddenFiles, className, unsavedFiles }: Props) => { ({
files = {},
onFileSelect,
selectedFile,
rootFolder,
hideRoot = false,
collapsed = false,
allowFolderSelection = false,
hiddenFiles,
className,
unsavedFiles,
}: Props) => {
renderLogger.trace('FileTree'); renderLogger.trace('FileTree');
const computedHiddenFiles = useMemo(() => [...DEFAULT_HIDDEN_FILES, ...(hiddenFiles ?? [])], [hiddenFiles]); const computedHiddenFiles = useMemo(() => [...DEFAULT_HIDDEN_FILES, ...(hiddenFiles ?? [])], [hiddenFiles]);
const fileList = useMemo(() => { const fileList = useMemo(() => {
return buildFileList(files, rootFolder, computedHiddenFiles); return buildFileList(files, rootFolder, hideRoot, computedHiddenFiles);
}, [files, rootFolder, computedHiddenFiles]); }, [files, rootFolder, hideRoot, computedHiddenFiles]);
const [collapsedFolders, setCollapsedFolders] = useState(() => new Set<string>()); const [collapsedFolders, setCollapsedFolders] = useState(() => {
return collapsed
? new Set(fileList.filter((item) => item.kind === 'folder').map((item) => item.fullPath))
: new Set<string>();
});
useEffect(() => { useEffect(() => {
if (collapsed) {
setCollapsedFolders(new Set(fileList.filter((item) => item.kind === 'folder').map((item) => item.fullPath)));
return;
}
setCollapsedFolders((prevCollapsed) => { setCollapsedFolders((prevCollapsed) => {
const newCollapsed = new Set<string>(); const newCollapsed = new Set<string>();
@ -42,7 +65,7 @@ export const FileTree = memo(
return newCollapsed; return newCollapsed;
}); });
}, [fileList]); }, [fileList, collapsed]);
const filteredFileList = useMemo(() => { const filteredFileList = useMemo(() => {
const list = []; const list = [];
@ -109,6 +132,7 @@ export const FileTree = memo(
<Folder <Folder
key={fileOrFolder.id} key={fileOrFolder.id}
folder={fileOrFolder} folder={fileOrFolder}
selected={allowFolderSelection && selectedFile === fileOrFolder.fullPath}
collapsed={collapsedFolders.has(fileOrFolder.fullPath)} collapsed={collapsedFolders.has(fileOrFolder.fullPath)}
onClick={() => { onClick={() => {
toggleCollapseState(fileOrFolder.fullPath); toggleCollapseState(fileOrFolder.fullPath);
@ -131,13 +155,18 @@ export default FileTree;
interface FolderProps { interface FolderProps {
folder: FolderNode; folder: FolderNode;
collapsed: boolean; collapsed: boolean;
selected?: boolean;
onClick: () => void; onClick: () => void;
} }
function Folder({ folder: { depth, name }, collapsed, onClick }: FolderProps) { function Folder({ folder: { depth, name }, collapsed, selected = false, onClick }: FolderProps) {
return ( return (
<NodeButton <NodeButton
className="group bg-transparent text-bolt-elements-item-contentDefault hover:text-bolt-elements-item-contentActive hover:bg-bolt-elements-item-backgroundActive" className={classNames('group', {
'bg-transparent text-bolt-elements-item-contentDefault hover:text-bolt-elements-item-contentActive hover:bg-bolt-elements-item-backgroundActive':
!selected,
'bg-bolt-elements-item-backgroundAccent text-bolt-elements-item-contentAccent': selected,
})}
depth={depth} depth={depth}
iconClasses={classNames({ iconClasses={classNames({
'i-ph:caret-right scale-98': collapsed, 'i-ph:caret-right scale-98': collapsed,
@ -223,13 +252,18 @@ interface FolderNode extends BaseNode {
kind: 'folder'; kind: 'folder';
} }
function buildFileList(files: FileMap, rootFolder = '/', hiddenFiles: Array<string | RegExp>): Node[] { function buildFileList(
files: FileMap,
rootFolder = '/',
hideRoot: boolean,
hiddenFiles: Array<string | RegExp>,
): Node[] {
const folderPaths = new Set<string>(); const folderPaths = new Set<string>();
const fileList: Node[] = []; const fileList: Node[] = [];
let defaultDepth = 0; let defaultDepth = 0;
if (rootFolder === '/') { if (rootFolder === '/' && !hideRoot) {
defaultDepth = 1; defaultDepth = 1;
fileList.push({ kind: 'folder', name: '/', depth: 0, id: 0, fullPath: '/' }); fileList.push({ kind: 'folder', name: '/', depth: 0, id: 0, fullPath: '/' });
} }
@ -251,7 +285,7 @@ function buildFileList(files: FileMap, rootFolder = '/', hiddenFiles: Array<stri
const name = segments[i]; const name = segments[i];
const fullPath = (currentPath += `/${name}`); const fullPath = (currentPath += `/${name}`);
if (!fullPath.startsWith(rootFolder)) { if (!fullPath.startsWith(rootFolder) || (hideRoot && fullPath === rootFolder)) {
i++; i++;
continue; continue;
} }
@ -281,7 +315,7 @@ function buildFileList(files: FileMap, rootFolder = '/', hiddenFiles: Array<stri
} }
} }
return sortFileList(rootFolder, fileList); return sortFileList(rootFolder, fileList, hideRoot);
} }
function isHiddenFile(filePath: string, fileName: string, hiddenFiles: Array<string | RegExp>) { function isHiddenFile(filePath: string, fileName: string, hiddenFiles: Array<string | RegExp>) {
@ -307,7 +341,7 @@ function isHiddenFile(filePath: string, fileName: string, hiddenFiles: Array<str
* *
* @returns A new array of nodes sorted in depth-first order. * @returns A new array of nodes sorted in depth-first order.
*/ */
function sortFileList(rootFolder: string, nodeList: Node[]): Node[] { function sortFileList(rootFolder: string, nodeList: Node[], hideRoot: boolean): Node[] {
logger.trace('sortFileList'); logger.trace('sortFileList');
const nodeMap = new Map<string, Node>(); const nodeMap = new Map<string, Node>();
@ -335,13 +369,10 @@ function sortFileList(rootFolder: string, nodeList: Node[]): Node[] {
const depthFirstTraversal = (path: string): void => { const depthFirstTraversal = (path: string): void => {
const node = nodeMap.get(path); const node = nodeMap.get(path);
if (!node) { if (node) {
logger.warn(`Node not found for path: ${path}`); sortedList.push(node);
return;
} }
sortedList.push(node);
const children = childrenMap.get(path); const children = childrenMap.get(path);
if (children) { if (children) {
@ -355,7 +386,16 @@ function sortFileList(rootFolder: string, nodeList: Node[]): Node[] {
} }
}; };
depthFirstTraversal(rootFolder); if (hideRoot) {
// if root is hidden, start traversal from its immediate children
const rootChildren = childrenMap.get(rootFolder) || [];
for (const child of rootChildren) {
depthFirstTraversal(child.fullPath);
}
} else {
depthFirstTraversal(rootFolder);
}
return sortedList; return sortedList;
} }

View File

@ -24,6 +24,10 @@ $zIndexMax: 999;
z-index: 3; z-index: 3;
} }
.z-file-tree-breadcrumb {
z-index: $zIndexMax - 1;
}
.z-max { .z-max {
z-index: $zIndexMax; z-index: $zIndexMax;
} }

View File

@ -36,6 +36,7 @@
"@iconify-json/svg-spinners": "^1.1.2", "@iconify-json/svg-spinners": "^1.1.2",
"@lezer/highlight": "^1.2.0", "@lezer/highlight": "^1.2.0",
"@nanostores/react": "^0.7.2", "@nanostores/react": "^0.7.2",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@remix-run/cloudflare": "^2.10.2", "@remix-run/cloudflare": "^2.10.2",
"@remix-run/cloudflare-pages": "^2.10.2", "@remix-run/cloudflare-pages": "^2.10.2",
"@remix-run/react": "^2.10.2", "@remix-run/react": "^2.10.2",

View File

@ -95,6 +95,9 @@ importers:
'@nanostores/react': '@nanostores/react':
specifier: ^0.7.2 specifier: ^0.7.2
version: 0.7.2(nanostores@0.10.3)(react@18.3.1) version: 0.7.2(nanostores@0.10.3)(react@18.3.1)
'@radix-ui/react-dropdown-menu':
specifier: ^2.1.1
version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@remix-run/cloudflare': '@remix-run/cloudflare':
specifier: ^2.10.2 specifier: ^2.10.2
version: 2.10.2(@cloudflare/workers-types@4.20240620.0)(typescript@5.5.2) version: 2.10.2(@cloudflare/workers-types@4.20240620.0)(typescript@5.5.2)
@ -1085,6 +1088,21 @@ packages:
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
engines: {node: '>=14'} engines: {node: '>=14'}
'@floating-ui/core@1.6.7':
resolution: {integrity: sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==}
'@floating-ui/dom@1.6.10':
resolution: {integrity: sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==}
'@floating-ui/react-dom@2.1.1':
resolution: {integrity: sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
'@floating-ui/utils@0.2.7':
resolution: {integrity: sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==}
'@humanwhocodes/module-importer@1.0.1': '@humanwhocodes/module-importer@1.0.1':
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
engines: {node: '>=12.22'} engines: {node: '>=12.22'}
@ -1231,6 +1249,263 @@ packages:
'@polka/url@1.0.0-next.25': '@polka/url@1.0.0-next.25':
resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==}
'@radix-ui/primitive@1.1.0':
resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==}
'@radix-ui/react-arrow@1.1.0':
resolution: {integrity: sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-collection@1.1.0':
resolution: {integrity: sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-compose-refs@1.1.0':
resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-context@1.1.0':
resolution: {integrity: sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-direction@1.1.0':
resolution: {integrity: sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-dismissable-layer@1.1.0':
resolution: {integrity: sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-dropdown-menu@2.1.1':
resolution: {integrity: sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-focus-guards@1.1.0':
resolution: {integrity: sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-focus-scope@1.1.0':
resolution: {integrity: sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-id@1.1.0':
resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-menu@2.1.1':
resolution: {integrity: sha512-oa3mXRRVjHi6DZu/ghuzdylyjaMXLymx83irM7hTxutQbD+7IhPKdMdRHD26Rm+kHRrWcrUkkRPv5pd47a2xFQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-popper@1.2.0':
resolution: {integrity: sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-portal@1.1.1':
resolution: {integrity: sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-presence@1.1.0':
resolution: {integrity: sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-primitive@2.0.0':
resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-roving-focus@1.1.0':
resolution: {integrity: sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-slot@1.1.0':
resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-use-callback-ref@1.1.0':
resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-use-controllable-state@1.1.0':
resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-use-escape-keydown@1.1.0':
resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-use-layout-effect@1.1.0':
resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-use-rect@1.1.0':
resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-use-size@1.1.0':
resolution: {integrity: sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/rect@1.1.0':
resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==}
'@remix-run/cloudflare-pages@2.10.2': '@remix-run/cloudflare-pages@2.10.2':
resolution: {integrity: sha512-HaOdGkSMhe4zg1M8KDNNKb7VgBIHGpi0/90aLdYmzvZy+yeR0NOdrQh4P6gAYGCGSzqttuPOEIr4laXtBKI7Yg==} resolution: {integrity: sha512-HaOdGkSMhe4zg1M8KDNNKb7VgBIHGpi0/90aLdYmzvZy+yeR0NOdrQh4P6gAYGCGSzqttuPOEIr4laXtBKI7Yg==}
engines: {node: '>=18.0.0'} engines: {node: '>=18.0.0'}
@ -1883,6 +2158,10 @@ packages:
argparse@2.0.1: argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
aria-hidden@1.2.4:
resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==}
engines: {node: '>=10'}
aria-query@5.3.0: aria-query@5.3.0:
resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
@ -2372,6 +2651,9 @@ packages:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
detect-node-es@1.1.0:
resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
devlop@1.1.0: devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
@ -2789,6 +3071,10 @@ packages:
resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
get-nonce@1.0.1:
resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
engines: {node: '>=6'}
get-port@5.1.1: get-port@5.1.1:
resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -3011,6 +3297,9 @@ packages:
inline-style-parser@0.2.3: inline-style-parser@0.2.3:
resolution: {integrity: sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==} resolution: {integrity: sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==}
invariant@2.2.4:
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
ipaddr.js@1.9.1: ipaddr.js@1.9.1:
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
@ -4205,6 +4494,26 @@ packages:
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
react-remove-scroll-bar@2.3.6:
resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@types/react':
optional: true
react-remove-scroll@2.5.7:
resolution: {integrity: sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@types/react':
optional: true
react-resizable-panels@2.0.20: react-resizable-panels@2.0.20:
resolution: {integrity: sha512-aMbK3VF8U+VBICG+rwhE0Rr/eFZaRzmNq3akBRL1TrayIpLXz7Rbok0//kYeWj6SQRsjcQ3f4eRplJicM+oL6w==} resolution: {integrity: sha512-aMbK3VF8U+VBICG+rwhE0Rr/eFZaRzmNq3akBRL1TrayIpLXz7Rbok0//kYeWj6SQRsjcQ3f4eRplJicM+oL6w==}
peerDependencies: peerDependencies:
@ -4224,6 +4533,16 @@ packages:
peerDependencies: peerDependencies:
react: '>=16.8' react: '>=16.8'
react-style-singleton@2.2.1:
resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@types/react':
optional: true
react-toastify@10.0.5: react-toastify@10.0.5:
resolution: {integrity: sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==} resolution: {integrity: sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==}
peerDependencies: peerDependencies:
@ -4874,6 +5193,26 @@ packages:
url@0.11.3: url@0.11.3:
resolution: {integrity: sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==} resolution: {integrity: sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==}
use-callback-ref@1.3.2:
resolution: {integrity: sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@types/react':
optional: true
use-sidecar@1.1.2:
resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@types/react':
optional: true
use-sync-external-store@1.2.2: use-sync-external-store@1.2.2:
resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==}
peerDependencies: peerDependencies:
@ -5999,6 +6338,23 @@ snapshots:
'@fastify/busboy@2.1.1': {} '@fastify/busboy@2.1.1': {}
'@floating-ui/core@1.6.7':
dependencies:
'@floating-ui/utils': 0.2.7
'@floating-ui/dom@1.6.10':
dependencies:
'@floating-ui/core': 1.6.7
'@floating-ui/utils': 0.2.7
'@floating-ui/react-dom@2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/dom': 1.6.10
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@floating-ui/utils@0.2.7': {}
'@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/module-importer@1.0.1': {}
'@humanwhocodes/retry@0.3.0': {} '@humanwhocodes/retry@0.3.0': {}
@ -6206,6 +6562,238 @@ snapshots:
'@polka/url@1.0.0-next.25': {} '@polka/url@1.0.0-next.25': {}
'@radix-ui/primitive@1.1.0': {}
'@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(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.3
'@types/react-dom': 18.3.0
'@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-context@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-direction@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.0
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(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.3)(react@18.3.1)
'@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-dropdown-menu@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.0
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-menu': 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(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.3)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-focus-guards@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(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.3)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-id@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-menu@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.0
'@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1)
aria-hidden: 1.2.4
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-remove-scroll: 2.5.7(@types/react@18.3.3)(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-popper@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/react-dom': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-arrow': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(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.3)(react@18.3.1)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-use-rect': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-use-size': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/rect': 1.1.0
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-portal@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(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.3)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-presence@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-primitive@2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-roving-focus@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.0
'@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(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.3)(react@18.3.1)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-slot@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-use-rect@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
'@radix-ui/rect': 1.1.0
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-use-size@1.1.0(@types/react@18.3.3)(react@18.3.1)':
dependencies:
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/rect@1.1.0': {}
'@remix-run/cloudflare-pages@2.10.2(@cloudflare/workers-types@4.20240620.0)(typescript@5.5.2)': '@remix-run/cloudflare-pages@2.10.2(@cloudflare/workers-types@4.20240620.0)(typescript@5.5.2)':
dependencies: dependencies:
'@cloudflare/workers-types': 4.20240620.0 '@cloudflare/workers-types': 4.20240620.0
@ -7092,6 +7680,10 @@ snapshots:
argparse@2.0.1: {} argparse@2.0.1: {}
aria-hidden@1.2.4:
dependencies:
tslib: 2.6.3
aria-query@5.3.0: aria-query@5.3.0:
dependencies: dependencies:
dequal: 2.0.3 dequal: 2.0.3
@ -7621,6 +8213,8 @@ snapshots:
destroy@1.2.0: {} destroy@1.2.0: {}
detect-node-es@1.1.0: {}
devlop@1.1.0: devlop@1.1.0:
dependencies: dependencies:
dequal: 2.0.3 dequal: 2.0.3
@ -8156,6 +8750,8 @@ snapshots:
has-symbols: 1.0.3 has-symbols: 1.0.3
hasown: 2.0.2 hasown: 2.0.2
get-nonce@1.0.1: {}
get-port@5.1.1: {} get-port@5.1.1: {}
get-source@2.0.12: get-source@2.0.12:
@ -8429,6 +9025,10 @@ snapshots:
inline-style-parser@0.2.3: {} inline-style-parser@0.2.3: {}
invariant@2.2.4:
dependencies:
loose-envify: 1.4.0
ipaddr.js@1.9.1: {} ipaddr.js@1.9.1: {}
is-alphabetical@2.0.1: {} is-alphabetical@2.0.1: {}
@ -9978,6 +10578,25 @@ snapshots:
react-refresh@0.14.2: {} react-refresh@0.14.2: {}
react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.3.1):
dependencies:
react: 18.3.1
react-style-singleton: 2.2.1(@types/react@18.3.3)(react@18.3.1)
tslib: 2.6.3
optionalDependencies:
'@types/react': 18.3.3
react-remove-scroll@2.5.7(@types/react@18.3.3)(react@18.3.1):
dependencies:
react: 18.3.1
react-remove-scroll-bar: 2.3.6(@types/react@18.3.3)(react@18.3.1)
react-style-singleton: 2.2.1(@types/react@18.3.3)(react@18.3.1)
tslib: 2.6.3
use-callback-ref: 1.3.2(@types/react@18.3.3)(react@18.3.1)
use-sidecar: 1.1.2(@types/react@18.3.3)(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
react-resizable-panels@2.0.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1): react-resizable-panels@2.0.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies: dependencies:
react: 18.3.1 react: 18.3.1
@ -9995,6 +10614,15 @@ snapshots:
'@remix-run/router': 1.17.1 '@remix-run/router': 1.17.1
react: 18.3.1 react: 18.3.1
react-style-singleton@2.2.1(@types/react@18.3.3)(react@18.3.1):
dependencies:
get-nonce: 1.0.1
invariant: 2.2.4
react: 18.3.1
tslib: 2.6.3
optionalDependencies:
'@types/react': 18.3.3
react-toastify@10.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): react-toastify@10.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies: dependencies:
clsx: 2.1.1 clsx: 2.1.1
@ -10742,6 +11370,21 @@ snapshots:
punycode: 1.4.1 punycode: 1.4.1
qs: 6.12.3 qs: 6.12.3
use-callback-ref@1.3.2(@types/react@18.3.3)(react@18.3.1):
dependencies:
react: 18.3.1
tslib: 2.6.3
optionalDependencies:
'@types/react': 18.3.3
use-sidecar@1.1.2(@types/react@18.3.3)(react@18.3.1):
dependencies:
detect-node-es: 1.1.0
react: 18.3.1
tslib: 2.6.3
optionalDependencies:
'@types/react': 18.3.3
use-sync-external-store@1.2.2(react@18.3.1): use-sync-external-store@1.2.2(react@18.3.1):
dependencies: dependencies:
react: 18.3.1 react: 18.3.1