sccoreui
Version:
ui-sccore
154 lines (153 loc) • 10.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const React = tslib_1.__importStar(require("react"));
const react_virtual_1 = require("@tanstack/react-virtual");
const inputtext_1 = require("primereact/inputtext");
const svg_component_1 = tslib_1.__importDefault(require("../../directives/svg-component"));
const hooks_1 = require("primereact/hooks");
const skeleton_1 = require("primereact/skeleton");
function RowVirtualizerDynamic(props) {
var _a, _b;
const { optionTemplate, optionLabel, filterPlaceholder, matchKey = "id", values, multiple = false, onSelectionChange, fetchData, emptyMessage, emptyFilterMessage, refetchKey, } = props;
const parentRef = React.useRef(null);
const fetchDataRef = React.useRef(fetchData);
fetchDataRef.current = fetchData;
const loadingRef = React.useRef(false);
const allCount = React.useRef(null);
const totalRecordsCount = React.useRef(null);
const initialFetch = {
pageIndex: 0,
pageSize: 100,
searchTerm: "",
};
const [loading, setLoading] = React.useState(true);
const pageIndex = React.useRef(0);
const [inputValue, debouncedValue, setInputValue] = (0, hooks_1.useDebounce)("", 500);
const [enabled] = React.useState(true);
const [data, setData] = React.useState([]);
const virtualizer = (0, react_virtual_1.useVirtualizer)({
count: data.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 45,
enabled,
});
// Scroll handler
const handleScroll = () => {
const el = parentRef.current;
if (!el)
return;
const scrollOffset = el.scrollTop + el.clientHeight;
const threshold = el.scrollHeight - 100;
const checCount = allCount.current != null
? allCount.current > totalRecordsCount.current
: true;
if (el.scrollHeight > el.clientHeight && scrollOffset >= threshold && !loadingRef.current && checCount) {
loadingRef.current = true;
fetchMoreData(Object.assign(Object.assign({}, initialFetch), { pageIndex: pageIndex.current }));
}
};
const lastSearchTerm = React.useRef('');
const fetchMoreData = (props) => tslib_1.__awaiter(this, void 0, void 0, function* () {
var _c;
try {
const object = yield fetchDataRef.current(props);
if (object) {
loadingRef.current = false;
if (lastSearchTerm.current && !(props === null || props === void 0 ? void 0 : props.searchTerm)) {
// Search just cleared — reset data
setData(object.data);
}
else if ((props === null || props === void 0 ? void 0 : props.searchTerm) && (props === null || props === void 0 ? void 0 : props.searchTerm) !== "") {
totalRecordsCount.current = (_c = object === null || object === void 0 ? void 0 : object.data) === null || _c === void 0 ? void 0 : _c.length;
setData(object === null || object === void 0 ? void 0 : object.data);
}
else {
setData((prev) => {
const totalData = [...prev, ...object === null || object === void 0 ? void 0 : object.data];
totalRecordsCount.current = totalData.length;
return totalData;
});
}
setLoading(false);
allCount.current = object === null || object === void 0 ? void 0 : object.totalRecords;
pageIndex.current = pageIndex.current + 1;
lastSearchTerm.current = props === null || props === void 0 ? void 0 : props.searchTerm;
}
}
catch (error) {
console.error("Error fetching data:", error);
loadingRef.current = false;
setLoading(false);
}
});
React.useEffect(() => {
loadingRef.current = true;
setLoading(true);
fetchMoreData(Object.assign(Object.assign({}, initialFetch), { searchTerm: debouncedValue }));
}, [debouncedValue]);
const isFirstRender = React.useRef(true);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
if (refetchKey !== undefined) {
pageIndex.current = 0;
setData([]);
loadingRef.current = true;
setLoading(true);
fetchMoreData(Object.assign(Object.assign({}, initialFetch), { searchTerm: debouncedValue }));
}
}, [refetchKey]);
React.useEffect(() => {
const el = parentRef.current;
el && el.addEventListener("scroll", handleScroll);
return () => el === null || el === void 0 ? void 0 : el.removeEventListener("scroll", handleScroll);
}, []);
const items = virtualizer.getVirtualItems();
const handleSelect = (item) => {
const isSelected = values.some((x) => (x === null || x === void 0 ? void 0 : x[matchKey]) === (item === null || item === void 0 ? void 0 : item[matchKey]));
let newSelection;
if (!multiple) {
newSelection = isSelected ? [] : (item === null || item === void 0 ? void 0 : item[matchKey]) ? [item] : [];
}
else {
newSelection = isSelected
? values.filter((val) => (val === null || val === void 0 ? void 0 : val[matchKey]) !== (item === null || item === void 0 ? void 0 : item[matchKey]))
: [...values, item];
}
onSelectionChange && onSelectionChange(newSelection);
};
// Render Skeletons
const renderSkeletons = () => {
return Array.from({ length: 10 }).map((_, index) => ((0, jsx_runtime_1.jsx)("li", Object.assign({ className: "p-listbox-item cursor-pointer" }, { children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { height: "30px", width: "100%" }) }), index)));
};
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "p-listbox" }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ className: "p-listbox-header", "data-pc-section": "header" }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "p-listbox-filter-container", "data-pc-section": "filtercontainer" }, { children: (0, jsx_runtime_1.jsxs)("span", Object.assign({ className: "p-input-icon-right flex-order-1" }, { children: [inputValue === "" ? ((0, jsx_runtime_1.jsx)("span", Object.assign({ className: "p-input-suffix cursor-pointer" }, { children: (0, jsx_runtime_1.jsx)(svg_component_1.default, { icon: "search-md", size: 12 }) }))) : ((0, jsx_runtime_1.jsx)("span", Object.assign({ className: "p-input-suffix cursor-pointer", onClick: (e) => {
e.stopPropagation();
setInputValue("");
} }, { children: (0, jsx_runtime_1.jsx)(svg_component_1.default, { icon: "x-close", size: 12 }) }))), (0, jsx_runtime_1.jsx)(inputtext_1.InputText, { value: inputValue, onChange: (e) => setInputValue(e.target.value), placeholder: filterPlaceholder, className: "w-full" })] })) })) })), (0, jsx_runtime_1.jsx)("div", Object.assign({ ref: parentRef, className: "List virtual-box w-full bg-gray shadow-3", style: {
height: 400,
overflowY: "auto",
contain: "strict",
} }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ style: {
height: virtualizer.getTotalSize(),
width: "100%",
position: "relative",
}, className: `${data.length === 0
? "flex-column flex justify-content-around align-items-center h-full w-full"
: ""}` }, { children: loading && (data === null || data === void 0 ? void 0 : data.length) === 0 ? ((0, jsx_runtime_1.jsx)("ul", Object.assign({ className: "p-listbox-list w-full h-full" }, { children: renderSkeletons() }))) : (data === null || data === void 0 ? void 0 : data.length) === 0 ? (debouncedValue && debouncedValue !== "" ? ((0, jsx_runtime_1.jsx)("span", { children: emptyFilterMessage })) : ((0, jsx_runtime_1.jsx)("span", { children: emptyMessage }))) : ((0, jsx_runtime_1.jsx)("ul", Object.assign({ className: "p-listbox-list", style: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
transform: `translateY(${(_b = (_a = items[0]) === null || _a === void 0 ? void 0 : _a.start) !== null && _b !== void 0 ? _b : 0}px)`,
} }, { children: items.map((virtualRow) => {
var _a;
return ((0, jsx_runtime_1.jsx)("li", Object.assign({ "data-index": virtualRow.index, ref: virtualizer.measureElement, onClick: () => handleSelect(data[virtualRow.index]), className: `p-listbox-item ${virtualRow.index % 2 ? "ListItemOdd" : "ListItemEven"} ${values.some((y) => { var _a; return (y === null || y === void 0 ? void 0 : y[matchKey]) === ((_a = data[virtualRow.index]) === null || _a === void 0 ? void 0 : _a[matchKey]); })
? "p-highlight"
: ""} cursor-pointer` }, { children: loading ? ((0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { height: "30px", width: "100%" })) : optionTemplate ? (optionTemplate(data[virtualRow.index])) : ((0, jsx_runtime_1.jsx)("div", { children: (_a = data[virtualRow.index]) === null || _a === void 0 ? void 0 : _a[optionLabel] })) }), virtualRow.key));
}) }))) })) }))] })));
}
exports.default = RowVirtualizerDynamic;