nicklabs-ui 1.0.86 → 1.0.88

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A Vue 3 component library with glassmorphism design, built for modern web applications.
4
4
 
5
- **Version**: 1.0.81 | **Framework**: Vue 3.5+
5
+ **Version**: 1.0.87 | **Framework**: Vue 3.5+
6
6
 
7
7
  ---
8
8
 
@@ -25,6 +25,7 @@ A Vue 3 component library with glassmorphism design, built for modern web applic
25
25
  - [NDatePicker](#ndatepicker)
26
26
  - [Data Display](#data-display)
27
27
  - [NTable](#ntable)
28
+ - [NVirtualTable](#nvirtualtable)
28
29
  - [NList](#nlist)
29
30
  - [NTag](#ntag)
30
31
  - [NEmpty](#nempty)
@@ -959,6 +960,125 @@ function handleItemClick(item: User) {
959
960
 
960
961
  ---
961
962
 
963
+ #### NVirtualTable
964
+
965
+ A virtualized data table built on `@tanstack/vue-virtual`. Only the visible rows are rendered, so it stays smooth with very large datasets. Shares the same look, sorting behavior, loading, and empty state as [NTable](#ntable), but you render each row's cells yourself through the `cell` scoped slot.
966
+
967
+ **Props**
968
+
969
+ | Prop | Type | Default | Description |
970
+ |------|------|---------|-------------|
971
+ | `columns` | `NVirtualTableColumn[]` | `[]` | Column definitions |
972
+ | `items` | `T[]` | `[]` | Row data |
973
+ | `bordered` | `boolean` | `false` | Show borders |
974
+ | `hoverable` | `boolean` | `true` | Highlight rows on hover |
975
+ | `loading` | `boolean` | `false` | Show loading state (overlay) |
976
+ | `emptyTitle` | `string` | `"目前沒有資料"` | Title when no data |
977
+ | `emptyDescription` | `string` | `"可以點擊上方的按鈕來新增資料或重新整理"` | Description when no data |
978
+ | `itemKey` | `keyof T` | `"id"` | Unique key field |
979
+ | `rowHeight` | `number` | `56` | Estimated row height in **px** (drives virtualization) |
980
+ | `height` | `string` | `"480px"` | Height of the scrollable body |
981
+ | `overscan` | `number` | `8` | Extra rows rendered above/below the viewport |
982
+ | `actionsWidth` | `string` | `"120px"` | Fixed width of the actions column (only shown when the `actions` slot is used). Increase it when you render more buttons, otherwise they get clipped |
983
+
984
+ **Events**
985
+
986
+ | Event | Payload | Description |
987
+ |-------|---------|-------------|
988
+ | `sort` | `NVirtualTableSortState` | Column sort changed |
989
+ | `click` | `T` | Row was clicked |
990
+
991
+ **Slots**
992
+
993
+ | Slot | Description |
994
+ |------|-------------|
995
+ | `cell` | Renders all cells for a row (scoped: `{ item, columns, index }`). Wrap each cell in a `.vtable-td` element for correct grid layout |
996
+ | `actions` | Custom action buttons per row (scoped: `{ item, index }`); the actions column only appears when this slot is provided |
997
+ | `actions-header` | Custom header text for the actions column (default: "操作") |
998
+ | `empty` | Custom empty state content |
999
+
1000
+ **NVirtualTableColumn Interface**
1001
+
1002
+ ```typescript
1003
+ interface NVirtualTableColumn {
1004
+ key: string // Data field key
1005
+ label: string // Column header text
1006
+ sortable?: boolean
1007
+ width?: string // CSS grid track size (e.g. "120px", "2fr"); defaults to "1fr"
1008
+ }
1009
+ ```
1010
+
1011
+ **Usage**
1012
+
1013
+ ```vue
1014
+ <template>
1015
+ <NVirtualTable
1016
+ :columns="columns"
1017
+ :items="users"
1018
+ :row-height="56"
1019
+ height="600px"
1020
+ hoverable
1021
+ @sort="handleSort"
1022
+ @click="handleItemClick"
1023
+ >
1024
+ <!-- Render every cell for the row yourself -->
1025
+ <template #cell="{ item, columns }">
1026
+ <div v-for="column in columns" :key="column.key" class="vtable-td">
1027
+ {{ item[column.key] }}
1028
+ </div>
1029
+ </template>
1030
+
1031
+ <template #actions="{ item }">
1032
+ <NButton size="sm" variant="ghost" intent="primary" @click="edit(item)">Edit</NButton>
1033
+ <NButton size="sm" variant="ghost" intent="error" @click="remove(item)">Delete</NButton>
1034
+ </template>
1035
+ </NVirtualTable>
1036
+ </template>
1037
+
1038
+ <script setup lang="ts">
1039
+ import { ref } from 'vue'
1040
+ import { NVirtualTable, NButton } from 'nicklabs-ui'
1041
+ import type { NVirtualTableColumn, NVirtualTableSortState } from 'nicklabs-ui'
1042
+
1043
+ interface User {
1044
+ id: number
1045
+ name: string
1046
+ email: string
1047
+ role: string
1048
+ }
1049
+
1050
+ const columns: NVirtualTableColumn[] = [
1051
+ { key: 'name', label: 'Name', sortable: true, width: '200px' },
1052
+ { key: 'email', label: 'Email' },
1053
+ { key: 'role', label: 'Role', width: '120px' },
1054
+ ]
1055
+
1056
+ // Virtualization shines with large datasets
1057
+ const users = ref<User[]>(
1058
+ Array.from({ length: 10000 }, (_, i) => ({
1059
+ id: i,
1060
+ name: `User ${i}`,
1061
+ email: `user${i}@example.com`,
1062
+ role: i % 2 ? 'User' : 'Admin',
1063
+ })),
1064
+ )
1065
+
1066
+ function handleSort(state: NVirtualTableSortState) {
1067
+ console.log('Sort by:', state.key, state.order)
1068
+ }
1069
+
1070
+ function handleItemClick(item: User) {
1071
+ console.log('Clicked:', item)
1072
+ }
1073
+ </script>
1074
+ ```
1075
+
1076
+ > **Sorting is emit-only.** Like [NTable](#ntable), clicking a sortable header emits `sort` with the next `{ key, order }` state — the component does not reorder `items` itself. Sort the data in the parent (or server-side) and feed it back via `items`.
1077
+
1078
+ > **Responsive width.** Flexible (`1fr` / unset) columns won't compress below a readable minimum (120px). When the columns' combined minimum width exceeds the container — e.g. on phones — the whole table scrolls horizontally (header and body in sync) instead of squishing the columns. Fixed-width columns keep their exact width.
1079
+
1080
+ ---
1081
+
962
1082
  #### NList
963
1083
 
964
1084
  A full-featured data management component combining table, pagination, filtering, and CRUD operations.