mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-27 21:01:32 +08:00
feat: update UI components and styles with Radix and Tailwind integration
- Added new UI components including Button, Command, Dialog, Popover, and Dropzone using Radix UI. - Introduced global styles with Tailwind CSS for consistent theming and design. - Updated existing components to utilize new utility functions for class name management. - Enhanced Tooltip component with inline-block display for better layout. - Updated package dependencies in package.json and yarn.lock to include new Radix and Tailwind packages.
This commit is contained in:
parent
bab1a5445c
commit
534c2ce485
21
packages/ui/components.json
Normal file
21
packages/ui/components.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"hooks": "@/hooks",
|
||||
"lib": "@/lib",
|
||||
"ui": "@/components/ui",
|
||||
"utils": "@/utils"
|
||||
},
|
||||
"iconLibrary": "lucide",
|
||||
"rsc": false,
|
||||
"style": "new-york",
|
||||
"tailwind": {
|
||||
"baseColor": "zinc",
|
||||
"config": "",
|
||||
"css": "src/styles/globals.css",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"tsx": true
|
||||
}
|
||||
@ -47,8 +47,16 @@
|
||||
"@dnd-kit/modifiers": "^9.0.0",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@radix-ui/react-dialog": "^1.1.15",
|
||||
"@radix-ui/react-popover": "^1.1.15",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@radix-ui/react-use-controllable-state": "^1.2.2",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.525.0"
|
||||
"cmdk": "^1.1.1",
|
||||
"lucide-react": "^0.545.0",
|
||||
"react-dropzone": "^14.3.8",
|
||||
"tailwind-merge": "^2.5.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@heroui/react": "^2.8.4",
|
||||
|
||||
@ -28,7 +28,7 @@ export const Tooltip = ({
|
||||
}}
|
||||
showArrow={showArrow ?? true}
|
||||
{...rest}>
|
||||
<div className={cn('relative z-10', classNames?.placeholder)}>{children}</div>
|
||||
<div className={cn('relative z-10 inline-block', classNames?.placeholder)}>{children}</div>
|
||||
</HeroUITooltip>
|
||||
)
|
||||
}
|
||||
|
||||
52
packages/ui/src/components/ui/button.tsx
Normal file
52
packages/ui/src/components/ui/button.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import { Slot } from '@radix-ui/react-slot'
|
||||
import { cva, type VariantProps } from 'class-variance-authority'
|
||||
import * as React from 'react'
|
||||
|
||||
import { cn } from '@/utils/index'
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
||||
destructive:
|
||||
'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
||||
outline:
|
||||
'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
|
||||
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||
ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
|
||||
link: 'text-primary underline-offset-4 hover:underline'
|
||||
},
|
||||
size: {
|
||||
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
|
||||
sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
|
||||
lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
|
||||
icon: 'size-9',
|
||||
'icon-sm': 'size-8',
|
||||
'icon-lg': 'size-10'
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
size: 'default'
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
function Button({
|
||||
className,
|
||||
variant,
|
||||
size,
|
||||
asChild = false,
|
||||
...props
|
||||
}: React.ComponentProps<'button'> &
|
||||
VariantProps<typeof buttonVariants> & {
|
||||
asChild?: boolean
|
||||
}) {
|
||||
const Comp = asChild ? Slot : 'button'
|
||||
|
||||
return <Comp data-slot="button" className={cn(buttonVariants({ variant, size, className }))} {...props} />
|
||||
}
|
||||
|
||||
export { Button, buttonVariants }
|
||||
135
packages/ui/src/components/ui/command.tsx
Normal file
135
packages/ui/src/components/ui/command.tsx
Normal file
@ -0,0 +1,135 @@
|
||||
import { Command as CommandPrimitive } from 'cmdk'
|
||||
import { SearchIcon } from 'lucide-react'
|
||||
import * as React from 'react'
|
||||
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
||||
import { cn } from '@/utils/index'
|
||||
|
||||
function Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>) {
|
||||
return (
|
||||
<CommandPrimitive
|
||||
data-slot="command"
|
||||
className={cn(
|
||||
'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandDialog({
|
||||
title = 'Command Palette',
|
||||
description = 'Search for a command to run...',
|
||||
children,
|
||||
className,
|
||||
showCloseButton = true,
|
||||
...props
|
||||
}: React.ComponentProps<typeof Dialog> & {
|
||||
title?: string
|
||||
description?: string
|
||||
className?: string
|
||||
showCloseButton?: boolean
|
||||
}) {
|
||||
return (
|
||||
<Dialog {...props}>
|
||||
<DialogHeader className="sr-only">
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
<DialogDescription>{description}</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogContent className={cn('overflow-hidden p-0', className)} showCloseButton={showCloseButton}>
|
||||
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
||||
{children}
|
||||
</Command>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandInput({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Input>) {
|
||||
return (
|
||||
<div data-slot="command-input-wrapper" className="flex h-9 items-center gap-2 border-b px-3">
|
||||
<SearchIcon className="size-4 shrink-0 opacity-50" />
|
||||
<CommandPrimitive.Input
|
||||
data-slot="command-input"
|
||||
className={cn(
|
||||
'placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>) {
|
||||
return (
|
||||
<CommandPrimitive.List
|
||||
data-slot="command-list"
|
||||
className={cn('max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandEmpty({ ...props }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
|
||||
return <CommandPrimitive.Empty data-slot="command-empty" className="py-6 text-center text-sm" {...props} />
|
||||
}
|
||||
|
||||
function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>) {
|
||||
return (
|
||||
<CommandPrimitive.Group
|
||||
data-slot="command-group"
|
||||
className={cn(
|
||||
'text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandSeparator({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
|
||||
return (
|
||||
<CommandPrimitive.Separator
|
||||
data-slot="command-separator"
|
||||
className={cn('bg-border -mx-1 h-px', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {
|
||||
return (
|
||||
<CommandPrimitive.Item
|
||||
data-slot="command-item"
|
||||
className={cn(
|
||||
"data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandShortcut({ className, ...props }: React.ComponentProps<'span'>) {
|
||||
return (
|
||||
<span
|
||||
data-slot="command-shortcut"
|
||||
className={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Command,
|
||||
CommandDialog,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
CommandShortcut
|
||||
}
|
||||
119
packages/ui/src/components/ui/dialog.tsx
Normal file
119
packages/ui/src/components/ui/dialog.tsx
Normal file
@ -0,0 +1,119 @@
|
||||
import * as DialogPrimitive from '@radix-ui/react-dialog'
|
||||
import { XIcon } from 'lucide-react'
|
||||
import * as React from 'react'
|
||||
|
||||
import { cn } from '@/utils/index'
|
||||
|
||||
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
||||
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
||||
}
|
||||
|
||||
function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
||||
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
||||
}
|
||||
|
||||
function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
||||
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
||||
}
|
||||
|
||||
function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
||||
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
|
||||
}
|
||||
|
||||
function DialogOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
||||
return (
|
||||
<DialogPrimitive.Overlay
|
||||
data-slot="dialog-overlay"
|
||||
className={cn(
|
||||
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogContent({
|
||||
className,
|
||||
children,
|
||||
showCloseButton = true,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
||||
showCloseButton?: boolean
|
||||
}) {
|
||||
return (
|
||||
<DialogPortal data-slot="dialog-portal">
|
||||
<DialogOverlay />
|
||||
<DialogPrimitive.Content
|
||||
data-slot="dialog-content"
|
||||
className={cn(
|
||||
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg',
|
||||
className
|
||||
)}
|
||||
{...props}>
|
||||
{children}
|
||||
{showCloseButton && (
|
||||
<DialogPrimitive.Close
|
||||
data-slot="dialog-close"
|
||||
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
|
||||
<XIcon />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
)}
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPortal>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="dialog-header"
|
||||
className={cn('flex flex-col gap-2 text-center sm:text-left', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="dialog-footer"
|
||||
className={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
||||
return (
|
||||
<DialogPrimitive.Title
|
||||
data-slot="dialog-title"
|
||||
className={cn('text-lg leading-none font-semibold', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
||||
return (
|
||||
<DialogPrimitive.Description
|
||||
data-slot="dialog-description"
|
||||
className={cn('text-muted-foreground text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogOverlay,
|
||||
DialogPortal,
|
||||
DialogTitle,
|
||||
DialogTrigger
|
||||
}
|
||||
42
packages/ui/src/components/ui/popover.tsx
Normal file
42
packages/ui/src/components/ui/popover.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
'use client'
|
||||
|
||||
import * as PopoverPrimitive from '@radix-ui/react-popover'
|
||||
import * as React from 'react'
|
||||
|
||||
import { cn } from '@/utils/index'
|
||||
|
||||
function Popover({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
||||
return <PopoverPrimitive.Root data-slot="popover" {...props} />
|
||||
}
|
||||
|
||||
function PopoverTrigger({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
||||
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
||||
}
|
||||
|
||||
function PopoverContent({
|
||||
className,
|
||||
align = 'center',
|
||||
sideOffset = 4,
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
||||
return (
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
data-slot="popover-content"
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</PopoverPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
function PopoverAnchor({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
||||
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
|
||||
}
|
||||
|
||||
export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger }
|
||||
179
packages/ui/src/components/ui/shadcn-io/dropzone/index.tsx
Normal file
179
packages/ui/src/components/ui/shadcn-io/dropzone/index.tsx
Normal file
@ -0,0 +1,179 @@
|
||||
'use client'
|
||||
|
||||
import { UploadIcon } from 'lucide-react'
|
||||
import type { ReactNode } from 'react'
|
||||
import { createContext, use } from 'react'
|
||||
import type { DropEvent, DropzoneOptions, FileRejection } from 'react-dropzone'
|
||||
import { useDropzone } from 'react-dropzone'
|
||||
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { cn } from '@/utils/index'
|
||||
|
||||
type DropzoneContextType = {
|
||||
src?: File[]
|
||||
accept?: DropzoneOptions['accept']
|
||||
maxSize?: DropzoneOptions['maxSize']
|
||||
minSize?: DropzoneOptions['minSize']
|
||||
maxFiles?: DropzoneOptions['maxFiles']
|
||||
}
|
||||
|
||||
const renderBytes = (bytes: number) => {
|
||||
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
|
||||
let size = bytes
|
||||
let unitIndex = 0
|
||||
|
||||
while (size >= 1024 && unitIndex < units.length - 1) {
|
||||
size /= 1024
|
||||
unitIndex++
|
||||
}
|
||||
|
||||
return `${size.toFixed(2)}${units[unitIndex]}`
|
||||
}
|
||||
|
||||
const DropzoneContext = createContext<DropzoneContextType | undefined>(undefined)
|
||||
|
||||
export type DropzoneProps = Omit<DropzoneOptions, 'onDrop'> & {
|
||||
src?: File[]
|
||||
className?: string
|
||||
onDrop?: (acceptedFiles: File[], fileRejections: FileRejection[], event: DropEvent) => void
|
||||
children?: ReactNode
|
||||
}
|
||||
|
||||
export const Dropzone = ({
|
||||
accept,
|
||||
maxFiles = 1,
|
||||
maxSize,
|
||||
minSize,
|
||||
onDrop,
|
||||
onError,
|
||||
disabled,
|
||||
src,
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: DropzoneProps) => {
|
||||
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
||||
accept,
|
||||
maxFiles,
|
||||
maxSize,
|
||||
minSize,
|
||||
onError,
|
||||
disabled,
|
||||
onDrop: (acceptedFiles, fileRejections, event) => {
|
||||
if (fileRejections.length > 0) {
|
||||
const message = fileRejections.at(0)?.errors.at(0)?.message
|
||||
onError?.(new Error(message))
|
||||
return
|
||||
}
|
||||
|
||||
onDrop?.(acceptedFiles, fileRejections, event)
|
||||
},
|
||||
...props
|
||||
})
|
||||
|
||||
return (
|
||||
<DropzoneContext key={JSON.stringify(src)} value={{ src, accept, maxSize, minSize, maxFiles }}>
|
||||
<Button
|
||||
className={cn(
|
||||
'relative h-auto w-full flex-col overflow-hidden p-8',
|
||||
isDragActive && 'outline-none ring-1 ring-ring',
|
||||
className
|
||||
)}
|
||||
disabled={disabled}
|
||||
type="button"
|
||||
variant="outline"
|
||||
{...getRootProps()}>
|
||||
<input {...getInputProps()} disabled={disabled} />
|
||||
{children}
|
||||
</Button>
|
||||
</DropzoneContext>
|
||||
)
|
||||
}
|
||||
|
||||
const useDropzoneContext = () => {
|
||||
const context = use(DropzoneContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error('useDropzoneContext must be used within a Dropzone')
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
export type DropzoneContentProps = {
|
||||
children?: ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
const maxLabelItems = 3
|
||||
|
||||
export const DropzoneContent = ({ children, className }: DropzoneContentProps) => {
|
||||
const { src } = useDropzoneContext()
|
||||
|
||||
if (!src) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (children) {
|
||||
return children
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn('flex flex-col items-center justify-center', className)}>
|
||||
<div className="flex size-8 items-center justify-center rounded-md bg-muted text-muted-foreground">
|
||||
<UploadIcon size={16} />
|
||||
</div>
|
||||
<p className="my-2 w-full truncate font-medium text-sm">
|
||||
{src.length > maxLabelItems
|
||||
? `${new Intl.ListFormat('en').format(
|
||||
src.slice(0, maxLabelItems).map((file) => file.name)
|
||||
)} and ${src.length - maxLabelItems} more`
|
||||
: new Intl.ListFormat('en').format(src.map((file) => file.name))}
|
||||
</p>
|
||||
<p className="w-full text-wrap text-muted-foreground text-xs">Drag and drop or click to replace</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export type DropzoneEmptyStateProps = {
|
||||
children?: ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const DropzoneEmptyState = ({ children, className }: DropzoneEmptyStateProps) => {
|
||||
const { src, accept, maxSize, minSize, maxFiles } = useDropzoneContext()
|
||||
|
||||
if (src) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (children) {
|
||||
return children
|
||||
}
|
||||
|
||||
let caption = ''
|
||||
|
||||
if (accept) {
|
||||
caption += 'Accepts '
|
||||
caption += new Intl.ListFormat('en').format(Object.keys(accept))
|
||||
}
|
||||
|
||||
if (minSize && maxSize) {
|
||||
caption += ` between ${renderBytes(minSize)} and ${renderBytes(maxSize)}`
|
||||
} else if (minSize) {
|
||||
caption += ` at least ${renderBytes(minSize)}`
|
||||
} else if (maxSize) {
|
||||
caption += ` less than ${renderBytes(maxSize)}`
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn('flex flex-col items-center justify-center', className)}>
|
||||
<div className="flex size-8 items-center justify-center rounded-md bg-muted text-muted-foreground">
|
||||
<UploadIcon size={16} />
|
||||
</div>
|
||||
<p className="my-2 w-full truncate text-wrap font-medium text-sm">Upload {maxFiles === 1 ? 'a file' : 'files'}</p>
|
||||
<p className="w-full truncate text-wrap text-muted-foreground text-xs">Drag and drop or click to upload</p>
|
||||
{caption && <p className="text-wrap text-muted-foreground text-xs">{caption}.</p>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
123
packages/ui/src/styles/globals.css
Normal file
123
packages/ui/src/styles/globals.css
Normal file
@ -0,0 +1,123 @@
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
:root {
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.205 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--destructive-foreground: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--radius: 0.625rem;
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.145 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.145 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.985 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.396 0.141 25.723);
|
||||
--destructive-foreground: oklch(0.637 0.237 25.331);
|
||||
--border: oklch(0.269 0 0);
|
||||
--input: oklch(0.269 0 0);
|
||||
--ring: oklch(0.439 0 0);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(0.269 0 0);
|
||||
--sidebar-ring: oklch(0.439 0 0);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-destructive-foreground: var(--destructive-foreground);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
@ -1 +1,10 @@
|
||||
export { cn } from '@heroui/react'
|
||||
import { type ClassValue, clsx } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
/**
|
||||
* Merge class names with tailwind-merge
|
||||
* This utility combines clsx and tailwind-merge for optimal class name handling
|
||||
*/
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
@ -7,14 +7,15 @@
|
||||
"incremental": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "react-jsx",
|
||||
"lib": ["DOM", "DOM.Iterable", "ES6"],
|
||||
"lib": ["DOM", "DOM.Iterable", "ES2021"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"outDir": "./dist",
|
||||
"paths": {
|
||||
"@types": ["src/types"],
|
||||
"@utils": ["src/utils"]
|
||||
"@/*": ["src/*"],
|
||||
"@/types": ["src/types"],
|
||||
"@/utils": ["src/utils"]
|
||||
},
|
||||
"resolveJsonModule": true,
|
||||
"rootDir": ".",
|
||||
|
||||
156
yarn.lock
156
yarn.lock
@ -2781,6 +2781,10 @@ __metadata:
|
||||
"@dnd-kit/sortable": "npm:^10.0.0"
|
||||
"@dnd-kit/utilities": "npm:^3.2.2"
|
||||
"@heroui/react": "npm:^2.8.4"
|
||||
"@radix-ui/react-dialog": "npm:^1.1.15"
|
||||
"@radix-ui/react-popover": "npm:^1.1.15"
|
||||
"@radix-ui/react-slot": "npm:^1.2.3"
|
||||
"@radix-ui/react-use-controllable-state": "npm:^1.2.2"
|
||||
"@storybook/addon-docs": "npm:^9.1.6"
|
||||
"@storybook/addon-themes": "npm:^9.1.6"
|
||||
"@storybook/react-vite": "npm:^9.1.6"
|
||||
@ -2791,15 +2795,19 @@ __metadata:
|
||||
"@uiw/codemirror-themes-all": "npm:^4.25.1"
|
||||
"@uiw/react-codemirror": "npm:^4.25.1"
|
||||
antd: "npm:^5.22.5"
|
||||
class-variance-authority: "npm:^0.7.1"
|
||||
clsx: "npm:^2.1.1"
|
||||
cmdk: "npm:^1.1.1"
|
||||
eslint-plugin-storybook: "npm:9.1.6"
|
||||
framer-motion: "npm:^12.23.12"
|
||||
linguist-languages: "npm:^9.0.0"
|
||||
lucide-react: "npm:^0.525.0"
|
||||
lucide-react: "npm:^0.545.0"
|
||||
react: "npm:^19.0.0"
|
||||
react-dom: "npm:^19.0.0"
|
||||
react-dropzone: "npm:^14.3.8"
|
||||
storybook: "npm:^9.1.6"
|
||||
styled-components: "npm:^6.1.15"
|
||||
tailwind-merge: "npm:^2.5.5"
|
||||
tsdown: "npm:^0.15.5"
|
||||
tsx: "npm:^4.20.5"
|
||||
typescript: "npm:^5.6.2"
|
||||
@ -8819,7 +8827,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-compose-refs@npm:1.1.2":
|
||||
"@radix-ui/react-compose-refs@npm:1.1.2, @radix-ui/react-compose-refs@npm:^1.1.1":
|
||||
version: 1.1.2
|
||||
resolution: "@radix-ui/react-compose-refs@npm:1.1.2"
|
||||
peerDependencies:
|
||||
@ -8869,6 +8877,38 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-dialog@npm:^1.1.15, @radix-ui/react-dialog@npm:^1.1.6":
|
||||
version: 1.1.15
|
||||
resolution: "@radix-ui/react-dialog@npm:1.1.15"
|
||||
dependencies:
|
||||
"@radix-ui/primitive": "npm:1.1.3"
|
||||
"@radix-ui/react-compose-refs": "npm:1.1.2"
|
||||
"@radix-ui/react-context": "npm:1.1.2"
|
||||
"@radix-ui/react-dismissable-layer": "npm:1.1.11"
|
||||
"@radix-ui/react-focus-guards": "npm:1.1.3"
|
||||
"@radix-ui/react-focus-scope": "npm:1.1.7"
|
||||
"@radix-ui/react-id": "npm:1.1.1"
|
||||
"@radix-ui/react-portal": "npm:1.1.9"
|
||||
"@radix-ui/react-presence": "npm:1.1.5"
|
||||
"@radix-ui/react-primitive": "npm:2.1.3"
|
||||
"@radix-ui/react-slot": "npm:1.2.3"
|
||||
"@radix-ui/react-use-controllable-state": "npm:1.2.2"
|
||||
aria-hidden: "npm:^1.2.4"
|
||||
react-remove-scroll: "npm:^2.6.3"
|
||||
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
|
||||
checksum: 10c0/2f2c88e3c281acaea2fd9b96fa82132d59177d3aa5da2e7c045596fd4028e84e44ac52ac28f4f236910605dd7d9338c2858ba44a9ced2af2e3e523abbfd33014
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-direction@npm:1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "@radix-ui/react-direction@npm:1.1.1"
|
||||
@ -8939,7 +8979,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-id@npm:1.1.1":
|
||||
"@radix-ui/react-id@npm:1.1.1, @radix-ui/react-id@npm:^1.1.0":
|
||||
version: 1.1.1
|
||||
resolution: "@radix-ui/react-id@npm:1.1.1"
|
||||
dependencies:
|
||||
@ -8990,6 +9030,39 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-popover@npm:^1.1.15":
|
||||
version: 1.1.15
|
||||
resolution: "@radix-ui/react-popover@npm:1.1.15"
|
||||
dependencies:
|
||||
"@radix-ui/primitive": "npm:1.1.3"
|
||||
"@radix-ui/react-compose-refs": "npm:1.1.2"
|
||||
"@radix-ui/react-context": "npm:1.1.2"
|
||||
"@radix-ui/react-dismissable-layer": "npm:1.1.11"
|
||||
"@radix-ui/react-focus-guards": "npm:1.1.3"
|
||||
"@radix-ui/react-focus-scope": "npm:1.1.7"
|
||||
"@radix-ui/react-id": "npm:1.1.1"
|
||||
"@radix-ui/react-popper": "npm:1.2.8"
|
||||
"@radix-ui/react-portal": "npm:1.1.9"
|
||||
"@radix-ui/react-presence": "npm:1.1.5"
|
||||
"@radix-ui/react-primitive": "npm:2.1.3"
|
||||
"@radix-ui/react-slot": "npm:1.2.3"
|
||||
"@radix-ui/react-use-controllable-state": "npm:1.2.2"
|
||||
aria-hidden: "npm:^1.2.4"
|
||||
react-remove-scroll: "npm:^2.6.3"
|
||||
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
|
||||
checksum: 10c0/c1c76b5e5985b128d03b621424fb453f769931d497759a1977734d303007da9f970570cf3ea1f6968ab609ab4a97f384168bff056197bd2d3d422abea0e3614b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-popper@npm:1.2.8":
|
||||
version: 1.2.8
|
||||
resolution: "@radix-ui/react-popper@npm:1.2.8"
|
||||
@ -9058,7 +9131,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-primitive@npm:2.1.3":
|
||||
"@radix-ui/react-primitive@npm:2.1.3, @radix-ui/react-primitive@npm:^2.0.2":
|
||||
version: 2.1.3
|
||||
resolution: "@radix-ui/react-primitive@npm:2.1.3"
|
||||
dependencies:
|
||||
@ -9104,7 +9177,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-slot@npm:1.2.3":
|
||||
"@radix-ui/react-slot@npm:1.2.3, @radix-ui/react-slot@npm:^1.2.3":
|
||||
version: 1.2.3
|
||||
resolution: "@radix-ui/react-slot@npm:1.2.3"
|
||||
dependencies:
|
||||
@ -9132,7 +9205,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-use-controllable-state@npm:1.2.2":
|
||||
"@radix-ui/react-use-controllable-state@npm:1.2.2, @radix-ui/react-use-controllable-state@npm:^1.2.2":
|
||||
version: 1.2.2
|
||||
resolution: "@radix-ui/react-use-controllable-state@npm:1.2.2"
|
||||
dependencies:
|
||||
@ -16467,6 +16540,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"attr-accept@npm:^2.2.4":
|
||||
version: 2.2.5
|
||||
resolution: "attr-accept@npm:2.2.5"
|
||||
checksum: 10c0/9b4cb82213925cab2d568f71b3f1c7a7778f9192829aac39a281e5418cd00c04a88f873eb89f187e0bf786fa34f8d52936f178e62cbefb9254d57ecd88ada99b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"aws4fetch@npm:^1.0.20":
|
||||
version: 1.0.20
|
||||
resolution: "aws4fetch@npm:1.0.20"
|
||||
@ -17297,6 +17377,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"class-variance-authority@npm:^0.7.1":
|
||||
version: 0.7.1
|
||||
resolution: "class-variance-authority@npm:0.7.1"
|
||||
dependencies:
|
||||
clsx: "npm:^2.1.1"
|
||||
checksum: 10c0/0f438cea22131808b99272de0fa933c2532d5659773bfec0c583de7b3f038378996d3350683426b8e9c74a6286699382106d71fbec52f0dd5fbb191792cccb5b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"classcat@npm:^5.0.3":
|
||||
version: 5.0.5
|
||||
resolution: "classcat@npm:5.0.5"
|
||||
@ -17420,6 +17509,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cmdk@npm:^1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "cmdk@npm:1.1.1"
|
||||
dependencies:
|
||||
"@radix-ui/react-compose-refs": "npm:^1.1.1"
|
||||
"@radix-ui/react-dialog": "npm:^1.1.6"
|
||||
"@radix-ui/react-id": "npm:^1.1.0"
|
||||
"@radix-ui/react-primitive": "npm:^2.0.2"
|
||||
peerDependencies:
|
||||
react: ^18 || ^19 || ^19.0.0-rc
|
||||
react-dom: ^18 || ^19 || ^19.0.0-rc
|
||||
checksum: 10c0/5605ac4396ec9bc65c82f954da19dd89a0636a54026df72780e2470da1381f9d57434a80a53f2d57eaa4e759660a3ebba9232b74258dc09970576591eae03116
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"code-inspector-core@npm:0.20.14":
|
||||
version: 0.20.14
|
||||
resolution: "code-inspector-core@npm:0.20.14"
|
||||
@ -20578,6 +20682,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"file-selector@npm:^2.1.0":
|
||||
version: 2.1.2
|
||||
resolution: "file-selector@npm:2.1.2"
|
||||
dependencies:
|
||||
tslib: "npm:^2.7.0"
|
||||
checksum: 10c0/fe827e0e95410aacfcc3eabc38c29cc36055257f03c1c06b631a2b5af9730c142ad2c52f5d64724d02231709617bda984701f52bd1f4b7aca50fb6585a27c1d2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"file-stream-rotator@npm:0.6.1":
|
||||
version: 0.6.1
|
||||
resolution: "file-stream-rotator@npm:0.6.1"
|
||||
@ -23600,6 +23713,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lucide-react@npm:^0.545.0":
|
||||
version: 0.545.0
|
||||
resolution: "lucide-react@npm:0.545.0"
|
||||
peerDependencies:
|
||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
checksum: 10c0/942622c8e5d113e6fc6f66407703dc06474cf1a36ee9998b9f562f2e64737ea098c0db5a4e5ba2a8eb14abecb9da05be4584e9400c4a192ba5b2781f21928c21
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lz-string@npm:^1.5.0":
|
||||
version: 1.5.0
|
||||
resolution: "lz-string@npm:1.5.0"
|
||||
@ -27697,6 +27819,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-dropzone@npm:^14.3.8":
|
||||
version: 14.3.8
|
||||
resolution: "react-dropzone@npm:14.3.8"
|
||||
dependencies:
|
||||
attr-accept: "npm:^2.2.4"
|
||||
file-selector: "npm:^2.1.0"
|
||||
prop-types: "npm:^15.8.1"
|
||||
peerDependencies:
|
||||
react: ">= 16.8 || 18.0.0"
|
||||
checksum: 10c0/e17b1832783cda7b8824fe9370e99185d1abbdd5e4980b2985d6321c5768c8de18ff7b9ad550c809ee9743269dea608ff74d5208062754ce8377ad022897b278
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-error-boundary@npm:^6.0.0":
|
||||
version: 6.0.0
|
||||
resolution: "react-error-boundary@npm:6.0.0"
|
||||
@ -30066,6 +30201,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tailwind-merge@npm:^2.5.5":
|
||||
version: 2.6.0
|
||||
resolution: "tailwind-merge@npm:2.6.0"
|
||||
checksum: 10c0/fc8a5535524de9f4dacf1c16ab298581c7bb757d68a95faaf28942b1c555a619bba9d4c6726fe83986e44973b315410c1a5226e5354c30ba82353bd6d2288fa5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tailwind-variants@npm:3.1.0":
|
||||
version: 3.1.0
|
||||
resolution: "tailwind-variants@npm:3.1.0"
|
||||
@ -30776,7 +30918,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.8.0":
|
||||
"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.7.0, tslib@npm:^2.8.0":
|
||||
version: 2.8.1
|
||||
resolution: "tslib@npm:2.8.1"
|
||||
checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
|
||||
|
||||
Loading…
Reference in New Issue
Block a user