[site/components][f]: tooltip animation
This commit is contained in:
parent
5589b2244d
commit
1a13aed153
|
|
@ -1,115 +1,36 @@
|
||||||
import ReactDOM from 'react-dom'
|
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useState, useEffect, useRef, Fragment } from 'react'
|
|
||||||
import {
|
|
||||||
arrow,
|
|
||||||
autoPlacement,
|
|
||||||
autoUpdate,
|
|
||||||
FloatingPortal,
|
|
||||||
offset,
|
|
||||||
shift,
|
|
||||||
useDismiss,
|
|
||||||
useFloating,
|
|
||||||
useHover,
|
|
||||||
useInteractions,
|
|
||||||
useRole,
|
|
||||||
} from '@floating-ui/react-dom-interactions'
|
|
||||||
|
|
||||||
|
import { Tooltip } from './Tooltip';
|
||||||
import siteConfig from '../config/siteConfig.js'
|
import siteConfig from '../config/siteConfig.js'
|
||||||
import documentExtract from '../utils/documentExtract'
|
|
||||||
import { Tooltip } from './Tooltip'
|
|
||||||
|
|
||||||
|
|
||||||
// TODO cancel request on mouseleave when it hasn't been fulfilled yet
|
|
||||||
|
|
||||||
export const Anchor = (props) => {
|
export const Anchor = (props) => {
|
||||||
const { href } = props;
|
const { href } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const arrowRef = useRef(null);
|
|
||||||
|
|
||||||
const [ showTooltip, setShowTooltip ] = useState(false);
|
const absoluteContentPath = (href) => {
|
||||||
const [ preview, setPreview ] = useState("");
|
// return content path only if it points to a local file (href path is relative)
|
||||||
const [ previewLoaded, setPreviewLoaded ] = useState(false);
|
if (
|
||||||
|
href &&
|
||||||
const {
|
href.indexOf("http:") !== 0 &&
|
||||||
x,
|
href.indexOf("https:") !== 0
|
||||||
y,
|
) {
|
||||||
reference,
|
const currentPageContentPath = [siteConfig.rawContentBaseUrl, router.asPath].join("");
|
||||||
floating,
|
const hrefContentPath = new URL(href, currentPageContentPath).href;
|
||||||
placement,
|
// excluding notes and claims
|
||||||
strategy,
|
if (!hrefContentPath.includes("notes") && !hrefContentPath.includes("claims")) {
|
||||||
context,
|
return hrefContentPath;
|
||||||
middlewareData: { arrow: { x: arrowX, y: arrowY } = {}}
|
}
|
||||||
} = useFloating({
|
|
||||||
open: showTooltip,
|
|
||||||
onOpenChange: setShowTooltip,
|
|
||||||
whileElementsMounted: autoUpdate,
|
|
||||||
middleware: [
|
|
||||||
offset(5),
|
|
||||||
autoPlacement({ padding: 5 }),
|
|
||||||
shift({ padding: 5 }),
|
|
||||||
arrow({ element: arrowRef, padding: 4 })
|
|
||||||
]
|
|
||||||
});
|
|
||||||
const { getReferenceProps, getFloatingProps } = useInteractions([
|
|
||||||
useHover(context, { delay: 100 }),
|
|
||||||
useRole(context, { role: 'tooltip' }),
|
|
||||||
useDismiss(context, { ancestorScroll: true })
|
|
||||||
]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (showTooltip) {
|
|
||||||
fetchPreview();
|
|
||||||
}
|
}
|
||||||
}, [showTooltip])
|
|
||||||
|
|
||||||
const fetchPreview = async () => {
|
|
||||||
setPreviewLoaded(false);
|
|
||||||
const path = new URL(props.href, document.baseURI).pathname;
|
|
||||||
const rawContentPath = [siteConfig.rawContentBaseUrl, path].join("")
|
|
||||||
const response = await fetch(rawContentPath);
|
|
||||||
if (response.status !== 200) {
|
|
||||||
// TODO
|
|
||||||
console.log(`Looks like there was a problem. Status Code: ${response.status}`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const md = await response.text();
|
|
||||||
const extract = documentExtract(md);
|
|
||||||
|
|
||||||
setPreview(extract);
|
|
||||||
setPreviewLoaded(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (absoluteContentPath(props.href)) {
|
||||||
href &&
|
return (
|
||||||
href.indexOf("http:") !== 0 &&
|
<Tooltip {...props} absolutePath={absoluteContentPath(props.href)} render={ tooltipTriggerProps => (
|
||||||
href.indexOf("https:") !== 0 &&
|
<a {...tooltipTriggerProps} />
|
||||||
href.includes(".md")
|
)}
|
||||||
) {
|
/>
|
||||||
return <Fragment>
|
)
|
||||||
<a {...props} {...getReferenceProps({ref: reference})} />
|
|
||||||
<FloatingPortal>
|
|
||||||
{ showTooltip && previewLoaded &&
|
|
||||||
<Tooltip
|
|
||||||
{...getFloatingProps({
|
|
||||||
ref: floating,
|
|
||||||
theme: 'light',
|
|
||||||
arrowRef,
|
|
||||||
arrowX,
|
|
||||||
arrowY,
|
|
||||||
placement,
|
|
||||||
style: {
|
|
||||||
position: strategy,
|
|
||||||
left: x ?? '',
|
|
||||||
top: y ?? '',
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{ preview }
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
</FloatingPortal>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
}
|
||||||
return <a {...props} />;
|
return <a {...props} />;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,21 @@
|
||||||
import React from 'react';
|
import { useState, useEffect, useRef, Fragment } from 'react'
|
||||||
|
import {
|
||||||
|
arrow,
|
||||||
|
autoPlacement,
|
||||||
|
FloatingPortal,
|
||||||
|
inline,
|
||||||
|
offset,
|
||||||
|
shift,
|
||||||
|
useDismiss,
|
||||||
|
useFloating,
|
||||||
|
useHover,
|
||||||
|
useFocus,
|
||||||
|
useInteractions,
|
||||||
|
useRole,
|
||||||
|
} from '@floating-ui/react-dom-interactions'
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
|
|
||||||
|
import documentExtract from '../utils/documentExtract'
|
||||||
|
|
||||||
|
|
||||||
const tooltipBoxStyle = (theme) => ({
|
const tooltipBoxStyle = (theme) => ({
|
||||||
|
|
@ -11,7 +28,7 @@ const tooltipBoxStyle = (theme) => ({
|
||||||
boxShadow: 'rgba(0, 0, 0, 0.55) 0px 0px 16px -3px',
|
boxShadow: 'rgba(0, 0, 0, 0.55) 0px 0px 16px -3px',
|
||||||
})
|
})
|
||||||
|
|
||||||
const tooltipBodyStyle = () => ({
|
const tooltipBodyStyle = (theme) => ({
|
||||||
maxHeight: '3.6rem',
|
maxHeight: '3.6rem',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
lineHeight: '1.2rem',
|
lineHeight: '1.2rem',
|
||||||
|
|
@ -31,8 +48,51 @@ const tooltipArrowStyle = ({ theme, x, y, side }) => ({
|
||||||
transform: "rotate(45deg)"
|
transform: "rotate(45deg)"
|
||||||
})
|
})
|
||||||
|
|
||||||
export const Tooltip = React.forwardRef((props, ref) => {
|
export const Tooltip = (props) => {
|
||||||
const { theme, children, arrowRef, arrowX, arrowY, placement, ...tooltipProps } = props;
|
const theme = 'light'; // temporarily hard-coded; light theme tbd in next PR
|
||||||
|
|
||||||
|
const arrowRef = useRef(null);
|
||||||
|
const [ showTooltip, setShowTooltip ] = useState(false);
|
||||||
|
const [ tooltipContent, setTooltipContent ] = useState("");
|
||||||
|
const [ tooltipContentLoaded, setTooltipContentLoaded ] = useState(false);
|
||||||
|
// floating-ui dom hook
|
||||||
|
const {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
reference, // trigger element back ref
|
||||||
|
floating, // tooltip back ref
|
||||||
|
placement, // default: 'bottom'
|
||||||
|
strategy, // default: 'absolute'
|
||||||
|
context,
|
||||||
|
middlewareData: { arrow: { x: arrowX, y: arrowY } = {}} // data for arrow positioning
|
||||||
|
} = useFloating({
|
||||||
|
open: showTooltip, // state value binding
|
||||||
|
onOpenChange: setShowTooltip, // state value setter
|
||||||
|
middleware: [
|
||||||
|
offset(5), // offset from container border
|
||||||
|
autoPlacement({ padding: 5 }), // auto place vertically
|
||||||
|
shift({ padding: 5 }), // flip horizontally if necessary
|
||||||
|
arrow({ element: arrowRef, padding: 4 }), // add arrow element
|
||||||
|
inline(), // correct position for multiline anchor tags
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// floating-ui interactions hook
|
||||||
|
const { getReferenceProps, getFloatingProps } = useInteractions([
|
||||||
|
useHover(context, { delay: 100 }),
|
||||||
|
useFocus(context),
|
||||||
|
useRole(context, { role: 'tooltip' }),
|
||||||
|
useDismiss(context, { ancestorScroll: true }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const tooltipTriggerProps = getReferenceProps({ ...props, ref: reference});
|
||||||
|
const tooltipProps = getFloatingProps({
|
||||||
|
ref: floating,
|
||||||
|
style: {
|
||||||
|
position: strategy,
|
||||||
|
left: x ?? '',
|
||||||
|
top: y ?? '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const arrowPlacement = {
|
const arrowPlacement = {
|
||||||
top: 'bottom',
|
top: 'bottom',
|
||||||
|
|
@ -41,19 +101,56 @@ export const Tooltip = React.forwardRef((props, ref) => {
|
||||||
left: 'right',
|
left: 'right',
|
||||||
}[placement.split('-')[0]];
|
}[placement.split('-')[0]];
|
||||||
|
|
||||||
|
const fetchTooltipContent = async () => {
|
||||||
|
setTooltipContentLoaded(false);
|
||||||
|
|
||||||
|
const response = await fetch(props.absolutePath);
|
||||||
|
if (response.status !== 200) {
|
||||||
|
console.log(`Looks like there was a problem. Status Code: ${response.status}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const md = await response.text();
|
||||||
|
const extract = documentExtract(md);
|
||||||
|
|
||||||
|
setTooltipContent(extract);
|
||||||
|
setTooltipContentLoaded(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showTooltip) {
|
||||||
|
fetchTooltipContent();
|
||||||
|
}
|
||||||
|
}, [showTooltip])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tooltip" {...tooltipProps} ref={ref}>
|
<Fragment>
|
||||||
<div className="tooltip-box" style={ tooltipBoxStyle(theme) }>
|
{ props.render(tooltipTriggerProps) }
|
||||||
<div className="tooltip-body" style={ tooltipBodyStyle() }>
|
<FloatingPortal>
|
||||||
{ children }
|
<AnimatePresence>
|
||||||
</div>
|
{ showTooltip && tooltipContentLoaded &&
|
||||||
</div>
|
<motion.div
|
||||||
<div className="tooltip-arrow" ref={arrowRef} style={ tooltipArrowStyle({
|
{...tooltipProps}
|
||||||
theme,
|
initial={{ opacity: 0, scale: 0.85 }}
|
||||||
x: arrowX,
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
y: arrowY,
|
exit={{ opacity: 0 }}
|
||||||
side: arrowPlacement
|
transition={{ type: "spring", damping: 20, stiffness: 300 }}
|
||||||
}) }></div>
|
>
|
||||||
</div>
|
<div className="tooltip-box" style={ tooltipBoxStyle(theme) }>
|
||||||
|
<div className="tooltip-body" style={ tooltipBodyStyle(theme) }>
|
||||||
|
{ tooltipContent }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ref={arrowRef} className="tooltip-arrow" style={ tooltipArrowStyle({
|
||||||
|
theme,
|
||||||
|
x: arrowX,
|
||||||
|
y: arrowY,
|
||||||
|
side: arrowPlacement
|
||||||
|
})}>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
}
|
||||||
|
</AnimatePresence>
|
||||||
|
</FloatingPortal>
|
||||||
|
</Fragment>
|
||||||
)
|
)
|
||||||
})
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
"@silvenon/remark-smartypants": "^1.0.0",
|
"@silvenon/remark-smartypants": "^1.0.0",
|
||||||
"@tailwindcss/typography": "^0.5.2",
|
"@tailwindcss/typography": "^0.5.2",
|
||||||
"contentlayer": "^0.1.2",
|
"contentlayer": "^0.1.2",
|
||||||
|
"framer-motion": "^6.3.3",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"hast-util-to-string": "^2.0.0",
|
"hast-util-to-string": "^2.0.0",
|
||||||
"next": "^12.1.0",
|
"next": "^12.1.0",
|
||||||
|
|
@ -308,6 +309,21 @@
|
||||||
"resolved": "https://registry.npmjs.org/@effect-ts/system/-/system-0.55.1.tgz",
|
"resolved": "https://registry.npmjs.org/@effect-ts/system/-/system-0.55.1.tgz",
|
||||||
"integrity": "sha512-OEnwd9JhrV2Q5S7cke/ZgR56Hn75DSr1aIkA0PBE1edoX6GKB6nOdu8u/vPhvqjxLHfMgN8o+EVaWUHPLIC1UQ=="
|
"integrity": "sha512-OEnwd9JhrV2Q5S7cke/ZgR56Hn75DSr1aIkA0PBE1edoX6GKB6nOdu8u/vPhvqjxLHfMgN8o+EVaWUHPLIC1UQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@emotion/is-prop-valid": {
|
||||||
|
"version": "0.8.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
||||||
|
"integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emotion/memoize": "0.7.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@emotion/memoize": {
|
||||||
|
"version": "0.7.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
|
||||||
|
"integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@esbuild-plugins/node-resolve": {
|
"node_modules/@esbuild-plugins/node-resolve": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild-plugins/node-resolve/-/node-resolve-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild-plugins/node-resolve/-/node-resolve-0.1.4.tgz",
|
||||||
|
|
@ -2431,6 +2447,33 @@
|
||||||
"url": "https://www.patreon.com/infusion"
|
"url": "https://www.patreon.com/infusion"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "6.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.3.3.tgz",
|
||||||
|
"integrity": "sha512-wo0dCnoq5vn4L8YVOPO9W54dliH78vDaX0Lj+bSPUys6Nt5QaehrS3uaYa0q5eVeikUgtTjz070UhQ94thI5Sw==",
|
||||||
|
"dependencies": {
|
||||||
|
"framesync": "6.0.1",
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"popmotion": "11.0.3",
|
||||||
|
"style-value-types": "5.0.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "^0.8.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": ">=16.8 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/framesync": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fs.realpath": {
|
"node_modules/fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
|
@ -2701,6 +2744,11 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hey-listen": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="
|
||||||
|
},
|
||||||
"node_modules/html-void-elements": {
|
"node_modules/html-void-elements": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
|
||||||
|
|
@ -4630,6 +4678,17 @@
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/popmotion": {
|
||||||
|
"version": "11.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz",
|
||||||
|
"integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==",
|
||||||
|
"dependencies": {
|
||||||
|
"framesync": "6.0.1",
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"style-value-types": "5.0.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.12",
|
"version": "8.4.12",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz",
|
||||||
|
|
@ -5571,6 +5630,15 @@
|
||||||
"inline-style-parser": "0.1.1"
|
"inline-style-parser": "0.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/style-value-types": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==",
|
||||||
|
"dependencies": {
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/styled-jsx": {
|
"node_modules/styled-jsx": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.0.tgz",
|
||||||
|
|
@ -6334,6 +6402,21 @@
|
||||||
"resolved": "https://registry.npmjs.org/@effect-ts/system/-/system-0.55.1.tgz",
|
"resolved": "https://registry.npmjs.org/@effect-ts/system/-/system-0.55.1.tgz",
|
||||||
"integrity": "sha512-OEnwd9JhrV2Q5S7cke/ZgR56Hn75DSr1aIkA0PBE1edoX6GKB6nOdu8u/vPhvqjxLHfMgN8o+EVaWUHPLIC1UQ=="
|
"integrity": "sha512-OEnwd9JhrV2Q5S7cke/ZgR56Hn75DSr1aIkA0PBE1edoX6GKB6nOdu8u/vPhvqjxLHfMgN8o+EVaWUHPLIC1UQ=="
|
||||||
},
|
},
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"version": "0.8.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
||||||
|
"integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"@emotion/memoize": "0.7.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@emotion/memoize": {
|
||||||
|
"version": "0.7.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
|
||||||
|
"integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"@esbuild-plugins/node-resolve": {
|
"@esbuild-plugins/node-resolve": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild-plugins/node-resolve/-/node-resolve-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild-plugins/node-resolve/-/node-resolve-0.1.4.tgz",
|
||||||
|
|
@ -7722,6 +7805,27 @@
|
||||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
|
||||||
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA=="
|
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA=="
|
||||||
},
|
},
|
||||||
|
"framer-motion": {
|
||||||
|
"version": "6.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.3.3.tgz",
|
||||||
|
"integrity": "sha512-wo0dCnoq5vn4L8YVOPO9W54dliH78vDaX0Lj+bSPUys6Nt5QaehrS3uaYa0q5eVeikUgtTjz070UhQ94thI5Sw==",
|
||||||
|
"requires": {
|
||||||
|
"@emotion/is-prop-valid": "^0.8.2",
|
||||||
|
"framesync": "6.0.1",
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"popmotion": "11.0.3",
|
||||||
|
"style-value-types": "5.0.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"framesync": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"fs.realpath": {
|
"fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
|
@ -7914,6 +8018,11 @@
|
||||||
"space-separated-tokens": "^2.0.0"
|
"space-separated-tokens": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hey-listen": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="
|
||||||
|
},
|
||||||
"html-void-elements": {
|
"html-void-elements": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
|
||||||
|
|
@ -9196,6 +9305,17 @@
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
||||||
},
|
},
|
||||||
|
"popmotion": {
|
||||||
|
"version": "11.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz",
|
||||||
|
"integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==",
|
||||||
|
"requires": {
|
||||||
|
"framesync": "6.0.1",
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"style-value-types": "5.0.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "8.4.12",
|
"version": "8.4.12",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz",
|
||||||
|
|
@ -9840,6 +9960,15 @@
|
||||||
"inline-style-parser": "0.1.1"
|
"inline-style-parser": "0.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"style-value-types": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==",
|
||||||
|
"requires": {
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"styled-jsx": {
|
"styled-jsx": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
"@silvenon/remark-smartypants": "^1.0.0",
|
"@silvenon/remark-smartypants": "^1.0.0",
|
||||||
"@tailwindcss/typography": "^0.5.2",
|
"@tailwindcss/typography": "^0.5.2",
|
||||||
"contentlayer": "^0.1.2",
|
"contentlayer": "^0.1.2",
|
||||||
|
"framer-motion": "^6.3.3",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"hast-util-to-string": "^2.0.0",
|
"hast-util-to-string": "^2.0.0",
|
||||||
"next": "^12.1.0",
|
"next": "^12.1.0",
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ body {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
width: 10%;
|
width: 30%;
|
||||||
height: 1.2em;
|
height: 1.2em;
|
||||||
background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 50%);
|
background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 100%);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue