@atlaskit/editor-plugin-block-controls 12.1.0 → 12.2.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.
- package/CHANGELOG.md +19 -0
- package/dist/cjs/pm-plugins/decorations-drag-handle.js +19 -1
- package/dist/cjs/pm-plugins/decorations-quick-insert-button.js +19 -1
- package/dist/cjs/pm-plugins/main.js +77 -19
- package/dist/cjs/ui/consts.js +3 -1
- package/dist/cjs/ui/drag-handle.js +9 -0
- package/dist/cjs/ui/global-styles.js +13 -1
- package/dist/cjs/ui/quick-insert-button.js +8 -0
- package/dist/es2019/pm-plugins/decorations-drag-handle.js +14 -0
- package/dist/es2019/pm-plugins/decorations-quick-insert-button.js +13 -0
- package/dist/es2019/pm-plugins/main.js +79 -21
- package/dist/es2019/ui/consts.js +2 -0
- package/dist/es2019/ui/drag-handle.js +10 -1
- package/dist/es2019/ui/global-styles.js +17 -2
- package/dist/es2019/ui/quick-insert-button.js +9 -1
- package/dist/esm/pm-plugins/decorations-drag-handle.js +18 -0
- package/dist/esm/pm-plugins/decorations-quick-insert-button.js +18 -0
- package/dist/esm/pm-plugins/main.js +79 -21
- package/dist/esm/ui/consts.js +2 -0
- package/dist/esm/ui/drag-handle.js +10 -1
- package/dist/esm/ui/global-styles.js +14 -2
- package/dist/esm/ui/quick-insert-button.js +9 -1
- package/dist/types/pm-plugins/decorations-drag-handle.d.ts +7 -0
- package/dist/types/pm-plugins/decorations-quick-insert-button.d.ts +7 -0
- package/dist/types/ui/consts.d.ts +2 -0
- package/dist/types-ts4.5/pm-plugins/decorations-drag-handle.d.ts +7 -0
- package/dist/types-ts4.5/pm-plugins/decorations-quick-insert-button.d.ts +7 -0
- package/dist/types-ts4.5/ui/consts.d.ts +2 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-controls
|
|
2
2
|
|
|
3
|
+
## 12.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`1f87c5cc71aa3`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1f87c5cc71aa3) -
|
|
8
|
+
Improve reliability of editor controls positioning by using ProseMirror node decorations to apply
|
|
9
|
+
CSS anchor-name, replacing fragile CSS adjacency selectors. Gated behind
|
|
10
|
+
platform_editor_controls_reliable_anchor experiment.
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
|
|
16
|
+
## 12.1.1
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
3
22
|
## 12.1.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.findHandleDec = exports.emptyParagraphNodeDecorations = exports.dragHandleDecoration = void 0;
|
|
7
|
+
exports.findHandleDec = exports.findActiveDragHandleNodeDec = exports.emptyParagraphNodeDecorations = exports.dragHandleDecoration = exports.createActiveDragHandleNodeDecoration = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _react = require("react");
|
|
10
10
|
var _bindEventListener = require("bind-event-listener");
|
|
@@ -14,11 +14,29 @@ var _view = require("@atlaskit/editor-prosemirror/view");
|
|
|
14
14
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
15
15
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
16
16
|
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
17
|
+
var _consts = require("../ui/consts");
|
|
17
18
|
var _dragHandle = require("../ui/drag-handle");
|
|
18
19
|
var _decorationsCommon = require("./decorations-common");
|
|
19
20
|
var _marks = require("./utils/marks");
|
|
20
21
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
21
22
|
|
|
23
|
+
var TYPE_ACTIVE_HANDLE_DEC = 'active-drag-handle-node';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Creates a Decoration.node that marks the active node with `data-active-drag-handle="true"`.
|
|
27
|
+
* The CSS in staticControlsAnchorStyles then applies `anchor-name` to this attribute,
|
|
28
|
+
* which is more reliable than the adjacency-selector approach in dragHandlerAnchorStyles.
|
|
29
|
+
*/
|
|
30
|
+
var createActiveDragHandleNodeDecoration = exports.createActiveDragHandleNodeDecoration = function createActiveDragHandleNodeDecoration(pos, nodeSize) {
|
|
31
|
+
return _view.Decoration.node(pos, pos + nodeSize, (0, _defineProperty2.default)({}, _consts.ACTIVE_DRAG_HANDLE_ATTR, 'true'), {
|
|
32
|
+
type: TYPE_ACTIVE_HANDLE_DEC
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
var findActiveDragHandleNodeDec = exports.findActiveDragHandleNodeDec = function findActiveDragHandleNodeDec(decorations, from, to) {
|
|
36
|
+
return decorations.find(from, to, function (spec) {
|
|
37
|
+
return spec.type === TYPE_ACTIVE_HANDLE_DEC;
|
|
38
|
+
});
|
|
39
|
+
};
|
|
22
40
|
var emptyParagraphNodeDecorations = exports.emptyParagraphNodeDecorations = function emptyParagraphNodeDecorations() {
|
|
23
41
|
var anchorName = "--node-anchor-paragraph-0";
|
|
24
42
|
var style = "anchor-name: ".concat(anchorName, "; margin-top: 0px;");
|
|
@@ -4,23 +4,41 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.quickInsertButtonDecoration = exports.findQuickInsertInsertButtonDecoration = void 0;
|
|
7
|
+
exports.quickInsertButtonDecoration = exports.findQuickInsertInsertButtonDecoration = exports.findActiveQuickInsertNodeDec = exports.createActiveQuickInsertNodeDecoration = void 0;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
8
9
|
var _react = require("react");
|
|
9
10
|
var _uuid = _interopRequireDefault(require("uuid"));
|
|
10
11
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
11
12
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
12
13
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
13
14
|
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
15
|
+
var _consts = require("../ui/consts");
|
|
14
16
|
var _quickInsertButton = require("../ui/quick-insert-button");
|
|
15
17
|
var _marks = require("./utils/marks");
|
|
16
18
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
17
19
|
|
|
18
20
|
var TYPE_QUICK_INSERT = 'INSERT_BUTTON';
|
|
21
|
+
var TYPE_ACTIVE_QUICK_INSERT_NODE = 'active-quick-insert-node';
|
|
19
22
|
var findQuickInsertInsertButtonDecoration = exports.findQuickInsertInsertButtonDecoration = function findQuickInsertInsertButtonDecoration(decorations, from, to) {
|
|
20
23
|
return decorations.find(from, to, function (spec) {
|
|
21
24
|
return spec.type === TYPE_QUICK_INSERT;
|
|
22
25
|
});
|
|
23
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* Creates a Decoration.node that marks the active node with `data-active-quick-insert="true"`.
|
|
29
|
+
* The CSS in staticControlsAnchorStyles applies `anchor-name` to this attribute directly,
|
|
30
|
+
* replacing the unreliable adjacency selector `[block-ctrl-quick-insert-button] + *`.
|
|
31
|
+
*/
|
|
32
|
+
var createActiveQuickInsertNodeDecoration = exports.createActiveQuickInsertNodeDecoration = function createActiveQuickInsertNodeDecoration(pos, nodeSize) {
|
|
33
|
+
return _view.Decoration.node(pos, pos + nodeSize, (0, _defineProperty2.default)({}, _consts.ACTIVE_QUICK_INSERT_ATTR, 'true'), {
|
|
34
|
+
type: TYPE_ACTIVE_QUICK_INSERT_NODE
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
var findActiveQuickInsertNodeDec = exports.findActiveQuickInsertNodeDec = function findActiveQuickInsertNodeDec(decorations, from, to) {
|
|
38
|
+
return decorations.find(from, to, function (spec) {
|
|
39
|
+
return spec.type === TYPE_ACTIVE_QUICK_INSERT_NODE;
|
|
40
|
+
});
|
|
41
|
+
};
|
|
24
42
|
var quickInsertButtonDecoration = exports.quickInsertButtonDecoration = function quickInsertButtonDecoration(_ref) {
|
|
25
43
|
var api = _ref.api,
|
|
26
44
|
formatMessage = _ref.formatMessage,
|
|
@@ -445,21 +445,32 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
|
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
447
|
if (shouldRemoveHandle) {
|
|
448
|
-
var _activeNode5, _activeNode6;
|
|
448
|
+
var _activeNode5, _activeNode6, _activeNode7;
|
|
449
449
|
var oldHandle = (0, _decorationsDragHandle.findHandleDec)(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
|
|
450
450
|
decorations = decorations.remove(oldHandle);
|
|
451
|
+
// When removing the handle, also remove the anchor-marker node decorations
|
|
452
|
+
// (data-active-drag-handle / data-active-quick-insert) so the DOM attributes
|
|
453
|
+
// don't linger on nodes that are no longer active.
|
|
454
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_controls_reliable_anchor', 'isEnabled', true) && ((_activeNode7 = activeNode) === null || _activeNode7 === void 0 ? void 0 : _activeNode7.pos) !== undefined) {
|
|
455
|
+
var oldActiveNodeDec = (0, _decorationsDragHandle.findActiveDragHandleNodeDec)(decorations, activeNode.pos, activeNode.pos);
|
|
456
|
+
decorations = decorations.remove(oldActiveNodeDec);
|
|
457
|
+
if (activeNode.rootPos !== undefined) {
|
|
458
|
+
var oldActiveQuickInsertDec = (0, _decorationsQuickInsertButton.findActiveQuickInsertNodeDec)(decorations, activeNode.rootPos, activeNode.rootPos);
|
|
459
|
+
decorations = decorations.remove(oldActiveQuickInsertDec);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
451
462
|
// platform_editor_controls note: enables quick insert
|
|
452
463
|
if (flags.toolbarFlagsEnabled && quickInsertButtonEnabled) {
|
|
453
|
-
var
|
|
454
|
-
var oldQuickInsertButton = (0, _decorationsQuickInsertButton.findQuickInsertInsertButtonDecoration)(decorations, (
|
|
464
|
+
var _activeNode8, _activeNode9;
|
|
465
|
+
var oldQuickInsertButton = (0, _decorationsQuickInsertButton.findQuickInsertInsertButtonDecoration)(decorations, (_activeNode8 = activeNode) === null || _activeNode8 === void 0 ? void 0 : _activeNode8.rootPos, (_activeNode9 = activeNode) === null || _activeNode9 === void 0 ? void 0 : _activeNode9.rootPos);
|
|
455
466
|
decorations = decorations.remove(oldQuickInsertButton);
|
|
456
467
|
var _iterator = _createForOfIteratorHelper(nodeDecorationRegistry),
|
|
457
468
|
_step;
|
|
458
469
|
try {
|
|
459
470
|
var _loop2 = function _loop2() {
|
|
460
|
-
var
|
|
471
|
+
var _activeNode10, _activeNode11;
|
|
461
472
|
var factory = _step.value;
|
|
462
|
-
var old = decorations.find((
|
|
473
|
+
var old = decorations.find((_activeNode10 = activeNode) === null || _activeNode10 === void 0 ? void 0 : _activeNode10.rootPos, (_activeNode11 = activeNode) === null || _activeNode11 === void 0 ? void 0 : _activeNode11.rootPos, function (spec) {
|
|
463
474
|
return spec.type === factory.type;
|
|
464
475
|
});
|
|
465
476
|
decorations = decorations.remove(old);
|
|
@@ -479,8 +490,8 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
|
|
|
479
490
|
var _loop = function _loop() {
|
|
480
491
|
var factory = _step2.value;
|
|
481
492
|
if (factory.showInViewMode) {
|
|
482
|
-
var
|
|
483
|
-
var old = decorations.find((
|
|
493
|
+
var _activeNode0, _activeNode1;
|
|
494
|
+
var old = decorations.find((_activeNode0 = activeNode) === null || _activeNode0 === void 0 ? void 0 : _activeNode0.rootPos, (_activeNode1 = activeNode) === null || _activeNode1 === void 0 ? void 0 : _activeNode1.rootPos, function (spec) {
|
|
484
495
|
return spec.type === factory.type;
|
|
485
496
|
});
|
|
486
497
|
decorations = decorations.remove(old);
|
|
@@ -497,10 +508,10 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
|
|
|
497
508
|
}
|
|
498
509
|
}
|
|
499
510
|
} else if (api) {
|
|
500
|
-
var _latestActiveNode5,
|
|
511
|
+
var _latestActiveNode5, _latestActiveNode10;
|
|
501
512
|
if (shouldRecreateHandle && (!rightSideControlsEnabled || !isViewMode)) {
|
|
502
|
-
var
|
|
503
|
-
var _oldHandle = (0, _decorationsDragHandle.findHandleDec)(decorations, (
|
|
513
|
+
var _activeNode12, _activeNode13, _latestActiveNode, _latestActiveNode2, _latestActiveNode3, _latestActiveNode4;
|
|
514
|
+
var _oldHandle = (0, _decorationsDragHandle.findHandleDec)(decorations, (_activeNode12 = activeNode) === null || _activeNode12 === void 0 ? void 0 : _activeNode12.pos, (_activeNode13 = activeNode) === null || _activeNode13 === void 0 ? void 0 : _activeNode13.pos);
|
|
504
515
|
decorations = decorations.remove(_oldHandle);
|
|
505
516
|
var handleDec = (0, _decorationsDragHandle.dragHandleDecoration)({
|
|
506
517
|
api: api,
|
|
@@ -514,12 +525,44 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
|
|
|
514
525
|
editorState: newState
|
|
515
526
|
});
|
|
516
527
|
decorations = decorations.add(newState.doc, [handleDec]);
|
|
528
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_controls_reliable_anchor', 'isEnabled', true)) {
|
|
529
|
+
// Recreate the drag handle node decoration when the edit-mode node itself changed
|
|
530
|
+
// or its content was modified. Other triggers (editorSizeChanged, handleNeedsRedraw)
|
|
531
|
+
// don't move the decoration — DecorationSet.map() already remaps it correctly.
|
|
532
|
+
var needsNodeDecUpdate = activeNodeChanged || isActiveNodeModified;
|
|
533
|
+
if (needsNodeDecUpdate) {
|
|
534
|
+
var _newState$doc$nodeAt;
|
|
535
|
+
var nodeSize = (_newState$doc$nodeAt = newState.doc.nodeAt(latestActiveNode.pos)) === null || _newState$doc$nodeAt === void 0 ? void 0 : _newState$doc$nodeAt.nodeSize;
|
|
536
|
+
if (nodeSize !== undefined) {
|
|
537
|
+
var _activeNode14, _activeNode15;
|
|
538
|
+
var _oldActiveNodeDec = (0, _decorationsDragHandle.findActiveDragHandleNodeDec)(decorations, (_activeNode14 = activeNode) === null || _activeNode14 === void 0 ? void 0 : _activeNode14.pos, (_activeNode15 = activeNode) === null || _activeNode15 === void 0 ? void 0 : _activeNode15.pos);
|
|
539
|
+
decorations = decorations.remove(_oldActiveNodeDec);
|
|
540
|
+
decorations = decorations.add(newState.doc, [(0, _decorationsDragHandle.createActiveDragHandleNodeDecoration)(latestActiveNode.pos, nodeSize)]);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// The quick-insert decoration lives on the root node (rootPos), which can change
|
|
545
|
+
// independently of the edit-mode node — e.g. when only editorSizeChanged fires but
|
|
546
|
+
// rootActiveNodeChanged is also true. So we use a separate, broader guard that
|
|
547
|
+
// includes rootActiveNodeChanged to avoid leaving the attribute on a stale root node.
|
|
548
|
+
var needsQuickInsertDecUpdate = activeNodeChanged || isActiveNodeModified || rootActiveNodeChanged;
|
|
549
|
+
if (needsQuickInsertDecUpdate && latestActiveNode.rootPos !== undefined) {
|
|
550
|
+
var _newState$doc$nodeAt2;
|
|
551
|
+
var rootNodeSize = (_newState$doc$nodeAt2 = newState.doc.nodeAt(latestActiveNode.rootPos)) === null || _newState$doc$nodeAt2 === void 0 ? void 0 : _newState$doc$nodeAt2.nodeSize;
|
|
552
|
+
if (rootNodeSize !== undefined) {
|
|
553
|
+
var _activeNode16, _activeNode17;
|
|
554
|
+
var _oldActiveQuickInsertDec = (0, _decorationsQuickInsertButton.findActiveQuickInsertNodeDec)(decorations, (_activeNode16 = activeNode) === null || _activeNode16 === void 0 ? void 0 : _activeNode16.rootPos, (_activeNode17 = activeNode) === null || _activeNode17 === void 0 ? void 0 : _activeNode17.rootPos);
|
|
555
|
+
decorations = decorations.remove(_oldActiveQuickInsertDec);
|
|
556
|
+
decorations = decorations.add(newState.doc, [(0, _decorationsQuickInsertButton.createActiveQuickInsertNodeDecoration)(latestActiveNode.rootPos, rootNodeSize)]);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
517
560
|
}
|
|
518
561
|
if (shouldRecreateQuickInsertButton && ((_latestActiveNode5 = latestActiveNode) === null || _latestActiveNode5 === void 0 ? void 0 : _latestActiveNode5.rootPos) !== undefined &&
|
|
519
562
|
// platform_editor_controls note: enables quick insert
|
|
520
563
|
flags.toolbarFlagsEnabled && quickInsertButtonEnabled && (!rightSideControlsEnabled || !isViewMode)) {
|
|
521
|
-
var
|
|
522
|
-
var _oldQuickInsertButton = (0, _decorationsQuickInsertButton.findQuickInsertInsertButtonDecoration)(decorations, (
|
|
564
|
+
var _activeNode18, _activeNode19, _latestActiveNode6, _latestActiveNode7, _latestActiveNode8, _latestActiveNode9, _latestActiveNode0, _latestActiveNode1;
|
|
565
|
+
var _oldQuickInsertButton = (0, _decorationsQuickInsertButton.findQuickInsertInsertButtonDecoration)(decorations, (_activeNode18 = activeNode) === null || _activeNode18 === void 0 ? void 0 : _activeNode18.rootPos, (_activeNode19 = activeNode) === null || _activeNode19 === void 0 ? void 0 : _activeNode19.rootPos);
|
|
523
566
|
decorations = decorations.remove(_oldQuickInsertButton);
|
|
524
567
|
var quickInsertButton = (0, _decorationsQuickInsertButton.quickInsertButtonDecoration)({
|
|
525
568
|
api: api,
|
|
@@ -534,12 +577,27 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
|
|
|
534
577
|
editorState: newState
|
|
535
578
|
});
|
|
536
579
|
decorations = decorations.add(newState.doc, [quickInsertButton]);
|
|
580
|
+
|
|
581
|
+
// Update quick insert node decoration when the quick insert button is recreated but
|
|
582
|
+
// the drag handle was NOT recreated (shouldRecreateHandle was false). When
|
|
583
|
+
// shouldRecreateHandle is true, the block above already handles this.
|
|
584
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_controls_reliable_anchor', 'isEnabled', true) && !shouldRecreateHandle && ((_latestActiveNode1 = latestActiveNode) === null || _latestActiveNode1 === void 0 ? void 0 : _latestActiveNode1.rootPos) !== undefined) {
|
|
585
|
+
var _activeNode20, _newState$doc$nodeAt3;
|
|
586
|
+
if (((_activeNode20 = activeNode) === null || _activeNode20 === void 0 ? void 0 : _activeNode20.rootPos) !== undefined) {
|
|
587
|
+
var _oldActiveQuickInsertDec2 = (0, _decorationsQuickInsertButton.findActiveQuickInsertNodeDec)(decorations, activeNode.rootPos, activeNode.rootPos);
|
|
588
|
+
decorations = decorations.remove(_oldActiveQuickInsertDec2);
|
|
589
|
+
}
|
|
590
|
+
var _rootNodeSize = (_newState$doc$nodeAt3 = newState.doc.nodeAt(latestActiveNode.rootPos)) === null || _newState$doc$nodeAt3 === void 0 ? void 0 : _newState$doc$nodeAt3.nodeSize;
|
|
591
|
+
if (_rootNodeSize !== undefined) {
|
|
592
|
+
decorations = decorations.add(newState.doc, [(0, _decorationsQuickInsertButton.createActiveQuickInsertNodeDecoration)(latestActiveNode.rootPos, _rootNodeSize)]);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
537
595
|
if (rightSideControlsEnabled) {
|
|
538
596
|
var _iterator3 = _createForOfIteratorHelper(nodeDecorationRegistry),
|
|
539
597
|
_step3;
|
|
540
598
|
try {
|
|
541
599
|
var _loop3 = function _loop3() {
|
|
542
|
-
var
|
|
600
|
+
var _activeNode21, _activeNode22;
|
|
543
601
|
var factory = _step3.value;
|
|
544
602
|
if (!latestActiveNode || latestActiveNode.rootPos === undefined) {
|
|
545
603
|
return 0; // continue
|
|
@@ -553,7 +611,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
|
|
|
553
611
|
rootAnchorName: latestActiveNode.rootAnchorName,
|
|
554
612
|
rootNodeType: latestActiveNode.rootNodeType
|
|
555
613
|
};
|
|
556
|
-
var old = decorations.find((
|
|
614
|
+
var old = decorations.find((_activeNode21 = activeNode) === null || _activeNode21 === void 0 ? void 0 : _activeNode21.rootPos, (_activeNode22 = activeNode) === null || _activeNode22 === void 0 ? void 0 : _activeNode22.rootPos, function (spec) {
|
|
557
615
|
return spec.type === factory.type;
|
|
558
616
|
});
|
|
559
617
|
decorations = decorations.remove(old);
|
|
@@ -598,7 +656,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
|
|
|
598
656
|
}
|
|
599
657
|
|
|
600
658
|
// In view mode (edit/live pages), show right-side controls on block hover (without drag handle or quick insert)
|
|
601
|
-
var rootPos = (
|
|
659
|
+
var rootPos = (_latestActiveNode10 = latestActiveNode) === null || _latestActiveNode10 === void 0 ? void 0 : _latestActiveNode10.rootPos;
|
|
602
660
|
// rootPos is computed using the same logic as the floating insert menu, so it always points to a top-level (doc child) block when defined.
|
|
603
661
|
var isDocLevel = rootPos !== undefined && !isNaN(rootPos);
|
|
604
662
|
if (isViewMode && isDocLevel && flags.toolbarFlagsEnabled && rightSideControlsEnabled) {
|
|
@@ -719,15 +777,15 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
|
|
|
719
777
|
var newActiveNode;
|
|
720
778
|
// platform_editor_controls note: enables quick insert
|
|
721
779
|
if (flags.toolbarFlagsEnabled) {
|
|
722
|
-
var
|
|
780
|
+
var _latestActiveNode11, _latestActiveNode12;
|
|
723
781
|
// remove isEmptyDoc check and let decorations render and determine their own visibility
|
|
724
782
|
// In view mode with right-side controls we render node decorations (right-edge button), not the
|
|
725
783
|
// handle - so findHandleDec is always empty. Don't clear activeNode in that case.
|
|
726
|
-
var hasHandleOrViewModeControls = (0, _decorationsDragHandle.findHandleDec)(decorations, (
|
|
784
|
+
var hasHandleOrViewModeControls = (0, _decorationsDragHandle.findHandleDec)(decorations, (_latestActiveNode11 = latestActiveNode) === null || _latestActiveNode11 === void 0 ? void 0 : _latestActiveNode11.pos, (_latestActiveNode12 = latestActiveNode) === null || _latestActiveNode12 === void 0 ? void 0 : _latestActiveNode12.pos).length > 0 || isViewMode && rightSideControlsEnabled;
|
|
727
785
|
newActiveNode = meta !== null && meta !== void 0 && meta.editorBlurred || !(meta !== null && meta !== void 0 && meta.activeNode) && !hasHandleOrViewModeControls ? null : latestActiveNode;
|
|
728
786
|
} else {
|
|
729
|
-
var
|
|
730
|
-
newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) && (0, _decorationsDragHandle.findHandleDec)(decorations, (
|
|
787
|
+
var _latestActiveNode13, _latestActiveNode14;
|
|
788
|
+
newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) && (0, _decorationsDragHandle.findHandleDec)(decorations, (_latestActiveNode13 = latestActiveNode) === null || _latestActiveNode13 === void 0 ? void 0 : _latestActiveNode13.pos, (_latestActiveNode14 = latestActiveNode) === null || _latestActiveNode14 === void 0 ? void 0 : _latestActiveNode14.pos).length === 0 ? null : latestActiveNode;
|
|
731
789
|
}
|
|
732
790
|
var isMenuOpenNew = isMenuOpen;
|
|
733
791
|
if ((0, _experiments.editorExperiment)('platform_editor_block_menu', true)) {
|
package/dist/cjs/ui/consts.js
CHANGED
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.topPositionAdjustment = exports.spacingBetweenNodesForPreview = exports.spaceLookupMap = exports.rootElementGap = exports.nodeMargins = exports.getNestedNodeLeftPaddingMargin = exports.dropTargetMarginMap = exports.dragHandleGap = exports.STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER = exports.STICKY_CONTROLS_TOP_MARGIN = exports.QUICK_INSERT_WIDTH = exports.QUICK_INSERT_LEFT_OFFSET = exports.QUICK_INSERT_HEIGHT = exports.QUICK_INSERT_DIMENSIONS = exports.DRAG_HANDLE_ZINDEX = exports.DRAG_HANDLE_WRAPPED_MEDIA_EMBED_TOP_ADJUSTMENT = exports.DRAG_HANDLE_SYNCED_BLOCK_GAP = exports.DRAG_HANDLE_PARAGRAPH_TOP_ADJUSTMENT = exports.DRAG_HANDLE_PARAGRAPH_SMALL_TOP_ADJUSTMENT = exports.DRAG_HANDLE_NARROW_GAP = exports.DRAG_HANDLE_MAX_WIDTH_PLUS_GAP = exports.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH = exports.DRAG_HANDLE_MAX_GAP = exports.DRAG_HANDLE_LAYOUT_SECTION_TOP_ADJUSTMENT = exports.DRAG_HANDLE_HEIGHT = exports.DRAG_HANDLE_H6_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H5_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H4_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H3_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H2_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H1_TOP_ADJUSTMENT = exports.DRAG_HANDLE_DIVIDER_TOP_ADJUSTMENT = exports.DRAG_HANDLE_DEFAULT_GAP = exports.DRAG_HANDLE_BORDER_RADIUS = exports.DEFAULT_COLUMN_DISTRIBUTIONS = void 0;
|
|
7
|
+
exports.topPositionAdjustment = exports.spacingBetweenNodesForPreview = exports.spaceLookupMap = exports.rootElementGap = exports.nodeMargins = exports.getNestedNodeLeftPaddingMargin = exports.dropTargetMarginMap = exports.dragHandleGap = exports.STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER = exports.STICKY_CONTROLS_TOP_MARGIN = exports.QUICK_INSERT_WIDTH = exports.QUICK_INSERT_LEFT_OFFSET = exports.QUICK_INSERT_HEIGHT = exports.QUICK_INSERT_DIMENSIONS = exports.DRAG_HANDLE_ZINDEX = exports.DRAG_HANDLE_WRAPPED_MEDIA_EMBED_TOP_ADJUSTMENT = exports.DRAG_HANDLE_SYNCED_BLOCK_GAP = exports.DRAG_HANDLE_PARAGRAPH_TOP_ADJUSTMENT = exports.DRAG_HANDLE_PARAGRAPH_SMALL_TOP_ADJUSTMENT = exports.DRAG_HANDLE_NARROW_GAP = exports.DRAG_HANDLE_MAX_WIDTH_PLUS_GAP = exports.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH = exports.DRAG_HANDLE_MAX_GAP = exports.DRAG_HANDLE_LAYOUT_SECTION_TOP_ADJUSTMENT = exports.DRAG_HANDLE_HEIGHT = exports.DRAG_HANDLE_H6_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H5_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H4_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H3_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H2_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H1_TOP_ADJUSTMENT = exports.DRAG_HANDLE_DIVIDER_TOP_ADJUSTMENT = exports.DRAG_HANDLE_DEFAULT_GAP = exports.DRAG_HANDLE_BORDER_RADIUS = exports.DEFAULT_COLUMN_DISTRIBUTIONS = exports.ACTIVE_QUICK_INSERT_ATTR = exports.ACTIVE_DRAG_HANDLE_ATTR = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _styles = require("@atlaskit/editor-common/styles");
|
|
10
10
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
@@ -12,6 +12,8 @@ var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
|
|
|
12
12
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
13
13
|
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
14
14
|
var _dropTargetMarginMap;
|
|
15
|
+
var ACTIVE_DRAG_HANDLE_ATTR = exports.ACTIVE_DRAG_HANDLE_ATTR = 'data-active-drag-handle';
|
|
16
|
+
var ACTIVE_QUICK_INSERT_ATTR = exports.ACTIVE_QUICK_INSERT_ATTR = 'data-active-quick-insert';
|
|
15
17
|
var DRAG_HANDLE_HEIGHT = exports.DRAG_HANDLE_HEIGHT = 24;
|
|
16
18
|
var DRAG_HANDLE_BORDER_RADIUS = exports.DRAG_HANDLE_BORDER_RADIUS = 4;
|
|
17
19
|
var DRAG_HANDLE_ZINDEX = exports.DRAG_HANDLE_ZINDEX = _editorSharedStyles.akRichMediaResizeZIndex + _editorSharedStyles.akEditorUnitZIndex; //place above legacy resizer
|
|
@@ -827,6 +827,15 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
|
|
|
827
827
|
anchorName: anchorName
|
|
828
828
|
}) : anchorName;
|
|
829
829
|
var dom = view.dom.querySelector("[".concat((0, _domAttrName.getAnchorAttrName)(), "=\"").concat(safeAnchorName, "\"]"));
|
|
830
|
+
|
|
831
|
+
// Defence-in-depth guard: since the node decoration sets data-active-drag-handle on the
|
|
832
|
+
// active node, we check for it directly. This is a cheap DOM attribute read (no reflow,
|
|
833
|
+
// no style recalculation) and hides the control if the decoration hasn't been applied yet.
|
|
834
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_controls_reliable_anchor', 'isEnabled', true) && !(dom !== null && dom !== void 0 && dom.hasAttribute(_consts2.ACTIVE_DRAG_HANDLE_ATTR))) {
|
|
835
|
+
return {
|
|
836
|
+
display: 'none'
|
|
837
|
+
};
|
|
838
|
+
}
|
|
830
839
|
var hasResizer = nodeType === 'table' || nodeType === 'mediaSingle';
|
|
831
840
|
var isExtension = nodeType === 'extension' || nodeType === 'bodiedExtension' || nodeType === 'multiBodiedExtension' && (0, _platformFeatureFlags.fg)('confluence_frontend_native_tabs_extension');
|
|
832
841
|
var isBlockCard = nodeType === 'blockCard' && !!blockCardWidth;
|
|
@@ -363,6 +363,18 @@ var dragHandlerAnchorStyles = (0, _react.css)({
|
|
|
363
363
|
})
|
|
364
364
|
}
|
|
365
365
|
});
|
|
366
|
+
var activeControlsSelector = "[".concat(_consts.ACTIVE_DRAG_HANDLE_ATTR, "], [").concat(_consts.ACTIVE_QUICK_INSERT_ATTR, "]");
|
|
367
|
+
|
|
368
|
+
// Applies anchor-name via node decoration attributes rather than adjacency CSS selectors.
|
|
369
|
+
// This is more reliable than dragHandlerAnchorStyles which depends on DOM structure.
|
|
370
|
+
// Only nodes decorated with data-active-drag-handle / data-active-quick-insert get anchor-name.
|
|
371
|
+
var staticControlsAnchorStyles = (0, _react.css)({
|
|
372
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
|
|
373
|
+
'.ProseMirror': (0, _defineProperty2.default)({}, activeControlsSelector, {
|
|
374
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
|
|
375
|
+
anchorName: "var(".concat(_styles.ANCHOR_VARIABLE_NAME, ", attr(data-node-anchor type(<custom-ident>)))")
|
|
376
|
+
})
|
|
377
|
+
});
|
|
366
378
|
|
|
367
379
|
// Styles applied to nodes with anchors when dragging
|
|
368
380
|
var dragAnchorStyles = (0, _react.css)({
|
|
@@ -411,6 +423,6 @@ var GlobalStylesWrapper = exports.GlobalStylesWrapper = function GlobalStylesWra
|
|
|
411
423
|
exposure: true
|
|
412
424
|
}) ? (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? extendHoverZoneReducedNext : extendHoverZoneReduced : undefined,
|
|
413
425
|
// platform_editor_controls note: this allows drag handles to render on empty lines
|
|
414
|
-
toolbarFlagsEnabled ? undefined : withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, (0, _experiments.editorExperiment)('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withRelativePosStyleNext : withRelativePosStyle, topLevelNodeMarginStyles, (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withAnchorNameZindexStyleNext : withAnchorNameZindexStyle, (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) && (0, _expValEquals.expValEquals)('advanced_layouts', 'isEnabled', true) ? layoutColumnExtendedHoverZone : layoutColumnWithoutHoverZone, shouldRenderAnchors && (isDragging ? dragAnchorStyles : dragHandlerAnchorStyles)]
|
|
426
|
+
toolbarFlagsEnabled ? undefined : withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, (0, _experiments.editorExperiment)('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withRelativePosStyleNext : withRelativePosStyle, topLevelNodeMarginStyles, (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withAnchorNameZindexStyleNext : withAnchorNameZindexStyle, (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) && (0, _expValEquals.expValEquals)('advanced_layouts', 'isEnabled', true) ? layoutColumnExtendedHoverZone : layoutColumnWithoutHoverZone, shouldRenderAnchors && (isDragging ? dragAnchorStyles : dragHandlerAnchorStyles), (0, _expValEquals.expValEquals)('platform_editor_controls_reliable_anchor', 'isEnabled', true) ? staticControlsAnchorStyles : undefined]
|
|
415
427
|
});
|
|
416
428
|
};
|
|
@@ -190,6 +190,14 @@ var TypeAheadControl = exports.TypeAheadControl = function TypeAheadControl(_ref
|
|
|
190
190
|
anchorName: rootAnchorName
|
|
191
191
|
});
|
|
192
192
|
var dom = view.dom.querySelector("[".concat((0, _domAttrName.getAnchorAttrName)(), "=\"").concat(safeAnchorName, "\"]"));
|
|
193
|
+
|
|
194
|
+
// Defence-in-depth guard: the node decoration sets data-active-quick-insert on the
|
|
195
|
+
// active root node. Check for it directly — cheap DOM attribute read, no reflow.
|
|
196
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_controls_reliable_anchor', 'isEnabled', true) && !(dom !== null && dom !== void 0 && dom.hasAttribute(_consts.ACTIVE_QUICK_INSERT_ATTR))) {
|
|
197
|
+
return {
|
|
198
|
+
display: 'none'
|
|
199
|
+
};
|
|
200
|
+
}
|
|
193
201
|
var hasResizer = rootNodeType === 'table' || rootNodeType === 'mediaSingle';
|
|
194
202
|
var isExtension = rootNodeType === 'extension' || rootNodeType === 'bodiedExtension' || rootNodeType === 'multiBodiedExtension' && (0, _platformFeatureFlags.fg)('confluence_frontend_native_tabs_extension');
|
|
195
203
|
var isBlockCard = rootNodeType === 'blockCard';
|
|
@@ -7,9 +7,23 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
|
7
7
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
8
8
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
9
9
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
10
|
+
import { ACTIVE_DRAG_HANDLE_ATTR } from '../ui/consts';
|
|
10
11
|
import { DragHandle, DragHandleWithVisibility } from '../ui/drag-handle';
|
|
11
12
|
import { TYPE_HANDLE_DEC, TYPE_NODE_DEC, unmountDecorations } from './decorations-common';
|
|
12
13
|
import { getActiveBlockMarks, getMatchingBlockMarks } from './utils/marks';
|
|
14
|
+
const TYPE_ACTIVE_HANDLE_DEC = 'active-drag-handle-node';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a Decoration.node that marks the active node with `data-active-drag-handle="true"`.
|
|
18
|
+
* The CSS in staticControlsAnchorStyles then applies `anchor-name` to this attribute,
|
|
19
|
+
* which is more reliable than the adjacency-selector approach in dragHandlerAnchorStyles.
|
|
20
|
+
*/
|
|
21
|
+
export const createActiveDragHandleNodeDecoration = (pos, nodeSize) => Decoration.node(pos, pos + nodeSize, {
|
|
22
|
+
[ACTIVE_DRAG_HANDLE_ATTR]: 'true'
|
|
23
|
+
}, {
|
|
24
|
+
type: TYPE_ACTIVE_HANDLE_DEC
|
|
25
|
+
});
|
|
26
|
+
export const findActiveDragHandleNodeDec = (decorations, from, to) => decorations.find(from, to, spec => spec.type === TYPE_ACTIVE_HANDLE_DEC);
|
|
13
27
|
export const emptyParagraphNodeDecorations = () => {
|
|
14
28
|
const anchorName = `--node-anchor-paragraph-0`;
|
|
15
29
|
const style = `anchor-name: ${anchorName}; margin-top: 0px;`;
|
|
@@ -5,12 +5,25 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
|
5
5
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
6
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
7
7
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
8
|
+
import { ACTIVE_QUICK_INSERT_ATTR } from '../ui/consts';
|
|
8
9
|
import { QuickInsertWithVisibility } from '../ui/quick-insert-button';
|
|
9
10
|
import { getActiveBlockMarks, getMatchingBlockMarks } from './utils/marks';
|
|
10
11
|
const TYPE_QUICK_INSERT = 'INSERT_BUTTON';
|
|
12
|
+
const TYPE_ACTIVE_QUICK_INSERT_NODE = 'active-quick-insert-node';
|
|
11
13
|
export const findQuickInsertInsertButtonDecoration = (decorations, from, to) => {
|
|
12
14
|
return decorations.find(from, to, spec => spec.type === TYPE_QUICK_INSERT);
|
|
13
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* Creates a Decoration.node that marks the active node with `data-active-quick-insert="true"`.
|
|
18
|
+
* The CSS in staticControlsAnchorStyles applies `anchor-name` to this attribute directly,
|
|
19
|
+
* replacing the unreliable adjacency selector `[block-ctrl-quick-insert-button] + *`.
|
|
20
|
+
*/
|
|
21
|
+
export const createActiveQuickInsertNodeDecoration = (pos, nodeSize) => Decoration.node(pos, pos + nodeSize, {
|
|
22
|
+
[ACTIVE_QUICK_INSERT_ATTR]: 'true'
|
|
23
|
+
}, {
|
|
24
|
+
type: TYPE_ACTIVE_QUICK_INSERT_NODE
|
|
25
|
+
});
|
|
26
|
+
export const findActiveQuickInsertNodeDec = (decorations, from, to) => decorations.find(from, to, spec => spec.type === TYPE_ACTIVE_QUICK_INSERT_NODE);
|
|
14
27
|
export const quickInsertButtonDecoration = ({
|
|
15
28
|
api,
|
|
16
29
|
formatMessage,
|
|
@@ -19,10 +19,10 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
|
19
19
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
20
20
|
import { getAnchorAttrName } from '../ui/utils/dom-attr-name';
|
|
21
21
|
import { findNodeDecs, nodeDecorations } from './decorations-anchor';
|
|
22
|
-
import { dragHandleDecoration, emptyParagraphNodeDecorations, findHandleDec } from './decorations-drag-handle';
|
|
22
|
+
import { createActiveDragHandleNodeDecoration, dragHandleDecoration, emptyParagraphNodeDecorations, findActiveDragHandleNodeDec, findHandleDec } from './decorations-drag-handle';
|
|
23
23
|
import { dropTargetDecorations, findDropTargetDecs } from './decorations-drop-target';
|
|
24
24
|
import { getActiveDropTargetDecorations } from './decorations-drop-target-active';
|
|
25
|
-
import { findQuickInsertInsertButtonDecoration, quickInsertButtonDecoration } from './decorations-quick-insert-button';
|
|
25
|
+
import { createActiveQuickInsertNodeDecoration, findActiveQuickInsertNodeDec, findQuickInsertInsertButtonDecoration, quickInsertButtonDecoration } from './decorations-quick-insert-button';
|
|
26
26
|
import { handleMouseDown } from './handle-mouse-down';
|
|
27
27
|
import { handleMouseOver } from './handle-mouse-over';
|
|
28
28
|
import { boundKeydownHandler } from './keymap';
|
|
@@ -435,34 +435,45 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
435
435
|
}
|
|
436
436
|
}
|
|
437
437
|
if (shouldRemoveHandle) {
|
|
438
|
-
var _activeNode5, _activeNode6;
|
|
438
|
+
var _activeNode5, _activeNode6, _activeNode7;
|
|
439
439
|
const oldHandle = findHandleDec(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
|
|
440
440
|
decorations = decorations.remove(oldHandle);
|
|
441
|
+
// When removing the handle, also remove the anchor-marker node decorations
|
|
442
|
+
// (data-active-drag-handle / data-active-quick-insert) so the DOM attributes
|
|
443
|
+
// don't linger on nodes that are no longer active.
|
|
444
|
+
if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) && ((_activeNode7 = activeNode) === null || _activeNode7 === void 0 ? void 0 : _activeNode7.pos) !== undefined) {
|
|
445
|
+
const oldActiveNodeDec = findActiveDragHandleNodeDec(decorations, activeNode.pos, activeNode.pos);
|
|
446
|
+
decorations = decorations.remove(oldActiveNodeDec);
|
|
447
|
+
if (activeNode.rootPos !== undefined) {
|
|
448
|
+
const oldActiveQuickInsertDec = findActiveQuickInsertNodeDec(decorations, activeNode.rootPos, activeNode.rootPos);
|
|
449
|
+
decorations = decorations.remove(oldActiveQuickInsertDec);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
441
452
|
// platform_editor_controls note: enables quick insert
|
|
442
453
|
if (flags.toolbarFlagsEnabled && quickInsertButtonEnabled) {
|
|
443
|
-
var
|
|
444
|
-
const oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (
|
|
454
|
+
var _activeNode8, _activeNode9;
|
|
455
|
+
const oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (_activeNode8 = activeNode) === null || _activeNode8 === void 0 ? void 0 : _activeNode8.rootPos, (_activeNode9 = activeNode) === null || _activeNode9 === void 0 ? void 0 : _activeNode9.rootPos);
|
|
445
456
|
decorations = decorations.remove(oldQuickInsertButton);
|
|
446
457
|
for (const factory of nodeDecorationRegistry) {
|
|
447
|
-
var
|
|
448
|
-
const old = decorations.find((
|
|
458
|
+
var _activeNode0, _activeNode1;
|
|
459
|
+
const old = decorations.find((_activeNode0 = activeNode) === null || _activeNode0 === void 0 ? void 0 : _activeNode0.rootPos, (_activeNode1 = activeNode) === null || _activeNode1 === void 0 ? void 0 : _activeNode1.rootPos, spec => spec.type === factory.type);
|
|
449
460
|
decorations = decorations.remove(old);
|
|
450
461
|
}
|
|
451
462
|
if (rightSideControlsEnabled && isViewMode && fg('confluence_remix_button_right_side_block_fg')) {
|
|
452
463
|
for (const factory of nodeDecorationRegistry) {
|
|
453
464
|
if (factory.showInViewMode) {
|
|
454
|
-
var
|
|
455
|
-
const old = decorations.find((
|
|
465
|
+
var _activeNode10, _activeNode11;
|
|
466
|
+
const old = decorations.find((_activeNode10 = activeNode) === null || _activeNode10 === void 0 ? void 0 : _activeNode10.rootPos, (_activeNode11 = activeNode) === null || _activeNode11 === void 0 ? void 0 : _activeNode11.rootPos, spec => spec.type === factory.type);
|
|
456
467
|
decorations = decorations.remove(old);
|
|
457
468
|
}
|
|
458
469
|
}
|
|
459
470
|
}
|
|
460
471
|
}
|
|
461
472
|
} else if (api) {
|
|
462
|
-
var _latestActiveNode5,
|
|
473
|
+
var _latestActiveNode5, _latestActiveNode10;
|
|
463
474
|
if (shouldRecreateHandle && (!rightSideControlsEnabled || !isViewMode)) {
|
|
464
|
-
var
|
|
465
|
-
const oldHandle = findHandleDec(decorations, (
|
|
475
|
+
var _activeNode12, _activeNode13, _latestActiveNode, _latestActiveNode2, _latestActiveNode3, _latestActiveNode4;
|
|
476
|
+
const oldHandle = findHandleDec(decorations, (_activeNode12 = activeNode) === null || _activeNode12 === void 0 ? void 0 : _activeNode12.pos, (_activeNode13 = activeNode) === null || _activeNode13 === void 0 ? void 0 : _activeNode13.pos);
|
|
466
477
|
decorations = decorations.remove(oldHandle);
|
|
467
478
|
const handleDec = dragHandleDecoration({
|
|
468
479
|
api,
|
|
@@ -476,12 +487,44 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
476
487
|
editorState: newState
|
|
477
488
|
});
|
|
478
489
|
decorations = decorations.add(newState.doc, [handleDec]);
|
|
490
|
+
if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true)) {
|
|
491
|
+
// Recreate the drag handle node decoration when the edit-mode node itself changed
|
|
492
|
+
// or its content was modified. Other triggers (editorSizeChanged, handleNeedsRedraw)
|
|
493
|
+
// don't move the decoration — DecorationSet.map() already remaps it correctly.
|
|
494
|
+
const needsNodeDecUpdate = activeNodeChanged || isActiveNodeModified;
|
|
495
|
+
if (needsNodeDecUpdate) {
|
|
496
|
+
var _newState$doc$nodeAt;
|
|
497
|
+
const nodeSize = (_newState$doc$nodeAt = newState.doc.nodeAt(latestActiveNode.pos)) === null || _newState$doc$nodeAt === void 0 ? void 0 : _newState$doc$nodeAt.nodeSize;
|
|
498
|
+
if (nodeSize !== undefined) {
|
|
499
|
+
var _activeNode14, _activeNode15;
|
|
500
|
+
const oldActiveNodeDec = findActiveDragHandleNodeDec(decorations, (_activeNode14 = activeNode) === null || _activeNode14 === void 0 ? void 0 : _activeNode14.pos, (_activeNode15 = activeNode) === null || _activeNode15 === void 0 ? void 0 : _activeNode15.pos);
|
|
501
|
+
decorations = decorations.remove(oldActiveNodeDec);
|
|
502
|
+
decorations = decorations.add(newState.doc, [createActiveDragHandleNodeDecoration(latestActiveNode.pos, nodeSize)]);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// The quick-insert decoration lives on the root node (rootPos), which can change
|
|
507
|
+
// independently of the edit-mode node — e.g. when only editorSizeChanged fires but
|
|
508
|
+
// rootActiveNodeChanged is also true. So we use a separate, broader guard that
|
|
509
|
+
// includes rootActiveNodeChanged to avoid leaving the attribute on a stale root node.
|
|
510
|
+
const needsQuickInsertDecUpdate = activeNodeChanged || isActiveNodeModified || rootActiveNodeChanged;
|
|
511
|
+
if (needsQuickInsertDecUpdate && latestActiveNode.rootPos !== undefined) {
|
|
512
|
+
var _newState$doc$nodeAt2;
|
|
513
|
+
const rootNodeSize = (_newState$doc$nodeAt2 = newState.doc.nodeAt(latestActiveNode.rootPos)) === null || _newState$doc$nodeAt2 === void 0 ? void 0 : _newState$doc$nodeAt2.nodeSize;
|
|
514
|
+
if (rootNodeSize !== undefined) {
|
|
515
|
+
var _activeNode16, _activeNode17;
|
|
516
|
+
const oldActiveQuickInsertDec = findActiveQuickInsertNodeDec(decorations, (_activeNode16 = activeNode) === null || _activeNode16 === void 0 ? void 0 : _activeNode16.rootPos, (_activeNode17 = activeNode) === null || _activeNode17 === void 0 ? void 0 : _activeNode17.rootPos);
|
|
517
|
+
decorations = decorations.remove(oldActiveQuickInsertDec);
|
|
518
|
+
decorations = decorations.add(newState.doc, [createActiveQuickInsertNodeDecoration(latestActiveNode.rootPos, rootNodeSize)]);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
479
522
|
}
|
|
480
523
|
if (shouldRecreateQuickInsertButton && ((_latestActiveNode5 = latestActiveNode) === null || _latestActiveNode5 === void 0 ? void 0 : _latestActiveNode5.rootPos) !== undefined &&
|
|
481
524
|
// platform_editor_controls note: enables quick insert
|
|
482
525
|
flags.toolbarFlagsEnabled && quickInsertButtonEnabled && (!rightSideControlsEnabled || !isViewMode)) {
|
|
483
|
-
var
|
|
484
|
-
const oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (
|
|
526
|
+
var _activeNode18, _activeNode19, _latestActiveNode6, _latestActiveNode7, _latestActiveNode8, _latestActiveNode9, _latestActiveNode0, _latestActiveNode1;
|
|
527
|
+
const oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (_activeNode18 = activeNode) === null || _activeNode18 === void 0 ? void 0 : _activeNode18.rootPos, (_activeNode19 = activeNode) === null || _activeNode19 === void 0 ? void 0 : _activeNode19.rootPos);
|
|
485
528
|
decorations = decorations.remove(oldQuickInsertButton);
|
|
486
529
|
const quickInsertButton = quickInsertButtonDecoration({
|
|
487
530
|
api,
|
|
@@ -496,9 +539,24 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
496
539
|
editorState: newState
|
|
497
540
|
});
|
|
498
541
|
decorations = decorations.add(newState.doc, [quickInsertButton]);
|
|
542
|
+
|
|
543
|
+
// Update quick insert node decoration when the quick insert button is recreated but
|
|
544
|
+
// the drag handle was NOT recreated (shouldRecreateHandle was false). When
|
|
545
|
+
// shouldRecreateHandle is true, the block above already handles this.
|
|
546
|
+
if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) && !shouldRecreateHandle && ((_latestActiveNode1 = latestActiveNode) === null || _latestActiveNode1 === void 0 ? void 0 : _latestActiveNode1.rootPos) !== undefined) {
|
|
547
|
+
var _activeNode20, _newState$doc$nodeAt3;
|
|
548
|
+
if (((_activeNode20 = activeNode) === null || _activeNode20 === void 0 ? void 0 : _activeNode20.rootPos) !== undefined) {
|
|
549
|
+
const oldActiveQuickInsertDec = findActiveQuickInsertNodeDec(decorations, activeNode.rootPos, activeNode.rootPos);
|
|
550
|
+
decorations = decorations.remove(oldActiveQuickInsertDec);
|
|
551
|
+
}
|
|
552
|
+
const rootNodeSize = (_newState$doc$nodeAt3 = newState.doc.nodeAt(latestActiveNode.rootPos)) === null || _newState$doc$nodeAt3 === void 0 ? void 0 : _newState$doc$nodeAt3.nodeSize;
|
|
553
|
+
if (rootNodeSize !== undefined) {
|
|
554
|
+
decorations = decorations.add(newState.doc, [createActiveQuickInsertNodeDecoration(latestActiveNode.rootPos, rootNodeSize)]);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
499
557
|
if (rightSideControlsEnabled) {
|
|
500
558
|
for (const factory of nodeDecorationRegistry) {
|
|
501
|
-
var
|
|
559
|
+
var _activeNode21, _activeNode22;
|
|
502
560
|
if (!latestActiveNode || latestActiveNode.rootPos === undefined) {
|
|
503
561
|
continue;
|
|
504
562
|
}
|
|
@@ -511,7 +569,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
511
569
|
rootAnchorName: latestActiveNode.rootAnchorName,
|
|
512
570
|
rootNodeType: latestActiveNode.rootNodeType
|
|
513
571
|
};
|
|
514
|
-
const old = decorations.find((
|
|
572
|
+
const old = decorations.find((_activeNode21 = activeNode) === null || _activeNode21 === void 0 ? void 0 : _activeNode21.rootPos, (_activeNode22 = activeNode) === null || _activeNode22 === void 0 ? void 0 : _activeNode22.rootPos, spec => spec.type === factory.type);
|
|
515
573
|
decorations = decorations.remove(old);
|
|
516
574
|
|
|
517
575
|
// determines whether to show the decorations, see malleableUiPlugin.tsx
|
|
@@ -530,7 +588,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
530
588
|
}
|
|
531
589
|
|
|
532
590
|
// In view mode (edit/live pages), show right-side controls on block hover (without drag handle or quick insert)
|
|
533
|
-
const rootPos = (
|
|
591
|
+
const rootPos = (_latestActiveNode10 = latestActiveNode) === null || _latestActiveNode10 === void 0 ? void 0 : _latestActiveNode10.rootPos;
|
|
534
592
|
// rootPos is computed using the same logic as the floating insert menu, so it always points to a top-level (doc child) block when defined.
|
|
535
593
|
const isDocLevel = rootPos !== undefined && !isNaN(rootPos);
|
|
536
594
|
if (isViewMode && isDocLevel && flags.toolbarFlagsEnabled && rightSideControlsEnabled) {
|
|
@@ -620,15 +678,15 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
620
678
|
let newActiveNode;
|
|
621
679
|
// platform_editor_controls note: enables quick insert
|
|
622
680
|
if (flags.toolbarFlagsEnabled) {
|
|
623
|
-
var
|
|
681
|
+
var _latestActiveNode11, _latestActiveNode12;
|
|
624
682
|
// remove isEmptyDoc check and let decorations render and determine their own visibility
|
|
625
683
|
// In view mode with right-side controls we render node decorations (right-edge button), not the
|
|
626
684
|
// handle - so findHandleDec is always empty. Don't clear activeNode in that case.
|
|
627
|
-
const hasHandleOrViewModeControls = findHandleDec(decorations, (
|
|
685
|
+
const hasHandleOrViewModeControls = findHandleDec(decorations, (_latestActiveNode11 = latestActiveNode) === null || _latestActiveNode11 === void 0 ? void 0 : _latestActiveNode11.pos, (_latestActiveNode12 = latestActiveNode) === null || _latestActiveNode12 === void 0 ? void 0 : _latestActiveNode12.pos).length > 0 || isViewMode && rightSideControlsEnabled;
|
|
628
686
|
newActiveNode = meta !== null && meta !== void 0 && meta.editorBlurred || !(meta !== null && meta !== void 0 && meta.activeNode) && !hasHandleOrViewModeControls ? null : latestActiveNode;
|
|
629
687
|
} else {
|
|
630
|
-
var
|
|
631
|
-
newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) && findHandleDec(decorations, (
|
|
688
|
+
var _latestActiveNode13, _latestActiveNode14;
|
|
689
|
+
newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) && findHandleDec(decorations, (_latestActiveNode13 = latestActiveNode) === null || _latestActiveNode13 === void 0 ? void 0 : _latestActiveNode13.pos, (_latestActiveNode14 = latestActiveNode) === null || _latestActiveNode14 === void 0 ? void 0 : _latestActiveNode14.pos).length === 0 ? null : latestActiveNode;
|
|
632
690
|
}
|
|
633
691
|
let isMenuOpenNew = isMenuOpen;
|
|
634
692
|
if (editorExperiment('platform_editor_block_menu', true)) {
|
package/dist/es2019/ui/consts.js
CHANGED
|
@@ -3,6 +3,8 @@ import { breakoutResizableNodes as breakoutResizableNodesNew } from '@atlaskit/e
|
|
|
3
3
|
import { akEditorUnitZIndex, akRichMediaResizeZIndex } from '@atlaskit/editor-shared-styles';
|
|
4
4
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
5
5
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
6
|
+
export const ACTIVE_DRAG_HANDLE_ATTR = 'data-active-drag-handle';
|
|
7
|
+
export const ACTIVE_QUICK_INSERT_ATTR = 'data-active-quick-insert';
|
|
6
8
|
export const DRAG_HANDLE_HEIGHT = 24;
|
|
7
9
|
export const DRAG_HANDLE_BORDER_RADIUS = 4;
|
|
8
10
|
export const DRAG_HANDLE_ZINDEX = akRichMediaResizeZIndex + akEditorUnitZIndex; //place above legacy resizer
|
|
@@ -35,7 +35,7 @@ import { getControlBottomCSSValue, getControlHeightCSSValue, getLeftPosition, ge
|
|
|
35
35
|
import { expandAndUpdateSelection } from '../pm-plugins/utils/expand-and-update-selection';
|
|
36
36
|
import { isHandleCorrelatedToSelection, selectNode } from '../pm-plugins/utils/getSelection';
|
|
37
37
|
import { alignAnchorHeadInDirectionOfPos, expandSelectionHeadToNodeAtPos } from '../pm-plugins/utils/selection';
|
|
38
|
-
import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH, DRAG_HANDLE_ZINDEX, dragHandleGap, nodeMargins, spacingBetweenNodesForPreview, STICKY_CONTROLS_TOP_MARGIN, STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER, topPositionAdjustment } from './consts';
|
|
38
|
+
import { ACTIVE_DRAG_HANDLE_ATTR, DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH, DRAG_HANDLE_ZINDEX, dragHandleGap, nodeMargins, spacingBetweenNodesForPreview, STICKY_CONTROLS_TOP_MARGIN, STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER, topPositionAdjustment } from './consts';
|
|
39
39
|
import { DragHandleNestedIcon } from './drag-handle-nested-icon';
|
|
40
40
|
import { dragPreview } from './drag-preview';
|
|
41
41
|
import { refreshAnchorName } from './utils/anchor-name';
|
|
@@ -807,6 +807,15 @@ export const DragHandle = ({
|
|
|
807
807
|
anchorName
|
|
808
808
|
}) : anchorName;
|
|
809
809
|
const dom = view.dom.querySelector(`[${getAnchorAttrName()}="${safeAnchorName}"]`);
|
|
810
|
+
|
|
811
|
+
// Defence-in-depth guard: since the node decoration sets data-active-drag-handle on the
|
|
812
|
+
// active node, we check for it directly. This is a cheap DOM attribute read (no reflow,
|
|
813
|
+
// no style recalculation) and hides the control if the decoration hasn't been applied yet.
|
|
814
|
+
if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) && !(dom !== null && dom !== void 0 && dom.hasAttribute(ACTIVE_DRAG_HANDLE_ATTR))) {
|
|
815
|
+
return {
|
|
816
|
+
display: 'none'
|
|
817
|
+
};
|
|
818
|
+
}
|
|
810
819
|
const hasResizer = nodeType === 'table' || nodeType === 'mediaSingle';
|
|
811
820
|
const isExtension = nodeType === 'extension' || nodeType === 'bodiedExtension' || nodeType === 'multiBodiedExtension' && fg('confluence_frontend_native_tabs_extension');
|
|
812
821
|
const isBlockCard = nodeType === 'blockCard' && !!blockCardWidth;
|
|
@@ -11,7 +11,7 @@ import { ZERO_WIDTH_SPACE } from '@atlaskit/editor-common/whitespace';
|
|
|
11
11
|
import { akEditorBreakoutPadding, akEditorCalculatedWideLayoutWidth, akEditorCalculatedWideLayoutWidthSmallViewport, akEditorFullPageNarrowBreakout, akEditorGutterPaddingDynamic, akEditorGutterPaddingReduced } from '@atlaskit/editor-shared-styles';
|
|
12
12
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
13
13
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
14
|
-
import { DRAG_HANDLE_MAX_WIDTH_PLUS_GAP } from './consts';
|
|
14
|
+
import { ACTIVE_DRAG_HANDLE_ATTR, ACTIVE_QUICK_INSERT_ATTR, DRAG_HANDLE_MAX_WIDTH_PLUS_GAP } from './consts';
|
|
15
15
|
import { NODE_ANCHOR_ATTR_NAME } from './utils/dom-attr-name';
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -449,6 +449,21 @@ const dragHandlerAnchorStyles = css({
|
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
451
|
});
|
|
452
|
+
const activeControlsSelector = `[${ACTIVE_DRAG_HANDLE_ATTR}], [${ACTIVE_QUICK_INSERT_ATTR}]`;
|
|
453
|
+
|
|
454
|
+
// Applies anchor-name via node decoration attributes rather than adjacency CSS selectors.
|
|
455
|
+
// This is more reliable than dragHandlerAnchorStyles which depends on DOM structure.
|
|
456
|
+
// Only nodes decorated with data-active-drag-handle / data-active-quick-insert get anchor-name.
|
|
457
|
+
const staticControlsAnchorStyles = css({
|
|
458
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
|
|
459
|
+
'.ProseMirror': {
|
|
460
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors, @atlaskit/ui-styling-standard/no-unsafe-values
|
|
461
|
+
[activeControlsSelector]: {
|
|
462
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
|
|
463
|
+
anchorName: `var(${ANCHOR_VARIABLE_NAME}, attr(data-node-anchor type(<custom-ident>)))`
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
});
|
|
452
467
|
|
|
453
468
|
// Styles applied to nodes with anchors when dragging
|
|
454
469
|
const dragAnchorStyles = css({
|
|
@@ -499,6 +514,6 @@ export const GlobalStylesWrapper = ({
|
|
|
499
514
|
exposure: true
|
|
500
515
|
}) ? expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? extendHoverZoneReducedNext : extendHoverZoneReduced : undefined,
|
|
501
516
|
// platform_editor_controls note: this allows drag handles to render on empty lines
|
|
502
|
-
toolbarFlagsEnabled ? undefined : withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, editorExperiment('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withRelativePosStyleNext : withRelativePosStyle, topLevelNodeMarginStyles, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withAnchorNameZindexStyleNext : withAnchorNameZindexStyle, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) && expValEquals('advanced_layouts', 'isEnabled', true) ? layoutColumnExtendedHoverZone : layoutColumnWithoutHoverZone, shouldRenderAnchors && (isDragging ? dragAnchorStyles : dragHandlerAnchorStyles)]
|
|
517
|
+
toolbarFlagsEnabled ? undefined : withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, editorExperiment('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withRelativePosStyleNext : withRelativePosStyle, topLevelNodeMarginStyles, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withAnchorNameZindexStyleNext : withAnchorNameZindexStyle, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) && expValEquals('advanced_layouts', 'isEnabled', true) ? layoutColumnExtendedHoverZone : layoutColumnWithoutHoverZone, shouldRenderAnchors && (isDragging ? dragAnchorStyles : dragHandlerAnchorStyles), expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) ? staticControlsAnchorStyles : undefined]
|
|
503
518
|
});
|
|
504
519
|
};
|
|
@@ -24,7 +24,7 @@ import Tooltip from '@atlaskit/tooltip';
|
|
|
24
24
|
import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
|
|
25
25
|
import { getControlBottomCSSValue, getControlHeightCSSValue, getNodeHeight, getTopPosition, shouldBeSticky } from '../pm-plugins/utils/drag-handle-positions';
|
|
26
26
|
import { getLeftPositionForRootElement } from '../pm-plugins/utils/widget-positions';
|
|
27
|
-
import { QUICK_INSERT_DIMENSIONS, QUICK_INSERT_HEIGHT, QUICK_INSERT_LEFT_OFFSET, QUICK_INSERT_WIDTH, rootElementGap, STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER, topPositionAdjustment } from './consts';
|
|
27
|
+
import { ACTIVE_QUICK_INSERT_ATTR, QUICK_INSERT_DIMENSIONS, QUICK_INSERT_HEIGHT, QUICK_INSERT_LEFT_OFFSET, QUICK_INSERT_WIDTH, rootElementGap, STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER, topPositionAdjustment } from './consts';
|
|
28
28
|
import { refreshAnchorName } from './utils/anchor-name';
|
|
29
29
|
import { isInTextSelection, isNestedNodeSelected, isNonEditableBlock, isSelectionInNode } from './utils/document-checks';
|
|
30
30
|
import { getAnchorAttrName } from './utils/dom-attr-name';
|
|
@@ -179,6 +179,14 @@ export const TypeAheadControl = ({
|
|
|
179
179
|
anchorName: rootAnchorName
|
|
180
180
|
});
|
|
181
181
|
const dom = view.dom.querySelector(`[${getAnchorAttrName()}="${safeAnchorName}"]`);
|
|
182
|
+
|
|
183
|
+
// Defence-in-depth guard: the node decoration sets data-active-quick-insert on the
|
|
184
|
+
// active root node. Check for it directly — cheap DOM attribute read, no reflow.
|
|
185
|
+
if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) && !(dom !== null && dom !== void 0 && dom.hasAttribute(ACTIVE_QUICK_INSERT_ATTR))) {
|
|
186
|
+
return {
|
|
187
|
+
display: 'none'
|
|
188
|
+
};
|
|
189
|
+
}
|
|
182
190
|
const hasResizer = rootNodeType === 'table' || rootNodeType === 'mediaSingle';
|
|
183
191
|
const isExtension = rootNodeType === 'extension' || rootNodeType === 'bodiedExtension' || rootNodeType === 'multiBodiedExtension' && fg('confluence_frontend_native_tabs_extension');
|
|
184
192
|
const isBlockCard = rootNodeType === 'blockCard';
|
|
@@ -8,9 +8,27 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
|
8
8
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
9
9
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
10
10
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
11
|
+
import { ACTIVE_DRAG_HANDLE_ATTR } from '../ui/consts';
|
|
11
12
|
import { DragHandle, DragHandleWithVisibility } from '../ui/drag-handle';
|
|
12
13
|
import { TYPE_HANDLE_DEC, TYPE_NODE_DEC, unmountDecorations } from './decorations-common';
|
|
13
14
|
import { getActiveBlockMarks, getMatchingBlockMarks } from './utils/marks';
|
|
15
|
+
var TYPE_ACTIVE_HANDLE_DEC = 'active-drag-handle-node';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Creates a Decoration.node that marks the active node with `data-active-drag-handle="true"`.
|
|
19
|
+
* The CSS in staticControlsAnchorStyles then applies `anchor-name` to this attribute,
|
|
20
|
+
* which is more reliable than the adjacency-selector approach in dragHandlerAnchorStyles.
|
|
21
|
+
*/
|
|
22
|
+
export var createActiveDragHandleNodeDecoration = function createActiveDragHandleNodeDecoration(pos, nodeSize) {
|
|
23
|
+
return Decoration.node(pos, pos + nodeSize, _defineProperty({}, ACTIVE_DRAG_HANDLE_ATTR, 'true'), {
|
|
24
|
+
type: TYPE_ACTIVE_HANDLE_DEC
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
export var findActiveDragHandleNodeDec = function findActiveDragHandleNodeDec(decorations, from, to) {
|
|
28
|
+
return decorations.find(from, to, function (spec) {
|
|
29
|
+
return spec.type === TYPE_ACTIVE_HANDLE_DEC;
|
|
30
|
+
});
|
|
31
|
+
};
|
|
14
32
|
export var emptyParagraphNodeDecorations = function emptyParagraphNodeDecorations() {
|
|
15
33
|
var anchorName = "--node-anchor-paragraph-0";
|
|
16
34
|
var style = "anchor-name: ".concat(anchorName, "; margin-top: 0px;");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
1
2
|
import { createElement } from 'react';
|
|
2
3
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
3
4
|
import uuid from 'uuid';
|
|
@@ -5,14 +6,31 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
|
5
6
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
7
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
7
8
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
9
|
+
import { ACTIVE_QUICK_INSERT_ATTR } from '../ui/consts';
|
|
8
10
|
import { QuickInsertWithVisibility } from '../ui/quick-insert-button';
|
|
9
11
|
import { getActiveBlockMarks, getMatchingBlockMarks } from './utils/marks';
|
|
10
12
|
var TYPE_QUICK_INSERT = 'INSERT_BUTTON';
|
|
13
|
+
var TYPE_ACTIVE_QUICK_INSERT_NODE = 'active-quick-insert-node';
|
|
11
14
|
export var findQuickInsertInsertButtonDecoration = function findQuickInsertInsertButtonDecoration(decorations, from, to) {
|
|
12
15
|
return decorations.find(from, to, function (spec) {
|
|
13
16
|
return spec.type === TYPE_QUICK_INSERT;
|
|
14
17
|
});
|
|
15
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* Creates a Decoration.node that marks the active node with `data-active-quick-insert="true"`.
|
|
21
|
+
* The CSS in staticControlsAnchorStyles applies `anchor-name` to this attribute directly,
|
|
22
|
+
* replacing the unreliable adjacency selector `[block-ctrl-quick-insert-button] + *`.
|
|
23
|
+
*/
|
|
24
|
+
export var createActiveQuickInsertNodeDecoration = function createActiveQuickInsertNodeDecoration(pos, nodeSize) {
|
|
25
|
+
return Decoration.node(pos, pos + nodeSize, _defineProperty({}, ACTIVE_QUICK_INSERT_ATTR, 'true'), {
|
|
26
|
+
type: TYPE_ACTIVE_QUICK_INSERT_NODE
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
export var findActiveQuickInsertNodeDec = function findActiveQuickInsertNodeDec(decorations, from, to) {
|
|
30
|
+
return decorations.find(from, to, function (spec) {
|
|
31
|
+
return spec.type === TYPE_ACTIVE_QUICK_INSERT_NODE;
|
|
32
|
+
});
|
|
33
|
+
};
|
|
16
34
|
export var quickInsertButtonDecoration = function quickInsertButtonDecoration(_ref) {
|
|
17
35
|
var api = _ref.api,
|
|
18
36
|
formatMessage = _ref.formatMessage,
|
|
@@ -25,10 +25,10 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
|
25
25
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
26
26
|
import { getAnchorAttrName } from '../ui/utils/dom-attr-name';
|
|
27
27
|
import { findNodeDecs, nodeDecorations } from './decorations-anchor';
|
|
28
|
-
import { dragHandleDecoration, emptyParagraphNodeDecorations, findHandleDec } from './decorations-drag-handle';
|
|
28
|
+
import { createActiveDragHandleNodeDecoration, dragHandleDecoration, emptyParagraphNodeDecorations, findActiveDragHandleNodeDec, findHandleDec } from './decorations-drag-handle';
|
|
29
29
|
import { dropTargetDecorations, findDropTargetDecs } from './decorations-drop-target';
|
|
30
30
|
import { getActiveDropTargetDecorations } from './decorations-drop-target-active';
|
|
31
|
-
import { findQuickInsertInsertButtonDecoration, quickInsertButtonDecoration } from './decorations-quick-insert-button';
|
|
31
|
+
import { createActiveQuickInsertNodeDecoration, findActiveQuickInsertNodeDec, findQuickInsertInsertButtonDecoration, quickInsertButtonDecoration } from './decorations-quick-insert-button';
|
|
32
32
|
import { handleMouseDown } from './handle-mouse-down';
|
|
33
33
|
import { handleMouseOver } from './handle-mouse-over';
|
|
34
34
|
import { boundKeydownHandler } from './keymap';
|
|
@@ -438,21 +438,32 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
|
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
if (shouldRemoveHandle) {
|
|
441
|
-
var _activeNode5, _activeNode6;
|
|
441
|
+
var _activeNode5, _activeNode6, _activeNode7;
|
|
442
442
|
var oldHandle = findHandleDec(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
|
|
443
443
|
decorations = decorations.remove(oldHandle);
|
|
444
|
+
// When removing the handle, also remove the anchor-marker node decorations
|
|
445
|
+
// (data-active-drag-handle / data-active-quick-insert) so the DOM attributes
|
|
446
|
+
// don't linger on nodes that are no longer active.
|
|
447
|
+
if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) && ((_activeNode7 = activeNode) === null || _activeNode7 === void 0 ? void 0 : _activeNode7.pos) !== undefined) {
|
|
448
|
+
var oldActiveNodeDec = findActiveDragHandleNodeDec(decorations, activeNode.pos, activeNode.pos);
|
|
449
|
+
decorations = decorations.remove(oldActiveNodeDec);
|
|
450
|
+
if (activeNode.rootPos !== undefined) {
|
|
451
|
+
var oldActiveQuickInsertDec = findActiveQuickInsertNodeDec(decorations, activeNode.rootPos, activeNode.rootPos);
|
|
452
|
+
decorations = decorations.remove(oldActiveQuickInsertDec);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
444
455
|
// platform_editor_controls note: enables quick insert
|
|
445
456
|
if (flags.toolbarFlagsEnabled && quickInsertButtonEnabled) {
|
|
446
|
-
var
|
|
447
|
-
var oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (
|
|
457
|
+
var _activeNode8, _activeNode9;
|
|
458
|
+
var oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (_activeNode8 = activeNode) === null || _activeNode8 === void 0 ? void 0 : _activeNode8.rootPos, (_activeNode9 = activeNode) === null || _activeNode9 === void 0 ? void 0 : _activeNode9.rootPos);
|
|
448
459
|
decorations = decorations.remove(oldQuickInsertButton);
|
|
449
460
|
var _iterator = _createForOfIteratorHelper(nodeDecorationRegistry),
|
|
450
461
|
_step;
|
|
451
462
|
try {
|
|
452
463
|
var _loop2 = function _loop2() {
|
|
453
|
-
var
|
|
464
|
+
var _activeNode10, _activeNode11;
|
|
454
465
|
var factory = _step.value;
|
|
455
|
-
var old = decorations.find((
|
|
466
|
+
var old = decorations.find((_activeNode10 = activeNode) === null || _activeNode10 === void 0 ? void 0 : _activeNode10.rootPos, (_activeNode11 = activeNode) === null || _activeNode11 === void 0 ? void 0 : _activeNode11.rootPos, function (spec) {
|
|
456
467
|
return spec.type === factory.type;
|
|
457
468
|
});
|
|
458
469
|
decorations = decorations.remove(old);
|
|
@@ -472,8 +483,8 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
|
|
|
472
483
|
var _loop = function _loop() {
|
|
473
484
|
var factory = _step2.value;
|
|
474
485
|
if (factory.showInViewMode) {
|
|
475
|
-
var
|
|
476
|
-
var old = decorations.find((
|
|
486
|
+
var _activeNode0, _activeNode1;
|
|
487
|
+
var old = decorations.find((_activeNode0 = activeNode) === null || _activeNode0 === void 0 ? void 0 : _activeNode0.rootPos, (_activeNode1 = activeNode) === null || _activeNode1 === void 0 ? void 0 : _activeNode1.rootPos, function (spec) {
|
|
477
488
|
return spec.type === factory.type;
|
|
478
489
|
});
|
|
479
490
|
decorations = decorations.remove(old);
|
|
@@ -490,10 +501,10 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
|
|
|
490
501
|
}
|
|
491
502
|
}
|
|
492
503
|
} else if (api) {
|
|
493
|
-
var _latestActiveNode5,
|
|
504
|
+
var _latestActiveNode5, _latestActiveNode10;
|
|
494
505
|
if (shouldRecreateHandle && (!rightSideControlsEnabled || !isViewMode)) {
|
|
495
|
-
var
|
|
496
|
-
var _oldHandle = findHandleDec(decorations, (
|
|
506
|
+
var _activeNode12, _activeNode13, _latestActiveNode, _latestActiveNode2, _latestActiveNode3, _latestActiveNode4;
|
|
507
|
+
var _oldHandle = findHandleDec(decorations, (_activeNode12 = activeNode) === null || _activeNode12 === void 0 ? void 0 : _activeNode12.pos, (_activeNode13 = activeNode) === null || _activeNode13 === void 0 ? void 0 : _activeNode13.pos);
|
|
497
508
|
decorations = decorations.remove(_oldHandle);
|
|
498
509
|
var handleDec = dragHandleDecoration({
|
|
499
510
|
api: api,
|
|
@@ -507,12 +518,44 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
|
|
|
507
518
|
editorState: newState
|
|
508
519
|
});
|
|
509
520
|
decorations = decorations.add(newState.doc, [handleDec]);
|
|
521
|
+
if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true)) {
|
|
522
|
+
// Recreate the drag handle node decoration when the edit-mode node itself changed
|
|
523
|
+
// or its content was modified. Other triggers (editorSizeChanged, handleNeedsRedraw)
|
|
524
|
+
// don't move the decoration — DecorationSet.map() already remaps it correctly.
|
|
525
|
+
var needsNodeDecUpdate = activeNodeChanged || isActiveNodeModified;
|
|
526
|
+
if (needsNodeDecUpdate) {
|
|
527
|
+
var _newState$doc$nodeAt;
|
|
528
|
+
var nodeSize = (_newState$doc$nodeAt = newState.doc.nodeAt(latestActiveNode.pos)) === null || _newState$doc$nodeAt === void 0 ? void 0 : _newState$doc$nodeAt.nodeSize;
|
|
529
|
+
if (nodeSize !== undefined) {
|
|
530
|
+
var _activeNode14, _activeNode15;
|
|
531
|
+
var _oldActiveNodeDec = findActiveDragHandleNodeDec(decorations, (_activeNode14 = activeNode) === null || _activeNode14 === void 0 ? void 0 : _activeNode14.pos, (_activeNode15 = activeNode) === null || _activeNode15 === void 0 ? void 0 : _activeNode15.pos);
|
|
532
|
+
decorations = decorations.remove(_oldActiveNodeDec);
|
|
533
|
+
decorations = decorations.add(newState.doc, [createActiveDragHandleNodeDecoration(latestActiveNode.pos, nodeSize)]);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// The quick-insert decoration lives on the root node (rootPos), which can change
|
|
538
|
+
// independently of the edit-mode node — e.g. when only editorSizeChanged fires but
|
|
539
|
+
// rootActiveNodeChanged is also true. So we use a separate, broader guard that
|
|
540
|
+
// includes rootActiveNodeChanged to avoid leaving the attribute on a stale root node.
|
|
541
|
+
var needsQuickInsertDecUpdate = activeNodeChanged || isActiveNodeModified || rootActiveNodeChanged;
|
|
542
|
+
if (needsQuickInsertDecUpdate && latestActiveNode.rootPos !== undefined) {
|
|
543
|
+
var _newState$doc$nodeAt2;
|
|
544
|
+
var rootNodeSize = (_newState$doc$nodeAt2 = newState.doc.nodeAt(latestActiveNode.rootPos)) === null || _newState$doc$nodeAt2 === void 0 ? void 0 : _newState$doc$nodeAt2.nodeSize;
|
|
545
|
+
if (rootNodeSize !== undefined) {
|
|
546
|
+
var _activeNode16, _activeNode17;
|
|
547
|
+
var _oldActiveQuickInsertDec = findActiveQuickInsertNodeDec(decorations, (_activeNode16 = activeNode) === null || _activeNode16 === void 0 ? void 0 : _activeNode16.rootPos, (_activeNode17 = activeNode) === null || _activeNode17 === void 0 ? void 0 : _activeNode17.rootPos);
|
|
548
|
+
decorations = decorations.remove(_oldActiveQuickInsertDec);
|
|
549
|
+
decorations = decorations.add(newState.doc, [createActiveQuickInsertNodeDecoration(latestActiveNode.rootPos, rootNodeSize)]);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
510
553
|
}
|
|
511
554
|
if (shouldRecreateQuickInsertButton && ((_latestActiveNode5 = latestActiveNode) === null || _latestActiveNode5 === void 0 ? void 0 : _latestActiveNode5.rootPos) !== undefined &&
|
|
512
555
|
// platform_editor_controls note: enables quick insert
|
|
513
556
|
flags.toolbarFlagsEnabled && quickInsertButtonEnabled && (!rightSideControlsEnabled || !isViewMode)) {
|
|
514
|
-
var
|
|
515
|
-
var _oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (
|
|
557
|
+
var _activeNode18, _activeNode19, _latestActiveNode6, _latestActiveNode7, _latestActiveNode8, _latestActiveNode9, _latestActiveNode0, _latestActiveNode1;
|
|
558
|
+
var _oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (_activeNode18 = activeNode) === null || _activeNode18 === void 0 ? void 0 : _activeNode18.rootPos, (_activeNode19 = activeNode) === null || _activeNode19 === void 0 ? void 0 : _activeNode19.rootPos);
|
|
516
559
|
decorations = decorations.remove(_oldQuickInsertButton);
|
|
517
560
|
var quickInsertButton = quickInsertButtonDecoration({
|
|
518
561
|
api: api,
|
|
@@ -527,12 +570,27 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
|
|
|
527
570
|
editorState: newState
|
|
528
571
|
});
|
|
529
572
|
decorations = decorations.add(newState.doc, [quickInsertButton]);
|
|
573
|
+
|
|
574
|
+
// Update quick insert node decoration when the quick insert button is recreated but
|
|
575
|
+
// the drag handle was NOT recreated (shouldRecreateHandle was false). When
|
|
576
|
+
// shouldRecreateHandle is true, the block above already handles this.
|
|
577
|
+
if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) && !shouldRecreateHandle && ((_latestActiveNode1 = latestActiveNode) === null || _latestActiveNode1 === void 0 ? void 0 : _latestActiveNode1.rootPos) !== undefined) {
|
|
578
|
+
var _activeNode20, _newState$doc$nodeAt3;
|
|
579
|
+
if (((_activeNode20 = activeNode) === null || _activeNode20 === void 0 ? void 0 : _activeNode20.rootPos) !== undefined) {
|
|
580
|
+
var _oldActiveQuickInsertDec2 = findActiveQuickInsertNodeDec(decorations, activeNode.rootPos, activeNode.rootPos);
|
|
581
|
+
decorations = decorations.remove(_oldActiveQuickInsertDec2);
|
|
582
|
+
}
|
|
583
|
+
var _rootNodeSize = (_newState$doc$nodeAt3 = newState.doc.nodeAt(latestActiveNode.rootPos)) === null || _newState$doc$nodeAt3 === void 0 ? void 0 : _newState$doc$nodeAt3.nodeSize;
|
|
584
|
+
if (_rootNodeSize !== undefined) {
|
|
585
|
+
decorations = decorations.add(newState.doc, [createActiveQuickInsertNodeDecoration(latestActiveNode.rootPos, _rootNodeSize)]);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
530
588
|
if (rightSideControlsEnabled) {
|
|
531
589
|
var _iterator3 = _createForOfIteratorHelper(nodeDecorationRegistry),
|
|
532
590
|
_step3;
|
|
533
591
|
try {
|
|
534
592
|
var _loop3 = function _loop3() {
|
|
535
|
-
var
|
|
593
|
+
var _activeNode21, _activeNode22;
|
|
536
594
|
var factory = _step3.value;
|
|
537
595
|
if (!latestActiveNode || latestActiveNode.rootPos === undefined) {
|
|
538
596
|
return 0; // continue
|
|
@@ -546,7 +604,7 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
|
|
|
546
604
|
rootAnchorName: latestActiveNode.rootAnchorName,
|
|
547
605
|
rootNodeType: latestActiveNode.rootNodeType
|
|
548
606
|
};
|
|
549
|
-
var old = decorations.find((
|
|
607
|
+
var old = decorations.find((_activeNode21 = activeNode) === null || _activeNode21 === void 0 ? void 0 : _activeNode21.rootPos, (_activeNode22 = activeNode) === null || _activeNode22 === void 0 ? void 0 : _activeNode22.rootPos, function (spec) {
|
|
550
608
|
return spec.type === factory.type;
|
|
551
609
|
});
|
|
552
610
|
decorations = decorations.remove(old);
|
|
@@ -591,7 +649,7 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
|
|
|
591
649
|
}
|
|
592
650
|
|
|
593
651
|
// In view mode (edit/live pages), show right-side controls on block hover (without drag handle or quick insert)
|
|
594
|
-
var rootPos = (
|
|
652
|
+
var rootPos = (_latestActiveNode10 = latestActiveNode) === null || _latestActiveNode10 === void 0 ? void 0 : _latestActiveNode10.rootPos;
|
|
595
653
|
// rootPos is computed using the same logic as the floating insert menu, so it always points to a top-level (doc child) block when defined.
|
|
596
654
|
var isDocLevel = rootPos !== undefined && !isNaN(rootPos);
|
|
597
655
|
if (isViewMode && isDocLevel && flags.toolbarFlagsEnabled && rightSideControlsEnabled) {
|
|
@@ -712,15 +770,15 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
|
|
|
712
770
|
var newActiveNode;
|
|
713
771
|
// platform_editor_controls note: enables quick insert
|
|
714
772
|
if (flags.toolbarFlagsEnabled) {
|
|
715
|
-
var
|
|
773
|
+
var _latestActiveNode11, _latestActiveNode12;
|
|
716
774
|
// remove isEmptyDoc check and let decorations render and determine their own visibility
|
|
717
775
|
// In view mode with right-side controls we render node decorations (right-edge button), not the
|
|
718
776
|
// handle - so findHandleDec is always empty. Don't clear activeNode in that case.
|
|
719
|
-
var hasHandleOrViewModeControls = findHandleDec(decorations, (
|
|
777
|
+
var hasHandleOrViewModeControls = findHandleDec(decorations, (_latestActiveNode11 = latestActiveNode) === null || _latestActiveNode11 === void 0 ? void 0 : _latestActiveNode11.pos, (_latestActiveNode12 = latestActiveNode) === null || _latestActiveNode12 === void 0 ? void 0 : _latestActiveNode12.pos).length > 0 || isViewMode && rightSideControlsEnabled;
|
|
720
778
|
newActiveNode = meta !== null && meta !== void 0 && meta.editorBlurred || !(meta !== null && meta !== void 0 && meta.activeNode) && !hasHandleOrViewModeControls ? null : latestActiveNode;
|
|
721
779
|
} else {
|
|
722
|
-
var
|
|
723
|
-
newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) && findHandleDec(decorations, (
|
|
780
|
+
var _latestActiveNode13, _latestActiveNode14;
|
|
781
|
+
newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) && findHandleDec(decorations, (_latestActiveNode13 = latestActiveNode) === null || _latestActiveNode13 === void 0 ? void 0 : _latestActiveNode13.pos, (_latestActiveNode14 = latestActiveNode) === null || _latestActiveNode14 === void 0 ? void 0 : _latestActiveNode14.pos).length === 0 ? null : latestActiveNode;
|
|
724
782
|
}
|
|
725
783
|
var isMenuOpenNew = isMenuOpen;
|
|
726
784
|
if (editorExperiment('platform_editor_block_menu', true)) {
|
package/dist/esm/ui/consts.js
CHANGED
|
@@ -5,6 +5,8 @@ import { breakoutResizableNodes as breakoutResizableNodesNew } from '@atlaskit/e
|
|
|
5
5
|
import { akEditorUnitZIndex, akRichMediaResizeZIndex } from '@atlaskit/editor-shared-styles';
|
|
6
6
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
7
7
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
8
|
+
export var ACTIVE_DRAG_HANDLE_ATTR = 'data-active-drag-handle';
|
|
9
|
+
export var ACTIVE_QUICK_INSERT_ATTR = 'data-active-quick-insert';
|
|
8
10
|
export var DRAG_HANDLE_HEIGHT = 24;
|
|
9
11
|
export var DRAG_HANDLE_BORDER_RADIUS = 4;
|
|
10
12
|
export var DRAG_HANDLE_ZINDEX = akRichMediaResizeZIndex + akEditorUnitZIndex; //place above legacy resizer
|
|
@@ -40,7 +40,7 @@ import { getControlBottomCSSValue, getControlHeightCSSValue, getLeftPosition, ge
|
|
|
40
40
|
import { expandAndUpdateSelection } from '../pm-plugins/utils/expand-and-update-selection';
|
|
41
41
|
import { isHandleCorrelatedToSelection, selectNode } from '../pm-plugins/utils/getSelection';
|
|
42
42
|
import { alignAnchorHeadInDirectionOfPos, expandSelectionHeadToNodeAtPos } from '../pm-plugins/utils/selection';
|
|
43
|
-
import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH, DRAG_HANDLE_ZINDEX, dragHandleGap, nodeMargins, spacingBetweenNodesForPreview, STICKY_CONTROLS_TOP_MARGIN, STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER, topPositionAdjustment } from './consts';
|
|
43
|
+
import { ACTIVE_DRAG_HANDLE_ATTR, DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH, DRAG_HANDLE_ZINDEX, dragHandleGap, nodeMargins, spacingBetweenNodesForPreview, STICKY_CONTROLS_TOP_MARGIN, STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER, topPositionAdjustment } from './consts';
|
|
44
44
|
import { DragHandleNestedIcon } from './drag-handle-nested-icon';
|
|
45
45
|
import { dragPreview } from './drag-preview';
|
|
46
46
|
import { refreshAnchorName } from './utils/anchor-name';
|
|
@@ -823,6 +823,15 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
823
823
|
anchorName: anchorName
|
|
824
824
|
}) : anchorName;
|
|
825
825
|
var dom = view.dom.querySelector("[".concat(getAnchorAttrName(), "=\"").concat(safeAnchorName, "\"]"));
|
|
826
|
+
|
|
827
|
+
// Defence-in-depth guard: since the node decoration sets data-active-drag-handle on the
|
|
828
|
+
// active node, we check for it directly. This is a cheap DOM attribute read (no reflow,
|
|
829
|
+
// no style recalculation) and hides the control if the decoration hasn't been applied yet.
|
|
830
|
+
if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) && !(dom !== null && dom !== void 0 && dom.hasAttribute(ACTIVE_DRAG_HANDLE_ATTR))) {
|
|
831
|
+
return {
|
|
832
|
+
display: 'none'
|
|
833
|
+
};
|
|
834
|
+
}
|
|
826
835
|
var hasResizer = nodeType === 'table' || nodeType === 'mediaSingle';
|
|
827
836
|
var isExtension = nodeType === 'extension' || nodeType === 'bodiedExtension' || nodeType === 'multiBodiedExtension' && fg('confluence_frontend_native_tabs_extension');
|
|
828
837
|
var isBlockCard = nodeType === 'blockCard' && !!blockCardWidth;
|
|
@@ -12,7 +12,7 @@ import { ZERO_WIDTH_SPACE } from '@atlaskit/editor-common/whitespace';
|
|
|
12
12
|
import { akEditorBreakoutPadding, akEditorCalculatedWideLayoutWidth, akEditorCalculatedWideLayoutWidthSmallViewport, akEditorFullPageNarrowBreakout, akEditorGutterPaddingDynamic, akEditorGutterPaddingReduced } from '@atlaskit/editor-shared-styles';
|
|
13
13
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
14
14
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
15
|
-
import { DRAG_HANDLE_MAX_WIDTH_PLUS_GAP } from './consts';
|
|
15
|
+
import { ACTIVE_DRAG_HANDLE_ATTR, ACTIVE_QUICK_INSERT_ATTR, DRAG_HANDLE_MAX_WIDTH_PLUS_GAP } from './consts';
|
|
16
16
|
import { NODE_ANCHOR_ATTR_NAME } from './utils/dom-attr-name';
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -356,6 +356,18 @@ var dragHandlerAnchorStyles = css({
|
|
|
356
356
|
})
|
|
357
357
|
}
|
|
358
358
|
});
|
|
359
|
+
var activeControlsSelector = "[".concat(ACTIVE_DRAG_HANDLE_ATTR, "], [").concat(ACTIVE_QUICK_INSERT_ATTR, "]");
|
|
360
|
+
|
|
361
|
+
// Applies anchor-name via node decoration attributes rather than adjacency CSS selectors.
|
|
362
|
+
// This is more reliable than dragHandlerAnchorStyles which depends on DOM structure.
|
|
363
|
+
// Only nodes decorated with data-active-drag-handle / data-active-quick-insert get anchor-name.
|
|
364
|
+
var staticControlsAnchorStyles = css({
|
|
365
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
|
|
366
|
+
'.ProseMirror': _defineProperty({}, activeControlsSelector, {
|
|
367
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
|
|
368
|
+
anchorName: "var(".concat(ANCHOR_VARIABLE_NAME, ", attr(data-node-anchor type(<custom-ident>)))")
|
|
369
|
+
})
|
|
370
|
+
});
|
|
359
371
|
|
|
360
372
|
// Styles applied to nodes with anchors when dragging
|
|
361
373
|
var dragAnchorStyles = css({
|
|
@@ -404,6 +416,6 @@ export var GlobalStylesWrapper = function GlobalStylesWrapper(_ref) {
|
|
|
404
416
|
exposure: true
|
|
405
417
|
}) ? expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? extendHoverZoneReducedNext : extendHoverZoneReduced : undefined,
|
|
406
418
|
// platform_editor_controls note: this allows drag handles to render on empty lines
|
|
407
|
-
toolbarFlagsEnabled ? undefined : withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, editorExperiment('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withRelativePosStyleNext : withRelativePosStyle, topLevelNodeMarginStyles, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withAnchorNameZindexStyleNext : withAnchorNameZindexStyle, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) && expValEquals('advanced_layouts', 'isEnabled', true) ? layoutColumnExtendedHoverZone : layoutColumnWithoutHoverZone, shouldRenderAnchors && (isDragging ? dragAnchorStyles : dragHandlerAnchorStyles)]
|
|
419
|
+
toolbarFlagsEnabled ? undefined : withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, editorExperiment('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withRelativePosStyleNext : withRelativePosStyle, topLevelNodeMarginStyles, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withAnchorNameZindexStyleNext : withAnchorNameZindexStyle, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) && expValEquals('advanced_layouts', 'isEnabled', true) ? layoutColumnExtendedHoverZone : layoutColumnWithoutHoverZone, shouldRenderAnchors && (isDragging ? dragAnchorStyles : dragHandlerAnchorStyles), expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) ? staticControlsAnchorStyles : undefined]
|
|
408
420
|
});
|
|
409
421
|
};
|
|
@@ -28,7 +28,7 @@ import Tooltip from '@atlaskit/tooltip';
|
|
|
28
28
|
import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
|
|
29
29
|
import { getControlBottomCSSValue, getControlHeightCSSValue, getNodeHeight, getTopPosition, shouldBeSticky } from '../pm-plugins/utils/drag-handle-positions';
|
|
30
30
|
import { getLeftPositionForRootElement } from '../pm-plugins/utils/widget-positions';
|
|
31
|
-
import { QUICK_INSERT_DIMENSIONS, QUICK_INSERT_HEIGHT, QUICK_INSERT_LEFT_OFFSET, QUICK_INSERT_WIDTH, rootElementGap, STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER, topPositionAdjustment } from './consts';
|
|
31
|
+
import { ACTIVE_QUICK_INSERT_ATTR, QUICK_INSERT_DIMENSIONS, QUICK_INSERT_HEIGHT, QUICK_INSERT_LEFT_OFFSET, QUICK_INSERT_WIDTH, rootElementGap, STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER, topPositionAdjustment } from './consts';
|
|
32
32
|
import { refreshAnchorName } from './utils/anchor-name';
|
|
33
33
|
import { isInTextSelection, isNestedNodeSelected, isNonEditableBlock, isSelectionInNode } from './utils/document-checks';
|
|
34
34
|
import { getAnchorAttrName } from './utils/dom-attr-name';
|
|
@@ -184,6 +184,14 @@ export var TypeAheadControl = function TypeAheadControl(_ref) {
|
|
|
184
184
|
anchorName: rootAnchorName
|
|
185
185
|
});
|
|
186
186
|
var dom = view.dom.querySelector("[".concat(getAnchorAttrName(), "=\"").concat(safeAnchorName, "\"]"));
|
|
187
|
+
|
|
188
|
+
// Defence-in-depth guard: the node decoration sets data-active-quick-insert on the
|
|
189
|
+
// active root node. Check for it directly — cheap DOM attribute read, no reflow.
|
|
190
|
+
if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) && !(dom !== null && dom !== void 0 && dom.hasAttribute(ACTIVE_QUICK_INSERT_ATTR))) {
|
|
191
|
+
return {
|
|
192
|
+
display: 'none'
|
|
193
|
+
};
|
|
194
|
+
}
|
|
187
195
|
var hasResizer = rootNodeType === 'table' || rootNodeType === 'mediaSingle';
|
|
188
196
|
var isExtension = rootNodeType === 'extension' || rootNodeType === 'bodiedExtension' || rootNodeType === 'multiBodiedExtension' && fg('confluence_frontend_native_tabs_extension');
|
|
189
197
|
var isBlockCard = rootNodeType === 'blockCard';
|
|
@@ -6,6 +6,13 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
|
6
6
|
import type { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
7
7
|
import type { BlockControlsPlugin, HandleOptions } from '../blockControlsPluginType';
|
|
8
8
|
import type { AnchorRectCache } from './utils/anchor-utils';
|
|
9
|
+
/**
|
|
10
|
+
* Creates a Decoration.node that marks the active node with `data-active-drag-handle="true"`.
|
|
11
|
+
* The CSS in staticControlsAnchorStyles then applies `anchor-name` to this attribute,
|
|
12
|
+
* which is more reliable than the adjacency-selector approach in dragHandlerAnchorStyles.
|
|
13
|
+
*/
|
|
14
|
+
export declare const createActiveDragHandleNodeDecoration: (pos: number, nodeSize: number) => Decoration;
|
|
15
|
+
export declare const findActiveDragHandleNodeDec: (decorations: DecorationSet, from?: number, to?: number) => Decoration[];
|
|
9
16
|
export declare const emptyParagraphNodeDecorations: () => Decoration;
|
|
10
17
|
export declare const findHandleDec: (decorations: DecorationSet, from?: number, to?: number) => Decoration[];
|
|
11
18
|
type DragHandleDecorationParams = {
|
|
@@ -19,5 +19,12 @@ type QuickInsertButtonDecorationParams = {
|
|
|
19
19
|
rootNodeType?: string;
|
|
20
20
|
rootPos: number;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* Creates a Decoration.node that marks the active node with `data-active-quick-insert="true"`.
|
|
24
|
+
* The CSS in staticControlsAnchorStyles applies `anchor-name` to this attribute directly,
|
|
25
|
+
* replacing the unreliable adjacency selector `[block-ctrl-quick-insert-button] + *`.
|
|
26
|
+
*/
|
|
27
|
+
export declare const createActiveQuickInsertNodeDecoration: (pos: number, nodeSize: number) => Decoration;
|
|
28
|
+
export declare const findActiveQuickInsertNodeDec: (decorations: DecorationSet, from?: number, to?: number) => Decoration[];
|
|
22
29
|
export declare const quickInsertButtonDecoration: ({ api, formatMessage, rootPos, anchorName, nodeType, nodeViewPortalProviderAPI, rootAnchorName, rootNodeType, anchorRectCache, editorState, }: QuickInsertButtonDecorationParams) => Decoration;
|
|
23
30
|
export {};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export declare const ACTIVE_DRAG_HANDLE_ATTR = "data-active-drag-handle";
|
|
2
|
+
export declare const ACTIVE_QUICK_INSERT_ATTR = "data-active-quick-insert";
|
|
1
3
|
export declare const DRAG_HANDLE_HEIGHT = 24;
|
|
2
4
|
export declare const DRAG_HANDLE_BORDER_RADIUS = 4;
|
|
3
5
|
export declare const DRAG_HANDLE_ZINDEX: number;
|
|
@@ -6,6 +6,13 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
|
6
6
|
import type { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
7
7
|
import type { BlockControlsPlugin, HandleOptions } from '../blockControlsPluginType';
|
|
8
8
|
import type { AnchorRectCache } from './utils/anchor-utils';
|
|
9
|
+
/**
|
|
10
|
+
* Creates a Decoration.node that marks the active node with `data-active-drag-handle="true"`.
|
|
11
|
+
* The CSS in staticControlsAnchorStyles then applies `anchor-name` to this attribute,
|
|
12
|
+
* which is more reliable than the adjacency-selector approach in dragHandlerAnchorStyles.
|
|
13
|
+
*/
|
|
14
|
+
export declare const createActiveDragHandleNodeDecoration: (pos: number, nodeSize: number) => Decoration;
|
|
15
|
+
export declare const findActiveDragHandleNodeDec: (decorations: DecorationSet, from?: number, to?: number) => Decoration[];
|
|
9
16
|
export declare const emptyParagraphNodeDecorations: () => Decoration;
|
|
10
17
|
export declare const findHandleDec: (decorations: DecorationSet, from?: number, to?: number) => Decoration[];
|
|
11
18
|
type DragHandleDecorationParams = {
|
|
@@ -19,5 +19,12 @@ type QuickInsertButtonDecorationParams = {
|
|
|
19
19
|
rootNodeType?: string;
|
|
20
20
|
rootPos: number;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* Creates a Decoration.node that marks the active node with `data-active-quick-insert="true"`.
|
|
24
|
+
* The CSS in staticControlsAnchorStyles applies `anchor-name` to this attribute directly,
|
|
25
|
+
* replacing the unreliable adjacency selector `[block-ctrl-quick-insert-button] + *`.
|
|
26
|
+
*/
|
|
27
|
+
export declare const createActiveQuickInsertNodeDecoration: (pos: number, nodeSize: number) => Decoration;
|
|
28
|
+
export declare const findActiveQuickInsertNodeDec: (decorations: DecorationSet, from?: number, to?: number) => Decoration[];
|
|
22
29
|
export declare const quickInsertButtonDecoration: ({ api, formatMessage, rootPos, anchorName, nodeType, nodeViewPortalProviderAPI, rootAnchorName, rootNodeType, anchorRectCache, editorState, }: QuickInsertButtonDecorationParams) => Decoration;
|
|
23
30
|
export {};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export declare const ACTIVE_DRAG_HANDLE_ATTR = "data-active-drag-handle";
|
|
2
|
+
export declare const ACTIVE_QUICK_INSERT_ATTR = "data-active-quick-insert";
|
|
1
3
|
export declare const DRAG_HANDLE_HEIGHT = 24;
|
|
2
4
|
export declare const DRAG_HANDLE_BORDER_RADIUS = 4;
|
|
3
5
|
export declare const DRAG_HANDLE_ZINDEX: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-controls",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.2.0",
|
|
4
4
|
"description": "Block controls plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^3.2.0",
|
|
57
57
|
"@atlaskit/primitives": "^19.0.0",
|
|
58
58
|
"@atlaskit/theme": "^25.0.0",
|
|
59
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
59
|
+
"@atlaskit/tmp-editor-statsig": "^90.1.0",
|
|
60
60
|
"@atlaskit/tokens": "^13.3.0",
|
|
61
61
|
"@atlaskit/tooltip": "^22.6.0",
|
|
62
62
|
"@babel/runtime": "^7.0.0",
|