[
  {
    "path": ".gitignore",
    "content": "/node_modules\n/.next\nnext.config.js\n.now"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 sambernhardt\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "`git clone https://github.com/sambernhardt/ipad-cursor.git`\n\n`npm i`\n\n`npm run start`\n\n![Preview](https://github.com/sambernhardt/ipad-cursor/blob/master/public/preview.gif)\n\n# Basic usage\n\n## Add the CursorProvider to a page\n```javascript\n// app.js\n\nimport App from 'next/app';\nimport CursorProvider from '../cursor/Provider';\n\nexport default class MyApp extends App {\n  render () {\n    const { Component, pageProps } = this.props;\n    \n    return (\n      <CursorProvider>\n        <Component {...pageProps} />\n      </CursorProvider>\n    )\n  }\n}\n```\n\n## Then wrap your components with the `WithHover` function\n```javascript\n// Component.js\nimport WithHover from '../cursor/WithHover';\n\nconst Component = () => <h1>;\n\nexport default WithHover(<Component />, 'block');\n```\n\n\n### Caveats:\n- To move the contents of the hovered component, the component must have a display type of `inline-block` or `block`. CSS transforms don't work on inline elements.\n\n"
  },
  {
    "path": "components/GoogleAnalytics/init.js",
    "content": "import ReactGA from \"react-ga\"\n \nexport const initGA = () => {\n  ReactGA.initialize(process.env.google_analytics)\n}\n \nexport const logPageView = () => {\n  ReactGA.set({ page: window.location.pathname })\n  ReactGA.pageview(window.location.pathname)\n}"
  },
  {
    "path": "components/GoogleAnalytics/layout.js",
    "content": "import React, { Component } from \"react\"\n \nimport { initGA, logPageView } from \"./init.js\"\n \nexport default class Layout extends Component {\n  componentDidMount () {\n    if (!window.GA_INITIALIZED) {\n      initGA()\n      window.GA_INITIALIZED = true\n    }\n    logPageView()\n  }\n \n  render () {\n    return (\n      <div>\n        {this.props.children}\n      </div>\n    )\n  }\n}"
  },
  {
    "path": "components/Providers.js",
    "content": "import { Fragment, useState, useEffect } from 'react';\nimport { createGlobalStyle, ThemeProvider } from 'styled-components';\nimport { Reset } from 'styled-reset';\nimport useDarkMode from 'use-dark-mode';\n\nimport {light, dark} from '../theme';\nimport CursorProvider from '../cursor/Provider';\n\nexport default ({children}) => {\n    const [mounted, setMounted] = useState(false);\n    const {value} = useDarkMode(false, { storageKey: null });\n\n    useEffect(() => {\n      setMounted(true)\n    }, []);\n\n    const body = \n      <Fragment>\n          <Reset/>\n          <ThemeProvider theme={value ? dark : light}>\n              <CursorProvider>\n                {children}\n                <GlobalStyle/>\n              </CursorProvider>\n          </ThemeProvider>\n      </Fragment>;\n\n    if (!mounted) {\n        return <div style={{ visibility: 'hidden' }}>{body}</div>\n    }\n    return body;\n}\n\nconst GlobalStyle = createGlobalStyle`\n  body {\n    color: ${({theme}) => theme.colors.body};\n    background: ${({theme}) => theme.colors.background};\n    font-family: ${({theme}) => theme.fonts.default};\n    -webkit-font-smoothing: antialiased;\n    -moz-osx-font-smoothing: grayscale;\n  }\n  h1 {\n    font-size: ${({theme}) => theme.fontSizes[3]}px;\n    margin-bottom: ${({theme}) => theme.space[3]}px;\n  }\n`;"
  },
  {
    "path": "components/components/Footer.js",
    "content": "import styled from 'styled-components';\nimport WithHover from '../../cursor/WithHover';\nimport Toggle from './Toggle';\n\nconst Container = styled.div`\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n`;\n\nconst Link = WithHover(styled.a`\n  color: ${({theme}) => theme.colors.blue};\n  text-decoration: none;\n  z-index: 99;\n  padding: 8px 2px;\n  &:hover {\n    color: ${({theme}) => theme.colors.body};\n  }\n`, 'block');\n\nconst Heading = styled.div`\n  font-size: 32px;\n`;\n\nexport default () => {\n\n  return (\n    <Container>\n        <Toggle/>\n        <Heading style={{ fontSize: '14px' }}>\n          Find me on <Link href=\"https://twitter.com/samuelbernhardt\">the tweets</Link> or check out <Link href=\"https://github.com/sambernhardt/ipad-cursor\">the code</Link>.\n        </Heading>\n    </Container>\n  )\n\n}"
  },
  {
    "path": "components/components/Header.js",
    "content": "import styled from 'styled-components';\n\nimport NavLink from './NavLink';\n\nconst Container = styled.div`\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n`;\n\nconst Title = styled.h2`\n  font-weight: 600;\n`;\n\nconst Links = styled.div`\n    display: flex;\n    font-weight: 600;\n`;\n\nconst Header = () => {\n    return (\n        <Container>\n            <Title>iPad Cursor</Title>\n            <Links>\n                <NavLink>Button 1</NavLink>\n                <NavLink>Button 2</NavLink>\n                <NavLink>Button 3</NavLink>\n            </Links>\n        </Container>\n    )\n}\n\nexport default Header;"
  },
  {
    "path": "components/components/Hero.js",
    "content": "import styled from 'styled-components';\n\nimport TextArea from './TextArea';\n\nconst Container = styled.div`\n  min-height: 70vh;\n  display: flex;\n  flex-direction: column;\n  align-items: flex-start;\n  justify-content: center;\n  margin-bottom: 24px;\n`;\n\nconst Hero = () => {\n    return (\n        <Container>\n            <TextArea\n                style={{ fontSize: '64px' }}\n                defaultValue=\"Hover over this text to see the cursor change size.\"\n                focus\n                placeholder=\"Header\"\n            />\n            <TextArea\n                defaultValue=\"Different sized text will change the cursor size appropriately.\"\n                placeholder=\"Subheader\"\n            />\n            <TextArea\n                style={{ fontSize: '14px' }}\n                defaultValue=\"Even teeny tiny text works.\"\n                placeholder=\"Small text\"\n            />\n        </Container>\n    )\n}\n\nexport default Hero;"
  },
  {
    "path": "components/components/NavLink.js",
    "content": "import { useState, useContext } from 'react';\nimport styled from 'styled-components';\n\nimport WithHover from '../../cursor/WithHover';\n\nconst Container = styled.div`\n    padding: 8px 16px;\n    position: relative;\n`;\n\nconst NavLink = (props) => {    \n    return (\n        <Container {...props} />\n    )\n}\n\nexport default WithHover(NavLink, 'block');"
  },
  {
    "path": "components/components/Text/index.js",
    "content": "import styled from 'styled-components';\n\nconst Subheader = styled.h2`\n    font-size: 16px;\n    font-weight: 600;\n    margin-bottom: 16px;\n`;\n\nmodule.exports = {\n    Subheader\n}"
  },
  {
    "path": "components/components/TextArea.js",
    "content": "import { useState, useEffect, useCallback, useContext } from 'react';\nimport { transparentize } from 'polished';\nimport styled from 'styled-components';\nimport autosize from 'autosize';\n\nimport WithHover from '../../cursor/WithHover';\n\nconst Container = WithHover(styled.textarea`\n  font-size: 32px;\n  width: 100%;\n  background: transparent;\n  color: ${({ theme }) => theme.colors.body};\n  font-family: ${({theme}) => theme.fonts.default};\n  border: none;\n  margin-bottom: 24px;\n  resize: none; \n  &:focus {\n      outline: none;\n  }\n  &::selection {\n    background: ${({theme}) => transparentize(.6, theme.colors.highlight)};\n  }\n`, 'text');\n\nconst TextArea = (props) => {\n    const [ myRef, setRef ] = useState();\n    const ref = useCallback(node => {\n        autosize(node)\n        setRef(node)\n    });\n\n    useEffect(() => {\n      if (myRef && props.focus) {\n        myRef.focus();\n      }\n    },[myRef])\n\n    return (\n        <Container passThroughRef={ref} rows=\"1\" {...props}/>\n    )\n}\n\nexport default TextArea;\n"
  },
  {
    "path": "components/components/Toggle.js",
    "content": "import { useContext } from 'react';\nimport styled from 'styled-components';\nimport { transparentize } from 'polished';\nimport WithHover from '../../cursor/WithHover';\nimport CursorContext from '../../cursor/Context';\n\nconst height = 20;\n\nconst Container = WithHover(styled.div`\n  display: inline-flex;\n  padding: 4px;\n  position: relative;\n  align-items: center;\n  \n  span {\n    font-size: 13px;\n    font-weight: 600;\n  }\n`, 'block');\n\nconst Dot = styled.div`\n  background: white;\n  box-shadow: 0 0 10px rgba(0,0,0,.2);\n  height: ${height - 4}px;\n  width: ${height - 4}px;\n  border-radius: ${(height - 4) / 2}px;\n  position: absolute;\n  left: 2px;\n  top: 2px;\n  transition: left .3s cubic-bezier(0.075, 0.82, 0.165, 1);\n`;\n\nconst ToggleContainer = styled.div`\n  position: relative;\n  height: ${height}px;\n  width: ${height * 2}px;\n  border-radius: ${height / 2}px;\n  background: ${({theme}) => transparentize(.7, theme.colors.body)};\n  margin-right: 16px;\n  overflow: hidden;\n  ${({showingCursor, theme}) => showingCursor && `\n    background: ${theme.colors.green};\n    ${Dot} {\n      left: ${height + 2}px;\n    }\n  `}\n`;\n\nexport default ({}) => {\n  const {toggleCursor, showingCursor} = useContext(CursorContext);\n\n  const handleClick = () => {\n    toggleCursor();\n  }\n\n  return (\n    <Container onClick={handleClick}>\n      <ToggleContainer showingCursor={showingCursor}>\n        <Dot />\n      </ToggleContainer>\n      <span>Show cursor</span>\n    </Container>\n  )\n};"
  },
  {
    "path": "cursor/Context.js",
    "content": "import { createContext } from 'react';\nexport default createContext(\"light\");"
  },
  {
    "path": "cursor/Cursor.js",
    "content": "import { useContext, useState, useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { transparentize } from 'polished';\n\nimport { gsap } from 'gsap';\nimport CursorContext from './Context';\nimport { getRelativePosition } from './utils';\n\nconst Debug = styled.div`\n    background: green;\n    width: 100vw;\n    position: absolute;\n    top: 0;\n    left: 0;\n    display: flex;\n    flex-wrap: wrap;\n    justify-content: flex-start;\n    padding: 8px 16px;\n    > * {\n        min-width: 200px;\n    }\n`;\n\nconst Cursor = styled.div`\n    width: 24px;\n    height: 24px;\n    position: absolute;\n    background: ${({theme}) => transparentize(.5, theme.colors.cursor)};\n    border-radius: 12px;\n    z-index: -1;\n\n    transition: opacity .3s;\n    &.block {\n        border-radius: 4px;\n    }\n    &.text {\n        height: 30px;\n        width: 3px;\n        border-radius: 1px;\n    }\n    &.pressing {\n        opacity: .5;\n        transition: opacity 0s;\n    }\n`;\n\nconst CursorContainer = ({ debug }) => {\n    const {\n        pos,\n        selectedElement,\n        status,\n        pressing,\n        setStatus\n    } = useContext(CursorContext);\n    \n    const cursorRef = useRef();\n    let baseStyles = {\n        left: pos.x - 12,\n        top: pos.y - 12,\n        width: '24px',\n        height: '24px',\n    };\n\n    // when the selectedElement or status changes\n    useEffect(() => {\n        if (!selectedElement.el) return;\n        if (status == \"entering\" || status == \"shifting\") {\n            // console.log(selectedElement)\n            if (selectedElement.type == \"block\") {\n                gsap.to(cursorRef.current, {\n                    duration: .5,\n                    ease: \"elastic.out(1, 1)\",\n                    left: selectedElement.el.offsetLeft,\n                    top: selectedElement.el.offsetTop,\n                    height: selectedElement.el.offsetHeight + \"px\",\n                    width: selectedElement.el.offsetWidth + \"px\",\n                    borderRadius: '4px',\n                    onComplete: () => {\n                        setStatus(\"entered\");\n                    }\n                });\n            }\n        } else if (status == \"exiting\") {\n            // kill all current animations for the block and clear the props it has added\n            gsap.killTweensOf(cursorRef.current);\n        }\n    }, [selectedElement, status]);\n\n\n    useEffect(() => {\n        // general exit handling\n        if (status == \"exiting\" && !selectedElement.el) {\n            gsap.killTweensOf(cursorRef.current);\n            gsap.to(cursorRef.current, {\n                duration: .5,\n                ease: \"elastic.out(1, .5)\",\n                width: '24px',\n                height: '24px',\n                x: 0,\n                y: 0,\n                left: pos.x - 12,\n                top: pos.y - 12,\n                borderRadius: '12px',\n                onComplete: () => {\n                    setStatus(\"\");\n                },\n            });\n        } else if ((status == \"entering\" || status == \"shifting\") && selectedElement.type == \"text\") {\n            // text cursor handling\n            const { textSize } = selectedElement.config;\n            gsap.killTweensOf(cursorRef.current);\n            gsap.to(cursorRef.current, {\n                duration: .5,\n                ease: \"elastic.out(1, 1)\",\n                height: textSize,\n                width: \"3px\",\n                x: 12,\n                y: (textSize / -2) + 10,\n                borderRadius: '1px',\n                onComplete: () => {\n                    setStatus(\"entered\");\n                }\n            });\n        }\n    }, [pos]);\n\n    if (selectedElement.el) {\n        const amount = 5;\n        const relativePos = getRelativePosition(pos, selectedElement.el);\n        const xMid = selectedElement.el.clientWidth / 2;\n        const yMid = selectedElement.el.clientHeight / 2;\n        const xMove = (relativePos.x - xMid) / selectedElement.el.clientWidth * amount;\n        const yMove = (relativePos.y - yMid) / selectedElement.el.clientHeight * amount;\n\n        if (selectedElement.type == \"block\") {\n            baseStyles = {\n                left: selectedElement.el.offsetLeft + xMove,\n                top: selectedElement.el.offsetTop + yMove,\n                height: selectedElement.el.offsetHeight + \"px\",\n                width: selectedElement.el.offsetWidth + \"px\",\n            }\n        }\n    }\n\n    let shapeClass = selectedElement.el && !(status == \"entering\" || status == \"shifting\") && selectedElement.type;\n    return (\n        <div>\n            {debug && <Debug>\n                <span>{JSON.stringify({pos})}</span>\n                <span>{JSON.stringify(selectedElement.type)}</span>\n                <span>{JSON.stringify({status})}</span>\n            </Debug>}\n            <Cursor\n                ref={cursorRef}\n                style={baseStyles}\n                className={[shapeClass, pressing && \"pressing\"]}\n            />\n        </div>\n    )\n}\n\nexport default CursorContainer;"
  },
  {
    "path": "cursor/Provider.js",
    "content": "import { useState } from 'react';\nimport { createGlobalStyle } from 'styled-components';\nimport Cursor from './Cursor';\nimport Context from './Context';\n\nconst GlobalStyle = createGlobalStyle`\n  body, input, textarea, a {\n    ${({ showingCursor }) => !showingCursor && `\n      cursor: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjbQg61aAAAADUlEQVQYV2P4//8/IwAI/QL/+TZZdwAAAABJRU5ErkJggg=='),\n      url(cursor.png),\n      none;\n    `}\n  }\n`;\n\nconst Provider = ({debug, children}) => {\n  const [ mousePos, setMousePos ] = useState({ x: 0, y: 0 });\n\n  const [ selectedElement, selectedElementSet ] = useState({ el: null });\n  const [ status, setStatus ] = useState(\"\");\n  const [ pressing, setPressing ] = useState(false);\n  const [ showingCursor, showingCursorSet ] = useState(false);\n\n  const handleMouseMove = ({ pageX, pageY }) => {\n    setMousePos({x: pageX, y: pageY})\n  };\n\n  const context = {\n    pos: mousePos,\n    selectedElementSet: (element) => {\n      selectedElementSet(element)\n      if (!selectedElement.el) {\n        setStatus(\"entering\")\n      } else {\n        setStatus(\"shifting\")\n      }\n\n    },\n    removeSelectedElement: () => {\n      setStatus(\"exiting\")\n      selectedElementSet({ el: null })\n    },\n    setStatus: setStatus,\n    status: status,\n    selectedElement,\n    pressing,\n\n    toggleCursor: () => showingCursorSet(!showingCursor),\n    showingCursor: showingCursor\n  };\n\n  return (\n    <div\n        onMouseMove={handleMouseMove}\n        onMouseDown={() => setPressing(true)}\n        onMouseUp={() => setPressing(false)}\n    >\n        <Context.Provider value={context}>\n            <GlobalStyle showingCursor={showingCursor} />\n            <Cursor debug={debug} />\n            {children}\n        </Context.Provider>\n    </div>\n  )\n};\n\nexport default Provider;"
  },
  {
    "path": "cursor/WithHover.js",
    "content": "import { useState, useContext } from 'react';\nimport CursorContext from './Context';\n\nimport { getRelativePosition } from './utils';\n\nexport default (Component, type, config) => ({passThroughRef, ...props}) => {\n    const context = useContext(CursorContext);\n    const { selectedElement, pos } = context;\n    const [ hovering, setHovering ] = useState(false);\n\n    const handleMouseEnter = e => {\n        if (!context.selectedElementSet) return;\n        let result = {\n            el: e.currentTarget,\n            type,\n            config: {...config}\n        }\n        if (type == \"text\") {\n            let computed = window.getComputedStyle(e.currentTarget).fontSize;\n            result.config.textSize = parseFloat(computed.replace(\"px\"));\n        }\n        context.selectedElementSet(result);\n        setHovering(true);\n    }\n    const handleMouseLeave = ({pageX, pageY, ...e}) => {\n        if (!context.removeSelectedElement) return;\n        context.removeSelectedElement()\n        setHovering(false);\n    }\n\n    let styles;\n    if (hovering && selectedElement.el && selectedElement.type == \"block\") {\n        const amount = selectedElement.config.hoverOffset ? selectedElement.config.hoverOffset : 2;\n        const relativePos = getRelativePosition(pos, selectedElement.el);\n        const xMid = selectedElement.el.offsetWidth / 2;\n        const yMid = selectedElement.el.offsetHeight / 2;\n        const xMove = (relativePos.x - xMid) / selectedElement.el.offsetHeight * amount;\n        const yMove = (relativePos.y - yMid) / selectedElement.el.offsetHeight * amount;\n        \n        styles = {\n            transform: `translate(${xMove}px, ${yMove}px)`,\n        }\n    }\n\n    return <Component\n        onMouseEnter={handleMouseEnter}\n        onMouseLeave={handleMouseLeave}\n        style={styles}\n        ref={passThroughRef}\n        {...props}\n    />\n}"
  },
  {
    "path": "cursor/utils.js",
    "content": "const getRelativePosition = (pageCoords, element) => {\n    return {\n        x: pageCoords.x - element.offsetLeft,\n        y: pageCoords.y - element.offsetTop\n    }\n}\n\nmodule.exports = {\n    getRelativePosition\n}"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"ipad-cursor\",\n  \"version\": \"0.0.1\",\n  \"description\": \"A web implementation of the new iPadOS cursor in Next.js\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"dev\": \"next\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  },\n  \"keywords\": [\n    \"next.js\",\n    \"next\",\n    \"styled-components\",\n    \"theme\"\n  ],\n  \"author\": \"sdbernhardt@gmail.com\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"autosize\": \"^4.0.2\",\n    \"gsap\": \"^3.2.6\",\n    \"isomorphic-unfetch\": \"^3.0.0\",\n    \"next\": \"^9.3.2\",\n    \"polished\": \"^3.6.0\",\n    \"react\": \"^16.9.0\",\n    \"react-dom\": \"^16.9.0\",\n    \"react-ga\": \"^2.7.0\",\n    \"styled-components\": \"^4.3.2\",\n    \"styled-reset\": \"^4.0.0\",\n    \"use-dark-mode\": \"^2.3.1\"\n  },\n  \"devDependencies\": {\n    \"babel-plugin-styled-components\": \"^1.10.6\"\n  }\n}\n"
  },
  {
    "path": "pages/_app.js",
    "content": "import React from 'react';\nimport App from 'next/app';\n\nimport Providers from '../components/Providers.js';\n\nexport default class MyApp extends App {\n  render () {\n    const { Component, pageProps } = this.props;\n    return (\n      <Providers>\n        <Component {...pageProps} />\n      </Providers>\n    )\n  }\n}"
  },
  {
    "path": "pages/_document.js",
    "content": "import Document from 'next/document'\nimport { ServerStyleSheet } from 'styled-components'\n\nexport default class MyDocument extends Document {\n  static async getInitialProps (ctx) {\n    const sheet = new ServerStyleSheet()\n    const originalRenderPage = ctx.renderPage\n\n    try {\n      ctx.renderPage = () =>\n        originalRenderPage({\n          enhanceApp: App => props => sheet.collectStyles(<App {...props}/>)\n          })\n\n      const initialProps = await Document.getInitialProps(ctx)\n      return {\n        ...initialProps,\n        styles: (\n          <>\n            {initialProps.styles}\n            {sheet.getStyleElement()}\n          </>\n        )\n      }\n    } finally {\n      sheet.seal()\n    }\n  }\n}\n\n"
  },
  {
    "path": "pages/index.js",
    "content": "import styled from 'styled-components';\n\nimport Header from '../components/components/Header';\nimport Hero from '../components/components/Hero';\nimport Footer from '../components/components/Footer';\nimport GoogleAnalytics from \"../components/GoogleAnalytics/layout.js\"\n\nconst Main = styled.div`\n  width: 100%;\n  max-width: 900px;\n  margin: 0 auto;\n  padding: 48px 24px;\n  box-sizing: border-box;\n`;\n\nconst Home = () => {\n  const body = (\n    <Main>\n        <Header />\n        <Hero />\n        <Footer/>\n    </Main>\n  );\n\n  return process.env.google_analytics ? <GoogleAnalytics>{body}</GoogleAnalytics> : body\n};\n\nexport default Home;"
  },
  {
    "path": "pages/test.js",
    "content": "import styled from 'styled-components';\n\nimport WithHover from '../cursor/WithHover';\n\nconst Link = WithHover(styled.div`\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 350px;\n    height: 350px;\n    border-radius: 8px;\n    font-size: 24px;\n    transition-duration: .2s;\n    &:hover {\n        transition-duration: 0s;\n    }\n\n`, 'block', {\n    hoverOffset: 20\n});\n\nconst Main = styled.div`\n  width: 100%;\n  max-width: 900px;\n  margin: 0 auto;\n  padding: 48px 24px;\n  box-sizing: border-box;\n`;\n\nexport default () => (\n    <Main>\n        <Link>Test</Link>\n    </Main>\n)"
  },
  {
    "path": "theme.js",
    "content": "const light = {\n  colors: {\n    background: '#fff',\n    foreground: '#eee',\n    cursor: '#888',\n    body: '#222',\n    black: '#222',\n    purple: '#11144C',\n    red: '#E16262',\n    green: 'rgb(52,199,89)',\n    yellow: '#FABC60',\n    blue: 'rgb(0,122,255)',\n    highlight: '#FABC60',\n  }\n}\n\n\n\n\nconst dark = {\n  colors: {\n    body: '#fff',\n    background: 'black',\n    cursor: '#bbb',\n    foreground: '#222',\n    purple: '#11144C',\n    red: '#E16262',\n    green: 'rgb(48,209,88)',\n    yellow: '#FABC60',\n    blue: 'rgb(10,132,255)',\n    highlight: 'rgb(10,132,255)',\n  }\n}\n\nconst common = {\n  breakpoints: ['40em', '52em', '64em'],\n  fonts: {\n    default: '-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;'\n  },\n  fontSizes: [16, 20, 24, 32, 48, 64],\n  space: [\n    0, 4, 8, 16, 32, 64, 128, 256\n  ]\n}\n\nmodule.exports = {\n  light: {...common, ...light},\n  dark: {...common, ...dark}\n}"
  }
]