@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.
@@ -13,14 +13,17 @@ const delegatedProps = reactiveOmit(props, 'class')
13
13
  <ComboboxTrigger
14
14
  v-bind="delegatedProps"
15
15
  :class="cn(
16
- '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',
17
- 'data-[state=open]:text-secondary data-[state=open]:border-strong data-[state=open]:bg-subtle',
18
- '[box-shadow:0_1px_6px_0_rgba(103,127,148,0.05)]',
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 handleRowSelect(rowId: string) {
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 === props.rows.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', // 24px
37
- 'sm': 'text-16px p-0.4em rounded-8px', // 32px
38
- 'md': 'text-20px p-0.4em rounded-10px', // 44px
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 = ({
@@ -13,7 +13,7 @@ const iconSize = computed(() => {
13
13
  case 'xs':
14
14
  return '8px'
15
15
  case 'sm':
16
- return '12px'
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/tela-build",
3
- "version": "1.53.0",
3
+ "version": "1.54.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "app.config.ts",