@mantine-vue/table 2.4.0 → 3.1.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/cjs/index.cjs +1623 -49
- package/cjs/index.cjs.map +1 -1
- package/esm/index.mjs +1600 -52
- package/esm/index.mjs.map +1 -1
- package/lib/components/MVT_TableSlots.d.ts +28 -0
- package/lib/components/buttons/MVT_EditActionButtons.d.ts +1 -1
- package/lib/components/menus/MVT_ColumnActionMenu.d.ts +1 -1
- package/lib/index.d.mts +7 -0
- package/lib/index.d.ts +7 -0
- package/lib/server-grouping/MVT_ServerGroupingBody.d.ts +24 -0
- package/lib/server-grouping/MVT_ServerGroupingGroupBy.d.ts +45 -0
- package/lib/server-grouping/createServerGroupingProvider.d.ts +39 -0
- package/lib/server-grouping/serverGrouping.types.d.ts +494 -0
- package/lib/server-grouping/serverGrouping.utils.d.ts +31 -0
- package/lib/server-grouping/serverGroupingSelection.d.ts +65 -0
- package/lib/server-grouping/useMVT_ServerGrouping.d.ts +50 -0
- package/lib/types.d.ts +36 -2
- package/lib/utils/style.utils.d.ts +12 -0
- package/locales/en.cjs +11 -0
- package/locales/en.mjs +11 -0
- package/package.json +4 -4
- package/styles.css +60 -0
- package/styles.layer.css +60 -0
package/cjs/index.cjs
CHANGED
|
@@ -149,6 +149,896 @@ var getDefaultColumnOrderIds = (tableOptions, reset = false) => {
|
|
|
149
149
|
];
|
|
150
150
|
};
|
|
151
151
|
//#endregion
|
|
152
|
+
//#region src/server-grouping/serverGrouping.types.ts
|
|
153
|
+
var MVT_SERVER_GROUPING_ROOT_PATH_ID = "__root__";
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region src/utils/utils.ts
|
|
156
|
+
var parseFromValuesOrFunc = (fn, arg) => fn instanceof Function ? fn(arg) : fn;
|
|
157
|
+
//#endregion
|
|
158
|
+
//#region src/server-grouping/serverGroupingSelection.ts
|
|
159
|
+
/** The server-grouping engine of a table, when server grouping is active. */
|
|
160
|
+
var getServerGroupingManager = (table) => table._serverGrouping;
|
|
161
|
+
/**
|
|
162
|
+
* Record rows that the user may currently select: loaded records inside
|
|
163
|
+
* expanded groups only (never group rows, never collapsed or unloaded
|
|
164
|
+
* groups), filtered by `enableRowSelection`.
|
|
165
|
+
*/
|
|
166
|
+
var getServerGroupingSelectableRows = (table) => {
|
|
167
|
+
const manager = getServerGroupingManager(table);
|
|
168
|
+
if (!manager) return [];
|
|
169
|
+
const { enableRowSelection } = table.options;
|
|
170
|
+
return manager.getVisibleRecordRows().filter((row) => parseFromValuesOrFunc(enableRowSelection, row) !== false);
|
|
171
|
+
};
|
|
172
|
+
/** Whether one record row is selected, honoring exclude mode. */
|
|
173
|
+
var isServerGroupingRecordSelected = (table, row) => {
|
|
174
|
+
const selectAll = getServerGroupingManager(table)?.getSelectAll();
|
|
175
|
+
if (selectAll?.active) return !selectAll.excludedRowIds.includes(row.id);
|
|
176
|
+
return !!table.getState().rowSelection?.[row.id];
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Header-checkbox state for a server-grouped table.
|
|
180
|
+
*
|
|
181
|
+
* In *include* mode `isAll` means "every selectable loaded record is
|
|
182
|
+
* selected". In *exclude* mode ("all matching records") the selection is a
|
|
183
|
+
* query, so the checkbox is checked, and turns indeterminate as soon as the
|
|
184
|
+
* user unchecks individual rows.
|
|
185
|
+
*/
|
|
186
|
+
var getServerGroupingSelectionSummary = (table) => {
|
|
187
|
+
const rows = getServerGroupingSelectableRows(table);
|
|
188
|
+
const selectAll = getServerGroupingManager(table)?.getSelectAll() ?? {
|
|
189
|
+
active: false,
|
|
190
|
+
excludedRowIds: []
|
|
191
|
+
};
|
|
192
|
+
if (selectAll.active) {
|
|
193
|
+
const excludedVisible = rows.filter((row) => selectAll.excludedRowIds.includes(row.id)).length;
|
|
194
|
+
return {
|
|
195
|
+
excludedRowIds: selectAll.excludedRowIds,
|
|
196
|
+
isAll: selectAll.excludedRowIds.length === 0,
|
|
197
|
+
isSelectAllMatching: true,
|
|
198
|
+
isSome: selectAll.excludedRowIds.length > 0,
|
|
199
|
+
mode: "exclude",
|
|
200
|
+
selectableCount: rows.length,
|
|
201
|
+
selectedCount: rows.length - excludedVisible,
|
|
202
|
+
selectedRowIds: []
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const rowSelection = table.getState().rowSelection ?? {};
|
|
206
|
+
const selectedCount = rows.filter((row) => rowSelection[row.id]).length;
|
|
207
|
+
const selectedRowIds = Object.keys(rowSelection).filter((rowId) => rowSelection[rowId]);
|
|
208
|
+
const isAll = rows.length > 0 && selectedCount === rows.length;
|
|
209
|
+
return {
|
|
210
|
+
excludedRowIds: [],
|
|
211
|
+
isAll,
|
|
212
|
+
isSelectAllMatching: false,
|
|
213
|
+
isSome: !isAll && selectedRowIds.length > 0,
|
|
214
|
+
mode: "include",
|
|
215
|
+
selectableCount: rows.length,
|
|
216
|
+
selectedCount,
|
|
217
|
+
selectedRowIds
|
|
218
|
+
};
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* Everything a bulk action needs to send to the server.
|
|
222
|
+
*
|
|
223
|
+
* In exclude mode this is the query plus the user's deselections — no row ids
|
|
224
|
+
* are transferred, so it scales to millions of matching records.
|
|
225
|
+
*/
|
|
226
|
+
var getServerGroupingSelectionPayload = (table) => {
|
|
227
|
+
const manager = getServerGroupingManager(table);
|
|
228
|
+
const summary = getServerGroupingSelectionSummary(table);
|
|
229
|
+
const tableState = table.getState();
|
|
230
|
+
return {
|
|
231
|
+
columnFilters: tableState.columnFilters ?? [],
|
|
232
|
+
excludedRowIds: summary.excludedRowIds,
|
|
233
|
+
globalFilter: tableState.globalFilter,
|
|
234
|
+
grouping: manager?.getGroupingFields() ?? [],
|
|
235
|
+
mode: summary.mode,
|
|
236
|
+
rowIds: summary.selectedRowIds,
|
|
237
|
+
sorting: tableState.sorting ?? []
|
|
238
|
+
};
|
|
239
|
+
};
|
|
240
|
+
/**
|
|
241
|
+
* Header-checkbox toggle.
|
|
242
|
+
*
|
|
243
|
+
* - **Checking** selects every loaded record inside expanded groups. Records in
|
|
244
|
+
* collapsed or unloaded groups are never implicitly selected.
|
|
245
|
+
* - **Unchecking** clears the *entire* selection — including records whose
|
|
246
|
+
* group was collapsed since, and everything added by "select all matching
|
|
247
|
+
* records". Removing only the on-screen ids would leave invisible records
|
|
248
|
+
* selected while the header checkbox reads unchecked.
|
|
249
|
+
*/
|
|
250
|
+
var toggleAllServerGroupingRecordsSelected = (table, value) => {
|
|
251
|
+
const manager = getServerGroupingManager(table);
|
|
252
|
+
const summary = getServerGroupingSelectionSummary(table);
|
|
253
|
+
if (!(value ?? !(summary.isAll || summary.isSelectAllMatching))) {
|
|
254
|
+
manager?.setSelectAll({
|
|
255
|
+
active: false,
|
|
256
|
+
excludedRowIds: []
|
|
257
|
+
});
|
|
258
|
+
table.setRowSelection({});
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (summary.isSelectAllMatching) {
|
|
262
|
+
manager?.setSelectAll({
|
|
263
|
+
active: true,
|
|
264
|
+
excludedRowIds: []
|
|
265
|
+
});
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const rows = getServerGroupingSelectableRows(table);
|
|
269
|
+
table.setRowSelection((prev) => {
|
|
270
|
+
const selection = { ...prev };
|
|
271
|
+
rows.forEach((row) => {
|
|
272
|
+
selection[row.id] = true;
|
|
273
|
+
});
|
|
274
|
+
return selection;
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
/** Deselect the given record ids (used by `selection.clearOnCollapse`). */
|
|
278
|
+
var deselectServerGroupingRecords = (table, rowIds) => {
|
|
279
|
+
if (!rowIds.length) return;
|
|
280
|
+
table.setRowSelection((prev) => {
|
|
281
|
+
const selection = { ...prev };
|
|
282
|
+
rowIds.forEach((rowId) => delete selection[rowId]);
|
|
283
|
+
return selection;
|
|
284
|
+
});
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* Toggle a single server-grouping record.
|
|
288
|
+
*
|
|
289
|
+
* Provider rows live outside the table's row model (`data` is empty), so
|
|
290
|
+
* `row.toggleSelected()` — which resolves the row through `table.getRow()` —
|
|
291
|
+
* would throw. Selection state is mutated directly instead.
|
|
292
|
+
*
|
|
293
|
+
* Supports shift-click range selection across the loaded records currently on
|
|
294
|
+
* screen, matching the behavior of a regular MVT table.
|
|
295
|
+
*/
|
|
296
|
+
var toggleServerGroupingRecordSelected = (table, row, value, options) => {
|
|
297
|
+
const manager = getServerGroupingManager(table);
|
|
298
|
+
const rows = getServerGroupingSelectableRows(table);
|
|
299
|
+
const targetIds = new Set([row.id]);
|
|
300
|
+
if (options?.batch && options.lastSelectedRowId) {
|
|
301
|
+
const lastIndex = rows.findIndex((candidate) => candidate.id === options.lastSelectedRowId);
|
|
302
|
+
const currentIndex = rows.findIndex((candidate) => candidate.id === row.id);
|
|
303
|
+
if (lastIndex !== -1 && currentIndex !== -1) {
|
|
304
|
+
const [start, end] = lastIndex < currentIndex ? [lastIndex, currentIndex] : [currentIndex, lastIndex];
|
|
305
|
+
for (let index = start; index <= end; index++) targetIds.add(rows[index].id);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
const selectAll = manager?.getSelectAll();
|
|
309
|
+
if (selectAll?.active) {
|
|
310
|
+
const excluded = new Set(selectAll.excludedRowIds);
|
|
311
|
+
targetIds.forEach((rowId) => {
|
|
312
|
+
if (value) excluded.delete(rowId);
|
|
313
|
+
else excluded.add(rowId);
|
|
314
|
+
});
|
|
315
|
+
manager.setSelectAll({
|
|
316
|
+
active: true,
|
|
317
|
+
excludedRowIds: [...excluded]
|
|
318
|
+
});
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
table.setRowSelection((prev) => {
|
|
322
|
+
const selection = { ...prev };
|
|
323
|
+
targetIds.forEach((rowId) => {
|
|
324
|
+
if (value) selection[rowId] = true;
|
|
325
|
+
else delete selection[rowId];
|
|
326
|
+
});
|
|
327
|
+
return selection;
|
|
328
|
+
});
|
|
329
|
+
};
|
|
330
|
+
/**
|
|
331
|
+
* Opt-in "select all matching records" action: asks the consumer-provided
|
|
332
|
+
* `serverGrouping.selection.loadAllMatchingRowIds` for every row id matching
|
|
333
|
+
* the current filters (across all groups and pages) and selects them.
|
|
334
|
+
*/
|
|
335
|
+
var selectAllMatchingServerGroupingRecords = async (table) => {
|
|
336
|
+
const manager = getServerGroupingManager(table);
|
|
337
|
+
if (!manager) return;
|
|
338
|
+
const selectionOptions = manager.options.selection;
|
|
339
|
+
if ((selectionOptions?.selectAllMode ?? "query") === "query") {
|
|
340
|
+
table.setRowSelection({});
|
|
341
|
+
manager.setSelectAll({
|
|
342
|
+
active: true,
|
|
343
|
+
excludedRowIds: []
|
|
344
|
+
});
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
const loadAllMatchingRowIds = selectionOptions?.loadAllMatchingRowIds;
|
|
348
|
+
if (!loadAllMatchingRowIds) return;
|
|
349
|
+
const tableState = table.getState();
|
|
350
|
+
const rowIds = await loadAllMatchingRowIds({
|
|
351
|
+
columnFilters: tableState.columnFilters ?? [],
|
|
352
|
+
globalFilter: tableState.globalFilter,
|
|
353
|
+
grouping: manager.getGroupingFields(),
|
|
354
|
+
sorting: tableState.sorting ?? [],
|
|
355
|
+
table
|
|
356
|
+
});
|
|
357
|
+
table.setRowSelection((prev) => {
|
|
358
|
+
const selection = { ...prev };
|
|
359
|
+
rowIds.forEach((rowId) => {
|
|
360
|
+
selection[rowId] = true;
|
|
361
|
+
});
|
|
362
|
+
return selection;
|
|
363
|
+
});
|
|
364
|
+
};
|
|
365
|
+
//#endregion
|
|
366
|
+
//#region src/server-grouping/serverGrouping.utils.ts
|
|
367
|
+
/**
|
|
368
|
+
* Escape a path segment part so group ids may safely contain the reserved
|
|
369
|
+
* characters `/` and `:` (and `%`, used for escaping).
|
|
370
|
+
*/
|
|
371
|
+
var escapeServerGroupPathPart = (part) => part.replace(/%/g, "%25").replace(/:/g, "%3A").replace(/\//g, "%2F");
|
|
372
|
+
var unescapeServerGroupPathPart = (part) => part.replace(/%2F/g, "/").replace(/%3A/g, ":").replace(/%25/g, "%");
|
|
373
|
+
/**
|
|
374
|
+
* Build the stable path id of a group's content, e.g.
|
|
375
|
+
* `createServerGroupPathId('__root__', 'country', 'BH')` → `'country:BH'` and
|
|
376
|
+
* `createServerGroupPathId('country:BH', 'salesperson', '42')` →
|
|
377
|
+
* `'country:BH/salesperson:42'`. Never derived from row indexes.
|
|
378
|
+
*/
|
|
379
|
+
var createServerGroupPathId = (parentPathId, field, groupId) => {
|
|
380
|
+
const segment = `${escapeServerGroupPathPart(field)}:${escapeServerGroupPathPart(groupId)}`;
|
|
381
|
+
return parentPathId === "__root__" ? segment : `${parentPathId}/${segment}`;
|
|
382
|
+
};
|
|
383
|
+
/** Parse a path id back into its `{ field, groupId }` segments. Root → `[]`. */
|
|
384
|
+
var parseServerGroupPathId = (pathId) => {
|
|
385
|
+
if (pathId === "__root__") return [];
|
|
386
|
+
return pathId.split("/").map((segment) => {
|
|
387
|
+
const separatorIndex = segment.indexOf(":");
|
|
388
|
+
return {
|
|
389
|
+
field: unescapeServerGroupPathPart(segment.slice(0, separatorIndex)),
|
|
390
|
+
groupId: unescapeServerGroupPathPart(segment.slice(separatorIndex + 1))
|
|
391
|
+
};
|
|
392
|
+
});
|
|
393
|
+
};
|
|
394
|
+
/** Depth of the content addressed by a path id (root → 0). */
|
|
395
|
+
var getServerGroupPathDepth = (pathId) => pathId === "__root__" ? 0 : pathId.split("/").length;
|
|
396
|
+
/** Whether `pathId` equals `ancestorPathId` or is nested anywhere below it. */
|
|
397
|
+
var isServerGroupPathOrDescendant = (pathId, ancestorPathId) => ancestorPathId === "__root__" || pathId === ancestorPathId || pathId.startsWith(`${ancestorPathId}/`);
|
|
398
|
+
/** JSON replacer producing deterministic output for plain objects. */
|
|
399
|
+
var stableReplacer = (_key, value) => {
|
|
400
|
+
if (value && typeof value === "object" && !Array.isArray(value)) return Object.keys(value).sort().reduce((acc, key) => {
|
|
401
|
+
acc[key] = value[key];
|
|
402
|
+
return acc;
|
|
403
|
+
}, {});
|
|
404
|
+
return value;
|
|
405
|
+
};
|
|
406
|
+
/**
|
|
407
|
+
* Serialize cache key parts deterministically (object key order does not
|
|
408
|
+
* affect the result).
|
|
409
|
+
*/
|
|
410
|
+
var serializeServerGroupingCacheKey = (parts) => JSON.stringify(parts, stableReplacer);
|
|
411
|
+
/** Whether an error was caused by request cancellation (never shown as an error). */
|
|
412
|
+
var isAbortError = (error) => error instanceof DOMException ? error.name === "AbortError" : error?.name === "AbortError";
|
|
413
|
+
//#endregion
|
|
414
|
+
//#region src/server-grouping/useMVT_ServerGrouping.ts
|
|
415
|
+
var createMVT_ServerGroupingManager = (table, controlledExpandedReader, controlledSelectAllReader) => {
|
|
416
|
+
const serverGroupingOptions = table.options.serverGrouping;
|
|
417
|
+
if (!serverGroupingOptions?.provider || serverGroupingOptions.enabled === false) return;
|
|
418
|
+
const options = serverGroupingOptions;
|
|
419
|
+
const provider = options.provider;
|
|
420
|
+
const sortingMode = options.sortingMode ?? "independent";
|
|
421
|
+
const filteringMode = options.filteringMode ?? "shared";
|
|
422
|
+
const cacheOptions = {
|
|
423
|
+
enabled: options.cache?.enabled ?? false,
|
|
424
|
+
gcTime: options.cache?.gcTime ?? 3e5,
|
|
425
|
+
keepCollapsedGroups: options.cache?.keepCollapsedGroups ?? true,
|
|
426
|
+
staleTime: options.cache?.staleTime ?? 0
|
|
427
|
+
};
|
|
428
|
+
const configuredPageSize = options.pagination?.defaultPageSize ?? options.initialPageSize ?? 10;
|
|
429
|
+
let defaultPageSize = configuredPageSize;
|
|
430
|
+
if (!Number.isInteger(configuredPageSize) || configuredPageSize <= 0) {
|
|
431
|
+
console.warn(`[mantine-vue-table] serverGrouping page size ${JSON.stringify(configuredPageSize)} is invalid — expected a positive integer. Falling back to 10.`);
|
|
432
|
+
defaultPageSize = 10;
|
|
433
|
+
}
|
|
434
|
+
const pathStates = (0, vue.ref)({});
|
|
435
|
+
const internalExpanded = (0, vue.ref)(table.options.initialState?.serverGroupingExpanded ?? {});
|
|
436
|
+
const internalSelectAll = (0, vue.ref)(table.options.initialState?.serverGroupingSelectAll ?? {
|
|
437
|
+
active: false,
|
|
438
|
+
excludedRowIds: []
|
|
439
|
+
});
|
|
440
|
+
const nodeRegistry = /* @__PURE__ */ new Map();
|
|
441
|
+
const controllers = /* @__PURE__ */ new Map();
|
|
442
|
+
const versions = /* @__PURE__ */ new Map();
|
|
443
|
+
const cache = /* @__PURE__ */ new Map();
|
|
444
|
+
const rowCache = /* @__PURE__ */ new Map();
|
|
445
|
+
const readControlledExpanded = controlledExpandedReader ?? (() => table.options.state?.serverGroupingExpanded);
|
|
446
|
+
const isExpandedControlled = readControlledExpanded() !== void 0;
|
|
447
|
+
const getExpanded = () => readControlledExpanded() ?? internalExpanded.value;
|
|
448
|
+
const setExpanded = (updater) => {
|
|
449
|
+
const next = updater instanceof Function ? updater(getExpanded()) : updater;
|
|
450
|
+
const onChange = table.options.onServerGroupingExpandedChange;
|
|
451
|
+
if (onChange) onChange(next);
|
|
452
|
+
if (!isExpandedControlled) internalExpanded.value = next;
|
|
453
|
+
};
|
|
454
|
+
const isExpanded = (pathId) => getExpanded()[pathId] === true;
|
|
455
|
+
const readControlledSelectAll = controlledSelectAllReader ?? (() => table.options.state?.serverGroupingSelectAll);
|
|
456
|
+
const isSelectAllControlled = readControlledSelectAll() !== void 0;
|
|
457
|
+
const getSelectAll = () => readControlledSelectAll() ?? internalSelectAll.value;
|
|
458
|
+
const setSelectAll = (updater) => {
|
|
459
|
+
const next = updater instanceof Function ? updater(getSelectAll()) : updater;
|
|
460
|
+
table.options.onServerGroupingSelectAllChange?.(next);
|
|
461
|
+
if (!isSelectAllControlled) internalSelectAll.value = next;
|
|
462
|
+
};
|
|
463
|
+
/** The "all matching" selection is tied to the query it was made under. */
|
|
464
|
+
const resetSelectAll = () => {
|
|
465
|
+
if (getSelectAll().active || getSelectAll().excludedRowIds.length) setSelectAll({
|
|
466
|
+
active: false,
|
|
467
|
+
excludedRowIds: []
|
|
468
|
+
});
|
|
469
|
+
};
|
|
470
|
+
const getGroupingFields = () => options.grouping ?? table.getState().grouping ?? [];
|
|
471
|
+
const setPathState = (pathId, state) => {
|
|
472
|
+
pathStates.value = {
|
|
473
|
+
...pathStates.value,
|
|
474
|
+
[pathId]: state
|
|
475
|
+
};
|
|
476
|
+
};
|
|
477
|
+
const getPathState = (pathId) => pathStates.value[pathId];
|
|
478
|
+
/**
|
|
479
|
+
* Table rows for one loaded record page. Rows are created (and cached) here
|
|
480
|
+
* rather than in the renderer so row ids — and therefore selection state —
|
|
481
|
+
* have a single source of truth shared by the body, the header checkbox, and
|
|
482
|
+
* the public selection APIs.
|
|
483
|
+
*/
|
|
484
|
+
const getRecordRows = (pathId) => {
|
|
485
|
+
const state = getPathState(pathId);
|
|
486
|
+
if (!state || state.kind !== "records" || !state.rows) return [];
|
|
487
|
+
const cached = rowCache.get(pathId);
|
|
488
|
+
if (cached && cached.source === state.rows) return cached.rows;
|
|
489
|
+
const depth = getServerGroupPathDepth(pathId);
|
|
490
|
+
const rows = state.rows.map((original, index) => {
|
|
491
|
+
return (0, _tanstack_vue_table.createRow)(table, provider.getRowId?.(original) ?? table.options.getRowId?.(original, index, void 0) ?? `${pathId}::${index}`, original, index, depth);
|
|
492
|
+
});
|
|
493
|
+
rowCache.set(pathId, {
|
|
494
|
+
rows,
|
|
495
|
+
source: state.rows
|
|
496
|
+
});
|
|
497
|
+
return rows;
|
|
498
|
+
};
|
|
499
|
+
/**
|
|
500
|
+
* Every loaded record row that is currently visible — i.e. inside expanded
|
|
501
|
+
* groups on the current pages. Records in collapsed or never-loaded groups
|
|
502
|
+
* are deliberately excluded, so selection can never reach them.
|
|
503
|
+
*/
|
|
504
|
+
const getVisibleRecordRows = () => Object.keys(pathStates.value).filter((pathId) => pathStates.value[pathId]?.kind === "records" && isPathVisible(pathId)).flatMap((pathId) => getRecordRows(pathId));
|
|
505
|
+
const getNode = (pathId) => {
|
|
506
|
+
const item = nodeRegistry.get(pathId);
|
|
507
|
+
if (!item) return void 0;
|
|
508
|
+
return {
|
|
509
|
+
count: void 0,
|
|
510
|
+
id: item.id,
|
|
511
|
+
label: item.label,
|
|
512
|
+
meta: item.meta,
|
|
513
|
+
original: item.original,
|
|
514
|
+
value: item.value,
|
|
515
|
+
...item.__node
|
|
516
|
+
};
|
|
517
|
+
};
|
|
518
|
+
const getParentItems = (pathId) => {
|
|
519
|
+
if (pathId === "__root__") return [];
|
|
520
|
+
const segments = pathId.split("/");
|
|
521
|
+
const items = [];
|
|
522
|
+
for (let index = 0; index < segments.length; index++) {
|
|
523
|
+
const ancestorPathId = segments.slice(0, index + 1).join("/");
|
|
524
|
+
const item = nodeRegistry.get(ancestorPathId);
|
|
525
|
+
if (item) items.push(item);
|
|
526
|
+
}
|
|
527
|
+
return items;
|
|
528
|
+
};
|
|
529
|
+
const getEffectiveSorting = (pathId, kind) => {
|
|
530
|
+
const override = getPathState(pathId)?.sorting;
|
|
531
|
+
if (override) return override;
|
|
532
|
+
const tableSorting = table.getState().sorting ?? [];
|
|
533
|
+
if (sortingMode === "shared") return tableSorting;
|
|
534
|
+
if (sortingMode === "records-only") return kind === "records" ? tableSorting : [];
|
|
535
|
+
return pathId === "__root__" ? tableSorting : [];
|
|
536
|
+
};
|
|
537
|
+
const getEffectiveFilters = (pathId, kind) => {
|
|
538
|
+
const state = getPathState(pathId);
|
|
539
|
+
if (state?.columnFilters || state?.globalFilter !== void 0) return {
|
|
540
|
+
columnFilters: state.columnFilters ?? [],
|
|
541
|
+
globalFilter: state.globalFilter
|
|
542
|
+
};
|
|
543
|
+
if (filteringMode === "independent") return {
|
|
544
|
+
columnFilters: [],
|
|
545
|
+
globalFilter: void 0
|
|
546
|
+
};
|
|
547
|
+
if (filteringMode === "records-only" && kind !== "records") return {
|
|
548
|
+
columnFilters: [],
|
|
549
|
+
globalFilter: void 0
|
|
550
|
+
};
|
|
551
|
+
const tableState = table.getState();
|
|
552
|
+
return {
|
|
553
|
+
columnFilters: tableState.columnFilters ?? [],
|
|
554
|
+
globalFilter: tableState.globalFilter
|
|
555
|
+
};
|
|
556
|
+
};
|
|
557
|
+
const isRootPath = (pathId) => pathId === MVT_SERVER_GROUPING_ROOT_PATH_ID;
|
|
558
|
+
const getDefaultPagination = () => ({
|
|
559
|
+
pageIndex: 0,
|
|
560
|
+
pageSize: defaultPageSize
|
|
561
|
+
});
|
|
562
|
+
/**
|
|
563
|
+
* Effective pagination of a path. The root level is driven by the table's
|
|
564
|
+
* own `pagination` state, so the standard bottom toolbar (page navigation +
|
|
565
|
+
* rows-per-page) controls it exactly like an ungrouped server-side table.
|
|
566
|
+
* Nested levels keep their own independent, fixed-page-size state.
|
|
567
|
+
*/
|
|
568
|
+
const getEffectivePagination = (pathId) => {
|
|
569
|
+
if (isRootPath(pathId)) {
|
|
570
|
+
const { pageIndex, pageSize } = table.getState().pagination;
|
|
571
|
+
return {
|
|
572
|
+
...getPathState(pathId)?.pagination,
|
|
573
|
+
pageIndex,
|
|
574
|
+
pageSize
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
return getPathState(pathId)?.pagination ?? getDefaultPagination();
|
|
578
|
+
};
|
|
579
|
+
/** Reset a path to page 0. Returns `true` when it triggered a root reload. */
|
|
580
|
+
const resetPageIndex = (pathId) => {
|
|
581
|
+
if (isRootPath(pathId)) {
|
|
582
|
+
const { pageIndex } = table.getState().pagination;
|
|
583
|
+
if (pageIndex === 0) return false;
|
|
584
|
+
table.setPageIndex(0);
|
|
585
|
+
return true;
|
|
586
|
+
}
|
|
587
|
+
const state = getPathState(pathId);
|
|
588
|
+
if (state) setPathState(pathId, {
|
|
589
|
+
...state,
|
|
590
|
+
pagination: {
|
|
591
|
+
...state.pagination,
|
|
592
|
+
cursor: void 0,
|
|
593
|
+
pageIndex: 0
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
return false;
|
|
597
|
+
};
|
|
598
|
+
const buildRequest = (pathId, kind, signal) => {
|
|
599
|
+
const grouping = getGroupingFields();
|
|
600
|
+
const depth = getServerGroupPathDepth(pathId);
|
|
601
|
+
const parentGroups = getParentItems(pathId);
|
|
602
|
+
const { columnFilters, globalFilter } = getEffectiveFilters(pathId, kind);
|
|
603
|
+
const base = {
|
|
604
|
+
columnFilters,
|
|
605
|
+
depth,
|
|
606
|
+
globalFilter,
|
|
607
|
+
grouping,
|
|
608
|
+
pagination: getEffectivePagination(pathId),
|
|
609
|
+
parentGroup: parentGroups.at(-1),
|
|
610
|
+
parentGroups,
|
|
611
|
+
pathId,
|
|
612
|
+
signal,
|
|
613
|
+
sorting: getEffectiveSorting(pathId, kind),
|
|
614
|
+
table
|
|
615
|
+
};
|
|
616
|
+
return kind === "groups" ? {
|
|
617
|
+
...base,
|
|
618
|
+
groupingField: grouping[depth]
|
|
619
|
+
} : base;
|
|
620
|
+
};
|
|
621
|
+
const getCacheKey = (request) => serializeServerGroupingCacheKey([
|
|
622
|
+
request.pathId,
|
|
623
|
+
request.grouping,
|
|
624
|
+
request.depth,
|
|
625
|
+
request.pagination,
|
|
626
|
+
request.sorting,
|
|
627
|
+
request.columnFilters,
|
|
628
|
+
request.globalFilter ?? null,
|
|
629
|
+
...provider.getCacheKey?.(request) ?? []
|
|
630
|
+
]);
|
|
631
|
+
const gcCache = () => {
|
|
632
|
+
const now = Date.now();
|
|
633
|
+
cache.forEach((entry, key) => {
|
|
634
|
+
if (now - entry.updatedAt > cacheOptions.gcTime) cache.delete(key);
|
|
635
|
+
});
|
|
636
|
+
};
|
|
637
|
+
const load = (pathId) => {
|
|
638
|
+
const grouping = getGroupingFields();
|
|
639
|
+
const depth = getServerGroupPathDepth(pathId);
|
|
640
|
+
const kind = depth >= grouping.length ? "records" : "groups";
|
|
641
|
+
const previous = getPathState(pathId);
|
|
642
|
+
const hasData = previous?.groups !== void 0 || previous?.rows !== void 0;
|
|
643
|
+
controllers.get(pathId)?.abort();
|
|
644
|
+
const controller = new AbortController();
|
|
645
|
+
controllers.set(pathId, controller);
|
|
646
|
+
const version = (versions.get(pathId) ?? 0) + 1;
|
|
647
|
+
versions.set(pathId, version);
|
|
648
|
+
const request = buildRequest(pathId, kind, controller.signal);
|
|
649
|
+
const isCurrent = () => versions.get(pathId) === version && !controller.signal.aborted;
|
|
650
|
+
let servedFromCache = false;
|
|
651
|
+
let cacheKey;
|
|
652
|
+
if (cacheOptions.enabled) {
|
|
653
|
+
cacheKey = getCacheKey(request);
|
|
654
|
+
const entry = cache.get(cacheKey);
|
|
655
|
+
if (entry) {
|
|
656
|
+
servedFromCache = true;
|
|
657
|
+
const fresh = Date.now() - entry.updatedAt <= cacheOptions.staleTime;
|
|
658
|
+
setPathState(pathId, {
|
|
659
|
+
...entry.payload,
|
|
660
|
+
columnFilters: previous?.columnFilters,
|
|
661
|
+
depth,
|
|
662
|
+
error: null,
|
|
663
|
+
globalFilter: previous?.globalFilter,
|
|
664
|
+
isFetching: !fresh,
|
|
665
|
+
isLoading: false,
|
|
666
|
+
pagination: request.pagination,
|
|
667
|
+
pathId,
|
|
668
|
+
sorting: previous?.sorting,
|
|
669
|
+
updatedAt: entry.updatedAt
|
|
670
|
+
});
|
|
671
|
+
if (entry.payload.kind === "groups") registerGroups(pathId, entry.payload.groups ?? [], grouping[depth], depth);
|
|
672
|
+
if (fresh) return;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
if (!servedFromCache) setPathState(pathId, {
|
|
676
|
+
...previous,
|
|
677
|
+
columnFilters: previous?.columnFilters,
|
|
678
|
+
depth,
|
|
679
|
+
error: null,
|
|
680
|
+
groups: kind === "groups" ? previous?.groups : void 0,
|
|
681
|
+
isFetching: true,
|
|
682
|
+
isLoading: !hasData,
|
|
683
|
+
kind,
|
|
684
|
+
pagination: request.pagination,
|
|
685
|
+
pathId,
|
|
686
|
+
rowCount: previous?.rowCount ?? 0,
|
|
687
|
+
rows: kind === "records" ? previous?.rows : void 0,
|
|
688
|
+
sorting: previous?.sorting
|
|
689
|
+
});
|
|
690
|
+
const eventPayload = {
|
|
691
|
+
path: request.parentGroups,
|
|
692
|
+
pathId
|
|
693
|
+
};
|
|
694
|
+
options.onGroupLoadStart?.({
|
|
695
|
+
...eventPayload,
|
|
696
|
+
request
|
|
697
|
+
});
|
|
698
|
+
const promise = kind === "groups" ? provider.loadGroups(request) : provider.loadRecords(request);
|
|
699
|
+
Promise.resolve(promise).then((response) => {
|
|
700
|
+
if (!isCurrent()) return;
|
|
701
|
+
const updatedAt = Date.now();
|
|
702
|
+
let payload;
|
|
703
|
+
if (kind === "groups") {
|
|
704
|
+
const context = {
|
|
705
|
+
depth,
|
|
706
|
+
field: grouping[depth],
|
|
707
|
+
request
|
|
708
|
+
};
|
|
709
|
+
const groups = (provider.getGroups(response) ?? []).map((group) => ({
|
|
710
|
+
count: provider.getGroupCount?.(group, context),
|
|
711
|
+
hasChildren: provider.hasGroupChildren?.(group, context) ?? true,
|
|
712
|
+
id: provider.getGroupId(group, context),
|
|
713
|
+
label: provider.getGroupLabel(group, context),
|
|
714
|
+
meta: provider.getGroupMeta?.(group, context) ?? {},
|
|
715
|
+
original: group,
|
|
716
|
+
value: provider.getGroupValue ? provider.getGroupValue(group, context) : group
|
|
717
|
+
}));
|
|
718
|
+
registerGroups(pathId, groups, grouping[depth], depth);
|
|
719
|
+
payload = {
|
|
720
|
+
groups,
|
|
721
|
+
kind,
|
|
722
|
+
rowCount: provider.getGroupRowCount(response)
|
|
723
|
+
};
|
|
724
|
+
options.onGroupLoadSuccess?.({
|
|
725
|
+
...eventPayload,
|
|
726
|
+
groups,
|
|
727
|
+
request,
|
|
728
|
+
response
|
|
729
|
+
});
|
|
730
|
+
} else {
|
|
731
|
+
const rows = provider.getRecords(response) ?? [];
|
|
732
|
+
payload = {
|
|
733
|
+
kind,
|
|
734
|
+
rowCount: provider.getRecordRowCount(response),
|
|
735
|
+
rows
|
|
736
|
+
};
|
|
737
|
+
options.onRecordLoadSuccess?.({
|
|
738
|
+
...eventPayload,
|
|
739
|
+
request,
|
|
740
|
+
response,
|
|
741
|
+
rows
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
setPathState(pathId, {
|
|
745
|
+
...getPathState(pathId),
|
|
746
|
+
...payload,
|
|
747
|
+
error: null,
|
|
748
|
+
isFetching: false,
|
|
749
|
+
isLoading: false,
|
|
750
|
+
updatedAt
|
|
751
|
+
});
|
|
752
|
+
if (cacheOptions.enabled && cacheKey) {
|
|
753
|
+
cache.set(cacheKey, {
|
|
754
|
+
pathId,
|
|
755
|
+
payload,
|
|
756
|
+
updatedAt
|
|
757
|
+
});
|
|
758
|
+
gcCache();
|
|
759
|
+
}
|
|
760
|
+
}).catch((error) => {
|
|
761
|
+
if (!isCurrent() || isAbortError(error)) return;
|
|
762
|
+
setPathState(pathId, {
|
|
763
|
+
...getPathState(pathId),
|
|
764
|
+
error,
|
|
765
|
+
isFetching: false,
|
|
766
|
+
isLoading: false
|
|
767
|
+
});
|
|
768
|
+
options.onError?.({
|
|
769
|
+
...eventPayload,
|
|
770
|
+
error,
|
|
771
|
+
request
|
|
772
|
+
});
|
|
773
|
+
});
|
|
774
|
+
};
|
|
775
|
+
const registerGroups = (parentPathId, groups, field, depth) => {
|
|
776
|
+
groups.forEach((node) => {
|
|
777
|
+
const childPathId = createServerGroupPathId(parentPathId, field, node.id);
|
|
778
|
+
const item = {
|
|
779
|
+
depth,
|
|
780
|
+
field,
|
|
781
|
+
id: node.id,
|
|
782
|
+
label: node.label,
|
|
783
|
+
meta: node.meta,
|
|
784
|
+
original: node.original,
|
|
785
|
+
value: node.value
|
|
786
|
+
};
|
|
787
|
+
item.__node = node;
|
|
788
|
+
nodeRegistry.set(childPathId, item);
|
|
789
|
+
});
|
|
790
|
+
};
|
|
791
|
+
const ensureLoaded = (pathId) => {
|
|
792
|
+
const state = getPathState(pathId);
|
|
793
|
+
if (!state || state.groups === void 0 && state.rows === void 0 && !state.isFetching) load(pathId);
|
|
794
|
+
};
|
|
795
|
+
const isPathVisible = (pathId) => {
|
|
796
|
+
if (pathId === "__root__") return true;
|
|
797
|
+
const segments = pathId.split("/");
|
|
798
|
+
for (let index = 0; index < segments.length; index++) if (!isExpanded(segments.slice(0, index + 1).join("/"))) return false;
|
|
799
|
+
return true;
|
|
800
|
+
};
|
|
801
|
+
const getLoadedVisiblePaths = () => Object.keys(pathStates.value).filter(isPathVisible);
|
|
802
|
+
const abortPathAndDescendants = (pathId) => {
|
|
803
|
+
controllers.forEach((controller, key) => {
|
|
804
|
+
if (!isServerGroupPathOrDescendant(key, pathId)) return;
|
|
805
|
+
controller.abort();
|
|
806
|
+
const state = getPathState(key);
|
|
807
|
+
if (state?.isFetching || state?.isLoading) setPathState(key, {
|
|
808
|
+
...state,
|
|
809
|
+
isFetching: false,
|
|
810
|
+
isLoading: false
|
|
811
|
+
});
|
|
812
|
+
});
|
|
813
|
+
};
|
|
814
|
+
const dropPathAndDescendants = (pathId) => {
|
|
815
|
+
const next = { ...pathStates.value };
|
|
816
|
+
Object.keys(next).forEach((key) => {
|
|
817
|
+
if (isServerGroupPathOrDescendant(key, pathId)) delete next[key];
|
|
818
|
+
});
|
|
819
|
+
pathStates.value = next;
|
|
820
|
+
cache.forEach((entry, key) => {
|
|
821
|
+
if (isServerGroupPathOrDescendant(entry.pathId, pathId)) cache.delete(key);
|
|
822
|
+
});
|
|
823
|
+
rowCache.forEach((_entry, key) => {
|
|
824
|
+
if (isServerGroupPathOrDescendant(key, pathId)) rowCache.delete(key);
|
|
825
|
+
});
|
|
826
|
+
};
|
|
827
|
+
const expand = (pathId) => {
|
|
828
|
+
if (isExpanded(pathId)) return;
|
|
829
|
+
setExpanded((prev) => ({
|
|
830
|
+
...prev,
|
|
831
|
+
[pathId]: true
|
|
832
|
+
}));
|
|
833
|
+
};
|
|
834
|
+
const collapse = (pathId) => {
|
|
835
|
+
if (!isExpanded(pathId)) return;
|
|
836
|
+
setExpanded((prev) => ({
|
|
837
|
+
...prev,
|
|
838
|
+
[pathId]: false
|
|
839
|
+
}));
|
|
840
|
+
};
|
|
841
|
+
const toggle = (pathId) => {
|
|
842
|
+
if (isExpanded(pathId)) collapse(pathId);
|
|
843
|
+
else expand(pathId);
|
|
844
|
+
};
|
|
845
|
+
const invalidate = (pathId) => {
|
|
846
|
+
if (pathId === void 0) cache.clear();
|
|
847
|
+
else cache.forEach((entry, key) => {
|
|
848
|
+
if (isServerGroupPathOrDescendant(entry.pathId, pathId)) cache.delete(key);
|
|
849
|
+
});
|
|
850
|
+
};
|
|
851
|
+
const reload = (pathId) => {
|
|
852
|
+
if (pathId !== void 0) {
|
|
853
|
+
invalidate(pathId);
|
|
854
|
+
if (getPathState(pathId)) load(pathId);
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
invalidate();
|
|
858
|
+
getLoadedVisiblePaths().forEach((visiblePathId) => load(visiblePathId));
|
|
859
|
+
};
|
|
860
|
+
const retry = (pathId) => {
|
|
861
|
+
load(pathId);
|
|
862
|
+
};
|
|
863
|
+
const reset = () => {
|
|
864
|
+
controllers.forEach((controller) => controller.abort());
|
|
865
|
+
controllers.clear();
|
|
866
|
+
versions.clear();
|
|
867
|
+
nodeRegistry.clear();
|
|
868
|
+
cache.clear();
|
|
869
|
+
rowCache.clear();
|
|
870
|
+
pathStates.value = {};
|
|
871
|
+
if (options.resetExpansionOnGroupingChange !== false) setExpanded({});
|
|
872
|
+
load(MVT_SERVER_GROUPING_ROOT_PATH_ID);
|
|
873
|
+
};
|
|
874
|
+
const setPagination = (pathId, updater) => {
|
|
875
|
+
const previous = getEffectivePagination(pathId);
|
|
876
|
+
const next = updater instanceof Function ? updater(previous) : {
|
|
877
|
+
...previous,
|
|
878
|
+
...updater
|
|
879
|
+
};
|
|
880
|
+
if (isRootPath(pathId)) {
|
|
881
|
+
const state = getPathState(pathId);
|
|
882
|
+
if (state) setPathState(pathId, {
|
|
883
|
+
...state,
|
|
884
|
+
pagination: next
|
|
885
|
+
});
|
|
886
|
+
const current = table.getState().pagination;
|
|
887
|
+
if (current.pageIndex === next.pageIndex && current.pageSize === next.pageSize) load(pathId);
|
|
888
|
+
else table.setPagination({
|
|
889
|
+
pageIndex: next.pageIndex,
|
|
890
|
+
pageSize: next.pageSize
|
|
891
|
+
});
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
const state = getPathState(pathId);
|
|
895
|
+
if (state) setPathState(pathId, {
|
|
896
|
+
...state,
|
|
897
|
+
pagination: next
|
|
898
|
+
});
|
|
899
|
+
else setPathState(pathId, {
|
|
900
|
+
depth: getServerGroupPathDepth(pathId),
|
|
901
|
+
error: null,
|
|
902
|
+
isFetching: false,
|
|
903
|
+
isLoading: false,
|
|
904
|
+
kind: getServerGroupPathDepth(pathId) >= getGroupingFields().length ? "records" : "groups",
|
|
905
|
+
pagination: next,
|
|
906
|
+
pathId,
|
|
907
|
+
rowCount: 0
|
|
908
|
+
});
|
|
909
|
+
load(pathId);
|
|
910
|
+
};
|
|
911
|
+
const setSorting = (pathId, updater) => {
|
|
912
|
+
const state = getPathState(pathId);
|
|
913
|
+
const previous = state?.sorting ?? [];
|
|
914
|
+
const next = updater instanceof Function ? updater(previous) : updater;
|
|
915
|
+
if (!state) return;
|
|
916
|
+
setPathState(pathId, {
|
|
917
|
+
...state,
|
|
918
|
+
sorting: next
|
|
919
|
+
});
|
|
920
|
+
if (!resetPageIndex(pathId)) load(pathId);
|
|
921
|
+
};
|
|
922
|
+
const setColumnFilters = (pathId, updater) => {
|
|
923
|
+
const state = getPathState(pathId);
|
|
924
|
+
if (!state) return;
|
|
925
|
+
const previous = state.columnFilters ?? [];
|
|
926
|
+
const next = updater instanceof Function ? updater(previous) : updater;
|
|
927
|
+
setPathState(pathId, {
|
|
928
|
+
...state,
|
|
929
|
+
columnFilters: next
|
|
930
|
+
});
|
|
931
|
+
if (!resetPageIndex(pathId)) load(pathId);
|
|
932
|
+
};
|
|
933
|
+
const setGlobalFilter = (pathId, value) => {
|
|
934
|
+
const state = getPathState(pathId);
|
|
935
|
+
if (!state) return;
|
|
936
|
+
setPathState(pathId, {
|
|
937
|
+
...state,
|
|
938
|
+
globalFilter: value
|
|
939
|
+
});
|
|
940
|
+
if (!resetPageIndex(pathId)) load(pathId);
|
|
941
|
+
};
|
|
942
|
+
const getState = () => ({
|
|
943
|
+
enabled: true,
|
|
944
|
+
expanded: getExpanded(),
|
|
945
|
+
grouping: getGroupingFields(),
|
|
946
|
+
paths: pathStates.value
|
|
947
|
+
});
|
|
948
|
+
(0, vue.watch)(() => ({ ...getExpanded() }), (next, prev) => {
|
|
949
|
+
Object.keys(next).forEach((pathId) => {
|
|
950
|
+
if (next[pathId] && !prev?.[pathId]) {
|
|
951
|
+
options.onGroupExpand?.({
|
|
952
|
+
group: getNode(pathId),
|
|
953
|
+
path: getParentItems(pathId),
|
|
954
|
+
pathId
|
|
955
|
+
});
|
|
956
|
+
ensureLoaded(pathId);
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
Object.keys(prev ?? {}).forEach((pathId) => {
|
|
960
|
+
if (prev?.[pathId] && !next[pathId]) {
|
|
961
|
+
options.onGroupCollapse?.({
|
|
962
|
+
group: getNode(pathId),
|
|
963
|
+
path: getParentItems(pathId),
|
|
964
|
+
pathId
|
|
965
|
+
});
|
|
966
|
+
abortPathAndDescendants(pathId);
|
|
967
|
+
if (options.selection?.clearOnCollapse) deselectServerGroupingRecords(table, Object.keys(pathStates.value).filter((key) => pathStates.value[key]?.kind === "records" && isServerGroupPathOrDescendant(key, pathId)).flatMap((key) => getRecordRows(key).map((row) => row.id)));
|
|
968
|
+
if (!cacheOptions.keepCollapsedGroups) dropPathAndDescendants(pathId);
|
|
969
|
+
}
|
|
970
|
+
});
|
|
971
|
+
});
|
|
972
|
+
(0, vue.watch)(() => JSON.stringify(getGroupingFields()), (next, prev) => {
|
|
973
|
+
if (next !== prev) {
|
|
974
|
+
resetSelectAll();
|
|
975
|
+
reset();
|
|
976
|
+
}
|
|
977
|
+
});
|
|
978
|
+
(0, vue.watch)(() => JSON.stringify([table.getState().columnFilters ?? [], table.getState().globalFilter ?? null]), (next, prev) => {
|
|
979
|
+
if (next === prev || filteringMode === "independent") return;
|
|
980
|
+
resetSelectAll();
|
|
981
|
+
invalidate();
|
|
982
|
+
getLoadedVisiblePaths().filter((pathId) => filteringMode === "shared" || getPathState(pathId)?.kind === "records").forEach((pathId) => {
|
|
983
|
+
setPathState(pathId, {
|
|
984
|
+
...getPathState(pathId),
|
|
985
|
+
groups: void 0,
|
|
986
|
+
rows: void 0
|
|
987
|
+
});
|
|
988
|
+
if (!resetPageIndex(pathId)) load(pathId);
|
|
989
|
+
});
|
|
990
|
+
});
|
|
991
|
+
(0, vue.watch)(() => JSON.stringify(table.getState().sorting ?? []), (next, prev) => {
|
|
992
|
+
if (next === prev) return;
|
|
993
|
+
getLoadedVisiblePaths().filter((pathId) => {
|
|
994
|
+
if (getPathState(pathId)?.sorting) return false;
|
|
995
|
+
if (sortingMode === "shared") return true;
|
|
996
|
+
if (sortingMode === "records-only") return getPathState(pathId)?.kind === "records";
|
|
997
|
+
return pathId === MVT_SERVER_GROUPING_ROOT_PATH_ID;
|
|
998
|
+
}).forEach((pathId) => {
|
|
999
|
+
if (!resetPageIndex(pathId)) load(pathId);
|
|
1000
|
+
});
|
|
1001
|
+
});
|
|
1002
|
+
(0, vue.watch)(() => {
|
|
1003
|
+
const { pageIndex, pageSize } = table.getState().pagination;
|
|
1004
|
+
return `${pageIndex}:${pageSize}`;
|
|
1005
|
+
}, (next, prev) => {
|
|
1006
|
+
if (next !== prev) load(MVT_SERVER_GROUPING_ROOT_PATH_ID);
|
|
1007
|
+
});
|
|
1008
|
+
load(MVT_SERVER_GROUPING_ROOT_PATH_ID);
|
|
1009
|
+
if ((0, vue.getCurrentScope)()) (0, vue.onScopeDispose)(() => {
|
|
1010
|
+
controllers.forEach((controller) => controller.abort());
|
|
1011
|
+
controllers.clear();
|
|
1012
|
+
});
|
|
1013
|
+
return {
|
|
1014
|
+
collapse,
|
|
1015
|
+
ensureLoaded,
|
|
1016
|
+
expand,
|
|
1017
|
+
getExpanded,
|
|
1018
|
+
getGroupingFields,
|
|
1019
|
+
getNode,
|
|
1020
|
+
getParentItems,
|
|
1021
|
+
getPathState,
|
|
1022
|
+
getRecordRows,
|
|
1023
|
+
getSelectAll,
|
|
1024
|
+
getState,
|
|
1025
|
+
getVisibleRecordRows,
|
|
1026
|
+
invalidate,
|
|
1027
|
+
isExpanded,
|
|
1028
|
+
options,
|
|
1029
|
+
reload,
|
|
1030
|
+
reset,
|
|
1031
|
+
retry,
|
|
1032
|
+
setColumnFilters,
|
|
1033
|
+
setExpanded,
|
|
1034
|
+
setGlobalFilter,
|
|
1035
|
+
setSelectAll,
|
|
1036
|
+
setPagination,
|
|
1037
|
+
setSorting,
|
|
1038
|
+
toggle
|
|
1039
|
+
};
|
|
1040
|
+
};
|
|
1041
|
+
//#endregion
|
|
152
1042
|
//#region src/utils/tanstack.helpers.ts
|
|
153
1043
|
/**
|
|
154
1044
|
* Vue equivalent of `@tanstack/react-table`'s `flexRender`.
|
|
@@ -178,9 +1068,6 @@ function createMVTColumnHelper() {
|
|
|
178
1068
|
}
|
|
179
1069
|
var createRow = (table, originalRow, rowIndex = -1, depth = 0, subRows, parentId) => (0, _tanstack_vue_table.createRow)(table, "mvt-row-create", originalRow ?? Object.assign({}, ...getAllLeafColumnDefs(table.options.columns).map((col) => ({ [getColumnId(col)]: "" }))), rowIndex, depth, subRows, parentId);
|
|
180
1070
|
//#endregion
|
|
181
|
-
//#region src/utils/utils.ts
|
|
182
|
-
var parseFromValuesOrFunc = (fn, arg) => fn instanceof Function ? fn(arg) : fn;
|
|
183
|
-
//#endregion
|
|
184
1071
|
//#region src/components/MVT_TableSlots.ts
|
|
185
1072
|
var MVT_SLOTS_KEY = Symbol("MVT_Slots");
|
|
186
1073
|
/**
|
|
@@ -656,7 +1543,7 @@ var MVT_EditCellTextInput = (0, vue.defineComponent)({
|
|
|
656
1543
|
label: modal ? def.header : void 0,
|
|
657
1544
|
name: cell.id,
|
|
658
1545
|
placeholder: !modal ? def.header : void 0,
|
|
659
|
-
|
|
1546
|
+
modelValue: value.value,
|
|
660
1547
|
variant: table.options.editDisplayMode === "table" ? "unstyled" : "default",
|
|
661
1548
|
onClick: (e) => e.stopPropagation(),
|
|
662
1549
|
ref: setRef
|
|
@@ -665,30 +1552,30 @@ var MVT_EditCellTextInput = (0, vue.defineComponent)({
|
|
|
665
1552
|
...common,
|
|
666
1553
|
searchable: true,
|
|
667
1554
|
...selectProps,
|
|
668
|
-
|
|
1555
|
+
"onUpdate:modelValue": (newValue) => {
|
|
669
1556
|
value.value = newValue;
|
|
670
|
-
selectProps.onChange?.(newValue, option);
|
|
671
1557
|
},
|
|
1558
|
+
onChange: selectProps.onChange,
|
|
672
1559
|
onBlur: blur
|
|
673
1560
|
});
|
|
674
1561
|
if (def.editVariant === "multi-select") return (0, vue.h)(_mantine_vue_core.MultiSelect, {
|
|
675
1562
|
...common,
|
|
676
1563
|
searchable: true,
|
|
677
1564
|
...selectProps,
|
|
678
|
-
|
|
1565
|
+
"onUpdate:modelValue": (newValue) => {
|
|
679
1566
|
value.value = newValue;
|
|
680
|
-
selectProps.onChange?.(newValue);
|
|
681
1567
|
},
|
|
1568
|
+
onChange: selectProps.onChange,
|
|
682
1569
|
onBlur: blur
|
|
683
1570
|
});
|
|
684
1571
|
return (0, vue.h)(_mantine_vue_core.TextInput, {
|
|
685
1572
|
...common,
|
|
686
|
-
|
|
1573
|
+
modelValue: value.value ?? "",
|
|
687
1574
|
...textProps,
|
|
688
|
-
|
|
689
|
-
value.value =
|
|
690
|
-
textProps.onChange?.(event);
|
|
1575
|
+
"onUpdate:modelValue": (nextValue) => {
|
|
1576
|
+
value.value = nextValue;
|
|
691
1577
|
},
|
|
1578
|
+
onChange: textProps.onChange,
|
|
692
1579
|
onBlur: blur,
|
|
693
1580
|
onKeydown: (event) => {
|
|
694
1581
|
textProps.onKeyDown?.(event);
|
|
@@ -1002,6 +1889,7 @@ var getIsRankingRows = (table) => {
|
|
|
1002
1889
|
};
|
|
1003
1890
|
var getIsRowSelected = ({ row, table }) => {
|
|
1004
1891
|
const { options: { enableRowSelection } } = table;
|
|
1892
|
+
if (getServerGroupingManager(table)) return isServerGroupingRecordSelected(table, row);
|
|
1005
1893
|
return row.getIsSelected() || parseFromValuesOrFunc(enableRowSelection, row) && row.getCanSelectSubRows() && row.getIsAllSubRowsSelected();
|
|
1006
1894
|
};
|
|
1007
1895
|
var getMVT_RowSelectionHandler = ({ renderedRowIndex = 0, row, table }) => (event, value) => {
|
|
@@ -1012,6 +1900,14 @@ var getMVT_RowSelectionHandler = ({ renderedRowIndex = 0, row, table }) => (even
|
|
|
1012
1900
|
row,
|
|
1013
1901
|
table
|
|
1014
1902
|
});
|
|
1903
|
+
if (getServerGroupingManager(table)) {
|
|
1904
|
+
toggleServerGroupingRecordSelected(table, row, value ?? !wasCurrentRowChecked, {
|
|
1905
|
+
batch: !!enableBatchRowSelection && enableMultiRowSelection !== false && event.shiftKey,
|
|
1906
|
+
lastSelectedRowId: lastSelectedRowId.value
|
|
1907
|
+
});
|
|
1908
|
+
lastSelectedRowId.value = row.id;
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1015
1911
|
row.toggleSelected(value ?? !wasCurrentRowChecked);
|
|
1016
1912
|
const changedRowIds = new Set([row.id]);
|
|
1017
1913
|
if (enableBatchRowSelection && enableMultiRowSelection && event.shiftKey && lastSelectedRowId.value !== null) {
|
|
@@ -1072,7 +1968,10 @@ var MVT_SelectCheckbox = (0, vue.defineComponent)({
|
|
|
1072
1968
|
const o = table.options;
|
|
1073
1969
|
const state = table.getState();
|
|
1074
1970
|
const selectAll = !row;
|
|
1075
|
-
const
|
|
1971
|
+
const anyTable = table;
|
|
1972
|
+
const serverGroupingSummary = selectAll && getServerGroupingManager(anyTable) ? getServerGroupingSelectionSummary(anyTable) : void 0;
|
|
1973
|
+
const isServerGrouping = !!getServerGroupingManager(anyTable);
|
|
1974
|
+
const checked = serverGroupingSummary ? serverGroupingSummary.isAll : selectAll ? o.selectAllMode === "page" ? table.getIsAllPageRowsSelected() : table.getIsAllRowsSelected() : isServerGrouping && row ? isServerGroupingRecordSelected(anyTable, row) : getIsRowSelected({
|
|
1076
1975
|
row,
|
|
1077
1976
|
table
|
|
1078
1977
|
});
|
|
@@ -1088,19 +1987,18 @@ var MVT_SelectCheckbox = (0, vue.defineComponent)({
|
|
|
1088
1987
|
renderedRowIndex: props.renderedRowIndex,
|
|
1089
1988
|
row,
|
|
1090
1989
|
table
|
|
1091
|
-
}) : getMVT_SelectAllHandler({ table });
|
|
1990
|
+
}) : serverGroupingSummary ? (event) => toggleAllServerGroupingRecordsSelected(anyTable, event.target?.checked ?? !serverGroupingSummary.isAll) : getMVT_SelectAllHandler({ table });
|
|
1092
1991
|
const common = {
|
|
1093
1992
|
"aria-label": label,
|
|
1094
1993
|
checked,
|
|
1095
|
-
disabled: state.isLoading || row && !row.getCanSelect() || row?.id === "mvt-row-create",
|
|
1994
|
+
disabled: state.isLoading || row && !row.getCanSelect() || row?.id === "mvt-row-create" || serverGroupingSummary?.selectableCount === 0 && serverGroupingSummary.selectedRowIds.length === 0,
|
|
1096
1995
|
size: state.density === "xs" ? "sm" : "md",
|
|
1097
1996
|
...checkboxProps,
|
|
1098
1997
|
title: void 0,
|
|
1099
|
-
onChange: (
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
checkboxProps.onChange?.(event);
|
|
1998
|
+
onChange: (nextChecked) => {
|
|
1999
|
+
selection({ shiftKey: lastShiftKey }, nextChecked);
|
|
2000
|
+
checkboxProps.onChange?.(nextChecked);
|
|
2001
|
+
lastShiftKey = false;
|
|
1104
2002
|
},
|
|
1105
2003
|
onClick: (event) => {
|
|
1106
2004
|
event.stopPropagation();
|
|
@@ -1109,7 +2007,7 @@ var MVT_SelectCheckbox = (0, vue.defineComponent)({
|
|
|
1109
2007
|
}
|
|
1110
2008
|
};
|
|
1111
2009
|
const control = o.selectDisplayMode === "switch" ? (0, vue.h)(_mantine_vue_core.Switch, common) : o.selectDisplayMode === "radio" || o.enableMultiRowSelection === false ? (0, vue.h)(_mantine_vue_core.Radio, common) : (0, vue.h)(_mantine_vue_core.Checkbox, {
|
|
1112
|
-
indeterminate: !checked && selectAll ? table.getIsSomeRowsSelected() : row?.getIsSomeSelected() && row.getCanSelectSubRows(),
|
|
2010
|
+
indeterminate: serverGroupingSummary ? serverGroupingSummary.isSome : !checked && selectAll ? table.getIsSomeRowsSelected() : row?.getIsSomeSelected() && row.getCanSelectSubRows(),
|
|
1113
2011
|
...common
|
|
1114
2012
|
});
|
|
1115
2013
|
return (0, vue.h)(_mantine_vue_core.Tooltip, {
|
|
@@ -1239,12 +2137,14 @@ var MVT_Default_Icons = {
|
|
|
1239
2137
|
//#region src/locales/en.ts
|
|
1240
2138
|
var MVT_Localization_EN = {
|
|
1241
2139
|
actions: "Actions",
|
|
2140
|
+
allMatchingRecordsSelected: "All records matching the current filters are selected",
|
|
1242
2141
|
and: "and",
|
|
1243
2142
|
cancel: "Cancel",
|
|
1244
2143
|
changeFilterMode: "Change filter mode",
|
|
1245
2144
|
changeSearchMode: "Change search mode",
|
|
1246
2145
|
clearFilter: "Clear filter",
|
|
1247
2146
|
clearSearch: "Clear search",
|
|
2147
|
+
clearGrouping: "Clear grouping",
|
|
1248
2148
|
clearSelection: "Clear selection",
|
|
1249
2149
|
clearSort: "Clear sort",
|
|
1250
2150
|
clickToCopy: "Click to copy",
|
|
@@ -1255,6 +2155,7 @@ var MVT_Localization_EN = {
|
|
|
1255
2155
|
copiedToClipboard: "Copied to clipboard",
|
|
1256
2156
|
dropToGroupBy: "Drop to group by {column}",
|
|
1257
2157
|
edit: "Edit",
|
|
2158
|
+
errorLoadingData: "Error loading data",
|
|
1258
2159
|
expand: "Expand",
|
|
1259
2160
|
expandAll: "Expand all",
|
|
1260
2161
|
filterArrIncludes: "Includes",
|
|
@@ -1287,13 +2188,18 @@ var MVT_Localization_EN = {
|
|
|
1287
2188
|
goToNextPage: "Go to next page",
|
|
1288
2189
|
goToPreviousPage: "Go to previous page",
|
|
1289
2190
|
grab: "Grab",
|
|
2191
|
+
groupBy: "Group by",
|
|
1290
2192
|
groupByColumn: "Group by {column}",
|
|
1291
2193
|
groupedBy: "Grouped by ",
|
|
1292
2194
|
hideAll: "Hide all",
|
|
1293
2195
|
hideColumn: "Hide {column} column",
|
|
2196
|
+
loading: "Loading…",
|
|
1294
2197
|
max: "Max",
|
|
1295
2198
|
min: "Min",
|
|
1296
2199
|
move: "Move",
|
|
2200
|
+
moveDown: "Move down",
|
|
2201
|
+
moveUp: "Move up",
|
|
2202
|
+
noGroupableColumns: "No groupable columns",
|
|
1297
2203
|
noRecordsToDisplay: "No records to display",
|
|
1298
2204
|
noResultsFound: "No results found",
|
|
1299
2205
|
of: "of",
|
|
@@ -1303,6 +2209,7 @@ var MVT_Localization_EN = {
|
|
|
1303
2209
|
pinToRight: "Pin to right",
|
|
1304
2210
|
resetColumnSize: "Reset column size",
|
|
1305
2211
|
resetOrder: "Reset order",
|
|
2212
|
+
retry: "Retry",
|
|
1306
2213
|
rowActions: "Row Actions",
|
|
1307
2214
|
rowNumber: "#",
|
|
1308
2215
|
rowNumbers: "Row Numbers",
|
|
@@ -1310,7 +2217,9 @@ var MVT_Localization_EN = {
|
|
|
1310
2217
|
save: "Save",
|
|
1311
2218
|
search: "Search",
|
|
1312
2219
|
selectedCountOfRowCountRowsSelected: "{selectedCount} of {rowCount} row(s) selected",
|
|
2220
|
+
selectedCountRowsSelected: "{selectedCount} row(s) selected",
|
|
1313
2221
|
select: "Select",
|
|
2222
|
+
selectAllMatching: "Select all matching records",
|
|
1314
2223
|
showAll: "Show all",
|
|
1315
2224
|
showAllColumns: "Show all columns",
|
|
1316
2225
|
showHideColumns: "Show/Hide columns",
|
|
@@ -1397,6 +2306,33 @@ var useMVT_TableOptions = (rawOptions) => {
|
|
|
1397
2306
|
manualPagination = true;
|
|
1398
2307
|
manualSorting = true;
|
|
1399
2308
|
}
|
|
2309
|
+
if (rest.serverGrouping?.provider && rest.serverGrouping.enabled !== false) {
|
|
2310
|
+
if (enableGrouping || rawOptions.manualGrouping) console.warn("[mantine-vue-table] `serverGrouping` cannot be combined with client-side `enableGrouping` or `manualGrouping`. Disable one of them — `serverGrouping` will take precedence for rendering.");
|
|
2311
|
+
manualFiltering = true;
|
|
2312
|
+
manualPagination = true;
|
|
2313
|
+
manualSorting = true;
|
|
2314
|
+
if (rawOptions.groupedColumnMode === void 0) rest.groupedColumnMode = false;
|
|
2315
|
+
const configuredPageSize = rest.serverGrouping.pagination?.defaultPageSize ?? rest.serverGrouping.initialPageSize;
|
|
2316
|
+
const seededPageSize = Number.isInteger(configuredPageSize) && configuredPageSize > 0 ? configuredPageSize : void 0;
|
|
2317
|
+
if (seededPageSize && rawOptions.state?.pagination === void 0) rest.initialState = {
|
|
2318
|
+
...rest.initialState,
|
|
2319
|
+
pagination: {
|
|
2320
|
+
pageIndex: rest.initialState?.pagination?.pageIndex ?? 0,
|
|
2321
|
+
pageSize: rest.initialState?.pagination?.pageSize ?? seededPageSize
|
|
2322
|
+
}
|
|
2323
|
+
};
|
|
2324
|
+
const { defaultGrouping } = rest.serverGrouping;
|
|
2325
|
+
if (defaultGrouping?.length && !rest.serverGrouping.grouping && rawOptions.state?.grouping === void 0 && rest.initialState?.grouping === void 0) rest.initialState = {
|
|
2326
|
+
...rest.initialState,
|
|
2327
|
+
grouping: [...defaultGrouping]
|
|
2328
|
+
};
|
|
2329
|
+
const configuredFields = [...rest.serverGrouping.grouping ?? [], ...defaultGrouping ?? []];
|
|
2330
|
+
if (configuredFields.length) {
|
|
2331
|
+
const knownFields = new Set([...getAllLeafColumnDefs(rawOptions.columns).map((col) => getColumnId(col)), ...rest.serverGrouping.groupBy?.columns ?? []]);
|
|
2332
|
+
const unknownFields = [...new Set(configuredFields)].filter((field) => !knownFields.has(field));
|
|
2333
|
+
if (unknownFields.length) console.warn(`[mantine-vue-table] serverGrouping field(s) ${unknownFields.map((field) => `"${field}"`).join(", ")} do not match any column id. Custom backend descriptors are supported — declare them in \`serverGrouping.groupBy.columns\` to silence this warning and make them selectable in the group-by toolbar.`);
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
1400
2336
|
const definedOptions = {
|
|
1401
2337
|
aggregationFns,
|
|
1402
2338
|
autoResetExpanded,
|
|
@@ -1645,6 +2581,12 @@ var useMVT_TableInstance = (definedTableOptions) => {
|
|
|
1645
2581
|
get: getter
|
|
1646
2582
|
});
|
|
1647
2583
|
};
|
|
2584
|
+
let serverGroupingManager;
|
|
2585
|
+
defineState("serverGroupingExpanded", () => serverGroupingManager?.getExpanded() ?? {});
|
|
2586
|
+
defineState("serverGroupingSelectAll", () => serverGroupingManager?.getSelectAll() ?? {
|
|
2587
|
+
active: false,
|
|
2588
|
+
excludedRowIds: []
|
|
2589
|
+
});
|
|
1648
2590
|
defineState("columnFilterFns", () => columnFilterFns.value);
|
|
1649
2591
|
defineState("columnOrder", () => columnOrder.value);
|
|
1650
2592
|
defineState("columnSizingInfo", () => columnSizingInfo.value);
|
|
@@ -1747,6 +2689,58 @@ var useMVT_TableInstance = (definedTableOptions) => {
|
|
|
1747
2689
|
table.setShowColumnFilters = statefulTableOptions.onShowColumnFiltersChange ?? ((updater) => applyUpdater(showColumnFilters, updater));
|
|
1748
2690
|
table.setShowGlobalFilter = statefulTableOptions.onShowGlobalFilterChange ?? ((updater) => applyUpdater(showGlobalFilter, updater));
|
|
1749
2691
|
table.setShowToolbarDropZone = statefulTableOptions.onShowToolbarDropZoneChange ?? ((updater) => applyUpdater(showToolbarDropZone, updater));
|
|
2692
|
+
serverGroupingManager = createMVT_ServerGroupingManager(table, () => userStateKeys.has("serverGroupingExpanded") ? readUserState().serverGroupingExpanded : void 0, () => userStateKeys.has("serverGroupingSelectAll") ? readUserState().serverGroupingSelectAll : void 0);
|
|
2693
|
+
table._serverGrouping = serverGroupingManager;
|
|
2694
|
+
if (serverGroupingManager) {
|
|
2695
|
+
const readUserRowCount = Object.getOwnPropertyDescriptor(definedTableOptions, "rowCount")?.get;
|
|
2696
|
+
Object.defineProperty(definedTableOptions, "rowCount", {
|
|
2697
|
+
configurable: true,
|
|
2698
|
+
enumerable: true,
|
|
2699
|
+
get: () => readUserRowCount?.call(definedTableOptions) ?? serverGroupingManager?.getPathState("__root__")?.rowCount
|
|
2700
|
+
});
|
|
2701
|
+
}
|
|
2702
|
+
table.getServerGroupingState = () => serverGroupingManager?.getState() ?? {
|
|
2703
|
+
enabled: false,
|
|
2704
|
+
expanded: {},
|
|
2705
|
+
grouping: [],
|
|
2706
|
+
paths: {}
|
|
2707
|
+
};
|
|
2708
|
+
table.getServerGroupingPathState = (pathId) => serverGroupingManager?.getPathState(pathId);
|
|
2709
|
+
table.expandServerGroup = (pathId) => serverGroupingManager?.expand(pathId);
|
|
2710
|
+
table.collapseServerGroup = (pathId) => serverGroupingManager?.collapse(pathId);
|
|
2711
|
+
table.toggleServerGroup = (pathId) => serverGroupingManager?.toggle(pathId);
|
|
2712
|
+
table.reloadServerGrouping = () => serverGroupingManager?.reload();
|
|
2713
|
+
table.reloadServerGroupingPath = (pathId) => serverGroupingManager?.reload(pathId);
|
|
2714
|
+
table.invalidateServerGrouping = () => serverGroupingManager?.invalidate();
|
|
2715
|
+
table.invalidateServerGroupingPath = (pathId) => serverGroupingManager?.invalidate(pathId);
|
|
2716
|
+
table.resetServerGroupingState = () => serverGroupingManager?.reset();
|
|
2717
|
+
table.setServerGroupingExpanded = (updater) => serverGroupingManager?.setExpanded(updater);
|
|
2718
|
+
table.setServerGroupingPagination = (pathId, pagination) => serverGroupingManager?.setPagination(pathId, pagination);
|
|
2719
|
+
table.setServerGroupingSorting = (pathId, sorting) => serverGroupingManager?.setSorting(pathId, sorting);
|
|
2720
|
+
table.setServerGroupingColumnFilters = (pathId, columnFilters) => serverGroupingManager?.setColumnFilters(pathId, columnFilters);
|
|
2721
|
+
table.setServerGroupingGlobalFilter = (pathId, globalFilter) => serverGroupingManager?.setGlobalFilter(pathId, globalFilter);
|
|
2722
|
+
table.getServerGroupingSelectionSummary = () => serverGroupingManager ? getServerGroupingSelectionSummary(table) : {
|
|
2723
|
+
excludedRowIds: [],
|
|
2724
|
+
isAll: false,
|
|
2725
|
+
isSelectAllMatching: false,
|
|
2726
|
+
isSome: false,
|
|
2727
|
+
mode: "include",
|
|
2728
|
+
selectableCount: 0,
|
|
2729
|
+
selectedCount: 0,
|
|
2730
|
+
selectedRowIds: []
|
|
2731
|
+
};
|
|
2732
|
+
table.toggleAllServerGroupingRecordsSelected = (value) => {
|
|
2733
|
+
if (serverGroupingManager) toggleAllServerGroupingRecordsSelected(table, value);
|
|
2734
|
+
};
|
|
2735
|
+
table.selectAllMatchingServerGroupingRecords = async () => {
|
|
2736
|
+
if (serverGroupingManager) await selectAllMatchingServerGroupingRecords(table);
|
|
2737
|
+
};
|
|
2738
|
+
table.getServerGroupingSelectAllState = () => serverGroupingManager?.getSelectAll() ?? {
|
|
2739
|
+
active: false,
|
|
2740
|
+
excludedRowIds: []
|
|
2741
|
+
};
|
|
2742
|
+
table.setServerGroupingSelectAllState = (updater) => serverGroupingManager?.setSelectAll(updater);
|
|
2743
|
+
table.getServerGroupingSelectionPayload = () => getServerGroupingSelectionPayload(table);
|
|
1750
2744
|
table._mvtSlots = mvtSlots;
|
|
1751
2745
|
table.setMVTSlots = (slots) => {
|
|
1752
2746
|
mvtSlots.value = slots;
|
|
@@ -1849,10 +2843,10 @@ var MVT_TablePagination = (0, vue.defineComponent)({
|
|
|
1849
2843
|
const { rowsPerPageOptions = defaultRowsPerPage, showRowsPerPage = true, withEdges = showEdges, ...rest } = paginationProps;
|
|
1850
2844
|
const controls = o.paginationDisplayMode === "pages" ? (0, vue.h)(_mantine_vue_core.Pagination, {
|
|
1851
2845
|
total: numberOfPages,
|
|
1852
|
-
|
|
2846
|
+
modelValue: pageIndex + 1,
|
|
1853
2847
|
withEdges,
|
|
1854
2848
|
...rest,
|
|
1855
|
-
|
|
2849
|
+
"onUpdate:modelValue": (page) => table.setPageIndex(page - 1)
|
|
1856
2850
|
}) : o.paginationDisplayMode === "default" ? [(0, vue.h)(_mantine_vue_core.Text, null, () => `${lastRowIndex === 0 ? 0 : (firstRowIndex + 1).toLocaleString()}-${lastRowIndex.toLocaleString()} ${o.localization.of} ${totalRowCount.toLocaleString()}`), (0, vue.h)(_mantine_vue_core.Group, { gap: 6 }, () => [
|
|
1857
2851
|
withEdges && (0, vue.h)(_mantine_vue_core.ActionIcon, {
|
|
1858
2852
|
"aria-label": o.localization.goToFirstPage,
|
|
@@ -1888,8 +2882,8 @@ var MVT_TablePagination = (0, vue.defineComponent)({
|
|
|
1888
2882
|
"aria-labelledby": "rpp-label",
|
|
1889
2883
|
class: MVT_TablePagination_module_default.pagesize,
|
|
1890
2884
|
data: rowsPerPageOptions,
|
|
1891
|
-
|
|
1892
|
-
|
|
2885
|
+
modelValue: pageSize.toString(),
|
|
2886
|
+
"onUpdate:modelValue": (value) => value && table.setPageSize(+value)
|
|
1893
2887
|
})]), controls]);
|
|
1894
2888
|
};
|
|
1895
2889
|
}
|
|
@@ -1929,26 +2923,50 @@ var MVT_ToolbarAlertBanner = (0, vue.defineComponent)({
|
|
|
1929
2923
|
const badgeProps = parseFromValuesOrFunc(o.mantineToolbarAlertBannerBadgeProps, { table });
|
|
1930
2924
|
const total = o.rowCount ?? table.getPrePaginationRowModel().flatRows.length;
|
|
1931
2925
|
const selectedCount = o.manualPagination ? Object.values(state.rowSelection).filter(Boolean).length : table.getFilteredSelectedRowModel().rows.length;
|
|
1932
|
-
const
|
|
2926
|
+
const serverGroupingSelection = o.serverGrouping?.selection;
|
|
2927
|
+
const serverGroupingSummary = table._serverGrouping ? table.getServerGroupingSelectionSummary() : void 0;
|
|
2928
|
+
const showSelectAllMatching = !!serverGroupingSelection?.enableSelectAllMatching && ((serverGroupingSelection.selectAllMode ?? "query") === "query" || !!serverGroupingSelection.loadAllMatchingRowIds) && !!serverGroupingSummary?.isAll && !serverGroupingSummary.isSelectAllMatching;
|
|
2929
|
+
const serverGroupingListsRecords = !serverGroupingSummary || table.getServerGroupingPathState("__root__")?.kind === "records";
|
|
2930
|
+
const selectedText = serverGroupingSummary?.isSelectAllMatching ? (o.localization.allMatchingRecordsSelected ?? "All records matching the current filters are selected") + (serverGroupingSummary.excludedRowIds.length ? ` (${serverGroupingSummary.excludedRowIds.length} excluded)` : "") : serverGroupingListsRecords ? o.localization.selectedCountOfRowCountRowsSelected.replace("{selectedCount}", String(selectedCount)).replace("{rowCount}", String(total)) : (o.localization.selectedCountRowsSelected ?? "{selectedCount} row(s) selected").replace("{selectedCount}", String(selectedCount));
|
|
2931
|
+
const selectedAlert = selectedCount || serverGroupingSummary?.isSelectAllMatching ? (0, vue.h)(_mantine_vue_core.Flex, {
|
|
1933
2932
|
align: "center",
|
|
1934
2933
|
gap: "sm"
|
|
1935
|
-
}, () => [
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
}, () => o.localization.clearSelection)]) : null;
|
|
1940
|
-
const groupedAlert = state.grouping.length ? (0, vue.h)(_mantine_vue_core.Flex, null, () => [`${o.localization.groupedBy} `, ...state.grouping.flatMap((columnId, index) => [index > 0 ? o.localization.thenBy : null, (0, vue.h)(_mantine_vue_core.Badge, {
|
|
1941
|
-
key: columnId,
|
|
1942
|
-
class: MVT_ToolbarAlertBanner_module_default["alert-badge"],
|
|
1943
|
-
variant: "filled",
|
|
1944
|
-
...badgeProps,
|
|
1945
|
-
rightSection: (0, vue.h)(_mantine_vue_core.ActionIcon, {
|
|
1946
|
-
color: "white",
|
|
1947
|
-
size: "xs",
|
|
2934
|
+
}, () => [
|
|
2935
|
+
selectedText,
|
|
2936
|
+
showSelectAllMatching && (0, vue.h)(_mantine_vue_core.Button, {
|
|
2937
|
+
size: "compact-xs",
|
|
1948
2938
|
variant: "subtle",
|
|
1949
|
-
onClick: () => table.
|
|
1950
|
-
}, () =>
|
|
1951
|
-
|
|
2939
|
+
onClick: () => void table.selectAllMatchingServerGroupingRecords()
|
|
2940
|
+
}, () => o.localization.selectAllMatching ?? "Select all matching records"),
|
|
2941
|
+
(0, vue.h)(_mantine_vue_core.Button, {
|
|
2942
|
+
size: "compact-xs",
|
|
2943
|
+
variant: "subtle",
|
|
2944
|
+
onClick: (event) => {
|
|
2945
|
+
if (serverGroupingSummary) {
|
|
2946
|
+
table.toggleAllServerGroupingRecordsSelected(false);
|
|
2947
|
+
return;
|
|
2948
|
+
}
|
|
2949
|
+
getMVT_SelectAllHandler({ table })(event, false, true);
|
|
2950
|
+
}
|
|
2951
|
+
}, () => o.localization.clearSelection)
|
|
2952
|
+
]) : null;
|
|
2953
|
+
const groupedAlert = state.grouping.length ? (0, vue.h)(_mantine_vue_core.Flex, null, () => [`${o.localization.groupedBy} `, ...state.grouping.flatMap((columnId, index) => {
|
|
2954
|
+
const column = table.getAllLeafColumns().find((col) => col.id === columnId);
|
|
2955
|
+
const header = column?.columnDef.header;
|
|
2956
|
+
const label = typeof header === "string" && header.length ? header : columnId;
|
|
2957
|
+
return [index > 0 ? o.localization.thenBy : null, (0, vue.h)(_mantine_vue_core.Badge, {
|
|
2958
|
+
key: columnId,
|
|
2959
|
+
class: MVT_ToolbarAlertBanner_module_default["alert-badge"],
|
|
2960
|
+
variant: "filled",
|
|
2961
|
+
...badgeProps,
|
|
2962
|
+
rightSection: (0, vue.h)(_mantine_vue_core.ActionIcon, {
|
|
2963
|
+
color: "white",
|
|
2964
|
+
size: "xs",
|
|
2965
|
+
variant: "subtle",
|
|
2966
|
+
onClick: () => column ? column.toggleGrouping() : table.setGrouping((prev) => prev.filter((field) => field !== columnId))
|
|
2967
|
+
}, () => (0, vue.h)(o.icons.IconX, { style: { transform: "scale(0.8)" } }))
|
|
2968
|
+
}, () => `${label} `)];
|
|
2969
|
+
})]) : null;
|
|
1952
2970
|
const custom = slots.default?.({
|
|
1953
2971
|
groupedAlert,
|
|
1954
2972
|
selectedAlert,
|
|
@@ -2070,6 +3088,207 @@ var MVT_BottomToolbar = (0, vue.defineComponent)({
|
|
|
2070
3088
|
};
|
|
2071
3089
|
}
|
|
2072
3090
|
});
|
|
3091
|
+
var MVT_ServerGrouping_module_default = {
|
|
3092
|
+
"group-row": "_group-row_u9zpp_1",
|
|
3093
|
+
"row-grid": "_row-grid_u9zpp_7",
|
|
3094
|
+
"group-cell": "_group-cell_u9zpp_11",
|
|
3095
|
+
"aggregate-cell": "_aggregate-cell_u9zpp_15",
|
|
3096
|
+
"expand-spacer": "_expand-spacer_u9zpp_19",
|
|
3097
|
+
"aux-row": "_aux-row_u9zpp_24",
|
|
3098
|
+
"aux-cell": "_aux-cell_u9zpp_28",
|
|
3099
|
+
pagination: "_pagination_u9zpp_32",
|
|
3100
|
+
pagesize: "_pagesize_u9zpp_36",
|
|
3101
|
+
"groupby-control": "_groupby-control_u9zpp_40",
|
|
3102
|
+
"groupby-active-row": "_groupby-active-row_u9zpp_45",
|
|
3103
|
+
"groupby-active-label": "_groupby-active-label_u9zpp_52"
|
|
3104
|
+
};
|
|
3105
|
+
//#endregion
|
|
3106
|
+
//#region src/server-grouping/MVT_ServerGroupingGroupBy.ts
|
|
3107
|
+
/**
|
|
3108
|
+
* Resolve the columns/fields offered by the group-by toolbar control.
|
|
3109
|
+
*
|
|
3110
|
+
* With `serverGrouping.groupBy.columns` set, exactly that whitelist is used
|
|
3111
|
+
* (entries may be custom descriptors like `'createdAt:month'`). Otherwise
|
|
3112
|
+
* every leaf `data` column whose `enableGrouping` is not `false` is offered —
|
|
3113
|
+
* display columns and columns with `enableGrouping: false` never appear.
|
|
3114
|
+
*/
|
|
3115
|
+
var getServerGroupableColumns = (table) => {
|
|
3116
|
+
const groupByOptions = table.options.serverGrouping?.groupBy;
|
|
3117
|
+
const getFieldLabel = groupByOptions?.getFieldLabel;
|
|
3118
|
+
const labelFor = (field) => {
|
|
3119
|
+
if (getFieldLabel) return getFieldLabel(field, table);
|
|
3120
|
+
const header = table.getAllLeafColumns().find((leafColumn) => leafColumn.id === field)?.columnDef.header;
|
|
3121
|
+
return typeof header === "string" && header.length ? header : field;
|
|
3122
|
+
};
|
|
3123
|
+
if (groupByOptions?.columns) return groupByOptions.columns.map((field) => ({
|
|
3124
|
+
id: field,
|
|
3125
|
+
label: labelFor(field)
|
|
3126
|
+
}));
|
|
3127
|
+
return table.getAllLeafColumns().filter((column) => column.columnDef.columnDefType === "data" && column.columnDef.enableGrouping !== false).map((column) => ({
|
|
3128
|
+
id: column.id,
|
|
3129
|
+
label: labelFor(column.id)
|
|
3130
|
+
}));
|
|
3131
|
+
};
|
|
3132
|
+
/** Build the scoped context handed to the group-by slot / render callback. */
|
|
3133
|
+
var getServerGroupingGroupByContext = (table, manager) => {
|
|
3134
|
+
const grouping = manager.getGroupingFields();
|
|
3135
|
+
const setGrouping = (next) => table.setGrouping(next);
|
|
3136
|
+
return {
|
|
3137
|
+
addGroup: (field) => {
|
|
3138
|
+
if (!grouping.includes(field)) setGrouping([...grouping, field]);
|
|
3139
|
+
},
|
|
3140
|
+
clearGrouping: () => setGrouping([]),
|
|
3141
|
+
groupableColumns: getServerGroupableColumns(table),
|
|
3142
|
+
grouping,
|
|
3143
|
+
moveGroup: (field, direction) => {
|
|
3144
|
+
const index = grouping.indexOf(field);
|
|
3145
|
+
const target = index + direction;
|
|
3146
|
+
if (index === -1 || target < 0 || target >= grouping.length) return;
|
|
3147
|
+
const next = [...grouping];
|
|
3148
|
+
[next[index], next[target]] = [next[target], next[index]];
|
|
3149
|
+
setGrouping(next);
|
|
3150
|
+
},
|
|
3151
|
+
removeGroup: (field) => setGrouping(grouping.filter((activeField) => activeField !== field)),
|
|
3152
|
+
table
|
|
3153
|
+
};
|
|
3154
|
+
};
|
|
3155
|
+
/**
|
|
3156
|
+
* Grouping actions for one column's action menu, or `undefined` when the
|
|
3157
|
+
* column cannot be grouped by.
|
|
3158
|
+
*
|
|
3159
|
+
* Uses exactly the same rules as the toolbar "Group by" control: server
|
|
3160
|
+
* grouping must be active and driven by the table's `grouping` state, the
|
|
3161
|
+
* control must not be disabled, and the column must be offered by
|
|
3162
|
+
* {@link getServerGroupableColumns}.
|
|
3163
|
+
*/
|
|
3164
|
+
var getServerGroupingColumnActions = (table, columnId) => {
|
|
3165
|
+
const manager = table._serverGrouping;
|
|
3166
|
+
if (!manager) return void 0;
|
|
3167
|
+
const groupByOptions = manager.options.groupBy ?? {};
|
|
3168
|
+
if (groupByOptions.enabled === false || groupByOptions.showInColumnActions === false) return;
|
|
3169
|
+
if (manager.options.grouping && groupByOptions.enabled !== true) return void 0;
|
|
3170
|
+
const context = getServerGroupingGroupByContext(table, manager);
|
|
3171
|
+
return context.groupableColumns.some((column) => column.id === columnId) ? context : void 0;
|
|
3172
|
+
};
|
|
3173
|
+
/**
|
|
3174
|
+
* Built-in group-by toolbar control for server-side grouping. Renders a
|
|
3175
|
+
* "Group by" menu (add / reorder / remove / clear levels) plus the active
|
|
3176
|
+
* levels as removable pills. Hidden when server grouping is inactive, when
|
|
3177
|
+
* `groupBy.enabled` is `false`, or when grouping is a static
|
|
3178
|
+
* `serverGrouping.grouping` array (which the control could not change).
|
|
3179
|
+
*/
|
|
3180
|
+
var MVT_ServerGroupingGroupBy = (0, vue.defineComponent)({
|
|
3181
|
+
name: "MVTServerGroupingGroupBy",
|
|
3182
|
+
inheritAttrs: false,
|
|
3183
|
+
props: { table: {
|
|
3184
|
+
type: Object,
|
|
3185
|
+
required: true
|
|
3186
|
+
} },
|
|
3187
|
+
setup(props) {
|
|
3188
|
+
const mvtSlots = useMVT_Slots();
|
|
3189
|
+
return () => {
|
|
3190
|
+
const table = props.table;
|
|
3191
|
+
const manager = table._serverGrouping;
|
|
3192
|
+
if (!manager) return null;
|
|
3193
|
+
const sgOptions = manager.options;
|
|
3194
|
+
const groupByOptions = sgOptions.groupBy ?? {};
|
|
3195
|
+
if (groupByOptions.enabled === false) return null;
|
|
3196
|
+
if (sgOptions.grouping && groupByOptions.enabled !== true) return null;
|
|
3197
|
+
const localization = table.options.localization;
|
|
3198
|
+
const icons = table.options.icons;
|
|
3199
|
+
const allowReorder = groupByOptions.allowReorder ?? true;
|
|
3200
|
+
const allowClearAll = groupByOptions.allowClearAll ?? true;
|
|
3201
|
+
const context = getServerGroupingGroupByContext(table, manager);
|
|
3202
|
+
const { addGroup, clearGrouping, groupableColumns, grouping, moveGroup, removeGroup } = context;
|
|
3203
|
+
const custom = mvtSlots.serverGroupByControl?.(context) ?? parseFromValuesOrFunc(groupByOptions.renderControl, context);
|
|
3204
|
+
if (custom !== void 0 && custom !== null) return custom;
|
|
3205
|
+
const labelFor = (field) => groupableColumns.find((column) => column.id === field)?.label ?? field;
|
|
3206
|
+
const activeRows = grouping.map((field, index) => (0, vue.h)(_mantine_vue_core.Box, {
|
|
3207
|
+
class: MVT_ServerGrouping_module_default["groupby-active-row"],
|
|
3208
|
+
key: field
|
|
3209
|
+
}, () => [
|
|
3210
|
+
allowReorder && (0, vue.h)(_mantine_vue_core.ActionIcon, {
|
|
3211
|
+
"aria-label": `${localization.moveUp ?? "Move up"} ${labelFor(field)}`,
|
|
3212
|
+
color: "gray",
|
|
3213
|
+
disabled: index === 0,
|
|
3214
|
+
onClick: () => moveGroup(field, -1),
|
|
3215
|
+
size: "xs",
|
|
3216
|
+
variant: "subtle"
|
|
3217
|
+
}, () => (0, vue.h)(icons.IconChevronDown, { style: { transform: "rotate(180deg)" } })),
|
|
3218
|
+
allowReorder && (0, vue.h)(_mantine_vue_core.ActionIcon, {
|
|
3219
|
+
"aria-label": `${localization.moveDown ?? "Move down"} ${labelFor(field)}`,
|
|
3220
|
+
color: "gray",
|
|
3221
|
+
disabled: index === grouping.length - 1,
|
|
3222
|
+
onClick: () => moveGroup(field, 1),
|
|
3223
|
+
size: "xs",
|
|
3224
|
+
variant: "subtle"
|
|
3225
|
+
}, () => (0, vue.h)(icons.IconChevronDown)),
|
|
3226
|
+
(0, vue.h)(_mantine_vue_core.Text, {
|
|
3227
|
+
class: MVT_ServerGrouping_module_default["groupby-active-label"],
|
|
3228
|
+
size: "sm"
|
|
3229
|
+
}, () => `${index + 1}. ${labelFor(field)}`),
|
|
3230
|
+
(0, vue.h)(_mantine_vue_core.ActionIcon, {
|
|
3231
|
+
"aria-label": (localization.ungroupByColumn ?? "Ungroup by {column}").replace("{column}", labelFor(field)),
|
|
3232
|
+
color: "gray",
|
|
3233
|
+
onClick: () => removeGroup(field),
|
|
3234
|
+
size: "xs",
|
|
3235
|
+
variant: "subtle"
|
|
3236
|
+
}, () => (0, vue.h)(icons.IconX))
|
|
3237
|
+
]));
|
|
3238
|
+
const menu = (0, vue.h)(_mantine_vue_core.Menu, {
|
|
3239
|
+
closeOnItemClick: false,
|
|
3240
|
+
position: "bottom-start",
|
|
3241
|
+
shadow: "md",
|
|
3242
|
+
width: 260,
|
|
3243
|
+
...groupByOptions.mantineMenuProps
|
|
3244
|
+
}, () => [(0, vue.h)(_mantine_vue_core.Menu.Target, null, () => (0, vue.h)(_mantine_vue_core.Button, {
|
|
3245
|
+
size: "xs",
|
|
3246
|
+
variant: "default",
|
|
3247
|
+
...groupByOptions.mantineButtonProps,
|
|
3248
|
+
leftSection: groupByOptions.mantineButtonProps?.leftSection ?? (0, vue.h)(icons.IconColumns)
|
|
3249
|
+
}, () => localization.groupBy ?? "Group by")), (0, vue.h)(_mantine_vue_core.Menu.Dropdown, null, () => [
|
|
3250
|
+
groupableColumns.length ? groupableColumns.map((column) => (0, vue.h)(_mantine_vue_core.Menu.Item, {
|
|
3251
|
+
disabled: grouping.includes(column.id),
|
|
3252
|
+
key: column.id,
|
|
3253
|
+
onClick: () => addGroup(column.id)
|
|
3254
|
+
}, () => column.label)) : (0, vue.h)(_mantine_vue_core.Menu.Label, null, () => localization.noGroupableColumns ?? "No groupable columns"),
|
|
3255
|
+
grouping.length > 0 && [
|
|
3256
|
+
(0, vue.h)(_mantine_vue_core.Menu.Divider),
|
|
3257
|
+
(0, vue.h)(_mantine_vue_core.Menu.Label, null, () => (localization.groupedBy ?? "Grouped by ").trim()),
|
|
3258
|
+
...activeRows
|
|
3259
|
+
],
|
|
3260
|
+
allowClearAll && grouping.length > 0 && [(0, vue.h)(_mantine_vue_core.Menu.Divider), (0, vue.h)(_mantine_vue_core.Menu.Item, {
|
|
3261
|
+
color: "red",
|
|
3262
|
+
onClick: () => clearGrouping()
|
|
3263
|
+
}, () => localization.clearGrouping ?? "Clear grouping")]
|
|
3264
|
+
])]);
|
|
3265
|
+
const pills = grouping.length > 0 && (0, vue.h)(_mantine_vue_core.PillGroup, { gap: 4 }, () => grouping.map((field, index) => {
|
|
3266
|
+
const pillProps = parseFromValuesOrFunc(groupByOptions.mantinePillProps, {
|
|
3267
|
+
field,
|
|
3268
|
+
index
|
|
3269
|
+
}) ?? {};
|
|
3270
|
+
return (0, vue.h)(_mantine_vue_core.Pill, {
|
|
3271
|
+
size: "sm",
|
|
3272
|
+
withRemoveButton: true,
|
|
3273
|
+
...pillProps,
|
|
3274
|
+
key: field,
|
|
3275
|
+
onRemove: () => removeGroup(field),
|
|
3276
|
+
removeButtonProps: {
|
|
3277
|
+
"aria-label": (localization.ungroupByColumn ?? "Ungroup by {column}").replace("{column}", labelFor(field)),
|
|
3278
|
+
...pillProps?.removeButtonProps
|
|
3279
|
+
}
|
|
3280
|
+
}, () => `${index + 1}. ${labelFor(field)}`);
|
|
3281
|
+
}));
|
|
3282
|
+
return (0, vue.h)(_mantine_vue_core.Box, {
|
|
3283
|
+
class: (0, clsx.default)("mvt-server-groupby-control", MVT_ServerGrouping_module_default["groupby-control"]),
|
|
3284
|
+
style: {
|
|
3285
|
+
display: "flex",
|
|
3286
|
+
gap: "8px"
|
|
3287
|
+
}
|
|
3288
|
+
}, () => [menu, pills]);
|
|
3289
|
+
};
|
|
3290
|
+
}
|
|
3291
|
+
});
|
|
2073
3292
|
var MVT_FilterOptionMenu_module_default = { symbol: "_symbol_1b3vj_1" };
|
|
2074
3293
|
//#endregion
|
|
2075
3294
|
//#region src/components/menus/MVT_FilterOptionMenu.ts
|
|
@@ -2458,7 +3677,7 @@ var MVT_ShowHideColumnsMenuItems = (0, vue.defineComponent)({
|
|
|
2458
3677
|
openDelay: 1e3,
|
|
2459
3678
|
withinPortal: true
|
|
2460
3679
|
}, () => (0, vue.h)(_mantine_vue_core.Switch, {
|
|
2461
|
-
checked,
|
|
3680
|
+
modelValue: checked,
|
|
2462
3681
|
class: MVT_ShowHideColumnsMenuItems_module_default.switch,
|
|
2463
3682
|
disabled: !column.getCanHide(),
|
|
2464
3683
|
label: def.header,
|
|
@@ -2777,6 +3996,7 @@ var MVT_TopToolbar = (0, vue.defineComponent)({
|
|
|
2777
3996
|
["both", "top"].includes(positionToolbarDropZone ?? "") && (0, vue.h)(MVT_ToolbarDropZone, { table }),
|
|
2778
3997
|
(0, vue.h)(_mantine_vue_core.Flex, { class: [MVT_TopToolbar_module_default["actions-container"], stackAlertBanner ? MVT_TopToolbar_module_default["actions-container-stack-alert"] : void 0] }, () => [
|
|
2779
3998
|
enableGlobalFilter && positionGlobalFilter === "left" && (0, vue.h)(MVT_GlobalFilterTextInput, globalFilterProps),
|
|
3999
|
+
table._serverGrouping && (0, vue.h)(MVT_ServerGroupingGroupBy, { table }),
|
|
2780
4000
|
parseFromValuesOrFunc(renderTopToolbarCustomActions, { table }) ?? (0, vue.h)("span"),
|
|
2781
4001
|
enableToolbarInternalActions ? (0, vue.h)(_mantine_vue_core.Flex, {
|
|
2782
4002
|
justify: "end",
|
|
@@ -2953,6 +4173,21 @@ var useMVT_ColumnVirtualizer = (table) => {
|
|
|
2953
4173
|
//#endregion
|
|
2954
4174
|
//#region src/utils/style.utils.ts
|
|
2955
4175
|
var parseCSSVarId = (id) => id.replace(/[^a-zA-Z0-9]/g, "_");
|
|
4176
|
+
/**
|
|
4177
|
+
* Width/flex styles that bind a cell to its column's live size variables, so
|
|
4178
|
+
* custom cells (server-grouping group rows, …) stay aligned with the root
|
|
4179
|
+
* table while columns are resized or reordered.
|
|
4180
|
+
*/
|
|
4181
|
+
var getMVT_ColumnWidthStyles = ({ columnId, grow, layoutMode, minSize }) => {
|
|
4182
|
+
const cssVar = `--col-${parseCSSVarId(columnId)}-size`;
|
|
4183
|
+
const styles = {
|
|
4184
|
+
minWidth: `max(calc(var(${cssVar}) * 1px), ${minSize ?? 30}px)`,
|
|
4185
|
+
width: `calc(var(${cssVar}) * 1px)`
|
|
4186
|
+
};
|
|
4187
|
+
if (layoutMode === "grid") styles.flex = `${[0, false].includes(grow) ? 0 : `var(${cssVar})`} 0 auto`;
|
|
4188
|
+
else if (layoutMode === "grid-no-grow") styles.flex = `${+(grow || 0)} 0 auto`;
|
|
4189
|
+
return styles;
|
|
4190
|
+
};
|
|
2956
4191
|
var getPrimaryShade = (theme) => typeof theme.primaryShade === "number" ? theme.primaryShade : theme.primaryShade?.dark ?? 7;
|
|
2957
4192
|
var getPrimaryColor = (theme, shade) => theme.colors[theme.primaryColor][shade ?? getPrimaryShade(theme)];
|
|
2958
4193
|
function dataVariable(name, value) {
|
|
@@ -3280,8 +4515,9 @@ var MVT_TableBodyCell = (0, vue.defineComponent)({
|
|
|
3280
4515
|
if (!columnDef.enableCellHoverReveal) return;
|
|
3281
4516
|
isCellContentOverflowing.value = false;
|
|
3282
4517
|
};
|
|
4518
|
+
const isServerGrouping = !!table._serverGrouping;
|
|
3283
4519
|
const renderCellContent = () => {
|
|
3284
|
-
if (cell.getIsPlaceholder()) return columnDef.PlaceholderCell?.({
|
|
4520
|
+
if (!isServerGrouping && cell.getIsPlaceholder()) return columnDef.PlaceholderCell?.({
|
|
3285
4521
|
cell,
|
|
3286
4522
|
column,
|
|
3287
4523
|
row,
|
|
@@ -3607,6 +4843,271 @@ var MVT_TableBodyRow = (0, vue.defineComponent)({
|
|
|
3607
4843
|
}
|
|
3608
4844
|
});
|
|
3609
4845
|
var Memo_MVT_TableBodyRow = MVT_TableBodyRow;
|
|
4846
|
+
//#endregion
|
|
4847
|
+
//#region src/server-grouping/MVT_ServerGroupingBody.ts
|
|
4848
|
+
var INDENT_PX = 24;
|
|
4849
|
+
/** Renders the server-grouping hierarchy as rows of the root table body. */
|
|
4850
|
+
var MVT_ServerGroupingBody = (0, vue.defineComponent)({
|
|
4851
|
+
name: "MVTServerGroupingBody",
|
|
4852
|
+
inheritAttrs: false,
|
|
4853
|
+
props: {
|
|
4854
|
+
table: {
|
|
4855
|
+
type: Object,
|
|
4856
|
+
required: true
|
|
4857
|
+
},
|
|
4858
|
+
tableProps: {
|
|
4859
|
+
type: Object,
|
|
4860
|
+
required: true
|
|
4861
|
+
}
|
|
4862
|
+
},
|
|
4863
|
+
setup(props) {
|
|
4864
|
+
const mvtSlots = useMVT_Slots();
|
|
4865
|
+
return () => {
|
|
4866
|
+
const { tableProps } = props;
|
|
4867
|
+
const table = props.table;
|
|
4868
|
+
const manager = table._serverGrouping;
|
|
4869
|
+
if (!manager) return null;
|
|
4870
|
+
const { options: sgOptions } = manager;
|
|
4871
|
+
const tableOptions = table.options;
|
|
4872
|
+
const localization = tableOptions.localization;
|
|
4873
|
+
const icons = tableOptions.icons;
|
|
4874
|
+
const visibleColumns = table.getVisibleLeafColumns();
|
|
4875
|
+
const colSpan = visibleColumns.length || 1;
|
|
4876
|
+
const layoutMode = tableOptions.layoutMode;
|
|
4877
|
+
const paginationOptions = {
|
|
4878
|
+
enabled: sgOptions.pagination?.enabled ?? true,
|
|
4879
|
+
mantineActionIconProps: sgOptions.pagination?.mantineActionIconProps ?? {},
|
|
4880
|
+
showAtRoot: sgOptions.pagination?.showAtRoot ?? (tableOptions.enablePagination === false || tableOptions.positionPagination === "none"),
|
|
4881
|
+
showForGroups: sgOptions.pagination?.showForGroups ?? true,
|
|
4882
|
+
showForRecords: sgOptions.pagination?.showForRecords ?? true
|
|
4883
|
+
};
|
|
4884
|
+
const indentStyle = (depth) => ({ paddingInlineStart: `${8 + depth * INDENT_PX}px` });
|
|
4885
|
+
const columnStyle = (column, extra) => ({
|
|
4886
|
+
...getMVT_ColumnWidthStyles({
|
|
4887
|
+
columnId: column.id,
|
|
4888
|
+
grow: column.columnDef.grow,
|
|
4889
|
+
layoutMode,
|
|
4890
|
+
minSize: column.columnDef.minSize
|
|
4891
|
+
}),
|
|
4892
|
+
...extra
|
|
4893
|
+
});
|
|
4894
|
+
const auxRow = (key, depth, children) => (0, vue.h)(_mantine_vue_core.TableTr, {
|
|
4895
|
+
class: (0, clsx.default)(MVT_ServerGrouping_module_default["aux-row"], layoutMode?.startsWith("grid") && MVT_ServerGrouping_module_default["row-grid"]),
|
|
4896
|
+
key
|
|
4897
|
+
}, () => (0, vue.h)(_mantine_vue_core.TableTd, {
|
|
4898
|
+
class: MVT_ServerGrouping_module_default["aux-cell"],
|
|
4899
|
+
colspan: colSpan,
|
|
4900
|
+
style: {
|
|
4901
|
+
...indentStyle(depth),
|
|
4902
|
+
...layoutMode?.startsWith("grid") ? {
|
|
4903
|
+
flex: "1 0 auto",
|
|
4904
|
+
width: "100%"
|
|
4905
|
+
} : {}
|
|
4906
|
+
}
|
|
4907
|
+
}, () => children));
|
|
4908
|
+
const loadingContent = (pathId, depth) => mvtSlots.serverGroupLoading?.({
|
|
4909
|
+
depth,
|
|
4910
|
+
pathId,
|
|
4911
|
+
table
|
|
4912
|
+
}) ?? parseFromValuesOrFunc(sgOptions.renderGroupLoading, {
|
|
4913
|
+
depth,
|
|
4914
|
+
pathId,
|
|
4915
|
+
table
|
|
4916
|
+
}) ?? (0, vue.h)(_mantine_vue_core.Group, { gap: "xs" }, () => [(0, vue.h)(_mantine_vue_core.Loader, { size: "xs" }), (0, vue.h)(_mantine_vue_core.Text, {
|
|
4917
|
+
c: "dimmed",
|
|
4918
|
+
size: "sm"
|
|
4919
|
+
}, () => localization.loading ?? "Loading…")]);
|
|
4920
|
+
const errorContent = (pathId, error, retry) => mvtSlots.serverGroupError?.({
|
|
4921
|
+
error,
|
|
4922
|
+
pathId,
|
|
4923
|
+
retry,
|
|
4924
|
+
table
|
|
4925
|
+
}) ?? parseFromValuesOrFunc(sgOptions.renderGroupError, {
|
|
4926
|
+
error,
|
|
4927
|
+
pathId,
|
|
4928
|
+
retry,
|
|
4929
|
+
table
|
|
4930
|
+
}) ?? (0, vue.h)(_mantine_vue_core.Alert, {
|
|
4931
|
+
color: "red",
|
|
4932
|
+
role: "alert",
|
|
4933
|
+
variant: "light"
|
|
4934
|
+
}, () => (0, vue.h)(_mantine_vue_core.Group, { gap: "sm" }, () => [(0, vue.h)(_mantine_vue_core.Text, { size: "sm" }, () => localization.errorLoadingData ?? (error instanceof Error && error.message) ?? "Error loading data"), (0, vue.h)(_mantine_vue_core.Button, {
|
|
4935
|
+
color: "red",
|
|
4936
|
+
onClick: retry,
|
|
4937
|
+
size: "compact-xs",
|
|
4938
|
+
variant: "outline"
|
|
4939
|
+
}, () => localization.retry ?? "Retry")]));
|
|
4940
|
+
const emptyContent = (pathId, field) => {
|
|
4941
|
+
const parentGroup = manager.getParentItems(pathId).at(-1);
|
|
4942
|
+
return mvtSlots.serverGroupEmpty?.({
|
|
4943
|
+
field,
|
|
4944
|
+
parentGroup,
|
|
4945
|
+
pathId,
|
|
4946
|
+
table
|
|
4947
|
+
}) ?? parseFromValuesOrFunc(sgOptions.renderGroupEmpty, {
|
|
4948
|
+
field,
|
|
4949
|
+
parentGroup,
|
|
4950
|
+
pathId,
|
|
4951
|
+
table
|
|
4952
|
+
}) ?? (0, vue.h)(_mantine_vue_core.Text, {
|
|
4953
|
+
c: "dimmed",
|
|
4954
|
+
size: "sm"
|
|
4955
|
+
}, () => localization.noRecordsToDisplay ?? "No records to display");
|
|
4956
|
+
};
|
|
4957
|
+
const paginationRow = (pathId, depth, state) => {
|
|
4958
|
+
const isRoot = pathId === MVT_SERVER_GROUPING_ROOT_PATH_ID;
|
|
4959
|
+
const { pageIndex, pageSize } = state.pagination;
|
|
4960
|
+
const totalRowCount = state.rowCount;
|
|
4961
|
+
if (!(paginationOptions.enabled && (state.kind === "groups" ? paginationOptions.showForGroups : paginationOptions.showForRecords) && (!isRoot || paginationOptions.showAtRoot) && (totalRowCount > pageSize || pageIndex > 0))) return null;
|
|
4962
|
+
const firstRowIndex = pageIndex * pageSize;
|
|
4963
|
+
const lastRowIndex = Math.min(firstRowIndex + pageSize, totalRowCount);
|
|
4964
|
+
const setPageIndex = (nextPageIndex) => manager.setPagination(pathId, { pageIndex: nextPageIndex });
|
|
4965
|
+
return auxRow(`${pathId}:pagination`, depth, (0, vue.h)(_mantine_vue_core.Group, {
|
|
4966
|
+
class: MVT_ServerGrouping_module_default.pagination,
|
|
4967
|
+
gap: "xs",
|
|
4968
|
+
wrap: "nowrap"
|
|
4969
|
+
}, () => [
|
|
4970
|
+
(0, vue.h)(_mantine_vue_core.Text, {
|
|
4971
|
+
c: "dimmed",
|
|
4972
|
+
size: "sm"
|
|
4973
|
+
}, () => `${totalRowCount === 0 ? 0 : (firstRowIndex + 1).toLocaleString()}-${lastRowIndex.toLocaleString()} ${localization.of} ${totalRowCount.toLocaleString()}`),
|
|
4974
|
+
(0, vue.h)(_mantine_vue_core.ActionIcon, {
|
|
4975
|
+
color: "gray",
|
|
4976
|
+
size: "sm",
|
|
4977
|
+
variant: "subtle",
|
|
4978
|
+
...paginationOptions.mantineActionIconProps,
|
|
4979
|
+
"aria-label": localization.goToPreviousPage,
|
|
4980
|
+
disabled: pageIndex <= 0 || state.isFetching,
|
|
4981
|
+
onClick: () => setPageIndex(pageIndex - 1)
|
|
4982
|
+
}, () => (0, vue.h)(icons.IconChevronLeft)),
|
|
4983
|
+
(0, vue.h)(_mantine_vue_core.ActionIcon, {
|
|
4984
|
+
color: "gray",
|
|
4985
|
+
size: "sm",
|
|
4986
|
+
variant: "subtle",
|
|
4987
|
+
...paginationOptions.mantineActionIconProps,
|
|
4988
|
+
"aria-label": localization.goToNextPage,
|
|
4989
|
+
disabled: lastRowIndex >= totalRowCount || state.isFetching,
|
|
4990
|
+
onClick: () => setPageIndex(pageIndex + 1)
|
|
4991
|
+
}, () => (0, vue.h)(icons.IconChevronRight))
|
|
4992
|
+
]));
|
|
4993
|
+
};
|
|
4994
|
+
const groupRow = (node, parentPathId, field, depth) => {
|
|
4995
|
+
const pathId = createServerGroupPathId(parentPathId, field, node.id);
|
|
4996
|
+
const expanded = manager.isExpanded(pathId);
|
|
4997
|
+
const childState = manager.getPathState(pathId);
|
|
4998
|
+
const context = {
|
|
4999
|
+
depth,
|
|
5000
|
+
field,
|
|
5001
|
+
group: node,
|
|
5002
|
+
isExpanded: expanded,
|
|
5003
|
+
parentGroups: manager.getParentItems(pathId).slice(0, -1),
|
|
5004
|
+
pathId,
|
|
5005
|
+
table
|
|
5006
|
+
};
|
|
5007
|
+
const hasChildren = node.hasChildren !== false;
|
|
5008
|
+
const rowProps = parseFromValuesOrFunc(sgOptions.mantineGroupRowProps, context) ?? {};
|
|
5009
|
+
const label = mvtSlots.serverGroupLabel?.(context) ?? parseFromValuesOrFunc(sgOptions.renderGroupLabel, context) ?? node.label;
|
|
5010
|
+
const count = mvtSlots.serverGroupCount?.(context) ?? parseFromValuesOrFunc(sgOptions.renderGroupCount, context) ?? (node.count !== void 0 ? `(${node.count.toLocaleString()})` : null);
|
|
5011
|
+
const labelColumn = visibleColumns.find((column) => column.columnDef.columnDefType !== "display");
|
|
5012
|
+
const labelCell = (column) => (0, vue.h)(_mantine_vue_core.TableTd, {
|
|
5013
|
+
class: MVT_ServerGrouping_module_default["group-cell"],
|
|
5014
|
+
key: column?.id ?? "mvt-server-group-label",
|
|
5015
|
+
style: column ? columnStyle(column, indentStyle(depth)) : indentStyle(depth)
|
|
5016
|
+
}, () => (0, vue.h)(_mantine_vue_core.Group, {
|
|
5017
|
+
gap: "xs",
|
|
5018
|
+
wrap: "nowrap"
|
|
5019
|
+
}, () => [
|
|
5020
|
+
hasChildren ? (0, vue.h)(_mantine_vue_core.ActionIcon, {
|
|
5021
|
+
"aria-expanded": String(expanded),
|
|
5022
|
+
"aria-label": `${expanded ? localization.collapse : localization.expand} ${node.label}`,
|
|
5023
|
+
color: "gray",
|
|
5024
|
+
onClick: () => manager.toggle(pathId),
|
|
5025
|
+
size: "sm",
|
|
5026
|
+
variant: "subtle"
|
|
5027
|
+
}, () => (0, vue.h)(expanded ? icons.IconChevronDown : icons.IconChevronRight)) : (0, vue.h)("span", { class: MVT_ServerGrouping_module_default["expand-spacer"] }),
|
|
5028
|
+
(0, vue.h)(_mantine_vue_core.Text, {
|
|
5029
|
+
fw: 600,
|
|
5030
|
+
size: "sm"
|
|
5031
|
+
}, () => [label]),
|
|
5032
|
+
count !== null && (0, vue.h)(_mantine_vue_core.Text, {
|
|
5033
|
+
c: "dimmed",
|
|
5034
|
+
size: "sm"
|
|
5035
|
+
}, () => [count]),
|
|
5036
|
+
expanded && childState?.isFetching && !childState.isLoading && (0, vue.h)(_mantine_vue_core.Loader, { size: "xs" })
|
|
5037
|
+
]));
|
|
5038
|
+
const aggregateCell = (column) => {
|
|
5039
|
+
const columnServerGrouping = column.columnDef.serverGrouping;
|
|
5040
|
+
let content = null;
|
|
5041
|
+
if (columnServerGrouping?.visible !== false && columnServerGrouping?.getValue) {
|
|
5042
|
+
const value = columnServerGrouping.getValue({
|
|
5043
|
+
...context,
|
|
5044
|
+
column
|
|
5045
|
+
});
|
|
5046
|
+
const cellContext = {
|
|
5047
|
+
...context,
|
|
5048
|
+
column,
|
|
5049
|
+
value
|
|
5050
|
+
};
|
|
5051
|
+
content = mvtSlots.serverGroupCell?.(cellContext) ?? (columnServerGrouping.Cell ? flexRender(columnServerGrouping.Cell, cellContext) : value ?? null);
|
|
5052
|
+
} else if (mvtSlots.serverGroupCell) content = mvtSlots.serverGroupCell({
|
|
5053
|
+
...context,
|
|
5054
|
+
column,
|
|
5055
|
+
value: void 0
|
|
5056
|
+
});
|
|
5057
|
+
return (0, vue.h)(_mantine_vue_core.TableTd, {
|
|
5058
|
+
class: MVT_ServerGrouping_module_default["aggregate-cell"],
|
|
5059
|
+
key: column.id,
|
|
5060
|
+
style: columnStyle(column)
|
|
5061
|
+
}, () => [content]);
|
|
5062
|
+
};
|
|
5063
|
+
const spacerCell = (column) => (0, vue.h)(_mantine_vue_core.TableTd, {
|
|
5064
|
+
key: column.id,
|
|
5065
|
+
style: columnStyle(column)
|
|
5066
|
+
}, () => null);
|
|
5067
|
+
const cells = visibleColumns.length ? visibleColumns.map((column) => column.id === labelColumn?.id ? labelCell(column) : column.columnDef.columnDefType === "display" ? spacerCell(column) : aggregateCell(column)) : [labelCell()];
|
|
5068
|
+
const rows = [(0, vue.h)(_mantine_vue_core.TableTr, {
|
|
5069
|
+
"aria-expanded": hasChildren ? String(expanded) : void 0,
|
|
5070
|
+
"aria-level": depth + 1,
|
|
5071
|
+
"data-depth": depth,
|
|
5072
|
+
"data-expanded": expanded || void 0,
|
|
5073
|
+
key: pathId,
|
|
5074
|
+
...rowProps,
|
|
5075
|
+
class: (0, clsx.default)(MVT_ServerGrouping_module_default["group-row"], layoutMode?.startsWith("grid") && MVT_ServerGrouping_module_default["row-grid"], rowProps?.class)
|
|
5076
|
+
}, () => cells)];
|
|
5077
|
+
if (expanded) rows.push(...levelRows(pathId, depth + 1));
|
|
5078
|
+
return rows;
|
|
5079
|
+
};
|
|
5080
|
+
const recordRows = (pathId) => {
|
|
5081
|
+
const rows = manager.getRecordRows(pathId);
|
|
5082
|
+
return rows.map((row, index) => (0, vue.h)(MVT_TableBodyRow, {
|
|
5083
|
+
key: row.id,
|
|
5084
|
+
numRows: rows.length,
|
|
5085
|
+
renderedRowIndex: index,
|
|
5086
|
+
row,
|
|
5087
|
+
table,
|
|
5088
|
+
tableProps
|
|
5089
|
+
}));
|
|
5090
|
+
};
|
|
5091
|
+
const levelRows = (pathId, depth) => {
|
|
5092
|
+
const state = manager.getPathState(pathId);
|
|
5093
|
+
const field = manager.getGroupingFields()[getServerGroupPathDepth(pathId)];
|
|
5094
|
+
if (!state || state.isLoading) return [auxRow(`${pathId}:loading`, depth, loadingContent(pathId, depth))];
|
|
5095
|
+
if (state.error != null) return [auxRow(`${pathId}:error`, depth, errorContent(pathId, state.error, () => manager.retry(pathId)))];
|
|
5096
|
+
const out = [];
|
|
5097
|
+
if (state.kind === "groups") {
|
|
5098
|
+
const groups = state.groups ?? [];
|
|
5099
|
+
if (!groups.length) out.push(auxRow(`${pathId}:empty`, depth, emptyContent(pathId, field)));
|
|
5100
|
+
else groups.forEach((node) => out.push(...groupRow(node, pathId, field, depth)));
|
|
5101
|
+
} else if (!(state.rows ?? []).length) out.push(auxRow(`${pathId}:empty`, depth, emptyContent(pathId, field)));
|
|
5102
|
+
else out.push(...recordRows(pathId));
|
|
5103
|
+
const pagination = paginationRow(pathId, depth, state);
|
|
5104
|
+
if (pagination) out.push(pagination);
|
|
5105
|
+
return out;
|
|
5106
|
+
};
|
|
5107
|
+
return (0, vue.h)(vue.Fragment, null, levelRows(MVT_SERVER_GROUPING_ROOT_PATH_ID, 0));
|
|
5108
|
+
};
|
|
5109
|
+
}
|
|
5110
|
+
});
|
|
3610
5111
|
var MVT_TableBody_module_default = {
|
|
3611
5112
|
root: "_root_17rwk_1",
|
|
3612
5113
|
"root-grid": "_root-grid_17rwk_6",
|
|
@@ -3736,7 +5237,10 @@ var MVT_TableBody = (0, vue.defineComponent)({
|
|
|
3736
5237
|
...tableBodyProps?.style
|
|
3737
5238
|
},
|
|
3738
5239
|
class: (0, clsx.default)(MVT_TableBody_module_default.root, layoutMode?.startsWith("grid") && MVT_TableBody_module_default["root-grid"], !currentRows.length && MVT_TableBody_module_default["root-no-rows"], rowVirtualizer && MVT_TableBody_module_default["root-virtualized"], tableBodyProps?.class)
|
|
3739
|
-
}, () => tableBodyProps?.children ?? (
|
|
5240
|
+
}, () => tableBodyProps?.children ?? (table._serverGrouping ? (0, vue.h)(MVT_ServerGroupingBody, {
|
|
5241
|
+
table,
|
|
5242
|
+
tableProps
|
|
5243
|
+
}) : null) ?? (!currentRows.length ? (0, vue.h)(MVT_TableBodyEmptyRow, commonRowProps) : (virtualRows ?? currentRows).map((rowOrVirtualRow, renderedRowIndex) => {
|
|
3740
5244
|
let index = renderedRowIndex;
|
|
3741
5245
|
if (rowVirtualizer) if (renderDetailPanel) {
|
|
3742
5246
|
if (rowOrVirtualRow.index % 2 === 1) return null;
|
|
@@ -4004,6 +5508,7 @@ var MVT_ColumnActionMenu = (0, vue.defineComponent)({
|
|
|
4004
5508
|
leftSection: (0, vue.h)(icon, { class: iconClass }),
|
|
4005
5509
|
onClick
|
|
4006
5510
|
}, () => label);
|
|
5511
|
+
const serverGroupBy = getServerGroupingColumnActions(table, column.id);
|
|
4007
5512
|
const internal = [];
|
|
4008
5513
|
if (o.enableSorting && column.getCanSort()) {
|
|
4009
5514
|
if (o.enableSortingRemoval !== false) internal.push(item(l.clearSort, icons.IconClearAll, () => column.clearSorting(), !column.getIsSorted()));
|
|
@@ -4025,6 +5530,11 @@ var MVT_ColumnActionMenu = (0, vue.defineComponent)({
|
|
|
4025
5530
|
table.setColumnOrder((old) => ["mvt-row-expand", ...old]);
|
|
4026
5531
|
}));
|
|
4027
5532
|
if (o.enableColumnPinning) internal.push((0, vue.h)(_mantine_vue_core.Menu.Divider));
|
|
5533
|
+
} else if (serverGroupBy) {
|
|
5534
|
+
const { addGroup, grouping, removeGroup } = serverGroupBy;
|
|
5535
|
+
const isGrouped = grouping.includes(column.id);
|
|
5536
|
+
internal.push(isGrouped ? item(l.clearGrouping ?? "Clear grouping", icons.IconClearAll, () => removeGroup(column.id)) : item(l.groupByColumn.replace("{column}", String(def.header)), icons.IconBoxMultiple, () => addGroup(column.id)));
|
|
5537
|
+
if (o.enableColumnPinning) internal.push((0, vue.h)(_mantine_vue_core.Menu.Divider));
|
|
4028
5538
|
}
|
|
4029
5539
|
if (o.enableColumnPinning && column.getCanPin()) {
|
|
4030
5540
|
internal.push(item(l.pinToLeft, icons.IconPinned, () => column.pin("left"), column.getIsPinned() === "left", MVT_ColumnActionMenu_module_default.left));
|
|
@@ -4055,7 +5565,7 @@ var MVT_ColumnActionMenu = (0, vue.defineComponent)({
|
|
|
4055
5565
|
withinPortal: true,
|
|
4056
5566
|
...attrs,
|
|
4057
5567
|
opened: props.opened,
|
|
4058
|
-
|
|
5568
|
+
"onUpdate:opened": props.onChange
|
|
4059
5569
|
}, () => [(0, vue.h)(_mantine_vue_core.Tooltip, {
|
|
4060
5570
|
label: actionProps.title ?? l.columnActions,
|
|
4061
5571
|
openDelay: 1e3,
|
|
@@ -4112,9 +5622,9 @@ var MVT_FilterCheckbox = (0, vue.defineComponent)({
|
|
|
4112
5622
|
size: table.getState().density === "xs" ? "sm" : "md",
|
|
4113
5623
|
...checkboxProps,
|
|
4114
5624
|
title: void 0,
|
|
4115
|
-
onChange: (
|
|
5625
|
+
onChange: (checked) => {
|
|
4116
5626
|
column.setFilterValue(value === void 0 ? "true" : value === "true" ? "false" : void 0);
|
|
4117
|
-
checkboxProps.onChange?.(
|
|
5627
|
+
checkboxProps.onChange?.(checked);
|
|
4118
5628
|
},
|
|
4119
5629
|
onClick: (e) => {
|
|
4120
5630
|
e.stopPropagation();
|
|
@@ -4427,7 +5937,7 @@ var MVT_FilterRangeSlider = (0, vue.defineComponent)({
|
|
|
4427
5937
|
class: (0, clsx.default)("mvt-filter-range-slider", MVT_FilterRangeSlider_module_default.root, rangeProps.class),
|
|
4428
5938
|
min,
|
|
4429
5939
|
max,
|
|
4430
|
-
|
|
5940
|
+
modelValue: values.value,
|
|
4431
5941
|
...rangeProps,
|
|
4432
5942
|
onChange: (value) => {
|
|
4433
5943
|
values.value = value;
|
|
@@ -5249,6 +6759,44 @@ var MantineVueTable = (0, vue.defineComponent)({
|
|
|
5249
6759
|
}
|
|
5250
6760
|
});
|
|
5251
6761
|
//#endregion
|
|
6762
|
+
//#region src/server-grouping/createServerGroupingProvider.ts
|
|
6763
|
+
var asString = (value) => value === null || value === void 0 ? "" : String(value);
|
|
6764
|
+
/**
|
|
6765
|
+
* Build a {@link MVT_ServerGroupingProvider} with sensible defaults for common
|
|
6766
|
+
* response formats:
|
|
6767
|
+
*
|
|
6768
|
+
* - `groups`/`records` default to the response itself when it is an array.
|
|
6769
|
+
* - `groupRowCount`/`recordRowCount` default to the mapped array length.
|
|
6770
|
+
* - `groupId`/`groupLabel` default to stringifying `groupValue` (or the group
|
|
6771
|
+
* itself when it is a primitive).
|
|
6772
|
+
* - `groupValue` defaults to the group object itself.
|
|
6773
|
+
* - `groupMeta` defaults to `{}`; `groupCount` and aggregates stay optional.
|
|
6774
|
+
* - `hasChildren` defaults to `true` (every level up to and including the last
|
|
6775
|
+
* grouping level is expandable).
|
|
6776
|
+
* - `rowId` falls back to the table's existing `getRowId` logic.
|
|
6777
|
+
*/
|
|
6778
|
+
var createServerGroupingProvider = (options) => {
|
|
6779
|
+
const getGroups = options.getGroups ?? options.groups ?? ((response) => Array.isArray(response) ? response : []);
|
|
6780
|
+
const getRecords = options.getRecords ?? options.records ?? ((response) => Array.isArray(response) ? response : []);
|
|
6781
|
+
const getGroupValue = options.getGroupValue ?? options.groupValue ?? ((group) => group);
|
|
6782
|
+
return {
|
|
6783
|
+
getGroupId: options.getGroupId ?? options.groupId ?? ((group, context) => asString(getGroupValue(group, context))),
|
|
6784
|
+
getGroupLabel: options.getGroupLabel ?? options.groupLabel ?? ((group, context) => asString(getGroupValue(group, context))),
|
|
6785
|
+
getGroupValue,
|
|
6786
|
+
getGroupCount: options.getGroupCount ?? options.groupCount,
|
|
6787
|
+
getGroupMeta: options.getGroupMeta ?? options.groupMeta ?? (() => ({})),
|
|
6788
|
+
hasGroupChildren: options.hasGroupChildren ?? options.hasChildren,
|
|
6789
|
+
loadGroups: options.loadGroups,
|
|
6790
|
+
getGroups,
|
|
6791
|
+
getGroupRowCount: options.getGroupRowCount ?? options.groupRowCount ?? ((response) => getGroups(response).length),
|
|
6792
|
+
loadRecords: options.loadRecords,
|
|
6793
|
+
getRecords,
|
|
6794
|
+
getRecordRowCount: options.getRecordRowCount ?? options.recordRowCount ?? ((response) => getRecords(response).length),
|
|
6795
|
+
getRowId: options.getRowId ?? options.rowId,
|
|
6796
|
+
getCacheKey: options.getCacheKey ?? options.cacheKey
|
|
6797
|
+
};
|
|
6798
|
+
};
|
|
6799
|
+
//#endregion
|
|
5252
6800
|
exports.MVT_AggregationFns = MVT_AggregationFns;
|
|
5253
6801
|
exports.MVT_BottomToolbar = MVT_BottomToolbar;
|
|
5254
6802
|
exports.MVT_ColumnActionMenu = MVT_ColumnActionMenu;
|
|
@@ -5273,7 +6821,10 @@ exports.MVT_GrabHandleButton = MVT_GrabHandleButton;
|
|
|
5273
6821
|
exports.MVT_ProgressBar = MVT_ProgressBar;
|
|
5274
6822
|
exports.MVT_RowActionMenu = MVT_RowActionMenu;
|
|
5275
6823
|
exports.MVT_RowPinButton = MVT_RowPinButton;
|
|
6824
|
+
exports.MVT_SERVER_GROUPING_ROOT_PATH_ID = MVT_SERVER_GROUPING_ROOT_PATH_ID;
|
|
5276
6825
|
exports.MVT_SelectCheckbox = MVT_SelectCheckbox;
|
|
6826
|
+
exports.MVT_ServerGroupingBody = MVT_ServerGroupingBody;
|
|
6827
|
+
exports.MVT_ServerGroupingGroupBy = MVT_ServerGroupingGroupBy;
|
|
5277
6828
|
exports.MVT_ShowHideColumnsButton = MVT_ShowHideColumnsButton;
|
|
5278
6829
|
exports.MVT_ShowHideColumnsMenu = MVT_ShowHideColumnsMenu;
|
|
5279
6830
|
exports.MVT_ShowHideColumnsMenuItems = MVT_ShowHideColumnsMenuItems;
|
|
@@ -5315,9 +6866,14 @@ exports.Memo_MVT_TableBody = Memo_MVT_TableBody;
|
|
|
5315
6866
|
exports.Memo_MVT_TableBodyCell = Memo_MVT_TableBodyCell;
|
|
5316
6867
|
exports.Memo_MVT_TableBodyRow = Memo_MVT_TableBodyRow;
|
|
5317
6868
|
exports.createMVTColumnHelper = createMVTColumnHelper;
|
|
6869
|
+
exports.createMVT_ServerGroupingManager = createMVT_ServerGroupingManager;
|
|
5318
6870
|
exports.createRow = createRow;
|
|
6871
|
+
exports.createServerGroupPathId = createServerGroupPathId;
|
|
6872
|
+
exports.createServerGroupingProvider = createServerGroupingProvider;
|
|
5319
6873
|
exports.dataVariable = dataVariable;
|
|
5320
6874
|
exports.defaultDisplayColumnProps = defaultDisplayColumnProps;
|
|
6875
|
+
exports.deselectServerGroupingRecords = deselectServerGroupingRecords;
|
|
6876
|
+
exports.escapeServerGroupPathPart = escapeServerGroupPathPart;
|
|
5321
6877
|
exports.flexRender = flexRender;
|
|
5322
6878
|
exports.getAllLeafColumnDefs = getAllLeafColumnDefs;
|
|
5323
6879
|
exports.getCanRankRows = getCanRankRows;
|
|
@@ -5327,21 +6883,36 @@ exports.getDefaultColumnOrderIds = getDefaultColumnOrderIds;
|
|
|
5327
6883
|
exports.getIsRankingRows = getIsRankingRows;
|
|
5328
6884
|
exports.getIsRowSelected = getIsRowSelected;
|
|
5329
6885
|
exports.getLeadingDisplayColumnIds = getLeadingDisplayColumnIds;
|
|
6886
|
+
exports.getMVT_ColumnWidthStyles = getMVT_ColumnWidthStyles;
|
|
5330
6887
|
exports.getMVT_RowSelectionHandler = getMVT_RowSelectionHandler;
|
|
5331
6888
|
exports.getMVT_Rows = getMVT_Rows;
|
|
5332
6889
|
exports.getMVT_SelectAllHandler = getMVT_SelectAllHandler;
|
|
5333
6890
|
exports.getPrimaryColor = getPrimaryColor;
|
|
5334
6891
|
exports.getPrimaryShade = getPrimaryShade;
|
|
6892
|
+
exports.getServerGroupPathDepth = getServerGroupPathDepth;
|
|
6893
|
+
exports.getServerGroupableColumns = getServerGroupableColumns;
|
|
6894
|
+
exports.getServerGroupingColumnActions = getServerGroupingColumnActions;
|
|
6895
|
+
exports.getServerGroupingGroupByContext = getServerGroupingGroupByContext;
|
|
6896
|
+
exports.getServerGroupingManager = getServerGroupingManager;
|
|
6897
|
+
exports.getServerGroupingSelectableRows = getServerGroupingSelectableRows;
|
|
6898
|
+
exports.getServerGroupingSelectionPayload = getServerGroupingSelectionPayload;
|
|
6899
|
+
exports.getServerGroupingSelectionSummary = getServerGroupingSelectionSummary;
|
|
5335
6900
|
exports.getTrailingDisplayColumnIds = getTrailingDisplayColumnIds;
|
|
6901
|
+
exports.isAbortError = isAbortError;
|
|
6902
|
+
exports.isServerGroupPathOrDescendant = isServerGroupPathOrDescendant;
|
|
6903
|
+
exports.isServerGroupingRecordSelected = isServerGroupingRecordSelected;
|
|
5336
6904
|
exports.localizedFilterOption = localizedFilterOption;
|
|
5337
6905
|
exports.mrtFilterOptions = mrtFilterOptions;
|
|
5338
6906
|
exports.parseCSSVarId = parseCSSVarId;
|
|
5339
6907
|
exports.parseFromValuesOrFunc = parseFromValuesOrFunc;
|
|
6908
|
+
exports.parseServerGroupPathId = parseServerGroupPathId;
|
|
5340
6909
|
exports.prepareColumns = prepareColumns;
|
|
5341
6910
|
exports.provideMVT_Slots = provideMVT_Slots;
|
|
5342
6911
|
exports.rankGlobalFuzzy = rankGlobalFuzzy;
|
|
5343
6912
|
exports.renderMVT_Renderable = renderMVT_Renderable;
|
|
5344
6913
|
exports.reorderColumn = reorderColumn;
|
|
6914
|
+
exports.selectAllMatchingServerGroupingRecords = selectAllMatchingServerGroupingRecords;
|
|
6915
|
+
exports.serializeServerGroupingCacheKey = serializeServerGroupingCacheKey;
|
|
5345
6916
|
exports.showRowActionsColumn = showRowActionsColumn;
|
|
5346
6917
|
exports.showRowDragColumn = showRowDragColumn;
|
|
5347
6918
|
exports.showRowExpandColumn = showRowExpandColumn;
|
|
@@ -5349,6 +6920,9 @@ exports.showRowNumbersColumn = showRowNumbersColumn;
|
|
|
5349
6920
|
exports.showRowPinningColumn = showRowPinningColumn;
|
|
5350
6921
|
exports.showRowSelectionColumn = showRowSelectionColumn;
|
|
5351
6922
|
exports.showRowSpacerColumn = showRowSpacerColumn;
|
|
6923
|
+
exports.toggleAllServerGroupingRecordsSelected = toggleAllServerGroupingRecordsSelected;
|
|
6924
|
+
exports.toggleServerGroupingRecordSelected = toggleServerGroupingRecordSelected;
|
|
6925
|
+
exports.unescapeServerGroupPathPart = unescapeServerGroupPathPart;
|
|
5352
6926
|
exports.useMVT_ColumnVirtualizer = useMVT_ColumnVirtualizer;
|
|
5353
6927
|
exports.useMVT_Effects = useMVT_Effects;
|
|
5354
6928
|
exports.useMVT_RowVirtualizer = useMVT_RowVirtualizer;
|