🦄 Refactored app to src main
This commit is contained in:
parent
59c04276ac
commit
cf67d463b3
9
.gitignore
vendored
9
.gitignore
vendored
@ -5,10 +5,17 @@
|
|||||||
app/node_modules
|
app/node_modules
|
||||||
app-next/node_modules
|
app-next/node_modules
|
||||||
api/node_modules
|
api/node_modules
|
||||||
/node_modules
|
node_modules
|
||||||
|
|
||||||
localhost-key.pem
|
localhost-key.pem
|
||||||
localhost.pem
|
localhost.pem
|
||||||
|
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
pnpm-lock.yaml
|
||||||
|
|
||||||
|
build/*
|
||||||
|
public/build/*
|
||||||
|
api/index.js
|
||||||
|
api/index.js.map
|
||||||
|
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
12
.prettierrc
Normal file
12
.prettierrc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"printWidth": 150,
|
||||||
|
"singleAttributePerLine": false,
|
||||||
|
"arrowParens": "always",
|
||||||
|
"plugins": []
|
||||||
|
}
|
@ -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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
10
app/.gitignore
vendored
10
app/.gitignore
vendored
@ -5,7 +5,9 @@ node_modules
|
|||||||
.vercel
|
.vercel
|
||||||
.output
|
.output
|
||||||
|
|
||||||
/build/
|
build/*
|
||||||
/public/build
|
public/build/*
|
||||||
/api/index.js
|
api/index.js
|
||||||
/api/index.js.map
|
api/index.js.map
|
||||||
|
|
||||||
|
pnpm-lock.yaml
|
12
app/.prettierrc
Normal file
12
app/.prettierrc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"printWidth": 150,
|
||||||
|
"singleAttributePerLine": false,
|
||||||
|
"arrowParens": "always",
|
||||||
|
"plugins": []
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
import { ChakraProvider } from '@chakra-ui/react'
|
|
||||||
import { theme } from './theme'
|
|
||||||
export const ChakraWrapper = props => {
|
|
||||||
return <ChakraProvider theme={theme}>{props.children}</ChakraProvider>
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { Flex } from '@chakra-ui/react'
|
|
||||||
|
|
||||||
export const Attention = props => {
|
|
||||||
return (
|
|
||||||
<Flex
|
|
||||||
{...props}
|
|
||||||
flexDirection={'column'}
|
|
||||||
justifyContent={'center'}
|
|
||||||
alignItems={'center'}
|
|
||||||
cursor={'pointer'}
|
|
||||||
>
|
|
||||||
<Flex
|
|
||||||
w={props.w || '40px'}
|
|
||||||
mb='10px'
|
|
||||||
h='2px'
|
|
||||||
bg='linear-gradient(to right, #f34a4a, #ffbc48, #58ca70, #47b5e6, #a555e8, #f34a4a);'
|
|
||||||
backgroundSize='200%'
|
|
||||||
borderBottomRadius={'20px'}
|
|
||||||
transition='all 0.5s ease-in-out'
|
|
||||||
sx={{
|
|
||||||
'@keyframes moving-rainbow': {
|
|
||||||
'0%': { backgroundPosition: '0 0' },
|
|
||||||
'100%': { backgroundPosition: '200% 0' }
|
|
||||||
},
|
|
||||||
// add delay
|
|
||||||
animation: `moving-rainbow 3s infinite linear`
|
|
||||||
}}
|
|
||||||
></Flex>
|
|
||||||
</Flex>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { Flex } from '@chakra-ui/react'
|
|
||||||
|
|
||||||
export const Hamburger = props => {
|
|
||||||
const lineCount = [1, 2, 3]
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Flex
|
|
||||||
{...props}
|
|
||||||
flexDirection={'column'}
|
|
||||||
justifyContent={'center'}
|
|
||||||
alignItems={'center'}
|
|
||||||
cursor={'pointer'}
|
|
||||||
>
|
|
||||||
{lineCount.map((line, idx) => {
|
|
||||||
return (
|
|
||||||
<Flex
|
|
||||||
key={idx}
|
|
||||||
w='40px'
|
|
||||||
mb='10px'
|
|
||||||
h='3px'
|
|
||||||
bg='linear-gradient(to right, #f34a4a, #ffbc48, #58ca70, #47b5e6, #a555e8, #f34a4a);'
|
|
||||||
backgroundSize='200%'
|
|
||||||
borderRadius={'9px'}
|
|
||||||
sx={{
|
|
||||||
'@keyframes moving-rainbow': {
|
|
||||||
'0%': { backgroundPosition: '0 0' },
|
|
||||||
'100%': { backgroundPosition: '200% 0' }
|
|
||||||
},
|
|
||||||
// add delay
|
|
||||||
animation: `moving-rainbow 3s infinite linear -${idx * 0.3}s}`
|
|
||||||
}}
|
|
||||||
></Flex>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</Flex>
|
|
||||||
)
|
|
||||||
}
|
|
@ -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 (
|
|
||||||
<Center
|
|
||||||
transition="all 0.2s ease-out"
|
|
||||||
{...props}
|
|
||||||
{...props?.chakras}
|
|
||||||
fontSize={props?.size}
|
|
||||||
>
|
|
||||||
{icon}
|
|
||||||
</Center>
|
|
||||||
)
|
|
||||||
}
|
|
@ -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 (
|
|
||||||
<>
|
|
||||||
<Flex flexDirection="column" gap={4} width="auto">
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
|
||||||
placeholder="Email"
|
|
||||||
type="email"
|
|
||||||
value={email}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
|
||||||
placeholder="Password"
|
|
||||||
type="password"
|
|
||||||
value={password}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<Flex
|
|
||||||
width="100%"
|
|
||||||
color="white"
|
|
||||||
background="chakras.violet"
|
|
||||||
borderRadius={6}
|
|
||||||
cursor="pointer"
|
|
||||||
paddingX={5}
|
|
||||||
paddingY={2}
|
|
||||||
>
|
|
||||||
Login
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
@ -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 (
|
|
||||||
<>
|
|
||||||
<Flex
|
|
||||||
as='nav'
|
|
||||||
w='100%'
|
|
||||||
alignItems={'center'}
|
|
||||||
justifyContent='center'
|
|
||||||
flexDir={'row'}
|
|
||||||
position='fixed'
|
|
||||||
py={'1%'}
|
|
||||||
px={'1%'}
|
|
||||||
bottom={'100%'}
|
|
||||||
transform={`translateY(${mt})`}
|
|
||||||
transition={'all 0.3s ease-in-out'}
|
|
||||||
// top={'100%'}
|
|
||||||
// top={0}
|
|
||||||
left={0}
|
|
||||||
right={0}
|
|
||||||
>
|
|
||||||
<Hamburger ml='auto'></Hamburger>
|
|
||||||
<Flex
|
|
||||||
opacity={navActive ? 0 : 1}
|
|
||||||
position='absolute'
|
|
||||||
transition={'all 0.2s ease-in-out'}
|
|
||||||
top='100%'
|
|
||||||
left={'50%'}
|
|
||||||
translateX={'-50%'}
|
|
||||||
>
|
|
||||||
{/* w={navActive ? '0px' : '40px'} */}
|
|
||||||
<Attention></Attention>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<RightNav></RightNav>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
@ -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 (
|
|
||||||
<Flex
|
|
||||||
cursor='pointer'
|
|
||||||
w='10px'
|
|
||||||
h='8px'
|
|
||||||
borderRadius={'2px'}
|
|
||||||
sx={{
|
|
||||||
'@keyframes placeholder-rainbow': keyframes,
|
|
||||||
'@keyframes placeholder-opacity': {
|
|
||||||
'0%': { opacity: 0.2 },
|
|
||||||
'100%': { opacity: 1 }
|
|
||||||
},
|
|
||||||
// add delay
|
|
||||||
animation: `placeholder-rainbow 8s infinite linear, placeholder-opacity 1.3s linear 0s infinite alternate none running}`
|
|
||||||
}}
|
|
||||||
{...props}
|
|
||||||
></Flex>
|
|
||||||
)
|
|
||||||
}
|
|
@ -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(
|
|
||||||
<RemixServer context={remixContext} url={request.url} />
|
|
||||||
)
|
|
||||||
|
|
||||||
responseHeaders.set('Content-Type', 'text/html')
|
|
||||||
|
|
||||||
return new Response('<!DOCTYPE html>' + markup, {
|
|
||||||
status: responseStatusCode,
|
|
||||||
headers: responseHeaders
|
|
||||||
})
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { getMiddleSample } from './_utils';
|
|
||||||
|
|
||||||
export default class Segment {
|
|
||||||
constructor({ samples }) {
|
|
||||||
this.samples = samples;
|
|
||||||
this.progress = getMiddleSample(samples).progress;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export const DEFAULT_PRECISION = 2;
|
|
@ -1,2 +0,0 @@
|
|||||||
export { default as GradientPath } from './GradientPath';
|
|
||||||
export { getData, strokeToFill } from './_data';
|
|
@ -5,7 +5,8 @@
|
|||||||
"build": "remix build",
|
"build": "remix build",
|
||||||
"dev": "remix dev --port 9999",
|
"dev": "remix dev --port 9999",
|
||||||
"lint": "eslint --ext .js,.ts,.jsx,.tsx .",
|
"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": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^2.7.1",
|
"@chakra-ui/react": "^2.7.1",
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
* @type {import('@remix-run/dev').AppConfig}
|
* @type {import('@remix-run/dev').AppConfig}
|
||||||
*/
|
*/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
ignoredRouteFiles: ['**/.*']
|
ignoredRouteFiles: ["**/.*"],
|
||||||
// future: {
|
// future: {
|
||||||
// unstable_dev: true
|
// unstable_dev: true
|
||||||
// appServerPort: 3999
|
// appServerPort: 3999
|
||||||
// }
|
// }
|
||||||
// appDirectory: "app",
|
appDirectory: "src",
|
||||||
// assetsBuildDirectory: "public/build",
|
// assetsBuildDirectory: "public/build",
|
||||||
// serverBuildPath: "build/index.js",
|
// serverBuildPath: "build/index.js",
|
||||||
// publicPath: "/build/",
|
// publicPath: "/build/",
|
||||||
|
6
app/src/Providers/Chakra/ChakraWrapper.tsx
Normal file
6
app/src/Providers/Chakra/ChakraWrapper.tsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { ChakraProvider } from "@chakra-ui/react"
|
||||||
|
|
||||||
|
import { theme } from "./theme"
|
||||||
|
export const ChakraWrapper = (props) => {
|
||||||
|
return <ChakraProvider theme={theme}>{props.children}</ChakraProvider>
|
||||||
|
}
|
@ -1,11 +1,17 @@
|
|||||||
|
const greys = {
|
||||||
|
light: "#F1F1F3",
|
||||||
|
lightt: "#E7E6E8",
|
||||||
|
medium: "#E0E0E0",
|
||||||
|
dark: "#BDBDBD",
|
||||||
|
}
|
||||||
|
|
||||||
|
const grey = "#F1F1F3"
|
||||||
|
|
||||||
const g = {
|
const g = {
|
||||||
grey: "#F1F1F3",
|
gray: grey,
|
||||||
greys: {
|
grey,
|
||||||
light: "#F1F1F3",
|
grays: greys,
|
||||||
lightt: "#E7E6E8",
|
greys,
|
||||||
medium: "#E0E0E0",
|
|
||||||
dark: "#BDBDBD",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// for bad spellers
|
// for bad spellers
|
||||||
@ -33,6 +39,22 @@ export const colors = {
|
|||||||
indigo: "#5C6BC0",
|
indigo: "#5C6BC0",
|
||||||
violet: "#AB47BC",
|
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
|
// all colors of the rainbow
|
||||||
rainbow: {
|
rainbow: {
|
||||||
red: "#FF0000",
|
red: "#FF0000",
|
@ -2,8 +2,8 @@ import React, { createContext } from "react"
|
|||||||
import flatted, { parse, stringify } from "flatted"
|
import flatted, { parse, stringify } from "flatted"
|
||||||
import { Subject } from "rxjs"
|
import { Subject } from "rxjs"
|
||||||
|
|
||||||
import { sanitise } from "~/functions/sanitise"
|
import { sanitise } from "../functions/sanitise"
|
||||||
import { smarts } from "~/smarts"
|
import { smarts } from "../smarts"
|
||||||
|
|
||||||
export interface ThingtimeContextInterface {
|
export interface ThingtimeContextInterface {
|
||||||
thingtime: any
|
thingtime: any
|
||||||
@ -292,7 +292,7 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
|
|||||||
const [thingtimeReference, rawSet] = React.useState()
|
const [thingtimeReference, rawSet] = React.useState()
|
||||||
|
|
||||||
const thingtimeRef = React.useRef(thingtimeReference)
|
const thingtimeRef = React.useRef(thingtimeReference)
|
||||||
const stateRef = React.useRef({
|
const stateRef: any = React.useRef({
|
||||||
c: 1,
|
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)
|
const paths = smarts.parsePropertyPath(path)
|
||||||
|
|
32
app/src/components/Buttons/Attention.tsx
Normal file
32
app/src/components/Buttons/Attention.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { Flex } from "@chakra-ui/react"
|
||||||
|
|
||||||
|
export const Attention = (props) => {
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
{...props}
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
flexDirection="column"
|
||||||
|
cursor="pointer"
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
"@keyframes moving-rainbow": {
|
||||||
|
"0%": { backgroundPosition: "0 0" },
|
||||||
|
"100%": { backgroundPosition: "200% 0" },
|
||||||
|
},
|
||||||
|
// add delay
|
||||||
|
animation: `moving-rainbow 3s infinite linear`,
|
||||||
|
}}
|
||||||
|
width={props.w || "40px"}
|
||||||
|
height="2px"
|
||||||
|
marginBottom="10px"
|
||||||
|
background="linear-gradient(to right, #f34a4a, #ffbc48, #58ca70, #47b5e6, #a555e8, #f34a4a);"
|
||||||
|
backgroundSize="200%"
|
||||||
|
borderBottomRadius="20px"
|
||||||
|
transition="all 0.5s ease-in-out"
|
||||||
|
></Flex>
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
}
|
38
app/src/components/Buttons/Hamburger.tsx
Normal file
38
app/src/components/Buttons/Hamburger.tsx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { Flex } from "@chakra-ui/react"
|
||||||
|
|
||||||
|
export const Hamburger = (props) => {
|
||||||
|
const lineCount = [1, 2, 3]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
{...props}
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
flexDirection="column"
|
||||||
|
cursor="pointer"
|
||||||
|
>
|
||||||
|
{lineCount.map((line, idx) => {
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
key={idx}
|
||||||
|
sx={{
|
||||||
|
"@keyframes moving-rainbow": {
|
||||||
|
"0%": { backgroundPosition: "0 0" },
|
||||||
|
"100%": { backgroundPosition: "200% 0" },
|
||||||
|
},
|
||||||
|
// add delay
|
||||||
|
animation: `moving-rainbow 3s infinite linear -${idx * 0.3}s}`,
|
||||||
|
}}
|
||||||
|
width="40px"
|
||||||
|
height="3px"
|
||||||
|
marginBottom="10px"
|
||||||
|
background="linear-gradient(to right, #f34a4a, #ffbc48, #58ca70, #47b5e6, #a555e8, #f34a4a);"
|
||||||
|
backgroundSize="200%"
|
||||||
|
borderRadius="9px"
|
||||||
|
></Flex>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
}
|
@ -468,6 +468,7 @@ export const Commander = (props) => {
|
|||||||
sx={{
|
sx={{
|
||||||
"&::placeholder": {
|
"&::placeholder": {
|
||||||
color: "greys.dark",
|
color: "greys.dark",
|
||||||
|
// color: "white",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
width="100%"
|
width="100%"
|
@ -564,6 +564,7 @@ export const CommanderV1 = (props) => {
|
|||||||
sx={{
|
sx={{
|
||||||
"&::placeholder": {
|
"&::placeholder": {
|
||||||
color: "greys.dark",
|
color: "greys.dark",
|
||||||
|
// color: "white",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
zIndex={9999}
|
zIndex={9999}
|
||||||
@ -601,6 +602,8 @@ export const CommanderV1 = (props) => {
|
|||||||
sx={{
|
sx={{
|
||||||
"&::placeholder": {
|
"&::placeholder": {
|
||||||
color: "greys.dark",
|
color: "greys.dark",
|
||||||
|
// color: "white",
|
||||||
|
// textShadow: "0 0 5px black",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
zIndex={9999}
|
zIndex={9999}
|
225
app/src/components/Icon/Icon.tsx
Normal file
225
app/src/components/Icon/Icon.tsx
Normal file
@ -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 (
|
||||||
|
<Center
|
||||||
|
transition="all 0.2s ease-out"
|
||||||
|
{...props}
|
||||||
|
{...props?.chakras}
|
||||||
|
fontSize={props?.size}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
</Center>
|
||||||
|
)
|
||||||
|
}
|
92
app/src/components/Login/Login.tsx
Normal file
92
app/src/components/Login/Login.tsx
Normal file
@ -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 (
|
||||||
|
<>
|
||||||
|
<form>
|
||||||
|
<Flex flexDirection="column" gap={4} width="255px" maxWidth="100%">
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
sx={{
|
||||||
|
'&::placeholder': {
|
||||||
|
color: 'greys.dark'
|
||||||
|
// color: "white",
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
background="grey"
|
||||||
|
border="none"
|
||||||
|
borderRadius="5px"
|
||||||
|
outline="none"
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
placeholder="Email"
|
||||||
|
type="username"
|
||||||
|
value={email}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
sx={{
|
||||||
|
'&::placeholder': {
|
||||||
|
color: 'greys.dark'
|
||||||
|
// color: "white",
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
background="grey"
|
||||||
|
border="none"
|
||||||
|
borderRadius="5px"
|
||||||
|
outline="none"
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
placeholder="Password"
|
||||||
|
type="password"
|
||||||
|
value={password}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
sx={{
|
||||||
|
'@keyframes moving-rainbow': {
|
||||||
|
'0%': { backgroundPosition: '0 0' },
|
||||||
|
'100%': { backgroundPosition: 'calc(100px + 400%) 0' }
|
||||||
|
},
|
||||||
|
animation: 'moving-rainbow 40s infinite linear'
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
display="Flex"
|
||||||
|
justifyContent="flex-start"
|
||||||
|
width="100%"
|
||||||
|
color="white"
|
||||||
|
fontWeight="bold"
|
||||||
|
background="chakras.violet"
|
||||||
|
backgroundSize="calc(100px + 400%)"
|
||||||
|
// Add rainbow animation background gradient right to left
|
||||||
|
bgGradient="linear-gradient(to right, #47b5e6, #a555e8, #f34a4a, #ffbc48, #58ca70, #47b5e6)"
|
||||||
|
borderRadius={6}
|
||||||
|
_hover={{
|
||||||
|
opacity: 0.9
|
||||||
|
}}
|
||||||
|
cursor="pointer"
|
||||||
|
transition="all 150ms ease-in-out"
|
||||||
|
paddingX={4}
|
||||||
|
paddingY={2}
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -3,7 +3,7 @@ import { Box } from "@chakra-ui/react"
|
|||||||
|
|
||||||
import { useThingtime } from "../Thingtime/useThingtime"
|
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 { thingtime, setThingtime, loading } = useThingtime()
|
||||||
|
|
||||||
const [inputValue, setInputValue] = React.useState()
|
const [inputValue, setInputValue] = React.useState()
|
||||||
@ -153,7 +153,7 @@ export const MagicInput = React.forwardRef((props, ref) => {
|
|||||||
contentEditable={!props?.readonly ? true : false}
|
contentEditable={!props?.readonly ? true : false}
|
||||||
dangerouslySetInnerHTML={dangerouslySetInnerHTML}
|
dangerouslySetInnerHTML={dangerouslySetInnerHTML}
|
||||||
onFocus={onFocus}
|
onFocus={onFocus}
|
||||||
onInput={(value) => {
|
onInput={(value: EventTarget | any) => {
|
||||||
const innerText = value?.target?.innerText
|
const innerText = value?.target?.innerText
|
||||||
console.log("MagicInput got onInput event value", value)
|
console.log("MagicInput got onInput event value", value)
|
||||||
console.log("MagicInput got onInput event innerText", innerText)
|
console.log("MagicInput got onInput event innerText", innerText)
|
@ -3,7 +3,7 @@ import { Box, Center, Flex, Text } from "@chakra-ui/react"
|
|||||||
import { Link, useLocation, useNavigate } from "@remix-run/react"
|
import { Link, useLocation, useNavigate } from "@remix-run/react"
|
||||||
|
|
||||||
import { Commander } from "../Commander/Commander"
|
import { Commander } from "../Commander/Commander"
|
||||||
import { CommanderV1 } from "../Commander/CommanderV1"
|
import { CommanderV1 } from "../Commander/CommanderV2"
|
||||||
import { Icon } from "../Icon/Icon"
|
import { Icon } from "../Icon/Icon"
|
||||||
import { RainbowSkeleton } from "../Skeleton/RainbowSkeleton"
|
import { RainbowSkeleton } from "../Skeleton/RainbowSkeleton"
|
||||||
import { ProfileDrawer } from "./ProfileDrawer"
|
import { ProfileDrawer } from "./ProfileDrawer"
|
@ -1,90 +1,83 @@
|
|||||||
import React from "react"
|
import React from 'react';
|
||||||
import { Box, Center, Flex } from "@chakra-ui/react"
|
import { Box, Center, Flex } from '@chakra-ui/react';
|
||||||
import { Link, useLocation, useNavigate } from "@remix-run/react"
|
import { Link, useLocation, useNavigate } from '@remix-run/react';
|
||||||
|
|
||||||
import { Commander } from "../Commander/Commander"
|
import { Commander } from '../Commander/Commander';
|
||||||
import { CommanderV1 } from "../Commander/CommanderV1"
|
import { CommanderV1 } from '../Commander/CommanderV2';
|
||||||
import { Icon } from "../Icon/Icon"
|
import { Icon } from '../Icon/Icon';
|
||||||
import { RainbowSkeleton } from "../Skeleton/RainbowSkeleton"
|
import { RainbowSkeleton } from '../Skeleton/RainbowSkeleton';
|
||||||
import { ProfileDrawer } from "./ProfileDrawer"
|
import { ProfileDrawer } from './ProfileDrawer';
|
||||||
|
|
||||||
export const Nav = (props) => {
|
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(() => {
|
const toggleProfileDrawer = React.useCallback(() => {
|
||||||
setProfileDrawerOpen(!profileDrawerOpen)
|
setProfileDrawerOpen(!profileDrawerOpen);
|
||||||
}, [profileDrawerOpen])
|
}, [profileDrawerOpen]);
|
||||||
|
|
||||||
const inEditorMode = React.useMemo(() => {
|
const inEditorMode = React.useMemo(() => {
|
||||||
if (pathname.slice(0, 7) === "/editor") {
|
if (pathname.slice(0, 7) === '/editor') {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}, [pathname])
|
}, [pathname]);
|
||||||
|
|
||||||
const inEditMode = React.useMemo(() => {
|
const inEditMode = React.useMemo(() => {
|
||||||
if (pathname.slice(0, 5) === "/edit") {
|
if (pathname.slice(0, 5) === '/edit') {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}, [pathname])
|
}, [pathname]);
|
||||||
|
|
||||||
const editorToggleable = React.useMemo(() => {
|
const editorToggleable = React.useMemo(() => {
|
||||||
if (pathname.slice(0, 7) === "/things") {
|
if (pathname.slice(0, 7) === '/things') {
|
||||||
return true
|
return true;
|
||||||
} else if (pathname.slice(0, 5) === "/edit") {
|
} else if (pathname.slice(0, 5) === '/edit') {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}, [pathname])
|
}, [pathname]);
|
||||||
|
|
||||||
const toggleEdit = React.useCallback(
|
const toggleEdit = React.useCallback(
|
||||||
(e) => {
|
(e) => {
|
||||||
// if first characters of pathname are /things replace with /edit
|
// if first characters of pathname are /things replace with /edit
|
||||||
// or if first characters of pathname are /edit replace with /things
|
// or if first characters of pathname are /edit replace with /things
|
||||||
if (pathname.slice(0, 7) === "/things") {
|
if (pathname.slice(0, 7) === '/things') {
|
||||||
const newPathname = pathname.replace("/things", "/edit")
|
const newPathname = pathname.replace('/things', '/edit');
|
||||||
navigate(newPathname)
|
navigate(newPathname);
|
||||||
} else if (pathname.slice(0, 7) === "/editor") {
|
} else if (pathname.slice(0, 7) === '/editor') {
|
||||||
const newPathname = pathname.replace("/editor", "/things")
|
const newPathname = pathname.replace('/editor', '/things');
|
||||||
navigate(newPathname)
|
navigate(newPathname);
|
||||||
} else if (pathname.slice(0, 5) === "/edit") {
|
} else if (pathname.slice(0, 5) === '/edit') {
|
||||||
const newPathname = pathname.replace("/edit", "/things")
|
const newPathname = pathname.replace('/edit', '/things');
|
||||||
navigate(newPathname)
|
navigate(newPathname);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[pathname, navigate]
|
[pathname, navigate]
|
||||||
)
|
);
|
||||||
|
|
||||||
const toggleEditor = React.useCallback(
|
const toggleEditor = React.useCallback(
|
||||||
(e) => {
|
(e) => {
|
||||||
// if first characters of pathname are /things replace with /edit
|
// if first characters of pathname are /things replace with /edit
|
||||||
// or if first characters of pathname are /edit replace with /things
|
// or if first characters of pathname are /edit replace with /things
|
||||||
if (pathname.slice(0, 7) === "/editor") {
|
if (pathname.slice(0, 7) === '/editor') {
|
||||||
const newPathname = pathname.replace("/editor", "/edit")
|
const newPathname = pathname.replace('/editor', '/edit');
|
||||||
navigate(newPathname)
|
navigate(newPathname);
|
||||||
} else if (pathname.slice(0, 5) === "/edit") {
|
} else if (pathname.slice(0, 5) === '/edit') {
|
||||||
const newPathname = pathname.replace("/edit", "/editor")
|
const newPathname = pathname.replace('/edit', '/editor');
|
||||||
navigate(newPathname)
|
navigate(newPathname);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[pathname, navigate]
|
[pathname, navigate]
|
||||||
)
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box position="fixed" zIndex={9999} top={0} right={0} left={0} maxWidth="100vw">
|
||||||
position="fixed"
|
|
||||||
zIndex={9999}
|
|
||||||
top={0}
|
|
||||||
right={0}
|
|
||||||
left={0}
|
|
||||||
maxWidth="100vw"
|
|
||||||
>
|
|
||||||
<Flex
|
<Flex
|
||||||
as="nav"
|
as="nav"
|
||||||
position="relative"
|
position="relative"
|
||||||
@ -99,25 +92,15 @@ export const Nav = (props) => {
|
|||||||
// bg='white'
|
// bg='white'
|
||||||
// boxShadow={'0px 0px 10px rgba(0,0,0,0.1)'}
|
// boxShadow={'0px 0px 10px rgba(0,0,0,0.1)'}
|
||||||
>
|
>
|
||||||
<Center
|
<Center className="nav-left-section" display={['none', 'flex']} height="100%" marginRight="auto">
|
||||||
className="nav-left-section"
|
|
||||||
display={["none", "flex"]}
|
|
||||||
height="100%"
|
|
||||||
marginRight="auto"
|
|
||||||
>
|
|
||||||
<Center transform="scaleX(-100%)" cursor="pointer">
|
<Center transform="scaleX(-100%)" cursor="pointer">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<Icon size="12px" name="unicorn"></Icon>
|
<Icon size="12px" name="🦄"></Icon>
|
||||||
</Link>
|
</Link>
|
||||||
</Center>
|
</Center>
|
||||||
</Center>
|
</Center>
|
||||||
<CommanderV1 global id="nav" rainbow={false}></CommanderV1>
|
<CommanderV1 global id="nav" rainbow={false}></CommanderV1>
|
||||||
<Center
|
<Center className="nav-right-section" columnGap={[3, 8]} height="100%" marginLeft="auto">
|
||||||
className="nav-right-section"
|
|
||||||
columnGap={[3, 8]}
|
|
||||||
height="100%"
|
|
||||||
marginLeft="auto"
|
|
||||||
>
|
|
||||||
{inEditMode && (
|
{inEditMode && (
|
||||||
<Center
|
<Center
|
||||||
// transform="scaleX(-100%)"
|
// transform="scaleX(-100%)"
|
||||||
@ -126,10 +109,10 @@ export const Nav = (props) => {
|
|||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
chakras={{
|
chakras={{
|
||||||
opacity: inEditorMode ? 1 : 0.3,
|
opacity: inEditorMode ? 1 : 0.3
|
||||||
}}
|
}}
|
||||||
size="12px"
|
size="12px"
|
||||||
name="two eyes"
|
name="👀"
|
||||||
></Icon>
|
></Icon>
|
||||||
{/* <Icon
|
{/* <Icon
|
||||||
size="12px"
|
size="12px"
|
||||||
@ -138,17 +121,13 @@ export const Nav = (props) => {
|
|||||||
</Center>
|
</Center>
|
||||||
)}
|
)}
|
||||||
{editorToggleable && (
|
{editorToggleable && (
|
||||||
<Center
|
<Center transform="scaleX(-100%)" cursor="pointer" onClick={toggleEdit}>
|
||||||
transform="scaleX(-100%)"
|
|
||||||
cursor="pointer"
|
|
||||||
onClick={toggleEdit}
|
|
||||||
>
|
|
||||||
<Icon
|
<Icon
|
||||||
chakras={{
|
chakras={{
|
||||||
opacity: inEditMode ? 1 : 0.3,
|
opacity: inEditMode ? 1 : 0.3
|
||||||
}}
|
}}
|
||||||
size="12px"
|
size="12px"
|
||||||
name="paint"
|
name="🎨"
|
||||||
></Icon>
|
></Icon>
|
||||||
{/* <Icon
|
{/* <Icon
|
||||||
size="12px"
|
size="12px"
|
||||||
@ -156,12 +135,12 @@ export const Nav = (props) => {
|
|||||||
></Icon> */}
|
></Icon> */}
|
||||||
</Center>
|
</Center>
|
||||||
)}
|
)}
|
||||||
<Center transform={["", "scaleX(-100%)"]} cursor="pointer">
|
<Center transform={['', 'scaleX(-100%)']} cursor="pointer">
|
||||||
<Icon size="12px" name="rainbow"></Icon>
|
<Icon size="12px" name="🌈"></Icon>
|
||||||
</Center>
|
</Center>
|
||||||
<Center display={["flex", "none"]} cursor="pointer">
|
<Center display={['flex', 'none']} cursor="pointer">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<Icon size="12px" name="unicorn"></Icon>
|
<Icon size="12px" name="🦄"></Icon>
|
||||||
</Link>
|
</Link>
|
||||||
</Center>
|
</Center>
|
||||||
</Center>
|
</Center>
|
||||||
@ -181,5 +160,5 @@ export const Nav = (props) => {
|
|||||||
</Box>
|
</Box>
|
||||||
{/* <ProfileDrawer isOpen={profileDrawerOpen}></ProfileDrawer> */}
|
{/* <ProfileDrawer isOpen={profileDrawerOpen}></ProfileDrawer> */}
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
};
|
@ -1,8 +1,8 @@
|
|||||||
import React from 'react'
|
import React from "react"
|
||||||
import { Drawer, DrawerBody, DrawerContent, Flex } from '@chakra-ui/react'
|
import { Drawer, DrawerBody, DrawerContent, Flex } from "@chakra-ui/react"
|
||||||
|
|
||||||
export const ProfileDrawer = props => {
|
export const ProfileDrawer = (props) => {
|
||||||
const navItems = ['settings']
|
const navItems = ["settings"]
|
||||||
|
|
||||||
const onClose = React.useCallback(() => {
|
const onClose = React.useCallback(() => {
|
||||||
// nothing
|
// nothing
|
||||||
@ -10,12 +10,12 @@ export const ProfileDrawer = props => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer
|
<Drawer
|
||||||
placement='right'
|
|
||||||
size='md'
|
|
||||||
isOpen={props?.isOpen}
|
isOpen={props?.isOpen}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
|
placement="right"
|
||||||
|
size="md"
|
||||||
>
|
>
|
||||||
<DrawerContent maxW={'90%'} mt={'35px'} className='ProfileDrawer'>
|
<DrawerContent className="ProfileDrawer" maxWidth="90%" marginTop="35px">
|
||||||
<DrawerBody>
|
<DrawerBody>
|
||||||
{navItems.map((item, idx) => {
|
{navItems.map((item, idx) => {
|
||||||
return <Flex key={idx}>{item}</Flex>
|
return <Flex key={idx}>{item}</Flex>
|
70
app/src/components/Nav/ReactiveNav.tsx
Normal file
70
app/src/components/Nav/ReactiveNav.tsx
Normal file
@ -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 (
|
||||||
|
<>
|
||||||
|
<Flex
|
||||||
|
as="nav"
|
||||||
|
position="fixed"
|
||||||
|
right={0}
|
||||||
|
bottom="100%"
|
||||||
|
left={0}
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
flexDirection="row"
|
||||||
|
width="100%"
|
||||||
|
transform={`translateY(${mt})`}
|
||||||
|
transition="all 0.3s ease-in-out"
|
||||||
|
// top={'100%'}
|
||||||
|
// top={0}
|
||||||
|
paddingX="1%"
|
||||||
|
paddingY="1%"
|
||||||
|
>
|
||||||
|
<Hamburger marginLeft="auto"></Hamburger>
|
||||||
|
<Flex
|
||||||
|
position="absolute"
|
||||||
|
top="100%"
|
||||||
|
left="50%"
|
||||||
|
opacity={navActive ? 0 : 1}
|
||||||
|
transition="all 0.2s ease-in-out"
|
||||||
|
translateX="-50%"
|
||||||
|
>
|
||||||
|
{/* w={navActive ? '0px' : '40px'} */}
|
||||||
|
<Attention></Attention>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<RightNav></RightNav>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
import React from 'react'
|
import React from "react"
|
||||||
import { Center, Text } from '@chakra-ui/react'
|
import { Center, Text } from "@chakra-ui/react"
|
||||||
|
|
||||||
export const ReactiveRightNav = props => {
|
export const ReactiveRightNav = (props) => {
|
||||||
const setNav = React.useCallback(active => {
|
const setNav = React.useCallback((active) => {
|
||||||
setMr(active ? '0%' : '-100%')
|
setMr(active ? "0%" : "-100%")
|
||||||
setNavActive(active)
|
setNavActive(active)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ export const ReactiveRightNav = props => {
|
|||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
// react to mouse move event
|
// react to mouse move event
|
||||||
const listener = event => {
|
const listener = (event) => {
|
||||||
const windowWidth = window.innerWidth
|
const windowWidth = window.innerWidth
|
||||||
if (!entered) {
|
if (!entered) {
|
||||||
if (event?.clientX >= windowWidth - 60) {
|
if (event?.clientX >= windowWidth - 60) {
|
||||||
@ -21,56 +21,56 @@ export const ReactiveRightNav = props => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.addEventListener('mousemove', listener)
|
window.addEventListener("mousemove", listener)
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('mousemove', listener)
|
window.removeEventListener("mousemove", listener)
|
||||||
}
|
}
|
||||||
}, [setNav, entered])
|
}, [setNav, entered])
|
||||||
|
|
||||||
const [navActive, setNavActive] = React.useState(false)
|
const [navActive, setNavActive] = React.useState(false)
|
||||||
|
|
||||||
// const defaultMr = '-100%'
|
// const defaultMr = '-100%'
|
||||||
const defaultMr = '0%'
|
const defaultMr = "0%"
|
||||||
|
|
||||||
const [mr, setMr] = React.useState(defaultMr)
|
const [mr, setMr] = React.useState(defaultMr)
|
||||||
|
|
||||||
const navItems = React.useMemo(() => {
|
const navItems = React.useMemo(() => {
|
||||||
return ['home', 'imagine', 'create', 'share']
|
return ["home", "imagine", "create", "share"]
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Center
|
<Center
|
||||||
mr={mr}
|
position="fixed"
|
||||||
transition={'all 0.3s ease-in-out'}
|
|
||||||
position='fixed'
|
|
||||||
top={0}
|
top={0}
|
||||||
right={0}
|
right={0}
|
||||||
h='100%'
|
flexDirection="column"
|
||||||
flexDir='column'
|
height="100%"
|
||||||
|
marginRight={mr}
|
||||||
|
transition="all 0.3s ease-in-out"
|
||||||
>
|
>
|
||||||
<Center
|
<Center
|
||||||
|
flexDirection="column"
|
||||||
|
minWidth="600px"
|
||||||
|
maxWidth="100%"
|
||||||
|
height="85%"
|
||||||
|
background="rgba(0, 0, 0, 0.01)"
|
||||||
|
borderLeftRadius="40px"
|
||||||
onMouseEnter={() => setEntered(true)}
|
onMouseEnter={() => setEntered(true)}
|
||||||
onMouseLeave={() => setEntered(false)}
|
onMouseLeave={() => setEntered(false)}
|
||||||
flexDir={'column'}
|
paddingX={100}
|
||||||
borderLeftRadius={'40px'}
|
paddingY={80}
|
||||||
h='85%'
|
|
||||||
minW={'600px'}
|
|
||||||
maxW='100%'
|
|
||||||
py={80}
|
|
||||||
px={100}
|
|
||||||
bg={`rgba(0, 0, 0, 0.01)`}
|
|
||||||
>
|
>
|
||||||
{navItems.map((navItem, idx) => {
|
{navItems.map((navItem, idx) => {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
color='black'
|
|
||||||
my={'auto'}
|
|
||||||
fontWeight='semibold'
|
|
||||||
key={idx}
|
key={idx}
|
||||||
textTransform={'capitalize'}
|
as="h2"
|
||||||
as='h2'
|
color="black"
|
||||||
cursor='pointer'
|
fontSize="30px"
|
||||||
fontSize='30px'
|
fontWeight="semibold"
|
||||||
|
textTransform="capitalize"
|
||||||
|
cursor="pointer"
|
||||||
|
marginY="auto"
|
||||||
>
|
>
|
||||||
{navItem}
|
{navItem}
|
||||||
</Text>
|
</Text>
|
@ -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
|
// do not render more than the limit of things to prevent infinite loops
|
||||||
|
|
||||||
return safe(props)
|
return safe(props)
|
46
app/src/components/Skeleton/RainbowSkeleton.tsx
Normal file
46
app/src/components/Skeleton/RainbowSkeleton.tsx
Normal file
@ -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 (
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
"@keyframes placeholder-rainbow": keyframes,
|
||||||
|
"@keyframes placeholder-opacity": {
|
||||||
|
"0%": { opacity: 0.2 },
|
||||||
|
"100%": { opacity: 1 },
|
||||||
|
},
|
||||||
|
// add delay
|
||||||
|
animation: `placeholder-rainbow 8s infinite linear, placeholder-opacity 1.3s linear 0s infinite alternate none running}`,
|
||||||
|
}}
|
||||||
|
width="10px"
|
||||||
|
height="8px"
|
||||||
|
borderRadius="2px"
|
||||||
|
cursor="pointer"
|
||||||
|
{...props}
|
||||||
|
></Flex>
|
||||||
|
)
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import { useContext } from "react"
|
import { useContext } from "react"
|
||||||
|
|
||||||
import { ThingtimeContext } from "~/Providers/ThingtimeProvider"
|
import { ThingtimeContext } from "../../Providers/ThingtimeProvider"
|
||||||
|
|
||||||
const getGlobal = () => {
|
const getGlobal = () => {
|
||||||
try {
|
try {
|
||||||
@ -10,7 +10,7 @@ const getGlobal = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useThingtime = (props?: any) => {
|
export const useThingtime = (props?: any): any => {
|
||||||
const value = useContext(ThingtimeContext)
|
const value = useContext(ThingtimeContext)
|
||||||
|
|
||||||
// const { thingtime, setThingtime, getThingtime, thingtimeRef } = value
|
// const { thingtime, setThingtime, getThingtime, thingtimeRef } = value
|
@ -1,6 +1,6 @@
|
|||||||
import { hydrate } from 'react-dom'
|
import { hydrate } from "react-dom"
|
||||||
// import { RemixBrowser } from "remix";
|
// import { RemixBrowser } from "remix";
|
||||||
import { RemixBrowser } from '@remix-run/react'
|
import { RemixBrowser } from "@remix-run/react"
|
||||||
try {
|
try {
|
||||||
window.process = {}
|
window.process = {}
|
||||||
} catch (err) {
|
} catch (err) {
|
21
app/src/entry.server.tsx
Normal file
21
app/src/entry.server.tsx
Normal file
@ -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(
|
||||||
|
<RemixServer context={remixContext} url={request.url} />
|
||||||
|
)
|
||||||
|
|
||||||
|
responseHeaders.set("Content-Type", "text/html")
|
||||||
|
|
||||||
|
return new Response("<!DOCTYPE html>" + markup, {
|
||||||
|
status: responseStatusCode,
|
||||||
|
headers: responseHeaders,
|
||||||
|
})
|
||||||
|
}
|
21
app/src/global-types.d.ts
vendored
Normal file
21
app/src/global-types.d.ts
vendored
Normal file
@ -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<any>): React.ReactElement | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
8
app/src/gp/Sample.js
Normal file
8
app/src/gp/Sample.js
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
8
app/src/gp/Segment.js
Normal file
8
app/src/gp/Segment.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { getMiddleSample } from "./_utils"
|
||||||
|
|
||||||
|
export default class Segment {
|
||||||
|
constructor({ samples }) {
|
||||||
|
this.samples = samples
|
||||||
|
this.progress = getMiddleSample(samples).progress
|
||||||
|
}
|
||||||
|
}
|
1
app/src/gp/_constants.js
Normal file
1
app/src/gp/_constants.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const DEFAULT_PRECISION = 2
|
@ -1,7 +1,7 @@
|
|||||||
import Sample from './Sample';
|
import { DEFAULT_PRECISION } from "./_constants"
|
||||||
import Segment from './Segment';
|
import { convertPathToNode } from "./_utils"
|
||||||
import { convertPathToNode } from './_utils';
|
import Sample from "./Sample"
|
||||||
import { DEFAULT_PRECISION } from './_constants';
|
import Segment from "./Segment"
|
||||||
|
|
||||||
// The main function responsible for getting data
|
// The main function responsible for getting data
|
||||||
// This will take a path, number of samples, number of samples, and a precision value
|
// This will take a path, number of samples, number of samples, and a precision value
|
||||||
@ -11,34 +11,34 @@ export const getData = ({
|
|||||||
path,
|
path,
|
||||||
segments,
|
segments,
|
||||||
samples,
|
samples,
|
||||||
precision = DEFAULT_PRECISION
|
precision = DEFAULT_PRECISION,
|
||||||
}) => {
|
}) => {
|
||||||
// Convert the given path to a DOM node if it isn't already one
|
// 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
|
// 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
|
// 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(),
|
const pathLength = path.getTotalLength(),
|
||||||
totalSamples = segments * samples,
|
totalSamples = segments * samples,
|
||||||
allSamples = [],
|
allSamples = [],
|
||||||
allSegments = [];
|
allSegments = []
|
||||||
|
|
||||||
// For the number of total samples, get the x, y, and progress values for each sample along the path
|
// 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++) {
|
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 the user asks to round our x and y values, do so
|
||||||
if (precision) {
|
if (precision) {
|
||||||
x = +x.toFixed(precision);
|
x = +x.toFixed(precision)
|
||||||
y = +y.toFixed(precision);
|
y = +y.toFixed(precision)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Sample and push it onto the allSamples array
|
// 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
|
// 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++) {
|
for (let segment = 0; segment < segments; segment++) {
|
||||||
const currentStart = segment * samples,
|
const currentStart = segment * samples,
|
||||||
nextStart = currentStart + samples,
|
nextStart = currentStart + samples,
|
||||||
segmentSamples = [];
|
segmentSamples = []
|
||||||
|
|
||||||
// Push all current samples onto segmentSamples
|
// Push all current samples onto segmentSamples
|
||||||
for (let samInSeg = 0; samInSeg < samples; samInSeg++) {
|
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
|
// 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
|
// 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 our group of segments
|
||||||
return allSegments;
|
return allSegments
|
||||||
};
|
}
|
||||||
|
|
||||||
// The function responsible for converting strokable data (from getData()) into fillable data
|
// 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
|
// 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,
|
outlinedStrokes,
|
||||||
precision,
|
precision,
|
||||||
pathClosed
|
pathClosed
|
||||||
);
|
)
|
||||||
|
|
||||||
return averagedSegmentJoins;
|
return averagedSegmentJoins
|
||||||
};
|
}
|
||||||
|
|
||||||
// An internal function for outlining stroked data
|
// An internal function for outlining stroked data
|
||||||
const outlineStrokes = (data, width, precision) => {
|
const outlineStrokes = (data, width, precision) => {
|
||||||
@ -85,53 +85,53 @@ const outlineStrokes = (data, width, precision) => {
|
|||||||
const p0 = new Sample({
|
const p0 = new Sample({
|
||||||
...startPoint,
|
...startPoint,
|
||||||
x: Math.sin(angle) * radius + startPoint.x,
|
x: Math.sin(angle) * radius + startPoint.x,
|
||||||
y: -Math.cos(angle) * radius + startPoint.y
|
y: -Math.cos(angle) * radius + startPoint.y,
|
||||||
}),
|
}),
|
||||||
p1 = new Sample({
|
p1 = new Sample({
|
||||||
...startPoint,
|
...startPoint,
|
||||||
x: -Math.sin(angle) * radius + startPoint.x,
|
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 the user asks to round our x and y values, do so
|
||||||
if (precision) {
|
if (precision) {
|
||||||
p0.x = +p0.x.toFixed(precision);
|
p0.x = +p0.x.toFixed(precision)
|
||||||
p0.y = +p0.y.toFixed(precision);
|
p0.y = +p0.y.toFixed(precision)
|
||||||
p1.x = +p1.x.toFixed(precision);
|
p1.x = +p1.x.toFixed(precision)
|
||||||
p1.y = +p1.y.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
|
// We need to set the radius (half of the width) and have a holding array for outlined Segments
|
||||||
const radius = width / 2,
|
const radius = width / 2,
|
||||||
outlinedData = [];
|
outlinedData = []
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const samples = data[i].samples,
|
const samples = data[i].samples,
|
||||||
segmentSamples = [];
|
segmentSamples = []
|
||||||
|
|
||||||
// For each sample point and the following sample point (if there is one) compute the angle
|
// 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)
|
// 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++) {
|
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 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
|
const p0 = samples[j], // First point
|
||||||
p1 = samples[j + 1], // Second point
|
p1 = samples[j + 1], // Second point
|
||||||
angle = Math.atan2(p1.y - p0.y, p1.x - p0.x), // Perpendicular angle to p0 and p1
|
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
|
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
|
// 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
|
// The p0 for j > 0 will always be the same as p1 anyhow, so let's not add redundant points
|
||||||
if (j === 0) {
|
if (j === 0) {
|
||||||
segmentSamples.push(...p0Perps);
|
segmentSamples.push(...p0Perps)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always push the second sample point's perpendicular points
|
// Always push the second sample point's perpendicular points
|
||||||
segmentSamples.push(...p1Perps);
|
segmentSamples.push(...p1Perps)
|
||||||
}
|
}
|
||||||
|
|
||||||
// segmentSamples is out of order...
|
// segmentSamples is out of order...
|
||||||
@ -140,14 +140,14 @@ const outlineStrokes = (data, width, precision) => {
|
|||||||
new Segment({
|
new Segment({
|
||||||
samples: [
|
samples: [
|
||||||
...segmentSamples.filter((s, i) => i % 2 === 0),
|
...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
|
// 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
|
// 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)
|
// Find the average x and y between two points (p0 and p1)
|
||||||
const avg = (p0, p1) => ({
|
const avg = (p0, p1) => ({
|
||||||
x: (p0.x + p1.x) / 2,
|
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
|
// Recombine the new x and y positions with all the other keys in the object
|
||||||
const combine = (segment, pos, avg) => ({
|
const combine = (segment, pos, avg) => ({
|
||||||
...segment[pos],
|
...segment[pos],
|
||||||
x: avg.x,
|
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++) {
|
for (let i = 0; i < outlinedData.length; i++) {
|
||||||
// If path is closed: the current segment's samples;
|
// If path is closed: the current segment's samples;
|
||||||
@ -186,34 +186,34 @@ const averageSegmentJoins = (outlinedData, precision, pathClosed) => {
|
|||||||
? outlinedData[i + 1].samples
|
? outlinedData[i + 1].samples
|
||||||
: init_outlinedData[0].samples,
|
: init_outlinedData[0].samples,
|
||||||
currentMiddle = currentSamples.length / 2, // The "middle" sample in the current segment's 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
|
// Average two sets of outlined samples to create p0Average and p1Average
|
||||||
const p0Average = avg(currentSamples[currentMiddle - 1], nextSamples[0]),
|
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 the user asks to round our x and y values, do so
|
||||||
if (precision) {
|
if (precision) {
|
||||||
p0Average.x = +p0Average.x.toFixed(precision);
|
p0Average.x = +p0Average.x.toFixed(precision)
|
||||||
p0Average.y = +p0Average.y.toFixed(precision);
|
p0Average.y = +p0Average.y.toFixed(precision)
|
||||||
p1Average.x = +p1Average.x.toFixed(precision);
|
p1Average.x = +p1Average.x.toFixed(precision)
|
||||||
p1Average.y = +p1Average.y.toFixed(precision);
|
p1Average.y = +p1Average.y.toFixed(precision)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the previous values with new Samples
|
// Replace the previous values with new Samples
|
||||||
currentSamples[currentMiddle - 1] = new Sample({
|
currentSamples[currentMiddle - 1] = new Sample({
|
||||||
...combine(currentSamples, currentMiddle - 1, p0Average)
|
...combine(currentSamples, currentMiddle - 1, p0Average),
|
||||||
});
|
})
|
||||||
currentSamples[currentMiddle] = new Sample({
|
currentSamples[currentMiddle] = new Sample({
|
||||||
...combine(currentSamples, currentMiddle, p1Average)
|
...combine(currentSamples, currentMiddle, p1Average),
|
||||||
});
|
})
|
||||||
nextSamples[0] = new Sample({
|
nextSamples[0] = new Sample({
|
||||||
...combine(nextSamples, 0, p0Average)
|
...combine(nextSamples, 0, p0Average),
|
||||||
});
|
})
|
||||||
nextSamples[nextEnd] = new Sample({
|
nextSamples[nextEnd] = new Sample({
|
||||||
...combine(nextSamples, nextEnd, p1Average)
|
...combine(nextSamples, nextEnd, p1Average),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return outlinedData;
|
return outlinedData
|
||||||
};
|
}
|
@ -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
|
// An internal function to help with the repetition of adding fill, stroke, and stroke-width attributes
|
||||||
export const styleAttrs = (
|
export const styleAttrs = (fill, stroke, strokeWidth, progress, animation) => {
|
||||||
fill,
|
|
||||||
stroke,
|
|
||||||
strokeWidth,
|
|
||||||
progress,
|
|
||||||
animation
|
|
||||||
) => {
|
|
||||||
const determineColor = (type, progress) =>
|
const determineColor = (type, progress) =>
|
||||||
typeof type === "string" ? type : tinygradient(type).rgbAt(progress)
|
typeof type === "string" ? type : tinygradient(type).rgbAt(progress)
|
||||||
|
|
||||||
@ -38,9 +32,9 @@ export const styleAttrs = (
|
|||||||
|
|
||||||
if (animation?.name) {
|
if (animation?.name) {
|
||||||
// TODO: add animation-direction support
|
// TODO: add animation-direction support
|
||||||
|
|
||||||
const duration = animation.duration || 5
|
const duration = animation.duration || 5
|
||||||
|
|
||||||
attrs["style"] = `
|
attrs["style"] = `
|
||||||
animation-name: ${animation?.name};
|
animation-name: ${animation?.name};
|
||||||
animation-delay: ${progress * duration - duration}s;
|
animation-delay: ${progress * duration - duration}s;
|
2
app/src/gp/index.js
Normal file
2
app/src/gp/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { default as GradientPath } from "./GradientPath"
|
||||||
|
export { getData, strokeToFill } from "./_data"
|
@ -1,6 +1,6 @@
|
|||||||
export const config = { runtime: 'edge' }
|
export const config = { runtime: "edge" }
|
||||||
|
|
||||||
export default function Edge () {
|
export default function Edge() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Welcome to Thingtime@Edge</h1>
|
<h1>Welcome to Thingtime@Edge</h1>
|
@ -15,7 +15,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"~/*": ["./app/*"]
|
"~/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
|
||||||
// Remix takes care of building everything in `remix build`.
|
// Remix takes care of building everything in `remix build`.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"build": {
|
"build": {
|
||||||
"env": {
|
"env": {
|
||||||
"ENABLE_FILE_SYSTEM_API": "1"
|
"ENABLE_FILE_SYSTEM_API": "1"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user