@veristone/nuxt-v-app 0.2.11 → 0.2.14

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.
@@ -52,11 +52,12 @@
52
52
  <USelect
53
53
  v-for="filter in props.filters"
54
54
  :key="filter.key"
55
- v-model="filterValues[filter.key]"
55
+ :model-value="(filterValues[filter.key] as string)"
56
56
  :items="filter.options"
57
57
  :placeholder="filter.label"
58
58
  size="sm"
59
59
  class="w-40"
60
+ @update:model-value="(v: string) => filterValues[filter.key] = v"
60
61
  />
61
62
  </template>
62
63
 
@@ -166,50 +167,44 @@
166
167
  </template>
167
168
 
168
169
  <script setup lang="ts">
169
- /**
170
- * VATable - Veristone data table component built on Nuxt UI's UTable + TanStack Table.
171
- *
172
- * @props
173
- * name - Optional card header title
174
- * data - Row data array
175
- * columns - TanStack TableColumn definitions; supports `meta.preset` for cell rendering
176
- * loading - Shows skeleton on initial load; shows inline spinner on subsequent refreshes
177
- * initialPageLimit - Default page size (default: 10)
178
- * selectable - Enables row checkboxes; exposes `selectedRows` via template ref
179
- * showSearch - Renders a global search input in the toolbar
180
- * filters - Array of { key, label, options } for toolbar USelect dropdowns
181
- * onRefresh - Async callback; shows a refresh spinner button in the toolbar
182
- * onRowClick - Called with the row's original data when a row is clicked
183
- * defaultSort - Column key to sort by on mount
184
- * defaultSortDesc - Sort descending when defaultSort is set (default: false)
185
- * manualPagination - Enables server-side pagination mode
186
- * total - Total row count for server-side pagination
187
- *
188
- * @models (v-model)
189
- * sorting - SortingState — sync sort state with parent
190
- * filterValues - Record<string, unknown> — sync active filter values with parent
191
- * globalFilter - string sync search input value with parent
192
- * page - number (1-based) — current page in manual pagination mode
193
- * itemsPerPage - number — page size in manual pagination mode
194
- *
195
- * @slots
196
- * header-right - Content rendered on the right side of the card header
197
- * toolbar-left - Custom controls (e.g. filter selects) injected into the toolbar
198
- * next to the search input and built-in filter dropdowns
199
- * Example:
200
- * <template #toolbar-left>
201
- * <USelect v-model="status" :items="opts" placeholder="Status" size="sm" />
202
- * </template>
203
- * bulk-actions - Shown in the toolbar when rows are selected; receives
204
- * { selected, count, clear }
205
- * actions-cell - Renders an "Actions" column; receives { row }
206
- * [column]-cell - Override cell rendering for a specific column by accessor key
207
- *
208
- * @exposes
209
- * selectedRows - Array of selected row originals
210
- * rowSelection - Raw TanStack row selection state
211
- * clearSelection - Clears the current row selection
212
- */
170
+ import type { SortingState } from '@tanstack/vue-table'
171
+ import { getPaginationRowModel } from '@tanstack/vue-table'
172
+ import type { TableColumn, DropdownMenuItem } from '@nuxt/ui'
173
+ import CellRenderer from './CellRenderer.vue'
174
+
175
+ interface FilterOption {
176
+ key: string
177
+ label: string
178
+ options: { label: string; value: string }[]
179
+ }
180
+
181
+ const props = withDefaults(
182
+ defineProps<{
183
+ name?: string
184
+ data?: Record<string, unknown>[]
185
+ columns: TableColumn<any>[]
186
+ loading?: boolean
187
+ initialPageLimit?: number
188
+ selectable?: boolean
189
+ showSearch?: boolean
190
+ filters?: FilterOption[]
191
+ onRefresh?: () => Promise<void>
192
+ onRowClick?: (row: any) => void
193
+ defaultSort?: string
194
+ defaultSortDesc?: boolean
195
+ manualPagination?: boolean
196
+ total?: number
197
+ }>(),
198
+ {
199
+ data: () => [],
200
+ loading: false,
201
+ initialPageLimit: 10,
202
+ selectable: false,
203
+ showSearch: true,
204
+ defaultSortDesc: false,
205
+ manualPagination: false,
206
+ }
207
+ )
213
208
 
214
209
  // Sorting state - v-model support
215
210
  const sorting = defineModel<SortingState>("sorting", {
@@ -397,41 +392,40 @@ const tableColumns = computed(() => {
397
392
  'expiresAt', 'completedAt', 'created_at', 'updated_at'
398
393
  ]
399
394
 
400
- const columns = props.columns.map(col => {
401
- const hasDataAccessor = Boolean(col.accessorKey || (col as any).accessorFn || (col as any).key);
402
- const colDef = {
395
+ const columns: TableColumn<any>[] = props.columns.map((col) => {
396
+ const accessorKey = (col as any).accessorKey as string | undefined
397
+ const hasDataAccessor = Boolean(accessorKey || (col as any).accessorFn || (col as any).key)
398
+ const colDef: TableColumn<any> = {
403
399
  ...col,
404
400
  enableSorting: col.enableSorting ?? hasDataAccessor,
405
- };
401
+ }
406
402
 
407
- // Auto-detect date columns based on accessorKey
408
- const isDateColumn = dateColumnPatterns.includes(col.accessorKey)
403
+ const isDateColumn = accessorKey ? dateColumnPatterns.includes(accessorKey) : false
409
404
  const hasPreset = col.meta?.preset && col.meta.preset !== 'actions'
410
405
 
411
406
  if (hasPreset || isDateColumn) {
412
- // Use existing preset or auto-detected date preset
413
407
  const preset = col.meta?.preset || 'date'
414
408
  const format = col.meta?.format || 'relative'
415
409
 
416
- colDef.cell = ({ row }) => {
417
- const value = row?.original?.[col.accessorKey as string];
410
+ colDef.cell = ({ row }: { row: any }) => {
411
+ const value = accessorKey ? row?.original?.[accessorKey] : undefined
418
412
  return h(CellRenderer, {
419
413
  value,
420
414
  column: { ...col, meta: { ...col.meta, preset, format } },
421
415
  row: row?.original
422
- });
423
- };
416
+ })
417
+ }
424
418
  }
425
419
 
426
- return colDef;
427
- });
420
+ return colDef
421
+ })
428
422
 
429
423
  if (props.selectable) {
430
- const selectColumn: TableColumn<unknown> = {
424
+ const selectColumn: TableColumn<any> = {
431
425
  id: 'select',
432
426
  enableSorting: false,
433
427
  enableHiding: false,
434
- header: ({ table }) =>
428
+ header: ({ table }: { table: any }) =>
435
429
  h(UCheckbox, {
436
430
  modelValue: table.getIsSomePageRowsSelected()
437
431
  ? 'indeterminate'
@@ -440,7 +434,7 @@ const tableColumns = computed(() => {
440
434
  table.toggleAllPageRowsSelected(!!value),
441
435
  'aria-label': 'Select all rows',
442
436
  }),
443
- cell: ({ row }) =>
437
+ cell: ({ row }: { row: any }) =>
444
438
  h(UCheckbox, {
445
439
  modelValue: row.getIsSelected(),
446
440
  'onUpdate:modelValue': (value: boolean | 'indeterminate') =>
@@ -453,21 +447,20 @@ const tableColumns = computed(() => {
453
447
  td: 'w-10',
454
448
  },
455
449
  },
456
- };
450
+ }
457
451
 
458
- columns.unshift(selectColumn);
452
+ columns.unshift(selectColumn)
459
453
  }
460
454
 
461
455
  // Add actions column if slot provided AND no actions column already exists
462
- if (slots['actions-cell'] && !columns.some(c => c.id === 'actions' || c.accessorKey === 'actions')) {
463
- const actionsColumn: TableColumn<unknown> = {
456
+ if (slots['actions-cell'] && !columns.some((c: any) => c.id === 'actions' || c.accessorKey === 'actions')) {
457
+ const actionsColumn: TableColumn<any> = {
464
458
  id: 'actions',
465
459
  header: 'Actions',
466
460
  enableSorting: false,
467
461
  enableHiding: false,
468
- cell: ({ row }) => {
469
- // Render slot content
470
- return h('div', {}, slots['actions-cell']?.({ row }));
462
+ cell: ({ row }: { row: any }) => {
463
+ return h('div', {}, slots['actions-cell']?.({ row }))
471
464
  },
472
465
  meta: {
473
466
  class: {
@@ -475,9 +468,9 @@ const tableColumns = computed(() => {
475
468
  td: 'text-right',
476
469
  },
477
470
  },
478
- };
471
+ }
479
472
 
480
- columns.push(actionsColumn);
473
+ columns.push(actionsColumn)
481
474
  }
482
475
 
483
476
  return columns;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veristone/nuxt-v-app",
3
- "version": "0.2.11",
3
+ "version": "0.2.14",
4
4
  "description": "Veristone Nuxt App Layer - Shared components, composables, and layouts",
5
5
  "type": "module",
6
6
  "private": false,