Increase DND performance via minimzing component updates
This commit is contained in:
parent
8ff2faaa24
commit
61940705b9
|
@ -261,8 +261,7 @@
|
||||||
class="component"
|
class="component"
|
||||||
class:selected={selectedIndex === orderMap[component.component]}
|
class:selected={selectedIndex === orderMap[component.component]}
|
||||||
on:click={() => addComponent(component.component)}
|
on:click={() => addComponent(component.component)}
|
||||||
on:mouseover={() => (selectedIndex = null)}
|
on:mouseenter={() => (selectedIndex = null)}
|
||||||
on:focus
|
|
||||||
>
|
>
|
||||||
<Icon name={component.icon} />
|
<Icon name={component.icon} />
|
||||||
<Body size="XS">{component.name}</Body>
|
<Body size="XS">{component.name}</Body>
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
$: source = $dndStore.source
|
$: source = $dndStore.source
|
||||||
$: target = $dndStore.target
|
$: target = $dndStore.target
|
||||||
$: drop = $dndStore.drop
|
$: drop = $dndStore.drop
|
||||||
|
$: gridScreen = $isGridScreen
|
||||||
|
|
||||||
// Local flag for whether we are awaiting an async drop event
|
// Local flag for whether we are awaiting an async drop event
|
||||||
let dropping = false
|
let dropping = false
|
||||||
|
@ -235,7 +236,7 @@
|
||||||
|
|
||||||
// Callback when on top of a component
|
// Callback when on top of a component
|
||||||
const onDragOver = (e: DragEvent) => {
|
const onDragOver = (e: DragEvent) => {
|
||||||
if (!source || !target || $isGridScreen) {
|
if (!source || !target || gridScreen) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleEvent(e)
|
handleEvent(e)
|
||||||
|
@ -243,7 +244,7 @@
|
||||||
|
|
||||||
// Callback when entering a potential drop target
|
// Callback when entering a potential drop target
|
||||||
const onDragEnter = async (e: DragEvent) => {
|
const onDragEnter = async (e: DragEvent) => {
|
||||||
if (!source || $isGridScreen || !(e.target instanceof HTMLElement)) {
|
if (!source || gridScreen || !(e.target instanceof HTMLElement)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +279,7 @@
|
||||||
source.type,
|
source.type,
|
||||||
drop.parent,
|
drop.parent,
|
||||||
drop.index,
|
drop.index,
|
||||||
$dndStore.source?.props
|
$dndStore.meta?.props
|
||||||
)
|
)
|
||||||
dropping = false
|
dropping = false
|
||||||
stopDragging()
|
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">
|
<script lang="ts">
|
||||||
import { isGridScreen, dndParent, dndSource, dndIsDragging } from "@/stores"
|
import {
|
||||||
|
isGridScreen,
|
||||||
|
dndParent,
|
||||||
|
dndSource,
|
||||||
|
dndIsDragging,
|
||||||
|
dndStore,
|
||||||
|
} from "@/stores"
|
||||||
import { DNDPlaceholderID } from "@/constants"
|
import { DNDPlaceholderID } from "@/constants"
|
||||||
import IndicatorSet from "./IndicatorSet.svelte"
|
import IndicatorSet from "./IndicatorSet.svelte"
|
||||||
|
|
||||||
// On grid screens, don't draw the indicator until we've dragged over the
|
// 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
|
// screen. When this happens, the dndSource props will be set as we will have
|
||||||
// attached grid metadata styles.
|
// attached grid metadata styles.
|
||||||
$: waitingForGrid = $isGridScreen && !$dndSource?.props
|
$: waitingForGrid = $isGridScreen && !$dndStore.meta?.props
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $dndIsDragging}
|
{#if $dndIsDragging}
|
||||||
|
|
|
@ -85,7 +85,7 @@
|
||||||
// real component to render in the new position before updating the DND
|
// real component to render in the new position before updating the DND
|
||||||
// store, preventing the green DND overlay from being out of position
|
// store, preventing the green DND overlay from being out of position
|
||||||
if ($dndSource?.isNew && styles) {
|
if ($dndSource?.isNew && styles) {
|
||||||
dndStore.actions.updateSourceProps({
|
dndStore.actions.updateNewComponentProps({
|
||||||
_styles: {
|
_styles: {
|
||||||
normal: styles,
|
normal: styles,
|
||||||
},
|
},
|
||||||
|
|
|
@ -93,6 +93,7 @@
|
||||||
const observeMutations = (node: Node) => {
|
const observeMutations = (node: Node) => {
|
||||||
mutationObserver.observe(node, {
|
mutationObserver.observe(node, {
|
||||||
attributes: true,
|
attributes: true,
|
||||||
|
attributeFilter: ["style"],
|
||||||
})
|
})
|
||||||
observingMutations = true
|
observingMutations = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ interface DNDSource {
|
||||||
icon?: string
|
icon?: string
|
||||||
type: string
|
type: string
|
||||||
isNew: boolean
|
isNew: boolean
|
||||||
props?: Record<string, any>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DNDTarget {
|
interface DNDTarget {
|
||||||
|
@ -32,10 +31,15 @@ interface DNDDrop {
|
||||||
index: number
|
index: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DNDMeta {
|
||||||
|
props?: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
interface DNDState {
|
interface DNDState {
|
||||||
source?: DNDSource
|
source?: DNDSource
|
||||||
target?: DNDTarget
|
target?: DNDTarget
|
||||||
drop?: DNDDrop
|
drop?: DNDDrop
|
||||||
|
meta?: DNDMeta
|
||||||
}
|
}
|
||||||
|
|
||||||
const createDndStore = () => {
|
const createDndStore = () => {
|
||||||
|
@ -106,15 +110,12 @@ const createDndStore = () => {
|
||||||
store.set({})
|
store.set({})
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateSourceProps = (props: Record<string, any>) => {
|
const updateNewComponentProps = (props: Record<string, any>) => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
if (!state.source) {
|
|
||||||
return state
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
source: {
|
meta: {
|
||||||
...state.source,
|
...state.meta,
|
||||||
props,
|
props,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -129,7 +130,7 @@ const createDndStore = () => {
|
||||||
updateTarget,
|
updateTarget,
|
||||||
updateDrop,
|
updateDrop,
|
||||||
reset,
|
reset,
|
||||||
updateSourceProps,
|
updateNewComponentProps,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue