UNPKG

@etsoo/materialui

Version:

TypeScript Material-UI Implementation

100 lines (99 loc) 4.36 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useCombinedRefs, useDimensions, useSearchParamsWithCache } from "@etsoo/react"; import React from "react"; import { MUGlobal } from "../MUGlobal"; import { ScrollerListEx } from "../ScrollerListEx"; import { SearchBar } from "../SearchBar"; import { CommonPage } from "./CommonPage"; import { GridUtils } from "../GridUtils"; import Box from "@mui/material/Box"; import Stack from "@mui/material/Stack"; /** * Fixed height list page * @param props Props * @returns Component */ export function FixedListPage(props) { // Destruct const { adjustHeight, fields, fieldTemplate, loadData, mRef, sizeReadyMiliseconds = 0, pageProps = {}, cacheKey, cacheMinutes = 15, searchBarTop, ...rest } = props; pageProps.paddings ??= MUGlobal.pagePaddings; // States const [states] = React.useState({}); const initLoadedRef = React.useRef(); // Scroll container const [scrollContainer, updateScrollContainer] = React.useState(); const refs = useCombinedRefs(mRef, (ref) => { if (ref == null) return; const first = states.ref == null; states.ref = ref; if (first) reset(); }); const reset = () => { if (states.data == null || states.ref == null) return; states.ref.reset({ data: states.data }); }; // On submit callback const onSubmit = (data, _reset) => { states.data = data; reset(); }; const localLoadData = (props, lastItem) => { return loadData(GridUtils.createLoader(props, fieldTemplate, cacheKey, false), lastItem); }; // Search data const searchData = useSearchParamsWithCache(cacheKey); const onInitLoad = (ref) => { // Avoid repeatedly load from cache if (initLoadedRef.current || !cacheKey) return undefined; // Cache data const cacheData = GridUtils.getCacheData(cacheKey, cacheMinutes); if (cacheData) { const { rows, state } = cacheData; GridUtils.mergeSearchData(state, searchData); // Scroll position const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`); if (scrollData) { const { scrollOffset } = JSON.parse(scrollData); globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0); } // Update flag value initLoadedRef.current = true; // Return cached rows and state return [rows, state]; } return undefined; }; const onListScroll = (props) => { if (!cacheKey || !initLoadedRef.current) return; sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props)); }; // Watch container const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds); const rect = dimensions[0][2]; const list = React.useMemo(() => { if (rect != null && rect.height > 50) { let height = document.documentElement.clientHeight - Math.round(rect.top + rect.height + 1); if (adjustHeight != null) height -= typeof adjustHeight === "number" ? adjustHeight : adjustHeight(height, rect); return (_jsx(Box, { id: "list-container", sx: { height: height + "px" }, children: _jsx(ScrollerListEx, { autoLoad: false, height: height, loadData: localLoadData, mRef: refs, onUpdateRows: GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, onScroll: onListScroll, oRef: (element) => { if (element != null) updateScrollContainer(element); }, ...rest }) })); } }, [rect]); const f = typeof fields == "function" ? fields(searchData ?? {}) : fields; const { paddings, ...pageRest } = pageProps; // Layout return (_jsx(CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer, children: _jsxs(Stack, { children: [_jsx(Box, { ref: dimensions[0][0], sx: { padding: paddings }, children: rect && rect.width > 100 && (_jsx(SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop, width: rect.width })) }), list] }) })); }