diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 0000000..fad4d88 --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 shadcn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 1870bbe..a96c287 100644 --- a/README.md +++ b/README.md @@ -77,3 +77,7 @@ every file inherited from it, and INBUXA's own notice is added to the files it changes. Those files are offered upstream under the AGPL-3.0-only or a proprietary license. INBUXA uses them under the AGPL-3.0 only. INBUXA isn't affiliated with or endorsed by Stalwart Labs. + +The base components in `src/components/ui` follow the structure of +[shadcn/ui](https://ui.shadcn.com), used under the [MIT license](./LICENSES/MIT.txt). +Each of those files says so in its header. diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx index adb9001..e19e377 100644 --- a/src/components/ui/badge.tsx +++ b/src/components/ui/badge.tsx @@ -1,22 +1,31 @@ /* - * 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 { Slot } from '@radix-ui/react-slot'; import { cva, type VariantProps } from 'class-variance-authority'; import { cn } from '@/lib/utils'; const badgeVariants = cva( - 'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', + [ + 'inline-flex w-fit shrink-0 items-center gap-1 rounded-md border px-2.5 py-0.5 text-xs font-semibold whitespace-nowrap transition-colors', + 'outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2', + '[&>svg]:pointer-events-none [&>svg]:size-3', + ], { variants: { variant: { - default: 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80', - secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80', - destructive: 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80', + default: 'border-transparent bg-primary text-primary-foreground shadow [a&]:hover:bg-primary/80', + secondary: 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/80', + destructive: + 'border-transparent bg-destructive text-destructive-foreground shadow [a&]:hover:bg-destructive/80', outline: 'text-foreground', }, }, @@ -26,10 +35,16 @@ const badgeVariants = cva( }, ); -export interface BadgeProps extends React.HTMLAttributes, VariantProps {} - -function Badge({ className, variant, ...props }: BadgeProps) { - return
; +function Badge({ + className, + variant = 'default', + asChild = false, + ...props +}: React.ComponentProps<'span'> & VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot : 'span'; + return ( + + ); } export { Badge, badgeVariants }; diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index e14e802..e81a4d8 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -1,12 +1,12 @@ /* - * 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 - * - * Modified by Coffey Labs in 2026 for INBUXA. + * SPDX-License-Identifier: MIT */ +// Structure from shadcn/ui 4.21.1 (MIT), styled for inbuxa. + import * as React from 'react'; import { Slot } from '@radix-ui/react-slot'; import { cva, type VariantProps } from 'class-variance-authority'; @@ -14,7 +14,12 @@ import { cva, type VariantProps } from 'class-variance-authority'; import { cn } from '@/lib/utils'; const buttonVariants = cva( - 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background active:scale-[0.98] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', + [ + 'inline-flex shrink-0 items-center justify-center gap-2 rounded-lg text-sm font-medium whitespace-nowrap transition-all outline-none', + 'focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background', + 'active:scale-[0.98] disabled:pointer-events-none disabled:opacity-50', + "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + ], { variants: { variant: { @@ -27,9 +32,9 @@ const buttonVariants = cva( }, size: { default: 'h-9 px-4 py-2', - sm: 'h-8 rounded-lg px-3 text-xs', + sm: 'h-8 px-3 text-xs', lg: 'h-10 rounded-xl px-8', - icon: 'h-9 w-9', + icon: 'size-9', }, }, defaultVariants: { @@ -39,17 +44,23 @@ const buttonVariants = cva( }, ); -export interface ButtonProps - extends React.ButtonHTMLAttributes, VariantProps { - asChild?: boolean; +function Button({ + className, + variant = 'default', + size = 'default', + asChild = false, + ...props +}: React.ComponentProps<'button'> & VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot : 'button'; + return ( + + ); } -const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : 'button'; - return ; - }, -); -Button.displayName = 'Button'; - export { Button, buttonVariants }; diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx index 198f9a9..386f484 100644 --- a/src/components/ui/card.tsx +++ b/src/components/ui/card.tsx @@ -1,52 +1,47 @@ /* - * 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 - * - * Modified by Coffey Labs in 2026 for INBUXA. + * SPDX-License-Identifier: MIT */ +// Structure from shadcn/ui 4.21.1 (MIT), styled for inbuxa. + import * as React from 'react'; import { cn } from '@/lib/utils'; -const Card = React.forwardRef>(({ className, ...props }, ref) => ( -
-)); -Card.displayName = 'Card'; +// The card has no padding of its own: header, content and footer each pad +// themselves, and content and footer skip the top so they sit under the header. -const CardHeader = React.forwardRef>( - ({ className, ...props }, ref) => ( -
- ), -); -CardHeader.displayName = 'CardHeader'; +function Card({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); +} -const CardTitle = React.forwardRef>( - ({ className, ...props }, ref) => ( -
- ), -); -CardTitle.displayName = 'CardTitle'; +function CardHeader({ className, ...props }: React.ComponentProps<'div'>) { + return
; +} -const CardDescription = React.forwardRef>( - ({ className, ...props }, ref) => ( -
- ), -); -CardDescription.displayName = 'CardDescription'; +function CardTitle({ className, ...props }: React.ComponentProps<'div'>) { + return
; +} -const CardContent = React.forwardRef>( - ({ className, ...props }, ref) =>
, -); -CardContent.displayName = 'CardContent'; +function CardDescription({ className, ...props }: React.ComponentProps<'div'>) { + return
; +} -const CardFooter = React.forwardRef>( - ({ className, ...props }, ref) => ( -
- ), -); -CardFooter.displayName = 'CardFooter'; +function CardContent({ className, ...props }: React.ComponentProps<'div'>) { + return
; +} + +function CardFooter({ className, ...props }: React.ComponentProps<'div'>) { + return
; +} export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }; diff --git a/src/components/ui/checkbox.tsx b/src/components/ui/checkbox.tsx index d452ec1..3adb403 100644 --- a/src/components/ui/checkbox.tsx +++ b/src/components/ui/checkbox.tsx @@ -1,32 +1,35 @@ /* - * 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 CheckboxPrimitive from '@radix-ui/react-checkbox'; -import { Check } from 'lucide-react'; +import { CheckIcon } from 'lucide-react'; import { cn } from '@/lib/utils'; -const Checkbox = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - - - -)); -Checkbox.displayName = CheckboxPrimitive.Root.displayName; +function Checkbox({ className, ...props }: React.ComponentProps) { + return ( + + + + + + ); +} export { Checkbox }; diff --git a/src/components/ui/collapsible.tsx b/src/components/ui/collapsible.tsx index 833fb41..101d3e3 100644 --- a/src/components/ui/collapsible.tsx +++ b/src/components/ui/collapsible.tsx @@ -1,15 +1,25 @@ /* - * 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 CollapsiblePrimitive from '@radix-ui/react-collapsible'; -const Collapsible = CollapsiblePrimitive.Root; +function Collapsible(props: React.ComponentProps) { + return ; +} -const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; +function CollapsibleTrigger(props: React.ComponentProps) { + return ; +} -const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; +function CollapsibleContent(props: React.ComponentProps) { + return ; +} export { Collapsible, CollapsibleTrigger, CollapsibleContent }; diff --git a/src/components/ui/fieldClasses.ts b/src/components/ui/fieldClasses.ts new file mode 100644 index 0000000..9f019e5 --- /dev/null +++ b/src/components/ui/fieldClasses.ts @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2026 Coffey Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/** The look the text fields share: Input and Textarea. */ +export const fieldClasses = [ + 'w-full min-w-0 rounded-lg border border-input bg-background/60 text-base shadow-sm transition-[color,box-shadow] outline-none md:text-sm', + 'placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground', + 'focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/25', + 'aria-invalid:border-destructive aria-invalid:ring-destructive/20', + 'disabled:cursor-not-allowed disabled:opacity-50', +]; diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index 584a416..619a383 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -1,31 +1,30 @@ /* - * 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 - * - * Modified by Coffey Labs in 2026 for INBUXA. + * SPDX-License-Identifier: MIT */ +// Structure from shadcn/ui 4.21.1 (MIT), styled for inbuxa. + import * as React from 'react'; import { cn } from '@/lib/utils'; +import { fieldClasses } from '@/components/ui/fieldClasses'; -const Input = React.forwardRef>( - ({ className, type, ...props }, ref) => { - return ( - - ); - }, -); -Input.displayName = 'Input'; +function Input({ className, type, ...props }: React.ComponentProps<'input'>) { + return ( + + ); +} export { Input }; diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx index 07a9172..b24eb10 100644 --- a/src/components/ui/label.tsx +++ b/src/components/ui/label.tsx @@ -1,23 +1,28 @@ /* - * 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 LabelPrimitive from '@radix-ui/react-label'; -import { cva, type VariantProps } from 'class-variance-authority'; import { cn } from '@/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.ComponentRef, - React.ComponentPropsWithoutRef & VariantProps ->(({ className, ...props }, ref) => ( - -)); -Label.displayName = LabelPrimitive.Root.displayName; +function Label({ className, ...props }: React.ComponentProps) { + return ( + + ); +} export { Label }; diff --git a/src/components/ui/popover.tsx b/src/components/ui/popover.tsx index b0bf519..821304d 100644 --- a/src/components/ui/popover.tsx +++ b/src/components/ui/popover.tsx @@ -1,37 +1,51 @@ /* - * 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 PopoverPrimitive from '@radix-ui/react-popover'; import { cn } from '@/lib/utils'; -const Popover = PopoverPrimitive.Root; +function Popover(props: React.ComponentProps) { + return ; +} -const PopoverTrigger = PopoverPrimitive.Trigger; +function PopoverTrigger(props: React.ComponentProps) { + return ; +} -const PopoverAnchor = PopoverPrimitive.Anchor; +function PopoverAnchor(props: React.ComponentProps) { + return ; +} -const PopoverContent = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, align = 'center', sideOffset = 4, ...props }, ref) => ( - - - -)); -PopoverContent.displayName = PopoverPrimitive.Content.displayName; +function PopoverContent({ + className, + align = 'center', + sideOffset = 4, + ...props +}: React.ComponentProps) { + return ( + + + + ); +} export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }; diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx index 4f82af3..fe0c029 100644 --- a/src/components/ui/separator.tsx +++ b/src/components/ui/separator.tsx @@ -1,26 +1,35 @@ /* - * 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 SeparatorPrimitive from '@radix-ui/react-separator'; import { cn } from '@/lib/utils'; -const Separator = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => ( - -)); -Separator.displayName = SeparatorPrimitive.Root.displayName; +function Separator({ + className, + orientation = 'horizontal', + decorative = true, + ...props +}: React.ComponentProps) { + return ( + + ); +} export { Separator }; diff --git a/src/components/ui/switch.tsx b/src/components/ui/switch.tsx index ded3fe9..511f731 100644 --- a/src/components/ui/switch.tsx +++ b/src/components/ui/switch.tsx @@ -1,33 +1,35 @@ /* - * 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 SwitchPrimitives from '@radix-ui/react-switch'; +import * as SwitchPrimitive from '@radix-ui/react-switch'; import { cn } from '@/lib/utils'; -const Switch = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - ) { + return ( + - -)); -Switch.displayName = SwitchPrimitives.Root.displayName; + {...props} + > + + + ); +} export { Switch }; diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx index e2d3e90..d836209 100644 --- a/src/components/ui/tabs.tsx +++ b/src/components/ui/tabs.tsx @@ -1,59 +1,61 @@ /* - * 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 TabsPrimitive from '@radix-ui/react-tabs'; import { cn } from '@/lib/utils'; -const Tabs = TabsPrimitive.Root; +function Tabs({ className, ...props }: React.ComponentProps) { + return ; +} -const TabsList = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -TabsList.displayName = TabsPrimitive.List.displayName; +function TabsList({ className, ...props }: React.ComponentProps) { + return ( + + ); +} -const TabsTrigger = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; +function TabsTrigger({ className, ...props }: React.ComponentProps) { + return ( + + ); +} -const TabsContent = React.forwardRef< - React.ComponentRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -TabsContent.displayName = TabsPrimitive.Content.displayName; +function TabsContent({ className, ...props }: React.ComponentProps) { + return ( + + ); +} export { Tabs, TabsList, TabsTrigger, TabsContent }; diff --git a/src/components/ui/textarea.tsx b/src/components/ui/textarea.tsx index eaf9ffd..f71568c 100644 --- a/src/components/ui/textarea.tsx +++ b/src/components/ui/textarea.tsx @@ -1,27 +1,21 @@ /* - * 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 { cn } from '@/lib/utils'; +import { fieldClasses } from '@/components/ui/fieldClasses'; -const Textarea = React.forwardRef>( - ({ className, ...props }, ref) => { - return ( -