@a-vision-software/vue-input-components 1.4.20 → 1.4.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-vision-software/vue-input-components",
3
- "version": "1.4.20",
3
+ "version": "1.4.21",
4
4
  "description": "A collection of reusable Vue 3 input components with TypeScript support",
5
5
  "author": "A-Vision Software",
6
6
  "license": "MIT",
@@ -96,7 +96,7 @@
96
96
  }"
97
97
  @click="handleSort(column)"
98
98
  >
99
- <div class="list__column-header">
99
+ <div class="list__column-header" :title="column.headerTooltip">
100
100
  <span>{{ column.label }}</span>
101
101
  <span
102
102
  v-if="column.sortable"
@@ -219,7 +219,7 @@ import { ref, computed, watch } from 'vue'
219
219
  import TextInput from './TextInput.vue'
220
220
  import Action from './Action.vue'
221
221
  import Checkbox from './Checkbox.vue'
222
- import type { ListProps, ListEmits, ListColumn, ListAction } from '../types/list'
222
+ import type { ListProps, ListEmits, ListColumn, ListAction, ListRowData } from '../types/list'
223
223
  import { config } from '../config'
224
224
 
225
225
  const props = withDefaults(defineProps<ListProps>(), {
@@ -341,6 +341,9 @@ const filteredData = computed(() => {
341
341
  if (filterableColumns.length === 0) return props.data
342
342
 
343
343
  return props.data.filter((row) => {
344
+ // Always include rows excluded from filtering
345
+ if (row.excludeFromFilter) return true
346
+
344
347
  return filterableColumns.some((column) => {
345
348
  const value = row[column.key]
346
349
  if (value == null) return false
@@ -364,36 +367,57 @@ const filteredData = computed(() => {
364
367
  })
365
368
 
366
369
  const sortedAndFilteredData = computed(() => {
367
- if (!sortColumn.value) return filteredData.value
368
-
369
- return [...filteredData.value].sort((a, b) => {
370
- const column = sortColumn.value!
371
- const aValue = a[column.key]
372
- const bValue = b[column.key]
373
- const sortOrder = sortDirection.value === 'asc' ? 1 : -1
374
-
375
- // Handle different data types
376
- if (column.type === 'date') {
377
- const dateA = new Date(aValue).getTime()
378
- const dateB = new Date(bValue).getTime()
379
- return (dateA - dateB) * sortOrder
370
+ // Separate fixed rows (excluded from sorting) from sortable rows
371
+ const fixedRows: ListRowData[] = []
372
+ const sortableRows: ListRowData[] = []
373
+
374
+ filteredData.value.forEach((row) => {
375
+ if (row.excludeFromSort) {
376
+ fixedRows.push(row)
377
+ } else {
378
+ sortableRows.push(row)
380
379
  }
380
+ })
381
381
 
382
- if (column.type === 'number') {
383
- return (aValue - bValue) * sortOrder
384
- }
382
+ // Sort only the sortable rows if sorting is active
383
+ let sortedRows = sortableRows
384
+ if (sortColumn.value) {
385
+ sortedRows = [...sortableRows].sort((a, b) => {
386
+ const column = sortColumn.value!
387
+ const aValue = a[column.key]
388
+ const bValue = b[column.key]
389
+ const sortOrder = sortDirection.value === 'asc' ? 1 : -1
390
+
391
+ // Handle different data types
392
+ if (column.type === 'date') {
393
+ const dateA = new Date(aValue).getTime()
394
+ const dateB = new Date(bValue).getTime()
395
+ return (dateA - dateB) * sortOrder
396
+ }
385
397
 
386
- if (column.type === 'checkbox') {
387
- const aChecked = aValue?.modelValue || false
388
- const bChecked = bValue?.modelValue || false
389
- return (aChecked - bChecked) * sortOrder
390
- }
398
+ if (column.type === 'number') {
399
+ return (aValue - bValue) * sortOrder
400
+ }
391
401
 
392
- // Default string comparison for text and other types
393
- const stringA = String(aValue || '').toLowerCase()
394
- const stringB = String(bValue || '').toLowerCase()
395
- return stringA.localeCompare(stringB) * sortOrder
396
- })
402
+ if (column.type === 'checkbox') {
403
+ const aChecked = aValue?.modelValue || false
404
+ const bChecked = bValue?.modelValue || false
405
+ return (aChecked - bChecked) * sortOrder
406
+ }
407
+
408
+ // Default string comparison for text and other types
409
+ const stringA = String(aValue || '').toLowerCase()
410
+ const stringB = String(bValue || '').toLowerCase()
411
+ return stringA.localeCompare(stringB) * sortOrder
412
+ })
413
+ }
414
+
415
+ // Separate fixed rows by their fixed position
416
+ const topFixedRows = fixedRows.filter((row) => row.fixed === 'top')
417
+ const bottomFixedRows = fixedRows.filter((row) => row.fixed === 'bottom')
418
+
419
+ // Return rows in order: top fixed, sorted, bottom fixed
420
+ return [...topFixedRows, ...sortedRows, ...bottomFixedRows]
397
421
  })
398
422
 
399
423
  defineExpose({
package/src/types/list.ts CHANGED
@@ -38,6 +38,7 @@ interface ListColumn {
38
38
  minWidth?: string
39
39
  maxWidth?: string
40
40
  cellClasses?: conditionalClassList
41
+ headerTooltip?: string
41
42
  }
42
43
 
43
44
  interface ListFilter {
@@ -47,7 +48,7 @@ interface ListFilter {
47
48
 
48
49
  interface ListProps {
49
50
  columns: ListColumn[]
50
- data: any[]
51
+ data: ListRowData[]
51
52
  actions?: ListActionProps[]
52
53
  CSVDownload?: string
53
54
  filter?: {
@@ -76,6 +77,15 @@ interface ListIconProps {
76
77
  color?: string
77
78
  }
78
79
 
80
+ interface ListRowData {
81
+ excludeFromSort?: boolean
82
+ excludeFromFilter?: boolean
83
+ fixed?: 'top' | 'bottom'
84
+ selected?: boolean
85
+ class?: string
86
+ [key: string]: any
87
+ }
88
+
79
89
  export type {
80
90
  ListPresentation,
81
91
  ListProps,
@@ -85,4 +95,5 @@ export type {
85
95
  ListIconProps,
86
96
  ListColumn,
87
97
  ListFilter,
98
+ ListRowData,
88
99
  }
@@ -65,7 +65,13 @@
65
65
  <script setup lang="ts">
66
66
  import { ref } from 'vue'
67
67
  import List from '@/components/List.vue'
68
- import type { ListColumn, ListActionProps, ListCheckboxProps, ListIconProps } from '@/types'
68
+ import type {
69
+ ListColumn,
70
+ ListActionProps,
71
+ ListCheckboxProps,
72
+ ListIconProps,
73
+ ListRowData,
74
+ } from '@/types'
69
75
 
70
76
  const autosaveActive = (info: any) => {
71
77
  console.log('Autosave active', info)
@@ -130,6 +136,7 @@ const columns: ListColumn[] = [
130
136
  filterable: false,
131
137
  align: 'center',
132
138
  width: '4rem',
139
+ headerTooltip: 'User status indicator',
133
140
  },
134
141
  {
135
142
  key: 'name',
@@ -137,6 +144,7 @@ const columns: ListColumn[] = [
137
144
  type: 'text',
138
145
  sortable: true,
139
146
  filterable: true,
147
+ headerTooltip: 'The full name of the user',
140
148
  },
141
149
  {
142
150
  key: 'email',
@@ -144,6 +152,7 @@ const columns: ListColumn[] = [
144
152
  type: 'email',
145
153
  sortable: true,
146
154
  filterable: true,
155
+ headerTooltip: 'Contact email address',
147
156
  cellClasses: {
148
157
  lightredEmail: (value: any) => value.includes('bob'),
149
158
  },
@@ -154,6 +163,7 @@ const columns: ListColumn[] = [
154
163
  type: 'date',
155
164
  sortable: true,
156
165
  width: '6rem',
166
+ headerTooltip: 'Account creation date',
157
167
  },
158
168
  {
159
169
  key: 'active',
@@ -162,6 +172,7 @@ const columns: ListColumn[] = [
162
172
  align: 'center',
163
173
  sortable: true,
164
174
  width: '4rem',
175
+ headerTooltip: 'Account active status',
165
176
  },
166
177
  {
167
178
  key: 'actions',
@@ -172,7 +183,39 @@ const columns: ListColumn[] = [
172
183
  },
173
184
  ]
174
185
 
175
- const data = ref([
186
+ const data = ref<ListRowData[]>([
187
+ {
188
+ // This row will always appear at the top when sorting
189
+ excludeFromSort: true,
190
+ fixed: 'top',
191
+ selected: false,
192
+ select: <ListCheckboxProps>{
193
+ modelValue: false,
194
+ disabled: false,
195
+ onCheckboxClick: selectClick,
196
+ },
197
+ status: <ListIconProps>{
198
+ icon: 'crown',
199
+ color: 'gold',
200
+ },
201
+ name: 'Current User (Fixed at Top)',
202
+ email: 'current@example.com',
203
+ joined: '2024-01-01',
204
+ active: {
205
+ modelValue: true,
206
+ disabled: false,
207
+ autosave: autosaveActive,
208
+ onCheckboxClick: selectClick,
209
+ },
210
+ actions: <ListActionProps[]>[
211
+ {
212
+ id: 'edit',
213
+ label: 'Edit',
214
+ icon: 'edit',
215
+ onActionClick: rowActionClick,
216
+ },
217
+ ],
218
+ },
176
219
  {
177
220
  class: 'testclass',
178
221
  selected: false,
@@ -390,6 +433,36 @@ const data = ref([
390
433
  },
391
434
  ],
392
435
  },
436
+ {
437
+ // This row will always appear at the bottom when sorting and is excluded from filtering
438
+ excludeFromSort: true,
439
+ excludeFromFilter: true,
440
+ fixed: 'bottom',
441
+ select: <ListCheckboxProps>{
442
+ modelValue: false,
443
+ disabled: false,
444
+ onCheckboxClick: selectClick,
445
+ },
446
+ status: <ListIconProps>{
447
+ icon: 'info-circle',
448
+ color: 'blue',
449
+ },
450
+ name: 'Footer Row (Fixed at Bottom)',
451
+ email: 'footer@example.com',
452
+ joined: '2024-12-31',
453
+ active: {
454
+ modelValue: true,
455
+ disabled: false,
456
+ },
457
+ actions: <ListActionProps[]>[
458
+ {
459
+ id: 'info',
460
+ label: 'Info',
461
+ icon: 'info',
462
+ onActionClick: rowActionClick,
463
+ },
464
+ ],
465
+ },
393
466
  ])
394
467
  </script>
395
468
 
@@ -431,4 +504,8 @@ const data = ref([
431
504
  :deep(.list-test__section .list__cell.lightredEmail) {
432
505
  background-color: rgba(255, 0, 0, 0.1);
433
506
  }
507
+
508
+ :deep(.list-test__section .list__row--testclass) {
509
+ background-color: rgba(155, 155, 0, 0.1);
510
+ }
434
511
  </style>