@atlaskit/editor-plugin-insert-block 4.3.2 → 4.3.4

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 (85) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/insertBlockPlugin.js +8 -2
  3. package/dist/cjs/ui/toolbar-components/EmojiButton.js +25 -83
  4. package/dist/cjs/ui/toolbar-components/InsertButton.js +250 -0
  5. package/dist/cjs/ui/toolbar-components/TableSizePicker.js +25 -48
  6. package/dist/cjs/ui/toolbar-components/hooks/useEmojiPickerPopup.js +52 -0
  7. package/dist/cjs/ui/toolbar-components/hooks/useInsertButtonState.js +89 -0
  8. package/dist/cjs/ui/toolbar-components/hooks/usePopupManager.js +65 -0
  9. package/dist/cjs/ui/toolbar-components/hooks/useTableSelectorPopup.js +35 -0
  10. package/dist/cjs/ui/toolbar-components/popups/EmojiPickerPopup.js +53 -0
  11. package/dist/cjs/ui/toolbar-components/popups/TableSelectorPopupWrapper.js +36 -0
  12. package/dist/cjs/ui/toolbar-components/shared/constants.js +18 -0
  13. package/dist/cjs/ui/toolbar-components/shared/types.js +5 -0
  14. package/dist/cjs/ui/toolbar-components.js +66 -2
  15. package/dist/es2019/insertBlockPlugin.js +8 -2
  16. package/dist/es2019/ui/toolbar-components/EmojiButton.js +24 -77
  17. package/dist/es2019/ui/toolbar-components/InsertButton.js +243 -0
  18. package/dist/es2019/ui/toolbar-components/TableSizePicker.js +26 -41
  19. package/dist/es2019/ui/toolbar-components/hooks/useEmojiPickerPopup.js +42 -0
  20. package/dist/es2019/ui/toolbar-components/hooks/useInsertButtonState.js +81 -0
  21. package/dist/es2019/ui/toolbar-components/hooks/usePopupManager.js +50 -0
  22. package/dist/es2019/ui/toolbar-components/hooks/useTableSelectorPopup.js +27 -0
  23. package/dist/es2019/ui/toolbar-components/popups/EmojiPickerPopup.js +47 -0
  24. package/dist/es2019/ui/toolbar-components/popups/TableSelectorPopupWrapper.js +30 -0
  25. package/dist/es2019/ui/toolbar-components/shared/constants.js +12 -0
  26. package/dist/es2019/ui/toolbar-components/shared/types.js +1 -0
  27. package/dist/es2019/ui/toolbar-components.js +63 -3
  28. package/dist/esm/insertBlockPlugin.js +8 -2
  29. package/dist/esm/ui/toolbar-components/EmojiButton.js +26 -83
  30. package/dist/esm/ui/toolbar-components/InsertButton.js +242 -0
  31. package/dist/esm/ui/toolbar-components/TableSizePicker.js +26 -48
  32. package/dist/esm/ui/toolbar-components/hooks/useEmojiPickerPopup.js +45 -0
  33. package/dist/esm/ui/toolbar-components/hooks/useInsertButtonState.js +82 -0
  34. package/dist/esm/ui/toolbar-components/hooks/usePopupManager.js +58 -0
  35. package/dist/esm/ui/toolbar-components/hooks/useTableSelectorPopup.js +28 -0
  36. package/dist/esm/ui/toolbar-components/popups/EmojiPickerPopup.js +46 -0
  37. package/dist/esm/ui/toolbar-components/popups/TableSelectorPopupWrapper.js +29 -0
  38. package/dist/esm/ui/toolbar-components/shared/constants.js +12 -0
  39. package/dist/esm/ui/toolbar-components/shared/types.js +1 -0
  40. package/dist/esm/ui/toolbar-components.js +67 -3
  41. package/dist/types/insertBlockPluginType.d.ts +2 -2
  42. package/dist/types/types/index.d.ts +3 -3
  43. package/dist/types/ui/ElementBrowser/types.d.ts +3 -3
  44. package/dist/types/ui/ToolbarInsertBlock/block-insert-element-browser.d.ts +8 -8
  45. package/dist/types/ui/ToolbarInsertBlock/block-insert-menu.d.ts +12 -12
  46. package/dist/types/ui/ToolbarInsertBlock/create-items.d.ts +24 -24
  47. package/dist/types/ui/ToolbarInsertBlock/dropdown-button.d.ts +4 -4
  48. package/dist/types/ui/ToolbarInsertBlock/index.d.ts +1 -1
  49. package/dist/types/ui/ToolbarInsertBlock/item.d.ts +2 -2
  50. package/dist/types/ui/ToolbarInsertBlock/types.d.ts +36 -36
  51. package/dist/types/ui/toolbar-components/EmojiButton.d.ts +2 -7
  52. package/dist/types/ui/toolbar-components/InsertButton.d.ts +18 -0
  53. package/dist/types/ui/toolbar-components/TableSizePicker.d.ts +3 -5
  54. package/dist/types/ui/toolbar-components/hooks/useEmojiPickerPopup.d.ts +20 -0
  55. package/dist/types/ui/toolbar-components/hooks/useInsertButtonState.d.ts +24 -0
  56. package/dist/types/ui/toolbar-components/hooks/usePopupManager.d.ts +21 -0
  57. package/dist/types/ui/toolbar-components/hooks/useTableSelectorPopup.d.ts +19 -0
  58. package/dist/types/ui/toolbar-components/popups/EmojiPickerPopup.d.ts +16 -0
  59. package/dist/types/ui/toolbar-components/popups/TableSelectorPopupWrapper.d.ts +15 -0
  60. package/dist/types/ui/toolbar-components/shared/constants.d.ts +12 -0
  61. package/dist/types/ui/toolbar-components/shared/types.d.ts +8 -0
  62. package/dist/types/ui/toolbar-components.d.ts +9 -2
  63. package/dist/types-ts4.5/insertBlockPluginType.d.ts +2 -2
  64. package/dist/types-ts4.5/types/index.d.ts +3 -3
  65. package/dist/types-ts4.5/ui/ElementBrowser/types.d.ts +3 -3
  66. package/dist/types-ts4.5/ui/ToolbarInsertBlock/block-insert-element-browser.d.ts +8 -8
  67. package/dist/types-ts4.5/ui/ToolbarInsertBlock/block-insert-menu.d.ts +12 -12
  68. package/dist/types-ts4.5/ui/ToolbarInsertBlock/create-items.d.ts +24 -24
  69. package/dist/types-ts4.5/ui/ToolbarInsertBlock/dropdown-button.d.ts +4 -4
  70. package/dist/types-ts4.5/ui/ToolbarInsertBlock/index.d.ts +1 -1
  71. package/dist/types-ts4.5/ui/ToolbarInsertBlock/item.d.ts +2 -2
  72. package/dist/types-ts4.5/ui/ToolbarInsertBlock/types.d.ts +36 -36
  73. package/dist/types-ts4.5/ui/toolbar-components/EmojiButton.d.ts +2 -7
  74. package/dist/types-ts4.5/ui/toolbar-components/InsertButton.d.ts +18 -0
  75. package/dist/types-ts4.5/ui/toolbar-components/TableSizePicker.d.ts +3 -5
  76. package/dist/types-ts4.5/ui/toolbar-components/hooks/useEmojiPickerPopup.d.ts +20 -0
  77. package/dist/types-ts4.5/ui/toolbar-components/hooks/useInsertButtonState.d.ts +24 -0
  78. package/dist/types-ts4.5/ui/toolbar-components/hooks/usePopupManager.d.ts +21 -0
  79. package/dist/types-ts4.5/ui/toolbar-components/hooks/useTableSelectorPopup.d.ts +19 -0
  80. package/dist/types-ts4.5/ui/toolbar-components/popups/EmojiPickerPopup.d.ts +16 -0
  81. package/dist/types-ts4.5/ui/toolbar-components/popups/TableSelectorPopupWrapper.d.ts +15 -0
  82. package/dist/types-ts4.5/ui/toolbar-components/shared/constants.d.ts +15 -0
  83. package/dist/types-ts4.5/ui/toolbar-components/shared/types.d.ts +8 -0
  84. package/dist/types-ts4.5/ui/toolbar-components.d.ts +9 -2
  85. package/package.json +8 -9
@@ -0,0 +1,243 @@
1
+ import React, { useRef, useState } from 'react';
2
+ import { useIntl } from 'react-intl-next';
3
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
4
+ import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
5
+ import { useEditorToolbar } from '@atlaskit/editor-common/toolbar';
6
+ import { Popup } from '@atlaskit/editor-common/ui';
7
+ import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
8
+ import { akEditorMenuZIndex } from '@atlaskit/editor-shared-styles';
9
+ import { ToolbarButton, ToolbarTooltip, AddIcon, useToolbarUI } from '@atlaskit/editor-toolbar';
10
+ import { fg } from '@atlaskit/platform-feature-flags';
11
+ import InsertMenu, { DEFAULT_HEIGHT } from '../ElementBrowser/InsertMenu';
12
+ import { useEmojiPickerPopup } from './hooks/useEmojiPickerPopup';
13
+ import { useInsertButtonState } from './hooks/useInsertButtonState';
14
+ import { useTableSelectorPopup } from './hooks/useTableSelectorPopup';
15
+ import { EmojiPickerPopup } from './popups/EmojiPickerPopup';
16
+
17
+ // This determines how the popup should fit. We prefer the insert menu
18
+ // opening on the bottom as we have a search bar and should only open on
19
+ // top if there is more than sufficient room.
20
+ const FIT_HEIGHT_BUFFER = 100;
21
+ export const InsertButton = ({
22
+ api,
23
+ showElementBrowserLink = false,
24
+ isFullPageAppearance = false,
25
+ tableSelectorSupported,
26
+ nativeStatusSupported,
27
+ horizontalRuleEnabled,
28
+ expandEnabled,
29
+ insertMenuItems,
30
+ numberOfButtons,
31
+ onInsertBlockType
32
+ }) => {
33
+ const {
34
+ editorView
35
+ } = useEditorToolbar();
36
+ const {
37
+ isDisabled,
38
+ popupsMountPoint,
39
+ popupsBoundariesElement,
40
+ popupsScrollableElement
41
+ } = useToolbarUI();
42
+ const {
43
+ formatMessage
44
+ } = useIntl();
45
+ const [insertMenuOpen, setInsertMenuOpen] = useState(false);
46
+ const insertButtonRef = useRef(null);
47
+ const emojiPickerPopup = useEmojiPickerPopup({
48
+ api,
49
+ buttonRef: insertButtonRef
50
+ });
51
+ const tableSelectorPopup = useTableSelectorPopup({
52
+ api,
53
+ buttonRef: insertButtonRef
54
+ });
55
+ const showMediaPicker = useSharedPluginStateSelector(api, 'media.showMediaPicker');
56
+ const {
57
+ dropdownItems,
58
+ emojiProvider,
59
+ isTypeAheadAllowed
60
+ } = useInsertButtonState({
61
+ api,
62
+ editorView: editorView || undefined,
63
+ horizontalRuleEnabled,
64
+ insertMenuItems,
65
+ nativeStatusSupported,
66
+ numberOfButtons,
67
+ tableSelectorSupported,
68
+ expandEnabled,
69
+ showElementBrowserLink
70
+ });
71
+ if (!(api !== null && api !== void 0 && api.insertBlock)) {
72
+ return null;
73
+ }
74
+ const toggleInsertMenuOpen = newState => {
75
+ setInsertMenuOpen(newState);
76
+ };
77
+ const onPopupUnmount = () => {
78
+ requestAnimationFrame(() => api === null || api === void 0 ? void 0 : api.core.actions.focus());
79
+ };
80
+ const onClick = () => {
81
+ toggleInsertMenuOpen(!insertMenuOpen);
82
+ };
83
+ const onItemActivated = ({
84
+ item,
85
+ inputMethod
86
+ }) => {
87
+ var _api$core, _api$hyperlink, _api$imageUpload, _api$mention, _api$mention$actions, _api$taskDecision, _api$rule, _api$core4, _api$date, _api$date$commands, _api$placeholderText, _api$layout, _api$core5, _api$status, _api$status$commands, _api$expand;
88
+ if (!editorView) {
89
+ return;
90
+ }
91
+ const {
92
+ state,
93
+ dispatch
94
+ } = editorView;
95
+
96
+ // need to do this before inserting nodes so scrollIntoView works properly
97
+ if (!editorView.hasFocus()) {
98
+ editorView.focus();
99
+ }
100
+ switch (item.value.name) {
101
+ case 'link':
102
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$hyperlink = api.hyperlink) === null || _api$hyperlink === void 0 ? void 0 : _api$hyperlink.commands.showLinkToolbar(inputMethod));
103
+ break;
104
+ case 'table':
105
+ // workaround to solve race condition where cursor is not placed correctly inside table
106
+ queueMicrotask(() => {
107
+ var _api$table, _api$table$actions$in, _api$table$actions;
108
+ api === null || api === void 0 ? void 0 : (_api$table = api.table) === null || _api$table === void 0 ? void 0 : (_api$table$actions$in = (_api$table$actions = _api$table.actions).insertTable) === null || _api$table$actions$in === void 0 ? void 0 : _api$table$actions$in.call(_api$table$actions, {
109
+ action: ACTION.INSERTED,
110
+ actionSubject: ACTION_SUBJECT.DOCUMENT,
111
+ actionSubjectId: ACTION_SUBJECT_ID.TABLE,
112
+ attributes: {
113
+ inputMethod
114
+ },
115
+ eventType: EVENT_TYPE.TRACK
116
+ })(state, dispatch);
117
+ });
118
+ break;
119
+ case 'table selector':
120
+ tableSelectorPopup.toggle(inputMethod);
121
+ break;
122
+ case 'image upload':
123
+ if (api !== null && api !== void 0 && (_api$imageUpload = api.imageUpload) !== null && _api$imageUpload !== void 0 && _api$imageUpload.actions.startUpload) {
124
+ api.imageUpload.actions.startUpload()(state, dispatch);
125
+ }
126
+ break;
127
+ case 'media':
128
+ if (showMediaPicker) {
129
+ if (fg('platform_editor_add_media_from_url_rollout')) {
130
+ var _api$core2, _api$mediaInsert;
131
+ api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(api === null || api === void 0 ? void 0 : (_api$mediaInsert = api.mediaInsert) === null || _api$mediaInsert === void 0 ? void 0 : _api$mediaInsert.commands.showMediaInsertPopup());
132
+ } else {
133
+ showMediaPicker();
134
+ }
135
+ }
136
+ break;
137
+ case 'mention':
138
+ api === null || api === void 0 ? void 0 : (_api$mention = api.mention) === null || _api$mention === void 0 ? void 0 : (_api$mention$actions = _api$mention.actions) === null || _api$mention$actions === void 0 ? void 0 : _api$mention$actions.openTypeAhead(inputMethod);
139
+ break;
140
+ case 'emoji':
141
+ emojiPickerPopup.toggle(inputMethod);
142
+ break;
143
+ case 'codeblock':
144
+ case 'blockquote':
145
+ case 'panel':
146
+ onInsertBlockType === null || onInsertBlockType === void 0 ? void 0 : onInsertBlockType(item.value.name)(state, dispatch);
147
+ break;
148
+ case 'action':
149
+ case 'decision':
150
+ const listType = item.value.name === 'action' ? 'taskList' : 'decisionList';
151
+ api === null || api === void 0 ? void 0 : (_api$taskDecision = api.taskDecision) === null || _api$taskDecision === void 0 ? void 0 : _api$taskDecision.actions.insertTaskDecision(listType, inputMethod)(state, dispatch);
152
+ break;
153
+ case 'horizontalrule':
154
+ api === null || api === void 0 ? void 0 : (_api$rule = api.rule) === null || _api$rule === void 0 ? void 0 : _api$rule.actions.insertHorizontalRule(inputMethod)(state, dispatch);
155
+ break;
156
+ case 'macro':
157
+ if (!fg('platform_editor_refactor_view_more')) {
158
+ var _api$core3, _api$quickInsert;
159
+ api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(api === null || api === void 0 ? void 0 : (_api$quickInsert = api.quickInsert) === null || _api$quickInsert === void 0 ? void 0 : _api$quickInsert.commands.openElementBrowserModal);
160
+ }
161
+ break;
162
+ case 'date':
163
+ api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute(api === null || api === void 0 ? void 0 : (_api$date = api.date) === null || _api$date === void 0 ? void 0 : (_api$date$commands = _api$date.commands) === null || _api$date$commands === void 0 ? void 0 : _api$date$commands.insertDate({
164
+ inputMethod
165
+ }));
166
+ break;
167
+ case 'placeholder text':
168
+ api === null || api === void 0 ? void 0 : (_api$placeholderText = api.placeholderText) === null || _api$placeholderText === void 0 ? void 0 : _api$placeholderText.actions.showPlaceholderFloatingToolbar(state, dispatch);
169
+ break;
170
+ case 'layout':
171
+ api === null || api === void 0 ? void 0 : (_api$layout = api.layout) === null || _api$layout === void 0 ? void 0 : _api$layout.actions.insertLayoutColumns(inputMethod)(state, dispatch);
172
+ break;
173
+ case 'status':
174
+ api === null || api === void 0 ? void 0 : (_api$core5 = api.core) === null || _api$core5 === void 0 ? void 0 : _api$core5.actions.execute(api === null || api === void 0 ? void 0 : (_api$status = api.status) === null || _api$status === void 0 ? void 0 : (_api$status$commands = _api$status.commands) === null || _api$status$commands === void 0 ? void 0 : _api$status$commands.insertStatus(inputMethod));
175
+ break;
176
+ case 'expand':
177
+ api === null || api === void 0 ? void 0 : (_api$expand = api.expand) === null || _api$expand === void 0 ? void 0 : _api$expand.actions.insertExpand(state, dispatch);
178
+ break;
179
+ default:
180
+ if (item && item.onClick) {
181
+ item.onClick();
182
+ }
183
+ break;
184
+ }
185
+ toggleInsertMenuOpen(false);
186
+ };
187
+ const onInsert = ({
188
+ item
189
+ }) => {
190
+ onItemActivated({
191
+ item,
192
+ inputMethod: INPUT_METHOD.INSERT_MENU
193
+ });
194
+ };
195
+ const toggleVisibility = () => {
196
+ toggleInsertMenuOpen(!insertMenuOpen);
197
+ };
198
+ return /*#__PURE__*/React.createElement(React.Fragment, null, insertMenuOpen && insertButtonRef.current && editorView && /*#__PURE__*/React.createElement(Popup, {
199
+ target: insertButtonRef.current,
200
+ fitHeight: DEFAULT_HEIGHT + FIT_HEIGHT_BUFFER,
201
+ fitWidth: 350,
202
+ offset: [0, 3],
203
+ mountTo: popupsMountPoint,
204
+ boundariesElement: popupsBoundariesElement,
205
+ scrollableElement: popupsScrollableElement,
206
+ onUnmount: onPopupUnmount,
207
+ focusTrap: true,
208
+ zIndex: akEditorMenuZIndex,
209
+ preventOverflow: true,
210
+ alignX: "right"
211
+ }, /*#__PURE__*/React.createElement(InsertMenu, {
212
+ editorView: editorView,
213
+ dropdownItems: dropdownItems,
214
+ onInsert: onInsert,
215
+ toggleVisiblity: toggleVisibility,
216
+ showElementBrowserLink: showElementBrowserLink,
217
+ pluginInjectionApi: api,
218
+ isFullPageAppearance: isFullPageAppearance
219
+ })), emojiProvider && /*#__PURE__*/React.createElement(EmojiPickerPopup, {
220
+ isOpen: emojiPickerPopup.isOpen,
221
+ targetRef: insertButtonRef,
222
+ emojiProvider: Promise.resolve(emojiProvider),
223
+ onSelection: emojiPickerPopup.handleSelectedEmoji,
224
+ onClickOutside: emojiPickerPopup.handleClickOutside,
225
+ onEscapeKeydown: emojiPickerPopup.handleEscapeKeydown,
226
+ onUnmount: emojiPickerPopup.onPopupUnmount,
227
+ popupsMountPoint: popupsMountPoint,
228
+ popupsBoundariesElement: popupsBoundariesElement,
229
+ popupsScrollableElement: popupsScrollableElement
230
+ }), /*#__PURE__*/React.createElement(ToolbarTooltip, {
231
+ content: formatMessage(messages.insertMenu)
232
+ }, /*#__PURE__*/React.createElement(ToolbarButton, {
233
+ iconBefore: /*#__PURE__*/React.createElement(AddIcon, {
234
+ size: "small",
235
+ label: formatMessage(messages.insertMenu)
236
+ }),
237
+ ariaKeyshortcuts: "/",
238
+ ref: insertButtonRef,
239
+ onClick: onClick,
240
+ isSelected: insertMenuOpen,
241
+ isDisabled: !isTypeAheadAllowed || isDisabled
242
+ })));
243
+ };
@@ -1,11 +1,10 @@
1
- import React, { useRef, useState } from 'react';
1
+ import React, { useRef } from 'react';
2
2
  import { useIntl } from 'react-intl-next';
3
- import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
4
3
  import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
5
4
  import { useEditorToolbar } from '@atlaskit/editor-common/toolbar';
6
- import { TableSelectorPopup } from '@atlaskit/editor-common/ui';
7
5
  import { MoreItemsIcon, ToolbarButton, ToolbarTooltip, useToolbarUI } from '@atlaskit/editor-toolbar';
8
- import { isDetachedElement } from './utils/utils';
6
+ import { useTableSelectorPopup } from './hooks/useTableSelectorPopup';
7
+ import { TableSelectorPopupWrapper } from './popups/TableSelectorPopupWrapper';
9
8
  export const TableSizePicker = ({
10
9
  api,
11
10
  tableSelectorSupported
@@ -16,50 +15,36 @@ export const TableSizePicker = ({
16
15
  const {
17
16
  editorView
18
17
  } = useEditorToolbar();
18
+ const tableSizePickerRef = useRef(null);
19
19
  const {
20
- popupsMountPoint
20
+ popupsMountPoint,
21
+ popupsBoundariesElement,
22
+ popupsScrollableElement
21
23
  } = useToolbarUI();
22
- const [tableSizePickerOpen, setTableSizePickerOpen] = useState(false);
23
- const [isOpenedByKeyboard, setIsOpenedByKeyboard] = useState(false);
24
- const tableSizePickerRef = useRef(null);
24
+ const tableSelectorPopup = useTableSelectorPopup({
25
+ api,
26
+ buttonRef: tableSizePickerRef
27
+ });
25
28
  if (!(editorView !== null && editorView !== void 0 && editorView.state.schema.nodes.table) || !tableSelectorSupported) {
26
29
  return null;
27
30
  }
28
- const handleSelectedTableSize = (rowsCount, colsCount) => {
29
- // workaround to solve race condition where cursor is not placed correctly inside table
30
- queueMicrotask(() => {
31
- var _api$core, _api$table;
32
- api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$table = api.table) === null || _api$table === void 0 ? void 0 : _api$table.commands.insertTableWithSize(rowsCount, colsCount, INPUT_METHOD.PICKER));
33
- });
34
- setTableSizePickerOpen(false);
35
- };
36
- const handleTableSelectorClickOutside = e => {
37
- // Ignore click events for detached elements.
38
- if (e.target instanceof HTMLElement && !isDetachedElement(e.target)) {
39
- setTableSizePickerOpen(false);
40
- }
41
- };
42
- const handleTableSelectorPressEscape = () => {
43
- var _tableSizePickerRef$c;
44
- setTableSizePickerOpen(false);
45
- (_tableSizePickerRef$c = tableSizePickerRef.current) === null || _tableSizePickerRef$c === void 0 ? void 0 : _tableSizePickerRef$c.focus();
46
- };
47
- const onUnmount = () => {
48
- api === null || api === void 0 ? void 0 : api.core.actions.focus();
49
- };
50
31
  const onClick = event => {
51
- setIsOpenedByKeyboard(event.detail === 0 ? true : false);
52
- setTableSizePickerOpen(!tableSizePickerOpen);
32
+ if (event.detail === 0) {
33
+ tableSelectorPopup.handleKeyboardOpen(event);
34
+ }
35
+ tableSelectorPopup.toggle();
53
36
  };
54
- return /*#__PURE__*/React.createElement(React.Fragment, null, tableSizePickerRef.current && tableSizePickerOpen && /*#__PURE__*/React.createElement(TableSelectorPopup, {
55
- allowOutsideSelection: true,
56
- target: tableSizePickerRef.current,
57
- onUnmount: onUnmount,
58
- onSelection: handleSelectedTableSize,
37
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TableSelectorPopupWrapper, {
38
+ isOpen: tableSelectorPopup.isOpen,
39
+ targetRef: tableSizePickerRef,
40
+ isOpenedByKeyboard: tableSelectorPopup.isOpenedByKeyboard,
41
+ onSelection: tableSelectorPopup.handleSelectedTableSize,
42
+ onClickOutside: tableSelectorPopup.handleClickOutside,
43
+ onEscapeKeydown: tableSelectorPopup.handleEscapeKeydown,
44
+ onUnmount: tableSelectorPopup.onPopupUnmount,
59
45
  popupsMountPoint: popupsMountPoint,
60
- handleClickOutside: handleTableSelectorClickOutside,
61
- handleEscapeKeydown: handleTableSelectorPressEscape,
62
- isOpenedByKeyboard: isOpenedByKeyboard
46
+ popupsBoundariesElement: popupsBoundariesElement,
47
+ popupsScrollableElement: popupsScrollableElement
63
48
  }), /*#__PURE__*/React.createElement(ToolbarTooltip, {
64
49
  content: formatMessage(messages.tableSelector)
65
50
  }, /*#__PURE__*/React.createElement(ToolbarButton, {
@@ -67,7 +52,7 @@ export const TableSizePicker = ({
67
52
  label: formatMessage(messages.tableSelector)
68
53
  }),
69
54
  onClick: onClick,
70
- isSelected: tableSizePickerOpen,
55
+ isSelected: tableSelectorPopup.isOpen,
71
56
  ref: tableSizePickerRef
72
57
  })));
73
58
  };
@@ -0,0 +1,42 @@
1
+ import { useCallback } from 'react';
2
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
3
+ import { usePopupManager } from './usePopupManager';
4
+ export const useEmojiPickerPopup = ({
5
+ api,
6
+ buttonRef
7
+ }) => {
8
+ const popupManager = usePopupManager({
9
+ focusTarget: buttonRef,
10
+ analytics: {
11
+ onToggle: isOpen => {
12
+ if (isOpen) {
13
+ var _api$analytics;
14
+ api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.fireAnalyticsEvent({
15
+ action: ACTION.OPENED,
16
+ actionSubject: ACTION_SUBJECT.PICKER,
17
+ actionSubjectId: ACTION_SUBJECT_ID.PICKER_EMOJI,
18
+ attributes: {
19
+ inputMethod: INPUT_METHOD.TOOLBAR
20
+ },
21
+ eventType: EVENT_TYPE.UI
22
+ });
23
+ }
24
+ }
25
+ }
26
+ });
27
+ const handleSelectedEmoji = useCallback(emojiId => {
28
+ var _api$emoji;
29
+ api === null || api === void 0 ? void 0 : api.core.actions.focus();
30
+ api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : (_api$emoji = api.emoji) === null || _api$emoji === void 0 ? void 0 : _api$emoji.commands.insertEmoji(emojiId, INPUT_METHOD.PICKER));
31
+ popupManager.close();
32
+ return true;
33
+ }, [api, popupManager]);
34
+ const onPopupUnmount = useCallback(() => {
35
+ requestAnimationFrame(() => api === null || api === void 0 ? void 0 : api.core.actions.focus());
36
+ }, [api]);
37
+ return {
38
+ ...popupManager,
39
+ handleSelectedEmoji,
40
+ onPopupUnmount
41
+ };
42
+ };
@@ -0,0 +1,81 @@
1
+ import { useIntl } from 'react-intl-next';
2
+ import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
3
+ import { createItems } from '../../ToolbarInsertBlock/create-items';
4
+ export const useInsertButtonState = ({
5
+ api,
6
+ editorView,
7
+ horizontalRuleEnabled,
8
+ insertMenuItems,
9
+ nativeStatusSupported,
10
+ numberOfButtons,
11
+ tableSelectorSupported,
12
+ expandEnabled,
13
+ showElementBrowserLink
14
+ }) => {
15
+ const {
16
+ formatMessage
17
+ } = useIntl();
18
+ const isTypeAheadAllowed = useSharedPluginStateSelector(api, 'typeAhead.isAllowed');
19
+ const imageUploadEnabled = useSharedPluginStateSelector(api, 'imageUpload.enabled');
20
+ const mentionsSupported = !!useSharedPluginStateSelector(api, 'mention.mentionProvider');
21
+ const canInsertMention = useSharedPluginStateSelector(api, 'mention.canInsertMention');
22
+ const dateEnabled = useSharedPluginStateSelector(api, 'date.isInitialised');
23
+ const placeholderTextEnabled = useSharedPluginStateSelector(api, 'placeholderText.allowInserting');
24
+ const mediaAllowsUploads = useSharedPluginStateSelector(api, 'media.allowsUploads');
25
+ const canInsertLink = useSharedPluginStateSelector(api, 'hyperlink.canInsertLink');
26
+ const activeLinkMark = useSharedPluginStateSelector(api, 'hyperlink.activeLinkMark');
27
+ const connectivityMode = useSharedPluginStateSelector(api, 'connectivity.mode');
28
+ const emojiProvider = useSharedPluginStateSelector(api, 'emoji.emojiProvider');
29
+ const availableWrapperBlockTypes = useSharedPluginStateSelector(api, 'blockType.availableWrapperBlockTypes');
30
+
31
+ // Computed values
32
+ const mediaUploadsEnabled = mediaAllowsUploads;
33
+ const mediaSupported = mediaAllowsUploads !== undefined;
34
+ const isEditorOffline = connectivityMode === 'offline';
35
+ const imageUploadSupported = !!(api !== null && api !== void 0 && api.imageUpload);
36
+ const mentionsDisabled = !canInsertMention;
37
+ const linkSupported = canInsertLink !== undefined;
38
+ const linkDisabled = !canInsertLink || !!activeLinkMark;
39
+ const emojiDisabled = !emojiProvider;
40
+ const actionSupported = !!(editorView !== null && editorView !== void 0 && editorView.state.schema.nodes.taskItem);
41
+ const decisionSupported = !!(editorView !== null && editorView !== void 0 && editorView.state.schema.nodes.decisionItem);
42
+ const layoutSectionEnabled = !!(api !== null && api !== void 0 && api.layout);
43
+ const [, dropdownItems] = editorView !== null && editorView !== void 0 && editorView.state.schema ? createItems({
44
+ isTypeAheadAllowed: isTypeAheadAllowed,
45
+ tableSupported: !!(editorView !== null && editorView !== void 0 && editorView.state.schema.nodes.table),
46
+ tableSelectorSupported,
47
+ mediaUploadsEnabled,
48
+ mediaSupported,
49
+ isEditorOffline,
50
+ imageUploadSupported,
51
+ imageUploadEnabled,
52
+ mentionsSupported,
53
+ mentionsDisabled,
54
+ actionSupported,
55
+ decisionSupported,
56
+ linkSupported,
57
+ linkDisabled,
58
+ emojiDisabled,
59
+ hasEmojiPlugin: !!(api !== null && api !== void 0 && api.emoji),
60
+ hasMentionsPlugin: !!(api !== null && api !== void 0 && api.mention),
61
+ hasMediaPlugin: !!(api !== null && api !== void 0 && api.media),
62
+ nativeStatusSupported,
63
+ dateEnabled,
64
+ placeholderTextEnabled,
65
+ horizontalRuleEnabled,
66
+ layoutSectionEnabled,
67
+ expandEnabled,
68
+ showElementBrowserLink,
69
+ emojiProvider,
70
+ availableWrapperBlockTypes,
71
+ insertMenuItems,
72
+ schema: editorView === null || editorView === void 0 ? void 0 : editorView.state.schema,
73
+ numberOfButtons: numberOfButtons || 0,
74
+ formatMessage
75
+ }) : [, []];
76
+ return {
77
+ dropdownItems,
78
+ emojiProvider,
79
+ isTypeAheadAllowed
80
+ };
81
+ };
@@ -0,0 +1,50 @@
1
+ import { useState, useCallback } from 'react';
2
+ import { isDetachedElement } from '../utils/utils';
3
+ export const usePopupManager = (config = {}) => {
4
+ const [isOpen, setIsOpen] = useState(false);
5
+ const [isOpenedByKeyboard, setIsOpenedByKeyboard] = useState(false);
6
+ const toggle = useCallback(inputMethod => {
7
+ var _config$analytics, _config$analytics$onT;
8
+ const newState = !isOpen;
9
+ setIsOpen(newState);
10
+ if (newState) {
11
+ var _config$onOpen;
12
+ (_config$onOpen = config.onOpen) === null || _config$onOpen === void 0 ? void 0 : _config$onOpen.call(config, inputMethod);
13
+ } else {
14
+ var _config$onClose;
15
+ (_config$onClose = config.onClose) === null || _config$onClose === void 0 ? void 0 : _config$onClose.call(config);
16
+ }
17
+ (_config$analytics = config.analytics) === null || _config$analytics === void 0 ? void 0 : (_config$analytics$onT = _config$analytics.onToggle) === null || _config$analytics$onT === void 0 ? void 0 : _config$analytics$onT.call(_config$analytics, newState, inputMethod);
18
+ }, [isOpen, config]);
19
+ const close = useCallback(() => {
20
+ var _config$onClose2, _config$analytics2, _config$analytics2$on;
21
+ setIsOpen(false);
22
+ (_config$onClose2 = config.onClose) === null || _config$onClose2 === void 0 ? void 0 : _config$onClose2.call(config);
23
+ (_config$analytics2 = config.analytics) === null || _config$analytics2 === void 0 ? void 0 : (_config$analytics2$on = _config$analytics2.onToggle) === null || _config$analytics2$on === void 0 ? void 0 : _config$analytics2$on.call(_config$analytics2, false);
24
+ }, [config]);
25
+ const handleEscapeKeydown = useCallback(() => {
26
+ var _config$focusTarget, _config$focusTarget$c;
27
+ close();
28
+ (_config$focusTarget = config.focusTarget) === null || _config$focusTarget === void 0 ? void 0 : (_config$focusTarget$c = _config$focusTarget.current) === null || _config$focusTarget$c === void 0 ? void 0 : _config$focusTarget$c.focus();
29
+ }, [close, config.focusTarget]);
30
+ const handleClickOutside = useCallback(e => {
31
+ if (e.target instanceof HTMLElement && !isDetachedElement(e.target)) {
32
+ close();
33
+ }
34
+ }, [close]);
35
+ const handleKeyboardOpen = useCallback(event => {
36
+ if (event.key === 'Enter' || event.key === ' ') {
37
+ setIsOpenedByKeyboard(true);
38
+ event.preventDefault();
39
+ }
40
+ }, []);
41
+ return {
42
+ isOpen,
43
+ isOpenedByKeyboard,
44
+ toggle,
45
+ close,
46
+ handleEscapeKeydown,
47
+ handleClickOutside,
48
+ handleKeyboardOpen
49
+ };
50
+ };
@@ -0,0 +1,27 @@
1
+ import { useCallback } from 'react';
2
+ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
3
+ import { usePopupManager } from './usePopupManager';
4
+ export const useTableSelectorPopup = ({
5
+ api,
6
+ buttonRef
7
+ }) => {
8
+ const popupManager = usePopupManager({
9
+ focusTarget: buttonRef
10
+ });
11
+ const handleSelectedTableSize = useCallback((rowsCount, colsCount) => {
12
+ // workaround to solve race condition where cursor is not placed correctly inside table
13
+ queueMicrotask(() => {
14
+ var _api$core, _api$table;
15
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$table = api.table) === null || _api$table === void 0 ? void 0 : _api$table.commands.insertTableWithSize(rowsCount, colsCount, INPUT_METHOD.PICKER));
16
+ });
17
+ popupManager.close();
18
+ }, [api, popupManager]);
19
+ const onPopupUnmount = useCallback(() => {
20
+ api === null || api === void 0 ? void 0 : api.core.actions.focus();
21
+ }, [api]);
22
+ return {
23
+ ...popupManager,
24
+ handleSelectedTableSize,
25
+ onPopupUnmount
26
+ };
27
+ };
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import { Popup } from '@atlaskit/editor-common/ui';
3
+ import { OutsideClickTargetRefContext, withReactEditorViewOuterListeners as withOuterListeners } from '@atlaskit/editor-common/ui-react';
4
+ import { akEditorMenuZIndex } from '@atlaskit/editor-shared-styles';
5
+ import { EmojiPicker as AkEmojiPicker } from '@atlaskit/emoji/picker';
6
+ const EmojiPicker = props => {
7
+ const setOutsideClickTargetRef = React.useContext(OutsideClickTargetRefContext);
8
+ return /*#__PURE__*/React.createElement(AkEmojiPicker, {
9
+ onPickerRef: setOutsideClickTargetRef,
10
+ emojiProvider: props.emojiProvider,
11
+ onSelection: props.onSelection
12
+ });
13
+ };
14
+ const EmojiPickerWithListeners = withOuterListeners(EmojiPicker);
15
+ export const EmojiPickerPopup = ({
16
+ isOpen,
17
+ targetRef,
18
+ emojiProvider,
19
+ onSelection,
20
+ onClickOutside,
21
+ onEscapeKeydown,
22
+ onUnmount,
23
+ popupsMountPoint,
24
+ popupsBoundariesElement,
25
+ popupsScrollableElement
26
+ }) => {
27
+ if (!isOpen || !targetRef.current || !emojiProvider) {
28
+ return null;
29
+ }
30
+ return /*#__PURE__*/React.createElement(Popup, {
31
+ target: targetRef.current,
32
+ fitHeight: 350,
33
+ fitWidth: 350,
34
+ offset: [0, 3],
35
+ mountTo: popupsMountPoint,
36
+ boundariesElement: popupsBoundariesElement,
37
+ scrollableElement: popupsScrollableElement,
38
+ onUnmount: onUnmount,
39
+ focusTrap: true,
40
+ zIndex: akEditorMenuZIndex
41
+ }, /*#__PURE__*/React.createElement(EmojiPickerWithListeners, {
42
+ emojiProvider: emojiProvider,
43
+ onSelection: onSelection,
44
+ handleClickOutside: onClickOutside,
45
+ handleEscapeKeydown: onEscapeKeydown
46
+ }));
47
+ };
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { TableSelectorPopup } from '@atlaskit/editor-common/ui';
3
+ export const TableSelectorPopupWrapper = ({
4
+ isOpen,
5
+ targetRef,
6
+ isOpenedByKeyboard,
7
+ onSelection,
8
+ onClickOutside,
9
+ onEscapeKeydown,
10
+ onUnmount,
11
+ popupsMountPoint,
12
+ popupsBoundariesElement,
13
+ popupsScrollableElement
14
+ }) => {
15
+ if (!isOpen || !targetRef.current) {
16
+ return null;
17
+ }
18
+ return /*#__PURE__*/React.createElement(TableSelectorPopup, {
19
+ allowOutsideSelection: true,
20
+ target: targetRef.current,
21
+ onUnmount: onUnmount,
22
+ onSelection: onSelection,
23
+ popupsMountPoint: popupsMountPoint,
24
+ popupsBoundariesElement: popupsBoundariesElement,
25
+ popupsScrollableElement: popupsScrollableElement,
26
+ handleClickOutside: onClickOutside,
27
+ handleEscapeKeydown: onEscapeKeydown,
28
+ isOpenedByKeyboard: isOpenedByKeyboard
29
+ });
30
+ };
@@ -0,0 +1,12 @@
1
+ export const POPUP_Z_INDEX = 'akEditorMenuZIndex';
2
+ export const POPUP_DIMENSIONS = {
3
+ EMOJI_PICKER: {
4
+ fitHeight: 350,
5
+ fitWidth: 350,
6
+ offset: [0, 3]
7
+ }
8
+ };
9
+ export const FOCUS_DELAY = {
10
+ ANIMATION_FRAME: 'requestAnimationFrame',
11
+ MICROTASK: 'queueMicrotask'
12
+ };
@@ -0,0 +1 @@
1
+ export {};