Use a container as the DND placeholder and use approx size when dragging into grids

This commit is contained in:
Andrew Kingston 2022-10-19 14:39:28 +01:00
parent 803b11d65f
commit 0c2e286ca7
9 changed files with 108 additions and 74 deletions

View File

@ -446,12 +446,7 @@ export const getFrontendStore = () => {
_id: Helpers.uuid(), _id: Helpers.uuid(),
_component: definition.component, _component: definition.component,
_styles: { _styles: {
normal: { normal: {},
"grid-column-start": 1,
"grid-column-end": 2,
"grid-row-start": 1,
"grid-row-end": 2,
},
hover: {}, hover: {},
active: {}, active: {},
}, },

View File

@ -87,10 +87,9 @@
"showSettingsBar": true, "showSettingsBar": true,
"size": { "size": {
"width": 400, "width": 400,
"height": 100 "height": 200
}, },
"styles": [ "styles": [
"grid",
"padding", "padding",
"size", "size",
"background", "background",

View File

@ -35,6 +35,7 @@
export let isScreen = false export let isScreen = false
export let isBlock = false export let isBlock = false
export let parent = null export let parent = null
export let parentType = null
// Get parent contexts // Get parent contexts
const context = getContext("context") const context = getContext("context")
@ -165,15 +166,21 @@
$: pad = pad || (interactive && hasChildren && inDndPath) $: pad = pad || (interactive && hasChildren && inDndPath)
$: $dndIsDragging, (pad = false) $: $dndIsDragging, (pad = false)
// Update component context // We can apply additional styles automatically if required.
$: store.set({ // One use case for this is ensuring grid children have proper styles to
id, // display properly inside a grid.
children: children.length, $: additionalStyles = getAdditionalStyles(
styles: { instance._styles?.normal || {},
parentType,
definition
)
// Compute overall styles
$: styles = {
...instance._styles, ...instance._styles,
normal: { normal: {
...instance._styles?.normal, ...instance._styles?.normal,
...(selected ? $builderStore.gridStyles : null), ...additionalStyles,
}, },
custom: customCSS, custom: customCSS,
id, id,
@ -181,7 +188,13 @@
interactive, interactive,
draggable, draggable,
editable, editable,
}, }
// Update component context
$: store.set({
id,
children: children.length,
styles,
empty: emptyState, empty: emptyState,
selected, selected,
name, name,
@ -442,6 +455,54 @@
}) })
} }
const getAdditionalStyles = (styles, parentType, definition) => {
let newStyles = {}
// Ensure grid styles are set
if (parentType?.endsWith("/grid")) {
newStyles = {
...newStyles,
overflow: "hidden",
width: "auto",
height: "auto",
}
// Guess rough grid size from definition size
let columns = 6
let rows = 4
if (definition.size?.width) {
columns = Math.round(definition.size.width / 100)
}
if (definition.size?.height) {
rows = Math.round(definition.size.height / 100)
}
// Ensure grid position styles are set
if (!styles["grid-column-start"]) {
newStyles["grid-column-start"] = 1
}
if (!styles["grid-column-end"]) {
newStyles["grid-column-end"] = columns + 1
}
if (!styles["grid-row-start"]) {
newStyles["grid-row-start"] = 1
}
if (!styles["grid-row-end"]) {
newStyles["grid-row-end"] = rows + 1
}
// Ensure grid end styles aren't before grid start styles
if (newStyles["grid-column-end"] <= newStyles["grid-column-start"]) {
newStyles["grid-column-end"] = newStyles["grid-column-start"] + 1
}
if (newStyles["grid-row-end"] <= newStyles["grid-row-start"]) {
newStyles["grid-row-end"] = newStyles["grid-row-start"] + 1
}
}
return newStyles
}
onMount(() => { onMount(() => {
if ( if (
$appStore.isDevApp && $appStore.isDevApp &&
@ -450,6 +511,7 @@
componentStore.actions.registerInstance(id, { componentStore.actions.registerInstance(id, {
component: instance._component, component: instance._component,
getSettings: () => cachedSettings, getSettings: () => cachedSettings,
getStyles: () => styles,
getRawSettings: () => ({ ...staticSettings, ...dynamicSettings }), getRawSettings: () => ({ ...staticSettings, ...dynamicSettings }),
getDataContext: () => get(context), getDataContext: () => get(context),
reload: () => initialise(instance, true), reload: () => initialise(instance, true),
@ -490,7 +552,11 @@
<ComponentPlaceholder /> <ComponentPlaceholder />
{:else if children.length} {:else if children.length}
{#each children as child (child._id)} {#each children as child (child._id)}
<svelte:self instance={child} parent={id} /> <svelte:self
instance={child}
parent={id}
parentType={instance._component}
/>
{/each} {/each}
{:else if emptyState} {:else if emptyState}
{#if isScreen} {#if isScreen}

View File

@ -1,33 +0,0 @@
<script>
import { dndBounds } from "stores"
import { DNDPlaceholderID } from "constants"
$: style = getStyle($dndBounds)
const getStyle = bounds => {
if (!bounds) {
return null
}
return `--height: ${bounds.height}px; --width: ${bounds.width}px;`
}
</script>
{#if style}
<div class="wrapper">
<div class="placeholder" id={DNDPlaceholderID} {style} />
</div>
{/if}
<style>
.wrapper {
overflow: hidden;
}
.placeholder {
display: block;
height: var(--height);
width: var(--width);
max-height: 100%;
max-width: 100%;
opacity: 0;
}
</style>

View File

@ -6,7 +6,8 @@
let left, top, height, width let left, top, height, width
const updatePosition = () => { const updatePosition = () => {
const node = document.getElementById(DNDPlaceholderID) const node =
document.getElementsByClassName(DNDPlaceholderID)[0]?.childNodes[0]
if (!node) { if (!node) {
height = 0 height = 0
width = 0 width = 0

View File

@ -1,6 +1,6 @@
<script> <script>
import { onMount, onDestroy } from "svelte" import { onMount, onDestroy } from "svelte"
import { builderStore, screenStore } from "stores" import { builderStore, componentStore, screenStore } from "stores"
import { Utils } from "@budibase/frontend-core" import { Utils } from "@budibase/frontend-core"
import { findComponentById } from "utils/components.js" import { findComponentById } from "utils/components.js"
@ -157,16 +157,14 @@
return return
} }
const compDef = findComponentById( const instance = componentStore.actions.getComponentInstance(dragInfo.id)
$screenStore.activeScreen.props, if (!instance) {
dragInfo.id
)
if (!compDef) {
return return
} }
const styles = instance.getStyles()
const domGrid = getDOMNode(dragInfo.gridId) const domGrid = getDOMNode(dragInfo.gridId)
if (domGrid) { if (domGrid) {
const getStyle = x => parseInt(compDef._styles.normal?.[x] || "0") const getStyle = x => parseInt(styles?.normal?.[x] || "0")
dragInfo.grid = { dragInfo.grid = {
startX: e.clientX, startX: e.clientX,
startY: e.clientY, startY: e.clientY,

View File

@ -32,5 +32,4 @@ export const ActionTypes = {
} }
export const DNDPlaceholderID = "dnd-placeholder" export const DNDPlaceholderID = "dnd-placeholder"
export const DNDPlaceholderType = "dnd-placeholder"
export const ScreenslotType = "screenslot" export const ScreenslotType = "screenslot"

View File

@ -5,9 +5,8 @@ import { devToolsStore } from "./devTools"
import { screenStore } from "./screens" import { screenStore } from "./screens"
import { builderStore } from "./builder" import { builderStore } from "./builder"
import Router from "../components/Router.svelte" import Router from "../components/Router.svelte"
import DNDPlaceholder from "../components/preview/DNDPlaceholder.svelte"
import * as AppComponents from "../components/app/index.js" import * as AppComponents from "../components/app/index.js"
import { DNDPlaceholderType, ScreenslotType } from "../constants.js" import { ScreenslotType } from "../constants.js"
const budibasePrefix = "@budibase/standard-components/" const budibasePrefix = "@budibase/standard-components/"
@ -103,8 +102,6 @@ const createComponentStore = () => {
// Screenslot is an edge case // Screenslot is an edge case
if (type === ScreenslotType) { if (type === ScreenslotType) {
type = `${budibasePrefix}${type}` type = `${budibasePrefix}${type}`
} else if (type === DNDPlaceholderType) {
return {}
} }
// Handle built-in components // Handle built-in components
@ -124,8 +121,6 @@ const createComponentStore = () => {
} }
if (type === ScreenslotType) { if (type === ScreenslotType) {
return Router return Router
} else if (type === DNDPlaceholderType) {
return DNDPlaceholder
} }
// Handle budibase components // Handle budibase components
@ -140,6 +135,10 @@ const createComponentStore = () => {
return customComponentManifest?.[type]?.Component return customComponentManifest?.[type]?.Component
} }
const getComponentInstance = id => {
return get(store).mountedComponents[id]
}
const registerCustomComponent = ({ Component, schema, version }) => { const registerCustomComponent = ({ Component, schema, version }) => {
if (!Component || !schema?.schema?.name || !version) { if (!Component || !schema?.schema?.name || !version) {
return return
@ -171,6 +170,7 @@ const createComponentStore = () => {
getComponentById, getComponentById,
getComponentDefinition, getComponentDefinition,
getComponentConstructor, getComponentConstructor,
getComponentInstance,
registerCustomComponent, registerCustomComponent,
}, },
} }

View File

@ -2,11 +2,11 @@ import { derived } from "svelte/store"
import { routeStore } from "./routes" import { routeStore } from "./routes"
import { builderStore } from "./builder" import { builderStore } from "./builder"
import { appStore } from "./app" import { appStore } from "./app"
import { dndIndex, dndParent, dndIsNewComponent } from "./dnd.js" import { dndIndex, dndParent, dndIsNewComponent, dndBounds } from "./dnd.js"
import { RoleUtils } from "@budibase/frontend-core" import { RoleUtils } from "@budibase/frontend-core"
import { findComponentById, findComponentParent } from "../utils/components.js" import { findComponentById, findComponentParent } from "../utils/components.js"
import { Helpers } from "@budibase/bbui" import { Helpers } from "@budibase/bbui"
import { DNDPlaceholderID, DNDPlaceholderType } from "constants" import { DNDPlaceholderID } from "constants"
const createScreenStore = () => { const createScreenStore = () => {
const store = derived( const store = derived(
@ -17,6 +17,7 @@ const createScreenStore = () => {
dndParent, dndParent,
dndIndex, dndIndex,
dndIsNewComponent, dndIsNewComponent,
dndBounds,
], ],
([ ([
$appStore, $appStore,
@ -25,6 +26,7 @@ const createScreenStore = () => {
$dndParent, $dndParent,
$dndIndex, $dndIndex,
$dndIsNewComponent, $dndIsNewComponent,
$dndBounds,
]) => { ]) => {
let activeLayout, activeScreen let activeLayout, activeScreen
let screens let screens
@ -79,8 +81,15 @@ const createScreenStore = () => {
// Insert placeholder component // Insert placeholder component
const placeholder = { const placeholder = {
_component: DNDPlaceholderID, _component: "@budibase/standard-components/container",
_id: DNDPlaceholderType, _id: DNDPlaceholderID,
_styles: {
normal: {
width: `${$dndBounds?.width || 666}px`,
height: `${$dndBounds?.height || 666}px`,
opacity: 0,
},
},
static: true, static: true,
} }
let parent = findComponentById(activeScreen.props, $dndParent) let parent = findComponentById(activeScreen.props, $dndParent)