diff --git a/remix/app/Providers/ThingtimeProvider.tsx b/remix/app/Providers/ThingtimeProvider.tsx index 6dd10c7..9f4351e 100644 --- a/remix/app/Providers/ThingtimeProvider.tsx +++ b/remix/app/Providers/ThingtimeProvider.tsx @@ -9,11 +9,12 @@ export interface ThingtimeContextInterface { setThingtime: any getThingtime: any thingtimeRef: any + loading: boolean } -export const ThingtimeContext = createContext< - ThingtimeContextInterface[] | null ->(null) +export const ThingtimeContext = createContext( + null +) try { window.smarts = smarts diff --git a/remix/app/components/Commander/Commander.tsx b/remix/app/components/Commander/Commander.tsx index 276f93d..0a55ae9 100644 --- a/remix/app/components/Commander/Commander.tsx +++ b/remix/app/components/Commander/Commander.tsx @@ -1,8 +1,9 @@ import React from "react" import ClickAwayListener from "react-click-away-listener" -import { Center, Flex, Input } from "@chakra-ui/react" +import { Box, Center, Flex, Input } from "@chakra-ui/react" import Fuse from "fuse.js" +import { MagicInput } from "../MagicInput/MagicInput" import { Rainbow } from "../Rainbow/Rainbow" import { Thingtime } from "../Thingtime/Thingtime" import { useThingtime } from "../Thingtime/useThingtime" @@ -69,9 +70,13 @@ export const Commander = (props) => { // commanderActive useEffect React.useEffect(() => { if (commanderActive) { - inputRef?.current?.focus?.() + if (props?.global) { + inputRef?.current?.focus?.() + } } else { - document.activeElement.blur() + if (props?.global) { + document.activeElement.blur() + } if ( thingtimeRef?.current?.settings?.commander?.[commanderId] @@ -98,6 +103,7 @@ export const Commander = (props) => { commanderActive, thingtimeRef, setShowContext, + props?.global, commanderId, inputValue, contextPath, @@ -116,27 +122,43 @@ export const Commander = (props) => { const command = React.useMemo(() => { // const sanitizedCommand = sanitise(value) // const sanitizedCommand = inputValue - const sanitizedCommand = virtualValue + const sanitizedInput = virtualValue const validSetter = validSetters?.find((setter) => { - if (sanitizedCommand?.includes(setter)) { + if (sanitizedInput?.includes(setter)) { return setter } return false }) if (typeof validSetter === "string") { - const indexOfSplitter = sanitizedCommand?.indexOf(validSetter) + const indexOfSplitter = sanitizedInput?.indexOf(validSetter) const [pathRaw, valRaw] = [ - sanitizedCommand?.slice(0, indexOfSplitter), - sanitizedCommand?.slice(indexOfSplitter + validSetter?.length), + sanitizedInput?.slice(0, indexOfSplitter), + sanitizedInput?.slice(indexOfSplitter + validSetter?.length), ] - return [pathRaw?.trim(), valRaw?.trim()] + const pathTrimmed = pathRaw?.trim() + + let path = pathTrimmed + + if (pathTrimmed && props?.pathPrefix) { + path = props?.pathPrefix + "." + pathTrimmed + } else if (props?.pathPrefix) { + path = props?.pathPrefix + } + + return [path, valRaw?.trim()] } - return [sanitizedCommand] + + if (props?.pathPrefix) { + return [props?.pathPrefix, sanitizedInput] + } + + return [sanitizedInput] }, [ // inputValue, + props?.pathPrefix, virtualValue, validSetters, ]) @@ -167,7 +189,9 @@ export const Commander = (props) => { const escaped = restOfCommandValue ?.replace(/"/g, '\\"') ?.replace(/'/g, "\\'") - const ret = `"${escaped}"` + ?.replace(/`/g, "\\`") + + const ret = `\`${escaped}\`` return ret }, [commandValue, validQuotations]) @@ -270,6 +294,8 @@ export const Commander = (props) => { if (curSuggestionIdx !== null) { selectSuggestion(curSuggestionIdx) } + console.log("nik commanderActive", commanderActive) + console.log("nik commandIsAction", commandIsAction) if (commanderActive) { try { if (commandIsAction) { @@ -378,7 +404,10 @@ export const Commander = (props) => { setHoveredSuggestion(0) } } else if (e?.code === "Enter") { - executeCommand() + // if not shift enter then execute command + if (!e?.shiftKey) { + executeCommand() + } } } }, @@ -414,89 +443,140 @@ export const Commander = (props) => { setVirtualValue(inputValue) }, [inputValue]) - const InputJSX = React.useMemo(() => { - return ( - - ) - }, [inputRef, inputValue, onInputChange, openCommander]) + const onMagicInput = React.useCallback((args) => { + // props?.onValueChange?.(args) + + setInputValue(args?.value) + setHoveredSuggestion(null) + }, []) + + const InputPartWrapper = React.useCallback( + (props) => { + return {props?.children} + }, + [commanderActive] + ) + + const InputPart = React.useMemo(() => { + if (props?.simple) { + return ( + + ) + } - const MainInput = React.useMemo(() => { return ( -
- {props?.rainbow && ( - - )} - {InputJSX} -
+ ) - }, [InputJSX, commanderActive, rainbowRepeats, props?.rainbow, mobileVW]) + }, [ + inputRef, + onInputChange, + commanderActive, + props?.rainbow, + props?.placeholder, + openCommander, + onMagicInput, + props?.simple, + inputValue, + ]) return ( +
+ {props?.rainbow && ( + +
+ + {/* {InputPart} */} + {InputPart} + +
+
+ )} + {!props?.rainbow && InputPart} +
{ ) })} - {showContext && ( + {showContext && props?.context && ( { )} -
- {props?.rainbow && ( - - {MainInput} - - )} - {!props?.rainbow && MainInput} -
) diff --git a/remix/app/components/Commander/CommanderV1.tsx b/remix/app/components/Commander/CommanderV1.tsx new file mode 100644 index 0000000..0368bd2 --- /dev/null +++ b/remix/app/components/Commander/CommanderV1.tsx @@ -0,0 +1,568 @@ +import React from "react" +import ClickAwayListener from "react-click-away-listener" +import { Center, Flex, Input } from "@chakra-ui/react" +import Fuse from "fuse.js" + +import { Rainbow } from "../Rainbow/Rainbow" +import { Thingtime } from "../Thingtime/Thingtime" +import { useThingtime } from "../Thingtime/useThingtime" + +import { sanitise } from "~/functions/sanitise" +import { getParentPath } from "~/smarts" + +export const CommanderV1 = (props) => { + const { thingtime, setThingtime, getThingtime, thingtimeRef, paths } = + useThingtime() + + const commanderId = React.useMemo(() => { + return props?.id || "global" + }, [props?.id]) + + const inputRef = React.useRef() + + const global = props?.global + + const commanderSettings = React.useMemo(() => { + return thingtime?.settings?.commander?.[commanderId] || {} + }, [ + thingtime?.settings?.commander, + thingtime?.settings?.commander?.[commanderId], + commanderId, + ]) + + const [inputValue, setInputValue] = React.useState("") + const [virtualValue, setVirtualValue] = React.useState("") + const [hoveredSuggestion, setHoveredSuggestion] = React.useState() + const [active, setActive] = React.useState(false) + const [contextPath, setContextPath] = React.useState() + + const mode = React.useMemo(() => { + return props?.mode || "value" + }, [props?.mode]) + + const [showContext, setShowContextState] = React.useState(false) + + const mobileVW = React.useMemo(() => { + return "calc(100vw - 55px)" + }, []) + + const rainbowRepeats = 2 + + const setShowContext = React.useCallback( + (value, from?: string) => { + setShowContextState(value) + }, + [setShowContextState] + ) + // const [suggestions, setSuggestions] = React.useState([]) + + const contextValue = React.useMemo(() => { + // TODO: Figure out why this is running on every click + const ret = getThingtime(contextPath) + return ret + }, [contextPath, getThingtime]) + + const commanderActive = React.useMemo(() => { + return thingtime?.settings?.commander?.[commanderId]?.commanderActive + }, [commanderSettings, commanderId]) + + // commanderActive useEffect + React.useEffect(() => { + if (commanderActive) { + inputRef?.current?.focus?.() + } else { + document.activeElement.blur() + + if ( + thingtimeRef?.current?.settings?.commander?.[commanderId] + ?.clearCommanderOnToggle + ) { + setInputValue("") + setHoveredSuggestion(null) + } + if ( + thingtimeRef?.current?.settings?.commander?.[commanderId]?.commander?.[ + commanderId + ]?.clearCommanderContextOnToggle + ) { + setShowContext(false, "commanderActive useEffect") + } + if (contextPath !== undefined && !inputValue) { + setContextPath(undefined) + } + if (showContext !== false) { + setShowContext(false) + } + } + }, [ + commanderActive, + thingtimeRef, + setShowContext, + commanderId, + inputValue, + contextPath, + showContext, + ]) + + const onInputChange = React.useCallback((e) => { + setInputValue(e.target.value) + setHoveredSuggestion(null) + }, []) + + const validSetters = React.useMemo(() => { + return ["=", " is ", " IS ", " Is ", " iS "] + }, []) + + const command = React.useMemo(() => { + // const sanitizedCommand = sanitise(value) + // const sanitizedCommand = inputValue + const sanitizedCommand = virtualValue + + const validSetter = validSetters?.find((setter) => { + if (sanitizedCommand?.includes(setter)) { + return setter + } + return false + }) + + if (typeof validSetter === "string") { + const indexOfSplitter = sanitizedCommand?.indexOf(validSetter) + const [pathRaw, valRaw] = [ + sanitizedCommand?.slice(0, indexOfSplitter), + sanitizedCommand?.slice(indexOfSplitter + validSetter?.length), + ] + + return [pathRaw?.trim(), valRaw?.trim()] + } + return [sanitizedCommand] + }, [ + // inputValue, + virtualValue, + validSetters, + ]) + + const commandPath = React.useMemo(() => { + return command?.[0] + // return sanitise(command?.[0]) + }, [command]) + + const commandValue = React.useMemo(() => { + return command?.[1] + }, [command]) + + const validQuotations = React.useMemo(() => { + return ['"', "'"] + }, []) + + const escapedCommandValue = React.useMemo(() => { + // replace quotations with escaped quoations except for first and last quotation + const startingQuotation = commandValue?.[0] + const endingQuotation = commandValue?.[commandValue?.length - 1] + const isQuoted = + validQuotations?.includes(startingQuotation) && + validQuotations?.includes(endingQuotation) + const restOfCommandValue = isQuoted + ? commandValue?.slice(1, commandValue?.length - 1) + : commandValue + const escaped = restOfCommandValue + ?.replace(/"/g, '\\"') + ?.replace(/'/g, "\\'") + const ret = `"${escaped}"` + return ret + }, [commandValue, validQuotations]) + + const commandIsAction = React.useMemo(() => { + return commandPath && commandValue + }, [commandPath, commandValue]) + + const suggestions = React.useMemo(() => { + try { + const fuse = new Fuse(paths) + + const results = fuse.search(inputValue) + + const mappedResults = results?.map((result) => { + return result?.item + }) + + return mappedResults + } catch (err) { + console.error("fuse error", err) + } + }, [inputValue, paths]) + + const showSuggestions = React.useMemo(() => { + return ( + inputValue?.length && + suggestions?.length && + commanderActive && + thingtime?.settings?.commander?.[commanderId]?.hideSuggestionsOnToggle + ) + }, [ + inputValue, + suggestions, + commanderActive, + commanderId, + thingtime?.settings?.commander, + commanderSettings, + ]) + + const selectSuggestion = React.useCallback( + (suggestionIdx) => { + const suggestion = suggestions?.[suggestionIdx] + + setInputValue(suggestion) + setHoveredSuggestion(null) + setContextPath(suggestion) + setShowContext(true, "Select suggestion") + }, + [setInputValue, setContextPath, setShowContext, suggestions] + ) + + const commandContainsPath = React.useMemo(() => { + const commandIncludesSuggestion = suggestions?.find((suggestion) => { + return commandPath?.includes(suggestion) + }) + // return false + return commandIncludesSuggestion + }, [commandPath, suggestions]) + + const openCommander = React.useCallback(() => { + setThingtime(`settings.commander.${commanderId}.commanderActive`, true) + }, [setThingtime, commanderId]) + + const closeCommander = React.useCallback( + (e?: any) => { + if (!e?.defaultPrevented) { + if (thingtime?.settings?.commander?.[commanderId]?.commanderActive) { + setThingtime( + `settings.commander.${commanderId}.commanderActive`, + false + ) + } + } + }, + [ + setThingtime, + commanderId, + commanderSettings, + thingtime?.settings?.commander, + ] + ) + + const toggleCommander = React.useCallback(() => { + if (thingtime?.settings?.commander?.[commanderId]?.commanderActive) { + closeCommander() + } else { + openCommander() + } + }, [ + thingtime?.settings?.commander, + commanderSettings, + commanderId, + closeCommander, + openCommander, + ]) + + const executeCommand = React.useCallback(() => { + // if selection is active then select it + const curSuggestionIdx = hoveredSuggestion + if (curSuggestionIdx !== null) { + selectSuggestion(curSuggestionIdx) + } + if (commanderActive) { + try { + if (commandIsAction) { + // nothing + const prevVal = getThingtime(commandPath) + const parentPath = getParentPath(commandPath) || "thingtime" + try { + // first try to execute literal javscript + const fn = `() => { return ${commandValue} }` + const evalFn = eval(fn) + const realVal = evalFn() + setThingtime(commandPath, realVal) + } catch (err) { + console.log( + "Caught error after trying to execute literal javascript", + err + ) + + // likely literaly javascript wasn't valid + try { + const fn = `() => { return ${escapedCommandValue} }` + const evalFn = eval(fn) + const realVal = evalFn() + const prevVal = getThingtime(commandPath) + const parentPath = getParentPath(commandPath) + setThingtime(commandPath, realVal) + } catch { + // something very bad went wrong + console.log( + "Caught error after trying to execute escaped literal javascript", + err + ) + } + } + // if (!prevVal) { + setContextPath(commandPath) + setShowContext(true, "commandIsAction check") + // } + } + // if (commandContainsPath) + else { + // const prevValue = getThingtime(commandPath) + + // const newValue = setThingtime(commandPath, prevValue) + + console.log("Setting context path", commandPath) + setContextPath(commandPath) + setShowContext(true, "commandContainsPath check") + } + } catch (err) { + console.error("Caught error on commander onEnter", err) + } + } + }, [ + hoveredSuggestion, + selectSuggestion, + commanderActive, + commandIsAction, + commandPath, + commandValue, + escapedCommandValue, + getThingtime, + setThingtime, + setContextPath, + setShowContext, + ]) + + const allCommanderKeyListener = React.useCallback( + (e: any) => { + console.log("commander key listener e?.code", e?.code) + thingtimeRef.current = thingtime + if (e?.metaKey && e?.code === "KeyP") { + e.preventDefault() + e.stopPropagation() + toggleCommander() + } + // if key escape close all modals + else if (e?.code === "Escape") { + closeCommander() + } + + // only run these if commander active + + if (commanderActive) { + // if arrow keys then move selection + if (e?.code === "ArrowUp") { + // move selection up + const curSuggestionIdx = + typeof hoveredSuggestion === "number" + ? hoveredSuggestion + : suggestions?.length + const newSuggestionIdx = curSuggestionIdx - 1 + if (newSuggestionIdx >= 0) { + setHoveredSuggestion(newSuggestionIdx) + } else { + setHoveredSuggestion(suggestions?.length - 1) + } + } else if (e?.code === "ArrowDown") { + // move selection down + const curSuggestionIdx = + typeof hoveredSuggestion === "number" ? hoveredSuggestion : -1 + const newSuggestionIdx = curSuggestionIdx + 1 + if (newSuggestionIdx < suggestions?.length) { + setHoveredSuggestion(newSuggestionIdx) + } else { + setHoveredSuggestion(0) + } + } else if (e?.code === "Enter") { + executeCommand() + } + } + }, + [ + closeCommander, + toggleCommander, + hoveredSuggestion, + suggestions, + thingtime, + thingtimeRef, + commanderActive, + executeCommand, + ] + ) + + React.useEffect(() => { + window.addEventListener("keydown", allCommanderKeyListener) + + return () => { + window.removeEventListener("keydown", allCommanderKeyListener) + } + }, [allCommanderKeyListener]) + + React.useEffect(() => { + if (typeof hoveredSuggestion === "number") { + setVirtualValue(suggestions?.[hoveredSuggestion]) + } else { + setVirtualValue(inputValue) + } + }, [hoveredSuggestion, inputValue, suggestions]) + + React.useEffect(() => { + setVirtualValue(inputValue) + }, [inputValue]) + + return ( + + + + + setHoveredSuggestion(null)} + paddingY={3} + > + {suggestions?.map((suggestion, i) => { + return ( + selectSuggestion(i)} + onMouseEnter={() => setHoveredSuggestion(i)} + paddingX={4} + > + {suggestion} + + ) + })} + + {showContext && ( + + + + )} + + +
+ +
+ + +
+
+
+
+
+ ) +} diff --git a/remix/app/components/Icon/Icon.tsx b/remix/app/components/Icon/Icon.tsx index 23318ea..7f5d583 100644 --- a/remix/app/components/Icon/Icon.tsx +++ b/remix/app/components/Icon/Icon.tsx @@ -12,12 +12,21 @@ export const Icon = (props) => { if (["crystal"]?.includes(name)) { return "🔮" } + if (["flower", "hibiscus"]?.includes(name)) { + return "🌺" + } if (["sparke", "magic"]?.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 "📚" } @@ -82,6 +91,9 @@ export const Icon = (props) => { if (["star", "favorite"]?.includes(name)) { return "⭐" } + if (["glowing star", "glowing favorite"]?.includes(name)) { + return "🌟" + } if (["question", "help"]?.includes(name)) { return "❓" } @@ -152,7 +164,11 @@ export const Icon = (props) => { }, [name]) return ( -
+
{icon}
) diff --git a/remix/app/components/MagicInput/MagicInput.tsx b/remix/app/components/MagicInput/MagicInput.tsx new file mode 100644 index 0000000..c392eb5 --- /dev/null +++ b/remix/app/components/MagicInput/MagicInput.tsx @@ -0,0 +1,150 @@ +import React from "react" +import { Box } from "@chakra-ui/react" + +import { useThingtime } from "../Thingtime/useThingtime" + +export const MagicInput = (props) => { + const { thingtime, setThingtime, loading } = useThingtime() + + const [inputValue, setInputValue] = React.useState() + + const contentEditableRef = React.useRef(null) + const editValueRef = React.useRef({}) + + const fullPath = React.useMemo(() => { + const ret = props?.fullPath || props?.path + + // store this thing in the global db + try { + // window.meta.things[ret] = props?.value + } catch { + // nothing + } + + return ret + }, [props?.fullPath, props?.path, props?.value]) + + const [contentEditableValue, setContentEditableValue] = React.useState( + props?.value || props?.placeholder + ) + + const updateContentEditableValue = React.useCallback((value) => { + // replace all new line occurences in value with

+ + console.log("MagicInput updating contentEditableValue with value", value) + + // extract all series of new lines + const newlines = value?.split?.(/[^\n]/)?.filter((v) => v !== "") + + let newValue = value + + // replace all new lines groups with

+ newlines?.forEach?.((newline) => { + const baseLength = "\n"?.length + + const newlineClone = newline + + const newlineClonePart1 = newlineClone?.replace( + "\n\n\n", + "

" + ) + const newlineClonePart2 = newlineClonePart1?.replace( + /\n\n/g, + "

" + ) + const newlineClonePart3 = newlineClonePart2?.replace(/\n/g, "
") + + newValue = newValue?.replace(newline, newlineClonePart3) + }) + + setContentEditableValue(newValue) + }, []) + + React.useEffect(() => { + setInputValue(contentEditableValue) + }, [contentEditableValue]) + + React.useEffect(() => { + const entries = Object.entries(editValueRef.current) + const propsValueInEntries = entries?.find?.( + (entry) => entry[1] === props?.value + ) + if (!propsValueInEntries) { + // const valueToUse = props?.value || props?.placeholder + const valueToUse = props?.value + updateContentEditableValue(valueToUse) + // setContentEditableValue(props?.value) + } else { + const [time, value] = propsValueInEntries + if (time && value) { + delete editValueRef.current[time] + } + } + }, [props?.value, props?.placeholder, updateContentEditableValue]) + + const onValueChange = React.useCallback( + (args) => { + const { value } = args + props?.onValueChange?.({ value }) + // updateContentEditableValue(value) + }, + [props?.onValueChange] + ) + + const updateValue = React.useCallback( + (args) => { + const { value } = args + + onValueChange({ value }) + setInputValue(value) + // setThingtime(fullPath, value) + }, + [fullPath, setThingtime, onValueChange] + ) + + const onFocus = React.useCallback( + (e) => { + props?.onFocus?.(e) + }, + [props?.onFocus] + ) + + return ( + + { + const innerText = value?.target?.innerText + console.log("MagicInput got onInput event value", value) + console.log("MagicInput got onInput event innerText", innerText) + if (typeof innerText === "string") { + const time = Date.now() + editValueRef.current[time] = innerText + updateValue({ value: innerText }) + } + }} + > + + {props?.placeholder || "Imagine.."} + + + ) +} diff --git a/remix/app/components/Nav/Nav.tsx b/remix/app/components/Nav/Nav.tsx index 19da4de..4bd5707 100644 --- a/remix/app/components/Nav/Nav.tsx +++ b/remix/app/components/Nav/Nav.tsx @@ -1,8 +1,9 @@ import React from "react" import { Box, Center, Flex } from "@chakra-ui/react" -import { Link } from "@remix-run/react" +import { Link, useLocation, useNavigate } from "@remix-run/react" import { Commander } from "../Commander/Commander" +import { CommanderV1 } from "../Commander/CommanderV1" import { Icon } from "../Icon/Icon" import { RainbowSkeleton } from "../Skeleton/RainbowSkeleton" import { ProfileDrawer } from "./ProfileDrawer" @@ -10,10 +11,47 @@ import { ProfileDrawer } from "./ProfileDrawer" export const Nav = (props) => { const [profileDrawerOpen, setProfileDrawerOpen] = React.useState(false) + const { pathname } = useLocation() + + const navigate = useNavigate() + const toggleProfileDrawer = React.useCallback(() => { setProfileDrawerOpen(!profileDrawerOpen) }, [profileDrawerOpen]) + const inEditMode = React.useMemo(() => { + if (pathname.slice(0, 5) === "/edit") { + return true + } + return false + }, [pathname]) + + const editorToggleable = React.useMemo(() => { + if (pathname.slice(0, 7) === "/things") { + return true + } else if (pathname.slice(0, 5) === "/edit") { + return true + } + return false + }, [pathname]) + + const toggleEditor = React.useCallback( + (e) => { + // if first characters of pathname are /things replace with /edit + // or if first characters of pathname are /edit replace with /things + if (pathname.slice(0, 7) === "/things") { + const newPathname = pathname.replace("/things", "/edit") + e?.preventDefault?.() + navigate(newPathname) + } else if (pathname.slice(0, 5) === "/edit") { + const newPathname = pathname.replace("/edit", "/things") + e?.preventDefault?.() + navigate(newPathname) + } + }, + [pathname, navigate] + ) + return ( <> { width="100%" maxWidth="100%" marginY={1} - paddingX="12px" - paddingY="10px" + paddingX="18px" + paddingY="14px" // bg='white' // boxShadow={'0px 0px 10px rgba(0,0,0,0.1)'} > -
- - - +
+
+ + + +
- +
- + {editorToggleable && ( +
+ + {/* */} +
+ )} +
+ +
{/* { width="100%" height="100%" opacity={hidden ? "0" : opacity} + // pointerEvents="none" transition={opacityTransition} > {/* debug svg */} diff --git a/remix/app/components/Thingtime/Thingtime.tsx b/remix/app/components/Thingtime/Thingtime.tsx index d00e3fc..ada30ad 100644 --- a/remix/app/components/Thingtime/Thingtime.tsx +++ b/remix/app/components/Thingtime/Thingtime.tsx @@ -17,7 +17,9 @@ import { } from "@chakra-ui/react" import { Commander } from "../Commander/Commander" +// import { Magic } from "../Commander/Magic" import { Icon } from "../Icon/Icon" +import { MagicInput } from "../MagicInput/MagicInput" import { Safe } from "../Safety/Safe" import { useThingtime } from "./useThingtime" @@ -242,64 +244,91 @@ export const Thingtime = (props) => { return ["view", "edit"] }, []) + const AtomicWrapper = React.useCallback((args) => { + return ( + + {args?.children} + + ) + }, []) + const thingtimeChildren = React.useMemo(() => { - if (template1Modes?.includes(mode)) { - if (keys?.length && !circular) { - const ret = ( - - - {keysToUse?.length && - keysToUse.map((key, idx) => { - if (!key?.human) { - key = { - human: key, - key: key, - } - } + let inner = Imagine.. + if (keys?.length && !circular) { + inner = ( + <> + {keysToUse?.length && + keysToUse.map((key, idx) => { + if (!key?.human) { + key = { + human: key, + key: key, + } + } - const nextThing = thing[key?.key] + const nextThing = thing[key?.key] - const nextSeen = [...seen] + const nextSeen = [...seen] - if (typeof nextThing === "object") { - nextSeen.push(nextThing) - } + if (typeof nextThing === "object") { + nextSeen.push(nextThing) + } - return ( - - ) - })} - - - ) - return ret - } + return ( + + ) + })} + + ) + } + if (type === "object" && !circular) { + return ( + + + {inner} + + + ) } }, [ keysToUse, - mode, circular, seen, type, @@ -311,31 +340,8 @@ export const Thingtime = (props) => { valuePl, pl, keys, - template1Modes, ]) - const AtomicWrapper = React.useCallback((props) => { - return ( - - {props?.children} - - ) - }, []) - const [contentEditableThing, setContentEditableThing] = React.useState(thing) const updateContentEditableThing = React.useCallback((value) => { @@ -388,6 +394,7 @@ export const Thingtime = (props) => { (args) => { const { value } = args + console.log("nik running updateValue", value) setThingtime(fullPath, value) }, [fullPath, setThingtime] @@ -449,10 +456,15 @@ export const Thingtime = (props) => { ) } - if (type === "string" && typeof contentEditableThing === "string") { + if (type === "string") { return ( - + {/* { updateValue({ value: innerText }) } }} - > + > */} ) } if (type === "undefined") { return ( - + {/* TODO: Implement UI-less commander */} - + ) } @@ -614,13 +632,14 @@ export const Thingtime = (props) => { position="relative" flexDirection="column" // width="500px" + rowGap={2} width={props?.width || props?.w || "100%"} maxWidth="100%" + // marginTop={3} paddingRight={pr} + // minW={depth === 1 ? '120px' : null} onMouseEnter={handleMouseEvent} onMouseLeave={handleMouseEvent} - // minW={depth === 1 ? '120px' : null} - paddingY={3} {...(props.chakras || {})} className={`thing uuid-${uuid}`} data-path={props?.path} @@ -663,9 +682,11 @@ export const Thingtime = (props) => { {atomicValue} )} {!loading && thingtimeChildren && ( - {thingtimeChildren} + + {thingtimeChildren} + {addChildUi} + )} - {addChildUi} )