import { toastError } from "../error/toast-error"; import { $authTokenPermissions, $textEditingInstanceSelector, } from "../nano-states"; const isTextEditing = (event: ClipboardEvent) => { // Text is edited on the Canvas using the default Canvas text editor settings. if ($textEditingInstanceSelector.get() != null) { return true; } // Text is edited inside an input, textarea, or contenteditable (i.e. codemirror editor) field. if ( event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement || (event.target instanceof HTMLElement && event.target.closest("[contenteditable]")) ) { return true; } return false; }; /** * * # Note: * validateClipboardEvent determines when to use default copy/paste behavior or if a WebStudio instance will be copied, pasted, or cut. * # How to test: * 1. Focus on an input in the style panel (width, style source) or name input in settings. Select the text, then copy and paste any instance in the Navigator tree or on the Canvas. * 2. Edit text in a paragraph on the Canvas. Select text (single or multiple lines), then press Cmd+X. The paragraph should not be deleted. * 3. Select CSS preview text, then select an instance in the Navigator. Press Cmd+C, then Cmd+V. **/ const validateClipboardEvent = (event: ClipboardEvent) => { if (event.clipboardData === null) { return false; } if (isTextEditing(event)) { return false; } // Allows native selection of text in the Builder panels, such as CSS Preview. if (event.type === "copy") { const isInBuilderContext = window.self === window.top; if (isInBuilderContext) { // Note on event.target: // // The spec (https://w3c.github.io/clipboard-apis/#to-fire-a-clipboard-event) // says that if the context is not editable, the target should be the focused node. // // But in practice it seems that the target is based // on where the cursor is, rather than which element has focus. // For example, if a