Fix multiple issues with z-index, reordering and resizing
This commit is contained in:
parent
efca3eef4f
commit
b1f2fe326a
|
@ -1,5 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
import { get } from "svelte/store"
|
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
|
|
||||||
const { columns, rand, scroll, visibleColumns } = getContext("spreadsheet")
|
const { columns, rand, scroll, visibleColumns } = getContext("spreadsheet")
|
||||||
|
@ -12,8 +11,9 @@
|
||||||
let left = 0
|
let left = 0
|
||||||
let columnCount = 0
|
let columnCount = 0
|
||||||
|
|
||||||
|
$: cutoff = $scroll.left + 40 + $columns[0]?.width || 0
|
||||||
|
|
||||||
const startResizing = (idx, e) => {
|
const startResizing = (idx, e) => {
|
||||||
const $columns = get(columns)
|
|
||||||
// Prevent propagation to stop reordering triggering
|
// Prevent propagation to stop reordering triggering
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|
||||||
|
@ -60,23 +60,25 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#each $visibleColumns as col}
|
{#each $visibleColumns as col}
|
||||||
<div
|
{#if col.idx === 0 || col.left + col.width > cutoff}
|
||||||
class="resize-slider"
|
<div
|
||||||
class:visible={columnIdx === col.idx}
|
class="resize-slider"
|
||||||
on:mousedown={e => startResizing(col.idx, e)}
|
class:visible={columnIdx === col.idx}
|
||||||
style="--left:{col.left +
|
on:mousedown={e => startResizing(col.idx, e)}
|
||||||
col.width -
|
style="--left:{col.left +
|
||||||
(col.idx === 0 ? 0 : $scroll.left)}px;"
|
col.width -
|
||||||
>
|
(col.idx === 0 ? 0 : $scroll.left)}px;"
|
||||||
<div class="resize-indicator" />
|
>
|
||||||
</div>
|
<div class="resize-indicator" />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.resize-slider {
|
.resize-slider {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: var(--controls-height);
|
top: var(--controls-height);
|
||||||
z-index: 6;
|
z-index: 10;
|
||||||
height: var(--cell-height);
|
height: var(--cell-height);
|
||||||
left: var(--left);
|
left: var(--left);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
|
@ -21,13 +21,12 @@
|
||||||
// Sheet constants
|
// Sheet constants
|
||||||
const cellHeight = 36
|
const cellHeight = 36
|
||||||
const limit = 100
|
const limit = 100
|
||||||
const defaultWidth = 160
|
const defaultWidth = 200
|
||||||
const rand = Math.random()
|
const rand = Math.random()
|
||||||
|
|
||||||
// State stores
|
// State stores
|
||||||
const rows = writable([])
|
const rows = writable([])
|
||||||
const columns = writable([])
|
const columns = writable([])
|
||||||
const hoveredRowId = writable(null)
|
|
||||||
const selectedCellId = writable(null)
|
const selectedCellId = writable(null)
|
||||||
const selectedRows = writable({})
|
const selectedRows = writable({})
|
||||||
const changeCache = writable({})
|
const changeCache = writable({})
|
||||||
|
@ -44,12 +43,11 @@
|
||||||
})
|
})
|
||||||
|
|
||||||
// Build up spreadsheet context and additional stores
|
// Build up spreadsheet context and additional stores
|
||||||
const context = {
|
let context = {
|
||||||
API,
|
API,
|
||||||
rand,
|
rand,
|
||||||
rows,
|
rows,
|
||||||
columns,
|
columns,
|
||||||
hoveredRowId,
|
|
||||||
selectedCellId,
|
selectedCellId,
|
||||||
selectedRows,
|
selectedRows,
|
||||||
tableId,
|
tableId,
|
||||||
|
@ -59,8 +57,9 @@
|
||||||
bounds,
|
bounds,
|
||||||
scroll,
|
scroll,
|
||||||
}
|
}
|
||||||
const { reorder, reorderPlaceholder } = createReorderStores(context)
|
|
||||||
const { visibleRows, visibleColumns } = createViewportStores(context)
|
const { visibleRows, visibleColumns } = createViewportStores(context)
|
||||||
|
context = { ...context, visibleRows, visibleColumns }
|
||||||
|
const { reorder } = createReorderStores(context)
|
||||||
|
|
||||||
$: query = LuceneUtils.buildLuceneQuery(filter)
|
$: query = LuceneUtils.buildLuceneQuery(filter)
|
||||||
$: fetch = createFetch(tableId)
|
$: fetch = createFetch(tableId)
|
||||||
|
@ -202,7 +201,6 @@
|
||||||
setContext("spreadsheet", {
|
setContext("spreadsheet", {
|
||||||
...context,
|
...context,
|
||||||
reorder,
|
reorder,
|
||||||
reorderPlaceholder,
|
|
||||||
visibleRows,
|
visibleRows,
|
||||||
visibleColumns,
|
visibleColumns,
|
||||||
spreadsheetAPI,
|
spreadsheetAPI,
|
||||||
|
@ -226,7 +224,9 @@
|
||||||
sticky={column.idx === 0}
|
sticky={column.idx === 0}
|
||||||
reorderSource={$reorder.columnIdx === column.idx}
|
reorderSource={$reorder.columnIdx === column.idx}
|
||||||
reorderTarget={$reorder.swapColumnIdx === column.idx}
|
reorderTarget={$reorder.swapColumnIdx === column.idx}
|
||||||
on:mousedown={e => reorder.actions.startReordering(column.idx, e)}
|
on:mousedown={column.idx === 123
|
||||||
|
? null
|
||||||
|
: e => reorder.actions.startReordering(column.idx, e)}
|
||||||
width={column.width}
|
width={column.width}
|
||||||
left={column.left}
|
left={column.left}
|
||||||
>
|
>
|
||||||
|
@ -249,24 +249,15 @@
|
||||||
|
|
||||||
<!-- New row placeholder -->
|
<!-- New row placeholder -->
|
||||||
<div class="row new" style="--top:{($rows.length + 1) * cellHeight}px;">
|
<div class="row new" style="--top:{($rows.length + 1) * cellHeight}px;">
|
||||||
<SpreadsheetCell
|
<SpreadsheetCell label on:click={addRow} width="40" left="0">
|
||||||
label
|
|
||||||
on:click={addRow}
|
|
||||||
on:mouseenter={() => ($hoveredRowId = "new")}
|
|
||||||
rowHovered={$hoveredRowId === "new"}
|
|
||||||
width="40"
|
|
||||||
left="0"
|
|
||||||
>
|
|
||||||
<Icon hoverable name="Add" size="S" />
|
<Icon hoverable name="Add" size="S" />
|
||||||
</SpreadsheetCell>
|
</SpreadsheetCell>
|
||||||
{#each $visibleColumns as column}
|
{#each $visibleColumns as column}
|
||||||
<SpreadsheetCell
|
<SpreadsheetCell
|
||||||
sticky={column.idx === 0}
|
sticky={column.idx === 0}
|
||||||
rowHovered={$hoveredRowId === "new"}
|
|
||||||
reorderSource={$reorder.columnIdx === column.idx}
|
reorderSource={$reorder.columnIdx === column.idx}
|
||||||
reorderTarget={$reorder.swapColumnIdx === column.idx}
|
reorderTarget={$reorder.swapColumnIdx === column.idx}
|
||||||
on:click={() => addRow(column)}
|
on:click={() => addRow(column)}
|
||||||
on:mouseenter={() => ($hoveredRowId = "new")}
|
|
||||||
width={column.width}
|
width={column.width}
|
||||||
left={column.left}
|
left={column.left}
|
||||||
/>
|
/>
|
||||||
|
@ -304,7 +295,7 @@
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: inherit;
|
width: inherit;
|
||||||
z-index: 4;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
.row.new {
|
.row.new {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -313,4 +304,7 @@
|
||||||
.row :global(> :last-child) {
|
.row :global(> :last-child) {
|
||||||
border-right-width: 1px;
|
border-right-width: 1px;
|
||||||
}
|
}
|
||||||
|
input[type="checkbox"] {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
export let header = false
|
export let header = false
|
||||||
export let label = false
|
export let label = false
|
||||||
export let spacer = false
|
|
||||||
export let rowHovered = false
|
|
||||||
export let rowSelected = false
|
export let rowSelected = false
|
||||||
export let sticky = false
|
export let sticky = false
|
||||||
export let selected = false
|
export let selected = false
|
||||||
|
@ -17,9 +15,7 @@
|
||||||
class="cell col-{column}"
|
class="cell col-{column}"
|
||||||
class:header
|
class:header
|
||||||
class:label
|
class:label
|
||||||
class:spacer
|
|
||||||
class:row-selected={rowSelected}
|
class:row-selected={rowSelected}
|
||||||
class:row-hovered={rowHovered}
|
|
||||||
class:sticky
|
class:sticky
|
||||||
class:selected
|
class:selected
|
||||||
class:reorder-source={reorderSource}
|
class:reorder-source={reorderSource}
|
||||||
|
@ -53,10 +49,7 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transition: border-color 130ms ease-out;
|
transition: border-color 130ms ease-out;
|
||||||
width: var(--width);
|
width: var(--width);
|
||||||
transform: translateX(var(--left));
|
left: var(--left);
|
||||||
}
|
|
||||||
.cell.row-hovered {
|
|
||||||
background: var(--cell-background-hover);
|
|
||||||
}
|
}
|
||||||
.cell.selected {
|
.cell.selected {
|
||||||
box-shadow: inset 0 0 0 2px var(--spectrum-global-color-blue-400);
|
box-shadow: inset 0 0 0 2px var(--spectrum-global-color-blue-400);
|
||||||
|
@ -68,26 +61,18 @@
|
||||||
.cell:hover {
|
.cell:hover {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
.cell.row-selected:after {
|
.cell.row-selected {
|
||||||
pointer-events: none;
|
background-color: var(--spectrum-global-color-gray-100);
|
||||||
content: " ";
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
opacity: 0.2;
|
|
||||||
background-color: var(--spectrum-global-color-blue-600);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Header cells */
|
/* Header cells */
|
||||||
.cell.header {
|
.cell.header {
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
padding: 0 var(--cell-padding);
|
padding: 0 var(--cell-padding);
|
||||||
z-index: 3;
|
|
||||||
border-color: var(--spectrum-global-color-gray-200);
|
border-color: var(--spectrum-global-color-gray-200);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
gap: calc(2 * var(--cell-spacing));
|
gap: calc(2 * var(--cell-spacing));
|
||||||
|
z-index: 10;
|
||||||
}
|
}
|
||||||
.cell.header :global(span) {
|
.cell.header :global(span) {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
@ -96,20 +81,24 @@
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
.cell.header:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.cell.header.sticky,
|
||||||
|
.cell.header.label {
|
||||||
|
z-index: 11;
|
||||||
|
}
|
||||||
|
|
||||||
/* Sticky styles */
|
/* Sticky styles */
|
||||||
.cell.sticky {
|
.cell.sticky {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
z-index: 2;
|
|
||||||
border-left-width: 0;
|
border-left-width: 0;
|
||||||
transform: none;
|
transform: none;
|
||||||
left: 40px;
|
left: 40px;
|
||||||
|
z-index: 5;
|
||||||
}
|
}
|
||||||
.cell.sticky.selected {
|
.cell.selected.sticky {
|
||||||
z-index: 3;
|
z-index: 6;
|
||||||
}
|
|
||||||
.cell.header.sticky {
|
|
||||||
z-index: 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reorder styles */
|
/* Reorder styles */
|
||||||
|
@ -119,43 +108,22 @@
|
||||||
.cell.header.reorder-source {
|
.cell.header.reorder-source {
|
||||||
background: var(--spectrum-global-color-gray-200);
|
background: var(--spectrum-global-color-gray-200);
|
||||||
}
|
}
|
||||||
.cell.reorder-target {
|
.cell.reorder-target:after {
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
.cell.reorder-target:before {
|
|
||||||
content: " ";
|
content: " ";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -2px;
|
right: 0;
|
||||||
background: var(--spectrum-global-color-blue-400);
|
background: var(--spectrum-global-color-blue-400);
|
||||||
width: 2px;
|
width: 2px;
|
||||||
z-index: 100;
|
|
||||||
height: calc(var(--cell-height) + 1px);
|
height: calc(var(--cell-height) + 1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Label cells */
|
/* Label cells */
|
||||||
.cell.label {
|
.cell.label {
|
||||||
|
padding: var(--cell-padding);
|
||||||
width: 40px;
|
width: 40px;
|
||||||
padding: 0 12px;
|
|
||||||
border-left-width: 0;
|
border-left-width: 0;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 2;
|
z-index: 5;
|
||||||
}
|
|
||||||
.cell.label.header {
|
|
||||||
z-index: 4;
|
|
||||||
}
|
|
||||||
.cell.label :global(span) {
|
|
||||||
min-width: 14px;
|
|
||||||
text-align: center;
|
|
||||||
color: var(--spectrum-global-color-gray-500);
|
|
||||||
}
|
|
||||||
.cell.label :global(input[type="checkbox"]) {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Spacer cells */
|
|
||||||
.cell.spacer {
|
|
||||||
background: none;
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
const {
|
const {
|
||||||
selectedCellId,
|
selectedCellId,
|
||||||
reorder,
|
reorder,
|
||||||
hoveredRowId,
|
|
||||||
selectedRows,
|
selectedRows,
|
||||||
changeCache,
|
changeCache,
|
||||||
spreadsheetAPI,
|
spreadsheetAPI,
|
||||||
|
@ -22,9 +21,7 @@
|
||||||
} = getContext("spreadsheet")
|
} = getContext("spreadsheet")
|
||||||
|
|
||||||
$: rowSelected = !!$selectedRows[row._id]
|
$: rowSelected = !!$selectedRows[row._id]
|
||||||
$: rowHovered = $hoveredRowId === row._id
|
|
||||||
$: data = { ...row, ...$changeCache[row._id] }
|
$: data = { ...row, ...$changeCache[row._id] }
|
||||||
$: containsSelectedCell = $selectedCellId?.split("-")[0] === row._id
|
|
||||||
|
|
||||||
const getCellForField = field => {
|
const getCellForField = field => {
|
||||||
const type = field.schema.type
|
const type = field.schema.type
|
||||||
|
@ -50,36 +47,23 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div class="row" style="--top:{(row.__idx + 1) * cellHeight}px;">
|
||||||
class="row"
|
<SpreadsheetCell label {rowSelected} on:click={() => selectRow(row._id)}>
|
||||||
style="--top:{(row.__idx + 1) * cellHeight}px;"
|
<div class="checkbox" class:visible={rowSelected}>
|
||||||
class:contains-selected-cell={containsSelectedCell}
|
|
||||||
>
|
|
||||||
<SpreadsheetCell
|
|
||||||
label
|
|
||||||
{rowSelected}
|
|
||||||
{rowHovered}
|
|
||||||
on:mouseenter={() => ($hoveredRowId = row._id)}
|
|
||||||
on:click={() => selectRow(row._id)}
|
|
||||||
>
|
|
||||||
{#if rowSelected || rowHovered}
|
|
||||||
<input type="checkbox" checked={rowSelected} />
|
<input type="checkbox" checked={rowSelected} />
|
||||||
{:else}
|
</div>
|
||||||
<span>
|
<div class="number" class:visible={!rowSelected}>
|
||||||
{row.__idx + 1}
|
{row.__idx + 1}
|
||||||
</span>
|
</div>
|
||||||
{/if}
|
|
||||||
</SpreadsheetCell>
|
</SpreadsheetCell>
|
||||||
{#each $visibleColumns as column (column.name)}
|
{#each $visibleColumns as column (column.name)}
|
||||||
{@const cellIdx = `${row._id}-${column.name}`}
|
{@const cellIdx = `${row._id}-${column.name}`}
|
||||||
<SpreadsheetCell
|
<SpreadsheetCell
|
||||||
{rowSelected}
|
{rowSelected}
|
||||||
{rowHovered}
|
|
||||||
sticky={column.idx === 0}
|
sticky={column.idx === 0}
|
||||||
selected={$selectedCellId === cellIdx}
|
selected={$selectedCellId === cellIdx}
|
||||||
reorderSource={$reorder.columnIdx === column.idx}
|
reorderSource={$reorder.columnIdx === column.idx}
|
||||||
reorderTarget={$reorder.swapColumnIdx === column.idx}
|
reorderTarget={$reorder.swapColumnIdx === column.idx}
|
||||||
on:mouseenter={() => ($hoveredRowId = row._id)}
|
|
||||||
on:click={() => ($selectedCellId = cellIdx)}
|
on:click={() => ($selectedCellId = cellIdx)}
|
||||||
width={column.width}
|
width={column.width}
|
||||||
left={column.left}
|
left={column.left}
|
||||||
|
@ -101,14 +85,36 @@
|
||||||
.row {
|
.row {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: var(--top);
|
||||||
transform: translateY(var(--top));
|
|
||||||
width: inherit;
|
width: inherit;
|
||||||
}
|
}
|
||||||
.row.contains-selected-cell {
|
.row:hover :global(.cell) {
|
||||||
z-index: 1;
|
background: var(--cell-background-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Styles for label cell */
|
||||||
|
.checkbox {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
input[type="checkbox"] {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.number {
|
||||||
|
display: none;
|
||||||
|
min-width: 14px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--spectrum-global-color-gray-500);
|
||||||
|
}
|
||||||
|
.row:hover .checkbox,
|
||||||
|
.checkbox.visible,
|
||||||
|
.number.visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.row:hover .number {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add right border to last cell */
|
||||||
.row :global(> :last-child) {
|
.row :global(> :last-child) {
|
||||||
border-right-width: 1px;
|
border-right-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,13 +151,6 @@
|
||||||
var(--cell-background) 40%
|
var(--cell-background) 40%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
:global(.cell.hovered) .arrow {
|
|
||||||
background: linear-gradient(
|
|
||||||
to right,
|
|
||||||
transparent 0%,
|
|
||||||
var(--cell-background-hover) 40%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
.options {
|
.options {
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -170,7 +163,6 @@
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
max-height: calc(6 * var(--cell-height) - 1px);
|
max-height: calc(6 * var(--cell-height) - 1px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
z-index: 1;
|
|
||||||
}
|
}
|
||||||
.option {
|
.option {
|
||||||
flex: 0 0 var(--cell-height);
|
flex: 0 0 var(--cell-height);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { get, writable } from "svelte/store"
|
import { get, writable } from "svelte/store"
|
||||||
|
|
||||||
export const createReorderStores = context => {
|
export const createReorderStores = context => {
|
||||||
const { columns, bounds, rows, scroll, rand } = context
|
const { columns, visibleColumns, rand, scroll, bounds } = context
|
||||||
const reorderInitialState = {
|
const reorderInitialState = {
|
||||||
columnIdx: null,
|
columnIdx: null,
|
||||||
swapColumnIdx: null,
|
swapColumnIdx: null,
|
||||||
|
@ -10,33 +10,14 @@ export const createReorderStores = context => {
|
||||||
}
|
}
|
||||||
const reorder = writable(reorderInitialState)
|
const reorder = writable(reorderInitialState)
|
||||||
|
|
||||||
// This is broken into its own store as it is rapidly updated, and we want to
|
|
||||||
// ensure good performance by avoiding updating other components which depend
|
|
||||||
// on other reordering state
|
|
||||||
const placeholderInitialState = {
|
|
||||||
x: null,
|
|
||||||
initialX: null,
|
|
||||||
width: null,
|
|
||||||
height: null,
|
|
||||||
}
|
|
||||||
const placeholder = writable(placeholderInitialState)
|
|
||||||
|
|
||||||
// Callback when dragging on a colum header and starting reordering
|
// Callback when dragging on a colum header and starting reordering
|
||||||
const startReordering = (columnIdx, e) => {
|
const startReordering = (columnIdx, e) => {
|
||||||
const $columns = get(columns)
|
const $columns = get(columns)
|
||||||
const $bounds = get(bounds)
|
const $bounds = get(bounds)
|
||||||
const $rows = get(rows)
|
|
||||||
const $scroll = get(scroll)
|
const $scroll = get(scroll)
|
||||||
|
|
||||||
// Generate new breakpoints for the current columns
|
// Generate new breakpoints for the current columns
|
||||||
let breakpoints = []
|
let breakpoints = $columns.map(col => col.left + col.width)
|
||||||
$columns.forEach((col, idx) => {
|
|
||||||
breakpoints.push(col.left)
|
|
||||||
if (idx === $columns.length - 1) {
|
|
||||||
breakpoints.push(col.left + col.width)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const self = $columns[columnIdx]
|
|
||||||
|
|
||||||
// Update state
|
// Update state
|
||||||
reorder.set({
|
reorder.set({
|
||||||
|
@ -44,15 +25,8 @@ export const createReorderStores = context => {
|
||||||
breakpoints,
|
breakpoints,
|
||||||
swapColumnIdx: null,
|
swapColumnIdx: null,
|
||||||
initialMouseX: e.clientX,
|
initialMouseX: e.clientX,
|
||||||
})
|
|
||||||
placeholder.set({
|
|
||||||
initialX: self.left,
|
|
||||||
x: self.left,
|
|
||||||
width: self.width,
|
|
||||||
height: ($rows.length + 2) * 32,
|
|
||||||
sheetLeft: $bounds.left,
|
|
||||||
maxX: $bounds.width - self.width,
|
|
||||||
scrollLeft: $scroll.left,
|
scrollLeft: $scroll.left,
|
||||||
|
sheetLeft: $bounds.left,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Add listeners to handle mouse movement
|
// Add listeners to handle mouse movement
|
||||||
|
@ -71,34 +45,18 @@ export const createReorderStores = context => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute new placeholder position
|
|
||||||
const $placeholder = get(placeholder)
|
|
||||||
let newX =
|
|
||||||
e.clientX -
|
|
||||||
$reorder.initialMouseX +
|
|
||||||
$placeholder.initialX -
|
|
||||||
$placeholder.scrollLeft
|
|
||||||
newX = Math.max(0, newX)
|
|
||||||
newX = Math.min($placeholder.maxX, newX)
|
|
||||||
|
|
||||||
// Compute the closest breakpoint to the current position
|
// Compute the closest breakpoint to the current position
|
||||||
let swapColumnIdx
|
let swapColumnIdx
|
||||||
let minDistance = Number.MAX_SAFE_INTEGER
|
let minDistance = Number.MAX_SAFE_INTEGER
|
||||||
|
const mouseX = e.clientX - $reorder.sheetLeft + $reorder.scrollLeft
|
||||||
$reorder.breakpoints.forEach((point, idx) => {
|
$reorder.breakpoints.forEach((point, idx) => {
|
||||||
const distance = Math.abs(
|
const distance = Math.abs(point - mouseX)
|
||||||
point - e.clientX + $placeholder.sheetLeft - $placeholder.scrollLeft
|
|
||||||
)
|
|
||||||
if (distance < minDistance) {
|
if (distance < minDistance) {
|
||||||
minDistance = distance
|
minDistance = distance
|
||||||
swapColumnIdx = idx
|
swapColumnIdx = idx
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Update state
|
|
||||||
placeholder.update(state => {
|
|
||||||
state.x = newX
|
|
||||||
return state
|
|
||||||
})
|
|
||||||
if (swapColumnIdx !== $reorder.swapColumnIdx) {
|
if (swapColumnIdx !== $reorder.swapColumnIdx) {
|
||||||
reorder.update(state => {
|
reorder.update(state => {
|
||||||
state.swapColumnIdx = swapColumnIdx
|
state.swapColumnIdx = swapColumnIdx
|
||||||
|
@ -111,6 +69,7 @@ export const createReorderStores = context => {
|
||||||
const stopReordering = () => {
|
const stopReordering = () => {
|
||||||
// Swap position of columns
|
// Swap position of columns
|
||||||
let { columnIdx, swapColumnIdx } = get(reorder)
|
let { columnIdx, swapColumnIdx } = get(reorder)
|
||||||
|
swapColumnIdx++
|
||||||
columns.update(state => {
|
columns.update(state => {
|
||||||
const removed = state.splice(columnIdx, 1)
|
const removed = state.splice(columnIdx, 1)
|
||||||
if (--swapColumnIdx < columnIdx) {
|
if (--swapColumnIdx < columnIdx) {
|
||||||
|
@ -131,7 +90,6 @@ export const createReorderStores = context => {
|
||||||
|
|
||||||
// Reset state
|
// Reset state
|
||||||
reorder.set(reorderInitialState)
|
reorder.set(reorderInitialState)
|
||||||
placeholder.set(placeholderInitialState)
|
|
||||||
|
|
||||||
// Remove event handlers
|
// Remove event handlers
|
||||||
document.removeEventListener("mousemove", onReorderMouseMove)
|
document.removeEventListener("mousemove", onReorderMouseMove)
|
||||||
|
@ -147,6 +105,5 @@ export const createReorderStores = context => {
|
||||||
stopReordering,
|
stopReordering,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
reorderPlaceholder: placeholder,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { writable, derived } from "svelte/store"
|
import { writable, derived } from "svelte/store"
|
||||||
|
import { Utils } from "../../../utils"
|
||||||
|
|
||||||
export const createViewportStores = context => {
|
export const createViewportStores = context => {
|
||||||
const { cellHeight, columns, rows, scroll, bounds } = context
|
const { cellHeight, columns, rows, scroll, bounds } = context
|
||||||
|
@ -16,15 +17,17 @@ export const createViewportStores = context => {
|
||||||
|
|
||||||
// Debounce scroll updates so we can slow down visible row computation
|
// Debounce scroll updates so we can slow down visible row computation
|
||||||
scroll.subscribe(({ left, top }) => {
|
scroll.subscribe(({ left, top }) => {
|
||||||
// Only update local state when big changes occur
|
window.requestAnimationFrame(() => {
|
||||||
if (Math.abs(top - scrollTop) > cellHeight * 2) {
|
// Only update local state when big changes occur
|
||||||
scrollTop = top
|
if (Math.abs(top - scrollTop) > cellHeight * 2) {
|
||||||
scrollTopStore.set(top)
|
scrollTop = top
|
||||||
}
|
scrollTopStore.set(top)
|
||||||
if (Math.abs(left - scrollLeft) > 100) {
|
}
|
||||||
scrollLeft = left
|
if (Math.abs(left - scrollLeft) > 100) {
|
||||||
scrollLeftStore.set(left)
|
scrollLeft = left
|
||||||
}
|
scrollLeftStore.set(left)
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Derive visible rows
|
// Derive visible rows
|
||||||
|
@ -32,8 +35,8 @@ export const createViewportStores = context => {
|
||||||
[rows, scrollTopStore, height],
|
[rows, scrollTopStore, height],
|
||||||
([$rows, $scrollTop, $height]) => {
|
([$rows, $scrollTop, $height]) => {
|
||||||
console.log("new rows")
|
console.log("new rows")
|
||||||
const maxRows = Math.ceil($height / cellHeight) + 8
|
const maxRows = Math.ceil($height / cellHeight) + 16
|
||||||
const firstRow = Math.max(0, Math.floor($scrollTop / cellHeight) - 4)
|
const firstRow = Math.max(0, Math.floor($scrollTop / cellHeight) - 8)
|
||||||
return $rows.slice(firstRow, firstRow + maxRows)
|
return $rows.slice(firstRow, firstRow + maxRows)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue