@atlaskit/editor-plugin-selection 1.4.3 → 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/mark-boundary-cursor/marks-side.js +12 -0
  3. package/dist/cjs/mark-boundary-cursor/ui/mark-boundary-cursor-decoration.js +38 -0
  4. package/dist/cjs/mark-boundary-cursor/utils/active-marks-side.js +40 -0
  5. package/dist/cjs/mark-boundary-cursor/utils/inline-code-side.js +45 -0
  6. package/dist/cjs/plugin.js +9 -1
  7. package/dist/cjs/pm-plugins/mark-boundary-cursor-main.js +51 -0
  8. package/dist/cjs/pm-plugins/mark-boundary-cursor-plugin-key.js +8 -0
  9. package/dist/es2019/mark-boundary-cursor/marks-side.js +6 -0
  10. package/dist/es2019/mark-boundary-cursor/ui/mark-boundary-cursor-decoration.js +41 -0
  11. package/dist/es2019/mark-boundary-cursor/utils/active-marks-side.js +36 -0
  12. package/dist/es2019/mark-boundary-cursor/utils/inline-code-side.js +34 -0
  13. package/dist/es2019/plugin.js +6 -1
  14. package/dist/es2019/pm-plugins/mark-boundary-cursor-main.js +45 -0
  15. package/dist/es2019/pm-plugins/mark-boundary-cursor-plugin-key.js +2 -0
  16. package/dist/esm/mark-boundary-cursor/marks-side.js +6 -0
  17. package/dist/esm/mark-boundary-cursor/ui/mark-boundary-cursor-decoration.js +32 -0
  18. package/dist/esm/mark-boundary-cursor/utils/active-marks-side.js +34 -0
  19. package/dist/esm/mark-boundary-cursor/utils/inline-code-side.js +39 -0
  20. package/dist/esm/plugin.js +9 -1
  21. package/dist/esm/pm-plugins/mark-boundary-cursor-main.js +45 -0
  22. package/dist/esm/pm-plugins/mark-boundary-cursor-plugin-key.js +2 -0
  23. package/dist/types/mark-boundary-cursor/marks-side.d.ts +5 -0
  24. package/dist/types/mark-boundary-cursor/ui/mark-boundary-cursor-decoration.d.ts +2 -0
  25. package/dist/types/mark-boundary-cursor/utils/active-marks-side.d.ts +18 -0
  26. package/dist/types/mark-boundary-cursor/utils/inline-code-side.d.ts +18 -0
  27. package/dist/types/pm-plugins/mark-boundary-cursor-main.d.ts +5 -0
  28. package/dist/types/pm-plugins/mark-boundary-cursor-plugin-key.d.ts +2 -0
  29. package/dist/types-ts4.5/mark-boundary-cursor/marks-side.d.ts +5 -0
  30. package/dist/types-ts4.5/mark-boundary-cursor/ui/mark-boundary-cursor-decoration.d.ts +2 -0
  31. package/dist/types-ts4.5/mark-boundary-cursor/utils/active-marks-side.d.ts +18 -0
  32. package/dist/types-ts4.5/mark-boundary-cursor/utils/inline-code-side.d.ts +18 -0
  33. package/dist/types-ts4.5/pm-plugins/mark-boundary-cursor-main.d.ts +5 -0
  34. package/dist/types-ts4.5/pm-plugins/mark-boundary-cursor-plugin-key.d.ts +2 -0
  35. package/package.json +6 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/editor-plugin-selection
2
2
 
3
+ ## 1.4.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#140867](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/140867)
8
+ [`17b58500a94e3`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/17b58500a94e3) -
9
+ [ux] ED-24255 Adding a custom mark boundary cursor to fix the cursor position in inline code
10
+
3
11
  ## 1.4.3
4
12
 
5
13
  ### Patch Changes
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.MarksSide = void 0;
7
+ var MarksSide = exports.MarksSide = /*#__PURE__*/function (MarksSide) {
8
+ MarksSide[MarksSide["None"] = 0] = "None";
9
+ MarksSide[MarksSide["Left"] = -1] = "Left";
10
+ MarksSide[MarksSide["Right"] = 1] = "Right";
11
+ return MarksSide;
12
+ }({});
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createMarkBoundaryCursorDecoration = void 0;
7
+ var _view = require("@atlaskit/editor-prosemirror/view");
8
+ var containerStyle = "\n\tposition: relative;\n";
9
+ var caretStyle = "\n\tposition: absolute;\n\theight: 100%;\n\twidth: 1px;\n\tleft: -0.5px;\n\tbottom: 0;\n\tbackground-color: ".concat("var(--ds-text, #172B4D)", ";\n");
10
+ var toDOM = function toDOM() {
11
+ var container = document.createElement('span');
12
+ container.className = 'ProseMirror-mark-boundary-cursor';
13
+ container.setAttribute('style', containerStyle);
14
+ var caret = document.createElement('div');
15
+ caret.setAttribute('style', caretStyle);
16
+ caret.animate([{
17
+ opacity: 1
18
+ }, {
19
+ opacity: 1,
20
+ offset: 0.5
21
+ }, {
22
+ opacity: 0,
23
+ offset: 0.5
24
+ }, {
25
+ opacity: 0
26
+ }], {
27
+ duration: 1000,
28
+ iterations: Infinity
29
+ });
30
+ container.appendChild(caret);
31
+ return container;
32
+ };
33
+ var createMarkBoundaryCursorDecoration = exports.createMarkBoundaryCursorDecoration = function createMarkBoundaryCursorDecoration(pos, side) {
34
+ return _view.Decoration.widget(pos, toDOM, {
35
+ key: 'mark-boundary-cursor',
36
+ side: side
37
+ });
38
+ };
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getActiveMarksSide = getActiveMarksSide;
7
+ var _utils = require("@atlaskit/editor-common/utils");
8
+ var _model = require("@atlaskit/editor-prosemirror/model");
9
+ var _marksSide = require("../marks-side");
10
+ var _inlineCodeSide = require("./inline-code-side");
11
+ /**
12
+ * Will determine which side of the current selection the mark-boundary-cursor should
13
+ * favour / point towards, based on which marks are currently active and which marks
14
+ * are applied to the nodes to the left and right side of the current selection.
15
+ *
16
+ * @param {Selection} options.selection - The current selection.
17
+ * @param {readonly Mark[] | null} options.storedMarks - Current stored marks, if any.
18
+ * @returns {MarksSide} - The side (left -1, right 1, or none 0) the mark-boundary-cursor should favour.
19
+ */
20
+ function getActiveMarksSide(_ref) {
21
+ var _nodeBefore$marks, _nodeAfter$marks;
22
+ var selection = _ref.selection,
23
+ storedMarks = _ref.storedMarks;
24
+ if (!(0, _utils.isTextSelection)(selection) || !selection.empty) {
25
+ return _marksSide.MarksSide.None;
26
+ }
27
+ var _selection$$head = selection.$head,
28
+ nodeBefore = _selection$$head.nodeBefore,
29
+ nodeAfter = _selection$$head.nodeAfter;
30
+ var leftMarks = (_nodeBefore$marks = nodeBefore === null || nodeBefore === void 0 ? void 0 : nodeBefore.marks) !== null && _nodeBefore$marks !== void 0 ? _nodeBefore$marks : [];
31
+ var rightMarks = (_nodeAfter$marks = nodeAfter === null || nodeAfter === void 0 ? void 0 : nodeAfter.marks) !== null && _nodeAfter$marks !== void 0 ? _nodeAfter$marks : [];
32
+ if (_model.Mark.sameSet(leftMarks, rightMarks)) {
33
+ return _marksSide.MarksSide.None;
34
+ }
35
+ return (0, _inlineCodeSide.getInlineCodeCursorSide)({
36
+ leftMarks: leftMarks,
37
+ rightMarks: rightMarks,
38
+ storedMarks: storedMarks
39
+ });
40
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getInlineCodeCursorSide = getInlineCodeCursorSide;
7
+ var _marksSide = require("../marks-side");
8
+ /**
9
+ * Given the marks on the left and right side of the current selection, and the stored
10
+ * marks being updated during a transaction, this function returns the side (-1 = left,
11
+ * 1 = right) for which node the mark boundary cursor decoration should be added
12
+ *
13
+ * This is intended to correct an issue where the default cursor does not render in the
14
+ * expected location when navigating via arrow keys past the boundary of an inline code
15
+ * node
16
+ */
17
+ function getInlineCodeCursorSide(_ref) {
18
+ var leftMarks = _ref.leftMarks,
19
+ rightMarks = _ref.rightMarks,
20
+ storedMarks = _ref.storedMarks;
21
+ var isInlineCodeToLeft = leftMarks.some(function (mark) {
22
+ return mark.type.name === 'code';
23
+ });
24
+ var isInlineCodeToRight = rightMarks.some(function (mark) {
25
+ return mark.type.name === 'code';
26
+ });
27
+ var isInlineCodeBeingStored = !!storedMarks && (storedMarks === null || storedMarks === void 0 ? void 0 : storedMarks.some(function (mark) {
28
+ return mark.type.name === 'code';
29
+ }));
30
+ var isStoredMarksBeingCleared = !!storedMarks && storedMarks.length === 0;
31
+
32
+ // This condition covers two scenarios:
33
+ // a) When the cursor is on the left side of the inline code, and is expected to be
34
+ // positioned within the inline code after pressing arrow right
35
+ // b) When the cursor is on the right side of the inline code, and is expected to be
36
+ // positioned outside of the inline code after pressing arrow right
37
+ // in both of these cases the cursor needs to be corrected to be positioned inline
38
+ // with the node to the right
39
+ // NOTE: In editor-plugin-text-formatting there is logic on left/right key press
40
+ // which dispatches a transaction to update the stored marks
41
+ if (isInlineCodeToRight && isInlineCodeBeingStored || isInlineCodeToLeft && isStoredMarksBeingCleared) {
42
+ return _marksSide.MarksSide.Right;
43
+ }
44
+ return _marksSide.MarksSide.None;
45
+ }
@@ -5,11 +5,14 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.selectionPlugin = exports.default = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
8
10
  var _commands = require("./commands");
9
11
  var _gapCursorKeymap = _interopRequireDefault(require("./pm-plugins/gap-cursor-keymap"));
10
12
  var _gapCursorMain = _interopRequireDefault(require("./pm-plugins/gap-cursor-main"));
11
13
  var _gapCursorPluginKey = require("./pm-plugins/gap-cursor-plugin-key");
12
14
  var _keymap = _interopRequireDefault(require("./pm-plugins/keymap"));
15
+ var _markBoundaryCursorMain = require("./pm-plugins/mark-boundary-cursor-main");
13
16
  var _selectionMain = require("./pm-plugins/selection-main");
14
17
  var _types = require("./types");
15
18
  var displayGapCursor = function displayGapCursor(toggle) {
@@ -69,7 +72,12 @@ var selectionPlugin = exports.selectionPlugin = function selectionPlugin(_ref2)
69
72
  plugin: function plugin() {
70
73
  return _gapCursorMain.default;
71
74
  }
72
- }];
75
+ }].concat((0, _toConsumableArray2.default)((0, _platformFeatureFlags.fg)('platform_editor_mark_boundary_cursor') ? [{
76
+ name: 'markBoundaryCursor',
77
+ plugin: function plugin() {
78
+ return (0, _markBoundaryCursorMain.createMarkBoundaryCursorPlugin)();
79
+ }
80
+ }] : []));
73
81
  }
74
82
  };
75
83
  };
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createMarkBoundaryCursorPlugin = void 0;
7
+ var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
8
+ var _view = require("@atlaskit/editor-prosemirror/view");
9
+ var _markBoundaryCursorDecoration = require("../mark-boundary-cursor/ui/mark-boundary-cursor-decoration");
10
+ var _activeMarksSide = require("../mark-boundary-cursor/utils/active-marks-side");
11
+ var _markBoundaryCursorPluginKey = require("./mark-boundary-cursor-plugin-key");
12
+ var createMarkBoundaryCursorPlugin = exports.createMarkBoundaryCursorPlugin = function createMarkBoundaryCursorPlugin() {
13
+ return new _safePlugin.SafePlugin({
14
+ key: _markBoundaryCursorPluginKey.markBoundaryCursorPluginKey,
15
+ state: {
16
+ init: function init() {
17
+ return {
18
+ decorations: _view.DecorationSet.empty
19
+ };
20
+ },
21
+ apply: function apply(tr, currentState) {
22
+ var selection = tr.selection,
23
+ storedMarks = tr.storedMarks,
24
+ doc = tr.doc,
25
+ selectionSet = tr.selectionSet,
26
+ storedMarksSet = tr.storedMarksSet;
27
+ if (!selectionSet && !storedMarksSet) {
28
+ return currentState;
29
+ }
30
+ var side = (0, _activeMarksSide.getActiveMarksSide)({
31
+ selection: selection,
32
+ storedMarks: storedMarks
33
+ });
34
+ if (!side) {
35
+ return {
36
+ decorations: _view.DecorationSet.empty
37
+ };
38
+ }
39
+ return {
40
+ decorations: _view.DecorationSet.create(doc, [(0, _markBoundaryCursorDecoration.createMarkBoundaryCursorDecoration)(selection.head, side)])
41
+ };
42
+ }
43
+ },
44
+ props: {
45
+ decorations: function decorations(state) {
46
+ var _markBoundaryCursorPl;
47
+ return (_markBoundaryCursorPl = _markBoundaryCursorPluginKey.markBoundaryCursorPluginKey.getState(state)) === null || _markBoundaryCursorPl === void 0 ? void 0 : _markBoundaryCursorPl.decorations;
48
+ }
49
+ }
50
+ });
51
+ };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.markBoundaryCursorPluginKey = void 0;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ var markBoundaryCursorPluginKey = exports.markBoundaryCursorPluginKey = new _state.PluginKey('markBoundaryCursorPlugin');
@@ -0,0 +1,6 @@
1
+ export let MarksSide = /*#__PURE__*/function (MarksSide) {
2
+ MarksSide[MarksSide["None"] = 0] = "None";
3
+ MarksSide[MarksSide["Left"] = -1] = "Left";
4
+ MarksSide[MarksSide["Right"] = 1] = "Right";
5
+ return MarksSide;
6
+ }({});
@@ -0,0 +1,41 @@
1
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
+ const containerStyle = `
3
+ position: relative;
4
+ `;
5
+ const caretStyle = `
6
+ position: absolute;
7
+ height: 100%;
8
+ width: 1px;
9
+ left: -0.5px;
10
+ bottom: 0;
11
+ background-color: ${"var(--ds-text, #172B4D)"};
12
+ `;
13
+ const toDOM = () => {
14
+ const container = document.createElement('span');
15
+ container.className = 'ProseMirror-mark-boundary-cursor';
16
+ container.setAttribute('style', containerStyle);
17
+ const caret = document.createElement('div');
18
+ caret.setAttribute('style', caretStyle);
19
+ caret.animate([{
20
+ opacity: 1
21
+ }, {
22
+ opacity: 1,
23
+ offset: 0.5
24
+ }, {
25
+ opacity: 0,
26
+ offset: 0.5
27
+ }, {
28
+ opacity: 0
29
+ }], {
30
+ duration: 1000,
31
+ iterations: Infinity
32
+ });
33
+ container.appendChild(caret);
34
+ return container;
35
+ };
36
+ export const createMarkBoundaryCursorDecoration = (pos, side) => {
37
+ return Decoration.widget(pos, toDOM, {
38
+ key: 'mark-boundary-cursor',
39
+ side
40
+ });
41
+ };
@@ -0,0 +1,36 @@
1
+ import { isTextSelection } from '@atlaskit/editor-common/utils';
2
+ import { Mark } from '@atlaskit/editor-prosemirror/model';
3
+ import { MarksSide } from '../marks-side';
4
+ import { getInlineCodeCursorSide } from './inline-code-side';
5
+ /**
6
+ * Will determine which side of the current selection the mark-boundary-cursor should
7
+ * favour / point towards, based on which marks are currently active and which marks
8
+ * are applied to the nodes to the left and right side of the current selection.
9
+ *
10
+ * @param {Selection} options.selection - The current selection.
11
+ * @param {readonly Mark[] | null} options.storedMarks - Current stored marks, if any.
12
+ * @returns {MarksSide} - The side (left -1, right 1, or none 0) the mark-boundary-cursor should favour.
13
+ */
14
+ export function getActiveMarksSide({
15
+ selection,
16
+ storedMarks
17
+ }) {
18
+ var _nodeBefore$marks, _nodeAfter$marks;
19
+ if (!isTextSelection(selection) || !selection.empty) {
20
+ return MarksSide.None;
21
+ }
22
+ const {
23
+ nodeBefore,
24
+ nodeAfter
25
+ } = selection.$head;
26
+ const leftMarks = (_nodeBefore$marks = nodeBefore === null || nodeBefore === void 0 ? void 0 : nodeBefore.marks) !== null && _nodeBefore$marks !== void 0 ? _nodeBefore$marks : [];
27
+ const rightMarks = (_nodeAfter$marks = nodeAfter === null || nodeAfter === void 0 ? void 0 : nodeAfter.marks) !== null && _nodeAfter$marks !== void 0 ? _nodeAfter$marks : [];
28
+ if (Mark.sameSet(leftMarks, rightMarks)) {
29
+ return MarksSide.None;
30
+ }
31
+ return getInlineCodeCursorSide({
32
+ leftMarks,
33
+ rightMarks,
34
+ storedMarks
35
+ });
36
+ }
@@ -0,0 +1,34 @@
1
+ import { MarksSide } from '../marks-side';
2
+ /**
3
+ * Given the marks on the left and right side of the current selection, and the stored
4
+ * marks being updated during a transaction, this function returns the side (-1 = left,
5
+ * 1 = right) for which node the mark boundary cursor decoration should be added
6
+ *
7
+ * This is intended to correct an issue where the default cursor does not render in the
8
+ * expected location when navigating via arrow keys past the boundary of an inline code
9
+ * node
10
+ */
11
+ export function getInlineCodeCursorSide({
12
+ leftMarks,
13
+ rightMarks,
14
+ storedMarks
15
+ }) {
16
+ const isInlineCodeToLeft = leftMarks.some(mark => mark.type.name === 'code');
17
+ const isInlineCodeToRight = rightMarks.some(mark => mark.type.name === 'code');
18
+ const isInlineCodeBeingStored = !!storedMarks && (storedMarks === null || storedMarks === void 0 ? void 0 : storedMarks.some(mark => mark.type.name === 'code'));
19
+ const isStoredMarksBeingCleared = !!storedMarks && storedMarks.length === 0;
20
+
21
+ // This condition covers two scenarios:
22
+ // a) When the cursor is on the left side of the inline code, and is expected to be
23
+ // positioned within the inline code after pressing arrow right
24
+ // b) When the cursor is on the right side of the inline code, and is expected to be
25
+ // positioned outside of the inline code after pressing arrow right
26
+ // in both of these cases the cursor needs to be corrected to be positioned inline
27
+ // with the node to the right
28
+ // NOTE: In editor-plugin-text-formatting there is logic on left/right key press
29
+ // which dispatches a transaction to update the stored marks
30
+ if (isInlineCodeToRight && isInlineCodeBeingStored || isInlineCodeToLeft && isStoredMarksBeingCleared) {
31
+ return MarksSide.Right;
32
+ }
33
+ return MarksSide.None;
34
+ }
@@ -1,8 +1,10 @@
1
+ import { fg } from '@atlaskit/platform-feature-flags';
1
2
  import { selectNearNode } from './commands';
2
3
  import gapCursorKeymapPlugin from './pm-plugins/gap-cursor-keymap';
3
4
  import gapCursorPlugin from './pm-plugins/gap-cursor-main';
4
5
  import { gapCursorPluginKey } from './pm-plugins/gap-cursor-plugin-key';
5
6
  import selectionKeymapPlugin from './pm-plugins/keymap';
7
+ import { createMarkBoundaryCursorPlugin } from './pm-plugins/mark-boundary-cursor-main';
6
8
  import { createPlugin } from './pm-plugins/selection-main';
7
9
  import { selectionPluginKey } from './types';
8
10
  const displayGapCursor = toggle => ({
@@ -55,7 +57,10 @@ export const selectionPlugin = ({
55
57
  }, {
56
58
  name: 'gapCursor',
57
59
  plugin: () => gapCursorPlugin
58
- }];
60
+ }, ...(fg('platform_editor_mark_boundary_cursor') ? [{
61
+ name: 'markBoundaryCursor',
62
+ plugin: () => createMarkBoundaryCursorPlugin()
63
+ }] : [])];
59
64
  }
60
65
  });
61
66
  export default selectionPlugin;
@@ -0,0 +1,45 @@
1
+ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
3
+ import { createMarkBoundaryCursorDecoration } from '../mark-boundary-cursor/ui/mark-boundary-cursor-decoration';
4
+ import { getActiveMarksSide } from '../mark-boundary-cursor/utils/active-marks-side';
5
+ import { markBoundaryCursorPluginKey } from './mark-boundary-cursor-plugin-key';
6
+ export const createMarkBoundaryCursorPlugin = () => {
7
+ return new SafePlugin({
8
+ key: markBoundaryCursorPluginKey,
9
+ state: {
10
+ init: () => ({
11
+ decorations: DecorationSet.empty
12
+ }),
13
+ apply(tr, currentState) {
14
+ const {
15
+ selection,
16
+ storedMarks,
17
+ doc,
18
+ selectionSet,
19
+ storedMarksSet
20
+ } = tr;
21
+ if (!selectionSet && !storedMarksSet) {
22
+ return currentState;
23
+ }
24
+ const side = getActiveMarksSide({
25
+ selection,
26
+ storedMarks
27
+ });
28
+ if (!side) {
29
+ return {
30
+ decorations: DecorationSet.empty
31
+ };
32
+ }
33
+ return {
34
+ decorations: DecorationSet.create(doc, [createMarkBoundaryCursorDecoration(selection.head, side)])
35
+ };
36
+ }
37
+ },
38
+ props: {
39
+ decorations: state => {
40
+ var _markBoundaryCursorPl;
41
+ return (_markBoundaryCursorPl = markBoundaryCursorPluginKey.getState(state)) === null || _markBoundaryCursorPl === void 0 ? void 0 : _markBoundaryCursorPl.decorations;
42
+ }
43
+ }
44
+ });
45
+ };
@@ -0,0 +1,2 @@
1
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
2
+ export const markBoundaryCursorPluginKey = new PluginKey('markBoundaryCursorPlugin');
@@ -0,0 +1,6 @@
1
+ export var MarksSide = /*#__PURE__*/function (MarksSide) {
2
+ MarksSide[MarksSide["None"] = 0] = "None";
3
+ MarksSide[MarksSide["Left"] = -1] = "Left";
4
+ MarksSide[MarksSide["Right"] = 1] = "Right";
5
+ return MarksSide;
6
+ }({});
@@ -0,0 +1,32 @@
1
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
+ var containerStyle = "\n\tposition: relative;\n";
3
+ var caretStyle = "\n\tposition: absolute;\n\theight: 100%;\n\twidth: 1px;\n\tleft: -0.5px;\n\tbottom: 0;\n\tbackground-color: ".concat("var(--ds-text, #172B4D)", ";\n");
4
+ var toDOM = function toDOM() {
5
+ var container = document.createElement('span');
6
+ container.className = 'ProseMirror-mark-boundary-cursor';
7
+ container.setAttribute('style', containerStyle);
8
+ var caret = document.createElement('div');
9
+ caret.setAttribute('style', caretStyle);
10
+ caret.animate([{
11
+ opacity: 1
12
+ }, {
13
+ opacity: 1,
14
+ offset: 0.5
15
+ }, {
16
+ opacity: 0,
17
+ offset: 0.5
18
+ }, {
19
+ opacity: 0
20
+ }], {
21
+ duration: 1000,
22
+ iterations: Infinity
23
+ });
24
+ container.appendChild(caret);
25
+ return container;
26
+ };
27
+ export var createMarkBoundaryCursorDecoration = function createMarkBoundaryCursorDecoration(pos, side) {
28
+ return Decoration.widget(pos, toDOM, {
29
+ key: 'mark-boundary-cursor',
30
+ side: side
31
+ });
32
+ };
@@ -0,0 +1,34 @@
1
+ import { isTextSelection } from '@atlaskit/editor-common/utils';
2
+ import { Mark } from '@atlaskit/editor-prosemirror/model';
3
+ import { MarksSide } from '../marks-side';
4
+ import { getInlineCodeCursorSide } from './inline-code-side';
5
+ /**
6
+ * Will determine which side of the current selection the mark-boundary-cursor should
7
+ * favour / point towards, based on which marks are currently active and which marks
8
+ * are applied to the nodes to the left and right side of the current selection.
9
+ *
10
+ * @param {Selection} options.selection - The current selection.
11
+ * @param {readonly Mark[] | null} options.storedMarks - Current stored marks, if any.
12
+ * @returns {MarksSide} - The side (left -1, right 1, or none 0) the mark-boundary-cursor should favour.
13
+ */
14
+ export function getActiveMarksSide(_ref) {
15
+ var _nodeBefore$marks, _nodeAfter$marks;
16
+ var selection = _ref.selection,
17
+ storedMarks = _ref.storedMarks;
18
+ if (!isTextSelection(selection) || !selection.empty) {
19
+ return MarksSide.None;
20
+ }
21
+ var _selection$$head = selection.$head,
22
+ nodeBefore = _selection$$head.nodeBefore,
23
+ nodeAfter = _selection$$head.nodeAfter;
24
+ var leftMarks = (_nodeBefore$marks = nodeBefore === null || nodeBefore === void 0 ? void 0 : nodeBefore.marks) !== null && _nodeBefore$marks !== void 0 ? _nodeBefore$marks : [];
25
+ var rightMarks = (_nodeAfter$marks = nodeAfter === null || nodeAfter === void 0 ? void 0 : nodeAfter.marks) !== null && _nodeAfter$marks !== void 0 ? _nodeAfter$marks : [];
26
+ if (Mark.sameSet(leftMarks, rightMarks)) {
27
+ return MarksSide.None;
28
+ }
29
+ return getInlineCodeCursorSide({
30
+ leftMarks: leftMarks,
31
+ rightMarks: rightMarks,
32
+ storedMarks: storedMarks
33
+ });
34
+ }
@@ -0,0 +1,39 @@
1
+ import { MarksSide } from '../marks-side';
2
+ /**
3
+ * Given the marks on the left and right side of the current selection, and the stored
4
+ * marks being updated during a transaction, this function returns the side (-1 = left,
5
+ * 1 = right) for which node the mark boundary cursor decoration should be added
6
+ *
7
+ * This is intended to correct an issue where the default cursor does not render in the
8
+ * expected location when navigating via arrow keys past the boundary of an inline code
9
+ * node
10
+ */
11
+ export function getInlineCodeCursorSide(_ref) {
12
+ var leftMarks = _ref.leftMarks,
13
+ rightMarks = _ref.rightMarks,
14
+ storedMarks = _ref.storedMarks;
15
+ var isInlineCodeToLeft = leftMarks.some(function (mark) {
16
+ return mark.type.name === 'code';
17
+ });
18
+ var isInlineCodeToRight = rightMarks.some(function (mark) {
19
+ return mark.type.name === 'code';
20
+ });
21
+ var isInlineCodeBeingStored = !!storedMarks && (storedMarks === null || storedMarks === void 0 ? void 0 : storedMarks.some(function (mark) {
22
+ return mark.type.name === 'code';
23
+ }));
24
+ var isStoredMarksBeingCleared = !!storedMarks && storedMarks.length === 0;
25
+
26
+ // This condition covers two scenarios:
27
+ // a) When the cursor is on the left side of the inline code, and is expected to be
28
+ // positioned within the inline code after pressing arrow right
29
+ // b) When the cursor is on the right side of the inline code, and is expected to be
30
+ // positioned outside of the inline code after pressing arrow right
31
+ // in both of these cases the cursor needs to be corrected to be positioned inline
32
+ // with the node to the right
33
+ // NOTE: In editor-plugin-text-formatting there is logic on left/right key press
34
+ // which dispatches a transaction to update the stored marks
35
+ if (isInlineCodeToRight && isInlineCodeBeingStored || isInlineCodeToLeft && isStoredMarksBeingCleared) {
36
+ return MarksSide.Right;
37
+ }
38
+ return MarksSide.None;
39
+ }
@@ -1,8 +1,11 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import { fg } from '@atlaskit/platform-feature-flags';
1
3
  import { selectNearNode as _selectNearNode } from './commands';
2
4
  import gapCursorKeymapPlugin from './pm-plugins/gap-cursor-keymap';
3
5
  import gapCursorPlugin from './pm-plugins/gap-cursor-main';
4
6
  import { gapCursorPluginKey } from './pm-plugins/gap-cursor-plugin-key';
5
7
  import selectionKeymapPlugin from './pm-plugins/keymap';
8
+ import { createMarkBoundaryCursorPlugin } from './pm-plugins/mark-boundary-cursor-main';
6
9
  import { createPlugin } from './pm-plugins/selection-main';
7
10
  import { selectionPluginKey } from './types';
8
11
  var displayGapCursor = function displayGapCursor(toggle) {
@@ -62,7 +65,12 @@ export var selectionPlugin = function selectionPlugin(_ref2) {
62
65
  plugin: function plugin() {
63
66
  return gapCursorPlugin;
64
67
  }
65
- }];
68
+ }].concat(_toConsumableArray(fg('platform_editor_mark_boundary_cursor') ? [{
69
+ name: 'markBoundaryCursor',
70
+ plugin: function plugin() {
71
+ return createMarkBoundaryCursorPlugin();
72
+ }
73
+ }] : []));
66
74
  }
67
75
  };
68
76
  };
@@ -0,0 +1,45 @@
1
+ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
3
+ import { createMarkBoundaryCursorDecoration } from '../mark-boundary-cursor/ui/mark-boundary-cursor-decoration';
4
+ import { getActiveMarksSide } from '../mark-boundary-cursor/utils/active-marks-side';
5
+ import { markBoundaryCursorPluginKey } from './mark-boundary-cursor-plugin-key';
6
+ export var createMarkBoundaryCursorPlugin = function createMarkBoundaryCursorPlugin() {
7
+ return new SafePlugin({
8
+ key: markBoundaryCursorPluginKey,
9
+ state: {
10
+ init: function init() {
11
+ return {
12
+ decorations: DecorationSet.empty
13
+ };
14
+ },
15
+ apply: function apply(tr, currentState) {
16
+ var selection = tr.selection,
17
+ storedMarks = tr.storedMarks,
18
+ doc = tr.doc,
19
+ selectionSet = tr.selectionSet,
20
+ storedMarksSet = tr.storedMarksSet;
21
+ if (!selectionSet && !storedMarksSet) {
22
+ return currentState;
23
+ }
24
+ var side = getActiveMarksSide({
25
+ selection: selection,
26
+ storedMarks: storedMarks
27
+ });
28
+ if (!side) {
29
+ return {
30
+ decorations: DecorationSet.empty
31
+ };
32
+ }
33
+ return {
34
+ decorations: DecorationSet.create(doc, [createMarkBoundaryCursorDecoration(selection.head, side)])
35
+ };
36
+ }
37
+ },
38
+ props: {
39
+ decorations: function decorations(state) {
40
+ var _markBoundaryCursorPl;
41
+ return (_markBoundaryCursorPl = markBoundaryCursorPluginKey.getState(state)) === null || _markBoundaryCursorPl === void 0 ? void 0 : _markBoundaryCursorPl.decorations;
42
+ }
43
+ }
44
+ });
45
+ };
@@ -0,0 +1,2 @@
1
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
2
+ export var markBoundaryCursorPluginKey = new PluginKey('markBoundaryCursorPlugin');
@@ -0,0 +1,5 @@
1
+ export declare enum MarksSide {
2
+ None = 0,
3
+ Left = -1,
4
+ Right = 1
5
+ }
@@ -0,0 +1,2 @@
1
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
+ export declare const createMarkBoundaryCursorDecoration: (pos: number, side: number) => Decoration;
@@ -0,0 +1,18 @@
1
+ import { Mark } from '@atlaskit/editor-prosemirror/model';
2
+ import type { Selection } from '@atlaskit/editor-prosemirror/state';
3
+ import { MarksSide } from '../marks-side';
4
+ type GetActiveMarksSideOptions = {
5
+ selection: Selection;
6
+ storedMarks?: readonly Mark[] | null;
7
+ };
8
+ /**
9
+ * Will determine which side of the current selection the mark-boundary-cursor should
10
+ * favour / point towards, based on which marks are currently active and which marks
11
+ * are applied to the nodes to the left and right side of the current selection.
12
+ *
13
+ * @param {Selection} options.selection - The current selection.
14
+ * @param {readonly Mark[] | null} options.storedMarks - Current stored marks, if any.
15
+ * @returns {MarksSide} - The side (left -1, right 1, or none 0) the mark-boundary-cursor should favour.
16
+ */
17
+ export declare function getActiveMarksSide({ selection, storedMarks, }: GetActiveMarksSideOptions): MarksSide;
18
+ export {};
@@ -0,0 +1,18 @@
1
+ import { type Mark } from '@atlaskit/editor-prosemirror/model';
2
+ import { MarksSide } from '../marks-side';
3
+ type GetInlineCodeCursorSideOptions = {
4
+ leftMarks: readonly Mark[];
5
+ rightMarks: readonly Mark[];
6
+ storedMarks?: readonly Mark[] | null;
7
+ };
8
+ /**
9
+ * Given the marks on the left and right side of the current selection, and the stored
10
+ * marks being updated during a transaction, this function returns the side (-1 = left,
11
+ * 1 = right) for which node the mark boundary cursor decoration should be added
12
+ *
13
+ * This is intended to correct an issue where the default cursor does not render in the
14
+ * expected location when navigating via arrow keys past the boundary of an inline code
15
+ * node
16
+ */
17
+ export declare function getInlineCodeCursorSide({ leftMarks, rightMarks, storedMarks, }: GetInlineCodeCursorSideOptions): MarksSide;
18
+ export {};
@@ -0,0 +1,5 @@
1
+ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
3
+ export declare const createMarkBoundaryCursorPlugin: () => SafePlugin<{
4
+ decorations: DecorationSet;
5
+ }>;
@@ -0,0 +1,2 @@
1
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
2
+ export declare const markBoundaryCursorPluginKey: PluginKey<any>;
@@ -0,0 +1,5 @@
1
+ export declare enum MarksSide {
2
+ None = 0,
3
+ Left = -1,
4
+ Right = 1
5
+ }
@@ -0,0 +1,2 @@
1
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
+ export declare const createMarkBoundaryCursorDecoration: (pos: number, side: number) => Decoration;
@@ -0,0 +1,18 @@
1
+ import { Mark } from '@atlaskit/editor-prosemirror/model';
2
+ import type { Selection } from '@atlaskit/editor-prosemirror/state';
3
+ import { MarksSide } from '../marks-side';
4
+ type GetActiveMarksSideOptions = {
5
+ selection: Selection;
6
+ storedMarks?: readonly Mark[] | null;
7
+ };
8
+ /**
9
+ * Will determine which side of the current selection the mark-boundary-cursor should
10
+ * favour / point towards, based on which marks are currently active and which marks
11
+ * are applied to the nodes to the left and right side of the current selection.
12
+ *
13
+ * @param {Selection} options.selection - The current selection.
14
+ * @param {readonly Mark[] | null} options.storedMarks - Current stored marks, if any.
15
+ * @returns {MarksSide} - The side (left -1, right 1, or none 0) the mark-boundary-cursor should favour.
16
+ */
17
+ export declare function getActiveMarksSide({ selection, storedMarks, }: GetActiveMarksSideOptions): MarksSide;
18
+ export {};
@@ -0,0 +1,18 @@
1
+ import { type Mark } from '@atlaskit/editor-prosemirror/model';
2
+ import { MarksSide } from '../marks-side';
3
+ type GetInlineCodeCursorSideOptions = {
4
+ leftMarks: readonly Mark[];
5
+ rightMarks: readonly Mark[];
6
+ storedMarks?: readonly Mark[] | null;
7
+ };
8
+ /**
9
+ * Given the marks on the left and right side of the current selection, and the stored
10
+ * marks being updated during a transaction, this function returns the side (-1 = left,
11
+ * 1 = right) for which node the mark boundary cursor decoration should be added
12
+ *
13
+ * This is intended to correct an issue where the default cursor does not render in the
14
+ * expected location when navigating via arrow keys past the boundary of an inline code
15
+ * node
16
+ */
17
+ export declare function getInlineCodeCursorSide({ leftMarks, rightMarks, storedMarks, }: GetInlineCodeCursorSideOptions): MarksSide;
18
+ export {};
@@ -0,0 +1,5 @@
1
+ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
3
+ export declare const createMarkBoundaryCursorPlugin: () => SafePlugin<{
4
+ decorations: DecorationSet;
5
+ }>;
@@ -0,0 +1,2 @@
1
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
2
+ export declare const markBoundaryCursorPluginKey: PluginKey<any>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-selection",
3
- "version": "1.4.3",
3
+ "version": "1.4.4",
4
4
  "description": "Selection plugin for @atlaskit/editor-core",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -20,11 +20,12 @@
20
20
  "runReact18": false
21
21
  },
22
22
  "dependencies": {
23
- "@atlaskit/editor-common": "^89.0.0",
23
+ "@atlaskit/editor-common": "^89.2.0",
24
24
  "@atlaskit/editor-prosemirror": "6.0.0",
25
25
  "@atlaskit/editor-shared-styles": "^2.13.0",
26
26
  "@atlaskit/editor-tables": "^2.8.0",
27
27
  "@atlaskit/platform-feature-flags": "^0.3.0",
28
+ "@atlaskit/tokens": "^1.59.0",
28
29
  "@babel/runtime": "^7.0.0"
29
30
  },
30
31
  "peerDependencies": {
@@ -78,6 +79,9 @@
78
79
  "platform-feature-flags": {
79
80
  "platform.editor.single-player-expand": {
80
81
  "type": "boolean"
82
+ },
83
+ "platform_editor_mark_boundary_cursor": {
84
+ "type": "boolean"
81
85
  }
82
86
  }
83
87
  }