@soft-stech/bootsman-ui-shadcn 2.0.20 → 2.0.22
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/BuiPaginationCommon.vue_vue_type_script_setup_true_lang-BOuWIF4c.js +179 -0
- package/dist/BuiScrollArea.vue_vue_type_script_setup_true_lang-lyWD8KAT.js +144 -0
- package/dist/{BuiScrollBar.vue_vue_type_script_setup_true_lang-cV0od8j0.js → BuiScrollBar.vue_vue_type_script_setup_true_lang-BCvjzEmb.js} +4 -4
- package/dist/BuiTable.vue_vue_type_script_setup_true_lang-BQRl7YR1.js +37 -0
- package/dist/{BuiTableEmpty.vue_vue_type_script_setup_true_lang-Da4qHIWo.js → BuiTableEmpty.vue_vue_type_script_setup_true_lang-CuffOAuP.js} +1 -1
- package/dist/BuiTableRow.vue_vue_type_script_setup_true_lang-BQnadEa7.js +51 -0
- package/dist/components/input/index.js +22 -22
- package/dist/components/pagination/BuiPaginationCommon.js +1 -1
- package/dist/components/pagination/BuiPaginationCommon.vue.d.ts +4 -0
- package/dist/components/pagination/index.js +1 -1
- package/dist/components/scroll-area/BuiScrollArea.js +1 -1
- package/dist/components/scroll-area/BuiScrollArea.vue.d.ts +256 -2
- package/dist/components/scroll-area/BuiScrollBar.js +1 -1
- package/dist/components/scroll-area/index.js +2 -2
- package/dist/components/table/BuiDataTable.vue.d.ts +9 -4
- package/dist/components/table/BuiTable.js +1 -1
- package/dist/components/table/BuiTable.vue.d.ts +1487 -2
- package/dist/components/table/BuiTableEmpty.js +1 -1
- package/dist/components/table/BuiTableRow.js +1 -1
- package/dist/components/table/index.d.ts +1 -0
- package/dist/components/table/index.js +726 -663
- package/dist/index.js +6 -6
- package/dist/lib/useGlobalCursor.d.ts +4 -0
- package/dist/lib/useGlobalCursor.js +15 -0
- package/dist/lib/useResizeColumns.d.ts +3812 -0
- package/dist/lib/useResizeColumns.js +97 -79
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/input/BuiInput.vue +1 -1
- package/src/components/pagination/BuiPaginationCommon.vue +16 -4
- package/src/components/scroll-area/BuiScrollArea.vue +9 -2
- package/src/components/scroll-area/BuiScrollBar.vue +4 -4
- package/src/components/table/BuiDataTable.vue +152 -34
- package/src/components/table/BuiTable.vue +12 -3
- package/src/components/table/BuiTableRow.vue +6 -0
- package/src/components/table/index.ts +2 -0
- package/src/lib/useGlobalCursor.ts +17 -0
- package/src/lib/useResizeColumns.ts +151 -42
- package/src/stories/BuiDataTable.stories.ts +13 -0
- package/src/stories/components/BuiDataTableStory.vue +4 -4
- package/src/stories/components/BuiDataTableWithScrollStory.vue +292 -0
- package/dist/BuiPaginationCommon.vue_vue_type_script_setup_true_lang-DhSRYKth.js +0 -170
- package/dist/BuiScrollArea.vue_vue_type_script_setup_true_lang-XkIzRs-G.js +0 -141
- package/dist/BuiTable.vue_vue_type_script_setup_true_lang-Dd_dkcy4.js +0 -30
- package/dist/BuiTableRow.vue_vue_type_script_setup_true_lang-BJk8Yk1B.js +0 -54
|
@@ -24,6 +24,7 @@ const props = defineProps<{
|
|
|
24
24
|
total: number
|
|
25
25
|
translations?: {
|
|
26
26
|
itemsPerPage: string
|
|
27
|
+
itemsPerPageAuto: string
|
|
27
28
|
page: string
|
|
28
29
|
of: string
|
|
29
30
|
}
|
|
@@ -31,14 +32,21 @@ const props = defineProps<{
|
|
|
31
32
|
|
|
32
33
|
const pageSize = defineModel<PageSize>('pageSize', { default: 10, required: true })
|
|
33
34
|
const pageIndex = defineModel<number>('pageIndex', { default: 1, required: true })
|
|
35
|
+
const pageAuto = defineModel<boolean | undefined>('pageAuto', { default: false, required: true })
|
|
34
36
|
const totalPages = computed(() => Math.ceil(props.total / pageSize.value))
|
|
35
37
|
|
|
36
38
|
const pageSizeString = computed({
|
|
37
39
|
get() {
|
|
38
|
-
return String(pageSize.value)
|
|
40
|
+
return pageAuto.value ? props.translations?.itemsPerPageAuto || 'Auto' : String(pageSize.value)
|
|
39
41
|
},
|
|
40
42
|
set(value: string) {
|
|
41
|
-
|
|
43
|
+
pageAuto.value = value === 'auto'
|
|
44
|
+
|
|
45
|
+
if (value === 'auto') {
|
|
46
|
+
pageIndex.value = 1
|
|
47
|
+
} else {
|
|
48
|
+
pageSize.value = parseInt(value) as PageSize
|
|
49
|
+
}
|
|
42
50
|
}
|
|
43
51
|
})
|
|
44
52
|
</script>
|
|
@@ -56,15 +64,19 @@ const pageSizeString = computed({
|
|
|
56
64
|
</p>
|
|
57
65
|
<BuiSelect v-model="pageSizeString">
|
|
58
66
|
<BuiSelectTrigger class="mr-2 w-[70px]">
|
|
59
|
-
<BuiSelectValue :placeholder="
|
|
67
|
+
<BuiSelectValue :placeholder="pageSizeString" />
|
|
60
68
|
</BuiSelectTrigger>
|
|
61
69
|
<BuiSelectContent side="top">
|
|
70
|
+
<BuiSelectItem key="auto" value="auto">
|
|
71
|
+
{{ props.translations?.itemsPerPageAuto || 'Auto' }}
|
|
72
|
+
</BuiSelectItem>
|
|
73
|
+
|
|
62
74
|
<BuiSelectItem v-for="pageSize in pageSizes" :key="pageSize" :value="pageSize.toString()">
|
|
63
75
|
{{ pageSize }}
|
|
64
76
|
</BuiSelectItem>
|
|
65
77
|
</BuiSelectContent>
|
|
66
78
|
</BuiSelect>
|
|
67
|
-
<template v-if="totalPages > 1">
|
|
79
|
+
<template v-if="!pageAuto && totalPages > 1">
|
|
68
80
|
<p class="text-muted-foreground text-sm">
|
|
69
81
|
{{ translations?.page || 'Page' }} {{ page }} {{ translations?.of || 'of' }}
|
|
70
82
|
{{ totalPages }}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { type HTMLAttributes, computed } from 'vue'
|
|
2
|
+
import { type HTMLAttributes, computed, ref } from 'vue'
|
|
3
3
|
import {
|
|
4
4
|
ScrollAreaCorner,
|
|
5
5
|
ScrollAreaRoot,
|
|
@@ -16,10 +16,17 @@ const delegatedProps = computed(() => {
|
|
|
16
16
|
|
|
17
17
|
return delegated
|
|
18
18
|
})
|
|
19
|
+
|
|
20
|
+
const tableWrapperRef = ref<InstanceType<typeof ScrollAreaRoot> | null>(null)
|
|
21
|
+
defineExpose({ tableWrapperRef })
|
|
19
22
|
</script>
|
|
20
23
|
|
|
21
24
|
<template>
|
|
22
|
-
<ScrollAreaRoot
|
|
25
|
+
<ScrollAreaRoot
|
|
26
|
+
ref="tableWrapperRef"
|
|
27
|
+
v-bind="delegatedProps"
|
|
28
|
+
:class="cn('relative overflow-hidden', props.class)"
|
|
29
|
+
>
|
|
23
30
|
<ScrollAreaViewport class="h-full w-full rounded-[inherit]">
|
|
24
31
|
<slot />
|
|
25
32
|
</ScrollAreaViewport>
|
|
@@ -22,13 +22,13 @@ const delegatedProps = computed(() => {
|
|
|
22
22
|
v-bind="delegatedProps"
|
|
23
23
|
:class="
|
|
24
24
|
cn(
|
|
25
|
-
'z-
|
|
26
|
-
orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent p-px',
|
|
27
|
-
orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent p-px',
|
|
25
|
+
'z-10 flex touch-none transition-colors select-none',
|
|
26
|
+
props.orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent p-px',
|
|
27
|
+
props.orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent p-px',
|
|
28
28
|
props.class
|
|
29
29
|
)
|
|
30
30
|
"
|
|
31
31
|
>
|
|
32
|
-
<ScrollAreaThumb class="relative flex-1 rounded-full
|
|
32
|
+
<ScrollAreaThumb class="bg-border relative flex-1 rounded-full" />
|
|
33
33
|
</ScrollAreaScrollbar>
|
|
34
34
|
</template>
|
|
@@ -1,17 +1,38 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { PaginationState } from '@tanstack/vue-table'
|
|
3
|
+
|
|
4
|
+
export type PaginationAutoState = PaginationState & {
|
|
5
|
+
pageAuto?: boolean
|
|
6
|
+
}
|
|
7
|
+
</script>
|
|
8
|
+
|
|
1
9
|
<script setup lang="ts" generic="TData, TValue">
|
|
10
|
+
import { BuiButton } from '@/components/button'
|
|
2
11
|
import {
|
|
3
12
|
BuiCollapsible,
|
|
4
13
|
BuiCollapsibleContent,
|
|
5
14
|
BuiCollapsibleTrigger
|
|
6
15
|
} from '@/components/collapsible'
|
|
16
|
+
import {
|
|
17
|
+
BuiCommand,
|
|
18
|
+
BuiCommandEmpty,
|
|
19
|
+
BuiCommandInput,
|
|
20
|
+
BuiCommandItem,
|
|
21
|
+
BuiCommandList,
|
|
22
|
+
BuiCommandSeparator
|
|
23
|
+
} from '@/components/command'
|
|
24
|
+
import { BuiContextMenuContent, BuiContextMenuItem } from '@/components/context-menu'
|
|
7
25
|
import { BuiPaginationCommon, type PageSize } from '@/components/pagination'
|
|
26
|
+
import { BuiPopover, BuiPopoverContent, BuiPopoverTrigger } from '@/components/popover'
|
|
27
|
+
import { BuiScrollArea } from '@/components/scroll-area'
|
|
8
28
|
import BuiTableRowSubrow from '@/components/table/BuiTableRowSubrow.vue'
|
|
29
|
+
import { useResizeColumns } from '@/lib/useResizeColumns'
|
|
30
|
+
import { cn, valueUpdater } from '@/lib/utils'
|
|
9
31
|
import type {
|
|
10
32
|
Column,
|
|
11
33
|
ColumnDef,
|
|
12
34
|
ColumnOrderState,
|
|
13
35
|
Header,
|
|
14
|
-
PaginationState,
|
|
15
36
|
Row,
|
|
16
37
|
RowSelectionState,
|
|
17
38
|
SortingState,
|
|
@@ -24,8 +45,18 @@ import {
|
|
|
24
45
|
getSortedRowModel,
|
|
25
46
|
useVueTable
|
|
26
47
|
} from '@tanstack/vue-table'
|
|
27
|
-
import { computed, watchEffect, ref, watch, onMounted, onBeforeMount, nextTick } from 'vue'
|
|
28
48
|
import {
|
|
49
|
+
useElementSize,
|
|
50
|
+
useEventListener,
|
|
51
|
+
useSessionStorage,
|
|
52
|
+
useIntersectionObserver,
|
|
53
|
+
useElementVisibility
|
|
54
|
+
} from '@vueuse/core'
|
|
55
|
+
import { isEqual } from 'lodash-es'
|
|
56
|
+
import { ChevronDown, Settings2Icon } from 'lucide-vue-next'
|
|
57
|
+
import { computed, nextTick, onBeforeMount, onMounted, ref, watch, watchEffect } from 'vue'
|
|
58
|
+
import {
|
|
59
|
+
BuiDataTableColumnList,
|
|
29
60
|
BuiTable,
|
|
30
61
|
BuiTableBody,
|
|
31
62
|
BuiTableCell,
|
|
@@ -33,32 +64,15 @@ import {
|
|
|
33
64
|
BuiTableHead,
|
|
34
65
|
BuiTableHeader,
|
|
35
66
|
BuiTableRow,
|
|
36
|
-
getPinningStyle
|
|
37
|
-
BuiDataTableColumnList
|
|
67
|
+
getPinningStyle
|
|
38
68
|
} from './'
|
|
39
|
-
import {
|
|
40
|
-
BuiCommand,
|
|
41
|
-
BuiCommandEmpty,
|
|
42
|
-
BuiCommandInput,
|
|
43
|
-
BuiCommandList,
|
|
44
|
-
BuiCommandItem,
|
|
45
|
-
BuiCommandSeparator
|
|
46
|
-
} from '@/components/command'
|
|
47
|
-
import { BuiContextMenuContent, BuiContextMenuItem } from '@/components/context-menu'
|
|
48
|
-
import { BuiPopover, BuiPopoverContent, BuiPopoverTrigger } from '@/components/popover'
|
|
49
|
-
import { BuiScrollArea } from '@/components/scroll-area'
|
|
50
|
-
import { BuiButton } from '@/components/button'
|
|
51
|
-
import { Settings2Icon, ChevronDown } from 'lucide-vue-next'
|
|
52
|
-
import { useElementSize, useEventListener } from '@vueuse/core'
|
|
53
|
-
import { isEqual } from 'lodash-es'
|
|
54
|
-
import { cn, valueUpdater } from '@/lib/utils'
|
|
55
|
-
import { useResizeColumns } from '@/lib/useResizeColumns'
|
|
56
|
-
import { useSessionStorage } from '@vueuse/core'
|
|
69
|
+
import { useGlobalCursor } from '@/lib/useGlobalCursor'
|
|
57
70
|
|
|
58
71
|
const NO_GROUP_KEY = '#UNDEFINED#'
|
|
59
72
|
const defaultColumnContextMenuTranslations = {
|
|
60
73
|
hideColumn: 'Hide column',
|
|
61
|
-
|
|
74
|
+
resetThisSize: 'Reset size for this column',
|
|
75
|
+
resetSize: 'Reset size for all columns',
|
|
62
76
|
sortAsc: 'Sort ascending',
|
|
63
77
|
sortDesc: 'Sort descending'
|
|
64
78
|
}
|
|
@@ -85,11 +99,13 @@ const props = withDefaults(
|
|
|
85
99
|
columnResetVisibility?: string
|
|
86
100
|
paginationTranslations?: {
|
|
87
101
|
itemsPerPage: string
|
|
102
|
+
itemsPerPageAuto: string
|
|
88
103
|
page: string
|
|
89
104
|
of: string
|
|
90
105
|
}
|
|
91
106
|
headerContextMenuTranslations?: {
|
|
92
107
|
hideColumn?: string
|
|
108
|
+
resetThisSize?: string
|
|
93
109
|
resetSize?: string
|
|
94
110
|
sortAsc?: string
|
|
95
111
|
sortDesc?: string
|
|
@@ -110,7 +126,7 @@ const props = withDefaults(
|
|
|
110
126
|
)
|
|
111
127
|
|
|
112
128
|
const sorting = defineModel<SortingState>('sorting')
|
|
113
|
-
const pagination = defineModel<
|
|
129
|
+
const pagination = defineModel<PaginationAutoState>('pagination')
|
|
114
130
|
const rowSelection = defineModel<RowSelectionState>('selection')
|
|
115
131
|
const columnVisibility = defineModel<VisibilityState>('columnVisibility')
|
|
116
132
|
const columnOrder = defineModel<ColumnOrderState>('columnOrder')
|
|
@@ -152,7 +168,6 @@ const table = useVueTable({
|
|
|
152
168
|
await nextTick()
|
|
153
169
|
|
|
154
170
|
resetCells()
|
|
155
|
-
setInitialColumnWidths()
|
|
156
171
|
},
|
|
157
172
|
onColumnOrderChange: (updaterOrValue) => {
|
|
158
173
|
valueUpdater(updaterOrValue, columnOrder)
|
|
@@ -180,6 +195,15 @@ const table = useVueTable({
|
|
|
180
195
|
getRowId: props.getRowId
|
|
181
196
|
})
|
|
182
197
|
|
|
198
|
+
const pageAuto = computed({
|
|
199
|
+
get() {
|
|
200
|
+
return pagination.value?.pageAuto || false
|
|
201
|
+
},
|
|
202
|
+
set: (state: boolean) => {
|
|
203
|
+
if (!pagination.value) return
|
|
204
|
+
pagination.value.pageAuto = state
|
|
205
|
+
}
|
|
206
|
+
})
|
|
183
207
|
const tablePageSize = computed<PageSize>({
|
|
184
208
|
get() {
|
|
185
209
|
return table.getState().pagination.pageSize as PageSize
|
|
@@ -257,18 +281,20 @@ watch(columnsListIds, () => {
|
|
|
257
281
|
})
|
|
258
282
|
|
|
259
283
|
const tableHeaderRef = ref<InstanceType<typeof BuiTableHeader> | null>(null)
|
|
284
|
+
const tableElementRef = ref<InstanceType<typeof BuiTable> | null>(null)
|
|
260
285
|
const { height } = useElementSize(tableHeaderRef)
|
|
261
286
|
|
|
262
287
|
const {
|
|
263
288
|
tableHeaderElement,
|
|
289
|
+
tableElement,
|
|
264
290
|
calculatedColumnSizing,
|
|
265
291
|
isResizing,
|
|
266
292
|
resizingCellId,
|
|
293
|
+
resetCell,
|
|
267
294
|
resetCells,
|
|
268
295
|
handleResizeControlMouseDown,
|
|
269
296
|
handleResizeControlMouseUp,
|
|
270
297
|
setInitialColumnWidths,
|
|
271
|
-
setProvidedCellWidths,
|
|
272
298
|
isMouseDownOnHandler,
|
|
273
299
|
isMouseUpOnHandler
|
|
274
300
|
} = useResizeColumns()
|
|
@@ -278,10 +304,10 @@ onBeforeMount(() => {
|
|
|
278
304
|
})
|
|
279
305
|
|
|
280
306
|
onMounted(() => {
|
|
281
|
-
if (tableHeaderRef.value) {
|
|
307
|
+
if (tableElementRef.value && tableHeaderRef.value) {
|
|
308
|
+
tableElement.value = tableElementRef.value
|
|
282
309
|
tableHeaderElement.value = tableHeaderRef.value
|
|
283
310
|
|
|
284
|
-
setProvidedCellWidths(columnSizing.value)
|
|
285
311
|
setInitialColumnWidths()
|
|
286
312
|
}
|
|
287
313
|
|
|
@@ -304,7 +330,7 @@ const getHeaderCellSortingButton = (header: Header<TData, unknown>) => {
|
|
|
304
330
|
return currentHeaderCell?.querySelector('button[sorting-enabled]')
|
|
305
331
|
}
|
|
306
332
|
|
|
307
|
-
type HeaderCellAction = 'hideColumn' | 'resetSize' | 'sortAsc' | 'sortDesc'
|
|
333
|
+
type HeaderCellAction = 'hideColumn' | 'resetThisSize' | 'resetSize' | 'sortAsc' | 'sortDesc'
|
|
308
334
|
const availableHeaderCellActions = (header: Header<TData, unknown>) => {
|
|
309
335
|
const out: HeaderCellAction[] = []
|
|
310
336
|
|
|
@@ -319,6 +345,7 @@ const availableHeaderCellActions = (header: Header<TData, unknown>) => {
|
|
|
319
345
|
}
|
|
320
346
|
|
|
321
347
|
if (props.enableColumnResizing) {
|
|
348
|
+
out.push('resetThisSize')
|
|
322
349
|
out.push('resetSize')
|
|
323
350
|
}
|
|
324
351
|
|
|
@@ -329,6 +356,9 @@ const onHeaderCellAction = (header: Header<TData, unknown>, action: HeaderCellAc
|
|
|
329
356
|
case 'hideColumn':
|
|
330
357
|
header.column.toggleVisibility()
|
|
331
358
|
break
|
|
359
|
+
case 'resetThisSize':
|
|
360
|
+
resetCell(header.id)
|
|
361
|
+
break
|
|
332
362
|
case 'resetSize':
|
|
333
363
|
resetCells()
|
|
334
364
|
break
|
|
@@ -399,13 +429,82 @@ const handleHeaderCellMouseDown = (e: Event) => {
|
|
|
399
429
|
isMouseDownOnHandler.value =
|
|
400
430
|
targetHTMLElement.className.includes && targetHTMLElement.className.includes('resize-handler')
|
|
401
431
|
}
|
|
432
|
+
|
|
433
|
+
const { setCursor, resetCursor } = useGlobalCursor()
|
|
434
|
+
|
|
435
|
+
watch(isResizing, () => {
|
|
436
|
+
if (isResizing.value) {
|
|
437
|
+
setCursor('col-resize')
|
|
438
|
+
} else {
|
|
439
|
+
resetCursor()
|
|
440
|
+
}
|
|
441
|
+
})
|
|
442
|
+
|
|
443
|
+
const rows = computed(() => table.getRowModel().rows)
|
|
444
|
+
const rowsLength = computed(() => rows.value.length)
|
|
445
|
+
const sentinel = ref<HTMLElement | null>(null)
|
|
446
|
+
const sentinelVisible = useElementVisibility(sentinel)
|
|
447
|
+
const sentinelKey = computed(() => `sentinel-${rowsLength.value}`)
|
|
448
|
+
|
|
449
|
+
const { stop } = useIntersectionObserver(
|
|
450
|
+
sentinel,
|
|
451
|
+
async ([{ isIntersecting }]) => {
|
|
452
|
+
if (isIntersecting && pageAuto.value) {
|
|
453
|
+
await nextTick()
|
|
454
|
+
loadMore()
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (tablePageSize.value >= props.totalItems) {
|
|
458
|
+
stop()
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
rootMargin: '0px 0px 50px 0px'
|
|
463
|
+
}
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
let loadingMore = false
|
|
467
|
+
async function loadMore() {
|
|
468
|
+
if (loadingMore) return
|
|
469
|
+
loadingMore = true
|
|
470
|
+
|
|
471
|
+
const newSize = Math.min(tablePageSize.value + 50, props.totalItems)
|
|
472
|
+
table.setPageSize(newSize)
|
|
473
|
+
|
|
474
|
+
await nextTick()
|
|
475
|
+
loadingMore = false
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
watch(pageAuto, (newPageAuto, oldPageAuto) => {
|
|
479
|
+
if (newPageAuto && !oldPageAuto) {
|
|
480
|
+
if (tableElementRef.value && tableElementRef.value.scrollAreaElementRef?.tableWrapperRef) {
|
|
481
|
+
tableElementRef.value.scrollAreaElementRef.tableWrapperRef.scrollTop()
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
})
|
|
485
|
+
|
|
486
|
+
const isUpdating = ref(false)
|
|
487
|
+
watch(rowsLength, async () => {
|
|
488
|
+
if (!pageAuto.value || isUpdating.value) return
|
|
489
|
+
|
|
490
|
+
isUpdating.value = true
|
|
491
|
+
await nextTick()
|
|
492
|
+
|
|
493
|
+
//Add a small delay to ensure rendering is complete
|
|
494
|
+
setTimeout(() => {
|
|
495
|
+
if (sentinelVisible.value) {
|
|
496
|
+
loadMore()
|
|
497
|
+
}
|
|
498
|
+
isUpdating.value = false
|
|
499
|
+
}, 50)
|
|
500
|
+
})
|
|
402
501
|
</script>
|
|
403
502
|
|
|
404
503
|
<template>
|
|
405
504
|
<div v-if="$slots.caption" class="w-full py-3">
|
|
406
505
|
<slot name="caption" :table="table" />
|
|
407
506
|
</div>
|
|
408
|
-
<BuiTable>
|
|
507
|
+
<BuiTable ref="tableElementRef">
|
|
409
508
|
<template v-if="enableColumnListControl" #columnVisibility>
|
|
410
509
|
<BuiPopover v-model:open="open">
|
|
411
510
|
<BuiPopoverTrigger as-child>
|
|
@@ -449,6 +548,17 @@ const handleHeaderCellMouseDown = (e: Event) => {
|
|
|
449
548
|
>
|
|
450
549
|
{{ columnResetVisibility }}
|
|
451
550
|
</BuiCommandItem>
|
|
551
|
+
<BuiCommandItem
|
|
552
|
+
value="reset_columns_size"
|
|
553
|
+
key="reset_columns_size"
|
|
554
|
+
class="text-muted-foreground px-2 py-1.5 font-medium"
|
|
555
|
+
@select="resetCells"
|
|
556
|
+
>
|
|
557
|
+
{{
|
|
558
|
+
headerContextMenuTranslations?.['resetSize'] ??
|
|
559
|
+
defaultColumnContextMenuTranslations['resetSize']
|
|
560
|
+
}}
|
|
561
|
+
</BuiCommandItem>
|
|
452
562
|
</BuiScrollArea>
|
|
453
563
|
</BuiCommandList>
|
|
454
564
|
</BuiCommand>
|
|
@@ -499,9 +609,8 @@ const handleHeaderCellMouseDown = (e: Event) => {
|
|
|
499
609
|
:key="idx"
|
|
500
610
|
>
|
|
501
611
|
{{
|
|
502
|
-
headerContextMenuTranslations
|
|
503
|
-
|
|
504
|
-
: defaultColumnContextMenuTranslations[action]
|
|
612
|
+
headerContextMenuTranslations?.[action] ??
|
|
613
|
+
defaultColumnContextMenuTranslations[action]
|
|
505
614
|
}}
|
|
506
615
|
</BuiContextMenuItem>
|
|
507
616
|
</BuiContextMenuContent>
|
|
@@ -518,7 +627,7 @@ const handleHeaderCellMouseDown = (e: Event) => {
|
|
|
518
627
|
v-for="(value, key) in groupedRows"
|
|
519
628
|
:key="key"
|
|
520
629
|
v-model:open="groupsOpenStateRef[key]"
|
|
521
|
-
@update:open="(value) => handleGroupToggle(value, key)"
|
|
630
|
+
@update:open="(value: boolean) => handleGroupToggle(value, key)"
|
|
522
631
|
>
|
|
523
632
|
<BuiTableRow class="bg-foreground/4 border-b-0">
|
|
524
633
|
<BuiTableCell :colspan="columns.length" class="pb-0!">
|
|
@@ -607,6 +716,14 @@ const handleHeaderCellMouseDown = (e: Event) => {
|
|
|
607
716
|
<slot name="nodata">No data</slot>
|
|
608
717
|
</BuiTableEmpty>
|
|
609
718
|
</template>
|
|
719
|
+
|
|
720
|
+
<tr
|
|
721
|
+
v-if="pageAuto && tablePageSize < props.totalItems"
|
|
722
|
+
ref="sentinel"
|
|
723
|
+
class="h-4 w-full"
|
|
724
|
+
:data-key="sentinelKey"
|
|
725
|
+
:key="sentinelKey"
|
|
726
|
+
/>
|
|
610
727
|
</BuiTableBody>
|
|
611
728
|
</BuiTable>
|
|
612
729
|
<div
|
|
@@ -626,6 +743,7 @@ const handleHeaderCellMouseDown = (e: Event) => {
|
|
|
626
743
|
:total="computedItems"
|
|
627
744
|
v-model:pageIndex="pageIndex"
|
|
628
745
|
v-model:pageSize="tablePageSize"
|
|
746
|
+
v-model:pageAuto="pageAuto"
|
|
629
747
|
:translations="paginationTranslations"
|
|
630
748
|
>
|
|
631
749
|
</BuiPaginationCommon>
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { BuiScrollArea, BuiScrollBar } from '@/components/scroll-area'
|
|
3
3
|
import { cn } from '@/lib/utils'
|
|
4
|
+
import { ref } from 'vue'
|
|
4
5
|
|
|
5
6
|
const props = defineProps<{ class?: string }>()
|
|
7
|
+
const tableRef = ref<HTMLTableElement | undefined>(undefined)
|
|
8
|
+
const scrollAreaElementRef = ref<InstanceType<typeof BuiScrollArea> | null>(null)
|
|
9
|
+
|
|
10
|
+
defineExpose({ tableRef, scrollAreaElementRef })
|
|
6
11
|
</script>
|
|
7
12
|
|
|
8
13
|
<template>
|
|
9
|
-
<BuiScrollArea
|
|
14
|
+
<BuiScrollArea
|
|
15
|
+
ref="scrollAreaElementRef"
|
|
16
|
+
class="border-border/16 w-full grow overflow-auto rounded-sm border"
|
|
17
|
+
:scroll-hide-delay="100"
|
|
18
|
+
>
|
|
10
19
|
<slot name="columnVisibility" />
|
|
11
|
-
<div class="flex min-h-[90px] grow flex-col">
|
|
12
|
-
<table :class="cn('h-full
|
|
20
|
+
<div class="flex min-h-[90px] w-full grow flex-col">
|
|
21
|
+
<table ref="tableRef" :class="cn('h-full caption-top text-sm', props.class)">
|
|
13
22
|
<slot />
|
|
14
23
|
</table>
|
|
15
24
|
</div>
|
|
@@ -4,6 +4,10 @@ import { cn } from '@/lib/utils'
|
|
|
4
4
|
|
|
5
5
|
const props = defineProps<{ class?: string }>()
|
|
6
6
|
const emits = defineEmits(['mouseenter', 'mouseleave'])
|
|
7
|
+
|
|
8
|
+
defineOptions({
|
|
9
|
+
inheritAttrs: false
|
|
10
|
+
})
|
|
7
11
|
</script>
|
|
8
12
|
|
|
9
13
|
<template>
|
|
@@ -19,6 +23,7 @@ const emits = defineEmits(['mouseenter', 'mouseleave'])
|
|
|
19
23
|
:data-row-state="$attrs['data-row-state']"
|
|
20
24
|
@mouseenter="emits('mouseenter')"
|
|
21
25
|
@mouseleave="emits('mouseleave')"
|
|
26
|
+
v-bind="$attrs"
|
|
22
27
|
>
|
|
23
28
|
<slot />
|
|
24
29
|
</tr>
|
|
@@ -36,6 +41,7 @@ const emits = defineEmits(['mouseenter', 'mouseleave'])
|
|
|
36
41
|
:data-row-state="$attrs['data-row-state']"
|
|
37
42
|
@mouseenter="emits('mouseenter')"
|
|
38
43
|
@mouseleave="emits('mouseleave')"
|
|
44
|
+
v-bind="$attrs"
|
|
39
45
|
>
|
|
40
46
|
<slot />
|
|
41
47
|
</tr>
|
|
@@ -14,6 +14,8 @@ export { default as BuiTableFooter } from './BuiTableFooter.vue'
|
|
|
14
14
|
export { default as BuiDataTable } from './BuiDataTable.vue'
|
|
15
15
|
export { default as BuiDataTableColumnList } from './BuiDataTableColumnList.vue'
|
|
16
16
|
|
|
17
|
+
export type { PaginationAutoState } from './BuiDataTable.vue'
|
|
18
|
+
|
|
17
19
|
export function getPinningStyle<TData>(_column: Column<TData, unknown>): CSSProperties {
|
|
18
20
|
// FYI sticky columns not possible with transparent background colors
|
|
19
21
|
// const isPinned = column.getIsPinned()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { onUnmounted } from 'vue'
|
|
2
|
+
|
|
3
|
+
export function useGlobalCursor() {
|
|
4
|
+
function setCursor(cursor: string) {
|
|
5
|
+
document.body.style.cursor = cursor
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function resetCursor() {
|
|
9
|
+
document.body.style.cursor = ''
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
onUnmounted(() => {
|
|
13
|
+
resetCursor()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
return { setCursor, resetCursor }
|
|
17
|
+
}
|