diff --git a/sites/shared/.eslintignore b/sites/shared/.eslintignore
new file mode 100644
index 00000000000..b8018b39d54
--- /dev/null
+++ b/sites/shared/.eslintignore
@@ -0,0 +1,4 @@
+themes/*
+styles/*
+.eslintignore
+*.css
diff --git a/sites/shared/.eslintrc.yml b/sites/shared/.eslintrc.yml
new file mode 100644
index 00000000000..592252726ca
--- /dev/null
+++ b/sites/shared/.eslintrc.yml
@@ -0,0 +1,18 @@
+env:
+ browser: true
+ es2021: true
+extends:
+ - eslint:recommended
+ - plugin:react/recommended
+overrides: []
+parserOptions:
+ ecmaVersion: latest
+ sourceType: module
+plugins:
+ - react
+rules:
+ react/prop-types: off
+ react/react-in-jsx-scope: off
+globals:
+ module: readonly
+
diff --git a/sites/shared/components/error/error-boundary.js b/sites/shared/components/error/error-boundary.js
index 6ffef23816f..ac6c2367d42 100644
--- a/sites/shared/components/error/error-boundary.js
+++ b/sites/shared/components/error/error-boundary.js
@@ -1,55 +1,67 @@
-import React from 'react';
+import React from 'react'
import ResetButtons from './reset-buttons'
-import {EventGroup} from 'shared/components/workbench/events'
-import DefaultErrorView from './view';
+import { LogGroup } from 'shared/components/workbench/logs'
+import DefaultErrorView from './view'
const ErrorView = (props) => {
if (props.children) return props.children
const inspectChildrenProps = {
type: 'error',
- events: [props.error],
- units: props.gist?.units
+ logs: [props.error],
+ units: props.gist?.units,
}
- const inspectChildren = ()
- return (props.children || (
+ const inspectChildren =
+ return (
+ props.children || (
+
If you think your last action caused this error, you can:
- ))
+
+ )
+ )
}
class ErrorBoundary extends React.Component {
constructor(props) {
- super(props);
- this.state = { hasError: false };
+ super(props)
+ this.state = { hasError: false }
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
- return { hasError: true, error };
+ return { hasError: true, error }
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
- console.log(error, errorInfo);
+ console.log(error, errorInfo)
}
componentDidUpdate(prevProps) {
if (this.props.gist !== prevProps.gist) {
- this.setState({hasError: false})
+ this.setState({ hasError: false })
}
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
- return {this.errorView}
+ return (
+
+ {this.errorView}
+
+ )
}
try {
- return this.props.children;
- } catch(e) {
- return {this.errorView};
+ return this.props.children
+ } catch (e) {
+ return (
+
+ {this.errorView}
+
+ )
}
}
}
diff --git a/sites/shared/components/workbench/draft/error.js b/sites/shared/components/workbench/draft/error.js
index b3c2645e6c7..0cb6bf54f64 100644
--- a/sites/shared/components/workbench/draft/error.js
+++ b/sites/shared/components/workbench/draft/error.js
@@ -1,18 +1,30 @@
-import DefaultErrorView from 'shared/components/error/view';
+import DefaultErrorView from 'shared/components/error/view'
-const Error = ({ draft, patternProps, error, updateGist }) => {
- const inspectChildren = (
+const Error = ({ logs=[], updateGist }) => {
+ let errors = 0
+ let warnings = 0
+ for (const log of logs) {
+ errors += log.errors.length
+ warnings += log.warnings.length
+ }
+
+ const inspectChildren = (
+
-
- Check the
+ Check the{' '}
+
- Check the partially rendered pattern below to see which areas are problematic
-
)
+
+ )
- return (
- Don't be alarmed, but we ran into some trouble while drafting this pattern.
- )
+ return (
+
+ No need to be alarmed, but we ran into some trouble while drafting this pattern.
+
+ )
}
export default Error
diff --git a/sites/shared/components/workbench/draft/index.js b/sites/shared/components/workbench/draft/index.js
index b0625c095e8..dd963478399 100644
--- a/sites/shared/components/workbench/draft/index.js
+++ b/sites/shared/components/workbench/draft/index.js
@@ -1,16 +1,18 @@
import SvgWrapper from './svg-wrapper'
import Error from './error.js'
-const LabDraft = props => {
- const { app, draft, gist, updateGist, unsetGist, showInfo, feedback, hasRequiredMeasurements } = props
+const LabDraft = (props) => {
+ const { app, draft, gist, updateGist, unsetGist, showInfo, feedback, hasRequiredMeasurements } =
+ props
if (!draft || !hasRequiredMeasurements) return null
// Render as SVG
if (gist?.renderer === 'svg') {
let svg
- try { svg = draft.render() }
- catch(error) {
+ try {
+ svg = draft.render()
+ } catch (error) {
console.log('Failed to render design', error)
return
}
@@ -19,19 +21,26 @@ const LabDraft = props => {
// Render as React
let patternProps = {}
- try { patternProps = draft.getRenderProps() }
- catch(error) {
+ try {
+ patternProps = draft.getRenderProps()
+ } catch (error) {
console.log('Failed to get render props for design', error)
return
}
+ const errors = []
+ for (const logs of patternProps.logs) {
+ errors.push(...logs.error)
+ }
+
return (
<>
- {(!patternProps || patternProps.logs?.error?.length > 0)
- ?
- : null
- }
-
+ {!patternProps || errors.length > 0 ? (
+
+ ) : null}
+
>
)
}
diff --git a/sites/shared/components/workbench/draft/part/index.js b/sites/shared/components/workbench/draft/part/index.js
index 82b35b13ed1..54b2bcb6ff3 100644
--- a/sites/shared/components/workbench/draft/part/index.js
+++ b/sites/shared/components/workbench/draft/part/index.js
@@ -88,7 +88,7 @@ const XrayPart = props => {
export const PartInner = forwardRef((props, ref) => {
const { partName, part, gist } = props
- const grid = gist.paperless ? (
+ const Grid = gist.paperless ? (
{
) : null
return (
- {grid}
+ {Grid}
{
gist._state?.xray?.enabled &&
@@ -140,7 +140,7 @@ const Part = props => {
const { partName, part} = props
return (
-
+
)
diff --git a/sites/shared/components/workbench/draft/stack.js b/sites/shared/components/workbench/draft/stack.js
index ec7e68fd67d..95aeea434e2 100644
--- a/sites/shared/components/workbench/draft/stack.js
+++ b/sites/shared/components/workbench/draft/stack.js
@@ -2,10 +2,10 @@ import Part from './part'
import { getProps } from './utils'
const Stack = props => {
- const { stackName, stack, gist, app, updateGist, unsetGist, showInfo } = props
+ const { stack, gist, app, updateGist, unsetGist, showInfo } = props
return (
-
+
{[...stack.parts].map((part) => (
{
- const { patternProps, gist, app, updateGist, unsetGist, showInfo } = props
+ const { patternProps=false, gist, app, updateGist, unsetGist, showInfo } = props
+
+ if (!patternProps) return null
return {({ size }) => (
(
-
- {err.stack.split(/\n/g).slice(0, 5).map((l, i) => ( 0 ? ' break-all' : '')}>{l}
))}
-
-)
-
-// Markdown wrapper to suppress creation of P tags
-const Md = ({ children }) => props.children }}>{children}
-
-const Event = ({ evt, units }) => {
- if (Array.isArray(evt)) {
- if (evt[1]?.mm) return ${formatMm(evt[1].mm, units, 'html')}`
- }}/>
- else return evt.map(e => )
- }
-
- else if (evt.message) return
- else if (typeof evt === 'string') return {evt}
-
- return Note a recognized event: {JSON.stringify(evt, null ,2)}
-}
-
-export const EventGroup = ({ type='info', events=[], units='metric' }) => events.length > 0 ? (
-
-
{type}
-
-
-
- # |
- Message |
-
-
-
- {events.map((evt, i) => (
-
- {i} |
- |
-
- ))}
-
-
-
-) : null
-
-const order = [
- 'error',
- 'warning',
- 'info',
- 'debug'
-]
-const Events = props => props?.draft?.store.logs
- ? (
-
-
-
- {order.map(type => (props.draft.store.logs[type].length > 0)
- ? (
- -
- {type}
- {type === 'debug' ? '' : |}
-
- ) : (
- -
- {type}
- {type === 'debug' ? '' : |}
-
- )
- )}
-
- {order.map(type =>
)}
-
-
- ) : null
-
-export default Events
diff --git a/sites/shared/components/workbench/logs.js b/sites/shared/components/workbench/logs.js
new file mode 100644
index 00000000000..a88970fdf0c
--- /dev/null
+++ b/sites/shared/components/workbench/logs.js
@@ -0,0 +1,112 @@
+import Markdown from 'react-markdown'
+import { formatMm } from 'shared/utils'
+import { Tab, Tabs } from '../mdx/tabs.js'
+
+export const Error = ({ err }) => (
+
+ {err.stack
+ .split(/\n/g)
+ .slice(0, 5)
+ .map((l, i) => (
+ 0 ? ' break-all' : '')}
+ >
+ {l}
+
+ ))}
+
+)
+
+// Markdown wrapper to suppress creation of P tags
+const Md = ({ children }) => (
+ props.children }}>{children}
+)
+
+const Log = ({ log, units }) => {
+ if (Array.isArray(log)) {
+ if (log[1]?.mm)
+ return (
+ ${formatMm(log[1].mm, units, 'html')}`,
+ }}
+ />
+ )
+ else return log.map((l) => )
+ } else if (log.message) return
+ else if (typeof log === 'string') return {log}
+
+ return Unrecognized log: {JSON.stringify(log, null, 2)}
+}
+
+export const LogGroup = ({ type = 'info', logs = [], units = 'metric' }) =>
+ logs.length > 0 ? (
+
+
+ {type}
+
+
+
+
+ # |
+ Message |
+
+
+
+ {logs.map((log, i) => (
+
+ {i} |
+
+
+ |
+
+ ))}
+
+
+
+ ) : null
+
+const order = ['error', 'warning', 'info', 'debug']
+
+const StoreLogs = ({ logs, units }) => (
+
+
+
+ {order.map((type) =>
+ logs[type].length > 0 ? (
+ -
+
+ {type}
+
+ {type === 'debug' ? '' : |}
+
+ ) : (
+ -
+ {type}
+ {type === 'debug' ? '' : |}
+
+ )
+ )}
+
+ {order.map((type) => (
+
+ ))}
+
+
+)
+
+const Logs = (props) =>
+ props.draft.stores.length === 1 ? (
+
+ ) : (
+ `Set ${i}`).join(',')}>
+ {props.draft.stores.map((store, i) => (
+
+
+
+ ))}
+
+ )
+
+export default Logs
diff --git a/sites/shared/components/workbench/menu/view.js b/sites/shared/components/workbench/menu/view.js
index 10732f879bf..d92b08a914b 100644
--- a/sites/shared/components/workbench/menu/view.js
+++ b/sites/shared/components/workbench/menu/view.js
@@ -1,90 +1,92 @@
import MenuIcon from 'shared/components/icons/menu.js'
import { linkClasses, Chevron } from 'shared/components/navigation/primary.js'
import { useTranslation } from 'next-i18next'
-import {defaultGist} from 'shared/hooks/useGist'
+import { defaultGist } from 'shared/hooks/useGist'
-const View = props => {
+const View = (props) => {
const { t } = useTranslation(['app'])
const entries = [
{
name: 'measurements',
title: t('measurements'),
- onClick: () => props.updateGist(['_state', 'view'], 'measurements', true)
+ onClick: () => props.updateGist(['_state', 'view'], 'measurements', true),
},
{
name: 'draft',
title: t('draftDesign', { design: props.design.config.data.name }),
- onClick: () => props.updateGist(['_state', 'view'], 'draft', true)
+ onClick: () => props.updateGist(['_state', 'view'], 'draft', true),
},
{
name: 'test',
title: t('testDesign', { design: props.design.config.data.name }),
- onClick: () => props.updateGist(['_state', 'view'], 'test', true)
+ onClick: () => props.updateGist(['_state', 'view'], 'test', true),
},
{
name: 'printingLayout',
- title: t('layoutThing', { thing: props.design.config.data.name })
- + ': ' + t('forPrinting'),
- onClick: () => props.updateGist(['_state', 'view'], 'printingLayout', true)
+ title: t('layoutThing', { thing: props.design.config.data.name }) + ': ' + t('forPrinting'),
+ onClick: () => props.updateGist(['_state', 'view'], 'printingLayout', true),
},
{
name: 'cuttingLayout',
- title: t('layoutThing', { thing: props.design.config.data.name })
- + ': ' + t('forCutting'),
- onClick: () => props.updateGist(['_state', 'view'], 'cuttingLayout', true)
+ title: t('layoutThing', { thing: props.design.config.data.name }) + ': ' + t('forCutting'),
+ onClick: () => props.updateGist(['_state', 'view'], 'cuttingLayout', true),
},
{
name: 'export',
title: t('exportThing', { thing: props.design.config.data.name }),
- onClick: () => props.updateGist(['_state', 'view'], 'export', true)
+ onClick: () => props.updateGist(['_state', 'view'], 'export', true),
},
{
- name: 'events',
- title: t('events'),
- onClick: () => props.updateGist(['_state', 'view'], 'events', true)
+ name: 'logs',
+ title: t('logs'),
+ onClick: () => props.updateGist(['_state', 'view'], 'logs', true),
},
{
name: 'yaml',
title: t('YAML'),
- onClick: () => props.updateGist(['_state', 'view'], 'yaml', true)
+ onClick: () => props.updateGist(['_state', 'view'], 'yaml', true),
},
{
name: 'json',
title: t('JSON'),
- onClick: () => props.updateGist(['_state', 'view'], 'json', true)
+ onClick: () => props.updateGist(['_state', 'view'], 'json', true),
},
{
name: 'edit',
title: t('editThing', { thing: 'YAML' }),
- onClick: () => props.updateGist(['_state', 'view'], 'edit', true)
+ onClick: () => props.updateGist(['_state', 'view'], 'edit', true),
},
{
name: 'clear',
title: t('clearThing', { thing: 'YAML' }),
- onClick: () => props.setGist(defaultGist(props.design, props.gist.locale))
+ onClick: () => props.setGist(defaultGist(props.design, props.gist.locale)),
},
]
return (
-
-
+
-
-
- {t('view')}
+ `}
+ >
+
+
+ {t('view')}
- {entries.map(entry => (
+ {entries.map((entry) => (
-
-
diff --git a/sites/shared/components/workbench/sample.js b/sites/shared/components/workbench/sample.js
index 29506dbe8f9..c7e6806b8cb 100644
--- a/sites/shared/components/workbench/sample.js
+++ b/sites/shared/components/workbench/sample.js
@@ -1,18 +1,24 @@
+import SvgWrapper from './draft/svg-wrapper'
+import Error from './draft/error.js'
import { svgattrPlugin } from '@freesewing/plugin-svgattr'
import { useTranslation } from 'next-i18next'
-const LabSample = ({ gist, draft }) => {
+const LabSample = ({ gist, draft, updateGist, unsetGist, showInfo, app, feedback }) => {
const { t } = useTranslation(['workbench'])
let svg
let title = ''
+ let patternProps
+ const errors = []
if (gist.sample) {
try {
draft.use(svgattrPlugin, {
class: 'freesewing pattern max-h-screen'
})
- draft.sample()
- svg = draft.render()
+ draft = draft.sample()
+ // Render as React
+ patternProps = draft.getRenderProps()
+ for (const logs of patternProps.logs) errors.push(...logs.error)
}
catch(err) {
console.log(err)
@@ -27,6 +33,12 @@ const LabSample = ({ gist, draft }) => {
return (
<>
{title}
+ {!patternProps || errors.length > 0 ? (
+
+ ) : null}
+
>
)
diff --git a/sites/shared/components/wrappers/workbench.js b/sites/shared/components/wrappers/workbench.js
index 35548de590a..c98321aa281 100644
--- a/sites/shared/components/wrappers/workbench.js
+++ b/sites/shared/components/wrappers/workbench.js
@@ -1,5 +1,5 @@
-import { useEffect, useState, useMemo,} from 'react'
-import {useGist} from 'shared/hooks/useGist'
+import { useEffect, useState, useMemo } from 'react'
+import { useGist } from 'shared/hooks/useGist'
import Layout from 'shared/components/layouts/default'
import Menu from 'shared/components/workbench/menu/index.js'
import DraftError from 'shared/components/workbench/draft/error.js'
@@ -14,11 +14,11 @@ import LabSample from 'shared/components/workbench/sample.js'
import ExportDraft from 'shared/components/workbench/exporting/index.js'
import GistAsJson from 'shared/components/workbench/gist-as-json.js'
import GistAsYaml from 'shared/components/workbench/yaml.js'
-import DraftEvents from 'shared/components/workbench/events.js'
+import DraftLogs from 'shared/components/workbench/logs.js'
import CutLayout from 'shared/components/workbench/layout/cut'
import PrintingLayout from 'shared/components/workbench/layout/print'
-import ErrorBoundary from 'shared/components/error/error-boundary';
+import ErrorBoundary from 'shared/components/error/error-boundary'
const views = {
measurements: Measurements,
@@ -27,7 +27,7 @@ const views = {
printingLayout: PrintingLayout,
cuttingLayout: CutLayout,
export: ExportDraft,
- events: DraftEvents,
+ logs: DraftLogs,
yaml: GistAsYaml,
json: GistAsJson,
welcome: () => TODO
,
@@ -54,15 +54,16 @@ const doPreload = async (preload, from, design, gist, setGist, setPreloaded) =>
* keeping the gist state, which will trickle down
* to all workbench subcomponents
*/
-const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false }) => {
-
+const WorkbenchWrapper = ({ app, design, preload = false, from = false, layout = false }) => {
// State for gist
- const {gist, setGist, unsetGist, updateGist, gistReady, undoGist, resetGist} = useGist(design, app);
+ const { gist, setGist, unsetGist, updateGist, gistReady, undoGist, resetGist } = useGist(
+ design,
+ app
+ )
const [messages, setMessages] = useState([])
const [popup, setPopup] = useState(false)
const [preloaded, setPreloaded] = useState(false)
-
// We'll use this in more than one location
const hasRequiredMeasurements = hasRequiredMeasurementsMethod(design, gist)
@@ -70,34 +71,31 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
// force view to measurements
useEffect(() => {
if (!gistReady) return
- if (gist._state?.view !== 'measurements'
- && !hasRequiredMeasurements
- ) updateGist(['_state', 'view'], 'measurements')
+ if (gist._state?.view !== 'measurements' && !hasRequiredMeasurements)
+ updateGist(['_state', 'view'], 'measurements')
}, [gistReady, gist._state?.view, hasRequiredMeasurements])
// If we need to preload the gist, do so
useEffect(() => {
- if (
- preload &&
- preload !== preloaded &&
- from &&
- preloaders[from]
- ) {
- doPreload(preload, from, design, gist, setGist, setPreloaded)
+ if (preload && preload !== preloaded && from && preloaders[from]) {
+ doPreload(preload, from, design, gist, setGist, setPreloaded)
}
}, [preload, preloaded, from, design])
-
// Helper methods to manage the gist state
- const updateWBGist = useMemo(() => (path, value, closeNav=false, addToHistory=true) => {
- updateGist(path, value, addToHistory)
- // Force close of menu on mobile if it is open
- if (closeNav && app.primaryMenu) app.setPrimaryMenu(false)
- }, [app])
+ const updateWBGist = useMemo(
+ () =>
+ (path, value, closeNav = false, addToHistory = true) => {
+ updateGist(path, value, addToHistory)
+ // Force close of menu on mobile if it is open
+ if (closeNav && app.primaryMenu) app.setPrimaryMenu(false)
+ },
+ [app]
+ )
// Helper methods to handle messages
const feedback = {
- add: msg => {
+ add: (msg) => {
const newMsgs = [...messages]
if (Array.isArray(msg)) newMsgs.push(...msg)
else newMsgs.push(msg)
@@ -108,16 +106,18 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
}
// don't do anything until the gist is ready
- if (!gistReady) {return null}
+ if (!gistReady) {
+ return null
+ }
// Generate the draft here so we can pass it down to both the view and the options menu
let draft = false
- if (['draft', 'events', 'test', 'printingLayout'].indexOf(gist._state?.view) !== -1) {
+ if (['draft', 'logs', 'test', 'printingLayout'].indexOf(gist._state?.view) !== -1) {
gist.embed = true
// get the appropriate layout for the view
const layout = gist.layouts?.[gist._state.view] || gist.layout || true
// hand it separately to the design
- draft = new design({...gist, layout})
+ draft = new design({ ...gist, layout })
draft.init()
// add theme to svg renderer
@@ -125,9 +125,8 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
// draft it for draft and event views. Other views may add plugins, etc and we don't want to draft twice
try {
- if (['draft', 'events'].indexOf(gist._state.view) > -1) draft.draft()
- }
- catch(error) {
+ if (['draft', 'logs'].indexOf(gist._state.view) > -1) draft.draft()
+ } catch (error) {
console.log('Failed to draft design', error)
return
}
@@ -152,33 +151,30 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
app: app,
noSearch: true,
workbench: true,
- AltMenu:
,
+ AltMenu: ,
showInfo: setPopup,
}
const errorProps = {
undoGist,
resetGist,
- gist
+ gist,
}
// Layout to use
- const LayoutComponent = layout
- ? layout
- : Layout
+ const LayoutComponent = layout ? layout : Layout
- const Component = views[gist._state?.view]
- ? views[gist._state.view]
- : views.welcome
+ const Component = views[gist._state?.view] ? views[gist._state.view] : views.welcome
- return
- {messages}
-
-
- {popup && setPopup(false)}>{popup}}
-
-
+ return (
+
+ {messages}
+
+
+ {popup && setPopup(false)}>{popup}}
+
+
+ )
}
export default WorkbenchWrapper
-
diff --git a/sites/shared/config/postcss.config.js b/sites/shared/config/postcss.config.js
index 8aeb8379b4a..5e92fafc535 100644
--- a/sites/shared/config/postcss.config.js
+++ b/sites/shared/config/postcss.config.js
@@ -1,4 +1,4 @@
// Can't seem to make this work as ESM
module.exports = {
- plugins: ['tailwindcss/nesting', 'tailwindcss', 'autoprefixer'],
+ plugins: ['tailwindcss/nesting', 'tailwindcss', 'autoprefixer', 'postcss-for'],
}
diff --git a/sites/shared/package.json b/sites/shared/package.json
index c91f3314416..b3dbcc730aa 100644
--- a/sites/shared/package.json
+++ b/sites/shared/package.json
@@ -28,6 +28,7 @@
"lodash.unset": "^4.5.2",
"mdast-util-toc": "^6.1.0",
"pdfkit": "^0.13.0",
+ "postcss-for": "^2.1.1",
"react-markdown": "^8.0.0",
"react-sizeme": "^3.0.2",
"react-timeago": "^7.1.0",
@@ -44,6 +45,8 @@
},
"devDependencies": {
"autoprefixer": "^10.4.0",
+ "eslint": "^8.23.1",
+ "eslint-plugin-react": "^7.31.8",
"lodash.set": "^4.3.2",
"postcss": "^8.4.4",
"tailwindcss": "^3.0.1",
diff --git a/sites/shared/styles/svg-freesewing-draft.css b/sites/shared/styles/svg-freesewing-draft.css
index 88b2ef7988f..9cf2db6d879 100644
--- a/sites/shared/styles/svg-freesewing-draft.css
+++ b/sites/shared/styles/svg-freesewing-draft.css
@@ -161,6 +161,20 @@ svg.freesewing.pattern {
}
}
+/* Styling for v3 sampling */
+@for $i from 1 to 10 {
+
+ svg.freesewing.pattern g.sample-$i path.fabric,
+ svg.freesewing.pattern g.sample-$i path.lining,
+ svg.freesewing.pattern g.sample-$i path.interfacing {
+ stroke: var(--pattern-sample-$i);
+ fill: var(--pattern-sample-$i);
+ fill-opacity: 0.01;
+ }
+
+}
+
+
/* Styling the shadow DOM is hard to do
* This is for styling FreeSewing snippets
* TODO: Update snippets to use inline styles with CSS vars
@@ -257,3 +271,6 @@ figure.develop.example div.develop {
}
}
+
+
+
diff --git a/sites/shared/themes/light.js b/sites/shared/themes/light.js
index 5904970a87f..8e05a2a6f04 100644
--- a/sites/shared/themes/light.js
+++ b/sites/shared/themes/light.js
@@ -257,4 +257,17 @@ module.exports = {
'--pattern-stroke-6xl': "16px",
// Pattern 7xl stroke width
'--pattern-stroke-7xl': "20px",
+
+ // Pattern sampling styles
+ '--pattern-sample-1': colors.red["500"],
+ '--pattern-sample-2': colors.orange["500"],
+ '--pattern-sample-3': colors.yellow["500"],
+ '--pattern-sample-4': colors.lime["500"],
+ '--pattern-sample-5': colors.emerald["500"],
+ '--pattern-sample-6': colors.cyan["500"],
+ '--pattern-sample-7': colors.blue["500"],
+ '--pattern-sample-8': colors.violet["500"],
+ '--pattern-sample-9': colors.fuchsia["500"],
+ '--pattern-sample-10': colors.rose["500"],
+
}
diff --git a/yarn.lock b/yarn.lock
index 0d07dc1582e..89a50ceeded 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7934,6 +7934,26 @@ eslint-plugin-react@^7.28.0, eslint-plugin-react@^7.29.4:
semver "^6.3.0"
string.prototype.matchall "^4.0.7"
+eslint-plugin-react@^7.31.8:
+ version "7.31.8"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz#3a4f80c10be1bcbc8197be9e8b641b2a3ef219bf"
+ integrity sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw==
+ dependencies:
+ array-includes "^3.1.5"
+ array.prototype.flatmap "^1.3.0"
+ doctrine "^2.1.0"
+ estraverse "^5.3.0"
+ jsx-ast-utils "^2.4.1 || ^3.0.0"
+ minimatch "^3.1.2"
+ object.entries "^1.1.5"
+ object.fromentries "^2.0.5"
+ object.hasown "^1.1.1"
+ object.values "^1.1.5"
+ prop-types "^15.8.1"
+ resolve "^2.0.0-next.3"
+ semver "^6.3.0"
+ string.prototype.matchall "^4.0.7"
+
eslint-plugin-yaml@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-yaml/-/eslint-plugin-yaml-0.5.0.tgz#8c79d9d6389b67cbcf58ef6f970c4c086665a63a"
@@ -9555,6 +9575,11 @@ has-bigints@^1.0.1, has-bigints@^1.0.2:
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
+has-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+ integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==
+
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -11124,6 +11149,11 @@ jest-validate@^27.3.1, jest-validate@^27.4.2:
leven "^3.1.0"
pretty-format "^27.5.1"
+js-base64@^2.1.9:
+ version "2.6.4"
+ resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
+ integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
+
js-sdsl@^4.1.4:
version "4.1.4"
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.4.tgz#78793c90f80e8430b7d8dc94515b6c77d98a26a6"
@@ -15346,6 +15376,14 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==
+postcss-for@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-for/-/postcss-for-2.1.1.tgz#841378c0ef909d50e1980d5aa71e6a340e728fcd"
+ integrity sha512-X0R84FCyr5cqzW4+/g4Dvz2OUe1iwC3G/atIrwEpiRstZlBBpknV+ETlIneSTnw/iXgUnEoTRaO2qXY62YWLhQ==
+ dependencies:
+ postcss "^5.0.0"
+ postcss-simple-vars "^2.0.0"
+
postcss-import@^14.1.0:
version "14.1.0"
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0"
@@ -15385,6 +15423,13 @@ postcss-selector-parser@6.0.10, postcss-selector-parser@^6.0.10, postcss-selecto
cssesc "^3.0.0"
util-deprecate "^1.0.2"
+postcss-simple-vars@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-simple-vars/-/postcss-simple-vars-2.0.0.tgz#d0a1091b0da22b79507028f7b22b976c0a60b8d5"
+ integrity sha512-HllLaKKCBOdKudyzqrw/ve5rWouM9cDL+WHaSF9q4CkBEPjdTdiKNw1xF2dAz5rUKrxVmnUmOYxamwy37dnq2Q==
+ dependencies:
+ postcss "^5.0.21"
+
postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
@@ -15408,6 +15453,16 @@ postcss@8.4.14:
picocolors "^1.0.0"
source-map-js "^1.0.2"
+postcss@^5.0.0, postcss@^5.0.21:
+ version "5.2.18"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5"
+ integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==
+ dependencies:
+ chalk "^1.1.3"
+ js-base64 "^2.1.9"
+ source-map "^0.5.6"
+ supports-color "^3.2.3"
+
postcss@^8.4.12, postcss@^8.4.14, postcss@^8.4.4, postcss@^8.4.5:
version "8.4.16"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.16.tgz#33a1d675fac39941f5f445db0de4db2b6e01d43c"
@@ -18188,6 +18243,13 @@ supports-color@^2.0.0:
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
+supports-color@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+ integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==
+ dependencies:
+ has-flag "^1.0.0"
+
supports-color@^5.3.0, supports-color@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"