Skip to content

Commit

Permalink
Moves away from display: flex and uses display: table instead
Browse files Browse the repository at this point in the history
  • Loading branch information
gurupras committed Jun 6, 2022
1 parent d210946 commit dea0425
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 74 deletions.
6 changes: 2 additions & 4 deletions src/components/column.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export default defineComponent({
},
onMouseMove () {
const dx = mouse.x - this.x
this.$emit('resize', `${this.w + dx}px`)
this.$emit('resize', this.w + dx)
},
onMouseUp () {
document.removeEventListener('mousemove', this.onMouseMove)
Expand All @@ -88,16 +88,14 @@ export default defineComponent({
mounted () {
const styles = getComputedStyle(this.$el)
const width = parseInt(styles.width, 10)
this.$emit('resize', `${width}px`)
this.$emit('resize', width)
}
})
</script>

<style lang="scss" scoped>
.column-root {
position: relative;
display: flex;
align-items: center;
text-align: left;
border: 1px solid grey;
&:last-child {
Expand Down
5 changes: 2 additions & 3 deletions src/components/fs-tree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,11 @@ describe('FSTree', () => {
expect(wrapper.findAllComponents(Column).length).toBe(2)
})
test('Applies column-specific styles', async () => {
const width = '24px'
const width = 24
wrapper.vm.columnWidths[NameColumn.label] = width
await nextTick()
const style = getComputedStyle(wrapper.find('.column-header').element)
expect(style.getPropertyValue('min-width')).toEqual(width)
expect(style.getPropertyValue('max-width')).toEqual(width)
expect(style.getPropertyValue('width')).toEqual(`${width}px`)
})
test('Binds column label properly', async () => {
expect(wrapper.findComponent(Column).vm.label).toEqual(NameColumn.label)
Expand Down
220 changes: 155 additions & 65 deletions src/components/fs-tree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,43 @@
tabindex="0"
@click="onClick"
@keyup="onKeyUp">
<div class="header-root">
<Column v-for="col in columns" :key="col.label"
class="column-header"
:style="columnStyles[col.label]"
:label="col.label"
:sort="sortColumn.label === col.label ? sortOrder : SortOrder.Undefined"
@update:sort="(val: SortOrder) => onSort(col, val)"
@resize="(val: string) => { columnWidths[col.label] = val }"/>
</div>
<div class="body-root">
<RecycleScroller class="scroller"
ref="scroller"
:items="contentsArray"
:item-size="22"
v-slot="{ item, index }: { item: import('@/js/store').DepthEntry, index: number }">
<div class="entry-row" :class="{selected: selectionPlugin.selected.value[item.id], focused: index === selectionPlugin.focusedIndex.value}">
<div v-for="col in columns" :key="item.id + '-' + col.label" class="entry-column" :style="columnStyles[col.label]">
<component :is="col.component"
:entry-id="item.id"
:entry="item.entry"
:depth="item.depth"
:store="store"
:key-field="col.keyField"
:config="config"
:parent-entry="store.isUpOneLevelEntry(item.entry)"
@click.stop="($event: MouseEvent) => onRowClick($event, item, index)"
@toggle-expand="($event: MouseEvent) => onToggleExpand($event, item.id)"
@dblclick.stop="($event: MouseEvent) => onRowDoubleClick($event, item, index)"/>
@resize="onTableResize">
<template #before>
<div class="table header-root">
<div class="table-row">
<Column v-for="(col, idx) in columns" :key="col.label"
class="table-cell column-header"
:style="columnStyles[col.label]"
:label="col.label"
:sort="sortColumn.label === col.label ? sortOrder : SortOrder.Undefined"
:ref="'column-' + col.label"
@update:sort="(val: SortOrder) => onSort(col, val)"
@resize="(val: number) => onResizeColumn(idx, val)"/>
</div>
</div>
</template>
<template v-slot="{ item, index }: { item: import('@/js/store').DepthEntry, index: number }">
<div class="entry-row" :class="{selected: selectionPlugin.selected.value[item.id], focused: index === selectionPlugin.focusedIndex.value}">
<div v-for="col in columns" :key="item.id + '-' + col.label" class="entry-column table-cell" :style="columnStyles[col.label]">
<component :is="col.component"
:entry-id="item.id"
:entry="item.entry"
:depth="item.depth"
:store="store"
:key-field="col.keyField"
:config="config"
:parent-entry="store.isUpOneLevelEntry(item.entry)"
@click.stop="($event: MouseEvent) => onRowClick($event, item, index)"
@toggle-expand="($event: MouseEvent) => onToggleExpand($event, item.id)"
@dblclick.stop="($event: MouseEvent) => onRowDoubleClick($event, item, index)"/>
</div>
</div>
</template>
</RecycleScroller>
</div>
</div>
Expand All @@ -41,6 +49,7 @@
import { DepthEntry, DepthEntryMap, RootSymbol, Store, StoreEntry } from '@/js/store'
import { defineComponent } from '@vue/runtime-core'
import type { PropType } from 'vue'
import { ref, computed } from 'vue'
import { Column, NameColumn, SizeColumn, DateModifiedColumn, SortOrder } from '@/js/column'
import { RecycleScroller } from 'vue-virtual-scroller'
Expand Down Expand Up @@ -84,13 +93,35 @@ export default defineComponent({
}
}
},
setup () {
setup (props) {
const el = ref(null)
const selectionPlugin = SelectionPlugin()
const keyboardNavigationPlugin = KeyboardNavigationPlugin(selectionPlugin)
const width = ref(0)
const columnWidths = ref<Record<string, number>>({})
const columnStyles = computed(() => {
const result: Record<string, Record<string, string>> = {}
for (const column of props.columns) {
const label = column.label
const width = columnWidths.value[label]
result[label] = {}
if (width) {
result[label] = {
width: `${width}px`
}
}
}
return result
})
return {
el,
selectionPlugin,
keyboardNavigationPlugin,
SortOrder
SortOrder,
columnWidths,
columnStyles,
width
}
},
watch: {
Expand All @@ -99,21 +130,6 @@ export default defineComponent({
}
},
computed: {
columnStyles (): any {
const result: any = {}
for (const column of this.columns) {
const label = column.label
const width = this.columnWidths[label]
result[label] = {}
if (width) {
result[label] = {
'min-width': width,
'max-width': width
}
}
}
return result
},
contentsArray (): DepthEntry[] {
return Object.values(this.contents)
}
Expand All @@ -122,7 +138,6 @@ export default defineComponent({
return {
sortColumn: null as any as Column,
sortOrder: SortOrder.Undefined,
columnWidths: {} as any,
contents: {} as DepthEntryMap
}
},
Expand Down Expand Up @@ -191,6 +206,52 @@ export default defineComponent({
})
await this.$nextTick()
this.selectionPlugin?.onContentsUpdated(this.contentsArray, this.contents)
},
onResizeColumn (index: number, newWidth: number) {
const column = this.columns[index]
const nextColumn = this.columns[index + 1]
if (nextColumn) {
// This can happen if the last column emits an initial ressize
const currentWidth = this.columnWidths[column.label]
if (currentWidth !== undefined) {
const nextColumnWidth = parseInt(this.columnStyles[nextColumn.label].width, 10)
const diff = newWidth - currentWidth
const newNNextColumnWidth = nextColumnWidth - diff
this.columnWidths[nextColumn.label] = newNNextColumnWidth
}
}
// Resizing this column involves reducing the width of this column and increasing the width of the next column such that the total width remains the same
// TODO: Maybe store width as a property on $el
// Add this to the next column
this.columnWidths[column.label] = newWidth
},
onTableResize () {
const style = getComputedStyle(this.$refs.scroller.$el)
const newWidth = parseInt(style.width, 10)
this.width = newWidth
// Need to resize all columns to stay wiithin this new width
const currentColumnWidths: Record<string, number> = {}
const newColumnWidths: Record<string, number> = {}
const oldWidth = Object.entries(this.columnWidths).map(([label, width]: [label: string, width: number]) => {
currentColumnWidths[label] = width
return width
}).reduce((a, b) => a + b, 0)
let sum = 0
for (const column of this.columns) {
const { label } = column
const ratio = currentColumnWidths[label] / oldWidth
const width = newWidth * ratio
newColumnWidths[label] = width
sum += width
}
const diff = newWidth - sum
if (diff !== 0) {
// Add the diff to the last column
newColumnWidths[this.columns[this.columns.length - 1].label] += diff
}
this.columnWidths = newColumnWidths
}
},
beforeMount () {
Expand Down Expand Up @@ -223,26 +284,35 @@ export default defineComponent({
font-family: system-ui,Ubuntu,Droid Sans,sans-serif;
font-size: 14px;
.table {
display: table;
table-layout: fixed;
width: 100%;
}
.table-row {
display: table-row;
width: 100%;
}
.table-cell {
display: table-cell;
}
.header-root {
display: flex;
flex-direction: row;
align-items: center;
.column-header {
flex: 1;
width: 100%;
align-items: center;
overflow: hidden;
&:last-child {
:deep(.resizer) {
display: none;
}
}
}
}
.body-root {
flex: 1;
overflow-y: hidden;
overflow-x: hidden;
.scroller {
height: 100%;
overflow-y: auto;
}
.selected {
background-color: var(--fstree-row-selected-background-color);
Expand All @@ -254,23 +324,43 @@ export default defineComponent({
outline-offset: -1px;
}
:deep(.scroller > div:first-child) {
margin-top: 1px;
}
.entry-row {
display: flex;
flex-direction: row;
flex: 1;
.scroller {
height: 100%;
width: 100%;
height: var(--fstree-row-height);
line-height: var(--fstree-row-line-height);
&:not(.selected):hover {
background-color: var(--fstree-row-hover-color);
overflow-y: auto;
overflow-x: hidden;
:deep(.scroller > div:first-child) {
margin-top: 1px;
}
.entry-column {
flex: 1;
:deep(.vue-recycle-scroller__item-wrapper) {
display: table;
table-layout: fixed;
height: 100%;
.vue-recycle-scroller__item-view {
display: table-row;
height: var(--fstree-row-height);
line-height: var(--fstree-row-line-height);
}
}
.entry-row {
display: flex;
width: 100%;
height: var(--fstree-row-height);
line-height: var(--fstree-row-line-height);
&:not(.selected):hover {
background-color: var(--fstree-row-hover-color);
}
.entry-column {
display: table-cell;
max-height: var(--fstree-row-height);
height: var(--fstree-row-height);
line-height: var(--fstree-row-line-height);
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/name-node.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ export default defineComponent({
&.expand-on-row-click {
cursor: pointer;
}
height: var(--fstree-row-height);
line-height: var(--fstree-row-line-height);
height: inherit;
line-height: inherit;
font-size: var(--fstree-name-node-font-size);
.row {
Expand Down

0 comments on commit dea0425

Please sign in to comment.