Update when grid lines are shown, show sibling borders, add component padding, remove row and column settings

This commit is contained in:
Andrew Kingston 2024-08-06 11:07:20 +01:00
parent 5071f39153
commit df77aa3f83
No known key found for this signature in database
6 changed files with 107 additions and 100 deletions

View File

@ -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 return settings
} }

View File

@ -145,32 +145,6 @@
], ],
"defaultValue": "flex" "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", "type": "select",
"label": "Direction", "label": "Direction",

View File

@ -480,10 +480,10 @@
position: relative; position: relative;
padding: 32px; padding: 32px;
} }
.main:has(.screenslot-dom > .component > .grid) { /* .main:has(.screenslot-dom > .component > .grid) {
padding-top: 0; padding-top: 0;
padding-bottom: 0; padding-bottom: 0;
} }*/
.layout--none .main { .layout--none .main {
padding: 0; padding: 0;
} }

View File

@ -2,19 +2,18 @@
import { getContext } from "svelte" import { getContext } from "svelte"
const component = getContext("component") const component = getContext("component")
const { styleable, builderStore } = getContext("sdk") const { styleable } = getContext("sdk")
const context = getContext("context") const context = getContext("context")
export let cols = 12 const cols = 12
export let rows = 12 const rowHeight = 24
let width let width
let height let height
$: cols = cols || 12
$: rows = rows || 12
$: mobile = $context.device.mobile $: mobile = $context.device.mobile
$: empty = $component.empty $: empty = $component.empty
$: rows = Math.max(1, Math.floor(height / rowHeight))
$: colSize = width / cols $: colSize = width / cols
$: rowSize = height / rows $: rowSize = height / rows
</script> </script>
@ -22,7 +21,6 @@
<div <div
class="grid" class="grid"
class:mobile class:mobile
class:builder={$builderStore.inBuilder}
bind:clientWidth={width} bind:clientWidth={width}
bind:clientHeight={height} bind:clientHeight={height}
use:styleable={{ use:styleable={{
@ -39,13 +37,11 @@
data-rows={rows} data-rows={rows}
data-cols={cols} data-cols={cols}
> >
{#if $builderStore.inBuilder}
<div class="underlay"> <div class="underlay">
{#each { length: cols * rows } as _} {#each { length: cols * rows } as _}
<div class="placeholder" /> <div class="placeholder" />
{/each} {/each}
</div> </div>
{/if}
<!-- Only render the slot if not empty, as we don't want the placeholder --> <!-- Only render the slot if not empty, as we don't want the placeholder -->
{#if !empty} {#if !empty}
@ -57,32 +53,53 @@
.grid { .grid {
position: relative; position: relative;
height: 400px; height: 400px;
gap: 0; --spacing: 10;
}
.grid.builder {
background: var(--spectrum-alias-background-color-secondary);
} }
.grid, .grid,
.underlay { .underlay {
display: grid; display: grid;
grid-template-rows: repeat(var(--rows), 1fr); grid-template-rows: repeat(var(--rows), 1fr);
grid-template-columns: repeat(var(--cols), 1fr); grid-template-columns: repeat(var(--cols), 1fr);
gap: 0;
} }
.underlay { .underlay {
display: none;
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
border: 1px solid var(--spectrum-global-color-gray-900); border-top: 1px solid var(--spectrum-global-color-gray-900);
opacity: 0.07; border-left: 1px solid var(--spectrum-global-color-gray-900);
opacity: 0.1;
pointer-events: none; pointer-events: none;
} }
.underlay { .underlay {
z-index: 0; z-index: 0;
} }
.placeholder { .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 */ /* Ensure all top level children have grid styles applied */
@ -90,6 +107,9 @@
display: flex; display: flex;
overflow: auto; overflow: auto;
pointer-events: all; pointer-events: all;
position: relative;
padding: 5px;
margin: 5px;
/* On desktop, use desktop metadata and fall back to mobile */ /* On desktop, use desktop metadata and fall back to mobile */
/* Position vars */ /* Position vars */
@ -98,7 +118,12 @@
--grid-desktop-col-end, --grid-desktop-col-end,
var( var(
--grid-mobile-col-end, --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)); --row-start: var(--grid-desktop-row-start, var(--grid-mobile-row-start, 1));
@ -106,7 +131,12 @@
--grid-desktop-row-end, --grid-desktop-row-end,
var( var(
--grid-mobile-row-end, --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, --grid-mobile-col-end,
var( var(
--grid-desktop-col-end, --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)); --row-start: var(--grid-mobile-row-start, var(--grid-desktop-row-start, 1));
@ -145,7 +180,12 @@
--grid-mobile-row-end, --grid-mobile-row-end,
var( var(
--grid-desktop-row-end, --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
)
)
) )
); );

View File

@ -4,7 +4,7 @@
import { Utils, memo } from "@budibase/frontend-core" import { Utils, memo } from "@budibase/frontend-core"
import { import {
isGridEvent, isGridEvent,
getGridParentID, getGridParent,
GridParams, GridParams,
getGridVar, getGridVar,
} from "utils/grid" } from "utils/grid"
@ -62,6 +62,9 @@
const { startX, startY, rowStart, rowEnd, colStart, colEnd } = grid const { startX, startY, rowStart, rowEnd, colStart, colEnd } = grid
const domGrid = getDOMNode(gridId) const domGrid = getDOMNode(gridId)
if (!domGrid) {
return
}
const cols = parseInt(domGrid.dataset.cols) const cols = parseInt(domGrid.dataset.cols)
const rows = parseInt(domGrid.dataset.rows) const rows = parseInt(domGrid.dataset.rows)
const { width, height } = domGrid.getBoundingClientRect() const { width, height } = domGrid.getBoundingClientRect()
@ -107,7 +110,7 @@
} }
gridStyles.set(newStyles) gridStyles.set(newStyles)
} }
}, 100) }, 10)
const handleEvent = e => { const handleEvent = e => {
e.preventDefault() e.preventDefault()
@ -140,16 +143,20 @@
// Find grid parent // Find grid parent
const domComponent = getDOMNode(id) const domComponent = getDOMNode(id)
const gridId = getGridParentID(domComponent) const domGrid = getGridParent(domComponent)
if (!gridId) { if (!domGrid) {
return return
} }
// Apply active class to grid
domComponent.parentNode.classList.add("dragging")
domGrid.classList.add("highlight")
// Update state // Update state
dragInfo = { dragInfo = {
domTarget: e.target, domTarget: e.target,
id, id,
gridId, gridId: domGrid.parentNode.dataset.id,
mode, mode,
side, side,
} }
@ -168,10 +175,12 @@
const { id, gridId } = dragInfo const { id, gridId } = dragInfo
const domComponent = getDOMNode(id) const domComponent = getDOMNode(id)
const domGrid = getDOMNode(gridId) const domGrid = getDOMNode(gridId)
if (!domComponent || !domGrid) {
return
}
const gridCols = parseInt(domGrid.dataset.cols) const gridCols = parseInt(domGrid.dataset.cols)
const gridRows = parseInt(domGrid.dataset.rows) const gridRows = parseInt(domGrid.dataset.rows)
const styles = getComputedStyle(domComponent.parentNode) const styles = getComputedStyle(domComponent.parentNode)
if (domGrid) {
dragInfo.grid = { dragInfo.grid = {
startX: e.clientX, startX: e.clientX,
startY: e.clientY, startY: e.clientY,
@ -184,7 +193,6 @@
} }
handleEvent(e) handleEvent(e)
} }
}
const onDragOver = e => { const onDragOver = e => {
if (!dragInfo?.grid) { if (!dragInfo?.grid) {
@ -195,15 +203,26 @@
// Callback when drag stops (whether dropped or not) // Callback when drag stops (whether dropped or not)
const stopDragging = async () => { const stopDragging = async () => {
if (!dragInfo) {
return
}
const { id, gridId, domTarget } = dragInfo
// Save changes // Save changes
if ($gridStyles) { if ($gridStyles) {
await builderStore.actions.updateStyles($gridStyles, dragInfo.id) await builderStore.actions.updateStyles($gridStyles, id)
} }
// Reset listener // Reset DOM
if (dragInfo?.domTarget) { const domComponent = getDOMNode(id)
dragInfo.domTarget.removeEventListener("dragend", stopDragging) if (domComponent) {
domComponent.parentNode.classList.remove("dragging")
} }
const domGrid = getDOMNode(gridId)
if (domGrid) {
domGrid.classList.remove("highlight")
}
domTarget.removeEventListener("dragend", stopDragging)
// Reset state // Reset state
dragInfo = null dragInfo = null

View File

@ -60,8 +60,8 @@ export const isGridChild = node => {
} }
// Gets the component ID of the closest parent grid // Gets the component ID of the closest parent grid
export const getGridParentID = node => { export const getGridParent = node => {
return node?.parentNode?.closest(".grid")?.parentNode.dataset.id return node?.parentNode?.closest(".grid")
} }
// Svelte action to apply required class names and styles to our component // Svelte action to apply required class names and styles to our component