Increase DND performance via minimzing component updates
This commit is contained in:
parent
8ff2faaa24
commit
61940705b9
|
@ -261,8 +261,7 @@
|
|||
class="component"
|
||||
class:selected={selectedIndex === orderMap[component.component]}
|
||||
on:click={() => addComponent(component.component)}
|
||||
on:mouseover={() => (selectedIndex = null)}
|
||||
on:focus
|
||||
on:mouseenter={() => (selectedIndex = null)}
|
||||
>
|
||||
<Icon name={component.icon} />
|
||||
<Body size="XS">{component.name}</Body>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
$: source = $dndStore.source
|
||||
$: target = $dndStore.target
|
||||
$: drop = $dndStore.drop
|
||||
$: gridScreen = $isGridScreen
|
||||
|
||||
// Local flag for whether we are awaiting an async drop event
|
||||
let dropping = false
|
||||
|
@ -235,7 +236,7 @@
|
|||
|
||||
// Callback when on top of a component
|
||||
const onDragOver = (e: DragEvent) => {
|
||||
if (!source || !target || $isGridScreen) {
|
||||
if (!source || !target || gridScreen) {
|
||||
return
|
||||
}
|
||||
handleEvent(e)
|
||||
|
@ -243,7 +244,7 @@
|
|||
|
||||
// Callback when entering a potential drop target
|
||||
const onDragEnter = async (e: DragEvent) => {
|
||||
if (!source || $isGridScreen || !(e.target instanceof HTMLElement)) {
|
||||
if (!source || gridScreen || !(e.target instanceof HTMLElement)) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -278,7 +279,7 @@
|
|||
source.type,
|
||||
drop.parent,
|
||||
drop.index,
|
||||
$dndStore.source?.props
|
||||
$dndStore.meta?.props
|
||||
)
|
||||
dropping = false
|
||||
stopDragging()
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
<!--<script>-->
|
||||
<!-- import { onMount, tick } from "svelte"-->
|
||||
<!-- import { Utils } from "@budibase/frontend-core"-->
|
||||
<!-- import { componentStore, dndNewComponentType, isGridScreen } from "@/stores"-->
|
||||
<!-- import { DNDPlaceholderID } from "@/constants"-->
|
||||
<!-- import IndicatorSet from "@/components/preview/IndicatorSet.svelte"-->
|
||||
|
||||
<!-- let left, top, height, width-->
|
||||
<!-- let observing = false-->
|
||||
<!-- let hasGridStyles = false-->
|
||||
|
||||
<!-- // On grid screens, we need to wait for grid styles to be properly set on-->
|
||||
<!-- // the hidden placeholder component before rendering this overlay-->
|
||||
<!-- $: waitingForGrid = $isGridScreen && !hasGridStyles-->
|
||||
<!-- $: instance = componentStore.actions.getComponentInstance(DNDPlaceholderID)-->
|
||||
<!-- $: state = $instance?.state-->
|
||||
<!-- $: styles = $state?.styles?.normal || {}-->
|
||||
<!-- $: {-->
|
||||
<!-- if ($isGridScreen && !hasGridStyles) {-->
|
||||
<!-- checkGridStyles(styles)-->
|
||||
<!-- }-->
|
||||
<!-- }-->
|
||||
|
||||
<!-- // We pull the component name from the definition-->
|
||||
<!-- $: definition =-->
|
||||
<!-- componentStore.actions.getComponentDefinition($dndNewComponentType)-->
|
||||
|
||||
<!-- // Wait for grid styles to be set, then tick and await a position update-->
|
||||
<!-- // before finally signalling we're allowed to render-->
|
||||
<!-- const checkGridStyles = async styles => {-->
|
||||
<!-- const hasStyles = Object.keys(styles).some(key => key.startsWith("--grid"))-->
|
||||
<!-- if (hasStyles) {-->
|
||||
<!-- await tick()-->
|
||||
<!-- updatePosition()-->
|
||||
<!-- hasGridStyles = true-->
|
||||
<!-- }-->
|
||||
<!-- }-->
|
||||
|
||||
<!-- // Observe style changes in the placeholder DOM node and use this to trigger-->
|
||||
<!-- // a redraw of our overlay-->
|
||||
<!-- const observer = new MutationObserver(mutations => {-->
|
||||
<!-- if (mutations.some(mutation => mutation.attributeName === "style")) {-->
|
||||
<!-- debouncedUpdate()-->
|
||||
<!-- }-->
|
||||
<!-- })-->
|
||||
|
||||
<!-- const updatePosition = () => {-->
|
||||
<!-- const wrapperNode = document.getElementsByClassName(DNDPlaceholderID)[0]-->
|
||||
<!-- let domNode = wrapperNode-->
|
||||
<!-- const insideGrid = wrapperNode?.dataset.insideGrid === "true"-->
|
||||
<!-- if (!insideGrid) {-->
|
||||
<!-- domNode = document.getElementsByClassName(`${DNDPlaceholderID}-dom`)[0]-->
|
||||
<!-- }-->
|
||||
<!-- if (!domNode) {-->
|
||||
<!-- height = 0-->
|
||||
<!-- width = 0-->
|
||||
<!-- } else {-->
|
||||
<!-- const bounds = domNode.getBoundingClientRect()-->
|
||||
<!-- left = bounds.left-->
|
||||
<!-- top = bounds.top-->
|
||||
<!-- height = bounds.height-->
|
||||
<!-- width = bounds.width-->
|
||||
<!-- }-->
|
||||
|
||||
<!-- // Initialise observer if not already done-->
|
||||
<!-- if (!observing && wrapperNode) {-->
|
||||
<!-- observing = true-->
|
||||
<!-- observer.observe(wrapperNode, { attributes: true })-->
|
||||
<!-- }-->
|
||||
<!-- }-->
|
||||
<!-- const debouncedUpdate = Utils.domDebounce(updatePosition)-->
|
||||
|
||||
<!-- onMount(() => {-->
|
||||
<!-- const interval = setInterval(debouncedUpdate, 100)-->
|
||||
<!-- return () => {-->
|
||||
<!-- observer.disconnect()-->
|
||||
<!-- clearInterval(interval)-->
|
||||
<!-- }-->
|
||||
<!-- })-->
|
||||
<!--</script>-->
|
||||
|
||||
<!--<!–{#if left != null && top != null && width && height && !waitingForGrid}–>-->
|
||||
<!--<!– <div–>-->
|
||||
<!--<!– class="overlay"–>-->
|
||||
<!--<!– class:animate={!$isGridScreen}–>-->
|
||||
<!--<!– style="left:{left}px; top:{top}px; width:{width}px; height:{height}px;"–>-->
|
||||
<!--<!– >–>-->
|
||||
<!--<!– {definition?.name || ""}–>-->
|
||||
<!--<!– </div>–>-->
|
||||
<!--<!– <IndicatorSet componentId={DNDPlaceholderID} color="red" />–>-->
|
||||
|
||||
<!--<!–{/if}–>-->
|
||||
<!--<style>-->
|
||||
<!-- .overlay {-->
|
||||
<!-- position: fixed;-->
|
||||
<!-- z-index: 800;-->
|
||||
<!-- background: hsl(160, 64%, 90%);-->
|
||||
<!-- border-radius: 4px;-->
|
||||
<!-- border: 2px solid var(--spectrum-global-color-static-green-500);-->
|
||||
<!-- display: grid;-->
|
||||
<!-- place-items: center;-->
|
||||
<!-- color: hsl(160, 64%, 40%);-->
|
||||
<!-- font-size: 14px;-->
|
||||
<!-- }-->
|
||||
<!-- .overlay.animate {-->
|
||||
<!-- transition: all 130ms ease-out;-->
|
||||
<!-- }-->
|
||||
<!--</style>-->
|
|
@ -1,12 +1,18 @@
|
|||
<script lang="ts">
|
||||
import { isGridScreen, dndParent, dndSource, dndIsDragging } from "@/stores"
|
||||
import {
|
||||
isGridScreen,
|
||||
dndParent,
|
||||
dndSource,
|
||||
dndIsDragging,
|
||||
dndStore,
|
||||
} from "@/stores"
|
||||
import { DNDPlaceholderID } from "@/constants"
|
||||
import IndicatorSet from "./IndicatorSet.svelte"
|
||||
|
||||
// On grid screens, don't draw the indicator until we've dragged over the
|
||||
// screen. When this happens, the dndSource props will be set as we will have
|
||||
// attached grid metadata styles.
|
||||
$: waitingForGrid = $isGridScreen && !$dndSource?.props
|
||||
$: waitingForGrid = $isGridScreen && !$dndStore.meta?.props
|
||||
</script>
|
||||
|
||||
{#if $dndIsDragging}
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
// real component to render in the new position before updating the DND
|
||||
// store, preventing the green DND overlay from being out of position
|
||||
if ($dndSource?.isNew && styles) {
|
||||
dndStore.actions.updateSourceProps({
|
||||
dndStore.actions.updateNewComponentProps({
|
||||
_styles: {
|
||||
normal: styles,
|
||||
},
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
const observeMutations = (node: Node) => {
|
||||
mutationObserver.observe(node, {
|
||||
attributes: true,
|
||||
attributeFilter: ["style"],
|
||||
})
|
||||
observingMutations = true
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ interface DNDSource {
|
|||
icon?: string
|
||||
type: string
|
||||
isNew: boolean
|
||||
props?: Record<string, any>
|
||||
}
|
||||
|
||||
interface DNDTarget {
|
||||
|
@ -32,10 +31,15 @@ interface DNDDrop {
|
|||
index: number
|
||||
}
|
||||
|
||||
interface DNDMeta {
|
||||
props?: Record<string, any>
|
||||
}
|
||||
|
||||
interface DNDState {
|
||||
source?: DNDSource
|
||||
target?: DNDTarget
|
||||
drop?: DNDDrop
|
||||
meta?: DNDMeta
|
||||
}
|
||||
|
||||
const createDndStore = () => {
|
||||
|
@ -106,15 +110,12 @@ const createDndStore = () => {
|
|||
store.set({})
|
||||
}
|
||||
|
||||
const updateSourceProps = (props: Record<string, any>) => {
|
||||
const updateNewComponentProps = (props: Record<string, any>) => {
|
||||
store.update(state => {
|
||||
if (!state.source) {
|
||||
return state
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
source: {
|
||||
...state.source,
|
||||
meta: {
|
||||
...state.meta,
|
||||
props,
|
||||
},
|
||||
}
|
||||
|
@ -129,7 +130,7 @@ const createDndStore = () => {
|
|||
updateTarget,
|
||||
updateDrop,
|
||||
reset,
|
||||
updateSourceProps,
|
||||
updateNewComponentProps,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue