Merge branch 'develop' into eriese-lint-all
This commit is contained in:
commit
6cca85ada0
27 changed files with 448 additions and 462 deletions
|
@ -42,7 +42,7 @@ Now everybody knows this part requires the `head` measurement.
|
||||||
|
|
||||||
This change will also get picked up by the development environment, and you'll now see this screen:
|
This change will also get picked up by the development environment, and you'll now see this screen:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Since it's just one measurement, let's simply enter a value by hand.
|
Since it's just one measurement, let's simply enter a value by hand.
|
||||||
For example `38` as 38cm is a realistic head circumference measurement for a baby.
|
For example `38` as 38cm is a realistic head circumference measurement for a baby.
|
||||||
|
|
|
@ -95,8 +95,6 @@
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"pretty-quick": "^3.0.0",
|
"pretty-quick": "^3.0.0",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react": "^17.0.2",
|
|
||||||
"react-dom": "^17.0.2",
|
|
||||||
"rehype-format": "^4.0.1",
|
"rehype-format": "^4.0.1",
|
||||||
"remark": "^14.0.2",
|
"remark": "^14.0.2",
|
||||||
"remark-frontmatter": "^4.0.1",
|
"remark-frontmatter": "^4.0.1",
|
||||||
|
|
|
@ -12,7 +12,7 @@ const runTests = async (...params) => {
|
||||||
//await apikeyTests(...params)
|
//await apikeyTests(...params)
|
||||||
//await accountTests(...params)
|
//await accountTests(...params)
|
||||||
//await personTests(...params)
|
//await personTests(...params)
|
||||||
await patternTests(...params)
|
//await patternTests(...params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load initial data required for tests
|
// Load initial data required for tests
|
||||||
|
|
|
@ -70,6 +70,7 @@ export const setup = async () => {
|
||||||
console.log('Failed at account confirmation request', err)
|
console.log('Failed at account confirmation request', err)
|
||||||
process.exit()
|
process.exit()
|
||||||
}
|
}
|
||||||
|
console.log(JSON.stringify(result.data, null ,2))
|
||||||
store[acc].token = result.data.token
|
store[acc].token = result.data.token
|
||||||
store[acc].username = result.data.account.username
|
store[acc].username = result.data.account.username
|
||||||
store[acc].id = result.data.account.id
|
store[acc].id = result.data.account.id
|
||||||
|
|
|
@ -107,19 +107,12 @@ const Footer = ({ app }) => {
|
||||||
<div className="lg:col-span-2 -order-2 2xl:order-2 px-4 lg:px-0">
|
<div className="lg:col-span-2 -order-2 2xl:order-2 px-4 lg:px-0">
|
||||||
{/* Social icons */}
|
{/* Social icons */}
|
||||||
<div className="w-full sm:w-auto flex flex-row flex-wrap gap-4 lg:gap-8 items-center justify-center">
|
<div className="w-full sm:w-auto flex flex-row flex-wrap gap-4 lg:gap-8 items-center justify-center">
|
||||||
<Link href="/contact">
|
<Link href="/contact" className="hover:text-secondary hover:-mt-2 transition-all" title="Contact information">
|
||||||
<a
|
|
||||||
className="hover:text-secondary hover:-mt-2 transition-all"
|
|
||||||
title="Contact information"
|
|
||||||
>
|
|
||||||
<HelpIcon {...icon} />
|
<HelpIcon {...icon} />
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
{Object.keys(social).map((item) => (
|
{Object.keys(social).map((item) => (
|
||||||
<Link key={item} href={social[item].href}>
|
<Link key={item} href={social[item].href} className="hover:text-secondary hover:-mt-2 transition-all" title={item}>
|
||||||
<a className="hover:text-secondary hover:-mt-2 transition-all" title={item}>
|
|
||||||
{social[item].icon}
|
{social[item].icon}
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -19,11 +19,7 @@ const DefaultLayout = ({ app, title = false, crumbs = false, children = [] }) =>
|
||||||
slug={slug}
|
slug={slug}
|
||||||
before={[
|
before={[
|
||||||
<div className="flex flex-row items-center justify-between border-b mb-4" key="home-key">
|
<div className="flex flex-row items-center justify-between border-b mb-4" key="home-key">
|
||||||
<Link href="/">
|
<Link href="/"><HomeIcon /></Link>
|
||||||
<a>
|
|
||||||
<HomeIcon />
|
|
||||||
</a>
|
|
||||||
</Link>
|
|
||||||
<ThemePicker app={app} />
|
<ThemePicker app={app} />
|
||||||
</div>,
|
</div>,
|
||||||
]}
|
]}
|
||||||
|
|
|
@ -74,8 +74,8 @@ const SubLevel = ({ nodes = {}, active }) => (
|
||||||
items-center
|
items-center
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<Link href={`${child.__slug}`}>
|
<Link
|
||||||
<a
|
href={`${child.__slug}`}
|
||||||
title={child.__title}
|
title={child.__title}
|
||||||
className={`
|
className={`
|
||||||
grow pl-2 border-l-2
|
grow pl-2 border-l-2
|
||||||
|
@ -105,7 +105,6 @@ const SubLevel = ({ nodes = {}, active }) => (
|
||||||
<span className={child.__slug === active ? 'font-bold' : ''}>
|
<span className={child.__slug === active ? 'font-bold' : ''}>
|
||||||
{child.__linktitle || child.__title}
|
{child.__linktitle || child.__title}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
<Chevron w={6} m={3} />
|
<Chevron w={6} m={3} />
|
||||||
</summary>
|
</summary>
|
||||||
|
@ -114,8 +113,9 @@ const SubLevel = ({ nodes = {}, active }) => (
|
||||||
</li>
|
</li>
|
||||||
) : (
|
) : (
|
||||||
<li className="pl-2 flex flex-row items-center" key={child.__slug}>
|
<li className="pl-2 flex flex-row items-center" key={child.__slug}>
|
||||||
<Link href={`${child.__slug}`} title={child.__title}>
|
<Link
|
||||||
<a
|
href={`${child.__slug}`}
|
||||||
|
title={child.__title}
|
||||||
className={`
|
className={`
|
||||||
pl-2 border-l-2
|
pl-2 border-l-2
|
||||||
grow
|
grow
|
||||||
|
@ -144,7 +144,6 @@ const SubLevel = ({ nodes = {}, active }) => (
|
||||||
<span className={child.__slug === active ? 'font-bold' : ''}>
|
<span className={child.__slug === active ? 'font-bold' : ''}>
|
||||||
{child.__linktitle || child.__title}
|
{child.__linktitle || child.__title}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
|
@ -152,56 +151,6 @@ const SubLevel = ({ nodes = {}, active }) => (
|
||||||
</ul>
|
</ul>
|
||||||
)
|
)
|
||||||
|
|
||||||
// Component that renders a toplevel of navigation
|
|
||||||
/*
|
|
||||||
const TopLevel = ({ icon, title, nav, current, slug, hasChildren=false, active }) => (
|
|
||||||
<details className='py-1' open={0}>
|
|
||||||
<summary className={`
|
|
||||||
flex flex-row uppercase gap-4 font-bold text-lg
|
|
||||||
hover:cursor-row-resize
|
|
||||||
p-2
|
|
||||||
text-base-content
|
|
||||||
sm:text-base-content
|
|
||||||
items-center
|
|
||||||
`}>
|
|
||||||
<span className="text-secondary">{icon}</span>
|
|
||||||
<Link href={`${slug}`}>
|
|
||||||
<a className={`
|
|
||||||
grow ${linkClasses} hover:cursor-pointer
|
|
||||||
${slug === active
|
|
||||||
? 'text-secondary sm:text-secondary'
|
|
||||||
: ''
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</a>
|
|
||||||
</Link>
|
|
||||||
{hasChildren && <Chevron />}
|
|
||||||
</summary>
|
|
||||||
{hasChildren && <SubLevel nodes={current} active={active} />}
|
|
||||||
</details>
|
|
||||||
)
|
|
||||||
|
|
||||||
const Navigation = ({ app, active, className='' }) => {
|
|
||||||
if (!app.navigation) return null
|
|
||||||
const output = []
|
|
||||||
for (const page of order(app.navigation)) output.push(<TopLevel
|
|
||||||
key={page.__slug}
|
|
||||||
icon={icons[page.__slug]
|
|
||||||
? icons[page.__slug]('w-6 h-6')
|
|
||||||
: <span className="text-3xl mr-2 translate-y-3 inline-block p-0 leading-3">°</span>
|
|
||||||
}
|
|
||||||
title={page.__title}
|
|
||||||
slug={page.__slug}
|
|
||||||
hasChildren={1}
|
|
||||||
nav={app.navigation}
|
|
||||||
current={order(app.navigation[page.__slug])}
|
|
||||||
active={active}
|
|
||||||
/>)
|
|
||||||
|
|
||||||
return <div className={`pb-20 ${className}`}>{output}</div>
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
export const Icons = ({
|
export const Icons = ({
|
||||||
app,
|
app,
|
||||||
ulClasses = '',
|
ulClasses = '',
|
||||||
|
@ -215,11 +164,9 @@ export const Icons = ({
|
||||||
for (const page of order(app.navigation)) {
|
for (const page of order(app.navigation)) {
|
||||||
output.push(
|
output.push(
|
||||||
<li key={page.__slug}>
|
<li key={page.__slug}>
|
||||||
<Link href={`${page.__slug}`}>
|
<Link href={`${page.__slug}`} className={linkClasses} title={page.__title} style={linkStyle}>
|
||||||
<a className={linkClasses} title={page.__title} style={linkStyle}>
|
|
||||||
{icons[page.__slug] ? icons[page.__slug]('w-14 h-14') : <HelpIcon />}
|
{icons[page.__slug] ? icons[page.__slug]('w-14 h-14') : <HelpIcon />}
|
||||||
<span className="font-bold">{page.__title}</span>
|
<span className="font-bold">{page.__title}</span>
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
|
@ -227,16 +174,7 @@ export const Icons = ({
|
||||||
|
|
||||||
return <ul className={ulClasses}>{output}</ul>
|
return <ul className={ulClasses}>{output}</ul>
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
const PrimaryMenu = ({ app, active, before=[], after=[] }) => (
|
|
||||||
<nav className="mb-12">
|
|
||||||
{before}
|
|
||||||
<Icons app={app} ulClasses="hidden md:block lg:hidden flex flex-col items-center"/>
|
|
||||||
<Navigation app={app} active={active} className="md:hidden lg:block"/>
|
|
||||||
{after}
|
|
||||||
</nav>
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
export const MainSections = ({ app, active }) => {
|
export const MainSections = ({ app, active }) => {
|
||||||
if (!app.navigation) return null
|
if (!app.navigation) return null
|
||||||
const output = []
|
const output = []
|
||||||
|
@ -268,8 +206,8 @@ export const MainSections = ({ app, active }) => {
|
||||||
{txt}
|
{txt}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<Link href={`${page.__slug}`}>
|
<Link
|
||||||
<a
|
href={`${page.__slug}`}
|
||||||
className={`${linkClasses}
|
className={`${linkClasses}
|
||||||
flex flex-row gap-4 items-center
|
flex flex-row gap-4 items-center
|
||||||
hover:bg-secondary hover:bg-opacity-10
|
hover:bg-secondary hover:bg-opacity-10
|
||||||
|
@ -278,7 +216,6 @@ export const MainSections = ({ app, active }) => {
|
||||||
title={page.__title}
|
title={page.__title}
|
||||||
>
|
>
|
||||||
{txt}
|
{txt}
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -67,8 +67,7 @@ const Hit = (props) => (
|
||||||
${props.index === props.active ? 'bg-secondary bg-opacity-30' : 'bg-base-300 bg-opacity-10'}
|
${props.index === props.active ? 'bg-secondary bg-opacity-30' : 'bg-base-300 bg-opacity-10'}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<Link href={props.hit.page}>
|
<Link href={props.hit.page} className="flex flex-row justify-between gap-2">
|
||||||
<a href={props.hit.page} className="flex flex-row justify-between gap-2">
|
|
||||||
<span className="text-base sm:text-xl font-bold leading-5">
|
<span className="text-base sm:text-xl font-bold leading-5">
|
||||||
{props.hit._highlightResult?.title ? (
|
{props.hit._highlightResult?.title ? (
|
||||||
<CustomHighlight hit={props.hit} attribute="title" />
|
<CustomHighlight hit={props.hit} attribute="title" />
|
||||||
|
@ -79,20 +78,15 @@ const Hit = (props) => (
|
||||||
<span className="text-xs pt-0.5 sm:text-base sm:pt-1 font-bold uppercase">
|
<span className="text-xs pt-0.5 sm:text-base sm:pt-1 font-bold uppercase">
|
||||||
{props.hit.page.split('/')[1]}
|
{props.hit.page.split('/')[1]}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
{props.hit._snippetResult?.body && (
|
{props.hit._snippetResult?.body && (
|
||||||
<Link href={props.hit.page}>
|
<Link href={props.hit.page} className="text-sm sm:text-base block py-1">
|
||||||
<a href={props.hit.page} className="text-sm sm:text-base block py-1">
|
|
||||||
<CustomHighlight hit={props.hit} attribute="body" snippet />
|
<CustomHighlight hit={props.hit} attribute="body" snippet />
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
{props.hit?._highlightResult?.page && (
|
{props.hit?._highlightResult?.page && (
|
||||||
<Link href={props.hit.page}>
|
<Link href={props.hit.page} className="text-xs sm:text-sm block opacity-70">
|
||||||
<a href={props.hit.page} className="text-xs sm:text-sm block opacity-70">
|
|
||||||
<CustomHighlight hit={props.hit} attribute="page" />
|
<CustomHighlight hit={props.hit} attribute="page" />
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -25,21 +25,22 @@
|
||||||
"serve": "pm2 start npm --name 'dev' -- run start"
|
"serve": "pm2 start npm --name 'dev' -- run start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.0.1",
|
"@heroicons/react": "latest",
|
||||||
"@mdx-js/loader": "^2.0.0-rc.2",
|
"@mdx-js/loader": "latest",
|
||||||
"@mdx-js/mdx": "^2.0.0-rc.2",
|
"@mdx-js/mdx": "latest",
|
||||||
"@mdx-js/react": "^2.0.0-rc.2",
|
"@mdx-js/react": "latest",
|
||||||
"@mdx-js/runtime": "next",
|
"@mdx-js/runtime": "latest",
|
||||||
"@next/bundle-analyzer": "^13.0.5",
|
"@next/bundle-analyzer": "^13",
|
||||||
"@tailwindcss/typography": "^0.5.0",
|
"@tailwindcss/typography": "latest",
|
||||||
"algoliasearch": "^4.11.0",
|
"algoliasearch": "^4.11.0",
|
||||||
"daisyui": "^2.0.6",
|
"daisyui": "^2.0.6",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.orderby": "^4.6.0",
|
"lodash.orderby": "^4.6.0",
|
||||||
"lodash.set": "^4.3.2",
|
"lodash.set": "^4.3.2",
|
||||||
"netlify-cli": "^12.0.4",
|
"next": "^13",
|
||||||
"next": "latest",
|
"react": "^18.2.0",
|
||||||
"react-copy-to-clipboard": "^5.0.4",
|
"react-copy-to-clipboard": "^5.0.4",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
"react-hotkeys-hook": "^3.4.4",
|
"react-hotkeys-hook": "^3.4.4",
|
||||||
"react-instantsearch-dom": "^6.18.0",
|
"react-instantsearch-dom": "^6.18.0",
|
||||||
"react-markdown": "^8.0.3",
|
"react-markdown": "^8.0.3",
|
||||||
|
|
|
@ -48,9 +48,9 @@ const PatternPicker = ({ app }) => {
|
||||||
{sectionPatterns(section).map((pattern) => (
|
{sectionPatterns(section).map((pattern) => (
|
||||||
<li key={pattern}>
|
<li key={pattern}>
|
||||||
<Link href={app.navigation[section][pattern].__slug}>
|
<Link href={app.navigation[section][pattern].__slug}>
|
||||||
<a className="capitalize pr-4 text-secondary hover:text-secondary-focus hover:underline">
|
<span className="capitalize pr-4 text-secondary hover:text-secondary-focus hover:underline">
|
||||||
{pattern}
|
{pattern}
|
||||||
</a>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -110,10 +110,13 @@ const Footer = ({ app }) => {
|
||||||
{/* Social icons */}
|
{/* Social icons */}
|
||||||
<div className="w-full sm:w-auto flex flex-row flex-wrap gap-4 lg:gap-8 items-center justify-center">
|
<div className="w-full sm:w-auto flex flex-row flex-wrap gap-4 lg:gap-8 items-center justify-center">
|
||||||
{Object.keys(social).map((item) => (
|
{Object.keys(social).map((item) => (
|
||||||
<Link key={item} href={social[item].href}>
|
<Link
|
||||||
<a className="hover:text-secondary hover:-mt-2 transition-all" title={item}>
|
key={item}
|
||||||
|
href={social[item].href}
|
||||||
|
className="hover:text-secondary hover:-mt-2 transition-all"
|
||||||
|
title={item}
|
||||||
|
>
|
||||||
{social[item].icon}
|
{social[item].icon}
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.orderby": "^4.6.0",
|
"lodash.orderby": "^4.6.0",
|
||||||
"lodash.set": "^4.3.2",
|
"lodash.set": "^4.3.2",
|
||||||
"netlify-cli": "^12.0.4",
|
|
||||||
"next": "latest",
|
"next": "latest",
|
||||||
"next-i18next": "^12.0.0",
|
"next-i18next": "^12.0.0",
|
||||||
"react-copy-to-clipboard": "^5.0.4",
|
"react-copy-to-clipboard": "^5.0.4",
|
||||||
|
|
|
@ -10,14 +10,17 @@ const DesignLinks = ({ list, prefix='' }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className="flex flex-col flex-wrap gap-2">
|
<ul className="flex flex-col flex-wrap gap-2">
|
||||||
{list.map( d => (
|
{list.map((d) => (
|
||||||
<li key={d} className="p-2">
|
<li key={d} className="p-2">
|
||||||
<Link href={`${prefix}/${d}`}>
|
<Link
|
||||||
<a className="capitalize text-xl p-4 font-bold text-secondary hover:text-secondary-focus hover:underline">
|
href={`${prefix}/${d}`}
|
||||||
|
className="capitalize text-xl p-4 font-bold text-secondary hover:text-secondary-focus hover:underline"
|
||||||
|
>
|
||||||
{t(`patterns:${d}.t`)}
|
{t(`patterns:${d}.t`)}
|
||||||
<br />
|
<br />
|
||||||
<span className="text-lg font-normal p-4 text-base-content">{t(`patterns:${d}.d`)}</span>
|
<span className="text-lg font-normal p-4 text-base-content">
|
||||||
</a>
|
{t(`patterns:${d}.d`)}
|
||||||
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
@ -29,9 +32,7 @@ const PatternListPageTemplate = ({ section=false }) => {
|
||||||
const app = useApp()
|
const app = useApp()
|
||||||
const { t } = useTranslation(['app'])
|
const { t } = useTranslation(['app'])
|
||||||
|
|
||||||
const title = section
|
const title = section ? app.navigation[section].__title : t('designs')
|
||||||
? app.navigation[section].__title
|
|
||||||
: t('designs')
|
|
||||||
|
|
||||||
const sectionDesigns = (section = false) => {
|
const sectionDesigns = (section = false) => {
|
||||||
if (!section) {
|
if (!section) {
|
||||||
|
@ -47,7 +48,11 @@ const PatternListPageTemplate = ({ section=false }) => {
|
||||||
<Page app={app} title={`FreeSewing Lab: ${title}`} layout={Layout}>
|
<Page app={app} title={`FreeSewing Lab: ${title}`} layout={Layout}>
|
||||||
<div className="max-w-7xl m-auto py-20 md:py-36 min-h-screen">
|
<div className="max-w-7xl m-auto py-20 md:py-36 min-h-screen">
|
||||||
<section className="px-8">
|
<section className="px-8">
|
||||||
<PageTitle app={app} slug={section ? app.navigation[section].__slug : '/' } title={title} />
|
<PageTitle
|
||||||
|
app={app}
|
||||||
|
slug={section ? app.navigation[section].__slug : '/'}
|
||||||
|
title={title}
|
||||||
|
/>
|
||||||
<DesignLinks list={sectionDesigns(section)} />
|
<DesignLinks list={sectionDesigns(section)} />
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
@ -56,5 +61,3 @@ const PatternListPageTemplate = ({ section=false }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PatternListPageTemplate
|
export default PatternListPageTemplate
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.orderby": "^4.6.0",
|
"lodash.orderby": "^4.6.0",
|
||||||
"lodash.set": "^4.3.2",
|
"lodash.set": "^4.3.2",
|
||||||
"netlify-cli": "^12.0.4",
|
|
||||||
"next": "latest",
|
"next": "latest",
|
||||||
"react-hotkeys-hook": "^3.4.4",
|
"react-hotkeys-hook": "^3.4.4",
|
||||||
"react-instantsearch-dom": "^6.18.0",
|
"react-instantsearch-dom": "^6.18.0",
|
||||||
|
|
|
@ -6,10 +6,8 @@ const Breadcrumbs = ({ crumbs = [], title }) =>
|
||||||
crumbs ? (
|
crumbs ? (
|
||||||
<ul className="flex flex-row flex-wrap gap-2 font-bold">
|
<ul className="flex flex-row flex-wrap gap-2 font-bold">
|
||||||
<li>
|
<li>
|
||||||
<Link href="/">
|
<Link href="/" title="FreeSewing" className="text-base-content">
|
||||||
<a title="FreeSewing" className="text-base-content">
|
|
||||||
<FreeSewingIcon />
|
<FreeSewingIcon />
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
{crumbs.map((crumb) => (
|
{crumbs.map((crumb) => (
|
||||||
|
@ -17,10 +15,12 @@ const Breadcrumbs = ({ crumbs = [], title }) =>
|
||||||
<li className="text-base-content px-2">»</li>
|
<li className="text-base-content px-2">»</li>
|
||||||
<li>
|
<li>
|
||||||
{crumb[1] ? (
|
{crumb[1] ? (
|
||||||
<Link href={crumb[1]}>
|
<Link
|
||||||
<a title={crumb[0]} className="text-secondary hover:text-secondary-focus">
|
href={crumb[1]}
|
||||||
|
title={crumb[0]}
|
||||||
|
className="text-secondary hover:text-secondary-focus"
|
||||||
|
>
|
||||||
{crumb[0]}
|
{crumb[0]}
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-base-content">{crumb[0]}</span>
|
<span className="text-base-content">{crumb[0]}</span>
|
||||||
|
|
|
@ -27,32 +27,31 @@ const Breadcrumbs = ({ app, slug=false, title }) => {
|
||||||
for (const i in chunks) {
|
for (const i in chunks) {
|
||||||
const j = parseInt(i) + parseInt(1)
|
const j = parseInt(i) + parseInt(1)
|
||||||
const page = get(app.navigation, chunks.slice(0, j))
|
const page = get(app.navigation, chunks.slice(0, j))
|
||||||
if (page) crumbs.push([page.__linktitle, '/'+chunks.slice(0,j).join('/'), (j < chunks.length)])
|
if (page) crumbs.push([page.__linktitle, '/' + chunks.slice(0, j).join('/'), j < chunks.length])
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className="flex flex-row flex-wrap gap-2 font-bold">
|
<ul className="flex flex-row flex-wrap gap-2 font-bold">
|
||||||
<li>
|
<li>
|
||||||
<Link href="/">
|
<Link href="/" title="To the homepage" className="text-base-content">
|
||||||
<a title="To the homepage" className="text-base-content">
|
|
||||||
<Logo size={24} fill="currentColor" stroke={false} />
|
<Logo size={24} fill="currentColor" stroke={false} />
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
{crumbs.map(crumb => (
|
{crumbs.map((crumb) => (
|
||||||
<React.Fragment key={crumb[1]}>
|
<React.Fragment key={crumb[1]}>
|
||||||
<li className="text-base-content">»</li>
|
<li className="text-base-content">»</li>
|
||||||
<li>
|
<li>
|
||||||
{crumb[2]
|
{crumb[2] ? (
|
||||||
? (
|
<Link
|
||||||
<Link href={crumb[1]}>
|
href={crumb[1]}
|
||||||
<a title={crumb[0]} className="text-secondary hover:text-secondary-focus">
|
title={crumb[0]}
|
||||||
|
className="text-secondary hover:text-secondary-focus"
|
||||||
|
>
|
||||||
{crumb[0]}
|
{crumb[0]}
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
)
|
) : (
|
||||||
: <span className="text-base-content">{crumb[0]}</span>
|
<span className="text-base-content">{crumb[0]}</span>
|
||||||
}
|
)}
|
||||||
</li>
|
</li>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
|
@ -78,7 +77,6 @@ const asideClasses = `
|
||||||
xl:w-1/4
|
xl:w-1/4
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
||||||
const DefaultLayout = ({
|
const DefaultLayout = ({
|
||||||
app,
|
app,
|
||||||
title = false,
|
title = false,
|
||||||
|
@ -105,35 +103,44 @@ const DefaultLayout = ({
|
||||||
const [collapseAltMenu, setCollapseAltMenu] = useState(false)
|
const [collapseAltMenu, setCollapseAltMenu] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`
|
<div
|
||||||
|
className={`
|
||||||
flex flex-col justify-between
|
flex flex-col justify-between
|
||||||
min-h-screen
|
min-h-screen
|
||||||
bg-base-100
|
bg-base-100
|
||||||
`}>
|
`}
|
||||||
|
>
|
||||||
<Header app={app} setSearch={setSearch} />
|
<Header app={app} setSearch={setSearch} />
|
||||||
<main className="grow bg-base-100">
|
<main className="grow bg-base-100">
|
||||||
<div className="m-auto flex flex-row justify-center">
|
<div className="m-auto flex flex-row justify-center">
|
||||||
|
<aside
|
||||||
<aside className={`
|
className={`
|
||||||
${asideClasses}
|
${asideClasses}
|
||||||
${app.primaryMenu ? '' : 'translate-x-[-100%]'} transition-transform
|
${app.primaryMenu ? '' : 'translate-x-[-100%]'} transition-transform
|
||||||
sm:flex-row-reverse
|
sm:flex-row-reverse
|
||||||
${workbench && collapsePrimaryNav
|
${workbench && collapsePrimaryNav ? 'sm:px-0 sm:w-16' : 'sm:px-1 md:px-4 lg:px-8'}
|
||||||
? 'sm:px-0 sm:w-16'
|
|
||||||
: 'sm:px-1 md:px-4 lg:px-8'
|
|
||||||
}
|
|
||||||
w-96
|
w-96
|
||||||
`}>
|
`}
|
||||||
|
>
|
||||||
{workbench && (
|
{workbench && (
|
||||||
<div className={`hidden sm:flex`}>
|
<div className={`hidden sm:flex`}>
|
||||||
<button
|
<button
|
||||||
className="text-secondary-focus h-full px-2 pl-4 hover:animate-pulse"
|
className="text-secondary-focus h-full px-2 pl-4 hover:animate-pulse"
|
||||||
onClick={() => setCollapsePrimaryNav(!collapsePrimaryNav)}
|
onClick={() => setCollapsePrimaryNav(!collapsePrimaryNav)}
|
||||||
>
|
>
|
||||||
{collapsePrimaryNav
|
{collapsePrimaryNav ? (
|
||||||
? <><Right /><Right /><Right /></>
|
<>
|
||||||
: <><Left /><Left /><Left /></>
|
<Right />
|
||||||
}
|
<Right />
|
||||||
|
<Right />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Left />
|
||||||
|
<Left />
|
||||||
|
<Left />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -141,14 +148,13 @@ const DefaultLayout = ({
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<div className="p-0 m-0 bg-base-100">
|
<div className="p-0 m-0 bg-base-100">
|
||||||
<section className={`
|
<section
|
||||||
|
className={`
|
||||||
p-4 pt-24 sm:pt-28
|
p-4 pt-24 sm:pt-28
|
||||||
sm:px-1 md:px-4 lg:px-8
|
sm:px-1 md:px-4 lg:px-8
|
||||||
${workbench && collapsePrimaryNav
|
${workbench && collapsePrimaryNav ? '' : 'max-w-7xl'}
|
||||||
? ''
|
`}
|
||||||
: 'max-w-7xl'
|
>
|
||||||
}
|
|
||||||
`}>
|
|
||||||
<div>
|
<div>
|
||||||
{title && (
|
{title && (
|
||||||
<>
|
<>
|
||||||
|
@ -160,28 +166,35 @@ const DefaultLayout = ({
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{workbench && AltMenu && (
|
{workbench && AltMenu && (
|
||||||
<aside className={`
|
<aside
|
||||||
|
className={`
|
||||||
${asideClasses}
|
${asideClasses}
|
||||||
${app.primaryMenu ? '' : 'translate-x-[-100%]'} transition-transform
|
${app.primaryMenu ? '' : 'translate-x-[-100%]'} transition-transform
|
||||||
sm:flex-row
|
sm:flex-row
|
||||||
${collapseAltMenu
|
${collapseAltMenu ? 'sm:px-0 sm:w-16' : 'sm:px-1 md:px-4 lg:px-8 sm:w-[38.2%]'}
|
||||||
? 'sm:px-0 sm:w-16'
|
`}
|
||||||
: 'sm:px-1 md:px-4 lg:px-8 sm:w-[38.2%]'
|
>
|
||||||
}
|
|
||||||
`}>
|
|
||||||
<div className={`hidden sm:flex`}>
|
<div className={`hidden sm:flex`}>
|
||||||
<button
|
<button
|
||||||
className="text-secondary-focus h-full px-2 pr-4 hover:animate-pulse"
|
className="text-secondary-focus h-full px-2 pr-4 hover:animate-pulse"
|
||||||
onClick={() => setCollapseAltMenu(!collapseAltMenu)}
|
onClick={() => setCollapseAltMenu(!collapseAltMenu)}
|
||||||
>
|
>
|
||||||
{collapseAltMenu
|
{collapseAltMenu ? (
|
||||||
? <><Left /><Left /><Left /></>
|
<>
|
||||||
: <><Right /><Right /><Right /></>
|
<Left />
|
||||||
}
|
<Left />
|
||||||
|
<Left />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Right />
|
||||||
|
<Right />
|
||||||
|
<Right />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{AltMenu}
|
{AltMenu}
|
||||||
|
@ -190,13 +203,15 @@ const DefaultLayout = ({
|
||||||
</main>
|
</main>
|
||||||
{!noSearch && search && (
|
{!noSearch && search && (
|
||||||
<>
|
<>
|
||||||
<div className={`
|
<div
|
||||||
|
className={`
|
||||||
fixed w-full max-h-screen bg-base-100 top-0 z-30 pt-0 pb-16 px-8
|
fixed w-full max-h-screen bg-base-100 top-0 z-30 pt-0 pb-16 px-8
|
||||||
sm:rounded-lg sm:top-24
|
sm:rounded-lg sm:top-24
|
||||||
sm:max-w-xl sm:m-auto sm:inset-x-12
|
sm:max-w-xl sm:m-auto sm:inset-x-12
|
||||||
md:max-w-2xl
|
md:max-w-2xl
|
||||||
lg:max-w-4xl
|
lg:max-w-4xl
|
||||||
`}>
|
`}
|
||||||
|
>
|
||||||
<Search app={app} search={search} setSearch={setSearch} />
|
<Search app={app} search={search} setSearch={setSearch} />
|
||||||
</div>
|
</div>
|
||||||
<div className="fixed top-0 left-0 w-full min-h-screen bg-neutral z-20 bg-opacity-70"></div>
|
<div className="fixed top-0 left-0 w-full min-h-screen bg-neutral z-20 bg-opacity-70"></div>
|
||||||
|
|
|
@ -48,8 +48,12 @@ const LocalePicker = ({ app, iconOnly = false, bottom = false }) => {
|
||||||
<div className="overflow-hidden rounded-lg shadow-lg">
|
<div className="overflow-hidden rounded-lg shadow-lg">
|
||||||
<div className="relative grid gap-2 bg-base-100 p-4 grid-cols-1">
|
<div className="relative grid gap-2 bg-base-100 p-4 grid-cols-1">
|
||||||
{router.locales.map((locale) => (
|
{router.locales.map((locale) => (
|
||||||
<Link href={`${locale}/${router.asPath}`} key={locale}>
|
<Link
|
||||||
<a className="btn btn-primary">{t(locale)}</a>
|
href={`${locale}/${router.asPath}`}
|
||||||
|
key={locale}
|
||||||
|
className="btn btn-primary"
|
||||||
|
>
|
||||||
|
{t(locale)}
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -76,8 +76,8 @@ const renderPrevious = (node) =>
|
||||||
node ? (
|
node ? (
|
||||||
<div className="flex flex-row gap-2 items-center">
|
<div className="flex flex-row gap-2 items-center">
|
||||||
<LeftIcon className="w-6 h-6" />
|
<LeftIcon className="w-6 h-6" />
|
||||||
<Link href={'/' + node.__slug}>
|
<Link href={'/' + node.__slug} className="text-secondary break-words">
|
||||||
<a className="text-secondary break-words">{node.__linktitle}</a>
|
{node.__linktitle}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
@ -87,8 +87,8 @@ const renderPrevious = (node) =>
|
||||||
const renderNext = (node) =>
|
const renderNext = (node) =>
|
||||||
node ? (
|
node ? (
|
||||||
<div className="flex flex-row gap-2 items-center justify-end">
|
<div className="flex flex-row gap-2 items-center justify-end">
|
||||||
<Link href={'/' + node.__slug}>
|
<Link href={'/' + node.__slug} className="text-right break-words">
|
||||||
<a className="text-right break-words">{node.__linktitle}</a>
|
{node.__linktitle}
|
||||||
</Link>
|
</Link>
|
||||||
<RightIcon className="w-6 h-6" />
|
<RightIcon className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,26 +3,30 @@ import orderBy from 'lodash.orderby'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
||||||
// Helper method to filter out the real children
|
// Helper method to filter out the real children
|
||||||
const order = obj => orderBy(obj, ['__order', '__title'], ['asc', 'asc'])
|
const order = (obj) => orderBy(obj, ['__order', '__title'], ['asc', 'asc'])
|
||||||
const currentChildren = current => Object.values(order(current))
|
const currentChildren = (current) =>
|
||||||
.filter(entry => (typeof entry === 'object'))
|
Object.values(order(current)).filter((entry) => typeof entry === 'object')
|
||||||
|
|
||||||
const ReadMore = props => {
|
const ReadMore = (props) => {
|
||||||
// Don't bother if we don't have the navigation tree in app
|
// Don't bother if we don't have the navigation tree in app
|
||||||
if (!props.app) return null
|
if (!props.app) return null
|
||||||
|
|
||||||
const root = get(props.app.navigation, props.slug.split('/'))
|
const root = get(props.app.navigation, props.slug.split('/'))
|
||||||
const list = []
|
const list = []
|
||||||
for (const page of currentChildren(root)) {
|
for (const page of currentChildren(root)) {
|
||||||
list.push(<li key={page.__slug} className={props.recurse ? 'ont-bold' : ''}>
|
list.push(
|
||||||
<Link href={`/${page.__slug}`}>
|
<li key={page.__slug} className={props.recurse ? 'ont-bold' : ''}>
|
||||||
<a className={props.recurse ? 'inline-block font-bold pt-3 pb-1' : ''}>{page.__title}</a>
|
<Link
|
||||||
|
href={`/${page.__slug}`}
|
||||||
|
className={props.recurse ? 'inline-block font-bold pt-3 pb-1' : ''}
|
||||||
|
>
|
||||||
|
{page.__title}
|
||||||
</Link>
|
</Link>
|
||||||
{props.recurse && <ReadMore app={props.app} slug={page.__slug} />}
|
{props.recurse && <ReadMore app={props.app} slug={page.__slug} />}
|
||||||
</li>)
|
</li>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return <ul>{list}</ul>
|
return <ul>{list}</ul>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ReadMore
|
export default ReadMore
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import CommunityIcon from 'shared/components/icons/community.js'
|
||||||
import ShowcaseIcon from 'shared/components/icons/camera.js'
|
import ShowcaseIcon from 'shared/components/icons/camera.js'
|
||||||
|
|
||||||
// Don't show children for blog and showcase posts
|
// Don't show children for blog and showcase posts
|
||||||
const keepClosed = ['blog', 'showcase', ]
|
const keepClosed = ['blog', 'showcase']
|
||||||
|
|
||||||
// List of icons matched to top-level slug
|
// List of icons matched to top-level slug
|
||||||
const icons = {
|
const icons = {
|
||||||
|
@ -34,21 +34,26 @@ const icons = {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* helper method to order nav entries */
|
/* helper method to order nav entries */
|
||||||
const order = obj => orderBy(obj, ['__order', '__title'], ['asc', 'asc'])
|
const order = (obj) => orderBy(obj, ['__order', '__title'], ['asc', 'asc'])
|
||||||
|
|
||||||
// Component for the collapse toggle
|
// Component for the collapse toggle
|
||||||
// Exported for re-use
|
// Exported for re-use
|
||||||
export const Chevron = ({w=8, m=2}) => <svg className={`
|
export const Chevron = ({ w = 8, m = 2 }) => (
|
||||||
|
<svg
|
||||||
|
className={`
|
||||||
fill-current opacity-75 w-${w} h-${w} mr-${m}
|
fill-current opacity-75 w-${w} h-${w} mr-${m}
|
||||||
details-toggle hover:text-secondary sm:hover:text-secondary
|
details-toggle hover:text-secondary sm:hover:text-secondary
|
||||||
`}
|
`}
|
||||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
<path d="M12.95 10.707l.707-.707L8 4.343 6.586 5.757 10.828 10l-4.242 4.243L8 15.657l4.95-4.95z" />
|
<path d="M12.95 10.707l.707-.707L8 4.343 6.586 5.757 10.828 10l-4.242 4.243L8 15.657l4.95-4.95z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
// Helper method to filter out the real children
|
// Helper method to filter out the real children
|
||||||
const currentChildren = current => Object.values(order(current))
|
const currentChildren = (current) =>
|
||||||
.filter(entry => (typeof entry === 'object'))
|
Object.values(order(current)).filter((entry) => typeof entry === 'object')
|
||||||
|
|
||||||
// Shared classes for links
|
// Shared classes for links
|
||||||
// Exported for re-use
|
// Exported for re-use
|
||||||
|
@ -75,43 +80,52 @@ const isActive = (slug, active) => {
|
||||||
// Component that renders a sublevel of navigation
|
// Component that renders a sublevel of navigation
|
||||||
const SubLevel = ({ nodes = {}, active }) => (
|
const SubLevel = ({ nodes = {}, active }) => (
|
||||||
<ul className="pl-5 list-inside">
|
<ul className="pl-5 list-inside">
|
||||||
{currentChildren(nodes).map(child => (Object.keys(child).length > 4)
|
{currentChildren(nodes).map((child) =>
|
||||||
? (
|
Object.keys(child).length > 4 ? (
|
||||||
<li key={child.__slug} className="flex flex-row">
|
<li key={child.__slug} className="flex flex-row">
|
||||||
<details className="grow" open={isActive(child.__slug, active)}>
|
<details className="grow" open={isActive(child.__slug, active)}>
|
||||||
<summary className={`
|
<summary
|
||||||
|
className={`
|
||||||
flex flex-row
|
flex flex-row
|
||||||
px-2
|
px-2
|
||||||
text-base-content
|
text-base-content
|
||||||
sm:text-base-content
|
sm:text-base-content
|
||||||
hover:cursor-row-resize
|
hover:cursor-row-resize
|
||||||
items-center
|
items-center
|
||||||
`}>
|
`}
|
||||||
<Link href={`${child.__slug}`}>
|
>
|
||||||
<a title={child.__title} className={`
|
<Link
|
||||||
|
href={`${child.__slug}`}
|
||||||
|
title={child.__title}
|
||||||
|
className={`
|
||||||
grow pl-2 border-l-2
|
grow pl-2 border-l-2
|
||||||
${linkClasses}
|
|
||||||
hover:cursor-pointer
|
hover:cursor-pointer
|
||||||
hover:border-secondary
|
hover:border-secondary
|
||||||
sm:hover:border-secondary
|
sm:hover:border-secondary
|
||||||
${child.__slug === active
|
${
|
||||||
|
child.__slug === active
|
||||||
? 'text-secondary border-secondary sm:text-secondary sm:border-secondary'
|
? 'text-secondary border-secondary sm:text-secondary sm:border-secondary'
|
||||||
: 'text-base-content sm:text-base-content'
|
: 'text-base-content sm:text-base-content'
|
||||||
}
|
}
|
||||||
`}>
|
`}
|
||||||
<span className={`
|
>
|
||||||
|
<span className={linkClasses}>
|
||||||
|
<span
|
||||||
|
className={`
|
||||||
text-3xl mr-2 inline-block p-0 leading-3
|
text-3xl mr-2 inline-block p-0 leading-3
|
||||||
${child.__slug === active
|
${
|
||||||
|
child.__slug === active
|
||||||
? 'text-secondary sm:text-secondary translate-y-1'
|
? 'text-secondary sm:text-secondary translate-y-1'
|
||||||
: 'translate-y-3'
|
: 'translate-y-3'
|
||||||
}
|
}
|
||||||
`}>
|
`}
|
||||||
|
>
|
||||||
{child.__slug === active ? <>•</> : <>°</>}
|
{child.__slug === active ? <>•</> : <>°</>}
|
||||||
</span>
|
</span>
|
||||||
<span className={child.__slug === active ? 'font-bold' : ''}>
|
<span className={child.__slug === active ? 'font-bold' : ''}>
|
||||||
{child.__linktitle || child.__title}
|
{child.__linktitle || child.__title}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
<Chevron w={6} m={3} />
|
<Chevron w={6} m={3} />
|
||||||
</summary>
|
</summary>
|
||||||
|
@ -119,62 +133,67 @@ const SubLevel = ({ nodes={}, active }) => (
|
||||||
</details>
|
</details>
|
||||||
</li>
|
</li>
|
||||||
) : (
|
) : (
|
||||||
<li className='pl-2 flex flex-row items-center' key={child.__slug}>
|
<li className="pl-2 flex flex-row items-center" key={child.__slug}>
|
||||||
<Link href={`${child.__slug}`} title={child.__title}>
|
<Link
|
||||||
<a className={`
|
href={`${child.__slug}`}
|
||||||
|
title={child.__title}
|
||||||
|
className={`
|
||||||
pl-2 border-l-2
|
pl-2 border-l-2
|
||||||
grow
|
grow
|
||||||
${linkClasses}
|
|
||||||
hover:cursor-pointer
|
hover:cursor-pointer
|
||||||
hover:border-secondary
|
hover:border-secondary
|
||||||
sm:hover:border-secondary
|
sm:hover:border-secondary
|
||||||
${child.__slug === active
|
${
|
||||||
|
child.__slug === active
|
||||||
? 'text-secondary border-secondary sm:text-secondary sm:border-secondary'
|
? 'text-secondary border-secondary sm:text-secondary sm:border-secondary'
|
||||||
: 'text-base-content sm:text-base-content'
|
: 'text-base-content sm:text-base-content'
|
||||||
}`}>
|
}`}
|
||||||
<span className={`
|
>
|
||||||
|
<span className={linkClasses}>
|
||||||
|
<span
|
||||||
|
className={`
|
||||||
text-3xl mr-2 inline-block p-0 leading-3
|
text-3xl mr-2 inline-block p-0 leading-3
|
||||||
${child.__slug === active
|
${
|
||||||
|
child.__slug === active
|
||||||
? 'text-secondary sm:text-secondary translate-y-1'
|
? 'text-secondary sm:text-secondary translate-y-1'
|
||||||
: 'translate-y-3'
|
: 'translate-y-3'
|
||||||
}
|
}
|
||||||
`}>
|
`}
|
||||||
|
>
|
||||||
{child.__slug === active ? <>•</> : <>°</>}
|
{child.__slug === active ? <>•</> : <>°</>}
|
||||||
</span>
|
</span>
|
||||||
<span className={child.__slug === active ? 'font-bold' : ''}>
|
<span className={child.__slug === active ? 'font-bold' : ''}>
|
||||||
{child.__linktitle || child.__title}
|
{child.__linktitle || child.__title}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
|
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
)
|
)
|
||||||
|
|
||||||
// Component that renders a toplevel of navigation
|
// Component that renders a toplevel of navigation
|
||||||
const TopLevel = ({ icon, title, nav, current, slug, hasChildren = false, active }) => (
|
const TopLevel = ({ icon, title, nav, current, slug, hasChildren = false, active }) => (
|
||||||
<details className='py-1' open={((keepClosed.indexOf(current.__slug) === -1) ? 1 : 0)}>
|
<details className="py-1" open={keepClosed.indexOf(current.__slug) === -1 ? 1 : 0}>
|
||||||
<summary className={`
|
<summary
|
||||||
|
className={`
|
||||||
flex flex-row uppercase gap-4 font-bold text-lg
|
flex flex-row uppercase gap-4 font-bold text-lg
|
||||||
hover:cursor-row-resize
|
hover:cursor-row-resize
|
||||||
p-2
|
p-2
|
||||||
text-base-content
|
text-base-content
|
||||||
sm:text-base-content
|
sm:text-base-content
|
||||||
items-center
|
items-center
|
||||||
`}>
|
`}
|
||||||
|
>
|
||||||
<span className="text-secondary">{icon}</span>
|
<span className="text-secondary">{icon}</span>
|
||||||
<Link href={`${slug}`}>
|
<Link
|
||||||
<a className={`
|
href={`${slug}`}
|
||||||
|
className={`
|
||||||
grow ${linkClasses} hover:cursor-pointer
|
grow ${linkClasses} hover:cursor-pointer
|
||||||
${slug === active
|
${slug === active ? 'text-secondary sm:text-secondary' : ''}`}
|
||||||
? 'text-secondary sm:text-secondary'
|
|
||||||
: ''
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
{hasChildren && <Chevron />}
|
{hasChildren && <Chevron />}
|
||||||
</summary>
|
</summary>
|
||||||
|
@ -185,11 +204,16 @@ const TopLevel = ({ icon, title, nav, current, slug, hasChildren=false, active }
|
||||||
const Navigation = ({ app, active, className = '' }) => {
|
const Navigation = ({ app, active, className = '' }) => {
|
||||||
if (!app.navigation) return null
|
if (!app.navigation) return null
|
||||||
const output = []
|
const output = []
|
||||||
for (const page of order(app.navigation)) output.push(<TopLevel
|
for (const page of order(app.navigation))
|
||||||
|
output.push(
|
||||||
|
<TopLevel
|
||||||
key={page.__slug}
|
key={page.__slug}
|
||||||
icon={icons[page.__slug]
|
icon={
|
||||||
? icons[page.__slug]('w-6 h-6')
|
icons[page.__slug] ? (
|
||||||
: <span className="text-3xl mr-2 translate-y-3 inline-block p-0 leading-3">°</span>
|
icons[page.__slug]('w-6 h-6')
|
||||||
|
) : (
|
||||||
|
<span className="text-3xl mr-2 translate-y-3 inline-block p-0 leading-3">°</span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
title={page.__title}
|
title={page.__title}
|
||||||
slug={page.__slug}
|
slug={page.__slug}
|
||||||
|
@ -197,33 +221,32 @@ const Navigation = ({ app, active, className='' }) => {
|
||||||
nav={app.navigation}
|
nav={app.navigation}
|
||||||
current={order(app.navigation[page.__slug])}
|
current={order(app.navigation[page.__slug])}
|
||||||
active={active}
|
active={active}
|
||||||
/>)
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
return <div className={`pb-20 ${className}`}>{output}</div>
|
return <div className={`pb-20 ${className}`}>{output}</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Icons = ({
|
export const Icons = ({
|
||||||
app, active,
|
app,
|
||||||
|
active,
|
||||||
ulClasses = '',
|
ulClasses = '',
|
||||||
liClasses = '',
|
liClasses = '',
|
||||||
linkClasses = `grow text-lg lg:text-xl py-1 text-base-content sm:text-base-content
|
linkClasses = `grow text-lg lg:text-xl py-1 text-base-content sm:text-base-content
|
||||||
hover:text-secondary sm:hover:text-secondary hover:cursor-pointer
|
hover:text-secondary sm:hover:text-secondary hover:cursor-pointer
|
||||||
flex flex-col items-center`,
|
flex flex-col items-center`,
|
||||||
linkStyle={}
|
linkStyle = {},
|
||||||
}) => {
|
}) => {
|
||||||
if (!app.navigation) return null
|
if (!app.navigation) return null
|
||||||
const output = []
|
const output = []
|
||||||
for (const page of order(app.navigation)) {
|
for (const page of order(app.navigation)) {
|
||||||
output.push(
|
output.push(
|
||||||
<li key={page.__slug} className={liClasses}>
|
<li key={page.__slug} className={liClasses}>
|
||||||
<Link href={`${page.__slug}`}>
|
<Link href={`${page.__slug}`} title={page.__title} style={linkStyle}>
|
||||||
<a className={linkClasses} title={page.__title} style={linkStyle}>
|
<span className={linkClasses}>
|
||||||
{icons[page.__slug]
|
{icons[page.__slug] ? icons[page.__slug]('w-14 h-14') : <HelpIcon />}
|
||||||
? icons[page.__slug]('w-14 h-14')
|
<span className="font-bold">{page.__title}</span>
|
||||||
: <HelpIcon />
|
</span>
|
||||||
}
|
|
||||||
<span className='font-bold'>{page.__title}</span>
|
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
||||||
const PageLink = ({ href, txt, className="" }) => (
|
const PageLink = ({ href, txt, className = '' }) => (
|
||||||
<Link href={href}>
|
<Link
|
||||||
<a className={`font-bold text-secondary
|
href={href}
|
||||||
hover:text-secondary-focus hover:underline ${className}`}
|
className={`font-bold text-secondary hover:text-secondary-focus hover:underline ${className}`}
|
||||||
title={txt}>{txt}</a>
|
title={txt}
|
||||||
|
>
|
||||||
|
{txt}
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default PageLink
|
export default PageLink
|
||||||
|
|
||||||
|
|
|
@ -4,25 +4,35 @@ import Link from 'next/link'
|
||||||
|
|
||||||
/** an accessible dropdown menu for use by picker components */
|
/** an accessible dropdown menu for use by picker components */
|
||||||
export const Picker = ({ Icon, className, title, ariaLabel, iconOnly = false, children, end }) => {
|
export const Picker = ({ Icon, className, title, ariaLabel, iconOnly = false, children, end }) => {
|
||||||
|
return (
|
||||||
return (<Menu as="div" className={`w-auto relative`}>
|
<Menu as="div" className={`w-auto relative`}>
|
||||||
<Menu.Button className={iconOnly
|
<Menu.Button
|
||||||
|
className={
|
||||||
|
iconOnly
|
||||||
? `btn btn-sm`
|
? `btn btn-sm`
|
||||||
: `m-0 btn btn-neutral flex flex-row gap-2
|
: `m-0 btn btn-neutral flex flex-row gap-2
|
||||||
hover:bg-neutral-focus
|
hover:bg-neutral-focus
|
||||||
`}
|
`
|
||||||
aria-label={ariaLabel}>
|
}
|
||||||
|
aria-label={ariaLabel}
|
||||||
|
>
|
||||||
<Icon />
|
<Icon />
|
||||||
{!iconOnly && <span>{title}</span>}
|
{!iconOnly && <span>{title}</span>}
|
||||||
</Menu.Button>
|
</Menu.Button>
|
||||||
<Menu.Items as="ul" className={`p-2 shadow menu bg-base-100 rounded-box w-52 ${className} absolute ${end ? 'right-0' : 'left-0'} top-full mt-1`}>
|
<Menu.Items
|
||||||
|
as="ul"
|
||||||
|
className={`p-2 shadow menu bg-base-100 rounded-box w-52 ${className} absolute ${
|
||||||
|
end ? 'right-0' : 'left-0'
|
||||||
|
} top-full mt-1`}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</Menu.Items>
|
</Menu.Items>
|
||||||
</Menu>)
|
</Menu>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** get the menu item's class based on whether it's active */
|
/** get the menu item's class based on whether it's active */
|
||||||
const itemClass = (active) => "btn btn-ghost " + (active ? 'bg-base-200' : '')
|
const itemClass = (active) => 'btn btn-ghost ' + (active ? 'bg-base-200' : '')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a menu item that has a link in it
|
* a menu item that has a link in it
|
||||||
|
@ -32,34 +42,39 @@ const itemClass = (active) => "btn btn-ghost " + (active ? 'bg-base-200' : '')
|
||||||
** locale?: the locale the link links to
|
** locale?: the locale the link links to
|
||||||
* */
|
* */
|
||||||
export const PickerLink = (props) => {
|
export const PickerLink = (props) => {
|
||||||
return (<li role="menuitem">
|
return (
|
||||||
|
<li role="menuitem">
|
||||||
<Menu.Item>
|
<Menu.Item>
|
||||||
{({active}) => (<ForwardLink active={active} {...props}></ForwardLink>)}
|
{({ active }) => <ForwardLink active={active} {...props}></ForwardLink>}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</li>)
|
</li>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Necessary to have keyboard enter 'click' events passed to the link */
|
* Necessary to have keyboard enter 'click' events passed to the link */
|
||||||
const ForwardLink = forwardRef(({ href, locale, active, children, ...rest }, ref) => (
|
const ForwardLink = forwardRef(({ href, locale, active, children, ...rest }, ref) => (
|
||||||
<Link href={href} locale={locale}>
|
<Link
|
||||||
<a className={itemClass(active)} {...rest} role={undefined} ref={ref}>
|
href={href}
|
||||||
<span className="text-base-content">
|
locale={locale}
|
||||||
{children}
|
className={itemClass(active)}
|
||||||
</span>
|
{...rest}
|
||||||
</a>
|
role={undefined}
|
||||||
|
ref={ref}
|
||||||
|
>
|
||||||
|
<span className="text-base-content">{children}</span>
|
||||||
</Link>
|
</Link>
|
||||||
))
|
))
|
||||||
|
|
||||||
/** a menu item that is a button */
|
/** a menu item that is a button */
|
||||||
export const PickerButton = ({ onClick, children }) => {
|
export const PickerButton = ({ onClick, children }) => {
|
||||||
return (<Menu.Item as="li" onClick={onClick}>
|
return (
|
||||||
|
<Menu.Item as="li" onClick={onClick}>
|
||||||
{({ active }) => (
|
{({ active }) => (
|
||||||
<button className={itemClass(active)}>
|
<button className={itemClass(active)}>
|
||||||
<span className="text-base-content">
|
<span className="text-base-content">{children}</span>
|
||||||
{children}
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</Menu.Item>)
|
</Menu.Item>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,11 @@ export const InnerWordMark = () => (
|
||||||
)
|
)
|
||||||
|
|
||||||
export const WordMark = () => (
|
export const WordMark = () => (
|
||||||
<Link href="/">
|
<Link
|
||||||
<a
|
href="/"
|
||||||
role="button"
|
role="button"
|
||||||
className="btn btn-ghost btn-sm normal-case text-2xl hover:bg-transparent font-bold px-0 -mt-1"
|
className="btn btn-ghost btn-sm normal-case text-2xl hover:bg-transparent font-bold px-0 -mt-1"
|
||||||
>
|
>
|
||||||
<InnerWordMark />
|
<InnerWordMark />
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
|
|
|
@ -25,7 +25,7 @@ const PreviewTile = ({ img, slug, title, href=false, fixed=false }) => (
|
||||||
>
|
>
|
||||||
{href
|
{href
|
||||||
? <a href={href} title={title} className={linkClasses(fixed)}/>
|
? <a href={href} title={title} className={linkClasses(fixed)}/>
|
||||||
: <Link href={slug}><a title={title} className={linkClasses(fixed)}/></Link>
|
: <Link href={slug} title={title} className={linkClasses(fixed)}></Link>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { useState, useEffect } from 'react'
|
||||||
|
|
||||||
// See: https://mdxjs.com/guides/mdx-on-demand/
|
// See: https://mdxjs.com/guides/mdx-on-demand/
|
||||||
import { run } from '@mdx-js/mdx'
|
import { run } from '@mdx-js/mdx'
|
||||||
import * as runtime from 'react/jsx-runtime.js'
|
import * as runtime from 'react/jsx-runtime'
|
||||||
|
|
||||||
// Components that are available in all MDX
|
// Components that are available in all MDX
|
||||||
import customComponents from 'shared/components/mdx'
|
import customComponents from 'shared/components/mdx'
|
||||||
|
@ -18,7 +18,6 @@ import PrevNext from '../mdx/prev-next'
|
||||||
const Null = (props) => null
|
const Null = (props) => null
|
||||||
|
|
||||||
const MdxWrapper = ({ mdx, app, t, components = {} }) => {
|
const MdxWrapper = ({ mdx, app, t, components = {} }) => {
|
||||||
|
|
||||||
const [mdxModule, setMdxModule] = useState()
|
const [mdxModule, setMdxModule] = useState()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -34,20 +33,20 @@ const MdxWrapper = ({mdx, app, t, components={}}) => {
|
||||||
*/
|
*/
|
||||||
const allComponents = {
|
const allComponents = {
|
||||||
...customComponents(app, t),
|
...customComponents(app, t),
|
||||||
...components
|
...components,
|
||||||
}
|
}
|
||||||
|
|
||||||
// React component for MDX content
|
// React component for MDX content
|
||||||
const MdxContent = mdxModule ? mdxModule.default : Null
|
const MdxContent = mdxModule ? mdxModule.default : Null
|
||||||
|
|
||||||
return app
|
return app ? (
|
||||||
? (
|
|
||||||
<div className="text-primary mdx max-w-prose text-base-content max-w-prose text-lg lg:text-xl">
|
<div className="text-primary mdx max-w-prose text-base-content max-w-prose text-lg lg:text-xl">
|
||||||
{mdxModule && <MdxContent components={allComponents} />}
|
{mdxModule && <MdxContent components={allComponents} />}
|
||||||
<PrevNext app={app} />
|
<PrevNext app={app} />
|
||||||
</div>
|
</div>
|
||||||
) : <MdxContent components={allComponents}/>
|
) : (
|
||||||
|
<MdxContent components={allComponents} />
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MdxWrapper
|
export default MdxWrapper
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { useState, useEffect, Fragment } from 'react'
|
||||||
|
|
||||||
// See: https://mdxjs.com/guides/mdx-on-demand/
|
// See: https://mdxjs.com/guides/mdx-on-demand/
|
||||||
import { run } from '@mdx-js/mdx'
|
import { run } from '@mdx-js/mdx'
|
||||||
import * as runtime from 'react/jsx-runtime.js'
|
import * as runtime from 'react/jsx-runtime'
|
||||||
|
|
||||||
const TocWrapper = ({ toc, app }) => {
|
const TocWrapper = ({ toc, app }) => {
|
||||||
const [mdxModule, setMdxModule] = useState()
|
const [mdxModule, setMdxModule] = useState()
|
||||||
|
|
|
@ -43,6 +43,8 @@
|
||||||
"mdast-util-toc": "^6.1.0",
|
"mdast-util-toc": "^6.1.0",
|
||||||
"pdfkit": "^0.13.0",
|
"pdfkit": "^0.13.0",
|
||||||
"postcss-for": "^2.1.1",
|
"postcss-for": "^2.1.1",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
"react-markdown": "^8.0.0",
|
"react-markdown": "^8.0.0",
|
||||||
"react-sizeme": "^3.0.2",
|
"react-sizeme": "^3.0.2",
|
||||||
"react-timeago": "^7.1.0",
|
"react-timeago": "^7.1.0",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue