Refactor and tidy up

This commit is contained in:
Andrew Kingston 2024-07-30 16:48:54 +01:00
parent 29ddeab0d4
commit de183d5c78
No known key found for this signature in database
10 changed files with 74 additions and 50 deletions

View File

@ -117,6 +117,9 @@
"width": 400, "width": 400,
"height": 200 "height": 200
}, },
"grid": {
"fill": true
},
"styles": ["padding", "size", "background", "border", "shadow"], "styles": ["padding", "size", "background", "border", "shadow"],
"settings": [ "settings": [
{ {
@ -561,6 +564,10 @@
"width": 105, "width": 105,
"height": 32 "height": 32
}, },
"grid": {
"hAlign": "center",
"vAlign": "center"
},
"settings": [ "settings": [
{ {
"type": "text", "type": "text",

View File

@ -198,7 +198,9 @@
$: darkMode = !currentTheme?.includes("light") $: darkMode = !currentTheme?.includes("light")
// Build meta styles and stringify to apply to the wrapper node // Build meta styles and stringify to apply to the wrapper node
$: definitionMetaStyles = getDefinitonMetaStyles(definition)
$: metaStyles = { $: metaStyles = {
...definitionMetaStyles,
...instance._styles?.meta, ...instance._styles?.meta,
...ephemeralStyles, ...ephemeralStyles,
} }
@ -618,6 +620,22 @@
builderStore.actions.selectComponent(id) builderStore.actions.selectComponent(id)
} }
// Util to generate meta styles based on component definition
const alignToStyleMap = {
start: "flex-start",
center: "center",
end: "flex-end",
stretch: "stretch",
}
const getDefinitonMetaStyles = definition => {
const gridHAlign = definition.grid?.hAlign || "stretch"
const gridVAlign = definition.grid?.vAlign || "center"
return {
["align-items"]: alignToStyleMap[gridHAlign],
["justify-content"]: alignToStyleMap[gridVAlign],
}
}
onMount(() => { onMount(() => {
// Register this component instance for external access // Register this component instance for external access
if ($appStore.isDevApp) { if ($appStore.isDevApp) {
@ -661,6 +679,7 @@
class:parent={hasChildren} class:parent={hasChildren}
class:block={isBlock} class:block={isBlock}
class:error={errorState} class:error={errorState}
class:fill={definition.grid?.fill}
data-id={id} data-id={id}
data-name={name} data-name={name}
data-icon={icon} data-icon={icon}

View File

@ -123,4 +123,11 @@
--row-start: var(--grid-mobile-row-start, var(--grid-desktop-row-start, 1)); --row-start: var(--grid-mobile-row-start, var(--grid-desktop-row-start, 1));
--row-end: var(--grid-mobile-row-end, var(--grid-desktop-row-end, 2)); --row-end: var(--grid-mobile-row-end, var(--grid-desktop-row-end, 2));
} }
/* Handle grid children which need to fill the outer component wrapper */
.grid :global(> .component.fill > *) {
width: 100%;
height: 100%;
flex: 1 1 0;
}
</style> </style>

View File

@ -13,6 +13,7 @@
import { Utils } from "@budibase/frontend-core" import { Utils } from "@budibase/frontend-core"
import { findComponentById } from "utils/components.js" import { findComponentById } from "utils/components.js"
import { DNDPlaceholderID } from "constants" import { DNDPlaceholderID } from "constants"
import { isGridEvent } from "utils/grid"
const ThrottleRate = 130 const ThrottleRate = 130
@ -25,15 +26,6 @@
// 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
// Util to check if a DND event originates from a grid (or inside a grid).
// This is important as we do not handle grid DND in this handler.
const isGridEvent = e => {
return e.target
?.closest?.(".component")
?.parentNode?.closest?.(".component")
?.childNodes[0]?.classList.contains("grid")
}
// Util to get the inner DOM node by a component ID // Util to get the inner DOM node by a component ID
const getDOMNode = id => { const getDOMNode = id => {
return document.getElementsByClassName(`${id}-dom`)[0] return document.getElementsByClassName(`${id}-dom`)[0]
@ -267,7 +259,7 @@
// Check if we're adding a new component rather than moving one // Check if we're adding a new component rather than moving one
if (source.newComponentType) { if (source.newComponentType) {
dropping = true dropping = true
await builderStore.actions.dropNewComponent( builderStore.actions.dropNewComponent(
source.newComponentType, source.newComponentType,
drop.parent, drop.parent,
drop.index drop.index

View File

@ -1,7 +1,7 @@
<script> <script>
import { onMount } from "svelte" import { onMount } from "svelte"
import { DNDPlaceholderID } from "constants" import { DNDPlaceholderID } from "constants"
import { domDebounce } from "utils/domDebounce.js" import { Utils } from "@budibase/frontend-core"
let left, top, height, width let left, top, height, width
@ -19,7 +19,7 @@
width = bounds.width width = bounds.width
} }
} }
const debouncedUpdate = domDebounce(updatePosition) const debouncedUpdate = Utils.domDebounce(updatePosition)
onMount(() => { onMount(() => {
const interval = setInterval(debouncedUpdate, 100) const interval = setInterval(debouncedUpdate, 100)

View File

@ -2,6 +2,7 @@
import { onMount, onDestroy } from "svelte" import { onMount, onDestroy } from "svelte"
import { builderStore, componentStore } from "stores" import { builderStore, componentStore } from "stores"
import { Utils, memo } from "@budibase/frontend-core" import { Utils, memo } from "@budibase/frontend-core"
import { isGridEvent, getGridParentID } from "utils/grid"
// Enum for device preview type, included in CSS variables // Enum for device preview type, included in CSS variables
const Devices = { const Devices = {
@ -67,18 +68,6 @@
// Sugar for a combination of both min and max // Sugar for a combination of both min and max
const minMax = (value, min, max) => Math.min(max, Math.max(min, value)) const minMax = (value, min, max) => Math.min(max, Math.max(min, value))
// Util to check if a DND event originates from a grid (or inside a grid).
// This is important as we do not handle grid DND in this handler.
const isGridEvent = e => {
return (
e.target
.closest?.(".component")
?.parentNode.closest(".component")
?.childNodes[0].classList?.contains("grid") ||
e.target.classList.contains("anchor")
)
}
// Util to get the inner DOM node by a component ID // Util to get the inner DOM node by a component ID
const getDOMNode = id => { const getDOMNode = id => {
const component = document.getElementsByClassName(id)[0] const component = document.getElementsByClassName(id)[0]
@ -172,7 +161,7 @@
// Find grid parent // Find grid parent
const domComponent = getDOMNode(id) const domComponent = getDOMNode(id)
const gridId = domComponent?.closest(".grid")?.parentNode.dataset.id const gridId = getGridParentID(domComponent)
if (!gridId) { if (!gridId) {
return return
} }

View File

@ -2,7 +2,7 @@
import { onMount, onDestroy } from "svelte" import { onMount, onDestroy } from "svelte"
import Indicator from "./Indicator.svelte" import Indicator from "./Indicator.svelte"
import { builderStore, componentStore } from "stores" import { builderStore, componentStore } from "stores"
import { memo } from "@budibase/frontend-core" import { memo, Utils } from "@budibase/frontend-core"
import { writable } from "svelte/store" import { writable } from "svelte/store"
export let componentId = null export let componentId = null
@ -47,12 +47,12 @@
prefix, prefix,
allowResizeAnchors, allowResizeAnchors,
}) })
$: $config, updatePosition() $: $config, debouncedUpdate()
// Update position when component state changes // Update position when component state changes
$: instance = componentStore.actions.getComponentInstance(componentId) $: instance = componentStore.actions.getComponentInstance(componentId)
$: componentState = $instance?.state || writable() $: componentState = $instance?.state || writable()
$: $componentState, updatePosition() $: $componentState, debouncedUpdate()
const checkInsideGrid = id => { const checkInsideGrid = id => {
const component = document.getElementsByClassName(id)[0] const component = document.getElementsByClassName(id)[0]
@ -160,16 +160,17 @@
}) })
}) })
} }
const debouncedUpdate = Utils.domDebounce(updatePosition)
onMount(() => { onMount(() => {
updatePosition() debouncedUpdate()
interval = setInterval(updatePosition, 100) interval = setInterval(debouncedUpdate, 100)
document.addEventListener("scroll", updatePosition, true) document.addEventListener("scroll", debouncedUpdate, true)
}) })
onDestroy(() => { onDestroy(() => {
clearInterval(interval) clearInterval(interval)
document.removeEventListener("scroll", updatePosition, true) document.removeEventListener("scroll", v, true)
observers.forEach(o => o.disconnect()) observers.forEach(o => o.disconnect())
}) })
</script> </script>

View File

@ -4,7 +4,8 @@
import SettingsColorPicker from "./SettingsColorPicker.svelte" import SettingsColorPicker from "./SettingsColorPicker.svelte"
import SettingsPicker from "./SettingsPicker.svelte" import SettingsPicker from "./SettingsPicker.svelte"
import { builderStore, componentStore, dndIsDragging } from "stores" import { builderStore, componentStore, dndIsDragging } from "stores"
import { domDebounce } from "utils/domDebounce" import { Utils } from "@budibase/frontend-core"
import { isGridChild } from "utils/grid"
const verticalOffset = 36 const verticalOffset = 36
const horizontalOffset = 2 const horizontalOffset = 2
@ -49,8 +50,10 @@
return return
} }
const id = $builderStore.selectedComponentId const id = $builderStore.selectedComponentId
const parent = document.getElementsByClassName(id)?.[0] let element = document.getElementsByClassName(id)?.[0]
const element = parent?.children?.[0] if (!isGridChild(element)) {
element = element?.children?.[0]
}
// The settings bar is higher in the dom tree than the selection indicators // The settings bar is higher in the dom tree than the selection indicators
// as we want to be able to render the settings bar wider than the screen, // as we want to be able to render the settings bar wider than the screen,
@ -111,7 +114,7 @@
measured = true measured = true
} }
} }
const debouncedUpdate = domDebounce(updatePosition) const debouncedUpdate = Utils.domDebounce(updatePosition)
onMount(() => { onMount(() => {
debouncedUpdate() debouncedUpdate()

View File

@ -1,14 +0,0 @@
export const domDebounce = (callback, extractParams = x => x) => {
let active = false
let lastParams
return (...params) => {
lastParams = extractParams(...params)
if (!active) {
active = true
requestAnimationFrame(() => {
callback(lastParams)
active = false
})
}
}
}

View File

@ -0,0 +1,20 @@
export const isGridEvent = e => {
return (
e.target
.closest?.(".component")
?.parentNode.closest(".component")
?.childNodes[0]?.classList?.contains("grid") ||
e.target.classList.contains("anchor")
)
}
export const isGridChild = node => {
return node
?.closest(".component")
?.parentNode.closest(".component")
?.childNodes[0]?.classList?.contains("grid")
}
export const getGridParentID = node => {
return node?.closest(".grid")?.parentNode.dataset.id
}