myoperator-mcp 0.2.122 → 0.2.124

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.
Files changed (2) hide show
  1. package/dist/index.js +1632 -408
  2. 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<HTMLDivElement, AccordionProps>(
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<HTMLDivElement, AccordionItemProps>(
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<HTMLDivElement, AlertProps>(
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<HTMLDivElement, BadgeProps>(
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-semantic-border-layout bg-semantic-bg-primary text-semantic-text-secondary hover:bg-semantic-primary-surface",
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-secondary underline-offset-4 hover:underline",
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<HTMLButtonElement, ButtonProps>(
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 && !value.includes(trimmed)) {
1223
- onValueChange?.([...value, trimmed])
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
- setInputValue(e.target.value)
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 contextual */}
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
- {canAddCustom ? (
1360
- <span className="text-sm font-medium text-semantic-text-primary">
1361
- Press enter to add &ldquo;{inputValue.trim()}&rdquo;
1362
- </span>
1363
- ) : (
1364
- <span className="text-sm text-semantic-text-muted">
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 text below trigger */}
1397
- {helperText && !isOpen && (
1398
- <div className="flex items-center gap-1.5 mt-1.5">
1399
- <Info className="size-[18px] shrink-0 text-semantic-text-muted" />
1400
- <p className="m-0 text-sm text-semantic-text-muted">
1401
- {helperText}
1402
- </p>
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<HTMLDivElement, CreatableSelectProps>(
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
- onValueChange?.(trimmed)
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) => setSearch(e.target.value)}
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, Circle } from "lucide-react";
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-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-semantic-bg-ui data-[state=open]:bg-semantic-bg-ui",
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
- >(({ className, inset, ...props }, ref) => (
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-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-semantic-bg-ui focus:text-semantic-text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
2436
+ "relative flex cursor-pointer select-none items-center 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
- React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
2166
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
2167
- >(({ className, children, checked, ...props }, ref) => (
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-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-semantic-bg-ui focus:text-semantic-text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
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
- {children}
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
- React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
2190
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
2191
- >(({ className, children, ...props }, ref) => (
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-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-semantic-bg-ui focus:text-semantic-text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
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
- <Circle className="h-2 w-2 fill-current" />
2509
+ <Check className="h-4 w-4" />
2203
2510
  </DropdownMenuPrimitive.ItemIndicator>
2204
2511
  </span>
2205
- {children}
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<HTMLDivElement, FormModalProps>(
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 hover:border-semantic-border-input-focus focus:outline-none focus:border-semantic-border-input-focus focus:shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
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 hover:border-semantic-error-primary focus:outline-none focus:border-semantic-error-primary focus:shadow-[0_0_0_1px_rgba(240,68,56,0.1)]",
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<HTMLInputElement, InputProps>(
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<HTMLButtonElement, MultiSelectProps>(
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<HTMLDivElement, PageHeaderProps>(
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
- "readable-field": `import * as React from "react";
3597
- import { Copy, Check, Eye, EyeOff } from "lucide-react";
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
- export interface ReadableFieldProps
3601
- extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
3602
- /** Label text displayed above the field */
3603
- label: string;
3604
- /** Value to display and copy */
3605
- value: string;
3606
- /** Helper text displayed below the field */
3607
- helperText?: string;
3608
- /** When true, masks the value with dots and shows eye toggle */
3609
- secret?: boolean;
3610
- /** Header action (e.g., "Regenerate" link) */
3611
- headerAction?: {
3612
- label: string;
3613
- onClick: () => void;
3614
- /** When true, button is shown but non-interactive */
3615
- disabled?: boolean;
3616
- /** Tooltip text shown on hover when disabled */
3617
- disabledTooltip?: string;
3618
- };
3619
- /** Callback when value is copied */
3620
- onValueCopy?: (value: string) => void;
3621
- /** Additional class for the input container */
3622
- inputClassName?: string;
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
- * ReadableField displays a read-only value with copy-to-clipboard functionality.
3627
- * Supports secret mode for sensitive data like API keys and passwords.
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
- * // Simple readable field
3632
- * <ReadableField
3633
- * label="Base URL"
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<HTMLDivElement, ReadableFieldProps>(
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<HTMLButtonElement, SelectFieldProps>(
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-xs font-normal text-semantic-text-muted",
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="px-2 pb-2">
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 px-3 text-sm border border-semantic-border-input rounded bg-semantic-bg-primary placeholder:text-semantic-text-placeholder focus:outline-none focus:border-semantic-border-input-focus/50"
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<HTMLDivElement, SkeletonProps>(
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<HTMLDivElement, SpinnerProps>(
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<HTMLTableElement, TableProps>(
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<HTMLTableSectionElement, TableBodyProps>(
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<HTMLTableRowElement, TableRowProps>(
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<HTMLTableCellElement, TableHeadProps>(
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<HTMLTableCellElement, TableCellProps>(
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<HTMLButtonElement, TableToggleProps>(
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<HTMLSpanElement, TagProps>(
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 }))}
@@ -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/50 focus-within:shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
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/60 focus-within:shadow-[0_0_0_1px_rgba(240,68,56,0.1)]",
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
- "h-[42px] w-full rounded bg-semantic-bg-primary px-4 py-2 text-base text-semantic-text-primary outline-none transition-all file:border-0 file:bg-transparent file:text-base 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)]",
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/50 focus:shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
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/60 focus:shadow-[0_0_0_1px_rgba(240,68,56,0.1)]",
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<HTMLInputElement, TextFieldProps>(
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
- loading,
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<HTMLInputElement>) => {
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 inputId = id || generatedId;
5351
- const helperId = \`\${inputId}-helper\`;
5352
- const errorId = \`\${inputId}-error\`;
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
- // Render the input element
5358
- const inputElement = (
5359
- <input
5360
- ref={ref}
5361
- id={inputId}
5362
- type={type}
5363
- className={cn(
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={inputId}
6421
+ htmlFor={textareaId}
5395
6422
  className={cn(
5396
- "text-xs font-normal text-semantic-text-muted",
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
- {/* Input or Input Container */}
5408
- {hasAddons ? (
5409
- <div
5410
- className={cn(
5411
- textFieldContainerVariants({
5412
- state: derivedState,
5413
- disabled: disabled || loading,
5414
- }),
5415
- "h-[42px] px-4",
5416
- inputContainerClassName
5417
- )}
5418
- >
5419
- {prefix && (
5420
- <span className="text-sm text-semantic-text-muted mr-2 select-none">
5421
- {prefix}
5422
- </span>
5423
- )}
5424
- {leftIcon && (
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-xs text-semantic-error-primary"
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-xs text-semantic-text-muted">
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-xs",
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
- TextField.displayName = "TextField";
6488
+ Textarea.displayName = "Textarea";
5484
6489
 
5485
- export { TextField, textFieldContainerVariants, textFieldInputVariants };
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
- React.ElementRef<typeof ToastPrimitives.Root>,
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<HTMLElement, TypographyProps>(
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() {