fix(app): fix ctrl drag for insertion into subgrids

This commit is contained in:
Ruben Fiszel
2025-08-21 17:32:47 +00:00
parent 165adc0011
commit 752a1c958d
4 changed files with 74 additions and 53 deletions
@@ -200,14 +200,12 @@
allIdsInPath={$allIdsInPath}
selectedIds={$selectedComponent}
items={$app.grid}
on:redraw={(e) => {
onRedraw={(grid) => {
push(history, $app)
$app.grid = e.detail
$app.grid = grid
}}
root
on:dropped={(e) => {
const { id, overlapped, x, y } = e.detail
onDropped={({ id, overlapped, x, y }) => {
const overlappedComponent = findGridItem($app, overlapped)
if (overlappedComponent && !isContainer(overlappedComponent.data.type)) {
@@ -218,7 +218,7 @@
{#if $mode !== 'preview'}
<div
class={highlight
? `outline !outline-dashed outline-2 min-h-full ${
? `!outline-dashed outline-2 min-h-full ${
isActive && !$selectedComponent?.includes(id)
? 'outline-orange-600'
: 'outline-gray-400 dark:outline-gray-600'
@@ -229,19 +229,17 @@
<Grid
allIdsInPath={$allIdsInPath}
items={$app.subgrids?.[subGridId] ?? []}
on:redraw={(e) => {
onRedraw={(grid) => {
push(editorContext?.history, $app)
if ($app.subgrids) {
$app.subgrids[subGridId] = e.detail
$app.subgrids[subGridId] = grid
}
}}
selectedIds={$selectedComponent}
scroller={container}
parentWidth={$parentWidth - 17}
{containerWidth}
on:dropped={(e) => {
const { id, overlapped, x, y } = e.detail
onDropped={({ id, overlapped, x, y }) => {
if (!overlapped) {
moveToRoot(id, { x, y })
} else {
@@ -257,7 +255,6 @@
if (id === overlapped) {
return
}
moveComponentBetweenSubgrids(
id,
overlapped,
@@ -16,7 +16,7 @@
import { getContainerHeight } from './utils/container'
import { moveItem, getItemById, specifyUndefinedColumns } from './utils/item'
import { onMount, createEventDispatcher, getContext } from 'svelte'
import { onMount, getContext } from 'svelte'
import { getColumn, throttle } from './utils/other'
import MoveResize from './MoveResize.svelte'
import type { FilledItem } from './types'
@@ -34,8 +34,6 @@
type GridShadow
} from '../editor/appUtils'
const dispatch = createEventDispatcher()
type T = $$Generic
const { app, worldStore } = getContext<AppViewerContext>('AppViewerContext')
@@ -55,6 +53,20 @@
parentWidth?: number | undefined
disableMove?: boolean
children?: import('svelte').Snippet<[any]>
onDropped?: (e: { id: string; overlapped: string; x: number; y: number }) => void
onRedraw?: (grid: FilledItem<T>[]) => void
onResize?: (e: {
cols: number
xPerPx: number
yPerPx: number
width: number | undefined
}) => void
onMounted?: (e: {
cols: number
xPerPx: number
yPerPx: number
width: number | undefined
}) => void
}
let {
@@ -71,7 +83,11 @@
root = false,
parentWidth = undefined,
disableMove = false,
children
children,
onDropped,
onRedraw,
onResize,
onMounted
}: Props = $props()
const cols = columnConfiguration
@@ -83,10 +99,10 @@
let xPerPx = $state(0)
let yPerPx = rowHeight
const onResize = throttle(() => {
const onResizeThrottled = throttle(() => {
if (!getComputedCols) return
sortedItems = specifyUndefinedColumns(sortedItems, getComputedCols, cols)
dispatch('resize', {
onResize?.({
cols: getComputedCols,
xPerPx,
yPerPx,
@@ -116,13 +132,14 @@
if (!containerWidth && getComputedCols) {
sortedItems = specifyUndefinedColumns(sortedItems, getComputedCols, cols)
dispatch('mount', {
onMounted?.({
cols: getComputedCols,
xPerPx,
yPerPx // same as rowHeight
yPerPx,
width
})
} else {
onResize()
onResizeThrottled()
}
containerWidth = width
@@ -162,8 +179,7 @@
})
: []
}
const updateMatrix = ({ detail }) => {
let isPointerUp = detail.isPointerUp
const updateMatrix = ({ isPointerUp, id, activate }) => {
let citems: FilledItem<T>[]
if (isPointerUp) {
if (initItems == undefined) {
@@ -179,8 +195,8 @@
citems = smartCopy(initItems)
}
let nselectedIds = selectedIds ?? []
if (detail.id && !selectedIds?.includes(detail.id)) {
nselectedIds = [detail.id, ...(selectedIds ?? [])]
if (id && !selectedIds?.includes(id)) {
nselectedIds = [id, ...(selectedIds ?? [])]
}
for (let id of nselectedIds) {
let activeItem = getItemById(id, citems)
@@ -235,13 +251,13 @@
}
for (let id of nselectedIds ?? []) {
if (detail.activate) {
if (activate) {
moveResizes?.[id]?.inActivate()
}
}
if (isPointerUp && getComputedCols) {
dispatch('redraw', sortGridItemsPosition(smartCopy(sortedItems), getComputedCols))
onRedraw?.(sortGridItemsPosition(smartCopy(sortedItems), getComputedCols))
}
}
@@ -259,11 +275,11 @@
}
| undefined = $state(undefined)
const handleRepaint = ({ detail }) => {
if (!detail.isPointerUp) {
throttleMatrix({ detail })
const handleRepaint = ({ isPointerUp, id, activate }) => {
if (!isPointerUp) {
throttleMatrix({ isPointerUp, id, activate })
} else {
updateMatrix({ detail })
updateMatrix({ isPointerUp, id, activate })
}
/**
@@ -488,19 +504,19 @@
{/if}
<MoveResize
{mounted}
on:initmove={() => handleInitMove(item.id)}
onInitMove={() => handleInitMove(item.id)}
onMove={handleMove}
bind:shadow={shadows[item.id]}
bind:this={moveResizes[item.id]}
on:repaint={handleRepaint}
on:resizeStart={() => (resizing = true)}
on:resizeEnd={() => (resizing = false)}
onRepaint={handleRepaint}
onResizeStart={() => (resizing = true)}
onResizeEnd={() => (resizing = false)}
onTop={Boolean(allIdsInPath?.includes(item.id))}
id={item.id}
{xPerPx}
{yPerPx}
fakeShadow={$fakeShadowStore}
on:dropped={(e) => {
onDropped={({ id, overlapped, x, y }) => {
$componentDraggedIdStore = undefined
$componentDraggedParentIdStore = undefined
$overlappedStore = undefined
@@ -510,8 +526,7 @@
if ($moveMode === 'move') {
return
}
dispatch('dropped', e.detail)
onDropped?.({ id, overlapped, x, y })
}}
width={xPerPx == 0
? 0
@@ -1,5 +1,5 @@
<script lang="ts">
import { createEventDispatcher, getContext, onMount } from 'svelte'
import { getContext, onMount } from 'svelte'
import type { AppEditorContext, AppViewerContext } from '../types'
import { writable } from 'svelte/store'
import { twMerge } from 'tailwind-merge'
@@ -12,8 +12,6 @@
import { throttle } from './utils/other'
import { moveMode } from '../gridUtils'
const dispatch = createEventDispatcher()
interface Props {
sensor: any
width: any
@@ -43,6 +41,11 @@
shadow?: GridShadow | undefined
overlapped?: string | undefined
}) => void
onDropped?: (e: { id: string; overlapped: string; x: number; y: number }) => void
onInitMove?: () => void
onResizeStart?: () => void
onResizeEnd?: () => void
onRepaint?: (e: { id: string; isPointerUp: boolean; activate: boolean }) => void
children?: import('svelte').Snippet
}
@@ -69,6 +72,11 @@
disableMove = true,
mounted = false,
onMove,
onDropped,
onInitMove,
onResizeStart,
onResizeEnd,
onRepaint,
children
}: Props = $props()
@@ -112,7 +120,7 @@
window.addEventListener('pointermove', pointermove)
window.addEventListener('pointerup', pointerup)
dispatch('initmove')
onInitMove?.()
const cordDiff = {
x: (moveX / $scale) * 100 - initX,
@@ -165,11 +173,7 @@
}
let repaint = (activate: boolean, isPointerUp: boolean) => {
dispatch('repaint', {
id,
isPointerUp,
activate
})
onRepaint?.({ id, isPointerUp, activate })
}
// Autoscroll
@@ -221,7 +225,7 @@
initX = (clientX / $scale) * 100
initY = (clientY / $scale) * 100
dispatch('initmove')
onInitMove?.()
}
window.addEventListener('pointermove', pointermove)
window.addEventListener('pointerup', pointerup)
@@ -299,7 +303,6 @@
}
throttledComputeShadow(clientX, clientY)
onMove({
cordDiff,
clientY,
@@ -359,7 +362,7 @@
el.getAttribute('data-iscontainer') === 'true'
)
const newOverlapped = intersectingElement ? intersectingElement?.id.split('-')[1] : undefined
const newOverlapped = intersectingElement ? intersectingElement?.id.split('-')[2] : undefined
const container = newOverlapped
? intersectingElement?.querySelector('.svlt-grid-container')
@@ -411,6 +414,14 @@
dragClosure = undefined
}
if (!fakeShadow) {
return
}
if (!overlapped) {
return
}
if (!moving) {
return
}
@@ -421,7 +432,7 @@
return
}
dispatch('dropped', {
onDropped?.({
id,
overlapped,
x: fakeShadow?.x,
@@ -456,7 +467,7 @@
window.addEventListener('pointermove', resizePointerMove)
window.addEventListener('pointerup', resizePointerUp)
dispatch('resizeStart')
onResizeStart?.()
}
const resizePointerMove = ({ pageX, pageY }) => {
@@ -492,7 +503,7 @@
window.removeEventListener('pointermove', resizePointerMove)
window.removeEventListener('pointerup', resizePointerUp)
dispatch('resizeEnd')
onResizeEnd?.()
}
function shouldDisplayShadow(moveMode: 'insert' | 'move', overlapped: string | undefined) {