@gechiui/block-editor
Version:
154 lines (135 loc) • 5.21 kB
JavaScript
import { createElement } from "@gechiui/element";
/**
* GeChiUI dependencies
*/
import { useCallback } from '@gechiui/element';
import { serialize, pasteHandler, store as blocksStore } from '@gechiui/blocks';
import { documentHasSelection, documentHasUncollapsedSelection } from '@gechiui/dom';
import { useDispatch, useSelect } from '@gechiui/data';
import { __, _n, sprintf } from '@gechiui/i18n';
import { store as noticesStore } from '@gechiui/notices';
import { useRefEffect } from '@gechiui/compose';
/**
* Internal dependencies
*/
import { getPasteEventData } from '../../utils/get-paste-event-data';
import { store as blockEditorStore } from '../../store';
export function useNotifyCopy() {
const {
getBlockName
} = useSelect(blockEditorStore);
const {
getBlockType
} = useSelect(blocksStore);
const {
createSuccessNotice
} = useDispatch(noticesStore);
return useCallback((eventType, selectedBlockClientIds) => {
let notice = '';
if (selectedBlockClientIds.length === 1) {
var _getBlockType;
const clientId = selectedBlockClientIds[0];
const title = (_getBlockType = getBlockType(getBlockName(clientId))) === null || _getBlockType === void 0 ? void 0 : _getBlockType.title;
notice = eventType === 'copy' ? sprintf( // Translators: Name of the block being copied, e.g. "Paragraph".
__('“%s”区块已复制至剪贴板。'), title) : sprintf( // Translators: Name of the block being cut, e.g. "Paragraph".
__('“%s”区块已移动至剪贴板。'), title);
} else {
notice = eventType === 'copy' ? sprintf( // Translators: %d: Number of blocks being copied.
_n('已将%d区块复制至剪贴板。', 'Copied %d blocks to clipboard.', selectedBlockClientIds.length), selectedBlockClientIds.length) : sprintf( // Translators: %d: Number of blocks being cut.
_n('已将%d区块移至剪贴板。', 'Moved %d blocks to clipboard.', selectedBlockClientIds.length), selectedBlockClientIds.length);
}
createSuccessNotice(notice, {
type: 'snackbar'
});
}, []);
}
export function useClipboardHandler() {
const {
getBlocksByClientId,
getSelectedBlockClientIds,
hasMultiSelection,
getSettings
} = useSelect(blockEditorStore);
const {
flashBlock,
removeBlocks,
replaceBlocks
} = useDispatch(blockEditorStore);
const notifyCopy = useNotifyCopy();
return useRefEffect(node => {
function handler(event) {
const selectedBlockClientIds = getSelectedBlockClientIds();
if (selectedBlockClientIds.length === 0) {
return;
} // Always handle multiple selected blocks.
if (!hasMultiSelection()) {
const {
target
} = event;
const {
ownerDocument
} = target; // If copying, only consider actual text selection as selection.
// Otherwise, any focus on an input field is considered.
const hasSelection = event.type === 'copy' || event.type === 'cut' ? documentHasUncollapsedSelection(ownerDocument) : documentHasSelection(ownerDocument); // Let native copy behaviour take over in input fields.
if (hasSelection) {
return;
}
}
if (!node.contains(event.target.ownerDocument.activeElement)) {
return;
}
const eventDefaultPrevented = event.defaultPrevented;
event.preventDefault();
if (event.type === 'copy' || event.type === 'cut') {
if (selectedBlockClientIds.length === 1) {
flashBlock(selectedBlockClientIds[0]);
}
notifyCopy(event.type, selectedBlockClientIds);
const blocks = getBlocksByClientId(selectedBlockClientIds);
const serialized = serialize(blocks);
event.clipboardData.setData('text/plain', serialized);
event.clipboardData.setData('text/html', serialized);
}
if (event.type === 'cut') {
removeBlocks(selectedBlockClientIds);
} else if (event.type === 'paste') {
if (eventDefaultPrevented) {
// This was likely already handled in rich-text/use-paste-handler.js
return;
}
const {
__experimentalCanUserUseUnfilteredHTML: canUserUseUnfilteredHTML
} = getSettings();
const {
plainText,
html
} = getPasteEventData(event);
const blocks = pasteHandler({
HTML: html,
plainText,
mode: 'BLOCKS',
canUserUseUnfilteredHTML
});
replaceBlocks(selectedBlockClientIds, blocks, blocks.length - 1, -1);
}
}
node.ownerDocument.addEventListener('copy', handler);
node.ownerDocument.addEventListener('cut', handler);
node.ownerDocument.addEventListener('paste', handler);
return () => {
node.ownerDocument.removeEventListener('copy', handler);
node.ownerDocument.removeEventListener('cut', handler);
node.ownerDocument.removeEventListener('paste', handler);
};
}, []);
}
function CopyHandler(_ref) {
let {
children
} = _ref;
return createElement("div", {
ref: useClipboardHandler()
}, children);
}
export default CopyHandler;
//# sourceMappingURL=index.js.map