chore(lab): Changes to handle multisets in core
This commit is contained in:
parent
e163ed1782
commit
f882a26408
18 changed files with 413 additions and 212 deletions
4
sites/shared/.eslintignore
Normal file
4
sites/shared/.eslintignore
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
themes/*
|
||||||
|
styles/*
|
||||||
|
.eslintignore
|
||||||
|
*.css
|
18
sites/shared/.eslintrc.yml
Normal file
18
sites/shared/.eslintrc.yml
Normal file
|
@ -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
|
||||||
|
|
|
@ -1,55 +1,67 @@
|
||||||
import React from 'react';
|
import React from 'react'
|
||||||
import ResetButtons from './reset-buttons'
|
import ResetButtons from './reset-buttons'
|
||||||
import {EventGroup} from 'shared/components/workbench/events'
|
import { LogGroup } from 'shared/components/workbench/logs'
|
||||||
import DefaultErrorView from './view';
|
import DefaultErrorView from './view'
|
||||||
|
|
||||||
const ErrorView = (props) => {
|
const ErrorView = (props) => {
|
||||||
if (props.children) return props.children
|
if (props.children) return props.children
|
||||||
|
|
||||||
const inspectChildrenProps = {
|
const inspectChildrenProps = {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
events: [props.error],
|
logs: [props.error],
|
||||||
units: props.gist?.units
|
units: props.gist?.units,
|
||||||
}
|
}
|
||||||
const inspectChildren = (<EventGroup {...inspectChildrenProps}></EventGroup>)
|
const inspectChildren = <LogGroup {...inspectChildrenProps}></LogGroup>
|
||||||
return (props.children || (<DefaultErrorView inspectChildren={inspectChildren}>
|
return (
|
||||||
|
props.children || (
|
||||||
|
<DefaultErrorView inspectChildren={inspectChildren}>
|
||||||
<h4>If you think your last action caused this error, you can: </h4>
|
<h4>If you think your last action caused this error, you can: </h4>
|
||||||
<ResetButtons undoGist={props.undoGist} resetGist={props.resetGist} />
|
<ResetButtons undoGist={props.undoGist} resetGist={props.resetGist} />
|
||||||
</DefaultErrorView>))
|
</DefaultErrorView>
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ErrorBoundary extends React.Component {
|
class ErrorBoundary extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props)
|
||||||
this.state = { hasError: false };
|
this.state = { hasError: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDerivedStateFromError(error) {
|
static getDerivedStateFromError(error) {
|
||||||
// Update state so the next render will show the fallback UI.
|
// Update state so the next render will show the fallback UI.
|
||||||
return { hasError: true, error };
|
return { hasError: true, error }
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidCatch(error, errorInfo) {
|
componentDidCatch(error, errorInfo) {
|
||||||
// You can also log the error to an error reporting service
|
// You can also log the error to an error reporting service
|
||||||
console.log(error, errorInfo);
|
console.log(error, errorInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if (this.props.gist !== prevProps.gist) {
|
if (this.props.gist !== prevProps.gist) {
|
||||||
this.setState({hasError: false})
|
this.setState({ hasError: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.hasError) {
|
if (this.state.hasError) {
|
||||||
// You can render any custom fallback UI
|
// You can render any custom fallback UI
|
||||||
return <ErrorView {...this.props} error={this.state.error}>{this.errorView}</ErrorView>
|
return (
|
||||||
|
<ErrorView {...this.props} error={this.state.error}>
|
||||||
|
{this.errorView}
|
||||||
|
</ErrorView>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return this.props.children;
|
return this.props.children
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
return <ErrorView {...this.props} error={e}>{this.errorView}</ErrorView>;
|
return (
|
||||||
|
<ErrorView {...this.props} error={e}>
|
||||||
|
{this.errorView}
|
||||||
|
</ErrorView>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 Error = ({ logs=[], updateGist }) => {
|
||||||
const inspectChildren = (<ul className="list-disc list-inside ml-4 text-xl">
|
let errors = 0
|
||||||
|
let warnings = 0
|
||||||
|
for (const log of logs) {
|
||||||
|
errors += log.errors.length
|
||||||
|
warnings += log.warnings.length
|
||||||
|
}
|
||||||
|
|
||||||
|
const inspectChildren = (
|
||||||
|
<ul className="list-disc list-inside ml-4 text-xl">
|
||||||
<li>
|
<li>
|
||||||
Check the <button className="btn-link" onClick={() => updateGist(['_state', 'view'], 'events')}>
|
Check the{' '}
|
||||||
<strong>{patternProps?.events?.error?.length} errors</strong> and <strong>
|
<button className="btn-link" onClick={() => updateGist(['_state', 'view'], 'logs')}>
|
||||||
{patternProps?.events?.warning?.length} warnings</strong></button>
|
<strong>{errors.length} errors</strong> and <strong>{warnings.length} warnings</strong>
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li>Check the partially rendered pattern below to see which areas are problematic</li>
|
<li>Check the partially rendered pattern below to see which areas are problematic</li>
|
||||||
</ul>)
|
</ul>
|
||||||
|
)
|
||||||
|
|
||||||
return (<DefaultErrorView inspectChildren={inspectChildren}>
|
return (
|
||||||
<p>Don't be alarmed, but we ran into some trouble while drafting this pattern.</p>
|
<DefaultErrorView inspectChildren={inspectChildren}>
|
||||||
</DefaultErrorView>)
|
<p>No need to be alarmed, but we ran into some trouble while drafting this pattern.</p>
|
||||||
|
</DefaultErrorView>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Error
|
export default Error
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import SvgWrapper from './svg-wrapper'
|
import SvgWrapper from './svg-wrapper'
|
||||||
import Error from './error.js'
|
import Error from './error.js'
|
||||||
|
|
||||||
const LabDraft = props => {
|
const LabDraft = (props) => {
|
||||||
const { app, draft, gist, updateGist, unsetGist, showInfo, feedback, hasRequiredMeasurements } = props
|
const { app, draft, gist, updateGist, unsetGist, showInfo, feedback, hasRequiredMeasurements } =
|
||||||
|
props
|
||||||
|
|
||||||
if (!draft || !hasRequiredMeasurements) return null
|
if (!draft || !hasRequiredMeasurements) return null
|
||||||
|
|
||||||
// Render as SVG
|
// Render as SVG
|
||||||
if (gist?.renderer === 'svg') {
|
if (gist?.renderer === 'svg') {
|
||||||
let svg
|
let svg
|
||||||
try { svg = draft.render() }
|
try {
|
||||||
catch(error) {
|
svg = draft.render()
|
||||||
|
} catch (error) {
|
||||||
console.log('Failed to render design', error)
|
console.log('Failed to render design', error)
|
||||||
return <Error error={error} {...props} />
|
return <Error error={error} {...props} />
|
||||||
}
|
}
|
||||||
|
@ -19,19 +21,26 @@ const LabDraft = props => {
|
||||||
|
|
||||||
// Render as React
|
// Render as React
|
||||||
let patternProps = {}
|
let patternProps = {}
|
||||||
try { patternProps = draft.getRenderProps() }
|
try {
|
||||||
catch(error) {
|
patternProps = draft.getRenderProps()
|
||||||
|
} catch (error) {
|
||||||
console.log('Failed to get render props for design', error)
|
console.log('Failed to get render props for design', error)
|
||||||
return <Error error={error} {...props} />
|
return <Error error={error} {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const errors = []
|
||||||
|
for (const logs of patternProps.logs) {
|
||||||
|
errors.push(...logs.error)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{(!patternProps || patternProps.logs?.error?.length > 0)
|
{!patternProps || errors.length > 0 ? (
|
||||||
? <Error {...{ draft, patternProps, updateGist }} />
|
<Error {...{ draft, patternProps, updateGist }} />
|
||||||
: null
|
) : null}
|
||||||
}
|
<SvgWrapper
|
||||||
<SvgWrapper {...{ draft, patternProps, gist, updateGist, unsetGist, showInfo, app, feedback }} />
|
{...{ draft, patternProps, gist, updateGist, unsetGist, showInfo, app, feedback }}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ const XrayPart = props => {
|
||||||
export const PartInner = forwardRef((props, ref) => {
|
export const PartInner = forwardRef((props, ref) => {
|
||||||
const { partName, part, gist } = props
|
const { partName, part, gist } = props
|
||||||
|
|
||||||
const grid = gist.paperless ? (
|
const Grid = gist.paperless ? (
|
||||||
<rect
|
<rect
|
||||||
x={part.topLeft.x}
|
x={part.topLeft.x}
|
||||||
y={part.topLeft.y}
|
y={part.topLeft.y}
|
||||||
|
@ -100,7 +100,7 @@ export const PartInner = forwardRef((props, ref) => {
|
||||||
) : null
|
) : null
|
||||||
|
|
||||||
return (<g ref={ref}>
|
return (<g ref={ref}>
|
||||||
{grid}
|
{Grid}
|
||||||
{
|
{
|
||||||
gist._state?.xray?.enabled &&
|
gist._state?.xray?.enabled &&
|
||||||
<XrayPart {...props} />
|
<XrayPart {...props} />
|
||||||
|
@ -140,7 +140,7 @@ const Part = props => {
|
||||||
const { partName, part} = props
|
const { partName, part} = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g {...getProps(part)} id={`part-${partName}`}>
|
<g {...getProps(part)} id={`${part.context.settings.idPrefix || ''}part-${partName}`} className={part.context.settings.idPrefix || ''}>
|
||||||
<PartInner {...props}/>
|
<PartInner {...props}/>
|
||||||
</g>
|
</g>
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,10 +2,10 @@ import Part from './part'
|
||||||
import { getProps } from './utils'
|
import { getProps } from './utils'
|
||||||
|
|
||||||
const Stack = props => {
|
const Stack = props => {
|
||||||
const { stackName, stack, gist, app, updateGist, unsetGist, showInfo } = props
|
const { stack, gist, app, updateGist, unsetGist, showInfo } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g {...getProps(stack)} id={`stack-${stackName}`}>
|
<g {...getProps(stack)}>
|
||||||
{[...stack.parts].map((part) => (
|
{[...stack.parts].map((part) => (
|
||||||
<Part {...{ app, gist, updateGist, unsetGist, showInfo }}
|
<Part {...{ app, gist, updateGist, unsetGist, showInfo }}
|
||||||
key={part.name}
|
key={part.name}
|
||||||
|
|
|
@ -26,7 +26,9 @@ import Stack from './stack'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const SvgWrapper = props => {
|
const SvgWrapper = props => {
|
||||||
const { patternProps, gist, app, updateGist, unsetGist, showInfo } = props
|
const { patternProps=false, gist, app, updateGist, unsetGist, showInfo } = props
|
||||||
|
|
||||||
|
if (!patternProps) return null
|
||||||
|
|
||||||
return <SizeMe>{({ size }) => (
|
return <SizeMe>{({ size }) => (
|
||||||
<TransformWrapper
|
<TransformWrapper
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
import Markdown from 'react-markdown'
|
|
||||||
import { formatMm } from 'shared/utils'
|
|
||||||
|
|
||||||
export const Error = ({err}) => (
|
|
||||||
<pre>
|
|
||||||
{err.stack.split(/\n/g).slice(0, 5).map((l, i) => (<code key={`error-${i}`} className={'block whitespace-pre-wrap' + (i > 0 ? ' break-all' : '')}>{l}</code>))}
|
|
||||||
</pre>
|
|
||||||
)
|
|
||||||
|
|
||||||
// Markdown wrapper to suppress creation of P tags
|
|
||||||
const Md = ({ children }) => <Markdown components={{ p: props => props.children }}>{children}</Markdown>
|
|
||||||
|
|
||||||
const Event = ({ evt, units }) => {
|
|
||||||
if (Array.isArray(evt)) {
|
|
||||||
if (evt[1]?.mm) return <span dangerouslySetInnerHTML={{
|
|
||||||
__html: `${evt[0]}: <strong>${formatMm(evt[1].mm, units, 'html')}</strong>`
|
|
||||||
}}/>
|
|
||||||
else return evt.map(e => <Event evt={e} key={e} />)
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (evt.message) return <Error err={evt} />
|
|
||||||
else if (typeof evt === 'string') return <Md>{evt}</Md>
|
|
||||||
|
|
||||||
return <Md>Note a recognized event: {JSON.stringify(evt, null ,2)}</Md>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EventGroup = ({ type='info', events=[], units='metric' }) => events.length > 0 ? (
|
|
||||||
<div className="">
|
|
||||||
<h3 className="capitalize" id={`events-${type}`}>{type}</h3>
|
|
||||||
<table className="table w-full mdx">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th className="text-right w-16">#</th>
|
|
||||||
<th>Message</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{events.map((evt, i) => (
|
|
||||||
<tr key={i} className="leading-1 hover:bg-base-200 hover:bg-opacity-40">
|
|
||||||
<td className="text-right p-1 pr-4 font-bold opacity-80 text-accent">{i}</td>
|
|
||||||
<td className="p-1 pl-4"><Event evt={evt} units={units}/></td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
) : null
|
|
||||||
|
|
||||||
const order = [
|
|
||||||
'error',
|
|
||||||
'warning',
|
|
||||||
'info',
|
|
||||||
'debug'
|
|
||||||
]
|
|
||||||
const Events = props => props?.draft?.store.logs
|
|
||||||
? (
|
|
||||||
<div className="max-w-screen-xl m-auto">
|
|
||||||
<div className="flex flex-col">
|
|
||||||
<ul className="flex flex-row row-wrap">
|
|
||||||
{order.map(type => (props.draft.store.logs[type].length > 0)
|
|
||||||
? (
|
|
||||||
<li key={type} className="">
|
|
||||||
<a href={`#events-${type}`} className={`text-secondary font-bold capitalize text-xl`}>{type}</a>
|
|
||||||
{type === 'debug' ? '' : <span className="px-2 font-bold">|</span>}
|
|
||||||
</li>
|
|
||||||
) : (
|
|
||||||
<li key={type} className="text-base-content font-bold capitalize text-xl">
|
|
||||||
<span className="opacity-50">{type}</span>
|
|
||||||
{type === 'debug' ? '' : <span className="px-2 font-bold">|</span>}
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
{order.map(type => <EventGroup type={type} events={props.draft.store.logs[type]} units={props.gist.units}/>)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : null
|
|
||||||
|
|
||||||
export default Events
|
|
112
sites/shared/components/workbench/logs.js
Normal file
112
sites/shared/components/workbench/logs.js
Normal file
|
@ -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 }) => (
|
||||||
|
<pre>
|
||||||
|
{err.stack
|
||||||
|
.split(/\n/g)
|
||||||
|
.slice(0, 5)
|
||||||
|
.map((l, i) => (
|
||||||
|
<code
|
||||||
|
key={`error-${i}`}
|
||||||
|
className={'block whitespace-pre-wrap' + (i > 0 ? ' break-all' : '')}
|
||||||
|
>
|
||||||
|
{l}
|
||||||
|
</code>
|
||||||
|
))}
|
||||||
|
</pre>
|
||||||
|
)
|
||||||
|
|
||||||
|
// Markdown wrapper to suppress creation of P tags
|
||||||
|
const Md = ({ children }) => (
|
||||||
|
<Markdown components={{ p: (props) => props.children }}>{children}</Markdown>
|
||||||
|
)
|
||||||
|
|
||||||
|
const Log = ({ log, units }) => {
|
||||||
|
if (Array.isArray(log)) {
|
||||||
|
if (log[1]?.mm)
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `${log[0]}: <strong>${formatMm(log[1].mm, units, 'html')}</strong>`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
else return log.map((l) => <Log log={l} key={l} />)
|
||||||
|
} else if (log.message) return <Error err={log} />
|
||||||
|
else if (typeof log === 'string') return <Md>{log}</Md>
|
||||||
|
|
||||||
|
return <Md>Unrecognized log: {JSON.stringify(log, null, 2)}</Md>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LogGroup = ({ type = 'info', logs = [], units = 'metric' }) =>
|
||||||
|
logs.length > 0 ? (
|
||||||
|
<div className="">
|
||||||
|
<h3 className="capitalize" id={`logs-${type}`}>
|
||||||
|
{type}
|
||||||
|
</h3>
|
||||||
|
<table className="table w-full mdx">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th className="text-right w-16">#</th>
|
||||||
|
<th>Message</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{logs.map((log, i) => (
|
||||||
|
<tr key={i} className="leading-1 hover:bg-base-200 hover:bg-opacity-40">
|
||||||
|
<td className="text-right p-1 pr-4 font-bold opacity-80 text-accent">{i}</td>
|
||||||
|
<td className="p-1 pl-4">
|
||||||
|
<Log log={log} units={units} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
) : null
|
||||||
|
|
||||||
|
const order = ['error', 'warning', 'info', 'debug']
|
||||||
|
|
||||||
|
const StoreLogs = ({ logs, units }) => (
|
||||||
|
<div className="max-w-screen-xl m-auto">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<ul className="flex flex-row row-wrap">
|
||||||
|
{order.map((type) =>
|
||||||
|
logs[type].length > 0 ? (
|
||||||
|
<li key={type} className="">
|
||||||
|
<a href={`#logs-${type}`} className={`text-secondary font-bold capitalize text-xl`}>
|
||||||
|
{type}
|
||||||
|
</a>
|
||||||
|
{type === 'debug' ? '' : <span className="px-2 font-bold">|</span>}
|
||||||
|
</li>
|
||||||
|
) : (
|
||||||
|
<li key={type} className="text-base-content font-bold capitalize text-xl">
|
||||||
|
<span className="opacity-50">{type}</span>
|
||||||
|
{type === 'debug' ? '' : <span className="px-2 font-bold">|</span>}
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
{order.map((type) => (
|
||||||
|
<LogGroup type={type} logs={logs[type]} units={units} key={type} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const Logs = (props) =>
|
||||||
|
props.draft.stores.length === 1 ? (
|
||||||
|
<StoreLogs logs={props.draft.stores[0].logs} units={props.gist.units} />
|
||||||
|
) : (
|
||||||
|
<Tabs tabs={props.draft.stores.map((store, i) => `Set ${i}`).join(',')}>
|
||||||
|
{props.draft.stores.map((store, i) => (
|
||||||
|
<Tab key={i}>
|
||||||
|
<StoreLogs logs={store.logs} units={props.gist.units} />
|
||||||
|
</Tab>
|
||||||
|
))}
|
||||||
|
</Tabs>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Logs
|
|
@ -1,90 +1,92 @@
|
||||||
import MenuIcon from 'shared/components/icons/menu.js'
|
import MenuIcon from 'shared/components/icons/menu.js'
|
||||||
import { linkClasses, Chevron } from 'shared/components/navigation/primary.js'
|
import { linkClasses, Chevron } from 'shared/components/navigation/primary.js'
|
||||||
import { useTranslation } from 'next-i18next'
|
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 { t } = useTranslation(['app'])
|
||||||
const entries = [
|
const entries = [
|
||||||
{
|
{
|
||||||
name: 'measurements',
|
name: 'measurements',
|
||||||
title: t('measurements'),
|
title: t('measurements'),
|
||||||
onClick: () => props.updateGist(['_state', 'view'], 'measurements', true)
|
onClick: () => props.updateGist(['_state', 'view'], 'measurements', true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'draft',
|
name: 'draft',
|
||||||
title: t('draftDesign', { design: props.design.config.data.name }),
|
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',
|
name: 'test',
|
||||||
title: t('testDesign', { design: props.design.config.data.name }),
|
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',
|
name: 'printingLayout',
|
||||||
title: t('layoutThing', { thing: props.design.config.data.name })
|
title: t('layoutThing', { thing: props.design.config.data.name }) + ': ' + t('forPrinting'),
|
||||||
+ ': ' + t('forPrinting'),
|
onClick: () => props.updateGist(['_state', 'view'], 'printingLayout', true),
|
||||||
onClick: () => props.updateGist(['_state', 'view'], 'printingLayout', true)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'cuttingLayout',
|
name: 'cuttingLayout',
|
||||||
title: t('layoutThing', { thing: props.design.config.data.name })
|
title: t('layoutThing', { thing: props.design.config.data.name }) + ': ' + t('forCutting'),
|
||||||
+ ': ' + t('forCutting'),
|
onClick: () => props.updateGist(['_state', 'view'], 'cuttingLayout', true),
|
||||||
onClick: () => props.updateGist(['_state', 'view'], 'cuttingLayout', true)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'export',
|
name: 'export',
|
||||||
title: t('exportThing', { thing: props.design.config.data.name }),
|
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',
|
name: 'logs',
|
||||||
title: t('events'),
|
title: t('logs'),
|
||||||
onClick: () => props.updateGist(['_state', 'view'], 'events', true)
|
onClick: () => props.updateGist(['_state', 'view'], 'logs', true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'yaml',
|
name: 'yaml',
|
||||||
title: t('YAML'),
|
title: t('YAML'),
|
||||||
onClick: () => props.updateGist(['_state', 'view'], 'yaml', true)
|
onClick: () => props.updateGist(['_state', 'view'], 'yaml', true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'json',
|
name: 'json',
|
||||||
title: t('JSON'),
|
title: t('JSON'),
|
||||||
onClick: () => props.updateGist(['_state', 'view'], 'json', true)
|
onClick: () => props.updateGist(['_state', 'view'], 'json', true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'edit',
|
name: 'edit',
|
||||||
title: t('editThing', { thing: 'YAML' }),
|
title: t('editThing', { thing: 'YAML' }),
|
||||||
onClick: () => props.updateGist(['_state', 'view'], 'edit', true)
|
onClick: () => props.updateGist(['_state', 'view'], 'edit', true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'clear',
|
name: 'clear',
|
||||||
title: t('clearThing', { thing: 'YAML' }),
|
title: t('clearThing', { thing: 'YAML' }),
|
||||||
onClick: () => props.setGist(defaultGist(props.design, props.gist.locale))
|
onClick: () => props.setGist(defaultGist(props.design, props.gist.locale)),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<details className='py-1' open>
|
<details className="py-1" open>
|
||||||
<summary className={`
|
<summary
|
||||||
|
className={`
|
||||||
flex flex-row uppercase gap-4 font-bold text-lg
|
flex flex-row uppercase gap-4 font-bold text-lg
|
||||||
hover:cursor-row-resize
|
hover:cursor-row-resize
|
||||||
p-2
|
p-2
|
||||||
text-base-content
|
text-base-content
|
||||||
sm:text-base-content
|
sm:text-base-content
|
||||||
items-center
|
items-center
|
||||||
`}>
|
`}
|
||||||
<span className="text-secondary-focus mr-4"><MenuIcon /></span>
|
>
|
||||||
<span className={`grow ${linkClasses} hover:cursor-resize`}>
|
<span className="text-secondary-focus mr-4">
|
||||||
{t('view')}
|
<MenuIcon />
|
||||||
</span>
|
</span>
|
||||||
|
<span className={`grow ${linkClasses} hover:cursor-resize`}>{t('view')}</span>
|
||||||
<Chevron />
|
<Chevron />
|
||||||
</summary>
|
</summary>
|
||||||
<ul className="pl-5 list-inside">
|
<ul className="pl-5 list-inside">
|
||||||
{entries.map(entry => (
|
{entries.map((entry) => (
|
||||||
<li key={entry.title} className="flex flex-row">
|
<li key={entry.title} className="flex flex-row">
|
||||||
<button title={entry.title} className={`
|
<button
|
||||||
|
title={entry.title}
|
||||||
|
className={`
|
||||||
grow pl-2 border-l-2
|
grow pl-2 border-l-2
|
||||||
${linkClasses}
|
${linkClasses}
|
||||||
hover:cursor-pointer
|
hover:cursor-pointer
|
||||||
|
@ -92,22 +94,28 @@ const View = props => {
|
||||||
sm:hover:border-secondary-focus
|
sm:hover:border-secondary-focus
|
||||||
text-left
|
text-left
|
||||||
capitalize
|
capitalize
|
||||||
${entry.name === props.gist?._state?.view
|
${
|
||||||
? 'text-secondary border-secondary sm:text-secondary-focus sm:border-secondary-focus'
|
entry.name === props.gist?._state?.view
|
||||||
: 'text-base-content sm:text-base-content'
|
? 'text-secondary border-secondary sm:text-secondary-focus sm:border-secondary-focus'
|
||||||
|
: 'text-base-content sm:text-base-content'
|
||||||
}
|
}
|
||||||
`} onClick={entry.onClick}>
|
`}
|
||||||
<span className={`
|
onClick={entry.onClick}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={`
|
||||||
text-3xl mr-2 inline-block p-0 leading-3
|
text-3xl mr-2 inline-block p-0 leading-3
|
||||||
${entry.name === props.gist?._state?.view
|
${
|
||||||
? 'text-secondary sm:text-secondary-focus translate-y-1 font-bold'
|
entry.name === props.gist?._state?.view
|
||||||
: 'translate-y-3'
|
? 'text-secondary sm:text-secondary-focus translate-y-1 font-bold'
|
||||||
|
: 'translate-y-3'
|
||||||
}
|
}
|
||||||
`}>
|
`}
|
||||||
|
>
|
||||||
{entry.name === props.gist?._state?.view ? <>•</> : <>°</>}
|
{entry.name === props.gist?._state?.view ? <>•</> : <>°</>}
|
||||||
</span>
|
</span>
|
||||||
<span className={entry.name === props.gist?._state?.view ? 'font-bold' : ''}>
|
<span className={entry.name === props.gist?._state?.view ? 'font-bold' : ''}>
|
||||||
{ entry.title }
|
{entry.title}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,18 +1,24 @@
|
||||||
|
import SvgWrapper from './draft/svg-wrapper'
|
||||||
|
import Error from './draft/error.js'
|
||||||
import { svgattrPlugin } from '@freesewing/plugin-svgattr'
|
import { svgattrPlugin } from '@freesewing/plugin-svgattr'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
const LabSample = ({ gist, draft }) => {
|
const LabSample = ({ gist, draft, updateGist, unsetGist, showInfo, app, feedback }) => {
|
||||||
|
|
||||||
const { t } = useTranslation(['workbench'])
|
const { t } = useTranslation(['workbench'])
|
||||||
let svg
|
let svg
|
||||||
let title = ''
|
let title = ''
|
||||||
|
let patternProps
|
||||||
|
const errors = []
|
||||||
if (gist.sample) {
|
if (gist.sample) {
|
||||||
try {
|
try {
|
||||||
draft.use(svgattrPlugin, {
|
draft.use(svgattrPlugin, {
|
||||||
class: 'freesewing pattern max-h-screen'
|
class: 'freesewing pattern max-h-screen'
|
||||||
})
|
})
|
||||||
draft.sample()
|
draft = draft.sample()
|
||||||
svg = draft.render()
|
// Render as React
|
||||||
|
patternProps = draft.getRenderProps()
|
||||||
|
for (const logs of patternProps.logs) errors.push(...logs.error)
|
||||||
}
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
|
@ -27,6 +33,12 @@ const LabSample = ({ gist, draft }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h2>{title}</h2>
|
<h2>{title}</h2>
|
||||||
|
{!patternProps || errors.length > 0 ? (
|
||||||
|
<Error {...{ draft, patternProps, updateGist }} />
|
||||||
|
) : null}
|
||||||
|
<SvgWrapper
|
||||||
|
{...{ draft, patternProps, gist, updateGist, unsetGist, showInfo, app, feedback }}
|
||||||
|
/>
|
||||||
<div className="freesewing pattern" dangerouslySetInnerHTML={{__html: svg}} />
|
<div className="freesewing pattern" dangerouslySetInnerHTML={{__html: svg}} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useEffect, useState, useMemo,} from 'react'
|
import { useEffect, useState, useMemo } from 'react'
|
||||||
import {useGist} from 'shared/hooks/useGist'
|
import { useGist } from 'shared/hooks/useGist'
|
||||||
import Layout from 'shared/components/layouts/default'
|
import Layout from 'shared/components/layouts/default'
|
||||||
import Menu from 'shared/components/workbench/menu/index.js'
|
import Menu from 'shared/components/workbench/menu/index.js'
|
||||||
import DraftError from 'shared/components/workbench/draft/error.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 ExportDraft from 'shared/components/workbench/exporting/index.js'
|
||||||
import GistAsJson from 'shared/components/workbench/gist-as-json.js'
|
import GistAsJson from 'shared/components/workbench/gist-as-json.js'
|
||||||
import GistAsYaml from 'shared/components/workbench/yaml.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 CutLayout from 'shared/components/workbench/layout/cut'
|
||||||
import PrintingLayout from 'shared/components/workbench/layout/print'
|
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 = {
|
const views = {
|
||||||
measurements: Measurements,
|
measurements: Measurements,
|
||||||
|
@ -27,7 +27,7 @@ const views = {
|
||||||
printingLayout: PrintingLayout,
|
printingLayout: PrintingLayout,
|
||||||
cuttingLayout: CutLayout,
|
cuttingLayout: CutLayout,
|
||||||
export: ExportDraft,
|
export: ExportDraft,
|
||||||
events: DraftEvents,
|
logs: DraftLogs,
|
||||||
yaml: GistAsYaml,
|
yaml: GistAsYaml,
|
||||||
json: GistAsJson,
|
json: GistAsJson,
|
||||||
welcome: () => <p>TODO</p>,
|
welcome: () => <p>TODO</p>,
|
||||||
|
@ -54,15 +54,16 @@ const doPreload = async (preload, from, design, gist, setGist, setPreloaded) =>
|
||||||
* keeping the gist state, which will trickle down
|
* keeping the gist state, which will trickle down
|
||||||
* to all workbench subcomponents
|
* 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
|
// 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 [messages, setMessages] = useState([])
|
||||||
const [popup, setPopup] = useState(false)
|
const [popup, setPopup] = useState(false)
|
||||||
const [preloaded, setPreloaded] = useState(false)
|
const [preloaded, setPreloaded] = useState(false)
|
||||||
|
|
||||||
|
|
||||||
// We'll use this in more than one location
|
// We'll use this in more than one location
|
||||||
const hasRequiredMeasurements = hasRequiredMeasurementsMethod(design, gist)
|
const hasRequiredMeasurements = hasRequiredMeasurementsMethod(design, gist)
|
||||||
|
|
||||||
|
@ -70,34 +71,31 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
|
||||||
// force view to measurements
|
// force view to measurements
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!gistReady) return
|
if (!gistReady) return
|
||||||
if (gist._state?.view !== 'measurements'
|
if (gist._state?.view !== 'measurements' && !hasRequiredMeasurements)
|
||||||
&& !hasRequiredMeasurements
|
updateGist(['_state', 'view'], 'measurements')
|
||||||
) updateGist(['_state', 'view'], 'measurements')
|
|
||||||
}, [gistReady, gist._state?.view, hasRequiredMeasurements])
|
}, [gistReady, gist._state?.view, hasRequiredMeasurements])
|
||||||
|
|
||||||
// If we need to preload the gist, do so
|
// If we need to preload the gist, do so
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (preload && preload !== preloaded && from && preloaders[from]) {
|
||||||
preload &&
|
doPreload(preload, from, design, gist, setGist, setPreloaded)
|
||||||
preload !== preloaded &&
|
|
||||||
from &&
|
|
||||||
preloaders[from]
|
|
||||||
) {
|
|
||||||
doPreload(preload, from, design, gist, setGist, setPreloaded)
|
|
||||||
}
|
}
|
||||||
}, [preload, preloaded, from, design])
|
}, [preload, preloaded, from, design])
|
||||||
|
|
||||||
|
|
||||||
// Helper methods to manage the gist state
|
// Helper methods to manage the gist state
|
||||||
const updateWBGist = useMemo(() => (path, value, closeNav=false, addToHistory=true) => {
|
const updateWBGist = useMemo(
|
||||||
updateGist(path, value, addToHistory)
|
() =>
|
||||||
// Force close of menu on mobile if it is open
|
(path, value, closeNav = false, addToHistory = true) => {
|
||||||
if (closeNav && app.primaryMenu) app.setPrimaryMenu(false)
|
updateGist(path, value, addToHistory)
|
||||||
}, [app])
|
// Force close of menu on mobile if it is open
|
||||||
|
if (closeNav && app.primaryMenu) app.setPrimaryMenu(false)
|
||||||
|
},
|
||||||
|
[app]
|
||||||
|
)
|
||||||
|
|
||||||
// Helper methods to handle messages
|
// Helper methods to handle messages
|
||||||
const feedback = {
|
const feedback = {
|
||||||
add: msg => {
|
add: (msg) => {
|
||||||
const newMsgs = [...messages]
|
const newMsgs = [...messages]
|
||||||
if (Array.isArray(msg)) newMsgs.push(...msg)
|
if (Array.isArray(msg)) newMsgs.push(...msg)
|
||||||
else 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
|
// 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
|
// Generate the draft here so we can pass it down to both the view and the options menu
|
||||||
let draft = false
|
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
|
gist.embed = true
|
||||||
// get the appropriate layout for the view
|
// get the appropriate layout for the view
|
||||||
const layout = gist.layouts?.[gist._state.view] || gist.layout || true
|
const layout = gist.layouts?.[gist._state.view] || gist.layout || true
|
||||||
// hand it separately to the design
|
// hand it separately to the design
|
||||||
draft = new design({...gist, layout})
|
draft = new design({ ...gist, layout })
|
||||||
draft.init()
|
draft.init()
|
||||||
|
|
||||||
// add theme to svg renderer
|
// 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
|
// draft it for draft and event views. Other views may add plugins, etc and we don't want to draft twice
|
||||||
try {
|
try {
|
||||||
if (['draft', 'events'].indexOf(gist._state.view) > -1) draft.draft()
|
if (['draft', 'logs'].indexOf(gist._state.view) > -1) draft.draft()
|
||||||
}
|
} catch (error) {
|
||||||
catch(error) {
|
|
||||||
console.log('Failed to draft design', error)
|
console.log('Failed to draft design', error)
|
||||||
return <DraftError error={error} app={app} draft={draft} at={'draft'} />
|
return <DraftError error={error} app={app} draft={draft} at={'draft'} />
|
||||||
}
|
}
|
||||||
|
@ -152,33 +151,30 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
|
||||||
app: app,
|
app: app,
|
||||||
noSearch: true,
|
noSearch: true,
|
||||||
workbench: true,
|
workbench: true,
|
||||||
AltMenu: <Menu {...componentProps }/>,
|
AltMenu: <Menu {...componentProps} />,
|
||||||
showInfo: setPopup,
|
showInfo: setPopup,
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorProps = {
|
const errorProps = {
|
||||||
undoGist,
|
undoGist,
|
||||||
resetGist,
|
resetGist,
|
||||||
gist
|
gist,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Layout to use
|
// Layout to use
|
||||||
const LayoutComponent = layout
|
const LayoutComponent = layout ? layout : Layout
|
||||||
? layout
|
|
||||||
: Layout
|
|
||||||
|
|
||||||
const Component = views[gist._state?.view]
|
const Component = views[gist._state?.view] ? views[gist._state.view] : views.welcome
|
||||||
? views[gist._state.view]
|
|
||||||
: views.welcome
|
|
||||||
|
|
||||||
return <LayoutComponent {...layoutProps}>
|
return (
|
||||||
{messages}
|
<LayoutComponent {...layoutProps}>
|
||||||
<ErrorBoundary {...errorProps}>
|
{messages}
|
||||||
<Component {...componentProps} />
|
<ErrorBoundary {...errorProps}>
|
||||||
{popup && <Modal cancel={() => setPopup(false)}>{popup}</Modal>}
|
<Component {...componentProps} />
|
||||||
</ErrorBoundary>
|
{popup && <Modal cancel={() => setPopup(false)}>{popup}</Modal>}
|
||||||
</LayoutComponent>
|
</ErrorBoundary>
|
||||||
|
</LayoutComponent>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WorkbenchWrapper
|
export default WorkbenchWrapper
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Can't seem to make this work as ESM
|
// Can't seem to make this work as ESM
|
||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: ['tailwindcss/nesting', 'tailwindcss', 'autoprefixer'],
|
plugins: ['tailwindcss/nesting', 'tailwindcss', 'autoprefixer', 'postcss-for'],
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"lodash.unset": "^4.5.2",
|
"lodash.unset": "^4.5.2",
|
||||||
"mdast-util-toc": "^6.1.0",
|
"mdast-util-toc": "^6.1.0",
|
||||||
"pdfkit": "^0.13.0",
|
"pdfkit": "^0.13.0",
|
||||||
|
"postcss-for": "^2.1.1",
|
||||||
"react-markdown": "^8.0.0",
|
"react-markdown": "^8.0.0",
|
||||||
"react-sizeme": "^3.0.2",
|
"react-sizeme": "^3.0.2",
|
||||||
"react-timeago": "^7.1.0",
|
"react-timeago": "^7.1.0",
|
||||||
|
@ -44,6 +45,8 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "^10.4.0",
|
"autoprefixer": "^10.4.0",
|
||||||
|
"eslint": "^8.23.1",
|
||||||
|
"eslint-plugin-react": "^7.31.8",
|
||||||
"lodash.set": "^4.3.2",
|
"lodash.set": "^4.3.2",
|
||||||
"postcss": "^8.4.4",
|
"postcss": "^8.4.4",
|
||||||
"tailwindcss": "^3.0.1",
|
"tailwindcss": "^3.0.1",
|
||||||
|
|
|
@ -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
|
/* Styling the shadow DOM is hard to do
|
||||||
* This is for styling FreeSewing snippets
|
* This is for styling FreeSewing snippets
|
||||||
* TODO: Update snippets to use inline styles with CSS vars
|
* TODO: Update snippets to use inline styles with CSS vars
|
||||||
|
@ -257,3 +271,6 @@ figure.develop.example div.develop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -257,4 +257,17 @@ module.exports = {
|
||||||
'--pattern-stroke-6xl': "16px",
|
'--pattern-stroke-6xl': "16px",
|
||||||
// Pattern 7xl stroke width
|
// Pattern 7xl stroke width
|
||||||
'--pattern-stroke-7xl': "20px",
|
'--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"],
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
62
yarn.lock
62
yarn.lock
|
@ -7934,6 +7934,26 @@ eslint-plugin-react@^7.28.0, eslint-plugin-react@^7.29.4:
|
||||||
semver "^6.3.0"
|
semver "^6.3.0"
|
||||||
string.prototype.matchall "^4.0.7"
|
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:
|
eslint-plugin-yaml@^0.5.0:
|
||||||
version "0.5.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-yaml/-/eslint-plugin-yaml-0.5.0.tgz#8c79d9d6389b67cbcf58ef6f970c4c086665a63a"
|
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"
|
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
|
||||||
integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
|
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:
|
has-flag@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
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"
|
leven "^3.1.0"
|
||||||
pretty-format "^27.5.1"
|
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:
|
js-sdsl@^4.1.4:
|
||||||
version "4.1.4"
|
version "4.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.4.tgz#78793c90f80e8430b7d8dc94515b6c77d98a26a6"
|
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"
|
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
|
||||||
integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==
|
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:
|
postcss-import@^14.1.0:
|
||||||
version "14.1.0"
|
version "14.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0"
|
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"
|
cssesc "^3.0.0"
|
||||||
util-deprecate "^1.0.2"
|
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:
|
postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
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"
|
picocolors "^1.0.0"
|
||||||
source-map-js "^1.0.2"
|
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:
|
postcss@^8.4.12, postcss@^8.4.14, postcss@^8.4.4, postcss@^8.4.5:
|
||||||
version "8.4.16"
|
version "8.4.16"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.16.tgz#33a1d675fac39941f5f445db0de4db2b6e01d43c"
|
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"
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
||||||
integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
|
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:
|
supports-color@^5.3.0, supports-color@^5.5.0:
|
||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue