1
0
Fork 0
mirror of synced 2024-09-10 22:46:09 +12:00

Fix some scroll issues and add shadow to sticky column

This commit is contained in:
Andrew Kingston 2023-03-01 18:32:23 +00:00
parent ca96a61cde
commit 15dffb0f40
9 changed files with 117 additions and 92 deletions

View file

@ -5,8 +5,7 @@
import { getIconForField } from "./utils"
import SheetScrollWrapper from "./SheetScrollWrapper.svelte"
const { visibleColumns, reorder, selectedRows, rows } =
getContext("spreadsheet")
const { visibleColumns, reorder } = getContext("spreadsheet")
</script>
<div>

View file

@ -1,11 +1,12 @@
<script>
import SheetCell from "./SheetCell.svelte"
import { Icon } from "@budibase/bbui"
import { getContext } from "svelte"
const { visibleColumns, cellHeight, rows, selectedCellId, reorder } =
const { visibleColumns, hoveredRowId, rows, selectedCellId, reorder } =
getContext("spreadsheet")
$: rowHovered = $hoveredRowId === "new"
const addRow = async field => {
const newRow = await rows.actions.addRow()
if (newRow) {
@ -14,9 +15,10 @@
}
</script>
<div class="row new">
<div class="row" on:mouseover={() => ($hoveredRowId = "new")}>
{#each $visibleColumns as column}
<SheetCell
{rowHovered}
on:click={() => addRow(column)}
width={column.width}
left={column.left}
@ -30,8 +32,7 @@
.row {
display: flex;
}
:global(.sheet:not(.is-resizing):not(.is-reordering) .row:hover .cell) {
background: var(--cell-background-hover);
.row:hover :global(.cell) {
cursor: pointer;
}
</style>

View file

@ -31,6 +31,7 @@
const tableIdStore = writable()
const selectedCellId = writable()
const selectedRows = writable({})
const hoveredRowId = writable()
const scroll = writable({
left: 0,
top: 0,
@ -51,6 +52,7 @@
cellHeight,
bounds,
scroll,
hoveredRowId,
tableId: tableIdStore,
}
const { rows, schema } = createRowsStore(context)
@ -114,7 +116,7 @@
display: flex;
flex-direction: row;
justify-items: flex-start;
align-items: stretch;
align-items: flex-start;
overflow: hidden;
height: 0;
position: relative;
@ -124,5 +126,6 @@
overflow: hidden;
display: flex;
flex-direction: column;
align-self: stretch;
}
</style>

View file

@ -1,18 +1,11 @@
<script>
import { getContext, onMount } from "svelte"
import { Utils } from "../../utils"
import SheetScrollWrapper from "./SheetScrollWrapper.svelte"
const { columns, selectedCellId, cellHeight, rows, bounds, scroll } =
getContext("spreadsheet")
const padding = 180
const { selectedCellId, hoveredRowId, bounds } = getContext("spreadsheet")
let ref
$: scrollLeft = $scroll.left
$: scrollTop = $scroll.top
onMount(() => {
// Observe and record the height of the body
const observer = new ResizeObserver(() => {
@ -28,8 +21,8 @@
<div
bind:this={ref}
class="sheet-body"
class:horizontally-scrolled={scrollLeft > 0}
on:click|self={() => ($selectedCellId = null)}
on:mouseleave={() => ($hoveredRowId = null)}
>
<SheetScrollWrapper>
<slot />
@ -44,20 +37,4 @@
overflow: hidden;
flex: 1 1 auto;
}
.sheet-body::-webkit-scrollbar-track {
background: transparent;
}
/* Add shadow to sticky cells when horizontally scrolled */
.horizontally-scrolled :global(.cell.sticky) {
border-right-width: 1px;
}
.horizontally-scrolled :global(.cell.sticky:after) {
content: " ";
position: absolute;
width: 10px;
left: 100%;
height: 100%;
background: linear-gradient(to right, rgba(0, 0, 0, 0.08), transparent);
}
</style>

View file

@ -1,9 +1,8 @@
<svelte:options immutable={true} />
<script>
export let header = false
export let label = false
export let rowSelected = false
export let rowHovered = false
export let sticky = false
export let selected = false
export let reorderSource = false
@ -16,12 +15,12 @@
class:header
class:label
class:row-selected={rowSelected}
class:row-hovered={rowHovered}
class:sticky
class:selected
class:reorder-source={reorderSource}
class:reorder-target={reorderTarget}
on:focus
on:mouseenter
on:click
on:mousedown
style="--width:{width}px;"
@ -64,6 +63,9 @@
.cell.row-selected {
background-color: var(--spectrum-global-color-gray-100);
}
.cell.row-hovered {
background: var(--cell-background-hover);
}
/* Header cells */
.cell.header {

View file

@ -7,17 +7,25 @@
export let row
const { selectedCellId, reorder, selectedRows, rows, visibleColumns } =
getContext("spreadsheet")
const {
selectedCellId,
reorder,
selectedRows,
rows,
visibleColumns,
hoveredRowId,
} = getContext("spreadsheet")
$: rowSelected = !!$selectedRows[row._id]
$: rowHovered = $hoveredRowId === row._id
</script>
<div class="row">
<div class="row" on:mouseover={() => ($hoveredRowId = row._id)}>
{#each $visibleColumns as column (column.name)}
{@const cellIdx = `${row._id}-${column.name}`}
<SheetCell
{rowSelected}
{rowHovered}
selected={$selectedCellId === cellIdx}
reorderSource={$reorder.columnIdx === column.idx}
reorderTarget={$reorder.swapColumnIdx === column.idx}
@ -41,7 +49,4 @@
.row {
display: flex;
}
:global(.sheet:not(.is-resizing):not(.is-reordering) .row:hover .cell) {
background: var(--cell-background-hover);
}
</style>

View file

@ -69,11 +69,11 @@
const offset = deltaY * step
let newScrollTop = scrollTop
newScrollTop += offset
newScrollTop = Math.max(0, newScrollTop)
newScrollTop = Math.min(
newScrollTop,
($rows.length + 1) * cellHeight - $bounds.height
)
newScrollTop = Math.max(0, newScrollTop)
scroll.update(state => ({
...state,
top: newScrollTop,
@ -91,6 +91,8 @@
<style>
.scroll-wrapper {
min-width: 100%;
min-height: 100%;
background: var(--background-alt);
transform: translate3d(var(--offset-x), var(--offset-y), 0);
overflow: hidden;

View file

@ -6,9 +6,17 @@
import { getCellComponent } from "./utils"
import SheetScrollWrapper from "./SheetScrollWrapper.svelte"
const { rows, selectedRows, stickyColumn, visibleRows, selectedCellId } =
getContext("spreadsheet")
const {
rows,
selectedRows,
stickyColumn,
visibleRows,
selectedCellId,
hoveredRowId,
scroll,
} = getContext("spreadsheet")
$: scrollLeft = $scroll.left
$: rowCount = $rows.length
$: selectedRowCount = Object.values($selectedRows).filter(x => !!x).length
$: width = 40 + $stickyColumn?.width || 0
@ -41,7 +49,11 @@
}
</script>
<div class="sticky-column" style="--width:{width}px;">
<div
class="sticky-column"
style="--width:{width}px;"
class:scrolled={scrollLeft > 0}
>
<div class="row">
<!-- Field headers -->
<SheetCell header label on:click={selectAll} width="40" left="0">
@ -67,70 +79,96 @@
{/if}
</div>
<SheetScrollWrapper scrollHorizontally={false}>
{#each $visibleRows as row}
{@const rowSelected = !!$selectedRows[row._id]}
<div class="row">
<div on:mouseleave={() => ($hoveredRowId = null)}>
<SheetScrollWrapper scrollHorizontally={false}>
{#each $visibleRows as row}
{@const rowSelected = !!$selectedRows[row._id]}
{@const rowHovered = $hoveredRowId === row._id}
<div class="row" on:mouseenter={() => ($hoveredRowId = row._id)}>
<SheetCell
label
{rowSelected}
{rowHovered}
on:click={() => selectRow(row._id)}
width="40"
>
<div class="checkbox" class:visible={rowSelected || rowHovered}>
<Checkbox value={rowSelected} />
</div>
<div class="number" class:visible={!(rowSelected || rowHovered)}>
{row.__idx + 1}
</div>
</SheetCell>
{#if $stickyColumn}
{@const cellIdx = `${row._id}-${$stickyColumn.name}`}
<SheetCell
{rowSelected}
{rowHovered}
sticky
selected={$selectedCellId === cellIdx}
on:click={() => ($selectedCellId = cellIdx)}
width={$stickyColumn.width}
left="40"
>
<svelte:component
this={getCellComponent($stickyColumn)}
value={row[$stickyColumn.name]}
schema={$stickyColumn.schema}
selected={$selectedCellId === cellIdx}
onChange={val =>
rows.actions.updateRow(row._id, $stickyColumn, val)}
readonly={$stickyColumn.schema.autocolumn}
/>
</SheetCell>
{/if}
</div>
{/each}
<div class="row new" on:mouseover={() => ($hoveredRowId = "new")}>
<SheetCell
rowHovered={$hoveredRowId === "new"}
label
{rowSelected}
on:click={() => selectRow(row._id)}
on:click={addRow}
width="40"
>
<div class="checkbox" class:visible={rowSelected}>
<Checkbox value={rowSelected} />
</div>
<div class="number" class:visible={!rowSelected}>
{row.__idx + 1}
</div>
<Icon hoverable name="Add" size="S" />
</SheetCell>
{#if $stickyColumn}
{@const cellIdx = `${row._id}-${$stickyColumn.name}`}
<SheetCell
{rowSelected}
sticky
selected={$selectedCellId === cellIdx}
on:click={() => ($selectedCellId = cellIdx)}
on:click={addRow}
width={$stickyColumn.width}
left="40"
>
<svelte:component
this={getCellComponent($stickyColumn)}
value={row[$stickyColumn.name]}
schema={$stickyColumn.schema}
selected={$selectedCellId === cellIdx}
onChange={val =>
rows.actions.updateRow(row._id, $stickyColumn, val)}
readonly={$stickyColumn.schema.autocolumn}
/>
</SheetCell>
rowHovered={$hoveredRowId === "new"}
/>
{/if}
</div>
{/each}
<div class="row">
<SheetCell label on:click={addRow} width="40">
<Icon hoverable name="Add" size="S" />
</SheetCell>
{#if $stickyColumn}
<SheetCell on:click={addRow} width={$stickyColumn.width} left="40" />
{/if}
</div>
</SheetScrollWrapper>
</SheetScrollWrapper>
</div>
</div>
<style>
.sticky-column {
flex: 0 0 var(--width);
z-index: 20;
overflow: visible;
border-right: 1px solid var(--spectrum-global-color-gray-200);
}
.sticky-column.scrolled {
box-shadow: 1px -4px 8px rgba(0, 0, 0, 0.1);
}
.sticky-column :global(.cell) {
border-right-width: 0;
}
.row {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: stretch;
}
.row.new:hover :global(.cell) {
cursor: pointer;
}
/* Styles for label cell */
.checkbox {
@ -140,12 +178,9 @@
display: none;
color: var(--spectrum-global-color-gray-500);
}
.row:hover .checkbox,
.checkbox.visible {
display: flex;
}
.checkbox.visible,
.number.visible {
display: block;
display: flex;
}
.row:hover .number {
display: none;

View file

@ -6,6 +6,7 @@ export const createColumnsStores = context => {
const columns = writable([])
const stickyColumn = writable(null)
// Merge new schema fields with existing schema in order to preserve widths
schema.subscribe($schema => {
const currentColumns = get(columns)
if (!$schema) {