-
-
{'>'} Button
+
+
+ {'>'} Button
+
+
+
+ {'>'} Combobox
+
+
+
+ {'>'} Input
+
+
+
+ {'>'} Link
+
+
+
+ {'>'} Tooltip
+
- {'>'} Combobox
+
+ {'>'} Dropdown Menu
+
- {'>'} Input
+
+ {'>'} Collapsible
+
- {'>'} Link
+
+ {'>'} Sidebar
+
diff --git a/examples/ui-playground/src/app/playground/shadcn/sidebar/components/app-sidebar.tsx b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/app-sidebar.tsx
new file mode 100644
index 00000000..98d493ac
--- /dev/null
+++ b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/app-sidebar.tsx
@@ -0,0 +1,158 @@
+import * as React from 'react'
+
+import {
+ ChartLineUpIcon,
+ StackIcon,
+ StorefrontIcon,
+ TerminalWindowIcon,
+ TreeStructureIcon,
+ WaveformIcon,
+} from '@phosphor-icons/react'
+
+import {
+ Sidebar,
+ SidebarContent,
+ SidebarFooter,
+ SidebarHeader,
+ SidebarRail,
+} from '@genseki/react/v2'
+
+import { NavFooter } from './nav-footer'
+import { NavHeader } from './nav-header'
+import { NavMain } from './nav-main'
+
+// This is sample data.
+const data = {
+ teams: [
+ {
+ name: 'Acme Inc',
+ logo: StackIcon,
+ plan: 'Enterprise',
+ },
+ {
+ name: 'Acme Corp.',
+ logo: WaveformIcon,
+ plan: 'Startup',
+ },
+ {
+ name: 'Evil Corp.',
+ logo: TerminalWindowIcon,
+ plan: 'Free',
+ },
+ ],
+ navMain: [
+ {
+ title: 'Omni-Channel Management',
+ url: '#',
+ icon: TreeStructureIcon,
+ isActive: true,
+ items: [
+ {
+ title: 'Bplus Sync',
+ url: '#',
+ },
+ {
+ title: 'Product',
+ url: '#',
+ },
+ {
+ title: 'Delivery Fee (by Weight)',
+ url: '#',
+ },
+ {
+ title: 'Delivery Fee (by Carton)',
+ url: '#',
+ },
+ {
+ title: 'Order',
+ url: '#',
+ },
+ {
+ title: 'Data export',
+ url: '#',
+ },
+ {
+ title: 'Packing',
+ url: '#',
+ },
+ {
+ title: 'Inventory',
+ url: '#',
+ },
+ {
+ title: 'Inventory transfer',
+ url: '#',
+ },
+ ],
+ },
+ {
+ title: 'Dashboard',
+ url: '#',
+ icon: ChartLineUpIcon,
+ isActive: true,
+ items: [
+ {
+ title: 'User summary',
+ url: '#',
+ },
+ {
+ title: 'Sales reports',
+ url: '#',
+ },
+ {
+ title: 'Finance overview',
+ url: '#',
+ },
+ {
+ title: 'Growth analytics',
+ url: '#',
+ },
+ {
+ title: 'Performance metrics',
+ url: '#',
+ },
+ {
+ title: 'Engagement insights',
+ url: '#',
+ },
+ ],
+ },
+ {
+ title: 'Storefront Management',
+ url: '#',
+ icon: StorefrontIcon,
+ isActive: true,
+ items: [
+ {
+ title: 'Line shop',
+ url: '#',
+ },
+ {
+ title: 'Shopee',
+ url: '#',
+ },
+ {
+ title: 'Lazada',
+ url: '#',
+ },
+ ],
+ },
+ ],
+}
+
+export function AppSidebar({ ...props }: React.ComponentProps
) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-footer.tsx b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-footer.tsx
new file mode 100644
index 00000000..5b7c33ec
--- /dev/null
+++ b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-footer.tsx
@@ -0,0 +1,58 @@
+import { CaretUpDownIcon, SignOutIcon, UserIcon } from '@phosphor-icons/react'
+
+import { Typography } from '@genseki/react'
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+ SidebarMenu,
+ SidebarMenuItem,
+} from '@genseki/react/v2'
+
+import { cn } from '../../../../../../../../packages/react/src/react/utils/cn'
+
+function NavFooter() {
+ return (
+
+
+
+
+
+
+
+
+
+ Signout
+
+
+
+
+
+ )
+}
+
+export { NavFooter }
diff --git a/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-header.tsx b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-header.tsx
new file mode 100644
index 00000000..16bc966b
--- /dev/null
+++ b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-header.tsx
@@ -0,0 +1,38 @@
+import { MoonStarsIcon } from '@phosphor-icons/react'
+
+import { Typography } from '@genseki/react'
+import { SidebarMenu, SidebarMenuItem, SidebarTrigger } from '@genseki/react/v2'
+
+function NavHeader() {
+ return (
+
+
+
+
+
+
+
+
+ BRV
+
+
+ 1.0.1
+
+
+
+
+
+
+
+
+ )
+}
+
+export { NavHeader }
diff --git a/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-main.tsx b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-main.tsx
new file mode 100644
index 00000000..72cf2058
--- /dev/null
+++ b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-main.tsx
@@ -0,0 +1,99 @@
+'use client'
+
+import type { Icon } from '@phosphor-icons/react'
+import { CaretRightIcon } from '@phosphor-icons/react'
+import Link from 'next/link'
+
+import { Typography } from '@genseki/react'
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+ SidebarGroup,
+ SidebarMenu,
+ SidebarMenuButton,
+ SidebarMenuItem,
+ SidebarMenuSub,
+ SidebarMenuSubButton,
+ SidebarMenuSubItem,
+} from '@genseki/react/v2'
+
+import { cn } from '../../../../../../../../packages/react/src/react/utils/cn'
+
+function NavMain({
+ items,
+}: {
+ items: {
+ title: string
+ url: string
+ icon?: Icon
+ isActive?: boolean
+ items?: {
+ title: string
+ url: string
+ }[]
+ }[]
+}) {
+ return (
+
+
+ {items.map((item) => (
+
+
+
+
+ {item.icon && (
+
+ )}
+
+ {item.title}
+
+
+
+
+
+
+ {item.items?.map((subItem) => (
+
+
+
+
+ {subItem.title}
+
+
+
+
+ ))}
+
+
+
+
+ ))}
+
+
+ )
+}
+
+export { NavMain }
diff --git a/examples/ui-playground/src/app/playground/shadcn/sidebar/page.tsx b/examples/ui-playground/src/app/playground/shadcn/sidebar/page.tsx
new file mode 100644
index 00000000..23faafa7
--- /dev/null
+++ b/examples/ui-playground/src/app/playground/shadcn/sidebar/page.tsx
@@ -0,0 +1,56 @@
+'use client'
+
+import {
+ Breadcrumb,
+ BreadcrumbEllipsis,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbList,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+ SidebarInset,
+ SidebarProvider,
+ SidebarTrigger,
+} from '@genseki/react/v2'
+
+import { AppSidebar } from './components/app-sidebar'
+
+function DummySidebarPage() {
+ return (
+
+
+
+
+
+
+
+ )
+}
+
+export default DummySidebarPage
diff --git a/examples/ui-playground/src/app/playground/shadcn/tooltip-section.tsx b/examples/ui-playground/src/app/playground/shadcn/tooltip-section.tsx
new file mode 100644
index 00000000..fed62785
--- /dev/null
+++ b/examples/ui-playground/src/app/playground/shadcn/tooltip-section.tsx
@@ -0,0 +1,277 @@
+import React from 'react'
+
+import {
+ InfoIcon,
+ MagnifyingGlassIcon,
+ PaperPlaneRightIcon,
+ QuestionMarkIcon,
+ WarningIcon,
+} from '@phosphor-icons/react'
+
+import { Typography } from '@genseki/react'
+import { Button } from '@genseki/react/v2'
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@genseki/react/v2'
+
+import { PlaygroundCard } from '~/src/components/card'
+
+// Basic Tooltip
+function BasicTooltip() {
+ return (
+
+
+
+
+
+
+ This is a basic tooltip
+
+
+
+ )
+}
+
+// Tooltip with Icon
+function TooltipWithIcon() {
+ return (
+
+
+
+
+
+
+ Information tooltip
+
+
+
+
+
+
+
+
+ Warning tooltip
+
+
+
+
+
+
+
+
+ Help tooltip
+
+
+
+ )
+}
+
+// Tooltip Positions
+function TooltipPositions() {
+ return (
+
+
+
+
+
+
+
+ Tooltip on top
+
+
+
+
+
+
+
+
+
+
+ Tooltip on bottom
+
+
+
+
+
+
+
+
+
+
+ Tooltip on left
+
+
+
+
+
+
+
+
+
+
+ Tooltip on right
+
+
+
+
+ )
+}
+
+// Tooltip with Long Content
+function TooltipLongContent() {
+ return (
+
+
+
+
+
+
+ Send this email to the recipient. This action cannot be undone.
+
+
+
+
+
+
+
+
+ Search through all your documents and files for specific content.
+
+
+
+ )
+}
+
+// Tooltip Alignment
+function TooltipAlignment() {
+ return (
+
+
+
+
+
+
+
+ Aligned to start
+
+
+
+
+
+
+
+
+
+
+ Aligned to center
+
+
+
+
+
+
+
+
+
+
+ Aligned to end
+
+
+
+
+ )
+}
+
+// Disabled Tooltip
+function DisabledTooltip() {
+ return (
+
+
+
+
+
+
+ This button is disabled
+
+
+
+
+
+ )
+}
+
+export function TooltipSection() {
+ return (
+
+
+
+
+ A simple tooltip that appears on hover.
+
+
+
+
+
+
+
+
+ Tooltips can be used with icon buttons to provide additional context.
+
+
+
+
+
+
+
+
+ Tooltips can be positioned on any side of the trigger element.
+
+
+
+
+
+
+
+
+ Tooltips can contain longer text content with proper wrapping.
+
+
+
+
+
+
+
+
+ Control the alignment of tooltips relative to their trigger element.
+
+
+
+
+
+
+
+
+ Tooltips work with disabled elements to provide helpful information.
+
+
+
+
+
+
+
+ )
+}
diff --git a/packages/react/package.json b/packages/react/package.json
index 967c24df..ffdaa89e 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -52,11 +52,14 @@
"@intentui/icons": "^1.10.31",
"@internationalized/date": "^3.8.2",
"@phosphor-icons/react": "^2.1.8",
+ "@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.15",
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.2.0",
+ "@radix-ui/react-tooltip": "^1.2.8",
"@radix-ui/react-use-controllable-state": "^1.2.2",
"@react-aria/i18n": "^3.12.9",
"@react-aria/visually-hidden": "^3.8.23",
diff --git a/packages/react/src/react/components/primitives/breadcrumbs.tsx b/packages/react/src/react/components/primitives/breadcrumbs.tsx
index 50b5a425..71c61b71 100644
--- a/packages/react/src/react/components/primitives/breadcrumbs.tsx
+++ b/packages/react/src/react/components/primitives/breadcrumbs.tsx
@@ -9,14 +9,29 @@ import { twMerge } from 'tailwind-merge'
import { Link } from './link'
import { composeTailwindRenderProps } from './primitive'
+/**
+ *
+ * React Aria component
+ *
+ */
+
+/**
+ * @deprecated
+ */
interface BreadcrumbsContextProps {
separator?: 'chevron' | 'slash' | boolean
}
+/**
+ * @deprecated
+ */
const BreadcrumbsProvider = createContext({
separator: 'slash',
})
+/**
+ * @deprecated
+ */
const Breadcrumbs = ({
className,
...props
@@ -28,11 +43,17 @@ const Breadcrumbs = ({
)
}
+/**
+ * @deprecated
+ */
interface BreadcrumbsItemProps extends BreadcrumbProps, BreadcrumbsContextProps {
href?: string
trailing?: React.ReactNode
}
+/**
+ * @deprecated
+ */
const BreadcrumbsItem = ({
href,
separator = true,
@@ -63,6 +84,9 @@ const BreadcrumbsItem = ({
)
}
+/**
+ * @deprecated
+ */
const Separator = ({ separator = 'slash' }: { separator?: BreadcrumbsItemProps['separator'] }) => {
return (
diff --git a/packages/react/src/react/components/primitives/button.tsx b/packages/react/src/react/components/primitives/button.tsx
index 8d83521f..a5ff9aac 100644
--- a/packages/react/src/react/components/primitives/button.tsx
+++ b/packages/react/src/react/components/primitives/button.tsx
@@ -148,7 +148,7 @@ interface ButtonLinkProps
/**
* @deprecated
*/
-const AriaButtonLink = React.forwardRef(function ButtonLink(
+const ButtonLink = React.forwardRef(function ButtonLink(
{ className, variant, size, isDisabled = false, isPending = false, children, ...props },
ref
) {
@@ -184,4 +184,4 @@ const AriaButtonLink = React.forwardRef(func
)
})
-export { AriaButtonLink, Button, type ButtonLinkProps, type ButtonProps }
+export { Button, ButtonLink, type ButtonLinkProps, type ButtonProps }
diff --git a/packages/react/src/react/components/primitives/sidebar.tsx b/packages/react/src/react/components/primitives/sidebar.tsx
index a2b2713f..8073d707 100644
--- a/packages/react/src/react/components/primitives/sidebar.tsx
+++ b/packages/react/src/react/components/primitives/sidebar.tsx
@@ -34,9 +34,17 @@ import { Tooltip, TooltipContent } from './tooltip'
import { BaseIcon } from '../../components/primitives/base-icon'
import { useMediaQuery } from '../../hooks/use-media-query'
-
+/**
+ * @deprecated
+ */
const SIDEBAR_COOKIE_NAME = 'sidebar-state'
+/**
+ * @deprecated
+ */
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
+/**
+ * @deprecated
+ */
type SidebarContextProps = {
state: 'expanded' | 'collapsed'
open: boolean
@@ -47,8 +55,14 @@ type SidebarContextProps = {
toggleSidebar: () => void
}
+/**
+ * @deprecated
+ */
const SidebarContext = createContext(null)
+/**
+ * @deprecated
+ */
const useSidebar = () => {
const context = use(SidebarContext)
if (!context) {
@@ -58,6 +72,9 @@ const useSidebar = () => {
return context
}
+/**
+ * @deprecated
+ */
interface SidebarProviderProps extends React.ComponentProps<'div'> {
defaultOpen?: boolean
isOpen?: boolean
@@ -65,6 +82,9 @@ interface SidebarProviderProps extends React.ComponentProps<'div'> {
onOpenChange?: (open: boolean) => void
}
+/**
+ * @deprecated
+ */
const SidebarProvider = ({
defaultOpen = true,
isOpen: openProp,
@@ -149,6 +169,9 @@ const SidebarProvider = ({
)
}
+/**
+ * @deprecated
+ */
const gap = tv({
base: [
'w-(--sidebar-width) group-data-[sidebar-collapsible=hidden]/sidebar-container:w-0',
@@ -167,6 +190,9 @@ const gap = tv({
},
})
+/**
+ * @deprecated
+ */
const sidebar = tv({
base: [
'fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) not-has-data-sidebar-footer:pb-2 transition-[left,right,width] duration-200 ease-linear md:flex',
@@ -198,6 +224,9 @@ const sidebar = tv({
},
})
+/**
+ * @deprecated
+ */
interface SidebarProps extends React.ComponentProps<'div'> {
intent?: 'default' | 'float' | 'inset' | 'fleet'
collapsible?: 'hidden' | 'dock' | 'none'
@@ -205,6 +234,9 @@ interface SidebarProps extends React.ComponentProps<'div'> {
closeButton?: boolean
}
+/**
+ * @deprecated
+ */
const Sidebar = ({
closeButton = true,
collapsible = 'hidden',
@@ -281,6 +313,9 @@ const Sidebar = ({
)
}
+/**
+ * @deprecated
+ */
const header = tv({
base: 'mb-2 flex flex-col **:data-[slot=sidebar-label-mask]:hidden',
variants: {
@@ -291,6 +326,9 @@ const header = tv({
},
})
+/**
+ * @deprecated
+ */
const SidebarHeader = ({ className, ref, ...props }: React.ComponentProps<'div'>) => {
const { state } = use(SidebarContext)!
return (
@@ -302,7 +340,9 @@ const SidebarHeader = ({ className, ref, ...props }: React.ComponentProps<'div'>
/>
)
}
-
+/**
+ * @deprecated
+ */
const footer = tv({
base: [
'mt-auto flex flex-col p-2',
@@ -331,7 +371,9 @@ const footer = tv({
},
},
})
-
+/**
+ * @deprecated
+ */
const SidebarFooter = ({ className, ...props }: React.ComponentProps<'div'>) => {
const { state, isMobile } = useSidebar()
const collapsed = state === 'collapsed' && !isMobile
@@ -348,7 +390,9 @@ const SidebarFooter = ({ className, ...props }: React.ComponentProps<'div'>) =>
/>
)
}
-
+/**
+ * @deprecated
+ */
const SidebarContent = ({ className, ...props }: React.ComponentProps<'div'>) => {
const { state } = useSidebar()
return (
@@ -363,7 +407,9 @@ const SidebarContent = ({ className, ...props }: React.ComponentProps<'div'>) =>
/>
)
}
-
+/**
+ * @deprecated
+ */
const SidebarSectionGroup = ({ className, ...props }: React.ComponentProps<'section'>) => {
const { state, isMobile } = useSidebar()
const collapsed = state === 'collapsed' && !isMobile
@@ -380,9 +426,15 @@ const SidebarSectionGroup = ({ className, ...props }: React.ComponentProps<'sect
)
}
+/**
+ * @deprecated
+ */
interface SidebarSectionProps extends React.ComponentProps<'div'> {
label?: string
}
+/**
+ * @deprecated
+ */
const SidebarSection = ({ className, ...props }: SidebarSectionProps) => {
const { state } = useSidebar()
return (
@@ -405,6 +457,9 @@ const SidebarSection = ({ className, ...props }: SidebarSectionProps) => {
)
}
+/**
+ * @deprecated
+ */
const sidebarItemStyles = tv({
base: [
'group/sidebar-item relative col-span-full cursor-pointer overflow-hidden text-sidebar-fg/70 focus-visible:outline-hidden sm:text-sm',
@@ -440,6 +495,9 @@ const sidebarItemStyles = tv({
],
})
+/**
+ * @deprecated
+ */
interface SidebarItemProps extends Omit, 'children'> {
ghost?: boolean
isCurrent?: boolean
@@ -452,6 +510,9 @@ interface SidebarItemProps extends Omit, 'chil
badge?: string | number | undefined
}
+/**
+ * @deprecated
+ */
const SidebarItem = ({
isCurrent,
tooltip,
@@ -523,6 +584,9 @@ const SidebarItem = ({
)
}
+/**
+ * @deprecated
+ */
const sidebarLink = tv({
base: 'col-span-full items-center focus:outline-hidden',
variants: {
@@ -534,8 +598,14 @@ const sidebarLink = tv({
},
})
+/**
+ * @deprecated
+ */
interface SidebarLinkProps extends LinkProps {}
+/**
+ * @deprecated
+ */
const SidebarLink = React.forwardRef(
({ className, ...props }, ref) => {
const { state, isMobile } = useSidebar()
@@ -556,6 +626,9 @@ const SidebarLink = React.forwardRef(
}
)
+/**
+ * @deprecated
+ */
const SidebarInset = ({ className, ref, ...props }: React.ComponentProps<'main'>) => {
return (
)
}
+/**
+ * @deprecated
+ */
interface SidebarDisclosureGroupProps extends DisclosureGroupProps {}
+
+/**
+ * @deprecated
+ */
const SidebarDisclosureGroup = ({
allowsMultipleExpanded = true,
className,
@@ -587,8 +667,14 @@ const SidebarDisclosureGroup = ({
)
}
+/**
+ * @deprecated
+ */
interface SidebarDisclosureProps extends DisclosureProps {}
+/**
+ * @deprecated
+ */
const SidebarDisclosure = React.forwardRef>(
({ className, ...props }, ref) => {
const { state } = useSidebar()
@@ -606,6 +692,9 @@ const SidebarDisclosure = React.forwardRef(
({ className, onClick, ...props }, ref) => {
const { state, isMobile, toggleSidebar } = useSidebar()
@@ -670,6 +765,9 @@ const SidebarDisclosureTrigger = React.forwardRef) => {
return (
{
return (
{
)
}
+/**
+ * @deprecated
+ */
const SidebarTrigger = ({
onPress,
children,
@@ -724,6 +828,9 @@ const SidebarTrigger = ({
)
}
+/**
+ * @deprecated
+ */
const SidebarRail = ({ className, ref, ...props }: React.ComponentProps<'button'>) => {
const { toggleSidebar } = useSidebar()
@@ -748,8 +855,14 @@ const SidebarRail = ({ className, ref, ...props }: React.ComponentProps<'button'
)
}
+/**
+ * @deprecated
+ */
type SidebarLabelProps = React.ComponentProps
+/**
+ * @deprecated
+ */
const SidebarLabel = ({ className, ref, ...props }: SidebarLabelProps) => {
const { state, isMobile } = useSidebar()
const collapsed = state === 'collapsed' && !isMobile
@@ -772,6 +885,9 @@ const SidebarLabel = ({ className, ref, ...props }: SidebarLabelProps) => {
return null
}
+/**
+ * @deprecated
+ */
const nav = tv({
base: [
'isolate flex h-[3.2rem] items-center justify-between gap-x-2 px-4 text-navbar-fg sm:justify-start md:w-full',
@@ -784,10 +900,16 @@ const nav = tv({
},
})
+/**
+ * @deprecated
+ */
interface SidebarNavProps extends React.ComponentProps<'nav'> {
isSticky?: boolean
}
+/**
+ * @deprecated
+ */
const SidebarNav = ({ isSticky = false, className, ...props }: SidebarNavProps) => {
return
}
diff --git a/packages/react/src/react/components/primitives/tooltip.tsx b/packages/react/src/react/components/primitives/tooltip.tsx
index 3723a35c..84e3f188 100644
--- a/packages/react/src/react/components/primitives/tooltip.tsx
+++ b/packages/react/src/react/components/primitives/tooltip.tsx
@@ -12,6 +12,9 @@ import {
import type { VariantProps } from 'tailwind-variants'
import { tv } from 'tailwind-variants'
+/**
+ * @deprecated
+ */
const tooltipStyles = tv({
base: [
'group rounded-lg p-6 text-base will-change-transform dark:shadow-none [&_strong]:font-medium',
@@ -40,9 +43,19 @@ const tooltipStyles = tv({
},
})
+/**
+ * @deprecated
+ */
type TooltipProps = React.ComponentProps
+
+/**
+ * @deprecated
+ */
const Tooltip = (props: TooltipProps) =>
+/**
+ * @deprecated
+ */
interface TooltipContentProps
extends Omit,
VariantProps {
@@ -50,6 +63,9 @@ interface TooltipContentProps
children: React.ReactNode
}
+/**
+ * @deprecated
+ */
const TooltipContent = ({
offset = 10,
showArrow = true,
@@ -86,6 +102,9 @@ const TooltipContent = ({
)
}
+/**
+ * @deprecated
+ */
const TooltipTrigger: typeof Button = Button
export type { TooltipContentProps, TooltipProps }
diff --git a/packages/react/v2/components/primitives/breadcrumb.tsx b/packages/react/v2/components/primitives/breadcrumb.tsx
new file mode 100644
index 00000000..aaf4f066
--- /dev/null
+++ b/packages/react/v2/components/primitives/breadcrumb.tsx
@@ -0,0 +1,103 @@
+import * as React from 'react'
+
+import { DotsThreeIcon } from '@phosphor-icons/react'
+import { Slot } from '@radix-ui/react-slot'
+
+import { cn } from '../../../src/react/utils/cn'
+
+function Breadcrumb({ ...props }: React.ComponentProps<'nav'>) {
+ return
+}
+
+function BreadcrumbList({ className, ...props }: React.ComponentProps<'ol'>) {
+ return (
+
+ )
+}
+
+function BreadcrumbItem({ className, ...props }: React.ComponentProps<'li'>) {
+ return (
+
+ )
+}
+
+function BreadcrumbLink({
+ asChild,
+ className,
+ ...props
+}: React.ComponentProps<'a'> & {
+ asChild?: boolean
+}) {
+ const Comp = asChild ? Slot : 'a'
+
+ return (
+
+ )
+}
+
+function BreadcrumbPage({ className, ...props }: React.ComponentProps<'span'>) {
+ return (
+
+ )
+}
+
+function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<'li'>) {
+ return (
+ svg]:size-7', className)}
+ {...props}
+ >
+ {children ?? '/'}
+
+ )
+}
+
+function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<'span'>) {
+ return (
+
+
+ More
+
+ )
+}
+
+export {
+ Breadcrumb,
+ BreadcrumbEllipsis,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbList,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+}
diff --git a/packages/react/v2/components/primitives/button.tsx b/packages/react/v2/components/primitives/button.tsx
index 1cc94075..e3a34ae7 100644
--- a/packages/react/v2/components/primitives/button.tsx
+++ b/packages/react/v2/components/primitives/button.tsx
@@ -11,7 +11,7 @@ import { cn } from '../../../src/react/utils/cn'
const buttonVariants = cva(
[
- "inline-flex items-center justify-center gap-4 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-8 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring ring-offset-1 focus-visible:ring-ring/50 focus-visible:ring-[2px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
+ "inline-flex items-center justify-center gap-4 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-8 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring ring-offset-1 focus-visible:ring-ring focus-visible:ring-[2px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
'disabled:opacity-80 cursor-pointer',
],
{
@@ -30,7 +30,7 @@ const buttonVariants = cva(
ghost:
' bg-surface-button-ghost hover:bg-surface-button-ghost-hover active:bg-surface-button-ghost text-text-secondary hover:text-accent-foreground dark:hover:bg-accent/50',
destructive:
- 'bg-destructive text-white hover:bg-destructive/90 active:bg-destructive focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
+ 'bg-destructive text-white hover:bg-destructive/90 active:bg-destructive focus-visible:ring-destructive dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
},
size: {
default: 'h-18 px-8 py-4 has-[>svg]:px-6',
diff --git a/packages/react/v2/components/primitives/collapsible.tsx b/packages/react/v2/components/primitives/collapsible.tsx
new file mode 100644
index 00000000..847d9737
--- /dev/null
+++ b/packages/react/v2/components/primitives/collapsible.tsx
@@ -0,0 +1,21 @@
+'use client'
+
+import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'
+
+function Collapsible({ ...props }: React.ComponentProps) {
+ return
+}
+
+function CollapsibleTrigger({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function CollapsibleContent({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+export { Collapsible, CollapsibleContent, CollapsibleTrigger }
diff --git a/packages/react/v2/components/primitives/dropdown-menu.tsx b/packages/react/v2/components/primitives/dropdown-menu.tsx
new file mode 100644
index 00000000..8567a59e
--- /dev/null
+++ b/packages/react/v2/components/primitives/dropdown-menu.tsx
@@ -0,0 +1,229 @@
+'use client'
+
+import * as React from 'react'
+
+import { CaretRightIcon, CheckCircleIcon, CheckIcon } from '@phosphor-icons/react'
+import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
+
+import { cn } from '../../../src/react/utils/cn'
+
+function DropdownMenu({ ...props }: React.ComponentProps) {
+ return
+}
+
+function DropdownMenuPortal({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function DropdownMenuTrigger({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function DropdownMenuContent({
+ className,
+ sideOffset = 4,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+function DropdownMenuGroup({ ...props }: React.ComponentProps) {
+ return
+}
+
+function DropdownMenuItem({
+ className,
+ inset,
+ variant = 'default',
+ ...props
+}: React.ComponentProps & {
+ inset?: boolean
+ variant?: 'default' | 'destructive'
+}) {
+ return (
+
+ )
+}
+
+function DropdownMenuCheckboxItem({
+ className,
+ children,
+ checked,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ )
+}
+
+function DropdownMenuRadioGroup({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function DropdownMenuRadioItem({
+ className,
+ children,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ )
+}
+
+function DropdownMenuLabel({
+ className,
+ inset,
+ ...props
+}: React.ComponentProps & {
+ inset?: boolean
+}) {
+ return (
+
+ )
+}
+
+function DropdownMenuSeparator({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {
+ return (
+
+ )
+}
+
+function DropdownMenuSub({ ...props }: React.ComponentProps) {
+ return
+}
+
+function DropdownMenuSubTrigger({
+ className,
+ inset,
+ children,
+ ...props
+}: React.ComponentProps & {
+ inset?: boolean
+}) {
+ return (
+
+ {children}
+
+
+ )
+}
+
+function DropdownMenuSubContent({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+export {
+ DropdownMenu,
+ DropdownMenuCheckboxItem,
+ DropdownMenuContent,
+ DropdownMenuGroup,
+ DropdownMenuItem,
+ DropdownMenuLabel,
+ DropdownMenuPortal,
+ DropdownMenuRadioGroup,
+ DropdownMenuRadioItem,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuTrigger,
+}
diff --git a/packages/react/v2/components/primitives/index.ts b/packages/react/v2/components/primitives/index.ts
index b6443f69..cccacad5 100644
--- a/packages/react/v2/components/primitives/index.ts
+++ b/packages/react/v2/components/primitives/index.ts
@@ -1,8 +1,11 @@
+export * from './breadcrumb'
export * from './button'
export * from './button-group'
+export * from './collapsible'
export * from './combobox'
export * from './command'
export * from './dialog'
+export * from './dropdown-menu'
export * from './input'
export * from './input-group'
export * from './label'
@@ -10,3 +13,6 @@ export * from './link'
export * from './popover'
export * from './separator'
export * from './sheet'
+export * from './sidebar'
+export * from './skeleton'
+export * from './tooltip'
diff --git a/packages/react/v2/components/primitives/sidebar.tsx b/packages/react/v2/components/primitives/sidebar.tsx
new file mode 100644
index 00000000..385f7a40
--- /dev/null
+++ b/packages/react/v2/components/primitives/sidebar.tsx
@@ -0,0 +1,689 @@
+'use client'
+
+import * as React from 'react'
+
+import { SidebarIcon } from '@phosphor-icons/react'
+import { Slot } from '@radix-ui/react-slot'
+import { useControllableState } from '@radix-ui/react-use-controllable-state'
+import { cva, type VariantProps } from 'class-variance-authority'
+
+import { Button } from './button'
+import { Input } from './input'
+import { Separator } from './separator'
+import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from './sheet'
+import { Skeleton } from './skeleton'
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './tooltip'
+
+import { useMediaQuery } from '../../../src/react/hooks/use-media-query'
+import { cn } from '../../../src/react/utils/cn'
+
+const SIDEBAR_COOKIE_NAME = 'sidebar-state'
+const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
+const SIDEBAR_WIDTH = '17rem'
+const SIDEBAR_WIDTH_MOBILE = '18rem'
+const SIDEBAR_WIDTH_ICON = '3.75rem'
+const SIDEBAR_KEYBOARD_SHORTCUT = 'b'
+
+type SidebarContextProps = {
+ state: 'expanded' | 'collapsed'
+ open: boolean
+ setOpen: (open: boolean) => void
+ openMobile: boolean
+ setOpenMobile: (open: boolean) => void
+ isMobile: boolean
+ toggleSidebar: () => void
+}
+
+const SidebarContext = React.createContext(null)
+
+function useSidebar() {
+ const context = React.useContext(SidebarContext)
+ if (!context) {
+ throw new Error('useSidebar must be used within a SidebarProvider.')
+ }
+
+ return context
+}
+
+function SidebarProvider({
+ defaultOpen = true,
+ open: openProp,
+ onOpenChange: setOpenProp,
+ className,
+ style,
+ children,
+ ...props
+}: React.ComponentProps<'div'> & {
+ defaultOpen?: boolean
+ open?: boolean
+ onOpenChange?: (open: boolean) => void
+}) {
+ const initialRenderRef = React.useRef(true)
+ const isMobile = useMediaQuery('(max-width: 600px)')
+ const [openMobile, setOpenMobile] = React.useState(false)
+
+ // This is the internal state of the sidebar.
+ // We use openProp and setOpenProp for control from outside the component.
+ const [open, setOpen] = useControllableState({
+ defaultProp: defaultOpen,
+ prop: openProp,
+ onChange: setOpenProp,
+ })
+
+ React.useEffect(() => {
+ if (initialRenderRef.current) {
+ initialRenderRef.current = false
+ return
+ }
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
+ }, [open])
+
+ // Helper to toggle the sidebar.
+ const toggleSidebar = React.useCallback(() => {
+ return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)
+ }, [isMobile, setOpen, setOpenMobile])
+
+ // Adds a keyboard shortcut to toggle the sidebar.
+ React.useEffect(() => {
+ const handleKeyDown = (event: KeyboardEvent) => {
+ if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
+ event.preventDefault()
+ toggleSidebar()
+ }
+ }
+
+ window.addEventListener('keydown', handleKeyDown)
+ return () => window.removeEventListener('keydown', handleKeyDown)
+ }, [toggleSidebar])
+
+ // We add a state so that we can do data-state="expanded" or "collapsed".
+ // This makes it easier to style the sidebar with Tailwind classes.
+ const state = open ? 'expanded' : 'collapsed'
+
+ const contextValue = React.useMemo(
+ () => ({
+ state,
+ open,
+ setOpen,
+ isMobile,
+ openMobile,
+ setOpenMobile,
+ toggleSidebar,
+ }),
+ [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
+ )
+
+ return (
+
+
+
+ {children}
+
+
+
+ )
+}
+
+function Sidebar({
+ side = 'left',
+ variant = 'sidebar',
+ collapsible = 'offcanvas',
+ className,
+ children,
+ ...props
+}: React.ComponentProps<'div'> & {
+ side?: 'left' | 'right'
+ variant?: 'sidebar' | 'floating' | 'inset'
+ collapsible?: 'offcanvas' | 'icon' | 'none'
+}) {
+ const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
+
+ if (collapsible === 'none') {
+ return (
+
+ {children}
+
+ )
+ }
+
+ if (isMobile) {
+ return (
+
+
+
+ Sidebar
+ Displays the mobile sidebar.
+
+ {children}
+
+
+ )
+ }
+
+ return (
+
+ {/* This is what handles the sidebar gap on desktop */}
+
+
+
+ )
+}
+
+function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps) {
+ const { toggleSidebar } = useSidebar()
+
+ return (
+
+ )
+}
+
+function SidebarRail({ className, ...props }: React.ComponentProps<'button'>) {
+ const { toggleSidebar } = useSidebar()
+
+ return (
+
+ )
+}
+
+function SidebarInset({ className, ...props }: React.ComponentProps<'main'>) {
+ return (
+
+ )
+}
+
+function SidebarInput({ className, ...props }: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SidebarHeader({ className, ...props }: React.ComponentProps<'div'>) {
+ return (
+
+ )
+}
+
+function SidebarFooter({ className, ...props }: React.ComponentProps<'div'>) {
+ return (
+
+ )
+}
+
+function SidebarSeparator({ className, ...props }: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SidebarContent({ className, ...props }: React.ComponentProps<'div'>) {
+ return (
+
+ )
+}
+
+function SidebarGroup({ className, ...props }: React.ComponentProps<'div'>) {
+ return (
+
+ )
+}
+
+function SidebarGroupLabel({
+ className,
+ asChild = false,
+ ...props
+}: React.ComponentProps<'div'> & { asChild?: boolean }) {
+ const Comp = asChild ? Slot : 'div'
+
+ return (
+ svg]:size-8 [&>svg]:shrink-0',
+ 'group-data-[collapsible=icon]:-mt-16 group-data-[collapsible=icon]:opacity-0',
+ className
+ )}
+ {...props}
+ />
+ )
+}
+
+function SidebarGroupAction({
+ className,
+ asChild = false,
+ ...props
+}: React.ComponentProps<'button'> & { asChild?: boolean }) {
+ const Comp = asChild ? Slot : 'button'
+
+ return (
+ svg]:size-8 [&>svg]:shrink-0',
+ // Increases the hit area of the button on mobile.
+ 'after:absolute after:-inset-4 md:after:hidden',
+ 'group-data-[collapsible=icon]:hidden',
+ className
+ )}
+ {...props}
+ />
+ )
+}
+
+function SidebarGroupContent({ className, ...props }: React.ComponentProps<'div'>) {
+ return (
+
+ )
+}
+
+function SidebarMenu({ className, ...props }: React.ComponentProps<'ul'>) {
+ return (
+
+ )
+}
+
+function SidebarMenuItem({ className, ...props }: React.ComponentProps<'li'>) {
+ return (
+
+ )
+}
+
+const sidebarMenuButtonVariants = cva(
+ 'peer/menu-button flex w-full items-center gap-4 overflow-hidden rounded-md p-4 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-16 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-16! group-data-[collapsible=icon]:p-4! [&>span:last-child]:truncate [&>svg]:size-8 [&>svg]:shrink-0',
+ {
+ variants: {
+ variant: {
+ default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
+ outline:
+ 'bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',
+ },
+ size: {
+ default: 'h-16 text-sm',
+ sm: 'h-14 text-xs',
+ lg: 'h-24 text-sm group-data-[collapsible=icon]:p-0!',
+ },
+ },
+ defaultVariants: {
+ variant: 'default',
+ size: 'default',
+ },
+ }
+)
+
+function SidebarMenuButton({
+ asChild = false,
+ isActive = false,
+ variant = 'default',
+ size = 'default',
+ tooltip,
+ className,
+ ...props
+}: React.ComponentProps<'button'> & {
+ asChild?: boolean
+ isActive?: boolean
+ tooltip?: string | React.ComponentProps
+} & VariantProps) {
+ const Comp = asChild ? Slot : 'button'
+ const { isMobile, state } = useSidebar()
+
+ const button = (
+
+ )
+
+ if (!tooltip) {
+ return button
+ }
+
+ if (typeof tooltip === 'string') {
+ tooltip = {
+ children: tooltip,
+ }
+ }
+
+ return (
+
+ {button}
+
+
+ )
+}
+
+function SidebarMenuAction({
+ className,
+ asChild = false,
+ showOnHover = false,
+ ...props
+}: React.ComponentProps<'button'> & {
+ asChild?: boolean
+ showOnHover?: boolean
+}) {
+ const Comp = asChild ? Slot : 'button'
+
+ return (
+ svg]:size-8 [&>svg]:shrink-0',
+ // Increases the hit area of the button on mobile.
+ 'after:absolute after:-inset-4 md:after:hidden',
+ 'peer-data-[size=sm]/menu-button:top-2',
+ 'peer-data-[size=default]/menu-button:top-3',
+ 'peer-data-[size=lg]/menu-button:top-5',
+ 'group-data-[collapsible=icon]:hidden',
+ showOnHover &&
+ 'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0',
+ className
+ )}
+ {...props}
+ />
+ )
+}
+
+function SidebarMenuBadge({ className, ...props }: React.ComponentProps<'div'>) {
+ return (
+
+ )
+}
+
+function SidebarMenuSkeleton({
+ className,
+ showIcon = false,
+ ...props
+}: React.ComponentProps<'div'> & {
+ showIcon?: boolean
+}) {
+ // Random width between 50 to 90%.
+ const width = React.useMemo(() => {
+ return `${Math.floor(Math.random() * 40) + 50}%`
+ }, [])
+
+ return (
+
+ {showIcon && }
+
+
+ )
+}
+
+function SidebarMenuSub({ className, ...props }: React.ComponentProps<'ul'>) {
+ return (
+
+ )
+}
+
+function SidebarMenuSubItem({ className, ...props }: React.ComponentProps<'li'>) {
+ return (
+
+ )
+}
+
+function SidebarMenuSubButton({
+ asChild = false,
+ size = 'md',
+ isActive = false,
+ className,
+ ...props
+}: React.ComponentProps<'a'> & {
+ asChild?: boolean
+ size?: 'sm' | 'md'
+ isActive?: boolean
+}) {
+ const Comp = asChild ? Slot : 'a'
+
+ return (
+ svg]:text-sidebar-accent-foreground flex h-14 min-w-0 -translate-x-px items-center gap-4 overflow-hidden rounded-md px-4 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-8 [&>svg]:shrink-0',
+ 'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',
+ size === 'sm' && 'text-xs',
+ size === 'md' && 'text-sm',
+ 'group-data-[collapsible=icon]:hidden',
+ className
+ )}
+ {...props}
+ />
+ )
+}
+
+export {
+ Sidebar,
+ SidebarContent,
+ SidebarFooter,
+ SidebarGroup,
+ SidebarGroupAction,
+ SidebarGroupContent,
+ SidebarGroupLabel,
+ SidebarHeader,
+ SidebarInput,
+ SidebarInset,
+ SidebarMenu,
+ SidebarMenuAction,
+ SidebarMenuBadge,
+ SidebarMenuButton,
+ SidebarMenuItem,
+ SidebarMenuSkeleton,
+ SidebarMenuSub,
+ SidebarMenuSubButton,
+ SidebarMenuSubItem,
+ SidebarProvider,
+ SidebarRail,
+ SidebarSeparator,
+ SidebarTrigger,
+ useSidebar,
+}
diff --git a/packages/react/v2/components/primitives/skeleton.tsx b/packages/react/v2/components/primitives/skeleton.tsx
new file mode 100644
index 00000000..a4f2ad1a
--- /dev/null
+++ b/packages/react/v2/components/primitives/skeleton.tsx
@@ -0,0 +1,13 @@
+import { cn } from '../../../src/react/utils/cn'
+
+function Skeleton({ className, ...props }: React.ComponentProps<'div'>) {
+ return (
+
+ )
+}
+
+export { Skeleton }
diff --git a/packages/react/v2/components/primitives/tooltip.tsx b/packages/react/v2/components/primitives/tooltip.tsx
new file mode 100644
index 00000000..98b556b9
--- /dev/null
+++ b/packages/react/v2/components/primitives/tooltip.tsx
@@ -0,0 +1,58 @@
+'use client'
+
+import * as React from 'react'
+
+import * as TooltipPrimitive from '@radix-ui/react-tooltip'
+
+import { cn } from '../../../src/react/utils/cn'
+
+function TooltipProvider({
+ delayDuration = 0,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function Tooltip({ ...props }: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+function TooltipTrigger({ ...props }: React.ComponentProps) {
+ return
+}
+
+function TooltipContent({
+ className,
+ sideOffset = 0,
+ children,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+ {children}
+
+
+
+ )
+}
+
+export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 61769819..f83376ce 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -424,9 +424,15 @@ importers:
'@phosphor-icons/react':
specifier: ^2.1.8
version: 2.1.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-collapsible':
+ specifier: ^1.1.12
+ version: 1.1.12(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-dialog':
specifier: ^1.1.15
version: 1.1.15(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-dropdown-menu':
+ specifier: ^2.1.16
+ version: 2.1.16(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-label':
specifier: ^2.1.7
version: 2.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -439,6 +445,9 @@ importers:
'@radix-ui/react-slot':
specifier: ^1.2.0
version: 1.2.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-tooltip':
+ specifier: ^1.2.8
+ version: 1.2.8(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-controllable-state':
specifier: ^1.2.2
version: 1.2.2(@types/react@19.1.6)(react@19.1.0)
@@ -1524,6 +1533,32 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-collapsible@1.1.12':
+ resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==}
+ 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.7':
+ resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==}
+ 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.2':
resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==}
peerDependencies:
@@ -1555,6 +1590,15 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-direction@1.1.1':
+ resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==}
+ 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.11':
resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==}
peerDependencies:
@@ -1568,6 +1612,19 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-dropdown-menu@2.1.16':
+ resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==}
+ 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.3':
resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==}
peerDependencies:
@@ -1612,6 +1669,19 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-menu@2.1.16':
+ resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==}
+ 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-popover@1.1.15':
resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==}
peerDependencies:
@@ -1677,6 +1747,19 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-roving-focus@1.1.11':
+ resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==}
+ 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-separator@1.1.7':
resolution: {integrity: sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==}
peerDependencies:
@@ -1708,6 +1791,19 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-tooltip@1.2.8':
+ resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==}
+ 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-use-callback-ref@1.1.1':
resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==}
peerDependencies:
@@ -1771,6 +1867,19 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-visually-hidden@1.2.3':
+ resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==}
+ 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/rect@1.1.1':
resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==}
@@ -6782,6 +6891,34 @@ snapshots:
'@types/react': 19.1.6
'@types/react-dom': 19.1.6(@types/react@19.1.6)
+ '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ optionalDependencies:
+ '@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
+
+ '@radix-ui/react-collection@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ optionalDependencies:
+ '@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
+
'@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.6)(react@19.1.0)':
dependencies:
react: 19.1.0
@@ -6816,6 +6953,12 @@ snapshots:
'@types/react': 19.1.6
'@types/react-dom': 19.1.6(@types/react@19.1.6)
+ '@radix-ui/react-direction@1.1.1(@types/react@19.1.6)(react@19.1.0)':
+ dependencies:
+ react: 19.1.0
+ optionalDependencies:
+ '@types/react': 19.1.6
+
'@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.3
@@ -6829,6 +6972,21 @@ snapshots:
'@types/react': 19.1.6
'@types/react-dom': 19.1.6(@types/react@19.1.6)
+ '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ optionalDependencies:
+ '@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
+
'@radix-ui/react-focus-guards@1.1.3(@types/react@19.1.6)(react@19.1.0)':
dependencies:
react: 19.1.0
@@ -6862,6 +7020,32 @@ snapshots:
'@types/react': 19.1.6
'@types/react-dom': 19.1.6(@types/react@19.1.6)
+ '@radix-ui/react-menu@2.1.16(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
+ aria-hidden: 1.2.6
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ react-remove-scroll: 2.7.1(@types/react@19.1.6)(react@19.1.0)
+ optionalDependencies:
+ '@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
+
'@radix-ui/react-popover@1.1.15(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.3
@@ -6932,6 +7116,23 @@ snapshots:
'@types/react': 19.1.6
'@types/react-dom': 19.1.6(@types/react@19.1.6)
+ '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ optionalDependencies:
+ '@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
+
'@radix-ui/react-separator@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -6955,6 +7156,26 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.6
+ '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ optionalDependencies:
+ '@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
+
'@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.1.6)(react@19.1.0)':
dependencies:
react: 19.1.0
@@ -7003,6 +7224,15 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.6
+ '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ optionalDependencies:
+ '@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
+
'@radix-ui/rect@1.1.1': {}
'@react-aria/autocomplete@3.0.0-beta.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':