@atlaskit/editor-plugin-block-controls 7.7.2 → 7.7.3
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/CHANGELOG.md +8 -0
- package/dist/cjs/blockControlsPlugin.js +14 -0
- package/dist/cjs/pm-plugins/selection-preservation/editor-commands.js +32 -0
- package/dist/cjs/pm-plugins/selection-preservation/plugin-key.js +8 -0
- package/dist/cjs/pm-plugins/selection-preservation/pm-plugin.js +99 -0
- package/dist/cjs/pm-plugins/selection-preservation/types.js +5 -0
- package/dist/cjs/pm-plugins/selection-preservation/utils.js +24 -0
- package/dist/cjs/ui/drag-handle.js +182 -62
- package/dist/es2019/blockControlsPlugin.js +11 -1
- package/dist/es2019/pm-plugins/selection-preservation/editor-commands.js +28 -0
- package/dist/es2019/pm-plugins/selection-preservation/plugin-key.js +2 -0
- package/dist/es2019/pm-plugins/selection-preservation/pm-plugin.js +92 -0
- package/dist/es2019/pm-plugins/selection-preservation/types.js +1 -0
- package/dist/es2019/pm-plugins/selection-preservation/utils.js +16 -0
- package/dist/es2019/ui/drag-handle.js +156 -33
- package/dist/esm/blockControlsPlugin.js +14 -0
- package/dist/esm/pm-plugins/selection-preservation/editor-commands.js +26 -0
- package/dist/esm/pm-plugins/selection-preservation/plugin-key.js +2 -0
- package/dist/esm/pm-plugins/selection-preservation/pm-plugin.js +93 -0
- package/dist/esm/pm-plugins/selection-preservation/types.js +1 -0
- package/dist/esm/pm-plugins/selection-preservation/utils.js +18 -0
- package/dist/esm/ui/drag-handle.js +184 -64
- package/dist/types/blockControlsPluginType.d.ts +12 -1
- package/dist/types/pm-plugins/selection-preservation/editor-commands.d.ts +13 -0
- package/dist/types/pm-plugins/selection-preservation/plugin-key.d.ts +3 -0
- package/dist/types/pm-plugins/selection-preservation/pm-plugin.d.ts +26 -0
- package/dist/types/pm-plugins/selection-preservation/types.d.ts +7 -0
- package/dist/types/pm-plugins/selection-preservation/utils.d.ts +10 -0
- package/dist/types-ts4.5/blockControlsPluginType.d.ts +12 -1
- package/dist/types-ts4.5/pm-plugins/selection-preservation/editor-commands.d.ts +13 -0
- package/dist/types-ts4.5/pm-plugins/selection-preservation/plugin-key.d.ts +3 -0
- package/dist/types-ts4.5/pm-plugins/selection-preservation/pm-plugin.d.ts +26 -0
- package/dist/types-ts4.5/pm-plugins/selection-preservation/types.d.ts +7 -0
- package/dist/types-ts4.5/pm-plugins/selection-preservation/utils.d.ts +10 -0
- package/package.json +4 -3
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { selectionPreservationPluginKey } from './plugin-key';
|
|
2
|
+
/**
|
|
3
|
+
* Detects if any of the transactions include user-driven selection changes.
|
|
4
|
+
*
|
|
5
|
+
* @param transactions The list of transactions to check.
|
|
6
|
+
* @returns True if any transaction includes a user-driven selection change, otherwise false.
|
|
7
|
+
*/
|
|
8
|
+
export var hasUserSelectionChange = function hasUserSelectionChange(transactions) {
|
|
9
|
+
return transactions.some(function (tr) {
|
|
10
|
+
return tr.getMeta('pointer') || tr.getMeta('uiEvent') || tr.getMeta('paste') || tr.getMeta('cut') || tr.getMeta('composition') ||
|
|
11
|
+
// IME input
|
|
12
|
+
// Keyboard events that change selection
|
|
13
|
+
tr.getMeta('addToHistory') && tr.selectionSet;
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
export var getSelectionPreservationMeta = function getSelectionPreservationMeta(tr) {
|
|
17
|
+
return tr.getMeta(selectionPreservationPluginKey);
|
|
18
|
+
};
|
|
@@ -13,17 +13,18 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
13
13
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
14
14
|
import { css, jsx } from '@emotion/react';
|
|
15
15
|
import { bind } from 'bind-event-listener';
|
|
16
|
+
import { getDocument } from '@atlaskit/browser-apis';
|
|
16
17
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
17
18
|
import { browser as browserLegacy, getBrowserInfo } from '@atlaskit/editor-common/browser';
|
|
18
19
|
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
19
20
|
import { dragToMoveDown, dragToMoveLeft, dragToMoveRight, dragToMoveUp, getAriaKeyshortcuts, TooltipContentWithMultipleShortcuts } from '@atlaskit/editor-common/keymaps';
|
|
20
21
|
import { blockControlsMessages } from '@atlaskit/editor-common/messages';
|
|
21
22
|
import { deleteSelectedRange } from '@atlaskit/editor-common/selection';
|
|
22
|
-
import {
|
|
23
|
+
import { DRAG_HANDLE_WIDTH, tableControlsSpacing } from '@atlaskit/editor-common/styles';
|
|
23
24
|
import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
|
|
24
25
|
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
25
26
|
import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
|
|
26
|
-
import {
|
|
27
|
+
import { akEditorFullPageNarrowBreakout, akEditorTableToolbarSize, relativeSizeToBaseFontSize } from '@atlaskit/editor-shared-styles/consts';
|
|
27
28
|
import DragHandleVerticalIcon from '@atlaskit/icon/core/drag-handle-vertical';
|
|
28
29
|
import DragHandlerIcon from '@atlaskit/icon/glyph/drag-handler';
|
|
29
30
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
@@ -37,6 +38,7 @@ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
|
37
38
|
import Tooltip from '@atlaskit/tooltip';
|
|
38
39
|
import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
|
|
39
40
|
import { key } from '../pm-plugins/main';
|
|
41
|
+
import { selectionPreservationPluginKey } from '../pm-plugins/selection-preservation/plugin-key';
|
|
40
42
|
import { getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
|
|
41
43
|
import { getControlBottomCSSValue, getControlHeightCSSValue, getLeftPosition, getNodeHeight, getTopPosition, shouldBeSticky, shouldMaskNodeControls } from '../pm-plugins/utils/drag-handle-positions';
|
|
42
44
|
import { isHandleCorrelatedToSelection, isNodeWithCodeBlock, selectNode } from '../pm-plugins/utils/getSelection';
|
|
@@ -293,18 +295,81 @@ var getNodeMargins = function getNodeMargins(node) {
|
|
|
293
295
|
}
|
|
294
296
|
return nodeMargins[nodeTypeName] || nodeMargins['default'];
|
|
295
297
|
};
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
298
|
+
var isRangeSpanningMultipleNodes = function isRangeSpanningMultipleNodes(range) {
|
|
299
|
+
if (range.endIndex - range.startIndex <= 1) {
|
|
300
|
+
return false; // At most one child
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Count block nodes in the range, return true if more than one
|
|
304
|
+
var blockCount = 0;
|
|
305
|
+
for (var i = range.startIndex; i < range.endIndex; i++) {
|
|
306
|
+
if (range.parent.child(i).isBlock) {
|
|
307
|
+
blockCount++;
|
|
308
|
+
}
|
|
309
|
+
if (blockCount > 1) {
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return false;
|
|
314
|
+
};
|
|
315
|
+
var shouldExpandSelection = function shouldExpandSelection(range, startPos) {
|
|
316
|
+
return !!range && isRangeSpanningMultipleNodes(range) && range.start <= startPos && range.end >= startPos + 1;
|
|
317
|
+
};
|
|
318
|
+
var calculateBlockRange = function calculateBlockRange(_ref) {
|
|
319
|
+
var selection = _ref.selection,
|
|
320
|
+
doc = _ref.doc,
|
|
321
|
+
resolvedStartPos = _ref.resolvedStartPos,
|
|
322
|
+
isShiftPressed = _ref.isShiftPressed;
|
|
323
|
+
if (!isShiftPressed) {
|
|
324
|
+
// When not pressing shift, create range including all block nodes within the selection
|
|
325
|
+
return selection.$from.blockRange(selection.$to);
|
|
326
|
+
}
|
|
327
|
+
if (resolvedStartPos.pos < selection.from) {
|
|
328
|
+
// If shift+click selecting upwards, get range from start of node to end of selection
|
|
329
|
+
return resolvedStartPos.blockRange(selection.$to);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Shift+click selecting downwards, get range from start of selection to pos within or after node
|
|
333
|
+
var resolvedPosWithinOrAfterNode = doc.resolve(resolvedStartPos.pos + 1);
|
|
334
|
+
return selection.$from.blockRange(resolvedPosWithinOrAfterNode);
|
|
335
|
+
};
|
|
336
|
+
var createExpandedSelection = function createExpandedSelection(doc, selection, range) {
|
|
337
|
+
return TextSelection.create(doc, Math.min(selection.from, range.start), Math.max(selection.to, range.end));
|
|
338
|
+
};
|
|
339
|
+
var createSelectionFromRange = function createSelectionFromRange(_ref2) {
|
|
340
|
+
var tr = _ref2.tr,
|
|
341
|
+
selection = _ref2.selection,
|
|
342
|
+
startPos = _ref2.startPos,
|
|
343
|
+
nodeType = _ref2.nodeType,
|
|
344
|
+
range = _ref2.range,
|
|
345
|
+
api = _ref2.api;
|
|
346
|
+
if (range && shouldExpandSelection(range, startPos)) {
|
|
347
|
+
var expandedSelection = createExpandedSelection(tr.doc, selection, range);
|
|
348
|
+
if (!expandedSelection.eq(tr.selection)) {
|
|
349
|
+
tr.setSelection(expandedSelection);
|
|
350
|
+
}
|
|
351
|
+
return tr;
|
|
352
|
+
}
|
|
353
|
+
var node = tr.doc.nodeAt(startPos);
|
|
354
|
+
var isEmptyNode = (node === null || node === void 0 ? void 0 : node.content.size) === 0;
|
|
355
|
+
if (isEmptyNode && node.type.name !== 'paragraph') {
|
|
356
|
+
tr.setSelection(new NodeSelection(tr.doc.resolve(startPos)));
|
|
357
|
+
return tr;
|
|
358
|
+
}
|
|
359
|
+
return selectNode(tr, startPos, nodeType, api);
|
|
360
|
+
};
|
|
361
|
+
export var DragHandle = function DragHandle(_ref3) {
|
|
362
|
+
var _api$core4;
|
|
363
|
+
var view = _ref3.view,
|
|
364
|
+
api = _ref3.api,
|
|
365
|
+
formatMessage = _ref3.formatMessage,
|
|
366
|
+
getPos = _ref3.getPos,
|
|
367
|
+
anchorName = _ref3.anchorName,
|
|
368
|
+
nodeType = _ref3.nodeType,
|
|
369
|
+
handleOptions = _ref3.handleOptions,
|
|
370
|
+
_ref3$isTopLevelNode = _ref3.isTopLevelNode,
|
|
371
|
+
isTopLevelNode = _ref3$isTopLevelNode === void 0 ? true : _ref3$isTopLevelNode,
|
|
372
|
+
anchorRectCache = _ref3.anchorRectCache;
|
|
308
373
|
var buttonRef = useRef(null);
|
|
309
374
|
var _useState = useState(false),
|
|
310
375
|
_useState2 = _slicedToArray(_useState, 2),
|
|
@@ -365,14 +430,69 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
365
430
|
}
|
|
366
431
|
}
|
|
367
432
|
}, [anchorName, nodeType, view.dom]);
|
|
368
|
-
var
|
|
433
|
+
var handleOnClickNew = useCallback(function (e) {
|
|
369
434
|
var _api$core;
|
|
435
|
+
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref4) {
|
|
436
|
+
var _api$analytics, _resolvedStartPos$nod, _selectionPreservatio, _api$blockControls, _api$blockControls2;
|
|
437
|
+
var tr = _ref4.tr;
|
|
438
|
+
var startPos = getPos();
|
|
439
|
+
if (startPos === undefined) {
|
|
440
|
+
return tr;
|
|
441
|
+
}
|
|
442
|
+
var resolvedStartPos = tr.doc.resolve(startPos);
|
|
443
|
+
api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
|
|
444
|
+
eventType: EVENT_TYPE.UI,
|
|
445
|
+
action: ACTION.CLICKED,
|
|
446
|
+
actionSubject: ACTION_SUBJECT.BUTTON,
|
|
447
|
+
actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
|
|
448
|
+
attributes: {
|
|
449
|
+
nodeDepth: resolvedStartPos.depth,
|
|
450
|
+
nodeType: ((_resolvedStartPos$nod = resolvedStartPos.nodeAfter) === null || _resolvedStartPos$nod === void 0 ? void 0 : _resolvedStartPos$nod.type.name) || ''
|
|
451
|
+
}
|
|
452
|
+
})(tr);
|
|
453
|
+
var preservedSelection = (_selectionPreservatio = selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection;
|
|
454
|
+
var selection = preservedSelection || tr.selection;
|
|
455
|
+
var range = calculateBlockRange({
|
|
456
|
+
doc: tr.doc,
|
|
457
|
+
selection: selection,
|
|
458
|
+
resolvedStartPos: resolvedStartPos,
|
|
459
|
+
isShiftPressed: e.shiftKey
|
|
460
|
+
});
|
|
461
|
+
tr = createSelectionFromRange({
|
|
462
|
+
tr: tr,
|
|
463
|
+
selection: selection,
|
|
464
|
+
startPos: startPos,
|
|
465
|
+
nodeType: nodeType,
|
|
466
|
+
range: range,
|
|
467
|
+
api: api
|
|
468
|
+
});
|
|
469
|
+
api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.startPreservingSelection()({
|
|
470
|
+
tr: tr
|
|
471
|
+
});
|
|
472
|
+
api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.toggleBlockMenu({
|
|
473
|
+
anchorName: anchorName,
|
|
474
|
+
openedViaKeyboard: false,
|
|
475
|
+
triggerByNode: expValEqualsNoExposure('platform_synced_block', 'isEnabled', true) ? {
|
|
476
|
+
nodeType: nodeType,
|
|
477
|
+
pos: startPos,
|
|
478
|
+
rootPos: tr.doc.resolve(startPos).before(1)
|
|
479
|
+
} : undefined
|
|
480
|
+
})({
|
|
481
|
+
tr: tr
|
|
482
|
+
});
|
|
483
|
+
tr.setMeta('scrollIntoView', false);
|
|
484
|
+
return tr;
|
|
485
|
+
});
|
|
486
|
+
view.focus();
|
|
487
|
+
}, [api, view, getPos, nodeType, anchorName]);
|
|
488
|
+
var handleOnClick = useCallback(function (e) {
|
|
489
|
+
var _api$core2;
|
|
370
490
|
if (!isMultiSelect) {
|
|
371
491
|
setDragHandleSelected(!dragHandleSelected);
|
|
372
492
|
}
|
|
373
|
-
api === null || api === void 0 || (_api$
|
|
374
|
-
var _api$blockControls$sh, _api$
|
|
375
|
-
var tr =
|
|
493
|
+
api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref5) {
|
|
494
|
+
var _api$blockControls$sh, _api$analytics2;
|
|
495
|
+
var tr = _ref5.tr;
|
|
376
496
|
var startPos = getPos();
|
|
377
497
|
if (startPos === undefined) {
|
|
378
498
|
return tr;
|
|
@@ -401,8 +521,8 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
401
521
|
rootPos: rootPos
|
|
402
522
|
} : undefined;
|
|
403
523
|
if (BLOCK_MENU_ENABLED && editorExperiment('platform_editor_controls', 'variant1')) {
|
|
404
|
-
var _api$
|
|
405
|
-
api === null || api === void 0 || (_api$
|
|
524
|
+
var _api$blockControls3;
|
|
525
|
+
api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.toggleBlockMenu({
|
|
406
526
|
anchorName: anchorName,
|
|
407
527
|
triggerByNode: triggerByNode,
|
|
408
528
|
openedViaKeyboard: expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? false : undefined
|
|
@@ -411,8 +531,8 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
411
531
|
});
|
|
412
532
|
e.stopPropagation();
|
|
413
533
|
} else if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
414
|
-
var _api$
|
|
415
|
-
api === null || api === void 0 || (_api$
|
|
534
|
+
var _api$blockControls4;
|
|
535
|
+
api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || _api$blockControls4.commands.toggleBlockMenu({
|
|
416
536
|
anchorName: anchorName,
|
|
417
537
|
triggerByNode: triggerByNode,
|
|
418
538
|
openedViaKeyboard: expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? false : undefined
|
|
@@ -422,18 +542,18 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
422
542
|
e.stopPropagation();
|
|
423
543
|
}
|
|
424
544
|
} else if (isTopLevelNode && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && fg('platform_editor_elements_dnd_shift_click_select')) {
|
|
425
|
-
var _api$
|
|
545
|
+
var _api$blockControls5;
|
|
426
546
|
var alignAnchorHeadToSel = alignAnchorHeadInDirectionOfPos(tr.selection, startPos);
|
|
427
547
|
var selectionWithExpandedHead = expandSelectionHeadToNodeAtPos(alignAnchorHeadToSel, startPos);
|
|
428
548
|
tr.setSelection(selectionWithExpandedHead);
|
|
429
|
-
api === null || api === void 0 || (_api$
|
|
549
|
+
api === null || api === void 0 || (_api$blockControls5 = api.blockControls) === null || _api$blockControls5 === void 0 || _api$blockControls5.commands.setMultiSelectPositions()({
|
|
430
550
|
tr: tr
|
|
431
551
|
});
|
|
432
552
|
}
|
|
433
553
|
var resolvedMovingNode = tr.doc.resolve(startPos);
|
|
434
554
|
var maybeNode = resolvedMovingNode.nodeAfter;
|
|
435
555
|
tr.setMeta('scrollIntoView', false);
|
|
436
|
-
api === null || api === void 0 || (_api$
|
|
556
|
+
api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.attachAnalyticsEvent({
|
|
437
557
|
eventType: EVENT_TYPE.UI,
|
|
438
558
|
action: ACTION.CLICKED,
|
|
439
559
|
actionSubject: ACTION_SUBJECT.BUTTON,
|
|
@@ -450,10 +570,10 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
450
570
|
var handleKeyDown = useCallback(function (e) {
|
|
451
571
|
// allow user to use spacebar to select the node
|
|
452
572
|
if (!e.repeat && e.key === ' ') {
|
|
453
|
-
var _api$
|
|
573
|
+
var _api$core3;
|
|
454
574
|
var startPos = getPos();
|
|
455
|
-
api === null || api === void 0 || (_api$
|
|
456
|
-
var tr =
|
|
575
|
+
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref6) {
|
|
576
|
+
var tr = _ref6.tr;
|
|
457
577
|
if (startPos === undefined) {
|
|
458
578
|
return tr;
|
|
459
579
|
}
|
|
@@ -476,20 +596,20 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
476
596
|
// return focus to editor to resume editing from caret position
|
|
477
597
|
view.focus();
|
|
478
598
|
}
|
|
479
|
-
}, [getPos, api === null || api === void 0 || (_api$
|
|
599
|
+
}, [getPos, api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions, isMultiSelect, view]);
|
|
480
600
|
var handleKeyDownNew = useCallback(function (e) {
|
|
481
601
|
// allow user to use spacebar to select the node
|
|
482
602
|
if (e.key === 'Enter' || !e.repeat && e.key === ' ') {
|
|
483
|
-
var _api$
|
|
484
|
-
if (
|
|
603
|
+
var _getDocument, _api$core5;
|
|
604
|
+
if (((_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : _getDocument.activeElement) !== buttonRef.current) {
|
|
485
605
|
return;
|
|
486
606
|
}
|
|
487
607
|
e.preventDefault();
|
|
488
608
|
e.stopPropagation();
|
|
489
609
|
var startPos = getPos();
|
|
490
|
-
api === null || api === void 0 || (_api$
|
|
491
|
-
var _api$
|
|
492
|
-
var tr =
|
|
610
|
+
api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.execute(function (_ref7) {
|
|
611
|
+
var _api$blockControls6, _api$userIntent;
|
|
612
|
+
var tr = _ref7.tr;
|
|
493
613
|
if (startPos === undefined) {
|
|
494
614
|
return tr;
|
|
495
615
|
}
|
|
@@ -503,7 +623,7 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
503
623
|
pos: startPos,
|
|
504
624
|
rootPos: rootPos
|
|
505
625
|
} : undefined;
|
|
506
|
-
api === null || api === void 0 || (_api$
|
|
626
|
+
api === null || api === void 0 || (_api$blockControls6 = api.blockControls) === null || _api$blockControls6 === void 0 || _api$blockControls6.commands.toggleBlockMenu({
|
|
507
627
|
anchorName: anchorName,
|
|
508
628
|
triggerByNode: triggerByNode,
|
|
509
629
|
openedViaKeyboard: true
|
|
@@ -518,11 +638,11 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
518
638
|
} else if (e.key === 'Backspace' || e.key === 'Delete') {
|
|
519
639
|
e.preventDefault();
|
|
520
640
|
e.stopPropagation();
|
|
521
|
-
api === null || api === void 0 || api.core.actions.execute(function (
|
|
522
|
-
var _api$
|
|
523
|
-
var tr =
|
|
641
|
+
api === null || api === void 0 || api.core.actions.execute(function (_ref8) {
|
|
642
|
+
var _api$blockControls7;
|
|
643
|
+
var tr = _ref8.tr;
|
|
524
644
|
deleteSelectedRange(tr);
|
|
525
|
-
api === null || api === void 0 || (_api$
|
|
645
|
+
api === null || api === void 0 || (_api$blockControls7 = api.blockControls) === null || _api$blockControls7 === void 0 || _api$blockControls7.commands.toggleBlockMenu({
|
|
526
646
|
closeMenu: true
|
|
527
647
|
})({
|
|
528
648
|
tr: tr
|
|
@@ -550,21 +670,21 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
550
670
|
start: start
|
|
551
671
|
};
|
|
552
672
|
},
|
|
553
|
-
onGenerateDragPreview: function onGenerateDragPreview(
|
|
673
|
+
onGenerateDragPreview: function onGenerateDragPreview(_ref9) {
|
|
554
674
|
var _api$blockControls$sh2;
|
|
555
|
-
var nativeSetDragImage =
|
|
675
|
+
var nativeSetDragImage = _ref9.nativeSetDragImage;
|
|
556
676
|
if (isMultiSelect) {
|
|
557
|
-
var _api$
|
|
558
|
-
api === null || api === void 0 || (_api$
|
|
559
|
-
var tr =
|
|
677
|
+
var _api$core6;
|
|
678
|
+
api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref0) {
|
|
679
|
+
var tr = _ref0.tr;
|
|
560
680
|
var handlePos = getPos();
|
|
561
681
|
if (typeof handlePos !== 'number') {
|
|
562
682
|
return tr;
|
|
563
683
|
}
|
|
564
684
|
var newHandlePosCheck = isHandleCorrelatedToSelection(view.state, tr.selection, handlePos);
|
|
565
685
|
if (!tr.selection.empty && newHandlePosCheck) {
|
|
566
|
-
var _api$
|
|
567
|
-
api === null || api === void 0 || (_api$
|
|
686
|
+
var _api$blockControls8;
|
|
687
|
+
api === null || api === void 0 || (_api$blockControls8 = api.blockControls) === null || _api$blockControls8 === void 0 || _api$blockControls8.commands.setMultiSelectPositions()({
|
|
568
688
|
tr: tr
|
|
569
689
|
});
|
|
570
690
|
} else if (fg('platform_editor_elements_dnd_select_node_on_drag')) {
|
|
@@ -634,8 +754,8 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
634
754
|
};
|
|
635
755
|
}
|
|
636
756
|
},
|
|
637
|
-
render: function render(
|
|
638
|
-
var container =
|
|
757
|
+
render: function render(_ref1) {
|
|
758
|
+
var container = _ref1.container;
|
|
639
759
|
var dom = view.dom.querySelector("[".concat(getAnchorAttrName(), "=\"").concat(anchorName, "\"]"));
|
|
640
760
|
if (!dom) {
|
|
641
761
|
return;
|
|
@@ -667,13 +787,13 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
667
787
|
});
|
|
668
788
|
},
|
|
669
789
|
onDragStart: function onDragStart() {
|
|
670
|
-
var _api$
|
|
790
|
+
var _api$core7;
|
|
671
791
|
if (start === undefined) {
|
|
672
792
|
return;
|
|
673
793
|
}
|
|
674
|
-
api === null || api === void 0 || (_api$
|
|
675
|
-
var _api$blockControls$sh3, _api$
|
|
676
|
-
var tr =
|
|
794
|
+
api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref10) {
|
|
795
|
+
var _api$blockControls$sh3, _api$blockControls9, _api$analytics3;
|
|
796
|
+
var tr = _ref10.tr;
|
|
677
797
|
var nodeTypes, hasSelectedMultipleNodes;
|
|
678
798
|
var resolvedMovingNode = tr.doc.resolve(start);
|
|
679
799
|
var maybeNode = resolvedMovingNode.nodeAfter;
|
|
@@ -686,11 +806,11 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
686
806
|
nodeTypes = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name;
|
|
687
807
|
hasSelectedMultipleNodes = false;
|
|
688
808
|
}
|
|
689
|
-
api === null || api === void 0 || (_api$
|
|
809
|
+
api === null || api === void 0 || (_api$blockControls9 = api.blockControls) === null || _api$blockControls9 === void 0 || _api$blockControls9.commands.setNodeDragged(getPos, anchorName, nodeType)({
|
|
690
810
|
tr: tr
|
|
691
811
|
});
|
|
692
812
|
tr.setMeta('scrollIntoView', false);
|
|
693
|
-
api === null || api === void 0 || (_api$
|
|
813
|
+
api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || _api$analytics3.actions.attachAnalyticsEvent({
|
|
694
814
|
eventType: EVENT_TYPE.UI,
|
|
695
815
|
action: ACTION.DRAGGED,
|
|
696
816
|
actionSubject: ACTION_SUBJECT.ELEMENT,
|
|
@@ -984,7 +1104,7 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
984
1104
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
|
|
985
1105
|
,
|
|
986
1106
|
style: !editorExperiment('platform_editor_controls', 'variant1') ? editorExperiment('platform_editor_block_control_optimise_render', true) ? positionStyles : positionStylesOld : {},
|
|
987
|
-
onClick: handleOnClick,
|
|
1107
|
+
onClick: expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true) ? handleOnClickNew : handleOnClick,
|
|
988
1108
|
onKeyDown: expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true) && expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? handleKeyDownNew : handleKeyDown
|
|
989
1109
|
// eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
|
|
990
1110
|
,
|
|
@@ -1069,15 +1189,15 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
1069
1189
|
var render = isTooltip ? buttonWithTooltip() : renderButton();
|
|
1070
1190
|
return editorExperiment('platform_editor_controls', 'variant1') ? stickyRender : render;
|
|
1071
1191
|
};
|
|
1072
|
-
export var DragHandleWithVisibility = function DragHandleWithVisibility(
|
|
1073
|
-
var view =
|
|
1074
|
-
api =
|
|
1075
|
-
formatMessage =
|
|
1076
|
-
getPos =
|
|
1077
|
-
anchorName =
|
|
1078
|
-
nodeType =
|
|
1079
|
-
handleOptions =
|
|
1080
|
-
anchorRectCache =
|
|
1192
|
+
export var DragHandleWithVisibility = function DragHandleWithVisibility(_ref11) {
|
|
1193
|
+
var view = _ref11.view,
|
|
1194
|
+
api = _ref11.api,
|
|
1195
|
+
formatMessage = _ref11.formatMessage,
|
|
1196
|
+
getPos = _ref11.getPos,
|
|
1197
|
+
anchorName = _ref11.anchorName,
|
|
1198
|
+
nodeType = _ref11.nodeType,
|
|
1199
|
+
handleOptions = _ref11.handleOptions,
|
|
1200
|
+
anchorRectCache = _ref11.anchorRectCache;
|
|
1081
1201
|
return jsx(VisibilityContainer, {
|
|
1082
1202
|
api: api
|
|
1083
1203
|
}, jsx(DragHandle, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type IntlShape } from 'react-intl-next';
|
|
2
2
|
import { type INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
3
|
-
import type { EditorCommand, NextEditorPlugin, OptionalPlugin
|
|
3
|
+
import type { DIRECTION, EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
|
|
4
4
|
import type { AccessibilityUtilsPlugin } from '@atlaskit/editor-plugin-accessibility-utils';
|
|
5
5
|
import { type AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
|
|
6
6
|
import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
|
|
@@ -132,6 +132,17 @@ export type BlockControlsPlugin = NextEditorPlugin<'blockControls', {
|
|
|
132
132
|
setNodeDragged: (getPos: () => number | undefined, anchorName: string, nodeType: string) => EditorCommand;
|
|
133
133
|
setSelectedViaDragHandle: (isSelectedViaDragHandle?: boolean) => EditorCommand;
|
|
134
134
|
showDragHandleAt: (pos: number, anchorName: string, nodeType: string, handleOptions?: HandleOptions, rootPos?: number, rootAnchorName?: string, rootNodeType?: string) => EditorCommand;
|
|
135
|
+
/**
|
|
136
|
+
* Starts preserving the current selection across transactions.
|
|
137
|
+
* Used when opening block menus, dragging, or other interactions
|
|
138
|
+
* where multi-node selections should remain stable.
|
|
139
|
+
*/
|
|
140
|
+
startPreservingSelection: () => EditorCommand;
|
|
141
|
+
/**
|
|
142
|
+
* Stops preserving the selection, allowing it to change freely.
|
|
143
|
+
* Called when block menus close or drag operations end.
|
|
144
|
+
*/
|
|
145
|
+
stopPreservingSelection: () => EditorCommand;
|
|
135
146
|
toggleBlockMenu: (options?: {
|
|
136
147
|
anchorName?: string;
|
|
137
148
|
closeMenu?: boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EditorCommand } from '@atlaskit/editor-common/types';
|
|
2
|
+
/**
|
|
3
|
+
* Start preserving the selection when a UI interaction requires it
|
|
4
|
+
*
|
|
5
|
+
* e.g., block menu open, drag-and-drop in progress
|
|
6
|
+
*/
|
|
7
|
+
export declare const startPreservingSelection: EditorCommand;
|
|
8
|
+
/**
|
|
9
|
+
* Stop preserving the selection when a UI interaction completes
|
|
10
|
+
*
|
|
11
|
+
* e.g., block menu closed, drag-and-drop ended
|
|
12
|
+
*/
|
|
13
|
+
export declare const stopPreservingSelection: EditorCommand;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import type { SelectionPreservationPluginState } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Selection Preservation Plugin for ProseMirror Editor
|
|
5
|
+
*
|
|
6
|
+
* Solves a ProseMirror limitation where TextSelection cannot include positions at node boundaries
|
|
7
|
+
* (like media/images). When a selection spans text + media nodes, subsequent transactions cause
|
|
8
|
+
* ProseMirror to collapse the selection to the nearest inline position, excluding the media node.
|
|
9
|
+
* This is problematic for features like block menus and drag-and-drop that need stable multi-node
|
|
10
|
+
* selections while performing operations.
|
|
11
|
+
*
|
|
12
|
+
* The plugin works in three phases:
|
|
13
|
+
* (1) Explicitly save a selection via startPreservingSelection() when opening block menus or starting drag operations.
|
|
14
|
+
* (2) Map the saved selection through document changes to keep positions valid.
|
|
15
|
+
* (3) Detect when transactions collapse the selection and restore it via appendTransaction().
|
|
16
|
+
*
|
|
17
|
+
* Stops preserving via stopPreservingSelection() when the menu closes or operation completes.
|
|
18
|
+
*
|
|
19
|
+
* Commands: startPreservingSelection() to begin preservation, stopPreservingSelection() to end it.
|
|
20
|
+
*
|
|
21
|
+
* NOTE: Only use when the UI blocks user selection changes. For example: when a block menu overlay
|
|
22
|
+
* is open (editor becomes non-interactive), during drag-and-drop operations (user is mid-drag), or
|
|
23
|
+
* when modal dialogs are active. In these states, any selection changes are from ProseMirror's
|
|
24
|
+
* internal behavior (not user input) and should be prevented. Do not use during normal editing.
|
|
25
|
+
*/
|
|
26
|
+
export declare const createSelectionPreservationPlugin: () => SafePlugin<SelectionPreservationPluginState>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReadonlyTransaction, Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import type { SelectionPreservationMeta } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Detects if any of the transactions include user-driven selection changes.
|
|
5
|
+
*
|
|
6
|
+
* @param transactions The list of transactions to check.
|
|
7
|
+
* @returns True if any transaction includes a user-driven selection change, otherwise false.
|
|
8
|
+
*/
|
|
9
|
+
export declare const hasUserSelectionChange: (transactions: readonly Transaction[]) => boolean;
|
|
10
|
+
export declare const getSelectionPreservationMeta: (tr: Transaction | ReadonlyTransaction) => SelectionPreservationMeta | undefined;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type IntlShape } from 'react-intl-next';
|
|
2
2
|
import { type INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
3
|
-
import type { EditorCommand, NextEditorPlugin, OptionalPlugin
|
|
3
|
+
import type { DIRECTION, EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
|
|
4
4
|
import type { AccessibilityUtilsPlugin } from '@atlaskit/editor-plugin-accessibility-utils';
|
|
5
5
|
import { type AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
|
|
6
6
|
import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
|
|
@@ -132,6 +132,17 @@ export type BlockControlsPlugin = NextEditorPlugin<'blockControls', {
|
|
|
132
132
|
setNodeDragged: (getPos: () => number | undefined, anchorName: string, nodeType: string) => EditorCommand;
|
|
133
133
|
setSelectedViaDragHandle: (isSelectedViaDragHandle?: boolean) => EditorCommand;
|
|
134
134
|
showDragHandleAt: (pos: number, anchorName: string, nodeType: string, handleOptions?: HandleOptions, rootPos?: number, rootAnchorName?: string, rootNodeType?: string) => EditorCommand;
|
|
135
|
+
/**
|
|
136
|
+
* Starts preserving the current selection across transactions.
|
|
137
|
+
* Used when opening block menus, dragging, or other interactions
|
|
138
|
+
* where multi-node selections should remain stable.
|
|
139
|
+
*/
|
|
140
|
+
startPreservingSelection: () => EditorCommand;
|
|
141
|
+
/**
|
|
142
|
+
* Stops preserving the selection, allowing it to change freely.
|
|
143
|
+
* Called when block menus close or drag operations end.
|
|
144
|
+
*/
|
|
145
|
+
stopPreservingSelection: () => EditorCommand;
|
|
135
146
|
toggleBlockMenu: (options?: {
|
|
136
147
|
anchorName?: string;
|
|
137
148
|
closeMenu?: boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EditorCommand } from '@atlaskit/editor-common/types';
|
|
2
|
+
/**
|
|
3
|
+
* Start preserving the selection when a UI interaction requires it
|
|
4
|
+
*
|
|
5
|
+
* e.g., block menu open, drag-and-drop in progress
|
|
6
|
+
*/
|
|
7
|
+
export declare const startPreservingSelection: EditorCommand;
|
|
8
|
+
/**
|
|
9
|
+
* Stop preserving the selection when a UI interaction completes
|
|
10
|
+
*
|
|
11
|
+
* e.g., block menu closed, drag-and-drop ended
|
|
12
|
+
*/
|
|
13
|
+
export declare const stopPreservingSelection: EditorCommand;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import type { SelectionPreservationPluginState } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Selection Preservation Plugin for ProseMirror Editor
|
|
5
|
+
*
|
|
6
|
+
* Solves a ProseMirror limitation where TextSelection cannot include positions at node boundaries
|
|
7
|
+
* (like media/images). When a selection spans text + media nodes, subsequent transactions cause
|
|
8
|
+
* ProseMirror to collapse the selection to the nearest inline position, excluding the media node.
|
|
9
|
+
* This is problematic for features like block menus and drag-and-drop that need stable multi-node
|
|
10
|
+
* selections while performing operations.
|
|
11
|
+
*
|
|
12
|
+
* The plugin works in three phases:
|
|
13
|
+
* (1) Explicitly save a selection via startPreservingSelection() when opening block menus or starting drag operations.
|
|
14
|
+
* (2) Map the saved selection through document changes to keep positions valid.
|
|
15
|
+
* (3) Detect when transactions collapse the selection and restore it via appendTransaction().
|
|
16
|
+
*
|
|
17
|
+
* Stops preserving via stopPreservingSelection() when the menu closes or operation completes.
|
|
18
|
+
*
|
|
19
|
+
* Commands: startPreservingSelection() to begin preservation, stopPreservingSelection() to end it.
|
|
20
|
+
*
|
|
21
|
+
* NOTE: Only use when the UI blocks user selection changes. For example: when a block menu overlay
|
|
22
|
+
* is open (editor becomes non-interactive), during drag-and-drop operations (user is mid-drag), or
|
|
23
|
+
* when modal dialogs are active. In these states, any selection changes are from ProseMirror's
|
|
24
|
+
* internal behavior (not user input) and should be prevented. Do not use during normal editing.
|
|
25
|
+
*/
|
|
26
|
+
export declare const createSelectionPreservationPlugin: () => SafePlugin<SelectionPreservationPluginState>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReadonlyTransaction, Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import type { SelectionPreservationMeta } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Detects if any of the transactions include user-driven selection changes.
|
|
5
|
+
*
|
|
6
|
+
* @param transactions The list of transactions to check.
|
|
7
|
+
* @returns True if any transaction includes a user-driven selection change, otherwise false.
|
|
8
|
+
*/
|
|
9
|
+
export declare const hasUserSelectionChange: (transactions: readonly Transaction[]) => boolean;
|
|
10
|
+
export declare const getSelectionPreservationMeta: (tr: Transaction | ReadonlyTransaction) => SelectionPreservationMeta | undefined;
|