@fanvue/ui 3.7.2 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/cjs/components/Alert/Alert.cjs +28 -5
  2. package/dist/cjs/components/Alert/Alert.cjs.map +1 -1
  3. package/dist/cjs/components/Badge/Badge.cjs +17 -5
  4. package/dist/cjs/components/Badge/Badge.cjs.map +1 -1
  5. package/dist/cjs/components/Breadcrumb/Breadcrumb.cjs +46 -23
  6. package/dist/cjs/components/Breadcrumb/Breadcrumb.cjs.map +1 -1
  7. package/dist/cjs/components/Checkbox/Checkbox.cjs +1 -1
  8. package/dist/cjs/components/Checkbox/Checkbox.cjs.map +1 -1
  9. package/dist/cjs/components/Dialog/Dialog.cjs +21 -8
  10. package/dist/cjs/components/Dialog/Dialog.cjs.map +1 -1
  11. package/dist/cjs/components/FanFollowerCount/FanFollowerCount.cjs +64 -0
  12. package/dist/cjs/components/FanFollowerCount/FanFollowerCount.cjs.map +1 -0
  13. package/dist/cjs/components/IconButton/IconButton.cjs +1 -1
  14. package/dist/cjs/components/IconButton/IconButton.cjs.map +1 -1
  15. package/dist/cjs/components/Icons/GifIcon.cjs +101 -0
  16. package/dist/cjs/components/Icons/GifIcon.cjs.map +1 -0
  17. package/dist/cjs/components/Icons/VerifiedIcon.cjs +82 -0
  18. package/dist/cjs/components/Icons/VerifiedIcon.cjs.map +1 -0
  19. package/dist/cjs/components/Link/Link.cjs +85 -0
  20. package/dist/cjs/components/Link/Link.cjs.map +1 -0
  21. package/dist/cjs/components/Pagination/Pagination.cjs +7 -7
  22. package/dist/cjs/components/Pagination/Pagination.cjs.map +1 -1
  23. package/dist/cjs/components/Pill/Pill.cjs +3 -1
  24. package/dist/cjs/components/Pill/Pill.cjs.map +1 -1
  25. package/dist/cjs/components/ProfileOnlineStatus/ProfileOnlineStatus.cjs +44 -0
  26. package/dist/cjs/components/ProfileOnlineStatus/ProfileOnlineStatus.cjs.map +1 -0
  27. package/dist/cjs/components/ProfileStatus/ProfileStatus.cjs +51 -0
  28. package/dist/cjs/components/ProfileStatus/ProfileStatus.cjs.map +1 -0
  29. package/dist/cjs/components/Radio/Radio.cjs +65 -34
  30. package/dist/cjs/components/Radio/Radio.cjs.map +1 -1
  31. package/dist/cjs/components/RatingSummary/RatingSummary.cjs +103 -0
  32. package/dist/cjs/components/RatingSummary/RatingSummary.cjs.map +1 -0
  33. package/dist/cjs/components/ReviewCard/ReviewCard.cjs +51 -0
  34. package/dist/cjs/components/ReviewCard/ReviewCard.cjs.map +1 -0
  35. package/dist/cjs/components/Select/Select.cjs +4 -4
  36. package/dist/cjs/components/Select/Select.cjs.map +1 -1
  37. package/dist/cjs/components/TextField/TextField.cjs +4 -4
  38. package/dist/cjs/components/TextField/TextField.cjs.map +1 -1
  39. package/dist/cjs/components/Toast/Toast.cjs +18 -32
  40. package/dist/cjs/components/Toast/Toast.cjs.map +1 -1
  41. package/dist/cjs/components/UserDisplayName/UserDisplayName.cjs +67 -0
  42. package/dist/cjs/components/UserDisplayName/UserDisplayName.cjs.map +1 -0
  43. package/dist/cjs/components/UserHandle/UserHandle.cjs +46 -0
  44. package/dist/cjs/components/UserHandle/UserHandle.cjs.map +1 -0
  45. package/dist/cjs/components/UserItem/UserItem.cjs +74 -0
  46. package/dist/cjs/components/UserItem/UserItem.cjs.map +1 -0
  47. package/dist/cjs/index.cjs +24 -0
  48. package/dist/cjs/index.cjs.map +1 -1
  49. package/dist/cjs/utils/getInitials.cjs +10 -0
  50. package/dist/cjs/utils/getInitials.cjs.map +1 -0
  51. package/dist/components/Alert/Alert.mjs +28 -5
  52. package/dist/components/Alert/Alert.mjs.map +1 -1
  53. package/dist/components/Badge/Badge.mjs +17 -5
  54. package/dist/components/Badge/Badge.mjs.map +1 -1
  55. package/dist/components/Breadcrumb/Breadcrumb.mjs +46 -23
  56. package/dist/components/Breadcrumb/Breadcrumb.mjs.map +1 -1
  57. package/dist/components/Checkbox/Checkbox.mjs +1 -1
  58. package/dist/components/Checkbox/Checkbox.mjs.map +1 -1
  59. package/dist/components/Dialog/Dialog.mjs +21 -8
  60. package/dist/components/Dialog/Dialog.mjs.map +1 -1
  61. package/dist/components/FanFollowerCount/FanFollowerCount.mjs +47 -0
  62. package/dist/components/FanFollowerCount/FanFollowerCount.mjs.map +1 -0
  63. package/dist/components/IconButton/IconButton.mjs +1 -1
  64. package/dist/components/IconButton/IconButton.mjs.map +1 -1
  65. package/dist/components/Icons/GifIcon.mjs +84 -0
  66. package/dist/components/Icons/GifIcon.mjs.map +1 -0
  67. package/dist/components/Icons/VerifiedIcon.mjs +65 -0
  68. package/dist/components/Icons/VerifiedIcon.mjs.map +1 -0
  69. package/dist/components/Link/Link.mjs +68 -0
  70. package/dist/components/Link/Link.mjs.map +1 -0
  71. package/dist/components/Pagination/Pagination.mjs +7 -7
  72. package/dist/components/Pagination/Pagination.mjs.map +1 -1
  73. package/dist/components/Pill/Pill.mjs +3 -1
  74. package/dist/components/Pill/Pill.mjs.map +1 -1
  75. package/dist/components/ProfileOnlineStatus/ProfileOnlineStatus.mjs +27 -0
  76. package/dist/components/ProfileOnlineStatus/ProfileOnlineStatus.mjs.map +1 -0
  77. package/dist/components/ProfileStatus/ProfileStatus.mjs +34 -0
  78. package/dist/components/ProfileStatus/ProfileStatus.mjs.map +1 -0
  79. package/dist/components/Radio/Radio.mjs +66 -35
  80. package/dist/components/Radio/Radio.mjs.map +1 -1
  81. package/dist/components/RatingSummary/RatingSummary.mjs +86 -0
  82. package/dist/components/RatingSummary/RatingSummary.mjs.map +1 -0
  83. package/dist/components/ReviewCard/ReviewCard.mjs +34 -0
  84. package/dist/components/ReviewCard/ReviewCard.mjs.map +1 -0
  85. package/dist/components/Select/Select.mjs +4 -4
  86. package/dist/components/Select/Select.mjs.map +1 -1
  87. package/dist/components/TextField/TextField.mjs +4 -4
  88. package/dist/components/TextField/TextField.mjs.map +1 -1
  89. package/dist/components/Toast/Toast.mjs +18 -32
  90. package/dist/components/Toast/Toast.mjs.map +1 -1
  91. package/dist/components/UserDisplayName/UserDisplayName.mjs +50 -0
  92. package/dist/components/UserDisplayName/UserDisplayName.mjs.map +1 -0
  93. package/dist/components/UserHandle/UserHandle.mjs +29 -0
  94. package/dist/components/UserHandle/UserHandle.mjs.map +1 -0
  95. package/dist/components/UserItem/UserItem.mjs +57 -0
  96. package/dist/components/UserItem/UserItem.mjs.map +1 -0
  97. package/dist/index.d.ts +404 -15
  98. package/dist/index.mjs +24 -0
  99. package/dist/index.mjs.map +1 -1
  100. package/dist/utils/getInitials.mjs +10 -0
  101. package/dist/utils/getInitials.mjs.map +1 -0
  102. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.mjs","sources":["../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import * as ToastPrimitive from \"@radix-ui/react-toast\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { Button } from \"../Button/Button\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\nimport { ErrorIcon } from \"../Icons/ErrorIcon\";\nimport { InfoIcon } from \"../Icons/InfoIcon\";\nimport { SuccessIcon } from \"../Icons/SuccessIcon\";\nimport { WarningIcon } from \"../Icons/WarningIcon\";\n\n/** Visual/semantic variant of the toast notification. */\nexport type ToastVariant = \"info\" | \"warning\" | \"success\" | \"error\" | \"messageToast\";\n\nexport interface ToastProps\n extends Omit<Omit<React.ComponentPropsWithoutRef<typeof ToastPrimitive.Root>, \"type\">, \"title\"> {\n /** Visual/semantic variant of the toast. @default \"info\" */\n variant?: ToastVariant;\n /** Title text displayed in bold at the top of the toast. */\n title?: string;\n /** Description or body content displayed below the title. */\n description?: React.ReactNode;\n /** Label for the optional action button. @default \"Action\" */\n actionLabel?: string;\n /** Click handler for the action button. When provided, the action button is rendered. */\n onActionClick?: () => void;\n /** Whether to show the close button. @default true */\n showClose?: boolean;\n /** Accessible label for the close button. @default \"Close notification\" */\n closeLabel?: string;\n /** Avatar image URL (used by the `messageToast` variant). */\n avatarSrc?: string;\n /** Alt text for the avatar image. */\n avatarAlt?: string;\n /** Fallback content for the avatar (e.g. initials). */\n avatarFallback?: string;\n}\n\n/** Props for the {@link ToastProvider}. Wraps Radix `Toast.Provider`. */\nexport interface ToastProviderProps extends ToastPrimitive.ToastProviderProps {}\n/** Props for the {@link ToastViewport}. Controls where toasts are rendered on screen. */\nexport interface ToastViewportProps\n extends React.ComponentPropsWithoutRef<typeof ToastPrimitive.Viewport> {}\n\n/** Provides toast context. Wrap your application (or a subtree) with this provider. */\nexport const ToastProvider: React.FC<ToastProviderProps> = ToastPrimitive.Provider;\n\n/** Fixed-position container that renders active toasts. Place once at the root of your app. */\nexport const ToastViewport = React.forwardRef<\n React.ElementRef<typeof ToastPrimitive.Viewport>,\n ToastViewportProps\n>(({ className, ...props }, ref) => (\n <ToastPrimitive.Viewport\n ref={ref}\n className={cn(\n \"pointer-events-none fixed right-0 bottom-0 z-100 flex max-h-screen w-full flex-col-reverse gap-3 p-4 md:max-w-[420px]\",\n className,\n )}\n {...props}\n />\n));\n\nToastViewport.displayName = \"ToastViewport\";\n\nconst VariantIcon = ({ variant }: { variant: ToastVariant }) => {\n switch (variant) {\n case \"info\":\n return <InfoIcon className=\"size-5 text-info-content\" />;\n case \"warning\":\n return <WarningIcon className=\"size-5 text-warning-content\" />;\n case \"success\":\n return <SuccessIcon className=\"size-5 text-success-content\" />;\n case \"error\":\n return <ErrorIcon className=\"size-5 text-error-content\" />;\n }\n};\n\n/**\n * A dismissible notification that appears temporarily. Supports `info`,\n * `warning`, `success`, `error`, and `messageToast` variants with optional\n * action button, close control, and avatar.\n *\n * Use inside a {@link ToastProvider} with a {@link ToastViewport}.\n *\n * @example\n * ```tsx\n * <Toast variant=\"success\" title=\"Saved\" description=\"Your changes are live.\" />\n * ```\n */\nexport const Toast = React.forwardRef<React.ComponentRef<typeof ToastPrimitive.Root>, ToastProps>(\n (\n {\n className,\n variant = \"info\",\n title,\n description,\n actionLabel,\n onActionClick,\n showClose = true,\n closeLabel = \"Close notification\",\n avatarSrc,\n avatarAlt,\n avatarFallback,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <ToastPrimitive.Root\n ref={ref}\n data-testid=\"toast\"\n className={cn(\n // Base styles\n \"group pointer-events-auto relative flex w-full flex-col items-start gap-3 overflow-hidden rounded-xs border-none bg-surface-primary-inverted p-4 text-content-primary-inverted shadow-lg transition-all\",\n // Dark mode\n \"dark:border-opacity-100\",\n // Animation\n \"data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-bottom-full data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=end]:animate-out data-[swipe=move]:transition-none\",\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n <div className=\"flex w-full items-center gap-3\">\n <div className=\"self-start\">\n {variant === \"messageToast\" ? (\n avatarSrc && <Avatar src={avatarSrc} alt={avatarAlt} fallback={avatarFallback} />\n ) : (\n <VariantIcon variant={variant} />\n )}\n </div>\n <div className=\"flex flex-1 flex-col items-start\">\n {title && (\n <ToastPrimitive.Title className=\"typography-body-small-14px-semibold\">\n {title}\n </ToastPrimitive.Title>\n )}\n {description && (\n <ToastPrimitive.Description className=\"typography-body-small-14px-regular mt-1 opacity-90\">\n {description}\n </ToastPrimitive.Description>\n )}\n {children}\n {onActionClick && (\n <Button\n variant=\"secondary\"\n // These styles are basically inverted from the selected theme\n className=\"mt-4 border-content-primary-inverted text-content-primary-inverted\"\n size=\"32\"\n onClick={onActionClick}\n >\n {actionLabel ?? \"Action\"}\n </Button>\n )}\n </div>\n </div>\n {showClose && (\n <ToastPrimitive.Close asChild>\n <IconButton\n icon={<CloseIcon />}\n aria-label={closeLabel}\n // same as the button above\n className=\"absolute top-2 right-2 text-content-primary-inverted\"\n variant=\"tertiary\"\n size=\"24\"\n />\n </ToastPrimitive.Close>\n )}\n </ToastPrimitive.Root>\n );\n },\n);\n\nToast.displayName = \"Toast\";\n"],"names":[],"mappings":";;;;;;;;;;;;;AA8CO,MAAM,gBAA8C,eAAe;AAGnE,MAAM,gBAAgB,MAAM,WAGjC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,eAAe;AAAA,EAAf;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,EAAA;AACN,CACD;AAED,cAAc,cAAc;AAE5B,MAAM,cAAc,CAAC,EAAE,cAAyC;AAC9D,UAAQ,SAAA;AAAA,IACN,KAAK;AACH,aAAO,oBAAC,UAAA,EAAS,WAAU,2BAAA,CAA2B;AAAA,IACxD,KAAK;AACH,aAAO,oBAAC,aAAA,EAAY,WAAU,8BAAA,CAA8B;AAAA,IAC9D,KAAK;AACH,aAAO,oBAAC,aAAA,EAAY,WAAU,8BAAA,CAA8B;AAAA,IAC9D,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,WAAU,4BAAA,CAA4B;AAAA,EAAA;AAE9D;AAcO,MAAM,QAAQ,MAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACE;AAAA,MAAC,eAAe;AAAA,MAAf;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAW;AAAA;AAAA,UAET;AAAA;AAAA,UAEA;AAAA;AAAA,UAEA;AAAA;AAAA,UAEA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAA,qBAAC,OAAA,EAAI,WAAU,kCACb,UAAA;AAAA,YAAA,oBAAC,SAAI,WAAU,cACZ,sBAAY,iBACX,iCAAc,QAAA,EAAO,KAAK,WAAW,KAAK,WAAW,UAAU,eAAA,CAAgB,IAE/E,oBAAC,aAAA,EAAY,SAAkB,EAAA,CAEnC;AAAA,YACA,qBAAC,OAAA,EAAI,WAAU,oCACZ,UAAA;AAAA,cAAA,6BACE,eAAe,OAAf,EAAqB,WAAU,uCAC7B,UAAA,OACH;AAAA,cAED,eACC,oBAAC,eAAe,aAAf,EAA2B,WAAU,sDACnC,UAAA,aACH;AAAA,cAED;AAAA,cACA,iBACC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,SAAQ;AAAA,kBAER,WAAU;AAAA,kBACV,MAAK;AAAA,kBACL,SAAS;AAAA,kBAER,UAAA,eAAe;AAAA,gBAAA;AAAA,cAAA;AAAA,YAClB,EAAA,CAEJ;AAAA,UAAA,GACF;AAAA,UACC,aACC,oBAAC,eAAe,OAAf,EAAqB,SAAO,MAC3B,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,0BAAO,WAAA,EAAU;AAAA,cACjB,cAAY;AAAA,cAEZ,WAAU;AAAA,cACV,SAAQ;AAAA,cACR,MAAK;AAAA,YAAA;AAAA,UAAA,EACP,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;"}
1
+ {"version":3,"file":"Toast.mjs","sources":["../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import * as ToastPrimitive from \"@radix-ui/react-toast\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { Button } from \"../Button/Button\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\nimport { ErrorIcon } from \"../Icons/ErrorIcon\";\nimport { InfoIcon } from \"../Icons/InfoIcon\";\nimport { SuccessIcon } from \"../Icons/SuccessIcon\";\nimport { WarningIcon } from \"../Icons/WarningIcon\";\n\n/** Visual/semantic variant of the toast notification. */\nexport type ToastVariant = \"info\" | \"warning\" | \"success\" | \"error\" | \"messageToast\";\n\nexport interface ToastProps\n extends Omit<Omit<React.ComponentPropsWithoutRef<typeof ToastPrimitive.Root>, \"type\">, \"title\"> {\n /** Visual/semantic variant of the toast. @default \"info\" */\n variant?: ToastVariant;\n /** Title text displayed in bold at the top of the toast. */\n title?: string;\n /** Description or body content displayed below the title. */\n description?: React.ReactNode;\n /** Label for the optional action button. @default \"Action\" */\n actionLabel?: string;\n /** Click handler for the action button. When provided, the action button is rendered. */\n onActionClick?: () => void;\n /** Whether to show the close button. @default true */\n showClose?: boolean;\n /** Accessible label for the close button. @default \"Close notification\" */\n closeLabel?: string;\n /** Avatar image URL (used by the `messageToast` variant). */\n avatarSrc?: string;\n /** Alt text for the avatar image. */\n avatarAlt?: string;\n /** Fallback content for the avatar (e.g. initials). */\n avatarFallback?: string;\n}\n\n/** Props for the {@link ToastProvider}. Wraps Radix `Toast.Provider`. */\nexport interface ToastProviderProps extends ToastPrimitive.ToastProviderProps {}\n/** Props for the {@link ToastViewport}. Controls where toasts are rendered on screen. */\nexport interface ToastViewportProps\n extends React.ComponentPropsWithoutRef<typeof ToastPrimitive.Viewport> {}\n\n/** Provides toast context. Wrap your application (or a subtree) with this provider. */\nexport const ToastProvider: React.FC<ToastProviderProps> = ToastPrimitive.Provider;\n\n/** Fixed-position container that renders active toasts. Place once at the root of your app. */\nexport const ToastViewport = React.forwardRef<\n React.ElementRef<typeof ToastPrimitive.Viewport>,\n ToastViewportProps\n>(({ className, ...props }, ref) => (\n <ToastPrimitive.Viewport\n ref={ref}\n className={cn(\n \"pointer-events-none fixed right-0 bottom-0 z-100 flex max-h-screen w-full flex-col-reverse gap-3 p-4 md:max-w-[420px]\",\n className,\n )}\n {...props}\n />\n));\n\nToastViewport.displayName = \"ToastViewport\";\n\nconst VariantIcon = ({ variant }: { variant: ToastVariant }) => {\n switch (variant) {\n case \"info\":\n return <InfoIcon size={16} filled className=\"text-alerts-toast-icon-info\" />;\n case \"warning\":\n return <WarningIcon size={16} filled className=\"text-alerts-toast-icon-warning\" />;\n case \"success\":\n return <SuccessIcon className=\"size-4 text-alerts-toast-icon-success\" />;\n case \"error\":\n return <ErrorIcon className=\"size-4 text-alerts-toast-icon-error\" />;\n }\n};\n\n/**\n * A dismissible notification that appears temporarily. Supports `info`,\n * `warning`, `success`, `error`, and `messageToast` variants with optional\n * action button, close control, and avatar.\n *\n * Use inside a {@link ToastProvider} with a {@link ToastViewport}.\n *\n * @example\n * ```tsx\n * <Toast variant=\"success\" title=\"Saved\" description=\"Your changes are live.\" />\n * ```\n */\nexport const Toast = React.forwardRef<React.ComponentRef<typeof ToastPrimitive.Root>, ToastProps>(\n (\n {\n className,\n variant = \"info\",\n title,\n description,\n actionLabel,\n onActionClick,\n showClose = true,\n closeLabel = \"Close notification\",\n avatarSrc,\n avatarAlt,\n avatarFallback,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <ToastPrimitive.Root\n ref={ref}\n data-testid=\"toast\"\n className={cn(\n \"group pointer-events-auto relative flex w-full items-start gap-6 overflow-hidden rounded-md border-none bg-surface-primary-inverted py-3 pr-3 pl-4 text-content-primary-inverted shadow-md transition-all\",\n \"data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-bottom-full data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=end]:animate-out data-[swipe=move]:transition-none\",\n className,\n )}\n {...props}\n >\n <div className=\"flex min-w-0 flex-1 items-start gap-3 py-1 pr-1\">\n <div className=\"flex shrink-0 items-center pt-px\">\n {variant === \"messageToast\" ? (\n avatarSrc && <Avatar src={avatarSrc} alt={avatarAlt} fallback={avatarFallback} />\n ) : (\n <VariantIcon variant={variant} />\n )}\n </div>\n <div className=\"flex min-w-0 flex-1 flex-col items-start gap-4\">\n <div className=\"flex w-full flex-col items-start gap-1\">\n {title && (\n <ToastPrimitive.Title className=\"typography-body-small-14px-semibold\">\n {title}\n </ToastPrimitive.Title>\n )}\n {description && (\n <ToastPrimitive.Description className=\"typography-body-small-14px-regular\">\n {description}\n </ToastPrimitive.Description>\n )}\n {children}\n </div>\n {onActionClick && (\n <Button variant=\"outline\" negative size=\"32\" onClick={onActionClick}>\n {actionLabel ?? \"Action\"}\n </Button>\n )}\n </div>\n </div>\n {showClose && (\n <ToastPrimitive.Close asChild>\n <button\n type=\"button\"\n aria-label={closeLabel}\n className=\"flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-xs bg-buttons-secondary-negative-default text-content-primary-inverted transition-colors hover:bg-buttons-secondary-negative-hover focus-visible:shadow-focus-ring focus-visible:outline-none\"\n >\n <CloseIcon size={16} aria-hidden=\"true\" />\n </button>\n </ToastPrimitive.Close>\n )}\n </ToastPrimitive.Root>\n );\n },\n);\n\nToast.displayName = \"Toast\";\n"],"names":[],"mappings":";;;;;;;;;;;;AA6CO,MAAM,gBAA8C,eAAe;AAGnE,MAAM,gBAAgB,MAAM,WAGjC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,eAAe;AAAA,EAAf;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,EAAA;AACN,CACD;AAED,cAAc,cAAc;AAE5B,MAAM,cAAc,CAAC,EAAE,cAAyC;AAC9D,UAAQ,SAAA;AAAA,IACN,KAAK;AACH,iCAAQ,UAAA,EAAS,MAAM,IAAI,QAAM,MAAC,WAAU,+BAA8B;AAAA,IAC5E,KAAK;AACH,iCAAQ,aAAA,EAAY,MAAM,IAAI,QAAM,MAAC,WAAU,kCAAiC;AAAA,IAClF,KAAK;AACH,aAAO,oBAAC,aAAA,EAAY,WAAU,wCAAA,CAAwC;AAAA,IACxE,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,WAAU,sCAAA,CAAsC;AAAA,EAAA;AAExE;AAcO,MAAM,QAAQ,MAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACE;AAAA,MAAC,eAAe;AAAA,MAAf;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAA,qBAAC,OAAA,EAAI,WAAU,mDACb,UAAA;AAAA,YAAA,oBAAC,SAAI,WAAU,oCACZ,sBAAY,iBACX,iCAAc,QAAA,EAAO,KAAK,WAAW,KAAK,WAAW,UAAU,eAAA,CAAgB,IAE/E,oBAAC,aAAA,EAAY,SAAkB,EAAA,CAEnC;AAAA,YACA,qBAAC,OAAA,EAAI,WAAU,kDACb,UAAA;AAAA,cAAA,qBAAC,OAAA,EAAI,WAAU,0CACZ,UAAA;AAAA,gBAAA,6BACE,eAAe,OAAf,EAAqB,WAAU,uCAC7B,UAAA,OACH;AAAA,gBAED,eACC,oBAAC,eAAe,aAAf,EAA2B,WAAU,sCACnC,UAAA,aACH;AAAA,gBAED;AAAA,cAAA,GACH;AAAA,cACC,iBACC,oBAAC,QAAA,EAAO,SAAQ,WAAU,UAAQ,MAAC,MAAK,MAAK,SAAS,eACnD,UAAA,eAAe,SAAA,CAClB;AAAA,YAAA,EAAA,CAEJ;AAAA,UAAA,GACF;AAAA,UACC,aACC,oBAAC,eAAe,OAAf,EAAqB,SAAO,MAC3B,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY;AAAA,cACZ,WAAU;AAAA,cAEV,UAAA,oBAAC,WAAA,EAAU,MAAM,IAAI,eAAY,OAAA,CAAO;AAAA,YAAA;AAAA,UAAA,EAC1C,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;"}
@@ -0,0 +1,50 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../../utils/cn.mjs";
5
+ import { VerifiedIcon } from "../Icons/VerifiedIcon.mjs";
6
+ import { ProfileOnlineStatus } from "../ProfileOnlineStatus/ProfileOnlineStatus.mjs";
7
+ const UserDisplayName = React.forwardRef(
8
+ ({
9
+ ambassador,
10
+ ambassadorLabel = "Ambassador",
11
+ children,
12
+ className,
13
+ component = "span",
14
+ noWrap = true,
15
+ onlineLabel = "Online",
16
+ showOnlineStatus,
17
+ verified,
18
+ verifiedLabel = "Verified",
19
+ ...props
20
+ }, ref) => {
21
+ const Component = component;
22
+ const badge = ambassador ? { label: ambassadorLabel, tint: "text-success-content" } : verified ? { label: verifiedLabel, tint: "text-content-primary" } : null;
23
+ return /* @__PURE__ */ jsxs(
24
+ Component,
25
+ {
26
+ ref,
27
+ className: cn("inline-flex max-w-full items-center", className),
28
+ ...props,
29
+ children: [
30
+ /* @__PURE__ */ jsx("span", { className: cn("min-w-0", noWrap && "truncate"), children }),
31
+ badge && /* @__PURE__ */ jsx(
32
+ "span",
33
+ {
34
+ role: "img",
35
+ "aria-label": badge.label,
36
+ className: cn("ml-2 inline-flex shrink-0 items-center", badge.tint),
37
+ children: /* @__PURE__ */ jsx(VerifiedIcon, { size: 16 })
38
+ }
39
+ ),
40
+ showOnlineStatus && /* @__PURE__ */ jsx(ProfileOnlineStatus, { label: onlineLabel, className: "shrink-0 ml-2" })
41
+ ]
42
+ }
43
+ );
44
+ }
45
+ );
46
+ UserDisplayName.displayName = "UserDisplayName";
47
+ export {
48
+ UserDisplayName
49
+ };
50
+ //# sourceMappingURL=UserDisplayName.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserDisplayName.mjs","sources":["../../../src/components/UserDisplayName/UserDisplayName.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { VerifiedIcon } from \"../Icons/VerifiedIcon\";\nimport { ProfileOnlineStatus } from \"../ProfileOnlineStatus/ProfileOnlineStatus\";\n\nexport interface UserDisplayNameProps extends React.HTMLAttributes<HTMLElement> {\n /** Render an ambassador badge after the name. */\n ambassador?: boolean;\n /** Accessible label for the ambassador badge. @default \"Ambassador\" */\n ambassadorLabel?: string;\n /** HTML element used for the root wrapper. @default \"span\" */\n component?: \"span\" | \"h1\" | \"h2\" | \"h3\" | \"p\" | \"div\";\n /** Truncate the display name on a single line. @default true */\n noWrap?: boolean;\n /** Accessible label for the online-status indicator. @default \"Online\" */\n onlineLabel?: string;\n /** Render the inline online-status indicator after the name. @default false */\n showOnlineStatus?: boolean;\n /** Render a verified badge after the name (ignored when `ambassador` is set). */\n verified?: boolean;\n /** Accessible label for the verified badge. @default \"Verified\" */\n verifiedLabel?: string;\n}\n\n/**\n * Renders a user's display name with optional ambassador/verified badges and an\n * online-status indicator. Only the name shrinks and truncates; trailing badges\n * and the online-status indicator stay visible on the same line.\n *\n * Typography is not baked in: pass a `typography-*` utility via `className` on\n * the root and the name inherits it. Use `typography-body-small-14px-semibold`\n * for the standard display-name scale.\n *\n * When both `ambassador` and `verified` are set, the ambassador badge takes\n * precedence. Its tint uses `text-success-content` (not `text-icons-brand-green`)\n * so the green darkens in light mode and lightens in dark mode, matching\n * {@link ProfileOnlineStatus}; `text-icons-brand-green` is fixed across modes.\n *\n * @example\n * ```tsx\n * <UserDisplayName className=\"typography-body-small-14px-semibold\">Jane Doe</UserDisplayName>\n * ```\n */\nexport const UserDisplayName = React.forwardRef<HTMLElement, UserDisplayNameProps>(\n (\n {\n ambassador,\n ambassadorLabel = \"Ambassador\",\n children,\n className,\n component = \"span\",\n noWrap = true,\n onlineLabel = \"Online\",\n showOnlineStatus,\n verified,\n verifiedLabel = \"Verified\",\n ...props\n },\n ref,\n ) => {\n const Component = component as React.ElementType;\n\n const badge = ambassador\n ? { label: ambassadorLabel, tint: \"text-success-content\" }\n : verified\n ? { label: verifiedLabel, tint: \"text-content-primary\" }\n : null;\n\n return (\n <Component\n ref={ref}\n className={cn(\"inline-flex max-w-full items-center\", className)}\n {...props}\n >\n <span className={cn(\"min-w-0\", noWrap && \"truncate\")}>{children}</span>\n {badge && (\n <span\n role=\"img\"\n aria-label={badge.label}\n className={cn(\"ml-2 inline-flex shrink-0 items-center\", badge.tint)}\n >\n <VerifiedIcon size={16} />\n </span>\n )}\n {showOnlineStatus && <ProfileOnlineStatus label={onlineLabel} className=\"shrink-0 ml-2\" />}\n </Component>\n );\n },\n);\n\nUserDisplayName.displayName = \"UserDisplayName\";\n"],"names":[],"mappings":";;;;;;AA2CO,MAAM,kBAAkB,MAAM;AAAA,EACnC,CACE;AAAA,IACE;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,YAAY;AAElB,UAAM,QAAQ,aACV,EAAE,OAAO,iBAAiB,MAAM,uBAAA,IAChC,WACE,EAAE,OAAO,eAAe,MAAM,2BAC9B;AAEN,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,uCAAuC,SAAS;AAAA,QAC7D,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAA,oBAAC,UAAK,WAAW,GAAG,WAAW,UAAU,UAAU,GAAI,UAAS;AAAA,UAC/D,SACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY,MAAM;AAAA,cAClB,WAAW,GAAG,0CAA0C,MAAM,IAAI;AAAA,cAElE,UAAA,oBAAC,cAAA,EAAa,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,UAG3B,oBAAoB,oBAAC,qBAAA,EAAoB,OAAO,aAAa,WAAU,gBAAA,CAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAG9F;AACF;AAEA,gBAAgB,cAAc;"}
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../../utils/cn.mjs";
5
+ const HANDLE_SYMBOL = "@";
6
+ const UserHandle = React.forwardRef(
7
+ ({ children, className, ...props }, ref) => {
8
+ return /* @__PURE__ */ jsxs(
9
+ "span",
10
+ {
11
+ ref,
12
+ className: cn(
13
+ "typography-body-small-14px-regular block max-w-full truncate text-content-secondary",
14
+ className
15
+ ),
16
+ ...props,
17
+ children: [
18
+ HANDLE_SYMBOL,
19
+ children
20
+ ]
21
+ }
22
+ );
23
+ }
24
+ );
25
+ UserHandle.displayName = "UserHandle";
26
+ export {
27
+ UserHandle
28
+ };
29
+ //# sourceMappingURL=UserHandle.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserHandle.mjs","sources":["../../../src/components/UserHandle/UserHandle.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nconst HANDLE_SYMBOL = \"@\";\n\nexport interface UserHandleProps extends React.HTMLAttributes<HTMLSpanElement> {}\n\n/**\n * Renders a user handle prefixed with the `@` symbol as muted, truncated\n * secondary text.\n *\n * @example\n * ```tsx\n * <UserHandle>jane_doe</UserHandle>\n * ```\n */\nexport const UserHandle = React.forwardRef<HTMLSpanElement, UserHandleProps>(\n ({ children, className, ...props }, ref) => {\n return (\n <span\n ref={ref}\n className={cn(\n \"typography-body-small-14px-regular block max-w-full truncate text-content-secondary\",\n className,\n )}\n {...props}\n >\n {HANDLE_SYMBOL}\n {children}\n </span>\n );\n },\n);\n\nUserHandle.displayName = \"UserHandle\";\n"],"names":[],"mappings":";;;;AAGA,MAAM,gBAAgB;AAaf,MAAM,aAAa,MAAM;AAAA,EAC9B,CAAC,EAAE,UAAU,WAAW,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA;AAAA,UACA;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,WAAW,cAAc;"}
@@ -0,0 +1,57 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../../utils/cn.mjs";
5
+ import { getInitials } from "../../utils/getInitials.mjs";
6
+ import { Avatar } from "../Avatar/Avatar.mjs";
7
+ import { BellOffIcon } from "../Icons/BellOffIcon.mjs";
8
+ import { UserDisplayName } from "../UserDisplayName/UserDisplayName.mjs";
9
+ import { UserHandle } from "../UserHandle/UserHandle.mjs";
10
+ const AVATAR_SIZES = [16, 24, 32, 40, 48, 64, 88, 148];
11
+ const getNearestAvatarSize = (size) => AVATAR_SIZES.reduce(
12
+ (prev, curr) => Math.abs(curr - size) < Math.abs(prev - size) ? curr : prev
13
+ );
14
+ const UserItem = React.forwardRef(
15
+ ({
16
+ user,
17
+ avatarSize,
18
+ isOnline = false,
19
+ isMuted = false,
20
+ showOnlineStatus,
21
+ showHandle = true,
22
+ showAvatar = true,
23
+ className,
24
+ ...props
25
+ }, ref) => {
26
+ return /* @__PURE__ */ jsxs(
27
+ "div",
28
+ {
29
+ ref,
30
+ className: cn("relative flex w-full items-center justify-start px-2 py-1", className),
31
+ ...props,
32
+ children: [
33
+ isMuted && /* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 z-1 flex rounded-xs bg-surface-primary p-1", children: /* @__PURE__ */ jsx(BellOffIcon, { size: 16 }) }),
34
+ showAvatar && /* @__PURE__ */ jsx(
35
+ Avatar,
36
+ {
37
+ size: getNearestAvatarSize(avatarSize || 48),
38
+ src: user.avatarUri?.url,
39
+ alt: user.displayName,
40
+ fallback: getInitials(user.displayName),
41
+ onlineIndicator: Boolean(showOnlineStatus && isOnline)
42
+ }
43
+ ),
44
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-hidden pl-2", children: [
45
+ /* @__PURE__ */ jsx(UserDisplayName, { className: "typography-body-small-14px-semibold", children: user.nickname || user.displayName }),
46
+ showHandle && /* @__PURE__ */ jsx(UserHandle, { children: user.handle })
47
+ ] })
48
+ ]
49
+ }
50
+ );
51
+ }
52
+ );
53
+ UserItem.displayName = "UserItem";
54
+ export {
55
+ UserItem
56
+ };
57
+ //# sourceMappingURL=UserItem.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserItem.mjs","sources":["../../../src/components/UserItem/UserItem.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { getInitials } from \"../../utils/getInitials\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { BellOffIcon } from \"../Icons/BellOffIcon\";\nimport { UserDisplayName } from \"../UserDisplayName/UserDisplayName\";\nimport { UserHandle } from \"../UserHandle/UserHandle\";\n\nconst AVATAR_SIZES = [16, 24, 32, 40, 48, 64, 88, 148] as const;\ntype AvatarSizeToken = (typeof AVATAR_SIZES)[number];\n\n/** Snap an arbitrary pixel size to the nearest supported {@link Avatar} size token. */\nconst getNearestAvatarSize = (size: number): AvatarSizeToken =>\n AVATAR_SIZES.reduce((prev, curr) =>\n Math.abs(curr - size) < Math.abs(prev - size) ? curr : prev,\n );\n\n/** Minimal user shape consumed by {@link UserItem}. */\nexport type UserItemUser = {\n avatarUri?: { url: string; url2x?: string };\n displayName: string;\n handle: string;\n nickname?: string;\n};\n\nexport interface UserItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The user to display. */\n user: UserItemUser;\n /** Desired avatar size in px; snapped to the nearest supported token. @default 48 */\n avatarSize?: number;\n /** Show the muted indicator in the bottom-left corner. @default false */\n isMuted?: boolean;\n /** Whether the user is online (only shown when `showOnlineStatus` is also set). @default false */\n isOnline?: boolean;\n /** Render the avatar. @default true */\n showAvatar?: boolean;\n /** Render the handle line under the display name. @default true */\n showHandle?: boolean;\n /** Enable the avatar online indicator (combined with `isOnline`). */\n showOnlineStatus?: boolean;\n}\n\n/**\n * A compact user row showing an avatar, display name (or nickname) and handle,\n * with optional online and muted indicators.\n *\n * @example\n * ```tsx\n * <UserItem user={{ displayName: \"Jane Doe\", handle: \"jane_doe\" }} />\n * ```\n */\nexport const UserItem = React.forwardRef<HTMLDivElement, UserItemProps>(\n (\n {\n user,\n avatarSize,\n isOnline = false,\n isMuted = false,\n showOnlineStatus,\n showHandle = true,\n showAvatar = true,\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\"relative flex w-full items-center justify-start px-2 py-1\", className)}\n {...props}\n >\n {isMuted && (\n <div className=\"absolute bottom-0 left-0 z-1 flex rounded-xs bg-surface-primary p-1\">\n <BellOffIcon size={16} />\n </div>\n )}\n {showAvatar && (\n <Avatar\n size={getNearestAvatarSize(avatarSize || 48)}\n src={user.avatarUri?.url}\n alt={user.displayName}\n fallback={getInitials(user.displayName)}\n onlineIndicator={Boolean(showOnlineStatus && isOnline)}\n />\n )}\n <div className=\"flex-1 overflow-hidden pl-2\">\n <UserDisplayName className=\"typography-body-small-14px-semibold\">\n {user.nickname || user.displayName}\n </UserDisplayName>\n {showHandle && <UserHandle>{user.handle}</UserHandle>}\n </div>\n </div>\n );\n },\n);\n\nUserItem.displayName = \"UserItem\";\n"],"names":[],"mappings":";;;;;;;;;AAQA,MAAM,eAAe,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG;AAIrD,MAAM,uBAAuB,CAAC,SAC5B,aAAa;AAAA,EAAO,CAAC,MAAM,SACzB,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,IAAI,OAAO;AACzD;AAoCK,MAAM,WAAW,MAAM;AAAA,EAC5B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,IACb;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,6DAA6D,SAAS;AAAA,QACnF,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,WACC,oBAAC,SAAI,WAAU,uEACb,8BAAC,aAAA,EAAY,MAAM,IAAI,EAAA,CACzB;AAAA,UAED,cACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAM,qBAAqB,cAAc,EAAE;AAAA,cAC3C,KAAK,KAAK,WAAW;AAAA,cACrB,KAAK,KAAK;AAAA,cACV,UAAU,YAAY,KAAK,WAAW;AAAA,cACtC,iBAAiB,QAAQ,oBAAoB,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAGzD,qBAAC,OAAA,EAAI,WAAU,+BACb,UAAA;AAAA,YAAA,oBAAC,mBAAgB,WAAU,uCACxB,UAAA,KAAK,YAAY,KAAK,aACzB;AAAA,YACC,cAAc,oBAAC,YAAA,EAAY,UAAA,KAAK,OAAA,CAAO;AAAA,UAAA,EAAA,CAC1C;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,SAAS,cAAc;"}