@nu-grid/nuxt 0.1.4 → 0.3.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/dist/module.json +1 -1
- package/dist/runtime/cell-types/action-menu/ActionMenuRenderer.d.vue.ts +1 -1
- package/dist/runtime/cell-types/action-menu/ActionMenuRenderer.vue +1 -0
- package/dist/runtime/cell-types/action-menu/ActionMenuRenderer.vue.d.ts +1 -1
- package/dist/runtime/cell-types/date/index.d.ts +1 -1
- package/dist/runtime/cell-types/date/index.js +15 -1
- package/dist/runtime/cell-types/index.d.ts +2 -1
- package/dist/runtime/cell-types/index.js +3 -0
- package/dist/runtime/cell-types/lookup/LookupRenderer.vue +1 -1
- package/dist/runtime/cell-types/number/NumberFilter.vue +1 -1
- package/dist/runtime/cell-types/percentage/PercentageEditor.d.vue.ts +15 -0
- package/dist/runtime/cell-types/percentage/PercentageEditor.vue +56 -0
- package/dist/runtime/cell-types/percentage/PercentageEditor.vue.d.ts +15 -0
- package/dist/runtime/cell-types/percentage/PercentageFilter.d.vue.ts +7 -0
- package/dist/runtime/cell-types/percentage/PercentageFilter.vue +79 -0
- package/dist/runtime/cell-types/percentage/PercentageFilter.vue.d.ts +7 -0
- package/dist/runtime/cell-types/percentage/index.d.ts +10 -0
- package/dist/runtime/cell-types/percentage/index.js +38 -0
- package/dist/runtime/cell-types/selection/SelectionEditor.vue +1 -1
- package/dist/runtime/cell-types/selection/SelectionRenderer.vue +1 -0
- package/dist/runtime/components/NuGrid.d.vue.ts +8 -5
- package/dist/runtime/components/NuGrid.vue +41 -9
- package/dist/runtime/components/NuGrid.vue.d.ts +8 -5
- package/dist/runtime/components/_internal/NuGridBase.vue +128 -82
- package/dist/runtime/components/_internal/NuGridCellContent.vue +21 -1
- package/dist/runtime/components/_internal/NuGridColumnMenu.vue +2 -2
- package/dist/runtime/components/_internal/NuGridGroup.vue +22 -15
- package/dist/runtime/components/_internal/NuGridHeaderSortButton.vue +1 -0
- package/dist/runtime/components/_internal/NuGridRow.vue +13 -5
- package/dist/runtime/components/_internal/NuGridSplitGroup.vue +22 -16
- package/dist/runtime/components/_internal/NuGridTooltip.vue +1 -0
- package/dist/runtime/composables/_internal/column-flex-style.d.ts +22 -0
- package/dist/runtime/composables/_internal/column-flex-style.js +84 -0
- package/dist/runtime/composables/_internal/index.d.ts +1 -0
- package/dist/runtime/composables/_internal/index.js +1 -0
- package/dist/runtime/composables/_internal/useNuGridAddRow.js +5 -1
- package/dist/runtime/composables/_internal/useNuGridAutosize.d.ts +6 -3
- package/dist/runtime/composables/_internal/useNuGridAutosize.js +91 -9
- package/dist/runtime/composables/_internal/useNuGridCellEditing.js +3 -2
- package/dist/runtime/composables/_internal/useNuGridColumnResize.d.ts +17 -7
- package/dist/runtime/composables/_internal/useNuGridColumnResize.js +219 -8
- package/dist/runtime/composables/_internal/useNuGridCore.d.ts +1 -1
- package/dist/runtime/composables/_internal/useNuGridCore.js +16 -5
- package/dist/runtime/composables/_internal/useNuGridFocus.js +1 -1
- package/dist/runtime/composables/_internal/useNuGridRowSelection.js +1 -1
- package/dist/runtime/composables/_internal/useNuGridStatePersistence.d.ts +14 -1
- package/dist/runtime/composables/_internal/useNuGridStatePersistence.js +66 -3
- package/dist/runtime/composables/_internal/useNuGridUI.d.ts +116 -0
- package/dist/runtime/config/_internal/options-defaults.d.ts +3 -4
- package/dist/runtime/config/_internal/options-defaults.js +3 -4
- package/dist/runtime/config/_internal/prop-utils.d.ts +7 -1
- package/dist/runtime/config/_internal/prop-utils.js +20 -6
- package/dist/runtime/config/presets.js +2 -2
- package/dist/runtime/themes/nuGridTheme.d.ts +2 -0
- package/dist/runtime/themes/nuGridTheme.js +7 -4
- package/dist/runtime/themes/nuGridThemeCompact.d.ts +2 -0
- package/dist/runtime/themes/nuGridThemeCompact.js +7 -4
- package/dist/runtime/types/_internal/contexts/resize.d.ts +1 -0
- package/dist/runtime/types/_internal/contexts/ui-config.d.ts +4 -2
- package/dist/runtime/types/autosize.d.ts +4 -1
- package/dist/runtime/types/column.d.ts +41 -3
- package/dist/runtime/types/index.d.ts +2 -1
- package/dist/runtime/types/option-groups.d.ts +26 -8
- package/dist/runtime/types/props.d.ts +34 -9
- package/dist/runtime/types/resize.d.ts +2 -0
- package/dist/runtime/types/slots.d.ts +32 -0
- package/dist/runtime/types/slots.js +0 -0
- package/dist/runtime/types/tanstack-table.d.ts +3 -2
- package/dist/runtime/utils/index.d.ts +1 -0
- package/dist/runtime/utils/index.js +1 -0
- package/dist/runtime/utils/inferCellDataType.d.ts +27 -0
- package/dist/runtime/utils/inferCellDataType.js +91 -0
- package/package.json +3 -2
- package/dist/runtime/components/NuGridGroup.d.vue.ts +0 -20
- package/dist/runtime/components/NuGridGroup.vue +0 -650
- package/dist/runtime/components/NuGridGroup.vue.d.ts +0 -20
|
@@ -1,13 +1,173 @@
|
|
|
1
|
-
import { onUnmounted, ref } from "vue";
|
|
1
|
+
import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
|
2
2
|
function isTouchStartEvent(e) {
|
|
3
3
|
return e.type === "touchstart";
|
|
4
4
|
}
|
|
5
|
-
export function useNuGridColumnResize(props, tableApi) {
|
|
5
|
+
export function useNuGridColumnResize(props, tableApi, tableRef) {
|
|
6
6
|
const resizingGroupId = ref(null);
|
|
7
7
|
const resizingColumnId = ref(null);
|
|
8
|
+
const manuallyResizedColumns = ref(/* @__PURE__ */ new Set());
|
|
9
|
+
const resizeStartSizes = /* @__PURE__ */ new Map();
|
|
10
|
+
function syncColumnWidthsFromDOM(columnIds) {
|
|
11
|
+
if (!tableRef.value) return;
|
|
12
|
+
const newSizing = {};
|
|
13
|
+
const tbody = tableRef.value.querySelector("[data-tbody]");
|
|
14
|
+
const firstRow = tbody?.querySelector("[data-row-id]");
|
|
15
|
+
for (const columnId of columnIds) {
|
|
16
|
+
let measuredWidth = 0;
|
|
17
|
+
if (firstRow) {
|
|
18
|
+
const bodyCell = firstRow.querySelector(`[data-column-id="${columnId}"]`);
|
|
19
|
+
if (bodyCell) {
|
|
20
|
+
const rect = bodyCell.getBoundingClientRect();
|
|
21
|
+
measuredWidth = rect.width;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (measuredWidth === 0) {
|
|
25
|
+
const headerCell = tableRef.value.querySelector(
|
|
26
|
+
`[data-column-id="${columnId}"]`
|
|
27
|
+
);
|
|
28
|
+
if (headerCell) {
|
|
29
|
+
const rect = headerCell.getBoundingClientRect();
|
|
30
|
+
measuredWidth = rect.width;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (measuredWidth > 0) {
|
|
34
|
+
newSizing[columnId] = measuredWidth;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (Object.keys(newSizing).length > 0) {
|
|
38
|
+
tableApi.setColumnSizing((old) => ({
|
|
39
|
+
...old,
|
|
40
|
+
...newSizing
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
let stateWasRestored = false;
|
|
45
|
+
function syncInitialFlexWidths(forceSync = false) {
|
|
46
|
+
if (props.layout?.autoSize !== "fill") return;
|
|
47
|
+
if (!tableRef.value) return;
|
|
48
|
+
if (stateWasRestored && !forceSync) {
|
|
49
|
+
stateWasRestored = false;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (!forceSync) {
|
|
53
|
+
const currentSizing = tableApi.getState().columnSizing;
|
|
54
|
+
const restoredColumnIds = Object.keys(currentSizing);
|
|
55
|
+
if (restoredColumnIds.length > 0) {
|
|
56
|
+
manuallyResizedColumns.value = new Set(restoredColumnIds);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const allColumns = tableApi.getVisibleLeafColumns();
|
|
61
|
+
const flexColumns = allColumns.filter((col) => {
|
|
62
|
+
const colDef = col.columnDef;
|
|
63
|
+
return colDef.grow !== false;
|
|
64
|
+
}).map((col) => col.id);
|
|
65
|
+
if (flexColumns.length === 0) return;
|
|
66
|
+
syncColumnWidthsFromDOM(flexColumns);
|
|
67
|
+
manuallyResizedColumns.value = new Set(flexColumns);
|
|
68
|
+
}
|
|
69
|
+
function getContainerWidth() {
|
|
70
|
+
if (!tableRef.value) return 0;
|
|
71
|
+
const rootEl = tableRef.value.parentElement;
|
|
72
|
+
return rootEl?.getBoundingClientRect().width ?? 0;
|
|
73
|
+
}
|
|
74
|
+
function getSizingAsRatios() {
|
|
75
|
+
const containerWidth = getContainerWidth();
|
|
76
|
+
if (containerWidth === 0) return {};
|
|
77
|
+
const currentSizing = tableApi.getState().columnSizing;
|
|
78
|
+
const ratios = {};
|
|
79
|
+
for (const [columnId, pixelWidth] of Object.entries(currentSizing)) {
|
|
80
|
+
ratios[columnId] = pixelWidth / containerWidth;
|
|
81
|
+
}
|
|
82
|
+
return ratios;
|
|
83
|
+
}
|
|
84
|
+
function applySizingFromRatios(ratios) {
|
|
85
|
+
const containerWidth = getContainerWidth();
|
|
86
|
+
if (containerWidth === 0) return;
|
|
87
|
+
const pixelSizing = {};
|
|
88
|
+
const columnIds = [];
|
|
89
|
+
for (const [columnId, ratio] of Object.entries(ratios)) {
|
|
90
|
+
pixelSizing[columnId] = Math.round(ratio * containerWidth);
|
|
91
|
+
columnIds.push(columnId);
|
|
92
|
+
}
|
|
93
|
+
if (Object.keys(pixelSizing).length > 0) {
|
|
94
|
+
stateWasRestored = true;
|
|
95
|
+
tableApi.setColumnSizing((old) => ({
|
|
96
|
+
...old,
|
|
97
|
+
...pixelSizing
|
|
98
|
+
}));
|
|
99
|
+
manuallyResizedColumns.value = /* @__PURE__ */ new Set([...manuallyResizedColumns.value, ...columnIds]);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function applyRestoredSizing(sizing) {
|
|
103
|
+
if (Object.keys(sizing).length === 0) return;
|
|
104
|
+
stateWasRestored = true;
|
|
105
|
+
manuallyResizedColumns.value = /* @__PURE__ */ new Set([
|
|
106
|
+
...manuallyResizedColumns.value,
|
|
107
|
+
...Object.keys(sizing)
|
|
108
|
+
]);
|
|
109
|
+
}
|
|
110
|
+
let lastContainerWidth = 0;
|
|
111
|
+
let resizeObserver = null;
|
|
112
|
+
let rafId = null;
|
|
113
|
+
function handleContainerResize(entries) {
|
|
114
|
+
const entry = entries[0];
|
|
115
|
+
if (!entry) return;
|
|
116
|
+
const newWidth = entry.contentRect.width;
|
|
117
|
+
if (Math.abs(newWidth - lastContainerWidth) > 1) {
|
|
118
|
+
lastContainerWidth = newWidth;
|
|
119
|
+
if (rafId !== null) {
|
|
120
|
+
cancelAnimationFrame(rafId);
|
|
121
|
+
}
|
|
122
|
+
rafId = requestAnimationFrame(() => {
|
|
123
|
+
rafId = null;
|
|
124
|
+
manuallyResizedColumns.value = /* @__PURE__ */ new Set();
|
|
125
|
+
nextTick(() => {
|
|
126
|
+
syncInitialFlexWidths(true);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
onMounted(() => {
|
|
132
|
+
nextTick(() => {
|
|
133
|
+
nextTick(() => {
|
|
134
|
+
syncInitialFlexWidths();
|
|
135
|
+
if (tableRef.value && typeof ResizeObserver !== "undefined") {
|
|
136
|
+
const rootEl = tableRef.value.parentElement;
|
|
137
|
+
if (rootEl) {
|
|
138
|
+
lastContainerWidth = rootEl.getBoundingClientRect().width;
|
|
139
|
+
resizeObserver = new ResizeObserver(handleContainerResize);
|
|
140
|
+
resizeObserver.observe(rootEl);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
watch(
|
|
147
|
+
() => props.layout?.autoSize,
|
|
148
|
+
(newValue, oldValue) => {
|
|
149
|
+
if (newValue === "fill" && oldValue !== "fill") {
|
|
150
|
+
manuallyResizedColumns.value = /* @__PURE__ */ new Set();
|
|
151
|
+
nextTick(() => {
|
|
152
|
+
nextTick(() => {
|
|
153
|
+
syncInitialFlexWidths();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
onUnmounted(() => {
|
|
160
|
+
if (resizeObserver) {
|
|
161
|
+
resizeObserver.disconnect();
|
|
162
|
+
resizeObserver = null;
|
|
163
|
+
}
|
|
164
|
+
if (rafId !== null) {
|
|
165
|
+
cancelAnimationFrame(rafId);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
8
168
|
function getResizeHandler(header) {
|
|
9
|
-
if (props.layout?.
|
|
10
|
-
return
|
|
169
|
+
if (props.layout?.resizeMode === "shift") {
|
|
170
|
+
return createShiftResizeHandler(header, tableApi, manuallyResizedColumns);
|
|
11
171
|
}
|
|
12
172
|
return header.getResizeHandler();
|
|
13
173
|
}
|
|
@@ -17,6 +177,37 @@ export function useNuGridColumnResize(props, tableApi) {
|
|
|
17
177
|
event.stopPropagation();
|
|
18
178
|
document.body.classList.add("is-resizing-column");
|
|
19
179
|
resizingColumnId.value = header.column.id;
|
|
180
|
+
if (props.layout?.autoSize === "fill") {
|
|
181
|
+
const allColumns = tableApi.getVisibleLeafColumns();
|
|
182
|
+
const columnsToSync = allColumns.filter((col) => {
|
|
183
|
+
const colDef = col.columnDef;
|
|
184
|
+
return colDef.grow !== false && !manuallyResizedColumns.value.has(col.id);
|
|
185
|
+
}).map((col) => col.id);
|
|
186
|
+
syncColumnWidthsFromDOM(columnsToSync);
|
|
187
|
+
const newSet = new Set(manuallyResizedColumns.value);
|
|
188
|
+
newSet.add(header.column.id);
|
|
189
|
+
if (props.layout?.resizeMode === "shift") {
|
|
190
|
+
const currentIndex = allColumns.findIndex((col) => col.id === header.column.id);
|
|
191
|
+
if (currentIndex >= 0 && currentIndex < allColumns.length - 1) {
|
|
192
|
+
const nextColumn = allColumns[currentIndex + 1];
|
|
193
|
+
if (nextColumn) {
|
|
194
|
+
newSet.add(nextColumn.id);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
manuallyResizedColumns.value = newSet;
|
|
199
|
+
}
|
|
200
|
+
resizeStartSizes.set(header.column.id, header.column.getSize());
|
|
201
|
+
if (props.layout?.resizeMode === "shift") {
|
|
202
|
+
const allColumns = tableApi.getVisibleLeafColumns();
|
|
203
|
+
const currentIndex = allColumns.findIndex((col) => col.id === header.column.id);
|
|
204
|
+
if (currentIndex >= 0 && currentIndex < allColumns.length - 1) {
|
|
205
|
+
const nextColumn = allColumns[currentIndex + 1];
|
|
206
|
+
if (nextColumn) {
|
|
207
|
+
resizeStartSizes.set(nextColumn.id, nextColumn.getSize());
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
20
211
|
resizeHandler(event);
|
|
21
212
|
}
|
|
22
213
|
}
|
|
@@ -28,11 +219,25 @@ export function useNuGridColumnResize(props, tableApi) {
|
|
|
28
219
|
document.body.classList.add("is-resizing-column");
|
|
29
220
|
resizingColumnId.value = null;
|
|
30
221
|
resizingGroupId.value = header.id;
|
|
31
|
-
const
|
|
222
|
+
const leafHeaders = header.getLeafHeaders();
|
|
223
|
+
for (const leafHeader of leafHeaders) {
|
|
224
|
+
resizeStartSizes.set(leafHeader.column.id, leafHeader.column.getSize());
|
|
225
|
+
}
|
|
226
|
+
const resizeHandler = createGroupResizeHandler(header, tableApi, manuallyResizedColumns);
|
|
32
227
|
resizeHandler(event);
|
|
33
228
|
}
|
|
34
229
|
function handleResizeEnd() {
|
|
35
230
|
document.body.classList.remove("is-resizing-column");
|
|
231
|
+
for (const [columnId, startSize] of resizeStartSizes) {
|
|
232
|
+
const column = tableApi.getColumn(columnId);
|
|
233
|
+
if (column) {
|
|
234
|
+
const currentSize = column.getSize();
|
|
235
|
+
if (Math.abs(currentSize - startSize) > 1) {
|
|
236
|
+
manuallyResizedColumns.value = /* @__PURE__ */ new Set([...manuallyResizedColumns.value, columnId]);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
resizeStartSizes.clear();
|
|
36
241
|
resizingColumnId.value = null;
|
|
37
242
|
resizingGroupId.value = null;
|
|
38
243
|
}
|
|
@@ -51,10 +256,16 @@ export function useNuGridColumnResize(props, tableApi) {
|
|
|
51
256
|
handleGroupResizeStart,
|
|
52
257
|
handleResizeEnd,
|
|
53
258
|
resizingGroupId,
|
|
54
|
-
resizingColumnId
|
|
259
|
+
resizingColumnId,
|
|
260
|
+
manuallyResizedColumns,
|
|
261
|
+
// State persistence helpers
|
|
262
|
+
getContainerWidth,
|
|
263
|
+
getSizingAsRatios,
|
|
264
|
+
applySizingFromRatios,
|
|
265
|
+
applyRestoredSizing
|
|
55
266
|
};
|
|
56
267
|
}
|
|
57
|
-
export function
|
|
268
|
+
export function createShiftResizeHandler(header, table, _manuallyResizedColumns) {
|
|
58
269
|
return (e) => {
|
|
59
270
|
const column = table.getColumn(header.column.id);
|
|
60
271
|
const canResize = column?.getCanResize();
|
|
@@ -209,7 +420,7 @@ export function createMaintainWidthResizeHandler(header, table) {
|
|
|
209
420
|
}));
|
|
210
421
|
};
|
|
211
422
|
}
|
|
212
|
-
export function createGroupResizeHandler(header, table) {
|
|
423
|
+
export function createGroupResizeHandler(header, table, _manuallyResizedColumns) {
|
|
213
424
|
return (e) => {
|
|
214
425
|
;
|
|
215
426
|
e.persist?.();
|
|
@@ -6,7 +6,7 @@ import type { NuGridRowSelectionMode, NuGridStates, PinnableHeader, UseNuGridCol
|
|
|
6
6
|
/**
|
|
7
7
|
* Shared logic for processing columns with default cell renderers
|
|
8
8
|
*/
|
|
9
|
-
export declare function useNuGridColumns<T extends TableData>(propsColumns: Ref<NuGridColumn<T>[] | undefined>, data: Ref<T[]>, rowSelectionMode?: Ref<NuGridRowSelectionMode<T>>, actionMenuOptions?: Ref<NuGridActionMenuOptions<T> | undefined | false>, columnVisibilityState?: Ref<VisibilityState>): UseNuGridColumnsReturn<T>;
|
|
9
|
+
export declare function useNuGridColumns<T extends TableData>(propsColumns: Ref<NuGridColumn<T>[] | undefined>, data: Ref<T[]>, rowSelectionMode?: Ref<NuGridRowSelectionMode<T>>, actionMenuOptions?: Ref<NuGridActionMenuOptions<T> | undefined | false>, columnVisibilityState?: Ref<VisibilityState>, dataTypeInference?: Ref<boolean>): UseNuGridColumnsReturn<T>;
|
|
10
10
|
/**
|
|
11
11
|
* Helper function to update state values
|
|
12
12
|
*/
|
|
@@ -11,18 +11,20 @@ import { createReusableTemplate, reactiveOmit } from "@vueuse/core";
|
|
|
11
11
|
import { upperFirst } from "scule";
|
|
12
12
|
import { computed, watch } from "vue";
|
|
13
13
|
import { nuGridDefaults } from "../../config/_internal/index.js";
|
|
14
|
+
import { extractColumnValues, inferCellDataType } from "../../utils/inferCellDataType.js";
|
|
14
15
|
import { nuGridCellTypeRegistry } from "../useNuGridCellTypeRegistry.js";
|
|
15
16
|
import { useNuGridActionMenu } from "./useNuGridActionMenu.js";
|
|
16
17
|
import { useNuGridRowSelection } from "./useNuGridRowSelection.js";
|
|
17
|
-
export function useNuGridColumns(propsColumns, data, rowSelectionMode, actionMenuOptions, columnVisibilityState) {
|
|
18
|
+
export function useNuGridColumns(propsColumns, data, rowSelectionMode, actionMenuOptions, columnVisibilityState, dataTypeInference) {
|
|
18
19
|
const rowSelection = rowSelectionMode ? useNuGridRowSelection(rowSelectionMode, columnVisibilityState) : null;
|
|
19
20
|
const actionMenu = actionMenuOptions ? useNuGridActionMenu(actionMenuOptions, columnVisibilityState) : null;
|
|
20
21
|
const columns = computed(() => {
|
|
22
|
+
const inferenceEnabled = dataTypeInference?.value !== false;
|
|
21
23
|
const cols = propsColumns.value ?? Object.keys(data.value[0] ?? {}).map((accessorKey) => ({
|
|
22
24
|
accessorKey,
|
|
23
25
|
header: upperFirst(accessorKey)
|
|
24
26
|
}));
|
|
25
|
-
let processedCols = processColumns(cols);
|
|
27
|
+
let processedCols = processColumns(cols, inferenceEnabled);
|
|
26
28
|
if (rowSelection) {
|
|
27
29
|
processedCols = rowSelection.prependSelectionColumn(processedCols);
|
|
28
30
|
}
|
|
@@ -32,14 +34,23 @@ export function useNuGridColumns(propsColumns, data, rowSelectionMode, actionMen
|
|
|
32
34
|
return processedCols;
|
|
33
35
|
});
|
|
34
36
|
const pluginCache = /* @__PURE__ */ new Map();
|
|
35
|
-
function processColumns(columns2) {
|
|
37
|
+
function processColumns(columns2, inferenceEnabled) {
|
|
36
38
|
return columns2.map((column) => {
|
|
37
39
|
const col = { ...column };
|
|
38
40
|
if ("columns" in col && col.columns) {
|
|
39
|
-
col.columns = processColumns(col.columns);
|
|
41
|
+
col.columns = processColumns(col.columns, inferenceEnabled);
|
|
42
|
+
}
|
|
43
|
+
const accessorKey = col.accessorKey;
|
|
44
|
+
if (inferenceEnabled && col.cellDataType === void 0 && accessorKey && data.value.length > 0) {
|
|
45
|
+
const values = extractColumnValues(data.value, accessorKey);
|
|
46
|
+
const inferredType = inferCellDataType(values, accessorKey);
|
|
47
|
+
if (inferredType) {
|
|
48
|
+
;
|
|
49
|
+
col.cellDataType = inferredType;
|
|
50
|
+
}
|
|
40
51
|
}
|
|
41
52
|
const cellDataType = col.cellDataType;
|
|
42
|
-
if (cellDataType) {
|
|
53
|
+
if (cellDataType && cellDataType !== false) {
|
|
43
54
|
let plugin = pluginCache.get(cellDataType);
|
|
44
55
|
if (plugin === void 0) {
|
|
45
56
|
plugin = nuGridCellTypeRegistry.get(cellDataType);
|
|
@@ -9,7 +9,7 @@ export function useNuGridFocus(props, tableApi, rows, navigableRows, tableRef, r
|
|
|
9
9
|
const cmdArrows = usePropWithDefault(props, "focus", "cmdArrows");
|
|
10
10
|
const alignOnModel = usePropWithDefault(props, "focus", "alignOnModel");
|
|
11
11
|
const enableEditing = usePropWithDefault(props, "editing", "enabled");
|
|
12
|
-
const rowSelectionMode = computed(() => props.
|
|
12
|
+
const rowSelectionMode = computed(() => props.rowSelection ?? false);
|
|
13
13
|
const focusedCell = ref(null);
|
|
14
14
|
const gridHasFocus = ref(false);
|
|
15
15
|
let pointerDownInsideGrid = false;
|
|
@@ -2,7 +2,7 @@ import { computed, h, ref, watch } from "vue";
|
|
|
2
2
|
import NuGridCellCheckbox from "../../components/NuGridCellCheckbox.vue";
|
|
3
3
|
import { getDefaults } from "../../config/_internal/index.js";
|
|
4
4
|
import { nuGridCellTypeRegistry } from "../useNuGridCellTypeRegistry.js";
|
|
5
|
-
const selectionDefaults = getDefaults("
|
|
5
|
+
const selectionDefaults = getDefaults("rowSelection");
|
|
6
6
|
const selectionTotalsCache = /* @__PURE__ */ new WeakMap();
|
|
7
7
|
function createSelectionColumn(modeRef, enabledRef, rowSelectionEnabledRef, columnDef) {
|
|
8
8
|
const defaultColumn = {
|
|
@@ -10,6 +10,8 @@ export interface NuGridStateSnapshot {
|
|
|
10
10
|
columnPinning?: ColumnPinningState;
|
|
11
11
|
columnSizing?: ColumnSizingState;
|
|
12
12
|
columnSizingInfo?: ColumnSizingInfoState;
|
|
13
|
+
/** Column sizing stored as ratios (0-1) relative to container width for resolution-independent persistence */
|
|
14
|
+
columnSizingRatios?: Record<string, number>;
|
|
13
15
|
rowSelection?: RowSelectionState;
|
|
14
16
|
rowPinning?: RowPinningState;
|
|
15
17
|
sorting?: SortingState;
|
|
@@ -17,11 +19,22 @@ export interface NuGridStateSnapshot {
|
|
|
17
19
|
expanded?: ExpandedState;
|
|
18
20
|
pagination?: PaginationState;
|
|
19
21
|
}
|
|
22
|
+
export interface NuGridStatePersistenceHelpers {
|
|
23
|
+
/** Get current container width for ratio calculations */
|
|
24
|
+
getContainerWidth: () => number;
|
|
25
|
+
/** Get current sizing as ratios */
|
|
26
|
+
getSizingAsRatios: () => Record<string, number>;
|
|
27
|
+
/** Apply sizing from ratios and mark columns as manually resized */
|
|
28
|
+
applySizingFromRatios: (ratios: Record<string, number>) => void;
|
|
29
|
+
}
|
|
20
30
|
/**
|
|
21
31
|
* Composable for persisting and restoring NuGrid state to/from localStorage and cookies
|
|
22
32
|
* Handles all state initialization, restoration, and persistence logic
|
|
23
33
|
*/
|
|
24
|
-
export declare function useNuGridStatePersistence<T extends TableData = TableData>(states: NuGridStates, enabled: boolean, storageId: string | undefined, onStateChanged?: (state: NuGridStateSnapshot) => void, eventEmitter?: NuGridEventEmitter<T
|
|
34
|
+
export declare function useNuGridStatePersistence<T extends TableData = TableData>(states: NuGridStates, enabled: boolean, storageId: string | undefined, onStateChanged?: (state: NuGridStateSnapshot) => void, eventEmitter?: NuGridEventEmitter<T>, resizeHelpers?: NuGridStatePersistenceHelpers): {
|
|
25
35
|
getState: () => {};
|
|
26
36
|
setState: (_snapshot: NuGridStateSnapshot) => void;
|
|
37
|
+
clearState: () => void;
|
|
38
|
+
applyPendingRatios: () => void;
|
|
39
|
+
setResizeHelpers: (_helpers: NuGridStatePersistenceHelpers) => void;
|
|
27
40
|
};
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import { useCookie } from "#imports";
|
|
2
2
|
import { StorageSerializers, useStorage } from "@vueuse/core";
|
|
3
3
|
import { nextTick, onMounted, watch } from "vue";
|
|
4
|
-
export function useNuGridStatePersistence(states, enabled, storageId, onStateChanged, eventEmitter) {
|
|
4
|
+
export function useNuGridStatePersistence(states, enabled, storageId, onStateChanged, eventEmitter, resizeHelpers) {
|
|
5
5
|
const emitStateChanged = (state) => {
|
|
6
6
|
if (eventEmitter?.stateChanged) {
|
|
7
7
|
eventEmitter.stateChanged(state);
|
|
8
8
|
}
|
|
9
9
|
onStateChanged?.(state);
|
|
10
10
|
};
|
|
11
|
+
let pendingRatios = null;
|
|
12
|
+
let helpers = resizeHelpers;
|
|
11
13
|
if (!enabled || !storageId) {
|
|
12
14
|
return {
|
|
13
15
|
getState: () => ({}),
|
|
14
16
|
setState: (_snapshot) => {
|
|
17
|
+
},
|
|
18
|
+
clearState: () => {
|
|
19
|
+
},
|
|
20
|
+
applyPendingRatios: () => {
|
|
21
|
+
},
|
|
22
|
+
setResizeHelpers: (_helpers) => {
|
|
15
23
|
}
|
|
16
24
|
};
|
|
17
25
|
}
|
|
@@ -75,6 +83,12 @@ export function useNuGridStatePersistence(states, enabled, storageId, onStateCha
|
|
|
75
83
|
}
|
|
76
84
|
if (hasKeys(states.columnSizingState.value)) {
|
|
77
85
|
snapshot.columnSizing = states.columnSizingState.value;
|
|
86
|
+
if (helpers?.getSizingAsRatios) {
|
|
87
|
+
const ratios = helpers.getSizingAsRatios();
|
|
88
|
+
if (hasKeys(ratios)) {
|
|
89
|
+
snapshot.columnSizingRatios = ratios;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
78
92
|
}
|
|
79
93
|
if (hasKeys(states.columnSizingInfoState.value)) {
|
|
80
94
|
snapshot.columnSizingInfo = states.columnSizingInfoState.value;
|
|
@@ -129,7 +143,12 @@ export function useNuGridStatePersistence(states, enabled, storageId, onStateCha
|
|
|
129
143
|
if (snapshot.columnPinning !== void 0) {
|
|
130
144
|
states.columnPinningState.value = snapshot.columnPinning;
|
|
131
145
|
}
|
|
132
|
-
if (snapshot.
|
|
146
|
+
if (snapshot.columnSizingRatios !== void 0 && hasKeys(snapshot.columnSizingRatios)) {
|
|
147
|
+
pendingRatios = snapshot.columnSizingRatios;
|
|
148
|
+
if (snapshot.columnSizing !== void 0) {
|
|
149
|
+
states.columnSizingState.value = snapshot.columnSizing;
|
|
150
|
+
}
|
|
151
|
+
} else if (snapshot.columnSizing !== void 0) {
|
|
133
152
|
states.columnSizingState.value = snapshot.columnSizing;
|
|
134
153
|
}
|
|
135
154
|
if (snapshot.columnSizingInfo !== void 0) {
|
|
@@ -154,6 +173,12 @@ export function useNuGridStatePersistence(states, enabled, storageId, onStateCha
|
|
|
154
173
|
states.paginationState.value = snapshot.pagination;
|
|
155
174
|
}
|
|
156
175
|
}
|
|
176
|
+
function applyPendingRatios() {
|
|
177
|
+
if (pendingRatios && helpers?.applySizingFromRatios) {
|
|
178
|
+
helpers.applySizingFromRatios(pendingRatios);
|
|
179
|
+
pendingRatios = null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
157
182
|
function setState(snapshot) {
|
|
158
183
|
try {
|
|
159
184
|
isRestoring = true;
|
|
@@ -236,8 +261,46 @@ export function useNuGridStatePersistence(states, enabled, storageId, onStateCha
|
|
|
236
261
|
watchersActive = true;
|
|
237
262
|
initialActivationComplete = true;
|
|
238
263
|
}
|
|
264
|
+
function setResizeHelpers(newHelpers) {
|
|
265
|
+
helpers = newHelpers;
|
|
266
|
+
}
|
|
267
|
+
function clearState() {
|
|
268
|
+
try {
|
|
269
|
+
isRestoring = true;
|
|
270
|
+
if (storedState) {
|
|
271
|
+
storedState.value = null;
|
|
272
|
+
}
|
|
273
|
+
if (cookieStateRef) {
|
|
274
|
+
cookieStateRef.value = null;
|
|
275
|
+
}
|
|
276
|
+
states.globalFilterState.value = "";
|
|
277
|
+
states.columnFiltersState.value = [];
|
|
278
|
+
states.columnOrderState.value = [];
|
|
279
|
+
states.columnVisibilityState.value = {};
|
|
280
|
+
states.columnPinningState.value = {};
|
|
281
|
+
states.columnSizingState.value = {};
|
|
282
|
+
states.columnSizingInfoState.value = {};
|
|
283
|
+
states.rowSelectionState.value = {};
|
|
284
|
+
states.rowPinningState.value = {};
|
|
285
|
+
states.sortingState.value = [];
|
|
286
|
+
states.groupingState.value = [];
|
|
287
|
+
states.expandedState.value = {};
|
|
288
|
+
states.paginationState.value = { pageIndex: 0, pageSize: 10 };
|
|
289
|
+
pendingRatios = null;
|
|
290
|
+
emitStateChanged({});
|
|
291
|
+
nextTick(() => {
|
|
292
|
+
isRestoring = false;
|
|
293
|
+
});
|
|
294
|
+
} catch (error) {
|
|
295
|
+
console.warn("[NuGrid State] Failed to clear state:", error);
|
|
296
|
+
isRestoring = false;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
239
299
|
return {
|
|
240
300
|
getState,
|
|
241
|
-
setState
|
|
301
|
+
setState,
|
|
302
|
+
clearState,
|
|
303
|
+
applyPendingRatios,
|
|
304
|
+
setResizeHelpers
|
|
242
305
|
};
|
|
243
306
|
}
|
|
@@ -1281,6 +1281,122 @@ export declare function useNuGridUI(props: NuGridProps): {
|
|
|
1281
1281
|
virtualize?: boolean | undefined;
|
|
1282
1282
|
sticky?: boolean | "header" | "footer" | undefined;
|
|
1283
1283
|
} & import("tailwind-variants").ClassProp<import("tailwind-merge").ClassNameValue>) | undefined) => string;
|
|
1284
|
+
headerControls: (slotProps?: ({
|
|
1285
|
+
loading?: boolean | undefined;
|
|
1286
|
+
loadingAnimation?: "carousel" | "carousel-inverse" | "swing" | "elastic" | undefined;
|
|
1287
|
+
loadingColor?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" | undefined;
|
|
1288
|
+
focusCell?: boolean | undefined;
|
|
1289
|
+
focusRow?: boolean | undefined;
|
|
1290
|
+
rowInvalid?: boolean | undefined;
|
|
1291
|
+
hasLeftBorder?: boolean | undefined;
|
|
1292
|
+
hasRightBorder?: boolean | undefined;
|
|
1293
|
+
pinned?: boolean | undefined;
|
|
1294
|
+
gridFocused?: boolean | undefined;
|
|
1295
|
+
activeRow?: boolean | undefined;
|
|
1296
|
+
colResizing?: boolean | undefined;
|
|
1297
|
+
colDraggable?: boolean | undefined;
|
|
1298
|
+
colDragging?: boolean | undefined;
|
|
1299
|
+
colDropTarget?: boolean | undefined;
|
|
1300
|
+
focusMultiRow?: boolean | undefined;
|
|
1301
|
+
virtualize?: boolean | undefined;
|
|
1302
|
+
sticky?: boolean | "header" | "footer" | undefined;
|
|
1303
|
+
} & import("tailwind-variants").ClassProp<import("tailwind-merge").ClassNameValue>) | ({
|
|
1304
|
+
loading?: boolean | undefined;
|
|
1305
|
+
loadingAnimation?: "carousel" | "carousel-inverse" | "swing" | "elastic" | undefined;
|
|
1306
|
+
loadingColor?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" | undefined;
|
|
1307
|
+
focusCell?: boolean | undefined;
|
|
1308
|
+
focusRow?: boolean | undefined;
|
|
1309
|
+
rowInvalid?: boolean | undefined;
|
|
1310
|
+
hasLeftBorder?: boolean | undefined;
|
|
1311
|
+
hasRightBorder?: boolean | undefined;
|
|
1312
|
+
pinned?: boolean | undefined;
|
|
1313
|
+
gridFocused?: boolean | undefined;
|
|
1314
|
+
activeRow?: boolean | undefined;
|
|
1315
|
+
colResizing?: boolean | undefined;
|
|
1316
|
+
colDraggable?: boolean | undefined;
|
|
1317
|
+
colDragging?: boolean | undefined;
|
|
1318
|
+
colDropTarget?: boolean | undefined;
|
|
1319
|
+
focusMultiRow?: boolean | undefined;
|
|
1320
|
+
virtualize?: boolean | undefined;
|
|
1321
|
+
sticky?: boolean | "header" | "footer" | undefined;
|
|
1322
|
+
} & import("tailwind-variants").ClassProp<import("tailwind-merge").ClassNameValue>) | ({
|
|
1323
|
+
loading?: boolean | undefined;
|
|
1324
|
+
loadingAnimation?: "carousel" | "carousel-inverse" | "swing" | "elastic" | undefined;
|
|
1325
|
+
loadingColor?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" | undefined;
|
|
1326
|
+
focusCell?: boolean | undefined;
|
|
1327
|
+
focusRow?: boolean | undefined;
|
|
1328
|
+
rowInvalid?: boolean | undefined;
|
|
1329
|
+
hasLeftBorder?: boolean | undefined;
|
|
1330
|
+
hasRightBorder?: boolean | undefined;
|
|
1331
|
+
pinned?: boolean | undefined;
|
|
1332
|
+
gridFocused?: boolean | undefined;
|
|
1333
|
+
activeRow?: boolean | undefined;
|
|
1334
|
+
colResizing?: boolean | undefined;
|
|
1335
|
+
colDraggable?: boolean | undefined;
|
|
1336
|
+
colDragging?: boolean | undefined;
|
|
1337
|
+
colDropTarget?: boolean | undefined;
|
|
1338
|
+
focusMultiRow?: boolean | undefined;
|
|
1339
|
+
virtualize?: boolean | undefined;
|
|
1340
|
+
sticky?: boolean | "header" | "footer" | undefined;
|
|
1341
|
+
} & import("tailwind-variants").ClassProp<import("tailwind-merge").ClassNameValue>) | undefined) => string;
|
|
1342
|
+
columnMenu: (slotProps?: ({
|
|
1343
|
+
loading?: boolean | undefined;
|
|
1344
|
+
loadingAnimation?: "carousel" | "carousel-inverse" | "swing" | "elastic" | undefined;
|
|
1345
|
+
loadingColor?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" | undefined;
|
|
1346
|
+
focusCell?: boolean | undefined;
|
|
1347
|
+
focusRow?: boolean | undefined;
|
|
1348
|
+
rowInvalid?: boolean | undefined;
|
|
1349
|
+
hasLeftBorder?: boolean | undefined;
|
|
1350
|
+
hasRightBorder?: boolean | undefined;
|
|
1351
|
+
pinned?: boolean | undefined;
|
|
1352
|
+
gridFocused?: boolean | undefined;
|
|
1353
|
+
activeRow?: boolean | undefined;
|
|
1354
|
+
colResizing?: boolean | undefined;
|
|
1355
|
+
colDraggable?: boolean | undefined;
|
|
1356
|
+
colDragging?: boolean | undefined;
|
|
1357
|
+
colDropTarget?: boolean | undefined;
|
|
1358
|
+
focusMultiRow?: boolean | undefined;
|
|
1359
|
+
virtualize?: boolean | undefined;
|
|
1360
|
+
sticky?: boolean | "header" | "footer" | undefined;
|
|
1361
|
+
} & import("tailwind-variants").ClassProp<import("tailwind-merge").ClassNameValue>) | ({
|
|
1362
|
+
loading?: boolean | undefined;
|
|
1363
|
+
loadingAnimation?: "carousel" | "carousel-inverse" | "swing" | "elastic" | undefined;
|
|
1364
|
+
loadingColor?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" | undefined;
|
|
1365
|
+
focusCell?: boolean | undefined;
|
|
1366
|
+
focusRow?: boolean | undefined;
|
|
1367
|
+
rowInvalid?: boolean | undefined;
|
|
1368
|
+
hasLeftBorder?: boolean | undefined;
|
|
1369
|
+
hasRightBorder?: boolean | undefined;
|
|
1370
|
+
pinned?: boolean | undefined;
|
|
1371
|
+
gridFocused?: boolean | undefined;
|
|
1372
|
+
activeRow?: boolean | undefined;
|
|
1373
|
+
colResizing?: boolean | undefined;
|
|
1374
|
+
colDraggable?: boolean | undefined;
|
|
1375
|
+
colDragging?: boolean | undefined;
|
|
1376
|
+
colDropTarget?: boolean | undefined;
|
|
1377
|
+
focusMultiRow?: boolean | undefined;
|
|
1378
|
+
virtualize?: boolean | undefined;
|
|
1379
|
+
sticky?: boolean | "header" | "footer" | undefined;
|
|
1380
|
+
} & import("tailwind-variants").ClassProp<import("tailwind-merge").ClassNameValue>) | ({
|
|
1381
|
+
loading?: boolean | undefined;
|
|
1382
|
+
loadingAnimation?: "carousel" | "carousel-inverse" | "swing" | "elastic" | undefined;
|
|
1383
|
+
loadingColor?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" | undefined;
|
|
1384
|
+
focusCell?: boolean | undefined;
|
|
1385
|
+
focusRow?: boolean | undefined;
|
|
1386
|
+
rowInvalid?: boolean | undefined;
|
|
1387
|
+
hasLeftBorder?: boolean | undefined;
|
|
1388
|
+
hasRightBorder?: boolean | undefined;
|
|
1389
|
+
pinned?: boolean | undefined;
|
|
1390
|
+
gridFocused?: boolean | undefined;
|
|
1391
|
+
activeRow?: boolean | undefined;
|
|
1392
|
+
colResizing?: boolean | undefined;
|
|
1393
|
+
colDraggable?: boolean | undefined;
|
|
1394
|
+
colDragging?: boolean | undefined;
|
|
1395
|
+
colDropTarget?: boolean | undefined;
|
|
1396
|
+
focusMultiRow?: boolean | undefined;
|
|
1397
|
+
virtualize?: boolean | undefined;
|
|
1398
|
+
sticky?: boolean | "header" | "footer" | undefined;
|
|
1399
|
+
} & import("tailwind-variants").ClassProp<import("tailwind-merge").ClassNameValue>) | undefined) => string;
|
|
1284
1400
|
footerContent: (slotProps?: ({
|
|
1285
1401
|
loading?: boolean | undefined;
|
|
1286
1402
|
loadingAnimation?: "carousel" | "carousel-inverse" | "swing" | "elastic" | undefined;
|
|
@@ -21,7 +21,7 @@ export declare const nuGridDefaults: {
|
|
|
21
21
|
validateOnAddRow: true;
|
|
22
22
|
icon: string;
|
|
23
23
|
};
|
|
24
|
-
|
|
24
|
+
rowSelection: {
|
|
25
25
|
mode: "multi";
|
|
26
26
|
placement: "start";
|
|
27
27
|
enabled: true;
|
|
@@ -43,8 +43,8 @@ export declare const nuGridDefaults: {
|
|
|
43
43
|
mode: "div";
|
|
44
44
|
stickyHeaders: false;
|
|
45
45
|
scrollbars: "scroll";
|
|
46
|
-
autoSize:
|
|
47
|
-
|
|
46
|
+
autoSize: "fill";
|
|
47
|
+
resizeMode: "shift";
|
|
48
48
|
};
|
|
49
49
|
columnDefaults: {
|
|
50
50
|
sortIcons: {
|
|
@@ -113,7 +113,6 @@ export declare const nuGridDefaults: {
|
|
|
113
113
|
autoPageSizeMinimum: number;
|
|
114
114
|
suppressPanel: false;
|
|
115
115
|
};
|
|
116
|
-
skipAutoSizeColumns: never[];
|
|
117
116
|
cellTypes: never[];
|
|
118
117
|
addNewRow: false;
|
|
119
118
|
rowId: string;
|
|
@@ -21,7 +21,7 @@ export const nuGridDefaults = {
|
|
|
21
21
|
validateOnAddRow: true,
|
|
22
22
|
icon: "i-lucide-alert-circle"
|
|
23
23
|
},
|
|
24
|
-
|
|
24
|
+
rowSelection: {
|
|
25
25
|
mode: "multi",
|
|
26
26
|
placement: "start",
|
|
27
27
|
enabled: true,
|
|
@@ -43,8 +43,8 @@ export const nuGridDefaults = {
|
|
|
43
43
|
mode: "div",
|
|
44
44
|
stickyHeaders: false,
|
|
45
45
|
scrollbars: "scroll",
|
|
46
|
-
autoSize:
|
|
47
|
-
|
|
46
|
+
autoSize: "fill",
|
|
47
|
+
resizeMode: "shift"
|
|
48
48
|
},
|
|
49
49
|
columnDefaults: {
|
|
50
50
|
sortIcons: {
|
|
@@ -113,7 +113,6 @@ export const nuGridDefaults = {
|
|
|
113
113
|
autoPageSizeMinimum: 5,
|
|
114
114
|
suppressPanel: false
|
|
115
115
|
},
|
|
116
|
-
skipAutoSizeColumns: [],
|
|
117
116
|
cellTypes: [],
|
|
118
117
|
addNewRow: false,
|
|
119
118
|
rowId: "id",
|