@atlaskit/editor-plugin-insert-block 1.13.0 → 1.14.1

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 (30) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/cjs/plugin.js +23 -3
  3. package/dist/cjs/ui/ElementBrowser/InsertMenu.js +47 -13
  4. package/dist/cjs/ui/ElementRail/index.js +186 -2
  5. package/dist/cjs/ui/ElementRail/useInsertMenuRailItems.js +63 -0
  6. package/dist/cjs/ui/templateOptions.js +128 -57
  7. package/dist/cjs/ui/templates.js +1130 -0
  8. package/dist/es2019/plugin.js +23 -3
  9. package/dist/es2019/ui/ElementBrowser/InsertMenu.js +61 -26
  10. package/dist/es2019/ui/ElementRail/index.js +189 -1
  11. package/dist/es2019/ui/ElementRail/useInsertMenuRailItems.js +54 -0
  12. package/dist/es2019/ui/templateOptions.js +78 -11
  13. package/dist/es2019/ui/templates.js +1118 -0
  14. package/dist/esm/plugin.js +23 -3
  15. package/dist/esm/ui/ElementBrowser/InsertMenu.js +47 -13
  16. package/dist/esm/ui/ElementRail/index.js +185 -2
  17. package/dist/esm/ui/ElementRail/useInsertMenuRailItems.js +56 -0
  18. package/dist/esm/ui/templateOptions.js +128 -57
  19. package/dist/esm/ui/templates.js +1124 -0
  20. package/dist/types/ui/ElementRail/index.d.ts +7 -4
  21. package/dist/types/ui/ElementRail/useInsertMenuRailItems.d.ts +4 -0
  22. package/dist/types/ui/ToolbarInsertBlock/create-items.d.ts +1 -1
  23. package/dist/types/ui/templateOptions.d.ts +3 -1
  24. package/dist/types/ui/templates.d.ts +522 -0
  25. package/dist/types-ts4.5/ui/ElementRail/index.d.ts +7 -4
  26. package/dist/types-ts4.5/ui/ElementRail/useInsertMenuRailItems.d.ts +4 -0
  27. package/dist/types-ts4.5/ui/ToolbarInsertBlock/create-items.d.ts +1 -1
  28. package/dist/types-ts4.5/ui/templateOptions.d.ts +3 -1
  29. package/dist/types-ts4.5/ui/templates.d.ts +522 -0
  30. package/package.json +6 -4
@@ -4,6 +4,7 @@ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
4
4
  import { contentAllowedInCodeBlock, shouldSplitSelectedNodeOnNodeInsertion } from '@atlaskit/editor-common/insert';
5
5
  import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
6
6
  import { WithProviders } from '@atlaskit/editor-common/provider-factory';
7
+ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
7
8
  import { ToolbarSize } from '@atlaskit/editor-common/types';
8
9
  import { getWrappingOptions } from '@atlaskit/editor-common/utils';
9
10
  import { BLOCK_QUOTE, CODE_BLOCK, PANEL } from '@atlaskit/editor-plugin-block-type/consts';
@@ -54,6 +55,9 @@ export const insertBlockPlugin = ({
54
55
  const toggleDropdownMenuOptionsRef = {
55
56
  current: null
56
57
  };
58
+ const editorViewRef = {
59
+ current: null
60
+ };
57
61
  const registerToggleDropdownMenuOptions = cb => {
58
62
  toggleDropdownMenuOptionsRef.current = cb;
59
63
  return () => {
@@ -120,6 +124,17 @@ export const insertBlockPlugin = ({
120
124
  return [{
121
125
  name: 'elementBrowserPmPlugin',
122
126
  plugin: () => elementBrowserPmPlugin()
127
+ }, {
128
+ name: 'elementBrowserEditorViewRef',
129
+ plugin: () => {
130
+ return new SafePlugin({
131
+ view: editorView => {
132
+ // Workaround - need reference to editorView for contextPanel component
133
+ editorViewRef.current = editorView;
134
+ return {};
135
+ }
136
+ });
137
+ }
123
138
  }];
124
139
  },
125
140
  pluginsOptions: {
@@ -189,10 +204,13 @@ export const insertBlockPlugin = ({
189
204
  // If we decide to ship the feature, we will consider a separate plugin if needed.
190
205
  // Experiment one-pager: https://hello.atlassian.net/wiki/spaces/ETM/pages/3983684902/Experiment+Drive+element+usage+via+element+templates
191
206
  quickInsert: () => {
192
- if (editorExperiment('element-level-templates', true, {
207
+ var _options$UNSAFE_edito;
208
+ if (
209
+ // @ts-ignore
210
+ ['full-page', 'full-width'].includes((_options$UNSAFE_edito = options.UNSAFE_editorAppearance) !== null && _options$UNSAFE_edito !== void 0 ? _options$UNSAFE_edito : '') && editorExperiment('element-level-templates', true, {
193
211
  exposure: true
194
212
  })) {
195
- return templateOptions;
213
+ return templateOptions(api);
196
214
  }
197
215
  return [];
198
216
  }
@@ -211,8 +229,10 @@ export const insertBlockPlugin = ({
211
229
  // api.getSharedState() will have an outdated reference to editorState on first mount of this component
212
230
  // so instead just rely on plugin key as we don't need to be reactive to changes here
213
231
  const pluginState = elementBrowserPmKey.getState(state);
214
- if (pluginState !== null && pluginState !== void 0 && pluginState.menuBrowserOpen) {
232
+ if (pluginState !== null && pluginState !== void 0 && pluginState.menuBrowserOpen && editorViewRef.current) {
215
233
  return /*#__PURE__*/React.createElement(InsertMenuRail, {
234
+ editorView: editorViewRef.current,
235
+ options: options,
216
236
  api: api
217
237
  });
218
238
  }
@@ -16,6 +16,7 @@ import { withReactEditorViewOuterListeners as withOuterListeners } from '@atlask
16
16
  // eslint-disable-next-line @atlassian/tangerine/import/entry-points
17
17
  import { borderRadius } from '@atlaskit/theme';
18
18
  import { N0, N30A, N60A } from '@atlaskit/theme/colors';
19
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
19
20
  const InsertMenu = ({
20
21
  editorView,
21
22
  dropdownItems,
@@ -24,7 +25,7 @@ const InsertMenu = ({
24
25
  toggleVisiblity,
25
26
  pluginInjectionApi
26
27
  }) => {
27
- var _pluginInjectionApi$q6, _pluginInjectionApi$q7, _pluginInjectionApi$q8;
28
+ var _pluginInjectionApi$q7, _pluginInjectionApi$q8, _pluginInjectionApi$q9;
28
29
  const [itemCount, setItemCount] = useState(0);
29
30
  const transform = useCallback(item => ({
30
31
  title: item.content,
@@ -47,12 +48,19 @@ const InsertMenu = ({
47
48
  const quickInsertDropdownItems = dropdownItems.map(transform);
48
49
  const viewMoreItem = showElementBrowserLink ? quickInsertDropdownItems.pop() : undefined;
49
50
  const onInsertItem = useCallback(item => {
50
- var _pluginInjectionApi$q;
51
51
  toggleVisiblity();
52
52
  if (!editorView.hasFocus()) {
53
53
  editorView.focus();
54
54
  }
55
- pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q === void 0 ? void 0 : _pluginInjectionApi$q.actions.insertItem(item, INPUT_METHOD.TOOLBAR)(editorView.state, editorView.dispatch);
55
+ if (editorExperiment('insert-menu-in-right-rail', true)) {
56
+ var _pluginInjectionApi$q;
57
+ pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q === void 0 ? void 0 : _pluginInjectionApi$q.actions.insertItem(item,
58
+ // @ts-expect-error
59
+ INPUT_METHOD.INSERT_MENU_RIGHT_RAIL)(editorView.state, editorView.dispatch);
60
+ } else {
61
+ var _pluginInjectionApi$q2;
62
+ pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q2 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q2 === void 0 ? void 0 : _pluginInjectionApi$q2.actions.insertItem(item, INPUT_METHOD.TOOLBAR)(editorView.state, editorView.dispatch);
63
+ }
56
64
  }, [editorView, toggleVisiblity, pluginInjectionApi]);
57
65
  const getItems = useCallback((query, category) => {
58
66
  let result;
@@ -63,23 +71,35 @@ const InsertMenu = ({
63
71
  * @see above transform function for more details.
64
72
  */
65
73
  if (query) {
66
- var _pluginInjectionApi$q2, _pluginInjectionApi$q3;
67
- result = (_pluginInjectionApi$q2 = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q3 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q3 === void 0 ? void 0 : _pluginInjectionApi$q3.actions.getSuggestions({
74
+ var _pluginInjectionApi$q3, _pluginInjectionApi$q4;
75
+ result = (_pluginInjectionApi$q3 = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q4 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q4 === void 0 ? void 0 : _pluginInjectionApi$q4.actions.getSuggestions({
68
76
  query,
69
77
  category
70
- })) !== null && _pluginInjectionApi$q2 !== void 0 ? _pluginInjectionApi$q2 : [];
78
+ })) !== null && _pluginInjectionApi$q3 !== void 0 ? _pluginInjectionApi$q3 : [];
71
79
  } else {
72
- var _pluginInjectionApi$q4, _pluginInjectionApi$q5;
73
- const featuredQuickInsertSuggestions = (_pluginInjectionApi$q4 = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q5 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q5 === void 0 ? void 0 : _pluginInjectionApi$q5.actions.getSuggestions({
80
+ var _pluginInjectionApi$q5, _pluginInjectionApi$q6;
81
+ const featuredQuickInsertSuggestions = (_pluginInjectionApi$q5 = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q6 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q6 === void 0 ? void 0 : _pluginInjectionApi$q6.actions.getSuggestions({
74
82
  category,
75
- featuredItems: true
76
- })) !== null && _pluginInjectionApi$q4 !== void 0 ? _pluginInjectionApi$q4 : [];
77
- result = quickInsertDropdownItems.concat(featuredQuickInsertSuggestions);
83
+ featuredItems: true,
84
+ // @ts-ignore
85
+ templateItems: editorExperiment('element-level-templates', true)
86
+ })) !== null && _pluginInjectionApi$q5 !== void 0 ? _pluginInjectionApi$q5 : [];
87
+ if (editorExperiment('element-level-templates', true)) {
88
+ // Make sure template options appear as top 5 items
89
+ featuredQuickInsertSuggestions.sort((a, b) => {
90
+ var _b$priority, _a$priority;
91
+ return ((_b$priority = b.priority) !== null && _b$priority !== void 0 ? _b$priority : 0) - ((_a$priority = a.priority) !== null && _a$priority !== void 0 ? _a$priority : 0);
92
+ });
93
+ const templateItems = featuredQuickInsertSuggestions.splice(0, 5);
94
+ result = [...templateItems, ...quickInsertDropdownItems, ...featuredQuickInsertSuggestions];
95
+ } else {
96
+ result = quickInsertDropdownItems.concat(featuredQuickInsertSuggestions);
97
+ }
78
98
  }
79
99
  setItemCount(result.length);
80
100
  return result;
81
- }, [pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q6 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q6 === void 0 ? void 0 : _pluginInjectionApi$q6.actions, quickInsertDropdownItems]);
82
- const emptyStateHandler = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q7 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q7 === void 0 ? void 0 : (_pluginInjectionApi$q8 = _pluginInjectionApi$q7.sharedState.currentState()) === null || _pluginInjectionApi$q8 === void 0 ? void 0 : _pluginInjectionApi$q8.emptyStateHandler;
101
+ }, [pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q7 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q7 === void 0 ? void 0 : _pluginInjectionApi$q7.actions, quickInsertDropdownItems]);
102
+ const emptyStateHandler = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q8 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q8 === void 0 ? void 0 : (_pluginInjectionApi$q9 = _pluginInjectionApi$q8.sharedState.currentState()) === null || _pluginInjectionApi$q9 === void 0 ? void 0 : _pluginInjectionApi$q9.emptyStateHandler;
83
103
  return (
84
104
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
85
105
  jsx("div", {
@@ -129,21 +149,36 @@ const getInsertMenuHeight = ({
129
149
  }
130
150
  return 560; // For showing 6 Elements.
131
151
  };
132
- const insertMenuWrapper = itemCount => css({
133
- display: 'flex',
134
- flexDirection: 'column',
135
- width: '320px',
136
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
137
- height: `${getInsertMenuHeight({
138
- itemCount
139
- })}px`,
140
- backgroundColor: `${`var(--ds-surface-overlay, ${N0})`}`,
141
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
142
- borderRadius: `${borderRadius()}px`,
143
- boxShadow: `${`var(--ds-shadow-overlay, ${`0 0 0 1px ${N30A},
152
+ const insertMenuWrapper = itemCount => {
153
+ if (editorExperiment('insert-menu-in-right-rail', true)) {
154
+ return css({
155
+ display: 'flex',
156
+ flexDirection: 'column',
157
+ width: '310px',
158
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
159
+ height: 'calc(100% - 32px)',
160
+ margin: `0 -10px`,
161
+ backgroundColor: `${`var(--ds-surface-overlay, ${N0})`}`,
162
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
163
+ borderRadius: `${borderRadius()}px`
164
+ });
165
+ }
166
+ return css({
167
+ display: 'flex',
168
+ flexDirection: 'column',
169
+ width: '320px',
170
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
171
+ height: `${getInsertMenuHeight({
172
+ itemCount
173
+ })}px`,
174
+ backgroundColor: `${`var(--ds-surface-overlay, ${N0})`}`,
175
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
176
+ borderRadius: `${borderRadius()}px`,
177
+ boxShadow: `${`var(--ds-shadow-overlay, ${`0 0 0 1px ${N30A},
144
178
  0 2px 1px ${N30A},
145
179
  0 0 20px -6px ${N60A}`})`}`
146
- });
180
+ });
181
+ };
147
182
  const flexWrapperStyles = css({
148
183
  display: 'flex',
149
184
  flex: 1,
@@ -1,10 +1,198 @@
1
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
1
2
  import React from 'react';
3
+ import { useIntl } from 'react-intl-next';
4
+ import { IconButton } from '@atlaskit/button/new';
5
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
6
+ import { toolbarInsertBlockMessages } from '@atlaskit/editor-common/messages';
7
+ import Heading from '@atlaskit/heading';
8
+ import CrossIcon from '@atlaskit/icon/glyph/cross';
9
+ import { Box, xcss } from '@atlaskit/primitives';
10
+ import { toggleInsertMenuRightRail } from '../../pm-plugins/commands';
11
+ import InsertMenu from '../ElementBrowser/InsertMenu';
12
+ import { useInsertMenuRailItems } from './useInsertMenuRailItems';
13
+ const panelWrapper = xcss({
14
+ height: '100%'
15
+ });
16
+ const panelContentHeader = xcss({
17
+ height: '32px',
18
+ display: 'flex',
19
+ justifyContent: 'space-between',
20
+ alignItems: 'center'
21
+ });
22
+
2
23
  /**
3
24
  * For insert menu in right rail experiment
4
25
  * - Clean up ticket ED-24801
5
26
  */
6
27
  export const InsertMenuRail = ({
28
+ editorView,
29
+ options,
7
30
  api
8
31
  }) => {
9
- return /*#__PURE__*/React.createElement("div", null);
32
+ const dropdownItems = useInsertMenuRailItems(editorView, options, api);
33
+ const {
34
+ formatMessage
35
+ } = useIntl();
36
+ const onInsert = ({
37
+ item
38
+ }) => {
39
+ var _api$core, _api$hyperlink, _api$imageUpload, _api$media, _api$mention, _api$emoji, _api$codeBlock, _api$blockType, _api$panel, _api$taskDecision, _api$taskDecision2, _api$rule, _api$core2, _api$quickInsert, _api$core3, _api$date, _api$date$commands, _api$placeholderText, _api$layout, _api$core4, _api$status, _api$status$commands;
40
+ const {
41
+ state,
42
+ dispatch
43
+ } = editorView;
44
+ let inputMethod = INPUT_METHOD.INSERT_MENU_RIGHT_RAIL;
45
+ if (!api) {
46
+ return;
47
+ }
48
+ if (!editorView.hasFocus()) {
49
+ editorView.focus();
50
+ }
51
+
52
+ // Below is duplicated from ToolbarInsertBlock/index.tsx - this function is only called
53
+ // for BlockMenuItem items, which are rendered in the insert menu when no search has been performed.
54
+ // When a search is performed, the list will be filled by QuickInsertItems, which handle their own insertion.
55
+ switch (item.value.name) {
56
+ case 'link':
57
+ // @ts-expect-error
58
+ (_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));
59
+ break;
60
+ case 'table':
61
+ // workaround to solve race condition where cursor is not placed correctly inside table
62
+ queueMicrotask(() => {
63
+ var _api$table, _api$table$actions$in, _api$table$actions;
64
+ // @ts-expect-error
65
+ (_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, {
66
+ action: ACTION.INSERTED,
67
+ actionSubject: ACTION_SUBJECT.DOCUMENT,
68
+ actionSubjectId: ACTION_SUBJECT_ID.TABLE,
69
+ attributes: {
70
+ inputMethod
71
+ },
72
+ eventType: EVENT_TYPE.TRACK
73
+ })(state, dispatch);
74
+ });
75
+ break;
76
+ case 'image upload':
77
+ (_api$imageUpload = api.imageUpload) === null || _api$imageUpload === void 0 ? void 0 : _api$imageUpload.actions.startUpload()(state, dispatch);
78
+ break;
79
+ case 'media':
80
+ const mediaState = (_api$media = api.media) === null || _api$media === void 0 ? void 0 : _api$media.sharedState.currentState();
81
+ if (mediaState) {
82
+ var _api$analytics;
83
+ mediaState.showMediaPicker();
84
+ // @ts-expect-error
85
+ (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.attachAnalyticsEvent({
86
+ action: ACTION.OPENED,
87
+ actionSubject: ACTION_SUBJECT.PICKER,
88
+ actionSubjectId: ACTION_SUBJECT_ID.PICKER_CLOUD,
89
+ attributes: {
90
+ inputMethod
91
+ },
92
+ eventType: EVENT_TYPE.UI
93
+ });
94
+ }
95
+ break;
96
+ case 'mention':
97
+ const pluginState = (_api$mention = api.mention) === null || _api$mention === void 0 ? void 0 : _api$mention.sharedState.currentState();
98
+ if (pluginState && pluginState.canInsertMention) {
99
+ var _api$mention2, _api$mention2$actions;
100
+ // @ts-expect-error
101
+ (_api$mention2 = api.mention) === null || _api$mention2 === void 0 ? void 0 : (_api$mention2$actions = _api$mention2.actions) === null || _api$mention2$actions === void 0 ? void 0 : _api$mention2$actions.openTypeAhead(inputMethod);
102
+ }
103
+ break;
104
+ case 'emoji':
105
+ // @ts-expect-error
106
+ (_api$emoji = api.emoji) === null || _api$emoji === void 0 ? void 0 : _api$emoji.actions.openTypeAhead(inputMethod);
107
+ break;
108
+ case 'codeblock':
109
+ (_api$codeBlock = api.codeBlock) === null || _api$codeBlock === void 0 ? void 0 : _api$codeBlock.actions.insertCodeBlock(inputMethod);
110
+ break;
111
+ case 'blockquote':
112
+ // @ts-expect-error
113
+ (_api$blockType = api.blockType) === null || _api$blockType === void 0 ? void 0 : _api$blockType.actions.insertBlockQuote(inputMethod);
114
+ break;
115
+ case 'panel':
116
+ (_api$panel = api.panel) === null || _api$panel === void 0 ? void 0 : _api$panel.actions.insertPanel(inputMethod);
117
+ break;
118
+ case 'action':
119
+ // @ts-expect-error
120
+ (_api$taskDecision = api.taskDecision) === null || _api$taskDecision === void 0 ? void 0 : _api$taskDecision.actions.insertTaskDecision('taskList', inputMethod)(state, dispatch);
121
+ break;
122
+ case 'decision':
123
+ // @ts-expect-error
124
+ (_api$taskDecision2 = api.taskDecision) === null || _api$taskDecision2 === void 0 ? void 0 : _api$taskDecision2.actions.insertTaskDecision('decisionList', inputMethod)(state, dispatch);
125
+ break;
126
+ case 'horizontalrule':
127
+ // @ts-expect-error
128
+ (_api$rule = api.rule) === null || _api$rule === void 0 ? void 0 : _api$rule.actions.insertHorizontalRule(inputMethod)(state, dispatch);
129
+ break;
130
+ case 'macro':
131
+ (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute((_api$quickInsert = api.quickInsert) === null || _api$quickInsert === void 0 ? void 0 : _api$quickInsert.commands.openElementBrowserModal);
132
+ break;
133
+ case 'date':
134
+ (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute((_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({
135
+ // @ts-expect-error
136
+ inputMethod
137
+ }));
138
+ break;
139
+ case 'placeholder text':
140
+ (_api$placeholderText = api.placeholderText) === null || _api$placeholderText === void 0 ? void 0 : _api$placeholderText.actions.showPlaceholderFloatingToolbar(editorView.state, editorView.dispatch);
141
+ break;
142
+ case 'layout':
143
+ // @ts-expect-error
144
+ (_api$layout = api.layout) === null || _api$layout === void 0 ? void 0 : _api$layout.actions.insertLayoutColumns(inputMethod)(editorView.state, editorView.dispatch);
145
+ break;
146
+ case 'status':
147
+ // @ts-expect-error
148
+ (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute((_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));
149
+ break;
150
+
151
+ // https://product-fabric.atlassian.net/browse/ED-8053
152
+ // @ts-ignore: OK to fallthrough to default
153
+ case 'expand':
154
+ if (options.allowExpand) {
155
+ var _api$expand;
156
+ (_api$expand = api.expand) === null || _api$expand === void 0 ? void 0 : _api$expand.actions.insertExpand(state, dispatch);
157
+ break;
158
+ }
159
+
160
+ // eslint-disable-next-line no-fallthrough
161
+ default:
162
+ // leaving this blank for now
163
+ }
164
+ };
165
+ return /*#__PURE__*/React.createElement(Box, {
166
+ xcss: panelWrapper
167
+ }, /*#__PURE__*/React.createElement(Box, {
168
+ xcss: panelContentHeader
169
+ }, /*#__PURE__*/React.createElement(Heading, {
170
+ size: "small",
171
+ as: "h2"
172
+ }, formatMessage(toolbarInsertBlockMessages.insertRightRailTitle)), /*#__PURE__*/React.createElement(IconButton, {
173
+ appearance: "subtle",
174
+ testId: "right-rail-insert-menu-close-button",
175
+ label: formatMessage(toolbarInsertBlockMessages.closeInsertRightRail),
176
+ icon: CrossIcon,
177
+ onClick: () => {
178
+ if (!api) {
179
+ return;
180
+ }
181
+ api.core.actions.execute(({
182
+ tr
183
+ }) => {
184
+ var _api$contextPanel;
185
+ toggleInsertMenuRightRail(tr);
186
+ (_api$contextPanel = api.contextPanel) === null || _api$contextPanel === void 0 ? void 0 : _api$contextPanel.actions.applyChange(tr);
187
+ return tr;
188
+ });
189
+ }
190
+ })), /*#__PURE__*/React.createElement(InsertMenu, {
191
+ editorView: editorView,
192
+ dropdownItems: dropdownItems,
193
+ onInsert: onInsert,
194
+ toggleVisiblity: () => {},
195
+ showElementBrowserLink: true,
196
+ pluginInjectionApi: api
197
+ }));
10
198
  };
@@ -0,0 +1,54 @@
1
+ import { useMemo } from 'react';
2
+ import { useIntl } from 'react-intl-next';
3
+ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
4
+ import { createItems } from '../ToolbarInsertBlock/create-items';
5
+ export const useInsertMenuRailItems = (editorView, options, api) => {
6
+ const {
7
+ formatMessage
8
+ } = useIntl();
9
+ const {
10
+ dateState,
11
+ hyperlinkState,
12
+ imageUploadState,
13
+ mentionState,
14
+ emojiState,
15
+ blockTypeState,
16
+ mediaState,
17
+ typeAheadState,
18
+ placeholderTextState
19
+ } = useSharedPluginState(api, ['hyperlink', 'date', 'imageUpload', 'mention', 'emoji', 'blockType', 'media', 'typeAhead', 'placeholderText']);
20
+ const [_, dropdownItems] = useMemo(() => {
21
+ var _ref;
22
+ return createItems({
23
+ isTypeAheadAllowed: Boolean(typeAheadState === null || typeAheadState === void 0 ? void 0 : typeAheadState.isAllowed),
24
+ tableSupported: !!editorView.state.schema.nodes.table,
25
+ tableSelectorSupported: options.tableSelectorSupported && !!editorView.state.schema.nodes.table,
26
+ mediaUploadsEnabled: (_ref = mediaState && mediaState.allowsUploads) !== null && _ref !== void 0 ? _ref : undefined,
27
+ mediaSupported: !!mediaState,
28
+ imageUploadSupported: !!(api !== null && api !== void 0 && api.imageUpload),
29
+ imageUploadEnabled: imageUploadState === null || imageUploadState === void 0 ? void 0 : imageUploadState.enabled,
30
+ mentionsSupported: !!(mentionState && mentionState.mentionProvider),
31
+ mentionsDisabled: !!(mentionState && !mentionState.canInsertMention),
32
+ actionSupported: !!editorView.state.schema.nodes.taskItem,
33
+ decisionSupported: !!editorView.state.schema.nodes.decisionItem,
34
+ linkSupported: !!hyperlinkState,
35
+ linkDisabled: !hyperlinkState || !hyperlinkState.canInsertLink || !!hyperlinkState.activeLinkMark,
36
+ emojiDisabled: !emojiState || !emojiState.emojiProvider,
37
+ nativeStatusSupported: options.nativeStatusSupported,
38
+ dateEnabled: !!dateState,
39
+ placeholderTextEnabled: placeholderTextState && placeholderTextState.allowInserting,
40
+ horizontalRuleEnabled: options.horizontalRuleEnabled,
41
+ layoutSectionEnabled: Boolean(api === null || api === void 0 ? void 0 : api.layout),
42
+ expandEnabled: !!options.allowExpand,
43
+ showElementBrowserLink: options.showElementBrowserLink,
44
+ emojiProvider: emojiState === null || emojiState === void 0 ? void 0 : emojiState.emojiProvider,
45
+ availableWrapperBlockTypes: blockTypeState && blockTypeState.availableWrapperBlockTypes,
46
+ insertMenuItems: options.insertMenuItems,
47
+ schema: editorView.state.schema,
48
+ numberOfButtons: 10,
49
+ formatMessage,
50
+ isNewMenuEnabled: true
51
+ });
52
+ }, [api === null || api === void 0 ? void 0 : api.imageUpload, api === null || api === void 0 ? void 0 : api.layout, blockTypeState, dateState, editorView.state.schema, emojiState, formatMessage, hyperlinkState, imageUploadState === null || imageUploadState === void 0 ? void 0 : imageUploadState.enabled, mediaState, mentionState, options.allowExpand, options.horizontalRuleEnabled, options.insertMenuItems, options.nativeStatusSupported, options.showElementBrowserLink, options.tableSelectorSupported, placeholderTextState, typeAheadState === null || typeAheadState === void 0 ? void 0 : typeAheadState.isAllowed]);
53
+ return dropdownItems;
54
+ };
@@ -1,53 +1,120 @@
1
1
  import React from 'react';
2
+ import { ACTION, ACTION_SUBJECT, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
3
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
2
4
  import ActionListIcon from '../assets/action-list';
3
5
  import ApprovalsTrackerIcon from '../assets/approvals-tracker';
4
6
  import DecisionMatrixIcon from '../assets/decision-matrix';
5
7
  import DiscussionNotesIcon from '../assets/discussion-notes';
6
8
  import InstructionsOutlineIcon from '../assets/instructions-outline';
7
- export const templateOptions = [{
9
+ import { actionList, approvalsTracker, decisionMatrix, discussionNotes, instructionsOutline } from './templates';
10
+ const getTemplateInsertionPayload = (templateType, source) => ({
11
+ action: ACTION.INSERTED,
12
+ actionSubject: ACTION_SUBJECT.DOCUMENT,
13
+ actionSubjectId: 'elementTemplate',
14
+ attributes: {
15
+ inputMethod: source !== null && source !== void 0 ? source : INPUT_METHOD.QUICK_INSERT,
16
+ templateType
17
+ },
18
+ eventType: EVENT_TYPE.TRACK
19
+ });
20
+ const getTableWidth = api => {
21
+ var _api$table, _api$table$sharedStat;
22
+ return api !== null && api !== void 0 && (_api$table = api.table) !== null && _api$table !== void 0 && (_api$table$sharedStat = _api$table.sharedState.currentState()) !== null && _api$table$sharedStat !== void 0 && _api$table$sharedStat.isFullWidthModeEnabled ? 1800 : 760;
23
+ };
24
+ export const templateOptions = api => [{
8
25
  title: 'Discussion notes',
26
+ // @ts-ignore
27
+ id: 'discussionNotes',
9
28
  description: 'Record discussion points and action items',
10
29
  keywords: ['decisions', 'summary', 'meeting', 'chat', 'debrief', 'track', 'keep track', 'tasks', 'outstanding items', 'owners'],
11
30
  // Place templates right after AI item
12
31
  priority: 99,
13
32
  icon: () => /*#__PURE__*/React.createElement(DiscussionNotesIcon, null),
14
- action: () => {
15
- return false;
33
+ action: (insert, state, source) => {
34
+ var _api$analytics;
35
+ const tr = insert(Fragment.fromJSON(state.schema, discussionNotes(getTableWidth(api))), {
36
+ // @ts-ignore
37
+ isTemplate: true
38
+ });
39
+ api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.attachAnalyticsEvent(
40
+ // @ts-ignore
41
+ getTemplateInsertionPayload('discussionNotes', source))(tr);
42
+ return tr;
16
43
  }
17
44
  }, {
18
45
  title: 'Approvals tracker',
46
+ // @ts-ignore
47
+ id: 'approvalsTracker',
19
48
  description: 'Track reviewer approvals and dates',
20
49
  keywords: ['reviews', 'requests', 'rejected requests', 'review dates', 'timeline', 'checklist', 'sme timeline', 'sme requests', 'sme check', 'table'],
21
50
  priority: 99,
22
51
  icon: () => /*#__PURE__*/React.createElement(ApprovalsTrackerIcon, null),
23
- action: () => {
24
- return false;
52
+ action: (insert, state, source) => {
53
+ var _api$analytics2;
54
+ const tr = insert(Fragment.fromJSON(state.schema, approvalsTracker(getTableWidth(api))), {
55
+ // @ts-ignore
56
+ isTemplate: true
57
+ });
58
+ api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.attachAnalyticsEvent(
59
+ // @ts-ignore
60
+ getTemplateInsertionPayload('approvalsTracker', source))(tr);
61
+ return tr;
25
62
  }
26
63
  }, {
27
64
  title: 'Decision matrix',
65
+ // @ts-ignore
66
+ id: 'decisionMatrix',
28
67
  description: 'Compare options and make recommendations',
29
68
  keywords: ['pros', 'cons', 'recommended', 'rationale', 'evaluation', 'options', 'choice', 'table'],
30
69
  priority: 99,
31
70
  icon: () => /*#__PURE__*/React.createElement(DecisionMatrixIcon, null),
32
- action: () => {
33
- return false;
71
+ action: (insert, state, source) => {
72
+ var _api$analytics3;
73
+ const tr = insert(Fragment.fromJSON(state.schema, decisionMatrix(getTableWidth(api))), {
74
+ // @ts-ignore
75
+ isTemplate: true
76
+ });
77
+ api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.attachAnalyticsEvent(
78
+ // @ts-ignore
79
+ getTemplateInsertionPayload('decisionMatrix', source))(tr);
80
+ return tr;
34
81
  }
35
82
  }, {
36
83
  title: 'List of actions',
84
+ // @ts-ignore
85
+ id: 'actionList',
37
86
  description: 'Track tasks, assignees and deadlines',
38
87
  keywords: ['checklist', 'check', 'items', 'shopping list', 'jtbd', 'jobs to be done', 'due date', 'progress', 'task', 'tasks', 'prioritization', 'timeline', 'approvals', 'reviewers', 'review date'],
39
88
  priority: 99,
40
89
  icon: () => /*#__PURE__*/React.createElement(ActionListIcon, null),
41
- action: () => {
42
- return false;
90
+ action: (insert, state, source) => {
91
+ var _api$analytics4;
92
+ // @ts-ignore
93
+ const tr = insert(Fragment.fromJSON(state.schema, actionList), {
94
+ isTemplate: true
95
+ });
96
+ api === null || api === void 0 ? void 0 : (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 ? void 0 : _api$analytics4.actions.attachAnalyticsEvent(
97
+ // @ts-ignore
98
+ getTemplateInsertionPayload('actionList', source))(tr);
99
+ return tr;
43
100
  }
44
101
  }, {
45
102
  title: 'Instructions outline',
103
+ // @ts-ignore
104
+ id: 'instructionsOutline',
46
105
  description: 'Detailed steps for any process',
47
106
  keywords: ['steps', 'manual', 'tasks', 'jobs to be done', 'jtbd', 'how-to', 'guide', 'journey', 'checklist', 'tutorial', 'map', 'brochure', 'columns', 'layout', 'help'],
48
107
  priority: 99,
49
108
  icon: () => /*#__PURE__*/React.createElement(InstructionsOutlineIcon, null),
50
- action: () => {
51
- return false;
109
+ action: (insert, state, source) => {
110
+ var _api$analytics5;
111
+ // @ts-ignore
112
+ const tr = insert(Fragment.fromJSON(state.schema, instructionsOutline), {
113
+ isTemplate: true
114
+ });
115
+ api === null || api === void 0 ? void 0 : (_api$analytics5 = api.analytics) === null || _api$analytics5 === void 0 ? void 0 : _api$analytics5.actions.attachAnalyticsEvent(
116
+ // @ts-ignore
117
+ getTemplateInsertionPayload('instructionsOutline', source))(tr);
118
+ return tr;
52
119
  }
53
120
  }];