@liveblocks/react-ui 3.15.0 → 3.15.1-rc1

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 (60) hide show
  1. package/dist/_private/index.cjs +2 -0
  2. package/dist/_private/index.cjs.map +1 -1
  3. package/dist/_private/index.d.cts +3 -1
  4. package/dist/_private/index.d.ts +3 -1
  5. package/dist/_private/index.js +1 -0
  6. package/dist/_private/index.js.map +1 -1
  7. package/dist/components/AvatarStack.cjs +10 -5
  8. package/dist/components/AvatarStack.cjs.map +1 -1
  9. package/dist/components/AvatarStack.js +10 -5
  10. package/dist/components/AvatarStack.js.map +1 -1
  11. package/dist/components/CommentPin.cjs +4 -2
  12. package/dist/components/CommentPin.cjs.map +1 -1
  13. package/dist/components/CommentPin.js +4 -2
  14. package/dist/components/CommentPin.js.map +1 -1
  15. package/dist/components/FloatingComposer.cjs +17 -2
  16. package/dist/components/FloatingComposer.cjs.map +1 -1
  17. package/dist/components/FloatingComposer.js +18 -3
  18. package/dist/components/FloatingComposer.js.map +1 -1
  19. package/dist/components/FloatingThread.cjs +1 -0
  20. package/dist/components/FloatingThread.cjs.map +1 -1
  21. package/dist/components/FloatingThread.js +1 -0
  22. package/dist/components/FloatingThread.js.map +1 -1
  23. package/dist/components/internal/Dropdown.cjs +1 -0
  24. package/dist/components/internal/Dropdown.cjs.map +1 -1
  25. package/dist/components/internal/Dropdown.js +1 -0
  26. package/dist/components/internal/Dropdown.js.map +1 -1
  27. package/dist/components/internal/EmojiPicker.cjs +1 -0
  28. package/dist/components/internal/EmojiPicker.cjs.map +1 -1
  29. package/dist/components/internal/EmojiPicker.js +1 -0
  30. package/dist/components/internal/EmojiPicker.js.map +1 -1
  31. package/dist/components/internal/Tooltip.cjs +1 -0
  32. package/dist/components/internal/Tooltip.cjs.map +1 -1
  33. package/dist/components/internal/Tooltip.js +1 -0
  34. package/dist/components/internal/Tooltip.js.map +1 -1
  35. package/dist/icon.cjs +2 -0
  36. package/dist/icon.cjs.map +1 -1
  37. package/dist/icon.js +1 -0
  38. package/dist/icon.js.map +1 -1
  39. package/dist/icons/Plus.cjs +11 -0
  40. package/dist/icons/Plus.cjs.map +1 -0
  41. package/dist/icons/Plus.js +9 -0
  42. package/dist/icons/Plus.js.map +1 -0
  43. package/dist/icons/index.cjs +2 -0
  44. package/dist/icons/index.cjs.map +1 -1
  45. package/dist/icons/index.js +1 -0
  46. package/dist/icons/index.js.map +1 -1
  47. package/dist/index.d.cts +9 -1
  48. package/dist/index.d.ts +9 -1
  49. package/dist/utils/px.cjs +14 -0
  50. package/dist/utils/px.cjs.map +1 -0
  51. package/dist/utils/px.js +12 -0
  52. package/dist/utils/px.js.map +1 -0
  53. package/dist/version.cjs +1 -1
  54. package/dist/version.cjs.map +1 -1
  55. package/dist/version.js +1 -1
  56. package/dist/version.js.map +1 -1
  57. package/package.json +4 -4
  58. package/src/styles/index.css +8 -1
  59. package/styles.css +1 -1
  60. package/styles.css.map +1 -1
@@ -57,6 +57,7 @@ var ListOrdered = require('../icons/ListOrdered.cjs');
57
57
  var ListUnordered = require('../icons/ListUnordered.cjs');
58
58
  var Mention = require('../icons/Mention.cjs');
59
59
  var MinusCircle = require('../icons/MinusCircle.cjs');
60
+ var Plus = require('../icons/Plus.cjs');
60
61
  var QuestionMark = require('../icons/QuestionMark.cjs');
61
62
  var Redo = require('../icons/Redo.cjs');
62
63
  var Restore = require('../icons/Restore.cjs');
@@ -138,6 +139,7 @@ exports.ListOrderedIcon = ListOrdered.ListOrderedIcon;
138
139
  exports.ListUnorderedIcon = ListUnordered.ListUnorderedIcon;
139
140
  exports.MentionIcon = Mention.MentionIcon;
140
141
  exports.MinusCircleIcon = MinusCircle.MinusCircleIcon;
142
+ exports.PlusIcon = Plus.PlusIcon;
141
143
  exports.QuestionMarkIcon = QuestionMark.QuestionMarkIcon;
142
144
  exports.RedoIcon = Redo.RedoIcon;
143
145
  exports.RestoreIcon = Restore.RestoreIcon;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -447,6 +447,8 @@ declare function MentionIcon(props: ComponentProps<"svg">): react_jsx_runtime.JS
447
447
 
448
448
  declare function MinusCircleIcon(props: ComponentProps<"svg">): react_jsx_runtime.JSX.Element;
449
449
 
450
+ declare function PlusIcon(props: ComponentProps<"svg">): react_jsx_runtime.JSX.Element;
451
+
450
452
  declare function QuestionMarkIcon(props: ComponentProps<"svg">): react_jsx_runtime.JSX.Element;
451
453
 
452
454
  declare function RedoIcon(props: ComponentProps<"svg">): react_jsx_runtime.JSX.Element;
@@ -724,4 +726,4 @@ declare namespace index {
724
726
  };
725
727
  }
726
728
 
727
- 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, 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, useAiComposer, useInitial, useLiveblocksUiConfig, useRefs, useStableComponent };
729
+ 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, useAiComposer, useInitial, useLiveblocksUiConfig, useRefs, useStableComponent };
@@ -447,6 +447,8 @@ declare function MentionIcon(props: ComponentProps<"svg">): react_jsx_runtime.JS
447
447
 
448
448
  declare function MinusCircleIcon(props: ComponentProps<"svg">): react_jsx_runtime.JSX.Element;
449
449
 
450
+ declare function PlusIcon(props: ComponentProps<"svg">): react_jsx_runtime.JSX.Element;
451
+
450
452
  declare function QuestionMarkIcon(props: ComponentProps<"svg">): react_jsx_runtime.JSX.Element;
451
453
 
452
454
  declare function RedoIcon(props: ComponentProps<"svg">): react_jsx_runtime.JSX.Element;
@@ -724,4 +726,4 @@ declare namespace index {
724
726
  };
725
727
  }
726
728
 
727
- 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, 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, useAiComposer, useInitial, useLiveblocksUiConfig, useRefs, useStableComponent };
729
+ 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, useAiComposer, useInitial, useLiveblocksUiConfig, useRefs, useStableComponent };
@@ -58,6 +58,7 @@ export { ListOrderedIcon } from '../icons/ListOrdered.js';
58
58
  export { ListUnorderedIcon } from '../icons/ListUnordered.js';
59
59
  export { MentionIcon } from '../icons/Mention.js';
60
60
  export { MinusCircleIcon } from '../icons/MinusCircle.js';
61
+ export { PlusIcon } from '../icons/Plus.js';
61
62
  export { QuestionMarkIcon } from '../icons/QuestionMark.js';
62
63
  export { RedoIcon } from '../icons/Redo.js';
63
64
  export { RestoreIcon } from '../icons/Restore.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -7,6 +7,7 @@ var react = require('react');
7
7
  var constants = require('../constants.cjs');
8
8
  var overrides = require('../overrides.cjs');
9
9
  var cn = require('../utils/cn.cjs');
10
+ var px = require('../utils/px.cjs');
10
11
  var Avatar = require('./internal/Avatar.cjs');
11
12
  var Tooltip = require('./internal/Tooltip.cjs');
12
13
  var User = require('./internal/User.cjs');
@@ -23,7 +24,9 @@ const AvatarStack = react.forwardRef(
23
24
  ...props
24
25
  }, forwardedRef) => {
25
26
  const $ = overrides.useOverrides(overrides$1);
26
- const otherIds = react$1.useOthers((others) => others.map((user) => user.id));
27
+ const otherIds = react$1.useOthers(
28
+ (others) => [...others].sort((a, b) => b.connectionId - a.connectionId).map((user) => user.id).filter((userId) => userId !== void 0)
29
+ );
27
30
  const selfId = react$1.useSelf((self) => self.id);
28
31
  const userIds = react.useMemo(() => {
29
32
  const uniqueUserIds = /* @__PURE__ */ new Set([
@@ -33,8 +36,10 @@ const AvatarStack = react.forwardRef(
33
36
  ]);
34
37
  return [...uniqueUserIds];
35
38
  }, [selfId, otherIds, additionalUserIds]);
36
- const maxAvatars = Math.max(1, Math.floor(max));
37
- const visibleUserIds = userIds.slice(0, maxAvatars);
39
+ const maxItems = Math.max(2, Math.floor(max));
40
+ const shouldShowMore = userIds.length > maxItems;
41
+ const visibleAvatarsCount = shouldShowMore ? maxItems - 1 : maxItems;
42
+ const visibleUserIds = userIds.slice(0, visibleAvatarsCount);
38
43
  const hiddenUserIds = userIds.slice(visibleUserIds.length);
39
44
  const remainingUsersCount = hiddenUserIds.length;
40
45
  const visibleItemsCount = visibleUserIds.length + Number(remainingUsersCount > 0);
@@ -47,8 +52,8 @@ const AvatarStack = react.forwardRef(
47
52
  className: cn.cn("lb-root lb-avatar-stack", className),
48
53
  dir: $.dir,
49
54
  style: {
50
- "--lb-avatar-stack-count": visibleItemsCount - 1,
51
- "--lb-avatar-stack-size": size,
55
+ "--lb-avatar-stack-count": visibleItemsCount,
56
+ "--lb-avatar-stack-size": px.px(size),
52
57
  ...style
53
58
  },
54
59
  ...props,
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarStack.cjs","sources":["../../src/components/AvatarStack.tsx"],"sourcesContent":["\"use client\";\n\nimport { useOthers, useSelf } from \"@liveblocks/react\";\nimport type { ComponentPropsWithoutRef, CSSProperties } from \"react\";\nimport { forwardRef, useMemo } from \"react\";\n\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport type { GlobalOverrides } from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { Avatar } from \"./internal/Avatar\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\nimport { User } from \"./internal/User\";\n\nexport interface AvatarStackProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Optional additional user IDs to include in the stack.\n */\n userIds?: string[];\n\n /**\n * The maximum number of visible avatars.\n * Defaults to 3, set to `undefined` to show all avatars.\n */\n max?: number;\n\n /**\n * The size of the avatars.\n */\n size?: string | number;\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides>;\n}\n\n/**\n * Displays a stack of avatars for the users currently present in the room.\n */\nexport const AvatarStack = forwardRef<HTMLDivElement, AvatarStackProps>(\n (\n {\n userIds: additionalUserIds = [],\n max = 3,\n size,\n overrides,\n className,\n style,\n ...props\n },\n forwardedRef\n ) => {\n const $ = useOverrides(overrides);\n const otherIds = useOthers((others) => others.map((user) => user.id));\n const selfId = useSelf((self) => self.id);\n const userIds = useMemo(() => {\n const uniqueUserIds = new Set([\n selfId,\n ...otherIds,\n ...additionalUserIds,\n ]);\n\n return [...uniqueUserIds];\n }, [selfId, otherIds, additionalUserIds]);\n const maxAvatars = Math.max(1, Math.floor(max));\n const visibleUserIds = userIds.slice(0, maxAvatars);\n const hiddenUserIds = userIds.slice(visibleUserIds.length);\n const remainingUsersCount = hiddenUserIds.length;\n const visibleItemsCount =\n visibleUserIds.length + Number(remainingUsersCount > 0);\n\n if (userIds.length === 0) {\n return null;\n }\n\n return (\n <TooltipProvider>\n <div\n className={cn(\"lb-root lb-avatar-stack\", className)}\n dir={$.dir}\n style={\n {\n \"--lb-avatar-stack-count\": visibleItemsCount - 1,\n \"--lb-avatar-stack-size\": size,\n ...style,\n } as CSSProperties\n }\n {...props}\n ref={forwardedRef}\n >\n {visibleUserIds.map((userId, index) => {\n if (!userId) {\n return null;\n }\n\n return (\n <Tooltip\n key={userId}\n content={<User userId={userId} />}\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n >\n <Avatar\n userId={userId}\n className=\"lb-avatar-stack-avatar\"\n style={{ \"--lb-avatar-stack-index\": index } as CSSProperties}\n />\n </Tooltip>\n );\n })}\n {remainingUsersCount > 0 ? (\n <Tooltip\n content={\n <ul className=\"lb-users-tooltip-list\">\n {hiddenUserIds.map((userId) =>\n userId ? (\n <li key={userId} className=\"lb-users-tooltip-list-item\">\n <Avatar userId={userId} />\n <User userId={userId} />\n </li>\n ) : null\n )}\n </ul>\n }\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n className=\"lb-users-tooltip\"\n >\n <div\n className=\"lb-avatar lb-avatar-stack-avatar lb-avatar-stack-more\"\n style={\n {\n \"--lb-avatar-stack-index\": visibleUserIds.length,\n } as CSSProperties\n }\n >\n <span className=\"lb-avatar-fallback\">\n +{remainingUsersCount}\n </span>\n </div>\n </Tooltip>\n ) : null}\n </div>\n </TooltipProvider>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;;;;;;;;AA2CO;AAAoB;AAEvB;AACgC;AACxB;AACN;AACA;AACA;AACA;AACG;AAIL;AACA;AACA;AACA;AACE;AAA8B;AAC5B;AACG;AACA;AAGL;AAAwB;AAE1B;AACA;AACA;AACA;AACA;AAGA;AACE;AAAO;AAGT;AAEI;AAAC;AAAA;AACmD;AAC3C;AAEL;AACiD;AACrB;AACvB;AACL;AAEE;AACC;AAEJ;AACC;AACE;AAAO;AAGT;AACE;AAAC;AAAA;AAEgC;AACnB;AACM;AACb;AACC;AAEN;AAAC;AAAA;AACC;AACU;AACgC;AAAA;AAC5C;AAAA;AAXK;AAYP;AAEH;AAEC;AAAC;AAAA;AAGoB;AAGT;AAAwB;AACF;AAEtB;AAER;AAEU;AACM;AACb;AACC;AACI;AAEV;AAAC;AAAA;AACW;AAER;AAC4C;AAC5C;AAGmC;AAAA;AACjC;AACJ;AAAA;AACF;AAAA;AAEA;AAAA;AAAA;AAER;AAGN;;"}
1
+ {"version":3,"file":"AvatarStack.cjs","sources":["../../src/components/AvatarStack.tsx"],"sourcesContent":["\"use client\";\n\nimport { useOthers, useSelf } from \"@liveblocks/react\";\nimport type { ComponentPropsWithoutRef, CSSProperties } from \"react\";\nimport { forwardRef, useMemo } from \"react\";\n\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport type { GlobalOverrides } from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { px } from \"../utils/px\";\nimport { Avatar } from \"./internal/Avatar\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\nimport { User } from \"./internal/User\";\n\nexport interface AvatarStackProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Optional additional user IDs to include in the stack.\n */\n userIds?: string[];\n\n /**\n * The maximum number of items in the stack (at least 2).\n * Defaults to 3, set to `undefined` to show all avatars.\n */\n max?: number;\n\n /**\n * The size of the avatars.\n */\n size?: string | number;\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides>;\n}\n\n/**\n * Displays a stack of avatars for the users currently present in the room.\n */\nexport const AvatarStack = forwardRef<HTMLDivElement, AvatarStackProps>(\n (\n {\n userIds: additionalUserIds = [],\n max = 3,\n size,\n overrides,\n className,\n style,\n ...props\n },\n forwardedRef\n ) => {\n const $ = useOverrides(overrides);\n const otherIds = useOthers((others) =>\n [...others]\n .sort((a, b) => b.connectionId - a.connectionId)\n .map((user) => user.id)\n .filter((userId): userId is string => userId !== undefined)\n );\n const selfId = useSelf((self) => self.id);\n const userIds = useMemo(() => {\n const uniqueUserIds = new Set([\n selfId,\n ...otherIds,\n ...additionalUserIds,\n ]);\n\n return [...uniqueUserIds];\n }, [selfId, otherIds, additionalUserIds]);\n const maxItems = Math.max(2, Math.floor(max));\n const shouldShowMore = userIds.length > maxItems;\n const visibleAvatarsCount = shouldShowMore ? maxItems - 1 : maxItems;\n const visibleUserIds = userIds.slice(0, visibleAvatarsCount);\n const hiddenUserIds = userIds.slice(visibleUserIds.length);\n const remainingUsersCount = hiddenUserIds.length;\n const visibleItemsCount =\n visibleUserIds.length + Number(remainingUsersCount > 0);\n\n if (userIds.length === 0) {\n return null;\n }\n\n return (\n <TooltipProvider>\n <div\n className={cn(\"lb-root lb-avatar-stack\", className)}\n dir={$.dir}\n style={\n {\n \"--lb-avatar-stack-count\": visibleItemsCount,\n \"--lb-avatar-stack-size\": px(size),\n ...style,\n } as CSSProperties\n }\n {...props}\n ref={forwardedRef}\n >\n {visibleUserIds.map((userId, index) => {\n if (!userId) {\n return null;\n }\n\n return (\n <Tooltip\n key={userId}\n content={<User userId={userId} />}\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n >\n <Avatar\n userId={userId}\n className=\"lb-avatar-stack-avatar\"\n style={{ \"--lb-avatar-stack-index\": index } as CSSProperties}\n />\n </Tooltip>\n );\n })}\n {remainingUsersCount > 0 ? (\n <Tooltip\n content={\n <ul className=\"lb-users-tooltip-list\">\n {hiddenUserIds.map((userId) =>\n userId ? (\n <li key={userId} className=\"lb-users-tooltip-list-item\">\n <Avatar userId={userId} />\n <User userId={userId} />\n </li>\n ) : null\n )}\n </ul>\n }\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n className=\"lb-users-tooltip\"\n >\n <div\n className=\"lb-avatar lb-avatar-stack-avatar lb-avatar-stack-more\"\n style={\n {\n \"--lb-avatar-stack-index\": visibleUserIds.length,\n } as CSSProperties\n }\n >\n <span className=\"lb-avatar-fallback\">\n +{remainingUsersCount}\n </span>\n </div>\n </Tooltip>\n ) : null}\n </div>\n </TooltipProvider>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AA4CO;AAAoB;AAEvB;AACgC;AACxB;AACN;AACA;AACA;AACA;AACG;AAIL;AACA;AAAiB;AAI6C;AAE9D;AACA;AACE;AAA8B;AAC5B;AACG;AACA;AAGL;AAAwB;AAE1B;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACE;AAAO;AAGT;AAEI;AAAC;AAAA;AACmD;AAC3C;AAEL;AAC6B;AACM;AAC9B;AACL;AAEE;AACC;AAEJ;AACC;AACE;AAAO;AAGT;AACE;AAAC;AAAA;AAEgC;AACnB;AACM;AACb;AACC;AAEN;AAAC;AAAA;AACC;AACU;AACgC;AAAA;AAC5C;AAAA;AAXK;AAYP;AAEH;AAEC;AAAC;AAAA;AAGoB;AAGT;AAAwB;AACF;AAEtB;AAER;AAEU;AACM;AACb;AACC;AACI;AAEV;AAAC;AAAA;AACW;AAER;AAC4C;AAC5C;AAGmC;AAAA;AACjC;AACJ;AAAA;AACF;AAAA;AAEA;AAAA;AAAA;AAER;AAGN;;"}
@@ -5,6 +5,7 @@ import { forwardRef, useMemo } from 'react';
5
5
  import { FLOATING_ELEMENT_SIDE_OFFSET, FLOATING_ELEMENT_COLLISION_PADDING } from '../constants.js';
6
6
  import { useOverrides } from '../overrides.js';
7
7
  import { cn } from '../utils/cn.js';
8
+ import { px } from '../utils/px.js';
8
9
  import { Avatar } from './internal/Avatar.js';
9
10
  import { TooltipProvider, Tooltip } from './internal/Tooltip.js';
10
11
  import { User } from './internal/User.js';
@@ -21,7 +22,9 @@ const AvatarStack = forwardRef(
21
22
  ...props
22
23
  }, forwardedRef) => {
23
24
  const $ = useOverrides(overrides);
24
- const otherIds = useOthers((others) => others.map((user) => user.id));
25
+ const otherIds = useOthers(
26
+ (others) => [...others].sort((a, b) => b.connectionId - a.connectionId).map((user) => user.id).filter((userId) => userId !== void 0)
27
+ );
25
28
  const selfId = useSelf((self) => self.id);
26
29
  const userIds = useMemo(() => {
27
30
  const uniqueUserIds = /* @__PURE__ */ new Set([
@@ -31,8 +34,10 @@ const AvatarStack = forwardRef(
31
34
  ]);
32
35
  return [...uniqueUserIds];
33
36
  }, [selfId, otherIds, additionalUserIds]);
34
- const maxAvatars = Math.max(1, Math.floor(max));
35
- const visibleUserIds = userIds.slice(0, maxAvatars);
37
+ const maxItems = Math.max(2, Math.floor(max));
38
+ const shouldShowMore = userIds.length > maxItems;
39
+ const visibleAvatarsCount = shouldShowMore ? maxItems - 1 : maxItems;
40
+ const visibleUserIds = userIds.slice(0, visibleAvatarsCount);
36
41
  const hiddenUserIds = userIds.slice(visibleUserIds.length);
37
42
  const remainingUsersCount = hiddenUserIds.length;
38
43
  const visibleItemsCount = visibleUserIds.length + Number(remainingUsersCount > 0);
@@ -45,8 +50,8 @@ const AvatarStack = forwardRef(
45
50
  className: cn("lb-root lb-avatar-stack", className),
46
51
  dir: $.dir,
47
52
  style: {
48
- "--lb-avatar-stack-count": visibleItemsCount - 1,
49
- "--lb-avatar-stack-size": size,
53
+ "--lb-avatar-stack-count": visibleItemsCount,
54
+ "--lb-avatar-stack-size": px(size),
50
55
  ...style
51
56
  },
52
57
  ...props,
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarStack.js","sources":["../../src/components/AvatarStack.tsx"],"sourcesContent":["\"use client\";\n\nimport { useOthers, useSelf } from \"@liveblocks/react\";\nimport type { ComponentPropsWithoutRef, CSSProperties } from \"react\";\nimport { forwardRef, useMemo } from \"react\";\n\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport type { GlobalOverrides } from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { Avatar } from \"./internal/Avatar\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\nimport { User } from \"./internal/User\";\n\nexport interface AvatarStackProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Optional additional user IDs to include in the stack.\n */\n userIds?: string[];\n\n /**\n * The maximum number of visible avatars.\n * Defaults to 3, set to `undefined` to show all avatars.\n */\n max?: number;\n\n /**\n * The size of the avatars.\n */\n size?: string | number;\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides>;\n}\n\n/**\n * Displays a stack of avatars for the users currently present in the room.\n */\nexport const AvatarStack = forwardRef<HTMLDivElement, AvatarStackProps>(\n (\n {\n userIds: additionalUserIds = [],\n max = 3,\n size,\n overrides,\n className,\n style,\n ...props\n },\n forwardedRef\n ) => {\n const $ = useOverrides(overrides);\n const otherIds = useOthers((others) => others.map((user) => user.id));\n const selfId = useSelf((self) => self.id);\n const userIds = useMemo(() => {\n const uniqueUserIds = new Set([\n selfId,\n ...otherIds,\n ...additionalUserIds,\n ]);\n\n return [...uniqueUserIds];\n }, [selfId, otherIds, additionalUserIds]);\n const maxAvatars = Math.max(1, Math.floor(max));\n const visibleUserIds = userIds.slice(0, maxAvatars);\n const hiddenUserIds = userIds.slice(visibleUserIds.length);\n const remainingUsersCount = hiddenUserIds.length;\n const visibleItemsCount =\n visibleUserIds.length + Number(remainingUsersCount > 0);\n\n if (userIds.length === 0) {\n return null;\n }\n\n return (\n <TooltipProvider>\n <div\n className={cn(\"lb-root lb-avatar-stack\", className)}\n dir={$.dir}\n style={\n {\n \"--lb-avatar-stack-count\": visibleItemsCount - 1,\n \"--lb-avatar-stack-size\": size,\n ...style,\n } as CSSProperties\n }\n {...props}\n ref={forwardedRef}\n >\n {visibleUserIds.map((userId, index) => {\n if (!userId) {\n return null;\n }\n\n return (\n <Tooltip\n key={userId}\n content={<User userId={userId} />}\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n >\n <Avatar\n userId={userId}\n className=\"lb-avatar-stack-avatar\"\n style={{ \"--lb-avatar-stack-index\": index } as CSSProperties}\n />\n </Tooltip>\n );\n })}\n {remainingUsersCount > 0 ? (\n <Tooltip\n content={\n <ul className=\"lb-users-tooltip-list\">\n {hiddenUserIds.map((userId) =>\n userId ? (\n <li key={userId} className=\"lb-users-tooltip-list-item\">\n <Avatar userId={userId} />\n <User userId={userId} />\n </li>\n ) : null\n )}\n </ul>\n }\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n className=\"lb-users-tooltip\"\n >\n <div\n className=\"lb-avatar lb-avatar-stack-avatar lb-avatar-stack-more\"\n style={\n {\n \"--lb-avatar-stack-index\": visibleUserIds.length,\n } as CSSProperties\n }\n >\n <span className=\"lb-avatar-fallback\">\n +{remainingUsersCount}\n </span>\n </div>\n </Tooltip>\n ) : null}\n </div>\n </TooltipProvider>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;;;;;;AA2CO;AAAoB;AAEvB;AACgC;AACxB;AACN;AACA;AACA;AACA;AACG;AAIL;AACA;AACA;AACA;AACE;AAA8B;AAC5B;AACG;AACA;AAGL;AAAwB;AAE1B;AACA;AACA;AACA;AACA;AAGA;AACE;AAAO;AAGT;AAEI;AAAC;AAAA;AACmD;AAC3C;AAEL;AACiD;AACrB;AACvB;AACL;AAEE;AACC;AAEJ;AACC;AACE;AAAO;AAGT;AACE;AAAC;AAAA;AAEgC;AACnB;AACM;AACb;AACC;AAEN;AAAC;AAAA;AACC;AACU;AACgC;AAAA;AAC5C;AAAA;AAXK;AAYP;AAEH;AAEC;AAAC;AAAA;AAGoB;AAGT;AAAwB;AACF;AAEtB;AAER;AAEU;AACM;AACb;AACC;AACI;AAEV;AAAC;AAAA;AACW;AAER;AAC4C;AAC5C;AAGmC;AAAA;AACjC;AACJ;AAAA;AACF;AAAA;AAEA;AAAA;AAAA;AAER;AAGN;;"}
1
+ {"version":3,"file":"AvatarStack.js","sources":["../../src/components/AvatarStack.tsx"],"sourcesContent":["\"use client\";\n\nimport { useOthers, useSelf } from \"@liveblocks/react\";\nimport type { ComponentPropsWithoutRef, CSSProperties } from \"react\";\nimport { forwardRef, useMemo } from \"react\";\n\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport type { GlobalOverrides } from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { px } from \"../utils/px\";\nimport { Avatar } from \"./internal/Avatar\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\nimport { User } from \"./internal/User\";\n\nexport interface AvatarStackProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Optional additional user IDs to include in the stack.\n */\n userIds?: string[];\n\n /**\n * The maximum number of items in the stack (at least 2).\n * Defaults to 3, set to `undefined` to show all avatars.\n */\n max?: number;\n\n /**\n * The size of the avatars.\n */\n size?: string | number;\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides>;\n}\n\n/**\n * Displays a stack of avatars for the users currently present in the room.\n */\nexport const AvatarStack = forwardRef<HTMLDivElement, AvatarStackProps>(\n (\n {\n userIds: additionalUserIds = [],\n max = 3,\n size,\n overrides,\n className,\n style,\n ...props\n },\n forwardedRef\n ) => {\n const $ = useOverrides(overrides);\n const otherIds = useOthers((others) =>\n [...others]\n .sort((a, b) => b.connectionId - a.connectionId)\n .map((user) => user.id)\n .filter((userId): userId is string => userId !== undefined)\n );\n const selfId = useSelf((self) => self.id);\n const userIds = useMemo(() => {\n const uniqueUserIds = new Set([\n selfId,\n ...otherIds,\n ...additionalUserIds,\n ]);\n\n return [...uniqueUserIds];\n }, [selfId, otherIds, additionalUserIds]);\n const maxItems = Math.max(2, Math.floor(max));\n const shouldShowMore = userIds.length > maxItems;\n const visibleAvatarsCount = shouldShowMore ? maxItems - 1 : maxItems;\n const visibleUserIds = userIds.slice(0, visibleAvatarsCount);\n const hiddenUserIds = userIds.slice(visibleUserIds.length);\n const remainingUsersCount = hiddenUserIds.length;\n const visibleItemsCount =\n visibleUserIds.length + Number(remainingUsersCount > 0);\n\n if (userIds.length === 0) {\n return null;\n }\n\n return (\n <TooltipProvider>\n <div\n className={cn(\"lb-root lb-avatar-stack\", className)}\n dir={$.dir}\n style={\n {\n \"--lb-avatar-stack-count\": visibleItemsCount,\n \"--lb-avatar-stack-size\": px(size),\n ...style,\n } as CSSProperties\n }\n {...props}\n ref={forwardedRef}\n >\n {visibleUserIds.map((userId, index) => {\n if (!userId) {\n return null;\n }\n\n return (\n <Tooltip\n key={userId}\n content={<User userId={userId} />}\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n >\n <Avatar\n userId={userId}\n className=\"lb-avatar-stack-avatar\"\n style={{ \"--lb-avatar-stack-index\": index } as CSSProperties}\n />\n </Tooltip>\n );\n })}\n {remainingUsersCount > 0 ? (\n <Tooltip\n content={\n <ul className=\"lb-users-tooltip-list\">\n {hiddenUserIds.map((userId) =>\n userId ? (\n <li key={userId} className=\"lb-users-tooltip-list-item\">\n <Avatar userId={userId} />\n <User userId={userId} />\n </li>\n ) : null\n )}\n </ul>\n }\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n className=\"lb-users-tooltip\"\n >\n <div\n className=\"lb-avatar lb-avatar-stack-avatar lb-avatar-stack-more\"\n style={\n {\n \"--lb-avatar-stack-index\": visibleUserIds.length,\n } as CSSProperties\n }\n >\n <span className=\"lb-avatar-fallback\">\n +{remainingUsersCount}\n </span>\n </div>\n </Tooltip>\n ) : null}\n </div>\n </TooltipProvider>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;;;;;;;AA4CO;AAAoB;AAEvB;AACgC;AACxB;AACN;AACA;AACA;AACA;AACG;AAIL;AACA;AAAiB;AAI6C;AAE9D;AACA;AACE;AAA8B;AAC5B;AACG;AACA;AAGL;AAAwB;AAE1B;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACE;AAAO;AAGT;AAEI;AAAC;AAAA;AACmD;AAC3C;AAEL;AAC6B;AACM;AAC9B;AACL;AAEE;AACC;AAEJ;AACC;AACE;AAAO;AAGT;AACE;AAAC;AAAA;AAEgC;AACnB;AACM;AACb;AACC;AAEN;AAAC;AAAA;AACC;AACU;AACgC;AAAA;AAC5C;AAAA;AAXK;AAYP;AAEH;AAEC;AAAC;AAAA;AAGoB;AAGT;AAAwB;AACF;AAEtB;AAER;AAEU;AACM;AACb;AACC;AACI;AAEV;AAAC;AAAA;AACW;AAER;AAC4C;AAC5C;AAGmC;AAAA;AACjC;AACJ;AAAA;AACF;AAAA;AAEA;AAAA;AAAA;AAER;AAGN;;"}
@@ -4,6 +4,7 @@
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var react = require('react');
6
6
  var cn = require('../utils/cn.cjs');
7
+ var px = require('../utils/px.cjs');
7
8
  var Avatar = require('./internal/Avatar.cjs');
8
9
 
9
10
 
@@ -15,6 +16,7 @@ const CommentPin = react.forwardRef(
15
16
  type = "button",
16
17
  className,
17
18
  style,
19
+ children,
18
20
  ...props
19
21
  }, forwardedRef) => {
20
22
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -22,11 +24,11 @@ const CommentPin = react.forwardRef(
22
24
  {
23
25
  className: cn.cn("lb-root lb-comment-pin", className),
24
26
  "data-corner": corner,
25
- style: { "--lb-comment-pin-size": size, ...style },
27
+ style: { "--lb-comment-pin-size": px.px(size), ...style },
26
28
  type,
27
29
  ...props,
28
30
  ref: forwardedRef,
29
- children: userId ? /* @__PURE__ */ jsxRuntime.jsx(Avatar.Avatar, { className: "lb-comment-pin-avatar", userId }) : null
31
+ children: children ?? (userId ? /* @__PURE__ */ jsxRuntime.jsx(Avatar.Avatar, { className: "lb-comment-pin-avatar", userId }) : null)
30
32
  }
31
33
  );
32
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CommentPin.cjs","sources":["../../src/components/CommentPin.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentPropsWithoutRef, CSSProperties } from \"react\";\nimport { forwardRef } from \"react\";\n\nimport { cn } from \"../utils/cn\";\nimport { Avatar } from \"./internal/Avatar\";\n\nexport interface CommentPinProps extends ComponentPropsWithoutRef<\"button\"> {\n /**\n * The corner that points to the comment position.\n * Defaults to the bottom left corner.\n */\n corner?: \"top-left\" | \"top-right\" | \"bottom-right\" | \"bottom-left\";\n\n /**\n * The user ID to optionally display an avatar for.\n */\n userId?: string;\n\n /**\n * The size of the pin.\n */\n size?: string | number;\n}\n\n/**\n * Displays a comment pin that can be used as a trigger\n * for `FloatingComposer` and `FloatingThread`.\n */\nexport const CommentPin = forwardRef<HTMLButtonElement, CommentPinProps>(\n (\n {\n corner = \"bottom-left\",\n userId,\n size,\n type = \"button\",\n className,\n style,\n ...props\n },\n forwardedRef\n ) => {\n return (\n <button\n className={cn(\"lb-root lb-comment-pin\", className)}\n data-corner={corner}\n style={{ \"--lb-comment-pin-size\": size, ...style } as CSSProperties}\n type={type}\n {...props}\n ref={forwardedRef}\n >\n {userId ? (\n <Avatar className=\"lb-comment-pin-avatar\" userId={userId} />\n ) : null}\n </button>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;;;AA8BO;AAAmB;AAEtB;AACW;AACT;AACA;AACO;AACP;AACA;AACG;AAIL;AACE;AAAC;AAAA;AACkD;AACpC;AACoC;AACjD;AACI;AACC;AAID;AAAA;AACN;AAGN;;"}
1
+ {"version":3,"file":"CommentPin.cjs","sources":["../../src/components/CommentPin.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from \"react\";\nimport { forwardRef } from \"react\";\n\nimport { cn } from \"../utils/cn\";\nimport { px } from \"../utils/px\";\nimport { Avatar } from \"./internal/Avatar\";\n\nexport interface CommentPinProps extends ComponentPropsWithoutRef<\"button\"> {\n /**\n * The corner that points to the comment position.\n * Defaults to the bottom left corner.\n */\n corner?: \"top-left\" | \"top-right\" | \"bottom-right\" | \"bottom-left\";\n\n /**\n * The user ID to optionally display an avatar for.\n */\n userId?: string;\n\n /**\n * The size of the pin.\n */\n size?: string | number;\n\n /**\n * The content shown in the pin.\n * If provided, the `userId` prop is ignored.\n */\n children?: ReactNode;\n}\n\n/**\n * Displays a comment pin that can be used as a trigger\n * for `FloatingComposer` and `FloatingThread`.\n */\nexport const CommentPin = forwardRef<HTMLButtonElement, CommentPinProps>(\n (\n {\n corner = \"bottom-left\",\n userId,\n size,\n type = \"button\",\n className,\n style,\n children,\n ...props\n },\n forwardedRef\n ) => {\n return (\n <button\n className={cn(\"lb-root lb-comment-pin\", className)}\n data-corner={corner}\n style={{ \"--lb-comment-pin-size\": px(size), ...style } as CSSProperties}\n type={type}\n {...props}\n ref={forwardedRef}\n >\n {children ??\n (userId ? (\n <Avatar className=\"lb-comment-pin-avatar\" userId={userId} />\n ) : null)}\n </button>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;;;;AAqCO;AAAmB;AAEtB;AACW;AACT;AACA;AACO;AACP;AACA;AACA;AACG;AAIL;AACE;AAAC;AAAA;AACkD;AACpC;AACwC;AACrD;AACI;AACC;AAKC;AAAA;AACR;AAGN;;"}
@@ -2,6 +2,7 @@
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import { forwardRef } from 'react';
4
4
  import { cn } from '../utils/cn.js';
5
+ import { px } from '../utils/px.js';
5
6
  import { Avatar } from './internal/Avatar.js';
6
7
 
7
8
 
@@ -13,6 +14,7 @@ const CommentPin = forwardRef(
13
14
  type = "button",
14
15
  className,
15
16
  style,
17
+ children,
16
18
  ...props
17
19
  }, forwardedRef) => {
18
20
  return /* @__PURE__ */ jsx(
@@ -20,11 +22,11 @@ const CommentPin = forwardRef(
20
22
  {
21
23
  className: cn("lb-root lb-comment-pin", className),
22
24
  "data-corner": corner,
23
- style: { "--lb-comment-pin-size": size, ...style },
25
+ style: { "--lb-comment-pin-size": px(size), ...style },
24
26
  type,
25
27
  ...props,
26
28
  ref: forwardedRef,
27
- children: userId ? /* @__PURE__ */ jsx(Avatar, { className: "lb-comment-pin-avatar", userId }) : null
29
+ children: children ?? (userId ? /* @__PURE__ */ jsx(Avatar, { className: "lb-comment-pin-avatar", userId }) : null)
28
30
  }
29
31
  );
30
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CommentPin.js","sources":["../../src/components/CommentPin.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentPropsWithoutRef, CSSProperties } from \"react\";\nimport { forwardRef } from \"react\";\n\nimport { cn } from \"../utils/cn\";\nimport { Avatar } from \"./internal/Avatar\";\n\nexport interface CommentPinProps extends ComponentPropsWithoutRef<\"button\"> {\n /**\n * The corner that points to the comment position.\n * Defaults to the bottom left corner.\n */\n corner?: \"top-left\" | \"top-right\" | \"bottom-right\" | \"bottom-left\";\n\n /**\n * The user ID to optionally display an avatar for.\n */\n userId?: string;\n\n /**\n * The size of the pin.\n */\n size?: string | number;\n}\n\n/**\n * Displays a comment pin that can be used as a trigger\n * for `FloatingComposer` and `FloatingThread`.\n */\nexport const CommentPin = forwardRef<HTMLButtonElement, CommentPinProps>(\n (\n {\n corner = \"bottom-left\",\n userId,\n size,\n type = \"button\",\n className,\n style,\n ...props\n },\n forwardedRef\n ) => {\n return (\n <button\n className={cn(\"lb-root lb-comment-pin\", className)}\n data-corner={corner}\n style={{ \"--lb-comment-pin-size\": size, ...style } as CSSProperties}\n type={type}\n {...props}\n ref={forwardedRef}\n >\n {userId ? (\n <Avatar className=\"lb-comment-pin-avatar\" userId={userId} />\n ) : null}\n </button>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;AA8BO;AAAmB;AAEtB;AACW;AACT;AACA;AACO;AACP;AACA;AACG;AAIL;AACE;AAAC;AAAA;AACkD;AACpC;AACoC;AACjD;AACI;AACC;AAID;AAAA;AACN;AAGN;;"}
1
+ {"version":3,"file":"CommentPin.js","sources":["../../src/components/CommentPin.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from \"react\";\nimport { forwardRef } from \"react\";\n\nimport { cn } from \"../utils/cn\";\nimport { px } from \"../utils/px\";\nimport { Avatar } from \"./internal/Avatar\";\n\nexport interface CommentPinProps extends ComponentPropsWithoutRef<\"button\"> {\n /**\n * The corner that points to the comment position.\n * Defaults to the bottom left corner.\n */\n corner?: \"top-left\" | \"top-right\" | \"bottom-right\" | \"bottom-left\";\n\n /**\n * The user ID to optionally display an avatar for.\n */\n userId?: string;\n\n /**\n * The size of the pin.\n */\n size?: string | number;\n\n /**\n * The content shown in the pin.\n * If provided, the `userId` prop is ignored.\n */\n children?: ReactNode;\n}\n\n/**\n * Displays a comment pin that can be used as a trigger\n * for `FloatingComposer` and `FloatingThread`.\n */\nexport const CommentPin = forwardRef<HTMLButtonElement, CommentPinProps>(\n (\n {\n corner = \"bottom-left\",\n userId,\n size,\n type = \"button\",\n className,\n style,\n children,\n ...props\n },\n forwardedRef\n ) => {\n return (\n <button\n className={cn(\"lb-root lb-comment-pin\", className)}\n data-corner={corner}\n style={{ \"--lb-comment-pin-size\": px(size), ...style } as CSSProperties}\n type={type}\n {...props}\n ref={forwardedRef}\n >\n {children ??\n (userId ? (\n <Avatar className=\"lb-comment-pin-avatar\" userId={userId} />\n ) : null)}\n </button>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;;AAqCO;AAAmB;AAEtB;AACW;AACT;AACA;AACO;AACP;AACA;AACA;AACG;AAIL;AACE;AAAC;AAAA;AACkD;AACpC;AACwC;AACrD;AACI;AACC;AAKC;AAAA;AACR;AAGN;;"}
@@ -22,10 +22,12 @@ const FloatingComposer = react.forwardRef(
22
22
  sideOffset = constants.FLOATING_ELEMENT_SIDE_OFFSET,
23
23
  align = "start",
24
24
  alignOffset,
25
+ autoFocus = true,
25
26
  overrides: overrides$1,
26
27
  className,
27
28
  ...props
28
29
  }, forwardedRef) => {
30
+ const ref = react.useRef(null);
29
31
  const $ = overrides.useOverrides(overrides$1);
30
32
  const { portalContainer } = config.useLiveblocksUiConfig();
31
33
  const [isOpen, setIsOpen] = useControllableState.useControllableState(
@@ -33,6 +35,11 @@ const FloatingComposer = react.forwardRef(
33
35
  open,
34
36
  onOpenChange
35
37
  );
38
+ react.useImperativeHandle(
39
+ forwardedRef,
40
+ () => ref.current,
41
+ []
42
+ );
36
43
  return /* @__PURE__ */ jsxRuntime.jsxs(radixUi.Popover.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
37
44
  /* @__PURE__ */ jsxRuntime.jsx(radixUi.Popover.Trigger, { asChild: true, children }),
38
45
  /* @__PURE__ */ jsxRuntime.jsx(radixUi.Popover.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -45,6 +52,7 @@ const FloatingComposer = react.forwardRef(
45
52
  dir: $.dir,
46
53
  side,
47
54
  sideOffset,
55
+ updatePositionStrategy: "always",
48
56
  align,
49
57
  alignOffset,
50
58
  collisionPadding: constants.FLOATING_ELEMENT_COLLISION_PADDING,
@@ -61,14 +69,21 @@ const FloatingComposer = react.forwardRef(
61
69
  event.preventDefault();
62
70
  }
63
71
  },
72
+ onOpenAutoFocus: (event) => {
73
+ if (!autoFocus) {
74
+ event.preventDefault();
75
+ ref.current?.focus();
76
+ }
77
+ },
64
78
  asChild: true,
65
79
  children: /* @__PURE__ */ jsxRuntime.jsx(
66
80
  Composer.Composer,
67
81
  {
68
- ref: forwardedRef,
82
+ ref,
69
83
  overrides: overrides$1,
70
- autoFocus: true,
84
+ autoFocus,
71
85
  collapsed: false,
86
+ tabIndex: -1,
72
87
  ...props
73
88
  }
74
89
  )
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingComposer.cjs","sources":["../../src/components/FloatingComposer.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BaseMetadata, DCM, DTM, Relax } from \"@liveblocks/core\";\nimport { Popover as PopoverPrimitive } from \"radix-ui\";\nimport {\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n type RefAttributes,\n} from \"react\";\n\nimport { useLiveblocksUiConfig } from \"../config\";\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { useControllableState } from \"../utils/use-controllable-state\";\nimport type { ComposerProps } from \"./Composer\";\nimport { Composer } from \"./Composer\";\n\nexport interface FloatingComposerProps<\n TM extends BaseMetadata = DTM,\n CM extends BaseMetadata = DCM,\n> extends Omit<\n ComposerProps<TM, CM>,\n \"collapsed\" | \"onCollapsedChange\" | \"defaultCollapsed\"\n >,\n Relax<\n Pick<\n PopoverPrimitive.PopoverProps,\n \"defaultOpen\" | \"open\" | \"onOpenChange\"\n > &\n Pick<\n PopoverPrimitive.PopoverContentProps,\n \"side\" | \"sideOffset\" | \"align\" | \"alignOffset\"\n >\n > {\n /**\n * The element which opens the floating composer.\n */\n children: ReactNode;\n}\n\n/**\n * Displays a floating composer attached to a trigger element.\n */\nexport const FloatingComposer = forwardRef(\n <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n {\n children,\n defaultOpen,\n open,\n onOpenChange,\n side = \"right\",\n sideOffset = FLOATING_ELEMENT_SIDE_OFFSET,\n align = \"start\",\n alignOffset,\n overrides,\n className,\n ...props\n }: FloatingComposerProps<TM, CM>,\n forwardedRef: ForwardedRef<HTMLFormElement>\n ) => {\n const $ = useOverrides(overrides);\n const { portalContainer } = useLiveblocksUiConfig();\n const [isOpen, setIsOpen] = useControllableState(\n defaultOpen ?? false,\n open,\n onOpenChange\n );\n\n return (\n <PopoverPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>\n <PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n className={cn(\n \"lb-root lb-portal lb-elevation lb-floating-composer\",\n className\n )}\n dir={$.dir}\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n onEscapeKeyDown={(event) => {\n if (event.defaultPrevented) {\n return;\n }\n\n setIsOpen(false);\n\n // Prevent further parent layers from closing\n event.preventDefault();\n }}\n onInteractOutside={(event) => {\n // Prevent closing when interacting with elements inside portals\n // (e.g., emoji picker, dropdowns)\n const target = event.target as HTMLElement;\n if (target.closest(\".lb-portal\")) {\n event.preventDefault();\n }\n }}\n asChild\n >\n <Composer\n ref={forwardedRef}\n overrides={overrides}\n autoFocus\n collapsed={false}\n {...(props as ComposerProps<TM, CM>)}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n }\n) as <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n props: FloatingComposerProps<TM, CM> & RefAttributes<HTMLFormElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAgDO;AAAyB;AAE5B;AACE;AACA;AACA;AACA;AACO;AACM;AACL;AACR;AACA;AACA;AACG;AAIL;AACA;AACA;AAA4B;AACX;AACf;AACA;AAGF;AAEI;AAA4C;AAE1C;AAAkB;AAAjB;AACY;AACT;AACA;AACF;AACO;AACP;AACA;AACA;AACA;AACkB;AAEhB;AACE;AAAA;AAGF;AAGA;AAAqB;AACvB;AAIE;AACA;AACE;AAAqB;AACvB;AACF;AACO;AAEP;AAAC;AAAA;AACM;AACL;AACS;AACE;AACN;AAAA;AACP;AAAA;AAEJ;AACF;AAGN;;"}
1
+ {"version":3,"file":"FloatingComposer.cjs","sources":["../../src/components/FloatingComposer.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BaseMetadata, DCM, DTM, Relax } from \"@liveblocks/core\";\nimport { Popover as PopoverPrimitive } from \"radix-ui\";\nimport {\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n type RefAttributes,\n useImperativeHandle,\n useRef,\n} from \"react\";\n\nimport { useLiveblocksUiConfig } from \"../config\";\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { useControllableState } from \"../utils/use-controllable-state\";\nimport type { ComposerProps } from \"./Composer\";\nimport { Composer } from \"./Composer\";\n\nexport interface FloatingComposerProps<\n TM extends BaseMetadata = DTM,\n CM extends BaseMetadata = DCM,\n> extends Omit<\n ComposerProps<TM, CM>,\n \"collapsed\" | \"onCollapsedChange\" | \"defaultCollapsed\"\n >,\n Relax<\n Pick<\n PopoverPrimitive.PopoverProps,\n \"defaultOpen\" | \"open\" | \"onOpenChange\"\n > &\n Pick<\n PopoverPrimitive.PopoverContentProps,\n \"side\" | \"sideOffset\" | \"align\" | \"alignOffset\"\n >\n > {\n /**\n * The element which opens the floating composer.\n */\n children: ReactNode;\n}\n\n/**\n * Displays a floating composer attached to a trigger element.\n */\nexport const FloatingComposer = forwardRef(\n <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n {\n children,\n defaultOpen,\n open,\n onOpenChange,\n side = \"right\",\n sideOffset = FLOATING_ELEMENT_SIDE_OFFSET,\n align = \"start\",\n alignOffset,\n autoFocus = true,\n overrides,\n className,\n ...props\n }: FloatingComposerProps<TM, CM>,\n forwardedRef: ForwardedRef<HTMLFormElement>\n ) => {\n const ref = useRef<HTMLFormElement>(null);\n const $ = useOverrides(overrides);\n const { portalContainer } = useLiveblocksUiConfig();\n const [isOpen, setIsOpen] = useControllableState(\n defaultOpen ?? false,\n open,\n onOpenChange\n );\n\n useImperativeHandle<HTMLFormElement | null, HTMLFormElement | null>(\n forwardedRef,\n () => ref.current,\n []\n );\n\n return (\n <PopoverPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>\n <PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n className={cn(\n \"lb-root lb-portal lb-elevation lb-floating-composer\",\n className\n )}\n dir={$.dir}\n side={side}\n sideOffset={sideOffset}\n updatePositionStrategy=\"always\"\n align={align}\n alignOffset={alignOffset}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n onEscapeKeyDown={(event) => {\n if (event.defaultPrevented) {\n return;\n }\n\n setIsOpen(false);\n\n // Prevent further parent layers from closing\n event.preventDefault();\n }}\n onInteractOutside={(event) => {\n // Prevent closing when interacting with elements inside portals\n // (e.g., emoji picker, dropdowns)\n const target = event.target as HTMLElement;\n if (target.closest(\".lb-portal\")) {\n event.preventDefault();\n }\n }}\n onOpenAutoFocus={(event) => {\n if (!autoFocus) {\n event.preventDefault();\n ref.current?.focus();\n }\n }}\n asChild\n >\n <Composer\n ref={ref}\n overrides={overrides}\n autoFocus={autoFocus}\n collapsed={false}\n tabIndex={-1}\n {...(props as ComposerProps<TM, CM>)}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n }\n) as <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n props: FloatingComposerProps<TM, CM> & RefAttributes<HTMLFormElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAkDO;AAAyB;AAE5B;AACE;AACA;AACA;AACA;AACO;AACM;AACL;AACR;AACY;AACZ;AACA;AACG;AAIL;AACA;AACA;AACA;AAA4B;AACX;AACf;AACA;AAGF;AAAA;AACE;AACU;AACT;AAGH;AAEI;AAA4C;AAE1C;AAAkB;AAAjB;AACY;AACT;AACA;AACF;AACO;AACP;AACA;AACuB;AACvB;AACA;AACkB;AAEhB;AACE;AAAA;AAGF;AAGA;AAAqB;AACvB;AAIE;AACA;AACE;AAAqB;AACvB;AACF;AAEE;AACE;AACA;AAAmB;AACrB;AACF;AACO;AAEP;AAAC;AAAA;AACC;AACA;AACA;AACW;AACD;AACL;AAAA;AACP;AAAA;AAEJ;AACF;AAGN;;"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { Popover } from 'radix-ui';
4
- import { forwardRef } from 'react';
4
+ import { forwardRef, useRef, useImperativeHandle } from 'react';
5
5
  import { useLiveblocksUiConfig } from '../config.js';
6
6
  import { FLOATING_ELEMENT_COLLISION_PADDING, FLOATING_ELEMENT_SIDE_OFFSET } from '../constants.js';
7
7
  import { useOverrides } from '../overrides.js';
@@ -20,10 +20,12 @@ const FloatingComposer = forwardRef(
20
20
  sideOffset = FLOATING_ELEMENT_SIDE_OFFSET,
21
21
  align = "start",
22
22
  alignOffset,
23
+ autoFocus = true,
23
24
  overrides,
24
25
  className,
25
26
  ...props
26
27
  }, forwardedRef) => {
28
+ const ref = useRef(null);
27
29
  const $ = useOverrides(overrides);
28
30
  const { portalContainer } = useLiveblocksUiConfig();
29
31
  const [isOpen, setIsOpen] = useControllableState(
@@ -31,6 +33,11 @@ const FloatingComposer = forwardRef(
31
33
  open,
32
34
  onOpenChange
33
35
  );
36
+ useImperativeHandle(
37
+ forwardedRef,
38
+ () => ref.current,
39
+ []
40
+ );
34
41
  return /* @__PURE__ */ jsxs(Popover.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
35
42
  /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children }),
36
43
  /* @__PURE__ */ jsx(Popover.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
@@ -43,6 +50,7 @@ const FloatingComposer = forwardRef(
43
50
  dir: $.dir,
44
51
  side,
45
52
  sideOffset,
53
+ updatePositionStrategy: "always",
46
54
  align,
47
55
  alignOffset,
48
56
  collisionPadding: FLOATING_ELEMENT_COLLISION_PADDING,
@@ -59,14 +67,21 @@ const FloatingComposer = forwardRef(
59
67
  event.preventDefault();
60
68
  }
61
69
  },
70
+ onOpenAutoFocus: (event) => {
71
+ if (!autoFocus) {
72
+ event.preventDefault();
73
+ ref.current?.focus();
74
+ }
75
+ },
62
76
  asChild: true,
63
77
  children: /* @__PURE__ */ jsx(
64
78
  Composer,
65
79
  {
66
- ref: forwardedRef,
80
+ ref,
67
81
  overrides,
68
- autoFocus: true,
82
+ autoFocus,
69
83
  collapsed: false,
84
+ tabIndex: -1,
70
85
  ...props
71
86
  }
72
87
  )
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingComposer.js","sources":["../../src/components/FloatingComposer.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BaseMetadata, DCM, DTM, Relax } from \"@liveblocks/core\";\nimport { Popover as PopoverPrimitive } from \"radix-ui\";\nimport {\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n type RefAttributes,\n} from \"react\";\n\nimport { useLiveblocksUiConfig } from \"../config\";\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { useControllableState } from \"../utils/use-controllable-state\";\nimport type { ComposerProps } from \"./Composer\";\nimport { Composer } from \"./Composer\";\n\nexport interface FloatingComposerProps<\n TM extends BaseMetadata = DTM,\n CM extends BaseMetadata = DCM,\n> extends Omit<\n ComposerProps<TM, CM>,\n \"collapsed\" | \"onCollapsedChange\" | \"defaultCollapsed\"\n >,\n Relax<\n Pick<\n PopoverPrimitive.PopoverProps,\n \"defaultOpen\" | \"open\" | \"onOpenChange\"\n > &\n Pick<\n PopoverPrimitive.PopoverContentProps,\n \"side\" | \"sideOffset\" | \"align\" | \"alignOffset\"\n >\n > {\n /**\n * The element which opens the floating composer.\n */\n children: ReactNode;\n}\n\n/**\n * Displays a floating composer attached to a trigger element.\n */\nexport const FloatingComposer = forwardRef(\n <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n {\n children,\n defaultOpen,\n open,\n onOpenChange,\n side = \"right\",\n sideOffset = FLOATING_ELEMENT_SIDE_OFFSET,\n align = \"start\",\n alignOffset,\n overrides,\n className,\n ...props\n }: FloatingComposerProps<TM, CM>,\n forwardedRef: ForwardedRef<HTMLFormElement>\n ) => {\n const $ = useOverrides(overrides);\n const { portalContainer } = useLiveblocksUiConfig();\n const [isOpen, setIsOpen] = useControllableState(\n defaultOpen ?? false,\n open,\n onOpenChange\n );\n\n return (\n <PopoverPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>\n <PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n className={cn(\n \"lb-root lb-portal lb-elevation lb-floating-composer\",\n className\n )}\n dir={$.dir}\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n onEscapeKeyDown={(event) => {\n if (event.defaultPrevented) {\n return;\n }\n\n setIsOpen(false);\n\n // Prevent further parent layers from closing\n event.preventDefault();\n }}\n onInteractOutside={(event) => {\n // Prevent closing when interacting with elements inside portals\n // (e.g., emoji picker, dropdowns)\n const target = event.target as HTMLElement;\n if (target.closest(\".lb-portal\")) {\n event.preventDefault();\n }\n }}\n asChild\n >\n <Composer\n ref={forwardedRef}\n overrides={overrides}\n autoFocus\n collapsed={false}\n {...(props as ComposerProps<TM, CM>)}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n }\n) as <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n props: FloatingComposerProps<TM, CM> & RefAttributes<HTMLFormElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;AAgDO;AAAyB;AAE5B;AACE;AACA;AACA;AACA;AACO;AACM;AACL;AACR;AACA;AACA;AACG;AAIL;AACA;AACA;AAA4B;AACX;AACf;AACA;AAGF;AAEI;AAA4C;AAE1C;AAAkB;AAAjB;AACY;AACT;AACA;AACF;AACO;AACP;AACA;AACA;AACA;AACkB;AAEhB;AACE;AAAA;AAGF;AAGA;AAAqB;AACvB;AAIE;AACA;AACE;AAAqB;AACvB;AACF;AACO;AAEP;AAAC;AAAA;AACM;AACL;AACS;AACE;AACN;AAAA;AACP;AAAA;AAEJ;AACF;AAGN;;"}
1
+ {"version":3,"file":"FloatingComposer.js","sources":["../../src/components/FloatingComposer.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BaseMetadata, DCM, DTM, Relax } from \"@liveblocks/core\";\nimport { Popover as PopoverPrimitive } from \"radix-ui\";\nimport {\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n type RefAttributes,\n useImperativeHandle,\n useRef,\n} from \"react\";\n\nimport { useLiveblocksUiConfig } from \"../config\";\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { useControllableState } from \"../utils/use-controllable-state\";\nimport type { ComposerProps } from \"./Composer\";\nimport { Composer } from \"./Composer\";\n\nexport interface FloatingComposerProps<\n TM extends BaseMetadata = DTM,\n CM extends BaseMetadata = DCM,\n> extends Omit<\n ComposerProps<TM, CM>,\n \"collapsed\" | \"onCollapsedChange\" | \"defaultCollapsed\"\n >,\n Relax<\n Pick<\n PopoverPrimitive.PopoverProps,\n \"defaultOpen\" | \"open\" | \"onOpenChange\"\n > &\n Pick<\n PopoverPrimitive.PopoverContentProps,\n \"side\" | \"sideOffset\" | \"align\" | \"alignOffset\"\n >\n > {\n /**\n * The element which opens the floating composer.\n */\n children: ReactNode;\n}\n\n/**\n * Displays a floating composer attached to a trigger element.\n */\nexport const FloatingComposer = forwardRef(\n <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n {\n children,\n defaultOpen,\n open,\n onOpenChange,\n side = \"right\",\n sideOffset = FLOATING_ELEMENT_SIDE_OFFSET,\n align = \"start\",\n alignOffset,\n autoFocus = true,\n overrides,\n className,\n ...props\n }: FloatingComposerProps<TM, CM>,\n forwardedRef: ForwardedRef<HTMLFormElement>\n ) => {\n const ref = useRef<HTMLFormElement>(null);\n const $ = useOverrides(overrides);\n const { portalContainer } = useLiveblocksUiConfig();\n const [isOpen, setIsOpen] = useControllableState(\n defaultOpen ?? false,\n open,\n onOpenChange\n );\n\n useImperativeHandle<HTMLFormElement | null, HTMLFormElement | null>(\n forwardedRef,\n () => ref.current,\n []\n );\n\n return (\n <PopoverPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>\n <PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n className={cn(\n \"lb-root lb-portal lb-elevation lb-floating-composer\",\n className\n )}\n dir={$.dir}\n side={side}\n sideOffset={sideOffset}\n updatePositionStrategy=\"always\"\n align={align}\n alignOffset={alignOffset}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n onEscapeKeyDown={(event) => {\n if (event.defaultPrevented) {\n return;\n }\n\n setIsOpen(false);\n\n // Prevent further parent layers from closing\n event.preventDefault();\n }}\n onInteractOutside={(event) => {\n // Prevent closing when interacting with elements inside portals\n // (e.g., emoji picker, dropdowns)\n const target = event.target as HTMLElement;\n if (target.closest(\".lb-portal\")) {\n event.preventDefault();\n }\n }}\n onOpenAutoFocus={(event) => {\n if (!autoFocus) {\n event.preventDefault();\n ref.current?.focus();\n }\n }}\n asChild\n >\n <Composer\n ref={ref}\n overrides={overrides}\n autoFocus={autoFocus}\n collapsed={false}\n tabIndex={-1}\n {...(props as ComposerProps<TM, CM>)}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n }\n) as <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n props: FloatingComposerProps<TM, CM> & RefAttributes<HTMLFormElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;AAkDO;AAAyB;AAE5B;AACE;AACA;AACA;AACA;AACO;AACM;AACL;AACR;AACY;AACZ;AACA;AACG;AAIL;AACA;AACA;AACA;AAA4B;AACX;AACf;AACA;AAGF;AAAA;AACE;AACU;AACT;AAGH;AAEI;AAA4C;AAE1C;AAAkB;AAAjB;AACY;AACT;AACA;AACF;AACO;AACP;AACA;AACuB;AACvB;AACA;AACkB;AAEhB;AACE;AAAA;AAGF;AAGA;AAAqB;AACvB;AAIE;AACA;AACE;AAAqB;AACvB;AACF;AAEE;AACE;AACA;AAAmB;AACrB;AACF;AACO;AAEP;AAAC;AAAA;AACC;AACA;AACA;AACW;AACD;AACL;AAAA;AACP;AAAA;AAEJ;AACF;AAGN;;"}
@@ -46,6 +46,7 @@ const FloatingThread = react.forwardRef(
46
46
  dir: $.dir,
47
47
  side,
48
48
  sideOffset,
49
+ updatePositionStrategy: "always",
49
50
  align,
50
51
  alignOffset,
51
52
  collisionPadding: constants.FLOATING_ELEMENT_COLLISION_PADDING,
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingThread.cjs","sources":["../../src/components/FloatingThread.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BaseMetadata, DCM, DTM, Relax } from \"@liveblocks/core\";\nimport { Popover as PopoverPrimitive } from \"radix-ui\";\nimport {\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n type RefAttributes,\n} from \"react\";\n\nimport { useLiveblocksUiConfig } from \"../config\";\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { useControllableState } from \"../utils/use-controllable-state\";\nimport type { ThreadProps } from \"./Thread\";\nimport { Thread } from \"./Thread\";\n\nexport interface FloatingThreadProps<\n TM extends BaseMetadata = DTM,\n CM extends BaseMetadata = DCM,\n> extends ThreadProps<TM, CM>,\n Relax<\n Pick<\n PopoverPrimitive.PopoverProps,\n \"defaultOpen\" | \"open\" | \"onOpenChange\"\n > &\n Pick<\n PopoverPrimitive.PopoverContentProps,\n \"side\" | \"sideOffset\" | \"align\" | \"alignOffset\"\n >\n > {\n /**\n * The element which opens the floating thread.\n */\n children: ReactNode;\n}\n\n/**\n * Displays a floating thread attached to a trigger element.\n */\nexport const FloatingThread = forwardRef(\n <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n {\n thread,\n children,\n defaultOpen,\n open,\n onOpenChange,\n side = \"right\",\n sideOffset = FLOATING_ELEMENT_SIDE_OFFSET,\n align = \"start\",\n alignOffset,\n overrides,\n className,\n ...props\n }: FloatingThreadProps<TM, CM>,\n forwardedRef: ForwardedRef<HTMLDivElement>\n ) => {\n const $ = useOverrides(overrides);\n const { portalContainer } = useLiveblocksUiConfig();\n const [isOpen, setIsOpen] = useControllableState(\n defaultOpen ?? false,\n open,\n onOpenChange\n );\n\n return (\n <PopoverPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>\n <PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n className={cn(\n \"lb-root lb-portal lb-elevation lb-floating-thread\",\n className\n )}\n dir={$.dir}\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n onEscapeKeyDown={(event) => {\n if (event.defaultPrevented) {\n return;\n }\n\n setIsOpen(false);\n\n // Prevent further parent layers from closing\n event.preventDefault();\n }}\n onInteractOutside={(event) => {\n // Prevent closing when interacting with elements inside portals\n // (e.g., emoji picker, dropdowns)\n const target = event.target as HTMLElement;\n if (target.closest(\".lb-portal\")) {\n event.preventDefault();\n }\n }}\n asChild\n >\n <Thread\n ref={forwardedRef}\n thread={thread}\n overrides={overrides}\n {...props}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n }\n) as <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n props: FloatingThreadProps<TM, CM> & RefAttributes<HTMLDivElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;;;AA6CO;AAAuB;AAE1B;AACE;AACA;AACA;AACA;AACA;AACO;AACM;AACL;AACR;AACA;AACA;AACG;AAIL;AACA;AACA;AAA4B;AACX;AACf;AACA;AAGF;AAEI;AAA4C;AAE1C;AAAkB;AAAjB;AACY;AACT;AACA;AACF;AACO;AACP;AACA;AACA;AACA;AACkB;AAEhB;AACE;AAAA;AAGF;AAGA;AAAqB;AACvB;AAIE;AACA;AACE;AAAqB;AACvB;AACF;AACO;AAEP;AAAC;AAAA;AACM;AACL;AACA;AACI;AAAA;AACN;AAAA;AAEJ;AACF;AAGN;;"}
1
+ {"version":3,"file":"FloatingThread.cjs","sources":["../../src/components/FloatingThread.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BaseMetadata, DCM, DTM, Relax } from \"@liveblocks/core\";\nimport { Popover as PopoverPrimitive } from \"radix-ui\";\nimport {\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n type RefAttributes,\n} from \"react\";\n\nimport { useLiveblocksUiConfig } from \"../config\";\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { useControllableState } from \"../utils/use-controllable-state\";\nimport type { ThreadProps } from \"./Thread\";\nimport { Thread } from \"./Thread\";\n\nexport interface FloatingThreadProps<\n TM extends BaseMetadata = DTM,\n CM extends BaseMetadata = DCM,\n> extends ThreadProps<TM, CM>,\n Relax<\n Pick<\n PopoverPrimitive.PopoverProps,\n \"defaultOpen\" | \"open\" | \"onOpenChange\"\n > &\n Pick<\n PopoverPrimitive.PopoverContentProps,\n \"side\" | \"sideOffset\" | \"align\" | \"alignOffset\"\n >\n > {\n /**\n * The element which opens the floating thread.\n */\n children: ReactNode;\n}\n\n/**\n * Displays a floating thread attached to a trigger element.\n */\nexport const FloatingThread = forwardRef(\n <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n {\n thread,\n children,\n defaultOpen,\n open,\n onOpenChange,\n side = \"right\",\n sideOffset = FLOATING_ELEMENT_SIDE_OFFSET,\n align = \"start\",\n alignOffset,\n overrides,\n className,\n ...props\n }: FloatingThreadProps<TM, CM>,\n forwardedRef: ForwardedRef<HTMLDivElement>\n ) => {\n const $ = useOverrides(overrides);\n const { portalContainer } = useLiveblocksUiConfig();\n const [isOpen, setIsOpen] = useControllableState(\n defaultOpen ?? false,\n open,\n onOpenChange\n );\n\n return (\n <PopoverPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>\n <PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n className={cn(\n \"lb-root lb-portal lb-elevation lb-floating-thread\",\n className\n )}\n dir={$.dir}\n side={side}\n sideOffset={sideOffset}\n updatePositionStrategy=\"always\"\n align={align}\n alignOffset={alignOffset}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n onEscapeKeyDown={(event) => {\n if (event.defaultPrevented) {\n return;\n }\n\n setIsOpen(false);\n\n // Prevent further parent layers from closing\n event.preventDefault();\n }}\n onInteractOutside={(event) => {\n // Prevent closing when interacting with elements inside portals\n // (e.g., emoji picker, dropdowns)\n const target = event.target as HTMLElement;\n if (target.closest(\".lb-portal\")) {\n event.preventDefault();\n }\n }}\n asChild\n >\n <Thread\n ref={forwardedRef}\n thread={thread}\n overrides={overrides}\n {...props}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n }\n) as <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n props: FloatingThreadProps<TM, CM> & RefAttributes<HTMLDivElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;;;AA6CO;AAAuB;AAE1B;AACE;AACA;AACA;AACA;AACA;AACO;AACM;AACL;AACR;AACA;AACA;AACG;AAIL;AACA;AACA;AAA4B;AACX;AACf;AACA;AAGF;AAEI;AAA4C;AAE1C;AAAkB;AAAjB;AACY;AACT;AACA;AACF;AACO;AACP;AACA;AACuB;AACvB;AACA;AACkB;AAEhB;AACE;AAAA;AAGF;AAGA;AAAqB;AACvB;AAIE;AACA;AACE;AAAqB;AACvB;AACF;AACO;AAEP;AAAC;AAAA;AACM;AACL;AACA;AACI;AAAA;AACN;AAAA;AAEJ;AACF;AAGN;;"}
@@ -44,6 +44,7 @@ const FloatingThread = forwardRef(
44
44
  dir: $.dir,
45
45
  side,
46
46
  sideOffset,
47
+ updatePositionStrategy: "always",
47
48
  align,
48
49
  alignOffset,
49
50
  collisionPadding: FLOATING_ELEMENT_COLLISION_PADDING,
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingThread.js","sources":["../../src/components/FloatingThread.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BaseMetadata, DCM, DTM, Relax } from \"@liveblocks/core\";\nimport { Popover as PopoverPrimitive } from \"radix-ui\";\nimport {\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n type RefAttributes,\n} from \"react\";\n\nimport { useLiveblocksUiConfig } from \"../config\";\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { useControllableState } from \"../utils/use-controllable-state\";\nimport type { ThreadProps } from \"./Thread\";\nimport { Thread } from \"./Thread\";\n\nexport interface FloatingThreadProps<\n TM extends BaseMetadata = DTM,\n CM extends BaseMetadata = DCM,\n> extends ThreadProps<TM, CM>,\n Relax<\n Pick<\n PopoverPrimitive.PopoverProps,\n \"defaultOpen\" | \"open\" | \"onOpenChange\"\n > &\n Pick<\n PopoverPrimitive.PopoverContentProps,\n \"side\" | \"sideOffset\" | \"align\" | \"alignOffset\"\n >\n > {\n /**\n * The element which opens the floating thread.\n */\n children: ReactNode;\n}\n\n/**\n * Displays a floating thread attached to a trigger element.\n */\nexport const FloatingThread = forwardRef(\n <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n {\n thread,\n children,\n defaultOpen,\n open,\n onOpenChange,\n side = \"right\",\n sideOffset = FLOATING_ELEMENT_SIDE_OFFSET,\n align = \"start\",\n alignOffset,\n overrides,\n className,\n ...props\n }: FloatingThreadProps<TM, CM>,\n forwardedRef: ForwardedRef<HTMLDivElement>\n ) => {\n const $ = useOverrides(overrides);\n const { portalContainer } = useLiveblocksUiConfig();\n const [isOpen, setIsOpen] = useControllableState(\n defaultOpen ?? false,\n open,\n onOpenChange\n );\n\n return (\n <PopoverPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>\n <PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n className={cn(\n \"lb-root lb-portal lb-elevation lb-floating-thread\",\n className\n )}\n dir={$.dir}\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n onEscapeKeyDown={(event) => {\n if (event.defaultPrevented) {\n return;\n }\n\n setIsOpen(false);\n\n // Prevent further parent layers from closing\n event.preventDefault();\n }}\n onInteractOutside={(event) => {\n // Prevent closing when interacting with elements inside portals\n // (e.g., emoji picker, dropdowns)\n const target = event.target as HTMLElement;\n if (target.closest(\".lb-portal\")) {\n event.preventDefault();\n }\n }}\n asChild\n >\n <Thread\n ref={forwardedRef}\n thread={thread}\n overrides={overrides}\n {...props}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n }\n) as <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n props: FloatingThreadProps<TM, CM> & RefAttributes<HTMLDivElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;AA6CO;AAAuB;AAE1B;AACE;AACA;AACA;AACA;AACA;AACO;AACM;AACL;AACR;AACA;AACA;AACG;AAIL;AACA;AACA;AAA4B;AACX;AACf;AACA;AAGF;AAEI;AAA4C;AAE1C;AAAkB;AAAjB;AACY;AACT;AACA;AACF;AACO;AACP;AACA;AACA;AACA;AACkB;AAEhB;AACE;AAAA;AAGF;AAGA;AAAqB;AACvB;AAIE;AACA;AACE;AAAqB;AACvB;AACF;AACO;AAEP;AAAC;AAAA;AACM;AACL;AACA;AACI;AAAA;AACN;AAAA;AAEJ;AACF;AAGN;;"}
1
+ {"version":3,"file":"FloatingThread.js","sources":["../../src/components/FloatingThread.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BaseMetadata, DCM, DTM, Relax } from \"@liveblocks/core\";\nimport { Popover as PopoverPrimitive } from \"radix-ui\";\nimport {\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n type RefAttributes,\n} from \"react\";\n\nimport { useLiveblocksUiConfig } from \"../config\";\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { useControllableState } from \"../utils/use-controllable-state\";\nimport type { ThreadProps } from \"./Thread\";\nimport { Thread } from \"./Thread\";\n\nexport interface FloatingThreadProps<\n TM extends BaseMetadata = DTM,\n CM extends BaseMetadata = DCM,\n> extends ThreadProps<TM, CM>,\n Relax<\n Pick<\n PopoverPrimitive.PopoverProps,\n \"defaultOpen\" | \"open\" | \"onOpenChange\"\n > &\n Pick<\n PopoverPrimitive.PopoverContentProps,\n \"side\" | \"sideOffset\" | \"align\" | \"alignOffset\"\n >\n > {\n /**\n * The element which opens the floating thread.\n */\n children: ReactNode;\n}\n\n/**\n * Displays a floating thread attached to a trigger element.\n */\nexport const FloatingThread = forwardRef(\n <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n {\n thread,\n children,\n defaultOpen,\n open,\n onOpenChange,\n side = \"right\",\n sideOffset = FLOATING_ELEMENT_SIDE_OFFSET,\n align = \"start\",\n alignOffset,\n overrides,\n className,\n ...props\n }: FloatingThreadProps<TM, CM>,\n forwardedRef: ForwardedRef<HTMLDivElement>\n ) => {\n const $ = useOverrides(overrides);\n const { portalContainer } = useLiveblocksUiConfig();\n const [isOpen, setIsOpen] = useControllableState(\n defaultOpen ?? false,\n open,\n onOpenChange\n );\n\n return (\n <PopoverPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>\n <PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n className={cn(\n \"lb-root lb-portal lb-elevation lb-floating-thread\",\n className\n )}\n dir={$.dir}\n side={side}\n sideOffset={sideOffset}\n updatePositionStrategy=\"always\"\n align={align}\n alignOffset={alignOffset}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n onEscapeKeyDown={(event) => {\n if (event.defaultPrevented) {\n return;\n }\n\n setIsOpen(false);\n\n // Prevent further parent layers from closing\n event.preventDefault();\n }}\n onInteractOutside={(event) => {\n // Prevent closing when interacting with elements inside portals\n // (e.g., emoji picker, dropdowns)\n const target = event.target as HTMLElement;\n if (target.closest(\".lb-portal\")) {\n event.preventDefault();\n }\n }}\n asChild\n >\n <Thread\n ref={forwardedRef}\n thread={thread}\n overrides={overrides}\n {...props}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n }\n) as <TM extends BaseMetadata = DTM, CM extends BaseMetadata = DCM>(\n props: FloatingThreadProps<TM, CM> & RefAttributes<HTMLDivElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;AA6CO;AAAuB;AAE1B;AACE;AACA;AACA;AACA;AACA;AACO;AACM;AACL;AACR;AACA;AACA;AACG;AAIL;AACA;AACA;AAA4B;AACX;AACf;AACA;AAGF;AAEI;AAA4C;AAE1C;AAAkB;AAAjB;AACY;AACT;AACA;AACF;AACO;AACP;AACA;AACuB;AACvB;AACA;AACkB;AAEhB;AACE;AAAA;AAGF;AAGA;AAAqB;AACvB;AAIE;AACA;AACE;AAAqB;AACvB;AACF;AACO;AAEP;AAAC;AAAA;AACM;AACL;AACA;AACI;AAAA;AACN;AAAA;AAEJ;AACF;AAGN;;"}
@@ -39,6 +39,7 @@ function Dropdown({
39
39
  ),
40
40
  sideOffset: constants.FLOATING_ELEMENT_SIDE_OFFSET,
41
41
  collisionPadding: constants.FLOATING_ELEMENT_COLLISION_PADDING,
42
+ updatePositionStrategy: "always",
42
43
  ...props,
43
44
  children: content
44
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.cjs","sources":["../../../src/components/internal/Dropdown.tsx"],"sourcesContent":["\"use client\";\n\nimport { DropdownMenu as DropdownMenuPrimitive } from \"radix-ui\";\nimport type { ReactNode } from \"react\";\nimport { forwardRef } from \"react\";\n\nimport { useLiveblocksUiConfig } from \"../../config\";\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../../constants\";\nimport { useOverrides } from \"../../overrides\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface DropdownProps\n extends Pick<\n DropdownMenuPrimitive.DropdownMenuProps,\n \"defaultOpen\" | \"open\" | \"onOpenChange\"\n >,\n Pick<DropdownMenuPrimitive.DropdownMenuTriggerProps, \"children\">,\n Omit<DropdownMenuPrimitive.DropdownMenuContentProps, \"content\"> {\n content: ReactNode;\n}\n\ninterface DropdownItemProps\n extends DropdownMenuPrimitive.DropdownMenuItemProps {\n icon?: ReactNode;\n}\n\nexport function Dropdown({\n children,\n content,\n defaultOpen,\n open,\n onOpenChange,\n className,\n ...props\n}: DropdownProps) {\n const $ = useOverrides();\n const { portalContainer } = useLiveblocksUiConfig();\n\n return (\n <DropdownMenuPrimitive.Root\n defaultOpen={defaultOpen}\n open={open}\n onOpenChange={onOpenChange}\n dir={$.dir}\n >\n {children}\n <DropdownMenuPrimitive.Portal container={portalContainer}>\n <DropdownMenuPrimitive.Content\n className={cn(\n \"lb-root lb-portal lb-elevation lb-dropdown\",\n className\n )}\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n {...props}\n >\n {content}\n </DropdownMenuPrimitive.Content>\n </DropdownMenuPrimitive.Portal>\n </DropdownMenuPrimitive.Root>\n );\n}\n\nexport const DropdownItem = forwardRef<HTMLDivElement, DropdownItemProps>(\n ({ children, className, icon, ...props }, forwardedRef) => {\n return (\n <DropdownMenuPrimitive.DropdownMenuItem\n className={cn(\"lb-dropdown-item\", className)}\n {...props}\n ref={forwardedRef}\n >\n {icon ? (\n <span className=\"lb-dropdown-item-icon lb-icon-container\">\n {icon}\n </span>\n ) : null}\n {children ? (\n <span className=\"lb-dropdown-item-label\">{children}</span>\n ) : null}\n </DropdownMenuPrimitive.DropdownMenuItem>\n );\n }\n);\n\nexport const DropdownTrigger = DropdownMenuPrimitive.Trigger;\n"],"names":[],"mappings":";;;;;;;;;;;;AA6BO;AAAkB;AACvB;AACA;AACA;AACA;AACA;AACA;AAEF;AACE;AACA;AAEA;AACE;AAAuB;AAAtB;AACC;AACA;AACA;AACO;AAEN;AAAA;AAEC;AAAuB;AAAtB;AACY;AACT;AACA;AACF;AACY;AACM;AACd;AAEH;AAAA;AAEL;AAAA;AAAA;AAGN;AAEO;AAAqB;AAExB;AACE;AAAuB;AAAtB;AAC4C;AACvC;AACC;AAEJ;AAIG;AAGA;AAAA;AAAA;AACN;AAGN;AAEO;;;;"}
1
+ {"version":3,"file":"Dropdown.cjs","sources":["../../../src/components/internal/Dropdown.tsx"],"sourcesContent":["\"use client\";\n\nimport { DropdownMenu as DropdownMenuPrimitive } from \"radix-ui\";\nimport type { ReactNode } from \"react\";\nimport { forwardRef } from \"react\";\n\nimport { useLiveblocksUiConfig } from \"../../config\";\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../../constants\";\nimport { useOverrides } from \"../../overrides\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface DropdownProps\n extends Pick<\n DropdownMenuPrimitive.DropdownMenuProps,\n \"defaultOpen\" | \"open\" | \"onOpenChange\"\n >,\n Pick<DropdownMenuPrimitive.DropdownMenuTriggerProps, \"children\">,\n Omit<DropdownMenuPrimitive.DropdownMenuContentProps, \"content\"> {\n content: ReactNode;\n}\n\ninterface DropdownItemProps\n extends DropdownMenuPrimitive.DropdownMenuItemProps {\n icon?: ReactNode;\n}\n\nexport function Dropdown({\n children,\n content,\n defaultOpen,\n open,\n onOpenChange,\n className,\n ...props\n}: DropdownProps) {\n const $ = useOverrides();\n const { portalContainer } = useLiveblocksUiConfig();\n\n return (\n <DropdownMenuPrimitive.Root\n defaultOpen={defaultOpen}\n open={open}\n onOpenChange={onOpenChange}\n dir={$.dir}\n >\n {children}\n <DropdownMenuPrimitive.Portal container={portalContainer}>\n <DropdownMenuPrimitive.Content\n className={cn(\n \"lb-root lb-portal lb-elevation lb-dropdown\",\n className\n )}\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n updatePositionStrategy=\"always\"\n {...props}\n >\n {content}\n </DropdownMenuPrimitive.Content>\n </DropdownMenuPrimitive.Portal>\n </DropdownMenuPrimitive.Root>\n );\n}\n\nexport const DropdownItem = forwardRef<HTMLDivElement, DropdownItemProps>(\n ({ children, className, icon, ...props }, forwardedRef) => {\n return (\n <DropdownMenuPrimitive.DropdownMenuItem\n className={cn(\"lb-dropdown-item\", className)}\n {...props}\n ref={forwardedRef}\n >\n {icon ? (\n <span className=\"lb-dropdown-item-icon lb-icon-container\">\n {icon}\n </span>\n ) : null}\n {children ? (\n <span className=\"lb-dropdown-item-label\">{children}</span>\n ) : null}\n </DropdownMenuPrimitive.DropdownMenuItem>\n );\n }\n);\n\nexport const DropdownTrigger = DropdownMenuPrimitive.Trigger;\n"],"names":[],"mappings":";;;;;;;;;;;;AA6BO;AAAkB;AACvB;AACA;AACA;AACA;AACA;AACA;AAEF;AACE;AACA;AAEA;AACE;AAAuB;AAAtB;AACC;AACA;AACA;AACO;AAEN;AAAA;AAEC;AAAuB;AAAtB;AACY;AACT;AACA;AACF;AACY;AACM;AACK;AACnB;AAEH;AAAA;AAEL;AAAA;AAAA;AAGN;AAEO;AAAqB;AAExB;AACE;AAAuB;AAAtB;AAC4C;AACvC;AACC;AAEJ;AAIG;AAGA;AAAA;AAAA;AACN;AAGN;AAEO;;;;"}
@@ -37,6 +37,7 @@ function Dropdown({
37
37
  ),
38
38
  sideOffset: FLOATING_ELEMENT_SIDE_OFFSET,
39
39
  collisionPadding: FLOATING_ELEMENT_COLLISION_PADDING,
40
+ updatePositionStrategy: "always",
40
41
  ...props,
41
42
  children: content
42
43
  }