🚧 More work on React components
This commit is contained in:
parent
66b42967dc
commit
e2b5ba2ee7
10 changed files with 10841 additions and 73 deletions
10667
packages/components/package-lock.json
generated
10667
packages/components/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -22,7 +22,8 @@
|
||||||
"build": "./scripts/build.sh",
|
"build": "./scripts/build.sh",
|
||||||
"test": "echo \"components: No tests configured. Perhaps you'd like to do this?\" && exit 0",
|
"test": "echo \"components: No tests configured. Perhaps you'd like to do this?\" && exit 0",
|
||||||
"pubtest": "npm publish --registry http://localhost:6662",
|
"pubtest": "npm publish --registry http://localhost:6662",
|
||||||
"storybook": "start-storybook -p 6663"
|
"storybook": "start-storybook -p 6006",
|
||||||
|
"build-storybook": "build-storybook"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1",
|
||||||
|
@ -46,5 +47,15 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@freesewing/i18n": "0.11.3",
|
"@freesewing/i18n": "0.11.3",
|
||||||
"@freesewing/patterns": "0.18.6"
|
"@freesewing/patterns": "0.18.6"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.4.3",
|
||||||
|
"@storybook/addon-actions": "^5.0.10",
|
||||||
|
"@storybook/addon-console": "^1.1.0",
|
||||||
|
"@storybook/addon-links": "^5.0.10",
|
||||||
|
"@storybook/addons": "^5.0.10",
|
||||||
|
"@storybook/react": "^5.0.10",
|
||||||
|
"babel-loader": "^8.0.5",
|
||||||
|
"storybook-addon-material-ui": "^0.9.0-alpha.18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,6 @@ import { optionType, gistDefaults } from "../utils";
|
||||||
import { patternInfo, patternList } from "@freesewing/patterns";
|
import { patternInfo, patternList } from "@freesewing/patterns";
|
||||||
import { FormattedMessage, injectIntl } from "react-intl";
|
import { FormattedMessage, injectIntl } from "react-intl";
|
||||||
import { i18n as languages } from "@freesewing/i18n";
|
import { i18n as languages } from "@freesewing/i18n";
|
||||||
import List from "@material-ui/core/List";
|
|
||||||
import ListSubheader from "@material-ui/core/ListSubheader";
|
|
||||||
import CollapsedIcon from "@material-ui/icons/ArrowDropDown";
|
import CollapsedIcon from "@material-ui/icons/ArrowDropDown";
|
||||||
import ExpandedIcon from "@material-ui/icons/ArrowRight";
|
import ExpandedIcon from "@material-ui/icons/ArrowRight";
|
||||||
import PatternOptions from "../PatternOptions";
|
import PatternOptions from "../PatternOptions";
|
||||||
|
@ -37,8 +35,8 @@ const GistConfigurator = props => {
|
||||||
let dflts = gistDefaults(pattern.config, props.gist);
|
let dflts = gistDefaults(pattern.config, props.gist);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="gist-config">
|
<ul className="nav l1">
|
||||||
<div className="gist-options">
|
<li>
|
||||||
<h2>
|
<h2>
|
||||||
<FormattedMessage id="app.patternOptions" />
|
<FormattedMessage id="app.patternOptions" />
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -48,6 +46,8 @@ const GistConfigurator = props => {
|
||||||
updateValue={update}
|
updateValue={update}
|
||||||
triggerAction={props.triggerAction}
|
triggerAction={props.triggerAction}
|
||||||
/>
|
/>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
<h2>
|
<h2>
|
||||||
<FormattedMessage id="app.draftSettings" />
|
<FormattedMessage id="app.draftSettings" />
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -59,8 +59,8 @@ const GistConfigurator = props => {
|
||||||
language={props.intl.locale}
|
language={props.intl.locale}
|
||||||
languages={languages[props.intl.locale]}
|
languages={languages[props.intl.locale]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</li>
|
||||||
</div>
|
</ul>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,6 @@ import Count from "../PatternOptionCount";
|
||||||
import { optionType } from "../utils";
|
import { optionType } from "../utils";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { injectIntl } from "react-intl";
|
import { injectIntl } from "react-intl";
|
||||||
import ListItem from "@material-ui/core/ListItem";
|
|
||||||
import ListItemText from "@material-ui/core/ListItemText";
|
|
||||||
|
|
||||||
const OptionGroup = props => {
|
const OptionGroup = props => {
|
||||||
const update = (name, value) => props.updateValue("option", name, value);
|
const update = (name, value) => props.updateValue("option", name, value);
|
||||||
|
@ -60,7 +58,7 @@ const OptionGroup = props => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="optiongroup">
|
<React.Fragment>
|
||||||
{props.options.map(name => {
|
{props.options.map(name => {
|
||||||
let key = name;
|
let key = name;
|
||||||
let output = [];
|
let output = [];
|
||||||
|
@ -78,13 +76,9 @@ const OptionGroup = props => {
|
||||||
}
|
}
|
||||||
} else output.push(renderOption(name));
|
} else output.push(renderOption(name));
|
||||||
|
|
||||||
return (
|
return output;
|
||||||
<ListItem key={`lki-${key}`}>
|
|
||||||
<ListItemText>{output}</ListItemText>
|
|
||||||
</ListItem>
|
|
||||||
);
|
|
||||||
})}
|
})}
|
||||||
</div>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
40
packages/components/src/OptionGroup/stories.js
Normal file
40
packages/components/src/OptionGroup/stories.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import React from "react";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import OptionGroup from ".";
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
armholeDrop: { pct: 10, min: 1, max: 75 },
|
||||||
|
backlineBend: { pct: 50, min: 50, max: 100 },
|
||||||
|
chestEase: { pct: 8, min: 0, max: 20 },
|
||||||
|
hipsEase: { pct: 8, min: 0, max: 20 },
|
||||||
|
lengthBonus: { pct: 10, min: -20, max: 60 },
|
||||||
|
necklineBend: { pct: 100, min: 40, max: 100 },
|
||||||
|
necklineDrop: { pct: 20, min: 10, max: 35 },
|
||||||
|
stretchFactor: { pct: 5, min: 0, max: 15 },
|
||||||
|
shoulderStrapWidth: { pct: 15, min: 10, max: 40 },
|
||||||
|
shoulderStrapPlacement: { pct: 40, min: 20, max: 80 }
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
triggerAction: (type, data) =>
|
||||||
|
console.log(`Action of type ${type} triggered, data passed is`, data),
|
||||||
|
updateValue: (type, data) =>
|
||||||
|
console.log(`Update ${type} with new value`, data),
|
||||||
|
gist: {
|
||||||
|
settings: {
|
||||||
|
options: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pattern: {
|
||||||
|
config: {
|
||||||
|
name: "aaron",
|
||||||
|
options: options
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dflts: { options: {} },
|
||||||
|
options: Object.keys(options)
|
||||||
|
};
|
||||||
|
|
||||||
|
storiesOf("OptionGroup", module).add("Simon metric", () => (
|
||||||
|
<OptionGroup pattern="simon" {...props} units="metric" />
|
||||||
|
));
|
|
@ -4,6 +4,7 @@ import IconButton from "@material-ui/core/IconButton";
|
||||||
import ResetIcon from "@material-ui/icons/SettingsBackupRestore";
|
import ResetIcon from "@material-ui/icons/SettingsBackupRestore";
|
||||||
import HelpIcon from "@material-ui/icons/Help";
|
import HelpIcon from "@material-ui/icons/Help";
|
||||||
import { injectIntl } from "react-intl";
|
import { injectIntl } from "react-intl";
|
||||||
|
import ListSubheader from "@material-ui/core/ListSubheader";
|
||||||
|
|
||||||
const OptionPreamble = props => {
|
const OptionPreamble = props => {
|
||||||
const styles = {
|
const styles = {
|
||||||
|
@ -31,7 +32,7 @@ const OptionPreamble = props => {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div style={styles.container}>
|
<div style={styles.container}>
|
||||||
<div style={styles.left}>
|
<div style={styles.left} onClick={props.toggleExpanded}>
|
||||||
<h4 id={props.id}>{props.title}</h4>
|
<h4 id={props.id}>{props.title}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.right}>
|
<div style={styles.right}>
|
||||||
|
@ -40,7 +41,10 @@ const OptionPreamble = props => {
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.container}>
|
<div
|
||||||
|
style={styles.container}
|
||||||
|
className={expanded ? "expanded" : "collapsed"}
|
||||||
|
>
|
||||||
<div style={styles.left}>
|
<div style={styles.left}>
|
||||||
<p>{props.desc}</p>
|
<p>{props.desc}</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,7 +84,8 @@ OptionPreamble.propTypes = {
|
||||||
title: PropTypes.node.isRequired,
|
title: PropTypes.node.isRequired,
|
||||||
desc: PropTypes.node.isRequired,
|
desc: PropTypes.node.isRequired,
|
||||||
reset: PropTypes.func.isRequired,
|
reset: PropTypes.func.isRequired,
|
||||||
showHelp: PropTypes.func.isRequired
|
showHelp: PropTypes.func.isRequired,
|
||||||
|
expanded: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
export default injectIntl(OptionPreamble);
|
export default injectIntl(OptionPreamble);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import OptionPreamble from "../OptionPreamble";
|
||||||
const PatternOptionPctDegCount = props => {
|
const PatternOptionPctDegCount = props => {
|
||||||
const [value, setValue] = useState(props.dflt);
|
const [value, setValue] = useState(props.dflt);
|
||||||
const [previousValue, setPreviousValue] = useState(props.dflt);
|
const [previousValue, setPreviousValue] = useState(props.dflt);
|
||||||
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
|
||||||
const round = val => Math.round(val * 10) / 10;
|
const round = val => Math.round(val * 10) / 10;
|
||||||
|
|
||||||
|
@ -28,6 +29,8 @@ const PatternOptionPctDegCount = props => {
|
||||||
props.updateValue(props.name, props.dflt);
|
props.updateValue(props.name, props.dflt);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleExpanded = () => setExpanded(!expanded);
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
container: {
|
container: {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
@ -45,7 +48,7 @@ const PatternOptionPctDegCount = props => {
|
||||||
if (props.type === "deg") unit = "°";
|
if (props.type === "deg") unit = "°";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"pattern-option " + props.type}>
|
<li>
|
||||||
<OptionPreamble
|
<OptionPreamble
|
||||||
dflt={props.dflt}
|
dflt={props.dflt}
|
||||||
value={value}
|
value={value}
|
||||||
|
@ -54,6 +57,8 @@ const PatternOptionPctDegCount = props => {
|
||||||
id={"po-" + props.type + "-" + props.name}
|
id={"po-" + props.type + "-" + props.name}
|
||||||
displayValue={value + unit}
|
displayValue={value + unit}
|
||||||
reset={reset}
|
reset={reset}
|
||||||
|
toggleExpanded={toggleExpanded}
|
||||||
|
expanded={expanded}
|
||||||
showHelp={() =>
|
showHelp={() =>
|
||||||
props.triggerAction("showHelp", {
|
props.triggerAction("showHelp", {
|
||||||
type: "patternOption",
|
type: "patternOption",
|
||||||
|
@ -61,17 +66,19 @@ const PatternOptionPctDegCount = props => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<FormFieldSlider
|
{!expanded ? null : (
|
||||||
name={props.name}
|
<FormFieldSlider
|
||||||
value={value}
|
name={props.name}
|
||||||
min={props.min}
|
value={value}
|
||||||
max={props.max}
|
min={props.min}
|
||||||
step={props.type === "count" ? 1 : props.step}
|
max={props.max}
|
||||||
onChange={update}
|
step={props.type === "count" ? 1 : props.step}
|
||||||
label={"po-" + props.type + "-" + props.name}
|
onChange={update}
|
||||||
updateValue={update}
|
label={"po-" + props.type + "-" + props.name}
|
||||||
/>
|
updateValue={update}
|
||||||
</div>
|
/>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,44 +27,46 @@ const PatternOptions = props => {
|
||||||
let pattern = patternInfo[props.pattern];
|
let pattern = patternInfo[props.pattern];
|
||||||
let dflts = gistDefaults(pattern.config, props.gist);
|
let dflts = gistDefaults(pattern.config, props.gist);
|
||||||
|
|
||||||
|
const renderGroup = group => {
|
||||||
|
let open = true;
|
||||||
|
if (expanded.indexOf(group) === -1) open = false;
|
||||||
|
let output = [];
|
||||||
|
let children = null;
|
||||||
|
if (expanded.indexOf(group) !== -1)
|
||||||
|
children = (
|
||||||
|
<ul className="nav l3">
|
||||||
|
<OptionGroup
|
||||||
|
key={group + "-group"}
|
||||||
|
units={props.units}
|
||||||
|
pattern={pattern}
|
||||||
|
dflts={dflts}
|
||||||
|
options={pattern.optionGroups[group]}
|
||||||
|
updateValue={props.updateValue}
|
||||||
|
triggerAction={props.triggerAction}
|
||||||
|
/>
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
output.push(
|
||||||
|
<li className={open ? "expanded" : "collapsed"} key={group + "-ghead"}>
|
||||||
|
<h3 onClick={() => toggleGroup(group)}>
|
||||||
|
{open ? (
|
||||||
|
<CollapsedIcon className="collapse-icon" />
|
||||||
|
) : (
|
||||||
|
<ExpandedIcon className="collapse-icon" />
|
||||||
|
)}
|
||||||
|
<FormattedMessage id={"optiongroups." + group} />
|
||||||
|
</h3>
|
||||||
|
{children}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List subheader={<h3 />} className="pattern-options gist-side">
|
<ul className="nav l2">
|
||||||
{Object.keys(pattern.optionGroups).map(group => {
|
{Object.keys(pattern.optionGroups).map(group => renderGroup(group))}
|
||||||
let open = true;
|
</ul>
|
||||||
if (expanded.indexOf(group) === -1) open = false;
|
|
||||||
return (
|
|
||||||
<React.Fragment key={group + "-ghead"}>
|
|
||||||
<ListSubheader
|
|
||||||
className="optiongroup-heading"
|
|
||||||
className={
|
|
||||||
(open ? "expanded" : "collapsed") + " optiongroup-heading"
|
|
||||||
}
|
|
||||||
onClick={() => toggleGroup(group)}
|
|
||||||
>
|
|
||||||
<h3>
|
|
||||||
{open ? (
|
|
||||||
<CollapsedIcon className="collapse-icon" />
|
|
||||||
) : (
|
|
||||||
<ExpandedIcon className="collapse-icon" />
|
|
||||||
)}
|
|
||||||
<FormattedMessage id={"optiongroups." + group} />
|
|
||||||
</h3>
|
|
||||||
</ListSubheader>
|
|
||||||
{expanded.indexOf(group) === -1 ? null : (
|
|
||||||
<OptionGroup
|
|
||||||
key={group + "-group"}
|
|
||||||
units={props.units}
|
|
||||||
pattern={pattern}
|
|
||||||
dflts={dflts}
|
|
||||||
options={pattern.optionGroups[group]}
|
|
||||||
updateValue={props.updateValue}
|
|
||||||
triggerAction={props.triggerAction}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</List>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
13
packages/css-theme/package-lock.json
generated
Normal file
13
packages/css-theme/package-lock.json
generated
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"name": "@freesewing/css-theme",
|
||||||
|
"version": "0.33.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"open-color": {
|
||||||
|
"version": "1.6.3",
|
||||||
|
"resolved": "http://ep-foundry.ep.parl.union.eu/npm/repository/ep-registry/open-color/-/open-color-1.6.3.tgz",
|
||||||
|
"integrity": "sha512-UAnb19odLDupaVDSioSHZZlWEkJvKHDE7CxB3Zg1vS0FpHAc72AkzfH0wCSwYK5TKg6bjtmFSfmQF9FcjQANZA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,49 @@
|
||||||
li.optiongroup-heading {
|
ul.nav.l1,
|
||||||
|
ul.nav.l2,
|
||||||
|
ul.nav.l3 {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
padding: 0;
|
||||||
|
@include title-font;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.nav li {list-style-type: none;}
|
||||||
|
|
||||||
|
ul.nav h2,
|
||||||
|
ul.nav h3,
|
||||||
|
ul.nav h4 {
|
||||||
|
font-weight: normal;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
ul.nav h2:hover,
|
||||||
|
ul.nav h3:hover,
|
||||||
|
ul.nav h4:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background: $fc-hoverbg-light;
|
||||||
|
}
|
||||||
|
ul.nav h2 { font-size: 1.2rem; }
|
||||||
|
ul.nav h3 { font-size: 1.1rem; }
|
||||||
|
ul.nav h4 { font-size: 1rem; }
|
||||||
|
|
||||||
|
li.zdsfsdfptiongroup-heading,
|
||||||
|
li.option-headdsg {
|
||||||
background: $fc-bg-light;
|
background: $fc-bg-light;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
h3 {
|
h3, h4 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
svg.collapse-icon { margin-bottom: -5px;}
|
svg.collapse-icon { margin-bottom: -5px;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
li.optiongroup-heading:hover {
|
li.optiongroup-heafsding:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: $fc-hoverbg-light;
|
background: $fc-hoverbg-light;
|
||||||
}
|
}
|
||||||
body.dark {
|
body.dark {
|
||||||
li.optiongroup-heading {
|
li.optisdfsdongroup-heading {
|
||||||
background: $fc-bg-dark;
|
background: $fc-bg-dark;
|
||||||
}
|
}
|
||||||
li.optiongroup-heading:hover {
|
li.optiongrsdfsdoup-heading:hover {
|
||||||
background: $fc-hoverbg-dark;
|
background: $fc-hoverbg-dark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue