├── frontend ├── global.d.ts ├── src │ ├── pages │ │ ├── index.tsx │ │ ├── examples │ │ │ └── 1.tsx │ │ ├── 404.tsx │ │ ├── _error.tsx │ │ ├── _app.tsx │ │ └── _document.tsx │ ├── utils │ │ ├── functions │ │ │ ├── delay.ts │ │ │ ├── clamp.ts │ │ │ ├── mix.ts │ │ │ ├── lerp.ts │ │ │ ├── detectDevice.ts │ │ │ ├── isTouchDevice.ts │ │ │ ├── getRand.ts │ │ │ ├── getScrollbarWidth.ts │ │ │ ├── setCssVariables.ts │ │ │ └── seedRandom.ts │ │ ├── GlobalStyles.ts │ │ ├── media.ts │ │ ├── sharedTypes.ts │ │ ├── sharedValues.ts │ │ └── sharedStyled.ts │ ├── styles │ │ ├── components │ │ │ ├── measure.scss │ │ │ └── canvas.scss │ │ ├── index.scss │ │ └── base │ │ │ ├── fonts.scss │ │ │ ├── reset.scss │ │ │ └── global.scss │ ├── containers │ │ ├── ErrorPage │ │ │ └── ErrorPage.tsx │ │ ├── IndexPage │ │ │ ├── IndexPage.styles.ts │ │ │ └── IndexPage.tsx │ │ └── Examples │ │ │ └── 1 │ │ │ ├── ExamplePage.tsx │ │ │ ├── ExamplePage.styles.ts │ │ │ └── ExamplePage.data.ts │ ├── components │ │ ├── Caption │ │ │ ├── Caption.state.ts │ │ │ ├── coverBackgroundClasses │ │ │ │ ├── Components │ │ │ │ │ └── BackgroundSketch.ts │ │ │ │ └── App.ts │ │ │ ├── backgroundClasses │ │ │ │ ├── Components │ │ │ │ │ └── BackgroundSketch.ts │ │ │ │ └── App.ts │ │ │ ├── Caption.styles.ts │ │ │ ├── Caption.tsx │ │ │ └── classes │ │ │ │ ├── Components │ │ │ │ └── TextSketch.ts │ │ │ │ └── App.ts │ │ ├── PreloadImage │ │ │ ├── PreloadImage.tsx │ │ │ └── PreloadImage.styles.ts │ │ ├── Layout │ │ │ ├── Layout.styles.ts │ │ │ └── Layout.tsx │ │ ├── CodeRenderer │ │ │ ├── CodeRenderer.tsx │ │ │ └── CodeRenderer.styles.ts │ │ ├── LinkHandler │ │ │ └── LinkHandler.tsx │ │ └── GameTile │ │ │ ├── GameTile.styles.ts │ │ │ └── GameTile.tsx │ ├── sections │ │ ├── ShowOff │ │ │ ├── images │ │ │ │ ├── shape4.svg │ │ │ │ ├── shape5.svg │ │ │ │ ├── shape7.svg │ │ │ │ ├── shape2.svg │ │ │ │ ├── shape3.svg │ │ │ │ ├── shape1.svg │ │ │ │ ├── shape6.svg │ │ │ │ ├── shape8.svg │ │ │ │ └── shape9.svg │ │ │ ├── ShowOff.styles.ts │ │ │ └── ShowOff.tsx │ │ ├── CopyInfo │ │ │ ├── CopyInfo.tsx │ │ │ ├── CopyInfo.styles.ts │ │ │ └── images │ │ │ │ └── logo.svg │ │ └── DocsInfo │ │ │ ├── DocsInfo.styles.ts │ │ │ └── DocsInfo.tsx │ ├── seo │ │ ├── GoogleAnalytics │ │ │ └── GoogleAnalytics.tsx │ │ └── Head │ │ │ └── Head.tsx │ └── hooks │ │ ├── useWindowSize.ts │ │ ├── useMediaPreload.ts │ │ └── useElementSize.ts ├── public │ ├── favicon.ico │ ├── fonts │ │ ├── teko700.woff2 │ │ ├── openSans400.woff │ │ └── openSans800.woff2 │ └── vercel.svg ├── .eslintignore ├── .prettierrc.js ├── next-env.d.ts ├── next.config.js ├── .gitignore ├── tsconfig.json ├── README.md ├── .eslintrc.js ├── LICENSE └── package.json ├── react-just-parallax ├── .gitignore ├── src │ ├── utils │ │ ├── lerp.ts │ │ ├── isTouchDevice.ts │ │ ├── getScrollOffsets.ts │ │ ├── EventDispatcher.js │ │ ├── EventDispatcher.d.ts │ │ └── MouseMove.ts │ ├── index.ts │ ├── hooks │ │ └── useWindowSize.ts │ └── components │ │ ├── ScrollParallax │ │ └── ScrollParallax.tsx │ │ └── MouseParallax │ │ └── MouseParallax.tsx ├── declarations.d.ts ├── tsconfig.json ├── rollup.config.js ├── package.json └── README.md ├── cra-for-testing ├── src │ ├── react-app-env.d.ts │ ├── setupTests.ts │ ├── App.test.tsx │ ├── index.css │ ├── reportWebVitals.ts │ ├── index.tsx │ ├── logo.svg │ ├── App.css │ └── App.tsx ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── .gitignore ├── tsconfig.json ├── package.json └── README.md ├── .vscode ├── settings.json └── mySnippets.code-snippets └── README.md /frontend/global.d.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /react-just-parallax/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /cra-for-testing/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /frontend/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from 'containers/IndexPage/IndexPage'; 2 | -------------------------------------------------------------------------------- /cra-for-testing/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michalzalobny/react-just-parallax/HEAD/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/src/utils/functions/delay.ts: -------------------------------------------------------------------------------- 1 | export const delay = (time: number) => new Promise(res => setTimeout(res, time)); 2 | -------------------------------------------------------------------------------- /cra-for-testing/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michalzalobny/react-just-parallax/HEAD/cra-for-testing/public/favicon.ico -------------------------------------------------------------------------------- /cra-for-testing/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michalzalobny/react-just-parallax/HEAD/cra-for-testing/public/logo192.png -------------------------------------------------------------------------------- /cra-for-testing/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michalzalobny/react-just-parallax/HEAD/cra-for-testing/public/logo512.png -------------------------------------------------------------------------------- /frontend/src/utils/functions/clamp.ts: -------------------------------------------------------------------------------- 1 | export const clamp = (value: number) => { 2 | return Math.min(1, Math.max(0, value)); 3 | }; 4 | -------------------------------------------------------------------------------- /frontend/src/utils/functions/mix.ts: -------------------------------------------------------------------------------- 1 | export const mix = (a: number, b: number, t: number) => { 2 | return a * (1 - t) + t * b; 3 | }; 4 | -------------------------------------------------------------------------------- /frontend/public/fonts/teko700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michalzalobny/react-just-parallax/HEAD/frontend/public/fonts/teko700.woff2 -------------------------------------------------------------------------------- /frontend/src/utils/functions/lerp.ts: -------------------------------------------------------------------------------- 1 | export const lerp = (p1: number, p2: number, t: number) => { 2 | return p1 + (p2 - p1) * t; 3 | }; 4 | -------------------------------------------------------------------------------- /react-just-parallax/src/utils/lerp.ts: -------------------------------------------------------------------------------- 1 | export const lerp = (p1: number, p2: number, t: number) => { 2 | return p1 + (p2 - p1) * t; 3 | }; 4 | -------------------------------------------------------------------------------- /frontend/public/fonts/openSans400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michalzalobny/react-just-parallax/HEAD/frontend/public/fonts/openSans400.woff -------------------------------------------------------------------------------- /frontend/public/fonts/openSans800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michalzalobny/react-just-parallax/HEAD/frontend/public/fonts/openSans800.woff2 -------------------------------------------------------------------------------- /frontend/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | .next -------------------------------------------------------------------------------- /frontend/src/pages/examples/1.tsx: -------------------------------------------------------------------------------- 1 | export { default } from 'containers/Examples/1/ExamplePage'; 2 | export { getStaticProps } from 'containers/Examples/1/ExamplePage.data'; 3 | -------------------------------------------------------------------------------- /frontend/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require('./node_modules/gts/.prettierrc.json'), 3 | bracketSpacing: true, 4 | endOfLine: 'auto', 5 | printWidth: 100, 6 | }; 7 | -------------------------------------------------------------------------------- /frontend/src/styles/components/measure.scss: -------------------------------------------------------------------------------- 1 | .scrollbar-measure { 2 | width: 100px; 3 | height: 100px; 4 | overflow: scroll; 5 | position: absolute; 6 | top: -9999px; 7 | } 8 | -------------------------------------------------------------------------------- /react-just-parallax/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module "prefix" { 2 | export default function prefix(action: string): string; 3 | export default function prefix(action: "transform"): "transform"; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/src/utils/functions/detectDevice.ts: -------------------------------------------------------------------------------- 1 | export const isIosMobile = () => { 2 | const userAgent = window.navigator.userAgent; 3 | return userAgent.match(/iPad/i) || userAgent.match(/iPhone/i); 4 | }; 5 | -------------------------------------------------------------------------------- /frontend/src/styles/index.scss: -------------------------------------------------------------------------------- 1 | @import './base/fonts.scss'; 2 | @import './base/reset.scss'; 3 | @import './base/global.scss'; 4 | 5 | @import './components/measure.scss'; 6 | @import './components/canvas.scss'; 7 | -------------------------------------------------------------------------------- /frontend/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /frontend/src/styles/components/canvas.scss: -------------------------------------------------------------------------------- 1 | .canvas { 2 | &__wrapper { 3 | width: 100%; 4 | height: 100%; 5 | position: fixed; 6 | top: 0; 7 | left: 0; 8 | z-index: -1; 9 | user-select: none; 10 | pointer-events: none; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /cra-for-testing/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /frontend/src/utils/functions/isTouchDevice.ts: -------------------------------------------------------------------------------- 1 | export const isBrowser = () => typeof window !== 'undefined'; 2 | export const isTouchDevice = () => 3 | isBrowser() && 4 | ('ontouchstart' in window || 5 | 'ontouchstart' in document.documentElement || 6 | navigator.maxTouchPoints > 0); 7 | -------------------------------------------------------------------------------- /react-just-parallax/src/utils/isTouchDevice.ts: -------------------------------------------------------------------------------- 1 | export const isBrowser = () => typeof window !== "undefined"; 2 | export const isTouchDevice = () => 3 | isBrowser() && 4 | ("ontouchstart" in window || 5 | "ontouchstart" in document.documentElement || 6 | navigator.maxTouchPoints > 0); 7 | -------------------------------------------------------------------------------- /frontend/src/pages/404.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { useRouter } from 'next/router'; 3 | 4 | export default function Error404() { 5 | const router = useRouter(); 6 | 7 | useEffect(() => { 8 | void router.push('/'); 9 | }, [router]); 10 | 11 | return null; 12 | } 13 | -------------------------------------------------------------------------------- /cra-for-testing/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /react-just-parallax/src/index.ts: -------------------------------------------------------------------------------- 1 | // Setup based on: https://dev.to/siddharthvenkatesh/component-library-setup-with-react-typescript-and-rollup-onj 2 | 3 | export { MouseParallax } from "./components/MouseParallax/MouseParallax"; 4 | export { 5 | ScrollParallax, 6 | ScrollParallaxHandle, 7 | } from "./components/ScrollParallax/ScrollParallax"; 8 | -------------------------------------------------------------------------------- /frontend/src/utils/functions/getRand.ts: -------------------------------------------------------------------------------- 1 | export const getRandInt = (minimum: number, maximum: number): number => { 2 | return Math.floor(Math.random() * (maximum - minimum + 1)) + minimum; 3 | }; 4 | 5 | export const getRandFloat = (minimum: number, maximum: number): number => { 6 | return Math.random() * (maximum - minimum + 1) + minimum; 7 | }; 8 | -------------------------------------------------------------------------------- /frontend/src/utils/GlobalStyles.ts: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from 'styled-components'; 2 | 3 | import { media } from 'utils/media'; 4 | 5 | export const GlobalStyles = createGlobalStyle` 6 | html { 7 | font-size: calc(100vw / 375 * 10); 8 | 9 | ${media.tablet}{ 10 | font-size: calc(100vw / 1920 * 10); 11 | } 12 | 13 | ${media.desktop}{ 14 | font-size: 62.5%; 15 | } 16 | } 17 | `; 18 | -------------------------------------------------------------------------------- /cra-for-testing/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /frontend/src/containers/ErrorPage/ErrorPage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | interface ErrorPageProps { 4 | statusCode: number; 5 | } 6 | 7 | export default function ErrorPage(props: ErrorPageProps) { 8 | const { statusCode } = props; 9 | return ( 10 | <> 11 |
12 |

Something went wrong {`| ${statusCode || 'undefined code'}`}

13 |
14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/utils/functions/getScrollbarWidth.ts: -------------------------------------------------------------------------------- 1 | export const getScrollbarWidth = () => { 2 | // Create the div 3 | const scrollDiv = document.createElement('div'); 4 | scrollDiv.className = 'scrollbar-measure'; 5 | document.body.appendChild(scrollDiv); 6 | // Get the scrollbar width 7 | const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; 8 | // Delete the div 9 | document.body.removeChild(scrollDiv); 10 | return scrollbarWidth; 11 | }; 12 | -------------------------------------------------------------------------------- /frontend/src/utils/media.ts: -------------------------------------------------------------------------------- 1 | export const breakpoints = { 2 | tablet: 767, 3 | tabletLand: 992, 4 | desktop: 1920, 5 | }; 6 | 7 | const customMediaQuery = (minWidth: number) => 8 | `@media only screen and (min-width: ${minWidth / 16}em)`; 9 | 10 | export const media = { 11 | custom: customMediaQuery, 12 | tablet: customMediaQuery(breakpoints.tablet), 13 | tabletLand: customMediaQuery(breakpoints.tabletLand), 14 | desktop: customMediaQuery(breakpoints.desktop), 15 | }; 16 | -------------------------------------------------------------------------------- /frontend/src/components/Caption/Caption.state.ts: -------------------------------------------------------------------------------- 1 | import { App } from './classes/App'; 2 | import * as Background from './backgroundClasses/App'; 3 | import * as CoverBackground from './coverBackgroundClasses/App'; 4 | 5 | interface AppState { 6 | app: App | null; 7 | background: Background.App | null; 8 | coverBackground: CoverBackground.App | null; 9 | } 10 | 11 | export const appState: AppState = { 12 | app: null, 13 | background: null, 14 | coverBackground: null, 15 | }; 16 | -------------------------------------------------------------------------------- /cra-for-testing/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | 15 | h2, 16 | h3 { 17 | margin: 0; 18 | } 19 | -------------------------------------------------------------------------------- /cra-for-testing/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /frontend/src/utils/functions/setCssVariables.ts: -------------------------------------------------------------------------------- 1 | export const VARIABLES = [ 2 | { 3 | name: '--transition-duration', 4 | value: '100' + 'ms', 5 | }, 6 | ]; 7 | 8 | interface SetCssVariables { 9 | variables: typeof VARIABLES; 10 | } 11 | 12 | export const setCssVariables = ({ variables }: SetCssVariables) => { 13 | const root = document.documentElement; 14 | 15 | for (let i = 0; i < variables.length; i++) { 16 | const el = variables[i]; 17 | root.style.setProperty(el.name, el.value); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /frontend/src/sections/ShowOff/images/shape4.svg: -------------------------------------------------------------------------------- 1 | shape4 -------------------------------------------------------------------------------- /frontend/src/sections/ShowOff/images/shape5.svg: -------------------------------------------------------------------------------- 1 | shape5 -------------------------------------------------------------------------------- /frontend/src/sections/ShowOff/images/shape7.svg: -------------------------------------------------------------------------------- 1 | shape7 -------------------------------------------------------------------------------- /frontend/src/sections/ShowOff/images/shape2.svg: -------------------------------------------------------------------------------- 1 | shape2 -------------------------------------------------------------------------------- /frontend/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | 3 | const withPlugins = require('next-compose-plugins'); 4 | const withOptimizedImages = require('next-optimized-images'); 5 | 6 | const nextConfig = { 7 | reactStrictMode: true, 8 | i18n: { 9 | locales: ['en-US'], 10 | defaultLocale: 'en-US', 11 | }, 12 | compiler: { 13 | // ssr and displayName are configured by default 14 | styledComponents: true, 15 | }, 16 | webpack: config => { 17 | return config; 18 | }, 19 | }; 20 | 21 | module.exports = withPlugins([[withOptimizedImages]], nextConfig); 22 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | # typescript 37 | *.tsbuildinfo 38 | -------------------------------------------------------------------------------- /frontend/src/styles/base/fonts.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'teko'; 3 | font-weight: 700; 4 | font-style: normal; 5 | font-display: swap; 6 | src: url('/fonts/teko700.woff2') format('woff2'); 7 | } 8 | 9 | @font-face { 10 | font-family: 'opensans'; 11 | font-style: normal; 12 | font-weight: normal; 13 | font-display: swap; 14 | src: url('/fonts/openSans400.woff') format('woff'); 15 | } 16 | 17 | @font-face { 18 | font-family: 'opensans'; 19 | font-weight: 800; 20 | font-style: normal; 21 | font-display: swap; 22 | src: url('/fonts/openSans800.woff2') format('woff2'); 23 | } 24 | -------------------------------------------------------------------------------- /react-just-parallax/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | "target": "es6", 6 | "module": "esnext", 7 | "jsx": "react", 8 | "declaration": true, 9 | "declarationDir": "types", 10 | "sourceMap": true, 11 | "outDir": "dist", 12 | "strict": true, 13 | "moduleResolution": "node", 14 | "allowSyntheticDefaultImports": true, 15 | "esModuleInterop": true, 16 | "skipLibCheck": true, 17 | "forceConsistentCasingInFileNames": true, 18 | "emitDeclarationOnly": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /cra-for-testing/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /frontend/src/pages/_error.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { NextApiResponse } from 'next'; 3 | 4 | import ErrorPage from 'containers/ErrorPage/ErrorPage'; 5 | 6 | interface ErrorProps { 7 | res?: NextApiResponse; 8 | err?: NextApiResponse; 9 | } 10 | 11 | interface Error { 12 | statusCode: number; 13 | } 14 | 15 | export default function ErrorServer({ statusCode }: Error) { 16 | return ; 17 | } 18 | 19 | ErrorServer.getInitialProps = ({ res, err }: ErrorProps) => { 20 | const statusCode = res ? res.statusCode : err ? err.statusCode : 404; 21 | return { statusCode }; 22 | }; 23 | -------------------------------------------------------------------------------- /cra-for-testing/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot( 8 | document.getElementById('root') as HTMLElement 9 | ); 10 | root.render( 11 | 12 | 13 | 14 | ); 15 | 16 | // If you want to start measuring performance in your app, pass a function 17 | // to log results (for example: reportWebVitals(console.log)) 18 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 19 | reportWebVitals(); 20 | -------------------------------------------------------------------------------- /cra-for-testing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /frontend/src/components/PreloadImage/PreloadImage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { useMediaPreload } from 'hooks/useMediaPreload'; 4 | 5 | import * as S from './PreloadImage.styles'; 6 | 7 | interface Props { 8 | imageSrc: string; 9 | alt: string; 10 | shouldContain?: boolean; 11 | } 12 | 13 | export const PreloadImage = (props: Props) => { 14 | const { shouldContain = false, alt, imageSrc } = props; 15 | 16 | const { isLoaded } = useMediaPreload({ isImage: true, mediaSrc: imageSrc }); 17 | 18 | return ( 19 | <> 20 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.codeActionsOnSave": { 3 | "source.fixAll.eslint": true 4 | }, 5 | "editor.formatOnSave": true, 6 | "eslint.alwaysShowStatus": true, 7 | "editor.fontSize": 20, 8 | "emmet.includeLanguages": { 9 | "javascript": "javascriptreact" 10 | }, 11 | "html.format.wrapAttributes": "force-aligned", 12 | "editor.tabSize": 2, 13 | "workbench.editor.labelFormat": "short", 14 | "editor.defaultFormatter": "esbenp.prettier-vscode", 15 | "explorer.confirmDelete": false 16 | } 17 | // Installed extensions : "eslint, prettier ,bracketPairColorizer, GitLens, vscode-styled-components, indent-rainbow, path intellisense" 18 | // Installed git bash 19 | -------------------------------------------------------------------------------- /frontend/src/components/Layout/Layout.styles.ts: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | import { sharedValues } from 'utils/sharedValues'; 4 | 5 | interface ReadyWrapperProps { 6 | isReady: boolean; 7 | } 8 | 9 | export const ReadyWrapper = styled.div` 10 | position: fixed; 11 | top: 0; 12 | left: 0; 13 | width: 100%; 14 | height: 100%; 15 | z-index: 100; 16 | opacity: 1; 17 | transition: opacity 0.5s ease-in-out; 18 | background-color: ${sharedValues.colors.trueWhite}; 19 | 20 | ${props => 21 | props.isReady && 22 | css` 23 | opacity: 0; 24 | user-select: none; 25 | pointer-events: none; 26 | `} 27 | `; 28 | -------------------------------------------------------------------------------- /frontend/src/components/PreloadImage/PreloadImage.styles.ts: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | interface ImageProps { 4 | isLoaded: boolean; 5 | shouldContain: boolean; 6 | } 7 | 8 | export const Image = styled.img` 9 | position: absolute; 10 | top: 0; 11 | left: 0; 12 | width: 100%; 13 | height: 100%; 14 | object-fit: cover; 15 | opacity: 0; 16 | transition: opacity 0.45s; 17 | user-select: none; 18 | pointer-events: none; 19 | 20 | ${props => 21 | props.shouldContain && 22 | css` 23 | object-fit: contain; 24 | `} 25 | 26 | ${props => 27 | props.isLoaded && 28 | css` 29 | opacity: 1; 30 | `} 31 | `; 32 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/gts/tsconfig-google.json", 3 | "compilerOptions": { 4 | "target": "es2020", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "esModuleInterop": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "jsx": "preserve", 17 | "baseUrl": "src", 18 | "incremental": true 19 | }, 20 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 21 | "exclude": ["node_modules"] 22 | } 23 | -------------------------------------------------------------------------------- /frontend/src/seo/GoogleAnalytics/GoogleAnalytics.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const GoogleAnalytics = () => { 4 | const googleAnalyticsTag = process.env.NEXT_PUBLIC_GA_KEY as string; 5 | return ( 6 | <> 7 |