myoperator-mcp 0.2.123 → 0.2.125
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 +1633 -409
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -139,7 +139,7 @@ export interface AccordionProps
|
|
|
139
139
|
onValueChange?: (value: string[]) => void;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
const Accordion = React.forwardRef
|
|
142
|
+
const Accordion = React.forwardRef(
|
|
143
143
|
(
|
|
144
144
|
{
|
|
145
145
|
className,
|
|
@@ -150,8 +150,8 @@ const Accordion = React.forwardRef<HTMLDivElement, AccordionProps>(
|
|
|
150
150
|
onValueChange,
|
|
151
151
|
children,
|
|
152
152
|
...props
|
|
153
|
-
},
|
|
154
|
-
ref
|
|
153
|
+
}: AccordionProps,
|
|
154
|
+
ref: React.Ref<HTMLDivElement>
|
|
155
155
|
) => {
|
|
156
156
|
const [internalValue, setInternalValue] =
|
|
157
157
|
React.useState<string[]>(defaultValue);
|
|
@@ -207,8 +207,8 @@ export interface AccordionItemProps
|
|
|
207
207
|
disabled?: boolean;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
const AccordionItem = React.forwardRef
|
|
211
|
-
({ className, value, disabled, children, ...props }, ref) => {
|
|
210
|
+
const AccordionItem = React.forwardRef(
|
|
211
|
+
({ className, value, disabled, children, ...props }: AccordionItemProps, ref: React.Ref<HTMLDivElement>) => {
|
|
212
212
|
const { value: openValues, variant } = useAccordionContext();
|
|
213
213
|
const isOpen = openValues.includes(value);
|
|
214
214
|
|
|
@@ -248,10 +248,7 @@ export interface AccordionTriggerProps
|
|
|
248
248
|
showChevron?: boolean;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
const AccordionTrigger = React.forwardRef<
|
|
252
|
-
HTMLButtonElement,
|
|
253
|
-
AccordionTriggerProps
|
|
254
|
-
>(({ className, showChevron = true, children, ...props }, ref) => {
|
|
251
|
+
const AccordionTrigger = React.forwardRef(({ className, showChevron = true, children, ...props }: AccordionTriggerProps, ref: React.Ref<HTMLButtonElement>) => {
|
|
255
252
|
const {
|
|
256
253
|
type,
|
|
257
254
|
value: openValues,
|
|
@@ -310,10 +307,7 @@ export interface AccordionContentProps
|
|
|
310
307
|
React.HTMLAttributes<HTMLDivElement>,
|
|
311
308
|
VariantProps<typeof accordionContentVariants> {}
|
|
312
309
|
|
|
313
|
-
const AccordionContent = React.forwardRef<
|
|
314
|
-
HTMLDivElement,
|
|
315
|
-
AccordionContentProps
|
|
316
|
-
>(({ className, children, ...props }, ref) => {
|
|
310
|
+
const AccordionContent = React.forwardRef(({ className, children, ...props }: AccordionContentProps, ref: React.Ref<HTMLDivElement>) => {
|
|
317
311
|
const { variant } = useAccordionContext();
|
|
318
312
|
const { isOpen } = useAccordionItemContext();
|
|
319
313
|
const contentRef = React.useRef<HTMLDivElement>(null);
|
|
@@ -448,7 +442,7 @@ export interface AlertProps
|
|
|
448
442
|
defaultOpen?: boolean;
|
|
449
443
|
}
|
|
450
444
|
|
|
451
|
-
const Alert = React.forwardRef
|
|
445
|
+
const Alert = React.forwardRef(
|
|
452
446
|
(
|
|
453
447
|
{
|
|
454
448
|
className,
|
|
@@ -463,8 +457,8 @@ const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
|
|
|
463
457
|
defaultOpen = true,
|
|
464
458
|
children,
|
|
465
459
|
...props
|
|
466
|
-
},
|
|
467
|
-
ref
|
|
460
|
+
}: AlertProps,
|
|
461
|
+
ref: React.Ref<HTMLDivElement>
|
|
468
462
|
) => {
|
|
469
463
|
const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
|
|
470
464
|
const isControlled = controlledOpen !== undefined;
|
|
@@ -536,10 +530,7 @@ Alert.displayName = "Alert";
|
|
|
536
530
|
/**
|
|
537
531
|
* Alert title component for the heading text.
|
|
538
532
|
*/
|
|
539
|
-
const AlertTitle = React.forwardRef<
|
|
540
|
-
HTMLHeadingElement,
|
|
541
|
-
React.HTMLAttributes<HTMLHeadingElement>
|
|
542
|
-
>(({ className, ...props }, ref) => (
|
|
533
|
+
const AlertTitle = React.forwardRef(({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>, ref: React.Ref<HTMLHeadingElement>) => (
|
|
543
534
|
<h5
|
|
544
535
|
ref={ref}
|
|
545
536
|
className={cn("font-semibold leading-tight tracking-tight", className)}
|
|
@@ -551,15 +542,154 @@ AlertTitle.displayName = "AlertTitle";
|
|
|
551
542
|
/**
|
|
552
543
|
* Alert description component for the body text.
|
|
553
544
|
*/
|
|
554
|
-
const AlertDescription = React.forwardRef<
|
|
555
|
-
HTMLParagraphElement,
|
|
556
|
-
React.HTMLAttributes<HTMLParagraphElement>
|
|
557
|
-
>(({ className, ...props }, ref) => (
|
|
545
|
+
const AlertDescription = React.forwardRef(({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>, ref: React.Ref<HTMLParagraphElement>) => (
|
|
558
546
|
<p ref={ref} className={cn("m-0 mt-1 text-sm", className)} {...props} />
|
|
559
547
|
));
|
|
560
548
|
AlertDescription.displayName = "AlertDescription";
|
|
561
549
|
|
|
562
550
|
export { Alert, AlertTitle, AlertDescription, alertVariants };
|
|
551
|
+
`,
|
|
552
|
+
"avatar": `import * as React from "react";
|
|
553
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
554
|
+
|
|
555
|
+
import { cn } from "@/lib/utils";
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Extracts initials from a name string.
|
|
559
|
+
* For two+ words, takes first letter of first and last word.
|
|
560
|
+
* For single words, takes first two characters.
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* getInitials("Ankish Sachdeva") // "AS"
|
|
564
|
+
* getInitials("John") // "JO"
|
|
565
|
+
*/
|
|
566
|
+
function getInitials(name: string): string {
|
|
567
|
+
const parts = name.trim().split(/\\s+/);
|
|
568
|
+
return parts.length >= 2
|
|
569
|
+
? (parts[0][0] + parts[parts.length - 1][0]).toUpperCase()
|
|
570
|
+
: name.slice(0, 2).toUpperCase();
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const avatarVariants = cva(
|
|
574
|
+
"relative inline-flex items-center justify-center rounded-full font-semibold select-none shrink-0 overflow-hidden",
|
|
575
|
+
{
|
|
576
|
+
variants: {
|
|
577
|
+
variant: {
|
|
578
|
+
soft: "bg-semantic-bg-grey text-semantic-text-muted",
|
|
579
|
+
filled: "bg-semantic-primary text-semantic-text-inverted",
|
|
580
|
+
},
|
|
581
|
+
size: {
|
|
582
|
+
xs: "size-6 text-[10px]",
|
|
583
|
+
sm: "size-8 text-xs",
|
|
584
|
+
md: "size-10 text-sm",
|
|
585
|
+
lg: "size-12 text-base",
|
|
586
|
+
xl: "size-16 text-lg",
|
|
587
|
+
},
|
|
588
|
+
},
|
|
589
|
+
defaultVariants: {
|
|
590
|
+
variant: "soft",
|
|
591
|
+
size: "md",
|
|
592
|
+
},
|
|
593
|
+
}
|
|
594
|
+
);
|
|
595
|
+
|
|
596
|
+
const statusDotSizeMap = {
|
|
597
|
+
xs: "size-2 border",
|
|
598
|
+
sm: "size-2.5 border-[1.5px]",
|
|
599
|
+
md: "size-3 border-2",
|
|
600
|
+
lg: "size-3.5 border-2",
|
|
601
|
+
xl: "size-4 border-2",
|
|
602
|
+
} as const;
|
|
603
|
+
|
|
604
|
+
const statusColorMap = {
|
|
605
|
+
online: "bg-semantic-success-primary",
|
|
606
|
+
offline: "bg-semantic-bg-grey",
|
|
607
|
+
busy: "bg-semantic-error-primary",
|
|
608
|
+
away: "bg-semantic-warning-primary",
|
|
609
|
+
} as const;
|
|
610
|
+
|
|
611
|
+
export interface AvatarProps
|
|
612
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
613
|
+
VariantProps<typeof avatarVariants> {
|
|
614
|
+
/** Name used to auto-generate initials and aria-label */
|
|
615
|
+
name?: string;
|
|
616
|
+
/** Image URL \u2014 renders an <img> instead of initials */
|
|
617
|
+
src?: string;
|
|
618
|
+
/** Alt text for the image (defaults to name) */
|
|
619
|
+
alt?: string;
|
|
620
|
+
/** Override auto-generated initials (e.g., "AS") */
|
|
621
|
+
initials?: string;
|
|
622
|
+
/** Status indicator dot shown at bottom-right */
|
|
623
|
+
status?: "online" | "offline" | "busy" | "away";
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Avatar component for displaying user identity via image or initials.
|
|
628
|
+
*
|
|
629
|
+
* @example
|
|
630
|
+
* \`\`\`tsx
|
|
631
|
+
* <Avatar name="Ankish Sachdeva" />
|
|
632
|
+
* <Avatar name="John Doe" size="lg" variant="filled" />
|
|
633
|
+
* <Avatar src="/photo.jpg" alt="Profile" status="online" />
|
|
634
|
+
* <Avatar initials="AS" size="xs" />
|
|
635
|
+
* \`\`\`
|
|
636
|
+
*/
|
|
637
|
+
const Avatar = React.forwardRef(
|
|
638
|
+
(
|
|
639
|
+
{
|
|
640
|
+
className,
|
|
641
|
+
variant,
|
|
642
|
+
size,
|
|
643
|
+
name,
|
|
644
|
+
src,
|
|
645
|
+
alt,
|
|
646
|
+
initials,
|
|
647
|
+
status,
|
|
648
|
+
children,
|
|
649
|
+
...props
|
|
650
|
+
}: AvatarProps,
|
|
651
|
+
ref: React.Ref<HTMLDivElement>
|
|
652
|
+
) => {
|
|
653
|
+
const resolvedSize = size ?? "md";
|
|
654
|
+
const displayInitials = initials ?? (name ? getInitials(name) : undefined);
|
|
655
|
+
|
|
656
|
+
return (
|
|
657
|
+
<div
|
|
658
|
+
ref={ref}
|
|
659
|
+
className={cn(avatarVariants({ variant, size, className }))}
|
|
660
|
+
aria-label={name}
|
|
661
|
+
role="img"
|
|
662
|
+
{...props}
|
|
663
|
+
>
|
|
664
|
+
{src ? (
|
|
665
|
+
<img
|
|
666
|
+
src={src}
|
|
667
|
+
alt={alt ?? name ?? "Avatar"}
|
|
668
|
+
className="size-full object-cover"
|
|
669
|
+
/>
|
|
670
|
+
) : children ? (
|
|
671
|
+
children
|
|
672
|
+
) : displayInitials ? (
|
|
673
|
+
<span aria-hidden="true">{displayInitials}</span>
|
|
674
|
+
) : null}
|
|
675
|
+
|
|
676
|
+
{status && (
|
|
677
|
+
<span
|
|
678
|
+
className={cn(
|
|
679
|
+
"absolute bottom-0 right-0 rounded-full border-background",
|
|
680
|
+
statusDotSizeMap[resolvedSize],
|
|
681
|
+
statusColorMap[status]
|
|
682
|
+
)}
|
|
683
|
+
data-status={status}
|
|
684
|
+
/>
|
|
685
|
+
)}
|
|
686
|
+
</div>
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
);
|
|
690
|
+
Avatar.displayName = "Avatar";
|
|
691
|
+
|
|
692
|
+
export { Avatar, avatarVariants, getInitials };
|
|
563
693
|
`,
|
|
564
694
|
"badge": `import * as React from "react";
|
|
565
695
|
import { Slot } from "@radix-ui/react-slot";
|
|
@@ -630,7 +760,7 @@ export interface BadgeProps
|
|
|
630
760
|
asChild?: boolean;
|
|
631
761
|
}
|
|
632
762
|
|
|
633
|
-
const Badge = React.forwardRef
|
|
763
|
+
const Badge = React.forwardRef(
|
|
634
764
|
(
|
|
635
765
|
{
|
|
636
766
|
className,
|
|
@@ -641,8 +771,8 @@ const Badge = React.forwardRef<HTMLDivElement, BadgeProps>(
|
|
|
641
771
|
asChild = false,
|
|
642
772
|
children,
|
|
643
773
|
...props
|
|
644
|
-
},
|
|
645
|
-
ref
|
|
774
|
+
}: BadgeProps,
|
|
775
|
+
ref: React.Ref<HTMLDivElement>
|
|
646
776
|
) => {
|
|
647
777
|
const Comp = asChild ? Slot : "div";
|
|
648
778
|
|
|
@@ -695,13 +825,15 @@ const buttonVariants = cva(
|
|
|
695
825
|
"bg-semantic-primary text-semantic-text-inverted hover:bg-semantic-primary-hover",
|
|
696
826
|
destructive:
|
|
697
827
|
"bg-semantic-error-primary text-semantic-text-inverted hover:bg-semantic-error-hover",
|
|
828
|
+
success:
|
|
829
|
+
"bg-semantic-success-primary text-semantic-text-inverted hover:bg-semantic-success-hover",
|
|
698
830
|
outline:
|
|
699
|
-
"border border-
|
|
831
|
+
"border border-[var(--color-neutral-300,#D5D7DA)] bg-semantic-bg-primary text-semantic-text-secondary hover:bg-semantic-primary-surface",
|
|
700
832
|
secondary:
|
|
701
833
|
"bg-semantic-primary-surface text-semantic-text-secondary hover:bg-semantic-bg-hover",
|
|
702
834
|
ghost:
|
|
703
835
|
"text-semantic-text-muted hover:bg-semantic-bg-ui hover:text-semantic-text-primary",
|
|
704
|
-
link: "text-semantic-text-
|
|
836
|
+
link: "text-semantic-text-link underline-offset-4 hover:underline",
|
|
705
837
|
dashed:
|
|
706
838
|
"border border-dashed border-semantic-bg-hover bg-transparent text-semantic-text-muted hover:border-semantic-border-primary hover:text-semantic-text-secondary hover:bg-[var(--color-neutral-50)]",
|
|
707
839
|
},
|
|
@@ -747,7 +879,7 @@ export interface ButtonProps
|
|
|
747
879
|
loadingText?: string;
|
|
748
880
|
}
|
|
749
881
|
|
|
750
|
-
const Button = React.forwardRef
|
|
882
|
+
const Button = React.forwardRef(
|
|
751
883
|
(
|
|
752
884
|
{
|
|
753
885
|
className,
|
|
@@ -761,8 +893,8 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
761
893
|
children,
|
|
762
894
|
disabled,
|
|
763
895
|
...props
|
|
764
|
-
},
|
|
765
|
-
ref
|
|
896
|
+
}: ButtonProps,
|
|
897
|
+
ref: React.Ref<HTMLButtonElement>
|
|
766
898
|
) => {
|
|
767
899
|
const Comp = asChild ? Slot : "button";
|
|
768
900
|
|
|
@@ -884,10 +1016,7 @@ export interface CheckboxProps
|
|
|
884
1016
|
separateLabel?: boolean;
|
|
885
1017
|
}
|
|
886
1018
|
|
|
887
|
-
const Checkbox = React.forwardRef
|
|
888
|
-
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
|
889
|
-
CheckboxProps
|
|
890
|
-
>(
|
|
1019
|
+
const Checkbox = React.forwardRef(
|
|
891
1020
|
(
|
|
892
1021
|
{
|
|
893
1022
|
className,
|
|
@@ -900,8 +1029,8 @@ const Checkbox = React.forwardRef<
|
|
|
900
1029
|
id,
|
|
901
1030
|
disabled,
|
|
902
1031
|
...props
|
|
903
|
-
},
|
|
904
|
-
ref
|
|
1032
|
+
}: CheckboxProps,
|
|
1033
|
+
ref: React.Ref<React.ElementRef<typeof CheckboxPrimitive.Root>>
|
|
905
1034
|
) => {
|
|
906
1035
|
const checkbox = (
|
|
907
1036
|
<CheckboxPrimitive.Root
|
|
@@ -1075,10 +1204,7 @@ export interface ConfirmationModalProps {
|
|
|
1075
1204
|
* />
|
|
1076
1205
|
* \`\`\`
|
|
1077
1206
|
*/
|
|
1078
|
-
const ConfirmationModal = React.forwardRef
|
|
1079
|
-
HTMLDivElement,
|
|
1080
|
-
ConfirmationModalProps
|
|
1081
|
-
>(
|
|
1207
|
+
const ConfirmationModal = React.forwardRef(
|
|
1082
1208
|
(
|
|
1083
1209
|
{
|
|
1084
1210
|
open,
|
|
@@ -1093,8 +1219,8 @@ const ConfirmationModal = React.forwardRef<
|
|
|
1093
1219
|
cancelButtonText = "Cancel",
|
|
1094
1220
|
trigger,
|
|
1095
1221
|
className,
|
|
1096
|
-
},
|
|
1097
|
-
ref
|
|
1222
|
+
}: ConfirmationModalProps,
|
|
1223
|
+
ref: React.Ref<HTMLDivElement>
|
|
1098
1224
|
) => {
|
|
1099
1225
|
const handleConfirm = () => {
|
|
1100
1226
|
onConfirm?.();
|
|
@@ -1136,6 +1262,104 @@ const ConfirmationModal = React.forwardRef<
|
|
|
1136
1262
|
ConfirmationModal.displayName = "ConfirmationModal";
|
|
1137
1263
|
|
|
1138
1264
|
export { ConfirmationModal };
|
|
1265
|
+
`,
|
|
1266
|
+
"contact-list-item": `import * as React from "react";
|
|
1267
|
+
|
|
1268
|
+
import { cn } from "@/lib/utils";
|
|
1269
|
+
|
|
1270
|
+
import { Avatar } from "./avatar";
|
|
1271
|
+
|
|
1272
|
+
export interface ContactListItemProps
|
|
1273
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, "onClick"> {
|
|
1274
|
+
/** Contact name \u2014 displayed as primary text and used for Avatar initials */
|
|
1275
|
+
name: string;
|
|
1276
|
+
/** Secondary text below the name (e.g., phone number, email) */
|
|
1277
|
+
subtitle?: string;
|
|
1278
|
+
/** Content rendered at the right edge (e.g., channel badge, status text) */
|
|
1279
|
+
trailing?: React.ReactNode;
|
|
1280
|
+
/** Avatar image source \u2014 shows image instead of initials when provided */
|
|
1281
|
+
avatarSrc?: string;
|
|
1282
|
+
/** Whether this item is currently selected/active */
|
|
1283
|
+
isSelected?: boolean;
|
|
1284
|
+
/** Click handler */
|
|
1285
|
+
onClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
/**
|
|
1289
|
+
* ContactListItem displays a contact entry with avatar, name, optional subtitle,
|
|
1290
|
+
* and trailing content \u2014 used in contact directories, user lists, and search results.
|
|
1291
|
+
*
|
|
1292
|
+
* @example
|
|
1293
|
+
* \`\`\`tsx
|
|
1294
|
+
* <ContactListItem
|
|
1295
|
+
* name="Aditi Kumar"
|
|
1296
|
+
* subtitle="+91 98765 43210"
|
|
1297
|
+
* trailing="MY01"
|
|
1298
|
+
* onClick={() => selectContact("1")}
|
|
1299
|
+
* />
|
|
1300
|
+
* \`\`\`
|
|
1301
|
+
*/
|
|
1302
|
+
const ContactListItem = React.forwardRef(
|
|
1303
|
+
(
|
|
1304
|
+
{
|
|
1305
|
+
name,
|
|
1306
|
+
subtitle,
|
|
1307
|
+
trailing,
|
|
1308
|
+
avatarSrc,
|
|
1309
|
+
isSelected = false,
|
|
1310
|
+
onClick,
|
|
1311
|
+
className,
|
|
1312
|
+
...props
|
|
1313
|
+
}: ContactListItemProps,
|
|
1314
|
+
ref: React.Ref<HTMLDivElement>
|
|
1315
|
+
) => {
|
|
1316
|
+
return (
|
|
1317
|
+
<div
|
|
1318
|
+
ref={ref}
|
|
1319
|
+
role="button"
|
|
1320
|
+
tabIndex={0}
|
|
1321
|
+
onClick={onClick}
|
|
1322
|
+
onKeyDown={(e) => {
|
|
1323
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1324
|
+
e.preventDefault();
|
|
1325
|
+
onClick?.(e as unknown as React.MouseEvent<HTMLDivElement>);
|
|
1326
|
+
}
|
|
1327
|
+
}}
|
|
1328
|
+
className={cn(
|
|
1329
|
+
"flex items-center gap-3 px-3 py-3 cursor-pointer transition-colors",
|
|
1330
|
+
isSelected
|
|
1331
|
+
? "bg-semantic-bg-ui"
|
|
1332
|
+
: "hover:bg-semantic-bg-hover",
|
|
1333
|
+
className
|
|
1334
|
+
)}
|
|
1335
|
+
{...props}
|
|
1336
|
+
>
|
|
1337
|
+
<Avatar name={name} src={avatarSrc} size="sm" />
|
|
1338
|
+
|
|
1339
|
+
<div className="flex-1 flex items-center justify-between min-w-0">
|
|
1340
|
+
<div className="flex flex-col min-w-0">
|
|
1341
|
+
<span className="text-sm font-medium text-semantic-text-primary leading-5 truncate">
|
|
1342
|
+
{name}
|
|
1343
|
+
</span>
|
|
1344
|
+
{subtitle && (
|
|
1345
|
+
<span className="text-xs text-semantic-text-muted">
|
|
1346
|
+
{subtitle}
|
|
1347
|
+
</span>
|
|
1348
|
+
)}
|
|
1349
|
+
</div>
|
|
1350
|
+
{trailing && (
|
|
1351
|
+
<span className="text-xs font-medium text-semantic-text-muted shrink-0 ml-2">
|
|
1352
|
+
{trailing}
|
|
1353
|
+
</span>
|
|
1354
|
+
)}
|
|
1355
|
+
</div>
|
|
1356
|
+
</div>
|
|
1357
|
+
);
|
|
1358
|
+
}
|
|
1359
|
+
);
|
|
1360
|
+
ContactListItem.displayName = "ContactListItem";
|
|
1361
|
+
|
|
1362
|
+
export { ContactListItem };
|
|
1139
1363
|
`,
|
|
1140
1364
|
"creatable-multi-select": `import * as React from "react"
|
|
1141
1365
|
import { cva } from "class-variance-authority"
|
|
@@ -1188,12 +1412,13 @@ export interface CreatableMultiSelectProps
|
|
|
1188
1412
|
creatableHint?: string
|
|
1189
1413
|
/** Helper text shown below the trigger */
|
|
1190
1414
|
helperText?: string
|
|
1415
|
+
/** Max number of items that can be selected (default: unlimited) */
|
|
1416
|
+
maxItems?: number
|
|
1417
|
+
/** Max character length per item when typing/creating (default: unlimited) */
|
|
1418
|
+
maxLengthPerItem?: number
|
|
1191
1419
|
}
|
|
1192
1420
|
|
|
1193
|
-
const CreatableMultiSelect = React.forwardRef
|
|
1194
|
-
HTMLDivElement,
|
|
1195
|
-
CreatableMultiSelectProps
|
|
1196
|
-
>(
|
|
1421
|
+
const CreatableMultiSelect = React.forwardRef(
|
|
1197
1422
|
(
|
|
1198
1423
|
{
|
|
1199
1424
|
className,
|
|
@@ -1205,9 +1430,11 @@ const CreatableMultiSelect = React.forwardRef<
|
|
|
1205
1430
|
state = "default",
|
|
1206
1431
|
creatableHint = "Type to create a custom option",
|
|
1207
1432
|
helperText,
|
|
1433
|
+
maxItems,
|
|
1434
|
+
maxLengthPerItem,
|
|
1208
1435
|
...props
|
|
1209
|
-
},
|
|
1210
|
-
ref
|
|
1436
|
+
}: CreatableMultiSelectProps,
|
|
1437
|
+
ref: React.Ref<HTMLDivElement>
|
|
1211
1438
|
) => {
|
|
1212
1439
|
const [isOpen, setIsOpen] = React.useState(false)
|
|
1213
1440
|
const [inputValue, setInputValue] = React.useState("")
|
|
@@ -1219,12 +1446,18 @@ const CreatableMultiSelect = React.forwardRef<
|
|
|
1219
1446
|
const addValue = React.useCallback(
|
|
1220
1447
|
(val: string) => {
|
|
1221
1448
|
const trimmed = val.trim()
|
|
1222
|
-
if (trimmed
|
|
1223
|
-
|
|
1449
|
+
if (!trimmed || value.includes(trimmed)) return
|
|
1450
|
+
if (maxItems != null && value.length >= maxItems) return
|
|
1451
|
+
const toAdd =
|
|
1452
|
+
maxLengthPerItem != null
|
|
1453
|
+
? trimmed.slice(0, maxLengthPerItem)
|
|
1454
|
+
: trimmed
|
|
1455
|
+
if (toAdd) {
|
|
1456
|
+
onValueChange?.([...value, toAdd])
|
|
1224
1457
|
setInputValue("")
|
|
1225
1458
|
}
|
|
1226
1459
|
},
|
|
1227
|
-
[value, onValueChange]
|
|
1460
|
+
[value, onValueChange, maxItems, maxLengthPerItem]
|
|
1228
1461
|
)
|
|
1229
1462
|
|
|
1230
1463
|
const removeValue = React.useCallback(
|
|
@@ -1328,9 +1561,13 @@ const CreatableMultiSelect = React.forwardRef<
|
|
|
1328
1561
|
type="text"
|
|
1329
1562
|
value={inputValue}
|
|
1330
1563
|
onChange={(e) => {
|
|
1331
|
-
|
|
1564
|
+
const v = e.target.value
|
|
1565
|
+
setInputValue(
|
|
1566
|
+
maxLengthPerItem != null ? v.slice(0, maxLengthPerItem) : v
|
|
1567
|
+
)
|
|
1332
1568
|
if (!isOpen) setIsOpen(true)
|
|
1333
1569
|
}}
|
|
1570
|
+
maxLength={maxLengthPerItem}
|
|
1334
1571
|
onFocus={() => {
|
|
1335
1572
|
if (!disabled) setIsOpen(true)
|
|
1336
1573
|
}}
|
|
@@ -1354,18 +1591,14 @@ const CreatableMultiSelect = React.forwardRef<
|
|
|
1354
1591
|
{/* Dropdown panel */}
|
|
1355
1592
|
{isOpen && (
|
|
1356
1593
|
<div className="absolute z-[9999] top-full mt-1 w-full bg-semantic-bg-primary border border-semantic-border-layout rounded shadow-md animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-200">
|
|
1357
|
-
{/* Creatable hint \u2014
|
|
1594
|
+
{/* Creatable hint \u2014 Enter key */}
|
|
1358
1595
|
<div className="flex items-center justify-between px-4 py-2 border-b border-semantic-border-layout">
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
Press enter to add
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
{creatableHint}
|
|
1366
|
-
</span>
|
|
1367
|
-
)}
|
|
1368
|
-
<kbd className="inline-flex items-center gap-0.5 rounded border border-semantic-border-layout bg-semantic-bg-ui px-1.5 py-0.5 text-[10px] text-semantic-text-muted font-medium">
|
|
1596
|
+
<span className="text-sm text-semantic-text-muted">
|
|
1597
|
+
{canAddCustom
|
|
1598
|
+
? \`Press enter to add "\${inputValue.trim()}"\`
|
|
1599
|
+
: creatableHint}
|
|
1600
|
+
</span>
|
|
1601
|
+
<kbd className="inline-flex items-center gap-0.5 rounded border border-semantic-border-layout bg-semantic-bg-ui px-1.5 py-0.5 text-[10px] text-semantic-text-muted font-medium shrink-0">
|
|
1369
1602
|
Enter \u21B5
|
|
1370
1603
|
</kbd>
|
|
1371
1604
|
</div>
|
|
@@ -1393,14 +1626,31 @@ const CreatableMultiSelect = React.forwardRef<
|
|
|
1393
1626
|
</div>
|
|
1394
1627
|
)}
|
|
1395
1628
|
|
|
1396
|
-
{/* Helper
|
|
1397
|
-
{
|
|
1398
|
-
<div className="flex items-center gap-
|
|
1399
|
-
<
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1629
|
+
{/* Helper row below trigger: when maxLengthPerItem show dynamic hint + counter (Figma); else optional static helperText */}
|
|
1630
|
+
{maxLengthPerItem != null ? (
|
|
1631
|
+
<div className="flex items-center justify-between gap-2 mt-1.5">
|
|
1632
|
+
<div className="flex items-center gap-1.5 text-xs text-semantic-text-muted min-w-0">
|
|
1633
|
+
<Info className="size-3.5 shrink-0 text-semantic-text-muted" />
|
|
1634
|
+
<p className="m-0 truncate">
|
|
1635
|
+
{inputValue.trim()
|
|
1636
|
+
? \`Press Enter to add "\${inputValue.trim()}" \u21B5\`
|
|
1637
|
+
: creatableHint}
|
|
1638
|
+
</p>
|
|
1639
|
+
</div>
|
|
1640
|
+
<span className="text-sm text-semantic-text-muted shrink-0">
|
|
1641
|
+
{inputValue.length}/{maxLengthPerItem}
|
|
1642
|
+
</span>
|
|
1403
1643
|
</div>
|
|
1644
|
+
) : (
|
|
1645
|
+
helperText &&
|
|
1646
|
+
!isOpen && (
|
|
1647
|
+
<div className="flex items-center gap-1.5 mt-1.5">
|
|
1648
|
+
<Info className="size-[18px] shrink-0 text-semantic-text-muted" />
|
|
1649
|
+
<p className="m-0 text-sm text-semantic-text-muted">
|
|
1650
|
+
{helperText}
|
|
1651
|
+
</p>
|
|
1652
|
+
</div>
|
|
1653
|
+
)
|
|
1404
1654
|
)}
|
|
1405
1655
|
</div>
|
|
1406
1656
|
)
|
|
@@ -1454,9 +1704,11 @@ export interface CreatableSelectProps
|
|
|
1454
1704
|
creatableHint?: string
|
|
1455
1705
|
/** Whether the select is disabled */
|
|
1456
1706
|
disabled?: boolean
|
|
1707
|
+
/** Max character length for the value (enforced when open and when creating) */
|
|
1708
|
+
maxLength?: number
|
|
1457
1709
|
}
|
|
1458
1710
|
|
|
1459
|
-
const CreatableSelect = React.forwardRef
|
|
1711
|
+
const CreatableSelect = React.forwardRef(
|
|
1460
1712
|
(
|
|
1461
1713
|
{
|
|
1462
1714
|
className,
|
|
@@ -1467,9 +1719,10 @@ const CreatableSelect = React.forwardRef<HTMLDivElement, CreatableSelectProps>(
|
|
|
1467
1719
|
placeholder = "Select an option",
|
|
1468
1720
|
creatableHint = "Type to create a custom option",
|
|
1469
1721
|
disabled = false,
|
|
1722
|
+
maxLength,
|
|
1470
1723
|
...props
|
|
1471
|
-
},
|
|
1472
|
-
ref
|
|
1724
|
+
}: CreatableSelectProps,
|
|
1725
|
+
ref: React.Ref<HTMLDivElement>
|
|
1473
1726
|
) => {
|
|
1474
1727
|
const [open, setOpen] = React.useState(false)
|
|
1475
1728
|
const [search, setSearch] = React.useState("")
|
|
@@ -1516,11 +1769,12 @@ const CreatableSelect = React.forwardRef<HTMLDivElement, CreatableSelectProps>(
|
|
|
1516
1769
|
const handleCreate = React.useCallback(() => {
|
|
1517
1770
|
const trimmed = search.trim()
|
|
1518
1771
|
if (trimmed) {
|
|
1519
|
-
|
|
1772
|
+
const value = maxLength != null ? trimmed.slice(0, maxLength) : trimmed
|
|
1773
|
+
onValueChange?.(value)
|
|
1520
1774
|
setOpen(false)
|
|
1521
1775
|
setSearch("")
|
|
1522
1776
|
}
|
|
1523
|
-
}, [search, onValueChange])
|
|
1777
|
+
}, [search, onValueChange, maxLength])
|
|
1524
1778
|
|
|
1525
1779
|
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
1526
1780
|
if (e.key === "Escape") {
|
|
@@ -1608,7 +1862,11 @@ const CreatableSelect = React.forwardRef<HTMLDivElement, CreatableSelectProps>(
|
|
|
1608
1862
|
ref={inputRef}
|
|
1609
1863
|
type="text"
|
|
1610
1864
|
value={search}
|
|
1611
|
-
onChange={(e) =>
|
|
1865
|
+
onChange={(e) => {
|
|
1866
|
+
const v = e.target.value
|
|
1867
|
+
setSearch(maxLength != null ? v.slice(0, maxLength) : v)
|
|
1868
|
+
}}
|
|
1869
|
+
maxLength={maxLength}
|
|
1612
1870
|
onKeyDown={handleKeyDown}
|
|
1613
1871
|
className="flex-1 min-w-0 bg-transparent outline-none text-base text-semantic-text-primary placeholder:text-semantic-text-muted"
|
|
1614
1872
|
placeholder={selectedLabel || placeholder}
|
|
@@ -1720,6 +1978,45 @@ const CreatableSelect = React.forwardRef<HTMLDivElement, CreatableSelectProps>(
|
|
|
1720
1978
|
CreatableSelect.displayName = "CreatableSelect"
|
|
1721
1979
|
|
|
1722
1980
|
export { CreatableSelect, creatableSelectTriggerVariants }
|
|
1981
|
+
`,
|
|
1982
|
+
"date-divider": `import * as React from "react";
|
|
1983
|
+
|
|
1984
|
+
import { cn } from "@/lib/utils";
|
|
1985
|
+
|
|
1986
|
+
/**
|
|
1987
|
+
* DateDivider component for separating chat messages by date.
|
|
1988
|
+
* Renders a horizontal line with centered date text.
|
|
1989
|
+
*
|
|
1990
|
+
* @example
|
|
1991
|
+
* \`\`\`tsx
|
|
1992
|
+
* <DateDivider>Today</DateDivider>
|
|
1993
|
+
* <DateDivider>March 20, 2026</DateDivider>
|
|
1994
|
+
* \`\`\`
|
|
1995
|
+
*/
|
|
1996
|
+
export interface DateDividerProps
|
|
1997
|
+
extends React.HTMLAttributes<HTMLDivElement> {
|
|
1998
|
+
/** The date text to display. Can be a string like "Today", "March 20, 2026", etc. */
|
|
1999
|
+
children: React.ReactNode;
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
const DateDivider = React.forwardRef(
|
|
2003
|
+
({ className, children, ...props }: DateDividerProps, ref: React.Ref<HTMLDivElement>) => (
|
|
2004
|
+
<div
|
|
2005
|
+
ref={ref}
|
|
2006
|
+
className={cn("flex items-center gap-4 my-4", className)}
|
|
2007
|
+
{...props}
|
|
2008
|
+
>
|
|
2009
|
+
<div className="flex-1 h-px bg-semantic-border-layout" />
|
|
2010
|
+
<span className="text-xs text-semantic-text-muted shrink-0">
|
|
2011
|
+
{children}
|
|
2012
|
+
</span>
|
|
2013
|
+
<div className="flex-1 h-px bg-semantic-border-layout" />
|
|
2014
|
+
</div>
|
|
2015
|
+
)
|
|
2016
|
+
);
|
|
2017
|
+
DateDivider.displayName = "DateDivider";
|
|
2018
|
+
|
|
2019
|
+
export { DateDivider };
|
|
1723
2020
|
`,
|
|
1724
2021
|
"delete-confirmation-modal": `import * as React from "react";
|
|
1725
2022
|
|
|
@@ -1789,10 +2086,7 @@ export interface DeleteConfirmationModalProps {
|
|
|
1789
2086
|
* />
|
|
1790
2087
|
* \`\`\`
|
|
1791
2088
|
*/
|
|
1792
|
-
const DeleteConfirmationModal = React.forwardRef
|
|
1793
|
-
HTMLDivElement,
|
|
1794
|
-
DeleteConfirmationModalProps
|
|
1795
|
-
>(
|
|
2089
|
+
const DeleteConfirmationModal = React.forwardRef(
|
|
1796
2090
|
(
|
|
1797
2091
|
{
|
|
1798
2092
|
open,
|
|
@@ -1808,8 +2102,8 @@ const DeleteConfirmationModal = React.forwardRef<
|
|
|
1808
2102
|
cancelButtonText = "Cancel",
|
|
1809
2103
|
trigger,
|
|
1810
2104
|
className,
|
|
1811
|
-
},
|
|
1812
|
-
ref
|
|
2105
|
+
}: DeleteConfirmationModalProps,
|
|
2106
|
+
ref: React.Ref<HTMLDivElement>
|
|
1813
2107
|
) => {
|
|
1814
2108
|
const [inputValue, setInputValue] = React.useState("");
|
|
1815
2109
|
const isConfirmEnabled = inputValue === confirmText;
|
|
@@ -1905,10 +2199,7 @@ const DialogPortal = DialogPrimitive.Portal;
|
|
|
1905
2199
|
|
|
1906
2200
|
const DialogClose = DialogPrimitive.Close;
|
|
1907
2201
|
|
|
1908
|
-
const DialogOverlay = React.forwardRef<
|
|
1909
|
-
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
|
1910
|
-
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
1911
|
-
>(({ className, ...props }, ref) => (
|
|
2202
|
+
const DialogOverlay = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>, ref: React.Ref<React.ElementRef<typeof DialogPrimitive.Overlay>>) => (
|
|
1912
2203
|
<DialogPrimitive.Overlay
|
|
1913
2204
|
ref={ref}
|
|
1914
2205
|
className={cn(
|
|
@@ -1966,10 +2257,7 @@ const hasDialogDescription = (children: React.ReactNode): boolean => {
|
|
|
1966
2257
|
return found;
|
|
1967
2258
|
};
|
|
1968
2259
|
|
|
1969
|
-
const DialogContent = React.forwardRef<
|
|
1970
|
-
React.ElementRef<typeof DialogPrimitive.Content>,
|
|
1971
|
-
DialogContentProps
|
|
1972
|
-
>(({ className, children, size, hideCloseButton = false, ...props }, ref) => {
|
|
2260
|
+
const DialogContent = React.forwardRef(({ className, children, size, hideCloseButton = false, ...props }: DialogContentProps, ref: React.Ref<React.ElementRef<typeof DialogPrimitive.Content>>) => {
|
|
1973
2261
|
const hasDescription = hasDialogDescription(children);
|
|
1974
2262
|
|
|
1975
2263
|
return (
|
|
@@ -2027,10 +2315,7 @@ const DialogFooter = ({
|
|
|
2027
2315
|
);
|
|
2028
2316
|
DialogFooter.displayName = "DialogFooter";
|
|
2029
2317
|
|
|
2030
|
-
const DialogTitle = React.forwardRef<
|
|
2031
|
-
React.ElementRef<typeof DialogPrimitive.Title>,
|
|
2032
|
-
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
|
2033
|
-
>(({ className, ...props }, ref) => (
|
|
2318
|
+
const DialogTitle = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>, ref: React.Ref<React.ElementRef<typeof DialogPrimitive.Title>>) => (
|
|
2034
2319
|
<DialogPrimitive.Title
|
|
2035
2320
|
ref={ref}
|
|
2036
2321
|
className={cn(
|
|
@@ -2042,10 +2327,7 @@ const DialogTitle = React.forwardRef<
|
|
|
2042
2327
|
));
|
|
2043
2328
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
2044
2329
|
|
|
2045
|
-
const DialogDescription = React.forwardRef<
|
|
2046
|
-
React.ElementRef<typeof DialogPrimitive.Description>,
|
|
2047
|
-
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
|
2048
|
-
>(({ className, ...props }, ref) => (
|
|
2330
|
+
const DialogDescription = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>, ref: React.Ref<React.ElementRef<typeof DialogPrimitive.Description>>) => (
|
|
2049
2331
|
<DialogPrimitive.Description
|
|
2050
2332
|
ref={ref}
|
|
2051
2333
|
className={cn("text-sm text-muted-foreground", className)}
|
|
@@ -2070,13 +2352,20 @@ export {
|
|
|
2070
2352
|
`,
|
|
2071
2353
|
"dropdown-menu": `import * as React from "react";
|
|
2072
2354
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
2073
|
-
import { Check, ChevronRight
|
|
2355
|
+
import { Check, ChevronRight } from "lucide-react";
|
|
2074
2356
|
|
|
2075
2357
|
import { cn } from "@/lib/utils";
|
|
2076
2358
|
|
|
2077
2359
|
const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
2078
2360
|
|
|
2079
|
-
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
|
2361
|
+
const DropdownMenuTrigger = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Trigger>, ref: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.Trigger>>) => (
|
|
2362
|
+
<DropdownMenuPrimitive.Trigger
|
|
2363
|
+
ref={ref}
|
|
2364
|
+
className={cn("focus-visible:outline-none focus-visible:ring-0", className)}
|
|
2365
|
+
{...props}
|
|
2366
|
+
/>
|
|
2367
|
+
));
|
|
2368
|
+
DropdownMenuTrigger.displayName = DropdownMenuPrimitive.Trigger.displayName;
|
|
2080
2369
|
|
|
2081
2370
|
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
2082
2371
|
|
|
@@ -2086,16 +2375,13 @@ const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
|
|
2086
2375
|
|
|
2087
2376
|
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
|
2088
2377
|
|
|
2089
|
-
const DropdownMenuSubTrigger = React.forwardRef<
|
|
2090
|
-
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
|
2091
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
|
2378
|
+
const DropdownMenuSubTrigger = React.forwardRef(({ className, inset, children, ...props }: React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
|
2092
2379
|
inset?: boolean;
|
|
2093
|
-
}
|
|
2094
|
-
>(({ className, inset, children, ...props }, ref) => (
|
|
2380
|
+
}, ref: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>>) => (
|
|
2095
2381
|
<DropdownMenuPrimitive.SubTrigger
|
|
2096
2382
|
ref={ref}
|
|
2097
2383
|
className={cn(
|
|
2098
|
-
"flex cursor-
|
|
2384
|
+
"flex cursor-pointer select-none items-center rounded-sm px-2 py-2 text-sm text-semantic-text-secondary outline-none focus:bg-semantic-bg-ui focus:text-semantic-text-primary data-[state=open]:bg-semantic-bg-ui",
|
|
2099
2385
|
inset && "pl-8",
|
|
2100
2386
|
className
|
|
2101
2387
|
)}
|
|
@@ -2108,10 +2394,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
|
|
|
2108
2394
|
DropdownMenuSubTrigger.displayName =
|
|
2109
2395
|
DropdownMenuPrimitive.SubTrigger.displayName;
|
|
2110
2396
|
|
|
2111
|
-
const DropdownMenuSubContent = React.forwardRef<
|
|
2112
|
-
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
|
2113
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
|
2114
|
-
>(({ className, ...props }, ref) => (
|
|
2397
|
+
const DropdownMenuSubContent = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>, ref: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.SubContent>>) => (
|
|
2115
2398
|
<DropdownMenuPrimitive.SubContent
|
|
2116
2399
|
ref={ref}
|
|
2117
2400
|
className={cn(
|
|
@@ -2124,10 +2407,7 @@ const DropdownMenuSubContent = React.forwardRef<
|
|
|
2124
2407
|
DropdownMenuSubContent.displayName =
|
|
2125
2408
|
DropdownMenuPrimitive.SubContent.displayName;
|
|
2126
2409
|
|
|
2127
|
-
const DropdownMenuContent = React.forwardRef<
|
|
2128
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
|
2129
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
|
2130
|
-
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
2410
|
+
const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }: React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>, ref: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.Content>>) => (
|
|
2131
2411
|
<DropdownMenuPrimitive.Portal>
|
|
2132
2412
|
<DropdownMenuPrimitive.Content
|
|
2133
2413
|
ref={ref}
|
|
@@ -2143,76 +2423,110 @@ const DropdownMenuContent = React.forwardRef<
|
|
|
2143
2423
|
));
|
|
2144
2424
|
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
|
2145
2425
|
|
|
2146
|
-
const DropdownMenuItem = React.forwardRef<
|
|
2147
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
|
2148
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
|
2426
|
+
const DropdownMenuItem = React.forwardRef(({ className, inset, children, description, suffix, ...props }: React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
|
2149
2427
|
inset?: boolean;
|
|
2150
|
-
|
|
2151
|
-
|
|
2428
|
+
/** Secondary text displayed below children */
|
|
2429
|
+
description?: string;
|
|
2430
|
+
/** Content displayed at the right edge of the item */
|
|
2431
|
+
suffix?: React.ReactNode;
|
|
2432
|
+
}, ref: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.Item>>) => (
|
|
2152
2433
|
<DropdownMenuPrimitive.Item
|
|
2153
2434
|
ref={ref}
|
|
2154
2435
|
className={cn(
|
|
2155
|
-
"relative flex cursor-
|
|
2436
|
+
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-2 text-sm text-semantic-text-secondary outline-none transition-colors focus:bg-semantic-bg-ui focus:text-semantic-text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
2156
2437
|
inset && "pl-8",
|
|
2157
2438
|
className
|
|
2158
2439
|
)}
|
|
2159
2440
|
{...props}
|
|
2160
|
-
|
|
2441
|
+
>
|
|
2442
|
+
{description ? (
|
|
2443
|
+
<div className="flex flex-1 flex-col">
|
|
2444
|
+
<span>{children}</span>
|
|
2445
|
+
<span className="text-xs text-semantic-text-muted">{description}</span>
|
|
2446
|
+
</div>
|
|
2447
|
+
) : (
|
|
2448
|
+
children
|
|
2449
|
+
)}
|
|
2450
|
+
{suffix && (
|
|
2451
|
+
<span className="ml-auto text-xs text-semantic-text-muted shrink-0 pl-2">{suffix}</span>
|
|
2452
|
+
)}
|
|
2453
|
+
</DropdownMenuPrimitive.Item>
|
|
2161
2454
|
));
|
|
2162
2455
|
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
|
2163
2456
|
|
|
2164
|
-
const DropdownMenuCheckboxItem = React.forwardRef<
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2457
|
+
const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, checked, description, suffix, ...props }: React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem> & {
|
|
2458
|
+
/** Secondary text displayed below children */
|
|
2459
|
+
description?: string;
|
|
2460
|
+
/** Content displayed at the right edge of the item */
|
|
2461
|
+
suffix?: React.ReactNode;
|
|
2462
|
+
}, ref: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>>) => (
|
|
2168
2463
|
<DropdownMenuPrimitive.CheckboxItem
|
|
2169
2464
|
ref={ref}
|
|
2170
2465
|
className={cn(
|
|
2171
|
-
"relative flex cursor-
|
|
2466
|
+
"relative flex cursor-pointer select-none items-center rounded-sm py-2 pl-8 pr-2 text-sm text-semantic-text-secondary outline-none transition-colors focus:bg-semantic-bg-ui focus:text-semantic-text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
2172
2467
|
className
|
|
2173
2468
|
)}
|
|
2174
2469
|
checked={checked}
|
|
2175
2470
|
{...props}
|
|
2176
2471
|
>
|
|
2177
|
-
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
2472
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center text-semantic-primary">
|
|
2178
2473
|
<DropdownMenuPrimitive.ItemIndicator>
|
|
2179
2474
|
<Check className="h-4 w-4" />
|
|
2180
2475
|
</DropdownMenuPrimitive.ItemIndicator>
|
|
2181
2476
|
</span>
|
|
2182
|
-
{
|
|
2477
|
+
{description ? (
|
|
2478
|
+
<div className="flex flex-1 flex-col">
|
|
2479
|
+
<span>{children}</span>
|
|
2480
|
+
<span className="text-xs text-semantic-text-muted">{description}</span>
|
|
2481
|
+
</div>
|
|
2482
|
+
) : (
|
|
2483
|
+
children
|
|
2484
|
+
)}
|
|
2485
|
+
{suffix && (
|
|
2486
|
+
<span className="ml-auto text-xs text-semantic-text-muted shrink-0 pl-2">{suffix}</span>
|
|
2487
|
+
)}
|
|
2183
2488
|
</DropdownMenuPrimitive.CheckboxItem>
|
|
2184
2489
|
));
|
|
2185
2490
|
DropdownMenuCheckboxItem.displayName =
|
|
2186
2491
|
DropdownMenuPrimitive.CheckboxItem.displayName;
|
|
2187
2492
|
|
|
2188
|
-
const DropdownMenuRadioItem = React.forwardRef<
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2493
|
+
const DropdownMenuRadioItem = React.forwardRef(({ className, children, description, suffix, ...props }: React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem> & {
|
|
2494
|
+
/** Secondary text displayed below children */
|
|
2495
|
+
description?: string;
|
|
2496
|
+
/** Content displayed at the right edge of the item */
|
|
2497
|
+
suffix?: React.ReactNode;
|
|
2498
|
+
}, ref: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>>) => (
|
|
2192
2499
|
<DropdownMenuPrimitive.RadioItem
|
|
2193
2500
|
ref={ref}
|
|
2194
2501
|
className={cn(
|
|
2195
|
-
"relative flex cursor-
|
|
2502
|
+
"relative flex cursor-pointer select-none items-center rounded-sm py-2 pl-8 pr-2 text-sm text-semantic-text-secondary outline-none transition-colors focus:bg-semantic-bg-ui focus:text-semantic-text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
2196
2503
|
className
|
|
2197
2504
|
)}
|
|
2198
2505
|
{...props}
|
|
2199
2506
|
>
|
|
2200
|
-
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
2507
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center text-semantic-primary">
|
|
2201
2508
|
<DropdownMenuPrimitive.ItemIndicator>
|
|
2202
|
-
<
|
|
2509
|
+
<Check className="h-4 w-4" />
|
|
2203
2510
|
</DropdownMenuPrimitive.ItemIndicator>
|
|
2204
2511
|
</span>
|
|
2205
|
-
{
|
|
2512
|
+
{description ? (
|
|
2513
|
+
<div className="flex flex-1 flex-col">
|
|
2514
|
+
<span>{children}</span>
|
|
2515
|
+
<span className="text-xs text-semantic-text-muted">{description}</span>
|
|
2516
|
+
</div>
|
|
2517
|
+
) : (
|
|
2518
|
+
children
|
|
2519
|
+
)}
|
|
2520
|
+
{suffix && (
|
|
2521
|
+
<span className="ml-auto text-xs text-semantic-text-muted shrink-0 pl-2">{suffix}</span>
|
|
2522
|
+
)}
|
|
2206
2523
|
</DropdownMenuPrimitive.RadioItem>
|
|
2207
2524
|
));
|
|
2208
2525
|
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
|
2209
2526
|
|
|
2210
|
-
const DropdownMenuLabel = React.forwardRef<
|
|
2211
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
|
2212
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
|
2527
|
+
const DropdownMenuLabel = React.forwardRef(({ className, inset, ...props }: React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
|
2213
2528
|
inset?: boolean;
|
|
2214
|
-
}
|
|
2215
|
-
>(({ className, inset, ...props }, ref) => (
|
|
2529
|
+
}, ref: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.Label>>) => (
|
|
2216
2530
|
<DropdownMenuPrimitive.Label
|
|
2217
2531
|
ref={ref}
|
|
2218
2532
|
className={cn(
|
|
@@ -2225,10 +2539,7 @@ const DropdownMenuLabel = React.forwardRef<
|
|
|
2225
2539
|
));
|
|
2226
2540
|
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
|
2227
2541
|
|
|
2228
|
-
const DropdownMenuSeparator = React.forwardRef<
|
|
2229
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
|
2230
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
|
2231
|
-
>(({ className, ...props }, ref) => (
|
|
2542
|
+
const DropdownMenuSeparator = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>, ref: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.Separator>>) => (
|
|
2232
2543
|
<DropdownMenuPrimitive.Separator
|
|
2233
2544
|
ref={ref}
|
|
2234
2545
|
className={cn("-mx-1 my-1 h-px bg-semantic-border-layout", className)}
|
|
@@ -2395,7 +2706,7 @@ export interface FormModalProps {
|
|
|
2395
2706
|
* </FormModal>
|
|
2396
2707
|
* \`\`\`
|
|
2397
2708
|
*/
|
|
2398
|
-
const FormModal = React.forwardRef
|
|
2709
|
+
const FormModal = React.forwardRef(
|
|
2399
2710
|
(
|
|
2400
2711
|
{
|
|
2401
2712
|
open,
|
|
@@ -2411,8 +2722,8 @@ const FormModal = React.forwardRef<HTMLDivElement, FormModalProps>(
|
|
|
2411
2722
|
disableSave = false,
|
|
2412
2723
|
className,
|
|
2413
2724
|
size = "sm",
|
|
2414
|
-
},
|
|
2415
|
-
ref
|
|
2725
|
+
}: FormModalProps,
|
|
2726
|
+
ref: React.Ref<HTMLDivElement>
|
|
2416
2727
|
) => {
|
|
2417
2728
|
const handleSave = () => {
|
|
2418
2729
|
onSave?.();
|
|
@@ -2461,6 +2772,51 @@ const FormModal = React.forwardRef<HTMLDivElement, FormModalProps>(
|
|
|
2461
2772
|
FormModal.displayName = "FormModal";
|
|
2462
2773
|
|
|
2463
2774
|
export { FormModal };
|
|
2775
|
+
`,
|
|
2776
|
+
"image-media": `import * as React from "react";
|
|
2777
|
+
|
|
2778
|
+
import { cn } from "@/lib/utils";
|
|
2779
|
+
|
|
2780
|
+
/**
|
|
2781
|
+
* ImageMedia component for displaying images in chat messages.
|
|
2782
|
+
*
|
|
2783
|
+
* @example
|
|
2784
|
+
* \`\`\`tsx
|
|
2785
|
+
* <ImageMedia src="https://example.com/photo.jpg" />
|
|
2786
|
+
* <ImageMedia src="https://example.com/photo.jpg" alt="A sunset" />
|
|
2787
|
+
* <ImageMedia src="https://example.com/photo.jpg" maxHeight={400} />
|
|
2788
|
+
* <ImageMedia src="https://example.com/photo.jpg" maxHeight="50vh" />
|
|
2789
|
+
* \`\`\`
|
|
2790
|
+
*/
|
|
2791
|
+
export interface ImageMediaProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
2792
|
+
/** Image source URL */
|
|
2793
|
+
src: string;
|
|
2794
|
+
/** Alt text for the image */
|
|
2795
|
+
alt?: string;
|
|
2796
|
+
/** Maximum height of the image. Defaults to 280px */
|
|
2797
|
+
maxHeight?: number | string;
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2800
|
+
const ImageMedia = React.forwardRef(
|
|
2801
|
+
({ className, src, alt = "Image", maxHeight = 280, ...props }: ImageMediaProps, ref: React.Ref<HTMLDivElement>) => {
|
|
2802
|
+
const maxHeightStyle =
|
|
2803
|
+
typeof maxHeight === "number" ? \`\${maxHeight}px\` : maxHeight;
|
|
2804
|
+
|
|
2805
|
+
return (
|
|
2806
|
+
<div ref={ref} className={cn("relative", className)} {...props}>
|
|
2807
|
+
<img
|
|
2808
|
+
src={src}
|
|
2809
|
+
alt={alt}
|
|
2810
|
+
className="w-full rounded-t object-cover"
|
|
2811
|
+
style={{ maxHeight: maxHeightStyle }}
|
|
2812
|
+
/>
|
|
2813
|
+
</div>
|
|
2814
|
+
);
|
|
2815
|
+
}
|
|
2816
|
+
);
|
|
2817
|
+
ImageMedia.displayName = "ImageMedia";
|
|
2818
|
+
|
|
2819
|
+
export { ImageMedia };
|
|
2464
2820
|
`,
|
|
2465
2821
|
"input": `import * as React from "react";
|
|
2466
2822
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
@@ -2477,9 +2833,9 @@ const inputVariants = cva(
|
|
|
2477
2833
|
variants: {
|
|
2478
2834
|
state: {
|
|
2479
2835
|
default:
|
|
2480
|
-
"border border-semantic-border-input
|
|
2836
|
+
"border border-semantic-border-input focus:outline-none focus:border-semantic-border-input-focus focus:shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
|
|
2481
2837
|
error:
|
|
2482
|
-
"border border-semantic-error-primary/40
|
|
2838
|
+
"border border-semantic-error-primary/40 focus:outline-none focus:border-semantic-error-primary focus:shadow-[0_0_0_1px_rgba(240,68,56,0.1)]",
|
|
2483
2839
|
},
|
|
2484
2840
|
},
|
|
2485
2841
|
defaultVariants: {
|
|
@@ -2506,8 +2862,8 @@ export interface InputProps
|
|
|
2506
2862
|
showCheckIcon?: boolean;
|
|
2507
2863
|
}
|
|
2508
2864
|
|
|
2509
|
-
const Input = React.forwardRef
|
|
2510
|
-
({ className, state, type, showCheckIcon, onFocus, onBlur, onWheel, ...props }, ref) => {
|
|
2865
|
+
const Input = React.forwardRef(
|
|
2866
|
+
({ className, state, type, showCheckIcon, onFocus, onBlur, onWheel, ...props }: InputProps, ref: React.Ref<HTMLInputElement>) => {
|
|
2511
2867
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
2512
2868
|
|
|
2513
2869
|
const inputEl = (
|
|
@@ -2651,7 +3007,7 @@ export interface MultiSelectProps extends VariantProps<
|
|
|
2651
3007
|
* />
|
|
2652
3008
|
* \`\`\`
|
|
2653
3009
|
*/
|
|
2654
|
-
const MultiSelect = React.forwardRef
|
|
3010
|
+
const MultiSelect = React.forwardRef(
|
|
2655
3011
|
(
|
|
2656
3012
|
{
|
|
2657
3013
|
label,
|
|
@@ -2674,8 +3030,8 @@ const MultiSelect = React.forwardRef<HTMLButtonElement, MultiSelectProps>(
|
|
|
2674
3030
|
state,
|
|
2675
3031
|
id,
|
|
2676
3032
|
name,
|
|
2677
|
-
},
|
|
2678
|
-
ref
|
|
3033
|
+
}: MultiSelectProps,
|
|
3034
|
+
ref: React.Ref<HTMLButtonElement>
|
|
2679
3035
|
) => {
|
|
2680
3036
|
// Internal state for selected values (uncontrolled mode)
|
|
2681
3037
|
const [internalValue, setInternalValue] =
|
|
@@ -3070,7 +3426,7 @@ export interface PageHeaderProps
|
|
|
3070
3426
|
mobileOverflowLimit?: number;
|
|
3071
3427
|
}
|
|
3072
3428
|
|
|
3073
|
-
const PageHeader = React.forwardRef
|
|
3429
|
+
const PageHeader = React.forwardRef(
|
|
3074
3430
|
(
|
|
3075
3431
|
{
|
|
3076
3432
|
className,
|
|
@@ -3086,8 +3442,8 @@ const PageHeader = React.forwardRef<HTMLDivElement, PageHeaderProps>(
|
|
|
3086
3442
|
layout = "responsive",
|
|
3087
3443
|
mobileOverflowLimit = 2,
|
|
3088
3444
|
...props
|
|
3089
|
-
},
|
|
3090
|
-
ref
|
|
3445
|
+
}: PageHeaderProps,
|
|
3446
|
+
ref: React.Ref<HTMLDivElement>
|
|
3091
3447
|
) => {
|
|
3092
3448
|
// State for overflow expansion (moved to top level)
|
|
3093
3449
|
const [isOverflowExpanded, setIsOverflowExpanded] = React.useState(false);
|
|
@@ -3593,44 +3949,285 @@ export {
|
|
|
3593
3949
|
PaginationWidget,
|
|
3594
3950
|
};
|
|
3595
3951
|
`,
|
|
3596
|
-
"
|
|
3597
|
-
import {
|
|
3952
|
+
"panel": `import * as React from "react";
|
|
3953
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3954
|
+
import { X } from "lucide-react";
|
|
3955
|
+
|
|
3598
3956
|
import { cn } from "@/lib/utils";
|
|
3599
3957
|
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
}
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3958
|
+
import { Button } from "./button";
|
|
3959
|
+
|
|
3960
|
+
/**
|
|
3961
|
+
* Panel root variants
|
|
3962
|
+
*/
|
|
3963
|
+
const panelVariants = cva(
|
|
3964
|
+
"border-l border-semantic-border-layout bg-semantic-bg-primary flex flex-col overflow-hidden transition-all duration-300 ease-in-out shrink-0",
|
|
3965
|
+
{
|
|
3966
|
+
variants: {
|
|
3967
|
+
size: {
|
|
3968
|
+
sm: "",
|
|
3969
|
+
default: "",
|
|
3970
|
+
lg: "",
|
|
3971
|
+
},
|
|
3972
|
+
},
|
|
3973
|
+
defaultVariants: {
|
|
3974
|
+
size: "default",
|
|
3975
|
+
},
|
|
3976
|
+
}
|
|
3977
|
+
);
|
|
3978
|
+
|
|
3979
|
+
const panelWidths = {
|
|
3980
|
+
sm: "w-[280px]",
|
|
3981
|
+
default: "w-[320px]",
|
|
3982
|
+
lg: "w-[400px]",
|
|
3983
|
+
} as const;
|
|
3984
|
+
|
|
3985
|
+
export interface PanelProps
|
|
3986
|
+
extends React.HTMLAttributes<HTMLElement>,
|
|
3987
|
+
VariantProps<typeof panelVariants> {
|
|
3988
|
+
/** Whether the panel is open */
|
|
3989
|
+
open?: boolean;
|
|
3990
|
+
/** Panel title displayed in the header */
|
|
3991
|
+
title?: string;
|
|
3992
|
+
/** Callback when close button is clicked */
|
|
3993
|
+
onClose?: () => void;
|
|
3994
|
+
/** Optional footer content (e.g., action buttons) */
|
|
3995
|
+
footer?: React.ReactNode;
|
|
3996
|
+
/** Custom header content \u2014 replaces the default title + close button */
|
|
3997
|
+
header?: React.ReactNode;
|
|
3623
3998
|
}
|
|
3624
3999
|
|
|
3625
4000
|
/**
|
|
3626
|
-
*
|
|
3627
|
-
*
|
|
4001
|
+
* Panel is a collapsible side panel layout with a header, scrollable body,
|
|
4002
|
+
* and optional footer \u2014 used for detail views, settings, and edit forms.
|
|
3628
4003
|
*
|
|
3629
4004
|
* @example
|
|
3630
4005
|
* \`\`\`tsx
|
|
3631
|
-
*
|
|
3632
|
-
*
|
|
3633
|
-
* label="
|
|
4006
|
+
* <Panel open={isOpen} title="Contact Details" onClose={() => setIsOpen(false)}>
|
|
4007
|
+
* <TextField label="Name" value="Aditi Kumar" disabled size="sm" />
|
|
4008
|
+
* <TextField label="Email" value="email@example.com" disabled size="sm" />
|
|
4009
|
+
* </Panel>
|
|
4010
|
+
* \`\`\`
|
|
4011
|
+
*/
|
|
4012
|
+
const Panel = React.forwardRef(
|
|
4013
|
+
(
|
|
4014
|
+
{
|
|
4015
|
+
open = true,
|
|
4016
|
+
title,
|
|
4017
|
+
onClose,
|
|
4018
|
+
footer,
|
|
4019
|
+
header,
|
|
4020
|
+
size,
|
|
4021
|
+
className,
|
|
4022
|
+
children,
|
|
4023
|
+
"aria-label": ariaLabel,
|
|
4024
|
+
onKeyDown,
|
|
4025
|
+
...props
|
|
4026
|
+
}: PanelProps,
|
|
4027
|
+
ref: React.Ref<HTMLElement>
|
|
4028
|
+
) => {
|
|
4029
|
+
const resolvedSize = size ?? "default";
|
|
4030
|
+
const widthClass = panelWidths[resolvedSize];
|
|
4031
|
+
const innerRef = React.useRef<HTMLDivElement>(null);
|
|
4032
|
+
|
|
4033
|
+
// Focus the inner container when the panel opens
|
|
4034
|
+
React.useEffect(() => {
|
|
4035
|
+
if (open) {
|
|
4036
|
+
innerRef.current?.focus();
|
|
4037
|
+
}
|
|
4038
|
+
}, [open]);
|
|
4039
|
+
|
|
4040
|
+
const handleKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {
|
|
4041
|
+
if (e.key === "Escape" && onClose) {
|
|
4042
|
+
onClose();
|
|
4043
|
+
}
|
|
4044
|
+
// Forward to user-provided onKeyDown if any
|
|
4045
|
+
onKeyDown?.(e);
|
|
4046
|
+
};
|
|
4047
|
+
|
|
4048
|
+
return (
|
|
4049
|
+
<aside
|
|
4050
|
+
ref={ref}
|
|
4051
|
+
className={cn(
|
|
4052
|
+
panelVariants({ size }),
|
|
4053
|
+
open ? widthClass : "w-0 border-l-0",
|
|
4054
|
+
className
|
|
4055
|
+
)}
|
|
4056
|
+
aria-label={ariaLabel ?? title}
|
|
4057
|
+
aria-hidden={!open}
|
|
4058
|
+
onKeyDown={handleKeyDown}
|
|
4059
|
+
{...props}
|
|
4060
|
+
>
|
|
4061
|
+
<div
|
|
4062
|
+
ref={innerRef}
|
|
4063
|
+
tabIndex={-1}
|
|
4064
|
+
className={cn(widthClass, "flex flex-col h-full outline-none")}
|
|
4065
|
+
>
|
|
4066
|
+
{/* Header */}
|
|
4067
|
+
{header ?? (
|
|
4068
|
+
<div className="flex items-center gap-3 px-4 h-14 border-b border-semantic-border-layout shrink-0">
|
|
4069
|
+
{title && (
|
|
4070
|
+
<span className="flex-1 text-base font-semibold text-semantic-text-primary truncate">
|
|
4071
|
+
{title}
|
|
4072
|
+
</span>
|
|
4073
|
+
)}
|
|
4074
|
+
{onClose && (
|
|
4075
|
+
<Button
|
|
4076
|
+
variant="ghost"
|
|
4077
|
+
size="icon"
|
|
4078
|
+
onClick={onClose}
|
|
4079
|
+
aria-label="Close"
|
|
4080
|
+
>
|
|
4081
|
+
<X className="size-5" />
|
|
4082
|
+
</Button>
|
|
4083
|
+
)}
|
|
4084
|
+
</div>
|
|
4085
|
+
)}
|
|
4086
|
+
|
|
4087
|
+
{/* Body */}
|
|
4088
|
+
<div className="flex-1 overflow-y-auto">
|
|
4089
|
+
{children}
|
|
4090
|
+
</div>
|
|
4091
|
+
|
|
4092
|
+
{/* Footer */}
|
|
4093
|
+
{footer && (
|
|
4094
|
+
<div className="flex gap-3 px-4 py-3 shrink-0 border-t border-semantic-border-layout">
|
|
4095
|
+
{footer}
|
|
4096
|
+
</div>
|
|
4097
|
+
)}
|
|
4098
|
+
</div>
|
|
4099
|
+
</aside>
|
|
4100
|
+
);
|
|
4101
|
+
}
|
|
4102
|
+
);
|
|
4103
|
+
Panel.displayName = "Panel";
|
|
4104
|
+
|
|
4105
|
+
export { Panel, panelVariants };
|
|
4106
|
+
`,
|
|
4107
|
+
"phone-input": `import * as React from "react";
|
|
4108
|
+
import { ChevronDown } from "lucide-react";
|
|
4109
|
+
|
|
4110
|
+
import { cn } from "@/lib/utils";
|
|
4111
|
+
|
|
4112
|
+
/**
|
|
4113
|
+
* A phone number input with a country code prefix area.
|
|
4114
|
+
*
|
|
4115
|
+
* @example
|
|
4116
|
+
* \`\`\`tsx
|
|
4117
|
+
* <PhoneInput placeholder="Enter phone number" />
|
|
4118
|
+
* <PhoneInput countryFlag="\u{1F1FA}\u{1F1F8}" countryCode="+1" />
|
|
4119
|
+
* <PhoneInput onCountryClick={() => openCountryPicker()} />
|
|
4120
|
+
* \`\`\`
|
|
4121
|
+
*/
|
|
4122
|
+
export interface PhoneInputProps
|
|
4123
|
+
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type"> {
|
|
4124
|
+
/** Country flag emoji (e.g., "\u{1F1EE}\u{1F1F3}", "\u{1F1FA}\u{1F1F8}"). Defaults to "\u{1F1EE}\u{1F1F3}" */
|
|
4125
|
+
countryFlag?: string;
|
|
4126
|
+
/** Country dial code (e.g., "+91", "+1"). Defaults to "+91" */
|
|
4127
|
+
countryCode?: string;
|
|
4128
|
+
/** Whether to show the chevron dropdown indicator. Defaults to true */
|
|
4129
|
+
showChevron?: boolean;
|
|
4130
|
+
/** Handler called when the country code area is clicked */
|
|
4131
|
+
onCountryClick?: () => void;
|
|
4132
|
+
/** Additional className for the outer wrapper */
|
|
4133
|
+
wrapperClassName?: string;
|
|
4134
|
+
}
|
|
4135
|
+
|
|
4136
|
+
const PhoneInput = React.forwardRef(
|
|
4137
|
+
(
|
|
4138
|
+
{
|
|
4139
|
+
className,
|
|
4140
|
+
countryFlag = "\u{1F1EE}\u{1F1F3}",
|
|
4141
|
+
countryCode = "+91",
|
|
4142
|
+
showChevron = true,
|
|
4143
|
+
onCountryClick,
|
|
4144
|
+
wrapperClassName,
|
|
4145
|
+
disabled,
|
|
4146
|
+
...props
|
|
4147
|
+
}: PhoneInputProps,
|
|
4148
|
+
ref: React.Ref<HTMLInputElement>
|
|
4149
|
+
) => {
|
|
4150
|
+
return (
|
|
4151
|
+
<div
|
|
4152
|
+
className={cn(
|
|
4153
|
+
"flex items-center border border-semantic-border-layout rounded-lg focus-within:border-semantic-border-focus transition-colors",
|
|
4154
|
+
disabled && "opacity-60",
|
|
4155
|
+
wrapperClassName
|
|
4156
|
+
)}
|
|
4157
|
+
>
|
|
4158
|
+
<div
|
|
4159
|
+
className={cn(
|
|
4160
|
+
"flex items-center gap-1.5 pl-3 pr-2 h-10 shrink-0",
|
|
4161
|
+
onCountryClick && "cursor-pointer"
|
|
4162
|
+
)}
|
|
4163
|
+
onClick={onCountryClick}
|
|
4164
|
+
data-testid="phone-input-country"
|
|
4165
|
+
>
|
|
4166
|
+
<span className="text-sm">{countryFlag}</span>
|
|
4167
|
+
<span className="text-sm text-semantic-text-secondary">
|
|
4168
|
+
{countryCode}
|
|
4169
|
+
</span>
|
|
4170
|
+
{showChevron && (
|
|
4171
|
+
<ChevronDown className="size-3 text-semantic-text-muted" />
|
|
4172
|
+
)}
|
|
4173
|
+
</div>
|
|
4174
|
+
<div className="w-px h-5 bg-semantic-border-layout shrink-0" />
|
|
4175
|
+
<input
|
|
4176
|
+
type="tel"
|
|
4177
|
+
ref={ref}
|
|
4178
|
+
disabled={disabled}
|
|
4179
|
+
className={cn(
|
|
4180
|
+
"flex-1 h-10 px-3 text-sm text-semantic-text-primary placeholder:text-semantic-text-muted outline-none bg-transparent disabled:cursor-not-allowed",
|
|
4181
|
+
className
|
|
4182
|
+
)}
|
|
4183
|
+
{...props}
|
|
4184
|
+
/>
|
|
4185
|
+
</div>
|
|
4186
|
+
);
|
|
4187
|
+
}
|
|
4188
|
+
);
|
|
4189
|
+
PhoneInput.displayName = "PhoneInput";
|
|
4190
|
+
|
|
4191
|
+
export { PhoneInput };
|
|
4192
|
+
`,
|
|
4193
|
+
"readable-field": `import * as React from "react";
|
|
4194
|
+
import { Copy, Check, Eye, EyeOff } from "lucide-react";
|
|
4195
|
+
import { cn } from "@/lib/utils";
|
|
4196
|
+
|
|
4197
|
+
export interface ReadableFieldProps
|
|
4198
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
4199
|
+
/** Label text displayed above the field */
|
|
4200
|
+
label: string;
|
|
4201
|
+
/** Value to display and copy */
|
|
4202
|
+
value: string;
|
|
4203
|
+
/** Helper text displayed below the field */
|
|
4204
|
+
helperText?: string;
|
|
4205
|
+
/** When true, masks the value with dots and shows eye toggle */
|
|
4206
|
+
secret?: boolean;
|
|
4207
|
+
/** Header action (e.g., "Regenerate" link) */
|
|
4208
|
+
headerAction?: {
|
|
4209
|
+
label: string;
|
|
4210
|
+
onClick: () => void;
|
|
4211
|
+
/** When true, button is shown but non-interactive */
|
|
4212
|
+
disabled?: boolean;
|
|
4213
|
+
/** Tooltip text shown on hover when disabled */
|
|
4214
|
+
disabledTooltip?: string;
|
|
4215
|
+
};
|
|
4216
|
+
/** Callback when value is copied */
|
|
4217
|
+
onValueCopy?: (value: string) => void;
|
|
4218
|
+
/** Additional class for the input container */
|
|
4219
|
+
inputClassName?: string;
|
|
4220
|
+
}
|
|
4221
|
+
|
|
4222
|
+
/**
|
|
4223
|
+
* ReadableField displays a read-only value with copy-to-clipboard functionality.
|
|
4224
|
+
* Supports secret mode for sensitive data like API keys and passwords.
|
|
4225
|
+
*
|
|
4226
|
+
* @example
|
|
4227
|
+
* \`\`\`tsx
|
|
4228
|
+
* // Simple readable field
|
|
4229
|
+
* <ReadableField
|
|
4230
|
+
* label="Base URL"
|
|
3634
4231
|
* value="https://api.myoperator.co/v3/voice/gateway"
|
|
3635
4232
|
* />
|
|
3636
4233
|
*
|
|
@@ -3647,7 +4244,7 @@ export interface ReadableFieldProps
|
|
|
3647
4244
|
* />
|
|
3648
4245
|
* \`\`\`
|
|
3649
4246
|
*/
|
|
3650
|
-
export const ReadableField = React.forwardRef
|
|
4247
|
+
export const ReadableField = React.forwardRef(
|
|
3651
4248
|
(
|
|
3652
4249
|
{
|
|
3653
4250
|
label,
|
|
@@ -3659,8 +4256,8 @@ export const ReadableField = React.forwardRef<HTMLDivElement, ReadableFieldProps
|
|
|
3659
4256
|
className,
|
|
3660
4257
|
inputClassName,
|
|
3661
4258
|
...props
|
|
3662
|
-
},
|
|
3663
|
-
ref
|
|
4259
|
+
}: ReadableFieldProps,
|
|
4260
|
+
ref: React.Ref<HTMLDivElement>
|
|
3664
4261
|
) => {
|
|
3665
4262
|
const [copied, setCopied] = React.useState(false);
|
|
3666
4263
|
const [isVisible, setIsVisible] = React.useState(!secret);
|
|
@@ -3806,9 +4403,80 @@ export const ReadableField = React.forwardRef<HTMLDivElement, ReadableFieldProps
|
|
|
3806
4403
|
);
|
|
3807
4404
|
|
|
3808
4405
|
ReadableField.displayName = "ReadableField";
|
|
4406
|
+
`,
|
|
4407
|
+
"reply-quote": `import * as React from "react";
|
|
4408
|
+
|
|
4409
|
+
import { cn } from "@/lib/utils";
|
|
4410
|
+
|
|
4411
|
+
/**
|
|
4412
|
+
* ReplyQuote component for displaying a quoted message with a brand-accented left border.
|
|
4413
|
+
* Used in chat applications for reply-to previews.
|
|
4414
|
+
*
|
|
4415
|
+
* When an \`onClick\` handler is provided, the component becomes interactive:
|
|
4416
|
+
* it receives \`role="button"\`, \`tabIndex={0}\`, and keyboard support (Enter/Space).
|
|
4417
|
+
* A focus ring is shown when focused via keyboard.
|
|
4418
|
+
*
|
|
4419
|
+
* @example
|
|
4420
|
+
* \`\`\`tsx
|
|
4421
|
+
* <ReplyQuote sender="John Doe" message="Hello, how are you?" />
|
|
4422
|
+
* <ReplyQuote sender="Jane" message="Check this out!" onClick={() => scrollToMessage()} />
|
|
4423
|
+
* \`\`\`
|
|
4424
|
+
*/
|
|
4425
|
+
export interface ReplyQuoteProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4426
|
+
/** Name of the person being quoted */
|
|
4427
|
+
sender: string;
|
|
4428
|
+
/** The quoted message text */
|
|
4429
|
+
message: string;
|
|
4430
|
+
}
|
|
4431
|
+
|
|
4432
|
+
const ReplyQuote = React.forwardRef(
|
|
4433
|
+
({ className, sender, message, onClick, onKeyDown, role, tabIndex, "aria-label": ariaLabel, ...props }: ReplyQuoteProps, ref: React.Ref<HTMLDivElement>) => {
|
|
4434
|
+
const isInteractive = !!onClick;
|
|
4435
|
+
|
|
4436
|
+
const handleKeyDown = React.useCallback(
|
|
4437
|
+
(e: React.KeyboardEvent<HTMLDivElement>) => {
|
|
4438
|
+
if (onClick && (e.key === "Enter" || e.key === " ")) {
|
|
4439
|
+
if (e.key === " ") {
|
|
4440
|
+
e.preventDefault();
|
|
4441
|
+
}
|
|
4442
|
+
onClick(e as unknown as React.MouseEvent<HTMLDivElement>);
|
|
4443
|
+
}
|
|
4444
|
+
onKeyDown?.(e);
|
|
4445
|
+
},
|
|
4446
|
+
[onClick, onKeyDown]
|
|
4447
|
+
);
|
|
4448
|
+
|
|
4449
|
+
return (
|
|
4450
|
+
<div
|
|
4451
|
+
ref={ref}
|
|
4452
|
+
className={cn(
|
|
4453
|
+
"w-full bg-semantic-bg-ui border-l-[3px] border-semantic-border-accent rounded-sm px-4 py-1.5 mb-2 h-[56px] flex flex-col justify-center cursor-pointer hover:bg-semantic-bg-hover transition-colors",
|
|
4454
|
+
isInteractive && "focus-visible:ring-2 focus-visible:ring-semantic-border-focus focus-visible:ring-offset-1 focus-visible:outline-none",
|
|
4455
|
+
className
|
|
4456
|
+
)}
|
|
4457
|
+
role={role ?? (isInteractive ? "button" : undefined)}
|
|
4458
|
+
tabIndex={tabIndex ?? (isInteractive ? 0 : undefined)}
|
|
4459
|
+
onClick={onClick}
|
|
4460
|
+
onKeyDown={isInteractive ? handleKeyDown : onKeyDown}
|
|
4461
|
+
aria-label={ariaLabel ?? \`Quoted reply from \${sender}: \${message}\`}
|
|
4462
|
+
{...props}
|
|
4463
|
+
>
|
|
4464
|
+
<p className="text-[14px] font-semibold text-semantic-text-primary truncate leading-5 tracking-[0.014px] m-0">
|
|
4465
|
+
{sender}
|
|
4466
|
+
</p>
|
|
4467
|
+
<p className="text-[14px] text-semantic-text-muted truncate m-0">
|
|
4468
|
+
{message}
|
|
4469
|
+
</p>
|
|
4470
|
+
</div>
|
|
4471
|
+
);
|
|
4472
|
+
}
|
|
4473
|
+
);
|
|
4474
|
+
ReplyQuote.displayName = "ReplyQuote";
|
|
4475
|
+
|
|
4476
|
+
export { ReplyQuote };
|
|
3809
4477
|
`,
|
|
3810
4478
|
"select-field": `import * as React from "react";
|
|
3811
|
-
import { Loader2 } from "lucide-react";
|
|
4479
|
+
import { Loader2, Search } from "lucide-react";
|
|
3812
4480
|
|
|
3813
4481
|
import { cn } from "@/lib/utils";
|
|
3814
4482
|
import {
|
|
@@ -3898,7 +4566,7 @@ export interface SelectFieldProps {
|
|
|
3898
4566
|
* />
|
|
3899
4567
|
* \`\`\`
|
|
3900
4568
|
*/
|
|
3901
|
-
const SelectField = React.forwardRef
|
|
4569
|
+
const SelectField = React.forwardRef(
|
|
3902
4570
|
(
|
|
3903
4571
|
{
|
|
3904
4572
|
label,
|
|
@@ -3921,8 +4589,8 @@ const SelectField = React.forwardRef<HTMLButtonElement, SelectFieldProps>(
|
|
|
3921
4589
|
labelClassName,
|
|
3922
4590
|
id,
|
|
3923
4591
|
name,
|
|
3924
|
-
},
|
|
3925
|
-
ref
|
|
4592
|
+
}: SelectFieldProps,
|
|
4593
|
+
ref: React.Ref<HTMLButtonElement>
|
|
3926
4594
|
) => {
|
|
3927
4595
|
// Internal state for search
|
|
3928
4596
|
const [searchQuery, setSearchQuery] = React.useState("");
|
|
@@ -4019,7 +4687,7 @@ const SelectField = React.forwardRef<HTMLButtonElement, SelectFieldProps>(
|
|
|
4019
4687
|
<label
|
|
4020
4688
|
htmlFor={selectId}
|
|
4021
4689
|
className={cn(
|
|
4022
|
-
"text-
|
|
4690
|
+
"text-sm font-medium text-semantic-text-muted",
|
|
4023
4691
|
labelClassName
|
|
4024
4692
|
)}
|
|
4025
4693
|
>
|
|
@@ -4055,13 +4723,14 @@ const SelectField = React.forwardRef<HTMLButtonElement, SelectFieldProps>(
|
|
|
4055
4723
|
<SelectContent>
|
|
4056
4724
|
{/* Search input */}
|
|
4057
4725
|
{searchable && (
|
|
4058
|
-
<div className="
|
|
4726
|
+
<div className="flex items-center gap-2 px-3 pb-1.5 border-b border-semantic-border-layout">
|
|
4727
|
+
<Search className="size-4 text-semantic-text-muted shrink-0" />
|
|
4059
4728
|
<input
|
|
4060
4729
|
type="text"
|
|
4061
4730
|
placeholder={searchPlaceholder}
|
|
4062
4731
|
value={searchQuery}
|
|
4063
4732
|
onChange={handleSearchChange}
|
|
4064
|
-
className="w-full h-8
|
|
4733
|
+
className="w-full h-8 text-sm bg-transparent placeholder:text-semantic-text-muted focus:outline-none"
|
|
4065
4734
|
// Prevent closing dropdown when clicking input
|
|
4066
4735
|
onClick={(e) => e.stopPropagation()}
|
|
4067
4736
|
onKeyDown={(e) => e.stopPropagation()}
|
|
@@ -4169,10 +4838,7 @@ const Select = SelectPrimitive.Root;
|
|
|
4169
4838
|
|
|
4170
4839
|
const SelectGroup = SelectPrimitive.Group;
|
|
4171
4840
|
|
|
4172
|
-
const SelectValue = React.forwardRef<
|
|
4173
|
-
React.ElementRef<typeof SelectPrimitive.Value>,
|
|
4174
|
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Value>
|
|
4175
|
-
>(({ className, ...props }, ref) => (
|
|
4841
|
+
const SelectValue = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Value>, ref: React.Ref<React.ElementRef<typeof SelectPrimitive.Value>>) => (
|
|
4176
4842
|
<SelectPrimitive.Value
|
|
4177
4843
|
ref={ref}
|
|
4178
4844
|
className={cn("[&[data-placeholder]]:text-semantic-text-muted", className)}
|
|
@@ -4186,10 +4852,7 @@ export interface SelectTriggerProps
|
|
|
4186
4852
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>,
|
|
4187
4853
|
VariantProps<typeof selectTriggerVariants> {}
|
|
4188
4854
|
|
|
4189
|
-
const SelectTrigger = React.forwardRef<
|
|
4190
|
-
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
|
4191
|
-
SelectTriggerProps
|
|
4192
|
-
>(({ className, state, children, ...props }, ref) => (
|
|
4855
|
+
const SelectTrigger = React.forwardRef(({ className, state, children, ...props }: SelectTriggerProps, ref: React.Ref<React.ElementRef<typeof SelectPrimitive.Trigger>>) => (
|
|
4193
4856
|
<SelectPrimitive.Trigger
|
|
4194
4857
|
ref={ref}
|
|
4195
4858
|
className={cn(selectTriggerVariants({ state, className }))}
|
|
@@ -4203,10 +4866,7 @@ const SelectTrigger = React.forwardRef<
|
|
|
4203
4866
|
));
|
|
4204
4867
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
4205
4868
|
|
|
4206
|
-
const SelectScrollUpButton = React.forwardRef<
|
|
4207
|
-
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
|
4208
|
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
|
4209
|
-
>(({ className, ...props }, ref) => (
|
|
4869
|
+
const SelectScrollUpButton = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>, ref: React.Ref<React.ElementRef<typeof SelectPrimitive.ScrollUpButton>>) => (
|
|
4210
4870
|
<SelectPrimitive.ScrollUpButton
|
|
4211
4871
|
ref={ref}
|
|
4212
4872
|
className={cn(
|
|
@@ -4220,10 +4880,7 @@ const SelectScrollUpButton = React.forwardRef<
|
|
|
4220
4880
|
));
|
|
4221
4881
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
4222
4882
|
|
|
4223
|
-
const SelectScrollDownButton = React.forwardRef<
|
|
4224
|
-
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
|
4225
|
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
|
4226
|
-
>(({ className, ...props }, ref) => (
|
|
4883
|
+
const SelectScrollDownButton = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>, ref: React.Ref<React.ElementRef<typeof SelectPrimitive.ScrollDownButton>>) => (
|
|
4227
4884
|
<SelectPrimitive.ScrollDownButton
|
|
4228
4885
|
ref={ref}
|
|
4229
4886
|
className={cn(
|
|
@@ -4277,10 +4934,7 @@ function useUnlockBodyScroll() {
|
|
|
4277
4934
|
}, []);
|
|
4278
4935
|
}
|
|
4279
4936
|
|
|
4280
|
-
const SelectContent = React.forwardRef<
|
|
4281
|
-
React.ElementRef<typeof SelectPrimitive.Content>,
|
|
4282
|
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
|
4283
|
-
>(({ className, children, position = "popper", ...props }, ref) => {
|
|
4937
|
+
const SelectContent = React.forwardRef(({ className, children, position = "popper", ...props }: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>, ref: React.Ref<React.ElementRef<typeof SelectPrimitive.Content>>) => {
|
|
4284
4938
|
useUnlockBodyScroll();
|
|
4285
4939
|
|
|
4286
4940
|
return (
|
|
@@ -4318,10 +4972,7 @@ const SelectContent = React.forwardRef<
|
|
|
4318
4972
|
});
|
|
4319
4973
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
4320
4974
|
|
|
4321
|
-
const SelectLabel = React.forwardRef<
|
|
4322
|
-
React.ElementRef<typeof SelectPrimitive.Label>,
|
|
4323
|
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
|
4324
|
-
>(({ className, ...props }, ref) => (
|
|
4975
|
+
const SelectLabel = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>, ref: React.Ref<React.ElementRef<typeof SelectPrimitive.Label>>) => (
|
|
4325
4976
|
<SelectPrimitive.Label
|
|
4326
4977
|
ref={ref}
|
|
4327
4978
|
className={cn(
|
|
@@ -4333,10 +4984,7 @@ const SelectLabel = React.forwardRef<
|
|
|
4333
4984
|
));
|
|
4334
4985
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
4335
4986
|
|
|
4336
|
-
const SelectItem = React.forwardRef<
|
|
4337
|
-
React.ElementRef<typeof SelectPrimitive.Item>,
|
|
4338
|
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
|
4339
|
-
>(({ className, children, ...props }, ref) => (
|
|
4987
|
+
const SelectItem = React.forwardRef(({ className, children, ...props }: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>, ref: React.Ref<React.ElementRef<typeof SelectPrimitive.Item>>) => (
|
|
4340
4988
|
<SelectPrimitive.Item
|
|
4341
4989
|
ref={ref}
|
|
4342
4990
|
className={cn(
|
|
@@ -4357,10 +5005,7 @@ const SelectItem = React.forwardRef<
|
|
|
4357
5005
|
));
|
|
4358
5006
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
4359
5007
|
|
|
4360
|
-
const SelectSeparator = React.forwardRef<
|
|
4361
|
-
React.ElementRef<typeof SelectPrimitive.Separator>,
|
|
4362
|
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
|
4363
|
-
>(({ className, ...props }, ref) => (
|
|
5008
|
+
const SelectSeparator = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>, ref: React.Ref<React.ElementRef<typeof SelectPrimitive.Separator>>) => (
|
|
4364
5009
|
<SelectPrimitive.Separator
|
|
4365
5010
|
ref={ref}
|
|
4366
5011
|
className={cn("-mx-1 my-1 h-px bg-semantic-border-layout", className)}
|
|
@@ -4438,8 +5083,8 @@ export interface SkeletonProps
|
|
|
4438
5083
|
height?: number | string;
|
|
4439
5084
|
}
|
|
4440
5085
|
|
|
4441
|
-
const Skeleton = React.forwardRef
|
|
4442
|
-
({ className, variant, shape, width, height, style, ...props }, ref) => {
|
|
5086
|
+
const Skeleton = React.forwardRef(
|
|
5087
|
+
({ className, variant, shape, width, height, style, ...props }: SkeletonProps, ref: React.Ref<HTMLDivElement>) => {
|
|
4443
5088
|
const dimensionStyle: React.CSSProperties = {
|
|
4444
5089
|
...style,
|
|
4445
5090
|
...(width !== undefined
|
|
@@ -4525,7 +5170,7 @@ export interface SpinnerProps
|
|
|
4525
5170
|
"aria-label"?: string;
|
|
4526
5171
|
}
|
|
4527
5172
|
|
|
4528
|
-
const Spinner = React.forwardRef
|
|
5173
|
+
const Spinner = React.forwardRef(
|
|
4529
5174
|
(
|
|
4530
5175
|
{
|
|
4531
5176
|
className,
|
|
@@ -4533,8 +5178,8 @@ const Spinner = React.forwardRef<HTMLDivElement, SpinnerProps>(
|
|
|
4533
5178
|
variant,
|
|
4534
5179
|
"aria-label": ariaLabel = "Loading",
|
|
4535
5180
|
...props
|
|
4536
|
-
},
|
|
4537
|
-
ref
|
|
5181
|
+
}: SpinnerProps,
|
|
5182
|
+
ref: React.Ref<HTMLDivElement>
|
|
4538
5183
|
) => {
|
|
4539
5184
|
const strokeWidth = strokeWidths[size || "default"] ?? 3;
|
|
4540
5185
|
const radius = 10;
|
|
@@ -4667,13 +5312,10 @@ export interface SwitchProps
|
|
|
4667
5312
|
labelPosition?: "left" | "right";
|
|
4668
5313
|
}
|
|
4669
5314
|
|
|
4670
|
-
const Switch = React.forwardRef
|
|
4671
|
-
React.ElementRef<typeof SwitchPrimitives.Root>,
|
|
4672
|
-
SwitchProps
|
|
4673
|
-
>(
|
|
5315
|
+
const Switch = React.forwardRef(
|
|
4674
5316
|
(
|
|
4675
|
-
{ className, size, label, labelPosition = "right", disabled, ...props },
|
|
4676
|
-
ref
|
|
5317
|
+
{ className, size, label, labelPosition = "right", disabled, ...props }: SwitchProps,
|
|
5318
|
+
ref: React.Ref<React.ElementRef<typeof SwitchPrimitives.Root>>
|
|
4677
5319
|
) => {
|
|
4678
5320
|
const switchElement = (
|
|
4679
5321
|
<SwitchPrimitives.Root
|
|
@@ -4727,6 +5369,52 @@ const Switch = React.forwardRef<
|
|
|
4727
5369
|
Switch.displayName = "Switch";
|
|
4728
5370
|
|
|
4729
5371
|
export { Switch, switchVariants };
|
|
5372
|
+
`,
|
|
5373
|
+
"system-message": `import * as React from "react";
|
|
5374
|
+
|
|
5375
|
+
import { cn } from "@/lib/utils";
|
|
5376
|
+
|
|
5377
|
+
/**
|
|
5378
|
+
* SystemMessage component for displaying centered, muted system/timeline
|
|
5379
|
+
* events in a chat interface. Supports **bold** markdown-style formatting
|
|
5380
|
+
* which renders as link-colored bold text.
|
|
5381
|
+
*
|
|
5382
|
+
* @example
|
|
5383
|
+
* \`\`\`tsx
|
|
5384
|
+
* <SystemMessage>Assigned to **Alex Smith** by **Admin**</SystemMessage>
|
|
5385
|
+
* <SystemMessage>Chat was closed</SystemMessage>
|
|
5386
|
+
* \`\`\`
|
|
5387
|
+
*/
|
|
5388
|
+
export interface SystemMessageProps
|
|
5389
|
+
extends React.HTMLAttributes<HTMLDivElement> {
|
|
5390
|
+
/** The message text. Supports **bold** markdown syntax which renders as link-colored bold text. */
|
|
5391
|
+
children: string;
|
|
5392
|
+
}
|
|
5393
|
+
|
|
5394
|
+
const SystemMessage = React.forwardRef(
|
|
5395
|
+
({ className, children, ...props }: SystemMessageProps, ref: React.Ref<HTMLDivElement>) => (
|
|
5396
|
+
<div
|
|
5397
|
+
ref={ref}
|
|
5398
|
+
className={cn("flex justify-center my-1", className)}
|
|
5399
|
+
{...props}
|
|
5400
|
+
>
|
|
5401
|
+
<span className="text-[13px] text-semantic-text-muted">
|
|
5402
|
+
{children.split(/(\\*\\*[^*]+\\*\\*)/).map((part, i) =>
|
|
5403
|
+
part.startsWith("**") ? (
|
|
5404
|
+
<span key={i} className="text-semantic-text-link font-medium">
|
|
5405
|
+
{part.slice(2, -2)}
|
|
5406
|
+
</span>
|
|
5407
|
+
) : (
|
|
5408
|
+
part
|
|
5409
|
+
)
|
|
5410
|
+
)}
|
|
5411
|
+
</span>
|
|
5412
|
+
</div>
|
|
5413
|
+
)
|
|
5414
|
+
);
|
|
5415
|
+
SystemMessage.displayName = "SystemMessage";
|
|
5416
|
+
|
|
5417
|
+
export { SystemMessage };
|
|
4730
5418
|
`,
|
|
4731
5419
|
"table": `import * as React from "react";
|
|
4732
5420
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
@@ -4782,8 +5470,8 @@ export interface TableProps
|
|
|
4782
5470
|
wrapContent?: boolean;
|
|
4783
5471
|
}
|
|
4784
5472
|
|
|
4785
|
-
const Table = React.forwardRef
|
|
4786
|
-
({ className, size, withoutBorder, wrapContent, ...props }, ref) => (
|
|
5473
|
+
const Table = React.forwardRef(
|
|
5474
|
+
({ className, size, withoutBorder, wrapContent, ...props }: TableProps, ref: React.Ref<HTMLTableElement>) => (
|
|
4787
5475
|
<div
|
|
4788
5476
|
className={cn(
|
|
4789
5477
|
"relative w-full overflow-auto",
|
|
@@ -4804,10 +5492,7 @@ const Table = React.forwardRef<HTMLTableElement, TableProps>(
|
|
|
4804
5492
|
);
|
|
4805
5493
|
Table.displayName = "Table";
|
|
4806
5494
|
|
|
4807
|
-
const TableHeader = React.forwardRef<
|
|
4808
|
-
HTMLTableSectionElement,
|
|
4809
|
-
React.HTMLAttributes<HTMLTableSectionElement>
|
|
4810
|
-
>(({ className, ...props }, ref) => (
|
|
5495
|
+
const TableHeader = React.forwardRef(({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>, ref: React.Ref<HTMLTableSectionElement>) => (
|
|
4811
5496
|
<thead
|
|
4812
5497
|
ref={ref}
|
|
4813
5498
|
className={cn("bg-[var(--color-neutral-100)] [&_tr]:border-b", className)}
|
|
@@ -4826,8 +5511,8 @@ export interface TableBodyProps
|
|
|
4826
5511
|
loadingColumns?: number;
|
|
4827
5512
|
}
|
|
4828
5513
|
|
|
4829
|
-
const TableBody = React.forwardRef
|
|
4830
|
-
({ className, isLoading, loadingRows = 5, loadingColumns = 5, children, ...props }, ref) => (
|
|
5514
|
+
const TableBody = React.forwardRef(
|
|
5515
|
+
({ className, isLoading, loadingRows = 5, loadingColumns = 5, children, ...props }: TableBodyProps, ref: React.Ref<HTMLTableSectionElement>) => (
|
|
4831
5516
|
<tbody
|
|
4832
5517
|
ref={ref}
|
|
4833
5518
|
className={cn("[&_tr:last-child]:border-0", className)}
|
|
@@ -4843,10 +5528,7 @@ const TableBody = React.forwardRef<HTMLTableSectionElement, TableBodyProps>(
|
|
|
4843
5528
|
);
|
|
4844
5529
|
TableBody.displayName = "TableBody";
|
|
4845
5530
|
|
|
4846
|
-
const TableFooter = React.forwardRef<
|
|
4847
|
-
HTMLTableSectionElement,
|
|
4848
|
-
React.HTMLAttributes<HTMLTableSectionElement>
|
|
4849
|
-
>(({ className, ...props }, ref) => (
|
|
5531
|
+
const TableFooter = React.forwardRef(({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>, ref: React.Ref<HTMLTableSectionElement>) => (
|
|
4850
5532
|
<tfoot
|
|
4851
5533
|
ref={ref}
|
|
4852
5534
|
className={cn(
|
|
@@ -4863,8 +5545,8 @@ export interface TableRowProps extends React.HTMLAttributes<HTMLTableRowElement>
|
|
|
4863
5545
|
highlighted?: boolean;
|
|
4864
5546
|
}
|
|
4865
5547
|
|
|
4866
|
-
const TableRow = React.forwardRef
|
|
4867
|
-
({ className, highlighted, ...props }, ref) => (
|
|
5548
|
+
const TableRow = React.forwardRef(
|
|
5549
|
+
({ className, highlighted, ...props }: TableRowProps, ref: React.Ref<HTMLTableRowElement>) => (
|
|
4868
5550
|
<tr
|
|
4869
5551
|
ref={ref}
|
|
4870
5552
|
className={cn(
|
|
@@ -4889,10 +5571,10 @@ export interface TableHeadProps extends React.ThHTMLAttributes<HTMLTableCellElem
|
|
|
4889
5571
|
infoTooltip?: string;
|
|
4890
5572
|
}
|
|
4891
5573
|
|
|
4892
|
-
const TableHead = React.forwardRef
|
|
5574
|
+
const TableHead = React.forwardRef(
|
|
4893
5575
|
(
|
|
4894
|
-
{ className, sticky, sortDirection, infoTooltip, children, ...props },
|
|
4895
|
-
ref
|
|
5576
|
+
{ className, sticky, sortDirection, infoTooltip, children, ...props }: TableHeadProps,
|
|
5577
|
+
ref: React.Ref<HTMLTableCellElement>
|
|
4896
5578
|
) => (
|
|
4897
5579
|
<th
|
|
4898
5580
|
ref={ref}
|
|
@@ -4930,8 +5612,8 @@ export interface TableCellProps extends React.TdHTMLAttributes<HTMLTableCellElem
|
|
|
4930
5612
|
sticky?: boolean;
|
|
4931
5613
|
}
|
|
4932
5614
|
|
|
4933
|
-
const TableCell = React.forwardRef
|
|
4934
|
-
({ className, sticky, ...props }, ref) => (
|
|
5615
|
+
const TableCell = React.forwardRef(
|
|
5616
|
+
({ className, sticky, ...props }: TableCellProps, ref: React.Ref<HTMLTableCellElement>) => (
|
|
4935
5617
|
<td
|
|
4936
5618
|
ref={ref}
|
|
4937
5619
|
className={cn(
|
|
@@ -4945,10 +5627,7 @@ const TableCell = React.forwardRef<HTMLTableCellElement, TableCellProps>(
|
|
|
4945
5627
|
);
|
|
4946
5628
|
TableCell.displayName = "TableCell";
|
|
4947
5629
|
|
|
4948
|
-
const TableCaption = React.forwardRef<
|
|
4949
|
-
HTMLTableCaptionElement,
|
|
4950
|
-
React.HTMLAttributes<HTMLTableCaptionElement>
|
|
4951
|
-
>(({ className, ...props }, ref) => (
|
|
5630
|
+
const TableCaption = React.forwardRef(({ className, ...props }: React.HTMLAttributes<HTMLTableCaptionElement>, ref: React.Ref<HTMLTableCaptionElement>) => (
|
|
4952
5631
|
<caption
|
|
4953
5632
|
ref={ref}
|
|
4954
5633
|
className={cn("mt-4 text-sm text-semantic-text-muted", className)}
|
|
@@ -5037,8 +5716,8 @@ export interface TableToggleProps extends Omit<SwitchProps, "size"> {
|
|
|
5037
5716
|
size?: "sm" | "default";
|
|
5038
5717
|
}
|
|
5039
5718
|
|
|
5040
|
-
const TableToggle = React.forwardRef
|
|
5041
|
-
({ size = "sm", ...props }, ref) => (
|
|
5719
|
+
const TableToggle = React.forwardRef(
|
|
5720
|
+
({ size = "sm", ...props }: TableToggleProps, ref: React.Ref<HTMLButtonElement>) => (
|
|
5042
5721
|
<Switch ref={ref} size={size} {...props} />
|
|
5043
5722
|
)
|
|
5044
5723
|
);
|
|
@@ -5059,6 +5738,76 @@ export {
|
|
|
5059
5738
|
TableToggle,
|
|
5060
5739
|
tableVariants,
|
|
5061
5740
|
};
|
|
5741
|
+
`,
|
|
5742
|
+
"tabs": `import * as React from "react"
|
|
5743
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
|
5744
|
+
|
|
5745
|
+
import { cn } from "@/lib/utils"
|
|
5746
|
+
|
|
5747
|
+
/**
|
|
5748
|
+
* A flexible tabs component with underline-style active indicator.
|
|
5749
|
+
*
|
|
5750
|
+
* @example
|
|
5751
|
+
* \`\`\`tsx
|
|
5752
|
+
* <Tabs defaultValue="tab1">
|
|
5753
|
+
* <TabsList>
|
|
5754
|
+
* <TabsTrigger value="tab1">Tab 1</TabsTrigger>
|
|
5755
|
+
* <TabsTrigger value="tab2">Tab 2</TabsTrigger>
|
|
5756
|
+
* </TabsList>
|
|
5757
|
+
* <TabsContent value="tab1">Content 1</TabsContent>
|
|
5758
|
+
* <TabsContent value="tab2">Content 2</TabsContent>
|
|
5759
|
+
* </Tabs>
|
|
5760
|
+
* \`\`\`
|
|
5761
|
+
*/
|
|
5762
|
+
const Tabs = TabsPrimitive.Root
|
|
5763
|
+
|
|
5764
|
+
export interface TabsListProps
|
|
5765
|
+
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.List> {
|
|
5766
|
+
/** When true, tabs stretch to fill the full width equally */
|
|
5767
|
+
fullWidth?: boolean
|
|
5768
|
+
}
|
|
5769
|
+
|
|
5770
|
+
const TabsList = React.forwardRef(({ className, fullWidth, ...props }: TabsListProps, ref: React.Ref<React.ComponentRef<typeof TabsPrimitive.List>>) => (
|
|
5771
|
+
<TabsPrimitive.List
|
|
5772
|
+
ref={ref}
|
|
5773
|
+
className={cn(
|
|
5774
|
+
"inline-flex items-center border-b border-semantic-border-layout w-full",
|
|
5775
|
+
fullWidth && "[&>*]:flex-1",
|
|
5776
|
+
className
|
|
5777
|
+
)}
|
|
5778
|
+
{...props}
|
|
5779
|
+
/>
|
|
5780
|
+
))
|
|
5781
|
+
TabsList.displayName = TabsPrimitive.List.displayName
|
|
5782
|
+
|
|
5783
|
+
const TabsTrigger = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>, ref: React.Ref<React.ComponentRef<typeof TabsPrimitive.Trigger>>) => (
|
|
5784
|
+
<TabsPrimitive.Trigger
|
|
5785
|
+
ref={ref}
|
|
5786
|
+
className={cn(
|
|
5787
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap py-3 px-3 text-sm font-medium border-b-2 -mb-px cursor-pointer transition-colors",
|
|
5788
|
+
"text-semantic-text-muted border-transparent hover:text-semantic-text-secondary",
|
|
5789
|
+
"data-[state=active]:text-semantic-text-primary data-[state=active]:border-semantic-primary",
|
|
5790
|
+
"focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50",
|
|
5791
|
+
className
|
|
5792
|
+
)}
|
|
5793
|
+
{...props}
|
|
5794
|
+
/>
|
|
5795
|
+
))
|
|
5796
|
+
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
|
|
5797
|
+
|
|
5798
|
+
const TabsContent = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>, ref: React.Ref<React.ComponentRef<typeof TabsPrimitive.Content>>) => (
|
|
5799
|
+
<TabsPrimitive.Content
|
|
5800
|
+
ref={ref}
|
|
5801
|
+
className={cn(
|
|
5802
|
+
"mt-2 focus-visible:outline-none",
|
|
5803
|
+
className
|
|
5804
|
+
)}
|
|
5805
|
+
{...props}
|
|
5806
|
+
/>
|
|
5807
|
+
))
|
|
5808
|
+
TabsContent.displayName = TabsPrimitive.Content.displayName
|
|
5809
|
+
|
|
5810
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
|
5062
5811
|
`,
|
|
5063
5812
|
"tag": `import * as React from "react";
|
|
5064
5813
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
@@ -5110,8 +5859,8 @@ export interface TagProps
|
|
|
5110
5859
|
label?: string;
|
|
5111
5860
|
}
|
|
5112
5861
|
|
|
5113
|
-
const Tag = React.forwardRef
|
|
5114
|
-
({ className, variant, size, label, children, ...props }, ref) => {
|
|
5862
|
+
const Tag = React.forwardRef(
|
|
5863
|
+
({ className, variant, size, label, children, ...props }: TagProps, ref: React.Ref<HTMLSpanElement>) => {
|
|
5115
5864
|
return (
|
|
5116
5865
|
<span
|
|
5117
5866
|
className={cn(tagVariants({ variant, size, className }))}
|
|
@@ -5119,7 +5868,7 @@ const Tag = React.forwardRef<HTMLSpanElement, TagProps>(
|
|
|
5119
5868
|
{...props}
|
|
5120
5869
|
>
|
|
5121
5870
|
{label && <span className="font-semibold mr-1">{label}</span>}
|
|
5122
|
-
<span className="font-normal">{children}</span>
|
|
5871
|
+
<span className="font-normal inline-flex items-center gap-1">{children}</span>
|
|
5123
5872
|
</span>
|
|
5124
5873
|
);
|
|
5125
5874
|
}
|
|
@@ -5198,7 +5947,7 @@ export { Tag, TagGroup, tagVariants };
|
|
|
5198
5947
|
`,
|
|
5199
5948
|
"text-field": `import * as React from "react";
|
|
5200
5949
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
5201
|
-
import { Loader2 } from "lucide-react";
|
|
5950
|
+
import { Loader2, X } from "lucide-react";
|
|
5202
5951
|
|
|
5203
5952
|
import { cn } from "@/lib/utils";
|
|
5204
5953
|
|
|
@@ -5211,9 +5960,9 @@ const textFieldContainerVariants = cva(
|
|
|
5211
5960
|
variants: {
|
|
5212
5961
|
state: {
|
|
5213
5962
|
default:
|
|
5214
|
-
"border border-semantic-border-input focus-within:border-semantic-border-input-focus
|
|
5963
|
+
"border border-semantic-border-input focus-within:border-semantic-border-input-focus focus-within:shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
|
|
5215
5964
|
error:
|
|
5216
|
-
"border border-semantic-error-primary/40 focus-within:border-semantic-error-primary
|
|
5965
|
+
"border border-semantic-error-primary/40 focus-within:border-semantic-error-primary focus-within:shadow-[0_0_0_1px_rgba(240,68,56,0.1)]",
|
|
5217
5966
|
},
|
|
5218
5967
|
disabled: {
|
|
5219
5968
|
true: "cursor-not-allowed opacity-50 bg-[var(--color-neutral-50)]",
|
|
@@ -5231,18 +5980,23 @@ const textFieldContainerVariants = cva(
|
|
|
5231
5980
|
* TextField input variants (standalone without container)
|
|
5232
5981
|
*/
|
|
5233
5982
|
const textFieldInputVariants = cva(
|
|
5234
|
-
"
|
|
5983
|
+
"w-full rounded bg-semantic-bg-primary text-semantic-text-primary outline-none transition-all file:border-0 file:bg-transparent file:font-medium file:text-semantic-text-primary placeholder:text-semantic-text-placeholder disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-[var(--color-neutral-50)]",
|
|
5235
5984
|
{
|
|
5236
5985
|
variants: {
|
|
5237
5986
|
state: {
|
|
5238
5987
|
default:
|
|
5239
|
-
"border border-semantic-border-input focus:outline-none focus:border-semantic-border-input-focus
|
|
5988
|
+
"border border-semantic-border-input focus:outline-none focus:border-semantic-border-input-focus focus:shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
|
|
5240
5989
|
error:
|
|
5241
|
-
"border border-semantic-error-primary/40 focus:outline-none focus:border-semantic-error-primary
|
|
5990
|
+
"border border-semantic-error-primary/40 focus:outline-none focus:border-semantic-error-primary focus:shadow-[0_0_0_1px_rgba(240,68,56,0.1)]",
|
|
5991
|
+
},
|
|
5992
|
+
size: {
|
|
5993
|
+
default: "h-[42px] px-4 py-2 text-base file:text-base",
|
|
5994
|
+
sm: "h-9 px-3 py-1.5 text-sm file:text-sm",
|
|
5242
5995
|
},
|
|
5243
5996
|
},
|
|
5244
5997
|
defaultVariants: {
|
|
5245
5998
|
state: "default",
|
|
5999
|
+
size: "default",
|
|
5246
6000
|
},
|
|
5247
6001
|
}
|
|
5248
6002
|
);
|
|
@@ -5261,6 +6015,8 @@ export interface TextFieldProps
|
|
|
5261
6015
|
extends
|
|
5262
6016
|
Omit<React.ComponentProps<"input">, "size">,
|
|
5263
6017
|
VariantProps<typeof textFieldInputVariants> {
|
|
6018
|
+
/** Size of the text field \u2014 \`default\` (42px) or \`sm\` (36px, compact) */
|
|
6019
|
+
size?: "default" | "sm";
|
|
5264
6020
|
/** Label text displayed above the input */
|
|
5265
6021
|
label?: string;
|
|
5266
6022
|
/** Shows red asterisk next to label when true */
|
|
@@ -5281,6 +6037,10 @@ export interface TextFieldProps
|
|
|
5281
6037
|
showCount?: boolean;
|
|
5282
6038
|
/** Shows loading spinner inside input */
|
|
5283
6039
|
loading?: boolean;
|
|
6040
|
+
/** Shows a clear (X) button when input has a value */
|
|
6041
|
+
clearable?: boolean;
|
|
6042
|
+
/** Callback fired when the clear button is clicked */
|
|
6043
|
+
onClear?: () => void;
|
|
5284
6044
|
/** Additional class for the wrapper container */
|
|
5285
6045
|
wrapperClassName?: string;
|
|
5286
6046
|
/** Additional class for the label */
|
|
@@ -5289,35 +6049,329 @@ export interface TextFieldProps
|
|
|
5289
6049
|
inputContainerClassName?: string;
|
|
5290
6050
|
}
|
|
5291
6051
|
|
|
5292
|
-
const TextField = React.forwardRef
|
|
6052
|
+
const TextField = React.forwardRef(
|
|
6053
|
+
(
|
|
6054
|
+
{
|
|
6055
|
+
className,
|
|
6056
|
+
wrapperClassName,
|
|
6057
|
+
labelClassName,
|
|
6058
|
+
inputContainerClassName,
|
|
6059
|
+
state,
|
|
6060
|
+
size,
|
|
6061
|
+
label,
|
|
6062
|
+
required,
|
|
6063
|
+
helperText,
|
|
6064
|
+
error,
|
|
6065
|
+
leftIcon,
|
|
6066
|
+
rightIcon,
|
|
6067
|
+
prefix,
|
|
6068
|
+
suffix,
|
|
6069
|
+
showCount,
|
|
6070
|
+
loading,
|
|
6071
|
+
clearable,
|
|
6072
|
+
onClear,
|
|
6073
|
+
maxLength,
|
|
6074
|
+
value,
|
|
6075
|
+
defaultValue,
|
|
6076
|
+
onChange,
|
|
6077
|
+
onWheel,
|
|
6078
|
+
disabled,
|
|
6079
|
+
id,
|
|
6080
|
+
type,
|
|
6081
|
+
...props
|
|
6082
|
+
}: TextFieldProps,
|
|
6083
|
+
ref: React.ForwardedRef<HTMLInputElement>
|
|
6084
|
+
) => {
|
|
6085
|
+
// Internal ref for programmatic control (e.g., clearable)
|
|
6086
|
+
const internalRef = React.useRef<HTMLInputElement | null>(null);
|
|
6087
|
+
const mergedRef = React.useCallback(
|
|
6088
|
+
(node: HTMLInputElement | null) => {
|
|
6089
|
+
internalRef.current = node;
|
|
6090
|
+
if (typeof ref === "function") ref(node);
|
|
6091
|
+
else if (ref && typeof ref === "object") ref.current = node;
|
|
6092
|
+
},
|
|
6093
|
+
[ref]
|
|
6094
|
+
);
|
|
6095
|
+
|
|
6096
|
+
// Internal state for character count in uncontrolled mode
|
|
6097
|
+
const [internalValue, setInternalValue] = React.useState(
|
|
6098
|
+
defaultValue ?? ""
|
|
6099
|
+
);
|
|
6100
|
+
|
|
6101
|
+
// Determine if controlled
|
|
6102
|
+
const isControlled = value !== undefined;
|
|
6103
|
+
const currentValue = isControlled ? value : internalValue;
|
|
6104
|
+
|
|
6105
|
+
// Derive state from props
|
|
6106
|
+
const derivedState = error ? "error" : (state ?? "default");
|
|
6107
|
+
|
|
6108
|
+
// Handle change for both controlled and uncontrolled
|
|
6109
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
6110
|
+
if (!isControlled) {
|
|
6111
|
+
setInternalValue(e.target.value);
|
|
6112
|
+
}
|
|
6113
|
+
onChange?.(e);
|
|
6114
|
+
};
|
|
6115
|
+
|
|
6116
|
+
// Determine if we need the container wrapper (for icons/prefix/suffix)
|
|
6117
|
+
const hasAddons = leftIcon || rightIcon || prefix || suffix || loading || clearable;
|
|
6118
|
+
|
|
6119
|
+
// Handle clear
|
|
6120
|
+
const handleClear = () => {
|
|
6121
|
+
if (!isControlled) {
|
|
6122
|
+
setInternalValue("");
|
|
6123
|
+
if (internalRef.current) {
|
|
6124
|
+
internalRef.current.value = "";
|
|
6125
|
+
}
|
|
6126
|
+
}
|
|
6127
|
+
onClear?.();
|
|
6128
|
+
};
|
|
6129
|
+
|
|
6130
|
+
const showClearButton = clearable && String(currentValue).length > 0 && !disabled && !loading;
|
|
6131
|
+
|
|
6132
|
+
// Character count
|
|
6133
|
+
const charCount = String(currentValue).length;
|
|
6134
|
+
|
|
6135
|
+
// Generate unique IDs for accessibility
|
|
6136
|
+
const generatedId = React.useId();
|
|
6137
|
+
const inputId = id || generatedId;
|
|
6138
|
+
const helperId = \`\${inputId}-helper\`;
|
|
6139
|
+
const errorId = \`\${inputId}-error\`;
|
|
6140
|
+
|
|
6141
|
+
// Determine aria-describedby
|
|
6142
|
+
const ariaDescribedBy = error ? errorId : helperText ? helperId : undefined;
|
|
6143
|
+
|
|
6144
|
+
// Render the input element
|
|
6145
|
+
const inputElement = (
|
|
6146
|
+
<input
|
|
6147
|
+
ref={mergedRef}
|
|
6148
|
+
id={inputId}
|
|
6149
|
+
type={type}
|
|
6150
|
+
className={cn(
|
|
6151
|
+
hasAddons
|
|
6152
|
+
? cn(
|
|
6153
|
+
"flex-1 bg-transparent border-0 outline-none focus:ring-0 px-0 h-full text-semantic-text-primary placeholder:text-semantic-text-placeholder disabled:cursor-not-allowed",
|
|
6154
|
+
size === "sm" ? "text-sm" : "text-base"
|
|
6155
|
+
)
|
|
6156
|
+
: textFieldInputVariants({ state: derivedState, size, className }),
|
|
6157
|
+
type === "number" &&
|
|
6158
|
+
"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
6159
|
+
)}
|
|
6160
|
+
disabled={disabled || loading}
|
|
6161
|
+
maxLength={maxLength}
|
|
6162
|
+
value={isControlled ? value : undefined}
|
|
6163
|
+
defaultValue={!isControlled ? defaultValue : undefined}
|
|
6164
|
+
onChange={handleChange}
|
|
6165
|
+
onWheel={
|
|
6166
|
+
type === "number"
|
|
6167
|
+
? (e) => {
|
|
6168
|
+
e.currentTarget.blur();
|
|
6169
|
+
onWheel?.(e);
|
|
6170
|
+
}
|
|
6171
|
+
: onWheel
|
|
6172
|
+
}
|
|
6173
|
+
aria-invalid={!!error}
|
|
6174
|
+
aria-describedby={ariaDescribedBy}
|
|
6175
|
+
{...props}
|
|
6176
|
+
/>
|
|
6177
|
+
);
|
|
6178
|
+
|
|
6179
|
+
return (
|
|
6180
|
+
<div className={cn("flex flex-col gap-1", wrapperClassName)}>
|
|
6181
|
+
{/* Label */}
|
|
6182
|
+
{label && (
|
|
6183
|
+
<label
|
|
6184
|
+
htmlFor={inputId}
|
|
6185
|
+
className={cn(
|
|
6186
|
+
"text-sm font-medium text-semantic-text-muted",
|
|
6187
|
+
labelClassName
|
|
6188
|
+
)}
|
|
6189
|
+
>
|
|
6190
|
+
{label}
|
|
6191
|
+
{required && (
|
|
6192
|
+
<span className="text-semantic-error-primary ml-0.5">*</span>
|
|
6193
|
+
)}
|
|
6194
|
+
</label>
|
|
6195
|
+
)}
|
|
6196
|
+
|
|
6197
|
+
{/* Input or Input Container */}
|
|
6198
|
+
{hasAddons ? (
|
|
6199
|
+
<div
|
|
6200
|
+
className={cn(
|
|
6201
|
+
textFieldContainerVariants({
|
|
6202
|
+
state: derivedState,
|
|
6203
|
+
disabled: disabled || loading,
|
|
6204
|
+
}),
|
|
6205
|
+
size === "sm" ? "h-9 px-3" : "h-[42px] px-4",
|
|
6206
|
+
inputContainerClassName
|
|
6207
|
+
)}
|
|
6208
|
+
>
|
|
6209
|
+
{prefix && (
|
|
6210
|
+
<span className="text-sm text-semantic-text-muted mr-2 select-none">
|
|
6211
|
+
{prefix}
|
|
6212
|
+
</span>
|
|
6213
|
+
)}
|
|
6214
|
+
{leftIcon && (
|
|
6215
|
+
<span className="mr-2 text-semantic-text-muted [&_svg]:size-4 flex-shrink-0">
|
|
6216
|
+
{leftIcon}
|
|
6217
|
+
</span>
|
|
6218
|
+
)}
|
|
6219
|
+
{inputElement}
|
|
6220
|
+
{loading && (
|
|
6221
|
+
<Loader2 className="animate-spin size-4 text-semantic-text-muted ml-2 flex-shrink-0" />
|
|
6222
|
+
)}
|
|
6223
|
+
{!loading && rightIcon && (
|
|
6224
|
+
<span className="ml-2 text-semantic-text-muted [&_svg]:size-4 flex-shrink-0">
|
|
6225
|
+
{rightIcon}
|
|
6226
|
+
</span>
|
|
6227
|
+
)}
|
|
6228
|
+
{showClearButton && (
|
|
6229
|
+
<button
|
|
6230
|
+
type="button"
|
|
6231
|
+
onClick={handleClear}
|
|
6232
|
+
className="ml-2 text-semantic-text-muted hover:text-semantic-text-primary flex-shrink-0 cursor-pointer"
|
|
6233
|
+
aria-label="Clear input"
|
|
6234
|
+
tabIndex={-1}
|
|
6235
|
+
>
|
|
6236
|
+
<X className="size-4" />
|
|
6237
|
+
</button>
|
|
6238
|
+
)}
|
|
6239
|
+
{suffix && (
|
|
6240
|
+
<span className="text-sm text-semantic-text-muted ml-2 select-none">
|
|
6241
|
+
{suffix}
|
|
6242
|
+
</span>
|
|
6243
|
+
)}
|
|
6244
|
+
</div>
|
|
6245
|
+
) : (
|
|
6246
|
+
inputElement
|
|
6247
|
+
)}
|
|
6248
|
+
|
|
6249
|
+
{/* Helper text / Error message / Character count */}
|
|
6250
|
+
{(error || helperText || (showCount && maxLength)) && (
|
|
6251
|
+
<div className="flex justify-between items-start gap-2">
|
|
6252
|
+
{error ? (
|
|
6253
|
+
<span
|
|
6254
|
+
id={errorId}
|
|
6255
|
+
className="text-sm text-semantic-error-primary"
|
|
6256
|
+
>
|
|
6257
|
+
{error}
|
|
6258
|
+
</span>
|
|
6259
|
+
) : helperText ? (
|
|
6260
|
+
<span id={helperId} className="text-sm text-semantic-text-muted">
|
|
6261
|
+
{helperText}
|
|
6262
|
+
</span>
|
|
6263
|
+
) : (
|
|
6264
|
+
<span />
|
|
6265
|
+
)}
|
|
6266
|
+
{showCount && maxLength && (
|
|
6267
|
+
<span
|
|
6268
|
+
className={cn(
|
|
6269
|
+
"text-sm",
|
|
6270
|
+
charCount > maxLength
|
|
6271
|
+
? "text-semantic-error-primary"
|
|
6272
|
+
: "text-semantic-text-muted"
|
|
6273
|
+
)}
|
|
6274
|
+
>
|
|
6275
|
+
{charCount}/{maxLength}
|
|
6276
|
+
</span>
|
|
6277
|
+
)}
|
|
6278
|
+
</div>
|
|
6279
|
+
)}
|
|
6280
|
+
</div>
|
|
6281
|
+
);
|
|
6282
|
+
}
|
|
6283
|
+
);
|
|
6284
|
+
TextField.displayName = "TextField";
|
|
6285
|
+
|
|
6286
|
+
export { TextField, textFieldContainerVariants, textFieldInputVariants };
|
|
6287
|
+
`,
|
|
6288
|
+
"textarea": `import * as React from "react";
|
|
6289
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
6290
|
+
|
|
6291
|
+
import { cn } from "@/lib/utils";
|
|
6292
|
+
|
|
6293
|
+
/**
|
|
6294
|
+
* Textarea variants for different visual states
|
|
6295
|
+
*/
|
|
6296
|
+
const textareaVariants = cva(
|
|
6297
|
+
"w-full rounded bg-semantic-bg-primary text-semantic-text-primary outline-none transition-all placeholder:text-semantic-text-placeholder disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-[var(--color-neutral-50)]",
|
|
6298
|
+
{
|
|
6299
|
+
variants: {
|
|
6300
|
+
state: {
|
|
6301
|
+
default:
|
|
6302
|
+
"border border-semantic-border-input focus:outline-none focus:border-semantic-border-input-focus focus:shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
|
|
6303
|
+
error:
|
|
6304
|
+
"border border-semantic-error-primary/40 focus:outline-none focus:border-semantic-error-primary focus:shadow-[0_0_0_1px_rgba(240,68,56,0.1)]",
|
|
6305
|
+
},
|
|
6306
|
+
size: {
|
|
6307
|
+
default: "px-4 py-2.5 text-base",
|
|
6308
|
+
sm: "px-3 py-2 text-sm",
|
|
6309
|
+
},
|
|
6310
|
+
},
|
|
6311
|
+
defaultVariants: {
|
|
6312
|
+
state: "default",
|
|
6313
|
+
size: "default",
|
|
6314
|
+
},
|
|
6315
|
+
}
|
|
6316
|
+
);
|
|
6317
|
+
|
|
6318
|
+
/**
|
|
6319
|
+
* A multi-line text input with label, error state, helper text, character counter, and resize control.
|
|
6320
|
+
*
|
|
6321
|
+
* @example
|
|
6322
|
+
* \`\`\`tsx
|
|
6323
|
+
* <Textarea label="Description" placeholder="Enter description" />
|
|
6324
|
+
* <Textarea label="Notes" error="Too short" showCount maxLength={500} />
|
|
6325
|
+
* <Textarea label="JSON" rows={8} resize="vertical" />
|
|
6326
|
+
* \`\`\`
|
|
6327
|
+
*/
|
|
6328
|
+
export interface TextareaProps
|
|
6329
|
+
extends Omit<React.ComponentProps<"textarea">, "size">,
|
|
6330
|
+
VariantProps<typeof textareaVariants> {
|
|
6331
|
+
/** Size of the textarea \u2014 \`default\` or \`sm\` (compact) */
|
|
6332
|
+
size?: "default" | "sm";
|
|
6333
|
+
/** Label text displayed above the textarea */
|
|
6334
|
+
label?: string;
|
|
6335
|
+
/** Shows red asterisk next to label when true */
|
|
6336
|
+
required?: boolean;
|
|
6337
|
+
/** Helper text displayed below the textarea */
|
|
6338
|
+
helperText?: string;
|
|
6339
|
+
/** Error message \u2014 shows error state with red styling */
|
|
6340
|
+
error?: string;
|
|
6341
|
+
/** Shows character count when maxLength is set */
|
|
6342
|
+
showCount?: boolean;
|
|
6343
|
+
/** Controls CSS resize behavior. Defaults to "none" */
|
|
6344
|
+
resize?: "none" | "vertical" | "horizontal" | "both";
|
|
6345
|
+
/** Additional class for the wrapper container */
|
|
6346
|
+
wrapperClassName?: string;
|
|
6347
|
+
/** Additional class for the label */
|
|
6348
|
+
labelClassName?: string;
|
|
6349
|
+
}
|
|
6350
|
+
|
|
6351
|
+
const Textarea = React.forwardRef(
|
|
5293
6352
|
(
|
|
5294
6353
|
{
|
|
5295
6354
|
className,
|
|
5296
6355
|
wrapperClassName,
|
|
5297
6356
|
labelClassName,
|
|
5298
|
-
inputContainerClassName,
|
|
5299
6357
|
state,
|
|
6358
|
+
size,
|
|
5300
6359
|
label,
|
|
5301
6360
|
required,
|
|
5302
6361
|
helperText,
|
|
5303
6362
|
error,
|
|
5304
|
-
leftIcon,
|
|
5305
|
-
rightIcon,
|
|
5306
|
-
prefix,
|
|
5307
|
-
suffix,
|
|
5308
6363
|
showCount,
|
|
5309
|
-
|
|
6364
|
+
resize = "none",
|
|
5310
6365
|
maxLength,
|
|
6366
|
+
rows = 4,
|
|
5311
6367
|
value,
|
|
5312
6368
|
defaultValue,
|
|
5313
6369
|
onChange,
|
|
5314
|
-
onWheel,
|
|
5315
6370
|
disabled,
|
|
5316
6371
|
id,
|
|
5317
|
-
type,
|
|
5318
6372
|
...props
|
|
5319
|
-
},
|
|
5320
|
-
ref
|
|
6373
|
+
}: TextareaProps,
|
|
6374
|
+
ref: React.ForwardedRef<HTMLTextAreaElement>
|
|
5321
6375
|
) => {
|
|
5322
6376
|
// Internal state for character count in uncontrolled mode
|
|
5323
6377
|
const [internalValue, setInternalValue] = React.useState(
|
|
@@ -5332,68 +6386,41 @@ const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
5332
6386
|
const derivedState = error ? "error" : (state ?? "default");
|
|
5333
6387
|
|
|
5334
6388
|
// Handle change for both controlled and uncontrolled
|
|
5335
|
-
const handleChange = (e: React.ChangeEvent<
|
|
6389
|
+
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
5336
6390
|
if (!isControlled) {
|
|
5337
6391
|
setInternalValue(e.target.value);
|
|
5338
6392
|
}
|
|
5339
6393
|
onChange?.(e);
|
|
5340
6394
|
};
|
|
5341
6395
|
|
|
5342
|
-
// Determine if we need the container wrapper (for icons/prefix/suffix)
|
|
5343
|
-
const hasAddons = leftIcon || rightIcon || prefix || suffix || loading;
|
|
5344
|
-
|
|
5345
6396
|
// Character count
|
|
5346
6397
|
const charCount = String(currentValue).length;
|
|
5347
6398
|
|
|
5348
6399
|
// Generate unique IDs for accessibility
|
|
5349
6400
|
const generatedId = React.useId();
|
|
5350
|
-
const
|
|
5351
|
-
const helperId = \`\${
|
|
5352
|
-
const errorId = \`\${
|
|
6401
|
+
const textareaId = id || generatedId;
|
|
6402
|
+
const helperId = \`\${textareaId}-helper\`;
|
|
6403
|
+
const errorId = \`\${textareaId}-error\`;
|
|
5353
6404
|
|
|
5354
6405
|
// Determine aria-describedby
|
|
5355
6406
|
const ariaDescribedBy = error ? errorId : helperText ? helperId : undefined;
|
|
5356
6407
|
|
|
5357
|
-
//
|
|
5358
|
-
const
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
hasAddons
|
|
5365
|
-
? "flex-1 bg-transparent border-0 outline-none focus:ring-0 px-0 h-full text-base text-semantic-text-primary placeholder:text-semantic-text-placeholder disabled:cursor-not-allowed"
|
|
5366
|
-
: textFieldInputVariants({ state: derivedState, className }),
|
|
5367
|
-
type === "number" &&
|
|
5368
|
-
"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
5369
|
-
)}
|
|
5370
|
-
disabled={disabled || loading}
|
|
5371
|
-
maxLength={maxLength}
|
|
5372
|
-
value={isControlled ? value : undefined}
|
|
5373
|
-
defaultValue={!isControlled ? defaultValue : undefined}
|
|
5374
|
-
onChange={handleChange}
|
|
5375
|
-
onWheel={
|
|
5376
|
-
type === "number"
|
|
5377
|
-
? (e) => {
|
|
5378
|
-
e.currentTarget.blur();
|
|
5379
|
-
onWheel?.(e);
|
|
5380
|
-
}
|
|
5381
|
-
: onWheel
|
|
5382
|
-
}
|
|
5383
|
-
aria-invalid={!!error}
|
|
5384
|
-
aria-describedby={ariaDescribedBy}
|
|
5385
|
-
{...props}
|
|
5386
|
-
/>
|
|
5387
|
-
);
|
|
6408
|
+
// Resize class map
|
|
6409
|
+
const resizeClasses: Record<string, string> = {
|
|
6410
|
+
none: "resize-none",
|
|
6411
|
+
vertical: "resize-y",
|
|
6412
|
+
horizontal: "resize-x",
|
|
6413
|
+
both: "resize",
|
|
6414
|
+
};
|
|
5388
6415
|
|
|
5389
6416
|
return (
|
|
5390
6417
|
<div className={cn("flex flex-col gap-1", wrapperClassName)}>
|
|
5391
6418
|
{/* Label */}
|
|
5392
6419
|
{label && (
|
|
5393
6420
|
<label
|
|
5394
|
-
htmlFor={
|
|
6421
|
+
htmlFor={textareaId}
|
|
5395
6422
|
className={cn(
|
|
5396
|
-
"text-
|
|
6423
|
+
"text-sm font-medium text-semantic-text-muted",
|
|
5397
6424
|
labelClassName
|
|
5398
6425
|
)}
|
|
5399
6426
|
>
|
|
@@ -5404,46 +6431,24 @@ const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
5404
6431
|
</label>
|
|
5405
6432
|
)}
|
|
5406
6433
|
|
|
5407
|
-
{/*
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
<span className="mr-2 text-semantic-text-muted [&_svg]:size-4 flex-shrink-0">
|
|
5426
|
-
{leftIcon}
|
|
5427
|
-
</span>
|
|
5428
|
-
)}
|
|
5429
|
-
{inputElement}
|
|
5430
|
-
{loading && (
|
|
5431
|
-
<Loader2 className="animate-spin size-4 text-semantic-text-muted ml-2 flex-shrink-0" />
|
|
5432
|
-
)}
|
|
5433
|
-
{!loading && rightIcon && (
|
|
5434
|
-
<span className="ml-2 text-semantic-text-muted [&_svg]:size-4 flex-shrink-0">
|
|
5435
|
-
{rightIcon}
|
|
5436
|
-
</span>
|
|
5437
|
-
)}
|
|
5438
|
-
{suffix && (
|
|
5439
|
-
<span className="text-sm text-semantic-text-muted ml-2 select-none">
|
|
5440
|
-
{suffix}
|
|
5441
|
-
</span>
|
|
5442
|
-
)}
|
|
5443
|
-
</div>
|
|
5444
|
-
) : (
|
|
5445
|
-
inputElement
|
|
5446
|
-
)}
|
|
6434
|
+
{/* Textarea */}
|
|
6435
|
+
<textarea
|
|
6436
|
+
ref={ref}
|
|
6437
|
+
id={textareaId}
|
|
6438
|
+
rows={rows}
|
|
6439
|
+
className={cn(
|
|
6440
|
+
textareaVariants({ state: derivedState, size, className }),
|
|
6441
|
+
resizeClasses[resize]
|
|
6442
|
+
)}
|
|
6443
|
+
disabled={disabled}
|
|
6444
|
+
maxLength={maxLength}
|
|
6445
|
+
value={isControlled ? value : undefined}
|
|
6446
|
+
defaultValue={!isControlled ? defaultValue : undefined}
|
|
6447
|
+
onChange={handleChange}
|
|
6448
|
+
aria-invalid={!!error}
|
|
6449
|
+
aria-describedby={ariaDescribedBy}
|
|
6450
|
+
{...props}
|
|
6451
|
+
/>
|
|
5447
6452
|
|
|
5448
6453
|
{/* Helper text / Error message / Character count */}
|
|
5449
6454
|
{(error || helperText || (showCount && maxLength)) && (
|
|
@@ -5451,12 +6456,12 @@ const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
5451
6456
|
{error ? (
|
|
5452
6457
|
<span
|
|
5453
6458
|
id={errorId}
|
|
5454
|
-
className="text-
|
|
6459
|
+
className="text-sm text-semantic-error-primary"
|
|
5455
6460
|
>
|
|
5456
6461
|
{error}
|
|
5457
6462
|
</span>
|
|
5458
6463
|
) : helperText ? (
|
|
5459
|
-
<span id={helperId} className="text-
|
|
6464
|
+
<span id={helperId} className="text-sm text-semantic-text-muted">
|
|
5460
6465
|
{helperText}
|
|
5461
6466
|
</span>
|
|
5462
6467
|
) : (
|
|
@@ -5465,7 +6470,7 @@ const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
5465
6470
|
{showCount && maxLength && (
|
|
5466
6471
|
<span
|
|
5467
6472
|
className={cn(
|
|
5468
|
-
"text-
|
|
6473
|
+
"text-sm",
|
|
5469
6474
|
charCount > maxLength
|
|
5470
6475
|
? "text-semantic-error-primary"
|
|
5471
6476
|
: "text-semantic-text-muted"
|
|
@@ -5480,9 +6485,9 @@ const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
5480
6485
|
);
|
|
5481
6486
|
}
|
|
5482
6487
|
);
|
|
5483
|
-
|
|
6488
|
+
Textarea.displayName = "Textarea";
|
|
5484
6489
|
|
|
5485
|
-
export {
|
|
6490
|
+
export { Textarea, textareaVariants };
|
|
5486
6491
|
`,
|
|
5487
6492
|
"toast": `import * as React from "react";
|
|
5488
6493
|
import * as ToastPrimitives from "@radix-ui/react-toast";
|
|
@@ -5493,10 +6498,7 @@ import { cn } from "@/lib/utils";
|
|
|
5493
6498
|
|
|
5494
6499
|
const ToastProvider = ToastPrimitives.Provider;
|
|
5495
6500
|
|
|
5496
|
-
const ToastViewport = React.forwardRef<
|
|
5497
|
-
React.ElementRef<typeof ToastPrimitives.Viewport>,
|
|
5498
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
|
|
5499
|
-
>(({ className, ...props }, ref) => (
|
|
6501
|
+
const ToastViewport = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>, ref: React.Ref<React.ElementRef<typeof ToastPrimitives.Viewport>>) => (
|
|
5500
6502
|
<ToastPrimitives.Viewport
|
|
5501
6503
|
ref={ref}
|
|
5502
6504
|
className={cn(
|
|
@@ -5530,11 +6532,8 @@ const toastVariants = cva(
|
|
|
5530
6532
|
}
|
|
5531
6533
|
);
|
|
5532
6534
|
|
|
5533
|
-
const Toast = React.forwardRef<
|
|
5534
|
-
|
|
5535
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
|
|
5536
|
-
VariantProps<typeof toastVariants>
|
|
5537
|
-
>(({ className, variant, ...props }, ref) => {
|
|
6535
|
+
const Toast = React.forwardRef(({ className, variant, ...props }: React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
|
|
6536
|
+
VariantProps<typeof toastVariants>, ref: React.Ref<React.ElementRef<typeof ToastPrimitives.Root>>) => {
|
|
5538
6537
|
return (
|
|
5539
6538
|
<ToastPrimitives.Root
|
|
5540
6539
|
ref={ref}
|
|
@@ -5545,10 +6544,7 @@ const Toast = React.forwardRef<
|
|
|
5545
6544
|
});
|
|
5546
6545
|
Toast.displayName = ToastPrimitives.Root.displayName;
|
|
5547
6546
|
|
|
5548
|
-
const ToastAction = React.forwardRef<
|
|
5549
|
-
React.ElementRef<typeof ToastPrimitives.Action>,
|
|
5550
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
|
|
5551
|
-
>(({ className, ...props }, ref) => (
|
|
6547
|
+
const ToastAction = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>, ref: React.Ref<React.ElementRef<typeof ToastPrimitives.Action>>) => (
|
|
5552
6548
|
<ToastPrimitives.Action
|
|
5553
6549
|
ref={ref}
|
|
5554
6550
|
className={cn(
|
|
@@ -5564,10 +6560,7 @@ const ToastAction = React.forwardRef<
|
|
|
5564
6560
|
));
|
|
5565
6561
|
ToastAction.displayName = ToastPrimitives.Action.displayName;
|
|
5566
6562
|
|
|
5567
|
-
const ToastClose = React.forwardRef<
|
|
5568
|
-
React.ElementRef<typeof ToastPrimitives.Close>,
|
|
5569
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
|
|
5570
|
-
>(({ className, ...props }, ref) => (
|
|
6563
|
+
const ToastClose = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>, ref: React.Ref<React.ElementRef<typeof ToastPrimitives.Close>>) => (
|
|
5571
6564
|
<ToastPrimitives.Close
|
|
5572
6565
|
ref={ref}
|
|
5573
6566
|
className={cn(
|
|
@@ -5582,10 +6575,7 @@ const ToastClose = React.forwardRef<
|
|
|
5582
6575
|
));
|
|
5583
6576
|
ToastClose.displayName = ToastPrimitives.Close.displayName;
|
|
5584
6577
|
|
|
5585
|
-
const ToastTitle = React.forwardRef<
|
|
5586
|
-
React.ElementRef<typeof ToastPrimitives.Title>,
|
|
5587
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
|
5588
|
-
>(({ className, ...props }, ref) => (
|
|
6578
|
+
const ToastTitle = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>, ref: React.Ref<React.ElementRef<typeof ToastPrimitives.Title>>) => (
|
|
5589
6579
|
<ToastPrimitives.Title
|
|
5590
6580
|
ref={ref}
|
|
5591
6581
|
className={cn("text-sm font-semibold tracking-[0.014px]", className)}
|
|
@@ -5594,10 +6584,7 @@ const ToastTitle = React.forwardRef<
|
|
|
5594
6584
|
));
|
|
5595
6585
|
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
|
5596
6586
|
|
|
5597
|
-
const ToastDescription = React.forwardRef<
|
|
5598
|
-
React.ElementRef<typeof ToastPrimitives.Description>,
|
|
5599
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
|
|
5600
|
-
>(({ className, ...props }, ref) => (
|
|
6587
|
+
const ToastDescription = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>, ref: React.Ref<React.ElementRef<typeof ToastPrimitives.Description>>) => (
|
|
5601
6588
|
<ToastPrimitives.Description
|
|
5602
6589
|
ref={ref}
|
|
5603
6590
|
className={cn("text-xs tracking-[0.048px]", className)}
|
|
@@ -5982,10 +6969,7 @@ const Tooltip = TooltipPrimitive.Root;
|
|
|
5982
6969
|
|
|
5983
6970
|
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
5984
6971
|
|
|
5985
|
-
const TooltipContent = React.forwardRef<
|
|
5986
|
-
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
5987
|
-
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
|
|
5988
|
-
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
6972
|
+
const TooltipContent = React.forwardRef(({ className, sideOffset = 4, ...props }: React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>, ref: React.Ref<React.ElementRef<typeof TooltipPrimitive.Content>>) => (
|
|
5989
6973
|
<TooltipPrimitive.Portal>
|
|
5990
6974
|
<TooltipPrimitive.Content
|
|
5991
6975
|
ref={ref}
|
|
@@ -6000,10 +6984,7 @@ const TooltipContent = React.forwardRef<
|
|
|
6000
6984
|
));
|
|
6001
6985
|
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
6002
6986
|
|
|
6003
|
-
const TooltipArrow = React.forwardRef<
|
|
6004
|
-
React.ElementRef<typeof TooltipPrimitive.Arrow>,
|
|
6005
|
-
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Arrow>
|
|
6006
|
-
>(({ className, ...props }, ref) => (
|
|
6987
|
+
const TooltipArrow = React.forwardRef(({ className, ...props }: React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Arrow>, ref: React.Ref<React.ElementRef<typeof TooltipPrimitive.Arrow>>) => (
|
|
6007
6988
|
<TooltipPrimitive.Arrow
|
|
6008
6989
|
ref={ref}
|
|
6009
6990
|
className={cn("fill-semantic-primary", className)}
|
|
@@ -6155,7 +7136,7 @@ export interface TypographyProps extends React.HTMLAttributes<HTMLElement> {
|
|
|
6155
7136
|
* <Typography truncate>Very long text that will be truncated...</Typography>
|
|
6156
7137
|
* \`\`\`
|
|
6157
7138
|
*/
|
|
6158
|
-
const Typography = React.forwardRef
|
|
7139
|
+
const Typography = React.forwardRef(
|
|
6159
7140
|
(
|
|
6160
7141
|
{
|
|
6161
7142
|
children,
|
|
@@ -6168,8 +7149,8 @@ const Typography = React.forwardRef<HTMLElement, TypographyProps>(
|
|
|
6168
7149
|
tag,
|
|
6169
7150
|
htmlFor,
|
|
6170
7151
|
...props
|
|
6171
|
-
},
|
|
6172
|
-
ref
|
|
7152
|
+
}: TypographyProps,
|
|
7153
|
+
ref: React.Ref<HTMLElement>
|
|
6173
7154
|
) => {
|
|
6174
7155
|
const key: Key = \`\${kind}-\${variant}\`;
|
|
6175
7156
|
const Tag = (tag || mapTagName[key]) as React.ElementType;
|
|
@@ -6206,6 +7187,48 @@ export {
|
|
|
6206
7187
|
mapColorClassName,
|
|
6207
7188
|
mapAlignClassName,
|
|
6208
7189
|
};
|
|
7190
|
+
`,
|
|
7191
|
+
"unread-separator": `import * as React from "react";
|
|
7192
|
+
|
|
7193
|
+
import { cn } from "@/lib/utils";
|
|
7194
|
+
|
|
7195
|
+
/**
|
|
7196
|
+
* UnreadSeparator component for displaying a horizontal divider with an unread message count.
|
|
7197
|
+
* Used in chat message lists to indicate where unread messages begin.
|
|
7198
|
+
*
|
|
7199
|
+
* @example
|
|
7200
|
+
* \`\`\`tsx
|
|
7201
|
+
* <UnreadSeparator count={3} />
|
|
7202
|
+
* <UnreadSeparator count={1} />
|
|
7203
|
+
* <UnreadSeparator count={5} label="5 new messages" />
|
|
7204
|
+
* \`\`\`
|
|
7205
|
+
*/
|
|
7206
|
+
export interface UnreadSeparatorProps
|
|
7207
|
+
extends React.HTMLAttributes<HTMLDivElement> {
|
|
7208
|
+
/** Number of unread messages */
|
|
7209
|
+
count: number;
|
|
7210
|
+
/** Custom label. Defaults to "{count} unread message(s)" */
|
|
7211
|
+
label?: string;
|
|
7212
|
+
}
|
|
7213
|
+
|
|
7214
|
+
const UnreadSeparator = React.forwardRef(
|
|
7215
|
+
({ className, count, label, ...props }: UnreadSeparatorProps, ref: React.Ref<HTMLDivElement>) => (
|
|
7216
|
+
<div
|
|
7217
|
+
ref={ref}
|
|
7218
|
+
className={cn("flex items-center gap-4 my-2", className)}
|
|
7219
|
+
{...props}
|
|
7220
|
+
>
|
|
7221
|
+
<div className="flex-1 h-px bg-semantic-border-layout" />
|
|
7222
|
+
<span className="text-xs text-semantic-text-muted bg-semantic-bg-ui px-2 shrink-0">
|
|
7223
|
+
{label ?? \`\${count} unread message\${count !== 1 ? "s" : ""}\`}
|
|
7224
|
+
</span>
|
|
7225
|
+
<div className="flex-1 h-px bg-semantic-border-layout" />
|
|
7226
|
+
</div>
|
|
7227
|
+
)
|
|
7228
|
+
);
|
|
7229
|
+
UnreadSeparator.displayName = "UnreadSeparator";
|
|
7230
|
+
|
|
7231
|
+
export { UnreadSeparator };
|
|
6209
7232
|
`
|
|
6210
7233
|
};
|
|
6211
7234
|
var utilsSourceCode = `import { type ClassValue, clsx } from "clsx"
|
|
@@ -6334,6 +7357,24 @@ var componentMetadata = {
|
|
|
6334
7357
|
}
|
|
6335
7358
|
]
|
|
6336
7359
|
},
|
|
7360
|
+
"avatar": {
|
|
7361
|
+
"name": "Avatar",
|
|
7362
|
+
"description": "A avatar component.",
|
|
7363
|
+
"dependencies": [
|
|
7364
|
+
"class-variance-authority",
|
|
7365
|
+
"clsx",
|
|
7366
|
+
"tailwind-merge"
|
|
7367
|
+
],
|
|
7368
|
+
"props": [],
|
|
7369
|
+
"variants": [],
|
|
7370
|
+
"examples": [
|
|
7371
|
+
{
|
|
7372
|
+
"title": "Basic Avatar",
|
|
7373
|
+
"code": "<Avatar>Content</Avatar>",
|
|
7374
|
+
"description": "Simple avatar usage"
|
|
7375
|
+
}
|
|
7376
|
+
]
|
|
7377
|
+
},
|
|
6337
7378
|
"badge": {
|
|
6338
7379
|
"name": "Badge",
|
|
6339
7380
|
"description": "A status badge component with active, failed, disabled, outline, secondary, and destructive variants. Supports asChild for rendering as links.",
|
|
@@ -6604,6 +7645,24 @@ var componentMetadata = {
|
|
|
6604
7645
|
}
|
|
6605
7646
|
]
|
|
6606
7647
|
},
|
|
7648
|
+
"contact-list-item": {
|
|
7649
|
+
"name": "ContactListItem",
|
|
7650
|
+
"description": "A contact list item component.",
|
|
7651
|
+
"dependencies": [
|
|
7652
|
+
"class-variance-authority",
|
|
7653
|
+
"clsx",
|
|
7654
|
+
"tailwind-merge"
|
|
7655
|
+
],
|
|
7656
|
+
"props": [],
|
|
7657
|
+
"variants": [],
|
|
7658
|
+
"examples": [
|
|
7659
|
+
{
|
|
7660
|
+
"title": "Basic ContactListItem",
|
|
7661
|
+
"code": "<ContactListItem>Content</ContactListItem>",
|
|
7662
|
+
"description": "Simple contact list item usage"
|
|
7663
|
+
}
|
|
7664
|
+
]
|
|
7665
|
+
},
|
|
6607
7666
|
"creatable-multi-select": {
|
|
6608
7667
|
"name": "CreatableMultiSelect",
|
|
6609
7668
|
"description": "A creatable multi select component.",
|
|
@@ -6642,6 +7701,24 @@ var componentMetadata = {
|
|
|
6642
7701
|
}
|
|
6643
7702
|
]
|
|
6644
7703
|
},
|
|
7704
|
+
"date-divider": {
|
|
7705
|
+
"name": "DateDivider",
|
|
7706
|
+
"description": "A date divider component.",
|
|
7707
|
+
"dependencies": [
|
|
7708
|
+
"class-variance-authority",
|
|
7709
|
+
"clsx",
|
|
7710
|
+
"tailwind-merge"
|
|
7711
|
+
],
|
|
7712
|
+
"props": [],
|
|
7713
|
+
"variants": [],
|
|
7714
|
+
"examples": [
|
|
7715
|
+
{
|
|
7716
|
+
"title": "Basic DateDivider",
|
|
7717
|
+
"code": "<DateDivider>Content</DateDivider>",
|
|
7718
|
+
"description": "Simple date divider usage"
|
|
7719
|
+
}
|
|
7720
|
+
]
|
|
7721
|
+
},
|
|
6645
7722
|
"delete-confirmation-modal": {
|
|
6646
7723
|
"name": "DeleteConfirmationModal",
|
|
6647
7724
|
"description": "A delete confirmation modal component.",
|
|
@@ -6735,6 +7812,24 @@ var componentMetadata = {
|
|
|
6735
7812
|
}
|
|
6736
7813
|
]
|
|
6737
7814
|
},
|
|
7815
|
+
"image-media": {
|
|
7816
|
+
"name": "ImageMedia",
|
|
7817
|
+
"description": "A image media component.",
|
|
7818
|
+
"dependencies": [
|
|
7819
|
+
"class-variance-authority",
|
|
7820
|
+
"clsx",
|
|
7821
|
+
"tailwind-merge"
|
|
7822
|
+
],
|
|
7823
|
+
"props": [],
|
|
7824
|
+
"variants": [],
|
|
7825
|
+
"examples": [
|
|
7826
|
+
{
|
|
7827
|
+
"title": "Basic ImageMedia",
|
|
7828
|
+
"code": "<ImageMedia>Content</ImageMedia>",
|
|
7829
|
+
"description": "Simple image media usage"
|
|
7830
|
+
}
|
|
7831
|
+
]
|
|
7832
|
+
},
|
|
6738
7833
|
"input": {
|
|
6739
7834
|
"name": "Input",
|
|
6740
7835
|
"description": "A flexible input component for text entry with state variants. Supports default and error states.",
|
|
@@ -6888,6 +7983,44 @@ var componentMetadata = {
|
|
|
6888
7983
|
}
|
|
6889
7984
|
]
|
|
6890
7985
|
},
|
|
7986
|
+
"panel": {
|
|
7987
|
+
"name": "Panel",
|
|
7988
|
+
"description": "A panel component.",
|
|
7989
|
+
"dependencies": [
|
|
7990
|
+
"class-variance-authority",
|
|
7991
|
+
"clsx",
|
|
7992
|
+
"tailwind-merge",
|
|
7993
|
+
"lucide-react"
|
|
7994
|
+
],
|
|
7995
|
+
"props": [],
|
|
7996
|
+
"variants": [],
|
|
7997
|
+
"examples": [
|
|
7998
|
+
{
|
|
7999
|
+
"title": "Basic Panel",
|
|
8000
|
+
"code": "<Panel>Content</Panel>",
|
|
8001
|
+
"description": "Simple panel usage"
|
|
8002
|
+
}
|
|
8003
|
+
]
|
|
8004
|
+
},
|
|
8005
|
+
"phone-input": {
|
|
8006
|
+
"name": "PhoneInput",
|
|
8007
|
+
"description": "A phone input component.",
|
|
8008
|
+
"dependencies": [
|
|
8009
|
+
"class-variance-authority",
|
|
8010
|
+
"clsx",
|
|
8011
|
+
"tailwind-merge",
|
|
8012
|
+
"lucide-react"
|
|
8013
|
+
],
|
|
8014
|
+
"props": [],
|
|
8015
|
+
"variants": [],
|
|
8016
|
+
"examples": [
|
|
8017
|
+
{
|
|
8018
|
+
"title": "Basic PhoneInput",
|
|
8019
|
+
"code": "<PhoneInput>Content</PhoneInput>",
|
|
8020
|
+
"description": "Simple phone input usage"
|
|
8021
|
+
}
|
|
8022
|
+
]
|
|
8023
|
+
},
|
|
6891
8024
|
"readable-field": {
|
|
6892
8025
|
"name": "ReadableField",
|
|
6893
8026
|
"description": "A readable field component.",
|
|
@@ -6907,6 +8040,24 @@ var componentMetadata = {
|
|
|
6907
8040
|
}
|
|
6908
8041
|
]
|
|
6909
8042
|
},
|
|
8043
|
+
"reply-quote": {
|
|
8044
|
+
"name": "ReplyQuote",
|
|
8045
|
+
"description": "A reply quote component.",
|
|
8046
|
+
"dependencies": [
|
|
8047
|
+
"class-variance-authority",
|
|
8048
|
+
"clsx",
|
|
8049
|
+
"tailwind-merge"
|
|
8050
|
+
],
|
|
8051
|
+
"props": [],
|
|
8052
|
+
"variants": [],
|
|
8053
|
+
"examples": [
|
|
8054
|
+
{
|
|
8055
|
+
"title": "Basic ReplyQuote",
|
|
8056
|
+
"code": "<ReplyQuote>Content</ReplyQuote>",
|
|
8057
|
+
"description": "Simple reply quote usage"
|
|
8058
|
+
}
|
|
8059
|
+
]
|
|
8060
|
+
},
|
|
6910
8061
|
"select-field": {
|
|
6911
8062
|
"name": "SelectField",
|
|
6912
8063
|
"description": "A form-ready select component with label, helper text, error handling, and grouped options support.",
|
|
@@ -7106,6 +8257,24 @@ var componentMetadata = {
|
|
|
7106
8257
|
}
|
|
7107
8258
|
]
|
|
7108
8259
|
},
|
|
8260
|
+
"system-message": {
|
|
8261
|
+
"name": "SystemMessage",
|
|
8262
|
+
"description": "A system message component.",
|
|
8263
|
+
"dependencies": [
|
|
8264
|
+
"class-variance-authority",
|
|
8265
|
+
"clsx",
|
|
8266
|
+
"tailwind-merge"
|
|
8267
|
+
],
|
|
8268
|
+
"props": [],
|
|
8269
|
+
"variants": [],
|
|
8270
|
+
"examples": [
|
|
8271
|
+
{
|
|
8272
|
+
"title": "Basic SystemMessage",
|
|
8273
|
+
"code": "<SystemMessage>Content</SystemMessage>",
|
|
8274
|
+
"description": "Simple system message usage"
|
|
8275
|
+
}
|
|
8276
|
+
]
|
|
8277
|
+
},
|
|
7109
8278
|
"table": {
|
|
7110
8279
|
"name": "Table",
|
|
7111
8280
|
"description": "A composable table component with size variants, loading/empty states, sticky columns, and sorting support.",
|
|
@@ -7149,6 +8318,25 @@ var componentMetadata = {
|
|
|
7149
8318
|
}
|
|
7150
8319
|
]
|
|
7151
8320
|
},
|
|
8321
|
+
"tabs": {
|
|
8322
|
+
"name": "Tabs",
|
|
8323
|
+
"description": "A tabs component.",
|
|
8324
|
+
"dependencies": [
|
|
8325
|
+
"@radix-ui/react-tabs",
|
|
8326
|
+
"class-variance-authority",
|
|
8327
|
+
"clsx",
|
|
8328
|
+
"tailwind-merge"
|
|
8329
|
+
],
|
|
8330
|
+
"props": [],
|
|
8331
|
+
"variants": [],
|
|
8332
|
+
"examples": [
|
|
8333
|
+
{
|
|
8334
|
+
"title": "Basic Tabs",
|
|
8335
|
+
"code": "<Tabs>Content</Tabs>",
|
|
8336
|
+
"description": "Simple tabs usage"
|
|
8337
|
+
}
|
|
8338
|
+
]
|
|
8339
|
+
},
|
|
7152
8340
|
"tag": {
|
|
7153
8341
|
"name": "Tag",
|
|
7154
8342
|
"description": "A tag component for event labels with optional bold label prefix. Rounded rectangle tags for categorization.",
|
|
@@ -7326,6 +8514,24 @@ var componentMetadata = {
|
|
|
7326
8514
|
}
|
|
7327
8515
|
]
|
|
7328
8516
|
},
|
|
8517
|
+
"textarea": {
|
|
8518
|
+
"name": "Textarea",
|
|
8519
|
+
"description": "A textarea component.",
|
|
8520
|
+
"dependencies": [
|
|
8521
|
+
"class-variance-authority",
|
|
8522
|
+
"clsx",
|
|
8523
|
+
"tailwind-merge"
|
|
8524
|
+
],
|
|
8525
|
+
"props": [],
|
|
8526
|
+
"variants": [],
|
|
8527
|
+
"examples": [
|
|
8528
|
+
{
|
|
8529
|
+
"title": "Basic Textarea",
|
|
8530
|
+
"code": "<Textarea>Content</Textarea>",
|
|
8531
|
+
"description": "Simple textarea usage"
|
|
8532
|
+
}
|
|
8533
|
+
]
|
|
8534
|
+
},
|
|
7329
8535
|
"toast": {
|
|
7330
8536
|
"name": "Toast",
|
|
7331
8537
|
"description": "A toast component.",
|
|
@@ -7382,6 +8588,24 @@ var componentMetadata = {
|
|
|
7382
8588
|
"description": "Simple typography usage"
|
|
7383
8589
|
}
|
|
7384
8590
|
]
|
|
8591
|
+
},
|
|
8592
|
+
"unread-separator": {
|
|
8593
|
+
"name": "UnreadSeparator",
|
|
8594
|
+
"description": "A unread separator component.",
|
|
8595
|
+
"dependencies": [
|
|
8596
|
+
"class-variance-authority",
|
|
8597
|
+
"clsx",
|
|
8598
|
+
"tailwind-merge"
|
|
8599
|
+
],
|
|
8600
|
+
"props": [],
|
|
8601
|
+
"variants": [],
|
|
8602
|
+
"examples": [
|
|
8603
|
+
{
|
|
8604
|
+
"title": "Basic UnreadSeparator",
|
|
8605
|
+
"code": "<UnreadSeparator>Content</UnreadSeparator>",
|
|
8606
|
+
"description": "Simple unread separator usage"
|
|
8607
|
+
}
|
|
8608
|
+
]
|
|
7385
8609
|
}
|
|
7386
8610
|
};
|
|
7387
8611
|
function getComponentNames() {
|