@etsoo/materialui
Version:
TypeScript Material-UI Implementation
193 lines (192 loc) • 8.66 kB
JavaScript
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;
} }))] }));
}