UNPKG

@pisell/layout

Version:

基于 Fusion 设计系统的自然布局体系

145 lines (142 loc) 6.3 kB
import _extends from "@babel/runtime/helpers/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose"; var _excluded = ["prefix", "className", "style", "children", "minHeight", "mode", "noPadding", "contentProps", "header", "nav", "aside", "footer", "breakPoints", "sectionGap", "blockGap", "gridGap", "onBreakPointChange"]; import React, { Children, forwardRef, isValidElement, useEffect, useMemo, useRef, useState } from 'react'; import classNames from 'classnames'; import isValidArray from 'is-valid-array'; import ResizeObserver from 'resize-observer-polyfill'; import { getCurBreakPoint, getMaxNumberOfColumns, isValidGap, wrapUnit } from "../utils"; import Context from "../common/context"; import { DEFAULT_BREAK_POINTS } from "../common/constant"; import useCombinedRefs from "../hooks/use-combine-ref"; import useGuid from "../hooks/use-guid"; import PageContent from "./content"; var Page = function Page(props, ref) { var _classNames; var prefix = props.prefix, className = props.className, style = props.style, children = props.children, minHeight = props.minHeight, mode = props.mode, noPadding = props.noPadding, contentProps = props.contentProps, header = props.header, nav = props.nav, aside = props.aside, footer = props.footer, breakPointsProp = props.breakPoints, sectionGap = props.sectionGap, blockGap = props.blockGap, gridGap = props.gridGap, onBreakPointChange = props.onBreakPointChange, others = _objectWithoutPropertiesLoose(props, _excluded); var pageStyle = useMemo(function () { return _extends({}, style, { minHeight: minHeight }); }, [style, minHeight]); // 保证断点一定是有效数组 var breakPoints = isValidArray(breakPointsProp) ? breakPointsProp : DEFAULT_BREAK_POINTS; var pageRef = useRef(null); var combinedRef = useCombinedRefs(ref, pageRef); var contentRef = useRef(null); var bpRef = useRef(getCurBreakPoint(breakPoints)); var _useState = useState(getCurBreakPoint(breakPoints)), curBreakPoint = _useState[0], setBreakPoint = _useState[1]; var guid = useGuid('fd-layout-'); var pageSizeObsr = new ResizeObserver(function () { var _bpRef$current; var newBreakPoint = getCurBreakPoint(breakPoints); if ((bpRef === null || bpRef === void 0 ? void 0 : (_bpRef$current = bpRef.current) === null || _bpRef$current === void 0 ? void 0 : _bpRef$current.width) !== newBreakPoint.width && onBreakPointChange) { onBreakPointChange(newBreakPoint, bpRef === null || bpRef === void 0 ? void 0 : bpRef.current, breakPoints); } bpRef.current = newBreakPoint; setBreakPoint(newBreakPoint); }); useEffect(function () { if (pageRef !== null && pageRef !== void 0 && pageRef.current) { pageSizeObsr.observe(pageRef.current); } // 默认执行一次回调 if (onBreakPointChange) { onBreakPointChange(getCurBreakPoint(breakPoints), undefined, breakPoints); } return function () { if (pageRef.current) { pageSizeObsr.unobserve(pageRef.current); } }; }, []); var headerNode = header; var footerNode = footer; var navNode = nav; var asideNode = aside; var contentsNodes = []; // 非标准节点 如 Section, P 等 var tmp = Children.map(children, function (child) { if ( /*#__PURE__*/isValidElement(child)) { var _child$type; // @ts-ignore var tm = child === null || child === void 0 ? void 0 : (_child$type = child.type) === null || _child$type === void 0 ? void 0 : _child$type.typeMark; if (tm) { if (tm === 'Header') { headerNode = child; } else if (tm === 'Footer') { footerNode = child; } else if (tm === 'Aside') { asideNode = child; } else if (tm === 'Nav') { navNode = child; } else if (tm === 'Content') { contentsNodes.push(child); } else { return child; } return null; } } return child; }); var nonStdChildren = Array.isArray(tmp) ? tmp.filter(function (c) { return !!c; }) : null; var pageCls = classNames(className, (_classNames = {}, _classNames[prefix + "page"] = true, _classNames[prefix + "page--col-" + curBreakPoint.numberOfColumns] = true, _classNames[prefix + "page--not-tab"] = true, _classNames[prefix + "page--headless"] = !headerNode, _classNames[prefix + "page--footless"] = !footerNode, _classNames[prefix + "page--no-padding"] = noPadding, _classNames[prefix + "bg--" + mode] = !!mode, _classNames)); var defaultContent = contentsNodes.length > 0 ? contentsNodes : /*#__PURE__*/React.createElement(PageContent // @ts-ignore , _extends({ ref: contentRef, noPadding: noPadding // @ts-ignore }, contentProps), navNode, asideNode, nonStdChildren); return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", { // eslint-disable-next-line react/no-danger dangerouslySetInnerHTML: { __html: "\n :host,\n #" + guid + " {\n --page-max-content-width: " + wrapUnit(curBreakPoint.maxContentWidth === Infinity ? '100%' : wrapUnit(curBreakPoint.maxContentWidth)) + ";\n " + (isValidGap(sectionGap) ? "--page-section-gap: " + wrapUnit(sectionGap) + ";" : '') + "\n " + (isValidGap(blockGap) ? "--page-block-gap: " + wrapUnit(blockGap) + ";" : '') + "\n " + (isValidGap(gridGap) ? "--page-grid-gap: " + wrapUnit(gridGap) + ";" : '') + "\n }" } }), /*#__PURE__*/React.createElement("div", _extends({ id: guid, ref: combinedRef, className: pageCls, style: pageStyle }, others), /*#__PURE__*/React.createElement(Context.Provider, { value: { prefix: prefix, noPadding: noPadding, sectionGap: sectionGap, gridGap: gridGap, blockGap: blockGap, breakPoint: curBreakPoint, maxNumberOfColumns: getMaxNumberOfColumns(breakPoints) } }, headerNode, defaultContent, footerNode))); }; var RefPage = /*#__PURE__*/forwardRef(Page); RefPage.displayName = 'Page'; RefPage.defaultProps = { prefix: 'fd-layout-', mode: 'lining', breakPoints: DEFAULT_BREAK_POINTS }; export default RefPage;