remove unused stuff

This commit is contained in:
Jonathan Summers-Muir committed 2023-07-13 14:50:45 +08:00
1 parent 9e20c4d6a6
commit ff5037cf5b
19 files changed
-2149

No files matched your search

@@ -1,48 +0,0 @@
import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { VariantProps, cva } from 'class-variance-authority'
import { cn } from '@ui/lib/utils'
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: 'border border-input hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'underline-offset-4 hover:underline text-primary',
},
size: {
default: 'h-10 py-2 px-4',
sm: 'h-9 px-3 rounded-md',
lg: 'h-11 px-8 rounded-md',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : 'button'
return (
<Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
)
}
)
Button.displayName = 'Button'
export { Button, buttonVariants }
@@ -1,57 +0,0 @@
'use client'
import * as React from 'react'
import { ChevronLeft, ChevronRight } from 'lucide-react'
import { DayPicker } from 'react-day-picker'
import { cn } from '@ui/lib/utils'
import { buttonVariants } from '@ui/components/shadcn/button'
export type CalendarProps = React.ComponentProps<typeof DayPicker>
function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn('p-3', className)}
classNames={{
months: 'flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0',
month: 'space-y-4',
caption: 'flex justify-center pt-1 relative items-center',
caption_label: 'text-sm font-medium',
nav: 'space-x-1 flex items-center',
nav_button: cn(
buttonVariants({ variant: 'outline' }),
'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100'
),
nav_button_previous: 'absolute left-1',
nav_button_next: 'absolute right-1',
table: 'w-full border-collapse space-y-1',
head_row: 'flex',
head_cell: 'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]',
row: 'flex w-full mt-2',
cell: 'text-center text-sm p-0 relative [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20',
day: cn(
buttonVariants({ variant: 'ghost' }),
'h-9 w-9 p-0 font-normal aria-selected:opacity-100'
),
day_selected:
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
day_today: 'bg-accent text-accent-foreground',
day_outside: 'text-muted-foreground opacity-50',
day_disabled: 'text-muted-foreground opacity-50',
day_range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground',
day_hidden: 'invisible',
...classNames,
}}
components={{
IconLeft: ({ ...props }) => <ChevronLeft className="h-4 w-4" />,
IconRight: ({ ...props }) => <ChevronRight className="h-4 w-4" />,
}}
{...props}
/>
)
}
Calendar.displayName = 'Calendar'
export { Calendar }
@@ -1,145 +0,0 @@
'use client'
import * as React from 'react'
import { DialogProps } from '@radix-ui/react-dialog'
import { Command as CommandPrimitive } from 'cmdk-supabase'
import { Search } from 'lucide-react'
import { cn } from '@ui/lib/utils'
import { Dialog, DialogContent } from '@ui/components/shadcn/dialog'
const Command = React.forwardRef<
React.ElementRef<typeof CommandPrimitive>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
>(({ className, ...props }, ref) => (
<CommandPrimitive
ref={ref}
className={cn(
'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
className
)}
{...props}
/>
))
Command.displayName = CommandPrimitive.displayName
interface CommandDialogProps extends DialogProps {}
const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
return (
<Dialog {...props}>
<DialogContent className="overflow-hidden p-0 shadow-2xl">
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[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>
)
}
const CommandInput = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Input>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
>(({ className, ...props }, ref) => (
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
ref={ref}
className={cn(
'placeholder:text-foreground-muted flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50',
className
)}
{...props}
/>
</div>
))
CommandInput.displayName = CommandPrimitive.Input.displayName
const CommandList = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.List>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
>(({ className, ...props }, ref) => (
<CommandPrimitive.List
ref={ref}
className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}
{...props}
/>
))
CommandList.displayName = CommandPrimitive.List.displayName
const CommandEmpty = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Empty>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
>((props, ref) => (
<CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />
))
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
const CommandGroup = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Group>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Group
ref={ref}
className={cn(
'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',
className
)}
{...props}
/>
))
CommandGroup.displayName = CommandPrimitive.Group.displayName
const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Separator
ref={ref}
className={cn('-mx-1 h-px bg-border', className)}
{...props}
/>
))
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
const CommandItem = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Item
ref={ref}
className={cn(
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className
)}
{...props}
/>
))
CommandItem.displayName = CommandPrimitive.Item.displayName
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
return (
<span
className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}
{...props}
/>
)
}
CommandShortcut.displayName = 'CommandShortcut'
export {
Command,
CommandDialog,
CommandInput,
CommandList,
CommandEmpty,
CommandGroup,
CommandItem,
CommandShortcut,
CommandSeparator,
}
@@ -1,106 +0,0 @@
'use client'
import * as React from 'react'
import * as DialogPrimitive from '@radix-ui/react-dialog'
import { X } from 'lucide-react'
import { cn } from '@ui/lib/utils'
const Dialog = DialogPrimitive.Root
const DialogTrigger = DialogPrimitive.Trigger
const DialogPortal = ({ className, children, ...props }: DialogPrimitive.DialogPortalProps) => (
<DialogPrimitive.Portal className={cn(className)} {...props}>
<div className="fixed inset-0 z-50 flex items-start justify-center sm:items-center">
{children}
</div>
</DialogPrimitive.Portal>
)
DialogPortal.displayName = DialogPrimitive.Portal.displayName
const DialogOverlay = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Overlay
ref={ref}
className={cn(
'fixed inset-0 z-50 bg-background/80 backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in',
className
)}
{...props}
/>
))
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<DialogPortal>
<DialogOverlay />
<DialogPrimitive.Content
ref={ref}
className={cn(
'fixed z-50 grid w-full gap-4 rounded-b-lg border bg-background p-6 shadow-lg animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0',
className
)}
{...props}
>
{children}
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogPortal>
))
DialogContent.displayName = DialogPrimitive.Content.displayName
const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
<div className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)} {...props} />
)
DialogHeader.displayName = 'DialogHeader'
const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}
{...props}
/>
)
DialogFooter.displayName = 'DialogFooter'
const DialogTitle = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Title
ref={ref}
className={cn('text-lg font-semibold leading-none tracking-tight', className)}
{...props}
/>
))
DialogTitle.displayName = DialogPrimitive.Title.displayName
const DialogDescription = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description
ref={ref}
className={cn('text-sm text-muted-foreground', className)}
{...props}
/>
))
DialogDescription.displayName = DialogPrimitive.Description.displayName
export {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
}
-170
View File
@@ -1,170 +0,0 @@
import * as React from 'react'
import * as LabelPrimitive from '@radix-ui/react-label'
import { Slot } from '@radix-ui/react-slot'
import {
Controller,
ControllerProps,
FieldPath,
FieldValues,
FormProvider,
useFormContext,
} from 'react-hook-form'
import { cn } from '@ui/lib/utils'
import { Label } from '@ui/components/shadcn/label'
import { useId } from '@radix-ui/react-id'
const Form = FormProvider
type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> = {
name: TName
}
const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue)
const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
>({
...props
}: ControllerProps<TFieldValues, TName>) => {
return (
<FormFieldContext.Provider value={{ name: props.name }}>
<Controller {...props} />
</FormFieldContext.Provider>
)
}
const useFormField = () => {
const fieldContext = React.useContext(FormFieldContext)
const itemContext = React.useContext(FormItemContext)
const { getFieldState, formState } = useFormContext()
const fieldState = getFieldState(fieldContext.name, formState)
if (!fieldContext) {
throw new Error('useFormField should be used within <FormField>')
}
const { id } = itemContext
return {
id,
name: fieldContext.name,
formItemId: `${id}-form-item`,
formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`,
...fieldState,
}
}
type FormItemContextValue = {
id: string
}
const FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue)
const FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => {
// const id = React.useId()
const id = useId()
console.log('id', id)
return (
<FormItemContext.Provider value={{ id }}>
<div ref={ref} className={cn('space-y-2', className)} {...props} />
</FormItemContext.Provider>
)
}
)
FormItem.displayName = 'FormItem'
const FormLabel = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
>(({ className, ...props }, ref) => {
const { error, formItemId } = useFormField()
return (
<Label
ref={ref}
className={cn(error && 'text-destructive', className)}
htmlFor={formItemId}
{...props}
/>
)
})
FormLabel.displayName = 'FormLabel'
const FormControl = React.forwardRef<
React.ElementRef<typeof Slot>,
React.ComponentPropsWithoutRef<typeof Slot>
>(({ ...props }, ref) => {
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
return (
<Slot
ref={ref}
id={formItemId}
aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}
aria-invalid={!!error}
{...props}
/>
)
})
FormControl.displayName = 'FormControl'
const FormDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => {
const { formDescriptionId } = useFormField()
return (
<p
ref={ref}
id={formDescriptionId}
className={cn('text-sm text-muted-foreground', className)}
{...props}
/>
)
})
FormDescription.displayName = 'FormDescription'
const FormMessage = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, children, ...props }, ref) => {
const { error, formMessageId } = useFormField()
const body = error ? String(error?.message) : children
if (!body) {
return null
}
return (
<p
ref={ref}
id={formMessageId}
className={cn('text-sm font-medium text-red-900', className)}
{...props}
>
{body}
</p>
)
})
FormMessage.displayName = 'FormMessage'
export {
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
}
@@ -1,24 +0,0 @@
import * as React from 'react'
import { cn } from '@ui/lib/utils'
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
'flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className
)}
ref={ref}
{...props}
/>
)
}
)
Input.displayName = 'Input'
export { Input }
@@ -1,19 +0,0 @@
import * as React from 'react'
import * as LabelPrimitive from '@radix-ui/react-label'
import { VariantProps, cva } from 'class-variance-authority'
import { cn } from '@ui/lib/utils'
const labelVariants = cva(
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
)
const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />
))
Label.displayName = LabelPrimitive.Root.displayName
export { Label }
@@ -1,29 +0,0 @@
import * as React from 'react'
import * as PopoverPrimitive from '@radix-ui/react-popover'
import { cn } from '@ui/lib/utils'
const Popover = PopoverPrimitive.Root
const PopoverTrigger = PopoverPrimitive.Trigger
const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none animate-in 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',
className
)}
{...props}
/>
</PopoverPrimitive.Portal>
))
PopoverContent.displayName = PopoverPrimitive.Content.displayName
export { Popover, PopoverTrigger, PopoverContent }
@@ -1,118 +0,0 @@
import * as React from 'react'
import * as SelectPrimitive from '@radix-ui/react-select'
import { Check, ChevronDown } from 'lucide-react'
import { cn } from '@ui/lib/utils'
const Select = SelectPrimitive.Root
const SelectGroup = SelectPrimitive.Group
const SelectValue = SelectPrimitive.Value
const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
className={cn(
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className
)}
{...props}
>
{children}
<SelectPrimitive.Icon asChild>
<ChevronDown className="h-4 w-4 opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
))
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = 'popper', ...props }, ref) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
className={cn(
'relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md animate-in fade-in-80',
position === 'popper' && 'translate-y-1',
className
)}
position={position}
{...props}
>
<SelectPrimitive.Viewport
className={cn(
'p-1',
position === 'popper' &&
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'
)}
>
{children}
</SelectPrimitive.Viewport>
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
))
SelectContent.displayName = SelectPrimitive.Content.displayName
const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Label
ref={ref}
className={cn('py-1.5 pl-8 pr-2 text-sm font-semibold', className)}
{...props}
/>
))
SelectLabel.displayName = SelectPrimitive.Label.displayName
const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Item
ref={ref}
className={cn(
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
))
SelectItem.displayName = SelectPrimitive.Item.displayName
const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
className={cn('-mx-1 my-1 h-px bg-muted', className)}
{...props}
/>
))
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
export {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
}
-122
View File
@@ -1,122 +0,0 @@
import * as React from 'react'
import * as ToastPrimitives from '@radix-ui/react-toast'
import { VariantProps, cva } from 'class-variance-authority'
import { X } from 'lucide-react'
import { cn } from '@ui/lib/utils'
const ToastProvider = ToastPrimitives.Provider
const ToastViewport = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Viewport>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Viewport
ref={ref}
className={cn(
'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]',
className
)}
{...props}
/>
))
ToastViewport.displayName = ToastPrimitives.Viewport.displayName
const toastVariants = cva(
'data-[swipe=move]:transition-none group relative pointer-events-auto flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full data-[state=closed]:slide-out-to-right-full',
{
variants: {
variant: {
default: 'bg-background border',
destructive:
'group destructive border-destructive bg-destructive text-destructive-foreground',
},
},
defaultVariants: {
variant: 'default',
},
}
)
const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants>
>(({ className, variant, ...props }, ref) => {
return (
<ToastPrimitives.Root
ref={ref}
className={cn(toastVariants({ variant }), className)}
{...props}
/>
)
})
Toast.displayName = ToastPrimitives.Root.displayName
const ToastAction = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Action>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Action
ref={ref}
className={cn(
'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-destructive/30 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive',
className
)}
{...props}
/>
))
ToastAction.displayName = ToastPrimitives.Action.displayName
const ToastClose = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Close>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Close
ref={ref}
className={cn(
'absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600',
className
)}
toast-close=""
{...props}
>
<X className="h-4 w-4" />
</ToastPrimitives.Close>
))
ToastClose.displayName = ToastPrimitives.Close.displayName
const ToastTitle = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Title>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Title ref={ref} className={cn('text-sm font-semibold', className)} {...props} />
))
ToastTitle.displayName = ToastPrimitives.Title.displayName
const ToastDescription = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Description>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Description
ref={ref}
className={cn('text-sm opacity-90', className)}
{...props}
/>
))
ToastDescription.displayName = ToastPrimitives.Description.displayName
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>
type ToastActionElement = React.ReactElement<typeof ToastAction>
export {
type ToastProps,
type ToastActionElement,
ToastProvider,
ToastViewport,
Toast,
ToastTitle,
ToastDescription,
ToastClose,
ToastAction,
}
@@ -1,79 +0,0 @@
// Button.stories.ts|tsx
import type { Meta, StoryObj } from '@storybook/react'
import { Accordion, AccordionItem } from './Accordion'
import { Badge } from '../../../Badge'
const meta: Meta<typeof Accordion> = {
/* 👇 The title prop is optional.
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
* to learn how to generate automatic titles
*/
title: 'General/Accordion',
component: Accordion,
}
export default meta
type Story = StoryObj<typeof Accordion>
/*
*👇 Render functions are a framework specific feature to allow you control on how the component renders.
* See https://storybook.js.org/docs/react/api/csf
* to learn how to use render functions.
*/
export const Default = {
args: {
type: 'default',
},
render: ({ children, type }: any) => (
<Accordion type={type} openBehaviour="single" collapsible className="w-full">
<Accordion.Item value="item-1">
<Accordion.Trigger>
<span className="text-scale-900 group-hover:text-scale-1200">Title of the thing</span>
</Accordion.Trigger>
<Accordion.Content>Yes. It adheres to the WAI-ARIA design pattern.</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="item-2">
<Accordion.Trigger>Is it styled?</Accordion.Trigger>
<Accordion.Content>
Yes. It comes with default styles that matches the other components' aesthetic.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="item-3">
<Accordion.Trigger>Is it animated?</Accordion.Trigger>
<Accordion.Content>
Yes. It's animated by default, but you can disable it if you prefer.
</Accordion.Content>
</Accordion.Item>
</Accordion>
),
}
export const Bordered = {
args: {
type: 'bordered',
},
render: ({ children, type }: any) => (
<Accordion type={type} openBehaviour="single" collapsible className="w-full">
<Accordion.Item value="item-1">
<Accordion.Trigger>Is it accessible?</Accordion.Trigger>
<Accordion.Content>Yes. It adheres to the WAI-ARIA design pattern.</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="item-2">
<Accordion.Trigger>Is it styled?</Accordion.Trigger>
<Accordion.Content>
Yes. It comes with default styles that matches the other components' aesthetic.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="item-3">
<Accordion.Trigger>Is it animated?</Accordion.Trigger>
<Accordion.Content>
Yes. It's animated by default, but you can disable it if you prefer.
</Accordion.Content>
</Accordion.Item>
</Accordion>
),
}
@@ -1,235 +0,0 @@
import * as AccordionPrimitive from '@radix-ui/react-accordion'
import { cn } from './../../lib/utils'
import { VariantProps, cva, cx } from 'class-variance-authority'
import { ChevronDown } from 'lucide-react'
import React, { createContext, useContext, useState } from 'react'
export type AccordionRootVariantsProps = VariantProps<typeof accordionRootVariants>
const accordionRootVariants = cva('flex flex-col', {
variants: {
type: {
default: 'space-y-3',
bordered: '-space-y-px',
},
defaultVariants: {
type: 'default',
},
},
})
export type AccordionItemVariantsProps = VariantProps<typeof accordionItemVariants>
const accordionItemVariants = cva(
'group first:rounded-tl-md first:rounded-tr-md last:rounded-bl-md last:rounded-br-md',
{
variants: {
type: {
default: 'overflow-hidden',
bordered: 'border border-scale-700',
},
justified: {
true: 'justify-between',
false: '',
},
},
}
)
const accordionTriggerVariants = cva(
`flex flex-row items-center w-full text-left cursor-pointer focus-visible:ring-1 focus-visible:z-10 ring-scale-1100
justify-between transition-all hover:underline [&[data-state=open]>svg]:rotate-180`,
{
variants: {
type: {
default: 'gap-3',
bordered: `
px-6 py-4
font-medium text-base bg-transparent
transition-colors hover:bg-scale-200
overflow-hidden
group-first:rounded-tl-md group-first:rounded-tr-md
group-last:rounded-bl-md group-last:rounded-br-md`,
},
},
}
)
const accordionContentVariants = cva('pb-4 pt-0', {
variants: {
type: {
default: '',
bordered: 'px-6',
},
},
})
type Type = AccordionRootVariantsProps['type']
type Align = 'left' | 'right' | undefined
interface ContextValue {
chevronAlign: Align
justified: boolean
type: Type
defaultValue: AccordionPrimitive.AccordionImplSingleProps['defaultValue']
}
interface AdditionalProps {
openBehaviour: 'single' | 'multiple'
variant?: Type
// Add other additional props here
onChange?: (item: string | string[]) => void
type?: Type
justified?: AccordionItemVariantsProps['justified']
chevronAlign?: Align
}
interface AccordionComponent
extends React.ForwardRefExoticComponent<
ExtendedAccordionProps & React.RefAttributes<HTMLDivElement>
> {
Item: typeof AccordionItem
Content: typeof AccordionContent
Trigger: typeof AccordionTrigger
}
export interface AccordionSingleProps extends AccordionPrimitive.AccordionImplSingleProps {
openBehaviour: 'single'
value?: string
// Add other props specific to single accordion
}
export interface AccordionMultipleProps extends AccordionPrimitive.AccordionImplMultipleProps {
openBehaviour: 'multiple'
value?: string[]
// Add other props specific to multiple accordion
}
type ExtendedAccordionProps = (AccordionSingleProps | AccordionMultipleProps) & AdditionalProps
const AccordionContext = createContext<ContextValue>({
chevronAlign: 'left',
justified: false, // Set the default value to false
type: undefined,
defaultValue: undefined,
})
const Accordion: AccordionComponent = React.forwardRef(
({ openBehaviour, type, chevronAlign, justified, defaultValue, ...props }, ref) => {
function handleOnChange(e: string | string[]) {
if (props.onChange) props.onChange(e)
}
const contextValue = {
chevronAlign,
justified: justified || false, // Provide a default value of false
type: type || 'default', // Provide a default value for the type
defaultValue: Array.isArray(defaultValue) ? defaultValue.join('') : defaultValue, // Convert array to string
}
if (openBehaviour === 'single') {
const { value, children, className, ...singleProps } = props as AccordionSingleProps
return (
<AccordionPrimitive.Root
ref={ref}
type="single"
onValueChange={handleOnChange}
value={value}
defaultValue={defaultValue}
className={cn(accordionRootVariants({ type }), className)}
children={
<AccordionContext.Provider value={{ ...contextValue }}>
{children}
</AccordionContext.Provider>
}
{...singleProps}
/>
)
} else {
const { value, children, className, ...multipleProps } = props as AccordionMultipleProps
return (
<AccordionPrimitive.Root
ref={ref}
type="multiple"
onValueChange={handleOnChange}
value={value}
className={cn(accordionRootVariants({ type }), className)}
children={
<AccordionContext.Provider value={{ ...contextValue }}>
<div>{props.children}</div>
</AccordionContext.Provider>
}
{...multipleProps}
/>
)
}
}
) as AccordionComponent
export interface ItemAdditionalProps
extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> {}
export const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => {
const [open, setOpen] = useState(false)
let { type, justified } = useContext(AccordionContext)
return (
<AccordionPrimitive.Item
ref={ref}
className={cn(accordionItemVariants({ type, justified }), className)}
onClick={() => {
setOpen(!open)
}}
{...props}
/>
)
})
AccordionItem.displayName = AccordionPrimitive.Item.displayName
export const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => {
const { type } = useContext(AccordionContext)
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(accordionTriggerVariants({ type }), className)}
{...props}
>
{children}
<ChevronDown className="h-4 w-4 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
)
})
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
export const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => {
const { type } = useContext(AccordionContext)
return (
<AccordionPrimitive.Content
ref={ref}
className={cn(
'overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',
className
)}
{...props}
>
<div className={cx(accordionContentVariants({ type }))}>{children}</div>
</AccordionPrimitive.Content>
)
})
AccordionContent.displayName = AccordionPrimitive.Content.displayName
Accordion.Item = AccordionItem
Accordion.Content = AccordionContent
Accordion.Trigger = AccordionTrigger
export { Accordion }
@@ -1,92 +0,0 @@
// Button.stories.ts|tsx
import type { Meta, StoryObj } from '@storybook/react'
import { Alert, AlertProps } from './Alert'
import { IconAirplay } from '../Icon/icons/IconAirplay'
import { Terminal } from 'lucide-react'
const meta: Meta<typeof Alert> = {
/* 👇 The title prop is optional.
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
* to learn how to generate automatic titles
*/
title: 'General/Alert',
component: Alert,
}
export default meta
type Story = StoryObj<typeof Alert>
/*
*👇 Render functions are a framework specific feature to allow you control on how the component renders.
* See https://storybook.js.org/docs/react/api/csf
* to learn how to use render functions.
*/
export const Info = {
args: {
variant: 'info',
withIcon: true,
},
render: ({ withIcon, variant }: AlertProps) => (
<Alert variant={variant} withIcon={withIcon}>
<Alert.Title>Info Alert</Alert.Title>
<Alert.Description>This is an informative message for your application.</Alert.Description>
</Alert>
),
}
export const Danger = {
args: {
variant: 'danger',
withIcon: true,
},
render: ({ withIcon, variant }: AlertProps) => (
<Alert variant={variant} withIcon={withIcon}>
<Alert.Title>Danger Alert</Alert.Title>
<Alert.Description>This is a dangerous warning for your application.</Alert.Description>
</Alert>
),
}
export const Warning = {
args: {
variant: 'warning',
withIcon: true,
},
render: ({ withIcon, variant }: AlertProps) => (
<Alert variant={variant} withIcon={withIcon}>
<Alert.Title>Warning Alert</Alert.Title>
<Alert.Description>This is a warning message for your application.</Alert.Description>
</Alert>
),
}
export const Success = {
args: {
variant: 'success',
withIcon: true,
},
render: ({ withIcon, variant }: AlertProps) => (
<Alert variant={variant} withIcon={withIcon}>
<Alert.Title>Success Alert</Alert.Title>
<Alert.Description>This is a successful notification for your application.</Alert.Description>
</Alert>
),
}
export const Neutral = {
args: {
variant: 'neutral',
withIcon: true,
},
render: ({ withIcon, variant }: AlertProps) => (
<Alert variant={variant} withIcon={withIcon}>
<Alert.Title>Neutral Alert</Alert.Title>
<Alert.Description>This is a neutral message for your application.</Alert.Description>
</Alert>
),
}
@@ -1,145 +0,0 @@
import { cn } from '../../../../lib/utils'
import { VariantProps, cva } from 'class-variance-authority'
import { AlertOctagon, AlertTriangle, Check, Info } from 'lucide-react'
import * as React from 'react'
export type AlertRootVariantsProps = VariantProps<typeof alertRootVariants>
const alertRootVariants = cva(
`relative w-full
rounded-lg border
py-4 px-6
[&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11`,
{
variants: {
variant: {
danger: `bg-red-200 dark:bg-red-100 text-red-1200 border-red-700 [&>svg]:text-red-1200`,
warning: `bg-amber-200 dark:bg-amber-100 border-amber-700 [&>svg]:text-amber-1200`,
info: `bg-scale-400 border-scale-500 dark:bg-scale-100 dark:border-scale-300 [&>svg]:text-scale-1200`,
success: `bg-brand-300 dark:bg-brand-100 border-brand-700 [&>svg]:text-brand-900`,
neutral: `bg-scale-300 dark:bg-scale-300 border-scale-500 [&>svg]:text-scale-900`,
},
},
defaultVariants: {
variant: 'info',
},
}
)
const alertTitleVariants = cva('mb-1 font-medium leading-none tracking-tight', {
variants: {
variant: {
danger: `text-red-1200`,
warning: `text-amber-1200`,
info: `text-scale-1200`,
success: `text-brand-1200`,
neutral: `text-scale-1200`,
},
defaultVariants: {
variant: 'info',
},
},
})
const alertDescriptionVariants = cva('text-sm [&_p]:leading-relaxed', {
variants: {
variant: {
danger: 'text-red-1100',
warning: 'text-amber-1100',
info: 'text-scale-1100',
success: 'text-brand-1100',
neutral: 'text-scale-1100',
},
defaultVariants: {
variant: 'info',
},
},
})
interface ContextValue {
variant: AlertRootVariantsProps['variant']
}
const AlertContext = React.createContext<ContextValue>({
variant: undefined,
})
// Define the Alert component
interface AlertProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof alertRootVariants> {
withIcon: boolean
}
interface AlertComponent
extends React.ForwardRefExoticComponent<AlertProps & React.RefAttributes<HTMLDivElement>> {
Title: typeof AlertTitle
Description: typeof AlertDescription
}
type AlertIconVariant = Exclude<AlertRootVariantsProps['variant'], null | undefined>
const icons: Record<AlertIconVariant, React.ReactElement> = {
danger: <AlertOctagon strokeWidth={1.5} size={18} />,
success: <Check strokeWidth={1.5} size={18} />,
warning: <AlertTriangle strokeWidth={1.5} size={18} />,
info: <Info strokeWidth={1.5} size={18} />,
neutral: <></>,
}
const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
({ className, withIcon, variant = 'info', children, ...props }, ref) => {
const contextValue = {
variant,
}
return (
<div
ref={ref}
role="alert"
className={cn(alertRootVariants({ variant }), className)}
{...props}
children={
<AlertContext.Provider value={{ ...contextValue }}>
{withIcon && icons[variant as AlertIconVariant]}
{children}
</AlertContext.Provider>
}
/>
)
}
) as AlertComponent
Alert.displayName = 'Alert'
// Define the AlertTitle component as a subcomponent of Alert
interface AlertTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {}
const AlertTitle = React.forwardRef<HTMLHeadingElement, AlertTitleProps>(
({ className, ...props }, ref) => {
const { variant } = React.useContext(AlertContext)
console.log('variant', variant)
return <h5 ref={ref} className={cn(alertTitleVariants({ variant }), className)} {...props} />
}
)
AlertTitle.displayName = 'AlertTitle'
// Define the AlertDescription component as a subcomponent of Alert
interface AlertDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}
const AlertDescription = React.forwardRef<HTMLParagraphElement, AlertDescriptionProps>(
({ className, ...props }, ref) => {
const { variant } = React.useContext(AlertContext)
return (
<div ref={ref} className={cn(alertDescriptionVariants({ variant }), className)} {...props} />
)
}
)
AlertDescription.displayName = 'AlertDescription'
// Attach the subcomponents to the Alert component
Alert.Title = AlertTitle
Alert.Description = AlertDescription
// Export the Alert component
export { Alert }
@@ -1,155 +0,0 @@
import type { Meta, StoryObj } from '@storybook/react'
import { Badge, BadgeProps } from './Badge'
const meta: Meta<typeof Badge> = {
/* 👇 The title prop is optional.
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
* to learn how to generate automatic titles
*/
title: 'General/Badge',
component: Badge,
}
export default meta
type Story = StoryObj<typeof Badge>
export const Outline = {
args: {
variant: 'outline',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Brand = {
args: {
variant: 'brand',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Scale = {
args: {
variant: 'scale',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Tomato = {
args: {
variant: 'tomato',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Red = {
args: {
variant: 'red',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Crimson = {
args: {
variant: 'crimson',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Pink = {
args: {
variant: 'pink',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Purple = {
args: {
variant: 'purple',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Violet = {
args: {
variant: 'violet',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Indigo = {
args: {
variant: 'indigo',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Blue = {
args: {
variant: 'blue',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Green = {
args: {
variant: 'green',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Grass = {
args: {
variant: 'grass',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Orange = {
args: {
variant: 'orange',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Yellow = {
args: {
variant: 'yellow',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Amber = {
args: {
variant: 'amber',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Gold = {
args: {
variant: 'gold',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Gray = {
args: {
variant: 'gray',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Slate = {
args: {
variant: 'slate',
},
render: ({ variant }: BadgeProps) => <Badge variant={variant}>Hello World</Badge>,
}
export const Large = {
args: {
size: 'large',
},
render: ({ size }: BadgeProps) => <Badge size={size}>Hello World</Badge>,
}
@@ -1,51 +0,0 @@
import * as React from 'react'
import { VariantProps, cva } from 'class-variance-authority'
import { cn } from './../../lib/utils'
const badgeVariants = cva(
'inline-flex items-center border rounded-full px-2.5 py-0.5 text-xs font-normal transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
{
variants: {
variant: {
outline: 'text-foreground',
brand: 'bg-brand-200 text-brand-1100 border border-brand-700',
scale: 'bg-scale-200 text-scale-1100 border border-scale-700',
tomato: `bg-tomato-200 text-tomato-1100 border border-tomato-700`,
red: `bg-red-200 text-red-1100 border border-red-700`,
crimson: `bg-crimson-200 text-crimson-1100 border border-crimson-700`,
pink: `bg-pink-200 text-pink-1100 border border-pink-700`,
purple: `bg-purple-200 text-purple-1100 border border-purple-700`,
violet: `bg-violet-200 text-violet-1100 border border-violet-700`,
indigo: `bg-indigo-200 text-indigo-1100 border border-indigo-700`,
blue: `bg-blue-200 text-blue-1100 border border-blue-700`,
green: `bg-green-200 text-green-1100 border border-green-700`,
grass: `bg-grass-200 text-grass-1100 border border-grass-700`,
orange: `bg-orange-200 text-orange-1100 border border-orange-700`,
yellow: `bg-yellow-200 text-yellow-1100 border border-yellow-700`,
amber: `bg-amber-200 text-amber-1100 border border-amber-700`,
gold: `bg-gold-200 text-gold-1100 border border-gold-700`,
gray: `bg-gray-200 text-gray-1100 border border-gray-700`,
slate: `bg-slate-200 text-slate-1100 border border-slate-700`,
},
size: {
large: 'px-3 py-0.5 rounded-full text-sm',
},
},
defaultVariants: {
variant: 'scale',
},
}
)
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
const Badge = ({ className, variant, size, ...props }: BadgeProps) => {
return <div className={cn(badgeVariants({ variant, size }), className)} {...props} />
}
// Badge.displayName = 'Badge'
export { Badge }
@@ -1,175 +0,0 @@
// Button.stories.ts|tsx
import type { Meta, StoryObj } from '@storybook/react'
import { Button, ButtonProps } from './Button'
import { IconAirplay } from '../Icon/icons/IconAirplay'
const meta: Meta<typeof Button> = {
/* 👇 The title prop is optional.
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
* to learn how to generate automatic titles
*/
title: 'General/Button',
component: Button,
}
export default meta
type Story = StoryObj<typeof Button>
/*
*👇 Render functions are a framework specific feature to allow you control on how the component renders.
* See https://storybook.js.org/docs/react/api/csf
* to learn how to use render functions.
*/
export const Primary = {
args: {
children: 'Hello world',
type: 'primary',
},
render: ({ children, type }: ButtonProps) => <Button type={type}>{children}</Button>,
}
export const Default = {
args: {
children: 'Hello world',
type: 'default',
},
render: ({ children, type }: ButtonProps) => <Button type={type}>{children}</Button>,
}
export const Alternative = {
args: {
children: 'Hello world',
type: 'alternative',
},
render: ({ children, type }: ButtonProps) => <Button type={type}>{children}</Button>,
}
export const Outline = {
args: {
children: 'Hello world',
type: 'outline',
},
render: ({ children, type }: ButtonProps) => <Button type={type}>{children}</Button>,
}
export const Secondary = {
args: {
children: 'Hello world',
type: 'secondary',
},
render: ({ children, type }: ButtonProps) => <Button type={type}>{children}</Button>,
}
export const Dashed = {
args: {
children: 'Hello world',
type: 'dashed',
},
render: ({ children, type }: ButtonProps) => <Button type={type}>{children}</Button>,
}
export const Link = {
args: {
children: 'Hello world',
type: 'link',
},
render: ({ children, type }: ButtonProps) => <Button type={type}>{children}</Button>,
}
export const Text = {
args: {
children: 'Hello world',
type: 'text',
},
render: ({ children, type }: ButtonProps) => <Button type={type}>{children}</Button>,
}
export const Danger = {
args: {
children: 'Hello world',
type: 'danger',
},
render: ({ children, type }: ButtonProps) => <Button type={type}>{children}</Button>,
}
export const Block = {
args: {
children: 'Hello world',
type: 'primary',
block: true,
},
render: ({ children, type, block }: ButtonProps) => (
<Button block type={type}>
{children}
</Button>
),
}
export const Disabled = {
args: {
children: 'Hello world',
type: 'primary',
disabled: true,
},
render: ({ children, type, disabled }: ButtonProps) => (
<Button disabled type={type}>
{children}
</Button>
),
}
export const Sizes = {
args: {
children: 'Change the size below',
type: 'primary',
size: 'large',
},
render: ({ children, type, size }: ButtonProps) => (
<Button size={size} type={type}>
{children}
</Button>
),
}
export const LeftIcon = {
args: {
children: 'Change the size below',
type: 'primary',
iconLeft: <IconAirplay />,
},
render: ({ children, type, iconLeft }: ButtonProps) => (
<Button iconLeft={iconLeft} type={type}>
{children}
</Button>
),
}
export const RightIcon = {
args: {
children: 'Change the size below',
type: 'primary',
iconRight: <IconAirplay />,
},
render: ({ children, type, iconRight }: ButtonProps) => (
<Button iconRight={iconRight} type={type}>
{children}
</Button>
),
}
export const Loading = {
args: {
children: 'Change the size below',
type: 'primary',
loading: true,
},
render: ({ children, type, loading }: ButtonProps) => (
<Button loading={loading} type={type}>
{children}
</Button>
),
}
@@ -1,192 +0,0 @@
import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { VariantProps, cva } from 'class-variance-authority'
import { IconContext } from '@ui/components/Icon/IconContext'
import { IconLoader } from '@ui/components/Icon/icons/IconLoader'
import { cn } from '@ui/lib/utils'
import { sizes } from '@ui/lib/commonCva'
export type ButtonVariantProps = VariantProps<typeof buttonVariants>
const buttonVariants = cva(
`relative
cursor-pointer
inline-flex
items-center
space-x-2
text-center
font-regular
ease-out
duration-200
rounded
outline-none
transition-all
outline-0
focus-visible:outline-4
focus-visible:outline-offset-1`,
{
variants: {
type: {
primary: `
bg-brand-fixed-1100 hover:bg-brand-fixed-1000
text-white
bordershadow-brand-fixed-1000 hover:bordershadow-brand-fixed-900 dark:bordershadow-brand-fixed-1000 dark:hover:bordershadow-brand-fixed-1000
focus-visible:outline-brand-600
shadow-sm`,
secondary: `
bg-scale-1200
text-scale-100 hover:text-scale-800
focus-visible:text-scale-600
bordershadow-scale-1100 hover:bordershadow-scale-900
focus-visible:outline-scale-700
shadow-sm`,
default: `
text-scale-1200
bg-scale-100 hover:bg-scale-300
bordershadow-scale-600 hover:bordershadow-scale-700
dark:bordershadow-scale-700 hover:dark:bordershadow-scale-800
dark:bg-scale-500 dark:hover:bg-scale-600
focus-visible:outline-brand-600
shadow-sm`,
alternative: `
text-brand-1100
bg-brand-200 hover:bg-brand-400
bordershadow-brand-600 hover:bordershadow-brand-800
dark:bordershadow-brand-700 hover:dark:bordershadow-brand-800
focus-visible:border-brand-800
focus-visible:outline-brand-600
shadow-sm`,
outline: `
text-scale-1200
bg-transparent
bordershadow-scale-600 hover:bordershadow-scale-700
dark:bordershadow-scale-800 hover:dark:bordershadow-scale-900
focus-visible:outline-scale-700`,
dashed: `
text-scale-1200
border
border-dashed
border-scale-700 hover:border-scale-900
bg-transparent
focus-visible:outline-scale-700
shadow-sm`,
link: `
text-brand-1100
border
border-transparent
hover:bg-brand-400
border-opacity-0
bg-opacity-0 dark:bg-opacity-0
shadow-none
focus-visible:outline-scale-700`,
text: `
text-scale-1200
hover:bg-scale-500
shadow-none
focus-visible:outline-scale-700`,
danger: `
text-red-1100
bg-red-200
bordershadow-red-700 hover:bordershadow-red-900
hover:bg-red-900
hover:text-lo-contrast
focus-visible:outline-red-700
shadow-sm`,
warning: `
text-amber-1100
bg-amber-200
bordershadow-amber-700 hover:bordershadow-amber-900
hover:bg-amber-900
hover:text-hi-contrast
focus-visible:outline-amber-700
shadow-sm`,
},
block: {
true: 'w-full flex items-center justify-center',
},
size: {
...sizes,
},
overlay: {
base: `absolute inset-0 bg-scale-200 opacity-50`,
container: `fixed inset-0 transition-opacity`,
},
disabled: {
true: 'opacity-50 cursor-not-allowed pointer-events-none',
},
defaultVariants: {
// variant: 'default',
// size: 'default',
},
},
}
)
export type LoadingVariantProps = VariantProps<typeof loadingVariants>
const loadingVariants = cva('', {
variants: {
loading: {
default: '',
true: `animate-spin`,
},
},
})
export interface ButtonProps
// omit `type` as we use it to change type of button
// replaced with `htmlType`
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'type'>,
// omit 'disabled' as it is included in HTMLButtonElement
Omit<ButtonVariantProps, 'disabled'>,
LoadingVariantProps {
asChild?: boolean
type?: ButtonVariantProps['type']
htmlType?: React.ButtonHTMLAttributes<HTMLButtonElement>['type']
icon?: React.ReactNode
iconLeft?: React.ReactNode
iconRight?: React.ReactNode
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ asChild = false, size = 'small', type = 'primary', ...props }, ref) => {
const Comp = asChild ? Slot : 'button'
const { className, disabled, loading, icon, iconLeft, iconRight } = props
const showIcon = loading || icon
// decrecating 'showIcon' for rightIcon
const _iconLeft: React.ReactNode = icon ?? iconLeft
const buttonContent = (
<>
{showIcon &&
(loading ? (
<IconLoader size={size} className={cn(loadingVariants({ loading }))} />
) : _iconLeft ? (
<IconContext.Provider value={{ contextSize: size }}>{_iconLeft}</IconContext.Provider>
) : null)}
{props.children && <span className={'truncate'}>{props.children}</span>}
{iconRight && !loading && (
<IconContext.Provider value={{ contextSize: size }}>{iconRight}</IconContext.Provider>
)}
</>
)
return (
<Comp
className={cn(buttonVariants({ type, size, disabled }), className)}
ref={ref}
type={props.htmlType}
{...props}
>
{buttonContent}
</Comp>
)
}
)
Button.displayName = 'Button'
export { Button, buttonVariants }
@@ -1,187 +0,0 @@
// Inspired by react-hot-toast library
import * as React from 'react'
import { ToastActionElement, type ToastProps } from '@ui/components/shadcn/toast'
const TOAST_LIMIT = 1
const TOAST_REMOVE_DELAY = 1000000
type ToasterToast = ToastProps & {
id: string
title?: React.ReactNode
description?: React.ReactNode
action?: ToastActionElement
}
const actionTypes = {
ADD_TOAST: 'ADD_TOAST',
UPDATE_TOAST: 'UPDATE_TOAST',
DISMISS_TOAST: 'DISMISS_TOAST',
REMOVE_TOAST: 'REMOVE_TOAST',
} as const
let count = 0
function genId() {
count = (count + 1) % Number.MAX_VALUE
return count.toString()
}
type ActionType = typeof actionTypes
type Action =
| {
type: ActionType['ADD_TOAST']
toast: ToasterToast
}
| {
type: ActionType['UPDATE_TOAST']
toast: Partial<ToasterToast>
}
| {
type: ActionType['DISMISS_TOAST']
toastId?: ToasterToast['id']
}
| {
type: ActionType['REMOVE_TOAST']
toastId?: ToasterToast['id']
}
interface State {
toasts: ToasterToast[]
}
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) {
return
}
const timeout = setTimeout(() => {
toastTimeouts.delete(toastId)
dispatch({
type: 'REMOVE_TOAST',
toastId: toastId,
})
}, TOAST_REMOVE_DELAY)
toastTimeouts.set(toastId, timeout)
}
export const reducer = (state: State, action: Action): State => {
switch (action.type) {
case 'ADD_TOAST':
return {
...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
}
case 'UPDATE_TOAST':
return {
...state,
toasts: state.toasts.map((t) => (t.id === action.toast.id ? { ...t, ...action.toast } : t)),
}
case 'DISMISS_TOAST': {
const { toastId } = action
// ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity
if (toastId) {
addToRemoveQueue(toastId)
} else {
state.toasts.forEach((toast) => {
addToRemoveQueue(toast.id)
})
}
return {
...state,
toasts: state.toasts.map((t) =>
t.id === toastId || toastId === undefined
? {
...t,
open: false,
}
: t
),
}
}
case 'REMOVE_TOAST':
if (action.toastId === undefined) {
return {
...state,
toasts: [],
}
}
return {
...state,
toasts: state.toasts.filter((t) => t.id !== action.toastId),
}
}
}
const listeners: Array<(state: State) => void> = []
let memoryState: State = { toasts: [] }
function dispatch(action: Action) {
memoryState = reducer(memoryState, action)
listeners.forEach((listener) => {
listener(memoryState)
})
}
interface Toast extends Omit<ToasterToast, 'id'> {}
function toast({ ...props }: Toast) {
const id = genId()
const update = (props: ToasterToast) =>
dispatch({
type: 'UPDATE_TOAST',
toast: { ...props, id },
})
const dismiss = () => dispatch({ type: 'DISMISS_TOAST', toastId: id })
dispatch({
type: 'ADD_TOAST',
toast: {
...props,
id,
open: true,
onOpenChange: (open) => {
if (!open) dismiss()
},
},
})
return {
id: id,
dismiss,
update,
}
}
function useToast() {
const [state, setState] = React.useState<State>(memoryState)
React.useEffect(() => {
listeners.push(setState)
return () => {
const index = listeners.indexOf(setState)
if (index > -1) {
listeners.splice(index, 1)
}
}
}, [state])
return {
...state,
toast,
dismiss: (toastId?: string) => dispatch({ type: 'DISMISS_TOAST', toastId }),
}
}
export { useToast, toast }