To Vanilla!
This commit is contained in:
parent
9987db1956
commit
05e7c2babd
37 changed files with 610 additions and 545 deletions
21
package.json
21
package.json
|
|
@ -16,6 +16,7 @@
|
||||||
"glob": "^7.1.2",
|
"glob": "^7.1.2",
|
||||||
"gray-matter": "^3.1.1",
|
"gray-matter": "^3.1.1",
|
||||||
"js-yaml": "^3.10.0",
|
"js-yaml": "^3.10.0",
|
||||||
|
"prop-types": "^15.6.0",
|
||||||
"react-scripts": "^1.0.10",
|
"react-scripts": "^1.0.10",
|
||||||
"sharp": "^0.18.4",
|
"sharp": "^0.18.4",
|
||||||
"snazzy": "^7.0.0",
|
"snazzy": "^7.0.0",
|
||||||
|
|
@ -23,35 +24,33 @@
|
||||||
"sw-precache": "^5.2.0"
|
"sw-precache": "^5.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@researchgate/react-intersection-observer": "^0.5.0",
|
"@researchgate/react-intersection-observer": "^0.6.0",
|
||||||
"core-js": "^2.5.3",
|
"core-js": "^2.5.3",
|
||||||
"intersection-observer": "^0.5.0",
|
"intersection-observer": "^0.5.0",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"netlify-identity-widget": "^1.2.0",
|
"netlify-identity-widget": "^1.2.0",
|
||||||
"normalize.css": "^7.0.0",
|
"normalize.css": "^7.0.0",
|
||||||
"polished": "^1.7.0",
|
|
||||||
"react": "^16.0.0",
|
"react": "^16.0.0",
|
||||||
"react-dom": "^16.0.0",
|
"react-dom": "^16.0.0",
|
||||||
"react-helmet": "^5.1.3",
|
"react-helmet": "^5.1.3",
|
||||||
"react-markdown": "^2.5.0",
|
"react-markdown": "^2.5.0",
|
||||||
"react-router-dom": "^4.1.1",
|
"react-router-dom": "^4.1.1",
|
||||||
"react-snapshot": "^1.1.0",
|
"react-snapshot": "^1.1.0"
|
||||||
"styled-components": "^2.1.0"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run watch:content & react-scripts start",
|
"start": "npm run watch:content && react-scripts start",
|
||||||
"build": "npm run prepare-content && react-scripts build && react-snapshot && npm run sw",
|
"build":
|
||||||
|
"npm run prepare-content && react-scripts build && react-snapshot && npm run sw",
|
||||||
"parse-content": "node ./functions/parse-content.js",
|
"parse-content": "node ./functions/parse-content.js",
|
||||||
"resize-images": "node ./functions/resize-images.js",
|
"resize-images": "node ./functions/resize-images.js",
|
||||||
"prepare-content": "npm run parse-content & npm run resize-images",
|
"prepare-content": "npm run parse-content && npm run resize-images",
|
||||||
"watch:content": "chokidar 'content/**/**' -c 'npm run prepare-content' --initial",
|
"watch:content":
|
||||||
|
"chokidar 'content/**/**' -c 'npm run prepare-content' --initial",
|
||||||
"sw": "sw-precache --config='sw-precache-config.js'",
|
"sw": "sw-precache --config='sw-precache-config.js'",
|
||||||
"test": "standard | snazzy && react-scripts test --env=jsdom",
|
"test": "standard | snazzy && react-scripts test --env=jsdom",
|
||||||
"eject": "react-scripts eject"
|
"eject": "react-scripts eject"
|
||||||
},
|
},
|
||||||
"reactSnapshot": {
|
"reactSnapshot": {
|
||||||
"include": [
|
"include": ["/404"]
|
||||||
"/404"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
public/images/logo.png
Normal file
BIN
public/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
|
|
@ -14,7 +14,7 @@
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>Netlify CMS + React Starter</title>
|
<title>Netlify CMS + React Starter</title>
|
||||||
|
<!-- Place Google Fonts css here -->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|
|
||||||
18
src/components/BackgroundImage.css
Normal file
18
src/components/BackgroundImage.css
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
74
src/components/BackgroundImage.js
Normal file
74
src/components/BackgroundImage.js
Normal file
|
|
@ -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 (
|
||||||
|
<Observer {...options}>
|
||||||
|
<div
|
||||||
|
className={`BackgroundImage absolute ${className || ''}`}
|
||||||
|
src={this.state.src}
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url(${this.state.src})`,
|
||||||
|
backgroundSize: this.props.contain ? 'contain' : 'cover',
|
||||||
|
opacity: this.props.opacity || 1
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Observer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BackgroundImage.propTypes = {
|
||||||
|
src: PropTypes.string.isRequired
|
||||||
|
}
|
||||||
8
src/components/Content.css
Normal file
8
src/components/Content.css
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
.Content {
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Content--Image {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
|
||||||
import Marked from 'react-markdown'
|
import Marked from 'react-markdown'
|
||||||
|
|
||||||
import { getImageSrc, getImageSrcset } from '../util/getImageUrl'
|
import { getImageSrc, getImageSrcset } from '../util/getImageUrl'
|
||||||
|
import './Content.css'
|
||||||
|
|
||||||
export default ({ source }) => (
|
export default ({ source }) => (
|
||||||
<Content
|
<Marked
|
||||||
|
className='Content'
|
||||||
source={source}
|
source={source}
|
||||||
renderers={{
|
renderers={{
|
||||||
Image: ImageWithSrcset
|
Image: ImageWithSrcset
|
||||||
|
|
@ -12,18 +14,12 @@ export default ({ source }) => (
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
const Image = styled.img`
|
const ImageWithSrcset = ({ nodeKey, src, alt, ...props }) => (
|
||||||
max-width: 100%;
|
<img
|
||||||
height: auto;
|
className='Content--Image'
|
||||||
`
|
|
||||||
const Content = styled(Marked)`
|
|
||||||
white-space: pre-line;
|
|
||||||
`
|
|
||||||
|
|
||||||
const ImageWithSrcset = props => (
|
|
||||||
<Image
|
|
||||||
{...props}
|
{...props}
|
||||||
src={getImageSrc(props.src)}
|
src={getImageSrc(src)}
|
||||||
srcSet={getImageSrcset(props.src)}
|
srcSet={getImageSrcset(src)}
|
||||||
|
alt={alt}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
60
src/components/EnquiryFormSimple.css
Normal file
60
src/components/EnquiryFormSimple.css
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
62
src/components/EnquiryFormSimple.js
Normal file
62
src/components/EnquiryFormSimple.js
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import './EnquiryFormSimple.css'
|
||||||
|
|
||||||
|
export default ({
|
||||||
|
name = 'Simple Form',
|
||||||
|
subject = '', // optional subject of the notification email
|
||||||
|
action = ''
|
||||||
|
}) => (
|
||||||
|
<form
|
||||||
|
className='EnquiryForm'
|
||||||
|
name={name}
|
||||||
|
action={action}
|
||||||
|
data-netlify=''
|
||||||
|
data-netlify-honeypot='_gotcha'
|
||||||
|
>
|
||||||
|
<label className='EnquiryForm--Label'>
|
||||||
|
<input
|
||||||
|
className='EnquiryForm--Input'
|
||||||
|
type='text'
|
||||||
|
placeholder='Name'
|
||||||
|
name='name'
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className='EnquiryForm--Label'>
|
||||||
|
<input
|
||||||
|
className='EnquiryForm--Input'
|
||||||
|
type='phone'
|
||||||
|
placeholder='Phone'
|
||||||
|
name='phone'
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className='EnquiryForm--Label'>
|
||||||
|
<input
|
||||||
|
className='EnquiryForm--Input'
|
||||||
|
type='email'
|
||||||
|
placeholder='Email'
|
||||||
|
name='email'
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className='EnquiryForm--Label'>
|
||||||
|
<textarea
|
||||||
|
className='EnquiryForm--Textarea'
|
||||||
|
placeholder='Message'
|
||||||
|
name='message'
|
||||||
|
rows='10'
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<input type='text' name='_gotcha' style={{ display: 'none' }} />
|
||||||
|
{!!subject && <input type='hidden' name='subject' value={subject} />}
|
||||||
|
<input type='hidden' name='form-name' value={name} />
|
||||||
|
<input
|
||||||
|
className='Button Button--tertiary EnquiryForm--SubmitButton'
|
||||||
|
type='submit'
|
||||||
|
value='Enquire'
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
48
src/components/GithubCorner.css
Normal file
48
src/components/GithubCorner.css
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
.GithubCorner {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.GithubCorner svg {
|
||||||
|
fill: #151513;
|
||||||
|
color: #fff;
|
||||||
|
border: 0;
|
||||||
|
max-width: 12.5vmin;
|
||||||
|
max-height: 12.5vmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GithubCorner .octo-arm {
|
||||||
|
transform-origin: 130px 106px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GithubCorner:hover .octo-arm {
|
||||||
|
animation: octocat-wave 560ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
.GithubCorner:hover .octo-arm {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GithubCorner .octo-arm {
|
||||||
|
animation: octocat-wave 560ms ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes octocat-wave {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: rotate(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
20%,
|
||||||
|
60% {
|
||||||
|
transform: rotate(-25deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
40%,
|
||||||
|
80% {
|
||||||
|
transform: rotate(10deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,59 +1,20 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import './GithubCorner.css'
|
||||||
|
|
||||||
const GithubCorner = styled.a`
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: #151513;
|
|
||||||
color: #fff;
|
|
||||||
border: 0;
|
|
||||||
max-width: 12.5vmin;
|
|
||||||
max-height: 12.5vmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
.octo-arm {
|
|
||||||
transform-origin: 130px 106px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .octo-arm {
|
|
||||||
animation: octocat-wave 560ms ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes octocat-wave {
|
|
||||||
0%, 100% {
|
|
||||||
transform: rotate(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
20%, 60% {
|
|
||||||
transform: rotate(-25deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
40%, 80% {
|
|
||||||
transform: rotate(10deg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width:500px) {
|
|
||||||
&:hover .octo-arm {
|
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.octo-arm {
|
|
||||||
animation: octocat-wave 560ms ease-in-out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
export default ({ url }) => (
|
export default ({ url }) => (
|
||||||
<GithubCorner href={url} aria-label='View source on Github'>
|
<a className='GithubCorner' href={url} aria-label='View source on Github'>
|
||||||
<svg width='80' height='80' viewBox='0 0 250 250' aria-hidden='true'>
|
<svg width='80' height='80' viewBox='0 0 250 250' aria-hidden='true'>
|
||||||
<path d='M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z' />
|
<path d='M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z' />
|
||||||
<path className='octo-arm' d='M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2' fill='currentColor' />
|
<path
|
||||||
<path className='octo-body' d='M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z' fill='currentColor' />
|
className='octo-arm'
|
||||||
|
d='M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2'
|
||||||
|
fill='currentColor'
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
className='octo-body'
|
||||||
|
d='M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z'
|
||||||
|
fill='currentColor'
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</GithubCorner>
|
</a>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
18
src/components/LazyEmbed.css
Normal file
18
src/components/LazyEmbed.css
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
.LazyEmbed {
|
||||||
|
position: relative;
|
||||||
|
padding-bottom: 56.25%;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.LazyEmbed iframe,
|
||||||
|
.LazyEmbed object,
|
||||||
|
.LazyEmbed embed {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
55
src/components/LazyEmbed.js
Normal file
55
src/components/LazyEmbed.js
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import React from 'react'
|
||||||
|
import 'intersection-observer'
|
||||||
|
import Observer from '@researchgate/react-intersection-observer'
|
||||||
|
|
||||||
|
import './LazyEmbed.css'
|
||||||
|
|
||||||
|
class LazyEmbed extends React.Component {
|
||||||
|
static defaultProps = {
|
||||||
|
lazy: true
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
src: null,
|
||||||
|
dataSrc: this.props.src,
|
||||||
|
loaded: !this.props.lazy
|
||||||
|
}
|
||||||
|
|
||||||
|
handleIntersection = e => {
|
||||||
|
if (e.isIntersecting) {
|
||||||
|
this.setState({
|
||||||
|
src: this.state.dataSrc,
|
||||||
|
loaded: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps (nextProps) {
|
||||||
|
if (this.props.src === nextProps.src) return
|
||||||
|
this.setState({
|
||||||
|
src: nextProps.src,
|
||||||
|
dataSrc: nextProps.src
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
let className = this.props.className || ''
|
||||||
|
if (this.state.loaded) className += ' loaded'
|
||||||
|
const options = {
|
||||||
|
onChange: this.handleIntersection,
|
||||||
|
onlyOnce: true,
|
||||||
|
rootMargin: '0% 0% 100%'
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Observer {...options}>
|
||||||
|
<div
|
||||||
|
className={`LazyEmbed ${className}`}
|
||||||
|
dangerouslySetInnerHTML={{ __html: this.state.src }}
|
||||||
|
/>
|
||||||
|
</Observer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LazyEmbed
|
||||||
14
src/components/LazyImage.css
Normal file
14
src/components/LazyImage.css
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
.LazyImage {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
filter: blur(5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.LazyImage.loaded {
|
||||||
|
filter: blur(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.LazyImage:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
@ -1,53 +1,85 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import styled from 'styled-components'
|
|
||||||
import { getImageSrc, getImageSrcset } from '../util/getImageUrl'
|
|
||||||
import 'intersection-observer'
|
import 'intersection-observer'
|
||||||
import Observer from '@researchgate/react-intersection-observer'
|
import Observer from '@researchgate/react-intersection-observer'
|
||||||
|
|
||||||
const Image = styled.img`
|
import { getImageSrc, getImageSrcset } from '../util/getImageUrl'
|
||||||
display: block;
|
import './LazyImage.css'
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 2.5rem;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
class LazyImage extends React.Component {
|
class LazyImage extends React.Component {
|
||||||
|
static defaultProps = {
|
||||||
|
lazy: false,
|
||||||
|
enableSrcset: true,
|
||||||
|
imageSize: '300'
|
||||||
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
src: getImageSrc(this.props.src, '10'),
|
src: getImageSrc(
|
||||||
srcSet: '',
|
this.props.src,
|
||||||
dataSrc: getImageSrc(this.props.src, '300'),
|
this.props.lazy ? '10' : this.props.imageSize
|
||||||
dataSrcSet: getImageSrcset(this.props.src)
|
),
|
||||||
|
srcSet: this.props.lazy ? '' : getImageSrcset(this.props.src),
|
||||||
|
dataSrc: getImageSrc(this.props.src, this.props.imageSize),
|
||||||
|
dataSrcSet: getImageSrcset(this.props.src),
|
||||||
|
loaded: !this.props.lazy
|
||||||
}
|
}
|
||||||
|
|
||||||
handleIntersection = e => {
|
handleIntersection = e => {
|
||||||
if (e.isIntersecting) {
|
if (e.isIntersecting) {
|
||||||
this.setState({
|
const img = new Image()
|
||||||
src: this.state.dataSrc,
|
img.src = this.state.dataSrc
|
||||||
srcSet: this.state.dataSrcSet
|
img.onload = () => {
|
||||||
})
|
this.setState({
|
||||||
|
src: this.state.dataSrc,
|
||||||
|
srcSet: this.state.dataSrcSet,
|
||||||
|
loaded: true
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps (nextProps) {
|
||||||
|
if (this.props.src === nextProps.src) return
|
||||||
|
this.setState({
|
||||||
|
src: getImageSrc(nextProps.src, '10'),
|
||||||
|
srcSet: '',
|
||||||
|
dataSrc: getImageSrc(nextProps.src, '300'),
|
||||||
|
dataSrcSet: getImageSrcset(nextProps.src)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { sizes, alt, className } = this.props
|
const { sizes, lazy, onClick, alt } = this.props
|
||||||
|
let className = this.props.className || ''
|
||||||
|
if (this.state.loaded) className += ' loaded'
|
||||||
const options = {
|
const options = {
|
||||||
onChange: this.handleIntersection,
|
onChange: this.handleIntersection,
|
||||||
onlyOnce: true,
|
onlyOnce: true,
|
||||||
rootMargin: '0% 0% 50%'
|
rootMargin: '0% 0% 100%'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lazy) {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
className={`LazyImage ${className}`}
|
||||||
|
src={this.state.src}
|
||||||
|
srcSet={this.props.enableSrcset ? this.state.srcSet : undefined}
|
||||||
|
sizes={sizes || '100vw'}
|
||||||
|
onClick={onClick}
|
||||||
|
alt={alt}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Observer {...options}>
|
<Observer {...options}>
|
||||||
<Image
|
<img
|
||||||
|
className={`LazyImage ${className}`}
|
||||||
src={this.state.src}
|
src={this.state.src}
|
||||||
srcSet={this.state.srcSet}
|
srcSet={this.props.enableSrcset ? this.state.srcSet : undefined}
|
||||||
sizes={sizes || '100vw'}
|
sizes={sizes || '100vw'}
|
||||||
|
onClick={onClick}
|
||||||
alt={alt}
|
alt={alt}
|
||||||
className={className}
|
|
||||||
/>
|
/>
|
||||||
</Observer>
|
</Observer>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
9
src/components/Logo.css
Normal file
9
src/components/Logo.css
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
.Logo {
|
||||||
|
display: block;
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
height: 2rem;
|
||||||
|
width: 2.5rem;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
import styled from 'styled-components'
|
import React from 'react'
|
||||||
|
|
||||||
export default styled.span`
|
import './Logo.css'
|
||||||
display: block;
|
|
||||||
font-size: 2rem;
|
export default ({ inverted }) => (
|
||||||
padding: 0 1rem;
|
<div
|
||||||
`
|
className='Logo'
|
||||||
|
style={{
|
||||||
|
backgroundImage: 'url(/images/logo.png)'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
|
||||||
6
src/components/Nav.css
Normal file
6
src/components/Nav.css
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
.Nav {
|
||||||
|
background: white;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
@ -1,27 +1,27 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import { Link } from 'react-router-dom'
|
||||||
import { Container, Flex } from './common'
|
|
||||||
import NavLink from './NavLink'
|
|
||||||
import Logo from './Logo'
|
import Logo from './Logo'
|
||||||
|
import NavLink from './NavLink'
|
||||||
|
import './Nav.css'
|
||||||
|
|
||||||
const Nav = styled.div`
|
export default ({ handlePopupOpen }) => (
|
||||||
background: white;
|
<nav className='Nav'>
|
||||||
position: sticky;
|
<div className='Container'>
|
||||||
top: 0;
|
<div className='Flex alignCenter justifyStart'>
|
||||||
z-index: 1;
|
<Link to='/'>
|
||||||
`
|
<Logo />
|
||||||
|
</Link>
|
||||||
export default (props) => (
|
<NavLink to='/' exact>
|
||||||
<Nav>
|
Home
|
||||||
<Container>
|
</NavLink>
|
||||||
<Flex alignCenter>
|
<NavLink to='/about/' exact>
|
||||||
<Logo>
|
About
|
||||||
<span role='img' aria-label='Chili'>🌶</span>
|
</NavLink>
|
||||||
</Logo>
|
<NavLink to='/contact/' exact>
|
||||||
<NavLink to='/' exact>Home</NavLink>
|
Contact
|
||||||
<NavLink to='/about/' exact>About</NavLink>
|
</NavLink>
|
||||||
<NavLink to='/contact/' exact>Contact</NavLink>
|
</div>
|
||||||
</Flex>
|
</div>
|
||||||
</Container>
|
</nav>
|
||||||
</Nav>
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
17
src/components/NavLink.css
Normal file
17
src/components/NavLink.css
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
.NavLink {
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
display: block;
|
||||||
|
font-weight: 400;
|
||||||
|
transition: color 0.2s, border-bottom-color 0.2s;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
border-bottom-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.NavLink:hover,
|
||||||
|
.NavLink:active,
|
||||||
|
.NavLink:focus {
|
||||||
|
color: var(--primary);
|
||||||
|
border-bottom-color: currentColor;
|
||||||
|
}
|
||||||
|
|
@ -1,29 +1,10 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Route, Link } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import styled from 'styled-components'
|
|
||||||
|
|
||||||
import { color } from '../globalStyles'
|
import './NavLink.css'
|
||||||
|
|
||||||
const NavLink = styled.span`
|
export default ({ className, children, ...props }) => (
|
||||||
a {
|
<NavLink {...props} className={`NavLink ${className || ''}`}>
|
||||||
padding: .5rem 1rem;
|
{children}
|
||||||
display: block;
|
</NavLink>
|
||||||
font-weight: 400;
|
|
||||||
transition: color 0.2s, border-bottom-color 0.2s;
|
|
||||||
color: ${props => props.active ? color.primary : 'inherit'};
|
|
||||||
text-decoration: none;
|
|
||||||
border-bottom: 1px solid;
|
|
||||||
border-bottom-color: ${props => props.active ? color.primary : 'transparent'};
|
|
||||||
&:hover, &:active, &:focus {
|
|
||||||
color: ${props => props.active ? color.primary : 'inherit'};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
export default ({ to, exact, match, children }) => (
|
|
||||||
<Route path={to} exact={exact} children={({match}) => (
|
|
||||||
<NavLink active={match}>
|
|
||||||
<Link to={to}>{children}</Link>
|
|
||||||
</NavLink>
|
|
||||||
)} />
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import styled from 'styled-components'
|
|
||||||
import { color } from '../globalStyles'
|
|
||||||
|
|
||||||
export default ({
|
|
||||||
name = 'Simple Form',
|
|
||||||
subject = '', // optional subject of the notification email
|
|
||||||
action = ''
|
|
||||||
}) => (
|
|
||||||
<StyledForm
|
|
||||||
name={name}
|
|
||||||
action={action}
|
|
||||||
data-netlify=''
|
|
||||||
data-netlify-honeypot='_gotcha'
|
|
||||||
>
|
|
||||||
<Label className='Label'>
|
|
||||||
<Input
|
|
||||||
className='Input'
|
|
||||||
type='text'
|
|
||||||
placeholder='Your Name'
|
|
||||||
name='name'
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</Label>
|
|
||||||
<Label className='Label'>
|
|
||||||
<Input
|
|
||||||
className='Input'
|
|
||||||
type='email'
|
|
||||||
placeholder='Your Email'
|
|
||||||
name='email'
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</Label>
|
|
||||||
<Label className='Label'>
|
|
||||||
<Textarea
|
|
||||||
className='Input'
|
|
||||||
placeholder='Message'
|
|
||||||
name='message'
|
|
||||||
rows='10'
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</Label>
|
|
||||||
<Input type='text' name='_gotcha' style={{ display: 'none' }} />
|
|
||||||
{!!subject && <Input type='hidden' name='subject' value={subject} />}
|
|
||||||
<Input type='hidden' name='form-name' value={name} />
|
|
||||||
<Button className='button' type='submit' value='Send' />
|
|
||||||
</StyledForm>
|
|
||||||
)
|
|
||||||
|
|
||||||
const StyledForm = styled.form`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
max-width: 500px;
|
|
||||||
margin: 2.5rem 0;
|
|
||||||
|
|
||||||
& > * + * {
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
const Label = styled.label`
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
`
|
|
||||||
|
|
||||||
const Input = styled.input`
|
|
||||||
font-family: inherit;
|
|
||||||
font-weight: 400;
|
|
||||||
flex-grow: 1;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
border: none;
|
|
||||||
border-bottom: 1px solid #bababa;
|
|
||||||
padding: 0.5em 0;
|
|
||||||
line-height: 1;
|
|
||||||
transition: border-color 0.2s;
|
|
||||||
resize: none;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[disabled] {
|
|
||||||
opacity: 0.4;
|
|
||||||
pointer-events: none;
|
|
||||||
cursor: progress;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
const Textarea = Input.withComponent('textarea')
|
|
||||||
const Button = styled.input`
|
|
||||||
background: ${color.primary};
|
|
||||||
color: white;
|
|
||||||
text-transform: uppercase;
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: 400;
|
|
||||||
letter-spacing: 0.15em;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
display: inline-block;
|
|
||||||
padding: 1rem 2rem;
|
|
||||||
border: none;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[disabled] {
|
|
||||||
opacity: 0.4;
|
|
||||||
pointer-events: none;
|
|
||||||
cursor: progress;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
import styled from 'styled-components'
|
|
||||||
|
|
||||||
export default styled.div`
|
|
||||||
p {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
13
src/components/PageHeader.css
Normal file
13
src/components/PageHeader.css
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
.PageHeader {
|
||||||
|
line-height: 1em;
|
||||||
|
color: var(--primary);
|
||||||
|
background: var(--primary);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PageHeader--Title {
|
||||||
|
}
|
||||||
|
|
||||||
|
.PageHeader--Subtitle {
|
||||||
|
font-weight: 200;
|
||||||
|
}
|
||||||
|
|
@ -1,35 +1,17 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import styled from 'styled-components'
|
|
||||||
|
|
||||||
import { Section, Container, BackgroundImage } from './common'
|
import BackgroundImage from './BackgroundImage'
|
||||||
import { getImageSrc } from '../util/getImageUrl'
|
import './PageHeader.css'
|
||||||
import { color } from '../globalStyles'
|
|
||||||
|
|
||||||
const Header = styled(Section)`
|
|
||||||
line-height: 1em;
|
|
||||||
color: ${color.primary};
|
|
||||||
background: ${color.primary};
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-weight: 200;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const PageHeader = ({ title, subtitle, backgroundImage }) => (
|
const PageHeader = ({ title, subtitle, backgroundImage }) => (
|
||||||
<Header relative>
|
<div className='Section PageHeader relative'>
|
||||||
{backgroundImage && (
|
{backgroundImage && <BackgroundImage src={backgroundImage} opacity={0.5} />}
|
||||||
<BackgroundImage
|
<div className='Container relative'>
|
||||||
image={getImageSrc(backgroundImage, '1200')}
|
<h1 className='PageHeader--Title'>{title}</h1>
|
||||||
opacity={0.5}
|
{subtitle ? <h2 className='PageHeader--Subtitle'>{subtitle}</h2> : ''}
|
||||||
/>
|
</div>
|
||||||
)}
|
</div>
|
||||||
<Container relative>
|
|
||||||
<h1>{title}</h1>
|
|
||||||
{subtitle ? <h2>{subtitle}</h2> : ''}
|
|
||||||
</Container>
|
|
||||||
</Header>
|
|
||||||
)
|
)
|
||||||
|
|
||||||
PageHeader.propTypes = {
|
PageHeader.propTypes = {
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,4 @@
|
||||||
import React, { Component } from 'react'
|
import { Component } from 'react'
|
||||||
import styled from 'styled-components'
|
|
||||||
import { color } from '../globalStyles'
|
|
||||||
|
|
||||||
const Notification = styled.div`
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
text-align: center;
|
|
||||||
background: ${color.primary};
|
|
||||||
color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
min-height: 5rem;
|
|
||||||
transition: transform 0.1s ease-in-out;
|
|
||||||
transform: translateY(${props => (props.message ? '0' : '100%')});
|
|
||||||
`
|
|
||||||
const CloseButton = styled.button.attrs({
|
|
||||||
children: 'x'
|
|
||||||
})`
|
|
||||||
border: none;
|
|
||||||
background: white;
|
|
||||||
color: ${color.primary};
|
|
||||||
border-radius: 100%;
|
|
||||||
width: 2.5rem;
|
|
||||||
height: 2.5rem;
|
|
||||||
position: absolute;
|
|
||||||
right: 1rem;
|
|
||||||
top: 1rem;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
opacity: 0.7;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
export default class ServiceWorkerNotifications extends Component {
|
export default class ServiceWorkerNotifications extends Component {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
|
@ -93,11 +57,6 @@ export default class ServiceWorkerNotifications extends Component {
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
this.props.reloadOnUpdate && this.reloadIfUpdated()
|
this.props.reloadOnUpdate && this.reloadIfUpdated()
|
||||||
return this.state.message ? (
|
return null
|
||||||
<Notification message={this.state.message}>
|
|
||||||
{this.state.message}
|
|
||||||
<CloseButton onClick={this.handleDismiss} />
|
|
||||||
</Notification>
|
|
||||||
) : null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
import styled, { css } from 'styled-components'
|
|
||||||
|
|
||||||
const mixin = {
|
|
||||||
position: css`
|
|
||||||
${props => {
|
|
||||||
if (props.relative) return 'position: relative;'
|
|
||||||
if (props.absolute) return 'position: absolute;'
|
|
||||||
}};
|
|
||||||
`,
|
|
||||||
textAlign: css`
|
|
||||||
${props => {
|
|
||||||
if (props.taCenter) return 'text-align: center;'
|
|
||||||
if (props.taLeft) return 'text-align: left;'
|
|
||||||
if (props.taRight) return 'text-align: right;'
|
|
||||||
}};
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Absolute = styled.div`
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
`
|
|
||||||
|
|
||||||
export const Relative = styled.div`
|
|
||||||
position: relative;
|
|
||||||
z-index: 0;
|
|
||||||
`
|
|
||||||
|
|
||||||
export const Section = styled.section`
|
|
||||||
${mixin.position}
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
padding: ${props => {
|
|
||||||
if (props.thick) return '10rem 0'
|
|
||||||
if (props.thin) return '2.5rem 0'
|
|
||||||
return '5rem 0'
|
|
||||||
}};
|
|
||||||
`
|
|
||||||
|
|
||||||
export const Container = styled.div`
|
|
||||||
${mixin.position}
|
|
||||||
${mixin.textAlign}
|
|
||||||
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 90vw;
|
|
||||||
max-width: ${props => {
|
|
||||||
if (props.skinny) return '888px'
|
|
||||||
if (props.skinnier) return '555px'
|
|
||||||
return '1111px'
|
|
||||||
}};
|
|
||||||
`
|
|
||||||
|
|
||||||
export const Flex = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: ${props => props.column ? 'column' : 'row'};
|
|
||||||
justify-content: ${props => {
|
|
||||||
if (props.justifyCenter) return 'center'
|
|
||||||
if (props.justifyEnd) return 'flex-end'
|
|
||||||
if (props.justifyBetween) return 'space-between'
|
|
||||||
if (props.justifyAround) return 'space-around'
|
|
||||||
return 'flex-start'
|
|
||||||
}};
|
|
||||||
align-items: ${props => {
|
|
||||||
if (props.alignStart) return 'flex-start'
|
|
||||||
if (props.alignEnd) return 'flex-end'
|
|
||||||
if (props.alignStretch) return 'stretch'
|
|
||||||
return 'center'
|
|
||||||
}};
|
|
||||||
height: ${props => props.fill ? '100%' : 'auto'};
|
|
||||||
width: ${props => props.fill ? '100%' : 'auto'};
|
|
||||||
`
|
|
||||||
|
|
||||||
export const BackgroundImage = styled(Absolute)`
|
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
background-image: url(${props => props.image});
|
|
||||||
opacity: ${props => props.opacity || 1};
|
|
||||||
transition: opacity .5s ease;
|
|
||||||
`
|
|
||||||
|
|
@ -142,8 +142,8 @@ pre code:after {
|
||||||
}
|
}
|
||||||
|
|
||||||
.Container {
|
.Container {
|
||||||
max-width: 1467px;
|
max-width: 1111px;
|
||||||
width: 90vw;
|
width: 90%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
.Container.skinny {
|
.Container.skinny {
|
||||||
|
|
|
||||||
2
src/views/About.css
Normal file
2
src/views/About.css
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
.About {
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Helmet from 'react-helmet'
|
import Helmet from 'react-helmet'
|
||||||
|
|
||||||
import Page from '../components/Page'
|
|
||||||
import PageHeader from '../components/PageHeader'
|
import PageHeader from '../components/PageHeader'
|
||||||
import LazyImage from '../components/LazyImage'
|
import LazyImage from '../components/LazyImage'
|
||||||
import { Container, Section } from '../components/common'
|
|
||||||
import Content from '../components/Content.js'
|
import Content from '../components/Content.js'
|
||||||
|
import './About.css'
|
||||||
|
|
||||||
export default ({ page }) => (
|
export default ({ page }) => (
|
||||||
<Page>
|
<div className='About'>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{page.title}</title>
|
<title>{page.title}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
|
@ -17,17 +16,17 @@ export default ({ page }) => (
|
||||||
subtitle={page.subtitle}
|
subtitle={page.subtitle}
|
||||||
backgroundImage={page.featuredImage}
|
backgroundImage={page.featuredImage}
|
||||||
/>
|
/>
|
||||||
<Section thin>
|
<div className='Section thin'>
|
||||||
<Container>
|
<div className='Container'>
|
||||||
<Content source={page.section1} />
|
<Content source={page.section1} />
|
||||||
</Container>
|
</div>
|
||||||
</Section>
|
</div>
|
||||||
<Section thin>
|
<div className='Seciton thin'>
|
||||||
<Container>
|
<div className='Container'>
|
||||||
<Content source={page.section2} />
|
<Content source={page.section2} />
|
||||||
<p>The image below is a {'<LazyImage />'}</p>
|
<p>The image below is a {'<LazyImage />'}</p>
|
||||||
<LazyImage src={page.featuredImage} alt='LazyImage' />
|
<LazyImage src={page.featuredImage} alt='LazyImage' />
|
||||||
</Container>
|
</div>
|
||||||
</Section>
|
</div>
|
||||||
</Page>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
2
src/views/Contact.css
Normal file
2
src/views/Contact.css
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
.Contact {
|
||||||
|
}
|
||||||
|
|
@ -1,31 +1,31 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Helmet from 'react-helmet'
|
import Helmet from 'react-helmet'
|
||||||
import Page from '../components/Page'
|
|
||||||
import PageHeader from '../components/PageHeader'
|
import PageHeader from '../components/PageHeader'
|
||||||
import NetlifyControlledForm from '../components/NetlifyControlledForm'
|
// import NetlifyControlledForm from '../components/NetlifyControlledForm'
|
||||||
import NetlifySimpleForm from '../components/NetlifySimpleForm'
|
import EnquiryFormSimple from '../components/EnquiryFormSimple'
|
||||||
import { Container, Section } from '../components/common'
|
import Content from '../components/Content'
|
||||||
import Marked from 'react-markdown'
|
import './Contact.css'
|
||||||
|
|
||||||
export default ({ page }) => (
|
export default ({ page }) => (
|
||||||
<Page>
|
<div className='Contact'>
|
||||||
<PageHeader title={page.title} subtitle='<Contact />' />
|
<PageHeader title={page.title} subtitle='<Contact />' />
|
||||||
<Section thin>
|
<div className='Section thin'>
|
||||||
<Container>
|
<div className='Container'>
|
||||||
<Marked source={page.content} />
|
<Content source={page.content} />
|
||||||
<br />
|
<br />
|
||||||
<h3>{'<NetlifyControlledForm />'}</h3>
|
<h3>{'<NetlifyControlledForm />'}</h3>
|
||||||
<NetlifyControlledForm name={'Controlled Form'} />
|
{/* <NetlifyControlledForm name={'Controlled Form'} /> */}
|
||||||
<br />
|
<br />
|
||||||
<h3>{'<NetlifySimpleForm />'}</h3>
|
<h3>{'<NetlifySimpleForm />'}</h3>
|
||||||
<NetlifySimpleForm name='Simple Form' />
|
<EnquiryFormSimple name='Simple Form' />
|
||||||
<em>Note: these will only work when deployed on Netlify</em>
|
<em>Note: these will only work when deployed on Netlify</em>
|
||||||
<br />
|
<br />
|
||||||
<em>Also, they are active and I will receive submissions</em> 😉
|
<em>Also, they are active and I will receive submissions</em> 😉
|
||||||
</Container>
|
</div>
|
||||||
</Section>
|
</div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{page.title}</title>
|
<title>{page.title}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
</Page>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
2
src/views/Home.css
Normal file
2
src/views/Home.css
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
.Home {
|
||||||
|
}
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Helmet from 'react-helmet'
|
import Helmet from 'react-helmet'
|
||||||
import Page from '../components/Page'
|
|
||||||
import { Container, Section } from '../components/common'
|
|
||||||
import Content from '../components/Content'
|
import Content from '../components/Content'
|
||||||
import PageHeader from '../components/PageHeader'
|
import PageHeader from '../components/PageHeader'
|
||||||
|
import './Home.css'
|
||||||
|
|
||||||
export default ({ page }) => {
|
export default ({ page }) => {
|
||||||
const { title, subtitle } = page
|
const { title, subtitle } = page
|
||||||
return (
|
return (
|
||||||
<Page>
|
<main className='Home'>
|
||||||
<PageHeader title={title} subtitle={subtitle} />
|
<PageHeader title={title} subtitle={subtitle} />
|
||||||
<Section thin>
|
<div className='Section thin'>
|
||||||
<Container>
|
<div className='Container'>
|
||||||
<Content source={page.content} />
|
<Content source={page.content} />
|
||||||
</Container>
|
</div>
|
||||||
</Section>
|
</div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
</Page>
|
</main>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
src/views/NoMatch.css
Normal file
5
src/views/NoMatch.css
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
.body--NoMatch .React-Wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
@ -1,19 +1,24 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Helmet from 'react-helmet'
|
import Helmet from 'react-helmet'
|
||||||
import Page from '../components/Page'
|
|
||||||
import PageHeader from '../components/PageHeader'
|
|
||||||
import { Section, Container } from '../components/common'
|
|
||||||
|
|
||||||
export default () => (
|
import './NoMatch.css'
|
||||||
<Page>
|
|
||||||
<PageHeader title='404' subtitle='<NoMatch />' />
|
export default ({ siteUrl }) => (
|
||||||
<Section>
|
<div className='Page'>
|
||||||
<Container taCenter>
|
<section className='Section thick'>
|
||||||
<h3>404 – Page Not Found</h3>
|
<div className='Container taCenter'>
|
||||||
</Container>
|
<h1>404 - Page Not Found</h1>
|
||||||
</Section>
|
<p>
|
||||||
|
We can't find the page you are looking for!<br />Head back to{' '}
|
||||||
|
<a href={siteUrl}>
|
||||||
|
{siteUrl.replace(/(^https?:\/\/)/, '').replace(/\/$/, '')}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>404 – Page Not Found</title>
|
<title>404 – Page Not Found</title>
|
||||||
|
<body className='body--NoMatch' />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
</Page>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
67
yarn.lock
67
yarn.lock
|
|
@ -54,9 +54,9 @@
|
||||||
lodash "^4.2.0"
|
lodash "^4.2.0"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@researchgate/react-intersection-observer@^0.5.0":
|
"@researchgate/react-intersection-observer@^0.6.0":
|
||||||
version "0.5.0"
|
version "0.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/@researchgate/react-intersection-observer/-/react-intersection-observer-0.5.0.tgz#c83341fe2d86467816373e9141c37b71b90798d9"
|
resolved "https://registry.yarnpkg.com/@researchgate/react-intersection-observer/-/react-intersection-observer-0.6.0.tgz#505f20b62c8941a035442b61ac448870afb5d8a2"
|
||||||
dependencies:
|
dependencies:
|
||||||
invariant "^2.2.2"
|
invariant "^2.2.2"
|
||||||
prop-types "^15.6.0"
|
prop-types "^15.6.0"
|
||||||
|
|
@ -1260,13 +1260,6 @@ buffer@^4.3.0:
|
||||||
ieee754 "^1.1.4"
|
ieee754 "^1.1.4"
|
||||||
isarray "^1.0.0"
|
isarray "^1.0.0"
|
||||||
|
|
||||||
buffer@^5.0.3:
|
|
||||||
version "5.0.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.8.tgz#84daa52e7cf2fa8ce4195bc5cf0f7809e0930b24"
|
|
||||||
dependencies:
|
|
||||||
base64-js "^1.0.2"
|
|
||||||
ieee754 "^1.1.4"
|
|
||||||
|
|
||||||
builtin-modules@^1.0.0, builtin-modules@^1.1.1:
|
builtin-modules@^1.0.0, builtin-modules@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
|
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
|
||||||
|
|
@ -1776,10 +1769,6 @@ crypto-browserify@^3.11.0:
|
||||||
randombytes "^2.0.0"
|
randombytes "^2.0.0"
|
||||||
randomfill "^1.0.3"
|
randomfill "^1.0.3"
|
||||||
|
|
||||||
css-color-keywords@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
|
|
||||||
|
|
||||||
css-color-names@0.0.4:
|
css-color-names@0.0.4:
|
||||||
version "0.0.4"
|
version "0.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
|
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
|
||||||
|
|
@ -1820,14 +1809,6 @@ css-selector-tokenizer@^0.7.0:
|
||||||
fastparse "^1.1.1"
|
fastparse "^1.1.1"
|
||||||
regexpu-core "^1.0.0"
|
regexpu-core "^1.0.0"
|
||||||
|
|
||||||
css-to-react-native@^2.0.3:
|
|
||||||
version "2.0.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.0.4.tgz#cf4cc407558b3474d4ba8be1a2cd3b6ce713101b"
|
|
||||||
dependencies:
|
|
||||||
css-color-keywords "^1.0.0"
|
|
||||||
fbjs "^0.8.5"
|
|
||||||
postcss-value-parser "^3.3.0"
|
|
||||||
|
|
||||||
css-what@2.1:
|
css-what@2.1:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
|
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
|
||||||
|
|
@ -2844,7 +2825,7 @@ fb-watchman@^2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
bser "^2.0.0"
|
bser "^2.0.0"
|
||||||
|
|
||||||
fbjs@^0.8.16, fbjs@^0.8.5, fbjs@^0.8.9:
|
fbjs@^0.8.16:
|
||||||
version "0.8.16"
|
version "0.8.16"
|
||||||
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db"
|
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -3380,10 +3361,6 @@ hoek@4.x.x:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d"
|
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d"
|
||||||
|
|
||||||
hoist-non-react-statics@^1.2.0:
|
|
||||||
version "1.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
|
|
||||||
|
|
||||||
hoist-non-react-statics@^2.3.0:
|
hoist-non-react-statics@^2.3.0:
|
||||||
version "2.3.1"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0"
|
||||||
|
|
@ -3733,10 +3710,6 @@ is-fullwidth-code-point@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
||||||
|
|
||||||
is-function@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5"
|
|
||||||
|
|
||||||
is-glob@^2.0.0, is-glob@^2.0.1:
|
is-glob@^2.0.0, is-glob@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
|
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
|
||||||
|
|
@ -3802,12 +3775,6 @@ is-plain-obj@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
|
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
|
||||||
|
|
||||||
is-plain-object@^2.0.1:
|
|
||||||
version "2.0.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
|
|
||||||
dependencies:
|
|
||||||
isobject "^3.0.1"
|
|
||||||
|
|
||||||
is-posix-bracket@^0.1.0:
|
is-posix-bracket@^0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
|
resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
|
||||||
|
|
@ -3896,10 +3863,6 @@ isobject@^2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
isarray "1.0.0"
|
isarray "1.0.0"
|
||||||
|
|
||||||
isobject@^3.0.1:
|
|
||||||
version "3.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
|
|
||||||
|
|
||||||
isomorphic-fetch@^2.1.1:
|
isomorphic-fetch@^2.1.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
|
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
|
||||||
|
|
@ -5238,10 +5201,6 @@ pluralize@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
|
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
|
||||||
|
|
||||||
polished@^1.7.0:
|
|
||||||
version "1.9.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/polished/-/polished-1.9.0.tgz#76d277d6610dbcb85477dbba1bd1aa8e642741b6"
|
|
||||||
|
|
||||||
portfinder@^1.0.9:
|
portfinder@^1.0.9:
|
||||||
version "1.0.13"
|
version "1.0.13"
|
||||||
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
|
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
|
||||||
|
|
@ -6730,24 +6689,6 @@ style-loader@0.19.0:
|
||||||
loader-utils "^1.0.2"
|
loader-utils "^1.0.2"
|
||||||
schema-utils "^0.3.0"
|
schema-utils "^0.3.0"
|
||||||
|
|
||||||
styled-components@^2.1.0:
|
|
||||||
version "2.2.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.2.3.tgz#154575c269880c840f903f580287dab155cf684c"
|
|
||||||
dependencies:
|
|
||||||
buffer "^5.0.3"
|
|
||||||
css-to-react-native "^2.0.3"
|
|
||||||
fbjs "^0.8.9"
|
|
||||||
hoist-non-react-statics "^1.2.0"
|
|
||||||
is-function "^1.0.1"
|
|
||||||
is-plain-object "^2.0.1"
|
|
||||||
prop-types "^15.5.4"
|
|
||||||
stylis "3.x"
|
|
||||||
supports-color "^3.2.3"
|
|
||||||
|
|
||||||
stylis@3.x:
|
|
||||||
version "3.4.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.4.3.tgz#875bd0db3db37bb6de08f89275fc38ee2e32ee75"
|
|
||||||
|
|
||||||
supports-color@^2.0.0:
|
supports-color@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue