feat: feature/rainbow-component Fixed a few things

This commit is contained in:
Nikolaj Frey 2023-07-07 17:42:14 +10:00
parent c5c0958905
commit 2a8eb22976
7 changed files with 228 additions and 180 deletions

View File

@ -1,45 +1,46 @@
const g = {
grey: '#F1F1F3',
grey: "#F1F1F3",
greys: {
light: '#F1F1F3',
medium: '#E0E0E0',
dark: '#BDBDBD'
}
light: "#F1F1F3",
lightt: "#E7E6E8",
medium: "#E0E0E0",
dark: "#BDBDBD",
},
}
g.gray = g.grey
g.grays = g.greys
export const colors = {
white: '#FFFFFF',
white: "#FFFFFF",
...g,
black: '#000000',
black: "#000000",
// all colors of the chakras
chakras: {
root: '#C62828',
sacral: '#FF7043',
solarPlexus: '#FFEE58',
heart: '#66BB6A',
throat: '#42A5F5',
thirdEye: '#5C6BC0',
crown: '#AB47BC',
root: "#C62828",
sacral: "#FF7043",
solarPlexus: "#FFEE58",
heart: "#66BB6A",
throat: "#42A5F5",
thirdEye: "#5C6BC0",
crown: "#AB47BC",
red: '#C62828',
orange: '#FF7043',
yellow: '#FFEE58',
green: '#66BB6A',
blue: '#42A5F5',
indigo: '#5C6BC0',
violet: '#AB47BC'
red: "#C62828",
orange: "#FF7043",
yellow: "#FFEE58",
green: "#66BB6A",
blue: "#42A5F5",
indigo: "#5C6BC0",
violet: "#AB47BC",
},
// all colors of the rainbow
rainbow: {
red: '#FF0000',
orange: '#FF7F00',
yellow: '#FFFF00',
green: '#00FF00',
blue: '#0000FF',
indigo: '#4B0082',
violet: '#8F00FF'
}
red: "#FF0000",
orange: "#FF7F00",
yellow: "#FFFF00",
green: "#00FF00",
blue: "#0000FF",
indigo: "#4B0082",
violet: "#8F00FF",
},
}

View File

@ -22,7 +22,7 @@ try {
const force = {
settings: {
commanderActive: true,
commanderActive: false,
},
version: 22,
}
@ -89,6 +89,7 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
thingtimeRef.current = thingtime
try {
console.log("Setting thingtime to localStorage")
window.localStorage.setItem("thingtime", JSON.stringify(thingtime))
} catch (err) {
console.error("There was an error saving thingtime to localStorage")

View File

@ -45,14 +45,29 @@ export const Commander = (props) => {
if (commanderActive) {
inputRef?.current?.focus?.()
} else {
document.activeElement.blur()
if (thingtimeRef?.current?.settings?.clearCommanderOnToggle) {
setValue("")
}
if (thingtimeRef?.current?.settings?.clearCommanderContextOnToggle) {
setShowContext(false, "commanderActive useEffect")
}
if (contextPath !== undefined) {
setContextPath(undefined)
}
if (showContext !== false) {
setShowContext(false)
}
}
}, [commanderActive, thingtimeRef, setShowContext])
}, [
commanderActive,
thingtimeRef,
setShowContext,
value,
contextPath,
showContext,
])
const onChange = React.useCallback((e) => {
setValue(e.target.value)
@ -92,16 +107,6 @@ export const Commander = (props) => {
return command?.[1]
}, [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(() => {
return ['"', "'"]
}, [])
@ -148,34 +153,66 @@ export const Commander = (props) => {
// console.log('nik suggestions', suggestions)
console.log("nik useEffect suggestions commandPath", commandPath)
const removeSuggestions = [contextPath]
let ret = []
if (commandPath) {
const filteredSuggestions = suggestions.filter((suggestion, i) => {
return suggestion?.toLowerCase()?.includes(commandPath?.toLowerCase())
return (
suggestion?.toLowerCase()?.includes(commandPath?.toLowerCase()) ||
suggestion?.includes(commandPath)
)
})
if (!filteredSuggestions?.includes(commandPath)) {
const adjustedSuggestions = [commandPath, ...filteredSuggestions]
return adjustedSuggestions
ret = adjustedSuggestions
} else {
return filteredSuggestions
ret = filteredSuggestions
}
} else {
return suggestions
ret = suggestions
}
const filtered = ret.filter((suggestion) => {
return !removeSuggestions?.includes(suggestion)
})
console.log("nik useEffect suggestions commandPath", commandPath)
console.log("nik useEffect suggestions ret", ret)
console.log("nik useEffect suggestions suggestions", suggestions)
console.log("nik useEffect suggestions filtered", filtered)
return filtered
// if (value) {
// setShowContext(true, 'Thingtime changes update suggestions')
// }
}
}, [value, thingtime, commandPath])
}, [value, thingtime, commandPath, contextPath])
const commandContainsPath = React.useMemo(() => {
console.log("nik command", commandPath)
console.log("nik suggestions", suggestions)
const commandIncludesSuggestion = suggestions?.find((suggestion) => {
return commandPath?.includes(suggestion)
})
console.log("nik commandIncludesSuggestion", commandIncludesSuggestion)
// return false
return commandIncludesSuggestion
}, [commandPath, suggestions])
const onEnter = React.useCallback(
(props) => {
// if first characters of value equal tt. then run command
// or if first character is a dot then run command
try {
console.log("Commander onEnter")
console.log("nik Commander onEnter")
console.log("nik commandIsAction", commandIsAction)
console.log("nik commandContainsPath", commandContainsPath)
console.log("nik onEnter commandPath", commandPath)
if (commandIsAction) {
// nothing
try {
@ -193,6 +230,10 @@ export const Commander = (props) => {
console.log("setThingtime errored in Commander", err)
}
} else if (commandContainsPath) {
// const prevValue = getThingtime(commandPath)
// const newValue = setThingtime(commandPath, prevValue)
console.log("Setting context path", commandPath)
setContextPath(commandPath)
setShowContext(true, "commandContainsPath check")
@ -233,31 +274,16 @@ export const Commander = (props) => {
setThingtime("settings.commanderActive", true)
}, [setThingtime])
const closeCommander = React.useCallback(() => {
if (thingtime?.settings?.commanderActive) {
console.log("nik commander closing commander")
setThingtime("settings.commanderActive", false)
}
document.activeElement.blur()
if (value !== "") {
setValue("")
}
if (contextPath !== undefined) {
setContextPath(undefined)
}
if (showContext !== false) {
setShowContext(false)
}
}, [
setThingtime,
setShowContext,
value,
contextPath,
showContext,
thingtime?.settings?.commanderActive,
])
const closeCommander = React.useCallback(
(e) => {
console.log("nik e", e)
if (thingtime?.settings?.commanderActive) {
console.log("nik commander closing commander")
setThingtime("settings.commanderActive", false)
}
},
[setThingtime, thingtime?.settings?.commanderActive]
)
const toggleCommander = React.useCallback(() => {
if (thingtime?.settings?.commanderActive) {
@ -311,7 +337,7 @@ export const Commander = (props) => {
return "calc(100vw - 45px)"
}, [])
const rainbowRepeats = 1
const rainbowRepeats = 2
return (
<ClickAwayListener onClickAway={closeCommander}>
@ -326,11 +352,10 @@ export const Commander = (props) => {
justifyContent={["flex-start", "center"]}
// display={["flex", commanderActive ? "flex" : "none"]}
maxWidth="100%"
height="100%"
height={12}
// height="100%"
pointerEvents="none"
id="commander"
paddingX={1}
paddingY={1}
>
<Flex
position="absolute"
@ -364,7 +389,7 @@ export const Commander = (props) => {
<Flex
key={i}
_hover={{
bg: "greys.medium",
bg: "greys.lightt",
}}
cursor="pointer"
onClick={() => selectSuggestion(suggestion)}
@ -397,6 +422,7 @@ export const Commander = (props) => {
opacity={commanderActive ? 0.25 : 0}
repeats={rainbowRepeats}
thickness={8}
opacityTransition="all 1000ms ease"
overflow="visible"
>
<Center
@ -411,10 +437,10 @@ export const Commander = (props) => {
outline="none"
>
<Rainbow
opacity={commanderActive ? 0.5 : 0}
opacity={commanderActive ? 0.6 : 0}
position="absolute"
repeats={rainbowRepeats}
opacityTransition="all 3000ms ease"
opacityTransition="all 2500ms ease"
thickness={10}
></Rainbow>
<Input
@ -435,7 +461,7 @@ export const Commander = (props) => {
onChange={onChange}
onFocus={openCommander}
onKeyDown={onKeyDown}
placeholder={"What's on your mind?"}
placeholder="Imagine.."
value={value}
></Input>
</Center>

View File

@ -1,10 +1,11 @@
import React from 'react'
import { Box, Flex } from '@chakra-ui/react'
import { RainbowSkeleton } from '../Skeleton/RainbowSkeleton'
import { ProfileDrawer } from './ProfileDrawer'
import { Commander } from '../Commander/Commander'
import React from "react"
import { Box, Flex } from "@chakra-ui/react"
export const Nav = props => {
import { Commander } from "../Commander/Commander"
import { RainbowSkeleton } from "../Skeleton/RainbowSkeleton"
import { ProfileDrawer } from "./ProfileDrawer"
export const Nav = (props) => {
const [profileDrawerOpen, setProfileDrawerOpen] = React.useState(false)
const toggleProfileDrawer = React.useCallback(() => {
@ -14,36 +15,37 @@ export const Nav = props => {
return (
<>
<Box
position='fixed'
maxW='100vw'
top={0}
left={0}
right={0}
position="fixed"
zIndex={999}
top={0}
right={0}
left={0}
maxWidth="100vw"
>
<Flex
as='nav'
w='100%'
maxW='100%'
alignItems={'center'}
position='relative'
justifyContent='center'
flexDir={'row'}
py={'10px'}
px={2}
as="nav"
position="relative"
alignItems="center"
justifyContent="center"
flexDirection="row"
width="100%"
maxWidth="100%"
marginY={1}
paddingX="12px"
paddingY="10px"
// bg='white'
// boxShadow={'0px 0px 10px rgba(0,0,0,0.1)'}
>
<Commander></Commander>
<RainbowSkeleton
ml={'auto'}
w='25px'
h='25px'
cursor='pointer'
marginLeft="auto"
width="25px"
height="25px"
cursor="pointer"
onClick={toggleProfileDrawer}
bg={'rgba(0,0,0,0.1)'}
background="rgba(0,0,0,0.1)"
sx={{}}
borderRadius='999px'
borderRadius="999px"
></RainbowSkeleton>
{/* <RainbowSkeleton w='40px' ml='auto' mr={"4px"}></RainbowSkeleton>
<RainbowSkeleton></RainbowSkeleton> */}

View File

@ -7,6 +7,8 @@ import { useTrace } from "~/hooks/useTrace"
import { useUuid } from "~/hooks/useUuid"
export const Rainbow = (allProps: any): JSX.Element => {
// return allProps.children
const rainbow = ["#f34a4a", "#ffbc48", "#58ca70", "#47b5e6", "#a555e8"]
const props = useProps(allProps)
@ -71,6 +73,7 @@ export const Rainbow = (allProps: any): JSX.Element => {
const keyframe = `${(i / (repeatedColours.length - 1)) * 100}%`
ret[keyframe] = {
fill: colour,
"animation-timing-function": "ease-out",
stroke: colour,
}
})
@ -153,7 +156,7 @@ export const Rainbow = (allProps: any): JSX.Element => {
width: pathWidth || 1,
animation: {
name: `rainbow-${uuid}`,
duration: 5,
duration: props?.duration || 7,
},
})
@ -169,6 +172,7 @@ export const Rainbow = (allProps: any): JSX.Element => {
}
}, [
uuid,
props?.duration,
props?.segments,
props?.samples,
props?.precision,

View File

@ -1,9 +1,10 @@
import React from 'react'
import { Box, Flex } from '@chakra-ui/react'
import { Safe } from '../Safety/Safe'
import { useThingtime } from './useThingtime'
import React from "react"
import { Box, Flex } from "@chakra-ui/react"
export const Thingtime = props => {
import { Safe } from "../Safety/Safe"
import { useThingtime } from "./useThingtime"
export const Thingtime = (props) => {
// TODO: Add a circular reference seen prop check
// and add button to expand circular reference
// up to 1 level deep
@ -34,11 +35,11 @@ export const Thingtime = props => {
}, [props.thing])
const mode = React.useMemo(() => {
return 'view'
return "view"
}, [])
const validKeyTypes = React.useMemo(() => {
return ['object', 'array']
return ["object", "array"]
}, [])
const keys = React.useMemo(() => {
@ -55,42 +56,42 @@ export const Thingtime = props => {
}, [thing])
const valuePl = React.useMemo(() => {
if (typeof props?.valuePl === 'number') {
if (typeof props?.valuePl === "number") {
return props?.valuePl
}
return props?.path ? [4, 6] : [0, 0]
}, [props?.valuePl, props?.path])
const renderableValue = React.useMemo(() => {
if (type === 'string') {
if (type === "string") {
if (!thing) {
return 'Empty string'
return "Empty string"
}
return thing
} else if (type === 'number') {
} else if (type === "number") {
return thing
} else if (type === 'boolean') {
return thing ? 'true' : 'false'
} else if (type === 'object') {
} else if (type === "boolean") {
return thing ? "true" : "false"
} else if (type === "object") {
if (thing === null) {
return 'null'
return "null"
}
if (!keys?.length) {
return 'Empty object'
return "Something!"
}
try {
return JSON.stringify(thing, null, 2)
} catch (err) {
console.error(
'Caught error making renderableValue of thing',
"Caught error making renderableValue of thing",
err,
thing
)
return 'Circular reference in object.'
return "Circular reference in object."
}
} else {
return 'Undefined'
return "Something!"
}
}, [thing, type])
@ -108,24 +109,24 @@ export const Thingtime = props => {
window.thingtime.tmp[randId] = 0
const recurse = (obj, prefix) => {
Object.keys(obj).forEach(key => {
if (typeof obj[key] === 'object') {
Object.keys(obj).forEach((key) => {
if (typeof obj[key] === "object") {
if (window?.thingtime?.tmp[randId] < 1000) {
window.thingtime.tmp[randId]++
recurse(obj[key], `${prefix}${prefix && '.'}${key}`)
recurse(obj[key], `${prefix}${prefix && "."}${key}`)
} else {
console.error('Recursion limit reached in Thingtime.tsx')
console.error("Recursion limit reached in Thingtime.tsx")
}
} else {
ret.push({
key: `${prefix}${prefix && '.'}${key}`,
human: `${prefix}${prefix && ' '}${key}`
key: `${prefix}${prefix && "."}${key}`,
human: `${prefix}${prefix && " "}${key}`,
})
}
})
}
recurse(thing, '')
recurse(thing, "")
} catch (err) {
// console.error('Error in Thingtime.tsx creating flattenedKeys', err)
}
@ -139,27 +140,27 @@ export const Thingtime = props => {
const keysToUse = keys
// const keysToUse = flattenedKeys
const template1Modes = ['view', 'edit']
const template1Modes = ["view", "edit"]
if (template1Modes?.includes(mode)) {
if (keys?.length) {
value = (
<Safe {...props}>
<Flex
position='relative'
flexDir='column'
position="relative"
flexDirection="column"
// w={'500px'}
// w={['200px', '500px']}
maxW='100%'
py={props?.path ? 3 : 0}
pl={valuePl}
maxWidth="100%"
paddingLeft={valuePl}
paddingY={props?.path ? 3 : 0}
>
{keysToUse?.length &&
keysToUse.map((key, idx) => {
if (!key?.human) {
key = {
human: key,
key: key
key: key,
}
}
@ -183,13 +184,13 @@ export const Thingtime = props => {
} else {
editableValue = (
<Box
contentEditable={mode === 'edit'}
border='none'
outline={'none'}
py={2}
pl={pl}
fontSize={'20px'}
whiteSpace={'pre-line'}
paddingLeft={pl}
fontSize="20px"
border="none"
whiteSpace="pre-line"
outline="none"
contentEditable={mode === "edit"}
paddingY={2}
// dangerouslySetInnerHTML={{ __html: renderableValue }}
>
{renderableValue}
@ -199,7 +200,13 @@ export const Thingtime = props => {
}
const contextMenu = (
<Flex pr={4} userSelect={'none'} position='absolute' top={0} right={0}>
<Flex
position="absolute"
top={0}
right={0}
paddingRight={4}
userSelect="none"
>
Settings
</Flex>
)
@ -207,26 +214,26 @@ export const Thingtime = props => {
const [showContextMenu, setShowContextMenu] = React.useState(false)
const humanPath = React.useMemo(() => {
if (typeof props?.path === 'string') {
if (typeof props?.path === "string") {
return props?.path
}
return props?.path?.human || ''
return props?.path?.human || ""
}, [props?.path])
const path = React.useMemo(() => {
if (humanPath?.includes?.('hidden')) {
if (humanPath?.includes?.("hidden")) {
return null
}
if (humanPath?.includes?.('unique')) {
if (humanPath?.includes?.("unique")) {
// take only path from before the string unique
return humanPath.split?.('unique')?.[0]
return humanPath.split?.("unique")?.[0]
}
return (
<Flex
maxW='100%'
pl={props?.pathPl || pl}
wordBreak={'break-all'}
fontSize='12px'
maxWidth="100%"
paddingLeft={props?.pathPl || pl}
fontSize="12px"
wordBreak="break-all"
>
{humanPath}
</Flex>
@ -234,12 +241,12 @@ export const Thingtime = props => {
}, [humanPath, pl, props?.pathPl])
const handleMouseEvent = React.useCallback(
e => {
(e) => {
const target = e?.target
// extract uuid from className
const className = target?.className
if (className?.includes(uuid?.current)) {
setShowContextMenu(e?.type === 'mouseenter')
setShowContextMenu(e?.type === "mouseenter")
}
},
[uuid]
@ -248,15 +255,15 @@ export const Thingtime = props => {
return (
<Safe {...props} depth={depth} uuid={uuid?.current}>
<Flex
position="relative"
flexDirection="column"
width="500px"
maxWidth="100%"
paddingRight={pr}
onMouseEnter={handleMouseEvent}
onMouseLeave={handleMouseEvent}
position='relative'
flexDir='column'
py={3}
pr={pr}
w='500px'
// minW={depth === 1 ? '120px' : null}
maxW='100%'
paddingY={3}
{...props}
className={`thing-${uuid?.current}`}
>

View File

@ -1,19 +1,26 @@
export const sanitise = str => {
const isTT = str?.slice(0, 3) === 'tt.'
const isThingtime = str?.slice(0, 10) === 'thingtime.'
const isDot = str?.slice(0, 1) === '.'
export const sanitise = (str) => {
let ret = ""
console.log('nik thingtime sanitis 1', str, isTT, isThingtime, isDot)
const value = str?.trim()
if (isTT) {
str = str?.slice(3)
} else if (isThingtime) {
str = str?.slice(9)
} else if (isDot) {
str = str?.slice(1)
const sanitised = ["tt", "thingtime"]
const suffixes = [".", " "]
// find combination of sanitised + suffixes which str starts with
const match = sanitised.find((s) => value?.startsWith(s))
const withSuffix = suffixes.find(
(s) => match?.length && value[match?.length] === s
)
const noSuffix = match && value?.length === match?.length
if (match && withSuffix) {
ret = value?.slice(match.length + 1)
} else if (!noSuffix) {
ret = value
}
console.log("nik thingtime sanitis 1", match, withSuffix, ret)
console.log('nik thingtime sanitise 2', str, isTT, isThingtime, isDot)
return str
return ret
}