@atlaskit/editor-plugin-toolbar 3.2.0 → 3.3.0

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 CHANGED
@@ -1,5 +1,29 @@
1
1
  # @atlaskit/editor-plugin-toolbar
2
2
 
3
+ ## 3.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`d3e3f3fdb9cee`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d3e3f3fdb9cee) -
8
+ Add new selection toolbar type to event, add errorboundary for selection toolbar and try/catch
9
+ blocks with log exceptions to sentry
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
15
+ ## 3.2.1
16
+
17
+ ### Patch Changes
18
+
19
+ - [`14b9e966da4dd`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/14b9e966da4dd) -
20
+ [ux] ED-29517 Toolbar and offline banner is overlapping
21
+ - [`ef001bf65d48f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/ef001bf65d48f) -
22
+ Remove usage of `platform_editor_toolbar_aifc` inside editor packages - instead rely on checking
23
+ for new toolbar plugin option, make `enableNewToolbarExperience` mandatory for consumers to opt in
24
+ to new toolbar experience
25
+ - Updated dependencies
26
+
3
27
  ## 3.2.0
4
28
 
5
29
  ### Minor Changes
@@ -44,6 +44,9 @@
44
44
  {
45
45
  "path": "../../editor-toolbar-model/afm-cc/tsconfig.json"
46
46
  },
47
+ {
48
+ "path": "../../../platform/feature-flags/afm-cc/tsconfig.json"
49
+ },
47
50
  {
48
51
  "path": "../../../platform/feature-flags-react/afm-cc/tsconfig.json"
49
52
  },
@@ -44,6 +44,9 @@
44
44
  {
45
45
  "path": "../../editor-toolbar-model/afm-dev-agents/tsconfig.json"
46
46
  },
47
+ {
48
+ "path": "../../../platform/feature-flags/afm-dev-agents/tsconfig.json"
49
+ },
47
50
  {
48
51
  "path": "../../../platform/feature-flags-react/afm-dev-agents/tsconfig.json"
49
52
  },
@@ -44,6 +44,9 @@
44
44
  {
45
45
  "path": "../../editor-toolbar-model/afm-jira/tsconfig.json"
46
46
  },
47
+ {
48
+ "path": "../../../platform/feature-flags/afm-jira/tsconfig.json"
49
+ },
47
50
  {
48
51
  "path": "../../../platform/feature-flags-react/afm-jira/tsconfig.json"
49
52
  },
@@ -44,6 +44,9 @@
44
44
  {
45
45
  "path": "../../editor-toolbar-model/afm-passionfruit/tsconfig.json"
46
46
  },
47
+ {
48
+ "path": "../../../platform/feature-flags/afm-passionfruit/tsconfig.json"
49
+ },
47
50
  {
48
51
  "path": "../../../platform/feature-flags-react/afm-passionfruit/tsconfig.json"
49
52
  },
@@ -44,6 +44,9 @@
44
44
  {
45
45
  "path": "../../editor-toolbar-model/afm-post-office/tsconfig.json"
46
46
  },
47
+ {
48
+ "path": "../../../platform/feature-flags/afm-post-office/tsconfig.json"
49
+ },
47
50
  {
48
51
  "path": "../../../platform/feature-flags-react/afm-post-office/tsconfig.json"
49
52
  },
@@ -44,6 +44,9 @@
44
44
  {
45
45
  "path": "../../editor-toolbar-model/afm-rovo-extension/tsconfig.json"
46
46
  },
47
+ {
48
+ "path": "../../../platform/feature-flags/afm-rovo-extension/tsconfig.json"
49
+ },
47
50
  {
48
51
  "path": "../../../platform/feature-flags-react/afm-rovo-extension/tsconfig.json"
49
52
  },
@@ -44,6 +44,9 @@
44
44
  {
45
45
  "path": "../../editor-toolbar-model/afm-townsquare/tsconfig.json"
46
46
  },
47
+ {
48
+ "path": "../../../platform/feature-flags/afm-townsquare/tsconfig.json"
49
+ },
47
50
  {
48
51
  "path": "../../../platform/feature-flags-react/afm-townsquare/tsconfig.json"
49
52
  },
@@ -12,6 +12,7 @@ var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
12
12
  var _state = require("@atlaskit/editor-prosemirror/state");
13
13
  var _utils = require("@atlaskit/editor-prosemirror/utils");
14
14
  var _editorToolbarModel = require("@atlaskit/editor-toolbar-model");
15
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
16
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
16
17
  var _pluginKey = require("./pm-plugins/plugin-key");
17
18
  var _consts = require("./ui/consts");
@@ -70,8 +71,7 @@ var toolbarPlugin = exports.toolbarPlugin = function toolbarPlugin(_ref) {
70
71
  _ref$config = _ref.config,
71
72
  config = _ref$config === void 0 ? {
72
73
  disableSelectionToolbar: false,
73
- disableSelectionToolbarWhenPinned: false,
74
- enableNewToolbarExperience: true
74
+ disableSelectionToolbarWhenPinned: false
75
75
  } : _ref$config;
76
76
  var disableSelectionToolbar = config.disableSelectionToolbar,
77
77
  disableSelectionToolbarWhenPinned = config.disableSelectionToolbarWhenPinned;
@@ -185,6 +185,14 @@ var toolbarPlugin = exports.toolbarPlugin = function toolbarPlugin(_ref) {
185
185
  if (!editorView) {
186
186
  return null;
187
187
  }
188
+ if ((0, _platformFeatureFlags.fg)('platform_editor_toolbar_aifc_patch_7')) {
189
+ return /*#__PURE__*/_react.default.createElement(_SelectionToolbar.SelectionToolbarWithErrorBoundary, {
190
+ api: api,
191
+ editorView: editorView,
192
+ mountPoint: popupsMountPoint,
193
+ disableSelectionToolbarWhenPinned: disableSelectionToolbarWhenPinned !== null && disableSelectionToolbarWhenPinned !== void 0 ? disableSelectionToolbarWhenPinned : false
194
+ });
195
+ }
188
196
  return /*#__PURE__*/_react.default.createElement(_SelectionToolbar.SelectionToolbar, {
189
197
  api: api,
190
198
  editorView: editorView,
@@ -4,26 +4,28 @@ var _typeof = require("@babel/runtime/helpers/typeof");
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.SelectionToolbar = void 0;
7
+ exports.SelectionToolbarWithErrorBoundary = exports.SelectionToolbar = void 0;
8
8
  var _react = _interopRequireWildcard(require("react"));
9
9
  var _reactIntlNext = require("react-intl-next");
10
- var _browserApis = require("@atlaskit/browser-apis");
10
+ var _analytics = require("@atlaskit/editor-common/analytics");
11
11
  var _coreUtils = require("@atlaskit/editor-common/core-utils");
12
+ var _errorBoundary = require("@atlaskit/editor-common/error-boundary");
12
13
  var _hooks = require("@atlaskit/editor-common/hooks");
13
- var _messages = require("@atlaskit/editor-common/messages");
14
+ var _monitoring = require("@atlaskit/editor-common/monitoring");
14
15
  var _toolbar = require("@atlaskit/editor-common/toolbar");
15
16
  var _ui = require("@atlaskit/editor-common/ui");
16
17
  var _useSharedPluginStateSelector = require("@atlaskit/editor-common/use-shared-plugin-state-selector");
17
18
  var _utils = require("@atlaskit/editor-common/utils");
18
19
  var _state = require("@atlaskit/editor-prosemirror/state");
19
- var _utils2 = require("@atlaskit/editor-prosemirror/utils");
20
20
  var _editorToolbar = require("@atlaskit/editor-toolbar");
21
21
  var _editorToolbarModel = require("@atlaskit/editor-toolbar-model");
22
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
22
23
  var _platformFeatureFlagsReact = require("@atlaskit/platform-feature-flags-react");
23
24
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
24
25
  var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
25
26
  var _consts = require("../consts");
26
- var _toolbar2 = require("../utils/toolbar");
27
+ var _keyboardConfig = require("./keyboard-config");
28
+ var _utils2 = require("./utils");
27
29
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
28
30
  var isToolbarComponent = function isToolbarComponent(component) {
29
31
  return component.type === 'toolbar' && component.key === 'inline-text-toolbar';
@@ -67,6 +69,42 @@ var usePluginState = (0, _platformFeatureFlagsReact.conditionalHooksFactory)(fun
67
69
  selectedNode: selectedNode
68
70
  };
69
71
  });
72
+ var useOnPositionCalculated = (0, _platformFeatureFlagsReact.conditionalHooksFactory)(function () {
73
+ return (0, _platformFeatureFlags.fg)('platform_editor_toolbar_aifc_patch_7');
74
+ }, function (editorView) {
75
+ var onPositionCalculated = (0, _react.useCallback)(function (position) {
76
+ try {
77
+ var toolbarTitle = _consts.SELECTION_TOOLBAR_LABEL;
78
+
79
+ // Show special position on cell selection only when editor controls experiment is enabled
80
+ var isEditorControlsEnabled = (0, _expValEquals.expValEquals)('platform_editor_controls', 'cohort', 'variant1');
81
+ var isCellSelection = ('$anchorCell' in editorView.state.selection);
82
+ if (isCellSelection && isEditorControlsEnabled) {
83
+ return (0, _utils.calculateToolbarPositionOnCellSelection)(toolbarTitle)(editorView, position);
84
+ }
85
+ return (0, _utils.calculateToolbarPositionTrackHead)(toolbarTitle)(editorView, position);
86
+ } catch (error) {
87
+ (0, _monitoring.logException)(error, {
88
+ location: 'editor-plugin-toolbar/selectionToolbar'
89
+ });
90
+ return position;
91
+ }
92
+ }, [editorView]);
93
+ return onPositionCalculated;
94
+ }, function (editorView) {
95
+ var onPositionCalculated = (0, _react.useCallback)(function (position) {
96
+ var toolbarTitle = _consts.SELECTION_TOOLBAR_LABEL;
97
+
98
+ // Show special position on cell selection only when editor controls experiment is enabled
99
+ var isEditorControlsEnabled = (0, _expValEquals.expValEquals)('platform_editor_controls', 'cohort', 'variant1');
100
+ var isCellSelection = ('$anchorCell' in editorView.state.selection);
101
+ if (isCellSelection && isEditorControlsEnabled) {
102
+ return (0, _utils.calculateToolbarPositionOnCellSelection)(toolbarTitle)(editorView, position);
103
+ }
104
+ return (0, _utils.calculateToolbarPositionTrackHead)(toolbarTitle)(editorView, position);
105
+ }, [editorView]);
106
+ return onPositionCalculated;
107
+ });
70
108
  var SelectionToolbar = exports.SelectionToolbar = function SelectionToolbar(_ref) {
71
109
  var _api$toolbar;
72
110
  var api = _ref.api,
@@ -86,7 +124,7 @@ var SelectionToolbar = exports.SelectionToolbar = function SelectionToolbar(_ref
86
124
  return isToolbarComponent(component);
87
125
  });
88
126
  var keyboardNavigation = (0, _react.useMemo)(function () {
89
- return getKeyboardNavigationConfig(editorView, intl, api);
127
+ return (0, _keyboardConfig.getKeyboardNavigationConfig)(editorView, intl, api);
90
128
  }, [editorView, intl, api]);
91
129
  var _useToolbarUI = (0, _editorToolbar.useToolbarUI)(),
92
130
  isDisabled = _useToolbarUI.isDisabled;
@@ -95,17 +133,7 @@ var SelectionToolbar = exports.SelectionToolbar = function SelectionToolbar(_ref
95
133
  var isTextSelection = !editorView.state.selection.empty && editorView.state.selection instanceof _state.TextSelection;
96
134
  var isAllSelection = !editorView.state.selection.empty && editorView.state.selection instanceof _state.AllSelection;
97
135
  var isCellSelection = !editorView.state.selection.empty && '$anchorCell' in editorView.state.selection;
98
- var onPositionCalculated = (0, _react.useCallback)(function (position) {
99
- var toolbarTitle = _consts.SELECTION_TOOLBAR_LABEL;
100
-
101
- // Show special position on cell selection only when editor controls experiment is enabled
102
- var isEditorControlsEnabled = (0, _expValEquals.expValEquals)('platform_editor_controls', 'cohort', 'variant1');
103
- var isCellSelection = ('$anchorCell' in editorView.state.selection);
104
- if (isCellSelection && isEditorControlsEnabled) {
105
- return (0, _utils.calculateToolbarPositionOnCellSelection)(toolbarTitle)(editorView, position);
106
- }
107
- return (0, _utils.calculateToolbarPositionTrackHead)(toolbarTitle)(editorView, position);
108
- }, [editorView]);
136
+ var onPositionCalculated = useOnPositionCalculated(editorView);
109
137
  if ((0, _expValEquals.expValEquals)('platform_editor_toolbar_aifc_template_editor', 'isEnabled', true) && editorToolbarDockingPreference === 'top' && disableSelectionToolbarWhenPinned || !components || !toolbar) {
110
138
  return null;
111
139
  }
@@ -114,13 +142,14 @@ var SelectionToolbar = exports.SelectionToolbar = function SelectionToolbar(_ref
114
142
  }
115
143
  return /*#__PURE__*/_react.default.createElement(_ui.Popup, {
116
144
  offset: [0, 10],
117
- target: getDomRefFromSelection(editorView),
145
+ target: (0, _utils2.getDomRefFromSelection)(editorView),
118
146
  onPositionCalculated: onPositionCalculated,
119
147
  mountTo: mountPoint
120
148
  }, /*#__PURE__*/_react.default.createElement(_toolbar.EditorToolbarProvider, {
121
149
  editorView: editorView,
122
150
  editorToolbarDockingPreference: editorToolbarDockingPreference,
123
- editorViewMode: (0, _expValEquals.expValEquals)('platform_editor_toolbar_aifc_patch_4', 'isEnabled', true) ? editorViewMode !== null && editorViewMode !== void 0 ? editorViewMode : 'edit' : editorViewMode
151
+ editorViewMode: (0, _expValEquals.expValEquals)('platform_editor_toolbar_aifc_patch_4', 'isEnabled', true) ? editorViewMode !== null && editorViewMode !== void 0 ? editorViewMode : 'edit' : editorViewMode,
152
+ isOffline: isOffline
124
153
  }, /*#__PURE__*/_react.default.createElement(_toolbar.EditorToolbarUIProvider, {
125
154
  api: api,
126
155
  isDisabled: patch6Enabled ? isDisabled : isOffline
@@ -141,78 +170,21 @@ var SelectionToolbar = exports.SelectionToolbar = function SelectionToolbar(_ref
141
170
  }
142
171
  }))));
143
172
  };
144
- var getDomRefFromSelection = function getDomRefFromSelection(view
145
- // dispatchAnalyticsEvent?: DispatchAnalyticsEvent,
146
- ) {
147
- try {
148
- // Ignored via go/ees005
149
- // eslint-disable-next-line @atlaskit/editor/no-as-casting
150
- return (0, _utils2.findDomRefAtPos)(view.state.selection.from, view.domAtPos.bind(view));
151
- // Ignored via go/ees005
152
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
153
- } catch (error) {
154
- // // eslint-disable-next-line no-console
155
- // console.warn(error);
156
- // if (dispatchAnalyticsEvent) {
157
- // const payload: AnalyticsEventPayload = {
158
- // action: ACTION.ERRORED,
159
- // actionSubject: ACTION_SUBJECT.CONTENT_COMPONENT,
160
- // eventType: EVENT_TYPE.OPERATIONAL,
161
- // attributes: {
162
- // component: CONTENT_COMPONENT.FLOATING_TOOLBAR,
163
- // selection: view.state.selection.toJSON(),
164
- // position: view.state.selection.from,
165
- // docSize: view.state.doc.nodeSize,
166
- // error: error.toString(),
167
- // // @ts-expect-error - Object literal may only specify known properties, 'errorStack' does not exist in type
168
- // // This error was introduced after upgrading to TypeScript 5
169
- // errorStack: error.stack || undefined,
170
- // },
171
- // };
172
- // dispatchAnalyticsEvent(payload);
173
- // }
174
- }
175
- };
176
- var getKeyboardNavigationConfig = function getKeyboardNavigationConfig(editorView, intl, api) {
177
- if (!(editorView.dom instanceof HTMLElement)) {
178
- return;
179
- }
180
- var toolbarSelector = "[data-testid='editor-floating-toolbar']";
181
- return {
182
- childComponentSelector: toolbarSelector,
183
- dom: editorView.dom,
184
- isShortcutToFocusToolbar: _toolbar2.isShortcutToFocusToolbar,
185
- handleFocus: function handleFocus(event) {
186
- var _getDocument, _filteredFocusableEle, _filteredFocusableEle2, _filteredFocusableEle3;
187
- var toolbar = (_getDocument = (0, _browserApis.getDocument)()) === null || _getDocument === void 0 ? void 0 : _getDocument.querySelector(toolbarSelector);
188
- if (!(toolbar instanceof HTMLElement)) {
189
- return;
190
- }
191
- var filteredFocusableElements = (0, _toolbar2.getFocusableElements)(toolbar);
192
- (_filteredFocusableEle = filteredFocusableElements[0]) === null || _filteredFocusableEle === void 0 || _filteredFocusableEle.focus();
193
-
194
- // the button element removes the focus ring so this class adds it back
195
- if (((_filteredFocusableEle2 = filteredFocusableElements[0]) === null || _filteredFocusableEle2 === void 0 ? void 0 : _filteredFocusableEle2.tagName) === 'BUTTON') {
196
- filteredFocusableElements[0].classList.add('first-floating-toolbar-button');
197
- }
198
- (_filteredFocusableEle3 = filteredFocusableElements[0]) === null || _filteredFocusableEle3 === void 0 || _filteredFocusableEle3.scrollIntoView({
199
- behavior: 'smooth',
200
- block: 'center',
201
- inline: 'nearest'
202
- });
203
- event.preventDefault();
204
- event.stopPropagation();
205
- },
206
- handleEscape: function handleEscape(event) {
207
- var isDropdownOpen = !!document.querySelector('[data-toolbar-component="menu-section"]');
208
- if (isDropdownOpen) {
209
- return;
210
- }
211
- api === null || api === void 0 || api.core.actions.focus();
212
- event.preventDefault();
213
- event.stopPropagation();
214
- },
215
- ariaControls: _ui.EDIT_AREA_ID,
216
- ariaLabel: intl.formatMessage(_messages.fullPageMessages.toolbarLabel)
217
- };
173
+ var SelectionToolbarWithErrorBoundary = exports.SelectionToolbarWithErrorBoundary = function SelectionToolbarWithErrorBoundary(_ref2) {
174
+ var _api$analytics2;
175
+ var api = _ref2.api,
176
+ editorView = _ref2.editorView,
177
+ mountPoint = _ref2.mountPoint,
178
+ disableSelectionToolbarWhenPinned = _ref2.disableSelectionToolbarWhenPinned;
179
+ return /*#__PURE__*/_react.default.createElement(_errorBoundary.ErrorBoundary, {
180
+ component: _analytics.ACTION_SUBJECT.TOOLBAR,
181
+ componentId: _analytics.ACTION_SUBJECT_ID.SELECTION_TOOLBAR,
182
+ dispatchAnalyticsEvent: api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent,
183
+ fallbackComponent: null
184
+ }, /*#__PURE__*/_react.default.createElement(SelectionToolbar, {
185
+ api: api,
186
+ editorView: editorView,
187
+ mountPoint: mountPoint,
188
+ disableSelectionToolbarWhenPinned: disableSelectionToolbarWhenPinned
189
+ }));
218
190
  };
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getKeyboardNavigationConfig = void 0;
7
+ var _browserApis = require("@atlaskit/browser-apis");
8
+ var _messages = require("@atlaskit/editor-common/messages");
9
+ var _monitoring = require("@atlaskit/editor-common/monitoring");
10
+ var _ui = require("@atlaskit/editor-common/ui");
11
+ var _toolbar = require("../utils/toolbar");
12
+ var getKeyboardNavigationConfig = exports.getKeyboardNavigationConfig = function getKeyboardNavigationConfig(editorView, intl, api) {
13
+ if (!(editorView.dom instanceof HTMLElement)) {
14
+ return;
15
+ }
16
+ var toolbarSelector = "[data-testid='editor-floating-toolbar']";
17
+ return {
18
+ childComponentSelector: toolbarSelector,
19
+ dom: editorView.dom,
20
+ isShortcutToFocusToolbar: _toolbar.isShortcutToFocusToolbar,
21
+ handleFocus: function handleFocus(event) {
22
+ try {
23
+ var _getDocument, _filteredFocusableEle, _filteredFocusableEle2, _filteredFocusableEle3;
24
+ var toolbar = (_getDocument = (0, _browserApis.getDocument)()) === null || _getDocument === void 0 ? void 0 : _getDocument.querySelector(toolbarSelector);
25
+ if (!(toolbar instanceof HTMLElement)) {
26
+ return;
27
+ }
28
+ var filteredFocusableElements = (0, _toolbar.getFocusableElements)(toolbar);
29
+ (_filteredFocusableEle = filteredFocusableElements[0]) === null || _filteredFocusableEle === void 0 || _filteredFocusableEle.focus();
30
+
31
+ // the button element removes the focus ring so this class adds it back
32
+ if (((_filteredFocusableEle2 = filteredFocusableElements[0]) === null || _filteredFocusableEle2 === void 0 ? void 0 : _filteredFocusableEle2.tagName) === 'BUTTON') {
33
+ filteredFocusableElements[0].classList.add('first-floating-toolbar-button');
34
+ }
35
+ (_filteredFocusableEle3 = filteredFocusableElements[0]) === null || _filteredFocusableEle3 === void 0 || _filteredFocusableEle3.scrollIntoView({
36
+ behavior: 'smooth',
37
+ block: 'center',
38
+ inline: 'nearest'
39
+ });
40
+ event.preventDefault();
41
+ event.stopPropagation();
42
+ } catch (error) {
43
+ if (error instanceof Error) {
44
+ (0, _monitoring.logException)(error, {
45
+ location: 'editor-plugin-toolbar/selectionToolbar'
46
+ });
47
+ }
48
+ }
49
+ },
50
+ handleEscape: function handleEscape(event) {
51
+ try {
52
+ var isDropdownOpen = !!document.querySelector('[data-toolbar-component="menu-section"]');
53
+ if (isDropdownOpen) {
54
+ return;
55
+ }
56
+ api === null || api === void 0 || api.core.actions.focus();
57
+ event.preventDefault();
58
+ event.stopPropagation();
59
+ } catch (error) {
60
+ if (error instanceof Error) {
61
+ (0, _monitoring.logException)(error, {
62
+ location: 'editor-plugin-toolbar/selectionToolbar'
63
+ });
64
+ }
65
+ }
66
+ },
67
+ ariaControls: _ui.EDIT_AREA_ID,
68
+ ariaLabel: intl.formatMessage(_messages.fullPageMessages.toolbarLabel)
69
+ };
70
+ };
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getDomRefFromSelection = void 0;
7
+ var _analytics = require("@atlaskit/editor-common/analytics");
8
+ var _monitoring = require("@atlaskit/editor-common/monitoring");
9
+ var _utils = require("@atlaskit/editor-prosemirror/utils");
10
+ var getDomRefFromSelection = exports.getDomRefFromSelection = function getDomRefFromSelection(view, dispatchAnalyticsEvent) {
11
+ try {
12
+ var domRef = (0, _utils.findDomRefAtPos)(view.state.selection.from, view.domAtPos.bind(view));
13
+ if (domRef instanceof HTMLElement) {
14
+ return domRef;
15
+ }
16
+ throw new Error('Invalid DOM reference');
17
+ } catch (error) {
18
+ if (dispatchAnalyticsEvent) {
19
+ var payload = {
20
+ action: _analytics.ACTION.ERRORED,
21
+ actionSubject: _analytics.ACTION_SUBJECT.CONTENT_COMPONENT,
22
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL,
23
+ attributes: {
24
+ component: _analytics.CONTENT_COMPONENT.SELECTION_TOOLBAR,
25
+ selection: view.state.selection.toJSON(),
26
+ position: view.state.selection.from,
27
+ docSize: view.state.doc.nodeSize,
28
+ error: error instanceof Error ? error.toString() : String(error),
29
+ // @ts-expect-error - Object literal may only specify known properties, 'errorStack' does not exist in type
30
+ // This error was introduced after upgrading to TypeScript 5
31
+ errorStack: error instanceof Error ? error.stack : undefined
32
+ }
33
+ };
34
+ dispatchAnalyticsEvent(payload);
35
+ }
36
+ if (error instanceof Error) {
37
+ (0, _monitoring.logException)(error, {
38
+ location: 'editor-plugin-toolbar/selectionToolbar'
39
+ });
40
+ }
41
+ }
42
+ };
@@ -4,10 +4,11 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
4
4
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
5
5
  import { findSelectedNodeOfType, findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
6
6
  import { createComponentRegistry } from '@atlaskit/editor-toolbar-model';
7
+ import { fg } from '@atlaskit/platform-feature-flags';
7
8
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
9
  import { editorToolbarPluginKey } from './pm-plugins/plugin-key';
9
10
  import { DEFAULT_POPUP_SELECTORS } from './ui/consts';
10
- import { SelectionToolbar } from './ui/SelectionToolbar';
11
+ import { SelectionToolbar, SelectionToolbarWithErrorBoundary } from './ui/SelectionToolbar';
11
12
  import { getToolbarComponents } from './ui/toolbar-components';
12
13
  import { isEventInContainer } from './ui/utils/toolbar';
13
14
  function getSelectedNode(editorState) {
@@ -55,8 +56,7 @@ export const toolbarPlugin = ({
55
56
  api,
56
57
  config = {
57
58
  disableSelectionToolbar: false,
58
- disableSelectionToolbarWhenPinned: false,
59
- enableNewToolbarExperience: true
59
+ disableSelectionToolbarWhenPinned: false
60
60
  }
61
61
  }) => {
62
62
  const {
@@ -178,6 +178,14 @@ export const toolbarPlugin = ({
178
178
  if (!editorView) {
179
179
  return null;
180
180
  }
181
+ if (fg('platform_editor_toolbar_aifc_patch_7')) {
182
+ return /*#__PURE__*/React.createElement(SelectionToolbarWithErrorBoundary, {
183
+ api: api,
184
+ editorView: editorView,
185
+ mountPoint: popupsMountPoint,
186
+ disableSelectionToolbarWhenPinned: disableSelectionToolbarWhenPinned !== null && disableSelectionToolbarWhenPinned !== void 0 ? disableSelectionToolbarWhenPinned : false
187
+ });
188
+ }
181
189
  return /*#__PURE__*/React.createElement(SelectionToolbar, {
182
190
  api: api,
183
191
  editorView: editorView,
@@ -1,22 +1,24 @@
1
1
  import React, { useCallback, useMemo } from 'react';
2
2
  import { useIntl } from 'react-intl-next';
3
- import { getDocument } from '@atlaskit/browser-apis';
3
+ import { ACTION_SUBJECT, ACTION_SUBJECT_ID } from '@atlaskit/editor-common/analytics';
4
4
  import { isSSR } from '@atlaskit/editor-common/core-utils';
5
+ import { ErrorBoundary } from '@atlaskit/editor-common/error-boundary';
5
6
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
6
- import { fullPageMessages } from '@atlaskit/editor-common/messages';
7
+ import { logException } from '@atlaskit/editor-common/monitoring';
7
8
  import { EditorToolbarProvider, EditorToolbarUIProvider } from '@atlaskit/editor-common/toolbar';
8
- import { Popup, EDIT_AREA_ID } from '@atlaskit/editor-common/ui';
9
+ import { Popup } from '@atlaskit/editor-common/ui';
9
10
  import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
10
11
  import { calculateToolbarPositionTrackHead, calculateToolbarPositionOnCellSelection } from '@atlaskit/editor-common/utils';
11
12
  import { AllSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
12
- import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
13
13
  import { ToolbarSection, ToolbarButtonGroup, ToolbarDropdownItemSection, useToolbarUI } from '@atlaskit/editor-toolbar';
14
14
  import { ToolbarModelRenderer } from '@atlaskit/editor-toolbar-model';
15
+ import { fg } from '@atlaskit/platform-feature-flags';
15
16
  import { conditionalHooksFactory } from '@atlaskit/platform-feature-flags-react';
16
17
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
17
18
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
18
19
  import { SELECTION_TOOLBAR_LABEL } from '../consts';
19
- import { getFocusableElements, isShortcutToFocusToolbar } from '../utils/toolbar';
20
+ import { getKeyboardNavigationConfig } from './keyboard-config';
21
+ import { getDomRefFromSelection } from './utils';
20
22
  const isToolbarComponent = component => {
21
23
  return component.type === 'toolbar' && component.key === 'inline-text-toolbar';
22
24
  };
@@ -58,6 +60,40 @@ const usePluginState = conditionalHooksFactory(() => expValEquals('platform_edit
58
60
  selectedNode
59
61
  };
60
62
  });
63
+ const useOnPositionCalculated = conditionalHooksFactory(() => fg('platform_editor_toolbar_aifc_patch_7'), editorView => {
64
+ const onPositionCalculated = useCallback(position => {
65
+ try {
66
+ const toolbarTitle = SELECTION_TOOLBAR_LABEL;
67
+
68
+ // Show special position on cell selection only when editor controls experiment is enabled
69
+ const isEditorControlsEnabled = expValEquals('platform_editor_controls', 'cohort', 'variant1');
70
+ const isCellSelection = ('$anchorCell' in editorView.state.selection);
71
+ if (isCellSelection && isEditorControlsEnabled) {
72
+ return calculateToolbarPositionOnCellSelection(toolbarTitle)(editorView, position);
73
+ }
74
+ return calculateToolbarPositionTrackHead(toolbarTitle)(editorView, position);
75
+ } catch (error) {
76
+ logException(error, {
77
+ location: 'editor-plugin-toolbar/selectionToolbar'
78
+ });
79
+ return position;
80
+ }
81
+ }, [editorView]);
82
+ return onPositionCalculated;
83
+ }, editorView => {
84
+ const onPositionCalculated = useCallback(position => {
85
+ const toolbarTitle = SELECTION_TOOLBAR_LABEL;
86
+
87
+ // Show special position on cell selection only when editor controls experiment is enabled
88
+ const isEditorControlsEnabled = expValEquals('platform_editor_controls', 'cohort', 'variant1');
89
+ const isCellSelection = ('$anchorCell' in editorView.state.selection);
90
+ if (isCellSelection && isEditorControlsEnabled) {
91
+ return calculateToolbarPositionOnCellSelection(toolbarTitle)(editorView, position);
92
+ }
93
+ return calculateToolbarPositionTrackHead(toolbarTitle)(editorView, position);
94
+ }, [editorView]);
95
+ return onPositionCalculated;
96
+ });
61
97
  export const SelectionToolbar = ({
62
98
  api,
63
99
  editorView,
@@ -88,17 +124,7 @@ export const SelectionToolbar = ({
88
124
  const isTextSelection = !editorView.state.selection.empty && editorView.state.selection instanceof TextSelection;
89
125
  const isAllSelection = !editorView.state.selection.empty && editorView.state.selection instanceof AllSelection;
90
126
  const isCellSelection = !editorView.state.selection.empty && '$anchorCell' in editorView.state.selection;
91
- const onPositionCalculated = useCallback(position => {
92
- const toolbarTitle = SELECTION_TOOLBAR_LABEL;
93
-
94
- // Show special position on cell selection only when editor controls experiment is enabled
95
- const isEditorControlsEnabled = expValEquals('platform_editor_controls', 'cohort', 'variant1');
96
- const isCellSelection = ('$anchorCell' in editorView.state.selection);
97
- if (isCellSelection && isEditorControlsEnabled) {
98
- return calculateToolbarPositionOnCellSelection(toolbarTitle)(editorView, position);
99
- }
100
- return calculateToolbarPositionTrackHead(toolbarTitle)(editorView, position);
101
- }, [editorView]);
127
+ const onPositionCalculated = useOnPositionCalculated(editorView);
102
128
  if (expValEquals('platform_editor_toolbar_aifc_template_editor', 'isEnabled', true) && editorToolbarDockingPreference === 'top' && disableSelectionToolbarWhenPinned || !components || !toolbar) {
103
129
  return null;
104
130
  }
@@ -113,7 +139,8 @@ export const SelectionToolbar = ({
113
139
  }, /*#__PURE__*/React.createElement(EditorToolbarProvider, {
114
140
  editorView: editorView,
115
141
  editorToolbarDockingPreference: editorToolbarDockingPreference,
116
- editorViewMode: expValEquals('platform_editor_toolbar_aifc_patch_4', 'isEnabled', true) ? editorViewMode !== null && editorViewMode !== void 0 ? editorViewMode : 'edit' : editorViewMode
142
+ editorViewMode: expValEquals('platform_editor_toolbar_aifc_patch_4', 'isEnabled', true) ? editorViewMode !== null && editorViewMode !== void 0 ? editorViewMode : 'edit' : editorViewMode,
143
+ isOffline: isOffline
117
144
  }, /*#__PURE__*/React.createElement(EditorToolbarUIProvider, {
118
145
  api: api,
119
146
  isDisabled: patch6Enabled ? isDisabled : isOffline
@@ -134,78 +161,22 @@ export const SelectionToolbar = ({
134
161
  }
135
162
  }))));
136
163
  };
137
- const getDomRefFromSelection = (view
138
- // dispatchAnalyticsEvent?: DispatchAnalyticsEvent,
139
- ) => {
140
- try {
141
- // Ignored via go/ees005
142
- // eslint-disable-next-line @atlaskit/editor/no-as-casting
143
- return findDomRefAtPos(view.state.selection.from, view.domAtPos.bind(view));
144
- // Ignored via go/ees005
145
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
146
- } catch (error) {
147
- // // eslint-disable-next-line no-console
148
- // console.warn(error);
149
- // if (dispatchAnalyticsEvent) {
150
- // const payload: AnalyticsEventPayload = {
151
- // action: ACTION.ERRORED,
152
- // actionSubject: ACTION_SUBJECT.CONTENT_COMPONENT,
153
- // eventType: EVENT_TYPE.OPERATIONAL,
154
- // attributes: {
155
- // component: CONTENT_COMPONENT.FLOATING_TOOLBAR,
156
- // selection: view.state.selection.toJSON(),
157
- // position: view.state.selection.from,
158
- // docSize: view.state.doc.nodeSize,
159
- // error: error.toString(),
160
- // // @ts-expect-error - Object literal may only specify known properties, 'errorStack' does not exist in type
161
- // // This error was introduced after upgrading to TypeScript 5
162
- // errorStack: error.stack || undefined,
163
- // },
164
- // };
165
- // dispatchAnalyticsEvent(payload);
166
- // }
167
- }
168
- };
169
- const getKeyboardNavigationConfig = (editorView, intl, api) => {
170
- if (!(editorView.dom instanceof HTMLElement)) {
171
- return;
172
- }
173
- const toolbarSelector = "[data-testid='editor-floating-toolbar']";
174
- return {
175
- childComponentSelector: toolbarSelector,
176
- dom: editorView.dom,
177
- isShortcutToFocusToolbar: isShortcutToFocusToolbar,
178
- handleFocus: event => {
179
- var _getDocument, _filteredFocusableEle, _filteredFocusableEle2, _filteredFocusableEle3;
180
- const toolbar = (_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : _getDocument.querySelector(toolbarSelector);
181
- if (!(toolbar instanceof HTMLElement)) {
182
- return;
183
- }
184
- const filteredFocusableElements = getFocusableElements(toolbar);
185
- (_filteredFocusableEle = filteredFocusableElements[0]) === null || _filteredFocusableEle === void 0 ? void 0 : _filteredFocusableEle.focus();
186
-
187
- // the button element removes the focus ring so this class adds it back
188
- if (((_filteredFocusableEle2 = filteredFocusableElements[0]) === null || _filteredFocusableEle2 === void 0 ? void 0 : _filteredFocusableEle2.tagName) === 'BUTTON') {
189
- filteredFocusableElements[0].classList.add('first-floating-toolbar-button');
190
- }
191
- (_filteredFocusableEle3 = filteredFocusableElements[0]) === null || _filteredFocusableEle3 === void 0 ? void 0 : _filteredFocusableEle3.scrollIntoView({
192
- behavior: 'smooth',
193
- block: 'center',
194
- inline: 'nearest'
195
- });
196
- event.preventDefault();
197
- event.stopPropagation();
198
- },
199
- handleEscape: event => {
200
- const isDropdownOpen = !!document.querySelector('[data-toolbar-component="menu-section"]');
201
- if (isDropdownOpen) {
202
- return;
203
- }
204
- api === null || api === void 0 ? void 0 : api.core.actions.focus();
205
- event.preventDefault();
206
- event.stopPropagation();
207
- },
208
- ariaControls: EDIT_AREA_ID,
209
- ariaLabel: intl.formatMessage(fullPageMessages.toolbarLabel)
210
- };
164
+ export const SelectionToolbarWithErrorBoundary = ({
165
+ api,
166
+ editorView,
167
+ mountPoint,
168
+ disableSelectionToolbarWhenPinned
169
+ }) => {
170
+ var _api$analytics2;
171
+ return /*#__PURE__*/React.createElement(ErrorBoundary, {
172
+ component: ACTION_SUBJECT.TOOLBAR,
173
+ componentId: ACTION_SUBJECT_ID.SELECTION_TOOLBAR,
174
+ dispatchAnalyticsEvent: api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent,
175
+ fallbackComponent: null
176
+ }, /*#__PURE__*/React.createElement(SelectionToolbar, {
177
+ api: api,
178
+ editorView: editorView,
179
+ mountPoint: mountPoint,
180
+ disableSelectionToolbarWhenPinned: disableSelectionToolbarWhenPinned
181
+ }));
211
182
  };
@@ -0,0 +1,64 @@
1
+ import { getDocument } from '@atlaskit/browser-apis';
2
+ import { fullPageMessages } from '@atlaskit/editor-common/messages';
3
+ import { logException } from '@atlaskit/editor-common/monitoring';
4
+ import { EDIT_AREA_ID } from '@atlaskit/editor-common/ui';
5
+ import { getFocusableElements, isShortcutToFocusToolbar } from '../utils/toolbar';
6
+ export const getKeyboardNavigationConfig = (editorView, intl, api) => {
7
+ if (!(editorView.dom instanceof HTMLElement)) {
8
+ return;
9
+ }
10
+ const toolbarSelector = "[data-testid='editor-floating-toolbar']";
11
+ return {
12
+ childComponentSelector: toolbarSelector,
13
+ dom: editorView.dom,
14
+ isShortcutToFocusToolbar: isShortcutToFocusToolbar,
15
+ handleFocus: event => {
16
+ try {
17
+ var _getDocument, _filteredFocusableEle, _filteredFocusableEle2, _filteredFocusableEle3;
18
+ const toolbar = (_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : _getDocument.querySelector(toolbarSelector);
19
+ if (!(toolbar instanceof HTMLElement)) {
20
+ return;
21
+ }
22
+ const filteredFocusableElements = getFocusableElements(toolbar);
23
+ (_filteredFocusableEle = filteredFocusableElements[0]) === null || _filteredFocusableEle === void 0 ? void 0 : _filteredFocusableEle.focus();
24
+
25
+ // the button element removes the focus ring so this class adds it back
26
+ if (((_filteredFocusableEle2 = filteredFocusableElements[0]) === null || _filteredFocusableEle2 === void 0 ? void 0 : _filteredFocusableEle2.tagName) === 'BUTTON') {
27
+ filteredFocusableElements[0].classList.add('first-floating-toolbar-button');
28
+ }
29
+ (_filteredFocusableEle3 = filteredFocusableElements[0]) === null || _filteredFocusableEle3 === void 0 ? void 0 : _filteredFocusableEle3.scrollIntoView({
30
+ behavior: 'smooth',
31
+ block: 'center',
32
+ inline: 'nearest'
33
+ });
34
+ event.preventDefault();
35
+ event.stopPropagation();
36
+ } catch (error) {
37
+ if (error instanceof Error) {
38
+ logException(error, {
39
+ location: 'editor-plugin-toolbar/selectionToolbar'
40
+ });
41
+ }
42
+ }
43
+ },
44
+ handleEscape: event => {
45
+ try {
46
+ const isDropdownOpen = !!document.querySelector('[data-toolbar-component="menu-section"]');
47
+ if (isDropdownOpen) {
48
+ return;
49
+ }
50
+ api === null || api === void 0 ? void 0 : api.core.actions.focus();
51
+ event.preventDefault();
52
+ event.stopPropagation();
53
+ } catch (error) {
54
+ if (error instanceof Error) {
55
+ logException(error, {
56
+ location: 'editor-plugin-toolbar/selectionToolbar'
57
+ });
58
+ }
59
+ }
60
+ },
61
+ ariaControls: EDIT_AREA_ID,
62
+ ariaLabel: intl.formatMessage(fullPageMessages.toolbarLabel)
63
+ };
64
+ };
@@ -0,0 +1,36 @@
1
+ import { ACTION, ACTION_SUBJECT, CONTENT_COMPONENT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
+ import { logException } from '@atlaskit/editor-common/monitoring';
3
+ import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
4
+ export const getDomRefFromSelection = (view, dispatchAnalyticsEvent) => {
5
+ try {
6
+ const domRef = findDomRefAtPos(view.state.selection.from, view.domAtPos.bind(view));
7
+ if (domRef instanceof HTMLElement) {
8
+ return domRef;
9
+ }
10
+ throw new Error('Invalid DOM reference');
11
+ } catch (error) {
12
+ if (dispatchAnalyticsEvent) {
13
+ const payload = {
14
+ action: ACTION.ERRORED,
15
+ actionSubject: ACTION_SUBJECT.CONTENT_COMPONENT,
16
+ eventType: EVENT_TYPE.OPERATIONAL,
17
+ attributes: {
18
+ component: CONTENT_COMPONENT.SELECTION_TOOLBAR,
19
+ selection: view.state.selection.toJSON(),
20
+ position: view.state.selection.from,
21
+ docSize: view.state.doc.nodeSize,
22
+ error: error instanceof Error ? error.toString() : String(error),
23
+ // @ts-expect-error - Object literal may only specify known properties, 'errorStack' does not exist in type
24
+ // This error was introduced after upgrading to TypeScript 5
25
+ errorStack: error instanceof Error ? error.stack : undefined
26
+ }
27
+ };
28
+ dispatchAnalyticsEvent(payload);
29
+ }
30
+ if (error instanceof Error) {
31
+ logException(error, {
32
+ location: 'editor-plugin-toolbar/selectionToolbar'
33
+ });
34
+ }
35
+ }
36
+ };
@@ -7,10 +7,11 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
7
7
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
8
8
  import { findSelectedNodeOfType, findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
9
9
  import { createComponentRegistry } from '@atlaskit/editor-toolbar-model';
10
+ import { fg } from '@atlaskit/platform-feature-flags';
10
11
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
11
12
  import { editorToolbarPluginKey } from './pm-plugins/plugin-key';
12
13
  import { DEFAULT_POPUP_SELECTORS } from './ui/consts';
13
- import { SelectionToolbar } from './ui/SelectionToolbar';
14
+ import { SelectionToolbar, SelectionToolbarWithErrorBoundary } from './ui/SelectionToolbar';
14
15
  import { getToolbarComponents } from './ui/toolbar-components';
15
16
  import { isEventInContainer } from './ui/utils/toolbar';
16
17
  function getSelectedNode(editorState) {
@@ -63,8 +64,7 @@ export var toolbarPlugin = function toolbarPlugin(_ref) {
63
64
  _ref$config = _ref.config,
64
65
  config = _ref$config === void 0 ? {
65
66
  disableSelectionToolbar: false,
66
- disableSelectionToolbarWhenPinned: false,
67
- enableNewToolbarExperience: true
67
+ disableSelectionToolbarWhenPinned: false
68
68
  } : _ref$config;
69
69
  var disableSelectionToolbar = config.disableSelectionToolbar,
70
70
  disableSelectionToolbarWhenPinned = config.disableSelectionToolbarWhenPinned;
@@ -178,6 +178,14 @@ export var toolbarPlugin = function toolbarPlugin(_ref) {
178
178
  if (!editorView) {
179
179
  return null;
180
180
  }
181
+ if (fg('platform_editor_toolbar_aifc_patch_7')) {
182
+ return /*#__PURE__*/React.createElement(SelectionToolbarWithErrorBoundary, {
183
+ api: api,
184
+ editorView: editorView,
185
+ mountPoint: popupsMountPoint,
186
+ disableSelectionToolbarWhenPinned: disableSelectionToolbarWhenPinned !== null && disableSelectionToolbarWhenPinned !== void 0 ? disableSelectionToolbarWhenPinned : false
187
+ });
188
+ }
181
189
  return /*#__PURE__*/React.createElement(SelectionToolbar, {
182
190
  api: api,
183
191
  editorView: editorView,
@@ -1,22 +1,24 @@
1
1
  import React, { useCallback, useMemo } from 'react';
2
2
  import { useIntl } from 'react-intl-next';
3
- import { getDocument } from '@atlaskit/browser-apis';
3
+ import { ACTION_SUBJECT, ACTION_SUBJECT_ID } from '@atlaskit/editor-common/analytics';
4
4
  import { isSSR } from '@atlaskit/editor-common/core-utils';
5
+ import { ErrorBoundary } from '@atlaskit/editor-common/error-boundary';
5
6
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
6
- import { fullPageMessages } from '@atlaskit/editor-common/messages';
7
+ import { logException } from '@atlaskit/editor-common/monitoring';
7
8
  import { EditorToolbarProvider, EditorToolbarUIProvider } from '@atlaskit/editor-common/toolbar';
8
- import { Popup, EDIT_AREA_ID } from '@atlaskit/editor-common/ui';
9
+ import { Popup } from '@atlaskit/editor-common/ui';
9
10
  import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
10
11
  import { calculateToolbarPositionTrackHead, calculateToolbarPositionOnCellSelection } from '@atlaskit/editor-common/utils';
11
12
  import { AllSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
12
- import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
13
13
  import { ToolbarSection, ToolbarButtonGroup, ToolbarDropdownItemSection, useToolbarUI } from '@atlaskit/editor-toolbar';
14
14
  import { ToolbarModelRenderer } from '@atlaskit/editor-toolbar-model';
15
+ import { fg } from '@atlaskit/platform-feature-flags';
15
16
  import { conditionalHooksFactory } from '@atlaskit/platform-feature-flags-react';
16
17
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
17
18
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
18
19
  import { SELECTION_TOOLBAR_LABEL } from '../consts';
19
- import { getFocusableElements, isShortcutToFocusToolbar } from '../utils/toolbar';
20
+ import { getKeyboardNavigationConfig } from './keyboard-config';
21
+ import { getDomRefFromSelection } from './utils';
20
22
  var isToolbarComponent = function isToolbarComponent(component) {
21
23
  return component.type === 'toolbar' && component.key === 'inline-text-toolbar';
22
24
  };
@@ -59,6 +61,42 @@ var usePluginState = conditionalHooksFactory(function () {
59
61
  selectedNode: selectedNode
60
62
  };
61
63
  });
64
+ var useOnPositionCalculated = conditionalHooksFactory(function () {
65
+ return fg('platform_editor_toolbar_aifc_patch_7');
66
+ }, function (editorView) {
67
+ var onPositionCalculated = useCallback(function (position) {
68
+ try {
69
+ var toolbarTitle = SELECTION_TOOLBAR_LABEL;
70
+
71
+ // Show special position on cell selection only when editor controls experiment is enabled
72
+ var isEditorControlsEnabled = expValEquals('platform_editor_controls', 'cohort', 'variant1');
73
+ var isCellSelection = ('$anchorCell' in editorView.state.selection);
74
+ if (isCellSelection && isEditorControlsEnabled) {
75
+ return calculateToolbarPositionOnCellSelection(toolbarTitle)(editorView, position);
76
+ }
77
+ return calculateToolbarPositionTrackHead(toolbarTitle)(editorView, position);
78
+ } catch (error) {
79
+ logException(error, {
80
+ location: 'editor-plugin-toolbar/selectionToolbar'
81
+ });
82
+ return position;
83
+ }
84
+ }, [editorView]);
85
+ return onPositionCalculated;
86
+ }, function (editorView) {
87
+ var onPositionCalculated = useCallback(function (position) {
88
+ var toolbarTitle = SELECTION_TOOLBAR_LABEL;
89
+
90
+ // Show special position on cell selection only when editor controls experiment is enabled
91
+ var isEditorControlsEnabled = expValEquals('platform_editor_controls', 'cohort', 'variant1');
92
+ var isCellSelection = ('$anchorCell' in editorView.state.selection);
93
+ if (isCellSelection && isEditorControlsEnabled) {
94
+ return calculateToolbarPositionOnCellSelection(toolbarTitle)(editorView, position);
95
+ }
96
+ return calculateToolbarPositionTrackHead(toolbarTitle)(editorView, position);
97
+ }, [editorView]);
98
+ return onPositionCalculated;
99
+ });
62
100
  export var SelectionToolbar = function SelectionToolbar(_ref) {
63
101
  var _api$toolbar;
64
102
  var api = _ref.api,
@@ -87,17 +125,7 @@ export var SelectionToolbar = function SelectionToolbar(_ref) {
87
125
  var isTextSelection = !editorView.state.selection.empty && editorView.state.selection instanceof TextSelection;
88
126
  var isAllSelection = !editorView.state.selection.empty && editorView.state.selection instanceof AllSelection;
89
127
  var isCellSelection = !editorView.state.selection.empty && '$anchorCell' in editorView.state.selection;
90
- var onPositionCalculated = useCallback(function (position) {
91
- var toolbarTitle = SELECTION_TOOLBAR_LABEL;
92
-
93
- // Show special position on cell selection only when editor controls experiment is enabled
94
- var isEditorControlsEnabled = expValEquals('platform_editor_controls', 'cohort', 'variant1');
95
- var isCellSelection = ('$anchorCell' in editorView.state.selection);
96
- if (isCellSelection && isEditorControlsEnabled) {
97
- return calculateToolbarPositionOnCellSelection(toolbarTitle)(editorView, position);
98
- }
99
- return calculateToolbarPositionTrackHead(toolbarTitle)(editorView, position);
100
- }, [editorView]);
128
+ var onPositionCalculated = useOnPositionCalculated(editorView);
101
129
  if (expValEquals('platform_editor_toolbar_aifc_template_editor', 'isEnabled', true) && editorToolbarDockingPreference === 'top' && disableSelectionToolbarWhenPinned || !components || !toolbar) {
102
130
  return null;
103
131
  }
@@ -112,7 +140,8 @@ export var SelectionToolbar = function SelectionToolbar(_ref) {
112
140
  }, /*#__PURE__*/React.createElement(EditorToolbarProvider, {
113
141
  editorView: editorView,
114
142
  editorToolbarDockingPreference: editorToolbarDockingPreference,
115
- editorViewMode: expValEquals('platform_editor_toolbar_aifc_patch_4', 'isEnabled', true) ? editorViewMode !== null && editorViewMode !== void 0 ? editorViewMode : 'edit' : editorViewMode
143
+ editorViewMode: expValEquals('platform_editor_toolbar_aifc_patch_4', 'isEnabled', true) ? editorViewMode !== null && editorViewMode !== void 0 ? editorViewMode : 'edit' : editorViewMode,
144
+ isOffline: isOffline
116
145
  }, /*#__PURE__*/React.createElement(EditorToolbarUIProvider, {
117
146
  api: api,
118
147
  isDisabled: patch6Enabled ? isDisabled : isOffline
@@ -133,78 +162,21 @@ export var SelectionToolbar = function SelectionToolbar(_ref) {
133
162
  }
134
163
  }))));
135
164
  };
136
- var getDomRefFromSelection = function getDomRefFromSelection(view
137
- // dispatchAnalyticsEvent?: DispatchAnalyticsEvent,
138
- ) {
139
- try {
140
- // Ignored via go/ees005
141
- // eslint-disable-next-line @atlaskit/editor/no-as-casting
142
- return findDomRefAtPos(view.state.selection.from, view.domAtPos.bind(view));
143
- // Ignored via go/ees005
144
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
145
- } catch (error) {
146
- // // eslint-disable-next-line no-console
147
- // console.warn(error);
148
- // if (dispatchAnalyticsEvent) {
149
- // const payload: AnalyticsEventPayload = {
150
- // action: ACTION.ERRORED,
151
- // actionSubject: ACTION_SUBJECT.CONTENT_COMPONENT,
152
- // eventType: EVENT_TYPE.OPERATIONAL,
153
- // attributes: {
154
- // component: CONTENT_COMPONENT.FLOATING_TOOLBAR,
155
- // selection: view.state.selection.toJSON(),
156
- // position: view.state.selection.from,
157
- // docSize: view.state.doc.nodeSize,
158
- // error: error.toString(),
159
- // // @ts-expect-error - Object literal may only specify known properties, 'errorStack' does not exist in type
160
- // // This error was introduced after upgrading to TypeScript 5
161
- // errorStack: error.stack || undefined,
162
- // },
163
- // };
164
- // dispatchAnalyticsEvent(payload);
165
- // }
166
- }
167
- };
168
- var getKeyboardNavigationConfig = function getKeyboardNavigationConfig(editorView, intl, api) {
169
- if (!(editorView.dom instanceof HTMLElement)) {
170
- return;
171
- }
172
- var toolbarSelector = "[data-testid='editor-floating-toolbar']";
173
- return {
174
- childComponentSelector: toolbarSelector,
175
- dom: editorView.dom,
176
- isShortcutToFocusToolbar: isShortcutToFocusToolbar,
177
- handleFocus: function handleFocus(event) {
178
- var _getDocument, _filteredFocusableEle, _filteredFocusableEle2, _filteredFocusableEle3;
179
- var toolbar = (_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : _getDocument.querySelector(toolbarSelector);
180
- if (!(toolbar instanceof HTMLElement)) {
181
- return;
182
- }
183
- var filteredFocusableElements = getFocusableElements(toolbar);
184
- (_filteredFocusableEle = filteredFocusableElements[0]) === null || _filteredFocusableEle === void 0 || _filteredFocusableEle.focus();
185
-
186
- // the button element removes the focus ring so this class adds it back
187
- if (((_filteredFocusableEle2 = filteredFocusableElements[0]) === null || _filteredFocusableEle2 === void 0 ? void 0 : _filteredFocusableEle2.tagName) === 'BUTTON') {
188
- filteredFocusableElements[0].classList.add('first-floating-toolbar-button');
189
- }
190
- (_filteredFocusableEle3 = filteredFocusableElements[0]) === null || _filteredFocusableEle3 === void 0 || _filteredFocusableEle3.scrollIntoView({
191
- behavior: 'smooth',
192
- block: 'center',
193
- inline: 'nearest'
194
- });
195
- event.preventDefault();
196
- event.stopPropagation();
197
- },
198
- handleEscape: function handleEscape(event) {
199
- var isDropdownOpen = !!document.querySelector('[data-toolbar-component="menu-section"]');
200
- if (isDropdownOpen) {
201
- return;
202
- }
203
- api === null || api === void 0 || api.core.actions.focus();
204
- event.preventDefault();
205
- event.stopPropagation();
206
- },
207
- ariaControls: EDIT_AREA_ID,
208
- ariaLabel: intl.formatMessage(fullPageMessages.toolbarLabel)
209
- };
165
+ export var SelectionToolbarWithErrorBoundary = function SelectionToolbarWithErrorBoundary(_ref2) {
166
+ var _api$analytics2;
167
+ var api = _ref2.api,
168
+ editorView = _ref2.editorView,
169
+ mountPoint = _ref2.mountPoint,
170
+ disableSelectionToolbarWhenPinned = _ref2.disableSelectionToolbarWhenPinned;
171
+ return /*#__PURE__*/React.createElement(ErrorBoundary, {
172
+ component: ACTION_SUBJECT.TOOLBAR,
173
+ componentId: ACTION_SUBJECT_ID.SELECTION_TOOLBAR,
174
+ dispatchAnalyticsEvent: api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent,
175
+ fallbackComponent: null
176
+ }, /*#__PURE__*/React.createElement(SelectionToolbar, {
177
+ api: api,
178
+ editorView: editorView,
179
+ mountPoint: mountPoint,
180
+ disableSelectionToolbarWhenPinned: disableSelectionToolbarWhenPinned
181
+ }));
210
182
  };
@@ -0,0 +1,64 @@
1
+ import { getDocument } from '@atlaskit/browser-apis';
2
+ import { fullPageMessages } from '@atlaskit/editor-common/messages';
3
+ import { logException } from '@atlaskit/editor-common/monitoring';
4
+ import { EDIT_AREA_ID } from '@atlaskit/editor-common/ui';
5
+ import { getFocusableElements, isShortcutToFocusToolbar } from '../utils/toolbar';
6
+ export var getKeyboardNavigationConfig = function getKeyboardNavigationConfig(editorView, intl, api) {
7
+ if (!(editorView.dom instanceof HTMLElement)) {
8
+ return;
9
+ }
10
+ var toolbarSelector = "[data-testid='editor-floating-toolbar']";
11
+ return {
12
+ childComponentSelector: toolbarSelector,
13
+ dom: editorView.dom,
14
+ isShortcutToFocusToolbar: isShortcutToFocusToolbar,
15
+ handleFocus: function handleFocus(event) {
16
+ try {
17
+ var _getDocument, _filteredFocusableEle, _filteredFocusableEle2, _filteredFocusableEle3;
18
+ var toolbar = (_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : _getDocument.querySelector(toolbarSelector);
19
+ if (!(toolbar instanceof HTMLElement)) {
20
+ return;
21
+ }
22
+ var filteredFocusableElements = getFocusableElements(toolbar);
23
+ (_filteredFocusableEle = filteredFocusableElements[0]) === null || _filteredFocusableEle === void 0 || _filteredFocusableEle.focus();
24
+
25
+ // the button element removes the focus ring so this class adds it back
26
+ if (((_filteredFocusableEle2 = filteredFocusableElements[0]) === null || _filteredFocusableEle2 === void 0 ? void 0 : _filteredFocusableEle2.tagName) === 'BUTTON') {
27
+ filteredFocusableElements[0].classList.add('first-floating-toolbar-button');
28
+ }
29
+ (_filteredFocusableEle3 = filteredFocusableElements[0]) === null || _filteredFocusableEle3 === void 0 || _filteredFocusableEle3.scrollIntoView({
30
+ behavior: 'smooth',
31
+ block: 'center',
32
+ inline: 'nearest'
33
+ });
34
+ event.preventDefault();
35
+ event.stopPropagation();
36
+ } catch (error) {
37
+ if (error instanceof Error) {
38
+ logException(error, {
39
+ location: 'editor-plugin-toolbar/selectionToolbar'
40
+ });
41
+ }
42
+ }
43
+ },
44
+ handleEscape: function handleEscape(event) {
45
+ try {
46
+ var isDropdownOpen = !!document.querySelector('[data-toolbar-component="menu-section"]');
47
+ if (isDropdownOpen) {
48
+ return;
49
+ }
50
+ api === null || api === void 0 || api.core.actions.focus();
51
+ event.preventDefault();
52
+ event.stopPropagation();
53
+ } catch (error) {
54
+ if (error instanceof Error) {
55
+ logException(error, {
56
+ location: 'editor-plugin-toolbar/selectionToolbar'
57
+ });
58
+ }
59
+ }
60
+ },
61
+ ariaControls: EDIT_AREA_ID,
62
+ ariaLabel: intl.formatMessage(fullPageMessages.toolbarLabel)
63
+ };
64
+ };
@@ -0,0 +1,36 @@
1
+ import { ACTION, ACTION_SUBJECT, CONTENT_COMPONENT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
+ import { logException } from '@atlaskit/editor-common/monitoring';
3
+ import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
4
+ export var getDomRefFromSelection = function getDomRefFromSelection(view, dispatchAnalyticsEvent) {
5
+ try {
6
+ var domRef = findDomRefAtPos(view.state.selection.from, view.domAtPos.bind(view));
7
+ if (domRef instanceof HTMLElement) {
8
+ return domRef;
9
+ }
10
+ throw new Error('Invalid DOM reference');
11
+ } catch (error) {
12
+ if (dispatchAnalyticsEvent) {
13
+ var payload = {
14
+ action: ACTION.ERRORED,
15
+ actionSubject: ACTION_SUBJECT.CONTENT_COMPONENT,
16
+ eventType: EVENT_TYPE.OPERATIONAL,
17
+ attributes: {
18
+ component: CONTENT_COMPONENT.SELECTION_TOOLBAR,
19
+ selection: view.state.selection.toJSON(),
20
+ position: view.state.selection.from,
21
+ docSize: view.state.doc.nodeSize,
22
+ error: error instanceof Error ? error.toString() : String(error),
23
+ // @ts-expect-error - Object literal may only specify known properties, 'errorStack' does not exist in type
24
+ // This error was introduced after upgrading to TypeScript 5
25
+ errorStack: error instanceof Error ? error.stack : undefined
26
+ }
27
+ };
28
+ dispatchAnalyticsEvent(payload);
29
+ }
30
+ if (error instanceof Error) {
31
+ logException(error, {
32
+ location: 'editor-plugin-toolbar/selectionToolbar'
33
+ });
34
+ }
35
+ }
36
+ };
@@ -3,9 +3,7 @@ export type ToolbarPluginOptions = {
3
3
  disableSelectionToolbar?: boolean;
4
4
  disableSelectionToolbarWhenPinned?: boolean;
5
5
  /**
6
- * Option to enable new toolbar designs - use this to disable the entire toolbar experience where it can't be disabled via the experiment
7
- *
8
- * Default: `true`
6
+ * Option to enable new toolbar designs
9
7
  */
10
8
  enableNewToolbarExperience?: boolean;
11
9
  };
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
- import type { EditorView } from '@atlaskit/editor-prosemirror/view';
3
+ import { type EditorView } from '@atlaskit/editor-prosemirror/view';
4
4
  import type { ToolbarPlugin } from '../../toolbarPluginType';
5
5
  type SelectionToolbarProps = {
6
6
  api?: ExtractInjectionAPI<ToolbarPlugin>;
@@ -9,4 +9,5 @@ type SelectionToolbarProps = {
9
9
  mountPoint: HTMLElement | undefined;
10
10
  };
11
11
  export declare const SelectionToolbar: ({ api, editorView, mountPoint, disableSelectionToolbarWhenPinned, }: SelectionToolbarProps) => React.JSX.Element | null;
12
+ export declare const SelectionToolbarWithErrorBoundary: ({ api, editorView, mountPoint, disableSelectionToolbarWhenPinned, }: SelectionToolbarProps) => React.JSX.Element;
12
13
  export {};
@@ -0,0 +1,6 @@
1
+ import { type IntlShape } from 'react-intl-next';
2
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
4
+ import { type ToolbarKeyboardNavigationProviderConfig } from '@atlaskit/editor-toolbar';
5
+ import type { ToolbarPlugin } from '../../toolbarPluginType';
6
+ export declare const getKeyboardNavigationConfig: (editorView: EditorView, intl: IntlShape, api?: ExtractInjectionAPI<ToolbarPlugin>) => ToolbarKeyboardNavigationProviderConfig | undefined;
@@ -0,0 +1,3 @@
1
+ import { type DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
2
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
3
+ export declare const getDomRefFromSelection: (view: EditorView, dispatchAnalyticsEvent?: DispatchAnalyticsEvent) => HTMLElement | undefined;
@@ -3,9 +3,7 @@ export type ToolbarPluginOptions = {
3
3
  disableSelectionToolbar?: boolean;
4
4
  disableSelectionToolbarWhenPinned?: boolean;
5
5
  /**
6
- * Option to enable new toolbar designs - use this to disable the entire toolbar experience where it can't be disabled via the experiment
7
- *
8
- * Default: `true`
6
+ * Option to enable new toolbar designs
9
7
  */
10
8
  enableNewToolbarExperience?: boolean;
11
9
  };
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
- import type { EditorView } from '@atlaskit/editor-prosemirror/view';
3
+ import { type EditorView } from '@atlaskit/editor-prosemirror/view';
4
4
  import type { ToolbarPlugin } from '../../toolbarPluginType';
5
5
  type SelectionToolbarProps = {
6
6
  api?: ExtractInjectionAPI<ToolbarPlugin>;
@@ -9,4 +9,5 @@ type SelectionToolbarProps = {
9
9
  mountPoint: HTMLElement | undefined;
10
10
  };
11
11
  export declare const SelectionToolbar: ({ api, editorView, mountPoint, disableSelectionToolbarWhenPinned, }: SelectionToolbarProps) => React.JSX.Element | null;
12
+ export declare const SelectionToolbarWithErrorBoundary: ({ api, editorView, mountPoint, disableSelectionToolbarWhenPinned, }: SelectionToolbarProps) => React.JSX.Element;
12
13
  export {};
@@ -0,0 +1,6 @@
1
+ import { type IntlShape } from 'react-intl-next';
2
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
4
+ import { type ToolbarKeyboardNavigationProviderConfig } from '@atlaskit/editor-toolbar';
5
+ import type { ToolbarPlugin } from '../../toolbarPluginType';
6
+ export declare const getKeyboardNavigationConfig: (editorView: EditorView, intl: IntlShape, api?: ExtractInjectionAPI<ToolbarPlugin>) => ToolbarKeyboardNavigationProviderConfig | undefined;
@@ -0,0 +1,3 @@
1
+ import { type DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
2
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
3
+ export declare const getDomRefFromSelection: (view: EditorView, dispatchAnalyticsEvent?: DispatchAnalyticsEvent) => HTMLElement | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-toolbar",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Toolbar plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -38,16 +38,22 @@
38
38
  "@atlaskit/editor-prosemirror": "7.0.0",
39
39
  "@atlaskit/editor-toolbar": "^0.15.0",
40
40
  "@atlaskit/editor-toolbar-model": "^0.2.0",
41
+ "@atlaskit/platform-feature-flags": "^1.1.0",
41
42
  "@atlaskit/platform-feature-flags-react": "^0.3.0",
42
- "@atlaskit/tmp-editor-statsig": "^13.8.0",
43
+ "@atlaskit/tmp-editor-statsig": "^13.10.0",
43
44
  "@babel/runtime": "^7.0.0",
44
45
  "bind-event-listener": "^3.0.0",
45
46
  "react-intl-next": "npm:react-intl@^5.18.1"
46
47
  },
47
48
  "peerDependencies": {
48
- "@atlaskit/editor-common": "^110.10.0",
49
+ "@atlaskit/editor-common": "^110.12.0",
49
50
  "react": "^18.2.0"
50
51
  },
52
+ "platform-feature-flags": {
53
+ "platform_editor_toolbar_aifc_patch_7": {
54
+ "type": "boolean"
55
+ }
56
+ },
51
57
  "techstack": {
52
58
  "@atlassian/frontend": {
53
59
  "code-structure": [