diff --git a/packages/builder/src/components/common/NavItem.svelte b/packages/builder/src/components/common/NavItem.svelte
index b319560ddd..1fd43e2c70 100644
--- a/packages/builder/src/components/common/NavItem.svelte
+++ b/packages/builder/src/components/common/NavItem.svelte
@@ -16,6 +16,7 @@
export let scrollable = false
export let highlighted = false
export let rightAlignIcon = false
+ export let id
const scrollApi = getContext("scroll")
const dispatch = createEventDispatcher()
@@ -58,6 +59,7 @@
on:click={onClick}
ondragover="return false"
ondragenter="return false"
+ {id}
>
{#if withArrow}
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte
index 5add1fedac..c19cba1aac 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte
@@ -7,14 +7,15 @@
$: noPaste = !$store.componentToPaste
const keyboardEvent = (key, ctrlKey = false) => {
- // Ensure this component is selected first
- if (component._id !== $store.selectedComponentId) {
- store.update(state => {
- state.selectedComponentId = component._id
- return state
+ document.dispatchEvent(
+ new CustomEvent("component-menu", {
+ detail: {
+ key,
+ ctrlKey,
+ id: component?._id,
+ },
})
- }
- document.dispatchEvent(new KeyboardEvent("keydown", { key, ctrlKey }))
+ )
}
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentKeyHandler.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentKeyHandler.svelte
new file mode 100644
index 0000000000..467d9a5a2f
--- /dev/null
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentKeyHandler.svelte
@@ -0,0 +1,118 @@
+
+
+
store.actions.components.delete(componentToDelete)}
+/>
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte
index 0c292d1db4..71d0b9ae52 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte
@@ -2,62 +2,15 @@
import Panel from "components/design/Panel.svelte"
import ComponentTree from "./ComponentTree.svelte"
import { dndStore } from "./dndStore.js"
- import { goto, isActive } from "@roxi/routify"
- import { store, selectedScreen, selectedComponent } from "builderStore"
+ import { goto } from "@roxi/routify"
+ import { store, selectedScreen } from "builderStore"
import NavItem from "components/common/NavItem.svelte"
import ScreenslotDropdownMenu from "./ScreenslotDropdownMenu.svelte"
- import { setContext, onMount } from "svelte"
- import { get } from "svelte/store"
import DNDPositionIndicator from "./DNDPositionIndicator.svelte"
import { DropPosition } from "./dndStore"
- import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { notifications, Button } from "@budibase/bbui"
-
- let scrollRef
- let confirmDeleteDialog
-
- const scrollTo = bounds => {
- if (!bounds) {
- return
- }
- const sidebarWidth = 259
- const navItemHeight = 32
- const { scrollLeft, scrollTop, offsetHeight } = scrollRef
- let scrollBounds = scrollRef.getBoundingClientRect()
- let newOffsets = {}
-
- // Calculate left offset
- const offsetX = bounds.left + bounds.width + scrollLeft - 36
- if (offsetX > sidebarWidth) {
- newOffsets.left = offsetX - sidebarWidth
- } else {
- newOffsets.left = 0
- }
- if (newOffsets.left === scrollLeft) {
- delete newOffsets.left
- }
-
- // Calculate top offset
- const offsetY = bounds.top - scrollBounds?.top + scrollTop
- if (offsetY > scrollTop + offsetHeight - 2 * navItemHeight) {
- newOffsets.top = offsetY - offsetHeight + 2 * navItemHeight
- } else if (offsetY < scrollTop + navItemHeight) {
- newOffsets.top = offsetY - navItemHeight
- } else {
- delete newOffsets.top
- }
-
- // Skip if offset is unchanged
- if (newOffsets.left == null && newOffsets.top == null) {
- return
- }
-
- // Smoothly scroll to the offset
- scrollRef.scroll({
- ...newOffsets,
- behavior: "smooth",
- })
- }
+ import ComponentKeyHandler from "./ComponentKeyHandler.svelte"
+ import ComponentScrollWrapper from "./ComponentScrollWrapper.svelte"
const onDrop = async () => {
try {
@@ -67,95 +20,15 @@
notifications.error("Error saving component")
}
}
-
- // Set scroll context so components can invoke scrolling when selected
- setContext("scroll", {
- scrollTo,
- })
-
- const deleteComponent = async () => {
- await store.actions.components.delete(get(selectedComponent))
- }
-
- const handleKeyPress = async e => {
- // Ignore repeating events
- if (e.repeat) {
- return
- }
- // Ignore events when typing
- const activeTag = document.activeElement?.tagName.toLowerCase()
- if (["input", "textarea"].indexOf(activeTag) !== -1 && e.key !== "Escape") {
- return
- }
- const component = get(selectedComponent)
- try {
- if (e.ctrlKey || e.metaKey) {
- if (e.key === "ArrowUp") {
- e.preventDefault()
- await store.actions.components.moveUp(component)
- } else if (e.key === "ArrowDown") {
- e.preventDefault()
- await store.actions.components.moveDown(component)
- } else if (e.key === "c") {
- e.preventDefault()
- await store.actions.components.copy(component, false)
- } else if (e.key === "x") {
- e.preventDefault()
- store.actions.components.copy(component, true)
- } else if (e.key === "v") {
- e.preventDefault()
- await store.actions.components.paste(component, "inside")
- } else if (e.key === "d") {
- e.preventDefault()
- await store.actions.components.copy(component)
- await store.actions.components.paste(component, "below")
- } else if (e.key === "Enter") {
- e.preventDefault()
- $goto("./new")
- }
- } else if (e.key === "Backspace" || e.key === "Delete") {
- // Don't show confirmation for the screen itself
- if (component._id === get(selectedScreen).props._id) {
- return
- }
- e.preventDefault()
- confirmDeleteDialog.show()
- } else if (e.key === "ArrowUp") {
- e.preventDefault()
- await store.actions.components.selectPrevious()
- } else if (e.key === "ArrowDown") {
- e.preventDefault()
- await store.actions.components.selectNext()
- } else if (e.key === "Escape" && $isActive("./new")) {
- e.preventDefault()
- $goto("./")
- }
- } catch (error) {
- console.log(error)
- notifications.error("Error handling key press")
- }
- }
-
- onMount(() => {
- document.addEventListener("keydown", handleKeyPress)
- return () => {
- document.removeEventListener("keydown", handleKeyPress)
- }
- })
-
+
- - {
- $store.selectedComponentId = $selectedScreen?.props._id
- }}
- id={`component-${$selectedScreen?.props._id}`}
- >
+
-
{
+ $store.selectedComponentId = $selectedScreen?.props._id
+ }}
+ id={`component-${$selectedScreen?.props._id}`}
>
@@ -187,15 +64,9 @@
{/if}
-
+
-
+
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte
index 6704027f35..31d6eb132b 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte
@@ -68,7 +68,8 @@
closedNodes = closedNodes
}
- const onDrop = async () => {
+ const onDrop = async e => {
+ e.stopPropagation()
try {
await dndStore.actions.drop()
} catch (error) {