@nova-design-system/nova-vue 3.19.0 → 3.21.0
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 +0 -20
- package/dist/components/NvDatatable.d.ts +137 -90
- package/dist/components/NvDatatable.js +238 -130
- package/dist/generated/components.d.ts +1 -0
- package/dist/generated/components.js +9 -2
- package/dist/providers/NotificationService.d.ts +2 -0
- package/dist/providers/NotificationService.js +27 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,26 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
**Nova Components Vue** provides an easy way to use [Nova’s native Web Components](https://www.npmjs.com/package/@nova-design-system/nova-webcomponents) within your Vue applications.
|
|
4
4
|
|
|
5
|
-
- [Nova Components Vue](#nova-components-vue)
|
|
6
|
-
- [Key Features](#key-features)
|
|
7
|
-
- [Installation](#installation)
|
|
8
|
-
- [Setting up Tailwind](#setting-up-tailwind)
|
|
9
|
-
- [About Tailwind and the Nova Plugin](#about-tailwind-and-the-nova-plugin)
|
|
10
|
-
- [1. Install Tailwind CSS and the Vite Plugin](#1-install-tailwind-css-and-the-vite-plugin)
|
|
11
|
-
- [2. Configure the Vite Plugin](#2-configure-the-vite-plugin)
|
|
12
|
-
- [3. Create `tailwind.config.ts`](#3-create-tailwindconfigts)
|
|
13
|
-
- [4. Configure Tailwind and Nova Plugin in `main.css`](#4-configure-tailwind-and-nova-plugin-in-maincss)
|
|
14
|
-
- [5. Register NovaComponents and include the Nova Tokens](#5-register-novacomponents-and-include-the-nova-tokens)
|
|
15
|
-
- [6. Use Nova Components with Tailwind Utilities](#6-use-nova-components-with-tailwind-utilities)
|
|
16
|
-
- [7. Setup the Nova Font](#7-setup-the-nova-font)
|
|
17
|
-
- [Creating Your Own Style Components with Tailwind](#creating-your-own-style-components-with-tailwind)
|
|
18
|
-
- [Nova Font Pro Integration](#nova-font-pro-integration)
|
|
19
|
-
- [Option 1: Import in Global CSS (Recommended)](#option-1-import-in-global-css-recommended)
|
|
20
|
-
- [Option 2: HTML Integration](#option-2-html-integration)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
5
|
## Key Features
|
|
26
6
|
|
|
27
7
|
- **Lightweight Integration**: Leverage Nova Web Components with minimal configuration in Vue.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type VNode, type PropType } from 'vue';
|
|
2
|
+
import { type SortingState } from '@tanstack/vue-table';
|
|
2
3
|
/**
|
|
3
4
|
* Creates a typed NvDatatable component for a specific row type. This is the
|
|
4
5
|
* standard approach for generic components in Vue.
|
|
@@ -6,9 +7,9 @@ import { type VNode, type PropType } from 'vue';
|
|
|
6
7
|
* @returns {component} A Vue component definition typed for the specified row
|
|
7
8
|
* type.
|
|
8
9
|
*/
|
|
9
|
-
export declare function createNvDatatable<T
|
|
10
|
+
export declare function createNvDatatable<T>(): import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
10
11
|
columns: {
|
|
11
|
-
type: PropType<NvDatatableColumn<T>[]>;
|
|
12
|
+
type: PropType<NvDatatableColumn<T, keyof T, T[keyof T]>[]>;
|
|
12
13
|
required: true;
|
|
13
14
|
default: () => any[];
|
|
14
15
|
};
|
|
@@ -21,6 +22,10 @@ export declare function createNvDatatable<T extends NvDatatableRow>(): import("v
|
|
|
21
22
|
type: PropType<NvDatatablePaginationConfig>;
|
|
22
23
|
default: any;
|
|
23
24
|
};
|
|
25
|
+
sorting: {
|
|
26
|
+
type: PropType<NvDatatableSortingConfig>;
|
|
27
|
+
default: any;
|
|
28
|
+
};
|
|
24
29
|
renderPagination: {
|
|
25
30
|
type: PropType<(api: NvDatatableRenderPaginationAPI) => VNode>;
|
|
26
31
|
default: any;
|
|
@@ -33,7 +38,7 @@ export declare function createNvDatatable<T extends NvDatatableRow>(): import("v
|
|
|
33
38
|
[key: string]: any;
|
|
34
39
|
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
35
40
|
columns: {
|
|
36
|
-
type: PropType<NvDatatableColumn<T>[]>;
|
|
41
|
+
type: PropType<NvDatatableColumn<T, keyof T, T[keyof T]>[]>;
|
|
37
42
|
required: true;
|
|
38
43
|
default: () => any[];
|
|
39
44
|
};
|
|
@@ -46,6 +51,10 @@ export declare function createNvDatatable<T extends NvDatatableRow>(): import("v
|
|
|
46
51
|
type: PropType<NvDatatablePaginationConfig>;
|
|
47
52
|
default: any;
|
|
48
53
|
};
|
|
54
|
+
sorting: {
|
|
55
|
+
type: PropType<NvDatatableSortingConfig>;
|
|
56
|
+
default: any;
|
|
57
|
+
};
|
|
49
58
|
renderPagination: {
|
|
50
59
|
type: PropType<(api: NvDatatableRenderPaginationAPI) => VNode>;
|
|
51
60
|
default: any;
|
|
@@ -55,95 +64,92 @@ export declare function createNvDatatable<T extends NvDatatableRow>(): import("v
|
|
|
55
64
|
default: boolean;
|
|
56
65
|
};
|
|
57
66
|
}>> & Readonly<{}>, {
|
|
58
|
-
columns: NvDatatableColumn<T>[];
|
|
67
|
+
columns: NvDatatableColumn<T, keyof T, T[keyof T]>[];
|
|
59
68
|
rows: T[];
|
|
60
69
|
pagination: NvDatatablePaginationConfig;
|
|
70
|
+
sorting: NvDatatableSortingConfig;
|
|
61
71
|
renderPagination: (api: NvDatatableRenderPaginationAPI) => VNode;
|
|
62
72
|
stickyHeader: boolean;
|
|
63
73
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
74
|
+
/********************************* UTILS **************************************/
|
|
64
75
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
76
|
+
* Creates a strongly-typed column factory for a given row type.
|
|
77
|
+
*
|
|
78
|
+
* @template Row The row data type (e.g., `Product`)
|
|
79
|
+
*
|
|
80
|
+
* @returns {function} A function that accepts a column definition and infers:
|
|
81
|
+
* - `K` as the field key (`keyof Row`)
|
|
82
|
+
* - `F` as the return type of `valueFormatter` (defaults to `Row[K]`)
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* // Define your row type
|
|
87
|
+
* interface Product {
|
|
88
|
+
* name: string;
|
|
89
|
+
* price: number;
|
|
90
|
+
* }
|
|
91
|
+
*
|
|
92
|
+
* const col = makeColumn<Product>();
|
|
67
93
|
*/
|
|
68
|
-
export declare
|
|
69
|
-
columns: {
|
|
70
|
-
type: PropType<NvDatatableColumn<NvDatatableRow>[]>;
|
|
71
|
-
required: true;
|
|
72
|
-
default: () => any[];
|
|
73
|
-
};
|
|
74
|
-
rows: {
|
|
75
|
-
type: PropType<NvDatatableRow[]>;
|
|
76
|
-
required: true;
|
|
77
|
-
default: () => any[];
|
|
78
|
-
};
|
|
79
|
-
pagination: {
|
|
80
|
-
type: PropType<NvDatatablePaginationConfig>;
|
|
81
|
-
default: any;
|
|
82
|
-
};
|
|
83
|
-
renderPagination: {
|
|
84
|
-
type: PropType<(api: NvDatatableRenderPaginationAPI) => VNode>;
|
|
85
|
-
default: any;
|
|
86
|
-
};
|
|
87
|
-
stickyHeader: {
|
|
88
|
-
type: BooleanConstructor;
|
|
89
|
-
default: boolean;
|
|
90
|
-
};
|
|
91
|
-
}>, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
92
|
-
[key: string]: any;
|
|
93
|
-
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
94
|
-
columns: {
|
|
95
|
-
type: PropType<NvDatatableColumn<NvDatatableRow>[]>;
|
|
96
|
-
required: true;
|
|
97
|
-
default: () => any[];
|
|
98
|
-
};
|
|
99
|
-
rows: {
|
|
100
|
-
type: PropType<NvDatatableRow[]>;
|
|
101
|
-
required: true;
|
|
102
|
-
default: () => any[];
|
|
103
|
-
};
|
|
104
|
-
pagination: {
|
|
105
|
-
type: PropType<NvDatatablePaginationConfig>;
|
|
106
|
-
default: any;
|
|
107
|
-
};
|
|
108
|
-
renderPagination: {
|
|
109
|
-
type: PropType<(api: NvDatatableRenderPaginationAPI) => VNode>;
|
|
110
|
-
default: any;
|
|
111
|
-
};
|
|
112
|
-
stickyHeader: {
|
|
113
|
-
type: BooleanConstructor;
|
|
114
|
-
default: boolean;
|
|
115
|
-
};
|
|
116
|
-
}>> & Readonly<{}>, {
|
|
117
|
-
columns: NvDatatableColumn<NvDatatableRow>[];
|
|
118
|
-
rows: NvDatatableRow[];
|
|
119
|
-
pagination: NvDatatablePaginationConfig;
|
|
120
|
-
renderPagination: (api: NvDatatableRenderPaginationAPI) => VNode;
|
|
121
|
-
stickyHeader: boolean;
|
|
122
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
94
|
+
export declare function makeColumn<Row>(): <K extends keyof Row, F = Row[K]>(col: NvDatatableColumn<Row, K, F>) => NvDatatableColumn<Row, keyof Row, Row[keyof Row]>;
|
|
123
95
|
/********************************* TYPES **************************************/
|
|
124
96
|
/**
|
|
125
|
-
*
|
|
97
|
+
* Slot props for NvDatatable cell slots.
|
|
98
|
+
* Use this type to provide type safety for custom cell slot implementations.
|
|
99
|
+
*
|
|
100
|
+
* @template Row The row data type
|
|
101
|
+
* @template K The field key (keyof Row)
|
|
102
|
+
* @template F The formatted value type (defaults to Row[K])
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* type PersonRow = {
|
|
107
|
+
* id: number;
|
|
108
|
+
* isActive: boolean;
|
|
109
|
+
* };
|
|
110
|
+
*
|
|
111
|
+
* // For a column with valueFormatter that returns string
|
|
112
|
+
* type StatusSlotProps = NvDatatableSlotProps<PersonRow, 'isActive', string>;
|
|
113
|
+
*
|
|
114
|
+
* // For a column without valueFormatter (uses raw value)
|
|
115
|
+
* type IdSlotProps = NvDatatableSlotProps<PersonRow, 'id', number>;
|
|
116
|
+
* ```
|
|
126
117
|
*/
|
|
127
|
-
export
|
|
118
|
+
export interface NvDatatableSlotProps<Row, K extends keyof Row = keyof Row, F = Row[K]> {
|
|
119
|
+
/** The cell value (formatted if valueFormatter was used) */
|
|
120
|
+
value: F;
|
|
121
|
+
/** The full row data */
|
|
122
|
+
row: Row;
|
|
123
|
+
/** The field name */
|
|
124
|
+
field: K;
|
|
125
|
+
/** The row index (zero-based) */
|
|
126
|
+
rowIndex: number;
|
|
127
|
+
}
|
|
128
128
|
/**
|
|
129
|
-
*
|
|
129
|
+
* Props for NvDatatable component.
|
|
130
130
|
*/
|
|
131
|
-
export interface
|
|
132
|
-
/**
|
|
133
|
-
|
|
131
|
+
export interface NvDatatableProps<T> {
|
|
132
|
+
/** Column definitions */
|
|
133
|
+
columns: Array<NvDatatableColumn<T>>;
|
|
134
134
|
/** Row data */
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
|
|
135
|
+
rows: Array<T>;
|
|
136
|
+
/** Optional pagination configuration */
|
|
137
|
+
pagination?: NvDatatablePaginationConfig;
|
|
138
|
+
/** Optional render function for custom pagination UI */
|
|
139
|
+
renderPagination?: (api: NvDatatableRenderPaginationAPI) => VNode;
|
|
140
|
+
/** Should the header stick to the top of the table when scrolling? */
|
|
141
|
+
stickyHeader?: boolean;
|
|
142
|
+
/** CSS class */
|
|
143
|
+
class?: string;
|
|
144
|
+
/** Inline styles */
|
|
145
|
+
style?: string | Record<string, string>;
|
|
140
146
|
}
|
|
141
147
|
/**
|
|
142
148
|
* Column definition for NvDatatable.
|
|
143
149
|
*/
|
|
144
|
-
export interface NvDatatableColumn<
|
|
150
|
+
export interface NvDatatableColumn<Row, K extends keyof Row = keyof Row, F = Row[K]> {
|
|
145
151
|
/** Field name from row data */
|
|
146
|
-
field:
|
|
152
|
+
field: K;
|
|
147
153
|
/** Display name for column header */
|
|
148
154
|
headerName?: string;
|
|
149
155
|
/** Column width in pixels */
|
|
@@ -152,27 +158,44 @@ export interface NvDatatableColumn<T extends NvDatatableRow> {
|
|
|
152
158
|
resizable?: boolean;
|
|
153
159
|
/** Whether column is hidden */
|
|
154
160
|
hidden?: boolean;
|
|
161
|
+
/** Transform the raw value before rendering. Receives the cell value and full row object. */
|
|
162
|
+
valueFormatter?: (params: NvTableValueFormatterParams<Row, Row[K], K>) => F;
|
|
155
163
|
/** Custom cell renderer */
|
|
156
|
-
renderCell?: (params: NvTableRenderCellParams<
|
|
164
|
+
renderCell?: (params: NvTableRenderCellParams<Row, F, K>) => VNode | string | number;
|
|
165
|
+
/** Enable/disable sorting for this column */
|
|
166
|
+
sortable?: boolean;
|
|
167
|
+
/** Custom sorting function or built-in function name */
|
|
168
|
+
sortingFn?: ((rowA: any, rowB: any, columnId: string) => number) | string;
|
|
169
|
+
/** Start with descending sort for this column */
|
|
170
|
+
sortDescFirst?: boolean;
|
|
171
|
+
/** Invert the sort order (useful for rankings) */
|
|
172
|
+
invertSorting?: boolean;
|
|
173
|
+
/** Where to place undefined values in sort */
|
|
174
|
+
sortUndefined?: 'first' | 'last' | false | -1 | 1;
|
|
157
175
|
}
|
|
158
176
|
/**
|
|
159
|
-
*
|
|
177
|
+
* Parameters for custom cell rendering function.
|
|
160
178
|
*/
|
|
161
|
-
export interface
|
|
162
|
-
/**
|
|
163
|
-
|
|
179
|
+
export interface NvTableRenderCellParams<Row, Value, Field> {
|
|
180
|
+
/** Cell value */
|
|
181
|
+
value: Value;
|
|
164
182
|
/** Row data */
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
183
|
+
row: Row;
|
|
184
|
+
/** Field name */
|
|
185
|
+
field: Field;
|
|
186
|
+
/** Row index */
|
|
187
|
+
rowIndex: number;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Parameters for valueFormatter function.
|
|
191
|
+
*/
|
|
192
|
+
export interface NvTableValueFormatterParams<Row, Value, Field> {
|
|
193
|
+
/** Cell original value */
|
|
194
|
+
value: Value;
|
|
195
|
+
/** Row data */
|
|
196
|
+
row: Row;
|
|
197
|
+
/** Field name */
|
|
198
|
+
field: Field;
|
|
176
199
|
}
|
|
177
200
|
/**
|
|
178
201
|
* Pagination configuration for NvDatatable.
|
|
@@ -238,3 +261,27 @@ export interface NvDatatableRenderPaginationAPI {
|
|
|
238
261
|
/** Whether more items are available (only for infinite scroll) */
|
|
239
262
|
hasMore?: boolean;
|
|
240
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Sorting configuration for NvDatatable.
|
|
266
|
+
* Supports both client-side and server-side sorting.
|
|
267
|
+
*/
|
|
268
|
+
export interface NvDatatableSortingConfig {
|
|
269
|
+
/** Sorting mode */
|
|
270
|
+
mode: 'client' | 'server';
|
|
271
|
+
/** Enable multi-column sorting with Shift+Click */
|
|
272
|
+
enableMultiSort?: boolean;
|
|
273
|
+
/** Allow cycling through to "no sort" state */
|
|
274
|
+
enableSortingRemoval?: boolean;
|
|
275
|
+
/** Maximum number of columns for multi-sort */
|
|
276
|
+
maxMultiSortColCount?: number;
|
|
277
|
+
/** Start with descending sort as first toggle state */
|
|
278
|
+
sortDescFirst?: boolean;
|
|
279
|
+
/** Controlled sort state (for server-side sorting) */
|
|
280
|
+
sortState?: SortingState;
|
|
281
|
+
/** Callback when sorting changes (for server-side sorting) */
|
|
282
|
+
onSortingChange?: (sorting: SortingState) => void;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Sorting state type - array of sort descriptors
|
|
286
|
+
*/
|
|
287
|
+
export type NvDataTableSortingState = SortingState;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
2
2
|
import { defineComponent, computed, h, ref, watch, watchEffect, onUnmounted, } from 'vue';
|
|
3
|
-
import { useVueTable, getCoreRowModel, getPaginationRowModel, } from '@tanstack/vue-table';
|
|
4
|
-
import { NvTable } from '../generated/components';
|
|
3
|
+
import { useVueTable, getCoreRowModel, getPaginationRowModel, getSortedRowModel, } from '@tanstack/vue-table';
|
|
4
|
+
import { NvTable, NvTableheader } from '../generated/components';
|
|
5
5
|
/**
|
|
6
6
|
* Creates a typed NvDatatable component for a specific row type. This is the
|
|
7
7
|
* standard approach for generic components in Vue.
|
|
@@ -27,6 +27,10 @@ export function createNvDatatable() {
|
|
|
27
27
|
type: Object,
|
|
28
28
|
default: undefined,
|
|
29
29
|
},
|
|
30
|
+
sorting: {
|
|
31
|
+
type: Object,
|
|
32
|
+
default: undefined,
|
|
33
|
+
},
|
|
30
34
|
renderPagination: {
|
|
31
35
|
type: Function,
|
|
32
36
|
default: undefined,
|
|
@@ -42,59 +46,75 @@ export function createNvDatatable() {
|
|
|
42
46
|
pageIndex: 0,
|
|
43
47
|
pageSize: props.pagination?.initialPageSize || 10,
|
|
44
48
|
});
|
|
49
|
+
// Sorting state (controlled or uncontrolled)
|
|
50
|
+
const sortingState = ref(props.sorting?.sortState || []);
|
|
45
51
|
// Ref for observing last row (infinite scroll)
|
|
46
52
|
const lastRowRef = ref(null);
|
|
47
53
|
const tableColumns = computed(() => props.columns
|
|
48
54
|
.filter((col) => !col.hidden)
|
|
49
|
-
.map((col) =>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return
|
|
55
|
+
.map((col) => {
|
|
56
|
+
const columnDef = {
|
|
57
|
+
accessorKey: col.field,
|
|
58
|
+
accessorFn: col.valueFormatter
|
|
59
|
+
? (row) => {
|
|
60
|
+
const rawValue = row[col.field];
|
|
61
|
+
return col.valueFormatter({
|
|
62
|
+
value: rawValue,
|
|
63
|
+
row,
|
|
64
|
+
field: col.field,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
: undefined,
|
|
68
|
+
header: col.headerName || String(col.field),
|
|
69
|
+
size: col.width,
|
|
70
|
+
enableResizing: col.resizable ?? true,
|
|
71
|
+
// Sorting configuration
|
|
72
|
+
enableSorting: props.sorting ? col.sortable ?? true : false,
|
|
73
|
+
cell: (context) => {
|
|
74
|
+
const value = context.getValue();
|
|
75
|
+
const row = context.row.original;
|
|
76
|
+
const rowIndex = context.row.index;
|
|
77
|
+
const field = col.field;
|
|
78
|
+
// Priority: slot > renderCell > default
|
|
79
|
+
// Sanitize field name to ensure valid HTML attribute name
|
|
80
|
+
// Replace invalid characters (anything not a-z, A-Z, 0-9, -, _) with underscore
|
|
81
|
+
const sanitizedField = String(field).replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
82
|
+
const slotName = `cell-${sanitizedField}`;
|
|
83
|
+
if (slots[slotName]) {
|
|
84
|
+
return slots[slotName]({ value, row, field, rowIndex });
|
|
85
|
+
}
|
|
86
|
+
// Use custom renderCell if provided
|
|
87
|
+
if (col.renderCell) {
|
|
88
|
+
return col.renderCell({
|
|
89
|
+
value,
|
|
90
|
+
row,
|
|
91
|
+
field,
|
|
92
|
+
rowIndex,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// Default rendering
|
|
96
|
+
return value;
|
|
91
97
|
},
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
+
};
|
|
99
|
+
// Add optional sorting properties only if defined
|
|
100
|
+
if (col.sortingFn !== undefined) {
|
|
101
|
+
// @ts-expect-error - TanStack typing is strict but this works at runtime
|
|
102
|
+
columnDef.sortingFn = col.sortingFn;
|
|
103
|
+
}
|
|
104
|
+
if (col.sortDescFirst !== undefined) {
|
|
105
|
+
columnDef.sortDescFirst = col.sortDescFirst;
|
|
106
|
+
}
|
|
107
|
+
if (col.invertSorting !== undefined) {
|
|
108
|
+
columnDef.invertSorting = col.invertSorting;
|
|
109
|
+
}
|
|
110
|
+
if (col.sortUndefined !== undefined) {
|
|
111
|
+
columnDef.sortUndefined = col.sortUndefined;
|
|
112
|
+
}
|
|
113
|
+
return columnDef;
|
|
114
|
+
}));
|
|
115
|
+
// Determine base table configuration with sorting
|
|
116
|
+
const getBaseTableConfig = () => {
|
|
117
|
+
const baseConfig = {
|
|
98
118
|
get data() {
|
|
99
119
|
return computed(() => props.rows);
|
|
100
120
|
},
|
|
@@ -102,54 +122,103 @@ export function createNvDatatable() {
|
|
|
102
122
|
return tableColumns.value;
|
|
103
123
|
},
|
|
104
124
|
getCoreRowModel: getCoreRowModel(),
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
125
|
+
// Sorting configuration
|
|
126
|
+
...(props.sorting && {
|
|
127
|
+
get state() {
|
|
128
|
+
return {
|
|
129
|
+
sorting: props.sorting.mode === 'server' && props.sorting.sortState
|
|
130
|
+
? props.sorting.sortState
|
|
131
|
+
: sortingState.value,
|
|
132
|
+
};
|
|
110
133
|
},
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
134
|
+
onSortingChange: (updaterOrValue) => {
|
|
135
|
+
const currentSort = props.sorting.mode === 'server' && props.sorting.sortState
|
|
136
|
+
? props.sorting.sortState
|
|
137
|
+
: sortingState.value;
|
|
138
|
+
const newSort = typeof updaterOrValue === 'function'
|
|
139
|
+
? updaterOrValue(currentSort)
|
|
140
|
+
: updaterOrValue;
|
|
141
|
+
// Always update internal state for reactivity
|
|
142
|
+
sortingState.value = newSort;
|
|
143
|
+
// For server-side sorting, also call the callback
|
|
144
|
+
if (props.sorting?.mode === 'server' &&
|
|
145
|
+
props.sorting.onSortingChange) {
|
|
146
|
+
props.sorting.onSortingChange(newSort);
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
manualSorting: props.sorting.mode === 'server',
|
|
150
|
+
enableSorting: true,
|
|
151
|
+
enableMultiSort: props.sorting.enableMultiSort ?? false,
|
|
152
|
+
enableSortingRemoval: props.sorting.enableSortingRemoval ?? true,
|
|
153
|
+
maxMultiSortColCount: props.sorting.maxMultiSortColCount,
|
|
154
|
+
sortDescFirst: props.sorting.sortDescFirst ?? false,
|
|
155
|
+
// When multi-sort is enabled, treat all clicks as multi-sort events
|
|
156
|
+
isMultiSortEvent: props.sorting.enableMultiSort
|
|
157
|
+
? () => true
|
|
158
|
+
: undefined,
|
|
159
|
+
getSortedRowModel: props.sorting.mode === 'client' ? getSortedRowModel() : undefined,
|
|
160
|
+
}),
|
|
161
|
+
};
|
|
162
|
+
return baseConfig;
|
|
163
|
+
};
|
|
164
|
+
// Create reactive table instance based on pagination mode
|
|
165
|
+
const table = computed(() => {
|
|
166
|
+
const baseConfig = getBaseTableConfig();
|
|
167
|
+
if (!props.pagination || props.pagination.mode === 'infinite') {
|
|
168
|
+
// No pagination or infinite scroll - simple config
|
|
169
|
+
return useVueTable(baseConfig);
|
|
170
|
+
}
|
|
171
|
+
else if (props.pagination.mode === 'client') {
|
|
172
|
+
// Client-side pagination - table manages its own state
|
|
173
|
+
return useVueTable({
|
|
174
|
+
...baseConfig,
|
|
175
|
+
getPaginationRowModel: getPaginationRowModel(),
|
|
176
|
+
initialState: {
|
|
177
|
+
pagination: {
|
|
178
|
+
pageIndex: 0,
|
|
179
|
+
pageSize: props.pagination.initialPageSize || 10,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
// Server-side pagination - manual pagination with reactive state
|
|
186
|
+
return useVueTable({
|
|
187
|
+
...baseConfig,
|
|
188
|
+
manualPagination: true,
|
|
189
|
+
get pageCount() {
|
|
190
|
+
if (!props.pagination || props.pagination.mode !== 'server') {
|
|
191
|
+
return -1;
|
|
192
|
+
}
|
|
193
|
+
const pageSize = paginationState.value.pageSize;
|
|
194
|
+
if (props.pagination.totalPageCount !== undefined) {
|
|
195
|
+
return props.pagination.totalPageCount;
|
|
196
|
+
}
|
|
197
|
+
else if (props.pagination.totalRowCount !== undefined) {
|
|
198
|
+
return Math.ceil(props.pagination.totalRowCount / pageSize);
|
|
199
|
+
}
|
|
127
200
|
return -1;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
});
|
|
152
|
-
}
|
|
201
|
+
},
|
|
202
|
+
get state() {
|
|
203
|
+
const sortState = baseConfig.state
|
|
204
|
+
? baseConfig.state.sorting
|
|
205
|
+
: undefined;
|
|
206
|
+
return {
|
|
207
|
+
pagination: paginationState.value,
|
|
208
|
+
...(sortState !== undefined && { sorting: sortState }),
|
|
209
|
+
};
|
|
210
|
+
},
|
|
211
|
+
onPaginationChange: (updaterOrValue) => {
|
|
212
|
+
if (typeof updaterOrValue === 'function') {
|
|
213
|
+
paginationState.value = updaterOrValue(paginationState.value);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
paginationState.value = updaterOrValue;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
});
|
|
153
222
|
// Handle pagination changes for server mode
|
|
154
223
|
watch(paginationState, (newState) => {
|
|
155
224
|
if (props.pagination?.mode === 'server' &&
|
|
@@ -205,8 +274,8 @@ export function createNvDatatable() {
|
|
|
205
274
|
if (!props.pagination) {
|
|
206
275
|
return null;
|
|
207
276
|
}
|
|
208
|
-
const tablePaginationState = table.getState().pagination;
|
|
209
|
-
const pageCount = table.getPageCount();
|
|
277
|
+
const tablePaginationState = table.value.getState().pagination;
|
|
278
|
+
const pageCount = table.value.getPageCount();
|
|
210
279
|
const rowCount = props.pagination.mode === 'server'
|
|
211
280
|
? props.pagination.totalRowCount || props.rows.length
|
|
212
281
|
: props.rows.length;
|
|
@@ -215,14 +284,14 @@ export function createNvDatatable() {
|
|
|
215
284
|
pageSize: tablePaginationState.pageSize,
|
|
216
285
|
pageCount,
|
|
217
286
|
rowCount,
|
|
218
|
-
firstPage: () => table.setPageIndex(0),
|
|
219
|
-
previousPage: () => table.previousPage(),
|
|
220
|
-
nextPage: () => table.nextPage(),
|
|
221
|
-
lastPage: () => table.setPageIndex(pageCount - 1),
|
|
222
|
-
setPageIndex: (index) => table.setPageIndex(index),
|
|
223
|
-
setPageSize: (size) => table.setPageSize(size),
|
|
224
|
-
canPreviousPage: table.getCanPreviousPage(),
|
|
225
|
-
canNextPage: table.getCanNextPage(),
|
|
287
|
+
firstPage: () => table.value.setPageIndex(0),
|
|
288
|
+
previousPage: () => table.value.previousPage(),
|
|
289
|
+
nextPage: () => table.value.nextPage(),
|
|
290
|
+
lastPage: () => table.value.setPageIndex(pageCount - 1),
|
|
291
|
+
setPageIndex: (index) => table.value.setPageIndex(index),
|
|
292
|
+
setPageSize: (size) => table.value.setPageSize(size),
|
|
293
|
+
canPreviousPage: table.value.getCanPreviousPage(),
|
|
294
|
+
canNextPage: table.value.getCanNextPage(),
|
|
226
295
|
isLoading: props.pagination.mode === 'infinite'
|
|
227
296
|
? props.pagination.isLoading
|
|
228
297
|
: undefined,
|
|
@@ -232,7 +301,7 @@ export function createNvDatatable() {
|
|
|
232
301
|
};
|
|
233
302
|
});
|
|
234
303
|
return () => {
|
|
235
|
-
const tableRows = table.getRowModel().rows;
|
|
304
|
+
const tableRows = table.value.getRowModel().rows;
|
|
236
305
|
const isInfiniteScroll = props.pagination?.mode === 'infinite';
|
|
237
306
|
const tableElement = h(NvTable, attrs, {
|
|
238
307
|
default: () => [
|
|
@@ -240,25 +309,44 @@ export function createNvDatatable() {
|
|
|
240
309
|
h('thead', {
|
|
241
310
|
'data-sticky-top': props.stickyHeader ? 'true' : undefined,
|
|
242
311
|
}, [
|
|
243
|
-
...table.getHeaderGroups().map((headerGroup) => h('tr', { key: headerGroup.id }, [
|
|
244
|
-
...headerGroup.headers.map((header) =>
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
312
|
+
...table.value.getHeaderGroups().map((headerGroup) => h('tr', { key: headerGroup.id }, [
|
|
313
|
+
...headerGroup.headers.map((header) => {
|
|
314
|
+
const canSort = header.column.getCanSort();
|
|
315
|
+
const sortDirection = header.column.getIsSorted();
|
|
316
|
+
return h('th', {
|
|
317
|
+
key: header.id,
|
|
318
|
+
'data-testid': `datatable-header-${header.id}`,
|
|
319
|
+
style: {
|
|
320
|
+
width: header.column.columnDef.size
|
|
321
|
+
? `${header.column.columnDef.size}px`
|
|
322
|
+
: undefined,
|
|
323
|
+
},
|
|
324
|
+
'data-no-resize': header.column.columnDef
|
|
325
|
+
.enableResizing
|
|
326
|
+
? null
|
|
327
|
+
: true,
|
|
328
|
+
}, header.isPlaceholder
|
|
254
329
|
? null
|
|
255
|
-
:
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
330
|
+
: canSort
|
|
331
|
+
? h(NvTableheader, {
|
|
332
|
+
sortable: true,
|
|
333
|
+
sortDirection: sortDirection || 'none',
|
|
334
|
+
onSortDirectionChanged: (event) => {
|
|
335
|
+
// Call the TanStack handler
|
|
336
|
+
const handler = header.column.getToggleSortingHandler();
|
|
337
|
+
handler?.(event);
|
|
338
|
+
},
|
|
339
|
+
}, {
|
|
340
|
+
default: () => typeof header.column.columnDef.header ===
|
|
341
|
+
'function'
|
|
342
|
+
? header.column.columnDef.header(header.getContext())
|
|
343
|
+
: header.column.columnDef.header,
|
|
344
|
+
})
|
|
345
|
+
: typeof header.column.columnDef.header ===
|
|
346
|
+
'function'
|
|
347
|
+
? header.column.columnDef.header(header.getContext())
|
|
348
|
+
: header.column.columnDef.header);
|
|
349
|
+
}),
|
|
262
350
|
])),
|
|
263
351
|
]),
|
|
264
352
|
h('tbody', {}, [
|
|
@@ -266,12 +354,12 @@ export function createNvDatatable() {
|
|
|
266
354
|
const isLastRow = isInfiniteScroll && index === tableRows.length - 1;
|
|
267
355
|
return h('tr', {
|
|
268
356
|
key: row.id,
|
|
269
|
-
'data-testid': `datatable-row-${
|
|
357
|
+
'data-testid': `datatable-row-${index}`,
|
|
270
358
|
ref: isLastRow ? lastRowRef : undefined,
|
|
271
359
|
}, [
|
|
272
360
|
...row.getVisibleCells().map((cell) => h('td', {
|
|
273
361
|
key: cell.id,
|
|
274
|
-
'data-testid': `datatable-cell-${cell.id}`,
|
|
362
|
+
'data-testid': `datatable-cell-${cell.column.id}`,
|
|
275
363
|
}, typeof cell.column.columnDef.cell === 'function'
|
|
276
364
|
? cell.column.columnDef.cell(cell.getContext())
|
|
277
365
|
: cell.getValue())),
|
|
@@ -304,8 +392,28 @@ export function createNvDatatable() {
|
|
|
304
392
|
},
|
|
305
393
|
});
|
|
306
394
|
}
|
|
395
|
+
/********************************* UTILS **************************************/
|
|
307
396
|
/**
|
|
308
|
-
*
|
|
309
|
-
*
|
|
397
|
+
* Creates a strongly-typed column factory for a given row type.
|
|
398
|
+
*
|
|
399
|
+
* @template Row The row data type (e.g., `Product`)
|
|
400
|
+
*
|
|
401
|
+
* @returns {function} A function that accepts a column definition and infers:
|
|
402
|
+
* - `K` as the field key (`keyof Row`)
|
|
403
|
+
* - `F` as the return type of `valueFormatter` (defaults to `Row[K]`)
|
|
404
|
+
*
|
|
405
|
+
* @example
|
|
406
|
+
* ```ts
|
|
407
|
+
* // Define your row type
|
|
408
|
+
* interface Product {
|
|
409
|
+
* name: string;
|
|
410
|
+
* price: number;
|
|
411
|
+
* }
|
|
412
|
+
*
|
|
413
|
+
* const col = makeColumn<Product>();
|
|
310
414
|
*/
|
|
311
|
-
export
|
|
415
|
+
export function makeColumn() {
|
|
416
|
+
return function define(col) {
|
|
417
|
+
return col;
|
|
418
|
+
};
|
|
419
|
+
}
|
|
@@ -62,6 +62,7 @@ export declare const NvRow: import("vue").DefineSetupFnComponent<JSX.NvRow & imp
|
|
|
62
62
|
export declare const NvSplit: import("vue").DefineSetupFnComponent<JSX.NvSplit & import("./vue-component-lib/utils").InputProps<number[]>, {}, {}, JSX.NvSplit & import("./vue-component-lib/utils").InputProps<number[]> & {}, import("vue").PublicProps>;
|
|
63
63
|
export declare const NvStack: import("vue").DefineSetupFnComponent<JSX.NvStack & import("./vue-component-lib/utils").InputProps<string | number | boolean>, {}, {}, JSX.NvStack & import("./vue-component-lib/utils").InputProps<string | number | boolean> & {}, import("vue").PublicProps>;
|
|
64
64
|
export declare const NvTable: import("vue").DefineSetupFnComponent<JSX.NvTable & import("./vue-component-lib/utils").InputProps<string | number | boolean>, {}, {}, JSX.NvTable & import("./vue-component-lib/utils").InputProps<string | number | boolean> & {}, import("vue").PublicProps>;
|
|
65
|
+
export declare const NvTableheader: import("vue").DefineSetupFnComponent<JSX.NvTableheader & import("./vue-component-lib/utils").InputProps<string | number | boolean>, {}, {}, JSX.NvTableheader & import("./vue-component-lib/utils").InputProps<string | number | boolean> & {}, import("vue").PublicProps>;
|
|
65
66
|
export declare const NvToggle: import("vue").DefineSetupFnComponent<JSX.NvToggle & import("./vue-component-lib/utils").InputProps<boolean>, {}, {}, JSX.NvToggle & import("./vue-component-lib/utils").InputProps<boolean> & {}, import("vue").PublicProps>;
|
|
66
67
|
export declare const NvTogglebutton: import("vue").DefineSetupFnComponent<JSX.NvTogglebutton & import("./vue-component-lib/utils").InputProps<string | number | boolean>, {}, {}, JSX.NvTogglebutton & import("./vue-component-lib/utils").InputProps<string | number | boolean> & {}, import("vue").PublicProps>;
|
|
67
68
|
export declare const NvTogglebuttongroup: import("vue").DefineSetupFnComponent<JSX.NvTogglebuttongroup & import("./vue-component-lib/utils").InputProps<string[]>, {}, {}, JSX.NvTogglebuttongroup & import("./vue-component-lib/utils").InputProps<string[]> & {}, import("vue").PublicProps>;
|
|
@@ -75,7 +75,8 @@ export const NvButton = /*@__PURE__*/ defineContainer('nv-button', undefined, [
|
|
|
75
75
|
'disabled',
|
|
76
76
|
'fluid',
|
|
77
77
|
'type',
|
|
78
|
-
'form'
|
|
78
|
+
'form',
|
|
79
|
+
'disableTabindex'
|
|
79
80
|
]);
|
|
80
81
|
export const NvButtongroup = /*@__PURE__*/ defineContainer('nv-buttongroup', undefined, [
|
|
81
82
|
'size',
|
|
@@ -515,7 +516,8 @@ export const NvIconbutton = /*@__PURE__*/ defineContainer('nv-iconbutton', undef
|
|
|
515
516
|
'active',
|
|
516
517
|
'name',
|
|
517
518
|
'type',
|
|
518
|
-
'shape'
|
|
519
|
+
'shape',
|
|
520
|
+
'disableTabindex'
|
|
519
521
|
]);
|
|
520
522
|
export const NvLoader = /*@__PURE__*/ defineContainer('nv-loader', undefined, [
|
|
521
523
|
'size',
|
|
@@ -584,6 +586,11 @@ export const NvStack = /*@__PURE__*/ defineContainer('nv-stack', undefined, [
|
|
|
584
586
|
'vertical'
|
|
585
587
|
]);
|
|
586
588
|
export const NvTable = /*@__PURE__*/ defineContainer('nv-table', undefined);
|
|
589
|
+
export const NvTableheader = /*@__PURE__*/ defineContainer('nv-tableheader', undefined, [
|
|
590
|
+
'sortable',
|
|
591
|
+
'sortDirection',
|
|
592
|
+
'sortDirectionChanged'
|
|
593
|
+
]);
|
|
587
594
|
export const NvToggle = /*@__PURE__*/ defineContainer('nv-toggle', undefined, [
|
|
588
595
|
'inputId',
|
|
589
596
|
'name',
|
|
@@ -33,6 +33,8 @@ export interface NotificationOptions {
|
|
|
33
33
|
actions?: NotificationAction[];
|
|
34
34
|
/** Custom components for the notification actions. */
|
|
35
35
|
actionSlot?: Component;
|
|
36
|
+
/** Duration in milliseconds before auto-dismissing. 0 = sticky (no auto-dismiss). Default: 0 */
|
|
37
|
+
duration?: number;
|
|
36
38
|
}
|
|
37
39
|
/**
|
|
38
40
|
* A notification with all required fields populated.
|
|
@@ -25,6 +25,7 @@ class NotificationManager {
|
|
|
25
25
|
notifications = ref([]);
|
|
26
26
|
options;
|
|
27
27
|
containerApp = null;
|
|
28
|
+
timers = new Map();
|
|
28
29
|
constructor(options = {}) {
|
|
29
30
|
this.options = {
|
|
30
31
|
position: options.position || 'top-right',
|
|
@@ -116,6 +117,7 @@ class NotificationManager {
|
|
|
116
117
|
actions: options.actions ?? [],
|
|
117
118
|
actionSlot: options.actionSlot,
|
|
118
119
|
icon: options.icon,
|
|
120
|
+
duration: options.duration ?? 0,
|
|
119
121
|
createdAt: Date.now(),
|
|
120
122
|
};
|
|
121
123
|
// Remove oldest notifications if we exceed max
|
|
@@ -130,6 +132,13 @@ class NotificationManager {
|
|
|
130
132
|
const ref = this.elRefs.get(id);
|
|
131
133
|
const el = unwrapNotificationEl(ref);
|
|
132
134
|
el?.show();
|
|
135
|
+
// Set up auto-dismiss timer if duration > 0
|
|
136
|
+
if (notification.duration && notification.duration > 0) {
|
|
137
|
+
const timer = setTimeout(() => {
|
|
138
|
+
this.dismiss(id);
|
|
139
|
+
}, notification.duration);
|
|
140
|
+
this.timers.set(id, timer);
|
|
141
|
+
}
|
|
133
142
|
}, 0);
|
|
134
143
|
return id;
|
|
135
144
|
};
|
|
@@ -140,6 +149,12 @@ class NotificationManager {
|
|
|
140
149
|
* @param {string} id - The notification ID to dismiss
|
|
141
150
|
*/
|
|
142
151
|
dismiss = (id) => {
|
|
152
|
+
// Clear timer if exists
|
|
153
|
+
const timer = this.timers.get(id);
|
|
154
|
+
if (timer) {
|
|
155
|
+
clearTimeout(timer);
|
|
156
|
+
this.timers.delete(id);
|
|
157
|
+
}
|
|
143
158
|
const ref = this.elRefs.get(id);
|
|
144
159
|
const el = unwrapNotificationEl(ref);
|
|
145
160
|
el?.dismiss();
|
|
@@ -150,6 +165,12 @@ class NotificationManager {
|
|
|
150
165
|
* @param {string} id - The notification ID to dismiss
|
|
151
166
|
*/
|
|
152
167
|
remove = (id) => {
|
|
168
|
+
// Clear timer if exists
|
|
169
|
+
const timer = this.timers.get(id);
|
|
170
|
+
if (timer) {
|
|
171
|
+
clearTimeout(timer);
|
|
172
|
+
this.timers.delete(id);
|
|
173
|
+
}
|
|
153
174
|
this.notifications.value = this.notifications.value.filter((notification) => notification.id !== id);
|
|
154
175
|
this.elRefs.delete(id);
|
|
155
176
|
};
|
|
@@ -157,6 +178,9 @@ class NotificationManager {
|
|
|
157
178
|
* Clear all active notifications.
|
|
158
179
|
*/
|
|
159
180
|
removeAll = () => {
|
|
181
|
+
// Clear all timers
|
|
182
|
+
this.timers.forEach((timer) => clearTimeout(timer));
|
|
183
|
+
this.timers.clear();
|
|
160
184
|
this.notifications.value = [];
|
|
161
185
|
};
|
|
162
186
|
/**
|
|
@@ -175,6 +199,9 @@ class NotificationManager {
|
|
|
175
199
|
* Destroy the notification manager and clean up resources.
|
|
176
200
|
*/
|
|
177
201
|
destroy() {
|
|
202
|
+
// Clear all timers
|
|
203
|
+
this.timers.forEach((timer) => clearTimeout(timer));
|
|
204
|
+
this.timers.clear();
|
|
178
205
|
if (this.containerApp) {
|
|
179
206
|
this.containerApp.unmount();
|
|
180
207
|
this.containerApp = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nova-design-system/nova-vue",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.21.0",
|
|
4
4
|
"description": "Nova is a design system created by Elia Group to empower creators to efficiently build solutions that people love to use.",
|
|
5
5
|
"author": "Elia Group",
|
|
6
6
|
"homepage": "https://nova.eliagroup.io",
|