@atlaskit/editor-plugin-panel
Version:
Panel plugin for @atlaskit/editor-core.
352 lines (350 loc) • 15.7 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import React from 'react';
import { PanelType } from '@atlaskit/adf-schema';
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
import { withAnalytics } from '@atlaskit/editor-common/editor-analytics';
import commonMessages, { panelMessages as messages } from '@atlaskit/editor-common/messages';
import { getPanelTypeBackgroundNoTokens } from '@atlaskit/editor-common/panel';
import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check';
import { DEFAULT_BORDER_COLOR, panelBackgroundPalette } from '@atlaskit/editor-common/ui-color';
import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
import { akEditorSelectedNodeClassName } from '@atlaskit/editor-shared-styles';
import CopyIcon from '@atlaskit/icon/core/copy';
import CrossCircleIcon from '@atlaskit/icon/core/cross-circle';
import DeleteIcon from '@atlaskit/icon/core/delete';
import EmojiRemoveIcon from '@atlaskit/icon/core/emoji-remove';
import StatusDiscoveryIcon from '@atlaskit/icon/core/status-discovery';
import InformationIcon from '@atlaskit/icon/core/status-information';
import SuccessIcon from '@atlaskit/icon/core/status-success';
import WarningIcon from '@atlaskit/icon/core/status-warning';
import { changePanelType, removePanel } from '../editor-actions/actions';
import { findPanel } from '../pm-plugins/utils/utils';
import { panelTypeDropdown } from './panelTypeDropdown';
export var panelIconMap = _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, PanelType.INFO, {
shortName: ':info:',
id: 'atlassian-info'
}), PanelType.NOTE, {
shortName: ':note:',
id: 'atlassian-note'
}), PanelType.WARNING, {
shortName: ':warning:',
id: 'atlassian-warning'
}), PanelType.ERROR, {
shortName: ':cross_mark:',
id: 'atlassian-cross_mark'
}), PanelType.SUCCESS, {
shortName: ':check_mark:',
id: 'atlassian-check_mark'
}), PanelType.TIP, {
shortName: ':tip:',
id: 'atlassian-tip'
});
export var getToolbarItems = function getToolbarItems(formatMessage, panelNodeType, isCustomPanelEnabled, isCustomPanelEditable, providerFactory, hoverDecoration, editorAnalyticsAPI, activePanelType, activePanelColor, activePanelIcon, state, api) {
var areAllNewToolbarFlagsDisabled = !areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar));
// TODO: ED-14403 - investigate why these titles are not getting translated for the tooltips
var items = areAllNewToolbarFlagsDisabled ? [{
id: 'editor.panel.info',
type: 'button',
icon: InformationIcon,
onClick: changePanelType(editorAnalyticsAPI)(PanelType.INFO),
selected: activePanelType === PanelType.INFO,
title: formatMessage(messages.info),
tabIndex: null
}, {
id: 'editor.panel.note',
type: 'button',
icon: StatusDiscoveryIcon,
onClick: changePanelType(editorAnalyticsAPI)(PanelType.NOTE),
selected: activePanelType === PanelType.NOTE,
title: formatMessage(messages.note),
tabIndex: null
}, {
id: 'editor.panel.success',
type: 'button',
icon: SuccessIcon,
onClick: changePanelType(editorAnalyticsAPI)(PanelType.SUCCESS),
selected: activePanelType === PanelType.SUCCESS,
title: formatMessage(messages.success),
tabIndex: null
}, {
id: 'editor.panel.warning',
type: 'button',
icon: WarningIcon,
onClick: changePanelType(editorAnalyticsAPI)(PanelType.WARNING),
selected: activePanelType === PanelType.WARNING,
title: formatMessage(messages.warning),
tabIndex: null
}, {
id: 'editor.panel.error',
type: 'button',
icon: CrossCircleIcon,
onClick: changePanelType(editorAnalyticsAPI)(PanelType.ERROR),
selected: activePanelType === PanelType.ERROR,
title: formatMessage(messages.error),
tabIndex: null
}] : [panelTypeDropdown({
activePanelType: activePanelType,
editorAnalyticsAPI: editorAnalyticsAPI,
formatMessage: formatMessage
})].concat(_toConsumableArray(Boolean(api === null || api === void 0 ? void 0 : api.toolbar) ? [] : [{
type: 'separator'
}]));
if (isCustomPanelEnabled) {
var changeColor = function changeColor(color) {
return function (state, dispatch) {
var panelNode = findPanel(state);
if (panelNode === undefined) {
return false;
}
var previousColor = panelNode.node.attrs.panelType === 'custom' ? panelNode.node.attrs.panelColor || 'none' : getPanelTypeBackgroundNoTokens(panelNode.node.attrs.panelType);
var emojiInfo = panelNode.node.attrs.panelType;
var panelEmoji = panelIconMap[emojiInfo];
var previousEmoji = panelEmoji ? {
emoji: panelEmoji.shortName,
emojiId: panelEmoji.id
} : {};
if (previousColor === color) {
changePanelType(editorAnalyticsAPI)(PanelType.CUSTOM, _objectSpread({
color: color
}, previousEmoji), isCustomPanelEnabled)(state, dispatch);
return false;
}
var payload = {
action: ACTION.CHANGED_BACKGROUND_COLOR,
actionSubject: ACTION_SUBJECT.PANEL,
actionSubjectId: ACTION_SUBJECT_ID.PANEL,
attributes: {
newColor: color,
previousColor: previousColor
},
eventType: EVENT_TYPE.TRACK
};
withAnalytics(editorAnalyticsAPI, payload)(changePanelType(editorAnalyticsAPI)(PanelType.CUSTOM, _objectSpread({
color: color
}, previousEmoji), isCustomPanelEnabled))(state, dispatch);
return false;
};
};
var changeEmoji = function changeEmoji(emoji) {
return function (state, dispatch) {
var panelNode = findPanel(state);
if (panelNode === undefined) {
return false;
}
var previousIcon = panelNode.node.attrs.panelIcon || '';
if (previousIcon === emoji.shortName) {
changePanelType(editorAnalyticsAPI)(PanelType.CUSTOM, {
emoji: emoji.shortName,
emojiId: emoji.id,
emojiText: emoji.fallback
}, true)(state, dispatch);
return false;
}
var payload = {
action: ACTION.CHANGED_ICON,
actionSubject: ACTION_SUBJECT.PANEL,
actionSubjectId: ACTION_SUBJECT_ID.PANEL,
attributes: {
newIcon: emoji.shortName,
previousIcon: previousIcon
},
eventType: EVENT_TYPE.TRACK
};
withAnalytics(editorAnalyticsAPI, payload)(changePanelType(editorAnalyticsAPI)(PanelType.CUSTOM, {
emoji: emoji.shortName,
emojiId: emoji.id,
emojiText: emoji.fallback
}, true))(state, dispatch);
return false;
};
};
var removeEmoji = function removeEmoji() {
return function (state, dispatch) {
var panelNode = findPanel(state);
if (activePanelType === PanelType.CUSTOM && !activePanelIcon) {
return false;
}
if (panelNode === undefined) {
return false;
}
var payload = {
action: ACTION.REMOVE_ICON,
actionSubject: ACTION_SUBJECT.PANEL,
actionSubjectId: ACTION_SUBJECT_ID.PANEL,
attributes: {
icon: panelNode.node.attrs.panelIcon
},
eventType: EVENT_TYPE.TRACK
};
withAnalytics(editorAnalyticsAPI, payload)(changePanelType(editorAnalyticsAPI)(PanelType.CUSTOM, {
emoji: undefined,
emojiId: undefined,
emojiText: undefined
}, isCustomPanelEnabled))(state, dispatch);
return false;
};
};
var panelColor = activePanelType === PanelType.CUSTOM ? activePanelColor || getPanelTypeBackgroundNoTokens(PanelType.INFO) : getPanelTypeBackgroundNoTokens(activePanelType);
var defaultPalette = panelBackgroundPalette.find(function (item) {
return item.value === panelColor;
}) || {
// eslint-disable-next-line @atlassian/i18n/no-literal-string-in-object
label: 'Custom',
value: panelColor,
border: DEFAULT_BORDER_COLOR
};
if (isCustomPanelEditable) {
var colorPicker = {
id: 'editor.panel.colorPicker',
title: formatMessage(messages.backgroundColor),
isAriaExpanded: true,
type: 'select',
selectType: 'color',
defaultValue: defaultPalette,
options: panelBackgroundPalette,
onChange: function onChange(option) {
return changeColor(option.value);
}
};
var emojiPicker = {
id: 'editor.panel.emojiPicker',
title: formatMessage(messages.emoji),
type: 'select',
selectType: 'emoji',
options: [],
selected: activePanelType === PanelType.CUSTOM && !!activePanelIcon,
onChange: function onChange(emoji) {
return changeEmoji(emoji);
}
};
var removeEmojiButton = {
id: 'editor.panel.removeEmoji',
type: 'button',
icon: function icon() {
return /*#__PURE__*/React.createElement(EmojiRemoveIcon, {
spacing: 'spacious',
label: ''
});
},
onClick: removeEmoji(),
title: formatMessage(commonMessages.removeEmoji),
disabled: activePanelIcon ? false : true
};
items.push(emojiPicker, removeEmojiButton, {
type: 'separator'
}, colorPicker);
}
}
if (areAllNewToolbarFlagsDisabled) {
if (state) {
items.push({
type: 'separator'
});
items.push({
type: 'copy-button',
items: [{
state: state,
formatMessage: formatMessage,
nodeType: panelNodeType
}]
});
}
items.push({
type: 'separator'
}, {
id: 'editor.panel.delete',
type: 'button',
appearance: 'danger',
focusEditoronEnter: true,
icon: function icon() {
return /*#__PURE__*/React.createElement(DeleteIcon, {
spacing: 'spacious',
label: ''
});
},
onClick: removePanel(editorAnalyticsAPI),
onMouseEnter: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(panelNodeType, true),
onMouseLeave: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(panelNodeType, false),
onFocus: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(panelNodeType, true),
onBlur: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(panelNodeType, false),
title: formatMessage(commonMessages.remove),
tabIndex: null
});
} else {
var hoverDecorationProps = function hoverDecorationProps(nodeType, className) {
return {
onMouseEnter: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(nodeType, true, className),
onMouseLeave: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(nodeType, false, className),
onFocus: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(nodeType, true, className),
onBlur: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(nodeType, false, className)
};
};
// testId is required to show focus on trigger button on ESC key press
// see hideOnEsc in platform/packages/editor/editor-plugin-floating-toolbar/src/ui/Dropdown.tsx
var testId = 'panel-overflow-dropdown-trigger';
var overflowMenuConfig = [{
type: 'separator',
fullHeight: true
}, {
type: 'overflow-dropdown',
testId: testId,
options: [_objectSpread({
title: formatMessage(commonMessages.copyToClipboard),
onClick: function onClick() {
var _api$core, _api$floatingToolbar;
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute( // @ts-ignore
api === null || api === void 0 || (_api$floatingToolbar = api.floatingToolbar) === null || _api$floatingToolbar === void 0 ? void 0 : _api$floatingToolbar.commands.copyNode(panelNodeType, INPUT_METHOD.FLOATING_TB));
return true;
},
icon: /*#__PURE__*/React.createElement(CopyIcon, {
label: ""
})
}, hoverDecorationProps(panelNodeType, akEditorSelectedNodeClassName)), _objectSpread({
title: formatMessage(commonMessages.delete),
onClick: removePanel(editorAnalyticsAPI),
icon: /*#__PURE__*/React.createElement(DeleteIcon, {
label: ""
})
}, hoverDecorationProps(panelNodeType))]
}];
items.push.apply(items, overflowMenuConfig);
}
return items;
};
export var getToolbarConfig = function getToolbarConfig(state, intl) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var providerFactory = arguments.length > 3 ? arguments[3] : undefined;
var api = arguments.length > 4 ? arguments[4] : undefined;
var formatMessage = intl.formatMessage;
var panelObject = findPanel(state);
if (panelObject) {
var _api$decorations, _api$analytics;
var nodeType = state.schema.nodes.panel;
var _panelObject$node$att = panelObject.node.attrs,
panelType = _panelObject$node$att.panelType,
panelColor = _panelObject$node$att.panelColor,
panelIcon = _panelObject$node$att.panelIcon;
var isStandardPanel = function isStandardPanel(panelType) {
return panelType !== PanelType.CUSTOM ? panelType : undefined;
};
// force toolbar to be turned on
var items = getToolbarItems(formatMessage, nodeType, options.allowCustomPanel || false, options.allowCustomPanel && options.allowCustomPanelEdit || false, providerFactory, api === null || api === void 0 || (_api$decorations = api.decorations) === null || _api$decorations === void 0 ? void 0 : _api$decorations.actions.hoverDecoration, api === null || api === 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, areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar)) ? api : undefined);
var getDomRef = function getDomRef(editorView) {
var domAtPos = editorView.domAtPos.bind(editorView);
var element = findDomRefAtPos(panelObject.pos, domAtPos);
return element;
};
return {
title: 'Panel floating controls',
getDomRef: getDomRef,
nodeType: nodeType,
items: items,
scrollable: true,
groupLabel: formatMessage(messages.panelsGroup)
};
}
return;
};