1
0
Fork 0
freesewing/sites/shared/components/wrappers/page.mjs

79 lines
2.7 KiB
JavaScript
Raw Normal View History

2023-09-29 16:01:27 +02:00
// __SDEFILE__ - This file is a dependency for the stand-alone environment
2023-03-26 06:50:59 +02:00
// Dependencies
import React, { useState, useEffect, useContext } from 'react'
2023-08-28 14:28:07 +02:00
import { nsMerge } from 'shared/utils.mjs'
2023-09-04 08:40:05 +02:00
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
2023-03-26 06:50:59 +02:00
// Hooks
import { useTheme } from 'shared/hooks/use-theme.mjs'
// Components
import Head from 'next/head'
import { SwipeWrapper } from 'shared/components/wrappers/swipes.mjs'
import { LayoutWrapper, ns as layoutNs } from 'shared/components/wrappers/layout.mjs'
import { DefaultLayout, ns as defaultLayoutNs } from 'site/components/layouts/default.mjs'
2023-03-26 06:50:59 +02:00
import { Feeds } from 'site/components/feeds.mjs'
import { ModalContext } from 'shared/context/modal-context.mjs'
2023-03-26 06:50:59 +02:00
2023-09-04 08:40:05 +02:00
export const ns = nsMerge(layoutNs, defaultLayoutNs, 'status')
2023-03-26 06:50:59 +02:00
/* This component should wrap all page content */
export const PageWrapper = (props) => {
/*
* Deconstruct props
*/
const { layout = DefaultLayout, footer = true, header = true, children = [], path = [] } = props
// Title is typically set in props.t but check props.title too
const pageTitle = props.t ? props.t : props.title ? props.title : null
/*
* Slug should come from page props.path not from context
* which won't be available in SSR
*/
const slug = path.join('/')
/*
* Contexts
*/
const { modalContent } = useContext(ModalContext)
2023-09-04 08:40:05 +02:00
const { LoadingStatus } = useContext(LoadingStatusContext)
2023-03-26 06:50:59 +02:00
/*
* This forces a re-render upon initial bootstrap of the app
* This is needed to avoid hydration errors because theme can't be set reliably in SSR
*/
const { theme } = useTheme()
2023-03-26 06:50:59 +02:00
const [currentTheme, setCurrentTheme] = useState()
useEffect(() => setCurrentTheme(theme), [currentTheme, theme])
2023-03-26 06:50:59 +02:00
// Helper object to pass props down (keeps things DRY)
const childProps = { footer, header, pageTitle, slug }
2023-03-26 06:50:59 +02:00
// Make layout prop into a (uppercase) component
const Layout = layout
// Return wrapper
return (
<SwipeWrapper>
{pageTitle && (
<Head>
<meta property="og:title" content={pageTitle} key="title" />
{props.intro && (
<meta property="og:description" content={props.intro} key="description" />
)}
</Head>
)}
<div
data-theme={currentTheme} // This facilitates CSS selectors
key={currentTheme} // This forces the data-theme update
>
2023-09-04 08:40:05 +02:00
<LoadingStatus />
<Feeds />
<LayoutWrapper {...childProps}>
{Layout ? <Layout {...childProps}>{children}</Layout> : children}
</LayoutWrapper>
{typeof modalContent === 'function' ? modalContent() : modalContent}
</div>
</SwipeWrapper>
2023-03-26 06:50:59 +02:00
)
}