@polymarbot/nuxt-layer-shadcn-ui 0.9.3 → 0.9.5
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
|
|
2
|
-
//
|
|
3
|
-
// - returns non-empty VNodes → render those
|
|
4
|
-
// -
|
|
5
|
-
//
|
|
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 —
|
|
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: '
|
|
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'
|
|
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
|
-
return formatCurrency(value as number | string, column.currency
|
|
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
|
-
|
|
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>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type DataTableColumnType = 'text' | '
|
|
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'
|
package/app/utils/index.ts
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "0.9.5",
|
|
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.
|
|
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": "
|
|
45
|
+
"gitHead": "3c225089f3f8eeeda4b21c89d863d3675bbe0cdf"
|
|
46
46
|
}
|