{#snippet hiddenColumnsNote()} {#if hidden.length}
{hidden.length} {hidden.length === 1 ? 'column' : 'columns'} hidden by filter
{/if} {/snippet} {#snippet addColumnHeader()} {#if canAddColumn}
onNewColumn?.() }] : []), // Only offered when the table references another by foreign key. ...(joinTargets?.length ? [{ displayName: 'View joined column', icon: Merge, action: openJoinPicker }] : []) ]} btnId="db-table-add-column" > {#snippet buttonReplacement()}
{/snippet}
{/if} {@render hiddenColumnsNote()} {/snippet} {#snippet addColumnCell()} {#if canAddColumn}
{/if} {#if hidden.length}
{/if} {/snippet} { if (editing) cancelEdit() closeFormatOnOutsideClick(e) }} onkeydown={(e) => { if (formatting && e.key === 'Escape') formatting = undefined }} />
{#if totalRows > 0 && endRow !== 0} {Math.min(firstVisible + 1, totalRows)}–{Math.min(lastVisible, totalRows)} {#if rowCount !== undefined || endRow !== undefined} of {endRow ?? rowCount} rows {/if} {/if} {/snippet} {#snippet content()}
{#each columns as col (col.field)}
{#if formats[col.field]} {/if} openFormat(col.field) } ]} size="2xs" class="opacity-0 group-hover:opacity-100 focus-within:opacity-100" />
{/each}
{#if onNewColumn}
{/if}
{/snippet}
{#if dbTableOps.onInsert} { if (!$operatingWorkspace) return dbTableOps.onInsert?.({ values }).then(() => { refresh() sendUserToast('Row inserted') }) }} /> {/if}
(scrollTop = e.currentTarget.scrollTop)} onkeydown={onGridKeyDown} onclick={(e) => (selected = cellFromEvent(e))} ondblclick={(e) => { const cell = cellFromEvent(e) if (cell) startEdit(cell.row, cell.column) }} >
{#each displayColumns as col (col.field)} {@const sorted = sort?.column === col.field ? sort : undefined} {@const pin = pinned[col.field]} {#if col.field === firstRightPinned} {@render addColumnHeader()}
{/if}
startResize(e, col.field)} ondblclick={(e) => { e.stopPropagation() autoSize([col.field]) }} >
{/each} {#if !firstRightPinned} {@render addColumnHeader()}
{/if}
{#if endRow === 0}
{hasFilters ? 'No rows match the filters' : 'No rows'}
{/if}
{#each renderedIndices as i (i)} {@const data = rowAt(i)}
{#each displayColumns as col (col.field)} {@const isSelected = selected?.row === i && selected.column === col.field} {@const pin = pinned[col.field]} {@const style = data && data !== 'loading' ? cellStyle(data[col.field], col.datatype, formats[col.field]) : undefined} {#if col.field === firstRightPinned} {@render addColumnCell()}
{/if}
{#if pin}
{/if} {#if data === 'loading'}
{:else if data} {@const value = data[col.field]} {@const format = formats[col.field]} {@const shown = formatValue(value, format) ?? formatCell(value)} {#if value === null || value === undefined} NULL {:else if fkByColumn[col.field] && hasForeignKeyValue(value)} {@const fk = fkByColumn[col.field]} {:else} {shown} {/if} {/if}
{/each} {#if !firstRightPinned} {@render addColumnCell()}
{/if}
{/each}
{#if gridOuterWidth - viewportWidth > 0}
{/if} {#if gridOuterHeight - viewportHeight > 0}
{/if}
{ if (editing) { const el = cellElement(editing.row, editing.column) if (el) editorRect = el.getBoundingClientRect() } return editorRect }} >
e.stopPropagation()}> {#if editing} { if (e.key === 'Enter') { e.preventDefault() commitEdit() } else if (e.key === 'Escape') { e.preventDefault() e.stopPropagation() cancelEdit() } } }} />
Enter to save, Esc to cancel
{/if}
{ if (formatting) { const header = scrollEl?.querySelector(`[data-header-column="${CSS.escape(formatting)}"]`) // A hidden column has no header: its format opens from the columns button. const el = header ?? columnsAnchor if (el) formatRect = el.getBoundingClientRect() } return formatRect }} >
{#if formatting} {@const column = formatting} setFormat(column, f)} /> {/if}