@atlaskit/editor-plugin-copy-button
Version:
editor-plugin-copy-button for @atlaskit/editor-core
163 lines (158 loc) • 7.33 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createToolbarCopyCommandForMark = createToolbarCopyCommandForMark;
exports.createToolbarCopyCommandForNode = void 0;
exports.getProvideMarkVisualFeedbackForCopyButtonCommand = getProvideMarkVisualFeedbackForCopyButtonCommand;
exports.removeMarkVisualFeedbackForCopyButtonCommand = removeMarkVisualFeedbackForCopyButtonCommand;
exports.resetCopiedState = void 0;
var _enums = require("@atlaskit/editor-common/analytics/types/enums");
var _clipboard = require("@atlaskit/editor-common/clipboard");
var _copyButton = require("@atlaskit/editor-common/copy-button");
var _pluginKey = require("./plugin-key");
function createToolbarCopyCommandForMark(markType, editorAnalyticsApi) {
function command(state, dispatch) {
var textNode = state.tr.selection.$head.parent.maybeChild(state.tr.selection.$head.index());
if (!textNode) {
return false;
}
if (dispatch) {
// As calling copyHTMLToClipboard causes side effects -- we only run this when
// dispatch is provided -- as otherwise the consumer is only testing to see if
// the action is availble.
var domNode = (0, _copyButton.toDOM)(textNode, state.schema);
if (domNode) {
var div = document.createElement('div');
var p = document.createElement('p');
div.appendChild(p);
p.appendChild(domNode);
// The "1 1" refers to the start and end depth of the slice
// since we're copying the text inside a paragraph, it will always be 1 1
// https://github.com/ProseMirror/prosemirror-view/blob/master/src/clipboard.ts#L32
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
div.firstChild.setAttribute('data-pm-slice', '1 1 []');
// If we're copying a hyperlink, we'd copy the url as the fallback plain text
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
var linkUrl = domNode.getAttribute('href');
(0, _clipboard.copyHTMLToClipboard)(div, markType.name === 'link' && linkUrl ? linkUrl : undefined);
}
var copyToClipboardTr = state.tr;
copyToClipboardTr.setMeta(_pluginKey.copyButtonPluginKey, {
copied: true
});
var analyticsPayload = (0, _clipboard.getAnalyticsPayload)(state, _enums.ACTION.COPIED);
if (analyticsPayload && editorAnalyticsApi) {
var _editorAnalyticsApi$a;
analyticsPayload.attributes.inputMethod = _enums.INPUT_METHOD.FLOATING_TB;
analyticsPayload.attributes.markType = markType.name;
editorAnalyticsApi === null || editorAnalyticsApi === void 0 || (_editorAnalyticsApi$a = editorAnalyticsApi.attachAnalyticsEvent) === null || _editorAnalyticsApi$a === void 0 || _editorAnalyticsApi$a.call(editorAnalyticsApi, analyticsPayload)(copyToClipboardTr);
}
dispatch(copyToClipboardTr);
}
return true;
}
return command;
}
function getProvideMarkVisualFeedbackForCopyButtonCommand(markType) {
function provideMarkVisualFeedbackForCopyButtonCommand(state, dispatch) {
var tr = state.tr;
tr.setMeta(_pluginKey.copyButtonPluginKey, {
showSelection: true,
markType: markType
});
if (dispatch) {
dispatch(tr);
}
return true;
}
return provideMarkVisualFeedbackForCopyButtonCommand;
}
function removeMarkVisualFeedbackForCopyButtonCommand(state, dispatch) {
var tr = state.tr;
tr.setMeta(_pluginKey.copyButtonPluginKey, {
removeSelection: true
});
var copyButtonState = _pluginKey.copyButtonPluginKey.getState(state);
if (copyButtonState !== null && copyButtonState !== void 0 && copyButtonState.copied) {
tr.setMeta(_pluginKey.copyButtonPluginKey, {
copied: false
});
}
if (dispatch) {
dispatch(tr);
}
return true;
}
var createToolbarCopyCommandForNode = exports.createToolbarCopyCommandForNode = function createToolbarCopyCommandForNode(nodeType, editorAnalyticsApi, api, onClickMessage) {
return function (state, dispatch) {
var tr = state.tr,
schema = state.schema;
// This command should only be triggered by the Copy button in the floating toolbar
// which is only visible when selection is inside the target node
var contentNodeWithPos = (0, _copyButton.getSelectedNodeOrNodeParentByNodeType)({
nodeType: nodeType,
selection: tr.selection
});
if (!contentNodeWithPos) {
return false;
}
var copyToClipboardTr = tr;
copyToClipboardTr.setMeta(_pluginKey.copyButtonPluginKey, {
copied: true
});
var analyticsPayload = (0, _clipboard.getAnalyticsPayload)(state, _enums.ACTION.COPIED);
if (analyticsPayload && editorAnalyticsApi) {
var _editorAnalyticsApi$a2;
analyticsPayload.attributes.inputMethod = _enums.INPUT_METHOD.FLOATING_TB;
analyticsPayload.attributes.nodeType = contentNodeWithPos.node.type.name;
editorAnalyticsApi === null || editorAnalyticsApi === void 0 || (_editorAnalyticsApi$a2 = editorAnalyticsApi.attachAnalyticsEvent) === null || _editorAnalyticsApi$a2 === void 0 || _editorAnalyticsApi$a2.call(editorAnalyticsApi, analyticsPayload)(copyToClipboardTr);
}
if (dispatch) {
// As calling copyHTMLToClipboard causes side effects -- we only run this when
// dispatch is provided -- as otherwise the consumer is only testing to see if
// the action is availble.
var domNode = (0, _copyButton.toDOM)(contentNodeWithPos.node, schema);
(0, _copyButton.copyDomNode)(domNode, contentNodeWithPos.node.type, tr.selection);
copyToClipboardTr.setMeta('scrollIntoView', false);
dispatch(copyToClipboardTr);
}
/**
* A11y-10275 This prop api drilled from the plugin all the way down to the usage
* because it's the safest way to ensure accessibilityUtils is available and not
* undefined.
*
* see thread https://atlassian.slack.com/archives/C02CDUS3SUS/p1744256326459569
*/
if (onClickMessage) {
var _api$accessibilityUti;
api === null || api === void 0 || (_api$accessibilityUti = api.accessibilityUtils) === null || _api$accessibilityUti === void 0 || _api$accessibilityUti.actions.ariaNotify(onClickMessage, {
priority: 'important'
});
}
return true;
};
};
var resetCopiedState = exports.resetCopiedState = function resetCopiedState(nodeType, hoverDecoration, onMouseLeave) {
return function (state, dispatch) {
var customTr = state.tr;
// Avoid multipe dispatch
// https://product-fabric.atlassian.net/wiki/spaces/E/pages/2241659456/All+about+dispatch+and+why+there+shouldn+t+be+multiple#How-do-I-avoid-them%3F
var customDispatch = function customDispatch(tr) {
customTr = tr;
};
onMouseLeave ? onMouseLeave(state, customDispatch) : hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(nodeType, false)(state, customDispatch);
var copyButtonState = _pluginKey.copyButtonPluginKey.getState(state);
if (copyButtonState !== null && copyButtonState !== void 0 && copyButtonState.copied) {
customTr.setMeta(_pluginKey.copyButtonPluginKey, {
copied: false
});
}
if (dispatch) {
dispatch(customTr);
}
return true;
};
};