Add footer and improve styles

This commit is contained in:
Andrew Kingston 2022-11-24 15:59:24 +00:00
parent 17b0647e74
commit 1c3b6e0cec
1 changed files with 100 additions and 19 deletions

View File

@ -13,13 +13,13 @@
const { styleable, API } = getContext("sdk") const { styleable, API } = getContext("sdk")
const component = getContext("component") const component = getContext("component")
// Config
const limit = 100 const limit = 100
const defaultWidth = 200 const defaultWidth = 200
let widths let widths
let hoveredRow let hoveredRow
let selectedCell let selectedCell
let selectedRows = {}
let horizontallyScrolled = false let horizontallyScrolled = false
$: query = LuceneUtils.buildLuceneQuery(filter) $: query = LuceneUtils.buildLuceneQuery(filter)
@ -34,6 +34,8 @@
$: initWidths(fields) $: initWidths(fields)
$: gridStyles = getGridStyles(widths) $: gridStyles = getGridStyles(widths)
$: schema = $fetch.schema $: schema = $fetch.schema
$: rowCount = $fetch.rows?.length || 0
$: selectedRowCount = Object.values(selectedRows).filter(x => !!x).length
const createFetch = datasource => { const createFetch = datasource => {
return fetchData({ return fetchData({
@ -57,7 +59,7 @@
if (!widths?.length) { if (!widths?.length) {
return "--grid: 1fr;" return "--grid: 1fr;"
} }
return `--grid: 60px ${widths.map(x => `${x}px`).join(" ")};` return `--grid: 50px ${widths.map(x => `${x}px`).join(" ")};`
} }
const handleScroll = e => { const handleScroll = e => {
@ -86,6 +88,21 @@
} }
return "Text" return "Text"
} }
const selectRow = idx => {
selectedRows[idx] = !selectedRows[idx]
}
const selectAll = () => {
const allSelected = selectedRowCount === rowCount
if (allSelected) {
selectedRows = {}
} else {
for (let i = 0; i < rowCount; i++) {
selectedRows[i] = true
}
}
}
</script> </script>
<div use:styleable={$component.styles}> <div use:styleable={$component.styles}>
@ -107,8 +124,12 @@
</div> </div>
</div> </div>
<div class="spreadsheet" on:scroll={handleScroll} style={gridStyles}> <div class="spreadsheet" on:scroll={handleScroll} style={gridStyles}>
<div class="header cell label"> <!-- Field headers -->
<input type="checkbox" /> <div class="header cell label" on:click={selectAll}>
<input
type="checkbox"
checked={rowCount && selectedRowCount === rowCount}
/>
</div> </div>
{#each fields as field, fieldIdx} {#each fields as field, fieldIdx}
<div <div
@ -124,16 +145,34 @@
{field} {field}
</div> </div>
{/each} {/each}
<!-- All real rows -->
{#each $fetch.rows as row, rowIdx} {#each $fetch.rows as row, rowIdx}
<div class="cell label" class:hovered={hoveredRow === rowIdx}> {@const rowSelected = !!selectedRows[rowIdx]}
{rowIdx + 1} {@const rowHovered = hoveredRow === rowIdx}
<div
class="cell label"
class:row-selected={rowSelected}
class:hovered={rowHovered}
on:focus
on:mouseover={() => (hoveredRow = rowIdx)}
on:click={() => selectRow(rowIdx)}
>
{#if rowSelected || rowHovered}
<input type="checkbox" checked={rowSelected} />
{:else}
<span>
{rowIdx + 1}
</span>
{/if}
</div> </div>
{#each fields as field, fieldIdx} {#each fields as field, fieldIdx}
{@const cellIdx = rowIdx * fields.length + fieldIdx} {@const cellIdx = rowIdx * fields.length + fieldIdx}
<div <div
class="cell" class="cell"
class:row-selected={rowSelected}
class:sticky={fieldIdx === 0} class:sticky={fieldIdx === 0}
class:hovered={hoveredRow === rowIdx} class:hovered={rowHovered}
class:selected={selectedCell === cellIdx} class:selected={selectedCell === cellIdx}
class:shadow={horizontallyScrolled} class:shadow={horizontallyScrolled}
on:focus on:focus
@ -149,6 +188,25 @@
</div> </div>
{/each} {/each}
{/each} {/each}
<!-- New row placeholder -->
<div class="cell label">
<Icon hoverable name="Add" />
</div>
{#each fields as field, fieldIdx}
<div
class="cell"
class:sticky={fieldIdx === 0}
class:shadow={horizontallyScrolled}
/>
{/each}
</div>
<div class="footer">
{#if selectedRowCount}
{selectedRowCount} row{selectedRowCount === 1 ? "" : "s"} selected
{:else}
{rowCount} row{rowCount === 1 ? "" : "s"}
{/if}
</div> </div>
</div> </div>
</div> </div>
@ -170,6 +228,12 @@
overflow: auto; overflow: auto;
height: 800px; height: 800px;
position: relative; position: relative;
padding-bottom: 100px;
padding-right: 100px;
}
.wrapper ::-webkit-scrollbar-track {
background: var(--spectrum-global-color-gray-50);
} }
.controls { .controls {
@ -177,7 +241,7 @@
grid-template-columns: 1fr auto 1fr; grid-template-columns: 1fr auto 1fr;
align-items: center; align-items: center;
height: 36px; height: 36px;
padding: 0 16px; padding: 0 12px;
background: var(--spectrum-global-color-gray-200); background: var(--spectrum-global-color-gray-200);
gap: 8px; gap: 8px;
border-bottom: 1px solid var(--spectrum-global-color-gray-400); border-bottom: 1px solid var(--spectrum-global-color-gray-400);
@ -207,29 +271,29 @@
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
background: var(--spectrum-global-color-gray-50);
color: var(--spectrum-global-color-gray-900); color: var(--spectrum-global-color-gray-900);
font-size: 14px; font-size: 14px;
gap: 4px; gap: 4px;
} background: var(--spectrum-global-color-gray-50);
.cell:last-child {
border-right: none;
} }
.cell.hovered { .cell.hovered {
background: var(--spectrum-global-color-gray-100); background: var(--spectrum-global-color-gray-100);
} }
.cell.selected { .cell.selected {
box-shadow: inset 0 0 0 2px var(--primaryColorHover); box-shadow: inset 0 0 0 2px rgb(89, 167, 246);
z-index: 1; z-index: 1;
} }
.cell:hover { .cell:hover {
cursor: pointer; cursor: default;
} }
.cell.sticky { .cell.sticky {
position: sticky; position: sticky;
left: 60px; left: 50px;
z-index: 2; z-index: 2;
} }
.cell.row-selected {
background-color: rgba(20, 122, 243, 0.05);
}
.header { .header {
background: var(--spectrum-global-color-gray-200); background: var(--spectrum-global-color-gray-200);
@ -253,9 +317,8 @@
} }
.label { .label {
padding: 0 16px; padding: 0 12px;
border-right: none; border-right: none;
color: var(--spectrum-global-color-gray-500);
position: sticky; position: sticky;
left: 0; left: 0;
z-index: 2; z-index: 2;
@ -263,7 +326,25 @@
.label.header { .label.header {
z-index: 4; z-index: 4;
} }
.label.header input { .label span {
min-width: 14px;
text-align: center;
color: var(--spectrum-global-color-gray-500);
}
input[type="checkbox"] {
margin: 0; margin: 0;
} }
.footer {
height: 32px;
width: 100%;
border-top: 1px solid var(--spectrum-global-color-gray-400);
padding: 0 12px;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
background: var(--spectrum-global-color-gray-50);
}
</style> </style>