diff --git a/packages/editor/api-report.md b/packages/editor/api-report.md index b7120e987..24661b09f 100644 --- a/packages/editor/api-report.md +++ b/packages/editor/api-report.md @@ -720,11 +720,11 @@ export const defaultUserPreferences: Readonly<{ color: "#02B1CC" | "#11B3A3" | "#39B178" | "#55B467" | "#7B66DC" | "#9D5BD2" | "#BD54C6" | "#E34BA9" | "#EC5E41" | "#F04F88" | "#F2555A" | "#FF802B"; edgeScrollSpeed: 1; isDynamicSizeMode: false; + isPasteAtCursorMode: false; isSnapMode: false; isWrapMode: false; locale: "ar" | "ca" | "cs" | "da" | "de" | "en" | "es" | "fa" | "fi" | "fr" | "gl" | "he" | "hi-in" | "hr" | "hu" | "id" | "it" | "ja" | "ko-kr" | "ku" | "my" | "ne" | "no" | "pl" | "pt-br" | "pt-pt" | "ro" | "ru" | "sl" | "sv" | "te" | "th" | "tr" | "uk" | "vi" | "zh-cn" | "zh-tw"; name: "New User"; - pasteAtCursor: false; }>; // @public @@ -3365,6 +3365,8 @@ export interface TLUserPreferences { // (undocumented) isDynamicSizeMode?: boolean | null; // (undocumented) + isPasteAtCursorMode?: boolean | null; + // (undocumented) isSnapMode?: boolean | null; // (undocumented) isWrapMode?: boolean | null; @@ -3372,8 +3374,6 @@ export interface TLUserPreferences { locale?: null | string; // (undocumented) name?: null | string; - // (undocumented) - pasteAtCursor?: boolean | null; } // @public (undocumented) @@ -3475,6 +3475,8 @@ export class UserPreferencesManager { // (undocumented) getIsDynamicResizeMode(): boolean; // (undocumented) + getIsPasteAtCursorMode(): boolean; + // (undocumented) getIsSnapMode(): boolean; // (undocumented) getIsWrapMode(): boolean; @@ -3483,8 +3485,6 @@ export class UserPreferencesManager { // (undocumented) getName(): string; // (undocumented) - getPasteAtCursor(): boolean; - // (undocumented) getUserPreferences(): { animationSpeed: number; color: string; diff --git a/packages/editor/src/lib/config/TLUserPreferences.ts b/packages/editor/src/lib/config/TLUserPreferences.ts index c657bc34d..9afc02d45 100644 --- a/packages/editor/src/lib/config/TLUserPreferences.ts +++ b/packages/editor/src/lib/config/TLUserPreferences.ts @@ -22,7 +22,7 @@ export interface TLUserPreferences { isSnapMode?: boolean | null isWrapMode?: boolean | null isDynamicSizeMode?: boolean | null - pasteAtCursor?: boolean | null + isPasteAtCursorMode?: boolean | null } interface UserDataSnapshot { @@ -47,7 +47,7 @@ const userTypeValidator: T.Validator = T.object> /** @public */ diff --git a/packages/editor/src/lib/editor/managers/UserPreferencesManager.ts b/packages/editor/src/lib/editor/managers/UserPreferencesManager.ts index d830045a4..7dadbc201 100644 --- a/packages/editor/src/lib/editor/managers/UserPreferencesManager.ts +++ b/packages/editor/src/lib/editor/managers/UserPreferencesManager.ts @@ -98,7 +98,10 @@ export class UserPreferencesManager { ) } - @computed getPasteAtCursor() { - return this.user.userPreferences.get().pasteAtCursor ?? defaultUserPreferences.pasteAtCursor + @computed getIsPasteAtCursorMode() { + return ( + this.user.userPreferences.get().isPasteAtCursorMode ?? + defaultUserPreferences.isPasteAtCursorMode + ) } } diff --git a/packages/tldraw/src/lib/ui/components/menu-items.tsx b/packages/tldraw/src/lib/ui/components/menu-items.tsx index c1f006976..85f237aea 100644 --- a/packages/tldraw/src/lib/ui/components/menu-items.tsx +++ b/packages/tldraw/src/lib/ui/components/menu-items.tsx @@ -630,7 +630,9 @@ export function ToggleDynamicSizeModeItem() { export function TogglePasteAtCursorItem() { const actions = useActions() const editor = useEditor() - const pasteAtCursor = useValue('paste at cursor', () => editor.user.getPasteAtCursor(), [editor]) + const pasteAtCursor = useValue('paste at cursor', () => editor.user.getIsPasteAtCursorMode(), [ + editor, + ]) return } diff --git a/packages/tldraw/src/lib/ui/context/actions.tsx b/packages/tldraw/src/lib/ui/context/actions.tsx index 5ede44aef..bbc15c475 100644 --- a/packages/tldraw/src/lib/ui/context/actions.tsx +++ b/packages/tldraw/src/lib/ui/context/actions.tsx @@ -1159,7 +1159,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) { onSelect(source) { trackEvent('toggle-paste-at-cursor', { source }) editor.user.updateUserPreferences({ - pasteAtCursor: !editor.user.getPasteAtCursor(), + isPasteAtCursorMode: !editor.user.getIsPasteAtCursorMode(), }) }, checkbox: true, diff --git a/packages/tldraw/src/lib/ui/hooks/clipboard/pasteTldrawContent.ts b/packages/tldraw/src/lib/ui/hooks/clipboard/pasteTldrawContent.ts index 2fd2e447a..68d9dae7c 100644 --- a/packages/tldraw/src/lib/ui/hooks/clipboard/pasteTldrawContent.ts +++ b/packages/tldraw/src/lib/ui/hooks/clipboard/pasteTldrawContent.ts @@ -9,12 +9,10 @@ import { Editor, TLContent, VecLike } from '@tldraw/editor' * @internal */ export function pasteTldrawContent(editor: Editor, clipboard: TLContent, point?: VecLike) { - const p = point ?? (editor.inputs.shiftKey ? editor.inputs.currentPagePoint : undefined) - const selectionBoundsBefore = editor.getSelectionPageBounds() editor.mark('paste') editor.putContentOntoCurrentPage(clipboard, { - point: p, + point: point, select: true, }) const selectedBoundsAfter = editor.getSelectionPageBounds() diff --git a/packages/tldraw/src/lib/ui/hooks/useClipboardEvents.ts b/packages/tldraw/src/lib/ui/hooks/useClipboardEvents.ts index 0285d4d1f..175180de0 100644 --- a/packages/tldraw/src/lib/ui/hooks/useClipboardEvents.ts +++ b/packages/tldraw/src/lib/ui/hooks/useClipboardEvents.ts @@ -7,6 +7,7 @@ import { TLExternalContentSource, TLGeoShape, TLTextShape, + Vec, VecLike, isNonNull, preventDefault, @@ -669,22 +670,27 @@ export function useNativeClipboardEvents() { // input instead; e.g. when pasting text into a text shape's content if (editor.getEditingShapeId() !== null || disallowClipboardEvents(editor)) return + // Where should the shapes go? + let point: Vec | undefined = undefined + let pasteAtCursor = false + + // | Shiftkey | Paste at cursor mode | Paste at point? | + // | N | N | N | + // | Y | N | Y | + // | N | Y | Y | + // | Y | Y | N | + if (editor.inputs.shiftKey) pasteAtCursor = true + if (editor.user.getIsPasteAtCursorMode()) pasteAtCursor = !pasteAtCursor + if (pasteAtCursor) point = editor.inputs.currentPagePoint + // First try to use the clipboard data on the event if (e.clipboardData && !editor.inputs.shiftKey) { - if (editor.user.getPasteAtCursor()) { - handlePasteFromEventClipboardData(editor, e.clipboardData, editor.inputs.currentPagePoint) - } else { - handlePasteFromEventClipboardData(editor, e.clipboardData) - } + handlePasteFromEventClipboardData(editor, e.clipboardData, point) } else { // Or else use the clipboard API navigator.clipboard.read().then((clipboardItems) => { if (Array.isArray(clipboardItems) && clipboardItems[0] instanceof ClipboardItem) { - if (e.clipboardData && editor.user.getPasteAtCursor()) { - handlePasteFromClipboardApi(editor, clipboardItems) - } else { - handlePasteFromClipboardApi(editor, clipboardItems, editor.inputs.currentPagePoint) - } + handlePasteFromClipboardApi(editor, clipboardItems, point) } }) }