@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/esm/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { Fragment, Teleport, computed, defineComponent, h, inject, onBeforeUnmount, onMounted, provide, ref, resolveComponent, shallowRef, unref, watch } from "vue";
1
+ import { Fragment, Teleport, computed, defineComponent, getCurrentScope, h, inject, onBeforeUnmount, onMounted, onScopeDispose, provide, ref, resolveComponent, shallowRef, unref, watch } from "vue";
2
2
  import { aggregationFns, createRow as createRow$1, filterFns, getCoreRowModel, getExpandedRowModel, getFacetedMinMaxValues, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getGroupedRowModel, getPaginationRowModel, getSortedRowModel, sortingFns, useVueTable } from "@tanstack/vue-table";
3
- import { ActionIcon, Alert, Autocomplete, Badge, Box, Button, Checkbox, Collapse, Flex, Group, Highlight, Indicator, LoadingOverlay, Menu, Modal, MultiSelect, Pagination, Paper, Popover, Progress, Radio, RangeSlider, Select, Skeleton, Stack, Switch, Table, TableTbody, TableTd, TableTfoot, TableTh, TableThead, TableTr, Text, TextInput, Tooltip, Transition, UnstyledButton, darken, lighten, useDirection, useMantineColorScheme, useMantineTheme } from "@mantine-vue/core";
3
+ import { ActionIcon, Alert, Autocomplete, Badge, Box, Button, Checkbox, Collapse, Flex, Group, Highlight, Indicator, Loader, LoadingOverlay, Menu, Modal, MultiSelect, Pagination, Paper, Pill, PillGroup, Popover, Progress, Radio, RangeSlider, Select, Skeleton, Stack, Switch, Table, TableTbody, TableTd, TableTfoot, TableTh, TableThead, TableTr, Text, TextInput, Tooltip, Transition, UnstyledButton, darken, lighten, useDirection, useMantineColorScheme, useMantineTheme } from "@mantine-vue/core";
4
4
  import clsx from "clsx";
5
5
  import { compareItems, rankItem, rankings } from "@tanstack/match-sorter-utils";
6
6
  import { IconArrowAutofitContent, IconArrowsSort, IconBaselineDensityLarge, IconBaselineDensityMedium, IconBaselineDensitySmall, IconBoxMultiple, IconChevronDown, IconChevronLeft, IconChevronLeftPipe, IconChevronRight, IconChevronRightPipe, IconChevronsDown, IconCircleX, IconClearAll, IconColumns, IconDeviceFloppy, IconDots, IconDotsVertical, IconEdit, IconEyeOff, IconFilter, IconFilterCog, IconFilterOff, IconGripHorizontal, IconMaximize, IconMinimize, IconPinned, IconPinnedOff, IconSearch, IconSearchOff, IconSortAscending, IconSortDescending, IconX } from "@tabler/icons-vue";
@@ -125,6 +125,896 @@ var getDefaultColumnOrderIds = (tableOptions, reset = false) => {
125
125
  ];
126
126
  };
127
127
  //#endregion
128
+ //#region src/server-grouping/serverGrouping.types.ts
129
+ var MVT_SERVER_GROUPING_ROOT_PATH_ID = "__root__";
130
+ //#endregion
131
+ //#region src/utils/utils.ts
132
+ var parseFromValuesOrFunc = (fn, arg) => fn instanceof Function ? fn(arg) : fn;
133
+ //#endregion
134
+ //#region src/server-grouping/serverGroupingSelection.ts
135
+ /** The server-grouping engine of a table, when server grouping is active. */
136
+ var getServerGroupingManager = (table) => table._serverGrouping;
137
+ /**
138
+ * Record rows that the user may currently select: loaded records inside
139
+ * expanded groups only (never group rows, never collapsed or unloaded
140
+ * groups), filtered by `enableRowSelection`.
141
+ */
142
+ var getServerGroupingSelectableRows = (table) => {
143
+ const manager = getServerGroupingManager(table);
144
+ if (!manager) return [];
145
+ const { enableRowSelection } = table.options;
146
+ return manager.getVisibleRecordRows().filter((row) => parseFromValuesOrFunc(enableRowSelection, row) !== false);
147
+ };
148
+ /** Whether one record row is selected, honoring exclude mode. */
149
+ var isServerGroupingRecordSelected = (table, row) => {
150
+ const selectAll = getServerGroupingManager(table)?.getSelectAll();
151
+ if (selectAll?.active) return !selectAll.excludedRowIds.includes(row.id);
152
+ return !!table.getState().rowSelection?.[row.id];
153
+ };
154
+ /**
155
+ * Header-checkbox state for a server-grouped table.
156
+ *
157
+ * In *include* mode `isAll` means "every selectable loaded record is
158
+ * selected". In *exclude* mode ("all matching records") the selection is a
159
+ * query, so the checkbox is checked, and turns indeterminate as soon as the
160
+ * user unchecks individual rows.
161
+ */
162
+ var getServerGroupingSelectionSummary = (table) => {
163
+ const rows = getServerGroupingSelectableRows(table);
164
+ const selectAll = getServerGroupingManager(table)?.getSelectAll() ?? {
165
+ active: false,
166
+ excludedRowIds: []
167
+ };
168
+ if (selectAll.active) {
169
+ const excludedVisible = rows.filter((row) => selectAll.excludedRowIds.includes(row.id)).length;
170
+ return {
171
+ excludedRowIds: selectAll.excludedRowIds,
172
+ isAll: selectAll.excludedRowIds.length === 0,
173
+ isSelectAllMatching: true,
174
+ isSome: selectAll.excludedRowIds.length > 0,
175
+ mode: "exclude",
176
+ selectableCount: rows.length,
177
+ selectedCount: rows.length - excludedVisible,
178
+ selectedRowIds: []
179
+ };
180
+ }
181
+ const rowSelection = table.getState().rowSelection ?? {};
182
+ const selectedCount = rows.filter((row) => rowSelection[row.id]).length;
183
+ const selectedRowIds = Object.keys(rowSelection).filter((rowId) => rowSelection[rowId]);
184
+ const isAll = rows.length > 0 && selectedCount === rows.length;
185
+ return {
186
+ excludedRowIds: [],
187
+ isAll,
188
+ isSelectAllMatching: false,
189
+ isSome: !isAll && selectedRowIds.length > 0,
190
+ mode: "include",
191
+ selectableCount: rows.length,
192
+ selectedCount,
193
+ selectedRowIds
194
+ };
195
+ };
196
+ /**
197
+ * Everything a bulk action needs to send to the server.
198
+ *
199
+ * In exclude mode this is the query plus the user's deselections — no row ids
200
+ * are transferred, so it scales to millions of matching records.
201
+ */
202
+ var getServerGroupingSelectionPayload = (table) => {
203
+ const manager = getServerGroupingManager(table);
204
+ const summary = getServerGroupingSelectionSummary(table);
205
+ const tableState = table.getState();
206
+ return {
207
+ columnFilters: tableState.columnFilters ?? [],
208
+ excludedRowIds: summary.excludedRowIds,
209
+ globalFilter: tableState.globalFilter,
210
+ grouping: manager?.getGroupingFields() ?? [],
211
+ mode: summary.mode,
212
+ rowIds: summary.selectedRowIds,
213
+ sorting: tableState.sorting ?? []
214
+ };
215
+ };
216
+ /**
217
+ * Header-checkbox toggle.
218
+ *
219
+ * - **Checking** selects every loaded record inside expanded groups. Records in
220
+ * collapsed or unloaded groups are never implicitly selected.
221
+ * - **Unchecking** clears the *entire* selection — including records whose
222
+ * group was collapsed since, and everything added by "select all matching
223
+ * records". Removing only the on-screen ids would leave invisible records
224
+ * selected while the header checkbox reads unchecked.
225
+ */
226
+ var toggleAllServerGroupingRecordsSelected = (table, value) => {
227
+ const manager = getServerGroupingManager(table);
228
+ const summary = getServerGroupingSelectionSummary(table);
229
+ if (!(value ?? !(summary.isAll || summary.isSelectAllMatching))) {
230
+ manager?.setSelectAll({
231
+ active: false,
232
+ excludedRowIds: []
233
+ });
234
+ table.setRowSelection({});
235
+ return;
236
+ }
237
+ if (summary.isSelectAllMatching) {
238
+ manager?.setSelectAll({
239
+ active: true,
240
+ excludedRowIds: []
241
+ });
242
+ return;
243
+ }
244
+ const rows = getServerGroupingSelectableRows(table);
245
+ table.setRowSelection((prev) => {
246
+ const selection = { ...prev };
247
+ rows.forEach((row) => {
248
+ selection[row.id] = true;
249
+ });
250
+ return selection;
251
+ });
252
+ };
253
+ /** Deselect the given record ids (used by `selection.clearOnCollapse`). */
254
+ var deselectServerGroupingRecords = (table, rowIds) => {
255
+ if (!rowIds.length) return;
256
+ table.setRowSelection((prev) => {
257
+ const selection = { ...prev };
258
+ rowIds.forEach((rowId) => delete selection[rowId]);
259
+ return selection;
260
+ });
261
+ };
262
+ /**
263
+ * Toggle a single server-grouping record.
264
+ *
265
+ * Provider rows live outside the table's row model (`data` is empty), so
266
+ * `row.toggleSelected()` — which resolves the row through `table.getRow()` —
267
+ * would throw. Selection state is mutated directly instead.
268
+ *
269
+ * Supports shift-click range selection across the loaded records currently on
270
+ * screen, matching the behavior of a regular MVT table.
271
+ */
272
+ var toggleServerGroupingRecordSelected = (table, row, value, options) => {
273
+ const manager = getServerGroupingManager(table);
274
+ const rows = getServerGroupingSelectableRows(table);
275
+ const targetIds = new Set([row.id]);
276
+ if (options?.batch && options.lastSelectedRowId) {
277
+ const lastIndex = rows.findIndex((candidate) => candidate.id === options.lastSelectedRowId);
278
+ const currentIndex = rows.findIndex((candidate) => candidate.id === row.id);
279
+ if (lastIndex !== -1 && currentIndex !== -1) {
280
+ const [start, end] = lastIndex < currentIndex ? [lastIndex, currentIndex] : [currentIndex, lastIndex];
281
+ for (let index = start; index <= end; index++) targetIds.add(rows[index].id);
282
+ }
283
+ }
284
+ const selectAll = manager?.getSelectAll();
285
+ if (selectAll?.active) {
286
+ const excluded = new Set(selectAll.excludedRowIds);
287
+ targetIds.forEach((rowId) => {
288
+ if (value) excluded.delete(rowId);
289
+ else excluded.add(rowId);
290
+ });
291
+ manager.setSelectAll({
292
+ active: true,
293
+ excludedRowIds: [...excluded]
294
+ });
295
+ return;
296
+ }
297
+ table.setRowSelection((prev) => {
298
+ const selection = { ...prev };
299
+ targetIds.forEach((rowId) => {
300
+ if (value) selection[rowId] = true;
301
+ else delete selection[rowId];
302
+ });
303
+ return selection;
304
+ });
305
+ };
306
+ /**
307
+ * Opt-in "select all matching records" action: asks the consumer-provided
308
+ * `serverGrouping.selection.loadAllMatchingRowIds` for every row id matching
309
+ * the current filters (across all groups and pages) and selects them.
310
+ */
311
+ var selectAllMatchingServerGroupingRecords = async (table) => {
312
+ const manager = getServerGroupingManager(table);
313
+ if (!manager) return;
314
+ const selectionOptions = manager.options.selection;
315
+ if ((selectionOptions?.selectAllMode ?? "query") === "query") {
316
+ table.setRowSelection({});
317
+ manager.setSelectAll({
318
+ active: true,
319
+ excludedRowIds: []
320
+ });
321
+ return;
322
+ }
323
+ const loadAllMatchingRowIds = selectionOptions?.loadAllMatchingRowIds;
324
+ if (!loadAllMatchingRowIds) return;
325
+ const tableState = table.getState();
326
+ const rowIds = await loadAllMatchingRowIds({
327
+ columnFilters: tableState.columnFilters ?? [],
328
+ globalFilter: tableState.globalFilter,
329
+ grouping: manager.getGroupingFields(),
330
+ sorting: tableState.sorting ?? [],
331
+ table
332
+ });
333
+ table.setRowSelection((prev) => {
334
+ const selection = { ...prev };
335
+ rowIds.forEach((rowId) => {
336
+ selection[rowId] = true;
337
+ });
338
+ return selection;
339
+ });
340
+ };
341
+ //#endregion
342
+ //#region src/server-grouping/serverGrouping.utils.ts
343
+ /**
344
+ * Escape a path segment part so group ids may safely contain the reserved
345
+ * characters `/` and `:` (and `%`, used for escaping).
346
+ */
347
+ var escapeServerGroupPathPart = (part) => part.replace(/%/g, "%25").replace(/:/g, "%3A").replace(/\//g, "%2F");
348
+ var unescapeServerGroupPathPart = (part) => part.replace(/%2F/g, "/").replace(/%3A/g, ":").replace(/%25/g, "%");
349
+ /**
350
+ * Build the stable path id of a group's content, e.g.
351
+ * `createServerGroupPathId('__root__', 'country', 'BH')` → `'country:BH'` and
352
+ * `createServerGroupPathId('country:BH', 'salesperson', '42')` →
353
+ * `'country:BH/salesperson:42'`. Never derived from row indexes.
354
+ */
355
+ var createServerGroupPathId = (parentPathId, field, groupId) => {
356
+ const segment = `${escapeServerGroupPathPart(field)}:${escapeServerGroupPathPart(groupId)}`;
357
+ return parentPathId === "__root__" ? segment : `${parentPathId}/${segment}`;
358
+ };
359
+ /** Parse a path id back into its `{ field, groupId }` segments. Root → `[]`. */
360
+ var parseServerGroupPathId = (pathId) => {
361
+ if (pathId === "__root__") return [];
362
+ return pathId.split("/").map((segment) => {
363
+ const separatorIndex = segment.indexOf(":");
364
+ return {
365
+ field: unescapeServerGroupPathPart(segment.slice(0, separatorIndex)),
366
+ groupId: unescapeServerGroupPathPart(segment.slice(separatorIndex + 1))
367
+ };
368
+ });
369
+ };
370
+ /** Depth of the content addressed by a path id (root → 0). */
371
+ var getServerGroupPathDepth = (pathId) => pathId === "__root__" ? 0 : pathId.split("/").length;
372
+ /** Whether `pathId` equals `ancestorPathId` or is nested anywhere below it. */
373
+ var isServerGroupPathOrDescendant = (pathId, ancestorPathId) => ancestorPathId === "__root__" || pathId === ancestorPathId || pathId.startsWith(`${ancestorPathId}/`);
374
+ /** JSON replacer producing deterministic output for plain objects. */
375
+ var stableReplacer = (_key, value) => {
376
+ if (value && typeof value === "object" && !Array.isArray(value)) return Object.keys(value).sort().reduce((acc, key) => {
377
+ acc[key] = value[key];
378
+ return acc;
379
+ }, {});
380
+ return value;
381
+ };
382
+ /**
383
+ * Serialize cache key parts deterministically (object key order does not
384
+ * affect the result).
385
+ */
386
+ var serializeServerGroupingCacheKey = (parts) => JSON.stringify(parts, stableReplacer);
387
+ /** Whether an error was caused by request cancellation (never shown as an error). */
388
+ var isAbortError = (error) => error instanceof DOMException ? error.name === "AbortError" : error?.name === "AbortError";
389
+ //#endregion
390
+ //#region src/server-grouping/useMVT_ServerGrouping.ts
391
+ var createMVT_ServerGroupingManager = (table, controlledExpandedReader, controlledSelectAllReader) => {
392
+ const serverGroupingOptions = table.options.serverGrouping;
393
+ if (!serverGroupingOptions?.provider || serverGroupingOptions.enabled === false) return;
394
+ const options = serverGroupingOptions;
395
+ const provider = options.provider;
396
+ const sortingMode = options.sortingMode ?? "independent";
397
+ const filteringMode = options.filteringMode ?? "shared";
398
+ const cacheOptions = {
399
+ enabled: options.cache?.enabled ?? false,
400
+ gcTime: options.cache?.gcTime ?? 3e5,
401
+ keepCollapsedGroups: options.cache?.keepCollapsedGroups ?? true,
402
+ staleTime: options.cache?.staleTime ?? 0
403
+ };
404
+ const configuredPageSize = options.pagination?.defaultPageSize ?? options.initialPageSize ?? 10;
405
+ let defaultPageSize = configuredPageSize;
406
+ if (!Number.isInteger(configuredPageSize) || configuredPageSize <= 0) {
407
+ console.warn(`[mantine-vue-table] serverGrouping page size ${JSON.stringify(configuredPageSize)} is invalid — expected a positive integer. Falling back to 10.`);
408
+ defaultPageSize = 10;
409
+ }
410
+ const pathStates = ref({});
411
+ const internalExpanded = ref(table.options.initialState?.serverGroupingExpanded ?? {});
412
+ const internalSelectAll = ref(table.options.initialState?.serverGroupingSelectAll ?? {
413
+ active: false,
414
+ excludedRowIds: []
415
+ });
416
+ const nodeRegistry = /* @__PURE__ */ new Map();
417
+ const controllers = /* @__PURE__ */ new Map();
418
+ const versions = /* @__PURE__ */ new Map();
419
+ const cache = /* @__PURE__ */ new Map();
420
+ const rowCache = /* @__PURE__ */ new Map();
421
+ const readControlledExpanded = controlledExpandedReader ?? (() => table.options.state?.serverGroupingExpanded);
422
+ const isExpandedControlled = readControlledExpanded() !== void 0;
423
+ const getExpanded = () => readControlledExpanded() ?? internalExpanded.value;
424
+ const setExpanded = (updater) => {
425
+ const next = updater instanceof Function ? updater(getExpanded()) : updater;
426
+ const onChange = table.options.onServerGroupingExpandedChange;
427
+ if (onChange) onChange(next);
428
+ if (!isExpandedControlled) internalExpanded.value = next;
429
+ };
430
+ const isExpanded = (pathId) => getExpanded()[pathId] === true;
431
+ const readControlledSelectAll = controlledSelectAllReader ?? (() => table.options.state?.serverGroupingSelectAll);
432
+ const isSelectAllControlled = readControlledSelectAll() !== void 0;
433
+ const getSelectAll = () => readControlledSelectAll() ?? internalSelectAll.value;
434
+ const setSelectAll = (updater) => {
435
+ const next = updater instanceof Function ? updater(getSelectAll()) : updater;
436
+ table.options.onServerGroupingSelectAllChange?.(next);
437
+ if (!isSelectAllControlled) internalSelectAll.value = next;
438
+ };
439
+ /** The "all matching" selection is tied to the query it was made under. */
440
+ const resetSelectAll = () => {
441
+ if (getSelectAll().active || getSelectAll().excludedRowIds.length) setSelectAll({
442
+ active: false,
443
+ excludedRowIds: []
444
+ });
445
+ };
446
+ const getGroupingFields = () => options.grouping ?? table.getState().grouping ?? [];
447
+ const setPathState = (pathId, state) => {
448
+ pathStates.value = {
449
+ ...pathStates.value,
450
+ [pathId]: state
451
+ };
452
+ };
453
+ const getPathState = (pathId) => pathStates.value[pathId];
454
+ /**
455
+ * Table rows for one loaded record page. Rows are created (and cached) here
456
+ * rather than in the renderer so row ids — and therefore selection state —
457
+ * have a single source of truth shared by the body, the header checkbox, and
458
+ * the public selection APIs.
459
+ */
460
+ const getRecordRows = (pathId) => {
461
+ const state = getPathState(pathId);
462
+ if (!state || state.kind !== "records" || !state.rows) return [];
463
+ const cached = rowCache.get(pathId);
464
+ if (cached && cached.source === state.rows) return cached.rows;
465
+ const depth = getServerGroupPathDepth(pathId);
466
+ const rows = state.rows.map((original, index) => {
467
+ return createRow$1(table, provider.getRowId?.(original) ?? table.options.getRowId?.(original, index, void 0) ?? `${pathId}::${index}`, original, index, depth);
468
+ });
469
+ rowCache.set(pathId, {
470
+ rows,
471
+ source: state.rows
472
+ });
473
+ return rows;
474
+ };
475
+ /**
476
+ * Every loaded record row that is currently visible — i.e. inside expanded
477
+ * groups on the current pages. Records in collapsed or never-loaded groups
478
+ * are deliberately excluded, so selection can never reach them.
479
+ */
480
+ const getVisibleRecordRows = () => Object.keys(pathStates.value).filter((pathId) => pathStates.value[pathId]?.kind === "records" && isPathVisible(pathId)).flatMap((pathId) => getRecordRows(pathId));
481
+ const getNode = (pathId) => {
482
+ const item = nodeRegistry.get(pathId);
483
+ if (!item) return void 0;
484
+ return {
485
+ count: void 0,
486
+ id: item.id,
487
+ label: item.label,
488
+ meta: item.meta,
489
+ original: item.original,
490
+ value: item.value,
491
+ ...item.__node
492
+ };
493
+ };
494
+ const getParentItems = (pathId) => {
495
+ if (pathId === "__root__") return [];
496
+ const segments = pathId.split("/");
497
+ const items = [];
498
+ for (let index = 0; index < segments.length; index++) {
499
+ const ancestorPathId = segments.slice(0, index + 1).join("/");
500
+ const item = nodeRegistry.get(ancestorPathId);
501
+ if (item) items.push(item);
502
+ }
503
+ return items;
504
+ };
505
+ const getEffectiveSorting = (pathId, kind) => {
506
+ const override = getPathState(pathId)?.sorting;
507
+ if (override) return override;
508
+ const tableSorting = table.getState().sorting ?? [];
509
+ if (sortingMode === "shared") return tableSorting;
510
+ if (sortingMode === "records-only") return kind === "records" ? tableSorting : [];
511
+ return pathId === "__root__" ? tableSorting : [];
512
+ };
513
+ const getEffectiveFilters = (pathId, kind) => {
514
+ const state = getPathState(pathId);
515
+ if (state?.columnFilters || state?.globalFilter !== void 0) return {
516
+ columnFilters: state.columnFilters ?? [],
517
+ globalFilter: state.globalFilter
518
+ };
519
+ if (filteringMode === "independent") return {
520
+ columnFilters: [],
521
+ globalFilter: void 0
522
+ };
523
+ if (filteringMode === "records-only" && kind !== "records") return {
524
+ columnFilters: [],
525
+ globalFilter: void 0
526
+ };
527
+ const tableState = table.getState();
528
+ return {
529
+ columnFilters: tableState.columnFilters ?? [],
530
+ globalFilter: tableState.globalFilter
531
+ };
532
+ };
533
+ const isRootPath = (pathId) => pathId === MVT_SERVER_GROUPING_ROOT_PATH_ID;
534
+ const getDefaultPagination = () => ({
535
+ pageIndex: 0,
536
+ pageSize: defaultPageSize
537
+ });
538
+ /**
539
+ * Effective pagination of a path. The root level is driven by the table's
540
+ * own `pagination` state, so the standard bottom toolbar (page navigation +
541
+ * rows-per-page) controls it exactly like an ungrouped server-side table.
542
+ * Nested levels keep their own independent, fixed-page-size state.
543
+ */
544
+ const getEffectivePagination = (pathId) => {
545
+ if (isRootPath(pathId)) {
546
+ const { pageIndex, pageSize } = table.getState().pagination;
547
+ return {
548
+ ...getPathState(pathId)?.pagination,
549
+ pageIndex,
550
+ pageSize
551
+ };
552
+ }
553
+ return getPathState(pathId)?.pagination ?? getDefaultPagination();
554
+ };
555
+ /** Reset a path to page 0. Returns `true` when it triggered a root reload. */
556
+ const resetPageIndex = (pathId) => {
557
+ if (isRootPath(pathId)) {
558
+ const { pageIndex } = table.getState().pagination;
559
+ if (pageIndex === 0) return false;
560
+ table.setPageIndex(0);
561
+ return true;
562
+ }
563
+ const state = getPathState(pathId);
564
+ if (state) setPathState(pathId, {
565
+ ...state,
566
+ pagination: {
567
+ ...state.pagination,
568
+ cursor: void 0,
569
+ pageIndex: 0
570
+ }
571
+ });
572
+ return false;
573
+ };
574
+ const buildRequest = (pathId, kind, signal) => {
575
+ const grouping = getGroupingFields();
576
+ const depth = getServerGroupPathDepth(pathId);
577
+ const parentGroups = getParentItems(pathId);
578
+ const { columnFilters, globalFilter } = getEffectiveFilters(pathId, kind);
579
+ const base = {
580
+ columnFilters,
581
+ depth,
582
+ globalFilter,
583
+ grouping,
584
+ pagination: getEffectivePagination(pathId),
585
+ parentGroup: parentGroups.at(-1),
586
+ parentGroups,
587
+ pathId,
588
+ signal,
589
+ sorting: getEffectiveSorting(pathId, kind),
590
+ table
591
+ };
592
+ return kind === "groups" ? {
593
+ ...base,
594
+ groupingField: grouping[depth]
595
+ } : base;
596
+ };
597
+ const getCacheKey = (request) => serializeServerGroupingCacheKey([
598
+ request.pathId,
599
+ request.grouping,
600
+ request.depth,
601
+ request.pagination,
602
+ request.sorting,
603
+ request.columnFilters,
604
+ request.globalFilter ?? null,
605
+ ...provider.getCacheKey?.(request) ?? []
606
+ ]);
607
+ const gcCache = () => {
608
+ const now = Date.now();
609
+ cache.forEach((entry, key) => {
610
+ if (now - entry.updatedAt > cacheOptions.gcTime) cache.delete(key);
611
+ });
612
+ };
613
+ const load = (pathId) => {
614
+ const grouping = getGroupingFields();
615
+ const depth = getServerGroupPathDepth(pathId);
616
+ const kind = depth >= grouping.length ? "records" : "groups";
617
+ const previous = getPathState(pathId);
618
+ const hasData = previous?.groups !== void 0 || previous?.rows !== void 0;
619
+ controllers.get(pathId)?.abort();
620
+ const controller = new AbortController();
621
+ controllers.set(pathId, controller);
622
+ const version = (versions.get(pathId) ?? 0) + 1;
623
+ versions.set(pathId, version);
624
+ const request = buildRequest(pathId, kind, controller.signal);
625
+ const isCurrent = () => versions.get(pathId) === version && !controller.signal.aborted;
626
+ let servedFromCache = false;
627
+ let cacheKey;
628
+ if (cacheOptions.enabled) {
629
+ cacheKey = getCacheKey(request);
630
+ const entry = cache.get(cacheKey);
631
+ if (entry) {
632
+ servedFromCache = true;
633
+ const fresh = Date.now() - entry.updatedAt <= cacheOptions.staleTime;
634
+ setPathState(pathId, {
635
+ ...entry.payload,
636
+ columnFilters: previous?.columnFilters,
637
+ depth,
638
+ error: null,
639
+ globalFilter: previous?.globalFilter,
640
+ isFetching: !fresh,
641
+ isLoading: false,
642
+ pagination: request.pagination,
643
+ pathId,
644
+ sorting: previous?.sorting,
645
+ updatedAt: entry.updatedAt
646
+ });
647
+ if (entry.payload.kind === "groups") registerGroups(pathId, entry.payload.groups ?? [], grouping[depth], depth);
648
+ if (fresh) return;
649
+ }
650
+ }
651
+ if (!servedFromCache) setPathState(pathId, {
652
+ ...previous,
653
+ columnFilters: previous?.columnFilters,
654
+ depth,
655
+ error: null,
656
+ groups: kind === "groups" ? previous?.groups : void 0,
657
+ isFetching: true,
658
+ isLoading: !hasData,
659
+ kind,
660
+ pagination: request.pagination,
661
+ pathId,
662
+ rowCount: previous?.rowCount ?? 0,
663
+ rows: kind === "records" ? previous?.rows : void 0,
664
+ sorting: previous?.sorting
665
+ });
666
+ const eventPayload = {
667
+ path: request.parentGroups,
668
+ pathId
669
+ };
670
+ options.onGroupLoadStart?.({
671
+ ...eventPayload,
672
+ request
673
+ });
674
+ const promise = kind === "groups" ? provider.loadGroups(request) : provider.loadRecords(request);
675
+ Promise.resolve(promise).then((response) => {
676
+ if (!isCurrent()) return;
677
+ const updatedAt = Date.now();
678
+ let payload;
679
+ if (kind === "groups") {
680
+ const context = {
681
+ depth,
682
+ field: grouping[depth],
683
+ request
684
+ };
685
+ const groups = (provider.getGroups(response) ?? []).map((group) => ({
686
+ count: provider.getGroupCount?.(group, context),
687
+ hasChildren: provider.hasGroupChildren?.(group, context) ?? true,
688
+ id: provider.getGroupId(group, context),
689
+ label: provider.getGroupLabel(group, context),
690
+ meta: provider.getGroupMeta?.(group, context) ?? {},
691
+ original: group,
692
+ value: provider.getGroupValue ? provider.getGroupValue(group, context) : group
693
+ }));
694
+ registerGroups(pathId, groups, grouping[depth], depth);
695
+ payload = {
696
+ groups,
697
+ kind,
698
+ rowCount: provider.getGroupRowCount(response)
699
+ };
700
+ options.onGroupLoadSuccess?.({
701
+ ...eventPayload,
702
+ groups,
703
+ request,
704
+ response
705
+ });
706
+ } else {
707
+ const rows = provider.getRecords(response) ?? [];
708
+ payload = {
709
+ kind,
710
+ rowCount: provider.getRecordRowCount(response),
711
+ rows
712
+ };
713
+ options.onRecordLoadSuccess?.({
714
+ ...eventPayload,
715
+ request,
716
+ response,
717
+ rows
718
+ });
719
+ }
720
+ setPathState(pathId, {
721
+ ...getPathState(pathId),
722
+ ...payload,
723
+ error: null,
724
+ isFetching: false,
725
+ isLoading: false,
726
+ updatedAt
727
+ });
728
+ if (cacheOptions.enabled && cacheKey) {
729
+ cache.set(cacheKey, {
730
+ pathId,
731
+ payload,
732
+ updatedAt
733
+ });
734
+ gcCache();
735
+ }
736
+ }).catch((error) => {
737
+ if (!isCurrent() || isAbortError(error)) return;
738
+ setPathState(pathId, {
739
+ ...getPathState(pathId),
740
+ error,
741
+ isFetching: false,
742
+ isLoading: false
743
+ });
744
+ options.onError?.({
745
+ ...eventPayload,
746
+ error,
747
+ request
748
+ });
749
+ });
750
+ };
751
+ const registerGroups = (parentPathId, groups, field, depth) => {
752
+ groups.forEach((node) => {
753
+ const childPathId = createServerGroupPathId(parentPathId, field, node.id);
754
+ const item = {
755
+ depth,
756
+ field,
757
+ id: node.id,
758
+ label: node.label,
759
+ meta: node.meta,
760
+ original: node.original,
761
+ value: node.value
762
+ };
763
+ item.__node = node;
764
+ nodeRegistry.set(childPathId, item);
765
+ });
766
+ };
767
+ const ensureLoaded = (pathId) => {
768
+ const state = getPathState(pathId);
769
+ if (!state || state.groups === void 0 && state.rows === void 0 && !state.isFetching) load(pathId);
770
+ };
771
+ const isPathVisible = (pathId) => {
772
+ if (pathId === "__root__") return true;
773
+ const segments = pathId.split("/");
774
+ for (let index = 0; index < segments.length; index++) if (!isExpanded(segments.slice(0, index + 1).join("/"))) return false;
775
+ return true;
776
+ };
777
+ const getLoadedVisiblePaths = () => Object.keys(pathStates.value).filter(isPathVisible);
778
+ const abortPathAndDescendants = (pathId) => {
779
+ controllers.forEach((controller, key) => {
780
+ if (!isServerGroupPathOrDescendant(key, pathId)) return;
781
+ controller.abort();
782
+ const state = getPathState(key);
783
+ if (state?.isFetching || state?.isLoading) setPathState(key, {
784
+ ...state,
785
+ isFetching: false,
786
+ isLoading: false
787
+ });
788
+ });
789
+ };
790
+ const dropPathAndDescendants = (pathId) => {
791
+ const next = { ...pathStates.value };
792
+ Object.keys(next).forEach((key) => {
793
+ if (isServerGroupPathOrDescendant(key, pathId)) delete next[key];
794
+ });
795
+ pathStates.value = next;
796
+ cache.forEach((entry, key) => {
797
+ if (isServerGroupPathOrDescendant(entry.pathId, pathId)) cache.delete(key);
798
+ });
799
+ rowCache.forEach((_entry, key) => {
800
+ if (isServerGroupPathOrDescendant(key, pathId)) rowCache.delete(key);
801
+ });
802
+ };
803
+ const expand = (pathId) => {
804
+ if (isExpanded(pathId)) return;
805
+ setExpanded((prev) => ({
806
+ ...prev,
807
+ [pathId]: true
808
+ }));
809
+ };
810
+ const collapse = (pathId) => {
811
+ if (!isExpanded(pathId)) return;
812
+ setExpanded((prev) => ({
813
+ ...prev,
814
+ [pathId]: false
815
+ }));
816
+ };
817
+ const toggle = (pathId) => {
818
+ if (isExpanded(pathId)) collapse(pathId);
819
+ else expand(pathId);
820
+ };
821
+ const invalidate = (pathId) => {
822
+ if (pathId === void 0) cache.clear();
823
+ else cache.forEach((entry, key) => {
824
+ if (isServerGroupPathOrDescendant(entry.pathId, pathId)) cache.delete(key);
825
+ });
826
+ };
827
+ const reload = (pathId) => {
828
+ if (pathId !== void 0) {
829
+ invalidate(pathId);
830
+ if (getPathState(pathId)) load(pathId);
831
+ return;
832
+ }
833
+ invalidate();
834
+ getLoadedVisiblePaths().forEach((visiblePathId) => load(visiblePathId));
835
+ };
836
+ const retry = (pathId) => {
837
+ load(pathId);
838
+ };
839
+ const reset = () => {
840
+ controllers.forEach((controller) => controller.abort());
841
+ controllers.clear();
842
+ versions.clear();
843
+ nodeRegistry.clear();
844
+ cache.clear();
845
+ rowCache.clear();
846
+ pathStates.value = {};
847
+ if (options.resetExpansionOnGroupingChange !== false) setExpanded({});
848
+ load(MVT_SERVER_GROUPING_ROOT_PATH_ID);
849
+ };
850
+ const setPagination = (pathId, updater) => {
851
+ const previous = getEffectivePagination(pathId);
852
+ const next = updater instanceof Function ? updater(previous) : {
853
+ ...previous,
854
+ ...updater
855
+ };
856
+ if (isRootPath(pathId)) {
857
+ const state = getPathState(pathId);
858
+ if (state) setPathState(pathId, {
859
+ ...state,
860
+ pagination: next
861
+ });
862
+ const current = table.getState().pagination;
863
+ if (current.pageIndex === next.pageIndex && current.pageSize === next.pageSize) load(pathId);
864
+ else table.setPagination({
865
+ pageIndex: next.pageIndex,
866
+ pageSize: next.pageSize
867
+ });
868
+ return;
869
+ }
870
+ const state = getPathState(pathId);
871
+ if (state) setPathState(pathId, {
872
+ ...state,
873
+ pagination: next
874
+ });
875
+ else setPathState(pathId, {
876
+ depth: getServerGroupPathDepth(pathId),
877
+ error: null,
878
+ isFetching: false,
879
+ isLoading: false,
880
+ kind: getServerGroupPathDepth(pathId) >= getGroupingFields().length ? "records" : "groups",
881
+ pagination: next,
882
+ pathId,
883
+ rowCount: 0
884
+ });
885
+ load(pathId);
886
+ };
887
+ const setSorting = (pathId, updater) => {
888
+ const state = getPathState(pathId);
889
+ const previous = state?.sorting ?? [];
890
+ const next = updater instanceof Function ? updater(previous) : updater;
891
+ if (!state) return;
892
+ setPathState(pathId, {
893
+ ...state,
894
+ sorting: next
895
+ });
896
+ if (!resetPageIndex(pathId)) load(pathId);
897
+ };
898
+ const setColumnFilters = (pathId, updater) => {
899
+ const state = getPathState(pathId);
900
+ if (!state) return;
901
+ const previous = state.columnFilters ?? [];
902
+ const next = updater instanceof Function ? updater(previous) : updater;
903
+ setPathState(pathId, {
904
+ ...state,
905
+ columnFilters: next
906
+ });
907
+ if (!resetPageIndex(pathId)) load(pathId);
908
+ };
909
+ const setGlobalFilter = (pathId, value) => {
910
+ const state = getPathState(pathId);
911
+ if (!state) return;
912
+ setPathState(pathId, {
913
+ ...state,
914
+ globalFilter: value
915
+ });
916
+ if (!resetPageIndex(pathId)) load(pathId);
917
+ };
918
+ const getState = () => ({
919
+ enabled: true,
920
+ expanded: getExpanded(),
921
+ grouping: getGroupingFields(),
922
+ paths: pathStates.value
923
+ });
924
+ watch(() => ({ ...getExpanded() }), (next, prev) => {
925
+ Object.keys(next).forEach((pathId) => {
926
+ if (next[pathId] && !prev?.[pathId]) {
927
+ options.onGroupExpand?.({
928
+ group: getNode(pathId),
929
+ path: getParentItems(pathId),
930
+ pathId
931
+ });
932
+ ensureLoaded(pathId);
933
+ }
934
+ });
935
+ Object.keys(prev ?? {}).forEach((pathId) => {
936
+ if (prev?.[pathId] && !next[pathId]) {
937
+ options.onGroupCollapse?.({
938
+ group: getNode(pathId),
939
+ path: getParentItems(pathId),
940
+ pathId
941
+ });
942
+ abortPathAndDescendants(pathId);
943
+ 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)));
944
+ if (!cacheOptions.keepCollapsedGroups) dropPathAndDescendants(pathId);
945
+ }
946
+ });
947
+ });
948
+ watch(() => JSON.stringify(getGroupingFields()), (next, prev) => {
949
+ if (next !== prev) {
950
+ resetSelectAll();
951
+ reset();
952
+ }
953
+ });
954
+ watch(() => JSON.stringify([table.getState().columnFilters ?? [], table.getState().globalFilter ?? null]), (next, prev) => {
955
+ if (next === prev || filteringMode === "independent") return;
956
+ resetSelectAll();
957
+ invalidate();
958
+ getLoadedVisiblePaths().filter((pathId) => filteringMode === "shared" || getPathState(pathId)?.kind === "records").forEach((pathId) => {
959
+ setPathState(pathId, {
960
+ ...getPathState(pathId),
961
+ groups: void 0,
962
+ rows: void 0
963
+ });
964
+ if (!resetPageIndex(pathId)) load(pathId);
965
+ });
966
+ });
967
+ watch(() => JSON.stringify(table.getState().sorting ?? []), (next, prev) => {
968
+ if (next === prev) return;
969
+ getLoadedVisiblePaths().filter((pathId) => {
970
+ if (getPathState(pathId)?.sorting) return false;
971
+ if (sortingMode === "shared") return true;
972
+ if (sortingMode === "records-only") return getPathState(pathId)?.kind === "records";
973
+ return pathId === MVT_SERVER_GROUPING_ROOT_PATH_ID;
974
+ }).forEach((pathId) => {
975
+ if (!resetPageIndex(pathId)) load(pathId);
976
+ });
977
+ });
978
+ watch(() => {
979
+ const { pageIndex, pageSize } = table.getState().pagination;
980
+ return `${pageIndex}:${pageSize}`;
981
+ }, (next, prev) => {
982
+ if (next !== prev) load(MVT_SERVER_GROUPING_ROOT_PATH_ID);
983
+ });
984
+ load(MVT_SERVER_GROUPING_ROOT_PATH_ID);
985
+ if (getCurrentScope()) onScopeDispose(() => {
986
+ controllers.forEach((controller) => controller.abort());
987
+ controllers.clear();
988
+ });
989
+ return {
990
+ collapse,
991
+ ensureLoaded,
992
+ expand,
993
+ getExpanded,
994
+ getGroupingFields,
995
+ getNode,
996
+ getParentItems,
997
+ getPathState,
998
+ getRecordRows,
999
+ getSelectAll,
1000
+ getState,
1001
+ getVisibleRecordRows,
1002
+ invalidate,
1003
+ isExpanded,
1004
+ options,
1005
+ reload,
1006
+ reset,
1007
+ retry,
1008
+ setColumnFilters,
1009
+ setExpanded,
1010
+ setGlobalFilter,
1011
+ setSelectAll,
1012
+ setPagination,
1013
+ setSorting,
1014
+ toggle
1015
+ };
1016
+ };
1017
+ //#endregion
128
1018
  //#region src/utils/tanstack.helpers.ts
129
1019
  /**
130
1020
  * Vue equivalent of `@tanstack/react-table`'s `flexRender`.
@@ -154,9 +1044,6 @@ function createMVTColumnHelper() {
154
1044
  }
155
1045
  var createRow = (table, originalRow, rowIndex = -1, depth = 0, subRows, parentId) => createRow$1(table, "mvt-row-create", originalRow ?? Object.assign({}, ...getAllLeafColumnDefs(table.options.columns).map((col) => ({ [getColumnId(col)]: "" }))), rowIndex, depth, subRows, parentId);
156
1046
  //#endregion
157
- //#region src/utils/utils.ts
158
- var parseFromValuesOrFunc = (fn, arg) => fn instanceof Function ? fn(arg) : fn;
159
- //#endregion
160
1047
  //#region src/components/MVT_TableSlots.ts
161
1048
  var MVT_SLOTS_KEY = Symbol("MVT_Slots");
162
1049
  /**
@@ -632,7 +1519,7 @@ var MVT_EditCellTextInput = defineComponent({
632
1519
  label: modal ? def.header : void 0,
633
1520
  name: cell.id,
634
1521
  placeholder: !modal ? def.header : void 0,
635
- value: value.value,
1522
+ modelValue: value.value,
636
1523
  variant: table.options.editDisplayMode === "table" ? "unstyled" : "default",
637
1524
  onClick: (e) => e.stopPropagation(),
638
1525
  ref: setRef
@@ -641,30 +1528,30 @@ var MVT_EditCellTextInput = defineComponent({
641
1528
  ...common,
642
1529
  searchable: true,
643
1530
  ...selectProps,
644
- onChange: (newValue, option) => {
1531
+ "onUpdate:modelValue": (newValue) => {
645
1532
  value.value = newValue;
646
- selectProps.onChange?.(newValue, option);
647
1533
  },
1534
+ onChange: selectProps.onChange,
648
1535
  onBlur: blur
649
1536
  });
650
1537
  if (def.editVariant === "multi-select") return h(MultiSelect, {
651
1538
  ...common,
652
1539
  searchable: true,
653
1540
  ...selectProps,
654
- onChange: (newValue) => {
1541
+ "onUpdate:modelValue": (newValue) => {
655
1542
  value.value = newValue;
656
- selectProps.onChange?.(newValue);
657
1543
  },
1544
+ onChange: selectProps.onChange,
658
1545
  onBlur: blur
659
1546
  });
660
1547
  return h(TextInput, {
661
1548
  ...common,
662
- value: value.value ?? "",
1549
+ modelValue: value.value ?? "",
663
1550
  ...textProps,
664
- onChange: (event) => {
665
- value.value = typeof event === "string" ? event : event.target.value;
666
- textProps.onChange?.(event);
1551
+ "onUpdate:modelValue": (nextValue) => {
1552
+ value.value = nextValue;
667
1553
  },
1554
+ onChange: textProps.onChange,
668
1555
  onBlur: blur,
669
1556
  onKeydown: (event) => {
670
1557
  textProps.onKeyDown?.(event);
@@ -978,6 +1865,7 @@ var getIsRankingRows = (table) => {
978
1865
  };
979
1866
  var getIsRowSelected = ({ row, table }) => {
980
1867
  const { options: { enableRowSelection } } = table;
1868
+ if (getServerGroupingManager(table)) return isServerGroupingRecordSelected(table, row);
981
1869
  return row.getIsSelected() || parseFromValuesOrFunc(enableRowSelection, row) && row.getCanSelectSubRows() && row.getIsAllSubRowsSelected();
982
1870
  };
983
1871
  var getMVT_RowSelectionHandler = ({ renderedRowIndex = 0, row, table }) => (event, value) => {
@@ -988,6 +1876,14 @@ var getMVT_RowSelectionHandler = ({ renderedRowIndex = 0, row, table }) => (even
988
1876
  row,
989
1877
  table
990
1878
  });
1879
+ if (getServerGroupingManager(table)) {
1880
+ toggleServerGroupingRecordSelected(table, row, value ?? !wasCurrentRowChecked, {
1881
+ batch: !!enableBatchRowSelection && enableMultiRowSelection !== false && event.shiftKey,
1882
+ lastSelectedRowId: lastSelectedRowId.value
1883
+ });
1884
+ lastSelectedRowId.value = row.id;
1885
+ return;
1886
+ }
991
1887
  row.toggleSelected(value ?? !wasCurrentRowChecked);
992
1888
  const changedRowIds = new Set([row.id]);
993
1889
  if (enableBatchRowSelection && enableMultiRowSelection && event.shiftKey && lastSelectedRowId.value !== null) {
@@ -1048,7 +1944,10 @@ var MVT_SelectCheckbox = defineComponent({
1048
1944
  const o = table.options;
1049
1945
  const state = table.getState();
1050
1946
  const selectAll = !row;
1051
- const checked = selectAll ? o.selectAllMode === "page" ? table.getIsAllPageRowsSelected() : table.getIsAllRowsSelected() : getIsRowSelected({
1947
+ const anyTable = table;
1948
+ const serverGroupingSummary = selectAll && getServerGroupingManager(anyTable) ? getServerGroupingSelectionSummary(anyTable) : void 0;
1949
+ const isServerGrouping = !!getServerGroupingManager(anyTable);
1950
+ const checked = serverGroupingSummary ? serverGroupingSummary.isAll : selectAll ? o.selectAllMode === "page" ? table.getIsAllPageRowsSelected() : table.getIsAllRowsSelected() : isServerGrouping && row ? isServerGroupingRecordSelected(anyTable, row) : getIsRowSelected({
1052
1951
  row,
1053
1952
  table
1054
1953
  });
@@ -1064,19 +1963,18 @@ var MVT_SelectCheckbox = defineComponent({
1064
1963
  renderedRowIndex: props.renderedRowIndex,
1065
1964
  row,
1066
1965
  table
1067
- }) : getMVT_SelectAllHandler({ table });
1966
+ }) : serverGroupingSummary ? (event) => toggleAllServerGroupingRecordsSelected(anyTable, event.target?.checked ?? !serverGroupingSummary.isAll) : getMVT_SelectAllHandler({ table });
1068
1967
  const common = {
1069
1968
  "aria-label": label,
1070
1969
  checked,
1071
- disabled: state.isLoading || row && !row.getCanSelect() || row?.id === "mvt-row-create",
1970
+ disabled: state.isLoading || row && !row.getCanSelect() || row?.id === "mvt-row-create" || serverGroupingSummary?.selectableCount === 0 && serverGroupingSummary.selectedRowIds.length === 0,
1072
1971
  size: state.density === "xs" ? "sm" : "md",
1073
1972
  ...checkboxProps,
1074
1973
  title: void 0,
1075
- onChange: (event) => {
1076
- event.stopPropagation();
1077
- if (event.shiftKey === void 0) event.shiftKey = lastShiftKey;
1078
- selection(event);
1079
- checkboxProps.onChange?.(event);
1974
+ onChange: (nextChecked) => {
1975
+ selection({ shiftKey: lastShiftKey }, nextChecked);
1976
+ checkboxProps.onChange?.(nextChecked);
1977
+ lastShiftKey = false;
1080
1978
  },
1081
1979
  onClick: (event) => {
1082
1980
  event.stopPropagation();
@@ -1085,7 +1983,7 @@ var MVT_SelectCheckbox = defineComponent({
1085
1983
  }
1086
1984
  };
1087
1985
  const control = o.selectDisplayMode === "switch" ? h(Switch, common) : o.selectDisplayMode === "radio" || o.enableMultiRowSelection === false ? h(Radio, common) : h(Checkbox, {
1088
- indeterminate: !checked && selectAll ? table.getIsSomeRowsSelected() : row?.getIsSomeSelected() && row.getCanSelectSubRows(),
1986
+ indeterminate: serverGroupingSummary ? serverGroupingSummary.isSome : !checked && selectAll ? table.getIsSomeRowsSelected() : row?.getIsSomeSelected() && row.getCanSelectSubRows(),
1089
1987
  ...common
1090
1988
  });
1091
1989
  return h(Tooltip, {
@@ -1215,12 +2113,14 @@ var MVT_Default_Icons = {
1215
2113
  //#region src/locales/en.ts
1216
2114
  var MVT_Localization_EN = {
1217
2115
  actions: "Actions",
2116
+ allMatchingRecordsSelected: "All records matching the current filters are selected",
1218
2117
  and: "and",
1219
2118
  cancel: "Cancel",
1220
2119
  changeFilterMode: "Change filter mode",
1221
2120
  changeSearchMode: "Change search mode",
1222
2121
  clearFilter: "Clear filter",
1223
2122
  clearSearch: "Clear search",
2123
+ clearGrouping: "Clear grouping",
1224
2124
  clearSelection: "Clear selection",
1225
2125
  clearSort: "Clear sort",
1226
2126
  clickToCopy: "Click to copy",
@@ -1231,6 +2131,7 @@ var MVT_Localization_EN = {
1231
2131
  copiedToClipboard: "Copied to clipboard",
1232
2132
  dropToGroupBy: "Drop to group by {column}",
1233
2133
  edit: "Edit",
2134
+ errorLoadingData: "Error loading data",
1234
2135
  expand: "Expand",
1235
2136
  expandAll: "Expand all",
1236
2137
  filterArrIncludes: "Includes",
@@ -1263,13 +2164,18 @@ var MVT_Localization_EN = {
1263
2164
  goToNextPage: "Go to next page",
1264
2165
  goToPreviousPage: "Go to previous page",
1265
2166
  grab: "Grab",
2167
+ groupBy: "Group by",
1266
2168
  groupByColumn: "Group by {column}",
1267
2169
  groupedBy: "Grouped by ",
1268
2170
  hideAll: "Hide all",
1269
2171
  hideColumn: "Hide {column} column",
2172
+ loading: "Loading…",
1270
2173
  max: "Max",
1271
2174
  min: "Min",
1272
2175
  move: "Move",
2176
+ moveDown: "Move down",
2177
+ moveUp: "Move up",
2178
+ noGroupableColumns: "No groupable columns",
1273
2179
  noRecordsToDisplay: "No records to display",
1274
2180
  noResultsFound: "No results found",
1275
2181
  of: "of",
@@ -1279,6 +2185,7 @@ var MVT_Localization_EN = {
1279
2185
  pinToRight: "Pin to right",
1280
2186
  resetColumnSize: "Reset column size",
1281
2187
  resetOrder: "Reset order",
2188
+ retry: "Retry",
1282
2189
  rowActions: "Row Actions",
1283
2190
  rowNumber: "#",
1284
2191
  rowNumbers: "Row Numbers",
@@ -1286,7 +2193,9 @@ var MVT_Localization_EN = {
1286
2193
  save: "Save",
1287
2194
  search: "Search",
1288
2195
  selectedCountOfRowCountRowsSelected: "{selectedCount} of {rowCount} row(s) selected",
2196
+ selectedCountRowsSelected: "{selectedCount} row(s) selected",
1289
2197
  select: "Select",
2198
+ selectAllMatching: "Select all matching records",
1290
2199
  showAll: "Show all",
1291
2200
  showAllColumns: "Show all columns",
1292
2201
  showHideColumns: "Show/Hide columns",
@@ -1373,6 +2282,33 @@ var useMVT_TableOptions = (rawOptions) => {
1373
2282
  manualPagination = true;
1374
2283
  manualSorting = true;
1375
2284
  }
2285
+ if (rest.serverGrouping?.provider && rest.serverGrouping.enabled !== false) {
2286
+ 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.");
2287
+ manualFiltering = true;
2288
+ manualPagination = true;
2289
+ manualSorting = true;
2290
+ if (rawOptions.groupedColumnMode === void 0) rest.groupedColumnMode = false;
2291
+ const configuredPageSize = rest.serverGrouping.pagination?.defaultPageSize ?? rest.serverGrouping.initialPageSize;
2292
+ const seededPageSize = Number.isInteger(configuredPageSize) && configuredPageSize > 0 ? configuredPageSize : void 0;
2293
+ if (seededPageSize && rawOptions.state?.pagination === void 0) rest.initialState = {
2294
+ ...rest.initialState,
2295
+ pagination: {
2296
+ pageIndex: rest.initialState?.pagination?.pageIndex ?? 0,
2297
+ pageSize: rest.initialState?.pagination?.pageSize ?? seededPageSize
2298
+ }
2299
+ };
2300
+ const { defaultGrouping } = rest.serverGrouping;
2301
+ if (defaultGrouping?.length && !rest.serverGrouping.grouping && rawOptions.state?.grouping === void 0 && rest.initialState?.grouping === void 0) rest.initialState = {
2302
+ ...rest.initialState,
2303
+ grouping: [...defaultGrouping]
2304
+ };
2305
+ const configuredFields = [...rest.serverGrouping.grouping ?? [], ...defaultGrouping ?? []];
2306
+ if (configuredFields.length) {
2307
+ const knownFields = new Set([...getAllLeafColumnDefs(rawOptions.columns).map((col) => getColumnId(col)), ...rest.serverGrouping.groupBy?.columns ?? []]);
2308
+ const unknownFields = [...new Set(configuredFields)].filter((field) => !knownFields.has(field));
2309
+ 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.`);
2310
+ }
2311
+ }
1376
2312
  const definedOptions = {
1377
2313
  aggregationFns,
1378
2314
  autoResetExpanded,
@@ -1621,6 +2557,12 @@ var useMVT_TableInstance = (definedTableOptions) => {
1621
2557
  get: getter
1622
2558
  });
1623
2559
  };
2560
+ let serverGroupingManager;
2561
+ defineState("serverGroupingExpanded", () => serverGroupingManager?.getExpanded() ?? {});
2562
+ defineState("serverGroupingSelectAll", () => serverGroupingManager?.getSelectAll() ?? {
2563
+ active: false,
2564
+ excludedRowIds: []
2565
+ });
1624
2566
  defineState("columnFilterFns", () => columnFilterFns.value);
1625
2567
  defineState("columnOrder", () => columnOrder.value);
1626
2568
  defineState("columnSizingInfo", () => columnSizingInfo.value);
@@ -1723,6 +2665,58 @@ var useMVT_TableInstance = (definedTableOptions) => {
1723
2665
  table.setShowColumnFilters = statefulTableOptions.onShowColumnFiltersChange ?? ((updater) => applyUpdater(showColumnFilters, updater));
1724
2666
  table.setShowGlobalFilter = statefulTableOptions.onShowGlobalFilterChange ?? ((updater) => applyUpdater(showGlobalFilter, updater));
1725
2667
  table.setShowToolbarDropZone = statefulTableOptions.onShowToolbarDropZoneChange ?? ((updater) => applyUpdater(showToolbarDropZone, updater));
2668
+ serverGroupingManager = createMVT_ServerGroupingManager(table, () => userStateKeys.has("serverGroupingExpanded") ? readUserState().serverGroupingExpanded : void 0, () => userStateKeys.has("serverGroupingSelectAll") ? readUserState().serverGroupingSelectAll : void 0);
2669
+ table._serverGrouping = serverGroupingManager;
2670
+ if (serverGroupingManager) {
2671
+ const readUserRowCount = Object.getOwnPropertyDescriptor(definedTableOptions, "rowCount")?.get;
2672
+ Object.defineProperty(definedTableOptions, "rowCount", {
2673
+ configurable: true,
2674
+ enumerable: true,
2675
+ get: () => readUserRowCount?.call(definedTableOptions) ?? serverGroupingManager?.getPathState("__root__")?.rowCount
2676
+ });
2677
+ }
2678
+ table.getServerGroupingState = () => serverGroupingManager?.getState() ?? {
2679
+ enabled: false,
2680
+ expanded: {},
2681
+ grouping: [],
2682
+ paths: {}
2683
+ };
2684
+ table.getServerGroupingPathState = (pathId) => serverGroupingManager?.getPathState(pathId);
2685
+ table.expandServerGroup = (pathId) => serverGroupingManager?.expand(pathId);
2686
+ table.collapseServerGroup = (pathId) => serverGroupingManager?.collapse(pathId);
2687
+ table.toggleServerGroup = (pathId) => serverGroupingManager?.toggle(pathId);
2688
+ table.reloadServerGrouping = () => serverGroupingManager?.reload();
2689
+ table.reloadServerGroupingPath = (pathId) => serverGroupingManager?.reload(pathId);
2690
+ table.invalidateServerGrouping = () => serverGroupingManager?.invalidate();
2691
+ table.invalidateServerGroupingPath = (pathId) => serverGroupingManager?.invalidate(pathId);
2692
+ table.resetServerGroupingState = () => serverGroupingManager?.reset();
2693
+ table.setServerGroupingExpanded = (updater) => serverGroupingManager?.setExpanded(updater);
2694
+ table.setServerGroupingPagination = (pathId, pagination) => serverGroupingManager?.setPagination(pathId, pagination);
2695
+ table.setServerGroupingSorting = (pathId, sorting) => serverGroupingManager?.setSorting(pathId, sorting);
2696
+ table.setServerGroupingColumnFilters = (pathId, columnFilters) => serverGroupingManager?.setColumnFilters(pathId, columnFilters);
2697
+ table.setServerGroupingGlobalFilter = (pathId, globalFilter) => serverGroupingManager?.setGlobalFilter(pathId, globalFilter);
2698
+ table.getServerGroupingSelectionSummary = () => serverGroupingManager ? getServerGroupingSelectionSummary(table) : {
2699
+ excludedRowIds: [],
2700
+ isAll: false,
2701
+ isSelectAllMatching: false,
2702
+ isSome: false,
2703
+ mode: "include",
2704
+ selectableCount: 0,
2705
+ selectedCount: 0,
2706
+ selectedRowIds: []
2707
+ };
2708
+ table.toggleAllServerGroupingRecordsSelected = (value) => {
2709
+ if (serverGroupingManager) toggleAllServerGroupingRecordsSelected(table, value);
2710
+ };
2711
+ table.selectAllMatchingServerGroupingRecords = async () => {
2712
+ if (serverGroupingManager) await selectAllMatchingServerGroupingRecords(table);
2713
+ };
2714
+ table.getServerGroupingSelectAllState = () => serverGroupingManager?.getSelectAll() ?? {
2715
+ active: false,
2716
+ excludedRowIds: []
2717
+ };
2718
+ table.setServerGroupingSelectAllState = (updater) => serverGroupingManager?.setSelectAll(updater);
2719
+ table.getServerGroupingSelectionPayload = () => getServerGroupingSelectionPayload(table);
1726
2720
  table._mvtSlots = mvtSlots;
1727
2721
  table.setMVTSlots = (slots) => {
1728
2722
  mvtSlots.value = slots;
@@ -1825,10 +2819,10 @@ var MVT_TablePagination = defineComponent({
1825
2819
  const { rowsPerPageOptions = defaultRowsPerPage, showRowsPerPage = true, withEdges = showEdges, ...rest } = paginationProps;
1826
2820
  const controls = o.paginationDisplayMode === "pages" ? h(Pagination, {
1827
2821
  total: numberOfPages,
1828
- value: pageIndex + 1,
2822
+ modelValue: pageIndex + 1,
1829
2823
  withEdges,
1830
2824
  ...rest,
1831
- onChange: (page) => table.setPageIndex(page - 1)
2825
+ "onUpdate:modelValue": (page) => table.setPageIndex(page - 1)
1832
2826
  }) : o.paginationDisplayMode === "default" ? [h(Text, null, () => `${lastRowIndex === 0 ? 0 : (firstRowIndex + 1).toLocaleString()}-${lastRowIndex.toLocaleString()} ${o.localization.of} ${totalRowCount.toLocaleString()}`), h(Group, { gap: 6 }, () => [
1833
2827
  withEdges && h(ActionIcon, {
1834
2828
  "aria-label": o.localization.goToFirstPage,
@@ -1864,8 +2858,8 @@ var MVT_TablePagination = defineComponent({
1864
2858
  "aria-labelledby": "rpp-label",
1865
2859
  class: MVT_TablePagination_module_default.pagesize,
1866
2860
  data: rowsPerPageOptions,
1867
- value: pageSize.toString(),
1868
- onChange: (value) => value && table.setPageSize(+value)
2861
+ modelValue: pageSize.toString(),
2862
+ "onUpdate:modelValue": (value) => value && table.setPageSize(+value)
1869
2863
  })]), controls]);
1870
2864
  };
1871
2865
  }
@@ -1905,26 +2899,50 @@ var MVT_ToolbarAlertBanner = defineComponent({
1905
2899
  const badgeProps = parseFromValuesOrFunc(o.mantineToolbarAlertBannerBadgeProps, { table });
1906
2900
  const total = o.rowCount ?? table.getPrePaginationRowModel().flatRows.length;
1907
2901
  const selectedCount = o.manualPagination ? Object.values(state.rowSelection).filter(Boolean).length : table.getFilteredSelectedRowModel().rows.length;
1908
- const selectedAlert = selectedCount ? h(Flex, {
2902
+ const serverGroupingSelection = o.serverGrouping?.selection;
2903
+ const serverGroupingSummary = table._serverGrouping ? table.getServerGroupingSelectionSummary() : void 0;
2904
+ const showSelectAllMatching = !!serverGroupingSelection?.enableSelectAllMatching && ((serverGroupingSelection.selectAllMode ?? "query") === "query" || !!serverGroupingSelection.loadAllMatchingRowIds) && !!serverGroupingSummary?.isAll && !serverGroupingSummary.isSelectAllMatching;
2905
+ const serverGroupingListsRecords = !serverGroupingSummary || table.getServerGroupingPathState("__root__")?.kind === "records";
2906
+ 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));
2907
+ const selectedAlert = selectedCount || serverGroupingSummary?.isSelectAllMatching ? h(Flex, {
1909
2908
  align: "center",
1910
2909
  gap: "sm"
1911
- }, () => [o.localization.selectedCountOfRowCountRowsSelected.replace("{selectedCount}", String(selectedCount)).replace("{rowCount}", String(total)), h(Button, {
1912
- size: "compact-xs",
1913
- variant: "subtle",
1914
- onClick: (event) => getMVT_SelectAllHandler({ table })(event, false, true)
1915
- }, () => o.localization.clearSelection)]) : null;
1916
- const groupedAlert = state.grouping.length ? h(Flex, null, () => [`${o.localization.groupedBy} `, ...state.grouping.flatMap((columnId, index) => [index > 0 ? o.localization.thenBy : null, h(Badge, {
1917
- key: columnId,
1918
- class: MVT_ToolbarAlertBanner_module_default["alert-badge"],
1919
- variant: "filled",
1920
- ...badgeProps,
1921
- rightSection: h(ActionIcon, {
1922
- color: "white",
1923
- size: "xs",
2910
+ }, () => [
2911
+ selectedText,
2912
+ showSelectAllMatching && h(Button, {
2913
+ size: "compact-xs",
1924
2914
  variant: "subtle",
1925
- onClick: () => table.getColumn(columnId).toggleGrouping()
1926
- }, () => h(o.icons.IconX, { style: { transform: "scale(0.8)" } }))
1927
- }, () => `${table.getColumn(columnId).columnDef.header} `)])]) : null;
2915
+ onClick: () => void table.selectAllMatchingServerGroupingRecords()
2916
+ }, () => o.localization.selectAllMatching ?? "Select all matching records"),
2917
+ h(Button, {
2918
+ size: "compact-xs",
2919
+ variant: "subtle",
2920
+ onClick: (event) => {
2921
+ if (serverGroupingSummary) {
2922
+ table.toggleAllServerGroupingRecordsSelected(false);
2923
+ return;
2924
+ }
2925
+ getMVT_SelectAllHandler({ table })(event, false, true);
2926
+ }
2927
+ }, () => o.localization.clearSelection)
2928
+ ]) : null;
2929
+ const groupedAlert = state.grouping.length ? h(Flex, null, () => [`${o.localization.groupedBy} `, ...state.grouping.flatMap((columnId, index) => {
2930
+ const column = table.getAllLeafColumns().find((col) => col.id === columnId);
2931
+ const header = column?.columnDef.header;
2932
+ const label = typeof header === "string" && header.length ? header : columnId;
2933
+ return [index > 0 ? o.localization.thenBy : null, h(Badge, {
2934
+ key: columnId,
2935
+ class: MVT_ToolbarAlertBanner_module_default["alert-badge"],
2936
+ variant: "filled",
2937
+ ...badgeProps,
2938
+ rightSection: h(ActionIcon, {
2939
+ color: "white",
2940
+ size: "xs",
2941
+ variant: "subtle",
2942
+ onClick: () => column ? column.toggleGrouping() : table.setGrouping((prev) => prev.filter((field) => field !== columnId))
2943
+ }, () => h(o.icons.IconX, { style: { transform: "scale(0.8)" } }))
2944
+ }, () => `${label} `)];
2945
+ })]) : null;
1928
2946
  const custom = slots.default?.({
1929
2947
  groupedAlert,
1930
2948
  selectedAlert,
@@ -2046,6 +3064,207 @@ var MVT_BottomToolbar = defineComponent({
2046
3064
  };
2047
3065
  }
2048
3066
  });
3067
+ var MVT_ServerGrouping_module_default = {
3068
+ "group-row": "_group-row_u9zpp_1",
3069
+ "row-grid": "_row-grid_u9zpp_7",
3070
+ "group-cell": "_group-cell_u9zpp_11",
3071
+ "aggregate-cell": "_aggregate-cell_u9zpp_15",
3072
+ "expand-spacer": "_expand-spacer_u9zpp_19",
3073
+ "aux-row": "_aux-row_u9zpp_24",
3074
+ "aux-cell": "_aux-cell_u9zpp_28",
3075
+ pagination: "_pagination_u9zpp_32",
3076
+ pagesize: "_pagesize_u9zpp_36",
3077
+ "groupby-control": "_groupby-control_u9zpp_40",
3078
+ "groupby-active-row": "_groupby-active-row_u9zpp_45",
3079
+ "groupby-active-label": "_groupby-active-label_u9zpp_52"
3080
+ };
3081
+ //#endregion
3082
+ //#region src/server-grouping/MVT_ServerGroupingGroupBy.ts
3083
+ /**
3084
+ * Resolve the columns/fields offered by the group-by toolbar control.
3085
+ *
3086
+ * With `serverGrouping.groupBy.columns` set, exactly that whitelist is used
3087
+ * (entries may be custom descriptors like `'createdAt:month'`). Otherwise
3088
+ * every leaf `data` column whose `enableGrouping` is not `false` is offered —
3089
+ * display columns and columns with `enableGrouping: false` never appear.
3090
+ */
3091
+ var getServerGroupableColumns = (table) => {
3092
+ const groupByOptions = table.options.serverGrouping?.groupBy;
3093
+ const getFieldLabel = groupByOptions?.getFieldLabel;
3094
+ const labelFor = (field) => {
3095
+ if (getFieldLabel) return getFieldLabel(field, table);
3096
+ const header = table.getAllLeafColumns().find((leafColumn) => leafColumn.id === field)?.columnDef.header;
3097
+ return typeof header === "string" && header.length ? header : field;
3098
+ };
3099
+ if (groupByOptions?.columns) return groupByOptions.columns.map((field) => ({
3100
+ id: field,
3101
+ label: labelFor(field)
3102
+ }));
3103
+ return table.getAllLeafColumns().filter((column) => column.columnDef.columnDefType === "data" && column.columnDef.enableGrouping !== false).map((column) => ({
3104
+ id: column.id,
3105
+ label: labelFor(column.id)
3106
+ }));
3107
+ };
3108
+ /** Build the scoped context handed to the group-by slot / render callback. */
3109
+ var getServerGroupingGroupByContext = (table, manager) => {
3110
+ const grouping = manager.getGroupingFields();
3111
+ const setGrouping = (next) => table.setGrouping(next);
3112
+ return {
3113
+ addGroup: (field) => {
3114
+ if (!grouping.includes(field)) setGrouping([...grouping, field]);
3115
+ },
3116
+ clearGrouping: () => setGrouping([]),
3117
+ groupableColumns: getServerGroupableColumns(table),
3118
+ grouping,
3119
+ moveGroup: (field, direction) => {
3120
+ const index = grouping.indexOf(field);
3121
+ const target = index + direction;
3122
+ if (index === -1 || target < 0 || target >= grouping.length) return;
3123
+ const next = [...grouping];
3124
+ [next[index], next[target]] = [next[target], next[index]];
3125
+ setGrouping(next);
3126
+ },
3127
+ removeGroup: (field) => setGrouping(grouping.filter((activeField) => activeField !== field)),
3128
+ table
3129
+ };
3130
+ };
3131
+ /**
3132
+ * Grouping actions for one column's action menu, or `undefined` when the
3133
+ * column cannot be grouped by.
3134
+ *
3135
+ * Uses exactly the same rules as the toolbar "Group by" control: server
3136
+ * grouping must be active and driven by the table's `grouping` state, the
3137
+ * control must not be disabled, and the column must be offered by
3138
+ * {@link getServerGroupableColumns}.
3139
+ */
3140
+ var getServerGroupingColumnActions = (table, columnId) => {
3141
+ const manager = table._serverGrouping;
3142
+ if (!manager) return void 0;
3143
+ const groupByOptions = manager.options.groupBy ?? {};
3144
+ if (groupByOptions.enabled === false || groupByOptions.showInColumnActions === false) return;
3145
+ if (manager.options.grouping && groupByOptions.enabled !== true) return void 0;
3146
+ const context = getServerGroupingGroupByContext(table, manager);
3147
+ return context.groupableColumns.some((column) => column.id === columnId) ? context : void 0;
3148
+ };
3149
+ /**
3150
+ * Built-in group-by toolbar control for server-side grouping. Renders a
3151
+ * "Group by" menu (add / reorder / remove / clear levels) plus the active
3152
+ * levels as removable pills. Hidden when server grouping is inactive, when
3153
+ * `groupBy.enabled` is `false`, or when grouping is a static
3154
+ * `serverGrouping.grouping` array (which the control could not change).
3155
+ */
3156
+ var MVT_ServerGroupingGroupBy = defineComponent({
3157
+ name: "MVTServerGroupingGroupBy",
3158
+ inheritAttrs: false,
3159
+ props: { table: {
3160
+ type: Object,
3161
+ required: true
3162
+ } },
3163
+ setup(props) {
3164
+ const mvtSlots = useMVT_Slots();
3165
+ return () => {
3166
+ const table = props.table;
3167
+ const manager = table._serverGrouping;
3168
+ if (!manager) return null;
3169
+ const sgOptions = manager.options;
3170
+ const groupByOptions = sgOptions.groupBy ?? {};
3171
+ if (groupByOptions.enabled === false) return null;
3172
+ if (sgOptions.grouping && groupByOptions.enabled !== true) return null;
3173
+ const localization = table.options.localization;
3174
+ const icons = table.options.icons;
3175
+ const allowReorder = groupByOptions.allowReorder ?? true;
3176
+ const allowClearAll = groupByOptions.allowClearAll ?? true;
3177
+ const context = getServerGroupingGroupByContext(table, manager);
3178
+ const { addGroup, clearGrouping, groupableColumns, grouping, moveGroup, removeGroup } = context;
3179
+ const custom = mvtSlots.serverGroupByControl?.(context) ?? parseFromValuesOrFunc(groupByOptions.renderControl, context);
3180
+ if (custom !== void 0 && custom !== null) return custom;
3181
+ const labelFor = (field) => groupableColumns.find((column) => column.id === field)?.label ?? field;
3182
+ const activeRows = grouping.map((field, index) => h(Box, {
3183
+ class: MVT_ServerGrouping_module_default["groupby-active-row"],
3184
+ key: field
3185
+ }, () => [
3186
+ allowReorder && h(ActionIcon, {
3187
+ "aria-label": `${localization.moveUp ?? "Move up"} ${labelFor(field)}`,
3188
+ color: "gray",
3189
+ disabled: index === 0,
3190
+ onClick: () => moveGroup(field, -1),
3191
+ size: "xs",
3192
+ variant: "subtle"
3193
+ }, () => h(icons.IconChevronDown, { style: { transform: "rotate(180deg)" } })),
3194
+ allowReorder && h(ActionIcon, {
3195
+ "aria-label": `${localization.moveDown ?? "Move down"} ${labelFor(field)}`,
3196
+ color: "gray",
3197
+ disabled: index === grouping.length - 1,
3198
+ onClick: () => moveGroup(field, 1),
3199
+ size: "xs",
3200
+ variant: "subtle"
3201
+ }, () => h(icons.IconChevronDown)),
3202
+ h(Text, {
3203
+ class: MVT_ServerGrouping_module_default["groupby-active-label"],
3204
+ size: "sm"
3205
+ }, () => `${index + 1}. ${labelFor(field)}`),
3206
+ h(ActionIcon, {
3207
+ "aria-label": (localization.ungroupByColumn ?? "Ungroup by {column}").replace("{column}", labelFor(field)),
3208
+ color: "gray",
3209
+ onClick: () => removeGroup(field),
3210
+ size: "xs",
3211
+ variant: "subtle"
3212
+ }, () => h(icons.IconX))
3213
+ ]));
3214
+ const menu = h(Menu, {
3215
+ closeOnItemClick: false,
3216
+ position: "bottom-start",
3217
+ shadow: "md",
3218
+ width: 260,
3219
+ ...groupByOptions.mantineMenuProps
3220
+ }, () => [h(Menu.Target, null, () => h(Button, {
3221
+ size: "xs",
3222
+ variant: "default",
3223
+ ...groupByOptions.mantineButtonProps,
3224
+ leftSection: groupByOptions.mantineButtonProps?.leftSection ?? h(icons.IconColumns)
3225
+ }, () => localization.groupBy ?? "Group by")), h(Menu.Dropdown, null, () => [
3226
+ groupableColumns.length ? groupableColumns.map((column) => h(Menu.Item, {
3227
+ disabled: grouping.includes(column.id),
3228
+ key: column.id,
3229
+ onClick: () => addGroup(column.id)
3230
+ }, () => column.label)) : h(Menu.Label, null, () => localization.noGroupableColumns ?? "No groupable columns"),
3231
+ grouping.length > 0 && [
3232
+ h(Menu.Divider),
3233
+ h(Menu.Label, null, () => (localization.groupedBy ?? "Grouped by ").trim()),
3234
+ ...activeRows
3235
+ ],
3236
+ allowClearAll && grouping.length > 0 && [h(Menu.Divider), h(Menu.Item, {
3237
+ color: "red",
3238
+ onClick: () => clearGrouping()
3239
+ }, () => localization.clearGrouping ?? "Clear grouping")]
3240
+ ])]);
3241
+ const pills = grouping.length > 0 && h(PillGroup, { gap: 4 }, () => grouping.map((field, index) => {
3242
+ const pillProps = parseFromValuesOrFunc(groupByOptions.mantinePillProps, {
3243
+ field,
3244
+ index
3245
+ }) ?? {};
3246
+ return h(Pill, {
3247
+ size: "sm",
3248
+ withRemoveButton: true,
3249
+ ...pillProps,
3250
+ key: field,
3251
+ onRemove: () => removeGroup(field),
3252
+ removeButtonProps: {
3253
+ "aria-label": (localization.ungroupByColumn ?? "Ungroup by {column}").replace("{column}", labelFor(field)),
3254
+ ...pillProps?.removeButtonProps
3255
+ }
3256
+ }, () => `${index + 1}. ${labelFor(field)}`);
3257
+ }));
3258
+ return h(Box, {
3259
+ class: clsx("mvt-server-groupby-control", MVT_ServerGrouping_module_default["groupby-control"]),
3260
+ style: {
3261
+ display: "flex",
3262
+ gap: "8px"
3263
+ }
3264
+ }, () => [menu, pills]);
3265
+ };
3266
+ }
3267
+ });
2049
3268
  var MVT_FilterOptionMenu_module_default = { symbol: "_symbol_1b3vj_1" };
2050
3269
  //#endregion
2051
3270
  //#region src/components/menus/MVT_FilterOptionMenu.ts
@@ -2434,7 +3653,7 @@ var MVT_ShowHideColumnsMenuItems = defineComponent({
2434
3653
  openDelay: 1e3,
2435
3654
  withinPortal: true
2436
3655
  }, () => h(Switch, {
2437
- checked,
3656
+ modelValue: checked,
2438
3657
  class: MVT_ShowHideColumnsMenuItems_module_default.switch,
2439
3658
  disabled: !column.getCanHide(),
2440
3659
  label: def.header,
@@ -2753,6 +3972,7 @@ var MVT_TopToolbar = defineComponent({
2753
3972
  ["both", "top"].includes(positionToolbarDropZone ?? "") && h(MVT_ToolbarDropZone, { table }),
2754
3973
  h(Flex, { class: [MVT_TopToolbar_module_default["actions-container"], stackAlertBanner ? MVT_TopToolbar_module_default["actions-container-stack-alert"] : void 0] }, () => [
2755
3974
  enableGlobalFilter && positionGlobalFilter === "left" && h(MVT_GlobalFilterTextInput, globalFilterProps),
3975
+ table._serverGrouping && h(MVT_ServerGroupingGroupBy, { table }),
2756
3976
  parseFromValuesOrFunc(renderTopToolbarCustomActions, { table }) ?? h("span"),
2757
3977
  enableToolbarInternalActions ? h(Flex, {
2758
3978
  justify: "end",
@@ -2929,6 +4149,21 @@ var useMVT_ColumnVirtualizer = (table) => {
2929
4149
  //#endregion
2930
4150
  //#region src/utils/style.utils.ts
2931
4151
  var parseCSSVarId = (id) => id.replace(/[^a-zA-Z0-9]/g, "_");
4152
+ /**
4153
+ * Width/flex styles that bind a cell to its column's live size variables, so
4154
+ * custom cells (server-grouping group rows, …) stay aligned with the root
4155
+ * table while columns are resized or reordered.
4156
+ */
4157
+ var getMVT_ColumnWidthStyles = ({ columnId, grow, layoutMode, minSize }) => {
4158
+ const cssVar = `--col-${parseCSSVarId(columnId)}-size`;
4159
+ const styles = {
4160
+ minWidth: `max(calc(var(${cssVar}) * 1px), ${minSize ?? 30}px)`,
4161
+ width: `calc(var(${cssVar}) * 1px)`
4162
+ };
4163
+ if (layoutMode === "grid") styles.flex = `${[0, false].includes(grow) ? 0 : `var(${cssVar})`} 0 auto`;
4164
+ else if (layoutMode === "grid-no-grow") styles.flex = `${+(grow || 0)} 0 auto`;
4165
+ return styles;
4166
+ };
2932
4167
  var getPrimaryShade = (theme) => typeof theme.primaryShade === "number" ? theme.primaryShade : theme.primaryShade?.dark ?? 7;
2933
4168
  var getPrimaryColor = (theme, shade) => theme.colors[theme.primaryColor][shade ?? getPrimaryShade(theme)];
2934
4169
  function dataVariable(name, value) {
@@ -3256,8 +4491,9 @@ var MVT_TableBodyCell = defineComponent({
3256
4491
  if (!columnDef.enableCellHoverReveal) return;
3257
4492
  isCellContentOverflowing.value = false;
3258
4493
  };
4494
+ const isServerGrouping = !!table._serverGrouping;
3259
4495
  const renderCellContent = () => {
3260
- if (cell.getIsPlaceholder()) return columnDef.PlaceholderCell?.({
4496
+ if (!isServerGrouping && cell.getIsPlaceholder()) return columnDef.PlaceholderCell?.({
3261
4497
  cell,
3262
4498
  column,
3263
4499
  row,
@@ -3583,6 +4819,271 @@ var MVT_TableBodyRow = defineComponent({
3583
4819
  }
3584
4820
  });
3585
4821
  var Memo_MVT_TableBodyRow = MVT_TableBodyRow;
4822
+ //#endregion
4823
+ //#region src/server-grouping/MVT_ServerGroupingBody.ts
4824
+ var INDENT_PX = 24;
4825
+ /** Renders the server-grouping hierarchy as rows of the root table body. */
4826
+ var MVT_ServerGroupingBody = defineComponent({
4827
+ name: "MVTServerGroupingBody",
4828
+ inheritAttrs: false,
4829
+ props: {
4830
+ table: {
4831
+ type: Object,
4832
+ required: true
4833
+ },
4834
+ tableProps: {
4835
+ type: Object,
4836
+ required: true
4837
+ }
4838
+ },
4839
+ setup(props) {
4840
+ const mvtSlots = useMVT_Slots();
4841
+ return () => {
4842
+ const { tableProps } = props;
4843
+ const table = props.table;
4844
+ const manager = table._serverGrouping;
4845
+ if (!manager) return null;
4846
+ const { options: sgOptions } = manager;
4847
+ const tableOptions = table.options;
4848
+ const localization = tableOptions.localization;
4849
+ const icons = tableOptions.icons;
4850
+ const visibleColumns = table.getVisibleLeafColumns();
4851
+ const colSpan = visibleColumns.length || 1;
4852
+ const layoutMode = tableOptions.layoutMode;
4853
+ const paginationOptions = {
4854
+ enabled: sgOptions.pagination?.enabled ?? true,
4855
+ mantineActionIconProps: sgOptions.pagination?.mantineActionIconProps ?? {},
4856
+ showAtRoot: sgOptions.pagination?.showAtRoot ?? (tableOptions.enablePagination === false || tableOptions.positionPagination === "none"),
4857
+ showForGroups: sgOptions.pagination?.showForGroups ?? true,
4858
+ showForRecords: sgOptions.pagination?.showForRecords ?? true
4859
+ };
4860
+ const indentStyle = (depth) => ({ paddingInlineStart: `${8 + depth * INDENT_PX}px` });
4861
+ const columnStyle = (column, extra) => ({
4862
+ ...getMVT_ColumnWidthStyles({
4863
+ columnId: column.id,
4864
+ grow: column.columnDef.grow,
4865
+ layoutMode,
4866
+ minSize: column.columnDef.minSize
4867
+ }),
4868
+ ...extra
4869
+ });
4870
+ const auxRow = (key, depth, children) => h(TableTr, {
4871
+ class: clsx(MVT_ServerGrouping_module_default["aux-row"], layoutMode?.startsWith("grid") && MVT_ServerGrouping_module_default["row-grid"]),
4872
+ key
4873
+ }, () => h(TableTd, {
4874
+ class: MVT_ServerGrouping_module_default["aux-cell"],
4875
+ colspan: colSpan,
4876
+ style: {
4877
+ ...indentStyle(depth),
4878
+ ...layoutMode?.startsWith("grid") ? {
4879
+ flex: "1 0 auto",
4880
+ width: "100%"
4881
+ } : {}
4882
+ }
4883
+ }, () => children));
4884
+ const loadingContent = (pathId, depth) => mvtSlots.serverGroupLoading?.({
4885
+ depth,
4886
+ pathId,
4887
+ table
4888
+ }) ?? parseFromValuesOrFunc(sgOptions.renderGroupLoading, {
4889
+ depth,
4890
+ pathId,
4891
+ table
4892
+ }) ?? h(Group, { gap: "xs" }, () => [h(Loader, { size: "xs" }), h(Text, {
4893
+ c: "dimmed",
4894
+ size: "sm"
4895
+ }, () => localization.loading ?? "Loading…")]);
4896
+ const errorContent = (pathId, error, retry) => mvtSlots.serverGroupError?.({
4897
+ error,
4898
+ pathId,
4899
+ retry,
4900
+ table
4901
+ }) ?? parseFromValuesOrFunc(sgOptions.renderGroupError, {
4902
+ error,
4903
+ pathId,
4904
+ retry,
4905
+ table
4906
+ }) ?? h(Alert, {
4907
+ color: "red",
4908
+ role: "alert",
4909
+ variant: "light"
4910
+ }, () => h(Group, { gap: "sm" }, () => [h(Text, { size: "sm" }, () => localization.errorLoadingData ?? (error instanceof Error && error.message) ?? "Error loading data"), h(Button, {
4911
+ color: "red",
4912
+ onClick: retry,
4913
+ size: "compact-xs",
4914
+ variant: "outline"
4915
+ }, () => localization.retry ?? "Retry")]));
4916
+ const emptyContent = (pathId, field) => {
4917
+ const parentGroup = manager.getParentItems(pathId).at(-1);
4918
+ return mvtSlots.serverGroupEmpty?.({
4919
+ field,
4920
+ parentGroup,
4921
+ pathId,
4922
+ table
4923
+ }) ?? parseFromValuesOrFunc(sgOptions.renderGroupEmpty, {
4924
+ field,
4925
+ parentGroup,
4926
+ pathId,
4927
+ table
4928
+ }) ?? h(Text, {
4929
+ c: "dimmed",
4930
+ size: "sm"
4931
+ }, () => localization.noRecordsToDisplay ?? "No records to display");
4932
+ };
4933
+ const paginationRow = (pathId, depth, state) => {
4934
+ const isRoot = pathId === MVT_SERVER_GROUPING_ROOT_PATH_ID;
4935
+ const { pageIndex, pageSize } = state.pagination;
4936
+ const totalRowCount = state.rowCount;
4937
+ if (!(paginationOptions.enabled && (state.kind === "groups" ? paginationOptions.showForGroups : paginationOptions.showForRecords) && (!isRoot || paginationOptions.showAtRoot) && (totalRowCount > pageSize || pageIndex > 0))) return null;
4938
+ const firstRowIndex = pageIndex * pageSize;
4939
+ const lastRowIndex = Math.min(firstRowIndex + pageSize, totalRowCount);
4940
+ const setPageIndex = (nextPageIndex) => manager.setPagination(pathId, { pageIndex: nextPageIndex });
4941
+ return auxRow(`${pathId}:pagination`, depth, h(Group, {
4942
+ class: MVT_ServerGrouping_module_default.pagination,
4943
+ gap: "xs",
4944
+ wrap: "nowrap"
4945
+ }, () => [
4946
+ h(Text, {
4947
+ c: "dimmed",
4948
+ size: "sm"
4949
+ }, () => `${totalRowCount === 0 ? 0 : (firstRowIndex + 1).toLocaleString()}-${lastRowIndex.toLocaleString()} ${localization.of} ${totalRowCount.toLocaleString()}`),
4950
+ h(ActionIcon, {
4951
+ color: "gray",
4952
+ size: "sm",
4953
+ variant: "subtle",
4954
+ ...paginationOptions.mantineActionIconProps,
4955
+ "aria-label": localization.goToPreviousPage,
4956
+ disabled: pageIndex <= 0 || state.isFetching,
4957
+ onClick: () => setPageIndex(pageIndex - 1)
4958
+ }, () => h(icons.IconChevronLeft)),
4959
+ h(ActionIcon, {
4960
+ color: "gray",
4961
+ size: "sm",
4962
+ variant: "subtle",
4963
+ ...paginationOptions.mantineActionIconProps,
4964
+ "aria-label": localization.goToNextPage,
4965
+ disabled: lastRowIndex >= totalRowCount || state.isFetching,
4966
+ onClick: () => setPageIndex(pageIndex + 1)
4967
+ }, () => h(icons.IconChevronRight))
4968
+ ]));
4969
+ };
4970
+ const groupRow = (node, parentPathId, field, depth) => {
4971
+ const pathId = createServerGroupPathId(parentPathId, field, node.id);
4972
+ const expanded = manager.isExpanded(pathId);
4973
+ const childState = manager.getPathState(pathId);
4974
+ const context = {
4975
+ depth,
4976
+ field,
4977
+ group: node,
4978
+ isExpanded: expanded,
4979
+ parentGroups: manager.getParentItems(pathId).slice(0, -1),
4980
+ pathId,
4981
+ table
4982
+ };
4983
+ const hasChildren = node.hasChildren !== false;
4984
+ const rowProps = parseFromValuesOrFunc(sgOptions.mantineGroupRowProps, context) ?? {};
4985
+ const label = mvtSlots.serverGroupLabel?.(context) ?? parseFromValuesOrFunc(sgOptions.renderGroupLabel, context) ?? node.label;
4986
+ const count = mvtSlots.serverGroupCount?.(context) ?? parseFromValuesOrFunc(sgOptions.renderGroupCount, context) ?? (node.count !== void 0 ? `(${node.count.toLocaleString()})` : null);
4987
+ const labelColumn = visibleColumns.find((column) => column.columnDef.columnDefType !== "display");
4988
+ const labelCell = (column) => h(TableTd, {
4989
+ class: MVT_ServerGrouping_module_default["group-cell"],
4990
+ key: column?.id ?? "mvt-server-group-label",
4991
+ style: column ? columnStyle(column, indentStyle(depth)) : indentStyle(depth)
4992
+ }, () => h(Group, {
4993
+ gap: "xs",
4994
+ wrap: "nowrap"
4995
+ }, () => [
4996
+ hasChildren ? h(ActionIcon, {
4997
+ "aria-expanded": String(expanded),
4998
+ "aria-label": `${expanded ? localization.collapse : localization.expand} ${node.label}`,
4999
+ color: "gray",
5000
+ onClick: () => manager.toggle(pathId),
5001
+ size: "sm",
5002
+ variant: "subtle"
5003
+ }, () => h(expanded ? icons.IconChevronDown : icons.IconChevronRight)) : h("span", { class: MVT_ServerGrouping_module_default["expand-spacer"] }),
5004
+ h(Text, {
5005
+ fw: 600,
5006
+ size: "sm"
5007
+ }, () => [label]),
5008
+ count !== null && h(Text, {
5009
+ c: "dimmed",
5010
+ size: "sm"
5011
+ }, () => [count]),
5012
+ expanded && childState?.isFetching && !childState.isLoading && h(Loader, { size: "xs" })
5013
+ ]));
5014
+ const aggregateCell = (column) => {
5015
+ const columnServerGrouping = column.columnDef.serverGrouping;
5016
+ let content = null;
5017
+ if (columnServerGrouping?.visible !== false && columnServerGrouping?.getValue) {
5018
+ const value = columnServerGrouping.getValue({
5019
+ ...context,
5020
+ column
5021
+ });
5022
+ const cellContext = {
5023
+ ...context,
5024
+ column,
5025
+ value
5026
+ };
5027
+ content = mvtSlots.serverGroupCell?.(cellContext) ?? (columnServerGrouping.Cell ? flexRender(columnServerGrouping.Cell, cellContext) : value ?? null);
5028
+ } else if (mvtSlots.serverGroupCell) content = mvtSlots.serverGroupCell({
5029
+ ...context,
5030
+ column,
5031
+ value: void 0
5032
+ });
5033
+ return h(TableTd, {
5034
+ class: MVT_ServerGrouping_module_default["aggregate-cell"],
5035
+ key: column.id,
5036
+ style: columnStyle(column)
5037
+ }, () => [content]);
5038
+ };
5039
+ const spacerCell = (column) => h(TableTd, {
5040
+ key: column.id,
5041
+ style: columnStyle(column)
5042
+ }, () => null);
5043
+ const cells = visibleColumns.length ? visibleColumns.map((column) => column.id === labelColumn?.id ? labelCell(column) : column.columnDef.columnDefType === "display" ? spacerCell(column) : aggregateCell(column)) : [labelCell()];
5044
+ const rows = [h(TableTr, {
5045
+ "aria-expanded": hasChildren ? String(expanded) : void 0,
5046
+ "aria-level": depth + 1,
5047
+ "data-depth": depth,
5048
+ "data-expanded": expanded || void 0,
5049
+ key: pathId,
5050
+ ...rowProps,
5051
+ class: clsx(MVT_ServerGrouping_module_default["group-row"], layoutMode?.startsWith("grid") && MVT_ServerGrouping_module_default["row-grid"], rowProps?.class)
5052
+ }, () => cells)];
5053
+ if (expanded) rows.push(...levelRows(pathId, depth + 1));
5054
+ return rows;
5055
+ };
5056
+ const recordRows = (pathId) => {
5057
+ const rows = manager.getRecordRows(pathId);
5058
+ return rows.map((row, index) => h(MVT_TableBodyRow, {
5059
+ key: row.id,
5060
+ numRows: rows.length,
5061
+ renderedRowIndex: index,
5062
+ row,
5063
+ table,
5064
+ tableProps
5065
+ }));
5066
+ };
5067
+ const levelRows = (pathId, depth) => {
5068
+ const state = manager.getPathState(pathId);
5069
+ const field = manager.getGroupingFields()[getServerGroupPathDepth(pathId)];
5070
+ if (!state || state.isLoading) return [auxRow(`${pathId}:loading`, depth, loadingContent(pathId, depth))];
5071
+ if (state.error != null) return [auxRow(`${pathId}:error`, depth, errorContent(pathId, state.error, () => manager.retry(pathId)))];
5072
+ const out = [];
5073
+ if (state.kind === "groups") {
5074
+ const groups = state.groups ?? [];
5075
+ if (!groups.length) out.push(auxRow(`${pathId}:empty`, depth, emptyContent(pathId, field)));
5076
+ else groups.forEach((node) => out.push(...groupRow(node, pathId, field, depth)));
5077
+ } else if (!(state.rows ?? []).length) out.push(auxRow(`${pathId}:empty`, depth, emptyContent(pathId, field)));
5078
+ else out.push(...recordRows(pathId));
5079
+ const pagination = paginationRow(pathId, depth, state);
5080
+ if (pagination) out.push(pagination);
5081
+ return out;
5082
+ };
5083
+ return h(Fragment, null, levelRows(MVT_SERVER_GROUPING_ROOT_PATH_ID, 0));
5084
+ };
5085
+ }
5086
+ });
3586
5087
  var MVT_TableBody_module_default = {
3587
5088
  root: "_root_17rwk_1",
3588
5089
  "root-grid": "_root-grid_17rwk_6",
@@ -3712,7 +5213,10 @@ var MVT_TableBody = defineComponent({
3712
5213
  ...tableBodyProps?.style
3713
5214
  },
3714
5215
  class: clsx(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)
3715
- }, () => tableBodyProps?.children ?? (!currentRows.length ? h(MVT_TableBodyEmptyRow, commonRowProps) : (virtualRows ?? currentRows).map((rowOrVirtualRow, renderedRowIndex) => {
5216
+ }, () => tableBodyProps?.children ?? (table._serverGrouping ? h(MVT_ServerGroupingBody, {
5217
+ table,
5218
+ tableProps
5219
+ }) : null) ?? (!currentRows.length ? h(MVT_TableBodyEmptyRow, commonRowProps) : (virtualRows ?? currentRows).map((rowOrVirtualRow, renderedRowIndex) => {
3716
5220
  let index = renderedRowIndex;
3717
5221
  if (rowVirtualizer) if (renderDetailPanel) {
3718
5222
  if (rowOrVirtualRow.index % 2 === 1) return null;
@@ -3980,6 +5484,7 @@ var MVT_ColumnActionMenu = defineComponent({
3980
5484
  leftSection: h(icon, { class: iconClass }),
3981
5485
  onClick
3982
5486
  }, () => label);
5487
+ const serverGroupBy = getServerGroupingColumnActions(table, column.id);
3983
5488
  const internal = [];
3984
5489
  if (o.enableSorting && column.getCanSort()) {
3985
5490
  if (o.enableSortingRemoval !== false) internal.push(item(l.clearSort, icons.IconClearAll, () => column.clearSorting(), !column.getIsSorted()));
@@ -4001,6 +5506,11 @@ var MVT_ColumnActionMenu = defineComponent({
4001
5506
  table.setColumnOrder((old) => ["mvt-row-expand", ...old]);
4002
5507
  }));
4003
5508
  if (o.enableColumnPinning) internal.push(h(Menu.Divider));
5509
+ } else if (serverGroupBy) {
5510
+ const { addGroup, grouping, removeGroup } = serverGroupBy;
5511
+ const isGrouped = grouping.includes(column.id);
5512
+ 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)));
5513
+ if (o.enableColumnPinning) internal.push(h(Menu.Divider));
4004
5514
  }
4005
5515
  if (o.enableColumnPinning && column.getCanPin()) {
4006
5516
  internal.push(item(l.pinToLeft, icons.IconPinned, () => column.pin("left"), column.getIsPinned() === "left", MVT_ColumnActionMenu_module_default.left));
@@ -4031,7 +5541,7 @@ var MVT_ColumnActionMenu = defineComponent({
4031
5541
  withinPortal: true,
4032
5542
  ...attrs,
4033
5543
  opened: props.opened,
4034
- onChange: props.onChange
5544
+ "onUpdate:opened": props.onChange
4035
5545
  }, () => [h(Tooltip, {
4036
5546
  label: actionProps.title ?? l.columnActions,
4037
5547
  openDelay: 1e3,
@@ -4088,9 +5598,9 @@ var MVT_FilterCheckbox = defineComponent({
4088
5598
  size: table.getState().density === "xs" ? "sm" : "md",
4089
5599
  ...checkboxProps,
4090
5600
  title: void 0,
4091
- onChange: (e) => {
5601
+ onChange: (checked) => {
4092
5602
  column.setFilterValue(value === void 0 ? "true" : value === "true" ? "false" : void 0);
4093
- checkboxProps.onChange?.(e);
5603
+ checkboxProps.onChange?.(checked);
4094
5604
  },
4095
5605
  onClick: (e) => {
4096
5606
  e.stopPropagation();
@@ -4403,7 +5913,7 @@ var MVT_FilterRangeSlider = defineComponent({
4403
5913
  class: clsx("mvt-filter-range-slider", MVT_FilterRangeSlider_module_default.root, rangeProps.class),
4404
5914
  min,
4405
5915
  max,
4406
- value: values.value,
5916
+ modelValue: values.value,
4407
5917
  ...rangeProps,
4408
5918
  onChange: (value) => {
4409
5919
  values.value = value;
@@ -5225,6 +6735,44 @@ var MantineVueTable = defineComponent({
5225
6735
  }
5226
6736
  });
5227
6737
  //#endregion
5228
- export { MVT_AggregationFns, MVT_BottomToolbar, MVT_ColumnActionMenu, MVT_ColumnPinningButtons, MVT_CopyButton, MVT_DefaultColumn, MVT_DefaultDisplayColumn, MVT_Default_Icons, MVT_EditActionButtons, MVT_EditCellTextInput, MVT_EditRowModal, MVT_ExpandAllButton, MVT_ExpandButton, MVT_FilterCheckbox, MVT_FilterFns, MVT_FilterOptionMenu, MVT_FilterRangeFields, MVT_FilterRangeSlider, MVT_FilterTextInput, MVT_GlobalFilterTextInput, MVT_GrabHandleButton, MVT_ProgressBar, MVT_RowActionMenu, MVT_RowPinButton, MVT_SelectCheckbox, MVT_ShowHideColumnsButton, MVT_ShowHideColumnsMenu, MVT_ShowHideColumnsMenuItems, MVT_SortingFns, MVT_Table, MVT_TableBody, MVT_TableBodyCell, MVT_TableBodyCellValue, MVT_TableBodyEmptyRow, MVT_TableBodyRow, MVT_TableBodyRowGrabHandle, MVT_TableBodyRowPinButton, MVT_TableContainer, MVT_TableDetailPanel, MVT_TableFooter, MVT_TableFooterCell, MVT_TableFooterRow, MVT_TableHead, MVT_TableHeadCell, MVT_TableHeadCellFilterContainer, MVT_TableHeadCellFilterLabel, MVT_TableHeadCellGrabHandle, MVT_TableHeadCellResizeHandle, MVT_TableHeadCellSortLabel, MVT_TableHeadRow, MVT_TablePagination, MVT_TablePaper, MVT_ToggleDensePaddingButton, MVT_ToggleFiltersButton, MVT_ToggleFullScreenButton, MVT_ToggleGlobalFilterButton, MVT_ToggleRowActionMenuButton, MVT_ToolbarAlertBanner, MVT_ToolbarDropZone, MVT_ToolbarInternalButtons, MVT_TopToolbar, MantineVueTable, Memo_MVT_TableBody, Memo_MVT_TableBodyCell, Memo_MVT_TableBodyRow, createMVTColumnHelper, createRow, dataVariable, defaultDisplayColumnProps, flexRender, getAllLeafColumnDefs, getCanRankRows, getColumnId, getDefaultColumnFilterFn, getDefaultColumnOrderIds, getIsRankingRows, getIsRowSelected, getLeadingDisplayColumnIds, getMVT_RowSelectionHandler, getMVT_Rows, getMVT_SelectAllHandler, getPrimaryColor, getPrimaryShade, getTrailingDisplayColumnIds, localizedFilterOption, mrtFilterOptions, parseCSSVarId, parseFromValuesOrFunc, prepareColumns, provideMVT_Slots, rankGlobalFuzzy, renderMVT_Renderable, reorderColumn, showRowActionsColumn, showRowDragColumn, showRowExpandColumn, showRowNumbersColumn, showRowPinningColumn, showRowSelectionColumn, showRowSpacerColumn, useMVT_ColumnVirtualizer, useMVT_Effects, useMVT_RowVirtualizer, useMVT_Rows, useMVT_Slots, useMVT_TableInstance, useMVT_TableOptions, useMantineVueTable };
6738
+ //#region src/server-grouping/createServerGroupingProvider.ts
6739
+ var asString = (value) => value === null || value === void 0 ? "" : String(value);
6740
+ /**
6741
+ * Build a {@link MVT_ServerGroupingProvider} with sensible defaults for common
6742
+ * response formats:
6743
+ *
6744
+ * - `groups`/`records` default to the response itself when it is an array.
6745
+ * - `groupRowCount`/`recordRowCount` default to the mapped array length.
6746
+ * - `groupId`/`groupLabel` default to stringifying `groupValue` (or the group
6747
+ * itself when it is a primitive).
6748
+ * - `groupValue` defaults to the group object itself.
6749
+ * - `groupMeta` defaults to `{}`; `groupCount` and aggregates stay optional.
6750
+ * - `hasChildren` defaults to `true` (every level up to and including the last
6751
+ * grouping level is expandable).
6752
+ * - `rowId` falls back to the table's existing `getRowId` logic.
6753
+ */
6754
+ var createServerGroupingProvider = (options) => {
6755
+ const getGroups = options.getGroups ?? options.groups ?? ((response) => Array.isArray(response) ? response : []);
6756
+ const getRecords = options.getRecords ?? options.records ?? ((response) => Array.isArray(response) ? response : []);
6757
+ const getGroupValue = options.getGroupValue ?? options.groupValue ?? ((group) => group);
6758
+ return {
6759
+ getGroupId: options.getGroupId ?? options.groupId ?? ((group, context) => asString(getGroupValue(group, context))),
6760
+ getGroupLabel: options.getGroupLabel ?? options.groupLabel ?? ((group, context) => asString(getGroupValue(group, context))),
6761
+ getGroupValue,
6762
+ getGroupCount: options.getGroupCount ?? options.groupCount,
6763
+ getGroupMeta: options.getGroupMeta ?? options.groupMeta ?? (() => ({})),
6764
+ hasGroupChildren: options.hasGroupChildren ?? options.hasChildren,
6765
+ loadGroups: options.loadGroups,
6766
+ getGroups,
6767
+ getGroupRowCount: options.getGroupRowCount ?? options.groupRowCount ?? ((response) => getGroups(response).length),
6768
+ loadRecords: options.loadRecords,
6769
+ getRecords,
6770
+ getRecordRowCount: options.getRecordRowCount ?? options.recordRowCount ?? ((response) => getRecords(response).length),
6771
+ getRowId: options.getRowId ?? options.rowId,
6772
+ getCacheKey: options.getCacheKey ?? options.cacheKey
6773
+ };
6774
+ };
6775
+ //#endregion
6776
+ export { MVT_AggregationFns, MVT_BottomToolbar, MVT_ColumnActionMenu, MVT_ColumnPinningButtons, MVT_CopyButton, MVT_DefaultColumn, MVT_DefaultDisplayColumn, MVT_Default_Icons, MVT_EditActionButtons, MVT_EditCellTextInput, MVT_EditRowModal, MVT_ExpandAllButton, MVT_ExpandButton, MVT_FilterCheckbox, MVT_FilterFns, MVT_FilterOptionMenu, MVT_FilterRangeFields, MVT_FilterRangeSlider, MVT_FilterTextInput, MVT_GlobalFilterTextInput, MVT_GrabHandleButton, MVT_ProgressBar, MVT_RowActionMenu, MVT_RowPinButton, MVT_SERVER_GROUPING_ROOT_PATH_ID, MVT_SelectCheckbox, MVT_ServerGroupingBody, MVT_ServerGroupingGroupBy, MVT_ShowHideColumnsButton, MVT_ShowHideColumnsMenu, MVT_ShowHideColumnsMenuItems, MVT_SortingFns, MVT_Table, MVT_TableBody, MVT_TableBodyCell, MVT_TableBodyCellValue, MVT_TableBodyEmptyRow, MVT_TableBodyRow, MVT_TableBodyRowGrabHandle, MVT_TableBodyRowPinButton, MVT_TableContainer, MVT_TableDetailPanel, MVT_TableFooter, MVT_TableFooterCell, MVT_TableFooterRow, MVT_TableHead, MVT_TableHeadCell, MVT_TableHeadCellFilterContainer, MVT_TableHeadCellFilterLabel, MVT_TableHeadCellGrabHandle, MVT_TableHeadCellResizeHandle, MVT_TableHeadCellSortLabel, MVT_TableHeadRow, MVT_TablePagination, MVT_TablePaper, MVT_ToggleDensePaddingButton, MVT_ToggleFiltersButton, MVT_ToggleFullScreenButton, MVT_ToggleGlobalFilterButton, MVT_ToggleRowActionMenuButton, MVT_ToolbarAlertBanner, MVT_ToolbarDropZone, MVT_ToolbarInternalButtons, MVT_TopToolbar, MantineVueTable, Memo_MVT_TableBody, Memo_MVT_TableBodyCell, Memo_MVT_TableBodyRow, createMVTColumnHelper, createMVT_ServerGroupingManager, createRow, createServerGroupPathId, createServerGroupingProvider, dataVariable, defaultDisplayColumnProps, deselectServerGroupingRecords, escapeServerGroupPathPart, flexRender, getAllLeafColumnDefs, getCanRankRows, getColumnId, getDefaultColumnFilterFn, getDefaultColumnOrderIds, getIsRankingRows, getIsRowSelected, getLeadingDisplayColumnIds, getMVT_ColumnWidthStyles, getMVT_RowSelectionHandler, getMVT_Rows, getMVT_SelectAllHandler, getPrimaryColor, getPrimaryShade, getServerGroupPathDepth, getServerGroupableColumns, getServerGroupingColumnActions, getServerGroupingGroupByContext, getServerGroupingManager, getServerGroupingSelectableRows, getServerGroupingSelectionPayload, getServerGroupingSelectionSummary, getTrailingDisplayColumnIds, isAbortError, isServerGroupPathOrDescendant, isServerGroupingRecordSelected, localizedFilterOption, mrtFilterOptions, parseCSSVarId, parseFromValuesOrFunc, parseServerGroupPathId, prepareColumns, provideMVT_Slots, rankGlobalFuzzy, renderMVT_Renderable, reorderColumn, selectAllMatchingServerGroupingRecords, serializeServerGroupingCacheKey, showRowActionsColumn, showRowDragColumn, showRowExpandColumn, showRowNumbersColumn, showRowPinningColumn, showRowSelectionColumn, showRowSpacerColumn, toggleAllServerGroupingRecordsSelected, toggleServerGroupingRecordSelected, unescapeServerGroupPathPart, useMVT_ColumnVirtualizer, useMVT_Effects, useMVT_RowVirtualizer, useMVT_Rows, useMVT_Slots, useMVT_TableInstance, useMVT_TableOptions, useMantineVueTable };
5229
6777
 
5230
6778
  //# sourceMappingURL=index.mjs.map