@atlaskit/editor-plugin-quick-insert 6.0.5 → 6.0.7
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 +17 -0
- package/dist/cjs/pm-plugins/experiences/quick-insert-open-experience.js +150 -0
- package/dist/cjs/quickInsertPlugin.js +17 -6
- package/dist/es2019/pm-plugins/experiences/quick-insert-open-experience.js +144 -0
- package/dist/es2019/quickInsertPlugin.js +14 -5
- package/dist/esm/pm-plugins/experiences/quick-insert-open-experience.js +143 -0
- package/dist/esm/quickInsertPlugin.js +17 -6
- package/dist/types/pm-plugins/experiences/quick-insert-open-experience.d.ts +17 -0
- package/dist/types-ts4.5/pm-plugins/experiences/quick-insert-open-experience.d.ts +17 -0
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-quick-insert
|
|
2
2
|
|
|
3
|
+
## 6.0.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`0d661119b4293`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0d661119b4293) -
|
|
8
|
+
Clean up platform_editor_insertion experiment by shipping control variant. Remove modern TypeAhead
|
|
9
|
+
components and experiment infrastructure while preserving all existing functionality.
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
|
|
12
|
+
## 6.0.6
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [`610bf07ab4a4f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/610bf07ab4a4f) -
|
|
17
|
+
ED-29611 Editor quick insert experience tracking
|
|
18
|
+
- Updated dependencies
|
|
19
|
+
|
|
3
20
|
## 6.0.5
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.getQuickInsertOpenExperiencePlugin = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _experiences = require("@atlaskit/editor-common/experiences");
|
|
10
|
+
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
11
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
12
|
+
var pluginKey = new _state.PluginKey('quickInsertOpenExperience');
|
|
13
|
+
var START_METHOD = {
|
|
14
|
+
QUICK_INSERT_BUTTON: 'quick-insert-button',
|
|
15
|
+
TYPEAHEAD: 'typeahead'
|
|
16
|
+
};
|
|
17
|
+
var ABORT_REASON = {
|
|
18
|
+
USER_CANCELED: 'user-canceled',
|
|
19
|
+
EDITOR_DESTROYED: 'editor-destroyed'
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* This experience tracks when the quick insert is opened.
|
|
23
|
+
*
|
|
24
|
+
* Start: When user types `/` to open quick insert or clicks the quick insert button
|
|
25
|
+
* Success: When the quick insert menu is added to the DOM within 500ms of start
|
|
26
|
+
* Failure: When 500ms passes without the quick insert menu being added to the DOM
|
|
27
|
+
* Abort: When user presses escape or backspace
|
|
28
|
+
*/
|
|
29
|
+
var getQuickInsertOpenExperiencePlugin = exports.getQuickInsertOpenExperiencePlugin = function getQuickInsertOpenExperiencePlugin(_ref) {
|
|
30
|
+
var refs = _ref.refs;
|
|
31
|
+
var targetEl;
|
|
32
|
+
var editorViewEl;
|
|
33
|
+
var getTarget = function getTarget() {
|
|
34
|
+
if (!targetEl) {
|
|
35
|
+
targetEl = refs.popupsMountPoint || refs.wrapperElement || (0, _experiences.getPopupContainerFromEditorView)(editorViewEl);
|
|
36
|
+
}
|
|
37
|
+
return targetEl;
|
|
38
|
+
};
|
|
39
|
+
var experience = new _experiences.Experience('quick-insert-open', {
|
|
40
|
+
checks: [new _experiences.ExperienceCheckTimeout({
|
|
41
|
+
durationMs: 500
|
|
42
|
+
}), new _experiences.ExperienceCheckDomMutation({
|
|
43
|
+
onDomMutation: function onDomMutation(_ref2) {
|
|
44
|
+
var mutations = _ref2.mutations;
|
|
45
|
+
if (mutations.some(isQuickInsertMenuAddedInMutation)) {
|
|
46
|
+
return {
|
|
47
|
+
status: 'success'
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
observeConfig: function observeConfig() {
|
|
52
|
+
return {
|
|
53
|
+
target: getTarget(),
|
|
54
|
+
options: {
|
|
55
|
+
childList: true
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
})]
|
|
60
|
+
});
|
|
61
|
+
return new _safePlugin.SafePlugin({
|
|
62
|
+
key: pluginKey,
|
|
63
|
+
props: {
|
|
64
|
+
handleDOMEvents: {
|
|
65
|
+
click: function click(_view, event) {
|
|
66
|
+
if (isTargetQuickInsertButton(event.target)) {
|
|
67
|
+
experience.start({
|
|
68
|
+
metadata: {
|
|
69
|
+
method: START_METHOD.QUICK_INSERT_BUTTON
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
beforeinput: function beforeinput(view, event) {
|
|
75
|
+
if (isQuickInsertTrigger(event) && isSelectionWhichSupportsTypeahead(view)) {
|
|
76
|
+
experience.start({
|
|
77
|
+
metadata: {
|
|
78
|
+
method: START_METHOD.TYPEAHEAD
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
keydown: function keydown(_view, event) {
|
|
84
|
+
if (isCancelKey(event.key) && !isQuickInsertMenuWithinNode(getTarget())) {
|
|
85
|
+
experience.abort({
|
|
86
|
+
metadata: {
|
|
87
|
+
reason: ABORT_REASON.USER_CANCELED
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
view: function view(editorView) {
|
|
95
|
+
editorViewEl = editorView.dom;
|
|
96
|
+
return {
|
|
97
|
+
destroy: function destroy() {
|
|
98
|
+
experience.abort({
|
|
99
|
+
metadata: {
|
|
100
|
+
reason: ABORT_REASON.EDITOR_DESTROYED
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
var isQuickInsertTrigger = function isQuickInsertTrigger(_ref3) {
|
|
109
|
+
var inputType = _ref3.inputType,
|
|
110
|
+
data = _ref3.data;
|
|
111
|
+
return inputType === 'insertText' && data === '/';
|
|
112
|
+
};
|
|
113
|
+
var isSelectionWhichSupportsTypeahead = function isSelectionWhichSupportsTypeahead(_ref4) {
|
|
114
|
+
var _nodeBefore$textConte;
|
|
115
|
+
var state = _ref4.state;
|
|
116
|
+
var _state$selection = state.selection,
|
|
117
|
+
from = _state$selection.from,
|
|
118
|
+
$from = _state$selection.$from;
|
|
119
|
+
if ($from.parent.type.name === 'codeBlock') {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
if ($from.marks().some(function (mark) {
|
|
123
|
+
return mark.type.name === 'code';
|
|
124
|
+
})) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
if (from === 0) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
var nodeBefore = state.doc.resolve(from).nodeBefore;
|
|
131
|
+
if (!nodeBefore) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
var charBefore = ((_nodeBefore$textConte = nodeBefore.textContent) === null || _nodeBefore$textConte === void 0 ? void 0 : _nodeBefore$textConte.slice(-1)) || '';
|
|
135
|
+
return charBefore.trim().length === 0;
|
|
136
|
+
};
|
|
137
|
+
var isCancelKey = function isCancelKey(key) {
|
|
138
|
+
return key === 'Escape' || key === 'Backspace';
|
|
139
|
+
};
|
|
140
|
+
var isTargetQuickInsertButton = function isTargetQuickInsertButton(target) {
|
|
141
|
+
return target instanceof HTMLElement && (target.dataset.testid === 'editor-quick-insert-button' || !!target.closest('[data-testid="editor-quick-insert-button"]'));
|
|
142
|
+
};
|
|
143
|
+
var isQuickInsertMenuAddedInMutation = function isQuickInsertMenuAddedInMutation(_ref5) {
|
|
144
|
+
var type = _ref5.type,
|
|
145
|
+
addedNodes = _ref5.addedNodes;
|
|
146
|
+
return type === 'childList' && (0, _toConsumableArray2.default)(addedNodes).some(isQuickInsertMenuWithinNode);
|
|
147
|
+
};
|
|
148
|
+
var isQuickInsertMenuWithinNode = function isQuickInsertMenuWithinNode(node) {
|
|
149
|
+
return (0, _experiences.containsPopupWithNestedElement)(node, '.fabric-editor-typeahead');
|
|
150
|
+
};
|
|
@@ -7,8 +7,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.quickInsertPlugin = void 0;
|
|
8
8
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
9
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
10
|
-
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
11
10
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
12
12
|
var _react = _interopRequireDefault(require("react"));
|
|
13
13
|
var _reactIntlNext = require("react-intl-next");
|
|
14
14
|
var _coreUtils = require("@atlaskit/editor-common/core-utils");
|
|
@@ -19,8 +19,8 @@ var _typeAhead = require("@atlaskit/editor-common/type-ahead");
|
|
|
19
19
|
var _showMoreHorizontalEditorMore = _interopRequireDefault(require("@atlaskit/icon/core/migration/show-more-horizontal--editor-more"));
|
|
20
20
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
21
21
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
22
|
-
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
23
22
|
var _commands = require("./pm-plugins/commands");
|
|
23
|
+
var _quickInsertOpenExperience = require("./pm-plugins/experiences/quick-insert-open-experience");
|
|
24
24
|
var _pluginKey = require("./pm-plugins/plugin-key");
|
|
25
25
|
var _ModalElementBrowser = _interopRequireDefault(require("./ui/ModalElementBrowser"));
|
|
26
26
|
var _search = require("./ui/search");
|
|
@@ -29,6 +29,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
29
29
|
var quickInsertPlugin = exports.quickInsertPlugin = function quickInsertPlugin(_ref) {
|
|
30
30
|
var options = _ref.config,
|
|
31
31
|
api = _ref.api;
|
|
32
|
+
var refs = {};
|
|
32
33
|
var onInsert = function onInsert(item) {
|
|
33
34
|
var _options$onInsert;
|
|
34
35
|
options === null || options === void 0 || (_options$onInsert = options.onInsert) === null || _options$onInsert === void 0 || _options$onInsert.call(options, item);
|
|
@@ -41,9 +42,8 @@ var quickInsertPlugin = exports.quickInsertPlugin = function quickInsertPlugin(_
|
|
|
41
42
|
var query = _ref2.query,
|
|
42
43
|
editorState = _ref2.editorState;
|
|
43
44
|
var quickInsertState = _pluginKey.pluginKey.getState(editorState);
|
|
44
|
-
var queryAllItems = '';
|
|
45
45
|
return Promise.resolve((0, _search.getQuickInsertSuggestions)({
|
|
46
|
-
query:
|
|
46
|
+
query: query,
|
|
47
47
|
disableDefaultItems: options === null || options === void 0 ? void 0 : options.disableDefaultItems,
|
|
48
48
|
prioritySortingFn: options === null || options === void 0 ? void 0 : options.prioritySortingFn
|
|
49
49
|
}, quickInsertState === null || quickInsertState === void 0 ? void 0 : quickInsertState.lazyDefaultItems, quickInsertState === null || quickInsertState === void 0 ? void 0 : quickInsertState.providedItems));
|
|
@@ -81,13 +81,24 @@ var quickInsertPlugin = exports.quickInsertPlugin = function quickInsertPlugin(_
|
|
|
81
81
|
dispatch = _ref4.dispatch;
|
|
82
82
|
return quickInsertPluginFactory(defaultItems, providerFactory, getIntl, dispatch, options === null || options === void 0 ? void 0 : options.emptyStateHandler);
|
|
83
83
|
}
|
|
84
|
-
}]
|
|
84
|
+
}].concat((0, _toConsumableArray2.default)((0, _expValEquals.expValEquals)('platform_editor_experience_tracking', 'isEnabled', true) ? [{
|
|
85
|
+
name: 'quickInsertOpenExperience',
|
|
86
|
+
plugin: function plugin() {
|
|
87
|
+
return (0, _quickInsertOpenExperience.getQuickInsertOpenExperiencePlugin)({
|
|
88
|
+
refs: refs
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}] : []));
|
|
85
92
|
},
|
|
86
93
|
pluginsOptions: {
|
|
87
94
|
typeAhead: typeAhead
|
|
88
95
|
},
|
|
89
96
|
contentComponent: function contentComponent(_ref5) {
|
|
90
|
-
var editorView = _ref5.editorView
|
|
97
|
+
var editorView = _ref5.editorView,
|
|
98
|
+
popupsMountPoint = _ref5.popupsMountPoint,
|
|
99
|
+
wrapperElement = _ref5.wrapperElement;
|
|
100
|
+
refs.popupsMountPoint = popupsMountPoint || undefined;
|
|
101
|
+
refs.wrapperElement = wrapperElement || undefined;
|
|
91
102
|
if (!editorView || (0, _expValEquals.expValEquals)('platform_editor_hydratable_ui', 'isEnabled', true) && (0, _coreUtils.isSSR)()) {
|
|
92
103
|
return null;
|
|
93
104
|
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { containsPopupWithNestedElement, Experience, ExperienceCheckDomMutation, ExperienceCheckTimeout, getPopupContainerFromEditorView } from '@atlaskit/editor-common/experiences';
|
|
2
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
const pluginKey = new PluginKey('quickInsertOpenExperience');
|
|
5
|
+
const START_METHOD = {
|
|
6
|
+
QUICK_INSERT_BUTTON: 'quick-insert-button',
|
|
7
|
+
TYPEAHEAD: 'typeahead'
|
|
8
|
+
};
|
|
9
|
+
const ABORT_REASON = {
|
|
10
|
+
USER_CANCELED: 'user-canceled',
|
|
11
|
+
EDITOR_DESTROYED: 'editor-destroyed'
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* This experience tracks when the quick insert is opened.
|
|
15
|
+
*
|
|
16
|
+
* Start: When user types `/` to open quick insert or clicks the quick insert button
|
|
17
|
+
* Success: When the quick insert menu is added to the DOM within 500ms of start
|
|
18
|
+
* Failure: When 500ms passes without the quick insert menu being added to the DOM
|
|
19
|
+
* Abort: When user presses escape or backspace
|
|
20
|
+
*/
|
|
21
|
+
export const getQuickInsertOpenExperiencePlugin = ({
|
|
22
|
+
refs
|
|
23
|
+
}) => {
|
|
24
|
+
let targetEl;
|
|
25
|
+
let editorViewEl;
|
|
26
|
+
const getTarget = () => {
|
|
27
|
+
if (!targetEl) {
|
|
28
|
+
targetEl = refs.popupsMountPoint || refs.wrapperElement || getPopupContainerFromEditorView(editorViewEl);
|
|
29
|
+
}
|
|
30
|
+
return targetEl;
|
|
31
|
+
};
|
|
32
|
+
const experience = new Experience('quick-insert-open', {
|
|
33
|
+
checks: [new ExperienceCheckTimeout({
|
|
34
|
+
durationMs: 500
|
|
35
|
+
}), new ExperienceCheckDomMutation({
|
|
36
|
+
onDomMutation: ({
|
|
37
|
+
mutations
|
|
38
|
+
}) => {
|
|
39
|
+
if (mutations.some(isQuickInsertMenuAddedInMutation)) {
|
|
40
|
+
return {
|
|
41
|
+
status: 'success'
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
observeConfig: () => ({
|
|
46
|
+
target: getTarget(),
|
|
47
|
+
options: {
|
|
48
|
+
childList: true
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
})]
|
|
52
|
+
});
|
|
53
|
+
return new SafePlugin({
|
|
54
|
+
key: pluginKey,
|
|
55
|
+
props: {
|
|
56
|
+
handleDOMEvents: {
|
|
57
|
+
click: (_view, event) => {
|
|
58
|
+
if (isTargetQuickInsertButton(event.target)) {
|
|
59
|
+
experience.start({
|
|
60
|
+
metadata: {
|
|
61
|
+
method: START_METHOD.QUICK_INSERT_BUTTON
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
beforeinput: (view, event) => {
|
|
67
|
+
if (isQuickInsertTrigger(event) && isSelectionWhichSupportsTypeahead(view)) {
|
|
68
|
+
experience.start({
|
|
69
|
+
metadata: {
|
|
70
|
+
method: START_METHOD.TYPEAHEAD
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
keydown: (_view, event) => {
|
|
76
|
+
if (isCancelKey(event.key) && !isQuickInsertMenuWithinNode(getTarget())) {
|
|
77
|
+
experience.abort({
|
|
78
|
+
metadata: {
|
|
79
|
+
reason: ABORT_REASON.USER_CANCELED
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
view: editorView => {
|
|
87
|
+
editorViewEl = editorView.dom;
|
|
88
|
+
return {
|
|
89
|
+
destroy: () => {
|
|
90
|
+
experience.abort({
|
|
91
|
+
metadata: {
|
|
92
|
+
reason: ABORT_REASON.EDITOR_DESTROYED
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
const isQuickInsertTrigger = ({
|
|
101
|
+
inputType,
|
|
102
|
+
data
|
|
103
|
+
}) => {
|
|
104
|
+
return inputType === 'insertText' && data === '/';
|
|
105
|
+
};
|
|
106
|
+
const isSelectionWhichSupportsTypeahead = ({
|
|
107
|
+
state
|
|
108
|
+
}) => {
|
|
109
|
+
var _nodeBefore$textConte;
|
|
110
|
+
const {
|
|
111
|
+
from,
|
|
112
|
+
$from
|
|
113
|
+
} = state.selection;
|
|
114
|
+
if ($from.parent.type.name === 'codeBlock') {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
if ($from.marks().some(mark => mark.type.name === 'code')) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (from === 0) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
const nodeBefore = state.doc.resolve(from).nodeBefore;
|
|
124
|
+
if (!nodeBefore) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
const charBefore = ((_nodeBefore$textConte = nodeBefore.textContent) === null || _nodeBefore$textConte === void 0 ? void 0 : _nodeBefore$textConte.slice(-1)) || '';
|
|
128
|
+
return charBefore.trim().length === 0;
|
|
129
|
+
};
|
|
130
|
+
const isCancelKey = key => {
|
|
131
|
+
return key === 'Escape' || key === 'Backspace';
|
|
132
|
+
};
|
|
133
|
+
const isTargetQuickInsertButton = target => {
|
|
134
|
+
return target instanceof HTMLElement && (target.dataset.testid === 'editor-quick-insert-button' || !!target.closest('[data-testid="editor-quick-insert-button"]'));
|
|
135
|
+
};
|
|
136
|
+
const isQuickInsertMenuAddedInMutation = ({
|
|
137
|
+
type,
|
|
138
|
+
addedNodes
|
|
139
|
+
}) => {
|
|
140
|
+
return type === 'childList' && [...addedNodes].some(isQuickInsertMenuWithinNode);
|
|
141
|
+
};
|
|
142
|
+
const isQuickInsertMenuWithinNode = node => {
|
|
143
|
+
return containsPopupWithNestedElement(node, '.fabric-editor-typeahead');
|
|
144
|
+
};
|
|
@@ -8,8 +8,8 @@ import { TypeAheadAvailableNodes } from '@atlaskit/editor-common/type-ahead';
|
|
|
8
8
|
import ShowMoreHorizontalIcon from '@atlaskit/icon/core/migration/show-more-horizontal--editor-more';
|
|
9
9
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
10
10
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
11
|
-
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
12
11
|
import { createInsertItem, openElementBrowserModal } from './pm-plugins/commands';
|
|
12
|
+
import { getQuickInsertOpenExperiencePlugin } from './pm-plugins/experiences/quick-insert-open-experience';
|
|
13
13
|
import { pluginKey } from './pm-plugins/plugin-key';
|
|
14
14
|
import ModalElementBrowser from './ui/ModalElementBrowser';
|
|
15
15
|
import { getQuickInsertSuggestions } from './ui/search';
|
|
@@ -17,6 +17,7 @@ export const quickInsertPlugin = ({
|
|
|
17
17
|
config: options,
|
|
18
18
|
api
|
|
19
19
|
}) => {
|
|
20
|
+
const refs = {};
|
|
20
21
|
const onInsert = item => {
|
|
21
22
|
var _options$onInsert;
|
|
22
23
|
options === null || options === void 0 ? void 0 : (_options$onInsert = options.onInsert) === null || _options$onInsert === void 0 ? void 0 : _options$onInsert.call(options, item);
|
|
@@ -30,9 +31,8 @@ export const quickInsertPlugin = ({
|
|
|
30
31
|
editorState
|
|
31
32
|
}) {
|
|
32
33
|
const quickInsertState = pluginKey.getState(editorState);
|
|
33
|
-
const queryAllItems = '';
|
|
34
34
|
return Promise.resolve(getQuickInsertSuggestions({
|
|
35
|
-
query:
|
|
35
|
+
query: query,
|
|
36
36
|
disableDefaultItems: options === null || options === void 0 ? void 0 : options.disableDefaultItems,
|
|
37
37
|
prioritySortingFn: options === null || options === void 0 ? void 0 : options.prioritySortingFn
|
|
38
38
|
}, quickInsertState === null || quickInsertState === void 0 ? void 0 : quickInsertState.lazyDefaultItems, quickInsertState === null || quickInsertState === void 0 ? void 0 : quickInsertState.providedItems));
|
|
@@ -70,14 +70,23 @@ export const quickInsertPlugin = ({
|
|
|
70
70
|
getIntl,
|
|
71
71
|
dispatch
|
|
72
72
|
}) => quickInsertPluginFactory(defaultItems, providerFactory, getIntl, dispatch, options === null || options === void 0 ? void 0 : options.emptyStateHandler)
|
|
73
|
-
}
|
|
73
|
+
}, ...(expValEquals('platform_editor_experience_tracking', 'isEnabled', true) ? [{
|
|
74
|
+
name: 'quickInsertOpenExperience',
|
|
75
|
+
plugin: () => getQuickInsertOpenExperiencePlugin({
|
|
76
|
+
refs
|
|
77
|
+
})
|
|
78
|
+
}] : [])];
|
|
74
79
|
},
|
|
75
80
|
pluginsOptions: {
|
|
76
81
|
typeAhead
|
|
77
82
|
},
|
|
78
83
|
contentComponent({
|
|
79
|
-
editorView
|
|
84
|
+
editorView,
|
|
85
|
+
popupsMountPoint,
|
|
86
|
+
wrapperElement
|
|
80
87
|
}) {
|
|
88
|
+
refs.popupsMountPoint = popupsMountPoint || undefined;
|
|
89
|
+
refs.wrapperElement = wrapperElement || undefined;
|
|
81
90
|
if (!editorView || expValEquals('platform_editor_hydratable_ui', 'isEnabled', true) && isSSR()) {
|
|
82
91
|
return null;
|
|
83
92
|
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
import { containsPopupWithNestedElement, Experience, ExperienceCheckDomMutation, ExperienceCheckTimeout, getPopupContainerFromEditorView } from '@atlaskit/editor-common/experiences';
|
|
3
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
5
|
+
var pluginKey = new PluginKey('quickInsertOpenExperience');
|
|
6
|
+
var START_METHOD = {
|
|
7
|
+
QUICK_INSERT_BUTTON: 'quick-insert-button',
|
|
8
|
+
TYPEAHEAD: 'typeahead'
|
|
9
|
+
};
|
|
10
|
+
var ABORT_REASON = {
|
|
11
|
+
USER_CANCELED: 'user-canceled',
|
|
12
|
+
EDITOR_DESTROYED: 'editor-destroyed'
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* This experience tracks when the quick insert is opened.
|
|
16
|
+
*
|
|
17
|
+
* Start: When user types `/` to open quick insert or clicks the quick insert button
|
|
18
|
+
* Success: When the quick insert menu is added to the DOM within 500ms of start
|
|
19
|
+
* Failure: When 500ms passes without the quick insert menu being added to the DOM
|
|
20
|
+
* Abort: When user presses escape or backspace
|
|
21
|
+
*/
|
|
22
|
+
export var getQuickInsertOpenExperiencePlugin = function getQuickInsertOpenExperiencePlugin(_ref) {
|
|
23
|
+
var refs = _ref.refs;
|
|
24
|
+
var targetEl;
|
|
25
|
+
var editorViewEl;
|
|
26
|
+
var getTarget = function getTarget() {
|
|
27
|
+
if (!targetEl) {
|
|
28
|
+
targetEl = refs.popupsMountPoint || refs.wrapperElement || getPopupContainerFromEditorView(editorViewEl);
|
|
29
|
+
}
|
|
30
|
+
return targetEl;
|
|
31
|
+
};
|
|
32
|
+
var experience = new Experience('quick-insert-open', {
|
|
33
|
+
checks: [new ExperienceCheckTimeout({
|
|
34
|
+
durationMs: 500
|
|
35
|
+
}), new ExperienceCheckDomMutation({
|
|
36
|
+
onDomMutation: function onDomMutation(_ref2) {
|
|
37
|
+
var mutations = _ref2.mutations;
|
|
38
|
+
if (mutations.some(isQuickInsertMenuAddedInMutation)) {
|
|
39
|
+
return {
|
|
40
|
+
status: 'success'
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
observeConfig: function observeConfig() {
|
|
45
|
+
return {
|
|
46
|
+
target: getTarget(),
|
|
47
|
+
options: {
|
|
48
|
+
childList: true
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
})]
|
|
53
|
+
});
|
|
54
|
+
return new SafePlugin({
|
|
55
|
+
key: pluginKey,
|
|
56
|
+
props: {
|
|
57
|
+
handleDOMEvents: {
|
|
58
|
+
click: function click(_view, event) {
|
|
59
|
+
if (isTargetQuickInsertButton(event.target)) {
|
|
60
|
+
experience.start({
|
|
61
|
+
metadata: {
|
|
62
|
+
method: START_METHOD.QUICK_INSERT_BUTTON
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
beforeinput: function beforeinput(view, event) {
|
|
68
|
+
if (isQuickInsertTrigger(event) && isSelectionWhichSupportsTypeahead(view)) {
|
|
69
|
+
experience.start({
|
|
70
|
+
metadata: {
|
|
71
|
+
method: START_METHOD.TYPEAHEAD
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
keydown: function keydown(_view, event) {
|
|
77
|
+
if (isCancelKey(event.key) && !isQuickInsertMenuWithinNode(getTarget())) {
|
|
78
|
+
experience.abort({
|
|
79
|
+
metadata: {
|
|
80
|
+
reason: ABORT_REASON.USER_CANCELED
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
view: function view(editorView) {
|
|
88
|
+
editorViewEl = editorView.dom;
|
|
89
|
+
return {
|
|
90
|
+
destroy: function destroy() {
|
|
91
|
+
experience.abort({
|
|
92
|
+
metadata: {
|
|
93
|
+
reason: ABORT_REASON.EDITOR_DESTROYED
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
var isQuickInsertTrigger = function isQuickInsertTrigger(_ref3) {
|
|
102
|
+
var inputType = _ref3.inputType,
|
|
103
|
+
data = _ref3.data;
|
|
104
|
+
return inputType === 'insertText' && data === '/';
|
|
105
|
+
};
|
|
106
|
+
var isSelectionWhichSupportsTypeahead = function isSelectionWhichSupportsTypeahead(_ref4) {
|
|
107
|
+
var _nodeBefore$textConte;
|
|
108
|
+
var state = _ref4.state;
|
|
109
|
+
var _state$selection = state.selection,
|
|
110
|
+
from = _state$selection.from,
|
|
111
|
+
$from = _state$selection.$from;
|
|
112
|
+
if ($from.parent.type.name === 'codeBlock') {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
if ($from.marks().some(function (mark) {
|
|
116
|
+
return mark.type.name === 'code';
|
|
117
|
+
})) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (from === 0) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
var nodeBefore = state.doc.resolve(from).nodeBefore;
|
|
124
|
+
if (!nodeBefore) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
var charBefore = ((_nodeBefore$textConte = nodeBefore.textContent) === null || _nodeBefore$textConte === void 0 ? void 0 : _nodeBefore$textConte.slice(-1)) || '';
|
|
128
|
+
return charBefore.trim().length === 0;
|
|
129
|
+
};
|
|
130
|
+
var isCancelKey = function isCancelKey(key) {
|
|
131
|
+
return key === 'Escape' || key === 'Backspace';
|
|
132
|
+
};
|
|
133
|
+
var isTargetQuickInsertButton = function isTargetQuickInsertButton(target) {
|
|
134
|
+
return target instanceof HTMLElement && (target.dataset.testid === 'editor-quick-insert-button' || !!target.closest('[data-testid="editor-quick-insert-button"]'));
|
|
135
|
+
};
|
|
136
|
+
var isQuickInsertMenuAddedInMutation = function isQuickInsertMenuAddedInMutation(_ref5) {
|
|
137
|
+
var type = _ref5.type,
|
|
138
|
+
addedNodes = _ref5.addedNodes;
|
|
139
|
+
return type === 'childList' && _toConsumableArray(addedNodes).some(isQuickInsertMenuWithinNode);
|
|
140
|
+
};
|
|
141
|
+
var isQuickInsertMenuWithinNode = function isQuickInsertMenuWithinNode(node) {
|
|
142
|
+
return containsPopupWithNestedElement(node, '.fabric-editor-typeahead');
|
|
143
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
|
-
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
2
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
4
4
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
5
5
|
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; }
|
|
6
6
|
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; }
|
|
@@ -14,14 +14,15 @@ import { TypeAheadAvailableNodes } from '@atlaskit/editor-common/type-ahead';
|
|
|
14
14
|
import ShowMoreHorizontalIcon from '@atlaskit/icon/core/migration/show-more-horizontal--editor-more';
|
|
15
15
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
16
16
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
17
|
-
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
18
17
|
import { createInsertItem, openElementBrowserModal as _openElementBrowserModal } from './pm-plugins/commands';
|
|
18
|
+
import { getQuickInsertOpenExperiencePlugin } from './pm-plugins/experiences/quick-insert-open-experience';
|
|
19
19
|
import { pluginKey } from './pm-plugins/plugin-key';
|
|
20
20
|
import ModalElementBrowser from './ui/ModalElementBrowser';
|
|
21
21
|
import { getQuickInsertSuggestions } from './ui/search';
|
|
22
22
|
export var quickInsertPlugin = function quickInsertPlugin(_ref) {
|
|
23
23
|
var options = _ref.config,
|
|
24
24
|
api = _ref.api;
|
|
25
|
+
var refs = {};
|
|
25
26
|
var onInsert = function onInsert(item) {
|
|
26
27
|
var _options$onInsert;
|
|
27
28
|
options === null || options === void 0 || (_options$onInsert = options.onInsert) === null || _options$onInsert === void 0 || _options$onInsert.call(options, item);
|
|
@@ -34,9 +35,8 @@ export var quickInsertPlugin = function quickInsertPlugin(_ref) {
|
|
|
34
35
|
var query = _ref2.query,
|
|
35
36
|
editorState = _ref2.editorState;
|
|
36
37
|
var quickInsertState = pluginKey.getState(editorState);
|
|
37
|
-
var queryAllItems = '';
|
|
38
38
|
return Promise.resolve(getQuickInsertSuggestions({
|
|
39
|
-
query:
|
|
39
|
+
query: query,
|
|
40
40
|
disableDefaultItems: options === null || options === void 0 ? void 0 : options.disableDefaultItems,
|
|
41
41
|
prioritySortingFn: options === null || options === void 0 ? void 0 : options.prioritySortingFn
|
|
42
42
|
}, quickInsertState === null || quickInsertState === void 0 ? void 0 : quickInsertState.lazyDefaultItems, quickInsertState === null || quickInsertState === void 0 ? void 0 : quickInsertState.providedItems));
|
|
@@ -74,13 +74,24 @@ export var quickInsertPlugin = function quickInsertPlugin(_ref) {
|
|
|
74
74
|
dispatch = _ref4.dispatch;
|
|
75
75
|
return quickInsertPluginFactory(defaultItems, providerFactory, getIntl, dispatch, options === null || options === void 0 ? void 0 : options.emptyStateHandler);
|
|
76
76
|
}
|
|
77
|
-
}]
|
|
77
|
+
}].concat(_toConsumableArray(expValEquals('platform_editor_experience_tracking', 'isEnabled', true) ? [{
|
|
78
|
+
name: 'quickInsertOpenExperience',
|
|
79
|
+
plugin: function plugin() {
|
|
80
|
+
return getQuickInsertOpenExperiencePlugin({
|
|
81
|
+
refs: refs
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}] : []));
|
|
78
85
|
},
|
|
79
86
|
pluginsOptions: {
|
|
80
87
|
typeAhead: typeAhead
|
|
81
88
|
},
|
|
82
89
|
contentComponent: function contentComponent(_ref5) {
|
|
83
|
-
var editorView = _ref5.editorView
|
|
90
|
+
var editorView = _ref5.editorView,
|
|
91
|
+
popupsMountPoint = _ref5.popupsMountPoint,
|
|
92
|
+
wrapperElement = _ref5.wrapperElement;
|
|
93
|
+
refs.popupsMountPoint = popupsMountPoint || undefined;
|
|
94
|
+
refs.wrapperElement = wrapperElement || undefined;
|
|
84
95
|
if (!editorView || expValEquals('platform_editor_hydratable_ui', 'isEnabled', true) && isSSR()) {
|
|
85
96
|
return null;
|
|
86
97
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
type QuickInsertOpenExperienceOptions = {
|
|
3
|
+
refs: {
|
|
4
|
+
popupsMountPoint?: HTMLElement;
|
|
5
|
+
wrapperElement?: HTMLElement;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* This experience tracks when the quick insert is opened.
|
|
10
|
+
*
|
|
11
|
+
* Start: When user types `/` to open quick insert or clicks the quick insert button
|
|
12
|
+
* Success: When the quick insert menu is added to the DOM within 500ms of start
|
|
13
|
+
* Failure: When 500ms passes without the quick insert menu being added to the DOM
|
|
14
|
+
* Abort: When user presses escape or backspace
|
|
15
|
+
*/
|
|
16
|
+
export declare const getQuickInsertOpenExperiencePlugin: ({ refs }: QuickInsertOpenExperienceOptions) => SafePlugin<any>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
type QuickInsertOpenExperienceOptions = {
|
|
3
|
+
refs: {
|
|
4
|
+
popupsMountPoint?: HTMLElement;
|
|
5
|
+
wrapperElement?: HTMLElement;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* This experience tracks when the quick insert is opened.
|
|
10
|
+
*
|
|
11
|
+
* Start: When user types `/` to open quick insert or clicks the quick insert button
|
|
12
|
+
* Success: When the quick insert menu is added to the DOM within 500ms of start
|
|
13
|
+
* Failure: When 500ms passes without the quick insert menu being added to the DOM
|
|
14
|
+
* Abort: When user presses escape or backspace
|
|
15
|
+
*/
|
|
16
|
+
export declare const getQuickInsertOpenExperiencePlugin: ({ refs }: QuickInsertOpenExperienceOptions) => SafePlugin<any>;
|
|
17
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-quick-insert",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.7",
|
|
4
4
|
"description": "Quick insert plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -29,22 +29,22 @@
|
|
|
29
29
|
],
|
|
30
30
|
"atlaskit:src": "src/index.ts",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@atlaskit/button": "^23.
|
|
32
|
+
"@atlaskit/button": "^23.6.0",
|
|
33
33
|
"@atlaskit/editor-plugin-connectivity": "^6.0.0",
|
|
34
|
-
"@atlaskit/editor-plugin-metrics": "^7.
|
|
35
|
-
"@atlaskit/editor-plugin-type-ahead": "^6.
|
|
34
|
+
"@atlaskit/editor-plugin-metrics": "^7.1.0",
|
|
35
|
+
"@atlaskit/editor-plugin-type-ahead": "^6.5.0",
|
|
36
36
|
"@atlaskit/editor-prosemirror": "7.0.0",
|
|
37
37
|
"@atlaskit/icon": "^28.5.0",
|
|
38
|
-
"@atlaskit/modal-dialog": "^14.
|
|
38
|
+
"@atlaskit/modal-dialog": "^14.6.0",
|
|
39
39
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
40
40
|
"@atlaskit/theme": "^21.0.0",
|
|
41
|
-
"@atlaskit/tmp-editor-statsig": "^13.
|
|
42
|
-
"@atlaskit/tokens": "^
|
|
41
|
+
"@atlaskit/tmp-editor-statsig": "^13.32.0",
|
|
42
|
+
"@atlaskit/tokens": "^8.0.0",
|
|
43
43
|
"@babel/runtime": "^7.0.0",
|
|
44
44
|
"@emotion/react": "^11.7.1"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@atlaskit/editor-common": "^110.
|
|
47
|
+
"@atlaskit/editor-common": "^110.24.0",
|
|
48
48
|
"react": "^18.2.0",
|
|
49
49
|
"react-dom": "^18.2.0",
|
|
50
50
|
"react-intl-next": "npm:react-intl@^5.18.1"
|