# Tasks: enterprise-react-rich-text **Change ID**: enterprise-react-rich-text **Package**: `@suaveplan/react-rich-text` **Target path**: `react/media/react-rich-text` **Prerequisite packages on Verdaccio**: `@suaveplan/error`, `@suaveplan/react-translate` --- ## 0. Pre-flight (non-negotiable) - [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each) - [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Scaffold - [ ] Create directory tree. Write `package.json` at `0.1.0`, `tsconfig.json`, `vitest.config.ts`, scripts. - [ ] Dependencies: `@suaveplan/error workspace:^`, `@suaveplan/react-translate workspace:^`, `@tiptap/core catalog:editor`, `@tiptap/react catalog:editor`, `@tiptap/starter-kit catalog:editor`, `@tiptap/extension-mention catalog:editor`, `@tiptap/extension-placeholder catalog:editor`, `@tiptap/extension-link catalog:editor`, `@tiptap/pm catalog:editor`, `@tiptap/suggestion catalog:editor`, `zod catalog:forms`, `@opentelemetry/api catalog:observability`, `tslib catalog:build`. --- ## 2. Error codes and types - [ ] Define `RichTextError`; codes: `RICH_TEXT_INIT_FAILED`, `RICH_TEXT_PARSE_FAILED`. - [ ] Define all types: `FormatState`, `FormatMark`, `BlockType`, `HeadingLevel`, `MarkdownShortcutRule`, `MentionItem`, `SlashCommand`, `SlashCommandCategory`. --- ## 3. EditorEngine - [ ] `buildExtensions(options)` — assembles Tiptap extensions (StarterKit + Mention + Placeholder + Link + custom slash-command + markdown shortcuts). Throws `RichTextError(RICH_TEXT_INIT_FAILED)` on invalid config. - [ ] `htmlToMarkdown(html: string): string`, `markdownToHtml(md: string): string` — round-trip via regex transforms. - [ ] `filterSlashCommands(query, commands)`, `groupCommandsByCategory(commands)`, `executeSlashCommand(cmd, editor)`. - [ ] Write `editor-engine.test.ts` (≤500 lines): extensions build, htmlToMarkdown/markdownToHtml round-trip, filterSlashCommands, groupByCategory, executeSlashCommand. `{ timeout: 10000 }`. - [ ] Write `editor-engine.md`. --- ## 4. Hooks ### useRichText - [ ] Creates Tiptap `Editor` instance; returns `{ editor, html, markdown, isEmpty }`. OTel `rich_text.submit` span on submit. - [ ] Write test + md. ### useMentions - [ ] Provides suggestion callbacks for `@tiptap/extension-mention`; accepts `onSearch(query): Promise`. - [ ] Write test + md. ### useSlashCommands - [ ] Registers slash-command suggestion plugin; returns `{ commands, filter, execute }`. - [ ] Write test + md. --- ## 5. Components ### EditorContent - [ ] `` — renders Tiptap editor area. - [ ] Write test, stories (default, with-content, read-only, playground), md. ### Toolbar - [ ] Bold/italic/underline/strike/heading/list/quote/code/link buttons wired to `editor.chain()`. `useTranslation` for tooltips. - [ ] Write test, stories (default, formatting-applied, playground), md. ### BubbleMenu - [ ] Selection-anchored menu using Tiptap `BubbleMenu`. Bold/italic/link buttons. - [ ] Write test, stories (**default**, formatting, playground — previously missing), md. ### SlashCommandMenu - [ ] Tiptap suggestion dropdown; renders filtered `SlashCommand` list. - [ ] Write test, stories, md. ### MentionList - [ ] Mention suggestion dropdown with avatar + name. - [ ] Write test, stories, md. ### RichTextEditor - [ ] Composes all components. Accepts `initialContent`, `placeholder`, `onUpdate`, `onSubmit`, `mentionSearch`. - [ ] Write test, stories (default, with-mentions, with-slash-commands, markdown, playground), md. --- ## 6. E2E - [ ] `e2e/rich-text.spec.ts` — Playwright: - Type text, click Bold in toolbar → `` in output. - Type `/` → slash menu appears; select "Heading 1" → H1 applied. - Type `@` → mention list appears; click item → mention inserted. --- ## 7. Verify and publish - [ ] `bunx turbo lint typecheck test --filter=@suaveplan/react-rich-text` — green. - [ ] `bunx turbo test:coverage --filter=@suaveplan/react-rich-text` — 100%. - [ ] `bun scripts/publish.ts --package @suaveplan/react-rich-text`. - [ ] Archive change folder.