UNPKG

@atlaskit/editor-plugin-card

Version:

Card plugin for @atlaskit/editor-core

165 lines 7.09 kB
import React, { useEffect, useRef, useState } from 'react'; import { appearancePropsMap } from '@atlaskit/editor-common/card'; import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check'; import { FloatingToolbarButton as Button, FloatingToolbarSeparator as Separator } from '@atlaskit/editor-common/ui'; import { ArrowKeyNavigationType, DropdownContainer as UiDropdown } from '@atlaskit/editor-common/ui-menu'; import ChevronDownIcon from '@atlaskit/icon/core/chevron-down'; import { Flex } from '@atlaskit/primitives/compiled'; import { LinkAppearanceMenu } from './LinkToolbarAppearanceDropdown'; const CustomHyperlinkDropdown = props => { var _props$editorPluginAp, _props$cardOptions3, _props$editorPluginAp6, _props$editorPluginAp7; const [supportedUrlsMap, setSupportedUrlsMap] = useState(new Map()); const [isOpen, setIsOpen] = useState(false); const cardProvider = useRef(undefined); const containerRef = useRef(undefined); const areAnyNewToolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean((_props$editorPluginAp = props.editorPluginApi) === null || _props$editorPluginAp === void 0 ? void 0 : _props$editorPluginAp.toolbar)); const { url, intl, editorView, cardOptions, editorAnalyticsApi, allowDatasource, isDatasourceView, settingsConfig } = props; // Ignored via go/ees005 // eslint-disable-next-line require-await const getProvider = async () => { var _props$cardOptions; if ((_props$cardOptions = props.cardOptions) !== null && _props$cardOptions !== void 0 && _props$cardOptions.provider) { var _props$cardOptions2; return (_props$cardOptions2 = props.cardOptions) === null || _props$cardOptions2 === void 0 ? void 0 : _props$cardOptions2.provider; } if (cardProvider.current) { return cardProvider.current; } return new Promise(resolve => { var _props$editorPluginAp2, _props$editorPluginAp3, _props$editorPluginAp4, _props$editorPluginAp5; const cardProvider = (_props$editorPluginAp2 = props.editorPluginApi) === null || _props$editorPluginAp2 === void 0 ? void 0 : (_props$editorPluginAp3 = _props$editorPluginAp2.card) === null || _props$editorPluginAp3 === void 0 ? void 0 : (_props$editorPluginAp4 = _props$editorPluginAp3.sharedState) === null || _props$editorPluginAp4 === void 0 ? void 0 : (_props$editorPluginAp5 = _props$editorPluginAp4.currentState()) === null || _props$editorPluginAp5 === void 0 ? void 0 : _props$editorPluginAp5.provider; if (cardProvider) { resolve(cardProvider); } }); }; const resolveUrl = async url => { if (supportedUrlsMap.has(url)) { return; } let isUrlSupported = false; try { var _await$provider$findP; const provider = await getProvider(); isUrlSupported = (_await$provider$findP = await (provider === null || provider === void 0 ? void 0 : provider.findPattern(url))) !== null && _await$provider$findP !== void 0 ? _await$provider$findP : false; } catch (error) { // eslint-disable-line no-unused-vars isUrlSupported = false; } const newMap = new Map(supportedUrlsMap); newMap.set(url, isUrlSupported); setSupportedUrlsMap(newMap); }; useEffect(() => { resolveUrl(url); // before migrating from a class to a functional component, we were only reacting to changes in the url // eslint-disable-next-line react-hooks/exhaustive-deps }, [url, (_props$cardOptions3 = props.cardOptions) === null || _props$cardOptions3 === void 0 ? void 0 : _props$cardOptions3.provider, props.editorPluginApi]); if (!supportedUrlsMap.get(url)) { return null; } if (!editorView) { return null; } const dispatchCommand = fn => { fn && fn(editorView && editorView.state, editorView && editorView.dispatch, editorView); // Refocus the view to ensure the editor has focus if (editorView && !editorView.hasFocus()) { editorView.focus(); } }; const toggleOpen = () => setIsOpen(open => !open); const close = () => setIsOpen(false); const currentAppearanceDisplayInformation = appearancePropsMap['url']; const title = intl.formatMessage(currentAppearanceDisplayInformation.title); const trigger = /*#__PURE__*/React.createElement(Button, { selected: isOpen, title: title, "aria-label": title, "aria-expanded": isOpen, "aria-haspopup": true, onClick: toggleOpen, icon: currentAppearanceDisplayInformation.icon({ label: '' }), iconAfter: /*#__PURE__*/React.createElement(ChevronDownIcon, { label: "", spacing: "compact", size: "small" }), areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled }, title); return /*#__PURE__*/React.createElement(Flex, { ref: containerRef, gap: "space.075" }, /*#__PURE__*/React.createElement(UiDropdown, { mountTo: containerRef.current, isOpen: isOpen, handleClickOutside: close, handleEscapeKeydown: close, trigger: trigger, scrollableElement: containerRef.current // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , arrowKeyNavigationProviderOptions: { type: ArrowKeyNavigationType.MENU }, fitHeight: 400, fitWidth: 200 }, /*#__PURE__*/React.createElement(LinkAppearanceMenu, { url: url, intl: intl, currentAppearance: undefined, editorState: editorView.state, allowEmbeds: cardOptions === null || cardOptions === void 0 ? void 0 : cardOptions.allowEmbeds, allowBlockCards: cardOptions === null || cardOptions === void 0 ? void 0 : cardOptions.allowBlockCards, editorAnalyticsApi: editorAnalyticsApi, isDatasourceView: isDatasourceView, allowDatasource: allowDatasource, dispatchCommand: dispatchCommand, settingsConfig: settingsConfig, areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled })), !areToolbarFlagsEnabled(Boolean((_props$editorPluginAp6 = props.editorPluginApi) === null || _props$editorPluginAp6 === void 0 ? void 0 : _props$editorPluginAp6.toolbar)) && /*#__PURE__*/React.createElement(Separator, { areAnyNewToolbarFlagsEnabled: areToolbarFlagsEnabled(Boolean((_props$editorPluginAp7 = props.editorPluginApi) === null || _props$editorPluginAp7 === void 0 ? void 0 : _props$editorPluginAp7.toolbar)) })); }; export const getCustomHyperlinkAppearanceDropdown = ({ url, intl, editorAnalyticsApi, editorPluginApi, settingsConfig, cardOptions, allowDatasource, isDatasourceView }) => { return { type: 'custom', fallback: [], render: editorView => { if (!editorView) { return; } return /*#__PURE__*/React.createElement(CustomHyperlinkDropdown, { intl: intl, url: url, editorAnalyticsApi: editorAnalyticsApi, editorPluginApi: editorPluginApi, editorView: editorView, settingsConfig: settingsConfig, cardOptions: cardOptions, allowDatasource: allowDatasource, isDatasourceView: isDatasourceView }); } }; };