Break out spreadsheet body into its own component
This commit is contained in:
parent
c834a236b7
commit
0060025cca
|
@ -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 */
|
||||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue