@atlaskit/editor-plugin-insert-block 8.4.3 → 8.4.5
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 +14 -0
- package/dist/cjs/insertBlockPlugin.js +17 -0
- package/dist/cjs/pm-plugins/experiences/toolbar-action-experiences.js +183 -0
- package/dist/cjs/pm-plugins/experiences/toolbar-experience-utils.js +409 -0
- package/dist/cjs/ui/toolbar-components/EmojiButton.js +3 -1
- package/dist/cjs/ui/toolbar-components/ImageButton.js +2 -1
- package/dist/cjs/ui/toolbar-components/InsertButton.js +2 -1
- package/dist/cjs/ui/toolbar-components/LayoutButton.js +2 -1
- package/dist/cjs/ui/toolbar-components/MediaButton.js +3 -1
- package/dist/cjs/ui/toolbar-components/MentionButton.js +3 -1
- package/dist/cjs/ui/toolbar-components/TableButton.js +1 -1
- package/dist/cjs/ui/toolbar-components/TableSizePicker.js +3 -1
- package/dist/cjs/ui/toolbar-components/TaskListButton.js +2 -1
- package/dist/es2019/insertBlockPlugin.js +15 -0
- package/dist/es2019/pm-plugins/experiences/toolbar-action-experiences.js +173 -0
- package/dist/es2019/pm-plugins/experiences/toolbar-experience-utils.js +279 -0
- package/dist/es2019/ui/toolbar-components/EmojiButton.js +3 -1
- package/dist/es2019/ui/toolbar-components/ImageButton.js +3 -2
- package/dist/es2019/ui/toolbar-components/InsertButton.js +3 -2
- package/dist/es2019/ui/toolbar-components/LayoutButton.js +3 -2
- package/dist/es2019/ui/toolbar-components/MediaButton.js +3 -1
- package/dist/es2019/ui/toolbar-components/MentionButton.js +3 -1
- package/dist/es2019/ui/toolbar-components/TableButton.js +2 -2
- package/dist/es2019/ui/toolbar-components/TableSizePicker.js +3 -1
- package/dist/es2019/ui/toolbar-components/TaskListButton.js +3 -2
- package/dist/esm/insertBlockPlugin.js +17 -0
- package/dist/esm/pm-plugins/experiences/toolbar-action-experiences.js +177 -0
- package/dist/esm/pm-plugins/experiences/toolbar-experience-utils.js +403 -0
- package/dist/esm/ui/toolbar-components/EmojiButton.js +3 -1
- package/dist/esm/ui/toolbar-components/ImageButton.js +3 -2
- package/dist/esm/ui/toolbar-components/InsertButton.js +3 -2
- package/dist/esm/ui/toolbar-components/LayoutButton.js +3 -2
- package/dist/esm/ui/toolbar-components/MediaButton.js +3 -1
- package/dist/esm/ui/toolbar-components/MentionButton.js +3 -1
- package/dist/esm/ui/toolbar-components/TableButton.js +2 -2
- package/dist/esm/ui/toolbar-components/TableSizePicker.js +3 -1
- package/dist/esm/ui/toolbar-components/TaskListButton.js +3 -2
- package/dist/types/insertBlockPlugin.d.ts +1 -1
- package/dist/types/pm-plugins/experiences/toolbar-action-experiences.d.ts +10 -0
- package/dist/types/pm-plugins/experiences/toolbar-experience-utils.d.ts +57 -0
- package/dist/types-ts4.5/insertBlockPlugin.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/experiences/toolbar-action-experiences.d.ts +10 -0
- package/dist/types-ts4.5/pm-plugins/experiences/toolbar-experience-utils.d.ts +57 -0
- package/package.json +8 -4
|
@@ -3,7 +3,7 @@ import { useIntl } from 'react-intl-next';
|
|
|
3
3
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { ToolTipContent, getAriaKeyshortcuts, toggleTable } from '@atlaskit/editor-common/keymaps';
|
|
5
5
|
import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
|
|
6
|
-
import { useEditorToolbar } from '@atlaskit/editor-common/toolbar';
|
|
6
|
+
import { useEditorToolbar, TOOLBAR_BUTTON_TEST_ID } from '@atlaskit/editor-common/toolbar';
|
|
7
7
|
import { ToolbarButton, ToolbarTooltip, TableIcon } from '@atlaskit/editor-toolbar';
|
|
8
8
|
export const TableButton = ({
|
|
9
9
|
api
|
|
@@ -50,6 +50,6 @@ export const TableButton = ({
|
|
|
50
50
|
}),
|
|
51
51
|
onClick: onClick,
|
|
52
52
|
ariaKeyshortcuts: getAriaKeyshortcuts(toggleTable),
|
|
53
|
-
testId:
|
|
53
|
+
testId: TOOLBAR_BUTTON_TEST_ID.TABLE
|
|
54
54
|
}));
|
|
55
55
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useRef } from 'react';
|
|
2
2
|
import { useIntl } from 'react-intl-next';
|
|
3
3
|
import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
|
|
4
|
+
import { TOOLBAR_BUTTON_TEST_ID } from '@atlaskit/editor-common/toolbar';
|
|
4
5
|
import { MoreItemsIcon, ToolbarButton, ToolbarTooltip, useToolbarUI } from '@atlaskit/editor-toolbar';
|
|
5
6
|
import { useTableSelectorPopup } from './hooks/useTableSelectorPopup';
|
|
6
7
|
import { TableSelectorPopupWrapper } from './popups/TableSelectorPopupWrapper';
|
|
@@ -49,6 +50,7 @@ export const TableSizePicker = ({
|
|
|
49
50
|
}),
|
|
50
51
|
onClick: onClick,
|
|
51
52
|
isSelected: tableSelectorPopup.isOpen,
|
|
52
|
-
ref: tableSizePickerRef
|
|
53
|
+
ref: tableSizePickerRef,
|
|
54
|
+
testId: TOOLBAR_BUTTON_TEST_ID.TABLE_SELECTOR
|
|
53
55
|
})));
|
|
54
56
|
};
|
|
@@ -3,7 +3,7 @@ import { useIntl } from 'react-intl-next';
|
|
|
3
3
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { ToolTipContent, insertTaskList } from '@atlaskit/editor-common/keymaps';
|
|
5
5
|
import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
|
|
6
|
-
import { useEditorToolbar } from '@atlaskit/editor-common/toolbar';
|
|
6
|
+
import { TOOLBAR_BUTTON_TEST_ID, useEditorToolbar } from '@atlaskit/editor-common/toolbar';
|
|
7
7
|
import { ToolbarButton, ToolbarTooltip, TaskIcon } from '@atlaskit/editor-toolbar';
|
|
8
8
|
export const TaskListButton = ({
|
|
9
9
|
api
|
|
@@ -38,6 +38,7 @@ export const TaskListButton = ({
|
|
|
38
38
|
size: "small"
|
|
39
39
|
}),
|
|
40
40
|
onClick: onClick,
|
|
41
|
-
ariaKeyshortcuts: "[ ] Space"
|
|
41
|
+
ariaKeyshortcuts: "[ ] Space",
|
|
42
|
+
testId: TOOLBAR_BUTTON_TEST_ID.TASK_LIST
|
|
42
43
|
}));
|
|
43
44
|
};
|
|
@@ -9,6 +9,7 @@ import { BLOCK_QUOTE, CODE_BLOCK, PANEL } from '@atlaskit/editor-plugin-block-ty
|
|
|
9
9
|
import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
|
|
10
10
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
11
11
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
12
|
+
import { getToolbarActionExperiencesPlugin } from './pm-plugins/experiences/toolbar-action-experiences';
|
|
12
13
|
import { toggleInsertBlockPmKey, toggleInsertBlockPmPlugin } from './pm-plugins/toggleInsertBlock';
|
|
13
14
|
import { getToolbarComponents } from './ui/toolbar-components';
|
|
14
15
|
// Ignored via go/ees005
|
|
@@ -98,6 +99,7 @@ export var insertBlockPlugin = function insertBlockPlugin(_ref) {
|
|
|
98
99
|
options = _ref$config === void 0 ? {} : _ref$config,
|
|
99
100
|
api = _ref.api;
|
|
100
101
|
var isToolbarAIFCEnabled = Boolean(api === null || api === void 0 ? void 0 : api.toolbar);
|
|
102
|
+
var refs = {};
|
|
101
103
|
var primaryToolbarComponent = function primaryToolbarComponent(_ref2) {
|
|
102
104
|
var editorView = _ref2.editorView,
|
|
103
105
|
editorActions = _ref2.editorActions,
|
|
@@ -110,6 +112,7 @@ export var insertBlockPlugin = function insertBlockPlugin(_ref) {
|
|
|
110
112
|
disabled = _ref2.disabled,
|
|
111
113
|
isToolbarReducedSpacing = _ref2.isToolbarReducedSpacing,
|
|
112
114
|
isLastItem = _ref2.isLastItem;
|
|
115
|
+
refs.popupsMountPoint = popupsMountPoint || undefined;
|
|
113
116
|
var renderNode = function renderNode(providers) {
|
|
114
117
|
if (!editorView) {
|
|
115
118
|
return null;
|
|
@@ -216,6 +219,20 @@ export var insertBlockPlugin = function insertBlockPlugin(_ref) {
|
|
|
216
219
|
return toggleInsertBlockPmPlugin();
|
|
217
220
|
}
|
|
218
221
|
});
|
|
222
|
+
if (fg('platform_editor_experience_tracking_toolbar_button')) {
|
|
223
|
+
plugins.push({
|
|
224
|
+
name: 'toolbarActionExperiences',
|
|
225
|
+
plugin: function plugin() {
|
|
226
|
+
return getToolbarActionExperiencesPlugin({
|
|
227
|
+
refs: refs,
|
|
228
|
+
dispatchAnalyticsEvent: function dispatchAnalyticsEvent(payload) {
|
|
229
|
+
var _api$analytics;
|
|
230
|
+
return api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 ? void 0 : _api$analytics.fireAnalyticsEvent(payload);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
219
236
|
return plugins;
|
|
220
237
|
},
|
|
221
238
|
pluginsOptions: {},
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { bind } from 'bind-event-listener';
|
|
2
|
+
import { getDocument } from '@atlaskit/browser-apis';
|
|
3
|
+
import { Experience, EXPERIENCE_ID, ExperienceCheckDomMutation, ExperienceCheckTimeout, getPopupContainerFromEditorView } from '@atlaskit/editor-common/experiences';
|
|
4
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
5
|
+
import { TOOLBAR_BUTTON_TEST_ID } from '@atlaskit/editor-common/toolbar';
|
|
6
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
+
import { ExperienceCheckPopupMutation, getParentDOMAtSelection, handleEditorNodeInsertDomMutation, handleTypeAheadOpenDomMutation, isToolbarButtonClick } from './toolbar-experience-utils';
|
|
8
|
+
var pluginKey = new PluginKey('toolbarActionExperiences');
|
|
9
|
+
var TIMEOUT_DURATION = 1000;
|
|
10
|
+
var PRIMARY_TOOLBAR = 'primaryToolbar';
|
|
11
|
+
var ABORT_REASON = {
|
|
12
|
+
USER_CANCELED: 'userCanceled',
|
|
13
|
+
EDITOR_DESTROYED: 'editorDestroyed'
|
|
14
|
+
};
|
|
15
|
+
export var getToolbarActionExperiencesPlugin = function getToolbarActionExperiencesPlugin(_ref) {
|
|
16
|
+
var refs = _ref.refs,
|
|
17
|
+
dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent;
|
|
18
|
+
var editorView;
|
|
19
|
+
var popupTargetEl;
|
|
20
|
+
var getPopupsTarget = function getPopupsTarget() {
|
|
21
|
+
if (!popupTargetEl) {
|
|
22
|
+
var _editorView;
|
|
23
|
+
popupTargetEl = refs.popupsMountPoint || getPopupContainerFromEditorView((_editorView = editorView) === null || _editorView === void 0 ? void 0 : _editorView.dom);
|
|
24
|
+
}
|
|
25
|
+
return popupTargetEl;
|
|
26
|
+
};
|
|
27
|
+
var getEditorDom = function getEditorDom() {
|
|
28
|
+
var _editorView2;
|
|
29
|
+
if (((_editorView2 = editorView) === null || _editorView2 === void 0 ? void 0 : _editorView2.dom) instanceof HTMLElement) {
|
|
30
|
+
return editorView.dom;
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
};
|
|
34
|
+
var narrowParentObserveConfig = function narrowParentObserveConfig() {
|
|
35
|
+
var _getParentDOMAtSelect;
|
|
36
|
+
return {
|
|
37
|
+
target: (_getParentDOMAtSelect = getParentDOMAtSelection(editorView)) !== null && _getParentDOMAtSelect !== void 0 ? _getParentDOMAtSelect : getEditorDom(),
|
|
38
|
+
options: {
|
|
39
|
+
childList: true
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
var rootObserveConfig = function rootObserveConfig() {
|
|
44
|
+
return {
|
|
45
|
+
target: getEditorDom(),
|
|
46
|
+
options: {
|
|
47
|
+
childList: true
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
var createNodeInsertExperience = function createNodeInsertExperience(action) {
|
|
52
|
+
return new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
|
|
53
|
+
action: action,
|
|
54
|
+
actionSubjectId: PRIMARY_TOOLBAR,
|
|
55
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
56
|
+
checks: [new ExperienceCheckTimeout({
|
|
57
|
+
durationMs: TIMEOUT_DURATION
|
|
58
|
+
}), new ExperienceCheckDomMutation({
|
|
59
|
+
onDomMutation: handleEditorNodeInsertDomMutation,
|
|
60
|
+
observeConfig: narrowParentObserveConfig
|
|
61
|
+
}), new ExperienceCheckDomMutation({
|
|
62
|
+
onDomMutation: handleEditorNodeInsertDomMutation,
|
|
63
|
+
observeConfig: rootObserveConfig
|
|
64
|
+
})]
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
var createPopupExperience = function createPopupExperience(action, popupSelector) {
|
|
68
|
+
return new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
|
|
69
|
+
action: action,
|
|
70
|
+
actionSubjectId: PRIMARY_TOOLBAR,
|
|
71
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
72
|
+
checks: [new ExperienceCheckTimeout({
|
|
73
|
+
durationMs: TIMEOUT_DURATION
|
|
74
|
+
}), new ExperienceCheckPopupMutation(popupSelector, getPopupsTarget, getEditorDom)]
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
var experienceButtonMappings = [{
|
|
78
|
+
experience: createPopupExperience('emoji', '[data-emoji-picker-container]'),
|
|
79
|
+
buttonTestId: TOOLBAR_BUTTON_TEST_ID.EMOJI
|
|
80
|
+
}, {
|
|
81
|
+
experience: createPopupExperience('media', '[id="local-media-upload-button"], [data-testid="media-picker-file-input"]'),
|
|
82
|
+
buttonTestId: TOOLBAR_BUTTON_TEST_ID.MEDIA
|
|
83
|
+
}, {
|
|
84
|
+
experience: new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
|
|
85
|
+
action: 'mention',
|
|
86
|
+
actionSubjectId: PRIMARY_TOOLBAR,
|
|
87
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
88
|
+
checks: [new ExperienceCheckTimeout({
|
|
89
|
+
durationMs: TIMEOUT_DURATION
|
|
90
|
+
}), new ExperienceCheckDomMutation({
|
|
91
|
+
onDomMutation: handleTypeAheadOpenDomMutation,
|
|
92
|
+
observeConfig: narrowParentObserveConfig
|
|
93
|
+
})]
|
|
94
|
+
}),
|
|
95
|
+
buttonTestId: TOOLBAR_BUTTON_TEST_ID.MENTION
|
|
96
|
+
}, {
|
|
97
|
+
experience: createNodeInsertExperience('table'),
|
|
98
|
+
buttonTestId: TOOLBAR_BUTTON_TEST_ID.TABLE
|
|
99
|
+
}, {
|
|
100
|
+
experience: createPopupExperience('tableSelector', '[aria-label*="table size"], [data-testid*="table-selector"]'),
|
|
101
|
+
buttonTestId: TOOLBAR_BUTTON_TEST_ID.TABLE_SELECTOR
|
|
102
|
+
}, {
|
|
103
|
+
experience: createNodeInsertExperience('layout'),
|
|
104
|
+
buttonTestId: TOOLBAR_BUTTON_TEST_ID.LAYOUT
|
|
105
|
+
}, {
|
|
106
|
+
experience: createPopupExperience('image', '[id="local-media-upload-button"], [data-testid="media-picker-file-input"]'),
|
|
107
|
+
buttonTestId: TOOLBAR_BUTTON_TEST_ID.IMAGE
|
|
108
|
+
}, {
|
|
109
|
+
experience: createNodeInsertExperience('action'),
|
|
110
|
+
buttonTestId: TOOLBAR_BUTTON_TEST_ID.TASK_LIST
|
|
111
|
+
}];
|
|
112
|
+
var handleToolbarButtonClick = function handleToolbarButtonClick(target) {
|
|
113
|
+
for (var _i = 0, _experienceButtonMapp = experienceButtonMappings; _i < _experienceButtonMapp.length; _i++) {
|
|
114
|
+
var _experienceButtonMapp2 = _experienceButtonMapp[_i],
|
|
115
|
+
experience = _experienceButtonMapp2.experience,
|
|
116
|
+
buttonTestId = _experienceButtonMapp2.buttonTestId;
|
|
117
|
+
if (isToolbarButtonClick(target, buttonTestId)) {
|
|
118
|
+
experience.start({
|
|
119
|
+
forceRestart: true
|
|
120
|
+
});
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
var abortAllExperiences = function abortAllExperiences(reason) {
|
|
126
|
+
for (var _i2 = 0, _experienceButtonMapp3 = experienceButtonMappings; _i2 < _experienceButtonMapp3.length; _i2++) {
|
|
127
|
+
var experience = _experienceButtonMapp3[_i2].experience;
|
|
128
|
+
experience.abort({
|
|
129
|
+
reason: reason
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
var doc = getDocument();
|
|
134
|
+
if (!doc) {
|
|
135
|
+
return new SafePlugin({
|
|
136
|
+
key: pluginKey
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
var unbindClickListener = bind(doc, {
|
|
140
|
+
type: 'click',
|
|
141
|
+
listener: function listener(event) {
|
|
142
|
+
var target = event.target;
|
|
143
|
+
if (target instanceof HTMLElement) {
|
|
144
|
+
handleToolbarButtonClick(target);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
options: {
|
|
148
|
+
capture: true
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
var unbindKeydownListener = bind(doc, {
|
|
152
|
+
type: 'keydown',
|
|
153
|
+
listener: function listener(event) {
|
|
154
|
+
if (event.key === 'Escape') {
|
|
155
|
+
abortAllExperiences(ABORT_REASON.USER_CANCELED);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
options: {
|
|
159
|
+
capture: true
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
return new SafePlugin({
|
|
163
|
+
key: pluginKey,
|
|
164
|
+
view: function view(_view) {
|
|
165
|
+
editorView = _view;
|
|
166
|
+
return {
|
|
167
|
+
destroy: function destroy() {
|
|
168
|
+
abortAllExperiences(ABORT_REASON.EDITOR_DESTROYED);
|
|
169
|
+
editorView = undefined;
|
|
170
|
+
popupTargetEl = undefined;
|
|
171
|
+
unbindClickListener();
|
|
172
|
+
unbindKeydownListener();
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
};
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
|
+
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
5
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
6
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
7
|
+
import { getDocument } from '@atlaskit/browser-apis';
|
|
8
|
+
import { EXPERIENCE_FAILURE_REASON, popupWithNestedElement } from '@atlaskit/editor-common/experiences';
|
|
9
|
+
/**
|
|
10
|
+
* DOM marker selectors for node types inserted via toolbar actions.
|
|
11
|
+
* Matches outermost wrapper elements set synchronously by ReactNodeView
|
|
12
|
+
* (`{nodeTypeName}View-content-wrap`) or schema `toDOM` attributes.
|
|
13
|
+
*/
|
|
14
|
+
export var NODE_INSERT_MARKERS = {
|
|
15
|
+
TABLE: '.tableView-content-wrap',
|
|
16
|
+
LAYOUT: '.layoutSectionView-content-wrap',
|
|
17
|
+
LAYOUT_COLUMN: '.layoutColumnView-content-wrap',
|
|
18
|
+
TASK_LIST: '[data-node-type="actionList"]',
|
|
19
|
+
TASK_ITEM: '.taskItemView-content-wrap'
|
|
20
|
+
};
|
|
21
|
+
var COMBINED_NODE_INSERT_SELECTOR = [NODE_INSERT_MARKERS.TABLE, NODE_INSERT_MARKERS.LAYOUT, NODE_INSERT_MARKERS.LAYOUT_COLUMN, NODE_INSERT_MARKERS.TASK_LIST, NODE_INSERT_MARKERS.TASK_ITEM].join(', ');
|
|
22
|
+
export var isToolbarButtonClick = function isToolbarButtonClick(target, testId) {
|
|
23
|
+
var button = target.closest("button[data-testid=\"".concat(testId, "\"]"));
|
|
24
|
+
if (!button) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return !button.disabled && button.getAttribute('aria-disabled') !== 'true';
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* ExperienceCheck that observes popup mount point and all its
|
|
32
|
+
* `[data-editor-popup]` children with `{ childList: true }` (no subtree).
|
|
33
|
+
*
|
|
34
|
+
* Detects when a popup containing the given nested element is added to the
|
|
35
|
+
* DOM — either as a new `[data-editor-popup]` direct child, or as content
|
|
36
|
+
* rendered inside an existing `[data-editor-popup]` wrapper.
|
|
37
|
+
*/
|
|
38
|
+
export var TYPEAHEAD_DECORATION_SELECTOR = '[data-type-ahead="typeaheadDecoration"]';
|
|
39
|
+
export var handleTypeAheadOpenDomMutation = function handleTypeAheadOpenDomMutation(_ref) {
|
|
40
|
+
var mutations = _ref.mutations;
|
|
41
|
+
var _iterator = _createForOfIteratorHelper(mutations),
|
|
42
|
+
_step;
|
|
43
|
+
try {
|
|
44
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
45
|
+
var mutation = _step.value;
|
|
46
|
+
if (mutation.type !== 'childList') {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
var _iterator2 = _createForOfIteratorHelper(mutation.addedNodes),
|
|
50
|
+
_step2;
|
|
51
|
+
try {
|
|
52
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
53
|
+
var node = _step2.value;
|
|
54
|
+
if (!(node instanceof HTMLElement)) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (node.matches(TYPEAHEAD_DECORATION_SELECTOR) || node.querySelector(TYPEAHEAD_DECORATION_SELECTOR)) {
|
|
58
|
+
return {
|
|
59
|
+
status: 'success'
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
_iterator2.e(err);
|
|
65
|
+
} finally {
|
|
66
|
+
_iterator2.f();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} catch (err) {
|
|
70
|
+
_iterator.e(err);
|
|
71
|
+
} finally {
|
|
72
|
+
_iterator.f();
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
};
|
|
76
|
+
export var ExperienceCheckPopupMutation = /*#__PURE__*/function () {
|
|
77
|
+
function ExperienceCheckPopupMutation(nestedElementQuery, getTarget, getEditorDom) {
|
|
78
|
+
_classCallCheck(this, ExperienceCheckPopupMutation);
|
|
79
|
+
_defineProperty(this, "observers", []);
|
|
80
|
+
this.nestedElementQuery = nestedElementQuery;
|
|
81
|
+
this.getTarget = getTarget;
|
|
82
|
+
this.getEditorDom = getEditorDom;
|
|
83
|
+
}
|
|
84
|
+
return _createClass(ExperienceCheckPopupMutation, [{
|
|
85
|
+
key: "start",
|
|
86
|
+
value: function start(callback) {
|
|
87
|
+
var _this = this;
|
|
88
|
+
this.stop();
|
|
89
|
+
var target = this.getTarget();
|
|
90
|
+
if (!target) {
|
|
91
|
+
callback({
|
|
92
|
+
status: 'failure',
|
|
93
|
+
reason: EXPERIENCE_FAILURE_REASON.DOM_MUTATION_TARGET_NOT_FOUND
|
|
94
|
+
});
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
var doc = getDocument();
|
|
98
|
+
if (!doc) {
|
|
99
|
+
callback({
|
|
100
|
+
status: 'failure',
|
|
101
|
+
reason: EXPERIENCE_FAILURE_REASON.DOM_MUTATION_TARGET_NOT_FOUND
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
var query = this.nestedElementQuery;
|
|
106
|
+
var onMutation = function onMutation(mutations) {
|
|
107
|
+
var _iterator3 = _createForOfIteratorHelper(mutations),
|
|
108
|
+
_step3;
|
|
109
|
+
try {
|
|
110
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
111
|
+
var mutation = _step3.value;
|
|
112
|
+
if (mutation.type !== 'childList') {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
var _iterator4 = _createForOfIteratorHelper(mutation.addedNodes),
|
|
116
|
+
_step4;
|
|
117
|
+
try {
|
|
118
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
119
|
+
var node = _step4.value;
|
|
120
|
+
if (!(node instanceof HTMLElement)) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (popupWithNestedElement(node, query) || node.matches(query) || !!node.querySelector(query)) {
|
|
124
|
+
_this.stop();
|
|
125
|
+
callback({
|
|
126
|
+
status: 'success'
|
|
127
|
+
});
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
} catch (err) {
|
|
132
|
+
_iterator4.e(err);
|
|
133
|
+
} finally {
|
|
134
|
+
_iterator4.f();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch (err) {
|
|
138
|
+
_iterator3.e(err);
|
|
139
|
+
} finally {
|
|
140
|
+
_iterator3.f();
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
var observe = function observe(el) {
|
|
144
|
+
var observer = new MutationObserver(onMutation);
|
|
145
|
+
observer.observe(el, {
|
|
146
|
+
childList: true
|
|
147
|
+
});
|
|
148
|
+
_this.observers.push(observer);
|
|
149
|
+
};
|
|
150
|
+
observe(target);
|
|
151
|
+
var _iterator5 = _createForOfIteratorHelper(target.querySelectorAll('[data-editor-popup]')),
|
|
152
|
+
_step5;
|
|
153
|
+
try {
|
|
154
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
155
|
+
var wrapper = _step5.value;
|
|
156
|
+
observe(wrapper);
|
|
157
|
+
}
|
|
158
|
+
} catch (err) {
|
|
159
|
+
_iterator5.e(err);
|
|
160
|
+
} finally {
|
|
161
|
+
_iterator5.f();
|
|
162
|
+
}
|
|
163
|
+
var portalContainer = doc.querySelector('.atlaskit-portal-container');
|
|
164
|
+
if (portalContainer instanceof HTMLElement) {
|
|
165
|
+
var observePortal = function observePortal(portal) {
|
|
166
|
+
observe(portal);
|
|
167
|
+
var _iterator6 = _createForOfIteratorHelper(portal.children),
|
|
168
|
+
_step6;
|
|
169
|
+
try {
|
|
170
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
171
|
+
var child = _step6.value;
|
|
172
|
+
if (child instanceof HTMLElement) {
|
|
173
|
+
observe(child);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
} catch (err) {
|
|
177
|
+
_iterator6.e(err);
|
|
178
|
+
} finally {
|
|
179
|
+
_iterator6.f();
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
var containerObserver = new MutationObserver(function (mutations) {
|
|
183
|
+
var _iterator7 = _createForOfIteratorHelper(mutations),
|
|
184
|
+
_step7;
|
|
185
|
+
try {
|
|
186
|
+
for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
|
|
187
|
+
var mutation = _step7.value;
|
|
188
|
+
if (mutation.type !== 'childList') {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
var _iterator8 = _createForOfIteratorHelper(mutation.addedNodes),
|
|
192
|
+
_step8;
|
|
193
|
+
try {
|
|
194
|
+
for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
|
|
195
|
+
var node = _step8.value;
|
|
196
|
+
if (node instanceof HTMLElement) {
|
|
197
|
+
observePortal(node);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
} catch (err) {
|
|
201
|
+
_iterator8.e(err);
|
|
202
|
+
} finally {
|
|
203
|
+
_iterator8.f();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
} catch (err) {
|
|
207
|
+
_iterator7.e(err);
|
|
208
|
+
} finally {
|
|
209
|
+
_iterator7.f();
|
|
210
|
+
}
|
|
211
|
+
onMutation(mutations);
|
|
212
|
+
});
|
|
213
|
+
containerObserver.observe(portalContainer, {
|
|
214
|
+
childList: true
|
|
215
|
+
});
|
|
216
|
+
this.observers.push(containerObserver);
|
|
217
|
+
var _iterator9 = _createForOfIteratorHelper(portalContainer.querySelectorAll('.atlaskit-portal')),
|
|
218
|
+
_step9;
|
|
219
|
+
try {
|
|
220
|
+
for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
|
|
221
|
+
var portal = _step9.value;
|
|
222
|
+
observePortal(portal);
|
|
223
|
+
}
|
|
224
|
+
} catch (err) {
|
|
225
|
+
_iterator9.e(err);
|
|
226
|
+
} finally {
|
|
227
|
+
_iterator9.f();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
var editorDom = this.getEditorDom();
|
|
231
|
+
if (editorDom !== null && editorDom !== void 0 && editorDom.parentElement) {
|
|
232
|
+
observe(editorDom.parentElement);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Two-frame DOM check to handle cases where rendering happens before
|
|
236
|
+
// observers are attached.
|
|
237
|
+
var checkDom = function checkDom() {
|
|
238
|
+
if (doc.querySelector(query)) {
|
|
239
|
+
_this.stop();
|
|
240
|
+
callback({
|
|
241
|
+
status: 'success'
|
|
242
|
+
});
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
requestAnimationFrame(function () {
|
|
246
|
+
if (doc.querySelector(query)) {
|
|
247
|
+
_this.stop();
|
|
248
|
+
callback({
|
|
249
|
+
status: 'success'
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
requestAnimationFrame(checkDom);
|
|
255
|
+
}
|
|
256
|
+
}, {
|
|
257
|
+
key: "stop",
|
|
258
|
+
value: function stop() {
|
|
259
|
+
var _iterator0 = _createForOfIteratorHelper(this.observers),
|
|
260
|
+
_step0;
|
|
261
|
+
try {
|
|
262
|
+
for (_iterator0.s(); !(_step0 = _iterator0.n()).done;) {
|
|
263
|
+
var observer = _step0.value;
|
|
264
|
+
observer.disconnect();
|
|
265
|
+
}
|
|
266
|
+
} catch (err) {
|
|
267
|
+
_iterator0.e(err);
|
|
268
|
+
} finally {
|
|
269
|
+
_iterator0.f();
|
|
270
|
+
}
|
|
271
|
+
this.observers = [];
|
|
272
|
+
}
|
|
273
|
+
}]);
|
|
274
|
+
}();
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Returns the narrow parent DOM element at the current selection, suitable
|
|
278
|
+
* for observing with `{ childList: true }` (no subtree).
|
|
279
|
+
*
|
|
280
|
+
* Uses the resolved position's depth to find the block node at the cursor
|
|
281
|
+
* via `nodeDOM`, then returns its `parentElement` — the container whose
|
|
282
|
+
* direct children change when content is inserted at this position.
|
|
283
|
+
*
|
|
284
|
+
* Falls back to `domAtPos` if `nodeDOM` is unavailable.
|
|
285
|
+
*/
|
|
286
|
+
export var getParentDOMAtSelection = function getParentDOMAtSelection(editorView) {
|
|
287
|
+
if (!editorView) {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
var selection = editorView.state.selection;
|
|
292
|
+
var $from = selection.$from;
|
|
293
|
+
var parentDepth = Math.max(1, $from.depth);
|
|
294
|
+
var parentPos = $from.before(parentDepth);
|
|
295
|
+
var parentDom = editorView.nodeDOM(parentPos);
|
|
296
|
+
if (parentDom instanceof HTMLElement && parentDom.parentElement) {
|
|
297
|
+
return parentDom.parentElement;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Fallback: use domAtPos
|
|
301
|
+
var _editorView$domAtPos = editorView.domAtPos(selection.from),
|
|
302
|
+
node = _editorView$domAtPos.node;
|
|
303
|
+
var element = null;
|
|
304
|
+
if (node instanceof HTMLElement) {
|
|
305
|
+
element = node;
|
|
306
|
+
} else if (node instanceof Text) {
|
|
307
|
+
element = node.parentElement;
|
|
308
|
+
}
|
|
309
|
+
if (!element) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
var proseMirrorRoot = editorView.dom;
|
|
313
|
+
if (!(proseMirrorRoot instanceof HTMLElement)) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
if (element === proseMirrorRoot) {
|
|
317
|
+
return proseMirrorRoot;
|
|
318
|
+
}
|
|
319
|
+
if (element.parentElement && proseMirrorRoot.contains(element.parentElement)) {
|
|
320
|
+
return element.parentElement;
|
|
321
|
+
}
|
|
322
|
+
return proseMirrorRoot;
|
|
323
|
+
} catch (_unused) {
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Checks whether a DOM node matches any known node insert marker,
|
|
330
|
+
* either directly or via a nested element (e.g. breakout mark wrapper).
|
|
331
|
+
*/
|
|
332
|
+
var matchesNodeInsertMarker = function matchesNodeInsertMarker(node) {
|
|
333
|
+
if (!(node instanceof HTMLElement)) {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
return node.matches(COMBINED_NODE_INSERT_SELECTOR) || !!node.querySelector(COMBINED_NODE_INSERT_SELECTOR);
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Evaluates DOM mutations to detect a node insert action.
|
|
341
|
+
*
|
|
342
|
+
* Uses two strategies:
|
|
343
|
+
* 1. Marker-based: checks `addedNodes` against known node insert selectors.
|
|
344
|
+
* 2. Structure-based: detects element add+remove (block-level replacement).
|
|
345
|
+
*/
|
|
346
|
+
export var handleEditorNodeInsertDomMutation = function handleEditorNodeInsertDomMutation(_ref2) {
|
|
347
|
+
var mutations = _ref2.mutations;
|
|
348
|
+
var hasAddedElement = false;
|
|
349
|
+
var hasRemovedElement = false;
|
|
350
|
+
var _iterator1 = _createForOfIteratorHelper(mutations),
|
|
351
|
+
_step1;
|
|
352
|
+
try {
|
|
353
|
+
for (_iterator1.s(); !(_step1 = _iterator1.n()).done;) {
|
|
354
|
+
var mutation = _step1.value;
|
|
355
|
+
if (mutation.type !== 'childList') {
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
var _iterator10 = _createForOfIteratorHelper(mutation.addedNodes),
|
|
359
|
+
_step10;
|
|
360
|
+
try {
|
|
361
|
+
for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
|
|
362
|
+
var node = _step10.value;
|
|
363
|
+
if (matchesNodeInsertMarker(node)) {
|
|
364
|
+
return {
|
|
365
|
+
status: 'success'
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
if (node instanceof HTMLElement) {
|
|
369
|
+
hasAddedElement = true;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
} catch (err) {
|
|
373
|
+
_iterator10.e(err);
|
|
374
|
+
} finally {
|
|
375
|
+
_iterator10.f();
|
|
376
|
+
}
|
|
377
|
+
var _iterator11 = _createForOfIteratorHelper(mutation.removedNodes),
|
|
378
|
+
_step11;
|
|
379
|
+
try {
|
|
380
|
+
for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) {
|
|
381
|
+
var _node = _step11.value;
|
|
382
|
+
if (_node instanceof HTMLElement) {
|
|
383
|
+
hasRemovedElement = true;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
} catch (err) {
|
|
387
|
+
_iterator11.e(err);
|
|
388
|
+
} finally {
|
|
389
|
+
_iterator11.f();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
} catch (err) {
|
|
393
|
+
_iterator1.e(err);
|
|
394
|
+
} finally {
|
|
395
|
+
_iterator1.f();
|
|
396
|
+
}
|
|
397
|
+
if (hasAddedElement && hasRemovedElement) {
|
|
398
|
+
return {
|
|
399
|
+
status: 'success'
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
return undefined;
|
|
403
|
+
};
|
|
@@ -3,6 +3,7 @@ import { useIntl } from 'react-intl-next';
|
|
|
3
3
|
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
4
4
|
import { ToolTipContent, insertEmoji } from '@atlaskit/editor-common/keymaps';
|
|
5
5
|
import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
|
|
6
|
+
import { TOOLBAR_BUTTON_TEST_ID } from '@atlaskit/editor-common/toolbar';
|
|
6
7
|
import { ToolbarButton, ToolbarTooltip, EmojiIcon, useToolbarUI } from '@atlaskit/editor-toolbar';
|
|
7
8
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
8
9
|
import { useEmojiPickerPopup } from './hooks/useEmojiPickerPopup';
|
|
@@ -67,6 +68,7 @@ export var EmojiButton = function EmojiButton(_ref) {
|
|
|
67
68
|
return emojiPickerPopup.toggle();
|
|
68
69
|
},
|
|
69
70
|
isSelected: emojiPickerPopup.isOpen,
|
|
70
|
-
isDisabled: !isTypeAheadAllowed || !emojiProvider
|
|
71
|
+
isDisabled: !isTypeAheadAllowed || !emojiProvider,
|
|
72
|
+
testId: TOOLBAR_BUTTON_TEST_ID.EMOJI
|
|
71
73
|
})));
|
|
72
74
|
};
|