Update grid button text and refactor gutter cell into own component
This commit is contained in:
parent
3bbf055401
commit
5155727b56
|
@ -16,7 +16,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ActionButton icon="LockClosed" quiet on:click={openDropdown} {disabled}>
|
<ActionButton icon="LockClosed" quiet on:click={openDropdown} {disabled}>
|
||||||
Manage access
|
Access
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
<Modal bind:this={modal}>
|
<Modal bind:this={modal}>
|
||||||
<ManageAccessModal
|
<ManageAccessModal
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ActionButton {disabled} icon="CollectionAdd" quiet on:click={modal.show}>
|
<ActionButton {disabled} icon="CollectionAdd" quiet on:click={modal.show}>
|
||||||
Create view
|
Add view
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
<Modal bind:this={modal}>
|
<Modal bind:this={modal}>
|
||||||
<CreateViewModal />
|
<CreateViewModal />
|
||||||
|
|
|
@ -27,6 +27,12 @@
|
||||||
// Get the error for this cell if the row is focused
|
// Get the error for this cell if the row is focused
|
||||||
$: error = getErrorStore(rowFocused, cellId)
|
$: error = getErrorStore(rowFocused, cellId)
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if ($error) {
|
||||||
|
console.log(cellId, $error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Determine if the cell is editable
|
// Determine if the cell is editable
|
||||||
$: readonly =
|
$: readonly =
|
||||||
column.schema.autocolumn ||
|
column.schema.autocolumn ||
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
<script>
|
||||||
|
import { GutterWidth } from "../lib/constants"
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
import { Checkbox, Icon } from "@budibase/bbui"
|
||||||
|
import GridCell from "./GridCell.svelte"
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
||||||
|
export let row
|
||||||
|
export let rowFocused
|
||||||
|
export let rowHovered
|
||||||
|
export let rowSelected
|
||||||
|
export let disableExpand = false
|
||||||
|
export let disableNumber = false
|
||||||
|
|
||||||
|
const { config, dispatch, selectedRows } = getContext("grid")
|
||||||
|
const svelteDispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
const select = () => {
|
||||||
|
svelteDispatch("select")
|
||||||
|
const id = row?._id
|
||||||
|
if (id) {
|
||||||
|
selectedRows.update(state => {
|
||||||
|
let newState = {
|
||||||
|
...state,
|
||||||
|
[id]: !state[id],
|
||||||
|
}
|
||||||
|
if (!newState[id]) {
|
||||||
|
delete newState[id]
|
||||||
|
}
|
||||||
|
return newState
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const expand = () => {
|
||||||
|
svelteDispatch("expand")
|
||||||
|
if (row) {
|
||||||
|
dispatch("edit-row", row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<GridCell
|
||||||
|
width={GutterWidth}
|
||||||
|
highlighted={rowFocused || rowHovered}
|
||||||
|
selected={rowSelected}
|
||||||
|
>
|
||||||
|
<div class="gutter">
|
||||||
|
{#if $$slots.default}
|
||||||
|
<slot />
|
||||||
|
{:else}
|
||||||
|
<div
|
||||||
|
on:click={select}
|
||||||
|
class="checkbox"
|
||||||
|
class:visible={$config.allowDeleteRows &&
|
||||||
|
(disableNumber || rowSelected || rowHovered || rowFocused)}
|
||||||
|
>
|
||||||
|
<Checkbox value={rowSelected} />
|
||||||
|
</div>
|
||||||
|
{#if !disableNumber}
|
||||||
|
<div
|
||||||
|
class="number"
|
||||||
|
class:visible={!$config.allowDeleteRows ||
|
||||||
|
!(rowSelected || rowHovered || rowFocused)}
|
||||||
|
>
|
||||||
|
{row.__idx + 1}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
{#if $config.allowExpandRows}
|
||||||
|
<div
|
||||||
|
class="expand"
|
||||||
|
class:visible={!disableExpand && (rowFocused || rowHovered)}
|
||||||
|
>
|
||||||
|
<Icon name="Maximize" hoverable size="S" on:click={expand} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</GridCell>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.gutter {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: grid;
|
||||||
|
align-items: center;
|
||||||
|
padding: var(--cell-padding);
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
gap: var(--cell-spacing);
|
||||||
|
}
|
||||||
|
.checkbox,
|
||||||
|
.number {
|
||||||
|
display: none;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.checkbox :global(.spectrum-Checkbox) {
|
||||||
|
min-height: 0;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
.checkbox :global(.spectrum-Checkbox-box) {
|
||||||
|
margin: 3px 0 0 0;
|
||||||
|
}
|
||||||
|
.number {
|
||||||
|
color: var(--spectrum-global-color-gray-500);
|
||||||
|
}
|
||||||
|
.checkbox.visible,
|
||||||
|
.number.visible {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.expand {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.expand.visible {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -12,5 +12,5 @@
|
||||||
on:click={() => dispatch("add-column")}
|
on:click={() => dispatch("add-column")}
|
||||||
disabled={!$config.allowAddColumns}
|
disabled={!$config.allowAddColumns}
|
||||||
>
|
>
|
||||||
Create column
|
Add column
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
|
|
|
@ -14,5 +14,5 @@
|
||||||
!$config.allowAddRows ||
|
!$config.allowAddRows ||
|
||||||
(!$columns.length && !$stickyColumn)}
|
(!$columns.length && !$stickyColumn)}
|
||||||
>
|
>
|
||||||
Create row
|
Add row
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
|
|
|
@ -52,13 +52,13 @@
|
||||||
|
|
||||||
<div bind:this={anchor}>
|
<div bind:this={anchor}>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
icon="ViewColumn"
|
icon="MoveLeftRight"
|
||||||
quiet
|
quiet
|
||||||
size="M"
|
size="M"
|
||||||
on:click={() => (open = !open)}
|
on:click={() => (open = !open)}
|
||||||
selected={open}
|
selected={open}
|
||||||
>
|
>
|
||||||
Column width
|
Width
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
selected={open || anyHidden}
|
selected={open || anyHidden}
|
||||||
disabled={!$columns.length}
|
disabled={!$columns.length}
|
||||||
>
|
>
|
||||||
Hide columns
|
Columns
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -36,13 +36,13 @@
|
||||||
|
|
||||||
<div bind:this={anchor}>
|
<div bind:this={anchor}>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
icon="LineHeight"
|
icon="MoveUpDown"
|
||||||
quiet
|
quiet
|
||||||
size="M"
|
size="M"
|
||||||
on:click={() => (open = !open)}
|
on:click={() => (open = !open)}
|
||||||
selected={open}
|
selected={open}
|
||||||
>
|
>
|
||||||
Row height
|
Height
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,25 @@
|
||||||
import { getContext, onMount } from "svelte"
|
import { getContext, onMount } from "svelte"
|
||||||
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
||||||
import GridRow from "./GridRow.svelte"
|
import GridRow from "./GridRow.svelte"
|
||||||
|
import { BlankRowID } from "../lib/constants"
|
||||||
|
|
||||||
const { bounds, renderedRows, rowVerticalInversionIndex } = getContext("grid")
|
const {
|
||||||
|
bounds,
|
||||||
|
renderedRows,
|
||||||
|
renderedColumns,
|
||||||
|
rowVerticalInversionIndex,
|
||||||
|
config,
|
||||||
|
hoveredRowId,
|
||||||
|
dispatch,
|
||||||
|
} = getContext("grid")
|
||||||
|
|
||||||
let body
|
let body
|
||||||
|
|
||||||
|
$: renderColumnsWidth = $renderedColumns.reduce(
|
||||||
|
(total, col) => (total += col.width),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
// Observe and record the height of the body
|
// Observe and record the height of the body
|
||||||
const observer = new ResizeObserver(() => {
|
const observer = new ResizeObserver(() => {
|
||||||
|
@ -24,6 +38,16 @@
|
||||||
{#each $renderedRows as row, idx}
|
{#each $renderedRows as row, idx}
|
||||||
<GridRow {row} {idx} invertY={idx >= $rowVerticalInversionIndex} />
|
<GridRow {row} {idx} invertY={idx >= $rowVerticalInversionIndex} />
|
||||||
{/each}
|
{/each}
|
||||||
|
{#if $config.allowAddRows}
|
||||||
|
<div
|
||||||
|
class="blank"
|
||||||
|
class:highlighted={$hoveredRowId === BlankRowID}
|
||||||
|
style="width:{renderColumnsWidth}px"
|
||||||
|
on:mouseenter={() => ($hoveredRowId = BlankRowID)}
|
||||||
|
on:mouseleave={() => ($hoveredRowId = null)}
|
||||||
|
on:click={() => dispatch("add-row-inline", true)}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</GridScrollWrapper>
|
</GridScrollWrapper>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -35,4 +59,15 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
.blank {
|
||||||
|
height: var(--row-height);
|
||||||
|
background: var(--cell-background);
|
||||||
|
border-bottom: var(--cell-border);
|
||||||
|
border-right: var(--cell-border);
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.blank.highlighted {
|
||||||
|
background: var(--cell-background-hover);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,228 +0,0 @@
|
||||||
<script>
|
|
||||||
import GridCell from "../cells/GridCell.svelte"
|
|
||||||
import { getContext, onMount, tick } from "svelte"
|
|
||||||
import { Icon, Button } from "@budibase/bbui"
|
|
||||||
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
|
||||||
import DataCell from "../cells/DataCell.svelte"
|
|
||||||
import { fade } from "svelte/transition"
|
|
||||||
import { GutterWidth } from "../lib/constants"
|
|
||||||
|
|
||||||
export let animate = false
|
|
||||||
export let rowIdx = 0
|
|
||||||
|
|
||||||
const {
|
|
||||||
hoveredRowId,
|
|
||||||
focusedCellId,
|
|
||||||
stickyColumn,
|
|
||||||
config,
|
|
||||||
dispatch,
|
|
||||||
rows,
|
|
||||||
focusedCellAPI,
|
|
||||||
tableId,
|
|
||||||
subscribe,
|
|
||||||
renderedColumns,
|
|
||||||
focusedRow,
|
|
||||||
reorder,
|
|
||||||
} = getContext("grid")
|
|
||||||
|
|
||||||
let isAdding = false
|
|
||||||
let newRow = { _id: `new${rowIdx}` }
|
|
||||||
let touched = false
|
|
||||||
|
|
||||||
$: rowId = `new${rowIdx}`
|
|
||||||
$: firstColumn = $stickyColumn || $renderedColumns[0]
|
|
||||||
$: width = GutterWidth + ($stickyColumn?.width || 0)
|
|
||||||
$: $tableId, (isAdding = false)
|
|
||||||
$: rowHovered = $hoveredRowId === rowId
|
|
||||||
$: rowFocused = $focusedRow?._id === rowId
|
|
||||||
$: reorderSource = $reorder.sourceColumn
|
|
||||||
|
|
||||||
const addRow = async () => {
|
|
||||||
// Create row
|
|
||||||
const savedRow = await rows.actions.addRow(newRow, rowIdx)
|
|
||||||
if (savedRow) {
|
|
||||||
// Select the first cell if possible
|
|
||||||
if (firstColumn) {
|
|
||||||
$focusedCellId = `${savedRow._id}-${firstColumn.name}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset state
|
|
||||||
isAdding = false
|
|
||||||
newRow = {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const cancel = () => {
|
|
||||||
newRow = { _id: rowId }
|
|
||||||
isAdding = false
|
|
||||||
$focusedCellId = null
|
|
||||||
$hoveredRowId = null
|
|
||||||
}
|
|
||||||
|
|
||||||
const startAdding = async () => {
|
|
||||||
isAdding = true
|
|
||||||
$hoveredRowId = rowId
|
|
||||||
if (firstColumn) {
|
|
||||||
$focusedCellId = `${rowId}-${firstColumn.name}`
|
|
||||||
|
|
||||||
// Also focus the cell if it is a text-like cell
|
|
||||||
if (["string", "number"].includes(firstColumn.schema.type)) {
|
|
||||||
await tick()
|
|
||||||
$focusedCellAPI?.focus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateValue = (rowId, columnName, val) => {
|
|
||||||
touched = true
|
|
||||||
newRow[columnName] = val
|
|
||||||
}
|
|
||||||
|
|
||||||
const addViaModal = () => {
|
|
||||||
isAdding = false
|
|
||||||
dispatch("add-row")
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleKeyPress = e => {
|
|
||||||
if (!isAdding) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (e.key === "Escape") {
|
|
||||||
cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(() => subscribe("add-row-inline", startAdding))
|
|
||||||
onMount(() => {
|
|
||||||
document.addEventListener("keydown", handleKeyPress)
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("keydown", handleKeyPress)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Only show new row functionality if we have any columns -->
|
|
||||||
<div
|
|
||||||
class="container"
|
|
||||||
transition:fade={{ duration: 130 }}
|
|
||||||
on:focus
|
|
||||||
on:mouseenter={() => ($hoveredRowId = rowId)}
|
|
||||||
on:mouseleave={() => ($hoveredRowId = null)}
|
|
||||||
>
|
|
||||||
<div class="sticky-column" style="flex: 0 0 {width}px">
|
|
||||||
<GridCell width={GutterWidth} highlighted={rowHovered || rowFocused}>
|
|
||||||
<div class="gutter">
|
|
||||||
<div class="number">
|
|
||||||
<Icon name="Add" />
|
|
||||||
</div>
|
|
||||||
{#if $config.allowExpandRows}
|
|
||||||
<div class="expand" class:visible={rowFocused || rowHovered}>
|
|
||||||
<Icon name="Maximize" size="S" hoverable on:click={addViaModal} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</GridCell>
|
|
||||||
{#if $stickyColumn}
|
|
||||||
{@const cellId = `${rowId}-${$stickyColumn.name}`}
|
|
||||||
<DataCell
|
|
||||||
{cellId}
|
|
||||||
{rowFocused}
|
|
||||||
highlighted={rowHovered || rowFocused}
|
|
||||||
column={$stickyColumn}
|
|
||||||
row={newRow}
|
|
||||||
focused={$focusedCellId === cellId}
|
|
||||||
width={$stickyColumn.width}
|
|
||||||
{updateValue}
|
|
||||||
rowIdx={0}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<GridScrollWrapper scrollHorizontally wheelInteractive>
|
|
||||||
<div class="row">
|
|
||||||
{#each $renderedColumns as column}
|
|
||||||
{@const cellId = `${rowId}-${column.name}`}
|
|
||||||
{#key cellId}
|
|
||||||
<DataCell
|
|
||||||
{cellId}
|
|
||||||
{column}
|
|
||||||
{updateValue}
|
|
||||||
{rowFocused}
|
|
||||||
highlighted={rowHovered ||
|
|
||||||
rowFocused ||
|
|
||||||
reorderSource === column.name}
|
|
||||||
row={newRow}
|
|
||||||
focused={$focusedCellId === cellId}
|
|
||||||
width={column.width}
|
|
||||||
rowIdx={0}
|
|
||||||
/>
|
|
||||||
{/key}
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</GridScrollWrapper>
|
|
||||||
{#if Object.keys(newRow || {}).length > 1}
|
|
||||||
<div class="buttons" in:fade={{ duration: 130 }}>
|
|
||||||
<Button size="M" cta on:click={addRow}>Save</Button>
|
|
||||||
<Button size="M" secondary newStyles on:click={cancel}>Cancel</Button>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Floating buttons which sit on top of the underlay but below the sticky column */
|
|
||||||
.buttons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 8px;
|
|
||||||
pointer-events: all;
|
|
||||||
z-index: 3;
|
|
||||||
position: absolute;
|
|
||||||
top: calc(var(--row-height) + 24px);
|
|
||||||
left: var(--gutter-width);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sticky column styles */
|
|
||||||
.sticky-column {
|
|
||||||
display: flex;
|
|
||||||
z-index: 4;
|
|
||||||
position: relative;
|
|
||||||
align-self: flex-start;
|
|
||||||
}
|
|
||||||
.sticky-column :global(.cell:not(:last-child)) {
|
|
||||||
border-right: none;
|
|
||||||
}
|
|
||||||
.gutter {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
display: grid;
|
|
||||||
align-items: center;
|
|
||||||
padding: var(--cell-padding);
|
|
||||||
grid-template-columns: 1fr auto;
|
|
||||||
gap: var(--cell-spacing);
|
|
||||||
}
|
|
||||||
.number {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
color: var(--spectrum-global-color-gray-500);
|
|
||||||
}
|
|
||||||
.expand {
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.expand.visible {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normal column styles */
|
|
||||||
.row {
|
|
||||||
width: 0;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,25 +0,0 @@
|
||||||
<script>
|
|
||||||
import NewRow from "./NewRow.svelte"
|
|
||||||
import { getContext } from "svelte"
|
|
||||||
import { DefaultRowHeight } from "../lib/constants"
|
|
||||||
|
|
||||||
const { rows, renderedRows, scrollTop, rowHeight } = getContext("grid")
|
|
||||||
|
|
||||||
$: top =
|
|
||||||
$renderedRows.length * $rowHeight -
|
|
||||||
($scrollTop % $rowHeight) +
|
|
||||||
DefaultRowHeight
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="new-row-bottom" style="top:{top}px;">
|
|
||||||
<NewRow rowIdx={$rows.length} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.new-row-bottom {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,11 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import { Checkbox, Icon } from "@budibase/bbui"
|
import { Icon } from "@budibase/bbui"
|
||||||
import GridCell from "../cells/GridCell.svelte"
|
import GridCell from "../cells/GridCell.svelte"
|
||||||
import DataCell from "../cells/DataCell.svelte"
|
import DataCell from "../cells/DataCell.svelte"
|
||||||
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
||||||
import HeaderCell from "../cells/HeaderCell.svelte"
|
import HeaderCell from "../cells/HeaderCell.svelte"
|
||||||
import { GutterWidth } from "../lib/constants"
|
import { GutterWidth, BlankRowID } from "../lib/constants"
|
||||||
|
import GutterCell from "../cells/GutterCell.svelte"
|
||||||
|
|
||||||
const {
|
const {
|
||||||
rows,
|
rows,
|
||||||
|
@ -17,8 +18,8 @@
|
||||||
config,
|
config,
|
||||||
selectedCellMap,
|
selectedCellMap,
|
||||||
focusedRow,
|
focusedRow,
|
||||||
dispatch,
|
|
||||||
scrollLeft,
|
scrollLeft,
|
||||||
|
dispatch,
|
||||||
} = getContext("grid")
|
} = getContext("grid")
|
||||||
|
|
||||||
$: rowCount = $rows.length
|
$: rowCount = $rows.length
|
||||||
|
@ -37,19 +38,6 @@
|
||||||
$selectedRows = allRows
|
$selectedRows = allRows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectRow = id => {
|
|
||||||
selectedRows.update(state => {
|
|
||||||
let newState = {
|
|
||||||
...state,
|
|
||||||
[id]: !state[id],
|
|
||||||
}
|
|
||||||
if (!newState[id]) {
|
|
||||||
delete newState[id]
|
|
||||||
}
|
|
||||||
return newState
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -58,26 +46,7 @@
|
||||||
class:scrolled={$scrollLeft > 0}
|
class:scrolled={$scrollLeft > 0}
|
||||||
>
|
>
|
||||||
<div class="header row">
|
<div class="header row">
|
||||||
<GridCell width={GutterWidth} defaultHeight center>
|
<GutterCell disableExpand disableNumber on:select={selectAll} />
|
||||||
<div class="gutter">
|
|
||||||
<div class="checkbox visible">
|
|
||||||
{#if $config.allowDeleteRows}
|
|
||||||
<div on:click={selectAll}>
|
|
||||||
<Checkbox
|
|
||||||
value={rowCount && selectedRowCount === rowCount}
|
|
||||||
disabled={!$renderedRows.length}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{#if $config.allowExpandRows}
|
|
||||||
<div class="expand">
|
|
||||||
<Icon name="Maximize" size="S" />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</GridCell>
|
|
||||||
|
|
||||||
{#if $stickyColumn}
|
{#if $stickyColumn}
|
||||||
<HeaderCell column={$stickyColumn} orderable={false} idx="sticky" />
|
<HeaderCell column={$stickyColumn} orderable={false} idx="sticky" />
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -95,41 +64,7 @@
|
||||||
on:mouseenter={() => ($hoveredRowId = row._id)}
|
on:mouseenter={() => ($hoveredRowId = row._id)}
|
||||||
on:mouseleave={() => ($hoveredRowId = null)}
|
on:mouseleave={() => ($hoveredRowId = null)}
|
||||||
>
|
>
|
||||||
<GridCell
|
<GutterCell {row} {rowFocused} {rowHovered} {rowSelected} />
|
||||||
width={GutterWidth}
|
|
||||||
highlighted={rowFocused || rowHovered}
|
|
||||||
selected={rowSelected}
|
|
||||||
>
|
|
||||||
<div class="gutter">
|
|
||||||
<div
|
|
||||||
on:click={() => selectRow(row._id)}
|
|
||||||
class="checkbox"
|
|
||||||
class:visible={$config.allowDeleteRows &&
|
|
||||||
(rowSelected || rowHovered || rowFocused)}
|
|
||||||
>
|
|
||||||
<Checkbox value={rowSelected} />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="number"
|
|
||||||
class:visible={!$config.allowDeleteRows ||
|
|
||||||
!(rowSelected || rowHovered || rowFocused)}
|
|
||||||
>
|
|
||||||
{row.__idx + 1}
|
|
||||||
</div>
|
|
||||||
{#if $config.allowExpandRows}
|
|
||||||
<div class="expand" class:visible={rowFocused || rowHovered}>
|
|
||||||
<Icon
|
|
||||||
name="Maximize"
|
|
||||||
hoverable
|
|
||||||
size="S"
|
|
||||||
on:click={() => {
|
|
||||||
dispatch("edit-row", row)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</GridCell>
|
|
||||||
{#if $stickyColumn}
|
{#if $stickyColumn}
|
||||||
<DataCell
|
<DataCell
|
||||||
{row}
|
{row}
|
||||||
|
@ -146,6 +81,24 @@
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
{#if $config.allowAddRows}
|
||||||
|
<div
|
||||||
|
class="row new"
|
||||||
|
on:mouseenter={() => ($hoveredRowId = BlankRowID)}
|
||||||
|
on:mouseleave={() => ($hoveredRowId = null)}
|
||||||
|
on:click={() => dispatch("add-row-inline", true)}
|
||||||
|
>
|
||||||
|
<GutterCell disableExpand rowHovered={$hoveredRowId === BlankRowID}>
|
||||||
|
<Icon name="Add" />
|
||||||
|
</GutterCell>
|
||||||
|
{#if $stickyColumn}
|
||||||
|
<GridCell
|
||||||
|
width={$stickyColumn.width}
|
||||||
|
highlighted={$hoveredRowId === BlankRowID}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</GridScrollWrapper>
|
</GridScrollWrapper>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -203,43 +156,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
.row.new :global(*:hover) {
|
||||||
/* Styles for gutter */
|
cursor: pointer;
|
||||||
.gutter {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
display: grid;
|
|
||||||
align-items: center;
|
|
||||||
padding: var(--cell-padding);
|
|
||||||
grid-template-columns: 1fr auto;
|
|
||||||
gap: var(--cell-spacing);
|
|
||||||
}
|
|
||||||
.checkbox,
|
|
||||||
.number {
|
|
||||||
display: none;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.checkbox :global(.spectrum-Checkbox) {
|
|
||||||
min-height: 0;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
.checkbox :global(.spectrum-Checkbox-box) {
|
|
||||||
margin: 3px 0 0 0;
|
|
||||||
}
|
|
||||||
.number {
|
|
||||||
color: var(--spectrum-global-color-gray-500);
|
|
||||||
}
|
|
||||||
.checkbox.visible,
|
|
||||||
.number.visible {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.expand {
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.expand.visible {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: all;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -10,3 +10,4 @@ export const MediumRowHeight = 64
|
||||||
export const LargeRowHeight = 92
|
export const LargeRowHeight = 92
|
||||||
export const DefaultRowHeight = SmallRowHeight
|
export const DefaultRowHeight = SmallRowHeight
|
||||||
export const NewRowID = "new"
|
export const NewRowID = "new"
|
||||||
|
export const BlankRowID = "blank"
|
||||||
|
|
|
@ -75,6 +75,8 @@ export const deriveStores = context => {
|
||||||
leftEdge += $visibleColumns[endColIdx].width
|
leftEdge += $visibleColumns[endColIdx].width
|
||||||
endColIdx++
|
endColIdx++
|
||||||
}
|
}
|
||||||
|
// Render an additional column on either side to account for
|
||||||
|
// debounce column updates based on scroll position
|
||||||
const next = $visibleColumns.slice(
|
const next = $visibleColumns.slice(
|
||||||
Math.max(0, startColIdx - 1),
|
Math.max(0, startColIdx - 1),
|
||||||
endColIdx + 1
|
endColIdx + 1
|
||||||
|
|
Loading…
Reference in New Issue