🚧 Progress on React components
This commit is contained in:
parent
ea87274eb2
commit
d8cc1f76f3
59 changed files with 341 additions and 260 deletions
|
@ -1,89 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { gistDefaults } from "../utils";
|
||||
import { patternInfo, patternList } from "@freesewing/patterns";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import List from "@material-ui/core/List";
|
||||
import DraftSettingSa from "../DraftSettingSa";
|
||||
import DraftSettingMargin from "../DraftSettingMargin";
|
||||
import DraftSettingComplete from "../DraftSettingComplete";
|
||||
import DraftSettingPaperless from "../DraftSettingPaperless";
|
||||
import DraftSettingUnits from "../DraftSettingUnits";
|
||||
import DraftSettingLanguage from "../DraftSettingLanguage";
|
||||
import DraftSettingOnly from "../DraftSettingOnly";
|
||||
import DownIcon from "@material-ui/icons/KeyboardArrowDown";
|
||||
|
||||
const DraftActions = props => {
|
||||
const [expanded, setExpanded] = useState([]);
|
||||
|
||||
const toggleGroup = group => {
|
||||
let shown = expanded.slice(0);
|
||||
let index = shown.indexOf(group);
|
||||
if (index === -1) shown.push(group);
|
||||
else shown.splice(index, 1);
|
||||
setExpanded(shown);
|
||||
};
|
||||
|
||||
let paperSizes = ["A4", "Letter", "A3", "Tabloid", "A2", "A1", "A0"];
|
||||
let groups = {
|
||||
saveDraft: [
|
||||
<li>
|
||||
<FormattedMessage id="app.saveDraftToYourAccount" />
|
||||
</li>,
|
||||
<li>
|
||||
<FormattedMessage id="app.saveGistAsJSON" />
|
||||
</li>,
|
||||
<li>
|
||||
<FormattedMessage id="app.saveGistAsYAML" />
|
||||
</li>,
|
||||
<li>
|
||||
<FormattedMessage id="app.saveSvg" />
|
||||
</li>
|
||||
],
|
||||
exportDraft: [
|
||||
<li>
|
||||
<FormattedMessage id="app.exportDraft" />: PDF
|
||||
</li>,
|
||||
paperSizes.map(size => (
|
||||
<li>
|
||||
<FormattedMessage id="app.exportTiledPdf" />: {size}
|
||||
</li>
|
||||
))
|
||||
]
|
||||
};
|
||||
|
||||
return (
|
||||
<ul className="nav l2">
|
||||
{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);
|
||||
return (
|
||||
<React.Fragment>
|
||||
<li
|
||||
className={open ? "expanded" : "collapsed"}
|
||||
key={group + "-ghead"}
|
||||
>
|
||||
<h3 onClick={() => toggleGroup(group)}>
|
||||
<DownIcon
|
||||
className={
|
||||
"icon-col-exp " + (open ? "expanded" : "collapsed")
|
||||
}
|
||||
/>
|
||||
<FormattedMessage id={"app." + group} />
|
||||
</h3>
|
||||
</li>
|
||||
{children}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
DraftActions.propTypes = {};
|
||||
|
||||
DraftActions.defaultProps = {};
|
||||
|
||||
export default DraftActions;
|
|
@ -14,6 +14,6 @@ const props = {
|
|||
labels: ["No", "Yes"]
|
||||
};
|
||||
|
||||
storiesOf("DraftSettingComplete", module).add("Basic", () => (
|
||||
storiesOf("Low level/DraftSettingComplete", module).add("Basic", () => (
|
||||
<Complete {...props} />
|
||||
));
|
|
@ -1,10 +1,12 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import FormFieldList from "../FormFieldList";
|
||||
import FormFieldList from "../../form/FormFieldList";
|
||||
import OptionPreamble from "../OptionPreamble";
|
||||
import { injectIntl } from "react-intl";
|
||||
import { i18n as languages } from "@freesewing/i18n";
|
||||
|
||||
const DraftSettingLanguage = props => {
|
||||
const [value, setValue] = useState(props.dflt);
|
||||
const [value, setValue] = useState(props.intl.locale);
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
|
||||
const update = (name, newValue, evt) => {
|
||||
|
@ -13,33 +15,32 @@ const DraftSettingLanguage = props => {
|
|||
};
|
||||
|
||||
const reset = () => {
|
||||
setValue(props.dflt);
|
||||
props.updateValue(props.name, props.dflt);
|
||||
setValue(props.intl.locale);
|
||||
props.updateValue(props.name, props.intl.locale);
|
||||
};
|
||||
|
||||
const toggleExpanded = () => setExpanded(!expanded);
|
||||
|
||||
const option = (
|
||||
<FormFieldList
|
||||
name={props.name}
|
||||
value={value}
|
||||
dflt={props.dflt}
|
||||
dflt={props.intl.locale}
|
||||
onChange={update}
|
||||
label={"po-list-" + props.name}
|
||||
updateValue={update}
|
||||
list={props.languages}
|
||||
list={languages[props.intl.locale]}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<li>
|
||||
<OptionPreamble
|
||||
dflt={props.dflt}
|
||||
dflt={props.intl.locale}
|
||||
value={value}
|
||||
desc={props.desc}
|
||||
title={props.title}
|
||||
id={"po-list-" + props.name}
|
||||
displayValue={props.languages[value]}
|
||||
displayValue={languages[props.intl.locale][value]}
|
||||
reset={reset}
|
||||
toggleExpanded={toggleExpanded}
|
||||
expanded={expanded}
|
||||
|
@ -59,13 +60,9 @@ DraftSettingLanguage.propTypes = {
|
|||
triggerAction: PropTypes.func.isRequired,
|
||||
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.object.isRequired
|
||||
};
|
||||
|
||||
export default DraftSettingLanguage;
|
||||
export default injectIntl(DraftSettingLanguage);
|
|
@ -22,6 +22,6 @@ const props = {
|
|||
}
|
||||
};
|
||||
|
||||
storiesOf("DraftSettingLanguage", module).add("Basic", () => (
|
||||
storiesOf("Low level/DraftSettingLanguage", module).add("Basic", () => (
|
||||
<Lang {...props} />
|
||||
));
|
|
@ -1,12 +1,13 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import FormFieldList from "../FormFieldList";
|
||||
import FormFieldSlider from "../FormFieldSlider";
|
||||
import { formatMm, roundMm, defaultSa, sliderStep } from "../utils";
|
||||
import FormFieldList from "../../form/FormFieldList";
|
||||
import FormFieldSlider from "../../form/FormFieldSlider";
|
||||
import { formatMm, roundMm, defaultSa, sliderStep } from "../../utils";
|
||||
import OptionPreamble from "../OptionPreamble";
|
||||
|
||||
const DraftSettingMargin = props => {
|
||||
const [value, setValue] = useState(props.dflt);
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
|
||||
const update = (name, newValue, evt) => {
|
||||
newValue = roundMm(newValue);
|
||||
|
@ -27,23 +28,9 @@ const DraftSettingMargin = props => {
|
|||
props.updateValue("margin", props.dflt);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={"pattern-option list"}>
|
||||
<OptionPreamble
|
||||
dflt={props.dflt}
|
||||
value={value}
|
||||
desc={props.desc}
|
||||
title={props.title}
|
||||
id="po-slider-margin"
|
||||
displayValue={formatMm(value, props.units)}
|
||||
reset={reset}
|
||||
showHelp={() =>
|
||||
props.triggerAction("showHelp", {
|
||||
type: "draftSetting",
|
||||
value: "margin"
|
||||
})
|
||||
}
|
||||
/>
|
||||
const toggleExpanded = () => setExpanded(!expanded);
|
||||
|
||||
let option = (
|
||||
<FormFieldSlider
|
||||
name="customSa"
|
||||
value={value}
|
||||
|
@ -54,7 +41,29 @@ const DraftSettingMargin = props => {
|
|||
max={25.4}
|
||||
step={sliderStep[props.units]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<li>
|
||||
<OptionPreamble
|
||||
dflt={props.dflt}
|
||||
value={value}
|
||||
desc={props.desc}
|
||||
title={props.title}
|
||||
id="po-slider-margin"
|
||||
displayValue={formatMm(value, props.units)}
|
||||
reset={reset}
|
||||
toggleExpanded={toggleExpanded}
|
||||
expanded={expanded}
|
||||
showHelp={() =>
|
||||
props.triggerAction("showHelp", {
|
||||
type: "draftSetting",
|
||||
value: "margin"
|
||||
})
|
||||
}
|
||||
option={option}
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
|
@ -14,6 +14,6 @@ const props = {
|
|||
"This is the margin description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it."
|
||||
};
|
||||
|
||||
storiesOf("DraftSettingMargin", module)
|
||||
storiesOf("Low level/DraftSettingMargin", module)
|
||||
.add("Metric", () => <Margin {...props} units="metric" />)
|
||||
.add("Imperial", () => <Margin {...props} units="imperial" />);
|
|
@ -1,8 +1,8 @@
|
|||
import React, { useState } from "react";
|
||||
import FormFieldChecks from "../FormFieldChecks";
|
||||
import FormFieldList from "../FormFieldList";
|
||||
import FormFieldSlider from "../FormFieldSlider";
|
||||
import { formatMm, roundMm, defaultSa, sliderStep } from "../utils";
|
||||
import FormFieldChecks from "../../form/FormFieldChecks";
|
||||
import FormFieldList from "../../form/FormFieldList";
|
||||
import FormFieldSlider from "../../form/FormFieldSlider";
|
||||
import { formatMm, roundMm, defaultSa, sliderStep } from "../../utils";
|
||||
import OptionPreamble from "../OptionPreamble";
|
||||
|
||||
const DraftSettingOnly = props => {
|
|
@ -24,7 +24,7 @@ const props = {
|
|||
}
|
||||
};
|
||||
|
||||
storiesOf("DraftSettingOnly", module)
|
||||
storiesOf("Low level/DraftSettingOnly", module)
|
||||
.add("Default", () => <Sa {...props} />)
|
||||
.add("Default, all parts preselected", () => (
|
||||
<Sa {...props} customDflt={Object.keys(props.parts)} />
|
|
@ -15,6 +15,6 @@ const props = {
|
|||
labels: ["No", "Yes"]
|
||||
};
|
||||
|
||||
storiesOf("DraftSettingPaperless", module).add("Basic", () => (
|
||||
storiesOf("Low level/DraftSettingPaperless", module).add("Basic", () => (
|
||||
<Paperless {...props} />
|
||||
));
|
|
@ -1,8 +1,8 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import FormFieldList from "../FormFieldList";
|
||||
import FormFieldSlider from "../FormFieldSlider";
|
||||
import { formatMm, roundMm, defaultSa, sliderStep } from "../utils";
|
||||
import FormFieldList from "../../form/FormFieldList";
|
||||
import FormFieldSlider from "../../form/FormFieldSlider";
|
||||
import { formatMm, roundMm, defaultSa, sliderStep } from "../../utils";
|
||||
import OptionPreamble from "../OptionPreamble";
|
||||
|
||||
const DraftSettingSa = props => {
|
|
@ -19,6 +19,6 @@ const props = {
|
|||
}
|
||||
};
|
||||
|
||||
storiesOf("DraftSettingSa", module)
|
||||
storiesOf("Low level/DraftSettingSa", module)
|
||||
.add("Metric", () => <Sa {...props} units="metric" />)
|
||||
.add("Imperial", () => <Sa {...props} units="imperial" />);
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from "react";
|
||||
import FormFieldList from "../FormFieldList";
|
||||
import FormFieldList from "../../form/FormFieldList";
|
||||
import OptionPreamble from "../OptionPreamble";
|
||||
|
||||
const DraftSettingUnits = props => {
|
|
@ -18,4 +18,4 @@ const props = {
|
|||
}
|
||||
};
|
||||
|
||||
storiesOf("DraftSettingUnits", module).add("Basic", () => <Units {...props} />);
|
||||
storiesOf("Low level/DraftSettingUnits", module).add("Basic", () => <Units {...props} />);
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { gistDefaults } from "../utils";
|
||||
import { gistDefaults } from "../../utils";
|
||||
import { patternInfo, patternList } from "@freesewing/patterns";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import List from "@material-ui/core/List";
|
||||
|
@ -89,11 +89,7 @@ const DraftSettings = props => {
|
|||
dflt={props.units}
|
||||
list={units}
|
||||
/>,
|
||||
<DraftSettingLanguage
|
||||
{...addProps("locale")}
|
||||
dflt={props.language}
|
||||
languages={props.languages}
|
||||
/>
|
||||
<DraftSettingLanguage {...addProps("locale")} />
|
||||
]
|
||||
};
|
||||
|
|
@ -22,7 +22,7 @@ const props = {
|
|||
language: "en"
|
||||
};
|
||||
|
||||
storiesOf("DraftActions", module)
|
||||
storiesOf("Low level/DraftSettings", module)
|
||||
.add("Simon metric", () => (
|
||||
<DraftSettings pattern="simon" gist={false} units="metric" {...props} />
|
||||
))
|
|
@ -6,12 +6,11 @@ import Mm from "../PatternOptionMillimeter";
|
|||
import Bool from "../PatternOptionBool";
|
||||
import List from "../PatternOptionList";
|
||||
import Count from "../PatternOptionCount";
|
||||
import { optionType } from "../utils";
|
||||
import { optionType } from "../../utils";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { injectIntl } from "react-intl";
|
||||
|
||||
const OptionGroup = props => {
|
||||
const update = (name, value) => props.updateValue("option", name, value);
|
||||
|
||||
const renderOption = (name, sub=false) => {
|
||||
let option = props.pattern.config.options[name];
|
||||
|
@ -21,7 +20,7 @@ const OptionGroup = props => {
|
|||
name,
|
||||
dflt: props.dflts.options[name],
|
||||
units: props.units,
|
||||
updateValue: update,
|
||||
updateValue: props.updateValue,
|
||||
triggerAction: props.triggerAction,
|
||||
title: <FormattedMessage id={stringKey + "title"} />,
|
||||
desc: <FormattedMessage id={stringKey + "description"} />,
|
|
@ -35,6 +35,6 @@ const props = {
|
|||
options: Object.keys(options)
|
||||
};
|
||||
|
||||
storiesOf("OptionGroup", module).add("Simon metric", () => (
|
||||
storiesOf("Low level/OptionGroup", module).add("Simon metric", () => (
|
||||
<OptionGroup pattern="simon" {...props} units="metric" />
|
||||
));
|
|
@ -15,6 +15,6 @@ const props = {
|
|||
"This is the description. I'm wrapped in a p tag. This component is used within other components, and not very useful on its own."
|
||||
};
|
||||
|
||||
storiesOf("OptionPreamble", module).add("Preamble", () => (
|
||||
storiesOf("Low level/OptionPreamble", module).add("Preamble", () => (
|
||||
<Preamble {...props} />
|
||||
));
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import FormFieldBool from "../FormFieldBool";
|
||||
import FormFieldBool from "../../form/FormFieldBool";
|
||||
import OptionPreamble from "../OptionPreamble";
|
||||
|
||||
const PatternOptionBool = props => {
|
|
@ -16,6 +16,6 @@ const props = {
|
|||
labels: ["No", "Yes"]
|
||||
};
|
||||
|
||||
storiesOf("PatternOptionBool", module)
|
||||
storiesOf("Low level/PatternOptionBool", module)
|
||||
.add("Basic", () => <Bool {...props} />)
|
||||
.add("Yes as default", () => <Bool {...props} dflt={true} />);
|
|
@ -15,7 +15,7 @@ const props = {
|
|||
"This is the description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it."
|
||||
};
|
||||
|
||||
storiesOf("PatternOptionCount", module)
|
||||
storiesOf("Low level/PatternOptionCount", module)
|
||||
.add("Basic", () => <Count {...props} />)
|
||||
.add("From 20 to 80", () => <Count {...props} min={20} max={80} />)
|
||||
.add("Step: 5", () => <Count {...props} step={5} />);
|
|
@ -16,7 +16,7 @@ const props = {
|
|||
"This is the description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it."
|
||||
};
|
||||
|
||||
storiesOf("PatternOptionDegree", module)
|
||||
storiesOf("Low level/PatternOptionDegree", module)
|
||||
.add("Basic", () => <Pct {...props} />)
|
||||
.add("From 30 to 45", () => <Pct {...props} min={30} max={45} />)
|
||||
.add("Step: 10", () => <Pct {...props} step={10} max={180} dflt={90} />);
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import FormFieldList from "../FormFieldList";
|
||||
import FormFieldList from "../../form/FormFieldList";
|
||||
import OptionPreamble from "../OptionPreamble";
|
||||
|
||||
const PatternOptionList = props => {
|
|
@ -20,4 +20,4 @@ const props = {
|
|||
}
|
||||
};
|
||||
|
||||
storiesOf("PatternOptionList", module).add("Basic", () => <List {...props} />);
|
||||
storiesOf("Low level/PatternOptionList", module).add("Basic", () => <List {...props} />);
|
|
@ -6,8 +6,8 @@ import {
|
|||
roundMmUp,
|
||||
roundMmDown,
|
||||
formatMm
|
||||
} from "../utils";
|
||||
import FormFieldSlider from "../FormFieldSlider";
|
||||
} from "../../utils";
|
||||
import FormFieldSlider from "../../form/FormFieldSlider";
|
||||
import OptionPreamble from "../OptionPreamble";
|
||||
|
||||
const PatternOptionMillimeter = props => {
|
|
@ -21,7 +21,7 @@ const maxNotOnStep =
|
|||
const minNotOnStep =
|
||||
"Since our step is 0.1mm and our min value is 24.06 mm, it falls in between two steps (24mm and 24.1mm). Picking the min value would result in the rounded min value of 24mm, which is outside our min boundary. So we always round the min value up to the closest step. Also note that while the displayed value rounds to mm, under the hood we use 1/10th of a mm and the actual value passed for the min here is not 2.4cm but 24.1mm (2.41cm)";
|
||||
|
||||
storiesOf("PatternOptionMillimeter", module)
|
||||
storiesOf("Low level/PatternOptionMillimeter", module)
|
||||
.add("Metric", () => <Mm {...props} />)
|
||||
.add("Max: 12.486 cm", () => (
|
||||
<Mm {...props} max={124.86} desc={maxNotOnStep} />
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import FormFieldSlider from "../FormFieldSlider";
|
||||
import FormFieldSlider from "../../form/FormFieldSlider";
|
||||
import OptionPreamble from "../OptionPreamble";
|
||||
|
||||
const PatternOptionPctDegCount = props => {
|
|
@ -14,12 +14,12 @@ const props = {
|
|||
"This is the description. I'm wrapped in a p tag. This component is the base for the percentage, degree, and count pattern options."
|
||||
};
|
||||
|
||||
storiesOf("PatternOptionPctDegCount", module).add("Percentage", () => (
|
||||
storiesOf("Low level/PatternOptionPctDegCount", module).add("Percentage", () => (
|
||||
<PctDegCount {...props} type="pct" />
|
||||
));
|
||||
storiesOf("PatternOptionPctDegCount", module).add("Degree", () => (
|
||||
storiesOf("Low level/PatternOptionPctDegCount", module).add("Degree", () => (
|
||||
<PctDegCount {...props} type="deg" />
|
||||
));
|
||||
storiesOf("PatternOptionPctDegCount", module).add("Count", () => (
|
||||
storiesOf("Low level/PatternOptionPctDegCount", module).add("Count", () => (
|
||||
<PctDegCount {...props} type="count" />
|
||||
));
|
|
@ -15,7 +15,7 @@ const props = {
|
|||
"This is the description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it."
|
||||
};
|
||||
|
||||
storiesOf("PatternOptionPercentage", module)
|
||||
storiesOf("Low level/PatternOptionPercentage", module)
|
||||
.add("Basic", () => <Pct {...props} />)
|
||||
.add("From 20 to 80", () => <Pct {...props} min={20} max={80} />)
|
||||
.add("Step: 5", () => <Pct {...props} step={5} />);
|
|
@ -5,7 +5,7 @@ import Deg from "../PatternOptionDegree";
|
|||
import Mm from "../PatternOptionMillimeter";
|
||||
import Bool from "../PatternOptionBool";
|
||||
import OptionGroup from "../OptionGroup";
|
||||
import { optionType, defaultGist, gistDefaults } from "../utils";
|
||||
import { optionType, defaultGist, gistDefaults } from "../../utils";
|
||||
import { patternInfo, patternList } from "@freesewing/patterns";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import List from "@material-ui/core/List";
|
|
@ -14,7 +14,7 @@ const props = {
|
|||
}
|
||||
};
|
||||
|
||||
storiesOf("PatternOptions", module)
|
||||
storiesOf("Low level/PatternOptions", module)
|
||||
.add("Simon metric", () => (
|
||||
<PatternOptions pattern="simon" gist={false} units="metric" {...props} />
|
||||
))
|
|
@ -1,23 +1,22 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Pct from "../PatternOptionPercentage";
|
||||
import Deg from "../PatternOptionDegree";
|
||||
import Mm from "../PatternOptionMillimeter";
|
||||
import Bool from "../PatternOptionBool";
|
||||
import OptionGroup from "../OptionGroup";
|
||||
import Pct from "./PatternOptionPercentage";
|
||||
import Deg from "./PatternOptionDegree";
|
||||
import Mm from "./PatternOptionMillimeter";
|
||||
import Bool from "./PatternOptionBool";
|
||||
import OptionGroup from "./OptionGroup";
|
||||
import { optionType, gistDefaults } from "../utils";
|
||||
import { patternInfo, patternList } from "@freesewing/patterns";
|
||||
import { FormattedMessage, injectIntl } from "react-intl";
|
||||
import { i18n as languages } from "@freesewing/i18n";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import CollapsedIcon from "@material-ui/icons/ArrowDropDown";
|
||||
import ExpandedIcon from "@material-ui/icons/ArrowRight";
|
||||
import PatternOptions from "../PatternOptions";
|
||||
import DraftSettings from "../DraftSettings";
|
||||
import DraftActions from "../DraftActions";
|
||||
import PatternOptions from "./PatternOptions";
|
||||
import DraftSettings from "./DraftSettings";
|
||||
//import DraftActions from "DraftActions";
|
||||
import withGist from "../withGist";
|
||||
|
||||
const GistConfigurator = props => {
|
||||
console.log(languages);
|
||||
const [gist, setGist] = useState(props.gist);
|
||||
const DraftConfigurator = props => {
|
||||
const [gist, setGist] = useState(props.gist.get);
|
||||
const [expanded, setExpanded] = useState([]);
|
||||
|
||||
const update = (type, name, value) => {
|
||||
|
@ -31,9 +30,8 @@ const GistConfigurator = props => {
|
|||
else shown.splice(index, 1);
|
||||
setExpanded(shown);
|
||||
};
|
||||
|
||||
let pattern = patternInfo[props.pattern];
|
||||
let dflts = gistDefaults(pattern.config, props.gist);
|
||||
let dflts = gistDefaults(pattern.config, props.gist.get);
|
||||
|
||||
return (
|
||||
<ul className="nav l1">
|
||||
|
@ -44,7 +42,7 @@ const GistConfigurator = props => {
|
|||
<PatternOptions
|
||||
pattern={props.pattern}
|
||||
units={props.units}
|
||||
updateValue={update}
|
||||
updateValue={(name, value) => props.gist.set(value, 'settings', 'options', name)}
|
||||
triggerAction={props.triggerAction}
|
||||
/>
|
||||
</li>
|
||||
|
@ -55,27 +53,19 @@ const GistConfigurator = props => {
|
|||
<DraftSettings
|
||||
pattern={props.pattern}
|
||||
units={props.units}
|
||||
updateValue={update}
|
||||
updateValue={(name, value) => props.gist.set(value, 'settings', name)}
|
||||
triggerAction={props.triggerAction}
|
||||
language={props.intl.locale}
|
||||
languages={languages[props.intl.locale]}
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<h2>
|
||||
<FormattedMessage id="app.save" />
|
||||
</h2>
|
||||
<DraftActions />
|
||||
</li>
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
GistConfigurator.propTypes = {
|
||||
DraftConfigurator.propTypes = {
|
||||
pattern: PropTypes.oneOf(patternList),
|
||||
units: PropTypes.oneOf(["metric", "imperial"]).isRequired
|
||||
};
|
||||
|
||||
GistConfigurator.defaultProps = {};
|
||||
DraftConfigurator.defaultProps = {};
|
||||
|
||||
export default injectIntl(GistConfigurator);
|
||||
export default withGist(DraftConfigurator, {gist: {}, store: "yes"});
|
|
@ -9,14 +9,9 @@ const props = {
|
|||
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: {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
storiesOf("GistConfigurator", module)
|
||||
storiesOf("DraftConfigurator", module)
|
||||
.add("Simon metric", () => (
|
||||
<GistConfigurator pattern="simon" {...props} units="metric" />
|
||||
))
|
|
@ -1,31 +0,0 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import DraftSettings from ".";
|
||||
|
||||
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: {}
|
||||
}
|
||||
},
|
||||
languages: {
|
||||
de: "German",
|
||||
en: "English",
|
||||
es: "Spanish",
|
||||
fr: "French",
|
||||
nl: "Dutch"
|
||||
},
|
||||
language: "en"
|
||||
};
|
||||
|
||||
storiesOf("DraftSettings", module)
|
||||
.add("Simon metric", () => (
|
||||
<DraftSettings pattern="simon" gist={false} units="metric" {...props} />
|
||||
))
|
||||
.add("Trayvon imperial", () => (
|
||||
<DraftSettings pattern="trayvon" gist={false} units="imperial" {...props} />
|
||||
));
|
|
@ -3,8 +3,8 @@ import PropTypes from "prop-types";
|
|||
|
||||
const Emblem = props => (
|
||||
<React.Fragment>
|
||||
<span className="emb" style={{color: props.c1}}>{props.t1}</span>
|
||||
<span className="lem" style={{color: props.c2}}>{props.t2}</span>
|
||||
<span className="emb" style={{color: props.c1, fontSize: props.size+"px"}}>{props.t1}</span>
|
||||
<span className="lem" style={{color: props.c2, fontSize: props.size+"px"}}>{props.t2}</span>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
|
@ -17,11 +17,11 @@ Emblem.propTypes = {
|
|||
};
|
||||
|
||||
Emblem.defaultProps = {
|
||||
size: 24,
|
||||
size: 36,
|
||||
c1: "#111111",
|
||||
c2: "#111111",
|
||||
t1: "",
|
||||
t2: ""
|
||||
t2: "",
|
||||
};
|
||||
|
||||
export default Emblem;
|
||||
|
|
42
packages/components/src/Navbar/index.js
Normal file
42
packages/components/src/Navbar/index.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Logo from "../Logo";
|
||||
import Emblem from "../Emblem";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
const Navbar = props => {
|
||||
|
||||
const renderNav = nav => {
|
||||
let title = nav.title || nav.text;
|
||||
let text = typeof nav.text === "string"
|
||||
? <FormattedMessage id={nav.text} />
|
||||
: nav.text
|
||||
if (nav.type === "component") return nav.component
|
||||
return <a href={nav.href} className="nav" title={nav.title}>{text}</a>
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="navbar">
|
||||
<div>
|
||||
<div className="logo">{props.logo}</div>
|
||||
<div className="emblem">{props.emblem}</div>
|
||||
{props.navs.left.map(nav => renderNav(nav))}
|
||||
<div className="spread" />
|
||||
{props.navs.right.map(nav => renderNav(nav))}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
Navbar.propTypes = {
|
||||
navs: PropTypes.object,
|
||||
logo: PropTypes.node,
|
||||
emblem: PropTypes.node,
|
||||
};
|
||||
|
||||
Navbar.defaultProps = {
|
||||
navs: {left:[], right: []},
|
||||
logo: <Logo size={32} />,
|
||||
emblem: <Emblem t1="Free" t2="Sewing" size={20} c1="#74c0fc" c2="#e9ecef"/>
|
||||
};
|
||||
export default Navbar;
|
55
packages/components/src/Navbar/stories.js
Normal file
55
packages/components/src/Navbar/stories.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import Navbar from ".";
|
||||
import LanguageIcon from "@material-ui/icons/Translate";
|
||||
import DarkModeIcon from "@material-ui/icons/Brightness3";
|
||||
import Avatar from '@material-ui/core/Avatar';
|
||||
|
||||
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),
|
||||
};
|
||||
const navs = {
|
||||
left: [
|
||||
{
|
||||
type: "link",
|
||||
href: "https://freesewing.org/",
|
||||
text: "app.patterns"
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
href: "https://freesewing.org/",
|
||||
text: "app.docs"
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
href: "https://freesewing.org/",
|
||||
text: "app.community"
|
||||
},
|
||||
],
|
||||
right: [
|
||||
{
|
||||
type: "link",
|
||||
href: "https://freesewing.org/",
|
||||
text: "app.account",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
href: "https://freesewing.org/",
|
||||
text: <LanguageIcon className="nav-icon"/>,
|
||||
title: 'Languages'
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
href: "https://freesewing.org/",
|
||||
text: <DarkModeIcon className="nav-icon moon"/>,
|
||||
title: 'Dark mode'
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
storiesOf("Navbar", module)
|
||||
.add("Basic", () => <Navbar navs={navs}/>)
|
|
@ -9,7 +9,7 @@ const props = {
|
|||
};
|
||||
const noyes = ["No", "Yes"];
|
||||
|
||||
storiesOf("FormFieldBool", module)
|
||||
storiesOf("Low level/Form/FormFieldBool", module)
|
||||
.add("Basic", () => <FormFieldBool {...props} />)
|
||||
.add("False", () => <FormFieldBool {...props} dflt={false} />)
|
||||
.add("True", () => <FormFieldBool {...props} dflt={true} />)
|
|
@ -14,7 +14,7 @@ const props = {
|
|||
dflt: []
|
||||
};
|
||||
|
||||
storiesOf("FormFieldChecks", module)
|
||||
storiesOf("Low level/Form/FormFieldChecks", module)
|
||||
.add("Basic", () => <FormFieldChecks {...props} />)
|
||||
.add("Apple", () => <FormFieldChecks {...props} dflt={["apple"]} />)
|
||||
.add("Banana", () => <FormFieldChecks {...props} dflt={["banana"]} />)
|
|
@ -13,7 +13,7 @@ const props = {
|
|||
}
|
||||
};
|
||||
|
||||
storiesOf("FormFieldList", module)
|
||||
storiesOf("Low level/Form/FormFieldList", module)
|
||||
.add("Basic", () => <FormFieldList {...props} />)
|
||||
.add("Apple", () => <FormFieldList {...props} dflt="apple" />)
|
||||
.add("Banana", () => <FormFieldList {...props} dflt="banana" />)
|
|
@ -8,7 +8,7 @@ const props = {
|
|||
name: "exampleSliderOption"
|
||||
};
|
||||
|
||||
storiesOf("FormFieldSlider", module)
|
||||
storiesOf("Low level/Form/FormFieldSlider", module)
|
||||
.add("Basic", () => <FormFieldSlider {...props} />)
|
||||
.add("From 1 to 10", () => <FormFieldSlider {...props} min={1} max={10} />)
|
||||
.add("Step: 1", () => (
|
|
@ -159,3 +159,28 @@ export const optionDefault = option => {
|
|||
return option[type];
|
||||
}
|
||||
};
|
||||
|
||||
export const storage = {
|
||||
set: (key, value, raw) => {
|
||||
if (typeof localStorage === "undefined")
|
||||
throw(new Error("No localStorage support. And we need it. Bailing out."));
|
||||
|
||||
const _key = "fs_" + key;
|
||||
|
||||
if (typeof value === "undefined" || value === null)
|
||||
localStorage.removeItem(_key);
|
||||
else localStorage.setItem(_key, raw ? value : JSON.stringify(value));
|
||||
|
||||
return value;
|
||||
},
|
||||
get: (key, raw) => {
|
||||
if (typeof localStorage === "undefined")
|
||||
throw(new Error("No localStorage support. And we need it. Bailing out."));
|
||||
|
||||
const value = localStorage.getItem("fs_"+key);
|
||||
|
||||
return raw ? value : JSON.parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
export const cloneObject = src => Object.assign({}, src);
|
||||
|
|
39
packages/components/src/withGist/index.js
Normal file
39
packages/components/src/withGist/index.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
import React from "react";
|
||||
import { storage, cloneObject } from "../utils";
|
||||
|
||||
const withGist = (WrappedComponent, settings={gist:{}, store:false}) => {
|
||||
|
||||
return class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.update = this.update.bind(this);
|
||||
this.state = settings.gist || {};
|
||||
}
|
||||
|
||||
update(value, l1 = false, l2 = false, l3 = false) {
|
||||
console.log('update', value, l1, l2, l3, this.state);
|
||||
if (!l1) return;
|
||||
let gist = this.state;
|
||||
|
||||
if(typeof gist === "undefined") gist = {};
|
||||
if(l1 && typeof gist[l1] === "undefined") gist[l1] = {};
|
||||
if(l2 && typeof gist[l1][l2] === "undefined") gist[l1][l2] = {};
|
||||
if(l3 && typeof gist[l1][l2][l3] === "undefined") gist[l1][l2][l3] = {};
|
||||
|
||||
if (l3) gist[l1][l2][l3] = value;
|
||||
else if (l2) gist[l1][l2] = value;
|
||||
else if (l1) gist[l1] = value;
|
||||
this.setState(gist, () => {
|
||||
if (settings.store) storage.set(settings.store, this.state);
|
||||
console.log(this.state);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
return <WrappedComponent gist={{get: this.state.gist, set: this.update}} {...this.props} />;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default withGist;
|
|
@ -1,3 +1,3 @@
|
|||
@import "components/emblem";
|
||||
@import "components/pattern-option";
|
||||
@import "components/pattern-options";
|
||||
@import "components/navbar";
|
||||
@import "components/draft-configurator";
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
$fc-text-light: $oc-gray-9;
|
||||
$fc-text-dark: $oc-gray-0;
|
||||
$fc-bg-light: $oc-gray-0;
|
||||
$fc-bg-dark: $oc-gray-9;
|
||||
$fc-notice-light: $oc-yellow-7;
|
||||
$fc-notice-dark: $oc-lime-3;
|
||||
$fc-hoverbg-light: $oc-gray-1;
|
||||
$fc-hoverbg-dark: $oc-gray-8;
|
||||
$fc-accentbg-light: $oc-teal-5;
|
||||
$fc-accentbg-dark: $oc-teal-8;
|
||||
$fc-link-light: $oc-teal-8;
|
||||
$fc-link-dark: $oc-blue-3;
|
||||
|
||||
|
|
|
@ -65,7 +65,8 @@ svg.icon-col-exp.expanded {
|
|||
}
|
||||
|
||||
ul.nav.l2 div.col-exp,
|
||||
ul.nav.l3 div.col-exp {
|
||||
ul.nav.l3 div.col-exp,
|
||||
ul.nav.l4 div.col-exp {
|
||||
margin: 0 27px;
|
||||
}
|
||||
|
65
packages/css-theme/src/components/_navbar.scss
Normal file
65
packages/css-theme/src/components/_navbar.scss
Normal file
|
@ -0,0 +1,65 @@
|
|||
header.navbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 64px;
|
||||
width: calc(100% - 52px);
|
||||
margin: 0;
|
||||
padding: 0 26px;
|
||||
background: $fc-bg-dark;
|
||||
|
||||
div.logo {
|
||||
height: 64px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-right: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: $oc-gray-2;
|
||||
}
|
||||
div.emblem {
|
||||
margin-right: 26px;
|
||||
}
|
||||
div.spread { flex-grow: 1}
|
||||
a.nav,
|
||||
button {
|
||||
@include title-font;
|
||||
margin: 0;
|
||||
padding: 0 13px;
|
||||
height: 60px;
|
||||
color: $fc-text-dark;
|
||||
border: 0;
|
||||
line-height: 64px;
|
||||
border-bottom: 4px solid $fc-bg-dark;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease, border-color 0.2s ease-in-out;
|
||||
background:none;
|
||||
}
|
||||
button {
|
||||
/* For buttons, border does not count for height */
|
||||
height: 64px;
|
||||
}
|
||||
button:hover,
|
||||
a.nav:hover {
|
||||
cursor: pointer;
|
||||
color: $fc-link-dark;
|
||||
border-color: $fc-link-dark;
|
||||
}
|
||||
a.nav.active {
|
||||
border-color: $fc-link-dark;
|
||||
}
|
||||
svg.nav-icon {
|
||||
margin-right: 5px;
|
||||
margin-bottom: -6px;
|
||||
}
|
||||
svg.nav-icon.moon {
|
||||
transform: rotate(26deg);
|
||||
}
|
||||
}
|
||||
|
||||
header.navbar > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
div.pattern-option {
|
||||
.po-custom {
|
||||
color: $fc-notice-light;
|
||||
}
|
||||
label.po-list-item:hover {
|
||||
background: $fc-hoverbg-light;
|
||||
}
|
||||
}
|
||||
|
||||
body.dark {
|
||||
div.pattern-option {
|
||||
.po-custom {
|
||||
color: $fc-notice-dark;
|
||||
}
|
||||
label.po-list-item:hover {
|
||||
background: $fc-hoverbg-dark;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
export default class Storage {
|
||||
set(key, value, isJson) {
|
||||
set(key, value, raw = false) {
|
||||
if (typeof localStorage === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ export default class Storage {
|
|||
if (typeof value === "undefined" || value === null) {
|
||||
localStorage.removeItem(_key);
|
||||
} else {
|
||||
localStorage.setItem(_key, isJson ? JSON.stringify(value) : value);
|
||||
localStorage.setItem(_key, raw ? value : JSON.stringify(value));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
get(key, isJson) {
|
||||
get(key, raw = false) {
|
||||
if (typeof localStorage === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
@ -24,6 +24,6 @@ export default class Storage {
|
|||
|
||||
const value = localStorage.getItem(_key);
|
||||
|
||||
return isJson ? JSON.parse(value) : value;
|
||||
return raw ? value : JSON.parse(value);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue