diff --git a/apps/builder/app/builder/features/topbar/menu/menu.tsx b/apps/builder/app/builder/features/topbar/menu/menu.tsx index fc4e36df47..e7fa1756ea 100644 --- a/apps/builder/app/builder/features/topbar/menu/menu.tsx +++ b/apps/builder/app/builder/features/topbar/menu/menu.tsx @@ -140,7 +140,9 @@ export const Menu = () => { */} - emitCommand("deleteInstance")}> + emitCommand("deleteInstanceBuilder")} + > Delete diff --git a/apps/builder/app/builder/shared/commands.ts b/apps/builder/app/builder/shared/commands.ts index 6c2a0c4147..4a56d26e89 100644 --- a/apps/builder/app/builder/shared/commands.ts +++ b/apps/builder/app/builder/shared/commands.ts @@ -59,7 +59,6 @@ const makeBreakpointCommand = ( export const deleteSelectedInstance = () => { if ($isPreviewMode.get()) { - builderApi.toast.info("Deleting is not allowed in preview mode."); return; } const textEditingInstanceSelector = $textEditingInstanceSelector.get(); @@ -375,13 +374,11 @@ export const { emitCommand, subscribeCommands } = createCommandsEmitter({ }, */ - // instances - { - name: "deleteInstance", + name: "deleteInstanceBuilder", defaultHotkeys: ["backspace", "delete"], - // this disables hotkey for inputs on style panel - // but still work for input on canvas which call event.preventDefault() in keydown handler + // See "deleteInstanceCanvas" for details on why the command is separated for the canvas and builder. + disableHotkeyOutsideApp: true, disableOnInputLikeControls: true, handler: deleteSelectedInstance, }, diff --git a/apps/builder/app/canvas/shared/commands.ts b/apps/builder/app/canvas/shared/commands.ts index 840fe6ffff..214c028636 100644 --- a/apps/builder/app/canvas/shared/commands.ts +++ b/apps/builder/app/canvas/shared/commands.ts @@ -21,11 +21,21 @@ import { } from "../features/text-editor/toolbar-connector"; import { selectInstance } from "~/shared/awareness"; import { isDescendantOrSelf, type InstanceSelector } from "~/shared/tree-utils"; +import { deleteSelectedInstance } from "~/builder/shared/commands"; export const { emitCommand, subscribeCommands } = createCommandsEmitter({ source: "canvas", externalCommands: ["clickCanvas"], commands: [ + { + name: "deleteInstanceCanvas", + defaultHotkeys: ["backspace", "delete"], + disableHotkeyOutsideApp: true, + // We are not disabling "Backspace" or "Delete" on the canvas. This is the main reason we have separate functions: deleteInstanceCanvas and deleteInstanceBuilder. + disableOnInputLikeControls: false, + handler: deleteSelectedInstance, + }, + { name: "editInstanceText", hidden: true, diff --git a/apps/builder/app/shared/commands-emitter.ts b/apps/builder/app/shared/commands-emitter.ts index 7396b3f23e..991394df52 100644 --- a/apps/builder/app/shared/commands-emitter.ts +++ b/apps/builder/app/shared/commands-emitter.ts @@ -148,26 +148,22 @@ export const createCommandsEmitter = ({ ) { continue; } - const element = event.target as HTMLElement; - const isOnInputLikeControl = - ["input", "select", "textarea"].includes( - element.tagName.toLowerCase() - ) || - element.isContentEditable || - // Detect Radix select, dropdown and co. - element.getAttribute("role") === "option"; + const { disableOnInputLikeControls } = commandMeta; - // in some cases hotkey override default behavior - // on form tags and contentEditable - // though still proceed when default behavior is prevented - // this hack makes hotkeys work on canvas instances of input etc. - if ( - isOnInputLikeControl && - disableOnInputLikeControls && - event.defaultPrevented === false - ) { - continue; + if (disableOnInputLikeControls) { + const element = event.target as HTMLElement; + const isOnInputLikeControl = + ["input", "select", "textarea"].includes( + element.tagName.toLowerCase() + ) || + element.isContentEditable || + // Detect Radix select, dropdown and co. + element.getAttribute("role") === "option"; + + if (isOnInputLikeControl) { + continue; + } } emitted = true;