mirror of
https://github.com/kremalicious/blog.git
synced 2024-12-22 17:23:50 +01:00
gatsby v3 updates
This commit is contained in:
parent
3aa87e0e82
commit
2c171a5ee7
@ -42,9 +42,5 @@ module.exports = {
|
||||
title: '/Uses',
|
||||
link: '/uses'
|
||||
}
|
||||
],
|
||||
darkModeConfig: {
|
||||
classNameDark: 'dark',
|
||||
classNameLight: 'light'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -220,13 +220,6 @@ module.exports = {
|
||||
exclude: ['/archive', '/archive/**/*', '/thanks', '/tags']
|
||||
}
|
||||
},
|
||||
{
|
||||
resolve: 'gatsby-plugin-use-dark-mode',
|
||||
options: {
|
||||
...siteConfig.darkModeConfig,
|
||||
minify: true
|
||||
}
|
||||
},
|
||||
'gatsby-plugin-react-helmet',
|
||||
'gatsby-plugin-catch-links',
|
||||
'gatsby-redirect-from',
|
||||
|
36905
package-lock.json
generated
36905
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
40
package.json
40
package.json
@ -29,32 +29,31 @@
|
||||
"not op_mini all"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ethersproject/providers": "^5.0.23",
|
||||
"@ethersproject/units": "^5.0.10",
|
||||
"@ethersproject/providers": "^5.0.24",
|
||||
"@ethersproject/units": "^5.0.11",
|
||||
"@loadable/component": "^5.14.1",
|
||||
"@web3-react/core": "^6.1.9",
|
||||
"@web3-react/injected-connector": "^6.0.7",
|
||||
"classnames": "^2.2.6",
|
||||
"date-fns": "^2.17.0",
|
||||
"date-fns": "^2.19.0",
|
||||
"dms2dec": "^1.1.0",
|
||||
"ethereum-blockies": "github:MyEtherWallet/blockies",
|
||||
"fast-exif": "^1.0.1",
|
||||
"feather-icons": "^4.28.0",
|
||||
"fraction.js": "^4.0.13",
|
||||
"gatsby": "^3.0.3",
|
||||
"gatsby": "^3.0.4",
|
||||
"gatsby-plugin-catch-links": "^3.0.0",
|
||||
"gatsby-plugin-feed": "^3.0.0",
|
||||
"gatsby-plugin-image": "^1.0.0",
|
||||
"gatsby-plugin-image": "^1.0.1",
|
||||
"gatsby-plugin-lunr": "^1.5.2",
|
||||
"gatsby-plugin-manifest": "^3.0.0",
|
||||
"gatsby-plugin-matomo": "^0.9.0",
|
||||
"gatsby-plugin-meta-redirect": "^1.1.1",
|
||||
"gatsby-plugin-offline": "^4.0.0",
|
||||
"gatsby-plugin-react-helmet": "^4.0.0",
|
||||
"gatsby-plugin-sharp": "^3.0.0",
|
||||
"gatsby-plugin-sharp": "^3.0.1",
|
||||
"gatsby-plugin-sitemap": "^3.0.0",
|
||||
"gatsby-plugin-svgr": "^3.0.0-beta.0",
|
||||
"gatsby-plugin-use-dark-mode": "^1.3.0",
|
||||
"gatsby-plugin-webpack-size": "^1.0.0",
|
||||
"gatsby-redirect-from": "^0.3.0",
|
||||
"gatsby-remark-autolink-headers": "^3.0.0",
|
||||
@ -80,29 +79,28 @@
|
||||
"react-transition-group": "^4.4.1",
|
||||
"remark": "^13.0.0",
|
||||
"remark-react": "^8.0.0",
|
||||
"slugify": "^1.4.7",
|
||||
"use-dark-mode": "^2.3.1"
|
||||
"slugify": "^1.4.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"@testing-library/jest-dom": "^5.11.9",
|
||||
"@testing-library/react": "^11.2.5",
|
||||
"@types/classnames": "^2.2.11",
|
||||
"@types/fs-extra": "^9.0.7",
|
||||
"@types/fs-extra": "^9.0.8",
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/loadable__component": "^5.13.3",
|
||||
"@types/lunr": "^2.3.3",
|
||||
"@types/node": "^14.14.28",
|
||||
"@types/node": "^14.14.34",
|
||||
"@types/node-fetch": "^2.5.8",
|
||||
"@types/react": "^17.0.2",
|
||||
"@types/react-dom": "^17.0.1",
|
||||
"@types/react": "^17.0.3",
|
||||
"@types/react-dom": "^17.0.2",
|
||||
"@types/react-helmet": "^6.1.0",
|
||||
"@types/react-transition-group": "^4.4.0",
|
||||
"@types/shortid": "^0.0.29",
|
||||
"@typescript-eslint/eslint-plugin": "^4.15.2",
|
||||
"@typescript-eslint/parser": "^4.15.2",
|
||||
"@welldone-software/why-did-you-render": "^6.0.5",
|
||||
"eslint": "^7.21.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.17.0",
|
||||
"@typescript-eslint/parser": "^4.17.0",
|
||||
"@welldone-software/why-did-you-render": "^6.1.0",
|
||||
"eslint": "^7.22.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-graphql": "^4.0.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
@ -110,23 +108,23 @@
|
||||
"eslint-plugin-react": "^7.22.0",
|
||||
"eslint-plugin-testing-library": "^3.10.1",
|
||||
"fs-extra": "^9.1.0",
|
||||
"gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.20",
|
||||
"gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.21",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^26.6.3",
|
||||
"markdownlint-cli": "^0.26.0",
|
||||
"node-iptc": "^1.0.5",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"ora": "^5.3.0",
|
||||
"postcss": "^8.2.7",
|
||||
"postcss": "^8.2.8",
|
||||
"prettier": "^2.2.1",
|
||||
"shortid": "^2.2.16",
|
||||
"stylelint": "^13.11.0",
|
||||
"stylelint": "^13.12.0",
|
||||
"stylelint-config-css-modules": "^2.2.0",
|
||||
"stylelint-config-prettier": "^8.0.2",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"stylelint-prettier": "^1.2.0",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.2.2"
|
||||
"typescript": "^4.2.3"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { ReactElement, useState } from 'react'
|
||||
import Map from 'pigeon-maps'
|
||||
import Marker from 'pigeon-marker'
|
||||
import useDarkMode from 'use-dark-mode'
|
||||
import useDarkMode from '../../hooks/useDarkMode'
|
||||
|
||||
const mapbox = (mapboxId: string) => (
|
||||
x: string,
|
||||
@ -23,10 +23,7 @@ export default function ExifMap({
|
||||
}: {
|
||||
gps: { latitude: string; longitude: string }
|
||||
}): ReactElement {
|
||||
const { value } = useDarkMode(false, {
|
||||
classNameDark: 'dark',
|
||||
classNameLight: 'light'
|
||||
})
|
||||
const { value } = useDarkMode()
|
||||
const isDarkMode = value
|
||||
const [zoom, setZoom] = useState(12)
|
||||
|
||||
|
@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
|
||||
import { graphql } from 'gatsby'
|
||||
import { GatsbyImage } from 'gatsby-plugin-image'
|
||||
import { ImageProps } from '../../@types/Image'
|
||||
import * as styles from './Image.module.css'
|
||||
import { image as styleImage, imageTitle } from './Image.module.css'
|
||||
|
||||
export const Image = ({
|
||||
title,
|
||||
@ -12,11 +12,11 @@ export const Image = ({
|
||||
className
|
||||
}: ImageProps): ReactElement => (
|
||||
<figure
|
||||
className={`${styles.image} ${className ? className : ''}`}
|
||||
data-original={original && original.src}
|
||||
className={`${styleImage} ${className ? className : ''}`}
|
||||
data-original={original?.src}
|
||||
>
|
||||
<GatsbyImage backgroundColor="transparent" image={image} alt={alt} />
|
||||
{title && <figcaption className={styles.imageTitle}>{title}</figcaption>}
|
||||
<GatsbyImage backgroundColor="transparent" image={image} alt={alt} />
|
||||
{title && <figcaption className={imageTitle}>{title}</figcaption>}
|
||||
</figure>
|
||||
)
|
||||
|
||||
|
@ -3,7 +3,11 @@ import { Link, graphql } from 'gatsby'
|
||||
import { Image } from '../atoms/Image'
|
||||
import { Post } from '../../@types/Post'
|
||||
import PostTitle from '../templates/Post/Title'
|
||||
import * as styles from './PostTeaser.module.css'
|
||||
import {
|
||||
post as stylePost,
|
||||
empty,
|
||||
title as styleTitle
|
||||
} from './PostTeaser.module.css'
|
||||
|
||||
export const postTeaserQuery = graphql`
|
||||
fragment PostTeaser on MarkdownRemark {
|
||||
@ -42,21 +46,24 @@ export default function PostTeaser({
|
||||
|
||||
return (
|
||||
<Link
|
||||
className={styles.post}
|
||||
className={stylePost}
|
||||
to={slug}
|
||||
onClick={toggleSearch && toggleSearch}
|
||||
>
|
||||
{image ? (
|
||||
<Image image={image} alt={title} />
|
||||
<Image
|
||||
image={(image as any).childImageSharp.gatsbyImageData}
|
||||
alt={title}
|
||||
/>
|
||||
) : (
|
||||
<span className={styles.empty} />
|
||||
<span className={empty} />
|
||||
)}
|
||||
|
||||
<PostTitle
|
||||
title={title}
|
||||
date={hideDate ? null : date}
|
||||
updated={updated}
|
||||
className={styles.title}
|
||||
className={styleTitle}
|
||||
/>
|
||||
</Link>
|
||||
)
|
||||
|
@ -1,19 +1,18 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import useDarkMode from 'use-dark-mode'
|
||||
import * as styles from './ThemeSwitch.module.css'
|
||||
import { themeSwitch, checkbox, label } from './ThemeSwitch.module.css'
|
||||
import Icon from '../atoms/Icon'
|
||||
import { useSiteMetadata } from '../../hooks/use-site-metadata'
|
||||
import useDarkMode from '../../hooks/useDarkMode'
|
||||
|
||||
const ThemeToggleInput = ({
|
||||
isDark,
|
||||
toggleDark
|
||||
}: {
|
||||
isDark: boolean
|
||||
toggleDark(): void
|
||||
toggleDark: () => void
|
||||
}) => (
|
||||
<input
|
||||
onChange={toggleDark}
|
||||
onChange={() => toggleDark()}
|
||||
type="checkbox"
|
||||
name="toggle"
|
||||
value="toggle"
|
||||
@ -22,8 +21,15 @@ const ThemeToggleInput = ({
|
||||
/>
|
||||
)
|
||||
|
||||
const HeadMarkup = ({ themeColor }: { themeColor: string }) => (
|
||||
const HeadMarkup = ({
|
||||
bodyClass,
|
||||
themeColor
|
||||
}: {
|
||||
bodyClass: string
|
||||
themeColor: string
|
||||
}) => (
|
||||
<Helmet>
|
||||
<body className={bodyClass} />
|
||||
<meta name="theme-color" content={themeColor} />
|
||||
<meta
|
||||
name="apple-mobile-web-app-status-bar-style"
|
||||
@ -33,28 +39,30 @@ const HeadMarkup = ({ themeColor }: { themeColor: string }) => (
|
||||
)
|
||||
|
||||
export default function ThemeSwitch(): ReactElement {
|
||||
const { darkModeConfig } = useSiteMetadata()
|
||||
const darkMode = useDarkMode(false, darkModeConfig)
|
||||
const themeColor = darkMode.value ? '#1d2224' : '#e7eef4'
|
||||
const { value, toggle } = useDarkMode()
|
||||
const [themeColor, setThemeColor] = useState('')
|
||||
const [bodyClass, setBodyClass] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
setBodyClass(value ? 'dark' : null)
|
||||
setThemeColor(value ? '#1d2224' : '#e7eef4')
|
||||
}, [value])
|
||||
|
||||
return (
|
||||
<>
|
||||
<HeadMarkup themeColor={themeColor} />
|
||||
<aside className={styles.themeSwitch} title="Toggle Dark Mode">
|
||||
<HeadMarkup themeColor={themeColor} bodyClass={bodyClass} />
|
||||
<aside className={themeSwitch} title="Toggle Dark Mode">
|
||||
<label
|
||||
htmlFor="toggle"
|
||||
className={styles.checkbox}
|
||||
onClick={darkMode.toggle}
|
||||
onKeyPress={darkMode.toggle}
|
||||
className={checkbox}
|
||||
onClick={toggle}
|
||||
onKeyPress={toggle}
|
||||
role="presentation"
|
||||
>
|
||||
<span className={styles.label}>Toggle Dark Mode</span>
|
||||
<ThemeToggleInput
|
||||
isDark={darkMode.value}
|
||||
toggleDark={darkMode.toggle}
|
||||
/>
|
||||
<span className={label}>Toggle Dark Mode</span>
|
||||
<ThemeToggleInput isDark={value} toggleDark={toggle} />
|
||||
<div aria-live="assertive">
|
||||
{darkMode.value ? <Icon name="Sun" /> : <Icon name="Moon" />}
|
||||
{value ? <Icon name="Sun" /> : <Icon name="Moon" />}
|
||||
</div>
|
||||
</label>
|
||||
</aside>
|
||||
|
@ -3,19 +3,19 @@ import { graphql, Link, PageProps } from 'gatsby'
|
||||
import Page from './Page'
|
||||
import { Post, PageContext } from '../../@types/Post'
|
||||
import { Image } from '../atoms/Image'
|
||||
import * as styles from './Photos.module.css'
|
||||
import { photo as stylePhoto, photos as stylePhotos } from './Photos.module.css'
|
||||
import Pagination from '../molecules/Pagination'
|
||||
|
||||
export const PhotoThumb = ({ photo }: { photo: Post }): ReactElement => {
|
||||
const { title, image } = photo.frontmatter
|
||||
const { slug } = photo.fields
|
||||
const { fluid } = image.childImageSharp
|
||||
const { gatsbyImageData } = (image as any).childImageSharp
|
||||
|
||||
return (
|
||||
<article className={styles.photo}>
|
||||
<article className={stylePhoto}>
|
||||
{image && (
|
||||
<Link to={slug}>
|
||||
<Image title={title} fluid={fluid} alt={title} />
|
||||
<Image title={title} image={gatsbyImageData} alt={title} />
|
||||
</Link>
|
||||
)}
|
||||
</article>
|
||||
@ -55,7 +55,7 @@ export default function Photos(props: PhotosPageProps): ReactElement {
|
||||
post={page}
|
||||
pathname={props.location.pathname}
|
||||
>
|
||||
<section className={styles.photos}>
|
||||
<section className={stylePhotos}>
|
||||
{photos.map(({ node }: { node: Post }) => (
|
||||
<PhotoThumb key={node.id} photo={node} />
|
||||
))}
|
||||
|
@ -53,7 +53,7 @@ export default function Post({
|
||||
{image && (
|
||||
<Image
|
||||
className={styles.image}
|
||||
fluid={image.childImageSharp.fluid}
|
||||
image={(image as any).childImageSharp.gatsbyImageData}
|
||||
alt={title}
|
||||
/>
|
||||
)}
|
||||
|
@ -361,4 +361,5 @@ td {
|
||||
|
||||
.gatsby-image-wrapper {
|
||||
max-height: 100vh;
|
||||
display: block;
|
||||
}
|
||||
|
@ -28,10 +28,6 @@ const query = graphql`
|
||||
jsonfeed
|
||||
itemsPerPage
|
||||
repoContentPath
|
||||
darkModeConfig {
|
||||
classNameDark
|
||||
classNameLight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
62
src/hooks/useDarkMode.ts
Normal file
62
src/hooks/useDarkMode.ts
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// adapted from
|
||||
// https://github.com/daveschumaker/react-dark-mode-hook/blob/master/useDarkMode.js
|
||||
//
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
|
||||
const isClient = typeof window === 'object'
|
||||
|
||||
function getDarkMode() {
|
||||
// if (localStorage.getItem('theme') === 'dark') {
|
||||
// return true
|
||||
// } else if (localStorage.getItem('theme') === 'light') {
|
||||
// return false
|
||||
// }
|
||||
|
||||
if (
|
||||
isClient &&
|
||||
window.matchMedia &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export default function useDarkMode(): {
|
||||
value: boolean
|
||||
toggle?: () => void
|
||||
} {
|
||||
const [darkMode, setDarkMode] = useState(getDarkMode)
|
||||
|
||||
function toggleDarkMode() {
|
||||
setDarkMode(!darkMode)
|
||||
}
|
||||
|
||||
//
|
||||
// Handle system theme change events
|
||||
//
|
||||
const handleChange = useCallback(() => {
|
||||
setDarkMode(getDarkMode())
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isClient) return
|
||||
|
||||
const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
|
||||
try {
|
||||
darkModeQuery.addEventListener('change', handleChange)
|
||||
} catch (addEventListenerError) {
|
||||
console.error(addEventListenerError)
|
||||
}
|
||||
|
||||
return () =>
|
||||
window
|
||||
.matchMedia('(prefers-color-scheme: dark)')
|
||||
.removeEventListener('change', handleChange)
|
||||
}, [handleChange])
|
||||
|
||||
return { value: darkMode, toggle: toggleDarkMode }
|
||||
}
|
@ -5,21 +5,21 @@ import SEO from '../components/atoms/SEO'
|
||||
import PostTeaser from '../components/molecules/PostTeaser'
|
||||
import { PhotoThumb } from '../components/templates/Photos'
|
||||
import PostMore from '../components/templates/Post/More'
|
||||
import * as styles from './index.module.css'
|
||||
import { section, articles, articlesLast, photos } from './index.module.css'
|
||||
|
||||
export default function Home({ data }: PageProps): ReactElement {
|
||||
return (
|
||||
<>
|
||||
<SEO />
|
||||
<section className={styles.section}>
|
||||
<div className={styles.articles}>
|
||||
<section className={section}>
|
||||
<div className={articles}>
|
||||
{(data as any).latestArticles.edges
|
||||
.slice(0, 2)
|
||||
.map(({ node }: { node: Post }) => (
|
||||
<PostTeaser key={node.id} post={node} hideDate />
|
||||
))}
|
||||
</div>
|
||||
<div className={`${styles.articles} ${styles.articlesLast}`}>
|
||||
<div className={`${articles} ${articlesLast}`}>
|
||||
{(data as any).latestArticles.edges
|
||||
.slice(2, 8)
|
||||
.map(({ node }: { node: Post }) => (
|
||||
@ -30,8 +30,8 @@ export default function Home({ data }: PageProps): ReactElement {
|
||||
<PostMore to="/archive">All Articles</PostMore>
|
||||
</section>
|
||||
|
||||
<section className={styles.section}>
|
||||
<div className={styles.photos}>
|
||||
<section className={section}>
|
||||
<div className={photos}>
|
||||
{(data as any).latestPhotos.edges.map(({ node }: { node: Post }) => (
|
||||
<PhotoThumb key={node.id} photo={node} />
|
||||
))}
|
||||
|
Loading…
Reference in New Issue
Block a user