UI: Replace cmdk with custom implementation

This commit is contained in:
Fuma Nama
2024-10-31 18:08:00 +08:00
parent e248a0f813
commit 7a5393bc10
10 changed files with 288 additions and 534 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-ui': minor
---
Replace `cmdk` with custom implementation
@@ -53,7 +53,7 @@ export async function searchDocs(
id: doc.id,
content: doc.content,
type: doc.content === doc.section ? 'heading' : 'text',
url: doc.url,
url: doc.section_id ? `${doc.url}#${doc.section_id}` : doc.url,
});
}
}
-11
View File
@@ -94,17 +94,6 @@ export async function sync(
if (autoDeploy) await index.deploy();
}
const a = {
id: 'string',
title: 'string',
url: 'string',
tag: 'string',
page_id: 'string',
section: 'string',
section_id: 'string',
content: 'string',
};
export async function syncI18n(
cloudManager: CloudManager,
options: I18nSyncOptions,
-1
View File
@@ -74,7 +74,6 @@
"@radix-ui/react-tabs": "^1.1.1",
"@tailwindcss/typography": "^0.5.15",
"class-variance-authority": "^0.7.0",
"cmdk": "^1.0.0",
"fumadocs-core": "workspace:*",
"next-themes": "^0.3.0",
"react-medium-image-zoom": "^5.2.10",
@@ -6,12 +6,8 @@ import {
} from 'fumadocs-core/search/client';
import { type ReactNode, useState } from 'react';
import { useOnChange } from 'fumadocs-core/utils/use-on-change';
import {
SearchDialog,
type SharedProps,
type TagItem,
TagsList,
} from './search';
import { SearchDialog, type SharedProps } from './search';
import { type TagItem, TagsList } from './tag-list';
export interface AlgoliaSearchDialogProps extends SharedProps {
index: AlgoliaOptions['index'];
@@ -4,12 +4,8 @@ import { useDocsSearch } from 'fumadocs-core/search/client';
import { type ReactNode, useState } from 'react';
import { useOnChange } from 'fumadocs-core/utils/use-on-change';
import { useI18n } from '@/contexts/i18n';
import {
SearchDialog,
type SharedProps,
type TagItem,
TagsList,
} from './search';
import { SearchDialog, type SharedProps } from './search';
import { type TagItem, TagsList } from './tag-list';
export interface DefaultSearchDialogProps extends SharedProps {
/**
@@ -48,7 +44,7 @@ export default function DefaultSearchDialog({
type = 'fetch',
allowClear = false,
...props
}: DefaultSearchDialogProps): React.ReactElement {
}: DefaultSearchDialogProps): ReactNode {
const { locale } = useI18n();
const [tag, setTag] = useState(defaultTag);
const { search, setSearch, query } = useDocsSearch(
@@ -6,12 +6,8 @@ import {
} from 'fumadocs-core/search/client';
import { type ReactNode, useState } from 'react';
import { useOnChange } from 'fumadocs-core/utils/use-on-change';
import {
SearchDialog,
type SharedProps,
type TagItem,
TagsList,
} from './search';
import { SearchDialog, type SharedProps } from './search';
import { type TagItem, TagsList } from './tag-list';
export interface OramaSearchDialogProps extends SharedProps {
client: OramaCloudOptions['client'];
+214 -149
View File
@@ -1,25 +1,27 @@
'use client';
import { FileText, Hash, Loader2, SearchIcon, Text } from 'lucide-react';
import type { SortedResult } from 'fumadocs-core/server';
import { useRouter } from 'next/navigation';
import {
useMemo,
type ReactNode,
type HTMLAttributes,
type ReactElement,
useEffect,
useState,
useRef,
type ButtonHTMLAttributes,
} from 'react';
import { cva } from 'class-variance-authority';
import { useI18n } from '@/contexts/i18n';
import {
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandDialog,
} from '@/components/ui/command';
import { cn } from '@/utils/cn';
import { useSearchContext } from '@/contexts/search';
import { useSidebar } from '@/contexts/sidebar';
import { buttonVariants } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogOverlay,
DialogTitle,
} from '@radix-ui/react-dialog';
export type SearchLink = [name: string, href: string];
@@ -33,20 +35,22 @@ export interface SharedProps {
links?: SearchLink[];
}
interface SearchDialogProps
extends SharedProps,
Omit<SearchContentProps, 'items'> {
results: SortedResult[] | 'empty';
type SearchDialogProps = SharedProps &
SearchValueProps &
Omit<SearchResultProps, 'items'> & {
results: SortedResult[] | 'empty';
footer?: ReactNode;
}
footer?: ReactNode;
};
interface SearchContentProps {
interface SearchValueProps {
search: string;
onSearchChange: (v: string) => void;
isLoading?: boolean;
items: SortedResult[];
}
interface SearchResultProps {
items: SortedResult[];
hideResults?: boolean;
}
@@ -56,8 +60,9 @@ export function SearchDialog({
footer,
links = [],
...props
}: SearchDialogProps): ReactElement {
const defaultItems: SortedResult[] = useMemo(
}: SearchDialogProps) {
const { text } = useI18n();
const defaultItems = useMemo<SortedResult[]>(
() =>
links.map(([name, link]) => ({
type: 'page',
@@ -69,148 +74,208 @@ export function SearchDialog({
);
return (
<CommandDialog open={open} onOpenChange={onOpenChange}>
<Search
{...props}
items={props.results === 'empty' ? defaultItems : props.results}
hideResults={props.results === 'empty' && defaultItems.length === 0}
/>
{footer ? (
<div className="mt-auto flex flex-col border-t p-3">{footer}</div>
) : null}
</CommandDialog>
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogOverlay className="fixed inset-0 z-50 bg-fd-background/50 backdrop-blur-sm data-[state=closed]:animate-fd-fade-out data-[state=open]:animate-fd-fade-in" />
<DialogContent
aria-describedby={text.search}
className="fixed left-1/2 top-[10vh] z-50 w-[98vw] max-w-screen-sm origin-left -translate-x-1/2 rounded-lg border bg-fd-popover text-fd-popover-foreground shadow-lg data-[state=closed]:animate-fd-dialog-out data-[state=open]:animate-fd-dialog-in"
>
<DialogTitle className="hidden">{text.search}</DialogTitle>
<SearchInput
search={props.search}
onSearchChange={props.onSearchChange}
isLoading={props.isLoading}
/>
<SearchList
items={props.results === 'empty' ? defaultItems : props.results}
hideResults={props.results === 'empty' && defaultItems.length === 0}
/>
{footer ? (
<div className="mt-auto flex flex-col border-t p-3">{footer}</div>
) : null}
</DialogContent>
</Dialog>
);
}
const icons = {
text: <Text />,
heading: <Hash />,
page: <FileText />,
text: <Text className="size-4 text-fd-muted-foreground" />,
heading: <Hash className="size-4 text-fd-muted-foreground" />,
page: <FileText className="size-4 text-fd-muted-foreground" />,
};
function Search({
search,
onSearchChange,
items,
isLoading,
hideResults = false,
}: SearchContentProps): ReactElement {
function SearchInput({ search, onSearchChange, isLoading }: SearchValueProps) {
const { text } = useI18n();
const router = useRouter();
const { setOpenSearch } = useSearchContext();
const sidebar = useSidebar();
const onOpen = (url: string): void => {
router.push(url);
setOpenSearch(false);
if (location.pathname === url.split('#')[0]) {
sidebar.setOpen(false);
}
};
return (
<>
<CommandInput
<div className="flex flex-row items-center gap-2 px-3">
<LoadingIndicator isLoading={isLoading ?? false} />
<input
value={search}
onValueChange={onSearchChange}
onClose={() => {
setOpenSearch(false);
onChange={(e) => {
onSearchChange(e.target.value);
}}
placeholder={text.search}
className="w-full min-w-0 bg-transparent py-3 text-base placeholder:text-fd-muted-foreground focus-visible:outline-none"
/>
<button
type="button"
aria-label="Close Search"
onClick={() => {
setOpenSearch(false);
}}
className={cn(
buttonVariants({
color: 'outline',
className: 'text-xs p-1.5',
}),
)}
>
<div className="relative size-4">
<Loader2
className={cn(
'absolute size-full animate-spin text-fd-primary transition-opacity',
!isLoading && 'opacity-0',
)}
/>
<SearchIcon
className={cn(
'absolute size-full text-fd-muted-foreground transition-opacity',
isLoading && 'opacity-0',
)}
/>
</div>
</CommandInput>
<CommandList className={cn(hideResults && 'hidden')}>
<CommandEmpty>{text.searchNoResult}</CommandEmpty>
<CommandGroup value="result">
{items.map((item) => (
<CommandItem
key={item.id}
value={item.id}
onSelect={() => {
onOpen(item.url);
}}
icon={icons[item.type]}
nested={item.type !== 'page'}
>
{item.content}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</>
);
}
const itemVariants = cva(
'rounded-md border px-2 py-0.5 text-xs font-medium text-fd-muted-foreground transition-colors',
{
variants: {
active: {
true: 'bg-fd-accent text-fd-accent-foreground',
},
},
},
);
export interface TagItem {
name: string;
value: string | undefined;
}
export interface TagsListProps extends HTMLAttributes<HTMLDivElement> {
tag?: string;
onTagChange: (tag: string | undefined) => void;
allowClear?: boolean;
items: TagItem[];
}
export function TagsList({
tag,
onTagChange,
items,
allowClear,
...props
}: TagsListProps): ReactNode {
return (
<div
{...props}
className={cn('flex flex-row items-center gap-1', props.className)}
>
{items.map((item) => (
<button
type="button"
key={item.value}
className={cn(itemVariants({ active: tag === item.value }))}
onClick={() => {
if (tag === item.value && allowClear) {
onTagChange(undefined);
} else {
onTagChange(item.value);
}
}}
tabIndex={-1}
>
{item.name}
</button>
))}
{props.children}
Esc
</button>
</div>
);
}
function SearchList({ items, hideResults = false }: SearchResultProps) {
const [active, setActive] = useState<string>();
const { text } = useI18n();
const router = useRouter();
const sidebar = useSidebar();
const { setOpenSearch } = useSearchContext();
const listenerRef = useRef<(e: KeyboardEvent) => void>();
listenerRef.current = (e) => {
if (e.key === 'ArrowDown' || e.key == 'ArrowUp') {
setActive((cur) => {
const idx = items.findIndex((item) => item.id === cur);
if (idx === -1) return items.at(0)?.id;
return items.at(
(e.key === 'ArrowDown' ? idx + 1 : idx - 1) % items.length,
)?.id;
});
e.preventDefault();
}
if (e.key === 'Enter') {
const selected = items.find((item) => item.id === active);
if (selected) onOpen(selected.url);
e.preventDefault();
}
};
useEffect(() => {
const listener = (e: KeyboardEvent) => {
listenerRef.current?.(e);
};
window.addEventListener('keydown', listener);
return () => {
window.removeEventListener('keydown', listener);
};
}, []);
const onOpen = (url: string) => {
router.push(url);
setOpenSearch(false);
sidebar.setOpen(false);
};
return (
<div
className={cn(
'flex max-h-[460px] flex-col overflow-y-auto border-t p-2',
hideResults && 'hidden',
)}
>
{items.length === 0 ? (
<div className="py-12 text-center text-sm">{text.searchNoResult}</div>
) : null}
{items.map((item) => (
<CommandItem
key={item.id}
value={item.id}
active={active}
onActiveChange={setActive}
onClick={() => {
onOpen(item.url);
}}
>
{item.type !== 'page' ? (
<div
role="none"
className="ms-2 h-full min-h-10 w-px bg-fd-border"
/>
) : null}
{icons[item.type]}
<p className="truncate">{item.content}</p>
</CommandItem>
))}
</div>
);
}
function LoadingIndicator({ isLoading }: { isLoading: boolean }) {
return (
<div className="relative size-4">
<Loader2
className={cn(
'absolute size-full animate-spin text-fd-primary transition-opacity',
!isLoading && 'opacity-0',
)}
/>
<SearchIcon
className={cn(
'absolute size-full text-fd-muted-foreground transition-opacity',
isLoading && 'opacity-0',
)}
/>
</div>
);
}
function CommandItem({
active,
onActiveChange,
value,
...props
}: ButtonHTMLAttributes<HTMLButtonElement> & {
value: string;
active?: string;
onActiveChange: (value: string) => void;
}) {
const ref = useRef<HTMLButtonElement>(null);
useEffect(() => {
const element = ref.current;
if (active === value && element) {
element.scrollIntoView({
block: 'nearest',
});
}
}, [active, value]);
return (
<button
ref={ref}
type="button"
aria-selected={active === value}
onPointerEnter={() => {
onActiveChange(value);
}}
{...props}
className={cn(
'flex min-h-10 select-none flex-row items-center gap-2.5 rounded-lg px-2 text-start text-sm aria-disabled:pointer-events-none aria-disabled:opacity-50 aria-selected:bg-fd-accent aria-selected:text-fd-accent-foreground',
props.className,
)}
>
{props.children}
</button>
);
}
@@ -0,0 +1,61 @@
import type { HTMLAttributes } from 'react';
import { cva } from 'class-variance-authority';
import { cn } from '@/utils/cn';
export interface TagItem {
name: string;
value: string | undefined;
}
export interface TagsListProps extends HTMLAttributes<HTMLDivElement> {
tag?: string;
onTagChange: (tag: string | undefined) => void;
allowClear?: boolean;
items: TagItem[];
}
const itemVariants = cva(
'rounded-md border px-2 py-0.5 text-xs font-medium text-fd-muted-foreground transition-colors',
{
variants: {
active: {
true: 'bg-fd-accent text-fd-accent-foreground',
},
},
},
);
export function TagsList({
tag,
onTagChange,
items,
allowClear,
...props
}: TagsListProps) {
return (
<div
{...props}
className={cn('flex flex-row items-center gap-1', props.className)}
>
{items.map((item) => (
<button
type="button"
key={item.value}
className={cn(itemVariants({ active: tag === item.value }))}
onClick={() => {
if (tag === item.value && allowClear) {
onTagChange(undefined);
} else {
onTagChange(item.value);
}
}}
tabIndex={-1}
>
{item.name}
</button>
))}
{props.children}
</div>
);
}
-353
View File
@@ -1119,9 +1119,6 @@ importers:
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
cmdk:
specifier: ^1.0.0
version: 1.0.0(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
fumadocs-core:
specifier: workspace:*
version: link:../core
@@ -2246,9 +2243,6 @@ packages:
'@radix-ui/[email protected]':
resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==}
'@radix-ui/[email protected]':
resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==}
'@radix-ui/[email protected]':
resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==}
@@ -2304,15 +2298,6 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==}
peerDependencies:
@@ -2322,15 +2307,6 @@ packages:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==}
peerDependencies:
@@ -2349,19 +2325,6 @@ packages:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==}
peerDependencies:
@@ -2384,19 +2347,6 @@ packages:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==}
peerDependencies:
@@ -2410,15 +2360,6 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==}
peerDependencies:
@@ -2428,19 +2369,6 @@ packages:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==}
peerDependencies:
@@ -2454,15 +2382,6 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==}
peerDependencies:
@@ -2511,19 +2430,6 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==}
peerDependencies:
@@ -2537,19 +2443,6 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==}
peerDependencies:
@@ -2563,19 +2456,6 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==}
peerDependencies:
@@ -2628,15 +2508,6 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==}
peerDependencies:
@@ -2672,15 +2543,6 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==}
peerDependencies:
@@ -2690,15 +2552,6 @@ packages:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==}
peerDependencies:
@@ -2708,15 +2561,6 @@ packages:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==}
peerDependencies:
@@ -2726,15 +2570,6 @@ packages:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/[email protected]':
resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==}
peerDependencies:
@@ -3608,12 +3443,6 @@ packages:
resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==}
engines: {node: '>=6'}
[email protected]:
resolution: {integrity: sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
[email protected]:
resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==}
@@ -5540,16 +5369,6 @@ packages:
'@types/react':
optional: true
[email protected]:
resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==}
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
[email protected]:
resolution: {integrity: sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==}
engines: {node: '>=10'}
@@ -7511,10 +7330,6 @@ snapshots:
'@radix-ui/[email protected]': {}
'@radix-ui/[email protected]':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/[email protected]': {}
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
@@ -7571,26 +7386,12 @@ snapshots:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@babel/runtime': 7.26.0
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@babel/runtime': 7.26.0
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
react: 18.3.1
@@ -7603,29 +7404,6 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/primitive': 1.0.1
'@radix-ui/react-compose-refs': 1.0.1(@types/[email protected])([email protected])
'@radix-ui/react-context': 1.0.1(@types/[email protected])([email protected])
'@radix-ui/react-dismissable-layer': 1.0.5(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
'@radix-ui/react-focus-guards': 1.0.1(@types/[email protected])([email protected])
'@radix-ui/react-focus-scope': 1.0.4(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
'@radix-ui/react-id': 1.0.1(@types/[email protected])([email protected])
'@radix-ui/react-portal': 1.0.4(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
'@radix-ui/react-presence': 1.0.1(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
'@radix-ui/react-primitive': 1.0.3(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
'@radix-ui/react-slot': 1.0.2(@types/[email protected])([email protected])
'@radix-ui/react-use-controllable-state': 1.0.1(@types/[email protected])([email protected])
aria-hidden: 1.2.4
react: 18.3.1
react-dom: 18.3.1([email protected])
react-remove-scroll: 2.5.5(@types/[email protected])([email protected])
optionalDependencies:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@radix-ui/primitive': 1.1.0
@@ -7654,20 +7432,6 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/primitive': 1.0.1
'@radix-ui/react-compose-refs': 1.0.1(@types/[email protected])([email protected])
'@radix-ui/react-primitive': 1.0.3(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
'@radix-ui/react-use-callback-ref': 1.0.1(@types/[email protected])([email protected])
'@radix-ui/react-use-escape-keydown': 1.0.3(@types/[email protected])([email protected])
react: 18.3.1
react-dom: 18.3.1([email protected])
optionalDependencies:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@radix-ui/primitive': 1.1.0
@@ -7681,31 +7445,12 @@ snapshots:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@babel/runtime': 7.26.0
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/react-compose-refs': 1.0.1(@types/[email protected])([email protected])
'@radix-ui/react-primitive': 1.0.3(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
'@radix-ui/react-use-callback-ref': 1.0.1(@types/[email protected])([email protected])
react: 18.3.1
react-dom: 18.3.1([email protected])
optionalDependencies:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@radix-ui/react-compose-refs': 1.1.0(@types/[email protected])([email protected])
@@ -7717,14 +7462,6 @@ snapshots:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/react-use-layout-effect': 1.0.1(@types/[email protected])([email protected])
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@radix-ui/react-use-layout-effect': 1.1.0(@types/[email protected])([email protected])
@@ -7795,16 +7532,6 @@ snapshots:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/react-primitive': 1.0.3(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
react: 18.3.1
react-dom: 18.3.1([email protected])
optionalDependencies:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@radix-ui/react-primitive': 2.0.0(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
@@ -7815,17 +7542,6 @@ snapshots:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/react-compose-refs': 1.0.1(@types/[email protected])([email protected])
'@radix-ui/react-use-layout-effect': 1.0.1(@types/[email protected])([email protected])
react: 18.3.1
react-dom: 18.3.1([email protected])
optionalDependencies:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@radix-ui/react-compose-refs': 1.1.0(@types/[email protected])([email protected])
@@ -7836,16 +7552,6 @@ snapshots:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/react-slot': 1.0.2(@types/[email protected])([email protected])
react: 18.3.1
react-dom: 18.3.1([email protected])
optionalDependencies:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@radix-ui/react-slot': 1.1.0(@types/[email protected])([email protected])
@@ -7918,14 +7624,6 @@ snapshots:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/react-compose-refs': 1.0.1(@types/[email protected])([email protected])
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@radix-ui/react-compose-refs': 1.1.0(@types/[email protected])([email protected])
@@ -7969,27 +7667,12 @@ snapshots:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@babel/runtime': 7.26.0
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/react-use-callback-ref': 1.0.1(@types/[email protected])([email protected])
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@radix-ui/react-use-callback-ref': 1.1.0(@types/[email protected])([email protected])
@@ -7997,14 +7680,6 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@babel/runtime': 7.26.0
'@radix-ui/react-use-callback-ref': 1.0.1(@types/[email protected])([email protected])
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@radix-ui/react-use-callback-ref': 1.1.0(@types/[email protected])([email protected])
@@ -8012,13 +7687,6 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
'@babel/runtime': 7.26.0
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@radix-ui/[email protected](@types/[email protected])([email protected])':
dependencies:
react: 18.3.1
@@ -8964,16 +8632,6 @@ snapshots:
[email protected]: {}
[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected]):
dependencies:
'@radix-ui/react-dialog': 1.0.5(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
'@radix-ui/react-primitive': 1.0.3(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
react: 18.3.1
react-dom: 18.3.1([email protected])
transitivePeerDependencies:
- '@types/react'
- '@types/react-dom'
[email protected]: {}
[email protected]: {}
@@ -11397,17 +11055,6 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.12
[email protected](@types/[email protected])([email protected]):
dependencies:
react: 18.3.1
react-remove-scroll-bar: 2.3.6(@types/[email protected])([email protected])
react-style-singleton: 2.2.1(@types/[email protected])([email protected])
tslib: 2.8.0
use-callback-ref: 1.3.2(@types/[email protected])([email protected])
use-sidecar: 1.1.2(@types/[email protected])([email protected])
optionalDependencies:
'@types/react': 18.3.12
[email protected](@types/[email protected])([email protected]):
dependencies:
react: 18.3.1