UNPKG

@react95/gatsby-theme

Version:

A React95 theme for your Gatsby blog

179 lines (153 loc) 3.82 kB
import { Frame, Modal, Tree } from '@react95/core'; import * as R95Icons from '@react95/icons'; import styled from '@xstyled/styled-components'; import { Link, navigate } from 'gatsby'; import React from 'react'; import { isEmpty, isMobile } from '../utils'; import { TASKBAR_HEIGHT } from '../utils/constants'; import IconRenderer from './icon-renderer'; function getTreeData(nav, select) { return Object.values(nav).map( ({ slug, icon = {}, title, description, image, modal, ...restNavs }) => { const node = { label: title, title: description, id: slug, icon: <IconRenderer {...icon} />, }; if (!isEmpty(restNavs)) { const data = getTreeData(restNavs); return { ...node, onClick: () => select({ title, data }), children: data, }; } return { ...node, onClick: () => navigate(slug) }; }, ); } const Name = styled.span` word-break: break-word; padding: 2px; border: 1px dotted; border-color: transparent; `; const StyledFrame = styled(({ children, to, ...rest }) => ( <Frame {...rest}>{to ? <Link to={to}>{children}</Link> : children}</Frame> ))` text-align: center; position: relative; a, a:visited { color: inherit; text-decoration: none; } :focus { ${Frame}:after { content: ''; position: absolute; width: 100%; height: 100%; top: 0; left: 0; background-color: headerBackground; opacity: 0.5; } ${Name} { background-color: headerBackground; color: headerText; border-color: headerText; } } `; export const Shortcut = ({ label, icon: Icon = <R95Icons.Explorer101 variant="32x32_4" />, id: slug, ...rest }) => ( <StyledFrame display="inline-block" justifyContent="flex-start" alignItems="center" flexDirection="column" boxShadow="none" width="60px" bg="transparent" margin={12} tabIndex="0" {...(slug && { to: slug, })} {...rest} > <Frame mb={4} position="relative" boxShadow="none" bg="transparent" minHeight={34} display="flex" alignItems="center" justifyContent="center" > {Icon} </Frame> <Name>{label}</Name> </StyledFrame> ); const FrameWrapper = styled.div` height: 100%; display: grid; grid-template-columns: 1fr 2fr; grid-gap: 6px; `; const boxProps = { height: isMobile ? `calc(100% - ${TASKBAR_HEIGHT}px)` : 500, width: isMobile ? '100%' : 500, }; const ExplorerModal = ({ nav, closeModal }) => { const [selectedFolder, setSelectedFolder] = React.useState({ data: [] }); const treeData = getTreeData(nav, setSelectedFolder); return ( <Modal width="500" height="500" icon={<R95Icons.Explorer101 variant="16x16_4" />} title="Explorer" closeModal={closeModal} style={{ top: 0, ...boxProps }} > <FrameWrapper> <Frame bg="white" boxShadow="in" pl="1em" pr="1em"> <Tree data={treeData} /> </Frame> <Frame bg="white" boxShadow="in"> {selectedFolder.data.map((content) => ( <Shortcut key={content.id} {...content} /> ))} </Frame> </FrameWrapper> <Frame p={2} mt={6} boxShadow="in">{`${ Object.keys(nav).length } objects(s)`}</Frame> </Modal> ); }; const ContentExplorer = ({ nav }) => { const [isOpenned, toggleOpenned] = React.useState(false); return ( <> <Shortcut label="Explorer" onClick={() => toggleOpenned(true)} role="button" /> {isOpenned && ( <ExplorerModal nav={nav} closeModal={() => toggleOpenned(false)} /> )} </> ); }; export default ContentExplorer;