1
0
Fork 0
mirror of synced 2024-10-03 10:36:59 +13:00

More upgrades to grids to support new popovers and use popovers for options cells

This commit is contained in:
Andrew Kingston 2024-04-24 16:28:44 +01:00
parent 795991438f
commit 443be4cdab
7 changed files with 56 additions and 84 deletions

View file

@ -101,7 +101,7 @@
<style>
.wrapper {
flex: 1 1 auto;
flex: 0 0 400px;
margin: -28px -40px -40px -40px;
display: flex;
flex-direction: column;

View file

@ -1,10 +1,5 @@
<script>
import {
CoreDatePickerPopoverContents,
Icon,
Helpers,
clickOutside,
} from "@budibase/bbui"
import { CoreDatePickerPopoverContents, Icon, Helpers } from "@budibase/bbui"
import { onMount } from "svelte"
import dayjs from "dayjs"
import GridPopover from "../overlays/GridPopover.svelte"
@ -16,7 +11,6 @@
export let readonly = false
export let api
export let invertX = false
export let invertY = false
export let rand
let isOpen
@ -118,17 +112,15 @@
</div>
{#if isOpen}
<GridPopover bind:open={isOpen} {anchor} {invertX} {rand}>
<div class="picker" use:clickOutside={close}>
<CoreDatePickerPopoverContents
value={parsedValue}
on:change={e => (value = e.detail)}
{enableTime}
{timeOnly}
{ignoreTimezones}
useKeyboardShortcuts={false}
/>
</div>
<GridPopover open={isOpen} {anchor} {invertX} {rand} on:close={close}>
<CoreDatePickerPopoverContents
value={parsedValue}
useKeyboardShortcuts={false}
on:change={e => (value = e.detail)}
{enableTime}
{timeOnly}
{ignoreTimezones}
/>
</GridPopover>
{/if}
@ -155,9 +147,4 @@
line-height: 20px;
height: 20px;
}
.picker {
background: var(--grid-background-alt);
border: var(--cell-border);
border-radius: 2px;
}
</style>

View file

@ -1,7 +1,8 @@
<script>
import { Icon, clickOutside } from "@budibase/bbui"
import { Icon } from "@budibase/bbui"
import { getColor } from "../lib/utils"
import { onMount } from "svelte"
import GridPopover from "../overlays/GridPopover.svelte"
export let value
export let schema
@ -10,12 +11,13 @@
export let multi = false
export let readonly = false
export let api
export let invertX = false
export let invertY = false
export let invertX
export let contentLines = 1
export let rand
let isOpen = false
let focusedOptionIdx = null
let anchor
$: options = schema?.constraints?.inclusion || []
$: optionColors = schema?.optionColors || {}
@ -89,6 +91,7 @@
class:editable
class:open
on:click|self={editable ? open : null}
bind:this={anchor}
>
<div
class="values"
@ -115,16 +118,15 @@
<Icon name="ChevronDown" />
</div>
{/if}
{#if isOpen}
<div
class="options"
class:invertX
class:invertY
on:wheel={e => e.stopPropagation()}
use:clickOutside={close}
>
</div>
{#if isOpen}
<GridPopover open={isOpen} {anchor} {rand} {invertX} on:close={close}>
<div class="options" on:wheel={e => e.stopPropagation()}>
{#each options as option, idx}
{@const color = optionColors[option] || getOptionColor(option)}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="option"
on:click={() => toggleOption(option)}
@ -132,7 +134,9 @@
on:mouseenter={() => (focusedOptionIdx = idx)}
>
<div class="badge text" style="--color: {color}">
{option}
<span>
{option}
</span>
</div>
{#if values.includes(option)}
<Icon name="Checkmark" color="var(--accent-color)" />
@ -140,8 +144,8 @@
</div>
{/each}
</div>
{/if}
</div>
</GridPopover>
{/if}
<style>
.container {
@ -211,28 +215,14 @@
);
}
.options {
min-width: calc(100% + 2px);
position: absolute;
top: 100%;
left: -1px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
max-height: var(--max-cell-render-overflow);
overflow-y: auto;
border: var(--cell-border);
box-shadow: 0 0 20px -4px rgba(0, 0, 0, 0.15);
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
.options.invertX {
left: auto;
right: 0;
}
.options.invertY {
transform: translateY(-100%);
top: 0;
min-width: 200px;
max-width: 400px;
}
.option {
flex: 0 0 var(--default-row-height);
@ -247,5 +237,6 @@
.option:hover,
.option.focused {
background-color: var(--spectrum-global-color-gray-200);
cursor: pointer;
}
</style>

View file

@ -12,6 +12,7 @@
bounds,
hoveredRowId,
menu,
focusedCellAPI,
} = getContext("grid")
export let scrollVertically = false
@ -35,6 +36,9 @@
e.preventDefault()
updateScroll(e.deltaX, e.deltaY, e.clientY)
// Close any open popovers when scrolling
$focusedCellAPI?.blur()
// If a context menu was visible, hide it
if ($menu.visible) {
menu.actions.close()

View file

@ -1,40 +1,30 @@
<script>
import { Popover } from "@budibase/bbui"
import { getContext } from "svelte"
import { Popover, clickOutside } from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
export let rand
export let invertX
export let open
export let anchor
const { rowHeight, scroll } = getContext("grid")
let initialOffsetX = 0
let initialOffsetY = 0
$: updateInitialOffsets(open)
$: offsetX = initialOffsetX - $scroll.left
$: offsetY = initialOffsetY - ($scroll.top % $rowHeight)
$: style = `transform: translateX(${offsetX}px) translateY(${offsetY}px);`
$: markup = `<style>.grid-popover-container .spectrum-Popover { ${style} }</style>`
const updateInitialOffsets = open => {
if (!open) {
return
}
initialOffsetX = $scroll.left
initialOffsetY = $scroll.top % $rowHeight
}
const dispatch = createEventDispatcher()
</script>
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html markup}
<Popover
bind:open
{anchor}
align={invertX ? "right" : "left"}
portalTarget="#grid-{rand} .grid-popover-container"
offset={0}
offset={1}
>
<slot />
<div use:clickOutside={() => dispatch("close")}>
<slot />
</div>
</Popover>
<style>
:global(.grid-popover-container .spectrum-Popover) {
background: var(--grid-background-alt);
border: var(--cell-border);
}
</style>

View file

@ -17,6 +17,7 @@
height,
isDragging,
menu,
focusedCellAPI,
} = getContext("grid")
// State for dragging bars
@ -47,10 +48,11 @@
$: barLeft = ScrollBarSize + availWidth * ($scrollLeft / $maxScrollLeft)
// Helper to close the context menu if it's open
const closeMenu = () => {
const closePopovers = () => {
if ($menu.visible) {
menu.actions.close()
}
$focusedCellAPI?.blur()
}
const getLocation = e => {
@ -70,7 +72,7 @@
document.addEventListener("mouseup", stopVDragging)
document.addEventListener("touchend", stopVDragging)
isDraggingV = true
closeMenu()
closePopovers()
}
const moveVDragging = domDebounce(e => {
const delta = getLocation(e).y - initialMouse
@ -99,7 +101,7 @@
document.addEventListener("mouseup", stopHDragging)
document.addEventListener("touchend", stopHDragging)
isDraggingH = true
closeMenu()
closePopovers()
}
const moveHDragging = domDebounce(e => {
const delta = getLocation(e).x - initialMouse
@ -127,7 +129,6 @@
on:mousedown={startVDragging}
on:touchstart={startVDragging}
class:dragging={isDraggingV}
data-ignore-click-outside="true"
/>
{/if}
{#if $showHScrollbar}
@ -138,7 +139,6 @@
on:mousedown={startHDragging}
on:touchstart={startHDragging}
class:dragging={isDraggingH}
data-ignore-click-outside="true"
/>
{/if}

View file

@ -87,7 +87,7 @@ export const createActions = context => {
// Check if we need to start auto-scrolling
const $reorder = get(reorder)
const proximityCutoff = 140
const speedFactor = 8
const speedFactor = 16
const rightProximity = Math.max(0, $reorder.gridLeft + $reorder.width - x)
const leftProximity = Math.max(0, x - $reorder.gridLeft)
if (rightProximity < proximityCutoff) {