More upgrades to grids to support new popovers and use popovers for options cells
This commit is contained in:
parent
795991438f
commit
443be4cdab
|
@ -101,7 +101,7 @@
|
|||
|
||||
<style>
|
||||
.wrapper {
|
||||
flex: 1 1 auto;
|
||||
flex: 0 0 400px;
|
||||
margin: -28px -40px -40px -40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
@ -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}>
|
||||
<GridPopover open={isOpen} {anchor} {invertX} {rand} on:close={close}>
|
||||
<CoreDatePickerPopoverContents
|
||||
value={parsedValue}
|
||||
useKeyboardShortcuts={false}
|
||||
on:change={e => (value = e.detail)}
|
||||
{enableTime}
|
||||
{timeOnly}
|
||||
{ignoreTimezones}
|
||||
useKeyboardShortcuts={false}
|
||||
/>
|
||||
</div>
|
||||
</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>
|
||||
|
|
|
@ -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}
|
||||
</div>
|
||||
|
||||
{#if isOpen}
|
||||
<div
|
||||
class="options"
|
||||
class:invertX
|
||||
class:invertY
|
||||
on:wheel={e => e.stopPropagation()}
|
||||
use:clickOutside={close}
|
||||
>
|
||||
<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}">
|
||||
<span>
|
||||
{option}
|
||||
</span>
|
||||
</div>
|
||||
{#if values.includes(option)}
|
||||
<Icon name="Checkmark" color="var(--accent-color)" />
|
||||
|
@ -140,8 +144,8 @@
|
|||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</GridPopover>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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}
|
||||
>
|
||||
<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>
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue