@polymarbot/nuxt-layer-shadcn-ui 0.9.4 → 0.9.6

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.
@@ -1,10 +1,11 @@
1
- // Wraps a scoped table-cell slot. Branches by `slotFn` state:
2
- // - missing → render `#default` (no custom slot; show normal value)
3
- // - returns non-empty VNodes → render those
4
- // - returns empty (only Comment / empty Text / empty Fragment) → render
5
- // `#empty` (slot is authoritative don't fall back to the value)
1
+ // Wraps a scoped table-cell slot and centralizes "is this cell empty?".
2
+ // Routing:
3
+ // - `slotFn` provided and returns non-empty VNodes → render those
4
+ // - `slotFn` provided and returns empty render `#empty`
5
+ // - no `slotFn`, `empty` is true → render `#empty`
6
+ // - no `slotFn`, `empty` is false → render `#default`
6
7
  //
7
- // Empty detection catches `v-if` / `{{ value }}` returning nothing — but a
8
+ // Empty VNode detection catches `v-if` / `{{ value }}` returning nothing — a
8
9
  // rendered element with no content (e.g. `<div/>`) still counts as non-empty.
9
10
 
10
11
  import { Comment, Fragment, Text, type FunctionalComponent, type VNode } from 'vue'
@@ -26,15 +27,17 @@ function isEmptyVNodes (vnodes: VNode[] | undefined): boolean {
26
27
  const CellSlot: FunctionalComponent<{
27
28
  slotFn?: (scope: Record<string, unknown>) => VNode[]
28
29
  scope: Record<string, unknown>
30
+ /** When no `slotFn` is provided, signals that the underlying value is empty. */
31
+ empty?: boolean
29
32
  }> = (props, { slots }) => {
30
33
  if (props.slotFn) {
31
34
  const vnodes = props.slotFn(props.scope)
32
35
  if (!isEmptyVNodes(vnodes)) return vnodes
33
36
  return slots.empty?.()
34
37
  }
35
- return slots.default?.()
38
+ return props.empty ? slots.empty?.() : slots.default?.()
36
39
  }
37
- CellSlot.props = [ 'slotFn', 'scope' ]
40
+ CellSlot.props = [ 'slotFn', 'scope', 'empty' ]
38
41
  CellSlot.inheritAttrs = false
39
42
 
40
43
  export default CellSlot
@@ -10,15 +10,16 @@ interface User {
10
10
  role: string
11
11
  status: string
12
12
  amount: number
13
+ views: number
13
14
  createdAt: string
14
15
  }
15
16
 
16
17
  const sampleData: User[] = [
17
- { id: 1, name: 'Alice', email: 'alice@example.com', role: 'Admin', status: 'active', amount: 1234.56, createdAt: '2024-01-15T10:30:00Z' },
18
- { id: 2, name: 'Bob', email: 'bob@example.com', role: 'User', status: 'active', amount: 789.0, createdAt: '2024-02-20T14:15:00Z' },
19
- { id: 3, name: 'Charlie', email: 'charlie@example.com', role: 'Editor', status: 'inactive', amount: 2345.67, createdAt: '2024-03-10T09:00:00Z' },
20
- { id: 4, name: 'Diana', email: 'diana@example.com', role: 'Admin', status: 'active', amount: 456.78, createdAt: '2024-04-05T16:45:00Z' },
21
- { id: 5, name: 'Eve', email: 'eve@example.com', role: 'User', status: 'inactive', amount: 3456.89, createdAt: '2024-05-12T11:20:00Z' },
18
+ { id: 1, name: 'Alice', email: 'alice@example.com', role: 'Admin', status: 'active', amount: 1234.56, views: 12345, createdAt: '2024-01-15T10:30:00Z' },
19
+ { id: 2, name: 'Bob', email: 'bob@example.com', role: 'User', status: 'active', amount: 789.0, views: 678, createdAt: '2024-02-20T14:15:00Z' },
20
+ { id: 3, name: 'Charlie', email: 'charlie@example.com', role: 'Editor', status: 'inactive', amount: 2345.67, views: 1234567, createdAt: '2024-03-10T09:00:00Z' },
21
+ { id: 4, name: 'Diana', email: 'diana@example.com', role: 'Admin', status: 'active', amount: 456.78, views: 42, createdAt: '2024-04-05T16:45:00Z' },
22
+ { id: 5, name: 'Eve', email: 'eve@example.com', role: 'User', status: 'inactive', amount: 3456.89, views: 98765, createdAt: '2024-05-12T11:20:00Z' },
22
23
  ]
23
24
 
24
25
  const longData: User[] = Array.from({ length: 30 }, (_, i) => ({
@@ -28,6 +29,7 @@ const longData: User[] = Array.from({ length: 30 }, (_, i) => ({
28
29
  role: [ 'Admin', 'Editor', 'User' ][i % 3]!,
29
30
  status: i % 4 === 0 ? 'inactive' : 'active',
30
31
  amount: Math.round(Math.random() * 10000) / 100,
32
+ views: Math.round(Math.random() * 1_000_000),
31
33
  createdAt: new Date(2024, 0, 1 + i).toISOString(),
32
34
  }))
33
35
 
@@ -48,9 +50,9 @@ const sortableColumns: DataTableColumn[] = [
48
50
 
49
51
  const typeColumns: DataTableColumn[] = [
50
52
  { field: 'name', title: 'Name', width: '120px' },
53
+ { field: 'views', title: 'Views', width: '120px', type: 'number', align: 'right' },
51
54
  { field: 'amount', title: 'Amount', width: '120px', type: 'currency' },
52
55
  { field: 'createdAt', title: 'Date', width: '140px', type: 'date' },
53
- { field: 'status', title: 'Empty', width: '100px', type: 'empty' },
54
56
  ]
55
57
 
56
58
  const slotColumns: DataTableColumn[] = [
@@ -547,13 +549,13 @@ export const CellSlotEmptyFallback: Story = {
547
549
  const data = [
548
550
  { name: 'Empty value (no slot)', email: '', status: 'active', action: 'Edit' },
549
551
  { name: 'Empty slot output', email: 'demo@example.com', status: 'pending', action: 'Edit' },
550
- { name: 'Column type=\'empty\'', email: 'demo@example.com', status: 'active', action: '' },
552
+ { name: 'Empty value with slot', email: 'demo@example.com', status: 'active', action: '' },
551
553
  ]
552
554
  const columns: DataTableColumn[] = [
553
555
  { field: 'name', title: 'Demo case', minWidth: '200px' },
554
556
  { field: 'email', title: 'Email', minWidth: '200px' },
555
557
  { field: 'status', title: 'Status', width: '120px' },
556
- { field: 'action', title: 'Action', width: '120px', type: 'empty' },
558
+ { field: 'action', title: 'Action', width: '120px' },
557
559
  ]
558
560
  return { data, columns }
559
561
  },
@@ -141,14 +141,14 @@ function formatCellValue (value: unknown, column: DataTableColumn): string {
141
141
  case 'unixDate':
142
142
  return formatDateTime((value as number) * 1000).split(' ').join('\n')
143
143
 
144
+ case 'number':
145
+ return formatNumber(value as number | string)
146
+
144
147
  case 'currency':
145
148
  return formatCurrency(value as number | string, column.currency, {
146
149
  currencyDisplay: column.currencyDisplay,
147
150
  })
148
151
 
149
- case 'empty':
150
- return ''
151
-
152
152
  default:
153
153
  return String(value)
154
154
  }
@@ -421,20 +421,12 @@ defineExpose({
421
421
  <CellSlot
422
422
  :slotFn="$slots[column.field]"
423
423
  :scope="{ column, row, value: get(row, column.field), index }"
424
+ :empty="!formatCellValue(get(row, column.field), column)"
424
425
  >
425
426
  <template #default>
426
- <span
427
- v-if="!formatCellValue(get(row, column.field), column) && column.type !== 'empty'"
428
- :class="emptyCellClass"
429
- />
430
- <template v-else>
431
- {{ formatCellValue(get(row, column.field), column) }}
432
- </template>
427
+ {{ formatCellValue(get(row, column.field), column) }}
433
428
  </template>
434
- <template
435
- v-if="column.type !== 'empty'"
436
- #empty
437
- >
429
+ <template #empty>
438
430
  <span :class="emptyCellClass" />
439
431
  </template>
440
432
  </CellSlot>
@@ -443,7 +435,7 @@ defineExpose({
443
435
  </template>
444
436
 
445
437
  <TableRow
446
- v-else-if="!loading"
438
+ v-else
447
439
  data-virtual-row
448
440
  class="hover:bg-transparent"
449
441
  >
@@ -1,4 +1,4 @@
1
- export type DataTableColumnType = 'text' | 'date' | 'unixDate' | 'currency' | 'empty'
1
+ export type DataTableColumnType = 'text' | 'number' | 'date' | 'unixDate' | 'currency'
2
2
  export type DataTableColumnFixed = 'left' | 'right'
3
3
  export type DataTableColumnAlign = 'left' | 'center' | 'right'
4
4
  export type DataTableSelectionMode = 'single' | 'multiple'
@@ -3,4 +3,4 @@
3
3
  // Also serves as the shadcn CLI `utils` alias (see components.json).
4
4
  export { cn } from '@polymarbot/uitls-shared/vue/utils'
5
5
  export { safeHtml } from '@polymarbot/uitls-shared/utils-browser'
6
- export { isUrl, formatCurrency } from '@polymarbot/uitls-shared/utils'
6
+ export { isUrl, formatCurrency, formatNumber } from '@polymarbot/uitls-shared/utils'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polymarbot/nuxt-layer-shadcn-ui",
3
- "version": "0.9.4",
3
+ "version": "0.9.6",
4
4
  "description": "Nuxt layer providing shadcn-vue based UI components",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@polymarbot/nuxt-layer-basic": "^0.1",
21
- "@polymarbot/uitls-shared": "^0.6.1",
21
+ "@polymarbot/uitls-shared": "^0.6",
22
22
  "@tanstack/vue-table": "^8.21.3",
23
23
  "@types/lodash-es": "^4.17.12",
24
24
  "@types/qrcode": "^1.5.6",
@@ -42,5 +42,5 @@
42
42
  "vue-i18n": "^11",
43
43
  "vue-router": "^4 || ^5"
44
44
  },
45
- "gitHead": "9d816af97015b542dcfd6aae1ea8056f286a9891"
45
+ "gitHead": "908af6ffb1f55a62f62ee6bc17ca26b3f644ac32"
46
46
  }