1
0
Fork 0

🚧 More work on React components

This commit is contained in:
Joost De Cock 2019-04-26 08:25:15 +02:00
parent e2b5ba2ee7
commit 3d9192a5ae
12 changed files with 178 additions and 132 deletions

View file

@ -5,7 +5,7 @@ import { patternInfo, patternList } from "@freesewing/patterns";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import List from "@material-ui/core/List"; import List from "@material-ui/core/List";
import ListSubheader from "@material-ui/core/ListSubheader"; import ListSubheader from "@material-ui/core/ListSubheader";
import CollapsedIcon from "@material-ui/icons/ArrowDropDown"; import CollapsedIcon from "@material-ui/icons/KeyboardArrowDown";
import ExpandedIcon from "@material-ui/icons/ArrowRight"; import ExpandedIcon from "@material-ui/icons/ArrowRight";
import DraftSettingSa from "../DraftSettingSa"; import DraftSettingSa from "../DraftSettingSa";
import DraftSettingMargin from "../DraftSettingMargin"; import DraftSettingMargin from "../DraftSettingMargin";
@ -100,7 +100,7 @@ const DraftSettings = props => {
}; };
return ( return (
<List subheader={<h3 />} className="draft-settings gist-side"> <ul className="nav l2">
{Object.keys(groups).map(group => { {Object.keys(groups).map(group => {
let open = true; let open = true;
if (expanded.indexOf(group) === -1) open = false; if (expanded.indexOf(group) === -1) open = false;
@ -128,7 +128,7 @@ const DraftSettings = props => {
</React.Fragment> </React.Fragment>
); );
})} })}
</List> </ul>
); );
}; };

View file

@ -6,7 +6,7 @@ import { withStyles } from "@material-ui/core/styles";
const PaddedSlider = withStyles({ const PaddedSlider = withStyles({
container: { container: {
padding: "25px 0", padding: "25px 0",
overflowX: "hidden" // See: https://github.com/mui-org/material-ui/issues/14234 //overflowX: "hidden" // See: https://github.com/mui-org/material-ui/issues/14234
}, },
track: { height: "4px" }, track: { height: "4px" },
thumb: { width: "16px", height: "16px" } thumb: { width: "16px", height: "16px" }

View file

@ -13,7 +13,7 @@ import { injectIntl } from "react-intl";
const OptionGroup = props => { const OptionGroup = props => {
const update = (name, value) => props.updateValue("option", name, value); const update = (name, value) => props.updateValue("option", name, value);
const renderOption = name => { const renderOption = (name, sub=false) => {
let option = props.pattern.config.options[name]; let option = props.pattern.config.options[name];
let type = optionType(option); let type = optionType(option);
let stringKey = `options.${props.pattern.config.name}.${name}.`; let stringKey = `options.${props.pattern.config.name}.${name}.`;
@ -67,12 +67,14 @@ const OptionGroup = props => {
// Subgroup // Subgroup
for (let subGroup of Object.keys(name)) { for (let subGroup of Object.keys(name)) {
output.push( output.push(
<h4 key={subGroup + "-title"}> <h5 key={subGroup + "-title"} className="subheading">
<FormattedMessage id={"optiongroups." + subGroup} /> <FormattedMessage id={"optiongroups." + subGroup} />
</h4> </h5>
); );
let children = [];
for (let option of name[subGroup]) for (let option of name[subGroup])
output.push(renderOption(option)); children.push(renderOption(option, true));
output.push(<ul className="nav l4">{children}</ul>);
} }
} else output.push(renderOption(name)); } else output.push(renderOption(name));

View file

@ -1,6 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import IconButton from "@material-ui/core/IconButton"; import IconButton from "@material-ui/core/IconButton";
import DownIcon from "@material-ui/icons/KeyboardArrowDown";
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";
@ -17,7 +18,10 @@ const OptionPreamble = props => {
flexGrow: 1, flexGrow: 1,
margin: "0 0.5rem" margin: "0 0.5rem"
}, },
right: { margin: "0 0.5rem" } right: {
margin: 0,
textAlign: "right"
}
}; };
const resetLabel = props.intl.formatMessage({ const resetLabel = props.intl.formatMessage({
@ -31,42 +35,45 @@ const OptionPreamble = props => {
return ( return (
<React.Fragment> <React.Fragment>
<div style={styles.container}> <h4 onClick={props.toggleExpanded} style={styles.container}>
<div style={styles.left} onClick={props.toggleExpanded}>
<h4 id={props.id}>{props.title}</h4>
</div>
<div style={styles.right}>
<h4 className={props.value === props.dflt ? "po-dflt" : "po-custom"}>
{props.displayValue}
</h4>
</div>
</div>
<div
style={styles.container}
className={expanded ? "expanded" : "collapsed"}
>
<div style={styles.left}> <div style={styles.left}>
<p>{props.desc}</p> <DownIcon className={"icon-col-exp "+ (props.expanded ? "expanded" : "collapsed")}/>
</div> {props.title}
</div>
<div style={styles.right}> <div style={styles.right}>
<IconButton <span className={props.value === props.dflt ? "dflt" : "custom"}>
title={resetLabel} {props.displayValue}
aria-label={resetLabel} </span>
color="primary"
disabled={props.value === props.dflt ? true : false}
onClick={props.reset}
>
<ResetIcon />
</IconButton>
<IconButton
title={docsLabel}
aria-label={docsLabel}
color="primary"
onClick={props.showHelp}
>
<HelpIcon />
</IconButton>
</div> </div>
</h4>
<div className={props.expanded ? "col-exp expanded" : "col-exp collapsed"}>
<div style={styles.container}>
<div style={styles.left}>
<p>{props.desc}</p>
</div>
<div style={styles.right}>
<IconButton
title={resetLabel}
aria-label={resetLabel}
color="primary"
disabled={props.value === props.dflt ? true : false}
onClick={props.reset}
className="mini-icon-btn"
>
<ResetIcon />
</IconButton>
<IconButton
title={docsLabel}
aria-label={docsLabel}
color="primary"
onClick={props.showHelp}
className="mini-icon-btn"
>
<HelpIcon />
</IconButton>
</div>
</div>
{props.option}
</div> </div>
</React.Fragment> </React.Fragment>
); );

View file

@ -5,6 +5,7 @@ import OptionPreamble from "../OptionPreamble";
const PatternOptionBool = props => { const PatternOptionBool = props => {
const [value, setValue] = useState(props.dflt); const [value, setValue] = useState(props.dflt);
const [expanded, setExpanded] = useState(false);
const update = (name, newValue, evt) => { const update = (name, newValue, evt) => {
props.updateValue(props.name, newValue); props.updateValue(props.name, newValue);
@ -16,8 +17,21 @@ const PatternOptionBool = props => {
props.updateValue(props.name, props.dflt); props.updateValue(props.name, props.dflt);
}; };
const toggleExpanded = () => setExpanded(!expanded);
let option = (
<FormFieldBool
name={props.name}
value={value}
dflt={props.dflt}
onChange={update}
label={"po-bool-" + props.name}
updateValue={update}
labels={props.labels}
/>
)
return ( return (
<div className={"pattern-option bool"}> <li>
<OptionPreamble <OptionPreamble
dflt={props.dflt} dflt={props.dflt}
value={value} value={value}
@ -25,6 +39,8 @@ const PatternOptionBool = props => {
title={props.title} title={props.title}
id={"po-list-" + props.name} id={"po-list-" + props.name}
displayValue={value ? props.labels[1] : props.labels[0]} displayValue={value ? props.labels[1] : props.labels[0]}
toggleExpanded={toggleExpanded}
expanded={expanded}
reset={reset} reset={reset}
showHelp={() => showHelp={() =>
props.triggerAction("showHelp", { props.triggerAction("showHelp", {
@ -32,17 +48,9 @@ const PatternOptionBool = props => {
value: props.name value: props.name
}) })
} }
option={option}
/> />
<FormFieldBool </li>
name={props.name}
value={value}
dflt={props.dflt}
onChange={update}
label={"po-bool-" + props.name}
updateValue={update}
labels={props.labels}
/>
</div>
); );
}; };

View file

@ -5,6 +5,7 @@ import OptionPreamble from "../OptionPreamble";
const PatternOptionList = props => { const PatternOptionList = props => {
const [value, setValue] = useState(props.dflt); const [value, setValue] = useState(props.dflt);
const [expanded, setExpanded] = useState(false);
const update = (name, newValue, evt) => { const update = (name, newValue, evt) => {
props.updateValue(props.name, newValue); props.updateValue(props.name, newValue);
@ -16,6 +17,8 @@ const PatternOptionList = 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",
@ -37,9 +40,19 @@ const PatternOptionList = props => {
id: stringKey + item, id: stringKey + item,
defaultMessage: item defaultMessage: item
}); });
let option = (
<FormFieldList
name={props.name}
value={value}
dflt={props.dflt}
onChange={update}
label={"po-list-" + props.name}
updateValue={update}
list={list}
/>
)
return ( return (
<div className={"pattern-option list"}> <li>
<OptionPreamble <OptionPreamble
dflt={props.dflt} dflt={props.dflt}
value={value} value={value}
@ -48,23 +61,17 @@ const PatternOptionList = props => {
id={"po-list-" + props.name} id={"po-list-" + props.name}
displayValue={list[value]} displayValue={list[value]}
reset={reset} reset={reset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() => showHelp={() =>
props.triggerAction("showHelp", { props.triggerAction("showHelp", {
type: "patternOption", type: "patternOption",
value: props.name value: props.name
}) })
} }
option={option}
/> />
<FormFieldList </li>
name={props.name}
value={value}
dflt={props.dflt}
onChange={update}
label={"po-list-" + props.name}
updateValue={update}
list={list}
/>
</div>
); );
}; };

View file

@ -13,6 +13,7 @@ import OptionPreamble from "../OptionPreamble";
const PatternOptionMillimeter = props => { const PatternOptionMillimeter = 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 update = (name, newValue, evt) => { const update = (name, newValue, evt) => {
newValue = roundMm(newValue, props.units); newValue = roundMm(newValue, props.units);
@ -33,6 +34,8 @@ const PatternOptionMillimeter = 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",
@ -46,8 +49,21 @@ const PatternOptionMillimeter = props => {
right: { margin: "0 0.5rem" } right: { margin: "0 0.5rem" }
}; };
let option = (
<FormFieldSlider
name={props.name}
value={value}
min={roundMmUp(props.min, props.units)}
max={roundMmDown(props.max, props.units)}
step={sliderStep[props.units]}
onChange={update}
label={"po-mm-" + props.name}
updateValue={update}
/>
)
return ( return (
<div className="pattern-option millimeter"> <li>
<OptionPreamble <OptionPreamble
dflt={props.dflt} dflt={props.dflt}
value={value} value={value}
@ -56,24 +72,17 @@ const PatternOptionMillimeter = props => {
id={"po-mm-" + props.name} id={"po-mm-" + props.name}
displayValue={formatMm(value, props.units)} displayValue={formatMm(value, props.units)}
reset={reset} reset={reset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() => showHelp={() =>
props.triggerAction("showHelp", { props.triggerAction("showHelp", {
type: "patternOption", type: "patternOption",
value: props.name value: props.name
}) })
} }
option={option}
/> />
<FormFieldSlider </li>
name={props.name}
value={value}
min={roundMmUp(props.min, props.units)}
max={roundMmDown(props.max, props.units)}
step={sliderStep[props.units]}
onChange={update}
label={"po-mm-" + props.name}
updateValue={update}
/>
</div>
); );
}; };

View file

@ -31,22 +31,22 @@ const PatternOptionPctDegCount = props => {
const toggleExpanded = () => setExpanded(!expanded); const toggleExpanded = () => setExpanded(!expanded);
const styles = {
container: {
display: "flex",
flexDirection: "row",
alignItems: "center"
},
left: {
flexGrow: 1,
margin: "0 0.5rem"
},
right: { margin: "0 0.5rem" }
};
let unit = ""; let unit = "";
if (props.type === "pct") unit = "%"; if (props.type === "pct") unit = "%";
if (props.type === "deg") unit = "°"; if (props.type === "deg") unit = "°";
let option = (
<FormFieldSlider
name={props.name}
value={value}
min={props.min}
max={props.max}
step={props.type === "count" ? 1 : props.step}
onChange={update}
label={"po-" + props.type + "-" + props.name}
updateValue={update}
/>)
return ( return (
<li> <li>
<OptionPreamble <OptionPreamble
@ -65,19 +65,8 @@ const PatternOptionPctDegCount = props => {
value: props.name value: props.name
}) })
} }
option={option}
/> />
{!expanded ? null : (
<FormFieldSlider
name={props.name}
value={value}
min={props.min}
max={props.max}
step={props.type === "count" ? 1 : props.step}
onChange={update}
label={"po-" + props.type + "-" + props.name}
updateValue={update}
/>
)}
</li> </li>
); );
}; };

View file

@ -10,8 +10,7 @@ import { patternInfo, patternList } from "@freesewing/patterns";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import List from "@material-ui/core/List"; import List from "@material-ui/core/List";
import ListSubheader from "@material-ui/core/ListSubheader"; import ListSubheader from "@material-ui/core/ListSubheader";
import CollapsedIcon from "@material-ui/icons/ArrowDropDown"; import DownIcon from "@material-ui/icons/KeyboardArrowDown";
import ExpandedIcon from "@material-ui/icons/ArrowRight";
const PatternOptions = props => { const PatternOptions = props => {
const [expanded, setExpanded] = useState([]); const [expanded, setExpanded] = useState([]);
@ -49,11 +48,7 @@ const PatternOptions = props => {
output.push( output.push(
<li className={open ? "expanded" : "collapsed"} key={group + "-ghead"}> <li className={open ? "expanded" : "collapsed"} key={group + "-ghead"}>
<h3 onClick={() => toggleGroup(group)}> <h3 onClick={() => toggleGroup(group)}>
{open ? ( <DownIcon className={"icon-col-exp "+ (open ? "expanded" : "collapsed")}/>
<CollapsedIcon className="collapse-icon" />
) : (
<ExpandedIcon className="collapse-icon" />
)}
<FormattedMessage id={"optiongroups." + group} /> <FormattedMessage id={"optiongroups." + group} />
</h3> </h3>
{children} {children}

View file

@ -22,6 +22,7 @@
"clean": "rimraf ../../dist/css-theme", "clean": "rimraf ../../dist/css-theme",
"nodebuild": "BABEL_ENV=production rollup -c -o ../../dist/css-theme/index.js -f cjs", "nodebuild": "BABEL_ENV=production rollup -c -o ../../dist/css-theme/index.js -f cjs",
"modulebuild": "BABEL_ENV=production rollup -c -o ../../dist/css-theme/index.mjs -f es", "modulebuild": "BABEL_ENV=production rollup -c -o ../../dist/css-theme/index.mjs -f es",
"watch": "npx node-sass --watch --output-style compressed src/theme.scss ../../dist/css-theme/theme.css",
"build": "npx node-sass --output-style compressed src/theme.scss ../../dist/css-theme/theme.css", "build": "npx node-sass --output-style compressed src/theme.scss ../../dist/css-theme/theme.css",
"test": "echo \"css-theme: No tests configured. Perhaps you'd like to do this?\" && exit 0", "test": "echo \"css-theme: 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"

View file

@ -1,6 +1,6 @@
$fc-bg-light: $oc-gray-0; $fc-bg-light: $oc-gray-0;
$fc-bg-dark: $oc-gray-9; $fc-bg-dark: $oc-gray-9;
$fc-notice-light: $oc-lime-9; $fc-notice-light: $oc-yellow-7;
$fc-notice-dark: $oc-lime-3; $fc-notice-dark: $oc-lime-3;
$fc-hoverbg-light: $oc-gray-1; $fc-hoverbg-light: $oc-gray-1;
$fc-hoverbg-dark: $oc-gray-8; $fc-hoverbg-dark: $oc-gray-8;

View file

@ -1,49 +1,77 @@
ul.nav.l1 { overflow-x: hidden;}
ul.nav.l1, ul.nav.l1,
ul.nav.l2, ul.nav.l2,
ul.nav.l3 { ul.nav.l3,
margin-left: 0.5rem; ul.nav.l4 {
margin: 0;
padding: 0; padding: 0;
@include title-font; @include title-font;
} }
ul.nav li {list-style-type: none;} ul.nav li {list-style-type: none;}
ul.nav p { @include body-font;}
ul.nav.l4 li { padding-left: 0.75rem; }
ul.nav h2, ul.nav h2,
ul.nav h3, ul.nav h3,
ul.nav h4 { ul.nav h4,
ul.nav h5 {
font-weight: normal; font-weight: normal;
display: block; display: block;
margin: 0; margin: 0;
padding: 0.5rem; padding: 0.5rem 0.25rem;
} }
ul.nav h2:hover,
ul.nav h3:hover, ul.nav h3:hover,
ul.nav h4:hover { ul.nav h4:hover {
cursor: pointer; cursor: pointer;
background: $fc-hoverbg-light; background: $fc-hoverbg-light;
} }
ul.nav h2 { font-size: 1.2rem; } ul.nav h2 { font-size: 1.2rem; }
ul.nav h3 { font-size: 1.1rem; }
ul.nav h4 { font-size: 1rem; } ul.nav h4 { font-size: 1rem; }
ul.nav h5 { font-size: 1rem; padding-left: 1.5rem; font-weight: bold;}
li.zdsfsdfptiongroup-heading, ul.nav h3 {
li.option-headdsg { font-size: 1.1rem;
position: sticky;
top: 0;
background: $fc-bg-light; background: $fc-bg-light;
z-index: 3; z-index: 3;
h3, h4 {
margin: 0;
svg.collapse-icon { margin-bottom: -5px;}
}
} }
li.optiongroup-heafsding:hover { ul.nav span.custom {
cursor: pointer; color: $fc-notice-light;
background: $fc-hoverbg-light; font-weight: bold;
} }
.col-exp {
transition: max-height 0.3s ease-in-out, opacity 0.2s ease 0.2s;
}
.col-exp.expanded {
margin-top: 0;
opacity: 1;
}
.col-exp.collapsed {
opacity: 0;
max-height: 0;
overflow-y: hidden;
}
svg.icon-col-exp {
margin-bottom: -5px;
margin-right: 5px;
transition: transform 0.3s ease-in-out, opacity 0.2s ease-in-out;
opacity: 0.4;
}
svg.icon-col-exp.expanded {
transform: scale(-1);
opacity: 1;
}
ul.nav.l3 div.col-exp {
margin: 0 27px;
}
button.mini-icon-btn {
margin: 0;
padding: 2px;
}
body.dark { body.dark {
li.optisdfsdongroup-heading {
background: $fc-bg-dark;
}
li.optiongrsdfsdoup-heading:hover {
background: $fc-hoverbg-dark;
}
} }