{
  "version": 3,
  "sources": ["../../src/canvas/thread-view.tsx"],
  "sourcesContent": ["import { memo, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n\tcreateComment,\n\tEditor,\n\tEditorPortal,\n\tTLComment,\n\tTLCommentThread,\n\tTLRichText,\n\tTldrawUiButton,\n\tTldrawUiDropdownMenuContent,\n\tTldrawUiDropdownMenuGroup,\n\tTldrawUiDropdownMenuItem,\n\tTldrawUiDropdownMenuRoot,\n\tTldrawUiDropdownMenuTrigger,\n\tTldrawUiIcon,\n\tuseContainer,\n\tusePassThroughWheelEvents,\n\tuseTranslation,\n\tuseValue,\n} from 'tldraw'\nimport { CommentCard, CommentCardProps } from '../ui/comment-card'\nimport { CommentComposer } from '../ui/comment-composer'\nimport { EMPTY_COMMENT, isCommentEmpty } from '../ui/comment-extensions'\nimport { CommentThread } from '../ui/comment-thread'\nimport { CommentBody } from './comment-body'\nimport {\n\tclearCommentDraft,\n\tgetCommentDraft,\n\treplyDraftSlot,\n\tsaveCommentDraft,\n} from './comment-drafts'\nimport {\n\tcommitCommentMutation,\n\tdeleteComment,\n\tdeleteThread,\n\teditComment,\n\treopenThread,\n\tresolveThread,\n} from './comment-mutations'\nimport { CommentReactionPicker, CommentReactions } from './comment-reactions'\nimport { UNKNOWN_AUTHOR, UNKNOWN_COMMENT_AUTHOR } from './comment-render'\nimport { type CommentingContext } from './context'\nimport { useThreadComments } from './hooks'\nimport { useIsMobileCommenting, useMobilePlacement } from './mobile-placement'\nimport {\n\ttype CommentingComponents,\n\tgetCanModifyComment,\n\tuseCanComment,\n\tuseCanModifyComment,\n\tuseCommentingOptions,\n} from './options'\nimport { openThreadId } from './state'\n\nconst stop = (e: { stopPropagation(): void }) => e.stopPropagation()\n\n/**\n * A name-only view of an author resolver, for the mention/rich-text paths. Stable identity, so\n * `CommentBody`'s memoized render doesn't recompute on every render of its host.\n */\nexport function useResolveName(resolveAuthor: CommentingContext['resolveAuthor']) {\n\treturn useCallback((id: string) => resolveAuthor(id)?.name, [resolveAuthor])\n}\n\n/** How long the copy-link item reads \"Link copied\" before reverting. */\nconst LINK_COPIED_MS = 2000\n\n/**\n * What a thread's `getThreadHref` should put on the clipboard. Hosts may hand back a relative href,\n * which is meaningless once pasted elsewhere, so it's resolved against the current document first.\n * An href the URL parser can't make sense of is copied as-is rather than dropped.\n *\n * @internal\n */\nexport function absoluteThreadLink(href: string, base = window.location.href): string {\n\ttry {\n\t\treturn new URL(href, base).toString()\n\t} catch {\n\t\treturn href\n\t}\n}\n\n/**\n * Copy a thread's link, with a flag that stays set briefly afterwards so the control can confirm.\n * Only set once the write resolves, so a withheld clipboard doesn't claim a copy that didn't happen.\n */\nfunction useCopyLink(href: string | undefined) {\n\tconst [copied, setCopied] = useState(false)\n\tuseEffect(() => {\n\t\tif (!copied) return\n\t\tconst timeout = window.setTimeout(() => setCopied(false), LINK_COPIED_MS)\n\t\treturn () => window.clearTimeout(timeout)\n\t}, [copied])\n\tconst copy = useCallback(() => {\n\t\tif (href === undefined) return\n\t\tnavigator.clipboard?.writeText(absoluteThreadLink(href)).then(\n\t\t\t() => setCopied(true),\n\t\t\t() => setCopied(false)\n\t\t)\n\t}, [href])\n\treturn [copied, copy] as const\n}\n\nexport function toCardProps(\n\tcomment: TLComment,\n\tprops: Pick<CommentingContext, 'currentUserId' | 'resolveAuthor'>,\n\tcomponents: CommentingComponents,\n\tresolveName: (id: string) => string | undefined\n): CommentCardProps {\n\tconst Body = components.CommentBody\n\t// The `CommentBody` component slot overrides the built-in rich-text default (which resolves\n\t// mention ids to names).\n\tconst body = Body ? (\n\t\t<Body comment={comment} />\n\t) : (\n\t\t<CommentBody richText={comment.body} resolveName={resolveName} />\n\t)\n\treturn {\n\t\tauthor: props.resolveAuthor(comment.authorId) ?? UNKNOWN_COMMENT_AUTHOR,\n\t\tbody,\n\t\tdate: new Date(comment.createdAt).toISOString(),\n\t\tyou: comment.authorId === props.currentUserId,\n\t\tedited: comment.editedAt != null,\n\t}\n}\n\n/** A pin is this square (mirrors `--tlui-cmt-pin-size`). The two marker kinds differ in size *and*\n *  anchor point, so lining their previews up means correcting for both. Keep in sync with the CSS. */\nconst PIN_SIZE = 28\n\n/** A cluster/stack badge is this square (`--tlui-cmt-marker-size`) \u2014 pin-sized, so the marker\n *  kinds read as one family. Keep in sync with the stylesheet. */\nconst MARKER_SIZE = PIN_SIZE\n\n/** Where a popover's top card sits vertically, measured from the marker visual's middle. */\nconst CARD_TOP_Y = -28\n\n/** The horizontal gap between a marker visual's right edge and its popover/preview panel. The\n *  preview's hover bridge spans exactly this (see `--tlui-cmt-preview-bridge`). */\nconst PREVIEW_GAP = 6\n\n/**\n * Where a marker's popover sits relative to the marker's anchor point. The hover preview uses the\n * same origins, so moving a popover here moves its preview with it.\n *\n * Both marker kinds hang off their point the same way (`translate(0, -100%)`), differing only in\n * size \u2014 so each offset clears its own width plus the shared gap, and re-bases the shared card-top\n * measure from its bottom anchor to its middle.\n */\nexport const POPOVER_OFFSET = {\n\tthread: { x: PIN_SIZE + PREVIEW_GAP, y: CARD_TOP_Y - PIN_SIZE / 2 },\n\tlist: { x: MARKER_SIZE + PREVIEW_GAP, y: CARD_TOP_Y - MARKER_SIZE / 2 },\n} as const\n\n/** The open thread's popover container, portaled above the UI panels. A wheel over it passes\n *  through to the canvas (unless it scrolls its own content), like tldraw's panels. */\nexport function ThreadPopover({\n\tbase,\n\tchildren,\n}: {\n\tbase: { x: number; y: number }\n\tchildren: ReactNode\n}) {\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\t// On mobile the popover slides off its fixed offset to stay above the software keyboard and\n\t// on-screen; desktop keeps the fixed offset (base returned unchanged).\n\tconst isMobile = useIsMobileCommenting()\n\tconst placed = useMobilePlacement(ref, base, isMobile)\n\treturn (\n\t\t<EditorPortal>\n\t\t\t{/* contextmenu also stops here: portals bubble React events to the canvas's context-menu\n\t\t\t    trigger (the layer mounts inside it), which would open the canvas menu over this panel. */}\n\t\t\t<div\n\t\t\t\tref={ref}\n\t\t\t\tclassName=\"tlui-cmt-canvas-popover\"\n\t\t\t\tstyle={{ left: placed.left, top: placed.top }}\n\t\t\t\tonPointerDown={stop}\n\t\t\t\tonContextMenu={stop}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</EditorPortal>\n\t)\n}\n\n/**\n * One thread's interactive view: its comments, the reply composer, edit-in-place on your own\n * comments, and the resolve/delete actions. Read receipts are reported for every unread comment\n * while mounted, so only mount it where the thread is actually being shown.\n *\n * Memoized because the popover position rides the pin's per-frame render point, so the pin\n * re-renders on every camera frame while a thread is open.\n */\nexport const ThreadView = memo(function ThreadView({\n\teditor,\n\tthread,\n\t...props\n}: CommentingContext & { editor: Editor; thread: TLCommentThread }) {\n\tconst {\n\t\tcurrentUserId,\n\t\tresolveAuthor,\n\t\tonPostComment,\n\t\tisCommentUnread,\n\t\tonCommentsRead,\n\t\tgetMentionSuggestions,\n\t\trenderMentionSuggestion,\n\t\tgetThreadHref,\n\t} = props\n\tconst options = useCommentingOptions()\n\tconst comments = useThreadComments(editor, thread.id)\n\tconst msg = useTranslation()\n\tconst resolveName = useResolveName(resolveAuthor)\n\t// Rebuilt only when the comments change, not on every render \u2014 each of which would otherwise\n\t// re-allocate a date string and body element per comment.\n\tconst cards = useMemo(\n\t\t() =>\n\t\t\tcomments.map((c) =>\n\t\t\t\ttoCardProps(c, { currentUserId, resolveAuthor }, options.components, resolveName)\n\t\t\t),\n\t\t[comments, currentUserId, resolveAuthor, options.components, resolveName]\n\t)\n\tconst me = currentUserId ? resolveAuthor(currentUserId) : undefined\n\t// Composing, editing, deleting, and resolving are all gated on the viewer's permission. Where it's\n\t// withheld the composer gives way to the ComposerFallback slot and the affordances are hidden.\n\tconst canComment = useCanComment(currentUserId)\n\t// Editing and deleting are further per-record: the author's to do by default, wider or narrower\n\t// under a `canModifyComment` callback. Computed for the thread's comments in one pass, since\n\t// `renderComment` is a callback rather than a component and can't call a hook per comment.\n\tconst commentPermissions = useValue(\n\t\t'comment permissions',\n\t\t() =>\n\t\t\tnew Map(\n\t\t\t\tcomments.map((comment) => [\n\t\t\t\t\tcomment.id,\n\t\t\t\t\t{\n\t\t\t\t\t\tedit: getCanModifyComment(editor, currentUserId, { action: 'edit-comment', comment }),\n\t\t\t\t\t\tdelete: getCanModifyComment(editor, currentUserId, {\n\t\t\t\t\t\t\taction: 'delete-comment',\n\t\t\t\t\t\t\tcomment,\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t])\n\t\t\t),\n\t\t[editor, currentUserId, comments]\n\t)\n\t// Deleting a thread is its creator's by default (and server-enforced); `canModifyComment` is what\n\t// widens that. Still a commenting write, so `canComment` stays the outer gate.\n\tconst canModifyThread = useCanModifyComment(currentUserId, { action: 'delete-thread', thread })\n\tconst canDeleteThread = canComment && canModifyThread\n\tconst ComposerFallback = options.components.ComposerFallback\n\t// An unsent reply survives closing the thread (saved on every change, keyed by thread id) \u2014\n\t// the flip side of dismissing without a discard warning.\n\tconst [reply, setReply] = useState<TLRichText>(\n\t\t() => getCommentDraft(replyDraftSlot(thread.id)) ?? EMPTY_COMMENT\n\t)\n\tconst [editingId, setEditingId] = useState<string | null>(null)\n\tconst [editText, setEditText] = useState<TLRichText>(EMPTY_COMMENT)\n\tconst canReply = canComment && !thread.resolved\n\tconst container = useContainer()\n\t// Resolved when the composer closes rather than held as an element: the card unmounts while the\n\t// composer stands in its place, so the node captured on the way in is gone by the way out.\n\tconst editReturnFocus = useRef<(() => HTMLElement | null) | null>(null)\n\n\t// Tab from the canvas drops the caret in the reply box: a pin click leaves focus on the editor\n\t// container, so the first Tab would otherwise walk the app's UI. Capture phase, once per open thread.\n\tconst [focusReply, setFocusReply] = useState(false)\n\tconst tabTaken = useRef(false)\n\tconst swallowTabUp = useRef(false)\n\tuseEffect(() => {\n\t\tif (!canReply) {\n\t\t\t// Resolving unmounts the reply box under an open thread. Reopening it should feel like a\n\t\t\t// freshly opened thread: no autoFocus left armed from the last Tab, and Tab available again.\n\t\t\tsetFocusReply(false)\n\t\t\ttabTaken.current = false\n\t\t\treturn\n\t\t}\n\t\tconst doc = container.ownerDocument\n\t\tconst onKeyDown = (e: KeyboardEvent) => {\n\t\t\tif (e.key !== 'Tab' || e.shiftKey || e.metaKey || e.ctrlKey || e.altKey) return\n\t\t\tif (e.defaultPrevented || tabTaken.current) return\n\t\t\t// Focus rests on the container (or nothing) after a pin click. Anywhere else is deliberate, and\n\t\t\t// Tab belongs to whatever holds it.\n\t\t\tif (e.target !== container && e.target !== doc.body) return\n\t\t\ttabTaken.current = true\n\t\t\tswallowTabUp.current = true\n\t\t\tsetFocusReply(true)\n\t\t\te.preventDefault()\n\t\t\te.stopPropagation()\n\t\t}\n\t\t// The select tool navigates shapes on Tab's *keyup*, so a quick tap would both focus the reply and\n\t\t// step the selection. Swallow the release of the press we took, and only that one.\n\t\tconst onKeyUp = (e: KeyboardEvent) => {\n\t\t\tif (e.key !== 'Tab' || !swallowTabUp.current) return\n\t\t\tswallowTabUp.current = false\n\t\t\te.preventDefault()\n\t\t\te.stopPropagation()\n\t\t}\n\t\tdoc.addEventListener('keydown', onKeyDown, true)\n\t\tdoc.addEventListener('keyup', onKeyUp, true)\n\t\treturn () => {\n\t\t\tdoc.removeEventListener('keydown', onKeyDown, true)\n\t\t\tdoc.removeEventListener('keyup', onKeyUp, true)\n\t\t}\n\t}, [canReply, container])\n\n\t// Leaving the edit composer unmounts it while it holds focus, dropping focus to the editor\n\t// container \u2014 outside the thread, so a Tab from there walks the app's UI. Hand focus back to\n\t// whatever opened the composer instead.\n\tuseEffect(() => {\n\t\tif (editingId !== null) return\n\t\tconst resolve = editReturnFocus.current\n\t\teditReturnFocus.current = null\n\t\t// Runs after React has swapped the card back in, so the target is mounted again by now.\n\t\tresolve?.()?.focus()\n\t}, [editingId])\n\n\t// Reported as one batch so the host can record the receipts in a single write. The write flips\n\t// isCommentUnread to false, so re-runs find nothing to report.\n\tuseEffect(() => {\n\t\tif (!isCommentUnread || !onCommentsRead) return\n\t\tconst unreadIds = comments.filter((comment) => isCommentUnread(comment.id)).map((c) => c.id)\n\t\tif (unreadIds.length > 0) {\n\t\t\tonCommentsRead(unreadIds)\n\t\t}\n\t}, [comments, isCommentUnread, onCommentsRead])\n\n\tconst postReply = () => {\n\t\tif (isCommentEmpty(reply) || !currentUserId) return\n\t\tconst comment = commitCommentMutation(editor, ({ put }) => {\n\t\t\tconst comment = createComment({\n\t\t\t\tthreadId: thread.id,\n\t\t\t\tpageId: thread.pageId,\n\t\t\t\tauthorId: currentUserId,\n\t\t\t\tbody: reply,\n\t\t\t})\n\t\t\tput([comment])\n\t\t\treturn comment\n\t\t})\n\t\tsetReply(EMPTY_COMMENT)\n\t\tclearCommentDraft(replyDraftSlot(thread.id))\n\t\t// The host's callback is its own operation, not part of the post's history scope. It runs\n\t\t// last so a throwing host can't strand the composer holding a draft of a posted reply.\n\t\tonPostComment?.(comment)\n\t}\n\n\tconst toggleResolve = () => {\n\t\tif (!currentUserId) return\n\t\tif (thread.resolved) reopenThread(editor, thread)\n\t\telse resolveThread(editor, thread, currentUserId)\n\t}\n\n\t// No `currentUserId` check: unlike a resolve, a delete stamps nothing on the record, so who may\n\t// make it is `canModifyComment`'s call alone (which withholds it from an unidentified viewer by\n\t// default).\n\tconst removeThread = () => {\n\t\tdeleteThread(editor, thread)\n\t}\n\n\tconst ThreadActions = options.components.ThreadActions\n\t// The host's URL for this thread. Its presence is what puts \"copy link\" in the header menu.\n\tconst threadHref = getThreadHref?.(thread.id)\n\tconst [linkCopied, copyThreadLink] = useCopyLink(threadHref)\n\n\tconst startEdit = (comment: TLComment, { fromMoreMenu = false } = {}) => {\n\t\t// Edit from the \u22EF menu comes back to that button, looked up again on the way out since the card\n\t\t// unmounts. Otherwise return to whatever held focus, ignoring the body and the editor container.\n\t\tconst active = container.ownerDocument.activeElement\n\t\teditReturnFocus.current = fromMoreMenu\n\t\t\t? () => container.querySelector<HTMLElement>(`[data-cmt-more-for=\"${comment.id}\"]`)\n\t\t\t: active instanceof HTMLElement && active !== container && active !== document.body\n\t\t\t\t? () => (active.isConnected ? active : null)\n\t\t\t\t: null\n\t\tsetEditingId(comment.id)\n\t\tsetEditText(comment.body)\n\t}\n\n\tconst saveEdit = () => {\n\t\tconst comment = comments.find((c) => c.id === editingId)\n\t\tif (!comment || isCommentEmpty(editText)) return\n\t\teditComment(editor, comment, editText)\n\t\tsetEditingId(null)\n\t}\n\n\t// Swap a comment for a pre-filled composer while it's being edited; otherwise show the card,\n\t// with the affordances the viewer is allowed on it.\n\tconst renderComment = (card: CommentCardProps, index: number): ReactNode => {\n\t\tconst comment = comments[index]\n\t\tconst permissions = commentPermissions.get(comment.id)\n\t\tif (editingId === comment.id) {\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"tlui-cmt-editing\"\n\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\tif (e.key === 'Escape') {\n\t\t\t\t\t\t\tsetEditingId(null)\n\t\t\t\t\t\t\te.stopPropagation()\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<CommentComposer\n\t\t\t\t\t\tauthor={card.author}\n\t\t\t\t\t\tplaceholder={msg('comments.edit-placeholder')}\n\t\t\t\t\t\tvalue={editText}\n\t\t\t\t\t\tonChange={setEditText}\n\t\t\t\t\t\tonSubmit={saveEdit}\n\t\t\t\t\t\tsendLabel={msg('comments.save')}\n\t\t\t\t\t\tdisabled={isCommentEmpty(editText)}\n\t\t\t\t\t\tgetMentionSuggestions={getMentionSuggestions}\n\t\t\t\t\t\trenderMentionSuggestion={renderMentionSuggestion}\n\t\t\t\t\t\tautoFocus\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\t\treturn (\n\t\t\t<CommentCard\n\t\t\t\t{...card}\n\t\t\t\tfooter={\n\t\t\t\t\t<CommentReactions\n\t\t\t\t\t\tcomment={comment}\n\t\t\t\t\t\t// Reacting is a commenting write: without `canComment` the tally renders\n\t\t\t\t\t\t// read-only (no identity \u2192 pills aren't clickable).\n\t\t\t\t\t\tcurrentUserId={canComment ? currentUserId : null}\n\t\t\t\t\t\tresolveName={resolveName}\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\tactions={\n\t\t\t\t\tcanComment && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{(permissions?.edit || permissions?.delete) && (\n\t\t\t\t\t\t\t\t<TldrawUiDropdownMenuRoot id={`comment-actions-${comment.id}`}>\n\t\t\t\t\t\t\t\t\t<TldrawUiDropdownMenuTrigger>\n\t\t\t\t\t\t\t\t\t\t<TldrawUiButton\n\t\t\t\t\t\t\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\ttooltip={msg('comments.more-options')}\n\t\t\t\t\t\t\t\t\t\t\ttitle={msg('comments.more-options')}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"tlui-cmt-thread__action\"\n\t\t\t\t\t\t\t\t\t\t\tdata-cmt-more-for={comment.id}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<TldrawUiIcon\n\t\t\t\t\t\t\t\t\t\t\t\ticon=\"dots-vertical\"\n\t\t\t\t\t\t\t\t\t\t\t\tlabel={msg('comments.more-options')}\n\t\t\t\t\t\t\t\t\t\t\t\tsmall\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</TldrawUiButton>\n\t\t\t\t\t\t\t\t\t</TldrawUiDropdownMenuTrigger>\n\t\t\t\t\t\t\t\t\t<TldrawUiDropdownMenuContent\n\t\t\t\t\t\t\t\t\t\tclassName=\"tlui-cmt-menu\"\n\t\t\t\t\t\t\t\t\t\tside=\"bottom\"\n\t\t\t\t\t\t\t\t\t\talign=\"start\"\n\t\t\t\t\t\t\t\t\t\talignOffset={0}\n\t\t\t\t\t\t\t\t\t\tsideOffset={4}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<TldrawUiDropdownMenuGroup>\n\t\t\t\t\t\t\t\t\t\t\t{permissions?.edit && (\n\t\t\t\t\t\t\t\t\t\t\t\t<TldrawUiDropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"tlui-cmt-menu-item\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => startEdit(comment, { fromMoreMenu: true })}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span>{msg('comments.edit')}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t</TldrawUiDropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t{permissions?.delete && (\n\t\t\t\t\t\t\t\t\t\t\t\t<TldrawUiDropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"tlui-cmt-menu-item tlui-cmt-menu-item--danger\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => deleteComment(editor, comment)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span>{msg('action.delete')}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t</TldrawUiDropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</TldrawUiDropdownMenuGroup>\n\t\t\t\t\t\t\t\t\t</TldrawUiDropdownMenuContent>\n\t\t\t\t\t\t\t\t</TldrawUiDropdownMenuRoot>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{/* Last so react is always the rightmost pill. */}\n\t\t\t\t\t\t\t<CommentReactionPicker comment={comment} currentUserId={currentUserId} />\n\t\t\t\t\t\t</>\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t/>\n\t\t)\n\t}\n\n\t// Resolve and delete are commenting writes: behind `canComment`, plus the `currentUserId` a\n\t// resolve stamps into `resolved.by`.\n\tconst resolveLabel = msg(thread.resolved ? 'comments.reopen' : 'comments.resolve')\n\tconst headerActions = (\n\t\t<>\n\t\t\t{/* Host verbs \u2014 assign, link a ticket \u2014 sit ahead of the built-in actions. */}\n\t\t\t{ThreadActions && <ThreadActions thread={thread} comments={comments} />}\n\t\t\t{(threadHref !== undefined || canDeleteThread) && (\n\t\t\t\t<TldrawUiDropdownMenuRoot id={`comment-thread-actions-${thread.id}`}>\n\t\t\t\t\t<TldrawUiDropdownMenuTrigger>\n\t\t\t\t\t\t<TldrawUiButton\n\t\t\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\t\t\ttooltip={msg('comments.more-options')}\n\t\t\t\t\t\t\ttitle={msg('comments.more-options')}\n\t\t\t\t\t\t\tclassName=\"tlui-cmt-thread__action\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<TldrawUiIcon icon=\"dots-vertical\" label={msg('comments.more-options')} small />\n\t\t\t\t\t\t</TldrawUiButton>\n\t\t\t\t\t</TldrawUiDropdownMenuTrigger>\n\t\t\t\t\t<TldrawUiDropdownMenuContent\n\t\t\t\t\t\tclassName=\"tlui-cmt-menu\"\n\t\t\t\t\t\tside=\"bottom\"\n\t\t\t\t\t\talign=\"start\"\n\t\t\t\t\t\talignOffset={0}\n\t\t\t\t\t\tsideOffset={4}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TldrawUiDropdownMenuGroup>\n\t\t\t\t\t\t\t{/* A link is a read affordance: offered to anyone who can see the thread,\n\t\t\t\t\t\t\t    including a viewer who can't comment. `noClose` keeps the menu up so the\n\t\t\t\t\t\t\t    item can confirm the copy in place. */}\n\t\t\t\t\t\t\t{threadHref !== undefined && (\n\t\t\t\t\t\t\t\t<TldrawUiDropdownMenuItem noClose>\n\t\t\t\t\t\t\t\t\t<button type=\"button\" className=\"tlui-cmt-menu-item\" onClick={copyThreadLink}>\n\t\t\t\t\t\t\t\t\t\t<span>{msg(linkCopied ? 'comments.link-copied' : 'comments.copy-link')}</span>\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</TldrawUiDropdownMenuItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{canDeleteThread && (\n\t\t\t\t\t\t\t\t<TldrawUiDropdownMenuItem>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"tlui-cmt-menu-item tlui-cmt-menu-item--danger\"\n\t\t\t\t\t\t\t\t\t\tonClick={removeThread}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<span>{msg('comments.delete')}</span>\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</TldrawUiDropdownMenuItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</TldrawUiDropdownMenuGroup>\n\t\t\t\t\t</TldrawUiDropdownMenuContent>\n\t\t\t\t</TldrawUiDropdownMenuRoot>\n\t\t\t)}\n\t\t\t{canComment && currentUserId && (\n\t\t\t\t<TldrawUiButton\n\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\ttooltip={resolveLabel}\n\t\t\t\t\ttitle={resolveLabel}\n\t\t\t\t\tclassName=\"tlui-cmt-thread__action\"\n\t\t\t\t\tonClick={toggleResolve}\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiIcon icon=\"check\" label={resolveLabel} small />\n\t\t\t\t</TldrawUiButton>\n\t\t\t)}\n\t\t\t<TldrawUiButton\n\t\t\t\ttype=\"icon\"\n\t\t\t\ttooltip={msg('comments.dismiss')}\n\t\t\t\ttitle={msg('comments.dismiss')}\n\t\t\t\tclassName=\"tlui-cmt-thread__action\"\n\t\t\t\tonClick={() => openThreadId.set(editor, null)}\n\t\t\t>\n\t\t\t\t<TldrawUiIcon icon=\"cross-2\" label={msg('comments.dismiss')} small />\n\t\t\t</TldrawUiButton>\n\t\t</>\n\t)\n\n\treturn (\n\t\t<CommentThread\n\t\t\theader={msg('comments.thread-title')}\n\t\t\theaderActions={headerActions}\n\t\t\trenderComment={renderComment}\n\t\t\tcomments={cards}\n\t\t\tresolvedBanner={\n\t\t\t\tthread.resolved\n\t\t\t\t\t? msg('comments.resolved-by').replace(\n\t\t\t\t\t\t\t'{name}',\n\t\t\t\t\t\t\tresolveAuthor(thread.resolved.by)?.name ?? UNKNOWN_AUTHOR\n\t\t\t\t\t\t)\n\t\t\t\t\t: undefined\n\t\t\t}\n\t\t\tcomposer={\n\t\t\t\tcanReply\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tauthor: me ?? UNKNOWN_COMMENT_AUTHOR,\n\t\t\t\t\t\t\tplaceholder: msg('comments.reply-placeholder'),\n\t\t\t\t\t\t\tsendLabel: msg('comments.send'),\n\t\t\t\t\t\t\tvalue: reply,\n\t\t\t\t\t\t\tonChange: (value: TLRichText) => {\n\t\t\t\t\t\t\t\tsetReply(value)\n\t\t\t\t\t\t\t\tsaveCommentDraft(replyDraftSlot(thread.id), value)\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonSubmit: postReply,\n\t\t\t\t\t\t\t// Up in the empty reply box edits the comment directly above it, chat-style \u2014\n\t\t\t\t\t\t\t// only when you're allowed to edit it (the same gate as the Edit link).\n\t\t\t\t\t\t\tonArrowUpWhenEmpty: () => {\n\t\t\t\t\t\t\t\tconst last = comments[comments.length - 1]\n\t\t\t\t\t\t\t\tif (last && commentPermissions.get(last.id)?.edit) startEdit(last)\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t// No user, no author for the record \u2014 dead send button.\n\t\t\t\t\t\t\tdisabled: isCommentEmpty(reply) || !currentUserId,\n\t\t\t\t\t\t\tgetMentionSuggestions,\n\t\t\t\t\t\t\trenderMentionSuggestion,\n\t\t\t\t\t\t\t// Reuses the composer's own focus path, so the caret lands at the end of a\n\t\t\t\t\t\t\t// restored draft rather than in front of it.\n\t\t\t\t\t\t\tautoFocus: focusReply,\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined\n\t\t\t}\n\t\t\tfooter={\n\t\t\t\t!canComment && !thread.resolved && ComposerFallback ? (\n\t\t\t\t\t<ComposerFallback context=\"thread\" />\n\t\t\t\t) : undefined\n\t\t\t}\n\t\t/>\n\t)\n})\n"],
  "mappings": "AAgHE,SA4TI,UA5TJ,KAqVQ,YArVR;AAhHF,SAAS,MAAiB,aAAa,WAAW,SAAS,QAAQ,gBAAgB;AACnF;AAAA,EACC;AAAA,EAEA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,mBAAqC;AAC9C,SAAS,uBAAuB;AAChC,SAAS,eAAe,sBAAsB;AAC9C,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAC5B;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,uBAAuB,wBAAwB;AACxD,SAAS,gBAAgB,8BAA8B;AAEvD,SAAS,yBAAyB;AAClC,SAAS,uBAAuB,0BAA0B;AAC1D;AAAA,EAEC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,oBAAoB;AAE7B,MAAM,OAAO,CAAC,MAAmC,EAAE,gBAAgB;AAM5D,SAAS,eAAe,eAAmD;AACjF,SAAO,YAAY,CAAC,OAAe,cAAc,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AAC5E;AAGA,MAAM,iBAAiB;AAShB,SAAS,mBAAmB,MAAc,OAAO,OAAO,SAAS,MAAc;AACrF,MAAI;AACH,WAAO,IAAI,IAAI,MAAM,IAAI,EAAE,SAAS;AAAA,EACrC,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAMA,SAAS,YAAY,MAA0B;AAC9C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,YAAU,MAAM;AACf,QAAI,CAAC,OAAQ;AACb,UAAM,UAAU,OAAO,WAAW,MAAM,UAAU,KAAK,GAAG,cAAc;AACxE,WAAO,MAAM,OAAO,aAAa,OAAO;AAAA,EACzC,GAAG,CAAC,MAAM,CAAC;AACX,QAAM,OAAO,YAAY,MAAM;AAC9B,QAAI,SAAS,OAAW;AACxB,cAAU,WAAW,UAAU,mBAAmB,IAAI,CAAC,EAAE;AAAA,MACxD,MAAM,UAAU,IAAI;AAAA,MACpB,MAAM,UAAU,KAAK;AAAA,IACtB;AAAA,EACD,GAAG,CAAC,IAAI,CAAC;AACT,SAAO,CAAC,QAAQ,IAAI;AACrB;AAEO,SAAS,YACf,SACA,OACA,YACA,aACmB;AACnB,QAAM,OAAO,WAAW;AAGxB,QAAM,OAAO,OACZ,oBAAC,QAAK,SAAkB,IAExB,oBAAC,eAAY,UAAU,QAAQ,MAAM,aAA0B;AAEhE,SAAO;AAAA,IACN,QAAQ,MAAM,cAAc,QAAQ,QAAQ,KAAK;AAAA,IACjD;AAAA,IACA,MAAM,IAAI,KAAK,QAAQ,SAAS,EAAE,YAAY;AAAA,IAC9C,KAAK,QAAQ,aAAa,MAAM;AAAA,IAChC,QAAQ,QAAQ,YAAY;AAAA,EAC7B;AACD;AAIA,MAAM,WAAW;AAIjB,MAAM,cAAc;AAGpB,MAAM,aAAa;AAInB,MAAM,cAAc;AAUb,MAAM,iBAAiB;AAAA,EAC7B,QAAQ,EAAE,GAAG,WAAW,aAAa,GAAG,aAAa,WAAW,EAAE;AAAA,EAClE,MAAM,EAAE,GAAG,cAAc,aAAa,GAAG,aAAa,cAAc,EAAE;AACvE;AAIO,SAAS,cAAc;AAAA,EAC7B;AAAA,EACA;AACD,GAGG;AACF,QAAM,MAAM,OAAuB,IAAI;AACvC,4BAA0B,GAAG;AAG7B,QAAM,WAAW,sBAAsB;AACvC,QAAM,SAAS,mBAAmB,KAAK,MAAM,QAAQ;AACrD,SACC,oBAAC,gBAGA;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA,WAAU;AAAA,MACV,OAAO,EAAE,MAAM,OAAO,MAAM,KAAK,OAAO,IAAI;AAAA,MAC5C,eAAe;AAAA,MACf,eAAe;AAAA,MAEd;AAAA;AAAA,EACF,GACD;AAEF;AAUO,MAAM,aAAa,KAAK,SAASA,YAAW;AAAA,EAClD;AAAA,EACA;AAAA,EACA,GAAG;AACJ,GAAoE;AACnE,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI;AACJ,QAAM,UAAU,qBAAqB;AACrC,QAAM,WAAW,kBAAkB,QAAQ,OAAO,EAAE;AACpD,QAAM,MAAM,eAAe;AAC3B,QAAM,cAAc,eAAe,aAAa;AAGhD,QAAM,QAAQ;AAAA,IACb,MACC,SAAS;AAAA,MAAI,CAAC,MACb,YAAY,GAAG,EAAE,eAAe,cAAc,GAAG,QAAQ,YAAY,WAAW;AAAA,IACjF;AAAA,IACD,CAAC,UAAU,eAAe,eAAe,QAAQ,YAAY,WAAW;AAAA,EACzE;AACA,QAAM,KAAK,gBAAgB,cAAc,aAAa,IAAI;AAG1D,QAAM,aAAa,cAAc,aAAa;AAI9C,QAAM,qBAAqB;AAAA,IAC1B;AAAA,IACA,MACC,IAAI;AAAA,MACH,SAAS,IAAI,CAAC,YAAY;AAAA,QACzB,QAAQ;AAAA,QACR;AAAA,UACC,MAAM,oBAAoB,QAAQ,eAAe,EAAE,QAAQ,gBAAgB,QAAQ,CAAC;AAAA,UACpF,QAAQ,oBAAoB,QAAQ,eAAe;AAAA,YAClD,QAAQ;AAAA,YACR;AAAA,UACD,CAAC;AAAA,QACF;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IACD,CAAC,QAAQ,eAAe,QAAQ;AAAA,EACjC;AAGA,QAAM,kBAAkB,oBAAoB,eAAe,EAAE,QAAQ,iBAAiB,OAAO,CAAC;AAC9F,QAAM,kBAAkB,cAAc;AACtC,QAAM,mBAAmB,QAAQ,WAAW;AAG5C,QAAM,CAAC,OAAO,QAAQ,IAAI;AAAA,IACzB,MAAM,gBAAgB,eAAe,OAAO,EAAE,CAAC,KAAK;AAAA,EACrD;AACA,QAAM,CAAC,WAAW,YAAY,IAAI,SAAwB,IAAI;AAC9D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAqB,aAAa;AAClE,QAAM,WAAW,cAAc,CAAC,OAAO;AACvC,QAAM,YAAY,aAAa;AAG/B,QAAM,kBAAkB,OAA0C,IAAI;AAItE,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,WAAW,OAAO,KAAK;AAC7B,QAAM,eAAe,OAAO,KAAK;AACjC,YAAU,MAAM;AACf,QAAI,CAAC,UAAU;AAGd,oBAAc,KAAK;AACnB,eAAS,UAAU;AACnB;AAAA,IACD;AACA,UAAM,MAAM,UAAU;AACtB,UAAM,YAAY,CAAC,MAAqB;AACvC,UAAI,EAAE,QAAQ,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,OAAQ;AACzE,UAAI,EAAE,oBAAoB,SAAS,QAAS;AAG5C,UAAI,EAAE,WAAW,aAAa,EAAE,WAAW,IAAI,KAAM;AACrD,eAAS,UAAU;AACnB,mBAAa,UAAU;AACvB,oBAAc,IAAI;AAClB,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAAA,IACnB;AAGA,UAAM,UAAU,CAAC,MAAqB;AACrC,UAAI,EAAE,QAAQ,SAAS,CAAC,aAAa,QAAS;AAC9C,mBAAa,UAAU;AACvB,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAAA,IACnB;AACA,QAAI,iBAAiB,WAAW,WAAW,IAAI;AAC/C,QAAI,iBAAiB,SAAS,SAAS,IAAI;AAC3C,WAAO,MAAM;AACZ,UAAI,oBAAoB,WAAW,WAAW,IAAI;AAClD,UAAI,oBAAoB,SAAS,SAAS,IAAI;AAAA,IAC/C;AAAA,EACD,GAAG,CAAC,UAAU,SAAS,CAAC;AAKxB,YAAU,MAAM;AACf,QAAI,cAAc,KAAM;AACxB,UAAM,UAAU,gBAAgB;AAChC,oBAAgB,UAAU;AAE1B,cAAU,GAAG,MAAM;AAAA,EACpB,GAAG,CAAC,SAAS,CAAC;AAId,YAAU,MAAM;AACf,QAAI,CAAC,mBAAmB,CAAC,eAAgB;AACzC,UAAM,YAAY,SAAS,OAAO,CAAC,YAAY,gBAAgB,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE;AAC3F,QAAI,UAAU,SAAS,GAAG;AACzB,qBAAe,SAAS;AAAA,IACzB;AAAA,EACD,GAAG,CAAC,UAAU,iBAAiB,cAAc,CAAC;AAE9C,QAAM,YAAY,MAAM;AACvB,QAAI,eAAe,KAAK,KAAK,CAAC,cAAe;AAC7C,UAAM,UAAU,sBAAsB,QAAQ,CAAC,EAAE,IAAI,MAAM;AAC1D,YAAMC,WAAU,cAAc;AAAA,QAC7B,UAAU,OAAO;AAAA,QACjB,QAAQ,OAAO;AAAA,QACf,UAAU;AAAA,QACV,MAAM;AAAA,MACP,CAAC;AACD,UAAI,CAACA,QAAO,CAAC;AACb,aAAOA;AAAA,IACR,CAAC;AACD,aAAS,aAAa;AACtB,sBAAkB,eAAe,OAAO,EAAE,CAAC;AAG3C,oBAAgB,OAAO;AAAA,EACxB;AAEA,QAAM,gBAAgB,MAAM;AAC3B,QAAI,CAAC,cAAe;AACpB,QAAI,OAAO,SAAU,cAAa,QAAQ,MAAM;AAAA,QAC3C,eAAc,QAAQ,QAAQ,aAAa;AAAA,EACjD;AAKA,QAAM,eAAe,MAAM;AAC1B,iBAAa,QAAQ,MAAM;AAAA,EAC5B;AAEA,QAAM,gBAAgB,QAAQ,WAAW;AAEzC,QAAM,aAAa,gBAAgB,OAAO,EAAE;AAC5C,QAAM,CAAC,YAAY,cAAc,IAAI,YAAY,UAAU;AAE3D,QAAM,YAAY,CAAC,SAAoB,EAAE,eAAe,MAAM,IAAI,CAAC,MAAM;AAGxE,UAAM,SAAS,UAAU,cAAc;AACvC,oBAAgB,UAAU,eACvB,MAAM,UAAU,cAA2B,uBAAuB,QAAQ,EAAE,IAAI,IAChF,kBAAkB,eAAe,WAAW,aAAa,WAAW,SAAS,OAC5E,MAAO,OAAO,cAAc,SAAS,OACrC;AACJ,iBAAa,QAAQ,EAAE;AACvB,gBAAY,QAAQ,IAAI;AAAA,EACzB;AAEA,QAAM,WAAW,MAAM;AACtB,UAAM,UAAU,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AACvD,QAAI,CAAC,WAAW,eAAe,QAAQ,EAAG;AAC1C,gBAAY,QAAQ,SAAS,QAAQ;AACrC,iBAAa,IAAI;AAAA,EAClB;AAIA,QAAM,gBAAgB,CAAC,MAAwB,UAA6B;AAC3E,UAAM,UAAU,SAAS,KAAK;AAC9B,UAAM,cAAc,mBAAmB,IAAI,QAAQ,EAAE;AACrD,QAAI,cAAc,QAAQ,IAAI;AAC7B,aACC;AAAA,QAAC;AAAA;AAAA,UACA,WAAU;AAAA,UACV,WAAW,CAAC,MAAM;AACjB,gBAAI,EAAE,QAAQ,UAAU;AACvB,2BAAa,IAAI;AACjB,gBAAE,gBAAgB;AAAA,YACnB;AAAA,UACD;AAAA,UAEA;AAAA,YAAC;AAAA;AAAA,cACA,QAAQ,KAAK;AAAA,cACb,aAAa,IAAI,2BAA2B;AAAA,cAC5C,OAAO;AAAA,cACP,UAAU;AAAA,cACV,UAAU;AAAA,cACV,WAAW,IAAI,eAAe;AAAA,cAC9B,UAAU,eAAe,QAAQ;AAAA,cACjC;AAAA,cACA;AAAA,cACA,WAAS;AAAA;AAAA,UACV;AAAA;AAAA,MACD;AAAA,IAEF;AACA,WACC;AAAA,MAAC;AAAA;AAAA,QACC,GAAG;AAAA,QACJ,QACC;AAAA,UAAC;AAAA;AAAA,YACA;AAAA,YAGA,eAAe,aAAa,gBAAgB;AAAA,YAC5C;AAAA;AAAA,QACD;AAAA,QAED,SACC,cACC,iCACG;AAAA,wBAAa,QAAQ,aAAa,WACnC,qBAAC,4BAAyB,IAAI,mBAAmB,QAAQ,EAAE,IAC1D;AAAA,gCAAC,+BACA;AAAA,cAAC;AAAA;AAAA,gBACA,MAAK;AAAA,gBACL,SAAS,IAAI,uBAAuB;AAAA,gBACpC,OAAO,IAAI,uBAAuB;AAAA,gBAClC,WAAU;AAAA,gBACV,qBAAmB,QAAQ;AAAA,gBAE3B;AAAA,kBAAC;AAAA;AAAA,oBACA,MAAK;AAAA,oBACL,OAAO,IAAI,uBAAuB;AAAA,oBAClC,OAAK;AAAA;AAAA,gBACN;AAAA;AAAA,YACD,GACD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACA,WAAU;AAAA,gBACV,MAAK;AAAA,gBACL,OAAM;AAAA,gBACN,aAAa;AAAA,gBACb,YAAY;AAAA,gBAEZ,+BAAC,6BACC;AAAA,+BAAa,QACb,oBAAC,4BACA;AAAA,oBAAC;AAAA;AAAA,sBACA,MAAK;AAAA,sBACL,WAAU;AAAA,sBACV,SAAS,MAAM,UAAU,SAAS,EAAE,cAAc,KAAK,CAAC;AAAA,sBAExD,8BAAC,UAAM,cAAI,eAAe,GAAE;AAAA;AAAA,kBAC7B,GACD;AAAA,kBAEA,aAAa,UACb,oBAAC,4BACA;AAAA,oBAAC;AAAA;AAAA,sBACA,MAAK;AAAA,sBACL,WAAU;AAAA,sBACV,SAAS,MAAM,cAAc,QAAQ,OAAO;AAAA,sBAE5C,8BAAC,UAAM,cAAI,eAAe,GAAE;AAAA;AAAA,kBAC7B,GACD;AAAA,mBAEF;AAAA;AAAA,YACD;AAAA,aACD;AAAA,UAGD,oBAAC,yBAAsB,SAAkB,eAA8B;AAAA,WACxE;AAAA;AAAA,IAGH;AAAA,EAEF;AAIA,QAAM,eAAe,IAAI,OAAO,WAAW,oBAAoB,kBAAkB;AACjF,QAAM,gBACL,iCAEE;AAAA,qBAAiB,oBAAC,iBAAc,QAAgB,UAAoB;AAAA,KACnE,eAAe,UAAa,oBAC7B,qBAAC,4BAAyB,IAAI,0BAA0B,OAAO,EAAE,IAChE;AAAA,0BAAC,+BACA;AAAA,QAAC;AAAA;AAAA,UACA,MAAK;AAAA,UACL,SAAS,IAAI,uBAAuB;AAAA,UACpC,OAAO,IAAI,uBAAuB;AAAA,UAClC,WAAU;AAAA,UAEV,8BAAC,gBAAa,MAAK,iBAAgB,OAAO,IAAI,uBAAuB,GAAG,OAAK,MAAC;AAAA;AAAA,MAC/E,GACD;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACA,WAAU;AAAA,UACV,MAAK;AAAA,UACL,OAAM;AAAA,UACN,aAAa;AAAA,UACb,YAAY;AAAA,UAEZ,+BAAC,6BAIC;AAAA,2BAAe,UACf,oBAAC,4BAAyB,SAAO,MAChC,8BAAC,YAAO,MAAK,UAAS,WAAU,sBAAqB,SAAS,gBAC7D,8BAAC,UAAM,cAAI,aAAa,yBAAyB,oBAAoB,GAAE,GACxE,GACD;AAAA,YAEA,mBACA,oBAAC,4BACA;AAAA,cAAC;AAAA;AAAA,gBACA,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS;AAAA,gBAET,8BAAC,UAAM,cAAI,iBAAiB,GAAE;AAAA;AAAA,YAC/B,GACD;AAAA,aAEF;AAAA;AAAA,MACD;AAAA,OACD;AAAA,IAEA,cAAc,iBACd;AAAA,MAAC;AAAA;AAAA,QACA,MAAK;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,QACP,WAAU;AAAA,QACV,SAAS;AAAA,QAET,8BAAC,gBAAa,MAAK,SAAQ,OAAO,cAAc,OAAK,MAAC;AAAA;AAAA,IACvD;AAAA,IAED;AAAA,MAAC;AAAA;AAAA,QACA,MAAK;AAAA,QACL,SAAS,IAAI,kBAAkB;AAAA,QAC/B,OAAO,IAAI,kBAAkB;AAAA,QAC7B,WAAU;AAAA,QACV,SAAS,MAAM,aAAa,IAAI,QAAQ,IAAI;AAAA,QAE5C,8BAAC,gBAAa,MAAK,WAAU,OAAO,IAAI,kBAAkB,GAAG,OAAK,MAAC;AAAA;AAAA,IACpE;AAAA,KACD;AAGD,SACC;AAAA,IAAC;AAAA;AAAA,MACA,QAAQ,IAAI,uBAAuB;AAAA,MACnC;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,gBACC,OAAO,WACJ,IAAI,sBAAsB,EAAE;AAAA,QAC5B;AAAA,QACA,cAAc,OAAO,SAAS,EAAE,GAAG,QAAQ;AAAA,MAC5C,IACC;AAAA,MAEJ,UACC,WACG;AAAA,QACA,QAAQ,MAAM;AAAA,QACd,aAAa,IAAI,4BAA4B;AAAA,QAC7C,WAAW,IAAI,eAAe;AAAA,QAC9B,OAAO;AAAA,QACP,UAAU,CAAC,UAAsB;AAChC,mBAAS,KAAK;AACd,2BAAiB,eAAe,OAAO,EAAE,GAAG,KAAK;AAAA,QAClD;AAAA,QACA,UAAU;AAAA;AAAA;AAAA,QAGV,oBAAoB,MAAM;AACzB,gBAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,cAAI,QAAQ,mBAAmB,IAAI,KAAK,EAAE,GAAG,KAAM,WAAU,IAAI;AAAA,QAClE;AAAA;AAAA,QAEA,UAAU,eAAe,KAAK,KAAK,CAAC;AAAA,QACpC;AAAA,QACA;AAAA;AAAA;AAAA,QAGA,WAAW;AAAA,MACZ,IACC;AAAA,MAEJ,QACC,CAAC,cAAc,CAAC,OAAO,YAAY,mBAClC,oBAAC,oBAAiB,SAAQ,UAAS,IAChC;AAAA;AAAA,EAEN;AAEF,CAAC;",
  "names": ["ThreadView", "comment"]
}
