@meistrari/tela-build 1.53.0 → 1.54.1
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/components/tela/combobox/combobox-trigger.vue +6 -3
- package/components/tela/complex-table/complex-table-row.vue +11 -3
- package/components/tela/complex-table/complex-table-virtualized.vue +2 -0
- package/components/tela/complex-table/complex-table.vue +2 -0
- package/components/tela/complex-table/composables/table-common.ts +40 -3
- package/components/tela/icon-button/icon-button.vue +3 -3
- package/components/tela/icon.vue +2 -1
- package/package.json +1 -1
|
@@ -13,14 +13,17 @@ const delegatedProps = reactiveOmit(props, 'class')
|
|
|
13
13
|
<ComboboxTrigger
|
|
14
14
|
v-bind="delegatedProps"
|
|
15
15
|
:class="cn(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
!props.asChild && [
|
|
17
|
+
'group select-none flex items-center justify-between body-14-semibold gap-3 rounded-10px pl-11px pr-10px py-7px bg-white border-0.5px border transition hover:border-strong hover:bg-subtle',
|
|
18
|
+
'data-[state=open]:text-secondary data-[state=open]:border-strong data-[state=open]:bg-subtle',
|
|
19
|
+
'[box-shadow:0_1px_6px_0_rgba(103,127,148,0.05)]',
|
|
20
|
+
],
|
|
19
21
|
props.class,
|
|
20
22
|
)"
|
|
21
23
|
>
|
|
22
24
|
<slot />
|
|
23
25
|
<TelaIcon
|
|
26
|
+
v-if="!props.asChild"
|
|
24
27
|
name="i-ph-caret-down-bold"
|
|
25
28
|
size="15px"
|
|
26
29
|
color="icon-secondary"
|
|
@@ -31,7 +31,7 @@ const props = defineProps<{
|
|
|
31
31
|
}>()
|
|
32
32
|
|
|
33
33
|
const emit = defineEmits<{
|
|
34
|
-
select: [id: string]
|
|
34
|
+
select: [id: string, shiftKey: boolean]
|
|
35
35
|
open: [id: string]
|
|
36
36
|
}>()
|
|
37
37
|
|
|
@@ -87,10 +87,18 @@ function shouldEnableRowClick() {
|
|
|
87
87
|
return props.hoverMechanism === HoverMechanismTypes.Row && !props.disableRowClick
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
// Captured in the capture phase (before the checkbox toggles) so range-select
|
|
91
|
+
// with Shift can be resolved by the parent table.
|
|
92
|
+
const shiftHeldOnSelect = ref(false)
|
|
93
|
+
function captureSelectModifier(event: MouseEvent) {
|
|
94
|
+
shiftHeldOnSelect.value = event.shiftKey
|
|
95
|
+
}
|
|
96
|
+
|
|
90
97
|
function handleCheckboxChange() {
|
|
91
98
|
if (props.row.id) {
|
|
92
|
-
emit('select', props.row.id)
|
|
99
|
+
emit('select', props.row.id, shiftHeldOnSelect.value)
|
|
93
100
|
}
|
|
101
|
+
shiftHeldOnSelect.value = false
|
|
94
102
|
}
|
|
95
103
|
</script>
|
|
96
104
|
|
|
@@ -100,7 +108,7 @@ function handleCheckboxChange() {
|
|
|
100
108
|
:class="computedRowClass"
|
|
101
109
|
@click.stop="handleRowClick"
|
|
102
110
|
>
|
|
103
|
-
<td v-if="allowSelect" class="sticky left-0 bg-white z-9" :class="[selectClass]" @click.stop>
|
|
111
|
+
<td v-if="allowSelect" class="sticky left-0 bg-white z-9" :class="[selectClass]" @click.capture="captureSelectModifier" @click.stop>
|
|
104
112
|
<div
|
|
105
113
|
flex="~" h-px items-center justify-center w-32px relative z-0
|
|
106
114
|
>
|
|
@@ -36,6 +36,7 @@ const {
|
|
|
36
36
|
isAllSelected,
|
|
37
37
|
selectAll,
|
|
38
38
|
toggleRow,
|
|
39
|
+
setSelectedRows,
|
|
39
40
|
} = useTableSelection({
|
|
40
41
|
rows: computed(() => props.rows),
|
|
41
42
|
initialSelectedRows: props.selectedRows,
|
|
@@ -57,6 +58,7 @@ const {
|
|
|
57
58
|
isAllSelected,
|
|
58
59
|
selectAll,
|
|
59
60
|
toggleRow,
|
|
61
|
+
setSelectedRows,
|
|
60
62
|
})
|
|
61
63
|
|
|
62
64
|
const hoverMechanism = computed(() => props.hoverMechanism || HoverMechanismTypes.Cell)
|
|
@@ -42,6 +42,7 @@ const {
|
|
|
42
42
|
isAllSelected,
|
|
43
43
|
selectAll,
|
|
44
44
|
toggleRow,
|
|
45
|
+
setSelectedRows,
|
|
45
46
|
} = useTableSelection({
|
|
46
47
|
rows: computed(() => props.rows),
|
|
47
48
|
initialSelectedRows: props.selectedRows,
|
|
@@ -63,6 +64,7 @@ const {
|
|
|
63
64
|
isAllSelected,
|
|
64
65
|
selectAll,
|
|
65
66
|
toggleRow,
|
|
67
|
+
setSelectedRows,
|
|
66
68
|
})
|
|
67
69
|
|
|
68
70
|
const hoverMechanism = computed(() => props.hoverMechanism || HoverMechanismTypes.Cell)
|
|
@@ -19,23 +19,60 @@ export interface UseTableCommonOptions {
|
|
|
19
19
|
isAllSelected: Ref<boolean>
|
|
20
20
|
selectAll: (value: boolean) => string[]
|
|
21
21
|
toggleRow: (id: string) => string[]
|
|
22
|
+
setSelectedRows?: (ids: string[]) => void
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export function useTableCommon(options: UseTableCommonOptions) {
|
|
25
|
-
const { props, emit, mainTableEl, selectedRows, isAllSelected, selectAll, toggleRow } = options
|
|
26
|
+
const { props, emit, mainTableEl, selectedRows, isAllSelected, selectAll, toggleRow, setSelectedRows } = options
|
|
26
27
|
|
|
27
28
|
const hasHorizontalScroll = ref(false)
|
|
29
|
+
// Anchor for Shift range-select: the last row toggled without Shift.
|
|
30
|
+
const selectionAnchor = ref<string | null>(null)
|
|
31
|
+
// Rows selected by the last Shift range-select; the next Shift-click from
|
|
32
|
+
// the same anchor replaces them instead of accumulating (Gmail/Finder style).
|
|
33
|
+
const lastShiftRange = ref<string[]>([])
|
|
28
34
|
|
|
29
35
|
function shouldEnableRowClick(rowData: Row) {
|
|
30
36
|
return props.hoverMechanism === HoverMechanismTypes.Row && !props.disableRowClick?.(rowData)
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
function
|
|
39
|
+
function selectableRowIds(): string[] {
|
|
40
|
+
return props.rows.map((row: Row) => row?.id).filter(Boolean) as string[]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function rangeBetween(anchorId: string, targetId: string): string[] | null {
|
|
44
|
+
const ids = selectableRowIds()
|
|
45
|
+
const from = ids.indexOf(anchorId)
|
|
46
|
+
const to = ids.indexOf(targetId)
|
|
47
|
+
if (from === -1 || to === -1)
|
|
48
|
+
return null
|
|
49
|
+
const [lo, hi] = from <= to ? [from, to] : [to, from]
|
|
50
|
+
return ids.slice(lo, hi + 1)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function handleRowSelect(rowId: string, shiftKey = false) {
|
|
54
|
+
if (shiftKey && selectionAnchor.value && selectionAnchor.value !== rowId) {
|
|
55
|
+
const range = rangeBetween(selectionAnchor.value, rowId)
|
|
56
|
+
if (range) {
|
|
57
|
+
const previousRange = new Set(lastShiftRange.value)
|
|
58
|
+
const kept = selectedRows.value.filter((id: string) => !previousRange.has(id))
|
|
59
|
+
const newSelection = Array.from(new Set([...kept, ...range]))
|
|
60
|
+
lastShiftRange.value = range
|
|
61
|
+
if (!props.selectedRows)
|
|
62
|
+
setSelectedRows?.(newSelection)
|
|
63
|
+
emit('select', newSelection, newSelection.length === selectableRowIds().length)
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
selectionAnchor.value = rowId
|
|
69
|
+
lastShiftRange.value = []
|
|
70
|
+
|
|
34
71
|
if (props.selectedRows) {
|
|
35
72
|
const newSelection = selectedRows.value.includes(rowId)
|
|
36
73
|
? selectedRows.value.filter((id: string) => id !== rowId)
|
|
37
74
|
: [...selectedRows.value, rowId]
|
|
38
|
-
emit('select', newSelection, newSelection.length ===
|
|
75
|
+
emit('select', newSelection, newSelection.length === selectableRowIds().length)
|
|
39
76
|
return
|
|
40
77
|
}
|
|
41
78
|
|
|
@@ -33,9 +33,9 @@ const style = computed(() => {
|
|
|
33
33
|
const size = ({
|
|
34
34
|
'3xs': 'text-6px p-1 rounded-8px',
|
|
35
35
|
'2xs': 'text-8px p-4px rounded-4px', // 16px
|
|
36
|
-
'xs': 'text-12px p-6px rounded-6px', //
|
|
37
|
-
'sm': 'text-16px p-
|
|
38
|
-
'md': 'text-20px p-
|
|
36
|
+
'xs': 'text-12px p-6px rounded-6px', // 26px
|
|
37
|
+
'sm': 'text-16px p-6px rounded-8px', // 32px
|
|
38
|
+
'md': 'text-20px p-6.4px rounded-10px', // 44px
|
|
39
39
|
} as Record<typeof props.size, string>)[props.size]
|
|
40
40
|
|
|
41
41
|
const color = ({
|
package/components/tela/icon.vue
CHANGED
|
@@ -13,7 +13,7 @@ const iconSize = computed(() => {
|
|
|
13
13
|
case 'xs':
|
|
14
14
|
return '8px'
|
|
15
15
|
case 'sm':
|
|
16
|
-
return '
|
|
16
|
+
return '14px'
|
|
17
17
|
case '17px':
|
|
18
18
|
return '17px'
|
|
19
19
|
case '20px':
|
|
@@ -23,6 +23,7 @@ const iconSize = computed(() => {
|
|
|
23
23
|
case 'xl':
|
|
24
24
|
return '32px'
|
|
25
25
|
case 'md':
|
|
26
|
+
return '20px'
|
|
26
27
|
default:
|
|
27
28
|
return '16px'
|
|
28
29
|
}
|