Skip to content

Commit

Permalink
feat(table): add show option (#304) (#305)
Browse files Browse the repository at this point in the history
close #304 

---------

Co-authored-by: Kia King Ishii <kia.king.08@gmail.com>
  • Loading branch information
brc-dd and kiaking committed Jun 9, 2023
1 parent 91b9e7e commit 00b2e45
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 14 deletions.
26 changes: 26 additions & 0 deletions docs/components/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,32 @@ const options = useTable({
})
```

### Conditionally hide columns

You can conditionally hide columns by defining `show` option.

```ts
import { useTable } from '@globalbrain/sefirot/lib/composables/Table'

const options = useTable({
orders: ['name', 'age', 'email'],

columns: computed(() => ({
name: { ... },
age: { ... },
email: {
label: 'Email',
show: showEmail
}
}))
...
})
```

::: warning Limitation when using with `grow` option
When toggling the `show` option on a column with the `grow` option set to `true`, the auto-growing feature will be disabled. It is recommended to avoid using the `grow` option on columns that might be hidden.
:::

## Records & Cell options

The records are each row of data in the table and the cell is each item within the record. You may define various types of cells such as text, pill, or date.
Expand Down
20 changes: 14 additions & 6 deletions lib/components/STable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,28 @@ const body = shallowRef<HTMLElement | null>(null)
const block = shallowRef<HTMLElement | null>(null)
const row = shallowRef<HTMLElement | null>(null)
const ordersToShow = computed(() => {
return unref(props.options.orders).filter((key) => {
return unref(props.options.columns)[key]?.show !== false
})
})
watch(() => ordersToShow.value, handleResize)
const colToGrowAdjusted = ref(false)
const colToGrow = computed(() => {
if (colToGrowAdjusted.value) {
return -1
}
return unref(props.options.orders).findIndex((key) => {
return ordersToShow.value.findIndex((key) => {
return unref(props.options.columns)[key]?.grow
}) ?? -1
})
const nameOfColToGrow = computed(() => {
return unref(props.options.orders)[colToGrow.value]
return ordersToShow.value[colToGrow.value]
})
const cellOfColToGrow = computed(() => {
Expand Down Expand Up @@ -130,7 +138,7 @@ useResizeObserver(block, ([entry]) => {
const resizeObserver = useResizeObserver(head, handleResize)
function stopObserving() {
const orders = unref(props.options.orders)
const orders = ordersToShow.value
colWidths[orders[orders.length - 1]] = 'auto'
resizeObserver.stop()
}
Expand Down Expand Up @@ -236,7 +244,7 @@ function getCell(key: string, index: number) {
<div class="block" ref="block">
<div class="row" ref="row">
<STableItem
v-for="key in unref(options.orders)"
v-for="key in ordersToShow"
:key="key"
:name="key"
:class-name="unref(options.columns)[key].className"
Expand Down Expand Up @@ -281,7 +289,7 @@ function getCell(key: string, index: number) {
>
<div class="row" :class="isSummaryOrLastClass(rIndex)">
<STableItem
v-for="key in unref(options.orders)"
v-for="key in ordersToShow"
:key="key"
:name="key"
:class-name="unref(options.columns)[key].className"
Expand Down Expand Up @@ -313,7 +321,7 @@ function getCell(key: string, index: number) {
>
<div class="row" :class="isSummaryOrLastClass(rIndex)">
<STableItem
v-for="key in unref(options.orders)"
v-for="key in ordersToShow"
:key="key"
:name="key"
:class-name="unref(options.columns)[key].className"
Expand Down
1 change: 1 addition & 0 deletions lib/composables/Table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface TableColumn<V, R, SV, SR> {
resizable?: boolean
cell?: TableCell | TableColumnCellFn<V, R>
summaryCell?: TableCell | TableColumnCellFn<SV, SR>
show?: boolean
}

export type TableColumnCellFn<V, R> = (value: V, record: R) => TableCell
Expand Down
47 changes: 39 additions & 8 deletions stories/components/STable.01_Playground.story.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<script setup lang="ts">
import IconImageSquare from '@iconify-icons/ph/image-square'
import orderBy from 'lodash-es/orderBy'
import xor from 'lodash-es/xor'
import { orderBy, xor } from 'lodash-es'
import STable from 'sefirot/components/STable.vue'
import { createDropdown } from 'sefirot/composables/Dropdown'
import { useTable } from 'sefirot/composables/Table'
import { day } from 'sefirot/support/Day'
import { computed, markRaw, reactive, ref } from 'vue'
const title = 'Components / STable / 01. Playground'
interface Sort {
by: string
order: 'asc' | 'desc'
}
const title = 'Components / STable / 01. Playground'
const docs = '/components/table'
const optionsSelected = ref<string[]>([])
const sort = reactive<Sort>({
by: 'name',
order: 'asc'
Expand Down Expand Up @@ -187,7 +189,7 @@ const table = useTable({
'createdAt'
],
columns: {
columns: computed(() => ({
name: {
label: 'Name',
dropdown: dropdownName,
Expand All @@ -213,12 +215,14 @@ const table = useTable({
type: {
label: 'Type',
show: !optionsSelected.value.includes('hide-type'),
dropdown: dropdownType,
cell: { type: 'text', color: 'soft' }
},
width: {
label: 'Width',
show: !optionsSelected.value.includes('hide-width'),
dropdown: dropdownWidth,
cell: {
type: 'number',
Expand All @@ -241,6 +245,7 @@ const table = useTable({
tags: {
label: 'Tags',
show: !optionsSelected.value.includes('hide-tags'),
dropdown: dropdownTags,
cell: {
type: 'pills',
Expand All @@ -254,9 +259,27 @@ const table = useTable({
}
}
}
},
})),
menu: computed(() => [
{
label: 'Options',
state: optionsSelected.value.length ? 'indicate' : 'inactive',
dropdown: createDropdown([
{
type: 'filter',
selected: optionsSelected,
options: [
{ label: 'Hide type', value: 'hide-type', onClick: updateOptions },
{ label: 'Hide width', value: 'hide-width', onClick: updateOptions },
{ label: 'Hide tags', value: 'hide-tags', onClick: updateOptions }
]
}
])
}
]),
records: orderedData,
records: orderedData as any, // FIXME
total: computed(() => orderedData.value.length),
page: 1,
perPage: 5,
Expand All @@ -266,6 +289,10 @@ const table = useTable({
onReset: resetFilters
})
function updateOptions(value: string) {
optionsSelected.value = xor(optionsSelected.value, [value])
}
function updateSort(by: string, order: 'asc' | 'desc') {
sort.by = by
sort.order = order
Expand Down Expand Up @@ -296,7 +323,7 @@ function updateTagsFilter(value: string) {

<template>
<Story :title="title" source="Not available" auto-props-disabled>
<Board :title="title">
<Board :title="title" :docs="docs">
<STable class="table" :options="table" />
</Board>
</Story>
Expand All @@ -309,4 +336,8 @@ function updateTagsFilter(value: string) {
.table :deep(.col-width) { --table-col-width: 128px; }
.table :deep(.col-tags) { --table-col-width: 192px; }
.table :deep(.col-createdAt) { --table-col-width: 192px; }
.table {
margin-bottom: 16px;
}
</style>
25 changes: 25 additions & 0 deletions tests/components/STable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,29 @@ describe('components/STable', () => {
expect(wrapper.findAll('.summary .text')[1].text()).toBe('100')
})
})

describe('conditional hide', () => {
test('it hides column when `show` is set to `false`', () => {
const table = useTable({
orders: ['name', 'amount'],
columns: {
name: { label: 'Name' },
amount: { label: 'Amount', show: false }
},
records: [
{ name: 'Item 1', amount: 10 },
{ name: 'Item 2', amount: 90 }
]
})

const wrapper = mount(STable, {
props: {
options: table
}
})

expect(wrapper.find('.STable .head .col-name').exists()).toBe(true)
expect(wrapper.find('.STable .head .col-amount').exists()).toBe(false)
})
})
})

0 comments on commit 00b2e45

Please sign in to comment.