UNPKG

@etsoo/materialui

Version:

TypeScript Material-UI Implementation

193 lines (192 loc) 8.66 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import React from "react"; import { ReactUtils, useCombinedRefs, useDimensions, useSearchParamsWithCache } from "@etsoo/react"; import { DataGridEx } from "./DataGridEx"; import { MUGlobal } from "./MUGlobal"; import { PullToRefreshUI } from "./PullToRefreshUI"; import { ScrollerListEx } from "./ScrollerListEx"; import { SearchBar } from "./SearchBar"; import { Labels } from "./app/Labels"; import { GridUtils } from "./GridUtils"; import useMediaQuery from "@mui/material/useMediaQuery"; import Box from "@mui/material/Box"; import Stack from "@mui/material/Stack"; function defaultContainerBoxSx(paddings, hasField, _dataGrid) { const half = typeof paddings == "number" ? paddings / 2 : MUGlobal.half(paddings); return { "& .SearchBox": { marginBottom: hasField ? half : 0 } }; } /** * Responsible container * @param props Props * @returns Layout */ export function ResponsibleContainer(props) { // Destruct const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, searchBarTop, ...rest } = props; // Labels const labels = Labels.CommonPage; // Refs const refs = React.useRef({}); const state = refs.current; const mRefs = useCombinedRefs(mRef, (ref) => { if (ref == null) return; state.ref = ref; }); // Screen size detection const showDataGrid = useMediaQuery("(min-width:600px)"); // Update mounted state React.useEffect(() => { return () => { state.mounted = false; }; }, []); // Has fields const hasFields = fields != null && fields.length > 0; // Load data const localLoadData = (props, lastItem) => { state.mounted = true; return loadData(GridUtils.createLoader(props, fieldTemplate, cacheKey, false), lastItem); }; // Search data const searchData = useSearchParamsWithCache(cacheKey); // On submit callback const onSubmit = (data, _reset) => { if (data == null || state.ref == null) return; state.ref.reset({ data }); }; // Watch container const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds, (_preRect, rect) => { // Check if (rect == null) return true; // Last rect const lastRect = state.rect; // 32 = scroll bar width if (lastRect != null && state.mounted !== true && Math.abs(rect.width - lastRect.width) <= 32 && Math.abs(rect.height - lastRect.height) <= 32) return true; // Hold the new rect state.rect = rect; return false; }); const onInitLoad = (ref) => { // Avoid repeatedly load from cache if (refs.current.initLoaded || !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) { if ("resetAfterColumnIndex" in ref) { const { scrollLeft, scrollTop } = JSON.parse(scrollData); globalThis.setTimeout(() => ref.scrollTo({ scrollLeft, scrollTop }), 0); } else { const { scrollOffset } = JSON.parse(scrollData); globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0); } } // Update flag value refs.current.initLoaded = true; // Return cached rows and state return [rows, state]; } return undefined; }; const onListScroll = (props) => { if (!cacheKey || !refs.current.initLoaded) return; sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props)); }; const onGridScroll = (props) => { if (!cacheKey || !refs.current.initLoaded) return; sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props)); }; // Rect const rect = dimensions[0][2]; // Create list const list = (() => { // No layout if (rect == null) return undefined; // Height let heightLocal; if (height != null) { heightLocal = height; } else { // Auto calculation heightLocal = document.documentElement.clientHeight - Math.round(rect.bottom + 1); const style = window.getComputedStyle(dimensions[0][1]); const boxMargin = parseFloat(style.marginBottom); if (!isNaN(boxMargin)) heightLocal -= boxMargin; if (adjustHeight != null) heightLocal -= typeof adjustHeight === "number" ? adjustHeight : adjustHeight(heightLocal, rect); } if (adjustFabHeight) heightLocal = adjustFabHeight(heightLocal, showDataGrid); if (showDataGrid) { // Delete delete rest.itemRenderer; return (_jsx(Box, { className: "DataGridBox", children: _jsx(DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, onDoubleClick: (_, data) => quickAction && quickAction(data), outerRef: (element) => { if (element != null && elementReady) elementReady(element, true); }, onScroll: onGridScroll, columns: columns, onUpdateRows: GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, ...rest }) })); } // Delete delete rest.checkable; delete rest.borderRowsCount; delete rest.bottomHeight; delete rest.footerItemRenderer; delete rest.headerHeight; delete rest.hideFooter; delete rest.hoverColor; delete rest.selectable; return (_jsx(Box, { className: "ListBox", sx: { height: heightLocal }, children: _jsx(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, onUpdateRows: GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, mRef: mRefs, onClick: (event, data) => quickAction && ReactUtils.isSafeClick(event) && quickAction(data), oRef: (element) => { if (element != null && elementReady) elementReady(element, false); }, onScroll: onListScroll, ...rest }) })); })(); const searchBar = React.useMemo(() => { if (!hasFields || showDataGrid == null || rect?.width == null || rect.width < 20) return; const f = typeof fields == "function" ? fields(searchData) : fields; return (_jsx(SearchBar, { fields: f, onSubmit: onSubmit, className: `searchBar${showDataGrid ? "Grid" : "List"}`, width: rect.width, top: searchBarTop })); }, [showDataGrid, hasFields, searchBarHeight, rect?.width]); // Pull container const pullContainer = showDataGrid == null ? undefined : showDataGrid ? ".DataGridEx-Body" : ".ScrollerListEx-Body"; // Layout return (_jsxs(Box, { sx: containerBoxSx == null ? undefined : containerBoxSx(paddings, hasFields, showDataGrid), children: [_jsxs(Stack, { children: [_jsx(Box, { ref: dimensions[0][0], className: "SearchBox", sx: { height: hasFields ? searchBarHeight : 0 }, marginBottom: hasFields ? `${searchBarBottom}px!important` : undefined, children: searchBar }), list] }), pullToRefresh && pullContainer && list != null && (_jsx(PullToRefreshUI, { mainElement: pullContainer, triggerElement: pullContainer, instructionsPullToRefresh: labels.pullToRefresh, instructionsReleaseToRefresh: labels.releaseToRefresh, instructionsRefreshing: labels.refreshing, onRefresh: () => state.ref?.reset(), shouldPullToRefresh: () => { const container = document.querySelector(pullContainer); return !container?.scrollTop; } }))] })); }