@pilotiq/tiptap 0.1.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.
Files changed (130) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/Block.d.ts +47 -0
  4. package/dist/Block.d.ts.map +1 -0
  5. package/dist/Block.js +56 -0
  6. package/dist/Block.js.map +1 -0
  7. package/dist/MentionProvider.d.ts +97 -0
  8. package/dist/MentionProvider.d.ts.map +1 -0
  9. package/dist/MentionProvider.js +104 -0
  10. package/dist/MentionProvider.js.map +1 -0
  11. package/dist/RichTextField.d.ts +286 -0
  12. package/dist/RichTextField.d.ts.map +1 -0
  13. package/dist/RichTextField.js +369 -0
  14. package/dist/RichTextField.js.map +1 -0
  15. package/dist/extensions/BlockNodeExtension.d.ts +41 -0
  16. package/dist/extensions/BlockNodeExtension.d.ts.map +1 -0
  17. package/dist/extensions/BlockNodeExtension.js +103 -0
  18. package/dist/extensions/BlockNodeExtension.js.map +1 -0
  19. package/dist/extensions/DragHandleExtension.d.ts +19 -0
  20. package/dist/extensions/DragHandleExtension.d.ts.map +1 -0
  21. package/dist/extensions/DragHandleExtension.js +166 -0
  22. package/dist/extensions/DragHandleExtension.js.map +1 -0
  23. package/dist/extensions/GridExtension.d.ts +49 -0
  24. package/dist/extensions/GridExtension.d.ts.map +1 -0
  25. package/dist/extensions/GridExtension.js +105 -0
  26. package/dist/extensions/GridExtension.js.map +1 -0
  27. package/dist/extensions/MentionExtension.d.ts +71 -0
  28. package/dist/extensions/MentionExtension.d.ts.map +1 -0
  29. package/dist/extensions/MentionExtension.js +165 -0
  30. package/dist/extensions/MentionExtension.js.map +1 -0
  31. package/dist/extensions/MergeTagExtension.d.ts +24 -0
  32. package/dist/extensions/MergeTagExtension.d.ts.map +1 -0
  33. package/dist/extensions/MergeTagExtension.js +57 -0
  34. package/dist/extensions/MergeTagExtension.js.map +1 -0
  35. package/dist/extensions/SlashCommandExtension.d.ts +71 -0
  36. package/dist/extensions/SlashCommandExtension.d.ts.map +1 -0
  37. package/dist/extensions/SlashCommandExtension.js +244 -0
  38. package/dist/extensions/SlashCommandExtension.js.map +1 -0
  39. package/dist/extensions/TextSizeMarks.d.ts +33 -0
  40. package/dist/extensions/TextSizeMarks.d.ts.map +1 -0
  41. package/dist/extensions/TextSizeMarks.js +47 -0
  42. package/dist/extensions/TextSizeMarks.js.map +1 -0
  43. package/dist/index.d.ts +8 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +8 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/plugin.d.ts +18 -0
  48. package/dist/plugin.d.ts.map +1 -0
  49. package/dist/plugin.js +25 -0
  50. package/dist/plugin.js.map +1 -0
  51. package/dist/react/BlockNodeView.d.ts +19 -0
  52. package/dist/react/BlockNodeView.d.ts.map +1 -0
  53. package/dist/react/BlockNodeView.js +60 -0
  54. package/dist/react/BlockNodeView.js.map +1 -0
  55. package/dist/react/BlockSidePanel.d.ts +105 -0
  56. package/dist/react/BlockSidePanel.d.ts.map +1 -0
  57. package/dist/react/BlockSidePanel.js +339 -0
  58. package/dist/react/BlockSidePanel.js.map +1 -0
  59. package/dist/react/FloatingToolbar.d.ts +13 -0
  60. package/dist/react/FloatingToolbar.d.ts.map +1 -0
  61. package/dist/react/FloatingToolbar.js +113 -0
  62. package/dist/react/FloatingToolbar.js.map +1 -0
  63. package/dist/react/MentionMenu.d.ts +26 -0
  64. package/dist/react/MentionMenu.d.ts.map +1 -0
  65. package/dist/react/MentionMenu.js +64 -0
  66. package/dist/react/MentionMenu.js.map +1 -0
  67. package/dist/react/Palette.d.ts +26 -0
  68. package/dist/react/Palette.d.ts.map +1 -0
  69. package/dist/react/Palette.js +21 -0
  70. package/dist/react/Palette.js.map +1 -0
  71. package/dist/react/SlashMenu.d.ts +24 -0
  72. package/dist/react/SlashMenu.d.ts.map +1 -0
  73. package/dist/react/SlashMenu.js +74 -0
  74. package/dist/react/SlashMenu.js.map +1 -0
  75. package/dist/react/TableFloatingToolbar.d.ts +7 -0
  76. package/dist/react/TableFloatingToolbar.d.ts.map +1 -0
  77. package/dist/react/TableFloatingToolbar.js +108 -0
  78. package/dist/react/TableFloatingToolbar.js.map +1 -0
  79. package/dist/react/TiptapEditor.d.ts +20 -0
  80. package/dist/react/TiptapEditor.d.ts.map +1 -0
  81. package/dist/react/TiptapEditor.js +398 -0
  82. package/dist/react/TiptapEditor.js.map +1 -0
  83. package/dist/react/Toolbar.d.ts +45 -0
  84. package/dist/react/Toolbar.d.ts.map +1 -0
  85. package/dist/react/Toolbar.js +204 -0
  86. package/dist/react/Toolbar.js.map +1 -0
  87. package/dist/react/toolbarButtons.d.ts +36 -0
  88. package/dist/react/toolbarButtons.d.ts.map +1 -0
  89. package/dist/react/toolbarButtons.js +300 -0
  90. package/dist/react/toolbarButtons.js.map +1 -0
  91. package/dist/register.d.ts +20 -0
  92. package/dist/register.d.ts.map +1 -0
  93. package/dist/register.js +27 -0
  94. package/dist/register.js.map +1 -0
  95. package/dist/render.d.ts +89 -0
  96. package/dist/render.d.ts.map +1 -0
  97. package/dist/render.js +439 -0
  98. package/dist/render.js.map +1 -0
  99. package/package.json +92 -0
  100. package/src/Block.ts +75 -0
  101. package/src/MentionProvider.ts +153 -0
  102. package/src/RichTextField.test.ts +447 -0
  103. package/src/RichTextField.ts +508 -0
  104. package/src/extensions/BlockNodeExtension.ts +134 -0
  105. package/src/extensions/DragHandleExtension.ts +184 -0
  106. package/src/extensions/GridExtension.test.ts +31 -0
  107. package/src/extensions/GridExtension.ts +138 -0
  108. package/src/extensions/MentionExtension.ts +248 -0
  109. package/src/extensions/MergeTagExtension.ts +75 -0
  110. package/src/extensions/SlashCommandExtension.test.ts +147 -0
  111. package/src/extensions/SlashCommandExtension.ts +332 -0
  112. package/src/extensions/TextSizeMarks.ts +73 -0
  113. package/src/index.ts +28 -0
  114. package/src/plugin.test.ts +19 -0
  115. package/src/plugin.ts +26 -0
  116. package/src/react/BlockNodeView.tsx +99 -0
  117. package/src/react/BlockSidePanel.test.ts +412 -0
  118. package/src/react/BlockSidePanel.tsx +451 -0
  119. package/src/react/FloatingToolbar.tsx +304 -0
  120. package/src/react/MentionMenu.tsx +120 -0
  121. package/src/react/Palette.tsx +86 -0
  122. package/src/react/SlashMenu.tsx +129 -0
  123. package/src/react/TableFloatingToolbar.tsx +154 -0
  124. package/src/react/TiptapEditor.tsx +535 -0
  125. package/src/react/Toolbar.tsx +438 -0
  126. package/src/react/toolbarButtons.tsx +579 -0
  127. package/src/register.test.ts +14 -0
  128. package/src/register.ts +27 -0
  129. package/src/render.test.ts +745 -0
  130. package/src/render.ts +480 -0
@@ -0,0 +1,339 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
+ import { FormFields, parseFormDataToNested, clampPanelWidth as clampPanelWidthShared, useResizableWidth, } from '@pilotiq/pilotiq/react';
4
+ const PANEL_WIDTH_STORAGE_KEY = 'pilotiq.tiptap.sidePanel.width';
5
+ const PANEL_WIDTH_DEFAULT = 320;
6
+ const PANEL_WIDTH_MIN = 240;
7
+ const PANEL_WIDTH_MAX = 600;
8
+ // Keys that point at any tabbable / interactive element inside the panel.
9
+ // Same intent as Filament's focus-trap helper but kept inline — small one-off.
10
+ const FOCUSABLE_SELECTOR = [
11
+ 'a[href]',
12
+ 'button:not([disabled])',
13
+ 'input:not([disabled]):not([type="hidden"])',
14
+ 'select:not([disabled])',
15
+ 'textarea:not([disabled])',
16
+ '[tabindex]:not([tabindex="-1"])',
17
+ ].join(',');
18
+ export function BlockSidePanel({ editor, initialPos, blockType, blocks, onClose, }) {
19
+ const meta = blocks.find((b) => b.name === blockType);
20
+ // Live-tracked position of the block we're editing. Starts at the
21
+ // open-time position; every editor transaction maps it forward so the
22
+ // panel keeps writing to the same node even as the user types text
23
+ // elsewhere in the document.
24
+ const [pos, setPos] = useState(initialPos);
25
+ const posRef = useRef(initialPos);
26
+ // Prefilled values seed the form's `defaultValue`s. We re-read once
27
+ // when the panel opens (and on hard re-mount via key prop); ongoing
28
+ // edits don't snapshot the doc — the form's uncontrolled inputs hold
29
+ // their own state until the user closes the panel.
30
+ const initialValuesRef = useRef(pos !== null ? readBlockData(editor, pos) : {});
31
+ const asideRef = useRef(null);
32
+ const formRef = useRef(null);
33
+ // Width memory — survives panel close/reopen and full reload via
34
+ // localStorage. The shared `useResizableWidth` hook from
35
+ // `@pilotiq/pilotiq/react` handles the localStorage round-trip + drag
36
+ // pipeline; we just bind it to this panel's per-key bounds.
37
+ const { width, onResizeStart } = useResizableWidth({
38
+ storageKey: PANEL_WIDTH_STORAGE_KEY,
39
+ min: PANEL_WIDTH_MIN,
40
+ max: PANEL_WIDTH_MAX,
41
+ defaultWidth: PANEL_WIDTH_DEFAULT,
42
+ edge: 'left',
43
+ });
44
+ // Save focus on mount, focus the first focusable inside the panel,
45
+ // restore previous focus on unmount. Mount-only effect — re-mounting
46
+ // the panel for a different block (key={pos:blockType}) re-runs this.
47
+ useEffect(() => {
48
+ const previouslyFocused = (typeof document !== 'undefined'
49
+ ? document.activeElement
50
+ : null);
51
+ const aside = asideRef.current;
52
+ if (aside) {
53
+ const first = aside.querySelector(FOCUSABLE_SELECTOR);
54
+ first?.focus();
55
+ }
56
+ return () => {
57
+ // Try/catch — the previously focused element may have been removed
58
+ // (e.g. an editor selection refresh nuked the surrounding NodeView).
59
+ try {
60
+ previouslyFocused?.focus?.();
61
+ }
62
+ catch { /* noop */ }
63
+ };
64
+ }, []);
65
+ // ESC closes; Tab / Shift+Tab cycles within the panel. Bubble-phase
66
+ // listener — slash and mention menus' capture-phase ESC handlers fire
67
+ // first and stopPropagation, so ESC inside an open slash menu only
68
+ // closes the menu. ESC anywhere else (panel inputs, editor) closes
69
+ // the panel.
70
+ useEffect(() => {
71
+ const onKey = (e) => {
72
+ if (e.key === 'Escape') {
73
+ onClose();
74
+ e.preventDefault();
75
+ e.stopPropagation();
76
+ return;
77
+ }
78
+ if (e.key !== 'Tab')
79
+ return;
80
+ const aside = asideRef.current;
81
+ if (!aside)
82
+ return;
83
+ const active = document.activeElement;
84
+ if (!active || !aside.contains(active))
85
+ return;
86
+ const focusables = Array.from(aside.querySelectorAll(FOCUSABLE_SELECTOR)).filter((el) => !el.hasAttribute('disabled'));
87
+ if (focusables.length === 0)
88
+ return;
89
+ const first = focusables[0];
90
+ const last = focusables[focusables.length - 1];
91
+ if (e.shiftKey && active === first) {
92
+ e.preventDefault();
93
+ last.focus();
94
+ }
95
+ else if (!e.shiftKey && active === last) {
96
+ e.preventDefault();
97
+ first.focus();
98
+ }
99
+ };
100
+ document.addEventListener('keydown', onKey);
101
+ return () => document.removeEventListener('keydown', onKey);
102
+ }, [onClose]);
103
+ useEffect(() => {
104
+ if (pos === null)
105
+ return;
106
+ const handler = ({ transaction }) => {
107
+ const current = posRef.current;
108
+ if (current === null)
109
+ return;
110
+ const mapped = transaction.mapping.map(current);
111
+ // The block was deleted — close the panel.
112
+ const nodeNow = nodeAt(editor, mapped);
113
+ if (!nodeNow || nodeNow.type.name !== 'pilotiqBlock' || String(nodeNow.attrs['blockType'] ?? '') !== blockType) {
114
+ posRef.current = null;
115
+ setPos(null);
116
+ onClose();
117
+ return;
118
+ }
119
+ posRef.current = mapped;
120
+ setPos(mapped);
121
+ };
122
+ editor.on('transaction', handler);
123
+ return () => { editor.off('transaction', handler); };
124
+ }, [editor, blockType, pos, onClose]);
125
+ const writeBack = useCallback((nextValues) => {
126
+ const at = posRef.current;
127
+ if (at === null)
128
+ return;
129
+ // ProseMirror's `setNodeMarkup` lives on the transaction, not the
130
+ // ChainedCommands surface — go through `tr` directly. Pass `null`
131
+ // for the node-type arg to keep the existing type, just swap attrs.
132
+ const view = editor.view;
133
+ const state = editor.state;
134
+ const tr = state.tr.setNodeMarkup(at, null, { blockType, blockData: nextValues });
135
+ view.dispatch(tr);
136
+ }, [editor, blockType]);
137
+ const handleChange = useCallback(() => {
138
+ const formEl = formRef.current;
139
+ if (!formEl || !meta)
140
+ return;
141
+ // Snapshot the full form: nested arrays / objects materialize from
142
+ // dotted-path names (`items.0.title`), JSON-encoded hidden inputs
143
+ // (TagsInput / KeyValue / FileUpload-multi) sit as JSON strings,
144
+ // toggle / checkbox hidden inputs sit as `'true' | 'false'`. The
145
+ // coerce pass below normalizes those to canonical shapes.
146
+ const raw = parseFormDataToNested(new FormData(formEl));
147
+ const coerced = coerceBlockValues(raw, meta.schema);
148
+ writeBack(coerced);
149
+ }, [meta, writeBack]);
150
+ if (!meta || pos === null)
151
+ return null;
152
+ return (_jsxs("aside", { ref: asideRef, role: "dialog", "aria-label": `Edit ${meta.label}`, style: { width }, className: "absolute top-0 left-full ml-4 max-h-[calc(100vh-2rem)] overflow-y-auto rounded-lg border bg-background shadow-lg z-30", children: [_jsx("div", { role: "separator", "aria-orientation": "vertical", "aria-label": "Resize panel", onPointerDown: onResizeStart, className: "absolute left-0 top-0 h-full w-1 cursor-ew-resize hover:bg-border/80" }), _jsxs("header", { className: "sticky top-0 z-10 flex items-center justify-between gap-2 border-b bg-background px-3 py-2", children: [_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [meta.icon && _jsx("span", { "aria-hidden": "true", children: meta.icon }), _jsx("span", { className: "text-sm font-medium truncate", children: meta.label })] }), _jsx("button", { type: "button", onClick: onClose, "aria-label": "Close panel", className: "text-muted-foreground hover:text-foreground text-sm", children: "\u00D7" })] }), _jsx("form", { ref: formRef, onInput: handleChange, onChange: handleChange, onSubmit: (e) => { e.preventDefault(); }, className: "flex flex-col gap-3 px-3 py-3", children: _jsx(FormFields, { elements: meta.schema, values: initialValuesRef.current }) })] }));
153
+ }
154
+ /**
155
+ * Clamp + sanitize a candidate panel width against this panel's bounds
156
+ * (`[PANEL_WIDTH_MIN, PANEL_WIDTH_MAX]`, default `PANEL_WIDTH_DEFAULT`).
157
+ * Thin wrapper around the shared `clampPanelWidth` helper from
158
+ * `@pilotiq/pilotiq/react` — kept exported with the panel-specific
159
+ * defaults baked in so existing tests + downstream callers don't have
160
+ * to plumb the bounds themselves.
161
+ */
162
+ export function clampPanelWidth(value) {
163
+ return clampPanelWidthShared(value, {
164
+ min: PANEL_WIDTH_MIN,
165
+ max: PANEL_WIDTH_MAX,
166
+ defaultWidth: PANEL_WIDTH_DEFAULT,
167
+ });
168
+ }
169
+ /**
170
+ * Per-fieldType coerce of a nested values map (built by
171
+ * `parseFormDataToNested`) against the block's schema. Mirrors the
172
+ * server-side `coerceFormValues` at a small subset suitable for the
173
+ * side panel — we only run on top-level block fields plus the immediate
174
+ * children of any Repeater rows / Builder rows.data, which is all the
175
+ * V2 surface needs.
176
+ *
177
+ * Non-coerce passthrough for: text, textarea, select, radio, date,
178
+ * dateTime, email, color, toggleButtons, slug, hidden. (Their wire shape
179
+ * is already a plain string / array of strings.)
180
+ *
181
+ * Coerce branches:
182
+ * - `toggle` / `checkbox`: 'true' / 'false' string → boolean.
183
+ * - `number` / `slider`: parse to Number, null on empty, raw string
184
+ * passthrough on NaN (so a half-typed value isn't lost).
185
+ * - `tagsInput`: JSON-encoded string → string[].
186
+ * - `checkboxList`: JSON-encoded string OR array → string[].
187
+ * - `keyValue`: JSON-encoded string → Record<string, unknown>.
188
+ * - `fileUpload`: single → URL string passthrough; multiple →
189
+ * JSON-encoded string → string[].
190
+ * - `repeater`: each row in the array gets recursive coerce against
191
+ * the field's `template` (the inner field schema definition).
192
+ * - `builder`: each row's `data` gets recursive coerce against the
193
+ * block matching `row.type` from `field.blocks[]`. Unknown block
194
+ * types pass through verbatim — the renderer shows a placeholder
195
+ * and the data round-trips intact across config rollbacks.
196
+ *
197
+ * Exported for unit tests. Pure — no React, no DOM, no editor.
198
+ */
199
+ export function coerceBlockValues(raw, schema) {
200
+ const out = { ...raw };
201
+ for (const field of schema) {
202
+ const name = String(field['name'] ?? '');
203
+ if (!name)
204
+ continue;
205
+ const ft = String(field['fieldType'] ?? 'text');
206
+ const value = out[name];
207
+ out[name] = coerceField(value, ft, field);
208
+ }
209
+ return out;
210
+ }
211
+ function coerceField(value, ft, field) {
212
+ switch (ft) {
213
+ case 'toggle':
214
+ case 'checkbox':
215
+ return value === 'true' || value === true;
216
+ case 'number':
217
+ case 'slider':
218
+ return coerceNumber(value);
219
+ case 'tagsInput':
220
+ return parseJsonArray(value);
221
+ case 'checkboxList':
222
+ return parseJsonArray(value);
223
+ case 'keyValue':
224
+ return parseJsonObject(value);
225
+ case 'fileUpload': {
226
+ const multiple = Boolean(field['multiple']);
227
+ if (multiple)
228
+ return parseJsonArray(value);
229
+ return typeof value === 'string' ? value : '';
230
+ }
231
+ case 'repeater': {
232
+ if (!Array.isArray(value))
233
+ return [];
234
+ const template = field['template'] ?? [];
235
+ return value.map((row) => {
236
+ if (!row || typeof row !== 'object')
237
+ return {};
238
+ return coerceBlockValues(row, template);
239
+ });
240
+ }
241
+ case 'builder': {
242
+ if (!Array.isArray(value))
243
+ return [];
244
+ const blockMetas = field['blocks'] ?? [];
245
+ return value.map((row) => {
246
+ if (!row || typeof row !== 'object')
247
+ return { type: '', data: {} };
248
+ const r = row;
249
+ const type = String(r['type'] ?? '');
250
+ const data = r['data'] ?? {};
251
+ const block = blockMetas.find((b) => String(b['name'] ?? '') === type);
252
+ if (!block)
253
+ return { type, data };
254
+ const tpl = block['template'] ?? [];
255
+ return { type, data: coerceBlockValues(data, tpl) };
256
+ });
257
+ }
258
+ default:
259
+ return value === undefined ? '' : value;
260
+ }
261
+ }
262
+ function coerceNumber(value) {
263
+ if (value === '' || value === null || value === undefined)
264
+ return null;
265
+ if (typeof value === 'number')
266
+ return value;
267
+ const raw = String(value);
268
+ if (raw === '')
269
+ return null;
270
+ const n = Number(raw);
271
+ return Number.isNaN(n) ? raw : n;
272
+ }
273
+ function parseJsonArray(value) {
274
+ if (Array.isArray(value))
275
+ return value;
276
+ if (typeof value !== 'string' || value === '')
277
+ return [];
278
+ try {
279
+ const parsed = JSON.parse(value);
280
+ return Array.isArray(parsed) ? parsed : [];
281
+ }
282
+ catch {
283
+ return [];
284
+ }
285
+ }
286
+ function parseJsonObject(value) {
287
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
288
+ return value;
289
+ }
290
+ if (typeof value !== 'string' || value === '')
291
+ return {};
292
+ try {
293
+ const parsed = JSON.parse(value);
294
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
295
+ return parsed;
296
+ }
297
+ }
298
+ catch { /* fall through */ }
299
+ return {};
300
+ }
301
+ /**
302
+ * Read the resolved field value for a given input event target. Kept
303
+ * for back-compat — V1 used this in the per-event handler. V2 reads
304
+ * the entire form via `FormData` instead, but this helper still maps
305
+ * cleanly onto a single-input read for testing and is exported.
306
+ *
307
+ * String passthrough for the common case; explicit coercion for
308
+ * booleans and numerics so the round-trip into the node attrs preserves
309
+ * shape.
310
+ */
311
+ export function readBlockFieldValue(target, fieldMeta) {
312
+ const ft = String(fieldMeta.fieldType ?? 'text');
313
+ if (ft === 'toggle' || ft === 'checkbox') {
314
+ return target.checked === true;
315
+ }
316
+ if (ft === 'number' || ft === 'slider') {
317
+ const raw = target.value;
318
+ if (raw === '')
319
+ return null;
320
+ const n = Number(raw);
321
+ return Number.isNaN(n) ? raw : n;
322
+ }
323
+ return target.value;
324
+ }
325
+ function readBlockData(editor, pos) {
326
+ const node = nodeAt(editor, pos);
327
+ if (!node)
328
+ return {};
329
+ return node.attrs['blockData'] ?? {};
330
+ }
331
+ function nodeAt(editor, pos) {
332
+ try {
333
+ return editor.state.doc.nodeAt(pos);
334
+ }
335
+ catch {
336
+ return null;
337
+ }
338
+ }
339
+ //# sourceMappingURL=BlockSidePanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockSidePanel.js","sourceRoot":"","sources":["../../src/react/BlockSidePanel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Editor } from '@tiptap/core';
2
+ interface FloatingToolbarProps {
3
+ editor: Editor;
4
+ }
5
+ /**
6
+ * Selection-based formatting toolbar. Visible whenever the editor has a
7
+ * non-empty range selection inside text content. Inline marks (B/I/S/Code)
8
+ * are grouped together; Link sits after a separator since it's a different
9
+ * kind of action.
10
+ */
11
+ export declare function FloatingToolbar({ editor }: FloatingToolbarProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
13
+ //# sourceMappingURL=FloatingToolbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FloatingToolbar.d.ts","sourceRoot":"","sources":["../../src/react/FloatingToolbar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAI1C,UAAU,oBAAoB;IAC5B,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE,oBAAoB,2CAwH/D"}
@@ -0,0 +1,113 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { Tooltip } from '@base-ui/react/tooltip';
4
+ import { Dialog } from '@base-ui/react/dialog';
5
+ /**
6
+ * Selection-based formatting toolbar. Visible whenever the editor has a
7
+ * non-empty range selection inside text content. Inline marks (B/I/S/Code)
8
+ * are grouped together; Link sits after a separator since it's a different
9
+ * kind of action.
10
+ */
11
+ export function FloatingToolbar({ editor }) {
12
+ const [pos, setPos] = useState(null);
13
+ const [linkOpen, setLinkOpen] = useState(false);
14
+ const [linkUrl, setLinkUrl] = useState('');
15
+ useEffect(() => {
16
+ const update = () => {
17
+ const { from, to, empty } = editor.state.selection;
18
+ if (empty) {
19
+ setPos(null);
20
+ return;
21
+ }
22
+ // Don't show on full-block selections (e.g. clicking a custom block).
23
+ const slice = editor.state.doc.slice(from, to);
24
+ if (slice.content.childCount === 0) {
25
+ setPos(null);
26
+ return;
27
+ }
28
+ const start = editor.view.coordsAtPos(from);
29
+ const end = editor.view.coordsAtPos(to);
30
+ // Viewport-relative — pair with `position: fixed` below. The wrapper
31
+ // around <EditorContent> is `position: relative`, so an absolute toolbar
32
+ // would be positioned relative to it instead of the viewport.
33
+ // Lift the toolbar above the selection. The value is the toolbar's full
34
+ // height plus a small breathing gap; bump if the toolbar grows.
35
+ const top = Math.min(start.top, end.top) - 48;
36
+ const left = (start.left + end.right) / 2;
37
+ setPos({ top, left });
38
+ };
39
+ const close = () => setPos(null);
40
+ editor.on('selectionUpdate', update);
41
+ editor.on('blur', close);
42
+ // Keep the toolbar pinned to the selection when the page or any scroll
43
+ // ancestor scrolls (capture phase catches inner scrollers too).
44
+ window.addEventListener('scroll', update, true);
45
+ window.addEventListener('resize', update);
46
+ return () => {
47
+ editor.off('selectionUpdate', update);
48
+ editor.off('blur', close);
49
+ window.removeEventListener('scroll', update, true);
50
+ window.removeEventListener('resize', update);
51
+ };
52
+ }, [editor]);
53
+ const openLinkDialog = () => {
54
+ const previousUrl = editor.getAttributes('link')['href'];
55
+ setLinkUrl(previousUrl ?? '');
56
+ setLinkOpen(true);
57
+ };
58
+ const applyLink = () => {
59
+ setLinkOpen(false);
60
+ const trimmed = linkUrl.trim();
61
+ if (trimmed === '') {
62
+ editor.chain().focus().extendMarkRange('link').unsetLink().run();
63
+ return;
64
+ }
65
+ editor.chain().focus().extendMarkRange('link').setLink({ href: trimmed }).run();
66
+ };
67
+ const removeLink = () => {
68
+ setLinkOpen(false);
69
+ editor.chain().focus().extendMarkRange('link').unsetLink().run();
70
+ };
71
+ const mod = isMac() ? '⌘' : 'Ctrl+';
72
+ const isLink = editor.isActive('link');
73
+ return (_jsxs(_Fragment, { children: [pos && (_jsx(Tooltip.Provider, { delay: 400, children: _jsxs("div", { className: "fixed z-40 flex items-center gap-0.5 rounded-md border bg-popover px-1 py-1 text-popover-foreground shadow-md", style: { top: pos.top, left: pos.left, transform: 'translateX(-50%)' }, children: [_jsx(ToolbarButton, { label: `Bold (${mod}B)`, active: editor.isActive('bold'), onClick: () => editor.chain().focus().toggleBold().run(), children: _jsx(BoldIcon, {}) }), _jsx(ToolbarButton, { label: `Italic (${mod}I)`, active: editor.isActive('italic'), onClick: () => editor.chain().focus().toggleItalic().run(), children: _jsx(ItalicIcon, {}) }), _jsx(ToolbarButton, { label: `Strikethrough (${mod}⇧X)`, active: editor.isActive('strike'), onClick: () => editor.chain().focus().toggleStrike().run(), children: _jsx(StrikeIcon, {}) }), _jsx(ToolbarButton, { label: `Code (${mod}E)`, active: editor.isActive('code'), onClick: () => editor.chain().focus().toggleCode().run(), children: _jsx(CodeIcon, {}) }), _jsx("span", { "aria-hidden": true, className: "mx-1 h-5 w-px shrink-0 bg-border" }), _jsx(ToolbarButton, { label: isLink ? 'Edit link' : 'Add link', active: isLink, onClick: openLinkDialog, children: _jsx(LinkIcon, {}) })] }) })), _jsx(LinkDialog, { open: linkOpen, onOpenChange: setLinkOpen, url: linkUrl, onUrlChange: setLinkUrl, onApply: applyLink, onRemove: isLink ? removeLink : null, isEdit: isLink })] }));
74
+ }
75
+ function ToolbarButton({ label, active, onClick, children, }) {
76
+ return (_jsxs(Tooltip.Root, { children: [_jsx(Tooltip.Trigger, { render: (props) => (_jsx("button", { ...props, type: "button",
77
+ // mousedown + preventDefault keeps editor focus so the selection
78
+ // (and therefore the toolbar) survives the click.
79
+ onMouseDown: (e) => { e.preventDefault(); onClick(); }, className: `inline-flex h-7 w-7 items-center justify-center rounded text-foreground transition-colors ${active ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/60'}`, "aria-label": label, "aria-pressed": active, children: children })) }), _jsx(Tooltip.Portal, { children: _jsx(Tooltip.Positioner, { side: "top", sideOffset: 6, className: "isolate z-50", children: _jsx(Tooltip.Popup, { className: "rounded-md bg-foreground px-2 py-1 text-xs text-background shadow-md data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", children: label }) }) })] }));
80
+ }
81
+ function LinkDialog({ open, onOpenChange, url, onUrlChange, onApply, onRemove, isEdit, }) {
82
+ return (_jsx(Dialog.Root, { open: open, onOpenChange: onOpenChange, children: _jsxs(Dialog.Portal, { children: [_jsx(Dialog.Backdrop, { className: "fixed inset-0 z-50 bg-black/50 transition-opacity duration-150 data-[starting-style]:opacity-0 data-[ending-style]:opacity-0" }), _jsxs(Dialog.Popup, { className: "fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] sm:max-w-md translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg transition-[opacity,transform] duration-150 data-[starting-style]:scale-95 data-[starting-style]:opacity-0 data-[ending-style]:scale-95 data-[ending-style]:opacity-0", children: [_jsx(Dialog.Title, { className: "text-lg leading-none font-semibold", children: isEdit ? 'Edit link' : 'Add link' }), _jsx("input", { type: "url", value: url, onChange: (e) => onUrlChange(e.target.value), onKeyDown: (e) => {
83
+ if (e.key === 'Enter') {
84
+ e.preventDefault();
85
+ onApply();
86
+ }
87
+ }, placeholder: "https://example.com", autoFocus: true, className: "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" }), _jsxs("div", { className: "flex flex-row-reverse items-center gap-2", children: [_jsx("button", { type: "button", onClick: onApply, className: "inline-flex h-9 items-center justify-center rounded-md bg-primary px-3 text-sm font-medium text-primary-foreground hover:bg-primary/90", children: isEdit ? 'Update' : 'Add' }), _jsx("button", { type: "button", onClick: () => onOpenChange(false), className: "inline-flex h-9 items-center justify-center rounded-md border border-input bg-background px-3 text-sm font-medium hover:bg-accent hover:text-accent-foreground", children: "Cancel" }), onRemove && (_jsx("button", { type: "button", onClick: onRemove, className: "me-auto inline-flex h-9 items-center justify-center rounded-md px-3 text-sm font-medium text-destructive hover:bg-destructive/10", children: "Remove link" }))] })] })] }) }));
88
+ }
89
+ function isMac() {
90
+ if (typeof navigator === 'undefined')
91
+ return false;
92
+ // navigator.platform is deprecated but still the most reliable signal here.
93
+ return /Mac|iPhone|iPad|iPod/.test(navigator.platform);
94
+ }
95
+ // Inline SVG icons (lucide.dev paths). Kept inline so this package doesn't
96
+ // pull `lucide-react` as a peer dep — the rest of @pilotiq/tiptap is already
97
+ // inline-SVG (DragHandle).
98
+ function BoldIcon() {
99
+ return (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.25", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M6 12h9a4 4 0 0 1 0 8H6Z" }), _jsx("path", { d: "M6 4h7a4 4 0 0 1 0 8H6Z" })] }));
100
+ }
101
+ function ItalicIcon() {
102
+ return (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("line", { x1: "19", y1: "4", x2: "10", y2: "4" }), _jsx("line", { x1: "14", y1: "20", x2: "5", y2: "20" }), _jsx("line", { x1: "15", y1: "4", x2: "9", y2: "20" })] }));
103
+ }
104
+ function StrikeIcon() {
105
+ return (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M16 4H9a3 3 0 0 0-2.83 4" }), _jsx("path", { d: "M14 12a4 4 0 0 1 0 8H6" }), _jsx("line", { x1: "4", y1: "12", x2: "20", y2: "12" })] }));
106
+ }
107
+ function CodeIcon() {
108
+ return (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("polyline", { points: "16 18 22 12 16 6" }), _jsx("polyline", { points: "8 6 2 12 8 18" })] }));
109
+ }
110
+ function LinkIcon() {
111
+ return (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }), _jsx("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })] }));
112
+ }
113
+ //# sourceMappingURL=FloatingToolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FloatingToolbar.js","sourceRoot":"","sources":["../../src/react/FloatingToolbar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { MentionItem } from '../MentionProvider.js';
2
+ /**
3
+ * Mutable ref the document-level keydown listener in `TiptapEditor` reads.
4
+ * `MentionMenu` installs its keyboard handler on mount, clears on unmount —
5
+ * same protocol as `SlashMenu`'s `keyHandlerRef`.
6
+ */
7
+ export type MentionKeyHandlerRef = {
8
+ current: ((event: KeyboardEvent) => boolean) | null;
9
+ };
10
+ interface MentionMenuProps {
11
+ trigger: string;
12
+ items: MentionItem[];
13
+ command: (item: MentionItem) => void;
14
+ keyHandlerRef: MentionKeyHandlerRef;
15
+ }
16
+ /**
17
+ * Floating list of mention items. Mirrors `SlashMenu` but uses the lighter
18
+ * `MentionItem` shape (no command thunk per item — the `command` prop is
19
+ * pre-curried by the Suggestion plugin).
20
+ *
21
+ * Optional `group` strings on items render as section headings; items
22
+ * without a group land under "Suggestions".
23
+ */
24
+ export declare function MentionMenu({ trigger, items, command, keyHandlerRef }: MentionMenuProps): import("react/jsx-runtime").JSX.Element;
25
+ export {};
26
+ //# sourceMappingURL=MentionMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MentionMenu.d.ts","sourceRoot":"","sources":["../../src/react/MentionMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG;IAAE,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,CAAA;AAE1F,UAAU,gBAAgB;IACxB,OAAO,EAAQ,MAAM,CAAA;IACrB,KAAK,EAAU,WAAW,EAAE,CAAA;IAC5B,OAAO,EAAQ,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAA;IAC1C,aAAa,EAAE,oBAAoB,CAAA;CACpC;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,gBAAgB,2CAmFvF"}
@@ -0,0 +1,64 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState } from 'react';
3
+ /**
4
+ * Floating list of mention items. Mirrors `SlashMenu` but uses the lighter
5
+ * `MentionItem` shape (no command thunk per item — the `command` prop is
6
+ * pre-curried by the Suggestion plugin).
7
+ *
8
+ * Optional `group` strings on items render as section headings; items
9
+ * without a group land under "Suggestions".
10
+ */
11
+ export function MentionMenu({ trigger, items, command, keyHandlerRef }) {
12
+ const [active, setActive] = useState(0);
13
+ const containerRef = useRef(null);
14
+ const grouped = useMemo(() => groupBy(items, (it) => it.group ?? 'Suggestions'), [items]);
15
+ const renderOrder = useMemo(() => Array.from(grouped.values()).flat(), [grouped]);
16
+ useEffect(() => { setActive(0); }, [renderOrder]);
17
+ useEffect(() => {
18
+ const el = containerRef.current?.querySelector(`[data-index="${active}"]`);
19
+ el?.scrollIntoView({ block: 'nearest' });
20
+ }, [active]);
21
+ useEffect(() => {
22
+ keyHandlerRef.current = (event) => {
23
+ const len = renderOrder.length;
24
+ if (event.key === 'ArrowDown') {
25
+ setActive((i) => (len === 0 ? 0 : (i + 1) % len));
26
+ return true;
27
+ }
28
+ if (event.key === 'ArrowUp') {
29
+ setActive((i) => (len === 0 ? 0 : (i - 1 + len) % len));
30
+ return true;
31
+ }
32
+ if (event.key === 'Enter') {
33
+ const item = renderOrder[active];
34
+ if (item)
35
+ command(item);
36
+ return true;
37
+ }
38
+ return false;
39
+ };
40
+ return () => { keyHandlerRef.current = null; };
41
+ }, [renderOrder, active, command, keyHandlerRef]);
42
+ if (renderOrder.length === 0) {
43
+ return (_jsx("div", { className: "px-3 py-2 text-xs text-muted-foreground", children: "No matches" }));
44
+ }
45
+ let runningIndex = 0;
46
+ return (_jsx("div", { ref: containerRef, className: "max-h-72 w-64 overflow-y-auto p-1 text-sm", children: Array.from(grouped.entries()).map(([groupName, groupItems]) => (_jsxs("div", { children: [_jsx("div", { className: "px-2 pt-2 pb-1 text-[0.7rem] font-medium uppercase tracking-wide text-muted-foreground", children: groupName }), groupItems.map((item) => {
47
+ const idx = runningIndex++;
48
+ const isActive = idx === active;
49
+ return (_jsxs("button", { "data-index": idx, type: "button", onMouseDown: (e) => { e.preventDefault(); command(item); }, onMouseEnter: () => setActive(idx), className: `flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left ${isActive ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/60'}`, children: [_jsx("span", { className: "flex size-6 items-center justify-center rounded border bg-background text-xs", children: trigger }), _jsx("span", { className: "flex-1", children: item.label }), _jsx("span", { className: "text-xs text-muted-foreground", children: item.id })] }, item.id));
50
+ })] }, groupName))) }));
51
+ }
52
+ function groupBy(items, key) {
53
+ const out = new Map();
54
+ for (const item of items) {
55
+ const k = key(item);
56
+ const list = out.get(k);
57
+ if (list)
58
+ list.push(item);
59
+ else
60
+ out.set(k, [item]);
61
+ }
62
+ return out;
63
+ }
64
+ //# sourceMappingURL=MentionMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MentionMenu.js","sourceRoot":"","sources":["../../src/react/MentionMenu.tsx"],"names":[],"mappings":"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"}