160 lines
5.1 KiB
JavaScript
160 lines
5.1 KiB
JavaScript
import React, { useState } from 'react'
|
|
import Svg from './Svg'
|
|
import Defs from './Defs'
|
|
import Part from './Part'
|
|
import Develop from './Develop'
|
|
|
|
const PatternSvg = props => (
|
|
<Svg
|
|
embed={props.settings.embed}
|
|
width={props.width}
|
|
height={props.height}
|
|
language={props.settings.locale}
|
|
id={props.settings.idPrefix + 'svg'}
|
|
develop={props.develop || false}
|
|
style={props.style || {}}
|
|
viewBox={props.viewBox}
|
|
className={props.className || 'freesewing pattern'}
|
|
>
|
|
<Defs {...props} />
|
|
<style>{`:root { --pattern-scale: ${props.settings.scale || 1}}`}</style>
|
|
<g>
|
|
{Object.keys(props.parts).map((name) => (
|
|
<Part
|
|
part={props.parts[name]}
|
|
language={props.settings.locale}
|
|
paperless={props.settings.paperless}
|
|
units={props.settings.units}
|
|
key={name}
|
|
name={name}
|
|
focus={props.focus || false}
|
|
develop={props.develop || false}
|
|
raiseEvent={props.raiseEvent}
|
|
/>
|
|
))}
|
|
</g>
|
|
</Svg>
|
|
)
|
|
|
|
const Pattern = props => {
|
|
|
|
const {
|
|
pattern = 'examples',
|
|
patterns = {},
|
|
children=null,
|
|
options = {},
|
|
measurements = { head: 390},
|
|
part = '',
|
|
sample,
|
|
svgOnly=false,
|
|
allowDevelop=true
|
|
} = props
|
|
|
|
const [develop, setDevelop] = useState(false)
|
|
const [focus, setFocus] = useState(null)
|
|
|
|
// Don't continue if there's no pattern
|
|
if (!pattern || !patterns[pattern]) return <pre>{JSON.stringify(props,null,4)}</pre> //null
|
|
|
|
/* Helper method to handle user clicks */
|
|
const raiseEvent = (type, data) => {
|
|
if (type === 'clearFocusAll') return setFocus(null)
|
|
let f = {}
|
|
if (focus !== null) f = { ...focus }
|
|
if (typeof f[data.part] === 'undefined') f[data.part] = { paths: [], points: [], coords: [] }
|
|
if (type === 'point') f[data.part].points.push(data.name)
|
|
else if (type === 'path') f[data.part].paths.push(data.name)
|
|
else if (type === 'coords') f[data.part].coords.push(data.coords)
|
|
else if (type === 'clearFocus') {
|
|
let i = focus[data.part][data.type].indexOf(data.name)
|
|
f[data.part][data.type].splice(i, 1)
|
|
}
|
|
|
|
setFocus(f)
|
|
}
|
|
|
|
/* Handle various elements with focus */
|
|
let focusCount = 0
|
|
if (focus !== null) {
|
|
for (let p of Object.keys(focus)) {
|
|
for (let i in focus[p].points) focusCount++
|
|
for (let i in focus[p].paths) focusCount++
|
|
for (let i in focus[p].coords) focusCount++
|
|
}
|
|
}
|
|
|
|
/* Set up settings object */
|
|
const settings = {
|
|
options: { ...options },
|
|
measurements: { ...measurements },
|
|
...props.settings
|
|
}
|
|
// Support for options_ prefix
|
|
for (const [key, val] of Object.entries(props)) {
|
|
if (key.slice(0,8) === 'options_') settings.options[key.slice(8)] = (val === 'true')
|
|
? true
|
|
: (val === 'false')
|
|
? false
|
|
: val
|
|
if (key.slice(0,9) === 'settings_') settings[key.slice(9)] = (val === 'true')
|
|
? true
|
|
: (val === 'false')
|
|
? false
|
|
: val
|
|
}
|
|
|
|
if (part !== '') settings.only = [part]
|
|
const patternInstance = new patterns[pattern](settings)
|
|
if (sample) patternInstance.sample()
|
|
else patternInstance.draft()
|
|
const patternProps = patternInstance.getRenderProps()
|
|
return svgOnly
|
|
? <PatternSvg {...patternProps} develop={develop} focus={focus} raiseEvent={raiseEvent} />
|
|
: (
|
|
<figure className={`my-4 ${develop ? 'develop example' : 'example'}`}>
|
|
<div className="example text-base-content">
|
|
{allowDevelop && (
|
|
<div className="actions">
|
|
<div className="form-control">
|
|
<label className="cursor-pointer label justify-start gap-4 font-lg lg:font-xl font-bold">
|
|
<input
|
|
type="checkbox"
|
|
checked={develop}
|
|
className="toggle toggle-secondary"
|
|
onChange={() => setDevelop(!develop)}
|
|
/>
|
|
<span className="label-text text-secondary">{develop ? 'Disable' : 'Enable'} Developer View</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
)}
|
|
{develop && (
|
|
<div className="develop p-4 py-2 border rounded mb-2">
|
|
<div className="flex flex-row justify-between">
|
|
<h5>Developer info</h5>
|
|
<button
|
|
disabled={!develop}
|
|
className="px-2 py-1 rounded text-secondary border-secondary border text-sm"
|
|
onClick={() => raiseEvent('clearFocusAll', null)}
|
|
>
|
|
<strong>Clear</strong>
|
|
</button>
|
|
</div>
|
|
<Develop
|
|
focus={focus}
|
|
develop={develop}
|
|
raiseEvent={raiseEvent}
|
|
parts={patternProps.parts}
|
|
/>
|
|
</div>
|
|
)}
|
|
<div className="shadow rounded border border-base-200">
|
|
<PatternSvg {...patternProps} develop={develop} focus={focus} raiseEvent={raiseEvent} />
|
|
</div>
|
|
</div>
|
|
<figcaption className="text-base-content text-center text-base lg:text-lg italic">{children}</figcaption>
|
|
</figure>
|
|
)
|
|
}
|
|
|
|
export default Pattern
|