refactor(components): Removed prop-types dependency
This commit is contained in:
parent
8cf8424437
commit
cda9b03713
44 changed files with 559 additions and 1026 deletions
|
@ -1,49 +1,36 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Radio from '@material-ui/core/Radio'
|
||||
import RadioGroup from '@material-ui/core/RadioGroup'
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel'
|
||||
|
||||
const Bool = props => {
|
||||
const [value, setValue] = useState(props.dflt)
|
||||
const Bool = ({ dflt = false, labels = ['false', 'true'], value, name, updateValue }) => {
|
||||
const [val, setVal] = useState(dflt)
|
||||
useEffect(() => {
|
||||
if (props.value !== value) setValue(props.value)
|
||||
}, [props.value])
|
||||
if (value !== val) setVal(value)
|
||||
}, [value])
|
||||
const toggle = () => {
|
||||
props.updateValue(props.name, !value)
|
||||
setValue(!value)
|
||||
updateValue(name, !val)
|
||||
setVal(!val)
|
||||
}
|
||||
|
||||
return (
|
||||
<RadioGroup onChange={toggle} value={JSON.stringify(value)}>
|
||||
<RadioGroup onChange={toggle} value={JSON.stringify(val)}>
|
||||
<FormControlLabel
|
||||
control={<Radio color="primary" />}
|
||||
value="false"
|
||||
checked={value === 'true' || value === true || value === 1 ? false : true}
|
||||
label={props.labels[0]}
|
||||
checked={val === 'true' || val === true || val === 1 ? false : true}
|
||||
label={labels[0]}
|
||||
className="po-list-item"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={<Radio color="primary" />}
|
||||
value="true"
|
||||
checked={value === 'true' || value === true || value === 1 ? true : false}
|
||||
label={props.labels[1]}
|
||||
checked={val === 'true' || val === true || val === 1 ? true : false}
|
||||
label={labels[1]}
|
||||
className="po-list-item"
|
||||
/>
|
||||
</RadioGroup>
|
||||
)
|
||||
}
|
||||
|
||||
Bool.propTypes = {
|
||||
dflt: PropTypes.bool,
|
||||
labels: PropTypes.array,
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
Bool.defaultProps = {
|
||||
dflt: false,
|
||||
labels: ['false', 'true']
|
||||
}
|
||||
|
||||
export default Bool
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import FormGroup from "@material-ui/core/FormGroup";
|
||||
import FormControlLabel from "@material-ui/core/FormControlLabel";
|
||||
import Checkbox from "@material-ui/core/Checkbox";
|
||||
import React, { useState } from 'react'
|
||||
import FormGroup from '@material-ui/core/FormGroup'
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel'
|
||||
import Checkbox from '@material-ui/core/Checkbox'
|
||||
|
||||
const FormFieldChecks = props => {
|
||||
const [value, setValue] = useState(props.dflt ? props.dflt : []);
|
||||
const FormFieldChecks = (props) => {
|
||||
const [value, setValue] = useState(props.dflt ? props.dflt : [])
|
||||
|
||||
const toggle = part => {
|
||||
let parts = value.slice(0);
|
||||
let index = parts.indexOf(part);
|
||||
if (index === -1) parts.push(part);
|
||||
else parts.splice(index, 1);
|
||||
setValue(parts);
|
||||
props.updateValue(props.name, parts);
|
||||
};
|
||||
const toggle = (part) => {
|
||||
let parts = value.slice(0)
|
||||
let index = parts.indexOf(part)
|
||||
if (index === -1) parts.push(part)
|
||||
else parts.splice(index, 1)
|
||||
setValue(parts)
|
||||
props.updateValue(props.name, parts)
|
||||
}
|
||||
|
||||
return (
|
||||
<FormGroup>
|
||||
{Object.keys(props.checks).map(i => {
|
||||
{Object.keys(props.checks).map((i) => {
|
||||
return (
|
||||
<FormControlLabel
|
||||
control={
|
||||
|
@ -32,17 +31,10 @@ const FormFieldChecks = props => {
|
|||
key={i}
|
||||
className="po-list-item"
|
||||
/>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
FormFieldChecks.propTypes = {
|
||||
dflt: PropTypes.array,
|
||||
checks: PropTypes.object,
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default FormFieldChecks;
|
||||
export default FormFieldChecks
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Radio from '@material-ui/core/Radio'
|
||||
import RadioGroup from '@material-ui/core/RadioGroup'
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel'
|
||||
|
||||
const FormFieldList = props => {
|
||||
const FormFieldList = (props) => {
|
||||
const [value, setValue] = useState(props.dflt)
|
||||
useEffect(() => {
|
||||
if (props.value !== value) setValue(props.value)
|
||||
}, [props.value])
|
||||
const update = evt => {
|
||||
const update = (evt) => {
|
||||
props.updateValue(props.name, evt.target.value)
|
||||
setValue(evt.target.value)
|
||||
}
|
||||
|
@ -30,15 +29,4 @@ const FormFieldList = props => {
|
|||
)
|
||||
}
|
||||
|
||||
FormFieldList.propTypes = {
|
||||
dflt: PropTypes.oneOfType([
|
||||
PropTypes.number.isRequired,
|
||||
PropTypes.string.isRequired,
|
||||
PropTypes.bool.isRequired
|
||||
]),
|
||||
list: PropTypes.object,
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default FormFieldList
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import InvalidIcon from '@material-ui/icons/Warning'
|
||||
|
@ -47,13 +46,4 @@ const FormFieldMeasurement = (props) => {
|
|||
)
|
||||
}
|
||||
|
||||
FormFieldMeasurement.propTypes = {
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
label: PropTypes.string.isRequired,
|
||||
units: PropTypes.oneOf(['metric', 'imperial'])
|
||||
}
|
||||
|
||||
FormFieldMeasurement.defaultProps = {}
|
||||
|
||||
export default injectIntl(FormFieldMeasurement)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Slider from '@material-ui/core/Slider'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
|
@ -11,48 +10,32 @@ const PaddedSlider = withStyles({
|
|||
thumb: { width: '16px', height: '16px' }
|
||||
})(Slider)
|
||||
|
||||
const FormFieldSlider = props => {
|
||||
const [value, setValue] = useState(props.value)
|
||||
const FormFieldSlider = ({ min = 0, max = 100, step = 0.1, label = false, updateValue, name }) => {
|
||||
const [val, setVal] = useState(value)
|
||||
useEffect(() => {
|
||||
if (props.value !== value) setValue(props.value)
|
||||
}, [props.value])
|
||||
if (value !== val) setVal(value)
|
||||
}, [value])
|
||||
|
||||
const update = (evt, newValue) => {
|
||||
props.updateValue(props.name, newValue, evt)
|
||||
setValue(newValue)
|
||||
updateValue(name, newValue, evt)
|
||||
setVal(newValue)
|
||||
}
|
||||
|
||||
return (
|
||||
<PaddedSlider
|
||||
value={value}
|
||||
min={props.min}
|
||||
max={props.max}
|
||||
step={props.step}
|
||||
value={val}
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
onChange={update}
|
||||
onChangeCommitted={update}
|
||||
classes={{
|
||||
track: 'slider-track',
|
||||
thumb: 'slider-thumb'
|
||||
}}
|
||||
aria-labelledby={props.label}
|
||||
aria-labelledby={label}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
FormFieldSlider.propTypes = {
|
||||
min: PropTypes.number,
|
||||
max: PropTypes.number,
|
||||
step: PropTypes.number,
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.oneOf([false])])
|
||||
}
|
||||
|
||||
FormFieldSlider.defaultProps = {
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 0.1,
|
||||
label: false
|
||||
}
|
||||
|
||||
export default FormFieldSlider
|
||||
|
|
|
@ -1,26 +1,16 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Icon from '../Icon'
|
||||
|
||||
const Blockquote = props => {
|
||||
const Blockquote = (props) => {
|
||||
const attr = Object.assign({}, props)
|
||||
delete attr.type
|
||||
delete attr.children
|
||||
return (
|
||||
<blockquote className={props.type} {...attr}>
|
||||
{props.children}
|
||||
{props.type === 'fixme' ? null : <Icon icon={props.type} className={'icon ' + props.type} />}
|
||||
<blockquote className={props.type || 'note'} {...attr}>
|
||||
{props.children || null}
|
||||
{props.type !== 'fixme' && <Icon icon={props.type} className={'icon ' + props.type} />}
|
||||
</blockquote>
|
||||
)
|
||||
}
|
||||
|
||||
Blockquote.propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
||||
Blockquote.defaultProps = {
|
||||
type: 'note',
|
||||
children: null
|
||||
}
|
||||
export default Blockquote
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const Circle = (props) => (
|
||||
<circle
|
||||
|
@ -10,8 +9,4 @@ const Circle = (props) => (
|
|||
/>
|
||||
)
|
||||
|
||||
Circle.propTypes = {
|
||||
point: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default Circle
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Path from '../Path'
|
||||
import Point from '../Point'
|
||||
import Snippet from '../Snippet'
|
||||
|
@ -136,12 +135,4 @@ const Part = (props) => {
|
|||
)
|
||||
}
|
||||
|
||||
Part.propTypes = {
|
||||
part: PropTypes.object.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
language: PropTypes.string.isRequired,
|
||||
paperless: PropTypes.bool.isRequired,
|
||||
design: PropTypes.bool.isRequired
|
||||
}
|
||||
|
||||
export default Part
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import TextOnPath from '../TextOnPath'
|
||||
import DesignPath from '../DesignPath'
|
||||
import { getProps } from '../utils'
|
||||
|
@ -18,10 +17,4 @@ const Path = (props) => {
|
|||
return output
|
||||
}
|
||||
|
||||
Path.propTypes = {
|
||||
path: PropTypes.object.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
language: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default Path
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import DesignPoint from '../DesignPoint'
|
||||
import Text from '../Text'
|
||||
import Circle from '../Circle'
|
||||
|
@ -12,14 +11,8 @@ const Point = (props) => {
|
|||
output.push(<Text {...props} key={'point-' + props.name} />)
|
||||
if (props.point.attributes.get('data-circle'))
|
||||
output.push(<Circle point={props.point} key={'circle-' + props.name} />)
|
||||
if (output.length < 1) return null
|
||||
else return output
|
||||
}
|
||||
|
||||
Point.propTypes = {
|
||||
point: PropTypes.object.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
language: PropTypes.string.isRequired
|
||||
return output.length < 1 ? null : output
|
||||
}
|
||||
|
||||
export default Point
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { getProps } from '../utils'
|
||||
|
||||
const Snippet = (props) => {
|
||||
|
@ -25,8 +24,4 @@ const Snippet = (props) => {
|
|||
return <use {...snippetProps} {...getProps(props.snippet)} />
|
||||
}
|
||||
|
||||
Snippet.propTypes = {
|
||||
snippet: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default Snippet
|
||||
|
|
|
@ -1,40 +1,33 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const Svg = (props) => {
|
||||
const Svg = ({
|
||||
embed = true,
|
||||
design = false,
|
||||
language = 'en',
|
||||
className = 'freesewing draft',
|
||||
style = {},
|
||||
viewBox = false,
|
||||
width,
|
||||
height,
|
||||
children
|
||||
}) => {
|
||||
let attributes = {
|
||||
xmlns: 'http://www.w3.org/2000/svg',
|
||||
'xmlns:svg': 'http://www.w3.org/2000/svg',
|
||||
xmlnsXlink: 'http://www.w3.org/1999/xlink',
|
||||
xmlLang: props.language,
|
||||
viewBox: props.viewBox || `0 0 ${props.width} ${props.height}`,
|
||||
className: props.className,
|
||||
style: props.style
|
||||
xmlLang: language,
|
||||
viewBox: viewBox || `0 0 ${width} ${height}`,
|
||||
className,
|
||||
style
|
||||
}
|
||||
|
||||
if (!props.embed) {
|
||||
attributes.width = props.width + 'mm'
|
||||
attributes.height = props.height + 'mm'
|
||||
if (!embed) {
|
||||
attributes.width = width + 'mm'
|
||||
attributes.height = height + 'mm'
|
||||
}
|
||||
if (props.design) attributes.className += ' design'
|
||||
if (design) attributes.className += ' design'
|
||||
|
||||
return <svg {...attributes}>{props.children}</svg>
|
||||
}
|
||||
|
||||
Svg.propTypes = {
|
||||
embed: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
language: PropTypes.string,
|
||||
design: PropTypes.bool
|
||||
}
|
||||
|
||||
Svg.defaultProps = {
|
||||
embed: true,
|
||||
design: false,
|
||||
language: 'en',
|
||||
className: 'freesewing draft',
|
||||
style: {},
|
||||
viewBox: false
|
||||
return <svg {...attributes}>{children}</svg>
|
||||
}
|
||||
|
||||
export default Svg
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { strings } from '@freesewing/i18n'
|
||||
|
||||
const Text = (props) => {
|
||||
|
@ -30,6 +29,7 @@ const Text = (props) => {
|
|||
)
|
||||
}
|
||||
} else text.push(<tspan key="tspan-1">{translated}</tspan>)
|
||||
|
||||
return (
|
||||
<text
|
||||
x={props.point.x}
|
||||
|
@ -41,9 +41,4 @@ const Text = (props) => {
|
|||
)
|
||||
}
|
||||
|
||||
Text.propTypes = {
|
||||
point: PropTypes.object.isRequired,
|
||||
language: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default Text
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { strings } from '@freesewing/i18n'
|
||||
|
||||
const TextOnPath = (props) => {
|
||||
|
@ -29,9 +28,4 @@ const TextOnPath = (props) => {
|
|||
)
|
||||
}
|
||||
|
||||
TextOnPath.propTypes = {
|
||||
path: PropTypes.object.isRequired,
|
||||
language: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default TextOnPath
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Svg from './Svg'
|
||||
import Defs from './Defs'
|
||||
import Part from './Part'
|
||||
|
@ -11,8 +10,8 @@ const Draft = (props) => (
|
|||
height={props.height}
|
||||
language={props.settings.locale}
|
||||
id={props.settings.idPrefix + 'svg'}
|
||||
design={props.design}
|
||||
style={props.style}
|
||||
design={props.design || false}
|
||||
style={props.style || {}}
|
||||
viewBox={props.viewBox}
|
||||
className={props.className || 'freesewing draft'}
|
||||
>
|
||||
|
@ -20,7 +19,7 @@ const Draft = (props) => (
|
|||
units={props.settings.units}
|
||||
parts={props.parts}
|
||||
paperless={props.settings.paperless}
|
||||
design={props.design}
|
||||
design={props.design || false}
|
||||
/>
|
||||
<g>
|
||||
{Object.keys(props.parts).map((name) => (
|
||||
|
@ -31,8 +30,8 @@ const Draft = (props) => (
|
|||
units={props.settings.units}
|
||||
key={name}
|
||||
name={name}
|
||||
focus={props.focus}
|
||||
design={props.design}
|
||||
focus={props.focus || false}
|
||||
design={props.design || false}
|
||||
raiseEvent={props.raiseEvent}
|
||||
/>
|
||||
))}
|
||||
|
@ -40,16 +39,4 @@ const Draft = (props) => (
|
|||
</Svg>
|
||||
)
|
||||
|
||||
Draft.propTypes = {
|
||||
parts: PropTypes.object.isRequired,
|
||||
settings: PropTypes.object.isRequired,
|
||||
design: PropTypes.bool
|
||||
}
|
||||
|
||||
Draft.defaultProps = {
|
||||
design: false,
|
||||
focus: false,
|
||||
style: {}
|
||||
}
|
||||
|
||||
export default Draft
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import React, { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import FormFieldList from '../../.form/FormFieldList'
|
||||
import OptionPreamble from '../OptionPreamble'
|
||||
import { injectIntl } from 'react-intl'
|
||||
import { languages } from '@freesewing/i18n'
|
||||
|
||||
const DraftSettingLanguage = props => {
|
||||
const DraftSettingLanguage = (props) => {
|
||||
const [value, setValue] = useState(props.value === null ? props.intl.locale : props.value)
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
||||
|
@ -64,12 +63,4 @@ const DraftSettingLanguage = props => {
|
|||
)
|
||||
}
|
||||
|
||||
DraftSettingLanguage.propTypes = {
|
||||
raiseEvent: PropTypes.func.isRequired,
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
title: PropTypes.node.isRequired,
|
||||
desc: PropTypes.node.isRequired
|
||||
}
|
||||
|
||||
export default injectIntl(DraftSettingLanguage)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import React, { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import FormFieldSlider from '../../.form/FormFieldSlider'
|
||||
import formatMm from '@freesewing/utils/formatMm'
|
||||
import roundMm from '@freesewing/utils/roundMm'
|
||||
import sliderStep from '@freesewing/utils/sliderStep'
|
||||
import OptionPreamble from '../OptionPreamble'
|
||||
|
||||
const DraftSettingMargin = props => {
|
||||
const DraftSettingMargin = (props) => {
|
||||
const [value, setValue] = useState(props.value === null ? props.dflt : props.value)
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
||||
|
@ -77,16 +76,4 @@ const DraftSettingMargin = props => {
|
|||
)
|
||||
}
|
||||
|
||||
DraftSettingMargin.propTypes = {
|
||||
raiseEvent: PropTypes.func.isRequired,
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
title: PropTypes.node.isRequired,
|
||||
desc: PropTypes.node.isRequired,
|
||||
units: PropTypes.oneOf(['metric', 'imperial']).isRequired
|
||||
}
|
||||
|
||||
DraftSettingMargin.defaultProps = {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
export default DraftSettingMargin
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import FormFieldList from '../../.form/FormFieldList'
|
||||
import FormFieldSlider from '../../.form/FormFieldSlider'
|
||||
import formatMm from '@freesewing/utils/formatMm'
|
||||
|
@ -8,7 +7,7 @@ import defaultSa from '@freesewing/utils/defaultSa'
|
|||
import sliderStep from '@freesewing/utils/sliderStep'
|
||||
import OptionPreamble from '../OptionPreamble'
|
||||
|
||||
const DraftSettingSa = props => {
|
||||
const DraftSettingSa = (props) => {
|
||||
const [value, setValue] = useState(
|
||||
props.value === defaultSa[props.units] ? 'dflt' : props.value === 0 ? 'none' : 'custom'
|
||||
)
|
||||
|
@ -131,16 +130,4 @@ const DraftSettingSa = props => {
|
|||
)
|
||||
}
|
||||
|
||||
DraftSettingSa.propTypes = {
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
title: PropTypes.node.isRequired,
|
||||
desc: PropTypes.node.isRequired,
|
||||
units: PropTypes.oneOf(['metric', 'imperial']).isRequired,
|
||||
labels: PropTypes.object
|
||||
}
|
||||
|
||||
DraftSettingSa.defaultProps = {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
export default DraftSettingSa
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import DraftSettingSa from '../DraftSettingSa'
|
||||
import DraftSettingMargin from '../DraftSettingMargin'
|
||||
|
@ -11,9 +10,41 @@ import DraftSettingLanguage from '../DraftSettingLanguage'
|
|||
import DraftSettingOnly from '../DraftSettingOnly'
|
||||
import RightIcon from '@material-ui/icons/KeyboardArrowRight'
|
||||
|
||||
const DraftSettings = props => {
|
||||
const DraftSettings = ({
|
||||
units = 'metric',
|
||||
raiseEvent,
|
||||
updateValue,
|
||||
noDocs,
|
||||
pattern,
|
||||
config,
|
||||
data = { settings: {} }
|
||||
}) => {
|
||||
// State
|
||||
const [expanded, setExpanded] = useState([])
|
||||
const toggleGroup = group => {
|
||||
|
||||
// Building blocks
|
||||
const noyes = [<FormattedMessage id="app.no" />, <FormattedMessage id="app.yes" />]
|
||||
const hideshow = [<FormattedMessage id="app.hide" />, <FormattedMessage id="app.show" />]
|
||||
const metricimperial = {
|
||||
metric: <FormattedMessage id="app.metricUnits" />,
|
||||
imperial: <FormattedMessage id="app.imperialUnits" />
|
||||
}
|
||||
const labels = {
|
||||
sa: {
|
||||
none: <FormattedMessage id="app.noSeamAllowance" />,
|
||||
dflt: <FormattedMessage id="app.standardSeamAllowance" />,
|
||||
custom: <FormattedMessage id="app.customSeamAllowance" />
|
||||
},
|
||||
only: {
|
||||
dflt: <FormattedMessage id="app.default" />,
|
||||
custom: <FormattedMessage id="app.custom" />
|
||||
},
|
||||
paperless: noyes,
|
||||
advanced: hideshow,
|
||||
complete: hideshow
|
||||
}
|
||||
// Methods
|
||||
const toggleGroup = (group) => {
|
||||
let shown = expanded.slice(0)
|
||||
let index = shown.indexOf(group)
|
||||
if (index === -1) shown.push(group)
|
||||
|
@ -33,42 +64,21 @@ const DraftSettings = props => {
|
|||
case 'margin':
|
||||
return 2
|
||||
case 'units':
|
||||
return props.units
|
||||
return units
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
let noyes = [<FormattedMessage id="app.no" />, <FormattedMessage id="app.yes" />]
|
||||
let hideshow = [<FormattedMessage id="app.hide" />, <FormattedMessage id="app.show" />]
|
||||
let units = {
|
||||
metric: <FormattedMessage id="app.metricUnits" />,
|
||||
imperial: <FormattedMessage id="app.imperialUnits" />
|
||||
}
|
||||
const addProps = setting => {
|
||||
const labels = {
|
||||
sa: {
|
||||
none: <FormattedMessage id="app.noSeamAllowance" />,
|
||||
dflt: <FormattedMessage id="app.standardSeamAllowance" />,
|
||||
custom: <FormattedMessage id="app.customSeamAllowance" />
|
||||
},
|
||||
only: {
|
||||
dflt: <FormattedMessage id="app.default" />,
|
||||
custom: <FormattedMessage id="app.custom" />
|
||||
},
|
||||
paperless: noyes,
|
||||
advanced: hideshow,
|
||||
complete: hideshow
|
||||
}
|
||||
const addProps = (setting) => {
|
||||
let childProps = {
|
||||
raiseEvent: props.raiseEvent,
|
||||
updateValue: props.updateValue,
|
||||
units: props.units,
|
||||
raiseEvent,
|
||||
updateValue,
|
||||
units,
|
||||
key: setting,
|
||||
name: setting,
|
||||
labels: labels[setting],
|
||||
noDocs: props.noDocs,
|
||||
dflt: getDefault(setting, props.pattern),
|
||||
noDocs,
|
||||
dflt: getDefault(setting, pattern),
|
||||
designDflt: getDefault(setting)
|
||||
}
|
||||
childProps.title = <FormattedMessage id={'settings.' + setting + '.title'} />
|
||||
|
@ -76,26 +86,21 @@ const DraftSettings = props => {
|
|||
if (setting === 'only') {
|
||||
childProps.customDflt = []
|
||||
childProps.parts = {}
|
||||
if (props.config.draftOrder) {
|
||||
for (let part of props.config.draftOrder)
|
||||
if (config.draftOrder) {
|
||||
for (let part of config.draftOrder)
|
||||
childProps.parts[part] = <FormattedMessage id={'parts.' + part} />
|
||||
}
|
||||
}
|
||||
if (
|
||||
typeof props.data !== 'undefined' &&
|
||||
typeof props.data.settings !== 'undefined' &&
|
||||
typeof props.data.settings[setting] !== 'undefined'
|
||||
)
|
||||
childProps.value = props.data.settings[setting]
|
||||
if (typeof data.settings[setting] !== 'undefined') childProps.value = data.settings[setting]
|
||||
else childProps.value = null
|
||||
|
||||
return childProps
|
||||
}
|
||||
|
||||
let groups = {
|
||||
const groups = {
|
||||
advanced: [
|
||||
<DraftSettingLanguage {...addProps('locale')} />,
|
||||
<DraftSettingUnits {...addProps('units')} list={units} />,
|
||||
<DraftSettingUnits {...addProps('units')} list={metricimperial} />,
|
||||
<DraftSettingComplete {...addProps('complete')} />,
|
||||
<DraftSettingMargin {...addProps('margin')} />,
|
||||
<DraftSettingOnly {...addProps('only')} />
|
||||
|
@ -103,19 +108,19 @@ const DraftSettings = props => {
|
|||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<>
|
||||
<ul className="config l2 nogroups">
|
||||
<DraftSettingSa {...addProps('sa')} />
|
||||
<DraftSettingPaperless {...addProps('paperless')} />
|
||||
<DraftSettingAdvanced {...addProps('advanced')} />
|
||||
</ul>
|
||||
{props.data.settings.advanced ? (
|
||||
{data.settings.advanced && (
|
||||
<ul className="config l2">
|
||||
{Object.keys(groups).map(group => {
|
||||
{Object.keys(groups).map((group) => {
|
||||
let open = true
|
||||
if (expanded.indexOf(group) === -1) open = false
|
||||
let children = null
|
||||
if (open) children = groups[group].map(component => component)
|
||||
if (open) children = groups[group].map((component) => component)
|
||||
return (
|
||||
<React.Fragment key={group}>
|
||||
<li className={open ? 'expanded' : 'collapsed'} key={group + '-ghead'}>
|
||||
|
@ -129,15 +134,9 @@ const DraftSettings = props => {
|
|||
)
|
||||
})}
|
||||
</ul>
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
DraftSettings.propTypes = {
|
||||
config: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
DraftSettings.defaultProps = {}
|
||||
|
||||
export default DraftSettings
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Pct from '../PatternOptionPercentage'
|
||||
import Deg from '../PatternOptionDegree'
|
||||
import Mm from '../PatternOptionMillimeter'
|
||||
|
@ -12,7 +11,7 @@ import { FormattedMessage } from 'react-intl'
|
|||
import { injectIntl } from 'react-intl'
|
||||
import RightIcon from '@material-ui/icons/KeyboardArrowRight'
|
||||
|
||||
const OptionGroup = props => {
|
||||
const OptionGroup = (props) => {
|
||||
const renderOption = (name, sub = false) => {
|
||||
let option = props.config.options[name]
|
||||
let type = optionType(option)
|
||||
|
@ -66,12 +65,10 @@ const OptionGroup = props => {
|
|||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{props.options.map(name => {
|
||||
//let key = name;
|
||||
<>
|
||||
{props.options.map((name) => {
|
||||
let output = []
|
||||
if (typeof name === 'object') {
|
||||
//key = Object.keys(name).pop();
|
||||
// Subgroup
|
||||
for (let subGroup of Object.keys(name)) {
|
||||
let children = []
|
||||
|
@ -90,16 +87,8 @@ const OptionGroup = props => {
|
|||
|
||||
return output
|
||||
})}
|
||||
</React.Fragment>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
OptionGroup.propTypes = {
|
||||
config: PropTypes.object.isRequired,
|
||||
options: PropTypes.array.isRequired,
|
||||
units: PropTypes.oneOf(['metric', 'imperial']).isRequired
|
||||
}
|
||||
|
||||
OptionGroup.defaultProps = {}
|
||||
|
||||
export default injectIntl(OptionGroup)
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import RightIcon from '@material-ui/icons/KeyboardArrowRight'
|
||||
import ResetIcon from '@material-ui/icons/SettingsBackupRestore'
|
||||
import { injectIntl } from 'react-intl'
|
||||
|
||||
const OptionPreamble = props => {
|
||||
const OptionPreamble = ({
|
||||
intl,
|
||||
title,
|
||||
desc,
|
||||
dflt,
|
||||
designDflt,
|
||||
option,
|
||||
value,
|
||||
displayValue,
|
||||
displayFormat = 'node',
|
||||
sameButDifferent,
|
||||
expanded,
|
||||
toggleExpanded,
|
||||
reset,
|
||||
designReset
|
||||
}) => {
|
||||
const styles = {
|
||||
container: {
|
||||
display: 'flex',
|
||||
|
@ -22,43 +36,41 @@ const OptionPreamble = props => {
|
|||
}
|
||||
}
|
||||
|
||||
const resetLabel = props.intl.formatMessage({
|
||||
const resetLabel = intl.formatMessage({
|
||||
id: 'app.restoreDefaults',
|
||||
defaultMessage: ' ♻️ '
|
||||
})
|
||||
const resetDesignLabel = props.intl.formatMessage({
|
||||
const resetDesignLabel = intl.formatMessage({
|
||||
id: 'app.restoreDesignDefaults',
|
||||
defaultMessage: ' ♻️ '
|
||||
})
|
||||
const resetPatternLabel = props.intl.formatMessage({
|
||||
const resetPatternLabel = intl.formatMessage({
|
||||
id: 'app.restorePatternDefaults',
|
||||
defaultMessage: ' ♻️ '
|
||||
})
|
||||
|
||||
let pattern = false
|
||||
if (props.dflt !== props.designDflt) pattern = true
|
||||
let displayClass = props.value === props.dflt ? 'dflt' : 'custom'
|
||||
if (pattern && props.value === props.designDflt) displayClass = 'p-dflt'
|
||||
else if (pattern && props.sameButDifferent) displayClass = 'custom'
|
||||
let displayValue = <span className={displayClass}>{props.displayValue}</span>
|
||||
if (dflt !== designDflt) pattern = true
|
||||
let displayClass = value === dflt ? 'dflt' : 'custom'
|
||||
if (pattern && value === designDflt) displayClass = 'p-dflt'
|
||||
else if (pattern && sameButDifferent) displayClass = 'custom'
|
||||
let dspValue = <span className={displayClass}>{displayValue}</span>
|
||||
|
||||
if (props.displayFormat === 'html')
|
||||
displayValue = (
|
||||
<span className={displayClass} dangerouslySetInnerHTML={{ __html: props.displayValue }} />
|
||||
)
|
||||
if (displayFormat === 'html')
|
||||
dspValue = <span className={displayClass} dangerouslySetInnerHTML={{ __html: displayValue }} />
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div onClick={props.toggleExpanded} style={styles.container}>
|
||||
<div onClick={toggleExpanded} style={styles.container}>
|
||||
<div style={styles.left}>
|
||||
<RightIcon className={'icon-col-exp ' + (props.expanded ? 'expanded' : 'collapsed')} />
|
||||
{props.title}
|
||||
<RightIcon className={'icon-col-exp ' + (expanded ? 'expanded' : 'collapsed')} />
|
||||
{title}
|
||||
</div>
|
||||
<div style={styles.right}>{displayValue}</div>
|
||||
<div style={styles.right}>{dspValue}</div>
|
||||
</div>
|
||||
<div className={props.expanded ? 'col-exp expanded' : 'col-exp collapsed'}>
|
||||
<div className={expanded ? 'col-exp expanded' : 'col-exp collapsed'}>
|
||||
<div style={styles.container}>
|
||||
<div style={styles.left}>
|
||||
<p>{props.desc}</p>
|
||||
<p>{desc}</p>
|
||||
</div>
|
||||
<div style={styles.right}>
|
||||
{pattern ? (
|
||||
|
@ -66,8 +78,8 @@ const OptionPreamble = props => {
|
|||
title={resetDesignLabel}
|
||||
aria-label={resetDesignLabel}
|
||||
color="primary"
|
||||
disabled={props.value === props.designDflt ? true : false}
|
||||
onClick={props.designReset}
|
||||
disabled={value === designDflt ? true : false}
|
||||
onClick={designReset}
|
||||
className="mini-icon-btn pattern"
|
||||
>
|
||||
<ResetIcon />
|
||||
|
@ -77,40 +89,18 @@ const OptionPreamble = props => {
|
|||
title={pattern ? resetPatternLabel : resetLabel}
|
||||
aria-label={pattern ? resetPatternLabel : resetLabel}
|
||||
color="primary"
|
||||
disabled={props.value === props.dflt && !props.sameButDifferent ? true : false}
|
||||
onClick={props.reset}
|
||||
disabled={value === dflt && !sameButDifferent ? true : false}
|
||||
onClick={reset}
|
||||
className={'mini-icon-btn' + (pattern ? ' pattern' : '')}
|
||||
>
|
||||
<ResetIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
{props.option}
|
||||
{option}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
OptionPreamble.propTypes = {
|
||||
dflt: PropTypes.oneOfType([
|
||||
PropTypes.number.isRequired,
|
||||
PropTypes.string.isRequired,
|
||||
PropTypes.bool.isRequired
|
||||
]),
|
||||
value: PropTypes.oneOfType([
|
||||
PropTypes.number.isRequired,
|
||||
PropTypes.string.isRequired,
|
||||
PropTypes.bool.isRequired
|
||||
]),
|
||||
title: PropTypes.node.isRequired,
|
||||
desc: PropTypes.node.isRequired,
|
||||
reset: PropTypes.func.isRequired,
|
||||
expanded: PropTypes.bool,
|
||||
displayFormat: PropTypes.string
|
||||
}
|
||||
|
||||
OptionPreamble.defaultProps = {
|
||||
displayFormat: 'node'
|
||||
}
|
||||
|
||||
export default injectIntl(OptionPreamble)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import React, { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import FormFieldBool from '../../.form/FormFieldBool'
|
||||
import OptionPreamble from '../OptionPreamble'
|
||||
|
||||
const PatternOptionBool = props => {
|
||||
const PatternOptionBool = (props) => {
|
||||
const [value, setValue] = useState(props.value === null ? props.dflt : props.value)
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
||||
|
@ -62,18 +61,4 @@ const PatternOptionBool = props => {
|
|||
)
|
||||
}
|
||||
|
||||
PatternOptionBool.propTypes = {
|
||||
raiseEvent: PropTypes.func.isRequired,
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
dflt: PropTypes.oneOfType([
|
||||
PropTypes.number.isRequired,
|
||||
PropTypes.string.isRequired,
|
||||
PropTypes.bool.isRequired
|
||||
]),
|
||||
title: PropTypes.node.isRequired,
|
||||
desc: PropTypes.node.isRequired,
|
||||
labels: PropTypes.array.isRequired
|
||||
}
|
||||
|
||||
export default PatternOptionBool
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import React, { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import FormFieldList from '../../.form/FormFieldList'
|
||||
import OptionPreamble from '../OptionPreamble'
|
||||
|
||||
const PatternOptionList = props => {
|
||||
const PatternOptionList = (props) => {
|
||||
const [value, setValue] = useState(props.dflt)
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
||||
|
@ -70,13 +69,4 @@ const PatternOptionList = props => {
|
|||
)
|
||||
}
|
||||
|
||||
PatternOptionList.propTypes = {
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
dflt: PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.string.isRequired]),
|
||||
title: PropTypes.node.isRequired,
|
||||
desc: PropTypes.node.isRequired,
|
||||
list: PropTypes.array.isRequired
|
||||
}
|
||||
|
||||
export default PatternOptionList
|
||||
|
|
|
@ -1,94 +1,85 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import sliderStep from "@freesewing/utils/sliderStep";
|
||||
import roundMm from "@freesewing/utils/roundMm";
|
||||
import roundMmUp from "@freesewing/utils/roundMmUp";
|
||||
import roundMmDown from "@freesewing/utils/roundMmDown";
|
||||
import formatMm from "@freesewing/utils/formatMm";
|
||||
import FormFieldSlider from "../../.form/FormFieldSlider";
|
||||
import OptionPreamble from "../OptionPreamble";
|
||||
import React, { useState } from 'react'
|
||||
import sliderStep from '@freesewing/utils/sliderStep'
|
||||
import roundMm from '@freesewing/utils/roundMm'
|
||||
import roundMmUp from '@freesewing/utils/roundMmUp'
|
||||
import roundMmDown from '@freesewing/utils/roundMmDown'
|
||||
import formatMm from '@freesewing/utils/formatMm'
|
||||
import FormFieldSlider from '../../.form/FormFieldSlider'
|
||||
import OptionPreamble from '../OptionPreamble'
|
||||
|
||||
const PatternOptionMillimeter = props => {
|
||||
const [value, setValue] = useState(props.dflt);
|
||||
const [previousValue, setPreviousValue] = useState(props.dflt);
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
const PatternOptionMillimeter = ({
|
||||
title = false,
|
||||
desc = false,
|
||||
units = 'metric',
|
||||
min = 0,
|
||||
max = 100,
|
||||
updateValue,
|
||||
name,
|
||||
dflt,
|
||||
noDocs
|
||||
}) => {
|
||||
const [val, setVal] = useState(dflt)
|
||||
const [previousValue, setPreviousValue] = useState(dflt)
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
||||
const update = (name, newValue, evt) => {
|
||||
newValue = roundMm(newValue, props.units);
|
||||
newValue = roundMm(newValue, units)
|
||||
// Sometimes, when sliding, the rapid succession of updates
|
||||
// causes a weird timing issue to result in a value that is NaN.
|
||||
// If that's the case, just ignore this update and keep the
|
||||
// previous one instead
|
||||
if (!isNaN(newValue)) {
|
||||
setValue(newValue);
|
||||
if (evt.type !== "mousemove") props.updateValue(props.name, newValue);
|
||||
setVal(newValue)
|
||||
if (evt.type !== 'mousemove') updateValue(name, newValue)
|
||||
} else {
|
||||
if (evt.type !== "mousemove") props.updateValue(props.name, value);
|
||||
if (evt.type !== 'mousemove') updateValue(name, val)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
setValue(props.dflt);
|
||||
props.updateValue(props.name, props.dflt);
|
||||
};
|
||||
setVal(dflt)
|
||||
updateValue(name, dflt)
|
||||
}
|
||||
|
||||
const toggleExpanded = () => setExpanded(!expanded);
|
||||
const toggleExpanded = () => setExpanded(!expanded)
|
||||
|
||||
let option = (
|
||||
<FormFieldSlider
|
||||
name={props.name}
|
||||
value={value}
|
||||
min={roundMmUp(props.min, props.units)}
|
||||
max={roundMmDown(props.max, props.units)}
|
||||
step={sliderStep[props.units]}
|
||||
name={name}
|
||||
value={val}
|
||||
min={roundMmUp(min, units)}
|
||||
max={roundMmDown(units)}
|
||||
step={sliderStep[units]}
|
||||
onChange={update}
|
||||
label={"po-mm-" + props.name}
|
||||
label={'po-mm-' + name}
|
||||
updateValue={update}
|
||||
/>
|
||||
);
|
||||
)
|
||||
|
||||
return (
|
||||
<li>
|
||||
<OptionPreamble
|
||||
dflt={props.dflt}
|
||||
value={value}
|
||||
desc={props.desc}
|
||||
title={props.title}
|
||||
id={"po-mm-" + props.name}
|
||||
displayValue={formatMm(value, props.units)}
|
||||
dflt={dflt}
|
||||
value={val}
|
||||
desc={desc}
|
||||
title={title}
|
||||
id={'po-mm-' + name}
|
||||
displayValue={formatMm(val, units)}
|
||||
displayFormat="html"
|
||||
reset={reset}
|
||||
toggleExpanded={toggleExpanded}
|
||||
expanded={expanded}
|
||||
showHelp={() =>
|
||||
props.raiseEvent("showHelp", {
|
||||
type: "patternOption",
|
||||
value: props.name
|
||||
raiseEvent('showHelp', {
|
||||
type: 'patternOption',
|
||||
value: name
|
||||
})
|
||||
}
|
||||
option={option}
|
||||
noDocs={props.noDocs}
|
||||
noDocs={noDocs}
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
PatternOptionMillimeter.propTypes = {
|
||||
min: PropTypes.number,
|
||||
max: PropTypes.number,
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
dflt: PropTypes.number.isRequired,
|
||||
title: PropTypes.node.isRequired,
|
||||
desc: PropTypes.node.isRequired,
|
||||
units: PropTypes.oneOf(["metric", "imperial"]).isRequired
|
||||
};
|
||||
|
||||
PatternOptionMillimeter.defaultProps = {
|
||||
min: 0,
|
||||
max: 100,
|
||||
title: false,
|
||||
desc: false
|
||||
};
|
||||
|
||||
export default PatternOptionMillimeter;
|
||||
export default PatternOptionMillimeter
|
||||
|
|
|
@ -1,18 +1,27 @@
|
|||
import React, { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import FormFieldSlider from '../../.form/FormFieldSlider'
|
||||
import OptionPreamble from '../OptionPreamble'
|
||||
|
||||
const PatternOptionPctDegCount = props => {
|
||||
const PatternOptionPctDegCount = ({
|
||||
min = 0,
|
||||
max = 100,
|
||||
step = 0.1,
|
||||
type = 'pct',
|
||||
updateValue,
|
||||
name,
|
||||
dflt,
|
||||
designDflt,
|
||||
title,
|
||||
desc,
|
||||
value,
|
||||
raiseEvent,
|
||||
noDocs
|
||||
}) => {
|
||||
let factor = 1
|
||||
if (props.type === 'pct') factor = 100
|
||||
const round = val => Math.round(val * 10) / 10
|
||||
const [value, setValue] = useState(
|
||||
props.value === null ? props.dflt : round(props.value * factor)
|
||||
)
|
||||
const [previousValue, setPreviousValue] = useState(
|
||||
props.value === null ? props.dflt : round(props.value * factor)
|
||||
)
|
||||
if (type === 'pct') factor = 100
|
||||
const round = (val) => Math.round(val * 10) / 10
|
||||
const [val, setVal] = useState(value === null ? dflt : round(value * factor))
|
||||
const [previousValue, setPreviousValue] = useState(value === null ? dflt : round(value * factor))
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
||||
const update = (name, newValue, evt) => {
|
||||
|
@ -22,38 +31,38 @@ const PatternOptionPctDegCount = props => {
|
|||
// If that's the case, just ignore this update and keep the
|
||||
// previous one instead
|
||||
if (!isNaN(newValue)) {
|
||||
setValue(newValue)
|
||||
if (evt.type !== 'mousemove') props.updateValue(props.name, newValue / factor)
|
||||
setVal(newValue)
|
||||
if (evt.type !== 'mousemove') updateValue(name, newValue / factor)
|
||||
} else {
|
||||
if (evt.type !== 'mousemove') props.updateValue(props.name, value / factor)
|
||||
if (evt.type !== 'mousemove') updateValue(name, value / factor)
|
||||
}
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
setValue(props.dflt)
|
||||
props.updateValue(props.name, props.dflt / factor)
|
||||
setVal(dflt)
|
||||
updateValue(name, dflt / factor)
|
||||
}
|
||||
|
||||
const patternReset = () => {
|
||||
setValue(props.designDflt)
|
||||
props.updateValue(props.name, props.designDflt / factor)
|
||||
setVal(designDflt)
|
||||
updateValue(name, designDflt / factor)
|
||||
}
|
||||
|
||||
const toggleExpanded = () => setExpanded(!expanded)
|
||||
|
||||
let unit = ''
|
||||
if (props.type === 'pct') unit = '%'
|
||||
if (props.type === 'deg') unit = '°'
|
||||
if (type === 'pct') unit = '%'
|
||||
if (type === 'deg') unit = '°'
|
||||
|
||||
let option = (
|
||||
<FormFieldSlider
|
||||
name={props.name}
|
||||
value={value}
|
||||
min={props.min}
|
||||
max={props.max}
|
||||
step={props.type === 'count' ? 1 : props.step}
|
||||
name={name}
|
||||
value={val}
|
||||
min={min}
|
||||
max={max}
|
||||
step={type === 'count' ? 1 : step}
|
||||
onChange={update}
|
||||
label={'po-' + props.type + '-' + props.name}
|
||||
label={'po-' + type + '-' + name}
|
||||
updateValue={update}
|
||||
/>
|
||||
)
|
||||
|
@ -61,47 +70,28 @@ const PatternOptionPctDegCount = props => {
|
|||
return (
|
||||
<li>
|
||||
<OptionPreamble
|
||||
dflt={props.dflt}
|
||||
designDflt={props.designDflt}
|
||||
value={value}
|
||||
desc={props.desc}
|
||||
title={props.title}
|
||||
id={'po-' + props.type + '-' + props.name}
|
||||
displayValue={value + unit}
|
||||
dflt={dflt}
|
||||
designDflt={designDflt}
|
||||
value={val}
|
||||
desc={desc}
|
||||
title={title}
|
||||
id={'po-' + type + '-' + name}
|
||||
displayValue={val + unit}
|
||||
reset={reset}
|
||||
patternReset={patternReset}
|
||||
toggleExpanded={toggleExpanded}
|
||||
expanded={expanded}
|
||||
showHelp={() =>
|
||||
props.raiseEvent('showHelp', {
|
||||
raiseEvent('showHelp', {
|
||||
type: 'patternOption',
|
||||
value: props.name
|
||||
value: name
|
||||
})
|
||||
}
|
||||
option={option}
|
||||
noDocs={props.noDocs}
|
||||
noDocs={noDocs}
|
||||
/>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
PatternOptionPctDegCount.propTypes = {
|
||||
min: PropTypes.number,
|
||||
max: PropTypes.number,
|
||||
step: PropTypes.number,
|
||||
updateValue: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
dflt: PropTypes.number.isRequired,
|
||||
title: PropTypes.node.isRequired,
|
||||
desc: PropTypes.node.isRequired,
|
||||
type: PropTypes.oneOf(['pct', 'deg', 'count'])
|
||||
}
|
||||
|
||||
PatternOptionPctDegCount.defaultProps = {
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 0.1,
|
||||
type: 'pct'
|
||||
}
|
||||
|
||||
export default PatternOptionPctDegCount
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import React, { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import OptionGroup from '../OptionGroup'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import RightIcon from '@material-ui/icons/KeyboardArrowRight'
|
||||
|
||||
const PatternOptions = props => {
|
||||
const PatternOptions = (props) => {
|
||||
const [expanded, setExpanded] = useState([])
|
||||
const toggleGroup = group => {
|
||||
const toggleGroup = (group) => {
|
||||
let shown = expanded.slice(0)
|
||||
let index = shown.indexOf(group)
|
||||
if (index === -1) shown.push(group)
|
||||
|
@ -14,7 +13,7 @@ const PatternOptions = props => {
|
|||
setExpanded(shown)
|
||||
}
|
||||
|
||||
const renderGroup = group => {
|
||||
const renderGroup = (group) => {
|
||||
let open = true
|
||||
if (expanded.indexOf(group) === -1) open = false
|
||||
let output = []
|
||||
|
@ -58,11 +57,4 @@ const PatternOptions = props => {
|
|||
return <ul className="config l2">{children}</ul>
|
||||
}
|
||||
|
||||
PatternOptions.propTypes = {
|
||||
config: PropTypes.object.isRequired,
|
||||
raiseEvent: PropTypes.func
|
||||
}
|
||||
|
||||
PatternOptions.defaultProps = {}
|
||||
|
||||
export default PatternOptions
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
import React, { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import React from 'react'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import PatternOptions from './PatternOptions'
|
||||
import DraftSettings from './DraftSettings'
|
||||
|
||||
const DraftConfigurator = props => {
|
||||
const [expanded, setExpanded] = useState([])
|
||||
const DraftConfigurator = ({
|
||||
noDocs = false,
|
||||
units = 'metric',
|
||||
config = {},
|
||||
data = {},
|
||||
pattern,
|
||||
updatePatternData,
|
||||
raiseEvent
|
||||
}) => {
|
||||
let childProps = {
|
||||
noDocs,
|
||||
units,
|
||||
config,
|
||||
data,
|
||||
pattern,
|
||||
raiseEvent
|
||||
}
|
||||
return (
|
||||
<ul className="config l1">
|
||||
<li>
|
||||
|
@ -13,13 +27,8 @@ const DraftConfigurator = props => {
|
|||
<FormattedMessage id="app.designOptions" />
|
||||
</span>
|
||||
<PatternOptions
|
||||
noDocs={props.noDocs}
|
||||
config={props.config}
|
||||
data={props.data}
|
||||
pattern={props.pattern}
|
||||
updateValue={(name, value) => props.updatePatternData(value, 'settings', 'options', name)}
|
||||
raiseEvent={props.raiseEvent}
|
||||
units={props.units}
|
||||
{...childProps}
|
||||
updateValue={(name, value) => updatePatternData(value, 'settings', 'options', name)}
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
|
@ -27,25 +36,12 @@ const DraftConfigurator = props => {
|
|||
<FormattedMessage id="app.patternOptions" />
|
||||
</span>
|
||||
<DraftSettings
|
||||
noDocs={props.noDocs}
|
||||
config={props.config}
|
||||
data={props.data}
|
||||
pattern={props.pattern}
|
||||
updateValue={(name, value) => props.updatePatternData(value, 'settings', name)}
|
||||
raiseEvent={props.raiseEvent}
|
||||
units={props.units}
|
||||
{...childProps}
|
||||
updateValue={(name, value) => updatePatternData(value, 'settings', name)}
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
DraftConfigurator.propTypes = {
|
||||
units: PropTypes.oneOf(['metric', 'imperial']).isRequired
|
||||
}
|
||||
|
||||
DraftConfigurator.defaultProps = {
|
||||
noDocs: false
|
||||
}
|
||||
|
||||
export default DraftConfigurator
|
||||
|
|
|
@ -1,21 +1,10 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React from 'react'
|
||||
|
||||
const Emblem = props => (
|
||||
const Emblem = (props) => (
|
||||
<React.Fragment>
|
||||
<span className="emb">{props.t1}</span>
|
||||
<span className="lem">{props.t2}</span>
|
||||
<span className="emb">{props.t1 || 'Free'}</span>
|
||||
<span className="lem">{props.t2 || 'Sewing'}</span>
|
||||
</React.Fragment>
|
||||
);
|
||||
)
|
||||
|
||||
Emblem.propTypes = {
|
||||
t1: PropTypes.string,
|
||||
t2: PropTypes.string
|
||||
};
|
||||
|
||||
Emblem.defaultProps = {
|
||||
t1: "Free",
|
||||
t2: "Sewing"
|
||||
};
|
||||
|
||||
export default Emblem;
|
||||
export default Emblem
|
||||
|
|
|
@ -1,41 +1,47 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import examples from "@freesewing/examples";
|
||||
import rendertest from "@freesewing/rendertest";
|
||||
import tutorial from "@freesewing/tutorial";
|
||||
import Draft from "../Draft";
|
||||
import Design from "../Workbench/Design";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import ResetIcon from "@material-ui/icons/SettingsBackupRestore";
|
||||
import Switch from "@material-ui/core/Switch";
|
||||
import React, { useState } from 'react'
|
||||
import examples from '@freesewing/examples'
|
||||
import rendertest from '@freesewing/rendertest'
|
||||
import tutorial from '@freesewing/tutorial'
|
||||
import Draft from '../Draft'
|
||||
import Design from '../Workbench/Design'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import ResetIcon from '@material-ui/icons/SettingsBackupRestore'
|
||||
import Switch from '@material-ui/core/Switch'
|
||||
|
||||
const Example = props => {
|
||||
const [design, setDesign] = useState(false);
|
||||
const [focus, setFocus] = useState(null);
|
||||
const Example = ({
|
||||
pattern = 'examples',
|
||||
design = true,
|
||||
caption = '',
|
||||
options = {},
|
||||
settings,
|
||||
part = '',
|
||||
sample
|
||||
}) => {
|
||||
const [designMode, setDesignMode] = useState(false)
|
||||
const [focus, setFocus] = useState(null)
|
||||
|
||||
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);
|
||||
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);
|
||||
};
|
||||
setFocus(f)
|
||||
}
|
||||
|
||||
let focusCount = 0;
|
||||
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++;
|
||||
for (let i in focus[p].points) focusCount++
|
||||
for (let i in focus[p].paths) focusCount++
|
||||
for (let i in focus[p].coords) focusCount++
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,75 +49,49 @@ const Example = props => {
|
|||
examples,
|
||||
rendertest,
|
||||
tutorial
|
||||
};
|
||||
const settings = {
|
||||
options: { ...props.options },
|
||||
}
|
||||
settings = {
|
||||
options: { ...options },
|
||||
measurements: { headCircumference: 390 },
|
||||
...props.settings
|
||||
};
|
||||
if (props.part !== "") settings.only = [props.part];
|
||||
const pattern = new patterns[props.pattern](settings);
|
||||
...settings
|
||||
}
|
||||
if (part !== '') settings.only = [part]
|
||||
const patternInstance = new patterns[pattern](settings)
|
||||
|
||||
if (props.sample) pattern.sample();
|
||||
else pattern.draft();
|
||||
const patternProps = pattern.getRenderProps();
|
||||
if (sample) patternInstance.sample()
|
||||
else patternInstance.draft()
|
||||
const patternProps = patternInstance.getRenderProps()
|
||||
return (
|
||||
<figure className={design ? "design example" : "example"}>
|
||||
<figure className={designMode ? 'design example' : 'example'}>
|
||||
<div className="example">
|
||||
{props.design ? (
|
||||
{designMode ? (
|
||||
<div className="actions">
|
||||
{design ? (
|
||||
<IconButton
|
||||
color="primary"
|
||||
onClick={() => raiseEvent("clearFocusAll", null)}
|
||||
>
|
||||
<ResetIcon />
|
||||
</IconButton>
|
||||
) : null}
|
||||
<IconButton color="primary" onClick={() => raiseEvent('clearFocusAll', null)}>
|
||||
<ResetIcon />
|
||||
</IconButton>
|
||||
<Switch
|
||||
checked={design}
|
||||
onChange={() => setDesign(!design)}
|
||||
value={design}
|
||||
checked={designMode}
|
||||
onChange={() => setDesignMode(!designMode)}
|
||||
value={designMode}
|
||||
color="primary"
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<Draft
|
||||
{...patternProps}
|
||||
design={design}
|
||||
focus={focus}
|
||||
raiseEvent={raiseEvent}
|
||||
/>
|
||||
<Draft {...patternProps} design={design} focus={focus} raiseEvent={raiseEvent} />
|
||||
</div>
|
||||
<figcaption>{props.caption}</figcaption>
|
||||
{design ? (
|
||||
<figcaption>{caption}</figcaption>
|
||||
{designMode && (
|
||||
<div className="design">
|
||||
<Design
|
||||
focus={focus}
|
||||
design={design}
|
||||
design={designMode}
|
||||
raiseEvent={raiseEvent}
|
||||
parts={patternProps.parts}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
)}
|
||||
</figure>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
Example.propTypes = {
|
||||
pattern: PropTypes.string,
|
||||
design: PropTypes.bool,
|
||||
caption: PropTypes.string,
|
||||
part: PropTypes.string,
|
||||
options: PropTypes.obj
|
||||
};
|
||||
|
||||
Example.defaultProps = {
|
||||
pattern: "examples",
|
||||
design: true,
|
||||
caption: "",
|
||||
options: {},
|
||||
part: ""
|
||||
};
|
||||
|
||||
export default Example;
|
||||
export default Example
|
||||
|
|
|
@ -1,40 +1,24 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import icons from "./icons";
|
||||
import React from 'react'
|
||||
import icons from './icons'
|
||||
|
||||
const Icon = props => {
|
||||
return (
|
||||
<svg
|
||||
style={props.style}
|
||||
className={props.className}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={props.size}
|
||||
height={props.size}
|
||||
viewBox={props.viewBox}
|
||||
>
|
||||
<path
|
||||
stroke="none"
|
||||
fill={props.color ? props.color : "currentColor"}
|
||||
d={icons[props.icon]}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
const Icon = ({
|
||||
size = 24,
|
||||
viewBox = '0 0 24 24',
|
||||
className = '',
|
||||
icon = 'github',
|
||||
color = false,
|
||||
style = {}
|
||||
}) => (
|
||||
<svg
|
||||
style={style}
|
||||
className={className}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox={viewBox}
|
||||
>
|
||||
<path stroke="none" fill={color ? color : 'currentColor'} d={icons[icon]} />
|
||||
</svg>
|
||||
)
|
||||
|
||||
Icon.propTypes = {
|
||||
size: PropTypes.number,
|
||||
viewBox: PropTypes.string,
|
||||
icon: PropTypes.string,
|
||||
style: PropTypes.object
|
||||
};
|
||||
|
||||
Icon.defaultProps = {
|
||||
size: 24,
|
||||
viewBox: "0 0 24 24",
|
||||
className: "",
|
||||
icon: "github",
|
||||
color: false,
|
||||
style: {}
|
||||
};
|
||||
|
||||
export default Icon;
|
||||
export default Icon
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import patterns from './patterns'
|
||||
|
||||
const LineDrawing = props => {
|
||||
const LineDrawing = (props) => {
|
||||
const attr = {
|
||||
style: props.style,
|
||||
className: 'fs linedrawing ' + props.className,
|
||||
style: props.style || {},
|
||||
className: 'fs linedrawing ' + (props.className || ''),
|
||||
xmlns: 'http://www.w3.org/2000/svg',
|
||||
viewBox: '0 0 270 270'
|
||||
}
|
||||
|
@ -13,20 +12,7 @@ const LineDrawing = props => {
|
|||
attr.width = props.size
|
||||
attr.height = props.size
|
||||
}
|
||||
return <svg {...attr}>{patterns[props.pattern] || null}</svg>
|
||||
}
|
||||
|
||||
LineDrawing.propTypes = {
|
||||
size: PropTypes.number,
|
||||
pattern: PropTypes.string,
|
||||
style: PropTypes.object
|
||||
}
|
||||
|
||||
LineDrawing.defaultProps = {
|
||||
size: 0,
|
||||
className: '',
|
||||
pattern: 'aaron',
|
||||
style: {}
|
||||
return <svg {...attr}>{patterns[props.pattern || 'aaron'] || null}</svg>
|
||||
}
|
||||
|
||||
export default LineDrawing
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,11 +1,15 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Logo from '../Logo'
|
||||
import Emblem from '../Emblem'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import useMediaQuery from '@material-ui/core/useMediaQuery'
|
||||
|
||||
const Navbar = props => {
|
||||
const Navbar = ({
|
||||
home = 'https://freesewing.org/',
|
||||
navs = { left: [], right: [], mleft: {}, mright: {} },
|
||||
logo = <Logo embed color="#e9ecef" />,
|
||||
emblem = <Emblem />
|
||||
}) => {
|
||||
const mobile = useMediaQuery('(max-width:599px)')
|
||||
|
||||
if (mobile) return null
|
||||
|
@ -47,49 +51,36 @@ const Navbar = props => {
|
|||
let homeProps = {
|
||||
href: '#home'
|
||||
}
|
||||
if (typeof props.home === 'function') homeProps.onClick = props.home
|
||||
else homeProps.href = props.home
|
||||
if (typeof home === 'function') homeProps.onClick = home
|
||||
else homeProps.href = home
|
||||
|
||||
let logo = (
|
||||
let logoDiv = (
|
||||
<div className="logo">
|
||||
<a id="home" {...homeProps} data-test="navbar-home">
|
||||
{props.logo}
|
||||
{logo}
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
let emblem = (
|
||||
let emblemDiv = (
|
||||
<div className="emblem">
|
||||
<a {...homeProps}>{props.emblem}</a>
|
||||
<a {...homeProps}>{emblem}</a>
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<header className="navbar">
|
||||
<div>
|
||||
<div style={{ display: 'flex' }}>
|
||||
{logo}
|
||||
{emblem}
|
||||
{Object.keys(props.navs.left).map(key => renderNav(key, props.navs.left[key]))}
|
||||
{logoDiv}
|
||||
{emblemDiv}
|
||||
{Object.keys(navs.left).map((key) => renderNav(key, navs.left[key]))}
|
||||
</div>
|
||||
<div className="spread" />
|
||||
<div style={{ display: 'flex' }}>
|
||||
{Object.keys(props.navs.right).map(key => renderNav(key, props.navs.right[key]))}
|
||||
{Object.keys(navs.right).map((key) => renderNav(key, navs.right[key]))}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
Navbar.propTypes = {
|
||||
navs: PropTypes.object,
|
||||
logo: PropTypes.node,
|
||||
emblem: PropTypes.node,
|
||||
home: PropTypes.oneOfType([PropTypes.string, PropTypes.func])
|
||||
}
|
||||
|
||||
Navbar.defaultProps = {
|
||||
home: 'https://freesewing.org/',
|
||||
navs: { left: [], right: [], mleft: {}, mright: {} },
|
||||
logo: <Logo embed color="#e9ecef" />,
|
||||
emblem: <Emblem />
|
||||
}
|
||||
export default Navbar
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,38 +1,23 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import poses from "./poses";
|
||||
import React from 'react'
|
||||
import poses from './poses'
|
||||
|
||||
const Robot = props => {
|
||||
return (
|
||||
<svg
|
||||
className={props.className}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={props.embed ? "" : props.size}
|
||||
height={props.embed ? "" : props.size}
|
||||
viewBox={props.viewBox}
|
||||
>
|
||||
<path
|
||||
stroke="none"
|
||||
fill={props.color ? props.color : "currentColor"}
|
||||
d={poses[props.pose]}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
const Robot = ({
|
||||
size = 124,
|
||||
viewBox = '0 0 500 500',
|
||||
className = '',
|
||||
pose = 'yay',
|
||||
color = false,
|
||||
embed = false
|
||||
}) => (
|
||||
<svg
|
||||
className={className || ''}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={embed ? '' : size || 124}
|
||||
height={embed ? '' : size || 124}
|
||||
viewBox={viewBox || '0 0 500 500'}
|
||||
>
|
||||
<path stroke="none" fill={color ? color : 'currentColor'} d={poses[pose]} />
|
||||
</svg>
|
||||
)
|
||||
|
||||
Robot.propTypes = {
|
||||
size: PropTypes.number,
|
||||
viewBox: PropTypes.string,
|
||||
pose: PropTypes.string,
|
||||
embed: PropTypes.bool
|
||||
};
|
||||
|
||||
Robot.defaultProps = {
|
||||
size: 124,
|
||||
viewBox: "0 0 500 500",
|
||||
className: "",
|
||||
pose: "yay",
|
||||
color: false
|
||||
};
|
||||
|
||||
export default Robot;
|
||||
export default Robot
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import { injectIntl } from 'react-intl'
|
||||
|
||||
const OptionGroup = props => {
|
||||
const OptionGroup = (props) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{props.options.map(name => {
|
||||
{props.options.map((name) => {
|
||||
let output = []
|
||||
if (typeof name === 'object') {
|
||||
// Subgroup
|
||||
|
@ -44,11 +43,4 @@ const OptionGroup = props => {
|
|||
)
|
||||
}
|
||||
|
||||
OptionGroup.propTypes = {
|
||||
config: PropTypes.object.isRequired,
|
||||
options: PropTypes.array.isRequired
|
||||
}
|
||||
|
||||
OptionGroup.defaultProps = {}
|
||||
|
||||
export default injectIntl(OptionGroup)
|
||||
|
|
|
@ -1,46 +1,38 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OptionGroup from "../OptionGroup";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import React from 'react'
|
||||
import OptionGroup from '../OptionGroup'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
|
||||
const PatternOptions = props => {
|
||||
const renderGroup = group => {
|
||||
let output = [];
|
||||
const PatternOptions = (props) => {
|
||||
const renderGroup = (group) => {
|
||||
let output = []
|
||||
let children = (
|
||||
<ul className="links">
|
||||
<OptionGroup
|
||||
key={group + "-group"}
|
||||
key={group + '-group'}
|
||||
units={props.units}
|
||||
config={props.config}
|
||||
options={props.config.optionGroups[group]}
|
||||
sampleOption={props.sampleOption}
|
||||
/>
|
||||
</ul>
|
||||
);
|
||||
)
|
||||
output.push(
|
||||
<li key={group + "-ghead"} className="nodot">
|
||||
<li key={group + '-ghead'} className="nodot">
|
||||
<h3>
|
||||
<FormattedMessage id={"optiongroups." + group} />
|
||||
<FormattedMessage id={'optiongroups.' + group} />
|
||||
</h3>
|
||||
{children}
|
||||
</li>
|
||||
);
|
||||
)
|
||||
|
||||
return output;
|
||||
};
|
||||
return output
|
||||
}
|
||||
|
||||
return (
|
||||
<ul className="links">
|
||||
{Object.keys(props.config.optionGroups).map(group => renderGroup(group))}
|
||||
{Object.keys(props.config.optionGroups).map((group) => renderGroup(group))}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
PatternOptions.propTypes = {
|
||||
config: PropTypes.object.isRequired,
|
||||
sampleOption: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
PatternOptions.defaultProps = {};
|
||||
|
||||
export default PatternOptions;
|
||||
export default PatternOptions
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const Spinner = props => {
|
||||
const Spinner = (props) => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={props.embed ? '' : props.size}
|
||||
height={props.embed ? '' : props.size}
|
||||
width={props.embed ? '' : props.size || 200}
|
||||
height={props.embed ? '' : props.size || 200}
|
||||
viewBox="-28 -28 108 108"
|
||||
className={'spinner ' + props.className}
|
||||
>
|
||||
|
@ -65,14 +64,4 @@ const Spinner = props => {
|
|||
)
|
||||
}
|
||||
|
||||
Spinner.propTypes = {
|
||||
size: PropTypes.number,
|
||||
embed: PropTypes.bool
|
||||
}
|
||||
|
||||
Spinner.defaultProps = {
|
||||
size: 200,
|
||||
embed: false
|
||||
}
|
||||
|
||||
export default Spinner
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Draft from '../../Draft'
|
||||
import Zoombox from '../Zoombox'
|
||||
import Design from '../Design'
|
||||
|
@ -115,7 +114,7 @@ const DraftPattern = (props) => {
|
|||
|
||||
return (
|
||||
<div className="fs-sa">
|
||||
<section>
|
||||
<section style={{ margin: '1rem' }}>
|
||||
<Draft
|
||||
{...patternProps}
|
||||
design={design}
|
||||
|
@ -224,7 +223,7 @@ const DraftPattern = (props) => {
|
|||
updatePatternData={props.updateGist}
|
||||
raiseEvent={props.raiseEvent}
|
||||
freesewing={props.freesewing}
|
||||
units={props.units}
|
||||
units={props.units || 'metric'}
|
||||
/>
|
||||
</div>
|
||||
</aside>
|
||||
|
@ -232,18 +231,4 @@ const DraftPattern = (props) => {
|
|||
)
|
||||
}
|
||||
|
||||
DraftPattern.propTypes = {
|
||||
gist: PropTypes.object.isRequired,
|
||||
updateGist: PropTypes.func.isRequired,
|
||||
config: PropTypes.object.isRequired,
|
||||
raiseEvent: PropTypes.func.isRequired,
|
||||
Pattern: PropTypes.func.isRequired,
|
||||
units: PropTypes.oneOf(['metric', 'imperial'])
|
||||
}
|
||||
|
||||
DraftPattern.defaultProps = {
|
||||
units: 'metric',
|
||||
pointInfo: null
|
||||
}
|
||||
|
||||
export default DraftPattern
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import { FormattedMessage, FormattedHTMLMessage } from "react-intl";
|
||||
import FormFieldMeasurement from "../../.form/FormFieldMeasurement";
|
||||
import { withBreasts, withoutBreasts } from "@freesewing/models";
|
||||
import React from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { FormattedMessage, FormattedHTMLMessage } from 'react-intl'
|
||||
import FormFieldMeasurement from '../../.form/FormFieldMeasurement'
|
||||
import { withBreasts, withoutBreasts } from '@freesewing/models'
|
||||
|
||||
const Measurements = props => {
|
||||
const Measurements = (props) => {
|
||||
const styles = {
|
||||
container: {
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
width: "100%",
|
||||
minHeight: "70vh"
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
width: '100%',
|
||||
minHeight: '70vh'
|
||||
},
|
||||
chooser: {
|
||||
width: "100%",
|
||||
maxWidth: "500px",
|
||||
margin: "auto",
|
||||
alignSelf: "center"
|
||||
width: '100%',
|
||||
maxWidth: '500px',
|
||||
margin: 'auto',
|
||||
alignSelf: 'center'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const getValue = m => {
|
||||
if (props.measurements === null) return "";
|
||||
if (typeof props.measurements[m] === "undefined") return "";
|
||||
return props.measurements[m];
|
||||
};
|
||||
const getValue = (m) => {
|
||||
if (props.measurements === null) return ''
|
||||
if (typeof props.measurements[m] === 'undefined') return ''
|
||||
return props.measurements[m]
|
||||
}
|
||||
|
||||
if (props.required.length < 1)
|
||||
return (
|
||||
|
@ -43,18 +42,14 @@ const Measurements = props => {
|
|||
<p>
|
||||
<FormattedMessage id="cfp.seeDocsAt" />
|
||||
|
||||
<a
|
||||
href={
|
||||
"https://" + props.language + "/.freesewing.dev/core/config"
|
||||
}
|
||||
>
|
||||
<a href={'https://' + props.language + '/.freesewing.dev/core/config'}>
|
||||
{props.language}
|
||||
.freesewing.dev/core/config
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<div style={styles.chooser}>
|
||||
|
@ -79,13 +74,13 @@ const Measurements = props => {
|
|||
<h3 id="manual">
|
||||
<FormattedMessage id="cfp.enterMeasurements" />
|
||||
</h3>
|
||||
{props.required.map(m => (
|
||||
{props.required.map((m) => (
|
||||
<FormFieldMeasurement
|
||||
key={m}
|
||||
name={m}
|
||||
units={props.units}
|
||||
value={getValue(m)}
|
||||
label={"measurements." + m}
|
||||
label={'measurements.' + m}
|
||||
updateValue={props.updateMeasurement}
|
||||
/>
|
||||
))}
|
||||
|
@ -96,11 +91,9 @@ const Measurements = props => {
|
|||
<FormattedMessage id="app.withoutBreasts" />
|
||||
</h4>
|
||||
<ul>
|
||||
{Object.keys(withoutBreasts).map(m => (
|
||||
{Object.keys(withoutBreasts).map((m) => (
|
||||
<li key={m}>
|
||||
<Button
|
||||
onClick={() => props.preloadMeasurements(withoutBreasts[m])}
|
||||
>
|
||||
<Button onClick={() => props.preloadMeasurements(withoutBreasts[m])}>
|
||||
<FormattedMessage id="cfp.size" />
|
||||
|
||||
{m.slice(-2)}
|
||||
|
@ -112,7 +105,7 @@ const Measurements = props => {
|
|||
<FormattedMessage id="app.withBreasts" />
|
||||
</h4>
|
||||
<ul>
|
||||
{Object.keys(withBreasts).map(m => (
|
||||
{Object.keys(withBreasts).map((m) => (
|
||||
<li key={m}>
|
||||
<Button onClick={() => props.preloadMeasurements(withBreasts[m])}>
|
||||
<FormattedMessage id="cfp.size" />
|
||||
|
@ -124,15 +117,7 @@ const Measurements = props => {
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
Measurements.propTypes = {
|
||||
measurements: PropTypes.object.isRequired,
|
||||
required: PropTypes.array.isRequired,
|
||||
units: PropTypes.oneOf(["metric", "imperial"]),
|
||||
updateMeasurement: PropTypes.func.isRequired,
|
||||
preloadMeasurements: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default Measurements;
|
||||
export default Measurements
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import SampleConfigurator from '../../SampleConfigurator'
|
||||
import svgattrPlugin from '@freesewing/plugin-svgattr'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
|
@ -35,7 +34,7 @@ const SamplePattern = (props) => {
|
|||
updateGist={props.updateGist}
|
||||
raiseEvent={props.raiseEvent}
|
||||
freesewing={props.freesewing}
|
||||
units={props.units}
|
||||
units={props.units || 'metric'}
|
||||
/>
|
||||
</div>
|
||||
</aside>
|
||||
|
@ -43,18 +42,4 @@ const SamplePattern = (props) => {
|
|||
)
|
||||
}
|
||||
|
||||
SamplePattern.propTypes = {
|
||||
gist: PropTypes.object.isRequired,
|
||||
updateGist: PropTypes.func.isRequired,
|
||||
config: PropTypes.object.isRequired,
|
||||
raiseEvent: PropTypes.func.isRequired,
|
||||
Pattern: PropTypes.func.isRequired,
|
||||
units: PropTypes.oneOf(['metric', 'imperial'])
|
||||
}
|
||||
|
||||
SamplePattern.defaultProps = {
|
||||
units: 'metric',
|
||||
pointInfo: null
|
||||
}
|
||||
|
||||
export default SamplePattern
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Logo from "../../Logo";
|
||||
import FormattedMessage from "react-intl";
|
||||
import Button from "@material-ui/core/Button";
|
||||
|
||||
const Welcome = props => {
|
||||
|
||||
const style = {
|
||||
textAlign: "center"
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fs-sa">
|
||||
<section style={{style}}>
|
||||
<div><Logo size={250} /></div>
|
||||
<h1><FormattedMessage id="app.welcome" /></h1>
|
||||
<p><FormattedMessage id="cfp.devDocsAvailableAt" /> <a href="https://freesewing.dev/">freesewing.dev</a></p>
|
||||
<p><FormattedMessage id="cfp.talkToUs" />: <a href="https://gitter.im/freesewing/freesewing/">gitter.im/freesewing</a></p>
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="large"
|
||||
onClick={() => props.setDisplay('pattern')}
|
||||
><FormattedMessage id="app.docs" /></Button>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Welcome;
|
|
@ -43,7 +43,6 @@ const Zoombox = (props) => {
|
|||
setPanning(false)
|
||||
setPanFrom(false)
|
||||
updateViewBox(evt)
|
||||
//props.setViewBox(`${from[0] * factor} ${from[1] * factor} ${to[0] * factor} ${to[1] * factor}`)
|
||||
}
|
||||
}
|
||||
const handlePan = (evt) => {
|
||||
|
@ -55,9 +54,9 @@ const Zoombox = (props) => {
|
|||
// Bump into left
|
||||
} else if (from[1] + (evt.clientY - panFrom[1]) <= -5) {
|
||||
// Bump into top
|
||||
} else if (to[0] + (evt.clientX - panFrom[0]) >= box.width - 11) {
|
||||
} else if (to[0] + (evt.clientX - panFrom[0]) >= box.width + 5) {
|
||||
// Bump into right
|
||||
} else if (to[1] + (evt.clientY - panFrom[1]) >= box.height - 11) {
|
||||
} else if (to[1] + (evt.clientY - panFrom[1]) >= box.height + 5) {
|
||||
// Bump into bottom
|
||||
} else {
|
||||
setPanFrom([evt.clientX, evt.clientY])
|
||||
|
@ -78,7 +77,12 @@ const Zoombox = (props) => {
|
|||
if (dragging == 2) {
|
||||
updateViewBox(evt)
|
||||
if (falseAlarm) setFalseAlarm(false)
|
||||
} else setFalseAlarm(true)
|
||||
} else {
|
||||
setFalseAlarm(true)
|
||||
let box = ref.current.getBoundingClientRect()
|
||||
setBox(box)
|
||||
setFactor(props.patternProps.width / box.width)
|
||||
}
|
||||
setDragging(false)
|
||||
setPanning(false)
|
||||
evt.stopPropagation()
|
||||
|
@ -93,20 +97,15 @@ const Zoombox = (props) => {
|
|||
setTo([evt.clientX - box.x, evt.clientY - box.y])
|
||||
}
|
||||
}
|
||||
const handleMouseOver = (evt) => {
|
||||
evt.stopPropagation()
|
||||
evt.preventDefault()
|
||||
setFactor(props.patternProps.width / box.width)
|
||||
}
|
||||
const updateViewBox = (evt) => {
|
||||
props.setViewBox(
|
||||
from[0] * factor +
|
||||
' ' +
|
||||
from[1] * factor +
|
||||
' ' +
|
||||
(evt.clientX - box.x - from[0]) * factor +
|
||||
(to[0] - from[0]) * factor +
|
||||
' ' +
|
||||
(evt.clientY - box.y - from[1]) * factor
|
||||
(to[1] - from[1]) * factor
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -115,7 +114,6 @@ const Zoombox = (props) => {
|
|||
<div
|
||||
onMouseDown={handleMouseDown}
|
||||
onMouseUp={handleMouseUp}
|
||||
onMouseOver={handleMouseOver}
|
||||
onMouseMove={handleMouseMove}
|
||||
className="zoombox"
|
||||
ref={ref}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import withGist from '../withGist'
|
||||
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles'
|
||||
import Navbar from '../Navbar'
|
||||
|
@ -17,7 +16,18 @@ import Welcome from './Welcome'
|
|||
import Footer from '../Footer'
|
||||
import Measurements from './Measurements'
|
||||
|
||||
const Workbench = (props) => {
|
||||
const Workbench = ({
|
||||
updateGist,
|
||||
setLanguage,
|
||||
userLanguage = 'en',
|
||||
language = 'en',
|
||||
gist,
|
||||
importGist,
|
||||
config,
|
||||
freesewing,
|
||||
Pattern,
|
||||
units = 'metric'
|
||||
}) => {
|
||||
const [display, setDisplay] = useState(null)
|
||||
const [pattern, setPattern] = useState(false)
|
||||
const [theme, setTheme] = useState('light')
|
||||
|
@ -27,27 +37,23 @@ const Workbench = (props) => {
|
|||
useEffect(() => {
|
||||
let m = getMeasurements()
|
||||
setMeasurements(m)
|
||||
props.updateGist(m, 'settings', 'measurements')
|
||||
updateGist(m, 'settings', 'measurements')
|
||||
setDisplay(getDisplay())
|
||||
props.setLanguage(props.userLanguage || 'en')
|
||||
setLanguage(userLanguage)
|
||||
}, [])
|
||||
useEffect(() => {
|
||||
if (props.from) props.importGist(props.from)
|
||||
}, [props.from])
|
||||
useEffect(() => {
|
||||
if (props.language !== props.gist.settings.locale)
|
||||
props.updateGist(props.language, 'settings', 'locale')
|
||||
}, [props.language])
|
||||
if (language !== gist.settings.locale) updateGist(language, 'settings', 'locale')
|
||||
}, [language])
|
||||
|
||||
const getDisplay = () => storage.get(props.config.name + '-display')
|
||||
const getDisplay = () => storage.get(config.name + '-display')
|
||||
const saveDisplay = (d) => {
|
||||
setDisplay(d)
|
||||
storage.set(props.config.name + '-display', d)
|
||||
storage.set(config.name + '-display', d)
|
||||
}
|
||||
const getMeasurements = () => storage.get(props.config.name + '-measurements')
|
||||
const getMeasurements = () => storage.get(config.name + '-measurements')
|
||||
const saveMeasurements = (data) => {
|
||||
storage.set(props.config.name + '-measurements', data)
|
||||
props.updateGist(data, 'settings', 'measurements')
|
||||
storage.set(config.name + '-measurements', data)
|
||||
updateGist(data, 'settings', 'measurements')
|
||||
}
|
||||
const updateMeasurement = (name, val) => {
|
||||
let updatedMeasurements = { ...measurements }
|
||||
|
@ -64,7 +70,7 @@ const Workbench = (props) => {
|
|||
saveMeasurements(updatedMeasurements)
|
||||
}
|
||||
const measurementsMissing = () => {
|
||||
let required = props.config.measurements
|
||||
let required = config.measurements
|
||||
if (required.length < 1) return false
|
||||
if (measurements === null) return true
|
||||
for (let m of required) {
|
||||
|
@ -110,7 +116,7 @@ const Workbench = (props) => {
|
|||
version: {
|
||||
type: 'link',
|
||||
href: 'https://github.com/freesewing/freesewing/releases',
|
||||
text: 'v' + props.freesewing.version
|
||||
text: 'v' + freesewing.version
|
||||
},
|
||||
language: {
|
||||
type: 'button',
|
||||
|
@ -140,19 +146,19 @@ const Workbench = (props) => {
|
|||
let main = null
|
||||
switch (display) {
|
||||
case 'languages':
|
||||
main = <LanguageChooser setLanguage={props.setLanguage} setDisplay={saveDisplay} />
|
||||
main = <LanguageChooser setLanguage={setLanguage} setDisplay={saveDisplay} />
|
||||
break
|
||||
case 'draft':
|
||||
if (measurementsMissing()) saveDisplay('measurements')
|
||||
main = (
|
||||
<DraftPattern
|
||||
freesewing={props.freesewing}
|
||||
Pattern={props.Pattern}
|
||||
config={props.config}
|
||||
gist={props.gist}
|
||||
updateGist={props.updateGist}
|
||||
freesewing={freesewing}
|
||||
Pattern={Pattern}
|
||||
config={config}
|
||||
gist={gist}
|
||||
updateGist={updateGist}
|
||||
raiseEvent={raiseEvent}
|
||||
units={props.units}
|
||||
units={units}
|
||||
svgExport={svgExport}
|
||||
setSvgExport={setSvgExport}
|
||||
theme={theme}
|
||||
|
@ -163,13 +169,13 @@ const Workbench = (props) => {
|
|||
if (measurementsMissing()) saveDisplay('measurements')
|
||||
main = (
|
||||
<SamplePattern
|
||||
freesewing={props.freesewing}
|
||||
Pattern={props.Pattern}
|
||||
config={props.config}
|
||||
gist={props.gist}
|
||||
updateGist={props.updateGist}
|
||||
freesewing={freesewing}
|
||||
Pattern={Pattern}
|
||||
config={config}
|
||||
gist={gist}
|
||||
updateGist={updateGist}
|
||||
raiseEvent={raiseEvent}
|
||||
units={props.units}
|
||||
units={units}
|
||||
/>
|
||||
)
|
||||
break
|
||||
|
@ -177,59 +183,49 @@ const Workbench = (props) => {
|
|||
main = (
|
||||
<Measurements
|
||||
measurements={measurements}
|
||||
required={props.config.measurements}
|
||||
units={props.units}
|
||||
required={config.measurements}
|
||||
units={units}
|
||||
updateMeasurement={updateMeasurement}
|
||||
preloadMeasurements={preloadMeasurements}
|
||||
language={props.language}
|
||||
language={language}
|
||||
/>
|
||||
)
|
||||
break
|
||||
case 'json':
|
||||
main = <Json gist={props.gist} />
|
||||
main = <Json gist={gist} />
|
||||
break
|
||||
case 'inspect':
|
||||
main = (
|
||||
<InspectPattern
|
||||
freesewing={props.freesewing}
|
||||
Pattern={props.Pattern}
|
||||
config={props.config}
|
||||
gist={props.gist}
|
||||
updateGist={props.updateGist}
|
||||
freesewing={freesewing}
|
||||
Pattern={Pattern}
|
||||
config={config}
|
||||
gist={gist}
|
||||
updateGist={updateGist}
|
||||
raiseEvent={raiseEvent}
|
||||
units={props.units}
|
||||
units={units}
|
||||
svgExport={svgExport}
|
||||
setSvgExport={setSvgExport}
|
||||
/>
|
||||
)
|
||||
break
|
||||
default:
|
||||
main = <Welcome language={props.language} setDisplay={saveDisplay} />
|
||||
main = <Welcome language={language} setDisplay={saveDisplay} />
|
||||
}
|
||||
|
||||
const themes = { dark, light }
|
||||
|
||||
return (
|
||||
<MuiThemeProvider theme={createMuiTheme(themes[theme])}>
|
||||
<div className={theme === 'light' ? 'theme-wrapper light' : 'theme-wrapper dark'}>
|
||||
{display !== 'welcome' ? <Navbar navs={navs} home={() => saveDisplay('welcome')} /> : null}
|
||||
{main}
|
||||
{display !== 'welcome' ? <Footer language={props.language} /> : null}
|
||||
{display !== 'welcome' ? <Footer language={language} /> : null}
|
||||
</div>
|
||||
</MuiThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
Workbench.propTypes = {
|
||||
freesewing: PropTypes.object.isRequired,
|
||||
Pattern: PropTypes.func.isRequired,
|
||||
config: PropTypes.object.isRequired,
|
||||
from: PropTypes.object
|
||||
}
|
||||
|
||||
Workbench.defaultProps = {
|
||||
from: { settings: { embed: true } }
|
||||
}
|
||||
|
||||
export default withLanguage(
|
||||
withGist(Workbench, {
|
||||
gist: defaultGist,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue