@rufous/ui 0.2.106 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.cjs +35 -12
- package/dist/main.css +27 -2
- package/dist/main.d.cts +28 -1
- package/dist/main.d.ts +28 -1
- package/dist/main.js +35 -12
- package/package.json +2 -2
package/dist/main.cjs
CHANGED
|
@@ -4439,6 +4439,12 @@ function DataGrid({
|
|
|
4439
4439
|
columns: initialColumnsProp,
|
|
4440
4440
|
data,
|
|
4441
4441
|
actions,
|
|
4442
|
+
loading = false,
|
|
4443
|
+
pagination = true,
|
|
4444
|
+
paginationMode = "client",
|
|
4445
|
+
rowCount,
|
|
4446
|
+
paginationModel,
|
|
4447
|
+
onPaginationModelChange,
|
|
4442
4448
|
pageSize: initialPageSize = 10,
|
|
4443
4449
|
pageSizeOptions = [5, 10, 25, 50],
|
|
4444
4450
|
title,
|
|
@@ -4479,6 +4485,23 @@ function DataGrid({
|
|
|
4479
4485
|
const [sortDirection, setSortDirection] = (0, import_react23.useState)(null);
|
|
4480
4486
|
const [filterText, setFilterText] = (0, import_react23.useState)("");
|
|
4481
4487
|
const [currentPage, setCurrentPage] = (0, import_react23.useState)(1);
|
|
4488
|
+
const activePage = paginationModel ? paginationModel.page + 1 : currentPage;
|
|
4489
|
+
const activePageSize = paginationModel ? paginationModel.pageSize : pageSize;
|
|
4490
|
+
const handlePageChange = (newPage) => {
|
|
4491
|
+
if (onPaginationModelChange) {
|
|
4492
|
+
onPaginationModelChange({ page: newPage - 1, pageSize: activePageSize });
|
|
4493
|
+
} else {
|
|
4494
|
+
setCurrentPage(newPage);
|
|
4495
|
+
}
|
|
4496
|
+
};
|
|
4497
|
+
const handlePageSizeChange = (newSize) => {
|
|
4498
|
+
if (onPaginationModelChange) {
|
|
4499
|
+
onPaginationModelChange({ page: 0, pageSize: newSize });
|
|
4500
|
+
} else {
|
|
4501
|
+
setPageSize(newSize);
|
|
4502
|
+
setCurrentPage(1);
|
|
4503
|
+
}
|
|
4504
|
+
};
|
|
4482
4505
|
const [resizingColumn, setResizingColumn] = (0, import_react23.useState)(null);
|
|
4483
4506
|
const [startX, setStartX] = (0, import_react23.useState)(0);
|
|
4484
4507
|
const [startWidth, setStartWidth] = (0, import_react23.useState)(0);
|
|
@@ -4711,11 +4734,14 @@ function DataGrid({
|
|
|
4711
4734
|
return 0;
|
|
4712
4735
|
});
|
|
4713
4736
|
}, [filteredData, sortField, sortDirection, resolvedColumns]);
|
|
4714
|
-
const
|
|
4737
|
+
const isServer = paginationMode === "server";
|
|
4738
|
+
const totalRows = isServer ? rowCount ?? data.length : filteredData.length;
|
|
4739
|
+
const totalPages = Math.max(1, Math.ceil(totalRows / activePageSize));
|
|
4715
4740
|
const paginatedData = (0, import_react23.useMemo)(() => {
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4741
|
+
if (isServer) return data;
|
|
4742
|
+
const start = (activePage - 1) * activePageSize;
|
|
4743
|
+
return sortedData.slice(start, start + activePageSize);
|
|
4744
|
+
}, [isServer, data, sortedData, activePage, activePageSize]);
|
|
4719
4745
|
const handleExport = () => {
|
|
4720
4746
|
const exportableCols = resolvedColumns.filter((c) => !c.hidden && c.isExportable !== false);
|
|
4721
4747
|
const headers = exportableCols.map((c) => c.headerName).join(",");
|
|
@@ -4810,7 +4836,7 @@ function DataGrid({
|
|
|
4810
4836
|
onClick: () => setShowManageColumns(true)
|
|
4811
4837
|
},
|
|
4812
4838
|
/* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.Columns, { size: 16 })
|
|
4813
|
-
)), /* @__PURE__ */ import_react23.default.createElement("button", { className: "dg-action-btn", onClick: handleExport }, /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.Download, { size: 14 }), " Export CSV"), headerActions && /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-header-slot ${alignClass(headerActions.align)}` }, headerActions.content))), /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-toolbar ${alignClass(toolbarContent?.align)}` }, toolbarContent?.content || ""), /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-table-wrap${paginatedData.length === 0 ? " dg-table-wrap--empty" : ""}` }, /* @__PURE__ */ import_react23.default.createElement("table", { className: "dg-table" }, /* @__PURE__ */ import_react23.default.createElement("thead", null, /* @__PURE__ */ import_react23.default.createElement("tr", null, visibleColumns.map((col, idx) => {
|
|
4839
|
+
)), /* @__PURE__ */ import_react23.default.createElement("button", { className: "dg-action-btn", onClick: handleExport }, /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.Download, { size: 14 }), " Export CSV"), headerActions && /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-header-slot ${alignClass(headerActions.align)}` }, headerActions.content))), /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-toolbar ${alignClass(toolbarContent?.align)}` }, toolbarContent?.content || ""), /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-table-wrap${paginatedData.length === 0 && !loading ? " dg-table-wrap--empty" : ""}` }, loading && /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-loading-overlay" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-loading-spinner" })), /* @__PURE__ */ import_react23.default.createElement("table", { className: "dg-table" }, /* @__PURE__ */ import_react23.default.createElement("thead", null, /* @__PURE__ */ import_react23.default.createElement("tr", null, visibleColumns.map((col, idx) => {
|
|
4814
4840
|
const colField = String(col.field);
|
|
4815
4841
|
const width = columnWidths[colField] || 200;
|
|
4816
4842
|
const leftOffset = getLeftOffset(col, idx);
|
|
@@ -4924,17 +4950,14 @@ function DataGrid({
|
|
|
4924
4950
|
},
|
|
4925
4951
|
action.icon
|
|
4926
4952
|
)))));
|
|
4927
|
-
})()))))), paginatedData.length === 0 && /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-empty-state" }, /* @__PURE__ */ import_react23.default.createElement("svg", { className: "dg-empty-icon", viewBox: "0 0 200 160", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ import_react23.default.createElement("rect", { x: "20", y: "30", width: "160", height: "100", rx: "8", fill: "var(--hover-color)", stroke: "var(--border-color)", strokeWidth: "1.5" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "20", y: "30", width: "160", height: "28", rx: "8", fill: "var(--border-color)", opacity: "0.5" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "20", y: "50", width: "160", height: "8", rx: "0", fill: "var(--border-color)", opacity: "0.5" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "72", y1: "30", x2: "72", y2: "130", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "128", y1: "30", x2: "128", y2: "130", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "20", y1: "78", x2: "180", y2: "78", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "20", y1: "104", x2: "180", y2: "104", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "32", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "84", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "140", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "32", y: "113", width: "20", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "84", y: "113", width: "32", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "140", y: "113", width: "20", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ import_react23.default.createElement("circle", { cx: "148", cy: "108", r: "26", fill: "var(--surface-color)", stroke: "var(--border-color)", strokeWidth: "1.5" }), /* @__PURE__ */ import_react23.default.createElement("circle", { cx: "145", cy: "105", r: "10", stroke: "var(--text-secondary)", strokeWidth: "2.5", opacity: "0.5" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "152", y1: "113", x2: "161", y2: "122", stroke: "var(--text-secondary)", strokeWidth: "2.5", strokeLinecap: "round", opacity: "0.5" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "141", y1: "101", x2: "149", y2: "109", stroke: "var(--text-secondary)", strokeWidth: "2", strokeLinecap: "round", opacity: "0.5" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "149", y1: "101", x2: "141", y2: "109", stroke: "var(--text-secondary)", strokeWidth: "2", strokeLinecap: "round", opacity: "0.5" })), /* @__PURE__ */ import_react23.default.createElement("p", { className: "dg-empty-title" }, "No data found"), /* @__PURE__ */ import_react23.default.createElement("p", { className: "dg-empty-subtitle" }, filterText || hasActiveFilters ? "Try adjusting your search or filters" : "No records to display"))), /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ import_react23.default.createElement("span", null, "Rows per page:"), /* @__PURE__ */ import_react23.default.createElement(
|
|
4953
|
+
})()))))), paginatedData.length === 0 && /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-empty-state" }, /* @__PURE__ */ import_react23.default.createElement("svg", { className: "dg-empty-icon", viewBox: "0 0 200 160", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ import_react23.default.createElement("rect", { x: "20", y: "30", width: "160", height: "100", rx: "8", fill: "var(--hover-color)", stroke: "var(--border-color)", strokeWidth: "1.5" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "20", y: "30", width: "160", height: "28", rx: "8", fill: "var(--border-color)", opacity: "0.5" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "20", y: "50", width: "160", height: "8", rx: "0", fill: "var(--border-color)", opacity: "0.5" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "72", y1: "30", x2: "72", y2: "130", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "128", y1: "30", x2: "128", y2: "130", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "20", y1: "78", x2: "180", y2: "78", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "20", y1: "104", x2: "180", y2: "104", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "32", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "84", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "140", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "32", y: "113", width: "20", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "84", y: "113", width: "32", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ import_react23.default.createElement("rect", { x: "140", y: "113", width: "20", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ import_react23.default.createElement("circle", { cx: "148", cy: "108", r: "26", fill: "var(--surface-color)", stroke: "var(--border-color)", strokeWidth: "1.5" }), /* @__PURE__ */ import_react23.default.createElement("circle", { cx: "145", cy: "105", r: "10", stroke: "var(--text-secondary)", strokeWidth: "2.5", opacity: "0.5" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "152", y1: "113", x2: "161", y2: "122", stroke: "var(--text-secondary)", strokeWidth: "2.5", strokeLinecap: "round", opacity: "0.5" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "141", y1: "101", x2: "149", y2: "109", stroke: "var(--text-secondary)", strokeWidth: "2", strokeLinecap: "round", opacity: "0.5" }), /* @__PURE__ */ import_react23.default.createElement("line", { x1: "149", y1: "101", x2: "141", y2: "109", stroke: "var(--text-secondary)", strokeWidth: "2", strokeLinecap: "round", opacity: "0.5" })), /* @__PURE__ */ import_react23.default.createElement("p", { className: "dg-empty-title" }, "No data found"), /* @__PURE__ */ import_react23.default.createElement("p", { className: "dg-empty-subtitle" }, filterText || hasActiveFilters ? "Try adjusting your search or filters" : "No records to display"))), pagination && /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ import_react23.default.createElement("span", null, "Rows per page:"), /* @__PURE__ */ import_react23.default.createElement(
|
|
4928
4954
|
"select",
|
|
4929
4955
|
{
|
|
4930
|
-
value:
|
|
4931
|
-
onChange: (e) =>
|
|
4932
|
-
setPageSize(Number(e.target.value));
|
|
4933
|
-
setCurrentPage(1);
|
|
4934
|
-
}
|
|
4956
|
+
value: activePageSize,
|
|
4957
|
+
onChange: (e) => handlePageSizeChange(Number(e.target.value))
|
|
4935
4958
|
},
|
|
4936
4959
|
pageSizeOptions.map((o) => /* @__PURE__ */ import_react23.default.createElement("option", { key: o, value: o }, o))
|
|
4937
|
-
)), /* @__PURE__ */ import_react23.default.createElement("span", null, (
|
|
4960
|
+
)), /* @__PURE__ */ import_react23.default.createElement("span", null, (activePage - 1) * activePageSize + 1, "\u2013", Math.min(activePage * activePageSize, totalRows), " of ", totalRows)), /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-page-nav" }, /* @__PURE__ */ import_react23.default.createElement("button", { className: "dg-page-btn", disabled: activePage === 1, onClick: () => handlePageChange(activePage - 1) }, /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.ChevronLeft, { size: 15 })), /* @__PURE__ */ import_react23.default.createElement("span", { className: "dg-page-fraction" }, activePage, " / ", totalPages), /* @__PURE__ */ import_react23.default.createElement("button", { className: "dg-page-btn", disabled: activePage === totalPages, onClick: () => handlePageChange(activePage + 1) }, /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.ChevronRight, { size: 15 })))), activeMenu && /* @__PURE__ */ import_react23.default.createElement(
|
|
4938
4961
|
"div",
|
|
4939
4962
|
{
|
|
4940
4963
|
ref: menuRef,
|
package/dist/main.css
CHANGED
|
@@ -443,6 +443,7 @@
|
|
|
443
443
|
overflow-x: auto;
|
|
444
444
|
overflow-y: auto;
|
|
445
445
|
flex: 1;
|
|
446
|
+
position: relative;
|
|
446
447
|
}
|
|
447
448
|
.dg-table-wrap--empty {
|
|
448
449
|
display: flex;
|
|
@@ -936,6 +937,30 @@
|
|
|
936
937
|
--tf-hover-border-color: var(--text-secondary);
|
|
937
938
|
--tf-primary-color: var(--primary-color);
|
|
938
939
|
}
|
|
940
|
+
.dg-loading-overlay {
|
|
941
|
+
position: absolute;
|
|
942
|
+
inset: 0;
|
|
943
|
+
top: 41px;
|
|
944
|
+
background: rgba(255, 255, 255, 0.65);
|
|
945
|
+
display: flex;
|
|
946
|
+
align-items: center;
|
|
947
|
+
justify-content: center;
|
|
948
|
+
z-index: 20;
|
|
949
|
+
pointer-events: all;
|
|
950
|
+
}
|
|
951
|
+
.dg-loading-spinner {
|
|
952
|
+
width: 32px;
|
|
953
|
+
height: 32px;
|
|
954
|
+
border: 3px solid rgba(0, 0, 0, 0.1);
|
|
955
|
+
border-top-color: var(--primary-color, #f15b24);
|
|
956
|
+
border-radius: 50%;
|
|
957
|
+
animation: dg-spin 0.7s linear infinite;
|
|
958
|
+
}
|
|
959
|
+
@keyframes dg-spin {
|
|
960
|
+
to {
|
|
961
|
+
transform: rotate(360deg);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
939
964
|
.dg-empty-state {
|
|
940
965
|
flex: 1;
|
|
941
966
|
display: flex;
|
|
@@ -6321,11 +6346,11 @@ pre {
|
|
|
6321
6346
|
z-index: 2;
|
|
6322
6347
|
}
|
|
6323
6348
|
.rf-text-field__adornment--start {
|
|
6324
|
-
margin-left:
|
|
6349
|
+
margin-left: 0px;
|
|
6325
6350
|
margin-right: -6px;
|
|
6326
6351
|
}
|
|
6327
6352
|
.rf-text-field__adornment--end {
|
|
6328
|
-
margin-right:
|
|
6353
|
+
margin-right: 0px;
|
|
6329
6354
|
margin-left: -6px;
|
|
6330
6355
|
}
|
|
6331
6356
|
.rf-text-field--standard .rf-text-field__adornment--start {
|
package/dist/main.d.cts
CHANGED
|
@@ -863,10 +863,37 @@ interface DataGridToolbarSlot {
|
|
|
863
863
|
content: React__default.ReactNode;
|
|
864
864
|
align?: 'left' | 'center' | 'right';
|
|
865
865
|
}
|
|
866
|
+
interface PaginationModel {
|
|
867
|
+
/** 0-indexed current page */
|
|
868
|
+
page: number;
|
|
869
|
+
pageSize: number;
|
|
870
|
+
}
|
|
866
871
|
interface DataGridProps<T> {
|
|
867
872
|
columns: Column<T>[];
|
|
868
873
|
data: T[];
|
|
869
874
|
actions?: Action<T>[] | ((item: T) => Action<T>[]);
|
|
875
|
+
/** Show a loading overlay over the table body */
|
|
876
|
+
loading?: boolean;
|
|
877
|
+
/** Show the pagination bar. Defaults to true. */
|
|
878
|
+
pagination?: boolean;
|
|
879
|
+
/**
|
|
880
|
+
* 'client' (default) — DataGrid filters, sorts, and paginates data internally.
|
|
881
|
+
* 'server' — data is already the current page; DataGrid skips client-side
|
|
882
|
+
* filtering/sorting/slicing and delegates everything to the server.
|
|
883
|
+
*/
|
|
884
|
+
paginationMode?: 'client' | 'server';
|
|
885
|
+
/**
|
|
886
|
+
* Total number of rows across all pages (server mode).
|
|
887
|
+
* Used to compute total page count when paginationMode="server".
|
|
888
|
+
*/
|
|
889
|
+
rowCount?: number;
|
|
890
|
+
/**
|
|
891
|
+
* Controlled pagination state. page is 0-indexed.
|
|
892
|
+
* When provided, the DataGrid uses these values instead of internal state.
|
|
893
|
+
*/
|
|
894
|
+
paginationModel?: PaginationModel;
|
|
895
|
+
/** Called whenever the page or pageSize changes. page is 0-indexed. */
|
|
896
|
+
onPaginationModelChange?: (model: PaginationModel) => void;
|
|
870
897
|
pageSize?: number;
|
|
871
898
|
pageSizeOptions?: number[];
|
|
872
899
|
title?: string;
|
|
@@ -886,7 +913,7 @@ interface DataGridProps<T> {
|
|
|
886
913
|
|
|
887
914
|
declare function DataGrid<T extends {
|
|
888
915
|
id: string | number;
|
|
889
|
-
}>({ columns: initialColumnsProp, data, actions, pageSize: initialPageSize, pageSizeOptions, title, className, sx, onRowDoubleClick, onCellDoubleClick, headerActions, toolbarContent, }: DataGridProps<T>): React__default.JSX.Element;
|
|
916
|
+
}>({ columns: initialColumnsProp, data, actions, loading, pagination, paginationMode, rowCount, paginationModel, onPaginationModelChange, pageSize: initialPageSize, pageSizeOptions, title, className, sx, onRowDoubleClick, onCellDoubleClick, headerActions, toolbarContent, }: DataGridProps<T>): React__default.JSX.Element;
|
|
890
917
|
|
|
891
918
|
type SelectOption = {
|
|
892
919
|
value: string | number;
|
package/dist/main.d.ts
CHANGED
|
@@ -863,10 +863,37 @@ interface DataGridToolbarSlot {
|
|
|
863
863
|
content: React__default.ReactNode;
|
|
864
864
|
align?: 'left' | 'center' | 'right';
|
|
865
865
|
}
|
|
866
|
+
interface PaginationModel {
|
|
867
|
+
/** 0-indexed current page */
|
|
868
|
+
page: number;
|
|
869
|
+
pageSize: number;
|
|
870
|
+
}
|
|
866
871
|
interface DataGridProps<T> {
|
|
867
872
|
columns: Column<T>[];
|
|
868
873
|
data: T[];
|
|
869
874
|
actions?: Action<T>[] | ((item: T) => Action<T>[]);
|
|
875
|
+
/** Show a loading overlay over the table body */
|
|
876
|
+
loading?: boolean;
|
|
877
|
+
/** Show the pagination bar. Defaults to true. */
|
|
878
|
+
pagination?: boolean;
|
|
879
|
+
/**
|
|
880
|
+
* 'client' (default) — DataGrid filters, sorts, and paginates data internally.
|
|
881
|
+
* 'server' — data is already the current page; DataGrid skips client-side
|
|
882
|
+
* filtering/sorting/slicing and delegates everything to the server.
|
|
883
|
+
*/
|
|
884
|
+
paginationMode?: 'client' | 'server';
|
|
885
|
+
/**
|
|
886
|
+
* Total number of rows across all pages (server mode).
|
|
887
|
+
* Used to compute total page count when paginationMode="server".
|
|
888
|
+
*/
|
|
889
|
+
rowCount?: number;
|
|
890
|
+
/**
|
|
891
|
+
* Controlled pagination state. page is 0-indexed.
|
|
892
|
+
* When provided, the DataGrid uses these values instead of internal state.
|
|
893
|
+
*/
|
|
894
|
+
paginationModel?: PaginationModel;
|
|
895
|
+
/** Called whenever the page or pageSize changes. page is 0-indexed. */
|
|
896
|
+
onPaginationModelChange?: (model: PaginationModel) => void;
|
|
870
897
|
pageSize?: number;
|
|
871
898
|
pageSizeOptions?: number[];
|
|
872
899
|
title?: string;
|
|
@@ -886,7 +913,7 @@ interface DataGridProps<T> {
|
|
|
886
913
|
|
|
887
914
|
declare function DataGrid<T extends {
|
|
888
915
|
id: string | number;
|
|
889
|
-
}>({ columns: initialColumnsProp, data, actions, pageSize: initialPageSize, pageSizeOptions, title, className, sx, onRowDoubleClick, onCellDoubleClick, headerActions, toolbarContent, }: DataGridProps<T>): React__default.JSX.Element;
|
|
916
|
+
}>({ columns: initialColumnsProp, data, actions, loading, pagination, paginationMode, rowCount, paginationModel, onPaginationModelChange, pageSize: initialPageSize, pageSizeOptions, title, className, sx, onRowDoubleClick, onCellDoubleClick, headerActions, toolbarContent, }: DataGridProps<T>): React__default.JSX.Element;
|
|
890
917
|
|
|
891
918
|
type SelectOption = {
|
|
892
919
|
value: string | number;
|
package/dist/main.js
CHANGED
|
@@ -4311,6 +4311,12 @@ function DataGrid({
|
|
|
4311
4311
|
columns: initialColumnsProp,
|
|
4312
4312
|
data,
|
|
4313
4313
|
actions,
|
|
4314
|
+
loading = false,
|
|
4315
|
+
pagination = true,
|
|
4316
|
+
paginationMode = "client",
|
|
4317
|
+
rowCount,
|
|
4318
|
+
paginationModel,
|
|
4319
|
+
onPaginationModelChange,
|
|
4314
4320
|
pageSize: initialPageSize = 10,
|
|
4315
4321
|
pageSizeOptions = [5, 10, 25, 50],
|
|
4316
4322
|
title,
|
|
@@ -4351,6 +4357,23 @@ function DataGrid({
|
|
|
4351
4357
|
const [sortDirection, setSortDirection] = useState9(null);
|
|
4352
4358
|
const [filterText, setFilterText] = useState9("");
|
|
4353
4359
|
const [currentPage, setCurrentPage] = useState9(1);
|
|
4360
|
+
const activePage = paginationModel ? paginationModel.page + 1 : currentPage;
|
|
4361
|
+
const activePageSize = paginationModel ? paginationModel.pageSize : pageSize;
|
|
4362
|
+
const handlePageChange = (newPage) => {
|
|
4363
|
+
if (onPaginationModelChange) {
|
|
4364
|
+
onPaginationModelChange({ page: newPage - 1, pageSize: activePageSize });
|
|
4365
|
+
} else {
|
|
4366
|
+
setCurrentPage(newPage);
|
|
4367
|
+
}
|
|
4368
|
+
};
|
|
4369
|
+
const handlePageSizeChange = (newSize) => {
|
|
4370
|
+
if (onPaginationModelChange) {
|
|
4371
|
+
onPaginationModelChange({ page: 0, pageSize: newSize });
|
|
4372
|
+
} else {
|
|
4373
|
+
setPageSize(newSize);
|
|
4374
|
+
setCurrentPage(1);
|
|
4375
|
+
}
|
|
4376
|
+
};
|
|
4354
4377
|
const [resizingColumn, setResizingColumn] = useState9(null);
|
|
4355
4378
|
const [startX, setStartX] = useState9(0);
|
|
4356
4379
|
const [startWidth, setStartWidth] = useState9(0);
|
|
@@ -4583,11 +4606,14 @@ function DataGrid({
|
|
|
4583
4606
|
return 0;
|
|
4584
4607
|
});
|
|
4585
4608
|
}, [filteredData, sortField, sortDirection, resolvedColumns]);
|
|
4586
|
-
const
|
|
4609
|
+
const isServer = paginationMode === "server";
|
|
4610
|
+
const totalRows = isServer ? rowCount ?? data.length : filteredData.length;
|
|
4611
|
+
const totalPages = Math.max(1, Math.ceil(totalRows / activePageSize));
|
|
4587
4612
|
const paginatedData = useMemo2(() => {
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4613
|
+
if (isServer) return data;
|
|
4614
|
+
const start = (activePage - 1) * activePageSize;
|
|
4615
|
+
return sortedData.slice(start, start + activePageSize);
|
|
4616
|
+
}, [isServer, data, sortedData, activePage, activePageSize]);
|
|
4591
4617
|
const handleExport = () => {
|
|
4592
4618
|
const exportableCols = resolvedColumns.filter((c) => !c.hidden && c.isExportable !== false);
|
|
4593
4619
|
const headers = exportableCols.map((c) => c.headerName).join(",");
|
|
@@ -4682,7 +4708,7 @@ function DataGrid({
|
|
|
4682
4708
|
onClick: () => setShowManageColumns(true)
|
|
4683
4709
|
},
|
|
4684
4710
|
/* @__PURE__ */ React75.createElement(Columns, { size: 16 })
|
|
4685
|
-
)), /* @__PURE__ */ React75.createElement("button", { className: "dg-action-btn", onClick: handleExport }, /* @__PURE__ */ React75.createElement(Download, { size: 14 }), " Export CSV"), headerActions && /* @__PURE__ */ React75.createElement("div", { className: `dg-header-slot ${alignClass(headerActions.align)}` }, headerActions.content))), /* @__PURE__ */ React75.createElement("div", { className: `dg-toolbar ${alignClass(toolbarContent?.align)}` }, toolbarContent?.content || ""), /* @__PURE__ */ React75.createElement("div", { className: `dg-table-wrap${paginatedData.length === 0 ? " dg-table-wrap--empty" : ""}` }, /* @__PURE__ */ React75.createElement("table", { className: "dg-table" }, /* @__PURE__ */ React75.createElement("thead", null, /* @__PURE__ */ React75.createElement("tr", null, visibleColumns.map((col, idx) => {
|
|
4711
|
+
)), /* @__PURE__ */ React75.createElement("button", { className: "dg-action-btn", onClick: handleExport }, /* @__PURE__ */ React75.createElement(Download, { size: 14 }), " Export CSV"), headerActions && /* @__PURE__ */ React75.createElement("div", { className: `dg-header-slot ${alignClass(headerActions.align)}` }, headerActions.content))), /* @__PURE__ */ React75.createElement("div", { className: `dg-toolbar ${alignClass(toolbarContent?.align)}` }, toolbarContent?.content || ""), /* @__PURE__ */ React75.createElement("div", { className: `dg-table-wrap${paginatedData.length === 0 && !loading ? " dg-table-wrap--empty" : ""}` }, loading && /* @__PURE__ */ React75.createElement("div", { className: "dg-loading-overlay" }, /* @__PURE__ */ React75.createElement("div", { className: "dg-loading-spinner" })), /* @__PURE__ */ React75.createElement("table", { className: "dg-table" }, /* @__PURE__ */ React75.createElement("thead", null, /* @__PURE__ */ React75.createElement("tr", null, visibleColumns.map((col, idx) => {
|
|
4686
4712
|
const colField = String(col.field);
|
|
4687
4713
|
const width = columnWidths[colField] || 200;
|
|
4688
4714
|
const leftOffset = getLeftOffset(col, idx);
|
|
@@ -4796,17 +4822,14 @@ function DataGrid({
|
|
|
4796
4822
|
},
|
|
4797
4823
|
action.icon
|
|
4798
4824
|
)))));
|
|
4799
|
-
})()))))), paginatedData.length === 0 && /* @__PURE__ */ React75.createElement("div", { className: "dg-empty-state" }, /* @__PURE__ */ React75.createElement("svg", { className: "dg-empty-icon", viewBox: "0 0 200 160", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React75.createElement("rect", { x: "20", y: "30", width: "160", height: "100", rx: "8", fill: "var(--hover-color)", stroke: "var(--border-color)", strokeWidth: "1.5" }), /* @__PURE__ */ React75.createElement("rect", { x: "20", y: "30", width: "160", height: "28", rx: "8", fill: "var(--border-color)", opacity: "0.5" }), /* @__PURE__ */ React75.createElement("rect", { x: "20", y: "50", width: "160", height: "8", rx: "0", fill: "var(--border-color)", opacity: "0.5" }), /* @__PURE__ */ React75.createElement("line", { x1: "72", y1: "30", x2: "72", y2: "130", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ React75.createElement("line", { x1: "128", y1: "30", x2: "128", y2: "130", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ React75.createElement("line", { x1: "20", y1: "78", x2: "180", y2: "78", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ React75.createElement("line", { x1: "20", y1: "104", x2: "180", y2: "104", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ React75.createElement("rect", { x: "32", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ React75.createElement("rect", { x: "84", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ React75.createElement("rect", { x: "140", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ React75.createElement("rect", { x: "32", y: "113", width: "20", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ React75.createElement("rect", { x: "84", y: "113", width: "32", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ React75.createElement("rect", { x: "140", y: "113", width: "20", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ React75.createElement("circle", { cx: "148", cy: "108", r: "26", fill: "var(--surface-color)", stroke: "var(--border-color)", strokeWidth: "1.5" }), /* @__PURE__ */ React75.createElement("circle", { cx: "145", cy: "105", r: "10", stroke: "var(--text-secondary)", strokeWidth: "2.5", opacity: "0.5" }), /* @__PURE__ */ React75.createElement("line", { x1: "152", y1: "113", x2: "161", y2: "122", stroke: "var(--text-secondary)", strokeWidth: "2.5", strokeLinecap: "round", opacity: "0.5" }), /* @__PURE__ */ React75.createElement("line", { x1: "141", y1: "101", x2: "149", y2: "109", stroke: "var(--text-secondary)", strokeWidth: "2", strokeLinecap: "round", opacity: "0.5" }), /* @__PURE__ */ React75.createElement("line", { x1: "149", y1: "101", x2: "141", y2: "109", stroke: "var(--text-secondary)", strokeWidth: "2", strokeLinecap: "round", opacity: "0.5" })), /* @__PURE__ */ React75.createElement("p", { className: "dg-empty-title" }, "No data found"), /* @__PURE__ */ React75.createElement("p", { className: "dg-empty-subtitle" }, filterText || hasActiveFilters ? "Try adjusting your search or filters" : "No records to display"))), /* @__PURE__ */ React75.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ React75.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ React75.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ React75.createElement("span", null, "Rows per page:"), /* @__PURE__ */ React75.createElement(
|
|
4825
|
+
})()))))), paginatedData.length === 0 && /* @__PURE__ */ React75.createElement("div", { className: "dg-empty-state" }, /* @__PURE__ */ React75.createElement("svg", { className: "dg-empty-icon", viewBox: "0 0 200 160", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React75.createElement("rect", { x: "20", y: "30", width: "160", height: "100", rx: "8", fill: "var(--hover-color)", stroke: "var(--border-color)", strokeWidth: "1.5" }), /* @__PURE__ */ React75.createElement("rect", { x: "20", y: "30", width: "160", height: "28", rx: "8", fill: "var(--border-color)", opacity: "0.5" }), /* @__PURE__ */ React75.createElement("rect", { x: "20", y: "50", width: "160", height: "8", rx: "0", fill: "var(--border-color)", opacity: "0.5" }), /* @__PURE__ */ React75.createElement("line", { x1: "72", y1: "30", x2: "72", y2: "130", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ React75.createElement("line", { x1: "128", y1: "30", x2: "128", y2: "130", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ React75.createElement("line", { x1: "20", y1: "78", x2: "180", y2: "78", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ React75.createElement("line", { x1: "20", y1: "104", x2: "180", y2: "104", stroke: "var(--border-color)", strokeWidth: "1" }), /* @__PURE__ */ React75.createElement("rect", { x: "32", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ React75.createElement("rect", { x: "84", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ React75.createElement("rect", { x: "140", y: "87", width: "28", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.4" }), /* @__PURE__ */ React75.createElement("rect", { x: "32", y: "113", width: "20", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ React75.createElement("rect", { x: "84", y: "113", width: "32", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ React75.createElement("rect", { x: "140", y: "113", width: "20", height: "6", rx: "3", fill: "var(--border-color)", opacity: "0.3" }), /* @__PURE__ */ React75.createElement("circle", { cx: "148", cy: "108", r: "26", fill: "var(--surface-color)", stroke: "var(--border-color)", strokeWidth: "1.5" }), /* @__PURE__ */ React75.createElement("circle", { cx: "145", cy: "105", r: "10", stroke: "var(--text-secondary)", strokeWidth: "2.5", opacity: "0.5" }), /* @__PURE__ */ React75.createElement("line", { x1: "152", y1: "113", x2: "161", y2: "122", stroke: "var(--text-secondary)", strokeWidth: "2.5", strokeLinecap: "round", opacity: "0.5" }), /* @__PURE__ */ React75.createElement("line", { x1: "141", y1: "101", x2: "149", y2: "109", stroke: "var(--text-secondary)", strokeWidth: "2", strokeLinecap: "round", opacity: "0.5" }), /* @__PURE__ */ React75.createElement("line", { x1: "149", y1: "101", x2: "141", y2: "109", stroke: "var(--text-secondary)", strokeWidth: "2", strokeLinecap: "round", opacity: "0.5" })), /* @__PURE__ */ React75.createElement("p", { className: "dg-empty-title" }, "No data found"), /* @__PURE__ */ React75.createElement("p", { className: "dg-empty-subtitle" }, filterText || hasActiveFilters ? "Try adjusting your search or filters" : "No records to display"))), pagination && /* @__PURE__ */ React75.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ React75.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ React75.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ React75.createElement("span", null, "Rows per page:"), /* @__PURE__ */ React75.createElement(
|
|
4800
4826
|
"select",
|
|
4801
4827
|
{
|
|
4802
|
-
value:
|
|
4803
|
-
onChange: (e) =>
|
|
4804
|
-
setPageSize(Number(e.target.value));
|
|
4805
|
-
setCurrentPage(1);
|
|
4806
|
-
}
|
|
4828
|
+
value: activePageSize,
|
|
4829
|
+
onChange: (e) => handlePageSizeChange(Number(e.target.value))
|
|
4807
4830
|
},
|
|
4808
4831
|
pageSizeOptions.map((o) => /* @__PURE__ */ React75.createElement("option", { key: o, value: o }, o))
|
|
4809
|
-
)), /* @__PURE__ */ React75.createElement("span", null, (
|
|
4832
|
+
)), /* @__PURE__ */ React75.createElement("span", null, (activePage - 1) * activePageSize + 1, "\u2013", Math.min(activePage * activePageSize, totalRows), " of ", totalRows)), /* @__PURE__ */ React75.createElement("div", { className: "dg-page-nav" }, /* @__PURE__ */ React75.createElement("button", { className: "dg-page-btn", disabled: activePage === 1, onClick: () => handlePageChange(activePage - 1) }, /* @__PURE__ */ React75.createElement(ChevronLeft, { size: 15 })), /* @__PURE__ */ React75.createElement("span", { className: "dg-page-fraction" }, activePage, " / ", totalPages), /* @__PURE__ */ React75.createElement("button", { className: "dg-page-btn", disabled: activePage === totalPages, onClick: () => handlePageChange(activePage + 1) }, /* @__PURE__ */ React75.createElement(ChevronRight, { size: 15 })))), activeMenu && /* @__PURE__ */ React75.createElement(
|
|
4810
4833
|
"div",
|
|
4811
4834
|
{
|
|
4812
4835
|
ref: menuRef,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rufous/ui",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Experimental: A lightweight React UI component library (Beta)",
|
|
7
7
|
"style": "./dist/main.css",
|
|
@@ -93,4 +93,4 @@
|
|
|
93
93
|
"react": "^18.0.0 || ^19.0.0",
|
|
94
94
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
95
95
|
}
|
|
96
|
-
}
|
|
96
|
+
}
|