From 90fdaeb4060f0e04a7a1bf274356316d3bb1d9d8 Mon Sep 17 00:00:00 2001 From: Morten Olsen Date: Wed, 23 Mar 2022 22:00:27 +0100 Subject: [PATCH] update --- :w | 102 ----------------------- articles/hiring/index.yml | 1 + articles/hyperconnect/authentication.md | 10 +++ articles/hyperconnect/definition.md | 6 ++ articles/hyperconnect/index.yml | 25 ++++++ articles/my-home-runs-redux/index.yml | 1 + articles/npm-safety/index.yml | 3 + articles/npm-safety/main.md | 12 +++ package.json | 1 + src/components/animations/slide-in.tsx | 51 ++++++++++++ src/components/animations/transition.tsx | 57 +++++++++++++ src/components/experiences/index.tsx | 33 +++++--- src/components/featured/index.tsx | 1 + src/components/hero/background.tsx | 25 +++++- src/components/hero/index.tsx | 5 +- src/components/navigation/index.tsx | 8 +- src/components/tiles/article/index.tsx | 13 +-- src/config.ts | 7 ++ src/data/articles.ts | 7 +- src/data/experiences.ts | 1 - src/data/profile.ts | 1 - src/hooks/animation.ts | 28 +++++++ src/pages/_app.tsx | 5 +- src/pages/articles/[id].tsx | 14 +++- src/pages/index.tsx | 4 + yarn.lock | 50 ++++++++++- 26 files changed, 337 insertions(+), 134 deletions(-) delete mode 100644 :w create mode 100644 articles/hyperconnect/authentication.md create mode 100644 articles/hyperconnect/definition.md create mode 100644 articles/hyperconnect/index.yml create mode 100644 articles/npm-safety/index.yml create mode 100644 articles/npm-safety/main.md create mode 100644 src/components/animations/slide-in.tsx create mode 100644 src/components/animations/transition.tsx create mode 100644 src/config.ts create mode 100644 src/hooks/animation.ts diff --git a/:w b/:w deleted file mode 100644 index bc7cdef..0000000 --- a/:w +++ /dev/null @@ -1,102 +0,0 @@ -import React from 'react'; -import styled from 'styled-components'; -import { Profile } from '../../data/profile'; -import { HeroBackground } from './background'; - -type Props = { - profile: Profile; -} - -const Wrapper = styled.div` - position: relative; - min-height: 900px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 30px; -`; - -const Avatar = styled.div<{src: string}>` - background-image: url('${({ src }) => src}'); - max-width: 400px; - width: 100%; - border-radius: 50%; - background-size: cover; - border: solid 10px #fff; - box-shadow: 0 0 15px rgba(0, 0, 0, 0.5); - transform: scaleX(-1); -`; - -const AvatarSpacer = styled.div` - padding-bottom: 100%; -`; - -const Name = styled.h1` - font-size: 4rem; - line-height: 4rem; - font-weight: 400; - color: #fff; - margin: 0; - text-shadow: 0 0 15px rgba(0, 0, 0, 0.5); - text-align: center; -`; - -const Tagline = styled.h2` - font-size: 2rem; - font-weight: 100; - color: #fff; - margin: 0; - text-shadow: 0 0 15px rgba(0, 0, 0, 0.5); - text-align: center; -`; - -const Social = styled.div` - margin-top: 40px; - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: center; -`; - -const SocialItem = styled.a` - display: flex; - align-items: center; - justify-content: center; - padding: 20px; - color: #000; -`; - -const SocialText = styled.div` - margin-left: 20px; -`; - -const SocialLogo = styled.div<{ src: string }>` - background-image: url('${({ src }) => src}'); - width: 50px; - height: 50px; - background-size: cover; -` - -const Hero: React.FC = ({ profile }) => ( - - - - - - {profile.name} - - {profile.tagline} - - {profile.social.map((social) => ( - - - {social.name} - - ))} - - - -); - -export { Hero }; diff --git a/articles/hiring/index.yml b/articles/hiring/index.yml index ee620b1..b1accb7 100644 --- a/articles/hiring/index.yml +++ b/articles/hiring/index.yml @@ -1,4 +1,5 @@ title: How to hire engineers, by an engineer cover: cover.png +published: 2021-03-15 parts: - main.md diff --git a/articles/hyperconnect/authentication.md b/articles/hyperconnect/authentication.md new file mode 100644 index 0000000..51f390f --- /dev/null +++ b/articles/hyperconnect/authentication.md @@ -0,0 +1,10 @@ +we will need a way for our devices to identify with one and another, and since we might not have access to any particular node in the system at the time of authentication, this needs to work without a trusted third party at the time of connection. + +The best way I can think of here is to use a signing authority. + +Our authentication will consist of two main concept; a passport and a passport authority. + +Each device will create a passport, which contains some various information but most important is a public key coresponding to a private key stored on the device. A device then has to go through a "claim process" where a user assign it as their device. this happens by that uses passport authority uses a private key to sign the device's passport, and giving it the authorities public key. + +Now our device has a signed passport, and the oublic key of the authority, so when two devices needs to connect they can now go through an authentication process to verify each others passport. If both devices verifies the other device's passport as valid the connection can be established. + diff --git a/articles/hyperconnect/definition.md b/articles/hyperconnect/definition.md new file mode 100644 index 0000000..dcfde16 --- /dev/null +++ b/articles/hyperconnect/definition.md @@ -0,0 +1,6 @@ +What does hyper-connectivity mean? Well, a common interpretation is to be available on multiple different channels. We al know that one guy whom you contact on text message only to get a reply on Signal, just to get a follow up using email. + +Then what does it mean for devices to be hyper connected? In this case it means using all available forms of communication in order to get data from one place to another, which is what this article is about. + +Today, when a developer want a system to send data from one place to another he needs to pick a transport protocol such as http. Then connect + diff --git a/articles/hyperconnect/index.yml b/articles/hyperconnect/index.yml new file mode 100644 index 0000000..db78776 --- /dev/null +++ b/articles/hyperconnect/index.yml @@ -0,0 +1,25 @@ +title: Creating a hyper connectivity framework +parts: + - title: definition + file: definition.md + - title: reason + - title: target + - title: design + notes: | + onion based stream + 4 way streams + - title: connection + notes: | + peerjs, tcp, ble(?) + session id + - title: reconnection + - title: authentication + file: authentication.md + notes: | + passport service + - title: security + notes: | + diff-hellman + - title: transport-nodes + - title: proof-of-concept + - title: conclusion diff --git a/articles/my-home-runs-redux/index.yml b/articles/my-home-runs-redux/index.yml index 373c9b2..c70704d 100644 --- a/articles/my-home-runs-redux/index.yml +++ b/articles/my-home-runs-redux/index.yml @@ -1,4 +1,5 @@ title: My home runs Redux cover: cover.png +published: 2021-03-15 parts: - main.md diff --git a/articles/npm-safety/index.yml b/articles/npm-safety/index.yml new file mode 100644 index 0000000..c6f787b --- /dev/null +++ b/articles/npm-safety/index.yml @@ -0,0 +1,3 @@ +title: NPM safety +parts: + - main.md diff --git a/articles/npm-safety/main.md b/articles/npm-safety/main.md new file mode 100644 index 0000000..3bb4f47 --- /dev/null +++ b/articles/npm-safety/main.md @@ -0,0 +1,12 @@ +The NPM eco system has hade a long list of stories about major dependencies turning evil lately, either by direct involvment from the package maintainer or due to the maintainer being compromised. What ever the reason, it does bring in to focus the dangers of package managers! + +The threat landscaoe being what it is it is tine that we as developers start ti apply a little extra operational security to mitigate some of the risk that comes from installing unaudited oackages, which are in essence just arbitrary executing code which can conceil a viper virus or a remote access token as easily as a random email attachment. + +So what can we do to protect ourselfs? we can split the attacks into to groups, one which attacks the users of our application and one that attacks our selves and our CI/CD pipelines + +Combating the former is hard and here the only thing short of manually auditing every change in every depebdebcy is to set up monitoring of dependencies with vulnerabilities and freeze dependencies versions to known good versions + +The later attack type is the one this article is going to focus on. + +A NPM oackage has the ability to run post install hooks, which essentially allow it to execute any code as the current user upon installing the dependency. This allows a malicius oackage to infect your system upon installation by also installing malware or running malicious commands. This can be mitigated by disable install hooks, but some packages have legitinate use cases for these install hooks. + diff --git a/package.json b/package.json index dd04c8d..bedf2c6 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@types/yaml": "^1.9.7", "babel-plugin-styled-components": "^2.0.6", "file-loader": "^6.2.0", + "framer-motion": "^6.2.8", "fs-extra": "^10.0.1", "marked": "^4.0.12", "next-compose-plugins": "^2.2.1", diff --git a/src/components/animations/slide-in.tsx b/src/components/animations/slide-in.tsx new file mode 100644 index 0000000..2897042 --- /dev/null +++ b/src/components/animations/slide-in.tsx @@ -0,0 +1,51 @@ +import { motion, useAnimation } from 'framer-motion'; +import React, { useEffect, useMemo, useRef } from 'react'; +import { useOnScreen } from '../../hooks/animation'; + +const SlideIn: React.FC> = ({ + children, + ...props +}) => { + const ref = useRef(); + const controls = useAnimation(); + const onScreen = useOnScreen(ref); + const slideTime = useMemo( + () => 1, + [], + ); + + useEffect( + () => { + if (!onScreen) { + return; + } + controls.start({ + y: 0, + opacity: 1, + scale: 1, + transition: { + duration: slideTime, + ease: "easeOut" + } + }) + }, + [controls, onScreen], + ); + + return ( + + {children} + + ) +} + +export { SlideIn }; diff --git a/src/components/animations/transition.tsx b/src/components/animations/transition.tsx new file mode 100644 index 0000000..1af6ab9 --- /dev/null +++ b/src/components/animations/transition.tsx @@ -0,0 +1,57 @@ +import { useEffect, useState } from "react" +import { motion, useAnimation } from 'framer-motion'; + +const Transition: React.FC = ({ children }) => { + return <>{children} + // const [displayChildren, setDisplayChildren] = useState(children); + // const [inTransition, setInTransition] = useState(false); + // const controls = useAnimation(); + // + // useEffect(() => { + // if (children !== displayChildren) { + // setInTransition(true); + // } + // }, [children, setDisplayChildren, displayChildren]); + // + // useEffect(() => { + // if (!inTransition || displayChildren === children) { + // return; + // } + // controls.start({ + // opacity: 1, + // y: 0, + // transition: { + // duration: 0.3, + // ease: "easeOut" + // } + // }).then(() => { + // setInTransition(false); + // setDisplayChildren(children); + // }); + // }, [inTransition, children, displayChildren]) + // + // return ( + // <> + // {inTransition && ( + // + // {children} + // + // )} + //
{displayChildren}
+ // + // ); +} + +export { Transition }; diff --git a/src/components/experiences/index.tsx b/src/components/experiences/index.tsx index ee2bbde..e66aafc 100644 --- a/src/components/experiences/index.tsx +++ b/src/components/experiences/index.tsx @@ -1,7 +1,8 @@ -import React, { useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import ReactMarkdown from "react-markdown"; import styled from "styled-components"; import { Experience } from "../../data/experiences" +import { SlideIn } from '../animations/slide-in'; type Props = { experiences: Experience[]; @@ -44,7 +45,7 @@ const ExperienceWrapper = styled.div` } `; -const Inner = styled.div` +const Inner = styled(SlideIn)` border: solid 1px #eee; padding: 20px; `; @@ -73,25 +74,31 @@ const More = styled.div` margin-top: 10px; `; +const Hidden = styled.div` + overflow: hidden; + transition: all 0.3s ease-out; +`; + const ExperienceRow = ({ experience }) => { const [visible, setVisible] = useState(false); return ( - + {experience.company.name} {experience.title} - {visible ? ( - <> - - {experience.content} - - setVisible(false)}>Show less - - ) : ( - setVisible(true)}>Show more - )} + + + {experience.content} + + + setVisible(!visible)}>Show {visible ? 'less' : 'more'} diff --git a/src/components/featured/index.tsx b/src/components/featured/index.tsx index 6208265..6d8ab2a 100644 --- a/src/components/featured/index.tsx +++ b/src/components/featured/index.tsx @@ -1,5 +1,6 @@ import React, { ReactNode } from 'react'; import styled from 'styled-components'; +import { SlideIn } from '../animations/slide-in'; type Props = { title: string; diff --git a/src/components/hero/background.tsx b/src/components/hero/background.tsx index 3e83295..3a1ba27 100644 --- a/src/components/hero/background.tsx +++ b/src/components/hero/background.tsx @@ -1,6 +1,6 @@ import React, { Suspense, useMemo, useRef, useState } from 'react'; import { Canvas, useFrame, useLoader } from '@react-three/fiber'; -import { Euler, Vector3 } from 'three'; +import { Clock, Euler, Vector3 } from 'three'; import { TextureLoader } from 'three/src/loaders/TextureLoader' import styled from 'styled-components'; const { default: smoke } = require('./smoke.png'); @@ -14,6 +14,24 @@ const Wrapper = styled.div` z-index: -1; `; +const FrameLimiter = () => { + const [clock] = React.useState(new Clock()); + const [fps] = React.useState(10); + + useFrame((state: any) => { + state.ready = false; + const timeUntilNextFrame = (1000 / fps) - clock.getDelta(); + + setTimeout(() => { + state.ready = true; + state.invalidate(); + }, Math.max(0, timeUntilNextFrame)); + + }); + + return <>; +}; + const Cloud = ({ texture }) => { const ref = useRef(); const width = window.innerWidth / 2; @@ -21,7 +39,7 @@ const Cloud = ({ texture }) => { useFrame(() => { if (!ref.current) return; - ref.current.rotation.z -= 0.001; + ref.current.rotation.z -= 0.003; }); return ( @@ -45,7 +63,7 @@ const Clouds = () => { return ( <> {items.map((_, i) => ( - + ))} ) @@ -69,6 +87,7 @@ const Scene = () => { rotation: [1.16, -0.12, 0.27], }} > + = ({ profile }) => ( {profile.tagline} {profile.social.map((social) => ( - + + {social.name} + ))} diff --git a/src/components/navigation/index.tsx b/src/components/navigation/index.tsx index d1db4cc..00fcbca 100644 --- a/src/components/navigation/index.tsx +++ b/src/components/navigation/index.tsx @@ -3,6 +3,10 @@ import React from "react"; import styled from "styled-components"; import { Content } from "../content"; +type Props = { + name: string; +}; + const Menu = styled.aside` font-size: 2rem; padding: 1rem 0; @@ -13,10 +17,10 @@ const Menu = styled.aside` const MenuItem = styled(Link)` `; -const Navigation: React.FC<{}> = () => ( +const Navigation: React.FC = ({ name }) => ( - by Morten Olsen + by {name} ); diff --git a/src/components/tiles/article/index.tsx b/src/components/tiles/article/index.tsx index 58363cc..5b40c62 100644 --- a/src/components/tiles/article/index.tsx +++ b/src/components/tiles/article/index.tsx @@ -2,12 +2,13 @@ import Link from 'next/link'; import React from 'react'; import styled from 'styled-components'; import { Article } from '../../../data/articles'; +import { SlideIn } from '../../animations/slide-in'; type Props = { article: Article; } -const Wrapper = styled.div` +const Wrapper = styled(SlideIn)` cursor: pointer; display: flex; padding: 15px; @@ -58,11 +59,13 @@ const ArticleTile: React.FC = ({ article }) => (
{article.title}
- 3 days ago + {article.published} - - - + {article.cover && ( + + + + )} ); diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..cb95b5f --- /dev/null +++ b/src/config.ts @@ -0,0 +1,7 @@ +class Config { + public get dev() { + return process && process.env.NODE_ENV === 'development'; + } +} + +export const config = new Config(); diff --git a/src/data/articles.ts b/src/data/articles.ts index 3564c39..c48af32 100644 --- a/src/data/articles.ts +++ b/src/data/articles.ts @@ -5,6 +5,7 @@ import { remark } from 'remark'; import remarkHtml from 'remark-html'; import behead from 'remark-behead'; import { visit } from 'unist-util-visit'; +import { config } from '../config'; const imageModules = (require as any).context( '../../articles', @@ -18,7 +19,6 @@ const images = imageModules.keys().map((key) => ({ const replaceImages = ({ id }) => (tree: any) => { visit(tree, 'image', (node) => { - console.log(id); if (!node.url.startsWith('./')) return; const correctedUrl = `.${path.resolve('/', id, node.url)}`; const image = images.find((i: any) => i.key === correctedUrl); @@ -113,7 +113,10 @@ export class Articles { const articles = await Promise.all(articleLocations.map( (location) => this.#loadArticle(path.join(rootLocation, location)), )); - return articles; + return articles + .sort((a, b) => new Date(b.published || 0).getTime() - new Date(a.published || 0).getTime()) + .filter(a => a.published || config.dev) + } public getImage = (article: string, name: string) => { diff --git a/src/data/experiences.ts b/src/data/experiences.ts index 3f36a88..71f2354 100644 --- a/src/data/experiences.ts +++ b/src/data/experiences.ts @@ -18,7 +18,6 @@ const images = imageModules.keys().map((key) => ({ const replaceImages = ({ id }) => (tree: any) => { visit(tree, 'image', (node) => { - console.log(id); if (!node.url.startsWith('./')) return; const correctedUrl = `.${path.resolve('/', id, node.url)}`; const image = images.find((i: any) => i.key === correctedUrl); diff --git a/src/data/profile.ts b/src/data/profile.ts index 1424dba..e125b06 100644 --- a/src/data/profile.ts +++ b/src/data/profile.ts @@ -44,7 +44,6 @@ export class ProfileDB { structure.avatar = image.url; } structure.social = structure.social.map((social) => { - console.log(social.logo, images) const image = images.find((i: any) => i.key === `.${path.resolve('/', social.logo)}`) return { ...social, diff --git a/src/hooks/animation.ts b/src/hooks/animation.ts new file mode 100644 index 0000000..2889823 --- /dev/null +++ b/src/hooks/animation.ts @@ -0,0 +1,28 @@ +import { MutableRefObject, useEffect, useState } from "react"; + +export const useOnScreen = (ref: MutableRefObject, rootMargin = '0px') => { + const [isIntersecting, setIntersecting] = useState(false); + + useEffect(() => { + const { current } = ref; + const observer = new IntersectionObserver( + ([entry]) => { + setIntersecting(entry.isIntersecting); + }, + { + rootMargin + } + ); + if (current) { + observer.observe(current); + } + return () => { + if (current) { + observer.unobserve(current); + } + }; + }, [ref]); + + return isIntersecting; +} + diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 78e3d41..9af22e0 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -5,6 +5,7 @@ import Head from 'next/head'; import "@fontsource/merriweather"; import "@fontsource/pacifico"; import "@fontsource/fredoka"; +import { Transition } from '../components/animations/transition'; const GlobalStyle = createGlobalStyle` * { @@ -42,7 +43,9 @@ export default function App({ Component, pageProps }: AppProps) { - + + + ); }; diff --git a/src/pages/articles/[id].tsx b/src/pages/articles/[id].tsx index 04b7d0e..93ae2a7 100644 --- a/src/pages/articles/[id].tsx +++ b/src/pages/articles/[id].tsx @@ -4,15 +4,19 @@ import { Article, articleDB } from '../../data/articles'; import { Content } from '../../components/content'; import ReactMarkdown, { Components } from 'react-markdown'; import { Navigation } from '../../components/navigation'; +import Head from 'next/head'; +import { Profile, profileDB } from '../../data/profile'; type Props = { article: Article; + profile: Profile; }; const Image = styled.img` `; -const ImageWrapper = styled.div` +const ImageWrapper = styled.span` + display: block; text-align: center; `; @@ -67,10 +71,14 @@ const components: Components = { const ArticleView: React.FC = ({ article, + profile, }) => { return ( <> - + + {profile.name} - {article.title} + +

{article.title}

@@ -96,9 +104,11 @@ export async function getStaticPaths() { export async function getStaticProps({ params }: any) { const { id } = params; const article = await articleDB.get(id); + const profile = await profileDB.get(); return { props: { article, + profile, } } } diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 935b0a9..264da8b 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,3 +1,4 @@ +import Head from 'next/head'; import React from 'react'; import { Content } from '../components/content'; import { Experiences } from '../components/experiences'; @@ -17,6 +18,9 @@ type Props = { const Home: React.FC = ({ articles, profile, experiences }) => ( <> + + {profile.name} - {profile.tagline} + diff --git a/yarn.lock b/yarn.lock index ce81d31..89f1dc0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -155,7 +155,7 @@ resolved "https://registry.yarnpkg.com/@chevrotain/utils/-/utils-10.1.2.tgz#d2fb7b968141139e5c2419553e5295382c265e7d" integrity sha512-bbZIpW6fdyf7FMaeDmw3cBbkTqsecxEkwlVKgVfqqXWBPLH6azxhPA2V9F7OhoZSVrsnMYw7QuyK6qutXPjEew== -"@emotion/is-prop-valid@^0.8.8": +"@emotion/is-prop-valid@^0.8.2", "@emotion/is-prop-valid@^0.8.8": version "0.8.8" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== @@ -1025,6 +1025,26 @@ file-loader@^6.2.0: loader-utils "^2.0.0" schema-utils "^3.0.0" +framer-motion@^6.2.8: + version "6.2.8" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.2.8.tgz#02abb529191af7e2df444185fe27e932215b715d" + integrity sha512-4PtBWFJ6NqR350zYVt9AsFDtISTqsdqna79FvSYPfYDXuuqFmiKtZdkTnYPslnsOMedTW0pEvaQ7eqjD+sA+HA== + 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" + +framesync@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20" + integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA== + dependencies: + tslib "^2.1.0" + fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" @@ -1156,6 +1176,11 @@ hast-util-whitespace@^2.0.0: resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz#4fc1086467cc1ef5ba20673cb6b03cec3a970f1c" integrity sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg== +hey-listen@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" + integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== + hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -1986,6 +2011,16 @@ picomatch@^2.3.0: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +popmotion@11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9" + integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA== + dependencies: + framesync "6.0.1" + hey-listen "^1.0.8" + style-value-types "5.0.0" + tslib "^2.1.0" + postcss-value-parser@^4.0.2: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" @@ -2517,6 +2552,14 @@ style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" +style-value-types@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad" + integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA== + dependencies: + hey-listen "^1.0.8" + tslib "^2.1.0" + styled-components@^5.3.3: version "5.3.3" resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.3.tgz#312a3d9a549f4708f0fb0edc829eb34bde032743" @@ -2644,6 +2687,11 @@ trough@^2.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== +tslib@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"