2023-07-04 08:05:08 +00:00
|
|
|
import React from "react"
|
|
|
|
import ClickAwayListener from "react-click-away-listener"
|
2023-08-13 05:53:47 +00:00
|
|
|
import { Box, Center, Flex, Input } from "@chakra-ui/react"
|
2023-07-15 08:08:36 +00:00
|
|
|
import Fuse from "fuse.js"
|
2023-07-04 08:05:08 +00:00
|
|
|
|
2023-08-13 05:53:47 +00:00
|
|
|
import { MagicInput } from "../MagicInput/MagicInput"
|
2023-07-05 10:05:35 +00:00
|
|
|
import { Rainbow } from "../Rainbow/Rainbow"
|
2023-07-04 08:05:08 +00:00
|
|
|
import { Thingtime } from "../Thingtime/Thingtime"
|
|
|
|
import { useThingtime } from "../Thingtime/useThingtime"
|
|
|
|
|
|
|
|
import { sanitise } from "~/functions/sanitise"
|
|
|
|
import { getParentPath } from "~/smarts"
|
|
|
|
|
|
|
|
export const Commander = (props) => {
|
2023-07-15 08:08:36 +00:00
|
|
|
const { thingtime, setThingtime, getThingtime, thingtimeRef, paths } =
|
|
|
|
useThingtime()
|
2023-07-01 14:13:27 +00:00
|
|
|
|
2023-08-12 12:22:52 +00:00
|
|
|
const commanderId = React.useMemo(() => {
|
|
|
|
return props?.id || "global"
|
|
|
|
}, [props?.id])
|
|
|
|
|
2023-07-01 14:13:27 +00:00
|
|
|
const inputRef = React.useRef()
|
|
|
|
|
2023-08-12 14:06:33 +00:00
|
|
|
const global = props?.global
|
|
|
|
|
|
|
|
const commanderSettings = React.useMemo(() => {
|
|
|
|
return thingtime?.settings?.commander?.[commanderId] || {}
|
|
|
|
}, [
|
|
|
|
thingtime?.settings?.commander,
|
|
|
|
thingtime?.settings?.commander?.[commanderId],
|
|
|
|
commanderId,
|
|
|
|
])
|
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
const [inputValue, setInputValue] = React.useState("")
|
|
|
|
const [virtualValue, setVirtualValue] = React.useState("")
|
|
|
|
const [hoveredSuggestion, setHoveredSuggestion] = React.useState()
|
2023-07-05 10:05:35 +00:00
|
|
|
const [active, setActive] = React.useState(false)
|
2023-07-01 09:46:36 +00:00
|
|
|
const [contextPath, setContextPath] = React.useState()
|
|
|
|
|
2023-08-12 12:22:52 +00:00
|
|
|
const mode = React.useMemo(() => {
|
|
|
|
return props?.mode || "value"
|
|
|
|
}, [props?.mode])
|
|
|
|
|
2023-07-01 14:13:27 +00:00
|
|
|
const [showContext, setShowContextState] = React.useState(false)
|
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
const mobileVW = React.useMemo(() => {
|
2023-07-21 01:13:02 +00:00
|
|
|
return "calc(100vw - 55px)"
|
2023-07-15 08:08:36 +00:00
|
|
|
}, [])
|
|
|
|
|
|
|
|
const rainbowRepeats = 2
|
|
|
|
|
2023-07-01 14:13:27 +00:00
|
|
|
const setShowContext = React.useCallback(
|
2023-07-04 08:05:08 +00:00
|
|
|
(value, from?: string) => {
|
2023-07-01 14:13:27 +00:00
|
|
|
setShowContextState(value)
|
|
|
|
},
|
|
|
|
[setShowContextState]
|
|
|
|
)
|
2023-07-04 08:05:08 +00:00
|
|
|
// const [suggestions, setSuggestions] = React.useState([])
|
2023-07-01 09:46:36 +00:00
|
|
|
|
|
|
|
const contextValue = React.useMemo(() => {
|
2023-07-04 08:05:08 +00:00
|
|
|
// TODO: Figure out why this is running on every click
|
2023-07-01 09:46:36 +00:00
|
|
|
const ret = getThingtime(contextPath)
|
|
|
|
return ret
|
|
|
|
}, [contextPath, getThingtime])
|
|
|
|
|
2023-07-05 10:05:35 +00:00
|
|
|
const commanderActive = React.useMemo(() => {
|
2023-08-12 14:06:33 +00:00
|
|
|
return thingtime?.settings?.commander?.[commanderId]?.commanderActive
|
|
|
|
}, [commanderSettings, commanderId])
|
2023-07-05 10:05:35 +00:00
|
|
|
|
|
|
|
// commanderActive useEffect
|
2023-07-01 14:13:27 +00:00
|
|
|
React.useEffect(() => {
|
2023-07-05 10:05:35 +00:00
|
|
|
if (commanderActive) {
|
2023-08-13 05:53:47 +00:00
|
|
|
if (props?.global) {
|
|
|
|
inputRef?.current?.focus?.()
|
|
|
|
}
|
2023-07-01 14:13:27 +00:00
|
|
|
} else {
|
2023-08-13 05:53:47 +00:00
|
|
|
if (props?.global) {
|
|
|
|
document.activeElement.blur()
|
|
|
|
}
|
2023-07-07 07:42:14 +00:00
|
|
|
|
2023-08-12 14:06:33 +00:00
|
|
|
if (
|
|
|
|
thingtimeRef?.current?.settings?.commander?.[commanderId]
|
|
|
|
?.clearCommanderOnToggle
|
|
|
|
) {
|
2023-07-15 08:08:36 +00:00
|
|
|
setInputValue("")
|
|
|
|
setHoveredSuggestion(null)
|
2023-07-01 14:13:27 +00:00
|
|
|
}
|
2023-08-12 14:06:33 +00:00
|
|
|
if (
|
|
|
|
thingtimeRef?.current?.settings?.commander?.[commanderId]?.commander?.[
|
|
|
|
commanderId
|
|
|
|
]?.clearCommanderContextOnToggle
|
|
|
|
) {
|
2023-07-05 10:05:35 +00:00
|
|
|
setShowContext(false, "commanderActive useEffect")
|
2023-07-01 14:13:27 +00:00
|
|
|
}
|
2023-08-11 00:04:20 +00:00
|
|
|
if (contextPath !== undefined && !inputValue) {
|
2023-07-07 07:42:14 +00:00
|
|
|
setContextPath(undefined)
|
|
|
|
}
|
|
|
|
if (showContext !== false) {
|
|
|
|
setShowContext(false)
|
|
|
|
}
|
2023-07-01 09:46:36 +00:00
|
|
|
}
|
2023-07-07 07:42:14 +00:00
|
|
|
}, [
|
|
|
|
commanderActive,
|
|
|
|
thingtimeRef,
|
|
|
|
setShowContext,
|
2023-08-13 05:53:47 +00:00
|
|
|
props?.global,
|
2023-08-12 14:06:33 +00:00
|
|
|
commanderId,
|
2023-07-15 08:08:36 +00:00
|
|
|
inputValue,
|
2023-07-07 07:42:14 +00:00
|
|
|
contextPath,
|
|
|
|
showContext,
|
|
|
|
])
|
2023-07-01 09:46:36 +00:00
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
const onInputChange = React.useCallback((e) => {
|
|
|
|
setInputValue(e.target.value)
|
|
|
|
setHoveredSuggestion(null)
|
2023-07-01 09:46:36 +00:00
|
|
|
}, [])
|
|
|
|
|
2023-07-01 14:13:27 +00:00
|
|
|
const validSetters = React.useMemo(() => {
|
2023-08-11 00:04:20 +00:00
|
|
|
return ["=", " is ", " IS ", " Is ", " iS "]
|
2023-07-01 14:13:27 +00:00
|
|
|
}, [])
|
|
|
|
|
|
|
|
const command = React.useMemo(() => {
|
2023-07-15 08:08:36 +00:00
|
|
|
// const sanitizedCommand = sanitise(value)
|
|
|
|
// const sanitizedCommand = inputValue
|
2023-08-13 05:53:47 +00:00
|
|
|
const sanitizedInput = virtualValue
|
2023-07-01 14:13:27 +00:00
|
|
|
|
2023-08-11 00:04:20 +00:00
|
|
|
const validSetter = validSetters?.find((setter) => {
|
2023-08-13 05:53:47 +00:00
|
|
|
if (sanitizedInput?.includes(setter)) {
|
2023-08-11 00:04:20 +00:00
|
|
|
return setter
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
|
|
|
|
if (typeof validSetter === "string") {
|
2023-08-13 05:53:47 +00:00
|
|
|
const indexOfSplitter = sanitizedInput?.indexOf(validSetter)
|
2023-07-01 14:13:27 +00:00
|
|
|
const [pathRaw, valRaw] = [
|
2023-08-13 05:53:47 +00:00
|
|
|
sanitizedInput?.slice(0, indexOfSplitter),
|
|
|
|
sanitizedInput?.slice(indexOfSplitter + validSetter?.length),
|
2023-07-01 14:13:27 +00:00
|
|
|
]
|
2023-08-11 00:04:20 +00:00
|
|
|
|
2023-08-13 05:53:47 +00:00
|
|
|
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()]
|
|
|
|
}
|
|
|
|
|
|
|
|
if (props?.pathPrefix) {
|
|
|
|
return [props?.pathPrefix, sanitizedInput]
|
2023-07-01 14:13:27 +00:00
|
|
|
}
|
2023-08-13 05:53:47 +00:00
|
|
|
|
|
|
|
return [sanitizedInput]
|
2023-07-15 08:08:36 +00:00
|
|
|
}, [
|
|
|
|
// inputValue,
|
2023-08-13 05:53:47 +00:00
|
|
|
props?.pathPrefix,
|
2023-07-15 08:08:36 +00:00
|
|
|
virtualValue,
|
|
|
|
validSetters,
|
|
|
|
])
|
2023-07-01 14:13:27 +00:00
|
|
|
|
|
|
|
const commandPath = React.useMemo(() => {
|
2023-07-15 08:08:36 +00:00
|
|
|
return command?.[0]
|
|
|
|
// return sanitise(command?.[0])
|
2023-07-01 14:13:27 +00:00
|
|
|
}, [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, "\\'")
|
2023-08-13 05:53:47 +00:00
|
|
|
?.replace(/`/g, "\\`")
|
|
|
|
|
|
|
|
const ret = `\`${escaped}\``
|
2023-07-01 14:13:27 +00:00
|
|
|
return ret
|
|
|
|
}, [commandValue, validQuotations])
|
|
|
|
|
|
|
|
const commandIsAction = React.useMemo(() => {
|
|
|
|
return commandPath && commandValue
|
|
|
|
}, [commandPath, commandValue])
|
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
const suggestions = React.useMemo(() => {
|
2023-08-03 10:56:42 +00:00
|
|
|
try {
|
|
|
|
const fuse = new Fuse(paths)
|
2023-07-01 14:13:27 +00:00
|
|
|
|
2023-08-03 10:56:42 +00:00
|
|
|
const results = fuse.search(inputValue)
|
2023-07-01 14:13:27 +00:00
|
|
|
|
2023-08-03 10:56:42 +00:00
|
|
|
const mappedResults = results?.map((result) => {
|
|
|
|
return result?.item
|
|
|
|
})
|
2023-07-07 07:42:14 +00:00
|
|
|
|
2023-08-03 10:56:42 +00:00
|
|
|
return mappedResults
|
|
|
|
} catch (err) {
|
2023-08-03 13:48:56 +00:00
|
|
|
console.error("fuse error", err)
|
2023-08-03 10:56:42 +00:00
|
|
|
}
|
2023-07-15 08:08:36 +00:00
|
|
|
}, [inputValue, paths])
|
2023-07-07 07:42:14 +00:00
|
|
|
|
2023-08-09 03:34:18 +00:00
|
|
|
const showSuggestions = React.useMemo(() => {
|
|
|
|
return (
|
|
|
|
inputValue?.length &&
|
|
|
|
suggestions?.length &&
|
|
|
|
commanderActive &&
|
2023-08-12 14:06:33 +00:00
|
|
|
thingtime?.settings?.commander?.[commanderId]?.hideSuggestionsOnToggle
|
2023-08-09 03:34:18 +00:00
|
|
|
)
|
|
|
|
}, [
|
|
|
|
inputValue,
|
|
|
|
suggestions,
|
|
|
|
commanderActive,
|
2023-08-12 14:06:33 +00:00
|
|
|
commanderId,
|
|
|
|
thingtime?.settings?.commander,
|
|
|
|
commanderSettings,
|
2023-08-09 03:34:18 +00:00
|
|
|
])
|
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
const selectSuggestion = React.useCallback(
|
|
|
|
(suggestionIdx) => {
|
|
|
|
const suggestion = suggestions?.[suggestionIdx]
|
2023-07-07 07:42:14 +00:00
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
setInputValue(suggestion)
|
|
|
|
setHoveredSuggestion(null)
|
|
|
|
setContextPath(suggestion)
|
|
|
|
setShowContext(true, "Select suggestion")
|
|
|
|
},
|
|
|
|
[setInputValue, setContextPath, setShowContext, suggestions]
|
|
|
|
)
|
2023-07-07 07:42:14 +00:00
|
|
|
|
|
|
|
const commandContainsPath = React.useMemo(() => {
|
|
|
|
const commandIncludesSuggestion = suggestions?.find((suggestion) => {
|
|
|
|
return commandPath?.includes(suggestion)
|
|
|
|
})
|
|
|
|
// return false
|
|
|
|
return commandIncludesSuggestion
|
|
|
|
}, [commandPath, suggestions])
|
2023-07-01 14:13:27 +00:00
|
|
|
|
2023-07-01 09:46:36 +00:00
|
|
|
const openCommander = React.useCallback(() => {
|
2023-08-12 14:06:33 +00:00
|
|
|
setThingtime(`settings.commander.${commanderId}.commanderActive`, true)
|
|
|
|
}, [setThingtime, commanderId])
|
2023-07-01 09:46:36 +00:00
|
|
|
|
2023-07-07 07:42:14 +00:00
|
|
|
const closeCommander = React.useCallback(
|
2023-07-15 08:08:36 +00:00
|
|
|
(e?: any) => {
|
2023-07-21 13:33:47 +00:00
|
|
|
if (!e?.defaultPrevented) {
|
2023-08-12 14:06:33 +00:00
|
|
|
if (thingtime?.settings?.commander?.[commanderId]?.commanderActive) {
|
|
|
|
setThingtime(
|
|
|
|
`settings.commander.${commanderId}.commanderActive`,
|
|
|
|
false
|
|
|
|
)
|
2023-07-21 13:33:47 +00:00
|
|
|
}
|
2023-07-07 07:42:14 +00:00
|
|
|
}
|
|
|
|
},
|
2023-08-12 14:06:33 +00:00
|
|
|
[
|
|
|
|
setThingtime,
|
|
|
|
commanderId,
|
|
|
|
commanderSettings,
|
|
|
|
thingtime?.settings?.commander,
|
|
|
|
]
|
2023-07-07 07:42:14 +00:00
|
|
|
)
|
2023-07-01 09:46:36 +00:00
|
|
|
|
|
|
|
const toggleCommander = React.useCallback(() => {
|
2023-08-12 14:06:33 +00:00
|
|
|
if (thingtime?.settings?.commander?.[commanderId]?.commanderActive) {
|
2023-07-01 09:46:36 +00:00
|
|
|
closeCommander()
|
|
|
|
} else {
|
|
|
|
openCommander()
|
|
|
|
}
|
2023-08-12 14:06:33 +00:00
|
|
|
}, [
|
|
|
|
thingtime?.settings?.commander,
|
|
|
|
commanderSettings,
|
|
|
|
commanderId,
|
|
|
|
closeCommander,
|
|
|
|
openCommander,
|
|
|
|
])
|
2023-07-01 09:46:36 +00:00
|
|
|
|
2023-08-08 22:13:09 +00:00
|
|
|
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
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2023-08-11 00:04:20 +00:00
|
|
|
// if (!prevVal) {
|
|
|
|
setContextPath(commandPath)
|
|
|
|
setShowContext(true, "commandIsAction check")
|
|
|
|
// }
|
2023-08-08 22:13:09 +00:00
|
|
|
}
|
|
|
|
// 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,
|
|
|
|
])
|
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
const allCommanderKeyListener = React.useCallback(
|
|
|
|
(e: any) => {
|
|
|
|
console.log("commander key listener e?.code", e?.code)
|
2023-07-21 14:32:08 +00:00
|
|
|
thingtimeRef.current = thingtime
|
2023-07-04 08:05:08 +00:00
|
|
|
if (e?.metaKey && e?.code === "KeyP") {
|
2023-07-01 09:46:36 +00:00
|
|
|
e.preventDefault()
|
|
|
|
e.stopPropagation()
|
|
|
|
toggleCommander()
|
|
|
|
}
|
|
|
|
// if key escape close all modals
|
2023-07-15 08:08:36 +00:00
|
|
|
else if (e?.code === "Escape") {
|
2023-07-01 09:46:36 +00:00
|
|
|
closeCommander()
|
|
|
|
}
|
2023-07-21 13:33:47 +00:00
|
|
|
|
2023-08-03 10:56:42 +00:00
|
|
|
// 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") {
|
2023-08-13 05:53:47 +00:00
|
|
|
// if not shift enter then execute command
|
|
|
|
if (!e?.shiftKey) {
|
|
|
|
executeCommand()
|
|
|
|
}
|
2023-07-15 08:08:36 +00:00
|
|
|
}
|
|
|
|
}
|
2023-07-01 14:13:27 +00:00
|
|
|
},
|
2023-07-15 08:08:36 +00:00
|
|
|
[
|
|
|
|
closeCommander,
|
|
|
|
toggleCommander,
|
|
|
|
hoveredSuggestion,
|
|
|
|
suggestions,
|
2023-07-21 14:32:08 +00:00
|
|
|
thingtime,
|
|
|
|
thingtimeRef,
|
2023-07-15 08:08:36 +00:00
|
|
|
commanderActive,
|
2023-08-08 22:13:09 +00:00
|
|
|
executeCommand,
|
2023-07-15 08:08:36 +00:00
|
|
|
]
|
2023-07-01 14:13:27 +00:00
|
|
|
)
|
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
React.useEffect(() => {
|
|
|
|
window.addEventListener("keydown", allCommanderKeyListener)
|
2023-07-01 14:13:27 +00:00
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
return () => {
|
|
|
|
window.removeEventListener("keydown", allCommanderKeyListener)
|
|
|
|
}
|
|
|
|
}, [allCommanderKeyListener])
|
2023-07-01 14:13:27 +00:00
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
React.useEffect(() => {
|
|
|
|
if (typeof hoveredSuggestion === "number") {
|
|
|
|
setVirtualValue(suggestions?.[hoveredSuggestion])
|
|
|
|
} else {
|
|
|
|
setVirtualValue(inputValue)
|
|
|
|
}
|
|
|
|
}, [hoveredSuggestion, inputValue, suggestions])
|
2023-07-01 09:46:36 +00:00
|
|
|
|
2023-07-15 08:08:36 +00:00
|
|
|
React.useEffect(() => {
|
|
|
|
setVirtualValue(inputValue)
|
|
|
|
}, [inputValue])
|
2023-07-05 10:05:35 +00:00
|
|
|
|
2023-08-13 05:53:47 +00:00
|
|
|
const onMagicInput = React.useCallback((args) => {
|
|
|
|
// props?.onValueChange?.(args)
|
|
|
|
|
|
|
|
setInputValue(args?.value)
|
|
|
|
setHoveredSuggestion(null)
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
const InputPartWrapper = React.useCallback(
|
|
|
|
(props) => {
|
|
|
|
return <Box paddingX={commanderActive ? 1 : 0}>{props?.children}</Box>
|
|
|
|
},
|
|
|
|
[commanderActive]
|
|
|
|
)
|
|
|
|
|
|
|
|
const InputPart = React.useMemo(() => {
|
|
|
|
if (props?.simple) {
|
|
|
|
return (
|
|
|
|
<Input
|
|
|
|
// display='none'
|
|
|
|
// opacity={0}
|
|
|
|
ref={inputRef}
|
|
|
|
sx={{
|
|
|
|
"&::placeholder": {
|
|
|
|
color: "greys.dark",
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
width="100%"
|
|
|
|
height="100%"
|
|
|
|
background="grey"
|
|
|
|
border="none"
|
|
|
|
borderRadius="5px"
|
|
|
|
outline="none"
|
|
|
|
onChange={onInputChange}
|
|
|
|
onFocus={openCommander}
|
|
|
|
placeholder="Imagine.."
|
|
|
|
value={inputValue}
|
|
|
|
></Input>
|
|
|
|
)
|
|
|
|
}
|
2023-08-12 14:06:33 +00:00
|
|
|
|
|
|
|
return (
|
2023-08-13 05:53:47 +00:00
|
|
|
<MagicInput
|
|
|
|
placeholder={props?.placeholder || "Imagine.."}
|
|
|
|
onValueChange={onMagicInput}
|
|
|
|
onFocus={openCommander}
|
|
|
|
chakras={{
|
|
|
|
marginX: commanderActive && props?.rainbow ? 4 : 0,
|
|
|
|
}}
|
|
|
|
transition="all 0.5s ease-in-out"
|
|
|
|
></MagicInput>
|
2023-08-12 14:06:33 +00:00
|
|
|
)
|
2023-08-13 05:53:47 +00:00
|
|
|
}, [
|
|
|
|
inputRef,
|
|
|
|
onInputChange,
|
|
|
|
commanderActive,
|
|
|
|
props?.rainbow,
|
|
|
|
props?.placeholder,
|
|
|
|
openCommander,
|
|
|
|
onMagicInput,
|
|
|
|
props?.simple,
|
|
|
|
inputValue,
|
|
|
|
])
|
2023-08-12 14:06:33 +00:00
|
|
|
|
2023-07-01 09:46:36 +00:00
|
|
|
return (
|
2023-07-01 14:49:01 +00:00
|
|
|
<ClickAwayListener onClickAway={closeCommander}>
|
2023-07-01 14:13:27 +00:00
|
|
|
<Flex
|
2023-08-13 05:53:47 +00:00
|
|
|
// position="absolute"
|
|
|
|
// top={0}
|
|
|
|
// right={0}
|
|
|
|
// left={0}
|
2023-07-01 14:49:01 +00:00
|
|
|
// zIndex={99999}
|
|
|
|
// position='fixed'
|
|
|
|
// top='100px'
|
2023-08-13 05:53:47 +00:00
|
|
|
className={"commander-uuid-" + commanderId}
|
2023-07-05 10:14:49 +00:00
|
|
|
// display={["flex", commanderActive ? "flex" : "none"]}
|
2023-08-13 05:53:47 +00:00
|
|
|
justifyContent="flex-start"
|
2023-07-04 08:05:08 +00:00
|
|
|
maxWidth="100%"
|
2023-07-07 07:42:14 +00:00
|
|
|
// height="100%"
|
2023-08-13 05:53:47 +00:00
|
|
|
// paddingX={1}
|
2023-07-01 09:46:36 +00:00
|
|
|
>
|
2023-08-13 05:53:47 +00:00
|
|
|
<Center
|
|
|
|
position="relative"
|
|
|
|
flexDirection="column"
|
|
|
|
width={["100%", "400px"]}
|
|
|
|
maxWidth={[mobileVW, "100%"]}
|
|
|
|
height="100%"
|
|
|
|
>
|
|
|
|
{props?.rainbow && (
|
|
|
|
<Rainbow
|
|
|
|
filter="blur(15px)"
|
|
|
|
opacity={commanderActive ? 0.25 : 0}
|
|
|
|
repeats={rainbowRepeats}
|
|
|
|
thickness={10}
|
|
|
|
opacityTransition="all 1000ms ease"
|
|
|
|
overflow="visible"
|
|
|
|
>
|
|
|
|
<Center
|
|
|
|
position="relative"
|
|
|
|
overflow="hidden"
|
|
|
|
width={["100%", "400px"]}
|
|
|
|
maxWidth={[mobileVW, "100%"]}
|
|
|
|
height="100%"
|
|
|
|
padding="1px"
|
|
|
|
borderRadius="6px"
|
|
|
|
pointerEvents="all"
|
|
|
|
outline="none"
|
|
|
|
>
|
|
|
|
<Rainbow
|
|
|
|
opacity={commanderActive ? 0.6 : 0}
|
|
|
|
position="absolute"
|
|
|
|
repeats={rainbowRepeats}
|
|
|
|
opacityTransition="all 2500ms ease"
|
|
|
|
thickness={1}
|
|
|
|
>
|
|
|
|
{/* <InputPartWrapper>{InputPart}</InputPartWrapper> */}
|
|
|
|
{InputPart}
|
|
|
|
</Rainbow>
|
|
|
|
</Center>
|
|
|
|
</Rainbow>
|
|
|
|
)}
|
|
|
|
{!props?.rainbow && InputPart}
|
|
|
|
</Center>
|
2023-07-01 14:13:27 +00:00
|
|
|
<Flex
|
2023-08-13 05:53:47 +00:00
|
|
|
// position="absolute"
|
|
|
|
// top="100%"
|
|
|
|
// right={0}
|
|
|
|
// left={0}
|
|
|
|
alignItems="flex-start"
|
2023-07-04 08:05:08 +00:00
|
|
|
flexDirection="column"
|
|
|
|
maxWidth="100%"
|
|
|
|
height="auto"
|
2023-08-13 05:53:47 +00:00
|
|
|
// marginTop={2}
|
2023-07-04 08:05:08 +00:00
|
|
|
borderRadius="12px"
|
2023-08-13 05:53:47 +00:00
|
|
|
// marginX={1}
|
2023-07-01 14:13:27 +00:00
|
|
|
>
|
2023-07-01 14:49:01 +00:00
|
|
|
<Flex
|
2023-07-24 03:02:27 +00:00
|
|
|
alignItems={["flex-start", "center"]}
|
2023-07-04 08:05:08 +00:00
|
|
|
flexDirection="column"
|
2023-07-24 03:02:27 +00:00
|
|
|
overflowY="scroll"
|
|
|
|
width="auto"
|
2023-07-04 08:05:08 +00:00
|
|
|
maxWidth="100%"
|
2023-07-24 03:02:27 +00:00
|
|
|
maxHeight="90vh"
|
2023-07-04 08:05:08 +00:00
|
|
|
borderRadius="12px"
|
2023-07-01 14:49:01 +00:00
|
|
|
>
|
2023-07-24 03:02:27 +00:00
|
|
|
<Flex
|
|
|
|
flexDirection="column"
|
|
|
|
flexShrink={0}
|
|
|
|
display={showSuggestions ? "flex" : "none"}
|
|
|
|
overflowY="scroll"
|
|
|
|
width={["100%", "400px"]}
|
|
|
|
maxWidth="100%"
|
|
|
|
maxHeight="300px"
|
|
|
|
marginBottom={3}
|
|
|
|
background="grey"
|
|
|
|
borderRadius="12px"
|
|
|
|
pointerEvents="all"
|
|
|
|
id="commander-suggestions"
|
|
|
|
onMouseLeave={() => setHoveredSuggestion(null)}
|
|
|
|
paddingY={3}
|
|
|
|
>
|
|
|
|
{suggestions?.map((suggestion, i) => {
|
|
|
|
return (
|
|
|
|
<Flex
|
|
|
|
key={i}
|
|
|
|
background={hoveredSuggestion === i ? "greys.lightt" : null}
|
|
|
|
_hover={{
|
|
|
|
background: "greys.lightt",
|
|
|
|
}}
|
|
|
|
cursor="pointer"
|
|
|
|
onClick={() => selectSuggestion(i)}
|
|
|
|
onMouseEnter={() => setHoveredSuggestion(i)}
|
|
|
|
paddingX={4}
|
|
|
|
>
|
|
|
|
{suggestion}
|
|
|
|
</Flex>
|
|
|
|
)
|
|
|
|
})}
|
|
|
|
</Flex>
|
2023-08-13 05:53:47 +00:00
|
|
|
{showContext && props?.context && (
|
2023-08-03 10:56:42 +00:00
|
|
|
<Flex
|
|
|
|
display={showContext ? "flex" : "none"}
|
|
|
|
maxWidth="100%"
|
|
|
|
background="grey"
|
|
|
|
borderRadius="12px"
|
|
|
|
pointerEvents="all"
|
|
|
|
paddingY={3}
|
|
|
|
>
|
2023-08-09 03:34:18 +00:00
|
|
|
<Thingtime
|
|
|
|
width="600px"
|
|
|
|
path={contextPath}
|
|
|
|
thing={contextValue}
|
|
|
|
></Thingtime>
|
2023-08-03 10:56:42 +00:00
|
|
|
</Flex>
|
|
|
|
)}
|
2023-07-01 14:49:01 +00:00
|
|
|
</Flex>
|
2023-07-01 14:13:27 +00:00
|
|
|
</Flex>
|
2023-07-01 14:49:01 +00:00
|
|
|
</Flex>
|
|
|
|
</ClickAwayListener>
|
2023-07-01 09:46:36 +00:00
|
|
|
)
|
|
|
|
}
|