value 2
48 | */
49 | title: PropTypes.string
50 | };
51 |
52 | AccordionPanel.defaultProps = {
53 | expanded: false
54 | };
55 |
56 | export default CSSModules(AccordionPanel, styles, { allowMultiple: true });
57 |
--------------------------------------------------------------------------------
/src/Checkbox/README.md:
--------------------------------------------------------------------------------
1 | Checkbox:
2 |
3 |
6 |
7 | Checked:
8 |
9 |
13 |
14 | Disabled:
15 |
16 |
20 |
21 | Left label:
22 |
23 |
28 |
29 | Custom onClick method:
30 |
31 | {}
32 |
33 |
38 |
39 | onChange callback:
40 |
41 |
46 |
47 | No label:
48 |
49 |
51 |
52 | No label and checked:
53 |
54 |
57 |
58 | Required:
59 |
60 |
64 |
65 | Custom validation:
66 |
67 |
72 |
73 | Custom function before change:
74 |
75 |
79 |
80 | Label and ID:
81 |
82 |
86 |
--------------------------------------------------------------------------------
/src/NavItem/NavItem.css:
--------------------------------------------------------------------------------
1 | @import '../Button/Button.css';
2 | @import '../styles/variables.css';
3 |
4 | .base {
5 | border-style: none;
6 | border-top: 1px solid #eee !important; /* Important designation needed to overwrite Button styling in prod build */
7 | }
8 |
9 | .subNav {
10 | height: 40px;
11 | transition: height .3s ease-in-out;
12 | }
13 |
14 | .subNav.collapsed {
15 | height: 0;
16 | }
17 |
18 | .navItem button {
19 | width: 100%;
20 | border-color: var(--silver);
21 | border-left: solid 5px transparent;
22 | position: relative;
23 | display: block;
24 | padding: 10px 15px;
25 | text-align: left;
26 | color: var(--dark-gray);
27 | background-color: var(--white);
28 | }
29 |
30 | .subNav button {
31 | padding-left: 38px;
32 | }
33 |
34 | .subNav.collapsed button {
35 | display: none;
36 | }
37 |
38 | .navItem button:hover {
39 | background-color: var(--silver);
40 | color: var(--dark-gray);
41 | }
42 |
43 | .navItem button:focus {
44 | outline: none;
45 | }
46 |
47 | .active > button, .active > a > button {
48 | border-left-color: var(--blue);
49 | background-color: var(--silver);
50 | color: var(--blue);
51 | }
52 |
53 | .caret::before {
54 | content: "";
55 | border: solid var(--blue);
56 | border-width: 0 2px 2px 0;
57 | display: inline-block;
58 | padding: 5px;
59 | transform: rotate(45deg);
60 | position: absolute;
61 | top: -5px;
62 | left: 5px;
63 | }
64 |
65 | .caret {
66 | position: relative;
67 | width: 18px;
68 | height: 10px;
69 | vertical-align: middle;
70 | float: right;
71 | clear: right;
72 | border-color: var(--dark-gray);
73 | transform: none;
74 | margin: 5px 0 0;
75 | transition: transform .3s;
76 | top: -2px;
77 | }
78 |
79 |
80 | .collapsed .caret {
81 | transform: rotate(90deg);
82 | }
--------------------------------------------------------------------------------
/src/Accordion/__tests__/__snapshots__/accordion.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Test Accordion component Test render correctly 1`] = `
4 |
8 |
11 |
12 |
18 |
21 |
24 |
28 | Text for first accordion item.
29 |
30 |
31 |
32 |
33 |
34 |
40 |
43 |
46 |
49 | Text for second accordion item
50 |
51 |
52 |
53 |
54 |
55 |
61 |
64 |
67 |
70 | Text for third accordion item
71 |
72 |
73 |
74 |
75 |
76 |
77 | `;
78 |
--------------------------------------------------------------------------------
/src/Task/__tests__/task.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { Task } from "../index";
4 |
5 | import renderer from "react-test-renderer";
6 |
7 | describe("Test correct render", () => {
8 | it("Test correct render", function() {
9 | const tree = renderer
10 | .create(
)
11 | .toJSON();
12 | expect(tree).toMatchSnapshot();
13 | });
14 | });
15 |
16 | describe("Test Task component", () => {
17 | it("applies css classes supplied in className prop", function() {
18 | const task = mount(
);
19 | expect(task.props().className).toBe("myClass anotherClass");
20 | expect(task.find("span").html()).toContain("myClass anotherClass");
21 | });
22 | it("applies icon supplied in icon prop", function() {
23 | const task = mount(
);
24 | expect(task.find("i").exists()).toBe(true);
25 | expect(task.find("i").html()).toContain("fa fa-github");
26 | });
27 | it("applies id prop", function() {
28 | const task = mount(
);
29 | expect(task.props().id).toBe("myId");
30 | expect(task.find("span").html()).toContain('id="myId');
31 | });
32 | it("applies onClick prop", function() {
33 | const clickHandler = jest.fn();
34 | const task = mount(
);
35 | task.simulate("click");
36 | expect(clickHandler).toBeCalled();
37 | });
38 | it("does not apply onClick prop", function() {
39 | const clickHandler = jest.fn();
40 | const task = mount(
);
41 | task.simulate("click");
42 | expect(clickHandler).not.toBeCalled();
43 | });
44 | it("applies selected CSS class if true", function() {
45 | const task = mount(
);
46 | expect(task.props().selected).toBe(true);
47 | expect(task.find("span").html()).toContain("selected");
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/src/Tab/Tab.css:
--------------------------------------------------------------------------------
1 | @import '../styles/variables.css';
2 |
3 | .tab {
4 | composes: bg-silver from '../styles.css';
5 | composes: sky-blue from '../styles.css';
6 | composes: border-colorless from '../styles.css';
7 | composes: border-transparent from '../styles.css';
8 | composes: border-bottom-none from '../styles.css';
9 | composes: marg-r-half from '../styles.css';
10 | composes: pad-v-1 from '../styles.css';
11 | composes: pad-h-2 from '../styles.css';
12 | composes: cursor-pointer from '../styles.css';
13 | border-top: 1px solid var(--white);
14 | display: inline-block;
15 | position: relative;
16 | list-style: none;
17 | }
18 |
19 | .vTab {
20 | composes: bg-silver from '../styles.css';
21 | composes: sky-blue from '../styles.css';
22 | composes: border-colorless from '../styles.css';
23 | composes: border-transparent from '../styles.css';
24 | composes: border-right-none from '../styles.css';
25 | composes: marg-b-half from '../styles.css';
26 | composes: pad-v-2 from '../styles.css';
27 | composes: pad-h-1 from '../styles.css';
28 | composes: cursor-pointer from '../styles.css';
29 | border-left: 1px solid var(--white);
30 | display: block;
31 | position: relative;
32 | list-style: none;
33 | }
34 |
35 | .selected {
36 | composes: bg-white from '../styles.css';
37 | composes: dark-gray from '../styles.css';
38 | border-color: var(--gray) !important; /* Important designation added for production build */
39 | bottom: -1px;
40 | }
41 |
42 | .vSelected {
43 | composes: bg-white from '../styles.css';
44 | composes: dark-gray from '../styles.css';
45 | border-color: var(--gray) !important; /* Important designation added for production build */
46 | right: -1px;
47 | }
48 |
49 | .disabled {
50 | composes: bg-white from '../styles.css';
51 | composes: cursor-default from '../styles.css';
52 | composes: dark-gray from '../styles.css';
53 | }
54 |
55 | .icon-left {
56 | margin-right: 0.25rem;
57 | }
--------------------------------------------------------------------------------
/src/FileUpload/FileUpload.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import Dropzone from "react-dropzone";
4 | import cx from "classnames";
5 | import CSSModules from "react-css-modules";
6 | import styles from "./fileupload.css";
7 |
8 | export class FileUpload extends React.PureComponent {
9 | constructor(props) {
10 | super(props);
11 | }
12 |
13 | onDropHandler = files => {
14 | if (typeof this.props.onChange !== "undefined") {
15 | this.props.onChange(files);
16 | }
17 | };
18 |
19 | render() {
20 | const { className, text, accept, style, inputRef } = this.props;
21 | let textClass = cx({
22 | text: true
23 | });
24 | return (
25 |
32 | {text}
33 |
34 | );
35 | }
36 | }
37 |
38 | FileUpload.propTypes = {
39 | /**
40 | * The MIME type of files that are accepted. */
41 | accept: PropTypes.string,
42 |
43 | /** An object, array, or string of CSS classes to apply to FileUpload.*/
44 | className: PropTypes.oneOfType([
45 | PropTypes.string,
46 | PropTypes.object,
47 | PropTypes.array
48 | ]),
49 |
50 | /** Function that will be called when a file is uploaded.
51 | * Returns an array of uploaded files. */
52 | onChange: PropTypes.func,
53 |
54 | /**
55 | * Text that will be displayed on the FileUpload component.
56 | */
57 | text: PropTypes.string,
58 |
59 | /**
60 | * Pass inline styling here.
61 | */
62 | style: PropTypes.object,
63 |
64 | /**
65 | * Ref for Dropzone element
66 | */
67 | inputRef: PropTypes.func
68 | };
69 |
70 | export default CSSModules(FileUpload, styles, { allowMultiple: true });
71 |
--------------------------------------------------------------------------------
/src/ProgressBar/README.md:
--------------------------------------------------------------------------------
1 | Basic ProgressBar:
2 |
3 |
4 |
5 | Basic ProgressBar with custom color:
6 |
7 |
8 |
9 | Determinate ProgressBar:
10 |
11 | initialState = {value: 30}
12 | increase = () => {
13 | setState((prevState) => {
14 | return {value: prevState.value + 5}
15 | });
16 | }
17 | decrease = () => {
18 | setState((prevState) => {
19 | return {value: prevState.value - 5}
20 | });
21 | }
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Progress: {state.value}%
30 |
31 |
32 | ProgressBar with buffer:
33 |
34 |
35 |
36 | Circular ProgressBar:
37 |
38 |
39 |
40 | Circular determinate ProgressBar with custom color and style:
41 |
42 | initialState = {value: 30}
43 | increase = () => {
44 | setState((prevState) => {
45 | return {value: prevState.value + 10}
46 | });
47 | }
48 | decrease = () => {
49 | setState((prevState) => {
50 | return {value: prevState.value - 10}
51 | });
52 | }
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/src/Switch/README.md:
--------------------------------------------------------------------------------
1 | ###### Default Switch:
2 |
3 |
4 | ###### Default Switch with label:
5 |
6 |
7 |
8 | ###### Default Switch with label to left:
9 |
10 |
11 |
12 | ###### Different sized Switches:
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | ###### Multiple Switches tied to same behavior (name prop):
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | ###### Switch with custom colors and styles:
29 |
30 |
31 |
32 |
33 |
34 |
35 | ###### Disabled and hidden Switches:
36 |
37 |
38 |
39 |
40 |
41 |
42 | ###### Switch with onClick:
43 |
44 | function customSwitchClick() {
45 | console.info("onClick event!");
46 | }
47 |
48 |
49 |
50 | ###### Switch with onChange:
51 |
52 | function customSwitchChange() {
53 | console.info("onChange event!");
54 | }
55 |
56 |
57 |
58 | ###### Make checks before changing component's state (onbeforechange). It receives a value with current checked state:
59 |
60 | function customSwitchBeforeChange(value) {
61 | if(!value) {
62 | let accept = confirm("Do you want to check this?");
63 | return accept;
64 | }
65 |
66 | return true;
67 | }
68 |
69 |
70 |
71 | This method should return true or false, allowing or not the onChange handler to be fired. If undefined, will prevent it.
72 |
73 |
74 |
--------------------------------------------------------------------------------
/src/CheckboxGroup/README.md:
--------------------------------------------------------------------------------
1 | CheckboxGroup
2 |
3 | { console.log(value, event, isValid, checked)}}>
4 |
5 |
6 |
7 |
8 |
9 | Inline CheckboxGroup
10 |
11 |
12 |
13 |
16 |
20 |
21 |
22 |
25 |
29 |
30 |
31 |
32 | CheckboxGroup with inline children
33 |
34 |
35 |
38 |
42 |
43 |
44 | CheckboxGroup with checked minimum
45 |
46 |
47 |
50 |
53 |
54 |
55 | CheckboxGroup with checked maximum
56 |
57 |
58 |
61 |
65 |
66 |
--------------------------------------------------------------------------------
/src/Radio/README.md:
--------------------------------------------------------------------------------
1 | The Radio component is a controlled component that must be used within the RadioGroup component. For more examples view the RadioGroup examples.
2 |
3 | ###### Default Radio:
4 |
5 |
6 |
7 |
8 |
9 |
10 | ###### Disabled Radio:
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ###### Hidden Radio:
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | ###### Radio with left-positioned label:
27 |
28 |
29 |
30 |
31 |
32 |
33 | ###### Custom onClick method:
34 |
35 |
36 | { console.log(data.index, data.value) } }/>
37 |
38 |
39 |
40 | ###### Custom onChange method:
41 |
42 |
43 | { console.log(data.checked, data.value) } }/>
44 |
45 |
46 |
47 | ###### Custom function before change:
48 |
49 |
50 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/Icon/Icon.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import CSSModules from "react-css-modules";
5 | import styles from "./Icon.css";
6 |
7 | /**
8 | * Master Icon component. Used as a stand alone component or in conjunction with button and avatar
9 | */
10 | export class Icon extends React.PureComponent {
11 | constructor(props) {
12 | super(props);
13 |
14 | if (!this.props.icon) {
15 | console.warn(
16 | "You are attempting to use an icon without passing in an icon property."
17 | );
18 | }
19 | }
20 |
21 | render() {
22 | const { className, small, large, style, onClick, icon } = this.props;
23 |
24 | let iconClasses = cx({
25 | large: large,
26 | small: small
27 | });
28 |
29 | return (
30 |
36 | );
37 | }
38 | }
39 |
40 | Icon.propTypes = {
41 | /** An Object, array, or string of CSS classes to apply to Input.*/
42 | className: PropTypes.oneOfType([
43 | PropTypes.string,
44 | PropTypes.object,
45 | PropTypes.array
46 | ]),
47 | /**
48 | * Defines an icon for the icon.
49 | * @examples ''
50 | */
51 | icon: PropTypes.string,
52 | /**
53 | * Defines a large sized icon element.
54 | * @examples ''
55 | */
56 | large: PropTypes.bool,
57 | /**
58 | * Defines an onclick for the icon.
59 | * @examples ' this._handleClick } icon={"fa fa-id-card"}/>'
60 | */
61 | onClick: PropTypes.func,
62 | /**
63 | * Defines a small sized icon element.
64 | * @examples ''
65 | */
66 | small: PropTypes.bool,
67 | /**
68 | * Pass inline styling here.
69 | */
70 | style: PropTypes.object
71 | };
72 |
73 | export default CSSModules(Icon, styles, { allowMultiple: true });
74 |
--------------------------------------------------------------------------------
/src/Text/Text.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import CSSModules from "react-css-modules";
5 | import styles from "./Text.css";
6 |
7 | export class Text extends React.PureComponent {
8 | constructor(props) {
9 | super(props);
10 | }
11 |
12 | render() {
13 | const { as, body, children, className, ...other } = this.props;
14 |
15 | // Not all available elements are included below, only the ones needing custom styling.
16 | const textStyles = cx({
17 | blockquote: as === "blockquote",
18 | bodyFont: body,
19 | code: as === "code",
20 | defaultFont: !body && as !== "label",
21 | h1: as === "h1",
22 | h2: as === "h2",
23 | h3: as === "h3",
24 | h4: as === "h4",
25 | h5: as === "h5",
26 | h6: as === "h6",
27 | label: as === "label",
28 | link: as === "a",
29 | small: as === "small"
30 | });
31 |
32 | const TextElement = `${this.props.as}`;
33 |
34 | let element = (
35 |
36 | {children}
37 |
38 | );
39 |
40 | return element;
41 | }
42 | }
43 |
44 | Text.propTypes = {
45 | /** Defines what HTML element to render the Text component as. Possibilities include, but are not limited to b, body, del, em, h1, h2, h3, h4, h5, h6, i, ins, label, mark, p, small, strong, sub, and sup. */
46 | as: PropTypes.string,
47 | /** Allows theme to differentiate font-family between default font and body copy in variables.css */
48 | body: PropTypes.bool,
49 | /**
50 | * Text, any HTML element, or React Component.
51 | */
52 | children: PropTypes.node,
53 | /** An Object, array, or string of CSS classes to apply to Input. */
54 | className: PropTypes.oneOfType([
55 | PropTypes.string,
56 | PropTypes.object,
57 | PropTypes.array
58 | ])
59 | };
60 |
61 | Text.defaultProps = {
62 | as: "span"
63 | };
64 |
65 | export default CSSModules(Text, styles, { allowMultiple: true });
66 |
--------------------------------------------------------------------------------
/src/TabPanel/TabPanel.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import CSSModules from "react-css-modules";
5 | import styles from "./TabPanel.css";
6 |
7 | /**
8 | * TabPanel component
9 | */
10 | export class TabPanel extends React.PureComponent {
11 | constructor(props) {
12 | super(props);
13 |
14 | // Initial state
15 | this.state = {
16 | selected: this.props.selected || false
17 | };
18 | }
19 |
20 | UNSAFE_componentWillReceiveProps = nextProps => {
21 | if (nextProps.selected !== this.props.selected) {
22 | this.setState({ selected: nextProps.selected });
23 | }
24 | };
25 |
26 | render() {
27 | const { className, children, bordered, vertical, style } = this.props;
28 |
29 | let tabPanelClasses = cx(
30 | {
31 | selected: this.state.selected,
32 | bordered,
33 | vertical
34 | },
35 | "tabPanel"
36 | );
37 |
38 | return (
39 |
40 | {children}
41 |
42 | );
43 | }
44 | }
45 |
46 | TabPanel.propTypes = {
47 | /**
48 | * Will be automatically set when bordered prop is passed to Tabs component.
49 | */
50 | bordered: PropTypes.bool,
51 |
52 | /**
53 | * Text, components or elements that will be displayed as TabPanel content.
54 | */
55 | children: PropTypes.node,
56 |
57 | /**
58 | * An object, array, or string of CSS classes to apply to TabPanel.
59 | */
60 | className: PropTypes.oneOfType([
61 | PropTypes.string,
62 | PropTypes.object,
63 | PropTypes.array
64 | ]),
65 |
66 | /**
67 | * When true, TabPanel is selected.
68 | */
69 | selected: PropTypes.bool,
70 |
71 | /**
72 | * Pass inline styling here.
73 | */
74 | style: PropTypes.object,
75 |
76 | /**
77 | * Will be automatically set when vertical prop is passed to Tabs component.
78 | */
79 | vertical: PropTypes.bool
80 | };
81 |
82 | export default CSSModules(TabPanel, styles, { allowMultiple: true });
83 |
--------------------------------------------------------------------------------
/src/Task/Task.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import CSSModules from "react-css-modules";
5 | import styles from "./Task.css";
6 |
7 | export class Task extends React.PureComponent {
8 | constructor(props) {
9 | super(props);
10 | }
11 |
12 | render() {
13 | const {
14 | className,
15 | icon,
16 | id,
17 | index,
18 | onClick,
19 | selected,
20 | style,
21 | title
22 | } = this.props;
23 |
24 | const taskLinkClasses = cx({
25 | taskLink: true,
26 | selected: selected
27 | });
28 |
29 | return (
30 | {
36 | if (onClick) {
37 | onClick(e, id, index);
38 | }
39 | }}
40 | >
41 | {icon ? : null}
42 | {title}
43 |
44 | );
45 | }
46 | }
47 |
48 | Task.propTypes = {
49 | /** An Object, array, or string of CSS classes to apply to Task.*/
50 | className: PropTypes.oneOfType([
51 | PropTypes.string,
52 | PropTypes.object,
53 | PropTypes.array
54 | ]),
55 | /**
56 | * Adds font-awesome icon to left of title
57 | */
58 | icon: PropTypes.string,
59 | /**
60 | * Will set the html "id" property on the Task.
61 | */
62 | id: PropTypes.string,
63 | /**
64 | * The index of the Task within the parent Taskbar.
65 | */
66 | index: PropTypes.number,
67 | /**
68 | * Function that will be executed on click.
69 | */
70 | onClick: PropTypes.func,
71 | /**
72 | * Adds selected class if true
73 | */
74 | selected: PropTypes.bool,
75 | /** Pass inline styling here. */
76 | style: PropTypes.object,
77 | /**
78 | * Text for task
79 | * @examples 'Item One'
80 | */
81 | title: PropTypes.string
82 | };
83 |
84 | Task.defaultProps = {
85 | title: "Item One"
86 | };
87 |
88 | export default CSSModules(Task, styles, { allowMultiple: true });
89 |
--------------------------------------------------------------------------------
/src/Breadcrumb/__tests__/breadcrumb.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { Breadcrumb } from "../index";
4 | import { BreadcrumbItem } from "../../BreadcrumbItem/index";
5 | import { Text } from "../../Text/index";
6 |
7 | import renderer from "react-test-renderer";
8 |
9 | describe("Test Breadcrumb component", () => {
10 | it("Test correct render", function() {
11 | const tree = renderer
12 | .create(
13 |
14 |
15 |
16 | Atlas
17 |
18 |
19 |
20 |
21 | Breadcrumb
22 |
23 |
24 |
25 | Breadcrumb Example
26 |
27 |
28 | )
29 | .toJSON();
30 | expect(tree).toMatchSnapshot();
31 | });
32 | });
33 |
34 | describe("Testing Breadcrumb component: Basic Tests", () => {
35 | const brdcrmb = mount(
36 |
37 |
38 |
39 | Atlas
40 |
41 |
42 |
43 |
44 | Breadcrumb
45 |
46 |
47 |
48 | Breadcrumb Example
49 |
50 |
51 | );
52 |
53 | it("Basic Breadcrumb", () => {
54 | expect(brdcrmb.exists()).toBe(true);
55 | });
56 |
57 | it("Contains No Child", () => {
58 | const breadcrumb = mount();
59 |
60 | expect(breadcrumb.props().children).toBeUndefined();
61 | });
62 |
63 | it("Contains Child", () => {
64 | expect(brdcrmb.props()).toHaveProperty("children");
65 | });
66 |
67 | it("Basic Breadcrumb with BreadcrumbItem child", () => {
68 | expect(
69 | brdcrmb.contains(
70 |
71 |
72 | Atlas
73 |
74 |
75 | )
76 | ).toBeTruthy();
77 | });
78 | });
79 |
--------------------------------------------------------------------------------
/src/Card/README.md:
--------------------------------------------------------------------------------
1 | Basic Fieldset Card:
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Card with Image:
12 |
13 |
14 | Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,
15 |
16 |
17 |
18 |
19 | Card with Image and restricted width:
20 |
21 |
22 | Lorem-ipsum-dolor-sit-amet-consectetuer
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Option/Option.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import { Text } from "../Text";
5 | import CSSModules from "react-css-modules";
6 | import styles from "./Option.css";
7 | import blacklist from "blacklist";
8 |
9 | export class Option extends React.PureComponent {
10 | constructor(props) {
11 | super(props);
12 | this.optionDivRef = React.createRef();
13 | }
14 | _handleHover = e => {
15 | this.props.optionHover(e, this.props.index);
16 | };
17 |
18 | _clickHandler = e => {
19 | this.props.optionClick(e, this.props.value, this.props.index);
20 | };
21 |
22 | render() {
23 | const { hover, selected, text, value, ...others } = this.props;
24 |
25 | // Declaring the following variables so they don't get passed to the option element through the prop spread.
26 | const othersFiltered = blacklist(others, "optionClick", "optionHover");
27 |
28 | const optionWrapper = cx({
29 | optionWrapper: true,
30 | hover: hover && !selected,
31 | selected: selected
32 | });
33 |
34 | return (
35 |
42 |
43 | {text}
44 |
45 |
46 | );
47 | }
48 | }
49 |
50 | Option.propTypes = {
51 | /** Define whether or not the Option should get hover styling.*/
52 | hover: PropTypes.bool,
53 | /** Define an index for the Option.*/
54 | index: PropTypes.number,
55 | /** Sets a handler function to be executed when onClick event occurs.*/
56 | optionClick: PropTypes.func,
57 | /** Sets a handler function to be executed when onMouseOver event occurs.*/
58 | optionHover: PropTypes.func,
59 | /** Define whether or not the Option should get selected styling.*/
60 | selected: PropTypes.bool,
61 | /** Define display text for the Option.*/
62 | text: PropTypes.string,
63 | /** Define a value for the Option.*/
64 | value: PropTypes.string
65 | };
66 |
67 | Option.defaultProps = {};
68 |
69 | export default CSSModules(Option, styles, { allowMultiple: true });
70 |
--------------------------------------------------------------------------------
/src/Dialog/README.md:
--------------------------------------------------------------------------------
1 | INFO Dialog:
2 |
3 | initialState = {active: false}
4 | handleToggle = () => {
5 | setState({ active: !state.active })
6 | };
7 | handleOk = () => {
8 | setState({ active: !state.active })
9 | };
10 |
11 |
12 |
22 |
23 |
24 | CONFIRM Dialog:
25 |
26 | initialState = {active: false}
27 | handleToggle = () => {
28 | setState({ active: !state.active })
29 | };
30 | handleCancel = () => {
31 | alert('Cancel callback');
32 | setState({ active: !state.active })
33 | };
34 | handleOk = () => {
35 | alert('OK callback');
36 | setState({ active: !state.active })
37 | };
38 |
39 |
40 |
49 |
50 |
51 | WARNING Dialog:
52 |
53 | initialState = {active: false}
54 | handleToggle = () => {
55 | setState({ active: !state.active })
56 | };
57 |
58 | handleCancel = () => {
59 | setState({ active: !state.active })
60 | };
61 |
62 | handleOk = () => {
63 | setState({ active: !state.active })
64 | };
65 |
66 |
67 |
76 |
--------------------------------------------------------------------------------
/src/Taskbar/__tests__/taskbar.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { Taskbar } from "../index";
4 | import { Task } from "../../Task/index";
5 | import renderer from "react-test-renderer";
6 |
7 | describe("Test Taskbar component", () => {
8 | it("Test render correctly", () => {
9 | const comp = (
10 |
11 |
12 |
13 |
14 |
15 | );
16 | const tree = renderer.create(comp).toJSON();
17 | expect(tree).toMatchSnapshot();
18 | });
19 |
20 | it("centers", () => {
21 | const taskbar = mount(
22 |
23 |
24 |
25 |
26 |
27 | );
28 |
29 | expect(taskbar.find(".taskbarContainer.center").exists()).toBe(true);
30 | });
31 |
32 | it("applies className", () => {
33 | const taskbar = mount(
34 |
35 |
36 |
37 |
38 |
39 | );
40 |
41 | expect(taskbar.find(".myClass.taskbar").exists()).toBe(true);
42 | });
43 |
44 | it("applies style", () => {
45 | const taskbar = mount(
46 |
47 |
48 |
49 |
50 |
51 | );
52 |
53 | expect(taskbar.find(".myClass.taskbar").props().style).toEqual({
54 | color: "red"
55 | });
56 | });
57 |
58 | it("passes onClick to children", () => {
59 | const handleClick = jest.fn();
60 | const taskbar = mount(
61 |
62 |
63 |
64 |
65 |
66 | );
67 |
68 | taskbar
69 | .find("Task")
70 | .first()
71 | .simulate("click");
72 | expect(handleClick).toBeCalled();
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/src/Table/Table.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import { BootstrapTable } from "react-bootstrap-table";
5 | import CSSModules from "react-css-modules";
6 | import styles from "./Table.css";
7 |
8 | /**
9 | * The most common Table props are documented below. Documentation for the other props can be found at: https://github.com/AllenFang/react-bootstrap-table
10 | */
11 | export class Table extends React.PureComponent {
12 | render() {
13 | const {
14 | className,
15 | children,
16 | data,
17 | options,
18 | maxHeight,
19 | search,
20 | pagination,
21 | style,
22 | ...props
23 | } = this.props;
24 |
25 | return (
26 |
40 | {children}
41 |
42 | );
43 | }
44 | }
45 |
46 | Table.propTypes = {
47 | search: PropTypes.bool,
48 | children: PropTypes.any.isRequired,
49 | data: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
50 | pagination: PropTypes.bool,
51 | options: PropTypes.shape({
52 | defaultSortName: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
53 | defaultSortOrder: PropTypes.oneOfType([PropTypes.string, PropTypes.array])
54 | }),
55 | /** An Object, array, or string of CSS classes to apply to Table.*/
56 | className: PropTypes.oneOfType([
57 | PropTypes.string,
58 | PropTypes.object,
59 | PropTypes.array
60 | ]),
61 | maxHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
62 | /**
63 | * Pass inline styling here.
64 | */
65 | style: PropTypes.object
66 | };
67 |
68 | Table.defaultProps = {
69 | pagination: false,
70 | options: {
71 | defaultSortName: "",
72 | defaultSortOrder: ""
73 | }
74 | };
75 |
76 | export default CSSModules(Table, styles, { allowMultiple: true });
77 |
--------------------------------------------------------------------------------
/src/Radio/Radio.css:
--------------------------------------------------------------------------------
1 | @import '../styles/variables.css';
2 |
3 | .disabled {
4 | composes: default-text from '../styles.css';
5 | }
6 |
7 | .relative {
8 | position: relative;
9 | }
10 |
11 | .padding {
12 | padding-bottom: 5px;
13 | }
14 |
15 | .input {
16 | composes: relative;
17 | top: 1px;
18 | }
19 |
20 | .radio {
21 | position: absolute;
22 | top: 0;
23 | left: 0;
24 | height: 16px;
25 | width: 16px;
26 | display: inline-block;
27 | composes: cursor-pointer from '../styles.css';
28 | composes: default-border from '../styles.css';
29 | composes: circle from '../styles.css';
30 | background: -webkit-linear-gradient(#fff, #e6e6e6); /* For Safari 5.1 to 6.0 */
31 | background: -o-linear-gradient(#fff, #e6e6e6); /* For Opera 11.1 to 12.0 */
32 | background: -moz-linear-gradient(#fff, #e6e6e6); /* For Firefox 3.6 to 15 */
33 | background: linear-gradient(#fff, #e6e6e6); /* Standard syntax */
34 | }
35 |
36 | .disabled {
37 | opacity: 0.65;
38 | composes: cursor-not-allowed from '../styles.css';
39 | pointer-events: none;
40 | }
41 |
42 | .hidden {
43 | display: none;
44 | visibility: hidden;
45 | }
46 |
47 | .checked {
48 | composes: radio;
49 | composes: white-inset-shadow from '../styles.css';
50 | background: var(--primary);
51 | }
52 |
53 | .focus {
54 | box-shadow: 0 0 6px rgba(35, 173, 255, 1);
55 | }
56 |
57 | .checkmark {
58 | composes: relative;
59 | top: 0px;
60 | }
61 |
62 | .error {
63 | border: solid 1px var(--error);
64 | }
65 |
66 | .label {
67 | composes: default-font from '../styles.css';
68 | cursor: pointer;
69 | white-space: nowrap;
70 | padding-right: 5px;
71 | margin-left: 5px;
72 | }
73 |
74 | .label_left {
75 | composes: label;
76 | padding-right: 5px;
77 | margin-left: 0;
78 | margin-right: 5px;
79 | }
80 |
81 | .inline_block {
82 | display: inline-block;
83 | }
84 |
85 | .radio_padding {
86 | padding: 7px 10px 0 0;
87 | }
88 |
89 | .float_left {
90 | float: left;
91 | padding-right: 3px;
92 | }
93 |
94 | .float_right {
95 | float: right;
96 | padding-left: 3px;
97 | position: relative;
98 | }
99 |
100 | .input_style {
101 | opacity: 0; /*this needs to stay here to avoid display issues in IE*/
102 | }
--------------------------------------------------------------------------------
/src/Text/README.md:
--------------------------------------------------------------------------------
1 | ###### Default Text component:
2 |
3 | Hello World
4 |
5 | ###### Nested Text components:
6 |
7 | Hello World
8 |
9 | ###### Nested view components:
10 |
11 | There is a Button inside my Text.
12 |
13 | ###### Default Text for body copy:
14 |
15 | Hello World
16 |
17 | ###### Input label:
18 |
19 |
20 | Input Label
21 |
22 |
23 |
24 | ###### Headers and Sub-Headers:
25 |
26 |
27 | h1 Heading Secondary text
28 | h2 Heading Secondary text
29 | h3 Heading Secondary text
30 | h4 Heading Secondary text
31 | h5 Heading Secondary text
32 | h6 Heading Secondary text
33 |
34 |
35 | ###### Paragraph Text:
36 |
37 |
38 | Parapraph One
39 | Paragraph Two
40 |
41 |
42 | ###### Bold text:
43 |
44 | Hello World
45 |
46 | ###### Important text:
47 |
48 | Hello World
49 |
50 | ###### Italic text:
51 |
52 | Hello World
53 |
54 | ###### Emphasized text:
55 |
56 | Hello World
57 |
58 | ###### Deleted text:
59 |
60 | Hello World
61 |
62 | ###### Inserted text:
63 |
64 | Hello World
65 |
66 | ###### Marked text:
67 |
68 | Hello World
69 |
70 | ###### Small text (must be used within another Text component):
71 |
72 | Hello World
73 |
74 | ###### Subscript text:
75 |
76 | Hello World
77 |
78 | ###### Superscript text:
79 |
80 | Hello World
81 |
82 | ###### Code text:
83 |
84 | Sample Code: Hello World
85 |
86 | ###### Blockquote text:
87 |
88 | Hello World
89 |
90 | ###### Link text:
91 |
92 | Hello World
93 |
94 |
--------------------------------------------------------------------------------
/src/Avatar/README.md:
--------------------------------------------------------------------------------
1 |
2 | Title prop gets truncated to 1st letter:
3 |
4 |
5 |
6 | Icon takes precedence over title:
7 |
8 |
9 |
10 | Image takes precedence over icon:
11 |
12 |
17 |
18 | Image takes precedence over title:
19 |
20 |
21 |
22 | Child takes precedence over parameters:
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Image takes precedence over fallbackImage:
35 |
36 |
37 |
38 | fallbackImage takes precedence over title:
39 |
40 |
41 |
42 | fallbackImage will replace an image that fails to load:
43 |
44 |
45 |
46 | Update Avatar options via state after initial render:
47 |
48 | initialState = {image: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTGNZh4ycC0G2UbBGDVgJ56hYbZ0j1mU9J05xLg9O5ZazV1GJTT"}
49 | handleToggle = () => {
50 | setState({image: "https://octodex.github.com/images/codercat.jpg"})
51 | };
52 |
53 |
54 |
55 |
56 |
57 |
Image path: {state.image}
58 |
--------------------------------------------------------------------------------
/src/Tabs/__tests__/__snapshots__/tabs.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Test dropdown component Test render correctly 1`] = `
4 |
8 |
12 | -
17 | Tab 1
18 |
19 | -
24 | Tab 2
25 |
26 | -
31 | Tab 3
32 |
33 | -
38 | Tab 4
39 |
40 | -
45 | Tab 5
46 |
47 |
48 |
52 |
53 | Content 1
54 |
55 |
56 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin laoreet lorem sit amet finibus rutrum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque habitant morbi tristique senectus et netus et malesuada
57 |
58 |
61 | fames ac turpis egestas
62 |
63 | et siem.
64 |
65 |
66 |
70 |
71 | Content 2
72 |
73 |
74 | Tab content here
75 |
76 |
77 |
81 |
82 | Content 3
83 |
84 |
85 | Tab content here
86 |
87 |
88 |
92 |
93 | Content 4
94 |
95 |
96 | Tab content here
97 |
98 |
99 |
103 |
104 | Content 5
105 |
106 |
107 | Tab content here
108 |
109 |
110 |
111 | `;
112 |
--------------------------------------------------------------------------------
/src/ListItem/__tests__/listItem.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { ListItem } from "../index";
4 | import renderer from "react-test-renderer";
5 |
6 | describe("Test ListItem component", () => {
7 | it("Test render correctly", () => {
8 | const comp = Item one;
9 | const tree = renderer.create(comp).toJSON();
10 | expect(tree).toMatchSnapshot();
11 | });
12 |
13 | it("renders children", () => {
14 | const li = mount(Item one);
15 | expect(li.text()).toBe("Item one");
16 | });
17 |
18 | it("renders className", () => {
19 | const li = mount(Item one);
20 | expect(
21 | li
22 | .children()
23 | .first()
24 | .html()
25 | ).toContain("myClass");
26 | expect(li.find(".myClass").exists()).toBe(true);
27 | });
28 |
29 | it("sets id attribute", () => {
30 | const li = mount(
31 |
32 | Item one
33 |
34 | );
35 |
36 | expect(li.find('[id="itemOne"]').exists()).toBe(true);
37 | });
38 |
39 | it("renders leftItem", () => {
40 | const leftItem = `left
`;
41 | const li = mount(
42 |
43 | Item one
44 |
45 | );
46 |
47 | expect(li.html()).toContain("myLeftItem");
48 | });
49 |
50 | it("handles click", () => {
51 | const handleClick = jest.fn();
52 | const li = mount(
53 |
54 | Item one
55 |
56 | );
57 |
58 | li.simulate("click");
59 | expect(handleClick).toBeCalled();
60 | });
61 |
62 | it("renders rightItem", () => {
63 | const rightItem = `left
`;
64 | const li = mount(
65 |
66 | Item one
67 |
68 | );
69 |
70 | expect(li.html()).toContain("myRightItem");
71 | });
72 |
73 | it("sets inline style", () => {
74 | const li = mount(
75 |
76 | Item one
77 |
78 | );
79 |
80 | expect(
81 | li
82 | .children()
83 | .first()
84 | .html()
85 | ).toContain('style="color: red;"');
86 | });
87 | });
88 |
--------------------------------------------------------------------------------
/src/Nav/__tests__/__snapshots__/nav.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Test Nav component render Render correctly 1`] = `
4 |
8 | -
13 |
26 |
27 | -
32 |
45 |
46 | -
51 |
64 |
65 | -
70 |
83 |
84 | -
89 |
102 |
103 |
104 | `;
105 |
--------------------------------------------------------------------------------
/docs/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | React-Atlas Contributing Guidelines
2 |
3 | Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
4 | External Contributors
5 |
6 | Fork repo to your personal profile.
7 | Clone your forked repo to your machine.
8 | Go inside newly cloned directory and:
9 |
10 | git remote add upstream https://github.com/DigitalRiver/react-atlas.git # to add the ability to fetch the most recent code from React-Atlas master branch
11 | npm install # to install node modules
12 | npm run bootstrap:dev # to have lerna install and setup the different packages as well as generate atlas code
13 | npm run docs:dev # to start a local docs server at port 6060
14 | Write tests & code in ES6 goodness :-) and then run the test suite:
15 | npm run test
16 |
17 | If any snapshot tests need to be updated, run the following command:
18 | npm run updateSnapshot
19 |
20 | Confirm that there were no errors in the test results. Commit your changes. A pre-commit hook will run Prettier and Eslint on your changes. Fix any errors found, then commit again. Rebase your branch to upstream/master and squash any unhelpful commits. Push your branch to your personal fork. Create a PR back into DigitalRiver/react-atlas or the appropriate release candidate branch. If this is your first PR into React-Atlas you will be asked to sign a Contributor's License Agreement online Wait patiently :-)
21 |
22 |
23 | Internal Contributor Rules/Expectations
24 |
25 | Only branches that are release candidates or will be contributed to by multiple developers should be pushed to DigitalRiver/React-Atlas.
26 | Any branch pushed to DigitalRiver/React-Atlas must have an associated issue and reference that issue in a commit message. The issues should have a list of expected changes, and the commit messages should reference which changes have been completed so that another developer could assist with that development effort.
27 | Experimental branches or feature branches that will only be contributed to by one developer should be pushed to a private fork to keep the master repository as clean as possible.
28 | PRs can contain more than one commit, but each commit must solve an issue, be releasable on its own, and contain a helpful message.
29 |
30 |
--------------------------------------------------------------------------------
/docs/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this project, and in the interest of
4 | fostering an open and welcoming community, we pledge to respect all people who
5 | contribute through reporting issues, posting feature requests, updating
6 | documentation, submitting pull requests or patches, and other activities.
7 |
8 | We are committed to making participation in this project a harassment-free
9 | experience for everyone, regardless of level of experience, gender, gender
10 | identity and expression, sexual orientation, disability, personal appearance,
11 | body size, race, ethnicity, age, religion, or nationality.
12 |
13 | Examples of unacceptable behavior by participants include:
14 |
15 | * The use of sexualized language or imagery
16 | * Personal attacks
17 | * Trolling or insulting/derogatory comments
18 | * Public or private harassment
19 | * Publishing other's private information, such as physical or electronic
20 | addresses, without explicit permission
21 | * Other unethical or unprofessional conduct
22 |
23 | Project maintainers have the right and responsibility to remove, edit, or
24 | reject comments, commits, code, wiki edits, issues, and other contributions
25 | that are not aligned to this Code of Conduct, or to ban temporarily or
26 | permanently any contributor for other behaviors that they deem inappropriate,
27 | threatening, offensive, or harmful.
28 |
29 | By adopting this Code of Conduct, project maintainers commit themselves to
30 | fairly and consistently applying these principles to every aspect of managing
31 | this project. Project maintainers who do not follow or enforce the Code of
32 | Conduct may be permanently removed from the project team.
33 |
34 | This Code of Conduct applies both within project spaces and in public spaces
35 | when an individual is representing the project or its community.
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
38 | reported by contacting a project maintainer. All
39 | complaints will be reviewed and investigated and will result in a response that
40 | is deemed necessary and appropriate to the circumstances. Maintainers are
41 | obligated to maintain confidentiality with regard to the reporter of an
42 | incident.
43 |
44 |
45 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
46 | version 1.3.0, available at
47 | [http://contributor-covenant.org/version/1/3/0/][version]
48 |
49 | [homepage]: http://contributor-covenant.org
50 | [version]: http://contributor-covenant.org/version/1/3/0/
51 |
--------------------------------------------------------------------------------
/src/Dialog/__tests__/dialog.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { Dialog } from "../index";
4 | import renderer from "react-test-renderer";
5 |
6 | describe("Test Dialog component", () => {
7 | it("Test render correctly", () => {
8 | const comp =
9 |
14 | ;
15 | const tree = renderer.create(comp).toJSON();
16 | expect(tree).toMatchSnapshot();
17 | });
18 | });
19 |
20 | describe("Dialog component - Basic test", () => {
21 | it("Dialog component(info) - Basic test", function() {
22 | const dial = mount(
23 |
28 | );
29 | expect(dial.props().active).toEqual(false);
30 | });
31 |
32 | it("Dialog component(confirm) - Basic test", function() {
33 | const handleToggle = jest.fn();
34 | const handleOk = jest.fn();
35 | const handleCancel = jest.fn();
36 | const dial = mount(
37 |
38 |
39 |
52 |
53 | );
54 | dial.find("button").simulate("click");
55 | expect(
56 | dial
57 | .find(".dialogClass")
58 | .children()
59 | .first()
60 | .props().active
61 | ).toBe(true);
62 | });
63 |
64 | it("Dialog component(warning) - Basic test", function() {
65 | const handleToggle = jest.fn();
66 | const handleOk = jest.fn();
67 | const handleCancel = jest.fn();
68 | const dial = mount(
69 |
70 |
71 |
83 |
84 | );
85 | expect(dial.find("Dialog").props().warning).toBe(true);
86 | });
87 | });
88 |
--------------------------------------------------------------------------------
/src/Accordion/Accordion.css:
--------------------------------------------------------------------------------
1 | .accordion {
2 | composes: default-border from '../styles.css';
3 | composes: border-bottom-none from '../styles.css';
4 | composes: bg-white from '../styles.css';
5 | composes: default-text from '../styles.css';
6 | composes: default-font from '../styles.css';
7 | cursor: default;
8 | width: 100%;
9 | }
10 | .disabled {
11 | composes: cursor-not-allowed from '../styles.css';
12 | opacity: 0.6;
13 | }
14 | .accordion_header {
15 | composes: marg-0 from '../styles.css';
16 | composes: cursor-pointer from '../styles.css';
17 | composes: default-border-bottom from '../styles.css';
18 | composes: border-left-none from '../styles.css';
19 | composes: border-top-none from '../styles.css';
20 | composes: border-right-none from '../styles.css';
21 | composes: header-font from '../styles.css';
22 | composes: pad-h-2 from '../styles.css';
23 | line-height: 1.5rem;
24 | vertical-align: middle;
25 | text-align: left;
26 | }
27 | .rightAlign {
28 | text-align: right;
29 | composes: pad-h-2 from '../styles.css';
30 | }
31 | .centerAlign {
32 | text-align: center;
33 | }
34 | .header-active {
35 | composes: bg-primary from '../styles.css';
36 | composes: white from '../styles.css';
37 | }
38 | .header-inactive {
39 | composes: bg-silver from '../styles.css';
40 | }
41 | .hover {
42 | composes: bg-gray from '../styles.css' !important;
43 | composes: white from '../styles.css';
44 | }
45 | .panel {
46 | display: none;
47 | padding-left: 0rem;
48 | padding-right: 0rem;
49 | }
50 | .active {
51 | border-top: none;
52 | border-left: none;
53 | border-right: none;
54 | border-bottom: 1px solid #ccc;
55 | max-height: 100%;
56 | opacity: 1;
57 | padding: 1rem 0rem 1rem 0rem;
58 | -moz-transition: .25s;
59 | -ms-transition: .25s;
60 | -o-transition: .25s;
61 | -webkit-transition: .25s;
62 | transition: .25s;
63 | transition-timing-function: ease-in;
64 | }
65 | .active .panel {
66 | display: block;
67 | padding-left: 1rem;
68 | padding-right: 1rem;
69 | }
70 |
71 | .inactive {
72 | max-height: 0;
73 | padding: 0rem;
74 | opacity: 0;
75 | -moz-transition: .1s;
76 | -ms-transition: .1s;
77 | -o-transition: .1s;
78 | -webkit-transition: .1s;
79 | transition: .1s;
80 | }
81 |
82 | .expandAll {
83 | composes: marg-b-1 from '../styles.css';
84 | composes: primary-text from '../styles.css';
85 | composes: default-font from '../styles.css';
86 | cursor: pointer;
87 | }
88 | .expandAll:hover {
89 | text-decoration: underline;
90 | }
--------------------------------------------------------------------------------
/src/TabPanel/__tests__/tabPanel.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { TabPanel } from "../index";
4 | import renderer from "react-test-renderer";
5 |
6 | describe("Test dropdown component", () => {
7 | it("Test render correctly", () => {
8 | const comp = (
9 |
10 | Content 1
11 | Tab content here
12 |
13 | );
14 | const tree = renderer.create(comp).toJSON();
15 | expect(tree).toMatchSnapshot();
16 | });
17 |
18 | it("renders border", () => {
19 | const tp = mount(
20 |
21 | Content 1
22 | Tab content here
23 |
24 | );
25 |
26 | expect(tp.find(".bordered").exists()).toBe(true);
27 | });
28 |
29 | it("renders vertical", () => {
30 | const tp = mount(
31 |
32 | Content 1
33 | Tab content here
34 |
35 | );
36 |
37 | expect(tp.find(".vertical").exists()).toBe(true);
38 | });
39 |
40 | it("applies className", () => {
41 | const tp = mount(
42 |
43 | Content 1
44 | Tab content here
45 |
46 | );
47 |
48 | expect(tp.find(".myClass").exists()).toBe(true);
49 | });
50 |
51 | it("applies style", () => {
52 | const tp = mount(
53 |
54 | Content 1
55 | Tab content here
56 |
57 | );
58 | expect(tp.find("div.myClass").props().style).toEqual({ color: "red" });
59 | });
60 |
61 | it("handles defaults", () => {
62 | const tp = mount(
63 |
64 | Content 1
65 | Tab content here
66 |
67 | );
68 |
69 | expect(tp.find(".bordered").exists()).not.toBe(true);
70 | expect(tp.find(".vertical").exists()).not.toBe(true);
71 | expect(tp.state().selected).toBe(false);
72 | });
73 |
74 | it("CWRP updates selected", () => {
75 | const tp = mount(
76 |
77 | Content 1
78 | Tab content here
79 |
80 | );
81 |
82 | expect(tp.state().selected).toBe(false);
83 | tp.setProps({ selected: true });
84 | expect(tp.state().selected).toBe(true);
85 | tp.setProps({ selected: false });
86 | expect(tp.state().selected).toBe(false);
87 | //again to get the else branch
88 | tp.setProps({ selected: false });
89 | expect(tp.state().selected).toBe(false);
90 | });
91 | });
92 |
--------------------------------------------------------------------------------
/config/webpack.index.config.js:
--------------------------------------------------------------------------------
1 | let path = require("path");
2 | let webpack = require("webpack");
3 | const ExtractTextPlugin = require("extract-text-webpack-plugin");
4 |
5 | let config = {
6 | entry: {
7 | index: "./src/index.js"
8 | },
9 | output: {
10 | path: path.join(__dirname, "../lib"),
11 | filename: "index.js",
12 | libraryTarget: "umd"
13 | },
14 | externals: [
15 | {
16 | react: {
17 | root: "React",
18 | commonjs2: "react",
19 | commonjs: "react",
20 | amd: "react"
21 | }
22 | },
23 | {
24 | "react-dom": {
25 | root: "ReactDOM",
26 | commonjs2: "react-dom",
27 | commonjs: "react-dom",
28 | amd: "react-dom"
29 | }
30 | }
31 | ],
32 | module: {
33 | rules: [
34 | {
35 | test: /.js?$/,
36 | loader: "babel-loader",
37 | exclude: /node_modules/
38 | }
39 | ]
40 | },
41 | plugins: [
42 | new webpack.DefinePlugin({
43 | "process.env": {
44 | NODE_ENV: JSON.stringify(process.env.NODE_ENV)
45 | }
46 | })
47 | ]
48 | };
49 |
50 | if (process.env.NODE_ENV === "development") {
51 | config.devtool = "source-map";
52 | }
53 |
54 | if (process.env.NODE_ENV === "production") {
55 | config.module.rules.push({
56 | test: /\.css$/,
57 | loader: ExtractTextPlugin.extract({
58 | fallback: "style-loader",
59 | use: [
60 | {
61 | loader: "css-loader",
62 | query: {
63 | modules: true,
64 | importLoaders: 1,
65 | localIdentName: "ra_[name]__[local]",
66 | minimize: true
67 | }
68 | },
69 | {
70 | loader: "postcss-loader",
71 | options: {
72 | config: {
73 | path: "config/postcss.config.js"
74 | }
75 | }
76 | }
77 | ]
78 | })
79 | });
80 | config.plugins.push(new ExtractTextPlugin("atlasThemes.min.css"));
81 | } else {
82 | config.module.rules.push({
83 | test: /\.css$/,
84 | loaders: [
85 | "style-loader?sourceMap",
86 | "css-loader?modules&importLoaders=1&localIdentName=ra_[name]__[local]",
87 | {
88 | loader: "postcss-loader",
89 | options: {
90 | config: {
91 | path: "config/postcss.config.js"
92 | }
93 | }
94 | }
95 | ]
96 | });
97 | }
98 |
99 | module.exports = config;
100 |
--------------------------------------------------------------------------------
/src/Overlay/Overlay.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import CSSModules from "react-css-modules";
5 | import styles from "./Overlay.css";
6 |
7 | export class Overlay extends React.PureComponent {
8 | componentDidMount() {
9 | const { active, lockScroll, onEscKeyDown } = this.props;
10 | if (onEscKeyDown) {
11 | document.body.addEventListener("keydown", this.handleEscKey);
12 | }
13 | if (active && lockScroll) {
14 | document.body.style.overflow = "hidden";
15 | }
16 | }
17 |
18 | componentWillUnmount() {
19 | const { active, lockScroll, onEscKeyDown } = this.props;
20 | if (active && lockScroll) {
21 | document.body.style.overflow = "";
22 | }
23 |
24 | if (onEscKeyDown) {
25 | document.body.removeEventListener("keydown", this.handleEscKey);
26 | }
27 | }
28 |
29 | handleEscKey = e => {
30 | const { active, onEscKeyDown } = this.props;
31 | if (active && onEscKeyDown && e.which === 27) {
32 | onEscKeyDown(e);
33 | }
34 | };
35 |
36 | handleClick = event => {
37 | event.preventDefault();
38 | event.stopPropagation();
39 | if (this.props.onClick) {
40 | this.props.onClick(event);
41 | }
42 | };
43 |
44 | render() {
45 | const { active, className, style } = this.props;
46 | const overlayStyles = cx("overlay", {
47 | active
48 | });
49 | return (
50 |
56 | );
57 | }
58 | }
59 |
60 | Overlay.propTypes = {
61 | /**
62 | * When true, Overlay will display
63 | */
64 | active: PropTypes.bool,
65 |
66 | /** An object, array, or string of CSS classes to apply to Overlay.*/
67 | className: PropTypes.oneOfType([
68 | PropTypes.string,
69 | PropTypes.object,
70 | PropTypes.array
71 | ]),
72 |
73 | /**
74 | * Determines to hide page scroll
75 | */
76 | lockScroll: PropTypes.bool,
77 |
78 | /**
79 | * Event handler for esc key down
80 | */
81 | onEscKeyDown: PropTypes.func,
82 |
83 | /**
84 | * Click event handler.
85 | */
86 | onClick: PropTypes.func,
87 |
88 | /**
89 | * Pass inline styling here.
90 | */
91 | style: PropTypes.object
92 | };
93 |
94 | Overlay.defaultProps = {
95 | active: false,
96 | className: "",
97 | lockScroll: false
98 | };
99 |
100 | export default CSSModules(Overlay, styles, { allowMultiple: true });
101 |
--------------------------------------------------------------------------------
/src/Overlay/__tests__/overlay.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { Overlay } from "../index";
4 |
5 | import renderer from "react-test-renderer";
6 |
7 | describe("Test correct render", () => {
8 | it("Test correct render", function() {
9 | const tree = renderer
10 | .create()
11 | .toJSON();
12 | expect(tree).toMatchSnapshot();
13 | });
14 | });
15 |
16 | describe("Testing Overlay component", () => {
17 | it("unmount removes element", function() {
18 | const overlay = mount();
19 | overlay.unmount();
20 | expect(overlay.html()).toBe(null);
21 | });
22 |
23 | it("unmount cleans up", function() {
24 | const overlay = mount(
25 |
26 | );
27 | expect(document.body.style.overflow).toBe("hidden");
28 | overlay.unmount();
29 | expect(document.body.style.overflow).toBe("");
30 | });
31 |
32 | it("handles click", function() {
33 | const handleClick = jest.fn();
34 | const event = {
35 | "preventDefault": jest.fn(),
36 | "stopPropagation": jest.fn()
37 | };
38 | const overlay = mount();
39 | overlay.simulate("click", event);
40 | expect(handleClick).toBeCalled();
41 | expect(event.preventDefault).toBeCalled();
42 | expect(event.stopPropagation).toBeCalled();
43 | });
44 |
45 | it("stops defaults and propagation on click when onClick is not defined", function() {
46 | const handleClick = jest.fn();
47 | const event = {
48 | "preventDefault": jest.fn(),
49 | "stopPropagation": jest.fn()
50 | };
51 | const overlay = mount();
52 | overlay.simulate("click", event);
53 | expect(handleClick).not.toBeCalled();
54 | expect(event.preventDefault).toBeCalled();
55 | expect(event.stopPropagation).toBeCalled();
56 | });
57 |
58 | it("handles onEscKeyDown", function() {
59 | const handleEsc = jest.fn();
60 | const overlay = mount(); //eslint-disable-line no-unused-vars
61 |
62 | document.body.dispatchEvent(new KeyboardEvent("keydown", { "which": "27" }));
63 | expect(handleEsc).toBeCalled();
64 | });
65 |
66 | it("does not onEscKeyDown when a different key is pressed", function() {
67 | const handleEsc = jest.fn();
68 | const overlay = mount(); //eslint-disable-line no-unused-vars
69 |
70 | document.body.dispatchEvent(new KeyboardEvent("keydown", { "which": "28" }));
71 | expect(handleEsc).not.toBeCalled();
72 | });
73 | });
74 |
--------------------------------------------------------------------------------
/src/Portal/Portal.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import PropTypes from "prop-types";
3 | import ReactDOM from "react-dom";
4 | import cx from "classnames";
5 | import CSSModules from "react-css-modules";
6 | import styles from "./Portal.css";
7 |
8 | export class Portal extends Component {
9 | componentDidMount() {
10 | this._renderOverlay();
11 | }
12 |
13 | componentDidUpdate() {
14 | this._renderOverlay();
15 | }
16 |
17 | componentWillUnmount() {
18 | this._unrenderOverlay();
19 | this._unmountOverlayTarget();
20 | }
21 |
22 | _getOverlay() {
23 | if (!this.props.children) {
24 | return null;
25 | }
26 | return (
27 |
28 | {this.props.children}
29 |
30 | );
31 | }
32 |
33 | _renderOverlay() {
34 | const overlay = this._getOverlay();
35 | if (overlay !== null) {
36 | this._mountOverlayTarget();
37 | this._overlayInstance = ReactDOM.unstable_renderSubtreeIntoContainer(
38 | this,
39 | overlay,
40 | this._overlayTarget
41 | );
42 | } else {
43 | this._unrenderOverlay();
44 | this._unmountOverlayTarget();
45 | }
46 | }
47 |
48 | _unrenderOverlay() {
49 | if (this._overlayTarget) {
50 | ReactDOM.unmountComponentAtNode(this._overlayTarget);
51 | this._overlayInstance = null;
52 | }
53 | }
54 |
55 | _mountOverlayTarget() {
56 | if (!this._overlayTarget) {
57 | this._overlayTarget = document.createElement("div");
58 | this._portalContainerNode = document.body;
59 | this._portalContainerNode.appendChild(this._overlayTarget);
60 | }
61 | }
62 |
63 | _unmountOverlayTarget() {
64 | if (this._overlayTarget) {
65 | this._portalContainerNode.removeChild(this._overlayTarget);
66 | this._overlayTarget = null;
67 | }
68 | this._portalContainerNode = null;
69 | }
70 |
71 | render() {
72 | return null;
73 | }
74 | }
75 |
76 | Portal.propTypes = {
77 | /**
78 | * Text, any HTML element, or React Component.
79 | */
80 | children: PropTypes.node,
81 |
82 | /** An object, array, or string of CSS classes to apply to Portal.*/
83 | className: PropTypes.oneOfType([
84 | PropTypes.string,
85 | PropTypes.object,
86 | PropTypes.array
87 | ]),
88 |
89 | /**
90 | * Pass inline styling here.
91 | */
92 | style: PropTypes.object
93 | };
94 |
95 | Portal.defaultProps = {
96 | className: ""
97 | };
98 |
99 | export default CSSModules(Portal, styles, { allowMultiple: true });
100 |
--------------------------------------------------------------------------------
/src/Alert/Alert.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import styles from "./Alert.css";
5 | import CSSModules from "react-css-modules";
6 |
7 | export class Alert extends React.PureComponent {
8 | constructor(props) {
9 | super(props);
10 |
11 | // component state
12 | this.state = {
13 | visible: true
14 | };
15 | }
16 |
17 | _closeAlert = event => {
18 | if (this.props.onDismiss) {
19 | this.props.onDismiss(event);
20 | }
21 | this.setState({
22 | visible: false
23 | });
24 | };
25 |
26 | render() {
27 | let { hidden, children, dismissible, type, className, style } = this.props;
28 | const alertClasses = cx({
29 | alert: true,
30 | success: type === "success",
31 | warning: type === "warning",
32 | danger: type === "danger",
33 | hidden
34 | });
35 | return (
36 |
37 | {this.state.visible && (
38 |
39 | {children}
40 | {dismissible && (
41 |
48 | ×
49 |
50 | )}
51 |
52 | )}
53 |
54 | );
55 | }
56 | }
57 |
58 | Alert.propTypes = {
59 | /**
60 | * Any HTML element or React Component.
61 | */
62 | children: PropTypes.node.isRequired,
63 |
64 | /**
65 | * An object, array, or string of CSS classes to apply to Button.
66 | */
67 | className: PropTypes.oneOfType([
68 | PropTypes.string,
69 | PropTypes.object,
70 | PropTypes.array
71 | ]),
72 |
73 | /**
74 | * When true, the Alert can be dismissed.
75 | */
76 | dismissible: PropTypes.bool,
77 |
78 | /**
79 | * A boolean to hide or show the alert component.
80 | */
81 | hidden: PropTypes.bool,
82 |
83 | /**
84 | * Function that will be executed on dismiss.
85 | */
86 | onDismiss: PropTypes.func,
87 |
88 | /**
89 | * Pass inline styles here.
90 | */
91 | style: PropTypes.object,
92 |
93 | /**
94 | * Will set the Alert's style. One of: 'info', 'success', 'warning', 'danger'
95 | */
96 | type: PropTypes.string
97 | };
98 |
99 | Alert.defaultProps = {
100 | type: "info"
101 | };
102 |
103 | export default CSSModules(Alert, styles, { allowMultiple: true });
104 |
--------------------------------------------------------------------------------
/src/TabList/TabList.js:
--------------------------------------------------------------------------------
1 | import React, { cloneElement } from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import CSSModules from "react-css-modules";
5 | import styles from "./TabList.css";
6 |
7 | /**
8 | * TabList component
9 | */
10 | export class TabList extends React.PureComponent {
11 | constructor(props) {
12 | super(props);
13 |
14 | // Initial state
15 | this.state = {
16 | selectedTab: this.props.selectedTab || 0
17 | };
18 | }
19 |
20 | UNSAFE_componentWillReceiveProps(nextProps) {
21 | if (nextProps.selectedTab !== this.props.selectedTab) {
22 | this.setState({ selectedTab: nextProps.selectedTab });
23 | }
24 | }
25 |
26 | _setSelectedTab = (index, event) => {
27 | this.setState({ selectedTab: index });
28 | this.props.setSelectedIndex(index, event);
29 | };
30 |
31 | render() {
32 | const { className, children, vertical, style } = this.props;
33 |
34 | const tabs = React.Children.map(children, (child, index) => {
35 | child = cloneElement(child, {
36 | tabIndex: index,
37 | selected: this.state.selectedTab === index,
38 | setSelectedTab: this._setSelectedTab,
39 | vertical: vertical
40 | });
41 |
42 | return child;
43 | });
44 |
45 | let tabListClasses = cx(
46 | {
47 | vertical
48 | },
49 | "tabList"
50 | );
51 |
52 | return (
53 |
56 | );
57 | }
58 | }
59 |
60 | TabList.propTypes = {
61 | /**
62 | * Will be automatically set when bordered prop is passed to Tabs component.
63 | *
64 | * @ignore
65 | */
66 | bordered: PropTypes.bool,
67 |
68 | /**
69 | * An object, array, or string of CSS classes to apply to TabPanel.
70 | */
71 | className: PropTypes.oneOfType([
72 | PropTypes.string,
73 | PropTypes.object,
74 | PropTypes.array
75 | ]),
76 |
77 | /**
78 | * Tab components that will be displayed in TabList.
79 | */
80 | children: PropTypes.node.isRequired,
81 |
82 | /**
83 | * Selected tab index (default 0 - first tab).
84 | */
85 | selectedTab: PropTypes.number,
86 |
87 | /**
88 | * Handler to execute when a tab is selected, in Tabs component.
89 | */
90 | setSelectedIndex: PropTypes.func,
91 |
92 | /**
93 | * Pass inline styling here.
94 | */
95 | style: PropTypes.object,
96 |
97 | /**
98 | * Will be automatically set when vertical prop is passed to Tabs component.
99 | */
100 | vertical: PropTypes.bool
101 | };
102 |
103 | export default CSSModules(TabList, styles, { allowMultiple: true });
104 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { Accordion } from "./Accordion";
2 | export { Accordion };
3 | import { AccordionPanel } from "./AccordionPanel";
4 | export { AccordionPanel };
5 | import { Alert } from "./Alert";
6 | export { Alert };
7 | import { Avatar } from "./Avatar";
8 | export { Avatar };
9 | import { Breadcrumb } from "./Breadcrumb";
10 | export { Breadcrumb };
11 | import { BreadcrumbItem } from "./BreadcrumbItem";
12 | export { BreadcrumbItem };
13 | import { Button } from "./Button";
14 | export { Button };
15 | import { Card } from "./Card";
16 | export { Card };
17 | import { Checkbox } from "./Checkbox";
18 | export { Checkbox };
19 | import { CheckboxGroup } from "./CheckboxGroup";
20 | export { CheckboxGroup };
21 | import { Dialog } from "./Dialog";
22 | export { Dialog };
23 | import { Dropdown } from "./Dropdown";
24 | export { Dropdown };
25 | import { FileUpload } from "./FileUpload";
26 | export { FileUpload };
27 | import { Form } from "./Form";
28 | export { Form };
29 | import { Hint } from "./Hint";
30 | export { Hint };
31 | import { Icon } from "./Icon";
32 | export { Icon };
33 | import { Label } from "./Label";
34 | export { Label };
35 | import { List } from "./List";
36 | export { List };
37 | import { ListGroup } from "./ListGroup";
38 | export { ListGroup };
39 | import { ListItem } from "./ListItem";
40 | export { ListItem };
41 | import { Modal } from "./Modal";
42 | export { Modal };
43 | import { Nav } from "./Nav";
44 | export { Nav };
45 | import { NavItem } from "./NavItem";
46 | export { NavItem };
47 | import { Option } from "./Option";
48 | export { Option };
49 | import { Overlay } from "./Overlay";
50 | export { Overlay };
51 | import { Portal } from "./Portal";
52 | export { Portal };
53 | import { ProgressBar } from "./ProgressBar";
54 | export { ProgressBar };
55 | import { Radio } from "./Radio";
56 | export { Radio };
57 | import { RadioGroup } from "./RadioGroup";
58 | export { RadioGroup };
59 | import { Switch } from "./Switch";
60 | export { Switch };
61 | import { Tab } from "./Tab";
62 | export { Tab };
63 | import { Table } from "./Table";
64 | export { Table };
65 | import { TableHeader } from "./TableHeader";
66 | export { TableHeader };
67 | import { TabList } from "./TabList";
68 | export { TabList };
69 | import { TabPanel } from "./TabPanel";
70 | export { TabPanel };
71 | import { Tabs } from "./Tabs";
72 | export { Tabs };
73 | import { Task } from "./Task";
74 | export { Task };
75 | import { Taskbar } from "./Taskbar";
76 | export { Taskbar };
77 | import { Text } from "./Text";
78 | export { Text };
79 | import { TextArea } from "./TextArea";
80 | export { TextArea };
81 | import { TextField } from "./TextField";
82 | export { TextField };
83 | import { Timer } from "./Timer";
84 | export { Timer };
85 | import { Tooltip } from "./Tooltip";
86 | export { Tooltip };
87 |
--------------------------------------------------------------------------------
/src/Tooltip/__tests__/tooltip.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { Tooltip } from "../index";
4 |
5 | import { verifyPropsDefaultValue } from "../../utils/propsVerification";
6 |
7 | import renderer from "react-test-renderer";
8 |
9 | describe("Test Tooltip component render", () => {
10 | it("Render correctly", () => {
11 | const tree = renderer
12 | .create(
13 | "}
17 | tooltipDelay={3000}
18 | active={false}
19 | className={"class"}
20 | />
21 | )
22 | .toJSON();
23 | expect(tree).toMatchSnapshot();
24 | });
25 | });
26 |
27 | describe("Testing Tooltip component", () => {
28 | it("Tooltip component - Properties basic test", function() {
29 | const comp = mount(
30 | "}
34 | tooltipDelay={3000}
35 | active={false}
36 | className={"class"}
37 | />
38 | );
39 | const expectedProps = new Map([
40 | ["tooltip", "Hey I'm a tooltip"],
41 | ["position", "top"],
42 | ["tooltipDelay", 3000],
43 | ["active", false],
44 | ["className", "class"]
45 | ]);
46 |
47 | expect(verifyPropsDefaultValue(comp, expectedProps)).toEqual(true);
48 | });
49 |
50 | it("Tooltip component - Mouse in with delays", function() {
51 | const comp = mount();
52 | jest.useFakeTimers();
53 | expect(comp.state().active).toEqual(false);
54 | comp.simulate("mouseEnter");
55 | jest.runAllTimers();
56 | expect(comp.state().active).toEqual(true);
57 | });
58 |
59 | it("Tooltip component - Mouse in without delays", function() {
60 | const comp = mount();
61 | jest.useFakeTimers();
62 | expect(comp.state().active).toEqual(false);
63 | comp.simulate("mouseEnter");
64 | jest.runAllTimers();
65 | expect(comp.state().active).toEqual(true);
66 | });
67 |
68 | it("Tooltip component - Mouse in/out", function() {
69 | const comp = mount();
70 |
71 | comp.simulate("mouseEnter");
72 | expect(comp.state().active).toEqual(true);
73 |
74 | comp.simulate("mouseLeave");
75 | expect(comp.state().active).toEqual(false);
76 | });
77 |
78 | it("Tooltip children overwrite icon", function() {
79 | const comp = mount(
80 |
81 | {" "}
82 | foo
83 |
84 | );
85 | expect(comp.find("i").exists()).toBe(false);
86 | });
87 | });
88 |
--------------------------------------------------------------------------------
/src/Card/Card.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import CSSModules from "react-css-modules";
5 | import styles from "./Card.css";
6 |
7 | /**
8 | * Simple Card component that wraps a div around content with card styling.
9 | */
10 | export class Card extends React.PureComponent {
11 | constructor(props) {
12 | super(props);
13 | }
14 | render() {
15 | const {
16 | children,
17 | className,
18 | legend,
19 | style,
20 | standardFieldset,
21 | image,
22 | title
23 | } = this.props;
24 | let cardBody = children ? (
25 | {children}
26 | ) : null;
27 |
28 | let isFieldset = standardFieldset ? (
29 |
33 | ) : null;
34 |
35 | let useImage = image ?
: null;
36 |
37 | let Title = title ? {title}
: null;
38 |
39 | let card = !standardFieldset ? (
40 |
41 | {useImage}
42 | {Title}
43 | {cardBody}
44 |
45 | ) : null;
46 |
47 | return (
48 |
49 | {isFieldset}
50 | {card}
51 |
52 | );
53 | }
54 | }
55 |
56 | Card.propTypes = {
57 | /**
58 | * Any HTML element or React Component.
59 | * @examples Some Text.
60 | */
61 | children: PropTypes.node.isRequired,
62 |
63 | /** An object, array, or string of CSS classes to apply to card.*/
64 | className: PropTypes.oneOfType([
65 | PropTypes.string,
66 | PropTypes.object,
67 | PropTypes.array
68 | ]),
69 |
70 | /**
71 | * Path to an image that will be displayed in Card.
72 | * @examples "http://path.to/an/image.jpg"
73 | */
74 | image: PropTypes.string,
75 |
76 | /**
77 | * Legend that will be displayed on Card when standardFieldset prop is true.
78 | */
79 | legend: PropTypes.string,
80 |
81 | /**
82 | * When true, will generate a fieldset Card.
83 | * @example {children}
84 | */
85 | standardFieldset: PropTypes.bool,
86 |
87 | /**
88 | * Pass inline styles here.
89 | */
90 | style: PropTypes.object,
91 |
92 | /**
93 | * Title that will be displayed inside Cards that do not have the standardFieldset prop.
94 | * @examples "Title Words" will output "Title Words"
95 | */
96 | title: PropTypes.string
97 | };
98 |
99 | export default CSSModules(Card, styles, { allowMultiple: true });
100 |
--------------------------------------------------------------------------------
/src/Label/__tests__/label.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { Label } from "../index";
4 | import renderer from "react-test-renderer";
5 |
6 | describe("Test Label component", () => {
7 | it("Test render correctly", () => {
8 | const comp = ;
9 | const tree = renderer.create(comp).toJSON();
10 | expect(tree).toMatchSnapshot();
11 | });
12 |
13 | it("htmlFor renders for attribute", () => {
14 | const label = mount();
15 |
16 | expect(label.props().htmlFor).toBe("someField");
17 | expect(
18 | label
19 | .find("label")
20 | .find('[htmlFor="someField"]')
21 | .exists()
22 | ).toBe(true);
23 | });
24 |
25 | it("inline && leftLabel renders with inline css classes", () => {
26 | const label = mount(
27 |
28 | );
29 |
30 | expect(label.find(".inline").exists()).toBe(true);
31 | });
32 |
33 | it("renders label text", () => {
34 | const label = mount(
35 |
36 | );
37 |
38 | expect(label.find("label").text()).toEqual("Some Field:");
39 | });
40 |
41 | it("leftLabel omits unneeded css classes", () => {
42 | const label = mount(
43 |
44 | );
45 |
46 | expect(label.find(".labelSpacing").exists()).toBe(false);
47 | expect(label.find(".verticalPadding").exists()).toBe(false);
48 | });
49 |
50 | it("renders * by default for required", () => {
51 | const label = mount(
52 |
53 | );
54 |
55 | expect(label.find(".required").html()).toContain("*");
56 | });
57 |
58 | it("renders text if supplied for required", () => {
59 | const label = mount(
60 |
65 | );
66 |
67 | expect(label.find(".required").html()).toContain("this field is required");
68 | });
69 |
70 | it("renders text if supplied for required", () => {
71 | const label = mount(
72 |
77 | );
78 |
79 | expect(label.find(".required").html()).toContain("this field is required");
80 | });
81 |
82 | it("applies error css class if status is error and required is true", () => {
83 | const label = mount(
84 |
85 | );
86 |
87 | expect(label.find(".required_error").exists()).toBe(true);
88 | });
89 | });
90 |
--------------------------------------------------------------------------------
/src/Card/__tests__/card.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { Card } from "../index";
4 | import { Checkbox } from "../../Checkbox/Checkbox";
5 | import { CheckboxGroup } from "../../CheckboxGroup/CheckboxGroup";
6 | import { verifyPropsDefaultValue } from "../../utils/propsVerification";
7 |
8 | import renderer from "react-test-renderer";
9 |
10 | describe("Test Card component", () => {
11 | it("renders correctly", () => {
12 | const tree = renderer
13 | .create()
14 | .toJSON();
15 | expect(tree).toMatchSnapshot();
16 | });
17 | });
18 |
19 | describe("Test Card component: Basic Tests", () => {
20 | let cardComponent = null;
21 |
22 | it("Card - Basic properties test", function() {
23 | cardComponent = mount();
24 | const expected = new Map([["className", "name"], ["legend", "lalala"]]);
25 | expect(verifyPropsDefaultValue(cardComponent, expected)).toEqual(true);
26 | });
27 |
28 | it("Basic Accordion", () => {
29 | expect(
30 | cardComponent.exists(
31 |
32 | Child
33 |
34 | )
35 | ).toBe(true);
36 | });
37 |
38 | it("Contains No Child", () => {
39 | cardComponent = mount();
40 | expect(cardComponent.props().children).toBeUndefined();
41 | });
42 |
43 | it("Card - Children test", function() {
44 | cardComponent = mount(
45 |
46 | Card Test
47 |
48 | );
49 | expect(cardComponent.props()).toHaveProperty("children");
50 | });
51 |
52 | it("Test Standard Fieldset", function() {
53 | cardComponent = mount(
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | );
62 | expect(cardComponent.props().standardFieldset).toBe(true);
63 | });
64 |
65 | it("Card - Image prop test", function() {
66 | cardComponent = mount(
67 |
68 | );
69 | expect(cardComponent.props().image).toBe(
70 | "https://static1.squarespace.com/static/5369465be4b0507a1fd05af0/5397d14be4b06a5454f5633c/5397d15ae4b06a5454f56351/1404441173879/neo_001126-02.jpg?format=1500w"
71 | );
72 | });
73 |
74 | it("Test Title prop", () => {
75 | cardComponent = mount(first);
76 | expect(cardComponent.props().title).toBe("first");
77 | });
78 | });
79 |
--------------------------------------------------------------------------------
/src/RadioGroup/__tests__/radioGroup.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { Radio } from "../../Radio/index";
4 | import { RadioGroup } from "../index";
5 |
6 | import renderer from "react-test-renderer";
7 |
8 | describe("Test RadioGroup component render", () => {
9 | it("Render correctly", () => {
10 | const tree = renderer
11 | .create(
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | )
21 | .toJSON();
22 | expect(tree).toMatchSnapshot();
23 | });
24 | });
25 |
26 | describe("Testing radio component", () => {
27 | it("RadioGroup - Basic test", function() {
28 | mount(
29 |
30 |
31 |
32 |
33 | );
34 | });
35 |
36 | it("RadioGroup - Change selection test", function() {
37 | const result = mount(
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | );
47 | expect(result.state().checkedRadio).toEqual(0);
48 |
49 | result
50 | .find(Radio)
51 | .last()
52 | .simulate("click");
53 | expect(result.state().checkedRadio).toEqual(5);
54 |
55 | result
56 | .find(Radio)
57 | .first()
58 | .simulate("click");
59 | expect(result.state().checkedRadio).toEqual(0);
60 | });
61 |
62 | it("RadioGroup - Change props ", function() {
63 | const result = mount(
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | );
73 | result.setProps({ "name": "Name" });
74 |
75 | result
76 | .find(Radio)
77 | .last()
78 | .simulate("click");
79 | expect(result.state().checkedRadio).toEqual(5);
80 |
81 | result.setProps({ "selectedIndex": 1 });
82 | expect(result.state().checkedRadio).toEqual(1);
83 | });
84 | });
85 |
--------------------------------------------------------------------------------
/src/Tab/Tab.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import cx from "classnames";
4 | import CSSModules from "react-css-modules";
5 | import styles from "./Tab.css";
6 |
7 | /**
8 | * Tab component
9 | */
10 | export class Tab extends React.PureComponent {
11 | constructor(props) {
12 | super(props);
13 |
14 | // Initial state
15 | this.state = {
16 | selected: this.props.selected,
17 | disabled: this.props.disabled
18 | };
19 | }
20 |
21 | UNSAFE_componentWillReceiveProps = nextProps => {
22 | if (nextProps.selected !== this.props.selected) {
23 | this.setState({ selected: nextProps.selected });
24 | }
25 | };
26 |
27 | _handleClick = event => {
28 | let selected = this.props.tabIndex;
29 |
30 | if (!this.state.disabled) {
31 | this.props.setSelectedTab(selected, event);
32 | }
33 | };
34 |
35 | render() {
36 | const { className, children, vertical, icon, style } = this.props;
37 |
38 | let tabClasses = cx({
39 | tab: !vertical,
40 | vTab: vertical,
41 | selected: this.state.selected && !vertical,
42 | vSelected: this.state.selected && vertical,
43 | disabled: this.state.disabled
44 | });
45 |
46 | return (
47 |
53 | {icon ? : null}
54 | {children}
55 |
56 | );
57 | }
58 | }
59 |
60 | Tab.propTypes = {
61 | /**
62 | * Child components or elements to be displayed as the title on Tab.
63 | */
64 | children: PropTypes.node,
65 |
66 | /**
67 | * An object, array, or string of CSS classes to apply to Tab.
68 | */
69 | className: PropTypes.oneOfType([
70 | PropTypes.string,
71 | PropTypes.object,
72 | PropTypes.array
73 | ]),
74 |
75 | /**
76 | * When true, Tab sill be disabled.
77 | */
78 | disabled: PropTypes.bool,
79 |
80 | /**
81 | * The CSS class name for the icon that will be displayed on Tab.
82 | */
83 | icon: PropTypes.string,
84 |
85 | /**
86 | * When true, Tab will be selected.
87 | */
88 | selected: PropTypes.bool,
89 |
90 | /**
91 | * Function to be executed when a Tab is selected.
92 | */
93 | setSelectedTab: PropTypes.func,
94 |
95 | /**
96 | * Pass inline styling here.
97 | */
98 | style: PropTypes.object,
99 |
100 | /**
101 | * Tab index.
102 | */
103 | tabIndex: PropTypes.number,
104 |
105 | /**
106 | * When true, Tabs will display vertically.
107 | */
108 | vertical: PropTypes.bool
109 | };
110 |
111 | Tab.defaultProps = {
112 | selected: false,
113 | disabled: false
114 | };
115 |
116 | export default CSSModules(Tab, styles, { allowMultiple: true });
117 |
--------------------------------------------------------------------------------
/src/Checkbox/Checkbox.css:
--------------------------------------------------------------------------------
1 | @import '../styles/variables.css';
2 |
3 | .disabled {
4 | composes: default-text from '../styles.css';
5 | }
6 |
7 | .relative {
8 | position:relative;
9 | }
10 |
11 | .padding {
12 | padding-bottom: 5px;
13 | }
14 |
15 | .input {
16 | composes: relative;
17 | top: 1px;
18 | }
19 |
20 | .checkbox {
21 | composes: rounded from '../styles.css';
22 | composes: default-border from "../styles.css";
23 | composes: relative;
24 | position: absolute;
25 | top: 0px;
26 | width: 16px;
27 | height: 16px;
28 | cursor: pointer;
29 | }
30 |
31 | .disabled {
32 | opacity: 0.65;
33 | composes: cursor-not-allowed from '../styles.css';
34 | pointer-events: none;
35 | }
36 |
37 | .checked {
38 | composes: checkbox;
39 | composes: bg-primary from '../styles.css';
40 | }
41 |
42 | .hidden {
43 | display: none;
44 | visibility: hidden;
45 | }
46 |
47 | .focus {
48 | box-shadow: 0 0 6px var(--primary)
49 | }
50 |
51 | .checkmark {
52 | composes: relative;
53 | top: 0px;
54 | left: 4px;
55 | width: 4px;
56 | height: 10px;
57 | transform: rotate(45deg);
58 | border: solid var(--white);
59 | border-width: 0 3px 3px 0;
60 | }
61 |
62 | .error {
63 | border: solid 1px var(--error);
64 | }
65 |
66 | /* Display checkbox with out the checkbox selected. */
67 | .not_checked {
68 | composes: checkbox;
69 | background: -webkit-linear-gradient(#fff, #e6e6e6); /* For Safari 5.1 to 6.0 */
70 | background: -o-linear-gradient(#fff, #e6e6e6); /* For Opera 11.1 to 12.0 */
71 | background: -moz-linear-gradient(#fff, #e6e6e6); /* For Firefox 3.6 to 15 */
72 | background: linear-gradient(#fff, #e6e6e6); /* Standard syntax */
73 | }
74 |
75 | .label {
76 | composes: default-font from '../styles.css';
77 | cursor: pointer;
78 | white-space: nowrap;
79 | padding-right:5px;
80 | }
81 |
82 | /* label text */
83 | .label_left {
84 | composes: label;
85 | padding-right: 2px;
86 | margin-left: 0px;
87 | }
88 |
89 | .error_text {
90 | composes: default-font from '../styles.css';
91 | composes: error-text from '../styles.css';
92 | }
93 |
94 | .error_message {
95 | composes: error_text;
96 | margin-left:23px;
97 | }
98 |
99 | .inline_block {
100 | display: inline-block;
101 | }
102 |
103 | .checkbox_padding {
104 | padding: 10px 10px 0 0;
105 | }
106 |
107 | .inline_padding {
108 | padding: 2px 10px 0 0;
109 | }
110 |
111 | .float_left {
112 | float:left;
113 | padding-right: 3px;
114 | }
115 |
116 | .float_right {
117 | float:right;
118 | padding-left: 3px;
119 | position: relative;
120 | }
121 |
122 | .opacity {
123 | /*this needs to stay here to avoid display issues with those modules in IE*/
124 | opacity: 0;
125 | }
126 |
127 | .required {
128 | composes: secondary-text from '../styles.css';
129 | }
130 |
131 | .required_error {
132 | composes: error-text from '../styles.css';
133 | }
--------------------------------------------------------------------------------
/src/Alert/README.md:
--------------------------------------------------------------------------------
1 | Alert:
2 |
3 |
4 | This is a default Alert!
5 |
6 |
7 | Alert with multiple inline text elements:
8 |
9 |
10 |
11 | Success! Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed volutpat nisi non odio pretium imperdiet. Praesent eget quam egestas, mattis orci sit amet, faucibus ipsum. Aliquam viverra vulputate porttitor. Suspendisse potenti. Nullam sit amet massa non nulla rhoncus dictum in ac ipsum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Cras suscipit luctus tellus, nec finibus justo dignissim ac. Aliquam iaculis libero turpis, quis imperdiet elit consequat eget. In hac habitasse platea dictumst. Aliquam volutpat, nisi eget tincidunt accumsan, eros magna tincidunt tellus, quis accumsan enim turpis sit amet ex. Morbi accumsan, felis sed ultricies molestie, massa odio tristique est, sed eleifend sapien massa in massa. Vestibulum gravida maximus varius. Vivamus a elit consectetur, ornare est in, gravida turpis.
12 |
13 |
14 |
15 | Alert with children:
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Alert types:
27 |
28 |
29 |
30 |
31 | Success! This alert box indicates a successful or positive action.
32 |
33 |
34 |
35 |
36 | Info! This alert box indicates a neutral informative change or action.
37 |
38 |
39 |
40 |
41 | Warning! This alert box indicates a warning that might need attention.
42 |
43 |
44 |
45 |
46 | Danger! This alert box indicates a dangerous or potentially negative action.
47 |
48 |
49 |
50 | Dismissible Alerts:
51 |
52 |
53 |
54 | Success! This alert box indicates a successful or positive action.
55 |
56 |
57 |
58 |
59 | Info! This alert box indicates a neutral informative change or action.
60 |
61 |
62 |
63 |
64 | Warning! This alert box indicates a warning that might need attention.
65 |
66 |
67 |
68 |
69 | Danger! This alert box indicates a dangerous or potentially negative action.
70 |
71 |
72 |
73 | onDismiss callback:
74 |
75 |
76 | Success! This alert box will trigger a callback function when dismissed.
77 |
--------------------------------------------------------------------------------
/src/Tab/__tests__/tab.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { mount } from "enzyme";
3 | import { Tab } from "../index";
4 | import renderer from "react-test-renderer";
5 |
6 | describe("Test Tab component", () => {
7 | it("Test render correctly", () => {
8 | const comp = My Tab;
9 | const tree = renderer.create(comp).toJSON();
10 | expect(tree).toMatchSnapshot();
11 | });
12 |
13 | it("applies className", () => {
14 | const tab = mount(My Tab);
15 |
16 | expect(tab.find(".myClass").exists()).toBe(true);
17 | });
18 |
19 | it("sets defaults", () => {
20 | const tab = mount(My Tab);
21 |
22 | expect(tab.state().selected).toBe(false);
23 | expect(tab.state().disabled).toBe(false);
24 | expect(tab.props().selected).toBe(false);
25 | expect(tab.props().disabled).toBe(false);
26 | });
27 |
28 | it("applies disabled", () => {
29 | const tab = mount(My Tab);
30 |
31 | expect(tab.state().disabled).toBe(true);
32 | expect(tab.props().disabled).toBe(true);
33 | });
34 |
35 | it("applies icon", () => {
36 | const tab = mount(My Tab);
37 |
38 | expect(tab.find("i.fa.fa-github").exists()).toBe(true);
39 | });
40 |
41 | it("applies selected", () => {
42 | const tab = mount(My Tab);
43 |
44 | expect(tab.state().selected).toBe(true);
45 | expect(tab.props().selected).toBe(true);
46 | });
47 |
48 | it("handles setSelectedTab", () => {
49 | const handleSelect = jest.fn();
50 | const tab = mount(My Tab);
51 |
52 | tab.simulate("click");
53 | expect(handleSelect).toBeCalled();
54 | });
55 |
56 | it("does not call setSelectedTab when disabled", () => {
57 | const handleSelect = jest.fn();
58 | const tab = mount(
59 |
60 | My Tab
61 |
62 | );
63 |
64 | tab.simulate("click");
65 | expect(handleSelect).not.toBeCalled();
66 | });
67 |
68 | it("applies style", () => {
69 | const tab = mount(My Tab);
70 |
71 | expect(tab.find("li").props().style).toEqual({ color: "red" });
72 | });
73 |
74 | it("applies vertical", () => {
75 | const tab = mount(
76 |
77 | My Tab
78 |
79 | );
80 |
81 | expect(tab.find(".vTab").exists()).toBe(true);
82 | expect(tab.find(".vSelected").exists()).toBe(true);
83 | });
84 |
85 | it("CWRP updates selected", () => {
86 | const tab = mount(
87 |
88 | My Tab
89 |
90 | );
91 | //starting true to catch else branch
92 | expect(tab.state().selected).toBe(true);
93 | tab.setProps({ selected: true });
94 | expect(tab.state().selected).toBe(true);
95 | tab.setProps({ selected: false });
96 | expect(tab.state().selected).toBe(false);
97 | tab.setProps({ selected: true });
98 | expect(tab.state().selected).toBe(true);
99 | });
100 | });
101 |
--------------------------------------------------------------------------------
/src/ProgressBar/ProgressBar.css:
--------------------------------------------------------------------------------
1 | @import '../styles/variables.css';
2 |
3 | .linear {
4 | position: relative;
5 | overflow: hidden;
6 | width: 100%;
7 | background: var(--silver) none repeat scroll 0% 0%;
8 | height: .4rem;
9 | }
10 | .linear.indeterminate .value {
11 | transform-origin: center center;
12 | animation: linear-indeterminate-bar 1s linear infinite;
13 | }
14 |
15 | .buffer {
16 |
17 | }
18 |
19 | .value, .buffer {
20 | position: absolute;
21 | top: 0;
22 | right: 0;
23 | bottom: 0;
24 | left: 0;
25 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); /*$animation-curve-default;*/
26 | transform: scaleX(0);
27 | transform-origin: left center;
28 | }
29 |
30 | .value {
31 | composes: bg-primary from "../styles.css"
32 | }
33 | .buffer {
34 | background-image: linear-gradient(to right, rgba(255,255,255, 0.7), rgba(255,255,255, 0.7)),
35 | linear-gradient(to right, var(--primary), var(--primary));
36 |
37 | }
38 |
39 | .circular {
40 | position: relative;
41 | display: inline-block;
42 | width: 60px;
43 | height: 60px;
44 | transform: rotate(-90deg);
45 | }
46 | .circular.indeterminate .circle {
47 | animation: circular-indeterminate-bar-rotate 2s linear infinite;
48 | }
49 | .circular.indeterminate .path {
50 | animation: circular-indeterminate-bar-dash 1.5s ease-in-out infinite;
51 | stroke-dasharray: 1.25, 250;
52 | stroke-dashoffset: 0;
53 | }
54 | .circular.multicolor .path {
55 | animation: circular-indeterminate-bar-dash 1.5s ease-in-out infinite,
56 | colors (1.5s * 4) ease-in-out infinite;
57 | }
58 |
59 | .circle {
60 | width: 100%;
61 | height: 100%;
62 | }
63 |
64 | .path {
65 | transition: stroke-dasharray .35s cubic-bezier(0.4, 0, 0.2, 1);
66 | fill: none;
67 | stroke-dasharray: 0, 500;
68 | stroke-dashoffset: 0;
69 | stroke-linecap: round;
70 | stroke-miterlimit: 20;
71 | stroke-width: 4;
72 | stroke: var(--primary);
73 | }
74 |
75 | .indeterminate {
76 |
77 | }
78 |
79 | .determinate {
80 |
81 | }
82 |
83 | @keyframes linear-indeterminate-bar {
84 | 0% {
85 | transform: translate(-50%) scaleX(0);
86 | }
87 |
88 | 50% {
89 | transform: translate(-0%) scaleX(.3);
90 | }
91 |
92 | 100% {
93 | transform: translate(50%) scaleX(0);
94 | }
95 | }
96 |
97 | @keyframes circular-indeterminate-bar-rotate {
98 | 100% {
99 | transform: rotate(360deg);
100 | }
101 | }
102 |
103 | @keyframes circular-indeterminate-bar-dash {
104 | 0% {
105 | stroke-dasharray: 1.25, 250;
106 | stroke-dashoffset: 0;
107 | }
108 |
109 | 50% {
110 | stroke-dasharray: 111.25, 250;
111 | stroke-dashoffset: -43.75;
112 | }
113 |
114 | 100% {
115 | stroke-dasharray: 111.25, 250;
116 | stroke-dashoffset: -155;
117 | }
118 | }
119 |
120 | @keyframes colors {
121 | 0% {
122 | stroke: #4285f4;
123 | }
124 |
125 | 25% {
126 | stroke: #de3e35;
127 | }
128 |
129 | 50% {
130 | stroke: #f7c223;
131 | }
132 |
133 | 75% {
134 | stroke: #1b9a59;
135 | }
136 |
137 | 100% {
138 | stroke: #4285f4;
139 | }
140 | }
--------------------------------------------------------------------------------