diff --git a/src/components/ui/alert-dialog.tsx b/src/components/ui/alert-dialog.tsx index b253adf..fa90fdf 100644 --- a/src/components/ui/alert-dialog.tsx +++ b/src/components/ui/alert-dialog.tsx @@ -1,104 +1,91 @@ /* - * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * SPDX-FileCopyrightText: 2023 shadcn + * SPDX-FileCopyrightText: 2026 Coffey Labs LLC * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + * SPDX-License-Identifier: MIT */ +// Structure from shadcn/ui 4.21.1 (MIT), styled for inbuxa. + import * as React from 'react'; import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'; import { cn } from '@/lib/utils'; import { buttonVariants } from '@/components/ui/button'; +import { + modalContentClasses, + modalFooterClasses, + modalHeaderClasses, + modalOverlayClasses, +} from '@/components/ui/modalClasses'; -const AlertDialog = AlertDialogPrimitive.Root; +function AlertDialog(props: React.ComponentProps) { + return ; +} -const AlertDialogTrigger = AlertDialogPrimitive.Trigger; +function AlertDialogTrigger(props: React.ComponentProps) { + return ; +} -const AlertDialogPortal = AlertDialogPrimitive.Portal; +function AlertDialogContent({ className, ...props }: React.ComponentProps) { + return ( + + + + + ); +} -const AlertDialogOverlay = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName; +function AlertDialogHeader({ className, ...props }: React.ComponentProps<'div'>) { + return
; +} -const AlertDialogContent = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - ) { + return
; +} + +function AlertDialogTitle({ className, ...props }: React.ComponentProps) { + return ( + - -)); -AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName; + ); +} -const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( -
-); -AlertDialogHeader.displayName = 'AlertDialogHeader'; +function AlertDialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} -const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes) => ( -
-); -AlertDialogFooter.displayName = 'AlertDialogFooter'; +function AlertDialogAction({ className, ...props }: React.ComponentProps) { + return ; +} -const AlertDialogTitle = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName; - -const AlertDialogDescription = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName; - -const AlertDialogAction = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName; - -const AlertDialogCancel = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName; +function AlertDialogCancel({ className, ...props }: React.ComponentProps) { + return ( + + ); +} export { AlertDialog, - AlertDialogPortal, - AlertDialogOverlay, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx index ac254bb..3b4a957 100644 --- a/src/components/ui/calendar.tsx +++ b/src/components/ui/calendar.tsx @@ -1,121 +1,76 @@ /* - * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * SPDX-FileCopyrightText: 2023 shadcn + * SPDX-FileCopyrightText: 2026 Coffey Labs LLC * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + * SPDX-License-Identifier: MIT */ +// Structure from shadcn/ui 4.21.1 (MIT), styled for inbuxa. + import * as React from 'react'; -import { ChevronDown, ChevronLeft, ChevronRight } from 'lucide-react'; +import { ChevronLeft, ChevronRight } from 'lucide-react'; import { DayPicker, getDefaultClassNames, type DayButton } from '@daypicker/react'; import { cn } from '@/lib/utils'; import { Button, buttonVariants } from '@/components/ui/button'; +const navButton = cn( + buttonVariants({ variant: 'ghost' }), + 'size-(--cell-size) p-0 select-none aria-disabled:opacity-50', +); + +/** + * A month grid for picking one day. The console only picks single dates (the + * date field), so only that is styled: no ranges, week numbers or month and + * year dropdowns. + */ function Calendar({ className, classNames, - showOutsideDays = true, - captionLayout = 'label', - buttonVariant = 'ghost', - formatters, components, + showOutsideDays = true, ...props -}: React.ComponentProps & { - buttonVariant?: React.ComponentProps['variant']; -}) { - const defaultClassNames = getDefaultClassNames(); - +}: React.ComponentProps) { + const base = getDefaultClassNames(); return ( svg]:rotate-180`, - String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`, className, )} - captionLayout={captionLayout} - formatters={{ - formatMonthDropdown: (date) => date.toLocaleString('default', { month: 'short' }), - ...formatters, - }} classNames={{ - root: cn('w-fit', defaultClassNames.root), - months: cn('relative flex flex-col gap-4 md:flex-row', defaultClassNames.months), - month: cn('flex w-full flex-col gap-4', defaultClassNames.month), - nav: cn('absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1', defaultClassNames.nav), - button_previous: cn( - buttonVariants({ variant: buttonVariant }), - 'size-(--cell-size) p-0 select-none aria-disabled:opacity-50', - defaultClassNames.button_previous, - ), - button_next: cn( - buttonVariants({ variant: buttonVariant }), - 'size-(--cell-size) p-0 select-none aria-disabled:opacity-50', - defaultClassNames.button_next, - ), + root: cn('w-fit', base.root), + months: cn('relative flex flex-col gap-4 md:flex-row', base.months), + month: cn('flex w-full flex-col gap-4', base.month), + nav: cn('absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1', base.nav), + button_previous: cn(navButton, base.button_previous), + button_next: cn(navButton, base.button_next), month_caption: cn( 'flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)', - defaultClassNames.month_caption, + base.month_caption, ), - dropdowns: cn( - 'flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium', - defaultClassNames.dropdowns, - ), - dropdown_root: cn( - 'relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50', - defaultClassNames.dropdown_root, - ), - dropdown: cn('absolute inset-0 bg-popover opacity-0', defaultClassNames.dropdown), - caption_label: cn( - 'font-medium select-none', - captionLayout === 'label' - ? 'text-sm' - : 'flex h-8 items-center gap-1 rounded-md pr-1 pl-2 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground', - defaultClassNames.caption_label, - ), - month_grid: cn('w-full border-collapse', defaultClassNames.month_grid), - weekdays: cn('flex', defaultClassNames.weekdays), - weekday: cn( - 'flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none', - defaultClassNames.weekday, - ), - week: cn('mt-2 flex w-full', defaultClassNames.week), - week_number_header: cn('w-(--cell-size) select-none', defaultClassNames.week_number_header), - week_number: cn('text-[0.8rem] text-muted-foreground select-none', defaultClassNames.week_number), - day: cn( - 'group/day relative aspect-square h-full w-full p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-md', - props.showWeekNumber - ? '[&:nth-child(2)[data-selected=true]_button]:rounded-l-md' - : '[&:first-child[data-selected=true]_button]:rounded-l-md', - defaultClassNames.day, - ), - range_start: cn('rounded-l-md bg-accent', defaultClassNames.range_start), - range_middle: cn('rounded-none', defaultClassNames.range_middle), - range_end: cn('rounded-r-md bg-accent', defaultClassNames.range_end), - today: cn( - 'rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none', - defaultClassNames.today, - ), - outside: cn('text-muted-foreground aria-selected:text-muted-foreground', defaultClassNames.outside), - disabled: cn('text-muted-foreground opacity-50', defaultClassNames.disabled), - hidden: cn('invisible', defaultClassNames.hidden), + caption_label: cn('text-sm font-medium select-none', base.caption_label), + month_grid: cn('w-full border-collapse', base.month_grid), + weekdays: cn('flex', base.weekdays), + weekday: cn('flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none', base.weekday), + week: cn('mt-2 flex w-full', base.week), + day: cn('group/day relative aspect-square size-full p-0 text-center select-none', base.day), + today: cn('rounded-md bg-accent text-accent-foreground', base.today), + outside: cn('text-muted-foreground aria-selected:text-muted-foreground', base.outside), + disabled: cn('text-muted-foreground opacity-50', base.disabled), + hidden: cn('invisible', base.hidden), ...classNames, }} components={{ - Root: ({ className, rootRef, ...props }) => ( -
+ Root: ({ className, rootRef, ...rest }) => ( +
), - Chevron: ({ className, orientation, ...props }) => { - const Icon = orientation === 'left' ? ChevronLeft : orientation === 'right' ? ChevronRight : ChevronDown; - return ; + Chevron: ({ className, orientation, ...rest }) => { + const Icon = orientation === 'left' ? ChevronLeft : ChevronRight; + return ; }, DayButton: CalendarDayButton, - WeekNumber: ({ children, ...props }) => ( - -
{children}
- - ), ...components, }} {...props} @@ -124,9 +79,8 @@ function Calendar({ } function CalendarDayButton({ className, day, modifiers, ...props }: React.ComponentProps) { - const defaultClassNames = getDefaultClassNames(); - const ref = React.useRef(null); + // Keyboard moves focus between days by re-rendering; follow it. React.useEffect(() => { if (modifiers.focused) ref.current?.focus(); }, [modifiers.focused]); @@ -137,15 +91,12 @@ function CalendarDayButton({ className, day, modifiers, ...props }: React.Compon variant="ghost" size="icon" data-day={day.date.toLocaleDateString()} - data-selected-single={ - modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle - } - data-range-start={modifiers.range_start} - data-range-end={modifiers.range_end} - data-range-middle={modifiers.range_middle} + data-selected-single={modifiers.selected} className={cn( - 'flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70', - defaultClassNames.day, + 'flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal dark:hover:text-accent-foreground', + 'group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50', + 'data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground', + getDefaultClassNames().day, className, )} {...props} @@ -153,4 +104,4 @@ function CalendarDayButton({ className, day, modifiers, ...props }: React.Compon ); } -export { Calendar, CalendarDayButton }; +export { Calendar }; diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx index 8e30b64..5d935f8 100644 --- a/src/components/ui/command.tsx +++ b/src/components/ui/command.tsx @@ -1,132 +1,100 @@ /* - * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * SPDX-FileCopyrightText: 2023 shadcn + * SPDX-FileCopyrightText: 2026 Coffey Labs LLC * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + * SPDX-License-Identifier: MIT */ +// Structure from shadcn/ui 4.21.1 (MIT), styled for inbuxa. + import * as React from 'react'; -import { type DialogProps } from '@radix-ui/react-dialog'; import { Command as CommandPrimitive } from 'cmdk'; import { Search } from 'lucide-react'; import { cn } from '@/lib/utils'; -import { Dialog, DialogContent } from '@/components/ui/dialog'; -const Command = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -Command.displayName = CommandPrimitive.displayName; - -const CommandDialog = ({ children, ...props }: DialogProps) => { +function Command({ className, ...props }: React.ComponentProps) { return ( - - - - {children} - - - + ); -}; +} -const CommandInput = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef & { trailing?: React.ReactNode } ->(({ className, trailing, ...props }, ref) => ( -
- - & { trailing?: React.ReactNode }) { + return ( +
+ + + {trailing} +
+ ); +} + +function CommandList({ className, ...props }: React.ComponentProps) { + return ( + + ); +} + +function CommandEmpty({ className, ...props }: React.ComponentProps) { + return ( + + ); +} + +function CommandGroup({ className, ...props }: React.ComponentProps) { + return ( + - {trailing} -
-)); -CommandInput.displayName = CommandPrimitive.Input.displayName; + ); +} -const CommandList = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -CommandList.displayName = CommandPrimitive.List.displayName; +function CommandItem({ className, ...props }: React.ComponentProps) { + return ( + + ); +} -const CommandEmpty = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->((props, ref) => ); -CommandEmpty.displayName = CommandPrimitive.Empty.displayName; - -const CommandGroup = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -CommandGroup.displayName = CommandPrimitive.Group.displayName; - -const CommandSeparator = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -CommandSeparator.displayName = CommandPrimitive.Separator.displayName; - -const CommandItem = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -CommandItem.displayName = CommandPrimitive.Item.displayName; - -const CommandShortcut = ({ className, ...props }: React.HTMLAttributes) => { - return ; -}; -CommandShortcut.displayName = 'CommandShortcut'; - -export { - Command, - CommandDialog, - CommandInput, - CommandList, - CommandEmpty, - CommandGroup, - CommandItem, - CommandShortcut, - CommandSeparator, -}; +export { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem }; diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx index 055ad11..0379ad7 100644 --- a/src/components/ui/dialog.tsx +++ b/src/components/ui/dialog.tsx @@ -1,98 +1,91 @@ /* - * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * SPDX-FileCopyrightText: 2023 shadcn + * SPDX-FileCopyrightText: 2026 Coffey Labs LLC * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + * SPDX-License-Identifier: MIT */ +// Structure from shadcn/ui 4.21.1 (MIT), styled for inbuxa. + import * as React from 'react'; import * as DialogPrimitive from '@radix-ui/react-dialog'; import { X } from 'lucide-react'; import { cn } from '@/lib/utils'; +import { + modalContentClasses, + modalFooterClasses, + modalHeaderClasses, + modalOverlayClasses, +} from '@/components/ui/modalClasses'; -const Dialog = DialogPrimitive.Root; +function Dialog(props: React.ComponentProps) { + return ; +} -const DialogTrigger = DialogPrimitive.Trigger; +function DialogTrigger(props: React.ComponentProps) { + return ; +} -const DialogPortal = DialogPrimitive.Portal; +function DialogClose(props: React.ComponentProps) { + return ; +} -const DialogClose = DialogPrimitive.Close; +function DialogContent({ + className, + children, + showCloseButton = true, + ...props +}: React.ComponentProps & { showCloseButton?: boolean }) { + return ( + + + + {children} + {showCloseButton && ( + + + Close + + )} + + + ); +} -const DialogOverlay = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; +function DialogHeader({ className, ...props }: React.ComponentProps<'div'>) { + return
; +} -const DialogContent = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef & { showCloseButton?: boolean } ->(({ className, children, showCloseButton = true, ...props }, ref) => ( - - - ) { + return
; +} + +function DialogTitle({ className, ...props }: React.ComponentProps) { + return ( + - {children} - {showCloseButton && ( - - - Close - - )} - - -)); -DialogContent.displayName = DialogPrimitive.Content.displayName; + /> + ); +} -const DialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( -
-); -DialogHeader.displayName = 'DialogHeader'; - -const DialogFooter = ({ className, ...props }: React.HTMLAttributes) => ( -
-); -DialogFooter.displayName = 'DialogFooter'; - -const DialogTitle = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DialogTitle.displayName = DialogPrimitive.Title.displayName; - -const DialogDescription = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DialogDescription.displayName = DialogPrimitive.Description.displayName; +function DialogDescription({ className, ...props }: React.ComponentProps) { + return ( + + ); +} export { Dialog, - DialogPortal, - DialogOverlay, DialogTrigger, DialogClose, DialogContent, diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx index 4790b35..bba58f8 100644 --- a/src/components/ui/dropdown-menu.tsx +++ b/src/components/ui/dropdown-menu.tsx @@ -1,186 +1,173 @@ /* - * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * SPDX-FileCopyrightText: 2023 shadcn + * SPDX-FileCopyrightText: 2026 Coffey Labs LLC * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + * SPDX-License-Identifier: MIT */ +// Structure from shadcn/ui 4.21.1 (MIT), styled for inbuxa. + import * as React from 'react'; import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; -import { Check, ChevronRight, Circle } from 'lucide-react'; +import { ChevronRight, Circle } from 'lucide-react'; import { cn } from '@/lib/utils'; -const DropdownMenu = DropdownMenuPrimitive.Root; +// The panel and the item rows, shared by the menu and its submenus. +const panel = [ + 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground', + 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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', +]; +const row = + 'relative flex cursor-default select-none items-center rounded-sm text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50'; -const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; +function DropdownMenu(props: React.ComponentProps) { + return ; +} -const DropdownMenuGroup = DropdownMenuPrimitive.Group; +function DropdownMenuTrigger(props: React.ComponentProps) { + return ; +} -const DropdownMenuPortal = DropdownMenuPrimitive.Portal; +function DropdownMenuContent({ + className, + sideOffset = 4, + ...props +}: React.ComponentProps) { + return ( + + + + ); +} -const DropdownMenuSub = DropdownMenuPrimitive.Sub; +function DropdownMenuGroup(props: React.ComponentProps) { + return ; +} -const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; +function DropdownMenuItem({ + className, + inset, + ...props +}: React.ComponentProps & { inset?: boolean }) { + return ( + svg]:size-4 [&>svg]:shrink-0', inset && 'pl-8', className)} + {...props} + /> + ); +} -const DropdownMenuSubTrigger = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef & { - inset?: boolean; - } ->(({ className, inset, children, ...props }, ref) => ( - - {children} - - -)); -DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName; +function DropdownMenuRadioGroup(props: React.ComponentProps) { + return ; +} -const DropdownMenuSubContent = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName; +function DropdownMenuRadioItem({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ); +} -const DropdownMenuContent = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, sideOffset = 4, ...props }, ref) => ( - - & { inset?: boolean }) { + return ( + + ); +} + +function DropdownMenuSeparator({ className, ...props }: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuSub(props: React.ComponentProps) { + return ; +} + +function DropdownMenuSubTrigger({ + className, + inset, + children, + ...props +}: React.ComponentProps & { inset?: boolean }) { + return ( + + {children} + + + ); +} + +function DropdownMenuSubContent({ + className, + ...props +}: React.ComponentProps) { + return ( + - -)); -DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; - -const DropdownMenuItem = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef & { - inset?: boolean; - } ->(({ className, inset, ...props }, ref) => ( - svg]:size-4 [&>svg]:shrink-0', - inset && 'pl-8', - className, - )} - {...props} - /> -)); -DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; - -const DropdownMenuCheckboxItem = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, children, checked, ...props }, ref) => ( - - - - - - - {children} - -)); -DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName; - -const DropdownMenuRadioItem = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)); -DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; - -const DropdownMenuLabel = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef & { - inset?: boolean; - } ->(({ className, inset, ...props }, ref) => ( - -)); -DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; - -const DropdownMenuSeparator = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; - -const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes) => { - return ; -}; -DropdownMenuShortcut.displayName = 'DropdownMenuShortcut'; + ); +} export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, + DropdownMenuGroup, DropdownMenuItem, - DropdownMenuCheckboxItem, + DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuLabel, DropdownMenuSeparator, - DropdownMenuShortcut, - DropdownMenuGroup, - DropdownMenuPortal, DropdownMenuSub, - DropdownMenuSubContent, DropdownMenuSubTrigger, - DropdownMenuRadioGroup, + DropdownMenuSubContent, }; diff --git a/src/components/ui/modalClasses.ts b/src/components/ui/modalClasses.ts new file mode 100644 index 0000000..57a29e2 --- /dev/null +++ b/src/components/ui/modalClasses.ts @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2026 Coffey Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/** The look Dialog and AlertDialog share. */ +export const modalOverlayClasses = + 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=closed]:animate-out data-[state=closed]:fade-out-0'; + +/** + * Centered with translate, so a caller can move it with its own `top-*`, + * `left-*` or `translate-*` classes (the help panel docks it to the right). + */ +export const modalContentClasses = [ + 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg', + 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]', + 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]', +]; + +export const modalHeaderClasses = 'flex flex-col text-center sm:text-left'; +export const modalFooterClasses = 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2'; diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx index b68e55d..61cf1d6 100644 --- a/src/components/ui/select.tsx +++ b/src/components/ui/select.tsx @@ -1,148 +1,115 @@ /* - * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * SPDX-FileCopyrightText: 2023 shadcn + * SPDX-FileCopyrightText: 2026 Coffey Labs LLC * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + * SPDX-License-Identifier: MIT */ +// Structure from shadcn/ui 4.21.1 (MIT), styled for inbuxa. + import * as React from 'react'; import * as SelectPrimitive from '@radix-ui/react-select'; import { Check, ChevronDown, ChevronUp } from 'lucide-react'; import { cn } from '@/lib/utils'; -const Select = SelectPrimitive.Root; +function Select(props: React.ComponentProps) { + return ; +} -const SelectGroup = SelectPrimitive.Group; +function SelectValue(props: React.ComponentProps) { + return ; +} -const SelectValue = SelectPrimitive.Value; - -const SelectTrigger = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - span]:line-clamp-1', - className, - )} - {...props} - > - {children} - - - - -)); -SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; - -const SelectScrollUpButton = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)); -SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; - -const SelectScrollDownButton = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)); -SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName; - -const SelectContent = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, children, position = 'popper', ...props }, ref) => ( - - ) { + return ( + span]:line-clamp-1', className, )} - position={position} {...props} > - - + + + + ); +} + +function SelectContent({ + className, + children, + position = 'popper', + ...props +}: React.ComponentProps) { + const popper = position === 'popper'; + return ( + + - {children} - - - - -)); -SelectContent.displayName = SelectPrimitive.Content.displayName; + + + + + {children} + + + + + + + ); +} -const SelectLabel = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -SelectLabel.displayName = SelectPrimitive.Label.displayName; +function SelectItem({ className, children, ...props }: React.ComponentProps) { + return ( + + + + + + + {children} + + ); +} -const SelectItem = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)); -SelectItem.displayName = SelectPrimitive.Item.displayName; +function SelectSeparator({ className, ...props }: React.ComponentProps) { + return ( + + ); +} -const SelectSeparator = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -SelectSeparator.displayName = SelectPrimitive.Separator.displayName; - -export { - Select, - SelectGroup, - SelectValue, - SelectTrigger, - SelectContent, - SelectLabel, - SelectItem, - SelectSeparator, - SelectScrollUpButton, - SelectScrollDownButton, -}; +export { Select, SelectValue, SelectTrigger, SelectContent, SelectItem, SelectSeparator };