Move new row component to top, automatically invert cell renderers when required
This commit is contained in:
parent
7050c6713a
commit
a0299d4c7c
|
@ -355,6 +355,9 @@
|
|||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
.compact .spectrum-Dropzone {
|
||||
padding: 6px 0 !important;
|
||||
}
|
||||
|
||||
.gallery {
|
||||
display: flex;
|
||||
|
@ -381,7 +384,14 @@
|
|||
}
|
||||
.compact .placeholder,
|
||||
.compact img {
|
||||
margin: 12px 16px;
|
||||
margin: 10px 16px;
|
||||
}
|
||||
.compact img {
|
||||
height: 90px;
|
||||
}
|
||||
.compact .gallery {
|
||||
padding: 6px 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.title {
|
||||
display: flex;
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
<div class="sort-indicator">
|
||||
<Icon
|
||||
size="S"
|
||||
name={$sort.order === "descending" ? "ChevronDown" : "ChevronUp"}
|
||||
name={$sort.order === "descending" ? "SortOrderDown" : "SortOrderUp"}
|
||||
color="var(--spectrum-global-color-gray-600)"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -158,10 +158,11 @@
|
|||
user-select: none;
|
||||
}
|
||||
.arrow {
|
||||
border-right: 2px solid var(--spectrum-global-color-blue-400);
|
||||
/*border-right: 2px solid var(--spectrum-global-color-blue-400);*/
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 2px;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
bottom: 2px;
|
||||
padding: 0 6px 0 16px;
|
||||
display: grid;
|
||||
|
@ -182,7 +183,7 @@
|
|||
box-shadow: 0 0 8px 4px rgba(0, 0, 0, 0.15);
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
max-height: calc(5 * var(--cell-height) + 1px);
|
||||
max-height: var(--max-cell-render-height);
|
||||
overflow-y: auto;
|
||||
border: var(--cell-border);
|
||||
}
|
||||
|
|
|
@ -293,7 +293,7 @@
|
|||
left: 0;
|
||||
min-width: 100%;
|
||||
max-width: calc(100% + 240px);
|
||||
max-height: calc(var(--cell-height) + 240px);
|
||||
max-height: var(--max-cell-render-height);
|
||||
background: var(--cell-background);
|
||||
border: var(--cell-border);
|
||||
box-shadow: 0 0 8px 4px rgba(0, 0, 0, 0.15);
|
||||
|
|
|
@ -68,16 +68,34 @@
|
|||
position: relative;
|
||||
width: 0;
|
||||
}
|
||||
.cell.selected:after,
|
||||
.cell.error:after,
|
||||
.cell.selected-other:not(.selected):after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: 2px solid transparent;
|
||||
pointer-events: none;
|
||||
border-radius: 2px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.cell.selected {
|
||||
box-shadow: inset 0 0 0 2px var(--spectrum-global-color-blue-400);
|
||||
z-index: 2;
|
||||
}
|
||||
.cell.error {
|
||||
box-shadow: inset 0 0 0 2px var(--spectrum-global-color-red-400);
|
||||
.cell.selected:after {
|
||||
border-color: var(--spectrum-global-color-blue-400);
|
||||
}
|
||||
.cell.error:after {
|
||||
border-color: var(--spectrum-global-color-red-400);
|
||||
}
|
||||
.cell.selected-other:not(.selected) {
|
||||
z-index: 1;
|
||||
box-shadow: inset 0 0 0 2px var(--user-color);
|
||||
}
|
||||
.cell.selected-other:not(.selected):after {
|
||||
border-color: var(--spectrum-global-color-red-400);
|
||||
}
|
||||
.cell:not(.selected) {
|
||||
user-select: none;
|
||||
|
@ -112,7 +130,8 @@
|
|||
.label {
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
padding: 1px 4px;
|
||||
margin: 0 0 -2px 0;
|
||||
padding: 1px 4px 3px 4px;
|
||||
background: var(--user-color);
|
||||
border-radius: 2px 2px 0 0;
|
||||
display: none;
|
||||
|
@ -129,7 +148,8 @@
|
|||
bottom: auto;
|
||||
top: 100%;
|
||||
border-radius: 0 0 2px 2px;
|
||||
padding: 0 4px 2px 4px;
|
||||
padding: 2px 4px 2px 4px;
|
||||
margin: -2px 0 0 0;
|
||||
}
|
||||
.cell:hover .label {
|
||||
display: block;
|
||||
|
|
|
@ -1,38 +1,16 @@
|
|||
<script>
|
||||
import { Icon } from "@budibase/bbui"
|
||||
import { ActionButton } from "@budibase/bbui"
|
||||
import { getContext } from "svelte"
|
||||
|
||||
const { dispatch, columns, ui } = getContext("sheet")
|
||||
|
||||
const addRow = () => {
|
||||
ui.actions.blur()
|
||||
dispatch("add-row")
|
||||
}
|
||||
const { dispatch, columns, stickyColumn } = getContext("sheet")
|
||||
</script>
|
||||
|
||||
{#if $columns.length}
|
||||
<div class="add-component" on:click={addRow}>
|
||||
<Icon size="XL" name="Add" />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.add-component {
|
||||
position: absolute;
|
||||
bottom: calc(20px + var(--spacing-l));
|
||||
right: calc(20px + var(--spacing-xl));
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
background: var(--spectrum-global-color-blue-500);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
color: white;
|
||||
box-shadow: 1px 3px 8px 0 rgba(0, 0, 0, 0.3);
|
||||
cursor: pointer;
|
||||
transition: transform ease-out 300ms, background ease-out 130ms;
|
||||
}
|
||||
.add-component:hover {
|
||||
background: var(--spectrum-global-color-blue-600);
|
||||
}
|
||||
</style>
|
||||
<ActionButton
|
||||
icon="Add"
|
||||
quiet
|
||||
size="M"
|
||||
on:click={() => dispatch("add-row-inline")}
|
||||
disabled={!$columns.length && !$stickyColumn}
|
||||
>
|
||||
Create row
|
||||
</ActionButton>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
background: var(--background);
|
||||
border-bottom: var(--cell-border);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
z-index: 2;
|
||||
height: var(--cell-height);
|
||||
}
|
||||
.row {
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
<script>
|
||||
import SheetCell from "../cells/SheetCell.svelte"
|
||||
import { getContext, onMount } from "svelte"
|
||||
import { Icon, Button } from "@budibase/bbui"
|
||||
import SheetScrollWrapper from "./SheetScrollWrapper.svelte"
|
||||
import DataCell from "../cells/DataCell.svelte"
|
||||
|
||||
const {
|
||||
renderedColumns,
|
||||
hoveredRowId,
|
||||
selectedCellId,
|
||||
stickyColumn,
|
||||
gutterWidth,
|
||||
scroll,
|
||||
config,
|
||||
dispatch,
|
||||
visibleColumns,
|
||||
rows,
|
||||
wheel,
|
||||
showHScrollbar,
|
||||
tableId,
|
||||
subscribe,
|
||||
selectedCellAPI,
|
||||
} = getContext("sheet")
|
||||
|
||||
let isAdding = false
|
||||
let newRow = {}
|
||||
let touched = false
|
||||
|
||||
$: firstColumn = $stickyColumn || $visibleColumns[0]
|
||||
$: rowHovered = $hoveredRowId === "new"
|
||||
$: containsSelectedCell = $selectedCellId?.startsWith("new-")
|
||||
$: width = gutterWidth + ($stickyColumn?.width || 0)
|
||||
$: scrollLeft = $scroll.left
|
||||
$: $tableId, (isAdding = false)
|
||||
|
||||
const addRow = async () => {
|
||||
const savedRow = await rows.actions.addRow(newRow, 0)
|
||||
if (savedRow && firstColumn) {
|
||||
$selectedCellId = `${savedRow._id}-${firstColumn.name}`
|
||||
isAdding = false
|
||||
}
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
isAdding = false
|
||||
}
|
||||
|
||||
const startAdding = () => {
|
||||
newRow = {}
|
||||
isAdding = true
|
||||
if (firstColumn) {
|
||||
$selectedCellId = `new-${firstColumn.name}`
|
||||
setTimeout(() => {
|
||||
$selectedCellAPI?.focus()
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
|
||||
const updateRow = (rowId, columnName, val) => {
|
||||
touched = true
|
||||
newRow[columnName] = val
|
||||
}
|
||||
|
||||
const addViaModal = () => {
|
||||
isAdding = false
|
||||
dispatch("add-row")
|
||||
}
|
||||
|
||||
onMount(() => subscribe("add-row-inline", startAdding))
|
||||
</script>
|
||||
|
||||
<!-- Only show new row functionality if we have any columns -->
|
||||
{#if firstColumn}
|
||||
<div
|
||||
class="container"
|
||||
class:visible={isAdding}
|
||||
on:wheel={wheel.actions.handleWheel}
|
||||
>
|
||||
<div class="content" class:above-scrollbar={$showHScrollbar}>
|
||||
<div
|
||||
class="new-row"
|
||||
on:mouseenter={() => ($hoveredRowId = "new")}
|
||||
on:mouseleave={() => ($hoveredRowId = null)}
|
||||
>
|
||||
<div
|
||||
class="sticky-column"
|
||||
style="flex: 0 0 {width}px"
|
||||
class:scrolled={scrollLeft > 0}
|
||||
>
|
||||
<SheetCell
|
||||
width={gutterWidth}
|
||||
{rowHovered}
|
||||
rowSelected={containsSelectedCell}
|
||||
>
|
||||
<div class="gutter">
|
||||
<div class="number">1</div>
|
||||
{#if $config.allowExpandRows}
|
||||
<Icon
|
||||
name="Maximize"
|
||||
size="S"
|
||||
hoverable
|
||||
on:click={addViaModal}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</SheetCell>
|
||||
{#if $stickyColumn}
|
||||
{@const cellId = `new-${$stickyColumn.name}`}
|
||||
<DataCell
|
||||
{cellId}
|
||||
column={$stickyColumn}
|
||||
row={newRow}
|
||||
{rowHovered}
|
||||
selected={$selectedCellId === cellId}
|
||||
rowSelected={containsSelectedCell}
|
||||
width={$stickyColumn.width}
|
||||
{updateRow}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
<SheetScrollWrapper scrollVertically={false}>
|
||||
<div class="row">
|
||||
{#each $renderedColumns as column}
|
||||
{@const cellId = `new-${column.name}`}
|
||||
<DataCell
|
||||
{cellId}
|
||||
{column}
|
||||
row={newRow}
|
||||
{rowHovered}
|
||||
selected={$selectedCellId === cellId}
|
||||
rowSelected={containsSelectedCell}
|
||||
width={column.width}
|
||||
{updateRow}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</SheetScrollWrapper>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<Button size="M" cta on:click={addRow}>Save</Button>
|
||||
<Button size="M" secondary newStyles on:click={cancel}>Cancel</Button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.container {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: var(--cell-height);
|
||||
transform: translateY(-100%);
|
||||
z-index: 1;
|
||||
transition: transform 130ms ease-out;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
var(--cell-background) 20%,
|
||||
transparent 100%
|
||||
);
|
||||
width: 100%;
|
||||
padding-bottom: 64px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.container.visible {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.content {
|
||||
pointer-events: all;
|
||||
background: var(--background);
|
||||
border-bottom: var(--cell-border);
|
||||
}
|
||||
|
||||
.new-row {
|
||||
display: flex;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
transition: margin-bottom 130ms ease-out;
|
||||
}
|
||||
.new-row.visible {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.new-row :global(.cell) {
|
||||
--cell-background: var(--background) !important;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.sticky-column {
|
||||
display: flex;
|
||||
z-index: 1;
|
||||
}
|
||||
/* Don't show borders between cells in the sticky column */
|
||||
.sticky-column :global(.cell:not(:last-child)) {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.row {
|
||||
width: 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Add shadow when scrolled */
|
||||
.sticky.scrolled :global(.cell:last-child:after) {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
left: 100%;
|
||||
background: linear-gradient(to right, rgba(0, 0, 0, 0.08), transparent);
|
||||
}
|
||||
|
||||
/* Styles for gutter */
|
||||
.gutter {
|
||||
flex: 1 1 auto;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
padding: var(--cell-padding);
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: var(--cell-spacing);
|
||||
}
|
||||
|
||||
/* Floating buttons */
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
margin: 16px 0 0 16px;
|
||||
pointer-events: all;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.number {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--spectrum-global-color-gray-500);
|
||||
}
|
||||
</style>
|
|
@ -27,7 +27,8 @@
|
|||
import KeyboardManager from "../overlays/KeyboardManager.svelte"
|
||||
import { clickOutside } from "@budibase/bbui"
|
||||
import SheetControls from "./SheetControls.svelte"
|
||||
import NewRow from "./NewRow.svelte"
|
||||
import NewRowTop from "./NewRowTop.svelte"
|
||||
import { MaxCellRenderHeight } from "../lib/constants"
|
||||
|
||||
export let API
|
||||
export let tableId
|
||||
|
@ -108,12 +109,12 @@
|
|||
id="sheet-{rand}"
|
||||
class:is-resizing={$isResizing}
|
||||
class:is-reordering={$isReordering}
|
||||
style="--cell-height:{cellHeight}px; --gutter-width:{gutterWidth}px;"
|
||||
style="--cell-height:{cellHeight}px; --gutter-width:{gutterWidth}px; --max-cell-render-height:{MaxCellRenderHeight}px;"
|
||||
>
|
||||
<div class="controls">
|
||||
<div class="controls-left">
|
||||
<slot name="controls" />
|
||||
<SheetControls />
|
||||
<slot name="controls" />
|
||||
</div>
|
||||
<div class="controls-right">
|
||||
<DeleteButton />
|
||||
|
@ -129,7 +130,8 @@
|
|||
<SheetBody />
|
||||
</div>
|
||||
{#if $config.allowAddRows}
|
||||
<NewRow />
|
||||
<!-- <NewRow />-->
|
||||
<NewRowTop />
|
||||
{/if}
|
||||
<ResizeOverlay />
|
||||
<ScrollOverlay />
|
||||
|
|
|
@ -2,11 +2,17 @@
|
|||
import { getContext, onMount } from "svelte"
|
||||
import SheetScrollWrapper from "./SheetScrollWrapper.svelte"
|
||||
import SheetRow from "./SheetRow.svelte"
|
||||
import { MaxCellRenderHeight } from "../lib/constants"
|
||||
|
||||
const { bounds, renderedRows } = getContext("sheet")
|
||||
const { bounds, renderedRows, visualRowCapacity, cellHeight } =
|
||||
getContext("sheet")
|
||||
|
||||
let body
|
||||
|
||||
$: inversionIdx =
|
||||
$visualRowCapacity - Math.ceil(MaxCellRenderHeight / cellHeight) - 2
|
||||
$: console.log(inversionIdx)
|
||||
|
||||
onMount(() => {
|
||||
// Observe and record the height of the body
|
||||
const observer = new ResizeObserver(() => {
|
||||
|
@ -22,7 +28,7 @@
|
|||
<div bind:this={body} class="sheet-body">
|
||||
<SheetScrollWrapper>
|
||||
{#each $renderedRows as row, idx}
|
||||
<SheetRow {row} {idx} />
|
||||
<SheetRow {row} {idx} invert={idx >= inversionIdx} />
|
||||
{/each}
|
||||
</SheetScrollWrapper>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<script>
|
||||
import SortButton from "../controls/SortButton.svelte"
|
||||
import HideColumnsButton from "../controls/HideColumnsButton.svelte"
|
||||
import AddRowButton from "../controls/AddRowButton.svelte"
|
||||
</script>
|
||||
|
||||
<AddRowButton />
|
||||
<HideColumnsButton />
|
||||
<SortButton />
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
export let row
|
||||
export let idx
|
||||
export let invert = false
|
||||
|
||||
const {
|
||||
selectedCellId,
|
||||
|
@ -40,6 +41,7 @@
|
|||
{cellId}
|
||||
{column}
|
||||
{row}
|
||||
{invert}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
@ -164,12 +164,12 @@
|
|||
|
||||
/* Add shadow when scrolled */
|
||||
.sticky-column.scrolled :global(.cell:last-child:after) {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
left: 100%;
|
||||
background: linear-gradient(to right, rgba(0, 0, 0, 0.08), transparent);
|
||||
/*content: " ";*/
|
||||
/*position: absolute;*/
|
||||
/*width: 10px;*/
|
||||
/*height: 100%;*/
|
||||
/*left: 100%;*/
|
||||
/*background: linear-gradient(to right, rgba(0, 0, 0, 0.08), transparent);*/
|
||||
}
|
||||
|
||||
/* Don't show borders between cells in the sticky column */
|
||||
|
@ -179,7 +179,7 @@
|
|||
|
||||
.header {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
z-index: 3;
|
||||
}
|
||||
.header :global(.cell) {
|
||||
background: var(--spectrum-global-color-gray-100);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export const MaxCellRenderHeight = 216
|
|
@ -12,7 +12,7 @@ export const createMaxScrollStores = context => {
|
|||
selectedCellId,
|
||||
gutterWidth,
|
||||
} = context
|
||||
const padding = 255
|
||||
const padding = 264
|
||||
|
||||
// Memoize store primitives
|
||||
const scrollTop = derived(scroll, $scroll => $scroll.top, 0)
|
||||
|
|
|
@ -136,7 +136,7 @@ export const createRowsStore = context => {
|
|||
} else {
|
||||
handleNewRows([newRow])
|
||||
}
|
||||
notifications.success("Row added successfully")
|
||||
notifications.success("Row created successfully")
|
||||
return newRow
|
||||
} catch (error) {
|
||||
notifications.error(`Error adding row: ${error?.message}`)
|
||||
|
|
|
@ -77,5 +77,10 @@ export const createViewportStores = context => {
|
|||
[]
|
||||
)
|
||||
|
||||
return { scrolledRowCount, visualRowCapacity, renderedRows, renderedColumns }
|
||||
return {
|
||||
scrolledRowCount,
|
||||
visualRowCapacity,
|
||||
renderedRows,
|
||||
renderedColumns,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue