@explita/daily-toolset-components
Version:
A lightweight and versatile collection of TypeScript utility functions and form components, inspired by ShadCN UI, designed for seamless everyday development. Enhance your Node.js, React, and Next.js projects with a well-structured suite of helpers for st
218 lines (217 loc) • 11.5 kB
JavaScript
"use client";
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataTable = DataTable;
const react_1 = __importStar(require("react"));
const fa6_1 = require("react-icons/fa6");
const _1 = require("./");
const daily_toolset_hooks_1 = require("@explita/daily-toolset-hooks");
function defaultColumns(columns, sortable) {
if (!sortable)
return columns;
return columns.map((col) => {
var _a;
return ({
...col,
sortable: (_a = col.sortable) !== null && _a !== void 0 ? _a : true,
});
});
}
function DataTable({ sortable = true, columns = [], data = [], onRowClick, hideFilter = false, hideHeader = false, hideFooter = false, additionalFilter, ref, emptyMessage = "No records found.", defaultRowsPerPage = 10, }) {
var _a, _b, _c;
const [filterValue, setFilterValue] = (0, react_1.useState)("");
const [page, setPage] = (0, react_1.useState)(1);
const [rowsPerPage, setRowsPerPage] = (0, react_1.useState)(10);
const [sortDescriptor, setSortDescriptor] = (0, react_1.useState)({
column: (_a = columns[0]) === null || _a === void 0 ? void 0 : _a.key.toString(),
direction: (_c = (_b = columns[0]) === null || _b === void 0 ? void 0 : _b.sortDir) !== null && _c !== void 0 ? _c : "asc",
});
(0, react_1.useEffect)(() => {
if (hideFooter === true)
setRowsPerPage(data === null || data === void 0 ? void 0 : data.length);
}, [data, hideFooter]);
const hasSearchFilter = Boolean(filterValue);
const filteredItems = (0, react_1.useMemo)(() => {
let filteredData = [...data];
if (hasSearchFilter) {
filteredData = filteredData.filter((item) => {
return Object.values(item)
.map((item) => (0, daily_toolset_hooks_1.stripTags)(item))
.join("")
.toLowerCase()
.includes(filterValue.toLowerCase());
});
}
return filteredData;
}, [data, filterValue, hasSearchFilter]);
const pages = Math.ceil(filteredItems.length / rowsPerPage);
const items = (0, react_1.useMemo)(() => {
const start = (page - 1) * rowsPerPage;
const end = start + rowsPerPage;
return filteredItems.slice(start, end);
}, [page, filteredItems, rowsPerPage]);
const sortedItems = (0, react_1.useMemo)(() => {
if (!sortable)
return items;
return [...items].sort((a, b) => {
const typeOfA = typeof a[sortDescriptor.column];
const typeOfB = typeof b[sortDescriptor.column];
const first = typeOfA === "number"
? Number(a[sortDescriptor.column])
: (0, daily_toolset_hooks_1.stripTags)(a[sortDescriptor.column]);
const second = typeOfB === "number"
? Number(b[sortDescriptor.column])
: (0, daily_toolset_hooks_1.stripTags)(b[sortDescriptor.column]);
const cmp = first < second ? -1 : first > second ? 1 : 0;
return sortDescriptor.direction === "desc" ? -cmp : cmp;
});
}, [sortDescriptor, items, sortable]);
const onNextPage = (0, react_1.useCallback)(() => {
if (page < pages)
setPage(page + 1);
else
setPage(1);
}, [page, pages]);
const onPreviousPage = (0, react_1.useCallback)(() => {
if (page > 1)
setPage(page - 1);
else
setPage(pages);
}, [page, pages]);
const onRowsPerPageChange = (0, react_1.useCallback)((value) => {
setRowsPerPage(Number(value));
setPage(1);
}, []);
const onSearchChange = (0, react_1.useCallback)((e) => {
if (e.target.value) {
setFilterValue(e.target.value);
setPage(1);
}
else {
setFilterValue("");
}
}, []);
return (react_1.default.createElement("div", { className: "explita-table-container" },
(pages > 0 || filterValue !== "") && hideFilter === false && (react_1.default.createElement(TableFilter, { filterValue,
onSearchChange,
rowsPerPage,
onRowsPerPageChange,
additionalFilter })),
react_1.default.createElement("div", { className: "table-main" },
react_1.default.createElement("table", { className: "explita-table", ref: ref },
hideHeader === false && (react_1.default.createElement(TableHeader, { columns, setSortDescriptor, sortDescriptor, sortable })),
react_1.default.createElement("tbody", null,
sortedItems.map((row, index) => {
return (react_1.default.createElement("tr", { key: index, onClick: () => onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(row) }, columns.map((column, index) => {
// if (row.includes("_id_")) return;
return (react_1.default.createElement("td", { key: index, style: column.style, className: column.className || "", "data-title": typeof column.title === "string" ? column.title : "" },
react_1.default.createElement("div", { className: column.key === "actions" ? "actions-container" : "" }, column.render
? column.render(row)
: row[column.key])));
})));
}),
sortedItems.length === 0 && (react_1.default.createElement("tr", null,
react_1.default.createElement("td", { colSpan: columns.length, "data-empty": sortedItems.length === 0 }, emptyMessage)))))),
pages > 0 &&
filteredItems.length > rowsPerPage &&
hideFooter === false && (react_1.default.createElement(TableFooter, { pages, page, onNextPage, onPreviousPage, filteredItems }))));
}
function TableFilter({ filterValue, onSearchChange, rowsPerPage, onRowsPerPageChange, additionalFilter, }) {
return (react_1.default.createElement("div", { className: "table-filter" },
react_1.default.createElement("div", null,
react_1.default.createElement("span", { className: "filter-label" }, "Show"),
react_1.default.createElement(_1.Select, { defaultValue: rowsPerPage, options: [
{ value: 10, label: "10 Records" },
{ value: 25, label: "25 Records" },
{ value: 50, label: "50 Records" },
{ value: 100, label: "100 Records" },
], isClearable: false, handleSelection: onRowsPerPageChange })),
react_1.default.createElement("div", null,
additionalFilter,
react_1.default.createElement(_1.Input.Search, { defaultValue: filterValue, placeholder: "Search table...", onChange: onSearchChange }))));
}
function TableHeader({ columns, sortable, sortDescriptor, setSortDescriptor, }) {
const processedColumns = defaultColumns(columns, sortable);
const setSortDescription = (0, react_1.useCallback)((item) => {
var _a;
if (!item.sortable || !sortable)
return;
if (item.key === sortDescriptor.column) {
if (sortDescriptor.direction === "asc") {
setSortDescriptor({ column: item.key, direction: "desc" });
}
else {
setSortDescriptor({ column: item.key, direction: "asc" });
}
}
else {
setSortDescriptor({
column: String(item.key),
direction: (_a = item.sortDir) !== null && _a !== void 0 ? _a : "asc",
});
}
}, [sortDescriptor, setSortDescriptor, sortable]);
return (react_1.default.createElement("thead", null,
react_1.default.createElement("tr", null, processedColumns.map((item, i) => (react_1.default.createElement("th", { key: i, style: { width: item.width }, onClick: () => setSortDescription(item), role: "button" },
react_1.default.createElement("div", { className: "header-container" },
item.title,
item.key !== "actions" && (react_1.default.createElement(SortArrow, { sortDescriptor,
sortable: !item.sortable ? false : sortable,
columnKey: String(item.key) })))))))));
}
function TableFooter({ pages, page, onNextPage, onPreviousPage, filteredItems, }) {
return (react_1.default.createElement("div", { className: "footer-container" },
react_1.default.createElement("div", null,
react_1.default.createElement("span", null,
"Page ",
page,
" of ",
pages),
react_1.default.createElement("span", null)),
react_1.default.createElement("div", null,
react_1.default.createElement(_1.Button, { size: "sm", variant: "outline", isDisabled: pages === 1, onClick: onPreviousPage },
react_1.default.createElement(fa6_1.FaChevronLeft, null),
react_1.default.createElement("span", { className: "label" }, "Previous")),
react_1.default.createElement(_1.Button, { size: "sm", variant: "outline", isDisabled: pages === 1, onClick: onNextPage },
react_1.default.createElement(fa6_1.FaChevronRight, null),
react_1.default.createElement("span", { className: "label" }, "Next")))));
}
function SortArrow({ columnKey, sortable, sortDescriptor }) {
if (!sortable || sortDescriptor.column === "")
return null;
return sortDescriptor.column === columnKey ? (react_1.default.createElement("span", { className: `sort-icon ${sortDescriptor.direction === "asc" ? "asc" : "desc"}` }, sortDescriptor.direction === "desc" ? (react_1.default.createElement(fa6_1.FaArrowDownZA, null)) : (react_1.default.createElement(fa6_1.FaArrowDownAZ, null)))) : (react_1.default.createElement("span", { className: "sort-icon inactive" },
react_1.default.createElement(fa6_1.FaArrowDownAZ, null)));
}