@atlaskit/editor-plugin-insert-block 18.0.6 → 18.1.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/cjs/ui/ToolbarInsertBlock/block-insert-element-browser.js +21 -3
  3. package/dist/cjs/ui/ToolbarInsertBlock/block-insert-menu.js +3 -1
  4. package/dist/cjs/ui/ToolbarInsertBlock/index.js +3 -1
  5. package/dist/cjs/ui/registered-insert-menu/RegisteredInsertButton.js +122 -0
  6. package/dist/cjs/ui/registered-insert-menu/RegisteredInsertMenu.compiled.css +11 -0
  7. package/dist/cjs/ui/registered-insert-menu/RegisteredInsertMenu.js +154 -0
  8. package/dist/cjs/ui/registered-insert-menu/RegisteredInsertMenuContent.js +53 -0
  9. package/dist/cjs/ui/registered-insert-menu/RegisteredInsertMenuItem.js +59 -0
  10. package/dist/cjs/ui/registered-insert-menu/RegisteredInsertMenuList.compiled.css +4 -0
  11. package/dist/cjs/ui/registered-insert-menu/RegisteredInsertMenuList.js +205 -0
  12. package/dist/cjs/ui/toolbar-components.js +5 -1
  13. package/dist/es2019/ui/ToolbarInsertBlock/block-insert-element-browser.js +21 -2
  14. package/dist/es2019/ui/ToolbarInsertBlock/block-insert-menu.js +3 -1
  15. package/dist/es2019/ui/ToolbarInsertBlock/index.js +3 -1
  16. package/dist/es2019/ui/registered-insert-menu/RegisteredInsertButton.js +107 -0
  17. package/dist/es2019/ui/registered-insert-menu/RegisteredInsertMenu.compiled.css +11 -0
  18. package/dist/es2019/ui/registered-insert-menu/RegisteredInsertMenu.js +117 -0
  19. package/dist/es2019/ui/registered-insert-menu/RegisteredInsertMenuContent.js +43 -0
  20. package/dist/es2019/ui/registered-insert-menu/RegisteredInsertMenuItem.js +49 -0
  21. package/dist/es2019/ui/registered-insert-menu/RegisteredInsertMenuList.compiled.css +4 -0
  22. package/dist/es2019/ui/registered-insert-menu/RegisteredInsertMenuList.js +161 -0
  23. package/dist/es2019/ui/toolbar-components.js +5 -1
  24. package/dist/esm/ui/ToolbarInsertBlock/block-insert-element-browser.js +21 -2
  25. package/dist/esm/ui/ToolbarInsertBlock/block-insert-menu.js +3 -1
  26. package/dist/esm/ui/ToolbarInsertBlock/index.js +3 -1
  27. package/dist/esm/ui/registered-insert-menu/RegisteredInsertButton.js +113 -0
  28. package/dist/esm/ui/registered-insert-menu/RegisteredInsertMenu.compiled.css +11 -0
  29. package/dist/esm/ui/registered-insert-menu/RegisteredInsertMenu.js +145 -0
  30. package/dist/esm/ui/registered-insert-menu/RegisteredInsertMenuContent.js +44 -0
  31. package/dist/esm/ui/registered-insert-menu/RegisteredInsertMenuItem.js +51 -0
  32. package/dist/esm/ui/registered-insert-menu/RegisteredInsertMenuList.compiled.css +4 -0
  33. package/dist/esm/ui/registered-insert-menu/RegisteredInsertMenuList.js +196 -0
  34. package/dist/esm/ui/toolbar-components.js +5 -1
  35. package/dist/types/types/index.d.ts +3 -1
  36. package/dist/types/ui/ToolbarInsertBlock/block-insert-element-browser.d.ts +1 -0
  37. package/dist/types/ui/ToolbarInsertBlock/block-insert-menu.d.ts +1 -0
  38. package/dist/types/ui/registered-insert-menu/RegisteredInsertButton.d.ts +12 -0
  39. package/dist/types/ui/registered-insert-menu/RegisteredInsertMenu.d.ts +12 -0
  40. package/dist/types/ui/registered-insert-menu/RegisteredInsertMenuContent.d.ts +15 -0
  41. package/dist/types/ui/registered-insert-menu/RegisteredInsertMenuItem.d.ts +15 -0
  42. package/dist/types/ui/registered-insert-menu/RegisteredInsertMenuList.d.ts +23 -0
  43. package/package.json +11 -5
@@ -0,0 +1,205 @@
1
+ /* RegisteredInsertMenuList.tsx generated by @compiled/babel-plugin v3.0.1 */
2
+ "use strict";
3
+
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+ Object.defineProperty(exports, "__esModule", {
7
+ value: true
8
+ });
9
+ exports.RegisteredInsertMenuList = void 0;
10
+ require("./RegisteredInsertMenuList.compiled.css");
11
+ var _runtime = require("@compiled/react/runtime");
12
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
13
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
14
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
+ var _react = _interopRequireWildcard(require("react"));
16
+ var _CellMeasurer = require("react-virtualized/dist/commonjs/CellMeasurer");
17
+ var _List = require("react-virtualized/dist/commonjs/List");
18
+ var _compiled = require("@atlaskit/primitives/compiled");
19
+ var _RegisteredInsertMenuItem = require("./RegisteredInsertMenuItem");
20
+ 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); }
21
+ 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; } } }; }
22
+ 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; } }
23
+ 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; }
24
+ var ESTIMATED_ROW_HEIGHT = 56;
25
+ var MENU_FOOTER_HEIGHT = 52;
26
+ var MENU_SEARCH_HEIGHT = 64;
27
+ var LIST_WIDTH = 350;
28
+ var listAriaProps = {
29
+ // @ts-expect-error react-virtualized forwards null to omit its grid-only default; its types exclude null.
30
+ 'aria-readonly': null
31
+ };
32
+ var styles = {
33
+ footer: "_1rjc1b66 _1i531l7x _15a5nqa1 _uwhke4h9 _1o9zidpf"
34
+ };
35
+ var RegisteredInsertMenuList = exports.RegisteredInsertMenuList = function RegisteredInsertMenuList(_ref) {
36
+ var _model$root$component, _model$root;
37
+ var editorView = _ref.editorView,
38
+ isOffline = _ref.isOffline,
39
+ listId = _ref.listId,
40
+ listLabel = _ref.listLabel,
41
+ maxHeight = _ref.maxHeight,
42
+ menuOpenId = _ref.menuOpenId,
43
+ model = _ref.model,
44
+ onClose = _ref.onClose,
45
+ onItemHover = _ref.onItemHover,
46
+ onRenderedItemsChange = _ref.onRenderedItemsChange,
47
+ selectedItemIndex = _ref.selectedItemIndex,
48
+ surfaceContext = _ref.surfaceContext;
49
+ var Root = (_model$root$component = (_model$root = model.root) === null || _model$root === void 0 ? void 0 : _model$root.component) !== null && _model$root$component !== void 0 ? _model$root$component : _react.default.Fragment;
50
+ var listRef = (0, _react.useRef)(null);
51
+ var rows = (0, _react.useMemo)(function () {
52
+ return model.sections.flat();
53
+ }, [model.sections]);
54
+ var cache = (0, _react.useMemo)(function () {
55
+ return new _CellMeasurer.CellMeasurerCache({
56
+ defaultHeight: ESTIMATED_ROW_HEIGHT,
57
+ fixedWidth: true
58
+ });
59
+ }, []);
60
+ var itemIndexByRowIndex = (0, _react.useMemo)(function () {
61
+ var indexes = new Map();
62
+ var itemIndex = 0;
63
+ rows.forEach(function (registration, rowIndex) {
64
+ if (registration.type === 'menu-item') {
65
+ indexes.set(rowIndex, itemIndex++);
66
+ }
67
+ });
68
+ return indexes;
69
+ }, [rows]);
70
+ var selectedRowIndex = (0, _react.useMemo)(function () {
71
+ var _iterator = _createForOfIteratorHelper(itemIndexByRowIndex),
72
+ _step;
73
+ try {
74
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
75
+ var _step$value = (0, _slicedToArray2.default)(_step.value, 2),
76
+ rowIndex = _step$value[0],
77
+ itemIndex = _step$value[1];
78
+ if (itemIndex === selectedItemIndex) {
79
+ return rowIndex;
80
+ }
81
+ }
82
+ } catch (err) {
83
+ _iterator.e(err);
84
+ } finally {
85
+ _iterator.f();
86
+ }
87
+ return -1;
88
+ }, [itemIndexByRowIndex, selectedItemIndex]);
89
+ var rowKeySignature = (0, _react.useMemo)(function () {
90
+ return rows.map(function (_ref2) {
91
+ var key = _ref2.key,
92
+ type = _ref2.type;
93
+ return "".concat(type, ":").concat(key);
94
+ }).join('\0');
95
+ }, [rows]);
96
+ (0, _react.useLayoutEffect)(function () {
97
+ var _listRef$current, _listRef$current2;
98
+ cache.clearAll();
99
+ (_listRef$current = listRef.current) === null || _listRef$current === void 0 || _listRef$current.recomputeRowHeights();
100
+ (_listRef$current2 = listRef.current) === null || _listRef$current2 === void 0 || _listRef$current2.scrollToPosition(0);
101
+ }, [cache, rowKeySignature]);
102
+ var onRowsRendered = (0, _react.useCallback)(function (_ref3) {
103
+ var _indexes$, _indexes;
104
+ var overscanStartIndex = _ref3.overscanStartIndex,
105
+ overscanStopIndex = _ref3.overscanStopIndex;
106
+ var indexes = (0, _toConsumableArray2.default)(itemIndexByRowIndex).filter(function (_ref4) {
107
+ var _ref5 = (0, _slicedToArray2.default)(_ref4, 1),
108
+ rowIndex = _ref5[0];
109
+ return rowIndex >= overscanStartIndex && rowIndex <= overscanStopIndex;
110
+ }).map(function (_ref6) {
111
+ var _ref7 = (0, _slicedToArray2.default)(_ref6, 2),
112
+ itemIndex = _ref7[1];
113
+ return itemIndex;
114
+ });
115
+ onRenderedItemsChange({
116
+ startIndex: (_indexes$ = indexes[0]) !== null && _indexes$ !== void 0 ? _indexes$ : -1,
117
+ stopIndex: (_indexes = indexes[indexes.length - 1]) !== null && _indexes !== void 0 ? _indexes : -1
118
+ });
119
+ }, [itemIndexByRowIndex, onRenderedItemsChange]);
120
+ var renderRow = (0, _react.useCallback)(function (_ref8) {
121
+ var _registration$compone;
122
+ var index = _ref8.index,
123
+ key = _ref8.key,
124
+ parent = _ref8.parent,
125
+ style = _ref8.style;
126
+ var registration = rows[index];
127
+ if (!registration) {
128
+ return null;
129
+ }
130
+ var itemIndex = itemIndexByRowIndex.get(index);
131
+ var rowContent = registration.type === 'menu-section' ? ( /*#__PURE__*/_react.default.createElement((_registration$compone = registration.component) !== null && _registration$compone !== void 0 ? _registration$compone : _react.default.Fragment, null, null)) : /*#__PURE__*/_react.default.createElement("div", {
132
+ onMouseMove: function onMouseMove() {
133
+ return onItemHover(itemIndex !== null && itemIndex !== void 0 ? itemIndex : 0);
134
+ }
135
+ }, /*#__PURE__*/_react.default.createElement(_RegisteredInsertMenuItem.RegisteredInsertMenuItem, {
136
+ editorView: editorView,
137
+ id: "".concat(listId, "-").concat(itemIndex),
138
+ isOffline: isOffline,
139
+ isSelected: itemIndex === selectedItemIndex,
140
+ menuOpenId: menuOpenId,
141
+ onClose: onClose,
142
+ registration: registration,
143
+ surfaceContext: surfaceContext
144
+ }));
145
+ return /*#__PURE__*/_react.default.createElement(_CellMeasurer.CellMeasurer, {
146
+ key: key,
147
+ cache: cache,
148
+ parent: parent,
149
+ columnIndex: 0,
150
+ rowIndex: index
151
+ }, function (_ref9) {
152
+ var registerChild = _ref9.registerChild;
153
+ return /*#__PURE__*/_react.default.createElement("div", {
154
+ ref: function ref(element) {
155
+ return registerChild === null || registerChild === void 0 ? void 0 : registerChild(element !== null && element !== void 0 ? element : undefined);
156
+ },
157
+ "data-index": index
158
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
159
+ ,
160
+ style: style
161
+ }, rowContent);
162
+ });
163
+ }, [cache, editorView, isOffline, itemIndexByRowIndex, listId, menuOpenId, onClose, onItemHover, rows, selectedItemIndex, surfaceContext]);
164
+ var footerItemIndex = itemIndexByRowIndex.size;
165
+ var listMaxHeight = Math.max(0, maxHeight - MENU_SEARCH_HEIGHT - (model.footer ? MENU_FOOTER_HEIGHT : 0));
166
+ var onFooterItemHover = (0, _react.useCallback)(function () {
167
+ return onItemHover(footerItemIndex);
168
+ }, [footerItemIndex, onItemHover]);
169
+ if (!model.root) {
170
+ return null;
171
+ }
172
+ return /*#__PURE__*/_react.default.createElement(Root, null, /*#__PURE__*/_react.default.createElement(_compiled.Box, {
173
+ "aria-label": listLabel,
174
+ id: listId,
175
+ role: "listbox"
176
+ }, rows.length > 0 && /*#__PURE__*/_react.default.createElement(_List.List
177
+ // eslint-disable-next-line react/jsx-props-no-spreading -- Omits the library's grid-only ARIA default without declaring it on the group role.
178
+ , (0, _extends2.default)({}, listAriaProps, {
179
+ tabIndex: null,
180
+ containerRole: "presentation",
181
+ height: Math.min(rows.length * ESTIMATED_ROW_HEIGHT, listMaxHeight),
182
+ overscanRowCount: 3,
183
+ onRowsRendered: onRowsRendered,
184
+ ref: listRef,
185
+ role: "group",
186
+ rowCount: rows.length,
187
+ rowHeight: cache.rowHeight,
188
+ rowRenderer: renderRow,
189
+ scrollToAlignment: "auto",
190
+ scrollToIndex: selectedRowIndex,
191
+ width: LIST_WIDTH
192
+ })), model.footer && /*#__PURE__*/_react.default.createElement(_compiled.Box, {
193
+ xcss: styles.footer,
194
+ onMouseMove: onFooterItemHover
195
+ }, /*#__PURE__*/_react.default.createElement(_RegisteredInsertMenuItem.RegisteredInsertMenuItem, {
196
+ editorView: editorView,
197
+ id: "".concat(listId, "-").concat(footerItemIndex),
198
+ isOffline: isOffline,
199
+ isSelected: footerItemIndex === selectedItemIndex,
200
+ menuOpenId: menuOpenId,
201
+ onClose: onClose,
202
+ registration: model.footer,
203
+ surfaceContext: surfaceContext
204
+ }))));
205
+ };
@@ -13,6 +13,8 @@ var _configResolver = require("./toolbar-components/config-resolver");
13
13
  var _EmojiButton = require("./toolbar-components/EmojiButton");
14
14
  var _ImageButton = require("./toolbar-components/ImageButton");
15
15
  var _InsertButton = require("./toolbar-components/InsertButton");
16
+ var _RegisteredInsertButton = require("./registered-insert-menu/RegisteredInsertButton");
17
+ var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
16
18
  var _LayoutButton = require("./toolbar-components/LayoutButton");
17
19
  var _MediaButton = require("./toolbar-components/MediaButton");
18
20
  var _MentionButton = require("./toolbar-components/MentionButton");
@@ -263,7 +265,9 @@ var getToolbarComponents = exports.getToolbarComponents = function getToolbarCom
263
265
  if ((_config$insert = config.insert) !== null && _config$insert !== void 0 && _config$insert.enabled) {
264
266
  var createInsertButtonComponent = function createInsertButtonComponent(breakpoint) {
265
267
  return function () {
266
- return /*#__PURE__*/_react.default.createElement(_InsertButton.InsertButton, {
268
+ return (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_slash_command') ? /*#__PURE__*/_react.default.createElement(_RegisteredInsertButton.RegisteredInsertButton, {
269
+ api: api
270
+ }) : /*#__PURE__*/_react.default.createElement(_InsertButton.InsertButton, {
267
271
  api: api,
268
272
  breakpoint: breakpoint,
269
273
  toolbarConfig: config,
@@ -1,12 +1,23 @@
1
- import React from 'react';
1
+ import React, { useCallback } from 'react';
2
2
  import { Popup } from '@atlaskit/editor-common/ui';
3
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
3
4
  import InsertMenu, { DEFAULT_HEIGHT } from '../ElementBrowser/InsertMenu';
5
+ import { RegisteredInsertMenuContent } from '../registered-insert-menu/RegisteredInsertMenuContent';
4
6
  import { DropDownButton } from './dropdown-button';
5
7
  // This determines how the popup should fit. We prefer the insert menu
6
8
  // opening on the bottom as we have a search bar and should only open on
7
9
  // top if there is more than sufficient room.
8
10
  const FIT_HEIGHT_BUFFER = 100;
9
11
  export const BlockInsertElementBrowser = props => {
12
+ const {
13
+ togglePlusMenuVisibility,
14
+ plusButtonRef
15
+ } = props;
16
+ const closeRegisteredMenu = useCallback(() => togglePlusMenuVisibility(), [togglePlusMenuVisibility]);
17
+ const closeRegisteredMenuAndRestoreFocus = useCallback(() => {
18
+ togglePlusMenuVisibility();
19
+ plusButtonRef === null || plusButtonRef === void 0 ? void 0 : plusButtonRef.focus();
20
+ }, [togglePlusMenuVisibility, plusButtonRef]);
10
21
  return /*#__PURE__*/React.createElement(React.Fragment, null, props.open && /*#__PURE__*/React.createElement(Popup, {
11
22
  target: props.plusButtonRef,
12
23
  fitHeight: DEFAULT_HEIGHT + FIT_HEIGHT_BUFFER,
@@ -19,7 +30,15 @@ export const BlockInsertElementBrowser = props => {
19
30
  scrollableElement: props.popupsScrollableElement,
20
31
  preventOverflow: true,
21
32
  alignX: "right"
22
- }, /*#__PURE__*/React.createElement(InsertMenu, {
33
+ }, isExperimentEnabled('platform_editor_slash_command') ? /*#__PURE__*/React.createElement(RegisteredInsertMenuContent, {
34
+ api: props.pluginInjectionApi,
35
+ editorView: props.editorView,
36
+ isOffline: Boolean(props.isEditorOffline),
37
+ onClose: closeRegisteredMenuAndRestoreFocus,
38
+ onDismiss: closeRegisteredMenu,
39
+ onSelect: closeRegisteredMenu,
40
+ target: props.plusButtonRef
41
+ }) : /*#__PURE__*/React.createElement(InsertMenu, {
23
42
  editorView: props.editorView,
24
43
  dropdownItems: props.items,
25
44
  onInsert: props.onInsert,
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
2
3
  import { BlockInsertElementBrowser } from './block-insert-element-browser';
3
4
  import { DropDownButton } from './dropdown-button';
4
5
  export const BlockInsertMenu = props => {
5
- if (props.items.length === 0 && !props.showElementBrowserLink) {
6
+ if (props.items.length === 0 && !props.showElementBrowserLink && !isExperimentEnabled('platform_editor_slash_command')) {
6
7
  return null;
7
8
  }
8
9
  if (props.disabled) {
@@ -36,6 +37,7 @@ export const BlockInsertMenu = props => {
36
37
  spacing: props.spacing,
37
38
  togglePlusMenuVisibility: props.togglePlusMenuVisibility,
38
39
  showElementBrowserLink: props.showElementBrowserLink,
40
+ isEditorOffline: props.isEditorOffline,
39
41
  pluginInjectionApi: props.pluginInjectionApi,
40
42
  isFullPageAppearance: props.isFullPageAppearance
41
43
  });
@@ -18,6 +18,7 @@ import { ToolbarButton } from '@atlaskit/editor-common/ui-menu';
18
18
  import { OutsideClickTargetRefContext, withReactEditorViewOuterListeners as withOuterListeners } from '@atlaskit/editor-common/ui-react';
19
19
  import { akEditorMenuZIndex } from '@atlaskit/editor-shared-styles';
20
20
  import { EmojiPicker as AkEmojiPicker } from '@atlaskit/emoji/picker';
21
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
21
22
  // Ignored via go/ees005
22
23
  // eslint-disable-next-line import/no-namespace
23
24
  import { fg } from '@atlaskit/platform-feature-flags/fg';
@@ -733,7 +734,7 @@ export class ToolbarInsertBlock extends React.PureComponent {
733
734
  const isTableSizeVisible = buttons.some(({
734
735
  value
735
736
  }) => value.name === 'table selector');
736
- if (buttons.length === 0 && dropdownItems.length === 0) {
737
+ if (buttons.length === 0 && dropdownItems.length === 0 && !isExperimentEnabled('platform_editor_slash_command')) {
737
738
  return null;
738
739
  }
739
740
  const toolbarButtons = [];
@@ -831,6 +832,7 @@ export class ToolbarInsertBlock extends React.PureComponent {
831
832
  onInsert: this.insertInsertMenuItem,
832
833
  togglePlusMenuVisibility: this.togglePlusMenuVisibility,
833
834
  showElementBrowserLink: this.props.showElementBrowserLink || false,
835
+ isEditorOffline: this.props.isEditorOffline,
834
836
  pluginInjectionApi: this.props.pluginInjectionApi,
835
837
  isFullPageAppearance: isFullPageAppearance
836
838
  })), (!((_this$props$pluginInj4 = this.props.pluginInjectionApi) !== null && _this$props$pluginInj4 !== void 0 && _this$props$pluginInj4.primaryToolbar) && this.props.showSeparator || isFullPageAppearance && editorExperiment('platform_editor_controls', 'variant1')) && /* eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage */
@@ -0,0 +1,107 @@
1
+ import React, { useCallback, useRef, useState } from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { getAriaKeyshortcuts, insertElements, ToolTipContent } from '@atlaskit/editor-common/keymaps';
4
+ import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
5
+ import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
6
+ import { TOOLBAR_BUTTON_TEST_ID, useEditorToolbar } from '@atlaskit/editor-common/toolbar';
7
+ import { Popup } from '@atlaskit/editor-common/ui';
8
+ import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity/connectivityPluginType';
9
+ import { akEditorMenuZIndex } from '@atlaskit/editor-shared-styles/constants';
10
+ import { AddIcon } from '@atlaskit/editor-toolbar/add-icon';
11
+ import { ToolbarButton } from '@atlaskit/editor-toolbar/toolbar-button';
12
+ import { ToolbarTooltip } from '@atlaskit/editor-toolbar/toolbar-tooltip';
13
+ import { useToolbarUI } from '@atlaskit/editor-toolbar/ui-context';
14
+ import { RegisteredInsertMenuContent } from './RegisteredInsertMenuContent';
15
+ const DEFAULT_MENU_MAX_HEIGHT = 520;
16
+ const FIT_HEIGHT_BUFFER = 100;
17
+ const POPUP_OFFSET = [0, 3];
18
+ /**
19
+ * The toolbar owns its popup lifecycle, but renders the same registered items
20
+ * and menu model as slash command.
21
+ */
22
+ export const RegisteredInsertButton = ({
23
+ api
24
+ }) => {
25
+ const {
26
+ editorView
27
+ } = useEditorToolbar();
28
+ const {
29
+ formatMessage
30
+ } = useIntl();
31
+ const {
32
+ isDisabled,
33
+ popupsBoundariesElement,
34
+ popupsMountPoint,
35
+ popupsScrollableElement
36
+ } = useToolbarUI();
37
+ const [isOpen, setIsOpen] = useState(false);
38
+ const buttonRef = useRef(null);
39
+ const {
40
+ connectivityMode,
41
+ isAllowed
42
+ } = useSharedPluginStateWithSelector(api, ['connectivity', 'typeAhead'], states => {
43
+ var _states$connectivityS, _states$typeAheadStat;
44
+ return {
45
+ connectivityMode: (_states$connectivityS = states.connectivityState) === null || _states$connectivityS === void 0 ? void 0 : _states$connectivityS.mode,
46
+ isAllowed: (_states$typeAheadStat = states.typeAheadState) === null || _states$typeAheadStat === void 0 ? void 0 : _states$typeAheadStat.isAllowed
47
+ };
48
+ });
49
+ const close = useCallback((restoreFocus = false) => {
50
+ setIsOpen(false);
51
+ if (restoreFocus) {
52
+ requestAnimationFrame(() => {
53
+ var _buttonRef$current;
54
+ return (_buttonRef$current = buttonRef.current) === null || _buttonRef$current === void 0 ? void 0 : _buttonRef$current.focus();
55
+ });
56
+ }
57
+ }, []);
58
+ const open = useCallback(() => {
59
+ setIsOpen(true);
60
+ }, []);
61
+ const onPopupUnmount = useCallback(() => {
62
+ // Outside dismissal must not move focus away from the element that was clicked.
63
+ setIsOpen(false);
64
+ }, []);
65
+ const closeAndRestoreFocus = useCallback(() => close(true), [close]);
66
+ const closeForSelection = useCallback(() => close(false), [close]);
67
+ if (!(api !== null && api !== void 0 && api.insertBlock) || !editorView) {
68
+ return null;
69
+ }
70
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ToolbarTooltip, {
71
+ content: /*#__PURE__*/React.createElement(ToolTipContent, {
72
+ description: formatMessage(messages.insertMenu),
73
+ keymap: insertElements
74
+ })
75
+ }, /*#__PURE__*/React.createElement(ToolbarButton, {
76
+ ariaKeyshortcuts: getAriaKeyshortcuts(insertElements),
77
+ iconBefore: /*#__PURE__*/React.createElement(AddIcon, {
78
+ size: "small",
79
+ label: formatMessage(messages.insertMenu)
80
+ }),
81
+ isDisabled: !isAllowed || isDisabled,
82
+ isSelected: isOpen,
83
+ onClick: isOpen ? () => close(true) : open,
84
+ ref: buttonRef,
85
+ testId: TOOLBAR_BUTTON_TEST_ID.INSERT
86
+ })), isOpen && buttonRef.current && /*#__PURE__*/React.createElement(Popup, {
87
+ alignX: "right",
88
+ boundariesElement: popupsBoundariesElement,
89
+ fitHeight: DEFAULT_MENU_MAX_HEIGHT + FIT_HEIGHT_BUFFER,
90
+ fitWidth: 350,
91
+ mountTo: popupsMountPoint,
92
+ offset: POPUP_OFFSET,
93
+ onUnmount: onPopupUnmount,
94
+ preventOverflow: true,
95
+ scrollableElement: popupsScrollableElement,
96
+ target: buttonRef.current,
97
+ zIndex: akEditorMenuZIndex
98
+ }, /*#__PURE__*/React.createElement(RegisteredInsertMenuContent, {
99
+ api: api,
100
+ editorView: editorView,
101
+ isOffline: isOfflineMode(connectivityMode),
102
+ onClose: closeAndRestoreFocus,
103
+ onDismiss: closeForSelection,
104
+ onSelect: closeForSelection,
105
+ target: buttonRef.current
106
+ })));
107
+ };
@@ -0,0 +1,11 @@
1
+ ._2rko12b0{border-radius:var(--ds-radius-small,4px)}
2
+ ._18zrutpp{padding-inline:var(--ds-space-150,9pt)}
3
+ ._1rjcutpp{padding-block:var(--ds-space-150,9pt)}._16qs130s{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #1e1f2126,0 0 1px #1e1f214f)}
4
+ ._18m915vq{overflow-y:hidden}
5
+ ._1bsb1edt{width:350px}
6
+ ._1e0c1txw{display:flex}
7
+ ._1o9zidpf{flex-shrink:0}
8
+ ._1reo15vq{overflow-x:hidden}
9
+ ._2lx21bp4{flex-direction:column}
10
+ ._bfhk1bhr{background-color:var(--ds-surface-overlay,#fff)}
11
+ ._c71l1lk4{max-height:520px}
@@ -0,0 +1,117 @@
1
+ /* RegisteredInsertMenu.tsx generated by @compiled/babel-plugin v3.0.1 */
2
+ import "./RegisteredInsertMenu.compiled.css";
3
+ import { ax, ix } from "@compiled/react/runtime";
4
+ import React, { useCallback, useId, useMemo, useState } from 'react';
5
+ import { getDocument } from '@atlaskit/browser-apis';
6
+ import { useIntl } from 'react-intl';
7
+ import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
8
+ import { buildQuickInsertMenuModel, getMatchingQuickInsertComponents } from '@atlaskit/editor-common/quick-insert/registered-menu-model';
9
+ import { MENU } from '@atlaskit/editor-common/quick-insert/keys';
10
+ import { TYPE_AHEAD_SURFACE_CONTEXT } from '@atlaskit/editor-common/type-ahead-surface-context';
11
+ import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
12
+ import { Box } from '@atlaskit/primitives/compiled';
13
+ import Textfield from '@atlaskit/textfield/text-field';
14
+ import { RegisteredInsertMenuList } from './RegisteredInsertMenuList';
15
+ const DEFAULT_MENU_MAX_HEIGHT = 520;
16
+ const styles = {
17
+ menu: "_2rko12b0 _1reo15vq _18m915vq _bfhk1bhr _16qs130s _1e0c1txw _2lx21bp4 _c71l1lk4 _1bsb1edt",
18
+ search: "_1rjcutpp _18zrutpp _1o9zidpf"
19
+ };
20
+ export const RegisteredInsertMenu = ({
21
+ components,
22
+ editorView,
23
+ isOffline,
24
+ onClose,
25
+ onSelect
26
+ }) => {
27
+ const {
28
+ formatMessage
29
+ } = useIntl();
30
+ const listId = useId();
31
+ const [menuOpenId] = useState(() => Symbol('registered-insert-menu-open'));
32
+ const [query, setQuery] = useState('');
33
+ const [selectedItemIndex, setSelectedItemIndex] = useState(0);
34
+ const [renderedItems, setRenderedItems] = useState({
35
+ startIndex: -1,
36
+ stopIndex: -1
37
+ });
38
+ const surfaceContext = useMemo(() => createSurfaceContext(TYPE_AHEAD_SURFACE_CONTEXT, {
39
+ menuOpenId
40
+ }), [menuOpenId]);
41
+ const model = useMemo(() => query === '' ? buildQuickInsertMenuModel(components, MENU, undefined, surfaceContext) : getMatchingQuickInsertComponents({
42
+ components,
43
+ formatMessage,
44
+ query,
45
+ rootComponent: MENU,
46
+ surfaceContext
47
+ }), [components, formatMessage, query, surfaceContext]);
48
+ const itemCount = useMemo(() => model.sections.reduce((count, [, ...items]) => count + items.length, 0) + (model.footer ? 1 : 0), [model.footer, model.sections]);
49
+ const isActiveItemMounted = selectedItemIndex >= 0 && selectedItemIndex < itemCount && (selectedItemIndex >= renderedItems.startIndex && selectedItemIndex <= renderedItems.stopIndex || Boolean(model.footer) && selectedItemIndex === itemCount - 1);
50
+ const activeItemId = `${listId}-${selectedItemIndex}`;
51
+ const selectNextItem = useCallback(() => {
52
+ setSelectedItemIndex(index => itemCount === 0 ? -1 : (index + 1) % itemCount);
53
+ }, [itemCount]);
54
+ const selectPreviousItem = useCallback(() => {
55
+ setSelectedItemIndex(index => itemCount === 0 ? -1 : index <= 0 ? itemCount - 1 : index - 1);
56
+ }, [itemCount]);
57
+ const selectActiveItem = useCallback(() => {
58
+ if (isActiveItemMounted) {
59
+ var _getDocument, _getDocument$getEleme;
60
+ (_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : (_getDocument$getEleme = _getDocument.getElementById(activeItemId)) === null || _getDocument$getEleme === void 0 ? void 0 : _getDocument$getEleme.click();
61
+ }
62
+ }, [activeItemId, isActiveItemMounted]);
63
+ const onQueryChange = useCallback(event => {
64
+ setQuery(event.currentTarget.value);
65
+ setSelectedItemIndex(0);
66
+ }, []);
67
+ const onKeyDown = useCallback(event => {
68
+ switch (event.key) {
69
+ case 'ArrowDown':
70
+ event.preventDefault();
71
+ selectNextItem();
72
+ break;
73
+ case 'ArrowUp':
74
+ event.preventDefault();
75
+ selectPreviousItem();
76
+ break;
77
+ case 'Enter':
78
+ event.preventDefault();
79
+ selectActiveItem();
80
+ break;
81
+ case 'Escape':
82
+ event.preventDefault();
83
+ onClose();
84
+ break;
85
+ }
86
+ }, [onClose, selectActiveItem, selectNextItem, selectPreviousItem]);
87
+ return /*#__PURE__*/React.createElement(Box, {
88
+ "data-registered-insert-menu": "",
89
+ testId: "registered-insert-menu",
90
+ onKeyDownCapture: onKeyDown,
91
+ xcss: styles.menu
92
+ }, /*#__PURE__*/React.createElement(Box, {
93
+ xcss: styles.search
94
+ }, /*#__PURE__*/React.createElement(Textfield, {
95
+ "aria-activedescendant": isActiveItemMounted ? activeItemId : undefined,
96
+ "aria-controls": listId,
97
+ "aria-expanded": "true",
98
+ autoFocus: true,
99
+ placeholder: "Search",
100
+ role: "combobox",
101
+ value: query,
102
+ onChange: onQueryChange
103
+ })), /*#__PURE__*/React.createElement(RegisteredInsertMenuList, {
104
+ editorView: editorView,
105
+ isOffline: isOffline,
106
+ listId: listId,
107
+ listLabel: formatMessage(messages.insertMenu),
108
+ maxHeight: DEFAULT_MENU_MAX_HEIGHT,
109
+ menuOpenId: menuOpenId,
110
+ model: model,
111
+ onClose: onSelect,
112
+ onItemHover: setSelectedItemIndex,
113
+ onRenderedItemsChange: setRenderedItems,
114
+ selectedItemIndex: selectedItemIndex,
115
+ surfaceContext: surfaceContext
116
+ }));
117
+ };
@@ -0,0 +1,43 @@
1
+ import React, { useCallback, useContext, useState } from 'react';
2
+ import { MENU } from '@atlaskit/editor-common/quick-insert/keys';
3
+ import { PlainOutsideClickTargetRefContext, withOuterListeners } from '@atlaskit/editor-common/ui';
4
+ import { RegisteredInsertMenu } from './RegisteredInsertMenu';
5
+ const RegisteredInsertMenuContainer = ({
6
+ children
7
+ }) => {
8
+ const setOutsideClickTargetRef = useContext(PlainOutsideClickTargetRefContext);
9
+ return /*#__PURE__*/React.createElement("div", {
10
+ ref: setOutsideClickTargetRef
11
+ }, children);
12
+ };
13
+ const RegisteredInsertMenuWithListeners = withOuterListeners(RegisteredInsertMenuContainer);
14
+ export const RegisteredInsertMenuContent = ({
15
+ api,
16
+ editorView,
17
+ isOffline,
18
+ onClose,
19
+ onDismiss,
20
+ onSelect,
21
+ target
22
+ }) => {
23
+ // Keep registrations stable while the open menu is searched or navigated.
24
+ const [components] = useState(() => {
25
+ var _api$uiControlRegistr, _api$uiControlRegistr2;
26
+ return (_api$uiControlRegistr = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(MENU.key)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [];
27
+ });
28
+ const onClickOutside = useCallback(event => {
29
+ if (event.target instanceof Node && target !== null && target !== void 0 && target.contains(event.target)) {
30
+ return;
31
+ }
32
+ onDismiss();
33
+ }, [onDismiss, target]);
34
+ return /*#__PURE__*/React.createElement(RegisteredInsertMenuWithListeners, {
35
+ handleClickOutside: onClickOutside
36
+ }, /*#__PURE__*/React.createElement(RegisteredInsertMenu, {
37
+ components: components,
38
+ editorView: editorView,
39
+ isOffline: isOffline,
40
+ onClose: onClose,
41
+ onSelect: onSelect
42
+ }));
43
+ };
@@ -0,0 +1,49 @@
1
+ import React, { useCallback, useMemo } from 'react';
2
+ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
3
+ import { insertSelectedItem } from '@atlaskit/editor-common/insert';
4
+ import { QuickInsertProvider } from '@atlaskit/editor-common/quick-insert/provider';
5
+ export const RegisteredInsertMenuItem = ({
6
+ editorView,
7
+ id,
8
+ isOffline,
9
+ isSelected,
10
+ menuOpenId,
11
+ onClose,
12
+ registration,
13
+ surfaceContext
14
+ }) => {
15
+ var _registration$compone;
16
+ const Component = (_registration$compone = registration.component) !== null && _registration$compone !== void 0 ? _registration$compone : React.Fragment;
17
+ const select = useCallback(selectionHandler => {
18
+ // Close first so a registered item may safely focus the editor or open its picker.
19
+ onClose();
20
+ queueMicrotask(() => {
21
+ const {
22
+ state
23
+ } = editorView;
24
+ const insert = (content, options = {}) => insertSelectedItem(content, options)(state, state.tr, state.selection.head);
25
+ const transaction = selectionHandler({
26
+ insert,
27
+ source: INPUT_METHOD.INSERT_MENU
28
+ });
29
+ if (transaction) {
30
+ editorView.dispatch(transaction);
31
+ }
32
+ });
33
+ }, [editorView, onClose]);
34
+ const contextValue = useMemo(() => ({
35
+ editorView,
36
+ isOffline,
37
+ item: {
38
+ id,
39
+ isSelected
40
+ },
41
+ menuOpenId,
42
+ select,
43
+ surface: 'toolbar',
44
+ surfaceContext
45
+ }), [editorView, id, isOffline, isSelected, menuOpenId, select, surfaceContext]);
46
+ return /*#__PURE__*/React.createElement(QuickInsertProvider, {
47
+ value: contextValue
48
+ }, /*#__PURE__*/React.createElement(Component, null, null));
49
+ };
@@ -0,0 +1,4 @@
1
+ ._1rjc1b66{padding-block:var(--ds-space-050,4px)}._15a5nqa1{border-top-style:solid}
2
+ ._1i531l7x{border-top-color:var(--ds-border,#0b120e24)}
3
+ ._1o9zidpf{flex-shrink:0}
4
+ ._uwhke4h9{border-top-width:var(--ds-border-width,1px)}