├── .nvmrc
├── src
├── Maps
│ └── .gitkeep
├── AnchorButton
│ └── .gitkeep
├── ScrollToTop
│ ├── ScrollToTop.test.js
│ └── ScrollToTop.js
├── utils
│ └── isClient.js
├── styleConstants.js
├── StoryCard
│ ├── StoryFooter.css
│ ├── StoryCard.css
│ ├── StoryLink.js
│ ├── StoryCard.js
│ ├── StoryLink.css
│ ├── StoryCard.test.js
│ └── StoryFooter.js
├── Icon
│ └── Icon.js
├── Slider
│ ├── RcSlider.js
│ ├── SliderTooltip.js
│ ├── Slider.js
│ └── SliderBox.css
├── Hero
│ ├── CollectionHero.js
│ ├── Hero.js
│ └── Hero.css
├── Pie
│ ├── Pie.css
│ └── Pie.js
├── Logo
│ ├── LogoStandard.js
│ └── LogoAnimated.js
├── Dropdown
│ ├── Dropdown.styles.css
│ ├── Dropdown.test.js
│ └── Dropdown.js
├── Button
│ ├── Button.js
│ ├── Button.test.js
│ └── Button.styles.css
├── Sankey
│ ├── Sankey.css
│ └── Sankey.js
├── Navigation
│ ├── NavRouterLink.css
│ ├── NavSubMenu.js
│ ├── NavRouterLink.js
│ ├── Header.css
│ ├── Header.js
│ ├── Nav.js
│ └── Nav.css
├── BarChart
│ └── BarChart.js
├── Footer
│ ├── Footer.js
│ └── Footer.css
├── Tag
│ └── Tag.js
├── Media
│ └── Media.js
├── Scatterplot
│ └── Scatterplot.js
├── index.js
├── AreaChart
│ ├── AreaChart.test.js
│ └── AreaChart.js
├── ChartData
│ └── ChartData.js
├── RechartsPie
│ ├── RechartsPie.js
│ └── RechartsPie.test.js
├── LeafletMap
│ ├── LeafletMap.js
│ └── LeafletMap.test.js
├── constants.css
├── Share
│ └── ShareCollection.js
├── Chart
│ └── Chart.js
└── global.styles.css
├── index.js
├── lib
├── ScrollToTop
│ ├── ScrollToTop.test.js
│ ├── ScrollToTop.css
│ └── ScrollToTop.js
├── utils
│ └── isClient.js
├── StoryCard
│ ├── StoryFooter.css
│ ├── StoryCard.css
│ ├── StoryLink.css
│ ├── StoryCard.js
│ ├── StoryLink.js
│ ├── StoryCard.test.js
│ └── StoryFooter.js
├── styleConstants.js
├── Pie
│ ├── Pie.css
│ └── Pie.js
├── Dropdown
│ ├── Dropdown.styles.css
│ ├── Dropdown.test.js
│ └── Dropdown.js
├── Sankey
│ ├── Sankey.css
│ └── Sankey.js
├── Navigation
│ ├── NavRouterLink.css
│ ├── Header.css
│ ├── NavSubMenu.js
│ ├── NavRouterLink.js
│ ├── Nav.css
│ └── Header.js
├── Button
│ ├── Button.styles.css
│ ├── Button.test.js
│ └── Button.js
├── Icon
│ └── Icon.js
├── Hero
│ ├── Hero.css
│ ├── CollectionHero.js
│ └── Hero.js
├── Logo
│ ├── LogoStandard.js
│ ├── Logo.js
│ └── LogoAnimated.js
├── Slider
│ ├── RcSlider.js
│ ├── SliderBox.css
│ ├── Slider.js
│ └── SliderTooltip.js
├── Footer
│ ├── Footer.css
│ └── Footer.js
├── constants.css
├── Scatterplot
│ └── Scatterplot.js
├── BarChart
│ └── BarChart.js
├── AreaChart
│ ├── AreaChart.test.js
│ └── AreaChart.js
├── Media
│ └── Media.js
├── Tag
│ └── Tag.js
├── RechartsPie
│ ├── RechartsPie.test.js
│ └── RechartsPie.js
├── LeafletMap
│ ├── LeafletMap.test.js
│ └── LeafletMap.js
├── StamenMap
│ ├── StamenMap.test.js
│ └── StamenMap.js
├── global.styles.css
├── ChartData
│ └── ChartData.js
├── DropdownMenu
│ └── DropdownMenu.js
├── Share
│ └── ShareCollection.js
└── index.js
├── .gitignore
├── .npmignore
├── .babelrc
├── .storybook
├── head.html
├── addons.js
├── config.js
└── webpack.config.js
├── assets
├── data-pattern-trans.png
├── civic-logo-animated.svg
└── civic-logo.svg
├── dist
├── 2273e3d8ad9264b7daa5bdbf8e6b47f8.png
├── 4f0283c6ce28e888000e978e537a6a56.png
└── a6137456ed160d7606981aa57c559898.png
├── mocha.options
├── .editorconfig
├── stories
├── Footer.story.js
├── Scatterplot.story.js
├── BarChart.story.js
├── ScrollToTop.story.js
├── Button.story.js
├── Hero.story.js
├── Sankey.story.js
├── StoryFooter.story.js
├── AreaChart.story.js
├── Editable.story.js
├── Dropdown.story.js
├── Header.story.js
├── Slider.story.js
├── RechartsPie.story.js
├── index.js
├── shared.js
├── StoryLink.story.js
├── Welcome.js
├── Pie.story.js
├── StoryCard.story.js
└── LeafletMap.story.js
├── mocha.conf.js
├── README.md
├── .eslintrc
└── package.json
/.nvmrc:
--------------------------------------------------------------------------------
1 | 6.9.5
2 |
--------------------------------------------------------------------------------
/src/Maps/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/AnchorButton/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | // require('./dist/index.js');
--------------------------------------------------------------------------------
/src/ScrollToTop/ScrollToTop.test.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/ScrollToTop/ScrollToTop.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log
3 | .DS_Store
4 | .dev
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log
3 | .DS_Store
4 | .dev
5 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["react", "es2015", "stage-1"],
3 | }
--------------------------------------------------------------------------------
/lib/ScrollToTop/ScrollToTop.css:
--------------------------------------------------------------------------------
1 | .RemoveUnderline {
2 | border-bottom: none;
3 | }
4 |
--------------------------------------------------------------------------------
/src/utils/isClient.js:
--------------------------------------------------------------------------------
1 | const isClient = typeof document !== 'undefined';
2 |
3 | export default isClient;
--------------------------------------------------------------------------------
/.storybook/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/assets/data-pattern-trans.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackoregon/component-library/HEAD/assets/data-pattern-trans.png
--------------------------------------------------------------------------------
/dist/2273e3d8ad9264b7daa5bdbf8e6b47f8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackoregon/component-library/HEAD/dist/2273e3d8ad9264b7daa5bdbf8e6b47f8.png
--------------------------------------------------------------------------------
/dist/4f0283c6ce28e888000e978e537a6a56.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackoregon/component-library/HEAD/dist/4f0283c6ce28e888000e978e537a6a56.png
--------------------------------------------------------------------------------
/dist/a6137456ed160d7606981aa57c559898.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackoregon/component-library/HEAD/dist/a6137456ed160d7606981aa57c559898.png
--------------------------------------------------------------------------------
/.storybook/addons.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-extraneous-dependencies */
2 | import '@kadira/storybook/addons';
3 | import '@kadira/storybook-addon-knobs/register';
--------------------------------------------------------------------------------
/lib/utils/isClient.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | var isClient = typeof document !== 'undefined';
7 |
8 | exports.default = isClient;
--------------------------------------------------------------------------------
/mocha.options:
--------------------------------------------------------------------------------
1 | --require mocha-clean
2 | --require babel-register
3 | --require ignore-styles
4 | --require source-map-support/register
5 | --colors
6 | --recursive
7 | --require ./mocha.conf.js
8 | --ui bdd
--------------------------------------------------------------------------------
/src/styleConstants.js:
--------------------------------------------------------------------------------
1 | export const ICONS = {
2 | eye: 'fa fa-eye',
3 | link: 'fa fa-link',
4 | check: 'fa fa-check',
5 | download: 'fa fa-cloud-download',
6 | hamburger: 'fa fa-bars fa-2x',
7 | };
8 |
--------------------------------------------------------------------------------
/lib/StoryCard/StoryFooter.css:
--------------------------------------------------------------------------------
1 | .footerlinks {
2 | padding: 24px;
3 | display: flex;
4 | flex-direction: row;
5 | justify-content: center;
6 | }
7 |
8 | .footerlinks div:first-child {
9 | margin-right: 32px;
10 | }
11 |
--------------------------------------------------------------------------------
/src/StoryCard/StoryFooter.css:
--------------------------------------------------------------------------------
1 | .footerlinks {
2 | padding: 24px;
3 | display: flex;
4 | flex-direction: row;
5 | justify-content: center;
6 | }
7 |
8 | .footerlinks div:first-child {
9 | margin-right: 32px;
10 | }
11 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/lib/styleConstants.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | var ICONS = exports.ICONS = {
7 | eye: 'fa fa-eye',
8 | link: 'fa fa-link',
9 | check: 'fa fa-check',
10 | download: 'fa fa-cloud-download',
11 | hamburger: 'fa fa-bars fa-2x'
12 | };
--------------------------------------------------------------------------------
/.storybook/config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-extraneous-dependencies */
2 | import { configure, setAddon } from '@kadira/storybook';
3 | import infoAddon from '@kadira/react-storybook-addon-info';
4 |
5 | setAddon(infoAddon);
6 |
7 | function loadStories() {
8 | require('../stories');
9 | }
10 |
11 | configure(loadStories, module);
12 |
--------------------------------------------------------------------------------
/src/Icon/Icon.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Icon = ({ className, handleClick }) => (
4 |
5 | );
6 |
7 | Icon.propTypes = {
8 | className: React.PropTypes.string,
9 | handleClick: React.PropTypes.func,
10 | };
11 |
12 | export default Icon;
13 |
--------------------------------------------------------------------------------
/src/Slider/RcSlider.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactSlider from 'rc-slider';
3 |
4 | const RcSlider = ({ min, max, value, onChange }) => (
5 |
14 | );
15 |
16 | export default RcSlider;
17 |
--------------------------------------------------------------------------------
/lib/StoryCard/StoryCard.css:
--------------------------------------------------------------------------------
1 | /* StoryCard Styles */
2 |
3 | .card {
4 | width: 100%;
5 | max-width: 1200px;
6 | padding: 60px 0px 30px 0px;
7 | margin: 0 auto;
8 | border-bottom: 1px solid rgba(243,242,243,1);
9 | }
10 |
11 | .card h2 {
12 | text-align: center;
13 | }
14 |
15 | .description {
16 | width: 100%;
17 | max-width: 800px;
18 | margin: 0 auto;
19 | text-align: left;
20 | }
21 |
--------------------------------------------------------------------------------
/src/StoryCard/StoryCard.css:
--------------------------------------------------------------------------------
1 | /* StoryCard Styles */
2 |
3 | .card {
4 | width: 100%;
5 | max-width: 1200px;
6 | padding: 60px 0px 30px 0px;
7 | margin: 0 auto;
8 | border-bottom: 1px solid rgba(243,242,243,1);
9 | }
10 |
11 | .card h2 {
12 | text-align: center;
13 | }
14 |
15 | .description {
16 | width: 100%;
17 | max-width: 800px;
18 | margin: 0 auto;
19 | text-align: left;
20 | }
21 |
--------------------------------------------------------------------------------
/lib/Pie/Pie.css:
--------------------------------------------------------------------------------
1 | /* Pie & Donut visualization */
2 |
3 | .donut-title {
4 | font-family: 'Roboto Condensed', sans-serif;
5 | font-size: 1.5rem;
6 | font-weight: 500;
7 | color: #220f25;
8 | fill: #220f25;
9 | }
10 |
11 | .donut-subtitle {
12 | font-family: 'Roboto Condensed', sans-serif;
13 | font-weight: 400;
14 | color: #706371;
15 | fill: #706371;
16 | text-transform: uppercase;
17 | }
18 |
--------------------------------------------------------------------------------
/src/Hero/CollectionHero.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Hero from './Hero';
3 | import Tag from '../Tag/Tag';
4 | import Share from '../Share/ShareCollection';
5 |
6 | const CollectionHero = props => (
7 |
8 |
9 | {props.title}
10 |
11 |
12 | );
13 |
14 | export default CollectionHero;
15 |
--------------------------------------------------------------------------------
/src/Pie/Pie.css:
--------------------------------------------------------------------------------
1 | /* Pie & Donut visualization */
2 |
3 | .donut-title {
4 | font-family: 'Roboto Condensed', sans-serif;
5 | font-size: 1.5rem;
6 | font-weight: 500;
7 | color: #220f25;
8 | fill: #220f25;
9 | }
10 |
11 | .donut-subtitle {
12 | font-family: 'Roboto Condensed', sans-serif;
13 | font-weight: 400;
14 | color: #706371;
15 | fill: #706371;
16 | text-transform: uppercase;
17 | }
18 |
--------------------------------------------------------------------------------
/src/Logo/LogoStandard.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import isClient from '../utils/isClient';
3 |
4 | const styles = {
5 | height: '80px',
6 | width: 'auto',
7 | };
8 |
9 | const LogoStandard = () => (
10 |
15 | );
16 |
17 | export default LogoStandard;
18 |
--------------------------------------------------------------------------------
/src/Logo/LogoAnimated.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import isClient from '../utils/isClient';
3 |
4 | const styles = {
5 | height: '80px',
6 | width: 'auto',
7 | };
8 |
9 | const Logo = ({ alt }) => (isClient && );
10 |
11 | Logo.displayName = 'Logo';
12 | Logo.propTypes = {
13 | alt: PropTypes.string,
14 | };
15 |
16 | export default Logo;
17 |
--------------------------------------------------------------------------------
/lib/Dropdown/Dropdown.styles.css:
--------------------------------------------------------------------------------
1 |
2 | .base {
3 | border: 1px solid #eee;
4 | border-radius: 3px;
5 | background-color: #FFFFFF;
6 | cursor: pointer;
7 | font-size: 15px;
8 | padding: 3px 10px;
9 | margin: 10px;
10 | }
11 |
12 | .content {
13 | background-color: rgba(44, 45, 85, 1);
14 | }
15 |
16 | /* Have to add div selector to bump up specificity */
17 | div:global(.Select-control) {
18 | border-radius: 0px;
19 | }
20 |
21 | /*
22 | span:global(.Select-arrow) {
23 | border-color: rgba(238,73,92,1) transparent transparent;
24 | }*/
25 |
--------------------------------------------------------------------------------
/src/Dropdown/Dropdown.styles.css:
--------------------------------------------------------------------------------
1 |
2 | .base {
3 | border: 1px solid #eee;
4 | border-radius: 3px;
5 | background-color: #FFFFFF;
6 | cursor: pointer;
7 | font-size: 15px;
8 | padding: 3px 10px;
9 | margin: 10px;
10 | }
11 |
12 | .content {
13 | background-color: rgba(44, 45, 85, 1);
14 | }
15 |
16 | /* Have to add div selector to bump up specificity */
17 | div:global(.Select-control) {
18 | border-radius: 0px;
19 | }
20 |
21 | /*
22 | span:global(.Select-arrow) {
23 | border-color: rgba(238,73,92,1) transparent transparent;
24 | }*/
25 |
--------------------------------------------------------------------------------
/stories/Footer.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import { Footer } from '../src';
4 |
5 | const displayName = Footer.displayName || 'Footer';
6 | const description = 'A basic footer';
7 | const title = 'Simple Usage';
8 |
9 | const demoCode = () => (
10 |
11 | );
12 |
13 | const propDocs = { inline: true, propTables: [Footer] };
14 |
15 | export default () => storiesOf(displayName, module)
16 | .addWithInfo(
17 | title,
18 | description,
19 | demoCode,
20 | propDocs,
21 | );
22 |
--------------------------------------------------------------------------------
/src/Button/Button.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import classNames from 'classnames/bind';
3 | import styles from './Button.styles.css';
4 |
5 | const cx = classNames.bind(styles);
6 |
7 | const className = cx({ base: true });
8 |
9 | const Button = ({ children, onClick }) => (
10 |
11 | {children}
12 |
13 | );
14 |
15 | Button.displayName = 'Button';
16 |
17 | Button.propTypes = {
18 | children: React.PropTypes.string,
19 | onClick: React.PropTypes.func,
20 | };
21 |
22 | export default Button;
23 |
--------------------------------------------------------------------------------
/lib/Sankey/Sankey.css:
--------------------------------------------------------------------------------
1 | .sankeyChart {
2 | margin-bottom: 20px;
3 | }
4 |
5 | .sankeyNode rect {
6 | fill: #999;
7 | shape-rendering: crispEdges;
8 | }
9 |
10 | .sankeyNode {
11 | fill-opacity: .6;
12 | }
13 |
14 | .sankeyNode:hover {
15 | cursor: pointer;
16 | fill-opacity: 1;
17 | }
18 |
19 | .sankeyNode text {
20 | fill: #555;
21 | stroke: none;
22 | font-size: .75em;
23 | }
24 |
25 | .sankeyLink {
26 | stroke: #cccccc;
27 | stroke-opacity: .4;
28 | fill: none;
29 | }
30 |
31 | .sankeyLink:hover {
32 | stroke-opacity: .8;
33 | cursor: pointer;
34 | }
35 |
--------------------------------------------------------------------------------
/src/Sankey/Sankey.css:
--------------------------------------------------------------------------------
1 | .sankeyChart {
2 | margin-bottom: 20px;
3 | }
4 |
5 | .sankeyNode rect {
6 | fill: #999;
7 | shape-rendering: crispEdges;
8 | }
9 |
10 | .sankeyNode {
11 | fill-opacity: .6;
12 | }
13 |
14 | .sankeyNode:hover {
15 | cursor: pointer;
16 | fill-opacity: 1;
17 | }
18 |
19 | .sankeyNode text {
20 | fill: #555;
21 | stroke: none;
22 | font-size: .75em;
23 | }
24 |
25 | .sankeyLink {
26 | stroke: #cccccc;
27 | stroke-opacity: .4;
28 | fill: none;
29 | }
30 |
31 | .sankeyLink:hover {
32 | stroke-opacity: .8;
33 | cursor: pointer;
34 | }
35 |
--------------------------------------------------------------------------------
/src/Hero/Hero.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './Hero.css';
3 |
4 | const DefaultChildren = () => (
5 |
Data for the people, by the people.
6 | );
7 |
8 | const Hero = ({ children }) => (
9 |
10 |
11 |
12 | {children || }
13 |
14 |
15 |
16 | );
17 |
18 | Hero.displayName = 'Hero';
19 |
20 | Hero.propTypes = {
21 | children: React.PropTypes.node,
22 | };
23 |
24 | export default Hero;
25 |
--------------------------------------------------------------------------------
/src/Button/Button.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import Button from './Button';
4 |
5 | describe('Button', () => {
6 | const testString = 'Hello';
7 | const wrapper = shallow({testString} );
8 | it('should render a button', () => {
9 | expect(wrapper.find('button')).to.have.length(1);
10 | });
11 | it('should render with class base', () => {
12 | expect(wrapper.props().className).to.contain('base');
13 | });
14 | it('should have the appropriate child text', () => {
15 | expect(wrapper.text()).to.eql(testString);
16 | });
17 | });
--------------------------------------------------------------------------------
/stories/Scatterplot.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import { Scatterplot } from '../src';
4 |
5 | const displayName = Scatterplot.displayName || 'Scatterplot';
6 | const title = 'Simple usage';
7 | const description = `
8 | Scatterplot build with Recharts.`;
9 |
10 | const demoCode = () => (
11 |
12 | );
13 |
14 | const propDocs = { inline: true, propTables: [Scatterplot] };
15 |
16 | export default () => storiesOf(displayName, module)
17 | .addWithInfo(
18 | title,
19 | description,
20 | demoCode,
21 | propDocs,
22 | );
23 |
--------------------------------------------------------------------------------
/lib/Navigation/NavRouterLink.css:
--------------------------------------------------------------------------------
1 | .NavRouterLink a {
2 | color: rgba(255,255,255,.65);
3 | flex: 1;
4 | display: block;
5 | font-family: 'Rubik', sans-serif;
6 | font-size: 1.25rem;
7 | border: none;
8 | font-weight: 500;
9 | text-transform: uppercase;
10 | text-decoration: none;
11 | padding: 1rem;
12 | text-align: center;
13 | }
14 |
15 | .NavRouterLink a:focus {
16 | color: rgba(255,255,255,.85);
17 | }
18 |
19 | .NavRouterLink a:hover {
20 | color: rgba(255,255,255,.85);
21 | text-decoration: none;
22 | }
23 |
24 | .NavRouterLink a:active {
25 | color: rgba(255,255,255,.85);
26 | }
27 |
--------------------------------------------------------------------------------
/src/Navigation/NavRouterLink.css:
--------------------------------------------------------------------------------
1 | .NavRouterLink a {
2 | color: rgba(255,255,255,.65);
3 | flex: 1;
4 | display: block;
5 | font-family: 'Rubik', sans-serif;
6 | font-size: 1.25rem;
7 | border: none;
8 | font-weight: 500;
9 | text-transform: uppercase;
10 | text-decoration: none;
11 | padding: 1rem;
12 | text-align: center;
13 | }
14 |
15 | .NavRouterLink a:focus {
16 | color: rgba(255,255,255,.85);
17 | }
18 |
19 | .NavRouterLink a:hover {
20 | color: rgba(255,255,255,.85);
21 | text-decoration: none;
22 | }
23 |
24 | .NavRouterLink a:active {
25 | color: rgba(255,255,255,.85);
26 | }
27 |
--------------------------------------------------------------------------------
/src/BarChart/BarChart.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import {
3 | BarChart, XAxis, YAxis, CartesianGrid, Tooltip, Legend, Bar,
4 | } from 'recharts';
5 |
6 | const HorizontalBarChart = ({ data }) =>
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | ;
16 |
17 | HorizontalBarChart.propTypes = {
18 | data: PropTypes.arrayOf(PropTypes.object),
19 | };
20 |
21 | export default HorizontalBarChart;
--------------------------------------------------------------------------------
/src/Footer/Footer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import LogoStandard from '../Logo/LogoStandard';
3 | import ScrollToTop from '../ScrollToTop/ScrollToTop';
4 | import styles from './Footer.css';
5 |
6 | const Footer = () => (
7 |
8 |
© Copyright {(new Date()).getFullYear()}
9 |
10 |
11 |
12 |
13 | );
14 |
15 | Footer.displayName = 'Footer';
16 |
17 | export default Footer;
18 | // src={isClient ? require('../../assets/civic-logo-stack_standard.svg') : ''}
19 |
--------------------------------------------------------------------------------
/src/ScrollToTop/ScrollToTop.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Icon from '../Icon/Icon';
3 |
4 | const hashToGoToTop = '#';
5 | const styles = { display: 'flex', flexDirection: 'column', textAlign: 'center' };
6 |
7 | const ScrollToTop = ({ iconStyle = null }) => (
8 |
18 | );
19 |
20 | ScrollToTop.displayName = 'ScrollToTop';
21 | ScrollToTop.propTypes = {
22 | iconStyle: React.PropTypes.string,
23 | };
24 |
25 | export default ScrollToTop;
26 |
--------------------------------------------------------------------------------
/src/Slider/SliderTooltip.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const SliderTooltip = ({ value }) => (
4 |
5 |
6 |
7 | $ { value.toFixed(2) } /hour
8 | $ { value * 8 } /day
9 | $ { Math.round(value * 8 * 5) } /week
10 | $ { value * 8 * 22 } /month
11 | $ { value * 8 * 22 * 12 } /year
12 |
13 |
14 |
15 | );
16 |
17 | export default SliderTooltip;
18 |
--------------------------------------------------------------------------------
/src/Tag/Tag.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled from 'styled-components';
3 | import { Link } from 'react-router';
4 |
5 | const StyledLink = styled(Link)`
6 | padding: 6px 6px 6px 6px;
7 | text-align: center;
8 | transition: all .2s ease-in-out;
9 | font-size: 1em;
10 | font-weight: 500;
11 | color: rgba(255, 255, 255, 1);
12 | cursor: pointer;
13 | border: 2px solid rgba(255, 255, 255, 1);
14 | `;
15 |
16 | const Tag = props => (
17 | {props.name}
18 | );
19 |
20 | Tag.displayName = 'Tag';
21 | Tag.propTypes = {
22 | location: React.PropTypes.string,
23 | name: React.PropTypes.string,
24 | };
25 |
26 | export default Tag;
27 |
--------------------------------------------------------------------------------
/src/StoryCard/StoryLink.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { Link } from 'react-router';
3 | import styles from './StoryLink.css';
4 |
5 | const StoryLink = ({ children, icon, route, action }) => (
6 |
7 | {route
8 | ?
{children}
9 | :
{children}
10 | }
11 |
12 | );
13 |
14 | StoryLink.displayName = 'StoryLink';
15 | StoryLink.propTypes = {
16 | action: PropTypes.func,
17 | children: PropTypes.node,
18 | icon: PropTypes.string,
19 | route: PropTypes.string,
20 | };
21 |
22 | export default StoryLink;
23 |
--------------------------------------------------------------------------------
/stories/BarChart.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import { BarChart } from '../src';
4 |
5 | const displayName = BarChart.displayName || 'BarChart';
6 | const title = 'Simple usage';
7 | const description = `
8 | This is some basic usage with the button with providing a label to show the text.
9 | Clicking should trigger an action.`;
10 |
11 | const demoCode = () => (
12 |
13 | );
14 |
15 | const propDocs = { inline: true, propTables: [BarChart] };
16 |
17 | export default () => storiesOf(displayName, module)
18 | .addWithInfo(
19 | title,
20 | description,
21 | demoCode,
22 | propDocs,
23 | );
--------------------------------------------------------------------------------
/lib/Button/Button.styles.css:
--------------------------------------------------------------------------------
1 | button.base {
2 | display: flex;
3 | padding: 6px 6px 6px 6px;
4 | flex-wrap: nowrap;
5 | align-items: center;
6 | justify-content: space-between;
7 | transition: all .2s ease-in-out;
8 | font-size: 1em;
9 | font-weight: 500;
10 | color: rgba(238, 73, 80, 1);
11 | cursor: pointer;
12 | font-weight: 600;
13 | }
14 |
15 | .base {
16 | border: 2px solid rgba(238, 73, 80, 1);
17 | }
18 |
19 | .base i {
20 | margin-right: 12px;
21 | }
22 |
23 | .base span {
24 | flex-wrap: nowrap;
25 | transition: all .2s ease-in-out;
26 | }
27 |
28 | .base:hover {
29 | background-color: rgba(238, 73, 80, 1);
30 | color: #fff;
31 | }
32 |
33 | .base:focus {
34 | outline: none;
35 | }
--------------------------------------------------------------------------------
/src/Button/Button.styles.css:
--------------------------------------------------------------------------------
1 | button.base {
2 | display: flex;
3 | padding: 6px 6px 6px 6px;
4 | flex-wrap: nowrap;
5 | align-items: center;
6 | justify-content: space-between;
7 | transition: all .2s ease-in-out;
8 | font-size: 1em;
9 | font-weight: 500;
10 | color: rgba(238, 73, 80, 1);
11 | cursor: pointer;
12 | font-weight: 600;
13 | }
14 |
15 | .base {
16 | border: 2px solid rgba(238, 73, 80, 1);
17 | }
18 |
19 | .base i {
20 | margin-right: 12px;
21 | }
22 |
23 | .base span {
24 | flex-wrap: nowrap;
25 | transition: all .2s ease-in-out;
26 | }
27 |
28 | .base:hover {
29 | background-color: rgba(238, 73, 80, 1);
30 | color: #fff;
31 | }
32 |
33 | .base:focus {
34 | outline: none;
35 | }
--------------------------------------------------------------------------------
/src/StoryCard/StoryCard.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import StoryFooter from './StoryFooter';
3 | import styles from './StoryCard.css';
4 |
5 | const StoryCard = ({ cardId, collectionId, title, children }) => (
6 |
7 |
{title}
8 |
9 | {children}
10 |
11 |
12 |
13 | );
14 |
15 | StoryCard.displayName = 'StoryCard';
16 |
17 | StoryCard.propTypes = {
18 | title: PropTypes.string,
19 | cardId: PropTypes.string,
20 | collectionId: PropTypes.string,
21 | children: PropTypes.node,
22 | };
23 |
24 | export default StoryCard;
25 |
--------------------------------------------------------------------------------
/lib/StoryCard/StoryLink.css:
--------------------------------------------------------------------------------
1 | .storylink {
2 | border-bottom: 2px solid rgba(238, 73, 80, 1);
3 | transition: all .2s ease-in-out;
4 | }
5 |
6 | .storylink a {
7 | display: flex;
8 | padding: 6px 6px 6px 6px;
9 | flex-wrap: nowrap;
10 | align-items: center;
11 | justify-content: space-between;
12 | font-family: 'Rubik', sans-serif;
13 | font-weight: 500;
14 | border-bottom: none; /* this is only because our global styles assign a border-bottom that we need to override */
15 | }
16 |
17 | .storylink a i {
18 | margin-right: 12px;
19 | }
20 |
21 | .storylink span {
22 | flex-wrap: nowrap;
23 | }
24 |
25 | .storylink a:hover {
26 | background-color: rgba(238, 73, 80, 1);
27 | color: #fff;
28 | }
29 |
30 | .storylink a:focus {
31 | outline: none;
32 | }
33 |
--------------------------------------------------------------------------------
/src/Navigation/NavSubMenu.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router';
3 | import styles from './Nav.css';
4 |
5 | const pathOrName = (p, n) => p || `/${n.toLowerCase()}`;
6 |
7 | const NavSubMenu = ({ items, isVisible }) => (
8 |
9 | {items.map((item, index) => (
10 |
11 | {item.name}
12 |
13 | ))
14 | }
15 |
16 | );
17 |
18 | NavSubMenu.displayName = 'NavSubMenu';
19 | NavSubMenu.propTypes = {
20 | items: React.PropTypes.arrayOf(React.PropTypes.shape({})),
21 | isVisible: React.PropTypes.bool,
22 | };
23 |
24 | export default NavSubMenu;
25 |
--------------------------------------------------------------------------------
/src/StoryCard/StoryLink.css:
--------------------------------------------------------------------------------
1 | .storylink {
2 | border-bottom: 2px solid rgba(238, 73, 80, 1);
3 | transition: all .2s ease-in-out;
4 | }
5 |
6 | .storylink a {
7 | display: flex;
8 | padding: 6px 6px 6px 6px;
9 | flex-wrap: nowrap;
10 | align-items: center;
11 | justify-content: space-between;
12 | font-family: 'Rubik', sans-serif;
13 | font-weight: 500;
14 | border-bottom: none; /* this is only because our global styles assign a border-bottom that we need to override */
15 | }
16 |
17 | .storylink a i {
18 | margin-right: 12px;
19 | }
20 |
21 | .storylink span {
22 | flex-wrap: nowrap;
23 | }
24 |
25 | .storylink a:hover {
26 | background-color: rgba(238, 73, 80, 1);
27 | color: #fff;
28 | }
29 |
30 | .storylink a:focus {
31 | outline: none;
32 | }
33 |
--------------------------------------------------------------------------------
/lib/Icon/Icon.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require("react");
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12 |
13 | var Icon = function Icon(_ref) {
14 | var className = _ref.className,
15 | handleClick = _ref.handleClick;
16 | return _react2.default.createElement(
17 | "span",
18 | null,
19 | _react2.default.createElement("i", { onClick: handleClick, className: className, "aria-hidden": "true" })
20 | );
21 | };
22 |
23 | Icon.propTypes = {
24 | className: _react2.default.PropTypes.string,
25 | handleClick: _react2.default.PropTypes.func
26 | };
27 |
28 | exports.default = Icon;
--------------------------------------------------------------------------------
/lib/Hero/Hero.css:
--------------------------------------------------------------------------------
1 | /* hero Styles */
2 |
3 | .hero {
4 | display: flex;
5 | /*position: absolute;*/
6 | background-color: rgba(34, 15, 37,1);
7 | height: 75vh;
8 | min-height: 420px;
9 | width: 100%;
10 | margin: 0;
11 | padding: 0;
12 | background-size: cover;
13 | background-position: center center;
14 | z-index: -100;
15 | align-items: center;
16 | justify-content: center;
17 | }
18 |
19 | .container {
20 | display: flex;
21 | width: 100%;
22 | max-width: 800px;
23 | }
24 |
25 | .content {
26 | position: relative;
27 | padding-top: 0px;
28 | }
29 |
30 | .content > h1 {
31 | font-size: 3em;
32 | line-height: 1.25em;
33 | color: rgba(255,255,255,1);
34 | font-weight: 100;
35 | }
36 |
37 | @media small {
38 | .container {
39 | padding: 0px 15px;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Hero/Hero.css:
--------------------------------------------------------------------------------
1 | /* hero Styles */
2 |
3 | .hero {
4 | display: flex;
5 | /*position: absolute;*/
6 | background-color: rgba(34, 15, 37,1);
7 | height: 75vh;
8 | min-height: 420px;
9 | width: 100%;
10 | margin: 0;
11 | padding: 0;
12 | background-size: cover;
13 | background-position: center center;
14 | z-index: -100;
15 | align-items: center;
16 | justify-content: center;
17 | }
18 |
19 | .container {
20 | display: flex;
21 | width: 100%;
22 | max-width: 800px;
23 | }
24 |
25 | .content {
26 | position: relative;
27 | padding-top: 0px;
28 | }
29 |
30 | .content > h1 {
31 | font-size: 3em;
32 | line-height: 1.25em;
33 | color: rgba(255,255,255,1);
34 | font-weight: 100;
35 | }
36 |
37 | @media small {
38 | .container {
39 | padding: 0px 15px;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/Logo/LogoStandard.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _isClient = require('../utils/isClient');
12 |
13 | var _isClient2 = _interopRequireDefault(_isClient);
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | var styles = {
18 | height: '80px',
19 | width: 'auto'
20 | };
21 |
22 | var LogoStandard = function LogoStandard() {
23 | return _react2.default.createElement('img', {
24 | alt: 'Hack Oregon footer logo',
25 | src: _isClient2.default ? require('../../assets/civic-logo-stack_standard.svg') : '',
26 | style: styles
27 | });
28 | };
29 |
30 | exports.default = LogoStandard;
--------------------------------------------------------------------------------
/src/Media/Media.js:
--------------------------------------------------------------------------------
1 | import isClient from '../utils/isClient';
2 |
3 | // these sizes are arbitrary and you can set them to whatever you wish
4 | import { css } from 'styled-components';
5 |
6 | const sizes = {
7 | giant: 1170,
8 | desktop: 992,
9 | tablet: 768,
10 | phone: 376,
11 | };
12 |
13 | // iterate through the sizes and create a media template
14 | const media = Object.keys(sizes).reduce((accumulator, label) => {
15 | // use em in breakpoints to work properly cross-browser and support users
16 | // changing their browsers font-size: https://zellwk.com/blog/media-query-units/
17 | const pxSize = sizes[label] / 16;
18 | accumulator[label] = (...args) => css`
19 | @media (max-width: ${pxSize}px) {
20 | ${css(...args)}
21 | }
22 | `;
23 | return accumulator;
24 | }, {});
25 |
26 | export default media;
27 |
--------------------------------------------------------------------------------
/src/Scatterplot/Scatterplot.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Tooltip } from 'recharts';
3 |
4 | const data = [{ x: 100, y: 200, z: 200 }, { x: 120, y: 100, z: 260 },
5 | { x: 170, y: 300, z: 400 }, { x: 140, y: 250, z: 280 },
6 | { x: 150, y: 400, z: 500 }, { x: 110, y: 280, z: 200 }];
7 |
8 | const Scatterplot = () => (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | );
17 |
18 | export default Scatterplot;
19 |
--------------------------------------------------------------------------------
/src/Slider/Slider.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import SliderTooltip from './SliderTooltip';
3 | import RcSlider from './RcSlider';
4 | import isClient from '../utils/isClient';
5 |
6 | const Slider = ({ value, onChange, min, max }) => {
7 | if (isClient) {
8 | require('!style-loader!css-loader!rc-slider/assets/index.css'); // eslint-disable-line
9 | require('!style-loader!css-loader!./SliderBox.css'); // eslint-disable-line
10 | }
11 | return (
12 |
13 |
14 |
15 |
16 | );
17 | };
18 | Slider.propTypes = {
19 | value: React.PropTypes.number,
20 | onChange: React.PropTypes.func,
21 | max: React.PropTypes.number,
22 | min: React.PropTypes.number,
23 | };
24 |
25 | export default Slider;
26 |
--------------------------------------------------------------------------------
/lib/Logo/Logo.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _isClient = require('../utils/isClient');
12 |
13 | var _isClient2 = _interopRequireDefault(_isClient);
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | var styles = {
18 | height: '80px',
19 | width: 'auto'
20 | };
21 |
22 | var Logo = function Logo(_ref) {
23 | var alt = _ref.alt;
24 | return _isClient2.default && _react2.default.createElement('img', { style: styles, src: require('../../assets/civic-logo-invert-animated.svg'), alt: alt });
25 | };
26 |
27 | Logo.displayName = 'Logo';
28 | Logo.propTypes = {
29 | alt: _react.PropTypes.string
30 | };
31 |
32 | exports.default = Logo;
--------------------------------------------------------------------------------
/stories/ScrollToTop.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf, action } from '@kadira/storybook';
3 | import { ScrollToTop } from '../src';
4 |
5 | const displayName = ScrollToTop.displayName || 'ScrollToTop';
6 | const title = 'Simple usage';
7 | const description = `
8 | This is some basic usage with the ScrollToTop component. Provide text to show in the scroll to link tag.`;
9 |
10 | const demoCode = () => (
11 | Back To Top
12 | );
13 |
14 | const propDocs = { inline: true, propTables: [ScrollToTop] };
15 |
16 | const altDemo = () => (
17 | 👟 🐋
18 | );
19 |
20 | const altTitle = 'with some emoji';
21 |
22 | export default () => storiesOf(displayName, module)
23 | .addWithInfo(
24 | title,
25 | description,
26 | demoCode,
27 | propDocs,
28 | )
29 | .add(altTitle, altDemo);
30 |
--------------------------------------------------------------------------------
/lib/Logo/LogoAnimated.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _isClient = require('../utils/isClient');
12 |
13 | var _isClient2 = _interopRequireDefault(_isClient);
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | var styles = {
18 | height: '80px',
19 | width: 'auto'
20 | };
21 |
22 | var Logo = function Logo(_ref) {
23 | var alt = _ref.alt;
24 | return _isClient2.default && _react2.default.createElement('img', { style: styles, src: require('../../assets/civic-logo-invert-animated.svg'), alt: alt });
25 | };
26 |
27 | Logo.displayName = 'Logo';
28 | Logo.propTypes = {
29 | alt: _react.PropTypes.string
30 | };
31 |
32 | exports.default = Logo;
--------------------------------------------------------------------------------
/src/Navigation/NavRouterLink.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { Link } from 'react-router';
3 | import styles from './NavRouterLink.css';
4 |
5 | const pathOrName = (p, n) => p || `/${n.toLowerCase()}`;
6 |
7 | const NavRouterLink = ({ path, customStyles, name }) => {
8 | const boxStyle = customStyles ? customStyles.box : null;
9 | const linkStyle = customStyles ? customStyles.link : null;
10 | const pathTo = pathOrName(path, name);
11 |
12 | return (
13 |
14 |
15 | {name}
16 |
17 |
18 |
19 | );
20 | };
21 |
22 | NavRouterLink.propTypes = {
23 | name: PropTypes.string,
24 | path: PropTypes.string,
25 | customStyles: PropTypes.object,
26 | };
27 |
28 | export default NavRouterLink;
29 |
--------------------------------------------------------------------------------
/lib/Slider/RcSlider.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _rcSlider = require('rc-slider');
12 |
13 | var _rcSlider2 = _interopRequireDefault(_rcSlider);
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | var RcSlider = function RcSlider(_ref) {
18 | var min = _ref.min,
19 | max = _ref.max,
20 | value = _ref.value,
21 | onChange = _ref.onChange;
22 | return _react2.default.createElement(_rcSlider2.default, {
23 | className: 'slider',
24 | min: min,
25 | max: max,
26 | step: 0.25,
27 | value: value,
28 | onChange: onChange,
29 | tipTransitionName: 'zoom-down'
30 | });
31 | };
32 |
33 | exports.default = RcSlider;
--------------------------------------------------------------------------------
/stories/Button.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf, action } from '@kadira/storybook';
3 | import { Button } from '../src';
4 |
5 | const displayName = Button.displayName || 'Button';
6 | const title = 'Simple usage';
7 | const description = `
8 | This is some basic usage with the button with providing a label to show the text.
9 | Clicking should trigger an action.`;
10 |
11 | const demoCode = () => (
12 | Hello Button
13 | );
14 |
15 | const propDocs = { inline: true, propTables: [Button] };
16 |
17 | const altDemo = () => (
18 | 😀 😎 👍 💯
19 | );
20 |
21 | const altTitle = 'with some emoji';
22 |
23 | export default () => storiesOf(displayName, module)
24 | .addWithInfo(
25 | title,
26 | description,
27 | demoCode,
28 | propDocs,
29 | )
30 | .add(altTitle, altDemo);
--------------------------------------------------------------------------------
/lib/Navigation/Header.css:
--------------------------------------------------------------------------------
1 | @value small, desktop from "../constants.css";
2 |
3 | .container {
4 | composes: primary-background-color from "../constants.css";
5 | width: 100%;
6 | min-width: 320px;
7 | }
8 |
9 | .header {
10 | composes: primary-background-color from "../constants.css";
11 | display: flex;
12 | z-index: 1;
13 | align-items: center;
14 | justify-content: center;
15 | width: 100%;
16 | min-width: 320px;
17 | margin: 0 auto;
18 | padding: 1rem 0;
19 | }
20 |
21 | .nav {
22 | margin: 0 30px 0 0;
23 | }
24 |
25 | .copyright {
26 | flex: 1;
27 | }
28 |
29 | .logo {
30 | margin: 1rem 0 0 2rem;
31 | flex: 2;
32 | }
33 |
34 | a.burger {
35 | display: none;
36 | padding: 2rem;
37 | }
38 |
39 | @media small {
40 | a.burger {
41 | display: block;
42 | }
43 |
44 | .nav.inactive {
45 | display: none;
46 | }
47 | .nav.active {
48 | display: block;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Navigation/Header.css:
--------------------------------------------------------------------------------
1 | @value small, desktop from "../constants.css";
2 |
3 | .container {
4 | composes: primary-background-color from "../constants.css";
5 | width: 100%;
6 | min-width: 320px;
7 | }
8 |
9 | .header {
10 | composes: primary-background-color from "../constants.css";
11 | display: flex;
12 | z-index: 1;
13 | align-items: center;
14 | justify-content: center;
15 | width: 100%;
16 | min-width: 320px;
17 | margin: 0 auto;
18 | padding: 1rem 0;
19 | }
20 |
21 | .nav {
22 | margin: 0 30px 0 0;
23 | }
24 |
25 | .copyright {
26 | flex: 1;
27 | }
28 |
29 | .logo {
30 | margin: 1rem 0 0 2rem;
31 | flex: 2;
32 | }
33 |
34 | a.burger {
35 | display: none;
36 | padding: 2rem;
37 | }
38 |
39 | @media small {
40 | a.burger {
41 | display: block;
42 | }
43 |
44 | .nav.inactive {
45 | display: none;
46 | }
47 | .nav.active {
48 | display: block;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/lib/Footer/Footer.css:
--------------------------------------------------------------------------------
1 | /* footer Styles */
2 |
3 | .footer {
4 | width: 100%;
5 | background: #fff;
6 | display: flex;
7 | align-items: center;
8 | justify-content: center;
9 | flex-direction: row;
10 | align-content: center;
11 | }
12 |
13 | .copyright {
14 | color: #726371;
15 | font-family: 'Rubik';
16 | font-weight: 500;
17 | margin: 12px 8px;
18 | }
19 |
20 | .logo {
21 | flex: 2 auto;
22 | display: flex;
23 | align-items: center;
24 | height: auto;
25 | }
26 |
27 | .logo > img {
28 | flex: 1;
29 | padding: 12px;
30 | }
31 |
32 | .scrollToTop {
33 | color: #EE495C;
34 | font-family: 'Rubik';
35 | font-weight: 500;
36 | margin: 12px 8px;
37 | }
38 |
39 | .scrollToTop > div {
40 | margin-left: auto;
41 | }
42 |
43 | @media (max-width: 768px) {
44 | .footer {
45 | flex-direction: column-reverse;
46 | }
47 | }
48 |
49 | @media (min-width: 768px) {
50 | .scrollToTop {
51 | margin-left: 0;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Footer/Footer.css:
--------------------------------------------------------------------------------
1 | /* footer Styles */
2 |
3 | .footer {
4 | width: 100%;
5 | background: #fff;
6 | display: flex;
7 | align-items: center;
8 | justify-content: center;
9 | flex-direction: row;
10 | align-content: center;
11 | }
12 |
13 | .copyright {
14 | color: #726371;
15 | font-family: 'Rubik';
16 | font-weight: 500;
17 | margin: 12px 8px;
18 | }
19 |
20 | .logo {
21 | flex: 2 auto;
22 | display: flex;
23 | align-items: center;
24 | height: auto;
25 | }
26 |
27 | .logo > img {
28 | flex: 1;
29 | padding: 12px;
30 | }
31 |
32 | .scrollToTop {
33 | color: #EE495C;
34 | font-family: 'Rubik';
35 | font-weight: 500;
36 | margin: 12px 8px;
37 | }
38 |
39 | .scrollToTop > div {
40 | margin-left: auto;
41 | }
42 |
43 | @media (max-width: 768px) {
44 | .footer {
45 | flex-direction: column-reverse;
46 | }
47 | }
48 |
49 | @media (min-width: 768px) {
50 | .scrollToTop {
51 | margin-left: 0;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/lib/Button/Button.test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _react = require('react');
4 |
5 | var _react2 = _interopRequireDefault(_react);
6 |
7 | var _enzyme = require('enzyme');
8 |
9 | var _Button = require('./Button');
10 |
11 | var _Button2 = _interopRequireDefault(_Button);
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | describe('Button', function () {
16 | var testString = 'Hello';
17 | var wrapper = (0, _enzyme.shallow)(_react2.default.createElement(
18 | _Button2.default,
19 | null,
20 | testString
21 | ));
22 | it('should render a button', function () {
23 | expect(wrapper.find('button')).to.have.length(1);
24 | });
25 | it('should render with class base', function () {
26 | expect(wrapper.props().className).to.contain('base');
27 | });
28 | it('should have the appropriate child text', function () {
29 | expect(wrapper.text()).to.eql(testString);
30 | });
31 | });
--------------------------------------------------------------------------------
/src/Dropdown/Dropdown.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import sinon from 'sinon';
4 |
5 | import Dropdown from './Dropdown';
6 |
7 | describe('Dropdown', () => {
8 | const props = {};
9 | const testOptions = [
10 | { value: 'dog', label: 'Dog' },
11 | { value: 'cat', label: 'Cat' },
12 | { value: 'giraffe', label: 'Giraffe' },
13 | ];
14 |
15 | beforeEach(() => {
16 | props.onChange = sinon.spy();
17 | props.value = testOptions[0].value;
18 | props.options = testOptions;
19 | });
20 |
21 | it('should render a select dropdown', () => {
22 | const wrapper = shallow( );
23 | expect(wrapper.find('Select')).to.have.length(1);
24 | });
25 |
26 | it('should trigger onChange callback', () => {
27 | const wrapper = shallow( );
28 | wrapper.find('Select').simulate('change');
29 |
30 | expect(props.onChange).to.have.property('callCount', 1);
31 | });
32 | });
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | export AreaChart from './AreaChart/AreaChart';
2 | export BarChart from './BarChart/BarChart';
3 | export Sankey from './Sankey/Sankey';
4 | export Button from './Button/Button';
5 | export StoryCard from './StoryCard/StoryCard';
6 | export Chart from './Chart/Chart';
7 | export ChartData from './ChartData/ChartData';
8 | export Pie from './Pie/Pie';
9 | export Slider from './Slider/Slider';
10 | export Footer from './Footer/Footer';
11 | export ScrollToTop from './ScrollToTop/ScrollToTop';
12 | export Header from './Navigation/Header';
13 | export Nav from './Navigation/Nav';
14 | export NavRouterLink from './Navigation/NavRouterLink';
15 | export RechartsPie from './RechartsPie/RechartsPie';
16 | export LeafletMap from './LeafletMap/LeafletMap';
17 | export Dropdown from './Dropdown/Dropdown';
18 | export Icon from './Icon/Icon';
19 | export Scatterplot from './Scatterplot/Scatterplot';
20 |
21 | // export utils as well for broader use
22 | export isClient from './utils/isClient';
23 |
--------------------------------------------------------------------------------
/stories/Hero.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf, action } from '@kadira/storybook';
3 | import { Header } from '../src';
4 | import Hero from '../src/Hero/Hero';
5 | import CollectionHero from '../src/Hero/CollectionHero';
6 |
7 | const displayName = Hero.displayName || 'Hero';
8 |
9 | const defaultHeroTitle = 'with default hero';
10 | const description = 'this is the basic main page hero';
11 |
12 | const defaultHero = () => (
13 |
14 | );
15 |
16 | const collectionHero = () => (
17 |
18 |
19 |
24 |
25 | );
26 |
27 | const propDocs = { inline: true, propTables: [Header] };
28 |
29 | export default () => storiesOf(displayName, module)
30 | .add(
31 | defaultHeroTitle,
32 | defaultHero,
33 | )
34 | .add('collectionHero', collectionHero);
35 |
--------------------------------------------------------------------------------
/src/AreaChart/AreaChart.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import AreaChart from './AreaChart';
4 |
5 | describe('AreaChart', () => {
6 | const { data, colors } = {
7 | data: [{ name: 'Year 1', Line1: 6000, Line2: 4000, Line3: 2000 },
8 | { name: 'Year 2', Line1: 3000, Line2: 2000, Line3: 1500 }],
9 | colors: ['#a6cee3', '#1f78b4', '#b2df8a'],
10 | };
11 |
12 | const wrapper = shallow(
13 | ,
17 | );
18 |
19 | it('should render a div', () => {
20 | expect(wrapper.find('div')).to.have.length(1);
21 | });
22 |
23 | it('should render a div with one child element', () => {
24 | expect(wrapper.find('div').children()).to.have.length(1);
25 | });
26 |
27 | it('should render a div with one child element that itself has seven children elements', () => {
28 | expect(wrapper.find('div').children().props().children).to.have.length(7);
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/src/ChartData/ChartData.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 |
3 | class ChartData extends Component {
4 |
5 | static displayName = 'ChartData'
6 |
7 | static propTypes = {
8 | children: PropTypes.node,
9 | xScale: PropTypes.func,
10 | yScale: PropTypes.func,
11 | data: PropTypes.oneOfType([
12 | PropTypes.arrayOf(PropTypes.number),
13 | PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)),
14 | ]).isRequired,
15 | }
16 |
17 | static childContextTypes = {
18 | xScale: PropTypes.func,
19 | yScale: PropTypes.func,
20 | data: PropTypes.oneOfType([
21 | PropTypes.arrayOf(PropTypes.number),
22 | PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)),
23 | ]),
24 | }
25 |
26 | getChildContext() {
27 | const { xScale, yScale, data } = this.props;
28 | return { xScale, yScale, data };
29 | }
30 |
31 | render() {
32 | return (
33 |
34 | {this.props.children}
35 |
36 | );
37 | }
38 | }
39 |
40 | export default ChartData;
--------------------------------------------------------------------------------
/mocha.conf.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-extraneous-dependencies */
2 | // chai syntax
3 | const chai = require('chai');
4 | // dom object in node
5 | const jsdom = require('jsdom').jsdom;
6 |
7 | // stubbing/spying library
8 | const sinon = require('sinon');
9 | const sinonChai = require('sinon-chai');
10 |
11 | // global setup
12 | global.assert = chai.assert;
13 | global.expect = chai.expect;
14 | global.chai = chai;
15 | global.sinon = sinon;
16 |
17 | // dom setup
18 | global.document = jsdom('');
19 | global.navigator = {
20 | userAgent: 'node.js',
21 | platform: [],
22 | };
23 | global.window = document.defaultView;
24 |
25 | // we're going to emulate the dom with this part here
26 | const exposedProperties = ['window', 'navigator', 'document'];
27 | Object.keys(document.defaultView).forEach((property) => {
28 | if (typeof global[property] === 'undefined') {
29 | exposedProperties.push(property);
30 | global[property] = document.defaultView[property];
31 | }
32 | });
33 |
34 | // chai setup
35 | chai.use(sinonChai);
36 | chai.use(require('chai-enzyme')());
37 |
--------------------------------------------------------------------------------
/stories/Sankey.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { take } from 'ramda';
3 | import { storiesOf } from '@kadira/storybook';
4 | import { Sankey } from '../src';
5 |
6 | const displayName = Sankey.displayName || 'Sankey';
7 | const title = 'Simple usage';
8 | const description = `
9 | This is some basic usage with the Sankey component. Please refer to the btc-data.json file for formatting of data.
10 | In general, nodes and links are needed.`;
11 |
12 | const data = require('./btc-data.json');
13 |
14 | const transactionslinks = take(500, data.links.transactions);
15 | const spendingLinks = take(500, data.links.spending);
16 |
17 | const demoCode = () => (
18 |
19 |
20 |
21 |
22 | );
23 |
24 | const propDocs = { inline: true, propTables: [Sankey] };
25 |
26 | export default () => storiesOf(displayName, module)
27 | .addWithInfo(
28 | title,
29 | description,
30 | demoCode,
31 | propDocs,
32 | );
33 |
--------------------------------------------------------------------------------
/.storybook/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-extraneous-dependencies */
2 |
3 | const path = require('path');
4 |
5 | const isProd = process.env.NODE_ENV === 'production';
6 | const className = isProd ? '[hash:base64:5]' : '[name]__[local]-[hash:base64:5]';
7 |
8 | module.exports = {
9 | module: {
10 | loaders: [
11 | {
12 | test: /\.css$/,
13 | exclude: [path.resolve(__dirname, 'node_modules'), /assets\/.*\.css$/],
14 | loader: `style-loader!css-loader?modules&importLoaders=1&localIdentName=${className}!postcss-loader`,
15 | },
16 | {
17 | test: /assets\/.*\.css$/,
18 | // exclude: [path.resolve(__dirname, 'node_modules'), path.resolve(__dirname, '../src/assets')],
19 | loader: 'style-loader!css-loader!postcss-loader',
20 | },
21 |
22 | {
23 | test: /\.(png|svg|jpg|jpeg|gif)$/,
24 | loader: 'url-loader',
25 | query: {
26 | limit: 10000,
27 | emitFile: true,
28 | },
29 | },
30 |
31 | ],
32 | },
33 | postcss: () => [
34 | require('autoprefixer'),
35 | ],
36 | };
37 |
--------------------------------------------------------------------------------
/lib/Button/Button.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _bind = require('classnames/bind');
12 |
13 | var _bind2 = _interopRequireDefault(_bind);
14 |
15 | var _ButtonStyles = require('./Button.styles.css');
16 |
17 | var _ButtonStyles2 = _interopRequireDefault(_ButtonStyles);
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | var cx = _bind2.default.bind(_ButtonStyles2.default);
22 |
23 | var className = cx({ base: true });
24 |
25 | var Button = function Button(_ref) {
26 | var children = _ref.children,
27 | onClick = _ref.onClick;
28 | return _react2.default.createElement(
29 | 'button',
30 | { className: className, onClick: onClick },
31 | children
32 | );
33 | };
34 |
35 | Button.displayName = 'Button';
36 |
37 | Button.propTypes = {
38 | children: _react2.default.PropTypes.string,
39 | onClick: _react2.default.PropTypes.func
40 | };
41 |
42 | exports.default = Button;
--------------------------------------------------------------------------------
/stories/StoryFooter.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf, action } from '@kadira/storybook';
3 | import { withKnobs, text, object } from '@kadira/storybook-addon-knobs';
4 | import StoryFooter from '../src/StoryCard/StoryFooter';
5 | import { ICONS } from '../src/styleConstants';
6 |
7 | const collectionId = 'collection-id';
8 | const cardId = 'cardId';
9 |
10 | const propTableOptions = { inline: true, propTables: [StoryFooter] };
11 | const wrapperStyle = { width: '30%', padding: '10%', margin: '0 auto' };
12 | export default () => storiesOf('StoryFooter', module)
13 | .addDecorator(withKnobs)
14 | .addWithInfo(
15 | 'default usage',
16 | `Made with 2 components, 1 allows navigating to the card page & 1 copies the link for sharing.
17 | Since the links are made with card id and collection id, change the values in the knobs below,
18 | copy via the link then try pasting from your clipboard.
19 | `,
20 | () => (
21 |
22 | ),
23 | propTableOptions,
24 | );
25 |
--------------------------------------------------------------------------------
/lib/Hero/CollectionHero.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _Hero = require('./Hero');
12 |
13 | var _Hero2 = _interopRequireDefault(_Hero);
14 |
15 | var _Tag = require('../Tag/Tag');
16 |
17 | var _Tag2 = _interopRequireDefault(_Tag);
18 |
19 | var _ShareCollection = require('../Share/ShareCollection');
20 |
21 | var _ShareCollection2 = _interopRequireDefault(_ShareCollection);
22 |
23 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24 |
25 | var CollectionHero = function CollectionHero(props) {
26 | return _react2.default.createElement(
27 | _Hero2.default,
28 | null,
29 | _react2.default.createElement(_Tag2.default, { name: props.featuredTag }),
30 | _react2.default.createElement(
31 | 'h1',
32 | null,
33 | props.title
34 | ),
35 | _react2.default.createElement(_ShareCollection2.default, { collectionId: props.collectionId })
36 | );
37 | };
38 |
39 | exports.default = CollectionHero;
--------------------------------------------------------------------------------
/stories/AreaChart.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import { AreaChart } from '../src';
4 | import { colors } from './shared';
5 |
6 | const displayName = AreaChart.displayName || 'AreaChart';
7 | const title = 'Simple usage';
8 | const description = `
9 | This is some basic usage with the AreaChart.
10 | A legend includes line titles.
11 | A tooltip includes each line value at each X-axis point.`;
12 |
13 | const data = [
14 | { name: 'Year 1', Line1: 6000, Line2: 4000, Line3: 2000 },
15 | { name: 'Year 2', Line1: 3000, Line2: 2000, Line3: 1500 },
16 | { name: 'Year 3', Line1: 4000, Line2: 3000, Line3: 2250 },
17 | { name: 'Year 4', Line1: 4500, Line2: 3500, Line3: 2500 },
18 | { name: 'Year 5', Line1: 3500, Line2: 3000, Line3: 2000 },
19 | ];
20 |
21 | const demoCode = () => (
22 |
26 | );
27 |
28 | const propDocs = { inline: true, propTables: [AreaChart] };
29 |
30 | export default () => storiesOf(displayName, module)
31 | .addWithInfo(
32 | title,
33 | description,
34 | demoCode,
35 | propDocs,
36 | );
37 |
--------------------------------------------------------------------------------
/src/RechartsPie/RechartsPie.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import {
3 | PieChart, Pie, Cell, Legend,
4 | } from 'recharts';
5 |
6 | const RechartsPie = ({ data, chartProportions, colors, styles }) =>
7 |
8 |
9 |
10 |
11 | {
12 | data.map((entry, index) => (
13 | |
14 | ))
15 | }
16 |
17 |
18 |
;
19 |
20 | RechartsPie.propTypes = {
21 | data: PropTypes.arrayOf(PropTypes.object).isRequired,
22 | chartProportions: PropTypes.object.isRequired,
23 | colors: PropTypes.arrayOf(PropTypes.string),
24 | styles: PropTypes.object,
25 | };
26 |
27 | export default RechartsPie;
28 |
--------------------------------------------------------------------------------
/src/LeafletMap/LeafletMap.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { Map, TileLayer } from 'react-leaflet';
3 | import isClient from '../utils/isClient';
4 |
5 | const LeafletMap = ({ width, height, children, ...mapProps }) => (
6 |
7 | {isClient &&
8 |
9 |
13 | {children}
14 |
15 | }
16 |
17 | );
18 |
19 | LeafletMap.propTypes = {
20 | center: PropTypes.arrayOf(PropTypes.number),
21 | zoom: PropTypes.number,
22 | scrollWheelZoom: PropTypes.bool,
23 | children: PropTypes.node.isRequired,
24 | width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
25 | height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
26 | url: PropTypes.string,
27 | attribution: PropTypes.string,
28 | };
29 |
30 | LeafletMap.defaultProps = {
31 | center: [0, 0],
32 | zoom: 0,
33 | width: '100%',
34 | height: 600,
35 | scrollWheelZoom: false,
36 | url: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
37 | attribution: "© OpenStreetMap contributors",
38 | };
39 |
40 | export default LeafletMap;
41 |
--------------------------------------------------------------------------------
/stories/Editable.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import { withKnobs, text, boolean, number, object } from '@kadira/storybook-addon-knobs';
4 |
5 | export default () => storiesOf('Editable UI components', module)
6 | .addDecorator(withKnobs)
7 | .add('with a button', () => {
8 | const style = {
9 | backgroundColor: '#FFF',
10 | border: '1px solid #DDD',
11 | borderRadius: 2,
12 | outline: 0,
13 | fontSize: 15,
14 | cursor: 'pointer',
15 | };
16 |
17 | return (
18 |
22 | {text('Label', 'Hello Button')}
23 |
24 | );
25 | })
26 | .add('with some text', () => {
27 | let content = text('Content', 'This is the content');
28 | content = content.replace(/\n/g, ' ');
29 |
30 | return (
31 |
34 | );
35 | })
36 | .add('as dynamic variables', () => {
37 | const name = text('Name', 'David Daniel');
38 | const age = number('Age', 33);
39 |
40 | const content = `I am ${name} and I'm ${age} years old.`;
41 | return ({content}
);
42 | });
43 |
--------------------------------------------------------------------------------
/src/RechartsPie/RechartsPie.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import RechartsPie from './RechartsPie';
4 |
5 | describe('Recharts Pie', () => {
6 | const { data, colors, styles, chartProportions } = {
7 | data: [{ name: 'Group A', value: 400 }],
8 | styles: { fontFamily: 'Roboto Condensed', fontSize: '8', color: '#706371', fill: '#706371' },
9 | colors: ['#a6cee3', '#1f78b4'],
10 | chartProportions: {
11 | chartWidth: 2,
12 | chartHeight: 1,
13 | iconSize: 0.075,
14 | pieInnerRadius: 0.2,
15 | pieOuterRadius: 0.4,
16 | },
17 | };
18 |
19 | const wrapper = shallow(
20 | ,
26 | );
27 |
28 | it('should render a div', () => {
29 | expect(wrapper.find('div')).to.have.length(1);
30 | });
31 |
32 | it('should render a div with one child element', () => {
33 | expect(wrapper.find('div').children()).to.have.length(1);
34 | });
35 |
36 | it('should render a div with one child element that itself has two children elements', () => {
37 | expect(wrapper.find('div').children().props().children).to.have.length(2);
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/lib/constants.css:
--------------------------------------------------------------------------------
1 | @value small: (max-width: 640px);
2 | @value desktop: (min-width: 641px);
3 |
4 | /* Color */
5 | @value primary: rgba(34,15,37,1);
6 | @value secondary: rgba(238,73,92,1);
7 | @value tertiary: rgba(114,99,113,1);
8 | @value medium: rgba(170,164,171,1);
9 | @value subdued: rgba(243,242,243,1);
10 | @value offwhite: rgba(255,254,254,1);
11 | @value midnight: rgba(0,23,50,1);
12 |
13 | .primary-color {
14 | color: primary;
15 | fill: primary;
16 | }
17 |
18 | .primary-background-color {
19 | background-color: primary;
20 | }
21 |
22 | .secondary-color {
23 | color: secondary;
24 | fill: secondary;
25 | }
26 |
27 | .tertiary-color {
28 | color: tertiary;
29 | fill: tertiary;
30 | }
31 |
32 | .medium-color {
33 | color: medium;
34 | fill: medium;
35 | }
36 |
37 | .subdued-color {
38 | color: subdued;
39 | fill: subdued;
40 | }
41 |
42 | /* Phone Breakpoint */
43 |
44 | @media screen and small {
45 |
46 | }
47 |
48 |
49 | /* Tablet Portrait Breakpoint */
50 |
51 | @media screen and desktop and (max-width:768px) {
52 |
53 | }
54 |
55 |
56 | /* Tablet Landscape Breakpoint */
57 |
58 | @media screen and (min-width:769px) and (max-width: 1024) {
59 |
60 | }
61 |
62 |
63 | /* Desktop Breakpoint */
64 |
65 | @media screen and (min-width:1025px) {
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/constants.css:
--------------------------------------------------------------------------------
1 | @value small: (max-width: 640px);
2 | @value desktop: (min-width: 641px);
3 |
4 | /* Color */
5 | @value primary: rgba(34,15,37,1);
6 | @value secondary: rgba(238,73,92,1);
7 | @value tertiary: rgba(114,99,113,1);
8 | @value medium: rgba(170,164,171,1);
9 | @value subdued: rgba(243,242,243,1);
10 | @value offwhite: rgba(255,254,254,1);
11 | @value midnight: rgba(0,23,50,1);
12 |
13 | .primary-color {
14 | color: primary;
15 | fill: primary;
16 | }
17 |
18 | .primary-background-color {
19 | background-color: primary;
20 | }
21 |
22 | .secondary-color {
23 | color: secondary;
24 | fill: secondary;
25 | }
26 |
27 | .tertiary-color {
28 | color: tertiary;
29 | fill: tertiary;
30 | }
31 |
32 | .medium-color {
33 | color: medium;
34 | fill: medium;
35 | }
36 |
37 | .subdued-color {
38 | color: subdued;
39 | fill: subdued;
40 | }
41 |
42 | /* Phone Breakpoint */
43 |
44 | @media screen and small {
45 |
46 | }
47 |
48 |
49 | /* Tablet Portrait Breakpoint */
50 |
51 | @media screen and desktop and (max-width:768px) {
52 |
53 | }
54 |
55 |
56 | /* Tablet Landscape Breakpoint */
57 |
58 | @media screen and (min-width:769px) and (max-width: 1024) {
59 |
60 | }
61 |
62 |
63 | /* Desktop Breakpoint */
64 |
65 | @media screen and (min-width:1025px) {
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/lib/Scatterplot/Scatterplot.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _recharts = require('recharts');
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | var data = [{ x: 100, y: 200, z: 200 }, { x: 120, y: 100, z: 260 }, { x: 170, y: 300, z: 400 }, { x: 140, y: 250, z: 280 }, { x: 150, y: 400, z: 500 }, { x: 110, y: 280, z: 200 }];
16 |
17 | var Scatterplot = function Scatterplot() {
18 | return _react2.default.createElement(
19 | _recharts.ScatterChart,
20 | { width: 400, height: 400, margin: { top: 20, right: 20, bottom: 20, left: 20 } },
21 | _react2.default.createElement(_recharts.XAxis, { dataKey: 'x', name: 'stature', unit: 'cm' }),
22 | _react2.default.createElement(_recharts.YAxis, { dataKey: 'y', name: 'weight', unit: 'kg' }),
23 | _react2.default.createElement(_recharts.Scatter, { name: 'A school', data: data, fill: '#8884d8' }),
24 | _react2.default.createElement(_recharts.CartesianGrid, null),
25 | _react2.default.createElement(_recharts.Tooltip, { cursor: { strokeDasharray: '3 3' } })
26 | );
27 | };
28 |
29 | exports.default = Scatterplot;
--------------------------------------------------------------------------------
/lib/BarChart/BarChart.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _recharts = require('recharts');
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | var HorizontalBarChart = function HorizontalBarChart(_ref) {
16 | var data = _ref.data;
17 | return _react2.default.createElement(
18 | _recharts.BarChart,
19 | { layout: 'horizontal', width: 730, height: 250, data: data },
20 | _react2.default.createElement(_recharts.XAxis, { dataKey: 'name' }),
21 | _react2.default.createElement(_recharts.YAxis, null),
22 | _react2.default.createElement(_recharts.CartesianGrid, { strokeDasharray: '3 3' }),
23 | _react2.default.createElement(_recharts.Tooltip, null),
24 | _react2.default.createElement(_recharts.Legend, null),
25 | _react2.default.createElement(_recharts.Bar, { dataKey: 'x', fill: '#8884d8' }),
26 | _react2.default.createElement(_recharts.Bar, { dataKey: 'y', fill: '#82ca9d' })
27 | );
28 | };
29 |
30 | HorizontalBarChart.propTypes = {
31 | data: _react.PropTypes.arrayOf(_react.PropTypes.object)
32 | };
33 |
34 | exports.default = HorizontalBarChart;
--------------------------------------------------------------------------------
/lib/Hero/Hero.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _Hero = require('./Hero.css');
12 |
13 | var _Hero2 = _interopRequireDefault(_Hero);
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | var DefaultChildren = function DefaultChildren() {
18 | return _react2.default.createElement(
19 | 'h1',
20 | null,
21 | 'Data for the people,',
22 | _react2.default.createElement('br', null),
23 | 'by the people.'
24 | );
25 | };
26 |
27 | var Hero = function Hero(_ref) {
28 | var children = _ref.children;
29 | return _react2.default.createElement(
30 | 'div',
31 | { className: _Hero2.default.hero },
32 | _react2.default.createElement(
33 | 'div',
34 | { className: _Hero2.default.container },
35 | _react2.default.createElement(
36 | 'div',
37 | { className: _Hero2.default.content },
38 | children || _react2.default.createElement(DefaultChildren, null)
39 | )
40 | )
41 | );
42 | };
43 |
44 | Hero.displayName = 'Hero';
45 |
46 | Hero.propTypes = {
47 | children: _react2.default.PropTypes.node
48 | };
49 |
50 | exports.default = Hero;
--------------------------------------------------------------------------------
/lib/Slider/SliderBox.css:
--------------------------------------------------------------------------------
1 | .slider-container {
2 | width: 80%;
3 | margin: 40px auto;
4 | }
5 | .slider-container .slider {
6 | margin-bottom: 2em;
7 | }
8 |
9 | .rc-slider-tooltip-arrow {
10 | border-top-color: rgba(114,99,113,1);
11 | }
12 |
13 | .rc-slider-tooltip-inner {
14 | width: auto;
15 | height: auto;
16 | padding: 10px;
17 | font-size: 16px;
18 | border-radius: 2px;
19 | box-shadow: none;
20 | vertical-align: middle;
21 | background-color: rgba(114,99,113,1);
22 | }
23 |
24 | .rc-slider-tooltip-inner:before {
25 | content: "$ ";
26 | }
27 |
28 | .rc-slider-track {
29 | background-color: rgba(238,73,92,1);
30 | height: 4px;
31 | }
32 |
33 | .rc-slider-handle {
34 | border-color: rgba(238,73,92,1);
35 | background-color: rgba(238,73,92,1);
36 | width: 18px;
37 | height: 18px;
38 | margin-top: -7px;
39 | margin-left: -9px;
40 | }
41 |
42 | .rc-slider-handle:hover {
43 | border-color: rgba(238,73,92,1);
44 | }
45 |
46 | .panel-body {
47 | background-color: rgba(243,242,243,1);
48 | font-family: 'Roboto Condensed', sans-serif;
49 | }
50 |
51 | .hour, .day, .week, .month, .year {
52 | font-weight: bold;
53 | font-size: 1.2em;
54 | }
55 |
56 | /* Commented out. Legacy. Safe to remove completely? */
57 |
58 | .rc-slider-tooltip-placement-points-bc-tc .rc-slider-tooltip-arrow {
59 | border-top-color: #000;
60 | }
61 |
--------------------------------------------------------------------------------
/src/Slider/SliderBox.css:
--------------------------------------------------------------------------------
1 | .slider-container {
2 | width: 80%;
3 | margin: 40px auto;
4 | }
5 | .slider-container .slider {
6 | margin-bottom: 2em;
7 | }
8 |
9 | .rc-slider-tooltip-arrow {
10 | border-top-color: rgba(114,99,113,1);
11 | }
12 |
13 | .rc-slider-tooltip-inner {
14 | width: auto;
15 | height: auto;
16 | padding: 10px;
17 | font-size: 16px;
18 | border-radius: 2px;
19 | box-shadow: none;
20 | vertical-align: middle;
21 | background-color: rgba(114,99,113,1);
22 | }
23 |
24 | .rc-slider-tooltip-inner:before {
25 | content: "$ ";
26 | }
27 |
28 | .rc-slider-track {
29 | background-color: rgba(238,73,92,1);
30 | height: 4px;
31 | }
32 |
33 | .rc-slider-handle {
34 | border-color: rgba(238,73,92,1);
35 | background-color: rgba(238,73,92,1);
36 | width: 18px;
37 | height: 18px;
38 | margin-top: -7px;
39 | margin-left: -9px;
40 | }
41 |
42 | .rc-slider-handle:hover {
43 | border-color: rgba(238,73,92,1);
44 | }
45 |
46 | .panel-body {
47 | background-color: rgba(243,242,243,1);
48 | font-family: 'Roboto Condensed', sans-serif;
49 | }
50 |
51 | .hour, .day, .week, .month, .year {
52 | font-weight: bold;
53 | font-size: 1.2em;
54 | }
55 |
56 | /* Commented out. Legacy. Safe to remove completely? */
57 |
58 | .rc-slider-tooltip-placement-points-bc-tc .rc-slider-tooltip-arrow {
59 | border-top-color: #000;
60 | }
61 |
--------------------------------------------------------------------------------
/src/Share/ShareCollection.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import copy from 'copy-to-clipboard';
3 | import StoryLink from '../StoryCard/StoryLink';
4 | import { ICONS } from '../styleConstants';
5 |
6 | const MS_TO_SWITCH_TEXT = 3000; // 3 seconds
7 |
8 | export default class ShareCollection extends Component {
9 |
10 | static defaultProps = {
11 | collectionId: 'some-collection-id',
12 | }
13 |
14 | static propTypes = {
15 | collectionId: PropTypes.string,
16 | }
17 |
18 | constructor(props) {
19 | super(props);
20 | this.state = {
21 | copied: false,
22 | };
23 | }
24 |
25 | setToFalse = () => this.setState({ copied: false });
26 |
27 | switchState = ms => setTimeout(this.setToFalse, ms);
28 |
29 | handleCopy = () => {
30 | // NOTE: we need to make sure this will work on all browsers
31 | copy(`${window.location.href}`);
32 | this.switchState(MS_TO_SWITCH_TEXT);
33 | this.setState({ copied: true });
34 | }
35 |
36 | render() {
37 | const shareTxt = this.state.copied ? 'Link copied!' : 'Share'; // if copied, show Link copied, otherwise, show Share card
38 | const shareIcon = this.state.copied ? ICONS.check : ICONS.link;
39 | return (
40 | {shareTxt}
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/AreaChart/AreaChart.test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _react = require('react');
4 |
5 | var _react2 = _interopRequireDefault(_react);
6 |
7 | var _enzyme = require('enzyme');
8 |
9 | var _AreaChart = require('./AreaChart');
10 |
11 | var _AreaChart2 = _interopRequireDefault(_AreaChart);
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | describe('AreaChart', function () {
16 | var _data$colors = {
17 | data: [{ name: 'Year 1', Line1: 6000, Line2: 4000, Line3: 2000 }, { name: 'Year 2', Line1: 3000, Line2: 2000, Line3: 1500 }],
18 | colors: ['#a6cee3', '#1f78b4', '#b2df8a']
19 | },
20 | data = _data$colors.data,
21 | colors = _data$colors.colors;
22 |
23 |
24 | var wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_AreaChart2.default, {
25 | data: data,
26 | colors: colors
27 | }));
28 |
29 | it('should render a div', function () {
30 | expect(wrapper.find('div')).to.have.length(1);
31 | });
32 |
33 | it('should render a div with one child element', function () {
34 | expect(wrapper.find('div').children()).to.have.length(1);
35 | });
36 |
37 | it('should render a div with one child element that itself has seven children elements', function () {
38 | expect(wrapper.find('div').children().props().children).to.have.length(7);
39 | });
40 | });
--------------------------------------------------------------------------------
/lib/Dropdown/Dropdown.test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _react = require('react');
4 |
5 | var _react2 = _interopRequireDefault(_react);
6 |
7 | var _enzyme = require('enzyme');
8 |
9 | var _sinon = require('sinon');
10 |
11 | var _sinon2 = _interopRequireDefault(_sinon);
12 |
13 | var _Dropdown = require('./Dropdown');
14 |
15 | var _Dropdown2 = _interopRequireDefault(_Dropdown);
16 |
17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18 |
19 | describe('Dropdown', function () {
20 | var props = {};
21 | var testOptions = [{ value: 'dog', label: 'Dog' }, { value: 'cat', label: 'Cat' }, { value: 'giraffe', label: 'Giraffe' }];
22 |
23 | beforeEach(function () {
24 | props.onChange = _sinon2.default.spy();
25 | props.value = testOptions[0].value;
26 | props.options = testOptions;
27 | });
28 |
29 | it('should render a select dropdown', function () {
30 | var wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_Dropdown2.default, props));
31 | expect(wrapper.find('Select')).to.have.length(1);
32 | });
33 |
34 | it('should trigger onChange callback', function () {
35 | var wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_Dropdown2.default, props));
36 | wrapper.find('Select').simulate('change');
37 |
38 | expect(props.onChange).to.have.property('callCount', 1);
39 | });
40 | });
--------------------------------------------------------------------------------
/lib/ScrollToTop/ScrollToTop.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _Icon = require('../Icon/Icon');
12 |
13 | var _Icon2 = _interopRequireDefault(_Icon);
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | var hashToGoToTop = '#';
18 | var styles = { display: 'flex', flexDirection: 'column', textAlign: 'center' };
19 |
20 | var ScrollToTop = function ScrollToTop(_ref) {
21 | var _ref$iconStyle = _ref.iconStyle,
22 | iconStyle = _ref$iconStyle === undefined ? null : _ref$iconStyle;
23 | return _react2.default.createElement(
24 | 'div',
25 | null,
26 | _react2.default.createElement(
27 | 'a',
28 | {
29 | style: styles,
30 | 'aria-label': 'scroll to top',
31 | href: hashToGoToTop
32 | },
33 | iconStyle && _react2.default.createElement(_Icon2.default, { className: iconStyle }),
34 | _react2.default.createElement(
35 | 'span',
36 | null,
37 | 'Back to Top'
38 | )
39 | )
40 | );
41 | };
42 |
43 | ScrollToTop.displayName = 'ScrollToTop';
44 | ScrollToTop.propTypes = {
45 | iconStyle: _react2.default.PropTypes.string
46 | };
47 |
48 | exports.default = ScrollToTop;
--------------------------------------------------------------------------------
/stories/Dropdown.story.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import { Dropdown } from '../src';
4 |
5 | const displayName = Dropdown.displayName || 'Dropdown';
6 | const title = 'Simple usage';
7 | const description = `
8 | This is some basic usage with the select dropdown.
9 | Selecting a dropdown option should trigger an onChange call.`;
10 |
11 | const demoOptions = [
12 | { value: 'dog', label: 'Dog' },
13 | { value: 'cat', label: 'Cat' },
14 | { value: 'giraffe', label: 'Giraffe' },
15 | ];
16 |
17 | const demoCode = () => {
18 | class DemoDropdown extends Component {
19 | constructor() {
20 | super();
21 | this.state = { value: demoOptions[0].value };
22 | this.handleChange = this.handleChange.bind(this);
23 | }
24 |
25 | handleChange(value) {
26 | this.setState({ value });
27 | }
28 |
29 | render() {
30 | return (
31 |
36 | );
37 | }
38 | }
39 |
40 | return ;
41 | };
42 |
43 |
44 | const propDocs = { inline: true, propTables: [Dropdown] };
45 |
46 | export default () => storiesOf(displayName, module)
47 | .addWithInfo(
48 | title,
49 | description,
50 | demoCode,
51 | propDocs,
52 | );
--------------------------------------------------------------------------------
/stories/Header.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import { Header } from '../src';
4 | import Hero from '../src/Hero/Hero';
5 | import Tag from '../src/Tag/Tag';
6 | import ShareCollection from '../src/Share/ShareCollection';
7 |
8 | const displayName = Header.displayName || 'Header';
9 | const title = 'Simple usage';
10 | const description = `
11 | a basic nav with logo & nav controls`;
12 |
13 | const demoCode = () => (
14 |
15 | );
16 |
17 | const altTitle = 'with Platform Hero';
18 |
19 | const altDemo = () => (
20 | Some other slogan
21 | );
22 |
23 | const defaultHeroTitle = 'with default hero';
24 |
25 | const defaultHero = () => (
26 |
27 | );
28 |
29 | const collectionHero = () => (
30 |
31 |
32 |
33 |
34 | Title
35 |
36 |
37 |
38 | );
39 |
40 | const propDocs = { inline: true, propTables: [Header] };
41 |
42 | export default () => storiesOf(displayName, module)
43 | .addWithInfo(
44 | title,
45 | description,
46 | demoCode,
47 | propDocs,
48 | )
49 | .add(defaultHeroTitle, defaultHero)
50 | .add('collectionHero', collectionHero)
51 | .add(altTitle, altDemo);
52 |
--------------------------------------------------------------------------------
/src/Dropdown/Dropdown.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import classNames from 'classnames/bind';
3 | import Select from 'react-select';
4 | import isClient from '../utils/isClient';
5 | import styles from './Dropdown.styles.css';
6 |
7 | // NOTE: temporary fix until webpack 2 comes to storybook - otherwise don't use ! syntax for webpack loaders
8 | // if (isClient) require('!style-loader!css-loader!react-select/dist/react-select.css'); // eslint-disable-line
9 | if (isClient) require('../../assets/react-select.min.css'); // eslint-disable-line
10 |
11 | const cx = classNames.bind(styles);
12 |
13 | const className = cx({ base: true });
14 |
15 | const Dropdown = ({ options, onChange, value, clearable, searchable, disabled }) => (
16 |
25 | );
26 |
27 | Dropdown.displayName = 'Dropdown';
28 |
29 | Dropdown.propTypes = {
30 | onChange: PropTypes.func.isRequired,
31 | options: PropTypes.array.isRequired,
32 | value: PropTypes.any.isRequired, // eslint-disable-line react/forbid-prop-types
33 | clearable: PropTypes.bool,
34 | searchable: PropTypes.bool,
35 | disabled: PropTypes.bool,
36 | };
37 |
38 | Dropdown.defaultProps = {
39 | clearable: false,
40 | searchable: true,
41 | disabled: false,
42 | };
43 |
44 | export default Dropdown;
45 |
--------------------------------------------------------------------------------
/lib/Media/Media.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _templateObject = _taggedTemplateLiteral(['\n @media (max-width: ', 'px) {\n ', '\n }\n '], ['\n @media (max-width: ', 'px) {\n ', '\n }\n ']);
8 |
9 | var _isClient = require('../utils/isClient');
10 |
11 | var _isClient2 = _interopRequireDefault(_isClient);
12 |
13 | var _styledComponents = require('styled-components');
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
18 |
19 | // these sizes are arbitrary and you can set them to whatever you wish
20 |
21 |
22 | var sizes = {
23 | giant: 1170,
24 | desktop: 992,
25 | tablet: 768,
26 | phone: 376
27 | };
28 |
29 | // iterate through the sizes and create a media template
30 | var media = Object.keys(sizes).reduce(function (accumulator, label) {
31 | // use em in breakpoints to work properly cross-browser and support users
32 | // changing their browsers font-size: https://zellwk.com/blog/media-query-units/
33 | var pxSize = sizes[label] / 16;
34 | accumulator[label] = function () {
35 | return (0, _styledComponents.css)(_templateObject, pxSize, _styledComponents.css.apply(undefined, arguments));
36 | };
37 | return accumulator;
38 | }, {});
39 |
40 | exports.default = media;
--------------------------------------------------------------------------------
/lib/Navigation/NavSubMenu.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _reactRouter = require('react-router');
12 |
13 | var _Nav = require('./Nav.css');
14 |
15 | var _Nav2 = _interopRequireDefault(_Nav);
16 |
17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18 |
19 | var pathOrName = function pathOrName(p, n) {
20 | return p || '/' + n.toLowerCase();
21 | };
22 |
23 | var NavSubMenu = function NavSubMenu(_ref) {
24 | var items = _ref.items,
25 | isVisible = _ref.isVisible;
26 | return _react2.default.createElement(
27 | 'div',
28 | { className: _Nav2.default.nestedMenu + ' ' + (isVisible ? _Nav2.default.visible : _Nav2.default.hidden) },
29 | items.map(function (item, index) {
30 | return _react2.default.createElement(
31 | _reactRouter.Link,
32 | { key: index, to: pathOrName(item.path, item.name) },
33 | _react2.default.createElement(
34 | 'span',
35 | { className: 'nested-menu-link' },
36 | item.name
37 | )
38 | );
39 | })
40 | );
41 | };
42 |
43 | NavSubMenu.displayName = 'NavSubMenu';
44 | NavSubMenu.propTypes = {
45 | items: _react2.default.PropTypes.arrayOf(_react2.default.PropTypes.shape({})),
46 | isVisible: _react2.default.PropTypes.bool
47 | };
48 |
49 | exports.default = NavSubMenu;
--------------------------------------------------------------------------------
/lib/StoryCard/StoryCard.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _StoryFooter = require('./StoryFooter');
12 |
13 | var _StoryFooter2 = _interopRequireDefault(_StoryFooter);
14 |
15 | var _StoryCard = require('./StoryCard.css');
16 |
17 | var _StoryCard2 = _interopRequireDefault(_StoryCard);
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | var StoryCard = function StoryCard(_ref) {
22 | var cardId = _ref.cardId,
23 | collectionId = _ref.collectionId,
24 | title = _ref.title,
25 | children = _ref.children;
26 | return _react2.default.createElement(
27 | 'div',
28 | { className: _StoryCard2.default.card },
29 | _react2.default.createElement(
30 | 'h2',
31 | { className: 'Title Rubik' },
32 | title
33 | ),
34 | _react2.default.createElement(
35 | 'div',
36 | { className: _StoryCard2.default.description },
37 | children
38 | ),
39 | _react2.default.createElement(_StoryFooter2.default, { cardId: cardId, collectionId: collectionId })
40 | );
41 | };
42 |
43 | StoryCard.displayName = 'StoryCard';
44 |
45 | StoryCard.propTypes = {
46 | title: _react.PropTypes.string,
47 | cardId: _react.PropTypes.string,
48 | collectionId: _react.PropTypes.string,
49 | children: _react.PropTypes.node
50 | };
51 |
52 | exports.default = StoryCard;
--------------------------------------------------------------------------------
/stories/Slider.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import { Slider } from '../src';
4 |
5 | const displayName = Slider.displayName || 'Slider';
6 | const title = 'Simple usage';
7 | const description = `
8 | This is some basic usage with the slider component as built for Raise Effect, updated with changes for latest rc-slider. Due to the nature of the component, a higher order component is required to contain local state.
9 | Sliding should trigger changes that affect the local state.`;
10 |
11 |
12 | const demoCode = () => {
13 | class CustomSlider extends React.Component {
14 | constructor(props) {
15 | super(props);
16 | this.state = {
17 | value: 0,
18 | };
19 | this.handleChange = this.handleChange.bind(this);
20 | }
21 | handleChange(value) {
22 | this.setState({ value });
23 | }
24 | render() {
25 | return (
26 |
27 |
33 |
34 | );
35 | }
36 | }
37 |
38 | // NOTE - ONLY return block will be documented as src - find out how to show above code
39 | return ( );
40 | };
41 |
42 | const propDocs = { inline: true, propTables: [Slider] };
43 |
44 | export default () => storiesOf(displayName, module)
45 | .addWithInfo(
46 | title,
47 | description,
48 | demoCode,
49 | propDocs,
50 | );
--------------------------------------------------------------------------------
/src/LeafletMap/LeafletMap.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { mount } from 'enzyme';
3 | import { Map, TileLayer } from 'react-leaflet';
4 | import LeafletMap from './LeafletMap';
5 |
6 | describe('LeafletMap', () => {
7 | const props = {
8 | width: 600,
9 | height: 400,
10 | zoom: 5,
11 | center: [20, 10],
12 | scrollWheelZoom: true,
13 | };
14 |
15 | const wrapper = mount(
16 |
17 |
18 |
19 | ,
20 | );
21 |
22 | /**
23 | * shorthand getter function to find react-leaflet map
24 | */
25 | const getMap = () => wrapper.find(Map).at(0);
26 |
27 | it('should render a react-leaflet map', () => {
28 | expect(wrapper.find(Map)).to.have.length(1);
29 | });
30 |
31 | it('should pass all "extra" props to react-leaflet map', () => {
32 | const { zoom, center, scrollWheelZoom } = props;
33 | expect(getMap()).to.have.props({ zoom, center, scrollWheelZoom });
34 | });
35 |
36 | it('should render at least one tile-layer inside react-leaflet map', () => {
37 | expect(getMap().find(TileLayer)).to.have.length.above(0);
38 | });
39 |
40 | it('should create a map of specified width and height', () => {
41 | expect(getMap()).to.have.style('width', '600px');
42 | expect(getMap()).to.have.style('height', '400px');
43 | });
44 |
45 | it('should pass children to react-leaflet map', () => {
46 | expect(getMap().children().find('div')).to.have.length(1);
47 | expect(getMap().children().find('span')).to.have.length(1);
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/lib/Footer/Footer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _LogoStandard = require('../Logo/LogoStandard');
12 |
13 | var _LogoStandard2 = _interopRequireDefault(_LogoStandard);
14 |
15 | var _ScrollToTop = require('../ScrollToTop/ScrollToTop');
16 |
17 | var _ScrollToTop2 = _interopRequireDefault(_ScrollToTop);
18 |
19 | var _Footer = require('./Footer.css');
20 |
21 | var _Footer2 = _interopRequireDefault(_Footer);
22 |
23 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24 |
25 | var Footer = function Footer() {
26 | return _react2.default.createElement(
27 | 'div',
28 | { className: _Footer2.default.footer },
29 | _react2.default.createElement(
30 | 'div',
31 | { className: _Footer2.default.copyright },
32 | '\xA9 Copyright ',
33 | new Date().getFullYear()
34 | ),
35 | _react2.default.createElement(
36 | 'div',
37 | { className: _Footer2.default.logo },
38 | _react2.default.createElement(_LogoStandard2.default, null)
39 | ),
40 | _react2.default.createElement(
41 | 'div',
42 | { className: _Footer2.default.scrollToTop },
43 | _react2.default.createElement(_ScrollToTop2.default, { iconStyle: 'fa fa-angle-up' })
44 | )
45 | );
46 | };
47 |
48 | Footer.displayName = 'Footer';
49 |
50 | exports.default = Footer;
51 | // src={isClient ? require('../../assets/civic-logo-stack_standard.svg') : ''}
--------------------------------------------------------------------------------
/lib/Slider/Slider.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _SliderTooltip = require('./SliderTooltip');
12 |
13 | var _SliderTooltip2 = _interopRequireDefault(_SliderTooltip);
14 |
15 | var _RcSlider = require('./RcSlider');
16 |
17 | var _RcSlider2 = _interopRequireDefault(_RcSlider);
18 |
19 | var _isClient = require('../utils/isClient');
20 |
21 | var _isClient2 = _interopRequireDefault(_isClient);
22 |
23 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24 |
25 | var Slider = function Slider(_ref) {
26 | var value = _ref.value,
27 | onChange = _ref.onChange,
28 | min = _ref.min,
29 | max = _ref.max;
30 |
31 | if (_isClient2.default) {
32 | require('!style-loader!css-loader!rc-slider/assets/index.css'); // eslint-disable-line
33 | require('!style-loader!css-loader!./SliderBox.css'); // eslint-disable-line
34 | }
35 | return _react2.default.createElement(
36 | 'div',
37 | null,
38 | _react2.default.createElement(_RcSlider2.default, { tipformatter: null, min: min, max: max, value: value, onChange: onChange }),
39 | _react2.default.createElement(_SliderTooltip2.default, { value: value })
40 | );
41 | };
42 | Slider.propTypes = {
43 | value: _react2.default.PropTypes.number,
44 | onChange: _react2.default.PropTypes.func,
45 | max: _react2.default.PropTypes.number,
46 | min: _react2.default.PropTypes.number
47 | };
48 |
49 | exports.default = Slider;
--------------------------------------------------------------------------------
/stories/RechartsPie.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import { RechartsPie } from '../src';
4 | import { colors } from './shared';
5 |
6 | const propDocs = { inline: true, propTables: [RechartsPie] };
7 |
8 | const displayName = RechartsPie.displayName || 'RechartsPie';
9 | const title = 'Simple usage';
10 | const description = `
11 | This is a Recharts PieChart with a Recharts Legend component`;
12 |
13 | const data = [
14 | { name: 'Group A', value: 400 }, { name: 'Group B', value: 300 },
15 | { name: 'Group C', value: 300 }, { name: 'Group D', value: 200 },
16 | ];
17 |
18 | // This base can be adjusted to scale up or down the chart and legend
19 | const proportionBase = 200;
20 |
21 | // These multipliers can be adjusted to modify the individual
22 | const chartProportions = {
23 | chartWidth: proportionBase * 2,
24 | chartHeight: proportionBase * 1,
25 | iconSize: proportionBase * 0.075,
26 | pieInnerRadius: proportionBase * 0.2,
27 | pieOuterRadius: proportionBase * 0.4,
28 | };
29 |
30 | // Styles here based on src/Pie/Pie.css
31 | const styles = {
32 | fontFamily: 'Roboto Condensed',
33 | fontSize: proportionBase * 0.08,
34 | fontWeight: 400,
35 | color: '#706371',
36 | fill: '#706371',
37 | };
38 |
39 | const demoCode = () => (
40 |
46 | );
47 |
48 | export default () => storiesOf(displayName, module)
49 | .addWithInfo(
50 | title,
51 | description,
52 | demoCode,
53 | propDocs,
54 | );
55 |
--------------------------------------------------------------------------------
/lib/StoryCard/StoryLink.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _reactRouter = require('react-router');
12 |
13 | var _StoryLink = require('./StoryLink.css');
14 |
15 | var _StoryLink2 = _interopRequireDefault(_StoryLink);
16 |
17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18 |
19 | var StoryLink = function StoryLink(_ref) {
20 | var children = _ref.children,
21 | icon = _ref.icon,
22 | route = _ref.route,
23 | action = _ref.action;
24 | return _react2.default.createElement(
25 | 'div',
26 | { className: _StoryLink2.default.storylink },
27 | route ? _react2.default.createElement(
28 | _reactRouter.Link,
29 | { to: route },
30 | _react2.default.createElement('i', { className: icon }),
31 | _react2.default.createElement(
32 | 'span',
33 | null,
34 | children
35 | )
36 | ) : _react2.default.createElement(
37 | 'a',
38 | { tabIndex: '0', onClick: action },
39 | _react2.default.createElement('i', { className: icon }),
40 | _react2.default.createElement(
41 | 'span',
42 | null,
43 | children
44 | )
45 | )
46 | );
47 | };
48 |
49 | StoryLink.displayName = 'StoryLink';
50 | StoryLink.propTypes = {
51 | action: _react.PropTypes.func,
52 | children: _react.PropTypes.node,
53 | icon: _react.PropTypes.string,
54 | route: _react.PropTypes.string
55 | };
56 |
57 | exports.default = StoryLink;
--------------------------------------------------------------------------------
/lib/Tag/Tag.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _templateObject = _taggedTemplateLiteral(['\n padding: 6px 6px 6px 6px;\n text-align: center;\n transition: all .2s ease-in-out;\n font-size: 1em;\n font-weight: 500;\n color: rgba(255, 255, 255, 1);\n cursor: pointer;\n border: 2px solid rgba(255, 255, 255, 1);\n'], ['\n padding: 6px 6px 6px 6px;\n text-align: center;\n transition: all .2s ease-in-out;\n font-size: 1em;\n font-weight: 500;\n color: rgba(255, 255, 255, 1);\n cursor: pointer;\n border: 2px solid rgba(255, 255, 255, 1);\n']);
8 |
9 | var _react = require('react');
10 |
11 | var _react2 = _interopRequireDefault(_react);
12 |
13 | var _styledComponents = require('styled-components');
14 |
15 | var _styledComponents2 = _interopRequireDefault(_styledComponents);
16 |
17 | var _reactRouter = require('react-router');
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
22 |
23 | var StyledLink = (0, _styledComponents2.default)(_reactRouter.Link)(_templateObject);
24 |
25 | var Tag = function Tag(props) {
26 | return _react2.default.createElement(
27 | StyledLink,
28 | { to: props.location },
29 | props.name
30 | );
31 | };
32 |
33 | Tag.displayName = 'Tag';
34 | Tag.propTypes = {
35 | location: _react2.default.PropTypes.string,
36 | name: _react2.default.PropTypes.string
37 | };
38 |
39 | exports.default = Tag;
--------------------------------------------------------------------------------
/src/StoryCard/StoryCard.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import StoryCard from './StoryCard';
4 |
5 | describe('StoryCard', () => {
6 | const { title, cardId, collectionId } = {
7 | title: 'Test Story Card Title',
8 | cardId: 'card1',
9 | collectionId: 'collection1',
10 | };
11 |
12 | describe('common properties', () => {
13 | const wrapper = shallow(
14 | ,
15 | );
16 |
17 | it('should render the title as an h2', () => {
18 | const h2 = wrapper.find('h2');
19 |
20 | expect(h2.text()).to.contain(title);
21 | expect(h2.props().className).to.contain('Title');
22 | expect(h2.props().className).to.contain('FilsonSoft');
23 | });
24 |
25 | it('should include a StoryFooter that references this StoryCard', () => {
26 | const footer = wrapper.find('StoryFooter');
27 |
28 | expect(footer.props().cardId).to.equal(cardId);
29 | expect(footer.props().collectionId).to.equal(collectionId);
30 | });
31 | });
32 |
33 | describe('card children', () => {
34 | const wrapper = shallow(
35 |
36 | Some content
37 |
38 | Some other stuff
39 |
40 | ,
41 | );
42 |
43 | it('should render children into a container div under the title', () => {
44 | expect(wrapper.children()).to.have.length(3);
45 | expect(wrapper.find('h2 + div').children()).to.have.length(2);
46 | });
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/src/Navigation/Header.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes, Component } from 'react';
2 | import Nav from './Nav';
3 | import Logo from '../Logo/LogoAnimated';
4 | import styles from './Header.css';
5 | import Icon from '../Icon/Icon';
6 | import { ICONS } from '../styleConstants';
7 |
8 | class Header extends Component {
9 | constructor() {
10 | super();
11 | this.state = {
12 | menuActive: false,
13 | };
14 | }
15 |
16 | togglesNestedMenu = () => this.setState({ menuActive: !this.state.menuActive })
17 |
18 | render() {
19 | const { children, menu, title } = this.props;
20 | return (
21 |
22 |
23 |
24 |
25 |
26 |
27 |
33 |
34 | { children }
35 |
36 |
37 |
42 |
43 |
44 |
45 | );
46 | }
47 |
48 | }
49 |
50 | Header.displayName = 'Header';
51 | Header.propTypes = {
52 | menu: PropTypes.arrayOf(PropTypes.shape({})),
53 | title: PropTypes.string,
54 | children: PropTypes.node,
55 | };
56 |
57 | export default Header;
58 |
--------------------------------------------------------------------------------
/stories/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf, linkTo } from '@kadira/storybook'; // eslint-disable-line
3 | import buttonStory from './Button.story';
4 | import storycardStory from './StoryCard.story';
5 | import storyLinkStory from './StoryLink.story';
6 | import storyFooterStory from './StoryFooter.story';
7 | import editableStory from './Editable.story';
8 | import pieStory from './Pie.story';
9 | import sliderStory from './Slider.story';
10 | import areaChartStory from './AreaChart.story';
11 | import scrollToTopStory from './ScrollToTop.story';
12 | import barChartStory from './BarChart.story';
13 | import footerStory from './Footer.story';
14 | import sankeyStory from './Sankey.story';
15 | import headerStory from './Header.story';
16 | import leafletMap from './LeafletMap.story';
17 | import Welcome from './Welcome';
18 | import dropdownStory from './Dropdown.story';
19 | import rechartsPie from './RechartsPie.story';
20 | import heroStory from './Hero.story';
21 | import scatterplotStory from './Scatterplot.story';
22 |
23 | import '../src/global.styles.css';
24 | import '../assets/leaflet.css';
25 |
26 | // stories can be added directly here
27 | storiesOf('Welcome', module)
28 | .add('to Storybook', () => (
29 |
30 | ));
31 |
32 | // or imported as functions from files then composed in the order you invoke them
33 | editableStory();
34 | headerStory();
35 | buttonStory();
36 | storyLinkStory();
37 | storyFooterStory();
38 | storycardStory();
39 | sliderStory();
40 | pieStory();
41 | areaChartStory();
42 | dropdownStory();
43 | barChartStory();
44 | footerStory();
45 | sankeyStory();
46 | scrollToTopStory();
47 | rechartsPie();
48 | leafletMap();
49 | heroStory();
50 | scatterplotStory();
51 |
--------------------------------------------------------------------------------
/lib/RechartsPie/RechartsPie.test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _react = require('react');
4 |
5 | var _react2 = _interopRequireDefault(_react);
6 |
7 | var _enzyme = require('enzyme');
8 |
9 | var _RechartsPie = require('./RechartsPie');
10 |
11 | var _RechartsPie2 = _interopRequireDefault(_RechartsPie);
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | describe('Recharts Pie', function () {
16 | var _data$styles$colors$c = {
17 | data: [{ name: 'Group A', value: 400 }],
18 | styles: { fontFamily: 'Roboto Condensed', fontSize: '8', color: '#706371', fill: '#706371' },
19 | colors: ['#a6cee3', '#1f78b4'],
20 | chartProportions: {
21 | chartWidth: 2,
22 | chartHeight: 1,
23 | iconSize: 0.075,
24 | pieInnerRadius: 0.2,
25 | pieOuterRadius: 0.4
26 | }
27 | },
28 | data = _data$styles$colors$c.data,
29 | colors = _data$styles$colors$c.colors,
30 | styles = _data$styles$colors$c.styles,
31 | chartProportions = _data$styles$colors$c.chartProportions;
32 |
33 |
34 | var wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_RechartsPie2.default, {
35 | data: data,
36 | chartProportions: chartProportions,
37 | colors: colors,
38 | styles: styles
39 | }));
40 |
41 | it('should render a div', function () {
42 | expect(wrapper.find('div')).to.have.length(1);
43 | });
44 |
45 | it('should render a div with one child element', function () {
46 | expect(wrapper.find('div').children()).to.have.length(1);
47 | });
48 |
49 | it('should render a div with one child element that itself has two children elements', function () {
50 | expect(wrapper.find('div').children().props().children).to.have.length(2);
51 | });
52 | });
--------------------------------------------------------------------------------
/src/StoryCard/StoryFooter.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import copy from 'copy-to-clipboard';
3 | import StoryLink from './StoryLink';
4 | import { ICONS } from '../styleConstants';
5 | import styles from './StoryFooter.css';
6 |
7 | const MS_TO_SWITCH_TEXT = 3000; // 3 seconds
8 |
9 | export default class StoryFooter extends Component {
10 |
11 | static defaultProps = {
12 | cardId: 'some-card-id',
13 | collectionId: 'some-collection-id',
14 | }
15 |
16 | static propTypes = {
17 | cardId: PropTypes.string,
18 | collectionId: PropTypes.string,
19 | }
20 |
21 | constructor(props) {
22 | super(props);
23 | this.state = {
24 | copied: false,
25 | };
26 | }
27 |
28 | setToFalse = () => this.setState({ copied: false });
29 |
30 | switchState = ms => setTimeout(this.setToFalse, ms);
31 |
32 | handleCopy = () => {
33 | const { collectionId, cardId } = this.props;
34 | // NOTE: we need to make sure this will work on all browsers
35 | copy(`${window.location.origin}/${collectionId}/${cardId}`);
36 | this.switchState(MS_TO_SWITCH_TEXT);
37 | this.setState({ copied: true });
38 | }
39 |
40 | render() {
41 | const { collectionId, cardId } = this.props;
42 | const shareTxt = this.state.copied ? 'Link copied!' : 'Share card'; // if copied, show Link copied, otherwise, show Share card
43 | const shareIcon = this.state.copied ? ICONS.check : ICONS.link;
44 | return (
45 |
46 | View card
47 | {shareTxt}
48 |
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/AreaChart/AreaChart.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import {
3 | AreaChart, XAxis, YAxis, CartesianGrid, Area, Legend, Tooltip,
4 | } from 'recharts';
5 |
6 | const StackedAreaChart = ({ data, colors }) => {
7 | const gradients = [];
8 | const lines = [];
9 |
10 | const myKeys = Object.keys(data[0]);
11 | myKeys.forEach((key, index) => {
12 | if (key !== 'name') {
13 | lines.push( );
21 | gradients.push(
22 |
27 |
28 |
29 | );
30 | }
31 | });
32 |
33 | return (
34 |
35 |
36 |
37 |
38 | {gradients}
39 |
40 |
41 |
42 |
43 |
44 | {lines}
45 |
46 |
47 | );
48 | };
49 |
50 | StackedAreaChart.propTypes = {
51 | data: PropTypes.arrayOf(PropTypes.object).isRequired,
52 | colors: PropTypes.arrayOf(PropTypes.string).isRequired,
53 | };
54 |
55 | export default StackedAreaChart;
56 |
--------------------------------------------------------------------------------
/lib/RechartsPie/RechartsPie.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _recharts = require('recharts');
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | var RechartsPie = function RechartsPie(_ref) {
16 | var data = _ref.data,
17 | chartProportions = _ref.chartProportions,
18 | colors = _ref.colors,
19 | styles = _ref.styles;
20 | return _react2.default.createElement(
21 | 'div',
22 | { style: { display: 'flex', justifyContent: 'space-around', margin: 'auto' } },
23 | _react2.default.createElement(
24 | _recharts.PieChart,
25 | { width: chartProportions.chartWidth, height: chartProportions.chartHeight, data: data },
26 | _react2.default.createElement(_recharts.Legend, { layout: 'vertical', iconSize: chartProportions.iconSize, wrapperStyle: styles, iconType: 'square', verticalAlign: 'middle', align: 'right' }),
27 | _react2.default.createElement(
28 | _recharts.Pie,
29 | { data: data, cx: '50%', cy: '50%', innerRadius: chartProportions.pieInnerRadius, outerRadius: chartProportions.pieOuterRadius },
30 | data.map(function (entry, index) {
31 | return _react2.default.createElement(_recharts.Cell, { key: 'cell-' + index, fill: colors[index] });
32 | })
33 | )
34 | )
35 | );
36 | };
37 |
38 | RechartsPie.propTypes = {
39 | data: _react.PropTypes.arrayOf(_react.PropTypes.object).isRequired,
40 | chartProportions: _react.PropTypes.object.isRequired,
41 | colors: _react.PropTypes.arrayOf(_react.PropTypes.string),
42 | styles: _react.PropTypes.object
43 | };
44 |
45 | exports.default = RechartsPie;
--------------------------------------------------------------------------------
/lib/Navigation/NavRouterLink.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
8 |
9 | var _react = require('react');
10 |
11 | var _react2 = _interopRequireDefault(_react);
12 |
13 | var _reactRouter = require('react-router');
14 |
15 | var _NavRouterLink = require('./NavRouterLink.css');
16 |
17 | var _NavRouterLink2 = _interopRequireDefault(_NavRouterLink);
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | var pathOrName = function pathOrName(p, n) {
22 | return p || '/' + n.toLowerCase();
23 | };
24 |
25 | var NavRouterLink = function NavRouterLink(_ref) {
26 | var path = _ref.path,
27 | customStyles = _ref.customStyles,
28 | name = _ref.name;
29 |
30 | var boxStyle = customStyles ? customStyles.box : null;
31 | var linkStyle = customStyles ? customStyles.link : null;
32 | var pathTo = pathOrName(path, name);
33 |
34 | return _react2.default.createElement(
35 | 'li',
36 | { className: _NavRouterLink2.default.NavRouterLink, style: _extends({}, boxStyle) },
37 | _react2.default.createElement(
38 | _reactRouter.Link,
39 | { to: pathTo },
40 | _react2.default.createElement(
41 | 'span',
42 | { style: _extends({}, linkStyle) },
43 | name
44 | )
45 | )
46 | );
47 | };
48 |
49 | NavRouterLink.propTypes = {
50 | name: _react.PropTypes.string,
51 | path: _react.PropTypes.string,
52 | customStyles: _react.PropTypes.object
53 | };
54 |
55 | exports.default = NavRouterLink;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Outdated, currently maintained in [civic](https://github.com/hackoregon/civic) repository
2 |
3 | ## Hack Oregon's React Component Library
4 | ---
5 | ###### v 0.2.5
6 | ### Install
7 | ```bash
8 | $ npm i @hackoregon/component-library --save
9 | # or
10 | $ yarn add @hackoregon/component-library
11 | ```
12 |
13 | Hack Oregon's [React](http://facebook.github.io/react/) Component Library is a work in progress that encompasses platform components, a style guide, as well as data visualization components to be shared across projects.
14 |
15 | For styling, we are using [CSS Modules](https://github.com/css-modules/css-modules).
16 |
17 | The components that end up here are either built using [React Storybook](https://getstorybook.io) or were ported into the Storybook dev environment. We believe this will allow us to make cross project compatible components.
18 |
19 | Documentation for usage of these components and visual examples will be available at [Hack Oregon's Storybook](https://hackoregon.github.io/component-library/).
20 |
21 | ### Contributing
22 | Our issues/requests are tracked on waffle.io **==>** [](https://waffle.io/hackoregon/component-library)
23 |
24 | 1. Get Node 6.5 + - I recommend using [Node Version Manager](https://github.com/creationix/nvm).
25 | 2. `git clone https://github.com/hackoregon/component-library.git`
26 | 3. Install with `yarn` so that your npm packages are in sync.
27 | 4. `npm start` - spin up the storybook dev environment with hot module replacement.
28 | 5. `npm test` - run tests while coding
29 | 6. Code/Add components in the src folder with .test files alongside the source code.
30 | 7. Add stories in the story folder with .story extension.
31 | 8. Make a pull request to master from feature branches.
32 |
--------------------------------------------------------------------------------
/stories/shared.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const wallOfText = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
4 | export const wallOfRichText = (
5 |
6 |
Lorem ipsum dolor sit amet , consectetur adipisicing elit,
7 |
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
8 |
9 | Ut enim ad
10 | minim veniam, quis nostrud
11 | exercitation ullamco laboris
12 |
13 | nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
14 | velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
15 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
16 |
17 | );
18 |
19 | export const colors = [
20 | '#a6cee3',
21 | '#1f78b4',
22 | '#b2df8a',
23 | '#33a02c',
24 | '#fb9a99',
25 | '#e31a1c',
26 | '#fdbf6f',
27 | '#ff7f00',
28 | '#cab2d6',
29 | '#6a3d9a',
30 | '#ffff99',
31 | '#b15928',
32 | '#8dd3c7',
33 | '#fb8072',
34 | '#80b1d3',
35 | '#bebada',
36 | '#ffed6f',
37 | '#fdb462',
38 | '#b3de69',
39 | '#fccde5',
40 | '#d9d9d9',
41 | '#bc80bd',
42 | '#ccebc5',
43 | '#ffffb3',
44 | ];
45 | export const randomizer = () => Math.random() * 100;
46 | export const getColors = (datum, idx) => (arguments.length === 2 ? colors[idx] : colors[datum]);
47 | export const getRandomValuesArray = (numsOf, func) => [...new Array(numsOf)].map(func);
48 |
--------------------------------------------------------------------------------
/stories/StoryLink.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf, action } from '@kadira/storybook';
3 | import { withKnobs, text, object } from '@kadira/storybook-addon-knobs';
4 | import StoryLink from '../src/StoryCard/StoryLink';
5 | import { ICONS } from '../src/styleConstants';
6 |
7 | const collectionId = 'collection-id';
8 | const cardId = 'cardId';
9 |
10 | const propTableOptions = { inline: true, propTables: [StoryLink] };
11 | const wrapperStyle = { width: '30%', padding: '10%', margin: '0 auto' };
12 | export default () => storiesOf('StoryLink', module)
13 | .addDecorator(withKnobs)
14 | .addWithInfo(
15 | 'that can link to full page card',
16 | 'Wraps react-router , so that when given a route prop, it will route to the right part of the application.',
17 | () => (
18 |
19 | View card
20 |
21 | ),
22 | propTableOptions,
23 | )
24 | .addWithInfo(
25 | 'that can take an action',
26 | 'Either use it with component functions, or dispatch redux actions',
27 | () => (
28 |
29 | Download!
30 |
31 | ),
32 | propTableOptions,
33 | )
34 | .addWithInfo(
35 | 'takes any font awesome icon',
36 | 'Try switching the font awesome classnames with the knobs below to check out different looks.',
37 | () => {
38 | const fontAwesomeIcon = text('Font Awesome class', 'fa fa-code');
39 | return (
40 |
41 | {fontAwesomeIcon}
42 |
);
43 | },
44 | propTableOptions,
45 | );
46 |
--------------------------------------------------------------------------------
/lib/LeafletMap/LeafletMap.test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _react = require('react');
4 |
5 | var _react2 = _interopRequireDefault(_react);
6 |
7 | var _enzyme = require('enzyme');
8 |
9 | var _reactLeaflet = require('react-leaflet');
10 |
11 | var _LeafletMap = require('./LeafletMap');
12 |
13 | var _LeafletMap2 = _interopRequireDefault(_LeafletMap);
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | describe('LeafletMap', function () {
18 | var props = {
19 | width: 600,
20 | height: 400,
21 | zoom: 5,
22 | center: [20, 10],
23 | scrollWheelZoom: true
24 | };
25 |
26 | var wrapper = (0, _enzyme.mount)(_react2.default.createElement(
27 | _LeafletMap2.default,
28 | props,
29 | _react2.default.createElement('div', null),
30 | _react2.default.createElement('span', null)
31 | ));
32 |
33 | /**
34 | * shorthand getter function to find react-leaflet map
35 | */
36 | var getMap = function getMap() {
37 | return wrapper.find(_reactLeaflet.Map).at(0);
38 | };
39 |
40 | it('should render a react-leaflet map', function () {
41 | expect(wrapper.find(_reactLeaflet.Map)).to.have.length(1);
42 | });
43 |
44 | it('should pass all "extra" props to react-leaflet map', function () {
45 | var zoom = props.zoom,
46 | center = props.center,
47 | scrollWheelZoom = props.scrollWheelZoom;
48 |
49 | expect(getMap()).to.have.props({ zoom: zoom, center: center, scrollWheelZoom: scrollWheelZoom });
50 | });
51 |
52 | it('should render at least one tile-layer inside react-leaflet map', function () {
53 | expect(getMap().find(_reactLeaflet.TileLayer)).to.have.length.above(0);
54 | });
55 |
56 | it('should create a map of specified width and height', function () {
57 | expect(getMap()).to.have.style('width', '600px');
58 | expect(getMap()).to.have.style('height', '400px');
59 | });
60 |
61 | it('should pass children to react-leaflet map', function () {
62 | expect(getMap().children().find('div')).to.have.length(1);
63 | expect(getMap().children().find('span')).to.have.length(1);
64 | });
65 | });
--------------------------------------------------------------------------------
/lib/StamenMap/StamenMap.test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _react = require('react');
4 |
5 | var _react2 = _interopRequireDefault(_react);
6 |
7 | var _enzyme = require('enzyme');
8 |
9 | var _reactLeaflet = require('react-leaflet');
10 |
11 | var _LeafletMap = require('./LeafletMap');
12 |
13 | var _LeafletMap2 = _interopRequireDefault(_LeafletMap);
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | describe('LeafletMap', function () {
18 | var props = {
19 | width: 600,
20 | height: 400,
21 | zoom: 5,
22 | center: [20, 10],
23 | scrollWheelZoom: true
24 | };
25 |
26 | var wrapper = (0, _enzyme.mount)(_react2.default.createElement(
27 | _LeafletMap2.default,
28 | props,
29 | _react2.default.createElement('div', null),
30 | _react2.default.createElement('span', null)
31 | ));
32 |
33 | /**
34 | * shorthand getter function to find react-leaflet map
35 | */
36 | var getMap = function getMap() {
37 | return wrapper.find(_reactLeaflet.Map).at(0);
38 | };
39 |
40 | it('should render a react-leaflet map', function () {
41 | expect(wrapper.find(_reactLeaflet.Map)).to.have.length(1);
42 | });
43 |
44 | it('should pass all "extra" props to react-leaflet map', function () {
45 | var zoom = props.zoom,
46 | center = props.center,
47 | scrollWheelZoom = props.scrollWheelZoom;
48 |
49 | expect(getMap()).to.have.props({ zoom: zoom, center: center, scrollWheelZoom: scrollWheelZoom });
50 | });
51 |
52 | it('should render at least one tile-layer inside react-leaflet map', function () {
53 | expect(getMap().find(_reactLeaflet.TileLayer)).to.have.length.above(0);
54 | });
55 |
56 | it('should create a map of specified width and height', function () {
57 | expect(getMap()).to.have.style('width', '600px');
58 | expect(getMap()).to.have.style('height', '400px');
59 | });
60 |
61 | it('should pass children to react-leaflet map', function () {
62 | expect(getMap().children().find('div')).to.have.length(1);
63 | expect(getMap().children().find('span')).to.have.length(1);
64 | });
65 | });
--------------------------------------------------------------------------------
/src/Chart/Chart.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 |
3 | export default class Chart extends Component {
4 |
5 | static displayName = 'Chart'
6 |
7 | static childContextTypes = {
8 | height: PropTypes.number,
9 | width: PropTypes.number,
10 | margin: PropTypes.shape({
11 | top: PropTypes.number,
12 | bottom: PropTypes.number,
13 | left: PropTypes.number,
14 | right: PropTypes.number,
15 | }),
16 | };
17 |
18 | static propTypes = {
19 | height: PropTypes.number,
20 | width: PropTypes.number,
21 | children: PropTypes.node,
22 | margin: PropTypes.shape({
23 | top: PropTypes.number,
24 | bottom: PropTypes.number,
25 | left: PropTypes.number,
26 | right: PropTypes.number,
27 | }),
28 | };
29 |
30 | static defaultProps = {
31 | height: 0,
32 | width: 0,
33 | margin: {
34 | top: 0,
35 | bottom: 0,
36 | left: 0,
37 | right: 0,
38 | },
39 | };
40 |
41 |
42 | getChildContext() {
43 | const { width, height } = this.props;
44 | let { margin } = this.props;
45 |
46 | margin = {
47 | ...margin,
48 | top: 0,
49 | bottom: 0,
50 | left: 0,
51 | right: 0,
52 | };
53 |
54 | return { width, height, margin };
55 | }
56 | render() {
57 | const { width, height } = this.props;
58 | let { margin } = this.props;
59 |
60 | margin = {
61 | ...margin,
62 | top: 0,
63 | bottom: 0,
64 | left: 0,
65 | right: 0,
66 | };
67 |
68 | const insetString = `translate(${margin.left}, ${margin.top})`;
69 |
70 | return (
71 |
80 |
81 |
82 | {this.props.children}
83 |
84 |
85 |
86 |
91 |
92 | );
93 | }
94 | }
--------------------------------------------------------------------------------
/lib/StoryCard/StoryCard.test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _react = require('react');
4 |
5 | var _react2 = _interopRequireDefault(_react);
6 |
7 | var _enzyme = require('enzyme');
8 |
9 | var _StoryCard = require('./StoryCard');
10 |
11 | var _StoryCard2 = _interopRequireDefault(_StoryCard);
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | describe('StoryCard', function () {
16 | var _title$cardId$collect = {
17 | title: 'Test Story Card Title',
18 | cardId: 'card1',
19 | collectionId: 'collection1'
20 | },
21 | title = _title$cardId$collect.title,
22 | cardId = _title$cardId$collect.cardId,
23 | collectionId = _title$cardId$collect.collectionId;
24 |
25 |
26 | describe('common properties', function () {
27 | var wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_StoryCard2.default, { cardId: cardId, collectionId: collectionId, title: title }));
28 |
29 | it('should render the title as an h2', function () {
30 | var h2 = wrapper.find('h2');
31 |
32 | expect(h2.text()).to.contain(title);
33 | expect(h2.props().className).to.contain('Title');
34 | expect(h2.props().className).to.contain('FilsonSoft');
35 | });
36 |
37 | it('should include a StoryFooter that references this StoryCard', function () {
38 | var footer = wrapper.find('StoryFooter');
39 |
40 | expect(footer.props().cardId).to.equal(cardId);
41 | expect(footer.props().collectionId).to.equal(collectionId);
42 | });
43 | });
44 |
45 | describe('card children', function () {
46 | var wrapper = (0, _enzyme.shallow)(_react2.default.createElement(
47 | _StoryCard2.default,
48 | { cardId: cardId, collectionId: collectionId, title: title },
49 | _react2.default.createElement(
50 | 'div',
51 | { className: 'Description' },
52 | 'Some content'
53 | ),
54 | _react2.default.createElement(
55 | 'div',
56 | null,
57 | 'Some other stuff'
58 | )
59 | ));
60 |
61 | it('should render children into a container div under the title', function () {
62 | expect(wrapper.children()).to.have.length(3);
63 | expect(wrapper.find('h2 + div').children()).to.have.length(2);
64 | });
65 | });
66 | });
--------------------------------------------------------------------------------
/lib/Slider/SliderTooltip.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require("react");
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12 |
13 | var SliderTooltip = function SliderTooltip(_ref) {
14 | var value = _ref.value;
15 | return _react2.default.createElement(
16 | "div",
17 | { className: "panel panel-default" },
18 | _react2.default.createElement(
19 | "div",
20 | { className: "panel-body" },
21 | _react2.default.createElement(
22 | "ul",
23 | { className: "list-inline" },
24 | _react2.default.createElement(
25 | "li",
26 | null,
27 | _react2.default.createElement(
28 | "span",
29 | { className: "hour" },
30 | "$ ",
31 | value.toFixed(2)
32 | ),
33 | " /hour"
34 | ),
35 | _react2.default.createElement(
36 | "li",
37 | null,
38 | _react2.default.createElement(
39 | "span",
40 | { className: "day" },
41 | "$ ",
42 | value * 8
43 | ),
44 | " /day"
45 | ),
46 | _react2.default.createElement(
47 | "li",
48 | null,
49 | _react2.default.createElement(
50 | "span",
51 | { className: "week" },
52 | "$ ",
53 | Math.round(value * 8 * 5)
54 | ),
55 | " /week"
56 | ),
57 | _react2.default.createElement(
58 | "li",
59 | null,
60 | _react2.default.createElement(
61 | "span",
62 | { className: "month" },
63 | "$ ",
64 | value * 8 * 22
65 | ),
66 | " /month"
67 | ),
68 | _react2.default.createElement(
69 | "li",
70 | null,
71 | _react2.default.createElement(
72 | "span",
73 | { className: "year" },
74 | "$ ",
75 | value * 8 * 22 * 12
76 | ),
77 | " /year"
78 | )
79 | )
80 | )
81 | );
82 | };
83 |
84 | exports.default = SliderTooltip;
--------------------------------------------------------------------------------
/lib/Dropdown/Dropdown.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _bind = require('classnames/bind');
12 |
13 | var _bind2 = _interopRequireDefault(_bind);
14 |
15 | var _reactSelect = require('react-select');
16 |
17 | var _reactSelect2 = _interopRequireDefault(_reactSelect);
18 |
19 | var _isClient = require('../utils/isClient');
20 |
21 | var _isClient2 = _interopRequireDefault(_isClient);
22 |
23 | var _DropdownStyles = require('./Dropdown.styles.css');
24 |
25 | var _DropdownStyles2 = _interopRequireDefault(_DropdownStyles);
26 |
27 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
28 |
29 | // NOTE: temporary fix until webpack 2 comes to storybook - otherwise don't use ! syntax for webpack loaders
30 | // if (isClient) require('!style-loader!css-loader!react-select/dist/react-select.css'); // eslint-disable-line
31 | if (_isClient2.default) require('../../assets/react-select.min.css'); // eslint-disable-line
32 |
33 | var cx = _bind2.default.bind(_DropdownStyles2.default);
34 |
35 | var className = cx({ base: true });
36 |
37 | var Dropdown = function Dropdown(_ref) {
38 | var options = _ref.options,
39 | onChange = _ref.onChange,
40 | value = _ref.value,
41 | clearable = _ref.clearable,
42 | searchable = _ref.searchable,
43 | disabled = _ref.disabled;
44 | return _react2.default.createElement(_reactSelect2.default, {
45 | className: className,
46 | options: options,
47 | onChange: onChange,
48 | value: value,
49 | clearable: clearable,
50 | searchable: searchable,
51 | disabled: disabled
52 | });
53 | };
54 |
55 | Dropdown.displayName = 'Dropdown';
56 |
57 | Dropdown.propTypes = {
58 | onChange: _react.PropTypes.func.isRequired,
59 | options: _react.PropTypes.array.isRequired,
60 | value: _react.PropTypes.any.isRequired, // eslint-disable-line react/forbid-prop-types
61 | clearable: _react.PropTypes.bool,
62 | searchable: _react.PropTypes.bool,
63 | disabled: _react.PropTypes.bool
64 | };
65 |
66 | Dropdown.defaultProps = {
67 | clearable: false,
68 | searchable: true,
69 | disabled: false
70 | };
71 |
72 | exports.default = Dropdown;
--------------------------------------------------------------------------------
/src/Navigation/Nav.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes, Component } from 'react';
2 | import NavSubMenu from './NavSubMenu';
3 | import NavLink from './NavRouterLink';
4 | import styles from './Nav.css';
5 | import Icon from '../Icon/Icon';
6 |
7 | const defaultMenu = [
8 | {
9 | name: 'Collections',
10 | path: '/collections',
11 | nestedMenu: [
12 | { name: 'Budget', path: '/collections/budget' },
13 | { name: 'Emergency Response', path: '/collections/emergency' },
14 | { name: 'Housing', path: '/collections/housing' },
15 | { name: 'Homelessness', path: '/collections/homlessness' },
16 | { name: 'Transportation', path: '/collections/transportation' },
17 | { name: 'Past Projects', path: '/collections/past-projects' },
18 | ],
19 | },
20 | { name: 'About', path: '/about' },
21 | ];
22 |
23 | class Nav extends Component {
24 | constructor() {
25 | super();
26 | this.state = {
27 | menuActive: false,
28 | items: [],
29 | };
30 | }
31 |
32 | handleClick = (name, menu, e) => {
33 | e.preventDefault();
34 | const items = !this.state.menuActive ? menu : [];
35 |
36 | this.setState(() => ({ menuActive: !this.state.menuActive, items }));
37 | }
38 |
39 | render() {
40 | const { menu = defaultMenu, toggleNestedMenu = this.handleClick } = this.props;
41 | return (
42 |
43 |
44 |
45 | {menu.map((item, idx) =>
46 | (item.nestedMenu
47 | ? toggleNestedMenu(item.name, item.nestedMenu, e)}>{item.name} // eslint-disable-line
48 | :
53 | ))
54 | }
55 |
56 |
57 |
58 | );
59 | }
60 | }
61 |
62 | Nav.propTypes = {
63 | menu: PropTypes.arrayOf(PropTypes.shape({ name: PropTypes.string, path: PropTypes.string })),
64 | toggleNestedMenu: PropTypes.func,
65 | toggleSubNav: PropTypes.func,
66 | };
67 |
68 | export default Nav;
69 |
--------------------------------------------------------------------------------
/stories/Welcome.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 |
3 | const styles = {
4 | main: {
5 | margin: 15,
6 | maxWidth: 600,
7 | lineHeight: 1.4,
8 | fontFamily: '"Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif',
9 | },
10 |
11 | logo: {
12 | width: 200,
13 | },
14 |
15 | link: {
16 | color: '#1474f3',
17 | textDecoration: 'none',
18 | borderBottom: '1px solid #1474f3',
19 | paddingBottom: 2,
20 | },
21 |
22 | code: {
23 | fontSize: 15,
24 | fontWeight: 600,
25 | padding: '2px 5px',
26 | border: '1px solid #eae9e9',
27 | borderRadius: 4,
28 | backgroundColor: '#f3f2f2',
29 | color: '#3a3a3a',
30 | },
31 | };
32 |
33 | export default class Welcome extends React.Component {
34 |
35 | static propTypes = {
36 | showApp: PropTypes.func,
37 | }
38 |
39 | constructor() {
40 | super();
41 | this.showApp = this.showApp.bind(this);
42 | }
43 |
44 | showApp(e) {
45 | e.preventDefault();
46 | if (this.props.showApp) this.props.showApp();
47 | }
48 |
49 | render() {
50 | return (
51 |
52 |
53 |
Welcome to Hack Oregon's Storybook
54 |
55 | This is a UI component dev environment for the component library.
56 |
57 |
58 | Stories are originating from the /stories directory.
59 |
60 | A story is a state of one or more UI components.
61 |
62 | (Basically a story is like a visual test case.)
63 |
64 |
65 | See these sample stories for a component called Button.
66 |
67 |
68 | Just like that, you can add your own components as stories.
69 |
70 | You can also edit those components and see changes right away.
71 |
72 | (Try editing the Button component
73 | located at src/stories/Button.js.)
74 |
75 |
76 | );
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/stories/Pie.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf, action } from '@kadira/storybook';
3 | import {
4 | withKnobs,
5 | text, number, object, array,
6 | } from '@kadira/storybook-addon-knobs';
7 | import { Chart, ChartData, Pie } from '../src';
8 | import { colors, getRandomValuesArray, randomizer } from './shared';
9 |
10 | export default () => storiesOf('Pie/Donut visualization').addDecorator(withKnobs)
11 | .addWithInfo(
12 | 'simple usage',
13 | 'edit this visual in the knobs tab below and check click events in the actions tab',
14 | () => {
15 | const labels = ['A', 'B', 'C', 'D', 'E', 'F'];
16 | const numberOfData = number('Amount of data values', 3);
17 | const getRandomColors = array('Array of colors', colors.slice(0, numberOfData));
18 | const getColors = (datum, idx) =>
19 | (arguments.length === 2 ? getRandomColors[idx] : getRandomColors[datum]);
20 | const values = getRandomValuesArray(numberOfData, randomizer);
21 | const style = object('Chart Width and Height', {
22 | width: 600,
23 | height: 250,
24 | });
25 | const titleText = text('Title text', 'Some title');
26 | const subtitleText = text('Subtitle text', 'Some subtitle');
27 | const titleFontSize = number('Title font size', 24);
28 | const subtitleFontSize = number('Subtitle font size', 14);
29 | const innerRadius = number('Inner Radius', 75);
30 |
31 | return (
32 |
33 |
34 |
35 | console.log(`${labels[i]} clicked`))}
38 | style={(d, i) => ({ fill: getColors(i) })}
39 | >
40 |
44 | {titleText}
45 |
46 |
50 | {subtitleText}
51 |
52 |
53 |
54 |
55 |
56 | );
57 | });
58 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "parser": "babel-eslint",
4 | "plugins": [
5 | "babel",
6 | "import",
7 | "jsx-a11y",
8 | "prefer-object-spread",
9 | "react"
10 | ],
11 | "parserOptions": {
12 | "ecmaVersion": 6.5,
13 | "ecmaFeatures": {
14 | "jsx": true,
15 | "modules": true,
16 | "spread": true,
17 | "experimentalObjectRestSpread": true
18 | }
19 | },
20 | "settings": {
21 | "import/parser": "babel-eslint",
22 | },
23 | "env": {
24 | "es6": true,
25 | "browser": true,
26 | "node": true,
27 | "mocha": true
28 | },
29 | "rules": {
30 | "brace-style": [1, "1tbs", {"allowSingleLine": true}],
31 | "eol-last": 0,
32 | "global-require": 0,
33 | "import/default": 2,
34 | "import/named": 2,
35 | "import/namespace": 2,
36 | "import/no-duplicates": 2,
37 | "import/no-extraneous-dependencies": ["error", {"devDependencies": ["**/*.story.js", "**/*.test.js", "./stories/index.js"]}],
38 | "import/no-named-as-default": 2,
39 | "import/no-unresolved": 2,
40 | "import/prefer-default-export": 0,
41 | "jsx-a11y/href-no-hash": 1,
42 | "jsx-quotes": 1,
43 | "max-len": [0, { "ignoreComments": true, "ignoreStrings": true }],
44 | "no-alert": 0,
45 | "no-console": 1,
46 | "no-debugger": 1,
47 | "no-lone-blocks": 0,
48 | "no-multi-spaces": 0,
49 | "no-trailing-spaces": 0,
50 | "no-underscore-dangle": 0,
51 | "no-unused-expressions": 0,
52 | "no-var": 1,
53 | "react/display-name": [ 1, {"ignoreTranspilerName": false }],
54 | "react/forbid-prop-types": [1, {"forbid": ["any"]}],
55 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
56 | "react/no-danger": 1,
57 | "react/no-did-mount-set-state": 1,
58 | "react/no-did-update-set-state": 1,
59 | "react/no-direct-mutation-state": 1,
60 | "react/no-multi-comp": 1,
61 | "react/no-set-state": 0,
62 | "react/no-unknown-property": 1,
63 | "react/no-unused-prop-types": [2, { "skipShapeProps": true }],
64 | "react/prefer-es6-class": 1,
65 | "react/prop-types": 1,
66 | "react/react-in-jsx-scope": 1,
67 | "react/require-extension": 1,
68 | "react/self-closing-comp": 1,
69 | "react/sort-comp": 1,
70 | "react/wrap-multilines": 1,
71 | "semi": [1, "always"]
72 | },
73 | "globals": {
74 | "__DEV__": true,
75 | "expect": true,
76 | "assert": true,
77 | "enzyme": true,
78 | "sinon": true,
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/lib/LeafletMap/LeafletMap.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
8 |
9 | var _react = require('react');
10 |
11 | var _react2 = _interopRequireDefault(_react);
12 |
13 | var _reactLeaflet = require('react-leaflet');
14 |
15 | var _isClient = require('../utils/isClient');
16 |
17 | var _isClient2 = _interopRequireDefault(_isClient);
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
22 |
23 | var LeafletMap = function LeafletMap(_ref) {
24 | var width = _ref.width,
25 | height = _ref.height,
26 | children = _ref.children,
27 | mapProps = _objectWithoutProperties(_ref, ['width', 'height', 'children']);
28 |
29 | return _react2.default.createElement(
30 | 'div',
31 | null,
32 | _isClient2.default && _react2.default.createElement(
33 | _reactLeaflet.Map,
34 | _extends({}, mapProps, { style: { width: width, height: height } }),
35 | _react2.default.createElement(_reactLeaflet.TileLayer, {
36 | url: mapProps.url,
37 | attribution: mapProps.attribution
38 | }),
39 | children
40 | )
41 | );
42 | };
43 |
44 | LeafletMap.propTypes = {
45 | center: _react.PropTypes.arrayOf(_react.PropTypes.number),
46 | zoom: _react.PropTypes.number,
47 | scrollWheelZoom: _react.PropTypes.bool,
48 | children: _react.PropTypes.node.isRequired,
49 | width: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.string]),
50 | height: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.string]),
51 | url: _react.PropTypes.string,
52 | attribution: _react.PropTypes.string
53 | };
54 |
55 | LeafletMap.defaultProps = {
56 | center: [0, 0],
57 | zoom: 0,
58 | width: '100%',
59 | height: 600,
60 | scrollWheelZoom: false,
61 | url: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
62 | attribution: "© OpenStreetMap contributors"
63 | };
64 |
65 | exports.default = LeafletMap;
--------------------------------------------------------------------------------
/lib/AreaChart/AreaChart.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _recharts = require('recharts');
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | var StackedAreaChart = function StackedAreaChart(_ref) {
16 | var data = _ref.data,
17 | colors = _ref.colors;
18 |
19 | var gradients = [];
20 | var lines = [];
21 |
22 | var myKeys = Object.keys(data[0]);
23 | myKeys.forEach(function (key, index) {
24 | if (key !== 'name') {
25 | lines.push(_react2.default.createElement(_recharts.Area, {
26 | type: 'monotone',
27 | key: '' + myKeys[index],
28 | dataKey: '' + myKeys[index],
29 | stroke: colors[index],
30 | fillOpacity: 1,
31 | fill: 'url(#color' + index + ')'
32 | }));
33 | gradients.push(_react2.default.createElement(
34 | 'linearGradient',
35 | {
36 | key: 'color' + index,
37 | id: 'color' + index,
38 | x1: '0', y1: '0', x2: '0', y2: '1'
39 | },
40 | _react2.default.createElement('stop', { offset: '5%', stopColor: colors[index], stopOpacity: 0.8 }),
41 | _react2.default.createElement('stop', { offset: '95%', stopColor: colors[index], stopOpacity: 0.1 })
42 | ));
43 | }
44 | });
45 |
46 | return _react2.default.createElement(
47 | 'div',
48 | { style: { display: 'flex', justifyContent: 'space-around', margin: 'auto' } },
49 | _react2.default.createElement(
50 | _recharts.AreaChart,
51 | { width: 730, height: 250, data: data },
52 | _react2.default.createElement(_recharts.Legend, { layout: 'vertical', iconType: 'square', verticalAlign: 'top', align: 'left' }),
53 | _react2.default.createElement(
54 | 'defs',
55 | null,
56 | gradients
57 | ),
58 | _react2.default.createElement(_recharts.XAxis, { dataKey: 'name' }),
59 | _react2.default.createElement(_recharts.YAxis, null),
60 | _react2.default.createElement(_recharts.CartesianGrid, { strokeDasharray: '3 3' }),
61 | _react2.default.createElement(_recharts.Tooltip, null),
62 | lines
63 | )
64 | );
65 | };
66 |
67 | StackedAreaChart.propTypes = {
68 | data: _react.PropTypes.arrayOf(_react.PropTypes.object).isRequired,
69 | colors: _react.PropTypes.arrayOf(_react.PropTypes.string).isRequired
70 | };
71 |
72 | exports.default = StackedAreaChart;
--------------------------------------------------------------------------------
/lib/StamenMap/StamenMap.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
8 |
9 | var _react = require('react');
10 |
11 | var _react2 = _interopRequireDefault(_react);
12 |
13 | var _reactLeaflet = require('react-leaflet');
14 |
15 | var _isClient = require('../utils/isClient');
16 |
17 | var _isClient2 = _interopRequireDefault(_isClient);
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
22 |
23 | var StamenMap = function StamenMap(_ref) {
24 | var width = _ref.width,
25 | height = _ref.height,
26 | children = _ref.children,
27 | mapProps = _objectWithoutProperties(_ref, ['width', 'height', 'children']);
28 |
29 | return _react2.default.createElement(
30 | 'div',
31 | null,
32 | _isClient2.default && _react2.default.createElement(
33 | _reactLeaflet.Map,
34 | _extends({}, mapProps, { style: { width: width, height: height } }),
35 | _react2.default.createElement(_reactLeaflet.TileLayer, {
36 | url: 'http://{s}.tile.stamen.com/toner-lite/{z}/{x}/{y}.png',
37 | attribution: 'Map tiles by Stamen Design , under CC BY 3.0 . Data by OpenStreetMap , under CC BY SA .'
38 | }),
39 | children
40 | )
41 | );
42 | };
43 | StamenMap.propTypes = {
44 | center: _react.PropTypes.arrayOf(_react.PropTypes.number),
45 | zoom: _react.PropTypes.number,
46 | scrollWheelZoom: _react.PropTypes.bool,
47 | children: _react.PropTypes.node.isRequired,
48 | width: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.string]),
49 | height: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.string])
50 | };
51 |
52 | StamenMap.defaultProps = {
53 | center: [0, 0],
54 | zoom: 0,
55 | width: '100%',
56 | height: 600,
57 | scrollWheelZoom: false
58 | };
59 |
60 | exports.default = StamenMap;
61 |
62 | // attribution="© OpenStreetMap contributors"
--------------------------------------------------------------------------------
/lib/Navigation/Nav.css:
--------------------------------------------------------------------------------
1 | @value small, desktop from "../constants.css";
2 |
3 | .Nav {
4 | position: relative;
5 | min-width: 320px;
6 | }
7 |
8 | .Nav ul {
9 | display: flex;
10 | list-style: none;
11 | align-items: center;
12 | justify-content: center;
13 | }
14 |
15 | .Nav ul li {
16 | flex: 1 1 100%;
17 | }
18 |
19 | .Nav ul li span i { margin-left: 10px; }
20 |
21 | .Nav a {
22 | color: rgba(255,255,255,.65);
23 | flex: 1;
24 | display: block;
25 | font-family: 'Rubik', sans-serif;
26 | font-size: 1.25rem;
27 | border: none;
28 | font-weight: 500;
29 | text-transform: uppercase;
30 | text-decoration: none;
31 | padding: 1rem;
32 | text-align: center;
33 | }
34 |
35 | .Nav a:hover {
36 | color: rgba(255,255,255,.85);
37 | text-decoration: none;
38 | }
39 |
40 |
41 | .hidden {
42 | visibility: hidden;
43 | opacity: 0;
44 | }
45 |
46 | .visible {
47 | visibility: visible;
48 | opacity: 1;
49 | margin-top: 10px;
50 | }
51 |
52 | a.ex {
53 | display: none;
54 | position: absolute;
55 | right: 1rem;
56 | width: auto;
57 | z-index: 999;
58 | }
59 |
60 | @media desktop {
61 |
62 | .nestedMenu a {
63 | color: rgba(238,73,92,1);
64 | padding: 5px 0px;
65 | text-align: left;
66 | font-size: 16px;
67 | }
68 |
69 | .nestedMenu {
70 | position: absolute;
71 | z-index: 999;
72 | margin-top: 0px;
73 | width: 200px;
74 | background-color: #fff;
75 | padding: 20px;
76 | transition: all .5s cubic-bezier(0.42, 0, 0.14, 1);
77 | }
78 |
79 | .nestedMenu::after {
80 | content: "";
81 | position: absolute;
82 | bottom: 100%;
83 | left: 50%;
84 | margin-left: -24px;
85 | border-width: 12px;
86 | border-style: solid;
87 | border-color: transparent transparent #fff transparent;
88 | }
89 | }
90 |
91 | @media small {
92 | a.ex {
93 | display: block;
94 | }
95 |
96 | .Nav {
97 | transition: all .2s linear;
98 | }
99 |
100 | .Nav.visible {
101 | opacity: 1;
102 | }
103 |
104 | .Nav.hidden {
105 | opacity: 0;
106 | pointer-events: none;
107 | }
108 |
109 | .Nav {
110 | position: absolute;
111 | z-index: 1;
112 | height: 100%;
113 | width: 100%;
114 | margin: 0 !important;
115 | padding: 0 !important;
116 | top: 0;
117 | left: 0;
118 | background-color: rgba(34,15,37,1);
119 | }
120 |
121 | .Nav ul {
122 | display: block;
123 | position: relative;
124 | list-style: none;
125 | margin: 0;
126 | padding-top: 80px;
127 | }
128 |
129 | .Nav ul li {
130 | color: #ffffff;
131 | display: block;
132 | text-align: center;
133 | text-decoration: none;
134 | transition: all .25s ease-in-out;
135 | margin: 0;
136 | padding: 0;
137 | flex: none;
138 | }
139 |
140 | }
141 |
--------------------------------------------------------------------------------
/src/Navigation/Nav.css:
--------------------------------------------------------------------------------
1 | @value small, desktop from "../constants.css";
2 |
3 | .Nav {
4 | position: relative;
5 | min-width: 320px;
6 | }
7 |
8 | .Nav ul {
9 | display: flex;
10 | list-style: none;
11 | align-items: center;
12 | justify-content: center;
13 | }
14 |
15 | .Nav ul li {
16 | flex: 1 1 100%;
17 | }
18 |
19 | .Nav ul li span i { margin-left: 10px; }
20 |
21 | .Nav a {
22 | color: rgba(255,255,255,.65);
23 | flex: 1;
24 | display: block;
25 | font-family: 'Rubik', sans-serif;
26 | font-size: 1.25rem;
27 | border: none;
28 | font-weight: 500;
29 | text-transform: uppercase;
30 | text-decoration: none;
31 | padding: 1rem;
32 | text-align: center;
33 | }
34 |
35 | .Nav a:hover {
36 | color: rgba(255,255,255,.85);
37 | text-decoration: none;
38 | }
39 |
40 |
41 | .hidden {
42 | visibility: hidden;
43 | opacity: 0;
44 | }
45 |
46 | .visible {
47 | visibility: visible;
48 | opacity: 1;
49 | margin-top: 10px;
50 | }
51 |
52 | a.ex {
53 | display: none;
54 | position: absolute;
55 | right: 1rem;
56 | width: auto;
57 | z-index: 999;
58 | }
59 |
60 | @media desktop {
61 |
62 | .nestedMenu a {
63 | color: rgba(238,73,92,1);
64 | padding: 5px 0px;
65 | text-align: left;
66 | font-size: 16px;
67 | }
68 |
69 | .nestedMenu {
70 | position: absolute;
71 | z-index: 999;
72 | margin-top: 0px;
73 | width: 200px;
74 | background-color: #fff;
75 | padding: 20px;
76 | transition: all .5s cubic-bezier(0.42, 0, 0.14, 1);
77 | }
78 |
79 | .nestedMenu::after {
80 | content: "";
81 | position: absolute;
82 | bottom: 100%;
83 | left: 50%;
84 | margin-left: -24px;
85 | border-width: 12px;
86 | border-style: solid;
87 | border-color: transparent transparent #fff transparent;
88 | }
89 | }
90 |
91 | @media small {
92 | a.ex {
93 | display: block;
94 | }
95 |
96 | .Nav {
97 | transition: all .2s linear;
98 | }
99 |
100 | .Nav.visible {
101 | opacity: 1;
102 | }
103 |
104 | .Nav.hidden {
105 | opacity: 0;
106 | pointer-events: none;
107 | }
108 |
109 | .Nav {
110 | position: absolute;
111 | z-index: 1;
112 | height: 100%;
113 | width: 100%;
114 | margin: 0 !important;
115 | padding: 0 !important;
116 | top: 0;
117 | left: 0;
118 | background-color: rgba(34,15,37,1);
119 | }
120 |
121 | .Nav ul {
122 | display: block;
123 | position: relative;
124 | list-style: none;
125 | margin: 0;
126 | padding-top: 80px;
127 | }
128 |
129 | .Nav ul li {
130 | color: #ffffff;
131 | display: block;
132 | text-align: center;
133 | text-decoration: none;
134 | transition: all .25s ease-in-out;
135 | margin: 0;
136 | padding: 0;
137 | flex: none;
138 | }
139 |
140 | }
141 |
--------------------------------------------------------------------------------
/stories/StoryCard.story.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | import React from 'react';
3 | import { storiesOf } from '@kadira/storybook';
4 | import { StoryCard, Chart, ChartData, Pie } from '../src';
5 | import { getRandomValuesArray, getColors, randomizer, wallOfRichText } from './shared';
6 |
7 | const labels = ['A', 'B', 'C', 'D', 'E', 'F'];
8 | const width = 300;
9 | const height = 300;
10 | const tdDemo = () => ({wallOfRichText}
);
11 | const tdvDemo = () => (
12 |
13 | {wallOfRichText}
14 |
15 |
16 |
17 | console.log(`${labels[i]} clicked`)}
20 | style={(d, i) => ({ fill: getColors(i) })}
21 | >
22 |
26 | {'Dataset A'}
27 |
28 |
32 | {'subtitle'}
33 |
34 |
35 |
36 |
37 |
38 |
39 | console.log(`${labels[i]} clicked`)}
42 | style={(d, i) => ({ fill: getColors(i) })}
43 | >
44 |
48 | {'Dataset B'}
49 |
50 |
54 | {'subtitle'}
55 |
56 |
57 |
58 |
59 |
60 |
61 | );
62 |
63 | export default () => storiesOf('StoryCard', module)
64 | .addWithInfo(
65 | 'Simple usage',
66 | 'This is some basic usage with the StoryCard with just a title and descriptions',
67 | () => some descriptions go here
,
68 | { inline: true, propTables: [StoryCard] },
69 | )
70 | .addWithInfo('with title & description', 'this time with title & desc', tdDemo)
71 | .addWithInfo('with title, description & visualization', 'this time with title, desc & vis', tdvDemo);
72 |
--------------------------------------------------------------------------------
/lib/global.styles.css:
--------------------------------------------------------------------------------
1 | /* --- Import Google Fonts --- */
2 |
3 | /* Rubik for Headings */
4 |
5 | @import url('https://fonts.googleapis.com/css?family=Rubik:300,300i,400,400i,500,500i,700,700i,900,900i');
6 |
7 | /* Merriweather for paragraphs */
8 |
9 | @import url('https://fonts.googleapis.com/css?family=Merriweather:300,300i,400,400i,700,700i,900,900i');
10 |
11 | /* Roboto Condensed for data and tiny type */
12 |
13 | @import url('https://fonts.googleapis.com/css?family=Roboto+Condensed:300,300i,400,400i,700,700i');
14 |
15 | /* react-select styles */
16 | /* should be imported only when react select is */
17 | /*@import '~react-select/dist/react-select.css';*/
18 | @value offwhite, midnight, secondary from './constants.css';
19 |
20 | /* Base */
21 |
22 | html {
23 | font-size: 16px;
24 | line-height: 1.35em;
25 | background-color: offwhite;
26 | font-family: 'Merriweather', sans-serif;;
27 | font-weight: 400;
28 | color: midnight;
29 | min-height: 100% /* [3] */;
30 | -webkit-text-size-adjust: 100% /* [4] */;
31 | -ms-text-size-adjust: 100% /* [4] */;
32 | -moz-osx-font-smoothing: grayscale /* [5] */;
33 | -webkit-font-smoothing: antialiased /* [5] */;
34 | -webkit-overflow-scrolling: touch;
35 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
36 | }
37 |
38 | body {
39 | margin: 0;
40 | display: flex;
41 | flex-direction: column;
42 | }
43 |
44 | /* Links and Buttons */
45 |
46 | button, :global(a.button) {
47 | appearance: none;
48 | background-color: transparent;
49 | color: secondary;
50 | }
51 |
52 | a {
53 | color: secondary;
54 | text-decoration: none;
55 | cursor: pointer;
56 | opacity: 0.9;
57 | transition: all .25s ease-in-out;
58 | }
59 |
60 | a:hover {
61 | color: secondary;
62 | text-decoration: none;
63 | cursor: pointer;
64 | opacity: 1;
65 | }
66 |
67 | /* Global Styles from product_design */
68 |
69 | /* Typography */
70 |
71 |
72 | :global(.h1), h1 {
73 | font-size: 36px;
74 | font-size: 2.25rem;
75 | line-height: 2.625rem;
76 | font-family: "Rubik", sans-serif;
77 | font-weight: 100;
78 | }
79 |
80 | :global(.h2), h2 {
81 | font-size: 26px;
82 | font-size: 1.625rem;
83 | line-height: 2.125rem;
84 | font-family: "Rubik", sans-serif;
85 | font-weight: 700;
86 | }
87 |
88 | :global(.h3), h3 {
89 | font-size: 18px;
90 | font-size: 1.125rem;
91 | line-height: 1.625rem;
92 | font-family: "Rubik", sans-serif;
93 | font-weight: 700;
94 | }
95 |
96 | :global(.h4), h4 {
97 | font-size: 16px;
98 | font-size: 1rem;
99 | line-height: 1.375rem;
100 | font-family: "Rubik", sans-serif;
101 | font-weight: 700;
102 | }
103 |
104 | :global(.h5), h5 {
105 | font-size: 14px;
106 | font-size: 0.875rem;
107 | line-height: 1.125rem;
108 | font-family: "Rubik", sans-serif;
109 | font-weight: 500;
110 | }
111 |
112 | :global(.h6), h6 {
113 | font-size: 12px;
114 | font-size: 0.75rem;
115 | line-height: 0.9375rem;
116 | font-family: "Rubik", sans-serif;
117 | font-weight: 500;
118 | }
119 |
120 | p {
121 | font-family: "Merriweather", serif;
122 | font-size: 1em;
123 | color: #706371;
124 | }
125 |
--------------------------------------------------------------------------------
/src/global.styles.css:
--------------------------------------------------------------------------------
1 | /* --- Import Google Fonts --- */
2 |
3 | /* Rubik for Headings */
4 |
5 | @import url('https://fonts.googleapis.com/css?family=Rubik:300,300i,400,400i,500,500i,700,700i,900,900i');
6 |
7 | /* Merriweather for paragraphs */
8 |
9 | @import url('https://fonts.googleapis.com/css?family=Merriweather:300,300i,400,400i,700,700i,900,900i');
10 |
11 | /* Roboto Condensed for data and tiny type */
12 |
13 | @import url('https://fonts.googleapis.com/css?family=Roboto+Condensed:300,300i,400,400i,700,700i');
14 |
15 | /* react-select styles */
16 | /* should be imported only when react select is */
17 | /*@import '~react-select/dist/react-select.css';*/
18 | @value offwhite, midnight, secondary from './constants.css';
19 |
20 | /* Base */
21 |
22 | html {
23 | font-size: 16px;
24 | line-height: 1.35em;
25 | background-color: offwhite;
26 | font-family: 'Merriweather', sans-serif;;
27 | font-weight: 400;
28 | color: midnight;
29 | min-height: 100% /* [3] */;
30 | -webkit-text-size-adjust: 100% /* [4] */;
31 | -ms-text-size-adjust: 100% /* [4] */;
32 | -moz-osx-font-smoothing: grayscale /* [5] */;
33 | -webkit-font-smoothing: antialiased /* [5] */;
34 | -webkit-overflow-scrolling: touch;
35 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
36 | }
37 |
38 | body {
39 | margin: 0;
40 | display: flex;
41 | flex-direction: column;
42 | }
43 |
44 | /* Links and Buttons */
45 |
46 | button, :global(a.button) {
47 | appearance: none;
48 | background-color: transparent;
49 | color: secondary;
50 | }
51 |
52 | a {
53 | color: secondary;
54 | text-decoration: none;
55 | cursor: pointer;
56 | opacity: 0.9;
57 | transition: all .25s ease-in-out;
58 | }
59 |
60 | a:hover {
61 | color: secondary;
62 | text-decoration: none;
63 | cursor: pointer;
64 | opacity: 1;
65 | }
66 |
67 | /* Global Styles from product_design */
68 |
69 | /* Typography */
70 |
71 |
72 | :global(.h1), h1 {
73 | font-size: 36px;
74 | font-size: 2.25rem;
75 | line-height: 2.625rem;
76 | font-family: "Rubik", sans-serif;
77 | font-weight: 100;
78 | }
79 |
80 | :global(.h2), h2 {
81 | font-size: 26px;
82 | font-size: 1.625rem;
83 | line-height: 2.125rem;
84 | font-family: "Rubik", sans-serif;
85 | font-weight: 700;
86 | }
87 |
88 | :global(.h3), h3 {
89 | font-size: 18px;
90 | font-size: 1.125rem;
91 | line-height: 1.625rem;
92 | font-family: "Rubik", sans-serif;
93 | font-weight: 700;
94 | }
95 |
96 | :global(.h4), h4 {
97 | font-size: 16px;
98 | font-size: 1rem;
99 | line-height: 1.375rem;
100 | font-family: "Rubik", sans-serif;
101 | font-weight: 700;
102 | }
103 |
104 | :global(.h5), h5 {
105 | font-size: 14px;
106 | font-size: 0.875rem;
107 | line-height: 1.125rem;
108 | font-family: "Rubik", sans-serif;
109 | font-weight: 500;
110 | }
111 |
112 | :global(.h6), h6 {
113 | font-size: 12px;
114 | font-size: 0.75rem;
115 | line-height: 0.9375rem;
116 | font-family: "Rubik", sans-serif;
117 | font-weight: 500;
118 | }
119 |
120 | p {
121 | font-family: "Merriweather", serif;
122 | font-size: 1em;
123 | color: #706371;
124 | }
125 |
--------------------------------------------------------------------------------
/src/Sankey/Sankey.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { sankey } from 'd3-sankey';
3 | import { format } from 'd3-format';
4 | import { clone, max } from 'ramda';
5 | import styles from './Sankey.css';
6 |
7 | const formatNumber = format(',.0f');
8 | const formatNum = num => formatNumber(num);
9 |
10 | const colors = [
11 | '#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f',
12 | '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99', '#b15928', '#8dd3c7', '#fb8072',
13 | '#80b1d3', '#bebada', '#ffed6f', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9',
14 | '#bc80bd', '#ccebc5', '#ffffb3',
15 | ];
16 |
17 | const defaultMargin = { top: 20, right: 0, bottom: 20, left: 0 };
18 |
19 | const Sankey = ({ margin = defaultMargin, width = 650, height = 450, nodes, links }) => {
20 | const w = width - margin.left - margin.right;
21 | const h = height - margin.top - margin.bottom;
22 |
23 | const sankeyChart = sankey()
24 | .size([w, h])
25 | .nodeWidth(12)
26 | .nodePadding(8);
27 |
28 | const path = sankeyChart.link();
29 |
30 | const chart = {
31 | nodes: clone(nodes),
32 | links: clone(links),
33 | };
34 |
35 | sankeyChart.nodes(chart.nodes)
36 | .links(chart.links)
37 | .layout(32);
38 |
39 | const chartLinks = chart.links.map((link, idx) => (
40 |
41 |
42 | {`${link.source.name} → ${link.target.name}\n Value: ${formatNum(link.value)}`}
43 |
44 |
45 | ));
46 |
47 | const chartNodes = chart.nodes.map((node, idx) => (
48 |
49 |
50 | {`${node.name}\n${formatNum(node.value)}`}
51 |
52 | { (node.x >= w / 2) ?
53 | {node.name} :
54 | {node.name}
55 | }
56 |
57 | ));
58 |
59 | return (
60 |
61 |
62 | {chartLinks}
63 | {chartNodes}
64 |
65 |
66 | );
67 | };
68 |
69 | Sankey.displayName = 'Sankey';
70 | Sankey.propTypes = {
71 | margin: PropTypes.shape({
72 | top: PropTypes.number,
73 | right: PropTypes.number,
74 | bottom: PropTypes.number,
75 | left: PropTypes.number,
76 | }),
77 | width: PropTypes.number,
78 | height: PropTypes.number,
79 | nodes: PropTypes.arrayOf(PropTypes.shape({
80 | name: PropTypes.string,
81 | node: PropTypes.number,
82 | })),
83 | links: PropTypes.arrayOf(PropTypes.shape({
84 | source: PropTypes.number,
85 | target: PropTypes.number,
86 | value: PropTypes.number,
87 | })),
88 | };
89 |
90 | export default Sankey;
91 |
--------------------------------------------------------------------------------
/src/Pie/Pie.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { TransitionMotion, Motion, spring } from 'react-motion';
3 | import { arc, pie } from 'd3-shape';
4 | import './Pie.css';
5 |
6 | const willLeaveStyle = ({ style }) => ({
7 | ...style,
8 | startAngle: style.endAngle,
9 | });
10 |
11 | const willEnterStyle = ({ style }) => ({
12 | ...style,
13 | endAngle: style.startAngle,
14 | });
15 |
16 | const Pie = (props, context) => {
17 | const { width, height, data } = context;
18 | const { style, onClick } = props;
19 |
20 | const createPie = pie().sort(null);
21 | const createArc = arc()
22 | .outerRadius(props.outerRadius)
23 | .innerRadius(props.innerRadius);
24 | const pieData = createPie(data);
25 |
26 | const motionStyles = pieData.map((datum, index) => ({
27 | key: `${index}`,
28 | data: { ...datum, index },
29 | style: datum,
30 | }));
31 |
32 | const defaultStyles = pieData.map((datum, index) => ({
33 | key: `${index}`,
34 | data: { ...datum, index },
35 | style: { ...datum, endAngle: datum.startAngle },
36 | }));
37 |
38 | const centerTransform = `translate(${width / 2}, ${height / 2})`;
39 |
40 | return (
41 |
42 |
46 | {arcStyles => (
47 |
48 | {arcStyles.map(config => (
49 |
61 | {arcStyle =>
62 | {
68 | onClick(e, config.data.value, config.data.index);
69 | }}
70 | />
71 | }
72 |
73 | ))}
74 |
75 | )}
76 |
77 | {props.children}
78 |
79 | );
80 | };
81 |
82 | Pie.displayName = 'Pie';
83 |
84 | Pie.propTypes = {
85 | innerRadius: PropTypes.number,
86 | outerRadius: PropTypes.number,
87 | style: PropTypes.func,
88 | onClick: PropTypes.func,
89 | children: PropTypes.node,
90 | };
91 |
92 | Pie.contextTypes = {
93 | data: PropTypes.arrayOf(PropTypes.number),
94 | height: PropTypes.number,
95 | width: PropTypes.number,
96 | margin: PropTypes.shape({
97 | top: PropTypes.number,
98 | bottom: PropTypes.number,
99 | left: PropTypes.number,
100 | right: PropTypes.number,
101 | }),
102 | };
103 |
104 | export default Pie;
--------------------------------------------------------------------------------
/lib/ChartData/ChartData.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _react = require('react');
10 |
11 | var _react2 = _interopRequireDefault(_react);
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16 |
17 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
18 |
19 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
20 |
21 | var ChartData = function (_Component) {
22 | _inherits(ChartData, _Component);
23 |
24 | function ChartData() {
25 | _classCallCheck(this, ChartData);
26 |
27 | return _possibleConstructorReturn(this, (ChartData.__proto__ || Object.getPrototypeOf(ChartData)).apply(this, arguments));
28 | }
29 |
30 | _createClass(ChartData, [{
31 | key: 'getChildContext',
32 | value: function getChildContext() {
33 | var _props = this.props,
34 | xScale = _props.xScale,
35 | yScale = _props.yScale,
36 | data = _props.data;
37 |
38 | return { xScale: xScale, yScale: yScale, data: data };
39 | }
40 | }, {
41 | key: 'render',
42 | value: function render() {
43 | return _react2.default.createElement(
44 | 'g',
45 | null,
46 | this.props.children
47 | );
48 | }
49 | }]);
50 |
51 | return ChartData;
52 | }(_react.Component);
53 |
54 | ChartData.displayName = 'ChartData';
55 | ChartData.propTypes = {
56 | children: _react.PropTypes.node,
57 | xScale: _react.PropTypes.func,
58 | yScale: _react.PropTypes.func,
59 | data: _react.PropTypes.oneOfType([_react.PropTypes.arrayOf(_react.PropTypes.number), _react.PropTypes.arrayOf(_react.PropTypes.arrayOf(_react.PropTypes.number))]).isRequired
60 | };
61 | ChartData.childContextTypes = {
62 | xScale: _react.PropTypes.func,
63 | yScale: _react.PropTypes.func,
64 | data: _react.PropTypes.oneOfType([_react.PropTypes.arrayOf(_react.PropTypes.number), _react.PropTypes.arrayOf(_react.PropTypes.arrayOf(_react.PropTypes.number))])
65 | };
66 | exports.default = ChartData;
--------------------------------------------------------------------------------
/stories/LeafletMap.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import { Marker, Popup, GeoJSON } from 'react-leaflet';
4 | import L from 'leaflet';
5 | import { LeafletMap } from '../src';
6 | import Shapes from '../assets/Shapes.js'
7 |
8 | /**
9 | * pointing to hosted leaflet images for now,
10 | * we probably won't use defaults in real projects anyways
11 | */
12 | L.Icon.Default.imagePath = '//cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0/images/';
13 |
14 | const displayName = 'LeafletMap';
15 | const title = 'Basic Map';
16 | const description = `
17 | Really basic leaflet map component to get us started, provide boilerplate environment for other
18 | storybook leaflet components. Can evolve as we refine our usage, Maybe eventually in to a
19 | 'portland map' or other preconfigured maps.`;
20 |
21 | const portland = [45.52, -122.67];
22 |
23 | const basicMapDemo = () => (
24 |
25 |
26 |
27 | A pretty CSS3 popup. Easily customizable.
28 |
29 |
30 |
31 | );
32 |
33 | const boundsDemoTitle = 'With Bounds';
34 |
35 | const boundsMapProps = {
36 | width: 400,
37 | height: 300,
38 | bounds: [
39 | [45.654527, -122.464291],
40 | [45.431897, -122.836892],
41 | ],
42 | };
43 |
44 | const boundsDemo = () => (
45 |
46 |
47 |
48 | You should be zoomed to me ;)
49 |
50 |
51 |
52 | );
53 |
54 | const fancyDemoTitle = 'Stylized Portland Map with GeoJSON';
55 | const fancyDescription = 'Stylized map with GeoJSON capabilities. Currently using the toner-lite tiles from Stamen Design, but could be adapted to any files. To stylize individual regions defined in your GeoJSON file, youll need to reference the properties of the GeoJSON layer. In this example GeoJSON that would be Analysis-A';
56 |
57 | const fancyMapProps = {
58 | width: "60%",
59 | height: 500,
60 | center: [45.54362, -122.676482],
61 | zoom: 11,
62 | zoomControl: false,
63 | dragging: false,
64 | touchZoom: false,
65 | doubleClickZoom: false,
66 | scrollWheelZoom: false,
67 | url: "http://{s}.tile.stamen.com/toner-lite/{z}/{x}/{y}.png",
68 | attribution: "Map tiles by Stamen Design , under CC BY 3.0 . Data by OpenStreetMap , under CC BY SA .",
69 | };
70 |
71 | const fancyStyle = {
72 | "color": "#ff7800",
73 | "weight": 2,
74 | "opacity": 0.65
75 | };
76 |
77 | const fancyDemo = () => (
78 |
79 |
80 |
81 | );
82 |
83 | const propDocs = { inline: true, propTables: [LeafletMap] };
84 |
85 | export default () => storiesOf(displayName, module)
86 | .addWithInfo(
87 | title,
88 | description,
89 | basicMapDemo,
90 | propDocs,
91 | )
92 | .addWithInfo(
93 | boundsDemoTitle,
94 | boundsDemo,
95 | propDocs,
96 | )
97 | .addWithInfo(
98 | fancyDemoTitle,
99 | fancyDescription,
100 | fancyDemo,
101 | propDocs
102 | );
103 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@hackoregon/component-library",
3 | "version": "0.2.5",
4 | "description": "Official repo for Hack Oregon React component library",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "npm run build-lib & npm run build-dist",
8 | "build-lib": "babel src --out-dir lib --copy-files",
9 | "build-dist": "node ./build.js",
10 | "prebump": "NODE_ENV=production npm run build",
11 | "bump": "bump --prompt --commit --push",
12 | "postbump": "editme -w",
13 | "clean": "rimraf lib dist",
14 | "test": "mocha --opts ./mocha.options ./src/**/*.test.js",
15 | "test:watch": "npm run test -- -w",
16 | "start": "start-storybook -p 6006",
17 | "lint": "eslint src stories --fix",
18 | "deploy-storybook": "storybook-to-ghpages",
19 | "build-storybook": "build-storybook"
20 | },
21 | "author": "David Daniel (http://davidedaniel.github.io)",
22 | "license": "MIT",
23 | "repository": {
24 | "type": "git",
25 | "url": "https://github.com/hackoregon/component-library"
26 | },
27 | "devDependencies": {
28 | "@hackoregon/jinn": "^0.2.3",
29 | "@kadira/react-storybook-addon-info": "^3.3.0",
30 | "@kadira/storybook": "^2.21.0",
31 | "@kadira/storybook-addon-knobs": "^1.7.0",
32 | "@kadira/storybook-addons": "^1.6.1",
33 | "@kadira/storybook-deployer": "^1.2.0",
34 | "autoprefixer": "^6.7.7",
35 | "babel-cli": "^6.23.0",
36 | "babel-eslint": "^7.1.1",
37 | "babel-plugin-add-module-exports": "^0.2.1",
38 | "babel-preset-stage-1": "^6.16.0",
39 | "chai": "^3.5.0",
40 | "chai-enzyme": "^0.6.1",
41 | "cheerio": "^0.22.0",
42 | "css-loader": "^0.28.0",
43 | "editme": "^1.1.0",
44 | "enzyme": "^2.7.0",
45 | "eslint": "^3.12.1",
46 | "eslint-config-airbnb": "^13.0.0",
47 | "eslint-config-airbnb-base": "^11.0.0",
48 | "eslint-import-resolver-webpack": "^0.7.1",
49 | "eslint-loader": "^1.6.1",
50 | "eslint-plugin-babel": "^4.0.0",
51 | "eslint-plugin-import": "^2.2.0",
52 | "eslint-plugin-jsx-a11y": "^2.2.3",
53 | "eslint-plugin-prefer-object-spread": "^1.1.0",
54 | "eslint-plugin-react": "^6.8.0",
55 | "extract-text-webpack-plugin": "^1.0.1",
56 | "ignore-styles": "^5.0.1",
57 | "jsdom": "^9.12.0",
58 | "jsdom-global": "2.1.1",
59 | "mocha": "^3.2.0",
60 | "mocha-clean": "^1.0.0",
61 | "react-addons-css-transition-group": "^15.4.1",
62 | "react-addons-shallow-compare": "^15.4.1",
63 | "react-addons-test-utils": "^15.4.1",
64 | "rimraf": "^2.6.1",
65 | "sinon": "^1.17.7",
66 | "sinon-chai": "^2.8.0",
67 | "source-map-support": "^0.4.11",
68 | "style-loader": "^0.16.1",
69 | "webpack": "1.13.3"
70 | },
71 | "dependencies": {
72 | "classnames": "^2.2.5",
73 | "copy-to-clipboard": "^3.0.5",
74 | "d3": "^4.7.3",
75 | "d3-format": "^1.1.1",
76 | "d3-sankey": "^0.4.2",
77 | "d3-shape": "^1.0.6",
78 | "editme": "^1.1.0",
79 | "leaflet": "^1.0.3",
80 | "ramda": "^0.23.0",
81 | "rc-slider": "^5.4.0",
82 | "react": "^15.5.3",
83 | "react-addons-transition-group": "^15.5.3",
84 | "react-dom": "^15.5.3",
85 | "react-faux-dom": "^3.0.1",
86 | "react-leaflet": "^1.1.4",
87 | "react-motion": "^0.4.7",
88 | "react-router": "^3.0.0",
89 | "react-select": "^1.0.0-rc.3",
90 | "recharts": "^0.20.1",
91 | "styled-components": "^1.4.4",
92 | "version-bump-prompt": "^3.1.0"
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/lib/DropdownMenu/DropdownMenu.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
8 |
9 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
10 |
11 | var _react = require('react');
12 |
13 | var _react2 = _interopRequireDefault(_react);
14 |
15 | var _reactSelectize = require('react-selectize');
16 |
17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18 |
19 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
20 |
21 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
22 |
23 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
24 |
25 | var DropdownMenu = function (_Component) {
26 | _inherits(DropdownMenu, _Component);
27 |
28 | function DropdownMenu(props) {
29 | _classCallCheck(this, DropdownMenu);
30 |
31 | var _this = _possibleConstructorReturn(this, (DropdownMenu.__proto__ || Object.getPrototypeOf(DropdownMenu)).call(this, props));
32 |
33 | _this.state = {
34 | value: '',
35 | label: ''
36 | };
37 | _this.handleChange = _this.handleChange.bind(_this);
38 | return _this;
39 | }
40 |
41 | _createClass(DropdownMenu, [{
42 | key: 'handleChange',
43 | value: function handleChange(option) {
44 | if (option) {
45 | if (this.props.dispatch) {
46 | this.props.dispatch(this.props.reduxAction(option.value));
47 | }
48 | this.setState({ value: option.value, label: option.label });
49 | }
50 | }
51 | }, {
52 | key: 'render',
53 | value: function render() {
54 | require('react-selectize/dist/index.css');
55 | return _react2.default.createElement(_reactSelectize.SimpleSelect, _extends({}, this.props, {
56 | onValueChange: this.handleChange,
57 | theme: 'default',
58 | transitionEnter: true,
59 | transitionLeave: true,
60 | options: this.props.options
61 | }));
62 | }
63 | }]);
64 |
65 | return DropdownMenu;
66 | }(_react.Component);
67 |
68 | DropdownMenu.propTypes = {
69 | options: _react.PropTypes.arrayOf(_react.PropTypes.shape({
70 | value: _react.PropTypes.string,
71 | label: _react.PropTypes.string
72 | })),
73 | dispatch: _react.PropTypes.func,
74 | reduxAction: _react.PropTypes.func
75 | };
76 | exports.default = DropdownMenu;
--------------------------------------------------------------------------------
/lib/Share/ShareCollection.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _react = require('react');
10 |
11 | var _react2 = _interopRequireDefault(_react);
12 |
13 | var _copyToClipboard = require('copy-to-clipboard');
14 |
15 | var _copyToClipboard2 = _interopRequireDefault(_copyToClipboard);
16 |
17 | var _StoryLink = require('../StoryCard/StoryLink');
18 |
19 | var _StoryLink2 = _interopRequireDefault(_StoryLink);
20 |
21 | var _styleConstants = require('../styleConstants');
22 |
23 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24 |
25 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
26 |
27 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
28 |
29 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
30 |
31 | var MS_TO_SWITCH_TEXT = 3000; // 3 seconds
32 |
33 | var ShareCollection = function (_Component) {
34 | _inherits(ShareCollection, _Component);
35 |
36 | function ShareCollection(props) {
37 | _classCallCheck(this, ShareCollection);
38 |
39 | var _this = _possibleConstructorReturn(this, (ShareCollection.__proto__ || Object.getPrototypeOf(ShareCollection)).call(this, props));
40 |
41 | _this.setToFalse = function () {
42 | return _this.setState({ copied: false });
43 | };
44 |
45 | _this.switchState = function (ms) {
46 | return setTimeout(_this.setToFalse, ms);
47 | };
48 |
49 | _this.handleCopy = function () {
50 | // NOTE: we need to make sure this will work on all browsers
51 | (0, _copyToClipboard2.default)('' + window.location.href);
52 | _this.switchState(MS_TO_SWITCH_TEXT);
53 | _this.setState({ copied: true });
54 | };
55 |
56 | _this.state = {
57 | copied: false
58 | };
59 | return _this;
60 | }
61 |
62 | _createClass(ShareCollection, [{
63 | key: 'render',
64 | value: function render() {
65 | var shareTxt = this.state.copied ? 'Link copied!' : 'Share'; // if copied, show Link copied, otherwise, show Share card
66 | var shareIcon = this.state.copied ? _styleConstants.ICONS.check : _styleConstants.ICONS.link;
67 | return _react2.default.createElement(
68 | _StoryLink2.default,
69 | { className: 'Share', action: this.handleCopy, icon: shareIcon },
70 | shareTxt
71 | );
72 | }
73 | }]);
74 |
75 | return ShareCollection;
76 | }(_react.Component);
77 |
78 | ShareCollection.defaultProps = {
79 | collectionId: 'some-collection-id'
80 | };
81 | ShareCollection.propTypes = {
82 | collectionId: _react.PropTypes.string
83 | };
84 | exports.default = ShareCollection;
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.isClient = exports.Scatterplot = exports.Icon = exports.Dropdown = exports.LeafletMap = exports.RechartsPie = exports.NavRouterLink = exports.Nav = exports.Header = exports.ScrollToTop = exports.Footer = exports.Slider = exports.Pie = exports.ChartData = exports.Chart = exports.StoryCard = exports.Button = exports.Sankey = exports.BarChart = exports.AreaChart = undefined;
7 |
8 | var _AreaChart2 = require('./AreaChart/AreaChart');
9 |
10 | var _AreaChart3 = _interopRequireDefault(_AreaChart2);
11 |
12 | var _BarChart2 = require('./BarChart/BarChart');
13 |
14 | var _BarChart3 = _interopRequireDefault(_BarChart2);
15 |
16 | var _Sankey2 = require('./Sankey/Sankey');
17 |
18 | var _Sankey3 = _interopRequireDefault(_Sankey2);
19 |
20 | var _Button2 = require('./Button/Button');
21 |
22 | var _Button3 = _interopRequireDefault(_Button2);
23 |
24 | var _StoryCard2 = require('./StoryCard/StoryCard');
25 |
26 | var _StoryCard3 = _interopRequireDefault(_StoryCard2);
27 |
28 | var _Chart2 = require('./Chart/Chart');
29 |
30 | var _Chart3 = _interopRequireDefault(_Chart2);
31 |
32 | var _ChartData2 = require('./ChartData/ChartData');
33 |
34 | var _ChartData3 = _interopRequireDefault(_ChartData2);
35 |
36 | var _Pie2 = require('./Pie/Pie');
37 |
38 | var _Pie3 = _interopRequireDefault(_Pie2);
39 |
40 | var _Slider2 = require('./Slider/Slider');
41 |
42 | var _Slider3 = _interopRequireDefault(_Slider2);
43 |
44 | var _Footer2 = require('./Footer/Footer');
45 |
46 | var _Footer3 = _interopRequireDefault(_Footer2);
47 |
48 | var _ScrollToTop2 = require('./ScrollToTop/ScrollToTop');
49 |
50 | var _ScrollToTop3 = _interopRequireDefault(_ScrollToTop2);
51 |
52 | var _Header2 = require('./Navigation/Header');
53 |
54 | var _Header3 = _interopRequireDefault(_Header2);
55 |
56 | var _Nav2 = require('./Navigation/Nav');
57 |
58 | var _Nav3 = _interopRequireDefault(_Nav2);
59 |
60 | var _NavRouterLink2 = require('./Navigation/NavRouterLink');
61 |
62 | var _NavRouterLink3 = _interopRequireDefault(_NavRouterLink2);
63 |
64 | var _RechartsPie2 = require('./RechartsPie/RechartsPie');
65 |
66 | var _RechartsPie3 = _interopRequireDefault(_RechartsPie2);
67 |
68 | var _LeafletMap2 = require('./LeafletMap/LeafletMap');
69 |
70 | var _LeafletMap3 = _interopRequireDefault(_LeafletMap2);
71 |
72 | var _Dropdown2 = require('./Dropdown/Dropdown');
73 |
74 | var _Dropdown3 = _interopRequireDefault(_Dropdown2);
75 |
76 | var _Icon2 = require('./Icon/Icon');
77 |
78 | var _Icon3 = _interopRequireDefault(_Icon2);
79 |
80 | var _Scatterplot2 = require('./Scatterplot/Scatterplot');
81 |
82 | var _Scatterplot3 = _interopRequireDefault(_Scatterplot2);
83 |
84 | var _isClient2 = require('./utils/isClient');
85 |
86 | var _isClient3 = _interopRequireDefault(_isClient2);
87 |
88 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
89 |
90 | exports.AreaChart = _AreaChart3.default;
91 | exports.BarChart = _BarChart3.default;
92 | exports.Sankey = _Sankey3.default;
93 | exports.Button = _Button3.default;
94 | exports.StoryCard = _StoryCard3.default;
95 | exports.Chart = _Chart3.default;
96 | exports.ChartData = _ChartData3.default;
97 | exports.Pie = _Pie3.default;
98 | exports.Slider = _Slider3.default;
99 | exports.Footer = _Footer3.default;
100 | exports.ScrollToTop = _ScrollToTop3.default;
101 | exports.Header = _Header3.default;
102 | exports.Nav = _Nav3.default;
103 | exports.NavRouterLink = _NavRouterLink3.default;
104 | exports.RechartsPie = _RechartsPie3.default;
105 | exports.LeafletMap = _LeafletMap3.default;
106 | exports.Dropdown = _Dropdown3.default;
107 | exports.Icon = _Icon3.default;
108 | exports.Scatterplot = _Scatterplot3.default;
109 |
110 | // export utils as well for broader use
111 |
112 | exports.isClient = _isClient3.default;
--------------------------------------------------------------------------------
/assets/civic-logo-animated.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/Pie/Pie.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
8 |
9 | var _react = require('react');
10 |
11 | var _react2 = _interopRequireDefault(_react);
12 |
13 | var _reactMotion = require('react-motion');
14 |
15 | var _d3Shape = require('d3-shape');
16 |
17 | require('./Pie.css');
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | var willLeaveStyle = function willLeaveStyle(_ref) {
22 | var style = _ref.style;
23 | return _extends({}, style, {
24 | startAngle: style.endAngle
25 | });
26 | };
27 |
28 | var willEnterStyle = function willEnterStyle(_ref2) {
29 | var style = _ref2.style;
30 | return _extends({}, style, {
31 | endAngle: style.startAngle
32 | });
33 | };
34 |
35 | var Pie = function Pie(props, context) {
36 | var width = context.width,
37 | height = context.height,
38 | data = context.data;
39 | var style = props.style,
40 | _onClick = props.onClick;
41 |
42 |
43 | var createPie = (0, _d3Shape.pie)().sort(null);
44 | var createArc = (0, _d3Shape.arc)().outerRadius(props.outerRadius).innerRadius(props.innerRadius);
45 | var pieData = createPie(data);
46 |
47 | var motionStyles = pieData.map(function (datum, index) {
48 | return {
49 | key: '' + index,
50 | data: _extends({}, datum, { index: index }),
51 | style: datum
52 | };
53 | });
54 |
55 | var defaultStyles = pieData.map(function (datum, index) {
56 | return {
57 | key: '' + index,
58 | data: _extends({}, datum, { index: index }),
59 | style: _extends({}, datum, { endAngle: datum.startAngle })
60 | };
61 | });
62 |
63 | var centerTransform = 'translate(' + width / 2 + ', ' + height / 2 + ')';
64 |
65 | return _react2.default.createElement(
66 | 'g',
67 | { className: 'pie', transform: centerTransform },
68 | _react2.default.createElement(
69 | _reactMotion.TransitionMotion,
70 | {
71 | defaultStyles: defaultStyles, styles: motionStyles,
72 | willEnter: willEnterStyle, willLeave: willLeaveStyle
73 | },
74 | function (arcStyles) {
75 | return _react2.default.createElement(
76 | 'g',
77 | { className: 'slices' },
78 | arcStyles.map(function (config) {
79 | return _react2.default.createElement(
80 | _reactMotion.Motion,
81 | {
82 | defaultStyle: _extends({}, config.style, {
83 | endAngle: config.data.startAngle
84 | }),
85 | key: config.key,
86 | style: _extends({}, config.style, {
87 | startAngle: (0, _reactMotion.spring)(config.style.startAngle),
88 | endAngle: (0, _reactMotion.spring)(config.style.endAngle)
89 | })
90 | },
91 | function (arcStyle) {
92 | return _react2.default.createElement('path', {
93 | d: createArc(arcStyle),
94 | style: style(config.data.value, config.data.index),
95 | onClick: function onClick(e) {
96 | _onClick(e, config.data.value, config.data.index);
97 | }
98 | });
99 | }
100 | );
101 | })
102 | );
103 | }
104 | ),
105 | props.children
106 | );
107 | };
108 |
109 | Pie.displayName = 'Pie';
110 |
111 | Pie.propTypes = {
112 | innerRadius: _react.PropTypes.number,
113 | outerRadius: _react.PropTypes.number,
114 | style: _react.PropTypes.func,
115 | onClick: _react.PropTypes.func,
116 | children: _react.PropTypes.node
117 | };
118 |
119 | Pie.contextTypes = {
120 | data: _react.PropTypes.arrayOf(_react.PropTypes.number),
121 | height: _react.PropTypes.number,
122 | width: _react.PropTypes.number,
123 | margin: _react.PropTypes.shape({
124 | top: _react.PropTypes.number,
125 | bottom: _react.PropTypes.number,
126 | left: _react.PropTypes.number,
127 | right: _react.PropTypes.number
128 | })
129 | };
130 |
131 | exports.default = Pie;
--------------------------------------------------------------------------------
/assets/civic-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
10 |
12 |
14 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
33 |
35 |
38 |
40 |
41 |
42 |
43 |
44 |
45 |
48 |
50 |
52 |
55 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/lib/Sankey/Sankey.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _react = require('react');
8 |
9 | var _react2 = _interopRequireDefault(_react);
10 |
11 | var _d3Sankey = require('d3-sankey');
12 |
13 | var _d3Format = require('d3-format');
14 |
15 | var _ramda = require('ramda');
16 |
17 | var _Sankey = require('./Sankey.css');
18 |
19 | var _Sankey2 = _interopRequireDefault(_Sankey);
20 |
21 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22 |
23 | var formatNumber = (0, _d3Format.format)(',.0f');
24 | var formatNum = function formatNum(num) {
25 | return formatNumber(num);
26 | };
27 |
28 | var colors = ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99', '#b15928', '#8dd3c7', '#fb8072', '#80b1d3', '#bebada', '#ffed6f', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffffb3'];
29 |
30 | var defaultMargin = { top: 20, right: 0, bottom: 20, left: 0 };
31 |
32 | var Sankey = function Sankey(_ref) {
33 | var _ref$margin = _ref.margin,
34 | margin = _ref$margin === undefined ? defaultMargin : _ref$margin,
35 | _ref$width = _ref.width,
36 | width = _ref$width === undefined ? 650 : _ref$width,
37 | _ref$height = _ref.height,
38 | height = _ref$height === undefined ? 450 : _ref$height,
39 | nodes = _ref.nodes,
40 | links = _ref.links;
41 |
42 | var w = width - margin.left - margin.right;
43 | var h = height - margin.top - margin.bottom;
44 |
45 | var sankeyChart = (0, _d3Sankey.sankey)().size([w, h]).nodeWidth(12).nodePadding(8);
46 |
47 | var path = sankeyChart.link();
48 |
49 | var chart = {
50 | nodes: (0, _ramda.clone)(nodes),
51 | links: (0, _ramda.clone)(links)
52 | };
53 |
54 | sankeyChart.nodes(chart.nodes).links(chart.links).layout(32);
55 |
56 | var chartLinks = chart.links.map(function (link, idx) {
57 | return _react2.default.createElement(
58 | 'g',
59 | { key: _Sankey2.default.sankeyLink + '-' + idx },
60 | _react2.default.createElement(
61 | 'path',
62 | { className: _Sankey2.default.sankeyLink, d: path(link), style: { strokeWidth: (0, _ramda.max)(1, link.dy) } },
63 | _react2.default.createElement(
64 | 'title',
65 | null,
66 | link.source.name + ' \u2192 ' + link.target.name + '\n Value: ' + formatNum(link.value)
67 | )
68 | )
69 | );
70 | });
71 |
72 | var chartNodes = chart.nodes.map(function (node, idx) {
73 | return _react2.default.createElement(
74 | 'g',
75 | { key: _Sankey2.default.sankeyNode + '-' + idx, className: _Sankey2.default.sankeyNode, transform: 'translate(' + node.x + ',' + node.y + ')' },
76 | _react2.default.createElement(
77 | 'rect',
78 | { style: { fill: colors[idx] }, height: node.dy, width: sankeyChart.nodeWidth() },
79 | _react2.default.createElement(
80 | 'title',
81 | null,
82 | node.name + '\n' + formatNum(node.value)
83 | )
84 | ),
85 | node.x >= w / 2 ? _react2.default.createElement(
86 | 'text',
87 | { x: -8, y: node.dy / 2, dy: '.25em', textAnchor: 'end' },
88 | node.name
89 | ) : _react2.default.createElement(
90 | 'text',
91 | { x: 8 + sankeyChart.nodeWidth(), y: node.dy / 2, dy: '.25em', textAnchor: 'start' },
92 | node.name
93 | )
94 | );
95 | });
96 |
97 | return _react2.default.createElement(
98 | 'svg',
99 | { className: _Sankey2.default.sankeyChart, width: w + margin.left + margin.right, height: h + margin.top + margin.bottom },
100 | _react2.default.createElement(
101 | 'g',
102 | { transform: 'translate(' + margin.left + ',' + margin.top + ')' },
103 | chartLinks,
104 | chartNodes
105 | )
106 | );
107 | };
108 |
109 | Sankey.displayName = 'Sankey';
110 | Sankey.propTypes = {
111 | margin: _react.PropTypes.shape({
112 | top: _react.PropTypes.number,
113 | right: _react.PropTypes.number,
114 | bottom: _react.PropTypes.number,
115 | left: _react.PropTypes.number
116 | }),
117 | width: _react.PropTypes.number,
118 | height: _react.PropTypes.number,
119 | nodes: _react.PropTypes.arrayOf(_react.PropTypes.shape({
120 | name: _react.PropTypes.string,
121 | node: _react.PropTypes.number
122 | })),
123 | links: _react.PropTypes.arrayOf(_react.PropTypes.shape({
124 | source: _react.PropTypes.number,
125 | target: _react.PropTypes.number,
126 | value: _react.PropTypes.number
127 | }))
128 | };
129 |
130 | exports.default = Sankey;
--------------------------------------------------------------------------------
/lib/StoryCard/StoryFooter.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _react = require('react');
10 |
11 | var _react2 = _interopRequireDefault(_react);
12 |
13 | var _copyToClipboard = require('copy-to-clipboard');
14 |
15 | var _copyToClipboard2 = _interopRequireDefault(_copyToClipboard);
16 |
17 | var _StoryLink = require('./StoryLink');
18 |
19 | var _StoryLink2 = _interopRequireDefault(_StoryLink);
20 |
21 | var _styleConstants = require('../styleConstants');
22 |
23 | var _StoryFooter = require('./StoryFooter.css');
24 |
25 | var _StoryFooter2 = _interopRequireDefault(_StoryFooter);
26 |
27 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
28 |
29 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
30 |
31 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
32 |
33 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
34 |
35 | var MS_TO_SWITCH_TEXT = 3000; // 3 seconds
36 |
37 | var StoryFooter = function (_Component) {
38 | _inherits(StoryFooter, _Component);
39 |
40 | function StoryFooter(props) {
41 | _classCallCheck(this, StoryFooter);
42 |
43 | var _this = _possibleConstructorReturn(this, (StoryFooter.__proto__ || Object.getPrototypeOf(StoryFooter)).call(this, props));
44 |
45 | _this.setToFalse = function () {
46 | return _this.setState({ copied: false });
47 | };
48 |
49 | _this.switchState = function (ms) {
50 | return setTimeout(_this.setToFalse, ms);
51 | };
52 |
53 | _this.handleCopy = function () {
54 | var _this$props = _this.props,
55 | collectionId = _this$props.collectionId,
56 | cardId = _this$props.cardId;
57 | // NOTE: we need to make sure this will work on all browsers
58 |
59 | (0, _copyToClipboard2.default)(window.location.origin + '/' + collectionId + '/' + cardId);
60 | _this.switchState(MS_TO_SWITCH_TEXT);
61 | _this.setState({ copied: true });
62 | };
63 |
64 | _this.state = {
65 | copied: false
66 | };
67 | return _this;
68 | }
69 |
70 | _createClass(StoryFooter, [{
71 | key: 'render',
72 | value: function render() {
73 | var _props = this.props,
74 | collectionId = _props.collectionId,
75 | cardId = _props.cardId;
76 |
77 | var shareTxt = this.state.copied ? 'Link copied!' : 'Share card'; // if copied, show Link copied, otherwise, show Share card
78 | var shareIcon = this.state.copied ? _styleConstants.ICONS.check : _styleConstants.ICONS.link;
79 | return _react2.default.createElement(
80 | 'div',
81 | { className: _StoryFooter2.default.footerlinks },
82 | _react2.default.createElement(
83 | _StoryLink2.default,
84 | { className: 'Context', route: '/' + collectionId + '/' + cardId, icon: _styleConstants.ICONS.eye },
85 | 'View card'
86 | ),
87 | _react2.default.createElement(
88 | _StoryLink2.default,
89 | { className: 'Share', action: this.handleCopy, icon: shareIcon },
90 | shareTxt
91 | )
92 | );
93 | }
94 | }]);
95 |
96 | return StoryFooter;
97 | }(_react.Component);
98 |
99 | StoryFooter.defaultProps = {
100 | cardId: 'some-card-id',
101 | collectionId: 'some-collection-id'
102 | };
103 | StoryFooter.propTypes = {
104 | cardId: _react.PropTypes.string,
105 | collectionId: _react.PropTypes.string
106 | };
107 | exports.default = StoryFooter;
--------------------------------------------------------------------------------
/lib/Navigation/Header.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _react = require('react');
10 |
11 | var _react2 = _interopRequireDefault(_react);
12 |
13 | var _Nav = require('./Nav');
14 |
15 | var _Nav2 = _interopRequireDefault(_Nav);
16 |
17 | var _LogoAnimated = require('../Logo/LogoAnimated');
18 |
19 | var _LogoAnimated2 = _interopRequireDefault(_LogoAnimated);
20 |
21 | var _Header = require('./Header.css');
22 |
23 | var _Header2 = _interopRequireDefault(_Header);
24 |
25 | var _Icon = require('../Icon/Icon');
26 |
27 | var _Icon2 = _interopRequireDefault(_Icon);
28 |
29 | var _styleConstants = require('../styleConstants');
30 |
31 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
32 |
33 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
34 |
35 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
36 |
37 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
38 |
39 | var Header = function (_Component) {
40 | _inherits(Header, _Component);
41 |
42 | function Header() {
43 | _classCallCheck(this, Header);
44 |
45 | var _this = _possibleConstructorReturn(this, (Header.__proto__ || Object.getPrototypeOf(Header)).call(this));
46 |
47 | _this.togglesNestedMenu = function () {
48 | return _this.setState({ menuActive: !_this.state.menuActive });
49 | };
50 |
51 | _this.state = {
52 | menuActive: false
53 | };
54 | return _this;
55 | }
56 |
57 | _createClass(Header, [{
58 | key: 'render',
59 | value: function render() {
60 | var _props = this.props,
61 | children = _props.children,
62 | menu = _props.menu,
63 | title = _props.title;
64 |
65 | return _react2.default.createElement(
66 | 'div',
67 | { className: _Header2.default.container },
68 | _react2.default.createElement(
69 | 'nav',
70 | { className: _Header2.default.header },
71 | _react2.default.createElement(
72 | 'div',
73 | { className: _Header2.default.logo },
74 | _react2.default.createElement(_LogoAnimated2.default, { alt: title })
75 | ),
76 | _react2.default.createElement(
77 | 'div',
78 | { className: _Header2.default.nav + ' ' + (this.state.menuActive ? _Header2.default.active : _Header2.default.inactive) },
79 | _react2.default.createElement(_Nav2.default, {
80 | menu: menu,
81 | toggleSubNav: this.togglesNestedMenu,
82 | showNestedMenu: this.state.nestedMenu,
83 | togglesNestedMenu: this.togglesNestedMenu
84 | }),
85 | children
86 | ),
87 | _react2.default.createElement(
88 | 'a',
89 | { className: _Header2.default.burger },
90 | _react2.default.createElement(_Icon2.default, {
91 | key: 'nav-burger',
92 | className: '' + _styleConstants.ICONS.hamburger,
93 | handleClick: this.togglesNestedMenu
94 | })
95 | )
96 | )
97 | );
98 | }
99 | }]);
100 |
101 | return Header;
102 | }(_react.Component);
103 |
104 | Header.displayName = 'Header';
105 | Header.propTypes = {
106 | menu: _react.PropTypes.arrayOf(_react.PropTypes.shape({})),
107 | title: _react.PropTypes.string,
108 | children: _react.PropTypes.node
109 | };
110 |
111 | exports.default = Header;
--------------------------------------------------------------------------------