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