diff --git a/package-lock.json b/package-lock.json index b13ca14..fbe3535 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11309,8 +11309,7 @@ "lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=", - "dev": true + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" }, "lodash.uniq": { "version": "4.5.0", @@ -14457,9 +14456,9 @@ } }, "react": { - "version": "16.11.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.11.0.tgz", - "integrity": "sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g==", + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz", + "integrity": "sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -14638,14 +14637,14 @@ } }, "react-dom": { - "version": "16.11.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.11.0.tgz", - "integrity": "sha512-nrRyIUE1e7j8PaXSPtyRKtz+2y9ubW/ghNgqKFHHAHaeP0fpF5uXR+sq8IMRHC+ZUxw7W9NyCDTBtwWxvkb0iA==", + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.12.0.tgz", + "integrity": "sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.17.0" + "scheduler": "^0.18.0" } }, "react-draggable": { @@ -18264,9 +18263,9 @@ } }, "scheduler": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.17.0.tgz", - "integrity": "sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", + "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -21103,6 +21102,18 @@ "unist-util-stringify-position": "^2.0.0" } }, + "video-react": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/video-react/-/video-react-0.14.1.tgz", + "integrity": "sha512-R5ClJo58iJcQLS+bGNmuAMc/fx9/xcJ6oLrAlbuu7MGI49Jh7b7o79aUdQMZvzuynT1NvhVmD4N/fTOEmWNDlg==", + "requires": { + "@babel/runtime": "^7.4.5", + "classnames": "^2.2.6", + "lodash.throttle": "^4.1.1", + "prop-types": "^15.7.2", + "redux": "^4.0.1" + } + }, "vm-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", diff --git a/package.json b/package.json index ce87261..a056b37 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,9 @@ "material-design-icons": "^3.0.1", "mixpanel-browser": "2.30.1", "node-sass": "^4.13.1", - "react": "16.11.0", + "react": "^16.12.0", "react-cookie-banner": "^4.0.0", - "react-dom": "16.11.0", + "react-dom": "^16.12.0", "react-loader-spinner": "^3.1.5", "react-magic-slider-dots": "1.1.3", "react-mailchimp-subscribe": "2.1.0", @@ -40,7 +40,8 @@ "react-typing-animation": "1.6.2", "react-typing-effect": "2.0.2", "redux": "4.0.4", - "slick-carousel": "1.8.1" + "slick-carousel": "1.8.1", + "video-react": "^0.14.1" }, "devDependencies": { "@babel/core": "7.7.2", diff --git a/public/index.html b/public/index.html index e74cbe7..29e9a12 100644 --- a/public/index.html +++ b/public/index.html @@ -5,6 +5,10 @@ + + + + diff --git a/src/components/elements/Video/Video.js b/src/components/elements/Video/Video.js new file mode 100644 index 0000000..b04323b --- /dev/null +++ b/src/components/elements/Video/Video.js @@ -0,0 +1,88 @@ +// @flow +import React, { Component } from 'react'; +import { toInteger } from 'lodash'; +import { Player } from 'video-react'; +import { Mixpanel } from '../../../Mixpanel'; +import { Icon } from '..'; + +import './Video.scss'; + +type Props = { + videoId: string, + id: string, + header: string, +}; + +type State = { + videoClosed: boolean, +}; + +export default class Video extends Component { + constructor(props) { + super(props); + this.state = { + videoTimerSet: false, + videoClosed: false, + }; + } + + componentDidMount() { + // this.refs.player.subscribeToStateChange(this.handleVideoState.bind(this)); + this.handleVideoState = this.handleVideoState.bind(this); + } + + render() { + const { videoId, header, id } = this.props; + + const { videoClosed } = this.state; + + return ( +
+ {!videoClosed && ( +
+
+
{header}
+ +
+ { + // + } + + + +
+ )} +
+ ); + } + + handleVideoClose = () => { + const { videoClosed } = this.state; + const { id } = this.props; + + Mixpanel.track(`${id} / Video / ${videoClosed}`); + + this.setState({ + videoClosed: true, + }); + }; + + handleVideoState = state => { + const { videoTimerSet } = this.state; + const { id } = this.props; + + if (toInteger(state.currentTime) === 30 && !videoTimerSet) { + this.setState({ videoTimerSet: true }); + Mixpanel.track(`${id} / Video / ${toInteger(state.currentTime)}`); + } + }; +} diff --git a/src/components/elements/Video/Video.scss b/src/components/elements/Video/Video.scss new file mode 100644 index 0000000..fa11d89 --- /dev/null +++ b/src/components/elements/Video/Video.scss @@ -0,0 +1,47 @@ +@import '../../../styles/main'; + +.video { + @include margin(top bottom, 4); + @include margin(left right, 2); + max-width: 560px; + + &__header { + @include row; + align-items: center; + justify-content: space-between; + + &_caption { + @include margin(left, 0); + @include caption-left; + } + + // Icon overrides + .icon-container .button { + @include margin(right, reset); + color: $grey; + } + } +} + +// Video Player + +:global { + .video-react { + @include modal-elevation; + border-radius: 3px; + display: block; + margin: 100px auto; + max-width: 520px; + outline: none !important; + padding-top: 30% !important; + width: 50% !important; + } + .video-react-video { + outline: none !important; + } + .video-react-big-play-button { + background-color: $primary !important; + border: 0 !important; + outline: none !important; + } +} diff --git a/src/components/elements/index.js b/src/components/elements/index.js index 4cb126d..267154a 100644 --- a/src/components/elements/index.js +++ b/src/components/elements/index.js @@ -11,3 +11,4 @@ export { default as Modal } from './Modal/Modal.js'; export { default as OnboardingCard } from './OnboardingCard/OnboardingCard.js'; export { default as Tag } from './Tag/Tag'; export { default as Toggle } from './Toggle/Toggle'; +export { default as Video } from './Video/Video'; diff --git a/src/styles/main.scss b/src/styles/main.scss index 3cc1bee..c3f26e7 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -6,6 +6,9 @@ // import material icons @import url('https://fonts.googleapis.com/css?family=Roboto:400,700|Material+Icons'); +// import react-video styles +@import '~video-react/styles/scss/video-react'; + // Atoms @import 'atoms/align'; diff --git a/stories/video.stories.js b/stories/video.stories.js new file mode 100644 index 0000000..14c9e22 --- /dev/null +++ b/stories/video.stories.js @@ -0,0 +1,17 @@ +import React from "react"; + +import { storiesOf } from "@storybook/react"; +// import { action } from "@storybook/addon-actions"; +// import { linkTo } from "@storybook/addon-links"; +// import { Welcome } from "@storybook/react/demo"; +import { Video } from '../src/components/elements' + +storiesOf("Elements/Video", module) + .add("Video", () => ( +