Web:Common: moved out catalog from page layout and refactoring page layout
This commit is contained in:
parent
b572b84410
commit
3ae4b92ad7
176
packages/asc-web-common/components/Catalog/index.js
Normal file
176
packages/asc-web-common/components/Catalog/index.js
Normal file
@ -0,0 +1,176 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import PropTypes from "prop-types";
|
||||
import { isMobile, isMobileOnly } from "react-device-detect";
|
||||
import { Resizable } from "re-resizable";
|
||||
|
||||
import {
|
||||
isDesktop as isDesktopUtils,
|
||||
isTablet as isTabletUtils,
|
||||
isMobile as isMobileUtils,
|
||||
} from "@appserver/components/utils/device";
|
||||
|
||||
import SubCatalogBackdrop from "./sub-components/catalog-backdrop";
|
||||
import SubCatalogHeader from "./sub-components/catalog-header";
|
||||
import SubCatalogMainButton from "./sub-components/catalog-main-button";
|
||||
import SubCatalogBody from "./sub-components/catalog-body";
|
||||
|
||||
import { StyledCatalog } from "./styled-catalog";
|
||||
|
||||
const enable = {
|
||||
top: false,
|
||||
right: !isMobile,
|
||||
bottom: false,
|
||||
left: false,
|
||||
};
|
||||
|
||||
const Catalog = ({
|
||||
showText,
|
||||
setShowText,
|
||||
catalogOpen,
|
||||
toggleShowText,
|
||||
toggleCatalogOpen,
|
||||
children,
|
||||
...rest
|
||||
}) => {
|
||||
const [catalogHeaderContent, setCatalogHeaderContent] = React.useState(null);
|
||||
const [
|
||||
catalogMainButtonContent,
|
||||
setCatalogMainButtonContent,
|
||||
] = React.useState(null);
|
||||
const [catalogBodyContent, setCatalogBodyContent] = React.useState(null);
|
||||
|
||||
const refTimer = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isMobileOnly) {
|
||||
window.addEventListener("popstate", hideText);
|
||||
return () => window.removeEventListener("popstate", hideText);
|
||||
}
|
||||
}, [hideText]);
|
||||
|
||||
React.useEffect(() => {
|
||||
window.addEventListener("resize", sizeChangeHandler);
|
||||
return () => window.removeEventListener("resize", sizeChangeHandler);
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
sizeChangeHandler();
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
React.Children.forEach(children, (child) => {
|
||||
const childType =
|
||||
child && child.type && (child.type.displayName || child.type.name);
|
||||
|
||||
switch (childType) {
|
||||
case Catalog.Header.displayName:
|
||||
setCatalogHeaderContent(child);
|
||||
break;
|
||||
case Catalog.MainButton.displayName:
|
||||
setCatalogMainButtonContent(child);
|
||||
break;
|
||||
case Catalog.Body.displayName:
|
||||
setCatalogBodyContent(child);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}, [children]);
|
||||
|
||||
const sizeChangeHandler = React.useCallback(() => {
|
||||
clearTimeout(refTimer.current);
|
||||
|
||||
refTimer.current = setTimeout(() => {
|
||||
if (isMobileOnly || isMobileUtils() || window.innerWidth === 375)
|
||||
setShowText(true);
|
||||
if (
|
||||
((isTabletUtils() && window.innerWidth !== 375) || isMobile) &&
|
||||
!isMobileOnly
|
||||
)
|
||||
setShowText(false);
|
||||
if (isDesktopUtils() && !isMobile) setShowText(true);
|
||||
}, 100);
|
||||
}, [refTimer.current, setShowText]);
|
||||
|
||||
const hideText = React.useCallback((event) => {
|
||||
event.preventDefault;
|
||||
setShowText(false);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledCatalog showText={showText} catalogOpen={catalogOpen} {...rest}>
|
||||
<Resizable
|
||||
defaultSize={{
|
||||
width: 256,
|
||||
}}
|
||||
enable={enable}
|
||||
className="resizable-block"
|
||||
handleWrapperClass="resizable-border not-selectable"
|
||||
>
|
||||
<SubCatalogHeader showText={showText} onClick={toggleShowText}>
|
||||
{catalogHeaderContent ? catalogHeaderContent.props.children : null}
|
||||
</SubCatalogHeader>
|
||||
<SubCatalogMainButton showText={showText}>
|
||||
{catalogMainButtonContent
|
||||
? catalogMainButtonContent.props.children
|
||||
: null}
|
||||
</SubCatalogMainButton>
|
||||
<SubCatalogBody showText={showText}>
|
||||
{catalogBodyContent ? catalogBodyContent.props.children : null}
|
||||
</SubCatalogBody>
|
||||
</Resizable>
|
||||
</StyledCatalog>
|
||||
{catalogOpen && (isMobileOnly || window.innerWidth <= 375) && (
|
||||
<>
|
||||
<SubCatalogBackdrop onClick={toggleCatalogOpen} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Catalog.propTypes = {
|
||||
showText: PropTypes.bool,
|
||||
setShowText: PropTypes.func,
|
||||
catalogOpen: PropTypes.bool,
|
||||
toggleCatalogOpen: PropTypes.func,
|
||||
children: PropTypes.any,
|
||||
};
|
||||
|
||||
Catalog.Header = () => {
|
||||
return null;
|
||||
};
|
||||
Catalog.Header.displayName = "Header";
|
||||
|
||||
Catalog.MainButton = () => {
|
||||
return null;
|
||||
};
|
||||
Catalog.MainButton.displayName = "MainButton";
|
||||
|
||||
Catalog.Body = () => {
|
||||
return null;
|
||||
};
|
||||
Catalog.Body.displayName = "Body";
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { isLoaded, settingsStore } = auth;
|
||||
|
||||
const {
|
||||
showText,
|
||||
setShowText,
|
||||
catalogOpen,
|
||||
toggleShowText,
|
||||
toggleCatalogOpen,
|
||||
} = settingsStore;
|
||||
|
||||
return {
|
||||
showText,
|
||||
setShowText,
|
||||
catalogOpen,
|
||||
toggleShowText,
|
||||
toggleCatalogOpen,
|
||||
};
|
||||
})(observer(Catalog));
|
269
packages/asc-web-common/components/Catalog/styled-catalog.js
Normal file
269
packages/asc-web-common/components/Catalog/styled-catalog.js
Normal file
@ -0,0 +1,269 @@
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { isMobile, isMobileOnly, isTablet } from "react-device-detect";
|
||||
import {
|
||||
mobile,
|
||||
tablet,
|
||||
isMobile as isMobileUtils,
|
||||
isTablet as isTabletUtils,
|
||||
isDesktop as isDesktopUtils,
|
||||
} from "@appserver/components/utils/device";
|
||||
|
||||
import Heading from "@appserver/components/heading";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
import MenuIcon from "@appserver/components/public/static/images/menu.react.svg";
|
||||
import CrossIcon from "@appserver/components/public/static/images/cross.react.svg";
|
||||
|
||||
const StyledCatalog = styled.div`
|
||||
position: relative;
|
||||
|
||||
background: ${(props) => props.theme.catalog.background};
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
margin-top: 48px;
|
||||
`}
|
||||
|
||||
@media ${mobile} {
|
||||
position: fixed;
|
||||
margin-top: 16px;
|
||||
height: calc(100vh - 64px) !important;
|
||||
z-index: 400;
|
||||
}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
position: fixed;
|
||||
margin-top: 64px !important;
|
||||
height: calc(100vh - 64px) !important;
|
||||
`}
|
||||
|
||||
z-index: ${(props) =>
|
||||
props.showText && (isMobileOnly || isMobileUtils()) ? "205" : "100"};
|
||||
|
||||
.resizable-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
min-width: ${(props) => (props.showText ? "256px" : "52px")};
|
||||
width: ${(props) => (props.showText ? "256px" : "52px")};
|
||||
|
||||
height: calc(100% - 44px) !important;
|
||||
|
||||
background: ${(props) => props.theme.catalog.background};
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scrollbar-width: none;
|
||||
padding-bottom: 0px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
.resizable-border {
|
||||
div {
|
||||
cursor: ew-resize !important;
|
||||
}
|
||||
}
|
||||
@media ${tablet} {
|
||||
min-width: ${(props) => (props.showText ? "240px" : "52px")};
|
||||
max-width: ${(props) => (props.showText ? "240px" : "52px")};
|
||||
.resizable-border {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
display: ${(props) => (props.catalogOpen ? "flex" : "none")};
|
||||
min-width: 100vw;
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px) !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
${isTablet &&
|
||||
css`
|
||||
min-width: ${(props) => (props.showText ? "240px" : "52px")};
|
||||
max-width: ${(props) => (props.showText ? "240px" : "52px")};
|
||||
.resizable-border {
|
||||
display: none;
|
||||
}
|
||||
`}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
display: ${(props) => (props.catalogOpen ? "flex" : "none")};
|
||||
min-width: 100vw !important;
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px) !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-bottom: 0px;
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledCatalog.defaultProps = { theme: Base };
|
||||
|
||||
const StyledCatalogHeader = styled.div`
|
||||
padding: 12px 20px 13px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
@media ${tablet} {
|
||||
padding: 16px 16px 17px;
|
||||
margin: 0;
|
||||
justify-content: ${(props) => (props.showText ? "flex-start" : "center")};
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
border-bottom: ${(props) => props.theme.catalog.header.borderBottom};
|
||||
padding: 12px 16px 12px;
|
||||
margin-bottom: 16px !important;
|
||||
}
|
||||
|
||||
${isTablet &&
|
||||
css`
|
||||
padding: 16px 16px 17px;
|
||||
justify-content: ${(props) => (props.showText ? "flex-start" : "center")};
|
||||
margin: 0;
|
||||
`}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
border-bottom: ${(props) =>
|
||||
props.theme.catalog.header.borderBottom} !important;
|
||||
padding: 12px 16px 12px !important;
|
||||
margin-bottom: 16px !important;
|
||||
`}
|
||||
`;
|
||||
|
||||
StyledCatalogHeader.defaultProps = { theme: Base };
|
||||
|
||||
const StyledHeading = styled(Heading)`
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
line-height: 28px;
|
||||
@media ${tablet} {
|
||||
display: ${(props) => (props.showText ? "block" : "none")};
|
||||
margin-left: ${(props) => props.showText && "12px"};
|
||||
}
|
||||
|
||||
${isTablet &&
|
||||
css`
|
||||
display: ${(props) => (props.showText ? "block" : "none")};
|
||||
margin-left: ${(props) => props.showText && "12px"};
|
||||
`}
|
||||
|
||||
@media ${mobile} {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
margin-left: 0 !important;
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledIconBox = styled.div`
|
||||
display: none;
|
||||
align-items: center;
|
||||
height: 28px;
|
||||
|
||||
@media ${tablet} {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
display: flex !important;
|
||||
`}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
display: none !important;
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledMenuIcon = styled(MenuIcon)`
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
path {
|
||||
fill: ${(props) => props.theme.catalog.header.iconFill};
|
||||
}
|
||||
`;
|
||||
|
||||
StyledMenuIcon.defaultProps = { theme: Base };
|
||||
|
||||
const StyledCatalogMainButton = styled.div`
|
||||
padding: 0px 20px 16px;
|
||||
max-width: 216px;
|
||||
@media ${tablet} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
${isTablet &&
|
||||
css`
|
||||
display: none;
|
||||
`}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
display: none;
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledControlContainer = styled.div`
|
||||
background: ${(props) => props.theme.catalog.control.background};
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 10px;
|
||||
border-radius: 100px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 290;
|
||||
`;
|
||||
|
||||
StyledControlContainer.defaultProps = { theme: Base };
|
||||
|
||||
const StyledCrossIcon = styled(CrossIcon)`
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
path {
|
||||
fill: ${(props) => props.theme.catalog.control.fill};
|
||||
}
|
||||
`;
|
||||
|
||||
StyledCrossIcon.defaultProps = { theme: Base };
|
||||
|
||||
export {
|
||||
StyledCatalog,
|
||||
StyledCatalogHeader,
|
||||
StyledHeading,
|
||||
StyledIconBox,
|
||||
StyledMenuIcon,
|
||||
StyledCatalogMainButton,
|
||||
StyledControlContainer,
|
||||
StyledCrossIcon,
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Backdrop from "@appserver/components/backdrop";
|
||||
|
||||
import { StyledControlContainer, StyledCrossIcon } from "../styled-catalog";
|
||||
|
||||
const CatalogBackdrop = ({ showText, onClick, ...rest }) => {
|
||||
return (
|
||||
<>
|
||||
<StyledControlContainer onClick={onClick} {...rest}>
|
||||
<StyledCrossIcon />
|
||||
</StyledControlContainer>
|
||||
<Backdrop visible={true} zIndex={201} withBackground={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
CatalogBackdrop.propTypes = {
|
||||
showText: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default React.memo(CatalogBackdrop);
|
@ -0,0 +1,9 @@
|
||||
import React from "react";
|
||||
|
||||
const CatalogBody = ({ children }) => {
|
||||
return <> {children}</>;
|
||||
};
|
||||
|
||||
CatalogBody.displayName = "Body";
|
||||
|
||||
export default React.memo(CatalogBody);
|
@ -0,0 +1,33 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import {
|
||||
StyledCatalogHeader,
|
||||
StyledHeading,
|
||||
StyledIconBox,
|
||||
StyledMenuIcon,
|
||||
} from "../styled-catalog";
|
||||
|
||||
const CatalogHeader = ({ showText, children, onClick, ...rest }) => {
|
||||
return (
|
||||
<StyledCatalogHeader showText={showText} {...rest}>
|
||||
<StyledIconBox name="catalog-burger">
|
||||
<StyledMenuIcon onClick={onClick} />
|
||||
</StyledIconBox>
|
||||
|
||||
<StyledHeading showText={showText} size="large">
|
||||
{children}
|
||||
</StyledHeading>
|
||||
</StyledCatalogHeader>
|
||||
);
|
||||
};
|
||||
|
||||
CatalogHeader.propTypes = {
|
||||
children: PropTypes.any,
|
||||
showText: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
CatalogHeader.displayName = "Header";
|
||||
|
||||
export default React.memo(CatalogHeader);
|
@ -0,0 +1,11 @@
|
||||
import React from "react";
|
||||
|
||||
import { StyledCatalogMainButton } from "../styled-catalog";
|
||||
|
||||
const CatalogMainButton = (props) => {
|
||||
return <StyledCatalogMainButton {...props} />;
|
||||
};
|
||||
|
||||
CatalogMainButton.displayName = "MainButton";
|
||||
|
||||
export default CatalogMainButton;
|
@ -27,11 +27,6 @@ import FloatingButton from "../FloatingButton";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import Selecto from "react-selecto";
|
||||
import styled, { css } from "styled-components";
|
||||
import Catalog from "./sub-components/catalog";
|
||||
import SubCatalogBackdrop from "./sub-components/catalog-backdrop";
|
||||
import SubCatalogHeader from "./sub-components/catalog-header";
|
||||
import SubCatalogMainButton from "./sub-components/catalog-main-button";
|
||||
import SubCatalogBody from "./sub-components/catalog-body";
|
||||
|
||||
const StyledSelectoWrapper = styled.div`
|
||||
.selecto-selection {
|
||||
@ -58,21 +53,6 @@ const StyledMainBar = styled.div`
|
||||
`}
|
||||
`;
|
||||
|
||||
function CatalogHeader() {
|
||||
return null;
|
||||
}
|
||||
CatalogHeader.displayName = "CatalogHeader";
|
||||
|
||||
function CatalogMainButton() {
|
||||
return null;
|
||||
}
|
||||
CatalogMainButton.displayName = "CatalogMainButton";
|
||||
|
||||
function CatalogBody() {
|
||||
return null;
|
||||
}
|
||||
CatalogBody.displayName = "CatalogBody";
|
||||
|
||||
function ArticleHeader() {
|
||||
return null;
|
||||
}
|
||||
@ -109,9 +89,6 @@ function SectionPaging() {
|
||||
SectionPaging.displayName = "SectionPaging";
|
||||
|
||||
class PageLayout extends React.Component {
|
||||
static CatalogHeader = CatalogHeader;
|
||||
static CatalogMainButton = CatalogMainButton;
|
||||
static CatalogBody = CatalogBody;
|
||||
static ArticleHeader = ArticleHeader;
|
||||
static ArticleMainButton = ArticleMainButton;
|
||||
static ArticleBody = ArticleBody;
|
||||
@ -259,16 +236,8 @@ class PageLayout extends React.Component {
|
||||
isArticlePinned,
|
||||
isDesktop,
|
||||
isHomepage,
|
||||
showText,
|
||||
catalogOpen,
|
||||
userShowText,
|
||||
setShowText,
|
||||
toggleShowText,
|
||||
toggleCatalogOpen,
|
||||
} = this.props;
|
||||
let catalogHeaderContent = null;
|
||||
let catalogMainButtonContent = null;
|
||||
let catalogBodyContent = null;
|
||||
|
||||
let articleHeaderContent = null;
|
||||
let articleMainButtonContent = null;
|
||||
let articleBodyContent = null;
|
||||
@ -281,15 +250,6 @@ class PageLayout extends React.Component {
|
||||
child && child.type && (child.type.displayName || child.type.name);
|
||||
|
||||
switch (childType) {
|
||||
case CatalogHeader.displayName:
|
||||
catalogHeaderContent = child;
|
||||
break;
|
||||
case CatalogMainButton.displayName:
|
||||
catalogMainButtonContent = child;
|
||||
break;
|
||||
case CatalogBody.displayName:
|
||||
catalogBodyContent = child;
|
||||
break;
|
||||
case ArticleHeader.displayName:
|
||||
articleHeaderContent = child;
|
||||
break;
|
||||
@ -336,61 +296,11 @@ class PageLayout extends React.Component {
|
||||
isSectionBodyAvailable ||
|
||||
isSectionPagingAvailable ||
|
||||
isArticleAvailable,
|
||||
isBackdropAvailable = isArticleAvailable,
|
||||
isCatalogHeaderAvailable = !!catalogHeaderContent,
|
||||
isCatalogMainButtonAvailable = !!catalogMainButtonContent,
|
||||
isCatalogBodyAvailable = !!catalogBodyContent,
|
||||
isCatalogAvailable =
|
||||
isCatalogHeaderAvailable ||
|
||||
isCatalogMainButtonAvailable ||
|
||||
isCatalogBodyAvailable;
|
||||
isBackdropAvailable = isArticleAvailable;
|
||||
|
||||
const renderPageLayout = () => {
|
||||
return (
|
||||
<>
|
||||
{isCatalogAvailable && (
|
||||
<>
|
||||
{catalogOpen && (isMobileOnly || window.innerWidth <= 375) && (
|
||||
<>
|
||||
<SubCatalogBackdrop onClick={toggleCatalogOpen} />
|
||||
<Backdrop visible={true} zIndex={201} />
|
||||
</>
|
||||
)}
|
||||
<Catalog
|
||||
showText={showText}
|
||||
catalogOpen={catalogOpen}
|
||||
toggleCatalogOpen={toggleCatalogOpen}
|
||||
setShowText={setShowText}
|
||||
>
|
||||
{isCatalogHeaderAvailable && (
|
||||
<SubCatalogHeader
|
||||
showText={showText}
|
||||
onClick={toggleShowText}
|
||||
>
|
||||
{catalogHeaderContent
|
||||
? catalogHeaderContent.props.children
|
||||
: null}
|
||||
</SubCatalogHeader>
|
||||
)}
|
||||
|
||||
{isCatalogMainButtonAvailable && (
|
||||
<SubCatalogMainButton showText={showText}>
|
||||
{catalogMainButtonContent
|
||||
? catalogMainButtonContent.props.children
|
||||
: null}
|
||||
</SubCatalogMainButton>
|
||||
)}
|
||||
|
||||
{isCatalogBodyAvailable && (
|
||||
<SubCatalogBody showText={showText}>
|
||||
{catalogBodyContent
|
||||
? catalogBodyContent.props.children
|
||||
: null}
|
||||
</SubCatalogBody>
|
||||
)}
|
||||
</Catalog>
|
||||
</>
|
||||
)}
|
||||
{isBackdropAvailable && (
|
||||
<Backdrop
|
||||
zIndex={400}
|
||||
@ -448,7 +358,6 @@ class PageLayout extends React.Component {
|
||||
}}
|
||||
>
|
||||
<Section
|
||||
catalogOpen={catalogOpen}
|
||||
widthProp={width}
|
||||
unpinArticle={this.unpinArticle}
|
||||
pinned={isArticlePinned}
|
||||
@ -627,13 +536,6 @@ PageLayout.propTypes = {
|
||||
isHeaderVisible: PropTypes.bool,
|
||||
firstLoad: PropTypes.bool,
|
||||
isHomepage: PropTypes.bool,
|
||||
showText: PropTypes.bool,
|
||||
userShowText: PropTypes.bool,
|
||||
setShowText: PropTypes.func,
|
||||
toggleShowText: PropTypes.func,
|
||||
showCatalog: PropTypes.bool,
|
||||
toggleCatalogOpen: PropTypes.func,
|
||||
catalogOpen: PropTypes.bool,
|
||||
};
|
||||
|
||||
PageLayout.defaultProps = {
|
||||
@ -641,8 +543,6 @@ PageLayout.defaultProps = {
|
||||
withBodyAutoFocus: false,
|
||||
};
|
||||
|
||||
PageLayout.CatalogHeader = CatalogHeader;
|
||||
PageLayout.CatalogMainButton = CatalogMainButton;
|
||||
PageLayout.ArticleHeader = ArticleHeader;
|
||||
PageLayout.ArticleMainButton = ArticleMainButton;
|
||||
PageLayout.ArticleBody = ArticleBody;
|
||||
@ -664,13 +564,6 @@ export default inject(({ auth }) => {
|
||||
setIsArticleVisible,
|
||||
setIsBackdropVisible,
|
||||
isDesktopClient,
|
||||
showText,
|
||||
userShowText,
|
||||
setShowText,
|
||||
toggleShowText,
|
||||
showCatalog,
|
||||
toggleCatalogOpen,
|
||||
catalogOpen,
|
||||
} = settingsStore;
|
||||
|
||||
return {
|
||||
@ -685,12 +578,5 @@ export default inject(({ auth }) => {
|
||||
isBackdropVisible,
|
||||
setIsBackdropVisible,
|
||||
isDesktop: isDesktopClient,
|
||||
showText,
|
||||
setShowText,
|
||||
toggleShowText,
|
||||
showCatalog,
|
||||
userShowText,
|
||||
toggleCatalogOpen,
|
||||
catalogOpen,
|
||||
};
|
||||
})(observer(PageLayout));
|
||||
|
@ -1,48 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from "styled-components";
|
||||
import CrossIcon from "@appserver/components/public/static/images/cross.react.svg";
|
||||
import Base from "@appserver/components/themes/base";
|
||||
|
||||
const StyledControlContainer = styled.div`
|
||||
background: ${(props) => props.theme.catalog.control.background};
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 10px;
|
||||
border-radius: 100px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 290;
|
||||
`;
|
||||
|
||||
StyledControlContainer.defaultProps = { theme: Base };
|
||||
|
||||
const StyledCrossIcon = styled(CrossIcon)`
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
path {
|
||||
fill: ${(props) => props.theme.catalog.control.fill};
|
||||
}
|
||||
`;
|
||||
|
||||
StyledCrossIcon.defaultProps = { theme: Base };
|
||||
|
||||
const CatalogBackdrop = (props) => {
|
||||
const { showText, onClick, ...rest } = props;
|
||||
return (
|
||||
<StyledControlContainer onClick={onClick} {...rest}>
|
||||
<StyledCrossIcon />
|
||||
</StyledControlContainer>
|
||||
);
|
||||
};
|
||||
|
||||
CatalogBackdrop.propTypes = {
|
||||
showText: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default React.memo(CatalogBackdrop);
|
@ -1,9 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
const CatalogBody = (props) => {
|
||||
return <> {props.children}</>;
|
||||
};
|
||||
|
||||
CatalogBody.displayName = "CatalogBody";
|
||||
|
||||
export default React.memo(CatalogBody);
|
@ -1,134 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import styled, { css } from "styled-components";
|
||||
import Heading from "@appserver/components/heading";
|
||||
import { isMobileOnly, isTablet } from "react-device-detect";
|
||||
import MenuIcon from "@appserver/components/public/static/images/menu.react.svg";
|
||||
import { tablet, mobile } from "@appserver/components/utils/device";
|
||||
import Base from "@appserver/components/themes/base";
|
||||
|
||||
const StyledCatalogHeader = styled.div`
|
||||
padding: 12px 20px 13px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
@media ${tablet} {
|
||||
padding: 16px 16px 17px;
|
||||
margin: 0;
|
||||
justify-content: ${(props) => (props.showText ? "flex-start" : "center")};
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
border-bottom: ${(props) => props.theme.catalog.header.borderBottom};
|
||||
padding: 12px 16px 12px;
|
||||
margin-bottom: 16px !important;
|
||||
}
|
||||
|
||||
${isTablet &&
|
||||
css`
|
||||
padding: 16px 16px 17px;
|
||||
justify-content: ${(props) => (props.showText ? "flex-start" : "center")};
|
||||
margin: 0;
|
||||
`}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
border-bottom: ${(props) =>
|
||||
props.theme.catalog.header.borderBottom} !important;
|
||||
padding: 12px 16px 12px !important;
|
||||
margin-bottom: 16px !important;
|
||||
`}
|
||||
`;
|
||||
|
||||
StyledCatalogHeader.defaultProps = { theme: Base };
|
||||
|
||||
const StyledHeading = styled(Heading)`
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
line-height: 28px;
|
||||
@media ${tablet} {
|
||||
display: ${(props) => (props.showText ? "block" : "none")};
|
||||
margin-left: ${(props) => props.showText && "12px"};
|
||||
}
|
||||
|
||||
${isTablet &&
|
||||
css`
|
||||
display: ${(props) => (props.showText ? "block" : "none")};
|
||||
margin-left: ${(props) => props.showText && "12px"};
|
||||
`}
|
||||
|
||||
@media ${mobile} {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
margin-left: 0 !important;
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledIconBox = styled.div`
|
||||
display: none;
|
||||
align-items: center;
|
||||
height: 28px;
|
||||
|
||||
@media ${tablet} {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
${isTablet &&
|
||||
css`
|
||||
display: flex !important;
|
||||
`}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
display: none !important;
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledMenuIcon = styled(MenuIcon)`
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
path {
|
||||
fill: ${(props) => props.theme.catalog.header.iconFill};
|
||||
}
|
||||
`;
|
||||
|
||||
StyledMenuIcon.defaultProps = { theme: Base };
|
||||
|
||||
const CatalogHeader = (props) => {
|
||||
const { showText, children, onClick, ...rest } = props;
|
||||
|
||||
return (
|
||||
<StyledCatalogHeader showText={showText} {...rest}>
|
||||
<StyledIconBox name="catalog-burger">
|
||||
<StyledMenuIcon onClick={onClick} />
|
||||
</StyledIconBox>
|
||||
|
||||
<StyledHeading showText={showText} size="large">
|
||||
{children}
|
||||
</StyledHeading>
|
||||
</StyledCatalogHeader>
|
||||
);
|
||||
};
|
||||
|
||||
CatalogHeader.propTypes = {
|
||||
children: PropTypes.any,
|
||||
showText: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
CatalogHeader.displayName = "CatalogHeader";
|
||||
|
||||
export default React.memo(CatalogHeader);
|
@ -1,34 +0,0 @@
|
||||
import React from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
import { isMobileOnly, isTablet } from "react-device-detect";
|
||||
import { mobile, tablet } from "@appserver/components/utils/device";
|
||||
|
||||
const StyledCatalogMainButton = styled.div`
|
||||
padding: 0px 20px 16px;
|
||||
max-width: 216px;
|
||||
@media ${tablet} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
${isTablet &&
|
||||
css`
|
||||
display: none;
|
||||
`}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
display: none;
|
||||
`}
|
||||
`;
|
||||
|
||||
const CatalogMainButton = (props) => {
|
||||
return <StyledCatalogMainButton {...props} />;
|
||||
};
|
||||
|
||||
CatalogMainButton.displayName = "CatalogMainButton";
|
||||
|
||||
export default CatalogMainButton;
|
@ -1,175 +0,0 @@
|
||||
import React from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
import PropTypes from "prop-types";
|
||||
import { Resizable } from "re-resizable";
|
||||
import { isMobile, isMobileOnly, isTablet } from "react-device-detect";
|
||||
import {
|
||||
mobile,
|
||||
tablet,
|
||||
isMobile as isMobileUtils,
|
||||
isTablet as isTabletUtils,
|
||||
isDesktop as isDesktopUtils,
|
||||
} from "@appserver/components/utils/device";
|
||||
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
const StyledCatalog = styled.div`
|
||||
position: relative;
|
||||
|
||||
background: ${(props) => props.theme.catalog.background};
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
margin-top: 48px;
|
||||
`}
|
||||
|
||||
@media ${mobile} {
|
||||
position: fixed;
|
||||
margin-top: 16px;
|
||||
height: calc(100vh - 64px) !important;
|
||||
z-index: 400;
|
||||
}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
position: fixed;
|
||||
margin-top: 64px !important;
|
||||
height: calc(100vh - 64px) !important;
|
||||
`}
|
||||
|
||||
z-index: ${(props) =>
|
||||
props.showText && (isMobileOnly || isMobileUtils()) ? "201" : "100"};
|
||||
|
||||
.resizable-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
min-width: ${(props) => (props.showText ? "256px" : "52px")};
|
||||
width: ${(props) => (props.showText ? "256px" : "52px")};
|
||||
|
||||
height: calc(100% - 44px) !important;
|
||||
|
||||
background: ${(props) => props.theme.catalog.background};
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scrollbar-width: none;
|
||||
padding-bottom: 0px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
.resizable-border {
|
||||
div {
|
||||
cursor: ew-resize !important;
|
||||
}
|
||||
}
|
||||
@media ${tablet} {
|
||||
min-width: ${(props) => (props.showText ? "240px" : "52px")};
|
||||
max-width: ${(props) => (props.showText ? "240px" : "52px")};
|
||||
.resizable-border {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
display: ${(props) => (props.catalogOpen ? "flex" : "none")};
|
||||
min-width: 100vw;
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px) !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
${isTablet &&
|
||||
css`
|
||||
min-width: ${(props) => (props.showText ? "240px" : "52px")};
|
||||
max-width: ${(props) => (props.showText ? "240px" : "52px")};
|
||||
.resizable-border {
|
||||
display: none;
|
||||
}
|
||||
`}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
display: ${(props) => (props.catalogOpen ? "flex" : "none")};
|
||||
min-width: 100vw !important;
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px) !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-bottom: 0px;
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledCatalog.defaultProps = { theme: Base };
|
||||
|
||||
const Catalog = (props) => {
|
||||
const { showText, setShowText, catalogOpen, children, ...rest } = props;
|
||||
const refTimer = React.useRef(null);
|
||||
const enable = {
|
||||
top: false,
|
||||
right: !isMobile,
|
||||
bottom: false,
|
||||
left: false,
|
||||
};
|
||||
|
||||
const hideText = React.useCallback((event) => {
|
||||
event.preventDefault;
|
||||
setShowText(false);
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isMobileOnly) {
|
||||
window.addEventListener("popstate", hideText);
|
||||
return () => window.removeEventListener("popstate", hideText);
|
||||
}
|
||||
}, [hideText]);
|
||||
React.useEffect(() => {
|
||||
window.addEventListener("resize", sizeChangeHandler);
|
||||
return () => window.removeEventListener("resize", sizeChangeHandler);
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
sizeChangeHandler();
|
||||
}, []);
|
||||
const sizeChangeHandler = () => {
|
||||
clearTimeout(refTimer.current);
|
||||
|
||||
refTimer.current = setTimeout(() => {
|
||||
if (isMobileOnly || isMobileUtils() || window.innerWidth === 375)
|
||||
props.setShowText(true);
|
||||
if (
|
||||
((isTabletUtils() && window.innerWidth !== 375) || isMobile) &&
|
||||
!isMobileOnly
|
||||
)
|
||||
props.setShowText(false);
|
||||
if (isDesktopUtils() && !isMobile) props.setShowText(true);
|
||||
}, 100);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledCatalog showText={showText} catalogOpen={catalogOpen} {...rest}>
|
||||
<Resizable
|
||||
defaultSize={{
|
||||
width: 256,
|
||||
}}
|
||||
enable={enable}
|
||||
className="resizable-block"
|
||||
handleWrapperClass="resizable-border not-selectable"
|
||||
>
|
||||
{children}
|
||||
</Resizable>
|
||||
</StyledCatalog>
|
||||
);
|
||||
};
|
||||
|
||||
Catalog.propTypes = {
|
||||
showText: PropTypes.bool,
|
||||
setShowText: PropTypes.func,
|
||||
children: PropTypes.any,
|
||||
};
|
||||
|
||||
export default Catalog;
|
Loading…
Reference in New Issue
Block a user