@kinetixui/ui 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +44 -1
- package/dist/index.js +115 -0
- package/package.json +2 -2
- package/src/components/button-group.tsx +71 -0
- package/src/components/native-select.tsx +82 -0
- package/src/index.ts +16 -0
- package/src/stories/ButtonGroup.stories.tsx +32 -0
- package/src/stories/NativeSelect.stories.tsx +33 -0
package/dist/index.d.ts
CHANGED
|
@@ -1252,7 +1252,50 @@ declare const EmptyTitle: React$1.ForwardRefExoticComponent<React$1.HTMLAttribut
|
|
|
1252
1252
|
declare const EmptyDescription: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLParagraphElement> & React$1.RefAttributes<HTMLParagraphElement>>;
|
|
1253
1253
|
declare const EmptyContent: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
|
|
1254
1254
|
|
|
1255
|
+
/**
|
|
1256
|
+
* ButtonGroup — visually joins adjacent buttons into a connected cluster
|
|
1257
|
+
* (segmented-control style): inner corners squared off, shared borders
|
|
1258
|
+
* overlapped by 1px so they don't double up, the focused child raised
|
|
1259
|
+
* above its neighbours so its ring isn't clipped. Gap-fill addition (not
|
|
1260
|
+
* in the original Figma source) — matches the shadcn/ui ButtonGroup API
|
|
1261
|
+
* shape. Works with any child that renders its own border/radius (Button,
|
|
1262
|
+
* ButtonGroupText, a Select trigger, …), not just `<Button>`.
|
|
1263
|
+
*/
|
|
1264
|
+
interface ButtonGroupProps extends React$1.HTMLAttributes<HTMLDivElement> {
|
|
1265
|
+
orientation?: "horizontal" | "vertical";
|
|
1266
|
+
}
|
|
1267
|
+
declare const ButtonGroup: React$1.ForwardRefExoticComponent<ButtonGroupProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
1268
|
+
interface ButtonGroupSeparatorProps extends React$1.HTMLAttributes<HTMLDivElement> {
|
|
1269
|
+
orientation?: "horizontal" | "vertical";
|
|
1270
|
+
}
|
|
1271
|
+
/** A thin divider between segments — useful between non-outline buttons, where the group's own overlap trick has no shared border to lean on. */
|
|
1272
|
+
declare const ButtonGroupSeparator: React$1.ForwardRefExoticComponent<ButtonGroupSeparatorProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
1273
|
+
/** A static, non-interactive label segment inside a group — e.g. a unit or a prefix next to steppers. */
|
|
1274
|
+
declare const ButtonGroupText: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLSpanElement> & React$1.RefAttributes<HTMLSpanElement>>;
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* NativeSelect — a styled wrapper around the native `<select>` element,
|
|
1278
|
+
* for when a form should submit synchronously without JS (or just prefers
|
|
1279
|
+
* the OS-native picker on mobile) instead of Select's Radix popover.
|
|
1280
|
+
* Matches Input's `inputVariants` styling 1:1 so the two are drop-in
|
|
1281
|
+
* interchangeable in a Field. Gap-fill addition (not in the original
|
|
1282
|
+
* Figma source) — matches the shadcn/ui Native Select API shape.
|
|
1283
|
+
*/
|
|
1284
|
+
declare const nativeSelectVariants: (props?: ({
|
|
1285
|
+
state?: "Default" | "Focus" | "Disabled" | "Error" | null | undefined;
|
|
1286
|
+
corners?: "sharp" | "default" | "pill" | "rounded" | null | undefined;
|
|
1287
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
1288
|
+
interface NativeSelectProps extends Omit<React$1.SelectHTMLAttributes<HTMLSelectElement>, "size">, VariantProps<typeof nativeSelectVariants> {
|
|
1289
|
+
}
|
|
1290
|
+
declare const NativeSelect: React$1.ForwardRefExoticComponent<NativeSelectProps & React$1.RefAttributes<HTMLSelectElement>>;
|
|
1291
|
+
interface NativeSelectOptionProps extends React$1.OptionHTMLAttributes<HTMLOptionElement> {
|
|
1292
|
+
}
|
|
1293
|
+
declare const NativeSelectOption: React$1.ForwardRefExoticComponent<NativeSelectOptionProps & React$1.RefAttributes<HTMLOptionElement>>;
|
|
1294
|
+
interface NativeSelectOptGroupProps extends React$1.OptgroupHTMLAttributes<HTMLOptGroupElement> {
|
|
1295
|
+
}
|
|
1296
|
+
declare const NativeSelectOptGroup: React$1.ForwardRefExoticComponent<NativeSelectOptGroupProps & React$1.RefAttributes<HTMLOptGroupElement>>;
|
|
1297
|
+
|
|
1255
1298
|
/** Merges Tailwind class names, resolving conflicts (clsx + tailwind-merge). */
|
|
1256
1299
|
declare function cn(...inputs: ClassValue[]): string;
|
|
1257
1300
|
|
|
1258
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppBar, AppBarActions, AppBarBrand, AppBarLink, type AppBarLinkProps, AppBarNav, AspectRatio, AudioPlayer, type AudioPlayerProps, Avatar, AvatarFallback, AvatarGroup, type AvatarGroupProps, AvatarImage, Badge, type BadgeProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, type ButtonProps, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, CircularProgress, type CircularProgressProps, CodeBlock, type CodeBlockFile, type CodeBlockProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DataTable, DatePicker, type DatePickerProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, type EmptyMediaProps, EmptyTitle, Fab, type FabProps, Field, FieldControl, FieldDescription, FieldLabel, FieldMessage, FileUpload, FileUploadItem, type FileUploadItemProps, type FileUploadProps, Footer, FooterBottom, FooterColumn, type FooterColumnProps, FooterLink, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, HoverCardTrigger, Image, type ImageProps, Inform, type InformProps, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Kbd, KbdGroup, type KbdGroupProps, type KbdProps, Label, List, ListItem, type ListItemProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Metric, type MetricProps, Modal, type ModalProps, type ModalType, NavigationBar, type NavigationBarProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NumberInput, type NumberInputProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PasswordInput, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, Quote, type QuoteProps, RadioGroup, RadioGroupItem, Rating, type RatingProps, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarProvider, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, type SpinnerProps, Stepper, type StepperProps, type StepperStep, Switch, TabBar, TabBarItem, type TabBarItemProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableOfContents, type TableOfContentsProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, type TagProps, Textarea, type TextareaProps, Toaster, type TocItem, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UploadFile, badgeVariants, buttonVariants, cn, emptyMediaVariants, fabVariants, formatBytes, informVariants, inputVariants, messageVariants, navigationMenuTriggerStyle, spinnerVariants, tagVariants, textareaVariants, toggleVariants, useAppBar, useFormField, useSidebar };
|
|
1301
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppBar, AppBarActions, AppBarBrand, AppBarLink, type AppBarLinkProps, AppBarNav, AspectRatio, AudioPlayer, type AudioPlayerProps, Avatar, AvatarFallback, AvatarGroup, type AvatarGroupProps, AvatarImage, Badge, type BadgeProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, type ButtonGroupProps, ButtonGroupSeparator, type ButtonGroupSeparatorProps, ButtonGroupText, type ButtonProps, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, CircularProgress, type CircularProgressProps, CodeBlock, type CodeBlockFile, type CodeBlockProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DataTable, DatePicker, type DatePickerProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, type EmptyMediaProps, EmptyTitle, Fab, type FabProps, Field, FieldControl, FieldDescription, FieldLabel, FieldMessage, FileUpload, FileUploadItem, type FileUploadItemProps, type FileUploadProps, Footer, FooterBottom, FooterColumn, type FooterColumnProps, FooterLink, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, HoverCardTrigger, Image, type ImageProps, Inform, type InformProps, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Kbd, KbdGroup, type KbdGroupProps, type KbdProps, Label, List, ListItem, type ListItemProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Metric, type MetricProps, Modal, type ModalProps, type ModalType, NativeSelect, NativeSelectOptGroup, type NativeSelectOptGroupProps, NativeSelectOption, type NativeSelectOptionProps, type NativeSelectProps, NavigationBar, type NavigationBarProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NumberInput, type NumberInputProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PasswordInput, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, Quote, type QuoteProps, RadioGroup, RadioGroupItem, Rating, type RatingProps, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarProvider, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, type SpinnerProps, Stepper, type StepperProps, type StepperStep, Switch, TabBar, TabBarItem, type TabBarItemProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableOfContents, type TableOfContentsProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, type TagProps, Textarea, type TextareaProps, Toaster, type TocItem, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UploadFile, badgeVariants, buttonVariants, cn, emptyMediaVariants, fabVariants, formatBytes, informVariants, inputVariants, messageVariants, nativeSelectVariants, navigationMenuTriggerStyle, spinnerVariants, tagVariants, textareaVariants, toggleVariants, useAppBar, useFormField, useSidebar };
|
package/dist/index.js
CHANGED
|
@@ -3935,6 +3935,114 @@ var EmptyContent = React67.forwardRef(
|
|
|
3935
3935
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx72("div", { ref, className: cn("flex flex-col items-center gap-3", className), ...props })
|
|
3936
3936
|
);
|
|
3937
3937
|
EmptyContent.displayName = "EmptyContent";
|
|
3938
|
+
|
|
3939
|
+
// src/components/button-group.tsx
|
|
3940
|
+
import * as React68 from "react";
|
|
3941
|
+
import { jsx as jsx73 } from "react/jsx-runtime";
|
|
3942
|
+
var ButtonGroup = React68.forwardRef(
|
|
3943
|
+
({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ jsx73(
|
|
3944
|
+
"div",
|
|
3945
|
+
{
|
|
3946
|
+
ref,
|
|
3947
|
+
role: "group",
|
|
3948
|
+
"data-orientation": orientation,
|
|
3949
|
+
className: cn(
|
|
3950
|
+
"flex w-fit items-stretch [&>*]:relative [&>*]:focus-visible:z-10",
|
|
3951
|
+
orientation === "horizontal" ? "flex-row [&>*:not(:first-child)]:-ml-px [&>*:not(:first-child)]:rounded-l-none [&>*:not(:last-child)]:rounded-r-none" : "flex-col [&>*:not(:first-child)]:-mt-px [&>*:not(:first-child)]:rounded-t-none [&>*:not(:last-child)]:rounded-b-none",
|
|
3952
|
+
className
|
|
3953
|
+
),
|
|
3954
|
+
...props
|
|
3955
|
+
}
|
|
3956
|
+
)
|
|
3957
|
+
);
|
|
3958
|
+
ButtonGroup.displayName = "ButtonGroup";
|
|
3959
|
+
var ButtonGroupSeparator = React68.forwardRef(
|
|
3960
|
+
({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx73(
|
|
3961
|
+
"div",
|
|
3962
|
+
{
|
|
3963
|
+
ref,
|
|
3964
|
+
role: "separator",
|
|
3965
|
+
"aria-orientation": orientation,
|
|
3966
|
+
className: cn("shrink-0 self-stretch bg-border", orientation === "vertical" ? "my-1.5 w-px" : "mx-1.5 h-px", className),
|
|
3967
|
+
...props
|
|
3968
|
+
}
|
|
3969
|
+
)
|
|
3970
|
+
);
|
|
3971
|
+
ButtonGroupSeparator.displayName = "ButtonGroupSeparator";
|
|
3972
|
+
var ButtonGroupText = React68.forwardRef(
|
|
3973
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx73(
|
|
3974
|
+
"span",
|
|
3975
|
+
{
|
|
3976
|
+
ref,
|
|
3977
|
+
className: cn(
|
|
3978
|
+
"flex items-center gap-1.5 rounded-md border border-input bg-muted px-3 text-label-md text-foreground",
|
|
3979
|
+
className
|
|
3980
|
+
),
|
|
3981
|
+
...props
|
|
3982
|
+
}
|
|
3983
|
+
)
|
|
3984
|
+
);
|
|
3985
|
+
ButtonGroupText.displayName = "ButtonGroupText";
|
|
3986
|
+
|
|
3987
|
+
// src/components/native-select.tsx
|
|
3988
|
+
import * as React69 from "react";
|
|
3989
|
+
import { ChevronDown as ChevronDown4 } from "lucide-react";
|
|
3990
|
+
import { cva as cva19 } from "class-variance-authority";
|
|
3991
|
+
import { jsx as jsx74, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
3992
|
+
var nativeSelectVariants = cva19(
|
|
3993
|
+
[
|
|
3994
|
+
"flex w-full appearance-none border border-input bg-background px-3 py-3 pr-9",
|
|
3995
|
+
"font-sans text-[14px] leading-5 tracking-[0.25px] text-foreground",
|
|
3996
|
+
"outline-none transition-colors",
|
|
3997
|
+
"focus-visible:border-primary focus-visible:shadow-focus",
|
|
3998
|
+
"disabled:cursor-not-allowed disabled:opacity-disabled",
|
|
3999
|
+
"aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive aria-[invalid=true]:focus-visible:shadow-focus-destructive"
|
|
4000
|
+
],
|
|
4001
|
+
{
|
|
4002
|
+
variants: {
|
|
4003
|
+
state: {
|
|
4004
|
+
Default: "",
|
|
4005
|
+
Focus: "border-primary shadow-focus",
|
|
4006
|
+
Error: "border-destructive",
|
|
4007
|
+
Disabled: "opacity-disabled pointer-events-none"
|
|
4008
|
+
},
|
|
4009
|
+
corners: {
|
|
4010
|
+
sharp: "rounded-none",
|
|
4011
|
+
default: "rounded-sm",
|
|
4012
|
+
rounded: "rounded-md",
|
|
4013
|
+
pill: "rounded-full px-4"
|
|
4014
|
+
}
|
|
4015
|
+
},
|
|
4016
|
+
defaultVariants: { state: "Default", corners: "default" }
|
|
4017
|
+
}
|
|
4018
|
+
);
|
|
4019
|
+
var NativeSelect = React69.forwardRef(
|
|
4020
|
+
({ className, state, corners, disabled, "aria-invalid": ariaInvalid, children, ...props }, ref) => /* @__PURE__ */ jsxs41("div", { className: "relative", children: [
|
|
4021
|
+
/* @__PURE__ */ jsx74(
|
|
4022
|
+
"select",
|
|
4023
|
+
{
|
|
4024
|
+
ref,
|
|
4025
|
+
"data-slot": "native-select",
|
|
4026
|
+
"data-state": state ? state.toLowerCase() : void 0,
|
|
4027
|
+
"aria-invalid": ariaInvalid ?? (state === "Error" || void 0),
|
|
4028
|
+
disabled: disabled || state === "Disabled",
|
|
4029
|
+
className: cn(nativeSelectVariants({ state, corners }), className),
|
|
4030
|
+
...props,
|
|
4031
|
+
children
|
|
4032
|
+
}
|
|
4033
|
+
),
|
|
4034
|
+
/* @__PURE__ */ jsx74(ChevronDown4, { className: "pointer-events-none absolute right-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" })
|
|
4035
|
+
] })
|
|
4036
|
+
);
|
|
4037
|
+
NativeSelect.displayName = "NativeSelect";
|
|
4038
|
+
var NativeSelectOption = React69.forwardRef(
|
|
4039
|
+
({ ...props }, ref) => /* @__PURE__ */ jsx74("option", { ref, ...props })
|
|
4040
|
+
);
|
|
4041
|
+
NativeSelectOption.displayName = "NativeSelectOption";
|
|
4042
|
+
var NativeSelectOptGroup = React69.forwardRef(
|
|
4043
|
+
({ ...props }, ref) => /* @__PURE__ */ jsx74("optgroup", { ref, ...props })
|
|
4044
|
+
);
|
|
4045
|
+
NativeSelectOptGroup.displayName = "NativeSelectOptGroup";
|
|
3938
4046
|
export {
|
|
3939
4047
|
Accordion,
|
|
3940
4048
|
AccordionContent,
|
|
@@ -3974,6 +4082,9 @@ export {
|
|
|
3974
4082
|
BreadcrumbPage,
|
|
3975
4083
|
BreadcrumbSeparator,
|
|
3976
4084
|
Button,
|
|
4085
|
+
ButtonGroup,
|
|
4086
|
+
ButtonGroupSeparator,
|
|
4087
|
+
ButtonGroupText,
|
|
3977
4088
|
Calendar,
|
|
3978
4089
|
Card,
|
|
3979
4090
|
CardContent,
|
|
@@ -4122,6 +4233,9 @@ export {
|
|
|
4122
4233
|
MenubarTrigger,
|
|
4123
4234
|
Metric,
|
|
4124
4235
|
Modal,
|
|
4236
|
+
NativeSelect,
|
|
4237
|
+
NativeSelectOptGroup,
|
|
4238
|
+
NativeSelectOption,
|
|
4125
4239
|
NavigationBar,
|
|
4126
4240
|
NavigationMenu,
|
|
4127
4241
|
NavigationMenuContent,
|
|
@@ -4228,6 +4342,7 @@ export {
|
|
|
4228
4342
|
informVariants,
|
|
4229
4343
|
inputVariants,
|
|
4230
4344
|
messageVariants,
|
|
4345
|
+
nativeSelectVariants,
|
|
4231
4346
|
navigationMenuTriggerStyle,
|
|
4232
4347
|
spinnerVariants,
|
|
4233
4348
|
tagVariants,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kinetixui/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "KinetixUI React components — CVA + Radix + Tailwind on the KinetixUI token contract. Also distributed via the kinetixui CLI as a component registry.",
|
|
6
6
|
"keywords": [
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"react-dom": ">=18"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
|
-
"@kinetixui/tokens": "0.
|
|
93
|
+
"@kinetixui/tokens": "0.9.0",
|
|
94
94
|
"@testing-library/jest-dom": "^7.0.1",
|
|
95
95
|
"@testing-library/react": "^16.3.3",
|
|
96
96
|
"@testing-library/user-event": "^14.6.7",
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ButtonGroup — visually joins adjacent buttons into a connected cluster
|
|
8
|
+
* (segmented-control style): inner corners squared off, shared borders
|
|
9
|
+
* overlapped by 1px so they don't double up, the focused child raised
|
|
10
|
+
* above its neighbours so its ring isn't clipped. Gap-fill addition (not
|
|
11
|
+
* in the original Figma source) — matches the shadcn/ui ButtonGroup API
|
|
12
|
+
* shape. Works with any child that renders its own border/radius (Button,
|
|
13
|
+
* ButtonGroupText, a Select trigger, …), not just `<Button>`.
|
|
14
|
+
*/
|
|
15
|
+
export interface ButtonGroupProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
16
|
+
orientation?: "horizontal" | "vertical";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const ButtonGroup = React.forwardRef<HTMLDivElement, ButtonGroupProps>(
|
|
20
|
+
({ className, orientation = "horizontal", ...props }, ref) => (
|
|
21
|
+
<div
|
|
22
|
+
ref={ref}
|
|
23
|
+
role="group"
|
|
24
|
+
data-orientation={orientation}
|
|
25
|
+
className={cn(
|
|
26
|
+
"flex w-fit items-stretch [&>*]:relative [&>*]:focus-visible:z-10",
|
|
27
|
+
orientation === "horizontal"
|
|
28
|
+
? "flex-row [&>*:not(:first-child)]:-ml-px [&>*:not(:first-child)]:rounded-l-none [&>*:not(:last-child)]:rounded-r-none"
|
|
29
|
+
: "flex-col [&>*:not(:first-child)]:-mt-px [&>*:not(:first-child)]:rounded-t-none [&>*:not(:last-child)]:rounded-b-none",
|
|
30
|
+
className,
|
|
31
|
+
)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
),
|
|
35
|
+
);
|
|
36
|
+
ButtonGroup.displayName = "ButtonGroup";
|
|
37
|
+
|
|
38
|
+
export interface ButtonGroupSeparatorProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
39
|
+
orientation?: "horizontal" | "vertical";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** A thin divider between segments — useful between non-outline buttons, where the group's own overlap trick has no shared border to lean on. */
|
|
43
|
+
const ButtonGroupSeparator = React.forwardRef<HTMLDivElement, ButtonGroupSeparatorProps>(
|
|
44
|
+
({ className, orientation = "vertical", ...props }, ref) => (
|
|
45
|
+
<div
|
|
46
|
+
ref={ref}
|
|
47
|
+
role="separator"
|
|
48
|
+
aria-orientation={orientation}
|
|
49
|
+
className={cn("shrink-0 self-stretch bg-border", orientation === "vertical" ? "my-1.5 w-px" : "mx-1.5 h-px", className)}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
),
|
|
53
|
+
);
|
|
54
|
+
ButtonGroupSeparator.displayName = "ButtonGroupSeparator";
|
|
55
|
+
|
|
56
|
+
/** A static, non-interactive label segment inside a group — e.g. a unit or a prefix next to steppers. */
|
|
57
|
+
const ButtonGroupText = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(
|
|
58
|
+
({ className, ...props }, ref) => (
|
|
59
|
+
<span
|
|
60
|
+
ref={ref}
|
|
61
|
+
className={cn(
|
|
62
|
+
"flex items-center gap-1.5 rounded-md border border-input bg-muted px-3 text-label-md text-foreground",
|
|
63
|
+
className,
|
|
64
|
+
)}
|
|
65
|
+
{...props}
|
|
66
|
+
/>
|
|
67
|
+
),
|
|
68
|
+
);
|
|
69
|
+
ButtonGroupText.displayName = "ButtonGroupText";
|
|
70
|
+
|
|
71
|
+
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { ChevronDown } from "lucide-react";
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
6
|
+
import { cn } from "../lib/utils";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* NativeSelect — a styled wrapper around the native `<select>` element,
|
|
10
|
+
* for when a form should submit synchronously without JS (or just prefers
|
|
11
|
+
* the OS-native picker on mobile) instead of Select's Radix popover.
|
|
12
|
+
* Matches Input's `inputVariants` styling 1:1 so the two are drop-in
|
|
13
|
+
* interchangeable in a Field. Gap-fill addition (not in the original
|
|
14
|
+
* Figma source) — matches the shadcn/ui Native Select API shape.
|
|
15
|
+
*/
|
|
16
|
+
const nativeSelectVariants = cva(
|
|
17
|
+
[
|
|
18
|
+
"flex w-full appearance-none border border-input bg-background px-3 py-3 pr-9",
|
|
19
|
+
"font-sans text-[14px] leading-5 tracking-[0.25px] text-foreground",
|
|
20
|
+
"outline-none transition-colors",
|
|
21
|
+
"focus-visible:border-primary focus-visible:shadow-focus",
|
|
22
|
+
"disabled:cursor-not-allowed disabled:opacity-disabled",
|
|
23
|
+
"aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive aria-[invalid=true]:focus-visible:shadow-focus-destructive",
|
|
24
|
+
],
|
|
25
|
+
{
|
|
26
|
+
variants: {
|
|
27
|
+
state: {
|
|
28
|
+
Default: "",
|
|
29
|
+
Focus: "border-primary shadow-focus",
|
|
30
|
+
Error: "border-destructive",
|
|
31
|
+
Disabled: "opacity-disabled pointer-events-none",
|
|
32
|
+
},
|
|
33
|
+
corners: {
|
|
34
|
+
sharp: "rounded-none",
|
|
35
|
+
default: "rounded-sm",
|
|
36
|
+
rounded: "rounded-md",
|
|
37
|
+
pill: "rounded-full px-4",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
defaultVariants: { state: "Default", corners: "default" },
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export interface NativeSelectProps
|
|
45
|
+
extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, "size">,
|
|
46
|
+
VariantProps<typeof nativeSelectVariants> {}
|
|
47
|
+
|
|
48
|
+
const NativeSelect = React.forwardRef<HTMLSelectElement, NativeSelectProps>(
|
|
49
|
+
({ className, state, corners, disabled, "aria-invalid": ariaInvalid, children, ...props }, ref) => (
|
|
50
|
+
<div className="relative">
|
|
51
|
+
<select
|
|
52
|
+
ref={ref}
|
|
53
|
+
data-slot="native-select"
|
|
54
|
+
data-state={state ? state.toLowerCase() : undefined}
|
|
55
|
+
aria-invalid={ariaInvalid ?? (state === "Error" || undefined)}
|
|
56
|
+
disabled={disabled || state === "Disabled"}
|
|
57
|
+
className={cn(nativeSelectVariants({ state, corners }), className)}
|
|
58
|
+
{...props}
|
|
59
|
+
>
|
|
60
|
+
{children}
|
|
61
|
+
</select>
|
|
62
|
+
<ChevronDown className="pointer-events-none absolute right-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
|
|
63
|
+
</div>
|
|
64
|
+
),
|
|
65
|
+
);
|
|
66
|
+
NativeSelect.displayName = "NativeSelect";
|
|
67
|
+
|
|
68
|
+
export interface NativeSelectOptionProps extends React.OptionHTMLAttributes<HTMLOptionElement> {}
|
|
69
|
+
|
|
70
|
+
const NativeSelectOption = React.forwardRef<HTMLOptionElement, NativeSelectOptionProps>(
|
|
71
|
+
({ ...props }, ref) => <option ref={ref} {...props} />,
|
|
72
|
+
);
|
|
73
|
+
NativeSelectOption.displayName = "NativeSelectOption";
|
|
74
|
+
|
|
75
|
+
export interface NativeSelectOptGroupProps extends React.OptgroupHTMLAttributes<HTMLOptGroupElement> {}
|
|
76
|
+
|
|
77
|
+
const NativeSelectOptGroup = React.forwardRef<HTMLOptGroupElement, NativeSelectOptGroupProps>(
|
|
78
|
+
({ ...props }, ref) => <optgroup ref={ref} {...props} />,
|
|
79
|
+
);
|
|
80
|
+
NativeSelectOptGroup.displayName = "NativeSelectOptGroup";
|
|
81
|
+
|
|
82
|
+
export { NativeSelect, NativeSelectOption, NativeSelectOptGroup, nativeSelectVariants };
|
package/src/index.ts
CHANGED
|
@@ -323,5 +323,21 @@ export {
|
|
|
323
323
|
emptyMediaVariants,
|
|
324
324
|
type EmptyMediaProps,
|
|
325
325
|
} from "./components/empty";
|
|
326
|
+
export {
|
|
327
|
+
ButtonGroup,
|
|
328
|
+
ButtonGroupSeparator,
|
|
329
|
+
ButtonGroupText,
|
|
330
|
+
type ButtonGroupProps,
|
|
331
|
+
type ButtonGroupSeparatorProps,
|
|
332
|
+
} from "./components/button-group";
|
|
333
|
+
export {
|
|
334
|
+
NativeSelect,
|
|
335
|
+
NativeSelectOption,
|
|
336
|
+
NativeSelectOptGroup,
|
|
337
|
+
nativeSelectVariants,
|
|
338
|
+
type NativeSelectProps,
|
|
339
|
+
type NativeSelectOptionProps,
|
|
340
|
+
type NativeSelectOptGroupProps,
|
|
341
|
+
} from "./components/native-select";
|
|
326
342
|
|
|
327
343
|
export { cn } from "./lib/utils";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
|
|
2
|
+
Source of truth: apps/web/src/registry/demos.tsx */
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
5
|
+
import { Button, ButtonGroup } from "@kinetixui/ui";
|
|
6
|
+
import { Bold, Italic, Underline } from "lucide-react";
|
|
7
|
+
|
|
8
|
+
const Demo = () => (
|
|
9
|
+
<ButtonGroup>
|
|
10
|
+
<Button variant="Outline" size="icon" aria-label="Bold">
|
|
11
|
+
<Bold />
|
|
12
|
+
</Button>
|
|
13
|
+
<Button variant="Outline" size="icon" aria-label="Italic">
|
|
14
|
+
<Italic />
|
|
15
|
+
</Button>
|
|
16
|
+
<Button variant="Outline" size="icon" aria-label="Underline">
|
|
17
|
+
<Underline />
|
|
18
|
+
</Button>
|
|
19
|
+
</ButtonGroup>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const meta = {
|
|
23
|
+
title: "Controls & Actions/ButtonGroup",
|
|
24
|
+
parameters: {
|
|
25
|
+
layout: "centered",
|
|
26
|
+
docs: { source: { code: "<ButtonGroup>\\n <Button variant=\"Outline\" size=\"icon\"><Bold /></Button>\\n <Button variant=\"Outline\" size=\"icon\"><Italic /></Button>\\n <Button variant=\"Outline\" size=\"icon\"><Underline /></Button>\\n</ButtonGroup>", language: "tsx" } },
|
|
27
|
+
},
|
|
28
|
+
} satisfies Meta;
|
|
29
|
+
|
|
30
|
+
export default meta;
|
|
31
|
+
|
|
32
|
+
export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
|
|
2
|
+
Source of truth: apps/web/src/registry/demos.tsx */
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
5
|
+
import { NativeSelect, NativeSelectOptGroup, NativeSelectOption, Select } from "@kinetixui/ui";
|
|
6
|
+
|
|
7
|
+
const Demo = () => (
|
|
8
|
+
<NativeSelect className="max-w-xs" defaultValue="">
|
|
9
|
+
<NativeSelectOption value="" disabled>
|
|
10
|
+
Select a fruit…
|
|
11
|
+
</NativeSelectOption>
|
|
12
|
+
<NativeSelectOptGroup label="Citrus">
|
|
13
|
+
<NativeSelectOption value="orange">Orange</NativeSelectOption>
|
|
14
|
+
<NativeSelectOption value="lemon">Lemon</NativeSelectOption>
|
|
15
|
+
</NativeSelectOptGroup>
|
|
16
|
+
<NativeSelectOptGroup label="Stone fruit">
|
|
17
|
+
<NativeSelectOption value="peach">Peach</NativeSelectOption>
|
|
18
|
+
<NativeSelectOption value="plum">Plum</NativeSelectOption>
|
|
19
|
+
</NativeSelectOptGroup>
|
|
20
|
+
</NativeSelect>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const meta = {
|
|
24
|
+
title: "Form Inputs/NativeSelect",
|
|
25
|
+
parameters: {
|
|
26
|
+
layout: "centered",
|
|
27
|
+
docs: { source: { code: "<NativeSelect defaultValue=\"\">\\n <NativeSelectOption value=\"\" disabled>Select a fruit…</NativeSelectOption>\\n <NativeSelectOptGroup label=\"Citrus\">\\n <NativeSelectOption value=\"orange\">Orange</NativeSelectOption>\\n </NativeSelectOptGroup>\\n</NativeSelect>", language: "tsx" } },
|
|
28
|
+
},
|
|
29
|
+
} satisfies Meta;
|
|
30
|
+
|
|
31
|
+
export default meta;
|
|
32
|
+
|
|
33
|
+
export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
|