@liveblocks/react-ui 3.18.0-rc1 → 3.18.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 (55) hide show
  1. package/dist/_private/index.cjs +3 -2
  2. package/dist/_private/index.cjs.map +1 -1
  3. package/dist/_private/index.d.cts +24 -18
  4. package/dist/_private/index.d.ts +24 -18
  5. package/dist/_private/index.js +1 -1
  6. package/dist/components/Avatar.cjs +142 -0
  7. package/dist/components/Avatar.cjs.map +1 -0
  8. package/dist/components/Avatar.js +138 -0
  9. package/dist/components/Avatar.js.map +1 -0
  10. package/dist/components/AvatarStack.cjs +58 -44
  11. package/dist/components/AvatarStack.cjs.map +1 -1
  12. package/dist/components/AvatarStack.js +58 -44
  13. package/dist/components/AvatarStack.js.map +1 -1
  14. package/dist/components/Comment.cjs +3 -3
  15. package/dist/components/Comment.cjs.map +1 -1
  16. package/dist/components/Comment.js +3 -3
  17. package/dist/components/Comment.js.map +1 -1
  18. package/dist/components/CommentPin.cjs +2 -2
  19. package/dist/components/CommentPin.cjs.map +1 -1
  20. package/dist/components/CommentPin.js +2 -2
  21. package/dist/components/CommentPin.js.map +1 -1
  22. package/dist/components/Composer.cjs +3 -3
  23. package/dist/components/Composer.cjs.map +1 -1
  24. package/dist/components/Composer.js +3 -3
  25. package/dist/components/Composer.js.map +1 -1
  26. package/dist/components/InboxNotification.cjs +2 -2
  27. package/dist/components/InboxNotification.cjs.map +1 -1
  28. package/dist/components/InboxNotification.js +2 -2
  29. package/dist/components/InboxNotification.js.map +1 -1
  30. package/dist/components/internal/User.cjs +24 -10
  31. package/dist/components/internal/User.cjs.map +1 -1
  32. package/dist/components/internal/User.js +25 -11
  33. package/dist/components/internal/User.js.map +1 -1
  34. package/dist/index.cjs +2 -0
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +33 -1
  37. package/dist/index.d.ts +33 -1
  38. package/dist/index.js +1 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/version.cjs +1 -1
  41. package/dist/version.cjs.map +1 -1
  42. package/dist/version.js +1 -1
  43. package/dist/version.js.map +1 -1
  44. package/package.json +4 -4
  45. package/src/styles/index.css +21 -0
  46. package/styles.css +1 -1
  47. package/styles.css.map +1 -1
  48. package/dist/components/internal/Avatar.cjs +0 -63
  49. package/dist/components/internal/Avatar.cjs.map +0 -1
  50. package/dist/components/internal/Avatar.js +0 -61
  51. package/dist/components/internal/Avatar.js.map +0 -1
  52. package/dist/utils/use-user-or-group-info.cjs +0 -49
  53. package/dist/utils/use-user-or-group-info.cjs.map +0 -1
  54. package/dist/utils/use-user-or-group-info.js +0 -46
  55. package/dist/utils/use-user-or-group-info.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var Avatar = require('../components/internal/Avatar.cjs');
3
+ var Avatar = require('../components/Avatar.cjs');
4
4
  var Button = require('../components/internal/Button.cjs');
5
5
  var Group = require('../components/internal/Group.cjs');
6
6
  var GroupDescription = require('../components/internal/GroupDescription.cjs');
@@ -81,7 +81,8 @@ var Warning = require('../icons/Warning.cjs');
81
81
 
82
82
 
83
83
 
84
- exports.Avatar = Avatar.Avatar;
84
+ exports.GroupAvatar = Avatar.GroupAvatar;
85
+ exports.UserAvatar = Avatar.UserAvatar;
85
86
  exports.Button = Button.Button;
86
87
  exports.SelectButton = Button.SelectButton;
87
88
  exports.Group = Group.Group;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,24 +1,30 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as _liveblocks_core from '@liveblocks/core';
3
- import { Relax, AiTextPart, AiReasoningPart, AiChatMessage } from '@liveblocks/core';
4
2
  import * as react from 'react';
5
3
  import { ComponentProps, ReactNode, ComponentPropsWithoutRef, ElementType, ComponentType, Ref, RefCallback, FormEvent } from 'react';
4
+ import * as _liveblocks_core from '@liveblocks/core';
5
+ import { Relax, AiTextPart, AiReasoningPart, AiChatMessage } from '@liveblocks/core';
6
6
  import { Tooltip as Tooltip$1 } from 'radix-ui';
7
7
 
8
- type AvatarProps = ComponentProps<"div"> & {
8
+ interface UserAvatarProps extends ComponentProps<"div"> {
9
+ userId?: string;
9
10
  icon?: ReactNode;
10
- } & Relax<{
11
- /**
12
- * The user ID to display the avatar for.
13
- */
14
- userId: string;
15
- } | {
16
- /**
17
- * The group ID to display the avatar for.
18
- */
19
- groupId: string;
20
- }>;
21
- declare function Avatar({ userId, groupId, icon, ...props }: AvatarProps): react_jsx_runtime.JSX.Element;
11
+ tooltip?: ReactNode;
12
+ variant?: "default" | "outline";
13
+ }
14
+ interface GroupAvatarProps extends ComponentProps<"div"> {
15
+ groupId?: string;
16
+ icon?: ReactNode;
17
+ tooltip?: ReactNode;
18
+ variant?: "default" | "outline";
19
+ }
20
+ /**
21
+ * @private
22
+ */
23
+ declare function UserAvatar({ userId, icon, variant, ...props }: UserAvatarProps): react_jsx_runtime.JSX.Element;
24
+ /**
25
+ * @private
26
+ */
27
+ declare function GroupAvatar({ groupId, icon, variant, ...props }: GroupAvatarProps): react_jsx_runtime.JSX.Element;
22
28
 
23
29
  interface ButtonProps extends ComponentProps<"button"> {
24
30
  variant?: "default" | "toolbar" | "outline" | "ghost" | "primary" | "secondary" | "destructive";
@@ -360,13 +366,13 @@ interface UserProps extends ComponentProps<"span"> {
360
366
  /**
361
367
  * The user ID to display the user name for.
362
368
  */
363
- userId: string;
369
+ userId?: string;
364
370
  /**
365
371
  * Whether to replace the user name with "you" ($.USER_SELF) for the current user.
366
372
  */
367
373
  replaceSelf?: boolean;
368
374
  }
369
- declare function User({ userId, replaceSelf, className, children, ...props }: UserProps): react_jsx_runtime.JSX.Element;
375
+ declare function User({ userId, ...props }: UserProps): react_jsx_runtime.JSX.Element;
370
376
 
371
377
  interface LiveblocksUiConfigContext {
372
378
  portalContainer?: HTMLElement;
@@ -738,4 +744,4 @@ declare namespace index {
738
744
  };
739
745
  }
740
746
 
741
- export { index$2 as AiComposer, AiComposerEditorProps, AiComposerFormProps, AiComposerSubmitProps, index$1 as AiMessage, AiMessageContentComponents, AiMessageContentProps, AiMessageContentReasoningPartProps, AiMessageContentTextPartProps, ArrowCornerDownRightIcon, ArrowCornerUpRightIcon, ArrowDownIcon, ArrowUpIcon, AttachmentIcon, Avatar, BellCrossedIcon, BellIcon, BlockquoteIcon, BoldIcon, Button, CheckCircleFillIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CodeIcon, index as Collapsible, CommentIcon, CopyIcon, CrossCircleFillIcon, CrossIcon, DeleteIcon, EditIcon, EllipsisIcon, EmojiIcon, EmojiPlusIcon, GlobeIcon, Group, GroupDescription, H1Icon, H2Icon, H3Icon, ItalicIcon, LengthenIcon, List, ListOrderedIcon, ListUnorderedIcon, Markdown, MarkdownComponents, MarkdownComponentsBlockquoteProps, MarkdownComponentsCodeBlockProps, MarkdownComponentsHeadingProps, MarkdownComponentsImageProps, MarkdownComponentsInlineProps, MarkdownComponentsLinkProps, MarkdownComponentsListProps, MarkdownComponentsParagraphProps, MarkdownComponentsTableProps, MarkdownProps, MentionIcon, MinusCircleIcon, PlusIcon, Portal, Prose, QuestionMarkIcon, RedoIcon, RestoreIcon, RetryIcon, SearchIcon, SelectButton, SendIcon, ShortcutTooltip, ShortenIcon, SparklesIcon, SparklesTextIcon, SpinnerIcon, StopIcon, StrikethroughIcon, TextIcon, Tooltip, TooltipProvider, TranslateIcon, UnderlineIcon, UndoIcon, User, UserIcon, UsersIcon, WarningIcon, capitalize, cn, makeCursorSpring, useAiComposer, useInitial, useLiveblocksUiConfig, useRefs, useStableComponent };
747
+ export { index$2 as AiComposer, AiComposerEditorProps, AiComposerFormProps, AiComposerSubmitProps, index$1 as AiMessage, AiMessageContentComponents, AiMessageContentProps, AiMessageContentReasoningPartProps, AiMessageContentTextPartProps, ArrowCornerDownRightIcon, ArrowCornerUpRightIcon, ArrowDownIcon, ArrowUpIcon, AttachmentIcon, BellCrossedIcon, BellIcon, BlockquoteIcon, BoldIcon, Button, CheckCircleFillIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CodeIcon, index as Collapsible, CommentIcon, CopyIcon, CrossCircleFillIcon, CrossIcon, DeleteIcon, EditIcon, EllipsisIcon, EmojiIcon, EmojiPlusIcon, GlobeIcon, Group, GroupAvatar, GroupDescription, H1Icon, H2Icon, H3Icon, ItalicIcon, LengthenIcon, List, ListOrderedIcon, ListUnorderedIcon, Markdown, MarkdownComponents, MarkdownComponentsBlockquoteProps, MarkdownComponentsCodeBlockProps, MarkdownComponentsHeadingProps, MarkdownComponentsImageProps, MarkdownComponentsInlineProps, MarkdownComponentsLinkProps, MarkdownComponentsListProps, MarkdownComponentsParagraphProps, MarkdownComponentsTableProps, MarkdownProps, MentionIcon, MinusCircleIcon, PlusIcon, Portal, Prose, QuestionMarkIcon, RedoIcon, RestoreIcon, RetryIcon, SearchIcon, SelectButton, SendIcon, ShortcutTooltip, ShortenIcon, SparklesIcon, SparklesTextIcon, SpinnerIcon, StopIcon, StrikethroughIcon, TextIcon, Tooltip, TooltipProvider, TranslateIcon, UnderlineIcon, UndoIcon, User, UserAvatar, UserIcon, UsersIcon, WarningIcon, capitalize, cn, makeCursorSpring, useAiComposer, useInitial, useLiveblocksUiConfig, useRefs, useStableComponent };
@@ -1,24 +1,30 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as _liveblocks_core from '@liveblocks/core';
3
- import { Relax, AiTextPart, AiReasoningPart, AiChatMessage } from '@liveblocks/core';
4
2
  import * as react from 'react';
5
3
  import { ComponentProps, ReactNode, ComponentPropsWithoutRef, ElementType, ComponentType, Ref, RefCallback, FormEvent } from 'react';
4
+ import * as _liveblocks_core from '@liveblocks/core';
5
+ import { Relax, AiTextPart, AiReasoningPart, AiChatMessage } from '@liveblocks/core';
6
6
  import { Tooltip as Tooltip$1 } from 'radix-ui';
7
7
 
8
- type AvatarProps = ComponentProps<"div"> & {
8
+ interface UserAvatarProps extends ComponentProps<"div"> {
9
+ userId?: string;
9
10
  icon?: ReactNode;
10
- } & Relax<{
11
- /**
12
- * The user ID to display the avatar for.
13
- */
14
- userId: string;
15
- } | {
16
- /**
17
- * The group ID to display the avatar for.
18
- */
19
- groupId: string;
20
- }>;
21
- declare function Avatar({ userId, groupId, icon, ...props }: AvatarProps): react_jsx_runtime.JSX.Element;
11
+ tooltip?: ReactNode;
12
+ variant?: "default" | "outline";
13
+ }
14
+ interface GroupAvatarProps extends ComponentProps<"div"> {
15
+ groupId?: string;
16
+ icon?: ReactNode;
17
+ tooltip?: ReactNode;
18
+ variant?: "default" | "outline";
19
+ }
20
+ /**
21
+ * @private
22
+ */
23
+ declare function UserAvatar({ userId, icon, variant, ...props }: UserAvatarProps): react_jsx_runtime.JSX.Element;
24
+ /**
25
+ * @private
26
+ */
27
+ declare function GroupAvatar({ groupId, icon, variant, ...props }: GroupAvatarProps): react_jsx_runtime.JSX.Element;
22
28
 
23
29
  interface ButtonProps extends ComponentProps<"button"> {
24
30
  variant?: "default" | "toolbar" | "outline" | "ghost" | "primary" | "secondary" | "destructive";
@@ -360,13 +366,13 @@ interface UserProps extends ComponentProps<"span"> {
360
366
  /**
361
367
  * The user ID to display the user name for.
362
368
  */
363
- userId: string;
369
+ userId?: string;
364
370
  /**
365
371
  * Whether to replace the user name with "you" ($.USER_SELF) for the current user.
366
372
  */
367
373
  replaceSelf?: boolean;
368
374
  }
369
- declare function User({ userId, replaceSelf, className, children, ...props }: UserProps): react_jsx_runtime.JSX.Element;
375
+ declare function User({ userId, ...props }: UserProps): react_jsx_runtime.JSX.Element;
370
376
 
371
377
  interface LiveblocksUiConfigContext {
372
378
  portalContainer?: HTMLElement;
@@ -738,4 +744,4 @@ declare namespace index {
738
744
  };
739
745
  }
740
746
 
741
- export { index$2 as AiComposer, AiComposerEditorProps, AiComposerFormProps, AiComposerSubmitProps, index$1 as AiMessage, AiMessageContentComponents, AiMessageContentProps, AiMessageContentReasoningPartProps, AiMessageContentTextPartProps, ArrowCornerDownRightIcon, ArrowCornerUpRightIcon, ArrowDownIcon, ArrowUpIcon, AttachmentIcon, Avatar, BellCrossedIcon, BellIcon, BlockquoteIcon, BoldIcon, Button, CheckCircleFillIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CodeIcon, index as Collapsible, CommentIcon, CopyIcon, CrossCircleFillIcon, CrossIcon, DeleteIcon, EditIcon, EllipsisIcon, EmojiIcon, EmojiPlusIcon, GlobeIcon, Group, GroupDescription, H1Icon, H2Icon, H3Icon, ItalicIcon, LengthenIcon, List, ListOrderedIcon, ListUnorderedIcon, Markdown, MarkdownComponents, MarkdownComponentsBlockquoteProps, MarkdownComponentsCodeBlockProps, MarkdownComponentsHeadingProps, MarkdownComponentsImageProps, MarkdownComponentsInlineProps, MarkdownComponentsLinkProps, MarkdownComponentsListProps, MarkdownComponentsParagraphProps, MarkdownComponentsTableProps, MarkdownProps, MentionIcon, MinusCircleIcon, PlusIcon, Portal, Prose, QuestionMarkIcon, RedoIcon, RestoreIcon, RetryIcon, SearchIcon, SelectButton, SendIcon, ShortcutTooltip, ShortenIcon, SparklesIcon, SparklesTextIcon, SpinnerIcon, StopIcon, StrikethroughIcon, TextIcon, Tooltip, TooltipProvider, TranslateIcon, UnderlineIcon, UndoIcon, User, UserIcon, UsersIcon, WarningIcon, capitalize, cn, makeCursorSpring, useAiComposer, useInitial, useLiveblocksUiConfig, useRefs, useStableComponent };
747
+ export { index$2 as AiComposer, AiComposerEditorProps, AiComposerFormProps, AiComposerSubmitProps, index$1 as AiMessage, AiMessageContentComponents, AiMessageContentProps, AiMessageContentReasoningPartProps, AiMessageContentTextPartProps, ArrowCornerDownRightIcon, ArrowCornerUpRightIcon, ArrowDownIcon, ArrowUpIcon, AttachmentIcon, BellCrossedIcon, BellIcon, BlockquoteIcon, BoldIcon, Button, CheckCircleFillIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CodeIcon, index as Collapsible, CommentIcon, CopyIcon, CrossCircleFillIcon, CrossIcon, DeleteIcon, EditIcon, EllipsisIcon, EmojiIcon, EmojiPlusIcon, GlobeIcon, Group, GroupAvatar, GroupDescription, H1Icon, H2Icon, H3Icon, ItalicIcon, LengthenIcon, List, ListOrderedIcon, ListUnorderedIcon, Markdown, MarkdownComponents, MarkdownComponentsBlockquoteProps, MarkdownComponentsCodeBlockProps, MarkdownComponentsHeadingProps, MarkdownComponentsImageProps, MarkdownComponentsInlineProps, MarkdownComponentsLinkProps, MarkdownComponentsListProps, MarkdownComponentsParagraphProps, MarkdownComponentsTableProps, MarkdownProps, MentionIcon, MinusCircleIcon, PlusIcon, Portal, Prose, QuestionMarkIcon, RedoIcon, RestoreIcon, RetryIcon, SearchIcon, SelectButton, SendIcon, ShortcutTooltip, ShortenIcon, SparklesIcon, SparklesTextIcon, SpinnerIcon, StopIcon, StrikethroughIcon, TextIcon, Tooltip, TooltipProvider, TranslateIcon, UnderlineIcon, UndoIcon, User, UserAvatar, UserIcon, UsersIcon, WarningIcon, capitalize, cn, makeCursorSpring, useAiComposer, useInitial, useLiveblocksUiConfig, useRefs, useStableComponent };
@@ -1,4 +1,4 @@
1
- export { Avatar } from '../components/internal/Avatar.js';
1
+ export { GroupAvatar, UserAvatar } from '../components/Avatar.js';
2
2
  export { Button, SelectButton } from '../components/internal/Button.js';
3
3
  export { Group } from '../components/internal/Group.js';
4
4
  export { GroupDescription } from '../components/internal/GroupDescription.js';
@@ -0,0 +1,142 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var react$1 = require('@liveblocks/react');
6
+ var react = require('react');
7
+ var constants = require('../constants.cjs');
8
+ var overrides = require('../overrides.cjs');
9
+ var cn = require('../utils/cn.cjs');
10
+ var getInitials = require('../utils/get-initials.cjs');
11
+ var px = require('../utils/px.cjs');
12
+ var Tooltip = require('./internal/Tooltip.cjs');
13
+
14
+
15
+ function Avatar({
16
+ src,
17
+ name,
18
+ className,
19
+ children,
20
+ tooltip,
21
+ outline,
22
+ style,
23
+ ...props
24
+ }) {
25
+ const initials = react.useMemo(
26
+ () => name ? getInitials.getInitials(name) : void 0,
27
+ [name]
28
+ );
29
+ const resolvedOutline = typeof outline === "object" ? outline : typeof outline === "string" ? { color: outline } : outline === true ? {} : void 0;
30
+ const avatar = /* @__PURE__ */ jsxRuntime.jsx(
31
+ "div",
32
+ {
33
+ className: cn.cn("lb-avatar", className),
34
+ "data-variant": resolvedOutline ? "outline" : "default",
35
+ style: {
36
+ "--lb-avatar-outline-color": resolvedOutline?.color,
37
+ "--lb-avatar-outline-width": px.px(resolvedOutline?.width),
38
+ "--lb-avatar-outline-gap": px.px(resolvedOutline?.gap),
39
+ ...style
40
+ },
41
+ ...props,
42
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lb-avatar-content", children: children ?? (src ? /* @__PURE__ */ jsxRuntime.jsx("img", { className: "lb-avatar-image", src, alt: name }) : initials ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lb-avatar-fallback", "aria-label": name, title: name, children: initials }) : null) })
43
+ }
44
+ );
45
+ return tooltip ? /* @__PURE__ */ jsxRuntime.jsx(Tooltip.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
46
+ Tooltip.Tooltip,
47
+ {
48
+ content: tooltip,
49
+ sideOffset: constants.FLOATING_ELEMENT_SIDE_OFFSET,
50
+ collisionPadding: constants.FLOATING_ELEMENT_COLLISION_PADDING,
51
+ side: "top",
52
+ align: "center",
53
+ children: avatar
54
+ }
55
+ ) }) : avatar;
56
+ }
57
+ function ResolvedUserAvatar({
58
+ userId,
59
+ icon,
60
+ variant = "default",
61
+ tooltip,
62
+ ...props
63
+ }) {
64
+ const { user, isLoading } = react$1.useUser(userId);
65
+ return /* @__PURE__ */ jsxRuntime.jsx(
66
+ Avatar,
67
+ {
68
+ src: user?.avatar,
69
+ name: isLoading ? void 0 : user?.name ?? userId,
70
+ outline: variant === "outline" ? typeof user?.color === "string" ? user.color : void 0 : void 0,
71
+ "data-loading": isLoading ? "" : void 0,
72
+ tooltip,
73
+ ...props,
74
+ children: icon && (isLoading || !user?.avatar) ? icon : null
75
+ }
76
+ );
77
+ }
78
+ function ResolvedGroupAvatar({
79
+ groupId,
80
+ icon,
81
+ variant = "default",
82
+ tooltip,
83
+ ...props
84
+ }) {
85
+ const { info, isLoading } = react$1.useGroupInfo(groupId);
86
+ return /* @__PURE__ */ jsxRuntime.jsx(
87
+ Avatar,
88
+ {
89
+ src: info?.avatar,
90
+ name: isLoading ? void 0 : info?.name ?? groupId,
91
+ outline: variant === "outline" ? typeof info?.color === "string" ? info.color : void 0 : void 0,
92
+ "data-loading": isLoading ? "" : void 0,
93
+ tooltip,
94
+ ...props,
95
+ children: icon && (isLoading || !info?.avatar) ? icon : null
96
+ }
97
+ );
98
+ }
99
+ function UserAvatar({
100
+ userId,
101
+ icon,
102
+ variant = "default",
103
+ ...props
104
+ }) {
105
+ const $ = overrides.useOverrides();
106
+ if (!userId) {
107
+ return /* @__PURE__ */ jsxRuntime.jsx(Avatar, { name: $.USER_UNKNOWN, outline: variant === "outline", ...props, children: icon });
108
+ }
109
+ return /* @__PURE__ */ jsxRuntime.jsx(
110
+ ResolvedUserAvatar,
111
+ {
112
+ userId,
113
+ icon,
114
+ variant,
115
+ ...props
116
+ }
117
+ );
118
+ }
119
+ function GroupAvatar({
120
+ groupId,
121
+ icon,
122
+ variant = "default",
123
+ ...props
124
+ }) {
125
+ if (!groupId) {
126
+ return /* @__PURE__ */ jsxRuntime.jsx(Avatar, { outline: variant === "outline", ...props, children: icon });
127
+ }
128
+ return /* @__PURE__ */ jsxRuntime.jsx(
129
+ ResolvedGroupAvatar,
130
+ {
131
+ groupId,
132
+ icon,
133
+ variant,
134
+ ...props
135
+ }
136
+ );
137
+ }
138
+
139
+ exports.Avatar = Avatar;
140
+ exports.GroupAvatar = GroupAvatar;
141
+ exports.UserAvatar = UserAvatar;
142
+ //# sourceMappingURL=Avatar.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.cjs","sources":["../../src/components/Avatar.tsx"],"sourcesContent":["\"use client\";\n\nimport { useGroupInfo, useUser } from \"@liveblocks/react\";\nimport {\n type ComponentProps,\n type CSSProperties,\n type ReactNode,\n useMemo,\n} from \"react\";\n\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { getInitials } from \"../utils/get-initials\";\nimport { px } from \"../utils/px\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\n\nexport interface AvatarProps extends ComponentProps<\"div\"> {\n /**\n * The URL of the avatar's image.\n */\n src?: string;\n\n /**\n * The name of the avatar.\n */\n name?: string;\n\n /**\n * The content to display in the avatar's tooltip.\n */\n tooltip?: ReactNode;\n\n /**\n * Whether and how the avatar should have an outline.\n */\n outline?:\n | string\n | boolean\n | { color?: string; width?: string | number; gap?: string | number };\n\n /**\n * Override the avatar's content.\n */\n children?: ReactNode;\n}\n\nexport interface UserAvatarProps extends ComponentProps<\"div\"> {\n userId?: string;\n icon?: ReactNode;\n tooltip?: ReactNode;\n variant?: \"default\" | \"outline\";\n}\n\nexport interface GroupAvatarProps extends ComponentProps<\"div\"> {\n groupId?: string;\n icon?: ReactNode;\n tooltip?: ReactNode;\n variant?: \"default\" | \"outline\";\n}\n\ntype MakeRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;\n\nexport function Avatar({\n src,\n name,\n className,\n children,\n tooltip,\n outline,\n style,\n ...props\n}: AvatarProps) {\n const initials = useMemo(\n () => (name ? getInitials(name) : undefined),\n [name]\n );\n const resolvedOutline =\n typeof outline === \"object\"\n ? outline\n : typeof outline === \"string\"\n ? { color: outline }\n : outline === true\n ? {}\n : undefined;\n\n const avatar = (\n <div\n className={cn(\"lb-avatar\", className)}\n data-variant={resolvedOutline ? \"outline\" : \"default\"}\n style={\n {\n \"--lb-avatar-outline-color\": resolvedOutline?.color,\n \"--lb-avatar-outline-width\": px(resolvedOutline?.width),\n \"--lb-avatar-outline-gap\": px(resolvedOutline?.gap),\n ...style,\n } as CSSProperties\n }\n {...props}\n >\n <div className=\"lb-avatar-content\">\n {children ??\n (src ? (\n <img className=\"lb-avatar-image\" src={src} alt={name} />\n ) : initials ? (\n <span className=\"lb-avatar-fallback\" aria-label={name} title={name}>\n {initials}\n </span>\n ) : null)}\n </div>\n </div>\n );\n\n return tooltip ? (\n <TooltipProvider>\n <Tooltip\n content={tooltip}\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n >\n {avatar}\n </Tooltip>\n </TooltipProvider>\n ) : (\n avatar\n );\n}\n\nfunction ResolvedUserAvatar({\n userId,\n icon,\n variant = \"default\",\n tooltip,\n ...props\n}: MakeRequired<UserAvatarProps, \"userId\">) {\n const { user, isLoading } = useUser(userId);\n\n return (\n <Avatar\n src={user?.avatar}\n name={isLoading ? undefined : (user?.name ?? userId)}\n outline={\n variant === \"outline\"\n ? typeof user?.color === \"string\"\n ? user.color\n : undefined\n : undefined\n }\n data-loading={isLoading ? \"\" : undefined}\n tooltip={tooltip}\n {...props}\n >\n {icon && (isLoading || !user?.avatar) ? icon : null}\n </Avatar>\n );\n}\n\nfunction ResolvedGroupAvatar({\n groupId,\n icon,\n variant = \"default\",\n tooltip,\n ...props\n}: MakeRequired<GroupAvatarProps, \"groupId\">) {\n const { info, isLoading } = useGroupInfo(groupId);\n\n return (\n <Avatar\n src={info?.avatar}\n name={isLoading ? undefined : (info?.name ?? groupId)}\n outline={\n variant === \"outline\"\n ? typeof info?.color === \"string\"\n ? info.color\n : undefined\n : undefined\n }\n data-loading={isLoading ? \"\" : undefined}\n tooltip={tooltip}\n {...props}\n >\n {icon && (isLoading || !info?.avatar) ? icon : null}\n </Avatar>\n );\n}\n\n/**\n * @private\n */\nexport function UserAvatar({\n userId,\n icon,\n variant = \"default\",\n ...props\n}: UserAvatarProps) {\n const $ = useOverrides();\n\n if (!userId) {\n return (\n <Avatar name={$.USER_UNKNOWN} outline={variant === \"outline\"} {...props}>\n {icon}\n </Avatar>\n );\n }\n\n return (\n <ResolvedUserAvatar\n userId={userId}\n icon={icon}\n variant={variant}\n {...props}\n />\n );\n}\n\n/**\n * @private\n */\nexport function GroupAvatar({\n groupId,\n icon,\n variant = \"default\",\n ...props\n}: GroupAvatarProps) {\n if (!groupId) {\n return (\n <Avatar outline={variant === \"outline\"} {...props}>\n {icon}\n </Avatar>\n );\n }\n\n return (\n <ResolvedGroupAvatar\n groupId={groupId}\n icon={icon}\n variant={variant}\n {...props}\n />\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAkEO;AAAgB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AAEF;AACE;AAAiB;AACmB;AAC7B;AAEP;AASA;AACE;AAAC;AAAA;AACqC;AACQ;AAE1C;AACgD;AACQ;AACJ;AAC/C;AACL;AAEE;AAWJ;AAAA;AAIJ;AAEI;AAAC;AAAA;AACU;AACG;AACM;AACb;AACC;AAEL;AAAA;AAMT;AAEA;AAA4B;AAC1B;AACA;AACU;AACV;AAEF;AACE;AAEA;AACE;AAAC;AAAA;AACY;AACkC;AAMvC;AAEyB;AAC/B;AACI;AAE2C;AAAA;AAGrD;AAEA;AAA6B;AAC3B;AACA;AACU;AACV;AAEF;AACE;AAEA;AACE;AAAC;AAAA;AACY;AACkC;AAMvC;AAEyB;AAC/B;AACI;AAE2C;AAAA;AAGrD;AAKO;AAAoB;AACzB;AACA;AACU;AAEZ;AACE;AAEA;AACE;AAGE;AAIJ;AACE;AAAC;AAAA;AACC;AACA;AACA;AACI;AAAA;AAGV;AAKO;AAAqB;AAC1B;AACA;AACU;AAEZ;AACE;AACE;AAGE;AAIJ;AACE;AAAC;AAAA;AACC;AACA;AACA;AACI;AAAA;AAGV;;;;"}
@@ -0,0 +1,138 @@
1
+ "use client";
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { useUser, useGroupInfo } from '@liveblocks/react';
4
+ import { useMemo } from 'react';
5
+ import { FLOATING_ELEMENT_SIDE_OFFSET, FLOATING_ELEMENT_COLLISION_PADDING } from '../constants.js';
6
+ import { useOverrides } from '../overrides.js';
7
+ import { cn } from '../utils/cn.js';
8
+ import { getInitials } from '../utils/get-initials.js';
9
+ import { px } from '../utils/px.js';
10
+ import { TooltipProvider, Tooltip } from './internal/Tooltip.js';
11
+
12
+
13
+ function Avatar({
14
+ src,
15
+ name,
16
+ className,
17
+ children,
18
+ tooltip,
19
+ outline,
20
+ style,
21
+ ...props
22
+ }) {
23
+ const initials = useMemo(
24
+ () => name ? getInitials(name) : void 0,
25
+ [name]
26
+ );
27
+ const resolvedOutline = typeof outline === "object" ? outline : typeof outline === "string" ? { color: outline } : outline === true ? {} : void 0;
28
+ const avatar = /* @__PURE__ */ jsx(
29
+ "div",
30
+ {
31
+ className: cn("lb-avatar", className),
32
+ "data-variant": resolvedOutline ? "outline" : "default",
33
+ style: {
34
+ "--lb-avatar-outline-color": resolvedOutline?.color,
35
+ "--lb-avatar-outline-width": px(resolvedOutline?.width),
36
+ "--lb-avatar-outline-gap": px(resolvedOutline?.gap),
37
+ ...style
38
+ },
39
+ ...props,
40
+ children: /* @__PURE__ */ jsx("div", { className: "lb-avatar-content", children: children ?? (src ? /* @__PURE__ */ jsx("img", { className: "lb-avatar-image", src, alt: name }) : initials ? /* @__PURE__ */ jsx("span", { className: "lb-avatar-fallback", "aria-label": name, title: name, children: initials }) : null) })
41
+ }
42
+ );
43
+ return tooltip ? /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(
44
+ Tooltip,
45
+ {
46
+ content: tooltip,
47
+ sideOffset: FLOATING_ELEMENT_SIDE_OFFSET,
48
+ collisionPadding: FLOATING_ELEMENT_COLLISION_PADDING,
49
+ side: "top",
50
+ align: "center",
51
+ children: avatar
52
+ }
53
+ ) }) : avatar;
54
+ }
55
+ function ResolvedUserAvatar({
56
+ userId,
57
+ icon,
58
+ variant = "default",
59
+ tooltip,
60
+ ...props
61
+ }) {
62
+ const { user, isLoading } = useUser(userId);
63
+ return /* @__PURE__ */ jsx(
64
+ Avatar,
65
+ {
66
+ src: user?.avatar,
67
+ name: isLoading ? void 0 : user?.name ?? userId,
68
+ outline: variant === "outline" ? typeof user?.color === "string" ? user.color : void 0 : void 0,
69
+ "data-loading": isLoading ? "" : void 0,
70
+ tooltip,
71
+ ...props,
72
+ children: icon && (isLoading || !user?.avatar) ? icon : null
73
+ }
74
+ );
75
+ }
76
+ function ResolvedGroupAvatar({
77
+ groupId,
78
+ icon,
79
+ variant = "default",
80
+ tooltip,
81
+ ...props
82
+ }) {
83
+ const { info, isLoading } = useGroupInfo(groupId);
84
+ return /* @__PURE__ */ jsx(
85
+ Avatar,
86
+ {
87
+ src: info?.avatar,
88
+ name: isLoading ? void 0 : info?.name ?? groupId,
89
+ outline: variant === "outline" ? typeof info?.color === "string" ? info.color : void 0 : void 0,
90
+ "data-loading": isLoading ? "" : void 0,
91
+ tooltip,
92
+ ...props,
93
+ children: icon && (isLoading || !info?.avatar) ? icon : null
94
+ }
95
+ );
96
+ }
97
+ function UserAvatar({
98
+ userId,
99
+ icon,
100
+ variant = "default",
101
+ ...props
102
+ }) {
103
+ const $ = useOverrides();
104
+ if (!userId) {
105
+ return /* @__PURE__ */ jsx(Avatar, { name: $.USER_UNKNOWN, outline: variant === "outline", ...props, children: icon });
106
+ }
107
+ return /* @__PURE__ */ jsx(
108
+ ResolvedUserAvatar,
109
+ {
110
+ userId,
111
+ icon,
112
+ variant,
113
+ ...props
114
+ }
115
+ );
116
+ }
117
+ function GroupAvatar({
118
+ groupId,
119
+ icon,
120
+ variant = "default",
121
+ ...props
122
+ }) {
123
+ if (!groupId) {
124
+ return /* @__PURE__ */ jsx(Avatar, { outline: variant === "outline", ...props, children: icon });
125
+ }
126
+ return /* @__PURE__ */ jsx(
127
+ ResolvedGroupAvatar,
128
+ {
129
+ groupId,
130
+ icon,
131
+ variant,
132
+ ...props
133
+ }
134
+ );
135
+ }
136
+
137
+ export { Avatar, GroupAvatar, UserAvatar };
138
+ //# sourceMappingURL=Avatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.js","sources":["../../src/components/Avatar.tsx"],"sourcesContent":["\"use client\";\n\nimport { useGroupInfo, useUser } from \"@liveblocks/react\";\nimport {\n type ComponentProps,\n type CSSProperties,\n type ReactNode,\n useMemo,\n} from \"react\";\n\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { getInitials } from \"../utils/get-initials\";\nimport { px } from \"../utils/px\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\n\nexport interface AvatarProps extends ComponentProps<\"div\"> {\n /**\n * The URL of the avatar's image.\n */\n src?: string;\n\n /**\n * The name of the avatar.\n */\n name?: string;\n\n /**\n * The content to display in the avatar's tooltip.\n */\n tooltip?: ReactNode;\n\n /**\n * Whether and how the avatar should have an outline.\n */\n outline?:\n | string\n | boolean\n | { color?: string; width?: string | number; gap?: string | number };\n\n /**\n * Override the avatar's content.\n */\n children?: ReactNode;\n}\n\nexport interface UserAvatarProps extends ComponentProps<\"div\"> {\n userId?: string;\n icon?: ReactNode;\n tooltip?: ReactNode;\n variant?: \"default\" | \"outline\";\n}\n\nexport interface GroupAvatarProps extends ComponentProps<\"div\"> {\n groupId?: string;\n icon?: ReactNode;\n tooltip?: ReactNode;\n variant?: \"default\" | \"outline\";\n}\n\ntype MakeRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;\n\nexport function Avatar({\n src,\n name,\n className,\n children,\n tooltip,\n outline,\n style,\n ...props\n}: AvatarProps) {\n const initials = useMemo(\n () => (name ? getInitials(name) : undefined),\n [name]\n );\n const resolvedOutline =\n typeof outline === \"object\"\n ? outline\n : typeof outline === \"string\"\n ? { color: outline }\n : outline === true\n ? {}\n : undefined;\n\n const avatar = (\n <div\n className={cn(\"lb-avatar\", className)}\n data-variant={resolvedOutline ? \"outline\" : \"default\"}\n style={\n {\n \"--lb-avatar-outline-color\": resolvedOutline?.color,\n \"--lb-avatar-outline-width\": px(resolvedOutline?.width),\n \"--lb-avatar-outline-gap\": px(resolvedOutline?.gap),\n ...style,\n } as CSSProperties\n }\n {...props}\n >\n <div className=\"lb-avatar-content\">\n {children ??\n (src ? (\n <img className=\"lb-avatar-image\" src={src} alt={name} />\n ) : initials ? (\n <span className=\"lb-avatar-fallback\" aria-label={name} title={name}>\n {initials}\n </span>\n ) : null)}\n </div>\n </div>\n );\n\n return tooltip ? (\n <TooltipProvider>\n <Tooltip\n content={tooltip}\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n >\n {avatar}\n </Tooltip>\n </TooltipProvider>\n ) : (\n avatar\n );\n}\n\nfunction ResolvedUserAvatar({\n userId,\n icon,\n variant = \"default\",\n tooltip,\n ...props\n}: MakeRequired<UserAvatarProps, \"userId\">) {\n const { user, isLoading } = useUser(userId);\n\n return (\n <Avatar\n src={user?.avatar}\n name={isLoading ? undefined : (user?.name ?? userId)}\n outline={\n variant === \"outline\"\n ? typeof user?.color === \"string\"\n ? user.color\n : undefined\n : undefined\n }\n data-loading={isLoading ? \"\" : undefined}\n tooltip={tooltip}\n {...props}\n >\n {icon && (isLoading || !user?.avatar) ? icon : null}\n </Avatar>\n );\n}\n\nfunction ResolvedGroupAvatar({\n groupId,\n icon,\n variant = \"default\",\n tooltip,\n ...props\n}: MakeRequired<GroupAvatarProps, \"groupId\">) {\n const { info, isLoading } = useGroupInfo(groupId);\n\n return (\n <Avatar\n src={info?.avatar}\n name={isLoading ? undefined : (info?.name ?? groupId)}\n outline={\n variant === \"outline\"\n ? typeof info?.color === \"string\"\n ? info.color\n : undefined\n : undefined\n }\n data-loading={isLoading ? \"\" : undefined}\n tooltip={tooltip}\n {...props}\n >\n {icon && (isLoading || !info?.avatar) ? icon : null}\n </Avatar>\n );\n}\n\n/**\n * @private\n */\nexport function UserAvatar({\n userId,\n icon,\n variant = \"default\",\n ...props\n}: UserAvatarProps) {\n const $ = useOverrides();\n\n if (!userId) {\n return (\n <Avatar name={$.USER_UNKNOWN} outline={variant === \"outline\"} {...props}>\n {icon}\n </Avatar>\n );\n }\n\n return (\n <ResolvedUserAvatar\n userId={userId}\n icon={icon}\n variant={variant}\n {...props}\n />\n );\n}\n\n/**\n * @private\n */\nexport function GroupAvatar({\n groupId,\n icon,\n variant = \"default\",\n ...props\n}: GroupAvatarProps) {\n if (!groupId) {\n return (\n <Avatar outline={variant === \"outline\"} {...props}>\n {icon}\n </Avatar>\n );\n }\n\n return (\n <ResolvedGroupAvatar\n groupId={groupId}\n icon={icon}\n variant={variant}\n {...props}\n />\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAkEO;AAAgB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AAEF;AACE;AAAiB;AACmB;AAC7B;AAEP;AASA;AACE;AAAC;AAAA;AACqC;AACQ;AAE1C;AACgD;AACQ;AACJ;AAC/C;AACL;AAEE;AAWJ;AAAA;AAIJ;AAEI;AAAC;AAAA;AACU;AACG;AACM;AACb;AACC;AAEL;AAAA;AAMT;AAEA;AAA4B;AAC1B;AACA;AACU;AACV;AAEF;AACE;AAEA;AACE;AAAC;AAAA;AACY;AACkC;AAMvC;AAEyB;AAC/B;AACI;AAE2C;AAAA;AAGrD;AAEA;AAA6B;AAC3B;AACA;AACU;AACV;AAEF;AACE;AAEA;AACE;AAAC;AAAA;AACY;AACkC;AAMvC;AAEyB;AAC/B;AACI;AAE2C;AAAA;AAGrD;AAKO;AAAoB;AACzB;AACA;AACU;AAEZ;AACE;AAEA;AACE;AAGE;AAIJ;AACE;AAAC;AAAA;AACC;AACA;AACA;AACI;AAAA;AAGV;AAKO;AAAqB;AAC1B;AACA;AACU;AAEZ;AACE;AACE;AAGE;AAIJ;AACE;AAAC;AAAA;AACC;AACA;AACA;AACI;AAAA;AAGV;;"}
@@ -8,7 +8,7 @@ var constants = require('../constants.cjs');
8
8
  var overrides = require('../overrides.cjs');
9
9
  var cn = require('../utils/cn.cjs');
10
10
  var px = require('../utils/px.cjs');
11
- var Avatar = require('./internal/Avatar.cjs');
11
+ var Avatar = require('./Avatar.cjs');
12
12
  var Tooltip = require('./internal/Tooltip.cjs');
13
13
  var User = require('./internal/User.cjs');
14
14
 
@@ -19,32 +19,59 @@ const AvatarStack = react.forwardRef(
19
19
  max = 3,
20
20
  size,
21
21
  gap,
22
+ variant = "default",
22
23
  overrides: overrides$1,
23
24
  className,
24
25
  style,
25
26
  ...props
26
27
  }, forwardedRef) => {
27
28
  const $ = overrides.useOverrides(overrides$1);
28
- const otherIds = react$1.useOthers(
29
- (others) => [...others].sort((a, b) => b.connectionId - a.connectionId).map((user) => user.id)
29
+ const otherUsers = react$1.useOthers(
30
+ (others) => [...others].sort((a, b) => b.connectionId - a.connectionId).map((user) => ({
31
+ connectionId: user.connectionId,
32
+ userId: user.id
33
+ }))
30
34
  );
31
- const selfId = react$1.useSelf((self) => self.id);
32
- const userIds = react.useMemo(() => {
33
- const uniqueUserIds = new Set(
34
- [selfId, ...otherIds, ...additionalUserIds].filter(
35
- (userId) => userId !== null && userId !== void 0
36
- )
37
- );
38
- return [...uniqueUserIds];
39
- }, [selfId, otherIds, additionalUserIds]);
35
+ const selfUser = react$1.useSelf((self) => ({
36
+ connectionId: self.connectionId,
37
+ userId: self.id
38
+ }));
39
+ const users = react.useMemo(() => {
40
+ const uniqueUsers = /* @__PURE__ */ new Map();
41
+ const addUser = ({
42
+ connectionId,
43
+ userId
44
+ }) => {
45
+ if (userId !== null && userId !== void 0) {
46
+ const key = `user:${userId}`;
47
+ uniqueUsers.set(key, { key, userId });
48
+ } else {
49
+ const key = `connection:${connectionId}`;
50
+ uniqueUsers.set(key, { key, userId: null });
51
+ }
52
+ };
53
+ if (selfUser) {
54
+ addUser(selfUser);
55
+ }
56
+ for (const otherUser of otherUsers) {
57
+ addUser(otherUser);
58
+ }
59
+ for (const additionalUserId of additionalUserIds) {
60
+ if (additionalUserId !== null && additionalUserId !== void 0) {
61
+ const key = `user:${additionalUserId}`;
62
+ uniqueUsers.set(key, { key, userId: additionalUserId });
63
+ }
64
+ }
65
+ return [...uniqueUsers.values()];
66
+ }, [selfUser, otherUsers, additionalUserIds]);
40
67
  const maxItems = max === null ? Infinity : Math.max(2, Math.floor(max));
41
- const shouldShowMore = userIds.length > maxItems;
68
+ const shouldShowMore = users.length > maxItems;
42
69
  const visibleAvatarsCount = shouldShowMore ? maxItems - 1 : maxItems;
43
- const visibleUserIds = userIds.slice(0, visibleAvatarsCount);
44
- const hiddenUserIds = userIds.slice(visibleUserIds.length);
45
- const remainingUsersCount = hiddenUserIds.length;
46
- const visibleItemsCount = visibleUserIds.length + Number(remainingUsersCount > 0);
47
- if (userIds.length === 0) {
70
+ const visibleUsers = users.slice(0, visibleAvatarsCount);
71
+ const hiddenUsers = users.slice(visibleUsers.length);
72
+ const remainingUsersCount = hiddenUsers.length;
73
+ const visibleItemsCount = visibleUsers.length + Number(remainingUsersCount > 0);
74
+ if (users.length === 0) {
48
75
  return null;
49
76
  }
50
77
  return /* @__PURE__ */ jsxRuntime.jsx(Tooltip.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(
@@ -61,39 +88,26 @@ const AvatarStack = react.forwardRef(
61
88
  ...props,
62
89
  ref: forwardedRef,
63
90
  children: [
64
- visibleUserIds.map((userId, index) => {
65
- if (!userId) {
66
- return null;
67
- }
91
+ visibleUsers.map((user, index) => {
68
92
  return /* @__PURE__ */ jsxRuntime.jsx(
69
- Tooltip.Tooltip,
93
+ Avatar.UserAvatar,
70
94
  {
71
- content: /* @__PURE__ */ jsxRuntime.jsx(User.User, { userId }),
72
- sideOffset: constants.FLOATING_ELEMENT_SIDE_OFFSET,
73
- collisionPadding: constants.FLOATING_ELEMENT_COLLISION_PADDING,
74
- side: "top",
75
- align: "center",
76
- children: /* @__PURE__ */ jsxRuntime.jsx(
77
- Avatar.Avatar,
78
- {
79
- userId,
80
- className: "lb-avatar-stack-avatar",
81
- style: { "--lb-avatar-stack-index": index }
82
- }
83
- )
95
+ userId: user.userId ?? void 0,
96
+ variant,
97
+ className: "lb-avatar-stack-avatar",
98
+ style: { "--lb-avatar-stack-index": index },
99
+ tooltip: /* @__PURE__ */ jsxRuntime.jsx(User.User, { userId: user.userId ?? void 0 })
84
100
  },
85
- userId
101
+ user.key
86
102
  );
87
103
  }),
88
104
  remainingUsersCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
89
105
  Tooltip.Tooltip,
90
106
  {
91
- content: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "lb-users-tooltip-list", children: hiddenUserIds.map(
92
- (userId) => userId ? /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "lb-users-tooltip-list-item", children: [
93
- /* @__PURE__ */ jsxRuntime.jsx(Avatar.Avatar, { userId }),
94
- /* @__PURE__ */ jsxRuntime.jsx(User.User, { userId })
95
- ] }, userId) : null
96
- ) }),
107
+ content: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "lb-users-tooltip-list", children: hiddenUsers.map((user) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "lb-users-tooltip-list-item", children: [
108
+ /* @__PURE__ */ jsxRuntime.jsx(Avatar.UserAvatar, { userId: user.userId ?? void 0 }),
109
+ /* @__PURE__ */ jsxRuntime.jsx(User.User, { userId: user.userId ?? void 0 })
110
+ ] }, user.key)) }),
97
111
  sideOffset: constants.FLOATING_ELEMENT_SIDE_OFFSET,
98
112
  collisionPadding: constants.FLOATING_ELEMENT_COLLISION_PADDING,
99
113
  side: "top",
@@ -104,7 +118,7 @@ const AvatarStack = react.forwardRef(
104
118
  {
105
119
  className: "lb-avatar lb-avatar-stack-avatar lb-avatar-stack-more",
106
120
  style: {
107
- "--lb-avatar-stack-index": visibleUserIds.length
121
+ "--lb-avatar-stack-index": visibleUsers.length
108
122
  },
109
123
  children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "lb-avatar-fallback", children: [
110
124
  "+",