@pilotiq/tiptap 3.10.5 → 3.10.7

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.
Files changed (135) hide show
  1. package/CHANGELOG.md +751 -0
  2. package/boost/guidelines.md +268 -0
  3. package/boost/skills/pilotiq-tiptap-blocks/SKILL.md +48 -0
  4. package/boost/skills/pilotiq-tiptap-blocks/rules/custom-blocks.md +90 -0
  5. package/boost/skills/pilotiq-tiptap-blocks/rules/slash-menu-and-mentions.md +101 -0
  6. package/boost/skills/pilotiq-tiptap-blocks/rules/toolbar-and-extensibility.md +161 -0
  7. package/dist/markdownExtension.js +259 -164
  8. package/dist/react/BlockNodeView.d.ts +1 -1
  9. package/dist/react/FloatingToolbar.d.ts +1 -1
  10. package/dist/react/MentionMenu.d.ts +1 -1
  11. package/dist/react/Palette.d.ts +1 -1
  12. package/dist/react/SlashMenu.d.ts +1 -1
  13. package/dist/react/TableFloatingToolbar.d.ts +1 -1
  14. package/dist/react/TiptapEditor.d.ts +1 -1
  15. package/dist/react/Toolbar.d.ts +2 -2
  16. package/package.json +6 -4
  17. package/dist/Block.d.ts.map +0 -1
  18. package/dist/Block.js.map +0 -1
  19. package/dist/MentionProvider.d.ts.map +0 -1
  20. package/dist/MentionProvider.js.map +0 -1
  21. package/dist/PlainTextEditor.d.ts.map +0 -1
  22. package/dist/PlainTextEditor.js.map +0 -1
  23. package/dist/RichTextField.d.ts.map +0 -1
  24. package/dist/RichTextField.js.map +0 -1
  25. package/dist/extensions/AiInlineDiffExtension.d.ts.map +0 -1
  26. package/dist/extensions/AiInlineDiffExtension.js.map +0 -1
  27. package/dist/extensions/AiSuggestionExtension.d.ts.map +0 -1
  28. package/dist/extensions/AiSuggestionExtension.js.map +0 -1
  29. package/dist/extensions/BlockNodeExtension.d.ts.map +0 -1
  30. package/dist/extensions/BlockNodeExtension.js.map +0 -1
  31. package/dist/extensions/DragHandleExtension.d.ts.map +0 -1
  32. package/dist/extensions/DragHandleExtension.js.map +0 -1
  33. package/dist/extensions/GridExtension.d.ts.map +0 -1
  34. package/dist/extensions/GridExtension.js.map +0 -1
  35. package/dist/extensions/MentionExtension.d.ts.map +0 -1
  36. package/dist/extensions/MentionExtension.js.map +0 -1
  37. package/dist/extensions/MergeTagExtension.d.ts.map +0 -1
  38. package/dist/extensions/MergeTagExtension.js.map +0 -1
  39. package/dist/extensions/SlashCommandExtension.d.ts.map +0 -1
  40. package/dist/extensions/SlashCommandExtension.js.map +0 -1
  41. package/dist/extensions/TextSizeMarks.d.ts.map +0 -1
  42. package/dist/extensions/TextSizeMarks.js.map +0 -1
  43. package/dist/index.d.ts.map +0 -1
  44. package/dist/index.js.map +0 -1
  45. package/dist/markdownExtension.d.ts.map +0 -1
  46. package/dist/markdownStorage.d.ts.map +0 -1
  47. package/dist/markdownStorage.js.map +0 -1
  48. package/dist/plugin.d.ts.map +0 -1
  49. package/dist/plugin.js.map +0 -1
  50. package/dist/react/AiSuggestionBanner.d.ts.map +0 -1
  51. package/dist/react/AiSuggestionBanner.js.map +0 -1
  52. package/dist/react/BlockNodeView.d.ts.map +0 -1
  53. package/dist/react/BlockNodeView.js.map +0 -1
  54. package/dist/react/BlockSidePanel.d.ts.map +0 -1
  55. package/dist/react/BlockSidePanel.js.map +0 -1
  56. package/dist/react/CollabTextRenderer.d.ts.map +0 -1
  57. package/dist/react/CollabTextRenderer.js.map +0 -1
  58. package/dist/react/FloatingToolbar.d.ts.map +0 -1
  59. package/dist/react/FloatingToolbar.js.map +0 -1
  60. package/dist/react/MarkdownEditor.d.ts.map +0 -1
  61. package/dist/react/MarkdownEditor.js.map +0 -1
  62. package/dist/react/MentionMenu.d.ts.map +0 -1
  63. package/dist/react/MentionMenu.js.map +0 -1
  64. package/dist/react/Palette.d.ts.map +0 -1
  65. package/dist/react/Palette.js.map +0 -1
  66. package/dist/react/SlashMenu.d.ts.map +0 -1
  67. package/dist/react/SlashMenu.js.map +0 -1
  68. package/dist/react/TableFloatingToolbar.d.ts.map +0 -1
  69. package/dist/react/TableFloatingToolbar.js.map +0 -1
  70. package/dist/react/TiptapEditor.d.ts.map +0 -1
  71. package/dist/react/TiptapEditor.js.map +0 -1
  72. package/dist/react/Toolbar.d.ts.map +0 -1
  73. package/dist/react/Toolbar.js.map +0 -1
  74. package/dist/react/toolbarButtons.d.ts.map +0 -1
  75. package/dist/react/toolbarButtons.js.map +0 -1
  76. package/dist/react/useAiInlineDiff.d.ts.map +0 -1
  77. package/dist/react/useAiInlineDiff.js.map +0 -1
  78. package/dist/react/useAiSuggestionBridge.d.ts.map +0 -1
  79. package/dist/react/useAiSuggestionBridge.js.map +0 -1
  80. package/dist/register.d.ts.map +0 -1
  81. package/dist/register.js.map +0 -1
  82. package/dist/render.d.ts.map +0 -1
  83. package/dist/render.js.map +0 -1
  84. package/dist/surgicalOps.d.ts.map +0 -1
  85. package/dist/surgicalOps.js.map +0 -1
  86. package/dist/test/setup.d.ts.map +0 -1
  87. package/dist/test/setup.js.map +0 -1
  88. package/src/Block.ts +0 -75
  89. package/src/MentionProvider.ts +0 -153
  90. package/src/PlainTextEditor.dom.test.ts +0 -111
  91. package/src/PlainTextEditor.test.ts +0 -158
  92. package/src/PlainTextEditor.ts +0 -229
  93. package/src/RichTextField.test.ts +0 -447
  94. package/src/RichTextField.ts +0 -508
  95. package/src/extensions/AiInlineDiffExtension.ts +0 -286
  96. package/src/extensions/AiSuggestionExtension.test.ts +0 -141
  97. package/src/extensions/AiSuggestionExtension.ts +0 -522
  98. package/src/extensions/BlockNodeExtension.ts +0 -134
  99. package/src/extensions/DragHandleExtension.ts +0 -184
  100. package/src/extensions/GridExtension.test.ts +0 -31
  101. package/src/extensions/GridExtension.ts +0 -138
  102. package/src/extensions/MentionExtension.ts +0 -248
  103. package/src/extensions/MergeTagExtension.ts +0 -75
  104. package/src/extensions/SlashCommandExtension.test.ts +0 -147
  105. package/src/extensions/SlashCommandExtension.ts +0 -332
  106. package/src/extensions/TextSizeMarks.ts +0 -73
  107. package/src/index.ts +0 -62
  108. package/src/markdownExtension.ts +0 -19
  109. package/src/markdownStorage.ts +0 -49
  110. package/src/plugin.test.ts +0 -19
  111. package/src/plugin.ts +0 -26
  112. package/src/react/AiSuggestionBanner.tsx +0 -185
  113. package/src/react/BlockNodeView.tsx +0 -99
  114. package/src/react/BlockSidePanel.dom.test.tsx +0 -38
  115. package/src/react/BlockSidePanel.test.ts +0 -412
  116. package/src/react/BlockSidePanel.tsx +0 -451
  117. package/src/react/CollabTextRenderer.tsx +0 -228
  118. package/src/react/FloatingToolbar.tsx +0 -304
  119. package/src/react/MarkdownEditor.tsx +0 -603
  120. package/src/react/MentionMenu.tsx +0 -120
  121. package/src/react/Palette.tsx +0 -86
  122. package/src/react/SlashMenu.tsx +0 -129
  123. package/src/react/TableFloatingToolbar.tsx +0 -154
  124. package/src/react/TiptapEditor.dom.test.tsx +0 -112
  125. package/src/react/TiptapEditor.tsx +0 -777
  126. package/src/react/Toolbar.tsx +0 -438
  127. package/src/react/toolbarButtons.tsx +0 -579
  128. package/src/react/useAiInlineDiff.ts +0 -342
  129. package/src/react/useAiSuggestionBridge.ts +0 -223
  130. package/src/register.test.ts +0 -14
  131. package/src/register.ts +0 -42
  132. package/src/render.test.ts +0 -745
  133. package/src/render.ts +0 -480
  134. package/src/surgicalOps.ts +0 -205
  135. package/src/test/setup.ts +0 -64
@@ -0,0 +1,161 @@
1
+ # Toolbar & Extensibility
2
+
3
+ Three things in scope here: customizing the always-on toolbar, opting into non-default block primitives (`details`, `grid`, `lead`, `small`), and the pitfalls that bite when you extend the editor beyond the defaults.
4
+
5
+ ## Default toolbar layout
6
+
7
+ ```ts
8
+ [
9
+ ['bold', 'italic', 'underline', 'strike', 'subscript', 'superscript', 'link'],
10
+ ['h2', 'h3'],
11
+ ['alignStart', 'alignCenter', 'alignEnd'],
12
+ ['blockquote', 'codeBlock', 'bulletList', 'orderedList'],
13
+ ['undo', 'redo'],
14
+ ]
15
+ ```
16
+
17
+ Each inner array is a visually-separated group in the rendered toolbar. The selection-anchored floating toolbar (separate surface) shows a smaller subset on text selection — by default `bold / italic / link / clearFormatting`.
18
+
19
+ ## Three customization styles
20
+
21
+ Use whichever matches your intent:
22
+
23
+ ### Replace the whole layout
24
+
25
+ ```ts
26
+ RichTextField.make('body').toolbarButtons([
27
+ ['bold', 'italic', 'underline', 'strike', 'link'],
28
+ ['h2', 'h3'],
29
+ ['textColor', 'highlight'],
30
+ ['bulletList', 'orderedList'],
31
+ ['attachFiles', 'table', 'details', 'grid', 'gridDelete'],
32
+ ['undo', 'redo'],
33
+ ])
34
+ ```
35
+
36
+ ### Augment the defaults
37
+
38
+ ```ts
39
+ RichTextField.make('body')
40
+ .enableToolbarButtons(['lead', 'small']) // append to last group
41
+ .disableToolbarButtons(['table']) // drop from every group
42
+ ```
43
+
44
+ `enableToolbarButtons` always appends to the last group; reach for `toolbarButtons` if you need ids in a specific group.
45
+
46
+ ### Hide chrome entirely
47
+
48
+ ```ts
49
+ RichTextField.make('body')
50
+ .toolbar(false) // hide the always-on top toolbar
51
+ .floatingToolbar(false) // disable the selection-anchored quick toolbar
52
+ .slashCommand(false) // disable the slash menu
53
+ ```
54
+
55
+ All three are independent. A minimal-distraction config: `.toolbar(false).floatingToolbar(false)` but keep the slash menu so the user still has a way to insert blocks.
56
+
57
+ ## Recognized button ids
58
+
59
+ ```
60
+ Inline marks bold italic underline strike subscript superscript code lead small
61
+ Headings paragraph h1 h2 h3 h4 h5 h6
62
+ Alignment alignStart alignCenter alignEnd alignJustify
63
+ Block prims blockquote codeBlock bulletList orderedList horizontalRule
64
+ Style textColor highlight clearFormatting
65
+ Files attachFiles
66
+ Tables table tableAddColumnBefore tableAddColumnAfter tableDeleteColumn
67
+ tableAddRowBefore tableAddRowAfter tableDeleteRow
68
+ tableMergeCells tableSplitCell tableDelete
69
+ tableToggleHeaderRow tableToggleHeaderCell
70
+ Disclosure details
71
+ Layout grid gridDelete
72
+ Editing link undo redo
73
+ ```
74
+
75
+ **Unknown ids are silently dropped.** The union is forward-compatible — adding a new id later won't break existing field configs that referenced a typo or pre-release id.
76
+
77
+ ## Opt-in primitives (not in default toolbar)
78
+
79
+ These nodes ship but aren't surfaced unless you explicitly add their toolbar id (or they appear in the slash menu via the same mechanism). The renderer (`renderRichTextToHtml`) serializes them whether or not the toolbar exposes them — so a document with `details` content created elsewhere still round-trips correctly even if the local field config doesn't include the button.
80
+
81
+ ### `lead` / `small` size marks
82
+
83
+ Two inline marks for paragraph-style size variants:
84
+
85
+ - **`lead`** renders as `<span class="lead">…</span>`. Consumer owns the `.lead` CSS — there's no built-in stylesheet (`@pilotiq/pilotiq`'s typography preset typically has one; check yours).
86
+ - **`small`** renders as semantic `<small>…</small>`.
87
+
88
+ Surfaced as toolbar button ids `'lead'` / `'small'` and slash-menu entries under the **Style** group. Mirror the editor output in your own server-side render (`renderRichTextToHtml` does this correctly).
89
+
90
+ ### `details` (collapsible disclosure)
91
+
92
+ A node trio (`details` / `detailsSummary` / `detailsContent`) wired from `@tiptap/extension-details@3.22.4` — v3 consolidated the three classes into a single peer dep (the `-summary` / `-content` child packages don't exist on the v3 line).
93
+
94
+ - Toolbar id: `'details'` (opt-in)
95
+ - Slash entry under the **Insert** group
96
+ - Render emits standard `<details><summary>…</summary>…</details>` HTML
97
+ - Open / closed state round-trips via the node's `open: boolean` attr; the renderer adds the platform `open` attribute when `attrs.open === true`
98
+
99
+ ### `grid` / `gridDelete` (2-column / 3-column layout)
100
+
101
+ A node pair (`grid` + `gridColumn`) defined inline under `extensions/GridExtension.ts` — Tiptap doesn't ship a first-party grid extension. Schema constrains `grid` to `gridColumn{2,3}` so the user can't construct a 1-col or 4+-col grid through any path (toolbar / slash / paste).
102
+
103
+ - Toolbar ids: `'grid'` (insert; defaults to 2 columns when clicked) + `'gridDelete'` (unwrap the enclosing grid)
104
+ - Slash entries: `Two-column grid`, `Three-column grid` under the **Insert** group
105
+ - Render emits `<div class="pilotiq-grid pilotiq-grid-cols-N">…<div>col</div>…</div>` — consumer owns the CSS (same posture as `lead` / `small`)
106
+ - Out-of-range column counts (anything other than 2 or 3) clamp to 2 in both editor `parseHTML` and renderer. `clampGridColumns(value)` is exported from `GridExtension.ts` for tests; the render-side has its own micro-helper to keep `render.ts` Tiptap-runtime-free.
107
+
108
+ ## File attachments (`attachFiles` button)
109
+
110
+ The `attachFiles` toolbar button uploads via the panel's registered `UploadAdapter`. Per-field setters:
111
+
112
+ ```ts
113
+ RichTextField.make('body')
114
+ .fileAttachmentsAcceptedFileTypes(['image/*', 'application/pdf'])
115
+ .fileAttachmentsMaxSize(5 * 1024 * 1024) // 5 MB cap
116
+ .fileAttachmentsDirectory('articles') // sub-directory hint
117
+ .fileAttachmentsVisibility('public') // adapter-dependent
118
+ .resizableImages() // drag-handle resize on images
119
+ ```
120
+
121
+ The upload route enforces `maxSize` server-side — a tampered client can't bypass. **Without an `UploadAdapter` registered on the panel, the `attachFiles` button silently hides.** Wire one with `Pilotiq.uploads({ adapter: localUpload({...}) })` (or any adapter from `@pilotiq/media`, S3, R2, etc.).
122
+
123
+ This auto-hide behavior is intentional — see [[feedback-pilotiq-panel-module-client-safe]]: the `attachFiles` button checks `RenderContext.hasUploadAdapter` at meta-resolve time. The field renders correctly with the button absent rather than showing a broken control.
124
+
125
+ ## Drag handle — three-step drop dance
126
+
127
+ The framework ships per-block drag handles in `extensions/DragHandleExtension.ts`. If you write a **custom block with external drag UX** (not the default per-block handle), the drop handler must do three things or you get the dreaded snap-back-to-origin bug:
128
+
129
+ 1. **`setNodeSelection(pos)`** on the editor view to select the drop target
130
+ 2. **Set `view.dragging = { slice, move: true }`** before the drop dispatches
131
+ 3. **`serializeForClipboard(view, slice)`** so ProseMirror has the serialized content to insert
132
+
133
+ Missing any one of the three causes the dragged node to disappear from its drop position and snap back to where it came from. The framework's built-in handle does all three correctly; custom drag implementations (e.g. an external palette dragging onto the canvas) must too. See [[feedback-tiptap-drag-handle-pm-dragging]] for the full repro.
134
+
135
+ ## Module identity — dedupe Tiptap peers
136
+
137
+ `@tiptap/core` and `@tiptap/pm` keep state on module-level singletons. **Multiple copies break the editor** (silent: `instanceof` checks fail, schema lookups miss, NodeViews don't mount). Add them to `resolve.dedupe` in your Vite config:
138
+
139
+ ```ts
140
+ // vite.config.ts
141
+ export default defineConfig({
142
+ resolve: {
143
+ dedupe: ['@tiptap/core', '@tiptap/pm', '@tiptap/react'],
144
+ },
145
+ // …
146
+ })
147
+ ```
148
+
149
+ This is unrelated to pilotiq's general `optimizeDeps.exclude: ['@pilotiq/pilotiq']` rule (see [[feedback-vite-optimizedeps-exclude]]) — both can be needed simultaneously.
150
+
151
+ ## Toolbar-driven slash entries
152
+
153
+ The slash menu's **Style** and **Format** groups derive from the *active* toolbar buttons. If you hide `textColor` from the toolbar via `.disableToolbarButtons(['textColor'])`, it also disappears from the slash menu. Same for alignment — if no `alignStart` / `alignCenter` / `alignEnd` button is active, the Format group is empty and collapses.
154
+
155
+ The **Insert** group is the inverse: it always shows the core insertable nodes regardless of toolbar config (paragraph, headings, lists, code block, blockquote, horizontal rule). Opt-in primitives (`details`, `grid`) only appear in the Insert group when their toolbar id is in the active config.
156
+
157
+ ## See also
158
+
159
+ - `custom-blocks.md` — `Block.make(...)` user blocks appear in the slash menu after the framework groups.
160
+ - `slash-menu-and-mentions.md` — how merge tags and mentions interact with the slash menu surface.
161
+ - [[feedback-tiptap-block-name-collision]] — the `'block'` name pitfall (also covered in `custom-blocks.md`).