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 { 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 { Icons, welcomeSteps } from '../shared.js'
import Popout from 'shared/components/popout.js'
import Markdown from 'react-markdown'
import { Icons, welcomeSteps } from '../shared.mjs'
import { Popout } from 'shared/components/popout.mjs'
export const ns = ['bio']
@ -18,7 +20,7 @@ const Tab = ({ id, activeTab, setActiveTab, t }) => (
</button>
)
const UsernameSettings = ({ app, title = false, welcome = false }) => {
export const BioSettings = ({ app, title = false, welcome = false }) => {
const backend = useBackend(app)
const { t } = useTranslation(ns)
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 { 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 { Choice, Icons, welcomeSteps } from '../shared.js'
import { Choice, Icons, welcomeSteps } from '../shared.mjs'
export const ns = ['compare']

View file

@ -1,8 +1,10 @@
// Hooks
import { useState } from 'react'
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 { Choice, Icons, welcomeSteps } from '../shared.js'
import { Choice, Icons, welcomeSteps } from '../shared.mjs'
export const ns = ['control']

View file

@ -1,13 +1,15 @@
// Hooks
import { useState, useCallback } from 'react'
import { useTranslation } from 'next-i18next'
import useBackend from 'site/hooks/useBackend.js'
import Link from 'next/link'
import { Icons, welcomeSteps } from '../shared.js'
import { useBackend } from 'site/hooks/useBackend.mjs'
import { useDropzone } from 'react-dropzone'
// Components
import Link from 'next/link'
import { Icons, welcomeSteps } from '../shared.mjs'
export const ns = ['img']
const ImgSettings = ({ app, title = false, welcome = false }) => {
export const ImgSettings = ({ app, title = false, welcome = false }) => {
const backend = useBackend(app)
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 { 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 { Choice, Icons, welcomeSteps } from '../shared.js'
import { Choice, Icons, welcomeSteps } from '../shared.mjs'
export const ns = ['newsletter']

View file

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

View file

@ -1,12 +1,14 @@
// Hooks
import { useState } from 'react'
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 { Choice, Icons, welcomeSteps } from '../shared.js'
import { Choice, Icons, welcomeSteps } from '../shared.mjs'
export const ns = ['units']
const UnitsSettings = ({ app, title = false, welcome = false }) => {
export const UnitsSettings = ({ app, title = false, welcome = false }) => {
const backend = useBackend(app)
const { t } = useTranslation(ns)
const [selection, setSelection] = useState(app.account?.imperial === true ? 'imperial' : 'metric')
@ -25,7 +27,7 @@ const UnitsSettings = ({ app, title = false, welcome = false }) => {
return (
<>
{title ? <h1 className="text-4xl">{t('title')}</h1> : null}
{title ? <h1 className="text-4xl">{t('title')}</h1> : <h1></h1>}
{['metric', 'imperial'].map((val) => (
<Choice val={val} t={t} update={update} current={selection} bool key={val}>
<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 { 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 { Icons, welcomeSteps } from '../shared.js'
import OkIcon from 'shared/components/icons/ok.js'
import NoIcon from 'shared/components/icons/no.js'
import { Icons, welcomeSteps } from '../shared.mjs'
import { OkIcon, NoIcon } from 'shared/components/icons.mjs'
export const ns = ['username']
const UsernameSettings = ({ app, title = false, welcome = false }) => {
export const UsernameSettings = ({ app, title = false, welcome = false }) => {
const backend = useBackend(app)
const { t } = useTranslation(ns)
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 { useTranslation } from 'next-i18next'
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 { strapiHost } from 'shared/config/freesewing.mjs'
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 { 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 { freeSewingConfig } from 'site/freesewing.config.js'
import HelpIcon from 'shared/components/icons/help.js'
import DiscordIcon from 'shared/components/icons/discord.js'
import FacebookIcon from 'shared/components/icons/facebook.js'
import GithubIcon from 'shared/components/icons/github.js'
import InstagramIcon from 'shared/components/icons/instagram.js'
import RedditIcon from 'shared/components/icons/reddit.js'
import TwitterIcon from 'shared/components/icons/twitter.js'
import { freeSewingConfig } from 'site/freesewing.config.mjs'
import {
HelpIcon,
DiscordIcon,
FacebookIcon,
GithubIcon,
InstagramIcon,
RedditIcon,
TwitterIcon,
} from 'shared/components/icons.mjs'
const icon = { className: 'w-8 lg:w-12 h-8 lg:h-12' }
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="max-w-md m-auto">
<div>
<CreativeCommonsLogo className="w-64 m-auto" />
<CCLogo className="w-64 m-auto" />
</div>
<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">
{t('cc')}
</p>
@ -138,7 +139,7 @@ export const Footer = ({ app }) => {
{/* 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="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">
<WordMark />
</h5>

View file

@ -1,11 +1,9 @@
import { useState, useEffect } from 'react'
import ThemePicker, { ns as themeNs } from 'shared/components/theme-picker/index.js'
import LocalePicker, { ns as localeNs } from 'shared/components/locale-picker/index.js'
import CloseIcon from 'shared/components/icons/close.js'
import MenuIcon from 'shared/components/icons/menu.js'
import SearchIcon from 'shared/components/icons/search.js'
import Ribbon from 'shared/components/ribbon.js'
import { WordMark } from 'shared/components/wordmark.js'
import { ThemePicker, ns as themeNs } from 'shared/components/theme-picker/index.mjs'
import { LocalePicker, ns as localeNs } from 'shared/components/locale-picker/index.mjs'
import { CloseIcon, MenuIcon, SearchIcon } from 'shared/components/icons.mjs'
import { Ribbon } from 'shared/components/ribbon.mjs'
import { WordMark } from 'shared/components/wordmark.mjs'
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 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 slug = router.asPath.slice(1)
@ -18,7 +18,7 @@ const DefaultLayout = ({ app, title = false, children = [] }) => {
lg:block
`}
>
<Aside app={app} slug={slug} />
<AsideNavigation app={app} slug={slug} />
</section>
<section className="py-8 lg:py-16 px-6 xl:pl-8 2xl:pl-16">
<div>
@ -29,5 +29,3 @@ const DefaultLayout = ({ app, title = false, children = [] }) => {
</div>
)
}
export default DefaultLayout

View file

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

View file

@ -10,14 +10,14 @@ const PatternMeasurements = ({ pattern, before=null, after=null }) => {
for (const m of configs[pattern].measurements) {
measurements[m] = {
title: t(`measurements.${m}`),
required: true
required: true,
}
}
for (const m of configs[pattern].measurements || []) {
measurements[m] = {
name: m,
title: t(`measurements:${m}`),
required: false
required: false,
}
}
@ -28,7 +28,7 @@ const PatternMeasurements = ({ pattern, before=null, after=null }) => {
<div>
{before}
<ol className="list-inside ml-8 my-4">
{orderBy(measurements, ['title'], ['asc']).map(m => (
{orderBy(measurements, ['title'], ['asc']).map((m) => (
<li key={m.name}>
<PageLink href={'/docs/measurements/' + m.name.toLowerCase()} txt={m.title} />
</li>

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
className={`
fixed top-0 right-0 h-screen w-screen
@ -23,5 +23,3 @@ const Aside = ({ app, slug, mobileOnly = false, before = [], after = [] }) => (
{after}
</aside>
)
export default Aside

View file

@ -1,8 +1,8 @@
import { useState, useEffect } from 'react'
import Link from 'next/link'
import orderBy from 'lodash.orderby'
import FreeSewingIcon from 'shared/components/icons/freesewing.js'
import TopLevel from './top-level.js'
import { FreeSewingIcon } from 'shared/components/icons.mjs'
import { TopLevelNavigation as TopLevel } from './top-level.mjs'
/* helper method to order nav entries */
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>
}
const PrimaryMenu = ({ app, active, before = [], after = [] }) => (
export const PrimaryNavigation = ({ app, active, before = [], after = [] }) => (
<nav className="mb-12">
{before}
<Navigation app={app} active={active} />
{after}
</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,
connectSearchBox,
} 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)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -9,7 +9,7 @@ const api = axios.create({
timeout: 3000,
})
function useBackend(app) {
export function useBackend(app) {
const auth = {
headers: { Authorization: 'Bearer ' + app.token },
}
@ -107,5 +107,3 @@ function useBackend(app) {
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 Bugsnag from '@bugsnag/js'
import BugsnagPluginReact from '@bugsnag/plugin-react'
import { freeSewingConfig } from 'site/freesewing.config.js'
import { freeSewingConfig } from 'site/freesewing.config.mjs'
Bugsnag.start({
apiKey: freeSewingConfig.bugsnag.key,

View file

@ -1,22 +1,24 @@
import { useEffect } from 'react'
import Page from 'site/components/wrappers/page.js'
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 WelcomeWrapper from 'site/components/wrappers/welcome.js'
import Spinner from 'shared/components/icons/spinner.js'
// Hooks
import { useEffect, useState } from 'react'
import { useApp } from 'site/hooks/useApp.mjs'
import { useBackend } from 'site/hooks/useBackend.mjs'
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 {
GdprProfileDetails,
GdprMeasurementsDetails,
ns as gdprNs,
} from 'site/components/gdpr/details.js'
import Robot from 'shared/components/robot/index.js'
} from 'site/components/gdpr/details.mjs'
// Translation namespaces used on this page
const ns = Array.from(new Set([...gdprNs, 'confirm', 'locales', 'themes']))
@ -110,11 +112,11 @@ const ConfirmSignUpPage = (props) => {
// Short-circuit errors
if (error)
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}>
<SignupLinkExpired />
</WelcomeWrapper>
</Page>
</PageWrapper>
)
const partA = (
@ -181,7 +183,7 @@ const ConfirmSignUpPage = (props) => {
)
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}>
{ready ? (
<>
@ -223,7 +225,7 @@ const ConfirmSignUpPage = (props) => {
</Link>
</p>
</WelcomeWrapper>
</Page>
</PageWrapper>
)
}

View file

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

View file

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

View file

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

View file

@ -1,12 +1,15 @@
import Page from 'site/components/wrappers/page.js'
import useApp from 'site/hooks/useApp.js'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
// Hooks
import { useApp } from 'site/hooks/useApp.mjs'
import { useTranslation } from 'next-i18next'
import Layout from 'site/components/layouts/bare'
import Link from 'next/link'
import { useState } from 'react'
// Dependencies
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
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'
@ -29,7 +32,7 @@ const SignInPage = (props) => {
const clearUsername = () => app.setUsername(false)
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}>
<h1 className="text-neutral-content font-light text-3xl mb-4 pb-0 text-center">
{t('welcomeName', { name: app.username || '' })}
@ -82,7 +85,7 @@ const SignInPage = (props) => {
</Link>
</p>
</SusiWrapper>
</Page>
</PageWrapper>
)
}

View file

@ -1,15 +1,18 @@
import Page from 'site/components/wrappers/page.js'
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'
// Hooks
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 SusiWrapper from 'site/components/wrappers/susi.js'
import Spinner from 'shared/components/icons/spinner.js'
import Robot from 'shared/components/robot/index.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'
import { Spinner } from 'shared/components/spinner.mjs'
import { Robot } from 'shared/components/robot/index.mjs'
// Translation namespaces used on this page
const namespaces = ['signup', 'errors']
@ -59,7 +62,7 @@ const SignUpPage = (props) => {
const loadingClasses = app.loading ? 'opacity-50' : ''
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'}>
<h1 className={`text-neutral-content font-light text-3xl mb-0 pb-0 ${loadingClasses}`}>
{result ? (
@ -152,7 +155,7 @@ const SignUpPage = (props) => {
</>
)}
</SusiWrapper>
</Page>
</PageWrapper>
)
}

View file

@ -1,6 +1,8 @@
import Page from 'site/components/wrappers/page.js'
import useApp from 'site/hooks/useApp.js'
import Popout from 'shared/components/popout.js'
// Hooks
import { useApp } from 'site/hooks/useApp.mjs'
// Components
import { PageWrapper } from 'site/components/wrappers/page.mjs'
import { Popout } from 'shared/components/popout.mjs'
const TypographyPage = (props) => {
const app = useApp(props)
@ -13,7 +15,7 @@ const TypographyPage = (props) => {
)
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">
<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>
@ -84,7 +86,7 @@ const TypographyPage = (props) => {
)
})}
</div>
</Page>
</PageWrapper>
)
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,8 +1,7 @@
import React from 'react'
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 ? (
<ul className="flex flex-row flex-wrap gap-2 font-bold">
<li>
@ -30,5 +29,3 @@ const Breadcrumbs = ({ crumbs = [], title }) =>
))}
</ul>
) : 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>
)
export default Code

View file

@ -1,7 +1,7 @@
import ReactDOMServer from 'react-dom/server'
import { useState } from 'react'
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) =>
typeof DOMParser === 'undefined'
@ -13,19 +13,17 @@ const handleCopied = (setCopied) => {
setTimeout(() => setCopied(false), 1000)
}
const CopyToClipboardIcon = ({ content }) => {
export const CopyToClipboard = ({ content }) => {
const [copied, setCopied] = useState(false)
const text =
typeof content === 'string' ? content : strip(ReactDOMServer.renderToStaticMarkup(content))
return (
<CopyToClipboard text={text} onCopy={() => handleCopied(setCopied)}>
<Copy text={text} onCopy={() => handleCopied(setCopied)}>
<button className={copied ? 'text-success' : ''}>
<CopyIcon className="w-5 h-5" />
</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 useApp from 'site/hooks/useApp'
import useApp from 'site/hooks/useApp.mjs'
const DocsLink = ({ slug }) => {
export const DocsLink = ({ slug }) => {
const app = useApp()
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 ResetButtons from './reset-buttons'
import { ResetButtons } from './reset-buttons'
import { LogGroup } from 'shared/components/workbench/logs'
import DefaultErrorView from './view'
import { ErrorView as DefaultErrorView } from './view'
const ErrorView = (props) => {
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) {
super(props)
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
className={`
fixed top-0 left-0 right-0 w-screen h-screen
@ -18,5 +18,3 @@ const Loader = () => (
</div>
</div>
)
export default Loader

View file

@ -1,13 +1,15 @@
// Dependencies
import { Fragment } from 'react'
import { LocaleIcon, DownIcon } from 'shared/components/icons.mjs'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
import { Popover, Transition } from '@headlessui/react'
import Link from 'next/link'
// Components
import { I18nIcon, DownIcon } from 'shared/components/icons.mjs'
export const ns = ['locales']
const LocalePicker = ({ iconOnly = false, bottom = false }) => {
export const LocalePicker = ({ iconOnly = false, bottom = false }) => {
const { t } = useTranslation(ns)
const router = useRouter()
@ -18,7 +20,7 @@ const LocalePicker = ({ iconOnly = false, bottom = false }) => {
<Popover.Button
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>}
<DownIcon className={`ml-2 h-5 w-5 ${bottom ? 'rotate-180' : ''}`} aria-hidden="true" />
</Popover.Button>
@ -61,5 +63,3 @@ const LocalePicker = ({ iconOnly = false, bottom = false }) => {
</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 { Examples } from '@freesewing/examples'
import { Examples as Pattern } from '@freesewing/examples'
import Svg from '../workbench/draft/svg'
import Defs from '../workbench/draft/defs'
import Stack from '../workbench/draft/stack'
@ -11,7 +11,7 @@ import Md from 'react-markdown'
// head: 320,
// },
//}
const ExamplesComponent = ({ app, part, caption, xray }) => {
export const Examples = ({ app, part, caption, xray }) => {
// State for gist
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 pattern = Examples
const pattern = Pattern
const draft = new pattern({
only: [`examples.${part}`],
measurements: {},
@ -61,5 +61,3 @@ const ExamplesComponent = ({ app, part, caption, xray }) => {
</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 StatusCode from './status-code.js'
import { CopyToClipboard } from 'shared/components/copy-to-clipboard.mjs'
import { HttpStatusCode } from './http.mjs'
const names = {
js: 'Javascript',
@ -9,7 +9,7 @@ const names = {
yaml: 'file.yaml',
}
const Highlight = (props) => {
export const Highlight = (props) => {
let language = 'txt'
let status = false
if (props.language) language = props.language
@ -36,11 +36,9 @@ const Highlight = (props) => {
`}
>
<span>{names[language] ? names[language] : language}</span>
{status ? <StatusCode status={status} /> : <CopyToClipboard content={props.children} />}
{status ? <HttpStatusCode status={status} /> : <CopyToClipboard content={props.children} />}
</div>
<pre {...preProps}>{props.children}</pre>
</div>
)
}
export default Highlight

View file

@ -5,7 +5,7 @@ const methodClasses = {
delete: 'bg-red-600 text-white',
}
const Method = (props) => {
export const HttpMethod = (props) => {
let method = false
for (const m in methodClasses) {
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 Highlight from './highlight.js'
import YouTube from './youtube.js'
import Figure from './figure.js'
import ReadMore from './read-more.js'
import { Tab, Tabs } from './tabs.js'
import Example from './example.js'
import Examples from './examples.js'
import Method from './http-method.js'
import StatusCode from './status-code.js'
import { Popout } from 'shared/components/popout.mjs'
import { Highlight } from './highlight.mjs'
import { YouTube } from './youtube.mjs'
import { Figure } from './figure.mjs'
import { ReadMore } from './read-more.mjs'
import { Tab, Tabs } from './tabs.mjs'
import { TabbedExample as Example } from './tabbed-example.mjs'
import { Examples } from './examples.mjs'
import { HttpMethod, HttpStatusCode } from './http.mjs'
const Fixme = () => <p>FIXME</p>
const mdxCustomComponents = (app = false) => ({
export const MdxComponents = (app = false) => ({
// Custom components
Method,
StatusCode,
Method: HttpMethod,
StatusCode: HttpStatusCode,
Comment: (props) => <Popout {...props} comment />,
Fixme: (props) => <Popout {...props} fixme />,
Link: (props) => <Popout {...props} link />,
@ -38,7 +37,3 @@ const mdxCustomComponents = (app = false) => ({
PatternDocs: 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) =>
node ? (
<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">
{node.__linktitle}
</Link>
@ -89,13 +89,13 @@ const renderNext = (node) =>
<Link href={'/' + node.__slug} className="text-right break-words">
{node.__linktitle}
</Link>
<RightIcon className="w-6 h-6" />
<RightIcon className="w-6 h-6 shrink-0" />
</div>
) : (
<span></span>
)
const PrevNext = ({ app }) => {
export const PrevNext = ({ app }) => {
return (
<div className="grid grid-cols-2 gap-4 border-t mt-12 py-2">
{renderPrevious(previous(app))}
@ -103,5 +103,3 @@ const PrevNext = ({ app }) => {
</div>
)
}
export default PrevNext

View file

@ -7,7 +7,7 @@ const order = (obj) => orderBy(obj, ['__order', '__title'], ['asc', 'asc'])
const currentChildren = (current) =>
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
if (!props.app) return null
@ -28,5 +28,3 @@ const ReadMore = (props) => {
}
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 { pluginBundle } from '@freesewing/plugin-bundle'
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
const TabbedExample = ({
export const TabbedExample = ({
app,
children,
caption,
@ -156,5 +156,3 @@ const TabbedExample = ({
</div>
)
}
export default TabbedExample

View file

@ -19,7 +19,9 @@ export const Tabs = ({ tabs = '', active = 0, children }) => {
{tablist.map((title, tabId) => (
<button
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)}
>
{title}

View file

@ -1,4 +1,4 @@
const YouTube = (props) => (
export const YouTube = (props) => (
<iframe
className="w-full aspect-video"
src={
@ -9,6 +9,3 @@ const YouTube = (props) => (
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=[]}) => (
<aside className={`
export const AsideNavigation = ({ app, slug, mobileOnly = false, before = [], after = [] }) => (
<aside
className={`
fixed top-0 right-0 h-screen w-screen
overflow-y-auto z-20
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
2xl:pr-8
${mobileOnly ? 'block md:hidden' : ''}
`}>
`}
>
{before}
<PrimaryNavigation app={app} active={slug} />
{after}
</aside>
)
export default Aside

View file

@ -12,7 +12,7 @@ import {
UserIcon,
CommunityIcon,
ShowcaseIcon,
} from 'shared/components/icons.mjks'
} from 'shared/components/icons.mjs'
// Don't show children for blog and showcase posts
const keepClosed = ['blog', 'showcase']
@ -257,7 +257,7 @@ export const Icons = ({
return <ul className={ulClasses}>{output}</ul>
}
const PrimaryMenu = ({ app, active, before = [], after = [] }) => (
export const PrimaryNavigation = ({ app, active, before = [], after = [] }) => (
<nav className="mb-12">
{before}
<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}
</nav>
)
export default PrimaryMenu

View file

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

View file

@ -2,6 +2,8 @@ import { forwardRef } from 'react'
import { Menu } from '@headlessui/react'
import Link from 'next/link'
// FIXME: Is this even used at all?
/** an accessible dropdown menu for use by picker components */
export const Picker = ({ Icon, className, title, ariaLabel, iconOnly = false, children, end }) => {
return (

View file

@ -12,7 +12,7 @@ const colors = {
none: '',
}
const Popout = (props) => {
export const Popout = (props) => {
const [hide, setHide] = useState(false)
if (hide) return null
@ -75,5 +75,3 @@ const Popout = (props) => {
</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
className={`flex flex-col justify-between p-0 transition-transform
${loading ? 'theme-gradient loading h-1' : 'h-0 -translate-y-1'}
`}
></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:
// fail,
// ohno,
// shrug,
// shrug2,
// yay
const poses = {
fail,
ohno,
shrug,
shrug2,
yay,
}
const Robot = ({
export const Robot = ({
size = 124,
viewBox = '0 0 500 500',
className = '',
pose = 'yay',
color = false,
embed = false
embed = false,
}) => (
<svg
className={className || ''}
@ -25,5 +26,3 @@ const Robot = ({
<path stroke="none" fill={color ? color : 'currentColor'} d={poses[pose]} />
</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