Added infinite dragging and some css updates to make the canvas drag UX more consistent
This commit is contained in:
parent
1505476fe1
commit
293abc80e1
|
@ -11,6 +11,9 @@
|
||||||
import { Utils, memo } from "@budibase/frontend-core"
|
import { Utils, memo } from "@budibase/frontend-core"
|
||||||
import { selectedAutomation, automationStore } from "stores/builder"
|
import { selectedAutomation, automationStore } from "stores/builder"
|
||||||
|
|
||||||
|
// CSS classes that, on mouse down, will trigger the view drag behaviour
|
||||||
|
export let draggableClasses = []
|
||||||
|
|
||||||
export function toFocus() {
|
export function toFocus() {
|
||||||
viewToFocusEle()
|
viewToFocusEle()
|
||||||
}
|
}
|
||||||
|
@ -161,6 +164,10 @@
|
||||||
// Scale prop for the icon
|
// Scale prop for the icon
|
||||||
let dotDefault = 0.006
|
let dotDefault = 0.006
|
||||||
|
|
||||||
|
let viewDragStart = { x: 0, y: 0 }
|
||||||
|
let viewDragOffset = [0, 0]
|
||||||
|
let startPos = [0, 0]
|
||||||
|
|
||||||
$: bgSize = Math.max(bgDim * $view.scale, 10)
|
$: bgSize = Math.max(bgDim * $view.scale, 10)
|
||||||
$: bgWidth = bgSize
|
$: bgWidth = bgSize
|
||||||
$: bgHeight = bgSize
|
$: bgHeight = bgSize
|
||||||
|
@ -275,14 +282,17 @@
|
||||||
y,
|
y,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if (down && !$view.dragging && dragOffset) {
|
if (down && !$view.dragging) {
|
||||||
|
// Determine how much the view has moved since
|
||||||
|
viewDragOffset = [x - viewDragStart.x, y - viewDragStart.y]
|
||||||
|
|
||||||
contentPos.update(state => ({
|
contentPos.update(state => ({
|
||||||
...state,
|
...state,
|
||||||
x: x - dragOffset[0],
|
x: startPos[0] + viewDragOffset[0],
|
||||||
y: y - dragOffset[1],
|
y: startPos[1] + viewDragOffset[1],
|
||||||
}))
|
}))
|
||||||
offsetX = x - dragOffset[0]
|
offsetX = startPos[0] + viewDragOffset[0]
|
||||||
offsetY = y - dragOffset[1]
|
offsetY = startPos[1] + viewDragOffset[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearScrollInterval = () => {
|
const clearScrollInterval = () => {
|
||||||
|
@ -367,6 +377,9 @@
|
||||||
const globalMouseUp = () => {
|
const globalMouseUp = () => {
|
||||||
down = false
|
down = false
|
||||||
|
|
||||||
|
viewDragStart = { x: 0, y: 0 }
|
||||||
|
viewDragOffset = [0, 0]
|
||||||
|
|
||||||
if ($view.dragging) {
|
if ($view.dragging) {
|
||||||
dragOffset = [0, 0]
|
dragOffset = [0, 0]
|
||||||
view.update(state => ({
|
view.update(state => ({
|
||||||
|
@ -482,6 +495,11 @@
|
||||||
dragOffset = [Math.abs(x - $contentPos.x), Math.abs(y - $contentPos.y)]
|
dragOffset = [Math.abs(x - $contentPos.x), Math.abs(y - $contentPos.y)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isDraggable = e => {
|
||||||
|
const draggable = ["draggable-view", ...draggableClasses]
|
||||||
|
return draggable.some(cls => e.target.classList.contains(cls))
|
||||||
|
}
|
||||||
|
|
||||||
const viewToFocusEle = () => {
|
const viewToFocusEle = () => {
|
||||||
if ($focusElement) {
|
if ($focusElement) {
|
||||||
const viewWidth = viewDims.width
|
const viewWidth = viewDims.width
|
||||||
|
@ -566,31 +584,31 @@
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="draggable-view"
|
class="draggable-view"
|
||||||
|
class:dragging={down}
|
||||||
bind:this={viewPort}
|
bind:this={viewPort}
|
||||||
on:wheel={Utils.domDebounce(onViewScroll)}
|
on:wheel={Utils.domDebounce(onViewScroll)}
|
||||||
on:mousemove={Utils.domDebounce(onViewMouseMove)}
|
on:mousemove={Utils.domDebounce(onViewMouseMove)}
|
||||||
on:mouseup={onViewDragEnd}
|
on:mousedown={e => {
|
||||||
|
if ((e.which === 1 || e.button === 0) && isDraggable(e)) {
|
||||||
|
const { x, y } = eleXY(e, viewPort)
|
||||||
|
viewDragStart = { x, y }
|
||||||
|
startPos = [$contentPos.x, $contentPos.y]
|
||||||
|
down = true
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
on:mouseup={e => {
|
||||||
|
viewDragOffset = [0, 0]
|
||||||
|
if ((e.which === 1 || e.button === 0) && isDraggable(e)) {
|
||||||
|
down = false
|
||||||
|
}
|
||||||
|
onViewDragEnd()
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div class="content-wrap" style={wrapStyles} bind:this={contentWrap}>
|
||||||
class="content-wrap"
|
|
||||||
style={wrapStyles}
|
|
||||||
bind:this={contentWrap}
|
|
||||||
class:dragging={down}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="content"
|
class="content"
|
||||||
bind:this={mainContent}
|
bind:this={mainContent}
|
||||||
on:mousemove={Utils.domDebounce(onMoveContent)}
|
on:mousemove={Utils.domDebounce(onMoveContent)}
|
||||||
on:mousedown={e => {
|
|
||||||
if (e.which === 1 || e.button === 0) {
|
|
||||||
down = true
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
on:mouseup={e => {
|
|
||||||
if (e.which === 1 || e.button === 0) {
|
|
||||||
down = false
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<slot name="content" />
|
<slot name="content" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -608,7 +626,12 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
cursor: grab;
|
||||||
}
|
}
|
||||||
|
.draggable-view.dragging {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
transform-origin: 50% 50%;
|
transform-origin: 50% 50%;
|
||||||
transform: scale(var(--scale));
|
transform: scale(var(--scale));
|
||||||
|
@ -623,14 +646,9 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
width: var(--wrapW);
|
width: var(--wrapW);
|
||||||
height: var(--wrapH);
|
height: var(--wrapH);
|
||||||
cursor: grab;
|
|
||||||
transform: translate(var(--posX), var(--posY));
|
transform: translate(var(--posX), var(--posY));
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-wrap.dragging {
|
|
||||||
cursor: grabbing;
|
|
||||||
}
|
|
||||||
|
|
||||||
.draggable-background {
|
.draggable-background {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -223,6 +223,7 @@
|
||||||
.branch-actions {
|
.branch-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--spacing-l);
|
gap: var(--spacing-l);
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
.footer {
|
.footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -261,6 +262,7 @@
|
||||||
background-color: var(--background);
|
background-color: var(--background);
|
||||||
border: 1px solid var(--spectrum-global-color-gray-300);
|
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||||
border-radius: 4px 4px 4px 4px;
|
border-radius: 4px 4px 4px 4px;
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.blockSection {
|
.blockSection {
|
||||||
|
|
|
@ -127,7 +127,18 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="root" bind:this={treeEle}>
|
<div class="root" bind:this={treeEle}>
|
||||||
<DraggableCanvas bind:this={draggable}>
|
<DraggableCanvas
|
||||||
|
bind:this={draggable}
|
||||||
|
draggableClasses={[
|
||||||
|
"main-content",
|
||||||
|
"content",
|
||||||
|
"block",
|
||||||
|
"branched",
|
||||||
|
"branch",
|
||||||
|
"flow-item",
|
||||||
|
"branch-wrap",
|
||||||
|
]}
|
||||||
|
>
|
||||||
<span class="main-content" slot="content">
|
<span class="main-content" slot="content">
|
||||||
{#if Object.keys(blockRefs).length}
|
{#if Object.keys(blockRefs).length}
|
||||||
{#each blocks as block, idx (block.id)}
|
{#each blocks as block, idx (block.id)}
|
||||||
|
|
|
@ -400,6 +400,7 @@
|
||||||
width: 480px;
|
width: 480px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
.block .wrap {
|
.block .wrap {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -47,5 +47,6 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--spacing-m);
|
gap: var(--spacing-m);
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue