@atlaskit/editor-plugin-selection-extension 3.0.1 → 3.1.1
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 +20 -0
- package/dist/cjs/pm-plugins/actions.js +93 -0
- package/dist/cjs/pm-plugins/main.js +21 -0
- package/dist/cjs/pm-plugins/utils/getOffsetByPath.js +83 -0
- package/dist/cjs/pm-plugins/utils/index.js +23 -6
- package/dist/cjs/selectionExtensionPlugin.js +29 -2
- package/dist/cjs/types/index.js +2 -0
- package/dist/cjs/ui/extension/SelectionExtensionComponentWrapper.js +12 -6
- package/dist/es2019/pm-plugins/actions.js +93 -0
- package/dist/es2019/pm-plugins/main.js +22 -0
- package/dist/es2019/pm-plugins/utils/getOffsetByPath.js +76 -0
- package/dist/es2019/pm-plugins/utils/index.js +22 -5
- package/dist/es2019/selectionExtensionPlugin.js +31 -2
- package/dist/es2019/types/index.js +2 -0
- package/dist/es2019/ui/extension/SelectionExtensionComponentWrapper.js +11 -4
- package/dist/esm/pm-plugins/actions.js +87 -0
- package/dist/esm/pm-plugins/main.js +21 -0
- package/dist/esm/pm-plugins/utils/getOffsetByPath.js +78 -0
- package/dist/esm/pm-plugins/utils/index.js +21 -5
- package/dist/esm/selectionExtensionPlugin.js +29 -2
- package/dist/esm/types/index.js +2 -0
- package/dist/esm/ui/extension/SelectionExtensionComponentWrapper.js +13 -7
- package/dist/types/pm-plugins/actions.d.ts +8 -0
- package/dist/types/pm-plugins/main.d.ts +24 -0
- package/dist/types/pm-plugins/utils/getOffsetByPath.d.ts +14 -0
- package/dist/types/pm-plugins/utils/index.d.ts +12 -2
- package/dist/types/selectionExtensionPluginType.d.ts +8 -1
- package/dist/types/types/index.d.ts +17 -1
- package/dist/types-ts4.5/pm-plugins/actions.d.ts +8 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +24 -0
- package/dist/types-ts4.5/pm-plugins/utils/getOffsetByPath.d.ts +14 -0
- package/dist/types-ts4.5/pm-plugins/utils/index.d.ts +12 -2
- package/dist/types-ts4.5/selectionExtensionPluginType.d.ts +8 -1
- package/dist/types-ts4.5/types/index.d.ts +17 -1
- package/package.json +3 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import isEqual from 'lodash/isEqual';
|
|
1
2
|
import { JSONTransformer } from '@atlaskit/editor-json-transformer';
|
|
2
3
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
3
4
|
import { CellSelection, TableMap } from '@atlaskit/editor-tables';
|
|
@@ -28,11 +29,13 @@ const getSelectionInfoFromSameNode = selection => {
|
|
|
28
29
|
pointer: `/content/${$from.index()}/text`,
|
|
29
30
|
position: $to.parentOffset - 1
|
|
30
31
|
}
|
|
31
|
-
}]
|
|
32
|
+
}],
|
|
33
|
+
nodePos: $from.before() // position before the selection
|
|
32
34
|
};
|
|
33
35
|
};
|
|
34
36
|
const getSelectionInfoFromCellSelection = selection => {
|
|
35
37
|
const selectedNode = selection.$anchorCell.node(-1);
|
|
38
|
+
const nodePos = selection.$anchorCell.before(-1);
|
|
36
39
|
const selectionRanges = [];
|
|
37
40
|
const rect = getSelectedRect(selection);
|
|
38
41
|
for (let row = rect.top; row < rect.bottom; row++) {
|
|
@@ -47,14 +50,16 @@ const getSelectionInfoFromCellSelection = selection => {
|
|
|
47
50
|
}
|
|
48
51
|
return {
|
|
49
52
|
selectedNode,
|
|
50
|
-
selectionRanges
|
|
53
|
+
selectionRanges,
|
|
54
|
+
nodePos
|
|
51
55
|
};
|
|
52
56
|
};
|
|
53
57
|
export const getSelectionInfo = state => {
|
|
54
58
|
const selection = state.selection;
|
|
55
59
|
let selectionInfo = {
|
|
56
60
|
selectedNode: selection.$from.node(),
|
|
57
|
-
selectionRanges: []
|
|
61
|
+
selectionRanges: [],
|
|
62
|
+
nodePos: selection.$from.before() // default to the position before the selection
|
|
58
63
|
};
|
|
59
64
|
if (selection instanceof TextSelection) {
|
|
60
65
|
const {
|
|
@@ -70,9 +75,21 @@ export const getSelectionInfo = state => {
|
|
|
70
75
|
selectionInfo = getSelectionInfoFromCellSelection(selection);
|
|
71
76
|
}
|
|
72
77
|
const serializer = new JSONTransformer();
|
|
73
|
-
const
|
|
78
|
+
const {
|
|
79
|
+
selectionRanges,
|
|
80
|
+
selectedNode,
|
|
81
|
+
nodePos
|
|
82
|
+
} = selectionInfo;
|
|
83
|
+
const selectedNodeAdf = serializer.encodeNode(selectedNode);
|
|
74
84
|
return {
|
|
75
85
|
selectedNodeAdf,
|
|
76
|
-
selectionRanges
|
|
86
|
+
selectionRanges,
|
|
87
|
+
selectedNode,
|
|
88
|
+
nodePos
|
|
77
89
|
};
|
|
90
|
+
};
|
|
91
|
+
export const validateSelectedNode = (selectedNodeAdf, selectedNode) => {
|
|
92
|
+
const serializer = new JSONTransformer();
|
|
93
|
+
const selectedNodeAdfFromState = serializer.encodeNode(selectedNode);
|
|
94
|
+
return isEqual(selectedNodeAdf, selectedNodeAdfFromState);
|
|
78
95
|
};
|
|
@@ -2,8 +2,10 @@ import React from 'react';
|
|
|
2
2
|
import { selectionExtensionMessages } from '@atlaskit/editor-common/messages';
|
|
3
3
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
4
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
5
|
+
import { insertSmartLinks } from './pm-plugins/actions';
|
|
5
6
|
import { createPlugin, selectionExtensionPluginKey } from './pm-plugins/main';
|
|
6
7
|
import { getSelectionInfo } from './pm-plugins/utils';
|
|
8
|
+
import { SelectionExtensionActionTypes } from './types';
|
|
7
9
|
import { SelectionExtensionComponentWrapper } from './ui/extension/SelectionExtensionComponentWrapper';
|
|
8
10
|
import { getBoundingBoxFromSelection } from './ui/getBoundingBoxFromSelection';
|
|
9
11
|
import { selectionToolbar } from './ui/selectionToolbar';
|
|
@@ -41,6 +43,21 @@ export const selectionExtensionPlugin = ({
|
|
|
41
43
|
});
|
|
42
44
|
}
|
|
43
45
|
},
|
|
46
|
+
actions: {
|
|
47
|
+
insertSmartLinks: (linkInsertionOptions, selectedNodeAdf) => {
|
|
48
|
+
if (!editorViewRef.current) {
|
|
49
|
+
return {
|
|
50
|
+
status: 'error',
|
|
51
|
+
message: 'Editor view is not available'
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const {
|
|
55
|
+
state,
|
|
56
|
+
dispatch
|
|
57
|
+
} = editorViewRef.current;
|
|
58
|
+
return insertSmartLinks(linkInsertionOptions, selectedNodeAdf)(state, dispatch);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
44
61
|
contentComponent: ({
|
|
45
62
|
editorView
|
|
46
63
|
}) => {
|
|
@@ -134,16 +151,28 @@ export const selectionExtensionPlugin = ({
|
|
|
134
151
|
selection
|
|
135
152
|
};
|
|
136
153
|
if (fg('platform_editor_selection_extension_api_v2')) {
|
|
137
|
-
var _extension$onClick;
|
|
154
|
+
var _extension$onClick, _api$core;
|
|
138
155
|
const {
|
|
139
156
|
selectedNodeAdf,
|
|
140
|
-
selectionRanges
|
|
157
|
+
selectionRanges,
|
|
158
|
+
selectedNode,
|
|
159
|
+
nodePos
|
|
141
160
|
} = getSelectionInfo(view.state);
|
|
142
161
|
onClickCallbackOptions = {
|
|
143
162
|
selectedNodeAdf,
|
|
144
163
|
selectionRanges
|
|
145
164
|
};
|
|
146
165
|
(_extension$onClick = extension.onClick) === null || _extension$onClick === void 0 ? void 0 : _extension$onClick.call(extension, onClickCallbackOptions);
|
|
166
|
+
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
|
|
167
|
+
tr
|
|
168
|
+
}) => {
|
|
169
|
+
tr.setMeta(selectionExtensionPluginKey, {
|
|
170
|
+
type: SelectionExtensionActionTypes.SET_SELECTED_NODE,
|
|
171
|
+
selectedNode,
|
|
172
|
+
nodePos
|
|
173
|
+
});
|
|
174
|
+
return tr;
|
|
175
|
+
});
|
|
147
176
|
} else {
|
|
148
177
|
if (extension.onClick) {
|
|
149
178
|
extension.onClick(onClickCallbackOptions);
|
|
@@ -10,5 +10,7 @@ export let SelectionExtensionActionTypes = /*#__PURE__*/function (SelectionExten
|
|
|
10
10
|
SelectionExtensionActionTypes["SET_ACTIVE_EXTENSION"] = "set-active-extension";
|
|
11
11
|
SelectionExtensionActionTypes["UPDATE_ACTIVE_EXTENSION_COORDS"] = "update-active-extension-coords";
|
|
12
12
|
SelectionExtensionActionTypes["CLEAR_ACTIVE_EXTENSION"] = "clear-active-extension";
|
|
13
|
+
SelectionExtensionActionTypes["SET_SELECTED_NODE"] = "set-selected-node";
|
|
14
|
+
SelectionExtensionActionTypes["START_TRACK_CHANGES"] = "start-track-changes";
|
|
13
15
|
return SelectionExtensionActionTypes;
|
|
14
16
|
}({});
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef } from 'react';
|
|
2
2
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
3
|
-
import { useSharedPluginState, sharedPluginStateHookMigratorFactory } from '@atlaskit/editor-common/hooks';
|
|
4
|
-
import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
|
|
3
|
+
import { useSharedPluginState, sharedPluginStateHookMigratorFactory, useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
5
4
|
const useSharedState = sharedPluginStateHookMigratorFactory(api => {
|
|
6
|
-
const
|
|
7
|
-
|
|
5
|
+
const {
|
|
6
|
+
activeExtension,
|
|
7
|
+
mode
|
|
8
|
+
} = useSharedPluginStateWithSelector(api, ['selectionExtension', 'editorViewMode'], states => {
|
|
9
|
+
var _states$selectionExte, _states$editorViewMod;
|
|
10
|
+
return {
|
|
11
|
+
activeExtension: (_states$selectionExte = states.selectionExtensionState) === null || _states$selectionExte === void 0 ? void 0 : _states$selectionExte.activeExtension,
|
|
12
|
+
mode: (_states$editorViewMod = states.editorViewModeState) === null || _states$editorViewMod === void 0 ? void 0 : _states$editorViewMod.mode
|
|
13
|
+
};
|
|
14
|
+
});
|
|
8
15
|
return {
|
|
9
16
|
editorViewModeState: undefined,
|
|
10
17
|
mode,
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { SelectionExtensionActionTypes } from '../types';
|
|
2
|
+
import { selectionExtensionPluginKey } from './main';
|
|
3
|
+
import { validateSelectedNode } from './utils';
|
|
4
|
+
import { getOffsetByPath } from './utils/getOffsetByPath';
|
|
5
|
+
var insertLinkTr = function insertLinkTr(tr, link, offset, schema) {
|
|
6
|
+
var newFromPos = tr.mapping.map(offset.from);
|
|
7
|
+
var newToPos = tr.mapping.map(offset.to || offset.from);
|
|
8
|
+
var smartLink = schema.nodes.inlineCard.createChecked({
|
|
9
|
+
url: link
|
|
10
|
+
});
|
|
11
|
+
return tr.replaceWith(newFromPos, newToPos, smartLink);
|
|
12
|
+
};
|
|
13
|
+
export var insertSmartLinks = function insertSmartLinks(linkInsertionOption, selectedNodeAdf) {
|
|
14
|
+
return function (state, dispatch) {
|
|
15
|
+
var _selectionExtensionPl;
|
|
16
|
+
var tr = state.tr,
|
|
17
|
+
schema = state.schema;
|
|
18
|
+
if (!Array.isArray(linkInsertionOption)) {
|
|
19
|
+
linkInsertionOption = [linkInsertionOption];
|
|
20
|
+
}
|
|
21
|
+
if (linkInsertionOption.length === 0) {
|
|
22
|
+
return {
|
|
23
|
+
status: 'error',
|
|
24
|
+
message: 'No link insertion options provided'
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// we need to track if any changes were made since user click the toolbar button
|
|
29
|
+
// if there is change, we insert the links at the bottom of the page instead
|
|
30
|
+
var docChangedAfterClick = ((_selectionExtensionPl = selectionExtensionPluginKey.getState(state)) === null || _selectionExtensionPl === void 0 ? void 0 : _selectionExtensionPl.docChangedAfterClick) || false;
|
|
31
|
+
if (docChangedAfterClick) {
|
|
32
|
+
var docEnd = state.doc.content.size;
|
|
33
|
+
linkInsertionOption.forEach(function (option) {
|
|
34
|
+
var link = option.link;
|
|
35
|
+
tr.insert(tr.mapping.map(docEnd), schema.nodes.inlineCard.createChecked({
|
|
36
|
+
url: link
|
|
37
|
+
}));
|
|
38
|
+
});
|
|
39
|
+
tr.setMeta(selectionExtensionPluginKey, {
|
|
40
|
+
type: SelectionExtensionActionTypes.START_TRACK_CHANGES,
|
|
41
|
+
startTrackChanges: false // Reset the flag when starting to track changes
|
|
42
|
+
});
|
|
43
|
+
dispatch(tr);
|
|
44
|
+
return {
|
|
45
|
+
status: 'success',
|
|
46
|
+
message: 'Links inserted to page bottom successfully'
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
var newTr = tr;
|
|
50
|
+
try {
|
|
51
|
+
var _selectionExtensionPl2, _selectionExtensionPl3;
|
|
52
|
+
var selectedNode = (_selectionExtensionPl2 = selectionExtensionPluginKey.getState(state)) === null || _selectionExtensionPl2 === void 0 ? void 0 : _selectionExtensionPl2.selectedNode;
|
|
53
|
+
var nodePos = (_selectionExtensionPl3 = selectionExtensionPluginKey.getState(state)) === null || _selectionExtensionPl3 === void 0 ? void 0 : _selectionExtensionPl3.nodePos;
|
|
54
|
+
if (!selectedNode || nodePos === undefined) {
|
|
55
|
+
throw new Error('No selected node or node position found');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Validate if the selectedNodeAdf matches the selected node we have in the state
|
|
59
|
+
if (!validateSelectedNode(selectedNodeAdf, selectedNode)) {
|
|
60
|
+
throw new Error('Selected node ADF does not match the previous stored node');
|
|
61
|
+
}
|
|
62
|
+
linkInsertionOption.forEach(function (option) {
|
|
63
|
+
var link = option.link,
|
|
64
|
+
insertPosition = option.insertPosition;
|
|
65
|
+
var pointer = insertPosition.pointer,
|
|
66
|
+
from = insertPosition.from,
|
|
67
|
+
to = insertPosition.to;
|
|
68
|
+
var offset = getOffsetByPath(selectedNode, nodePos, pointer, from, to);
|
|
69
|
+
newTr = insertLinkTr(tr, link, offset, schema);
|
|
70
|
+
});
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return {
|
|
73
|
+
status: 'error',
|
|
74
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
newTr.setMeta(selectionExtensionPluginKey, {
|
|
78
|
+
type: SelectionExtensionActionTypes.START_TRACK_CHANGES,
|
|
79
|
+
startTrackChanges: false // Reset the flag when starting to track changes
|
|
80
|
+
});
|
|
81
|
+
dispatch(newTr);
|
|
82
|
+
return {
|
|
83
|
+
status: 'success',
|
|
84
|
+
message: 'Links inserted successfully'
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
};
|
|
@@ -3,6 +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 { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
5
5
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
|
+
import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
6
7
|
import { SelectionExtensionActionTypes } from '../types';
|
|
7
8
|
export var selectionExtensionPluginKey = new PluginKey('selectionExtensionPlugin');
|
|
8
9
|
export var createPlugin = function createPlugin() {
|
|
@@ -25,6 +26,26 @@ export var createPlugin = function createPlugin() {
|
|
|
25
26
|
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
26
27
|
activeExtension: undefined
|
|
27
28
|
});
|
|
29
|
+
case SelectionExtensionActionTypes.SET_SELECTED_NODE:
|
|
30
|
+
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
31
|
+
selectedNode: meta.selectedNode,
|
|
32
|
+
nodePos: meta.nodePos,
|
|
33
|
+
startTrackChanges: true,
|
|
34
|
+
docChangedAfterClick: false // Reset the flag when starting to track changes
|
|
35
|
+
});
|
|
36
|
+
case SelectionExtensionActionTypes.START_TRACK_CHANGES:
|
|
37
|
+
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
38
|
+
startTrackChanges: meta.startTrackChanges
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
var docChangedAfterClick = pluginState.startTrackChanges && tr.steps.some(function (step) {
|
|
42
|
+
return step instanceof ReplaceStep || step instanceof ReplaceAroundStep;
|
|
43
|
+
});
|
|
44
|
+
if (docChangedAfterClick) {
|
|
45
|
+
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
46
|
+
docChangedAfterClick: true,
|
|
47
|
+
startTrackChanges: false // Reset the flag to stop tracking after the document has changed
|
|
48
|
+
});
|
|
28
49
|
}
|
|
29
50
|
return pluginState;
|
|
30
51
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Fragment, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
|
|
3
|
+
// TODO: ED-28434 - move this to a shared package
|
|
4
|
+
// mirror code from https://bitbucket.org/atlassian/pf-adf-service/src/master/src/lib/update/get-offset.ts
|
|
5
|
+
|
|
6
|
+
export function getOffsetByPath(root, pos, pointer) {
|
|
7
|
+
var from = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
|
|
8
|
+
var to = arguments.length > 4 ? arguments[4] : undefined;
|
|
9
|
+
var parts = pointer.split('/');
|
|
10
|
+
var ref = root;
|
|
11
|
+
var len = parts.length;
|
|
12
|
+
// -1 to account for the root node (usually doc)
|
|
13
|
+
// The start of the document, right before the first content, is position 0.
|
|
14
|
+
var offset = pos; //-1;
|
|
15
|
+
|
|
16
|
+
for (var i = 1; i < len; i++) {
|
|
17
|
+
var key = parts[i];
|
|
18
|
+
if (ref instanceof Fragment && /^[0-9]+$/.test(key)) {
|
|
19
|
+
var index = parseInt(key, 10);
|
|
20
|
+
if (index >= ref.childCount) {
|
|
21
|
+
throw new Error("JSON pointer \"".concat(pointer, "\" points to non-existing location."));
|
|
22
|
+
}
|
|
23
|
+
var nextRef = ref.child(index);
|
|
24
|
+
while (index--) {
|
|
25
|
+
offset += ref.child(index).nodeSize;
|
|
26
|
+
}
|
|
27
|
+
ref = nextRef;
|
|
28
|
+
} else if (ref instanceof PMNode) {
|
|
29
|
+
/**
|
|
30
|
+
* Reference: https://prosemirror.net/docs/guide/#doc.data_structures
|
|
31
|
+
* +----------------------------------+
|
|
32
|
+
* | Node |
|
|
33
|
+
* | ^^^^ |
|
|
34
|
+
* | type: NodeType |
|
|
35
|
+
* | content: Fragment |
|
|
36
|
+
* | [ Node, Node, ...] |
|
|
37
|
+
* | attrs: Object |
|
|
38
|
+
* | marks: Mark |
|
|
39
|
+
* | [ |
|
|
40
|
+
* | type: MarkType |
|
|
41
|
+
* | attrs: Object |
|
|
42
|
+
* | ] |
|
|
43
|
+
* +----------------------------------+
|
|
44
|
+
*/
|
|
45
|
+
switch (key) {
|
|
46
|
+
case 'content':
|
|
47
|
+
// Entering or leaving a node that is not a leaf node (i.e. supports content) counts as one token.
|
|
48
|
+
offset++;
|
|
49
|
+
ref = ref.content;
|
|
50
|
+
break;
|
|
51
|
+
case 'attrs':
|
|
52
|
+
return {
|
|
53
|
+
type: 'attrs',
|
|
54
|
+
from: offset + from,
|
|
55
|
+
path: parts.slice(i + 1)
|
|
56
|
+
};
|
|
57
|
+
case 'text':
|
|
58
|
+
if (!ref.isText) {
|
|
59
|
+
throw new Error("\"".concat(parts.slice(0, i).join('/'), "\" doesn't have any \"text\" node!"));
|
|
60
|
+
}
|
|
61
|
+
continue;
|
|
62
|
+
default:
|
|
63
|
+
throw new Error("JSON pointer \"".concat(pointer, "\" points to an unsupported location."));
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
throw new Error("JSON pointer \"".concat(pointer, "\" points to an unsupported entity."));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (ref instanceof Fragment) {
|
|
70
|
+
throw new Error("Expected a Node, but the JSON pointer \"".concat(pointer, "\" points to a Fragment."));
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
type: 'node',
|
|
74
|
+
from: offset + from,
|
|
75
|
+
to: offset + (to !== null && to !== void 0 ? to : ref.nodeSize),
|
|
76
|
+
matches: [to ? ref.textBetween(from, to) : ref.textContent]
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import isEqual from 'lodash/isEqual';
|
|
1
2
|
import { JSONTransformer } from '@atlaskit/editor-json-transformer';
|
|
2
3
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
3
4
|
import { CellSelection, TableMap } from '@atlaskit/editor-tables';
|
|
@@ -24,11 +25,13 @@ var getSelectionInfoFromSameNode = function getSelectionInfoFromSameNode(selecti
|
|
|
24
25
|
pointer: "/content/".concat($from.index(), "/text"),
|
|
25
26
|
position: $to.parentOffset - 1
|
|
26
27
|
}
|
|
27
|
-
}]
|
|
28
|
+
}],
|
|
29
|
+
nodePos: $from.before() // position before the selection
|
|
28
30
|
};
|
|
29
31
|
};
|
|
30
32
|
var getSelectionInfoFromCellSelection = function getSelectionInfoFromCellSelection(selection) {
|
|
31
33
|
var selectedNode = selection.$anchorCell.node(-1);
|
|
34
|
+
var nodePos = selection.$anchorCell.before(-1);
|
|
32
35
|
var selectionRanges = [];
|
|
33
36
|
var rect = getSelectedRect(selection);
|
|
34
37
|
for (var row = rect.top; row < rect.bottom; row++) {
|
|
@@ -43,14 +46,16 @@ var getSelectionInfoFromCellSelection = function getSelectionInfoFromCellSelecti
|
|
|
43
46
|
}
|
|
44
47
|
return {
|
|
45
48
|
selectedNode: selectedNode,
|
|
46
|
-
selectionRanges: selectionRanges
|
|
49
|
+
selectionRanges: selectionRanges,
|
|
50
|
+
nodePos: nodePos
|
|
47
51
|
};
|
|
48
52
|
};
|
|
49
53
|
export var getSelectionInfo = function getSelectionInfo(state) {
|
|
50
54
|
var selection = state.selection;
|
|
51
55
|
var selectionInfo = {
|
|
52
56
|
selectedNode: selection.$from.node(),
|
|
53
|
-
selectionRanges: []
|
|
57
|
+
selectionRanges: [],
|
|
58
|
+
nodePos: selection.$from.before() // default to the position before the selection
|
|
54
59
|
};
|
|
55
60
|
if (selection instanceof TextSelection) {
|
|
56
61
|
var $from = selection.$from,
|
|
@@ -64,9 +69,20 @@ export var getSelectionInfo = function getSelectionInfo(state) {
|
|
|
64
69
|
selectionInfo = getSelectionInfoFromCellSelection(selection);
|
|
65
70
|
}
|
|
66
71
|
var serializer = new JSONTransformer();
|
|
67
|
-
var
|
|
72
|
+
var _selectionInfo = selectionInfo,
|
|
73
|
+
selectionRanges = _selectionInfo.selectionRanges,
|
|
74
|
+
selectedNode = _selectionInfo.selectedNode,
|
|
75
|
+
nodePos = _selectionInfo.nodePos;
|
|
76
|
+
var selectedNodeAdf = serializer.encodeNode(selectedNode);
|
|
68
77
|
return {
|
|
69
78
|
selectedNodeAdf: selectedNodeAdf,
|
|
70
|
-
selectionRanges:
|
|
79
|
+
selectionRanges: selectionRanges,
|
|
80
|
+
selectedNode: selectedNode,
|
|
81
|
+
nodePos: nodePos
|
|
71
82
|
};
|
|
83
|
+
};
|
|
84
|
+
export var validateSelectedNode = function validateSelectedNode(selectedNodeAdf, selectedNode) {
|
|
85
|
+
var serializer = new JSONTransformer();
|
|
86
|
+
var selectedNodeAdfFromState = serializer.encodeNode(selectedNode);
|
|
87
|
+
return isEqual(selectedNodeAdf, selectedNodeAdfFromState);
|
|
72
88
|
};
|
|
@@ -3,8 +3,10 @@ import React from 'react';
|
|
|
3
3
|
import { selectionExtensionMessages } from '@atlaskit/editor-common/messages';
|
|
4
4
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
5
5
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
|
+
import { insertSmartLinks as _insertSmartLinks } from './pm-plugins/actions';
|
|
6
7
|
import { createPlugin, selectionExtensionPluginKey } from './pm-plugins/main';
|
|
7
8
|
import { getSelectionInfo } from './pm-plugins/utils';
|
|
9
|
+
import { SelectionExtensionActionTypes } from './types';
|
|
8
10
|
import { SelectionExtensionComponentWrapper } from './ui/extension/SelectionExtensionComponentWrapper';
|
|
9
11
|
import { getBoundingBoxFromSelection } from './ui/getBoundingBoxFromSelection';
|
|
10
12
|
import { selectionToolbar as _selectionToolbar } from './ui/selectionToolbar';
|
|
@@ -43,6 +45,20 @@ export var selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
|
|
|
43
45
|
};
|
|
44
46
|
}
|
|
45
47
|
},
|
|
48
|
+
actions: {
|
|
49
|
+
insertSmartLinks: function insertSmartLinks(linkInsertionOptions, selectedNodeAdf) {
|
|
50
|
+
if (!editorViewRef.current) {
|
|
51
|
+
return {
|
|
52
|
+
status: 'error',
|
|
53
|
+
message: 'Editor view is not available'
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
var _editorViewRef$curren = editorViewRef.current,
|
|
57
|
+
state = _editorViewRef$curren.state,
|
|
58
|
+
dispatch = _editorViewRef$curren.dispatch;
|
|
59
|
+
return _insertSmartLinks(linkInsertionOptions, selectedNodeAdf)(state, dispatch);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
46
62
|
contentComponent: function contentComponent(_ref4) {
|
|
47
63
|
var _api$analytics;
|
|
48
64
|
var editorView = _ref4.editorView;
|
|
@@ -130,15 +146,26 @@ export var selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
|
|
|
130
146
|
selection: selection
|
|
131
147
|
};
|
|
132
148
|
if (fg('platform_editor_selection_extension_api_v2')) {
|
|
133
|
-
var _extension$onClick;
|
|
149
|
+
var _extension$onClick, _api$core;
|
|
134
150
|
var _getSelectionInfo = getSelectionInfo(view.state),
|
|
135
151
|
selectedNodeAdf = _getSelectionInfo.selectedNodeAdf,
|
|
136
|
-
selectionRanges = _getSelectionInfo.selectionRanges
|
|
152
|
+
selectionRanges = _getSelectionInfo.selectionRanges,
|
|
153
|
+
selectedNode = _getSelectionInfo.selectedNode,
|
|
154
|
+
nodePos = _getSelectionInfo.nodePos;
|
|
137
155
|
onClickCallbackOptions = {
|
|
138
156
|
selectedNodeAdf: selectedNodeAdf,
|
|
139
157
|
selectionRanges: selectionRanges
|
|
140
158
|
};
|
|
141
159
|
(_extension$onClick = extension.onClick) === null || _extension$onClick === void 0 || _extension$onClick.call(extension, onClickCallbackOptions);
|
|
160
|
+
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref5) {
|
|
161
|
+
var tr = _ref5.tr;
|
|
162
|
+
tr.setMeta(selectionExtensionPluginKey, {
|
|
163
|
+
type: SelectionExtensionActionTypes.SET_SELECTED_NODE,
|
|
164
|
+
selectedNode: selectedNode,
|
|
165
|
+
nodePos: nodePos
|
|
166
|
+
});
|
|
167
|
+
return tr;
|
|
168
|
+
});
|
|
142
169
|
} else {
|
|
143
170
|
if (extension.onClick) {
|
|
144
171
|
extension.onClick(onClickCallbackOptions);
|
package/dist/esm/types/index.js
CHANGED
|
@@ -10,5 +10,7 @@ export var SelectionExtensionActionTypes = /*#__PURE__*/function (SelectionExten
|
|
|
10
10
|
SelectionExtensionActionTypes["SET_ACTIVE_EXTENSION"] = "set-active-extension";
|
|
11
11
|
SelectionExtensionActionTypes["UPDATE_ACTIVE_EXTENSION_COORDS"] = "update-active-extension-coords";
|
|
12
12
|
SelectionExtensionActionTypes["CLEAR_ACTIVE_EXTENSION"] = "clear-active-extension";
|
|
13
|
+
SelectionExtensionActionTypes["SET_SELECTED_NODE"] = "set-selected-node";
|
|
14
|
+
SelectionExtensionActionTypes["START_TRACK_CHANGES"] = "start-track-changes";
|
|
13
15
|
return SelectionExtensionActionTypes;
|
|
14
16
|
}({});
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef } from 'react';
|
|
2
2
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
3
|
-
import { useSharedPluginState, sharedPluginStateHookMigratorFactory } from '@atlaskit/editor-common/hooks';
|
|
4
|
-
import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
|
|
3
|
+
import { useSharedPluginState, sharedPluginStateHookMigratorFactory, useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
5
4
|
var useSharedState = sharedPluginStateHookMigratorFactory(function (api) {
|
|
6
|
-
var
|
|
7
|
-
|
|
5
|
+
var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['selectionExtension', 'editorViewMode'], function (states) {
|
|
6
|
+
var _states$selectionExte, _states$editorViewMod;
|
|
7
|
+
return {
|
|
8
|
+
activeExtension: (_states$selectionExte = states.selectionExtensionState) === null || _states$selectionExte === void 0 ? void 0 : _states$selectionExte.activeExtension,
|
|
9
|
+
mode: (_states$editorViewMod = states.editorViewModeState) === null || _states$editorViewMod === void 0 ? void 0 : _states$editorViewMod.mode
|
|
10
|
+
};
|
|
11
|
+
}),
|
|
12
|
+
activeExtension = _useSharedPluginState.activeExtension,
|
|
13
|
+
mode = _useSharedPluginState.mode;
|
|
8
14
|
return {
|
|
9
15
|
editorViewModeState: undefined,
|
|
10
16
|
mode: mode,
|
|
11
17
|
activeExtension: activeExtension
|
|
12
18
|
};
|
|
13
19
|
}, function (api) {
|
|
14
|
-
var
|
|
15
|
-
selectionExtensionState =
|
|
16
|
-
editorViewModeState =
|
|
20
|
+
var _useSharedPluginState2 = useSharedPluginState(api, ['selectionExtension', 'editorViewMode']),
|
|
21
|
+
selectionExtensionState = _useSharedPluginState2.selectionExtensionState,
|
|
22
|
+
editorViewModeState = _useSharedPluginState2.editorViewModeState;
|
|
17
23
|
return {
|
|
18
24
|
editorViewModeState: editorViewModeState,
|
|
19
25
|
mode: editorViewModeState === null || editorViewModeState === void 0 ? void 0 : editorViewModeState.mode,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ADFEntity } from '@atlaskit/adf-utils/types';
|
|
2
|
+
import type { CommandDispatch } from '@atlaskit/editor-common/types';
|
|
3
|
+
import type { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import { type LinkInsertionOption } from '../types';
|
|
5
|
+
export declare const insertSmartLinks: (linkInsertionOption: LinkInsertionOption | LinkInsertionOption[], selectedNodeAdf: ADFEntity) => (state: EditorState, dispatch: CommandDispatch) => {
|
|
6
|
+
status: 'success' | 'error';
|
|
7
|
+
message?: string;
|
|
8
|
+
};
|
|
@@ -4,4 +4,28 @@ import { type SelectionExtensionPluginState } from '../types';
|
|
|
4
4
|
export declare const selectionExtensionPluginKey: PluginKey<SelectionExtensionPluginState>;
|
|
5
5
|
export declare const createPlugin: () => SafePlugin<SelectionExtensionPluginState | {
|
|
6
6
|
activeExtension: any;
|
|
7
|
+
selectedNode?: import("prosemirror-model").Node | undefined;
|
|
8
|
+
nodePos?: number | undefined;
|
|
9
|
+
startTrackChanges?: boolean | undefined;
|
|
10
|
+
docChangedAfterClick?: boolean | undefined;
|
|
11
|
+
} | {
|
|
12
|
+
selectedNode: any;
|
|
13
|
+
nodePos: any;
|
|
14
|
+
startTrackChanges: boolean;
|
|
15
|
+
docChangedAfterClick: boolean;
|
|
16
|
+
activeExtension?: {
|
|
17
|
+
extension: import("../types").SelectionExtension;
|
|
18
|
+
selection: import("../types").SelectionExtensionSelectionInfo;
|
|
19
|
+
coords: import("../types").SelectionExtensionCoords;
|
|
20
|
+
} | undefined;
|
|
21
|
+
} | {
|
|
22
|
+
startTrackChanges: any;
|
|
23
|
+
activeExtension?: {
|
|
24
|
+
extension: import("../types").SelectionExtension;
|
|
25
|
+
selection: import("../types").SelectionExtensionSelectionInfo;
|
|
26
|
+
coords: import("../types").SelectionExtensionCoords;
|
|
27
|
+
} | undefined;
|
|
28
|
+
selectedNode?: import("prosemirror-model").Node | undefined;
|
|
29
|
+
nodePos?: number | undefined;
|
|
30
|
+
docChangedAfterClick?: boolean | undefined;
|
|
7
31
|
}>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
export interface NodeOffset {
|
|
3
|
+
type: 'node';
|
|
4
|
+
from: number;
|
|
5
|
+
to: number;
|
|
6
|
+
matches: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface AttrsOffset {
|
|
9
|
+
type: 'attrs';
|
|
10
|
+
from: number;
|
|
11
|
+
path: string[];
|
|
12
|
+
}
|
|
13
|
+
export type Offset = NodeOffset | AttrsOffset;
|
|
14
|
+
export declare function getOffsetByPath(root: PMNode, pos: number, pointer: string, from?: number, to?: number): Offset;
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import { type ADFEntity } from '@atlaskit/adf-utils/types';
|
|
2
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
1
3
|
import { type EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
+
import { type SelectionRange } from '../../types';
|
|
5
|
+
type SelectionInfo = {
|
|
6
|
+
selectedNodeAdf: ADFEntity;
|
|
7
|
+
selectionRanges: SelectionRange[];
|
|
8
|
+
selectedNode: PMNode;
|
|
9
|
+
nodePos: number;
|
|
10
|
+
};
|
|
11
|
+
export declare const getSelectionInfo: (state: EditorState) => SelectionInfo;
|
|
12
|
+
export declare const validateSelectedNode: (selectedNodeAdf: ADFEntity, selectedNode: PMNode) => boolean;
|
|
13
|
+
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { type ADFEntity } from '@atlaskit/adf-utils/types';
|
|
1
2
|
import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
|
|
2
3
|
import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
|
|
3
4
|
import type { EditorViewModePlugin } from '@atlaskit/editor-plugin-editor-viewmode';
|
|
4
5
|
import type { SelectionToolbarPlugin } from '@atlaskit/editor-plugin-selection-toolbar';
|
|
5
|
-
import type { SelectionExtension, SelectionExtensionPluginOptions, SelectionExtensionPluginState, SelectionExtensionSelectionInfo } from './types';
|
|
6
|
+
import type { LinkInsertionOption, SelectionExtension, SelectionExtensionPluginOptions, SelectionExtensionPluginState, SelectionExtensionSelectionInfo } from './types';
|
|
6
7
|
export type SelectionExtensionPlugin = NextEditorPlugin<'selectionExtension', {
|
|
7
8
|
pluginConfiguration: SelectionExtensionPluginOptions | undefined;
|
|
8
9
|
dependencies: [
|
|
@@ -18,4 +19,10 @@ export type SelectionExtensionPlugin = NextEditorPlugin<'selectionExtension', {
|
|
|
18
19
|
}) => EditorCommand;
|
|
19
20
|
clearActiveExtension: () => EditorCommand;
|
|
20
21
|
};
|
|
22
|
+
actions: {
|
|
23
|
+
insertSmartLinks: (linkInsertionOption: LinkInsertionOption | LinkInsertionOption[], selectedNodeAdf: ADFEntity) => {
|
|
24
|
+
status: 'success' | 'error';
|
|
25
|
+
message?: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
21
28
|
}>;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { ADFEntity } from '@atlaskit/adf-utils/types';
|
|
3
3
|
import { type MenuItem } from '@atlaskit/editor-common/ui-menu';
|
|
4
4
|
import type { ViewMode } from '@atlaskit/editor-plugin-editor-viewmode';
|
|
5
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
5
6
|
export type MenuItemsType = Array<{
|
|
6
7
|
items: MenuItem[];
|
|
7
8
|
}>;
|
|
@@ -70,10 +71,21 @@ export type SelectionExtensionCoords = {
|
|
|
70
71
|
top: number;
|
|
71
72
|
bottom: number;
|
|
72
73
|
};
|
|
74
|
+
export type InsertPosition = {
|
|
75
|
+
pointer: string;
|
|
76
|
+
from?: number;
|
|
77
|
+
to?: number;
|
|
78
|
+
};
|
|
79
|
+
export type LinkInsertionOption = {
|
|
80
|
+
link: string;
|
|
81
|
+
insertPosition: InsertPosition;
|
|
82
|
+
};
|
|
73
83
|
export declare enum SelectionExtensionActionTypes {
|
|
74
84
|
SET_ACTIVE_EXTENSION = "set-active-extension",
|
|
75
85
|
UPDATE_ACTIVE_EXTENSION_COORDS = "update-active-extension-coords",
|
|
76
|
-
CLEAR_ACTIVE_EXTENSION = "clear-active-extension"
|
|
86
|
+
CLEAR_ACTIVE_EXTENSION = "clear-active-extension",
|
|
87
|
+
SET_SELECTED_NODE = "set-selected-node",
|
|
88
|
+
START_TRACK_CHANGES = "start-track-changes"
|
|
77
89
|
}
|
|
78
90
|
export type UpdateActiveExtensionAction = {
|
|
79
91
|
type: SelectionExtensionActionTypes.SET_ACTIVE_EXTENSION;
|
|
@@ -90,5 +102,9 @@ export type SelectionExtensionPluginState = {
|
|
|
90
102
|
selection: SelectionExtensionSelectionInfo;
|
|
91
103
|
coords: SelectionExtensionCoords;
|
|
92
104
|
};
|
|
105
|
+
selectedNode?: PMNode;
|
|
106
|
+
nodePos?: number;
|
|
107
|
+
startTrackChanges?: boolean;
|
|
108
|
+
docChangedAfterClick?: boolean;
|
|
93
109
|
};
|
|
94
110
|
export {};
|