feat(fs.dev): Added theme support
This commit is contained in:
parent
84ffe26a76
commit
e1ecd0cb98
26 changed files with 834 additions and 96 deletions
|
@ -114,6 +114,8 @@
|
||||||
},
|
},
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jsonfile": "^6.1.0"
|
"jsonfile": "^6.1.0",
|
||||||
|
"postcss": "^8.4.4",
|
||||||
|
"tailwindcss": "^3.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
42
packages/freesewing.dev/hooks/useApp.js
Normal file
42
packages/freesewing.dev/hooks/useApp.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import { useState } from 'react'
|
||||||
|
// Stores state in local storage
|
||||||
|
import useLocalStorage from 'shared/hooks/useLocalStorage.js'
|
||||||
|
|
||||||
|
function useApp(full = true) {
|
||||||
|
|
||||||
|
// User color scheme preference
|
||||||
|
const prefersDarkMode = (typeof window !== 'undefined' && typeof window.matchMedia === 'function')
|
||||||
|
? window.matchMedia(`(prefers-color-scheme: dark`).matches
|
||||||
|
: null
|
||||||
|
|
||||||
|
// React State
|
||||||
|
const [primaryMenu, setPrimaryMenu] = useState(false)
|
||||||
|
|
||||||
|
// Persistent state
|
||||||
|
const [account, setAccount] = useLocalStorage('account', { username: false })
|
||||||
|
const [theme, setTheme] = useLocalStorage('theme', prefersDarkMode ? 'dark' : 'light')
|
||||||
|
|
||||||
|
|
||||||
|
// State methods
|
||||||
|
const togglePrimaryMenu = () => setPrimaryMenu(!primaryMenu)
|
||||||
|
const openPrimaryMenu = () => setPrimaryMenu(true)
|
||||||
|
const closePrimaryMenu = () => setPrimaryMenu(false)
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
// State
|
||||||
|
primaryMenu,
|
||||||
|
theme,
|
||||||
|
|
||||||
|
// State setters
|
||||||
|
setPrimaryMenu,
|
||||||
|
setTheme,
|
||||||
|
|
||||||
|
// State handlers
|
||||||
|
togglePrimaryMenu,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useApp
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import config from '../freesewing.shared/config/next.mjs'
|
import configBuilder from '../freesewing.shared/config/next.mjs'
|
||||||
|
|
||||||
export default config
|
export default configBuilder('dev')
|
||||||
|
|
|
@ -16,12 +16,13 @@
|
||||||
"@mdx-js/runtime": "next",
|
"@mdx-js/runtime": "next",
|
||||||
"daisyui": "^1.16.2",
|
"daisyui": "^1.16.2",
|
||||||
"next": "latest",
|
"next": "latest",
|
||||||
|
"react-swipeable": "^6.2.0",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"remark-jargon": "^2.19.5"
|
"remark-jargon": "^2.19.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "^10.4.0",
|
"autoprefixer": "^10.4.0",
|
||||||
"postcss": "^8.4.4",
|
"postcss": "^8.4.4",
|
||||||
"tailwindcss": "^3.0.0"
|
"tailwindcss": "^3.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import '../styles/globals.css'
|
import 'shared/styles/globals.css'
|
||||||
|
|
||||||
const FreeSewingDev = ({ Component, pageProps }) => <Component {...pageProps} />
|
const FreeSewingDev = ({ Component, pageProps }) => <Component {...pageProps} />
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,19 @@
|
||||||
import Head from 'next/head'
|
import Page from 'shared/components/wrappers/page.js'
|
||||||
import Image from 'next/image'
|
import useApp from 'site/hooks/useApp.js'
|
||||||
|
import ThemePicker from 'shared/components/theme-picker.js'
|
||||||
|
|
||||||
export default function Home() {
|
export default (props) => {
|
||||||
|
const app = useApp()
|
||||||
return (
|
return (
|
||||||
<div>
|
<Page app={app} title='This is not a homepage'>
|
||||||
<Head>
|
<p className='px-8'>
|
||||||
<title>Create Next App</title>
|
<button
|
||||||
<meta name="description" content="Generated by create next app" />
|
className='btn btn-primary'
|
||||||
<link rel="icon" href="/favicon.ico" />
|
onClick={() => app.theme === 'dark' ? app.setTheme('light') : app.setTheme('dark')}
|
||||||
</Head>
|
>Toggle</button>
|
||||||
|
|
||||||
<main className="px-1">
|
|
||||||
<h1>
|
|
||||||
Welcome to <a href="https://nextjs.org">Next.js!</a>
|
|
||||||
</h1>
|
|
||||||
<button className="btn btn-primary">daisyUI Button</button>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Get started by editing{' '}
|
|
||||||
<code>pages/index.js</code>
|
|
||||||
</p>
|
</p>
|
||||||
|
<ThemePicker app={app} />
|
||||||
</main>
|
</Page>
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
packages/freesewing.shared/components/elements/h1.js
Normal file
13
packages/freesewing.shared/components/elements/h1.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
const H1 = props => (
|
||||||
|
<h1
|
||||||
|
className={`
|
||||||
|
text-4xl py-4 font-bold
|
||||||
|
lg:text-6xl
|
||||||
|
`}
|
||||||
|
style={{letterSpacing: '-0.15rem'}}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</h1>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default H1
|
84
packages/freesewing.shared/components/icon/icons.js
Normal file
84
packages/freesewing.shared/components/icon/icons.js
Normal file
File diff suppressed because one or more lines are too long
29
packages/freesewing.shared/components/icon/index.js
Normal file
29
packages/freesewing.shared/components/icon/index.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import icons from './icons'
|
||||||
|
|
||||||
|
const Icon = ({
|
||||||
|
size = 24,
|
||||||
|
icon = 'github',
|
||||||
|
color = false,
|
||||||
|
className = '',
|
||||||
|
embed = false
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
const svgProps = {
|
||||||
|
xmlns: 'http://www.w3.org/2000/svg',
|
||||||
|
viewBox: '0 0 24 24',
|
||||||
|
className: className,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size && !embed) {
|
||||||
|
svgProps.width = size
|
||||||
|
svgProps.height = size
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg {...svgProps}>
|
||||||
|
<path stroke="none" fill={color ? color : 'currentColor'} d={icons[icon]} />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Icon
|
60
packages/freesewing.shared/components/layouts/default.js
Normal file
60
packages/freesewing.shared/components/layouts/default.js
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import { useState } from 'react'
|
||||||
|
// Shared components
|
||||||
|
import PrimaryMenu from 'shared/components/navigation/primary'
|
||||||
|
//import Breadcrumbs from '@/shared/components/navigation/breadcrumbs'
|
||||||
|
import H1 from 'shared/components/elements/h1'
|
||||||
|
//import Icon from '@/shared/components/icon'
|
||||||
|
//import Button from '@/shared/components/elements/button'
|
||||||
|
// Site components
|
||||||
|
//import NavigationButtons from '@/site/components/navigation-buttons'
|
||||||
|
//import Search from '@/site/components/search'
|
||||||
|
|
||||||
|
const iconSize= 48
|
||||||
|
|
||||||
|
const DefaultLayout = props => {
|
||||||
|
|
||||||
|
const [leftNav, setLeftNav] = useState(false)
|
||||||
|
|
||||||
|
const toggleLeftNav = () => setLeftNav(!leftNav)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`
|
||||||
|
flex flex-col justify-between
|
||||||
|
min-h-screen
|
||||||
|
bg-base-100
|
||||||
|
`} data-theme={props.app.theme}>
|
||||||
|
<header className={`
|
||||||
|
bg-primary
|
||||||
|
p-4
|
||||||
|
block
|
||||||
|
sm:hidden
|
||||||
|
`}>
|
||||||
|
header
|
||||||
|
</header>
|
||||||
|
<main className={`
|
||||||
|
grow flex flex-row
|
||||||
|
sm:py-8
|
||||||
|
`}>
|
||||||
|
<aside className={`
|
||||||
|
fixed top-0 right-0
|
||||||
|
${props.app.primaryMenu ? '' : 'translate-x-[-100%]'} transition-transform
|
||||||
|
sm:relative sm:transform-none
|
||||||
|
h-screen
|
||||||
|
p-4
|
||||||
|
w-screen
|
||||||
|
sm:max-w-[38.2%]
|
||||||
|
`}>
|
||||||
|
<PrimaryMenu />
|
||||||
|
<button className='btn btn-primary' onClick={() => props.app.togglePrimaryMenu()}>Toggle</button>
|
||||||
|
</aside>
|
||||||
|
<section>
|
||||||
|
<H1>{props.title}</H1>
|
||||||
|
{props.children}
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
<footer className="bg-primary p-8">footer</footer>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DefaultLayout
|
32
packages/freesewing.shared/components/navigation/primary.js
Normal file
32
packages/freesewing.shared/components/navigation/primary.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import Icon from 'shared/components/icon/index.js'
|
||||||
|
|
||||||
|
const PrimaryMenu = props => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className={`
|
||||||
|
sm:max-w-sm
|
||||||
|
md:max-w-md
|
||||||
|
lg:max-w-lg
|
||||||
|
xl:max-w-xl
|
||||||
|
bg-base-200
|
||||||
|
`}>
|
||||||
|
<details>
|
||||||
|
<summary className='flex row uppercase font-bold text-lg gap-4'>
|
||||||
|
<Icon />
|
||||||
|
Tutorials
|
||||||
|
</summary>
|
||||||
|
<div className='pl-4'>
|
||||||
|
More stuff here
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
<ul>
|
||||||
|
<li>Tutorials</li>
|
||||||
|
<li>Guides</li>
|
||||||
|
<li>Howtos</li>
|
||||||
|
<li>Reference</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PrimaryMenu
|
13
packages/freesewing.shared/components/theme-picker.js
Normal file
13
packages/freesewing.shared/components/theme-picker.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import themes from 'shared/themes/index.js'
|
||||||
|
|
||||||
|
const ThemePicker = ({ app }) => {
|
||||||
|
return (
|
||||||
|
<select className="select select-bordered w-full max-w-xs" onChange={evt => app.setTheme(evt.target.value)}>
|
||||||
|
{Object.keys(themes).map(theme => (
|
||||||
|
<option>{theme}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThemePicker
|
|
@ -1,58 +0,0 @@
|
||||||
import React, { useState, useEffect } from 'react'
|
|
||||||
//import {themeChange} from "theme-change"
|
|
||||||
//import Head from 'next/head'
|
|
||||||
//import { useHotkeys } from 'react-hotkeys-hook'
|
|
||||||
//import themes from '@/shared/themes'
|
|
||||||
//import { useRouter } from 'next/router'
|
|
||||||
//import config from '@/site/freesewing.config.js'
|
|
||||||
// Shared components
|
|
||||||
//import ProgressBar from '@/shared/components/progress-bar'
|
|
||||||
//import Navbar from '@/shared/components/sections/navbar'
|
|
||||||
//import Footer from '@/site/components/footer'
|
|
||||||
//import Layout from '@/shared/components/layouts/default'
|
|
||||||
//import useNavigation from '@/shared/hooks/useNavigation'
|
|
||||||
|
|
||||||
/* This component should wrap all page content */
|
|
||||||
const AppWrapper= props => {
|
|
||||||
const router = useRouter()
|
|
||||||
const path = router.asPath
|
|
||||||
const locale = router.locale || config.language
|
|
||||||
const tree = useNavigation(locale, path)
|
|
||||||
|
|
||||||
// Trigger search with Ctrl+k
|
|
||||||
useHotkeys('ctrl+k', (evt) => {
|
|
||||||
evt.preventDefault()
|
|
||||||
setSearch(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
const [menu, setMenu] = useState(false)
|
|
||||||
const [search, setSearch] = useState(false)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
themeChange(false)
|
|
||||||
}, [menu])
|
|
||||||
|
|
||||||
const childProps = {
|
|
||||||
menu, setMenu, toggleMenu: () => setMenu(!menu),
|
|
||||||
search, setSearch, toggleSearch: () => setSearch(!search),
|
|
||||||
path, tree,
|
|
||||||
title: props.title,
|
|
||||||
t: props.t ? props.t : (x) => x,
|
|
||||||
locale, languages: config.languages,
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='flex flex-col min-h-screen'>
|
|
||||||
<ProgressBar />
|
|
||||||
{!props.noNavbar && <Navbar {...childProps}/>}
|
|
||||||
{props.noLayout
|
|
||||||
? props.children
|
|
||||||
: <Layout {...childProps}>{props.children}</Layout>
|
|
||||||
}
|
|
||||||
{!props.noFooter && !menu && <Footer />}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AppWrapper
|
|
||||||
|
|
68
packages/freesewing.shared/components/wrappers/page.js
Normal file
68
packages/freesewing.shared/components/wrappers/page.js
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import React, { useState, useEffect } from 'react'
|
||||||
|
import { useSwipeable } from 'react-swipeable'
|
||||||
|
//import {themeChange} from "theme-change"
|
||||||
|
//import Head from 'next/head'
|
||||||
|
//import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
|
//import themes from '@/shared/themes'
|
||||||
|
//import { useRouter } from 'next/router'
|
||||||
|
//import config from '@/site/freesewing.config.js'
|
||||||
|
// Shared components
|
||||||
|
import Layout from 'shared/components/layouts/default'
|
||||||
|
//import ProgressBar from '@/shared/components/progress-bar'
|
||||||
|
//import Navbar from '@/shared/components/sections/navbar'
|
||||||
|
//import Footer from '@/site/components/footer'
|
||||||
|
//import useNavigation from '@/shared/hooks/useNavigation'
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/* This component should wrap all page content */
|
||||||
|
const AppWrapper= props => {
|
||||||
|
|
||||||
|
const swipeHandlers = useSwipeable({
|
||||||
|
onSwipedLeft: evt => (props.app.primaryMenu) ? props.app.setPrimaryMenu(false) : null,
|
||||||
|
onSwipedRight: evt => (props.app.primaryMenu) ? null : props.app.setPrimaryMenu(true),
|
||||||
|
trackMouse: true
|
||||||
|
})
|
||||||
|
|
||||||
|
//const router = useRouter()
|
||||||
|
//const path = router.asPath
|
||||||
|
//const locale = router.locale || config.language
|
||||||
|
//const tree = useNavigation(locale, path)
|
||||||
|
|
||||||
|
// Trigger search with Ctrl+k
|
||||||
|
//useHotkeys('ctrl+k', (evt) => {
|
||||||
|
// evt.preventDefault()
|
||||||
|
// setSearch(true)
|
||||||
|
//})
|
||||||
|
|
||||||
|
//const [menu, setMenu] = useState(false)
|
||||||
|
//const [search, setSearch] = useState(false)
|
||||||
|
|
||||||
|
//useEffect(() => {
|
||||||
|
// themeChange(false)
|
||||||
|
//}, [menu])
|
||||||
|
|
||||||
|
const childProps = {
|
||||||
|
app: props.app,
|
||||||
|
title: props.title,
|
||||||
|
}
|
||||||
|
// menu, setMenu, toggleMenu: () => setMenu(!menu),
|
||||||
|
// search, setSearch, toggleSearch: () => setSearch(!search),
|
||||||
|
// path, tree,
|
||||||
|
// title: props.title,
|
||||||
|
// t: props.t ? props.t : (x) => x,
|
||||||
|
// locale, languages: config.languages,
|
||||||
|
//}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div {...swipeHandlers}>
|
||||||
|
{props.noLayout
|
||||||
|
? props.children
|
||||||
|
: <Layout {...childProps}>{props.children}</Layout>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AppWrapper
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
import path from 'path'
|
||||||
import remarkGfm from 'remark-gfm'
|
import remarkGfm from 'remark-gfm'
|
||||||
import remarkJargon from 'remark-jargon'
|
import remarkJargon from 'remark-jargon'
|
||||||
import { jargon } from '@freesewing/i18n'
|
import { jargon } from '@freesewing/i18n'
|
||||||
|
|
||||||
const config = {
|
const config = site => ({
|
||||||
experimental: {
|
experimental: {
|
||||||
externalDir: true,
|
externalDir: true,
|
||||||
esmExternals: true,
|
esmExternals: true,
|
||||||
|
@ -13,12 +14,10 @@ const config = {
|
||||||
// Fixes npm packages that depend on node modules
|
// Fixes npm packages that depend on node modules
|
||||||
if (!options.isServer) {
|
if (!options.isServer) {
|
||||||
config.resolve.fallback.fs = false
|
config.resolve.fallback.fs = false
|
||||||
|
config.resolve.fallback.path = false
|
||||||
config.resolve.fallback.child_process = false
|
config.resolve.fallback.child_process = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent symlink loops
|
|
||||||
config.resolve.symlinks = false
|
|
||||||
|
|
||||||
// MDX support
|
// MDX support
|
||||||
config.module.rules.push({
|
config.module.rules.push({
|
||||||
test: /\.md?$/,
|
test: /\.md?$/,
|
||||||
|
@ -36,6 +35,7 @@ const config = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
// Fix for nextjs bug #17806
|
// Fix for nextjs bug #17806
|
||||||
config.module.rules.push({
|
config.module.rules.push({
|
||||||
test: /index.mjs$/,
|
test: /index.mjs$/,
|
||||||
|
@ -45,8 +45,12 @@ const config = {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Aliases
|
||||||
|
config.resolve.alias.shared = path.resolve('../freesewing.shared/')
|
||||||
|
config.resolve.alias.site = path.resolve(`../freesewing.${site}/`)
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
export default config
|
export default config
|
||||||
|
|
|
@ -1,8 +1,22 @@
|
||||||
|
// Handle themes
|
||||||
|
const allThemes = require('../themes')
|
||||||
|
const themes = {}
|
||||||
|
for (const theme in allThemes) themes[theme] = allThemes[theme].config
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
'./pages/*.js',
|
'./pages/*.js',
|
||||||
'./pages/**/*.js',
|
'./pages/**/*.js',
|
||||||
|
'../freesewing.shared/components/**/*.js',
|
||||||
],
|
],
|
||||||
|
daisyui: {
|
||||||
|
styled: true,
|
||||||
|
themes: [ themes ],
|
||||||
|
base: true,
|
||||||
|
utils: true,
|
||||||
|
logs: true,
|
||||||
|
rtl: false,
|
||||||
|
},
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: require('daisyui/colors'),
|
colors: require('daisyui/colors'),
|
||||||
|
|
32
packages/freesewing.shared/hooks/useLocalStorage.js
Normal file
32
packages/freesewing.shared/hooks/useLocalStorage.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
// See: https://usehooks.com/useLocalStorage/
|
||||||
|
|
||||||
|
function useLocalStorage(key, initialValue) {
|
||||||
|
const prefix = 'fs_'
|
||||||
|
const [storedValue, setStoredValue] = useState(() => {
|
||||||
|
if (typeof window === 'undefined') return initialValue // SSR has no window object
|
||||||
|
try {
|
||||||
|
const item = window.localStorage.getItem(prefix + key)
|
||||||
|
return item ? JSON.parse(item) : initialValue
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
return initialValue
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const setValue = (value) => {
|
||||||
|
if (typeof window === 'undefined') return null // SSR has no window object
|
||||||
|
try {
|
||||||
|
const valueToStore = value instanceof Function ? value(storedValue) : value
|
||||||
|
setStoredValue(valueToStore)
|
||||||
|
window.localStorage.setItem(prefix + key, JSON.stringify(valueToStore))
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [storedValue, setValue]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useLocalStorage
|
21
packages/freesewing.shared/package.json
Normal file
21
packages/freesewing.shared/package.json
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "freesewing.shared",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev -p 3002",
|
||||||
|
"develop": "next dev -p 3002",
|
||||||
|
"build": "next build",
|
||||||
|
"export": "next build && next export",
|
||||||
|
"start": "next start -p 3002",
|
||||||
|
"serve": "pm2 start npm --name 'freesewing.dev' -- run start"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"daisyui": "^1.16.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"autoprefixer": "^10.4.0",
|
||||||
|
"postcss": "^8.4.4",
|
||||||
|
"tailwindcss": "^3.0.1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,3 +8,8 @@ body {
|
||||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
.primary-menu {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
}
|
55
packages/freesewing.shared/themes/bureaucrats.js
Normal file
55
packages/freesewing.shared/themes/bureaucrats.js
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
const colors = require('tailwindcss/colors')
|
||||||
|
const gray = colors.trueGray
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
icon: "👨💼",
|
||||||
|
config: {
|
||||||
|
'fontFamily': 'Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol',
|
||||||
|
'primary': colors.blue['600'],
|
||||||
|
'primary-focus': colors.blue['500'],
|
||||||
|
'primary-content': '#fff',
|
||||||
|
|
||||||
|
'secondary': colors.blue['600'],
|
||||||
|
'secondary-focus': colors.blue['200'],
|
||||||
|
'secondary-content': colors.blue['700'],
|
||||||
|
|
||||||
|
'accent': colors.blue['500'],
|
||||||
|
'accent-focus': colors.yellow['400'],
|
||||||
|
'accent-content': gray['900'],
|
||||||
|
|
||||||
|
'neutral': colors.blue['900'],
|
||||||
|
'neutral-focus': colors.blue['800'],
|
||||||
|
'neutral-content': colors.blue['100'],
|
||||||
|
|
||||||
|
'base-100': '#ffffff',
|
||||||
|
'base-200': gray['200'],
|
||||||
|
'base-300': gray['400'],
|
||||||
|
'base-content': gray['700'],
|
||||||
|
|
||||||
|
'info': colors.blue['400'],
|
||||||
|
'success': colors.green['600'],
|
||||||
|
'warning': colors.amber['500'],
|
||||||
|
'error': colors.red['600'],
|
||||||
|
|
||||||
|
'--rounded-box': '2px',
|
||||||
|
'--rounded-btn': '2px',
|
||||||
|
|
||||||
|
'--pattern-fabric': colors.trueGray['700'],
|
||||||
|
'--pattern-lining': colors.emerald['500'],
|
||||||
|
'--pattern-interfacing': colors.trueGray['400'],
|
||||||
|
'--pattern-canvas': colors.amber['600'],
|
||||||
|
'--pattern-various': colors.red['500'],
|
||||||
|
'--pattern-mark': colors.blue['500'],
|
||||||
|
'--pattern-contrast': colors.pink['500'],
|
||||||
|
'--pattern-note': colors.violet['500'],
|
||||||
|
|
||||||
|
".mdx.prose a" : {
|
||||||
|
color: colors.blue['600'],
|
||||||
|
'text-decoration': 'underline',
|
||||||
|
},
|
||||||
|
".mdx.prose a:hover" : {
|
||||||
|
color: colors.blue['500'],
|
||||||
|
'text-decoration': 'underline',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
43
packages/freesewing.shared/themes/dark.js
Normal file
43
packages/freesewing.shared/themes/dark.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
const colors = require('tailwindcss/colors')
|
||||||
|
const gray = colors.trueGray
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
icon: "🌚",
|
||||||
|
config: {
|
||||||
|
'fontFamily': '-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif',
|
||||||
|
'primary': gray['300'],
|
||||||
|
'primary-focus': colors.violet['300'],
|
||||||
|
'primary-content': gray['900'],
|
||||||
|
|
||||||
|
'secondary': colors.violet['500'],
|
||||||
|
'secondary-focus': colors.violet['400'],
|
||||||
|
'secondary-content': colors.violet['900'],
|
||||||
|
|
||||||
|
'accent': colors.emerald['500'],
|
||||||
|
'accent-focus': colors.emerald['400'],
|
||||||
|
'accent-content': gray['900'],
|
||||||
|
|
||||||
|
'neutral': gray['900'],
|
||||||
|
'neutral-focus': gray['800'],
|
||||||
|
'neutral-content': gray['300'],
|
||||||
|
|
||||||
|
'base-100': gray['800'],
|
||||||
|
'base-200': gray['700'],
|
||||||
|
'base-300': gray['600'],
|
||||||
|
'base-content': gray['300'],
|
||||||
|
|
||||||
|
'info': colors.emerald['700'],
|
||||||
|
'success': colors.green['500'],
|
||||||
|
'warning': colors.amber['500'],
|
||||||
|
'error': colors.red['400'],
|
||||||
|
|
||||||
|
'--pattern-fabric': colors.trueGray['300'],
|
||||||
|
'--pattern-lining': colors.emerald['700'],
|
||||||
|
'--pattern-interfacing': colors.trueGray['500'],
|
||||||
|
'--pattern-canvas': colors.amber['700'],
|
||||||
|
'--pattern-various': colors.red['700'],
|
||||||
|
'--pattern-mark': colors.blue['700'],
|
||||||
|
'--pattern-contrast': colors.pink['600'],
|
||||||
|
'--pattern-note': colors.violet['600'],
|
||||||
|
}
|
||||||
|
}
|
53
packages/freesewing.shared/themes/hax0r.js
Normal file
53
packages/freesewing.shared/themes/hax0r.js
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
const colors = require('tailwindcss/colors')
|
||||||
|
const gray = colors.trueGray
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
icon: "👩💻",
|
||||||
|
config: {
|
||||||
|
'fontFamily': `ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace;`,
|
||||||
|
'primary': colors.lime['600'],
|
||||||
|
'primary-focus': colors.lime['700'],
|
||||||
|
'primary-content': colors.lime['100'],
|
||||||
|
|
||||||
|
'secondary': colors.lime['600'],
|
||||||
|
'secondary-focus': colors.lime['500'],
|
||||||
|
'secondary-content': colors.lime['100'],
|
||||||
|
|
||||||
|
'accent': colors.yellow['400'],
|
||||||
|
'accent-focus': colors.yellow['500'],
|
||||||
|
'accent-content': gray['900'],
|
||||||
|
|
||||||
|
'neutral': colors.lime['900'],
|
||||||
|
'neutral-focus': gray['200'],
|
||||||
|
'neutral-content': colors.lime['300'],
|
||||||
|
|
||||||
|
'base-100': '#002808',
|
||||||
|
'base-200': '#002808',
|
||||||
|
'base-300': colors.lime['900'],
|
||||||
|
'base-content': colors.lime['500'],
|
||||||
|
|
||||||
|
'info': colors.lime['700'],
|
||||||
|
'success': colors.green['600'],
|
||||||
|
'warning': colors.amber['400'],
|
||||||
|
'error': colors.red['400'],
|
||||||
|
|
||||||
|
'--rounded-btn': '0',
|
||||||
|
|
||||||
|
'--pattern-fabric': colors.trueGray['700'],
|
||||||
|
'--pattern-lining': colors.emerald['500'],
|
||||||
|
'--pattern-interfacing': colors.trueGray['400'],
|
||||||
|
'--pattern-canvas': colors.amber['600'],
|
||||||
|
'--pattern-various': colors.red['500'],
|
||||||
|
'--pattern-mark': colors.blue['500'],
|
||||||
|
'--pattern-contrast': colors.pink['500'],
|
||||||
|
'--pattern-note': colors.violet['500'],
|
||||||
|
|
||||||
|
".mdx.prose a" : {
|
||||||
|
color: colors.lime['600'],
|
||||||
|
'text-decoration': 'underline',
|
||||||
|
},
|
||||||
|
".mdx.prose a:hover" : {
|
||||||
|
color: colors.lime['500'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
13
packages/freesewing.shared/themes/index.js
Normal file
13
packages/freesewing.shared/themes/index.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
const light = require('./light')
|
||||||
|
const dark = require('./dark')
|
||||||
|
const bureaucrats = require('./bureaucrats')
|
||||||
|
const kindergarten = require('./kindergarten')
|
||||||
|
const hax0r = require('./hax0r')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
light,
|
||||||
|
dark,
|
||||||
|
bureaucrats,
|
||||||
|
kindergarten,
|
||||||
|
hax0r,
|
||||||
|
}
|
54
packages/freesewing.shared/themes/kindergarten.js
Normal file
54
packages/freesewing.shared/themes/kindergarten.js
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
const colors = require('tailwindcss/colors')
|
||||||
|
const gray = colors.trueGray
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
icon: "🐕",
|
||||||
|
config: {
|
||||||
|
'fontFamily': "Chalkboard,comic sans ms,\"sanssecondaryerif\"",
|
||||||
|
'primary': colors.emerald['600'],
|
||||||
|
'primary-focus': colors.emerald['500'],
|
||||||
|
'primary-content': '#fff',
|
||||||
|
|
||||||
|
'secondary': colors.fuchsia['600'],
|
||||||
|
'secondary-focus': colors.fuchsia['500'],
|
||||||
|
'secondary-content': colors.gray['800'],
|
||||||
|
|
||||||
|
'accent': colors.green['500'],
|
||||||
|
'accent-focus': colors.yellow['400'],
|
||||||
|
'accent-content': gray['900'],
|
||||||
|
|
||||||
|
'neutral': colors.emerald['900'],
|
||||||
|
'neutral-focus': gray['200'],
|
||||||
|
'neutral-content': colors.emerald['100'],
|
||||||
|
|
||||||
|
'base-100': colors.yellow['200'],
|
||||||
|
'base-200': colors.yellow['300'],
|
||||||
|
'base-300': colors.yellow['400'],
|
||||||
|
'base-content': gray['700'],
|
||||||
|
|
||||||
|
'info': colors.pink['400'],
|
||||||
|
'success': colors.green['600'],
|
||||||
|
'warning': colors.amber['600'],
|
||||||
|
'error': colors.red['600'],
|
||||||
|
|
||||||
|
'--rounded-btn': '10rem',
|
||||||
|
|
||||||
|
'--pattern-fabric': colors.trueGray['700'],
|
||||||
|
'--pattern-lining': colors.emerald['500'],
|
||||||
|
'--pattern-interfacing': colors.trueGray['400'],
|
||||||
|
'--pattern-canvas': colors.amber['600'],
|
||||||
|
'--pattern-various': colors.red['500'],
|
||||||
|
'--pattern-mark': colors.blue['500'],
|
||||||
|
'--pattern-contrast': colors.pink['500'],
|
||||||
|
'--pattern-note': colors.violet['500'],
|
||||||
|
|
||||||
|
".mdx.prose a" : {
|
||||||
|
color: colors.fuchsia['600'],
|
||||||
|
'text-decoration': 'none',
|
||||||
|
},
|
||||||
|
".mdx.prose a:hover" : {
|
||||||
|
color: colors.fuchsia['500'],
|
||||||
|
'text-decoration': 'underline',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
162
packages/freesewing.shared/themes/light.js
Normal file
162
packages/freesewing.shared/themes/light.js
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
/**
|
||||||
|
* This is a theme file for FreeSewing's NextJS-based website
|
||||||
|
*
|
||||||
|
* You can change colors, fonts, and a few other things here.
|
||||||
|
* While technically, you can change more, it's really not recommended.
|
||||||
|
* Best to stick to the examples in this light theme
|
||||||
|
*
|
||||||
|
* If you want to make your own theme, copy this file to a new name.
|
||||||
|
* Update ../index.js to include it, and you're good to go.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We're using the TailwindCSS colors.
|
||||||
|
* Let's include them so we can reference them by name.
|
||||||
|
* For a full list, see: https://tailwindcss.com/docs/customizing-colors
|
||||||
|
*/
|
||||||
|
const colors = require('tailwindcss/colors')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
icon: "🌞",
|
||||||
|
config: {
|
||||||
|
|
||||||
|
/* FONTS
|
||||||
|
*
|
||||||
|
* This will apply to everything except code blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
// fontFamily: The font family to use.
|
||||||
|
'fontFamily': '-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif',
|
||||||
|
|
||||||
|
/* COLORS
|
||||||
|
*
|
||||||
|
* These names are a bit 'bootstrap' like, which can be misleading.
|
||||||
|
* We don't really use primary and secondary colors, nor do we have
|
||||||
|
* a warning color and so on.
|
||||||
|
* However, these names are used under the hood by TailwindCSS
|
||||||
|
* and DaisyUI, so we're stuck with them.
|
||||||
|
*
|
||||||
|
* Read the descriptions below to understand what each color is used for.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// base-100: The default background color
|
||||||
|
'base-100': colors.trueGray['100'],
|
||||||
|
// base-200: A slightly different background color, used for hovers and so on
|
||||||
|
'base-200': colors.trueGray['200'],
|
||||||
|
// base-300: A shade midway between dark and light
|
||||||
|
'base-300': colors.trueGray['400'],
|
||||||
|
// base-content: The default text color
|
||||||
|
'base-content': colors.trueGray['700'],
|
||||||
|
|
||||||
|
// primary: The main brand color and color of the primary button
|
||||||
|
'primary': colors.trueGray['900'],
|
||||||
|
// primary-focus: The :hover color for the primary button
|
||||||
|
'primary-focus': colors.violet['600'],
|
||||||
|
// primary-content: The text color for the primary button
|
||||||
|
'primary-content': colors.trueGray['200'],
|
||||||
|
|
||||||
|
// secondary: The link color
|
||||||
|
'secondary': colors.violet['500'],
|
||||||
|
// secondary: The :hover link color
|
||||||
|
'secondary-focus': colors.violet['400'],
|
||||||
|
// secondary: An alternative link color for on dark backgrounds
|
||||||
|
// Typically a light shade of the secondary color
|
||||||
|
'secondary-content': colors.violet['300'],
|
||||||
|
|
||||||
|
// accent: The accent color is used to highlight active things
|
||||||
|
// Should be something is positive/neutral. Avoid red or orange.
|
||||||
|
'accent': colors.emerald['500'],
|
||||||
|
// accent-focus: The :hover color for the accent button
|
||||||
|
'accent-focus': colors.emerald['400'],
|
||||||
|
// accent-content: The text color for the accent button
|
||||||
|
'accent-content': colors.trueGray['900'],
|
||||||
|
|
||||||
|
// neutral: Used as the background for the footer and code blocks.
|
||||||
|
// Should always be dark(ish) because of prism syntax highlighting
|
||||||
|
'neutral': colors.trueGray['800'],
|
||||||
|
// neutral-focus: Typically a shade lighter than neutral
|
||||||
|
'neutral-focus': colors.trueGray['700'],
|
||||||
|
// neutral-content: The text color on neutral backgrounds
|
||||||
|
'neutral-content': colors.trueGray['200'],
|
||||||
|
|
||||||
|
// info: Used rarely, can be another color best somewhat neutral looking
|
||||||
|
// and should work with the default text color
|
||||||
|
'info': colors.amber['300'],
|
||||||
|
// success: Used rarely, but if it is it's in notifications indicating success
|
||||||
|
// Typically some shade of green
|
||||||
|
'success': colors.green['500'],
|
||||||
|
// warning: We don't do warnings, but this is used for the tabs under code blocks
|
||||||
|
// and a couple of other UI elements.
|
||||||
|
'warning': colors.amber['500'],
|
||||||
|
// error: Used rarely, but if it is it's in notifications indicating success
|
||||||
|
// or the danger button
|
||||||
|
// Typically some shade of red
|
||||||
|
'error': colors.red['600'],
|
||||||
|
|
||||||
|
/* VARIOUS
|
||||||
|
*
|
||||||
|
* These are additional variables to control other aspects of the theme
|
||||||
|
*/
|
||||||
|
|
||||||
|
// border-radius for cards and other big elements
|
||||||
|
'--rounded-box': '0.5rem',
|
||||||
|
// border-radius for buttons and similar elements
|
||||||
|
'--rounded-btn': '0.5rem',
|
||||||
|
// border-radius for badges and other small elements
|
||||||
|
'--rounded-badge': '1.9rem',
|
||||||
|
// bounce animation time for button
|
||||||
|
'--animation-btn': '0.25s',
|
||||||
|
// bounce animation time for checkbox, toggle, etc
|
||||||
|
'--animation-input': '.4s',
|
||||||
|
// default card-body padding
|
||||||
|
'--padding-card': '2rem',
|
||||||
|
// default text case for buttons
|
||||||
|
'--btn-text-case': 'uppercase',
|
||||||
|
// default padding for navbar
|
||||||
|
'--navbar-padding': '.5rem',
|
||||||
|
// default border size for button
|
||||||
|
'--border-btn': '1px',
|
||||||
|
// focus ring size for button and inputs
|
||||||
|
'--focus-ring': '2px',
|
||||||
|
// focus ring offset size for button and inputs
|
||||||
|
'--focus-ring-offset': '2px',
|
||||||
|
|
||||||
|
/* FREESEWING PATTERN COLORS
|
||||||
|
*
|
||||||
|
* These are variables to style FreeSewing SVG output (drafts, examples, and so on)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Color for the main fabric
|
||||||
|
'--pattern-fabric': colors.trueGray['700'],
|
||||||
|
// Color for lining fabric
|
||||||
|
'--pattern-lining': colors.emerald['500'],
|
||||||
|
// Color for interfacing
|
||||||
|
'--pattern-interfacing': colors.trueGray['400'],
|
||||||
|
// Color for canvas
|
||||||
|
'--pattern-canvas': colors.amber['600'],
|
||||||
|
// Color for various fabric types
|
||||||
|
'--pattern-various': colors.red['500'],
|
||||||
|
// Color for marking things on a pattern
|
||||||
|
'--pattern-mark': colors.blue['500'],
|
||||||
|
// Color to provide contrast on a pattern
|
||||||
|
'--pattern-contrast': colors.pink['500'],
|
||||||
|
// Color for noting things on a pattern
|
||||||
|
'--pattern-note': colors.violet['500'],
|
||||||
|
|
||||||
|
/* ADVANCED
|
||||||
|
*
|
||||||
|
* You can override CSS this way, but ask yourself: why?
|
||||||
|
*
|
||||||
|
* One thing we do is take care of links in MDX content.
|
||||||
|
* Since this content is styled by the TailwindCSS Typography
|
||||||
|
* plugin, it won't follow the theme link styling.
|
||||||
|
*/
|
||||||
|
".mdx.prose a" : {
|
||||||
|
color: colors.violet['500'],
|
||||||
|
'text-decoration': 'none',
|
||||||
|
},
|
||||||
|
".mdx.prose a:hover" : {
|
||||||
|
color: colors.violet['400'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
13
yarn.lock
13
yarn.lock
|
@ -18224,6 +18224,11 @@ react-side-effect@^2.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.1.tgz#66c5701c3e7560ab4822a4ee2742dee215d72eb3"
|
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.1.tgz#66c5701c3e7560ab4822a4ee2742dee215d72eb3"
|
||||||
integrity sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==
|
integrity sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==
|
||||||
|
|
||||||
|
react-swipeable@^6.2.0:
|
||||||
|
version "6.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-swipeable/-/react-swipeable-6.2.0.tgz#057271cb7a6fb4af9d2a3f6d80ccdf33e2f64d47"
|
||||||
|
integrity sha512-nWQ8dEM8e/uswZLSIkXUsAnQmnX4MTcryOHBQIQYRMJFDpgDBSiVbKsz/BZVCIScF4NtJh16oyxwaNOepR6xSw==
|
||||||
|
|
||||||
react-tooltip@4.2.18:
|
react-tooltip@4.2.18:
|
||||||
version "4.2.18"
|
version "4.2.18"
|
||||||
resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.18.tgz#2fb8c5e115c4e5476f94081f4bb2ba77f5b2297f"
|
resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.18.tgz#2fb8c5e115c4e5476f94081f4bb2ba77f5b2297f"
|
||||||
|
@ -21272,10 +21277,10 @@ table@^6.0.9:
|
||||||
string-width "^4.2.0"
|
string-width "^4.2.0"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
tailwindcss@^3.0.0:
|
tailwindcss@^3.0.1:
|
||||||
version "3.0.0"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.0.tgz#f7dfd30996b3b1a84d656aaf3c8b6810b70d3d42"
|
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.1.tgz#bef72ff45d5cfed79bb648d30da952e521e98da4"
|
||||||
integrity sha512-UPAp2PS5vojAvGClJFIkdh2hfFyaSWo09Ma9j2vZYW+ANhTvpUHFjY85JgtrvvXXREtDvOXy2BxW1yHOz8apCg==
|
integrity sha512-EVDXVZkcueZ77/zfOJw7XkzCuxe5TCiT/S9pw9P183oRzSuwMZ7WO+W/L76jbJQA5qxGeUBJOVOLVBuAUfeZ3g==
|
||||||
dependencies:
|
dependencies:
|
||||||
arg "^5.0.1"
|
arg "^5.0.1"
|
||||||
chalk "^4.1.2"
|
chalk "^4.1.2"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue