UNPKG

@atlaskit/editor-plugin-card

Version:

Card plugin for @atlaskit/editor-core

191 lines (189 loc) 6.96 kB
import React from 'react'; import { ACTION, buildEditLinkPayload, INPUT_METHOD } from '@atlaskit/editor-common/analytics'; import { commandWithMetadata } from '@atlaskit/editor-common/card'; import { HyperlinkAddToolbar as HyperlinkToolbar } from '@atlaskit/editor-common/link'; import { linkToolbarMessages } from '@atlaskit/editor-common/messages'; import { LINKPICKER_HEIGHT_IN_PX, RECENT_SEARCH_HEIGHT_IN_PX, RECENT_SEARCH_WIDTH_IN_PX } from '@atlaskit/editor-common/ui'; import { NodeSelection } from '@atlaskit/editor-prosemirror/state'; import { hideLinkToolbar, showLinkToolbar } from '../pm-plugins/actions'; import { changeSelectedCardToLink, updateCard } from '../pm-plugins/doc'; import { displayInfoForCard, findCardInfo } from '../pm-plugins/utils'; export function HyperlinkAddToolbarWithState({ linkPickerOptions = {}, onSubmit, displayText, displayUrl, providerFactory, view, onCancel, invokeMethod, lpLinkPicker, onClose, onEscapeCallback, onClickAwayCallback }) { return /*#__PURE__*/React.createElement(HyperlinkToolbar, { linkPickerOptions: linkPickerOptions, onSubmit: onSubmit, displayText: displayText, displayUrl: displayUrl, providerFactory: providerFactory, view: view, onCancel: onCancel, invokeMethod: invokeMethod, lpLinkPicker: lpLinkPicker, onClose: onClose, onEscapeCallback: onEscapeCallback, onClickAwayCallback: onClickAwayCallback }); } // eslint-disable-next-line @repo/internal/react/no-class-components export class EditLinkToolbar extends React.Component { componentDidUpdate(prevProps) { if (prevProps.node !== this.props.node) { this.hideLinkToolbar(); } } componentWillUnmount() { this.hideLinkToolbar(); } hideLinkToolbar() { const { view } = this.props; view.dispatch(hideLinkToolbar(view.state.tr)); } render() { const { linkPickerOptions, providerFactory, url, text, view, onSubmit, forceFocusSelector, lpLinkPicker } = this.props; return /*#__PURE__*/React.createElement(HyperlinkAddToolbarWithState, { view: view, linkPickerOptions: linkPickerOptions, providerFactory: providerFactory, displayUrl: url, displayText: text // Assumes that the smart card link picker can only ever be invoked by clicking "edit" // via the floating toolbar , invokeMethod: INPUT_METHOD.FLOATING_TB, lpLinkPicker: lpLinkPicker // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onSubmit: (href, title, displayText, inputMethod, analytic) => { this.hideLinkToolbar(); if (onSubmit) { onSubmit(href, displayText || title, inputMethod, analytic); } } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onEscapeCallback: (state, dispatch) => { const { tr } = state; hideLinkToolbar(tr); forceFocusSelector === null || forceFocusSelector === void 0 ? void 0 : forceFocusSelector(`[aria-label="${linkToolbarMessages.editLink.defaultMessage}"]`)(tr); if (dispatch) { dispatch(tr); return true; } return false; } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onClickAwayCallback: (state, dispatch) => { const { tr } = state; if (dispatch) { dispatch(tr); return true; } return false; } }); } } export const getEditLinkCallback = (editorAnalyticsApi, scrollIntoView) => (state, dispatch) => { let type = 'hyperlink'; if (state.selection instanceof NodeSelection) { type = state.selection.node.type.name; } if (dispatch) { const { tr } = state; showLinkToolbar(tr); editorAnalyticsApi === null || editorAnalyticsApi === void 0 ? void 0 : editorAnalyticsApi.attachAnalyticsEvent(buildEditLinkPayload(type))(tr); tr.setMeta('scrollIntoView', scrollIntoView); dispatch(tr); return true; } return false; }; export const buildEditLinkToolbar = ({ providerFactory, node, pluginInjectionApi, linkPicker, lpLinkPicker }) => { return { type: 'custom', disableArrowNavigation: true, fallback: [], render: (view, idx) => { var _pluginInjectionApi$f, _pluginInjectionApi$f2; if (!view || !providerFactory) { return null; } const displayInfo = displayInfoForCard(node, findCardInfo(view.state)); return /*#__PURE__*/React.createElement(EditLinkToolbar, { key: idx, view: view, linkPickerOptions: linkPicker, providerFactory: providerFactory, url: displayInfo.url, text: displayInfo.title || '', node: node, lpLinkPicker: lpLinkPicker, forceFocusSelector: pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$f = pluginInjectionApi.floatingToolbar) === null || _pluginInjectionApi$f === void 0 ? void 0 : (_pluginInjectionApi$f2 = _pluginInjectionApi$f.actions) === null || _pluginInjectionApi$f2 === void 0 ? void 0 : _pluginInjectionApi$f2.forceFocusSelector // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onSubmit: (newHref, newText, inputMethod, analytic) => { const urlChanged = newHref !== displayInfo.url; const titleChanged = newText !== displayInfo.title; // If the title is changed in a smartlink, convert to standard blue hyperlink // (even if the url was also changed) - we don't want to lose the custom title. if (titleChanged) { var _pluginInjectionApi$a; return commandWithMetadata(changeSelectedCardToLink(newText, newHref, undefined, undefined, undefined, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions), { action: ACTION.UPDATED, inputMethod, sourceEvent: analytic })(view.state, view.dispatch); } if (urlChanged) { // If *only* the url is changed in a smart link, reresolve return updateCard(newHref, analytic)(view.state, view.dispatch); } } }); } }; }; export const editLinkToolbarConfig = (showLinkingToolbar, lpLinkPicker) => { return showLinkingToolbar ? { height: lpLinkPicker ? LINKPICKER_HEIGHT_IN_PX : RECENT_SEARCH_HEIGHT_IN_PX, width: RECENT_SEARCH_WIDTH_IN_PX, forcePlacement: true } : {}; };