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

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,129 @@ 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,
30340
+ onRowClick
30038
30341
  }) {
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
30342
+ let tableContent;
30343
+ if (loading) {
30344
+ tableContent = renderSkeletonRows(skeletonRowCount, resolvedColumns);
30345
+ } else if (rows?.length) {
30346
+ tableContent = rows.map((row) => {
30347
+ const visibleCells = getVisibleCellsInOrder(row, isDragging, renderOrder);
30348
+ const handleRowClick = onRowClick ? (event) => {
30349
+ const target = event.target;
30350
+ if (!target) return;
30351
+ const interactive = target.closest(
30352
+ 'a,button,input,select,textarea,label,[role=checkbox],[data-slot="table-action-trigger"]'
30091
30353
  );
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." }) }) });
30354
+ if (interactive) return;
30355
+ onRowClick(row.original, row.index);
30356
+ } : void 0;
30357
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
30358
+ "tr",
30359
+ {
30360
+ "data-state": row.getIsSelected() && "selected",
30361
+ className: cn$1(
30362
+ "border-b transition-colors hover:bg-[var(--accent)] data-[state=selected]:bg-muted",
30363
+ onRowClick && "cursor-pointer"
30364
+ ),
30365
+ onClick: handleRowClick,
30366
+ children: visibleCells.map(
30367
+ (cell) => renderTableCell(cell, isDragging, activeColumnId)
30368
+ )
30369
+ },
30370
+ row.id
30371
+ );
30372
+ });
30373
+ } else {
30374
+ tableContent = /* @__PURE__ */ jsxRuntimeExports.jsx("tr", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("td", { colSpan: resolvedColumns.length, className: "h-24 text-center", children: "No results." }) });
30375
+ }
30376
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { className: "[&_tr:last-child]:border-0", children: tableContent });
30096
30377
  }
30097
30378
  function BatchActionsToolbar({
30098
30379
  selectedCount,
@@ -30133,6 +30414,151 @@ function ColGroup({ columns, debug: debug2 }) {
30133
30414
  return /* @__PURE__ */ jsxRuntimeExports.jsx("col", { style: { width } }, String(col.id));
30134
30415
  }) });
30135
30416
  }
30417
+ function useDataTableHandlers({
30418
+ table,
30419
+ controllerOnBatchAction,
30420
+ onPaginationChange,
30421
+ setIsBodyScrolled,
30422
+ isBodyScrolled
30423
+ }) {
30424
+ const handleBatchAction = React.useCallback(
30425
+ (action) => {
30426
+ if (!controllerOnBatchAction) return;
30427
+ const selectedRows = table.getFilteredSelectedRowModel().rows.map((row) => row.original);
30428
+ controllerOnBatchAction(action, selectedRows);
30429
+ },
30430
+ [controllerOnBatchAction, table]
30431
+ );
30432
+ const handleScroll2 = React.useCallback(
30433
+ (e) => {
30434
+ const scrolled = (e.currentTarget?.scrollTop ?? 0) > 0;
30435
+ if (scrolled !== isBodyScrolled) setIsBodyScrolled(scrolled);
30436
+ },
30437
+ [isBodyScrolled, setIsBodyScrolled]
30438
+ );
30439
+ const handlePageChange = React.useCallback(
30440
+ (pageIndex) => {
30441
+ if (!onPaginationChange) return;
30442
+ onPaginationChange(
30443
+ pageIndex,
30444
+ table.getState().pagination?.pageSize ?? 25
30445
+ );
30446
+ },
30447
+ [onPaginationChange, table]
30448
+ );
30449
+ const handlePageSizeChange = React.useCallback(
30450
+ (pageSize) => {
30451
+ if (!onPaginationChange) return;
30452
+ onPaginationChange(table.getState().pagination?.pageIndex ?? 0, pageSize);
30453
+ },
30454
+ [onPaginationChange, table]
30455
+ );
30456
+ const handleExport = React.useCallback(() => {
30457
+ exportTableToCSV(table);
30458
+ }, [table]);
30459
+ return {
30460
+ handleBatchAction,
30461
+ handleScroll: handleScroll2,
30462
+ handlePageChange,
30463
+ handlePageSizeChange,
30464
+ handleExport
30465
+ };
30466
+ }
30467
+ function renderEmptyState(emptyState) {
30468
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
30469
+ "div",
30470
+ {
30471
+ className: "mmc-table-empty flex h-full w-full items-center justify-center",
30472
+ role: "region",
30473
+ "aria-label": "Empty state",
30474
+ children: emptyState
30475
+ }
30476
+ );
30477
+ }
30478
+ function renderTableLayout({
30479
+ toolbar,
30480
+ batchActions,
30481
+ scrollArea,
30482
+ pagination
30483
+ }) {
30484
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full flex flex-col min-h-0", children: [
30485
+ toolbar,
30486
+ batchActions,
30487
+ scrollArea,
30488
+ pagination
30489
+ ] });
30490
+ }
30491
+ function renderTableContent({
30492
+ table,
30493
+ loading,
30494
+ resolvedColumns,
30495
+ renderOrder,
30496
+ isDragging,
30497
+ activeColumnId,
30498
+ skeletonRowCount,
30499
+ isBodyScrolled,
30500
+ sortableHeaderIds,
30501
+ clampRef,
30502
+ sensors,
30503
+ handleDragStart,
30504
+ handleDragOver,
30505
+ handleDragEnd,
30506
+ tableRef,
30507
+ debug: debug2,
30508
+ onRowClick
30509
+ }) {
30510
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
30511
+ DndContext,
30512
+ {
30513
+ sensors,
30514
+ collisionDetection: closestCenter,
30515
+ modifiers: [restrictToHorizontalAxis],
30516
+ onDragStart: handleDragStart,
30517
+ onDragOver: handleDragOver,
30518
+ onDragEnd: handleDragEnd,
30519
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
30520
+ "table",
30521
+ {
30522
+ ref: tableRef,
30523
+ className: "w-full caption-bottom text-sm table-fixed",
30524
+ children: [
30525
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
30526
+ ColGroup,
30527
+ {
30528
+ columns: table.getVisibleLeafColumns(),
30529
+ debug: debug2
30530
+ }
30531
+ ),
30532
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
30533
+ TableHeader,
30534
+ {
30535
+ headerGroups: table.getHeaderGroups(),
30536
+ sortableHeaderIds,
30537
+ isBodyScrolled,
30538
+ isDragging,
30539
+ activeColumnId,
30540
+ clampRef
30541
+ }
30542
+ ),
30543
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
30544
+ TableBody,
30545
+ {
30546
+ loading,
30547
+ resolvedColumns,
30548
+ rows: table.getRowModel().rows,
30549
+ renderOrder,
30550
+ isDragging,
30551
+ activeColumnId,
30552
+ skeletonRowCount,
30553
+ onRowClick
30554
+ }
30555
+ )
30556
+ ]
30557
+ }
30558
+ )
30559
+ }
30560
+ );
30561
+ }
30136
30562
  function DataTable({
30137
30563
  columns,
30138
30564
  data,
@@ -30143,6 +30569,9 @@ function DataTable({
30143
30569
  toolbar,
30144
30570
  emptyState,
30145
30571
  forceEmptyState,
30572
+ manualPagination = false,
30573
+ pageCount,
30574
+ totalRowCount,
30146
30575
  onRowSelectionChange,
30147
30576
  onSortingChange,
30148
30577
  onPaginationChange,
@@ -30163,7 +30592,8 @@ function DataTable({
30163
30592
  setGlobalFilter,
30164
30593
  handleResetColumns,
30165
30594
  onBatchAction: controllerOnBatchAction,
30166
- onExportComplete: controllerOnExportComplete
30595
+ onExportComplete: controllerOnExportComplete,
30596
+ onRowClick: controllerOnRowClick
30167
30597
  } = useTableController({
30168
30598
  columns,
30169
30599
  data,
@@ -30172,6 +30602,8 @@ function DataTable({
30172
30602
  tableId,
30173
30603
  disableGlobalFilter: toolbar?.disableGlobalFilter,
30174
30604
  customGlobalFilterFn,
30605
+ manualPagination,
30606
+ pageCount,
30175
30607
  onRowSelectionChange,
30176
30608
  onSortingChange,
30177
30609
  onPaginationChange,
@@ -30181,208 +30613,111 @@ function DataTable({
30181
30613
  onRowClick,
30182
30614
  onExportComplete
30183
30615
  });
30184
- const [isDragging, setIsDragging] = React.useState(false);
30185
- const [activeColumnId, setActiveColumnId] = React.useState(
30186
- null
30187
- );
30188
- const [tempColumnOrder, setTempColumnOrder] = React.useState([]);
30189
30616
  const containerRef = React.useRef(null);
30190
30617
  const tableRef = React.useRef(null);
30191
- const clampRef = React.useRef({
30192
- minX: Number.NEGATIVE_INFINITY,
30193
- maxX: Number.POSITIVE_INFINITY
30194
- });
30195
30618
  const [isBodyScrolled, setIsBodyScrolled] = React.useState(false);
30196
30619
  const sensors = useSensors(
30197
30620
  useSensor(PointerSensor, { activationConstraint: { distance: 10 } }),
30198
30621
  useSensor(KeyboardSensor)
30199
30622
  );
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]
30623
+ const {
30624
+ isDragging,
30625
+ activeColumnId,
30626
+ renderOrder,
30627
+ sortableHeaderIds,
30628
+ clampRef,
30629
+ handleDragStart,
30630
+ handleDragOver,
30631
+ handleDragEnd
30632
+ } = useDragAndDrop({
30633
+ table,
30634
+ containerRef
30635
+ });
30636
+ const {
30637
+ handleBatchAction,
30638
+ handleScroll: handleScroll2,
30639
+ handlePageChange,
30640
+ handlePageSizeChange,
30641
+ handleExport
30642
+ } = useDataTableHandlers({
30643
+ table,
30644
+ controllerOnBatchAction,
30645
+ onPaginationChange,
30646
+ setIsBodyScrolled,
30647
+ isBodyScrolled
30648
+ });
30649
+ const isForcedEmpty = !loading && Boolean(forceEmptyState) && Boolean(emptyState);
30650
+ const selectedRowCount = table.getFilteredSelectedRowModel().rows.length;
30651
+ const hasSelectedRows = selectedRowCount > 0;
30652
+ const skeletonRowCount = loading ? table.getState().pagination?.pageSize ?? 25 : void 0;
30653
+ const batchActionHandler = controllerOnBatchAction ? handleBatchAction : void 0;
30654
+ const pageChangeHandler = onPaginationChange ? handlePageChange : void 0;
30655
+ const pageSizeChangeHandler = onPaginationChange ? handlePageSizeChange : void 0;
30656
+ const tableContent = isForcedEmpty ? renderEmptyState(emptyState) : renderTableContent({
30657
+ table,
30658
+ loading,
30659
+ resolvedColumns,
30660
+ renderOrder,
30661
+ isDragging,
30662
+ activeColumnId,
30663
+ skeletonRowCount,
30664
+ isBodyScrolled,
30665
+ sortableHeaderIds,
30666
+ clampRef,
30667
+ sensors,
30668
+ handleDragStart,
30669
+ handleDragOver,
30670
+ handleDragEnd,
30671
+ tableRef,
30672
+ debug: debug2,
30673
+ onRowClick: controllerOnRowClick
30674
+ });
30675
+ const toolbarElement = /* @__PURE__ */ jsxRuntimeExports.jsx(
30676
+ DataTableToolbar,
30677
+ {
30678
+ table,
30679
+ loading,
30680
+ globalFilter: globalFilter ?? "",
30681
+ onGlobalFilterChange: setGlobalFilter,
30682
+ onResetColumns: handleResetColumns,
30683
+ columnRegistry,
30684
+ onExport: handleExport,
30685
+ onExportComplete: controllerOnExportComplete,
30686
+ options: toolbar
30687
+ }
30242
30688
  );
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]
30689
+ const batchActions = hasSelectedRows ? /* @__PURE__ */ jsxRuntimeExports.jsx(
30690
+ BatchActionsToolbar,
30691
+ {
30692
+ selectedCount: selectedRowCount,
30693
+ onBatchAction: batchActionHandler
30694
+ }
30695
+ ) : null;
30696
+ const scrollArea = /* @__PURE__ */ jsxRuntimeExports.jsx(
30697
+ "div",
30698
+ {
30699
+ className: "relative w-full flex-1 min-h-0 overflow-auto",
30700
+ ref: containerRef,
30701
+ onScroll: handleScroll2,
30702
+ children: tableContent
30703
+ }
30275
30704
  );
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
- ] });
30705
+ const pagination = !isForcedEmpty ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 border-t border-border bg-[var(--tablehead-bg)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
30706
+ DataTablePagination,
30707
+ {
30708
+ table,
30709
+ manualPagination,
30710
+ totalRowCount,
30711
+ onPageChange: pageChangeHandler,
30712
+ onPageSizeChange: pageSizeChangeHandler
30713
+ }
30714
+ ) }) : null;
30715
+ return renderTableLayout({
30716
+ toolbar: toolbarElement,
30717
+ batchActions,
30718
+ scrollArea,
30719
+ pagination
30720
+ });
30386
30721
  }
30387
30722
  const ALIGNMENT_PRESETS = {
30388
30723
  NAME: "left",
@@ -32040,6 +32375,9 @@ function ResponsiveTable({
32040
32375
  toolbarOptions,
32041
32376
  emptyState,
32042
32377
  forceEmptyState,
32378
+ manualPagination,
32379
+ pageCount,
32380
+ totalRowCount,
32043
32381
  onRowSelectionChange,
32044
32382
  onSortingChange,
32045
32383
  onPaginationChange,
@@ -32064,6 +32402,9 @@ function ResponsiveTable({
32064
32402
  toolbar: toolbarOptions,
32065
32403
  emptyState,
32066
32404
  forceEmptyState,
32405
+ manualPagination,
32406
+ pageCount,
32407
+ totalRowCount,
32067
32408
  onRowSelectionChange,
32068
32409
  onSortingChange,
32069
32410
  onPaginationChange,