diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte
index 2a5211a253..020dc11ae8 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte
@@ -96,32 +96,6 @@
},
]
- // Add grid layout settings if required
- if (screen.props.layout === "grid") {
- settings = settings.concat([
- {
- key: "props.cols",
- label: "Columns",
- control: Stepper,
- defaultValue: 24,
- props: {
- min: 2,
- max: 50,
- },
- },
- {
- key: "props.rows",
- label: "Rows",
- control: Stepper,
- defaultValue: 24,
- props: {
- min: 2,
- max: 50,
- },
- },
- ])
- }
-
return settings
}
diff --git a/packages/client/manifest.json b/packages/client/manifest.json
index 6f665a80d7..8ca9698bcf 100644
--- a/packages/client/manifest.json
+++ b/packages/client/manifest.json
@@ -145,32 +145,6 @@
],
"defaultValue": "flex"
},
- {
- "type": "number",
- "label": "Columns",
- "key": "cols",
- "placeholder": 12,
- "defaultValue": 12,
- "min": 2,
- "max": 50,
- "dependsOn": {
- "setting": "layout",
- "value": "grid"
- }
- },
- {
- "type": "number",
- "label": "Rows",
- "key": "rows",
- "placeholder": 12,
- "defaultValue": 12,
- "min": 2,
- "max": 50,
- "dependsOn": {
- "setting": "layout",
- "value": "grid"
- }
- },
{
"type": "select",
"label": "Direction",
diff --git a/packages/client/src/components/app/Layout.svelte b/packages/client/src/components/app/Layout.svelte
index 9cfa74cbb0..34de8122c8 100644
--- a/packages/client/src/components/app/Layout.svelte
+++ b/packages/client/src/components/app/Layout.svelte
@@ -480,10 +480,10 @@
position: relative;
padding: 32px;
}
- .main:has(.screenslot-dom > .component > .grid) {
+ /* .main:has(.screenslot-dom > .component > .grid) {
padding-top: 0;
padding-bottom: 0;
- }
+ }*/
.layout--none .main {
padding: 0;
}
diff --git a/packages/client/src/components/app/container/GridContainer.svelte b/packages/client/src/components/app/container/GridContainer.svelte
index cfe6f7d7bf..b46e763277 100644
--- a/packages/client/src/components/app/container/GridContainer.svelte
+++ b/packages/client/src/components/app/container/GridContainer.svelte
@@ -2,19 +2,18 @@
import { getContext } from "svelte"
const component = getContext("component")
- const { styleable, builderStore } = getContext("sdk")
+ const { styleable } = getContext("sdk")
const context = getContext("context")
- export let cols = 12
- export let rows = 12
+ const cols = 12
+ const rowHeight = 24
let width
let height
- $: cols = cols || 12
- $: rows = rows || 12
$: mobile = $context.device.mobile
$: empty = $component.empty
+ $: rows = Math.max(1, Math.floor(height / rowHeight))
$: colSize = width / cols
$: rowSize = height / rows
@@ -22,7 +21,6 @@
- {#if $builderStore.inBuilder}
-
- {#each { length: cols * rows } as _}
-
- {/each}
-
- {/if}
+
+ {#each { length: cols * rows } as _}
+
+ {/each}
+
{#if !empty}
@@ -57,32 +53,53 @@
.grid {
position: relative;
height: 400px;
- gap: 0;
- }
- .grid.builder {
- background: var(--spectrum-alias-background-color-secondary);
+ --spacing: 10;
}
+
.grid,
.underlay {
display: grid;
grid-template-rows: repeat(var(--rows), 1fr);
grid-template-columns: repeat(var(--cols), 1fr);
+ gap: 0;
}
.underlay {
+ display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
- border: 1px solid var(--spectrum-global-color-gray-900);
- opacity: 0.07;
+ border-top: 1px solid var(--spectrum-global-color-gray-900);
+ border-left: 1px solid var(--spectrum-global-color-gray-900);
+ opacity: 0.1;
pointer-events: none;
}
.underlay {
z-index: 0;
}
.placeholder {
- border: 1px solid var(--spectrum-global-color-gray-900);
+ border-bottom: 1px solid var(--spectrum-global-color-gray-900);
+ border-right: 1px solid var(--spectrum-global-color-gray-900);
+ }
+
+ /* Highlight grid lines when resizing children */
+ :global(.grid.highlight > .underlay) {
+ display: grid;
+ }
+
+ /* Highlight sibling borders when resizing childern */
+ :global(.grid.highlight > .component:not(.dragging):after) {
+ content: "";
+ display: block;
+ position: absolute;
+ height: 100%;
+ width: 100%;
+ border: 1px solid var(--spectrum-global-color-static-blue-200);
+ pointer-events: none;
+ z-index: 1;
+ top: 0;
+ left: 0;
}
/* Ensure all top level children have grid styles applied */
@@ -90,6 +107,9 @@
display: flex;
overflow: auto;
pointer-events: all;
+ position: relative;
+ padding: 5px;
+ margin: 5px;
/* On desktop, use desktop metadata and fall back to mobile */
/* Position vars */
@@ -98,7 +118,12 @@
--grid-desktop-col-end,
var(
--grid-mobile-col-end,
- round(up, calc(var(--default-width) / var(--col-size) + 1))
+ round(
+ up,
+ calc(
+ (var(--spacing) * 2 + var(--default-width)) / var(--col-size) + 1
+ )
+ )
)
);
--row-start: var(--grid-desktop-row-start, var(--grid-mobile-row-start, 1));
@@ -106,7 +131,12 @@
--grid-desktop-row-end,
var(
--grid-mobile-row-end,
- round(up, calc(var(--default-height) / var(--row-size) + 1))
+ round(
+ up,
+ calc(
+ (var(--spacing) * 2 + var(--default-height)) / var(--row-size) + 1
+ )
+ )
)
);
@@ -137,7 +167,12 @@
--grid-mobile-col-end,
var(
--grid-desktop-col-end,
- round(up, calc(var(--default-width) / var(--col-size) + 1))
+ round(
+ up,
+ calc(
+ (var(--spacing) * 2 + var(--default-width)) / var(--col-size) + 1
+ )
+ )
)
);
--row-start: var(--grid-mobile-row-start, var(--grid-desktop-row-start, 1));
@@ -145,7 +180,12 @@
--grid-mobile-row-end,
var(
--grid-desktop-row-end,
- round(up, calc(var(--default-height) / var(--row-size) + 1))
+ round(
+ up,
+ calc(
+ (var(--spacing) * 2 + var(--default-height)) / var(--row-size) + 1
+ )
+ )
)
);
diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte
index f723d9ad29..fe004982d3 100644
--- a/packages/client/src/components/preview/GridDNDHandler.svelte
+++ b/packages/client/src/components/preview/GridDNDHandler.svelte
@@ -4,7 +4,7 @@
import { Utils, memo } from "@budibase/frontend-core"
import {
isGridEvent,
- getGridParentID,
+ getGridParent,
GridParams,
getGridVar,
} from "utils/grid"
@@ -62,6 +62,9 @@
const { startX, startY, rowStart, rowEnd, colStart, colEnd } = grid
const domGrid = getDOMNode(gridId)
+ if (!domGrid) {
+ return
+ }
const cols = parseInt(domGrid.dataset.cols)
const rows = parseInt(domGrid.dataset.rows)
const { width, height } = domGrid.getBoundingClientRect()
@@ -107,7 +110,7 @@
}
gridStyles.set(newStyles)
}
- }, 100)
+ }, 10)
const handleEvent = e => {
e.preventDefault()
@@ -140,16 +143,20 @@
// Find grid parent
const domComponent = getDOMNode(id)
- const gridId = getGridParentID(domComponent)
- if (!gridId) {
+ const domGrid = getGridParent(domComponent)
+ if (!domGrid) {
return
}
+ // Apply active class to grid
+ domComponent.parentNode.classList.add("dragging")
+ domGrid.classList.add("highlight")
+
// Update state
dragInfo = {
domTarget: e.target,
id,
- gridId,
+ gridId: domGrid.parentNode.dataset.id,
mode,
side,
}
@@ -168,22 +175,23 @@
const { id, gridId } = dragInfo
const domComponent = getDOMNode(id)
const domGrid = getDOMNode(gridId)
+ if (!domComponent || !domGrid) {
+ return
+ }
const gridCols = parseInt(domGrid.dataset.cols)
const gridRows = parseInt(domGrid.dataset.rows)
const styles = getComputedStyle(domComponent.parentNode)
- if (domGrid) {
- dragInfo.grid = {
- startX: e.clientX,
- startY: e.clientY,
+ dragInfo.grid = {
+ startX: e.clientX,
+ startY: e.clientY,
- // Ensure things are within limits
- rowStart: minMax(styles["grid-row-start"], 1, gridRows),
- rowEnd: minMax(styles["grid-row-end"], 2, gridRows + 1),
- colStart: minMax(styles["grid-column-start"], 1, gridCols),
- colEnd: minMax(styles["grid-column-end"], 2, gridCols + 1),
- }
- handleEvent(e)
+ // Ensure things are within limits
+ rowStart: minMax(styles["grid-row-start"], 1, gridRows),
+ rowEnd: minMax(styles["grid-row-end"], 2, gridRows + 1),
+ colStart: minMax(styles["grid-column-start"], 1, gridCols),
+ colEnd: minMax(styles["grid-column-end"], 2, gridCols + 1),
}
+ handleEvent(e)
}
const onDragOver = e => {
@@ -195,15 +203,26 @@
// Callback when drag stops (whether dropped or not)
const stopDragging = async () => {
+ if (!dragInfo) {
+ return
+ }
+ const { id, gridId, domTarget } = dragInfo
+
// Save changes
if ($gridStyles) {
- await builderStore.actions.updateStyles($gridStyles, dragInfo.id)
+ await builderStore.actions.updateStyles($gridStyles, id)
}
- // Reset listener
- if (dragInfo?.domTarget) {
- dragInfo.domTarget.removeEventListener("dragend", stopDragging)
+ // Reset DOM
+ const domComponent = getDOMNode(id)
+ if (domComponent) {
+ domComponent.parentNode.classList.remove("dragging")
}
+ const domGrid = getDOMNode(gridId)
+ if (domGrid) {
+ domGrid.classList.remove("highlight")
+ }
+ domTarget.removeEventListener("dragend", stopDragging)
// Reset state
dragInfo = null
diff --git a/packages/client/src/utils/grid.js b/packages/client/src/utils/grid.js
index 1d80e49696..54c5e2c24f 100644
--- a/packages/client/src/utils/grid.js
+++ b/packages/client/src/utils/grid.js
@@ -60,8 +60,8 @@ export const isGridChild = node => {
}
// Gets the component ID of the closest parent grid
-export const getGridParentID = node => {
- return node?.parentNode?.closest(".grid")?.parentNode.dataset.id
+export const getGridParent = node => {
+ return node?.parentNode?.closest(".grid")
}
// Svelte action to apply required class names and styles to our component