diff --git a/.gitignore b/.gitignore index fd505d1d995..a7905713741 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,7 @@ sites/org/authors.json sites/org/showcase-tags.mjs sites/org/design-examples.mjs sites/org/docs/designs/*.mdx +sites/org/recent-blog-posts.mjs # sde auto-generated content sites/sde/public/android-chrome-192x192.png diff --git a/config/exceptions.yaml b/config/exceptions.yaml index 72d7210956e..5204a3edcd2 100644 --- a/config/exceptions.yaml +++ b/config/exceptions.yaml @@ -101,6 +101,7 @@ packageJson: "./components/Null": "./components/Null/index.mjs" "./components/Number": "./components/Number/index.mjs" "./components/Pattern": "./components/Pattern/index.mjs" + "./components/Patrons": "./components/Patrons/index.mjs" "./components/Popout": "./components/Popout/index.mjs" "./components/Role": "./components/Role/index.mjs" "./components/SignIn": "./components/SignIn/index.mjs" diff --git a/packages/react/components/Link/index.mjs b/packages/react/components/Link/index.mjs index 26f67bc40c2..88c26830522 100644 --- a/packages/react/components/Link/index.mjs +++ b/packages/react/components/Link/index.mjs @@ -55,12 +55,27 @@ export const SuccessLink = ({ ) -export const CardLink = ({ href, title, Icon, children, Link }) => { +export const CardLink = ({ + href, + title, + icon, + children, + Link, + className = 'tw-bg-base-200 tw-text-base-content', +}) => { if (!Link) Link = BaseLink return ( - - {title} + +

+ {title} + {icon} +

{children} ) diff --git a/packages/react/components/Patrons/index.mjs b/packages/react/components/Patrons/index.mjs new file mode 100644 index 00000000000..7d32130bc2f --- /dev/null +++ b/packages/react/components/Patrons/index.mjs @@ -0,0 +1,309 @@ +// Dependencies +import { linkClasses } from '@freesewing/utils' +// Hooks +import React, { useEffect, useState } from 'react' +import { useAccount } from '@freesewing/react/hooks/useAccount' + +export const PleaseSubscribe = (props = {}) => ( +
+
+
+ +
+

Support FreeSewing

+ +
+
+
+
+) + +export const Plea = () => ( +
+

+ Hi friend + 👋 +

+ {[ + 'My name is Joost De Cock. I am the founder and maintainer of FreeSewing.', + 'I am here to ask your help. Or more accurately, your support. Which we really need.', + 'If you think FreeSewing is worthwhile, and if you can spare a few coins each month without hardship, please support our work.', + 'Thanks in advance for considering it.', + 'love', + ].map((txt, i) => ( +

+ {txt} +

+ ))} + +
+) + +const PaypalFormBody = ({ amount, period, currency }) => ( + <> + {[ + ...Object.entries(paypalConfig.vars[period === 'x' ? 'donate' : 'subscribe']), + ...Object.entries(paypalConfig.vars.shared), + ].map(([name, value]) => ( + + ))} + {period === 'x' ? ( + <> + + + + ) : ( + <> + + + + + + )} + + + +) + +export const Subscribe = ({ + color = 'secondary', + subscribeOnly, + amountPreset = '25', + periodPreset = 'm', +}) => { + const [amount, setAmount] = useState(amountPreset) + const [currency, setCurrency] = useState('eur') + const [period, setPeriod] = useState(periodPreset) + + const { amounts, currencies } = paypalConfig + const periods = subscribeOnly + ? paypalConfig.periods.filter((p) => p !== 'x') + : paypalConfig.periods + + return ( +
+
+
+ + setAmount(evt.target.value)} + /> +
+
+ + +
+
+
+ +
+
+ {periods.map((val) => ( +
+ +
+ ))} +
+
+ + +

+ Don't have a PayPal account? + + Ko-fi.com/FreeSewing + +

+ +
+ ) +} + +export const Joost = ({ className = 'tw-w-32', stroke = 0 }) => ( + + + +) + +const paypalConfig = { + /* + * This is the plan ID for FreeSewing Patron Subscriptions. + * Note that to maximize flexibility, and have a sort of pay-what-you-wnat + * system, we have only 1 plan: 1 euro/month. + * + * But we use quantity pricing. So if a person selects a 15/month plan, + * we subscribe them to the 1/month plan but set the quantity to 15. + */ + planId: 'P-41W64036N5201172WMTEKMIA', + /* + * List of amounts we display + * (users can also enter their own amount, which we'll floor to an int) + */ + amounts: [5, 10, 15, 25, 50, 75, 100], + /* + * Currencies supported by PayPal that we use + * https://developer.paypal.com/api/nvp-soap/currency-codes#paypal + */ + currencies: ['aud', 'cad', 'eur', 'usd'], + /* + * Periods for recurring payments + * x means donation, not subscription + */ + periods: ['w', 'm', '3m', '6m', 'y', 'x'], + periodLabels: { + w: 'Weekly', + m: 'Monthly', + '3m': 'Quarterly', + '6m': 'Half-yearly', + y: 'Yearly', + x: 'One time only', + }, + /* + * Variables to set in the form + * https://developer.paypal.com/api/nvp-soap/paypal-payments-standard/integration-guide/Appx-websitestandard-htmlvariables/ + */ + vars: { + // Subscribe form + subscribe: { + /* + * This value indicates it is a subscribe button that was clicked + */ + cmd: '_xclick-subscriptions', + /* + * Item name as shown to the user + * + * Will be replaced with the translated value at run time, but this is + * here as a safe default. + */ + item_name: 'FreeSewing Patron Subscription', + /* + * Return URL the user will be redirected to after completion + * of the payment. + */ + return: 'https://freesewing.org/patrons/thanks', + /* + * This needs to be set to 1 to indicate that recurring + * payments should be collected. + */ + src: 1, + }, + // Donate form + donate: { + /* + * This value indicates it is a donate button that was clicked + */ + cmd: '_donations', + /* + * Item name as shown to the user + * + * Will be replaced with the translated value at run time, but this is + * here as a safe default. + */ + item_name: 'FreeSewing Donation', + /* + * Return URL the user will be redirected to after completion + * of the payment. + */ + return: 'https://freesewing.org/donate/thanks', + }, + // Included in both forms + shared: { + /* + * This is required. It is the email address tied to FreeSewing's PayPal account. + */ + business: 'info@freesewing.org', + /* + * Do not let users include a note. It just clutters up the UI. + */ + no_note: 1, + /* + * This setting means the user will be redirected using GET + * without any payment variables included. It's the cleanest UI. + */ + rm: 1, + /* + * Image to display on the PayPal checkkout page + * Should be 150x50 pixels (which is small) + */ + image_url: 'https://data.freesewing.org/static/img/paypal-logo.png', + }, + }, +} diff --git a/packages/react/components/SignUp/index.mjs b/packages/react/components/SignUp/index.mjs index a8570827b3b..3a9d9a2418d 100644 --- a/packages/react/components/SignUp/index.mjs +++ b/packages/react/components/SignUp/index.mjs @@ -26,7 +26,7 @@ import { EmailInput } from '@freesewing/react/components/Input' import { IconButton } from '@freesewing/react/components/Button' //import { Robot } from 'shared/components/robot/index.mjs' -export const SignUp = () => { +export const SignUp = ({ embed = false }) => { // State const [email, setEmail] = useState('') const [emailValid, setEmailValid] = useState(false) @@ -56,22 +56,22 @@ export const SignUp = () => { if (status === 201 && body.result === 'created') setResult('success') else { setModal( - -
+ +

An error occured while trying to process your request

-

+

Unfortunately, we cannot recover from this error, we need a human being to look into this.

-

+

Feel free to try again, or reach out to support so we can assist you.

-
+
setResult(false)}> Back - + Contact support @@ -90,10 +90,13 @@ export const SignUp = () => { window.location.href = result.data.authUrl } } + const Heading = embed + ? ({ children }) =>

{children}

+ : ({ children }) =>

{children}

return ( -
-

+
+ {result ? ( result === 'success' ? ( Now check your inbox @@ -103,23 +106,23 @@ export const SignUp = () => { ) : ( Create a FreeSewing account )} -

+ {result ? ( result === 'success' ? ( <> -

+

Go check your inbox for an email from FreeSewing.org

-

+

Click your personal signup link in that email to create your FreeSewing account.

-
+
setResult(false)}> Back - + Contact support @@ -128,18 +131,18 @@ export const SignUp = () => { ) : ( <> robot here -

+

Unfortunately, we cannot recover from this error, we need a human being to look into this.

-

+

Feel free to try again, or reach out to support so we can assist you.

-
- - + Contact support
@@ -147,7 +150,7 @@ export const SignUp = () => { ) ) : ( <> -

To receive a sign-up link, enter your email address

+

To receive a sign-up link, enter your email address

{ Email me a sign-up link @@ -169,7 +172,7 @@ export const SignUp = () => { {showAll ? ( <> -
+
{['Google', 'GitHub'].map((provider) => ( { ))}
- - - + + + Sign in here -
+
setShowAll(false)}> - + Fewer options - +
) : ( -
+
setShowAll(true)}> More options diff --git a/packages/react/package.json b/packages/react/package.json index f49322b3637..4d0d9a3a67e 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -54,6 +54,7 @@ "./components/Null": "./components/Null/index.mjs", "./components/Number": "./components/Number/index.mjs", "./components/Pattern": "./components/Pattern/index.mjs", + "./components/Patrons": "./components/Patrons/index.mjs", "./components/Popout": "./components/Popout/index.mjs", "./components/Role": "./components/Role/index.mjs", "./components/SignIn": "./components/SignIn/index.mjs", diff --git a/sites/org/docusaurus.config.mjs b/sites/org/docusaurus.config.mjs index 81a4b390a5a..e1fe4ef6e97 100644 --- a/sites/org/docusaurus.config.mjs +++ b/sites/org/docusaurus.config.mjs @@ -268,65 +268,41 @@ const config = { { to: '/showcase/', label: '📷 Showcase', position: 'left' }, { to: '/blog/', label: '📰 Blog', position: 'left' }, { to: '/new/', label: '➕ New...', position: 'right' }, - { to: '/account/', label: '📰 Account', position: 'right' }, + { to: '/account/', label: '🔒 Account', position: 'right' }, ], }, footer: { style: 'light', links: [ { - title: 'Docs', + title: 'Sections', items: [ - { label: 'FreeSewing designs', to: '/docs/designs/' }, - { label: 'About FreeSewing', to: '/docs/about/' }, - { label: 'Measurements we use', to: '/docs/measurements/' }, - { label: 'Sewing terminology', to: '/docs/sewing/' }, + { label: 'FreeSewing Designs', to: '/designs/' }, + { label: 'FreeSewing Showcase', to: '/showcase/' }, + { label: 'FreeSewing Blog', to: '/blog/' }, + { label: 'FreeSewing Editor', to: '/editor/' }, ], }, { title: 'Help & Support', items: [ - { - label: 'Discord', - href: 'https://discord.freesewing.org/', - }, - { - label: 'GitHub Issues', - href: 'https://github.com/freesewing/freesewing/issues', - }, - { - label: 'GitHub Discussions', - href: 'https://github.com/freesewing/freesewing/discussions', - }, - { - label: 'All Support Options', - href: 'https://freesewing.org/support', - }, + { label: 'About FreeSewing', to: '/docs/about/' }, + { label: 'Getting Started', to: '/docs/about/guide/' }, + { label: 'Frequently Asked Questions', href: '/docs/about/faq/' }, + { label: 'Need Help?', href: '/support' }, ], }, { title: 'More', items: [ - { - label: 'FreeSewing.org', - to: 'https://freesewing.org/', - }, - { - label: 'Blog', - to: 'https://freesewing.org/blog/', - }, - { - label: 'Showcase', - to: 'https://freesewing.org/showccase/', - }, - { - label: 'Code on GitHub', - href: 'https://github.com/freesewing/freesewing', - }, + { label: 'FreeSewing.dev', to: 'https://freesewing.dev/' }, + { label: 'FreeSewing.social', to: 'https://freesewing.social/' }, + { label: 'Code on GitHub', to: 'https://github.com/freesewing/freesewing' }, + { label: 'FreeSewing Revenue Pledge 💜', href: '/docs/about/pledge/' }, ], }, ], - copyright: `FreeSewing is brought to you by Joost De Cock and contributors with the financial support of our patrons`, + copyright: `FreeSewing is brought to you by Joost De Cock and contributors with the financial support of our patrons`, }, prism: { theme: prismThemes.dracula, diff --git a/sites/org/scripts/prebuild-step3.mjs b/sites/org/scripts/prebuild-step3.mjs index 2f67a5d0e4b..5222eec53eb 100644 --- a/sites/org/scripts/prebuild-step3.mjs +++ b/sites/org/scripts/prebuild-step3.mjs @@ -1,6 +1,7 @@ import fs from 'fs' import { glob } from 'glob' import matter from 'gray-matter' +import { orderBy } from '../../../packages/utils/src/index.mjs' const loadExamplesTagsAndAuthors = async () => { const lists = { @@ -12,6 +13,7 @@ const loadExamplesTagsAndAuthors = async () => { const tags = [] const authors = [] const examples = {} + const recentBlogPosts = [] for (const type of Object.keys(lists)) { for (const file of lists[type]) { const content = await fs.readFileSync(file, 'utf-8') @@ -32,7 +34,12 @@ const loadExamplesTagsAndAuthors = async () => { if (typeof examples[tag] === 'undefined') examples[tag] = [] examples[tag].push({ title: data.data.title, id: file.split('/')[1] }) } - } + } else if (type === 'blog') + recentBlogPosts.push({ + title: data.data.title, + slug: file.split('/')[1], + date: new Date(data.data.date).getTime(), + }) } } @@ -40,6 +47,7 @@ const loadExamplesTagsAndAuthors = async () => { authors: [...new Set(authors.sort())], // Make them unique tags: [...new Set(tags.sort())], // Make them unique examples, + recentBlogPosts: orderBy(recentBlogPosts, 'date', 'desc').slice(0, 2), } } @@ -69,7 +77,7 @@ const loadUser = async (id) => { async function prebuild() { const all = {} - const { authors, examples, tags } = await loadExamplesTagsAndAuthors() + const { authors, examples, tags, recentBlogPosts } = await loadExamplesTagsAndAuthors() for (const author of authors) { const user = await loadUser(author) if (user.profile.id) all[user.profile.id] = userAsAuthor(user) @@ -80,6 +88,10 @@ async function prebuild() { `export const tags = ${JSON.stringify([...new Set(tags.sort())])}` ) fs.writeFileSync(`./design-examples.mjs`, `export const examples = ${JSON.stringify(examples)}`) + fs.writeFileSync( + `./recent-blog-posts.mjs`, + `export const recentBlogPosts = ${JSON.stringify(recentBlogPosts, 0, 2)}` + ) } prebuild() diff --git a/sites/org/src/pages/index.js b/sites/org/src/pages/index.js index 3411a33358b..c41da6abed2 100644 --- a/sites/org/src/pages/index.js +++ b/sites/org/src/pages/index.js @@ -1,84 +1,386 @@ +// Dependencies +import { recentBlogPosts } from '@site/recent-blog-posts.mjs' +// Hooks +import { useState, useEffect } from 'react' +// Components +import Link from '@docusaurus/Link' +import { DocusaurusPage } from '@freesewing/react/components/Docusaurus' import Layout from '@theme/Layout' -import MDXContent from '@theme/MDXContent' +import { + ChatIcon, + DesignIcon, + DocsIcon, + FreeSewingIcon, + HelpIcon, + NewsletterIcon, + NoIcon, + OkIcon, + ShowcaseIcon, +} from '@freesewing/react/components/Icon' +import { SignUp } from '@freesewing/react/components/SignUp' +import { + HortensiaFront, + HiFront, + TeaganFront, + AaronFront, + AlbertFront, + BruceBack, + BruceFront, + SimonBack, + SimonFront, + WahidBack, + WahidFront, +} from '@freesewing/react/components/LineDrawing' +import { BlogPostTeaser } from '@site/src/theme/BlogPostItems/index.js' +import { CardLink } from '@freesewing/react/components/Link' +import { PleaseSubscribe } from '@freesewing/react/components/Patrons' -const styles = { - top: { - margin: 'auto', - textAlign: 'center', - paddingTop: '2rem', - }, - logo: { - maxWidth: '140px', - }, - cards: { - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - maxWidth: '1600px', - margin: 'auto', - padding: '1rem', - gap: '1.5rem', - justifyContent: 'center', - marginBottom: '3rem', - }, - card: { - width: '100%', - maxWidth: '600px', - boxShadow: '1px 1px 5px #0004', - borderRadius: '0.5rem', - padding: '1rem 1.5rem', - backgroundColor: 'var(--ifm-footer-background-color)', - }, - cardheading: { - display: 'flex', - flexDirection: 'row', - width: '100%', - justifyContent: 'space-between', - alignItems: 'center', - }, - cardicon: { - fontSize: '2rem', - }, - cardp: { - fontSize: '1.15rem', - }, -} - -const Card = ({ title, icon, children, href }) => ( - -

- {title} - {icon} -

+const Card = ({ title, children, icon }) => ( +
) +const meta = { + title: 'Free Bespoke Sewing Patterns', + description: + 'FreeSewing is open source software to generate bespoke sewing ' + + 'patterns, loved by home sewers and fashion entrepreneurs alike.', +} + export default function Home() { return ( - - -
-

Fixme: Build home page

+ +
+
+ +

+ FreeSewing +

+

+ Free Bespoke Sewing Patterns +

-
- -

Documentation for all our designs.

+ +
+ } + > +

+ FreeSewing is open source software to generate bespoke sewing patterns, loved by home + sewers and fashion entrepreneurs alike. +

+

+ Industry sizing is a bunch of lies. Join the slow fashion revolution and enjoy clothes + that fit you. +

+

+ Speaking of revolution, we do not tolerate nazis here. +

- -

Documentation about FreeSewing.org and how to use it.

-
- -

Documentation for all the measurements we use.

-
- -

Documentation for various terms that are used in sewing.

+ } + > +

+ FreeSewing is not a company. We do not sell anything. We do not have staff or + employees. We do not have an office. We do not get paid. +

+

+ Our website does not contain any advertising. We do not track you. We do not sell your + personal data, or use it to train AI algorithms. We do not violate your privacy. +

- - + +
+ +
+ +
+
+
+ +
+
+

Reasons to join

+
    + {[0, 1, 2, 3].map((i) => ( +
  • + {reasonsToJoin[i]} +
  • + ))} +
+
+
+
+ +
+ {recentBlogPosts.map((post) => ( + + ))} +
+ +
+ } + > +

+ Browse our collection of designs, and turn them into sewing patterns that are + made-to-measure just for you. +

+
+ } + > +

+ Get inspiration from the FreeSewing community, and see how others have applied their + creativity to our designs. +

+
+ } + > +

+ FreeSewing.org is unlike any sewing pattern website you know. Read this short guide to + get the most our of our platform. +

+
+ } + > +

+ Some of the questions that come up often when people discover our platform are + answered here. +

+
+
+ +
+ +
+ +
+ } + > +

+ Subscribe to our newsletter and once every 3 months you'll receive an email from us + with honest wholesome content. No tracking, no ads, no nonsense. +

+
+ } + > +

+ While we are all volunteers, we have a good track record of helping people. So don't + be shy to reach out. +

+
+
+
+ ) } + +const HowDoesItWorkAnimation = () => { + const [step, setStep] = useState(0) + const [halfStep, setHalfStep] = useState(0) + + useEffect(() => { + setTimeout(() => { + if (step > 6) setStep(0) + else setStep(step + 1) + if (halfStep > 7) setHalfStep(0) + else setHalfStep(halfStep + 0.5) + }, 800) + }, [step]) + + return ( +
+
+
+ {slides.map((i) => ( +
+
+ {lineDrawings[i]} +
+
+ ))} +
+ + + </div> + <div className="tw-relative tw-w-full"> + <div className="tw-relative tw-h-72 md:tw-h-96 tw-overflow-hidden"> + {slides.map((i) => ( + <div + key={i} + className={`tw-duration-700 tw-ease-in-out tw-transition-all ${ + Math.floor(halfStep) === i ? 'tw-opacity-1' : 'tw-opacity-0' + } tw-absolute tw-top-0 tw-text-center tw-w-full`} + > + <div className="tw-w-full tw-flex tw-flex-row tw-items-center tw-h-72 md:tw-h-96 tw-w-full tw-justify-center"> + <img + src={`/img/models/model-${i}.png`} + className="tw-h-72 md:tw-h-96 tw-shrink-0 tw-px-8" + /> + </div> + </div> + ))} + <Nr nr={2} /> + <Title txt="Add a set of measurements" /> + </div> + </div> + <div className="tw-relative tw-w-full"> + <div className="tw-relative tw-h-96 tw-overflow-hidden"> + <div className="tw-w-full tw-flex tw-flex-row tw-items-center tw-h-72 md:tw-h-96 tw-w-full tw-justify-center"> + <Pattern key={step} i={step} /> + </div> + <Nr nr={3} /> + <Title txt="Customize your pattern" /> + </div> + </div> + </div> + ) +} + +const reasonsToJoin = [ + 'Generate bespoke sewing patterns.', + 'Store your patterns & measurements sets.', + 'Share your creations with the community.', + 'Open source. No ads. No nonsense.', +] + +const lineDrawings = [ + <AaronFront key={1} className="tw-h-72 md:tw-h-96" />, + <HiFront key={2} className="tw-h-72 md:tw-h-96" />, + <TeaganFront key={3} className="tw-h-72 md:tw-h-96" />, + <WahidFront key={4} className="tw-h-72 md:tw-h-96" />, + <AlbertFront key={5} className="tw-h-72 md:tw-h-96" />, + <BruceFront key={6} className="tw-h-72 md:tw-h-96" />, + <SimonFront key={7} className="tw-h-72 md:tw-h-96" />, + <HortensiaFront key={8} className="tw-h-72 md:tw-h-96" />, +] + +const patternTweaks = [ + <path + key={1} + d="M 0,121.4 L 0,705.1 L 253.46,705.1 C 253.46,474.02 281.12,307.05 281.12,307.05 C 187.15,307.05 128.12,163.24 163.07,19.43 L 119.46,8.83 C 92.11,121.4 92.11,121.4 0,121.4 z" + />, + <path + key={2} + d="M 0,121.4 L 0,705.1 L 253.46,705.1 C 253.46,481 279.96,321 279.96,321 C 184.87,321 126.42,170.22 163.07,19.43 L 119.46,8.83 C 92.11,121.4 92.11,121.4 0,121.4 z" + />, + <path + key={3} + d="M 0,121.4 L 0,705.1 L 253.46,705.1 C 253.46,481 273.47,321 273.47,321 C 181.62,321 126.42,170.22 163.07,19.43 L 119.46,8.83 C 92.11,121.4 92.11,121.4 0,121.4 z" + />, + <path + key={4} + d="M 0,121.4 L 0,742.92 L 253.46,742.92 C 253.46,481 273.47,321 273.47,321 C 181.62,321 126.42,170.22 163.07,19.43 L 119.46,8.83 C 92.11,121.4 92.11,121.4 0,121.4 z" + />, + <path + key={5} + d="M 0,121.4 L 0,742.92 L 253.46,742.92 C 253.46,481 273.47,321 273.47,321 C 181.62,321 126.42,170.22 163.07,19.43 L 119.46,8.83 C 95.69,106.65 80.04,121.4 0,121.4 z" + />, + <path + key={6} + d="M 0,152.02 L 0,742.92 L 253.46,742.92 C 253.46,481 273.47,321 273.47,321 C 181.62,321 126.42,170.22 163.07,19.43 L 119.46,8.83 C 89.22,133.26 73.57,152.02 0,152.02 z" + />, + <path + key={7} + d="M 0,152.02 L 0,742.92 L 253.46,742.92 C 253.46,481 273.47,321 273.47,321 C 183.55,321 130.16,170.66 166.7,20.31 L 123.1,9.71 C 93.04,133.38 76.92,152.02 0,152.02 z" + />, + <path + key={8} + d="M 0,152.02 L 0,742.92 L 253.46,742.92 C 253.46,481 273.47,321 273.47,321 C 181.55,321 126.27,170.2 162.92,19.39 L 126.88,10.63 C 97.02,133.5 80.4,152.02 0,152.02 z" + />, +] + +const Pattern = ({ i }) => ( + <svg + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="-300 -20 850 850" + stroke="currentColor" + strokeLinecap="round" + strokeLinejoin="round" + className="tw-fill-primary tw-h-72 md:tw-h-96" + strokeWidth="4" + fillOpacity="0.25" + > + {patternTweaks[i]} + </svg> +) + +const Nr = ({ nr }) => ( + <div className="tw-absolute tw-top-8 tw-w-full tw--ml-20"> + <span className="tw-bg-primary tw-text-primary-content tw-font-bold tw-rounded-full tw-w-12 tw-h-12 tw-flex tw-items-center tw-justify-center tw-align-center tw-m-auto tw-text-3xl"> + {nr} + </span> + </div> +) + +const Title = ({ txt }) => { + const shadow = `var(--ifm-background-color)` + + return ( + <div className="tw-absolute tw-top-28 tw-left-0 tw-w-full"> + <h3 + className="tw-text-2xl tw--rotate-12 tw-w-48 tw-text-center tw-m-auto" + style={{ + textShadow: `1px 1px 1px ${shadow}, -1px -1px 1px ${shadow}, -1px 1px 1px ${shadow}, 1px -1px 1px ${shadow}`, + }} + > + {txt} + </h3> + </div> + ) +} + +const slides = [0, 1, 2, 3, 4, 5, 6, 7] + +const RecentBlogPosts = () => ( + <div> + {recentBlogPosts.map((post) => ( + <p key={post.slug}>{post.title}</p> + ))} + </div> +) diff --git a/sites/org/src/pages/patrons/index.js b/sites/org/src/pages/patrons/index.js new file mode 100644 index 00000000000..d235949997b --- /dev/null +++ b/sites/org/src/pages/patrons/index.js @@ -0,0 +1,24 @@ +// Components +import Layout from '@theme/Layout' +import { DocusaurusPage } from '@freesewing/react/components/Docusaurus' +import { PleaseSubscribe } from '@freesewing/react/components/Patrons' + +const meta = { + title: 'Join the FreeSewing Patrons', + description: + 'If you think FreeSewing is worthwhile, and if you can spare ' + + 'a few coins each month without hardship, please support our work.', +} + +export default function PatronsPage() { + return ( + <DocusaurusPage DocusaurusLayout={Layout} {...meta} Layout={false}> + <div className="tw-max-w-7xl tw-mx-auto tw-my-12 tw-px-4"> + <h1>Join the FreeSewing Patrons</h1> + <div className="tw--mx-4"> + <PleaseSubscribe /> + </div> + </div> + </DocusaurusPage> + ) +} diff --git a/sites/org/src/pages/patrons/index.md b/sites/org/src/pages/patrons/index.md deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/sites/org/src/pages/patrons/join.md b/sites/org/src/pages/patrons/join.md deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/sites/org/src/pages/patrons/join.mjs b/sites/org/src/pages/patrons/join.mjs new file mode 100644 index 00000000000..d235949997b --- /dev/null +++ b/sites/org/src/pages/patrons/join.mjs @@ -0,0 +1,24 @@ +// Components +import Layout from '@theme/Layout' +import { DocusaurusPage } from '@freesewing/react/components/Docusaurus' +import { PleaseSubscribe } from '@freesewing/react/components/Patrons' + +const meta = { + title: 'Join the FreeSewing Patrons', + description: + 'If you think FreeSewing is worthwhile, and if you can spare ' + + 'a few coins each month without hardship, please support our work.', +} + +export default function PatronsPage() { + return ( + <DocusaurusPage DocusaurusLayout={Layout} {...meta} Layout={false}> + <div className="tw-max-w-7xl tw-mx-auto tw-my-12 tw-px-4"> + <h1>Join the FreeSewing Patrons</h1> + <div className="tw--mx-4"> + <PleaseSubscribe /> + </div> + </div> + </DocusaurusPage> + ) +} diff --git a/sites/org/src/theme/BlogPostItem/index.js b/sites/org/src/theme/BlogPostItem/index.js index 7b7d6586727..30393859058 100644 --- a/sites/org/src/theme/BlogPostItem/index.js +++ b/sites/org/src/theme/BlogPostItem/index.js @@ -38,7 +38,7 @@ const BlogPostHeader = ({ type }) => { ]} /> <h1> - <span className="block text-sm capitalize">{type}:</span> + <span className="tw-block tw-text-sm tw-capitalize">{type}:</span> {metadata.title} </h1> <BlogPostItemHeaderInfo /> diff --git a/sites/org/src/theme/BlogPostItems/index.js b/sites/org/src/theme/BlogPostItems/index.js index 9ee01fe855b..7e3f95ac35d 100644 --- a/sites/org/src/theme/BlogPostItems/index.js +++ b/sites/org/src/theme/BlogPostItems/index.js @@ -13,9 +13,9 @@ const textShadow = { const teaserClasses = `tw-absolute tw-bottom-4 tw-right-0 tw-ml-3 tw-rounded-l md:tw-rounded-l-lg tw-bg-neutral tw-bg-opacity-80 tw-p-1 tw-px-4 tw-font-medium - tw-text-neutral-content tw-text-right tw-text-sm md:tw-text-lg` + tw-text-neutral-content tw-text-right tw-text-sm md:tw-text-lg lg:tw-text-xl` -const BlogPostTeaser = ({ post }) => ( +export const BlogPostTeaser = ({ post }) => ( <Link className="tw-aspect-video tw-relative tw-shadow tw-rounded-lg" href={post.content.metadata.permalink} diff --git a/sites/org/static/img/models/model-0.png b/sites/org/static/img/models/model-0.png new file mode 100644 index 00000000000..98a24792e05 Binary files /dev/null and b/sites/org/static/img/models/model-0.png differ diff --git a/sites/org/static/img/models/model-1.png b/sites/org/static/img/models/model-1.png new file mode 100644 index 00000000000..332e4b59b0d Binary files /dev/null and b/sites/org/static/img/models/model-1.png differ diff --git a/sites/org/static/img/models/model-2.png b/sites/org/static/img/models/model-2.png new file mode 100644 index 00000000000..dfbc4b87224 Binary files /dev/null and b/sites/org/static/img/models/model-2.png differ diff --git a/sites/org/static/img/models/model-3.png b/sites/org/static/img/models/model-3.png new file mode 100644 index 00000000000..d8348db4942 Binary files /dev/null and b/sites/org/static/img/models/model-3.png differ diff --git a/sites/org/static/img/models/model-4.png b/sites/org/static/img/models/model-4.png new file mode 100644 index 00000000000..7dd783a1410 Binary files /dev/null and b/sites/org/static/img/models/model-4.png differ diff --git a/sites/org/static/img/models/model-5.png b/sites/org/static/img/models/model-5.png new file mode 100644 index 00000000000..51cf61c6f4e Binary files /dev/null and b/sites/org/static/img/models/model-5.png differ diff --git a/sites/org/static/img/models/model-6.png b/sites/org/static/img/models/model-6.png new file mode 100644 index 00000000000..83d35d7fc96 Binary files /dev/null and b/sites/org/static/img/models/model-6.png differ diff --git a/sites/org/static/img/models/model-7.png b/sites/org/static/img/models/model-7.png new file mode 100644 index 00000000000..2596e3bc23b Binary files /dev/null and b/sites/org/static/img/models/model-7.png differ