UNPKG

@atlaskit/editor-plugin-floating-toolbar

Version:

Floating toolbar plugin for @atlaskit/editor-core

777 lines (768 loc) 36.5 kB
import _extends from "@babel/runtime/helpers/extends"; import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; import _createClass from "@babel/runtime/helpers/createClass"; import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf"; import _inherits from "@babel/runtime/helpers/inherits"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } 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; } /* eslint-disable @atlaskit/design-system/no-css-tagged-template-expression -- needs manual remediation */ /** * @jsxRuntime classic * @jsx jsx */ import React, { Component } from 'react'; // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766 import { css, jsx } from '@emotion/react'; import { injectIntl } from 'react-intl'; import ButtonGroup from '@atlaskit/button/button-group'; import { areSameItems, messages } from '@atlaskit/editor-common/floating-toolbar'; import commonMessages from '@atlaskit/editor-common/messages'; import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check'; import { Announcer, FloatingToolbarButton as Button, FloatingToolbarSeparator as Separator } from '@atlaskit/editor-common/ui'; import { backgroundPaletteTooltipMessages } from '@atlaskit/editor-common/ui-color'; import { ColorPickerButton, ToolbarArrowKeyNavigationProvider } from '@atlaskit/editor-common/ui-menu'; import { hexToEditorBackgroundPaletteColor } from '@atlaskit/editor-palette'; import ShowMoreHorizontalIcon from '@atlaskit/icon/core/show-more-horizontal'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { checkShouldForceFocusAndApply, forceFocusSelector } from '../pm-plugins/force-focus'; import { showConfirmDialog } from '../pm-plugins/toolbar-data/commands'; import Dropdown from './Dropdown'; import { EmojiPickerButton } from './EmojiPickerButton'; import { ExtensionsPlaceholder } from './ExtensionsPlaceholder'; import { Input } from './Input'; import { ScrollButton } from './ScrollButton'; import { ScrollButtons } from './ScrollButtons'; import Select from './Select'; // eslint-disable-next-line jsdoc/require-jsdoc export function groupItems(items, areAnyNewToolbarFlagsEnabled) { var groupItems = items.reduce(function (accumulator, item, i) { var finalOutput = accumulator.finalOutput, buttonGroup = accumulator.buttonGroup; if (item.type === 'button') { var notLastItem = i < items.length - 1; var nextItemIsButton = items[i + 1] && items[i + 1].type === 'button'; var wasPreviousButton = items[i - 1] && items[i - 1].type === 'button'; var shouldBeRadioButton = notLastItem && nextItemIsButton || wasPreviousButton; // Only group as radio button if not explicitly set to false var isRadioButton = !expValEquals('platform_editor_august_a11y', 'isEnabled', true) ? shouldBeRadioButton : shouldBeRadioButton && item.isRadioButton !== false; if (isRadioButton) { item.isRadioButton = true; buttonGroup.push(item); if (!nextItemIsButton && wasPreviousButton) { finalOutput.push(buttonGroup); accumulator.buttonGroup = []; } } else { finalOutput.push(item); } } else if (item.type === 'separator' && areAnyNewToolbarFlagsEnabled) { var _items; var isLeadingSeparator = i === 0; var isTrailingSeparator = i === items.length - 1; var isDuplicateSeparator = ((_items = items[i - 1]) === null || _items === void 0 ? void 0 : _items.type) === 'separator'; !isLeadingSeparator && !isTrailingSeparator && !isDuplicateSeparator && finalOutput.push(item); } else { finalOutput.push(item); } return accumulator; }, { buttonGroup: [], finalOutput: [] }); return groupItems.finalOutput; } var ToolbarItems = /*#__PURE__*/React.memo(function (_ref) { var items = _ref.items, groupLabel = _ref.groupLabel, dispatchCommand = _ref.dispatchCommand, popupsMountPoint = _ref.popupsMountPoint, popupsBoundariesElement = _ref.popupsBoundariesElement, editorView = _ref.editorView, dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent, popupsScrollableElement = _ref.popupsScrollableElement, scrollable = _ref.scrollable, providerFactory = _ref.providerFactory, extensionsProvider = _ref.extensionsProvider, node = _ref.node, setDisableScroll = _ref.setDisableScroll, mountRef = _ref.mountRef, api = _ref.api, intl = _ref.intl; var emojiAndColourPickerMountPoint = scrollable ? popupsMountPoint || (editorView === null || editorView === void 0 ? void 0 : editorView.dom.closest('.fabric-editor-popup-scroll-parent')) || (editorView === null || editorView === void 0 ? void 0 : editorView.dom.closest('.ak-editor-content-area')) || undefined : popupsMountPoint; var areAnyNewToolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar)); var renderItem = function renderItem(item, idx) { var _api$contextPanel, _api$extension; switch (item.type) { case 'button': // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any var ButtonIcon = item.icon; var onClickHandler = function onClickHandler() { if (item.confirmDialog) { dispatchCommand(showConfirmDialog(idx)); } else { dispatchCommand(item.onClick); if (item.focusEditoronEnter && !(editorView !== null && editorView !== void 0 && editorView.hasFocus())) { editorView === null || editorView === void 0 || editorView.focus(); } } }; var getIconColor = function getIconColor(disabled, selected) { if (disabled) { return "var(--ds-icon-disabled, #080F214A)"; } if (selected) { return "var(--ds-icon-selected, #1868DB)"; } return 'currentColor'; }; return jsx(Button // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop, @atlaskit/design-system/no-unsafe-style-overrides -- Ignored via go/DSP-18766 , { className: item.className, key: idx, title: item.title, href: item.href, icon: item.icon ? jsx(ButtonIcon, { color: getIconColor(item.disabled, item.selected), spacing: "spacious", label: undefined, "aria-hidden": true // Icon is described by the button for screen readers }) : undefined, iconAfter: item.iconAfter ? jsx(item.iconAfter, { label: "" }) : undefined, appearance: item.appearance, target: item.target, onClick: onClickHandler // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onMouseEnter: function onMouseEnter() { return dispatchCommand(item.onMouseEnter); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onMouseLeave: function onMouseLeave() { return dispatchCommand(item.onMouseLeave); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onFocus: function onFocus() { return dispatchCommand(item.onFocus); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onBlur: function onBlur() { return dispatchCommand(item.onBlur); }, onMount: item.onMount, onUnmount: item.onUnmount, selected: item.selected, disabled: item.disabled, tooltipContent: item.tooltipContent, testId: item.testId, hideTooltipOnClick: item.hideTooltipOnClick, ariaHasPopup: item.ariaHasPopup, tabIndex: item.tabIndex, isRadioButton: item.isRadioButton, ariaLabel: expValEquals('platform_editor_floating_toolbar_button_aria_label', 'isEnabled', true) ? item === null || item === void 0 ? void 0 : item.ariaLabel : undefined, pulse: item.pulse, interactionName: item.interactionName, areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled }, item.showTitle && item.title); case 'input': return jsx(Input, { key: idx, mountPoint: popupsMountPoint, boundariesElement: popupsBoundariesElement, defaultValue: item.defaultValue, placeholder: item.placeholder // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onSubmit: function onSubmit(value) { return dispatchCommand(item.onSubmit(value)); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onBlur: function onBlur(value) { return dispatchCommand(item.onBlur(value)); } }); case 'custom': { return item.render(editorView, idx, dispatchAnalyticsEvent); } case 'overflow-dropdown': // if an option has a confirmDialog, we need to replace its onClick handler // to set the state to show the confirm dialog // crudely done here to avoid greater coupling with DropdownMenuItem from `floating-toolbar` // which would need knowledge of indexes, showConfirmDialog etc. var options = item.options.map(function (option, optionIndex) { if (!('type' in option) && option.confirmDialog) { var onClick = option.confirmDialog ? showConfirmDialog(idx, optionIndex) : option.onClick; return _objectSpread(_objectSpread({}, option), {}, { onClick: onClick }); } return option; }); return jsx(Dropdown, { alignX: areAnyNewToolbarFlagsEnabled ? 'right' : undefined, key: idx, title: intl.formatMessage(commonMessages.viewMore), icon: jsx(ShowMoreHorizontalIcon, { label: "", spacing: "spacious" }), dispatchCommand: dispatchCommand, options: options, disabled: item.disabled, tooltip: item.tooltip, hideExpandIcon: true, mountPoint: popupsMountPoint, boundariesElement: popupsBoundariesElement, scrollableElement: popupsScrollableElement, dropdownWidth: item.dropdownWidth, showSelected: item.showSelected, buttonTestId: item.testId, editorView: editorView, setDisableParentScroll: scrollable ? setDisableScroll : undefined, dropdownListId: (item === null || item === void 0 ? void 0 : item.id) && "".concat(item.id, "-dropdownList"), alignDropdownWithToolbar: items.length === 1, onClick: item.onClick, areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled }); case 'dropdown': var DropdownIcon = item.icon; var BeforeIcon = item.iconBefore; return jsx(Dropdown, { key: idx, title: item.title, icon: DropdownIcon && jsx(DropdownIcon, { label: item.title }), iconBefore: BeforeIcon && jsx(BeforeIcon, { label: "" }), dispatchCommand: dispatchCommand, options: item.options, disabled: item.disabled, tooltip: item.tooltip, hideExpandIcon: item.hideExpandIcon, mountPoint: popupsMountPoint, boundariesElement: popupsBoundariesElement, scrollableElement: popupsScrollableElement, dropdownWidth: item.dropdownWidth, showSelected: item.showSelected, buttonTestId: item.testId, editorView: editorView, setDisableParentScroll: scrollable ? setDisableScroll : undefined, dropdownListId: (item === null || item === void 0 ? void 0 : item.id) && "".concat(item.id, "-dropdownList"), alignDropdownWithToolbar: items.length === 1, onToggle: item.onToggle, footer: item.footer, onMount: item.onMount, onClick: item.onClick, pulse: item.pulse, shouldFitContainer: item.shouldFitContainer, areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled }); case 'select': if (item.selectType === 'list') { var ariaLabel = item.title || item.placeholder; return jsx(Select, { key: idx, dispatchCommand: dispatchCommand, options: item.options, hideExpandIcon: item.hideExpandIcon // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion , mountPoint: scrollable ? mountRef.current : undefined, boundariesElement: popupsBoundariesElement, scrollableElement: popupsScrollableElement, defaultValue: item.defaultValue, placeholder: item.placeholder // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onChange: function onChange(selected) { return dispatchCommand(item.onChange(selected)); }, ariaLabel: ariaLabel, filterOption: item.filterOption, setDisableParentScroll: scrollable ? setDisableScroll : undefined, classNamePrefix: 'floating-toolbar-select' }); } if (item.selectType === 'color') { return jsx(ColorPickerButton, { skipFocusButtonAfterPick: true, key: idx, isAriaExpanded: item.isAriaExpanded, title: item.title // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onChange: function onChange(selected) { dispatchCommand(item.onChange(selected)); }, colorPalette: item.options, currentColor: item.defaultValue ? item.defaultValue.value : undefined, placement: "Panels", mountPoint: emojiAndColourPickerMountPoint, setDisableParentScroll: scrollable ? setDisableScroll : undefined // Currently in floating toolbar, color picker is only // used in panel and table cell background color. // Both uses same color palette. // That's why hard-coding hexToEditorBackgroundPaletteColor // and paletteColorTooltipMessages. // When we need to support different color palette // in floating toolbar, we need to set hexToPaletteColor // and paletteColorTooltipMessages in item options. , hexToPaletteColor: hexToEditorBackgroundPaletteColor, paletteColorTooltipMessages: backgroundPaletteTooltipMessages, returnEscToButton: item.returnEscToButton }); } if (item.selectType === 'emoji') { return jsx(EmojiPickerButton, { key: idx, editorView: editorView, title: item.title, providerFactory: providerFactory, isSelected: item.selected // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onChange: function onChange(selected) { return dispatchCommand(item.onChange(selected)); }, mountPoint: emojiAndColourPickerMountPoint, popupsBoundariesElement: popupsBoundariesElement, setDisableParentScroll: scrollable ? setDisableScroll : undefined, pluginInjectionApi: api }); } return null; case 'extensions-placeholder': if (!editorView || !extensionsProvider) { return null; } return jsx(ExtensionsPlaceholder, { key: idx, node: node, editorView: editorView, extensionProvider: extensionsProvider, separator: item.separator, applyChangeToContextPanel: api === null || api === void 0 || (_api$contextPanel = api.contextPanel) === null || _api$contextPanel === void 0 ? void 0 : _api$contextPanel.actions.applyChange, extensionApi: api === null || api === void 0 || (_api$extension = api.extension) === null || _api$extension === void 0 ? void 0 : _api$extension.actions.api(), dispatchCommand: dispatchCommand, popupsMountPoint: popupsMountPoint, popupsBoundariesElement: popupsBoundariesElement, popupsScrollableElement: popupsScrollableElement, alignDropdownWithToolbar: items.length === 1, scrollable: scrollable, areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled }); case 'separator': if (areAnyNewToolbarFlagsEnabled) { return item.fullHeight ? jsx(Separator, { key: idx, fullHeight: true, areAnyNewToolbarFlagsEnabled: true }) : null; } return jsx(Separator, { key: idx, fullHeight: item.fullHeight, areAnyNewToolbarFlagsEnabled: false }); } }; var groupedItems = groupItems( // eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render -- Ignored via go/ees017 (to be fixed) items.filter(function (item) { return !item.hidden; }), areAnyNewToolbarFlagsEnabled); return jsx(ButtonGroup, { testId: "editor-floating-toolbar-items" }, groupedItems.map(function (element, index) { var isGroup = Array.isArray(element); if (isGroup) { return jsx("div", { // Ignored via go/ees005 // eslint-disable-next-line react/no-array-index-key key: index, css: areAnyNewToolbarFlagsEnabled ? buttonGroupStylesNew : buttonGroupStyles, role: "radiogroup", "aria-label": groupLabel !== null && groupLabel !== void 0 ? groupLabel : undefined, "data-testid": "editor-floating-toolbar-grouped-buttons" }, element.map(function (element) { var indexInAllItems = items.findIndex(function (item) { return item === element; }); return renderItem(element, indexInAllItems); })); } else { var indexInAllItems = items.findIndex(function (item) { return item === element; }); return renderItem(element, indexInAllItems); } })); }, function (prevProps, nextProps) { if (!nextProps.node) { return false; } // only rerender toolbar items if the node is different // otherwise it causes an issue where multiple popups stays open return !(prevProps.node.type !== nextProps.node.type || prevProps.node.attrs.localId !== nextProps.node.attrs.localId || !areSameItems(prevProps.items, nextProps.items) || !prevProps.mounted !== !nextProps.mounted); }); var buttonGroupStyles = css({ display: 'flex', gap: "var(--ds-space-050, 4px)" }); var buttonGroupStylesNew = css({ display: 'flex', gap: "var(--ds-space-075, 6px)" }); // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage var toolbarContainer = function toolbarContainer(areAnyNewToolbarFlagsEnabled, scrollable, hasSelect, firstElementIsSelect) { return css({ backgroundColor: "var(--ds-surface-overlay, #FFFFFF)", borderRadius: "var(--ds-radius-small, 3px)", boxShadow: "var(--ds-shadow-overlay, 0px 8px 12px #1E1F2126, 0px 0px 1px #1E1F214f)", display: 'flex', // eslint-disable-next-line @atlaskit/design-system/use-tokens-typography lineHeight: 1, boxSizing: 'border-box', // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766 '& > div > div': { alignItems: 'center' } }, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 scrollable ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css( // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 hasSelect ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css({ height: '40px' }) : // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css({ height: '32px' }), { overflow: 'hidden' }) : // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values areAnyNewToolbarFlagsEnabled ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values css({ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 padding: "var(--ds-space-0, 0px)".concat(" 4px ", "var(--ds-space-0, 0px)", " 4px") }, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 firstElementIsSelect && // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css({ paddingLeft: "var(--ds-space-050, 4px)" })) : // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css({ padding: "var(--ds-space-050, 4px)".concat(" ", "var(--ds-space-100, 8px)") }, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 firstElementIsSelect && // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css({ paddingLeft: "var(--ds-space-050, 4px)" })), // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values areAnyNewToolbarFlagsEnabled ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values css({ minHeight: "var(--ds-space-500, 40px)" }) : undefined); }; // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage var toolbarOverflow = function toolbarOverflow(_ref2) { var scrollable = _ref2.scrollable, scrollDisabled = _ref2.scrollDisabled, firstElementIsSelect = _ref2.firstElementIsSelect, areAnyNewToolbarFlagsEnabled = _ref2.areAnyNewToolbarFlagsEnabled; return css( // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 scrollable ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css( // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 scrollDisabled ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css({ overflow: 'hidden' }) : // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values css({ overflowX: 'auto', overflowY: 'hidden', // When scrollable is true, ScrollButtons will be shown, hence we want to hide show default horizontal scrollbar scrollbarWidth: 'none' }), { WebkitOverflowScrolling: 'touch', // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 padding: "var(--ds-space-050, 4px)".concat(" 0 ", "var(--ds-space-050, 4px)"), // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766 '> div': { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 '> div:first-child': firstElementIsSelect ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css({ marginLeft: "var(--ds-space-050, 4px)" }) : // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css({ marginLeft: "var(--ds-space-100, 8px)" }), // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766 '> div:last-child': { marginRight: "var(--ds-space-100, 8px)" } } }, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values areAnyNewToolbarFlagsEnabled ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values css({ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 padding: "var(--ds-space-0, 0px)".concat(" 4px ", "var(--ds-space-600, 48px)", " 4px"), // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors '> div': { minHeight: "var(--ds-space-500, 40px)", gap: "var(--ds-space-075, 6px)", // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766 '> div:first-child': { marginLeft: 0 }, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766 '> div:last-child': { marginRight: 0 } } }) : undefined) : // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 css({ display: 'flex' })); }; // eslint-disable-next-line @repo/internal/react/no-class-components var Toolbar = /*#__PURE__*/function (_Component) { function Toolbar(props) { var _this; _classCallCheck(this, Toolbar); _this = _callSuper(this, Toolbar, [props]); _defineProperty(_this, "shouldHandleArrowKeys", function () { var _this$props$items; //To prevent the keydown handling of arrow keys for custom toolbar items with 'disableArrowNavigation' prop enabled, //Usually the button which has menus or popups return !((_this$props$items = _this.props.items) !== null && _this$props$items !== void 0 && _this$props$items.find(function (item) { return item.type === 'custom' && item.disableArrowNavigation; })); }); _defineProperty(_this, "handleEscape", function (event) { var _this$props$editorVie; // If any menu is open inside the floating toolbar 'Esc' key should not // focus the editorview. // Event can't be stopped as they are not childnodes of floating toolbar // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage var isDropdownOpen = !!document.querySelector('[data-role="droplistContent"]'); // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage var isSelectMenuOpen = !!document.querySelector('.floating-toolbar-select__menu'); if (isDropdownOpen || isSelectMenuOpen) { return; } (_this$props$editorVie = _this.props.editorView) === null || _this$props$editorVie === void 0 || _this$props$editorVie.focus(); event.preventDefault(); event.stopPropagation(); }); _defineProperty(_this, "captureMouseEvent", function (event) { var _this$props$items2; // Don't capture mouse event for custom toolbars e.g. insert hyperlink if (((_this$props$items2 = _this.props.items) === null || _this$props$items2 === void 0 ? void 0 : _this$props$items2.length) === 1 && _this.props.items[0].type === 'custom') { return; } // Prevents toolbar from closing when clicking on the toolbar itself and not on the buttons event.stopPropagation(); event.preventDefault(); }); _defineProperty(_this, "isShortcutToFocusToolbar", function (event) { //Alt + F10 to reach first element in this floating toolbar return event.altKey && (event.key === 'F10' || event.keyCode === 121); }); _defineProperty(_this, "doesNodeRequireAssitiveMessage", function (node) { // Code blocks have an assistive message to announce the content of the code block to screen readers, so we don't need to announce the floating toolbar for those nodes var nodesWithAlternativeRoles = ['codeBlock']; if (nodesWithAlternativeRoles.includes(node.type.name)) { return false; } return true; }); _this.scrollContainerRef = /*#__PURE__*/React.createRef(); _this.mountRef = /*#__PURE__*/React.createRef(); _this.toolbarContainerRef = /*#__PURE__*/React.createRef(); _this.state = { scrollDisabled: false, mounted: false }; return _this; } // remove any decorations added by toolbar buttons i.e danger and selected styling // this prevents https://product-fabric.atlassian.net/browse/ED-10207 _inherits(Toolbar, _Component); return _createClass(Toolbar, [{ key: "resetStyling", value: function resetStyling() { if (this.props.editorView) { var _this$props$api; var _this$props$editorVie2 = this.props.editorView, state = _this$props$editorVie2.state, dispatch = _this$props$editorVie2.dispatch; (_this$props$api = this.props.api) === null || _this$props$api === void 0 || (_this$props$api = _this$props$api.decorations) === null || _this$props$api === void 0 || _this$props$api.actions.removeDecoration(state, dispatch); } } }, { key: "setDisableScroll", value: function setDisableScroll(disabled) { var _this2 = this; // wait before setting disabled state incase users jumping from one popup to another if (disabled) { requestAnimationFrame(function () { _this2.setState({ scrollDisabled: disabled }); }); } else { this.setState({ scrollDisabled: disabled }); } } }, { key: "componentDidMount", value: function componentDidMount() { this.setState({ mounted: true }); } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var _this$props; checkShouldForceFocusAndApply((_this$props = this.props) === null || _this$props === void 0 ? void 0 : _this$props.editorView); if (this.props.node !== prevProps.node) { this.resetStyling(); } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { var editorView = this.props.editorView; if (editorView) { var tr = editorView.state.tr, dispatch = editorView.dispatch; dispatch(forceFocusSelector(null)(tr)); } this.resetStyling(); } }, { key: "render", value: function render() { var _this$props$api2; var _this$props2 = this.props, items = _this$props2.items, className = _this$props2.className, node = _this$props2.node, intl = _this$props2.intl, scrollable = _this$props2.scrollable, mediaAssistiveMessage = _this$props2.mediaAssistiveMessage; var areAnyNewToolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean((_this$props$api2 = this.props.api) === null || _this$props$api2 === void 0 ? void 0 : _this$props$api2.toolbar)); if (!items || !items.length) { return null; } // Select has left padding of 4px to the border, everything else 8px var firstElementIsSelect = items[0].type === 'select'; var hasSelect = items.find(function (item) { return item.type === 'select' && item.selectType === 'list'; }); var shouldRenderAssistiveAnnouncer = expValEquals('editor_a11y_role_textbox', 'isEnabled', true) ? this.doesNodeRequireAssitiveMessage(node) : true; return jsx(React.Fragment, null, jsx(ToolbarArrowKeyNavigationProvider, { editorView: this.props.editorView, handleEscape: this.handleEscape, disableArrowKeyNavigation: !this.shouldHandleArrowKeys(), childComponentSelector: "[data-testid='editor-floating-toolbar']", isShortcutToFocusToolbar: this.isShortcutToFocusToolbar, intl: intl }, jsx("div", { ref: this.toolbarContainerRef, css: function css() { return [toolbarContainer(areAnyNewToolbarFlagsEnabled, scrollable, hasSelect !== undefined, firstElementIsSelect)]; }, "aria-label": intl.formatMessage(messages.floatingToolbarAriaLabel), role: "toolbar", "data-testid": "editor-floating-toolbar" // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , className: className, onMouseDown: areAnyNewToolbarFlagsEnabled ? this.captureMouseEvent : undefined }, shouldRenderAssistiveAnnouncer && jsx(Announcer, { text: mediaAssistiveMessage ? "".concat(mediaAssistiveMessage, ", ").concat(intl.formatMessage(messages.floatingToolbarAnnouncer)) : intl.formatMessage(messages.floatingToolbarAnnouncer), delay: 250 }), scrollable && areAnyNewToolbarFlagsEnabled && jsx(ScrollButton, { intl: intl, scrollContainerRef: this.scrollContainerRef, node: node, disabled: this.state.scrollDisabled, side: "left" }), jsx("div", { "data-testid": "floating-toolbar-items", ref: this.scrollContainerRef // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage , css: toolbarOverflow({ areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled, scrollable: scrollable, scrollDisabled: this.state.scrollDisabled, firstElementIsSelect: firstElementIsSelect }) }, jsx(ToolbarItems // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading , _extends({}, this.props, { setDisableScroll: this.setDisableScroll.bind(this), mountRef: this.mountRef, mounted: this.state.mounted }))), scrollable && (areAnyNewToolbarFlagsEnabled ? jsx(ScrollButton, { intl: intl, scrollContainerRef: this.scrollContainerRef, node: node, disabled: this.state.scrollDisabled, side: "right" }) : jsx(ScrollButtons, { intl: intl, scrollContainerRef: this.scrollContainerRef, node: node, disabled: this.state.scrollDisabled, areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled }))), jsx("div", { ref: this.mountRef }))); } }]); }(Component); // eslint-disable-next-line @typescript-eslint/ban-types var _default_1 = injectIntl(Toolbar); export default _default_1;