1
0
Fork 0

feat(org): Ported components to mjs and named exports

This commit is contained in:
joostdecock 2023-01-29 16:44:02 +01:00
parent 37f7833983
commit 595417a23b
118 changed files with 836 additions and 852 deletions

View file

@ -1,10 +1,12 @@
// Hooks
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import useBackend from 'site/hooks/useBackend.js' import { useBackend } from 'site/hooks/useBackend.mjs'
// Components
import Link from 'next/link' import Link from 'next/link'
import { Icons, welcomeSteps } from '../shared.js'
import Popout from 'shared/components/popout.js'
import Markdown from 'react-markdown' import Markdown from 'react-markdown'
import { Icons, welcomeSteps } from '../shared.mjs'
import { Popout } from 'shared/components/popout.mjs'
export const ns = ['bio'] export const ns = ['bio']
@ -18,7 +20,7 @@ const Tab = ({ id, activeTab, setActiveTab, t }) => (
</button> </button>
) )
const UsernameSettings = ({ app, title = false, welcome = false }) => { export const BioSettings = ({ app, title = false, welcome = false }) => {
const backend = useBackend(app) const backend = useBackend(app)
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const [bio, setBio] = useState(app.account.bio) const [bio, setBio] = useState(app.account.bio)
@ -91,5 +93,3 @@ const UsernameSettings = ({ app, title = false, welcome = false }) => {
</> </>
) )
} }
export default UsernameSettings

View file

@ -1,8 +1,10 @@
// Hooks
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import useBackend from 'site/hooks/useBackend.js' import { useBackend } from 'site/hooks/useBackend.mjs'
// Components
import Link from 'next/link' import Link from 'next/link'
import { Choice, Icons, welcomeSteps } from '../shared.js' import { Choice, Icons, welcomeSteps } from '../shared.mjs'
export const ns = ['compare'] export const ns = ['compare']

View file

@ -1,8 +1,10 @@
// Hooks
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import useBackend from 'site/hooks/useBackend.js' import { useBackend } from 'site/hooks/useBackend.mjs'
// Components
import Link from 'next/link' import Link from 'next/link'
import { Choice, Icons, welcomeSteps } from '../shared.js' import { Choice, Icons, welcomeSteps } from '../shared.mjs'
export const ns = ['control'] export const ns = ['control']

View file

@ -1,13 +1,15 @@
// Hooks
import { useState, useCallback } from 'react' import { useState, useCallback } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import useBackend from 'site/hooks/useBackend.js' import { useBackend } from 'site/hooks/useBackend.mjs'
import Link from 'next/link'
import { Icons, welcomeSteps } from '../shared.js'
import { useDropzone } from 'react-dropzone' import { useDropzone } from 'react-dropzone'
// Components
import Link from 'next/link'
import { Icons, welcomeSteps } from '../shared.mjs'
export const ns = ['img'] export const ns = ['img']
const ImgSettings = ({ app, title = false, welcome = false }) => { export const ImgSettings = ({ app, title = false, welcome = false }) => {
const backend = useBackend(app) const backend = useBackend(app)
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
@ -80,5 +82,3 @@ const ImgSettings = ({ app, title = false, welcome = false }) => {
</> </>
) )
} }
export default ImgSettings

View file

@ -1,8 +1,10 @@
// Hooks
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import useBackend from 'site/hooks/useBackend.js' import { useBackend } from 'site/hooks/useBackend.mjs'
// Components
import Link from 'next/link' import Link from 'next/link'
import { Choice, Icons, welcomeSteps } from '../shared.js' import { Choice, Icons, welcomeSteps } from '../shared.mjs'
export const ns = ['newsletter'] export const ns = ['newsletter']

View file

@ -1,12 +1,14 @@
import Link from 'next/link' import Link from 'next/link'
import CogIcon from 'shared/components/icons/cog.js' import {
import ControlIcon from 'shared/components/icons/control.js' CogIcon,
import NewsletterIcon from 'shared/components/icons/newsletter.js' ControlIcon,
import UnitsIcon from 'shared/components/icons/units.js' NewsletterIcon,
import CompareIcon from 'shared/components/icons/compare.js' UnitsIcon,
import LabelIcon from 'shared/components/icons/label.js' CompareIcon,
import BioIcon from 'shared/components/icons/bio.js' LabelIcon,
import UserIcon from 'shared/components/icons/user.js' BioIcon,
UserIcon,
} from 'shared/components/icons.mjs'
const btnClasses = { const btnClasses = {
dflt: dflt:

View file

@ -1,12 +1,14 @@
// Hooks
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import useBackend from 'site/hooks/useBackend.js' import { useBackend } from 'site/hooks/useBackend.mjs'
// Components
import Link from 'next/link' import Link from 'next/link'
import { Choice, Icons, welcomeSteps } from '../shared.js' import { Choice, Icons, welcomeSteps } from '../shared.mjs'
export const ns = ['units'] export const ns = ['units']
const UnitsSettings = ({ app, title = false, welcome = false }) => { export const UnitsSettings = ({ app, title = false, welcome = false }) => {
const backend = useBackend(app) const backend = useBackend(app)
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const [selection, setSelection] = useState(app.account?.imperial === true ? 'imperial' : 'metric') const [selection, setSelection] = useState(app.account?.imperial === true ? 'imperial' : 'metric')
@ -25,7 +27,7 @@ const UnitsSettings = ({ app, title = false, welcome = false }) => {
return ( return (
<> <>
{title ? <h1 className="text-4xl">{t('title')}</h1> : null} {title ? <h1 className="text-4xl">{t('title')}</h1> : <h1></h1>}
{['metric', 'imperial'].map((val) => ( {['metric', 'imperial'].map((val) => (
<Choice val={val} t={t} update={update} current={selection} bool key={val}> <Choice val={val} t={t} update={update} current={selection} bool key={val}>
<span className="block text-lg leading-5"> <span className="block text-lg leading-5">
@ -61,5 +63,3 @@ const UnitsSettings = ({ app, title = false, welcome = false }) => {
</> </>
) )
} }
export default UnitsSettings

View file

@ -1,14 +1,15 @@
// Hooks
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import useBackend from 'site/hooks/useBackend.js' import { useBackend } from 'site/hooks/useBackend.mjs'
// Components
import Link from 'next/link' import Link from 'next/link'
import { Icons, welcomeSteps } from '../shared.js' import { Icons, welcomeSteps } from '../shared.mjs'
import OkIcon from 'shared/components/icons/ok.js' import { OkIcon, NoIcon } from 'shared/components/icons.mjs'
import NoIcon from 'shared/components/icons/no.js'
export const ns = ['username'] export const ns = ['username']
const UsernameSettings = ({ app, title = false, welcome = false }) => { export const UsernameSettings = ({ app, title = false, welcome = false }) => {
const backend = useBackend(app) const backend = useBackend(app)
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const [username, setUsername] = useState(app.account.username) const [username, setUsername] = useState(app.account.username)
@ -85,5 +86,3 @@ const UsernameSettings = ({ app, title = false, welcome = false }) => {
</> </>
) )
} }
export default UsernameSettings

View file

@ -1,7 +1,7 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { configs } from 'shared/designs/index.js' import { configs } from 'shared/designs/index.js'
import DesignIcon from 'shared/components/icons/design.js' import { DesignIcon } from 'shared/components/icons.mjs'
import Worm from 'shared/components/worm.js' import Worm from 'shared/components/worm.js'
import { strapiHost } from 'shared/config/freesewing.mjs' import { strapiHost } from 'shared/config/freesewing.mjs'
import Link from 'next/link' import Link from 'next/link'

View file

@ -1,70 +0,0 @@
import Head from 'next/head'
const rss = (lang, type, title) => ({
title,
type: "application/rss+xml",
href: `/feeds/${type}-${lang}.rss.xml`
})
const atom = (lang, type, title) => ({
title,
type: "application/rss+atom",
href: `/feeds/${type}-${lang}.atom.xml`
})
const json = (lang, type, title) => ({
title,
type: "application/json",
href: `/feeds/${type}-${lang}.json`
})
const feeds = {
en: [
atom('en', 'blog', "Atom feed of FreeSewing.org blog posts"),
json('en', 'blog', "JSON feed of FreeSewing.org blog posts"),
rss( 'en', 'blog', "RSS feed of FreeSewing.org blog posts"),
atom('en', 'showcase', "Atom feed of FreeSewing.org showcase posts"),
json('en', 'showcase', "JSON feed of FreeSewing.org showcase posts"),
rss( 'en', 'showcase', "RSS feed of FreeSewing.org showcase posts"),
],
de: [
atom('de', 'blog', "Atom-Feed von FreeSewing.org-Blogbeiträgen"),
json('de', 'blog', "JSON-Feed von FreeSewing.org-Blogbeiträgen"),
rss( 'de', 'blog', "RSS-Feed von FreeSewing.org-Blogbeiträgen"),
atom('de', 'showcase', "Atom-Feed von FreeSewing.org-Galeriebeiträgen"),
json('de', 'showcase', "JSON-Feed von FreeSewing.org-Galeriebeiträgen"),
rss( 'de', 'showcase', "RSS-Feed von FreeSewing.org-Galeriebeiträgen"),
],
es: [
atom('es', 'blog', "Fuente Atom de las publicaciones del blog FreeSewing.org"),
json('es', 'blog', "Fuente JSON de las publicaciones del blog FreeSewing.org"),
rss( 'es', 'blog', "Fuente RSS de las publicaciones del blog FreeSewing.org"),
atom('es', 'showcase', "Fuente Atom de publicaciones de exhibición de FreeSewing.org"),
json('es', 'showcase', "Fuente JSON de publicaciones de exhibición de FreeSewing.org"),
rss( 'es', 'showcase', "Fuente RSS de publicaciones de exhibición de FreeSewing.org"),
],
fr: [
atom('fr', 'blog', "Flux Atom des articles du blog FreeSewing.org"),
json('fr', 'blog', "Flux JSON des articles du blog FreeSewing.org"),
rss( 'fr', 'blog', "Flux RSS des articles du blog FreeSewing.org"),
atom('fr', 'showcase', "Flux Atom des articles du galerie FreeSewing.org"),
json('fr', 'showcase', "Flux JSON des articles du galerie FreeSewing.org"),
rss( 'fr', 'showcase', "Flux RSS des articles du galerie FreeSewing.org"),
],
nl: [
atom('nl', 'blog', "Atom feed van FreeSewing.org blog posts"),
json('nl', 'blog', "JSON feed van FreeSewing.org blog posts"),
rss( 'nl', 'blog', "RSS feed van FreeSewing.org blog posts"),
atom('nl', 'showcase', "Atom feed van FreeSewing.org voorbeelden"),
json('nl', 'showcase', "JSON feed van FreeSewing.org voorbeelden"),
rss( 'nl', 'showcase', "RSS feed van FreeSewing.org voorbeelden"),
],
}
const Feeds = ({ lang='en' }) => (
<Head>
{feeds[lang].map(feed => <link key={feed.href} {...feed} />)}
</Head>
)
export default Feeds

View file

@ -0,0 +1,68 @@
import Head from 'next/head'
const rss = (lang, type, title) => ({
title,
type: 'application/rss+xml',
href: `/feeds/${type}-${lang}.rss.xml`,
})
const atom = (lang, type, title) => ({
title,
type: 'application/rss+atom',
href: `/feeds/${type}-${lang}.atom.xml`,
})
const json = (lang, type, title) => ({
title,
type: 'application/json',
href: `/feeds/${type}-${lang}.json`,
})
const feeds = {
en: [
atom('en', 'blog', 'Atom feed of FreeSewing.org blog posts'),
json('en', 'blog', 'JSON feed of FreeSewing.org blog posts'),
rss('en', 'blog', 'RSS feed of FreeSewing.org blog posts'),
atom('en', 'showcase', 'Atom feed of FreeSewing.org showcase posts'),
json('en', 'showcase', 'JSON feed of FreeSewing.org showcase posts'),
rss('en', 'showcase', 'RSS feed of FreeSewing.org showcase posts'),
],
de: [
atom('de', 'blog', 'Atom-Feed von FreeSewing.org-Blogbeiträgen'),
json('de', 'blog', 'JSON-Feed von FreeSewing.org-Blogbeiträgen'),
rss('de', 'blog', 'RSS-Feed von FreeSewing.org-Blogbeiträgen'),
atom('de', 'showcase', 'Atom-Feed von FreeSewing.org-Galeriebeiträgen'),
json('de', 'showcase', 'JSON-Feed von FreeSewing.org-Galeriebeiträgen'),
rss('de', 'showcase', 'RSS-Feed von FreeSewing.org-Galeriebeiträgen'),
],
es: [
atom('es', 'blog', 'Fuente Atom de las publicaciones del blog FreeSewing.org'),
json('es', 'blog', 'Fuente JSON de las publicaciones del blog FreeSewing.org'),
rss('es', 'blog', 'Fuente RSS de las publicaciones del blog FreeSewing.org'),
atom('es', 'showcase', 'Fuente Atom de publicaciones de exhibición de FreeSewing.org'),
json('es', 'showcase', 'Fuente JSON de publicaciones de exhibición de FreeSewing.org'),
rss('es', 'showcase', 'Fuente RSS de publicaciones de exhibición de FreeSewing.org'),
],
fr: [
atom('fr', 'blog', 'Flux Atom des articles du blog FreeSewing.org'),
json('fr', 'blog', 'Flux JSON des articles du blog FreeSewing.org'),
rss('fr', 'blog', 'Flux RSS des articles du blog FreeSewing.org'),
atom('fr', 'showcase', 'Flux Atom des articles du galerie FreeSewing.org'),
json('fr', 'showcase', 'Flux JSON des articles du galerie FreeSewing.org'),
rss('fr', 'showcase', 'Flux RSS des articles du galerie FreeSewing.org'),
],
nl: [
atom('nl', 'blog', 'Atom feed van FreeSewing.org blog posts'),
json('nl', 'blog', 'JSON feed van FreeSewing.org blog posts'),
rss('nl', 'blog', 'RSS feed van FreeSewing.org blog posts'),
atom('nl', 'showcase', 'Atom feed van FreeSewing.org voorbeelden'),
json('nl', 'showcase', 'JSON feed van FreeSewing.org voorbeelden'),
rss('nl', 'showcase', 'RSS feed van FreeSewing.org voorbeelden'),
],
}
export const Feeds = ({ lang = 'en' }) => (
<Head>
{feeds[lang].map((feed) => (
<link key={feed.href} {...feed} />
))}
</Head>
)

View file

@ -1,20 +1,21 @@
import Logo from 'shared/components/logos/freesewing.js'
import OsiLogo from 'shared/components/logos/osi.js'
import CreativeCommonsLogo from 'shared/components/logos/cc.js'
import CcByLogo from 'shared/components/logos/cc-by.js'
import Ribbon from 'shared/components/ribbon.js'
import Link from 'next/link' import Link from 'next/link'
import { WordMark } from 'shared/components/wordmark.js' import { FreeSewingLogo } from 'shared/components/logos/freesewing.mjs'
import { OsiLogo } from 'shared/components/logos/osi.mjs'
import { CCLogo } from 'shared/components/logos/cc.mjs'
import { CCByLogo } from 'shared/components/logos/cc-by.mjs'
import { Ribbon } from 'shared/components/ribbon.mjs'
import { WordMark } from 'shared/components/wordmark.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { freeSewingConfig } from 'site/freesewing.config.js' import { freeSewingConfig } from 'site/freesewing.config.mjs'
import {
import HelpIcon from 'shared/components/icons/help.js' HelpIcon,
import DiscordIcon from 'shared/components/icons/discord.js' DiscordIcon,
import FacebookIcon from 'shared/components/icons/facebook.js' FacebookIcon,
import GithubIcon from 'shared/components/icons/github.js' GithubIcon,
import InstagramIcon from 'shared/components/icons/instagram.js' InstagramIcon,
import RedditIcon from 'shared/components/icons/reddit.js' RedditIcon,
import TwitterIcon from 'shared/components/icons/twitter.js' TwitterIcon,
} from 'shared/components/icons.mjs'
const icon = { className: 'w-8 lg:w-12 h-8 lg:h-12' } const icon = { className: 'w-8 lg:w-12 h-8 lg:h-12' }
const social = { const social = {
@ -60,10 +61,10 @@ export const Footer = ({ app }) => {
<div className="mb-20 order-1 mt-20 2xl:mt-0 2xl:mb-0"> <div className="mb-20 order-1 mt-20 2xl:mt-0 2xl:mb-0">
<div className="max-w-md m-auto"> <div className="max-w-md m-auto">
<div> <div>
<CreativeCommonsLogo className="w-64 m-auto" /> <CCLogo className="w-64 m-auto" />
</div> </div>
<div className="flex flex-row gap-2 justify-center items-center mt-8"> <div className="flex flex-row gap-2 justify-center items-center mt-8">
<CcByLogo className="w-8 lg:w-12" /> <CCByLogo className="w-8 lg:w-12" />
<p className="text-neutral-content text-right basis-4/5 lg:basis-3/4 leading-5"> <p className="text-neutral-content text-right basis-4/5 lg:basis-3/4 leading-5">
{t('cc')} {t('cc')}
</p> </p>
@ -138,7 +139,7 @@ export const Footer = ({ app }) => {
{/* Col 3 - Logo & Slogan */} {/* Col 3 - Logo & Slogan */}
<div className="w-full 4xl:w-auto xl:max-w-md mb-8 text-center order-3 mt-0 lg:mt-20 2xl:mt-0 2xl:mb-0"> <div className="w-full 4xl:w-auto xl:max-w-md mb-8 text-center order-3 mt-0 lg:mt-20 2xl:mt-0 2xl:mb-0">
<div className="max-w-md m-auto"> <div className="max-w-md m-auto">
<Logo stroke="none" size={164} className="w-40 lg:w-64 m-auto m-auto" /> <FreeSewingLogo stroke="none" size={164} className="w-40 lg:w-64 m-auto m-auto" />
<h5 className="lg:text-3xl mt-4"> <h5 className="lg:text-3xl mt-4">
<WordMark /> <WordMark />
</h5> </h5>

View file

@ -1,11 +1,9 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import ThemePicker, { ns as themeNs } from 'shared/components/theme-picker/index.js' import { ThemePicker, ns as themeNs } from 'shared/components/theme-picker/index.mjs'
import LocalePicker, { ns as localeNs } from 'shared/components/locale-picker/index.js' import { LocalePicker, ns as localeNs } from 'shared/components/locale-picker/index.mjs'
import CloseIcon from 'shared/components/icons/close.js' import { CloseIcon, MenuIcon, SearchIcon } from 'shared/components/icons.mjs'
import MenuIcon from 'shared/components/icons/menu.js' import { Ribbon } from 'shared/components/ribbon.mjs'
import SearchIcon from 'shared/components/icons/search.js' import { WordMark } from 'shared/components/wordmark.mjs'
import Ribbon from 'shared/components/ribbon.js'
import { WordMark } from 'shared/components/wordmark.js'
export const ns = [...new Set([...themeNs, ...localeNs])] export const ns = [...new Set([...themeNs, ...localeNs])]

View file

@ -1,17 +0,0 @@
import { useRouter } from 'next/router'
import Aside from 'shared/components/navigation/aside'
import ThemePicker from 'shared/components/theme-picker'
const DefaultLayout = ({ app, children = [] }) => {
const router = useRouter()
const slug = router.asPath.slice(1)
return (
<>
<Aside app={app} slug={slug} before={<ThemePicker app={app} />} mobileOnly />
{children}
</>
)
}
export default DefaultLayout

View file

@ -0,0 +1,15 @@
import { useRouter } from 'next/router'
import { AsideNavigation } from 'shared/components/navigation/aside.mjs'
import { ThemePicker } from 'shared/components/theme-picker/index.mjs'
export const BareLayout = ({ app, children = [] }) => {
const router = useRouter()
const slug = router.asPath.slice(1)
return (
<>
<AsideNavigation app={app} slug={slug} before={<ThemePicker app={app} />} mobileOnly />
{children}
</>
)
}

View file

@ -1,7 +1,7 @@
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import Aside from 'site/components/navigation/aside' import { AsideNavigation } from 'site/components/navigation/aside.mjs'
const DefaultLayout = ({ app, title = false, children = [] }) => { export const DocsLayout = ({ app, title = false, children = [] }) => {
const router = useRouter() const router = useRouter()
const slug = router.asPath.slice(1) const slug = router.asPath.slice(1)
@ -18,7 +18,7 @@ const DefaultLayout = ({ app, title = false, children = [] }) => {
lg:block lg:block
`} `}
> >
<Aside app={app} slug={slug} /> <AsideNavigation app={app} slug={slug} />
</section> </section>
<section className="py-8 lg:py-16 px-6 xl:pl-8 2xl:pl-16"> <section className="py-8 lg:py-16 px-6 xl:pl-8 2xl:pl-16">
<div> <div>
@ -29,5 +29,3 @@ const DefaultLayout = ({ app, title = false, children = [] }) => {
</div> </div>
) )
} }
export default DefaultLayout

View file

@ -2,10 +2,8 @@
//import PatternOptions from './pattern-options.js' //import PatternOptions from './pattern-options.js'
//import PatternMeasurements from './pattern-measurements.js' //import PatternMeasurements from './pattern-measurements.js'
const components = { export const components = {
//PatternDocs, //PatternDocs,
//PatternOptions, //PatternOptions,
//PatternMeasurements, //PatternMeasurements,
} }
export default components

View file

@ -3,21 +3,21 @@ import { useTranslation } from 'next-i18next'
import orderBy from 'lodash.orderby' import orderBy from 'lodash.orderby'
import PageLink from 'shared/components/page-link.js' import PageLink from 'shared/components/page-link.js'
const PatternMeasurements = ({ pattern, before=null, after=null }) => { const PatternMeasurements = ({ pattern, before = null, after = null }) => {
const { t } = useTranslation(['measurements']) const { t } = useTranslation(['measurements'])
const measurements = {} const measurements = {}
for (const m of configs[pattern].measurements) { for (const m of configs[pattern].measurements) {
measurements[m] = { measurements[m] = {
title: t(`measurements.${m}`), title: t(`measurements.${m}`),
required: true required: true,
} }
} }
for (const m of configs[pattern].measurements || []) { for (const m of configs[pattern].measurements || []) {
measurements[m] = { measurements[m] = {
name: m, name: m,
title: t(`measurements:${m}`), title: t(`measurements:${m}`),
required: false required: false,
} }
} }
@ -28,7 +28,7 @@ const PatternMeasurements = ({ pattern, before=null, after=null }) => {
<div> <div>
{before} {before}
<ol className="list-inside ml-8 my-4"> <ol className="list-inside ml-8 my-4">
{orderBy(measurements, ['title'], ['asc']).map(m => ( {orderBy(measurements, ['title'], ['asc']).map((m) => (
<li key={m.name}> <li key={m.name}>
<PageLink href={'/docs/measurements/' + m.name.toLowerCase()} txt={m.title} /> <PageLink href={'/docs/measurements/' + m.name.toLowerCase()} txt={m.title} />
</li> </li>

View file

@ -49,7 +49,7 @@ const renderOptions = (groups, pattern, t) => {
return <ul className="list list-disc list-inside ml-4">{list}</ul> return <ul className="list list-disc list-inside ml-4">{list}</ul>
} }
const PatternOptions = ({ pattern, before=null, after=null }) => { const PatternOptions = ({ pattern, before = null, after = null }) => {
const { t } = useTranslation([`o_${pattern}`, 'og']) const { t } = useTranslation([`o_${pattern}`, 'og'])
return ( return (

View file

@ -1,6 +1,6 @@
import PrimaryNavigation from './primary' import { PrimaryNavigation } from './primary.mjs'
const Aside = ({ app, slug, mobileOnly = false, before = [], after = [] }) => ( export const AsideNavigation = ({ app, slug, mobileOnly = false, before = [], after = [] }) => (
<aside <aside
className={` className={`
fixed top-0 right-0 h-screen w-screen fixed top-0 right-0 h-screen w-screen
@ -23,5 +23,3 @@ const Aside = ({ app, slug, mobileOnly = false, before = [], after = [] }) => (
{after} {after}
</aside> </aside>
) )
export default Aside

View file

@ -1,8 +1,8 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import Link from 'next/link' import Link from 'next/link'
import orderBy from 'lodash.orderby' import orderBy from 'lodash.orderby'
import FreeSewingIcon from 'shared/components/icons/freesewing.js' import { FreeSewingIcon } from 'shared/components/icons.mjs'
import TopLevel from './top-level.js' import { TopLevelNavigation as TopLevel } from './top-level.mjs'
/* 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'])
@ -278,12 +278,10 @@ const Navigation = ({ app, active, className = '' }) => {
return <div className={`pb-20 ${className}`}>{output}</div> return <div className={`pb-20 ${className}`}>{output}</div>
} }
const PrimaryMenu = ({ app, active, before = [], after = [] }) => ( export const PrimaryNavigation = ({ app, active, before = [], after = [] }) => (
<nav className="mb-12"> <nav className="mb-12">
{before} {before}
<Navigation app={app} active={active} /> <Navigation app={app} active={active} />
{after} {after}
</nav> </nav>
) )
export default PrimaryMenu

View file

@ -1,5 +0,0 @@
const TopLevelNavigation = () => {
return <p>Top-level menu here</p>
}
export default TopLevelNavigation

View file

@ -0,0 +1,3 @@
export const TopLevelNavigation = () => {
return <p>Top-level menu here</p>
}

View file

@ -10,7 +10,7 @@ import {
connectHighlight, connectHighlight,
connectSearchBox, connectSearchBox,
} from 'react-instantsearch-dom' } from 'react-instantsearch-dom'
import { freeSewingConfig } from 'site/freesewing.config.js' import { freeSewingConfig } from 'site/freesewing.config.mjs'
const searchClient = algoliasearch(freeSewingConfig.algolia.app, freeSewingConfig.algolia.key) const searchClient = algoliasearch(freeSewingConfig.algolia.app, freeSewingConfig.algolia.key)

View file

@ -1,6 +1,6 @@
import Link from 'next/link' import Link from 'next/link'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import Loader from 'shared/components/loader.js' import { Loader } from 'shared/components/loader.mjs'
export const ns = ['auth'] export const ns = ['auth']
@ -83,7 +83,7 @@ const ConsentLacking = ({ t }) => (
</Wrap> </Wrap>
) )
const AuthWrapper = ({ children, app }) => { export const AuthWrapper = ({ children, app }) => {
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
if (!app.accountReady) return <Loader /> if (!app.accountReady) return <Loader />
if (!app.token || !app.account?.username) return <AuthRequired t={t} /> if (!app.token || !app.account?.username) return <AuthRequired t={t} />
@ -97,5 +97,3 @@ const AuthWrapper = ({ children, app }) => {
return children return children
} }
export default AuthWrapper

View file

@ -1,11 +1,20 @@
// Hooks
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
// Components
import { Header, ns as headerNs } from 'site/components/header/index.mjs' import { Header, ns as headerNs } from 'site/components/header/index.mjs'
import { Footer, ns as footerNs } from 'site/components/footer/index.mjs' import { Footer, ns as footerNs } from 'site/components/footer/index.mjs'
import { Search, ns as searchNs } from 'site/components/search' import { Search, ns as searchNs } from 'site/components/search.mjs'
export const ns = [...new Set([...headerNs, ...footerNs, ...searchNs])] export const ns = [...new Set([...headerNs, ...footerNs, ...searchNs])]
const LayoutWrapper = ({ app, children = [], footer, search, setSearch, noSearch = false }) => { export const LayoutWrapper = ({
app,
children = [],
footer,
search,
setSearch,
noSearch = false,
}) => {
const startNavigation = () => { const startNavigation = () => {
app.startLoading() app.startLoading()
// Force close of menu on mobile if it is open // Force close of menu on mobile if it is open
@ -48,5 +57,3 @@ const LayoutWrapper = ({ app, children = [], footer, search, setSearch, noSearch
</div> </div>
) )
} }
export default LayoutWrapper

View file

@ -1,19 +1,20 @@
// Hooks
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { useSwipeable } from 'react-swipeable' import { useSwipeable } from 'react-swipeable'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useHotkeys } from 'react-hotkeys-hook' import { useHotkeys } from 'react-hotkeys-hook'
// Layouts components // Components
import LayoutWrapper from 'site/components/wrappers/layout' import { LayoutWrapper } from 'site/components/wrappers/layout.mjs'
import Docs from 'site/components/layouts/docs' import { DocsLayout } from 'site/components/layouts/docs.mjs'
// Add feeds // Add feeds
import Feeds from 'site/components/feeds.js' import { Feeds } from 'site/components/feeds.mjs'
/* This component should wrap all page content */ /* This component should wrap all page content */
const PageWrapper = ({ export const PageWrapper = ({
title = 'FIXME: No title set', title = 'FIXME: No title set',
noSearch = false, noSearch = false,
app = false, app = false,
layout = Docs, layout = DocsLayout,
footer = true, footer = true,
crumbs = false, crumbs = false,
children = [], children = [],
@ -64,5 +65,3 @@ const PageWrapper = ({
</div> </div>
) )
} }
export default PageWrapper

View file

@ -5,7 +5,7 @@ const opacity = {
lgbtq: 80, lgbtq: 80,
} }
const SusiWrapper = ({ theme, children, error = false }) => ( export const SusiWrapper = ({ theme, children, error = false }) => (
<section <section
style={{ style={{
backgroundImage: `url('https://static.freesewing.org/img/splash/${theme || 'light'}.jpg')`, backgroundImage: `url('https://static.freesewing.org/img/splash/${theme || 'light'}.jpg')`,
@ -25,5 +25,3 @@ const SusiWrapper = ({ theme, children, error = false }) => (
</div> </div>
</section> </section>
) )
export default SusiWrapper

View file

@ -1,9 +1,7 @@
const WelcomeWrapper = ({ children }) => ( export const WelcomeWrapper = ({ children }) => (
<section className="m-0 p-0 w-full"> <section className="m-0 p-0 w-full">
<div className="flex flex-col items-center justify-start h-screen mt-4 lg:mt-32 max-w-lg m-auto"> <div className="flex flex-col items-center justify-start h-screen mt-4 lg:mt-32 max-w-lg m-auto">
<div className="w-full text-left">{children}</div> <div className="w-full text-left">{children}</div>
</div> </div>
</section> </section>
) )
export default WelcomeWrapper

View file

@ -80,7 +80,7 @@ const buildNavigation = (lang, t) => {
/* /*
* The actual hook * The actual hook
*/ */
function useApp({ bugsnag }) { export function useApp({ bugsnag }) {
// Load translation method // Load translation method
const locale = useRouter().locale const locale = useRouter().locale
const { t } = useTranslation() const { t } = useTranslation()
@ -183,5 +183,3 @@ function useApp({ bugsnag }) {
errId, errId,
} }
} }
export default useApp

View file

@ -9,7 +9,7 @@ const api = axios.create({
timeout: 3000, timeout: 3000,
}) })
function useBackend(app) { export function useBackend(app) {
const auth = { const auth = {
headers: { Authorization: 'Bearer ' + app.token }, headers: { Authorization: 'Bearer ' + app.token },
} }
@ -107,5 +107,3 @@ function useBackend(app) {
return backend return backend
} }
export default useBackend

3
sites/org/notes.md Normal file
View file

@ -0,0 +1,3 @@
to sit
bu hao yi se

View file

@ -3,7 +3,7 @@ import { appWithTranslation } from 'next-i18next'
import React from 'react' import React from 'react'
import Bugsnag from '@bugsnag/js' import Bugsnag from '@bugsnag/js'
import BugsnagPluginReact from '@bugsnag/plugin-react' import BugsnagPluginReact from '@bugsnag/plugin-react'
import { freeSewingConfig } from 'site/freesewing.config.js' import { freeSewingConfig } from 'site/freesewing.config.mjs'
Bugsnag.start({ Bugsnag.start({
apiKey: freeSewingConfig.bugsnag.key, apiKey: freeSewingConfig.bugsnag.key,

View file

@ -1,22 +1,24 @@
import { useEffect } from 'react' // Hooks
import Page from 'site/components/wrappers/page.js' import { useEffect, useState } from 'react'
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import useBackend from 'site/hooks/useBackend.js' import { useBackend } from 'site/hooks/useBackend.mjs'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare'
import Link from 'next/link'
import { useState } from 'react'
import WelcomeWrapper from 'site/components/wrappers/welcome.js'
import Spinner from 'shared/components/icons/spinner.js'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import Popout from 'shared/components/popout.js' import { useTranslation } from 'next-i18next'
// Dependencies
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import Link from 'next/link'
// Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs'
import { WelcomeWrapper } from 'site/components/wrappers/welcome.mjs'
import { Spinner } from 'shared/components/spinner.mjs'
import { Popout } from 'shared/components/popout.mjs'
import { Robot } from 'shared/components/robot/index.mjs'
import { import {
GdprProfileDetails, GdprProfileDetails,
GdprMeasurementsDetails, GdprMeasurementsDetails,
ns as gdprNs, ns as gdprNs,
} from 'site/components/gdpr/details.js' } from 'site/components/gdpr/details.mjs'
import Robot from 'shared/components/robot/index.js'
// Translation namespaces used on this page // Translation namespaces used on this page
const ns = Array.from(new Set([...gdprNs, 'confirm', 'locales', 'themes'])) const ns = Array.from(new Set([...gdprNs, 'confirm', 'locales', 'themes']))
@ -110,11 +112,11 @@ const ConfirmSignUpPage = (props) => {
// Short-circuit errors // Short-circuit errors
if (error) if (error)
return ( return (
<Page app={app} title={t('joinFreeSewing')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('joinFreeSewing')} layout={BareLayout} footer={false}>
<WelcomeWrapper theme={app.theme}> <WelcomeWrapper theme={app.theme}>
<SignupLinkExpired /> <SignupLinkExpired />
</WelcomeWrapper> </WelcomeWrapper>
</Page> </PageWrapper>
) )
const partA = ( const partA = (
@ -181,7 +183,7 @@ const ConfirmSignUpPage = (props) => {
) )
return ( return (
<Page app={app} title={t('joinFreeSewing')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('joinFreeSewing')} layout={BareLayout} footer={false}>
<WelcomeWrapper theme={app.theme}> <WelcomeWrapper theme={app.theme}>
{ready ? ( {ready ? (
<> <>
@ -223,7 +225,7 @@ const ConfirmSignUpPage = (props) => {
</Link> </Link>
</p> </p>
</WelcomeWrapper> </WelcomeWrapper>
</Page> </PageWrapper>
) )
} }

View file

@ -1,14 +1,16 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import mdxLoader from 'shared/mdx/loader' // Dependencies
import MdxWrapper from 'shared/components/wrappers/mdx'
import TocWrapper from 'shared/components/wrappers/toc'
import Head from 'next/head' import Head from 'next/head'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations' import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import components from 'site/components/mdx/index.js' import { mdxLoader } from 'shared/mdx/loader.mjs'
import { jargon } from 'site/jargon.mjs' import { jargon } from 'site/jargon.mjs'
// MDX paths import { mdxPaths } from 'site/prebuild/mdx.paths.mjs'
import mdxPaths from 'site/prebuild/mdx.paths.js' // Components
import { MdxWrapper } from 'shared/components/wrappers/mdx.mjs'
import { TocWrapper } from 'shared/components/wrappers/toc.mjs'
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { components } from 'site/components/mdx/index.mjs'
const MdxPage = (props) => { const MdxPage = (props) => {
// This hook is used for shared code and global state // This hook is used for shared code and global state
@ -26,7 +28,7 @@ const MdxPage = (props) => {
* active state * active state
*/ */
return ( return (
<Page app={app} {...props.page}> <PageWrapper app={app} {...props.page}>
<Head> <Head>
<meta property="og:title" content={props.page.title} key="title" /> <meta property="og:title" content={props.page.title} key="title" />
<meta property="og:type" content="article" key="type" /> <meta property="og:type" content="article" key="type" />
@ -53,7 +55,7 @@ const MdxPage = (props) => {
)} )}
<MdxWrapper mdx={props.mdx} app={app} components={components} /> <MdxWrapper mdx={props.mdx} app={app} components={components} />
</div> </div>
</Page> </PageWrapper>
) )
} }

View file

@ -1,10 +1,13 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import mdxLoader from 'shared/mdx/loader' // Dependencies
import MdxWrapper from 'shared/components/wrappers/mdx'
import ReadMore from 'shared/components/mdx/read-more.js'
import { jargon } from 'site/jargon.mjs'
import Head from 'next/head' import Head from 'next/head'
import mdxLoader from 'shared/mdx/loader'
// Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { MdxWrapper } from 'shared/components/wrappers/mdx.mjs'
import { ReadMore } from 'shared/components/mdx/read-more.mjs'
import { jargon } from 'site/jargon.mjs'
const DocsPage = ({ title, mdx, bugsnag }) => { const DocsPage = ({ title, mdx, bugsnag }) => {
const app = useApp({ bugsnag }) const app = useApp({ bugsnag })
@ -16,14 +19,14 @@ const DocsPage = ({ title, mdx, bugsnag }) => {
} }
return ( return (
<Page app={app} title={title}> <PageWrapper app={app} title={title}>
<Head> <Head>
<title>{fullTitle}</title> <title>{fullTitle}</title>
</Head> </Head>
<div className="w-full"> <div className="w-full">
<MdxWrapper mdx={mdx} app={app} components={components} /> <MdxWrapper mdx={mdx} app={app} components={components} />
</div> </div>
</Page> </PageWrapper>
) )
} }

View file

@ -1,11 +1,14 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import Popout from 'shared/components/popout.js' // Dependencies
import { serverSideTranslations } from 'next-i18next/serverSideTranslations' import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
//import { useTranslation } from 'next-i18next' //import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare'
import PageLink from 'shared/components/page-link'
import Head from 'next/head' import Head from 'next/head'
// Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { Popout } from 'shared/components/popout.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs'
import { PageLink } from 'shared/components/page-link.mjs'
const HomePage = (props) => { const HomePage = (props) => {
const app = useApp(props) const app = useApp(props)
@ -14,18 +17,18 @@ const HomePage = (props) => {
// const { t } = useTranslation(['homepage', 'ograph']) // const { t } = useTranslation(['homepage', 'ograph'])
return ( return (
<Page app={app} title={title} layout={Layout}> <PageWrapper app={app} title={title} layout={BareLayout}>
<Head> <Head>
<title>{title}</title> <title>{title}</title>
</Head> </Head>
<div> <div>
<div className="max-w-xl m-auto my-32 px-6"> <div className="max-w-xl m-auto my-32 px-6">
<Popout fixme> <Popout fixme>
Create homepage. Meanwhile check <PageLink href="/docs" txt="docs" /> Create homepage. Meanwhile check <PageLink href="/signup" txt="the signup flow" />
</Popout> </Popout>
</div> </div>
</div> </div>
</Page> </PageWrapper>
) )
} }

View file

@ -1,12 +1,15 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare'
import Link from 'next/link'
import { useState } from 'react' import { useState } from 'react'
// Dependencies
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { validateEmail, validateTld } from 'shared/utils.mjs' import { validateEmail, validateTld } from 'shared/utils.mjs'
import SusiWrapper from 'site/components/wrappers/susi.js' // Components
import Link from 'next/link'
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs'
import { SusiWrapper } from 'site/components/wrappers/susi.mjs'
const darkLinkClasses = 'decoration-1 underline text-medium font-medium hover:decoration-2' const darkLinkClasses = 'decoration-1 underline text-medium font-medium hover:decoration-2'
@ -29,7 +32,7 @@ const SignInPage = (props) => {
const clearUsername = () => app.setUsername(false) const clearUsername = () => app.setUsername(false)
return ( return (
<Page app={app} title={t('welcomeBack')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('welcomeBack')} layout={BareLayout} footer={false}>
<SusiWrapper theme={app.theme}> <SusiWrapper theme={app.theme}>
<h1 className="text-neutral-content font-light text-3xl mb-4 pb-0 text-center"> <h1 className="text-neutral-content font-light text-3xl mb-4 pb-0 text-center">
{t('welcomeName', { name: app.username || '' })} {t('welcomeName', { name: app.username || '' })}
@ -82,7 +85,7 @@ const SignInPage = (props) => {
</Link> </Link>
</p> </p>
</SusiWrapper> </SusiWrapper>
</Page> </PageWrapper>
) )
} }

View file

@ -1,15 +1,18 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js'
import useBackend from 'site/hooks/useBackend.js'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare'
import Link from 'next/link'
import { useState } from 'react' import { useState } from 'react'
import { useApp } from 'site/hooks/useApp.mjs'
import { useBackend } from 'site/hooks/useBackend.mjs'
import { useTranslation } from 'next-i18next'
// Dependencies
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { validateEmail, validateTld } from 'shared/utils.mjs' import { validateEmail, validateTld } from 'shared/utils.mjs'
import SusiWrapper from 'site/components/wrappers/susi.js' // Components
import Spinner from 'shared/components/icons/spinner.js' import Link from 'next/link'
import Robot from 'shared/components/robot/index.js' import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs'
import { SusiWrapper } from 'site/components/wrappers/susi.mjs'
import { Spinner } from 'shared/components/spinner.mjs'
import { Robot } from 'shared/components/robot/index.mjs'
// Translation namespaces used on this page // Translation namespaces used on this page
const namespaces = ['signup', 'errors'] const namespaces = ['signup', 'errors']
@ -59,7 +62,7 @@ const SignUpPage = (props) => {
const loadingClasses = app.loading ? 'opacity-50' : '' const loadingClasses = app.loading ? 'opacity-50' : ''
return ( return (
<Page app={app} title={t('joinFreeSewing')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('joinFreeSewing')} layout={BareLayout} footer={false}>
<SusiWrapper theme={app.theme} error={result && result !== 'success'}> <SusiWrapper theme={app.theme} error={result && result !== 'success'}>
<h1 className={`text-neutral-content font-light text-3xl mb-0 pb-0 ${loadingClasses}`}> <h1 className={`text-neutral-content font-light text-3xl mb-0 pb-0 ${loadingClasses}`}>
{result ? ( {result ? (
@ -152,7 +155,7 @@ const SignUpPage = (props) => {
</> </>
)} )}
</SusiWrapper> </SusiWrapper>
</Page> </PageWrapper>
) )
} }

View file

@ -1,6 +1,8 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import Popout from 'shared/components/popout.js' // Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { Popout } from 'shared/components/popout.mjs'
const TypographyPage = (props) => { const TypographyPage = (props) => {
const app = useApp(props) const app = useApp(props)
@ -13,7 +15,7 @@ const TypographyPage = (props) => {
) )
return ( return (
<Page app={{ ...app, navigation: null }} title="Typography"> <PageWrapper app={{ ...app, navigation: null }} title="Typography">
<div className="text-primary mdx max-w-prose text-base-content max-w-prose text-base"> <div className="text-primary mdx max-w-prose text-base-content max-w-prose text-base">
<p>This typography page shows an overview of different elements and how they are styled.</p> <p>This typography page shows an overview of different elements and how they are styled.</p>
<p>It&apos;s a good starting point for theme development.</p> <p>It&apos;s a good starting point for theme development.</p>
@ -84,7 +86,7 @@ const TypographyPage = (props) => {
) )
})} })}
</div> </div>
</Page> </PageWrapper>
) )
} }

View file

@ -1,10 +1,13 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare' // Dependencies
import AuthWrapper, { namespaces as authNs } from 'site/components/wrappers/auth/index.js' import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import BioSettings, { namespaces as bioNs } from 'site/components/account/bio/index.js' // Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs'
import { AuthWrapper, ns as authNs } from 'site/components/wrappers/auth/index.mjs'
import { BioSettings, ns as bioNs } from 'site/components/account/bio/index.mjs'
// Translation namespaces used on this page // Translation namespaces used on this page
const namespaces = [...bioNs, ...authNs] const namespaces = [...bioNs, ...authNs]
@ -14,13 +17,13 @@ const BioPage = (props) => {
const { t } = useTranslation(namespaces) const { t } = useTranslation(namespaces)
return ( return (
<Page app={app} title={t('title')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('title')} layout={BareLayout} footer={false}>
<AuthWrapper app={app}> <AuthWrapper app={app}>
<div className="m-auto max-w-lg text-center lg:mt-12 p-8"> <div className="m-auto max-w-lg text-center lg:mt-12 p-8">
<BioSettings app={app} title welcome /> <BioSettings app={app} title welcome />
</div> </div>
</AuthWrapper> </AuthWrapper>
</Page> </PageWrapper>
) )
} }
@ -29,7 +32,7 @@ export default BioPage
export async function getStaticProps({ locale }) { export async function getStaticProps({ locale }) {
return { return {
props: { props: {
...(await serverSideTranslations(locale)), ...(await serverSideTranslations(locale, namespaces)),
}, },
} }
} }

View file

@ -1,10 +1,13 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare' // Dependencies
import AuthWrapper, { namespaces as authNs } from 'site/components/wrappers/auth/index.js' import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import CompareSettings, { namespaces as compareNs } from 'site/components/account/compare/index.js' // Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs'
import { AuthWrapper, ns as authNs } from 'site/components/wrappers/auth/index.mjs'
import { CompareSettings, ns as compareNs } from 'site/components/account/compare/index.mjs'
// Translation namespaces used on this page // Translation namespaces used on this page
const namespaces = [...compareNs, ...authNs] const namespaces = [...compareNs, ...authNs]
@ -14,13 +17,13 @@ const ComparePage = (props) => {
const { t } = useTranslation(namespaces) const { t } = useTranslation(namespaces)
return ( return (
<Page app={app} title={t('title')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('title')} layout={BareLayout} footer={false}>
<AuthWrapper app={app}> <AuthWrapper app={app}>
<div className="m-auto max-w-lg text-center lg:mt-12 p-8"> <div className="m-auto max-w-lg text-center lg:mt-12 p-8">
<CompareSettings app={app} title welcome /> <CompareSettings app={app} title welcome />
</div> </div>
</AuthWrapper> </AuthWrapper>
</Page> </PageWrapper>
) )
} }
@ -29,7 +32,7 @@ export default ComparePage
export async function getStaticProps({ locale }) { export async function getStaticProps({ locale }) {
return { return {
props: { props: {
...(await serverSideTranslations(locale)), ...(await serverSideTranslations(locale, namespaces)),
}, },
} }
} }

View file

@ -1,10 +1,13 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare' // Dependencies
import AuthWrapper, { namespaces as authNs } from 'site/components/wrappers/auth/index.js' import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import ImgSettings, { namespaces as imgNs } from 'site/components/account/img/index.js' // Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs'
import { AuthWrapper, ns as authNs } from 'site/components/wrappers/auth/index.mjs'
import { ImgSettings, ns as imgNs } from 'site/components/account/img/index.mjs'
// Translation namespaces used on this page // Translation namespaces used on this page
const namespaces = [...imgNs, ...authNs] const namespaces = [...imgNs, ...authNs]
@ -14,13 +17,13 @@ const ImgPage = (props) => {
const { t } = useTranslation(namespaces) const { t } = useTranslation(namespaces)
return ( return (
<Page app={app} title={t('title')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('title')} layout={BareLayout} footer={false}>
<AuthWrapper app={app}> <AuthWrapper app={app}>
<div className="m-auto max-w-lg text-center lg:mt-12 p-8"> <div className="m-auto max-w-lg text-center lg:mt-12 p-8">
<ImgSettings app={app} title welcome /> <ImgSettings app={app} title welcome />
</div> </div>
</AuthWrapper> </AuthWrapper>
</Page> </PageWrapper>
) )
} }
@ -29,7 +32,7 @@ export default ImgPage
export async function getStaticProps({ locale }) { export async function getStaticProps({ locale }) {
return { return {
props: { props: {
...(await serverSideTranslations(locale)), ...(await serverSideTranslations(locale, namespaces)),
}, },
} }
} }

View file

@ -1,10 +1,13 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare' // Dependencies
import AuthWrapper, { namespaces as authNs } from 'site/components/wrappers/auth/index.js' import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import ControlSettings, { namespaces as controlNs } from 'site/components/account/control/index.js' // Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs'
import { AuthWrapper, ns as authNs } from 'site/components/wrappers/auth/index.mjs'
import { ControlSettings, ns as controlNs } from 'site/components/account/control/index.mjs'
// Translation namespaces used on this page // Translation namespaces used on this page
const namespaces = [...controlNs, ...authNs] const namespaces = [...controlNs, ...authNs]
@ -14,13 +17,13 @@ const WelcomePage = (props) => {
const { t } = useTranslation(namespaces) const { t } = useTranslation(namespaces)
return ( return (
<Page app={app} title={t('title')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('title')} layout={BareLayout} footer={false}>
<AuthWrapper app={app}> <AuthWrapper app={app}>
<div className="m-auto max-w-lg text-center lg:mt-12 p-8"> <div className="m-auto max-w-lg text-center lg:mt-12 p-8">
<ControlSettings app={app} title welcome /> <ControlSettings app={app} title welcome />
</div> </div>
</AuthWrapper> </AuthWrapper>
</Page> </PageWrapper>
) )
} }
@ -29,7 +32,7 @@ export default WelcomePage
export async function getStaticProps({ locale }) { export async function getStaticProps({ locale }) {
return { return {
props: { props: {
...(await serverSideTranslations(locale)), ...(await serverSideTranslations(locale, namespaces)),
}, },
} }
} }

View file

@ -1,12 +1,15 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare' // Dependencies
import AuthWrapper, { namespaces as authNs } from 'site/components/wrappers/auth/index.js' import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
// Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs'
import { AuthWrapper, ns as authNs } from 'site/components/wrappers/auth/index.mjs'
import NewsletterSettings, { import NewsletterSettings, {
namespaces as newsletterNs, ns as newsletterNs,
} from 'site/components/account/newsletter/index.js' } from 'site/components/account/newsletter/index.mjs'
// Translation namespaces used on this page // Translation namespaces used on this page
const namespaces = [...newsletterNs, ...authNs] const namespaces = [...newsletterNs, ...authNs]
@ -16,13 +19,13 @@ const WelcomePage = (props) => {
const { t } = useTranslation(namespaces) const { t } = useTranslation(namespaces)
return ( return (
<Page app={app} title={t('title')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('title')} layout={BareLayout} footer={false}>
<AuthWrapper app={app}> <AuthWrapper app={app}>
<div className="m-auto max-w-lg text-center lg:mt-12 p-8"> <div className="m-auto max-w-lg text-center lg:mt-12 p-8">
<NewsletterSettings app={app} title welcome /> <NewsletterSettings app={app} title welcome />
</div> </div>
</AuthWrapper> </AuthWrapper>
</Page> </PageWrapper>
) )
} }
@ -31,7 +34,7 @@ export default WelcomePage
export async function getStaticProps({ locale }) { export async function getStaticProps({ locale }) {
return { return {
props: { props: {
...(await serverSideTranslations(locale)), ...(await serverSideTranslations(locale, namespaces)),
}, },
} }
} }

View file

@ -1,10 +1,13 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare' // Dependencies
import AuthWrapper, { namespaces as authNs } from 'site/components/wrappers/auth/index.js' import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import UnitsSettings, { namespaces as unitsNs } from 'site/components/account/units/index.js' // Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs'
import { AuthWrapper, ns as authNs } from 'site/components/wrappers/auth/index.mjs'
import { UnitsSettings, ns as unitsNs } from 'site/components/account/units/index.mjs'
// Translation namespaces used on this page // Translation namespaces used on this page
const namespaces = [...unitsNs, ...authNs] const namespaces = [...unitsNs, ...authNs]
@ -14,13 +17,13 @@ const UnitsPage = (props) => {
const { t } = useTranslation(namespaces) const { t } = useTranslation(namespaces)
return ( return (
<Page app={app} title={t('title')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('title')} layout={BareLayout} footer={false}>
<AuthWrapper app={app}> <AuthWrapper app={app}>
<div className="m-auto max-w-lg text-center lg:mt-12 p-8"> <div className="m-auto max-w-lg text-center lg:mt-12 p-8">
<UnitsSettings app={app} title welcome /> <UnitsSettings app={app} title welcome />
</div> </div>
</AuthWrapper> </AuthWrapper>
</Page> </PageWrapper>
) )
} }
@ -29,7 +32,7 @@ export default UnitsPage
export async function getStaticProps({ locale }) { export async function getStaticProps({ locale }) {
return { return {
props: { props: {
...(await serverSideTranslations(locale)), ...(await serverSideTranslations(locale, namespaces)),
}, },
} }
} }

View file

@ -1,12 +1,13 @@
import Page from 'site/components/wrappers/page.js' // Hooks
import useApp from 'site/hooks/useApp.js' import { useApp } from 'site/hooks/useApp.mjs'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare' // Dependencies
import AuthWrapper, { namespaces as authNs } from 'site/components/wrappers/auth/index.js' import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import UsernameSettings, { // Components
namespaces as usernameNs, import { PageWrapper } from 'site/components/wrappers/page.mjs'
} from 'site/components/account/username/index.js' import { BareLayout } from 'site/components/layouts/bare.mjs'
import { AuthWrapper, ns as authNs } from 'site/components/wrappers/auth/index.mjs'
import { UsernameSettings, ns as usernameNs } from 'site/components/account/username/index.mjs'
// Translation namespaces used on this page // Translation namespaces used on this page
const namespaces = [...usernameNs, ...authNs] const namespaces = [...usernameNs, ...authNs]
@ -16,13 +17,13 @@ const UsernamePage = (props) => {
const { t } = useTranslation(namespaces) const { t } = useTranslation(namespaces)
return ( return (
<Page app={app} title={t('title')} layout={Layout} footer={false}> <PageWrapper app={app} title={t('title')} layout={BareLayout} footer={false}>
<AuthWrapper app={app}> <AuthWrapper app={app}>
<div className="m-auto max-w-lg text-center lg:mt-12 p-8"> <div className="m-auto max-w-lg text-center lg:mt-12 p-8">
<UsernameSettings app={app} title welcome /> <UsernameSettings app={app} title welcome />
</div> </div>
</AuthWrapper> </AuthWrapper>
</Page> </PageWrapper>
) )
} }
@ -31,7 +32,7 @@ export default UsernamePage
export async function getStaticProps({ locale }) { export async function getStaticProps({ locale }) {
return { return {
props: { props: {
...(await serverSideTranslations(locale)), ...(await serverSideTranslations(locale, namespaces)),
}, },
} }
} }

View file

@ -1,8 +1,7 @@
import React from 'react'
import Link from 'next/link' import Link from 'next/link'
import FreeSewingIcon from 'shared/components/icons.mjs' import { FreeSewingIcon } from 'shared/components/icons.mjs'
const Breadcrumbs = ({ crumbs = [], title }) => export 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>
@ -30,5 +29,3 @@ const Breadcrumbs = ({ crumbs = [], title }) =>
))} ))}
</ul> </ul>
) : null ) : null
export default Breadcrumbs

View file

@ -1,5 +1,3 @@
const Code = ({ children }) => ( export const Code = ({ children = null }) => (
<code className="text-accent px-1 font-bold">{children}</code> <code className="text-accent px-1 font-bold">{children}</code>
) )
export default Code

View file

@ -1,7 +1,7 @@
import ReactDOMServer from 'react-dom/server' import ReactDOMServer from 'react-dom/server'
import { useState } from 'react' import { useState } from 'react'
import { CopyIcon } from 'shared/components/icons.mjs' import { CopyIcon } from 'shared/components/icons.mjs'
import { CopyToClipboard } from 'react-copy-to-clipboard' import { CopyToClipboard as Copy } from 'react-copy-to-clipboard'
const strip = (html) => const strip = (html) =>
typeof DOMParser === 'undefined' typeof DOMParser === 'undefined'
@ -13,19 +13,17 @@ const handleCopied = (setCopied) => {
setTimeout(() => setCopied(false), 1000) setTimeout(() => setCopied(false), 1000)
} }
const CopyToClipboardIcon = ({ content }) => { export const CopyToClipboard = ({ content }) => {
const [copied, setCopied] = useState(false) const [copied, setCopied] = useState(false)
const text = const text =
typeof content === 'string' ? content : strip(ReactDOMServer.renderToStaticMarkup(content)) typeof content === 'string' ? content : strip(ReactDOMServer.renderToStaticMarkup(content))
return ( return (
<CopyToClipboard text={text} onCopy={() => handleCopied(setCopied)}> <Copy text={text} onCopy={() => handleCopied(setCopied)}>
<button className={copied ? 'text-success' : ''}> <button className={copied ? 'text-success' : ''}>
<CopyIcon className="w-5 h-5" /> <CopyIcon className="w-5 h-5" />
</button> </button>
</CopyToClipboard> </Copy>
) )
} }
export default CopyToClipboardIcon

View file

@ -1,12 +1,8 @@
import PageLink from './page-link' import PageLink from './page-link.mjs'
import get from 'lodash.get' import get from 'lodash.get'
import useApp from 'site/hooks/useApp' import useApp from 'site/hooks/useApp.mjs'
const DocsLink = ({ slug }) => { export const DocsLink = ({ slug }) => {
const app = useApp() const app = useApp()
return <PageLink href={slug} txt={get(app.navigation, [...slug.split('/'), '__title'])} /> return <PageLink href={slug} txt={get(app.navigation, [...slug.split('/'), '__title'])} />
} }
export default DocsLink

View file

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import ResetButtons from './reset-buttons' import { ResetButtons } from './reset-buttons'
import { LogGroup } from 'shared/components/workbench/logs' import { LogGroup } from 'shared/components/workbench/logs'
import DefaultErrorView from './view' import { ErrorView as DefaultErrorView } from './view'
const ErrorView = (props) => { const ErrorView = (props) => {
if (props.children) return props.children if (props.children) return props.children
@ -22,7 +22,7 @@ const ErrorView = (props) => {
) )
} }
class ErrorBoundary extends React.Component { export class ErrorBoundary extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { hasError: false } this.state = { hasError: false }
@ -65,5 +65,3 @@ class ErrorBoundary extends React.Component {
} }
} }
} }
export default ErrorBoundary

View file

@ -1,10 +0,0 @@
import { useTranslation } from 'next-i18next'
export default function ({resetGist, undoGist}) {
const {t} = useTranslation(['app'])
return (<div className="flex flex-row gap-4 my-4">
<button className="btn btn-primary" onClick={undoGist}>{t('undo')}</button>
<button className="btn btn-primary" onClick={resetGist}>{t('reset_all')}</button>
</div>
)}

View file

@ -0,0 +1,18 @@
import { useTranslation } from 'next-i18next'
// FIXME: I feel this should be kept closer to where it's used
export const ResetButtons = ({ resetGist, undoGist }) => {
const { t } = useTranslation(['app'])
return (
<div className="flex flex-row gap-4 my-4">
<button className="btn btn-primary" onClick={undoGist}>
{t('undo')}
</button>
<button className="btn btn-primary" onClick={resetGist}>
{t('reset_all')}
</button>
</div>
)
}

View file

@ -1,59 +0,0 @@
import Robot from 'shared/components/robot/index.js'
import Popout from 'shared/components/popout.js'
import { useTranslation } from 'next-i18next'
import { useState } from 'react'
const Error = ({ children, inspectChildren}) => {
const { t } = useTranslation(['errors'])
const [share, setShare] = useState(false)
return (
<div className="max-w-4xl m-auto">
<Popout warning>
<div className="flex flex-row justify-between">
<div>
<h3>{t('errors:something')}</h3>
{children}
</div>
<Robot pose='fail' />
</div>
</Popout>
<Popout tip>
<h3>Would you like to report this problem?</h3>
<p>
You can help us <strong>make FreeSewing better by reporting this problem</strong>.
</p>
<p>If you choose to report this:</p>
<ul className="list-disc list-inside ml-4 text-xl">
<li>
We will compile a <strong>crash report</strong> that contains everything needed <strong>to recreate this problem</strong>
</li>
<li>
We will include <strong>personal data</strong> such as your <strong>username</strong>, <strong>
email address</strong> and <strong>measurements</strong>
</li>
<li>
We will share this report and the data in it with <a className="text-primary font-bold"
href="https://github.com/orgs/freesewing/teams/bughunters">FreeSewing's bughunters team</a> who will investigate the problem on your behalf
</li>
<li>Your personal data will <strong>not be shared publicly</strong></li>
</ul>
<div className="form-control">
<label className="cursor-pointer flex flex-row gap-4 my-4">
<input type="checkbox" checked={share} className="checkbox checkbox-primary" onChange={() => setShare(!share)}/>
<span className="label-text text-xl">I agree to the use of my personal data for the purposes outlined above</span>
</label>
</div>
<p>
<button disabled={!share} className="btn btn-primary">Report this</button>
</p>
<p>
If you prefer not to share any info, or want to investigate the problem yourself, you can do so:
</p>
{inspectChildren}
</Popout>
</div>)
}
export default Error

View file

@ -0,0 +1,76 @@
import { useTranslation } from 'next-i18next'
import { useState } from 'react'
import { Robot } from 'shared/components/robot/index.mjs'
import { Popout } from 'shared/components/popout.mjs'
export const ErrorView = ({ children, inspectChildren }) => {
const { t } = useTranslation(['errors'])
const [share, setShare] = useState(false)
return (
<div className="max-w-4xl m-auto">
<Popout warning>
<div className="flex flex-row justify-between">
<div>
<h3>{t('errors:something')}</h3>
{children}
</div>
<Robot pose="fail" />
</div>
</Popout>
<Popout tip>
<h3>Would you like to report this problem?</h3>
<p>
You can help us <strong>make FreeSewing better by reporting this problem</strong>.
</p>
<p>If you choose to report this:</p>
<ul className="list-disc list-inside ml-4 text-xl">
<li>
We will compile a <strong>crash report</strong> that contains everything needed{' '}
<strong>to recreate this problem</strong>
</li>
<li>
We will include <strong>personal data</strong> such as your <strong>username</strong>,{' '}
<strong>email address</strong> and <strong>measurements</strong>
</li>
<li>
We will share this report and the data in it with{' '}
<a
className="text-primary font-bold"
href="https://github.com/orgs/freesewing/teams/bughunters"
>
FreeSewing's bughunters team
</a>{' '}
who will investigate the problem on your behalf
</li>
<li>
Your personal data will <strong>not be shared publicly</strong>
</li>
</ul>
<div className="form-control">
<label className="cursor-pointer flex flex-row gap-4 my-4">
<input
type="checkbox"
checked={share}
className="checkbox checkbox-primary"
onChange={() => setShare(!share)}
/>
<span className="label-text text-xl">
I agree to the use of my personal data for the purposes outlined above
</span>
</label>
</div>
<p>
<button disabled={!share} className="btn btn-primary">
Report this
</button>
</p>
<p>
If you prefer not to share any info, or want to investigate the problem yourself, you can
do so:
</p>
{inspectChildren}
</Popout>
</div>
)
}

File diff suppressed because one or more lines are too long

View file

@ -1,17 +0,0 @@
import React from 'react'
import Highlight from 'shared/components/mdx/highlight.js'
import hljs from 'highlight.js/lib/common'
const Json = props => {
const code = props.js
? JSON.stringify(props.js, null, 2)
: props.children
return <Highlight
language='json'
raw={hljs.highlight(code, { language: 'json' }).value}
/>
}
export default Json

View file

@ -0,0 +1,9 @@
import React from 'react'
import Highlight from 'shared/components/mdx/highlight.mjs'
import hljs from 'highlight.js/lib/common'
export const Json = (props) => {
const code = props.js ? JSON.stringify(props.js, null, 2) : props.children
return <Highlight language="json" raw={hljs.highlight(code, { language: 'json' }).value} />
}

View file

@ -1,30 +0,0 @@
import { useState } from 'react'
const Lightbox = ({ cancel, children }) => {
const [ box, setBox ] = useState(false)
if (box) return (
<div className={`
fixed top-0 left-0 right-0 w-screen h-screen
bg-neutral bg-opacity-90 z-30
hover:cursor-zoom-out flex flex-col justify-center
`} onClick={() => setBox(false)}>
<div className="m-auto text-neutral-content lightbox" style={{
maxHeight: "calc(100vh - 6rem)",
maxWidth: "calc(100vw - 6rem)",
}}>
{children}
</div>
</div>
)
return (
<div
onClick={() => setBox(!box)}
className="hover:cursor-zoom-in"
>{children}</div>
)
}
export default Lightbox

View file

@ -0,0 +1,33 @@
import { useState } from 'react'
export const Lightbox = ({ cancel, children }) => {
const [box, setBox] = useState(false)
if (box)
return (
<div
className={`
fixed top-0 left-0 right-0 w-screen h-screen
bg-neutral bg-opacity-90 z-30
hover:cursor-zoom-out flex flex-col justify-center
`}
onClick={() => setBox(false)}
>
<div
className="m-auto text-neutral-content lightbox"
style={{
maxHeight: 'calc(100vh - 6rem)',
maxWidth: 'calc(100vw - 6rem)',
}}
>
{children}
</div>
</div>
)
return (
<div onClick={() => setBox(!box)} className="hover:cursor-zoom-in">
{children}
</div>
)
}

View file

@ -1,6 +1,6 @@
import Spinner from 'shared/components/spinner.js' import { Spinner } from 'shared/components/spinner.mjs'
const Loader = () => ( export const Loader = () => (
<div <div
className={` className={`
fixed top-0 left-0 right-0 w-screen h-screen fixed top-0 left-0 right-0 w-screen h-screen
@ -18,5 +18,3 @@ const Loader = () => (
</div> </div>
</div> </div>
) )
export default Loader

View file

@ -1,13 +1,15 @@
// Dependencies
import { Fragment } from 'react' import { Fragment } from 'react'
import { LocaleIcon, DownIcon } from 'shared/components/icons.mjs'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { Popover, Transition } from '@headlessui/react' import { Popover, Transition } from '@headlessui/react'
import Link from 'next/link' import Link from 'next/link'
// Components
import { I18nIcon, DownIcon } from 'shared/components/icons.mjs'
export const ns = ['locales'] export const ns = ['locales']
const LocalePicker = ({ iconOnly = false, bottom = false }) => { export const LocalePicker = ({ iconOnly = false, bottom = false }) => {
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const router = useRouter() const router = useRouter()
@ -18,7 +20,7 @@ const LocalePicker = ({ iconOnly = false, bottom = false }) => {
<Popover.Button <Popover.Button
className={`h-12 group border-0 inline-flex items-center px-3 text-base text-neural-content hover:bg-neutral-focus`} className={`h-12 group border-0 inline-flex items-center px-3 text-base text-neural-content hover:bg-neutral-focus`}
> >
<LocaleIcon /> <I18nIcon />
{!iconOnly && <span className="ml-4 font-medium capitalize">{t(router.locale)}</span>} {!iconOnly && <span className="ml-4 font-medium capitalize">{t(router.locale)}</span>}
<DownIcon className={`ml-2 h-5 w-5 ${bottom ? 'rotate-180' : ''}`} aria-hidden="true" /> <DownIcon className={`ml-2 h-5 w-5 ${bottom ? 'rotate-180' : ''}`} aria-hidden="true" />
</Popover.Button> </Popover.Button>
@ -61,5 +63,3 @@ const LocalePicker = ({ iconOnly = false, bottom = false }) => {
</Popover> </Popover>
) )
} }
export default LocalePicker

View file

@ -1,7 +0,0 @@
const CcByLogo = ({ color='currentColor', className="w-6 h-6" }) => (
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" className={className}>
<path d="M 15.979992,0 C 11.547725,0 7.7962273,1.5468447 4.7257722,4.6397397 1.5749793,7.8390824 0,11.625762 0,15.997998 c 0,4.372236 1.5749793,8.13178 4.7257722,11.27823 3.1507936,3.145777 6.9022908,4.71977 11.2542198,4.71977 4.405488,0 8.224496,-1.585888 11.454296,-4.759785 C 30.477964,24.223648 32,20.478011 32,15.997998 32,11.517982 30.452163,7.7326347 27.356259,4.6397397 24.257681,1.546858 20.465819,0 15.979992,0 Z m 0.04001,2.8790794 c 3.631518,0 6.715299,1.2794302 9.251469,3.8394394 2.562949,2.5325614 3.845442,5.6262482 3.845442,9.2794792 0,3.679334 -1.256021,6.733309 -3.765412,9.159434 -2.644631,2.613564 -5.753553,3.91947 -9.331499,3.91947 -3.579291,0 -6.6630856,-1.292667 -9.2514698,-3.879454 -2.5910732,-2.586786 -3.8834564,-5.653341 -3.8834564,-9.19945 0,-3.546782 1.3069629,-6.6398113 3.9234714,-9.2794792 C 9.3179574,4.1584963 12.388488,2.8790794 16.020008,2.8790794 Z m -0.09803,2.7870445 c -1.20598,0.042082 -2.16164,1.0322514 -2.16081,2.2388397 -9.9e-5,1.2364266 1.002285,2.2388084 2.23884,2.2388394 1.236554,-3.1e-5 2.238936,-1.0024128 2.238839,-2.2388394 9.8e-5,-1.2364264 -1.002285,-2.2388088 -2.238839,-2.2388397 -0.02601,-4.528e-4 -0.05202,-4.528e-4 -0.07803,0 z m -3.195198,5.3380011 c -0.5691,0 -1.032387,0.461333 -1.032387,1.032388 v 6.544454 h 1.826685 v 7.748906 h 4.95986 v -7.748906 h 1.824684 v -6.544454 c 0,-0.571042 -0.463288,-1.032389 -1.032389,-1.032388 z" fill={color} stroke="none" />
</svg>
)
export default CcByLogo

View file

@ -0,0 +1,9 @@
export const CCByLogo = ({ color = 'currentColor', className = 'w-6 h-6' }) => (
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" className={className}>
<path
d="M 15.979992,0 C 11.547725,0 7.7962273,1.5468447 4.7257722,4.6397397 1.5749793,7.8390824 0,11.625762 0,15.997998 c 0,4.372236 1.5749793,8.13178 4.7257722,11.27823 3.1507936,3.145777 6.9022908,4.71977 11.2542198,4.71977 4.405488,0 8.224496,-1.585888 11.454296,-4.759785 C 30.477964,24.223648 32,20.478011 32,15.997998 32,11.517982 30.452163,7.7326347 27.356259,4.6397397 24.257681,1.546858 20.465819,0 15.979992,0 Z m 0.04001,2.8790794 c 3.631518,0 6.715299,1.2794302 9.251469,3.8394394 2.562949,2.5325614 3.845442,5.6262482 3.845442,9.2794792 0,3.679334 -1.256021,6.733309 -3.765412,9.159434 -2.644631,2.613564 -5.753553,3.91947 -9.331499,3.91947 -3.579291,0 -6.6630856,-1.292667 -9.2514698,-3.879454 -2.5910732,-2.586786 -3.8834564,-5.653341 -3.8834564,-9.19945 0,-3.546782 1.3069629,-6.6398113 3.9234714,-9.2794792 C 9.3179574,4.1584963 12.388488,2.8790794 16.020008,2.8790794 Z m -0.09803,2.7870445 c -1.20598,0.042082 -2.16164,1.0322514 -2.16081,2.2388397 -9.9e-5,1.2364266 1.002285,2.2388084 2.23884,2.2388394 1.236554,-3.1e-5 2.238936,-1.0024128 2.238839,-2.2388394 9.8e-5,-1.2364264 -1.002285,-2.2388088 -2.238839,-2.2388397 -0.02601,-4.528e-4 -0.05202,-4.528e-4 -0.07803,0 z m -3.195198,5.3380011 c -0.5691,0 -1.032387,0.461333 -1.032387,1.032388 v 6.544454 h 1.826685 v 7.748906 h 4.95986 v -7.748906 h 1.824684 v -6.544454 c 0,-0.571042 -0.463288,-1.032389 -1.032389,-1.032388 z"
fill={color}
stroke="none"
/>
</svg>
)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,36 +0,0 @@
import React from 'react'
import { logoPath } from 'shared/components/icons/freesewing.js'
import colors from 'tailwindcss/colors'
const strokes = {
light: colors.neutral[300],
dark: colors.neutral[800],
hax0r: colors.lime[700],
lgbtq: colors.neutral[500],
trans: colors.neutral[500],
}
let step = 0
const Logo = ({ className = 'w-20 h-20', theme = 'light', stroke = false }) => {
const svgProps = {
xmlns: 'http://www.w3.org/2000/svg',
viewBox: '1 0 25 25',
className: className,
}
return (
<svg {...svgProps}>
<defs>
<path id="react-logo" d={logoPath} />
</defs>
<use
xlinkHref="#react-logo"
fill="none"
stroke={stroke || strokes[theme]}
strokeWidth="0.5"
/>
<use xlinkHref="#react-logo" fill="currentColor" stroke="none" />
</svg>
)
}
export default Logo

File diff suppressed because one or more lines are too long

View file

@ -1,7 +0,0 @@
const OsiLogo = ({ color='currentColor', className="w-6 h-6" }) => (
<svg viewBox="-0.5 -0.5 33 33" xmlns="http://www.w3.org/2000/svg" className={className}>
<path d="m16 15.993m1.9113 4.9789a5.333 5.333 0 1 0-3.8226 0l-3.5923 9.3604a15.359 15.359 0 1 1 11.007 0z" fill="none" stroke={color} strokeWidth="2"/>
</svg>
)
export default OsiLogo

View file

@ -0,0 +1,10 @@
export const OsiLogo = ({ color = 'currentColor', className = 'w-6 h-6' }) => (
<svg viewBox="-0.5 -0.5 33 33" xmlns="http://www.w3.org/2000/svg" className={className}>
<path
d="m16 15.993m1.9113 4.9789a5.333 5.333 0 1 0-3.8226 0l-3.5923 9.3604a15.359 15.359 0 1 1 11.007 0z"
fill="none"
stroke={color}
strokeWidth="2"
/>
</svg>
)

View file

@ -1,5 +1,5 @@
import { Tutorial } from '@freesewing/tutorial' import { Tutorial } from '@freesewing/tutorial'
import { Examples } from '@freesewing/examples' import { Examples as Pattern } from '@freesewing/examples'
import Svg from '../workbench/draft/svg' import Svg from '../workbench/draft/svg'
import Defs from '../workbench/draft/defs' import Defs from '../workbench/draft/defs'
import Stack from '../workbench/draft/stack' import Stack from '../workbench/draft/stack'
@ -11,7 +11,7 @@ import Md from 'react-markdown'
// head: 320, // head: 320,
// }, // },
//} //}
const ExamplesComponent = ({ app, part, caption, xray }) => { export const Examples = ({ app, part, caption, xray }) => {
// State for gist // State for gist
const { gist, unsetGist, updateGist } = useGist('examples-mdx', app) const { gist, unsetGist, updateGist } = useGist('examples-mdx', app)
@ -21,7 +21,7 @@ const ExamplesComponent = ({ app, part, caption, xray }) => {
} }
//const measurements = part.includes('tutorial') ? measurementSets.tutorial : {} //const measurements = part.includes('tutorial') ? measurementSets.tutorial : {}
const pattern = Examples const pattern = Pattern
const draft = new pattern({ const draft = new pattern({
only: [`examples.${part}`], only: [`examples.${part}`],
measurements: {}, measurements: {},
@ -61,5 +61,3 @@ const ExamplesComponent = ({ app, part, caption, xray }) => {
</div> </div>
) )
} }
export default ExamplesComponent

View file

@ -1,38 +0,0 @@
import Popout from 'shared/components/popout'
import Lightbox from 'shared/components/lightbox'
import ImageWrapper from 'shared/components/wrappers/img.js'
const Figure = props => {
const title = props?.title
? props.title
: props?.alt
? props.alt
: false
return (
<figure className="block my-4">
<Lightbox>
<ImageWrapper>
<img
src={props?.src}
alt={props?.alt || ''}
title={title || ''}
className="m-auto"
/>
</ImageWrapper>
{title
? <figcaption className="text-center italic mt-1">{title}</figcaption>
: (
<Popout fixme>
<h5>This image does not have an alt of title specified</h5>
<p>Please improve our documentation and fix this.</p>
</Popout>
)
}
</Lightbox>
</figure>
)
}
export default Figure

View file

@ -0,0 +1,25 @@
import { Popout } from 'shared/components/popout.mjs'
import { Lightbox } from 'shared/components/lightbox.mjs'
import { ImageWrapper } from 'shared/components/wrappers/img.mjs'
export const Figure = (props) => {
const title = props?.title ? props.title : props?.alt ? props.alt : false
return (
<figure className="block my-4">
<Lightbox>
<ImageWrapper>
<img src={props?.src} alt={props?.alt || ''} title={title || ''} className="m-auto" />
</ImageWrapper>
{title ? (
<figcaption className="text-center italic mt-1">{title}</figcaption>
) : (
<Popout fixme>
<h5>This image does not have an alt of title specified</h5>
<p>Please improve our documentation and fix this.</p>
</Popout>
)}
</Lightbox>
</figure>
)
}

View file

@ -1,5 +1,5 @@
import CopyToClipboard from 'shared/components/copy-to-clipboard' import { CopyToClipboard } from 'shared/components/copy-to-clipboard.mjs'
import StatusCode from './status-code.js' import { HttpStatusCode } from './http.mjs'
const names = { const names = {
js: 'Javascript', js: 'Javascript',
@ -9,7 +9,7 @@ const names = {
yaml: 'file.yaml', yaml: 'file.yaml',
} }
const Highlight = (props) => { export const Highlight = (props) => {
let language = 'txt' let language = 'txt'
let status = false let status = false
if (props.language) language = props.language if (props.language) language = props.language
@ -36,11 +36,9 @@ const Highlight = (props) => {
`} `}
> >
<span>{names[language] ? names[language] : language}</span> <span>{names[language] ? names[language] : language}</span>
{status ? <StatusCode status={status} /> : <CopyToClipboard content={props.children} />} {status ? <HttpStatusCode status={status} /> : <CopyToClipboard content={props.children} />}
</div> </div>
<pre {...preProps}>{props.children}</pre> <pre {...preProps}>{props.children}</pre>
</div> </div>
) )
} }
export default Highlight

View file

@ -5,7 +5,7 @@ const methodClasses = {
delete: 'bg-red-600 text-white', delete: 'bg-red-600 text-white',
} }
const Method = (props) => { export const HttpMethod = (props) => {
let method = false let method = false
for (const m in methodClasses) { for (const m in methodClasses) {
if (!method && props[m]) method = m.toUpperCase() if (!method && props[m]) method = m.toUpperCase()
@ -22,4 +22,20 @@ const Method = (props) => {
) )
} }
export default Method const statusClasses = {
2: 'bg-green-600 text-white',
4: 'bg-orange-500 text-white',
5: 'bg-red-600 text-white',
}
export const HttpStatusCode = ({ status }) => {
return (
<div
className={`my-1 text-xs inline-flex items-center font-bold leading-sm uppercase px-3 py-1 rounded-full ${
statusClasses['' + status.slice(0, 1)]
}`}
>
{status}
</div>
)
}

View file

@ -1,20 +1,19 @@
import Popout from '../popout.js' import { Popout } from 'shared/components/popout.mjs'
import Highlight from './highlight.js' import { Highlight } from './highlight.mjs'
import YouTube from './youtube.js' import { YouTube } from './youtube.mjs'
import Figure from './figure.js' import { Figure } from './figure.mjs'
import ReadMore from './read-more.js' import { ReadMore } from './read-more.mjs'
import { Tab, Tabs } from './tabs.js' import { Tab, Tabs } from './tabs.mjs'
import Example from './example.js' import { TabbedExample as Example } from './tabbed-example.mjs'
import Examples from './examples.js' import { Examples } from './examples.mjs'
import Method from './http-method.js' import { HttpMethod, HttpStatusCode } from './http.mjs'
import StatusCode from './status-code.js'
const Fixme = () => <p>FIXME</p> const Fixme = () => <p>FIXME</p>
const mdxCustomComponents = (app = false) => ({ export const MdxComponents = (app = false) => ({
// Custom components // Custom components
Method, Method: HttpMethod,
StatusCode, StatusCode: HttpStatusCode,
Comment: (props) => <Popout {...props} comment />, Comment: (props) => <Popout {...props} comment />,
Fixme: (props) => <Popout {...props} fixme />, Fixme: (props) => <Popout {...props} fixme />,
Link: (props) => <Popout {...props} link />, Link: (props) => <Popout {...props} link />,
@ -38,7 +37,3 @@ const mdxCustomComponents = (app = false) => ({
PatternDocs: Fixme, PatternDocs: Fixme,
PatternOptions: Fixme, PatternOptions: Fixme,
}) })
export default mdxCustomComponents
//<span className="bg-secondary px-2 mx-1 rounded text-primary-content bg-opacity-80">{children}</span>

View file

@ -74,7 +74,7 @@ const next = (app) => {
const renderPrevious = (node) => 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 shrink-0" />
<Link href={'/' + node.__slug} className="text-secondary break-words"> <Link href={'/' + node.__slug} className="text-secondary break-words">
{node.__linktitle} {node.__linktitle}
</Link> </Link>
@ -89,13 +89,13 @@ const renderNext = (node) =>
<Link href={'/' + node.__slug} className="text-right break-words"> <Link href={'/' + node.__slug} className="text-right break-words">
{node.__linktitle} {node.__linktitle}
</Link> </Link>
<RightIcon className="w-6 h-6" /> <RightIcon className="w-6 h-6 shrink-0" />
</div> </div>
) : ( ) : (
<span></span> <span></span>
) )
const PrevNext = ({ app }) => { export const PrevNext = ({ app }) => {
return ( return (
<div className="grid grid-cols-2 gap-4 border-t mt-12 py-2"> <div className="grid grid-cols-2 gap-4 border-t mt-12 py-2">
{renderPrevious(previous(app))} {renderPrevious(previous(app))}
@ -103,5 +103,3 @@ const PrevNext = ({ app }) => {
</div> </div>
) )
} }
export default PrevNext

View file

@ -7,7 +7,7 @@ const order = (obj) => orderBy(obj, ['__order', '__title'], ['asc', 'asc'])
const currentChildren = (current) => const currentChildren = (current) =>
Object.values(order(current)).filter((entry) => typeof entry === 'object') Object.values(order(current)).filter((entry) => typeof entry === 'object')
const ReadMore = (props) => { export 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
@ -28,5 +28,3 @@ const ReadMore = (props) => {
} }
return <ul>{list}</ul> return <ul>{list}</ul>
} }
export default ReadMore

View file

@ -1,19 +0,0 @@
const statusClasses = {
2: 'bg-green-600 text-white',
4: 'bg-orange-500 text-white',
5: 'bg-red-600 text-white',
}
const StatusCode = ({ status }) => {
return (
<div
className={`my-1 text-xs inline-flex items-center font-bold leading-sm uppercase px-3 py-1 rounded-full ${
statusClasses['' + status.slice(0, 1)]
}`}
>
{status}
</div>
)
}
export default StatusCode

View file

@ -1,4 +1,4 @@
import { Tab, Tabs } from './tabs.js' import { Tab, Tabs } from './tabs.mjs'
import Md from 'react-markdown' import Md from 'react-markdown'
import { pluginBundle } from '@freesewing/plugin-bundle' import { pluginBundle } from '@freesewing/plugin-bundle'
import { pluginFlip } from '@freesewing/plugin-flip' import { pluginFlip } from '@freesewing/plugin-flip'
@ -99,7 +99,7 @@ const buildExample = (children, settings = { margin: 5 }, tutorial = false, pape
} }
// Wrapper component dealing with the tabs and code view // Wrapper component dealing with the tabs and code view
const TabbedExample = ({ export const TabbedExample = ({
app, app,
children, children,
caption, caption,
@ -156,5 +156,3 @@ const TabbedExample = ({
</div> </div>
) )
} }
export default TabbedExample

View file

@ -19,7 +19,9 @@ export const Tabs = ({ tabs = '', active = 0, children }) => {
{tablist.map((title, tabId) => ( {tablist.map((title, tabId) => (
<button <button
key={tabId} key={tabId}
className={`text-xl font-bold capitalize tab tab-bordered grow ${activeTab === tabId ? 'tab-active' : ''}`} className={`text-xl font-bold capitalize tab tab-bordered grow ${
activeTab === tabId ? 'tab-active' : ''
}`}
onClick={() => setActiveTab(tabId)} onClick={() => setActiveTab(tabId)}
> >
{title} {title}

View file

@ -1,4 +1,4 @@
const YouTube = (props) => ( export const YouTube = (props) => (
<iframe <iframe
className="w-full aspect-video" className="w-full aspect-video"
src={ src={
@ -9,6 +9,3 @@ const YouTube = (props) => (
frameBorder="0" frameBorder="0"
/> />
) )
export default YouTube

View file

@ -1,16 +0,0 @@
const Modal = ({ cancel, children }) => (
<div className={`
fixed top-0 left-0 right-0 w-screen h-screen
bg-neutral bg-opacity-80 z-30
hover:cursor-pointer flex flex-col justify-center
`} onClick={cancel}>
<div className="m-auto text-neutral-content lightbox" style={{
maxHeight: "calc(100vh - 6rem)",
maxWidth: "calc(100vw - 6rem)",
}}>
{children}
</div>
</div>
)
export default Modal

View file

@ -0,0 +1,20 @@
export const Modal = ({ cancel, children }) => (
<div
className={`
fixed top-0 left-0 right-0 w-screen h-screen
bg-neutral bg-opacity-80 z-30
hover:cursor-pointer flex flex-col justify-center
`}
onClick={cancel}
>
<div
className="m-auto text-neutral-content lightbox"
style={{
maxHeight: 'calc(100vh - 6rem)',
maxWidth: 'calc(100vw - 6rem)',
}}
>
{children}
</div>
</div>
)

View file

@ -1,7 +1,8 @@
import PrimaryNavigation from './primary' import { PrimaryNavigation } from './primary.mjs'
const Aside = ({ app, slug, mobileOnly=false, before=[], after=[]}) => ( export const AsideNavigation = ({ app, slug, mobileOnly = false, before = [], after = [] }) => (
<aside className={` <aside
className={`
fixed top-0 right-0 h-screen w-screen fixed top-0 right-0 h-screen w-screen
overflow-y-auto z-20 overflow-y-auto z-20
bg-base-100 text-base-content md:bg-base-50 bg-base-100 text-base-content md:bg-base-50
@ -16,11 +17,10 @@ const Aside = ({ app, slug, mobileOnly=false, before=[], after=[]}) => (
xl:w-lg xl:border-0 xl:w-lg xl:border-0
2xl:pr-8 2xl:pr-8
${mobileOnly ? 'block md:hidden' : ''} ${mobileOnly ? 'block md:hidden' : ''}
`}> `}
>
{before} {before}
<PrimaryNavigation app={app} active={slug}/> <PrimaryNavigation app={app} active={slug} />
{after} {after}
</aside> </aside>
) )
export default Aside

View file

@ -12,7 +12,7 @@ import {
UserIcon, UserIcon,
CommunityIcon, CommunityIcon,
ShowcaseIcon, ShowcaseIcon,
} from 'shared/components/icons.mjks' } from 'shared/components/icons.mjs'
// 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']
@ -257,7 +257,7 @@ export const Icons = ({
return <ul className={ulClasses}>{output}</ul> return <ul className={ulClasses}>{output}</ul>
} }
const PrimaryMenu = ({ app, active, before = [], after = [] }) => ( export const PrimaryNavigation = ({ app, active, before = [], after = [] }) => (
<nav className="mb-12"> <nav className="mb-12">
{before} {before}
<Icons app={app} ulClasses="hidden md:block lg:hidden flex flex-col items-center" /> <Icons app={app} ulClasses="hidden md:block lg:hidden flex flex-col items-center" />
@ -265,5 +265,3 @@ const PrimaryMenu = ({ app, active, before = [], after = [] }) => (
{after} {after}
</nav> </nav>
) )
export default PrimaryMenu

View file

@ -1,6 +1,6 @@
import Link from 'next/link' import Link from 'next/link'
const PageLink = ({ href, txt, className = '' }) => ( export const PageLink = ({ href, txt, className = '' }) => (
<Link <Link
href={href} href={href}
className={`font-medium text-secondary hover:text-secondary-focus hover:underline ${className}`} className={`font-medium text-secondary hover:text-secondary-focus hover:underline ${className}`}
@ -9,5 +9,3 @@ const PageLink = ({ href, txt, className = '' }) => (
{txt} {txt}
</Link> </Link>
) )
export default PageLink

View file

@ -2,6 +2,8 @@ import { forwardRef } from 'react'
import { Menu } from '@headlessui/react' import { Menu } from '@headlessui/react'
import Link from 'next/link' import Link from 'next/link'
// FIXME: Is this even used at all?
/** 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 (

View file

@ -12,7 +12,7 @@ const colors = {
none: '', none: '',
} }
const Popout = (props) => { export const Popout = (props) => {
const [hide, setHide] = useState(false) const [hide, setHide] = useState(false)
if (hide) return null if (hide) return null
@ -75,5 +75,3 @@ const Popout = (props) => {
</div> </div>
) )
} }
export default Popout

View file

@ -1,5 +0,0 @@
const RawSpan = ({ html='' }) => <span
dangerouslySetInnerHTML={{ __html: html }}
/>
export default RawSpan

View file

@ -0,0 +1 @@
export const RawSpan = ({ html = '' }) => <span dangerouslySetInnerHTML={{ __html: html }} />

View file

@ -1,11 +1,9 @@
import themes from 'shared/themes/runtime.js' import { themes } from 'shared/themes/runtime.mjs'
const Ribbon = ({ loading = false, theme = 'light' }) => ( export const Ribbon = ({ loading = false, theme = 'light' }) => (
<div <div
className={`flex flex-col justify-between p-0 transition-transform className={`flex flex-col justify-between p-0 transition-transform
${loading ? 'theme-gradient loading h-1' : 'h-0 -translate-y-1'} ${loading ? 'theme-gradient loading h-1' : 'h-0 -translate-y-1'}
`} `}
></div> ></div>
) )
export default Ribbon

View file

@ -1,19 +1,20 @@
import poses from './poses' import { fail, ohno, shrug, shrug2, yay } from './poses.mjs'
// pose is one of: const poses = {
// fail, fail,
// ohno, ohno,
// shrug, shrug,
// shrug2, shrug2,
// yay yay,
}
const Robot = ({ export const Robot = ({
size = 124, size = 124,
viewBox = '0 0 500 500', viewBox = '0 0 500 500',
className = '', className = '',
pose = 'yay', pose = 'yay',
color = false, color = false,
embed = false embed = false,
}) => ( }) => (
<svg <svg
className={className || ''} className={className || ''}
@ -25,5 +26,3 @@ const Robot = ({
<path stroke="none" fill={color ? color : 'currentColor'} d={poses[pose]} /> <path stroke="none" fill={color ? color : 'currentColor'} d={poses[pose]} />
</svg> </svg>
) )
export default Robot

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show more