feat: main Added good eslint presets and rules

This commit is contained in:
Nikolaj Frey 2023-07-04 18:05:08 +10:00
parent 4fb03692ce
commit 7aae5d4970
16 changed files with 2193 additions and 899 deletions

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
"remix": "npm run dev --prefix remix", "remix": "npm run dev --prefix remix",
"api": "npm run dev --prefix api", "api": "npm run dev --prefix api",
"build": "npm run build --prefix remix", "build": "npm run build --prefix remix",
"postinstall": "npm ci --prefix remix ; npm ci --prefix=api" "postinstall": "pnpm i --prefix remix ; pnpm i --prefix=api"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -1,6 +1,84 @@
module.exports = { module.exports = {
extends: ['@remix-run/eslint-config', '@remix-run/eslint-config/node'] parser: "@typescript-eslint/parser",
// rules: { parserOptions: {
// 'max-len': [2, { code: 70 }] ecmaVersion: 2020,
// } sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
env: {
browser: true,
node: true,
es6: true,
},
settings: {
react: {
version: "detect",
},
},
plugins: ["@typescript-eslint", "react", "prettier", "unused-imports", "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" }],
"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",
},
},
],
} }

View File

@ -23,6 +23,7 @@ export const colors = {
throat: '#42A5F5', throat: '#42A5F5',
thirdEye: '#5C6BC0', thirdEye: '#5C6BC0',
crown: '#AB47BC', crown: '#AB47BC',
red: '#C62828', red: '#C62828',
orange: '#FF7043', orange: '#FF7043',
yellow: '#FFEE58', yellow: '#FFEE58',

View File

@ -1,15 +1,18 @@
import React, { createContext } from 'react' import React, { createContext } from "react"
import { sanitise } from '~/functions/path'
import { smarts } from '~/smarts' import { sanitise } from "~/functions/sanitise"
import { smarts } from "~/smarts"
export interface ThingtimeContextInterface { export interface ThingtimeContextInterface {
thingtime: any thingtime: any
setThingtime: any setThingtime: any
getThingtime: any
thingtimeRef: any
} }
export const ThingtimeContext = createContext<ThingtimeContextInterface | null>( export const ThingtimeContext = createContext<
null ThingtimeContextInterface[] | null
) >(null)
try { try {
window.smarts = smarts window.smarts = smarts
@ -20,32 +23,32 @@ try {
const forceable = { const forceable = {
Content: { Content: {
hidden1: "Edit this to your heart's desire.", hidden1: "Edit this to your heart's desire.",
'How?': 'Just search for Content and edit the value to whatever you want.', "How?": "Just search for Content and edit the value to whatever you want.",
'Example:': `Content = New Content! "Example:": `Content = New Content!
Content.Nested Content = New Nested Content! Content.Nested Content = New Nested Content!
` `,
} },
} }
const initialThingtime = { const initialThingtime = {
nav: {}, nav: {},
version: 22, version: 22,
...forceable ...forceable,
} }
const userData = { const userData = {
settings: { settings: {
showCommander: true, showCommander: true,
clearCommanderOnToggle: true, clearCommanderOnToggle: true,
clearCommanderContextOnToggle: true clearCommanderContextOnToggle: true,
}, },
...forceable ...forceable,
} }
export const ThingtimeProvider = (props: any): JSX.Element => { export const ThingtimeProvider = (props: any): JSX.Element => {
const [thingtime, set] = React.useState({ const [thingtime, set] = React.useState({
...initialThingtime, ...initialThingtime,
...userData ...userData,
}) })
const thingtimeRef = React.useRef(thingtime) const thingtimeRef = React.useRef(thingtime)
@ -53,7 +56,7 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
// get thingtime from localstorage // get thingtime from localstorage
React.useEffect(() => { React.useEffect(() => {
try { try {
const thingtimeFromLocalStorage = window.localStorage.getItem('thingtime') const thingtimeFromLocalStorage = window.localStorage.getItem("thingtime")
if (thingtimeFromLocalStorage) { if (thingtimeFromLocalStorage) {
const parsed = JSON.parse(thingtimeFromLocalStorage) const parsed = JSON.parse(thingtimeFromLocalStorage)
@ -65,14 +68,14 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
} else { } else {
const newThingtime = { const newThingtime = {
...parsed, ...parsed,
...initialThingtime ...initialThingtime,
} }
set(newThingtime) set(newThingtime)
} }
} }
} }
} catch (err) { } catch (err) {
console.error('There was an error getting thingtime from localStorage') console.error("There was an error getting thingtime from localStorage")
} }
}, []) }, [])
@ -80,9 +83,9 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
thingtimeRef.current = thingtime thingtimeRef.current = thingtime
try { try {
window.localStorage.setItem('thingtime', JSON.stringify(thingtime)) window.localStorage.setItem("thingtime", JSON.stringify(thingtime))
} catch (err) { } catch (err) {
console.error('There was an error saving thingtime to localStorage') console.error("There was an error saving thingtime to localStorage")
} }
}, [thingtime]) }, [thingtime])
@ -91,7 +94,7 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
const prevThingtime = thingtime const prevThingtime = thingtime
const newThingtime = { const newThingtime = {
...prevThingtime ...prevThingtime,
} }
// check if first characters of path starts with thingtime or tt and strip from path // check if first characters of path starts with thingtime or tt and strip from path
@ -102,9 +105,9 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
// subtract last path part from dot delimitted path // subtract last path part from dot delimitted path
// prop1.prop2.prop3 => prop1.prop2 // prop1.prop2.prop3 => prop1.prop2
const pathParts = path.split('.') const pathParts = path.split(".")
pathParts.pop() pathParts.pop()
const parentPath = pathParts.join('.') const parentPath = pathParts.join(".")
if (parentPath?.length) { if (parentPath?.length) {
const parent = smarts.getsmart(newThingtime, parentPath) const parent = smarts.getsmart(newThingtime, parentPath)
@ -121,10 +124,17 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
const getThingtime = React.useCallback( const getThingtime = React.useCallback(
(...args) => { (...args) => {
const path = args[0] const rawPath = args[0]
if (path === 'thingtime' || path === 'tt' || path === '.' || !path) { if (
rawPath === "thingtime" ||
rawPath === "tt" ||
rawPath === "." ||
!rawPath
) {
return thingtime return thingtime
} }
const path = sanitise(rawPath)
console.log("Getting thingtime at path", path)
return smarts.getsmart(thingtime, path) return smarts.getsmart(thingtime, path)
}, },
[thingtime] [thingtime]
@ -138,12 +148,12 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
// nothing // nothing
} }
const keyListener = e => {} const keyListener = (e) => {}
window.addEventListener('keydown', keyListener) window.addEventListener("keydown", keyListener)
return () => { return () => {
window.removeEventListener('keydown', keyListener) window.removeEventListener("keydown", keyListener)
} }
}, [setThingtime, thingtime]) }, [setThingtime, thingtime])
@ -151,7 +161,7 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
thingtime, thingtime,
setThingtime, setThingtime,
getThingtime, getThingtime,
thingtimeRef thingtimeRef,
} }
return ( return (

View File

@ -1,31 +1,34 @@
import React from 'react' import React from "react"
import { Center, Box, Flex, Input } from '@chakra-ui/react' import ClickAwayListener from "react-click-away-listener"
import { useThingtime } from '../Thingtime/useThingtime' import { Center, Flex, Input } from "@chakra-ui/react"
import { Thingtime } from '../Thingtime/Thingtime'
import { sanitise } from '~/functions/path'
import ClickAwayListener from 'react-click-away-listener'
export const Commander = props => { import { Thingtime } from "../Thingtime/Thingtime"
import { useThingtime } from "../Thingtime/useThingtime"
import { sanitise } from "~/functions/sanitise"
import { getParentPath } from "~/smarts"
export const Commander = (props) => {
const { thingtime, setThingtime, getThingtime, thingtimeRef } = useThingtime() const { thingtime, setThingtime, getThingtime, thingtimeRef } = useThingtime()
const inputRef = React.useRef() const inputRef = React.useRef()
const [value, setValue] = React.useState('') const [value, setValue] = React.useState("")
const [contextPath, setContextPath] = React.useState() const [contextPath, setContextPath] = React.useState()
const [showContext, setShowContextState] = React.useState(false) const [showContext, setShowContextState] = React.useState(false)
const setShowContext = React.useCallback( const setShowContext = React.useCallback(
(value, from) => { (value, from?: string) => {
setShowContextState(value) setShowContextState(value)
}, },
[setShowContextState] [setShowContextState]
) )
const [suggestions, setSuggestions] = React.useState([]) // const [suggestions, setSuggestions] = React.useState([])
const contextValue = React.useMemo(() => { const contextValue = React.useMemo(() => {
console.log('thingtime updated!') // TODO: Figure out why this is running on every click
const ret = getThingtime(contextPath) const ret = getThingtime(contextPath)
return ret return ret
}, [contextPath, getThingtime]) }, [contextPath, getThingtime])
@ -34,33 +37,26 @@ export const Commander = props => {
return thingtime?.settings?.showCommander return thingtime?.settings?.showCommander
}, [thingtime?.settings?.showCommander]) }, [thingtime?.settings?.showCommander])
// watch value
React.useEffect(() => {
if (!value?.length) {
setSuggestions([])
}
}, [value])
// showCommander useEffect // showCommander useEffect
React.useEffect(() => { React.useEffect(() => {
if (showCommander) { if (showCommander) {
inputRef?.current?.focus?.() inputRef?.current?.focus?.()
} else { } else {
if (thingtimeRef?.current?.settings?.clearCommanderOnToggle) { if (thingtimeRef?.current?.settings?.clearCommanderOnToggle) {
setValue('') setValue("")
} }
if (thingtimeRef?.current?.settings?.clearCommanderContextOnToggle) { if (thingtimeRef?.current?.settings?.clearCommanderContextOnToggle) {
setShowContext(false, 'showCommander useEffect') setShowContext(false, "showCommander useEffect")
} }
} }
}, [showCommander, thingtimeRef, setShowContext]) }, [showCommander, thingtimeRef, setShowContext])
const onChange = React.useCallback(e => { const onChange = React.useCallback((e) => {
setValue(e.target.value) setValue(e.target.value)
}, []) }, [])
const validSetters = React.useMemo(() => { const validSetters = React.useMemo(() => {
return ['=', ' is '] return ["=", " is "]
}, []) }, [])
const command = React.useMemo(() => { const command = React.useMemo(() => {
@ -70,35 +66,39 @@ export const Commander = props => {
const indexOfSplitter = sanitizedCommand?.indexOf(validSetters[0]) const indexOfSplitter = sanitizedCommand?.indexOf(validSetters[0])
const [pathRaw, valRaw] = [ const [pathRaw, valRaw] = [
sanitizedCommand?.slice(0, indexOfSplitter), sanitizedCommand?.slice(0, indexOfSplitter),
sanitizedCommand?.slice(indexOfSplitter + validSetters[0]?.length) sanitizedCommand?.slice(indexOfSplitter + validSetters[0]?.length),
] ]
return [pathRaw?.trim(), valRaw?.trim()] return [pathRaw?.trim(), valRaw?.trim()]
} else if (sanitizedCommand?.includes(validSetters[1])) { } else if (sanitizedCommand?.includes(validSetters[1])) {
const indexOfSplitter = sanitizedCommand?.indexOf(validSetters[1]) const indexOfSplitter = sanitizedCommand?.indexOf(validSetters[1])
const [pathRaw, valRaw] = [ const [pathRaw, valRaw] = [
sanitizedCommand?.slice(0, indexOfSplitter), sanitizedCommand?.slice(0, indexOfSplitter),
sanitizedCommand?.slice(indexOfSplitter + validSetters[1]?.length) sanitizedCommand?.slice(indexOfSplitter + validSetters[1]?.length),
] ]
return [pathRaw?.trim(), valRaw?.trim()] return [pathRaw?.trim(), valRaw?.trim()]
} }
console.log("nik sanitizedCommand", sanitizedCommand)
return [sanitizedCommand] return [sanitizedCommand]
}, [value, validSetters]) }, [value, validSetters])
const commandContainsPath = React.useMemo(() => {
const suggestionsIncludesSubstring = suggestions?.find(suggestion => {
return command?.includes(suggestion)
})
return suggestionsIncludesSubstring
}, [suggestions, command])
const commandPath = React.useMemo(() => { const commandPath = React.useMemo(() => {
return command?.[0] return sanitise(command?.[0])
}, [command]) }, [command])
const commandValue = React.useMemo(() => { const commandValue = React.useMemo(() => {
return command?.[1] return command?.[1]
}, [command]) }, [command])
const commandContainsPath = React.useMemo(() => {
console.log("nik command", commandPath)
// const commandIncludesSuggestion = suggestions?.find(suggestion => {
// return commandPath?.includes(suggestion)
// })
// console.log('nik commandIncludesSuggestion', commandIncludesSuggestion)
return false
// return commandIncludesSuggestion
}, [commandPath])
const validQuotations = React.useMemo(() => { const validQuotations = React.useMemo(() => {
return ['"', "'"] return ['"', "'"]
}, []) }, [])
@ -124,26 +124,28 @@ export const Commander = props => {
return commandPath && commandValue return commandPath && commandValue
}, [commandPath, commandValue]) }, [commandPath, commandValue])
// thingtime changes update suggestions const suggestions = React.useMemo(() => {
React.useEffect(() => {
// when thingtime changes, update suggestions
// with all flattened key path values recursively
if (value?.length) { if (value?.length) {
const suggestions = ['tt', 'thingtime', '.'] const suggestions = ["tt", "thingtime", "."]
const recurse = (obj, path) => { const populateSuggestions = (obj, path) => {
Object.keys(obj).forEach(key => { Object.keys(obj).forEach((key) => {
const val = obj[key] const val = obj[key]
const newPath = path ? `${path}.${key}` : key const newPath = path ? `${path}${path ? "." : ""}${key}` : key
if (typeof val === 'object') { if (typeof val === "object") {
suggestions.push(newPath) suggestions.push(newPath)
recurse(val, newPath) populateSuggestions(val, newPath)
} else { } else {
suggestions.push(newPath) suggestions.push(newPath)
} }
}) })
} }
recurse(thingtime, '')
// populateSuggestions(thingtime, commandPath)
populateSuggestions(thingtime, "")
// console.log('nik suggestions', suggestions)
console.log("nik useEffect suggestions commandPath", commandPath)
if (commandPath) { if (commandPath) {
const filteredSuggestions = suggestions.filter((suggestion, i) => { const filteredSuggestions = suggestions.filter((suggestion, i) => {
@ -151,25 +153,26 @@ export const Commander = props => {
}) })
if (!filteredSuggestions?.includes(commandPath)) { if (!filteredSuggestions?.includes(commandPath)) {
const adjustedSuggestions = [commandPath, ...filteredSuggestions] const adjustedSuggestions = [commandPath, ...filteredSuggestions]
setSuggestions(adjustedSuggestions) return adjustedSuggestions
} else { } else {
setSuggestions(filteredSuggestions) return filteredSuggestions
} }
} else { } else {
setSuggestions(suggestions) return suggestions
} }
// if (value) { // if (value) {
// setShowContext(true, 'Thingtime changes update suggestions') // setShowContext(true, 'Thingtime changes update suggestions')
// } // }
} }
}, [thingtime, value, commandPath, setShowContext]) }, [value, thingtime, commandPath, setShowContext])
const onEnter = React.useCallback( const onEnter = React.useCallback(
props => { (props) => {
// if first characters of value equal tt. then run command // if first characters of value equal tt. then run command
// or if first character is a dot then run command // or if first character is a dot then run command
try { try {
console.log("Commander onEnter")
if (commandIsAction) { if (commandIsAction) {
// nothing // nothing
try { try {
@ -177,20 +180,22 @@ export const Commander = props => {
const evalFn = eval(fn) const evalFn = eval(fn)
const realVal = evalFn() const realVal = evalFn()
const prevVal = getThingtime(commandPath) const prevVal = getThingtime(commandPath)
const parentPath = getParentPath(commandPath)
setThingtime(commandPath, realVal) setThingtime(commandPath, realVal)
if (!prevVal) { if (!prevVal) {
setContextPath(commandPath) setContextPath(parentPath)
setShowContext(true, 'commandIsAction check') setShowContext(true, "commandIsAction check")
} }
} catch (err) { } catch (err) {
console.log('setThingtime errored in Commander', err) console.log("setThingtime errored in Commander", err)
} }
} else if (commandContainsPath) { } else if (commandContainsPath) {
console.log("Setting context path", commandPath)
setContextPath(commandPath) setContextPath(commandPath)
setShowContext(true, 'commandContainsPath check') setShowContext(true, "commandContainsPath check")
} }
} catch (err) { } catch (err) {
console.error('Caught error on commander onEnter', err) console.error("Caught error on commander onEnter", err)
} }
}, },
[ [
@ -199,14 +204,14 @@ export const Commander = props => {
setThingtime, setThingtime,
commandIsAction, commandIsAction,
commandPath, commandPath,
commandContainsPath commandContainsPath,
] ]
) )
// trigger on enter // trigger on enter
const onKeyDown = React.useCallback( const onKeyDown = React.useCallback(
e => { (e) => {
if (e.key === 'Enter') { if (e.key === "Enter") {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
onEnter({ e }) onEnter({ e })
@ -220,15 +225,23 @@ export const Commander = props => {
) )
const openCommander = React.useCallback(() => { const openCommander = React.useCallback(() => {
setThingtime('settings.showCommander', true) setThingtime("settings.showCommander", true)
}, [setThingtime]) }, [setThingtime])
const closeCommander = React.useCallback(() => { const closeCommander = React.useCallback(() => {
setThingtime('settings.showCommander', false) if (thingtime?.settings?.showCommander) {
setValue('') setThingtime("settings.showCommander", false)
setShowContext(false) }
setContextPath(undefined) if (value !== "") {
}, [setThingtime, setShowContext]) setValue("")
}
if (contextPath !== undefined) {
setContextPath(undefined)
}
if (showContext !== false) {
setShowContext(false)
}
}, [setThingtime, setShowContext, value, contextPath, showContext])
const toggleCommander = React.useCallback(() => { const toggleCommander = React.useCallback(() => {
if (thingtime?.settings?.showCommander) { if (thingtime?.settings?.showCommander) {
@ -240,104 +253,104 @@ export const Commander = props => {
React.useEffect(() => { React.useEffect(() => {
const keyListener = (e: any) => { const keyListener = (e: any) => {
if (e?.metaKey && e?.code === 'KeyP') { if (e?.metaKey && e?.code === "KeyP") {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
toggleCommander() toggleCommander()
} }
// if key escape close all modals // if key escape close all modals
console.log('commander key listener e?.code', e?.code) console.log("commander key listener e?.code", e?.code)
if (e?.code === 'Escape') { if (e?.code === "Escape") {
closeCommander() closeCommander()
} }
} }
window.addEventListener('keydown', keyListener) window.addEventListener("keydown", keyListener)
return () => { return () => {
window.removeEventListener('keydown', keyListener) window.removeEventListener("keydown", keyListener)
} }
}, [setThingtime, thingtime, toggleCommander, closeCommander]) }, [setThingtime, thingtime, toggleCommander, closeCommander])
const selectSuggestion = React.useCallback( const selectSuggestion = React.useCallback(
suggestion => { (suggestion) => {
setValue(suggestion) setValue(suggestion)
setContextPath(suggestion) setContextPath(suggestion)
setShowContext(true, 'Select suggestion') setShowContext(true, "Select suggestion")
}, },
[setValue, setContextPath, setShowContext] [setValue, setContextPath, setShowContext]
) )
const excludedSuggestions = React.useMemo(() => { const excludedSuggestions = React.useMemo(() => {
return ['.'] return ["."]
}, []) }, [])
const renderedSuggestions = React.useMemo(() => { const renderedSuggestions = React.useMemo(() => {
return suggestions?.filter(suggestion => { return suggestions?.filter((suggestion) => {
return !excludedSuggestions?.includes(suggestion) return !excludedSuggestions?.includes(suggestion)
}) })
}, [suggestions, excludedSuggestions]) }, [suggestions, excludedSuggestions])
const mobileVW = React.useMemo(() => { const mobileVW = React.useMemo(() => {
return 'calc(100vw - 45px)' return "calc(100vw - 45px)"
}, []) }, [])
return ( return (
<ClickAwayListener onClickAway={closeCommander}> <ClickAwayListener onClickAway={closeCommander}>
<Flex <Flex
id='commander' position="absolute"
// display={['flex', showCommander ? 'flex' : 'none']} // display={['flex', showCommander ? 'flex' : 'none']}
justifyContent={['flex-start', 'center']} top={0}
// zIndex={99999} // zIndex={99999}
// position='fixed' // position='fixed'
// top='100px' // top='100px'
pointerEvents={'none'}
position='absolute'
h='100%'
top={0}
left={0}
right={0} right={0}
py={1} left={0}
px={1} justifyContent={["flex-start", "center"]}
maxW='100%' maxWidth="100%"
height="100%"
pointerEvents="none"
id="commander"
paddingX={1}
paddingY={1}
> >
<Flex <Flex
alignItems={['flex-start', 'center']} position="absolute"
position='absolute' top="100%"
top={'100%'}
maxH='90vh'
overflowY='scroll'
left={0}
right={0} right={0}
h='auto' left={0}
mt={2} alignItems={["flex-start", "center"]}
mx={1} flexDirection="column"
maxW='100%' overflowY="scroll"
borderRadius={'12px'} maxWidth="100%"
flexDir='column' height="auto"
maxHeight="90vh"
marginTop={2}
borderRadius="12px"
marginX={1}
> >
<Flex <Flex
display={renderedSuggestions?.length ? 'flex' : 'none'} flexDirection="column"
w={['100%', '400px']} display={renderedSuggestions?.length ? "flex" : "none"}
maxW={'100%'} width={["100%", "400px"]}
bg='grey' maxWidth="100%"
borderRadius={'12px'} marginBottom={3}
flexDir='column' background="grey"
id='commander-suggestions' borderRadius="12px"
py={3} pointerEvents="all"
mb={3} id="commander-suggestions"
pointerEvents={'all'} paddingY={3}
> >
{renderedSuggestions.map((suggestion, i) => { {renderedSuggestions?.map((suggestion, i) => {
return ( return (
<Flex <Flex
cursor='pointer'
px={4}
_hover={{
bg: 'greys.medium'
}}
key={i} key={i}
_hover={{
bg: "greys.medium",
}}
cursor="pointer"
onClick={() => selectSuggestion(suggestion)} onClick={() => selectSuggestion(suggestion)}
paddingX={4}
> >
{suggestion} {suggestion}
</Flex> </Flex>
@ -345,60 +358,46 @@ export const Commander = props => {
})} })}
</Flex> </Flex>
<Flex <Flex
display={showContext ? 'flex' : 'none'} display={showContext ? "flex" : "none"}
maxW='100%' maxWidth="100%"
py={3} background="grey"
borderRadius={'12px'} borderRadius="12px"
bg='grey' pointerEvents="all"
pointerEvents={'all'} paddingY={3}
> >
<Thingtime thing={contextValue}></Thingtime> <Thingtime thing={contextValue}></Thingtime>
</Flex> </Flex>
</Flex> </Flex>
<Center <Center
position='relative' position="relative"
bg='grey' overflow="hidden"
w={['100%', '400px']} width={["100%", "400px"]}
maxW={[mobileVW, '100%']} maxWidth={[mobileVW, "100%"]}
h='100%' height="100%"
outline={'none'} padding="1px"
overflow='hidden' background="grey"
p={'1px'} borderRadius="6px"
borderRadius={'6px'} pointerEvents="all"
pointerEvents={'all'} outline="none"
> >
<Box
position='absolute'
width='105%'
pb={'105%'}
bg={
'conic-gradient(#f34a4a, #ffbc48, #58ca70, #47b5e6, #a555e8, #f34a4a)'
}
sx={{
'@keyframes rainbow-conical': {
'100%': {
transform: 'rotate(-360deg)'
}
},
animation: 'rainbow-conical 1s linear infinite'
}}
></Box>
<Input <Input
// display='none'
// opacity={0}
ref={inputRef} ref={inputRef}
h='100%' sx={{
borderRadius={'5px'} "&::placeholder": {
outline={'none'} color: "greys.dark",
border={'none'} },
value={value} }}
width="100%"
height="100%"
border="none"
borderRadius="5px"
outline="none"
onChange={onChange} onChange={onChange}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
w='100%'
sx={{
'&::placeholder': {
color: 'greys.dark'
}
}}
placeholder={"What's on your mind?"} placeholder={"What's on your mind?"}
value={value}
></Input> ></Input>
</Center> </Center>
</Flex> </Flex>

View File

@ -29,10 +29,10 @@ export const Nav = props => {
position='relative' position='relative'
justifyContent='center' justifyContent='center'
flexDir={'row'} flexDir={'row'}
py={2} py={'10px'}
px={2} px={2}
bg='white' // bg='white'
boxShadow={'0px 0px 10px rgba(0,0,0,0.1)'} // boxShadow={'0px 0px 10px rgba(0,0,0,0.1)'}
> >
<Commander></Commander> <Commander></Commander>
<RainbowSkeleton <RainbowSkeleton

View File

@ -0,0 +1,14 @@
import React from "react"
import { Box } from "@chakra-ui/react"
export const Rainbow = (props: any): JSX.Element => {
const rainbow = ["#f34a4a", "#ffbc48", "#58ca70", "#47b5e6", "#a555e8"]
const [colors, setColors] = React.useState(props?.colors || rainbow)
return (
<Box width={20} height={20} background="green">
{props?.children}
</Box>
)
}

View File

@ -10,10 +10,18 @@ export const Thingtime = props => {
const [uuid, setUuid] = React.useState() const [uuid, setUuid] = React.useState()
const depth = React.useMemo(() => {
return props?.depth || 1
}, [props?.depth])
const pl = React.useMemo(() => { const pl = React.useMemo(() => {
return props?.pl || [4, 6] return props?.pl || [4, 6]
}, [props?.pl]) }, [props?.pl])
const pr = React.useMemo(() => {
return props?.pr || (depth === 1 ? [4, 6] : 0)
}, [props?.pr])
// will only run on the client // will only run on the client
React.useEffect(() => { React.useEffect(() => {
setUuid(Math.random().toString(36).substring(7)) setUuid(Math.random().toString(36).substring(7))
@ -21,10 +29,6 @@ export const Thingtime = props => {
const { thingtime } = useThingtime() const { thingtime } = useThingtime()
const depth = React.useMemo(() => {
return props?.depth || 1
}, [props?.depth])
const thing = React.useMemo(() => { const thing = React.useMemo(() => {
return props.thing return props.thing
}, [props.thing]) }, [props.thing])
@ -249,6 +253,7 @@ export const Thingtime = props => {
position='relative' position='relative'
flexDir='column' flexDir='column'
py={3} py={3}
pr={pr}
w='500px' w='500px'
// minW={depth === 1 ? '120px' : null} // minW={depth === 1 ? '120px' : null}
maxW='100%' maxW='100%'

View File

@ -1,6 +1,6 @@
import React, { useContext } from 'react' import { useContext } from "react"
import { ThingtimeContext } from '~/Providers/ThingtimeProvider' import { ThingtimeContext } from "~/Providers/ThingtimeProvider"
const getGlobal = () => { const getGlobal = () => {
try { try {
@ -13,7 +13,7 @@ const getGlobal = () => {
export const useThingtime = (props?: any) => { export const useThingtime = (props?: any) => {
const value = useContext(ThingtimeContext) const value = useContext(ThingtimeContext)
const { thingtime, setThingtime, getThingtime, thingtimeRef } = value // const { thingtime, setThingtime, getThingtime, thingtimeRef } = value
return value return value
} }

View File

@ -1,18 +0,0 @@
export const sanitise = str => {
const isTT = str?.slice(0, 3) === 'tt.'
const isThingtime = str?.slice(0, 9) === 'thingtime.'
const isDot = str?.slice(0, 1) === '.'
if (isTT) {
str = str?.slice(3)
}
if (isThingtime) {
str = str?.slice(9)
}
if (isDot) {
str = str?.slice(1)
}
return str
}

View File

@ -0,0 +1,19 @@
export const sanitise = str => {
const isTT = str?.slice(0, 3) === 'tt.'
const isThingtime = str?.slice(0, 10) === 'thingtime.'
const isDot = str?.slice(0, 1) === '.'
console.log('nik thingtime sanitis 1', str, isTT, isThingtime, isDot)
if (isTT) {
str = str?.slice(3)
} else if (isThingtime) {
str = str?.slice(9)
} else if (isDot) {
str = str?.slice(1)
}
console.log('nik thingtime sanitise 2', str, isTT, isThingtime, isDot)
return str
}

View File

@ -1,26 +1,32 @@
import { Flex } from '@chakra-ui/react' import { Box, Flex } from "@chakra-ui/react"
import { ProfileDrawer } from '~/components/Nav/ProfileDrawer'
import { Splash } from '~/components/Splash/Splash'
import { Thingtime } from '~/components/Thingtime/Thingtime'
import { ThingtimeDemo } from '~/components/Thingtime/ThingtimeDemo'
import { useThingtime } from '~/components/Thingtime/useThingtime'
export default function Index () { import { ProfileDrawer } from "~/components/Nav/ProfileDrawer"
import { Rainbow } from "~/components/Rainbow/Rainbow"
import { Splash } from "~/components/Splash/Splash"
import { Thingtime } from "~/components/Thingtime/Thingtime"
import { ThingtimeDemo } from "~/components/Thingtime/ThingtimeDemo"
import { useThingtime } from "~/components/Thingtime/useThingtime"
export default function Index() {
const { thingtime } = useThingtime() const { thingtime } = useThingtime()
return ( return (
<Flex <Flex
maxW='100%' alignItems="center"
flexDir='column' justifyContent="center"
alignItems='center' flexDirection="column"
justifyContent='center' maxWidth="100%"
> >
<Box paddingTop={200}></Box>
<Rainbow>
<Box width="200px" height="20px" background="grey"></Box>
</Rainbow>
<Splash></Splash> <Splash></Splash>
<Thingtime <Thingtime
mb={200} marginBottom={200}
path='Content' path="Content"
valuePl={0} valuePl={0}
thing={thingtime['Content']} thing={thingtime["Content"]}
></Thingtime> ></Thingtime>
<ThingtimeDemo></ThingtimeDemo> <ThingtimeDemo></ThingtimeDemo>
<ProfileDrawer></ProfileDrawer> <ProfileDrawer></ProfileDrawer>

View File

@ -53,6 +53,15 @@ export const pause = (value, opts) => {
export const save = (value, opts) => { export const save = (value, opts) => {
return stringify(value, opts) return stringify(value, opts)
} }
// extract parent path from dot delimitted path
export const getParentPath = path => {
const parts = path.split('.')
parts.pop()
return parts.join('.')
}
export const toJavascript = (value, opts = {}) => { export const toJavascript = (value, opts = {}) => {
let defaultOpts = { let defaultOpts = {
wrapInFunction: true, wrapInFunction: true,

View File

@ -3,7 +3,9 @@
"sideEffects": false, "sideEffects": false,
"scripts": { "scripts": {
"build": "remix build", "build": "remix build",
"dev": "remix dev --port 9999" "dev": "remix dev --port 9999",
"lint": "eslint --ext .js,.ts,.jsx,.tsx .",
"lint-fix": "eslint --ext .js,.ts,.jsx,.tsx . --fix"
}, },
"dependencies": { "dependencies": {
"@chakra-ui/react": "^2.7.1", "@chakra-ui/react": "^2.7.1",
@ -12,6 +14,7 @@
"@remix-run/serve": "^1.15.0", "@remix-run/serve": "^1.15.0",
"@vercel/analytics": "^0.1.11", "@vercel/analytics": "^0.1.11",
"@vercel/remix": "^1.15.0", "@vercel/remix": "^1.15.0",
"gradient-path": "^2.3.0",
"isbot": "latest", "isbot": "latest",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"react": "^18.2.0", "react": "^18.2.0",
@ -22,9 +25,21 @@
"devDependencies": { "devDependencies": {
"@remix-run/dev": "^1.15.0", "@remix-run/dev": "^1.15.0",
"@remix-run/eslint-config": "^1.15.0", "@remix-run/eslint-config": "^1.15.0",
"@shopify/eslint-plugin": "^42.1.0",
"@types/eslint": "^8.40.2",
"@types/react": "^18.0.25", "@types/react": "^18.0.25",
"@types/react-dom": "^18.0.11", "@types/react-dom": "^18.0.11",
"eslint": "^8.28.0", "@typescript-eslint/parser": "^5.60.1",
"eslint": "^8.43.0",
"eslint-config-prettier": "^8.8.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-chakra-ui": "^0.8.0",
"eslint-plugin-hydrogen": "^0.12.3",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"typescript": "^4.9.3" "typescript": "^4.9.3"
}, },
"engines": { "engines": {

File diff suppressed because it is too large Load Diff