feat: feature/999 I did it
This commit is contained in:
parent
2a7995c363
commit
4fc02ca68b
@ -3,7 +3,7 @@ import { Box } from "@chakra-ui/react"
|
|||||||
|
|
||||||
import { useThingtime } from "../Thingtime/useThingtime"
|
import { useThingtime } from "../Thingtime/useThingtime"
|
||||||
|
|
||||||
export const MagicInput = (props) => {
|
export const MagicInput = React.forwardRef((props, ref) => {
|
||||||
const { thingtime, setThingtime, loading } = useThingtime()
|
const { thingtime, setThingtime, loading } = useThingtime()
|
||||||
|
|
||||||
const [inputValue, setInputValue] = React.useState()
|
const [inputValue, setInputValue] = React.useState()
|
||||||
@ -92,9 +92,10 @@ export const MagicInput = (props) => {
|
|||||||
(args) => {
|
(args) => {
|
||||||
const { value } = args
|
const { value } = args
|
||||||
props?.onValueChange?.({ value })
|
props?.onValueChange?.({ value })
|
||||||
|
props?.onChange?.({ value })
|
||||||
// updateContentEditableValue(value)
|
// updateContentEditableValue(value)
|
||||||
},
|
},
|
||||||
[props?.onValueChange]
|
[props?.onValueChange, props?.onChange]
|
||||||
)
|
)
|
||||||
|
|
||||||
const updateValue = React.useCallback(
|
const updateValue = React.useCallback(
|
||||||
@ -115,20 +116,36 @@ export const MagicInput = (props) => {
|
|||||||
[props?.onFocus]
|
[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(() => {
|
const dangerouslySetInnerHTML = React.useMemo(() => {
|
||||||
if (!props?.readonly) {
|
if (!props?.readonly) {
|
||||||
return { __html: contentEditableValue }
|
return { __html: contentEditableValue }
|
||||||
}
|
}
|
||||||
// return { __html: contentEditableValue }
|
// return { __html: contentEditableValue }
|
||||||
}, [contentEditableValue, props?.readonly])
|
}, [contentEditableValue, props?.readonly])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
position="relative"
|
position="relative"
|
||||||
width="100%"
|
width="100%"
|
||||||
transition={props?.transition}
|
transition={props?.transition}
|
||||||
{...(props?.chakras || {})}
|
{...(props?.chakras || {})}
|
||||||
|
ref={ref}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
|
className="magic-input-focusable"
|
||||||
ref={contentEditableRef}
|
ref={contentEditableRef}
|
||||||
width="100%"
|
width="100%"
|
||||||
border="none"
|
border="none"
|
||||||
@ -146,6 +163,7 @@ export const MagicInput = (props) => {
|
|||||||
updateValue({ value: innerText })
|
updateValue({ value: innerText })
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
onKeyDown={maybeUpdateValue}
|
||||||
>
|
>
|
||||||
{props?.readonly ? props?.value : null}
|
{props?.readonly ? props?.value : null}
|
||||||
</Box>
|
</Box>
|
||||||
@ -171,4 +189,4 @@ export const MagicInput = (props) => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
@ -40,6 +40,8 @@ export const Thingtime = (props) => {
|
|||||||
|
|
||||||
const [circular, setCircular] = React.useState(props?.circular)
|
const [circular, setCircular] = React.useState(props?.circular)
|
||||||
|
|
||||||
|
const thingtimeRef = React.useRef()
|
||||||
|
|
||||||
const editValueRef = React.useRef({})
|
const editValueRef = React.useRef({})
|
||||||
|
|
||||||
const depth = React.useMemo(() => {
|
const depth = React.useMemo(() => {
|
||||||
@ -304,13 +306,9 @@ export const Thingtime = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return keys
|
return keys
|
||||||
}, [hasChakraChildren, keys])
|
}, [keys, renderChakra])
|
||||||
// const keysToUse = flattenedKeys
|
// const keysToUse = flattenedKeys
|
||||||
|
|
||||||
const template1Modes = React.useMemo(() => {
|
|
||||||
return ["view", "edit"]
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const AtomicWrapper = React.useCallback((args) => {
|
const AtomicWrapper = React.useCallback((args) => {
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
@ -652,6 +650,59 @@ export const Thingtime = (props) => {
|
|||||||
return humanPath
|
return humanPath
|
||||||
}, [humanPath, props?.edit])
|
}, [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(() => {
|
const pathDom = React.useMemo(() => {
|
||||||
if (chakras) {
|
if (chakras) {
|
||||||
return <></>
|
return <></>
|
||||||
@ -661,8 +712,10 @@ export const Thingtime = (props) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MagicInput
|
<MagicInput
|
||||||
|
ref={pathRef}
|
||||||
value={renderedPath}
|
value={renderedPath}
|
||||||
readonly={!props?.edit}
|
readonly={!props?.edit}
|
||||||
|
onEnter={updatePath}
|
||||||
chakras={{
|
chakras={{
|
||||||
maxWidth: "100%",
|
maxWidth: "100%",
|
||||||
paddingLeft: props?.pathPl || pl,
|
paddingLeft: props?.pathPl || pl,
|
||||||
@ -720,9 +773,10 @@ export const Thingtime = (props) => {
|
|||||||
return (
|
return (
|
||||||
<Safe {...props} depth={depth} uuid={uuid}>
|
<Safe {...props} depth={depth} uuid={uuid}>
|
||||||
<Flex
|
<Flex
|
||||||
|
ref={thingtimeRef}
|
||||||
position="relative"
|
position="relative"
|
||||||
flexDirection="column"
|
|
||||||
// width="500px"
|
// width="500px"
|
||||||
|
flexDirection="column"
|
||||||
rowGap={2}
|
rowGap={2}
|
||||||
width={width}
|
width={width}
|
||||||
maxWidth="100%"
|
maxWidth="100%"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import React from "react"
|
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 { useLocation, useMatches } from "@remix-run/react"
|
||||||
|
|
||||||
import { Thingtime } from "./Thingtime"
|
import { Thingtime } from "./Thingtime"
|
||||||
@ -58,21 +60,59 @@ export const ThingtimeURL = (props) => {
|
|||||||
return false
|
return false
|
||||||
}, [pathname])
|
}, [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 (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
ref={containerRef}
|
||||||
|
// position="sticky"
|
||||||
|
position="relative"
|
||||||
alignItems={inEditorMode ? "flex-start" : "center"}
|
alignItems={inEditorMode ? "flex-start" : "center"}
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
|
// overflow="scroll"
|
||||||
|
// height="auto"
|
||||||
flexDirection={inEditorMode ? "row" : "column"}
|
flexDirection={inEditorMode ? "row" : "column"}
|
||||||
maxWidth="100%"
|
maxWidth="100%"
|
||||||
|
// maxHeight="100vh"
|
||||||
>
|
>
|
||||||
{inEditorMode && (
|
{inEditorMode && (
|
||||||
<Thingtime
|
<Box
|
||||||
path={path}
|
ref={editorRef}
|
||||||
thing={thing}
|
position="relative"
|
||||||
render
|
// position="sticky"
|
||||||
chakras={{ marginY: 200 }}
|
// top={200}
|
||||||
|
// alignSelf="flex-start"
|
||||||
|
// overflow="scroll"
|
||||||
width="600px"
|
width="600px"
|
||||||
></Thingtime>
|
// width="100%"
|
||||||
|
maxHeight="100vh"
|
||||||
|
paddingY={2}
|
||||||
|
>
|
||||||
|
<Thingtime
|
||||||
|
path={path}
|
||||||
|
thing={thing}
|
||||||
|
render
|
||||||
|
chakras={{ marginY: 200 }}
|
||||||
|
width="600px"
|
||||||
|
></Thingtime>
|
||||||
|
</Box>
|
||||||
)}
|
)}
|
||||||
<Thingtime
|
<Thingtime
|
||||||
edit={inEditMode}
|
edit={inEditMode}
|
||||||
|
@ -30,6 +30,9 @@
|
|||||||
"react-contenteditable": "^3.3.7",
|
"react-contenteditable": "^3.3.7",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^4.10.1",
|
"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",
|
"tinygradient": "^1.1.5",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
|
@ -74,6 +74,15 @@ dependencies:
|
|||||||
react-icons:
|
react-icons:
|
||||||
specifier: ^4.10.1
|
specifier: ^4.10.1
|
||||||
version: 4.10.1(react@18.2.0)
|
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:
|
tinygradient:
|
||||||
specifier: ^1.1.5
|
specifier: ^1.1.5
|
||||||
version: 1.1.5
|
version: 1.1.5
|
||||||
@ -8301,6 +8310,10 @@ packages:
|
|||||||
through2: 2.0.5
|
through2: 2.0.5
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/performance-now@2.1.0:
|
||||||
|
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/periscopic@3.1.0:
|
/periscopic@3.1.0:
|
||||||
resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
|
resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -8587,6 +8600,12 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/raf@3.4.1:
|
||||||
|
resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==}
|
||||||
|
dependencies:
|
||||||
|
performance-now: 2.1.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/randombytes@2.1.0:
|
/randombytes@2.1.0:
|
||||||
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -8746,6 +8765,28 @@ packages:
|
|||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: false
|
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):
|
/react-style-singleton@2.2.1(@types/react@17.0.62)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==}
|
resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -8763,6 +8804,17 @@ packages:
|
|||||||
tslib: 2.5.0
|
tslib: 2.5.0
|
||||||
dev: false
|
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:
|
/react@18.2.0:
|
||||||
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
|
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
Loading…
Reference in New Issue
Block a user