import React, { useState } from "react"; import { TinaCMS, TinaCMSConfig, TinaProvider } from "tinacms"; import { Button } from "@tinacms/styles"; import { useLoadPage } from "../hooks"; import { CodeBlock } from "./CodeBlock"; import Loader from "./Loader"; import ErrorRenderer from "./ErrorRenderer"; import styled, { css } from "styled-components"; import { DocsTextWrapper, GlobalStyle } from "./tinaioStyles/DocsTextWrapper"; import Toc from "./tinaioStyles/toc"; import Pagination from "./Pagination"; export interface Config { pages: Page[]; components: { Link: React.FC<{ to: string }>; Loading?: React.FC; RenderError?: React.FC<{ error: Error }>; }; labels?: { tableOfContentsTitle?: string; }; cmsToggle?: boolean; tinaConfig?: TinaCMSConfig; } export interface DemoPage { default: React.FC; code?: string; tinaConfig?: TinaCMSConfig; } export interface Page { label: string; slug: string; loadPage: Promise; } export const MDXComponents = { pre: function pre(props: any) { return
; }, code: CodeBlock, }; export interface LayoutProps { config: Config; currentSlug: string; } export const Layout: React.FC = ({ config, currentSlug }) => { const cleanCurrentSlug = currentSlug.startsWith("/") ? currentSlug : "/" + currentSlug; const { Link, Loading, RenderError } = config.components; const [showCode, setVisibility] = useState(false); const foundPage = config.pages.find((page) => page.slug === cleanCurrentSlug); if (!foundPage) { throw Error(`did not find page with slug ${currentSlug}`); } const currentPage = foundPage; const currentIndex = config.pages.findIndex((page) => page === currentPage); const [Page, loading, error] = useLoadPage( currentPage.loadPage as Promise ); // eslint-disable-next-line @typescript-eslint/no-var-requires const pageTinaConfig: TinaCMSConfig = Page?.tinaConfig || {}; const cms = new TinaCMS({ ...config.tinaConfig, ...pageTinaConfig, }); const ErrorHandler = (RenderError || ErrorRenderer) as React.FC< React.PropsWithChildren >; const errorMessage = error?.message || JSON.stringify(error); return ( <> {(loading && Loading && ) || Loader} {errorMessage && {errorMessage}} {Page && ( <> {config.cmsToggle && ( )} {Page.code && ( )} {showCode && ( {typeof Page.code == "undefined" ? "" : Page.code.toString() || ""} )} )} ); }; /* * STYLES -------------------------------------------------------------- */ export const DocGridToc = styled.div` grid-area: toc; width: 100%; @media (min-width: 830px) { padding-top: 4.5rem; } `; interface DocsLayoutProps { children: any; } const DocsLayout = ({ children }: DocsLayoutProps) => { return ( <> {children} ); }; const Overlay = styled.div` pointer-events: none; display: block; position: fixed; z-index: -1; top: 0; left: 0; width: 100%; height: 100%; background-color: var(--color-secondary); transition: all 180ms ease-out; opacity: 0; z-index: 1200; ${(props) => props.open && css` opacity: 0.7; pointer-events: all; `}; `; const DocsLayoutDiv = styled.div` @media (min-width: 1200px) { position: relative; padding: 0 0 0 16rem; ${Overlay} { display: none; } } `; interface Overlay { open: boolean; } export const DocsGrid = styled.div` display: grid; width: 100%; position: relative; grid-auto-columns: minmax(1.5rem, 4rem) minmax(280px, 768px) minmax(1.5rem, 4rem); grid-template-areas: ". header ." ". toc ." ". content ."; padding-top: 2rem; padding-bottom: 3rem; @media (min-width: 830px) { grid-template-areas: ". header header ." ". content toc ."; margin: 0 auto; grid-auto-columns: minmax(2rem, auto) fit-content(768px) 240px minmax(0, auto); grid-column-gap: 2rem; } @media (min-width: 1600px) { grid-auto-columns: auto 768px 330px auto; grid-column-gap: 3rem; } `; export const DocGridHeader = styled.div` grid-area: header; width: 100%; @media (min-width: 830px) { max-width: none; } `; export const DocGridContent = styled.div` grid-area: content; width: 100%; `; export const DocsPageTitle = styled.h1` font-size: 2rem; line-height: 1.3; letter-spacing: 0.1px; color: var(--color-primary); position: relative; font-family: var(--font-tuner); font-style: normal; @media (max-width: 1199px) { margin: 0 0 1.25rem 0 !important; } `; export const DocsNavToggle = styled.div` position: fixed; margin-top: 1.25rem; left: 1rem; z-index: 500; @media (min-width: 999px) { display: none; } `; export default Layout;