Add footer and improve styles
This commit is contained in:
parent
17b0647e74
commit
1c3b6e0cec
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue