@atlaskit/editor-plugin-selection 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/LICENSE.md +13 -0
  3. package/README.md +30 -0
  4. package/dist/cjs/actions.js +11 -0
  5. package/dist/cjs/commands.js +257 -0
  6. package/dist/cjs/gap-cursor/actions.js +255 -0
  7. package/dist/cjs/gap-cursor/direction.js +23 -0
  8. package/dist/cjs/gap-cursor/selection.js +30 -0
  9. package/dist/cjs/gap-cursor/utils/is-ignored.js +12 -0
  10. package/dist/cjs/gap-cursor/utils/is-valid-target-node.js +12 -0
  11. package/dist/cjs/gap-cursor/utils/place-gap-cursor.js +103 -0
  12. package/dist/cjs/gap-cursor/utils.js +137 -0
  13. package/dist/cjs/gap-cursor-selection.js +37 -0
  14. package/dist/cjs/index.js +12 -0
  15. package/dist/cjs/plugin-factory.js +49 -0
  16. package/dist/cjs/plugin.js +75 -0
  17. package/dist/cjs/pm-plugins/events/create-selection-between.js +92 -0
  18. package/dist/cjs/pm-plugins/events/keydown.js +115 -0
  19. package/dist/cjs/pm-plugins/gap-cursor-keymap.js +46 -0
  20. package/dist/cjs/pm-plugins/gap-cursor-main.js +159 -0
  21. package/dist/cjs/pm-plugins/gap-cursor-plugin-key.js +8 -0
  22. package/dist/cjs/pm-plugins/keymap.js +16 -0
  23. package/dist/cjs/pm-plugins/selection-main.js +104 -0
  24. package/dist/cjs/reducer.js +26 -0
  25. package/dist/cjs/types.js +20 -0
  26. package/dist/cjs/utils.js +280 -0
  27. package/dist/es2019/actions.js +5 -0
  28. package/dist/es2019/commands.js +250 -0
  29. package/dist/es2019/gap-cursor/actions.js +256 -0
  30. package/dist/es2019/gap-cursor/direction.js +15 -0
  31. package/dist/es2019/gap-cursor/selection.js +1 -0
  32. package/dist/es2019/gap-cursor/utils/is-ignored.js +1 -0
  33. package/dist/es2019/gap-cursor/utils/is-valid-target-node.js +1 -0
  34. package/dist/es2019/gap-cursor/utils/place-gap-cursor.js +94 -0
  35. package/dist/es2019/gap-cursor/utils.js +124 -0
  36. package/dist/es2019/gap-cursor-selection.js +2 -0
  37. package/dist/es2019/index.js +1 -0
  38. package/dist/es2019/plugin-factory.js +43 -0
  39. package/dist/es2019/plugin.js +60 -0
  40. package/dist/es2019/pm-plugins/events/create-selection-between.js +89 -0
  41. package/dist/es2019/pm-plugins/events/keydown.js +111 -0
  42. package/dist/es2019/pm-plugins/gap-cursor-keymap.js +40 -0
  43. package/dist/es2019/pm-plugins/gap-cursor-main.js +157 -0
  44. package/dist/es2019/pm-plugins/gap-cursor-plugin-key.js +2 -0
  45. package/dist/es2019/pm-plugins/keymap.js +10 -0
  46. package/dist/es2019/pm-plugins/selection-main.js +97 -0
  47. package/dist/es2019/reducer.js +18 -0
  48. package/dist/es2019/types.js +9 -0
  49. package/dist/es2019/utils.js +233 -0
  50. package/dist/esm/actions.js +5 -0
  51. package/dist/esm/commands.js +251 -0
  52. package/dist/esm/gap-cursor/actions.js +249 -0
  53. package/dist/esm/gap-cursor/direction.js +15 -0
  54. package/dist/esm/gap-cursor/selection.js +1 -0
  55. package/dist/esm/gap-cursor/utils/is-ignored.js +1 -0
  56. package/dist/esm/gap-cursor/utils/is-valid-target-node.js +1 -0
  57. package/dist/esm/gap-cursor/utils/place-gap-cursor.js +97 -0
  58. package/dist/esm/gap-cursor/utils.js +128 -0
  59. package/dist/esm/gap-cursor-selection.js +2 -0
  60. package/dist/esm/index.js +1 -0
  61. package/dist/esm/plugin-factory.js +43 -0
  62. package/dist/esm/plugin.js +68 -0
  63. package/dist/esm/pm-plugins/events/create-selection-between.js +86 -0
  64. package/dist/esm/pm-plugins/events/keydown.js +109 -0
  65. package/dist/esm/pm-plugins/gap-cursor-keymap.js +40 -0
  66. package/dist/esm/pm-plugins/gap-cursor-main.js +153 -0
  67. package/dist/esm/pm-plugins/gap-cursor-plugin-key.js +2 -0
  68. package/dist/esm/pm-plugins/keymap.js +10 -0
  69. package/dist/esm/pm-plugins/selection-main.js +98 -0
  70. package/dist/esm/reducer.js +19 -0
  71. package/dist/esm/types.js +9 -0
  72. package/dist/esm/utils.js +241 -0
  73. package/dist/types/actions.d.ts +17 -0
  74. package/dist/types/commands.d.ts +9 -0
  75. package/dist/types/gap-cursor/actions.d.ts +23 -0
  76. package/dist/types/gap-cursor/direction.d.ts +10 -0
  77. package/dist/types/gap-cursor/selection.d.ts +1 -0
  78. package/dist/types/gap-cursor/utils/is-ignored.d.ts +1 -0
  79. package/dist/types/gap-cursor/utils/is-valid-target-node.d.ts +1 -0
  80. package/dist/types/gap-cursor/utils/place-gap-cursor.d.ts +2 -0
  81. package/dist/types/gap-cursor/utils.d.ts +8 -0
  82. package/dist/types/gap-cursor-selection.d.ts +2 -0
  83. package/dist/types/index.d.ts +3 -0
  84. package/dist/types/plugin-factory.d.ts +2 -0
  85. package/dist/types/plugin.d.ts +13 -0
  86. package/dist/types/pm-plugins/events/create-selection-between.d.ts +4 -0
  87. package/dist/types/pm-plugins/events/keydown.d.ts +2 -0
  88. package/dist/types/pm-plugins/gap-cursor-keymap.d.ts +2 -0
  89. package/dist/types/pm-plugins/gap-cursor-main.d.ts +6 -0
  90. package/dist/types/pm-plugins/gap-cursor-plugin-key.d.ts +2 -0
  91. package/dist/types/pm-plugins/keymap.d.ts +3 -0
  92. package/dist/types/pm-plugins/selection-main.d.ts +7 -0
  93. package/dist/types/reducer.d.ts +3 -0
  94. package/dist/types/types.d.ts +20 -0
  95. package/dist/types/utils.d.ts +58 -0
  96. package/package.json +93 -0
  97. package/types/package.json +15 -0
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.toDOM = void 0;
8
+ var _toArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toArray"));
9
+ var _selection = require("@atlaskit/editor-common/selection");
10
+ var _utils = require("../utils");
11
+ /**
12
+ * We have a couple of nodes that require us to compute style
13
+ * on different elements, ideally all nodes should be able to
14
+ * compute the appropriate styles based on their wrapper.
15
+ */
16
+ var nestedCases = {
17
+ 'tableView-content-wrap': 'table',
18
+ 'mediaSingleView-content-wrap': '.rich-media-item',
19
+ 'bodiedExtensionView-content-wrap': '.extension-container',
20
+ 'embedCardView-content-wrap': '.rich-media-item',
21
+ 'datasourceView-content-wrap': '.datasourceView-content-inner-wrap'
22
+ };
23
+ var computeNestedStyle = function computeNestedStyle(dom) {
24
+ var foundKey = Object.keys(nestedCases).find(function (className) {
25
+ return dom.classList.contains(className);
26
+ });
27
+ var nestedSelector = foundKey && nestedCases[foundKey];
28
+ if (nestedSelector) {
29
+ var nestedElement = dom.querySelector(nestedSelector);
30
+ if (nestedElement) {
31
+ return window.getComputedStyle(nestedElement);
32
+ }
33
+ }
34
+ };
35
+ var measureHeight = function measureHeight(style) {
36
+ return measureValue(style, ['height', 'padding-top', 'padding-bottom', 'border-top-width', 'border-bottom-width']);
37
+ };
38
+ var measureWidth = function measureWidth(style) {
39
+ return measureValue(style, ['width', 'padding-left', 'padding-right', 'border-left-width', 'border-right-width']);
40
+ };
41
+ var measureValue = function measureValue(style, measureValues) {
42
+ var _measureValues = (0, _toArray2.default)(measureValues),
43
+ base = _measureValues[0],
44
+ contentBoxValues = _measureValues.slice(1);
45
+ var measures = [style.getPropertyValue(base)];
46
+ var boxSizing = style.getPropertyValue('box-sizing');
47
+ if (boxSizing === 'content-box') {
48
+ contentBoxValues.forEach(function (value) {
49
+ measures.push(style.getPropertyValue(value));
50
+ });
51
+ }
52
+ var result = 0;
53
+ for (var i = 0; i < measures.length; i++) {
54
+ result += parseFloat(measures[i]);
55
+ }
56
+ return result;
57
+ };
58
+ var mutateElementStyle = function mutateElementStyle(element, style, side) {
59
+ element.style.transform = style.getPropertyValue('transform');
60
+ if ((0, _utils.isLeftCursor)(side)) {
61
+ element.style.width = style.getPropertyValue('width');
62
+ element.style.marginLeft = style.getPropertyValue('margin-left');
63
+ } else {
64
+ var marginRight = parseFloat(style.getPropertyValue('margin-right'));
65
+ if (marginRight > 0) {
66
+ element.style.marginLeft = "-".concat(Math.abs(marginRight), "px");
67
+ } else {
68
+ element.style.paddingRight = "".concat(Math.abs(marginRight), "px");
69
+ }
70
+ }
71
+ };
72
+ var toDOM = exports.toDOM = function toDOM(view, getPos) {
73
+ var selection = view.state.selection;
74
+ var $from = selection.$from,
75
+ side = selection.side;
76
+ var isRightCursor = side === _selection.Side.RIGHT;
77
+ var node = isRightCursor ? $from.nodeBefore : $from.nodeAfter;
78
+ var nodeStart = getPos();
79
+ // @ts-ignore - [unblock prosemirror bump] nodeStart can be undefined
80
+ var dom = view.nodeDOM(nodeStart);
81
+ var element = document.createElement('span');
82
+ element.className = "ProseMirror-gapcursor ".concat(isRightCursor ? '-right' : '-left');
83
+ element.appendChild(document.createElement('span'));
84
+ if (dom instanceof HTMLElement && element.firstChild) {
85
+ var style = computeNestedStyle(dom) || window.getComputedStyle(dom);
86
+ var gapCursor = element.firstChild;
87
+ gapCursor.style.height = "".concat(measureHeight(style), "px");
88
+ var layoutMode = node && (0, _utils.getLayoutModeFromTargetNode)(node);
89
+
90
+ // TODO remove this table specific piece. need to figure out margin collapsing logic
91
+ if (nodeStart !== 0 || layoutMode || (node === null || node === void 0 ? void 0 : node.type.name) === 'table') {
92
+ gapCursor.style.marginTop = style.getPropertyValue('margin-top');
93
+ }
94
+ if (layoutMode) {
95
+ gapCursor.setAttribute('layout', layoutMode);
96
+ var breakoutModeStyle = (0, _utils.getComputedStyleForLayoutMode)(dom, node, style);
97
+ gapCursor.style.width = "".concat(measureWidth(breakoutModeStyle), "px");
98
+ } else {
99
+ mutateElementStyle(gapCursor, style, selection.side);
100
+ }
101
+ }
102
+ return element;
103
+ };
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getComputedStyleForLayoutMode = void 0;
7
+ exports.getLayoutModeFromTargetNode = getLayoutModeFromTargetNode;
8
+ exports.getMediaNearPos = getMediaNearPos;
9
+ exports.isTextBlockNearPos = exports.isLeftCursor = exports.isIgnoredClick = void 0;
10
+ var _mediaSingle = require("@atlaskit/editor-common/media-single");
11
+ var _styles = require("@atlaskit/editor-common/styles");
12
+ var _selection = require("./selection");
13
+ var isLeftCursor = exports.isLeftCursor = function isLeftCursor(side) {
14
+ return side === _selection.Side.LEFT;
15
+ };
16
+ function getMediaNearPos(doc, $pos, schema) {
17
+ var dir = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : -1;
18
+ var $currentPos = $pos;
19
+ var currentNode = null;
20
+ var _schema$nodes = schema.nodes,
21
+ mediaSingle = _schema$nodes.mediaSingle,
22
+ media = _schema$nodes.media,
23
+ mediaGroup = _schema$nodes.mediaGroup;
24
+ do {
25
+ $currentPos = doc.resolve(dir === -1 ? $currentPos.before() : $currentPos.after());
26
+ if (!$currentPos) {
27
+ return null;
28
+ }
29
+ currentNode = (dir === -1 ? $currentPos.nodeBefore : $currentPos.nodeAfter) || $currentPos.parent;
30
+ if (!currentNode || currentNode.type === schema.nodes.doc) {
31
+ return null;
32
+ }
33
+ if (currentNode.type === mediaSingle || currentNode.type === media || currentNode.type === mediaGroup) {
34
+ return currentNode;
35
+ }
36
+ } while ($currentPos.depth > 0);
37
+ return null;
38
+ }
39
+ var isTextBlockNearPos = exports.isTextBlockNearPos = function isTextBlockNearPos(doc, schema, $pos, dir) {
40
+ var $currentPos = $pos;
41
+ var currentNode = dir === -1 ? $currentPos.nodeBefore : $currentPos.nodeAfter;
42
+
43
+ // If next node is a text or a text block bail out early.
44
+ if (currentNode && (currentNode.isTextblock || currentNode.isText)) {
45
+ return true;
46
+ }
47
+ while ($currentPos.depth > 0) {
48
+ $currentPos = doc.resolve(dir === -1 ? $currentPos.before() : $currentPos.after());
49
+ if (!$currentPos) {
50
+ return false;
51
+ }
52
+ currentNode = (dir === -1 ? $currentPos.nodeBefore : $currentPos.nodeAfter) || $currentPos.parent;
53
+ if (!currentNode || currentNode.type === schema.nodes.doc) {
54
+ return false;
55
+ }
56
+ if (currentNode.isTextblock) {
57
+ return true;
58
+ }
59
+ }
60
+ var childNode = currentNode;
61
+ while (childNode && childNode.firstChild) {
62
+ childNode = childNode.firstChild;
63
+ if (childNode && (childNode.isTextblock || childNode.isText)) {
64
+ return true;
65
+ }
66
+ }
67
+ return false;
68
+ };
69
+ function getLayoutModeFromTargetNode(node) {
70
+ var layout;
71
+ if (node.attrs.layout) {
72
+ layout = node.attrs.layout;
73
+ }
74
+ if (node.marks && node.marks.length) {
75
+ layout = (node.marks.find(function (mark) {
76
+ return mark.type.name === 'breakout';
77
+ }) || {
78
+ attrs: {
79
+ mode: ''
80
+ }
81
+ }).attrs.mode;
82
+ }
83
+ if (node.type.name === 'table' && node.attrs.width) {
84
+ layout = 'fixed-width';
85
+ }
86
+ if (['wide', 'full-width', 'fixed-width'].indexOf(layout) === -1) {
87
+ return '';
88
+ }
89
+ return layout;
90
+ }
91
+ var isIgnoredClick = exports.isIgnoredClick = function isIgnoredClick(elem) {
92
+ if (elem.nodeName === 'BUTTON' || elem.closest('button')) {
93
+ return true;
94
+ }
95
+
96
+ // check if we're clicking an image caption placeholder
97
+ if (elem.closest("[data-id=\"".concat(_mediaSingle.CAPTION_PLACEHOLDER_ID, "\"]"))) {
98
+ return true;
99
+ }
100
+
101
+ // check if target node has a parent table node
102
+ var tableWrap;
103
+ var node = elem;
104
+ while (node) {
105
+ if (node.className && (node.getAttribute('class') || '').indexOf(_styles.TableSharedCssClassName.TABLE_CONTAINER) > -1) {
106
+ tableWrap = node;
107
+ break;
108
+ }
109
+ node = node.parentNode;
110
+ }
111
+ if (tableWrap) {
112
+ var rowControls = tableWrap.querySelector(".".concat(_styles.TableSharedCssClassName.TABLE_ROW_CONTROLS_WRAPPER));
113
+ var isColumnControlsDecoration = elem && elem.classList && elem.classList.contains(_styles.TableSharedCssClassName.TABLE_COLUMN_CONTROLS_DECORATIONS);
114
+ return rowControls && rowControls.contains(elem) || isColumnControlsDecoration;
115
+ }
116
+
117
+ // Check if unsupported node selection
118
+ // (without this, selection requires double clicking in FF due to posAtCoords differences)
119
+ if (elem.closest(".".concat(_styles.UnsupportedSharedCssClassName.BLOCK_CONTAINER))) {
120
+ return true;
121
+ }
122
+ return false;
123
+ };
124
+
125
+ /*
126
+ Calculates custom style for breakout mode
127
+ Mainly to handle table width to include the numbered column width as well
128
+ */
129
+ var getComputedStyleForLayoutMode = exports.getComputedStyleForLayoutMode = function getComputedStyleForLayoutMode(dom, node, style) {
130
+ if (node && node.type.name === 'table') {
131
+ var tableContainer = dom.querySelector('.pm-table-container');
132
+ if (tableContainer) {
133
+ return window.getComputedStyle(tableContainer);
134
+ }
135
+ }
136
+ return style;
137
+ };
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "GapCursorSelection", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _selection.GapCursorSelection;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "Side", {
13
+ enumerable: true,
14
+ get: function get() {
15
+ return _selection.Side;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "hasGapCursorPlugin", {
19
+ enumerable: true,
20
+ get: function get() {
21
+ return _actions.hasGapCursorPlugin;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "setCursorForTopLevelBlocks", {
25
+ enumerable: true,
26
+ get: function get() {
27
+ return _actions.setCursorForTopLevelBlocks;
28
+ }
29
+ });
30
+ Object.defineProperty(exports, "setSelectionTopLevelBlocks", {
31
+ enumerable: true,
32
+ get: function get() {
33
+ return _actions.setSelectionTopLevelBlocks;
34
+ }
35
+ });
36
+ var _selection = require("@atlaskit/editor-common/selection");
37
+ var _actions = require("./gap-cursor/actions");
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "selectionPlugin", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _plugin.selectionPlugin;
10
+ }
11
+ });
12
+ var _plugin = require("./plugin");
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.getPluginState = exports.createPluginState = exports.createCommand = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _utils = require("@atlaskit/editor-common/utils");
10
+ var _state = require("@atlaskit/editor-prosemirror/state");
11
+ var _view = require("@atlaskit/editor-prosemirror/view");
12
+ var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
13
+ var _reducer = require("./reducer");
14
+ var _types = require("./types");
15
+ var _utils2 = require("./utils");
16
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
17
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
18
+ var handleDocChanged = function handleDocChanged(tr, pluginState) {
19
+ // in some collab edge cases mapping decorations could throw an error
20
+ try {
21
+ if (pluginState.decorationSet.find().length === 0 && (!tr.selectionSet || (0, _utils2.getDecorations)(tr).find().length === 0)) {
22
+ return pluginState;
23
+ }
24
+ var decorationSet = pluginState.decorationSet.map(tr.mapping, tr.doc);
25
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
26
+ decorationSet: decorationSet
27
+ });
28
+ } catch (error) {
29
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
30
+ decorationSet: _view.DecorationSet.empty
31
+ });
32
+ }
33
+ };
34
+ var handleSelectionChanged = function handleSelectionChanged(tr, pluginState) {
35
+ // Reset relative selection pos when user clicks to select a node
36
+ if ((tr.selection instanceof _state.NodeSelection && (0, _utils2.isSelectableContainerNode)(tr.selection.node) || tr.selection instanceof _cellSelection.CellSelection) && !tr.getMeta(_types.selectionPluginKey)) {
37
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
38
+ selectionRelativeToNode: undefined
39
+ });
40
+ }
41
+ return pluginState;
42
+ };
43
+ var _pluginFactory = (0, _utils.pluginFactory)(_types.selectionPluginKey, _reducer.reducer, {
44
+ onDocChanged: handleDocChanged,
45
+ onSelectionChanged: handleSelectionChanged
46
+ }),
47
+ createCommand = exports.createCommand = _pluginFactory.createCommand,
48
+ getPluginState = exports.getPluginState = _pluginFactory.getPluginState,
49
+ createPluginState = exports.createPluginState = _pluginFactory.createPluginState;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.selectionPlugin = exports.default = void 0;
8
+ var _commands = require("./commands");
9
+ var _gapCursorKeymap = _interopRequireDefault(require("./pm-plugins/gap-cursor-keymap"));
10
+ var _gapCursorMain = _interopRequireDefault(require("./pm-plugins/gap-cursor-main"));
11
+ var _gapCursorPluginKey = require("./pm-plugins/gap-cursor-plugin-key");
12
+ var _keymap = _interopRequireDefault(require("./pm-plugins/keymap"));
13
+ var _selectionMain = require("./pm-plugins/selection-main");
14
+ var _types = require("./types");
15
+ var displayGapCursor = function displayGapCursor(toggle) {
16
+ return function (_ref) {
17
+ var tr = _ref.tr;
18
+ return tr.setMeta(_gapCursorPluginKey.gapCursorPluginKey, {
19
+ displayGapCursor: toggle
20
+ });
21
+ };
22
+ };
23
+ var selectionPlugin = exports.selectionPlugin = function selectionPlugin(_ref2) {
24
+ var options = _ref2.config;
25
+ return {
26
+ name: 'selection',
27
+ commands: {
28
+ displayGapCursor: displayGapCursor
29
+ },
30
+ actions: {
31
+ selectNearNode: function selectNearNode(_ref3) {
32
+ var selectionRelativeToNode = _ref3.selectionRelativeToNode,
33
+ selection = _ref3.selection;
34
+ return function (state) {
35
+ return (0, _commands.selectNearNode)(selectionRelativeToNode, selection)({
36
+ tr: state.tr
37
+ }) || state.tr;
38
+ };
39
+ }
40
+ },
41
+ getSharedState: function getSharedState(editorState) {
42
+ if (!editorState) {
43
+ return undefined;
44
+ }
45
+ var pluginState = _types.selectionPluginKey.getState(editorState);
46
+ return {
47
+ selectionRelativeToNode: pluginState === null || pluginState === void 0 ? void 0 : pluginState.selectionRelativeToNode
48
+ };
49
+ },
50
+ pmPlugins: function pmPlugins() {
51
+ return [{
52
+ name: 'selection',
53
+ plugin: function plugin(_ref4) {
54
+ var dispatch = _ref4.dispatch,
55
+ dispatchAnalyticsEvent = _ref4.dispatchAnalyticsEvent;
56
+ return (0, _selectionMain.createPlugin)(dispatch, dispatchAnalyticsEvent, options);
57
+ }
58
+ }, {
59
+ name: 'selectionKeymap',
60
+ plugin: _keymap.default
61
+ }, {
62
+ name: 'gapCursorKeymap',
63
+ plugin: function plugin() {
64
+ return (0, _gapCursorKeymap.default)();
65
+ }
66
+ }, {
67
+ name: 'gapCursor',
68
+ plugin: function plugin() {
69
+ return _gapCursorMain.default;
70
+ }
71
+ }];
72
+ }
73
+ };
74
+ };
75
+ var _default = exports.default = selectionPlugin;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.onCreateSelectionBetween = void 0;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ function isNodeContentEmpty(maybeNode) {
9
+ return (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.content.size) === 0 || (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.textContent) === '';
10
+ }
11
+ function findEmptySelectableParentNodePosition($pos, isValidPosition) {
12
+ var doc = $pos.doc;
13
+ if ($pos.pos + 1 > doc.content.size) {
14
+ return null;
15
+ }
16
+ if ($pos.nodeBefore !== null) {
17
+ if (isValidPosition($pos)) {
18
+ return $pos;
19
+ }
20
+
21
+ // We can not use `$pos.before()` because ProseMirror throws an error when depth is zero.
22
+ var currentPosIndex = $pos.index();
23
+ if (currentPosIndex === 0) {
24
+ return null;
25
+ }
26
+ var previousIndex = currentPosIndex - 1;
27
+ var $previousPos = $pos.doc.resolve($pos.posAtIndex(previousIndex));
28
+ if (isValidPosition($previousPos)) {
29
+ return $previousPos;
30
+ }
31
+ return null;
32
+ }
33
+ if (isValidPosition($pos)) {
34
+ return $pos;
35
+ }
36
+ var positionLevelUp = $pos.before();
37
+ var resolvedPositionLevelUp = doc.resolve(positionLevelUp);
38
+ return findEmptySelectableParentNodePosition(resolvedPositionLevelUp, isValidPosition);
39
+ }
40
+ var checkPositionNode = function checkPositionNode($pos) {
41
+ var maybeNode = $pos.nodeAfter;
42
+ if (!maybeNode || !maybeNode.isBlock) {
43
+ return false;
44
+ }
45
+ if (maybeNode.isAtom) {
46
+ return true;
47
+ }
48
+ return isNodeContentEmpty(maybeNode) && _state.NodeSelection.isSelectable(maybeNode);
49
+ };
50
+ function findNextSelectionPosition(_ref) {
51
+ var $targetHead = _ref.$targetHead,
52
+ $anchor = _ref.$anchor,
53
+ doc = _ref.doc;
54
+ var direction = $anchor.pos < $targetHead.pos ? 'down' : 'up';
55
+ var maybeNextPosition = findEmptySelectableParentNodePosition($targetHead, checkPositionNode);
56
+ if (maybeNextPosition && maybeNextPosition.nodeAfter) {
57
+ var nodeAfter = maybeNextPosition.nodeAfter;
58
+ var pos = maybeNextPosition.pos;
59
+ var nextPositionToSelect = direction === 'down' ? Math.min(nodeAfter.nodeSize + pos, doc.content.size) : Math.max(pos, 0);
60
+ return doc.resolve(nextPositionToSelect);
61
+ }
62
+ return null;
63
+ }
64
+ var onCreateSelectionBetween = exports.onCreateSelectionBetween = function onCreateSelectionBetween(view, $anchor, $head) {
65
+ var _$head$parent, _$head$parent2;
66
+ if ($anchor.pos === $head.pos) {
67
+ return null;
68
+ }
69
+ if ($anchor.depth === $head.depth && $anchor.sameParent($head)) {
70
+ return null;
71
+ }
72
+
73
+ // If the head is targeting a paragraph on root, then let ProseMirror handle the text selection
74
+ if ($head.depth === 1 && ((_$head$parent = $head.parent) === null || _$head$parent === void 0 ? void 0 : _$head$parent.type.name) === 'paragraph') {
75
+ return null;
76
+ }
77
+
78
+ // If head is at the beginning of a non-empty textblock, let ProseMirror handle the text selection
79
+ if ((_$head$parent2 = $head.parent) !== null && _$head$parent2 !== void 0 && _$head$parent2.isTextblock && !isNodeContentEmpty($head.parent) && $head.parentOffset === 0) {
80
+ return null;
81
+ }
82
+ var $nextHeadPosition = findNextSelectionPosition({
83
+ $targetHead: $head,
84
+ $anchor: $anchor,
85
+ doc: view.state.doc
86
+ });
87
+ if (!$nextHeadPosition) {
88
+ return null;
89
+ }
90
+ var forcedTextSelection = _state.TextSelection.create(view.state.doc, $anchor.pos, $nextHeadPosition.pos);
91
+ return forcedTextSelection;
92
+ };
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.onKeydown = void 0;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ /*
9
+ * The way expand was built, no browser reconize selection on it.
10
+ * For instance, when a selection going to a "collapsed" expand
11
+ * the browser will try to send the cursor to inside the expand content (wrong),
12
+ * this behavior is caused because the expand content is never true hidden
13
+ * we just set the height to 1px.
14
+ *
15
+ * So, we need to capture a possible selection event
16
+ * when a collapsed exxpand is the next node in the common depth.
17
+ * If that is true, we create a new TextSelection and stop the event bubble
18
+ */
19
+ var isCollpasedExpand = function isCollpasedExpand(node) {
20
+ return Boolean(node && ['expand', 'nestedExpand'].includes(node.type.name) && !node.attrs.__expanded);
21
+ };
22
+
23
+ /**
24
+ * ED-18072 - Cannot shift + arrow past bodied extension if it is not empty
25
+ */
26
+ var isBodiedExtension = function isBodiedExtension(node) {
27
+ return Boolean(node && ['bodiedExtension'].includes(node.type.name));
28
+ };
29
+
30
+ /**
31
+ * ED-19861 - [Regression] keyboard selections within action items are unpredicatable
32
+ * Table was added to the list of problematic nodes because the desired behaviour when Shift+Up from outside the
33
+ * table is to select the table node itself, rather than the table cell content. Previously this behaviour was handled
34
+ * in `packages/editor/editor-core/src/plugins/selection/pm-plugins/events/create-selection-between.ts` but there was
35
+ * a bug in `create-selection-between` which after fixing the bug that code was no longer handling table selection
36
+ * correctly, so to fix that table was added here.
37
+ */
38
+ var isTable = function isTable(node) {
39
+ return Boolean(node && ['table'].includes(node.type.name));
40
+ };
41
+ var isProblematicNode = function isProblematicNode(node) {
42
+ return isCollpasedExpand(node) || isBodiedExtension(node) || isTable(node);
43
+ };
44
+ var findFixedProblematicNodePosition = function findFixedProblematicNodePosition(doc, $head, direction) {
45
+ if ($head.pos === 0 || $head.depth === 0) {
46
+ return null;
47
+ }
48
+ if (direction === 'up') {
49
+ var pos = $head.before();
50
+ var $posResolved = $head.doc.resolve(pos);
51
+ var maybeProblematicNode = $posResolved.nodeBefore;
52
+ if (maybeProblematicNode && isProblematicNode(maybeProblematicNode)) {
53
+ var nodeSize = maybeProblematicNode.nodeSize;
54
+ var nodeStartPosition = pos - nodeSize;
55
+
56
+ // ($head.pos - 1) will correspond to (nodeStartPosition + nodeSize) when we are at the start of the text node
57
+ var isAtEndOfProblematicNode = $head.pos - 1 === nodeStartPosition + nodeSize;
58
+ if (isAtEndOfProblematicNode) {
59
+ var startPosNode = Math.max(nodeStartPosition, 0);
60
+ var $startPosNode = $head.doc.resolve(Math.min(startPosNode, $head.doc.content.size));
61
+ return $startPosNode;
62
+ }
63
+ }
64
+ }
65
+ if (direction === 'down') {
66
+ var _pos = $head.after();
67
+ var _maybeProblematicNode = doc.nodeAt(_pos);
68
+ if (_maybeProblematicNode && isProblematicNode(_maybeProblematicNode) && $head.pos + 1 === _pos) {
69
+ var _nodeSize = _maybeProblematicNode.nodeSize;
70
+ var nodePosition = _pos + _nodeSize;
71
+ var _startPosNode = Math.max(nodePosition, 0);
72
+ var _$startPosNode = $head.doc.resolve(Math.min(_startPosNode, $head.doc.content.size));
73
+ return _$startPosNode;
74
+ }
75
+ }
76
+ return null;
77
+ };
78
+ var onKeydown = exports.onKeydown = function onKeydown(view, event) {
79
+ /*
80
+ * This workaround is needed for some specific situations.
81
+ * - expand collapse
82
+ * - bodied extension
83
+ */
84
+ if (!(event instanceof KeyboardEvent)) {
85
+ return false;
86
+ }
87
+ if (!event.shiftKey || event.ctrlKey || event.metaKey) {
88
+ return false;
89
+ }
90
+ if (!['ArrowUp', 'ArrowDown', 'ArrowRight', 'ArrowLeft', 'Home', 'End'].includes(event.key)) {
91
+ return false;
92
+ }
93
+ var _view$state = view.state,
94
+ doc = _view$state.doc,
95
+ _view$state$selection = _view$state.selection,
96
+ $head = _view$state$selection.$head,
97
+ $anchor = _view$state$selection.$anchor;
98
+ if (event.key === 'ArrowRight' && $head.nodeAfter || event.key === 'ArrowLeft' && $head.nodeBefore) {
99
+ return false;
100
+ }
101
+ var direction = ['ArrowLeft', 'ArrowUp', 'Home'].includes(event.key) ? 'up' : 'down';
102
+ var $fixedProblematicNodePosition = findFixedProblematicNodePosition(doc, $head, direction);
103
+ if ($fixedProblematicNodePosition) {
104
+ // an offset is used here so that left arrow selects the first character before the node (consistent with arrow right)
105
+ var headOffset = event.key === 'ArrowLeft' ? -1 : 0;
106
+ var head = $fixedProblematicNodePosition.pos + headOffset;
107
+ var forcedTextSelection = _state.TextSelection.create(view.state.doc, $anchor.pos, head);
108
+ var tr = view.state.tr;
109
+ tr.setSelection(forcedTextSelection);
110
+ view.dispatch(tr);
111
+ event.preventDefault();
112
+ return true;
113
+ }
114
+ return false;
115
+ };
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = keymapPlugin;
7
+ var _keymaps = require("@atlaskit/editor-common/keymaps");
8
+ var _commands = require("@atlaskit/editor-prosemirror/commands");
9
+ var _keymap = require("@atlaskit/editor-prosemirror/keymap");
10
+ var _actions = require("../gap-cursor/actions");
11
+ var _direction = require("../gap-cursor/direction");
12
+ var _selection = require("../gap-cursor/selection");
13
+ function keymapPlugin() {
14
+ var map = {};
15
+ (0, _keymaps.bindKeymapWithCommand)(_keymaps.insertNewLine.common, function (state, dispatch, view) {
16
+ var isInGapCursor = state.selection instanceof _selection.GapCursorSelection;
17
+ // Only operate in gap cursor
18
+ if (!isInGapCursor) {
19
+ return false;
20
+ }
21
+ return (0, _commands.createParagraphNear)(state, dispatch);
22
+ }, map);
23
+ (0, _keymaps.bindKeymapWithCommand)(_keymaps.moveLeft.common, function (state, dispatch, view) {
24
+ var endOfTextblock = view ? view.endOfTextblock.bind(view) : undefined;
25
+ return (0, _actions.arrow)(_direction.Direction.LEFT, endOfTextblock)(state, dispatch, view);
26
+ }, map);
27
+ (0, _keymaps.bindKeymapWithCommand)(_keymaps.moveRight.common, function (state, dispatch, view) {
28
+ var endOfTextblock = view ? view.endOfTextblock.bind(view) : undefined;
29
+ return (0, _actions.arrow)(_direction.Direction.RIGHT, endOfTextblock)(state, dispatch);
30
+ }, map);
31
+ (0, _keymaps.bindKeymapWithCommand)(_keymaps.moveUp.common, function (state, dispatch, view) {
32
+ var endOfTextblock = view ? view.endOfTextblock.bind(view) : undefined;
33
+ return (0, _actions.arrow)(_direction.Direction.UP, endOfTextblock)(state, dispatch);
34
+ }, map);
35
+ (0, _keymaps.bindKeymapWithCommand)(_keymaps.moveDown.common, function (state, dispatch, view) {
36
+ var endOfTextblock = view ? view.endOfTextblock.bind(view) : undefined;
37
+ return (0, _actions.arrow)(_direction.Direction.DOWN, endOfTextblock)(state, dispatch);
38
+ }, map);
39
+
40
+ // default PM's Backspace doesn't handle removing block nodes when cursor is after it
41
+ (0, _keymaps.bindKeymapWithCommand)(_keymaps.backspace.common, (0, _actions.deleteNode)(_direction.Direction.BACKWARD), map);
42
+
43
+ // handle Delete key (remove node after the cursor)
44
+ (0, _keymaps.bindKeymapWithCommand)(_keymaps.deleteKey.common, (0, _actions.deleteNode)(_direction.Direction.FORWARD), map);
45
+ return (0, _keymap.keymap)(map);
46
+ }