@codemation/ui 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.turbo/turbo-build.log +19 -0
  2. package/.turbo/turbo-lint.log +4 -0
  3. package/.turbo/turbo-typecheck.log +4 -0
  4. package/CHANGELOG.md +25 -0
  5. package/LICENSE +37 -0
  6. package/dist/index.cjs +845 -0
  7. package/dist/index.cjs.map +1 -0
  8. package/dist/index.d.cts +417 -0
  9. package/dist/index.d.ts +417 -0
  10. package/dist/index.js +749 -0
  11. package/dist/index.js.map +1 -0
  12. package/package.json +71 -0
  13. package/src/components/StatusPill.tsx +33 -0
  14. package/src/components/composite/CodemationDialog.tsx +137 -0
  15. package/src/components/composite/JsonMonacoEditor.tsx +75 -0
  16. package/src/components/reui/tree/Tree.tsx +35 -0
  17. package/src/components/reui/tree/TreeContext.ts +21 -0
  18. package/src/components/reui/tree/TreeDragLine.tsx +28 -0
  19. package/src/components/reui/tree/TreeItem.tsx +51 -0
  20. package/src/components/reui/tree/TreeItemLabel.tsx +58 -0
  21. package/src/components/ui/badge.tsx +40 -0
  22. package/src/components/ui/button.tsx +64 -0
  23. package/src/components/ui/collapsible.tsx +26 -0
  24. package/src/components/ui/dialog.tsx +137 -0
  25. package/src/components/ui/dropdown-menu.tsx +239 -0
  26. package/src/components/ui/input.tsx +20 -0
  27. package/src/components/ui/label.tsx +18 -0
  28. package/src/components/ui/select.tsx +171 -0
  29. package/src/components/ui/switch.tsx +29 -0
  30. package/src/components/ui/tabs.tsx +76 -0
  31. package/src/components/ui/textarea.tsx +18 -0
  32. package/src/index.ts +76 -0
  33. package/src/lib/cn.ts +6 -0
  34. package/src/lucide-icons.d.ts +46 -0
  35. package/test/StatusPill.test.tsx +26 -0
  36. package/test/primitives.test.tsx +707 -0
  37. package/test/setup.ts +7 -0
  38. package/test/ui-components.test.tsx +208 -0
  39. package/tsconfig.json +11 -0
  40. package/tsdown.config.ts +10 -0
  41. package/vitest.ui.config.ts +40 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["LabelPrimitive","SwitchPrimitive","CollapsiblePrimitive","DialogPrimitive","DropdownMenuPrimitive","SelectPrimitive","TabsPrimitive","defaultOptions: NonNullable<ComponentProps<typeof Editor>[\"options\"]>","KIND_CLASSES: Record<StatusKind, string>"],"sources":["../src/lib/cn.ts","../src/components/ui/badge.tsx","../src/components/ui/input.tsx","../src/components/ui/label.tsx","../src/components/ui/switch.tsx","../src/components/ui/button.tsx","../src/components/ui/collapsible.tsx","../src/components/ui/dialog.tsx","../src/components/ui/dropdown-menu.tsx","../src/components/ui/select.tsx","../src/components/ui/tabs.tsx","../src/components/ui/textarea.tsx","../src/components/reui/tree/TreeContext.ts","../src/components/reui/tree/Tree.tsx","../src/components/reui/tree/TreeDragLine.tsx","../src/components/reui/tree/TreeItem.tsx","../src/components/reui/tree/TreeItemLabel.tsx","../src/components/composite/CodemationDialog.tsx","../src/components/composite/JsonMonacoEditor.tsx","../src/components/StatusPill.tsx"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Slot } from \"radix-ui\";\n\nimport { cn } from \"../../lib/cn\";\n\nconst badgeVariants = cva(\n \"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap shadow-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n secondary: \"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80\",\n destructive:\n \"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20\",\n outline: \"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground\",\n ghost: \"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction Badge({\n className,\n variant = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot.Root : \"span\";\n\n return (\n <Comp data-slot=\"badge\" data-variant={variant} className={cn(badgeVariants({ variant }), className)} {...props} />\n );\n}\n\nexport { Badge, badgeVariants };\n","import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"border-input file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n \"aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Input };\n","import * as React from \"react\";\nimport { Label as LabelPrimitive } from \"radix-ui\";\nimport { cn } from \"../../lib/cn\";\n\nfunction Label({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) {\n return (\n <LabelPrimitive.Root\n data-slot=\"label\"\n className={cn(\n \"text-sm leading-none font-medium select-none group-data-[disabled=true]/form-item:pointer-events-none group-data-[disabled=true]/form-item:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Label };\n","import * as React from \"react\";\nimport { Switch as SwitchPrimitive } from \"radix-ui\";\nimport { cn } from \"../../lib/cn\";\n\nfunction Switch({ className, ...props }: React.ComponentProps<typeof SwitchPrimitive.Root>) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n className={cn(\n \"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-xs transition-[color,box-shadow] outline-none\",\n \"focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80\",\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n \"pointer-events-none block size-4 rounded-full bg-white shadow-sm ring-0 transition-transform\",\n \"data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0\",\n )}\n />\n </SwitchPrimitive.Root>\n );\n}\n\nexport { Switch };\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Slot } from \"radix-ui\";\n\nimport { cn } from \"../../lib/cn\";\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap shadow-sm transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n outline:\n \"shadow-none border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"shadow-none hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"shadow-none bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"shadow-none text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-sm px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-sm px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-8\",\n \"icon-xs\": \"size-6 rounded-sm in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-7 rounded-sm in-data-[slot=button-group]:rounded-md\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot.Root : \"button\";\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Collapsible as CollapsiblePrimitive } from \"radix-ui\";\n\nimport { cn } from \"../../lib/cn\";\n\nfunction Collapsible(props: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />;\n}\n\nfunction CollapsibleTrigger(props: React.ComponentProps<typeof CollapsiblePrimitive.Trigger>) {\n return <CollapsiblePrimitive.Trigger data-slot=\"collapsible-trigger\" {...props} />;\n}\n\nfunction CollapsibleContent({ className, ...props }: React.ComponentProps<typeof CollapsiblePrimitive.Content>) {\n return (\n <CollapsiblePrimitive.Content\n data-slot=\"collapsible-content\"\n className={cn(\"overflow-hidden\", className)}\n {...props}\n />\n );\n}\n\nexport { Collapsible, CollapsibleContent, CollapsibleTrigger };\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Dialog as DialogPrimitive } from \"radix-ui\";\n\nimport { cn } from \"../../lib/cn\";\nimport { Button } from \"./button\";\nimport XIcon from \"lucide-react/dist/esm/icons/x\";\n\nfunction Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nfunction DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nfunction DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nfunction DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nfunction DialogOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n showCloseButton?: boolean;\n}) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-background p-4 text-sm ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n className,\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close data-slot=\"dialog-close\" asChild>\n <Button variant=\"ghost\" className=\"absolute top-2 right-2\" size=\"icon-sm\">\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </Button>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div data-slot=\"dialog-header\" className={cn(\"flex flex-col gap-2\", className)} {...props} />;\n}\n\nfunction DialogFooter({\n className,\n showCloseButton = false,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showCloseButton?: boolean;\n}) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end\",\n className,\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close asChild>\n <Button variant=\"outline\">Close</Button>\n </DialogPrimitive.Close>\n )}\n </div>\n );\n}\n\nfunction DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-base leading-none font-medium\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\n \"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","\"use client\";\n\nimport * as React from \"react\";\nimport { DropdownMenu as DropdownMenuPrimitive } from \"radix-ui\";\n\nimport { cn } from \"../../lib/cn\";\nimport CheckIcon from \"lucide-react/dist/esm/icons/check\";\nimport ChevronRightIcon from \"lucide-react/dist/esm/icons/chevron-right\";\n\nfunction DropdownMenu({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nfunction DropdownMenuPortal({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {\n return <DropdownMenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />;\n}\n\nfunction DropdownMenuTrigger({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n return <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nfunction DropdownMenuContent({\n className,\n align = \"start\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n align={align}\n className={cn(\n \"z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:overflow-hidden data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nfunction DropdownMenuGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {\n return <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: \"default\" | \"destructive\";\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n data-inset={inset}\n className={cn(\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n data-slot=\"dropdown-menu-checkbox-item-indicator\"\n >\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction DropdownMenuRadioGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {\n return <DropdownMenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />;\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n data-inset={inset}\n className={cn(\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n data-slot=\"dropdown-menu-radio-item-indicator\"\n >\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\"px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7\", className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuShortcut({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSub({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto\" />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nfunction DropdownMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n return (\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"z-50 min-w-[96px] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n};\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Select as SelectPrimitive } from \"radix-ui\";\n\nimport { cn } from \"../../lib/cn\";\nimport CheckIcon from \"lucide-react/dist/esm/icons/check\";\nimport ChevronDownIcon from \"lucide-react/dist/esm/icons/chevron-down\";\nimport ChevronUpIcon from \"lucide-react/dist/esm/icons/chevron-up\";\n\nfunction Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nfunction SelectGroup({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group data-slot=\"select-group\" className={cn(\"scroll-my-1 p-1\", className)} {...props} />;\n}\n\nfunction SelectValue({ ...props }: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nfunction SelectTrigger({\n className,\n size = \"default\",\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {\n size?: \"sm\" | \"default\";\n}) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n \"flex w-fit items-center justify-between gap-1.5 rounded-md border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap shadow-sm transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-sm *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"pointer-events-none size-4 text-muted-foreground\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\n\nfunction SelectContent({\n className,\n children,\n position = \"item-aligned\",\n align = \"center\",\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n data-align-trigger={position === \"item-aligned\"}\n className={cn(\n \"relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n position === \"popper\" &&\n \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n className,\n )}\n position={position}\n align={align}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n data-position={position}\n className={cn(\n \"data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)\",\n position === \"popper\" && \"\",\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\n\nfunction SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(\"px-1.5 py-1 text-xs text-muted-foreground\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectItem({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\n className,\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute right-2 flex size-4 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"pointer-events-none\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\n\nfunction SelectSeparator({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\"pointer-events-none -mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectScrollUpButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n return (\n <SelectPrimitive.ScrollUpButton\n data-slot=\"select-scroll-up-button\"\n className={cn(\n \"z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n <ChevronUpIcon />\n </SelectPrimitive.ScrollUpButton>\n );\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n return (\n <SelectPrimitive.ScrollDownButton\n data-slot=\"select-scroll-down-button\"\n className={cn(\n \"z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n <ChevronDownIcon />\n </SelectPrimitive.ScrollDownButton>\n );\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Tabs as TabsPrimitive } from \"radix-ui\";\n\nimport { cn } from \"../../lib/cn\";\n\nfunction Tabs({ className, orientation = \"horizontal\", ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n data-orientation={orientation}\n className={cn(\"group/tabs flex gap-2 data-horizontal:flex-col\", className)}\n {...props}\n />\n );\n}\n\nconst tabsListVariants = cva(\n \"group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none\",\n {\n variants: {\n variant: {\n default: \"bg-muted\",\n line: \"gap-1 bg-transparent\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction TabsList({\n className,\n variant = \"default\",\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.List> & VariantProps<typeof tabsListVariants>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n data-variant={variant}\n className={cn(tabsListVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nfunction TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n \"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent\",\n \"data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground\",\n \"after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return (\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n className={cn(\"flex-1 text-sm outline-none\", className)}\n {...props}\n />\n );\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };\n","import * as React from \"react\";\n\nimport { cn } from \"../../lib/cn\";\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Textarea };\n","import type { ItemInstance } from \"@headless-tree/core\";\nimport { createContext } from \"react\";\n\nexport type ToggleIconType = \"chevron\" | \"plus-minus\";\n\nexport type TreeContextValue<T = unknown> = {\n indent: number;\n currentItem?: ItemInstance<T>;\n tree?: {\n getContainerProps?: () => Record<string, unknown>;\n getDragLineStyle?: () => Record<string, unknown> | null;\n };\n toggleIconType?: ToggleIconType;\n};\n\nexport const TreeContext = createContext<TreeContextValue>({\n indent: 20,\n currentItem: undefined,\n tree: undefined,\n toggleIconType: \"plus-minus\",\n});\n","\"use client\";\n\nimport { Slot } from \"radix-ui\";\nimport type { CSSProperties, HTMLAttributes } from \"react\";\n\nimport { cn } from \"../../../lib/cn\";\n\nimport { TreeContext, type ToggleIconType } from \"./TreeContext\";\n\ntype TreeProps = HTMLAttributes<HTMLDivElement> & {\n indent?: number;\n tree?: {\n getContainerProps?: () => Record<string, unknown>;\n };\n toggleIconType?: ToggleIconType;\n asChild?: boolean;\n};\n\nexport function Tree(args: Readonly<TreeProps>) {\n const { indent = 20, tree, className, toggleIconType = \"chevron\", asChild = false, ...props } = args;\n const containerProps = tree?.getContainerProps?.() ?? {};\n const mergedProps = { ...props, ...containerProps };\n const { style: propStyle, ...otherProps } = mergedProps as HTMLAttributes<HTMLDivElement>;\n const mergedStyle = {\n ...propStyle,\n \"--tree-indent\": `${indent}px`,\n } as CSSProperties;\n const Component = asChild ? Slot.Root : \"div\";\n\n return (\n <TreeContext.Provider value={{ indent, tree, toggleIconType }}>\n <Component data-slot=\"tree\" style={mergedStyle} className={cn(\"flex flex-col\", className)} {...otherProps} />\n </TreeContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useContext, type HTMLAttributes } from \"react\";\n\nimport { cn } from \"../../../lib/cn\";\n\nimport { TreeContext } from \"./TreeContext\";\n\nexport function TreeDragLine(args: Readonly<HTMLAttributes<HTMLDivElement>>) {\n const { className, ...props } = args;\n const { tree } = useContext(TreeContext);\n const dragLine = tree?.getDragLineStyle?.();\n\n if (!dragLine) {\n return null;\n }\n\n return (\n <div\n style={dragLine}\n className={cn(\n \"bg-primary before:bg-background before:border-primary absolute z-30 -mt-px h-0.5 w-[unset] before:absolute before:-top-[3px] before:left-0 before:size-2 before:border-2 before:rounded-full\",\n className,\n )}\n {...props}\n />\n );\n}\n","\"use client\";\n\nimport type { ItemInstance } from \"@headless-tree/core\";\nimport { Slot } from \"radix-ui\";\nimport { useContext, type ButtonHTMLAttributes, type CSSProperties } from \"react\";\n\nimport { cn } from \"../../../lib/cn\";\n\nimport { TreeContext } from \"./TreeContext\";\n\ntype TreeItemProps<T = unknown> = Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"indent\"> & {\n item: ItemInstance<T>;\n indent?: number;\n asChild?: boolean;\n};\n\nexport function TreeItem<T = unknown>(args: Readonly<TreeItemProps<T>>) {\n const { item, className, asChild = false, children, ...props } = args;\n const parentContext = useContext(TreeContext);\n const indent = parentContext.indent;\n const itemProps = item.getProps();\n const mergedProps = { ...props, children, ...itemProps };\n const { style: propStyle, ...otherProps } = mergedProps as ButtonHTMLAttributes<HTMLButtonElement>;\n const mergedStyle = {\n ...propStyle,\n \"--tree-padding\": `${item.getItemMeta().level * indent}px`,\n } as CSSProperties;\n const defaultProps = {\n \"data-slot\": \"tree-item\",\n style: mergedStyle,\n className: cn(\n \"z-10 ps-(--tree-padding) outline-hidden select-none not-last:pb-0.5 focus:z-20 data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n ),\n \"data-focus\": item.isFocused() || false,\n \"data-folder\": item.isFolder() || false,\n \"data-selected\": typeof item.isSelected === \"function\" ? item.isSelected() || false : undefined,\n \"data-drag-target\": typeof item.isDragTarget === \"function\" ? item.isDragTarget() || false : undefined,\n \"data-search-match\": typeof item.isMatchingSearch === \"function\" ? item.isMatchingSearch() || false : undefined,\n \"aria-expanded\": item.isExpanded(),\n };\n const Component = asChild ? Slot.Root : \"button\";\n\n return (\n <TreeContext.Provider value={{ ...parentContext, currentItem: item as ItemInstance<unknown> }}>\n <Component {...defaultProps} {...otherProps}>\n {children}\n </Component>\n </TreeContext.Provider>\n );\n}\n","\"use client\";\n\nimport ChevronDownIcon from \"lucide-react/dist/esm/icons/chevron-down\";\nimport MinusIcon from \"lucide-react/dist/esm/icons/minus\";\nimport PlusIcon from \"lucide-react/dist/esm/icons/plus\";\nimport { Slot } from \"radix-ui\";\nimport { Fragment, useContext, type HTMLAttributes } from \"react\";\n\nimport { cn } from \"../../../lib/cn\";\n\nimport { TreeContext } from \"./TreeContext\";\n\ntype TreeItemLabelProps = HTMLAttributes<HTMLSpanElement> & {\n item?: {\n isFolder: () => boolean;\n isExpanded: () => boolean;\n getItemName: () => string;\n };\n asChild?: boolean;\n};\n\nexport function TreeItemLabel(args: Readonly<TreeItemLabelProps>) {\n const { item: propItem, children, className, asChild = false, ...props } = args;\n const { currentItem, toggleIconType } = useContext(TreeContext);\n const item = propItem ?? currentItem;\n\n if (!item) {\n return null;\n }\n\n const Component = asChild ? Slot.Root : \"span\";\n\n return (\n <Component\n data-slot=\"tree-item-label\"\n className={cn(\n \"in-focus-visible:ring-ring/50 bg-background hover:bg-accent in-data-[selected=true]:bg-accent in-data-[selected=true]:text-accent-foreground in-data-[drag-target=true]:bg-accent flex items-center gap-1 transition-colors not-in-data-[folder=true]:ps-7 in-focus-visible:ring-[3px] in-data-[search-match=true]:bg-blue-50! [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"rounded-sm py-1.5 px-2 text-sm\",\n className,\n )}\n {...props}\n >\n <Fragment>\n {item.isFolder() &&\n (toggleIconType === \"plus-minus\" ? (\n item.isExpanded() ? (\n <MinusIcon className=\"text-muted-foreground size-3.5\" stroke=\"currentColor\" strokeWidth=\"1\" />\n ) : (\n <PlusIcon className=\"text-muted-foreground size-3.5\" stroke=\"currentColor\" strokeWidth=\"1\" />\n )\n ) : (\n <ChevronDownIcon className=\"text-muted-foreground size-4 in-aria-[expanded=false]:-rotate-90\" />\n ))}\n {children ?? item.getItemName()}\n </Fragment>\n </Component>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { Dialog, DialogContent, DialogTitle } from \"../ui/dialog\";\nimport { cn } from \"../../lib/cn\";\n\nconst maxWidthBySize = {\n narrow: \"sm:max-w-lg\",\n wide: \"sm:max-w-2xl\",\n full: \"sm:max-w-[min(92vw,960px)]\",\n} as const;\n\nexport type CodemationDialogSize = keyof typeof maxWidthBySize;\n\nexport type CodemationDialogRootProps = Readonly<{\n children: React.ReactNode;\n onClose: () => void;\n /** Root `data-testid` (applied to the dialog panel). */\n testId?: string;\n /** `dialog` (default) or `alertdialog` for confirmations. */\n role?: \"dialog\" | \"alertdialog\";\n /** Max width preset; default `wide`. */\n size?: CodemationDialogSize;\n /** Extra classes on the Radix panel (e.g. `max-h-[min(90vh,640px)]`). */\n contentClassName?: string;\n /** Corner X to dismiss (Radix); default false — use `<CodemationDialog.Actions>` for explicit buttons. */\n showCloseButton?: boolean;\n}>;\n\nfunction CodemationDialogRoot({\n children,\n onClose,\n testId,\n role = \"dialog\",\n size = \"wide\",\n contentClassName,\n showCloseButton = false,\n}: CodemationDialogRootProps) {\n return (\n <Dialog\n open\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n <DialogContent\n showCloseButton={showCloseButton}\n data-testid={testId}\n role={role}\n aria-describedby={undefined}\n className={cn(\n \"flex max-h-[min(92vh,900px)] flex-col gap-0 overflow-hidden p-0\",\n maxWidthBySize[size],\n contentClassName,\n )}\n >\n {children}\n </DialogContent>\n </Dialog>\n );\n}\n\nexport type CodemationDialogTitleProps = Readonly<{\n children: React.ReactNode;\n className?: string;\n}>;\n\n/**\n * Do not set `id` on the underlying Radix `DialogTitle` — the dialog root assigns `titleId`\n * in context; overriding `id` breaks `aria-labelledby` and Radix dev warnings.\n */\nfunction CodemationDialogTitle({ children, className }: CodemationDialogTitleProps) {\n return (\n <DialogTitle\n className={cn(\"m-0 shrink-0 border-b border-border px-4 py-3 text-base leading-none font-semibold\", className)}\n >\n {children}\n </DialogTitle>\n );\n}\n\nexport type CodemationDialogContentProps = Readonly<{\n children: React.ReactNode;\n className?: string;\n}>;\n\nfunction CodemationDialogContent({ children, className }: CodemationDialogContentProps) {\n return (\n <div className={cn(\"flex min-h-0 flex-1 flex-col gap-4 overflow-auto px-4 py-3 text-sm\", className)}>\n {children}\n </div>\n );\n}\n\nexport type CodemationDialogActionsProps = Readonly<{\n children: React.ReactNode;\n /** Toolbar directly under the title (e.g. filters). Default is footer actions. */\n position?: \"top\" | \"bottom\";\n /** Flex alignment for the button row. */\n align?: \"start\" | \"end\" | \"between\";\n className?: string;\n}>;\n\nfunction CodemationDialogActions({\n children,\n position = \"bottom\",\n align = \"end\",\n className,\n}: CodemationDialogActionsProps) {\n return (\n <div\n className={cn(\n \"flex shrink-0 flex-wrap gap-2 border-border bg-muted/30 px-4 py-3\",\n position === \"top\" ? \"border-b\" : \"border-t\",\n align === \"end\" && \"justify-end\",\n align === \"start\" && \"justify-start\",\n align === \"between\" && \"justify-between\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nexport type CodemationDialogCompound = typeof CodemationDialogRoot & {\n Title: typeof CodemationDialogTitle;\n Content: typeof CodemationDialogContent;\n Actions: typeof CodemationDialogActions;\n};\n\nexport const CodemationDialog = Object.assign(CodemationDialogRoot, {\n Title: CodemationDialogTitle,\n Content: CodemationDialogContent,\n Actions: CodemationDialogActions,\n}) as CodemationDialogCompound;\n","\"use client\";\n\nimport Editor from \"@monaco-editor/react\";\nimport type { ComponentProps } from \"react\";\n\nimport { Textarea } from \"../ui/textarea\";\n\nconst defaultOptions: NonNullable<ComponentProps<typeof Editor>[\"options\"]> = {\n automaticLayout: true,\n formatOnPaste: true,\n formatOnType: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: false,\n lineNumbersMinChars: 3,\n tabSize: 2,\n insertSpaces: true,\n wordWrap: \"on\",\n bracketPairColorization: {\n enabled: true,\n },\n guides: {\n indentation: true,\n bracketPairs: true,\n },\n padding: {\n top: 12,\n bottom: 12,\n },\n};\n\n/**\n * Monaco-based JSON editor with a mirrored, visually hidden `<textarea>` that carries the same value.\n * Tests and automation can drive `data-testid` on that textarea because Monaco's surface is not a reliable\n * DOM target for `fireEvent.change` / user typing simulation.\n */\nexport function JsonMonacoEditor(\n args: Readonly<{\n path: string;\n value: string;\n onChange: (value: string | undefined) => void;\n /** Shown below the editor region when set. */\n error?: string | null;\n /** Passed to the hidden textarea for stable test selectors. */\n testId?: string;\n }>,\n) {\n const { path, value, onChange, error, testId = \"workflow-json-editor-input\" } = args;\n return (\n <div className=\"relative flex min-h-0 flex-1 flex-col\">\n <div className=\"h-[min(60vh,560px)] min-h-[200px] shrink-0 overflow-hidden rounded-md border border-border bg-background\">\n <Editor\n height=\"100%\"\n language=\"json\"\n path={path}\n value={value}\n onChange={onChange}\n loading={<div className=\"grid h-full place-items-center text-xs text-muted-foreground\">Loading editor…</div>}\n options={defaultOptions}\n />\n </div>\n <Textarea\n data-testid={testId}\n value={value}\n onChange={(event) => {\n onChange(event.target.value);\n }}\n spellCheck={false}\n className=\"pointer-events-none absolute inset-0 h-px w-px min-h-0 resize-none border-0 p-0 opacity-0\"\n aria-hidden=\"true\"\n tabIndex={-1}\n />\n {error ? <div className=\"mt-1 text-xs text-destructive\">{error}</div> : null}\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { Badge } from \"./ui/badge\";\nimport { cn } from \"../lib/cn\";\n\nexport type StatusKind = \"success\" | \"warning\" | \"danger\" | \"neutral\" | \"info\";\n\nconst KIND_CLASSES: Record<StatusKind, string> = {\n success:\n \"bg-emerald-100 text-emerald-800 border-emerald-200 hover:bg-emerald-100 dark:bg-emerald-900/30 dark:text-emerald-300 dark:border-emerald-800\",\n warning:\n \"bg-amber-100 text-amber-800 border-amber-200 hover:bg-amber-100 dark:bg-amber-900/30 dark:text-amber-300 dark:border-amber-800\",\n danger:\n \"bg-red-100 text-red-800 border-red-200 hover:bg-red-100 dark:bg-red-900/30 dark:text-red-300 dark:border-red-800\",\n neutral: \"border-border text-foreground bg-transparent hover:bg-muted\",\n info: \"bg-blue-100 text-blue-800 border-blue-200 hover:bg-blue-100 dark:bg-blue-900/30 dark:text-blue-300 dark:border-blue-800\",\n};\n\nexport interface StatusPillProps {\n status: StatusKind;\n children?: React.ReactNode;\n className?: string;\n}\n\nexport function StatusPill({ status, children, className }: StatusPillProps) {\n return (\n <Badge variant=\"outline\" className={cn(\"inline-flex items-center gap-1\", KIND_CLASSES[status], className)}>\n {children ?? status}\n </Badge>\n );\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@codemation/ui",
3
+ "version": "0.2.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "author": "Made Relevant B.V.",
8
+ "homepage": "https://www.maderelevant.com",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/MadeRelevant/codemation",
12
+ "directory": "packages/ui"
13
+ },
14
+ "license": "SEE LICENSE IN LICENSE",
15
+ "type": "module",
16
+ "main": "./dist/index.cjs",
17
+ "module": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "development": "./src/index.ts",
23
+ "import": "./dist/index.js",
24
+ "require": "./dist/index.cjs"
25
+ }
26
+ },
27
+ "dependencies": {
28
+ "class-variance-authority": "^0.7.1",
29
+ "clsx": "^2.1.1",
30
+ "tailwind-merge": "^3.5.0"
31
+ },
32
+ "peerDependencies": {
33
+ "@headless-tree/core": "*",
34
+ "@monaco-editor/react": "*",
35
+ "lucide-react": "*",
36
+ "radix-ui": "*",
37
+ "react": "*",
38
+ "react-dom": "*"
39
+ },
40
+ "devDependencies": {
41
+ "eslint": "^10.0.3",
42
+ "@headless-tree/core": "^1.6.3",
43
+ "@headless-tree/react": "^1.6.3",
44
+ "@monaco-editor/react": "^4.7.0",
45
+ "@testing-library/jest-dom": "^6.9.1",
46
+ "@testing-library/react": "^16.3.2",
47
+ "@types/react": "*",
48
+ "@types/react-dom": "^19.2.3",
49
+ "class-variance-authority": "^0.7.1",
50
+ "clsx": "^2.1.1",
51
+ "jsdom": "^29.1.1",
52
+ "lucide-react": "^0.577.0",
53
+ "radix-ui": "^1.4.3",
54
+ "react": "^19.2.4",
55
+ "react-dom": "^19.2.4",
56
+ "tailwind-merge": "^3.5.0",
57
+ "tsdown": "^0.15.5",
58
+ "typescript": "^5.9.3",
59
+ "vitest": "^4.1.6"
60
+ },
61
+ "sideEffects": false,
62
+ "scripts": {
63
+ "changeset:verify": "pnpm --workspace-root run changeset:verify",
64
+ "dev": "tsdown --watch",
65
+ "build": "tsdown",
66
+ "typecheck": "tsc -p tsconfig.json --noEmit",
67
+ "lint": "eslint .",
68
+ "test:unit": "vitest run --config vitest.ui.config.ts --passWithNoTests",
69
+ "test:ui": "vitest run --config vitest.ui.config.ts"
70
+ }
71
+ }
@@ -0,0 +1,33 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+
5
+ import { Badge } from "./ui/badge";
6
+ import { cn } from "../lib/cn";
7
+
8
+ export type StatusKind = "success" | "warning" | "danger" | "neutral" | "info";
9
+
10
+ const KIND_CLASSES: Record<StatusKind, string> = {
11
+ success:
12
+ "bg-emerald-100 text-emerald-800 border-emerald-200 hover:bg-emerald-100 dark:bg-emerald-900/30 dark:text-emerald-300 dark:border-emerald-800",
13
+ warning:
14
+ "bg-amber-100 text-amber-800 border-amber-200 hover:bg-amber-100 dark:bg-amber-900/30 dark:text-amber-300 dark:border-amber-800",
15
+ danger:
16
+ "bg-red-100 text-red-800 border-red-200 hover:bg-red-100 dark:bg-red-900/30 dark:text-red-300 dark:border-red-800",
17
+ neutral: "border-border text-foreground bg-transparent hover:bg-muted",
18
+ info: "bg-blue-100 text-blue-800 border-blue-200 hover:bg-blue-100 dark:bg-blue-900/30 dark:text-blue-300 dark:border-blue-800",
19
+ };
20
+
21
+ export interface StatusPillProps {
22
+ status: StatusKind;
23
+ children?: React.ReactNode;
24
+ className?: string;
25
+ }
26
+
27
+ export function StatusPill({ status, children, className }: StatusPillProps) {
28
+ return (
29
+ <Badge variant="outline" className={cn("inline-flex items-center gap-1", KIND_CLASSES[status], className)}>
30
+ {children ?? status}
31
+ </Badge>
32
+ );
33
+ }
@@ -0,0 +1,137 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+
5
+ import { Dialog, DialogContent, DialogTitle } from "../ui/dialog";
6
+ import { cn } from "../../lib/cn";
7
+
8
+ const maxWidthBySize = {
9
+ narrow: "sm:max-w-lg",
10
+ wide: "sm:max-w-2xl",
11
+ full: "sm:max-w-[min(92vw,960px)]",
12
+ } as const;
13
+
14
+ export type CodemationDialogSize = keyof typeof maxWidthBySize;
15
+
16
+ export type CodemationDialogRootProps = Readonly<{
17
+ children: React.ReactNode;
18
+ onClose: () => void;
19
+ /** Root `data-testid` (applied to the dialog panel). */
20
+ testId?: string;
21
+ /** `dialog` (default) or `alertdialog` for confirmations. */
22
+ role?: "dialog" | "alertdialog";
23
+ /** Max width preset; default `wide`. */
24
+ size?: CodemationDialogSize;
25
+ /** Extra classes on the Radix panel (e.g. `max-h-[min(90vh,640px)]`). */
26
+ contentClassName?: string;
27
+ /** Corner X to dismiss (Radix); default false — use `<CodemationDialog.Actions>` for explicit buttons. */
28
+ showCloseButton?: boolean;
29
+ }>;
30
+
31
+ function CodemationDialogRoot({
32
+ children,
33
+ onClose,
34
+ testId,
35
+ role = "dialog",
36
+ size = "wide",
37
+ contentClassName,
38
+ showCloseButton = false,
39
+ }: CodemationDialogRootProps) {
40
+ return (
41
+ <Dialog
42
+ open
43
+ onOpenChange={(open) => {
44
+ if (!open) onClose();
45
+ }}
46
+ >
47
+ <DialogContent
48
+ showCloseButton={showCloseButton}
49
+ data-testid={testId}
50
+ role={role}
51
+ aria-describedby={undefined}
52
+ className={cn(
53
+ "flex max-h-[min(92vh,900px)] flex-col gap-0 overflow-hidden p-0",
54
+ maxWidthBySize[size],
55
+ contentClassName,
56
+ )}
57
+ >
58
+ {children}
59
+ </DialogContent>
60
+ </Dialog>
61
+ );
62
+ }
63
+
64
+ export type CodemationDialogTitleProps = Readonly<{
65
+ children: React.ReactNode;
66
+ className?: string;
67
+ }>;
68
+
69
+ /**
70
+ * Do not set `id` on the underlying Radix `DialogTitle` — the dialog root assigns `titleId`
71
+ * in context; overriding `id` breaks `aria-labelledby` and Radix dev warnings.
72
+ */
73
+ function CodemationDialogTitle({ children, className }: CodemationDialogTitleProps) {
74
+ return (
75
+ <DialogTitle
76
+ className={cn("m-0 shrink-0 border-b border-border px-4 py-3 text-base leading-none font-semibold", className)}
77
+ >
78
+ {children}
79
+ </DialogTitle>
80
+ );
81
+ }
82
+
83
+ export type CodemationDialogContentProps = Readonly<{
84
+ children: React.ReactNode;
85
+ className?: string;
86
+ }>;
87
+
88
+ function CodemationDialogContent({ children, className }: CodemationDialogContentProps) {
89
+ return (
90
+ <div className={cn("flex min-h-0 flex-1 flex-col gap-4 overflow-auto px-4 py-3 text-sm", className)}>
91
+ {children}
92
+ </div>
93
+ );
94
+ }
95
+
96
+ export type CodemationDialogActionsProps = Readonly<{
97
+ children: React.ReactNode;
98
+ /** Toolbar directly under the title (e.g. filters). Default is footer actions. */
99
+ position?: "top" | "bottom";
100
+ /** Flex alignment for the button row. */
101
+ align?: "start" | "end" | "between";
102
+ className?: string;
103
+ }>;
104
+
105
+ function CodemationDialogActions({
106
+ children,
107
+ position = "bottom",
108
+ align = "end",
109
+ className,
110
+ }: CodemationDialogActionsProps) {
111
+ return (
112
+ <div
113
+ className={cn(
114
+ "flex shrink-0 flex-wrap gap-2 border-border bg-muted/30 px-4 py-3",
115
+ position === "top" ? "border-b" : "border-t",
116
+ align === "end" && "justify-end",
117
+ align === "start" && "justify-start",
118
+ align === "between" && "justify-between",
119
+ className,
120
+ )}
121
+ >
122
+ {children}
123
+ </div>
124
+ );
125
+ }
126
+
127
+ export type CodemationDialogCompound = typeof CodemationDialogRoot & {
128
+ Title: typeof CodemationDialogTitle;
129
+ Content: typeof CodemationDialogContent;
130
+ Actions: typeof CodemationDialogActions;
131
+ };
132
+
133
+ export const CodemationDialog = Object.assign(CodemationDialogRoot, {
134
+ Title: CodemationDialogTitle,
135
+ Content: CodemationDialogContent,
136
+ Actions: CodemationDialogActions,
137
+ }) as CodemationDialogCompound;
@@ -0,0 +1,75 @@
1
+ "use client";
2
+
3
+ import Editor from "@monaco-editor/react";
4
+ import type { ComponentProps } from "react";
5
+
6
+ import { Textarea } from "../ui/textarea";
7
+
8
+ const defaultOptions: NonNullable<ComponentProps<typeof Editor>["options"]> = {
9
+ automaticLayout: true,
10
+ formatOnPaste: true,
11
+ formatOnType: true,
12
+ minimap: { enabled: false },
13
+ scrollBeyondLastLine: false,
14
+ lineNumbersMinChars: 3,
15
+ tabSize: 2,
16
+ insertSpaces: true,
17
+ wordWrap: "on",
18
+ bracketPairColorization: {
19
+ enabled: true,
20
+ },
21
+ guides: {
22
+ indentation: true,
23
+ bracketPairs: true,
24
+ },
25
+ padding: {
26
+ top: 12,
27
+ bottom: 12,
28
+ },
29
+ };
30
+
31
+ /**
32
+ * Monaco-based JSON editor with a mirrored, visually hidden `<textarea>` that carries the same value.
33
+ * Tests and automation can drive `data-testid` on that textarea because Monaco's surface is not a reliable
34
+ * DOM target for `fireEvent.change` / user typing simulation.
35
+ */
36
+ export function JsonMonacoEditor(
37
+ args: Readonly<{
38
+ path: string;
39
+ value: string;
40
+ onChange: (value: string | undefined) => void;
41
+ /** Shown below the editor region when set. */
42
+ error?: string | null;
43
+ /** Passed to the hidden textarea for stable test selectors. */
44
+ testId?: string;
45
+ }>,
46
+ ) {
47
+ const { path, value, onChange, error, testId = "workflow-json-editor-input" } = args;
48
+ return (
49
+ <div className="relative flex min-h-0 flex-1 flex-col">
50
+ <div className="h-[min(60vh,560px)] min-h-[200px] shrink-0 overflow-hidden rounded-md border border-border bg-background">
51
+ <Editor
52
+ height="100%"
53
+ language="json"
54
+ path={path}
55
+ value={value}
56
+ onChange={onChange}
57
+ loading={<div className="grid h-full place-items-center text-xs text-muted-foreground">Loading editor…</div>}
58
+ options={defaultOptions}
59
+ />
60
+ </div>
61
+ <Textarea
62
+ data-testid={testId}
63
+ value={value}
64
+ onChange={(event) => {
65
+ onChange(event.target.value);
66
+ }}
67
+ spellCheck={false}
68
+ className="pointer-events-none absolute inset-0 h-px w-px min-h-0 resize-none border-0 p-0 opacity-0"
69
+ aria-hidden="true"
70
+ tabIndex={-1}
71
+ />
72
+ {error ? <div className="mt-1 text-xs text-destructive">{error}</div> : null}
73
+ </div>
74
+ );
75
+ }
@@ -0,0 +1,35 @@
1
+ "use client";
2
+
3
+ import { Slot } from "radix-ui";
4
+ import type { CSSProperties, HTMLAttributes } from "react";
5
+
6
+ import { cn } from "../../../lib/cn";
7
+
8
+ import { TreeContext, type ToggleIconType } from "./TreeContext";
9
+
10
+ type TreeProps = HTMLAttributes<HTMLDivElement> & {
11
+ indent?: number;
12
+ tree?: {
13
+ getContainerProps?: () => Record<string, unknown>;
14
+ };
15
+ toggleIconType?: ToggleIconType;
16
+ asChild?: boolean;
17
+ };
18
+
19
+ export function Tree(args: Readonly<TreeProps>) {
20
+ const { indent = 20, tree, className, toggleIconType = "chevron", asChild = false, ...props } = args;
21
+ const containerProps = tree?.getContainerProps?.() ?? {};
22
+ const mergedProps = { ...props, ...containerProps };
23
+ const { style: propStyle, ...otherProps } = mergedProps as HTMLAttributes<HTMLDivElement>;
24
+ const mergedStyle = {
25
+ ...propStyle,
26
+ "--tree-indent": `${indent}px`,
27
+ } as CSSProperties;
28
+ const Component = asChild ? Slot.Root : "div";
29
+
30
+ return (
31
+ <TreeContext.Provider value={{ indent, tree, toggleIconType }}>
32
+ <Component data-slot="tree" style={mergedStyle} className={cn("flex flex-col", className)} {...otherProps} />
33
+ </TreeContext.Provider>
34
+ );
35
+ }
@@ -0,0 +1,21 @@
1
+ import type { ItemInstance } from "@headless-tree/core";
2
+ import { createContext } from "react";
3
+
4
+ export type ToggleIconType = "chevron" | "plus-minus";
5
+
6
+ export type TreeContextValue<T = unknown> = {
7
+ indent: number;
8
+ currentItem?: ItemInstance<T>;
9
+ tree?: {
10
+ getContainerProps?: () => Record<string, unknown>;
11
+ getDragLineStyle?: () => Record<string, unknown> | null;
12
+ };
13
+ toggleIconType?: ToggleIconType;
14
+ };
15
+
16
+ export const TreeContext = createContext<TreeContextValue>({
17
+ indent: 20,
18
+ currentItem: undefined,
19
+ tree: undefined,
20
+ toggleIconType: "plus-minus",
21
+ });
@@ -0,0 +1,28 @@
1
+ "use client";
2
+
3
+ import { useContext, type HTMLAttributes } from "react";
4
+
5
+ import { cn } from "../../../lib/cn";
6
+
7
+ import { TreeContext } from "./TreeContext";
8
+
9
+ export function TreeDragLine(args: Readonly<HTMLAttributes<HTMLDivElement>>) {
10
+ const { className, ...props } = args;
11
+ const { tree } = useContext(TreeContext);
12
+ const dragLine = tree?.getDragLineStyle?.();
13
+
14
+ if (!dragLine) {
15
+ return null;
16
+ }
17
+
18
+ return (
19
+ <div
20
+ style={dragLine}
21
+ className={cn(
22
+ "bg-primary before:bg-background before:border-primary absolute z-30 -mt-px h-0.5 w-[unset] before:absolute before:-top-[3px] before:left-0 before:size-2 before:border-2 before:rounded-full",
23
+ className,
24
+ )}
25
+ {...props}
26
+ />
27
+ );
28
+ }
@@ -0,0 +1,51 @@
1
+ "use client";
2
+
3
+ import type { ItemInstance } from "@headless-tree/core";
4
+ import { Slot } from "radix-ui";
5
+ import { useContext, type ButtonHTMLAttributes, type CSSProperties } from "react";
6
+
7
+ import { cn } from "../../../lib/cn";
8
+
9
+ import { TreeContext } from "./TreeContext";
10
+
11
+ type TreeItemProps<T = unknown> = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "indent"> & {
12
+ item: ItemInstance<T>;
13
+ indent?: number;
14
+ asChild?: boolean;
15
+ };
16
+
17
+ export function TreeItem<T = unknown>(args: Readonly<TreeItemProps<T>>) {
18
+ const { item, className, asChild = false, children, ...props } = args;
19
+ const parentContext = useContext(TreeContext);
20
+ const indent = parentContext.indent;
21
+ const itemProps = item.getProps();
22
+ const mergedProps = { ...props, children, ...itemProps };
23
+ const { style: propStyle, ...otherProps } = mergedProps as ButtonHTMLAttributes<HTMLButtonElement>;
24
+ const mergedStyle = {
25
+ ...propStyle,
26
+ "--tree-padding": `${item.getItemMeta().level * indent}px`,
27
+ } as CSSProperties;
28
+ const defaultProps = {
29
+ "data-slot": "tree-item",
30
+ style: mergedStyle,
31
+ className: cn(
32
+ "z-10 ps-(--tree-padding) outline-hidden select-none not-last:pb-0.5 focus:z-20 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
33
+ className,
34
+ ),
35
+ "data-focus": item.isFocused() || false,
36
+ "data-folder": item.isFolder() || false,
37
+ "data-selected": typeof item.isSelected === "function" ? item.isSelected() || false : undefined,
38
+ "data-drag-target": typeof item.isDragTarget === "function" ? item.isDragTarget() || false : undefined,
39
+ "data-search-match": typeof item.isMatchingSearch === "function" ? item.isMatchingSearch() || false : undefined,
40
+ "aria-expanded": item.isExpanded(),
41
+ };
42
+ const Component = asChild ? Slot.Root : "button";
43
+
44
+ return (
45
+ <TreeContext.Provider value={{ ...parentContext, currentItem: item as ItemInstance<unknown> }}>
46
+ <Component {...defaultProps} {...otherProps}>
47
+ {children}
48
+ </Component>
49
+ </TreeContext.Provider>
50
+ );
51
+ }