@liveblocks/react-ui 3.16.0-flow2 → 3.16.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.
@@ -12,7 +12,6 @@ var config = require('../config.cjs');
12
12
  require('../icons/index.cjs');
13
13
  var capitalize = require('../utils/capitalize.cjs');
14
14
  var cn = require('../utils/cn.cjs');
15
- var cursorSpring = require('../utils/cursor-spring.cjs');
16
15
  var Portal = require('../utils/Portal.cjs');
17
16
  var useInitial = require('../utils/use-initial.cjs');
18
17
  var useRefs = require('../utils/use-refs.cjs');
@@ -95,7 +94,6 @@ exports.User = User.User;
95
94
  exports.useLiveblocksUiConfig = config.useLiveblocksUiConfig;
96
95
  exports.capitalize = capitalize.capitalize;
97
96
  exports.cn = cn.cn;
98
- exports.makeCursorSpring = cursorSpring.makeCursorSpring;
99
97
  exports.Portal = Portal.Portal;
100
98
  exports.useInitial = useInitial.useInitial;
101
99
  exports.useRefs = useRefs.useRefs;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,5 +1,4 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as _liveblocks_core from '@liveblocks/core';
3
2
  import { Relax, AiTextPart, AiReasoningPart, AiChatMessage } from '@liveblocks/core';
4
3
  import * as react from 'react';
5
4
  import { ComponentProps, ReactNode, ComponentPropsWithoutRef, ElementType, ComponentType, Ref, RefCallback, FormEvent } from 'react';
@@ -495,17 +494,6 @@ declare function capitalize(string: string): string;
495
494
  */
496
495
  declare function cn(...args: (string | number | boolean | undefined | null)[]): string;
497
496
 
498
- type CursorCoordinates = {
499
- x: number;
500
- y: number;
501
- };
502
- declare function makeCursorSpring(): {
503
- get(): CursorCoordinates | null;
504
- set(point: CursorCoordinates | null): void;
505
- subscribe: (callback: (event: CursorCoordinates | null) => void) => _liveblocks_core.UnsubscribeCallback;
506
- dispose(): void;
507
- };
508
-
509
497
  declare const Portal: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & SlotProp & react.RefAttributes<HTMLDivElement>>;
510
498
 
511
499
  /**
@@ -738,4 +726,4 @@ declare namespace index {
738
726
  };
739
727
  }
740
728
 
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 };
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 };
@@ -1,5 +1,4 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as _liveblocks_core from '@liveblocks/core';
3
2
  import { Relax, AiTextPart, AiReasoningPart, AiChatMessage } from '@liveblocks/core';
4
3
  import * as react from 'react';
5
4
  import { ComponentProps, ReactNode, ComponentPropsWithoutRef, ElementType, ComponentType, Ref, RefCallback, FormEvent } from 'react';
@@ -495,17 +494,6 @@ declare function capitalize(string: string): string;
495
494
  */
496
495
  declare function cn(...args: (string | number | boolean | undefined | null)[]): string;
497
496
 
498
- type CursorCoordinates = {
499
- x: number;
500
- y: number;
501
- };
502
- declare function makeCursorSpring(): {
503
- get(): CursorCoordinates | null;
504
- set(point: CursorCoordinates | null): void;
505
- subscribe: (callback: (event: CursorCoordinates | null) => void) => _liveblocks_core.UnsubscribeCallback;
506
- dispose(): void;
507
- };
508
-
509
497
  declare const Portal: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & SlotProp & react.RefAttributes<HTMLDivElement>>;
510
498
 
511
499
  /**
@@ -738,4 +726,4 @@ declare namespace index {
738
726
  };
739
727
  }
740
728
 
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 };
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 };
@@ -10,7 +10,6 @@ export { useLiveblocksUiConfig } from '../config.js';
10
10
  import '../icons/index.js';
11
11
  export { capitalize } from '../utils/capitalize.js';
12
12
  export { cn } from '../utils/cn.js';
13
- export { makeCursorSpring } from '../utils/cursor-spring.js';
14
13
  export { Portal } from '../utils/Portal.js';
15
14
  export { useInitial } from '../utils/use-initial.js';
16
15
  export { useRefs } from '../utils/use-refs.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -369,6 +369,7 @@ const Comment = Object.assign(
369
369
  overrides: overrides$1,
370
370
  components: components$1,
371
371
  additionalContent,
372
+ body,
372
373
  avatar,
373
374
  author,
374
375
  date,
@@ -411,7 +412,7 @@ const Comment = Object.assign(
411
412
  []
412
413
  );
413
414
  const handleEditSubmit = react.useCallback(
414
- ({ body, attachments }, event) => {
415
+ ({ body: body2, attachments }, event) => {
415
416
  onCommentEdit?.(comment);
416
417
  if (event.isDefaultPrevented()) {
417
418
  return;
@@ -422,7 +423,7 @@ const Comment = Object.assign(
422
423
  editComment({
423
424
  commentId: comment.id,
424
425
  threadId: comment.threadId,
425
- body,
426
+ body: body2,
426
427
  attachments
427
428
  });
428
429
  },
@@ -550,26 +551,27 @@ const Comment = Object.assign(
550
551
  }
551
552
  );
552
553
  } else {
553
- content = comment.body ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
554
- /* @__PURE__ */ jsxRuntime.jsx(
555
- index.Body,
556
- {
557
- className: "lb-comment-body",
558
- id: bodyId,
559
- body: comment.body,
560
- components: {
561
- Mention: ({ mention }) => /* @__PURE__ */ jsxRuntime.jsx(
562
- CommentMention,
563
- {
564
- mention,
565
- onClick: (event) => onMentionClick?.(mention, event),
566
- overrides: overrides$1
567
- }
568
- ),
569
- Link: CommentLink
570
- }
554
+ const defaultBody = /* @__PURE__ */ jsxRuntime.jsx(
555
+ index.Body,
556
+ {
557
+ className: "lb-comment-body",
558
+ id: bodyId,
559
+ body: comment.body,
560
+ components: {
561
+ Mention: ({ mention }) => /* @__PURE__ */ jsxRuntime.jsx(
562
+ CommentMention,
563
+ {
564
+ mention,
565
+ onClick: (event) => onMentionClick?.(mention, event),
566
+ overrides: overrides$1
567
+ }
568
+ ),
569
+ Link: CommentLink
571
570
  }
572
- ),
571
+ }
572
+ );
573
+ content = comment.body ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
574
+ body === void 0 ? defaultBody : typeof body === "function" ? body({ comment, children: defaultBody }) : body,
573
575
  additionalContent,
574
576
  showAttachments && (mediaAttachments.length > 0 || fileAttachments.length > 0) ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lb-comment-attachments", children: [
575
577
  mediaAttachments.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lb-attachments", children: mediaAttachments.map((attachment) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -1 +1 @@
1
- {"version":3,"file":"Comment.cjs","sources":["../../src/components/Comment.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n assertNever,\n type BaseMetadata,\n type CommentAttachment,\n type CommentData,\n type CommentReaction as CommentReactionData,\n type DCM,\n type GroupMentionData,\n MENTION_CHARACTER,\n type MentionData,\n Permission,\n} from \"@liveblocks/core\";\nimport {\n useAddRoomCommentReaction,\n useDeleteRoomComment,\n useEditRoomComment,\n useRemoveRoomCommentReaction,\n useRoomAttachmentUrl,\n useRoomPermissions,\n} from \"@liveblocks/react/_private\";\nimport { Toggle as TogglePrimitive } from \"radix-ui\";\nimport type {\n ComponentProps,\n ComponentPropsWithoutRef,\n FormEvent,\n MouseEvent,\n PropsWithChildren,\n ReactNode,\n RefAttributes,\n SyntheticEvent,\n} from \"react\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport {\n ComponentsProvider,\n type GlobalComponents,\n useComponents,\n} from \"../components\";\nimport { CheckIcon } from \"../icons/Check\";\nimport { CrossIcon } from \"../icons/Cross\";\nimport { DeleteIcon } from \"../icons/Delete\";\nimport { EditIcon } from \"../icons/Edit\";\nimport { EllipsisIcon } from \"../icons/Ellipsis\";\nimport { EmojiPlusIcon } from \"../icons/EmojiPlus\";\nimport type {\n CommentOverrides,\n ComposerOverrides,\n GlobalOverrides,\n} from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport type { ComposerSubmitComment } from \"../primitives\";\nimport * as CommentPrimitive from \"../primitives/Comment\";\nimport type {\n CommentBodyLinkProps,\n CommentBodyMentionProps,\n CommentLinkProps,\n CommentMentionProps as CommentPrimitiveMentionProps,\n} from \"../primitives/Comment/types\";\nimport * as ComposerPrimitive from \"../primitives/Composer\";\nimport { Timestamp } from \"../primitives/Timestamp\";\nimport { useCurrentUserId } from \"../shared\";\nimport type { CommentAttachmentArgs } from \"../types\";\nimport { cn } from \"../utils/cn\";\nimport { download } from \"../utils/download\";\nimport { useIsGroupMentionMember } from \"../utils/use-group-mention\";\nimport { useRefs } from \"../utils/use-refs\";\nimport type { ComposerProps } from \"./Composer\";\nimport { Composer } from \"./Composer\";\nimport {\n FileAttachment,\n MediaAttachment,\n separateMediaAttachments,\n} from \"./internal/Attachment\";\nimport { Avatar } from \"./internal/Avatar\";\nimport { Button, CustomButton } from \"./internal/Button\";\nimport { Dropdown, DropdownItem, DropdownTrigger } from \"./internal/Dropdown\";\nimport { Emoji } from \"./internal/Emoji\";\nimport { EmojiPicker, EmojiPickerTrigger } from \"./internal/EmojiPicker\";\nimport { Group } from \"./internal/Group\";\nimport { List } from \"./internal/List\";\nimport { ShortcutTooltip, Tooltip, TooltipProvider } from \"./internal/Tooltip\";\nimport { User } from \"./internal/User\";\n\nconst REACTIONS_TRUNCATE = 5;\n\nexport interface CommentProps<CM extends BaseMetadata = DCM>\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /**\n * The comment to display.\n */\n comment: CommentData<CM>;\n\n /**\n * The comment's avatar.\n * Can be combined with `Comment.Avatar` to easily follow default styles.\n */\n avatar?: ReactNode;\n\n /**\n * The comment's author.\n * Can be combined with `Comment.Author` to easily follow default styles.\n */\n author?: ReactNode;\n\n /**\n * The comment's date.\n * Can be combined with `Comment.Date` to easily follow default styles,\n * or the `Timestamp` primitive for more control.\n */\n date?: ReactNode;\n\n /**\n * How to show or hide the actions.\n */\n showActions?: boolean | \"hover\";\n\n /**\n * Whether to show the comment if it was deleted. If set to `false`, it will render deleted comments as `null`.\n */\n showDeleted?: boolean;\n\n /**\n * Whether to show reactions.\n */\n showReactions?: boolean;\n\n /**\n * Whether to show attachments.\n */\n showAttachments?: boolean;\n\n /**\n * Whether to show the composer's formatting controls when editing the comment.\n */\n showComposerFormattingControls?: ComposerProps[\"showFormattingControls\"];\n\n /**\n * Whether to indent the comment's content.\n */\n indentContent?: boolean;\n\n /**\n * Additional content to display below the comment's body.\n */\n additionalContent?: ReactNode;\n\n /**\n * The event handler called when the comment is edited.\n */\n onCommentEdit?: (comment: CommentData) => void;\n\n /**\n * The event handler called when the comment is deleted.\n */\n onCommentDelete?: (comment: CommentData) => void;\n\n /**\n * The event handler called when clicking on the author.\n */\n onAuthorClick?: (userId: string, event: MouseEvent<HTMLElement>) => void;\n\n /**\n * The event handler called when clicking on a mention.\n */\n onMentionClick?: (\n mention: MentionData,\n event: MouseEvent<HTMLElement>\n ) => void;\n\n /**\n * The event handler called when clicking on a comment's attachment.\n */\n onAttachmentClick?: (\n args: CommentAttachmentArgs,\n event: MouseEvent<HTMLElement>\n ) => void;\n\n /**\n * Add (or change) items to display in the comment's dropdown.\n */\n dropdownItems?:\n | ReactNode\n | ((props: PropsWithChildren<{ comment: CommentData<CM> }>) => ReactNode);\n\n /**\n * Override the comment's content.\n */\n children?:\n | ReactNode\n | ((props: PropsWithChildren<{ comment: CommentData<CM> }>) => ReactNode);\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides & CommentOverrides & ComposerOverrides>;\n\n /**\n * Override the component's components.\n */\n components?: Partial<GlobalComponents>;\n\n /**\n * @internal\n */\n actions?: ReactNode;\n\n /**\n * @internal\n */\n actionsClassName?: string;\n\n /**\n * @internal\n */\n internalDropdownItems?: ReactNode;\n}\n\nexport interface CommentAvatarProps\n extends Omit<ComponentProps<\"div\">, \"children\"> {\n /**\n * The user ID to display the avatar for.\n */\n userId: string;\n}\n\nexport interface CommentAuthorProps\n extends Omit<ComponentProps<\"span\">, \"children\"> {\n /**\n * The user ID to display the author for.\n */\n userId: string;\n}\n\nexport interface CommentDateProps\n extends Omit<ComponentProps<\"span\">, \"children\"> {\n /**\n * The date to display.\n */\n date: Date | string | number;\n\n /**\n * The locale used when formatting the date.\n */\n locale?: string;\n}\n\nfunction CommentAvatar(props: CommentAvatarProps) {\n return <Avatar {...props} />;\n}\n\nfunction CommentAuthor(props: CommentAuthorProps) {\n return <User {...props} />;\n}\n\nfunction CommentDate({ locale, date, className, ...props }: CommentDateProps) {\n return (\n <Timestamp\n locale={locale}\n date={date}\n className={cn(\"lb-date\", className)}\n {...(props as Omit<ComponentProps<\"time\">, \"children\" | \"title\">)}\n />\n );\n}\n\nexport interface CommentDropdownItemProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onSelect\"> {\n /**\n * An optional icon displayed in this dropdown item.\n */\n icon?: ReactNode;\n\n /**\n * The event handler called when the dropdown item is selected.\n */\n onSelect?: (event: Event) => void;\n}\n\ninterface CommentReactionButtonProps\n extends ComponentPropsWithoutRef<typeof Button> {\n reaction: CommentReactionData;\n overrides?: Partial<GlobalOverrides & CommentOverrides>;\n}\n\ninterface CommentReactionProps extends ComponentPropsWithoutRef<\"button\"> {\n comment: CommentData;\n reaction: CommentReactionData;\n overrides?: Partial<GlobalOverrides & CommentOverrides>;\n}\n\ntype CommentNonInteractiveReactionProps = Omit<CommentReactionProps, \"comment\">;\n\ninterface CommentAttachmentProps extends ComponentProps<typeof FileAttachment> {\n attachment: CommentAttachment;\n onAttachmentClick?: CommentProps[\"onAttachmentClick\"];\n}\n\ninterface CommentMentionProps\n extends CommentBodyMentionProps,\n CommentPrimitiveMentionProps {\n overrides?: CommentProps[\"overrides\"];\n}\n\nfunction CommentUserMention({\n mention,\n className,\n ...props\n}: CommentMentionProps) {\n const currentId = useCurrentUserId();\n\n return (\n <CommentPrimitive.Mention\n className={cn(\"lb-mention lb-comment-mention\", className)}\n data-self={mention.id === currentId ? \"\" : undefined}\n {...props}\n >\n <span className=\"lb-mention-symbol\">{MENTION_CHARACTER}</span>\n <User userId={mention.id} />\n </CommentPrimitive.Mention>\n );\n}\n\nfunction CommentGroupMention({\n mention,\n className,\n ...props\n}: CommentMentionProps) {\n const isMember = useIsGroupMentionMember(mention as GroupMentionData);\n\n return (\n <CommentPrimitive.Mention\n className={cn(\"lb-mention lb-comment-mention\", className)}\n data-self={isMember ? \"\" : undefined}\n {...props}\n >\n <span className=\"lb-mention-symbol\">{MENTION_CHARACTER}</span>\n <Group groupId={mention.id} />\n </CommentPrimitive.Mention>\n );\n}\n\nexport function CommentMention({ mention, ...props }: CommentMentionProps) {\n switch (mention.kind) {\n case \"user\":\n return <CommentUserMention mention={mention} {...props} />;\n\n case \"group\":\n return <CommentGroupMention mention={mention} {...props} />;\n\n default:\n return assertNever(mention, \"Unhandled mention kind\");\n }\n}\n\nexport function CommentLink({\n href,\n children,\n className,\n ...props\n}: CommentBodyLinkProps & CommentLinkProps) {\n const { Anchor } = useComponents();\n\n return (\n <CommentPrimitive.Link\n className={cn(\"lb-comment-link\", className)}\n href={href}\n {...props}\n asChild\n >\n <Anchor {...props}>{children}</Anchor>\n </CommentPrimitive.Link>\n );\n}\n\nexport function CommentNonInteractiveLink({\n href: _href,\n children,\n className,\n ...props\n}: CommentBodyLinkProps & CommentLinkProps) {\n return (\n <span className={cn(\"lb-comment-link\", className)} {...props}>\n {children}\n </span>\n );\n}\n\nconst CommentReactionButton = forwardRef<\n HTMLButtonElement,\n CommentReactionButtonProps\n>(({ reaction, overrides, className, ...props }, forwardedRef) => {\n const $ = useOverrides(overrides);\n return (\n <CustomButton\n className={cn(\"lb-comment-reaction\", className)}\n variant=\"outline\"\n aria-label={$.COMMENT_REACTION_DESCRIPTION(\n reaction.emoji,\n reaction.users.length\n )}\n {...props}\n ref={forwardedRef}\n >\n <Emoji className=\"lb-comment-reaction-emoji\" emoji={reaction.emoji} />\n <span className=\"lb-comment-reaction-count\">{reaction.users.length}</span>\n </CustomButton>\n );\n});\n\nexport const CommentReaction = forwardRef<\n HTMLButtonElement,\n CommentReactionProps\n>(({ comment, reaction, overrides, disabled, ...props }, forwardedRef) => {\n const addReaction = useAddRoomCommentReaction(comment.roomId);\n const removeReaction = useRemoveRoomCommentReaction(comment.roomId);\n const currentId = useCurrentUserId();\n const isActive = useMemo(() => {\n return reaction.users.some((users) => users.id === currentId);\n }, [currentId, reaction]);\n const $ = useOverrides(overrides);\n const tooltipContent = useMemo(\n () => (\n <span>\n {$.COMMENT_REACTION_LIST(\n <List\n values={reaction.users.map((users) => (\n <User key={users.id} userId={users.id} replaceSelf />\n ))}\n formatRemaining={$.LIST_REMAINING_USERS}\n truncate={REACTIONS_TRUNCATE}\n locale={$.locale}\n />,\n reaction.emoji,\n reaction.users.length\n )}\n </span>\n ),\n [$, reaction]\n );\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n const handlePressedChange = useCallback(\n (isPressed: boolean) => {\n if (isPressed) {\n addReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji: reaction.emoji,\n });\n } else {\n removeReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji: reaction.emoji,\n });\n }\n },\n [addReaction, comment.threadId, comment.id, reaction.emoji, removeReaction]\n );\n\n return (\n <Tooltip\n content={tooltipContent}\n multiline\n className=\"lb-comment-reaction-tooltip\"\n >\n <TogglePrimitive.Root\n asChild\n pressed={isActive}\n onPressedChange={handlePressedChange}\n onClick={stopPropagation}\n disabled={disabled}\n ref={forwardedRef}\n >\n <CommentReactionButton\n data-self={isActive ? \"\" : undefined}\n reaction={reaction}\n overrides={overrides}\n {...props}\n />\n </TogglePrimitive.Root>\n </Tooltip>\n );\n});\n\nexport const CommentNonInteractiveReaction = forwardRef<\n HTMLButtonElement,\n CommentNonInteractiveReactionProps\n>(({ reaction, overrides, ...props }, forwardedRef) => {\n const currentId = useCurrentUserId();\n const isActive = useMemo(() => {\n return reaction.users.some((users) => users.id === currentId);\n }, [currentId, reaction]);\n\n return (\n <CommentReactionButton\n disableable={false}\n data-self={isActive ? \"\" : undefined}\n reaction={reaction}\n overrides={overrides}\n {...props}\n ref={forwardedRef}\n />\n );\n});\n\nfunction openAttachment({ attachment, url }: CommentAttachmentArgs) {\n // Open the attachment in a new tab if the attachment is a PDF,\n // an image, a video, or audio. Otherwise, download it.\n if (\n attachment.mimeType === \"application/pdf\" ||\n attachment.mimeType.startsWith(\"image/\") ||\n attachment.mimeType.startsWith(\"video/\") ||\n attachment.mimeType.startsWith(\"audio/\")\n ) {\n window.open(url, \"_blank\");\n } else {\n download(url, attachment.name);\n }\n}\n\nfunction CommentMediaAttachment({\n attachment,\n onAttachmentClick,\n roomId,\n className,\n overrides,\n ...props\n}: CommentAttachmentProps & {\n roomId: string;\n}) {\n const { url } = useRoomAttachmentUrl(attachment.id, roomId);\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLElement>) => {\n if (!url) {\n return;\n }\n\n const args: CommentAttachmentArgs = { attachment, url };\n\n onAttachmentClick?.(args, event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n openAttachment(args);\n },\n [attachment, onAttachmentClick, url]\n );\n\n return (\n <MediaAttachment\n className={cn(\"lb-comment-attachment\", className)}\n {...props}\n attachment={attachment}\n overrides={overrides}\n onClick={url ? handleClick : undefined}\n roomId={roomId}\n />\n );\n}\n\nfunction CommentFileAttachment({\n attachment,\n onAttachmentClick,\n roomId,\n className,\n overrides,\n ...props\n}: CommentAttachmentProps & {\n roomId: string;\n}) {\n const { url } = useRoomAttachmentUrl(attachment.id, roomId);\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLElement>) => {\n if (!url) {\n return;\n }\n\n const args: CommentAttachmentArgs = { attachment, url };\n\n onAttachmentClick?.(args, event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n openAttachment(args);\n },\n [attachment, onAttachmentClick, url]\n );\n\n return (\n <FileAttachment\n className={cn(\"lb-comment-attachment\", className)}\n {...props}\n attachment={attachment}\n overrides={overrides}\n onClick={url ? handleClick : undefined}\n roomId={roomId}\n />\n );\n}\n\nexport function CommentNonInteractiveFileAttachment({\n className,\n ...props\n}: CommentAttachmentProps) {\n return (\n <FileAttachment\n className={cn(\"lb-comment-attachment\", className)}\n allowMediaPreview={false}\n {...props}\n />\n );\n}\n\nconst CommentDropdownItem = forwardRef<\n HTMLDivElement,\n CommentDropdownItemProps\n>(({ children, icon, onSelect, onClick, ...props }, forwardedRef) => {\n const handleClick = useCallback(\n (event: MouseEvent<HTMLDivElement>) => {\n onClick?.(event);\n\n if (!event.isDefaultPrevented()) {\n event.stopPropagation();\n }\n },\n [onClick]\n );\n\n return (\n <DropdownItem\n icon={icon}\n onSelect={onSelect}\n onClick={handleClick}\n {...props}\n ref={forwardedRef}\n >\n {children}\n </DropdownItem>\n );\n});\n\n/**\n * Displays a single comment.\n *\n * @example\n * <>\n * {thread.comments.map((comment) => (\n * <Comment key={comment.id} comment={comment} />\n * ))}\n * </>\n */\nexport const Comment = Object.assign(\n forwardRef<HTMLDivElement, CommentProps>(\n (\n {\n comment,\n indentContent = true,\n showDeleted,\n showActions = \"hover\",\n showReactions = true,\n showAttachments = true,\n showComposerFormattingControls = true,\n onAuthorClick,\n onMentionClick,\n onAttachmentClick,\n onCommentEdit,\n onCommentDelete,\n dropdownItems,\n overrides,\n components,\n additionalContent,\n avatar,\n author,\n date,\n className,\n actions,\n actionsClassName,\n internalDropdownItems,\n children,\n ...props\n },\n forwardedRef\n ) => {\n const bodyId = `${comment.id}:body`;\n const ref = useRef<HTMLDivElement>(null);\n const mergedRefs = useRefs(forwardedRef, ref);\n const currentUserId = useCurrentUserId();\n const deleteComment = useDeleteRoomComment(comment.roomId);\n const editComment = useEditRoomComment(comment.roomId);\n const addReaction = useAddRoomCommentReaction(comment.roomId);\n const removeReaction = useRemoveRoomCommentReaction(comment.roomId);\n const $ = useOverrides(overrides);\n const [isEditing, setEditing] = useState(false);\n const [isTarget, setTarget] = useState(false);\n const [isMoreActionOpen, setMoreActionOpen] = useState(false);\n const [isReactionActionOpen, setReactionActionOpen] = useState(false);\n const { mediaAttachments, fileAttachments } = useMemo(() => {\n return separateMediaAttachments(comment.attachments);\n }, [comment.attachments]);\n\n const permissions = useRoomPermissions(comment.roomId);\n const canComment =\n permissions.size > 0\n ? permissions.has(Permission.CommentsWrite) ||\n permissions.has(Permission.Write)\n : true;\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n const handleEdit = useCallback(() => {\n setEditing(true);\n }, []);\n\n const handleEditCancel = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n setEditing(false);\n },\n []\n );\n\n const handleEditSubmit = useCallback(\n (\n { body, attachments }: ComposerSubmitComment,\n event: FormEvent<HTMLFormElement>\n ) => {\n // TODO: Add a way to preventDefault from within this callback, to override the default behavior (e.g. showing a confirmation dialog)\n onCommentEdit?.(comment);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n event.stopPropagation();\n event.preventDefault();\n\n setEditing(false);\n editComment({\n commentId: comment.id,\n threadId: comment.threadId,\n body,\n attachments,\n });\n },\n [comment, editComment, onCommentEdit]\n );\n\n const handleDelete = useCallback(() => {\n // TODO: Add a way to preventDefault from within this callback, to override the default behavior (e.g. showing a confirmation dialog)\n onCommentDelete?.(comment);\n\n deleteComment({\n commentId: comment.id,\n threadId: comment.threadId,\n });\n }, [comment, deleteComment, onCommentDelete]);\n\n const handleAuthorClick = useCallback(\n (event: MouseEvent<HTMLElement>) => {\n onAuthorClick?.(comment.userId, event);\n },\n [comment.userId, onAuthorClick]\n );\n\n const handleReactionSelect = useCallback(\n (emoji: string) => {\n const reactionIndex = comment.reactions.findIndex(\n (reaction) => reaction.emoji === emoji\n );\n\n if (\n reactionIndex >= 0 &&\n currentUserId &&\n comment.reactions[reactionIndex]?.users.some(\n (user) => user.id === currentUserId\n )\n ) {\n removeReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji,\n });\n } else {\n addReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji,\n });\n }\n },\n [\n addReaction,\n comment.id,\n comment.reactions,\n comment.threadId,\n removeReaction,\n currentUserId,\n ]\n );\n\n useEffect(() => {\n const isWindowDefined = typeof window !== \"undefined\";\n if (!isWindowDefined) return;\n\n const hash = window.location.hash;\n const commentId = hash.slice(1);\n\n if (commentId === comment.id) {\n setTarget(true);\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (!showDeleted && !comment.body) {\n return null;\n }\n\n const commentDropdownItems =\n comment.userId === currentUserId ? (\n <>\n <CommentDropdownItem onSelect={handleEdit} icon={<EditIcon />}>\n {$.COMMENT_EDIT}\n </CommentDropdownItem>\n <CommentDropdownItem onSelect={handleDelete} icon={<DeleteIcon />}>\n {$.COMMENT_DELETE}\n </CommentDropdownItem>\n </>\n ) : null;\n const defaultDropdownItems =\n internalDropdownItems || commentDropdownItems ? (\n <>\n {internalDropdownItems}\n {commentDropdownItems}\n </>\n ) : null;\n\n const dropdownContent =\n typeof dropdownItems === \"function\" ? (\n dropdownItems({ children: defaultDropdownItems, comment })\n ) : defaultDropdownItems || dropdownItems ? (\n <>\n {defaultDropdownItems}\n {dropdownItems}\n </>\n ) : null;\n\n let content: ReactNode;\n\n if (isEditing) {\n content = (\n <Composer\n className=\"lb-comment-composer\"\n onComposerSubmit={handleEditSubmit}\n defaultValue={comment.body}\n defaultAttachments={comment.attachments}\n autoFocus\n showAttribution={false}\n showAttachments={showAttachments}\n showFormattingControls={showComposerFormattingControls}\n actions={\n <>\n <Tooltip\n content={$.COMMENT_EDIT_COMPOSER_CANCEL}\n aria-label={$.COMMENT_EDIT_COMPOSER_CANCEL}\n >\n <Button\n className=\"lb-composer-action\"\n onClick={handleEditCancel}\n icon={<CrossIcon />}\n />\n </Tooltip>\n <ShortcutTooltip\n content={$.COMMENT_EDIT_COMPOSER_SAVE}\n shortcut=\"Enter\"\n >\n <ComposerPrimitive.Submit asChild>\n <Button\n variant=\"primary\"\n className=\"lb-composer-action\"\n onClick={stopPropagation}\n aria-label={$.COMMENT_EDIT_COMPOSER_SAVE}\n icon={<CheckIcon />}\n />\n </ComposerPrimitive.Submit>\n </ShortcutTooltip>\n </>\n }\n overrides={{\n COMPOSER_PLACEHOLDER: $.COMMENT_EDIT_COMPOSER_PLACEHOLDER,\n }}\n roomId={comment.roomId}\n />\n );\n } else {\n content = comment.body ? (\n <>\n <CommentPrimitive.Body\n className=\"lb-comment-body\"\n id={bodyId}\n body={comment.body}\n components={{\n Mention: ({ mention }) => (\n <CommentMention\n mention={mention}\n onClick={(event) => onMentionClick?.(mention, event)}\n overrides={overrides}\n />\n ),\n Link: CommentLink,\n }}\n />\n {additionalContent}\n {showAttachments &&\n (mediaAttachments.length > 0 || fileAttachments.length > 0) ? (\n <div className=\"lb-comment-attachments\">\n {mediaAttachments.length > 0 ? (\n <div className=\"lb-attachments\">\n {mediaAttachments.map((attachment) => (\n <CommentMediaAttachment\n key={attachment.id}\n attachment={attachment}\n overrides={overrides}\n onAttachmentClick={onAttachmentClick}\n roomId={comment.roomId}\n />\n ))}\n </div>\n ) : null}\n {fileAttachments.length > 0 ? (\n <div className=\"lb-attachments\">\n {fileAttachments.map((attachment) => (\n <CommentFileAttachment\n key={attachment.id}\n attachment={attachment}\n overrides={overrides}\n onAttachmentClick={onAttachmentClick}\n roomId={comment.roomId}\n />\n ))}\n </div>\n ) : null}\n </div>\n ) : null}\n {showReactions && comment.reactions.length > 0 && (\n <div className=\"lb-comment-reactions\">\n {comment.reactions.map((reaction) => (\n <CommentReaction\n key={reaction.emoji}\n comment={comment}\n reaction={reaction}\n overrides={overrides}\n disabled={!canComment}\n />\n ))}\n {canComment ? (\n <EmojiPicker onEmojiSelect={handleReactionSelect}>\n <Tooltip content={$.COMMENT_ADD_REACTION}>\n <EmojiPickerTrigger asChild>\n <Button\n className=\"lb-comment-reaction lb-comment-reaction-add\"\n variant=\"outline\"\n onClick={stopPropagation}\n aria-label={$.COMMENT_ADD_REACTION}\n icon={<EmojiPlusIcon />}\n />\n </EmojiPickerTrigger>\n </Tooltip>\n </EmojiPicker>\n ) : null}\n </div>\n )}\n </>\n ) : (\n <div className=\"lb-comment-body\">\n <p className=\"lb-comment-deleted\">{$.COMMENT_DELETED}</p>\n </div>\n );\n\n content =\n typeof children === \"function\"\n ? children({ comment, children: content })\n : (children ?? content);\n }\n\n return (\n <TooltipProvider>\n <ComponentsProvider components={components}>\n <div\n role=\"article\"\n id={comment.id}\n className={cn(\n \"lb-root lb-comment\",\n indentContent && \"lb-comment:indent-content\",\n showActions === \"hover\" && \"lb-comment:show-actions-hover\",\n (isMoreActionOpen || isReactionActionOpen) &&\n \"lb-comment:action-open\",\n className\n )}\n data-deleted={!comment.body ? \"\" : undefined}\n data-editing={isEditing ? \"\" : undefined}\n // In some cases, `:target` doesn't work as expected so we also define it manually.\n data-target={isTarget ? \"\" : undefined}\n aria-labelledby={bodyId}\n dir={$.dir}\n {...props}\n ref={mergedRefs}\n >\n <div className=\"lb-comment-header\">\n <div className=\"lb-comment-details\">\n {avatar ? (\n <div\n className=\"lb-comment-avatar\"\n onClick={handleAuthorClick}\n >\n {avatar}\n </div>\n ) : (\n <Avatar\n className=\"lb-comment-avatar\"\n userId={comment.userId}\n onClick={handleAuthorClick}\n />\n )}\n <span className=\"lb-comment-details-labels\">\n {author ? (\n <span\n className=\"lb-comment-author\"\n onClick={handleAuthorClick}\n >\n {author}\n </span>\n ) : (\n <User\n className=\"lb-comment-author\"\n userId={comment.userId}\n onClick={handleAuthorClick}\n />\n )}\n {date ? (\n <span className=\"lb-comment-date\">{date}</span>\n ) : (\n <span className=\"lb-comment-date\">\n <CommentDate\n locale={$.locale}\n date={comment.createdAt}\n className=\"lb-comment-date-created\"\n />\n {comment.editedAt && comment.body && (\n <>\n {\" \"}\n <span className=\"lb-comment-date-edited\">\n {$.COMMENT_EDITED}\n </span>\n </>\n )}\n </span>\n )}\n </span>\n </div>\n {showActions && !isEditing && (\n <div className={cn(\"lb-comment-actions\", actionsClassName)}>\n {actions ?? null}\n {showReactions && canComment ? (\n <EmojiPicker\n onEmojiSelect={handleReactionSelect}\n onOpenChange={setReactionActionOpen}\n >\n <Tooltip content={$.COMMENT_ADD_REACTION}>\n <EmojiPickerTrigger asChild>\n <Button\n className=\"lb-comment-action\"\n onClick={stopPropagation}\n aria-label={$.COMMENT_ADD_REACTION}\n icon={<EmojiPlusIcon />}\n />\n </EmojiPickerTrigger>\n </Tooltip>\n </EmojiPicker>\n ) : null}\n {dropdownContent ? (\n <Dropdown\n open={isMoreActionOpen}\n onOpenChange={setMoreActionOpen}\n align=\"end\"\n content={dropdownContent}\n >\n <Tooltip content={$.COMMENT_MORE}>\n <DropdownTrigger asChild>\n <Button\n className=\"lb-comment-action\"\n disabled={!comment.body}\n onClick={stopPropagation}\n aria-label={$.COMMENT_MORE}\n icon={<EllipsisIcon />}\n />\n </DropdownTrigger>\n </Tooltip>\n </Dropdown>\n ) : null}\n </div>\n )}\n </div>\n <div className=\"lb-comment-content\">{content}</div>\n </div>\n </ComponentsProvider>\n </TooltipProvider>\n );\n }\n ) as <CM extends BaseMetadata = DCM>(\n props: CommentProps<CM> & RefAttributes<HTMLDivElement>\n ) => JSX.Element,\n {\n /**\n * Displays a dropdown item in the comment's dropdown.\n */\n DropdownItem: CommentDropdownItem,\n\n /**\n * Displays a comment's avatar.\n */\n Avatar: CommentAvatar,\n\n /**\n * Displays a comment's author.\n */\n Author: CommentAuthor,\n\n /**\n * Displays a comment's date.\n */\n Date: CommentDate,\n }\n);\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4FA;AAmKA;AACE;AACF;AAEA;AACE;AACF;AAEA;AACE;AACE;AAAC;AAAA;AACC;AACA;AACkC;AAC7B;AAAA;AAGX;AAwCA;AAA4B;AAC1B;AACA;AAEF;AACE;AAEA;AACE;AAAkB;AAAjB;AACyD;AACb;AACvC;AAEJ;AAAuD;AAC7B;AAAA;AAAA;AAGhC;AAEA;AAA6B;AAC3B;AACA;AAEF;AACE;AAEA;AACE;AAAkB;AAAjB;AACyD;AAC7B;AACvB;AAEJ;AAAuD;AAC3B;AAAA;AAAA;AAGlC;AAEO;AACL;AAAsB;AAElB;AAAwD;AAGxD;AAAyD;AAGzD;AAAoD;AAE1D;AAEO;AAAqB;AAC1B;AACA;AACA;AAEF;AACE;AAEA;AACE;AAAkB;AAAjB;AAC2C;AAC1C;AACI;AACG;AAEsB;AAAA;AAGnC;AAEO;AAAmC;AAClC;AACN;AACA;AAEF;AACE;AAKF;AAEA;AAIE;AACA;AACE;AAAC;AAAA;AAC+C;AACtC;AACM;AACH;AACM;AACjB;AACI;AACC;AAEL;AAAoE;AACD;AAAA;AAAA;AAGzE;AAEa;AAIX;AACA;AACA;AACA;AACE;AAA4D;AAE9D;AACA;AAAuB;AAGd;AACD;AAAC;AAAA;AAGE;AACkB;AACT;AACA;AAAA;AACZ;AACS;AACM;AAEnB;AAEU;AAGd;AACE;AAAsB;AAGxB;AAA4B;AAExB;AACE;AAAY;AACQ;AACC;AACH;AACjB;AAED;AAAe;AACK;AACC;AACH;AACjB;AACH;AACF;AAC0E;AAG5E;AACE;AAAC;AAAA;AACU;AACA;AACC;AAEV;AAAiB;AAAhB;AACQ;AACE;AACQ;AACR;AACT;AACK;AAEL;AAAC;AAAA;AAC4B;AAC3B;AACA;AACI;AAAA;AACN;AAAA;AACF;AAAA;AAGN;AAEa;AAIX;AACA;AACE;AAA4D;AAG9D;AACE;AAAC;AAAA;AACc;AACc;AAC3B;AACA;AACI;AACC;AAAA;AAGX;AAEA;AAGE;AAME;AAAyB;AAEzB;AAA6B;AAEjC;AAEA;AAAgC;AAC9B;AACA;AACA;AACA;AACA;AAEF;AAGE;AAEA;AAAoB;AAEhB;AACE;AAAA;AAGF;AAEA;AAEA;AACE;AAAA;AAGF;AAAmB;AACrB;AACmC;AAGrC;AACE;AAAC;AAAA;AACiD;AAC5C;AACJ;AACA;AAC6B;AAC7B;AAAA;AAGN;AAEA;AAA+B;AAC7B;AACA;AACA;AACA;AACA;AAEF;AAGE;AAEA;AAAoB;AAEhB;AACE;AAAA;AAGF;AAEA;AAEA;AACE;AAAA;AAGF;AAAmB;AACrB;AACmC;AAGrC;AACE;AAAC;AAAA;AACiD;AAC5C;AACJ;AACA;AAC6B;AAC7B;AAAA;AAGN;AAEO;AAA6C;AAClD;AAEF;AACE;AACE;AAAC;AAAA;AACiD;AAC7B;AACf;AAAA;AAGV;AAEA;AAIE;AAAoB;AAEhB;AAEA;AACE;AAAsB;AACxB;AACF;AACQ;AAGV;AACE;AAAC;AAAA;AACC;AACA;AACS;AACL;AACC;AAEJ;AAAA;AAGP;AAYO;AAAuB;AAC5B;AAEI;AACE;AACgB;AAChB;AACc;AACE;AACE;AACe;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACG;AAIL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACE;AAAmD;AAGrD;AACA;AAMA;AACE;AAAsB;AAGxB;AACE;AAAe;AAGjB;AAAyB;AAErB;AACA;AAAgB;AAClB;AACC;AAGH;AAAyB;AAMrB;AAEA;AACE;AAAA;AAGF;AACA;AAEA;AACA;AAAY;AACS;AACD;AAClB;AACA;AACD;AACH;AACoC;AAGtC;AAEE;AAEA;AAAc;AACO;AACD;AACnB;AAGH;AAA0B;AAEtB;AAAqC;AACvC;AAC8B;AAGhC;AAA6B;AAEzB;AAAwC;AACL;AAGnC;AAG0C;AAChB;AAGxB;AAAe;AACK;AACC;AACnB;AACD;AAED;AAAY;AACQ;AACC;AACnB;AACD;AACH;AACF;AACA;AACE;AACQ;AACA;AACA;AACR;AACA;AACF;AAGF;AACE;AACA;AAAsB;AAEtB;AACA;AAEA;AACE;AAAc;AAChB;AAGF;AACE;AAAO;AAGT;AAGM;AAEA;AAGA;AAGN;AAGO;AAAA;AACA;AAIP;AAKO;AAAA;AACA;AAIP;AAEA;AACE;AACE;AAAC;AAAA;AACW;AACQ;AACI;AACM;AACnB;AACQ;AACjB;AACwB;AAGpB;AAAA;AAAC;AAAA;AACY;AACG;AAEd;AAAC;AAAA;AACW;AACD;AACQ;AAAA;AACnB;AAAA;AACF;AACA;AAAC;AAAA;AACY;AACF;AAGP;AAAC;AAAA;AACS;AACE;AACD;AACK;AACG;AAAA;AAErB;AAAA;AACF;AACF;AAES;AACe;AAC1B;AACgB;AAAA;AAClB;AAGF;AAEI;AAAA;AAAkB;AAAjB;AACW;AACN;AACU;AACF;AAER;AAAC;AAAA;AACC;AACmD;AACnD;AAAA;AACF;AAEI;AACR;AAAA;AACF;AACC;AAII;AAGK;AAAC;AAAA;AAEC;AACA;AACA;AACgB;AAAA;AAJA;AAQpB;AAIE;AAAC;AAAA;AAEC;AACA;AACA;AACgB;AAAA;AAJA;AAQpB;AAEJ;AAGC;AACC;AAAC;AAAA;AAEC;AACA;AACA;AACW;AAAA;AAJG;AAMjB;AAKO;AAAC;AAAA;AACW;AACF;AACC;AACK;AACO;AAAA;AAK3B;AACN;AASN;AAGmB;AAGrB;AAGM;AAAC;AAAA;AACM;AACO;AACD;AACT;AACiB;AACU;AAEzB;AACF;AACF;AACmC;AACJ;AAEF;AACZ;AACV;AACH;AACC;AAEL;AACE;AACG;AACC;AAAC;AAAA;AACW;AACD;AAER;AAAA;AAGH;AAAC;AAAA;AACW;AACM;AACP;AAAA;AACX;AAGC;AACC;AAAC;AAAA;AACW;AACD;AAER;AAAA;AAGH;AAAC;AAAA;AACW;AACM;AACP;AAAA;AACX;AAME;AAAA;AAAC;AAAA;AACW;AACI;AACJ;AAAA;AACZ;AAGK;AAAA;AAGD;AACF;AAEJ;AAEJ;AACF;AAGK;AAAW;AAEV;AAAC;AAAA;AACgB;AACD;AAIV;AAAC;AAAA;AACW;AACD;AACK;AACO;AAAA;AAG3B;AAAA;AAEA;AAEF;AAAC;AAAA;AACO;AACQ;AACR;AACG;AAIL;AAAC;AAAA;AACW;AACS;AACV;AACK;AACM;AAAA;AAG1B;AAAA;AAEA;AACN;AAEJ;AAC6C;AAAA;AAAA;AAGnD;AAEJ;AACF;AAGA;AAAA;AAAA;AAAA;AAIgB;AAAA;AAAA;AAAA;AAKN;AAAA;AAAA;AAAA;AAKA;AAAA;AAAA;AAAA;AAKF;AAEV;;;;;;;;"}
1
+ {"version":3,"file":"Comment.cjs","sources":["../../src/components/Comment.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n assertNever,\n type BaseMetadata,\n type CommentAttachment,\n type CommentData,\n type CommentReaction as CommentReactionData,\n type DCM,\n type GroupMentionData,\n MENTION_CHARACTER,\n type MentionData,\n Permission,\n} from \"@liveblocks/core\";\nimport {\n useAddRoomCommentReaction,\n useDeleteRoomComment,\n useEditRoomComment,\n useRemoveRoomCommentReaction,\n useRoomAttachmentUrl,\n useRoomPermissions,\n} from \"@liveblocks/react/_private\";\nimport { Toggle as TogglePrimitive } from \"radix-ui\";\nimport type {\n ComponentProps,\n ComponentPropsWithoutRef,\n FormEvent,\n MouseEvent,\n PropsWithChildren,\n ReactNode,\n RefAttributes,\n SyntheticEvent,\n} from \"react\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport {\n ComponentsProvider,\n type GlobalComponents,\n useComponents,\n} from \"../components\";\nimport { CheckIcon } from \"../icons/Check\";\nimport { CrossIcon } from \"../icons/Cross\";\nimport { DeleteIcon } from \"../icons/Delete\";\nimport { EditIcon } from \"../icons/Edit\";\nimport { EllipsisIcon } from \"../icons/Ellipsis\";\nimport { EmojiPlusIcon } from \"../icons/EmojiPlus\";\nimport type {\n CommentOverrides,\n ComposerOverrides,\n GlobalOverrides,\n} from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport type { ComposerSubmitComment } from \"../primitives\";\nimport * as CommentPrimitive from \"../primitives/Comment\";\nimport type {\n CommentBodyLinkProps,\n CommentBodyMentionProps,\n CommentLinkProps,\n CommentMentionProps as CommentPrimitiveMentionProps,\n} from \"../primitives/Comment/types\";\nimport * as ComposerPrimitive from \"../primitives/Composer\";\nimport { Timestamp } from \"../primitives/Timestamp\";\nimport { useCurrentUserId } from \"../shared\";\nimport type { CommentAttachmentArgs } from \"../types\";\nimport { cn } from \"../utils/cn\";\nimport { download } from \"../utils/download\";\nimport { useIsGroupMentionMember } from \"../utils/use-group-mention\";\nimport { useRefs } from \"../utils/use-refs\";\nimport type { ComposerProps } from \"./Composer\";\nimport { Composer } from \"./Composer\";\nimport {\n FileAttachment,\n MediaAttachment,\n separateMediaAttachments,\n} from \"./internal/Attachment\";\nimport { Avatar } from \"./internal/Avatar\";\nimport { Button, CustomButton } from \"./internal/Button\";\nimport { Dropdown, DropdownItem, DropdownTrigger } from \"./internal/Dropdown\";\nimport { Emoji } from \"./internal/Emoji\";\nimport { EmojiPicker, EmojiPickerTrigger } from \"./internal/EmojiPicker\";\nimport { Group } from \"./internal/Group\";\nimport { List } from \"./internal/List\";\nimport { ShortcutTooltip, Tooltip, TooltipProvider } from \"./internal/Tooltip\";\nimport { User } from \"./internal/User\";\n\nconst REACTIONS_TRUNCATE = 5;\n\nexport interface CommentProps<CM extends BaseMetadata = DCM>\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /**\n * The comment to display.\n */\n comment: CommentData<CM>;\n\n /**\n * The comment's avatar.\n * Can be combined with `Comment.Avatar` to easily follow default styles.\n */\n avatar?: ReactNode;\n\n /**\n * The comment's author.\n * Can be combined with `Comment.Author` to easily follow default styles.\n */\n author?: ReactNode;\n\n /**\n * The comment's date.\n * Can be combined with `Comment.Date` to easily follow default styles,\n * or the `Timestamp` primitive for more control.\n */\n date?: ReactNode;\n\n /**\n * How to show or hide the actions.\n */\n showActions?: boolean | \"hover\";\n\n /**\n * Whether to show the comment if it was deleted. If set to `false`, it will render deleted comments as `null`.\n */\n showDeleted?: boolean;\n\n /**\n * Whether to show reactions.\n */\n showReactions?: boolean;\n\n /**\n * Whether to show attachments.\n */\n showAttachments?: boolean;\n\n /**\n * Whether to show the composer's formatting controls when editing the comment.\n */\n showComposerFormattingControls?: ComposerProps[\"showFormattingControls\"];\n\n /**\n * Whether to indent the comment's content.\n */\n indentContent?: boolean;\n\n /**\n * Additional content to display below the comment's body.\n */\n additionalContent?: ReactNode;\n\n /**\n * Override the comment's body.\n */\n body?:\n | ReactNode\n | ((props: PropsWithChildren<{ comment: CommentData<CM> }>) => ReactNode);\n\n /**\n * The event handler called when the comment is edited.\n */\n onCommentEdit?: (comment: CommentData) => void;\n\n /**\n * The event handler called when the comment is deleted.\n */\n onCommentDelete?: (comment: CommentData) => void;\n\n /**\n * The event handler called when clicking on the author.\n */\n onAuthorClick?: (userId: string, event: MouseEvent<HTMLElement>) => void;\n\n /**\n * The event handler called when clicking on a mention.\n */\n onMentionClick?: (\n mention: MentionData,\n event: MouseEvent<HTMLElement>\n ) => void;\n\n /**\n * The event handler called when clicking on a comment's attachment.\n */\n onAttachmentClick?: (\n args: CommentAttachmentArgs,\n event: MouseEvent<HTMLElement>\n ) => void;\n\n /**\n * Add (or change) items to display in the comment's dropdown.\n */\n dropdownItems?:\n | ReactNode\n | ((props: PropsWithChildren<{ comment: CommentData<CM> }>) => ReactNode);\n\n /**\n * Override the comment's content.\n */\n children?:\n | ReactNode\n | ((props: PropsWithChildren<{ comment: CommentData<CM> }>) => ReactNode);\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides & CommentOverrides & ComposerOverrides>;\n\n /**\n * Override the component's components.\n */\n components?: Partial<GlobalComponents>;\n\n /**\n * @internal\n */\n actions?: ReactNode;\n\n /**\n * @internal\n */\n actionsClassName?: string;\n\n /**\n * @internal\n */\n internalDropdownItems?: ReactNode;\n}\n\nexport interface CommentAvatarProps\n extends Omit<ComponentProps<\"div\">, \"children\"> {\n /**\n * The user ID to display the avatar for.\n */\n userId: string;\n}\n\nexport interface CommentAuthorProps\n extends Omit<ComponentProps<\"span\">, \"children\"> {\n /**\n * The user ID to display the author for.\n */\n userId: string;\n}\n\nexport interface CommentDateProps\n extends Omit<ComponentProps<\"span\">, \"children\"> {\n /**\n * The date to display.\n */\n date: Date | string | number;\n\n /**\n * The locale used when formatting the date.\n */\n locale?: string;\n}\n\nfunction CommentAvatar(props: CommentAvatarProps) {\n return <Avatar {...props} />;\n}\n\nfunction CommentAuthor(props: CommentAuthorProps) {\n return <User {...props} />;\n}\n\nfunction CommentDate({ locale, date, className, ...props }: CommentDateProps) {\n return (\n <Timestamp\n locale={locale}\n date={date}\n className={cn(\"lb-date\", className)}\n {...(props as Omit<ComponentProps<\"time\">, \"children\" | \"title\">)}\n />\n );\n}\n\nexport interface CommentDropdownItemProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onSelect\"> {\n /**\n * An optional icon displayed in this dropdown item.\n */\n icon?: ReactNode;\n\n /**\n * The event handler called when the dropdown item is selected.\n */\n onSelect?: (event: Event) => void;\n}\n\ninterface CommentReactionButtonProps\n extends ComponentPropsWithoutRef<typeof Button> {\n reaction: CommentReactionData;\n overrides?: Partial<GlobalOverrides & CommentOverrides>;\n}\n\ninterface CommentReactionProps extends ComponentPropsWithoutRef<\"button\"> {\n comment: CommentData;\n reaction: CommentReactionData;\n overrides?: Partial<GlobalOverrides & CommentOverrides>;\n}\n\ntype CommentNonInteractiveReactionProps = Omit<CommentReactionProps, \"comment\">;\n\ninterface CommentAttachmentProps extends ComponentProps<typeof FileAttachment> {\n attachment: CommentAttachment;\n onAttachmentClick?: CommentProps[\"onAttachmentClick\"];\n}\n\ninterface CommentMentionProps\n extends CommentBodyMentionProps,\n CommentPrimitiveMentionProps {\n overrides?: CommentProps[\"overrides\"];\n}\n\nfunction CommentUserMention({\n mention,\n className,\n ...props\n}: CommentMentionProps) {\n const currentId = useCurrentUserId();\n\n return (\n <CommentPrimitive.Mention\n className={cn(\"lb-mention lb-comment-mention\", className)}\n data-self={mention.id === currentId ? \"\" : undefined}\n {...props}\n >\n <span className=\"lb-mention-symbol\">{MENTION_CHARACTER}</span>\n <User userId={mention.id} />\n </CommentPrimitive.Mention>\n );\n}\n\nfunction CommentGroupMention({\n mention,\n className,\n ...props\n}: CommentMentionProps) {\n const isMember = useIsGroupMentionMember(mention as GroupMentionData);\n\n return (\n <CommentPrimitive.Mention\n className={cn(\"lb-mention lb-comment-mention\", className)}\n data-self={isMember ? \"\" : undefined}\n {...props}\n >\n <span className=\"lb-mention-symbol\">{MENTION_CHARACTER}</span>\n <Group groupId={mention.id} />\n </CommentPrimitive.Mention>\n );\n}\n\nexport function CommentMention({ mention, ...props }: CommentMentionProps) {\n switch (mention.kind) {\n case \"user\":\n return <CommentUserMention mention={mention} {...props} />;\n\n case \"group\":\n return <CommentGroupMention mention={mention} {...props} />;\n\n default:\n return assertNever(mention, \"Unhandled mention kind\");\n }\n}\n\nexport function CommentLink({\n href,\n children,\n className,\n ...props\n}: CommentBodyLinkProps & CommentLinkProps) {\n const { Anchor } = useComponents();\n\n return (\n <CommentPrimitive.Link\n className={cn(\"lb-comment-link\", className)}\n href={href}\n {...props}\n asChild\n >\n <Anchor {...props}>{children}</Anchor>\n </CommentPrimitive.Link>\n );\n}\n\nexport function CommentNonInteractiveLink({\n href: _href,\n children,\n className,\n ...props\n}: CommentBodyLinkProps & CommentLinkProps) {\n return (\n <span className={cn(\"lb-comment-link\", className)} {...props}>\n {children}\n </span>\n );\n}\n\nconst CommentReactionButton = forwardRef<\n HTMLButtonElement,\n CommentReactionButtonProps\n>(({ reaction, overrides, className, ...props }, forwardedRef) => {\n const $ = useOverrides(overrides);\n return (\n <CustomButton\n className={cn(\"lb-comment-reaction\", className)}\n variant=\"outline\"\n aria-label={$.COMMENT_REACTION_DESCRIPTION(\n reaction.emoji,\n reaction.users.length\n )}\n {...props}\n ref={forwardedRef}\n >\n <Emoji className=\"lb-comment-reaction-emoji\" emoji={reaction.emoji} />\n <span className=\"lb-comment-reaction-count\">{reaction.users.length}</span>\n </CustomButton>\n );\n});\n\nexport const CommentReaction = forwardRef<\n HTMLButtonElement,\n CommentReactionProps\n>(({ comment, reaction, overrides, disabled, ...props }, forwardedRef) => {\n const addReaction = useAddRoomCommentReaction(comment.roomId);\n const removeReaction = useRemoveRoomCommentReaction(comment.roomId);\n const currentId = useCurrentUserId();\n const isActive = useMemo(() => {\n return reaction.users.some((users) => users.id === currentId);\n }, [currentId, reaction]);\n const $ = useOverrides(overrides);\n const tooltipContent = useMemo(\n () => (\n <span>\n {$.COMMENT_REACTION_LIST(\n <List\n values={reaction.users.map((users) => (\n <User key={users.id} userId={users.id} replaceSelf />\n ))}\n formatRemaining={$.LIST_REMAINING_USERS}\n truncate={REACTIONS_TRUNCATE}\n locale={$.locale}\n />,\n reaction.emoji,\n reaction.users.length\n )}\n </span>\n ),\n [$, reaction]\n );\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n const handlePressedChange = useCallback(\n (isPressed: boolean) => {\n if (isPressed) {\n addReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji: reaction.emoji,\n });\n } else {\n removeReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji: reaction.emoji,\n });\n }\n },\n [addReaction, comment.threadId, comment.id, reaction.emoji, removeReaction]\n );\n\n return (\n <Tooltip\n content={tooltipContent}\n multiline\n className=\"lb-comment-reaction-tooltip\"\n >\n <TogglePrimitive.Root\n asChild\n pressed={isActive}\n onPressedChange={handlePressedChange}\n onClick={stopPropagation}\n disabled={disabled}\n ref={forwardedRef}\n >\n <CommentReactionButton\n data-self={isActive ? \"\" : undefined}\n reaction={reaction}\n overrides={overrides}\n {...props}\n />\n </TogglePrimitive.Root>\n </Tooltip>\n );\n});\n\nexport const CommentNonInteractiveReaction = forwardRef<\n HTMLButtonElement,\n CommentNonInteractiveReactionProps\n>(({ reaction, overrides, ...props }, forwardedRef) => {\n const currentId = useCurrentUserId();\n const isActive = useMemo(() => {\n return reaction.users.some((users) => users.id === currentId);\n }, [currentId, reaction]);\n\n return (\n <CommentReactionButton\n disableable={false}\n data-self={isActive ? \"\" : undefined}\n reaction={reaction}\n overrides={overrides}\n {...props}\n ref={forwardedRef}\n />\n );\n});\n\nfunction openAttachment({ attachment, url }: CommentAttachmentArgs) {\n // Open the attachment in a new tab if the attachment is a PDF,\n // an image, a video, or audio. Otherwise, download it.\n if (\n attachment.mimeType === \"application/pdf\" ||\n attachment.mimeType.startsWith(\"image/\") ||\n attachment.mimeType.startsWith(\"video/\") ||\n attachment.mimeType.startsWith(\"audio/\")\n ) {\n window.open(url, \"_blank\");\n } else {\n download(url, attachment.name);\n }\n}\n\nfunction CommentMediaAttachment({\n attachment,\n onAttachmentClick,\n roomId,\n className,\n overrides,\n ...props\n}: CommentAttachmentProps & {\n roomId: string;\n}) {\n const { url } = useRoomAttachmentUrl(attachment.id, roomId);\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLElement>) => {\n if (!url) {\n return;\n }\n\n const args: CommentAttachmentArgs = { attachment, url };\n\n onAttachmentClick?.(args, event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n openAttachment(args);\n },\n [attachment, onAttachmentClick, url]\n );\n\n return (\n <MediaAttachment\n className={cn(\"lb-comment-attachment\", className)}\n {...props}\n attachment={attachment}\n overrides={overrides}\n onClick={url ? handleClick : undefined}\n roomId={roomId}\n />\n );\n}\n\nfunction CommentFileAttachment({\n attachment,\n onAttachmentClick,\n roomId,\n className,\n overrides,\n ...props\n}: CommentAttachmentProps & {\n roomId: string;\n}) {\n const { url } = useRoomAttachmentUrl(attachment.id, roomId);\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLElement>) => {\n if (!url) {\n return;\n }\n\n const args: CommentAttachmentArgs = { attachment, url };\n\n onAttachmentClick?.(args, event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n openAttachment(args);\n },\n [attachment, onAttachmentClick, url]\n );\n\n return (\n <FileAttachment\n className={cn(\"lb-comment-attachment\", className)}\n {...props}\n attachment={attachment}\n overrides={overrides}\n onClick={url ? handleClick : undefined}\n roomId={roomId}\n />\n );\n}\n\nexport function CommentNonInteractiveFileAttachment({\n className,\n ...props\n}: CommentAttachmentProps) {\n return (\n <FileAttachment\n className={cn(\"lb-comment-attachment\", className)}\n allowMediaPreview={false}\n {...props}\n />\n );\n}\n\nconst CommentDropdownItem = forwardRef<\n HTMLDivElement,\n CommentDropdownItemProps\n>(({ children, icon, onSelect, onClick, ...props }, forwardedRef) => {\n const handleClick = useCallback(\n (event: MouseEvent<HTMLDivElement>) => {\n onClick?.(event);\n\n if (!event.isDefaultPrevented()) {\n event.stopPropagation();\n }\n },\n [onClick]\n );\n\n return (\n <DropdownItem\n icon={icon}\n onSelect={onSelect}\n onClick={handleClick}\n {...props}\n ref={forwardedRef}\n >\n {children}\n </DropdownItem>\n );\n});\n\n/**\n * Displays a single comment.\n *\n * @example\n * <>\n * {thread.comments.map((comment) => (\n * <Comment key={comment.id} comment={comment} />\n * ))}\n * </>\n */\nexport const Comment = Object.assign(\n forwardRef<HTMLDivElement, CommentProps>(\n (\n {\n comment,\n indentContent = true,\n showDeleted,\n showActions = \"hover\",\n showReactions = true,\n showAttachments = true,\n showComposerFormattingControls = true,\n onAuthorClick,\n onMentionClick,\n onAttachmentClick,\n onCommentEdit,\n onCommentDelete,\n dropdownItems,\n overrides,\n components,\n additionalContent,\n body,\n avatar,\n author,\n date,\n className,\n actions,\n actionsClassName,\n internalDropdownItems,\n children,\n ...props\n },\n forwardedRef\n ) => {\n const bodyId = `${comment.id}:body`;\n const ref = useRef<HTMLDivElement>(null);\n const mergedRefs = useRefs(forwardedRef, ref);\n const currentUserId = useCurrentUserId();\n const deleteComment = useDeleteRoomComment(comment.roomId);\n const editComment = useEditRoomComment(comment.roomId);\n const addReaction = useAddRoomCommentReaction(comment.roomId);\n const removeReaction = useRemoveRoomCommentReaction(comment.roomId);\n const $ = useOverrides(overrides);\n const [isEditing, setEditing] = useState(false);\n const [isTarget, setTarget] = useState(false);\n const [isMoreActionOpen, setMoreActionOpen] = useState(false);\n const [isReactionActionOpen, setReactionActionOpen] = useState(false);\n const { mediaAttachments, fileAttachments } = useMemo(() => {\n return separateMediaAttachments(comment.attachments);\n }, [comment.attachments]);\n\n const permissions = useRoomPermissions(comment.roomId);\n const canComment =\n permissions.size > 0\n ? permissions.has(Permission.CommentsWrite) ||\n permissions.has(Permission.Write)\n : true;\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n const handleEdit = useCallback(() => {\n setEditing(true);\n }, []);\n\n const handleEditCancel = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n setEditing(false);\n },\n []\n );\n\n const handleEditSubmit = useCallback(\n (\n { body, attachments }: ComposerSubmitComment,\n event: FormEvent<HTMLFormElement>\n ) => {\n // TODO: Add a way to preventDefault from within this callback, to override the default behavior (e.g. showing a confirmation dialog)\n onCommentEdit?.(comment);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n event.stopPropagation();\n event.preventDefault();\n\n setEditing(false);\n editComment({\n commentId: comment.id,\n threadId: comment.threadId,\n body,\n attachments,\n });\n },\n [comment, editComment, onCommentEdit]\n );\n\n const handleDelete = useCallback(() => {\n // TODO: Add a way to preventDefault from within this callback, to override the default behavior (e.g. showing a confirmation dialog)\n onCommentDelete?.(comment);\n\n deleteComment({\n commentId: comment.id,\n threadId: comment.threadId,\n });\n }, [comment, deleteComment, onCommentDelete]);\n\n const handleAuthorClick = useCallback(\n (event: MouseEvent<HTMLElement>) => {\n onAuthorClick?.(comment.userId, event);\n },\n [comment.userId, onAuthorClick]\n );\n\n const handleReactionSelect = useCallback(\n (emoji: string) => {\n const reactionIndex = comment.reactions.findIndex(\n (reaction) => reaction.emoji === emoji\n );\n\n if (\n reactionIndex >= 0 &&\n currentUserId &&\n comment.reactions[reactionIndex]?.users.some(\n (user) => user.id === currentUserId\n )\n ) {\n removeReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji,\n });\n } else {\n addReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji,\n });\n }\n },\n [\n addReaction,\n comment.id,\n comment.reactions,\n comment.threadId,\n removeReaction,\n currentUserId,\n ]\n );\n\n useEffect(() => {\n const isWindowDefined = typeof window !== \"undefined\";\n if (!isWindowDefined) return;\n\n const hash = window.location.hash;\n const commentId = hash.slice(1);\n\n if (commentId === comment.id) {\n setTarget(true);\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (!showDeleted && !comment.body) {\n return null;\n }\n\n const commentDropdownItems =\n comment.userId === currentUserId ? (\n <>\n <CommentDropdownItem onSelect={handleEdit} icon={<EditIcon />}>\n {$.COMMENT_EDIT}\n </CommentDropdownItem>\n <CommentDropdownItem onSelect={handleDelete} icon={<DeleteIcon />}>\n {$.COMMENT_DELETE}\n </CommentDropdownItem>\n </>\n ) : null;\n const defaultDropdownItems =\n internalDropdownItems || commentDropdownItems ? (\n <>\n {internalDropdownItems}\n {commentDropdownItems}\n </>\n ) : null;\n\n const dropdownContent =\n typeof dropdownItems === \"function\" ? (\n dropdownItems({ children: defaultDropdownItems, comment })\n ) : defaultDropdownItems || dropdownItems ? (\n <>\n {defaultDropdownItems}\n {dropdownItems}\n </>\n ) : null;\n\n let content: ReactNode;\n\n if (isEditing) {\n content = (\n <Composer\n className=\"lb-comment-composer\"\n onComposerSubmit={handleEditSubmit}\n defaultValue={comment.body}\n defaultAttachments={comment.attachments}\n autoFocus\n showAttribution={false}\n showAttachments={showAttachments}\n showFormattingControls={showComposerFormattingControls}\n actions={\n <>\n <Tooltip\n content={$.COMMENT_EDIT_COMPOSER_CANCEL}\n aria-label={$.COMMENT_EDIT_COMPOSER_CANCEL}\n >\n <Button\n className=\"lb-composer-action\"\n onClick={handleEditCancel}\n icon={<CrossIcon />}\n />\n </Tooltip>\n <ShortcutTooltip\n content={$.COMMENT_EDIT_COMPOSER_SAVE}\n shortcut=\"Enter\"\n >\n <ComposerPrimitive.Submit asChild>\n <Button\n variant=\"primary\"\n className=\"lb-composer-action\"\n onClick={stopPropagation}\n aria-label={$.COMMENT_EDIT_COMPOSER_SAVE}\n icon={<CheckIcon />}\n />\n </ComposerPrimitive.Submit>\n </ShortcutTooltip>\n </>\n }\n overrides={{\n COMPOSER_PLACEHOLDER: $.COMMENT_EDIT_COMPOSER_PLACEHOLDER,\n }}\n roomId={comment.roomId}\n />\n );\n } else {\n const defaultBody = (\n <CommentPrimitive.Body\n className=\"lb-comment-body\"\n id={bodyId}\n body={comment.body}\n components={{\n Mention: ({ mention }) => (\n <CommentMention\n mention={mention}\n onClick={(event) => onMentionClick?.(mention, event)}\n overrides={overrides}\n />\n ),\n Link: CommentLink,\n }}\n />\n );\n\n content = comment.body ? (\n <>\n {body === undefined\n ? defaultBody\n : typeof body === \"function\"\n ? body({ comment, children: defaultBody })\n : body}\n {additionalContent}\n {showAttachments &&\n (mediaAttachments.length > 0 || fileAttachments.length > 0) ? (\n <div className=\"lb-comment-attachments\">\n {mediaAttachments.length > 0 ? (\n <div className=\"lb-attachments\">\n {mediaAttachments.map((attachment) => (\n <CommentMediaAttachment\n key={attachment.id}\n attachment={attachment}\n overrides={overrides}\n onAttachmentClick={onAttachmentClick}\n roomId={comment.roomId}\n />\n ))}\n </div>\n ) : null}\n {fileAttachments.length > 0 ? (\n <div className=\"lb-attachments\">\n {fileAttachments.map((attachment) => (\n <CommentFileAttachment\n key={attachment.id}\n attachment={attachment}\n overrides={overrides}\n onAttachmentClick={onAttachmentClick}\n roomId={comment.roomId}\n />\n ))}\n </div>\n ) : null}\n </div>\n ) : null}\n {showReactions && comment.reactions.length > 0 && (\n <div className=\"lb-comment-reactions\">\n {comment.reactions.map((reaction) => (\n <CommentReaction\n key={reaction.emoji}\n comment={comment}\n reaction={reaction}\n overrides={overrides}\n disabled={!canComment}\n />\n ))}\n {canComment ? (\n <EmojiPicker onEmojiSelect={handleReactionSelect}>\n <Tooltip content={$.COMMENT_ADD_REACTION}>\n <EmojiPickerTrigger asChild>\n <Button\n className=\"lb-comment-reaction lb-comment-reaction-add\"\n variant=\"outline\"\n onClick={stopPropagation}\n aria-label={$.COMMENT_ADD_REACTION}\n icon={<EmojiPlusIcon />}\n />\n </EmojiPickerTrigger>\n </Tooltip>\n </EmojiPicker>\n ) : null}\n </div>\n )}\n </>\n ) : (\n <div className=\"lb-comment-body\">\n <p className=\"lb-comment-deleted\">{$.COMMENT_DELETED}</p>\n </div>\n );\n\n content =\n typeof children === \"function\"\n ? children({ comment, children: content })\n : (children ?? content);\n }\n\n return (\n <TooltipProvider>\n <ComponentsProvider components={components}>\n <div\n role=\"article\"\n id={comment.id}\n className={cn(\n \"lb-root lb-comment\",\n indentContent && \"lb-comment:indent-content\",\n showActions === \"hover\" && \"lb-comment:show-actions-hover\",\n (isMoreActionOpen || isReactionActionOpen) &&\n \"lb-comment:action-open\",\n className\n )}\n data-deleted={!comment.body ? \"\" : undefined}\n data-editing={isEditing ? \"\" : undefined}\n // In some cases, `:target` doesn't work as expected so we also define it manually.\n data-target={isTarget ? \"\" : undefined}\n aria-labelledby={bodyId}\n dir={$.dir}\n {...props}\n ref={mergedRefs}\n >\n <div className=\"lb-comment-header\">\n <div className=\"lb-comment-details\">\n {avatar ? (\n <div\n className=\"lb-comment-avatar\"\n onClick={handleAuthorClick}\n >\n {avatar}\n </div>\n ) : (\n <Avatar\n className=\"lb-comment-avatar\"\n userId={comment.userId}\n onClick={handleAuthorClick}\n />\n )}\n <span className=\"lb-comment-details-labels\">\n {author ? (\n <span\n className=\"lb-comment-author\"\n onClick={handleAuthorClick}\n >\n {author}\n </span>\n ) : (\n <User\n className=\"lb-comment-author\"\n userId={comment.userId}\n onClick={handleAuthorClick}\n />\n )}\n {date ? (\n <span className=\"lb-comment-date\">{date}</span>\n ) : (\n <span className=\"lb-comment-date\">\n <CommentDate\n locale={$.locale}\n date={comment.createdAt}\n className=\"lb-comment-date-created\"\n />\n {comment.editedAt && comment.body && (\n <>\n {\" \"}\n <span className=\"lb-comment-date-edited\">\n {$.COMMENT_EDITED}\n </span>\n </>\n )}\n </span>\n )}\n </span>\n </div>\n {showActions && !isEditing && (\n <div className={cn(\"lb-comment-actions\", actionsClassName)}>\n {actions ?? null}\n {showReactions && canComment ? (\n <EmojiPicker\n onEmojiSelect={handleReactionSelect}\n onOpenChange={setReactionActionOpen}\n >\n <Tooltip content={$.COMMENT_ADD_REACTION}>\n <EmojiPickerTrigger asChild>\n <Button\n className=\"lb-comment-action\"\n onClick={stopPropagation}\n aria-label={$.COMMENT_ADD_REACTION}\n icon={<EmojiPlusIcon />}\n />\n </EmojiPickerTrigger>\n </Tooltip>\n </EmojiPicker>\n ) : null}\n {dropdownContent ? (\n <Dropdown\n open={isMoreActionOpen}\n onOpenChange={setMoreActionOpen}\n align=\"end\"\n content={dropdownContent}\n >\n <Tooltip content={$.COMMENT_MORE}>\n <DropdownTrigger asChild>\n <Button\n className=\"lb-comment-action\"\n disabled={!comment.body}\n onClick={stopPropagation}\n aria-label={$.COMMENT_MORE}\n icon={<EllipsisIcon />}\n />\n </DropdownTrigger>\n </Tooltip>\n </Dropdown>\n ) : null}\n </div>\n )}\n </div>\n <div className=\"lb-comment-content\">{content}</div>\n </div>\n </ComponentsProvider>\n </TooltipProvider>\n );\n }\n ) as <CM extends BaseMetadata = DCM>(\n props: CommentProps<CM> & RefAttributes<HTMLDivElement>\n ) => JSX.Element,\n {\n /**\n * Displays a dropdown item in the comment's dropdown.\n */\n DropdownItem: CommentDropdownItem,\n\n /**\n * Displays a comment's avatar.\n */\n Avatar: CommentAvatar,\n\n /**\n * Displays a comment's author.\n */\n Author: CommentAuthor,\n\n /**\n * Displays a comment's date.\n */\n Date: CommentDate,\n }\n);\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4FA;AA0KA;AACE;AACF;AAEA;AACE;AACF;AAEA;AACE;AACE;AAAC;AAAA;AACC;AACA;AACkC;AAC7B;AAAA;AAGX;AAwCA;AAA4B;AAC1B;AACA;AAEF;AACE;AAEA;AACE;AAAkB;AAAjB;AACyD;AACb;AACvC;AAEJ;AAAuD;AAC7B;AAAA;AAAA;AAGhC;AAEA;AAA6B;AAC3B;AACA;AAEF;AACE;AAEA;AACE;AAAkB;AAAjB;AACyD;AAC7B;AACvB;AAEJ;AAAuD;AAC3B;AAAA;AAAA;AAGlC;AAEO;AACL;AAAsB;AAElB;AAAwD;AAGxD;AAAyD;AAGzD;AAAoD;AAE1D;AAEO;AAAqB;AAC1B;AACA;AACA;AAEF;AACE;AAEA;AACE;AAAkB;AAAjB;AAC2C;AAC1C;AACI;AACG;AAEsB;AAAA;AAGnC;AAEO;AAAmC;AAClC;AACN;AACA;AAEF;AACE;AAKF;AAEA;AAIE;AACA;AACE;AAAC;AAAA;AAC+C;AACtC;AACM;AACH;AACM;AACjB;AACI;AACC;AAEL;AAAoE;AACD;AAAA;AAAA;AAGzE;AAEa;AAIX;AACA;AACA;AACA;AACE;AAA4D;AAE9D;AACA;AAAuB;AAGd;AACD;AAAC;AAAA;AAGE;AACkB;AACT;AACA;AAAA;AACZ;AACS;AACM;AAEnB;AAEU;AAGd;AACE;AAAsB;AAGxB;AAA4B;AAExB;AACE;AAAY;AACQ;AACC;AACH;AACjB;AAED;AAAe;AACK;AACC;AACH;AACjB;AACH;AACF;AAC0E;AAG5E;AACE;AAAC;AAAA;AACU;AACA;AACC;AAEV;AAAiB;AAAhB;AACQ;AACE;AACQ;AACR;AACT;AACK;AAEL;AAAC;AAAA;AAC4B;AAC3B;AACA;AACI;AAAA;AACN;AAAA;AACF;AAAA;AAGN;AAEa;AAIX;AACA;AACE;AAA4D;AAG9D;AACE;AAAC;AAAA;AACc;AACc;AAC3B;AACA;AACI;AACC;AAAA;AAGX;AAEA;AAGE;AAME;AAAyB;AAEzB;AAA6B;AAEjC;AAEA;AAAgC;AAC9B;AACA;AACA;AACA;AACA;AAEF;AAGE;AAEA;AAAoB;AAEhB;AACE;AAAA;AAGF;AAEA;AAEA;AACE;AAAA;AAGF;AAAmB;AACrB;AACmC;AAGrC;AACE;AAAC;AAAA;AACiD;AAC5C;AACJ;AACA;AAC6B;AAC7B;AAAA;AAGN;AAEA;AAA+B;AAC7B;AACA;AACA;AACA;AACA;AAEF;AAGE;AAEA;AAAoB;AAEhB;AACE;AAAA;AAGF;AAEA;AAEA;AACE;AAAA;AAGF;AAAmB;AACrB;AACmC;AAGrC;AACE;AAAC;AAAA;AACiD;AAC5C;AACJ;AACA;AAC6B;AAC7B;AAAA;AAGN;AAEO;AAA6C;AAClD;AAEF;AACE;AACE;AAAC;AAAA;AACiD;AAC7B;AACf;AAAA;AAGV;AAEA;AAIE;AAAoB;AAEhB;AAEA;AACE;AAAsB;AACxB;AACF;AACQ;AAGV;AACE;AAAC;AAAA;AACC;AACA;AACS;AACL;AACC;AAEJ;AAAA;AAGP;AAYO;AAAuB;AAC5B;AAEI;AACE;AACgB;AAChB;AACc;AACE;AACE;AACe;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACG;AAIL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACE;AAAmD;AAGrD;AACA;AAMA;AACE;AAAsB;AAGxB;AACE;AAAe;AAGjB;AAAyB;AAErB;AACA;AAAgB;AAClB;AACC;AAGH;AAAyB;AAMrB;AAEA;AACE;AAAA;AAGF;AACA;AAEA;AACA;AAAY;AACS;AACD;AAClB;AACA;AACD;AACH;AACoC;AAGtC;AAEE;AAEA;AAAc;AACO;AACD;AACnB;AAGH;AAA0B;AAEtB;AAAqC;AACvC;AAC8B;AAGhC;AAA6B;AAEzB;AAAwC;AACL;AAGnC;AAG0C;AAChB;AAGxB;AAAe;AACK;AACC;AACnB;AACD;AAED;AAAY;AACQ;AACC;AACnB;AACD;AACH;AACF;AACA;AACE;AACQ;AACA;AACA;AACR;AACA;AACF;AAGF;AACE;AACA;AAAsB;AAEtB;AACA;AAEA;AACE;AAAc;AAChB;AAGF;AACE;AAAO;AAGT;AAGM;AAEA;AAGA;AAGN;AAGO;AAAA;AACA;AAIP;AAKO;AAAA;AACA;AAIP;AAEA;AACE;AACE;AAAC;AAAA;AACW;AACQ;AACI;AACM;AACnB;AACQ;AACjB;AACwB;AAGpB;AAAA;AAAC;AAAA;AACY;AACG;AAEd;AAAC;AAAA;AACW;AACD;AACQ;AAAA;AACnB;AAAA;AACF;AACA;AAAC;AAAA;AACY;AACF;AAGP;AAAC;AAAA;AACS;AACE;AACD;AACK;AACG;AAAA;AAErB;AAAA;AACF;AACF;AAES;AACe;AAC1B;AACgB;AAAA;AAClB;AAGF;AACE;AAAkB;AAAjB;AACW;AACN;AACU;AACF;AAER;AAAC;AAAA;AACC;AACmD;AACnD;AAAA;AACF;AAEI;AACR;AAAA;AAIJ;AAEK;AAIK;AACL;AAII;AAGK;AAAC;AAAA;AAEC;AACA;AACA;AACgB;AAAA;AAJA;AAQpB;AAIE;AAAC;AAAA;AAEC;AACA;AACA;AACgB;AAAA;AAJA;AAQpB;AAEJ;AAGC;AACC;AAAC;AAAA;AAEC;AACA;AACA;AACW;AAAA;AAJG;AAMjB;AAKO;AAAC;AAAA;AACW;AACF;AACC;AACK;AACO;AAAA;AAK3B;AACN;AASN;AAGmB;AAGrB;AAGM;AAAC;AAAA;AACM;AACO;AACD;AACT;AACiB;AACU;AAEzB;AACF;AACF;AACmC;AACJ;AAEF;AACZ;AACV;AACH;AACC;AAEL;AACE;AACG;AACC;AAAC;AAAA;AACW;AACD;AAER;AAAA;AAGH;AAAC;AAAA;AACW;AACM;AACP;AAAA;AACX;AAGC;AACC;AAAC;AAAA;AACW;AACD;AAER;AAAA;AAGH;AAAC;AAAA;AACW;AACM;AACP;AAAA;AACX;AAME;AAAA;AAAC;AAAA;AACW;AACI;AACJ;AAAA;AACZ;AAGK;AAAA;AAGD;AACF;AAEJ;AAEJ;AACF;AAGK;AAAW;AAEV;AAAC;AAAA;AACgB;AACD;AAIV;AAAC;AAAA;AACW;AACD;AACK;AACO;AAAA;AAG3B;AAAA;AAEA;AAEF;AAAC;AAAA;AACO;AACQ;AACR;AACG;AAIL;AAAC;AAAA;AACW;AACS;AACV;AACK;AACM;AAAA;AAG1B;AAAA;AAEA;AACN;AAEJ;AAC6C;AAAA;AAAA;AAGnD;AAEJ;AACF;AAGA;AAAA;AAAA;AAAA;AAIgB;AAAA;AAAA;AAAA;AAKN;AAAA;AAAA;AAAA;AAKA;AAAA;AAAA;AAAA;AAKF;AAEV;;;;;;;;"}
@@ -367,6 +367,7 @@ const Comment = Object.assign(
367
367
  overrides,
368
368
  components,
369
369
  additionalContent,
370
+ body,
370
371
  avatar,
371
372
  author,
372
373
  date,
@@ -409,7 +410,7 @@ const Comment = Object.assign(
409
410
  []
410
411
  );
411
412
  const handleEditSubmit = useCallback(
412
- ({ body, attachments }, event) => {
413
+ ({ body: body2, attachments }, event) => {
413
414
  onCommentEdit?.(comment);
414
415
  if (event.isDefaultPrevented()) {
415
416
  return;
@@ -420,7 +421,7 @@ const Comment = Object.assign(
420
421
  editComment({
421
422
  commentId: comment.id,
422
423
  threadId: comment.threadId,
423
- body,
424
+ body: body2,
424
425
  attachments
425
426
  });
426
427
  },
@@ -548,26 +549,27 @@ const Comment = Object.assign(
548
549
  }
549
550
  );
550
551
  } else {
551
- content = comment.body ? /* @__PURE__ */ jsxs(Fragment, { children: [
552
- /* @__PURE__ */ jsx(
553
- CommentBody,
554
- {
555
- className: "lb-comment-body",
556
- id: bodyId,
557
- body: comment.body,
558
- components: {
559
- Mention: ({ mention }) => /* @__PURE__ */ jsx(
560
- CommentMention,
561
- {
562
- mention,
563
- onClick: (event) => onMentionClick?.(mention, event),
564
- overrides
565
- }
566
- ),
567
- Link: CommentLink
568
- }
552
+ const defaultBody = /* @__PURE__ */ jsx(
553
+ CommentBody,
554
+ {
555
+ className: "lb-comment-body",
556
+ id: bodyId,
557
+ body: comment.body,
558
+ components: {
559
+ Mention: ({ mention }) => /* @__PURE__ */ jsx(
560
+ CommentMention,
561
+ {
562
+ mention,
563
+ onClick: (event) => onMentionClick?.(mention, event),
564
+ overrides
565
+ }
566
+ ),
567
+ Link: CommentLink
569
568
  }
570
- ),
569
+ }
570
+ );
571
+ content = comment.body ? /* @__PURE__ */ jsxs(Fragment, { children: [
572
+ body === void 0 ? defaultBody : typeof body === "function" ? body({ comment, children: defaultBody }) : body,
571
573
  additionalContent,
572
574
  showAttachments && (mediaAttachments.length > 0 || fileAttachments.length > 0) ? /* @__PURE__ */ jsxs("div", { className: "lb-comment-attachments", children: [
573
575
  mediaAttachments.length > 0 ? /* @__PURE__ */ jsx("div", { className: "lb-attachments", children: mediaAttachments.map((attachment) => /* @__PURE__ */ jsx(