diff --git a/remix/app/components/MagicInput/MagicInput.tsx b/remix/app/components/MagicInput/MagicInput.tsx index af762f3..5ddabd8 100644 --- a/remix/app/components/MagicInput/MagicInput.tsx +++ b/remix/app/components/MagicInput/MagicInput.tsx @@ -3,7 +3,7 @@ import { Box } from "@chakra-ui/react" import { useThingtime } from "../Thingtime/useThingtime" -export const MagicInput = (props) => { +export const MagicInput = React.forwardRef((props, ref) => { const { thingtime, setThingtime, loading } = useThingtime() const [inputValue, setInputValue] = React.useState() @@ -92,9 +92,10 @@ export const MagicInput = (props) => { (args) => { const { value } = args props?.onValueChange?.({ value }) + props?.onChange?.({ value }) // updateContentEditableValue(value) }, - [props?.onValueChange] + [props?.onValueChange, props?.onChange] ) const updateValue = React.useCallback( @@ -115,20 +116,36 @@ export const MagicInput = (props) => { [props?.onFocus] ) + const maybeUpdateValue = React.useCallback( + (e) => { + const { key } = e + if (key === "Enter") { + if (props?.onEnter) { + e?.preventDefault?.() + } + props?.onEnter?.({ value: inputValue }) + } + }, + [inputValue, props?.onEnter] + ) + const dangerouslySetInnerHTML = React.useMemo(() => { if (!props?.readonly) { return { __html: contentEditableValue } } // return { __html: contentEditableValue } }, [contentEditableValue, props?.readonly]) + return ( { updateValue({ value: innerText }) } }} + onKeyDown={maybeUpdateValue} > {props?.readonly ? props?.value : null} @@ -171,4 +189,4 @@ export const MagicInput = (props) => { ) -} +}) diff --git a/remix/app/components/Thingtime/Thingtime.tsx b/remix/app/components/Thingtime/Thingtime.tsx index f508305..b8438b6 100644 --- a/remix/app/components/Thingtime/Thingtime.tsx +++ b/remix/app/components/Thingtime/Thingtime.tsx @@ -40,6 +40,8 @@ export const Thingtime = (props) => { const [circular, setCircular] = React.useState(props?.circular) + const thingtimeRef = React.useRef() + const editValueRef = React.useRef({}) const depth = React.useMemo(() => { @@ -304,13 +306,9 @@ export const Thingtime = (props) => { } return keys - }, [hasChakraChildren, keys]) + }, [keys, renderChakra]) // const keysToUse = flattenedKeys - const template1Modes = React.useMemo(() => { - return ["view", "edit"] - }, []) - const AtomicWrapper = React.useCallback((args) => { return ( { return humanPath }, [humanPath, props?.edit]) + const updatePath = React.useCallback( + (args) => { + if (typeof args?.value === "string") { + try { + const parentKeys = Object.keys(parent) + // create new object with new key order + const newObject = {} + + parentKeys.forEach((key) => { + if (key === path) { + newObject[args.value] = parent[key] + return + } + newObject[key] = parent[key] + }) + // set new object + setThingtime(parentPath, newObject) + + // focus next input + const focusableNodeList = thingtimeRef?.current?.querySelectorAll?.( + ".magic-input-focusable" + ) + + // convert focusable to array + const focusable = Array.from(focusableNodeList) + + const pathMagicInputFocusable = pathRef?.current?.querySelector?.( + ".magic-input-focusable" + ) + + const nearestMagicInput = focusable?.find((input) => { + if (input !== pathMagicInputFocusable) { + return true + } + return false + }) + + if (nearestMagicInput && nearestMagicInput?.focus) { + nearestMagicInput.focus() + } + } catch (err) { + console.error( + "Thingtime:657 Something went wrong reassigning path", + err + ) + } + } + }, + [parent, path, parentPath, setThingtime] + ) + + const pathRef = React.useRef(null) + const pathDom = React.useMemo(() => { if (chakras) { return <> @@ -661,8 +712,10 @@ export const Thingtime = (props) => { return ( <> { return ( { return false }, [pathname]) + const containerRef = React.useRef(null) + const editorRef = React.useRef(null) + + React.useEffect(() => { + const scrollListener = () => { + if (containerRef?.current?.getBoundingClientRect) { + const { top } = containerRef?.current?.getBoundingClientRect() + + editorRef.current.style.top = `${-top}px` + } + } + + window.addEventListener("scroll", scrollListener) + + return () => { + window.removeEventListener("scroll", scrollListener) + } + }, []) + return ( {inEditorMode && ( - + // width="100%" + maxHeight="100vh" + paddingY={2} + > + + )} =10'} dev: true + /raf@3.4.1: + resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} + dependencies: + performance-now: 2.1.0 + dev: false + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -8746,6 +8765,28 @@ packages: react: 18.2.0 dev: false + /react-sticky-el@2.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-oo+a2GedF4QMfCfm20e9gD+RuuQp/ngvwGMUXAXpST+h4WnmKhuv7x6MQ4X/e3AHiLYgE0zDyJo1Pzo8m51KpA==} + peerDependencies: + react: '>=16.3.0' + react-dom: '>=16.3.0' + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /react-sticky@6.0.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-LNH4UJlRatOqo29/VHxDZOf6fwbgfgcHO4mkEFvrie5FuaZCSTGtug5R8NGqJ0kSnX8gHw8qZN37FcvnFBJpTQ==} + peerDependencies: + react: '>=15' + react-dom: '>=15' + dependencies: + prop-types: 15.8.1 + raf: 3.4.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /react-style-singleton@2.2.1(@types/react@17.0.62)(react@18.2.0): resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} @@ -8763,6 +8804,17 @@ packages: tslib: 2.5.0 dev: false + /react-visibility-sensor@5.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cTUHqIK+zDYpeK19rzW6zF9YfT4486TIgizZW53wEZ+/GPBbK7cNS0EHyJVyHYacwFEvvHLEKfgJndbemWhB/w==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'}