myoperator-ui 0.0.40 → 0.0.42
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.js +553 -394
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -54,11 +54,27 @@ function prefixTailwindClasses(content, prefix) {
|
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
async function getRegistry(prefix = "") {
|
|
57
|
-
|
|
57
|
+
return {
|
|
58
|
+
"badge": {
|
|
59
|
+
name: "badge",
|
|
60
|
+
description: "A status badge component with active, failed, and disabled variants",
|
|
61
|
+
dependencies: [
|
|
62
|
+
"class-variance-authority",
|
|
63
|
+
"clsx",
|
|
64
|
+
"tailwind-merge"
|
|
65
|
+
],
|
|
66
|
+
files: [
|
|
67
|
+
{
|
|
68
|
+
name: "badge.tsx",
|
|
69
|
+
content: prefixTailwindClasses(`import * as React from "react"
|
|
58
70
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
59
71
|
|
|
60
72
|
import { cn } from "@/lib/utils"
|
|
61
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Badge variants for status indicators.
|
|
76
|
+
* Pill-shaped badges with different colors for different states.
|
|
77
|
+
*/
|
|
62
78
|
const badgeVariants = cva(
|
|
63
79
|
"inline-flex items-center justify-center rounded-full text-sm font-semibold transition-colors whitespace-nowrap",
|
|
64
80
|
{
|
|
@@ -82,10 +98,23 @@ const badgeVariants = cva(
|
|
|
82
98
|
}
|
|
83
99
|
)
|
|
84
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Badge component for displaying status indicators.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* \`\`\`tsx
|
|
106
|
+
* <Badge variant="active">Active</Badge>
|
|
107
|
+
* <Badge variant="failed">Failed</Badge>
|
|
108
|
+
* <Badge variant="disabled">Disabled</Badge>
|
|
109
|
+
* <Badge variant="active" leftIcon={<CheckIcon />}>Active</Badge>
|
|
110
|
+
* \`\`\`
|
|
111
|
+
*/
|
|
85
112
|
export interface BadgeProps
|
|
86
113
|
extends React.HTMLAttributes<HTMLDivElement>,
|
|
87
114
|
VariantProps<typeof badgeVariants> {
|
|
115
|
+
/** Icon displayed on the left side of the badge text */
|
|
88
116
|
leftIcon?: React.ReactNode
|
|
117
|
+
/** Icon displayed on the right side of the badge text */
|
|
89
118
|
rightIcon?: React.ReactNode
|
|
90
119
|
}
|
|
91
120
|
|
|
@@ -107,199 +136,499 @@ const Badge = React.forwardRef<HTMLDivElement, BadgeProps>(
|
|
|
107
136
|
Badge.displayName = "Badge"
|
|
108
137
|
|
|
109
138
|
export { Badge, badgeVariants }
|
|
110
|
-
`, prefix)
|
|
111
|
-
|
|
139
|
+
`, prefix)
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
"button": {
|
|
144
|
+
name: "button",
|
|
145
|
+
description: "A customizable button component with variants, sizes, and icons",
|
|
146
|
+
dependencies: [
|
|
147
|
+
"@radix-ui/react-slot",
|
|
148
|
+
"class-variance-authority",
|
|
149
|
+
"clsx",
|
|
150
|
+
"tailwind-merge",
|
|
151
|
+
"lucide-react"
|
|
152
|
+
],
|
|
153
|
+
files: [
|
|
154
|
+
{
|
|
155
|
+
name: "button.tsx",
|
|
156
|
+
content: prefixTailwindClasses(`import * as React from "react"
|
|
157
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
112
158
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
159
|
+
import { Loader2 } from "lucide-react"
|
|
113
160
|
|
|
114
161
|
import { cn } from "@/lib/utils"
|
|
115
162
|
|
|
116
|
-
const
|
|
117
|
-
"inline-flex items-center justify-center rounded text-sm transition-colors",
|
|
163
|
+
const buttonVariants = cva(
|
|
164
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
118
165
|
{
|
|
119
166
|
variants: {
|
|
120
167
|
variant: {
|
|
121
|
-
default: "bg-[#
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
168
|
+
default: "bg-[#343E55] text-white hover:bg-[#343E55]/90",
|
|
169
|
+
destructive:
|
|
170
|
+
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
171
|
+
outline:
|
|
172
|
+
"border border-[#343E55] bg-transparent text-[#343E55] hover:bg-[#343E55] hover:text-white",
|
|
173
|
+
secondary:
|
|
174
|
+
"bg-[#343E55]/20 text-[#343E55] hover:bg-[#343E55]/30",
|
|
175
|
+
ghost: "hover:bg-[#343E55]/10 hover:text-[#343E55]",
|
|
176
|
+
link: "text-[#343E55] underline-offset-4 hover:underline",
|
|
127
177
|
},
|
|
128
178
|
size: {
|
|
129
|
-
default: "
|
|
130
|
-
sm: "
|
|
131
|
-
lg: "
|
|
132
|
-
|
|
133
|
-
interactive: {
|
|
134
|
-
true: "cursor-pointer hover:bg-[#E5E7EB] active:bg-[#D1D5DB]",
|
|
135
|
-
false: "",
|
|
136
|
-
},
|
|
137
|
-
selected: {
|
|
138
|
-
true: "ring-2 ring-[#343E55] ring-offset-1",
|
|
139
|
-
false: "",
|
|
179
|
+
default: "py-2.5 px-4",
|
|
180
|
+
sm: "py-2 px-3 text-xs",
|
|
181
|
+
lg: "py-3 px-6",
|
|
182
|
+
icon: "p-2.5",
|
|
140
183
|
},
|
|
141
184
|
},
|
|
142
185
|
defaultVariants: {
|
|
143
186
|
variant: "default",
|
|
144
187
|
size: "default",
|
|
145
|
-
interactive: false,
|
|
146
|
-
selected: false,
|
|
147
188
|
},
|
|
148
189
|
}
|
|
149
190
|
)
|
|
150
191
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Button component for user interactions.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* \`\`\`tsx
|
|
197
|
+
* <Button variant="default" size="default">
|
|
198
|
+
* Click me
|
|
199
|
+
* </Button>
|
|
200
|
+
* \`\`\`
|
|
201
|
+
*/
|
|
202
|
+
export interface ButtonProps
|
|
203
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
204
|
+
VariantProps<typeof buttonVariants> {
|
|
205
|
+
/** Render as child element using Radix Slot */
|
|
206
|
+
asChild?: boolean
|
|
207
|
+
/** Icon displayed on the left side of the button text */
|
|
208
|
+
leftIcon?: React.ReactNode
|
|
209
|
+
/** Icon displayed on the right side of the button text */
|
|
210
|
+
rightIcon?: React.ReactNode
|
|
211
|
+
/** Shows loading spinner and disables button */
|
|
212
|
+
loading?: boolean
|
|
213
|
+
/** Text shown during loading state */
|
|
214
|
+
loadingText?: string
|
|
157
215
|
}
|
|
158
216
|
|
|
159
|
-
const
|
|
160
|
-
({
|
|
217
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
218
|
+
({
|
|
219
|
+
className,
|
|
220
|
+
variant,
|
|
221
|
+
size,
|
|
222
|
+
asChild = false,
|
|
223
|
+
leftIcon,
|
|
224
|
+
rightIcon,
|
|
225
|
+
loading = false,
|
|
226
|
+
loadingText,
|
|
227
|
+
children,
|
|
228
|
+
disabled,
|
|
229
|
+
...props
|
|
230
|
+
}, ref) => {
|
|
231
|
+
const Comp = asChild ? Slot : "button"
|
|
232
|
+
|
|
161
233
|
return (
|
|
162
|
-
<
|
|
163
|
-
className={cn(
|
|
234
|
+
<Comp
|
|
235
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
164
236
|
ref={ref}
|
|
165
|
-
|
|
166
|
-
tabIndex={interactive ? 0 : undefined}
|
|
167
|
-
aria-selected={selected}
|
|
237
|
+
disabled={disabled || loading}
|
|
168
238
|
{...props}
|
|
169
239
|
>
|
|
170
|
-
{
|
|
171
|
-
|
|
240
|
+
{loading ? (
|
|
241
|
+
<>
|
|
242
|
+
<Loader2 className="animate-spin" />
|
|
243
|
+
{loadingText || children}
|
|
244
|
+
</>
|
|
245
|
+
) : (
|
|
246
|
+
<>
|
|
247
|
+
{leftIcon}
|
|
248
|
+
{children}
|
|
249
|
+
{rightIcon}
|
|
250
|
+
</>
|
|
172
251
|
)}
|
|
173
|
-
|
|
174
|
-
</span>
|
|
252
|
+
</Comp>
|
|
175
253
|
)
|
|
176
254
|
}
|
|
177
255
|
)
|
|
178
|
-
|
|
256
|
+
Button.displayName = "Button"
|
|
179
257
|
|
|
180
|
-
export {
|
|
181
|
-
`, prefix)
|
|
182
|
-
|
|
183
|
-
|
|
258
|
+
export { Button, buttonVariants }
|
|
259
|
+
`, prefix)
|
|
260
|
+
}
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
"dropdown-menu": {
|
|
264
|
+
name: "dropdown-menu",
|
|
265
|
+
description: "A dropdown menu component for displaying actions and options",
|
|
266
|
+
dependencies: [
|
|
267
|
+
"@radix-ui/react-dropdown-menu",
|
|
268
|
+
"clsx",
|
|
269
|
+
"tailwind-merge",
|
|
270
|
+
"lucide-react"
|
|
271
|
+
],
|
|
272
|
+
files: [
|
|
273
|
+
{
|
|
274
|
+
name: "dropdown-menu.tsx",
|
|
275
|
+
content: prefixTailwindClasses(`import * as React from "react"
|
|
276
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
|
277
|
+
import { Check, ChevronRight, Circle } from "lucide-react"
|
|
184
278
|
|
|
185
279
|
import { cn } from "@/lib/utils"
|
|
186
280
|
|
|
187
|
-
|
|
188
|
-
* Table size variants for row height.
|
|
189
|
-
*/
|
|
190
|
-
const tableVariants = cva(
|
|
191
|
-
"w-full caption-bottom text-sm",
|
|
192
|
-
{
|
|
193
|
-
variants: {
|
|
194
|
-
size: {
|
|
195
|
-
sm: "[&_td]:py-2 [&_th]:py-2",
|
|
196
|
-
md: "[&_td]:py-3 [&_th]:py-3",
|
|
197
|
-
lg: "[&_td]:py-4 [&_th]:py-4",
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
defaultVariants: {
|
|
201
|
-
size: "md",
|
|
202
|
-
},
|
|
203
|
-
}
|
|
204
|
-
)
|
|
281
|
+
const DropdownMenu = DropdownMenuPrimitive.Root
|
|
205
282
|
|
|
206
|
-
|
|
207
|
-
extends React.HTMLAttributes<HTMLTableElement>,
|
|
208
|
-
VariantProps<typeof tableVariants> {
|
|
209
|
-
/** Remove outer border from the table */
|
|
210
|
-
withoutBorder?: boolean
|
|
211
|
-
}
|
|
283
|
+
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
|
212
284
|
|
|
213
|
-
const
|
|
214
|
-
({ className, size, withoutBorder, ...props }, ref) => (
|
|
215
|
-
<div className={cn(
|
|
216
|
-
"relative w-full overflow-auto",
|
|
217
|
-
!withoutBorder && "rounded-lg border border-[#E5E7EB]"
|
|
218
|
-
)}>
|
|
219
|
-
<table
|
|
220
|
-
ref={ref}
|
|
221
|
-
className={cn(tableVariants({ size, className }))}
|
|
222
|
-
{...props}
|
|
223
|
-
/>
|
|
224
|
-
</div>
|
|
225
|
-
)
|
|
226
|
-
)
|
|
227
|
-
Table.displayName = "Table"
|
|
285
|
+
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
|
228
286
|
|
|
229
|
-
const
|
|
230
|
-
HTMLTableSectionElement,
|
|
231
|
-
React.HTMLAttributes<HTMLTableSectionElement>
|
|
232
|
-
>(({ className, ...props }, ref) => (
|
|
233
|
-
<thead
|
|
234
|
-
ref={ref}
|
|
235
|
-
className={cn("bg-[#F9FAFB] [&_tr]:border-b", className)}
|
|
236
|
-
{...props}
|
|
237
|
-
/>
|
|
238
|
-
))
|
|
239
|
-
TableHeader.displayName = "TableHeader"
|
|
287
|
+
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
|
240
288
|
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
289
|
+
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
|
290
|
+
|
|
291
|
+
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
|
292
|
+
|
|
293
|
+
const DropdownMenuSubTrigger = React.forwardRef<
|
|
294
|
+
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
|
295
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
|
296
|
+
inset?: boolean
|
|
297
|
+
}
|
|
298
|
+
>(({ className, inset, children, ...props }, ref) => (
|
|
299
|
+
<DropdownMenuPrimitive.SubTrigger
|
|
246
300
|
ref={ref}
|
|
247
|
-
className={cn(
|
|
301
|
+
className={cn(
|
|
302
|
+
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-[#F3F4F6] data-[state=open]:bg-[#F3F4F6]",
|
|
303
|
+
inset && "pl-8",
|
|
304
|
+
className
|
|
305
|
+
)}
|
|
248
306
|
{...props}
|
|
249
|
-
|
|
307
|
+
>
|
|
308
|
+
{children}
|
|
309
|
+
<ChevronRight className="ml-auto h-4 w-4" />
|
|
310
|
+
</DropdownMenuPrimitive.SubTrigger>
|
|
250
311
|
))
|
|
251
|
-
|
|
312
|
+
DropdownMenuSubTrigger.displayName =
|
|
313
|
+
DropdownMenuPrimitive.SubTrigger.displayName
|
|
252
314
|
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
React.
|
|
315
|
+
const DropdownMenuSubContent = React.forwardRef<
|
|
316
|
+
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
|
317
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
|
256
318
|
>(({ className, ...props }, ref) => (
|
|
257
|
-
<
|
|
319
|
+
<DropdownMenuPrimitive.SubContent
|
|
258
320
|
ref={ref}
|
|
259
321
|
className={cn(
|
|
260
|
-
"border-
|
|
322
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-[#E5E7EB] bg-white p-1 text-[#333333] shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-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",
|
|
261
323
|
className
|
|
262
324
|
)}
|
|
263
325
|
{...props}
|
|
264
326
|
/>
|
|
265
327
|
))
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
export interface TableRowProps extends React.HTMLAttributes<HTMLTableRowElement> {
|
|
269
|
-
/** Highlight the row with a colored background */
|
|
270
|
-
highlighted?: boolean
|
|
271
|
-
}
|
|
328
|
+
DropdownMenuSubContent.displayName =
|
|
329
|
+
DropdownMenuPrimitive.SubContent.displayName
|
|
272
330
|
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
|
|
331
|
+
const DropdownMenuContent = React.forwardRef<
|
|
332
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
|
333
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
|
334
|
+
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
335
|
+
<DropdownMenuPrimitive.Portal>
|
|
336
|
+
<DropdownMenuPrimitive.Content
|
|
276
337
|
ref={ref}
|
|
338
|
+
sideOffset={sideOffset}
|
|
277
339
|
className={cn(
|
|
278
|
-
"
|
|
279
|
-
|
|
280
|
-
? "bg-[#EBF5FF]"
|
|
281
|
-
: "hover:bg-[#F9FAFB]/50 data-[state=selected]:bg-[#F3F4F6]",
|
|
340
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-[#E5E7EB] bg-white p-1 text-[#333333] shadow-md",
|
|
341
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-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",
|
|
282
342
|
className
|
|
283
343
|
)}
|
|
284
344
|
{...props}
|
|
285
345
|
/>
|
|
286
|
-
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
export interface TableHeadProps extends React.ThHTMLAttributes<HTMLTableCellElement> {
|
|
291
|
-
/** Make this column sticky on horizontal scroll */
|
|
292
|
-
sticky?: boolean
|
|
293
|
-
/** Sort direction indicator */
|
|
294
|
-
sortDirection?: 'asc' | 'desc' | null
|
|
295
|
-
/** Show info icon with tooltip */
|
|
296
|
-
infoTooltip?: string
|
|
297
|
-
}
|
|
346
|
+
</DropdownMenuPrimitive.Portal>
|
|
347
|
+
))
|
|
348
|
+
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
|
298
349
|
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
350
|
+
const DropdownMenuItem = React.forwardRef<
|
|
351
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
|
352
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
|
353
|
+
inset?: boolean
|
|
354
|
+
}
|
|
355
|
+
>(({ className, inset, ...props }, ref) => (
|
|
356
|
+
<DropdownMenuPrimitive.Item
|
|
357
|
+
ref={ref}
|
|
358
|
+
className={cn(
|
|
359
|
+
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-[#F3F4F6] focus:text-[#333333] data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
360
|
+
inset && "pl-8",
|
|
361
|
+
className
|
|
362
|
+
)}
|
|
363
|
+
{...props}
|
|
364
|
+
/>
|
|
365
|
+
))
|
|
366
|
+
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
|
367
|
+
|
|
368
|
+
const DropdownMenuCheckboxItem = React.forwardRef<
|
|
369
|
+
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
|
370
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
|
371
|
+
>(({ className, children, checked, ...props }, ref) => (
|
|
372
|
+
<DropdownMenuPrimitive.CheckboxItem
|
|
373
|
+
ref={ref}
|
|
374
|
+
className={cn(
|
|
375
|
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-[#F3F4F6] focus:text-[#333333] data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
376
|
+
className
|
|
377
|
+
)}
|
|
378
|
+
checked={checked}
|
|
379
|
+
{...props}
|
|
380
|
+
>
|
|
381
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
382
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
383
|
+
<Check className="h-4 w-4" />
|
|
384
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
385
|
+
</span>
|
|
386
|
+
{children}
|
|
387
|
+
</DropdownMenuPrimitive.CheckboxItem>
|
|
388
|
+
))
|
|
389
|
+
DropdownMenuCheckboxItem.displayName =
|
|
390
|
+
DropdownMenuPrimitive.CheckboxItem.displayName
|
|
391
|
+
|
|
392
|
+
const DropdownMenuRadioItem = React.forwardRef<
|
|
393
|
+
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
|
394
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
|
395
|
+
>(({ className, children, ...props }, ref) => (
|
|
396
|
+
<DropdownMenuPrimitive.RadioItem
|
|
397
|
+
ref={ref}
|
|
398
|
+
className={cn(
|
|
399
|
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-[#F3F4F6] focus:text-[#333333] data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
400
|
+
className
|
|
401
|
+
)}
|
|
402
|
+
{...props}
|
|
403
|
+
>
|
|
404
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
405
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
406
|
+
<Circle className="h-2 w-2 fill-current" />
|
|
407
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
408
|
+
</span>
|
|
409
|
+
{children}
|
|
410
|
+
</DropdownMenuPrimitive.RadioItem>
|
|
411
|
+
))
|
|
412
|
+
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
|
413
|
+
|
|
414
|
+
const DropdownMenuLabel = React.forwardRef<
|
|
415
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
|
416
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
|
417
|
+
inset?: boolean
|
|
418
|
+
}
|
|
419
|
+
>(({ className, inset, ...props }, ref) => (
|
|
420
|
+
<DropdownMenuPrimitive.Label
|
|
421
|
+
ref={ref}
|
|
422
|
+
className={cn(
|
|
423
|
+
"px-2 py-1.5 text-sm font-semibold",
|
|
424
|
+
inset && "pl-8",
|
|
425
|
+
className
|
|
426
|
+
)}
|
|
427
|
+
{...props}
|
|
428
|
+
/>
|
|
429
|
+
))
|
|
430
|
+
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
|
431
|
+
|
|
432
|
+
const DropdownMenuSeparator = React.forwardRef<
|
|
433
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
|
434
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
|
435
|
+
>(({ className, ...props }, ref) => (
|
|
436
|
+
<DropdownMenuPrimitive.Separator
|
|
437
|
+
ref={ref}
|
|
438
|
+
className={cn("-mx-1 my-1 h-px bg-[#E5E7EB]", className)}
|
|
439
|
+
{...props}
|
|
440
|
+
/>
|
|
441
|
+
))
|
|
442
|
+
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
|
443
|
+
|
|
444
|
+
const DropdownMenuShortcut = ({
|
|
445
|
+
className,
|
|
446
|
+
...props
|
|
447
|
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
448
|
+
return (
|
|
449
|
+
<span
|
|
450
|
+
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
|
451
|
+
{...props}
|
|
452
|
+
/>
|
|
453
|
+
)
|
|
454
|
+
}
|
|
455
|
+
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
|
|
456
|
+
|
|
457
|
+
export {
|
|
458
|
+
DropdownMenu,
|
|
459
|
+
DropdownMenuTrigger,
|
|
460
|
+
DropdownMenuContent,
|
|
461
|
+
DropdownMenuItem,
|
|
462
|
+
DropdownMenuCheckboxItem,
|
|
463
|
+
DropdownMenuRadioItem,
|
|
464
|
+
DropdownMenuLabel,
|
|
465
|
+
DropdownMenuSeparator,
|
|
466
|
+
DropdownMenuShortcut,
|
|
467
|
+
DropdownMenuGroup,
|
|
468
|
+
DropdownMenuPortal,
|
|
469
|
+
DropdownMenuSub,
|
|
470
|
+
DropdownMenuSubContent,
|
|
471
|
+
DropdownMenuSubTrigger,
|
|
472
|
+
DropdownMenuRadioGroup,
|
|
473
|
+
}
|
|
474
|
+
`, prefix)
|
|
475
|
+
}
|
|
476
|
+
]
|
|
477
|
+
},
|
|
478
|
+
"table": {
|
|
479
|
+
name: "table",
|
|
480
|
+
description: "A composable table component with size variants, loading/empty states, sticky columns, and sorting support",
|
|
481
|
+
dependencies: [
|
|
482
|
+
"class-variance-authority",
|
|
483
|
+
"clsx",
|
|
484
|
+
"tailwind-merge"
|
|
485
|
+
],
|
|
486
|
+
files: [
|
|
487
|
+
{
|
|
488
|
+
name: "table.tsx",
|
|
489
|
+
content: prefixTailwindClasses(`import * as React from "react"
|
|
490
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
491
|
+
|
|
492
|
+
import { cn } from "@/lib/utils"
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Table size variants for row height.
|
|
496
|
+
*/
|
|
497
|
+
const tableVariants = cva(
|
|
498
|
+
"w-full caption-bottom text-sm",
|
|
499
|
+
{
|
|
500
|
+
variants: {
|
|
501
|
+
size: {
|
|
502
|
+
sm: "[&_td]:py-2 [&_th]:py-2",
|
|
503
|
+
md: "[&_td]:py-3 [&_th]:py-3",
|
|
504
|
+
lg: "[&_td]:py-4 [&_th]:py-4",
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
defaultVariants: {
|
|
508
|
+
size: "md",
|
|
509
|
+
},
|
|
510
|
+
}
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Table component for displaying tabular data.
|
|
515
|
+
*
|
|
516
|
+
* @example
|
|
517
|
+
* \`\`\`tsx
|
|
518
|
+
* <Table size="md" withoutBorder>
|
|
519
|
+
* <TableHeader>
|
|
520
|
+
* <TableRow>
|
|
521
|
+
* <TableHead>Name</TableHead>
|
|
522
|
+
* <TableHead>Status</TableHead>
|
|
523
|
+
* </TableRow>
|
|
524
|
+
* </TableHeader>
|
|
525
|
+
* <TableBody>
|
|
526
|
+
* <TableRow>
|
|
527
|
+
* <TableCell>Item 1</TableCell>
|
|
528
|
+
* <TableCell><Badge variant="active">Active</Badge></TableCell>
|
|
529
|
+
* </TableRow>
|
|
530
|
+
* </TableBody>
|
|
531
|
+
* </Table>
|
|
532
|
+
* \`\`\`
|
|
533
|
+
*/
|
|
534
|
+
|
|
535
|
+
export interface TableProps
|
|
536
|
+
extends React.HTMLAttributes<HTMLTableElement>,
|
|
537
|
+
VariantProps<typeof tableVariants> {
|
|
538
|
+
/** Remove outer border from the table */
|
|
539
|
+
withoutBorder?: boolean
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
const Table = React.forwardRef<HTMLTableElement, TableProps>(
|
|
543
|
+
({ className, size, withoutBorder, ...props }, ref) => (
|
|
544
|
+
<div className={cn(
|
|
545
|
+
"relative w-full overflow-auto",
|
|
546
|
+
!withoutBorder && "rounded-lg border border-[#E5E7EB]"
|
|
547
|
+
)}>
|
|
548
|
+
<table
|
|
549
|
+
ref={ref}
|
|
550
|
+
className={cn(tableVariants({ size, className }))}
|
|
551
|
+
{...props}
|
|
552
|
+
/>
|
|
553
|
+
</div>
|
|
554
|
+
)
|
|
555
|
+
)
|
|
556
|
+
Table.displayName = "Table"
|
|
557
|
+
|
|
558
|
+
const TableHeader = React.forwardRef<
|
|
559
|
+
HTMLTableSectionElement,
|
|
560
|
+
React.HTMLAttributes<HTMLTableSectionElement>
|
|
561
|
+
>(({ className, ...props }, ref) => (
|
|
562
|
+
<thead
|
|
563
|
+
ref={ref}
|
|
564
|
+
className={cn("bg-[#F9FAFB] [&_tr]:border-b", className)}
|
|
565
|
+
{...props}
|
|
566
|
+
/>
|
|
567
|
+
))
|
|
568
|
+
TableHeader.displayName = "TableHeader"
|
|
569
|
+
|
|
570
|
+
const TableBody = React.forwardRef<
|
|
571
|
+
HTMLTableSectionElement,
|
|
572
|
+
React.HTMLAttributes<HTMLTableSectionElement>
|
|
573
|
+
>(({ className, ...props }, ref) => (
|
|
574
|
+
<tbody
|
|
575
|
+
ref={ref}
|
|
576
|
+
className={cn("[&_tr:last-child]:border-0", className)}
|
|
577
|
+
{...props}
|
|
578
|
+
/>
|
|
579
|
+
))
|
|
580
|
+
TableBody.displayName = "TableBody"
|
|
581
|
+
|
|
582
|
+
const TableFooter = React.forwardRef<
|
|
583
|
+
HTMLTableSectionElement,
|
|
584
|
+
React.HTMLAttributes<HTMLTableSectionElement>
|
|
585
|
+
>(({ className, ...props }, ref) => (
|
|
586
|
+
<tfoot
|
|
587
|
+
ref={ref}
|
|
588
|
+
className={cn(
|
|
589
|
+
"border-t bg-[#F9FAFB] font-medium [&>tr]:last:border-b-0",
|
|
590
|
+
className
|
|
591
|
+
)}
|
|
592
|
+
{...props}
|
|
593
|
+
/>
|
|
594
|
+
))
|
|
595
|
+
TableFooter.displayName = "TableFooter"
|
|
596
|
+
|
|
597
|
+
export interface TableRowProps extends React.HTMLAttributes<HTMLTableRowElement> {
|
|
598
|
+
/** Highlight the row with a colored background */
|
|
599
|
+
highlighted?: boolean
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
const TableRow = React.forwardRef<HTMLTableRowElement, TableRowProps>(
|
|
603
|
+
({ className, highlighted, ...props }, ref) => (
|
|
604
|
+
<tr
|
|
605
|
+
ref={ref}
|
|
606
|
+
className={cn(
|
|
607
|
+
"border-b border-[#E5E7EB] transition-colors",
|
|
608
|
+
highlighted
|
|
609
|
+
? "bg-[#EBF5FF]"
|
|
610
|
+
: "hover:bg-[#F9FAFB]/50 data-[state=selected]:bg-[#F3F4F6]",
|
|
611
|
+
className
|
|
612
|
+
)}
|
|
613
|
+
{...props}
|
|
614
|
+
/>
|
|
615
|
+
)
|
|
616
|
+
)
|
|
617
|
+
TableRow.displayName = "TableRow"
|
|
618
|
+
|
|
619
|
+
export interface TableHeadProps extends React.ThHTMLAttributes<HTMLTableCellElement> {
|
|
620
|
+
/** Make this column sticky on horizontal scroll */
|
|
621
|
+
sticky?: boolean
|
|
622
|
+
/** Sort direction indicator */
|
|
623
|
+
sortDirection?: 'asc' | 'desc' | null
|
|
624
|
+
/** Show info icon with tooltip */
|
|
625
|
+
infoTooltip?: string
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
const TableHead = React.forwardRef<HTMLTableCellElement, TableHeadProps>(
|
|
629
|
+
({ className, sticky, sortDirection, infoTooltip, children, ...props }, ref) => (
|
|
630
|
+
<th
|
|
631
|
+
ref={ref}
|
|
303
632
|
className={cn(
|
|
304
633
|
"h-12 px-4 text-left align-middle font-medium text-[#6B7280] text-xs uppercase tracking-wider [&:has([role=checkbox])]:pr-0",
|
|
305
634
|
sticky && "sticky left-0 bg-[#F9FAFB] z-10",
|
|
@@ -437,278 +766,109 @@ export {
|
|
|
437
766
|
TableAvatar,
|
|
438
767
|
tableVariants,
|
|
439
768
|
}
|
|
440
|
-
`, prefix)
|
|
441
|
-
|
|
442
|
-
|
|
769
|
+
`, prefix)
|
|
770
|
+
}
|
|
771
|
+
]
|
|
772
|
+
},
|
|
773
|
+
"tag": {
|
|
774
|
+
name: "tag",
|
|
775
|
+
description: "A tag component for event labels with optional bold label prefix",
|
|
776
|
+
dependencies: [
|
|
777
|
+
"class-variance-authority",
|
|
778
|
+
"clsx",
|
|
779
|
+
"tailwind-merge"
|
|
780
|
+
],
|
|
781
|
+
files: [
|
|
782
|
+
{
|
|
783
|
+
name: "tag.tsx",
|
|
784
|
+
content: prefixTailwindClasses(`import * as React from "react"
|
|
443
785
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
444
|
-
import { Loader2 } from "lucide-react"
|
|
445
786
|
|
|
446
787
|
import { cn } from "@/lib/utils"
|
|
447
788
|
|
|
448
|
-
|
|
449
|
-
|
|
789
|
+
/**
|
|
790
|
+
* Tag variants for event labels and categories.
|
|
791
|
+
* Rounded rectangle tags with optional bold labels.
|
|
792
|
+
*/
|
|
793
|
+
const tagVariants = cva(
|
|
794
|
+
"inline-flex items-center justify-center rounded text-sm transition-colors",
|
|
450
795
|
{
|
|
451
796
|
variants: {
|
|
452
797
|
variant: {
|
|
453
|
-
default: "bg-[#
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
"bg-[#343E55]/20 text-[#343E55] border-0 hover:bg-[#343E55]/30",
|
|
460
|
-
ghost: "border-0 hover:bg-[#343E55]/10 hover:text-[#343E55]",
|
|
461
|
-
link: "text-[#343E55] border-0 underline-offset-4 hover:underline",
|
|
798
|
+
default: "bg-[#F3F4F6] text-[#333333]",
|
|
799
|
+
primary: "bg-[#343E55]/10 text-[#343E55]",
|
|
800
|
+
secondary: "bg-[#E5E7EB] text-[#374151]",
|
|
801
|
+
success: "bg-[#E5FFF5] text-[#00A651]",
|
|
802
|
+
warning: "bg-[#FFF8E5] text-[#F59E0B]",
|
|
803
|
+
error: "bg-[#FFECEC] text-[#FF3B3B]",
|
|
462
804
|
},
|
|
463
805
|
size: {
|
|
464
|
-
default: "
|
|
465
|
-
sm: "
|
|
466
|
-
lg: "
|
|
467
|
-
|
|
806
|
+
default: "px-2 py-1",
|
|
807
|
+
sm: "px-1.5 py-0.5 text-xs",
|
|
808
|
+
lg: "px-3 py-1.5",
|
|
809
|
+
},
|
|
810
|
+
interactive: {
|
|
811
|
+
true: "cursor-pointer hover:bg-[#E5E7EB] active:bg-[#D1D5DB]",
|
|
812
|
+
false: "",
|
|
813
|
+
},
|
|
814
|
+
selected: {
|
|
815
|
+
true: "ring-2 ring-[#343E55] ring-offset-1",
|
|
816
|
+
false: "",
|
|
468
817
|
},
|
|
469
818
|
},
|
|
470
819
|
defaultVariants: {
|
|
471
820
|
variant: "default",
|
|
472
821
|
size: "default",
|
|
822
|
+
interactive: false,
|
|
823
|
+
selected: false,
|
|
473
824
|
},
|
|
474
825
|
}
|
|
475
826
|
)
|
|
476
827
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
828
|
+
/**
|
|
829
|
+
* Tag component for displaying event labels and categories.
|
|
830
|
+
*
|
|
831
|
+
* @example
|
|
832
|
+
* \`\`\`tsx
|
|
833
|
+
* <Tag>After Call Event</Tag>
|
|
834
|
+
* <Tag label="In Call Event:">Start of call, Bridge, Call ended</Tag>
|
|
835
|
+
* <Tag interactive onClick={() => console.log('clicked')}>Clickable</Tag>
|
|
836
|
+
* \`\`\`
|
|
837
|
+
*/
|
|
838
|
+
export interface TagProps
|
|
839
|
+
extends React.HTMLAttributes<HTMLSpanElement>,
|
|
840
|
+
VariantProps<typeof tagVariants> {
|
|
841
|
+
/** Bold label prefix displayed before the content */
|
|
842
|
+
label?: string
|
|
843
|
+
/** Make the tag clickable with hover/active states */
|
|
844
|
+
interactive?: boolean
|
|
845
|
+
/** Show selected state with ring outline */
|
|
846
|
+
selected?: boolean
|
|
485
847
|
}
|
|
486
848
|
|
|
487
|
-
const
|
|
488
|
-
({
|
|
489
|
-
className,
|
|
490
|
-
variant,
|
|
491
|
-
size,
|
|
492
|
-
asChild = false,
|
|
493
|
-
leftIcon,
|
|
494
|
-
rightIcon,
|
|
495
|
-
loading = false,
|
|
496
|
-
loadingText,
|
|
497
|
-
children,
|
|
498
|
-
disabled,
|
|
499
|
-
...props
|
|
500
|
-
}, ref) => {
|
|
501
|
-
const Comp = asChild ? Slot : "button"
|
|
502
|
-
|
|
849
|
+
const Tag = React.forwardRef<HTMLSpanElement, TagProps>(
|
|
850
|
+
({ className, variant, size, interactive, selected, label, children, ...props }, ref) => {
|
|
503
851
|
return (
|
|
504
|
-
<
|
|
505
|
-
className={cn(
|
|
852
|
+
<span
|
|
853
|
+
className={cn(tagVariants({ variant, size, interactive, selected, className }))}
|
|
506
854
|
ref={ref}
|
|
507
|
-
|
|
855
|
+
role={interactive ? "button" : undefined}
|
|
856
|
+
tabIndex={interactive ? 0 : undefined}
|
|
857
|
+
aria-selected={selected}
|
|
508
858
|
{...props}
|
|
509
859
|
>
|
|
510
|
-
{
|
|
511
|
-
|
|
512
|
-
<Loader2 className="animate-spin" />
|
|
513
|
-
{loadingText || children}
|
|
514
|
-
</>
|
|
515
|
-
) : (
|
|
516
|
-
<>
|
|
517
|
-
{leftIcon}
|
|
518
|
-
{children}
|
|
519
|
-
{rightIcon}
|
|
520
|
-
</>
|
|
860
|
+
{label && (
|
|
861
|
+
<span className="font-semibold mr-1">{label}</span>
|
|
521
862
|
)}
|
|
522
|
-
|
|
863
|
+
<span className="font-normal">{children}</span>
|
|
864
|
+
</span>
|
|
523
865
|
)
|
|
524
866
|
}
|
|
525
867
|
)
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
export { Button, buttonVariants }
|
|
529
|
-
`, prefix);
|
|
530
|
-
const dropdownMenuContent = prefixTailwindClasses(`import * as React from "react"
|
|
531
|
-
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
|
532
|
-
import { Check, ChevronRight, Circle } from "lucide-react"
|
|
533
|
-
|
|
534
|
-
import { cn } from "@/lib/utils"
|
|
535
|
-
|
|
536
|
-
const DropdownMenu = DropdownMenuPrimitive.Root
|
|
537
|
-
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
|
538
|
-
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
|
539
|
-
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
|
540
|
-
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
|
541
|
-
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
|
542
|
-
|
|
543
|
-
const DropdownMenuContent = React.forwardRef<
|
|
544
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
|
545
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
|
546
|
-
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
547
|
-
<DropdownMenuPrimitive.Portal>
|
|
548
|
-
<DropdownMenuPrimitive.Content
|
|
549
|
-
ref={ref}
|
|
550
|
-
sideOffset={sideOffset}
|
|
551
|
-
className={cn(
|
|
552
|
-
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-[#E5E7EB] bg-white p-1 text-[#333333] shadow-md",
|
|
553
|
-
className
|
|
554
|
-
)}
|
|
555
|
-
{...props}
|
|
556
|
-
/>
|
|
557
|
-
</DropdownMenuPrimitive.Portal>
|
|
558
|
-
))
|
|
559
|
-
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
|
560
|
-
|
|
561
|
-
const DropdownMenuItem = React.forwardRef<
|
|
562
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
|
563
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
|
564
|
-
inset?: boolean
|
|
565
|
-
}
|
|
566
|
-
>(({ className, inset, ...props }, ref) => (
|
|
567
|
-
<DropdownMenuPrimitive.Item
|
|
568
|
-
ref={ref}
|
|
569
|
-
className={cn(
|
|
570
|
-
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-[#F3F4F6] focus:text-[#333333] data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
571
|
-
inset && "pl-8",
|
|
572
|
-
className
|
|
573
|
-
)}
|
|
574
|
-
{...props}
|
|
575
|
-
/>
|
|
576
|
-
))
|
|
577
|
-
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
|
578
|
-
|
|
579
|
-
const DropdownMenuLabel = React.forwardRef<
|
|
580
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
|
581
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
|
582
|
-
inset?: boolean
|
|
583
|
-
}
|
|
584
|
-
>(({ className, inset, ...props }, ref) => (
|
|
585
|
-
<DropdownMenuPrimitive.Label
|
|
586
|
-
ref={ref}
|
|
587
|
-
className={cn(
|
|
588
|
-
"px-2 py-1.5 text-sm font-semibold",
|
|
589
|
-
inset && "pl-8",
|
|
590
|
-
className
|
|
591
|
-
)}
|
|
592
|
-
{...props}
|
|
593
|
-
/>
|
|
594
|
-
))
|
|
595
|
-
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
|
596
|
-
|
|
597
|
-
const DropdownMenuSeparator = React.forwardRef<
|
|
598
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
|
599
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
|
600
|
-
>(({ className, ...props }, ref) => (
|
|
601
|
-
<DropdownMenuPrimitive.Separator
|
|
602
|
-
ref={ref}
|
|
603
|
-
className={cn("-mx-1 my-1 h-px bg-[#E5E7EB]", className)}
|
|
604
|
-
{...props}
|
|
605
|
-
/>
|
|
606
|
-
))
|
|
607
|
-
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
|
608
|
-
|
|
609
|
-
const DropdownMenuShortcut = ({
|
|
610
|
-
className,
|
|
611
|
-
...props
|
|
612
|
-
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
613
|
-
return (
|
|
614
|
-
<span
|
|
615
|
-
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
|
616
|
-
{...props}
|
|
617
|
-
/>
|
|
618
|
-
)
|
|
619
|
-
}
|
|
620
|
-
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
|
|
868
|
+
Tag.displayName = "Tag"
|
|
621
869
|
|
|
622
|
-
export {
|
|
623
|
-
|
|
624
|
-
DropdownMenuTrigger,
|
|
625
|
-
DropdownMenuContent,
|
|
626
|
-
DropdownMenuItem,
|
|
627
|
-
DropdownMenuLabel,
|
|
628
|
-
DropdownMenuSeparator,
|
|
629
|
-
DropdownMenuShortcut,
|
|
630
|
-
DropdownMenuGroup,
|
|
631
|
-
DropdownMenuPortal,
|
|
632
|
-
DropdownMenuSub,
|
|
633
|
-
DropdownMenuRadioGroup,
|
|
634
|
-
}
|
|
635
|
-
`, prefix);
|
|
636
|
-
return {
|
|
637
|
-
button: {
|
|
638
|
-
name: "button",
|
|
639
|
-
description: "A customizable button component with variants, sizes, and icons",
|
|
640
|
-
dependencies: [
|
|
641
|
-
"@radix-ui/react-slot",
|
|
642
|
-
"class-variance-authority",
|
|
643
|
-
"clsx",
|
|
644
|
-
"tailwind-merge",
|
|
645
|
-
"lucide-react"
|
|
646
|
-
],
|
|
647
|
-
files: [
|
|
648
|
-
{
|
|
649
|
-
name: "button.tsx",
|
|
650
|
-
content: buttonContent
|
|
651
|
-
}
|
|
652
|
-
]
|
|
653
|
-
},
|
|
654
|
-
badge: {
|
|
655
|
-
name: "badge",
|
|
656
|
-
description: "A status badge component with active, failed, and disabled variants",
|
|
657
|
-
dependencies: [
|
|
658
|
-
"class-variance-authority",
|
|
659
|
-
"clsx",
|
|
660
|
-
"tailwind-merge"
|
|
661
|
-
],
|
|
662
|
-
files: [
|
|
663
|
-
{
|
|
664
|
-
name: "badge.tsx",
|
|
665
|
-
content: badgeContent
|
|
666
|
-
}
|
|
667
|
-
]
|
|
668
|
-
},
|
|
669
|
-
tag: {
|
|
670
|
-
name: "tag",
|
|
671
|
-
description: "A tag component for event labels with optional bold label prefix",
|
|
672
|
-
dependencies: [
|
|
673
|
-
"class-variance-authority",
|
|
674
|
-
"clsx",
|
|
675
|
-
"tailwind-merge"
|
|
676
|
-
],
|
|
677
|
-
files: [
|
|
678
|
-
{
|
|
679
|
-
name: "tag.tsx",
|
|
680
|
-
content: tagContent
|
|
681
|
-
}
|
|
682
|
-
]
|
|
683
|
-
},
|
|
684
|
-
table: {
|
|
685
|
-
name: "table",
|
|
686
|
-
description: "A composable table component with size variants, loading/empty states, sticky columns, and sorting support",
|
|
687
|
-
dependencies: [
|
|
688
|
-
"class-variance-authority",
|
|
689
|
-
"clsx",
|
|
690
|
-
"tailwind-merge"
|
|
691
|
-
],
|
|
692
|
-
files: [
|
|
693
|
-
{
|
|
694
|
-
name: "table.tsx",
|
|
695
|
-
content: tableContent
|
|
696
|
-
}
|
|
697
|
-
]
|
|
698
|
-
},
|
|
699
|
-
"dropdown-menu": {
|
|
700
|
-
name: "dropdown-menu",
|
|
701
|
-
description: "A dropdown menu component for displaying actions and options",
|
|
702
|
-
dependencies: [
|
|
703
|
-
"@radix-ui/react-dropdown-menu",
|
|
704
|
-
"clsx",
|
|
705
|
-
"tailwind-merge",
|
|
706
|
-
"lucide-react"
|
|
707
|
-
],
|
|
708
|
-
files: [
|
|
709
|
-
{
|
|
710
|
-
name: "dropdown-menu.tsx",
|
|
711
|
-
content: dropdownMenuContent
|
|
870
|
+
export { Tag, tagVariants }
|
|
871
|
+
`, prefix)
|
|
712
872
|
}
|
|
713
873
|
]
|
|
714
874
|
}
|
|
@@ -962,15 +1122,14 @@ var CSS_VARIABLES_V3 = `@tailwind base;
|
|
|
962
1122
|
}
|
|
963
1123
|
|
|
964
1124
|
`;
|
|
965
|
-
var getTailwindConfig = (
|
|
1125
|
+
var getTailwindConfig = (disablePreflight = false) => `/** @type {import('tailwindcss').Config} */
|
|
966
1126
|
export default {
|
|
967
1127
|
darkMode: ["class"],
|
|
968
1128
|
content: [
|
|
969
|
-
|
|
970
|
-
"./src
|
|
971
|
-
"./src/**/*.{js,ts,jsx,tsx}",`}
|
|
1129
|
+
"./index.html",
|
|
1130
|
+
"./src/**/*.{js,ts,jsx,tsx}",
|
|
972
1131
|
],
|
|
973
|
-
${
|
|
1132
|
+
${disablePreflight ? `corePlugins: {
|
|
974
1133
|
preflight: false,
|
|
975
1134
|
},
|
|
976
1135
|
` : ""}theme: {
|
|
@@ -1133,7 +1292,7 @@ async function init() {
|
|
|
1133
1292
|
const detectedTailwindConfig = await detectTailwindConfig();
|
|
1134
1293
|
let tailwindVersion = detectedTailwindVersion;
|
|
1135
1294
|
if (!tailwindVersion) {
|
|
1136
|
-
const
|
|
1295
|
+
const response = await prompts2([
|
|
1137
1296
|
{
|
|
1138
1297
|
type: "select",
|
|
1139
1298
|
name: "tailwindVersion",
|
|
@@ -1145,13 +1304,13 @@ async function init() {
|
|
|
1145
1304
|
initial: 0
|
|
1146
1305
|
}
|
|
1147
1306
|
]);
|
|
1148
|
-
tailwindVersion =
|
|
1307
|
+
tailwindVersion = response.tailwindVersion;
|
|
1149
1308
|
}
|
|
1150
1309
|
const componentsPath = "src/components/ui";
|
|
1151
1310
|
const utilsPath = "src/lib/utils.ts";
|
|
1152
1311
|
const tailwindConfig = detectedTailwindConfig;
|
|
1153
1312
|
const globalCss = detectedCss;
|
|
1154
|
-
const
|
|
1313
|
+
const disablePreflight = hasBootstrap;
|
|
1155
1314
|
const spinner = ora2("Initializing project...").start();
|
|
1156
1315
|
try {
|
|
1157
1316
|
const config = {
|
|
@@ -1252,12 +1411,12 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
1252
1411
|
if (tailwindVersion === "v3" && tailwindConfig) {
|
|
1253
1412
|
const tailwindConfigPath = path2.join(cwd, tailwindConfig);
|
|
1254
1413
|
if (!await fs2.pathExists(tailwindConfigPath)) {
|
|
1255
|
-
await fs2.writeFile(tailwindConfigPath, getTailwindConfig(
|
|
1414
|
+
await fs2.writeFile(tailwindConfigPath, getTailwindConfig(disablePreflight));
|
|
1256
1415
|
tailwindUpdated = true;
|
|
1257
1416
|
} else {
|
|
1258
1417
|
const existingConfig = await fs2.readFile(tailwindConfigPath, "utf-8");
|
|
1259
1418
|
if (!existingConfig.includes("hsl(var(--destructive))") && !existingConfig.includes("hsl(var(--ring))")) {
|
|
1260
|
-
await fs2.writeFile(tailwindConfigPath, getTailwindConfig(
|
|
1419
|
+
await fs2.writeFile(tailwindConfigPath, getTailwindConfig(disablePreflight));
|
|
1261
1420
|
tailwindUpdated = true;
|
|
1262
1421
|
}
|
|
1263
1422
|
}
|
|
@@ -1310,7 +1469,7 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
1310
1469
|
}
|
|
1311
1470
|
}
|
|
1312
1471
|
spinner.text = "Installing dependencies...";
|
|
1313
|
-
const deps =
|
|
1472
|
+
const deps = tailwindVersion === "v4" ? "clsx tailwind-merge class-variance-authority @radix-ui/react-slot lucide-react" : "clsx tailwind-merge class-variance-authority @radix-ui/react-slot lucide-react tailwindcss-animate tailwindcss@^3.4.0 autoprefixer";
|
|
1314
1473
|
try {
|
|
1315
1474
|
execSync(`npm install ${deps}`, { cwd, stdio: "pipe" });
|
|
1316
1475
|
console.log(chalk2.green("\n \u2713 Installed dependencies"));
|
|
@@ -1336,8 +1495,8 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
1336
1495
|
}
|
|
1337
1496
|
if (tailwindUpdated) {
|
|
1338
1497
|
console.log(chalk2.green(` \u2713 Updated ${tailwindConfig} with theme colors`));
|
|
1339
|
-
if (
|
|
1340
|
-
console.log(chalk2.blue(` \u2139
|
|
1498
|
+
if (disablePreflight) {
|
|
1499
|
+
console.log(chalk2.blue(` \u2139 Preflight disabled for Bootstrap compatibility`));
|
|
1341
1500
|
}
|
|
1342
1501
|
}
|
|
1343
1502
|
if (postcssCreated) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "myoperator-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.42",
|
|
4
4
|
"description": "CLI for adding myOperator UI components to your project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"dist"
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
|
-
"
|
|
14
|
+
"generate-registry": "node scripts/generate-registry.js",
|
|
15
|
+
"build": "npm run generate-registry && tsup src/index.ts --format esm --dts",
|
|
15
16
|
"dev": "tsup src/index.ts --format esm --watch",
|
|
16
17
|
"typecheck": "tsc --noEmit"
|
|
17
18
|
},
|