@machinemetrics/mm-react-components 0.2.3-25 → 0.2.3-26

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.
@@ -23981,6 +23981,198 @@ function useDroppable(_ref) {
23981
23981
  setNodeRef
23982
23982
  };
23983
23983
  }
23984
+ const restrictToHorizontalAxis = (_ref) => {
23985
+ let {
23986
+ transform
23987
+ } = _ref;
23988
+ return {
23989
+ ...transform,
23990
+ y: 0
23991
+ };
23992
+ };
23993
+ function restrictToBoundingRect(transform, rect, boundingRect) {
23994
+ const value = {
23995
+ ...transform
23996
+ };
23997
+ if (rect.top + transform.y <= boundingRect.top) {
23998
+ value.y = boundingRect.top - rect.top;
23999
+ } else if (rect.bottom + transform.y >= boundingRect.top + boundingRect.height) {
24000
+ value.y = boundingRect.top + boundingRect.height - rect.bottom;
24001
+ }
24002
+ if (rect.left + transform.x <= boundingRect.left) {
24003
+ value.x = boundingRect.left - rect.left;
24004
+ } else if (rect.right + transform.x >= boundingRect.left + boundingRect.width) {
24005
+ value.x = boundingRect.left + boundingRect.width - rect.right;
24006
+ }
24007
+ return value;
24008
+ }
24009
+ const restrictToParentElement = (_ref) => {
24010
+ let {
24011
+ containerNodeRect,
24012
+ draggingNodeRect,
24013
+ transform
24014
+ } = _ref;
24015
+ if (!draggingNodeRect || !containerNodeRect) {
24016
+ return transform;
24017
+ }
24018
+ return restrictToBoundingRect(transform, draggingNodeRect, containerNodeRect);
24019
+ };
24020
+ const restrictToVerticalAxis = (_ref) => {
24021
+ let {
24022
+ transform
24023
+ } = _ref;
24024
+ return {
24025
+ ...transform,
24026
+ x: 0
24027
+ };
24028
+ };
24029
+ function DataTablePagination({
24030
+ table,
24031
+ pageSizeOptions = [25, 50, 100, 250],
24032
+ className,
24033
+ compact: compact2 = false,
24034
+ onPageChange,
24035
+ onPageSizeChange,
24036
+ manualPagination = false,
24037
+ totalRowCount
24038
+ }) {
24039
+ const state = table.getState();
24040
+ const pageSize = state.pagination?.pageSize ?? 25;
24041
+ const pageIndex = state.pagination?.pageIndex ?? 0;
24042
+ const canPrev = table.getCanPreviousPage();
24043
+ const canNext = table.getCanNextPage();
24044
+ const totalRows = React.useMemo(() => {
24045
+ if (manualPagination) {
24046
+ if (totalRowCount !== void 0) {
24047
+ return totalRowCount;
24048
+ }
24049
+ const pageCount = table.getPageCount();
24050
+ if (pageCount > 0) {
24051
+ const approximateTotal = pageCount * pageSize;
24052
+ const currentPageRows = table.getRowModel().rows.length;
24053
+ if (pageIndex === pageCount - 1 && currentPageRows < pageSize) {
24054
+ return (pageCount - 1) * pageSize + currentPageRows;
24055
+ }
24056
+ return approximateTotal;
24057
+ }
24058
+ return 0;
24059
+ }
24060
+ return table.getFilteredRowModel().rows.length;
24061
+ }, [manualPagination, totalRowCount, table, pageSize, pageIndex]);
24062
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
24063
+ "div",
24064
+ {
24065
+ className: "mmc-pagination flex items-center justify-between gap-3 px-4 py-3 " + (className || ""),
24066
+ "data-slot": "pagination",
24067
+ children: [
24068
+ !compact2 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4 flex-1", children: [
24069
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm text-foreground", children: (() => {
24070
+ const selected = table.getFilteredSelectedRowModel().rows.length;
24071
+ if (selected > 0) {
24072
+ return `${selected} selected of ${totalRows} items`;
24073
+ }
24074
+ if (totalRows === 0) return "Showing 0 to 0 of 0 items";
24075
+ const start = pageIndex * pageSize + 1;
24076
+ const currentPageRows = table.getRowModel().rows.length;
24077
+ const end = manualPagination ? pageIndex * pageSize + currentPageRows : Math.min(totalRows, (pageIndex + 1) * pageSize);
24078
+ return `Showing ${start} to ${end} of ${totalRows} items`;
24079
+ })() }),
24080
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
24081
+ "div",
24082
+ {
24083
+ className: "mmc-pagination__page-size flex items-center gap-2",
24084
+ "data-slot": "page-size",
24085
+ children: [
24086
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-foreground", children: "Show:" }),
24087
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
24088
+ Select$1,
24089
+ {
24090
+ value: String(pageSize),
24091
+ onValueChange: (value) => {
24092
+ const size2 = Number(value);
24093
+ table.setPageIndex(0);
24094
+ table.setPageSize(size2);
24095
+ if (onPageSizeChange) {
24096
+ onPageSizeChange(size2);
24097
+ }
24098
+ if (onPageChange) {
24099
+ onPageChange(0);
24100
+ }
24101
+ },
24102
+ children: [
24103
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "h-9 w-20", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, {}) }),
24104
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectContent, { align: "end", children: pageSizeOptions.map((size2) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: String(size2), children: size2 }, size2)) })
24105
+ ]
24106
+ }
24107
+ )
24108
+ ]
24109
+ }
24110
+ )
24111
+ ] }),
24112
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mmc-pagination__nav space-x-4", "data-slot": "nav", children: [
24113
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
24114
+ Button$1,
24115
+ {
24116
+ variant: "ghost",
24117
+ className: "px-2.5 text-foreground hover:text-foreground disabled:text-muted-foreground disabled:opacity-50 disabled:hover:text-muted-foreground",
24118
+ onClick: () => {
24119
+ table.previousPage();
24120
+ if (onPageChange) {
24121
+ onPageChange(table.getState().pagination?.pageIndex ?? 0);
24122
+ }
24123
+ },
24124
+ disabled: !canPrev,
24125
+ "data-slot": "previous",
24126
+ children: "Previous"
24127
+ }
24128
+ ),
24129
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
24130
+ "span",
24131
+ {
24132
+ className: "text-sm text-foreground select-none",
24133
+ "data-slot": "page-indicator",
24134
+ children: (() => {
24135
+ const p2 = table.getState().pagination ?? {};
24136
+ const current = Math.max(1, (p2.pageIndex ?? 0) + 1);
24137
+ let count2;
24138
+ if (manualPagination) {
24139
+ const pageCountFn = table.getPageCount;
24140
+ count2 = typeof pageCountFn === "function" ? pageCountFn() : Math.max(1, Math.ceil(totalRows / Math.max(1, pageSize)));
24141
+ } else {
24142
+ const pageCountFn = table.getPageCount;
24143
+ count2 = typeof pageCountFn === "function" ? pageCountFn() : Math.max(
24144
+ 1,
24145
+ Math.ceil(
24146
+ (table.getFilteredRowModel().rows.length || 0) / Math.max(1, p2.pageSize ?? 10)
24147
+ )
24148
+ );
24149
+ }
24150
+ const safeCurrent = Math.min(current, count2);
24151
+ return `Page ${safeCurrent} of ${count2}`;
24152
+ })()
24153
+ }
24154
+ ),
24155
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
24156
+ Button$1,
24157
+ {
24158
+ variant: "ghost",
24159
+ className: "px-2.5 text-foreground hover:text-foreground disabled:text-muted-foreground disabled:opacity-50 disabled:hover:text-muted-foreground",
24160
+ onClick: () => {
24161
+ table.nextPage();
24162
+ if (onPageChange) {
24163
+ onPageChange(table.getState().pagination?.pageIndex ?? 0);
24164
+ }
24165
+ },
24166
+ disabled: !canNext,
24167
+ "data-slot": "next",
24168
+ children: "Next"
24169
+ }
24170
+ )
24171
+ ] })
24172
+ ]
24173
+ }
24174
+ );
24175
+ }
23984
24176
  function arrayMove(array, from, to) {
23985
24177
  const newArray = array.slice();
23986
24178
  newArray.splice(to < 0 ? newArray.length + to : to, 0, newArray.splice(from, 1)[0]);
@@ -24620,180 +24812,15 @@ function isAfter(a2, b) {
24620
24812
  }
24621
24813
  return a2.data.current.sortable.index < b.data.current.sortable.index;
24622
24814
  }
24623
- const restrictToHorizontalAxis = (_ref) => {
24624
- let {
24625
- transform
24626
- } = _ref;
24627
- return {
24628
- ...transform,
24629
- y: 0
24630
- };
24631
- };
24632
- function restrictToBoundingRect(transform, rect, boundingRect) {
24633
- const value = {
24634
- ...transform
24635
- };
24636
- if (rect.top + transform.y <= boundingRect.top) {
24637
- value.y = boundingRect.top - rect.top;
24638
- } else if (rect.bottom + transform.y >= boundingRect.top + boundingRect.height) {
24639
- value.y = boundingRect.top + boundingRect.height - rect.bottom;
24640
- }
24641
- if (rect.left + transform.x <= boundingRect.left) {
24642
- value.x = boundingRect.left - rect.left;
24643
- } else if (rect.right + transform.x >= boundingRect.left + boundingRect.width) {
24644
- value.x = boundingRect.left + boundingRect.width - rect.right;
24645
- }
24646
- return value;
24647
- }
24648
- const restrictToParentElement = (_ref) => {
24649
- let {
24650
- containerNodeRect,
24651
- draggingNodeRect,
24652
- transform
24653
- } = _ref;
24654
- if (!draggingNodeRect || !containerNodeRect) {
24655
- return transform;
24656
- }
24657
- return restrictToBoundingRect(transform, draggingNodeRect, containerNodeRect);
24658
- };
24659
- const restrictToVerticalAxis = (_ref) => {
24660
- let {
24661
- transform
24662
- } = _ref;
24663
- return {
24664
- ...transform,
24665
- x: 0
24666
- };
24667
- };
24668
- function DataTablePagination({
24669
- table,
24670
- pageSizeOptions = [25, 50, 100, 250],
24671
- className,
24672
- compact: compact2 = false,
24673
- onPageChange,
24674
- onPageSizeChange
24675
- }) {
24676
- const state = table.getState();
24677
- const pageSize = state.pagination?.pageSize ?? 25;
24678
- const canPrev = table.getCanPreviousPage();
24679
- const canNext = table.getCanNextPage();
24815
+ function MenuHeader({ title, className, right }) {
24680
24816
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
24681
24817
  "div",
24682
24818
  {
24683
- className: "mmc-pagination flex items-center justify-between gap-3 px-4 py-3 " + (className || ""),
24684
- "data-slot": "pagination",
24685
- children: [
24686
- !compact2 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4 flex-1", children: [
24687
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm text-foreground", children: (() => {
24688
- const total = table.getFilteredRowModel().rows.length;
24689
- const selected = table.getFilteredSelectedRowModel().rows.length;
24690
- if (selected > 0) {
24691
- return `${selected} selected of ${total} items`;
24692
- }
24693
- if (total === 0) return "Showing 0 to 0 of 0 items";
24694
- const { pageIndex = 0, pageSize: pageSize2 = 25 } = table.getState().pagination ?? {};
24695
- const start = pageIndex * pageSize2 + 1;
24696
- const end = Math.min(total, (pageIndex + 1) * pageSize2);
24697
- return `Showing ${start} to ${end} of ${total} items`;
24698
- })() }),
24699
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
24700
- "div",
24701
- {
24702
- className: "mmc-pagination__page-size flex items-center gap-2",
24703
- "data-slot": "page-size",
24704
- children: [
24705
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-foreground", children: "Show:" }),
24706
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
24707
- Select$1,
24708
- {
24709
- value: String(pageSize),
24710
- onValueChange: (value) => {
24711
- const size2 = Number(value);
24712
- table.setPageIndex(0);
24713
- table.setPageSize(size2);
24714
- if (onPageSizeChange) {
24715
- onPageSizeChange(size2);
24716
- }
24717
- if (onPageChange) {
24718
- onPageChange(0);
24719
- }
24720
- },
24721
- children: [
24722
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "h-9 w-20", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, {}) }),
24723
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectContent, { align: "end", children: pageSizeOptions.map((size2) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: String(size2), children: size2 }, size2)) })
24724
- ]
24725
- }
24726
- )
24727
- ]
24728
- }
24729
- )
24730
- ] }),
24731
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mmc-pagination__nav space-x-4", "data-slot": "nav", children: [
24732
- /* @__PURE__ */ jsxRuntimeExports.jsx(
24733
- Button$1,
24734
- {
24735
- variant: "ghost",
24736
- className: "px-2.5 text-foreground hover:text-foreground disabled:text-muted-foreground disabled:opacity-50 disabled:hover:text-muted-foreground",
24737
- onClick: () => {
24738
- table.previousPage();
24739
- if (onPageChange) {
24740
- onPageChange(table.getState().pagination?.pageIndex ?? 0);
24741
- }
24742
- },
24743
- disabled: !canPrev,
24744
- "data-slot": "previous",
24745
- children: "Previous"
24746
- }
24747
- ),
24748
- /* @__PURE__ */ jsxRuntimeExports.jsx(
24749
- "span",
24750
- {
24751
- className: "text-sm text-foreground select-none",
24752
- "data-slot": "page-indicator",
24753
- children: (() => {
24754
- const p2 = table.getState().pagination ?? {};
24755
- const current = Math.max(1, (p2.pageIndex ?? 0) + 1);
24756
- const count2 = typeof table.getPageCount === "function" ? table.getPageCount() : Math.max(
24757
- 1,
24758
- Math.ceil(
24759
- (table.getFilteredRowModel().rows.length || 0) / Math.max(1, p2.pageSize ?? 10)
24760
- )
24761
- );
24762
- const safeCurrent = Math.min(current, count2);
24763
- return `Page ${safeCurrent} of ${count2}`;
24764
- })()
24765
- }
24766
- ),
24767
- /* @__PURE__ */ jsxRuntimeExports.jsx(
24768
- Button$1,
24769
- {
24770
- variant: "ghost",
24771
- className: "px-2.5 text-foreground hover:text-foreground disabled:text-muted-foreground disabled:opacity-50 disabled:hover:text-muted-foreground",
24772
- onClick: () => {
24773
- table.nextPage();
24774
- if (onPageChange) {
24775
- onPageChange(table.getState().pagination?.pageIndex ?? 0);
24776
- }
24777
- },
24778
- disabled: !canNext,
24779
- "data-slot": "next",
24780
- children: "Next"
24781
- }
24782
- )
24783
- ] })
24784
- ]
24785
- }
24786
- );
24787
- }
24788
- function MenuHeader({ title, className, right }) {
24789
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
24790
- "div",
24791
- {
24792
- className: cn$1(
24793
- "mmc-menu-header flex items-center justify-between border-b px-4 py-2",
24794
- className
24795
- ),
24796
- "data-slot": "menu-header",
24819
+ className: cn$1(
24820
+ "mmc-menu-header flex items-center justify-between border-b px-4 py-2",
24821
+ className
24822
+ ),
24823
+ "data-slot": "menu-header",
24797
24824
  children: [
24798
24825
  /* @__PURE__ */ jsxRuntimeExports.jsx(
24799
24826
  "span",
@@ -29450,77 +29477,56 @@ function useBreakpoint(query = QUERY) {
29450
29477
  }, [query]);
29451
29478
  return matches;
29452
29479
  }
29453
- function useTableController(options) {
29454
- const {
29455
- columns,
29456
- data,
29457
- columnRegistry,
29458
- initialState: initialState2,
29459
- tableId,
29460
- disableGlobalFilter,
29461
- customGlobalFilterFn,
29462
- onRowSelectionChange,
29463
- onSortingChange,
29464
- onPaginationChange,
29465
- onColumnVisibilityChange,
29466
- onColumnOrderChange,
29467
- onBatchAction,
29468
- onRowClick,
29469
- onExportComplete
29470
- } = options;
29471
- const storageKey = tableId ? `mmrc:table:${tableId}` : void 0;
29472
- const persistedState = React.useMemo(() => {
29473
- if (!storageKey) return null;
29474
- try {
29475
- const raw = localStorage.getItem(storageKey);
29476
- if (!raw) return null;
29477
- const parsed = JSON.parse(raw);
29478
- return parsed;
29479
- } catch {
29480
- return null;
29480
+ function loadPersistedState(storageKey) {
29481
+ if (!storageKey) return null;
29482
+ try {
29483
+ const raw = localStorage.getItem(storageKey);
29484
+ if (!raw) return null;
29485
+ return JSON.parse(raw);
29486
+ } catch {
29487
+ return null;
29488
+ }
29489
+ }
29490
+ function resolveColumnsFromRegistry(columns, columnRegistry, columnOrder) {
29491
+ if (!columnRegistry) return columns;
29492
+ const entries = Object.entries(columnRegistry);
29493
+ const registryOrder = resolveColumnOrder(
29494
+ columnRegistry
29495
+ );
29496
+ const activeOrder = columnOrder.length ? columnOrder : registryOrder;
29497
+ const registryMap = new Map(entries);
29498
+ const seen = /* @__PURE__ */ new Set();
29499
+ const ordered = activeOrder.map((id) => {
29500
+ const descriptor = registryMap.get(id);
29501
+ if (!descriptor) return null;
29502
+ seen.add(id);
29503
+ return descriptor.columnDef;
29504
+ }).filter(Boolean);
29505
+ entries.forEach(([id, descriptor]) => {
29506
+ if (!seen.has(id)) {
29507
+ ordered.push(descriptor.columnDef);
29481
29508
  }
29482
- }, [storageKey]);
29483
- const {
29484
- sorting: [sorting, setSorting],
29485
- columnVisibility: [columnVisibility, setColumnVisibility],
29486
- columnOrder: [columnOrder, setColumnOrder],
29487
- columnPinning: [columnPinning, setColumnPinning],
29488
- rowSelection: [rowSelection, setRowSelection]
29489
- } = useDataTableState({
29490
- registry: columnRegistry,
29491
- initialSorting: persistedState?.sorting ?? initialState2?.sorting,
29492
- initialVisibility: persistedState?.columnVisibility ?? initialState2?.visibility,
29493
- initialColumnOrder: persistedState?.columnOrder ?? initialState2?.columnOrder,
29494
- initialPinning: initialState2?.columnPinning,
29495
- initialRowSelection: initialState2?.rowSelection
29496
- });
29497
- const resolvedColumns = React.useMemo(() => {
29498
- if (!columnRegistry) return columns;
29499
- const entries = Object.entries(columnRegistry);
29500
- const registryOrder = resolveColumnOrder(
29501
- columnRegistry
29502
- );
29503
- const activeOrder = columnOrder.length ? columnOrder : registryOrder;
29504
- const registryMap = new Map(entries);
29505
- const seen = /* @__PURE__ */ new Set();
29506
- const ordered = activeOrder.map((id) => {
29507
- const descriptor = registryMap.get(id);
29508
- if (!descriptor) return null;
29509
- seen.add(id);
29510
- return descriptor.columnDef;
29511
- }).filter(Boolean);
29512
- entries.forEach(([id, descriptor]) => {
29513
- if (!seen.has(id)) {
29514
- ordered.push(descriptor.columnDef);
29515
- }
29516
- });
29517
- return ordered;
29518
- }, [columnRegistry, columns, columnOrder]);
29519
- const [globalFilter, setGlobalFilter] = React.useState("");
29520
- const [pagination, setPagination] = React.useState({
29521
- pageIndex: 0,
29522
- pageSize: 25
29523
29509
  });
29510
+ return ordered;
29511
+ }
29512
+ function useWrappedStateSetters({
29513
+ rowSelection,
29514
+ setRowSelection,
29515
+ onRowSelectionChange,
29516
+ data,
29517
+ sorting,
29518
+ setSorting,
29519
+ onSortingChange,
29520
+ pagination,
29521
+ setPagination,
29522
+ onPaginationChange,
29523
+ columnVisibility,
29524
+ setColumnVisibility,
29525
+ onColumnVisibilityChange,
29526
+ columnOrder,
29527
+ setColumnOrder,
29528
+ onColumnOrderChange
29529
+ }) {
29524
29530
  const wrappedSetRowSelection = React.useCallback(
29525
29531
  (updater) => {
29526
29532
  const newSelection = typeof updater === "function" ? updater(rowSelection) : updater;
@@ -29572,6 +29578,141 @@ function useTableController(options) {
29572
29578
  },
29573
29579
  [columnOrder, setColumnOrder, onColumnOrderChange]
29574
29580
  );
29581
+ return {
29582
+ wrappedSetRowSelection,
29583
+ wrappedSetSorting,
29584
+ wrappedSetPagination,
29585
+ wrappedSetColumnVisibility,
29586
+ wrappedSetColumnOrder
29587
+ };
29588
+ }
29589
+ function getGlobalFilterFn(disableGlobalFilter, customGlobalFilterFn) {
29590
+ if (disableGlobalFilter) {
29591
+ return (_row, _columnId, _filterValue) => true;
29592
+ }
29593
+ if (customGlobalFilterFn) {
29594
+ return customGlobalFilterFn;
29595
+ }
29596
+ return void 0;
29597
+ }
29598
+ function createResetColumnsHandler({
29599
+ columnRegistry,
29600
+ initialState: initialState2,
29601
+ storageKey,
29602
+ registryDefaultVisibility,
29603
+ registryDefaultOrder,
29604
+ setSorting,
29605
+ setColumnVisibility,
29606
+ setColumnOrder,
29607
+ setColumnPinning,
29608
+ table
29609
+ }) {
29610
+ if (!columnRegistry && !initialState2) return void 0;
29611
+ return () => {
29612
+ if (storageKey) {
29613
+ try {
29614
+ localStorage.removeItem(storageKey);
29615
+ } catch {
29616
+ }
29617
+ }
29618
+ if (initialState2?.sorting) {
29619
+ setSorting([...initialState2.sorting]);
29620
+ } else {
29621
+ setSorting([]);
29622
+ }
29623
+ if (registryDefaultVisibility) {
29624
+ setColumnVisibility({ ...registryDefaultVisibility });
29625
+ } else if (initialState2?.visibility) {
29626
+ setColumnVisibility({ ...initialState2.visibility });
29627
+ } else {
29628
+ setColumnVisibility({});
29629
+ }
29630
+ if (registryDefaultOrder?.length) {
29631
+ setColumnOrder([...registryDefaultOrder]);
29632
+ } else if (initialState2?.columnOrder) {
29633
+ setColumnOrder([...initialState2.columnOrder]);
29634
+ }
29635
+ setColumnPinning(
29636
+ initialState2?.columnPinning ? {
29637
+ left: [...initialState2.columnPinning.left ?? []],
29638
+ right: [...initialState2.columnPinning.right ?? []]
29639
+ } : { left: [], right: [] }
29640
+ );
29641
+ table.resetColumnSizing();
29642
+ };
29643
+ }
29644
+ function useTableController(options) {
29645
+ const {
29646
+ columns,
29647
+ data,
29648
+ columnRegistry,
29649
+ initialState: initialState2,
29650
+ tableId,
29651
+ disableGlobalFilter,
29652
+ customGlobalFilterFn,
29653
+ manualPagination = false,
29654
+ pageCount,
29655
+ onRowSelectionChange,
29656
+ onSortingChange,
29657
+ onPaginationChange,
29658
+ onColumnVisibilityChange,
29659
+ onColumnOrderChange,
29660
+ onBatchAction,
29661
+ onRowClick,
29662
+ onExportComplete
29663
+ } = options;
29664
+ const storageKey = tableId ? `mmrc:table:${tableId}` : void 0;
29665
+ const persistedState = React.useMemo(
29666
+ () => loadPersistedState(storageKey),
29667
+ [storageKey]
29668
+ );
29669
+ const {
29670
+ sorting: [sorting, setSorting],
29671
+ columnVisibility: [columnVisibility, setColumnVisibility],
29672
+ columnOrder: [columnOrder, setColumnOrder],
29673
+ columnPinning: [columnPinning, setColumnPinning],
29674
+ rowSelection: [rowSelection, setRowSelection]
29675
+ } = useDataTableState({
29676
+ registry: columnRegistry,
29677
+ initialSorting: persistedState?.sorting ?? initialState2?.sorting,
29678
+ initialVisibility: persistedState?.columnVisibility ?? initialState2?.visibility,
29679
+ initialColumnOrder: persistedState?.columnOrder ?? initialState2?.columnOrder,
29680
+ initialPinning: initialState2?.columnPinning,
29681
+ initialRowSelection: initialState2?.rowSelection
29682
+ });
29683
+ const resolvedColumns = React.useMemo(
29684
+ () => resolveColumnsFromRegistry(columns, columnRegistry, columnOrder),
29685
+ [columns, columnRegistry, columnOrder]
29686
+ );
29687
+ const [globalFilter, setGlobalFilter] = React.useState("");
29688
+ const [pagination, setPagination] = React.useState({
29689
+ pageIndex: 0,
29690
+ pageSize: 25
29691
+ });
29692
+ const {
29693
+ wrappedSetRowSelection,
29694
+ wrappedSetSorting,
29695
+ wrappedSetPagination,
29696
+ wrappedSetColumnVisibility,
29697
+ wrappedSetColumnOrder
29698
+ } = useWrappedStateSetters({
29699
+ rowSelection,
29700
+ setRowSelection,
29701
+ onRowSelectionChange,
29702
+ data,
29703
+ sorting,
29704
+ setSorting,
29705
+ onSortingChange,
29706
+ pagination,
29707
+ setPagination,
29708
+ onPaginationChange,
29709
+ columnVisibility,
29710
+ setColumnVisibility,
29711
+ onColumnVisibilityChange,
29712
+ columnOrder,
29713
+ setColumnOrder,
29714
+ onColumnOrderChange
29715
+ });
29575
29716
  React.useEffect(() => {
29576
29717
  if (!storageKey) return;
29577
29718
  try {
@@ -29584,15 +29725,10 @@ function useTableController(options) {
29584
29725
  } catch {
29585
29726
  }
29586
29727
  }, [columnOrder, columnVisibility, sorting, storageKey]);
29587
- const globalFilterFn = React.useMemo(() => {
29588
- if (disableGlobalFilter) {
29589
- return (_row, _columnId, _filterValue) => true;
29590
- }
29591
- if (customGlobalFilterFn) {
29592
- return customGlobalFilterFn;
29593
- }
29594
- return void 0;
29595
- }, [disableGlobalFilter, customGlobalFilterFn]);
29728
+ const globalFilterFn = React.useMemo(
29729
+ () => getGlobalFilterFn(disableGlobalFilter, customGlobalFilterFn),
29730
+ [disableGlobalFilter, customGlobalFilterFn]
29731
+ );
29596
29732
  const table = useReactTable({
29597
29733
  data,
29598
29734
  columns: resolvedColumns,
@@ -29609,6 +29745,9 @@ function useTableController(options) {
29609
29745
  enableColumnResizing: true,
29610
29746
  enableColumnPinning: true,
29611
29747
  enableGlobalFilter: true,
29748
+ // Server-side pagination configuration
29749
+ manualPagination,
29750
+ ...manualPagination && pageCount !== void 0 && { pageCount },
29612
29751
  // Only include globalFilterFn prop if we have a custom filter or disabled filter
29613
29752
  // Omitting it allows TanStack Table to use its default filter behavior
29614
29753
  ...globalFilterFn !== void 0 && { globalFilterFn },
@@ -29622,7 +29761,10 @@ function useTableController(options) {
29622
29761
  getCoreRowModel: getCoreRowModel(),
29623
29762
  getSortedRowModel: getSortedRowModel(),
29624
29763
  getFilteredRowModel: getFilteredRowModel(),
29625
- getPaginationRowModel: getPaginationRowModel(),
29764
+ // Only use pagination row model for client-side pagination
29765
+ ...!manualPagination && {
29766
+ getPaginationRowModel: getPaginationRowModel()
29767
+ },
29626
29768
  getFacetedRowModel: getFacetedRowModel(),
29627
29769
  getFacetedUniqueValues: getFacetedUniqueValues(),
29628
29770
  debugTable: false
@@ -29642,52 +29784,32 @@ function useTableController(options) {
29642
29784
  ) : void 0,
29643
29785
  [columnRegistry]
29644
29786
  );
29645
- const handleResetColumns = React.useMemo(() => {
29646
- if (!columnRegistry && !initialState2) return void 0;
29647
- return () => {
29648
- if (storageKey) {
29649
- try {
29650
- localStorage.removeItem(storageKey);
29651
- } catch {
29652
- }
29653
- }
29654
- if (initialState2?.sorting) {
29655
- setSorting([...initialState2.sorting]);
29656
- } else {
29657
- setSorting([]);
29658
- }
29659
- if (registryDefaultVisibility) {
29660
- setColumnVisibility({ ...registryDefaultVisibility });
29661
- } else if (initialState2?.visibility) {
29662
- setColumnVisibility({ ...initialState2.visibility });
29663
- } else {
29664
- setColumnVisibility({});
29665
- }
29666
- if (registryDefaultOrder && registryDefaultOrder.length) {
29667
- setColumnOrder([...registryDefaultOrder]);
29668
- } else if (initialState2?.columnOrder) {
29669
- setColumnOrder([...initialState2.columnOrder]);
29670
- }
29671
- setColumnPinning(
29672
- initialState2?.columnPinning ? {
29673
- left: [...initialState2.columnPinning.left ?? []],
29674
- right: [...initialState2.columnPinning.right ?? []]
29675
- } : { left: [], right: [] }
29676
- );
29677
- table.resetColumnSizing();
29678
- };
29679
- }, [
29680
- columnRegistry,
29681
- initialState2,
29682
- registryDefaultVisibility,
29683
- registryDefaultOrder,
29684
- setColumnVisibility,
29685
- setColumnOrder,
29686
- setColumnPinning,
29687
- setSorting,
29688
- table,
29689
- storageKey
29690
- ]);
29787
+ const handleResetColumns = React.useMemo(
29788
+ () => createResetColumnsHandler({
29789
+ columnRegistry,
29790
+ initialState: initialState2,
29791
+ storageKey,
29792
+ registryDefaultVisibility,
29793
+ registryDefaultOrder,
29794
+ setSorting,
29795
+ setColumnVisibility,
29796
+ setColumnOrder,
29797
+ setColumnPinning,
29798
+ table
29799
+ }),
29800
+ [
29801
+ columnRegistry,
29802
+ initialState2,
29803
+ storageKey,
29804
+ registryDefaultVisibility,
29805
+ registryDefaultOrder,
29806
+ setSorting,
29807
+ setColumnVisibility,
29808
+ setColumnOrder,
29809
+ setColumnPinning,
29810
+ table
29811
+ ]
29812
+ );
29691
29813
  return {
29692
29814
  table,
29693
29815
  resolvedColumns,
@@ -29745,25 +29867,126 @@ function getAlignmentClass(align) {
29745
29867
  return void 0;
29746
29868
  }
29747
29869
  }
29748
- const TABLE_TOKENS = {
29749
- defaultColumnWidth: 160,
29750
- minColumnWidth: 96,
29751
- maxColumnWidth: 420,
29752
- toolbarGap: 8,
29753
- selectionColumnWidth: 44,
29754
- actionsColumnWidth: 64
29755
- };
29756
- function SortableHeader({
29757
- header,
29758
- isDragging,
29759
- activeColumnId,
29760
- clampRef
29870
+ function computeClampBounds(activeId, containerRef) {
29871
+ try {
29872
+ const th = document.querySelector(`th[data-col-id="${activeId}"]`);
29873
+ const container = containerRef.current;
29874
+ if (th && container) {
29875
+ const t = th.getBoundingClientRect();
29876
+ const c2 = container.getBoundingClientRect();
29877
+ return { minX: c2.left - t.left, maxX: c2.right - t.right };
29878
+ }
29879
+ } catch {
29880
+ }
29881
+ return {
29882
+ minX: Number.NEGATIVE_INFINITY,
29883
+ maxX: Number.POSITIVE_INFINITY
29884
+ };
29885
+ }
29886
+ function getVisibleColumnOrder(table, currentOrder) {
29887
+ const groups = table.getHeaderGroups();
29888
+ if (!groups.length) return currentOrder;
29889
+ return groups[0].headers.filter((h) => h.column.getIsVisible()).map((h) => h.column.id);
29890
+ }
29891
+ function useDragAndDrop({
29892
+ table,
29893
+ containerRef
29761
29894
  }) {
29762
- const id = header.column.id;
29763
- const {
29764
- attributes,
29765
- listeners,
29766
- setNodeRef,
29895
+ const [isDragging, setIsDragging] = React.useState(false);
29896
+ const [activeColumnId, setActiveColumnId] = React.useState(
29897
+ null
29898
+ );
29899
+ const [tempColumnOrder, setTempColumnOrder] = React.useState([]);
29900
+ const clampRef = React.useRef({
29901
+ minX: Number.NEGATIVE_INFINITY,
29902
+ maxX: Number.POSITIVE_INFINITY
29903
+ });
29904
+ const stateColumnOrder = table.getState().columnOrder;
29905
+ const allLeafColumnIds = table.getAllLeafColumns().map((c2) => c2.id);
29906
+ const baseOrder = stateColumnOrder?.length ? stateColumnOrder : allLeafColumnIds;
29907
+ const currentOrder = pinBoundaries(baseOrder);
29908
+ const visibleOrder = getVisibleColumnOrder(table, currentOrder);
29909
+ const renderOrder = pinBoundaries(
29910
+ isDragging && tempColumnOrder.length ? tempColumnOrder : visibleOrder
29911
+ );
29912
+ const sortableHeaderIds = React.useMemo(
29913
+ () => renderOrder.filter((id) => id !== "select" && id !== "actions"),
29914
+ [renderOrder]
29915
+ );
29916
+ const handleDragStart = React.useCallback(
29917
+ (event) => {
29918
+ setIsDragging(true);
29919
+ const activeId = String(event.active.id);
29920
+ setActiveColumnId(activeId);
29921
+ const visible = getVisibleColumnOrder(table, currentOrder);
29922
+ setTempColumnOrder(pinBoundaries(visible));
29923
+ clampRef.current = computeClampBounds(activeId, containerRef);
29924
+ },
29925
+ [currentOrder, table, containerRef]
29926
+ );
29927
+ const handleDragOver = React.useCallback((event) => {
29928
+ const { active, over } = event;
29929
+ if (!over) return;
29930
+ const activeId = String(active.id);
29931
+ const overId = String(over.id);
29932
+ if (activeId === overId) return;
29933
+ setTempColumnOrder((prev) => {
29934
+ const from = prev.indexOf(activeId);
29935
+ const to = prev.indexOf(overId);
29936
+ if (from === -1 || to === -1) return prev;
29937
+ const moved = arrayMove(prev, from, to);
29938
+ if (!moved.includes("select")) return moved;
29939
+ return ["select", ...moved.filter((id) => id !== "select")];
29940
+ });
29941
+ }, []);
29942
+ const handleDragEnd = React.useCallback(
29943
+ (_event) => {
29944
+ setIsDragging(false);
29945
+ setActiveColumnId(null);
29946
+ if (!tempColumnOrder.length) {
29947
+ setTempColumnOrder([]);
29948
+ return;
29949
+ }
29950
+ const normalizedTempOrder = pinBoundaries(tempColumnOrder);
29951
+ const prev = JSON.stringify(currentOrder);
29952
+ const next = JSON.stringify(normalizedTempOrder);
29953
+ if (prev !== next) {
29954
+ table.setColumnOrder(normalizedTempOrder);
29955
+ }
29956
+ setTempColumnOrder([]);
29957
+ },
29958
+ [currentOrder, table, tempColumnOrder]
29959
+ );
29960
+ return {
29961
+ isDragging,
29962
+ activeColumnId,
29963
+ renderOrder,
29964
+ sortableHeaderIds,
29965
+ clampRef,
29966
+ handleDragStart,
29967
+ handleDragOver,
29968
+ handleDragEnd
29969
+ };
29970
+ }
29971
+ const TABLE_TOKENS = {
29972
+ defaultColumnWidth: 160,
29973
+ minColumnWidth: 96,
29974
+ maxColumnWidth: 420,
29975
+ toolbarGap: 8,
29976
+ selectionColumnWidth: 44,
29977
+ actionsColumnWidth: 64
29978
+ };
29979
+ function SortableHeader({
29980
+ header,
29981
+ isDragging,
29982
+ activeColumnId,
29983
+ clampRef
29984
+ }) {
29985
+ const id = header.column.id;
29986
+ const {
29987
+ attributes,
29988
+ listeners,
29989
+ setNodeRef,
29767
29990
  transform,
29768
29991
  transition,
29769
29992
  isDragging: isItemDragging
@@ -30028,71 +30251,115 @@ function CellContent({
30028
30251
  }, [isRightAligned]);
30029
30252
  return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref, className: "mmc-table-cell__content", children });
30030
30253
  }
30254
+ function renderSkeletonRows(skeletonRowCount, resolvedColumns) {
30255
+ return [...Array(skeletonRowCount)].map((_, rowIndex) => {
30256
+ const rowKey = `skeleton-row-${rowIndex}`;
30257
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("tr", { className: "border-b", children: resolvedColumns.map((column, colIndex) => {
30258
+ const columnId = column.id || `skeleton-col-${rowIndex}-${colIndex}`;
30259
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
30260
+ "td",
30261
+ {
30262
+ className: cn$1(
30263
+ "px-4 py-2.5 align-middle text-xs font-normal transition-all duration-300 ease-[cubic-bezier(0.23,1,0.32,1)] will-change-transform",
30264
+ getAlignmentClass(column.meta?.align)
30265
+ ),
30266
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Skeleton, { className: "h-[21.333px] w-full" })
30267
+ },
30268
+ columnId
30269
+ );
30270
+ }) }, rowKey);
30271
+ });
30272
+ }
30273
+ function createFixedWidthStyle(width) {
30274
+ return {
30275
+ width,
30276
+ minWidth: width,
30277
+ maxWidth: width
30278
+ };
30279
+ }
30280
+ function renderTableCell(cell, isDragging, activeColumnId) {
30281
+ const isOtherColumnDimmed = isDragging && activeColumnId != null && cell.column.id !== activeColumnId && cell.column.id !== "select";
30282
+ let cellPaddingClass;
30283
+ if (cell.column.id === "select") {
30284
+ cellPaddingClass = "p-0";
30285
+ } else {
30286
+ cellPaddingClass = "[&:has([role=checkbox])]:pr-0";
30287
+ }
30288
+ const actionsPaddingClass = cell.column.id === "actions" ? "py-1.5" : void 0;
30289
+ let cellStyle;
30290
+ if (cell.column.id === "select") {
30291
+ cellStyle = createFixedWidthStyle(TABLE_TOKENS.selectionColumnWidth);
30292
+ } else if (cell.column.id === "actions") {
30293
+ cellStyle = createFixedWidthStyle(TABLE_TOKENS.actionsColumnWidth);
30294
+ } else {
30295
+ cellStyle = { width: cell.column.getSize() };
30296
+ }
30297
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
30298
+ "td",
30299
+ {
30300
+ className: cn$1(
30301
+ "px-4 py-2.5 align-middle text-xs font-normal",
30302
+ cellPaddingClass,
30303
+ actionsPaddingClass,
30304
+ getAlignmentClass(
30305
+ cell.column.columnDef.meta?.align
30306
+ ),
30307
+ isOtherColumnDimmed ? "opacity-40" : void 0
30308
+ ),
30309
+ style: cellStyle,
30310
+ "data-col-id": cell.column.id,
30311
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
30312
+ CellContent,
30313
+ {
30314
+ align: cell.column.columnDef.meta?.align,
30315
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
30316
+ }
30317
+ )
30318
+ },
30319
+ cell.id
30320
+ );
30321
+ }
30322
+ function getVisibleCellsInOrder(row, isDragging, renderOrder) {
30323
+ if (!isDragging) {
30324
+ return row.getVisibleCells();
30325
+ }
30326
+ return row.getVisibleCells().slice().sort((a2, b) => {
30327
+ const ia = renderOrder.indexOf(a2.column.id);
30328
+ const ib = renderOrder.indexOf(b.column.id);
30329
+ return ia - ib;
30330
+ });
30331
+ }
30031
30332
  function TableBody({
30032
30333
  loading,
30033
30334
  resolvedColumns,
30034
30335
  rows,
30035
30336
  renderOrder,
30036
30337
  isDragging,
30037
- activeColumnId
30338
+ activeColumnId,
30339
+ skeletonRowCount = 5
30038
30340
  }) {
30039
- return /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { className: "[&_tr:last-child]:border-0", children: loading ? [...Array(5)].map((_, i) => /* @__PURE__ */ jsxRuntimeExports.jsx("tr", { children: resolvedColumns.map((column, j) => /* @__PURE__ */ jsxRuntimeExports.jsx(
30040
- "td",
30041
- {
30042
- className: cn$1(
30043
- "px-4 py-2.5 align-middle text-xs font-normal transition-all duration-300 ease-[cubic-bezier(0.23,1,0.32,1)] will-change-transform",
30044
- getAlignmentClass(column.meta?.align)
30045
- ),
30046
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Skeleton, { className: "h-6 w-full" })
30047
- },
30048
- j
30049
- )) }, i)) : rows?.length ? rows.map((row) => /* @__PURE__ */ jsxRuntimeExports.jsx(
30050
- "tr",
30051
- {
30052
- "data-state": row.getIsSelected() && "selected",
30053
- className: "border-b transition-colors hover:bg-[var(--accent)] data-[state=selected]:bg-muted",
30054
- children: (isDragging ? row.getVisibleCells().slice().sort((a2, b) => {
30055
- const ia = renderOrder.indexOf(a2.column.id);
30056
- const ib = renderOrder.indexOf(b.column.id);
30057
- return ia - ib;
30058
- }) : row.getVisibleCells()).map((cell) => {
30059
- const isOtherColumnDimmed = isDragging && activeColumnId != null && cell.column.id !== activeColumnId && cell.column.id !== "select";
30060
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
30061
- "td",
30062
- {
30063
- className: cn$1(
30064
- "px-4 py-2.5 align-middle text-xs font-normal",
30065
- cell.column.id === "select" ? "p-0" : "[&:has([role=checkbox])]:pr-0",
30066
- cell.column.id === "actions" ? "py-1.5" : void 0,
30067
- getAlignmentClass(
30068
- cell.column.columnDef.meta?.align
30069
- ),
30070
- isOtherColumnDimmed ? "opacity-40" : void 0
30071
- ),
30072
- style: cell.column.id === "select" ? {
30073
- width: TABLE_TOKENS.selectionColumnWidth,
30074
- minWidth: TABLE_TOKENS.selectionColumnWidth,
30075
- maxWidth: TABLE_TOKENS.selectionColumnWidth
30076
- } : cell.column.id === "actions" ? {
30077
- width: TABLE_TOKENS.actionsColumnWidth,
30078
- minWidth: TABLE_TOKENS.actionsColumnWidth,
30079
- maxWidth: TABLE_TOKENS.actionsColumnWidth
30080
- } : { width: cell.column.getSize() },
30081
- "data-col-id": cell.column.id,
30082
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(
30083
- CellContent,
30084
- {
30085
- align: cell.column.columnDef.meta?.align,
30086
- children: flexRender(cell.column.columnDef.cell, cell.getContext())
30087
- }
30088
- )
30089
- },
30090
- cell.id
30091
- );
30092
- })
30093
- },
30094
- row.id
30095
- )) : /* @__PURE__ */ jsxRuntimeExports.jsx("tr", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("td", { colSpan: resolvedColumns.length, className: "h-24 text-center", children: "No results." }) }) });
30341
+ let tableContent;
30342
+ if (loading) {
30343
+ tableContent = renderSkeletonRows(skeletonRowCount, resolvedColumns);
30344
+ } else if (rows?.length) {
30345
+ tableContent = rows.map((row) => {
30346
+ const visibleCells = getVisibleCellsInOrder(row, isDragging, renderOrder);
30347
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
30348
+ "tr",
30349
+ {
30350
+ "data-state": row.getIsSelected() && "selected",
30351
+ className: "border-b transition-colors hover:bg-[var(--accent)] data-[state=selected]:bg-muted",
30352
+ children: visibleCells.map(
30353
+ (cell) => renderTableCell(cell, isDragging, activeColumnId)
30354
+ )
30355
+ },
30356
+ row.id
30357
+ );
30358
+ });
30359
+ } else {
30360
+ tableContent = /* @__PURE__ */ jsxRuntimeExports.jsx("tr", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("td", { colSpan: resolvedColumns.length, className: "h-24 text-center", children: "No results." }) });
30361
+ }
30362
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { className: "[&_tr:last-child]:border-0", children: tableContent });
30096
30363
  }
30097
30364
  function BatchActionsToolbar({
30098
30365
  selectedCount,
@@ -30133,6 +30400,149 @@ function ColGroup({ columns, debug: debug2 }) {
30133
30400
  return /* @__PURE__ */ jsxRuntimeExports.jsx("col", { style: { width } }, String(col.id));
30134
30401
  }) });
30135
30402
  }
30403
+ function useDataTableHandlers({
30404
+ table,
30405
+ controllerOnBatchAction,
30406
+ onPaginationChange,
30407
+ setIsBodyScrolled,
30408
+ isBodyScrolled
30409
+ }) {
30410
+ const handleBatchAction = React.useCallback(
30411
+ (action) => {
30412
+ if (!controllerOnBatchAction) return;
30413
+ const selectedRows = table.getFilteredSelectedRowModel().rows.map((row) => row.original);
30414
+ controllerOnBatchAction(action, selectedRows);
30415
+ },
30416
+ [controllerOnBatchAction, table]
30417
+ );
30418
+ const handleScroll2 = React.useCallback(
30419
+ (e) => {
30420
+ const scrolled = (e.currentTarget?.scrollTop ?? 0) > 0;
30421
+ if (scrolled !== isBodyScrolled) setIsBodyScrolled(scrolled);
30422
+ },
30423
+ [isBodyScrolled, setIsBodyScrolled]
30424
+ );
30425
+ const handlePageChange = React.useCallback(
30426
+ (pageIndex) => {
30427
+ if (!onPaginationChange) return;
30428
+ onPaginationChange(
30429
+ pageIndex,
30430
+ table.getState().pagination?.pageSize ?? 25
30431
+ );
30432
+ },
30433
+ [onPaginationChange, table]
30434
+ );
30435
+ const handlePageSizeChange = React.useCallback(
30436
+ (pageSize) => {
30437
+ if (!onPaginationChange) return;
30438
+ onPaginationChange(table.getState().pagination?.pageIndex ?? 0, pageSize);
30439
+ },
30440
+ [onPaginationChange, table]
30441
+ );
30442
+ const handleExport = React.useCallback(() => {
30443
+ exportTableToCSV(table);
30444
+ }, [table]);
30445
+ return {
30446
+ handleBatchAction,
30447
+ handleScroll: handleScroll2,
30448
+ handlePageChange,
30449
+ handlePageSizeChange,
30450
+ handleExport
30451
+ };
30452
+ }
30453
+ function renderEmptyState(emptyState) {
30454
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
30455
+ "div",
30456
+ {
30457
+ className: "mmc-table-empty flex h-full w-full items-center justify-center",
30458
+ role: "region",
30459
+ "aria-label": "Empty state",
30460
+ children: emptyState
30461
+ }
30462
+ );
30463
+ }
30464
+ function renderTableLayout({
30465
+ toolbar,
30466
+ batchActions,
30467
+ scrollArea,
30468
+ pagination
30469
+ }) {
30470
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full flex flex-col min-h-0", children: [
30471
+ toolbar,
30472
+ batchActions,
30473
+ scrollArea,
30474
+ pagination
30475
+ ] });
30476
+ }
30477
+ function renderTableContent({
30478
+ table,
30479
+ loading,
30480
+ resolvedColumns,
30481
+ renderOrder,
30482
+ isDragging,
30483
+ activeColumnId,
30484
+ skeletonRowCount,
30485
+ isBodyScrolled,
30486
+ sortableHeaderIds,
30487
+ clampRef,
30488
+ sensors,
30489
+ handleDragStart,
30490
+ handleDragOver,
30491
+ handleDragEnd,
30492
+ tableRef,
30493
+ debug: debug2
30494
+ }) {
30495
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
30496
+ DndContext,
30497
+ {
30498
+ sensors,
30499
+ collisionDetection: closestCenter,
30500
+ modifiers: [restrictToHorizontalAxis],
30501
+ onDragStart: handleDragStart,
30502
+ onDragOver: handleDragOver,
30503
+ onDragEnd: handleDragEnd,
30504
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
30505
+ "table",
30506
+ {
30507
+ ref: tableRef,
30508
+ className: "w-full caption-bottom text-sm table-fixed",
30509
+ children: [
30510
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
30511
+ ColGroup,
30512
+ {
30513
+ columns: table.getVisibleLeafColumns(),
30514
+ debug: debug2
30515
+ }
30516
+ ),
30517
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
30518
+ TableHeader,
30519
+ {
30520
+ headerGroups: table.getHeaderGroups(),
30521
+ sortableHeaderIds,
30522
+ isBodyScrolled,
30523
+ isDragging,
30524
+ activeColumnId,
30525
+ clampRef
30526
+ }
30527
+ ),
30528
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
30529
+ TableBody,
30530
+ {
30531
+ loading,
30532
+ resolvedColumns,
30533
+ rows: table.getRowModel().rows,
30534
+ renderOrder,
30535
+ isDragging,
30536
+ activeColumnId,
30537
+ skeletonRowCount
30538
+ }
30539
+ )
30540
+ ]
30541
+ }
30542
+ )
30543
+ }
30544
+ );
30545
+ }
30136
30546
  function DataTable({
30137
30547
  columns,
30138
30548
  data,
@@ -30143,6 +30553,9 @@ function DataTable({
30143
30553
  toolbar,
30144
30554
  emptyState,
30145
30555
  forceEmptyState,
30556
+ manualPagination = false,
30557
+ pageCount,
30558
+ totalRowCount,
30146
30559
  onRowSelectionChange,
30147
30560
  onSortingChange,
30148
30561
  onPaginationChange,
@@ -30172,6 +30585,8 @@ function DataTable({
30172
30585
  tableId,
30173
30586
  disableGlobalFilter: toolbar?.disableGlobalFilter,
30174
30587
  customGlobalFilterFn,
30588
+ manualPagination,
30589
+ pageCount,
30175
30590
  onRowSelectionChange,
30176
30591
  onSortingChange,
30177
30592
  onPaginationChange,
@@ -30181,208 +30596,110 @@ function DataTable({
30181
30596
  onRowClick,
30182
30597
  onExportComplete
30183
30598
  });
30184
- const [isDragging, setIsDragging] = React.useState(false);
30185
- const [activeColumnId, setActiveColumnId] = React.useState(
30186
- null
30187
- );
30188
- const [tempColumnOrder, setTempColumnOrder] = React.useState([]);
30189
30599
  const containerRef = React.useRef(null);
30190
30600
  const tableRef = React.useRef(null);
30191
- const clampRef = React.useRef({
30192
- minX: Number.NEGATIVE_INFINITY,
30193
- maxX: Number.POSITIVE_INFINITY
30194
- });
30195
30601
  const [isBodyScrolled, setIsBodyScrolled] = React.useState(false);
30196
30602
  const sensors = useSensors(
30197
30603
  useSensor(PointerSensor, { activationConstraint: { distance: 10 } }),
30198
30604
  useSensor(KeyboardSensor)
30199
30605
  );
30200
- const stateColumnOrder = table.getState().columnOrder;
30201
- const allLeafColumnIds = table.getAllLeafColumns().map((c2) => c2.id);
30202
- const baseOrder = stateColumnOrder?.length ? stateColumnOrder : allLeafColumnIds;
30203
- const currentOrder = pinBoundaries(baseOrder);
30204
- const headerGroups = table.getHeaderGroups();
30205
- const visibleOrder = headerGroups.length ? headerGroups[0].headers.filter((h) => h.column.getIsVisible()).map((h) => h.column.id) : currentOrder;
30206
- const renderOrder = pinBoundaries(
30207
- isDragging && tempColumnOrder.length ? tempColumnOrder : visibleOrder
30208
- );
30209
- const sortableHeaderIds = React.useMemo(
30210
- () => renderOrder.filter((id) => id !== "select" && id !== "actions"),
30211
- [renderOrder]
30212
- );
30213
- const handleDragStart = React.useCallback(
30214
- (event) => {
30215
- setIsDragging(true);
30216
- setActiveColumnId(String(event.active.id));
30217
- const groups = table.getHeaderGroups();
30218
- const visible = groups.length ? groups[0].headers.filter((h) => h.column.getIsVisible()).map((h) => h.column.id) : currentOrder;
30219
- setTempColumnOrder(pinBoundaries(visible));
30220
- try {
30221
- const activeId = String(event.active.id);
30222
- const th = document.querySelector(`th[data-col-id="${activeId}"]`);
30223
- const container = containerRef.current;
30224
- if (th && container) {
30225
- const t = th.getBoundingClientRect();
30226
- const c2 = container.getBoundingClientRect();
30227
- clampRef.current = { minX: c2.left - t.left, maxX: c2.right - t.right };
30228
- } else {
30229
- clampRef.current = {
30230
- minX: Number.NEGATIVE_INFINITY,
30231
- maxX: Number.POSITIVE_INFINITY
30232
- };
30233
- }
30234
- } catch {
30235
- clampRef.current = {
30236
- minX: Number.NEGATIVE_INFINITY,
30237
- maxX: Number.POSITIVE_INFINITY
30238
- };
30239
- }
30240
- },
30241
- [currentOrder, table]
30606
+ const {
30607
+ isDragging,
30608
+ activeColumnId,
30609
+ renderOrder,
30610
+ sortableHeaderIds,
30611
+ clampRef,
30612
+ handleDragStart,
30613
+ handleDragOver,
30614
+ handleDragEnd
30615
+ } = useDragAndDrop({
30616
+ table,
30617
+ containerRef
30618
+ });
30619
+ const {
30620
+ handleBatchAction,
30621
+ handleScroll: handleScroll2,
30622
+ handlePageChange,
30623
+ handlePageSizeChange,
30624
+ handleExport
30625
+ } = useDataTableHandlers({
30626
+ table,
30627
+ controllerOnBatchAction,
30628
+ onPaginationChange,
30629
+ setIsBodyScrolled,
30630
+ isBodyScrolled
30631
+ });
30632
+ const isForcedEmpty = !loading && Boolean(forceEmptyState) && Boolean(emptyState);
30633
+ const selectedRowCount = table.getFilteredSelectedRowModel().rows.length;
30634
+ const hasSelectedRows = selectedRowCount > 0;
30635
+ const skeletonRowCount = loading ? table.getState().pagination?.pageSize ?? 25 : void 0;
30636
+ const batchActionHandler = controllerOnBatchAction ? handleBatchAction : void 0;
30637
+ const pageChangeHandler = onPaginationChange ? handlePageChange : void 0;
30638
+ const pageSizeChangeHandler = onPaginationChange ? handlePageSizeChange : void 0;
30639
+ const tableContent = isForcedEmpty ? renderEmptyState(emptyState) : renderTableContent({
30640
+ table,
30641
+ loading,
30642
+ resolvedColumns,
30643
+ renderOrder,
30644
+ isDragging,
30645
+ activeColumnId,
30646
+ skeletonRowCount,
30647
+ isBodyScrolled,
30648
+ sortableHeaderIds,
30649
+ clampRef,
30650
+ sensors,
30651
+ handleDragStart,
30652
+ handleDragOver,
30653
+ handleDragEnd,
30654
+ tableRef,
30655
+ debug: debug2
30656
+ });
30657
+ const toolbarElement = /* @__PURE__ */ jsxRuntimeExports.jsx(
30658
+ DataTableToolbar,
30659
+ {
30660
+ table,
30661
+ loading,
30662
+ globalFilter: globalFilter ?? "",
30663
+ onGlobalFilterChange: setGlobalFilter,
30664
+ onResetColumns: handleResetColumns,
30665
+ columnRegistry,
30666
+ onExport: handleExport,
30667
+ onExportComplete: controllerOnExportComplete,
30668
+ options: toolbar
30669
+ }
30242
30670
  );
30243
- const handleDragOver = React.useCallback((event) => {
30244
- const { active, over } = event;
30245
- if (!over) return;
30246
- const activeId = String(active.id);
30247
- const overId = String(over.id);
30248
- if (activeId === overId) return;
30249
- setTempColumnOrder((prev) => {
30250
- const from = prev.indexOf(activeId);
30251
- const to = prev.indexOf(overId);
30252
- if (from === -1 || to === -1) return prev;
30253
- const moved = arrayMove(prev, from, to);
30254
- if (moved.includes("select")) {
30255
- const next = ["select", ...moved.filter((id) => id !== "select")];
30256
- return next;
30257
- }
30258
- return moved;
30259
- });
30260
- }, []);
30261
- const handleDragEnd = React.useCallback(
30262
- (_event) => {
30263
- setIsDragging(false);
30264
- setActiveColumnId(null);
30265
- if (!tempColumnOrder.length) return;
30266
- const normalizedTempOrder = pinBoundaries(tempColumnOrder);
30267
- const prev = JSON.stringify(currentOrder);
30268
- const next = JSON.stringify(normalizedTempOrder);
30269
- if (prev !== next) {
30270
- table.setColumnOrder(normalizedTempOrder);
30271
- }
30272
- setTempColumnOrder([]);
30273
- },
30274
- [currentOrder, table, tempColumnOrder]
30671
+ const batchActions = hasSelectedRows ? /* @__PURE__ */ jsxRuntimeExports.jsx(
30672
+ BatchActionsToolbar,
30673
+ {
30674
+ selectedCount: selectedRowCount,
30675
+ onBatchAction: batchActionHandler
30676
+ }
30677
+ ) : null;
30678
+ const scrollArea = /* @__PURE__ */ jsxRuntimeExports.jsx(
30679
+ "div",
30680
+ {
30681
+ className: "relative w-full flex-1 min-h-0 overflow-auto",
30682
+ ref: containerRef,
30683
+ onScroll: handleScroll2,
30684
+ children: tableContent
30685
+ }
30275
30686
  );
30276
- const isForcedEmpty = !loading && Boolean(forceEmptyState) && Boolean(emptyState);
30277
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full h-full flex flex-col min-h-0", children: [
30278
- /* @__PURE__ */ jsxRuntimeExports.jsx(
30279
- DataTableToolbar,
30280
- {
30281
- table,
30282
- loading,
30283
- globalFilter: globalFilter ?? "",
30284
- onGlobalFilterChange: setGlobalFilter,
30285
- onResetColumns: handleResetColumns,
30286
- columnRegistry,
30287
- onExport: () => exportTableToCSV(table),
30288
- onExportComplete: controllerOnExportComplete,
30289
- options: toolbar
30290
- }
30291
- ),
30292
- table.getFilteredSelectedRowModel().rows.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
30293
- BatchActionsToolbar,
30294
- {
30295
- selectedCount: table.getFilteredSelectedRowModel().rows.length,
30296
- onBatchAction: controllerOnBatchAction ? (action) => {
30297
- const selectedRows = table.getFilteredSelectedRowModel().rows.map((row) => row.original);
30298
- controllerOnBatchAction(action, selectedRows);
30299
- } : void 0
30300
- }
30301
- ),
30302
- /* @__PURE__ */ jsxRuntimeExports.jsx(
30303
- "div",
30304
- {
30305
- className: "relative w-full flex-1 min-h-0 overflow-auto",
30306
- ref: containerRef,
30307
- onScroll: (e) => {
30308
- const t = e.currentTarget;
30309
- const scrolled = (t?.scrollTop ?? 0) > 0;
30310
- if (scrolled !== isBodyScrolled) setIsBodyScrolled(scrolled);
30311
- },
30312
- children: isForcedEmpty ? /* @__PURE__ */ jsxRuntimeExports.jsx(
30313
- "div",
30314
- {
30315
- className: "mmc-table-empty flex h-full w-full items-center justify-center",
30316
- role: "region",
30317
- "aria-label": "Empty state",
30318
- children: emptyState
30319
- }
30320
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
30321
- DndContext,
30322
- {
30323
- sensors,
30324
- collisionDetection: closestCenter,
30325
- modifiers: [restrictToHorizontalAxis],
30326
- onDragStart: handleDragStart,
30327
- onDragOver: handleDragOver,
30328
- onDragEnd: handleDragEnd,
30329
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
30330
- "table",
30331
- {
30332
- ref: tableRef,
30333
- className: "w-full caption-bottom text-sm table-fixed",
30334
- children: [
30335
- /* @__PURE__ */ jsxRuntimeExports.jsx(
30336
- ColGroup,
30337
- {
30338
- columns: table.getVisibleLeafColumns(),
30339
- debug: debug2
30340
- }
30341
- ),
30342
- /* @__PURE__ */ jsxRuntimeExports.jsx(
30343
- TableHeader,
30344
- {
30345
- headerGroups: table.getHeaderGroups(),
30346
- sortableHeaderIds,
30347
- isBodyScrolled,
30348
- isDragging,
30349
- activeColumnId,
30350
- clampRef
30351
- }
30352
- ),
30353
- /* @__PURE__ */ jsxRuntimeExports.jsx(
30354
- TableBody,
30355
- {
30356
- loading,
30357
- resolvedColumns,
30358
- rows: table.getRowModel().rows,
30359
- renderOrder,
30360
- isDragging,
30361
- activeColumnId
30362
- }
30363
- )
30364
- ]
30365
- }
30366
- )
30367
- }
30368
- )
30369
- }
30370
- ),
30371
- isForcedEmpty ? null : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-t border-border bg-[var(--tablehead-bg)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
30372
- DataTablePagination,
30373
- {
30374
- table,
30375
- onPageChange: onPaginationChange ? (pageIndex) => onPaginationChange(
30376
- pageIndex,
30377
- table.getState().pagination?.pageSize ?? 25
30378
- ) : void 0,
30379
- onPageSizeChange: onPaginationChange ? (pageSize) => onPaginationChange(
30380
- table.getState().pagination?.pageIndex ?? 0,
30381
- pageSize
30382
- ) : void 0
30383
- }
30384
- ) })
30385
- ] });
30687
+ const pagination = !isForcedEmpty ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 border-t border-border bg-[var(--tablehead-bg)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
30688
+ DataTablePagination,
30689
+ {
30690
+ table,
30691
+ manualPagination,
30692
+ totalRowCount,
30693
+ onPageChange: pageChangeHandler,
30694
+ onPageSizeChange: pageSizeChangeHandler
30695
+ }
30696
+ ) }) : null;
30697
+ return renderTableLayout({
30698
+ toolbar: toolbarElement,
30699
+ batchActions,
30700
+ scrollArea,
30701
+ pagination
30702
+ });
30386
30703
  }
30387
30704
  const ALIGNMENT_PRESETS = {
30388
30705
  NAME: "left",
@@ -32040,6 +32357,9 @@ function ResponsiveTable({
32040
32357
  toolbarOptions,
32041
32358
  emptyState,
32042
32359
  forceEmptyState,
32360
+ manualPagination,
32361
+ pageCount,
32362
+ totalRowCount,
32043
32363
  onRowSelectionChange,
32044
32364
  onSortingChange,
32045
32365
  onPaginationChange,
@@ -32064,6 +32384,9 @@ function ResponsiveTable({
32064
32384
  toolbar: toolbarOptions,
32065
32385
  emptyState,
32066
32386
  forceEmptyState,
32387
+ manualPagination,
32388
+ pageCount,
32389
+ totalRowCount,
32067
32390
  onRowSelectionChange,
32068
32391
  onSortingChange,
32069
32392
  onPaginationChange,