Skip to content

Commit

Permalink
feat(table): support selecting single row (#477)
Browse files Browse the repository at this point in the history
Co-authored-by: Kia King Ishii <[email protected]>
  • Loading branch information
brc-dd and kiaking authored Feb 21, 2024
1 parent 85752d5 commit e54cbae
Show file tree
Hide file tree
Showing 4 changed files with 361 additions and 67 deletions.
4 changes: 2 additions & 2 deletions lib/components/SInputRadio.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const props = defineProps<{
checkIcon?: IconifyIcon | DefineComponent
checkText?: string
checkColor?: Color
text: string
text?: string
disabled?: boolean
modelValue: boolean
validation?: Validatable
Expand Down Expand Up @@ -68,7 +68,7 @@ function onClick() {
<div class="check" />
</div>

<p class="text">{{ text }}</p>
<p class="text" v-if="text">{{ text }}</p>
</div>
</div>
<template v-if="$slots.info" #info><slot name="info" /></template>
Expand Down
53 changes: 31 additions & 22 deletions lib/components/STable.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup lang="ts" generic="S extends any[] | any | undefined = undefined">
import { useVirtualizer } from '@tanstack/vue-virtual'
import { useResizeObserver } from '@vueuse/core'
import xor from 'lodash-es/xor'
Expand All @@ -15,6 +15,7 @@ import {
import { type Table } from '../composables/Table'
import { getTextWidth } from '../support/Text'
import SInputCheckbox from './SInputCheckbox.vue'
import SInputRadio from './SInputRadio.vue'
import SSpinner from './SSpinner.vue'
import STableCell from './STableCell.vue'
import STableColumn from './STableColumn.vue'
Expand All @@ -24,11 +25,11 @@ import STableItem from './STableItem.vue'
const props = defineProps<{
options: Table
selected?: unknown[]
selected?: S
}>()
const emit = defineEmits<{
(e: 'update:selected', value: unknown[]): void
(e: 'update:selected', value: S): void
}>()
const head = shallowRef<HTMLElement | null>(null)
Expand All @@ -41,7 +42,7 @@ const ordersToShow = computed(() => {
const show = unref(props.options.columns)[key]?.show
return toValue(show) !== false
})
if (!props.selected) {
if (props.selected === undefined) {
return orders
}
return ['__select', ...orders]
Expand Down Expand Up @@ -126,7 +127,7 @@ const recordsWithSummary = computed(() => {
})
const indexes = computed(() => {
if (!props.selected) {
if (props.selected === undefined) {
return []
}
const records = unref(props.options.records) ?? []
Expand All @@ -139,9 +140,6 @@ const selectedIndexes = reactive(new Set())
const control = computed({
get() {
if (!props.selected) {
return false
}
const selected = indexes.value.filter((index) => {
return selectedIndexes.has(index)
})
Expand All @@ -165,12 +163,11 @@ const control = computed({
})
watch(indexes, (newValue, oldValue) => {
if (!props.selected) {
return
if (Array.isArray(props.selected)) {
xor(newValue, oldValue).forEach((index) => {
selectedIndexes.delete(index)
})
}
xor(newValue, oldValue).forEach((index) => {
selectedIndexes.delete(index)
})
})
const virtualizerOptions = computed(() => ({
Expand Down Expand Up @@ -343,8 +340,12 @@ function getCell(key: string, index: number) {
return (isSummary(index) && col?.summaryCell) ? col?.summaryCell : col?.cell
}
function updateSelected(selected: unknown[]) {
if (xor(selected, props.selected ?? []).length) {
function updateSelected(selected: any) {
if (Array.isArray(props.selected)) {
if (xor(selected, props.selected ?? []).length) {
emit('update:selected', selected)
}
} else {
emit('update:selected', selected)
}
}
Expand All @@ -361,7 +362,7 @@ function updateSelected(selected: unknown[]) {
:actions="unref(options.actions)"
:borderless="unref(options.borderless)"
:on-reset="options.onReset"
:selected="selected"
:selected="Array.isArray(selected) ? selected : undefined"
/>

<div class="table" role="grid">
Expand Down Expand Up @@ -389,7 +390,7 @@ function updateSelected(selected: unknown[]) {
@resize="(value) => updateColWidth(key, value, true)"
>
<SInputCheckbox
v-if="key === '__select' && unref(options.records)?.length"
v-if="Array.isArray(selected) && key === '__select' && unref(options.records)?.length"
v-model="control"
/>
</STableColumn>
Expand Down Expand Up @@ -444,11 +445,18 @@ function updateSelected(selected: unknown[]) {
:record="recordsWithSummary[index]"
:records="unref(options.records)!"
>
<SInputCheckbox
v-if="key === '__select' && !isSummary(index)"
:value="selectedIndexes.has(indexes[index])"
@change="c => selectedIndexes[c ? 'add' : 'delete'](indexes[index])"
/>
<template v-if="key === '__select' && !isSummary(index)">
<SInputCheckbox
v-if="Array.isArray(selected)"
:model-value="selectedIndexes.has(indexes[index])"
@update:model-value="c => selectedIndexes[c ? 'add' : 'delete'](indexes[index])"
/>
<SInputRadio
v-else
:model-value="selected === indexes[index]"
@update:model-value="c => updateSelected(c ? indexes[index] : null)"
/>
</template>
</STableCell>
</STableItem>
</div>
Expand Down Expand Up @@ -598,6 +606,7 @@ function updateSelected(selected: unknown[]) {
align-items: center;
padding: 0 16px;
min-height: 40px;
user-select: none;
}
:deep(.container) {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
},
"devDependencies": {
"@globalbrain/eslint-config": "^1.5.2",
"@histoire/plugin-vue": "0.17.9",
"@histoire/plugin-vue": "^0.16.5",
"@iconify-icons/ph": "^1.2.5",
"@iconify-icons/ri": "^1.2.10",
"@iconify/vue": "^4.1.1",
Expand All @@ -91,7 +91,7 @@
"eslint": "^8.56.0",
"fuse.js": "^7.0.0",
"happy-dom": "^13.3.8",
"histoire": "0.17.9",
"histoire": "^0.16.5",
"lodash-es": "^4.17.21",
"markdown-it": "^14.0.0",
"normalize.css": "^8.0.1",
Expand Down
Loading

0 comments on commit e54cbae

Please sign in to comment.