diff --git a/app/assets/stylesheets/common/_focusable.scss b/app/assets/stylesheets/common/_focusable.scss new file mode 100644 index 00000000..eb3af643 --- /dev/null +++ b/app/assets/stylesheets/common/_focusable.scss @@ -0,0 +1,6 @@ +/* License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later */ +.focusable_item { + &:focus { + outline: 1px dotted black + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/global.css.scss b/app/assets/stylesheets/global.css.scss index 745425dc..e89aee50 100644 --- a/app/assets/stylesheets/global.css.scss +++ b/app/assets/stylesheets/global.css.scss @@ -43,3 +43,5 @@ @import 'common/z_indices'; @import 'common/ios_hack'; @import 'common/minimal'; + +@import 'common/focusable' \ No newline at end of file diff --git a/javascripts/src/components/common/BootstrapWrapper.tsx b/javascripts/src/components/common/BootstrapWrapper.tsx new file mode 100644 index 00000000..231f2003 --- /dev/null +++ b/javascripts/src/components/common/BootstrapWrapper.tsx @@ -0,0 +1,16 @@ +// License: LGPL-3.0-or-later +import * as React from 'react'; +import { observer } from 'mobx-react'; + +class BootstrapWrapper extends React.Component<{}, {}> { + render() { + return
+ {this.props.children} +
; + } +} + +export default observer(BootstrapWrapper) + + + diff --git a/javascripts/src/components/common/DefaultCloseButton.tsx b/javascripts/src/components/common/DefaultCloseButton.tsx new file mode 100644 index 00000000..2ce37e3e --- /dev/null +++ b/javascripts/src/components/common/DefaultCloseButton.tsx @@ -0,0 +1,115 @@ +import React = require("react"); +import { action, observable } from "mobx"; +import { Transition } from "react-transition-group"; +import { CloseButton } from "./svg/CloseButton"; +import color = require("color"); +import { observer } from "mobx-react"; +import ScreenReaderOnlyText from "./ScreenReaderOnlyText"; + +interface DefaultCloseButtonProps { + onClick?: () => void +} + +const mainColor = '#969696' +const darkenedColor = color(mainColor).darken(0.1).hex() +const defaultStyles = { + foreground: { + fill: mainColor + }, + background: { + stroke: mainColor, + fill: '#FFFFFF' + } +} + +const states: { [state: string]: any } = { + entering: { + foreground: { + fill: darkenedColor, + transition: 'fill 250ms ease-in-out' + }, + background: { + stroke: darkenedColor, + transition: 'stroke 250ms ease-in-out' + } + }, + entered: { + foreground: { + fill: darkenedColor, + }, + background: { + stroke: darkenedColor, + } + }, + exiting: { + foreground: { + fill: mainColor, + transition: 'fill 250ms ease-in-out' + }, + background: { + stroke: mainColor, + transition: 'stroke 250ms ease-in-out' + } + }, + exited: { + foreground: { + fill: mainColor, + }, + background: { + stroke: mainColor, + } + } +} + +@observer +export class DefaultCloseButton extends React.Component { + @observable + hovering: boolean + + @observable + focusing: boolean + + @action.bound + mouseEnter() { + this.hovering = true; + } + + @action.bound + mouseLeave() { + this.hovering = false; + } + + @action.bound + keyDown(event: React.KeyboardEvent) { + if (event.key == 'Enter') { + event.preventDefault(); + this.props.onClick(); + } + } + + render() { + return + {(hoverState) => { + const backgroundStyle = { + ...defaultStyles.background, + ...((states[hoverState] && states[hoverState].background) || {}) + } + + const foregroundStyle = + { + ...defaultStyles.foreground, + ...((states[hoverState] && states[hoverState].foreground) || {}) + } + + return + Close modal + + + } + } + + + } +} diff --git a/javascripts/src/components/common/Modal.spec.tsx b/javascripts/src/components/common/Modal.spec.tsx index dcad6ee5..7e534f25 100644 --- a/javascripts/src/components/common/Modal.spec.tsx +++ b/javascripts/src/components/common/Modal.spec.tsx @@ -2,9 +2,9 @@ import * as React from 'react'; import 'jest'; import Modal, {ModalProps} from './Modal' -import {shallow} from "enzyme"; -import {toJS} from "mobx"; +import {shallow, mount, ReactWrapper} from "enzyme"; import toJson from "enzyme-to-json"; +import { DefaultCloseButton } from './DefaultCloseButton'; describe('Modal', () => { test('nothing displayed if inactive', () => { @@ -13,16 +13,47 @@ describe('Modal', () => { expect(toJson(modal)).toMatchSnapshot() }) - test('active modal displays', () => { + describe('active modal displays', () => { let onCloseWasCalled = false - let modal = shallow( { + onCloseWasCalled = false; + modal = mount( { onCloseWasCalled = true}} + childGenerator={() =>
}/>) + }) + + it('matches snapshot', () => { + expect(toJson(modal)).toMatchSnapshot() + }) + + it('closes on modal component close', () => { + let modalComponent = modal.instance() as React.Component //casting to modal didn't work for reasons? + modalComponent.props.onClose() + expect(onCloseWasCalled).toBeTruthy() + }) + + it('closes on closeButtonClick', () => { + let closeButton = modal.find('DefaultCloseButton') + let instanceButton = closeButton.instance() as DefaultCloseButton + instanceButton.props.onClick(); + expect(onCloseWasCalled).toBeTruthy() + }) + }) + + + it('doesnt have a close button if we ask for none', () => { + let onCloseWasCalled = false + let modal = mount( { onCloseWasCalled = true}} - childGenerator={() =>
}/>) - expect(toJson(modal)).toMatchSnapshot() - let modalComponent = modal.instance() as React.Component //casting to modal didn't work for reasons? - modalComponent.props.onClose() - expect(onCloseWasCalled).toBeTruthy() + childGenerator={() =>
} + />) + expect(modal.find('DefaultCloseButton').exists()).toBeFalsy() }) + }) \ No newline at end of file diff --git a/javascripts/src/components/common/Modal.tsx b/javascripts/src/components/common/Modal.tsx index 819915d3..7c04dc1d 100644 --- a/javascripts/src/components/common/Modal.tsx +++ b/javascripts/src/components/common/Modal.tsx @@ -5,6 +5,9 @@ import AriaModal = require('react-aria-modal'); import { VelocityTransitionGroup } from 'velocity-react'; import 'velocity-animate'; import 'velocity-animate/velocity.ui'; +import { DefaultCloseButton } from './DefaultCloseButton'; +import BootstrapWrapper from './BootstrapWrapper'; +import { Row, Column } from './layout'; export interface ModalProps { onClose?: () => void // if you want your modal to close, this needs to set modalActive to false @@ -12,25 +15,44 @@ export interface ModalProps { titleText?: string focusDialog?: boolean dialogStyle?: any + showCloseButton?: boolean childGenerator: () => any } class Modal extends React.Component { static defaultProps = { - dialogStyle: { minWidth: '768px' } + dialogStyle: { minWidth: '768px' }, + showCloseButton: true } render() { - const innerModal = this.props.modalActive ? -
-

{this.props.titleText}

-
-
- {this.props.childGenerator()} -
+ +
+ + +

{this.props.titleText}

+
+ {this.props.showCloseButton ? + +
+ this.props.onClose()} /> +
+
: false + } +
+
+
+
+ {this.props.childGenerator()} +
+
+
: false const modal = @@ -61,7 +83,7 @@ class Modal extends React.Component { } } } - + runOnMount={true}> {innerModal} ; diff --git a/javascripts/src/components/common/ScreenReaderOnlyText.spec.tsx b/javascripts/src/components/common/ScreenReaderOnlyText.spec.tsx new file mode 100644 index 00000000..b79664a0 --- /dev/null +++ b/javascripts/src/components/common/ScreenReaderOnlyText.spec.tsx @@ -0,0 +1,13 @@ +// License: LGPL-3.0-or-later +import * as React from 'react'; +import 'jest'; +import ScreenReaderOnlyText from './ScreenReaderOnlyText' +import toJson from 'enzyme-to-json'; +import { shallow } from 'enzyme'; + +describe('ScreenReaderOnlyText', () => { + it('renders properly', () => { + let text = shallow(Test) + expect(toJson(text)).toMatchSnapshot() + }) +}) \ No newline at end of file diff --git a/javascripts/src/components/common/ScreenReaderOnlyText.tsx b/javascripts/src/components/common/ScreenReaderOnlyText.tsx new file mode 100644 index 00000000..132a71f5 --- /dev/null +++ b/javascripts/src/components/common/ScreenReaderOnlyText.tsx @@ -0,0 +1,29 @@ +// License: LGPL-3.0-or-later +import * as React from 'react'; + +export interface ScreenReaderOnlyTextProps +{ +} + +class ScreenReaderOnlyText extends React.Component { + + + render() { + const style:React.CSSProperties = { + position: 'absolute', + width: '1px', + height: '1px', + padding: 0, + margin: '-1px', + overflow: 'hidden', + clip: 'rect(0,0,0,0)', + border: 0 + } + return {this.props.children} + } +} + +export default ScreenReaderOnlyText; + + + diff --git a/javascripts/src/components/common/__snapshots__/Modal.spec.tsx.snap b/javascripts/src/components/common/__snapshots__/Modal.spec.tsx.snap index 178f305f..9ab548a2 100644 --- a/javascripts/src/components/common/__snapshots__/Modal.spec.tsx.snap +++ b/javascripts/src/components/common/__snapshots__/Modal.spec.tsx.snap @@ -1,68 +1,418 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Modal active modal displays 1`] = ` - - -
-

- title text -

-
-
-
-
- - +
+ + +
+
+ +
+
+ } + > + + +
+
+ +
+ + + + +
+ + +
`; exports[`Modal nothing displayed if inactive 1`] = ` diff --git a/javascripts/src/components/common/__snapshots__/ScreenReaderOnlyText.spec.tsx.snap b/javascripts/src/components/common/__snapshots__/ScreenReaderOnlyText.spec.tsx.snap new file mode 100644 index 00000000..45084801 --- /dev/null +++ b/javascripts/src/components/common/__snapshots__/ScreenReaderOnlyText.spec.tsx.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ScreenReaderOnlyText renders properly 1`] = ` + + Test + +`; diff --git a/javascripts/src/components/common/__snapshots__/layout.spec.tsx.snap b/javascripts/src/components/common/__snapshots__/layout.spec.tsx.snap new file mode 100644 index 00000000..b6c08e75 --- /dev/null +++ b/javascripts/src/components/common/__snapshots__/layout.spec.tsx.snap @@ -0,0 +1,142 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`layout Row renders multiple children properly 1`] = ` + +
+ +
+ + +
+ +
+ +`; + +exports[`layout Row renders single child properly 1`] = ` + +
+ +
+ +
+ +`; + +exports[`layout ThreeColumnFields renders multiple children properly 1`] = ` + + +
+ + +
+ + + + +
+ + + + +
+ + +
+ + +`; + +exports[`layout ThreeColumnFields renders single child properly 1`] = ` + + +
+ + +
+ + +
+ + +`; + +exports[`layout TwoColumnFields renders multiple children properly 1`] = ` + + +
+ + +
+ + + + +
+ + +
+ + +`; + +exports[`layout TwoColumnFields renders single child properly 1`] = ` + + +
+ + +
+ + +
+ + +`; diff --git a/javascripts/src/components/common/layout.spec.tsx b/javascripts/src/components/common/layout.spec.tsx new file mode 100644 index 00000000..ffac94b0 --- /dev/null +++ b/javascripts/src/components/common/layout.spec.tsx @@ -0,0 +1,107 @@ +// License: LGPL-3.0-or-later +import * as React from 'react'; +import 'jest'; +import Modal, { ModalProps } from './Modal' +import { shallow, mount, ReactWrapper } from "enzyme"; +import toJson from "enzyme-to-json"; +import { DefaultCloseButton } from './DefaultCloseButton'; +import { Column, Row, ThreeColumnFields, TwoColumnFields } from './layout'; + +const SimpleCheckerComponent = (props: { className?: string }) => { + return
+} + +describe('layout', () => { + describe('Column', () => { + it('sets proper class without none passed in', () => { + const column = shallow( + + ) + + expect(column.find(SimpleCheckerComponent).props()['className']).toBe('col-sm-12 ') + }) + + it('sets proper class with one passed in', () => { + const column = shallow( + + ) + + expect(column.find(SimpleCheckerComponent).props()['className']) + .toBe('col-lg-1 another_class') + }) + + it('sets proper display name', () => { + const column = shallow( + + ) + expect(Column.displayName).toBe('Column') + }) + }) + + describe('Row', () => { + it('renders single child properly', () => { + const row = mount( + + ) + + expect(toJson(row)).toMatchSnapshot() + }) + + + it('renders multiple children properly', () => { + const row = mount( + + + ) + + expect(toJson(row)).toMatchSnapshot() + }) + + it('has correct display name', () => { + const row = mount( + + ) + + expect(Row.displayName).toBe('Row') + }) + }) + + describe('ThreeColumnFields',() => { + it('renders single child properly', () => { + const fields = mount( + + ) + + expect(toJson(fields)).toMatchSnapshot() + }) + + it('renders multiple children properly', () => { + const fields = mount( + + + + ) + + expect(toJson(fields)).toMatchSnapshot() + }) + }) + + describe('TwoColumnFields',() => { + it('renders single child properly', () => { + const fields = mount( + + ) + + expect(toJson(fields)).toMatchSnapshot() + }) + + it('renders multiple children properly', () => { + const fields = mount( + + + ) + + expect(toJson(fields)).toMatchSnapshot() + }) + }) +}) \ No newline at end of file diff --git a/javascripts/src/components/common/layout.tsx b/javascripts/src/components/common/layout.tsx index 808933da..405aa960 100644 --- a/javascripts/src/components/common/layout.tsx +++ b/javascripts/src/components/common/layout.tsx @@ -3,36 +3,78 @@ import * as React from 'react'; import {observer} from "mobx-react"; import * as _ from 'lodash' -export const TwoColumnFields = observer((props:{children:Array>}) => { - return
+function arrayify(items: Array|T){ + return items instanceof Array ? items : [items] +} + +export const TwoColumnFields: React.StatelessComponent<{}> = (props:{children:Array>|React.ReactElement}) => { + const children = arrayify(props.children) + return { - _.take(props.children, 2).map((i:React.ReactElement) => { - let className = "col-sm-6" - if (_.last(props.children) !== i){ + children.map((i:React.ReactElement) => { + let className = "" + if (_.last(children) !== i){ className += " u-paddingRight--10" } if (i.props['className']){ className += i.props['className'] } - - return React.cloneElement(i, {wrapperClassName: className}) + return + {React.cloneElement(i, {className: className})} + })} -
-}) + +} -export const ThreeColumnFields = observer((props:{children:React.ReactElement[]}) => { - return
+TwoColumnFields.displayName = 'TwoColumnFields' + +export const ThreeColumnFields: React.StatelessComponent<{}> = (props:{children:Array>|React.ReactElement}) => { + const children = arrayify(props.children) + return { - _.take(props.children, 3).map((i:React.ReactElement) => { - let className = "col-sm-4" - if (_.last(props.children) !== i){ + children.map((i:React.ReactElement) => { + let className = "" + if (_.last(children) !== i){ className += " u-paddingRight--10" } if (i.props['className']){ className += i.props['className'] } - - return React.cloneElement(i, {wrapperClassName: className}) + return + {React.cloneElement(i, {className: className})} + })} + +} + +ThreeColumnFields.displayName = 'ThreeColumnFields' + + +export const Row: React.StatelessComponent<{}> = (props:{children:Array>|React.ReactElement}) => { + return
+ {props.children}
-}) \ No newline at end of file +} + +Row.displayName = 'Row' + +type ColumnBreakSize = 'xs'| 'sm'|'md'|'lg' +type ColumnSpan = 1|2|3|4|5|6|7|8|9|10|11|12 + +interface ColumnProps { + children:React.ReactElement + colSpan:ColumnSpan, + breakSize:ColumnBreakSize +} + +export const Column: React.StatelessComponent = (props) => { + let className = `col-${props.breakSize}-${props.colSpan} ` + props.children.props + if (props.children.props.className){ + className += props.children.props['className'] + } + + return React.cloneElement(props.children, {className: className}) +} + +Column.displayName = 'Column' diff --git a/javascripts/src/components/common/svg/CloseButton.tsx b/javascripts/src/components/common/svg/CloseButton.tsx new file mode 100644 index 00000000..d8e23f00 --- /dev/null +++ b/javascripts/src/components/common/svg/CloseButton.tsx @@ -0,0 +1,39 @@ +// License: LGPL-3.0-or-later +import React = require("react"); +interface CloseButtonProps { + backgroundCircleStyle:React.CSSProperties + foregroundCircleStyle:React.CSSProperties +} + +export const CloseButton = (props: CloseButtonProps) => { + return + + + + + +} \ No newline at end of file diff --git a/javascripts/src/components/common/svg/checkbox.tsx b/javascripts/src/components/common/svg/checkbox.tsx new file mode 100644 index 00000000..2f1840b7 --- /dev/null +++ b/javascripts/src/components/common/svg/checkbox.tsx @@ -0,0 +1,6 @@ +// License: LGPL-3.0-or-later +import * as React from 'react'; + +export const Checkbox = (props:React.SVGProps) => { + return +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8cebff3d..58ee6b22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -204,17 +204,17 @@ } }, "@babel/runtime": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.1.tgz", - "integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.3.tgz", + "integrity": "sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==", "requires": { - "regenerator-runtime": "^0.12.0" + "regenerator-runtime": "^0.13.2" }, "dependencies": { "regenerator-runtime": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" } } }, @@ -4974,6 +4974,30 @@ "integrity": "sha512-+T9qBbqe/jXtTjzVddArZExahoPPmt8eq3O1ZuCKZXjBVxf/ciUYNXrIDZJEVgYvpELnv6VlPRCfLzufRxpAag==", "dev": true }, + "@types/color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.0.tgz", + "integrity": "sha512-5qqtNia+m2I0/85+pd2YzAXaTyKO8j+svirO5aN+XaQJ5+eZ8nx0jPtEWZLxCi50xwYsX10xUHetFzfb1WEs4Q==", + "dev": true, + "requires": { + "@types/color-convert": "*" + } + }, + "@types/color-convert": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-1.9.0.tgz", + "integrity": "sha512-OKGEfULrvSL2VRbkl/gnjjgbbF7ycIlpSsX7Nkab4MOWi5XxmgBYvuiQ7lcCFY5cPDz7MUNaKgxte2VRmtr4Fg==", + "dev": true, + "requires": { + "@types/color-name": "*" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, "@types/enzyme": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.1.10.tgz", @@ -5104,6 +5128,15 @@ "@types/react": "*" } }, + "@types/react-transition-group": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-hP7vUaZMVSWKxo133P8U51U6UZ7+pbY+eAQb8+p6SZ2rB1rj3mOTDgTzhhi+R2SCB4S+sWekAAGoxdiZPG0ReQ==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/sinon": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-4.3.3.tgz", @@ -7402,7 +7435,8 @@ "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true }, "clone-deep": { "version": "2.0.2", @@ -7448,21 +7482,29 @@ } }, "color": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.3.tgz", - "integrity": "sha1-S60dDVJJndANvW8IaEQkZ+STlOY=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.0.tgz", + "integrity": "sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg==", "requires": { - "clone": "^1.0.2", - "color-convert": "^1.3.0", - "color-string": "^0.3.0" + "color-convert": "^1.9.1", + "color-string": "^1.5.2" }, "dependencies": { "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { - "color-name": "^1.1.1" + "color-name": "1.1.3" + } + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } } } @@ -7481,6 +7523,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "dev": true, "requires": { "color-name": "^1.0.0" } @@ -7494,6 +7537,28 @@ "color": "^0.11.0", "css-color-names": "0.0.4", "has": "^1.0.1" + }, + "dependencies": { + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "dev": true, + "requires": { + "clone": "^1.0.2", + "color-convert": "^1.3.0", + "color-string": "^0.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + } } }, "colors": { @@ -7853,6 +7918,26 @@ "integrity": "sha1-tQS9BYabOSWd0MXvw12EMXbczEo=", "dev": true }, + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "dev": true, + "requires": { + "clone": "^1.0.2", + "color-convert": "^1.3.0", + "color-string": "^0.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -15239,6 +15324,28 @@ "postcss": "^5.0.4", "postcss-message-helpers": "^2.0.0", "reduce-function-call": "^1.0.1" + }, + "dependencies": { + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "dev": true, + "requires": { + "clone": "^1.0.2", + "color-convert": "^1.3.0", + "color-string": "^0.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + } } }, "postcss-color-hex-alpha": { @@ -16732,11 +16839,11 @@ } }, "react-transition-group": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.5.3.tgz", - "integrity": "sha512-2DGFck6h99kLNr8pOFk+z4Soq3iISydwOFeeEVPjTN6+Y01CmvbWmnN02VuTWyFdnRtIDPe+wy2q6Ui8snBPZg==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", "requires": { - "dom-helpers": "^3.3.1", + "dom-helpers": "^3.4.0", "loose-envify": "^1.4.0", "prop-types": "^15.6.2", "react-lifecycles-compat": "^3.0.4" @@ -16759,11 +16866,6 @@ "object-assign": "^4.1.1", "react-is": "^16.8.1" } - }, - "react-is": { - "version": "16.8.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.1.tgz", - "integrity": "sha512-ioMCzVDWvCvKD8eeT+iukyWrBGrA3DiFYkXfBsVYIRdaREZuBjENG+KjrikavCLasozqRWTwFUagU/O4vPpRMA==" } } }, @@ -17507,6 +17609,21 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, "sinon": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/sinon/-/sinon-5.0.7.tgz", diff --git a/package.json b/package.json index b8fc04b6..a4cb5c71 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "generate-api-js": "rm -rf javascripts/api && npm run get-codegen-cli && npm run generate-openapi && java -jar .bin/swagger-codegen-cli.jar generate -l 'typescript-jquery' -i tmp/openapi.json -o javascripts/api --config 'swagger.json' -t lib/swagger-typescript-jquery" }, "devDependencies": { + "@types/color": "^3.0.0", "@types/enzyme": "^3.1.9", "@types/enzyme-to-json": "^1.5.1", "@types/es6-promise": "^3.3.0", @@ -32,6 +33,7 @@ "@types/react-intl": "^2.3.7", "@types/react-test-renderer": "^16.0.1", "@types/react-text-mask": "^5.4.2", + "@types/react-transition-group": "^2.9.0", "@types/sinon": "^4.3.3", "@types/validator": "^9.4.1", "@types/velocity-animate": "^1.2.33", @@ -87,7 +89,7 @@ "attr-binder": "0.3.1", "aws-sdk": "^2.402.0", "chart.js": "2.1.4", - "color": "0.11.3", + "color": "^3.1.0", "commons.css": "0.1.8", "cookie": "0.3.1", "cropperjs": "1.0.0-beta.2", @@ -138,6 +140,7 @@ "react-dom": "^16.3.1", "react-intl": "^2.4.0", "react-text-mask": "^5.3.0", + "react-transition-group": "^2.9.0", "shuffle-array": "1.0.1", "snabbdom": "0.3.0", "snake-case": "2.1.0",