@beemafrica/ui 0.1.5 → 0.1.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beemafrica/ui",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Shared Beem UI components built on shadcn/Radix",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -22,6 +22,7 @@
22
22
  "@tanstack/react-table": "^9.1.2",
23
23
  "class-variance-authority": "^0.7.1",
24
24
  "clsx": "^2.1.1",
25
+ "cmdk": "^1.1.1",
25
26
  "lucide-react": "^1.31.0",
26
27
  "next-themes": "^0.4.6",
27
28
  "radix-ui": "^1.6.7",
@@ -0,0 +1,49 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { Slot } from "radix-ui"
4
+
5
+ import { cn } from "@beemafrica/ui/lib/utils"
6
+
7
+ const badgeVariants = cva(
8
+ "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
13
+ secondary:
14
+ "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
15
+ destructive:
16
+ "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
17
+ outline:
18
+ "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
19
+ ghost:
20
+ "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
21
+ link: "text-primary underline-offset-4 hover:underline",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: "default",
26
+ },
27
+ }
28
+ )
29
+
30
+ function Badge({
31
+ className,
32
+ variant = "default",
33
+ asChild = false,
34
+ ...props
35
+ }: React.ComponentProps<"span"> &
36
+ VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
37
+ const Comp = asChild ? Slot.Root : "span"
38
+
39
+ return (
40
+ <Comp
41
+ data-slot="badge"
42
+ data-variant={variant}
43
+ className={cn(badgeVariants({ variant }), className)}
44
+ {...props}
45
+ />
46
+ )
47
+ }
48
+
49
+ export { Badge, badgeVariants }
@@ -0,0 +1,195 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Command as CommandPrimitive } from "cmdk"
5
+
6
+ import { cn } from "@beemafrica/ui/lib/utils"
7
+ import {
8
+ Dialog,
9
+ DialogContent,
10
+ DialogDescription,
11
+ DialogHeader,
12
+ DialogTitle,
13
+ } from "@beemafrica/ui/components/dialog"
14
+ import {
15
+ InputGroup,
16
+ InputGroupAddon,
17
+ } from "@beemafrica/ui/components/input-group"
18
+ import { SearchIcon, CheckIcon } from "lucide-react"
19
+
20
+ function Command({
21
+ className,
22
+ ...props
23
+ }: React.ComponentProps<typeof CommandPrimitive>) {
24
+ return (
25
+ <CommandPrimitive
26
+ data-slot="command"
27
+ className={cn(
28
+ "flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground",
29
+ className
30
+ )}
31
+ {...props}
32
+ />
33
+ )
34
+ }
35
+
36
+ function CommandDialog({
37
+ title = "Command Palette",
38
+ description = "Search for a command to run...",
39
+ children,
40
+ className,
41
+ showCloseButton = false,
42
+ ...props
43
+ }: React.ComponentProps<typeof Dialog> & {
44
+ title?: string
45
+ description?: string
46
+ className?: string
47
+ showCloseButton?: boolean
48
+ }) {
49
+ return (
50
+ <Dialog {...props}>
51
+ <DialogHeader className="sr-only">
52
+ <DialogTitle>{title}</DialogTitle>
53
+ <DialogDescription>{description}</DialogDescription>
54
+ </DialogHeader>
55
+ <DialogContent
56
+ className={cn(
57
+ "top-1/3 translate-y-0 overflow-hidden rounded-xl! p-0",
58
+ className
59
+ )}
60
+ showCloseButton={showCloseButton}
61
+ >
62
+ {children}
63
+ </DialogContent>
64
+ </Dialog>
65
+ )
66
+ }
67
+
68
+ function CommandInput({
69
+ className,
70
+ ...props
71
+ }: React.ComponentProps<typeof CommandPrimitive.Input>) {
72
+ return (
73
+ <div data-slot="command-input-wrapper" className="p-1 pb-0">
74
+ <InputGroup className="h-8! rounded-lg! border-input/30 bg-input/30 shadow-none! *:data-[slot=input-group-addon]:ps-2!">
75
+ <CommandPrimitive.Input
76
+ data-slot="command-input"
77
+ className={cn(
78
+ "w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
79
+ className
80
+ )}
81
+ {...props}
82
+ />
83
+ <InputGroupAddon>
84
+ <SearchIcon className="size-4 shrink-0 opacity-50" />
85
+ </InputGroupAddon>
86
+ </InputGroup>
87
+ </div>
88
+ )
89
+ }
90
+
91
+ function CommandList({
92
+ className,
93
+ ...props
94
+ }: React.ComponentProps<typeof CommandPrimitive.List>) {
95
+ return (
96
+ <CommandPrimitive.List
97
+ data-slot="command-list"
98
+ className={cn(
99
+ "no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none",
100
+ className
101
+ )}
102
+ {...props}
103
+ />
104
+ )
105
+ }
106
+
107
+ function CommandEmpty({
108
+ className,
109
+ ...props
110
+ }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
111
+ return (
112
+ <CommandPrimitive.Empty
113
+ data-slot="command-empty"
114
+ className={cn("py-6 text-center text-sm", className)}
115
+ {...props}
116
+ />
117
+ )
118
+ }
119
+
120
+ function CommandGroup({
121
+ className,
122
+ ...props
123
+ }: React.ComponentProps<typeof CommandPrimitive.Group>) {
124
+ return (
125
+ <CommandPrimitive.Group
126
+ data-slot="command-group"
127
+ className={cn(
128
+ "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",
129
+ className
130
+ )}
131
+ {...props}
132
+ />
133
+ )
134
+ }
135
+
136
+ function CommandSeparator({
137
+ className,
138
+ ...props
139
+ }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
140
+ return (
141
+ <CommandPrimitive.Separator
142
+ data-slot="command-separator"
143
+ className={cn("-mx-1 h-px bg-border", className)}
144
+ {...props}
145
+ />
146
+ )
147
+ }
148
+
149
+ function CommandItem({
150
+ className,
151
+ children,
152
+ ...props
153
+ }: React.ComponentProps<typeof CommandPrimitive.Item>) {
154
+ return (
155
+ <CommandPrimitive.Item
156
+ data-slot="command-item"
157
+ className={cn(
158
+ "group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-muted data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-selected:*:[svg]:text-foreground",
159
+ className
160
+ )}
161
+ {...props}
162
+ >
163
+ {children}
164
+ <CheckIcon className="ms-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
165
+ </CommandPrimitive.Item>
166
+ )
167
+ }
168
+
169
+ function CommandShortcut({
170
+ className,
171
+ ...props
172
+ }: React.ComponentProps<"span">) {
173
+ return (
174
+ <span
175
+ data-slot="command-shortcut"
176
+ className={cn(
177
+ "ms-auto text-xs tracking-widest text-muted-foreground group-data-selected/command-item:text-foreground",
178
+ className
179
+ )}
180
+ {...props}
181
+ />
182
+ )
183
+ }
184
+
185
+ export {
186
+ Command,
187
+ CommandDialog,
188
+ CommandInput,
189
+ CommandList,
190
+ CommandEmpty,
191
+ CommandGroup,
192
+ CommandItem,
193
+ CommandShortcut,
194
+ CommandSeparator,
195
+ }
@@ -0,0 +1,156 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+
6
+ import { cn } from "@beemafrica/ui/lib/utils"
7
+ import { Button } from "@beemafrica/ui/components/button"
8
+ import { Input } from "@beemafrica/ui/components/input"
9
+ import { Textarea } from "@beemafrica/ui/components/textarea"
10
+
11
+ function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
12
+ return (
13
+ <div
14
+ data-slot="input-group"
15
+ role="group"
16
+ className={cn(
17
+ "group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pe-1.5 has-[>[data-align=inline-start]]:[&>input]:ps-1.5",
18
+ className
19
+ )}
20
+ {...props}
21
+ />
22
+ )
23
+ }
24
+
25
+ const inputGroupAddonVariants = cva(
26
+ "flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
27
+ {
28
+ variants: {
29
+ align: {
30
+ "inline-start":
31
+ "order-first ps-2 has-[>button]:ms-[-0.3rem] has-[>kbd]:ms-[-0.15rem]",
32
+ "inline-end":
33
+ "order-last pe-2 has-[>button]:me-[-0.3rem] has-[>kbd]:me-[-0.15rem]",
34
+ "block-start":
35
+ "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
36
+ "block-end":
37
+ "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2",
38
+ },
39
+ },
40
+ defaultVariants: {
41
+ align: "inline-start",
42
+ },
43
+ }
44
+ )
45
+
46
+ function InputGroupAddon({
47
+ className,
48
+ align = "inline-start",
49
+ ...props
50
+ }: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) {
51
+ return (
52
+ <div
53
+ role="group"
54
+ data-slot="input-group-addon"
55
+ data-align={align}
56
+ className={cn(inputGroupAddonVariants({ align }), className)}
57
+ onClick={(e) => {
58
+ if ((e.target as HTMLElement).closest("button")) {
59
+ return
60
+ }
61
+ e.currentTarget.parentElement?.querySelector("input")?.focus()
62
+ }}
63
+ {...props}
64
+ />
65
+ )
66
+ }
67
+
68
+ const inputGroupButtonVariants = cva(
69
+ "flex items-center gap-2 text-sm shadow-none",
70
+ {
71
+ variants: {
72
+ size: {
73
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
74
+ sm: "",
75
+ "icon-xs":
76
+ "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0",
77
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0",
78
+ },
79
+ },
80
+ defaultVariants: {
81
+ size: "xs",
82
+ },
83
+ }
84
+ )
85
+
86
+ function InputGroupButton({
87
+ className,
88
+ type = "button",
89
+ variant = "ghost",
90
+ size = "xs",
91
+ ...props
92
+ }: Omit<React.ComponentProps<typeof Button>, "size"> &
93
+ VariantProps<typeof inputGroupButtonVariants>) {
94
+ return (
95
+ <Button
96
+ type={type}
97
+ data-size={size}
98
+ variant={variant}
99
+ className={cn(inputGroupButtonVariants({ size }), className)}
100
+ {...props}
101
+ />
102
+ )
103
+ }
104
+
105
+ function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
106
+ return (
107
+ <span
108
+ className={cn(
109
+ "flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
110
+ className
111
+ )}
112
+ {...props}
113
+ />
114
+ )
115
+ }
116
+
117
+ function InputGroupInput({
118
+ className,
119
+ ...props
120
+ }: React.ComponentProps<"input">) {
121
+ return (
122
+ <Input
123
+ data-slot="input-group-control"
124
+ className={cn(
125
+ "flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent",
126
+ className
127
+ )}
128
+ {...props}
129
+ />
130
+ )
131
+ }
132
+
133
+ function InputGroupTextarea({
134
+ className,
135
+ ...props
136
+ }: React.ComponentProps<"textarea">) {
137
+ return (
138
+ <Textarea
139
+ data-slot="input-group-control"
140
+ className={cn(
141
+ "flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent",
142
+ className
143
+ )}
144
+ {...props}
145
+ />
146
+ )
147
+ }
148
+
149
+ export {
150
+ InputGroup,
151
+ InputGroupAddon,
152
+ InputGroupButton,
153
+ InputGroupText,
154
+ InputGroupInput,
155
+ InputGroupTextarea,
156
+ }