Skip to content

Commit

Permalink
refactor(table): responsive cells and rows height
Browse files Browse the repository at this point in the history
  • Loading branch information
qmhc committed Oct 24, 2023
1 parent fc80708 commit 94cc2eb
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 75 deletions.
8 changes: 8 additions & 0 deletions components/table/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ export function useStore(options: StoreOptions) {
setBorderHeight,
setRowHeight,
setRowMinHeight,
setCellHeight,
setVirtual,
setRowDraggable,
setRowExpandHeight,
Expand Down Expand Up @@ -671,6 +672,7 @@ export function useStore(options: StoreOptions) {
partial: false,
dragging: false,
listIndex: 0,
cellHeights: reactive({}),
data: item
}

Expand Down Expand Up @@ -831,6 +833,12 @@ export function useStore(options: StoreOptions) {
state.rowMinHeight = height
}

function setCellHeight(rowKey: Key, columnKey: Key, height: number) {
if (state.rowMap.has(rowKey)) {
state.rowMap.get(rowKey)!.cellHeights[columnKey] = height
}
}

function setRowDraggable(draggable: boolean) {
state.rowDraggable = !!draggable
}
Expand Down
1 change: 1 addition & 0 deletions components/table/symbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ export interface TableRowState {
partial: boolean,
dragging: boolean,
listIndex: number,
cellHeights: Record<Key, number>,
data: Data
}

Expand Down
132 changes: 80 additions & 52 deletions components/table/table-cell.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<template>
<div
v-bind="attrs"
ref="wrapper"
:class="className"
role="cell"
:scope="column.first ? 'row' : undefined"
Expand Down Expand Up @@ -52,66 +53,72 @@
</button>
</template>
</template>
<template v-else>
<template
v-if="usingTree && (indentedColumn ? column.key === indentedColumn.key : column.first)"
>
<span
:class="nh.be('pad')"
:style="{
[nh.cv('row-depth')]: row.depth
}"
></span>
<button
type="button"
:class="[nh.be('tree-expand'), !row.children?.length && nh.bem('tree-expand', 'hidden')]"
@click="handleExpandTree(row)"
<ResizeObserver v-else :disabled="!column.noEllipsis" :on-resize="handleCellResize">
<span :class="nh.be('content')">
<template
v-if="usingTree && (indentedColumn ? column.key === indentedColumn.key : column.first)"
>
<TableIcon v-if="row.treeExpanded" name="minus" :origin="icons.minus"></TableIcon>
<TableIcon v-else name="plus" :origin="icons.plus"></TableIcon>
</button>
</template>
<Ellipsis
v-if="!column.noEllipsis"
inherit
:tooltip-theme="tooltipTheme"
:tip-max-width="tooltipWidth"
>
<Renderer
v-if="isFunction(column.renderer)"
:renderer="column.renderer"
:data="{ row: row.data, rowIndex, column, columnIndex }"
></Renderer>
<template v-else-if="isFunction(column.accessor)">
{{ column.accessor(row.data, rowIndex) }}
</template>
<template v-else>
{{ row.data[column.key] }}
</template>
</Ellipsis>
<template v-else>
<Renderer
v-if="isFunction(column.renderer)"
:renderer="column.renderer"
:data="{ row: row.data, rowIndex, column, columnIndex }"
></Renderer>
<template v-else-if="isFunction(column.accessor)">
{{ column.accessor(row.data, rowIndex) }}
<span
:class="nh.be('pad')"
:style="{
[nh.cv('row-depth')]: row.depth
}"
></span>
<button
type="button"
:class="[
nh.be('tree-expand'),
!row.children?.length && nh.bem('tree-expand', 'hidden')
]"
@click="handleExpandTree(row)"
>
<TableIcon v-if="row.treeExpanded" name="minus" :origin="icons.minus"></TableIcon>
<TableIcon v-else name="plus" :origin="icons.plus"></TableIcon>
</button>
</template>
<Ellipsis
v-if="!column.noEllipsis"
inherit
:tooltip-theme="tooltipTheme"
:tip-max-width="tooltipWidth"
>
<Renderer
v-if="isFunction(column.renderer)"
:renderer="column.renderer"
:data="{ row: row.data, rowIndex, column, columnIndex }"
></Renderer>
<template v-else-if="isFunction(column.accessor)">
{{ column.accessor(row.data, rowIndex) }}
</template>
<template v-else>
{{ row.data[column.key] }}
</template>
</Ellipsis>
<template v-else>
{{ row.data[column.key] }}
<Renderer
v-if="isFunction(column.renderer)"
:renderer="column.renderer"
:data="{ row: row.data, rowIndex, column, columnIndex }"
></Renderer>
<template v-else-if="isFunction(column.accessor)">
{{ column.accessor(row.data, rowIndex) }}
</template>
<template v-else>
{{ row.data[column.key] }}
</template>
</template>
</template>
</template>
</span>
</ResizeObserver>
</div>
</template>

<script lang="ts">
import { Checkbox } from '@/components/checkbox'
import { Ellipsis } from '@/components/ellipsis'
import { Renderer } from '@/components/renderer'
import { ResizeObserver } from '@/components/resize-observer'
import { computed, defineComponent, inject, toRef } from 'vue'
import { computed, defineComponent, inject, ref, toRef } from 'vue'
import { useIcons, useNameHelper } from '@vexip-ui/config'
import TableIcon from './table-icon.vue'
Expand All @@ -137,6 +144,7 @@ export default defineComponent({
Checkbox,
Ellipsis,
Renderer,
ResizeObserver,
TableIcon
},
props: {
Expand Down Expand Up @@ -167,6 +175,9 @@ export default defineComponent({
const nh = useNameHelper('table')
const { isRtl } = useRtl()
const wrapper = ref<HTMLElement>()
const disableCheckRows = toRef(getters, 'disableCheckRows')
const disableExpandRows = toRef(getters, 'disableExpandRows')
const disableDragRows = toRef(getters, 'disableDragRows')
Expand All @@ -185,12 +196,13 @@ export default defineComponent({
customClass = state.cellClass
}
const typed = columnTypes.includes((props.column as TableTypeColumn).type)
return [
nh.be('cell'),
{
[nh.bem('cell', 'center')]:
columnTypes.includes((props.column as TableTypeColumn).type) ||
props.column.textAlign === 'center',
[nh.bem('cell', 'typed')]: typed,
[nh.bem('cell', 'center')]: typed || props.column.textAlign === 'center',
[nh.bem('cell', 'right')]: props.column.textAlign === 'right',
[nh.bem('cell', 'wrap')]: props.column.noEllipsis,
[nh.bem('cell', 'last')]: props.column.last
Expand Down Expand Up @@ -398,10 +410,25 @@ export default defineComponent({
mutations.handleTreeExpand(row.key, !row.treeExpanded)
}
function handleCellResize(entry: ResizeObserverEntry) {
if (!wrapper.value) return
const style = getComputedStyle(wrapper.value)
const borderHeight = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth)
mutations.setCellHeight(
props.row.key,
props.column.key,
(entry.borderBoxSize?.[0]?.blockSize ?? entry.contentRect.height) + borderHeight
)
}
return {
nh,
icons: useIcons(),
wrapper,
className,
cellSpan,
style,
Expand All @@ -428,7 +455,8 @@ export default defineComponent({
handleCheckRow,
handleExpandRow,
handleDragRow,
handleExpandTree
handleExpandTree,
handleCellResize
}
}
})
Expand Down
54 changes: 46 additions & 8 deletions components/table/table-foot-cell.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<template>
<div
v-bind="attrs"
ref="wrapper"
:class="className"
role="cell"
:scope="column.first ? 'row' : undefined"
Expand All @@ -13,7 +14,11 @@
@dblclick="handleDblclick"
@contextmenu="handleContextmenu"
>
<template v-if="isFunction(summary.renderer)">
<ResizeObserver
v-if="isFunction(summary.renderer)"
:disabled="!column.noEllipsis"
:on-resize="handleCellResize"
>
<Ellipsis
v-if="!column.noEllipsis"
inherit
Expand All @@ -30,31 +35,43 @@
:renderer="summary.renderer"
:data="{ column, index: columnIndex, rows: data, meta: summaryData }"
></Renderer>
</template>
</ResizeObserver>
</div>
</template>

<script lang="ts">
import { Ellipsis } from '@/components/ellipsis'
import { Renderer } from '@/components/renderer'
import { ResizeObserver } from '@/components/resize-observer'
import { computed, defineComponent, inject, toRef } from 'vue'
import { computed, defineComponent, inject, ref, toRef } from 'vue'
import { useNameHelper } from '@vexip-ui/config'
import { useRtl } from '@vexip-ui/hooks'
import { boundRange, isFunction } from '@vexip-ui/utils'
import { TABLE_ACTIONS, TABLE_STORE } from './symbol'
import { TABLE_ACTIONS, TABLE_STORE, columnTypes } from './symbol'
import type { PropType } from 'vue'
import type { ColumnWithKey, SummaryCellSpanFn, SummaryWithKey } from './symbol'
import type {
ColumnWithKey,
SummaryCellSpanFn,
SummaryWithKey,
TableRowState,
TableTypeColumn
} from './symbol'
export default defineComponent({
name: 'TableFootCell',
components: {
Ellipsis,
Renderer
Renderer,
ResizeObserver
},
props: {
row: {
type: Object as PropType<TableRowState>,
default: () => ({})
},
column: {
type: Object as PropType<ColumnWithKey>,
default: () => ({})
Expand Down Expand Up @@ -87,6 +104,8 @@ export default defineComponent({
const nh = useNameHelper('table')
const { isRtl } = useRtl()
const wrapper = ref<HTMLElement>()
// We use 'a' and 'b' to distinguish above and below
const prefix = computed(() => (props.above ? 'af' : 'bf'))
const summaries = computed(() => (props.above ? state.aboveSummaries : state.belowSummaries))
Expand All @@ -107,10 +126,13 @@ export default defineComponent({
customClass = state.footClass
}
const typed = columnTypes.includes((props.column as TableTypeColumn).type)
return [
nh.be('foot-cell'),
{
[nh.bem('foot-cell', 'center')]: props.column.textAlign === 'center',
[nh.bem('foot-cell', 'typed')]: typed,
[nh.bem('foot-cell', 'center')]: typed || props.column.textAlign === 'center',
[nh.bem('foot-cell', 'right')]: props.column.textAlign === 'right',
[nh.bem('foot-cell', 'wrap')]: props.column.noEllipsis,
[nh.bem('foot-cell', 'last')]: props.column.last
Expand Down Expand Up @@ -255,9 +277,24 @@ export default defineComponent({
tableActions?.emitFootEvent('Contextmenu', buildEventPayload(event))
}
function handleCellResize(entry: ResizeObserverEntry) {
if (!wrapper.value) return
const style = getComputedStyle(wrapper.value)
const borderHeight = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth)
mutations.setCellHeight(
props.row.key,
props.column.key,
(entry.borderBoxSize?.[0]?.blockSize ?? entry.contentRect.height) + borderHeight
)
}
return {
nh,
wrapper,
className,
cellSpan,
style,
Expand All @@ -272,7 +309,8 @@ export default defineComponent({
handleMouseLeave,
handleClick,
handleDblclick,
handleContextmenu
handleContextmenu,
handleCellResize
}
}
})
Expand Down
1 change: 1 addition & 0 deletions components/table/table-foot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<TableFootCell
v-for="(column, columnIndex) in columns"
:key="columnIndex"
:row="row"
:column="column"
:column-index="columnIndex"
:summary="summary"
Expand Down
Loading

0 comments on commit 94cc2eb

Please sign in to comment.