Break out spreadsheet body into its own component

This commit is contained in:
Andrew Kingston 2023-02-23 08:43:37 +00:00
parent c834a236b7
commit 0060025cca
3 changed files with 72 additions and 59 deletions

View File

@ -13,14 +13,15 @@
import { createResizeStore } from "./stores/resize" import { createResizeStore } from "./stores/resize"
import ReorderPlaceholder from "./ReorderPlaceholder.svelte" import ReorderPlaceholder from "./ReorderPlaceholder.svelte"
import ResizeSlider from "./ResizeSlider.svelte" import ResizeSlider from "./ResizeSlider.svelte"
import Header from "./Header.svelte" import SpreadsheetHeader from "./SpreadsheetHeader.svelte"
import SpreadsheetBody from "./SpreadsheetBody.svelte"
export let table export let table
export let filter export let filter
export let sortColumn export let sortColumn
export let sortOrder export let sortOrder
const { styleable, API, confirmationStore } = getContext("sdk") const { styleable, API } = getContext("sdk")
const component = getContext("component") const component = getContext("component")
// Sheet constants // Sheet constants
@ -63,7 +64,6 @@
spreadsheetAPI, spreadsheetAPI,
}) })
let horizontallyScrolled = false
let changeCache = {} let changeCache = {}
let newRows = [] let newRows = []
@ -77,7 +77,6 @@
limit, limit,
}) })
$: generateColumns($fetch) $: generateColumns($fetch)
$: gridStyles = getGridStyles($columns)
$: rowCount = $rows.length $: rowCount = $rows.length
$: selectedRowCount = Object.values($selectedRows).filter(x => !!x).length $: selectedRowCount = Object.values($selectedRows).filter(x => !!x).length
$: updateSortedRows($fetch.rows, newRows) $: updateSortedRows($fetch.rows, newRows)
@ -113,21 +112,6 @@
} }
} }
const getGridStyles = columns => {
const widths = columns?.map(x => x.width)
if (!widths?.length) {
return "--grid: 1fr;"
}
return `--grid: 40px ${widths.map(x => `${x}px`).join(" ")} 180px;`
}
const handleScroll = e => {
const nextHorizontallyScrolled = e.target.scrollLeft > 0
if (nextHorizontallyScrolled !== horizontallyScrolled) {
horizontallyScrolled = nextHorizontallyScrolled
}
}
const getCellForField = field => { const getCellForField = field => {
const type = field.schema.type const type = field.schema.type
if (type === "options") { if (type === "options") {
@ -212,14 +196,8 @@
<div use:styleable={$component.styles}> <div use:styleable={$component.styles}>
<div class="wrapper" class:resize={$resize.columnIdx != null}> <div class="wrapper" class:resize={$resize.columnIdx != null}>
<Header /> <SpreadsheetHeader />
<div <SpreadsheetBody>
class="spreadsheet"
on:scroll={handleScroll}
style={gridStyles}
on:click|self={() => ($selectedCellId = null)}
id={`sheet-${rand}-body`}
>
<!-- Field headers --> <!-- Field headers -->
<div class="header cell label" on:click={selectAll}> <div class="header cell label" on:click={selectAll}>
<input <input
@ -231,7 +209,6 @@
<div <div
class="header cell" class="header cell"
class:sticky={fieldIdx === 0} class:sticky={fieldIdx === 0}
class:shadow={horizontallyScrolled}
class:reorder-source={$reorder.columnIdx === fieldIdx} class:reorder-source={$reorder.columnIdx === fieldIdx}
class:reorder-target={$reorder.swapColumnIdx === fieldIdx} class:reorder-target={$reorder.swapColumnIdx === fieldIdx}
on:mousedown={e => reorder.actions.startReordering(fieldIdx, e)} on:mousedown={e => reorder.actions.startReordering(fieldIdx, e)}
@ -284,7 +261,6 @@
class:sticky={fieldIdx === 0} class:sticky={fieldIdx === 0}
class:hovered={rowHovered} class:hovered={rowHovered}
class:selected={$selectedCellId === cellIdx} class:selected={$selectedCellId === cellIdx}
class:shadow={horizontallyScrolled}
class:reorder-source={$reorder.columnIdx === fieldIdx} class:reorder-source={$reorder.columnIdx === fieldIdx}
class:reorder-target={$reorder.swapColumnIdx === fieldIdx} class:reorder-target={$reorder.swapColumnIdx === fieldIdx}
on:focus on:focus
@ -323,7 +299,6 @@
<div <div
class="cell new" class="cell new"
class:sticky={fieldIdx === 0} class:sticky={fieldIdx === 0}
class:shadow={horizontallyScrolled}
class:hovered={$hoveredRowId === "new"} class:hovered={$hoveredRowId === "new"}
class:reorder-source={$reorder.columnIdx === fieldIdx} class:reorder-source={$reorder.columnIdx === fieldIdx}
class:reorder-target={$reorder.swapColumnIdx === fieldIdx} class:reorder-target={$reorder.swapColumnIdx === fieldIdx}
@ -340,7 +315,7 @@
<!-- Vertical spacer --> <!-- Vertical spacer -->
<div class="vertical-spacer" /> <div class="vertical-spacer" />
</div> </SpreadsheetBody>
<!-- Reorder placeholder --> <!-- Reorder placeholder -->
<ReorderPlaceholder /> <ReorderPlaceholder />
@ -368,21 +343,6 @@
.wrapper.resize *:hover { .wrapper.resize *:hover {
cursor: col-resize; cursor: col-resize;
} }
.spreadsheet {
display: grid;
grid-template-columns: var(--grid);
justify-content: flex-start;
align-items: stretch;
overflow: auto;
max-height: 600px;
position: relative;
cursor: default;
}
.vertical-spacer {
grid-column: 1/-1;
height: 180px;
}
.wrapper ::-webkit-scrollbar-track { .wrapper ::-webkit-scrollbar-track {
background: var(--cell-background); background: var(--cell-background);
} }
@ -425,10 +385,6 @@
.cell.new:hover { .cell.new:hover {
cursor: pointer; cursor: pointer;
} }
.cell.spacer {
background: none;
border-bottom: none;
}
/* Header cells */ /* Header cells */
.header { .header {
@ -460,16 +416,15 @@
.sticky.selected { .sticky.selected {
z-index: 3; z-index: 3;
} }
.sticky.shadow {
border-right-width: 1px; /* Spacer cells */
.spacer {
background: none;
border-bottom: none;
} }
.sticky.shadow:after { .vertical-spacer {
content: " "; grid-column: 1/-1;
position: absolute; height: 180px;
width: 10px;
left: 100%;
height: 100%;
background: linear-gradient(to right, rgba(0, 0, 0, 0.08), transparent);
} }
/* Reorder styles */ /* Reorder styles */

View File

@ -0,0 +1,58 @@
<script>
import { getContext } from "svelte"
const { columns, selectedCellId, rand } = getContext("spreadsheet")
let horizontallyScrolled = false
$: gridStyles = getGridStyles($columns)
const getGridStyles = columns => {
const widths = columns?.map(x => x.width)
if (!widths?.length) {
return "--grid: 1fr;"
}
return `--grid: 40px ${widths.map(x => `${x}px`).join(" ")} 180px;`
}
const handleScroll = e => {
horizontallyScrolled = e.target.scrollLeft > 0
}
</script>
<div
class="spreadsheet"
class:horizontally-scrolled={horizontallyScrolled}
on:scroll={handleScroll}
style={gridStyles}
on:click|self={() => ($selectedCellId = null)}
id={`sheet-${rand}-body`}
>
<slot />
</div>
<style>
.spreadsheet {
display: grid;
grid-template-columns: var(--grid);
justify-content: flex-start;
align-items: stretch;
overflow: auto;
max-height: 600px;
position: relative;
cursor: default;
}
/* 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>