|
|
|
@ -8,8 +8,10 @@ |
|
|
|
<div> |
|
|
|
<div> |
|
|
|
Cell Heights: |
|
|
|
Cell Heights: |
|
|
|
{{ |
|
|
|
{{ |
|
|
|
rowHeights.map((entry) => |
|
|
|
cellHeights?.map((rowCellHeights) => |
|
|
|
entry.cellHeights?.map((entry) => `${entry.isCustomRenderer ? "*" : ""}${entry.height}`).join(",") |
|
|
|
rowCellHeights |
|
|
|
|
|
|
|
.map((entry) => (entry ? `${entry.isCustomRenderer ? "*" : ""}${entry.height}` : "null")) |
|
|
|
|
|
|
|
.join(",") |
|
|
|
) |
|
|
|
) |
|
|
|
}} |
|
|
|
}} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
@ -92,7 +94,7 @@ import { useI18n } from "vue3-i18n"; |
|
|
|
import * as lodash from "lodash-es"; |
|
|
|
import * as lodash from "lodash-es"; |
|
|
|
import type { ListTableColumn, ListTableProps, PageResponse } from "./types"; |
|
|
|
import type { ListTableColumn, ListTableProps, PageResponse } from "./types"; |
|
|
|
import { usePretextColumnWidths, type ColumnFlexConfig } from "./usePretextColumnWidths"; |
|
|
|
import { usePretextColumnWidths, type ColumnFlexConfig } from "./usePretextColumnWidths"; |
|
|
|
import { usePretextRowHeights, type RowHeightEntry } from "./usePretextRowHeights"; |
|
|
|
import { resolveRowHeights, type RowHeightEntry } from "./usePretextRowHeights"; |
|
|
|
import { useVirtualRows } from "./useVirtualRows"; |
|
|
|
import { useVirtualRows } from "./useVirtualRows"; |
|
|
|
|
|
|
|
|
|
|
|
const DEFAULT_FONT = "14px sans-serif"; |
|
|
|
const DEFAULT_FONT = "14px sans-serif"; |
|
|
|
@ -260,22 +262,20 @@ const { computedConfigs, totalFlexBasis, columnWidths } = usePretextColumnWidths |
|
|
|
{ |
|
|
|
{ |
|
|
|
font: "14px Inter, sans-serif", |
|
|
|
font: "14px Inter, sans-serif", |
|
|
|
headerFont: "bold 14px Inter, sans-serif", |
|
|
|
headerFont: "bold 14px Inter, sans-serif", |
|
|
|
|
|
|
|
formatCellValue, |
|
|
|
} |
|
|
|
} |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// Row heights via pretext - use actual column widths from flexbox algorithm |
|
|
|
// Row heights via pretext - use actual column widths from flexbox algorithm |
|
|
|
const { rowHeights, totalHeight } = usePretextRowHeights(pageDataRef, columnsRef, columnWidths, formatCellValue, { |
|
|
|
const { rowHeights, cellHeights } = resolveRowHeights(pageDataRef, columnsRef, columnWidths, formatCellValue, { |
|
|
|
font: props.font, |
|
|
|
font: props.font, |
|
|
|
lineHeight: 20, |
|
|
|
lineHeight: 20, |
|
|
|
debug: props.debug, |
|
|
|
debug: props.debug, |
|
|
|
|
|
|
|
fixedRowHeight: props.rowHeight, |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Virtualizer (needs rowHeights as number[] and viewportHeight) |
|
|
|
// Virtualizer (needs rowHeights as number[] and viewportHeight) |
|
|
|
const virtualizer = useVirtualRows( |
|
|
|
const virtualizer = useVirtualRows(rowHeights, viewportHeight, { overscan: 5 }); |
|
|
|
computed(() => rowHeights.value.map((r) => r.height)), |
|
|
|
|
|
|
|
viewportHeight, |
|
|
|
|
|
|
|
{ overscan: 5 } |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Destructure for template auto-unwrap (Vue 3 auto-unwraps top-level refs) |
|
|
|
// Destructure for template auto-unwrap (Vue 3 auto-unwraps top-level refs) |
|
|
|
const { visibleRows, totalHeight: virtualTotalHeight, onScroll } = virtualizer; |
|
|
|
const { visibleRows, totalHeight: virtualTotalHeight, onScroll } = virtualizer; |
|
|
|
@ -313,7 +313,6 @@ const tableContainerStyle = computed(() => { |
|
|
|
// ============================================================================= |
|
|
|
// ============================================================================= |
|
|
|
function getColumnStyle(col: ListTableColumn<T>): Record<string, string> { |
|
|
|
function getColumnStyle(col: ListTableColumn<T>): Record<string, string> { |
|
|
|
const config = computedConfigs.value.find((c) => c.key === col.key); |
|
|
|
const config = computedConfigs.value.find((c) => c.key === col.key); |
|
|
|
|
|
|
|
|
|
|
|
const explicitWidth = col.width !== undefined && col.width !== "auto" ? Number(col.width) : undefined; |
|
|
|
const explicitWidth = col.width !== undefined && col.width !== "auto" ? Number(col.width) : undefined; |
|
|
|
if (explicitWidth !== undefined && Number.isFinite(explicitWidth) && explicitWidth > 0) { |
|
|
|
if (explicitWidth !== undefined && Number.isFinite(explicitWidth) && explicitWidth > 0) { |
|
|
|
return { |
|
|
|
return { |
|
|
|
@ -327,16 +326,25 @@ function getColumnStyle(col: ListTableColumn<T>): Record<string, string> { |
|
|
|
// Find the column index to get the computed width |
|
|
|
// Find the column index to get the computed width |
|
|
|
const colIndex = columnsRef.value.findIndex((c) => c.key === col.key); |
|
|
|
const colIndex = columnsRef.value.findIndex((c) => c.key === col.key); |
|
|
|
const computedWidth = colIndex >= 0 ? columnWidths.value[colIndex] : 0; |
|
|
|
const computedWidth = colIndex >= 0 ? columnWidths.value[colIndex] : 0; |
|
|
|
|
|
|
|
const fallbackBasis = Number(col.minWidth ?? 120); |
|
|
|
|
|
|
|
|
|
|
|
if (!config) { |
|
|
|
if (!config) { |
|
|
|
return { flex: "1 1 100px", minWidth: "50px", maxWidth: "300px" }; |
|
|
|
return { |
|
|
|
|
|
|
|
flexGrow: "1.1", |
|
|
|
|
|
|
|
flexShrink: "1.1", |
|
|
|
|
|
|
|
flexBasis: `${fallbackBasis}px`, |
|
|
|
|
|
|
|
minWidth: `${Math.max(fallbackBasis, 50)}px`, |
|
|
|
|
|
|
|
maxWidth: "300px", |
|
|
|
|
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Apply the computed flex factors to the real cells so the row can consume |
|
|
|
// Apply the computed flex factors to the real cells so the row can consume |
|
|
|
// any remaining space after fixed-width columns and scrollbar width. |
|
|
|
// any remaining space after fixed-width columns and scrollbar width. |
|
|
|
const flexBasis = computedWidth > 0 ? computedWidth : config.flexBasis; |
|
|
|
const flexBasis = computedWidth > 0 ? computedWidth : config.flexBasis; |
|
|
|
return { |
|
|
|
return { |
|
|
|
flex: `${config.flexGrow} ${config.flexShrink} ${flexBasis}px`, |
|
|
|
flexGrow: `${config.flexGrow}`, |
|
|
|
|
|
|
|
flexShrink: `${config.flexShrink}`, |
|
|
|
|
|
|
|
flexBasis: `${flexBasis}px`, |
|
|
|
minWidth: `${config.minWidth}px`, |
|
|
|
minWidth: `${config.minWidth}px`, |
|
|
|
maxWidth: `${config.maxWidth}px`, |
|
|
|
maxWidth: `${config.maxWidth}px`, |
|
|
|
}; |
|
|
|
}; |
|
|
|
@ -455,6 +463,7 @@ onUnmounted(() => { |
|
|
|
|
|
|
|
|
|
|
|
.header-cell { |
|
|
|
.header-cell { |
|
|
|
display: flex; |
|
|
|
display: flex; |
|
|
|
|
|
|
|
flex: 1 1 120px; |
|
|
|
align-items: center; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
justify-content: center; |
|
|
|
padding: 8px 4px; |
|
|
|
padding: 8px 4px; |
|
|
|
@ -462,6 +471,7 @@ onUnmounted(() => { |
|
|
|
border-right: 1px solid v-bind("state.style.tableBorderColor"); |
|
|
|
border-right: 1px solid v-bind("state.style.tableBorderColor"); |
|
|
|
overflow: hidden; |
|
|
|
overflow: hidden; |
|
|
|
word-break: break-word; |
|
|
|
word-break: break-word; |
|
|
|
|
|
|
|
min-width: 0; |
|
|
|
|
|
|
|
|
|
|
|
&:last-child { |
|
|
|
&:last-child { |
|
|
|
border-right: none; |
|
|
|
border-right: none; |
|
|
|
@ -510,6 +520,7 @@ onUnmounted(() => { |
|
|
|
|
|
|
|
|
|
|
|
.table-cell { |
|
|
|
.table-cell { |
|
|
|
display: flex; |
|
|
|
display: flex; |
|
|
|
|
|
|
|
flex: 1 1 120px; |
|
|
|
align-items: center; |
|
|
|
align-items: center; |
|
|
|
padding: 8px 4px; |
|
|
|
padding: 8px 4px; |
|
|
|
box-sizing: border-box; |
|
|
|
box-sizing: border-box; |
|
|
|
@ -517,6 +528,7 @@ onUnmounted(() => { |
|
|
|
overflow: hidden; |
|
|
|
overflow: hidden; |
|
|
|
word-break: break-word; |
|
|
|
word-break: break-word; |
|
|
|
min-height: 100%; |
|
|
|
min-height: 100%; |
|
|
|
|
|
|
|
min-width: 0; |
|
|
|
|
|
|
|
|
|
|
|
&:last-child { |
|
|
|
&:last-child { |
|
|
|
border-right: none; |
|
|
|
border-right: none; |
|
|
|
@ -530,6 +542,7 @@ onUnmounted(() => { |
|
|
|
text-overflow: clip; |
|
|
|
text-overflow: clip; |
|
|
|
white-space: normal; |
|
|
|
white-space: normal; |
|
|
|
word-break: break-word; |
|
|
|
word-break: break-word; |
|
|
|
|
|
|
|
text-align: center; |
|
|
|
color: v-bind("state.style.tableColor"); |
|
|
|
color: v-bind("state.style.tableColor"); |
|
|
|
font: v-bind("props.font"); |
|
|
|
font: v-bind("props.font"); |
|
|
|
} |
|
|
|
} |
|
|
|
|