@atlaskit/editor-plugin-block-controls 7.11.3 → 7.11.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 7.11.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [`26f8da78a699c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/26f8da78a699c) -
8
+ EDITOR-3756 Fix initial collapse of preserved selection
9
+ - Updated dependencies
10
+
3
11
  ## 7.11.3
4
12
 
5
13
  ### Patch Changes
@@ -8,11 +8,7 @@ exports.createSelectionPreservationPlugin = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _monitoring = require("@atlaskit/editor-common/monitoring");
10
10
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
11
- var _selection = require("@atlaskit/editor-common/selection");
12
- var _state = require("@atlaskit/editor-prosemirror/state");
13
- var _transform = require("@atlaskit/editor-prosemirror/transform");
14
- var _main = require("../main");
15
- var _getSelection = require("../utils/getSelection");
11
+ var _selection = require("../utils/selection");
16
12
  var _editorCommands = require("./editor-commands");
17
13
  var _pluginKey = require("./plugin-key");
18
14
  var _utils = require("./utils");
@@ -64,7 +60,7 @@ var createSelectionPreservationPlugin = exports.createSelectionPreservationPlugi
64
60
  newState.preservedSelection = undefined;
65
61
  }
66
62
  if (newState.preservedSelection && tr.docChanged) {
67
- newState.preservedSelection = mapSelection(newState.preservedSelection, tr);
63
+ newState.preservedSelection = (0, _selection.mapPreservedSelection)(newState.preservedSelection, tr);
68
64
  }
69
65
  return newState;
70
66
  }
@@ -97,44 +93,4 @@ var createSelectionPreservationPlugin = exports.createSelectionPreservationPlugi
97
93
  return null;
98
94
  }
99
95
  });
100
- };
101
- var mapSelection = function mapSelection(selection, tr) {
102
- var _ref = (0, _main.getBlockControlsMeta)(tr) || {},
103
- nodeMoved = _ref.nodeMoved,
104
- nodeMovedOffset = _ref.nodeMovedOffset;
105
- var mapping = nodeMoved && typeof nodeMovedOffset === 'number' ? new _transform.Mapping([new _transform.StepMap([0, 0, nodeMovedOffset])]) : tr.mapping;
106
- if (selection instanceof _state.TextSelection) {
107
- var from = mapping.map(selection.from);
108
- var to = mapping.map(selection.to);
109
- var isSelectionEmpty = from === to;
110
- var wasSelectionEmpty = selection.from === selection.to;
111
- if (isSelectionEmpty) {
112
- if (!wasSelectionEmpty) {
113
- // If selection has become empty i.e. content has been deleted, stop preserving
114
- return undefined;
115
- }
116
- // When preserving a cursor selection, just map the position without expanding
117
- return new _state.TextSelection(tr.doc.resolve(from));
118
- }
119
-
120
- // expand the text selection range to block boundaries, so as document changes occur the
121
- // selection always includes whole nodes
122
- var expanded = (0, _selection.expandToBlockRange)(tr.doc.resolve(from), tr.doc.resolve(to));
123
-
124
- // collapse the expanded range to a valid selection range
125
- var _collapseToSelectionR = (0, _getSelection.collapseToSelectionRange)(expanded.$from, expanded.$to),
126
- $from = _collapseToSelectionR.$from,
127
- $to = _collapseToSelectionR.$to;
128
-
129
- // stop preserving if preserved selection becomes invalid
130
- if ($from.pos < 0 || $to.pos > tr.doc.content.size || $from.pos >= $to.pos) {
131
- return undefined;
132
- }
133
- return new _state.TextSelection($from, $to);
134
- }
135
- try {
136
- return selection.map(tr.doc, mapping);
137
- } catch (_unused) {
138
- return undefined;
139
- }
140
96
  };
@@ -3,9 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.getSelectedSlicePosition = exports.getMultiSelectionIfPosInside = exports.expandSelectionHeadToNodeAtPos = exports.alignAnchorHeadInDirectionOfPos = void 0;
6
+ exports.mapPreservedSelection = exports.getSelectedSlicePosition = exports.getMultiSelectionIfPosInside = exports.expandSelectionHeadToNodeAtPos = exports.alignAnchorHeadInDirectionOfPos = void 0;
7
+ var _selection = require("@atlaskit/editor-common/selection");
7
8
  var _state = require("@atlaskit/editor-prosemirror/state");
9
+ var _transform = require("@atlaskit/editor-prosemirror/transform");
8
10
  var _main = require("../main");
11
+ var _getSelection = require("./getSelection");
9
12
  var getMultiSelectionIfPosInside = exports.getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(api, pos, tr) {
10
13
  var _api$blockControls, _pluginState$multiSel, _tr$getMeta;
11
14
  var pluginState = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState();
@@ -26,7 +29,12 @@ var getMultiSelectionIfPosInside = exports.getMultiSelectionIfPosInside = functi
26
29
  };
27
30
 
28
31
  /**
32
+ * Given a handle position, returns the from and to positions of the selected content.
33
+ * If the handle position is not in a multi-selection, it returns the node's from and to positions.
29
34
  *
35
+ * @param handlePos The position of the handle
36
+ * @param tr The transaction to use for position calculations
37
+ * @param api The BlockControlsPlugin API for accessing shared state
30
38
  * @returns from and to positions of the selected content (after expansion)
31
39
  */
32
40
  var getSelectedSlicePosition = exports.getSelectedSlicePosition = function getSelectedSlicePosition(handlePos, tr, api) {
@@ -72,4 +80,52 @@ var expandSelectionHeadToNodeAtPos = exports.expandSelectionHeadToNodeAtPos = fu
72
80
  */
73
81
  var alignAnchorHeadInDirectionOfPos = exports.alignAnchorHeadInDirectionOfPos = function alignAnchorHeadInDirectionOfPos(selection, pos) {
74
82
  return selection instanceof _state.NodeSelection && Math.max(pos, selection.anchor) === selection.anchor ? new _state.TextSelection(selection.$head, selection.$anchor) : selection;
83
+ };
84
+
85
+ /**
86
+ * This maps a preserved selection through a transaction, expanding text selections to block boundaries.
87
+ *
88
+ * @param selection The existing preserved selection to map
89
+ * @param tr The transaction to map through
90
+ * @returns The mapped selection or undefined if mapping is not possible
91
+ */
92
+ var mapPreservedSelection = exports.mapPreservedSelection = function mapPreservedSelection(selection, tr) {
93
+ var _ref = (0, _main.getBlockControlsMeta)(tr) || {},
94
+ nodeMoved = _ref.nodeMoved,
95
+ nodeMovedOffset = _ref.nodeMovedOffset;
96
+ var mapping = nodeMoved && typeof nodeMovedOffset === 'number' ? new _transform.Mapping([new _transform.StepMap([0, 0, nodeMovedOffset])]) : tr.mapping;
97
+ if (selection instanceof _state.TextSelection) {
98
+ var from = mapping.map(selection.from);
99
+ var to = mapping.map(selection.to);
100
+ var isSelectionEmpty = from === to;
101
+ var wasSelectionEmpty = selection.from === selection.to;
102
+ if (isSelectionEmpty) {
103
+ if (!wasSelectionEmpty) {
104
+ // If selection has become empty i.e. content has been deleted, stop preserving
105
+ return undefined;
106
+ }
107
+ // When preserving a cursor selection, just map the position without expanding
108
+ return new _state.TextSelection(tr.doc.resolve(from));
109
+ }
110
+
111
+ // expand the text selection range to block boundaries, so as document changes occur the
112
+ // selection always includes whole nodes
113
+ var expanded = (0, _selection.expandToBlockRange)(tr.doc.resolve(from), tr.doc.resolve(to));
114
+
115
+ // collapse the expanded range to a valid selection range
116
+ var _collapseToSelectionR = (0, _getSelection.collapseToSelectionRange)(expanded.$from, expanded.$to),
117
+ $from = _collapseToSelectionR.$from,
118
+ $to = _collapseToSelectionR.$to;
119
+
120
+ // stop preserving if preserved selection becomes invalid
121
+ if ($from.pos < 0 || $to.pos > tr.doc.content.size || $from.pos >= $to.pos) {
122
+ return undefined;
123
+ }
124
+ return new _state.TextSelection($from, $to);
125
+ }
126
+ try {
127
+ return selection.map(tr.doc, mapping);
128
+ } catch (_unused) {
129
+ return undefined;
130
+ }
75
131
  };
@@ -410,13 +410,14 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref2) {
410
410
  var handleOnClickNew = (0, _react.useCallback)(function (e) {
411
411
  var _api$core;
412
412
  api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref3) {
413
- var _api$analytics, _resolvedStartPos$nod, _selectionPreservatio, _api$blockControls, _api$blockControls2;
413
+ var _selectionPreservatio, _api$analytics, _resolvedStartPos$nod, _api$blockControls, _api$blockControls2;
414
414
  var tr = _ref3.tr;
415
415
  var startPos = getPos();
416
416
  if (startPos === undefined) {
417
417
  return tr;
418
418
  }
419
419
  var resolvedStartPos = tr.doc.resolve(startPos);
420
+ var selection = ((_selectionPreservatio = _pluginKey.selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection) || tr.selection;
420
421
  api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
421
422
  eventType: _analytics.EVENT_TYPE.UI,
422
423
  action: _analytics.ACTION.CLICKED,
@@ -427,7 +428,6 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref2) {
427
428
  nodeType: ((_resolvedStartPos$nod = resolvedStartPos.nodeAfter) === null || _resolvedStartPos$nod === void 0 ? void 0 : _resolvedStartPos$nod.type.name) || ''
428
429
  }
429
430
  })(tr);
430
- var selection = ((_selectionPreservatio = _pluginKey.selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection) || tr.selection;
431
431
  var range = getExpandedSelectionRange({
432
432
  doc: tr.doc,
433
433
  selection: selection,
@@ -1,10 +1,6 @@
1
1
  import { logException } from '@atlaskit/editor-common/monitoring';
2
2
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
3
- import { expandToBlockRange } from '@atlaskit/editor-common/selection';
4
- import { TextSelection } from '@atlaskit/editor-prosemirror/state';
5
- import { Mapping, StepMap } from '@atlaskit/editor-prosemirror/transform';
6
- import { getBlockControlsMeta } from '../main';
7
- import { collapseToSelectionRange } from '../utils/getSelection';
3
+ import { mapPreservedSelection } from '../utils/selection';
8
4
  import { stopPreservingSelection } from './editor-commands';
9
5
  import { selectionPreservationPluginKey } from './plugin-key';
10
6
  import { getSelectionPreservationMeta, hasUserSelectionChange } from './utils';
@@ -57,7 +53,7 @@ export const createSelectionPreservationPlugin = () => {
57
53
  newState.preservedSelection = undefined;
58
54
  }
59
55
  if (newState.preservedSelection && tr.docChanged) {
60
- newState.preservedSelection = mapSelection(newState.preservedSelection, tr);
56
+ newState.preservedSelection = mapPreservedSelection(newState.preservedSelection, tr);
61
57
  }
62
58
  return newState;
63
59
  }
@@ -90,46 +86,4 @@ export const createSelectionPreservationPlugin = () => {
90
86
  return null;
91
87
  }
92
88
  });
93
- };
94
- const mapSelection = (selection, tr) => {
95
- const {
96
- nodeMoved,
97
- nodeMovedOffset
98
- } = getBlockControlsMeta(tr) || {};
99
- const mapping = nodeMoved && typeof nodeMovedOffset === 'number' ? new Mapping([new StepMap([0, 0, nodeMovedOffset])]) : tr.mapping;
100
- if (selection instanceof TextSelection) {
101
- const from = mapping.map(selection.from);
102
- const to = mapping.map(selection.to);
103
- const isSelectionEmpty = from === to;
104
- const wasSelectionEmpty = selection.from === selection.to;
105
- if (isSelectionEmpty) {
106
- if (!wasSelectionEmpty) {
107
- // If selection has become empty i.e. content has been deleted, stop preserving
108
- return undefined;
109
- }
110
- // When preserving a cursor selection, just map the position without expanding
111
- return new TextSelection(tr.doc.resolve(from));
112
- }
113
-
114
- // expand the text selection range to block boundaries, so as document changes occur the
115
- // selection always includes whole nodes
116
- const expanded = expandToBlockRange(tr.doc.resolve(from), tr.doc.resolve(to));
117
-
118
- // collapse the expanded range to a valid selection range
119
- const {
120
- $from,
121
- $to
122
- } = collapseToSelectionRange(expanded.$from, expanded.$to);
123
-
124
- // stop preserving if preserved selection becomes invalid
125
- if ($from.pos < 0 || $to.pos > tr.doc.content.size || $from.pos >= $to.pos) {
126
- return undefined;
127
- }
128
- return new TextSelection($from, $to);
129
- }
130
- try {
131
- return selection.map(tr.doc, mapping);
132
- } catch {
133
- return undefined;
134
- }
135
89
  };
@@ -1,5 +1,8 @@
1
- import { TextSelection, NodeSelection } from '@atlaskit/editor-prosemirror/state';
2
- import { key } from '../main';
1
+ import { expandToBlockRange } from '@atlaskit/editor-common/selection';
2
+ import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
3
+ import { Mapping, StepMap } from '@atlaskit/editor-prosemirror/transform';
4
+ import { getBlockControlsMeta, key } from '../main';
5
+ import { collapseToSelectionRange } from './getSelection';
3
6
  export const getMultiSelectionIfPosInside = (api, pos, tr) => {
4
7
  var _api$blockControls, _pluginState$multiSel, _tr$getMeta;
5
8
  const pluginState = api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState();
@@ -20,7 +23,12 @@ export const getMultiSelectionIfPosInside = (api, pos, tr) => {
20
23
  };
21
24
 
22
25
  /**
26
+ * Given a handle position, returns the from and to positions of the selected content.
27
+ * If the handle position is not in a multi-selection, it returns the node's from and to positions.
23
28
  *
29
+ * @param handlePos The position of the handle
30
+ * @param tr The transaction to use for position calculations
31
+ * @param api The BlockControlsPlugin API for accessing shared state
24
32
  * @returns from and to positions of the selected content (after expansion)
25
33
  */
26
34
  export const getSelectedSlicePosition = (handlePos, tr, api) => {
@@ -67,4 +75,54 @@ export const expandSelectionHeadToNodeAtPos = (selection, nodePos) => {
67
75
  */
68
76
  export const alignAnchorHeadInDirectionOfPos = (selection, pos) => {
69
77
  return selection instanceof NodeSelection && Math.max(pos, selection.anchor) === selection.anchor ? new TextSelection(selection.$head, selection.$anchor) : selection;
78
+ };
79
+
80
+ /**
81
+ * This maps a preserved selection through a transaction, expanding text selections to block boundaries.
82
+ *
83
+ * @param selection The existing preserved selection to map
84
+ * @param tr The transaction to map through
85
+ * @returns The mapped selection or undefined if mapping is not possible
86
+ */
87
+ export const mapPreservedSelection = (selection, tr) => {
88
+ const {
89
+ nodeMoved,
90
+ nodeMovedOffset
91
+ } = getBlockControlsMeta(tr) || {};
92
+ const mapping = nodeMoved && typeof nodeMovedOffset === 'number' ? new Mapping([new StepMap([0, 0, nodeMovedOffset])]) : tr.mapping;
93
+ if (selection instanceof TextSelection) {
94
+ const from = mapping.map(selection.from);
95
+ const to = mapping.map(selection.to);
96
+ const isSelectionEmpty = from === to;
97
+ const wasSelectionEmpty = selection.from === selection.to;
98
+ if (isSelectionEmpty) {
99
+ if (!wasSelectionEmpty) {
100
+ // If selection has become empty i.e. content has been deleted, stop preserving
101
+ return undefined;
102
+ }
103
+ // When preserving a cursor selection, just map the position without expanding
104
+ return new TextSelection(tr.doc.resolve(from));
105
+ }
106
+
107
+ // expand the text selection range to block boundaries, so as document changes occur the
108
+ // selection always includes whole nodes
109
+ const expanded = expandToBlockRange(tr.doc.resolve(from), tr.doc.resolve(to));
110
+
111
+ // collapse the expanded range to a valid selection range
112
+ const {
113
+ $from,
114
+ $to
115
+ } = collapseToSelectionRange(expanded.$from, expanded.$to);
116
+
117
+ // stop preserving if preserved selection becomes invalid
118
+ if ($from.pos < 0 || $to.pos > tr.doc.content.size || $from.pos >= $to.pos) {
119
+ return undefined;
120
+ }
121
+ return new TextSelection($from, $to);
122
+ }
123
+ try {
124
+ return selection.map(tr.doc, mapping);
125
+ } catch {
126
+ return undefined;
127
+ }
70
128
  };
@@ -389,12 +389,13 @@ export const DragHandle = ({
389
389
  api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
390
390
  tr
391
391
  }) => {
392
- var _api$analytics, _resolvedStartPos$nod, _selectionPreservatio, _api$blockControls, _api$blockControls2;
392
+ var _selectionPreservatio, _api$analytics, _resolvedStartPos$nod, _api$blockControls, _api$blockControls2;
393
393
  const startPos = getPos();
394
394
  if (startPos === undefined) {
395
395
  return tr;
396
396
  }
397
397
  const resolvedStartPos = tr.doc.resolve(startPos);
398
+ const selection = ((_selectionPreservatio = selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection) || tr.selection;
398
399
  api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.attachAnalyticsEvent({
399
400
  eventType: EVENT_TYPE.UI,
400
401
  action: ACTION.CLICKED,
@@ -405,7 +406,6 @@ export const DragHandle = ({
405
406
  nodeType: ((_resolvedStartPos$nod = resolvedStartPos.nodeAfter) === null || _resolvedStartPos$nod === void 0 ? void 0 : _resolvedStartPos$nod.type.name) || ''
406
407
  }
407
408
  })(tr);
408
- const selection = ((_selectionPreservatio = selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection) || tr.selection;
409
409
  const range = getExpandedSelectionRange({
410
410
  doc: tr.doc,
411
411
  selection,
@@ -3,11 +3,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
3
3
  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) { _defineProperty(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; }
4
4
  import { logException } from '@atlaskit/editor-common/monitoring';
5
5
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
6
- import { expandToBlockRange } from '@atlaskit/editor-common/selection';
7
- import { TextSelection } from '@atlaskit/editor-prosemirror/state';
8
- import { Mapping, StepMap } from '@atlaskit/editor-prosemirror/transform';
9
- import { getBlockControlsMeta } from '../main';
10
- import { collapseToSelectionRange } from '../utils/getSelection';
6
+ import { mapPreservedSelection } from '../utils/selection';
11
7
  import { stopPreservingSelection } from './editor-commands';
12
8
  import { selectionPreservationPluginKey } from './plugin-key';
13
9
  import { getSelectionPreservationMeta, hasUserSelectionChange } from './utils';
@@ -58,7 +54,7 @@ export var createSelectionPreservationPlugin = function createSelectionPreservat
58
54
  newState.preservedSelection = undefined;
59
55
  }
60
56
  if (newState.preservedSelection && tr.docChanged) {
61
- newState.preservedSelection = mapSelection(newState.preservedSelection, tr);
57
+ newState.preservedSelection = mapPreservedSelection(newState.preservedSelection, tr);
62
58
  }
63
59
  return newState;
64
60
  }
@@ -91,44 +87,4 @@ export var createSelectionPreservationPlugin = function createSelectionPreservat
91
87
  return null;
92
88
  }
93
89
  });
94
- };
95
- var mapSelection = function mapSelection(selection, tr) {
96
- var _ref = getBlockControlsMeta(tr) || {},
97
- nodeMoved = _ref.nodeMoved,
98
- nodeMovedOffset = _ref.nodeMovedOffset;
99
- var mapping = nodeMoved && typeof nodeMovedOffset === 'number' ? new Mapping([new StepMap([0, 0, nodeMovedOffset])]) : tr.mapping;
100
- if (selection instanceof TextSelection) {
101
- var from = mapping.map(selection.from);
102
- var to = mapping.map(selection.to);
103
- var isSelectionEmpty = from === to;
104
- var wasSelectionEmpty = selection.from === selection.to;
105
- if (isSelectionEmpty) {
106
- if (!wasSelectionEmpty) {
107
- // If selection has become empty i.e. content has been deleted, stop preserving
108
- return undefined;
109
- }
110
- // When preserving a cursor selection, just map the position without expanding
111
- return new TextSelection(tr.doc.resolve(from));
112
- }
113
-
114
- // expand the text selection range to block boundaries, so as document changes occur the
115
- // selection always includes whole nodes
116
- var expanded = expandToBlockRange(tr.doc.resolve(from), tr.doc.resolve(to));
117
-
118
- // collapse the expanded range to a valid selection range
119
- var _collapseToSelectionR = collapseToSelectionRange(expanded.$from, expanded.$to),
120
- $from = _collapseToSelectionR.$from,
121
- $to = _collapseToSelectionR.$to;
122
-
123
- // stop preserving if preserved selection becomes invalid
124
- if ($from.pos < 0 || $to.pos > tr.doc.content.size || $from.pos >= $to.pos) {
125
- return undefined;
126
- }
127
- return new TextSelection($from, $to);
128
- }
129
- try {
130
- return selection.map(tr.doc, mapping);
131
- } catch (_unused) {
132
- return undefined;
133
- }
134
90
  };
@@ -1,5 +1,8 @@
1
- import { TextSelection, NodeSelection } from '@atlaskit/editor-prosemirror/state';
2
- import { key } from '../main';
1
+ import { expandToBlockRange } from '@atlaskit/editor-common/selection';
2
+ import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
3
+ import { Mapping, StepMap } from '@atlaskit/editor-prosemirror/transform';
4
+ import { getBlockControlsMeta, key } from '../main';
5
+ import { collapseToSelectionRange } from './getSelection';
3
6
  export var getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(api, pos, tr) {
4
7
  var _api$blockControls, _pluginState$multiSel, _tr$getMeta;
5
8
  var pluginState = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState();
@@ -20,7 +23,12 @@ export var getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(
20
23
  };
21
24
 
22
25
  /**
26
+ * Given a handle position, returns the from and to positions of the selected content.
27
+ * If the handle position is not in a multi-selection, it returns the node's from and to positions.
23
28
  *
29
+ * @param handlePos The position of the handle
30
+ * @param tr The transaction to use for position calculations
31
+ * @param api The BlockControlsPlugin API for accessing shared state
24
32
  * @returns from and to positions of the selected content (after expansion)
25
33
  */
26
34
  export var getSelectedSlicePosition = function getSelectedSlicePosition(handlePos, tr, api) {
@@ -66,4 +74,52 @@ export var expandSelectionHeadToNodeAtPos = function expandSelectionHeadToNodeAt
66
74
  */
67
75
  export var alignAnchorHeadInDirectionOfPos = function alignAnchorHeadInDirectionOfPos(selection, pos) {
68
76
  return selection instanceof NodeSelection && Math.max(pos, selection.anchor) === selection.anchor ? new TextSelection(selection.$head, selection.$anchor) : selection;
77
+ };
78
+
79
+ /**
80
+ * This maps a preserved selection through a transaction, expanding text selections to block boundaries.
81
+ *
82
+ * @param selection The existing preserved selection to map
83
+ * @param tr The transaction to map through
84
+ * @returns The mapped selection or undefined if mapping is not possible
85
+ */
86
+ export var mapPreservedSelection = function mapPreservedSelection(selection, tr) {
87
+ var _ref = getBlockControlsMeta(tr) || {},
88
+ nodeMoved = _ref.nodeMoved,
89
+ nodeMovedOffset = _ref.nodeMovedOffset;
90
+ var mapping = nodeMoved && typeof nodeMovedOffset === 'number' ? new Mapping([new StepMap([0, 0, nodeMovedOffset])]) : tr.mapping;
91
+ if (selection instanceof TextSelection) {
92
+ var from = mapping.map(selection.from);
93
+ var to = mapping.map(selection.to);
94
+ var isSelectionEmpty = from === to;
95
+ var wasSelectionEmpty = selection.from === selection.to;
96
+ if (isSelectionEmpty) {
97
+ if (!wasSelectionEmpty) {
98
+ // If selection has become empty i.e. content has been deleted, stop preserving
99
+ return undefined;
100
+ }
101
+ // When preserving a cursor selection, just map the position without expanding
102
+ return new TextSelection(tr.doc.resolve(from));
103
+ }
104
+
105
+ // expand the text selection range to block boundaries, so as document changes occur the
106
+ // selection always includes whole nodes
107
+ var expanded = expandToBlockRange(tr.doc.resolve(from), tr.doc.resolve(to));
108
+
109
+ // collapse the expanded range to a valid selection range
110
+ var _collapseToSelectionR = collapseToSelectionRange(expanded.$from, expanded.$to),
111
+ $from = _collapseToSelectionR.$from,
112
+ $to = _collapseToSelectionR.$to;
113
+
114
+ // stop preserving if preserved selection becomes invalid
115
+ if ($from.pos < 0 || $to.pos > tr.doc.content.size || $from.pos >= $to.pos) {
116
+ return undefined;
117
+ }
118
+ return new TextSelection($from, $to);
119
+ }
120
+ try {
121
+ return selection.map(tr.doc, mapping);
122
+ } catch (_unused) {
123
+ return undefined;
124
+ }
69
125
  };
@@ -407,13 +407,14 @@ export var DragHandle = function DragHandle(_ref2) {
407
407
  var handleOnClickNew = useCallback(function (e) {
408
408
  var _api$core;
409
409
  api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref3) {
410
- var _api$analytics, _resolvedStartPos$nod, _selectionPreservatio, _api$blockControls, _api$blockControls2;
410
+ var _selectionPreservatio, _api$analytics, _resolvedStartPos$nod, _api$blockControls, _api$blockControls2;
411
411
  var tr = _ref3.tr;
412
412
  var startPos = getPos();
413
413
  if (startPos === undefined) {
414
414
  return tr;
415
415
  }
416
416
  var resolvedStartPos = tr.doc.resolve(startPos);
417
+ var selection = ((_selectionPreservatio = selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection) || tr.selection;
417
418
  api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
418
419
  eventType: EVENT_TYPE.UI,
419
420
  action: ACTION.CLICKED,
@@ -424,7 +425,6 @@ export var DragHandle = function DragHandle(_ref2) {
424
425
  nodeType: ((_resolvedStartPos$nod = resolvedStartPos.nodeAfter) === null || _resolvedStartPos$nod === void 0 ? void 0 : _resolvedStartPos$nod.type.name) || ''
425
426
  }
426
427
  })(tr);
427
- var selection = ((_selectionPreservatio = selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection) || tr.selection;
428
428
  var range = getExpandedSelectionRange({
429
429
  doc: tr.doc,
430
430
  selection: selection,
@@ -2,7 +2,7 @@ import { type IntlShape } from 'react-intl-next';
2
2
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
3
3
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
4
4
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
5
- import type { EditorState, ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
5
+ import type { EditorState, ReadonlyTransaction, Transaction } from '@atlaskit/editor-prosemirror/state';
6
6
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
7
7
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
8
  import type { ActiveDropTargetNode, BlockControlsMeta, BlockControlsPlugin, PluginState } from '../blockControlsPluginType';
@@ -61,4 +61,4 @@ export declare const createPlugin: (api: ExtractInjectionAPI<BlockControlsPlugin
61
61
  lastDragCancelled: any;
62
62
  isSelectedViaDragHandle: any;
63
63
  }>;
64
- export declare const getBlockControlsMeta: (tr: ReadonlyTransaction) => BlockControlsMeta | undefined;
64
+ export declare const getBlockControlsMeta: (tr: Transaction | ReadonlyTransaction) => BlockControlsMeta | undefined;
@@ -1,12 +1,17 @@
1
1
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
- import { type Transaction, type Selection } from '@atlaskit/editor-prosemirror/state';
2
+ import { type ReadonlyTransaction, type Selection, type Transaction } from '@atlaskit/editor-prosemirror/state';
3
3
  import type { BlockControlsPlugin } from '../../blockControlsPluginType';
4
4
  export declare const getMultiSelectionIfPosInside: (api: ExtractInjectionAPI<BlockControlsPlugin>, pos: number, tr?: Transaction) => {
5
5
  anchor?: number;
6
6
  head?: number;
7
7
  };
8
8
  /**
9
+ * Given a handle position, returns the from and to positions of the selected content.
10
+ * If the handle position is not in a multi-selection, it returns the node's from and to positions.
9
11
  *
12
+ * @param handlePos The position of the handle
13
+ * @param tr The transaction to use for position calculations
14
+ * @param api The BlockControlsPlugin API for accessing shared state
10
15
  * @returns from and to positions of the selected content (after expansion)
11
16
  */
12
17
  export declare const getSelectedSlicePosition: (handlePos: number, tr: Transaction, api: ExtractInjectionAPI<BlockControlsPlugin>) => {
@@ -25,3 +30,11 @@ export declare const expandSelectionHeadToNodeAtPos: (selection: Selection, node
25
30
  * which may not align with the existing selection.
26
31
  */
27
32
  export declare const alignAnchorHeadInDirectionOfPos: (selection: Selection, pos: number) => Selection;
33
+ /**
34
+ * This maps a preserved selection through a transaction, expanding text selections to block boundaries.
35
+ *
36
+ * @param selection The existing preserved selection to map
37
+ * @param tr The transaction to map through
38
+ * @returns The mapped selection or undefined if mapping is not possible
39
+ */
40
+ export declare const mapPreservedSelection: (selection: Selection, tr: ReadonlyTransaction | Transaction) => Selection | undefined;
@@ -2,7 +2,7 @@ import { type IntlShape } from 'react-intl-next';
2
2
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
3
3
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
4
4
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
5
- import type { EditorState, ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
5
+ import type { EditorState, ReadonlyTransaction, Transaction } from '@atlaskit/editor-prosemirror/state';
6
6
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
7
7
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
8
  import type { ActiveDropTargetNode, BlockControlsMeta, BlockControlsPlugin, PluginState } from '../blockControlsPluginType';
@@ -61,4 +61,4 @@ export declare const createPlugin: (api: ExtractInjectionAPI<BlockControlsPlugin
61
61
  lastDragCancelled: any;
62
62
  isSelectedViaDragHandle: any;
63
63
  }>;
64
- export declare const getBlockControlsMeta: (tr: ReadonlyTransaction) => BlockControlsMeta | undefined;
64
+ export declare const getBlockControlsMeta: (tr: Transaction | ReadonlyTransaction) => BlockControlsMeta | undefined;
@@ -1,12 +1,17 @@
1
1
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
- import { type Transaction, type Selection } from '@atlaskit/editor-prosemirror/state';
2
+ import { type ReadonlyTransaction, type Selection, type Transaction } from '@atlaskit/editor-prosemirror/state';
3
3
  import type { BlockControlsPlugin } from '../../blockControlsPluginType';
4
4
  export declare const getMultiSelectionIfPosInside: (api: ExtractInjectionAPI<BlockControlsPlugin>, pos: number, tr?: Transaction) => {
5
5
  anchor?: number;
6
6
  head?: number;
7
7
  };
8
8
  /**
9
+ * Given a handle position, returns the from and to positions of the selected content.
10
+ * If the handle position is not in a multi-selection, it returns the node's from and to positions.
9
11
  *
12
+ * @param handlePos The position of the handle
13
+ * @param tr The transaction to use for position calculations
14
+ * @param api The BlockControlsPlugin API for accessing shared state
10
15
  * @returns from and to positions of the selected content (after expansion)
11
16
  */
12
17
  export declare const getSelectedSlicePosition: (handlePos: number, tr: Transaction, api: ExtractInjectionAPI<BlockControlsPlugin>) => {
@@ -25,3 +30,11 @@ export declare const expandSelectionHeadToNodeAtPos: (selection: Selection, node
25
30
  * which may not align with the existing selection.
26
31
  */
27
32
  export declare const alignAnchorHeadInDirectionOfPos: (selection: Selection, pos: number) => Selection;
33
+ /**
34
+ * This maps a preserved selection through a transaction, expanding text selections to block boundaries.
35
+ *
36
+ * @param selection The existing preserved selection to map
37
+ * @param tr The transaction to map through
38
+ * @returns The mapped selection or undefined if mapping is not possible
39
+ */
40
+ export declare const mapPreservedSelection: (selection: Selection, tr: ReadonlyTransaction | Transaction) => Selection | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "7.11.3",
3
+ "version": "7.11.4",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -37,7 +37,7 @@
37
37
  "@atlaskit/editor-plugin-interaction": "^10.0.0",
38
38
  "@atlaskit/editor-plugin-limited-mode": "^3.1.0",
39
39
  "@atlaskit/editor-plugin-metrics": "^7.1.0",
40
- "@atlaskit/editor-plugin-quick-insert": "^6.0.0",
40
+ "@atlaskit/editor-plugin-quick-insert": "^6.1.0",
41
41
  "@atlaskit/editor-plugin-selection": "^6.1.0",
42
42
  "@atlaskit/editor-plugin-toolbar": "^3.4.0",
43
43
  "@atlaskit/editor-plugin-type-ahead": "^6.5.0",
@@ -54,7 +54,7 @@
54
54
  "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^3.2.0",
55
55
  "@atlaskit/primitives": "^16.4.0",
56
56
  "@atlaskit/theme": "^21.0.0",
57
- "@atlaskit/tmp-editor-statsig": "^14.5.0",
57
+ "@atlaskit/tmp-editor-statsig": "^14.6.0",
58
58
  "@atlaskit/tokens": "^8.4.0",
59
59
  "@atlaskit/tooltip": "^20.10.0",
60
60
  "@babel/runtime": "^7.0.0",