UNPKG

@atlaskit/editor-common

Version:

A package that contains common classes and components for editor and renderer

136 lines (135 loc) 3.98 kB
import React, { useEffect, useRef, useState } from 'react'; import Loadable from 'react-loadable'; import { getContextualToolbarItemsFromModule } from '../extensions'; import { nodeToJSON } from '../utils'; import { DropdownMenuItem } from './DropdownMenuItem'; import { DropdownSeparator } from './DropdownSeparator'; const noop = () => null; const isDefaultExport = mod => { return mod.hasOwnProperty('default'); }; const resolveExtensionIcon = async getIcon => { if (!getIcon) { return noop; } const maybeIcon = await getIcon(); return isDefaultExport(maybeIcon) ? maybeIcon.default : maybeIcon; }; const convertExtensionToDropdownMenuItem = ({ item, disabled, node, extension, IconComponent }) => { let title = ''; if (item.label) { title = item.label; } else if (typeof item.tooltip === 'string') { title = item.tooltip; } else if (item.ariaLabel) { title = item.ariaLabel; } item.disabled = (disabled === null || disabled === void 0 ? void 0 : disabled(item.key)) || false; const getIcon = () => { const label = item.label || ''; return IconComponent ? /*#__PURE__*/React.createElement(IconComponent, { label: label }) : undefined; }; return { title, icon: getIcon(), disabled: item.disabled, onClick: () => { if (typeof item.action !== 'function') { throw new Error(`'action' of context toolbar item '${item.key}' is not a function`); } const targetNodeAdf = nodeToJSON(node); extension.extensionApi && item.action(targetNodeAdf, extension.extensionApi); return true; } }; }; const DropdownMenuExtensionItem = ({ item, editorView, disabled, node, extension, dropdownOptions }) => { // Use ref to keep icon component stable across renders const iconRef = useRef(null); if (!iconRef.current && item.icon) { iconRef.current = Loadable({ loader: () => resolveExtensionIcon(item.icon), loading: noop }); } const dropdownItem = convertExtensionToDropdownMenuItem({ item, disabled, node, extension, IconComponent: iconRef.current }); if (!dropdownItem) { return null; } return /*#__PURE__*/React.createElement(DropdownMenuItem, { key: item.key, item: dropdownItem, editorView: editorView, hide: dropdownOptions.hide, dispatchCommand: dropdownOptions.dispatchCommand, showSelected: dropdownOptions.showSelected, intl: dropdownOptions.intl }); }; export const DropdownMenuExtensionItems = props => { const { node, editorView, extension, disabled, dropdownOptions, areAnyNewToolbarFlagsEnabled } = props; // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any const [extensions, setExtensions] = useState([]); useEffect(() => { getExtensions(); async function getExtensions() { const provider = await extension.extensionProvider; if (provider) { setExtensions(await provider.getExtensions()); } } }, [extension.extensionProvider]); const nodeAdf = React.useMemo(() => nodeToJSON(node), [node]); const extensionItems = React.useMemo(() => { if (!extension.extensionApi) { return []; } return getContextualToolbarItemsFromModule(extensions, nodeAdf, extension.extensionApi); }, [extensions, nodeAdf, extension.extensionApi]); if (!extensionItems.length || !dropdownOptions) { return null; } return /*#__PURE__*/React.createElement(React.Fragment, null, extensionItems.map((item, _idx) => { if (!('key' in item)) { return null; } return /*#__PURE__*/React.createElement(DropdownMenuExtensionItem, { key: item.key, item: item, editorView: editorView, disabled: disabled, node: node, extension: extension, dropdownOptions: dropdownOptions }); }), areAnyNewToolbarFlagsEnabled && /*#__PURE__*/React.createElement(DropdownSeparator, null)); };