@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
package/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ # @atlaskit/editor-plugin-selection
package/LICENSE.md ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2023 Atlassian Pty Ltd
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # Editor plugin selection
2
+
3
+ Selection plugin for @atlaskit/editor-core
4
+
5
+ **Note:** This component is designed for internal Atlassian development.
6
+ External contributors will be able to use this component but will not be able to submit issues.
7
+
8
+ ## Install
9
+ ---
10
+ - **Install** - *yarn add @atlaskit/editor-plugin-selection*
11
+ - **npm** - [@atlaskit/editor-plugin-selection](https://www.npmjs.com/package/@atlaskit/editor-plugin-selection)
12
+ - **Source** - [Bitbucket](https://bitbucket.org/atlassian/atlassian-frontend/src/master/packages/editor/editor-plugin-selection)
13
+ - **Bundle** - [unpkg.com](https://unpkg.com/@atlaskit/editor-plugin-selection/dist/)
14
+
15
+ ## Usage
16
+ ---
17
+ **Internal use only**
18
+
19
+ @atlaskit/editor-plugin-selection is intended for internal use by the @atlaskit/editor-core and as a plugin dependency of the Editor within your product.
20
+
21
+ Direct use of this component is not supported.
22
+
23
+ Please see [Atlaskit - Editor plugin selection](https://atlaskit.atlassian.com/packages/editor/editor-plugin-selection) for documentation and examples for this package.
24
+
25
+ ## Support
26
+ ---
27
+ For internal Atlassian, visit the slack channel [#help-editor](https://atlassian.slack.com/archives/CFG3PSQ9E) for support or visit [go/editor-help](https://go/editor-help) to submit a bug.
28
+ ## License
29
+ ---
30
+ Please see [Atlassian Frontend - License](https://developer.atlassian.com/cloud/framework/atlassian-frontend/#license) for more licensing information.
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SelectionActionTypes = void 0;
7
+ var SelectionActionTypes = exports.SelectionActionTypes = /*#__PURE__*/function (SelectionActionTypes) {
8
+ SelectionActionTypes["SET_DECORATIONS"] = "SET_DECORATIONS";
9
+ SelectionActionTypes["SET_RELATIVE_SELECTION"] = "SET_RELATIVE_SELECTION";
10
+ return SelectionActionTypes;
11
+ }({});
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.setSelectionRelativeToNode = exports.setSelectionInsideAtNodeEnd = exports.selectNearNode = exports.arrowRight = exports.arrowLeft = void 0;
7
+ var _selection = require("@atlaskit/editor-common/selection");
8
+ var _utils = require("@atlaskit/editor-common/utils");
9
+ var _state = require("@atlaskit/editor-prosemirror/state");
10
+ var _actions = require("./actions");
11
+ var _gapCursorSelection = require("./gap-cursor-selection");
12
+ var _pluginFactory = require("./plugin-factory");
13
+ var _types = require("./types");
14
+ var _utils2 = require("./utils");
15
+ var selectNearNode = exports.selectNearNode = function selectNearNode(selectionRelativeToNode, selection) {
16
+ return function (_ref) {
17
+ var tr = _ref.tr;
18
+ tr.setMeta(_types.selectionPluginKey, {
19
+ type: _actions.SelectionActionTypes.SET_RELATIVE_SELECTION,
20
+ selectionRelativeToNode: selectionRelativeToNode
21
+ });
22
+ if (selection) {
23
+ return tr.setSelection(selection);
24
+ }
25
+ return tr;
26
+ };
27
+ };
28
+ var setSelectionRelativeToNode = exports.setSelectionRelativeToNode = function setSelectionRelativeToNode(selectionRelativeToNode, selection) {
29
+ return (0, _pluginFactory.createCommand)({
30
+ type: _actions.SelectionActionTypes.SET_RELATIVE_SELECTION,
31
+ selectionRelativeToNode: selectionRelativeToNode
32
+ }, function (tr) {
33
+ return selectNearNode(selectionRelativeToNode, selection)({
34
+ tr: tr
35
+ }) || tr;
36
+ });
37
+ };
38
+ var arrowRight = exports.arrowRight = function arrowRight(state, dispatch) {
39
+ var selection = state.selection;
40
+ if (selection instanceof _gapCursorSelection.GapCursorSelection) {
41
+ return arrowRightFromGapCursor(selection)(state, dispatch);
42
+ } else if (selection instanceof _state.NodeSelection) {
43
+ return arrowRightFromNode(selection)(state, dispatch);
44
+ } else if (selection instanceof _state.TextSelection) {
45
+ return arrowRightFromText(selection)(state, dispatch);
46
+ }
47
+ return false;
48
+ };
49
+ var arrowLeft = exports.arrowLeft = function arrowLeft(state, dispatch) {
50
+ var selection = state.selection;
51
+ if (selection instanceof _gapCursorSelection.GapCursorSelection) {
52
+ return arrowLeftFromGapCursor(selection)(state, dispatch);
53
+ } else if (selection instanceof _state.NodeSelection) {
54
+ return arrowLeftFromNode(selection)(state, dispatch);
55
+ } else if (selection instanceof _state.TextSelection) {
56
+ return arrowLeftFromText(selection)(state, dispatch);
57
+ }
58
+ return false;
59
+ };
60
+ var arrowRightFromGapCursor = function arrowRightFromGapCursor(selection) {
61
+ return function (state, dispatch) {
62
+ var $from = selection.$from,
63
+ $to = selection.$to,
64
+ side = selection.side;
65
+ if (side === _gapCursorSelection.Side.LEFT) {
66
+ var selectableNode = (0, _utils2.findSelectableContainerAfter)($to, state.doc);
67
+ if (selectableNode) {
68
+ return setSelectionRelativeToNode(_types.RelativeSelectionPos.Start, _state.NodeSelection.create(state.doc, selectableNode.pos))(state, dispatch);
69
+ }
70
+ } else if (side === _gapCursorSelection.Side.RIGHT && (0, _utils2.isSelectionAtEndOfParentNode)($from, selection)) {
71
+ var _selectableNode = (0, _utils2.findSelectableContainerParent)(selection);
72
+ if (_selectableNode) {
73
+ return setSelectionRelativeToNode(_types.RelativeSelectionPos.End, _state.NodeSelection.create(state.doc, _selectableNode.pos))(state, dispatch);
74
+ }
75
+ }
76
+ return false;
77
+ };
78
+ };
79
+ var arrowLeftFromGapCursor = function arrowLeftFromGapCursor(selection) {
80
+ return function (state, dispatch) {
81
+ var $from = selection.$from,
82
+ side = selection.side;
83
+ var _getPluginState = (0, _pluginFactory.getPluginState)(state),
84
+ selectionRelativeToNode = _getPluginState.selectionRelativeToNode;
85
+ if (side === _gapCursorSelection.Side.RIGHT) {
86
+ var selectableNode = (0, _utils2.findSelectableContainerBefore)($from, state.doc);
87
+ if (selectableNode) {
88
+ return setSelectionRelativeToNode(_types.RelativeSelectionPos.End, _state.NodeSelection.create(state.doc, selectableNode.pos))(state, dispatch);
89
+ }
90
+ } else if (side === _gapCursorSelection.Side.LEFT && (0, _utils2.isSelectionAtStartOfParentNode)($from, selection)) {
91
+ if (selectionRelativeToNode === _types.RelativeSelectionPos.Before) {
92
+ var $parent = state.doc.resolve(selection.$from.before(selection.$from.depth));
93
+ if ($parent) {
94
+ var _selectableNode2 = (0, _utils2.findSelectableContainerBefore)($parent, state.doc);
95
+ if (_selectableNode2 && (0, _selection.isIgnored)(_selectableNode2.node)) {
96
+ // selection is inside node without gap cursor preceeded by another node without gap cursor - set node selection for previous node
97
+ return setSelectionRelativeToNode(_types.RelativeSelectionPos.End, _state.NodeSelection.create(state.doc, _selectableNode2.pos))(state, dispatch);
98
+ }
99
+ }
100
+ // we don't return this as we want to reset the relative pos, but not block other plugins
101
+ // from responding to arrow left key
102
+ setSelectionRelativeToNode()(state, dispatch);
103
+ } else {
104
+ var _selectableNode3 = (0, _utils2.findSelectableContainerParent)(selection);
105
+ if (_selectableNode3) {
106
+ return setSelectionRelativeToNode(_types.RelativeSelectionPos.Start, _state.NodeSelection.create(state.doc, _selectableNode3.pos))(state, dispatch);
107
+ }
108
+ }
109
+ }
110
+ return false;
111
+ };
112
+ };
113
+ var arrowRightFromNode = function arrowRightFromNode(selection) {
114
+ return function (state, dispatch) {
115
+ var node = selection.node,
116
+ from = selection.from,
117
+ $to = selection.$to;
118
+ var _getPluginState2 = (0, _pluginFactory.getPluginState)(state),
119
+ selectionRelativeToNode = _getPluginState2.selectionRelativeToNode;
120
+ if (node.isAtom) {
121
+ if ((0, _utils2.isSelectionAtEndOfParentNode)($to, selection)) {
122
+ // selection is for inline node that is the last child of its parent node - set text selection after it
123
+ return findAndSetTextSelection(_types.RelativeSelectionPos.End, state.doc.resolve(from + 1), _types.SelectionDirection.After)(state, dispatch);
124
+ }
125
+ return false;
126
+ } else if (selectionRelativeToNode === _types.RelativeSelectionPos.Start) {
127
+ // selection is for container node - set selection inside it at the start
128
+ return setSelectionInsideAtNodeStart(_types.RelativeSelectionPos.Inside, node, from)(state, dispatch);
129
+ } else if ((0, _selection.isIgnored)(node) && (!selectionRelativeToNode || selectionRelativeToNode === _types.RelativeSelectionPos.End)) {
130
+ var selectableNode = (0, _utils2.findSelectableContainerAfter)($to, state.doc);
131
+ if (selectableNode && (0, _selection.isIgnored)(selectableNode.node)) {
132
+ // selection is for node without gap cursor followed by another node without gap cursor - set node selection for next node
133
+ return setSelectionRelativeToNode(_types.RelativeSelectionPos.Start, _state.NodeSelection.create(state.doc, selectableNode.pos))(state, dispatch);
134
+ }
135
+ }
136
+ return false;
137
+ };
138
+ };
139
+ var arrowLeftFromNode = function arrowLeftFromNode(selection) {
140
+ return function (state, dispatch) {
141
+ var node = selection.node,
142
+ from = selection.from,
143
+ to = selection.to,
144
+ $from = selection.$from;
145
+ var _getPluginState3 = (0, _pluginFactory.getPluginState)(state),
146
+ selectionRelativeToNode = _getPluginState3.selectionRelativeToNode;
147
+ if (node.isAtom) {
148
+ if ((0, _utils2.isSelectionAtStartOfParentNode)($from, selection)) {
149
+ // selection is for inline node that is the first child of its parent node - set text selection before it
150
+ return findAndSetTextSelection(_types.RelativeSelectionPos.Start, state.doc.resolve(from), _types.SelectionDirection.Before)(state, dispatch);
151
+ }
152
+ return false;
153
+ } else if (selectionRelativeToNode === _types.RelativeSelectionPos.End) {
154
+ // selection is for container node - set selection inside it at the end
155
+ return setSelectionInsideAtNodeEnd(_types.RelativeSelectionPos.Inside, node, from, to)(state, dispatch);
156
+ } else if (!selectionRelativeToNode || selectionRelativeToNode === _types.RelativeSelectionPos.Inside) {
157
+ // selection is for container node - set selection inside it at the start
158
+ // (this is a special case when the user selects by clicking node)
159
+ return setSelectionInsideAtNodeStart(_types.RelativeSelectionPos.Before, node, from)(state, dispatch);
160
+ } else if ((0, _selection.isIgnored)(node) && selectionRelativeToNode === _types.RelativeSelectionPos.Start) {
161
+ // selection is for node without gap cursor preceeded by another node without gap cursor - set node selection for previous node
162
+ var selectableNode = (0, _utils2.findSelectableContainerBefore)($from, state.doc);
163
+ if (selectableNode && (0, _selection.isIgnored)(selectableNode.node)) {
164
+ return setSelectionRelativeToNode(_types.RelativeSelectionPos.End, _state.NodeSelection.create(state.doc, selectableNode.pos))(state, dispatch);
165
+ }
166
+ }
167
+ return false;
168
+ };
169
+ };
170
+ var arrowRightFromText = function arrowRightFromText(selection) {
171
+ return function (state, dispatch) {
172
+ if ((0, _utils2.isSelectionAtEndOfParentNode)(selection.$to, selection)) {
173
+ var selectableNode = (0, _utils2.findSelectableContainerParent)(selection);
174
+ if (selectableNode) {
175
+ return setSelectionRelativeToNode(_types.RelativeSelectionPos.End, _state.NodeSelection.create(state.doc, selectableNode.pos))(state, dispatch);
176
+ }
177
+ }
178
+ return false;
179
+ };
180
+ };
181
+ var arrowLeftFromText = function arrowLeftFromText(selection) {
182
+ return function (state, dispatch) {
183
+ var _getPluginState4 = (0, _pluginFactory.getPluginState)(state),
184
+ selectionRelativeToNode = _getPluginState4.selectionRelativeToNode;
185
+ if (selectionRelativeToNode === _types.RelativeSelectionPos.Before) {
186
+ var selectableNode = (0, _utils2.findSelectableContainerBefore)(selection.$from, state.doc);
187
+ if (selectableNode && (0, _selection.isIgnored)(selectableNode.node)) {
188
+ // selection is inside node without gap cursor preceeded by another node without gap cursor - set node selection for previous node
189
+ return setSelectionRelativeToNode(_types.RelativeSelectionPos.End, _state.NodeSelection.create(state.doc, selectableNode.pos))(state, dispatch);
190
+ }
191
+ // we don't return this as we want to reset the relative pos, but not block other plugins
192
+ // from responding to arrow left key
193
+ setSelectionRelativeToNode(undefined)(state, dispatch);
194
+ } else if ((0, _utils2.isSelectionAtStartOfParentNode)(selection.$from, selection)) {
195
+ var _selectableNode4 = (0, _utils2.findSelectableContainerParent)(selection);
196
+ if (_selectableNode4) {
197
+ return setSelectionRelativeToNode(_types.RelativeSelectionPos.Start, _state.NodeSelection.create(state.doc, _selectableNode4.pos))(state, dispatch);
198
+ }
199
+ }
200
+ return false;
201
+ };
202
+ };
203
+ var findAndSetTextSelection = function findAndSetTextSelection(selectionRelativeToNode, $pos, dir) {
204
+ return function (state, dispatch) {
205
+ var sel = _state.Selection.findFrom($pos, dir, true);
206
+ if (sel) {
207
+ return setSelectionRelativeToNode(selectionRelativeToNode, sel)(state, dispatch);
208
+ }
209
+ return false;
210
+ };
211
+ };
212
+ var setSelectionInsideAtNodeStart = function setSelectionInsideAtNodeStart(selectionRelativeToNode, node, pos) {
213
+ return function (state, dispatch) {
214
+ if ((0, _utils.isNodeEmpty)(node)) {
215
+ return findAndSetTextSelection(selectionRelativeToNode, state.doc.resolve(pos), _types.SelectionDirection.After)(state, dispatch);
216
+ }
217
+ var selectableNode = (0, _utils2.findFirstChildNodeToSelect)(node);
218
+ if (selectableNode) {
219
+ var childNode = selectableNode.node,
220
+ childPos = selectableNode.pos;
221
+ var selectionPos = pos + childPos + 1;
222
+ if (childNode.isText || childNode.isAtom) {
223
+ return findAndSetTextSelection(selectionRelativeToNode, state.doc.resolve(selectionPos), _types.SelectionDirection.Before)(state, dispatch);
224
+ } else if ((0, _utils.isEmptyParagraph)(childNode)) {
225
+ return findAndSetTextSelection(selectionRelativeToNode, state.doc.resolve(selectionPos + 1), _types.SelectionDirection.Before)(state, dispatch);
226
+ } else if (!(0, _selection.isIgnored)(node)) {
227
+ return setSelectionRelativeToNode(selectionRelativeToNode, new _gapCursorSelection.GapCursorSelection(state.doc.resolve(selectionPos), _gapCursorSelection.Side.LEFT))(state, dispatch);
228
+ } else if ((0, _utils2.isSelectableContainerNode)(node)) {
229
+ return setSelectionRelativeToNode(selectionRelativeToNode, _state.NodeSelection.create(state.doc, selectionPos))(state, dispatch);
230
+ }
231
+ }
232
+ return false;
233
+ };
234
+ };
235
+ var setSelectionInsideAtNodeEnd = exports.setSelectionInsideAtNodeEnd = function setSelectionInsideAtNodeEnd(selectionRelativeToNode, node, from, to) {
236
+ return function (state, dispatch) {
237
+ if ((0, _utils.isNodeEmpty)(node)) {
238
+ return findAndSetTextSelection(selectionRelativeToNode, state.doc.resolve(to), _types.SelectionDirection.Before)(state, dispatch);
239
+ }
240
+ var selectableNode = (0, _utils2.findLastChildNodeToSelect)(node);
241
+ if (selectableNode) {
242
+ var childNode = selectableNode.node,
243
+ childPos = selectableNode.pos;
244
+ var selectionPos = from + childPos + childNode.nodeSize;
245
+ if (childNode.isText || childNode.isAtom) {
246
+ return findAndSetTextSelection(selectionRelativeToNode, state.doc.resolve(selectionPos + 1), _types.SelectionDirection.After)(state, dispatch);
247
+ } else if ((0, _utils.isEmptyParagraph)(childNode)) {
248
+ return findAndSetTextSelection(selectionRelativeToNode, state.doc.resolve(selectionPos), _types.SelectionDirection.After)(state, dispatch);
249
+ } else if (!(0, _selection.isIgnored)(node)) {
250
+ return setSelectionRelativeToNode(selectionRelativeToNode, new _gapCursorSelection.GapCursorSelection(state.doc.resolve(selectionPos + 1), _gapCursorSelection.Side.RIGHT))(state, dispatch);
251
+ } else if ((0, _utils2.isSelectableContainerNode)(node)) {
252
+ return setSelectionRelativeToNode(selectionRelativeToNode, _state.NodeSelection.create(state.doc, selectionPos))(state, dispatch);
253
+ }
254
+ }
255
+ return false;
256
+ };
257
+ };
@@ -0,0 +1,255 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.shouldSkipGapCursor = exports.setSelectionTopLevelBlocks = exports.setCursorForTopLevelBlocks = exports.hasGapCursorPlugin = exports.deleteNode = exports.arrow = void 0;
7
+ var _selection = require("@atlaskit/editor-common/selection");
8
+ var _utils = require("@atlaskit/editor-common/utils");
9
+ var _state = require("@atlaskit/editor-prosemirror/state");
10
+ var _utils2 = require("@atlaskit/editor-prosemirror/utils");
11
+ var _gapCursorPluginKey = require("../pm-plugins/gap-cursor-plugin-key");
12
+ var _direction = require("./direction");
13
+ var _selection2 = require("./selection");
14
+ var _utils3 = require("./utils");
15
+ var _isValidTargetNode = require("./utils/is-valid-target-node");
16
+ var shouldSkipGapCursor = exports.shouldSkipGapCursor = function shouldSkipGapCursor(direction, state, $pos) {
17
+ var _$pos$nodeBefore;
18
+ var doc = state.doc,
19
+ schema = state.schema;
20
+ switch (direction) {
21
+ case _direction.Direction.UP:
22
+ if ((0, _selection.atTheBeginningOfDoc)(state)) {
23
+ return false;
24
+ }
25
+ return (0, _utils.isPositionNearTableRow)($pos, schema, 'before') || (0, _utils3.isTextBlockNearPos)(doc, schema, $pos, -1) || (0, _utils.isNodeBeforeMediaNode)($pos, state);
26
+ case _direction.Direction.DOWN:
27
+ return (0, _selection.atTheEndOfDoc)(state) || (0, _utils3.isTextBlockNearPos)(doc, schema, $pos, 1) || (0, _utils.isPositionNearTableRow)($pos, schema, 'after') || ((_$pos$nodeBefore = $pos.nodeBefore) === null || _$pos$nodeBefore === void 0 ? void 0 : _$pos$nodeBefore.type.name) === 'text' && !$pos.nodeAfter // end of a paragraph
28
+ ;
29
+
30
+ default:
31
+ return false;
32
+ }
33
+ };
34
+
35
+ // These cases should be handled using the handleMediaGapCursor function
36
+ function shouldHandleMediaGapCursor(dir, state) {
37
+ var _selection$$from$node;
38
+ var selection = state.selection;
39
+ var upArrowFromGapCursorIntoMedia = selection instanceof _selection2.GapCursorSelection && dir === _direction.Direction.UP && selection.$from.nodeBefore && (0, _utils.isMediaNode)(selection.$from.nodeBefore);
40
+ var downArrowFromGapCursorIntoMediaGroup = selection instanceof _selection2.GapCursorSelection && dir === _direction.Direction.DOWN && ((_selection$$from$node = selection.$from.nodeAfter) === null || _selection$$from$node === void 0 ? void 0 : _selection$$from$node.type.name) === 'mediaGroup';
41
+ return upArrowFromGapCursorIntoMedia || downArrowFromGapCursorIntoMediaGroup;
42
+ }
43
+
44
+ // Handle media gap cursor for up/down arrow into media nodes
45
+ // Should check this case by using shouldHandleMediaGapCursor first
46
+ function handleMediaGapCursor(dir, state) {
47
+ var selection = state.selection,
48
+ tr = state.tr;
49
+ var $pos = (0, _direction.isBackward)(dir) ? selection.$from : selection.$to;
50
+ if (dir === _direction.Direction.UP && selection.$from.nodeBefore && (0, _utils.isMediaNode)(selection.$from.nodeBefore)) {
51
+ var _tr$doc$nodeAt;
52
+ var nodeBeforePos = (0, _utils2.findPositionOfNodeBefore)(tr.selection);
53
+ if (nodeBeforePos && selection.side === 'right' && ((_tr$doc$nodeAt = tr.doc.nodeAt(nodeBeforePos)) === null || _tr$doc$nodeAt === void 0 ? void 0 : _tr$doc$nodeAt.type.name) === 'mediaSingle') {
54
+ tr.setSelection(new _state.NodeSelection(tr.doc.resolve(nodeBeforePos))).scrollIntoView();
55
+ } else if (nodeBeforePos || nodeBeforePos === 0) {
56
+ tr.setSelection(new _selection2.GapCursorSelection(tr.doc.resolve(nodeBeforePos), _selection2.Side.LEFT)).scrollIntoView();
57
+ }
58
+ }
59
+ if (dir === _direction.Direction.DOWN && selection.$from.nodeAfter) {
60
+ var nodeAfterPos = selection.side === 'right' ? $pos.pos : $pos.pos + selection.$from.nodeAfter.nodeSize;
61
+ if (nodeAfterPos) {
62
+ tr.setSelection(new _selection2.GapCursorSelection(tr.doc.resolve(nodeAfterPos), _selection2.Side.LEFT)).scrollIntoView();
63
+ }
64
+ }
65
+ return tr;
66
+ }
67
+ var arrow = exports.arrow = function arrow(dir, endOfTextblock) {
68
+ return function (state, dispatch, view) {
69
+ var doc = state.doc,
70
+ selection = state.selection,
71
+ tr = state.tr;
72
+ var $pos = (0, _direction.isBackward)(dir) ? selection.$from : selection.$to;
73
+ var mustMove = selection.empty;
74
+
75
+ // start from text selection
76
+ if (selection instanceof _state.TextSelection) {
77
+ // if cursor is in the middle of a text node, do nothing
78
+ if (!endOfTextblock || !endOfTextblock(dir.toString())) {
79
+ return false;
80
+ }
81
+
82
+ // UP/DOWN jumps to the nearest texblock skipping gapcursor whenever possible
83
+ if (shouldSkipGapCursor(dir, state, $pos)) {
84
+ return false;
85
+ }
86
+
87
+ // otherwise resolve previous/next position
88
+ $pos = doc.resolve((0, _direction.isBackward)(dir) ? $pos.before() : $pos.after());
89
+ mustMove = false;
90
+ }
91
+ if (selection instanceof _state.NodeSelection) {
92
+ if (selection.node.isInline) {
93
+ return false;
94
+ }
95
+ if (dir === _direction.Direction.UP && !(0, _selection.atTheBeginningOfDoc)(state) && !(0, _utils.isNodeBeforeMediaNode)($pos, state) || dir === _direction.Direction.DOWN) {
96
+ // We dont add gap cursor on node selections going up and down
97
+ // Except we do if we're going up for a block node which is the
98
+ // first node in the document OR the node before is a media node
99
+ return false;
100
+ }
101
+ }
102
+
103
+ // Handle media gap cursor for up/down arrow into media nodes
104
+ if (shouldHandleMediaGapCursor(dir, state)) {
105
+ var updatedTr = handleMediaGapCursor(dir, state);
106
+ if (dispatch) {
107
+ dispatch(updatedTr);
108
+ }
109
+ return true;
110
+ }
111
+
112
+ // when jumping between block nodes at the same depth, we need to reverse cursor without changing ProseMirror position
113
+ if (selection instanceof _selection2.GapCursorSelection &&
114
+ // next node allow gap cursor position
115
+ (0, _isValidTargetNode.isValidTargetNode)((0, _direction.isBackward)(dir) ? $pos.nodeBefore : $pos.nodeAfter) && (
116
+ // gap cursor changes block node
117
+ (0, _direction.isBackward)(dir) && selection.side === _selection2.Side.LEFT || (0, _direction.isForward)(dir) && selection.side === _selection2.Side.RIGHT)) {
118
+ // reverse cursor position
119
+ if (dispatch) {
120
+ dispatch(tr.setSelection(new _selection2.GapCursorSelection($pos, selection.side === _selection2.Side.RIGHT ? _selection2.Side.LEFT : _selection2.Side.RIGHT)).scrollIntoView());
121
+ }
122
+ return true;
123
+ }
124
+ if (view) {
125
+ var domAtPos = view.domAtPos.bind(view);
126
+ var target = (0, _utils2.findDomRefAtPos)($pos.pos, domAtPos);
127
+ if (target && target.textContent === _utils.ZERO_WIDTH_SPACE) {
128
+ return false;
129
+ }
130
+ }
131
+ var nextSelection = _selection2.GapCursorSelection.findFrom($pos, (0, _direction.isBackward)(dir) ? -1 : 1, mustMove);
132
+ if (!nextSelection) {
133
+ return false;
134
+ }
135
+ if (!(0, _isValidTargetNode.isValidTargetNode)((0, _direction.isForward)(dir) ? nextSelection.$from.nodeBefore : nextSelection.$from.nodeAfter)) {
136
+ // reverse cursor position
137
+ if (dispatch) {
138
+ dispatch(tr.setSelection(new _selection2.GapCursorSelection(nextSelection.$from, (0, _direction.isForward)(dir) ? _selection2.Side.LEFT : _selection2.Side.RIGHT)).scrollIntoView());
139
+ }
140
+ return true;
141
+ }
142
+ if (dispatch) {
143
+ dispatch(tr.setSelection(nextSelection).scrollIntoView());
144
+ }
145
+ return true;
146
+ };
147
+ };
148
+ var deleteNode = exports.deleteNode = function deleteNode(dir) {
149
+ return function (state, dispatch) {
150
+ if (state.selection instanceof _selection2.GapCursorSelection) {
151
+ var _state$selection = state.selection,
152
+ $from = _state$selection.$from,
153
+ $anchor = _state$selection.$anchor;
154
+ var tr = state.tr;
155
+ if ((0, _direction.isBackward)(dir)) {
156
+ if (state.selection.side === 'left') {
157
+ tr.setSelection(new _selection2.GapCursorSelection($anchor, _selection2.Side.RIGHT));
158
+ if (dispatch) {
159
+ dispatch(tr);
160
+ }
161
+ return true;
162
+ }
163
+ tr = (0, _utils2.removeNodeBefore)(state.tr);
164
+ } else if ($from.nodeAfter) {
165
+ tr = tr.delete($from.pos, $from.pos + $from.nodeAfter.nodeSize);
166
+ }
167
+ if (dispatch) {
168
+ dispatch(tr.setSelection(_state.Selection.near(tr.doc.resolve(tr.mapping.map(state.selection.$from.pos)))).scrollIntoView());
169
+ }
170
+ return true;
171
+ }
172
+ return false;
173
+ };
174
+ };
175
+
176
+ // This function captures clicks outside of the ProseMirror contentEditable area
177
+ // see also description of "handleClick" in gap-cursor pm-plugin
178
+ var captureCursorCoords = function captureCursorCoords(event, editorRef, posAtCoords, tr) {
179
+ var rect = editorRef.getBoundingClientRect();
180
+
181
+ // capture clicks before the first block element
182
+ if (event.clientY < rect.top) {
183
+ return {
184
+ position: 0,
185
+ side: _selection2.Side.LEFT
186
+ };
187
+ }
188
+ if (rect.left > 0) {
189
+ // calculate start position of a node that is vertically at the same level
190
+ var _coords = posAtCoords({
191
+ left: rect.left,
192
+ top: event.clientY
193
+ });
194
+ if (_coords && _coords.inside > -1) {
195
+ var $from = tr.doc.resolve(_coords.inside);
196
+ var start = $from.before(1);
197
+ var side = event.clientX < rect.left ? _selection2.Side.LEFT : _selection2.Side.RIGHT;
198
+ var position;
199
+ if (side === _selection2.Side.LEFT) {
200
+ position = start;
201
+ } else {
202
+ var node = tr.doc.nodeAt(start);
203
+ if (node) {
204
+ position = start + node.nodeSize;
205
+ }
206
+ }
207
+ return {
208
+ position: position,
209
+ side: side
210
+ };
211
+ }
212
+ }
213
+ return null;
214
+ };
215
+ var setSelectionTopLevelBlocks = exports.setSelectionTopLevelBlocks = function setSelectionTopLevelBlocks(tr, event, editorRef, posAtCoords, editorFocused) {
216
+ var cursorCoords = captureCursorCoords(event, editorRef, posAtCoords, tr);
217
+ if (!cursorCoords) {
218
+ return;
219
+ }
220
+ var $pos = cursorCoords.position !== undefined ? tr.doc.resolve(cursorCoords.position) : null;
221
+ if ($pos === null) {
222
+ return;
223
+ }
224
+ var isGapCursorAllowed = cursorCoords.side === _selection2.Side.LEFT ? (0, _isValidTargetNode.isValidTargetNode)($pos.nodeAfter) : (0, _isValidTargetNode.isValidTargetNode)($pos.nodeBefore);
225
+ if (isGapCursorAllowed && _selection2.GapCursorSelection.valid($pos)) {
226
+ // this forces PM to re-render the decoration node if we change the side of the gap cursor, it doesn't do it by default
227
+ if (tr.selection instanceof _selection2.GapCursorSelection) {
228
+ tr.setSelection(_state.Selection.near($pos));
229
+ } else {
230
+ tr.setSelection(new _selection2.GapCursorSelection($pos, cursorCoords.side));
231
+ }
232
+ }
233
+ // try to set text selection if the editor isnt focused
234
+ // if the editor is focused, we are most likely dragging a selection outside.
235
+ else if (editorFocused === false) {
236
+ var selectionTemp = _state.Selection.findFrom($pos, cursorCoords.side === _selection2.Side.LEFT ? 1 : -1, true);
237
+ if (selectionTemp) {
238
+ tr.setSelection(selectionTemp);
239
+ }
240
+ }
241
+ };
242
+ var setCursorForTopLevelBlocks = exports.setCursorForTopLevelBlocks = function setCursorForTopLevelBlocks(event, editorRef, posAtCoords, editorFocused) {
243
+ return function (state, dispatch) {
244
+ var tr = state.tr;
245
+ setSelectionTopLevelBlocks(tr, event, editorRef, posAtCoords, editorFocused);
246
+ if (tr.selectionSet && dispatch) {
247
+ dispatch(tr);
248
+ return true;
249
+ }
250
+ return false;
251
+ };
252
+ };
253
+ var hasGapCursorPlugin = exports.hasGapCursorPlugin = function hasGapCursorPlugin(state) {
254
+ return Boolean(_gapCursorPluginKey.gapCursorPluginKey.get(state));
255
+ };
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Direction = void 0;
7
+ exports.isBackward = isBackward;
8
+ exports.isForward = isForward;
9
+ var Direction = exports.Direction = /*#__PURE__*/function (Direction) {
10
+ Direction["UP"] = "up";
11
+ Direction["RIGHT"] = "right";
12
+ Direction["DOWN"] = "down";
13
+ Direction["LEFT"] = "left";
14
+ Direction["BACKWARD"] = "backward";
15
+ Direction["FORWARD"] = "forward";
16
+ return Direction;
17
+ }({});
18
+ function isBackward(dir) {
19
+ return [Direction.UP, Direction.LEFT, Direction.BACKWARD].indexOf(dir) !== -1;
20
+ }
21
+ function isForward(dir) {
22
+ return [Direction.RIGHT, Direction.DOWN, Direction.FORWARD].indexOf(dir) !== -1;
23
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "GapBookmark", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _selection.GapBookmark;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "GapCursorSelection", {
13
+ enumerable: true,
14
+ get: function get() {
15
+ return _selection.GapCursorSelection;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "JSON_ID", {
19
+ enumerable: true,
20
+ get: function get() {
21
+ return _selection.JSON_ID;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "Side", {
25
+ enumerable: true,
26
+ get: function get() {
27
+ return _selection.Side;
28
+ }
29
+ });
30
+ var _selection = require("@atlaskit/editor-common/selection");
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "isIgnored", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _selection.isIgnored;
10
+ }
11
+ });
12
+ var _selection = require("@atlaskit/editor-common/selection");
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "isValidTargetNode", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _selection.isValidTargetNode;
10
+ }
11
+ });
12
+ var _selection = require("@atlaskit/editor-common/selection");