Commit b9b49d3c by Ari Rizzitano

deployable docs!!! + lintfixes

parent f171a162
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
"scripts": { "scripts": {
"build": "NODE_ENV=production webpack", "build": "NODE_ENV=production webpack",
"build-storybook": "build-storybook", "build-storybook": "build-storybook",
"deploy-storybook": "storybook-to-ghpages",
"lint": "eslint .", "lint": "eslint .",
"prestart": "install-self-peers", "prestart": "install-self-peers",
"poststop": "yarn install", "poststop": "yarn install",
...@@ -20,6 +21,7 @@ ...@@ -20,6 +21,7 @@
}, },
"devDependencies": { "devDependencies": {
"@kadira/storybook": "^2.21.0", "@kadira/storybook": "^2.21.0",
"@kadira/storybook-deployer": "^1.2.0",
"@team-griffin/install-self-peers": "^1.0.0", "@team-griffin/install-self-peers": "^1.0.0",
"babel-cli": "^6.24.1", "babel-cli": "^6.24.1",
"babel-loader": "^7.0.0", "babel-loader": "^7.0.0",
......
...@@ -2,14 +2,15 @@ import React from 'react'; ...@@ -2,14 +2,15 @@ import React from 'react';
import { Input } from 'reactstrap'; import { Input } from 'reactstrap';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import asInput from './utils/asInput'; import asInput, { inputProps } from './utils/asInput';
class Select extends React.Component { class Select extends React.Component {
getOption(option, i) { static getOption(option, i) {
let { label, value } = option; let { label, value } = option;
if (typeof option === 'string') { if (typeof option === 'string') {
label = value = option; label = option;
value = option;
} }
return ( return (
...@@ -21,29 +22,29 @@ class Select extends React.Component { ...@@ -21,29 +22,29 @@ class Select extends React.Component {
return this.props.options.map((option, i) => { return this.props.options.map((option, i) => {
let section; let section;
if (option.options) { if (option.options) {
const groupOpts = option.options.map((opt, j) => this.getOption(opt, j)); const groupOpts = option.options.map((opt, j) => Select.getOption(opt, j));
section = ( section = (
<optgroup label={option.label} key={`group-${i}`}> <optgroup label={option.label} key={option.label}>
{groupOpts} {groupOpts}
</optgroup> </optgroup>
); );
} else { } else {
section = this.getOption(option, i); section = Select.getOption(option, i);
} }
return section; return section;
}); });
} }
render() { render() {
const props = { ...this.props }, const props = { ...this.props };
options = this.getOptions(); const options = this.getOptions();
return ( return (
<Input <Input
id={this.props.id} id={props.id}
type="select" type="select"
name={this.props.name} name={props.name}
value={this.props.value} value={props.value}
aria-describedby={props.describedBy} aria-describedby={props.describedBy}
onChange={props.onChange} onChange={props.onChange}
onBlur={props.onBlur} onBlur={props.onBlur}
...@@ -54,11 +55,19 @@ class Select extends React.Component { ...@@ -54,11 +55,19 @@ class Select extends React.Component {
} }
} }
Select.propTypes = {
...inputProps,
options: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string),
PropTypes.arrayOf(PropTypes.object),
]).isRequired,
};
const SelectInput = asInput(Select); const SelectInput = asInput(Select);
SelectInput.propTypes = { SelectInput.propTypes = {
...SelectInput.propTypes, ...SelectInput.propTypes,
options: PropTypes.array.isRequired ...Select.propTypes,
}; };
export default SelectInput; export default SelectInput;
import React, { Component } from 'react'; import React from 'react';
import { TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap'; import { TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import classnames from 'classnames'; import classnames from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { newId } from './utils'; import { newId } from './utils/newId';
class TabInterface extends React.Component { class TabInterface extends React.Component {
constructor(props) { constructor(props) {
...@@ -35,13 +35,14 @@ class TabInterface extends React.Component { ...@@ -35,13 +35,14 @@ class TabInterface extends React.Component {
buildLabels() { buildLabels() {
return this.props.tabLabels.map((label, i) => { return this.props.tabLabels.map((label, i) => {
const selected = this.state.activeTab === i; const selected = this.state.activeTab === i;
const labelId = this.genLabelId(i);
return ( return (
<NavItem <NavItem
aria-selected={selected} aria-selected={selected}
aria-controls={this.genPanelId(i)} aria-controls={this.genPanelId(i)}
id={this.genLabelId(i)} id={labelId}
key={i} key={labelId}
role="tab" role="tab"
tabIndex={selected ? 0 : -1} tabIndex={selected ? 0 : -1}
> >
...@@ -59,13 +60,14 @@ class TabInterface extends React.Component { ...@@ -59,13 +60,14 @@ class TabInterface extends React.Component {
buildPanels() { buildPanels() {
return this.props.panels.map((panel, i) => { return this.props.panels.map((panel, i) => {
const selected = this.state.activeTab === i; const selected = this.state.activeTab === i;
const panelId = this.genPanelId(i);
return ( return (
<TabPane <TabPane
aria-hidden={!selected} aria-hidden={!selected}
aria-labelledby={this.genLabelId(i)} aria-labelledby={this.genLabelId(i)}
id={this.genPanelId(i)} id={panelId}
key={i} key={panelId}
role="tabpanel" role="tabpanel"
tabId={i} tabId={i}
> >
...@@ -76,11 +78,11 @@ class TabInterface extends React.Component { ...@@ -76,11 +78,11 @@ class TabInterface extends React.Component {
} }
render() { render() {
const labels = this.buildLabels(), const labels = this.buildLabels();
panels = this.buildPanels(); const panels = this.buildPanels();
return ( return (
<div className={this.props.className}> <div>
<Nav tabs role="tablist"> <Nav tabs role="tablist">
{labels} {labels}
</Nav> </Nav>
......
import React from 'react'; import React from 'react';
import { Input } from 'reactstrap'; import { Input } from 'reactstrap';
import asInput from './utils/asInput'; import asInput, { inputProps } from './utils/asInput';
function TextField(props) { function TextField(props) {
return ( return (
...@@ -15,12 +15,15 @@ function TextField(props) { ...@@ -15,12 +15,15 @@ function TextField(props) {
onChange={props.onChange} onChange={props.onChange}
onBlur={props.onBlur} onBlur={props.onBlur}
aria-invalid={!props.isValid} aria-invalid={!props.isValid}
disabled={props.disabled}
required={props.required} required={props.required}
state={props.inputState} state={props.inputState}
/> />
); );
} }
TextField.propTypes = inputProps;
const TextInput = asInput(TextField); const TextInput = asInput(TextField);
export default TextInput; export default TextInput;
...@@ -6,6 +6,20 @@ import newId from './newId'; ...@@ -6,6 +6,20 @@ import newId from './newId';
const getDisplayName = WrappedComponent => WrappedComponent.displayName || WrappedComponent.name || 'Component'; const getDisplayName = WrappedComponent => WrappedComponent.displayName || WrappedComponent.name || 'Component';
export const inputProps = {
label: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
value: PropTypes.string,
description: PropTypes.oneOfType([
PropTypes.string,
PropTypes.element,
]),
disabled: PropTypes.bool,
required: PropTypes.bool,
onChange: PropTypes.func,
validator: PropTypes.func,
};
const asInput = (WrappedComponent) => { const asInput = (WrappedComponent) => {
class NewComponent extends React.Component { class NewComponent extends React.Component {
constructor(props) { constructor(props) {
...@@ -24,22 +38,10 @@ const asInput = (WrappedComponent) => { ...@@ -24,22 +38,10 @@ const asInput = (WrappedComponent) => {
}; };
} }
handleChange(event) {
this.setState({ value: event.target.value });
this.props.onChange(event.target.value, this.props.name);
}
handleBlur(event) {
if (this.props.validator) {
this.setState(this.props.validator);
}
}
getDescriptions() { getDescriptions() {
// possible future work: multiple feedback msgs? // possible future work: multiple feedback msgs?
const errorId = `error-${this.state.id}`, const errorId = `error-${this.state.id}`;
descriptionId = `description-${this.state.id}`; const descriptionId = `description-${this.state.id}`;
const desc = {}; const desc = {};
if (!this.state.isValid) { if (!this.state.isValid) {
...@@ -63,6 +65,18 @@ const asInput = (WrappedComponent) => { ...@@ -63,6 +65,18 @@ const asInput = (WrappedComponent) => {
return desc; return desc;
} }
handleBlur(event) {
if (this.props.validator) {
this.setState(this.props.validator);
}
this.props.onBlur(event.target.value, this.props.name);
}
handleChange(event) {
this.setState({ value: event.target.value });
this.props.onChange(event.target.value, this.props.name);
}
render() { render() {
const { description, error, describedBy } = this.getDescriptions(); const { description, error, describedBy } = this.getDescriptions();
...@@ -85,22 +99,15 @@ const asInput = (WrappedComponent) => { ...@@ -85,22 +99,15 @@ const asInput = (WrappedComponent) => {
NewComponent.displayName = `asInput(${getDisplayName(WrappedComponent)})`; NewComponent.displayName = `asInput(${getDisplayName(WrappedComponent)})`;
NewComponent.propTypes = { NewComponent.propTypes = inputProps;
label: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
value: PropTypes.string,
description: PropTypes.oneOfType([
PropTypes.string,
PropTypes.element,
]),
disabled: PropTypes.bool,
required: PropTypes.bool,
onChange: PropTypes.func,
};
NewComponent.defaultProps = { NewComponent.defaultProps = {
onChange: () => {}, onChange: () => {},
value: '', value: '',
description: undefined,
disabled: false,
required: false,
validator: () => {},
}; };
return NewComponent; return NewComponent;
......
...@@ -33,6 +33,13 @@ ...@@ -33,6 +33,13 @@
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/@kadira/storybook-channel/-/storybook-channel-1.1.0.tgz#806d1cdf2498d11cce09871a6fd27bbb41ed3564" resolved "https://registry.yarnpkg.com/@kadira/storybook-channel/-/storybook-channel-1.1.0.tgz#806d1cdf2498d11cce09871a6fd27bbb41ed3564"
"@kadira/storybook-deployer@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@kadira/storybook-deployer/-/storybook-deployer-1.2.0.tgz#1708f5cb37fa08ab4173b1bd99df6f4717dfae12"
dependencies:
git-url-parse "^6.0.2"
shelljs "^0.7.0"
"@kadira/storybook-ui@^3.10.1": "@kadira/storybook-ui@^3.10.1":
version "3.11.0" version "3.11.0"
resolved "https://registry.yarnpkg.com/@kadira/storybook-ui/-/storybook-ui-3.11.0.tgz#a5ccdcc479aa5e08465c58e7df493e37e4b2a14a" resolved "https://registry.yarnpkg.com/@kadira/storybook-ui/-/storybook-ui-3.11.0.tgz#a5ccdcc479aa5e08465c58e7df493e37e4b2a14a"
...@@ -2768,6 +2775,19 @@ getpass@^0.1.1: ...@@ -2768,6 +2775,19 @@ getpass@^0.1.1:
dependencies: dependencies:
assert-plus "^1.0.0" assert-plus "^1.0.0"
git-up@^2.0.0:
version "2.0.8"
resolved "https://registry.yarnpkg.com/git-up/-/git-up-2.0.8.tgz#24be049c9f0b193481d2df4e016a16530a5f4ef4"
dependencies:
is-ssh "^1.3.0"
parse-url "^1.3.0"
git-url-parse@^6.0.2:
version "6.2.2"
resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-6.2.2.tgz#be49024e14b8487553436b4572b8b439532fa871"
dependencies:
git-up "^2.0.0"
glob-base@^0.3.0: glob-base@^0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
...@@ -3223,6 +3243,12 @@ is-resolvable@^1.0.0: ...@@ -3223,6 +3243,12 @@ is-resolvable@^1.0.0:
dependencies: dependencies:
tryit "^1.0.1" tryit "^1.0.1"
is-ssh@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.0.tgz#ebea1169a2614da392a63740366c3ce049d8dff6"
dependencies:
protocols "^1.1.0"
is-stream@^1.0.1: is-stream@^1.0.1:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
...@@ -4008,6 +4034,13 @@ parse-json@^2.2.0: ...@@ -4008,6 +4034,13 @@ parse-json@^2.2.0:
dependencies: dependencies:
error-ex "^1.2.0" error-ex "^1.2.0"
parse-url@^1.3.0:
version "1.3.7"
resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-1.3.7.tgz#636cb6e32b88255c704e30ab4349676703267af8"
dependencies:
is-ssh "^1.3.0"
protocols "^1.4.0"
parseurl@~1.3.1: parseurl@~1.3.1:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
...@@ -4421,6 +4454,10 @@ prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@~15.5.7: ...@@ -4421,6 +4454,10 @@ prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@~15.5.7:
dependencies: dependencies:
fbjs "^0.8.9" fbjs "^0.8.9"
protocols@^1.1.0, protocols@^1.4.0:
version "1.4.5"
resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.5.tgz#21de1f441c4ef7094408ed9f1c94f7a114b87557"
proxy-addr@~1.1.3: proxy-addr@~1.1.3:
version "1.1.4" version "1.1.4"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3"
...@@ -5001,7 +5038,7 @@ shallowequal@0.2.x, shallowequal@^0.2.2: ...@@ -5001,7 +5038,7 @@ shallowequal@0.2.x, shallowequal@^0.2.2:
dependencies: dependencies:
lodash.keys "^3.1.2" lodash.keys "^3.1.2"
shelljs@^0.7.4, shelljs@^0.7.5: shelljs@^0.7.0, shelljs@^0.7.4, shelljs@^0.7.5:
version "0.7.7" version "0.7.7"
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1"
dependencies: dependencies:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment