{"version":3,"sources":["hooks/use-window-size.tsx","hooks/use-debounce.ts","utils.ts","Loading.tsx","Cursor.tsx","Point.ts","closest.ts","hooks/use-image.tsx","hooks/use-closest-grid-image.tsx","App.tsx","hooks/use-debounced-position.tsx","serviceWorker.ts","index.tsx"],"names":["getSize","x","document","documentElement","clientWidth","y","clientHeight","useWindowSize","useState","windowSize","setWindowSize","useEffect","onResize","window","addEventListener","removeEventListener","useDebounce","value","delay","debouncedValue","setDebouncedValue","handler","setTimeout","undefined","clearTimeout","isMouse","matchMedia","matches","Loading","position","pointing","className","Cursor","style","zIndex","transform","src","width","alt","distancePoints","x1","y1","x2","y2","dividePoints","multiplyPointByNumber","number","multiplyPoints","addPoints","subtractPoints","pointToCSSTransform","type","unit","lastPicked","useClosest","size","absolutePosition","positions","closest","setClosest","index","Number","MAX_VALUE","i","length","pos","distance","includes","unshift","Math","min","bruteClosest","defaultValue","image","status","fetchPositions","a","async","fetch","json","map","useClosestGridImage","setStyle","useAsync","result","imageIndex","pointPosition","setState","createElement","onload","onerror","useImage","origin","resizedImageSize","height","containerWidth","containerHeight","fill","itemRatio","rectRatio","scale","fitSize","translate","adjustment","transformOrigin","App","left","setLeft","setPosition","useMove","useDrag","xy","useDebouncedPosition","bind","mousePosition","filter","key","isLocalhost","Boolean","location","hostname","match","registerValidSW","swUrl","config","navigator","serviceWorker","register","then","registration","onupdatefound","installingWorker","installing","onstatechange","state","controller","console","log","onUpdate","onSuccess","catch","error","ReactDOM","render","getElementById","URL","process","href","headers","response","contentType","get","indexOf","ready","unregister","reload","checkValidServiceWorker"],"mappings":"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","file":"static/js/main.919b6db1.chunk.js","sourcesContent":["import { useState, useEffect } from 'react';\n\nconst getSize = () => ({\n\tx: document.documentElement.clientWidth,\n\ty: document.documentElement.clientHeight,\n});\n\nexport const useWindowSize = () => {\n\tconst [windowSize, setWindowSize] = useState(getSize());\n\n\tuseEffect(() => {\n\t\tconst onResize = () => {\n\t\t\tsetWindowSize(getSize());\n\t\t};\n\n\t\twindow.addEventListener('resize', onResize);\n\t\treturn () => window.removeEventListener('resize', onResize);\n\t}, []);\n\n\treturn windowSize;\n};\n","import { useState, useEffect } from \"react\";\n\nexport const useDebounce = (value: T, delay: number) => {\n const [debouncedValue, setDebouncedValue] = useState();\n\n useEffect(\n () => {\n const handler = setTimeout(() => {\n setDebouncedValue(value);\n }, delay);\n\n return () => {\n setDebouncedValue(undefined);\n clearTimeout(handler);\n };\n },\n [value, delay]\n );\n\n return debouncedValue;\n}","export const isMouse = window.matchMedia('(any-hover: hover)').matches;\n","import React from 'react';\nimport { useDebounce } from './hooks/use-debounce';\nimport { Point } from './Point';\nimport { isMouse } from './utils';\n\nexport const Loading: React.FC<{ position?: Point }> = ({ position }) => {\n const pointing = useDebounce(position, 1200);\n return (\n
\n
\n {!position\n ? isMouse\n ? 'Please move your pointer'\n : 'Please tap on the screen'\n : pointing\n ? 'Pointer located. Pointing...'\n : 'Finding pointer... Please\\u00a0hold\\u00a0still.'}\n
\n
\n );\n};\n","import React from 'react';\nimport { Point } from './Point';\n\nexport const Cursor: React.FC<{ position: Point }> = ({ position }) => (\n \n \"pointer\"\n \n);\n","export type Point = {\n x: number;\n y: number;\n};\n\nexport const distancePoints = (\n { x: x1, y: y1 }: Point,\n { x: x2, y: y2 }: Point\n) => (x1 - x2) ** 2 + (y1 - y2) ** 2;\n\nexport const dividePoints = (\n { x: x1, y: y1 }: Point,\n { x: x2, y: y2 }: Point\n) => ({\n x: x1 / x2,\n y: y1 / y2\n});\n\nexport const dividePointByNumber = ({ x, y }: Point, number: number) => ({\n x: x / number,\n y: y / number\n});\n\nexport const multiplyPointByNumber = ({ x, y }: Point, number: number) => ({\n x: x * number,\n y: y * number\n});\n\nexport const multiplyPoints = (\n { x: x1, y: y1 }: Point,\n { x: x2, y: y2 }: Point\n) => ({\n x: x1 * x2,\n y: y1 * y2\n});\n\nexport const addPoints = (\n { x: x1, y: y1 }: Point,\n { x: x2, y: y2 }: Point\n) => ({\n x: x1 + x2,\n y: y1 + y2\n});\n\nexport const subtractPoints = (\n { x: x1, y: y1 }: Point,\n { x: x2, y: y2 }: Point\n) => ({\n x: x1 - x2,\n y: y1 - y2\n});\n\nexport const remainderPoints = (\n { x: x1, y: y1 }: Point,\n { x: x2, y: y2 }: Point\n) => ({\n x: x1 % x2,\n y: y1 % y2\n});\n\nexport const pointFromSize = ({\n width: x,\n height: y\n}: {\n width: number;\n height: number;\n}) => ({\n x,\n y\n});\n\nexport const pointToCSSTransform = (\n { x, y }: Point,\n type: string,\n unit: string | undefined = 'px'\n) => `${type}(${x}${unit}, ${y}${unit})`;\n\nexport const fitSize = (\n { x: width, y: height }: Point,\n { x: containerWidth, y: containerHeight }: Point,\n fill: boolean | undefined = true\n) => {\n const itemRatio = height / width;\n const rectRatio = containerHeight / containerWidth;\n const scale = (fill\n ? itemRatio > rectRatio\n : itemRatio < rectRatio)\n ? containerWidth / width\n : containerHeight / height;\n return {\n x: width * scale,\n y: height * scale\n };\n};\n","import { Point, distancePoints, dividePoints } from './Point';\nimport { useState, useEffect } from 'react';\n\nconst lastPicked : number[] = [];\n\nconst bruteClosest = (position: Point, positions: Point[]) => {\n let index = undefined;\n let closest = Number.MAX_VALUE;\n for (let i = 0; i < positions.length; i++) {\n const pos = positions[i];\n const distance = distancePoints(pos, position);\n if (distance < closest && !lastPicked.includes(i)) {\n closest = distance;\n index = i;\n };\n }\n lastPicked.unshift(index!);\n lastPicked.length = Math.min(lastPicked.length, 4);\n return index;\n};\n\nexport const useClosest = (\n size: Point,\n absolutePosition?: Point,\n positions?: Point[]\n) => {\n const [closest, setClosest] = useState();\n useEffect(() => {\n if (!absolutePosition || !positions) {\n setClosest(undefined);\n return;\n }\n const position = dividePoints(absolutePosition, size);\n const closest = bruteClosest(position, positions);\n setClosest(closest);\n }, [positions, absolutePosition, size]);\n return [\n closest,\n !!positions && closest !== undefined ? positions[closest] : undefined\n ] as [number | undefined, Point | undefined];\n};\n","import { useState, useEffect } from 'react';\n\ntype ImageLoad = {\n\timage?: HTMLImageElement;\n\tstatus: 'loading' | 'loaded' | 'failed';\n};\n\nconst defaultValue : ImageLoad = { image: undefined, status: 'loading' };\nexport const useImage = (src?: string) => {\n\tconst [{ image, status }, setState] = useState(defaultValue);\n\n\tuseEffect(() => {\n\t\tif (!src) return;\n\t\tconst image = document.createElement('img');\n\n\t\tconst onload = () => {\n\t\t\tsetState({ image, status: 'loaded' });\n\t\t};\n\n\t\tconst onerror = () => {\n\t\t\tsetState({ image: undefined, status: 'failed' });\n\t\t};\n\n\t\timage.addEventListener('load', onload);\n\t\timage.addEventListener('error', onerror);\n\t\timage.src = src;\n\n\t\treturn () => {\n\t\t\timage.removeEventListener('load', onload);\n\t\t\timage.removeEventListener('error', onerror);\n\t\t\tsetState(defaultValue);\n\t\t};\n\t}, [src]);\n\n\treturn [image, status] as [HTMLImageElement | undefined, 'loading' | 'loaded' | 'failed'];\n};\n","import { CSSProperties, useEffect, useState } from 'react';\n\nimport {\n Point,\n multiplyPoints,\n pointFromSize,\n dividePoints,\n subtractPoints,\n multiplyPointByNumber,\n pointToCSSTransform,\n addPoints,\n fitSize\n} from '../Point';\nimport { useAsync } from 'react-async-hook';\nimport { useClosest } from '../closest';\nimport { useImage } from './use-image';\nimport { useWindowSize } from './use-window-size';\n\nconst fetchPositions = async (): Promise =>\n ((await (await fetch(`/new-positions.json`)).json()) as [\n number,\n number\n ][]).map(([x, y]) => ({ x, y }));\n\nexport const useClosestGridImage = (absolutePosition?: Point) => {\n const [style, setStyle] = useState();\n const windowSize = useWindowSize();\n const { result: positions } = useAsync(fetchPositions, []);\n\n const [imageIndex, pointPosition] = useClosest(\n windowSize,\n absolutePosition,\n positions\n );\n const image = useImage(\n imageIndex !== undefined ? `/images/${imageIndex}.jpg` : undefined\n )[0];\n useEffect(() => {\n if (!image || !absolutePosition || !pointPosition) {\n setStyle(undefined);\n return;\n }\n const position = dividePoints(absolutePosition, windowSize);\n const origin = multiplyPointByNumber(pointPosition, 100);\n const imageSize = pointFromSize(image);\n const resizedImageSize = fitSize(imageSize, windowSize);\n const translate = multiplyPointByNumber(\n multiplyPoints(subtractPoints(resizedImageSize, windowSize), position),\n -1\n );\n const adjustment = multiplyPoints(\n subtractPoints(position, pointPosition),\n resizedImageSize\n );\n setStyle({\n width: `${resizedImageSize.x}px`,\n height: `${resizedImageSize.y}px`,\n transform: translate\n ? `${pointToCSSTransform(\n addPoints(translate, adjustment),\n 'translate',\n 'px'\n )} scale(1.2)`\n : undefined,\n transformOrigin: `${origin.x}% ${origin.y}%`\n });\n }, [windowSize, pointPosition, image, absolutePosition]);\n return [image, style] as [typeof image, typeof style];\n};\n","import React from 'react';\n\nimport './App.css';\nimport { useWindowSize } from './hooks/use-window-size';\nimport { Loading } from './Loading';\nimport { Cursor } from './Cursor';\nimport { useDebouncedPosition } from './hooks/use-debounced-position';\nimport { useClosestGridImage } from './hooks/use-closest-grid-image';\nimport { isMouse } from './utils';\n\nconst App: React.FC = () => {\n const windowSize = useWindowSize();\n\n const [bind, position, mousePosition] = useDebouncedPosition();\n const [image, style] = useClosestGridImage(position);\n return (\n <>\n \n \n {!isMouse && mousePosition ? : null}\n {image ? (\n <>\n
\n \n
\n
\n \n
\n \n ) : (\n \n )}\n \n \n );\n};\n\nexport default App;\n","import { useState, useEffect } from \"react\";\nimport { Point } from \"../Point\";\nimport { isMouse } from \"../utils\";\nimport { useMove, useDrag } from \"react-use-gesture\";\nimport { useDebounce } from \"./use-debounce\";\n\nexport const useDebouncedPosition = () => {\n const [left, setLeft] = useState(false);\n const [position, setPosition] = useState();\n\n useEffect(() => {\n document.addEventListener('mouseleave', () => setLeft(true));\n document.addEventListener('mouseenter', () => setLeft(false));\n }, []);\n\n const bind = (isMouse ? useMove : useDrag)(({ xy: [x, y] }) => {\n setPosition({ x: x, y });\n });\n const debouncedPosition = useDebounce(position, 2000);\n return [bind, debouncedPosition, !left ? position : undefined] as [\n typeof bind,\n typeof debouncedPosition,\n typeof position\n ];\n};\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.0/8 are considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\ntype Config = {\n onSuccess?: (registration: ServiceWorkerRegistration) => void;\n onUpdate?: (registration: ServiceWorkerRegistration) => void;\n};\n\nexport function register(config?: Config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(\n process.env.PUBLIC_URL,\n window.location.href\n );\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl: string, config?: Config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl: string, config?: Config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl, {\n headers: { 'Service-Worker': 'script' }\n })\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(, document.getElementById('root'));\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.register();\n"],"sourceRoot":""}