diff --git a/package.json b/package.json index 09be3b4..be5a9e9 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "glob": "^7.1.2", "gray-matter": "^3.1.1", "js-yaml": "^3.10.0", + "prop-types": "^15.6.0", "react-scripts": "^1.0.10", "sharp": "^0.18.4", "snazzy": "^7.0.0", @@ -23,35 +24,33 @@ "sw-precache": "^5.2.0" }, "dependencies": { - "@researchgate/react-intersection-observer": "^0.5.0", + "@researchgate/react-intersection-observer": "^0.6.0", "core-js": "^2.5.3", "intersection-observer": "^0.5.0", "lodash": "^4.17.4", "netlify-identity-widget": "^1.2.0", "normalize.css": "^7.0.0", - "polished": "^1.7.0", "react": "^16.0.0", "react-dom": "^16.0.0", "react-helmet": "^5.1.3", "react-markdown": "^2.5.0", "react-router-dom": "^4.1.1", - "react-snapshot": "^1.1.0", - "styled-components": "^2.1.0" + "react-snapshot": "^1.1.0" }, "scripts": { - "start": "npm run watch:content & react-scripts start", - "build": "npm run prepare-content && react-scripts build && react-snapshot && npm run sw", + "start": "npm run watch:content && react-scripts start", + "build": + "npm run prepare-content && react-scripts build && react-snapshot && npm run sw", "parse-content": "node ./functions/parse-content.js", "resize-images": "node ./functions/resize-images.js", - "prepare-content": "npm run parse-content & npm run resize-images", - "watch:content": "chokidar 'content/**/**' -c 'npm run prepare-content' --initial", + "prepare-content": "npm run parse-content && npm run resize-images", + "watch:content": + "chokidar 'content/**/**' -c 'npm run prepare-content' --initial", "sw": "sw-precache --config='sw-precache-config.js'", "test": "standard | snazzy && react-scripts test --env=jsdom", "eject": "react-scripts eject" }, "reactSnapshot": { - "include": [ - "/404" - ] + "include": ["/404"] } } diff --git a/public/images/logo.png b/public/images/logo.png new file mode 100644 index 0000000..820aca9 Binary files /dev/null and b/public/images/logo.png differ diff --git a/public/index.html b/public/index.html index 061420a..77be9f4 100644 --- a/public/index.html +++ b/public/index.html @@ -14,7 +14,7 @@ Learn how to configure a non-root public URL by running `npm run build`. --> Netlify CMS + React Starter - +
diff --git a/src/components/BackgroundImage.css b/src/components/BackgroundImage.css new file mode 100644 index 0000000..59d1da2 --- /dev/null +++ b/src/components/BackgroundImage.css @@ -0,0 +1,18 @@ +.BackgroundImage { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background-position: center; + transition: opacity 0.5s ease; + overflow: hidden; +} + +.BackgroundImage-lazy { + filter: blur(5px); +} + +.BackgroundImage-lazy-loaded { + filter: blur(0); +} diff --git a/src/components/BackgroundImage.js b/src/components/BackgroundImage.js new file mode 100644 index 0000000..25f4130 --- /dev/null +++ b/src/components/BackgroundImage.js @@ -0,0 +1,74 @@ +import React from 'react' +import PropTypes from 'prop-types' +import 'intersection-observer' +import Observer from '@researchgate/react-intersection-observer' + +import './BackgroundImage.css' +import { getImageSrc } from '../util/getImageUrl' + +export default class BackgroundImage extends React.Component { + static defaultProps = { + lazy: false, + src: '' + } + + state = { + src: + this.props.src.indexOf('http') === 0 + ? '' + : getImageSrc(this.props.src, this.props.lazy ? 10 : 1800), + dataSrc: getImageSrc(this.props.src, 1800), + loaded: false + } + + handleIntersection = e => { + if (e.isIntersecting) { + const img = new Image() + img.src = this.state.dataSrc + img.onload = () => { + this.setState({ + src: this.state.dataSrc, + loaded: true + }) + } + } + } + + componentWillReceiveProps (nextProps) { + if (this.props.src === nextProps.src) return + + this.setState({ + src: getImageSrc(nextProps.src, nextProps.lazy ? 10 : 1800), + dataSrc: getImageSrc(nextProps.src, 1800) + }) + } + + render () { + let className = this.props.className || '' + if (this.state.loaded) className += ' BackgroundImage-lazy-loaded' + if (this.props.lazy) className += ' BackgroundImage-lazy' + const options = { + onChange: this.handleIntersection, + onlyOnce: true, + rootMargin: '0% 0% 100%' + } + + return ( + +
+ + ) + } +} + +BackgroundImage.propTypes = { + src: PropTypes.string.isRequired +} diff --git a/src/components/Content.css b/src/components/Content.css new file mode 100644 index 0000000..07463a3 --- /dev/null +++ b/src/components/Content.css @@ -0,0 +1,8 @@ +.Content { + white-space: pre-line; +} + +.Content--Image { + max-width: 100%; + height: auto; +} diff --git a/src/components/Content.js b/src/components/Content.js index d03d5a0..9f70e04 100644 --- a/src/components/Content.js +++ b/src/components/Content.js @@ -1,10 +1,12 @@ import React from 'react' -import styled from 'styled-components' import Marked from 'react-markdown' + import { getImageSrc, getImageSrcset } from '../util/getImageUrl' +import './Content.css' export default ({ source }) => ( - ( /> ) -const Image = styled.img` - max-width: 100%; - height: auto; -` -const Content = styled(Marked)` - white-space: pre-line; -` - -const ImageWithSrcset = props => ( - ( + {alt} ) diff --git a/src/components/EnquiryFormSimple.css b/src/components/EnquiryFormSimple.css new file mode 100644 index 0000000..6ae5d2f --- /dev/null +++ b/src/components/EnquiryFormSimple.css @@ -0,0 +1,60 @@ +.EnquiryForm { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + max-width: 500px; + margin: 2.5rem 0; +} + +.EnquiryForm > * + * { + margin-top: 1.5rem; +} + +.EnquiryForm--Label { + width: 100%; + display: flex; + align-items: center; + flex-wrap: wrap; +} + +.EnquiryForm--Input, +.EnquiryForm--Textarea { + font-family: inherit; + font-weight: 400; + flex-grow: 1; + box-sizing: border-box; + display: block; + margin: 0; + border: none; + padding: 1em; + line-height: 1; + transition: border-color 0.2s; + resize: none; + background: var(--lightGrey); + border-radius: 0; +} + +.EnquiryForm--Input:-webkit-autofill { + -webkit-box-shadow: 0 0 0 1000px var(--lightGrey) inset !important; +} + +.EnquiryForm--Input:focus { + outline: none; + border-color: black; +} + +.EnquiryForm--Input[disabled] { + opacity: 0.4; + pointer-events: none; + cursor: progress; +} + +.EnquiryForm--Input::placeholder { + text-transform: uppercase; +} + +.EnquiryForm--SubmitButton { + width: 90%; + margin: 2rem auto 0; +} diff --git a/src/components/EnquiryFormSimple.js b/src/components/EnquiryFormSimple.js new file mode 100644 index 0000000..401db84 --- /dev/null +++ b/src/components/EnquiryFormSimple.js @@ -0,0 +1,62 @@ +import React from 'react' + +import './EnquiryFormSimple.css' + +export default ({ + name = 'Simple Form', + subject = '', // optional subject of the notification email + action = '' +}) => ( +
+ + + +