🚧 More work on React components
This commit is contained in:
parent
4d7b7df674
commit
fa43bf1d0c
16 changed files with 313 additions and 30 deletions
|
@ -53,6 +53,7 @@
|
|||
"@babel/register": "^7.0.0",
|
||||
"@material-ui/core": "3.9.3",
|
||||
"@material-ui/icons": "3.0.2",
|
||||
"@material-ui/lab": "3.0.0-alpha.30",
|
||||
"@storybook/addon-backgrounds": "5.0.10",
|
||||
"@storybook/addon-knobs": "5.0.10",
|
||||
"@storybook/addon-notes": "5.0.10",
|
||||
|
|
|
@ -3,7 +3,7 @@ import { storiesOf, addDecorator } from "@storybook/react";
|
|||
import Emblem from ".";
|
||||
import "../../../../dist/css-theme/theme.css";
|
||||
|
||||
storiesOf("Graphics/Emblem", module).add(
|
||||
storiesOf("Emblem", module).add(
|
||||
"FreeSewing",
|
||||
() => <Emblem t1="Free" t2="Sewing" />,
|
||||
{ notes: { markdown: ` test **here**` } }
|
||||
|
|
17
packages/components/src/FormFieldBool/stories.js
Normal file
17
packages/components/src/FormFieldBool/stories.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import FormFieldBool from ".";
|
||||
|
||||
const props = {
|
||||
updateOption: (name, value) =>
|
||||
console.log(`Updated option ${name}, value is now: ${value}`),
|
||||
name: "exampleBoolOption"
|
||||
};
|
||||
const noyes = ["No", "Yes"];
|
||||
|
||||
storiesOf("FormFieldBool", module)
|
||||
.add("Basic", () => <FormFieldBool {...props} />)
|
||||
.add("False", () => <FormFieldBool {...props} dflt={false} />)
|
||||
.add("True", () => <FormFieldBool {...props} dflt={true} />)
|
||||
.add("No", () => <FormFieldBool {...props} dflt={false} labels={noyes} />)
|
||||
.add("Yes", () => <FormFieldBool {...props} dflt={true} labels={noyes} />);
|
35
packages/components/src/FormFieldList/index.js
Normal file
35
packages/components/src/FormFieldList/index.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
import React, { useState } 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 [value, setValue] = useState(props.dflt);
|
||||
const update = evt => {
|
||||
props.updateOption(props.name, evt.target.value);
|
||||
setValue(evt.target.value);
|
||||
};
|
||||
return (
|
||||
<RadioGroup onChange={update} value={value}>
|
||||
{Object.keys(props.list).map((item, index) => (
|
||||
<FormControlLabel
|
||||
key={item}
|
||||
control={<Radio color="primary" />}
|
||||
value={item}
|
||||
checked={value === item ? true : false}
|
||||
label={props.list[item]}
|
||||
/>
|
||||
))}
|
||||
</RadioGroup>
|
||||
);
|
||||
};
|
||||
|
||||
FormFieldList.propTypes = {
|
||||
dflt: PropTypes.bool,
|
||||
list: PropTypes.object,
|
||||
updateOption: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default FormFieldList;
|
20
packages/components/src/FormFieldList/stories.js
Normal file
20
packages/components/src/FormFieldList/stories.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import FormFieldList from ".";
|
||||
|
||||
const props = {
|
||||
updateOption: (name, value) =>
|
||||
console.log(`Updated option ${name}, value is now: ${value}`),
|
||||
name: "exampleListOption",
|
||||
list: {
|
||||
apple: "Apple",
|
||||
banana: "Banana",
|
||||
cherry: "Cherry"
|
||||
}
|
||||
};
|
||||
|
||||
storiesOf("FormFieldList", module)
|
||||
.add("Basic", () => <FormFieldList {...props} />)
|
||||
.add("Apple", () => <FormFieldList {...props} dflt="apple" />)
|
||||
.add("Banana", () => <FormFieldList {...props} dflt="banana" />)
|
||||
.add("Cherry", () => <FormFieldList {...props} dflt="cherry" />);
|
56
packages/components/src/FormFieldSlider/index.js
Normal file
56
packages/components/src/FormFieldSlider/index.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Slider from "@material-ui/lab/Slider";
|
||||
import { withStyles } from "@material-ui/core/styles";
|
||||
|
||||
const PaddedSlider = withStyles({
|
||||
container: { padding: "25px 0" },
|
||||
track: { height: "4px" },
|
||||
thumb: { width: "16px", height: "16px" }
|
||||
})(Slider);
|
||||
|
||||
const FormFieldSlider = props => {
|
||||
const [value, setValue] = useState(props.value);
|
||||
|
||||
const update = (evt, newValue) => {
|
||||
props.updateOption(props.name, newValue, evt);
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
// Force state update when rerendering due to props change
|
||||
if (props.value !== value) setValue(props.value);
|
||||
|
||||
return (
|
||||
<PaddedSlider
|
||||
value={value}
|
||||
min={props.min}
|
||||
max={props.max}
|
||||
step={props.step}
|
||||
onChange={update}
|
||||
onDragEnd={update}
|
||||
classes={{
|
||||
track: "slider-track",
|
||||
thumb: "slider-thumb"
|
||||
}}
|
||||
aria-labelledby={props.label}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
FormFieldSlider.propTypes = {
|
||||
min: PropTypes.number,
|
||||
max: PropTypes.number,
|
||||
step: PropTypes.number,
|
||||
updateOption: 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;
|
19
packages/components/src/FormFieldSlider/stories.js
Normal file
19
packages/components/src/FormFieldSlider/stories.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import FormFieldSlider from ".";
|
||||
|
||||
const props = {
|
||||
updateOption: (name, value) =>
|
||||
console.log(`Updated option ${name}, value is now: ${value}`),
|
||||
name: "exampleSliderOption"
|
||||
};
|
||||
|
||||
storiesOf("FormFieldSlider", module)
|
||||
.add("Basic", () => <FormFieldSlider {...props} />)
|
||||
.add("From 1 to 10", () => <FormFieldSlider {...props} min={1} max={10} />)
|
||||
.add("Step: 1", () => (
|
||||
<FormFieldSlider {...props} min={1} max={10} step={1} />
|
||||
))
|
||||
.add("Defalt: 7", () => (
|
||||
<FormFieldSlider {...props} min={1} max={10} dflt={7} />
|
||||
));
|
File diff suppressed because one or more lines are too long
|
@ -1,10 +1,8 @@
|
|||
import React from "react";
|
||||
import { storiesOf, addDecorator } from "@storybook/react";
|
||||
//import {muiTheme} from 'storybook-addon-material-ui';
|
||||
import Logo from ".";
|
||||
|
||||
storiesOf("Graphics/Logo", module)
|
||||
// .addDecorator(muiTheme())
|
||||
storiesOf("Logo", module)
|
||||
.add("Default", () => <Logo />)
|
||||
.add("Custom size", () => <Logo size={100} />)
|
||||
.add("Custom color", () => (
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import Ogol from ".";
|
||||
import "../../../../dist/css-theme/theme.css";
|
||||
import { dark as backgrounds } from "../../.storybook/backgrounds";
|
||||
|
||||
storiesOf("Graphics/Ogol", module)
|
||||
storiesOf("Ogol", module)
|
||||
.add("Default", () => <Ogol />, { backgrounds })
|
||||
.add("Custom color", () => <Ogol color="green" />, { backgrounds })
|
||||
.add("Custom color", () => <Ogol color="yellow" />, { backgrounds })
|
||||
.add("Custom size", () => <Ogol size={200} />, { backgrounds });
|
||||
|
|
122
packages/components/src/PatternOptionPercentage/index.js
Normal file
122
packages/components/src/PatternOptionPercentage/index.js
Normal file
|
@ -0,0 +1,122 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import FormFieldSlider from "../FormFieldSlider";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import ResetIcon from "@material-ui/icons/SettingsBackupRestore";
|
||||
import HelpIcon from "@material-ui/icons/Help";
|
||||
|
||||
const PatternOptionPercentage = props => {
|
||||
const [value, setValue] = useState(props.dflt);
|
||||
const [previousValue, setPreviousValue] = useState(props.dflt);
|
||||
|
||||
const round = val => Math.round(val * 10) / 10;
|
||||
|
||||
const update = (name, newValue, evt) => {
|
||||
newValue = round(newValue);
|
||||
// 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.updateOption(props.name, newValue);
|
||||
} else {
|
||||
if (evt.type !== "mousemove") props.updateOption(props.name, value);
|
||||
}
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
setValue(props.dflt);
|
||||
props.updateOption(props.name, props.dflt);
|
||||
};
|
||||
|
||||
const styles = {
|
||||
container: {
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center"
|
||||
},
|
||||
left: {
|
||||
flexGrow: 1,
|
||||
margin: "0 0.5rem"
|
||||
},
|
||||
right: { margin: "0 0.5rem" }
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="pattern-option percentage">
|
||||
<div style={styles.container}>
|
||||
<div style={styles.left}>
|
||||
<h4 id={"po-pct-" + props.name}>{props.title}</h4>
|
||||
</div>
|
||||
<div style={styles.right}>
|
||||
<h4 className={value === props.dflt ? "dflt" : "custom"}>{value}%</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div style={styles.container}>
|
||||
<div style={styles.left}>
|
||||
<p>{props.desc}</p>
|
||||
</div>
|
||||
<div style={styles.right}>
|
||||
<IconButton
|
||||
title={props.resetLabel}
|
||||
aria-label={props.resetLabel}
|
||||
color="primary"
|
||||
disabled={value === props.dflt ? true : false}
|
||||
onClick={reset}
|
||||
>
|
||||
<ResetIcon />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
title={props.docsLabel}
|
||||
aria-label={props.docsLabel}
|
||||
color="primary"
|
||||
onClick={() =>
|
||||
props.triggerAction("showHelp", {
|
||||
type: "patternOption",
|
||||
value: props.name
|
||||
})
|
||||
}
|
||||
>
|
||||
<HelpIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
<FormFieldSlider
|
||||
name={props.name}
|
||||
value={value}
|
||||
min={props.min}
|
||||
max={props.max}
|
||||
step={props.step}
|
||||
onChange={update}
|
||||
label={"po-pct-" + props.name}
|
||||
updateOption={update}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
PatternOptionPercentage.propTypes = {
|
||||
min: PropTypes.number,
|
||||
max: PropTypes.number,
|
||||
step: PropTypes.number,
|
||||
updateOption: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
dflt: PropTypes.number.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
desc: PropTypes.string.isRequired,
|
||||
resetLabel: PropTypes.string,
|
||||
docsLabel: PropTypes.string
|
||||
};
|
||||
|
||||
PatternOptionPercentage.defaultProps = {
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 0.1,
|
||||
title: false,
|
||||
desc: false,
|
||||
resetLabel: "♻️",
|
||||
docsLabel: "🤔"
|
||||
};
|
||||
|
||||
export default PatternOptionPercentage;
|
|
@ -0,0 +1 @@
|
|||
div.pattern-option .custom { color: #5c940d; }
|
21
packages/components/src/PatternOptionPercentage/stories.js
Normal file
21
packages/components/src/PatternOptionPercentage/stories.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import Pct from ".";
|
||||
import "./stories.css";
|
||||
|
||||
const props = {
|
||||
triggerAction: (type, data) =>
|
||||
console.log(`Action of type ${type} triggered, data passed is`, data),
|
||||
updateOption: (name, value) =>
|
||||
console.log(`Updated percentage option ${name}, value is now: ${value}`),
|
||||
name: "examplePercentageOption",
|
||||
dflt: 50
|
||||
};
|
||||
|
||||
storiesOf("PatternOptionPercentage", module).add("Basic", () => (
|
||||
<Pct
|
||||
{...props}
|
||||
title="This is the title. I'm wrapped in an h4 tag"
|
||||
desc="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 (we've made it green in this example)."
|
||||
/>
|
||||
));
|
|
@ -1,19 +0,0 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import Bool from ".";
|
||||
|
||||
const props = {
|
||||
updateOption: (name, value) =>
|
||||
console.log(`Updated option ${name}, value is now: ${value}`),
|
||||
name: "exampleBoolOption"
|
||||
};
|
||||
const noyes = ["No", "Yes"];
|
||||
|
||||
storiesOf("Draft/Options/Bool", module)
|
||||
.add("Default", () => <Bool {...props} />)
|
||||
.add("Default: false", () => <Bool {...props} dflt={false} />)
|
||||
.add("Default: true", () => <Bool {...props} dflt={true} />)
|
||||
.add("With labels, No", () => <Bool {...props} dflt={false} labels={noyes} />)
|
||||
.add("With labels, Yes", () => (
|
||||
<Bool {...props} dflt={true} labels={noyes} />
|
||||
));
|
13
yarn.lock
13
yarn.lock
|
@ -2195,6 +2195,17 @@
|
|||
"@babel/runtime" "^7.2.0"
|
||||
recompose "0.28.0 - 0.30.0"
|
||||
|
||||
"@material-ui/lab@3.0.0-alpha.30":
|
||||
version "3.0.0-alpha.30"
|
||||
resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-3.0.0-alpha.30.tgz#c6c64d0ff2b28410a09e4009f3677499461f3df8"
|
||||
integrity sha512-d8IXbkQO92Ln7f/Tzy8Q5cLi/sMWH/Uz1xrOO5NKUgg42whwyCuoT9ErddDPFNQmPi9d1C7A5AG8ONjEAbAIyQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.2.0"
|
||||
"@material-ui/utils" "^3.0.0-alpha.2"
|
||||
classnames "^2.2.5"
|
||||
keycode "^2.1.9"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
"@material-ui/system@^3.0.0-alpha.0":
|
||||
version "3.0.0-alpha.2"
|
||||
resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-3.0.0-alpha.2.tgz#096e80c8bb0f70aea435b9e38ea7749ee77b4e46"
|
||||
|
@ -11543,7 +11554,7 @@ jws@^3.1.5:
|
|||
jwa "^1.4.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
keycode@^2.2.0:
|
||||
keycode@^2.1.9, keycode@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.2.0.tgz#3d0af56dc7b8b8e5cba8d0a97f107204eec22b04"
|
||||
integrity sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ=
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue