@liveblocks/react-ui 2.14.0 → 2.15.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.
- package/dist/_private/index.d.mts +24 -22
- package/dist/_private/index.d.ts +24 -22
- package/dist/_private/index.js +1 -0
- package/dist/_private/index.js.map +1 -1
- package/dist/_private/index.mjs +1 -0
- package/dist/_private/index.mjs.map +1 -1
- package/dist/components/Comment.js +358 -256
- package/dist/components/Comment.js.map +1 -1
- package/dist/components/Comment.mjs +334 -232
- package/dist/components/Comment.mjs.map +1 -1
- package/dist/components/Composer.js +308 -225
- package/dist/components/Composer.js.map +1 -1
- package/dist/components/Composer.mjs +288 -206
- package/dist/components/Composer.mjs.map +1 -1
- package/dist/components/HistoryVersionSummary.js +28 -32
- package/dist/components/HistoryVersionSummary.js.map +1 -1
- package/dist/components/HistoryVersionSummary.mjs +27 -31
- package/dist/components/HistoryVersionSummary.mjs.map +1 -1
- package/dist/components/HistoryVersionSummaryList.js +11 -9
- package/dist/components/HistoryVersionSummaryList.js.map +1 -1
- package/dist/components/HistoryVersionSummaryList.mjs +10 -8
- package/dist/components/HistoryVersionSummaryList.mjs.map +1 -1
- package/dist/components/InboxNotification.js +202 -143
- package/dist/components/InboxNotification.js.map +1 -1
- package/dist/components/InboxNotification.mjs +180 -121
- package/dist/components/InboxNotification.mjs.map +1 -1
- package/dist/components/InboxNotificationList.js +19 -14
- package/dist/components/InboxNotificationList.js.map +1 -1
- package/dist/components/InboxNotificationList.mjs +17 -12
- package/dist/components/InboxNotificationList.mjs.map +1 -1
- package/dist/components/Thread.js +104 -86
- package/dist/components/Thread.js.map +1 -1
- package/dist/components/Thread.mjs +93 -75
- package/dist/components/Thread.mjs.map +1 -1
- package/dist/components/internal/Attachment.js +161 -113
- package/dist/components/internal/Attachment.js.map +1 -1
- package/dist/components/internal/Attachment.mjs +150 -102
- package/dist/components/internal/Attachment.mjs.map +1 -1
- package/dist/components/internal/Attribution.js +15 -13
- package/dist/components/internal/Attribution.js.map +1 -1
- package/dist/components/internal/Attribution.mjs +15 -13
- package/dist/components/internal/Attribution.mjs.map +1 -1
- package/dist/components/internal/Avatar.js +27 -20
- package/dist/components/internal/Avatar.js.map +1 -1
- package/dist/components/internal/Avatar.mjs +23 -16
- package/dist/components/internal/Avatar.mjs.map +1 -1
- package/dist/components/internal/Button.js +5 -4
- package/dist/components/internal/Button.js.map +1 -1
- package/dist/components/internal/Button.mjs +4 -3
- package/dist/components/internal/Button.mjs.map +1 -1
- package/dist/components/internal/Dropdown.js +27 -19
- package/dist/components/internal/Dropdown.js.map +1 -1
- package/dist/components/internal/Dropdown.mjs +26 -18
- package/dist/components/internal/Dropdown.mjs.map +1 -1
- package/dist/components/internal/Emoji.js +4 -3
- package/dist/components/internal/Emoji.js.map +1 -1
- package/dist/components/internal/Emoji.mjs +3 -2
- package/dist/components/internal/Emoji.mjs.map +1 -1
- package/dist/components/internal/EmojiPicker.js +96 -72
- package/dist/components/internal/EmojiPicker.js.map +1 -1
- package/dist/components/internal/EmojiPicker.mjs +90 -66
- package/dist/components/internal/EmojiPicker.mjs.map +1 -1
- package/dist/components/internal/Icon.js +5 -4
- package/dist/components/internal/Icon.js.map +1 -1
- package/dist/components/internal/Icon.mjs +5 -4
- package/dist/components/internal/Icon.mjs.map +1 -1
- package/dist/components/internal/InboxNotificationThread.js +53 -38
- package/dist/components/internal/InboxNotificationThread.js.map +1 -1
- package/dist/components/internal/InboxNotificationThread.mjs +53 -38
- package/dist/components/internal/InboxNotificationThread.mjs.map +1 -1
- package/dist/components/internal/List.js +8 -6
- package/dist/components/internal/List.js.map +1 -1
- package/dist/components/internal/List.mjs +6 -4
- package/dist/components/internal/List.mjs.map +1 -1
- package/dist/components/internal/Room.js +8 -6
- package/dist/components/internal/Room.js.map +1 -1
- package/dist/components/internal/Room.mjs +7 -5
- package/dist/components/internal/Room.mjs.map +1 -1
- package/dist/components/internal/Tooltip.js +49 -33
- package/dist/components/internal/Tooltip.js.map +1 -1
- package/dist/components/internal/Tooltip.mjs +46 -30
- package/dist/components/internal/Tooltip.mjs.map +1 -1
- package/dist/components/internal/User.js +8 -6
- package/dist/components/internal/User.js.map +1 -1
- package/dist/components/internal/User.mjs +7 -5
- package/dist/components/internal/User.mjs.map +1 -1
- package/dist/components.js +12 -29
- package/dist/components.js.map +1 -1
- package/dist/components.mjs +6 -5
- package/dist/components.mjs.map +1 -1
- package/dist/config.js +16 -12
- package/dist/config.js.map +1 -1
- package/dist/config.mjs +13 -9
- package/dist/config.mjs.map +1 -1
- package/dist/icons/ArrowDown.js +7 -6
- package/dist/icons/ArrowDown.js.map +1 -1
- package/dist/icons/ArrowDown.mjs +7 -6
- package/dist/icons/ArrowDown.mjs.map +1 -1
- package/dist/icons/ArrowUp.js +7 -6
- package/dist/icons/ArrowUp.js.map +1 -1
- package/dist/icons/ArrowUp.mjs +7 -6
- package/dist/icons/ArrowUp.mjs.map +1 -1
- package/dist/icons/Attachment.js +7 -6
- package/dist/icons/Attachment.js.map +1 -1
- package/dist/icons/Attachment.mjs +7 -6
- package/dist/icons/Attachment.mjs.map +1 -1
- package/dist/icons/Bold.js +7 -6
- package/dist/icons/Bold.js.map +1 -1
- package/dist/icons/Bold.mjs +7 -6
- package/dist/icons/Bold.mjs.map +1 -1
- package/dist/icons/Check.js +7 -6
- package/dist/icons/Check.js.map +1 -1
- package/dist/icons/Check.mjs +7 -6
- package/dist/icons/Check.mjs.map +1 -1
- package/dist/icons/Code.js +7 -6
- package/dist/icons/Code.js.map +1 -1
- package/dist/icons/Code.mjs +7 -6
- package/dist/icons/Code.mjs.map +1 -1
- package/dist/icons/Cross.js +12 -8
- package/dist/icons/Cross.js.map +1 -1
- package/dist/icons/Cross.mjs +12 -8
- package/dist/icons/Cross.mjs.map +1 -1
- package/dist/icons/Delete.js +7 -6
- package/dist/icons/Delete.js.map +1 -1
- package/dist/icons/Delete.mjs +7 -6
- package/dist/icons/Delete.mjs.map +1 -1
- package/dist/icons/Edit.js +7 -6
- package/dist/icons/Edit.js.map +1 -1
- package/dist/icons/Edit.mjs +7 -6
- package/dist/icons/Edit.mjs.map +1 -1
- package/dist/icons/Ellipsis.js +21 -16
- package/dist/icons/Ellipsis.js.map +1 -1
- package/dist/icons/Ellipsis.mjs +21 -16
- package/dist/icons/Ellipsis.mjs.map +1 -1
- package/dist/icons/Emoji.js +25 -18
- package/dist/icons/Emoji.js.map +1 -1
- package/dist/icons/Emoji.mjs +25 -18
- package/dist/icons/Emoji.mjs.map +1 -1
- package/dist/icons/EmojiAdd.js +28 -20
- package/dist/icons/EmojiAdd.js.map +1 -1
- package/dist/icons/EmojiAdd.mjs +28 -20
- package/dist/icons/EmojiAdd.mjs.map +1 -1
- package/dist/icons/Italic.js +7 -6
- package/dist/icons/Italic.js.map +1 -1
- package/dist/icons/Italic.mjs +7 -6
- package/dist/icons/Italic.mjs.map +1 -1
- package/dist/icons/Mention.js +12 -8
- package/dist/icons/Mention.js.map +1 -1
- package/dist/icons/Mention.mjs +12 -8
- package/dist/icons/Mention.mjs.map +1 -1
- package/dist/icons/Resolve.js +14 -10
- package/dist/icons/Resolve.js.map +1 -1
- package/dist/icons/Resolve.mjs +14 -10
- package/dist/icons/Resolve.mjs.map +1 -1
- package/dist/icons/Resolved.js +16 -12
- package/dist/icons/Resolved.js.map +1 -1
- package/dist/icons/Resolved.mjs +16 -12
- package/dist/icons/Resolved.mjs.map +1 -1
- package/dist/icons/Restore.js +12 -8
- package/dist/icons/Restore.js.map +1 -1
- package/dist/icons/Restore.mjs +12 -8
- package/dist/icons/Restore.mjs.map +1 -1
- package/dist/icons/Search.js +7 -6
- package/dist/icons/Search.js.map +1 -1
- package/dist/icons/Search.mjs +7 -6
- package/dist/icons/Search.mjs.map +1 -1
- package/dist/icons/Send.js +7 -6
- package/dist/icons/Send.js.map +1 -1
- package/dist/icons/Send.mjs +7 -6
- package/dist/icons/Send.mjs.map +1 -1
- package/dist/icons/Spinner.js +8 -7
- package/dist/icons/Spinner.js.map +1 -1
- package/dist/icons/Spinner.mjs +8 -7
- package/dist/icons/Spinner.mjs.map +1 -1
- package/dist/icons/Strikethrough.js +7 -6
- package/dist/icons/Strikethrough.js.map +1 -1
- package/dist/icons/Strikethrough.mjs +7 -6
- package/dist/icons/Strikethrough.mjs.map +1 -1
- package/dist/icons/Warning.js +14 -10
- package/dist/icons/Warning.js.map +1 -1
- package/dist/icons/Warning.mjs +14 -10
- package/dist/icons/Warning.mjs.map +1 -1
- package/dist/icons/index.js +42 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/icons/index.mjs +19 -0
- package/dist/icons/index.mjs.map +1 -0
- package/dist/index.d.mts +14 -12
- package/dist/index.d.ts +14 -12
- package/dist/overrides.js +65 -36
- package/dist/overrides.js.map +1 -1
- package/dist/overrides.mjs +59 -12
- package/dist/overrides.mjs.map +1 -1
- package/dist/primitives/Comment/index.js +75 -66
- package/dist/primitives/Comment/index.js.map +1 -1
- package/dist/primitives/Comment/index.mjs +71 -62
- package/dist/primitives/Comment/index.mjs.map +1 -1
- package/dist/primitives/Composer/contexts.js +11 -11
- package/dist/primitives/Composer/index.js +343 -284
- package/dist/primitives/Composer/index.js.map +1 -1
- package/dist/primitives/Composer/index.mjs +262 -203
- package/dist/primitives/Composer/index.mjs.map +1 -1
- package/dist/primitives/Composer/utils.js +20 -21
- package/dist/primitives/Composer/utils.js.map +1 -1
- package/dist/primitives/Composer/utils.mjs +4 -5
- package/dist/primitives/Composer/utils.mjs.map +1 -1
- package/dist/primitives/EmojiPicker/contexts.js +3 -3
- package/dist/primitives/EmojiPicker/index.js +160 -142
- package/dist/primitives/EmojiPicker/index.js.map +1 -1
- package/dist/primitives/EmojiPicker/index.mjs +122 -104
- package/dist/primitives/EmojiPicker/index.mjs.map +1 -1
- package/dist/primitives/FileSize.js +9 -7
- package/dist/primitives/FileSize.js.map +1 -1
- package/dist/primitives/FileSize.mjs +7 -5
- package/dist/primitives/FileSize.mjs.map +1 -1
- package/dist/primitives/Timestamp.js +12 -10
- package/dist/primitives/Timestamp.js.map +1 -1
- package/dist/primitives/Timestamp.mjs +7 -5
- package/dist/primitives/Timestamp.mjs.map +1 -1
- package/dist/primitives/index.d.mts +24 -23
- package/dist/primitives/index.d.ts +24 -23
- package/dist/primitives/internal/Emoji.js +7 -5
- package/dist/primitives/internal/Emoji.js.map +1 -1
- package/dist/primitives/internal/Emoji.mjs +6 -4
- package/dist/primitives/internal/Emoji.mjs.map +1 -1
- package/dist/shared.js +2 -7
- package/dist/shared.js.map +1 -1
- package/dist/shared.mjs +2 -7
- package/dist/shared.mjs.map +1 -1
- package/dist/slate/plugins/auto-links.mjs +1 -1
- package/dist/slate/plugins/custom-links.mjs +1 -1
- package/dist/slate/plugins/mentions.mjs +1 -1
- package/dist/utils/Persist.js +19 -18
- package/dist/utils/Persist.js.map +1 -1
- package/dist/utils/Persist.mjs +7 -6
- package/dist/utils/Persist.mjs.map +1 -1
- package/dist/utils/Portal.js +5 -4
- package/dist/utils/Portal.js.map +1 -1
- package/dist/utils/Portal.mjs +4 -3
- package/dist/utils/Portal.mjs.map +1 -1
- package/dist/utils/use-controllable-state.js +5 -5
- package/dist/utils/use-index.js +7 -7
- package/dist/utils/use-initial.js +2 -2
- package/dist/utils/use-interval.js +4 -4
- package/dist/utils/use-latest.js +3 -3
- package/dist/utils/use-observable.js +2 -2
- package/dist/utils/use-refs.js +2 -2
- package/dist/utils/use-rerender.js +2 -2
- package/dist/utils/use-visible.js +24 -2
- package/dist/utils/use-visible.js.map +1 -1
- package/dist/utils/use-visible.mjs +23 -2
- package/dist/utils/use-visible.mjs.map +1 -1
- package/dist/utils/use-window-focus.js +2 -2
- package/dist/utils/use-window-focus.js.map +1 -1
- package/dist/utils/use-window-focus.mjs +1 -1
- package/dist/utils/use-window-focus.mjs.map +1 -1
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/dist/version.mjs +2 -2
- package/dist/version.mjs.map +1 -1
- package/package.json +10 -25
- package/dist/utils/use-id.js +0 -29
- package/dist/utils/use-id.js.map +0 -1
- package/dist/utils/use-id.mjs +0 -27
- package/dist/utils/use-id.mjs.map +0 -1
- package/dist/utils/use-layout-effect.js +0 -8
- package/dist/utils/use-layout-effect.js.map +0 -1
- package/dist/utils/use-layout-effect.mjs +0 -6
- package/dist/utils/use-layout-effect.mjs.map +0 -1
- package/dist/utils/use-transition.js +0 -16
- package/dist/utils/use-transition.js.map +0 -1
- package/dist/utils/use-transition.mjs +0 -14
- package/dist/utils/use-transition.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Thread.js","sources":["../../src/components/Thread.tsx"],"sourcesContent":["\"use client\";\n\nimport type {\n BaseMetadata,\n CommentData,\n DM,\n ThreadData,\n} from \"@liveblocks/core\";\nimport { useThreadSubscription } from \"@liveblocks/react\";\nimport {\n useMarkRoomThreadAsResolved,\n useMarkRoomThreadAsUnresolved,\n} from \"@liveblocks/react/_private\";\nimport * as TogglePrimitive from \"@radix-ui/react-toggle\";\nimport type {\n ComponentPropsWithoutRef,\n ForwardedRef,\n RefAttributes,\n SyntheticEvent,\n} from \"react\";\nimport React, {\n forwardRef,\n Fragment,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\n\nimport { ArrowDownIcon } from \"../icons/ArrowDown\";\nimport { ResolveIcon } from \"../icons/Resolve\";\nimport { ResolvedIcon } from \"../icons/Resolved\";\nimport type {\n CommentOverrides,\n ComposerOverrides,\n GlobalOverrides,\n ThreadOverrides,\n} from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport { classNames } from \"../utils/class-names\";\nimport { findLastIndex } from \"../utils/find-last-index\";\nimport type { CommentProps } from \"./Comment\";\nimport { Comment } from \"./Comment\";\nimport type { ComposerProps } from \"./Composer\";\nimport { Composer } from \"./Composer\";\nimport { Button } from \"./internal/Button\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\n\nexport interface ThreadProps<M extends BaseMetadata = DM>\n extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The thread to display.\n */\n thread: ThreadData<M>;\n\n /**\n * How to show or hide the composer to reply to the thread.\n */\n showComposer?: boolean | \"collapsed\";\n\n /**\n * Whether to show the action to resolve the thread.\n */\n showResolveAction?: boolean;\n\n /**\n * How to show or hide the actions.\n */\n showActions?: CommentProps[\"showActions\"];\n\n /**\n * Whether to show reactions.\n */\n showReactions?: CommentProps[\"showReactions\"];\n\n /**\n * Whether to show the composer's formatting controls.\n */\n showComposerFormattingControls?: ComposerProps[\"showFormattingControls\"];\n\n /**\n * Whether to indent the comments' content.\n */\n indentCommentContent?: CommentProps[\"indentContent\"];\n\n /**\n * Whether to show deleted comments.\n */\n showDeletedComments?: CommentProps[\"showDeleted\"];\n\n /**\n * Whether to show attachments.\n */\n showAttachments?: boolean;\n\n /**\n * The event handler called when changing the resolved status.\n */\n onResolvedChange?: (resolved: boolean) => void;\n\n /**\n * The event handler called when a comment is edited.\n */\n onCommentEdit?: CommentProps[\"onCommentEdit\"];\n\n /**\n * The event handler called when a comment is deleted.\n */\n onCommentDelete?: CommentProps[\"onCommentDelete\"];\n\n /**\n * The event handler called when the thread is deleted.\n * A thread is deleted when all its comments are deleted.\n */\n onThreadDelete?: (thread: ThreadData<M>) => void;\n\n /**\n * The event handler called when clicking on a comment's author.\n */\n onAuthorClick?: CommentProps[\"onAuthorClick\"];\n\n /**\n * The event handler called when clicking on a mention.\n */\n onMentionClick?: CommentProps[\"onMentionClick\"];\n\n /**\n * The event handler called when clicking on a comment's attachment.\n */\n onAttachmentClick?: CommentProps[\"onAttachmentClick\"];\n\n /**\n * The event handler called when the composer is submitted.\n */\n onComposerSubmit?: ComposerProps[\"onComposerSubmit\"];\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<\n GlobalOverrides & ThreadOverrides & CommentOverrides & ComposerOverrides\n >;\n}\n\n/**\n * Displays a thread of comments, with a composer to reply\n * to it.\n *\n * @example\n * <>\n * {threads.map((thread) => (\n * <Thread key={thread.id} thread={thread} />\n * ))}\n * </>\n */\nexport const Thread = forwardRef(\n <M extends BaseMetadata = DM>(\n {\n thread,\n indentCommentContent = true,\n showActions = \"hover\",\n showDeletedComments,\n showResolveAction = true,\n showReactions = true,\n showComposer = \"collapsed\",\n showAttachments = true,\n showComposerFormattingControls = true,\n onResolvedChange,\n onCommentEdit,\n onCommentDelete,\n onThreadDelete,\n onAuthorClick,\n onMentionClick,\n onAttachmentClick,\n onComposerSubmit,\n overrides,\n className,\n ...props\n }: ThreadProps<M>,\n forwardedRef: ForwardedRef<HTMLDivElement>\n ) => {\n const markThreadAsResolved = useMarkRoomThreadAsResolved(thread.roomId);\n const markThreadAsUnresolved = useMarkRoomThreadAsUnresolved(thread.roomId);\n const $ = useOverrides(overrides);\n const firstCommentIndex = useMemo(() => {\n return showDeletedComments\n ? 0\n : thread.comments.findIndex((comment) => comment.body);\n }, [showDeletedComments, thread.comments]);\n const lastCommentIndex = useMemo(() => {\n return showDeletedComments\n ? thread.comments.length - 1\n : findLastIndex(thread.comments, (comment) => comment.body);\n }, [showDeletedComments, thread.comments]);\n const { status: subscriptionStatus, unreadSince } = useThreadSubscription(\n thread.id\n );\n const unreadIndex = useMemo(() => {\n // The user is not subscribed to this thread.\n if (subscriptionStatus !== \"subscribed\") {\n return;\n }\n\n // The user hasn't read the thread yet, so all comments are unread.\n if (unreadSince === null) {\n return firstCommentIndex;\n }\n\n // The user has read the thread, so we find the first unread comment.\n const unreadIndex = thread.comments.findIndex(\n (comment) =>\n (showDeletedComments ? true : comment.body) &&\n comment.createdAt > unreadSince\n );\n\n return unreadIndex >= 0 && unreadIndex < thread.comments.length\n ? unreadIndex\n : undefined;\n }, [\n firstCommentIndex,\n showDeletedComments,\n subscriptionStatus,\n thread.comments,\n unreadSince,\n ]);\n const [newIndex, setNewIndex] = useState<number>();\n const newIndicatorIndex = newIndex === undefined ? unreadIndex : newIndex;\n\n useEffect(() => {\n if (unreadIndex) {\n // Keep the \"new\" indicator at the lowest unread index.\n setNewIndex((persistedUnreadIndex) =>\n Math.min(persistedUnreadIndex ?? Infinity, unreadIndex)\n );\n }\n }, [unreadIndex]);\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n const handleResolvedChange = useCallback(\n (resolved: boolean) => {\n onResolvedChange?.(resolved);\n\n if (resolved) {\n markThreadAsResolved(thread.id);\n } else {\n markThreadAsUnresolved(thread.id);\n }\n },\n [\n markThreadAsResolved,\n markThreadAsUnresolved,\n onResolvedChange,\n thread.id,\n ]\n );\n\n const handleCommentDelete = useCallback(\n (comment: CommentData) => {\n onCommentDelete?.(comment);\n\n const filteredComments = thread.comments.filter(\n (comment) => comment.body\n );\n\n if (filteredComments.length <= 1) {\n onThreadDelete?.(thread);\n }\n },\n [onCommentDelete, onThreadDelete, thread]\n );\n\n return (\n <TooltipProvider>\n <div\n className={classNames(\n \"lb-root lb-thread\",\n showActions === \"hover\" && \"lb-thread:show-actions-hover\",\n className\n )}\n data-resolved={thread.resolved ? \"\" : undefined}\n data-unread={unreadIndex !== undefined ? \"\" : undefined}\n dir={$.dir}\n {...props}\n ref={forwardedRef}\n >\n <div className=\"lb-thread-comments\">\n {thread.comments.map((comment, index) => {\n const isFirstComment = index === firstCommentIndex;\n const isUnread =\n unreadIndex !== undefined && index >= unreadIndex;\n\n const children = (\n <Comment\n key={comment.id}\n className=\"lb-thread-comment\"\n data-unread={isUnread ? \"\" : undefined}\n comment={comment}\n indentContent={indentCommentContent}\n showDeleted={showDeletedComments}\n showActions={showActions}\n showReactions={showReactions}\n showAttachments={showAttachments}\n showComposerFormattingControls={\n showComposerFormattingControls\n }\n onCommentEdit={onCommentEdit}\n onCommentDelete={handleCommentDelete}\n onAuthorClick={onAuthorClick}\n onMentionClick={onMentionClick}\n onAttachmentClick={onAttachmentClick}\n autoMarkReadThreadId={\n index === lastCommentIndex && isUnread\n ? thread.id\n : undefined\n }\n additionalActionsClassName={\n isFirstComment ? \"lb-thread-actions\" : undefined\n }\n additionalActions={\n isFirstComment && showResolveAction ? (\n <Tooltip\n content={\n thread.resolved\n ? $.THREAD_UNRESOLVE\n : $.THREAD_RESOLVE\n }\n >\n <TogglePrimitive.Root\n pressed={thread.resolved}\n onPressedChange={handleResolvedChange}\n asChild\n >\n <Button\n className=\"lb-comment-action\"\n onClick={stopPropagation}\n aria-label={\n thread.resolved\n ? $.THREAD_UNRESOLVE\n : $.THREAD_RESOLVE\n }\n >\n {thread.resolved ? (\n <ResolvedIcon className=\"lb-button-icon\" />\n ) : (\n <ResolveIcon className=\"lb-button-icon\" />\n )}\n </Button>\n </TogglePrimitive.Root>\n </Tooltip>\n ) : null\n }\n />\n );\n\n return index === newIndicatorIndex &&\n newIndicatorIndex !== firstCommentIndex &&\n newIndicatorIndex <= lastCommentIndex ? (\n <Fragment key={comment.id}>\n <div\n className=\"lb-thread-new-indicator\"\n aria-label={$.THREAD_NEW_INDICATOR_DESCRIPTION}\n >\n <span className=\"lb-thread-new-indicator-label\">\n <ArrowDownIcon className=\"lb-thread-new-indicator-label-icon\" />\n {$.THREAD_NEW_INDICATOR}\n </span>\n </div>\n {children}\n </Fragment>\n ) : (\n children\n );\n })}\n </div>\n {showComposer && (\n <Composer\n className=\"lb-thread-composer\"\n threadId={thread.id}\n defaultCollapsed={showComposer === \"collapsed\" ? true : undefined}\n showAttachments={showAttachments}\n showFormattingControls={showComposerFormattingControls}\n onComposerSubmit={onComposerSubmit}\n overrides={{\n COMPOSER_PLACEHOLDER: $.THREAD_COMPOSER_PLACEHOLDER,\n COMPOSER_SEND: $.THREAD_COMPOSER_SEND,\n }}\n roomId={thread.roomId}\n />\n )}\n </div>\n </TooltipProvider>\n );\n }\n) as <M extends BaseMetadata = DM>(\n props: ThreadProps<M> & RefAttributes<HTMLDivElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2JO;AAAe;AAElB;AACE;AACuB;AACT;AACd;AACoB;AACJ;AACD;AACG;AACe;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACG;AAIL;AACA;AACA;AACA;AACE;AAEuD;AAEzD;AACE;AAE4D;AAE9D;AAAoD;AAC3C;AAET;AAEE;AACE;AAAA;AAIF;AACE;AAAO;AAIT;AAAoC;AAGZ;AAGxB;AAEI;AACH;AACD;AACA;AACA;AACO;AACP;AAEF;AACA;AAEA;AACE;AAEE;AAAA;AACwD;AACxD;AACF;AAGF;AACE;AAAsB;AAGxB;AAA6B;AAEzB;AAEA;AACE;AAA8B;AAE9B;AAAgC;AAClC;AACF;AACA;AACE;AACA;AACA;AACO;AACT;AAGF;AAA4B;AAExB;AAEA;AAAyC;AAClB;AAGvB;AACE;AAAuB;AACzB;AACF;AACwC;AAG1C;AAEK;AACY;AACT;AAC2B;AAC3B;AACF;AACsC;AACQ;AACvC;AACH;AACC;AAEJ;AAAc;AAEX;AACA;AAGA;AACG;AACc;AACH;AACmB;AAC7B;AACe;AACF;AACb;AACA;AACA;AACA;AAGA;AACiB;AACjB;AACA;AACA;AAIM;AAGmC;AAIpC;AAIS;AAGP;AACiB;AACC;AACV;AAEN;AACW;AACD;AAID;AAIL;AAAuB;AAEvB;AAAsB;AAK7B;AAKV;AAGG;AAAsB;AACpB;AACW;AACI;AAEb;AAAe;AACb;AAAwB;AAO/B;AAKH;AACW;AACO;AACuC;AACxD;AACwB;AACxB;AACW;AACe;AACP;AACnB;AACe;AAIvB;AAGN;;"}
|
|
1
|
+
{"version":3,"file":"Thread.js","sources":["../../src/components/Thread.tsx"],"sourcesContent":["\"use client\";\n\nimport type {\n BaseMetadata,\n CommentData,\n DM,\n ThreadData,\n} from \"@liveblocks/core\";\nimport { useThreadSubscription } from \"@liveblocks/react\";\nimport {\n useMarkRoomThreadAsResolved,\n useMarkRoomThreadAsUnresolved,\n} from \"@liveblocks/react/_private\";\nimport * as TogglePrimitive from \"@radix-ui/react-toggle\";\nimport type {\n ComponentPropsWithoutRef,\n ForwardedRef,\n RefAttributes,\n SyntheticEvent,\n} from \"react\";\nimport {\n forwardRef,\n Fragment,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\n\nimport { ArrowDownIcon } from \"../icons/ArrowDown\";\nimport { ResolveIcon } from \"../icons/Resolve\";\nimport { ResolvedIcon } from \"../icons/Resolved\";\nimport type {\n CommentOverrides,\n ComposerOverrides,\n GlobalOverrides,\n ThreadOverrides,\n} from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport { classNames } from \"../utils/class-names\";\nimport { findLastIndex } from \"../utils/find-last-index\";\nimport type { CommentProps } from \"./Comment\";\nimport { Comment } from \"./Comment\";\nimport type { ComposerProps } from \"./Composer\";\nimport { Composer } from \"./Composer\";\nimport { Button } from \"./internal/Button\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\n\nexport interface ThreadProps<M extends BaseMetadata = DM>\n extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The thread to display.\n */\n thread: ThreadData<M>;\n\n /**\n * How to show or hide the composer to reply to the thread.\n */\n showComposer?: boolean | \"collapsed\";\n\n /**\n * Whether to show the action to resolve the thread.\n */\n showResolveAction?: boolean;\n\n /**\n * How to show or hide the actions.\n */\n showActions?: CommentProps[\"showActions\"];\n\n /**\n * Whether to show reactions.\n */\n showReactions?: CommentProps[\"showReactions\"];\n\n /**\n * Whether to show the composer's formatting controls.\n */\n showComposerFormattingControls?: ComposerProps[\"showFormattingControls\"];\n\n /**\n * Whether to indent the comments' content.\n */\n indentCommentContent?: CommentProps[\"indentContent\"];\n\n /**\n * Whether to show deleted comments.\n */\n showDeletedComments?: CommentProps[\"showDeleted\"];\n\n /**\n * Whether to show attachments.\n */\n showAttachments?: boolean;\n\n /**\n * The event handler called when changing the resolved status.\n */\n onResolvedChange?: (resolved: boolean) => void;\n\n /**\n * The event handler called when a comment is edited.\n */\n onCommentEdit?: CommentProps[\"onCommentEdit\"];\n\n /**\n * The event handler called when a comment is deleted.\n */\n onCommentDelete?: CommentProps[\"onCommentDelete\"];\n\n /**\n * The event handler called when the thread is deleted.\n * A thread is deleted when all its comments are deleted.\n */\n onThreadDelete?: (thread: ThreadData<M>) => void;\n\n /**\n * The event handler called when clicking on a comment's author.\n */\n onAuthorClick?: CommentProps[\"onAuthorClick\"];\n\n /**\n * The event handler called when clicking on a mention.\n */\n onMentionClick?: CommentProps[\"onMentionClick\"];\n\n /**\n * The event handler called when clicking on a comment's attachment.\n */\n onAttachmentClick?: CommentProps[\"onAttachmentClick\"];\n\n /**\n * The event handler called when the composer is submitted.\n */\n onComposerSubmit?: ComposerProps[\"onComposerSubmit\"];\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<\n GlobalOverrides & ThreadOverrides & CommentOverrides & ComposerOverrides\n >;\n}\n\n/**\n * Displays a thread of comments, with a composer to reply\n * to it.\n *\n * @example\n * <>\n * {threads.map((thread) => (\n * <Thread key={thread.id} thread={thread} />\n * ))}\n * </>\n */\nexport const Thread = forwardRef(\n <M extends BaseMetadata = DM>(\n {\n thread,\n indentCommentContent = true,\n showActions = \"hover\",\n showDeletedComments,\n showResolveAction = true,\n showReactions = true,\n showComposer = \"collapsed\",\n showAttachments = true,\n showComposerFormattingControls = true,\n onResolvedChange,\n onCommentEdit,\n onCommentDelete,\n onThreadDelete,\n onAuthorClick,\n onMentionClick,\n onAttachmentClick,\n onComposerSubmit,\n overrides,\n className,\n ...props\n }: ThreadProps<M>,\n forwardedRef: ForwardedRef<HTMLDivElement>\n ) => {\n const markThreadAsResolved = useMarkRoomThreadAsResolved(thread.roomId);\n const markThreadAsUnresolved = useMarkRoomThreadAsUnresolved(thread.roomId);\n const $ = useOverrides(overrides);\n const firstCommentIndex = useMemo(() => {\n return showDeletedComments\n ? 0\n : thread.comments.findIndex((comment) => comment.body);\n }, [showDeletedComments, thread.comments]);\n const lastCommentIndex = useMemo(() => {\n return showDeletedComments\n ? thread.comments.length - 1\n : findLastIndex(thread.comments, (comment) => comment.body);\n }, [showDeletedComments, thread.comments]);\n const { status: subscriptionStatus, unreadSince } = useThreadSubscription(\n thread.id\n );\n const unreadIndex = useMemo(() => {\n // The user is not subscribed to this thread.\n if (subscriptionStatus !== \"subscribed\") {\n return;\n }\n\n // The user hasn't read the thread yet, so all comments are unread.\n if (unreadSince === null) {\n return firstCommentIndex;\n }\n\n // The user has read the thread, so we find the first unread comment.\n const unreadIndex = thread.comments.findIndex(\n (comment) =>\n (showDeletedComments ? true : comment.body) &&\n comment.createdAt > unreadSince\n );\n\n return unreadIndex >= 0 && unreadIndex < thread.comments.length\n ? unreadIndex\n : undefined;\n }, [\n firstCommentIndex,\n showDeletedComments,\n subscriptionStatus,\n thread.comments,\n unreadSince,\n ]);\n const [newIndex, setNewIndex] = useState<number>();\n const newIndicatorIndex = newIndex === undefined ? unreadIndex : newIndex;\n\n useEffect(() => {\n if (unreadIndex) {\n // Keep the \"new\" indicator at the lowest unread index.\n setNewIndex((persistedUnreadIndex) =>\n Math.min(persistedUnreadIndex ?? Infinity, unreadIndex)\n );\n }\n }, [unreadIndex]);\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n const handleResolvedChange = useCallback(\n (resolved: boolean) => {\n onResolvedChange?.(resolved);\n\n if (resolved) {\n markThreadAsResolved(thread.id);\n } else {\n markThreadAsUnresolved(thread.id);\n }\n },\n [\n markThreadAsResolved,\n markThreadAsUnresolved,\n onResolvedChange,\n thread.id,\n ]\n );\n\n const handleCommentDelete = useCallback(\n (comment: CommentData) => {\n onCommentDelete?.(comment);\n\n const filteredComments = thread.comments.filter(\n (comment) => comment.body\n );\n\n if (filteredComments.length <= 1) {\n onThreadDelete?.(thread);\n }\n },\n [onCommentDelete, onThreadDelete, thread]\n );\n\n return (\n <TooltipProvider>\n <div\n className={classNames(\n \"lb-root lb-thread\",\n showActions === \"hover\" && \"lb-thread:show-actions-hover\",\n className\n )}\n data-resolved={thread.resolved ? \"\" : undefined}\n data-unread={unreadIndex !== undefined ? \"\" : undefined}\n dir={$.dir}\n {...props}\n ref={forwardedRef}\n >\n <div className=\"lb-thread-comments\">\n {thread.comments.map((comment, index) => {\n const isFirstComment = index === firstCommentIndex;\n const isUnread =\n unreadIndex !== undefined && index >= unreadIndex;\n\n const children = (\n <Comment\n key={comment.id}\n className=\"lb-thread-comment\"\n data-unread={isUnread ? \"\" : undefined}\n comment={comment}\n indentContent={indentCommentContent}\n showDeleted={showDeletedComments}\n showActions={showActions}\n showReactions={showReactions}\n showAttachments={showAttachments}\n showComposerFormattingControls={\n showComposerFormattingControls\n }\n onCommentEdit={onCommentEdit}\n onCommentDelete={handleCommentDelete}\n onAuthorClick={onAuthorClick}\n onMentionClick={onMentionClick}\n onAttachmentClick={onAttachmentClick}\n autoMarkReadThreadId={\n index === lastCommentIndex && isUnread\n ? thread.id\n : undefined\n }\n additionalActionsClassName={\n isFirstComment ? \"lb-thread-actions\" : undefined\n }\n additionalActions={\n isFirstComment && showResolveAction ? (\n <Tooltip\n content={\n thread.resolved\n ? $.THREAD_UNRESOLVE\n : $.THREAD_RESOLVE\n }\n >\n <TogglePrimitive.Root\n pressed={thread.resolved}\n onPressedChange={handleResolvedChange}\n asChild\n >\n <Button\n className=\"lb-comment-action\"\n onClick={stopPropagation}\n aria-label={\n thread.resolved\n ? $.THREAD_UNRESOLVE\n : $.THREAD_RESOLVE\n }\n >\n {thread.resolved ? (\n <ResolvedIcon className=\"lb-button-icon\" />\n ) : (\n <ResolveIcon className=\"lb-button-icon\" />\n )}\n </Button>\n </TogglePrimitive.Root>\n </Tooltip>\n ) : null\n }\n />\n );\n\n return index === newIndicatorIndex &&\n newIndicatorIndex !== firstCommentIndex &&\n newIndicatorIndex <= lastCommentIndex ? (\n <Fragment key={comment.id}>\n <div\n className=\"lb-thread-new-indicator\"\n aria-label={$.THREAD_NEW_INDICATOR_DESCRIPTION}\n >\n <span className=\"lb-thread-new-indicator-label\">\n <ArrowDownIcon className=\"lb-thread-new-indicator-label-icon\" />\n {$.THREAD_NEW_INDICATOR}\n </span>\n </div>\n {children}\n </Fragment>\n ) : (\n children\n );\n })}\n </div>\n {showComposer && (\n <Composer\n className=\"lb-thread-composer\"\n threadId={thread.id}\n defaultCollapsed={showComposer === \"collapsed\" ? true : undefined}\n showAttachments={showAttachments}\n showFormattingControls={showComposerFormattingControls}\n onComposerSubmit={onComposerSubmit}\n overrides={{\n COMPOSER_PLACEHOLDER: $.THREAD_COMPOSER_PLACEHOLDER,\n COMPOSER_SEND: $.THREAD_COMPOSER_SEND,\n }}\n roomId={thread.roomId}\n />\n )}\n </div>\n </TooltipProvider>\n );\n }\n) as <M extends BaseMetadata = DM>(\n props: ThreadProps<M> & RefAttributes<HTMLDivElement>\n) => JSX.Element;\n"],"names":["forwardRef","overrides","useMarkRoomThreadAsResolved","useMarkRoomThreadAsUnresolved","useOverrides","useMemo","findLastIndex","useThreadSubscription","unreadIndex","useState","useEffect","useCallback","comment","jsx","TooltipProvider","jsxs","classNames","Comment","Tooltip","TogglePrimitive","Button","ResolvedIcon","ResolveIcon","Fragment","ArrowDownIcon","Composer"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { useThreadSubscription } from '@liveblocks/react';
|
|
3
3
|
import { useMarkRoomThreadAsResolved, useMarkRoomThreadAsUnresolved } from '@liveblocks/react/_private';
|
|
4
4
|
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
|
5
|
-
import
|
|
5
|
+
import { forwardRef, useMemo, useState, useEffect, useCallback, Fragment } from 'react';
|
|
6
6
|
import { ArrowDownIcon } from '../icons/ArrowDown.mjs';
|
|
7
7
|
import { ResolveIcon } from '../icons/Resolve.mjs';
|
|
8
8
|
import { ResolvedIcon } from '../icons/Resolved.mjs';
|
|
@@ -15,6 +15,7 @@ import { Button } from './internal/Button.mjs';
|
|
|
15
15
|
import { Tooltip } from './internal/Tooltip.mjs';
|
|
16
16
|
import { TooltipProvider } from '@radix-ui/react-tooltip';
|
|
17
17
|
|
|
18
|
+
"use client";
|
|
18
19
|
const Thread = forwardRef(
|
|
19
20
|
({
|
|
20
21
|
thread,
|
|
@@ -108,79 +109,96 @@ const Thread = forwardRef(
|
|
|
108
109
|
},
|
|
109
110
|
[onCommentDelete, onThreadDelete, thread]
|
|
110
111
|
);
|
|
111
|
-
return /* @__PURE__ */
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
112
|
+
return /* @__PURE__ */ jsx(TooltipProvider, {
|
|
113
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
114
|
+
className: classNames(
|
|
115
|
+
"lb-root lb-thread",
|
|
116
|
+
showActions === "hover" && "lb-thread:show-actions-hover",
|
|
117
|
+
className
|
|
118
|
+
),
|
|
119
|
+
"data-resolved": thread.resolved ? "" : void 0,
|
|
120
|
+
"data-unread": unreadIndex !== void 0 ? "" : void 0,
|
|
121
|
+
dir: $.dir,
|
|
122
|
+
...props,
|
|
123
|
+
ref: forwardedRef,
|
|
124
|
+
children: [
|
|
125
|
+
/* @__PURE__ */ jsx("div", {
|
|
126
|
+
className: "lb-thread-comments",
|
|
127
|
+
children: thread.comments.map((comment, index) => {
|
|
128
|
+
const isFirstComment = index === firstCommentIndex;
|
|
129
|
+
const isUnread = unreadIndex !== void 0 && index >= unreadIndex;
|
|
130
|
+
const children = /* @__PURE__ */ jsx(Comment, {
|
|
131
|
+
className: "lb-thread-comment",
|
|
132
|
+
"data-unread": isUnread ? "" : void 0,
|
|
133
|
+
comment,
|
|
134
|
+
indentContent: indentCommentContent,
|
|
135
|
+
showDeleted: showDeletedComments,
|
|
136
|
+
showActions,
|
|
137
|
+
showReactions,
|
|
138
|
+
showAttachments,
|
|
139
|
+
showComposerFormattingControls,
|
|
140
|
+
onCommentEdit,
|
|
141
|
+
onCommentDelete: handleCommentDelete,
|
|
142
|
+
onAuthorClick,
|
|
143
|
+
onMentionClick,
|
|
144
|
+
onAttachmentClick,
|
|
145
|
+
autoMarkReadThreadId: index === lastCommentIndex && isUnread ? thread.id : void 0,
|
|
146
|
+
additionalActionsClassName: isFirstComment ? "lb-thread-actions" : void 0,
|
|
147
|
+
additionalActions: isFirstComment && showResolveAction ? /* @__PURE__ */ jsx(Tooltip, {
|
|
148
|
+
content: thread.resolved ? $.THREAD_UNRESOLVE : $.THREAD_RESOLVE,
|
|
149
|
+
children: /* @__PURE__ */ jsx(TogglePrimitive.Root, {
|
|
150
|
+
pressed: thread.resolved,
|
|
151
|
+
onPressedChange: handleResolvedChange,
|
|
152
|
+
asChild: true,
|
|
153
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
154
|
+
className: "lb-comment-action",
|
|
155
|
+
onClick: stopPropagation,
|
|
156
|
+
"aria-label": thread.resolved ? $.THREAD_UNRESOLVE : $.THREAD_RESOLVE,
|
|
157
|
+
children: thread.resolved ? /* @__PURE__ */ jsx(ResolvedIcon, {
|
|
158
|
+
className: "lb-button-icon"
|
|
159
|
+
}) : /* @__PURE__ */ jsx(ResolveIcon, {
|
|
160
|
+
className: "lb-button-icon"
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
}) : null
|
|
165
|
+
}, comment.id);
|
|
166
|
+
return index === newIndicatorIndex && newIndicatorIndex !== firstCommentIndex && newIndicatorIndex <= lastCommentIndex ? /* @__PURE__ */ jsxs(Fragment, {
|
|
167
|
+
children: [
|
|
168
|
+
/* @__PURE__ */ jsx("div", {
|
|
169
|
+
className: "lb-thread-new-indicator",
|
|
170
|
+
"aria-label": $.THREAD_NEW_INDICATOR_DESCRIPTION,
|
|
171
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
172
|
+
className: "lb-thread-new-indicator-label",
|
|
173
|
+
children: [
|
|
174
|
+
/* @__PURE__ */ jsx(ArrowDownIcon, {
|
|
175
|
+
className: "lb-thread-new-indicator-label-icon"
|
|
176
|
+
}),
|
|
177
|
+
$.THREAD_NEW_INDICATOR
|
|
178
|
+
]
|
|
179
|
+
})
|
|
180
|
+
}),
|
|
181
|
+
children
|
|
182
|
+
]
|
|
183
|
+
}, comment.id) : children;
|
|
184
|
+
})
|
|
185
|
+
}),
|
|
186
|
+
showComposer && /* @__PURE__ */ jsx(Composer, {
|
|
187
|
+
className: "lb-thread-composer",
|
|
188
|
+
threadId: thread.id,
|
|
189
|
+
defaultCollapsed: showComposer === "collapsed" ? true : void 0,
|
|
190
|
+
showAttachments,
|
|
191
|
+
showFormattingControls: showComposerFormattingControls,
|
|
192
|
+
onComposerSubmit,
|
|
193
|
+
overrides: {
|
|
194
|
+
COMPOSER_PLACEHOLDER: $.THREAD_COMPOSER_PLACEHOLDER,
|
|
195
|
+
COMPOSER_SEND: $.THREAD_COMPOSER_SEND
|
|
196
|
+
},
|
|
197
|
+
roomId: thread.roomId
|
|
198
|
+
})
|
|
199
|
+
]
|
|
200
|
+
})
|
|
201
|
+
});
|
|
184
202
|
}
|
|
185
203
|
);
|
|
186
204
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Thread.mjs","sources":["../../src/components/Thread.tsx"],"sourcesContent":["\"use client\";\n\nimport type {\n BaseMetadata,\n CommentData,\n DM,\n ThreadData,\n} from \"@liveblocks/core\";\nimport { useThreadSubscription } from \"@liveblocks/react\";\nimport {\n useMarkRoomThreadAsResolved,\n useMarkRoomThreadAsUnresolved,\n} from \"@liveblocks/react/_private\";\nimport * as TogglePrimitive from \"@radix-ui/react-toggle\";\nimport type {\n ComponentPropsWithoutRef,\n ForwardedRef,\n RefAttributes,\n SyntheticEvent,\n} from \"react\";\nimport React, {\n forwardRef,\n Fragment,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\n\nimport { ArrowDownIcon } from \"../icons/ArrowDown\";\nimport { ResolveIcon } from \"../icons/Resolve\";\nimport { ResolvedIcon } from \"../icons/Resolved\";\nimport type {\n CommentOverrides,\n ComposerOverrides,\n GlobalOverrides,\n ThreadOverrides,\n} from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport { classNames } from \"../utils/class-names\";\nimport { findLastIndex } from \"../utils/find-last-index\";\nimport type { CommentProps } from \"./Comment\";\nimport { Comment } from \"./Comment\";\nimport type { ComposerProps } from \"./Composer\";\nimport { Composer } from \"./Composer\";\nimport { Button } from \"./internal/Button\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\n\nexport interface ThreadProps<M extends BaseMetadata = DM>\n extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The thread to display.\n */\n thread: ThreadData<M>;\n\n /**\n * How to show or hide the composer to reply to the thread.\n */\n showComposer?: boolean | \"collapsed\";\n\n /**\n * Whether to show the action to resolve the thread.\n */\n showResolveAction?: boolean;\n\n /**\n * How to show or hide the actions.\n */\n showActions?: CommentProps[\"showActions\"];\n\n /**\n * Whether to show reactions.\n */\n showReactions?: CommentProps[\"showReactions\"];\n\n /**\n * Whether to show the composer's formatting controls.\n */\n showComposerFormattingControls?: ComposerProps[\"showFormattingControls\"];\n\n /**\n * Whether to indent the comments' content.\n */\n indentCommentContent?: CommentProps[\"indentContent\"];\n\n /**\n * Whether to show deleted comments.\n */\n showDeletedComments?: CommentProps[\"showDeleted\"];\n\n /**\n * Whether to show attachments.\n */\n showAttachments?: boolean;\n\n /**\n * The event handler called when changing the resolved status.\n */\n onResolvedChange?: (resolved: boolean) => void;\n\n /**\n * The event handler called when a comment is edited.\n */\n onCommentEdit?: CommentProps[\"onCommentEdit\"];\n\n /**\n * The event handler called when a comment is deleted.\n */\n onCommentDelete?: CommentProps[\"onCommentDelete\"];\n\n /**\n * The event handler called when the thread is deleted.\n * A thread is deleted when all its comments are deleted.\n */\n onThreadDelete?: (thread: ThreadData<M>) => void;\n\n /**\n * The event handler called when clicking on a comment's author.\n */\n onAuthorClick?: CommentProps[\"onAuthorClick\"];\n\n /**\n * The event handler called when clicking on a mention.\n */\n onMentionClick?: CommentProps[\"onMentionClick\"];\n\n /**\n * The event handler called when clicking on a comment's attachment.\n */\n onAttachmentClick?: CommentProps[\"onAttachmentClick\"];\n\n /**\n * The event handler called when the composer is submitted.\n */\n onComposerSubmit?: ComposerProps[\"onComposerSubmit\"];\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<\n GlobalOverrides & ThreadOverrides & CommentOverrides & ComposerOverrides\n >;\n}\n\n/**\n * Displays a thread of comments, with a composer to reply\n * to it.\n *\n * @example\n * <>\n * {threads.map((thread) => (\n * <Thread key={thread.id} thread={thread} />\n * ))}\n * </>\n */\nexport const Thread = forwardRef(\n <M extends BaseMetadata = DM>(\n {\n thread,\n indentCommentContent = true,\n showActions = \"hover\",\n showDeletedComments,\n showResolveAction = true,\n showReactions = true,\n showComposer = \"collapsed\",\n showAttachments = true,\n showComposerFormattingControls = true,\n onResolvedChange,\n onCommentEdit,\n onCommentDelete,\n onThreadDelete,\n onAuthorClick,\n onMentionClick,\n onAttachmentClick,\n onComposerSubmit,\n overrides,\n className,\n ...props\n }: ThreadProps<M>,\n forwardedRef: ForwardedRef<HTMLDivElement>\n ) => {\n const markThreadAsResolved = useMarkRoomThreadAsResolved(thread.roomId);\n const markThreadAsUnresolved = useMarkRoomThreadAsUnresolved(thread.roomId);\n const $ = useOverrides(overrides);\n const firstCommentIndex = useMemo(() => {\n return showDeletedComments\n ? 0\n : thread.comments.findIndex((comment) => comment.body);\n }, [showDeletedComments, thread.comments]);\n const lastCommentIndex = useMemo(() => {\n return showDeletedComments\n ? thread.comments.length - 1\n : findLastIndex(thread.comments, (comment) => comment.body);\n }, [showDeletedComments, thread.comments]);\n const { status: subscriptionStatus, unreadSince } = useThreadSubscription(\n thread.id\n );\n const unreadIndex = useMemo(() => {\n // The user is not subscribed to this thread.\n if (subscriptionStatus !== \"subscribed\") {\n return;\n }\n\n // The user hasn't read the thread yet, so all comments are unread.\n if (unreadSince === null) {\n return firstCommentIndex;\n }\n\n // The user has read the thread, so we find the first unread comment.\n const unreadIndex = thread.comments.findIndex(\n (comment) =>\n (showDeletedComments ? true : comment.body) &&\n comment.createdAt > unreadSince\n );\n\n return unreadIndex >= 0 && unreadIndex < thread.comments.length\n ? unreadIndex\n : undefined;\n }, [\n firstCommentIndex,\n showDeletedComments,\n subscriptionStatus,\n thread.comments,\n unreadSince,\n ]);\n const [newIndex, setNewIndex] = useState<number>();\n const newIndicatorIndex = newIndex === undefined ? unreadIndex : newIndex;\n\n useEffect(() => {\n if (unreadIndex) {\n // Keep the \"new\" indicator at the lowest unread index.\n setNewIndex((persistedUnreadIndex) =>\n Math.min(persistedUnreadIndex ?? Infinity, unreadIndex)\n );\n }\n }, [unreadIndex]);\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n const handleResolvedChange = useCallback(\n (resolved: boolean) => {\n onResolvedChange?.(resolved);\n\n if (resolved) {\n markThreadAsResolved(thread.id);\n } else {\n markThreadAsUnresolved(thread.id);\n }\n },\n [\n markThreadAsResolved,\n markThreadAsUnresolved,\n onResolvedChange,\n thread.id,\n ]\n );\n\n const handleCommentDelete = useCallback(\n (comment: CommentData) => {\n onCommentDelete?.(comment);\n\n const filteredComments = thread.comments.filter(\n (comment) => comment.body\n );\n\n if (filteredComments.length <= 1) {\n onThreadDelete?.(thread);\n }\n },\n [onCommentDelete, onThreadDelete, thread]\n );\n\n return (\n <TooltipProvider>\n <div\n className={classNames(\n \"lb-root lb-thread\",\n showActions === \"hover\" && \"lb-thread:show-actions-hover\",\n className\n )}\n data-resolved={thread.resolved ? \"\" : undefined}\n data-unread={unreadIndex !== undefined ? \"\" : undefined}\n dir={$.dir}\n {...props}\n ref={forwardedRef}\n >\n <div className=\"lb-thread-comments\">\n {thread.comments.map((comment, index) => {\n const isFirstComment = index === firstCommentIndex;\n const isUnread =\n unreadIndex !== undefined && index >= unreadIndex;\n\n const children = (\n <Comment\n key={comment.id}\n className=\"lb-thread-comment\"\n data-unread={isUnread ? \"\" : undefined}\n comment={comment}\n indentContent={indentCommentContent}\n showDeleted={showDeletedComments}\n showActions={showActions}\n showReactions={showReactions}\n showAttachments={showAttachments}\n showComposerFormattingControls={\n showComposerFormattingControls\n }\n onCommentEdit={onCommentEdit}\n onCommentDelete={handleCommentDelete}\n onAuthorClick={onAuthorClick}\n onMentionClick={onMentionClick}\n onAttachmentClick={onAttachmentClick}\n autoMarkReadThreadId={\n index === lastCommentIndex && isUnread\n ? thread.id\n : undefined\n }\n additionalActionsClassName={\n isFirstComment ? \"lb-thread-actions\" : undefined\n }\n additionalActions={\n isFirstComment && showResolveAction ? (\n <Tooltip\n content={\n thread.resolved\n ? $.THREAD_UNRESOLVE\n : $.THREAD_RESOLVE\n }\n >\n <TogglePrimitive.Root\n pressed={thread.resolved}\n onPressedChange={handleResolvedChange}\n asChild\n >\n <Button\n className=\"lb-comment-action\"\n onClick={stopPropagation}\n aria-label={\n thread.resolved\n ? $.THREAD_UNRESOLVE\n : $.THREAD_RESOLVE\n }\n >\n {thread.resolved ? (\n <ResolvedIcon className=\"lb-button-icon\" />\n ) : (\n <ResolveIcon className=\"lb-button-icon\" />\n )}\n </Button>\n </TogglePrimitive.Root>\n </Tooltip>\n ) : null\n }\n />\n );\n\n return index === newIndicatorIndex &&\n newIndicatorIndex !== firstCommentIndex &&\n newIndicatorIndex <= lastCommentIndex ? (\n <Fragment key={comment.id}>\n <div\n className=\"lb-thread-new-indicator\"\n aria-label={$.THREAD_NEW_INDICATOR_DESCRIPTION}\n >\n <span className=\"lb-thread-new-indicator-label\">\n <ArrowDownIcon className=\"lb-thread-new-indicator-label-icon\" />\n {$.THREAD_NEW_INDICATOR}\n </span>\n </div>\n {children}\n </Fragment>\n ) : (\n children\n );\n })}\n </div>\n {showComposer && (\n <Composer\n className=\"lb-thread-composer\"\n threadId={thread.id}\n defaultCollapsed={showComposer === \"collapsed\" ? true : undefined}\n showAttachments={showAttachments}\n showFormattingControls={showComposerFormattingControls}\n onComposerSubmit={onComposerSubmit}\n overrides={{\n COMPOSER_PLACEHOLDER: $.THREAD_COMPOSER_PLACEHOLDER,\n COMPOSER_SEND: $.THREAD_COMPOSER_SEND,\n }}\n roomId={thread.roomId}\n />\n )}\n </div>\n </TooltipProvider>\n );\n }\n) as <M extends BaseMetadata = DM>(\n props: ThreadProps<M> & RefAttributes<HTMLDivElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA2JO;AAAe;AAElB;AACE;AACuB;AACT;AACd;AACoB;AACJ;AACD;AACG;AACe;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACG;AAIL;AACA;AACA;AACA;AACE;AAEuD;AAEzD;AACE;AAE4D;AAE9D;AAAoD;AAC3C;AAET;AAEE;AACE;AAAA;AAIF;AACE;AAAO;AAIT;AAAoC;AAGZ;AAGxB;AAEI;AACH;AACD;AACA;AACA;AACO;AACP;AAEF;AACA;AAEA;AACE;AAEE;AAAA;AACwD;AACxD;AACF;AAGF;AACE;AAAsB;AAGxB;AAA6B;AAEzB;AAEA;AACE;AAA8B;AAE9B;AAAgC;AAClC;AACF;AACA;AACE;AACA;AACA;AACO;AACT;AAGF;AAA4B;AAExB;AAEA;AAAyC;AAClB;AAGvB;AACE;AAAuB;AACzB;AACF;AACwC;AAG1C;AAEK;AACY;AACT;AAC2B;AAC3B;AACF;AACsC;AACQ;AACvC;AACH;AACC;AAEJ;AAAc;AAEX;AACA;AAGA;AACG;AACc;AACH;AACmB;AAC7B;AACe;AACF;AACb;AACA;AACA;AACA;AAGA;AACiB;AACjB;AACA;AACA;AAIM;AAGmC;AAIpC;AAIS;AAGP;AACiB;AACC;AACV;AAEN;AACW;AACD;AAID;AAIL;AAAuB;AAEvB;AAAsB;AAK7B;AAKV;AAGG;AAAsB;AACpB;AACW;AACI;AAEb;AAAe;AACb;AAAwB;AAO/B;AAKH;AACW;AACO;AACuC;AACxD;AACwB;AACxB;AACW;AACe;AACP;AACnB;AACe;AAIvB;AAGN;;"}
|
|
1
|
+
{"version":3,"file":"Thread.mjs","sources":["../../src/components/Thread.tsx"],"sourcesContent":["\"use client\";\n\nimport type {\n BaseMetadata,\n CommentData,\n DM,\n ThreadData,\n} from \"@liveblocks/core\";\nimport { useThreadSubscription } from \"@liveblocks/react\";\nimport {\n useMarkRoomThreadAsResolved,\n useMarkRoomThreadAsUnresolved,\n} from \"@liveblocks/react/_private\";\nimport * as TogglePrimitive from \"@radix-ui/react-toggle\";\nimport type {\n ComponentPropsWithoutRef,\n ForwardedRef,\n RefAttributes,\n SyntheticEvent,\n} from \"react\";\nimport {\n forwardRef,\n Fragment,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\n\nimport { ArrowDownIcon } from \"../icons/ArrowDown\";\nimport { ResolveIcon } from \"../icons/Resolve\";\nimport { ResolvedIcon } from \"../icons/Resolved\";\nimport type {\n CommentOverrides,\n ComposerOverrides,\n GlobalOverrides,\n ThreadOverrides,\n} from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport { classNames } from \"../utils/class-names\";\nimport { findLastIndex } from \"../utils/find-last-index\";\nimport type { CommentProps } from \"./Comment\";\nimport { Comment } from \"./Comment\";\nimport type { ComposerProps } from \"./Composer\";\nimport { Composer } from \"./Composer\";\nimport { Button } from \"./internal/Button\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\n\nexport interface ThreadProps<M extends BaseMetadata = DM>\n extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The thread to display.\n */\n thread: ThreadData<M>;\n\n /**\n * How to show or hide the composer to reply to the thread.\n */\n showComposer?: boolean | \"collapsed\";\n\n /**\n * Whether to show the action to resolve the thread.\n */\n showResolveAction?: boolean;\n\n /**\n * How to show or hide the actions.\n */\n showActions?: CommentProps[\"showActions\"];\n\n /**\n * Whether to show reactions.\n */\n showReactions?: CommentProps[\"showReactions\"];\n\n /**\n * Whether to show the composer's formatting controls.\n */\n showComposerFormattingControls?: ComposerProps[\"showFormattingControls\"];\n\n /**\n * Whether to indent the comments' content.\n */\n indentCommentContent?: CommentProps[\"indentContent\"];\n\n /**\n * Whether to show deleted comments.\n */\n showDeletedComments?: CommentProps[\"showDeleted\"];\n\n /**\n * Whether to show attachments.\n */\n showAttachments?: boolean;\n\n /**\n * The event handler called when changing the resolved status.\n */\n onResolvedChange?: (resolved: boolean) => void;\n\n /**\n * The event handler called when a comment is edited.\n */\n onCommentEdit?: CommentProps[\"onCommentEdit\"];\n\n /**\n * The event handler called when a comment is deleted.\n */\n onCommentDelete?: CommentProps[\"onCommentDelete\"];\n\n /**\n * The event handler called when the thread is deleted.\n * A thread is deleted when all its comments are deleted.\n */\n onThreadDelete?: (thread: ThreadData<M>) => void;\n\n /**\n * The event handler called when clicking on a comment's author.\n */\n onAuthorClick?: CommentProps[\"onAuthorClick\"];\n\n /**\n * The event handler called when clicking on a mention.\n */\n onMentionClick?: CommentProps[\"onMentionClick\"];\n\n /**\n * The event handler called when clicking on a comment's attachment.\n */\n onAttachmentClick?: CommentProps[\"onAttachmentClick\"];\n\n /**\n * The event handler called when the composer is submitted.\n */\n onComposerSubmit?: ComposerProps[\"onComposerSubmit\"];\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<\n GlobalOverrides & ThreadOverrides & CommentOverrides & ComposerOverrides\n >;\n}\n\n/**\n * Displays a thread of comments, with a composer to reply\n * to it.\n *\n * @example\n * <>\n * {threads.map((thread) => (\n * <Thread key={thread.id} thread={thread} />\n * ))}\n * </>\n */\nexport const Thread = forwardRef(\n <M extends BaseMetadata = DM>(\n {\n thread,\n indentCommentContent = true,\n showActions = \"hover\",\n showDeletedComments,\n showResolveAction = true,\n showReactions = true,\n showComposer = \"collapsed\",\n showAttachments = true,\n showComposerFormattingControls = true,\n onResolvedChange,\n onCommentEdit,\n onCommentDelete,\n onThreadDelete,\n onAuthorClick,\n onMentionClick,\n onAttachmentClick,\n onComposerSubmit,\n overrides,\n className,\n ...props\n }: ThreadProps<M>,\n forwardedRef: ForwardedRef<HTMLDivElement>\n ) => {\n const markThreadAsResolved = useMarkRoomThreadAsResolved(thread.roomId);\n const markThreadAsUnresolved = useMarkRoomThreadAsUnresolved(thread.roomId);\n const $ = useOverrides(overrides);\n const firstCommentIndex = useMemo(() => {\n return showDeletedComments\n ? 0\n : thread.comments.findIndex((comment) => comment.body);\n }, [showDeletedComments, thread.comments]);\n const lastCommentIndex = useMemo(() => {\n return showDeletedComments\n ? thread.comments.length - 1\n : findLastIndex(thread.comments, (comment) => comment.body);\n }, [showDeletedComments, thread.comments]);\n const { status: subscriptionStatus, unreadSince } = useThreadSubscription(\n thread.id\n );\n const unreadIndex = useMemo(() => {\n // The user is not subscribed to this thread.\n if (subscriptionStatus !== \"subscribed\") {\n return;\n }\n\n // The user hasn't read the thread yet, so all comments are unread.\n if (unreadSince === null) {\n return firstCommentIndex;\n }\n\n // The user has read the thread, so we find the first unread comment.\n const unreadIndex = thread.comments.findIndex(\n (comment) =>\n (showDeletedComments ? true : comment.body) &&\n comment.createdAt > unreadSince\n );\n\n return unreadIndex >= 0 && unreadIndex < thread.comments.length\n ? unreadIndex\n : undefined;\n }, [\n firstCommentIndex,\n showDeletedComments,\n subscriptionStatus,\n thread.comments,\n unreadSince,\n ]);\n const [newIndex, setNewIndex] = useState<number>();\n const newIndicatorIndex = newIndex === undefined ? unreadIndex : newIndex;\n\n useEffect(() => {\n if (unreadIndex) {\n // Keep the \"new\" indicator at the lowest unread index.\n setNewIndex((persistedUnreadIndex) =>\n Math.min(persistedUnreadIndex ?? Infinity, unreadIndex)\n );\n }\n }, [unreadIndex]);\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n const handleResolvedChange = useCallback(\n (resolved: boolean) => {\n onResolvedChange?.(resolved);\n\n if (resolved) {\n markThreadAsResolved(thread.id);\n } else {\n markThreadAsUnresolved(thread.id);\n }\n },\n [\n markThreadAsResolved,\n markThreadAsUnresolved,\n onResolvedChange,\n thread.id,\n ]\n );\n\n const handleCommentDelete = useCallback(\n (comment: CommentData) => {\n onCommentDelete?.(comment);\n\n const filteredComments = thread.comments.filter(\n (comment) => comment.body\n );\n\n if (filteredComments.length <= 1) {\n onThreadDelete?.(thread);\n }\n },\n [onCommentDelete, onThreadDelete, thread]\n );\n\n return (\n <TooltipProvider>\n <div\n className={classNames(\n \"lb-root lb-thread\",\n showActions === \"hover\" && \"lb-thread:show-actions-hover\",\n className\n )}\n data-resolved={thread.resolved ? \"\" : undefined}\n data-unread={unreadIndex !== undefined ? \"\" : undefined}\n dir={$.dir}\n {...props}\n ref={forwardedRef}\n >\n <div className=\"lb-thread-comments\">\n {thread.comments.map((comment, index) => {\n const isFirstComment = index === firstCommentIndex;\n const isUnread =\n unreadIndex !== undefined && index >= unreadIndex;\n\n const children = (\n <Comment\n key={comment.id}\n className=\"lb-thread-comment\"\n data-unread={isUnread ? \"\" : undefined}\n comment={comment}\n indentContent={indentCommentContent}\n showDeleted={showDeletedComments}\n showActions={showActions}\n showReactions={showReactions}\n showAttachments={showAttachments}\n showComposerFormattingControls={\n showComposerFormattingControls\n }\n onCommentEdit={onCommentEdit}\n onCommentDelete={handleCommentDelete}\n onAuthorClick={onAuthorClick}\n onMentionClick={onMentionClick}\n onAttachmentClick={onAttachmentClick}\n autoMarkReadThreadId={\n index === lastCommentIndex && isUnread\n ? thread.id\n : undefined\n }\n additionalActionsClassName={\n isFirstComment ? \"lb-thread-actions\" : undefined\n }\n additionalActions={\n isFirstComment && showResolveAction ? (\n <Tooltip\n content={\n thread.resolved\n ? $.THREAD_UNRESOLVE\n : $.THREAD_RESOLVE\n }\n >\n <TogglePrimitive.Root\n pressed={thread.resolved}\n onPressedChange={handleResolvedChange}\n asChild\n >\n <Button\n className=\"lb-comment-action\"\n onClick={stopPropagation}\n aria-label={\n thread.resolved\n ? $.THREAD_UNRESOLVE\n : $.THREAD_RESOLVE\n }\n >\n {thread.resolved ? (\n <ResolvedIcon className=\"lb-button-icon\" />\n ) : (\n <ResolveIcon className=\"lb-button-icon\" />\n )}\n </Button>\n </TogglePrimitive.Root>\n </Tooltip>\n ) : null\n }\n />\n );\n\n return index === newIndicatorIndex &&\n newIndicatorIndex !== firstCommentIndex &&\n newIndicatorIndex <= lastCommentIndex ? (\n <Fragment key={comment.id}>\n <div\n className=\"lb-thread-new-indicator\"\n aria-label={$.THREAD_NEW_INDICATOR_DESCRIPTION}\n >\n <span className=\"lb-thread-new-indicator-label\">\n <ArrowDownIcon className=\"lb-thread-new-indicator-label-icon\" />\n {$.THREAD_NEW_INDICATOR}\n </span>\n </div>\n {children}\n </Fragment>\n ) : (\n children\n );\n })}\n </div>\n {showComposer && (\n <Composer\n className=\"lb-thread-composer\"\n threadId={thread.id}\n defaultCollapsed={showComposer === \"collapsed\" ? true : undefined}\n showAttachments={showAttachments}\n showFormattingControls={showComposerFormattingControls}\n onComposerSubmit={onComposerSubmit}\n overrides={{\n COMPOSER_PLACEHOLDER: $.THREAD_COMPOSER_PLACEHOLDER,\n COMPOSER_SEND: $.THREAD_COMPOSER_SEND,\n }}\n roomId={thread.roomId}\n />\n )}\n </div>\n </TooltipProvider>\n );\n }\n) as <M extends BaseMetadata = DM>(\n props: ThreadProps<M> & RefAttributes<HTMLDivElement>\n) => JSX.Element;\n"],"names":["unreadIndex","comment"],"mappings":"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"}
|