@soft-stech/bootsman-ui-shadcn 1.1.16 → 1.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BuiDataTable.vue_vue_type_script_setup_true_lang-CcM2IC6f.js +219 -0
- package/dist/{variables-BFHGTsK4.js → BuiPaginationCommon.vue_vue_type_script_setup_true_lang-dh6FvXRc.js} +4 -3
- package/dist/{BuiDataTable.vue_vue_type_script_setup_true_lang-DY56g6bi.js → BuiTableRowSubrow.vue_vue_type_script_setup_true_lang-zozuVlJm.js} +553 -670
- package/dist/assets/main.css +1 -1
- package/dist/components/ui/pagination/BuiPaginationCommon.js +1 -1
- package/dist/components/ui/pagination/index.js +1 -1
- package/dist/components/ui/table/BuiDataTable.js +1 -1
- package/dist/components/ui/table/BuiDataTable.vue.d.ts +10 -1
- package/dist/components/ui/table/BuiTableRowSubrow.js +4 -0
- package/dist/components/ui/table/BuiTableRowSubrow.vue.d.ts +35 -0
- package/dist/components/ui/table/index.d.ts +1 -0
- package/dist/components/ui/table/index.js +18 -16
- package/dist/index.js +315 -312
- package/package.json +2 -1
- package/src/components/stories/{Collapsible.story.vue → BuiCollapsible.story.vue} +1 -1
- package/src/components/stories/BuiDataTable.story.vue +59 -17
- package/src/components/stories/data/tasks.json +2 -1
- package/src/components/ui/pagination/BuiPaginationCommon.vue +1 -1
- package/src/components/ui/table/BuiDataTable.vue +58 -15
- package/src/components/ui/table/BuiTableRowSubrow.vue +30 -0
- package/src/components/ui/table/index.ts +1 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@soft-stech/bootsman-ui-shadcn",
|
3
|
-
"version": "1.1.
|
3
|
+
"version": "1.1.18",
|
4
4
|
"type": "module",
|
5
5
|
"files": [
|
6
6
|
"dist",
|
@@ -60,6 +60,7 @@
|
|
60
60
|
"bumpp": "9.4.0",
|
61
61
|
"eslint": "8.57.0",
|
62
62
|
"eslint-plugin-vue": "9.24.0",
|
63
|
+
"fast-sort": "^3.4.0",
|
63
64
|
"glob": "10.3.10",
|
64
65
|
"histoire": "0.17.15",
|
65
66
|
"jsdom": "23.2.0",
|
@@ -8,7 +8,7 @@ const isOpen = ref(false)
|
|
8
8
|
|
9
9
|
<template>
|
10
10
|
<Story title="BuiCollapsible" autoPropsDisabled>
|
11
|
-
<Variant :key="`variant-default`" :title="`
|
11
|
+
<Variant :key="`variant-default`" :title="`Default`">
|
12
12
|
<div class="flex justify-center pt-12">
|
13
13
|
<BuiCollapsible v-model:open="isOpen" class="w-[350px] space-y-2">
|
14
14
|
<div class="flex items-center justify-between space-x-4 px-4">
|
@@ -1,16 +1,13 @@
|
|
1
1
|
<script setup lang="ts">
|
2
2
|
import { BuiDataTable } from '@/components/ui/table'
|
3
|
-
import
|
4
|
-
ColumnDef,
|
5
|
-
PaginationState,
|
6
|
-
RowSelectionState,
|
7
|
-
SortingState
|
8
|
-
} from '@tanstack/vue-table'
|
9
|
-
import { h, ref } from 'vue'
|
10
|
-
import { z } from 'zod'
|
11
|
-
import { BuiButton, BuiCheckbox } from '@/index'
|
3
|
+
import { BuiButton, BuiCheckbox, BuiTabs, BuiTabsList, BuiTabsTrigger } from '@/index'
|
12
4
|
import { tableColumnSortCommon } from '@/lib/utils'
|
5
|
+
import type { ColumnDef, PaginationState, Row, RowSelectionState } from '@tanstack/vue-table'
|
6
|
+
import { sort, type ISortByObjectSorter } from 'fast-sort'
|
13
7
|
import { logEvent } from 'histoire/client'
|
8
|
+
import { AlignJustifyIcon, FolderIcon } from 'lucide-vue-next'
|
9
|
+
import { computed, h, ref } from 'vue'
|
10
|
+
import { z } from 'zod'
|
14
11
|
import tasks from './data/tasks.json'
|
15
12
|
|
16
13
|
const taskSchema = z.object({
|
@@ -18,7 +15,8 @@ const taskSchema = z.object({
|
|
18
15
|
title: z.string(),
|
19
16
|
status: z.string(),
|
20
17
|
label: z.string(),
|
21
|
-
priority: z.string()
|
18
|
+
priority: z.string(),
|
19
|
+
errorMessage: z.string().optional()
|
22
20
|
})
|
23
21
|
type Task = z.infer<typeof taskSchema>
|
24
22
|
const columns: ColumnDef<Task>[] = [
|
@@ -59,7 +57,8 @@ const columns: ColumnDef<Task>[] = [
|
|
59
57
|
]
|
60
58
|
const data = ref<Task[]>(tasks)
|
61
59
|
|
62
|
-
|
60
|
+
type TaskSortingState = { id: keyof Task; desc: boolean }
|
61
|
+
const sorting = ref<TaskSortingState[]>([{ id: 'id', desc: false }])
|
63
62
|
const pagination = ref<PaginationState>({
|
64
63
|
pageIndex: 0,
|
65
64
|
pageSize: 10
|
@@ -71,14 +70,42 @@ function updateSelection(val: RowSelectionState) {
|
|
71
70
|
logEvent('selection was changed', val)
|
72
71
|
selection.value = val
|
73
72
|
}
|
73
|
+
|
74
|
+
type GroupBy = 'none' | 'status'
|
75
|
+
const groupBy = ref<GroupBy>('none')
|
76
|
+
const groupLabels = {
|
77
|
+
status: 'Status'
|
78
|
+
}
|
79
|
+
|
80
|
+
const sortedData = computed(() => {
|
81
|
+
const sortDirection = (sorting.value[0].desc ? 'desc' : 'asc') as 'asc'
|
82
|
+
const sortColumn = sorting.value[0].id
|
83
|
+
const groupByStr = groupBy.value
|
84
|
+
|
85
|
+
const sortBy: ISortByObjectSorter<Task> | ISortByObjectSorter<Task>[] = [
|
86
|
+
{
|
87
|
+
[sortDirection]: groupByStr === 'none' ? sortColumn : [(row) => row[groupByStr], sortColumn]
|
88
|
+
}
|
89
|
+
]
|
90
|
+
|
91
|
+
return sort(data.value).by([...sortBy])
|
92
|
+
})
|
93
|
+
|
94
|
+
function renderSubComponent(row: Row<Task>) {
|
95
|
+
if (row.original.errorMessage) {
|
96
|
+
return () => h('span', { style: 'color: red' }, `Subrow: ${row.original.errorMessage}`)
|
97
|
+
} else {
|
98
|
+
return undefined
|
99
|
+
}
|
100
|
+
}
|
74
101
|
</script>
|
75
102
|
|
76
103
|
<template>
|
77
104
|
<Story title="BuiDataTable" autoPropsDisabled :layout="{ type: 'grid', width: '95%' }">
|
78
|
-
<Variant key="variant" title="Sorting, Pagination">
|
105
|
+
<Variant key="variant" title="Sorting, Pagination, Grouping, Subrow">
|
79
106
|
<BuiDataTable
|
80
107
|
:columns="columns"
|
81
|
-
:data="
|
108
|
+
:data="sortedData"
|
82
109
|
v-model:sorting="sorting"
|
83
110
|
v-model:pagination="pagination"
|
84
111
|
@update:selection="updateSelection"
|
@@ -86,14 +113,29 @@ function updateSelection(val: RowSelectionState) {
|
|
86
113
|
class="caption-top"
|
87
114
|
:manualPagination="false"
|
88
115
|
:getRowId="(row) => row.id"
|
116
|
+
:groupBy="groupBy === 'none' ? undefined : groupBy"
|
117
|
+
:groupLabels="groupLabels"
|
118
|
+
:renderSubComponent="renderSubComponent"
|
89
119
|
>
|
90
120
|
<template #caption="{ table }">
|
91
121
|
<div class="flex justify-between">
|
92
122
|
<BuiButton variant="outline">Download YAML</BuiButton>
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
123
|
+
|
124
|
+
<BuiTabs v-model="groupBy">
|
125
|
+
<BuiTabsList class="grid w-full grid-cols-2" :variant="'default'">
|
126
|
+
<BuiTabsTrigger value="none" :variant="'default'"
|
127
|
+
><AlignJustifyIcon
|
128
|
+
/></BuiTabsTrigger>
|
129
|
+
<BuiTabsTrigger value="status" :variant="'default'">
|
130
|
+
<FolderIcon />
|
131
|
+
</BuiTabsTrigger>
|
132
|
+
</BuiTabsList>
|
133
|
+
</BuiTabs>
|
134
|
+
|
135
|
+
<span>
|
136
|
+
{{ table.getFilteredSelectedRowModel().rows?.length }} of
|
137
|
+
{{ table.getFilteredRowModel().rows?.length }} row(s) selected
|
138
|
+
</span>
|
97
139
|
</div>
|
98
140
|
</template>
|
99
141
|
</BuiDataTable>
|
@@ -417,7 +417,8 @@
|
|
417
417
|
"title": "Backing up the driver won't do anything, we need to parse the redundant RAM pixel!",
|
418
418
|
"status": "done",
|
419
419
|
"label": "feature",
|
420
|
-
"priority": "medium"
|
420
|
+
"priority": "medium",
|
421
|
+
"errorMessage": "ERROR"
|
421
422
|
},
|
422
423
|
{
|
423
424
|
"id": "TASK-1427",
|
@@ -46,7 +46,7 @@ const pageSizeString = computed({
|
|
46
46
|
:itemsPerPage="pageSize"
|
47
47
|
v-model:page="pageIndex"
|
48
48
|
>
|
49
|
-
<BuiPaginationList class="flex items-center justify-center gap-2">
|
49
|
+
<BuiPaginationList class="relative flex items-center justify-center gap-2">
|
50
50
|
<p class="text-sm text-muted-foreground">Items per page</p>
|
51
51
|
<BuiSelect v-model.number="pageSizeString">
|
52
52
|
<BuiSelectTrigger class="mr-2 w-[70px]">
|
@@ -1,10 +1,18 @@
|
|
1
1
|
<script setup lang="ts" generic="TData, TValue">
|
2
|
+
import {
|
3
|
+
BuiCollapsible,
|
4
|
+
BuiCollapsibleContent,
|
5
|
+
BuiCollapsibleTrigger
|
6
|
+
} from '@/components/ui/collapsible'
|
7
|
+
import { BuiPaginationCommon, type PageSize } from '@/components/ui/pagination'
|
8
|
+
import BuiTableRowSubrow from '@/components/ui/table/BuiTableRowSubrow.vue'
|
9
|
+
import { valueUpdater } from '@/lib/utils'
|
2
10
|
import type {
|
3
11
|
ColumnDef,
|
4
|
-
SortingState,
|
5
12
|
PaginationState,
|
13
|
+
Row,
|
6
14
|
RowSelectionState,
|
7
|
-
|
15
|
+
SortingState
|
8
16
|
} from '@tanstack/vue-table'
|
9
17
|
import {
|
10
18
|
FlexRender,
|
@@ -13,6 +21,7 @@ import {
|
|
13
21
|
getSortedRowModel,
|
14
22
|
useVueTable
|
15
23
|
} from '@tanstack/vue-table'
|
24
|
+
import { computed } from 'vue'
|
16
25
|
import {
|
17
26
|
BuiTable,
|
18
27
|
BuiTableBody,
|
@@ -24,9 +33,6 @@ import {
|
|
24
33
|
BuiTableHeader,
|
25
34
|
BuiTableRow
|
26
35
|
} from './'
|
27
|
-
import { BuiPaginationCommon, type PageSize } from '@/components/ui/pagination'
|
28
|
-
import { valueUpdater } from '@/lib/utils'
|
29
|
-
import { computed } from 'vue'
|
30
36
|
|
31
37
|
const props = withDefaults(
|
32
38
|
defineProps<{
|
@@ -37,7 +43,10 @@ const props = withDefaults(
|
|
37
43
|
totalItems?: number
|
38
44
|
manualPagination?: boolean
|
39
45
|
manualSorting?: boolean
|
46
|
+
groupBy?: keyof TData
|
47
|
+
groupLabels?: { [key in keyof TData]?: string }
|
40
48
|
getRowId?: (originalRow: TData, index: number, parent?: Row<TData>) => string
|
49
|
+
renderSubComponent?: (row: Row<TData>) => (() => any) | undefined
|
41
50
|
}>(),
|
42
51
|
{ pageSize: 10, showPagination: true, manualPagination: true, manualSorting: true, totalItems: 0 }
|
43
52
|
)
|
@@ -105,6 +114,17 @@ const pageIndex = computed({
|
|
105
114
|
table.setPageIndex(index - 1)
|
106
115
|
}
|
107
116
|
})
|
117
|
+
|
118
|
+
const groupedRows = computed(() => {
|
119
|
+
if (!props.groupBy) return null
|
120
|
+
|
121
|
+
return table.getRowModel().rows.reduce((acc, row) => {
|
122
|
+
const col = row.getValue(props.groupBy! as string) as string
|
123
|
+
acc[col] = acc[col] || []
|
124
|
+
acc[col].push(row)
|
125
|
+
return acc
|
126
|
+
}, Object.create(null))
|
127
|
+
})
|
108
128
|
</script>
|
109
129
|
|
110
130
|
<template>
|
@@ -123,21 +143,44 @@ const pageIndex = computed({
|
|
123
143
|
</BuiTableHeader>
|
124
144
|
<BuiTableBody>
|
125
145
|
<template v-if="table.getRowModel().rows?.length">
|
126
|
-
<
|
127
|
-
v-for="
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
146
|
+
<template v-if="props.groupBy && groupedRows">
|
147
|
+
<BuiCollapsible asChild v-for="(value, key) in groupedRows" :key="key" :open="true">
|
148
|
+
<BuiCollapsibleTrigger asChild>
|
149
|
+
<BuiTableRow class="bg-foreground/[0.04]">
|
150
|
+
<BuiTableCell :colspan="columns.length" class="!pb-0">
|
151
|
+
<div class="inline-block rounded-t bg-background px-4 py-3">
|
152
|
+
{{ props.groupLabels && props.groupLabels[props.groupBy] }}: {{ key }}
|
153
|
+
</div>
|
154
|
+
</BuiTableCell>
|
155
|
+
</BuiTableRow>
|
156
|
+
</BuiCollapsibleTrigger>
|
157
|
+
<BuiCollapsibleContent asChild>
|
158
|
+
<template v-for="row in value" :key="row.id">
|
159
|
+
<BuiTableRowSubrow
|
160
|
+
:columns="props.columns"
|
161
|
+
:row="row"
|
162
|
+
:renderSubComponent="props.renderSubComponent"
|
163
|
+
/>
|
164
|
+
</template>
|
165
|
+
</BuiCollapsibleContent>
|
166
|
+
</BuiCollapsible>
|
167
|
+
</template>
|
168
|
+
|
169
|
+
<template v-else>
|
170
|
+
<template v-for="row in table.getRowModel().rows" :key="row.id">
|
171
|
+
<BuiTableRowSubrow
|
172
|
+
:columns="props.columns"
|
173
|
+
:row="row"
|
174
|
+
:renderSubComponent="props.renderSubComponent"
|
175
|
+
/>
|
176
|
+
</template>
|
177
|
+
</template>
|
135
178
|
</template>
|
136
179
|
<template v-else>
|
137
180
|
<BuiTableEmpty :colspan="columns.length">No data</BuiTableEmpty>
|
138
181
|
</template>
|
139
182
|
</BuiTableBody>
|
140
|
-
<BuiTableFooter v-if="showPagination && table.getPageCount()">
|
183
|
+
<BuiTableFooter v-if="showPagination && table.getPageCount() > 1">
|
141
184
|
<BuiTableRow>
|
142
185
|
<BuiTableCell :colspan="columns.length">
|
143
186
|
<BuiPaginationCommon
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<script setup lang="ts" generic="TData, TValue">
|
2
|
+
import { BuiTableCell, BuiTableRow } from '@/components/ui/table'
|
3
|
+
import { FlexRender, type ColumnDef, type Row } from '@tanstack/vue-table'
|
4
|
+
|
5
|
+
const props = defineProps<{
|
6
|
+
row: Row<TData>
|
7
|
+
renderSubComponent?: (row: Row<TData>) => (() => any) | undefined
|
8
|
+
columns: ColumnDef<TData, TValue>[]
|
9
|
+
}>()
|
10
|
+
</script>
|
11
|
+
|
12
|
+
<template>
|
13
|
+
<BuiTableRow
|
14
|
+
:data-state="row.getIsSelected() ? 'selected' : undefined"
|
15
|
+
:class="props.renderSubComponent?.(row) ? 'border-b-0' : ''"
|
16
|
+
>
|
17
|
+
<BuiTableCell v-for="cell in row.getVisibleCells()" :key="cell.id">
|
18
|
+
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
19
|
+
</BuiTableCell>
|
20
|
+
</BuiTableRow>
|
21
|
+
|
22
|
+
<BuiTableRow
|
23
|
+
v-if="props.renderSubComponent?.(row)"
|
24
|
+
:data-state="row.getIsSelected() ? 'selected' : undefined"
|
25
|
+
>
|
26
|
+
<BuiTableCell :colspan="columns.length" class="pt-0">
|
27
|
+
<component :is="props.renderSubComponent?.(row)?.()"></component>
|
28
|
+
</BuiTableCell>
|
29
|
+
</BuiTableRow>
|
30
|
+
</template>
|
@@ -4,6 +4,7 @@ export { default as BuiTableCell } from './BuiTableCell.vue'
|
|
4
4
|
export { default as BuiTableHead } from './BuiTableHead.vue'
|
5
5
|
export { default as BuiTableHeader } from './BuiTableHeader.vue'
|
6
6
|
export { default as BuiTableRow } from './BuiTableRow.vue'
|
7
|
+
export { default as BuiTableRowSubrow } from './BuiTableRowSubrow.vue'
|
7
8
|
export { default as BuiTableCaption } from './BuiTableCaption.vue'
|
8
9
|
export { default as BuiTableEmpty } from './BuiTableEmpty.vue'
|
9
10
|
export { default as BuiTableFooter } from './BuiTableFooter.vue'
|