@atlaskit/editor-plugin-selection-extension 2.0.0 → 2.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/main.js +39 -0
- package/dist/cjs/selectionExtensionPlugin.js +73 -15
- package/dist/cjs/types/index.js +5 -0
- package/dist/cjs/ui/extension/SelectionExtensionComponentWrapper.js +69 -0
- package/dist/cjs/ui/getBoundingBoxFromSelection.js +35 -0
- package/dist/cjs/ui/toolbar/SelectionExtensionDropdownMenu.js +18 -3
- package/dist/cjs/ui/toolbar/SelectionExtensionDropdownMenuButton.js +1 -0
- package/dist/cjs/ui/toolbar/SelectionExtensionItems.js +13 -1
- package/dist/es2019/pm-plugins/main.js +31 -0
- package/dist/es2019/selectionExtensionPlugin.js +63 -12
- package/dist/es2019/types/index.js +1 -0
- package/dist/es2019/ui/extension/SelectionExtensionComponentWrapper.js +62 -0
- package/dist/es2019/ui/getBoundingBoxFromSelection.js +29 -0
- package/dist/es2019/ui/toolbar/SelectionExtensionDropdownMenu.js +18 -3
- package/dist/es2019/ui/toolbar/SelectionExtensionDropdownMenuButton.js +1 -0
- package/dist/es2019/ui/toolbar/SelectionExtensionItems.js +13 -1
- package/dist/esm/pm-plugins/main.js +32 -0
- package/dist/esm/selectionExtensionPlugin.js +73 -15
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/ui/extension/SelectionExtensionComponentWrapper.js +60 -0
- package/dist/esm/ui/getBoundingBoxFromSelection.js +29 -0
- package/dist/esm/ui/toolbar/SelectionExtensionDropdownMenu.js +18 -3
- package/dist/esm/ui/toolbar/SelectionExtensionDropdownMenuButton.js +1 -0
- package/dist/esm/ui/toolbar/SelectionExtensionItems.js +13 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/pm-plugins/main.d.ts +7 -0
- package/dist/types/selectionExtensionPluginType.d.ts +11 -23
- package/dist/types/types/index.d.ts +51 -0
- package/dist/types/ui/extension/SelectionExtensionComponentWrapper.d.ts +12 -0
- package/dist/types/ui/getBoundingBoxFromSelection.d.ts +11 -0
- package/dist/types/ui/toolbar/SelectionExtensionDropdownMenu.d.ts +5 -1
- package/dist/types/ui/toolbar/SelectionExtensionItems.d.ts +3 -2
- package/dist/types-ts4.5/index.d.ts +1 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +7 -0
- package/dist/types-ts4.5/selectionExtensionPluginType.d.ts +11 -23
- package/dist/types-ts4.5/types/index.d.ts +51 -0
- package/dist/types-ts4.5/ui/extension/SelectionExtensionComponentWrapper.d.ts +12 -0
- package/dist/types-ts4.5/ui/getBoundingBoxFromSelection.d.ts +11 -0
- package/dist/types-ts4.5/ui/toolbar/SelectionExtensionDropdownMenu.d.ts +5 -1
- package/dist/types-ts4.5/ui/toolbar/SelectionExtensionItems.d.ts +3 -2
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-selection-extension
|
|
2
2
|
|
|
3
|
+
## 2.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#119729](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/119729)
|
|
8
|
+
[`beae885f06562`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/beae885f06562) -
|
|
9
|
+
ED-26710 add analytics events to selection extension plugin
|
|
10
|
+
|
|
11
|
+
## 2.1.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- [#115116](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/115116)
|
|
16
|
+
[`344eb36211daa`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/344eb36211daa) -
|
|
17
|
+
[ux] ED-26394 support component rendering in editor selection plugin
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
|
|
3
23
|
## 2.0.0
|
|
4
24
|
|
|
5
25
|
### Major Changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.selectionExtensionPluginKey = exports.createPlugin = void 0;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
+
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
10
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
11
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
12
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
13
|
+
var selectionExtensionPluginKey = exports.selectionExtensionPluginKey = new _state.PluginKey('selectionExtensionPlugin');
|
|
14
|
+
var createPlugin = exports.createPlugin = function createPlugin() {
|
|
15
|
+
return new _safePlugin.SafePlugin({
|
|
16
|
+
key: selectionExtensionPluginKey,
|
|
17
|
+
state: {
|
|
18
|
+
init: function init() {
|
|
19
|
+
return {
|
|
20
|
+
activeExtension: undefined
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
apply: function apply(tr, pluginState) {
|
|
24
|
+
var meta = tr.getMeta(selectionExtensionPluginKey);
|
|
25
|
+
switch (meta === null || meta === void 0 ? void 0 : meta.type) {
|
|
26
|
+
case 'set-active-extension':
|
|
27
|
+
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
28
|
+
activeExtension: meta.extension
|
|
29
|
+
});
|
|
30
|
+
case 'clear-active-extension':
|
|
31
|
+
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
32
|
+
activeExtension: undefined
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return pluginState;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
};
|
|
@@ -6,12 +6,49 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.selectionExtensionPlugin = void 0;
|
|
8
8
|
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _main = require("./pm-plugins/main");
|
|
10
|
+
var _SelectionExtensionComponentWrapper = require("./ui/extension/SelectionExtensionComponentWrapper");
|
|
11
|
+
var _getBoundingBoxFromSelection = require("./ui/getBoundingBoxFromSelection");
|
|
9
12
|
var _SelectionExtensionItems = require("./ui/toolbar/SelectionExtensionItems");
|
|
10
13
|
var selectionExtensionPlugin = exports.selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
|
|
11
14
|
var api = _ref.api,
|
|
12
15
|
config = _ref.config;
|
|
13
16
|
return {
|
|
14
17
|
name: 'selectionExtension',
|
|
18
|
+
getSharedState: function getSharedState(editorState) {
|
|
19
|
+
if (!editorState) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return _main.selectionExtensionPluginKey.getState(editorState) || null;
|
|
23
|
+
},
|
|
24
|
+
commands: {
|
|
25
|
+
setActiveExtension: function setActiveExtension(extension) {
|
|
26
|
+
return function (_ref2) {
|
|
27
|
+
var tr = _ref2.tr;
|
|
28
|
+
return tr.setMeta(_main.selectionExtensionPluginKey, {
|
|
29
|
+
type: 'set-active-extension',
|
|
30
|
+
extension: extension
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
clearActiveExtension: function clearActiveExtension() {
|
|
35
|
+
return function (_ref3) {
|
|
36
|
+
var tr = _ref3.tr;
|
|
37
|
+
return tr.setMeta(_main.selectionExtensionPluginKey, {
|
|
38
|
+
type: 'clear-active-extension'
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
contentComponent: function contentComponent(_ref4) {
|
|
44
|
+
var _api$analytics;
|
|
45
|
+
var editorView = _ref4.editorView;
|
|
46
|
+
return /*#__PURE__*/_react.default.createElement(_SelectionExtensionComponentWrapper.SelectionExtensionComponentWrapper, {
|
|
47
|
+
editorView: editorView,
|
|
48
|
+
api: api,
|
|
49
|
+
editorAnalyticsAPI: api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions
|
|
50
|
+
});
|
|
51
|
+
},
|
|
15
52
|
pluginsOptions: {
|
|
16
53
|
selectionToolbar: function selectionToolbar(state) {
|
|
17
54
|
var _api$editorViewMode;
|
|
@@ -52,20 +89,33 @@ var selectionExtensionPlugin = exports.selectionExtensionPlugin = function selec
|
|
|
52
89
|
return;
|
|
53
90
|
}
|
|
54
91
|
}
|
|
55
|
-
var handleOnExtensionClick = function handleOnExtensionClick(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
92
|
+
var handleOnExtensionClick = function handleOnExtensionClick(view) {
|
|
93
|
+
return function (extension) {
|
|
94
|
+
var currentSelection = state.selection;
|
|
95
|
+
var from = currentSelection.from,
|
|
96
|
+
to = currentSelection.to;
|
|
97
|
+
var text = state.doc.textBetween(from, to, '\n');
|
|
98
|
+
var coords = (0, _getBoundingBoxFromSelection.getBoundingBoxFromSelection)(view, from, to);
|
|
99
|
+
var selection = {
|
|
100
|
+
text: text,
|
|
101
|
+
selection: {
|
|
102
|
+
from: from,
|
|
103
|
+
to: to
|
|
104
|
+
},
|
|
105
|
+
coords: coords
|
|
106
|
+
};
|
|
60
107
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
108
|
+
// Render component here
|
|
109
|
+
if (extension.component) {
|
|
110
|
+
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.selectionExtension.commands.setActiveExtension({
|
|
111
|
+
extension: extension,
|
|
112
|
+
selection: selection
|
|
113
|
+
}));
|
|
67
114
|
}
|
|
68
|
-
|
|
115
|
+
if (extension.onClick) {
|
|
116
|
+
extension.onClick(selection);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
69
119
|
};
|
|
70
120
|
|
|
71
121
|
/**
|
|
@@ -75,16 +125,16 @@ var selectionExtensionPlugin = exports.selectionExtensionPlugin = function selec
|
|
|
75
125
|
type: 'custom',
|
|
76
126
|
supportsViewMode: true,
|
|
77
127
|
render: function render(view) {
|
|
78
|
-
var _api$
|
|
128
|
+
var _api$analytics2;
|
|
79
129
|
if (!view) {
|
|
80
130
|
return;
|
|
81
131
|
}
|
|
82
132
|
return /*#__PURE__*/_react.default.createElement(_SelectionExtensionItems.SelectionExtensionItems, {
|
|
83
133
|
api: api,
|
|
84
134
|
editorView: view,
|
|
85
|
-
editorAnalyticsAPI: api === null || api === void 0 || (_api$
|
|
135
|
+
editorAnalyticsAPI: api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions,
|
|
86
136
|
extensions: extensions,
|
|
87
|
-
onExtensionClick: handleOnExtensionClick
|
|
137
|
+
onExtensionClick: handleOnExtensionClick(view)
|
|
88
138
|
});
|
|
89
139
|
},
|
|
90
140
|
fallback: []
|
|
@@ -95,6 +145,14 @@ var selectionExtensionPlugin = exports.selectionExtensionPlugin = function selec
|
|
|
95
145
|
rank: -6
|
|
96
146
|
};
|
|
97
147
|
}
|
|
148
|
+
},
|
|
149
|
+
pmPlugins: function pmPlugins() {
|
|
150
|
+
return [{
|
|
151
|
+
name: 'selectionExtension',
|
|
152
|
+
plugin: function plugin() {
|
|
153
|
+
return (0, _main.createPlugin)();
|
|
154
|
+
}
|
|
155
|
+
}];
|
|
98
156
|
}
|
|
99
157
|
};
|
|
100
158
|
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.SelectionExtensionComponentWrapper = void 0;
|
|
8
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
10
|
+
var _hooks = require("@atlaskit/editor-common/hooks");
|
|
11
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
12
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
13
|
+
var SelectionExtensionComponentWrapper = exports.SelectionExtensionComponentWrapper = function SelectionExtensionComponentWrapper(_ref) {
|
|
14
|
+
var _selectionExtensionSt4;
|
|
15
|
+
var api = _ref.api,
|
|
16
|
+
editorAnalyticsAPI = _ref.editorAnalyticsAPI;
|
|
17
|
+
var componentRef = (0, _react.useRef)();
|
|
18
|
+
var _useSharedPluginState = (0, _hooks.useSharedPluginState)(api, ['selectionExtension', 'editorViewMode']),
|
|
19
|
+
selectionExtensionState = _useSharedPluginState.selectionExtensionState,
|
|
20
|
+
editorViewModeState = _useSharedPluginState.editorViewModeState;
|
|
21
|
+
|
|
22
|
+
// Closed from active extension
|
|
23
|
+
var handleOnClose = (0, _react.useCallback)(function () {
|
|
24
|
+
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.selectionExtension.commands.clearActiveExtension());
|
|
25
|
+
// Clears reference to active component
|
|
26
|
+
componentRef.current = undefined;
|
|
27
|
+
if (editorAnalyticsAPI) {
|
|
28
|
+
editorAnalyticsAPI.fireAnalyticsEvent({
|
|
29
|
+
action: _analytics.ACTION.CLOSED,
|
|
30
|
+
actionSubject: _analytics.ACTION_SUBJECT.EDITOR_PLUGIN_SELECTION_EXTENSION,
|
|
31
|
+
actionSubjectId: _analytics.ACTION_SUBJECT_ID.EDITOR_PLUGIN_SELECTION_EXTENSION_COMPONENT,
|
|
32
|
+
eventType: _analytics.EVENT_TYPE.TRACK
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}, [editorAnalyticsAPI, api]);
|
|
36
|
+
|
|
37
|
+
// Closed from editor page mode change
|
|
38
|
+
(0, _react.useEffect)(function () {
|
|
39
|
+
if (componentRef.current !== undefined) {
|
|
40
|
+
handleOnClose();
|
|
41
|
+
}
|
|
42
|
+
}, [handleOnClose, editorViewModeState]);
|
|
43
|
+
|
|
44
|
+
// Viewed analytics event for component mount
|
|
45
|
+
(0, _react.useEffect)(function () {
|
|
46
|
+
var _selectionExtensionSt, _selectionExtensionSt2;
|
|
47
|
+
if (componentRef.current !== (selectionExtensionState === null || selectionExtensionState === void 0 || (_selectionExtensionSt = selectionExtensionState.activeExtension) === null || _selectionExtensionSt === void 0 ? void 0 : _selectionExtensionSt.extension.component) && (selectionExtensionState === null || selectionExtensionState === void 0 || (_selectionExtensionSt2 = selectionExtensionState.activeExtension) === null || _selectionExtensionSt2 === void 0 ? void 0 : _selectionExtensionSt2.extension.component) !== undefined) {
|
|
48
|
+
var _selectionExtensionSt3;
|
|
49
|
+
if (editorAnalyticsAPI) {
|
|
50
|
+
editorAnalyticsAPI.fireAnalyticsEvent({
|
|
51
|
+
action: _analytics.ACTION.VIEWED,
|
|
52
|
+
actionSubject: _analytics.ACTION_SUBJECT.EDITOR_PLUGIN_SELECTION_EXTENSION,
|
|
53
|
+
actionSubjectId: _analytics.ACTION_SUBJECT_ID.EDITOR_PLUGIN_SELECTION_EXTENSION_COMPONENT,
|
|
54
|
+
eventType: _analytics.EVENT_TYPE.TRACK
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// Sets reference to active component
|
|
58
|
+
componentRef.current = selectionExtensionState === null || selectionExtensionState === void 0 || (_selectionExtensionSt3 = selectionExtensionState.activeExtension) === null || _selectionExtensionSt3 === void 0 ? void 0 : _selectionExtensionSt3.extension.component;
|
|
59
|
+
}
|
|
60
|
+
}, [selectionExtensionState, editorAnalyticsAPI]);
|
|
61
|
+
if (!(selectionExtensionState !== null && selectionExtensionState !== void 0 && (_selectionExtensionSt4 = selectionExtensionState.activeExtension) !== null && _selectionExtensionSt4 !== void 0 && _selectionExtensionSt4.extension.component)) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
var ExtensionComponent = selectionExtensionState.activeExtension.extension.component;
|
|
65
|
+
return /*#__PURE__*/_react.default.createElement(ExtensionComponent, {
|
|
66
|
+
closeExtension: handleOnClose,
|
|
67
|
+
selection: selectionExtensionState.activeExtension.selection
|
|
68
|
+
});
|
|
69
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getBoundingBoxFromSelection = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Calculates the bounding box coordinates of a text selection within an editor view.
|
|
9
|
+
*
|
|
10
|
+
* @param view - The editor view instance.
|
|
11
|
+
* @param from - The starting position of the selection.
|
|
12
|
+
* @param to - The ending position of the selection.
|
|
13
|
+
* @returns An object containing the top, left, bottom, and right coordinates of the bounding box.
|
|
14
|
+
*/
|
|
15
|
+
var getBoundingBoxFromSelection = exports.getBoundingBoxFromSelection = function getBoundingBoxFromSelection(view, from, to) {
|
|
16
|
+
var top = Infinity,
|
|
17
|
+
left = Infinity,
|
|
18
|
+
bottom = -Infinity,
|
|
19
|
+
right = -Infinity;
|
|
20
|
+
|
|
21
|
+
// initial version
|
|
22
|
+
for (var pos = from; pos <= to; pos++) {
|
|
23
|
+
var coords = view.coordsAtPos(pos);
|
|
24
|
+
top = Math.min(top, coords.top);
|
|
25
|
+
left = Math.min(left, coords.left);
|
|
26
|
+
bottom = Math.max(bottom, coords.bottom);
|
|
27
|
+
right = Math.max(right, coords.right);
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
top: top,
|
|
31
|
+
left: left,
|
|
32
|
+
bottom: bottom,
|
|
33
|
+
right: right
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -9,13 +9,15 @@ exports.SelectionExtensionDropdownMenu = void 0;
|
|
|
9
9
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
10
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
11
11
|
var _reactIntlNext = require("react-intl-next");
|
|
12
|
+
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
12
13
|
var _uiMenu = require("@atlaskit/editor-common/ui-menu");
|
|
13
14
|
var _SelectionExtensionDropdownMenuButton = require("./SelectionExtensionDropdownMenuButton");
|
|
14
15
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
15
16
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
16
17
|
var SelectionExtensionDropdownMenuComponent = /*#__PURE__*/_react.default.memo(function (_ref) {
|
|
17
18
|
var items = _ref.items,
|
|
18
|
-
onItemActivated = _ref.onItemActivated
|
|
19
|
+
onItemActivated = _ref.onItemActivated,
|
|
20
|
+
editorAnalyticsAPI = _ref.editorAnalyticsAPI;
|
|
19
21
|
var _useState = (0, _react.useState)(false),
|
|
20
22
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
21
23
|
isMenuOpen = _useState2[0],
|
|
@@ -31,9 +33,22 @@ var SelectionExtensionDropdownMenuComponent = /*#__PURE__*/_react.default.memo(f
|
|
|
31
33
|
onItemActivated: onItemActivated,
|
|
32
34
|
"data-testid": "selection-extension-dropdown-menu"
|
|
33
35
|
}, /*#__PURE__*/_react.default.createElement(_SelectionExtensionDropdownMenuButton.SelectionExtensionDropdownMenuButton, {
|
|
34
|
-
"data-testid": "selection-extension-dropdown-button",
|
|
35
36
|
onClick: function onClick() {
|
|
36
|
-
return setIsMenuOpen(
|
|
37
|
+
return setIsMenuOpen(function (prevIsMenuOpen) {
|
|
38
|
+
var nextIsMenuOpen = !prevIsMenuOpen;
|
|
39
|
+
if (editorAnalyticsAPI) {
|
|
40
|
+
editorAnalyticsAPI.fireAnalyticsEvent({
|
|
41
|
+
action: _analytics.ACTION.CLICKED,
|
|
42
|
+
actionSubject: _analytics.ACTION_SUBJECT.BUTTON,
|
|
43
|
+
actionSubjectId: _analytics.ACTION_SUBJECT_ID.EDITOR_PLUGIN_SELECTION_EXTENSION_DROPDOWN,
|
|
44
|
+
eventType: _analytics.EVENT_TYPE.TRACK,
|
|
45
|
+
attributes: {
|
|
46
|
+
toggle: nextIsMenuOpen ? _analytics.ACTION.OPENED : _analytics.ACTION.CLOSED
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return nextIsMenuOpen;
|
|
51
|
+
});
|
|
37
52
|
}
|
|
38
53
|
}));
|
|
39
54
|
});
|
|
@@ -12,6 +12,7 @@ var _apps = _interopRequireDefault(require("@atlaskit/icon/core/apps"));
|
|
|
12
12
|
var SelectionExtensionDropdownMenuButtonComponent = function SelectionExtensionDropdownMenuButtonComponent(_ref) {
|
|
13
13
|
var onClick = _ref.onClick;
|
|
14
14
|
return /*#__PURE__*/_react.default.createElement(_uiMenu.ToolbarButton, {
|
|
15
|
+
testId: "selection-extension-dropdown-button",
|
|
15
16
|
onClick: onClick
|
|
16
17
|
}, /*#__PURE__*/_react.default.createElement(_apps.default, {
|
|
17
18
|
label: "selection extension dropdown"
|
|
@@ -10,6 +10,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
|
|
|
10
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
11
11
|
var _reactIntlNext = require("react-intl-next");
|
|
12
12
|
var _uuid = require("uuid");
|
|
13
|
+
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
13
14
|
var _SelectionExtensionDropdownMenu = require("./SelectionExtensionDropdownMenu");
|
|
14
15
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
15
16
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
@@ -21,6 +22,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
21
22
|
var transformExtensionsToItems = function transformExtensionsToItems(extensions) {
|
|
22
23
|
var extensionToItems = extensions.map(function (extension) {
|
|
23
24
|
return {
|
|
25
|
+
key: extension.id,
|
|
24
26
|
content: extension.name,
|
|
25
27
|
value: {
|
|
26
28
|
name: extension.id
|
|
@@ -33,7 +35,8 @@ var transformExtensionsToItems = function transformExtensionsToItems(extensions)
|
|
|
33
35
|
};
|
|
34
36
|
var SelectionExtensionItemsComponent = exports.SelectionExtensionItemsComponent = function SelectionExtensionItemsComponent(_ref) {
|
|
35
37
|
var extensions = _ref.extensions,
|
|
36
|
-
onExtensionClick = _ref.onExtensionClick
|
|
38
|
+
onExtensionClick = _ref.onExtensionClick,
|
|
39
|
+
editorAnalyticsAPI = _ref.editorAnalyticsAPI;
|
|
37
40
|
var extensionsWithIdentifier = (0, _react.useMemo)(function () {
|
|
38
41
|
return extensions.map(function (extension) {
|
|
39
42
|
return _objectSpread(_objectSpread({}, extension), {}, {
|
|
@@ -51,9 +54,18 @@ var SelectionExtensionItemsComponent = exports.SelectionExtensionItemsComponent
|
|
|
51
54
|
});
|
|
52
55
|
if (extension) {
|
|
53
56
|
onExtensionClick(extension);
|
|
57
|
+
if (editorAnalyticsAPI) {
|
|
58
|
+
editorAnalyticsAPI.fireAnalyticsEvent({
|
|
59
|
+
action: _analytics.ACTION.CLICKED,
|
|
60
|
+
actionSubject: _analytics.ACTION_SUBJECT.BUTTON,
|
|
61
|
+
actionSubjectId: _analytics.ACTION_SUBJECT_ID.EDITOR_PLUGIN_SELECTION_EXTENSION_ITEM,
|
|
62
|
+
eventType: _analytics.EVENT_TYPE.TRACK
|
|
63
|
+
});
|
|
64
|
+
}
|
|
54
65
|
}
|
|
55
66
|
};
|
|
56
67
|
return /*#__PURE__*/_react.default.createElement(_SelectionExtensionDropdownMenu.SelectionExtensionDropdownMenu, {
|
|
68
|
+
editorAnalyticsAPI: editorAnalyticsAPI,
|
|
57
69
|
items: items,
|
|
58
70
|
onItemActivated: handleOnItemActivated
|
|
59
71
|
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
export const selectionExtensionPluginKey = new PluginKey('selectionExtensionPlugin');
|
|
4
|
+
export const createPlugin = () => {
|
|
5
|
+
return new SafePlugin({
|
|
6
|
+
key: selectionExtensionPluginKey,
|
|
7
|
+
state: {
|
|
8
|
+
init: () => {
|
|
9
|
+
return {
|
|
10
|
+
activeExtension: undefined
|
|
11
|
+
};
|
|
12
|
+
},
|
|
13
|
+
apply: (tr, pluginState) => {
|
|
14
|
+
const meta = tr.getMeta(selectionExtensionPluginKey);
|
|
15
|
+
switch (meta === null || meta === void 0 ? void 0 : meta.type) {
|
|
16
|
+
case 'set-active-extension':
|
|
17
|
+
return {
|
|
18
|
+
...pluginState,
|
|
19
|
+
activeExtension: meta.extension
|
|
20
|
+
};
|
|
21
|
+
case 'clear-active-extension':
|
|
22
|
+
return {
|
|
23
|
+
...pluginState,
|
|
24
|
+
activeExtension: undefined
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return pluginState;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { selectionExtensionPluginKey, createPlugin } from './pm-plugins/main';
|
|
3
|
+
import { SelectionExtensionComponentWrapper } from './ui/extension/SelectionExtensionComponentWrapper';
|
|
4
|
+
import { getBoundingBoxFromSelection } from './ui/getBoundingBoxFromSelection';
|
|
2
5
|
import { SelectionExtensionItems } from './ui/toolbar/SelectionExtensionItems';
|
|
3
6
|
export const selectionExtensionPlugin = ({
|
|
4
7
|
api,
|
|
@@ -6,6 +9,39 @@ export const selectionExtensionPlugin = ({
|
|
|
6
9
|
}) => {
|
|
7
10
|
return {
|
|
8
11
|
name: 'selectionExtension',
|
|
12
|
+
getSharedState(editorState) {
|
|
13
|
+
if (!editorState) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return selectionExtensionPluginKey.getState(editorState) || null;
|
|
17
|
+
},
|
|
18
|
+
commands: {
|
|
19
|
+
setActiveExtension: extension => ({
|
|
20
|
+
tr
|
|
21
|
+
}) => {
|
|
22
|
+
return tr.setMeta(selectionExtensionPluginKey, {
|
|
23
|
+
type: 'set-active-extension',
|
|
24
|
+
extension
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
clearActiveExtension: () => ({
|
|
28
|
+
tr
|
|
29
|
+
}) => {
|
|
30
|
+
return tr.setMeta(selectionExtensionPluginKey, {
|
|
31
|
+
type: 'clear-active-extension'
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
contentComponent: ({
|
|
36
|
+
editorView
|
|
37
|
+
}) => {
|
|
38
|
+
var _api$analytics;
|
|
39
|
+
return /*#__PURE__*/React.createElement(SelectionExtensionComponentWrapper, {
|
|
40
|
+
editorView: editorView,
|
|
41
|
+
api: api,
|
|
42
|
+
editorAnalyticsAPI: api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions
|
|
43
|
+
});
|
|
44
|
+
},
|
|
9
45
|
pluginsOptions: {
|
|
10
46
|
selectionToolbar: state => {
|
|
11
47
|
var _api$editorViewMode, _api$editorViewMode$s;
|
|
@@ -48,24 +84,35 @@ export const selectionExtensionPlugin = ({
|
|
|
48
84
|
return;
|
|
49
85
|
}
|
|
50
86
|
}
|
|
51
|
-
const handleOnExtensionClick = extension => {
|
|
87
|
+
const handleOnExtensionClick = view => extension => {
|
|
52
88
|
const {
|
|
53
|
-
selection
|
|
89
|
+
selection: currentSelection
|
|
54
90
|
} = state;
|
|
55
91
|
const {
|
|
56
92
|
from,
|
|
57
93
|
to
|
|
58
|
-
} =
|
|
94
|
+
} = currentSelection;
|
|
59
95
|
const text = state.doc.textBetween(from, to, '\n');
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
extension.onClick({
|
|
96
|
+
const coords = getBoundingBoxFromSelection(view, from, to);
|
|
97
|
+
const selection = {
|
|
63
98
|
text,
|
|
64
99
|
selection: {
|
|
65
100
|
from,
|
|
66
101
|
to
|
|
67
|
-
}
|
|
68
|
-
|
|
102
|
+
},
|
|
103
|
+
coords
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Render component here
|
|
107
|
+
if (extension.component) {
|
|
108
|
+
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : api.selectionExtension.commands.setActiveExtension({
|
|
109
|
+
extension,
|
|
110
|
+
selection
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
if (extension.onClick) {
|
|
114
|
+
extension.onClick(selection);
|
|
115
|
+
}
|
|
69
116
|
};
|
|
70
117
|
|
|
71
118
|
/**
|
|
@@ -75,16 +122,16 @@ export const selectionExtensionPlugin = ({
|
|
|
75
122
|
type: 'custom',
|
|
76
123
|
supportsViewMode: true,
|
|
77
124
|
render: view => {
|
|
78
|
-
var _api$
|
|
125
|
+
var _api$analytics2;
|
|
79
126
|
if (!view) {
|
|
80
127
|
return;
|
|
81
128
|
}
|
|
82
129
|
return /*#__PURE__*/React.createElement(SelectionExtensionItems, {
|
|
83
130
|
api: api,
|
|
84
131
|
editorView: view,
|
|
85
|
-
editorAnalyticsAPI: api === null || api === void 0 ? void 0 : (_api$
|
|
132
|
+
editorAnalyticsAPI: api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions,
|
|
86
133
|
extensions: extensions,
|
|
87
|
-
onExtensionClick: handleOnExtensionClick
|
|
134
|
+
onExtensionClick: handleOnExtensionClick(view)
|
|
88
135
|
});
|
|
89
136
|
},
|
|
90
137
|
fallback: []
|
|
@@ -95,6 +142,10 @@ export const selectionExtensionPlugin = ({
|
|
|
95
142
|
rank: -6
|
|
96
143
|
};
|
|
97
144
|
}
|
|
98
|
-
}
|
|
145
|
+
},
|
|
146
|
+
pmPlugins: () => [{
|
|
147
|
+
name: 'selectionExtension',
|
|
148
|
+
plugin: () => createPlugin()
|
|
149
|
+
}]
|
|
99
150
|
};
|
|
100
151
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
|
|
4
|
+
export const SelectionExtensionComponentWrapper = ({
|
|
5
|
+
api,
|
|
6
|
+
editorAnalyticsAPI
|
|
7
|
+
}) => {
|
|
8
|
+
var _selectionExtensionSt4;
|
|
9
|
+
const componentRef = useRef();
|
|
10
|
+
const {
|
|
11
|
+
selectionExtensionState,
|
|
12
|
+
editorViewModeState
|
|
13
|
+
} = useSharedPluginState(api, ['selectionExtension', 'editorViewMode']);
|
|
14
|
+
|
|
15
|
+
// Closed from active extension
|
|
16
|
+
const handleOnClose = useCallback(() => {
|
|
17
|
+
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : api.selectionExtension.commands.clearActiveExtension());
|
|
18
|
+
// Clears reference to active component
|
|
19
|
+
componentRef.current = undefined;
|
|
20
|
+
if (editorAnalyticsAPI) {
|
|
21
|
+
editorAnalyticsAPI.fireAnalyticsEvent({
|
|
22
|
+
action: ACTION.CLOSED,
|
|
23
|
+
actionSubject: ACTION_SUBJECT.EDITOR_PLUGIN_SELECTION_EXTENSION,
|
|
24
|
+
actionSubjectId: ACTION_SUBJECT_ID.EDITOR_PLUGIN_SELECTION_EXTENSION_COMPONENT,
|
|
25
|
+
eventType: EVENT_TYPE.TRACK
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}, [editorAnalyticsAPI, api]);
|
|
29
|
+
|
|
30
|
+
// Closed from editor page mode change
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (componentRef.current !== undefined) {
|
|
33
|
+
handleOnClose();
|
|
34
|
+
}
|
|
35
|
+
}, [handleOnClose, editorViewModeState]);
|
|
36
|
+
|
|
37
|
+
// Viewed analytics event for component mount
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
var _selectionExtensionSt, _selectionExtensionSt2;
|
|
40
|
+
if (componentRef.current !== (selectionExtensionState === null || selectionExtensionState === void 0 ? void 0 : (_selectionExtensionSt = selectionExtensionState.activeExtension) === null || _selectionExtensionSt === void 0 ? void 0 : _selectionExtensionSt.extension.component) && (selectionExtensionState === null || selectionExtensionState === void 0 ? void 0 : (_selectionExtensionSt2 = selectionExtensionState.activeExtension) === null || _selectionExtensionSt2 === void 0 ? void 0 : _selectionExtensionSt2.extension.component) !== undefined) {
|
|
41
|
+
var _selectionExtensionSt3;
|
|
42
|
+
if (editorAnalyticsAPI) {
|
|
43
|
+
editorAnalyticsAPI.fireAnalyticsEvent({
|
|
44
|
+
action: ACTION.VIEWED,
|
|
45
|
+
actionSubject: ACTION_SUBJECT.EDITOR_PLUGIN_SELECTION_EXTENSION,
|
|
46
|
+
actionSubjectId: ACTION_SUBJECT_ID.EDITOR_PLUGIN_SELECTION_EXTENSION_COMPONENT,
|
|
47
|
+
eventType: EVENT_TYPE.TRACK
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// Sets reference to active component
|
|
51
|
+
componentRef.current = selectionExtensionState === null || selectionExtensionState === void 0 ? void 0 : (_selectionExtensionSt3 = selectionExtensionState.activeExtension) === null || _selectionExtensionSt3 === void 0 ? void 0 : _selectionExtensionSt3.extension.component;
|
|
52
|
+
}
|
|
53
|
+
}, [selectionExtensionState, editorAnalyticsAPI]);
|
|
54
|
+
if (!(selectionExtensionState !== null && selectionExtensionState !== void 0 && (_selectionExtensionSt4 = selectionExtensionState.activeExtension) !== null && _selectionExtensionSt4 !== void 0 && _selectionExtensionSt4.extension.component)) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const ExtensionComponent = selectionExtensionState.activeExtension.extension.component;
|
|
58
|
+
return /*#__PURE__*/React.createElement(ExtensionComponent, {
|
|
59
|
+
closeExtension: handleOnClose,
|
|
60
|
+
selection: selectionExtensionState.activeExtension.selection
|
|
61
|
+
});
|
|
62
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculates the bounding box coordinates of a text selection within an editor view.
|
|
3
|
+
*
|
|
4
|
+
* @param view - The editor view instance.
|
|
5
|
+
* @param from - The starting position of the selection.
|
|
6
|
+
* @param to - The ending position of the selection.
|
|
7
|
+
* @returns An object containing the top, left, bottom, and right coordinates of the bounding box.
|
|
8
|
+
*/
|
|
9
|
+
export const getBoundingBoxFromSelection = (view, from, to) => {
|
|
10
|
+
let top = Infinity,
|
|
11
|
+
left = Infinity,
|
|
12
|
+
bottom = -Infinity,
|
|
13
|
+
right = -Infinity;
|
|
14
|
+
|
|
15
|
+
// initial version
|
|
16
|
+
for (let pos = from; pos <= to; pos++) {
|
|
17
|
+
const coords = view.coordsAtPos(pos);
|
|
18
|
+
top = Math.min(top, coords.top);
|
|
19
|
+
left = Math.min(left, coords.left);
|
|
20
|
+
bottom = Math.max(bottom, coords.bottom);
|
|
21
|
+
right = Math.max(right, coords.right);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
top,
|
|
25
|
+
left,
|
|
26
|
+
bottom,
|
|
27
|
+
right
|
|
28
|
+
};
|
|
29
|
+
};
|