@lovett/ui 0.0.11 → 0.2.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/chunk-RBYWGBQ2.js +2752 -0
- package/dist/chunk-RBYWGBQ2.js.map +1 -0
- package/dist/index.d.ts +5574 -57
- package/dist/index.js +21650 -11206
- package/dist/index.js.map +1 -1
- package/dist/rich-composer-impl-5NO443A6.js +1859 -0
- package/dist/rich-composer-impl-5NO443A6.js.map +1 -0
- package/dist/styles.css +1570 -0
- package/dist/tokens.css +112 -0
- package/package.json +8 -1
- package/src/__tests__/avatar.test.tsx +272 -0
- package/src/__tests__/bar-chart.test.tsx +809 -0
- package/src/__tests__/board.test.tsx +420 -0
- package/src/__tests__/chart-math.test.ts +922 -0
- package/src/__tests__/chart-series.test.ts +339 -0
- package/src/__tests__/code-block.test.tsx +134 -0
- package/src/__tests__/display-popover.test.tsx +195 -0
- package/src/__tests__/display-store.test.tsx +307 -0
- package/src/__tests__/donut-chart.test.tsx +397 -0
- package/src/__tests__/dropdown-menu.test.tsx +156 -2
- package/src/__tests__/filter-menu.test.tsx +175 -0
- package/src/__tests__/gauge-ring.test.tsx +233 -0
- package/src/__tests__/line-chart.test.tsx +612 -0
- package/src/__tests__/ranked-bars.test.tsx +343 -0
- package/src/__tests__/remark-underline.test.ts +194 -0
- package/src/__tests__/sortable.test.tsx +394 -0
- package/src/__tests__/sparkline.test.tsx +368 -0
- package/src/__tests__/stat-layer.test.tsx +271 -0
- package/src/__tests__/stat-strip.test.tsx +175 -0
- package/src/__tests__/status.test.tsx +293 -0
- package/src/__tests__/tabs.test.tsx +303 -0
- package/src/__tests__/token-shape.test.ts +132 -2
- package/src/avatar.tsx +352 -0
- package/src/bar-chart.tsx +1214 -0
- package/src/board.tsx +658 -0
- package/src/chart-frame.tsx +960 -0
- package/src/chart-legend.tsx +304 -0
- package/src/chart-tooltip.tsx +267 -0
- package/src/code-block.tsx +62 -8
- package/src/delta-chip.tsx +263 -0
- package/src/detail/__tests__/activity-pane.test.tsx +369 -0
- package/src/detail/__tests__/detail-chrome.test.tsx +134 -0
- package/src/detail/__tests__/detail-surface.test.tsx +529 -0
- package/src/detail/__tests__/field-row.test.tsx +357 -0
- package/src/detail/activity-pane.tsx +611 -0
- package/src/detail/calendar.tsx +355 -0
- package/src/detail/detail-divider.tsx +261 -0
- package/src/detail/detail-header.tsx +287 -0
- package/src/detail/detail-menu.tsx +254 -0
- package/src/detail/detail-surface.tsx +1110 -0
- package/src/detail/field-list.tsx +196 -0
- package/src/detail/field-row.tsx +1131 -0
- package/src/detail/index.ts +58 -0
- package/src/detail/segmented-choice.tsx +94 -0
- package/src/detail/types.ts +129 -0
- package/src/display-popover.tsx +487 -0
- package/src/display-store.tsx +301 -0
- package/src/donut-chart.tsx +988 -0
- package/src/dropdown-menu.tsx +290 -19
- package/src/filter-core/EXPORTS.md +85 -0
- package/src/filter-core/__tests__/columns.test.ts +159 -0
- package/src/filter-core/__tests__/faceting.test.ts +193 -0
- package/src/filter-core/__tests__/filter-fns.test.ts +519 -0
- package/src/filter-core/__tests__/operators.test.ts +235 -0
- package/src/filter-core/__tests__/state.test.ts +268 -0
- package/src/filter-core/__tests__/url.test.ts +350 -0
- package/src/filter-core/columns.ts +134 -0
- package/src/filter-core/date-utils.ts +38 -0
- package/src/filter-core/examples/task-filter-columns.ts +121 -0
- package/src/filter-core/faceting.ts +120 -0
- package/src/filter-core/filter-fns.ts +335 -0
- package/src/filter-core/index.ts +105 -0
- package/src/filter-core/operators.ts +433 -0
- package/src/filter-core/state.ts +280 -0
- package/src/filter-core/types.ts +247 -0
- package/src/filter-core/url.ts +261 -0
- package/src/filter-dropdown.tsx +12 -0
- package/src/filter-menu.tsx +649 -0
- package/src/floating-drawer.tsx +19 -1
- package/src/gauge-ring.tsx +435 -0
- package/src/hue.ts +52 -0
- package/src/index.ts +303 -0
- package/src/kbd.tsx +27 -4
- package/src/lib/chart.ts +866 -0
- package/src/lib/focus.ts +43 -1
- package/src/lib/layer-stack.ts +30 -3
- package/src/lib/remark-underline.ts +443 -0
- package/src/lib/series.ts +169 -0
- package/src/line-chart.tsx +1176 -0
- package/src/markdown.tsx +26 -7
- package/src/modal.tsx +42 -18
- package/src/progress-ledger.tsx +304 -0
- package/src/ranked-bars.tsx +386 -0
- package/src/segmented-pill.tsx +32 -9
- package/src/sortable.tsx +520 -1
- package/src/sparkline.tsx +416 -0
- package/src/stat-card.tsx +376 -0
- package/src/stat-strip.tsx +327 -0
- package/src/status.tsx +215 -0
- package/src/styles.css +1570 -0
- package/src/tabs.tsx +206 -25
- package/src/task-card.tsx +610 -0
- package/src/thread/__tests__/comment-body-hostile.test.tsx +331 -0
- package/src/thread/__tests__/comment-tree.test.ts +151 -0
- package/src/thread/__tests__/emoji.test.ts +187 -0
- package/src/thread/__tests__/fixtures/thread-fixture.ts +252 -0
- package/src/thread/__tests__/link-preview-source.test.ts +120 -0
- package/src/thread/__tests__/link-preview.test.tsx +600 -0
- package/src/thread/__tests__/markdown-format.test.ts +82 -0
- package/src/thread/__tests__/markdown-spec.test.ts +469 -0
- package/src/thread/__tests__/relative-time.test.ts +71 -0
- package/src/thread/__tests__/rich-composer.test.tsx +799 -0
- package/src/thread/__tests__/scroll-caret.test.ts +58 -0
- package/src/thread/__tests__/suggestion-list.test.tsx +648 -0
- package/src/thread/__tests__/thread-scroll-ownership.test.tsx +88 -0
- package/src/thread/__tests__/thread.test.tsx +742 -0
- package/src/thread/__tests__/use-attachments.test.tsx +679 -0
- package/src/thread/actions.tsx +196 -0
- package/src/thread/attachments.tsx +1071 -0
- package/src/thread/comment-body.tsx +148 -0
- package/src/thread/comment-tree.ts +182 -0
- package/src/thread/comment.tsx +967 -0
- package/src/thread/composer-footer.tsx +125 -0
- package/src/thread/composer.tsx +319 -0
- package/src/thread/emoji.ts +283 -0
- package/src/thread/index.ts +153 -0
- package/src/thread/link-preview.tsx +341 -0
- package/src/thread/markdown-format.ts +155 -0
- package/src/thread/markdown-spec.ts +754 -0
- package/src/thread/rail.tsx +372 -0
- package/src/thread/reactions.tsx +415 -0
- package/src/thread/relative-time.tsx +94 -0
- package/src/thread/rich-composer-impl.tsx +1601 -0
- package/src/thread/rich-composer.tsx +195 -0
- package/src/thread/scroll-caret.ts +37 -0
- package/src/thread/suggestion-list.tsx +182 -0
- package/src/thread/thread.tsx +718 -0
- package/src/thread/types.ts +232 -0
- package/src/thread/use-attachments.ts +598 -0
- package/src/thread/use-now.ts +73 -0
- package/src/thread/use-thread.ts +316 -0
- package/src/tokens.css +112 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/thread/scroll-caret.ts","../src/thread/emoji.ts","../src/thread/markdown-spec.ts","../src/thread/suggestion-list.tsx","../src/thread/rich-composer-impl.tsx"],"names":["ProseMirrorNode","ProseMirrorPluginKey","useRef","jsxs","jsx","useLayoutEffect","active","editor","rows","Fragment","UnderlineIcon","LinkIcon"],"mappings":"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","file":"rich-composer-impl-5NO443A6.js","sourcesContent":["/**\n * The scroll math behind `handleScrollToSelection` (ADR-148, owner report\n * 2026-09-07: \"when I did returns or new lines in the rich editor, the same\n * issue happened again\").\n *\n * It lives in its own module for one reason: it is the part that can be\n * tested. jsdom performs no layout, so `coordsAtPos` and\n * `getBoundingClientRect` are meaningless there — but the DECISION made from\n * those numbers is pure arithmetic, and that is where a sign error or an\n * off-by-a-line would hide.\n *\n * The rule: move the editor's own `scrollTop` by the smallest amount that puts\n * the caret inside the box with one line of slack, and never move anything\n * else. A single element's `scrollTop` cannot chain to an ancestor, which is\n * the entire point — ProseMirror's default walks up and scrolls every\n * scrollable ancestor it can find.\n */\n\nexport interface CaretBox {\n readonly top: number\n readonly bottom: number\n}\n\n/**\n * How far to move `scrollTop`. Positive scrolls down, negative up, 0 means the\n * caret is already comfortably inside.\n *\n * `pad` is one line height: a caret flush against the edge reads as clipped\n * even though it is technically visible.\n */\nexport function caretScrollDelta(box: CaretBox, caret: CaretBox, pad: number): number {\n // Above the top edge (plus slack) — pull up.\n if (caret.top < box.top + pad) return caret.top - (box.top + pad)\n // Below the bottom edge (minus slack) — push down.\n if (caret.bottom > box.bottom - pad) return caret.bottom - (box.bottom - pad)\n return 0\n}\n","/**\n * emoji — the curated shortcode table behind the `:` picker (ADR-149 D3).\n *\n * A HAND-MAINTAINED table, not a dataset. `emojibase-data` and friends are\n * ~1 MB and would load with the composer chunk for a feature whose whole job\n * is to save four keystrokes. This is roughly 150 entries covering what this\n * product's people actually reach for; adding one is a one-line PR against\n * `EMOJI_ROWS` below, and that is the intended maintenance model.\n *\n * EVERY GLYPH IS WRITTEN AS A `\\u{...}` ESCAPE, NEVER A RAW BYTE. A raw high\n * byte makes a source file grep as binary and blinds the CLAUDE.md §8 gates —\n * the lesson from ADR-147 D8, restated as ADR-149 AC#9. This file must stay\n * `US-ASCII`/`UTF-8 text` under `file(1)` with zero bytes >= 0x80, and so must\n * every test that names a glyph.\n *\n * DIALECT: GitHub shortcodes, the most widely known. Where Slack, Teams or a\n * person's muscle memory spells one differently, the difference is an ALIAS on\n * the same entry, never a second entry — the owner's `:side-eye:` is an alias\n * of GitHub's `roll_eyes`. `-` and `_` are interchangeable everywhere (the\n * query and the table are both normalized), so `:side-eye:` and `:side_eye:`\n * are the same lookup.\n *\n * OUT OF SCOPE for v1 (D3): skin-tone modifiers and ZWJ sequences. They\n * multiply the table and need a per-user preference to be anything but a\n * gimmick.\n */\n\nexport interface EmojiEntry {\n /** The canonical GitHub shortcode, without the surrounding colons. */\n readonly name: string\n /** The character itself. Written as `\\u{...}` at the source level. */\n readonly glyph: string\n /** Other spellings that resolve to this entry (Slack/Teams/plain English). */\n readonly aliases: readonly string[]\n /** Search terms that are not names — `:party:` has to find `tada`. */\n readonly keywords: readonly string[]\n}\n\n/**\n * One row per emoji: `[name, glyph, aliases, keywords]`, the two lists\n * pipe-joined so a row stays one line. Expanded once, below.\n */\ntype EmojiRow = readonly [name: string, glyph: string, aliases: string, keywords: string]\n\nconst EMOJI_ROWS: readonly EmojiRow[] = [\n /* ── Faces ───────────────────────────────────────────────────────────── */\n ['grinning', '\\u{1F600}', '', 'smile|happy|grin'],\n ['smiley', '\\u{1F603}', '', 'happy|joy|cheerful'],\n ['smile', '\\u{1F604}', '', 'happy|joy|laugh'],\n ['grin', '\\u{1F601}', '', 'happy|beam|pleased'],\n ['laughing', '\\u{1F606}', 'satisfied', 'haha|lol|funny'],\n ['sweat_smile', '\\u{1F605}', '', 'phew|relief|nervous'],\n ['joy', '\\u{1F602}', 'lol', 'laugh|tears|haha|funny'],\n ['rofl', '\\u{1F923}', 'rolling_on_the_floor_laughing', 'lol|haha|hilarious'],\n ['slightly_smiling_face', '\\u{1F642}', 'slight_smile', 'smile|fine|ok'],\n ['upside_down_face', '\\u{1F643}', 'upside_down', 'irony|sarcasm|silly'],\n ['wink', '\\u{1F609}', '', 'flirt|joke|kidding'],\n ['blush', '\\u{1F60A}', '', 'happy|shy|smile'],\n ['innocent', '\\u{1F607}', '', 'angel|halo|good'],\n ['heart_eyes', '\\u{1F60D}', '', 'love|adore|crush'],\n ['star_struck', '\\u{1F929}', '', 'amazed|wow|excited'],\n ['yum', '\\u{1F60B}', '', 'delicious|tasty|tongue'],\n ['raised_eyebrow', '\\u{1F928}', 'face_with_raised_eyebrow', 'skeptical|doubt|suspicious'],\n ['neutral_face', '\\u{1F610}', '', 'meh|blank|straight'],\n ['expressionless', '\\u{1F611}', '', 'blank|meh|deadpan'],\n ['smirk', '\\u{1F60F}', '', 'smug|sly|knowing'],\n ['unamused', '\\u{1F612}', '', 'meh|annoyed|unimpressed'],\n ['roll_eyes', '\\u{1F644}', 'face_with_rolling_eyes|side_eye|sideeye', 'whatever|annoyed|sarcasm|really'],\n ['grimacing', '\\u{1F62C}', '', 'awkward|eek|yikes'],\n ['relieved', '\\u{1F60C}', '', 'phew|calm|content'],\n ['pensive', '\\u{1F614}', '', 'sad|thoughtful|wistful'],\n ['sleeping', '\\u{1F634}', '', 'zzz|asleep|bored'],\n ['exploding_head', '\\u{1F92F}', 'mind_blown', 'mindblown|whoa|shocked'],\n ['partying_face', '\\u{1F973}', '', 'birthday|hooray|horn'],\n ['sunglasses', '\\u{1F60E}', '', 'cool|deal|smooth'],\n ['nerd_face', '\\u{1F913}', 'nerd', 'geek|glasses|smart'],\n ['monocle_face', '\\u{1F9D0}', 'monocle', 'inspect|scrutinize|examine'],\n ['confused', '\\u{1F615}', '', 'unsure|puzzled'],\n ['slightly_frowning_face', '\\u{1F641}', 'slight_frown', 'sad|frown'],\n ['open_mouth', '\\u{1F62E}', '', 'wow|surprise|shock'],\n ['flushed', '\\u{1F633}', '', 'blush|embarrassed|shy'],\n ['pleading_face', '\\u{1F97A}', 'pleading', 'puppy|beg|please'],\n ['fearful', '\\u{1F628}', '', 'scared|afraid|yikes'],\n ['cry', '\\u{1F622}', '', 'sad|tear|upset'],\n ['sob', '\\u{1F62D}', 'crying', 'bawl|sad|tears'],\n ['scream', '\\u{1F631}', '', 'horror|shock|panic'],\n ['disappointed', '\\u{1F61E}', '', 'sad|letdown'],\n ['weary', '\\u{1F629}', '', 'exhausted|tired|done'],\n ['tired_face', '\\u{1F62B}', '', 'exhausted|fed_up'],\n ['yawning_face', '\\u{1F971}', 'yawn', 'bored|sleepy|tired'],\n ['rage', '\\u{1F621}', 'enraged', 'angry|mad|furious'],\n ['angry', '\\u{1F620}', '', 'mad|annoyed|cross'],\n ['thinking', '\\u{1F914}', 'thinking_face|hmm', 'ponder|consider|unsure'],\n ['shushing_face', '\\u{1F92B}', 'shush', 'quiet|secret|hush'],\n ['zipper_mouth_face', '\\u{1F910}', 'zipper_mouth', 'secret|quiet|sealed'],\n ['saluting_face', '\\u{1FAE1}', 'salute', 'respect|acknowledge|yessir'],\n ['face_holding_back_tears', '\\u{1F979}', 'holding_back_tears', 'emotional|touched|proud'],\n ['clown_face', '\\u{1F921}', 'clown', 'joke|silly|circus'],\n ['ghost', '\\u{1F47B}', '', 'boo|spooky|halloween'],\n ['skull', '\\u{1F480}', '', 'dead|rip|died'],\n ['robot', '\\u{1F916}', 'robot_face', 'bot|automation|machine'],\n ['see_no_evil', '\\u{1F648}', '', 'monkey|hide|oops'],\n ['poop', '\\u{1F4A9}', 'hankey', 'bad|garbage|rubbish'],\n\n /* ── Hands and body ──────────────────────────────────────────────────── */\n ['+1', '\\u{1F44D}', 'thumbsup|thumbs_up|like', 'yes|agree|approve|ok'],\n ['-1', '\\u{1F44E}', 'thumbsdown|thumbs_down|dislike', 'no|disagree|reject'],\n ['ok_hand', '\\u{1F44C}', '', 'perfect|fine|good'],\n ['clap', '\\u{1F44F}', '', 'applause|bravo|well_done'],\n ['raised_hands', '\\u{1F64C}', '', 'praise|hooray|celebrate'],\n ['pray', '\\u{1F64F}', 'folded_hands', 'please|thanks|thank_you|hope'],\n ['muscle', '\\u{1F4AA}', 'flex', 'strong|strength|power'],\n ['wave', '\\u{1F44B}', '', 'hi|hello|bye|greeting'],\n ['point_right', '\\u{1F449}', '', 'this|direction|there'],\n ['point_left', '\\u{1F448}', '', 'that|direction|back'],\n ['crossed_fingers', '\\u{1F91E}', 'fingers_crossed', 'luck|hope|wish'],\n ['handshake', '\\u{1F91D}', '', 'deal|agree|partner'],\n ['writing_hand', '\\u{270D}\\u{FE0F}', 'writing', 'note|sign|draft'],\n ['eyes', '\\u{1F440}', '', 'look|watch|reviewing|see'],\n ['brain', '\\u{1F9E0}', '', 'smart|idea|think'],\n ['facepalm', '\\u{1F926}', '', 'oops|ugh|smh'],\n ['shrug', '\\u{1F937}', '', 'dunno|idk|whatever'],\n ['raising_hand', '\\u{1F64B}', 'raise_hand', 'question|volunteer|me'],\n\n /* ── Celebration and energy ──────────────────────────────────────────── */\n ['tada', '\\u{1F389}', 'party|hooray|celebrate', 'confetti|launch|ship|shipped|done'],\n ['sparkles', '\\u{2728}', '', 'shiny|magic|new|clean'],\n ['fire', '\\u{1F525}', 'flame|lit', 'hot|burning|great'],\n ['rocket', '\\u{1F680}', '', 'launch|ship|deploy|fast'],\n ['boom', '\\u{1F4A5}', 'collision', 'explode|bang|impact'],\n ['zap', '\\u{26A1}', 'lightning', 'fast|power|energy'],\n ['star', '\\u{2B50}', '', 'favourite|rating|good'],\n ['100', '\\u{1F4AF}', 'hundred|perfect', 'score|agree|exactly'],\n ['trophy', '\\u{1F3C6}', '', 'win|award|champion'],\n ['dart', '\\u{1F3AF}', 'bullseye|target', 'goal|aim|precise'],\n ['crown', '\\u{1F451}', '', 'king|queen|best'],\n ['gem', '\\u{1F48E}', 'diamond', 'jewel|valuable|premium'],\n ['bulb', '\\u{1F4A1}', 'idea|light_bulb', 'insight|bright|suggestion'],\n\n /* ── Work, status and objects ────────────────────────────────────────── */\n ['moneybag', '\\u{1F4B0}', 'money', 'budget|cash|spend'],\n ['chart_with_upwards_trend', '\\u{1F4C8}', 'chart_up|trending_up', 'growth|increase|up'],\n ['chart_with_downwards_trend', '\\u{1F4C9}', 'chart_down|trending_down', 'decline|decrease|down'],\n ['bar_chart', '\\u{1F4CA}', 'chart', 'data|report|stats'],\n ['clipboard', '\\u{1F4CB}', '', 'list|notes|tasks'],\n ['calendar', '\\u{1F4C5}', 'date', 'schedule|day|meeting'],\n ['pushpin', '\\u{1F4CC}', 'pin', 'pinned|note|important'],\n ['paperclip', '\\u{1F4CE}', 'attachment', 'attach|file|clip'],\n ['mag', '\\u{1F50D}', 'search|magnifying_glass', 'find|look|zoom'],\n ['lock', '\\u{1F512}', '', 'secure|private|closed'],\n ['unlock', '\\u{1F513}', '', 'open|access'],\n ['key', '\\u{1F511}', '', 'access|password|secret'],\n ['bell', '\\u{1F514}', 'notification', 'alert|ring|remind'],\n ['no_bell', '\\u{1F515}', 'mute', 'silence|quiet|off'],\n ['hourglass', '\\u{231B}', 'waiting', 'time|wait|pending'],\n ['alarm_clock', '\\u{23F0}', 'alarm', 'time|remind|deadline'],\n ['stopwatch', '\\u{23F1}\\u{FE0F}', 'timer', 'time|measure|speed'],\n ['warning', '\\u{26A0}\\u{FE0F}', 'caution', 'careful|alert|risk'],\n ['no_entry', '\\u{26D4}', 'blocked', 'stop|forbidden|blocker'],\n ['white_check_mark', '\\u{2705}', 'check|done', 'complete|yes|approved|shipped'],\n ['heavy_check_mark', '\\u{2714}\\u{FE0F}', 'checkmark|tick', 'done|yes|verified'],\n ['x', '\\u{274C}', 'cross_mark', 'no|wrong|cancel|failed'],\n ['question', '\\u{2753}', '', 'help|ask|unknown'],\n ['exclamation', '\\u{2757}', 'heavy_exclamation_mark', 'important|alert'],\n ['construction', '\\u{1F6A7}', 'wip', 'work_in_progress|building|roadworks'],\n ['hammer', '\\u{1F528}', '', 'build|fix|tool'],\n ['wrench', '\\u{1F527}', '', 'fix|tool|maintenance'],\n ['gear', '\\u{2699}\\u{FE0F}', 'settings', 'config|cog|options'],\n ['bug', '\\u{1F41B}', '', 'defect|issue|error'],\n ['computer', '\\u{1F4BB}', 'laptop', 'code|work|dev'],\n ['email', '\\u{2709}\\u{FE0F}', 'envelope', 'mail|message|send'],\n ['package', '\\u{1F4E6}', '', 'box|release|ship|delivery'],\n ['memo', '\\u{1F4DD}', 'note|pencil', 'write|notes|edit'],\n ['art', '\\u{1F3A8}', 'palette', 'creative|paint|design'],\n ['speech_balloon', '\\u{1F4AC}', 'comment', 'talk|message|chat'],\n ['thought_balloon', '\\u{1F4AD}', 'thought', 'idea|think|dream'],\n ['mega', '\\u{1F4E3}', 'megaphone|announce', 'announcement|shout|promote'],\n ['link', '\\u{1F517}', '', 'url|chain|connect'],\n ['globe_with_meridians', '\\u{1F310}', 'globe', 'internet|web|world'],\n\n /* ── Hearts ──────────────────────────────────────────────────────────── */\n ['heart', '\\u{2764}\\u{FE0F}', 'red_heart|love', 'like|adore'],\n ['broken_heart', '\\u{1F494}', '', 'sad|heartbreak'],\n ['sparkling_heart', '\\u{1F496}', '', 'love|sparkle'],\n ['two_hearts', '\\u{1F495}', '', 'love|cute'],\n\n /* ── Nature ──────────────────────────────────────────────────────────── */\n ['sunny', '\\u{2600}\\u{FE0F}', 'sun', 'weather|clear|bright'],\n ['rainbow', '\\u{1F308}', '', 'colour|pride|hope'],\n ['seedling', '\\u{1F331}', 'sprout', 'grow|new|plant'],\n ['four_leaf_clover', '\\u{1F340}', 'clover', 'luck|lucky'],\n ['unicorn', '\\u{1F984}', '', 'magic|rare|special'],\n\n /* ── Food and drink ──────────────────────────────────────────────────── */\n ['coffee', '\\u{2615}', 'cafe', 'caffeine|morning|espresso'],\n ['beer', '\\u{1F37A}', '', 'drink|cheers|friday'],\n ['champagne', '\\u{1F37E}', '', 'celebrate|launch|cheers'],\n ['clinking_glasses', '\\u{1F942}', 'cheers', 'toast|celebrate'],\n ['pizza', '\\u{1F355}', '', 'food|slice'],\n ['birthday', '\\u{1F382}', 'birthday_cake', 'cake|celebrate'],\n\n /* ── Play ────────────────────────────────────────────────────────────── */\n ['video_game', '\\u{1F3AE}', 'gamepad', 'play|gaming'],\n ['gift', '\\u{1F381}', 'present', 'birthday|surprise'],\n]\n\nfunction splitList(value: string): readonly string[] {\n return value === '' ? [] : value.split('|')\n}\n\n/** The table, expanded. Order is the tie-break in {@link searchEmoji}. */\nexport const THREAD_EMOJI: readonly EmojiEntry[] = EMOJI_ROWS.map(\n ([name, glyph, aliases, keywords]) => ({\n name,\n glyph,\n aliases: splitList(aliases),\n keywords: splitList(keywords),\n }),\n)\n\n/**\n * One spelling rule for both sides of the lookup: case-insensitive, `-` and\n * `_` interchangeable, surrounding colons ignored. That is what makes the\n * owner's `:side-eye:` and GitHub's `:side_eye:` the same key without a second\n * table row.\n */\nexport function normalizeShortcode(value: string): string {\n return value.trim().toLowerCase().replace(/^:+|:+$/g, '').replaceAll('-', '_')\n}\n\nconst BY_SHORTCODE: ReadonlyMap<string, EmojiEntry> = (() => {\n const map = new Map<string, EmojiEntry>()\n for (const entry of THREAD_EMOJI) {\n for (const code of [entry.name, ...entry.aliases]) {\n const key = normalizeShortcode(code)\n // First writer wins, so a canonical name can never be shadowed by an\n // alias added later in the table.\n if (!map.has(key)) map.set(key, entry)\n }\n }\n return map\n})()\n\n/** Resolve one shortcode — `tada`, `:tada:`, `side-eye` — to its entry. */\nexport function emojiByShortcode(code: string): EmojiEntry | undefined {\n return BY_SHORTCODE.get(normalizeShortcode(code))\n}\n\n/**\n * Rank, most specific first: an exact name, an exact alias, an exact keyword,\n * then the prefix forms of each. `:party:` therefore finds `tada` (alias,\n * exact) ahead of `partying_face` (name, prefix) — D3's worked example.\n * Anything that matches nothing scores `null` and is dropped.\n */\nfunction score(entry: EmojiEntry, query: string): number | null {\n if (entry.name === query) return 0\n if (entry.aliases.includes(query)) return 1\n if (entry.keywords.includes(query)) return 2\n if (entry.name.startsWith(query)) return 3\n if (entry.aliases.some((alias) => alias.startsWith(query))) return 4\n if (entry.keywords.some((keyword) => keyword.startsWith(query))) return 5\n return null\n}\n\n/** How many options the popup shows at once. */\nexport const EMOJI_RESULT_LIMIT = 8\n\n/**\n * Prefix search over names, aliases and keywords (D4). An empty query returns\n * nothing on purpose — the `:` trigger has a two-character threshold, and a\n * bare colon must stay punctuation.\n */\nexport function searchEmoji(query: string, limit: number = EMOJI_RESULT_LIMIT): readonly EmojiEntry[] {\n const normalized = normalizeShortcode(query)\n if (normalized === '') return []\n const ranked: { readonly entry: EmojiEntry; readonly rank: number; readonly order: number }[] = []\n for (const [order, entry] of THREAD_EMOJI.entries()) {\n const rank = score(entry, normalized)\n if (rank !== null) ranked.push({ entry, rank, order })\n }\n ranked.sort((a, b) => (a.rank === b.rank ? a.order - b.order : a.rank - b.rank))\n return ranked.slice(0, limit).map((match) => match.entry)\n}\n","/**\n * markdown-spec — the editor side of the thread wire format.\n *\n * ADR-148 D3, D4, D13. `body_md` is markdown and stays markdown (D1): the rich\n * editor is an editing surface over that string, never a second storage\n * format. This file is the ONLY place the editor learns how the two syntaxes\n * ADR-147 D11 / ADR-148 D13 add on top of CommonMark + GFM are spelled:\n *\n * @[Marcus Webb](user:usr_9f2) <-> a `mention` node (D4)\n * ++underlined++ <-> the `underline` mark (D13)\n *\n * …plus the fail-closed detector `isRichEditable` (D3 rule 2), and the two\n * helpers the composer and the tests both use, `parseRichMarkdown` /\n * `serializeRichMarkdown`, so there is exactly one parse and one serialize\n * path in the package.\n *\n * NOT re-exported from the package barrel, on purpose. Everything here imports\n * TipTap statically, and the barrel must stay free of it so a thread LIST never\n * pays for ProseMirror (D5, AC#10). The lazily loaded `rich-composer-impl.tsx`\n * is the only production consumer; the tests import this file directly.\n *\n * THE UNDERLINE GRAMMAR, as agreed with the renderer side (`++text++`, no\n * whitespace touching the markers, no `++` inside `++`) is deliberately\n * STRICTER than the tokenizer StarterKit's own Underline ships — that one trims\n * inner whitespace and spans lines — which is why StarterKit's copy is disabled\n * and the mark is defined here. Same name, same commands, same `Mod-u`; only\n * the markdown spelling is ours.\n *\n * ESCAPING. `@tiptap/markdown` backslash-escapes `` \\ ` * _ [ ] ~ `` in text\n * and HTML-encodes `& < >`, which already covers most of CommonMark's inline\n * syntax and blockquotes. It does NOT escape `+` (so a literal `++x++` typed in\n * the editor would come back as an underline) or block starters (`# `, `- `,\n * `1. `, `---`), so a paragraph typed as \"- not a list\" would come back as a\n * list. Those are handled here, before the manager runs, with a private-use\n * sentinel that stands in for the backslash: the manager would double any real\n * backslash it saw, and it would double-encode any entity. The sentinel is\n * swapped for `\\` after serialization. A U+E000 already present in user text is\n * dropped first; it is a private-use code point with no meaning to keep.\n */\n\nimport {\n Editor,\n Extension,\n InputRule,\n Mark,\n mergeAttributes,\n type Extensions,\n type JSONContent,\n type MarkdownToken,\n type Range,\n markInputRule,\n} from '@tiptap/core'\nimport { Mention, type MentionNodeAttrs, type MentionOptions } from '@tiptap/extension-mention'\nimport { Markdown, type MarkdownManager } from '@tiptap/markdown'\nimport { Node as ProseMirrorNode, type Schema } from '@tiptap/pm/model'\nimport { PluginKey } from '@tiptap/pm/state'\nimport { StarterKit } from '@tiptap/starter-kit'\nimport { parseMentionHref, type MentionTargetType } from './comment-body'\nimport { emojiByShortcode, searchEmoji } from './emoji'\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n underline: {\n setUnderline: () => ReturnType\n toggleUnderline: () => ReturnType\n unsetUnderline: () => ReturnType\n }\n }\n}\n\n/* ── Underline (D13) ──────────────────────────────────────────────────────── */\n\nconst UNDERLINE_MARKER = '++'\n\n/**\n * `++text++`: the inner text starts and ends with a non-space, contains no\n * `++` (so no nesting) and no newline. Anything else is literal text, which is\n * what the renderer side does with it too.\n *\n * A backslash escape is consumed as ONE unit, so the closer can never begin\n * inside one: in `++C\\+\\+++` the escaped pluses are text and the last two\n * characters are the closer. Without this the lazy match ended at the `+` of\n * `\\+` and the serialized form did not re-parse to itself.\n */\nconst UNDERLINE_PATTERN = /^\\+\\+(?=\\S)((?:\\\\[^\\n]|(?!\\+\\+)[^\\n\\\\])+?)(?<=\\S)\\+\\+/\n\ninterface UnderlineOptions {\n readonly HTMLAttributes: Record<string, unknown>\n}\n\n/**\n * The `++text++` input rule's pattern. Exported so it can be tested without an\n * Editor: input rules only fire on real text input, which jsdom cannot\n * faithfully simulate, and the regex is where a bug would actually live. The\n * end-to-end behaviour is verified in a browser.\n *\n * STRICTER than TipTap's own bold/strike rules, deliberately, because it has to\n * agree with the RENDERER. `lib/remark-underline.ts` rejects whitespace\n * immediately inside either marker; TipTap's `(?!\\s+\\*\\*)` shape does not, so a\n * copy of it fired on `++ under++` — the editor would have drawn an underline\n * that the renderer then showed as literal plus signs. The lookarounds are the\n * fix: `(?!\\s)` after the opener, `(?<!\\s)` before the closer, and a lazy\n * `[^+]+?` so a run cannot swallow a second pair. (Lookbehind is ES2018,\n * Safari 16.4+ — the same floor `overflow: clip` already sets.)\n */\nexport const UNDERLINE_INPUT_RULE = /(?:^|\\s)(\\+\\+(?!\\s)([^+]+?)(?<!\\s)\\+\\+)$/\n\nexport const ThreadUnderline = Mark.create<UnderlineOptions>({\n name: 'underline',\n\n addOptions() {\n return { HTMLAttributes: {} }\n },\n\n parseHTML() {\n return [\n { tag: 'u' },\n {\n style: 'text-decoration',\n consuming: false,\n getAttrs: (style) =>\n typeof style === 'string' && style.includes('underline') ? {} : false,\n },\n ]\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['u', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]\n },\n\n addCommands() {\n return {\n setUnderline:\n () =>\n ({ commands }) =>\n commands.setMark(this.name),\n toggleUnderline:\n () =>\n ({ commands }) =>\n commands.toggleMark(this.name),\n unsetUnderline:\n () =>\n ({ commands }) =>\n commands.unsetMark(this.name),\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-u': () => this.editor.commands.toggleUnderline(),\n 'Mod-U': () => this.editor.commands.toggleUnderline(),\n }\n },\n\n /**\n * Type `++text++` and it becomes underlined, the moment the closing `++`\n * lands — the same as `**bold**` and `~~strike~~`, which StarterKit gives us\n * for free. Without this the mark had commands, a shortcut and full markdown\n * serialization but no way to reach it by TYPING, which is the way people\n * who know markdown actually reach it. (Owner, 2026-09-07: \"is it not like\n * obsidian where you type them in and it autoformats as you type?\")\n *\n * The pattern mirrors TipTap's own bold rule, with `+` swapped for `*`:\n * - `(?:^|\\s)` — the run starts at the line start or after whitespace, so\n * `i++;` and `C++` are never rules, matching the renderer's flanking rule\n * (D13) rather than fighting it.\n * - `(?!\\s+\\+\\+)` — no whitespace immediately inside the opener.\n * - `[^+]+` — the content cannot itself contain `+`, so `+++` runs and\n * `a++b++c++d` degrade to text instead of matching greedily.\n */\n addInputRules() {\n return [markInputRule({ find: UNDERLINE_INPUT_RULE, type: this.type })]\n },\n\n markdownTokenizer: {\n name: 'underline',\n level: 'inline',\n start: (src) => src.indexOf(UNDERLINE_MARKER),\n tokenize: (src, _tokens, lexer) => {\n const match = UNDERLINE_PATTERN.exec(src)\n const inner = match?.[1]\n if (match === null || inner === undefined) return undefined\n return { type: 'underline', raw: match[0], text: inner, tokens: lexer.inlineTokens(inner) }\n },\n },\n\n parseMarkdown: (token, helpers) =>\n helpers.applyMark('underline', helpers.parseInline(token.tokens ?? [])),\n\n renderMarkdown: (node, helpers) => `++${helpers.renderChildren(node)}++`,\n})\n\n/* ── Mention (D4) ─────────────────────────────────────────────────────────── */\n\n/**\n * The Suggestion plugin key the `@` picker (ADR-149) hangs off. Exported so\n * the composer can read the plugin state — \"is a Suggestion popup open?\" is\n * what D7 (no bubble menu while it is) and D9 (Escape closes it second) need.\n */\nexport const THREAD_MENTION_SUGGESTION_KEY = new PluginKey('threadMentionSuggestion')\n\n/** `@[label](scheme:id)`; the label may carry `\\]` / `\\[` / `\\\\` escapes. */\nconst MENTION_PATTERN = /^@\\[((?:\\\\.|[^\\]\\\\\\n])+)\\]\\(([^)\\s]+)\\)/\n\nfunction escapeMentionLabel(label: string): string {\n return label.replace(/[\\\\[\\]]/g, (char) => `\\\\${char}`)\n}\n\nfunction unescapeMentionLabel(raw: string): string {\n return raw.replace(/\\\\(.)/g, '$1')\n}\n\nexport interface ThreadMentionAttrs {\n readonly id: string\n readonly label: string\n readonly type: MentionTargetType\n}\n\n/** Narrow a node's attrs to a mention without a cast. Null for anything malformed. */\nfunction readMentionAttrs(attrs: Record<string, unknown> | undefined): ThreadMentionAttrs | null {\n if (attrs === undefined) return null\n const id = attrs['id']\n const label = attrs['label']\n const type = attrs['type']\n if (typeof id !== 'string' || id === '') return null\n if (typeof type !== 'string') return null\n const target = parseMentionHref(`${type}:${id}`)\n if (target === null) return null\n return { id: target.id, label: typeof label === 'string' && label !== '' ? label : id, type: target.type }\n}\n\nexport const ThreadMention = Mention.extend({\n addAttributes() {\n return {\n ...this.parent?.(),\n type: {\n default: 'user',\n parseHTML: (element) => element.getAttribute('data-mention-type'),\n renderHTML: (attributes) => ({ 'data-mention-type': attributes['type'] }),\n },\n }\n },\n\n markdownTokenizer: {\n name: 'mention',\n level: 'inline',\n start: (src) => src.indexOf('@['),\n tokenize: (src) => {\n const match = MENTION_PATTERN.exec(src)\n const rawLabel = match?.[1]\n const href = match?.[2]\n if (match === null || rawLabel === undefined || href === undefined) return undefined\n // Any other `@[…](…)` — an https link, an unknown scheme — is NOT a\n // mention. Returning undefined hands it back to marked, which tokenizes\n // it as a plain link, exactly as the renderer treats it.\n const target = parseMentionHref(href)\n if (target === null) return undefined\n return {\n type: 'mention',\n raw: match[0],\n label: unescapeMentionLabel(rawLabel),\n id: target.id,\n mentionType: target.type,\n }\n },\n },\n\n parseMarkdown: (token) => ({\n type: 'mention',\n attrs: {\n id: token['id'],\n label: token['label'],\n type: token['mentionType'],\n mentionSuggestionChar: '@',\n },\n }),\n\n renderMarkdown: (node) => {\n const mention = readMentionAttrs(node.attrs)\n // A mention node without a valid target cannot reach the wire: it would\n // serialize to something the server-side extractor would refuse. Its\n // label survives as text so nothing the user wrote disappears.\n if (mention === null) return typeof node.attrs?.['label'] === 'string' ? `@${node.attrs['label']}` : ''\n return `@[${escapeMentionLabel(mention.label)}](${mention.type}:${mention.id})`\n },\n})\n\n/* ── The subset (D2 / D3) ─────────────────────────────────────────────────── */\n\nexport const RICH_HEADING_LEVELS = [1, 2, 3] as const\nconst RICH_HEADING_LEVEL_SET: ReadonlySet<number> = new Set<number>(RICH_HEADING_LEVELS)\n\ntype MentionSuggestion = MentionOptions['suggestion']\n\n/**\n * How many characters after the sigil before the popup may open (ADR-149 D4).\n *\n * A bare `:` is punctuation and far more common in prose than an emoji, so it\n * takes two; a bare `@` is rare enough that one is right. Below the threshold\n * the plugin hands the renderer an EMPTY item list, which is what closes the\n * popup — the same door \"no matches\" comes through, so there is one rule in\n * the UI and not two.\n */\nexport const MENTION_SUGGESTION_MIN_QUERY = 1\nexport const EMOJI_SUGGESTION_MIN_QUERY = 2\n\n/**\n * The `:` trigger's Suggestion plugin key, beside the `@` one above. Two keys\n * because they are two plugins; ONE popup, because they are one interaction\n * (D1) — the difference is data and rendering, never behaviour.\n */\nexport const THREAD_EMOJI_SUGGESTION_KEY = new PluginKey('threadEmojiSuggestion')\n\n/**\n * A complete, typed shortcode at the end of the current textblock. The shape\n * is deliberately only the lexical first pass: `EMOJI_INPUT_RULE` then asks\n * the curated table whether the spelling is a real name or alias. Keywords\n * are search aids, not shortcodes, and must not make prose transform.\n */\nconst EMOJI_SHORTCODE_AT_END = /(?:^|\\s)(:([^:\\s]+):)$/\n\n/**\n * Slack-style closing-colon matcher, exported for a direct test. TipTap input\n * rules only run on real text input, while `insertContent` bypasses them.\n */\nexport const EMOJI_INPUT_RULE = (text: string) => {\n const match = EMOJI_SHORTCODE_AT_END.exec(text)\n const shortcode = match?.[1]\n if (match === null || shortcode === undefined || emojiByShortcode(shortcode) === undefined) {\n return null\n }\n return { index: match.index, text: match[0], data: { shortcode } }\n}\n\nconst ThreadEmojiShortcode = Extension.create({\n name: 'threadEmojiShortcode',\n\n addInputRules() {\n return [\n new InputRule({\n find: EMOJI_INPUT_RULE,\n handler: ({ state, range, match }) => {\n const shortcode = match.data?.['shortcode']\n const entry = typeof shortcode === 'string' ? emojiByShortcode(shortcode) : undefined\n if (entry === undefined || typeof shortcode !== 'string') return null\n state.tr.insertText(entry.glyph, range.to - shortcode.length, range.to)\n return undefined\n },\n }),\n ]\n },\n})\n\n/**\n * What the `:` picker hands back when an option is chosen.\n *\n * `id` is the canonical shortcode, and it is deliberately the ONLY thing that\n * crosses the seam: `@tiptap/extension-mention` types its `command` payload as\n * `MentionNodeAttrs`, so an emoji-shaped payload would not type-check through\n * it. Passing the shortcode and re-resolving the glyph from the table on the\n * other side keeps this honest with zero casts, and means the insert can never\n * write a glyph that is not in the table.\n */\nexport interface EmojiSuggestionAttrs {\n readonly id: string\n readonly label: string\n}\n\n/**\n * D2 — an emoji is inserted as UNICODE, never as a shortcode. `body_md` then\n * contains the character, so every render site (the digest, an export, an\n * agent's context, a plain-text copy) shows it without a lookup table.\n *\n * The trailing space, and the guard against doubling it, mirror the mention\n * command exactly, so choosing from either popup leaves the caret in the same\n * place.\n */\nfunction insertEmoji({\n editor,\n range,\n props,\n}: {\n editor: Editor\n range: Range\n props: MentionNodeAttrs\n}): void {\n const entry = emojiByShortcode(props.id ?? '')\n if (entry === undefined) return\n const nodeAfter = editor.view.state.selection.$to.nodeAfter\n const to = nodeAfter?.text?.startsWith(' ') === true ? range.to + 1 : range.to\n editor\n .chain()\n .focus()\n .insertContentAt({ from: range.from, to }, [{ type: 'text', text: `${entry.glyph} ` }])\n .run()\n}\n\n/** The `:` picker's options, in the shape the Suggestion payload accepts. */\nfunction emojiSuggestionItems(query: string): EmojiSuggestionAttrs[] {\n return searchEmoji(query).map((entry) => ({ id: entry.name, label: entry.glyph }))\n}\n\n/**\n * The two trigger configurations (D1). The DATA half — what each trigger\n * offers and what choosing does — lives here; the RENDERING half is one\n * `render()` per trigger, supplied by the composer, pointing at one popup.\n */\nexport interface RichSuggestionRenderers {\n /** The `@` trigger. Absent, the mention popup never opens. */\n readonly mention?: Partial<MentionSuggestion> | undefined\n /** The `:` trigger. Absent, the emoji popup never opens. */\n readonly emoji?: Partial<MentionSuggestion> | undefined\n}\n\n/**\n * The editor's extension set — the D3 subset, written down (ADR-148 D2).\n *\n * StarterKit is configured explicitly so a future minor cannot admit a\n * construct silently. Today the only things it does not keep at default are\n * the heading levels (1–3), the link options an EDITOR needs (a click must\n * edit, not navigate), and `underline: false` — replaced by `ThreadUnderline`\n * above, same name and commands, strict `++` grammar.\n *\n * BOTH triggers hang off the ONE Mention extension, through its `suggestions`\n * array. That is not a trick: `@tiptap/suggestion` is a transitive dependency\n * with no direct entry in `@lovett/ui`'s `package.json`, so under pnpm's\n * strict layout it cannot be imported from this package, and ADR-148 D2\n * deliberately did not install it (\"zero new runtime dependencies\",\n * ADR-149 AC#1). `suggestions` is the extension's own supported way to run a\n * second trigger, and it gives the `:` plugin the same match-finding,\n * dismissal and floating-ui anchoring the `@` one already had. The `:` trigger\n * never creates a mention node — its `command` inserts text (D2).\n */\nexport function richSubsetExtensions(renderers: RichSuggestionRenderers = {}): Extensions {\n return [\n StarterKit.configure({\n heading: { levels: [...RICH_HEADING_LEVELS] },\n // horizontalRule: default, IN — owner, 2026-09-07.\n underline: false,\n link: {\n openOnClick: false,\n autolink: true,\n linkOnPaste: true,\n enableClickSelection: false,\n },\n }),\n ThreadUnderline,\n ThreadEmojiShortcode,\n ThreadMention.configure({\n HTMLAttributes: { class: 'ds-thread-mention' },\n suggestions: [\n {\n char: '@',\n pluginKey: THREAD_MENTION_SUGGESTION_KEY,\n minQueryLength: MENTION_SUGGESTION_MIN_QUERY,\n ...renderers.mention,\n },\n {\n char: ':',\n pluginKey: THREAD_EMOJI_SUGGESTION_KEY,\n minQueryLength: EMOJI_SUGGESTION_MIN_QUERY,\n // The plugin's own view of what it is offering. The POPUP does not\n // read this — it recomputes from the query, because\n // `@tiptap/suggestion` types its items as `any` and the composer\n // does not take `any` — but leaving it unset would make the plugin's\n // state say \"no items\" while eight are on screen, which is a lie any\n // future reader of that state would trip over.\n items: ({ query }: { query: string }) => emojiSuggestionItems(query),\n command: insertEmoji,\n // A shortcode typed inside code stays literal: `:tada:` in a snippet\n // is text about an emoji, not an emoji. The mention trigger keeps\n // the extension's own default, which asks the schema whether a\n // mention node may sit here.\n allow: ({ editor }: { editor: Editor }) =>\n !editor.isActive('codeBlock') && !editor.isActive('code'),\n ...renderers.emoji,\n },\n ],\n }),\n Markdown,\n ]\n}\n\n/* ── Headless probe ───────────────────────────────────────────────────────── */\n\nlet probe: Editor | null = null\n\n/**\n * One headless editor over the subset, created on first use. It owns the\n * `MarkdownManager` every parse and serialize below goes through and the\n * schema the detector checks against — so the detector, the tests and the live\n * composer agree by construction, not by keeping three configurations in step.\n */\nfunction getProbe(): Editor {\n if (probe === null) {\n probe = new Editor({ element: null, extensions: richSubsetExtensions(), content: '' })\n }\n return probe\n}\n\nfunction getManager(): MarkdownManager {\n const manager = getProbe().markdown\n if (manager === undefined) {\n throw new Error('rich composer: the Markdown extension did not attach a manager')\n }\n return manager\n}\n\nfunction getSchema(): Schema {\n return getProbe().schema\n}\n\n/* ── Parse / serialize ────────────────────────────────────────────────────── */\n\nexport function parseRichMarkdown(markdown: string): JSONContent {\n return canonicalizeInlineMarks(getManager().parse(markdown))\n}\n\n/* ── Canonical mark boundaries ────────────────────────────────────────────── */\n\n/**\n * Marks that markdown cannot open or close on whitespace. `*a *` is not\n * emphasis and `` ` a ` `` is `a`; a link, by contrast, keeps `[a ](url)`.\n */\nconst BOUNDARY_MARKS: readonly string[] = ['bold', 'italic', 'underline', 'strike', 'code']\n\nfunction hasMark(node: JSONContent, type: string): boolean {\n return (node.marks ?? []).some((mark) => mark.type === type)\n}\n\nfunction withoutMark(node: JSONContent, type: string): JSONContent {\n const marks = (node.marks ?? []).filter((mark) => mark.type !== type)\n const { marks: _marks, ...rest } = node\n return marks.length === 0 ? rest : { ...rest, marks }\n}\n\n/**\n * Push the whitespace at either end of every maximal run of `type`-marked text\n * OUT of the mark — into a node that keeps the run's other marks. One mark at\n * a time, so `**bold with *italic inside* it**` is untouched (the bold run is\n * all three nodes; the italic run has no boundary whitespace) while\n * `*quarter @[…] **creative***` — italic on the space beside a mention, which\n * no serializer can spell — settles into the one form that re-parses to\n * itself. This is the canonicalization D3 rule 1 allows, applied where the\n * manager's own output would otherwise not be a fixed point.\n */\nfunction trimMarkRuns(content: readonly JSONContent[], type: string): JSONContent[] {\n const out: JSONContent[] = []\n let run: JSONContent[] = []\n const flush = () => {\n if (run.length === 0) return\n const first = run[0]\n const last = run[run.length - 1]\n if (first === undefined || last === undefined) return\n const leading = /^\\s+/.exec(first.text ?? '')?.[0] ?? ''\n if (leading !== '' && leading.length < (first.text ?? '').length) {\n run[0] = { ...first, text: (first.text ?? '').slice(leading.length) }\n out.push(withoutMark({ ...first, text: leading }, type))\n } else if (leading !== '') {\n run[0] = withoutMark(first, type)\n }\n const tail = run[run.length - 1]\n if (tail !== undefined && run.length >= 1 && !(run.length === 1 && leading !== '' && leading.length >= (first.text ?? '').length)) {\n const trailing = /\\s+$/.exec(tail.text ?? '')?.[0] ?? ''\n if (trailing !== '' && trailing.length < (tail.text ?? '').length) {\n run[run.length - 1] = { ...tail, text: (tail.text ?? '').slice(0, -trailing.length) }\n out.push(...run)\n out.push(withoutMark({ ...tail, text: trailing }, type))\n run = []\n return\n }\n if (trailing !== '' && run.length > 1) {\n run[run.length - 1] = withoutMark(tail, type)\n }\n }\n out.push(...run)\n run = []\n }\n for (const node of content) {\n if (node.type === 'text' && hasMark(node, type)) {\n run.push(node)\n continue\n }\n flush()\n out.push(node)\n }\n flush()\n return out\n}\n\nfunction canonicalizeInlineMarks(node: JSONContent): JSONContent {\n const content = node.content\n if (content === undefined) return node\n if (node.type === 'paragraph' || node.type === 'heading') {\n let inline: JSONContent[] = [...content]\n for (const type of BOUNDARY_MARKS) inline = trimMarkRuns(inline, type)\n return { ...node, content: inline }\n }\n return { ...node, content: content.map(canonicalizeInlineMarks) }\n}\n\n/**\n * Run a document through the schema: attrs get their defaults, invalid\n * content throws. `parse → normalize` is what `editor.setContent` produces,\n * so this is what the round-trip tests compare.\n */\nexport function normalizeRichDocument(doc: JSONContent): JSONContent {\n const node = ProseMirrorNode.fromJSON(getSchema(), doc)\n node.check()\n return node.toJSON()\n}\n\nconst ESCAPE_SENTINEL = '\\u{E000}'\n\nfunction hasCodeMark(node: JSONContent): boolean {\n return (node.marks ?? []).some((mark) => mark.type === 'code')\n}\n\n/** Block starters the manager does not escape; `>` it already entity-encodes. */\nfunction escapeBlockStart(text: string): string {\n return text\n .replace(/^(#{1,6})(?=[ \\t]|$)/, (hashes) => hashes.replace(/#/g, `${ESCAPE_SENTINEL}#`))\n .replace(/^([-+])(?=[ \\t]|$)/, `${ESCAPE_SENTINEL}$1`)\n .replace(/^(\\d{1,9})([.)])(?=[ \\t]|$)/, `$1${ESCAPE_SENTINEL}$2`)\n .replace(/^-{3,}[ \\t]*$/, (rule) => `${ESCAPE_SENTINEL}${rule}`)\n}\n\nfunction escapePlusRuns(text: string): string {\n return text.replace(/\\+{2,}/g, (run) => run.replace(/\\+/g, `${ESCAPE_SENTINEL}+`))\n}\n\n/**\n * Mark, in a COPY of the tree, every character the manager would let through\n * unescaped. Code is left alone at every level: inside a code block or a code\n * mark the characters are literal already.\n */\nfunction markLiteralSyntax(node: JSONContent): JSONContent {\n if (node.type === 'codeBlock') return node\n const content = node.content\n if (content === undefined) return node\n let lineStart = node.type === 'paragraph' || node.type === 'heading'\n const next = content.map((child): JSONContent => {\n if (child.type === 'text') {\n const startsLine = lineStart\n lineStart = false\n if (hasCodeMark(child)) return child\n const source = (child.text ?? '').replaceAll(ESCAPE_SENTINEL, '')\n let text = escapePlusRuns(source)\n if (startsLine) text = escapeBlockStart(text)\n return text === child.text ? child : { ...child, text }\n }\n if (child.type === 'hardBreak') {\n lineStart = true\n return child\n }\n lineStart = false\n return markLiteralSyntax(child)\n })\n return { ...node, content: next }\n}\n\nexport function serializeRichMarkdown(doc: JSONContent): string {\n // The same boundary rule on the way out: a mark the editor put on a trailing\n // space cannot be spelled, so it is moved off the space before the manager\n // sees it, and the output re-parses to exactly what was serialized.\n // Trailing blank lines are not markdown: CommonMark parses `x\\n\\n` and `x`\n // to the same tree, and the editor always ends in an empty paragraph (the\n // trailing node that lets a caret land after a final list or code block).\n // Trimming the end is what makes the serialized form a fixed point.\n return getManager()\n .serialize(markLiteralSyntax(canonicalizeInlineMarks(doc)))\n .replaceAll(ESCAPE_SENTINEL, '\\\\')\n .trimEnd()\n}\n\n/* ── Fail-closed detector (D3 rule 2) ─────────────────────────────────────── */\n\n/**\n * Every token marked's lexer may emit for a body the subset can hold. Anything\n * not on this list — `table`, `html`, `image`, a token a future marked adds —\n * fails closed, which is the point: the list is what we can VOUCH for, not\n * what we happen to have seen.\n */\nconst SUPPORTED_TOKENS: ReadonlySet<string> = new Set([\n 'space',\n 'paragraph',\n 'heading',\n 'hr',\n 'blockquote',\n 'list',\n 'list_item',\n 'code',\n 'def',\n 'text',\n 'strong',\n 'em',\n 'del',\n 'codespan',\n 'link',\n 'br',\n 'escape',\n 'underline',\n 'mention',\n])\n\nfunction tokensSupported(tokens: readonly MarkdownToken[]): boolean {\n return tokens.every((token) => {\n const type = token.type\n if (type === undefined || !SUPPORTED_TOKENS.has(type)) return false\n if (type === 'heading' && !RICH_HEADING_LEVEL_SET.has(token.depth ?? 1)) return false\n if (type === 'list_item' && token['task'] === true) return false\n const children: MarkdownToken[] = [...(token.tokens ?? []), ...(token.items ?? [])]\n return tokensSupported(children)\n })\n}\n\nfunction documentSupported(node: JSONContent): boolean {\n if (node.type === 'heading') {\n const level = node.attrs?.['level']\n if (typeof level !== 'number' || !RICH_HEADING_LEVEL_SET.has(level)) return false\n }\n if (node.type === 'mention' && readMentionAttrs(node.attrs) === null) return false\n return (node.content ?? []).every(documentSupported)\n}\n\n/**\n * May this body open in the rich editor?\n *\n * Two checks, because they fail differently. The token scan catches syntax\n * the schema could *absorb* but must not — raw `<u>` would become an underline\n * mark and be re-serialized as `++`, which is exactly the byte change rule 2\n * forbids. The schema check (`Node.fromJSON` + `check()`, plus the attrs the\n * schema does not validate) catches anything the parse emits that the editor\n * cannot hold. Either failing means the plain composer, source untouched.\n */\nexport function isRichEditable(markdown: string): boolean {\n if (markdown.trim() === '') return true\n const manager = getManager()\n let tokens: readonly MarkdownToken[]\n try {\n tokens = manager.instance.lexer(markdown)\n } catch {\n return false\n }\n if (!tokensSupported(tokens)) return false\n try {\n const doc = manager.parse(markdown)\n if (!documentSupported(doc)) return false\n normalizeRichDocument(doc)\n return true\n } catch {\n return false\n }\n}\n","/**\n * SuggestionList — the ONE popup behind both composer triggers (ADR-149 D1).\n *\n * `@` and `:` are the same interaction: type a sigil, filter a list, choose\n * with the keyboard, insert something. The differences are DATA and RENDERING\n * — who supplies the options and what each row shows — never behaviour, so\n * there is one listbox here and two configurations in `markdown-spec.ts`.\n * Two popups would mean two focus models and two sets of accessibility bugs.\n *\n * D5, the contract this file exists to hold:\n *\n * - The EDITOR keeps DOM focus throughout. Nothing in here is ever focused:\n * the options are buttons for their hit area and click semantics, held out\n * of the tab order and guarded by a `mousedown` preventDefault so a click\n * cannot move the caret. The editor points at the active option with\n * `aria-activedescendant` (set by the composer, which owns the editor's\n * DOM node) and at this list with `aria-controls`.\n * - `role=\"listbox\"` / `role=\"option\"` / `aria-selected`, so the pairing is\n * the one an AT expects from a combobox-shaped completion.\n * - The active option is scrolled into view INSIDE THE POPUP ONLY. This\n * codebase has fixed \"the page scrolls while I type\" twice (the composer's\n * `handleScrollToSelection`, then its height ceiling), and\n * `Element.scrollIntoView` is exactly the API that reintroduces it — it\n * walks up and scrolls every scrollable ancestor. So: arithmetic on this\n * one element's `scrollTop`, plus `overscroll-behavior: contain` in CSS\n * for the wheel and touch paths. A single element's `scrollTop` cannot\n * chain.\n *\n * The two pure helpers below are exported because they are the part jsdom can\n * actually verify: wrapping and scroll arithmetic. Placement is floating-ui's\n * job and is checked in the browser pass, not here.\n */\n\nimport { useLayoutEffect, useRef } from 'react'\n\nexport interface SuggestionOption {\n /** Stable identity for React and for the option's DOM id. */\n readonly key: string\n /** The row's primary text — a person's name, or `:shortcode:`. */\n readonly label: string\n /** Secondary text, right-aligned: the mention's kind, or an alias hit. */\n readonly hint?: string | undefined\n /** The leading glyph slot: an emoji character, or a person's initial. */\n readonly glyph?: string | undefined\n /**\n * Whether the glyph merely repeats what the label already says.\n *\n * A mention's leading initial is the first letter of the name beside it, so\n * it is decoration and is hidden from assistive technology. An EMOJI is the\n * opposite: it is the thing being chosen, and hiding it would leave a\n * screen-reader user choosing between shortcodes with no idea what any of\n * them looks like. Unhidden, the option announces the emoji's own Unicode\n * name — \"party popper\" — which is the whole point of the row.\n */\n readonly glyphDecorative?: boolean | undefined\n}\n\n/**\n * Move `current` by `delta` through a list of `length`, wrapping at both ends\n * (D5: \"ArrowUp / ArrowDown move the active option and wrap\"). An empty list\n * has no active option, which is `0` — the popup is closed in that case\n * anyway, and a negative index would be a worse lie.\n */\nexport function wrapIndex(current: number, length: number, delta: number): number {\n if (length <= 0) return 0\n return (((current + delta) % length) + length) % length\n}\n\nexport interface ScrollViewport {\n readonly scrollTop: number\n readonly clientHeight: number\n}\n\nexport interface ScrollTarget {\n readonly offsetTop: number\n readonly offsetHeight: number\n}\n\n/**\n * The popup's new `scrollTop` so the active option is fully visible, moved by\n * the smallest amount that does it — and never anything else's scrollTop.\n */\nexport function listScrollTop(view: ScrollViewport, target: ScrollTarget): number {\n if (target.offsetTop < view.scrollTop) return target.offsetTop\n const bottom = target.offsetTop + target.offsetHeight\n if (bottom > view.scrollTop + view.clientHeight) return bottom - view.clientHeight\n return view.scrollTop\n}\n\nexport interface SuggestionListProps {\n /** The listbox's DOM id — the editor's `aria-controls` points at it. */\n readonly id: string\n /** The listbox's accessible name (\"Emoji\", \"Mention someone\"). */\n readonly label: string\n readonly options: readonly SuggestionOption[]\n readonly activeIndex: number\n /** Option DOM ids, so the editor's `aria-activedescendant` can name one. */\n readonly optionId: (index: number) => string\n /** Insert the option at `index` (a click, or Enter / Tab from the editor). */\n readonly onSelect: (index: number) => void\n /** A pointer hover makes an option active without inserting it. */\n readonly onActivate: (index: number) => void\n}\n\nexport function SuggestionList({\n id,\n label,\n options,\n activeIndex,\n optionId,\n onSelect,\n onActivate,\n}: SuggestionListProps) {\n const listRef = useRef<HTMLDivElement>(null)\n\n useLayoutEffect(() => {\n const list = listRef.current\n if (list === null) return\n const option = list.children.item(activeIndex)\n if (!(option instanceof HTMLElement)) return\n list.scrollTop = listScrollTop(list, option)\n }, [activeIndex, options])\n\n return (\n <div\n ref={listRef}\n id={id}\n role=\"listbox\"\n aria-label={label}\n className=\"ds-thread-suggestions\"\n // The options refuse focus one by one; this refuses it for the padding\n // ring and the scrollbar between them. Without it a click on either\n // blurs the contenteditable, which closes the popup and moves focus —\n // the exact hole D5 says must not exist.\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n >\n {options.map((option, index) => {\n const active = index === activeIndex\n return (\n <button\n key={option.key}\n type=\"button\"\n id={optionId(index)}\n role=\"option\"\n aria-selected={active}\n // D5: the editor keeps focus. These are buttons for their hit area\n // and click semantics only — never for focus.\n tabIndex={-1}\n data-active={active}\n className=\"ds-thread-suggestions__option\"\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onMouseEnter={() => {\n onActivate(index)\n }}\n onClick={() => {\n onSelect(index)\n }}\n >\n <span\n // Reserved slot either way, so a hidden glyph still holds the\n // column and the labels stay on one alignment grid.\n {...(option.glyphDecorative === true || option.glyph === undefined\n ? { 'aria-hidden': true as const }\n : {})}\n className=\"ds-thread-suggestions__glyph\"\n >\n {option.glyph}\n </span>\n <span className=\"ds-thread-suggestions__label\">{option.label}</span>\n {option.hint === undefined ? null : (\n <span className=\"ds-thread-suggestions__hint\">{option.hint}</span>\n )}\n </button>\n )\n })}\n </div>\n )\n}\n","/**\n * RichThreadComposerImpl — the TipTap surface behind the rich composer.\n *\n * ADR-148. This module is reached ONLY through the `lazy()` boundary in\n * rich-composer.tsx (D5): every TipTap import here is static and ordinary, so\n * Vite splits the whole editor into one chunk and the D6 fallback wraps one\n * promise. Nothing in this file is re-exported from the package barrel.\n *\n * Two components. The default export is the GATE (D3 rule 2): it runs\n * `isRichEditable` on the draft before any editor exists and, if the body\n * holds syntax the subset cannot carry, renders the plain composer with the\n * source untouched and a one-line notice. `RichSurface` below it owns the\n * editor. The gate lives here rather than in the shell because the detector\n * needs the subset's schema, and the shell must stay free of TipTap.\n *\n * The seam stays `ThreadComposerProps`: markdown in through `value`, markdown\n * out through `onChange`, and verified attachment ticket ids out through the\n * optional `onSubmit` argument (ADR-151 D1). Hooks and host capabilities sit\n * on top: `onEditor`, `mentionItems`, upload/GIF callbacks, limits, and the\n * shell's polite `announce` region. Missing capabilities render no inert UI.\n *\n * DRAFT TIMING (D12). `onChange` receives serialized markdown on a 300 ms\n * trailing debounce, not on every transaction, and is flushed on blur, send\n * and unmount. Because the parent is therefore up to 300 ms behind the editor,\n * SEND does not call `onSubmit` until the parent has caught up: `requestSubmit`\n * flushes, and an effect fires `onSubmit` once `value` equals what was flushed\n * and every attachment has a verified ticket — so `useThread.submit`, which\n * reads the draft it was rendered with, always sends the latest keystrokes.\n * `canSend` reads the editor's own emptiness for the same reason.\n *\n * KEYBOARD (D9). Every Escape level lives in ONE `handleKeyDown`: bubble menu,\n * then Suggestion popup, then `onCancel`. `editorProps` handlers run before\n * any extension keymap, which is what makes the order a fact rather than a\n * hope. Tab is answered from `handleDOMEvents.keydown` returning true — that\n * skips ProseMirror's keymaps (StarterKit binds Tab to indent a list item)\n * WITHOUT preventing the browser default, so focus leaves the editor. While a\n * suggestion popup is open Tab is NOT waved through: ADR-149 D5 gives it to\n * the popup, so the DOM-event handler stands down and `handleKeyDown` inserts.\n *\n * SUGGESTIONS (ADR-149). Two triggers, ONE popup. `markdown-spec.ts` owns the\n * data half (what `@` and `:` offer, and what choosing inserts); this file\n * owns the UI half: the `render()` lifecycle each trigger gets, the single\n * `<SuggestionList>` both of them draw into, and the keys. The popup NEVER\n * takes focus — it is mounted in a portal outside the editor and pointed at by\n * `aria-controls` / `aria-activedescendant` on the contenteditable itself, so\n * `document.activeElement` is the editor through open, arrow, insert and\n * escape (D5, AC#6).\n *\n * IME (D11). The bubble predicate refuses while `view.composing` or our own\n * composition flag is set; `compositionstart` closes an open menu outright.\n *\n * What jsdom cannot verify here, and the tests say so: the bubble menu's\n * pixel placement (floating-ui needs layout) and real composition sessions.\n * Both are on the owner's eyeball + IME pass (AC#13).\n */\n\nimport type { CSSProperties, KeyboardEvent as ReactKeyboardEvent } from 'react'\nimport { useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n Bold,\n Check,\n Code,\n CornerDownRight,\n Heading1,\n Heading2,\n Heading3,\n Italic,\n Images,\n Link as LinkIcon,\n List,\n ListOrdered,\n Minus,\n SquareCode,\n Strikethrough,\n TextQuote,\n Underline as UnderlineIcon,\n Unlink,\n X,\n} from 'lucide-react'\nimport { isTextSelection, type Editor } from '@tiptap/core'\nimport { Placeholder } from '@tiptap/extension-placeholder'\nimport { Fragment, Node as ProseMirrorNode, Slice } from '@tiptap/pm/model'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { PluginKey as ProseMirrorPluginKey } from '@tiptap/pm/state'\nimport type { EditorView } from '@tiptap/pm/view'\nimport { EditorContent, useEditor, useEditorState } from '@tiptap/react'\nimport { BubbleMenu } from '@tiptap/react/menus'\nimport { Button } from '../button'\nimport { Kbd } from '../kbd'\nimport { cn } from '../lib/utils'\nimport { Popover } from '../popover'\nimport {\n ATTACHMENT_ACCEPT,\n AttachmentButton,\n AttachmentDropZone,\n AttachmentTray,\n GifPicker,\n} from './attachments'\nimport type { MentionTargetType } from './comment-body'\nimport type { MentionSuggestionItem } from './types'\nimport { ThreadComposer, type ThreadComposerProps } from './composer'\nimport { ComposerFooter } from './composer-footer'\nimport { caretScrollDelta } from './scroll-caret'\nimport { searchEmoji } from './emoji'\nimport {\n EMOJI_SUGGESTION_MIN_QUERY,\n MENTION_SUGGESTION_MIN_QUERY,\n THREAD_EMOJI_SUGGESTION_KEY,\n THREAD_MENTION_SUGGESTION_KEY,\n isRichEditable,\n parseRichMarkdown,\n richSubsetExtensions,\n serializeRichMarkdown,\n type EmojiSuggestionAttrs,\n} from './markdown-spec'\nimport { ComposerNotice, type RichComposerAttachmentProps } from './rich-composer'\nimport { SuggestionList, wrapIndex, type SuggestionOption } from './suggestion-list'\nimport { useAttachments } from './use-attachments'\n\n/** D12: the draft leaves the editor on this trailing debounce. */\nexport const DRAFT_DEBOUNCE_MS = 300\n\n/** D3 rule 2, in the user's words. Rendered above the plain composer and spoken once. */\nexport const FAIL_CLOSED_NOTICE =\n 'Opened in the plain editor: this comment uses formatting the rich editor cannot hold. Nothing was changed.'\n\nexport type { MentionSuggestionItem } from './types'\n\n/** Hooks on top of the seam. None of these is part of `ThreadComposerProps`. */\nexport interface RichComposerHooks extends RichComposerAttachmentProps {\n /** Receives the live editor once created, and null when it goes away. */\n readonly onEditor?: ((editor: Editor | null) => void) | undefined\n /** ADR-149's seam: items for the `@` picker. Absent, the popup never opens. */\n readonly mentionItems?: ((query: string) => readonly MentionSuggestionItem[]) | undefined\n /** The shell's polite live region. */\n readonly announce?: ((message: string) => void) | undefined\n}\n\nexport type RichThreadComposerImplProps = ThreadComposerProps & RichComposerHooks\n\n/* ── Platform spelling, read once (same reasoning as composer.tsx) ─────────── */\n\nconst IS_APPLE: boolean =\n typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.userAgent)\nconst SEND_KEYCAP = IS_APPLE ? '⌘↵' : 'Ctrl ↵'\nconst MOD_NAME = IS_APPLE ? 'Command' : 'Control'\n\n/** React accepts CSS custom properties in `style`; the DOM typings do not declare them. */\ntype StyleWithVars = CSSProperties & Record<`--${string}`, string>\n\nconst BUBBLE_MENU_KEY = new ProseMirrorPluginKey('threadBubbleMenu')\n\n/* ── The gate (D3 rule 2) ─────────────────────────────────────────────────── */\n\nexport default function RichThreadComposerImpl(props: RichThreadComposerImplProps) {\n const { value, onChange, announce } = props\n\n // What the parent currently holds BECAUSE we emitted it. A `value` that\n // differs from it arrived from outside — a resumed draft, a comment opened\n // for editing, a reset after send — and is the only kind that can change the\n // gate's answer. Our own emissions never re-run the detector: the editor\n // cannot produce syntax the editor cannot hold.\n const lastEmitted = useRef<string | null>(null)\n const [gate, setGate] = useState(() => ({ value, rich: isRichEditable(value) }))\n if (value !== gate.value) {\n setGate({ value, rich: value === lastEmitted.current ? gate.rich : isRichEditable(value) })\n }\n\n const emit = useCallback(\n (next: string) => {\n lastEmitted.current = next\n onChange(next)\n },\n [onChange],\n )\n\n useEffect(() => {\n if (!gate.rich) announce?.(FAIL_CLOSED_NOTICE)\n }, [announce, gate.rich])\n\n if (!gate.rich) {\n const {\n onEditor: _onEditor,\n mentionItems: _items,\n announce: _announce,\n uploadAttachment: _uploadAttachment,\n attachGif: _attachGif,\n searchGifs: _searchGifs,\n attachmentAccept: _attachmentAccept,\n attachmentMaxPerComment: _attachmentMaxPerComment,\n attachmentMaxFileBytes: _attachmentMaxFileBytes,\n attachmentMaxTotalBytes: _attachmentMaxTotalBytes,\n ...plain\n } = props\n return (\n <div className=\"flex flex-col gap-[var(--space-1)]\">\n <ComposerNotice>{FAIL_CLOSED_NOTICE}</ComposerNotice>\n <ThreadComposer {...plain} onChange={emit} />\n </div>\n )\n }\n return <RichSurface {...props} onChange={emit} />\n}\n\n/* ── The suggestion popup (ADR-149) ───────────────────────────────────────── */\n\n/** Which trigger a popup session belongs to. Two configs, one popup (D1). */\ntype SuggestionKind = 'mention' | 'emoji'\n\n/** What choosing an option hands back. Both shapes carry `id` + `label`. */\ntype SuggestionAttrs = MentionSuggestionItem | EmojiSuggestionAttrs\n\n/**\n * The slice of `@tiptap/suggestion`'s render props this file actually uses,\n * declared locally and precisely.\n *\n * `@tiptap/suggestion` types `SuggestionProps` with `I = any`, so reading\n * `props.items` or `props.command` through its own types would leak `any` into\n * this file (CLAUDE.md §3). A narrower parameter type is still assignable — a\n * handler that accepts less than it is given always is — so this costs\n * nothing and keeps the file free of `any`.\n */\ninterface SuggestionRenderProps {\n readonly query: string\n readonly command: (attrs: SuggestionAttrs) => void\n readonly mount: (\n element: HTMLElement,\n options?: {\n onPosition?: (data: { x: number; y: number; strategy: 'absolute' | 'fixed' }) => void\n },\n ) => () => void\n}\n\n/** The rows a session is showing: what to draw, and what to insert. */\ninterface SuggestionRows {\n readonly options: readonly SuggestionOption[]\n readonly attrs: readonly SuggestionAttrs[]\n}\n\nconst EMPTY_ROWS: SuggestionRows = { options: [], attrs: [] }\n\nconst SUGGESTION_KEYS: Readonly<Record<SuggestionKind, PluginKey>> = {\n mention: THREAD_MENTION_SUGGESTION_KEY,\n emoji: THREAD_EMOJI_SUGGESTION_KEY,\n}\n\nconst SUGGESTION_LABELS: Readonly<Record<SuggestionKind, string>> = {\n mention: 'Mention someone',\n emoji: 'Emoji',\n}\n\n/** The same two, as the noun the polite announcement counts. */\nconst SUGGESTION_NOUNS: Readonly<Record<SuggestionKind, string>> = {\n mention: 'mention',\n emoji: 'emoji',\n}\n\n/**\n * D4's thresholds, enforced HERE and not only on the plugin.\n *\n * `minQueryLength` in the Suggestion config stops the plugin doing needless\n * `items()` work, but all it does to the renderer is hand it an empty item\n * list — and this file computes its rows from the QUERY rather than from\n * `props.items` (see `SuggestionRenderProps`). So the threshold has to be a\n * rule the popup itself applies, or a host whose `mentionItems` ignores its\n * query would open the popup on a bare `@`. Same constants, one behaviour.\n */\nconst SUGGESTION_MIN_QUERY: Readonly<Record<SuggestionKind, number>> = {\n mention: MENTION_SUGGESTION_MIN_QUERY,\n emoji: EMOJI_SUGGESTION_MIN_QUERY,\n}\n\n/** User-facing names for the three mention schemes (ADR-147 D11). */\nconst MENTION_KIND_LABELS: Readonly<Record<MentionTargetType, string>> = {\n user: 'Person',\n task_item: 'Task',\n task_board: 'Board',\n}\n\n/**\n * Close a Suggestion plugin without touching the document.\n *\n * This is the exact transaction `@tiptap/suggestion`'s own `exitSuggestion()`\n * dispatches. It is re-spelled here rather than imported because that package\n * is transitive — ADR-148 D2 deliberately did not install it, and AC#1 forbids\n * adding it — so under pnpm's strict layout `@lovett/ui` cannot resolve it.\n * The meta also marks the range dismissed, which is what keeps the popup shut\n * after Escape instead of reopening on the next keystroke.\n */\nfunction exitSuggestionPlugin(view: EditorView, kind: SuggestionKind): void {\n view.dispatch(view.state.tr.setMeta(SUGGESTION_KEYS[kind], { exit: true }))\n}\n\n/** The `:` picker's rows: the glyph, its canonical `:shortcode:`. */\nfunction emojiRows(query: string): SuggestionRows {\n const entries = searchEmoji(query)\n return {\n options: entries.map((entry) => ({\n key: entry.name,\n label: `:${entry.name}:`,\n glyph: entry.glyph,\n })),\n attrs: entries.map((entry) => ({ id: entry.name, label: entry.glyph })),\n }\n}\n\n/** The first character of a label, for the leading slot. */\nfunction leadingInitial(label: string): string {\n return ([...label][0] ?? '').toUpperCase()\n}\n\n/** The `@` picker's rows, from whatever list the host handed us (D6). */\nfunction mentionRows(items: readonly MentionSuggestionItem[]): SuggestionRows {\n return {\n options: items.map((item) => ({\n key: `${item.type}:${item.id}`,\n label: item.label,\n hint: MENTION_KIND_LABELS[item.type],\n glyph: leadingInitial(item.label),\n // The initial is the label's own first letter — decoration, not\n // information. The emoji rows above deliberately do NOT set this.\n glyphDecorative: true,\n })),\n attrs: [...items],\n }\n}\n\n/* ── Helpers ──────────────────────────────────────────────────────────────── */\n\nfunction isPlainTab(event: KeyboardEvent): boolean {\n return event.key === 'Tab' && !event.altKey && !event.ctrlKey && !event.metaKey\n}\n\nconst BARE_URL = /^(?:https?:\\/\\/|www\\.)\\S+$/i\n\n/**\n * What the link field accepts: an http(s) / mailto / tel URL, or a bare domain\n * that gets `https://` in front. Anything with another scheme is refused —\n * `javascript:` above all — before it can reach `setLink`, which refuses it\n * again by its own allowlist. Two locks, same door.\n */\nfunction normalizeHref(input: string): string | null {\n const trimmed = input.trim()\n if (trimmed === '') return null\n if (/^[a-z][a-z0-9+.-]*:/i.test(trimmed)) {\n return /^(?:https?:|mailto:|tel:)/i.test(trimmed) ? trimmed : null\n }\n if (/^(?:www\\.)?[\\w-]+(?:\\.[\\w-]+)+(?:[/?#]\\S*)?$/i.test(trimmed)) return `https://${trimmed}`\n return null\n}\n\n/** A `--space-*` token as a number, for floating-ui's offset. Falls back to the token's documented value. */\nfunction readSpaceToken(element: HTMLElement | null, token: string, fallback: number): number {\n if (element === null || typeof getComputedStyle !== 'function') return fallback\n const raw = parseFloat(getComputedStyle(element).getPropertyValue(token))\n return Number.isFinite(raw) && raw > 0 ? raw : fallback\n}\n\nfunction focusableButtons(root: HTMLElement | null): HTMLButtonElement[] {\n if (root === null) return []\n return Array.from(root.querySelectorAll<HTMLButtonElement>('button:not([disabled])'))\n}\n\n/* ── The editor ───────────────────────────────────────────────────────────── */\n\ninterface LatestProps {\n readonly value: string\n readonly onChange: (value: string) => void\n readonly onSubmit: (attachmentIds?: readonly string[]) => void\n readonly onCancel: (() => void) | undefined\n readonly mentionItems: ((query: string) => readonly MentionSuggestionItem[]) | undefined\n readonly announce: ((message: string) => void) | undefined\n}\n\nfunction RichSurface({\n value,\n onChange,\n onSubmit,\n onCancel,\n placeholder = 'Add a comment…',\n submitLabel = 'Comment',\n cancelLabel = 'Cancel',\n sending = false,\n disabled = false,\n replyingTo,\n avatar,\n rows = 3,\n mode,\n onModeChange,\n autoFocus = false,\n toolbar = true,\n maxLength,\n label,\n className,\n onEditor,\n mentionItems,\n announce,\n uploadAttachment,\n attachGif,\n searchGifs,\n attachmentAccept,\n attachmentMaxPerComment,\n attachmentMaxFileBytes,\n attachmentMaxTotalBytes,\n}: RichThreadComposerImplProps) {\n const labelId = useId()\n const hintId = useId()\n const linkErrorId = useId()\n const listboxId = useId()\n const shellRef = useRef<HTMLDivElement>(null)\n const bubbleRef = useRef<HTMLDivElement>(null)\n const linkInputRef = useRef<HTMLInputElement>(null)\n const [gifPickerOpen, setGifPickerOpen] = useState(false)\n const attachments = useAttachments({\n ...(uploadAttachment === undefined ? {} : { upload: uploadAttachment }),\n ...(attachGif === undefined ? {} : { attachGif }),\n ...(announce === undefined ? {} : { onError: announce }),\n ...(attachmentMaxPerComment === undefined\n ? {}\n : { maxPerComment: attachmentMaxPerComment }),\n ...(attachmentMaxFileBytes === undefined ? {} : { maxFileBytes: attachmentMaxFileBytes }),\n ...(attachmentMaxTotalBytes === undefined\n ? {}\n : { maxTotalBytes: attachmentMaxTotalBytes }),\n })\n\n // The editor is created once; its callbacks read the latest props through\n // this ref rather than the closures they were created with.\n const latest = useRef<LatestProps>({ value, onChange, onSubmit, onCancel, mentionItems, announce })\n useLayoutEffect(() => {\n latest.current = { value, onChange, onSubmit, onCancel, mentionItems, announce }\n })\n const editorRef = useRef<Editor | null>(null)\n\n // D12 — draft emission.\n const lastEmitted = useRef<string>(value)\n const emitTimer = useRef<number | null>(null)\n const [pendingSubmit, setPendingSubmit] = useState<string | null>(null)\n\n // D7 / D9 / D11 — menu state. Refs are the truth the ProseMirror handlers\n // read synchronously; the React state mirrors them for rendering.\n const composing = useRef(false)\n const bubbleOpenRef = useRef(false)\n\n // ADR-149 — the suggestion popup. The ref is what `handleKeyDown` reads\n // (a keystroke cannot wait for a render); the state is what draws.\n const suggestionRef = useRef<{\n readonly kind: SuggestionKind\n readonly attrs: readonly SuggestionAttrs[]\n readonly command: (attrs: SuggestionAttrs) => void\n } | null>(null)\n const activeIndexRef = useRef(0)\n const [suggestion, setSuggestion] = useState<{\n readonly kind: SuggestionKind\n readonly container: HTMLElement\n readonly options: readonly SuggestionOption[]\n } | null>(null)\n const [activeIndex, setActiveIndex] = useState(0)\n\n const setActiveOption = useCallback((index: number) => {\n activeIndexRef.current = index\n setActiveIndex(index)\n }, [])\n\n const optionDomId = useCallback(\n (index: number) => `${listboxId}-option-${String(index)}`,\n [listboxId],\n )\n\n /** Insert the row at `index`; the plugin's own command owns the document. */\n const commitSuggestion = useCallback((index: number) => {\n const active = suggestionRef.current\n const attrs = active?.attrs[index]\n if (active === undefined || active === null || attrs === undefined) return\n active.command(attrs)\n }, [])\n const dismissedSelection = useRef<{ from: number; to: number } | null>(null)\n const [bubbleOpen, setBubbleOpen] = useState(false)\n const [focusRequest, setFocusRequest] = useState<'toolbar' | 'link' | null>(null)\n const [linkMode, setLinkMode] = useState(false)\n const [linkDraft, setLinkDraft] = useState('')\n const [linkError, setLinkError] = useState(false)\n const [rovingIndex, setRovingIndex] = useState(0)\n\n const setBubble = useCallback((open: boolean) => {\n bubbleOpenRef.current = open\n setBubbleOpen((prev) => (prev === open ? prev : open))\n if (!open) {\n setLinkMode(false)\n setLinkError(false)\n setFocusRequest(null)\n }\n }, [])\n\n /** D7: the one predicate both the plugin and the React state answer to. */\n const shouldShowBubble = useCallback((editor: Editor): boolean => {\n if (!editor.isEditable) return false\n const { selection, doc } = editor.state\n if (selection.empty || !isTextSelection(selection)) return false\n if (doc.textBetween(selection.from, selection.to, ' ').trim() === '') return false\n if (editor.isActive('codeBlock')) return false\n if (editor.view.composing || composing.current) return false\n if (suggestionRef.current !== null) return false\n const dismissed = dismissedSelection.current\n if (dismissed !== null) {\n if (dismissed.from === selection.from && dismissed.to === selection.to) return false\n dismissedSelection.current = null\n }\n return true\n }, [])\n\n const syncBubble = useCallback(\n (editor: Editor) => {\n setBubble(shouldShowBubble(editor))\n },\n [setBubble, shouldShowBubble],\n )\n\n const dismissBubble = useCallback(\n (editor: Editor) => {\n const { from, to } = editor.state.selection\n dismissedSelection.current = { from, to }\n setBubble(false)\n editor.view.dispatch(editor.state.tr.setMeta(BUBBLE_MENU_KEY, 'hide'))\n },\n [setBubble],\n )\n\n const emitNow = useCallback((editor: Editor): string => {\n const markdown = serializeRichMarkdown(editor.getJSON())\n if (markdown !== lastEmitted.current) {\n lastEmitted.current = markdown\n latest.current.onChange(markdown)\n }\n return markdown\n }, [])\n\n const clearEmitTimer = useCallback(() => {\n if (emitTimer.current !== null) {\n window.clearTimeout(emitTimer.current)\n emitTimer.current = null\n }\n }, [])\n\n const scheduleEmit = useCallback(\n (editor: Editor) => {\n clearEmitTimer()\n emitTimer.current = window.setTimeout(() => {\n emitTimer.current = null\n if (!editor.isDestroyed) emitNow(editor)\n }, DRAFT_DEBOUNCE_MS)\n },\n [clearEmitTimer, emitNow],\n )\n\n const flushEmit = useCallback(\n (editor: Editor): string => {\n clearEmitTimer()\n return emitNow(editor)\n },\n [clearEmitTimer, emitNow],\n )\n\n const requestSubmit = useCallback(\n (editor: Editor) => {\n if (editor.isEmpty) return\n const markdown = flushEmit(editor)\n setPendingSubmit(markdown)\n },\n [flushEmit],\n )\n\n /**\n * D8 — pasted text. A single URL becomes a link whose text is the URL; text\n * that parses within the subset is parsed as markdown; anything else — a\n * plain paste (Shift), or markdown holding a table, raw HTML, an h4 — lands\n * as literal paragraphs so no character is dropped.\n */\n const parsePastedText = useCallback(\n (text: string, plain: boolean, view: EditorView): Slice => {\n const { schema } = view.state\n const trimmed = text.trim()\n const linkType = schema.marks['link']\n const paragraphType = schema.nodes['paragraph']\n if (linkType !== undefined && BARE_URL.test(trimmed)) {\n const href = /^www\\./i.test(trimmed) ? `https://${trimmed}` : trimmed\n return new Slice(Fragment.from(schema.text(trimmed, [linkType.create({ href })])), 0, 0)\n }\n if (!plain && isRichEditable(text)) {\n try {\n const doc = ProseMirrorNode.fromJSON(schema, parseRichMarkdown(text))\n doc.check()\n return Slice.maxOpen(doc.content)\n } catch {\n // Fall through to literal text; nothing is dropped either way.\n }\n }\n if (paragraphType === undefined) return Slice.empty\n const paragraphs = text\n .split(/\\r\\n?|\\n/)\n .map((line) => paragraphType.create(null, line === '' ? null : schema.text(line)))\n return Slice.maxOpen(Fragment.from(paragraphs))\n },\n [],\n )\n\n /**\n * One `render()` per trigger, both drawing the same `<SuggestionList>`\n * (ADR-149 D1). The closure per plugin owns exactly two things: the portal\n * element the popup lives in, and the `unmount` that floating-ui hands back.\n *\n * The rows are recomputed here from `props.query` rather than read off\n * `props.items`, because `@tiptap/suggestion` types its items as `any` and\n * this file does not take `any` (CLAUDE.md §3). The plugin still owns the\n * threshold — below `minQueryLength` it reports an empty query's worth of\n * items and we close, which is the same door \"no matches\" comes through.\n */\n const makeSuggestionRenderer = useCallback(\n (kind: SuggestionKind) => {\n let container: HTMLElement | null = null\n let unmount: (() => void) | null = null\n let lastQuery: string | null = null\n\n const rowsFor = (query: string): SuggestionRows => {\n // D4: a bare sigil is punctuation, not a trigger.\n if (query.length < SUGGESTION_MIN_QUERY[kind]) return EMPTY_ROWS\n if (kind === 'emoji') return emojiRows(query)\n const items = latest.current.mentionItems?.(query)\n return items === undefined ? EMPTY_ROWS : mentionRows(items)\n }\n\n const close = () => {\n if (unmount !== null) {\n unmount()\n unmount = null\n }\n container = null\n lastQuery = null\n if (suggestionRef.current?.kind === kind) suggestionRef.current = null\n setSuggestion((prev) => (prev !== null && prev.kind === kind ? null : prev))\n }\n\n const sync = (props: SuggestionRenderProps) => {\n const rows = rowsFor(props.query)\n // D4: nothing to show is one of the four things that mean \"no\".\n if (rows.options.length === 0) {\n close()\n return\n }\n const opening = container === null\n let element = container\n if (element === null) {\n element = document.createElement('div')\n element.className = 'ds-thread-suggestions-anchor'\n container = element\n // The plugin owns anchoring — it re-reads the caret rect on scroll,\n // resize and layout shift. `onPosition` is what keeps it from\n // hiding the element until it has measured, which would make the\n // popup invisible to a jsdom role query for no benefit.\n const anchored = element\n unmount = props.mount(element, {\n onPosition: ({ x, y, strategy }) => {\n anchored.style.position = strategy\n anchored.style.left = `${String(x)}px`\n anchored.style.top = `${String(y)}px`\n },\n })\n }\n // The plugin dispatches `started` and `updated` for one keystroke;\n // redrawing the same query would also reset the active option under a\n // user who had already arrowed down. The ref is refreshed on the SAME\n // side of this gate as the drawn rows, deliberately: `attrs` is what\n // an index resolves against, so letting it move while the options on\n // screen stay put would let Enter insert a row nobody was looking at.\n if (!opening && lastQuery === props.query) return\n suggestionRef.current = { kind, attrs: rows.attrs, command: props.command }\n lastQuery = props.query\n setActiveOption(0)\n setBubble(false)\n setSuggestion({ kind, container: element, options: rows.options })\n // A `role=\"textbox\"` cannot carry `aria-expanded` (ARIA reserves it\n // for combobox), so nothing in the markup tells a screen-reader user\n // the popup appeared. One polite line at OPEN does — once per\n // session, not once per keystroke, because a count that re-announces\n // on every letter is worse than no count at all.\n if (opening) {\n latest.current.announce?.(\n `${String(rows.options.length)} ${SUGGESTION_NOUNS[kind]} suggestions. Use the arrow keys to choose, Enter to insert, Escape to close.`,\n )\n }\n }\n\n return {\n onStart: sync,\n onUpdate: sync,\n onExit: close,\n // Escape, the arrows, Enter and Tab are all answered in\n // `handleKeyDown` below — `editorProps` handlers run before any\n // plugin's, which is what makes ADR-148 D9's Escape order a fact.\n onKeyDown: () => false,\n }\n },\n [setActiveOption, setBubble],\n )\n\n const editor = useEditor(\n {\n extensions: [\n ...richSubsetExtensions({\n mention: { render: () => makeSuggestionRenderer('mention') },\n emoji: { render: () => makeSuggestionRenderer('emoji') },\n }),\n Placeholder.configure({ placeholder }),\n ],\n content: value,\n contentType: 'markdown',\n editable: !disabled,\n autofocus: autoFocus ? 'end' : false,\n // D8 is implemented once, in `clipboardTextParser` below. TipTap's\n // regex paste rules (bold, italic, strike, code, …) would run a second,\n // looser pass over the pasted text — and re-format a Shift-paste that\n // was meant to stay literal. Input rules (typing `**x**`, `- `, `---`)\n // are unaffected.\n enablePasteRules: false,\n editorProps: {\n /**\n * THE fix for \"the entire viewport is scrolling down\" on Enter.\n *\n * ProseMirror scrolls the selection into view after any transaction\n * that asks for it — every Enter, every arrow key, most typing. Its\n * `scrollRectIntoView` walks UP from the editor and scrolls *every*\n * scrollable ancestor it finds until the caret is visible: the\n * thread's own body, then `PageShell`'s content region, then whatever\n * else. Capping the editor's height does not stop that; it only\n * changes which ancestor moves. The ancestors have to be taken out of\n * the walk entirely, and this hook is the only supported way to do it.\n *\n * Returning `true` means \"handled — do not run the default\". We then\n * do the one scroll that is legitimate: bring the caret into view\n * inside the EDITOR, and touch nothing else. `scrollTop` on a single\n * element cannot chain.\n */\n handleScrollToSelection: (view) => {\n const dom = view.dom as HTMLElement\n const head = view.state.selection.head\n let caret: { top: number; bottom: number }\n try {\n caret = view.coordsAtPos(head)\n } catch {\n // A position with no coords yet (mid-reconfigure). Nothing to\n // scroll to, and the default would be no better.\n return true\n }\n const box = dom.getBoundingClientRect()\n // One line of slack so the caret is never flush against the edge.\n const pad = parseFloat(getComputedStyle(dom).lineHeight) || 0\n dom.scrollTop += caretScrollDelta(box, caret, pad)\n return true\n },\n attributes: {\n role: 'textbox',\n 'aria-multiline': 'true',\n 'aria-labelledby': labelId,\n 'aria-describedby': hintId,\n },\n handleDOMEvents: {\n // D9: Tab is never captured. Returning true here skips ProseMirror's\n // own keydown handling (and every keymap) without preventDefault, so\n // the browser moves focus. ADR-149 D5 is the one exception: while a\n // suggestion popup is open Tab INSERTS, so this stands down and\n // `handleKeyDown` answers it (and does preventDefault, so focus\n // stays where it already is — on the editor).\n keydown: (_view, event) => isPlainTab(event) && suggestionRef.current === null,\n compositionstart: () => {\n composing.current = true\n setBubble(false)\n return false\n },\n compositionend: () => {\n composing.current = false\n return false\n },\n },\n handleKeyDown: (view, event) => {\n const editorFromView = editorRef.current\n if (editorFromView === null) return false\n const mod = event.metaKey || event.ctrlKey\n if (event.key === 'Escape') {\n if (bubbleOpenRef.current) {\n dismissBubble(editorFromView)\n return true\n }\n const openSuggestion = suggestionRef.current\n if (openSuggestion !== null) {\n // D5 / AC#7: close WITHOUT inserting, and do not fall through to\n // the reply composer's cancel — that is the third slot, not the\n // second. The plugin also records the range as dismissed, so the\n // popup does not spring back on the next keystroke.\n exitSuggestionPlugin(view, openSuggestion.kind)\n return true\n }\n const cancel = latest.current.onCancel\n if (cancel !== undefined) {\n cancel()\n return true\n }\n return false\n }\n if (mod && event.key === 'Enter') {\n requestSubmit(editorFromView)\n return true\n }\n // ADR-149 D5 — the popup's keys, intercepted before the editor's own\n // keymap. Every one of them is unmodified: Cmd+Enter above still\n // sends, and Shift+Enter still makes a hard break.\n const navigating = suggestionRef.current\n if (navigating !== null && !mod && !event.altKey && !event.shiftKey) {\n const count = navigating.attrs.length\n if (event.key === 'ArrowDown') {\n setActiveOption(wrapIndex(activeIndexRef.current, count, 1))\n return true\n }\n if (event.key === 'ArrowUp') {\n setActiveOption(wrapIndex(activeIndexRef.current, count, -1))\n return true\n }\n if (event.key === 'Enter' || event.key === 'Tab') {\n commitSuggestion(activeIndexRef.current)\n return true\n }\n }\n if (mod && event.shiftKey && !event.altKey && event.key.toLowerCase() === 'x') {\n editorFromView.chain().focus().toggleStrike().run()\n return true\n }\n if (mod && event.key === '.') {\n if (!shouldShowBubble(editorFromView)) return false\n dismissedSelection.current = null\n setBubble(true)\n setLinkMode(false)\n setRovingIndex(0)\n setFocusRequest('toolbar')\n return true\n }\n if (mod && !event.shiftKey && !event.altKey && event.key.toLowerCase() === 'k') {\n if (editorFromView.isActive('link') && view.state.selection.empty) {\n editorFromView.commands.extendMarkRange('link')\n }\n if (!shouldShowBubble(editorFromView)) return true\n dismissedSelection.current = null\n setBubble(true)\n setLinkDraft(readHref(editorFromView))\n setLinkError(false)\n setLinkMode(true)\n setFocusRequest('link')\n return true\n }\n return false\n },\n handlePaste: (_view, event) => {\n const dt = event.clipboardData\n if (!dt || dt.files.length > 0 || dt.types.includes('text/html')) return false\n return attachments.addPastedText(dt.getData('text/plain'))\n },\n clipboardTextParser: (text, _context, plain, view) => parsePastedText(text, plain, view),\n },\n onCreate: ({ editor: created }) => {\n editorRef.current = created\n },\n onUpdate: ({ editor: updated }) => {\n setPendingSubmit(null)\n scheduleEmit(updated)\n syncBubble(updated)\n },\n onSelectionUpdate: ({ editor: updated }) => {\n syncBubble(updated)\n },\n onFocus: ({ editor: focused }) => {\n syncBubble(focused)\n },\n onBlur: ({ editor: blurred, event }) => {\n flushEmit(blurred)\n const next = event.relatedTarget\n const insideMenu = next instanceof Node && bubbleRef.current?.contains(next) === true\n if (!insideMenu) setBubble(false)\n // D4: blur is one of the four things that close the popup. Clicking an\n // option cannot reach here — the option's `mousedown` is prevented, so\n // the editor never loses focus (D5, AC#6).\n const openSuggestion = suggestionRef.current\n if (openSuggestion !== null) exitSuggestionPlugin(blurred.view, openSuggestion.kind)\n },\n },\n [],\n )\n\n useLayoutEffect(() => {\n editorRef.current = editor\n }, [editor])\n\n useEffect(() => {\n onEditor?.(editor)\n return () => {\n onEditor?.(null)\n }\n }, [editor, onEditor])\n\n useEffect(() => {\n editor.setEditable(!disabled)\n }, [disabled, editor])\n\n const insertPastedText = useCallback(\n (localId: string) => {\n const text = attachments.insertAsText(localId)\n if (text === null) return\n const slice = parsePastedText(text, true, editor.view)\n editor.view.dispatch(editor.state.tr.replaceSelection(slice).scrollIntoView())\n editor.commands.focus()\n },\n [attachments, editor, parsePastedText],\n )\n\n // An external `value` — a resumed draft, a reset after send — replaces the\n // document. Our own emissions never come back through here, and a pending\n // emission is dropped rather than allowed to resurrect what was just replaced.\n useEffect(() => {\n if (value === lastEmitted.current) return\n clearEmitTimer()\n lastEmitted.current = value\n editor.commands.setContent(value, { contentType: 'markdown', emitUpdate: false })\n }, [clearEmitTimer, editor, value])\n\n // Send fires once the parent holds what was flushed AND every upload has a\n // verified ticket. Uploading never disables Send: pressing it records the\n // intent here, then this effect finishes the post when the last ticket lands.\n useEffect(() => {\n if (pendingSubmit === null || value !== pendingSubmit || attachments.isUploading) return\n if (attachments.attachments.some((attachment) => attachment.state !== 'ready')) return\n setPendingSubmit(null)\n onSubmit(attachments.ticketIds.length === 0 ? undefined : attachments.ticketIds)\n attachments.clear()\n }, [attachments, onSubmit, pendingSubmit, value])\n\n // Unmount: keystrokes still inside the debounce window reach the draft —\n // unless the parent moved on in the meantime, in which case they are stale\n // and must not clobber what replaced them.\n useEffect(\n () => () => {\n if (emitTimer.current === null) return\n window.clearTimeout(emitTimer.current)\n emitTimer.current = null\n if (latest.current.value === lastEmitted.current && !editor.isDestroyed) emitNow(editor)\n },\n [editor, emitNow],\n )\n\n // D10 — the counter's polite announcement at 90 %, once per crossing.\n const announced = useRef(false)\n useEffect(() => {\n if (maxLength === undefined) return\n const over = value.length > maxLength * 0.9\n if (over && !announced.current) {\n announced.current = true\n announce?.(\n `Approaching the comment length limit: ${String(value.length)} of ${String(maxLength)} characters`,\n )\n } else if (!over) {\n announced.current = false\n }\n }, [announce, maxLength, value.length])\n\n /**\n * D5 — the editor is the accessible OWNER of the popup. It keeps DOM focus,\n * points at the listbox with `aria-controls`, and names the active option\n * with `aria-activedescendant`; nothing inside the popup is ever focused.\n *\n * Written straight onto the contenteditable because `editorProps.attributes`\n * are fixed when the editor is created. That is safe: ProseMirror's document\n * decoration only removes attribute names IT set on a previous pass, so a\n * name it has never seen survives every transaction.\n */\n useLayoutEffect(() => {\n if (editor.isDestroyed) return\n const dom = editor.view.dom\n if (suggestion === null) {\n dom.removeAttribute('aria-controls')\n dom.removeAttribute('aria-activedescendant')\n return\n }\n dom.setAttribute('aria-controls', listboxId)\n dom.setAttribute('aria-activedescendant', optionDomId(activeIndex))\n }, [activeIndex, editor, listboxId, optionDomId, suggestion])\n\n // Keyboard-opened menu (D7): focus lands on the first button or the link field.\n useEffect(() => {\n if (focusRequest === null || !bubbleOpen) return\n const target =\n focusRequest === 'link' ? linkInputRef.current : focusableButtons(bubbleRef.current)[0]\n if (target instanceof HTMLElement) {\n target.focus()\n setFocusRequest(null)\n }\n }, [bubbleOpen, focusRequest, linkMode])\n\n const active = useEditorState({\n editor,\n selector: ({ editor: current }) => ({\n isEmpty: current.isEmpty,\n bold: current.isActive('bold'),\n italic: current.isActive('italic'),\n underline: current.isActive('underline'),\n strike: current.isActive('strike'),\n code: current.isActive('code'),\n link: current.isActive('link'),\n h1: current.isActive('heading', { level: 1 }),\n h2: current.isActive('heading', { level: 2 }),\n h3: current.isActive('heading', { level: 3 }),\n bulletList: current.isActive('bulletList'),\n orderedList: current.isActive('orderedList'),\n blockquote: current.isActive('blockquote'),\n codeBlock: current.isActive('codeBlock'),\n }),\n })\n\n const overLimit = maxLength !== undefined && value.length > maxLength\n const canSend =\n !active.isEmpty &&\n !sending &&\n !disabled &&\n !overLimit &&\n pendingSubmit === null &&\n !attachments.attachments.some((attachment) => attachment.state === 'failed')\n\n /* ── Bubble menu actions ───────────────────────────────────────────────── */\n\n const openLinkField = useCallback(() => {\n setLinkDraft(readHref(editor))\n setLinkError(false)\n setLinkMode(true)\n setFocusRequest('link')\n }, [editor])\n\n const applyLink = useCallback(() => {\n const href = normalizeHref(linkDraft)\n if (href === null) {\n setLinkError(true)\n return\n }\n const applied = editor.chain().focus().extendMarkRange('link').setLink({ href }).run()\n if (!applied) {\n setLinkError(true)\n return\n }\n setLinkMode(false)\n setLinkError(false)\n }, [editor, linkDraft])\n\n const removeLink = useCallback(() => {\n editor.chain().focus().extendMarkRange('link').unsetLink().run()\n setLinkMode(false)\n setLinkError(false)\n }, [editor])\n\n const closeLinkField = useCallback(() => {\n setLinkMode(false)\n setLinkError(false)\n setRovingIndex(BUBBLE_ACTIONS.length - 1)\n setFocusRequest('toolbar')\n }, [])\n\n /** Roving focus across the bubble toolbar; Escape returns to the editor. */\n const onToolbarKeyDown = useCallback(\n (event: ReactKeyboardEvent<HTMLDivElement>) => {\n const buttons = focusableButtons(event.currentTarget)\n const current = buttons.findIndex((button) => button === document.activeElement)\n const move = (index: number) => {\n const next = buttons[(index + buttons.length) % buttons.length]\n if (next === undefined) return\n setRovingIndex(buttons.indexOf(next))\n next.focus()\n }\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowDown':\n event.preventDefault()\n move(current + 1)\n return\n case 'ArrowLeft':\n case 'ArrowUp':\n event.preventDefault()\n move(current - 1)\n return\n case 'Home':\n event.preventDefault()\n move(0)\n return\n case 'End':\n event.preventDefault()\n move(buttons.length - 1)\n return\n case 'Escape':\n event.preventDefault()\n event.stopPropagation()\n dismissBubble(editor)\n editor.commands.focus()\n return\n default:\n return\n }\n },\n [dismissBubble, editor],\n )\n\n const onLinkFieldKeyDown = useCallback(\n (event: ReactKeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n applyLink()\n } else if (event.key === 'Escape') {\n event.preventDefault()\n event.stopPropagation()\n closeLinkField()\n }\n },\n [applyLink, closeLinkField],\n )\n\n const bubbleActive: Readonly<Record<BubbleAction, boolean>> = {\n bold: active.bold,\n italic: active.italic,\n underline: active.underline,\n strike: active.strike,\n code: active.code,\n link: active.link,\n }\n\n const runBubbleAction = useCallback(\n (action: BubbleAction) => {\n switch (action) {\n case 'bold':\n editor.chain().focus().toggleBold().run()\n return\n case 'italic':\n editor.chain().focus().toggleItalic().run()\n return\n case 'underline':\n editor.chain().focus().toggleUnderline().run()\n return\n case 'strike':\n editor.chain().focus().toggleStrike().run()\n return\n case 'code':\n editor.chain().focus().toggleCode().run()\n return\n case 'link':\n openLinkField()\n return\n }\n },\n [editor, openLinkField],\n )\n\n const runBlockAction = useCallback(\n (action: BlockAction) => {\n const chain = editor.chain().focus()\n switch (action) {\n case 'h1':\n chain.toggleHeading({ level: 1 }).run()\n return\n case 'h2':\n chain.toggleHeading({ level: 2 }).run()\n return\n case 'h3':\n chain.toggleHeading({ level: 3 }).run()\n return\n case 'bulletList':\n chain.toggleBulletList().run()\n return\n case 'orderedList':\n chain.toggleOrderedList().run()\n return\n case 'blockquote':\n chain.toggleBlockquote().run()\n return\n case 'codeBlock':\n chain.toggleCodeBlock().run()\n return\n case 'divider':\n chain.setHorizontalRule().run()\n return\n }\n },\n [editor],\n )\n\n const blockActive: Readonly<Record<BlockAction, boolean>> = {\n h1: active.h1,\n h2: active.h2,\n h3: active.h3,\n bulletList: active.bulletList,\n orderedList: active.orderedList,\n blockquote: active.blockquote,\n codeBlock: active.codeBlock,\n divider: false,\n }\n\n const shellStyle: StyleWithVars = {\n // Concentric: the host panel declares --thread-inner-radius as its own\n // radius minus its padding. Nothing here eyeballs a corner.\n borderRadius: 'var(--thread-inner-radius, var(--radius-sm))',\n borderColor: 'rgb(var(--border))',\n background: 'rgb(var(--surface-card))',\n '--composer-rows': String(rows),\n }\n\n const controlsDisabled = disabled || sending || pendingSubmit !== null\n\n return (\n <div className={cn('flex flex-col gap-[var(--space-1)]', className)}>\n {replyingTo === undefined ? null : (\n <p\n className=\"flex items-center gap-[var(--space-1)] text-[12px]\"\n style={{ color: 'rgb(var(--text-tertiary))' }}\n >\n <CornerDownRight size={10} strokeWidth={1.5} aria-hidden=\"true\" />\n Replying to{' '}\n <span className=\"font-semibold\" style={{ color: 'rgb(var(--text-secondary))' }}>\n {replyingTo}\n </span>\n </p>\n )}\n <div className=\"flex items-start gap-[var(--space-2)]\">\n {avatar}\n <AttachmentDropZone\n onFiles={attachments.addFiles}\n disabled={controlsDisabled || uploadAttachment === undefined}\n className=\"min-w-0 flex-1\"\n >\n <div\n ref={shellRef}\n className={cn(\n 'ds-thread-rich-composer relative min-w-0 w-full border',\n 'transition-[border-color,box-shadow] duration-[var(--dur-fast)] ease-[var(--ease-out)]',\n 'motion-reduce:transition-none',\n 'focus-within:border-[rgb(var(--accent))] focus-within:[box-shadow:var(--ring-focus)]',\n )}\n style={shellStyle}\n >\n {/* A contenteditable has no implicit name; these two are what the\n textbox points at (D10). */}\n <span id={labelId} className=\"sr-only\">\n {label}\n </span>\n <span id={hintId} className=\"sr-only\">\n {`${MOD_NAME}+Enter sends. ${MOD_NAME}+Period opens the formatting menu on a selection. Type @ to mention someone, or a colon and two letters for emoji, then use the arrow keys and Enter. Escape closes the menu${onCancel === undefined ? '' : ', then cancels the reply'}.`}\n </span>\n\n <EditorContent editor={editor} />\n\n {/* ADR-149 — ONE popup for both triggers. It is portalled into the\n element the Suggestion plugin mounts and anchors (floating-ui,\n already a dependency of that plugin), so it escapes the thread's\n own scroll clipping. It is still the editor's, through\n `aria-controls` above. */}\n {suggestion === null\n ? null\n : createPortal(\n <SuggestionList\n id={listboxId}\n label={SUGGESTION_LABELS[suggestion.kind]}\n options={suggestion.options}\n activeIndex={activeIndex}\n optionId={optionDomId}\n onSelect={commitSuggestion}\n onActivate={setActiveOption}\n />,\n suggestion.container,\n )}\n\n <BubbleMenu\n ref={bubbleRef}\n editor={editor}\n pluginKey={BUBBLE_MENU_KEY}\n updateDelay={0}\n shouldShow={({ editor: current }) => shouldShowBubble(current)}\n appendTo={() => shellRef.current ?? document.body}\n options={{\n placement: 'top',\n offset: readSpaceToken(shellRef.current, '--space-2', 8),\n flip: true,\n shift: true,\n }}\n className=\"ds-thread-bubble-menu\"\n data-open={bubbleOpen}\n >\n {!bubbleOpen ? null : linkMode ? (\n <div\n role=\"group\"\n aria-label=\"Link\"\n className=\"flex items-center gap-[var(--space-1)]\"\n style={{\n padding: 'var(--space-1)',\n background: 'rgb(var(--surface-card))',\n border: '1px solid rgb(var(--border))',\n borderRadius: 'var(--radius-sm)',\n boxShadow: 'var(--shadow-lg)',\n }}\n >\n <input\n ref={linkInputRef}\n type=\"url\"\n aria-label=\"Link URL\"\n aria-invalid={linkError}\n {...(linkError ? { 'aria-describedby': linkErrorId } : {})}\n placeholder=\"https://\"\n value={linkDraft}\n onChange={(event) => {\n setLinkDraft(event.target.value)\n setLinkError(false)\n }}\n onKeyDown={onLinkFieldKeyDown}\n className=\"min-w-0 bg-transparent text-[12.5px] outline-none\"\n style={{\n inlineSize: '22ch',\n blockSize: 'var(--ctrl-sm)',\n paddingInline: 'var(--space-2)',\n color: 'rgb(var(--foreground))',\n borderRadius: 'var(--radius-xs)',\n border: linkError\n ? '1px solid rgb(var(--warning))'\n : '1px solid rgb(var(--border))',\n }}\n />\n <Button\n variant=\"icon\"\n size=\"sm\"\n aria-label=\"Apply link\"\n title=\"Apply link\"\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onClick={applyLink}\n >\n <Check size={12} strokeWidth={2} aria-hidden=\"true\" />\n </Button>\n {active.link ? (\n <Button\n variant=\"icon\"\n size=\"sm\"\n aria-label=\"Remove link\"\n title=\"Remove link\"\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onClick={removeLink}\n >\n <Unlink size={12} strokeWidth={1.75} aria-hidden=\"true\" />\n </Button>\n ) : null}\n <Button\n variant=\"icon\"\n size=\"sm\"\n aria-label=\"Close link field\"\n title=\"Close\"\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onClick={closeLinkField}\n >\n <X size={12} strokeWidth={1.75} aria-hidden=\"true\" />\n </Button>\n {linkError ? (\n <span id={linkErrorId} role=\"alert\" className=\"sr-only\">\n Enter a web, email or phone link.\n </span>\n ) : null}\n </div>\n ) : (\n <div\n role=\"toolbar\"\n aria-label=\"Format selection\"\n aria-orientation=\"horizontal\"\n onKeyDown={onToolbarKeyDown}\n >\n {BUBBLE_ACTIONS.map((action, index) => {\n const Icon = action.icon\n return (\n <Button\n key={action.id}\n variant=\"icon\"\n size=\"sm\"\n aria-label={action.label}\n aria-pressed={bubbleActive[action.id]}\n title={`${action.label} (${MOD_NAME}+${action.keycap})`}\n tabIndex={index === rovingIndex ? 0 : -1}\n onMouseDown={(event) => {\n // Keep the editor's selection: a click here must\n // format it, not collapse it.\n event.preventDefault()\n }}\n onClick={() => {\n runBubbleAction(action.id)\n }}\n >\n <Icon size={12} strokeWidth={1.75} aria-hidden=\"true\" />\n </Button>\n )\n })}\n </div>\n )}\n </BubbleMenu>\n\n <AttachmentTray\n attachments={attachments.attachments}\n onRemove={attachments.remove}\n onInsertAsText={insertPastedText}\n className=\"px-[var(--space-2)]\"\n />\n\n {/* Switching composer implementations would unmount this hook and\n discard its local upload tickets. Remove the chips first; never\n turn a mode switch into a silent attachment loss. */}\n <ComposerFooter\n {...(mode === undefined ? {} : { mode })}\n {...(onModeChange === undefined ? {} : { onModeChange })}\n modeDisabled={controlsDisabled || attachments.attachments.length > 0}\n toolbar={\n <>\n {uploadAttachment === undefined ? null : (\n <AttachmentButton\n onFiles={attachments.addFiles}\n accept={attachmentAccept ?? ATTACHMENT_ACCEPT}\n disabled={controlsDisabled}\n />\n )}\n {attachGif === undefined || searchGifs === undefined ? null : (\n <Popover open={gifPickerOpen} onOpenChange={setGifPickerOpen}>\n <Popover.Trigger asChild>\n <Button\n variant=\"icon\"\n size=\"sm\"\n aria-label=\"Choose a GIF\"\n title=\"Choose a GIF\"\n disabled={controlsDisabled}\n >\n <Images size={12} strokeWidth={1.75} aria-hidden=\"true\" />\n </Button>\n </Popover.Trigger>\n <Popover.Content\n aria-label=\"Choose a GIF\"\n align=\"start\"\n className=\"p-[var(--space-3)]\"\n style={{\n inlineSize: 'calc(var(--space-12) * 8)',\n maxInlineSize: 'calc(100vw - var(--space-6))',\n }}\n >\n <GifPicker\n search={searchGifs}\n onPick={(gif) => {\n attachments.addGif(gif)\n setGifPickerOpen(false)\n }}\n />\n </Popover.Content>\n </Popover>\n )}\n {toolbar\n ? BLOCK_ACTIONS.map((action) => {\n const Icon = action.icon\n return (\n <Button\n key={action.id}\n variant=\"icon\"\n size=\"sm\"\n aria-label={action.label}\n title={action.label}\n {...(action.id === 'divider' ? {} : { 'aria-pressed': blockActive[action.id] })}\n disabled={controlsDisabled}\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onClick={() => {\n runBlockAction(action.id)\n }}\n >\n <Icon size={12} strokeWidth={1.75} aria-hidden=\"true\" />\n </Button>\n )\n })\n : null}\n </>\n }\n meta={\n <>\n {maxLength === undefined ? null : (\n <span\n className=\"tabular-nums text-right\"\n // Reserved slot so the counter cannot push the buttons around.\n style={{\n minInlineSize: '7ch',\n fontSize: '11.5px',\n color:\n value.length > maxLength * 0.9\n ? 'rgb(var(--warning-ink))'\n : 'rgb(var(--text-tertiary))',\n }}\n >\n {value.length}/{maxLength}\n </span>\n )}\n </>\n }\n actions={\n <>\n {onCancel === undefined ? null : (\n <Button variant=\"secondary\" size=\"sm\" onClick={onCancel} disabled={controlsDisabled}>\n {cancelLabel}\n </Button>\n )}\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={() => {\n requestSubmit(editor)\n }}\n disabled={!canSend}\n aria-label={sending ? 'Sending…' : submitLabel}\n trailingIcon={\n <span aria-hidden=\"true\" className=\"ds-composer-keycap\">\n <Kbd size=\"sm\" tone=\"on-accent\">\n {SEND_KEYCAP}\n </Kbd>\n </span>\n }\n >\n {sending ? 'Sending…' : submitLabel}\n </Button>\n </>\n }\n />\n </div>\n </AttachmentDropZone>\n </div>\n </div>\n )\n}\n\nfunction readHref(editor: Editor): string {\n const href = editor.getAttributes('link')['href']\n return typeof href === 'string' ? href : ''\n}\n\n/* ── The two action tables ────────────────────────────────────────────────── */\n\ntype BubbleAction = 'bold' | 'italic' | 'underline' | 'strike' | 'code' | 'link'\n\ninterface BubbleActionSpec {\n readonly id: BubbleAction\n readonly label: string\n readonly icon: typeof Bold\n readonly keycap: string\n}\n\n/** D7: six actions on a real selection, nothing else. */\nconst BUBBLE_ACTIONS: readonly BubbleActionSpec[] = [\n { id: 'bold', label: 'Bold', icon: Bold, keycap: 'B' },\n { id: 'italic', label: 'Italic', icon: Italic, keycap: 'I' },\n { id: 'underline', label: 'Underline', icon: UnderlineIcon, keycap: 'U' },\n { id: 'strike', label: 'Strikethrough', icon: Strikethrough, keycap: 'Shift+X' },\n { id: 'code', label: 'Code', icon: Code, keycap: 'E' },\n { id: 'link', label: 'Link', icon: LinkIcon, keycap: 'K' },\n]\n\ntype BlockAction =\n | 'h1'\n | 'h2'\n | 'h3'\n | 'bulletList'\n | 'orderedList'\n | 'blockquote'\n | 'codeBlock'\n | 'divider'\n\ninterface BlockActionSpec {\n readonly id: BlockAction\n readonly label: string\n readonly icon: typeof Bold\n}\n\n/** The persistent row: block-level actions act on the block, not the selection. */\nconst BLOCK_ACTIONS: readonly BlockActionSpec[] = [\n { id: 'h1', label: 'Heading 1', icon: Heading1 },\n { id: 'h2', label: 'Heading 2', icon: Heading2 },\n { id: 'h3', label: 'Heading 3', icon: Heading3 },\n { id: 'bulletList', label: 'Bulleted list', icon: List },\n { id: 'orderedList', label: 'Numbered list', icon: ListOrdered },\n { id: 'blockquote', label: 'Quote', icon: TextQuote },\n { id: 'codeBlock', label: 'Code block', icon: SquareCode },\n { id: 'divider', label: 'Divider', icon: Minus },\n]\n"]}
|