@rtif-sdk/web 1.4.0 → 1.5.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 (44) hide show
  1. package/dist/block-drag-handler.d.ts +26 -0
  2. package/dist/block-drag-handler.d.ts.map +1 -1
  3. package/dist/block-drag-handler.js +33 -23
  4. package/dist/block-drag-handler.js.map +1 -1
  5. package/dist/block-gutter.d.ts +81 -0
  6. package/dist/block-gutter.d.ts.map +1 -0
  7. package/dist/block-gutter.js +331 -0
  8. package/dist/block-gutter.js.map +1 -0
  9. package/dist/drop-indicator.d.ts.map +1 -1
  10. package/dist/drop-indicator.js +8 -34
  11. package/dist/drop-indicator.js.map +1 -1
  12. package/dist/editor.d.ts.map +1 -1
  13. package/dist/editor.js +23 -11
  14. package/dist/editor.js.map +1 -1
  15. package/dist/floating-toolbar.d.ts.map +1 -1
  16. package/dist/floating-toolbar.js +4 -7
  17. package/dist/floating-toolbar.js.map +1 -1
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/link-popover.d.ts.map +1 -1
  23. package/dist/link-popover.js +2 -43
  24. package/dist/link-popover.js.map +1 -1
  25. package/dist/renderer.d.ts.map +1 -1
  26. package/dist/renderer.js +27 -5
  27. package/dist/renderer.js.map +1 -1
  28. package/dist/selection-sync.d.ts.map +1 -1
  29. package/dist/selection-sync.js +20 -3
  30. package/dist/selection-sync.js.map +1 -1
  31. package/dist/types.d.ts +6 -0
  32. package/dist/types.d.ts.map +1 -1
  33. package/package.json +8 -4
  34. package/styles/all.css +20 -0
  35. package/styles/base.css +33 -0
  36. package/styles/block-gutter.css +76 -0
  37. package/styles/blocks.css +199 -0
  38. package/styles/drop-indicator.css +37 -0
  39. package/styles/floating-toolbar.css +51 -0
  40. package/styles/link-popover.css +64 -0
  41. package/styles/marks.css +27 -0
  42. package/styles/mention.css +17 -0
  43. package/styles/pickers.css +317 -0
  44. package/styles/toolbar.css +151 -0
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Block gutter toolbar — a Notion-style hover-revealed toolbar to the left
3
+ * of blocks with a "+" button (add block below) and a drag handle (reorder).
4
+ *
5
+ * The gutter owns hover detection and DOM elements. Drag-and-drop logic is
6
+ * delegated to {@link BlockDragHandler} in external handle mode.
7
+ *
8
+ * @module
9
+ */
10
+ import { blockTextLength } from '@rtif-sdk/core';
11
+ import { BlockDragHandler, findBlockElement } from './block-drag-handler.js';
12
+ import { getBlockStartOffset } from './plugins/block-utils.js';
13
+ // ---------------------------------------------------------------------------
14
+ // CSS class names
15
+ // ---------------------------------------------------------------------------
16
+ const CSS_GUTTER = 'rtif-block-gutter';
17
+ const CSS_ADD = 'rtif-gutter-add';
18
+ const CSS_HANDLE = 'rtif-drag-handle';
19
+ const CSS_HIDDEN = 'rtif-hidden';
20
+ // ---------------------------------------------------------------------------
21
+ // Factory
22
+ // ---------------------------------------------------------------------------
23
+ /**
24
+ * Create a block gutter toolbar.
25
+ *
26
+ * The gutter appears on hover or when the keyboard cursor enters a block.
27
+ * It provides a "+" button to add a new block below and a drag handle
28
+ * for block reordering.
29
+ *
30
+ * @param deps - Injected dependencies
31
+ * @returns A handle to attach/detach the gutter
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const gutter = createBlockGutter({
36
+ * root: editorRoot,
37
+ * engine,
38
+ * isReadOnly: () => false,
39
+ * getBlockElementMap: () => blockElementMap,
40
+ * generateBlockId: () => generateId(),
41
+ * focusAtOffset: (offset) => { ... },
42
+ * });
43
+ * gutter.attach();
44
+ * ```
45
+ */
46
+ export function createBlockGutter(deps) {
47
+ let attached = false;
48
+ // Active block state
49
+ let activeBlockId = null;
50
+ let mouseIsActive = false;
51
+ let isDragging = false;
52
+ let hideTimeout = null;
53
+ let rafId = null;
54
+ // -------------------------------------------------------------------------
55
+ // DOM creation
56
+ // -------------------------------------------------------------------------
57
+ const gutterEl = document.createElement('div');
58
+ gutterEl.className = CSS_GUTTER;
59
+ gutterEl.setAttribute('role', 'toolbar');
60
+ gutterEl.setAttribute('aria-label', 'Block actions');
61
+ gutterEl.setAttribute('contenteditable', 'false');
62
+ gutterEl.classList.add(CSS_HIDDEN);
63
+ // + button
64
+ const addButton = document.createElement('button');
65
+ addButton.className = CSS_ADD;
66
+ addButton.type = 'button';
67
+ addButton.setAttribute('aria-label', 'Add block below');
68
+ addButton.textContent = '+';
69
+ // Drag handle
70
+ const dragHandle = document.createElement('div');
71
+ dragHandle.className = CSS_HANDLE;
72
+ dragHandle.setAttribute('draggable', 'true');
73
+ dragHandle.setAttribute('role', 'button');
74
+ dragHandle.setAttribute('tabindex', '-1');
75
+ dragHandle.setAttribute('aria-label', 'Drag to reorder');
76
+ dragHandle.textContent = '\u2807'; // BRAILLE PATTERN DOTS-123
77
+ gutterEl.appendChild(addButton);
78
+ gutterEl.appendChild(dragHandle);
79
+ // -------------------------------------------------------------------------
80
+ // BlockDragHandler in external handle mode
81
+ // -------------------------------------------------------------------------
82
+ const blockDragHandler = new BlockDragHandler({
83
+ root: deps.root,
84
+ getDoc: () => deps.engine.state.doc,
85
+ dispatch: (ops) => deps.engine.dispatch(ops),
86
+ isReadOnly: deps.isReadOnly,
87
+ getBlockElementMap: () => deps.getBlockElementMap(),
88
+ externalHandleMode: true,
89
+ getHandleEl: () => dragHandle,
90
+ });
91
+ // -------------------------------------------------------------------------
92
+ // Gutter positioning
93
+ // -------------------------------------------------------------------------
94
+ function showGutter(blockEl) {
95
+ if (deps.isReadOnly())
96
+ return;
97
+ if (isDragging)
98
+ return;
99
+ const blockId = blockEl.getAttribute('data-rtif-block');
100
+ if (!blockId)
101
+ return;
102
+ activeBlockId = blockId;
103
+ dragHandle.setAttribute('data-drag-block-id', blockId);
104
+ const rootRect = deps.root.getBoundingClientRect();
105
+ const blockRect = blockEl.getBoundingClientRect();
106
+ // Account for scroll offset: getBoundingClientRect is viewport-relative,
107
+ // but absolute positioning is relative to the offsetParent (root).
108
+ // When the root is scrolled, we need to add scrollTop to compensate.
109
+ gutterEl.style.top = `${blockRect.top - rootRect.top + deps.root.scrollTop}px`;
110
+ gutterEl.style.height = `${blockRect.height}px`;
111
+ gutterEl.classList.remove(CSS_HIDDEN);
112
+ }
113
+ function hideGutter() {
114
+ gutterEl.classList.add(CSS_HIDDEN);
115
+ activeBlockId = null;
116
+ }
117
+ function clearHideTimeout() {
118
+ if (hideTimeout !== null) {
119
+ clearTimeout(hideTimeout);
120
+ hideTimeout = null;
121
+ }
122
+ }
123
+ function scheduleHide() {
124
+ clearHideTimeout();
125
+ hideTimeout = setTimeout(() => {
126
+ hideTimeout = null;
127
+ hideGutter();
128
+ mouseIsActive = false;
129
+ }, 150);
130
+ }
131
+ // -------------------------------------------------------------------------
132
+ // Hover detection (event delegation on root)
133
+ // -------------------------------------------------------------------------
134
+ function onMouseOver(e) {
135
+ const blockEl = findBlockElement(e.target, deps.root);
136
+ if (blockEl) {
137
+ clearHideTimeout();
138
+ mouseIsActive = true;
139
+ showGutter(blockEl);
140
+ }
141
+ }
142
+ function onMouseOut(e) {
143
+ const relatedTarget = e.relatedTarget;
144
+ if (relatedTarget) {
145
+ // Moving to gutter → grace
146
+ if (gutterEl.contains(relatedTarget))
147
+ return;
148
+ // Moving to another block → will trigger mouseover
149
+ if (deps.root.contains(relatedTarget)) {
150
+ const blockEl = findBlockElement(relatedTarget, deps.root);
151
+ if (blockEl)
152
+ return;
153
+ }
154
+ }
155
+ scheduleHide();
156
+ }
157
+ function onGutterMouseEnter() {
158
+ clearHideTimeout();
159
+ }
160
+ function onGutterMouseLeave(e) {
161
+ const relatedTarget = e.relatedTarget;
162
+ if (relatedTarget && deps.root.contains(relatedTarget)) {
163
+ const blockEl = findBlockElement(relatedTarget, deps.root);
164
+ if (blockEl)
165
+ return; // Moving back to a block
166
+ }
167
+ scheduleHide();
168
+ }
169
+ // -------------------------------------------------------------------------
170
+ // Drag state tracking — hide gutter during active drag
171
+ // -------------------------------------------------------------------------
172
+ function onDragStart() {
173
+ isDragging = true;
174
+ hideGutter();
175
+ }
176
+ function onDragEnd() {
177
+ isDragging = false;
178
+ }
179
+ // -------------------------------------------------------------------------
180
+ // Keyboard focus tracking (rAF-throttled)
181
+ // -------------------------------------------------------------------------
182
+ let prevFocusBlockId = null;
183
+ let unsubChange = null;
184
+ let unsubSelection = null;
185
+ function updateGutterForSelection() {
186
+ if (deps.isReadOnly())
187
+ return;
188
+ // Mouse hover takes priority
189
+ if (mouseIsActive)
190
+ return;
191
+ if (isDragging)
192
+ return;
193
+ const { selection, doc } = deps.engine.state;
194
+ const offset = selection.focus.offset;
195
+ try {
196
+ const block = deps.engine.getBlockAtOffset(offset);
197
+ if (block.id === prevFocusBlockId)
198
+ return;
199
+ prevFocusBlockId = block.id;
200
+ const blockEl = deps.getBlockElementMap().get(block.id);
201
+ if (!blockEl)
202
+ return; // Virtualized away
203
+ showGutter(blockEl);
204
+ }
205
+ catch {
206
+ // Offset out of range — hide
207
+ hideGutter();
208
+ }
209
+ }
210
+ function scheduleSelectionUpdate() {
211
+ if (rafId !== null)
212
+ return; // Already scheduled
213
+ rafId = requestAnimationFrame(() => {
214
+ rafId = null;
215
+ updateGutterForSelection();
216
+ });
217
+ }
218
+ // -------------------------------------------------------------------------
219
+ // + button handler
220
+ // -------------------------------------------------------------------------
221
+ function onAddMouseDown(e) {
222
+ e.preventDefault(); // Preserve editor focus
223
+ }
224
+ function onAddClick() {
225
+ if (deps.isReadOnly())
226
+ return;
227
+ if (!activeBlockId)
228
+ return;
229
+ const doc = deps.engine.state.doc;
230
+ const block = doc.blocks.find((b) => b.id === activeBlockId);
231
+ if (!block)
232
+ return;
233
+ const blockStart = getBlockStartOffset(doc, activeBlockId);
234
+ const blockLen = blockTextLength(block);
235
+ const splitOffset = blockStart + blockLen;
236
+ const newBlockId = deps.generateBlockId();
237
+ deps.engine.dispatch({
238
+ type: 'split_block',
239
+ offset: splitOffset,
240
+ newBlockId,
241
+ });
242
+ // Cursor at start of new block (splitOffset + 1 for virtual \n)
243
+ deps.focusAtOffset(splitOffset + 1);
244
+ }
245
+ // Drag handle also needs focus preservation
246
+ function onDragHandleMouseDown(e) {
247
+ e.preventDefault();
248
+ }
249
+ // -------------------------------------------------------------------------
250
+ // Blur handler
251
+ // -------------------------------------------------------------------------
252
+ function onBlur() {
253
+ clearHideTimeout();
254
+ hideGutter();
255
+ mouseIsActive = false;
256
+ prevFocusBlockId = null;
257
+ }
258
+ // -------------------------------------------------------------------------
259
+ // Lifecycle
260
+ // -------------------------------------------------------------------------
261
+ return {
262
+ attach() {
263
+ if (attached)
264
+ return;
265
+ attached = true;
266
+ // Append gutter to root
267
+ deps.root.appendChild(gutterEl);
268
+ // Hover listeners
269
+ deps.root.addEventListener('mouseover', onMouseOver);
270
+ deps.root.addEventListener('mouseout', onMouseOut);
271
+ gutterEl.addEventListener('mouseenter', onGutterMouseEnter);
272
+ gutterEl.addEventListener('mouseleave', onGutterMouseLeave);
273
+ // Button listeners
274
+ addButton.addEventListener('mousedown', onAddMouseDown);
275
+ addButton.addEventListener('click', onAddClick);
276
+ dragHandle.addEventListener('mousedown', onDragHandleMouseDown);
277
+ // Drag state listeners
278
+ deps.root.addEventListener('dragstart', onDragStart);
279
+ deps.root.addEventListener('dragend', onDragEnd);
280
+ // Blur
281
+ deps.root.addEventListener('blur', onBlur);
282
+ // Keyboard tracking (rAF-throttled)
283
+ unsubChange = deps.engine.onChange(() => scheduleSelectionUpdate());
284
+ unsubSelection = deps.engine.onSelectionChange(() => scheduleSelectionUpdate());
285
+ // Drag handler
286
+ blockDragHandler.attach();
287
+ },
288
+ detach() {
289
+ if (!attached)
290
+ return;
291
+ attached = false;
292
+ // Hover listeners
293
+ deps.root.removeEventListener('mouseover', onMouseOver);
294
+ deps.root.removeEventListener('mouseout', onMouseOut);
295
+ gutterEl.removeEventListener('mouseenter', onGutterMouseEnter);
296
+ gutterEl.removeEventListener('mouseleave', onGutterMouseLeave);
297
+ // Button listeners
298
+ addButton.removeEventListener('mousedown', onAddMouseDown);
299
+ addButton.removeEventListener('click', onAddClick);
300
+ dragHandle.removeEventListener('mousedown', onDragHandleMouseDown);
301
+ // Drag state listeners
302
+ deps.root.removeEventListener('dragstart', onDragStart);
303
+ deps.root.removeEventListener('dragend', onDragEnd);
304
+ // Blur
305
+ deps.root.removeEventListener('blur', onBlur);
306
+ // Keyboard tracking
307
+ unsubChange?.();
308
+ unsubSelection?.();
309
+ unsubChange = null;
310
+ unsubSelection = null;
311
+ // Cancel pending rAF
312
+ if (rafId !== null) {
313
+ cancelAnimationFrame(rafId);
314
+ rafId = null;
315
+ }
316
+ // Drag handler
317
+ blockDragHandler.detach();
318
+ // Remove DOM
319
+ if (gutterEl.parentNode) {
320
+ gutterEl.parentNode.removeChild(gutterEl);
321
+ }
322
+ // Clear state
323
+ clearHideTimeout();
324
+ activeBlockId = null;
325
+ mouseIsActive = false;
326
+ isDragging = false;
327
+ prevFocusBlockId = null;
328
+ },
329
+ };
330
+ }
331
+ //# sourceMappingURL=block-gutter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block-gutter.js","sourceRoot":"","sources":["../src/block-gutter.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"drop-indicator.d.ts","sourceRoot":"","sources":["../src/drop-indicator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAaH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,UAAU,CAAS;IAE3B;;;;;;;;;;;;OAYG;gBACS,SAAS,EAAE,WAAW;IAmBlC;;;;;;;;;;OAUG;IACH,WAAW,IAAI,IAAI;IAcnB;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI;IA0BvE;;;;;;;OAOG;IACH,IAAI,IAAI,IAAI;IAMZ;;;;;;;;;;OAUG;IACH,OAAO,IAAI,IAAI;IAmBf,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,YAAY;CAKrB"}
1
+ {"version":3,"file":"drop-indicator.d.ts","sourceRoot":"","sources":["../src/drop-indicator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAcH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,UAAU,CAAS;IAE3B;;;;;;;;;;;;OAYG;gBACS,SAAS,EAAE,WAAW;IAmBlC;;;;;;;;;;OAUG;IACH,WAAW,IAAI,IAAI;IAcnB;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI;IAwBvE;;;;;;;OAOG;IACH,IAAI,IAAI,IAAI;IAMZ;;;;;;;;;;OAUG;IACH,OAAO,IAAI,IAAI;IAmBf,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,YAAY;CAKrB"}
@@ -15,6 +15,7 @@
15
15
  // ---------------------------------------------------------------------------
16
16
  const CSS_LINE = 'rtif-drop-indicator';
17
17
  const CSS_OVERLAY = 'rtif-drop-overlay';
18
+ const CSS_HIDDEN = 'rtif-hidden';
18
19
  // ---------------------------------------------------------------------------
19
20
  // DropIndicator class
20
21
  // ---------------------------------------------------------------------------
@@ -94,7 +95,7 @@ export class DropIndicator {
94
95
  this._overlayEl = createOverlayElement();
95
96
  this._container.appendChild(this._overlayEl);
96
97
  }
97
- this._overlayEl.style.display = 'flex';
98
+ this._overlayEl.classList.remove(CSS_HIDDEN);
98
99
  }
99
100
  /**
100
101
  * Show a thin horizontal line before or after a block element.
@@ -127,9 +128,7 @@ export class DropIndicator {
127
128
  ? blockRect.top - containerRect.top
128
129
  : blockRect.bottom - containerRect.top;
129
130
  this._lineEl.style.top = `${top}px`;
130
- this._lineEl.style.left = '0';
131
- this._lineEl.style.right = '0';
132
- this._lineEl.style.display = '';
131
+ this._lineEl.classList.remove(CSS_HIDDEN);
133
132
  }
134
133
  /**
135
134
  * Hide all indicators (both line and overlay).
@@ -174,12 +173,12 @@ export class DropIndicator {
174
173
  // -----------------------------------------------------------------------
175
174
  _hideLine() {
176
175
  if (this._lineEl) {
177
- this._lineEl.style.display = 'none';
176
+ this._lineEl.classList.add(CSS_HIDDEN);
178
177
  }
179
178
  }
180
179
  _hideOverlay() {
181
180
  if (this._overlayEl) {
182
- this._overlayEl.style.display = 'none';
181
+ this._overlayEl.classList.add(CSS_HIDDEN);
183
182
  }
184
183
  }
185
184
  }
@@ -191,16 +190,7 @@ export class DropIndicator {
191
190
  */
192
191
  function createLineElement() {
193
192
  const el = document.createElement('div');
194
- el.className = CSS_LINE;
195
- el.style.position = 'absolute';
196
- el.style.height = '2px';
197
- el.style.left = '0';
198
- el.style.right = '0';
199
- el.style.backgroundColor =
200
- 'var(--rtif-accent-color, #2563eb)';
201
- el.style.pointerEvents = 'none';
202
- el.style.zIndex = '10';
203
- el.style.display = 'none';
193
+ el.className = `${CSS_LINE} ${CSS_HIDDEN}`;
204
194
  el.setAttribute('aria-hidden', 'true');
205
195
  return el;
206
196
  }
@@ -209,26 +199,10 @@ function createLineElement() {
209
199
  */
210
200
  function createOverlayElement() {
211
201
  const el = document.createElement('div');
212
- el.className = CSS_OVERLAY;
213
- el.style.position = 'absolute';
214
- el.style.inset = '0';
215
- el.style.zIndex = '20';
216
- el.style.pointerEvents = 'none';
217
- el.style.border =
218
- '2px dashed var(--rtif-accent-color, #2563eb)';
219
- el.style.borderRadius = '4px';
220
- el.style.backgroundColor = 'rgba(37, 99, 235, 0.05)';
221
- // Centered label — starts hidden, showForFile() removes display:none
222
- el.style.display = 'none';
223
- el.style.alignItems = 'center';
224
- el.style.justifyContent = 'center';
202
+ el.className = `${CSS_OVERLAY} ${CSS_HIDDEN}`;
225
203
  const label = document.createElement('span');
204
+ label.className = 'rtif-drop-overlay-label';
226
205
  label.textContent = 'Drop file to upload';
227
- label.style.color = 'var(--rtif-accent-color, #2563eb)';
228
- label.style.fontSize = '14px';
229
- label.style.fontWeight = '500';
230
- label.style.pointerEvents = 'none';
231
- label.style.userSelect = 'none';
232
206
  el.appendChild(label);
233
207
  el.setAttribute('aria-hidden', 'true');
234
208
  return el;
@@ -1 +1 @@
1
- {"version":3,"file":"drop-indicator.js","sourceRoot":"","sources":["../src/drop-indicator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"drop-indicator.js","sourceRoot":"","sources":["../src/drop-indicator.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAwB,MAAM,YAAY,CAAC;AAmDnF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CA6zBlE"}
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAwB,MAAM,YAAY,CAAC;AAmDnF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAy0BlE"}
package/dist/editor.js CHANGED
@@ -30,7 +30,7 @@ import { createFileDropHandler } from './content-handler-file.js';
30
30
  import { DropIndicator } from './drop-indicator.js';
31
31
  import { createMarkRendererRegistry, registerBuiltinRenderers, } from './mark-renderer.js';
32
32
  import { createBlockRendererRegistry, registerBuiltinBlockRenderers, } from './block-renderer.js';
33
- import { BlockDragHandler } from './block-drag-handler.js';
33
+ import { createBlockGutter } from './block-gutter.js';
34
34
  import { createCursorRectAPI } from './cursor-rect.js';
35
35
  import { createTriggerManager } from './trigger-manager.js';
36
36
  import { findContiguousMarkRange, adjustOffsetAroundAtomicMarks, adjustOffsetAroundAtomicBlocks } from './plugins/mark-utils.js';
@@ -90,6 +90,7 @@ export function createWebEditor(config) {
90
90
  root.setAttribute('aria-multiline', 'true');
91
91
  root.setAttribute('aria-label', config.accessibleLabel);
92
92
  root.setAttribute('data-rtif-root', '');
93
+ root.classList.add('rtif-editor');
93
94
  root.spellcheck = spellcheck;
94
95
  // Accessibility: announce read-only state to screen readers
95
96
  if (readOnly) {
@@ -252,15 +253,25 @@ export function createWebEditor(config) {
252
253
  // -------------------------------------------------------------------
253
254
  const dropIndicator = new DropIndicator(root);
254
255
  // -------------------------------------------------------------------
255
- // Block drag handler (reorder blocks via drag handles)
256
+ // Block gutter toolbar (+ button and drag handle on hover/focus)
256
257
  // -------------------------------------------------------------------
257
- const blockDragHandler = new BlockDragHandler({
258
- root,
259
- getDoc: () => engine.state.doc,
260
- dispatch: (ops) => engine.dispatch(ops),
261
- isReadOnly: () => readOnly,
262
- getBlockElementMap: () => blockElementMap,
263
- });
258
+ const gutterEnabled = config.gutter !== false;
259
+ const blockGutter = gutterEnabled
260
+ ? createBlockGutter({
261
+ root,
262
+ engine,
263
+ isReadOnly: () => readOnly,
264
+ getBlockElementMap: () => blockElementMap,
265
+ generateBlockId: () => generateId(),
266
+ focusAtOffset: (offset) => {
267
+ engine.setSelection({ anchor: { offset }, focus: { offset } });
268
+ setDomSelection(root, engine.state.doc, engine.state.selection, blockElementMap);
269
+ if (!root.contains(document.activeElement)) {
270
+ root.focus();
271
+ }
272
+ },
273
+ })
274
+ : null;
264
275
  // -------------------------------------------------------------------
265
276
  // Paste handler (via content pipeline)
266
277
  // -------------------------------------------------------------------
@@ -637,7 +648,7 @@ export function createWebEditor(config) {
637
648
  inputBridge.attach();
638
649
  clipboardHandler.attach();
639
650
  cursorNavHandler.attach();
640
- blockDragHandler.attach();
651
+ blockGutter?.attach();
641
652
  root.addEventListener('compositionstart', onCompositionStart);
642
653
  root.addEventListener('compositionupdate', onCompositionUpdate);
643
654
  root.addEventListener('compositionend', onCompositionEnd);
@@ -719,7 +730,7 @@ export function createWebEditor(config) {
719
730
  inputBridge.detach();
720
731
  clipboardHandler.detach();
721
732
  cursorNavHandler.detach();
722
- blockDragHandler.detach();
733
+ blockGutter?.detach();
723
734
  root.removeEventListener('compositionstart', onCompositionStart);
724
735
  root.removeEventListener('compositionupdate', onCompositionUpdate);
725
736
  root.removeEventListener('compositionend', onCompositionEnd);
@@ -762,6 +773,7 @@ export function createWebEditor(config) {
762
773
  root.removeAttribute('aria-label');
763
774
  root.removeAttribute('aria-readonly');
764
775
  root.removeAttribute('data-rtif-root');
776
+ root.classList.remove('rtif-editor');
765
777
  root.removeAttribute('data-placeholder');
766
778
  root.style.contain = '';
767
779
  root.style.whiteSpace = '';