feat: feature/999 I did it

This commit is contained in:
Nikolaj Frey 2023-08-18 00:21:38 +10:00
parent 2a7995c363
commit 4fc02ca68b
5 changed files with 183 additions and 16 deletions

View File

@ -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 (
<Box
position="relative"
width="100%"
transition={props?.transition}
{...(props?.chakras || {})}
ref={ref}
>
<Box
className="magic-input-focusable"
ref={contentEditableRef}
width="100%"
border="none"
@ -146,6 +163,7 @@ export const MagicInput = (props) => {
updateValue({ value: innerText })
}
}}
onKeyDown={maybeUpdateValue}
>
{props?.readonly ? props?.value : null}
</Box>
@ -171,4 +189,4 @@ export const MagicInput = (props) => {
</Box>
</Box>
)
}
})

View File

@ -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 (
<Flex
@ -652,6 +650,59 @@ export const Thingtime = (props) => {
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 (
<>
<MagicInput
ref={pathRef}
value={renderedPath}
readonly={!props?.edit}
onEnter={updatePath}
chakras={{
maxWidth: "100%",
paddingLeft: props?.pathPl || pl,
@ -720,9 +773,10 @@ export const Thingtime = (props) => {
return (
<Safe {...props} depth={depth} uuid={uuid}>
<Flex
ref={thingtimeRef}
position="relative"
flexDirection="column"
// width="500px"
flexDirection="column"
rowGap={2}
width={width}
maxWidth="100%"

View File

@ -1,5 +1,7 @@
import React from "react"
import { Flex } from "@chakra-ui/react"
// import { Sticky, StickyContainer } from "react-sticky"
import Sticky from "react-sticky-el"
import { Box, Flex } from "@chakra-ui/react"
import { useLocation, useMatches } from "@remix-run/react"
import { Thingtime } from "./Thingtime"
@ -58,21 +60,59 @@ export const ThingtimeURL = (props) => {
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 (
<Flex
ref={containerRef}
// position="sticky"
position="relative"
alignItems={inEditorMode ? "flex-start" : "center"}
justifyContent="center"
// overflow="scroll"
// height="auto"
flexDirection={inEditorMode ? "row" : "column"}
maxWidth="100%"
// maxHeight="100vh"
>
{inEditorMode && (
<Thingtime
path={path}
thing={thing}
render
chakras={{ marginY: 200 }}
<Box
ref={editorRef}
position="relative"
// position="sticky"
// top={200}
// alignSelf="flex-start"
// overflow="scroll"
width="600px"
></Thingtime>
// width="100%"
maxHeight="100vh"
paddingY={2}
>
<Thingtime
path={path}
thing={thing}
render
chakras={{ marginY: 200 }}
width="600px"
></Thingtime>
</Box>
)}
<Thingtime
edit={inEditMode}

View File

@ -30,6 +30,9 @@
"react-contenteditable": "^3.3.7",
"react-dom": "^18.2.0",
"react-icons": "^4.10.1",
"react-sticky": "^6.0.3",
"react-sticky-el": "^2.1.0",
"react-visibility-sensor": "^5.1.1",
"tinygradient": "^1.1.5",
"uuid": "^9.0.0"
},

View File

@ -74,6 +74,15 @@ dependencies:
react-icons:
specifier: ^4.10.1
version: 4.10.1(react@18.2.0)
react-sticky:
specifier: ^6.0.3
version: 6.0.3(react-dom@18.2.0)(react@18.2.0)
react-sticky-el:
specifier: ^2.1.0
version: 2.1.0(react-dom@18.2.0)(react@18.2.0)
react-visibility-sensor:
specifier: ^5.1.1
version: 5.1.1(react-dom@18.2.0)(react@18.2.0)
tinygradient:
specifier: ^1.1.5
version: 1.1.5
@ -8301,6 +8310,10 @@ packages:
through2: 2.0.5
dev: true
/performance-now@2.1.0:
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
dev: false
/periscopic@3.1.0:
resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
dependencies:
@ -8587,6 +8600,12 @@ packages:
engines: {node: '>=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'}