@etsoo/materialui
Version:
TypeScript Material-UI Implementation
110 lines (109 loc) • 4.67 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { css } from "@emotion/css";
import { ScrollerList } from "@etsoo/react";
import { Utils } from "@etsoo/shared";
import React from "react";
import { GridUtils } from "./GridUtils";
import { listCacheKeyGenerator, useListCacheInitLoad } from "./uses/useListCacheInitLoad";
import Box from "@mui/material/Box";
// Scroll bar size
const scrollbarSize = 16;
// Selected class name
const selectedClassName = "ScrollerListEx-Selected";
const createGridStyle = (alternatingColors, selectedColor) => {
return css({
"& .ScrollerListEx-Selected": {
backgroundColor: selectedColor
},
"& .ScrollerListEx-Row0:not(.ScrollerListEx-Selected)": {
backgroundColor: alternatingColors[0]
},
"& .ScrollerListEx-Row1:not(.ScrollerListEx-Selected)": {
backgroundColor: alternatingColors[1]
},
"@media (min-width: 800px)": {
"::-webkit-scrollbar": {
width: scrollbarSize,
height: scrollbarSize,
backgroundColor: "#f6f6f6"
},
"::-webkit-scrollbar-thumb": {
backgroundColor: "rgba(0,0,0,0.4)",
borderRadius: "2px"
},
"::-webkit-scrollbar-track-piece:start": {
background: "transparent"
},
"::-webkit-scrollbar-track-piece:end": {
background: "transparent"
}
}
});
};
/**
* Default styles for item renderer
*/
export const ScrollerListExItemDefaultStyles = {
height: `calc(100% - 16px)`,
/**
* default rowHeight is 150px when 16px margin top/bottom
*/
marginTop: "8px",
marginBottom: "8px",
overflow: "auto"
};
/**
* Extended ScrollerList
* @param props Props
* @returns Component
*/
export function ScrollerListEx(props) {
// Selected item ref
const selectedItem = React.useRef(null);
const onMouseDown = (div, data) => {
// Destruct
const [selectedDiv, selectedData] = selectedItem.current ?? [];
if (selectedData != null && selectedData[idField] === data[idField])
return;
selectedDiv?.classList.remove(selectedClassName);
div.classList.add(selectedClassName);
selectedItem.current = [div, data];
if (onSelectChange)
onSelectChange([data]);
};
const isSelected = (data) => {
const [_, selectedData] = selectedItem.current ?? [];
const selected = selectedData && data && selectedData[idField] === data[idField]
? true
: false;
return selected;
};
// Destruct
const { alternatingColors = [undefined, undefined], className, cacheKey, cacheMinutes = 15, idField = "id", itemRenderer = ({ data }) => (_jsx(Box, { component: "pre", sx: ScrollerListExItemDefaultStyles, children: JSON.stringify(data) })), onClick, onDoubleClick, onUpdateRows, onSelectChange, rowHeight = 150, selectedColor = "#edf4fb", ...rest } = props;
// Init handler
const initHandler = useListCacheInitLoad(cacheKey, cacheMinutes);
const onUpdateRowsHandler = React.useCallback((rows, state, reset) => {
GridUtils.getUpdateRowsHandler(cacheKey)?.(rows, state);
onUpdateRows?.(rows, state, reset);
if (cacheKey && reset) {
sessionStorage.removeItem(listCacheKeyGenerator(cacheKey));
}
}, [onUpdateRows, cacheKey]);
// Layout
return (_jsx(ScrollerList, { className: Utils.mergeClasses("ScrollerListEx-Body", className, createGridStyle(alternatingColors, selectedColor)), idField: idField, onRowsRendered: cacheKey
? (visibleRows) => sessionStorage.setItem(listCacheKeyGenerator(cacheKey), JSON.stringify(visibleRows))
: undefined, onInitLoad: initHandler, onUpdateRows: onUpdateRowsHandler, rowComponent: (cellProps) => {
const { index, style, items } = cellProps;
const data = items[index];
const selected = isSelected(data);
const rowClass = `ScrollerListEx-Row${index % 2}${selected ? ` ${selectedClassName}` : ""}`;
// Child
const child = itemRenderer({
index,
data,
style,
selected
});
return (_jsx("div", { className: rowClass, style: style, onMouseDown: (event) => onMouseDown(event.currentTarget, data), onClick: (event) => onClick && onClick(event, data), onDoubleClick: (event) => onDoubleClick && onDoubleClick(event, data), children: child }));
}, rowHeight: rowHeight, ...rest }));
}