diff --git a/.gitignore b/.gitignore index 9db8149..33522c8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,10 +5,17 @@ app/node_modules app-next/node_modules api/node_modules -/node_modules +node_modules localhost-key.pem localhost.pem yarn-error.log +pnpm-lock.yaml + +build/* +public/build/* +api/index.js +api/index.js.map + pnpm-lock.yaml \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..b390705 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "endOfLine": "lf", + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "useTabs": false, + "trailingComma": "none", + "printWidth": 150, + "singleAttributePerLine": false, + "arrowParens": "always", + "plugins": [] +} diff --git a/app/.eslintrc.js b/app/.eslintrc.js deleted file mode 100644 index 3b51f1b..0000000 --- a/app/.eslintrc.js +++ /dev/null @@ -1,96 +0,0 @@ -module.exports = { - parser: "@typescript-eslint/parser", - parserOptions: { - ecmaVersion: 2020, - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, - }, - env: { - browser: true, - node: true, - es6: true, - }, - settings: { - react: { - version: "detect", - }, - }, - plugins: [ - "@typescript-eslint", - "react", - // "unused-imports", - "prettier", - "simple-import-sort", - "chakra-ui", - ], - extends: [ - "@remix-run/eslint-config", - "eslint:recommended", - "plugin:react/recommended", - "plugin:react-hooks/recommended", - "plugin:@typescript-eslint/recommended", - ], - rules: { - "react/jsx-curly-brace-presence": [ - "error", - { props: "never", children: "never" }, - ], - "direct-eval/direct-eval": "off", - "no-eval": "off", - "no-async-promise-executor": "off", - "react/prop-types": "off", - "react/display-name": "off", - "@typescript-eslint/ban-ts-comment": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/no-unused-vars": "off", - // "unused-imports/no-unused-imports": "error", - // "unused-imports/no-unused-vars": "error", - "react/react-in-jsx-scope": "off", - "chakra-ui/props-order": "error", - "chakra-ui/props-shorthand": [ - "error", - { - noShorthand: true, - applyToAllComponents: true, - }, - ], - "chakra-ui/require-specific-component": "error", - "prettier/prettier": [ - "error", - { - semi: false, - singleQuote: false, - parser: "typescript", - bracketSpacing: true, - }, - ], - "simple-import-sort/imports": [ - "error", - { - groups: [ - // Packages `react` related packages come first. - ["^react", "^@?\\w"], - // Internal packages. - ["^(@root)(/.*|$)"], - ["^(@app)(/.*|$)"], - // Side effect imports. - ["^\\u0000"], - // Other relative imports. Put same-folder imports and `.` last. - ["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"], - ], - }, - ], - }, - overrides: [ - { - files: ["*.js"], - rules: { - "@typescript-eslint/no-var-requires": "off", - }, - }, - ], -} diff --git a/app/.gitignore b/app/.gitignore index 5d6a175..b293477 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -5,7 +5,9 @@ node_modules .vercel .output -/build/ -/public/build -/api/index.js -/api/index.js.map +build/* +public/build/* +api/index.js +api/index.js.map + +pnpm-lock.yaml \ No newline at end of file diff --git a/app/.prettierrc b/app/.prettierrc new file mode 100644 index 0000000..b390705 --- /dev/null +++ b/app/.prettierrc @@ -0,0 +1,12 @@ +{ + "endOfLine": "lf", + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "useTabs": false, + "trailingComma": "none", + "printWidth": 150, + "singleAttributePerLine": false, + "arrowParens": "always", + "plugins": [] +} diff --git a/app/app/Providers/Chakra/ChakraWrapper.tsx b/app/app/Providers/Chakra/ChakraWrapper.tsx deleted file mode 100644 index 4f9c2d4..0000000 --- a/app/app/Providers/Chakra/ChakraWrapper.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { ChakraProvider } from '@chakra-ui/react' -import { theme } from './theme' -export const ChakraWrapper = props => { - return {props.children} -} diff --git a/app/app/components/Buttons/Attention.tsx b/app/app/components/Buttons/Attention.tsx deleted file mode 100644 index 9b19ace..0000000 --- a/app/app/components/Buttons/Attention.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react' -import { Flex } from '@chakra-ui/react' - -export const Attention = props => { - return ( - - - - ) -} diff --git a/app/app/components/Buttons/Hamburger.tsx b/app/app/components/Buttons/Hamburger.tsx deleted file mode 100644 index c8a60ba..0000000 --- a/app/app/components/Buttons/Hamburger.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react' -import { Flex } from '@chakra-ui/react' - -export const Hamburger = props => { - const lineCount = [1, 2, 3] - - return ( - - {lineCount.map((line, idx) => { - return ( - - ) - })} - - ) -} diff --git a/app/app/components/Icon/Icon.tsx b/app/app/components/Icon/Icon.tsx deleted file mode 100644 index e21b0b9..0000000 --- a/app/app/components/Icon/Icon.tsx +++ /dev/null @@ -1,225 +0,0 @@ -import React from "react" -import { Center } from "@chakra-ui/react" -import emojis from "emojis-list" - -export const Icon = (props) => { - const name = props?.name - - const icon = React.useMemo(() => { - // nothing - if (["gear", "cog"]?.includes(name)) { - return "⚙️" - } - if (["crystal"]?.includes(name)) { - return "🔮" - } - if (["flower", "hibiscus"]?.includes(name)) { - return "🌺" - } - if (["sparke", "magic"]?.includes(name)) { - return "✨" - } - if (["wizard", "gandalf"]?.includes(name)) { - return "🧙‍♂️" - } - if (["two eyes"]?.includes(name)) { - return "👀" - } - if (["box", "thing", "object"]?.includes(name)) { - return "📦" - } - if (["pencil"]?.includes(name)) { - return "✏️" - } - if (["edit", "paint", "create"]?.includes(name)) { - return "🎨" - } - if (["book", "books"]?.includes(name)) { - return "📚" - } - if (["any", "magic wand"]?.includes(name)) { - return "🪄" - } - if (["book-open", "books-open"]?.includes(name)) { - return "📖" - } - if (["book-reader", "books-reader"]?.includes(name)) { - return "👩‍🏫" - } - if (["number", "hundred"]?.includes(name)) { - return "💯" - } - if (["puzzle", "types"]?.includes(name)) { - return "🧩" - } - if (["heart"]?.includes(name)) { - return "❤️" - } - if (["heart-broken"]?.includes(name)) { - return "💔" - } - if (["heart-pulse"]?.includes(name)) { - return "💗" - } - if (["string", "text"]?.includes(name)) { - return "💬" - } - if (["array", "list"]?.includes(name)) { - return "📚" - } - if (["boolean", "bool"]?.includes(name)) { - return "🌗" - // return "⚖️" - } - if (["rainbow"]?.includes(name)) { - return "🌈" - } - if (["sun"]?.includes(name)) { - return "☀️" - } - if (["moon"]?.includes(name)) { - return "🌙" - } - if (["unicorn"]?.includes(name)) { - return "🦄" - } - if (["user", "person"]?.includes(name)) { - return "👤" - } - if (["group", "team"]?.includes(name)) { - return "👥" - } - if (["success", "check"]?.includes(name)) { - return "✅" - } - if (["error", "stop"]?.includes(name)) { - return "❌" - } - if (["warning", "alert"]?.includes(name)) { - return "⚠️" - } - if (["time", "clock"]?.includes(name)) { - return "⏰" - } - if (["star", "favorite"]?.includes(name)) { - return "⭐" - } - if (["glowing star", "glowing favorite"]?.includes(name)) { - return "🌟" - } - if (["question", "help"]?.includes(name)) { - return "❓" - } - if (["video", "media"]?.includes(name)) { - return "🎥" - } - if (["music", "audio"]?.includes(name)) { - return "🎵" - } - if (["image", "picture"]?.includes(name)) { - return "🖼️" - } - if (["email", "mail"]?.includes(name)) { - return "✉️" - } - if (["computer", "laptop"]?.includes(name)) { - return "💻" - } - if (["mobile", "phone"]?.includes(name)) { - return "📱" - } - if (["world", "globe"]?.includes(name)) { - return "🌍" - } - if (["rocket", "launch"]?.includes(name)) { - return "🚀" - } - if (["pencil", "edit"]?.includes(name)) { - return "✏️" - } - if (["search", "magnify"]?.includes(name)) { - return "🔍" - } - if (["lock", "secure"]?.includes(name)) { - return "🔒" - } - if (["unlock", "access"]?.includes(name)) { - return "🔓" - } - if (["thumb-up", "like"]?.includes(name)) { - return "👍" - } - if (["thumb-down", "dislike"]?.includes(name)) { - return "👎" - } - if (["plus", "add"]?.includes(name)) { - return "➕" - } - if (["seedling", "seed"]?.includes(name)) { - return "🌱" - } - if (["undefined", "null", "question", "confused"]?.includes(name)) { - return "❓" - // return "🌫️" - } - if (["codex", "robot", "ai", "chatgpt"]?.includes(name)) { - return "🤖" - } - if (["trash", "bin", "delete", "remove"]?.includes(name)) { - return "🗑️" - } - if (["cash", "money"]?.includes(name)) { - // return "💰" - return "💵" - } - if (["money bag"]?.includes(name)) { - return "💰" - } - if (["cyclone", "tornado"]?.includes(name)) { - return "🌀" - } - if (["thingtime"]?.includes(name)) { - if (Math.random() > 0.5) { - return "🌳" - } - return "🌀" - } - if (["function", "lambda"]?.includes(name)) { - return "📐" - } - if (["pin", "pinned", "located"]?.includes(name)) { - return "📌" - } - - if (["wrap", "wrapped"]?.includes(name)) { - return "🎁" - // return "🎀" - } - - if (["dinosaur", "dino"]?.includes(name)) { - return "🦕" - } - - if (emojis?.includes(name)) { - return name - } - - if (["random"]?.includes(name)) { - return emojis[Math.floor(Math.random() * emojis.length)] - } - - // question mark - return "❓" - }, [name]) - - return ( -
- {icon} -
- ) -} diff --git a/app/app/components/Login/Login.tsx b/app/app/components/Login/Login.tsx deleted file mode 100644 index 0d08151..0000000 --- a/app/app/components/Login/Login.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React, { useState } from "react" -import { Flex, FormControl, Input } from "@chakra-ui/react" - -export const Login = (props) => { - const [email, setEmail] = useState("") - const [password, setPassword] = useState("") - - const handleLogin = () => { - // handle login - } - - return ( - <> - - - setEmail(e.target.value)} - placeholder="Email" - type="email" - value={email} - /> - - - - setPassword(e.target.value)} - placeholder="Password" - type="password" - value={password} - /> - - - - Login - - - - ) -} diff --git a/app/app/components/Nav/ReactiveNav.tsx b/app/app/components/Nav/ReactiveNav.tsx deleted file mode 100644 index f9bc1db..0000000 --- a/app/app/components/Nav/ReactiveNav.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react' -import { Flex } from '@chakra-ui/react' -import { Hamburger } from '../Buttons/Hamburger' -import { Attention } from '../Buttons/Attention' -import { RightNav } from './ReactiveRightNav' - -export const ReactiveNav = props => { - const [navItems] = React.useState([{}]) - - const setNav = React.useCallback(active => { - setMt(active ? '100%' : '0%') - setNavActive(active) - }, []) - - React.useEffect(() => { - // react to mouse move event - const listener = event => { - if (event?.clientY <= 20) { - setNav(true) - } else if (event?.clientY >= 100) { - setNav(false) - } - } - window.addEventListener('mousemove', listener) - return () => { - window.removeEventListener('mousemove', listener) - } - }, [setNav]) - - const [navActive, setNavActive] = React.useState(false) - - const [mt, setMt] = React.useState('0%') - - return ( - <> - - - - {/* w={navActive ? '0px' : '40px'} */} - - - - - - ) -} diff --git a/app/app/components/Skeleton/RainbowSkeleton.tsx b/app/app/components/Skeleton/RainbowSkeleton.tsx deleted file mode 100644 index 018a63a..0000000 --- a/app/app/components/Skeleton/RainbowSkeleton.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react' -import { Flex } from '@chakra-ui/react' - -export const RainbowSkeleton = props => { - const [rainbowColours] = React.useState([ - '#f34a4a', - '#ffbc48', - '#58ca70', - '#47b5e6', - '#a555e8' - ]) - - const keyframes = React.useMemo(() => { - let keyframes = {} - rainbowColours.forEach((colour, idx) => { - keyframes[Math.round((idx * 100) / rainbowColours.length) + '%'] = { - backgroundColor: colour - } - }) - keyframes['100%'] = { backgroundColor: rainbowColours[0] } - return keyframes - }, [rainbowColours]) - - if (props?.loaded) { - return props?.children - } - - return ( - - ) -} diff --git a/app/app/entry.server.tsx b/app/app/entry.server.tsx deleted file mode 100644 index 7fd3dec..0000000 --- a/app/app/entry.server.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { renderToString } from 'react-dom/server' -import { RemixServer } from '@remix-run/react' -import type { EntryContext } from '@remix-run/react/dist/entry' - -export default function handleRequest ( - request: Request, - responseStatusCode: number, - responseHeaders: Headers, - remixContext: EntryContext -) { - let markup = renderToString( - - ) - - responseHeaders.set('Content-Type', 'text/html') - - return new Response('' + markup, { - status: responseStatusCode, - headers: responseHeaders - }) -} diff --git a/app/app/gp/Sample.js b/app/app/gp/Sample.js deleted file mode 100644 index 76432d3..0000000 --- a/app/app/gp/Sample.js +++ /dev/null @@ -1,8 +0,0 @@ -export default class Sample { - constructor({ x, y, progress, segment }) { - this.x = x; - this.y = y; - this.progress = progress; - this.segment = segment; - } -} diff --git a/app/app/gp/Segment.js b/app/app/gp/Segment.js deleted file mode 100644 index 310902c..0000000 --- a/app/app/gp/Segment.js +++ /dev/null @@ -1,8 +0,0 @@ -import { getMiddleSample } from './_utils'; - -export default class Segment { - constructor({ samples }) { - this.samples = samples; - this.progress = getMiddleSample(samples).progress; - } -} diff --git a/app/app/gp/_constants.js b/app/app/gp/_constants.js deleted file mode 100644 index ed3a507..0000000 --- a/app/app/gp/_constants.js +++ /dev/null @@ -1 +0,0 @@ -export const DEFAULT_PRECISION = 2; diff --git a/app/app/gp/index.js b/app/app/gp/index.js deleted file mode 100644 index 6d907e1..0000000 --- a/app/app/gp/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default as GradientPath } from './GradientPath'; -export { getData, strokeToFill } from './_data'; diff --git a/app/package.json b/app/package.json index 7948f94..82b7219 100644 --- a/app/package.json +++ b/app/package.json @@ -5,7 +5,8 @@ "build": "remix build", "dev": "remix dev --port 9999", "lint": "eslint --ext .js,.ts,.jsx,.tsx .", - "lint-fix": "eslint --ext .js,.ts,.jsx,.tsx . --fix" + "lint-fix": "eslint --ext .js,.ts,.jsx,.tsx . --fix", + "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"" }, "dependencies": { "@chakra-ui/react": "^2.7.1", diff --git a/app/remix.config.js b/app/remix.config.js index 4a5d83f..1a2bef1 100644 --- a/app/remix.config.js +++ b/app/remix.config.js @@ -2,12 +2,12 @@ * @type {import('@remix-run/dev').AppConfig} */ module.exports = { - ignoredRouteFiles: ['**/.*'] + ignoredRouteFiles: ["**/.*"], // future: { // unstable_dev: true // appServerPort: 3999 // } - // appDirectory: "app", + appDirectory: "src", // assetsBuildDirectory: "public/build", // serverBuildPath: "build/index.js", // publicPath: "/build/", diff --git a/app/src/Providers/Chakra/ChakraWrapper.tsx b/app/src/Providers/Chakra/ChakraWrapper.tsx new file mode 100644 index 0000000..579fe99 --- /dev/null +++ b/app/src/Providers/Chakra/ChakraWrapper.tsx @@ -0,0 +1,6 @@ +import { ChakraProvider } from "@chakra-ui/react" + +import { theme } from "./theme" +export const ChakraWrapper = (props) => { + return {props.children} +} diff --git a/app/app/Providers/Chakra/colors.tsx b/app/src/Providers/Chakra/colors.tsx similarity index 58% rename from app/app/Providers/Chakra/colors.tsx rename to app/src/Providers/Chakra/colors.tsx index 60b6f6b..f951d02 100644 --- a/app/app/Providers/Chakra/colors.tsx +++ b/app/src/Providers/Chakra/colors.tsx @@ -1,11 +1,17 @@ +const greys = { + light: "#F1F1F3", + lightt: "#E7E6E8", + medium: "#E0E0E0", + dark: "#BDBDBD", +} + +const grey = "#F1F1F3" + const g = { - grey: "#F1F1F3", - greys: { - light: "#F1F1F3", - lightt: "#E7E6E8", - medium: "#E0E0E0", - dark: "#BDBDBD", - }, + gray: grey, + grey, + grays: greys, + greys, } // for bad spellers @@ -33,6 +39,22 @@ export const colors = { indigo: "#5C6BC0", violet: "#AB47BC", }, + chakrasDark: { + root: "#8E0000", + sacral: "#E65100", + solarPlexus: "#FDD835", + heart: "#33691E", + throat: "#1E88E5", + thirdEye: "#3949AB", + crown: "#6A1B9A", + red: "#8E0000", + orange: "#E65100", + yellow: "#FDD835", + green: "#33691E", + blue: "#1E88E5", + indigo: "#3949AB", + violet: "#6A1B9A", + }, // all colors of the rainbow rainbow: { red: "#FF0000", diff --git a/app/app/Providers/Chakra/space.tsx b/app/src/Providers/Chakra/space.tsx similarity index 100% rename from app/app/Providers/Chakra/space.tsx rename to app/src/Providers/Chakra/space.tsx diff --git a/app/app/Providers/Chakra/theme.tsx b/app/src/Providers/Chakra/theme.tsx similarity index 100% rename from app/app/Providers/Chakra/theme.tsx rename to app/src/Providers/Chakra/theme.tsx diff --git a/app/app/Providers/ThingtimeProvider.tsx b/app/src/Providers/ThingtimeProvider.tsx similarity index 99% rename from app/app/Providers/ThingtimeProvider.tsx rename to app/src/Providers/ThingtimeProvider.tsx index 6fee349..9a4df84 100644 --- a/app/app/Providers/ThingtimeProvider.tsx +++ b/app/src/Providers/ThingtimeProvider.tsx @@ -2,8 +2,8 @@ import React, { createContext } from "react" import flatted, { parse, stringify } from "flatted" import { Subject } from "rxjs" -import { sanitise } from "~/functions/sanitise" -import { smarts } from "~/smarts" +import { sanitise } from "../functions/sanitise" +import { smarts } from "../smarts" export interface ThingtimeContextInterface { thingtime: any @@ -292,7 +292,7 @@ export const ThingtimeProvider = (props: any): JSX.Element => { const [thingtimeReference, rawSet] = React.useState() const thingtimeRef = React.useRef(thingtimeReference) - const stateRef = React.useRef({ + const stateRef: any = React.useRef({ c: 1, }) @@ -409,7 +409,7 @@ export const ThingtimeProvider = (props: any): JSX.Element => { } } - const newThingtime = thingtimeReference + const newThingtime: any = thingtimeReference || {} const paths = smarts.parsePropertyPath(path) diff --git a/app/src/components/Buttons/Attention.tsx b/app/src/components/Buttons/Attention.tsx new file mode 100644 index 0000000..665095c --- /dev/null +++ b/app/src/components/Buttons/Attention.tsx @@ -0,0 +1,32 @@ +import React from "react" +import { Flex } from "@chakra-ui/react" + +export const Attention = (props) => { + return ( + + + + ) +} diff --git a/app/src/components/Buttons/Hamburger.tsx b/app/src/components/Buttons/Hamburger.tsx new file mode 100644 index 0000000..3cd90ca --- /dev/null +++ b/app/src/components/Buttons/Hamburger.tsx @@ -0,0 +1,38 @@ +import React from "react" +import { Flex } from "@chakra-ui/react" + +export const Hamburger = (props) => { + const lineCount = [1, 2, 3] + + return ( + + {lineCount.map((line, idx) => { + return ( + + ) + })} + + ) +} diff --git a/app/app/components/Commander/Commander.tsx b/app/src/components/Commander/Commander.tsx similarity index 99% rename from app/app/components/Commander/Commander.tsx rename to app/src/components/Commander/Commander.tsx index a097705..c4ffd06 100644 --- a/app/app/components/Commander/Commander.tsx +++ b/app/src/components/Commander/Commander.tsx @@ -468,6 +468,7 @@ export const Commander = (props) => { sx={{ "&::placeholder": { color: "greys.dark", + // color: "white", }, }} width="100%" diff --git a/app/app/components/Commander/CommanderV1.tsx b/app/src/components/Commander/CommanderV2.tsx similarity index 99% rename from app/app/components/Commander/CommanderV1.tsx rename to app/src/components/Commander/CommanderV2.tsx index 01faa1a..a6b3c6f 100644 --- a/app/app/components/Commander/CommanderV1.tsx +++ b/app/src/components/Commander/CommanderV2.tsx @@ -564,6 +564,7 @@ export const CommanderV1 = (props) => { sx={{ "&::placeholder": { color: "greys.dark", + // color: "white", }, }} zIndex={9999} @@ -601,6 +602,8 @@ export const CommanderV1 = (props) => { sx={{ "&::placeholder": { color: "greys.dark", + // color: "white", + // textShadow: "0 0 5px black", }, }} zIndex={9999} diff --git a/app/src/components/Icon/Icon.tsx b/app/src/components/Icon/Icon.tsx new file mode 100644 index 0000000..a7d92b9 --- /dev/null +++ b/app/src/components/Icon/Icon.tsx @@ -0,0 +1,225 @@ +import React from "react" +import { Center } from "@chakra-ui/react" +import emojis from "emojis-list" + +export const Icon = (props) => { + const name = props?.name + + const icon = React.useMemo(() => { + // nothing + if (["⚙️", "gear", "cog"]?.includes(name)) { + return "⚙️" + } + if (["🔮", "crystal"]?.includes(name)) { + return "🔮" + } + if (["🌺", "flower", "hibiscus"]?.includes(name)) { + return "🌺" + } + if (["✨", "sparke", "magic"]?.includes(name)) { + return "✨" + } + if (["🧙‍♂️", "wizard", "gandalf"]?.includes(name)) { + return "🧙‍♂️" + } + if (["👀", "two eyes"]?.includes(name)) { + return "👀" + } + if (["📦", "box", "thing", "object"]?.includes(name)) { + return "📦" + } + if (["✏️", "pencil"]?.includes(name)) { + return "✏️" + } + if (["🎨", "edit", "paint", "create"]?.includes(name)) { + return "🎨" + } + if (["📚", "book", "books"]?.includes(name)) { + return "📚" + } + if (["🪄", "any", "magic wand"]?.includes(name)) { + return "🪄" + } + if (["📖", "book-open", "books-open"]?.includes(name)) { + return "📖" + } + if (["👩‍🏫", "book-reader", "books-reader"]?.includes(name)) { + return "👩‍🏫" + } + if (["💯", "number", "hundred"]?.includes(name)) { + return "💯" + } + if (["🧩", "puzzle", "types"]?.includes(name)) { + return "🧩" + } + if (["❤️", "heart"]?.includes(name)) { + return "❤️" + } + if (["💔", "heart-broken"]?.includes(name)) { + return "💔" + } + if (["💗", "heart-pulse"]?.includes(name)) { + return "💗" + } + if (["💬", "string", "text"]?.includes(name)) { + return "💬" + } + if (["📚", "array", "list"]?.includes(name)) { + return "📚" + } + if (["🌗", "boolean", "bool"]?.includes(name)) { + return "🌗" + // return "⚖️" + } + if (["🌈", "rainbow"]?.includes(name)) { + return "🌈" + } + if (["☀️", "sun"]?.includes(name)) { + return "☀️" + } + if (["🌙", "moon"]?.includes(name)) { + return "🌙" + } + if (["🦄", "unicorn"]?.includes(name)) { + return "🦄" + } + if (["👤", "user", "person"]?.includes(name)) { + return "👤" + } + if (["👥", "group", "team"]?.includes(name)) { + return "👥" + } + if (["✅", "success", "check"]?.includes(name)) { + return "✅" + } + if (["❌", "error", "stop"]?.includes(name)) { + return "❌" + } + if (["⚠️", "warning", "alert"]?.includes(name)) { + return "⚠️" + } + if (["⏰", "time", "clock"]?.includes(name)) { + return "⏰" + } + if (["⭐", "star", "favorite"]?.includes(name)) { + return "⭐" + } + if (["🌟", "glowing star", "glowing favorite"]?.includes(name)) { + return "🌟" + } + if (["❓", "question", "help"]?.includes(name)) { + return "❓" + } + if (["🎥", "video", "media"]?.includes(name)) { + return "🎥" + } + if (["🎵", "music", "audio"]?.includes(name)) { + return "🎵" + } + if (["🖼️", "image", "picture"]?.includes(name)) { + return "🖼️" + } + if (["✉️", "email", "mail"]?.includes(name)) { + return "✉️" + } + if (["💻", "computer", "laptop"]?.includes(name)) { + return "💻" + } + if (["📱", "mobile", "phone"]?.includes(name)) { + return "📱" + } + if (["🌍", "world", "globe"]?.includes(name)) { + return "🌍" + } + if (["🚀", "rocket", "launch"]?.includes(name)) { + return "🚀" + } + if (["✏️", "pencil", "edit"]?.includes(name)) { + return "✏️" + } + if (["🔍", "search", "magnify"]?.includes(name)) { + return "🔍" + } + if (["🔒", "lock", "secure"]?.includes(name)) { + return "🔒" + } + if (["🔓", "unlock", "access"]?.includes(name)) { + return "🔓" + } + if (["👍", "thumb-up", "like"]?.includes(name)) { + return "👍" + } + if (["👎", "thumb-down", "dislike"]?.includes(name)) { + return "👎" + } + if (["➕", "plus", "add"]?.includes(name)) { + return "➕" + } + if (["🌱", "seedling", "seed"]?.includes(name)) { + return "🌱" + } + if (["❓", "undefined", "null", "question", "confused"]?.includes(name)) { + return "❓" + // return "🌫️" + } + if (["🤖", "codex", "robot", "ai", "chatgpt"]?.includes(name)) { + return "🤖" + } + if (["🗑️", "trash", "bin", "delete", "remove"]?.includes(name)) { + return "🗑️" + } + if (["cash", "money"]?.includes(name)) { + // return "💰" + return "💵" + } + if (["💰", "money bag"]?.includes(name)) { + return "💰" + } + if (["🌀", "cyclone", "tornado"]?.includes(name)) { + return "🌀" + } + if (["thingtime"]?.includes(name)) { + if (Math.random() > 0.5) { + return "🌳" + } + return "🌀" + } + if (["📐", "function", "lambda"]?.includes(name)) { + return "📐" + } + if (["📌", "pin", "pinned", "located"]?.includes(name)) { + return "📌" + } + + if (["🎁", "wrap", "wrapped"]?.includes(name)) { + return "🎁" + // return "🎀" + } + + if (["🦕", "dinosaur", "dino"]?.includes(name)) { + return "🦕" + } + + if (emojis?.includes(name)) { + return name + } + + if (["random"]?.includes(name)) { + return emojis[Math.floor(Math.random() * emojis.length)] + } + + // question mark + return "🤷‍♂️" + }, [name]) + + return ( +
+ {icon} +
+ ) +} diff --git a/app/app/components/Layout/Main.tsx b/app/src/components/Layout/Main.tsx similarity index 100% rename from app/app/components/Layout/Main.tsx rename to app/src/components/Layout/Main.tsx diff --git a/app/src/components/Login/Login.tsx b/app/src/components/Login/Login.tsx new file mode 100644 index 0000000..2c4234b --- /dev/null +++ b/app/src/components/Login/Login.tsx @@ -0,0 +1,92 @@ +import React, { useState } from 'react'; +import { Flex, Button, FormControl, Input } from '@chakra-ui/react'; + +export const Login = (props) => { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + + const handleLogin = (props) => { + // handle login + + const { username, password } = props; + + console.log('nik username', username); + console.log('nik password', password); + }; + + return ( + <> +
+ + + setEmail(e.target.value)} + placeholder="Email" + type="username" + value={email} + /> + + + + setPassword(e.target.value)} + placeholder="Password" + type="password" + value={password} + /> + + + + +
+ + ); +}; diff --git a/app/app/components/MagicInput/MagicInput.tsx b/app/src/components/MagicInput/MagicInput.tsx similarity index 97% rename from app/app/components/MagicInput/MagicInput.tsx rename to app/src/components/MagicInput/MagicInput.tsx index 5ddabd8..a70c8bd 100644 --- a/app/app/components/MagicInput/MagicInput.tsx +++ b/app/src/components/MagicInput/MagicInput.tsx @@ -3,7 +3,7 @@ import { Box } from "@chakra-ui/react" import { useThingtime } from "../Thingtime/useThingtime" -export const MagicInput = React.forwardRef((props, ref) => { +export const MagicInput = React.forwardRef((props: any, ref) => { const { thingtime, setThingtime, loading } = useThingtime() const [inputValue, setInputValue] = React.useState() @@ -153,7 +153,7 @@ export const MagicInput = React.forwardRef((props, ref) => { contentEditable={!props?.readonly ? true : false} dangerouslySetInnerHTML={dangerouslySetInnerHTML} onFocus={onFocus} - onInput={(value) => { + onInput={(value: EventTarget | any) => { const innerText = value?.target?.innerText console.log("MagicInput got onInput event value", value) console.log("MagicInput got onInput event innerText", innerText) diff --git a/app/app/components/Nav/Footer.tsx b/app/src/components/Nav/Footer.tsx similarity index 97% rename from app/app/components/Nav/Footer.tsx rename to app/src/components/Nav/Footer.tsx index ae4afb6..14eb8d8 100644 --- a/app/app/components/Nav/Footer.tsx +++ b/app/src/components/Nav/Footer.tsx @@ -3,7 +3,7 @@ import { Box, Center, Flex, Text } from "@chakra-ui/react" import { Link, useLocation, useNavigate } from "@remix-run/react" import { Commander } from "../Commander/Commander" -import { CommanderV1 } from "../Commander/CommanderV1" +import { CommanderV1 } from "../Commander/CommanderV2" import { Icon } from "../Icon/Icon" import { RainbowSkeleton } from "../Skeleton/RainbowSkeleton" import { ProfileDrawer } from "./ProfileDrawer" diff --git a/app/app/components/Nav/Nav.tsx b/app/src/components/Nav/Nav.tsx similarity index 51% rename from app/app/components/Nav/Nav.tsx rename to app/src/components/Nav/Nav.tsx index 707a7dc..5909fa9 100644 --- a/app/app/components/Nav/Nav.tsx +++ b/app/src/components/Nav/Nav.tsx @@ -1,90 +1,83 @@ -import React from "react" -import { Box, Center, Flex } from "@chakra-ui/react" -import { Link, useLocation, useNavigate } from "@remix-run/react" +import React from 'react'; +import { Box, Center, Flex } from '@chakra-ui/react'; +import { Link, useLocation, useNavigate } from '@remix-run/react'; -import { Commander } from "../Commander/Commander" -import { CommanderV1 } from "../Commander/CommanderV1" -import { Icon } from "../Icon/Icon" -import { RainbowSkeleton } from "../Skeleton/RainbowSkeleton" -import { ProfileDrawer } from "./ProfileDrawer" +import { Commander } from '../Commander/Commander'; +import { CommanderV1 } from '../Commander/CommanderV2'; +import { Icon } from '../Icon/Icon'; +import { RainbowSkeleton } from '../Skeleton/RainbowSkeleton'; +import { ProfileDrawer } from './ProfileDrawer'; export const Nav = (props) => { - const [profileDrawerOpen, setProfileDrawerOpen] = React.useState(false) + const [profileDrawerOpen, setProfileDrawerOpen] = React.useState(false); - const { pathname } = useLocation() + const { pathname } = useLocation(); - const navigate = useNavigate() + const navigate = useNavigate(); const toggleProfileDrawer = React.useCallback(() => { - setProfileDrawerOpen(!profileDrawerOpen) - }, [profileDrawerOpen]) + setProfileDrawerOpen(!profileDrawerOpen); + }, [profileDrawerOpen]); const inEditorMode = React.useMemo(() => { - if (pathname.slice(0, 7) === "/editor") { - return true + if (pathname.slice(0, 7) === '/editor') { + return true; } - return false - }, [pathname]) + return false; + }, [pathname]); const inEditMode = React.useMemo(() => { - if (pathname.slice(0, 5) === "/edit") { - return true + if (pathname.slice(0, 5) === '/edit') { + return true; } - return false - }, [pathname]) + return false; + }, [pathname]); const editorToggleable = React.useMemo(() => { - if (pathname.slice(0, 7) === "/things") { - return true - } else if (pathname.slice(0, 5) === "/edit") { - return true + if (pathname.slice(0, 7) === '/things') { + return true; + } else if (pathname.slice(0, 5) === '/edit') { + return true; } - return false - }, [pathname]) + return false; + }, [pathname]); const toggleEdit = React.useCallback( (e) => { // if first characters of pathname are /things replace with /edit // or if first characters of pathname are /edit replace with /things - if (pathname.slice(0, 7) === "/things") { - const newPathname = pathname.replace("/things", "/edit") - navigate(newPathname) - } else if (pathname.slice(0, 7) === "/editor") { - const newPathname = pathname.replace("/editor", "/things") - navigate(newPathname) - } else if (pathname.slice(0, 5) === "/edit") { - const newPathname = pathname.replace("/edit", "/things") - navigate(newPathname) + if (pathname.slice(0, 7) === '/things') { + const newPathname = pathname.replace('/things', '/edit'); + navigate(newPathname); + } else if (pathname.slice(0, 7) === '/editor') { + const newPathname = pathname.replace('/editor', '/things'); + navigate(newPathname); + } else if (pathname.slice(0, 5) === '/edit') { + const newPathname = pathname.replace('/edit', '/things'); + navigate(newPathname); } }, [pathname, navigate] - ) + ); const toggleEditor = React.useCallback( (e) => { // if first characters of pathname are /things replace with /edit // or if first characters of pathname are /edit replace with /things - if (pathname.slice(0, 7) === "/editor") { - const newPathname = pathname.replace("/editor", "/edit") - navigate(newPathname) - } else if (pathname.slice(0, 5) === "/edit") { - const newPathname = pathname.replace("/edit", "/editor") - navigate(newPathname) + if (pathname.slice(0, 7) === '/editor') { + const newPathname = pathname.replace('/editor', '/edit'); + navigate(newPathname); + } else if (pathname.slice(0, 5) === '/edit') { + const newPathname = pathname.replace('/edit', '/editor'); + navigate(newPathname); } }, [pathname, navigate] - ) + ); return ( <> - + { // bg='white' // boxShadow={'0px 0px 10px rgba(0,0,0,0.1)'} > -
+
- +
-
+
{inEditMode && (
{ > {/* {
)} {editorToggleable && ( -
+
{/* { > */}
)} -
- +
+
-
+
- +
@@ -181,5 +160,5 @@ export const Nav = (props) => { {/* */} - ) -} + ); +}; diff --git a/app/app/components/Nav/ProfileDrawer.tsx b/app/src/components/Nav/ProfileDrawer.tsx similarity index 53% rename from app/app/components/Nav/ProfileDrawer.tsx rename to app/src/components/Nav/ProfileDrawer.tsx index b48a5fa..a55b017 100644 --- a/app/app/components/Nav/ProfileDrawer.tsx +++ b/app/src/components/Nav/ProfileDrawer.tsx @@ -1,8 +1,8 @@ -import React from 'react' -import { Drawer, DrawerBody, DrawerContent, Flex } from '@chakra-ui/react' +import React from "react" +import { Drawer, DrawerBody, DrawerContent, Flex } from "@chakra-ui/react" -export const ProfileDrawer = props => { - const navItems = ['settings'] +export const ProfileDrawer = (props) => { + const navItems = ["settings"] const onClose = React.useCallback(() => { // nothing @@ -10,12 +10,12 @@ export const ProfileDrawer = props => { return ( - + {navItems.map((item, idx) => { return {item} diff --git a/app/src/components/Nav/ReactiveNav.tsx b/app/src/components/Nav/ReactiveNav.tsx new file mode 100644 index 0000000..ca9475b --- /dev/null +++ b/app/src/components/Nav/ReactiveNav.tsx @@ -0,0 +1,70 @@ +import React from "react" +import { Flex } from "@chakra-ui/react" + +import { Attention } from "../Buttons/Attention" +import { Hamburger } from "../Buttons/Hamburger" +import { RightNav } from "./ReactiveRightNav" + +export const ReactiveNav = (props) => { + const [navItems] = React.useState([{}]) + + const setNav = React.useCallback((active) => { + setMt(active ? "100%" : "0%") + setNavActive(active) + }, []) + + React.useEffect(() => { + // react to mouse move event + const listener = (event) => { + if (event?.clientY <= 20) { + setNav(true) + } else if (event?.clientY >= 100) { + setNav(false) + } + } + window.addEventListener("mousemove", listener) + return () => { + window.removeEventListener("mousemove", listener) + } + }, [setNav]) + + const [navActive, setNavActive] = React.useState(false) + + const [mt, setMt] = React.useState("0%") + + return ( + <> + + + + {/* w={navActive ? '0px' : '40px'} */} + + + + + + ) +} diff --git a/app/app/components/Nav/ReactiveRightNav.tsx b/app/src/components/Nav/ReactiveRightNav.tsx similarity index 51% rename from app/app/components/Nav/ReactiveRightNav.tsx rename to app/src/components/Nav/ReactiveRightNav.tsx index a60c100..f127cfb 100644 --- a/app/app/components/Nav/ReactiveRightNav.tsx +++ b/app/src/components/Nav/ReactiveRightNav.tsx @@ -1,9 +1,9 @@ -import React from 'react' -import { Center, Text } from '@chakra-ui/react' +import React from "react" +import { Center, Text } from "@chakra-ui/react" -export const ReactiveRightNav = props => { - const setNav = React.useCallback(active => { - setMr(active ? '0%' : '-100%') +export const ReactiveRightNav = (props) => { + const setNav = React.useCallback((active) => { + setMr(active ? "0%" : "-100%") setNavActive(active) }, []) @@ -11,7 +11,7 @@ export const ReactiveRightNav = props => { React.useEffect(() => { // react to mouse move event - const listener = event => { + const listener = (event) => { const windowWidth = window.innerWidth if (!entered) { if (event?.clientX >= windowWidth - 60) { @@ -21,56 +21,56 @@ export const ReactiveRightNav = props => { } } } - window.addEventListener('mousemove', listener) + window.addEventListener("mousemove", listener) return () => { - window.removeEventListener('mousemove', listener) + window.removeEventListener("mousemove", listener) } }, [setNav, entered]) const [navActive, setNavActive] = React.useState(false) // const defaultMr = '-100%' - const defaultMr = '0%' + const defaultMr = "0%" const [mr, setMr] = React.useState(defaultMr) const navItems = React.useMemo(() => { - return ['home', 'imagine', 'create', 'share'] + return ["home", "imagine", "create", "share"] }, []) return (
setEntered(true)} onMouseLeave={() => setEntered(false)} - flexDir={'column'} - borderLeftRadius={'40px'} - h='85%' - minW={'600px'} - maxW='100%' - py={80} - px={100} - bg={`rgba(0, 0, 0, 0.01)`} + paddingX={100} + paddingY={80} > {navItems.map((navItem, idx) => { return ( {navItem} diff --git a/app/app/components/Rainbow/Rainbow.tsx b/app/src/components/Rainbow/Rainbow.tsx similarity index 100% rename from app/app/components/Rainbow/Rainbow.tsx rename to app/src/components/Rainbow/Rainbow.tsx diff --git a/app/app/components/Safety/Safe.tsx b/app/src/components/Safety/Safe.tsx similarity index 57% rename from app/app/components/Safety/Safe.tsx rename to app/src/components/Safety/Safe.tsx index 600908a..e352039 100644 --- a/app/app/components/Safety/Safe.tsx +++ b/app/src/components/Safety/Safe.tsx @@ -1,6 +1,6 @@ -import { safe } from '~/functions/safe' +import { safe } from "~/functions/safe" -export const Safe = props => { +export const Safe = (props) => { // do not render more than the limit of things to prevent infinite loops return safe(props) diff --git a/app/src/components/Skeleton/RainbowSkeleton.tsx b/app/src/components/Skeleton/RainbowSkeleton.tsx new file mode 100644 index 0000000..6da42af --- /dev/null +++ b/app/src/components/Skeleton/RainbowSkeleton.tsx @@ -0,0 +1,46 @@ +import React from "react" +import { Flex } from "@chakra-ui/react" + +export const RainbowSkeleton = (props) => { + const [rainbowColours] = React.useState([ + "#f34a4a", + "#ffbc48", + "#58ca70", + "#47b5e6", + "#a555e8", + ]) + + const keyframes = React.useMemo(() => { + const keyframes = {} + rainbowColours.forEach((colour, idx) => { + keyframes[Math.round((idx * 100) / rainbowColours.length) + "%"] = { + backgroundColor: colour, + } + }) + keyframes["100%"] = { backgroundColor: rainbowColours[0] } + return keyframes + }, [rainbowColours]) + + if (props?.loaded) { + return props?.children + } + + return ( + + ) +} diff --git a/app/app/components/Splash/Splash.tsx b/app/src/components/Splash/Splash.tsx similarity index 100% rename from app/app/components/Splash/Splash.tsx rename to app/src/components/Splash/Splash.tsx diff --git a/app/app/components/Thingtime/SettingsMenu.tsx b/app/src/components/Thingtime/SettingsMenu.tsx similarity index 100% rename from app/app/components/Thingtime/SettingsMenu.tsx rename to app/src/components/Thingtime/SettingsMenu.tsx diff --git a/app/app/components/Thingtime/Thingtime.tsx b/app/src/components/Thingtime/Thingtime.tsx similarity index 100% rename from app/app/components/Thingtime/Thingtime.tsx rename to app/src/components/Thingtime/Thingtime.tsx diff --git a/app/app/components/Thingtime/ThingtimeDemo.tsx b/app/src/components/Thingtime/ThingtimeDemo.tsx similarity index 100% rename from app/app/components/Thingtime/ThingtimeDemo.tsx rename to app/src/components/Thingtime/ThingtimeDemo.tsx diff --git a/app/app/components/Thingtime/ThingtimeURL.tsx b/app/src/components/Thingtime/ThingtimeURL.tsx similarity index 100% rename from app/app/components/Thingtime/ThingtimeURL.tsx rename to app/src/components/Thingtime/ThingtimeURL.tsx diff --git a/app/app/components/Thingtime/useThingtime.tsx b/app/src/components/Thingtime/useThingtime.tsx similarity index 68% rename from app/app/components/Thingtime/useThingtime.tsx rename to app/src/components/Thingtime/useThingtime.tsx index 4b914b4..6359395 100644 --- a/app/app/components/Thingtime/useThingtime.tsx +++ b/app/src/components/Thingtime/useThingtime.tsx @@ -1,6 +1,6 @@ import { useContext } from "react" -import { ThingtimeContext } from "~/Providers/ThingtimeProvider" +import { ThingtimeContext } from "../../Providers/ThingtimeProvider" const getGlobal = () => { try { @@ -10,7 +10,7 @@ const getGlobal = () => { } } -export const useThingtime = (props?: any) => { +export const useThingtime = (props?: any): any => { const value = useContext(ThingtimeContext) // const { thingtime, setThingtime, getThingtime, thingtimeRef } = value diff --git a/app/app/components/rainbowText.tsx b/app/src/components/rainbowText.tsx similarity index 100% rename from app/app/components/rainbowText.tsx rename to app/src/components/rainbowText.tsx diff --git a/app/app/components/textAnimation1.tsx b/app/src/components/textAnimation1.tsx similarity index 100% rename from app/app/components/textAnimation1.tsx rename to app/src/components/textAnimation1.tsx diff --git a/app/app/entry.client.tsx b/app/src/entry.client.tsx similarity index 61% rename from app/app/entry.client.tsx rename to app/src/entry.client.tsx index 2d9c35c..6384dbe 100644 --- a/app/app/entry.client.tsx +++ b/app/src/entry.client.tsx @@ -1,6 +1,6 @@ -import { hydrate } from 'react-dom' +import { hydrate } from "react-dom" // import { RemixBrowser } from "remix"; -import { RemixBrowser } from '@remix-run/react' +import { RemixBrowser } from "@remix-run/react" try { window.process = {} } catch (err) { diff --git a/app/src/entry.server.tsx b/app/src/entry.server.tsx new file mode 100644 index 0000000..94b20ca --- /dev/null +++ b/app/src/entry.server.tsx @@ -0,0 +1,21 @@ +import { renderToString } from "react-dom/server" +import { RemixServer } from "@remix-run/react" +import type { EntryContext } from "@remix-run/react/dist/entry" + +export default function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + const markup = renderToString( + + ) + + responseHeaders.set("Content-Type", "text/html") + + return new Response("" + markup, { + status: responseStatusCode, + headers: responseHeaders, + }) +} diff --git a/app/app/functions/safe.tsx b/app/src/functions/safe.tsx similarity index 100% rename from app/app/functions/safe.tsx rename to app/src/functions/safe.tsx diff --git a/app/app/functions/sanitise.tsx b/app/src/functions/sanitise.tsx similarity index 100% rename from app/app/functions/sanitise.tsx rename to app/src/functions/sanitise.tsx diff --git a/app/src/global-types.d.ts b/app/src/global-types.d.ts new file mode 100644 index 0000000..3b1250a --- /dev/null +++ b/app/src/global-types.d.ts @@ -0,0 +1,21 @@ +// modify window / globalThis to support any properties +// so there's no property does not exist on window typescript errors + +// Path: app/src/global-types.d.ts +declare global { + interface Window { + [key: string]: any; + } + + // Modify React component props/args to allow anything + // so we don't get errors + // Property 'fullPath' does not exist on type '{ children?: ReactNode; }'. + + interface ForwardRefRenderFunction { + T: any; + (props: any, ref: React.Ref): React.ReactElement | null; + } + +} + +export {}; diff --git a/app/app/gp/GradientPath.js b/app/src/gp/GradientPath.js similarity index 100% rename from app/app/gp/GradientPath.js rename to app/src/gp/GradientPath.js diff --git a/app/src/gp/Sample.js b/app/src/gp/Sample.js new file mode 100644 index 0000000..19e8f62 --- /dev/null +++ b/app/src/gp/Sample.js @@ -0,0 +1,8 @@ +export default class Sample { + constructor({ x, y, progress, segment }) { + this.x = x + this.y = y + this.progress = progress + this.segment = segment + } +} diff --git a/app/src/gp/Segment.js b/app/src/gp/Segment.js new file mode 100644 index 0000000..c50c392 --- /dev/null +++ b/app/src/gp/Segment.js @@ -0,0 +1,8 @@ +import { getMiddleSample } from "./_utils" + +export default class Segment { + constructor({ samples }) { + this.samples = samples + this.progress = getMiddleSample(samples).progress + } +} diff --git a/app/src/gp/_constants.js b/app/src/gp/_constants.js new file mode 100644 index 0000000..fb0a370 --- /dev/null +++ b/app/src/gp/_constants.js @@ -0,0 +1 @@ +export const DEFAULT_PRECISION = 2 diff --git a/app/app/gp/_data.js b/app/src/gp/_data.js similarity index 76% rename from app/app/gp/_data.js rename to app/src/gp/_data.js index e0256d6..12017d3 100644 --- a/app/app/gp/_data.js +++ b/app/src/gp/_data.js @@ -1,7 +1,7 @@ -import Sample from './Sample'; -import Segment from './Segment'; -import { convertPathToNode } from './_utils'; -import { DEFAULT_PRECISION } from './_constants'; +import { DEFAULT_PRECISION } from "./_constants" +import { convertPathToNode } from "./_utils" +import Sample from "./Sample" +import Segment from "./Segment" // The main function responsible for getting data // This will take a path, number of samples, number of samples, and a precision value @@ -11,34 +11,34 @@ export const getData = ({ path, segments, samples, - precision = DEFAULT_PRECISION + precision = DEFAULT_PRECISION, }) => { // Convert the given path to a DOM node if it isn't already one - path = convertPathToNode(path); + path = convertPathToNode(path) // We decrement the number of samples per segment because when we group them later we will add on the first sample of the following segment - if (samples > 1) samples--; + if (samples > 1) samples-- // Get total length of path, total number of samples we will be generating, and two blank arrays to hold samples and segments const pathLength = path.getTotalLength(), totalSamples = segments * samples, allSamples = [], - allSegments = []; + allSegments = [] // For the number of total samples, get the x, y, and progress values for each sample along the path for (let sample = 0; sample <= totalSamples; sample++) { - const progress = sample / totalSamples; + const progress = sample / totalSamples - let { x, y } = path.getPointAtLength(progress * pathLength); + let { x, y } = path.getPointAtLength(progress * pathLength) // If the user asks to round our x and y values, do so if (precision) { - x = +x.toFixed(precision); - y = +y.toFixed(precision); + x = +x.toFixed(precision) + y = +y.toFixed(precision) } // Create a new Sample and push it onto the allSamples array - allSamples.push(new Sample({ x, y, progress })); + allSamples.push(new Sample({ x, y, progress })) } // Out of all the samples gathered previously, sort them into groups of segments @@ -46,23 +46,23 @@ export const getData = ({ for (let segment = 0; segment < segments; segment++) { const currentStart = segment * samples, nextStart = currentStart + samples, - segmentSamples = []; + segmentSamples = [] // Push all current samples onto segmentSamples for (let samInSeg = 0; samInSeg < samples; samInSeg++) { - segmentSamples.push(allSamples[currentStart + samInSeg]); + segmentSamples.push(allSamples[currentStart + samInSeg]) } // Push the first sample from the next segment onto segmentSamples - segmentSamples.push(allSamples[nextStart]); + segmentSamples.push(allSamples[nextStart]) // Create a new Segment with the samples from segmentSamples - allSegments.push(new Segment({ samples: segmentSamples })); + allSegments.push(new Segment({ samples: segmentSamples })) } // Return our group of segments - return allSegments; -}; + return allSegments +} // The function responsible for converting strokable data (from getData()) into fillable data // This allows any SVG path to be filled instead of just stroked, allowing for the user to fill and stroke paths simultaneously @@ -73,10 +73,10 @@ export const strokeToFill = (data, width, precision, pathClosed) => { outlinedStrokes, precision, pathClosed - ); + ) - return averagedSegmentJoins; -}; + return averagedSegmentJoins +} // An internal function for outlining stroked data const outlineStrokes = (data, width, precision) => { @@ -85,53 +85,53 @@ const outlineStrokes = (data, width, precision) => { const p0 = new Sample({ ...startPoint, x: Math.sin(angle) * radius + startPoint.x, - y: -Math.cos(angle) * radius + startPoint.y + y: -Math.cos(angle) * radius + startPoint.y, }), p1 = new Sample({ ...startPoint, x: -Math.sin(angle) * radius + startPoint.x, - y: Math.cos(angle) * radius + startPoint.y - }); + y: Math.cos(angle) * radius + startPoint.y, + }) // If the user asks to round our x and y values, do so if (precision) { - p0.x = +p0.x.toFixed(precision); - p0.y = +p0.y.toFixed(precision); - p1.x = +p1.x.toFixed(precision); - p1.y = +p1.y.toFixed(precision); + p0.x = +p0.x.toFixed(precision) + p0.y = +p0.y.toFixed(precision) + p1.x = +p1.x.toFixed(precision) + p1.y = +p1.y.toFixed(precision) } - return [p0, p1]; - }; + return [p0, p1] + } // We need to set the radius (half of the width) and have a holding array for outlined Segments const radius = width / 2, - outlinedData = []; + outlinedData = [] for (let i = 0; i < data.length; i++) { const samples = data[i].samples, - segmentSamples = []; + segmentSamples = [] // For each sample point and the following sample point (if there is one) compute the angle // Also compute the sample's various perpendicular points (with a distance of radius away from the sample point) for (let j = 0; j < samples.length; j++) { // If we're at the end of the segment and there are no further points, get outta here! - if (samples[j + 1] === undefined) break; + if (samples[j + 1] === undefined) break const p0 = samples[j], // First point p1 = samples[j + 1], // Second point angle = Math.atan2(p1.y - p0.y, p1.x - p0.x), // Perpendicular angle to p0 and p1 p0Perps = getPerpSamples(angle, radius, precision, p0), // Get perpedicular points with a distance of radius away from p0 - p1Perps = getPerpSamples(angle, radius, precision, p1); // Get perpedicular points with a distance of radius away from p1 + p1Perps = getPerpSamples(angle, radius, precision, p1) // Get perpedicular points with a distance of radius away from p1 // We only need the p0 perpendenciular points for the first sample // The p0 for j > 0 will always be the same as p1 anyhow, so let's not add redundant points if (j === 0) { - segmentSamples.push(...p0Perps); + segmentSamples.push(...p0Perps) } // Always push the second sample point's perpendicular points - segmentSamples.push(...p1Perps); + segmentSamples.push(...p1Perps) } // segmentSamples is out of order... @@ -140,14 +140,14 @@ const outlineStrokes = (data, width, precision) => { new Segment({ samples: [ ...segmentSamples.filter((s, i) => i % 2 === 0), - ...segmentSamples.filter((s, i) => i % 2 === 1).reverse() - ] + ...segmentSamples.filter((s, i) => i % 2 === 1).reverse(), + ], }) - ); + ) } - return outlinedData; -}; + return outlinedData +} // An internal function taking outlinedData (from outlineStrokes()) and averaging adjacent edges // If we didn't do this, our data would be fillable, but it would look stroked @@ -156,17 +156,17 @@ const averageSegmentJoins = (outlinedData, precision, pathClosed) => { // Find the average x and y between two points (p0 and p1) const avg = (p0, p1) => ({ x: (p0.x + p1.x) / 2, - y: (p0.y + p1.y) / 2 - }); + y: (p0.y + p1.y) / 2, + }) // Recombine the new x and y positions with all the other keys in the object const combine = (segment, pos, avg) => ({ ...segment[pos], x: avg.x, - y: avg.y - }); + y: avg.y, + }) - const init_outlinedData = JSON.parse(JSON.stringify(outlinedData)); //clone initial outlinedData Object + const init_outlinedData = JSON.parse(JSON.stringify(outlinedData)) //clone initial outlinedData Object for (let i = 0; i < outlinedData.length; i++) { // If path is closed: the current segment's samples; @@ -186,34 +186,34 @@ const averageSegmentJoins = (outlinedData, precision, pathClosed) => { ? outlinedData[i + 1].samples : init_outlinedData[0].samples, currentMiddle = currentSamples.length / 2, // The "middle" sample in the current segment's samples - nextEnd = nextSamples.length - 1; // The last sample in the next segment's samples + nextEnd = nextSamples.length - 1 // The last sample in the next segment's samples // Average two sets of outlined samples to create p0Average and p1Average const p0Average = avg(currentSamples[currentMiddle - 1], nextSamples[0]), - p1Average = avg(currentSamples[currentMiddle], nextSamples[nextEnd]); + p1Average = avg(currentSamples[currentMiddle], nextSamples[nextEnd]) // If the user asks to round our x and y values, do so if (precision) { - p0Average.x = +p0Average.x.toFixed(precision); - p0Average.y = +p0Average.y.toFixed(precision); - p1Average.x = +p1Average.x.toFixed(precision); - p1Average.y = +p1Average.y.toFixed(precision); + p0Average.x = +p0Average.x.toFixed(precision) + p0Average.y = +p0Average.y.toFixed(precision) + p1Average.x = +p1Average.x.toFixed(precision) + p1Average.y = +p1Average.y.toFixed(precision) } // Replace the previous values with new Samples currentSamples[currentMiddle - 1] = new Sample({ - ...combine(currentSamples, currentMiddle - 1, p0Average) - }); + ...combine(currentSamples, currentMiddle - 1, p0Average), + }) currentSamples[currentMiddle] = new Sample({ - ...combine(currentSamples, currentMiddle, p1Average) - }); + ...combine(currentSamples, currentMiddle, p1Average), + }) nextSamples[0] = new Sample({ - ...combine(nextSamples, 0, p0Average) - }); + ...combine(nextSamples, 0, p0Average), + }) nextSamples[nextEnd] = new Sample({ - ...combine(nextSamples, nextEnd, p1Average) - }); + ...combine(nextSamples, nextEnd, p1Average), + }) } - return outlinedData; -}; + return outlinedData +} diff --git a/app/app/gp/_utils.js b/app/src/gp/_utils.js similarity index 95% rename from app/app/gp/_utils.js rename to app/src/gp/_utils.js index e9069d7..96d8a9d 100644 --- a/app/app/gp/_utils.js +++ b/app/src/gp/_utils.js @@ -15,13 +15,7 @@ export const svgElem = (type, attrs) => { } // An internal function to help with the repetition of adding fill, stroke, and stroke-width attributes -export const styleAttrs = ( - fill, - stroke, - strokeWidth, - progress, - animation -) => { +export const styleAttrs = (fill, stroke, strokeWidth, progress, animation) => { const determineColor = (type, progress) => typeof type === "string" ? type : tinygradient(type).rgbAt(progress) @@ -38,9 +32,9 @@ export const styleAttrs = ( if (animation?.name) { // TODO: add animation-direction support - + const duration = animation.duration || 5 - + attrs["style"] = ` animation-name: ${animation?.name}; animation-delay: ${progress * duration - duration}s; diff --git a/app/src/gp/index.js b/app/src/gp/index.js new file mode 100644 index 0000000..e3ad20c --- /dev/null +++ b/app/src/gp/index.js @@ -0,0 +1,2 @@ +export { default as GradientPath } from "./GradientPath" +export { getData, strokeToFill } from "./_data" diff --git a/app/app/hooks/useIcons.tsx b/app/src/hooks/useIcons.tsx similarity index 100% rename from app/app/hooks/useIcons.tsx rename to app/src/hooks/useIcons.tsx diff --git a/app/app/hooks/usePath.tsx b/app/src/hooks/usePath.tsx similarity index 100% rename from app/app/hooks/usePath.tsx rename to app/src/hooks/usePath.tsx diff --git a/app/app/hooks/useProps.tsx b/app/src/hooks/useProps.tsx similarity index 100% rename from app/app/hooks/useProps.tsx rename to app/src/hooks/useProps.tsx diff --git a/app/app/hooks/useThings.tsx b/app/src/hooks/useThings.tsx similarity index 100% rename from app/app/hooks/useThings.tsx rename to app/src/hooks/useThings.tsx diff --git a/app/app/hooks/useTrace.tsx b/app/src/hooks/useTrace.tsx similarity index 100% rename from app/app/hooks/useTrace.tsx rename to app/src/hooks/useTrace.tsx diff --git a/app/app/hooks/useUuid.tsx b/app/src/hooks/useUuid.tsx similarity index 100% rename from app/app/hooks/useUuid.tsx rename to app/src/hooks/useUuid.tsx diff --git a/app/app/root.tsx b/app/src/root.tsx similarity index 100% rename from app/app/root.tsx rename to app/src/root.tsx diff --git a/app/app/routes/*.tsx b/app/src/routes/*.tsx similarity index 100% rename from app/app/routes/*.tsx rename to app/src/routes/*.tsx diff --git a/app/app/routes/edge.tsx b/app/src/routes/edge.tsx similarity index 51% rename from app/app/routes/edge.tsx rename to app/src/routes/edge.tsx index 70a7d28..3f1fda5 100644 --- a/app/app/routes/edge.tsx +++ b/app/src/routes/edge.tsx @@ -1,6 +1,6 @@ -export const config = { runtime: 'edge' } +export const config = { runtime: "edge" } -export default function Edge () { +export default function Edge() { return (

Welcome to Thingtime@Edge

diff --git a/app/app/routes/index.tsx b/app/src/routes/index.tsx similarity index 100% rename from app/app/routes/index.tsx rename to app/src/routes/index.tsx diff --git a/app/app/routes/login.tsx b/app/src/routes/login.tsx similarity index 100% rename from app/app/routes/login.tsx rename to app/src/routes/login.tsx diff --git a/app/app/routes/ode.tsx b/app/src/routes/ode.tsx similarity index 100% rename from app/app/routes/ode.tsx rename to app/src/routes/ode.tsx diff --git a/app/app/routes/rainbow/*.tsx b/app/src/routes/rainbow/*.tsx similarity index 100% rename from app/app/routes/rainbow/*.tsx rename to app/src/routes/rainbow/*.tsx diff --git a/app/app/smarts/index.tsx b/app/src/smarts/index.tsx similarity index 100% rename from app/app/smarts/index.tsx rename to app/src/smarts/index.tsx diff --git a/app/tsconfig.json b/app/tsconfig.json index 12a7428..c45aa5b 100644 --- a/app/tsconfig.json +++ b/app/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["./src/*"] }, // Remix takes care of building everything in `remix build`. diff --git a/app/vercel.json b/app/vercel.json index debafb4..dcfba92 100644 --- a/app/vercel.json +++ b/app/vercel.json @@ -1,7 +1,7 @@ { - "build": { - "env": { - "ENABLE_FILE_SYSTEM_API": "1" - } + "build": { + "env": { + "ENABLE_FILE_SYSTEM_API": "1" } -} \ No newline at end of file + } +}