@atlaskit/editor-plugin-panel 0.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 (57) hide show
  1. package/.eslintrc.js +18 -0
  2. package/CHANGELOG.md +1 -0
  3. package/LICENSE.md +13 -0
  4. package/README.md +30 -0
  5. package/dist/cjs/actions.js +125 -0
  6. package/dist/cjs/index.js +13 -0
  7. package/dist/cjs/message.js +44 -0
  8. package/dist/cjs/nodeviews/panel.js +94 -0
  9. package/dist/cjs/plugin.js +215 -0
  10. package/dist/cjs/pm-plugins/keymaps.js +81 -0
  11. package/dist/cjs/pm-plugins/main.js +28 -0
  12. package/dist/cjs/toolbar.js +293 -0
  13. package/dist/cjs/types.js +8 -0
  14. package/dist/cjs/utils.js +53 -0
  15. package/dist/es2019/actions.js +116 -0
  16. package/dist/es2019/index.js +1 -0
  17. package/dist/es2019/message.js +38 -0
  18. package/dist/es2019/nodeviews/panel.js +82 -0
  19. package/dist/es2019/plugin.js +191 -0
  20. package/dist/es2019/pm-plugins/keymaps.js +82 -0
  21. package/dist/es2019/pm-plugins/main.js +21 -0
  22. package/dist/es2019/toolbar.js +279 -0
  23. package/dist/es2019/types.js +2 -0
  24. package/dist/es2019/utils.js +48 -0
  25. package/dist/esm/actions.js +116 -0
  26. package/dist/esm/index.js +1 -0
  27. package/dist/esm/message.js +38 -0
  28. package/dist/esm/nodeviews/panel.js +87 -0
  29. package/dist/esm/plugin.js +208 -0
  30. package/dist/esm/pm-plugins/keymaps.js +74 -0
  31. package/dist/esm/pm-plugins/main.js +22 -0
  32. package/dist/esm/toolbar.js +286 -0
  33. package/dist/esm/types.js +2 -0
  34. package/dist/esm/utils.js +46 -0
  35. package/dist/types/actions.d.ts +12 -0
  36. package/dist/types/index.d.ts +3 -0
  37. package/dist/types/message.d.ts +37 -0
  38. package/dist/types/nodeviews/panel.d.ts +36 -0
  39. package/dist/types/plugin.d.ts +17 -0
  40. package/dist/types/pm-plugins/keymaps.d.ts +3 -0
  41. package/dist/types/pm-plugins/main.d.ts +11 -0
  42. package/dist/types/toolbar.d.ts +15 -0
  43. package/dist/types/types.d.ts +21 -0
  44. package/dist/types/utils.d.ts +5 -0
  45. package/dist/types-ts4.5/actions.d.ts +12 -0
  46. package/dist/types-ts4.5/index.d.ts +3 -0
  47. package/dist/types-ts4.5/message.d.ts +37 -0
  48. package/dist/types-ts4.5/nodeviews/panel.d.ts +36 -0
  49. package/dist/types-ts4.5/plugin.d.ts +17 -0
  50. package/dist/types-ts4.5/pm-plugins/keymaps.d.ts +3 -0
  51. package/dist/types-ts4.5/pm-plugins/main.d.ts +11 -0
  52. package/dist/types-ts4.5/toolbar.d.ts +15 -0
  53. package/dist/types-ts4.5/types.d.ts +21 -0
  54. package/dist/types-ts4.5/utils.d.ts +5 -0
  55. package/package.json +102 -0
  56. package/report.api.md +74 -0
  57. package/tmp/api-report-tmp.d.ts +44 -0
@@ -0,0 +1,191 @@
1
+ import React from 'react';
2
+ import { panel, PanelType } from '@atlaskit/adf-schema';
3
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
4
+ import { blockTypeMessages } from '@atlaskit/editor-common/messages';
5
+ import { IconCustomPanel, IconPanel, IconPanelError, IconPanelNote, IconPanelSuccess, IconPanelWarning } from '@atlaskit/editor-common/quick-insert';
6
+ import { createWrapSelectionTransaction } from '@atlaskit/editor-common/utils';
7
+ import { T50 } from '@atlaskit/theme/colors';
8
+ import { insertPanelWithAnalytics } from './actions';
9
+ import keymap from './pm-plugins/keymaps';
10
+ import { createPlugin } from './pm-plugins/main';
11
+ import { getToolbarConfig } from './toolbar';
12
+ const panelPlugin = ({
13
+ config: options = {},
14
+ api
15
+ }) => ({
16
+ name: 'panel',
17
+ nodes() {
18
+ const panelNode = panel(!!options.allowCustomPanel);
19
+ return [{
20
+ name: 'panel',
21
+ node: panelNode
22
+ }];
23
+ },
24
+ pmPlugins() {
25
+ return [{
26
+ name: 'panel',
27
+ plugin: ({
28
+ providerFactory,
29
+ dispatch
30
+ }) => createPlugin(dispatch, providerFactory, options)
31
+ }, {
32
+ name: 'panelKeyMap',
33
+ plugin: () => keymap()
34
+ }];
35
+ },
36
+ actions: {
37
+ insertPanel(inputMethod) {
38
+ var _api$analytics;
39
+ return insertPanelWithAnalytics(inputMethod, api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions);
40
+ }
41
+ },
42
+ pluginsOptions: {
43
+ quickInsert: ({
44
+ formatMessage
45
+ }) => {
46
+ let quickInsertOptions = [{
47
+ id: 'infopanel',
48
+ title: formatMessage(blockTypeMessages.infoPanel),
49
+ keywords: ['panel'],
50
+ description: formatMessage(blockTypeMessages.infoPanelDescription),
51
+ priority: 800,
52
+ icon: () => /*#__PURE__*/React.createElement(IconPanel, null),
53
+ action(insert, state) {
54
+ return createPanelAction({
55
+ state,
56
+ attributes: {
57
+ panelType: PanelType.INFO
58
+ },
59
+ api
60
+ });
61
+ }
62
+ }, {
63
+ id: 'notepanel',
64
+ title: formatMessage(blockTypeMessages.notePanel),
65
+ description: formatMessage(blockTypeMessages.notePanelDescription),
66
+ priority: 1000,
67
+ icon: () => /*#__PURE__*/React.createElement(IconPanelNote, null),
68
+ action(insert, state) {
69
+ return createPanelAction({
70
+ state,
71
+ attributes: {
72
+ panelType: PanelType.NOTE
73
+ },
74
+ api
75
+ });
76
+ }
77
+ }, {
78
+ id: 'successpanel',
79
+ title: formatMessage(blockTypeMessages.successPanel),
80
+ description: formatMessage(blockTypeMessages.successPanelDescription),
81
+ keywords: ['tip'],
82
+ priority: 1000,
83
+ icon: () => /*#__PURE__*/React.createElement(IconPanelSuccess, null),
84
+ action(insert, state) {
85
+ return createPanelAction({
86
+ state,
87
+ attributes: {
88
+ panelType: PanelType.SUCCESS
89
+ },
90
+ api
91
+ });
92
+ }
93
+ }, {
94
+ id: 'warningpanel',
95
+ title: formatMessage(blockTypeMessages.warningPanel),
96
+ description: formatMessage(blockTypeMessages.warningPanelDescription),
97
+ priority: 1000,
98
+ icon: () => /*#__PURE__*/React.createElement(IconPanelWarning, null),
99
+ action(insert, state) {
100
+ return createPanelAction({
101
+ state,
102
+ attributes: {
103
+ panelType: PanelType.WARNING
104
+ },
105
+ api
106
+ });
107
+ }
108
+ }, {
109
+ id: 'errorpanel',
110
+ title: formatMessage(blockTypeMessages.errorPanel),
111
+ description: formatMessage(blockTypeMessages.errorPanelDescription),
112
+ priority: 1000,
113
+ icon: () => /*#__PURE__*/React.createElement(IconPanelError, null),
114
+ action(insert, state) {
115
+ return createPanelAction({
116
+ state,
117
+ attributes: {
118
+ panelType: PanelType.ERROR
119
+ },
120
+ api
121
+ });
122
+ }
123
+ }];
124
+ if (options.allowCustomPanel && options.allowCustomPanelEdit) {
125
+ quickInsertOptions.push({
126
+ id: 'custompanel',
127
+ title: formatMessage(blockTypeMessages.customPanel),
128
+ description: formatMessage(blockTypeMessages.customPanelDescription),
129
+ priority: 1000,
130
+ icon: () => /*#__PURE__*/React.createElement(IconCustomPanel, null),
131
+ action(insert, state) {
132
+ return createPanelAction({
133
+ state,
134
+ attributes: {
135
+ panelType: PanelType.CUSTOM,
136
+ panelIcon: ':rainbow:',
137
+ panelIconId: '1f308',
138
+ panelIconText: '🌈',
139
+ // TODO: https://product-fabric.atlassian.net/browse/DSP-7268
140
+ // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
141
+ panelColor: T50
142
+ },
143
+ api
144
+ });
145
+ }
146
+ });
147
+ }
148
+ return quickInsertOptions;
149
+ },
150
+ floatingToolbar: (state, intl, providerFactory) => getToolbarConfig(state, intl, options, providerFactory, api)
151
+ }
152
+ });
153
+
154
+ /**
155
+ * Creates panel action and wrap selection transaction with analytics for the panel insertion.
156
+ *
157
+ * @example
158
+ * const tr = createPanelAction({
159
+ * state: editorState,
160
+ * attributes: { panelType: 'info' },
161
+ * });
162
+ * if (tr) {
163
+ * applyTransaction(tr);
164
+ * }
165
+ */
166
+ function createPanelAction({
167
+ state,
168
+ attributes,
169
+ api
170
+ }) {
171
+ const tr = createWrapSelectionTransaction({
172
+ state,
173
+ type: state.schema.nodes.panel,
174
+ nodeAttributes: attributes
175
+ });
176
+ if (tr) {
177
+ var _api$analytics2;
178
+ api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.attachAnalyticsEvent({
179
+ action: ACTION.INSERTED,
180
+ actionSubject: ACTION_SUBJECT.DOCUMENT,
181
+ actionSubjectId: ACTION_SUBJECT_ID.PANEL,
182
+ attributes: {
183
+ inputMethod: INPUT_METHOD.QUICK_INSERT,
184
+ panelType: attributes.panelType
185
+ },
186
+ eventType: EVENT_TYPE.TRACK
187
+ })(tr);
188
+ }
189
+ return tr;
190
+ }
191
+ export default panelPlugin;
@@ -0,0 +1,82 @@
1
+ import { isEmptyNode } from '@atlaskit/editor-common/utils';
2
+ import { keymap } from '@atlaskit/editor-prosemirror/keymap';
3
+ import { findParentNodeOfType, hasParentNodeOfType, setTextSelection } from '@atlaskit/editor-prosemirror/utils';
4
+ function findParentNode(selection, nodeType) {
5
+ const parentPosition = findParentNodeOfType(nodeType)(selection);
6
+ if (parentPosition) {
7
+ return parentPosition.node;
8
+ }
9
+ return null;
10
+ }
11
+ function isInsideAnEmptyNode(selection, nodeType, schema) {
12
+ const parentNode = findParentNode(selection, nodeType);
13
+ return parentNode && isEmptyNode(schema)(parentNode);
14
+ }
15
+
16
+ // Somewhat broken and subverted: https://product-fabric.atlassian.net/browse/ED-6504
17
+ export function keymapPlugin() {
18
+ const deleteCurrentItem = ($from, tr) => {
19
+ return tr.delete($from.before($from.depth) - 1, $from.end($from.depth) + 1);
20
+ };
21
+ const keymaps = {
22
+ Backspace: (state, dispatch) => {
23
+ var _nodeBeforePanel$type, _nodeBeforePanel$type2;
24
+ const {
25
+ selection,
26
+ schema: {
27
+ nodes
28
+ },
29
+ tr
30
+ } = state;
31
+ const {
32
+ panel,
33
+ blockquote
34
+ } = nodes;
35
+ const {
36
+ $from,
37
+ $to
38
+ } = selection;
39
+ // Don't do anything if selection is a range
40
+ if ($from.pos !== $to.pos) {
41
+ return false;
42
+ }
43
+
44
+ // If not at the start of a panel, no joining will happen so allow default behaviour (backspacing characters etc..)
45
+ if ($from.parentOffset !== 0) {
46
+ return false;
47
+ }
48
+ const $previousPos = tr.doc.resolve(Math.max(0, $from.before($from.depth) - 1));
49
+ const previousNodeType = $previousPos.pos > 0 && $previousPos.parent && $previousPos.parent.type;
50
+ const parentNodeType = $from.parent.type;
51
+ const isPreviousNodeAPanel = previousNodeType === panel;
52
+ const isParentNodeAPanel = parentNodeType === panel;
53
+ const nodeBeforePanel = $previousPos === null || $previousPos === void 0 ? void 0 : $previousPos.nodeBefore;
54
+
55
+ // Stops merging panels when deleting empty paragraph in between
56
+ // Stops merging blockquotes with panels when deleting from start of blockquote
57
+
58
+ if (isPreviousNodeAPanel && !isParentNodeAPanel || isInsideAnEmptyNode(selection, panel, state.schema) || hasParentNodeOfType(blockquote)(selection) ||
59
+ // Lift line of panel content up and out of the panel, when backspacing
60
+ // at the start of a panel, if the node before the panel is an 'isolating' node
61
+ // (for e.g. a table, or an expand), otherwise the default prosemirror backspace
62
+ // behaviour will fallback to 'select node backward' logic because the node
63
+ // before is an isolating node.
64
+ nodeBeforePanel !== null && nodeBeforePanel !== void 0 && (_nodeBeforePanel$type = nodeBeforePanel.type) !== null && _nodeBeforePanel$type !== void 0 && (_nodeBeforePanel$type2 = _nodeBeforePanel$type.spec) !== null && _nodeBeforePanel$type2 !== void 0 && _nodeBeforePanel$type2.isolating && hasParentNodeOfType(panel)(selection)) {
65
+ const content = $from.node($from.depth).content;
66
+ const insertPos = $previousPos.pos;
67
+ deleteCurrentItem($from, tr).insert(insertPos, content);
68
+ if (dispatch) {
69
+ dispatch(setTextSelection(insertPos)(tr).scrollIntoView());
70
+ }
71
+ return true;
72
+ }
73
+ const nodeType = $from.node().type;
74
+ if (nodeType !== panel) {
75
+ return false;
76
+ }
77
+ return true;
78
+ }
79
+ };
80
+ return keymap(keymaps);
81
+ }
82
+ export default keymapPlugin;
@@ -0,0 +1,21 @@
1
+ import { PanelSharedCssClassName } from '@atlaskit/editor-common/panel';
2
+ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
3
+ import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
4
+ import { getPanelNodeView } from '../nodeviews/panel';
5
+ import { pluginKey } from '../types';
6
+ export const createPlugin = (dispatch, providerFactory, pluginOptions) => {
7
+ const {
8
+ useLongPressSelection = false
9
+ } = pluginOptions;
10
+ return new SafePlugin({
11
+ key: pluginKey,
12
+ props: {
13
+ nodeViews: {
14
+ panel: getPanelNodeView(pluginOptions, providerFactory)
15
+ },
16
+ handleClickOn: createSelectionClickHandler(['panel'], target => !!target.closest(`.${PanelSharedCssClassName.prefix}`), {
17
+ useLongPressSelection
18
+ })
19
+ }
20
+ });
21
+ };
@@ -0,0 +1,279 @@
1
+ import { PanelType } from '@atlaskit/adf-schema';
2
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
3
+ import { withAnalytics } from '@atlaskit/editor-common/editor-analytics';
4
+ import commonMessages from '@atlaskit/editor-common/messages';
5
+ import { getPanelTypeBackgroundNoTokens } from '@atlaskit/editor-common/panel';
6
+ import { DEFAULT_BORDER_COLOR, panelBackgroundPalette } from '@atlaskit/editor-common/ui-color';
7
+ import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
8
+ import ErrorIcon from '@atlaskit/icon/glyph/editor/error';
9
+ import InfoIcon from '@atlaskit/icon/glyph/editor/info';
10
+ import NoteIcon from '@atlaskit/icon/glyph/editor/note';
11
+ import RemoveIcon from '@atlaskit/icon/glyph/editor/remove';
12
+ import RemoveEmojiIcon from '@atlaskit/icon/glyph/editor/remove-emoji';
13
+ import SuccessIcon from '@atlaskit/icon/glyph/editor/success';
14
+ import WarningIcon from '@atlaskit/icon/glyph/editor/warning';
15
+ import { changePanelType, removePanel } from './actions';
16
+ import { messages } from './message';
17
+ import { findPanel } from './utils';
18
+ export const panelIconMap = {
19
+ [PanelType.INFO]: {
20
+ shortName: ':info:',
21
+ id: 'atlassian-info'
22
+ },
23
+ [PanelType.NOTE]: {
24
+ shortName: ':note:',
25
+ id: 'atlassian-note'
26
+ },
27
+ [PanelType.WARNING]: {
28
+ shortName: ':warning:',
29
+ id: 'atlassian-warning'
30
+ },
31
+ [PanelType.ERROR]: {
32
+ shortName: ':cross_mark:',
33
+ id: 'atlassian-cross_mark'
34
+ },
35
+ [PanelType.SUCCESS]: {
36
+ shortName: ':check_mark:',
37
+ id: 'atlassian-check_mark'
38
+ },
39
+ [PanelType.TIP]: {
40
+ shortName: ':tip:',
41
+ id: 'atlassian-tip'
42
+ }
43
+ };
44
+ export const getToolbarItems = (formatMessage, panelNodeType, isCustomPanelEnabled, isCustomPanelEditable, providerFactory, hoverDecoration, editorAnalyticsAPI, activePanelType, activePanelColor, activePanelIcon, state) => {
45
+ // TODO: ED-14403 investigate why these titles are not getting translated for the tooltips
46
+ const items = [{
47
+ id: 'editor.panel.info',
48
+ type: 'button',
49
+ icon: InfoIcon,
50
+ onClick: changePanelType(editorAnalyticsAPI)(PanelType.INFO),
51
+ selected: activePanelType === PanelType.INFO,
52
+ title: formatMessage(messages.info),
53
+ tabIndex: null
54
+ }, {
55
+ id: 'editor.panel.note',
56
+ type: 'button',
57
+ icon: NoteIcon,
58
+ onClick: changePanelType(editorAnalyticsAPI)(PanelType.NOTE),
59
+ selected: activePanelType === PanelType.NOTE,
60
+ title: formatMessage(messages.note),
61
+ tabIndex: null
62
+ }, {
63
+ id: 'editor.panel.success',
64
+ type: 'button',
65
+ icon: SuccessIcon,
66
+ onClick: changePanelType(editorAnalyticsAPI)(PanelType.SUCCESS),
67
+ selected: activePanelType === PanelType.SUCCESS,
68
+ title: formatMessage(messages.success),
69
+ tabIndex: null
70
+ }, {
71
+ id: 'editor.panel.warning',
72
+ type: 'button',
73
+ icon: WarningIcon,
74
+ onClick: changePanelType(editorAnalyticsAPI)(PanelType.WARNING),
75
+ selected: activePanelType === PanelType.WARNING,
76
+ title: formatMessage(messages.warning),
77
+ tabIndex: null
78
+ }, {
79
+ id: 'editor.panel.error',
80
+ type: 'button',
81
+ icon: ErrorIcon,
82
+ onClick: changePanelType(editorAnalyticsAPI)(PanelType.ERROR),
83
+ selected: activePanelType === PanelType.ERROR,
84
+ title: formatMessage(messages.error),
85
+ tabIndex: null
86
+ }];
87
+ if (isCustomPanelEnabled) {
88
+ const changeColor = color => (state, dispatch) => {
89
+ const panelNode = findPanel(state);
90
+ if (panelNode === undefined) {
91
+ return false;
92
+ }
93
+ let previousColor = panelNode.node.attrs.panelType === 'custom' ? panelNode.node.attrs.panelColor || 'none' : getPanelTypeBackgroundNoTokens(panelNode.node.attrs.panelType);
94
+ const emojiInfo = panelNode.node.attrs.panelType;
95
+ const panelEmoji = panelIconMap[emojiInfo];
96
+ const previousEmoji = panelEmoji ? {
97
+ emoji: panelEmoji.shortName,
98
+ emojiId: panelEmoji.id
99
+ } : {};
100
+ if (previousColor === color) {
101
+ changePanelType(editorAnalyticsAPI)(PanelType.CUSTOM, {
102
+ color,
103
+ ...previousEmoji
104
+ }, isCustomPanelEnabled)(state, dispatch);
105
+ return false;
106
+ }
107
+ const payload = {
108
+ action: ACTION.CHANGED_BACKGROUND_COLOR,
109
+ actionSubject: ACTION_SUBJECT.PANEL,
110
+ actionSubjectId: ACTION_SUBJECT_ID.PANEL,
111
+ attributes: {
112
+ newColor: color,
113
+ previousColor: previousColor
114
+ },
115
+ eventType: EVENT_TYPE.TRACK
116
+ };
117
+ withAnalytics(editorAnalyticsAPI, payload)(changePanelType(editorAnalyticsAPI)(PanelType.CUSTOM, {
118
+ color,
119
+ ...previousEmoji
120
+ }, isCustomPanelEnabled))(state, dispatch);
121
+ return false;
122
+ };
123
+ const changeEmoji = emoji => (state, dispatch) => {
124
+ const panelNode = findPanel(state);
125
+ if (panelNode === undefined) {
126
+ return false;
127
+ }
128
+ let previousIcon = panelNode.node.attrs.panelIcon || '';
129
+ if (previousIcon === emoji.shortName) {
130
+ changePanelType(editorAnalyticsAPI)(PanelType.CUSTOM, {
131
+ emoji: emoji.shortName,
132
+ emojiId: emoji.id,
133
+ emojiText: emoji.fallback
134
+ }, true)(state, dispatch);
135
+ return false;
136
+ }
137
+ const payload = {
138
+ action: ACTION.CHANGED_ICON,
139
+ actionSubject: ACTION_SUBJECT.PANEL,
140
+ actionSubjectId: ACTION_SUBJECT_ID.PANEL,
141
+ attributes: {
142
+ newIcon: emoji.shortName,
143
+ previousIcon: previousIcon
144
+ },
145
+ eventType: EVENT_TYPE.TRACK
146
+ };
147
+ withAnalytics(editorAnalyticsAPI, payload)(changePanelType(editorAnalyticsAPI)(PanelType.CUSTOM, {
148
+ emoji: emoji.shortName,
149
+ emojiId: emoji.id,
150
+ emojiText: emoji.fallback
151
+ }, true))(state, dispatch);
152
+ return false;
153
+ };
154
+ const removeEmoji = () => (state, dispatch) => {
155
+ const panelNode = findPanel(state);
156
+ if (activePanelType === PanelType.CUSTOM && !activePanelIcon) {
157
+ return false;
158
+ }
159
+ if (panelNode === undefined) {
160
+ return false;
161
+ }
162
+ const payload = {
163
+ action: ACTION.REMOVE_ICON,
164
+ actionSubject: ACTION_SUBJECT.PANEL,
165
+ actionSubjectId: ACTION_SUBJECT_ID.PANEL,
166
+ attributes: {
167
+ icon: panelNode.node.attrs.panelIcon
168
+ },
169
+ eventType: EVENT_TYPE.TRACK
170
+ };
171
+ withAnalytics(editorAnalyticsAPI, payload)(changePanelType(editorAnalyticsAPI)(PanelType.CUSTOM, {
172
+ emoji: undefined,
173
+ emojiId: undefined,
174
+ emojiText: undefined
175
+ }, isCustomPanelEnabled))(state, dispatch);
176
+ return false;
177
+ };
178
+ const panelColor = activePanelType === PanelType.CUSTOM ? activePanelColor || getPanelTypeBackgroundNoTokens(PanelType.INFO) : getPanelTypeBackgroundNoTokens(activePanelType);
179
+ const defaultPalette = panelBackgroundPalette.find(item => item.value === panelColor) || {
180
+ label: 'Custom',
181
+ value: panelColor,
182
+ border: DEFAULT_BORDER_COLOR
183
+ };
184
+ if (isCustomPanelEditable) {
185
+ const colorPicker = {
186
+ id: 'editor.panel.colorPicker',
187
+ title: formatMessage(messages.backgroundColor),
188
+ type: 'select',
189
+ selectType: 'color',
190
+ defaultValue: defaultPalette,
191
+ options: panelBackgroundPalette,
192
+ onChange: option => changeColor(option.value)
193
+ };
194
+ const emojiPicker = {
195
+ id: 'editor.panel.emojiPicker',
196
+ title: formatMessage(messages.emoji),
197
+ type: 'select',
198
+ selectType: 'emoji',
199
+ options: [],
200
+ selected: activePanelType === PanelType.CUSTOM && !!activePanelIcon,
201
+ onChange: emoji => changeEmoji(emoji)
202
+ };
203
+ const removeEmojiButton = {
204
+ id: 'editor.panel.removeEmoji',
205
+ type: 'button',
206
+ icon: RemoveEmojiIcon,
207
+ onClick: removeEmoji(),
208
+ title: formatMessage(commonMessages.removeEmoji),
209
+ disabled: activePanelIcon ? false : true
210
+ };
211
+ items.push(emojiPicker, removeEmojiButton, {
212
+ type: 'separator'
213
+ }, colorPicker);
214
+ }
215
+ }
216
+ if (state) {
217
+ items.push({
218
+ type: 'copy-button',
219
+ items: [{
220
+ type: 'separator'
221
+ }, {
222
+ state,
223
+ formatMessage,
224
+ nodeType: panelNodeType
225
+ }]
226
+ });
227
+ }
228
+ items.push({
229
+ type: 'separator'
230
+ }, {
231
+ id: 'editor.panel.delete',
232
+ type: 'button',
233
+ appearance: 'danger',
234
+ focusEditoronEnter: true,
235
+ icon: RemoveIcon,
236
+ onClick: removePanel(editorAnalyticsAPI),
237
+ onMouseEnter: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(panelNodeType, true),
238
+ onMouseLeave: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(panelNodeType, false),
239
+ onFocus: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(panelNodeType, true),
240
+ onBlur: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(panelNodeType, false),
241
+ title: formatMessage(commonMessages.remove),
242
+ tabIndex: null
243
+ });
244
+ return items;
245
+ };
246
+ export const getToolbarConfig = (state, intl, options = {}, providerFactory, api) => {
247
+ const {
248
+ formatMessage
249
+ } = intl;
250
+ const panelObject = findPanel(state);
251
+ if (panelObject) {
252
+ var _api$analytics;
253
+ const nodeType = state.schema.nodes.panel;
254
+ const {
255
+ panelType,
256
+ panelColor,
257
+ panelIcon
258
+ } = panelObject.node.attrs;
259
+ const isStandardPanel = panelType => {
260
+ return panelType !== PanelType.CUSTOM ? panelType : undefined;
261
+ };
262
+
263
+ // force toolbar to be turned on
264
+ const items = getToolbarItems(formatMessage, nodeType, options.allowCustomPanel || false, options.allowCustomPanel && options.allowCustomPanelEdit || false, providerFactory, api === null || api === void 0 ? void 0 : api.decorations.actions.hoverDecoration, api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions, panelType, options.allowCustomPanel ? panelColor : undefined, options.allowCustomPanel ? panelIcon || isStandardPanel(panelType) : undefined, state);
265
+ const getDomRef = editorView => {
266
+ const domAtPos = editorView.domAtPos.bind(editorView);
267
+ const element = findDomRefAtPos(panelObject.pos, domAtPos);
268
+ return element;
269
+ };
270
+ return {
271
+ title: 'Panel floating controls',
272
+ getDomRef,
273
+ nodeType,
274
+ items,
275
+ scrollable: true
276
+ };
277
+ }
278
+ return;
279
+ };
@@ -0,0 +1,2 @@
1
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
2
+ export const pluginKey = new PluginKey('panelPlugin');
@@ -0,0 +1,48 @@
1
+ import { PanelType } from '@atlaskit/adf-schema';
2
+ import { PanelSharedCssClassName } from '@atlaskit/editor-common/panel';
3
+ import { hexToEditorBackgroundPaletteColor } from '@atlaskit/editor-palette';
4
+ import { findParentNodeOfType, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
5
+ export const findPanel = (state, selection) => {
6
+ const {
7
+ panel
8
+ } = state.schema.nodes;
9
+ return findSelectedNodeOfType(panel)(selection || state.selection) || findParentNodeOfType(panel)(selection || state.selection);
10
+ };
11
+ export const panelAttrsToDom = (attrs, allowCustomPanel) => {
12
+ const {
13
+ panelColor,
14
+ panelType,
15
+ panelIcon,
16
+ panelIconId,
17
+ panelIconText
18
+ } = attrs;
19
+ const isCustomPanel = panelType === PanelType.CUSTOM && allowCustomPanel;
20
+ const hasIcon = !isCustomPanel || !!panelIcon || !!panelIconId;
21
+ const tokenColor = panelColor && hexToEditorBackgroundPaletteColor(panelColor);
22
+ const panelBackgroundColor = tokenColor || panelColor;
23
+ const style = [`${panelColor && isCustomPanel ? `background-color: ${panelBackgroundColor};` : ''}`, `${hasIcon ? '' : 'padding-left: 12px;'}`].join('');
24
+ let panelAttrs = {
25
+ class: PanelSharedCssClassName.prefix,
26
+ 'data-panel-type': panelType || PanelType.INFO,
27
+ style
28
+ };
29
+ if (panelColor && isCustomPanel) {
30
+ panelAttrs = {
31
+ ...panelAttrs,
32
+ 'data-panel-color': panelColor,
33
+ 'data-panel-icon-id': panelIconId,
34
+ 'data-panel-icon-text': panelIconText
35
+ };
36
+ }
37
+ const iconDiv = ['div', {
38
+ class: PanelSharedCssClassName.icon
39
+ }];
40
+ const contentDiv = ['div', {
41
+ class: PanelSharedCssClassName.content
42
+ }, 0];
43
+ if (hasIcon) {
44
+ return ['div', panelAttrs, iconDiv, contentDiv];
45
+ } else {
46
+ return ['div', panelAttrs, contentDiv];
47
+ }
48
+ };