diff --git a/apps/website/app/(extract)/extract-nodes/components/MainContent.tsx b/apps/website/app/(extract)/extract-nodes/components/MainContent.tsx new file mode 100644 index 000000000..09b13c6e8 --- /dev/null +++ b/apps/website/app/(extract)/extract-nodes/components/MainContent.tsx @@ -0,0 +1,230 @@ +import { Badge } from "@repo/ui/components/ui/badge"; +import { Button } from "@repo/ui/components/ui/button"; +import { Card, CardContent } from "@repo/ui/components/ui/card"; +import { Checkbox } from "@repo/ui/components/ui/checkbox"; +import { Copy } from "lucide-react"; + +const NODE_TYPE_COLORS: Record = { + claim: "#7DA13E", + question: "#99890E", + hypothesis: "#7C4DFF", + evidence: "#dc0c4a", + result: "#E6A23C", + source: "#9E9E9E", + theory: "#8B5CF6", +}; + +const SAMPLE_NODES = [ + { + nodeType: "claim", + content: + "Basolateral secretion of Wnt5a is essential for establishing apical-basal polarity in epithelial cells.", + supportSnippet: + '"Wnt5a secreted from the basolateral surface was both necessary and sufficient for the establishment of apical-basal polarity" (p.9)', + sourceSection: "Discussion", + }, + { + nodeType: "evidence", + content: + "Wnt5a was detected exclusively in the basolateral medium of polarized MDCK cells grown on Transwell filters, with no detectable signal in the apical fraction.", + supportSnippet: + '"Western blot analysis of conditioned media showed Wnt5a protein exclusively in the basolateral fraction (Fig. 2A, lanes 3-4)"', + sourceSection: "Results", + }, + { + nodeType: "question", + content: + "What is the mechanism by which Wnt5a polarized secretion is directed to the basolateral membrane?", + supportSnippet: + '"The mechanism that directs Wnt5a specifically to the basolateral surface remains an open question" (p.11)', + sourceSection: "Discussion", + }, + { + nodeType: "hypothesis", + content: + "Ror2 receptor activation at the basolateral surface mediates Wnt5a-dependent lumen positioning.", + supportSnippet: + '"We hypothesize that Ror2, as the primary receptor for Wnt5a at the basolateral membrane, transduces the polarity signal required for single-lumen formation"', + sourceSection: "Discussion", + }, + { + nodeType: "result", + content: + "shRNA-mediated knockdown of Wnt5a resulted in multi-lumen cysts in 68% of colonies compared to 12% in control conditions.", + supportSnippet: + '"Quantification of cyst morphology revealed 68 ± 4% multi-lumen cysts in Wnt5a-KD versus 12 ± 3% in controls (Fig. 4B, p < 0.001)"', + sourceSection: "Results", + }, + { + nodeType: "source", + content: "Yamamoto et al. (2015) Nature Cell Biology 17(8):1024-1035", + supportSnippet: + "Primary research article on Wnt5a basolateral secretion and lumen formation in polarized epithelia.", + sourceSection: "References", + }, + { + nodeType: "theory", + content: + "Non-canonical Wnt signaling through the planar cell polarity pathway is a conserved mechanism for epithelial lumen morphogenesis.", + supportSnippet: + '"Our findings place Wnt5a upstream of the PCP pathway in the regulation of epithelial lumen morphogenesis, consistent with the broader role of non-canonical Wnt signaling in tissue polarity"', + sourceSection: "Discussion", + }, + { + nodeType: "evidence", + content: + "Co-immunoprecipitation showed that Wnt5a preferentially binds Ror2 receptor at the basolateral surface.", + supportSnippet: + '"IP-Western analysis demonstrated direct Wnt5a-Ror2 interaction in basolateral but not apical membrane fractions (Fig. 5C)"', + sourceSection: "Results", + }, + { + nodeType: "claim", + content: + "Loss of Wnt5a function disrupts lumen formation in 3D cyst cultures derived from epithelial cells.", + supportSnippet: + '"These data demonstrate that Wnt5a is required for proper lumen formation in three-dimensional culture systems"', + sourceSection: "Discussion", + }, +]; + +const EXPANDED_INDICES = new Set([0, 1]); + +const typeCounts = SAMPLE_NODES.reduce>((acc, node) => { + acc[node.nodeType] = (acc[node.nodeType] ?? 0) + 1; + return acc; +}, {}); + +const TABS = [ + { id: "all", label: "All", count: SAMPLE_NODES.length, color: undefined }, + ...Object.entries(typeCounts).map(([nodeType, count]) => ({ + id: nodeType, + label: nodeType.charAt(0).toUpperCase() + nodeType.slice(1), + count, + color: NODE_TYPE_COLORS[nodeType], + })), +]; + +// eslint-disable-next-line @typescript-eslint/naming-convention +export const MainContent = () => { + return ( +
+
+
+
+

+ Basolateral secretion of Wnt5a in polarized epithelial cells is + required for apical lumen formation +

+

+ Yamamoto H, Komekado H, Kikuchi A +

+
+ +
+
+ {TABS.map((tab) => ( + + {tab.color && ( + + )} + {tab.label} {tab.count} + + ))} +
+
+ +
+
+ {SAMPLE_NODES.map((node, index) => { + const color = NODE_TYPE_COLORS[node.nodeType] ?? "#64748b"; + const isExpanded = EXPANDED_INDICES.has(index); + return ( + + +
+ +
+
+ + {node.nodeType} + + {node.sourceSection && ( + + {node.sourceSection} + + )} +
+

+ {node.content} +

+ {isExpanded ? ( + <> +
+

+ {node.supportSnippet} +

+
+ + + ) : ( + + )} +
+
+
+
+ ); + })} +
+
+ +
+
+ + + {SAMPLE_NODES.length} of {SAMPLE_NODES.length} selected + +
+ + +
+
+
+ ); +}; diff --git a/apps/website/app/(extract)/extract-nodes/components/Sidebar.tsx b/apps/website/app/(extract)/extract-nodes/components/Sidebar.tsx new file mode 100644 index 000000000..f915efd17 --- /dev/null +++ b/apps/website/app/(extract)/extract-nodes/components/Sidebar.tsx @@ -0,0 +1,145 @@ +import { Button } from "@repo/ui/components/ui/button"; +import { Checkbox } from "@repo/ui/components/ui/checkbox"; +import { ChevronDown } from "lucide-react"; + +const NODE_TYPES = [ + { + label: "Claim", + description: + "An assertion about how something works or should work. Usually a single declarative sentence.", + candidateTag: "#clm-candidate", + color: "#7DA13E", + }, + { + label: "Question", + description: + "An unknown being explored through research. Framed as a question that can be investigated.", + candidateTag: "#que-candidate", + color: "#99890E", + }, + { + label: "Hypothesis", + description: + "A proposed answer to a question. Collects evidence for or against.", + candidateTag: "#hyp-candidate", + color: "#7C4DFF", + }, + { + label: "Evidence", + description: + "A discrete observation from a published dataset or experiment. Usually in past tense with observable, model system, and method.", + candidateTag: "#evd-candidate", + color: "#dc0c4a", + }, + { + label: "Result", + description: + "A discrete observation from ongoing research, in past tense. Includes source context.", + candidateTag: "#res-candidate", + color: "#E6A23C", + }, + { + label: "Source", + description: "A referenced publication or external resource.", + candidateTag: "#src-candidate", + color: "#9E9E9E", + }, + { + label: "Theory", + description: "A theoretical framework or model that explains phenomena.", + candidateTag: "#the-candidate", + color: "#8B5CF6", + }, +]; + +const SECTION_LABEL_CLASS = + "mb-3 block px-1 text-[18px] font-semibold tracking-[-0.016em] text-slate-800"; + +// eslint-disable-next-line @typescript-eslint/naming-convention +export const Sidebar = () => { + return ( + + ); +}; diff --git a/apps/website/app/(extract)/extract-nodes/page.tsx b/apps/website/app/(extract)/extract-nodes/page.tsx new file mode 100644 index 000000000..afd043d31 --- /dev/null +++ b/apps/website/app/(extract)/extract-nodes/page.tsx @@ -0,0 +1,13 @@ +import { MainContent } from "./components/MainContent"; +import { Sidebar } from "./components/Sidebar"; + +const ExtractNodesPage = () => { + return ( +
+ + +
+ ); +}; + +export default ExtractNodesPage; diff --git a/apps/website/app/(extract)/layout.tsx b/apps/website/app/(extract)/layout.tsx new file mode 100644 index 000000000..2a837484c --- /dev/null +++ b/apps/website/app/(extract)/layout.tsx @@ -0,0 +1,58 @@ +import type { Metadata } from "next"; +import "~/globals.css"; +import Image from "next/image"; +import Link from "next/link"; +import { Inter } from "next/font/google"; + +export const metadata: Metadata = { + title: "Extract Nodes | Discourse Graphs", + description: + "Extract structured discourse graph nodes from academic papers using AI.", +}; + +const inter = Inter({ + subsets: ["latin"], + display: "swap", +}); + +type ExtractLayoutProps = { + children: React.ReactNode; +}; + +const ExtractLayout = ({ children }: ExtractLayoutProps) => { + return ( +
+
+
+ + Discourse Graphs Logo + + Discourse Graphs + + + Extract + + + + + Back to site + +
+
+ +
{children}
+
+ ); +}; + +export default ExtractLayout; diff --git a/packages/ui/package.json b/packages/ui/package.json index b37816389..c6c0816c4 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -32,14 +32,16 @@ "typescript": "5.5.4" }, "dependencies": { + "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-slot": "^1.2.4", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.468.0", "react": "^19", "react-dom": "^19", "shadcn": "2.10.0", - "tailwindcss": "^3.1.0", "tailwind-merge": "^3.3.1", + "tailwindcss": "^3.1.0", "tailwindcss-animate": "^1.0.7", "tw-animate-css": "^1.3.4" } diff --git a/packages/ui/src/components/ui/badge.tsx b/packages/ui/src/components/ui/badge.tsx new file mode 100644 index 000000000..eb6f1e057 --- /dev/null +++ b/packages/ui/src/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@repo/ui/lib/utils"; + +const badgeVariants = cva( + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +type BadgeProps = React.HTMLAttributes & + VariantProps; + +// eslint-disable-next-line @typescript-eslint/naming-convention +const Badge = ({ className, variant, ...props }: BadgeProps) => { + return ( +
+ ); +}; + +export { Badge, badgeVariants }; diff --git a/packages/ui/src/components/ui/button.tsx b/packages/ui/src/components/ui/button.tsx new file mode 100644 index 000000000..1b624b5a1 --- /dev/null +++ b/packages/ui/src/components/ui/button.tsx @@ -0,0 +1,57 @@ +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@repo/ui/lib/utils"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +type ButtonProps = React.ButtonHTMLAttributes & + VariantProps & { + asChild?: boolean; + }; + +// eslint-disable-next-line @typescript-eslint/naming-convention +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + // eslint-disable-next-line @typescript-eslint/naming-convention + const Comp = asChild ? Slot : "button"; + return ( + + ); + }, +); +Button.displayName = "Button"; + +export { Button, buttonVariants }; diff --git a/packages/ui/src/components/ui/checkbox.tsx b/packages/ui/src/components/ui/checkbox.tsx new file mode 100644 index 000000000..5111f1092 --- /dev/null +++ b/packages/ui/src/components/ui/checkbox.tsx @@ -0,0 +1,30 @@ +"use client"; + +import * as React from "react"; +import * as CheckboxPrimitive from "@radix-ui/react-checkbox"; +import { Check } from "lucide-react"; + +import { cn } from "@repo/ui/lib/utils"; + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)); +Checkbox.displayName = CheckboxPrimitive.Root.displayName; + +export { Checkbox }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4afa7c66f..f4aba20dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -673,6 +673,12 @@ importers: packages/ui: dependencies: + '@radix-ui/react-checkbox': + specifier: ^1.3.3 + version: 1.3.3(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-slot': + specifier: ^1.2.4 + version: 1.2.4(@types/react@19.1.12)(react@19.1.1) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -3605,6 +3611,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-slot@1.2.4': + resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-switch@1.2.6': resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==} peerDependencies: @@ -5255,6 +5270,7 @@ packages: '@xmldom/xmldom@0.9.8': resolution: {integrity: sha512-p96FSY54r+WJ50FIOsCOjyj/wavs8921hG5+kVMmZgKcvIKxMXHTrjNJvRgWa/zuX3B6t2lijLNFaOyuxUH+2A==} engines: {node: '>=14.6'} + deprecated: this version has critical issues, please update to the latest version '@yarnpkg/lockfile@1.1.0': resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} @@ -13699,6 +13715,22 @@ snapshots: '@types/react': 19.1.12 '@types/react-dom': 19.1.9(@types/react@19.1.12) + '@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.12)(react@19.1.1) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.12)(react@19.1.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.12)(react@19.1.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.12)(react@19.1.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.12)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + optionalDependencies: + '@types/react': 19.1.12 + '@types/react-dom': 19.1.9(@types/react@19.1.12) + '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.3 @@ -13771,6 +13803,12 @@ snapshots: optionalDependencies: '@types/react': 19.1.12 + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.12)(react@19.1.1)': + dependencies: + react: 19.1.1 + optionalDependencies: + '@types/react': 19.1.12 + '@radix-ui/react-context-menu@2.2.16(@types/react-dom@18.2.17)(@types/react@18.2.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@radix-ui/primitive': 1.1.3 @@ -13818,6 +13856,12 @@ snapshots: optionalDependencies: '@types/react': 19.1.12 + '@radix-ui/react-context@1.1.2(@types/react@19.1.12)(react@19.1.1)': + dependencies: + react: 19.1.1 + optionalDependencies: + '@types/react': 19.1.12 + '@radix-ui/react-dialog@1.1.15(@types/react-dom@18.2.17)(@types/react@18.2.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@radix-ui/primitive': 1.1.3 @@ -14345,6 +14389,16 @@ snapshots: '@types/react': 19.1.12 '@types/react-dom': 19.1.9(@types/react@19.1.12) + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.12)(react@19.1.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.12)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + optionalDependencies: + '@types/react': 19.1.12 + '@types/react-dom': 19.1.9(@types/react@19.1.12) + '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.28.3 @@ -14373,6 +14427,15 @@ snapshots: '@types/react': 19.1.12 '@types/react-dom': 19.1.9(@types/react@19.1.12) + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.12)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + optionalDependencies: + '@types/react': 19.1.12 + '@types/react-dom': 19.1.9(@types/react@19.1.12) + '@radix-ui/react-progress@1.1.7(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/react-context': 1.1.2(@types/react@19.1.12)(react@19.0.0) @@ -14580,6 +14643,20 @@ snapshots: optionalDependencies: '@types/react': 19.1.12 + '@radix-ui/react-slot@1.2.3(@types/react@19.1.12)(react@19.1.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.12)(react@19.1.1) + react: 19.1.1 + optionalDependencies: + '@types/react': 19.1.12 + + '@radix-ui/react-slot@1.2.4(@types/react@19.1.12)(react@19.1.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.12)(react@19.1.1) + react: 19.1.1 + optionalDependencies: + '@types/react': 19.1.12 + '@radix-ui/react-switch@1.2.6(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.3 @@ -14755,6 +14832,14 @@ snapshots: optionalDependencies: '@types/react': 19.1.12 + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.1.12)(react@19.1.1)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.1.12)(react@19.1.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.12)(react@19.1.1) + react: 19.1.1 + optionalDependencies: + '@types/react': 19.1.12 + '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.2.21)(react@18.2.0)': dependencies: '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.21)(react@18.2.0) @@ -14769,6 +14854,13 @@ snapshots: optionalDependencies: '@types/react': 19.1.12 + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.1.12)(react@19.1.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.12)(react@19.1.1) + react: 19.1.1 + optionalDependencies: + '@types/react': 19.1.12 + '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.21)(react@18.2.0)': dependencies: '@babel/runtime': 7.28.3 @@ -14817,6 +14909,12 @@ snapshots: optionalDependencies: '@types/react': 19.1.12 + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.1.12)(react@19.1.1)': + dependencies: + react: 19.1.1 + optionalDependencies: + '@types/react': 19.1.12 + '@radix-ui/react-use-previous@1.0.1(@types/react@18.2.21)(react@18.2.0)': dependencies: '@babel/runtime': 7.28.3 @@ -14836,6 +14934,12 @@ snapshots: optionalDependencies: '@types/react': 19.1.12 + '@radix-ui/react-use-previous@1.1.1(@types/react@19.1.12)(react@19.1.1)': + dependencies: + react: 19.1.1 + optionalDependencies: + '@types/react': 19.1.12 + '@radix-ui/react-use-rect@1.0.1(@types/react@18.2.21)(react@18.2.0)': dependencies: '@babel/runtime': 7.28.3 @@ -14880,6 +14984,13 @@ snapshots: optionalDependencies: '@types/react': 19.1.12 + '@radix-ui/react-use-size@1.1.1(@types/react@19.1.12)(react@19.1.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.12)(react@19.1.1) + react: 19.1.1 + optionalDependencies: + '@types/react': 19.1.12 + '@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.28.3