Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | import { useRef, useState } from 'react'; import { type SectionElementProps } from '../store/Section'; import { useStore } from './store'; import { type SectionElementResult } from '../store/Section'; export const KeyNameRender: SectionElementProps['render'] = ( { children, ...reset }, { value, parentValue, keyName }, ) => { if (typeof children === 'number') { return <span {...reset}>{children}</span>; } return ( <Child {...reset} value={value} parentValue={parentValue} keyName={keyName}> {children} </Child> ); }; interface ChildProps<T extends object> extends React.HTMLAttributes<HTMLSpanElement>, SectionElementResult<T> {} const Child = <T extends object>(props: ChildProps<T>) => { const { value, parentValue, keyName, ...reset } = props; const $dom = useRef<HTMLElement>(null); const [currentValue, setCurrentValue] = useState(props.children); const { onEdit } = useStore(); const onKeyDown = (evn: React.KeyboardEvent<HTMLSpanElement>) => { if (evn.key === 'Enter') { $dom.current?.setAttribute('contentEditable', 'false'); } }; const onClick = (evn: React.MouseEvent<HTMLSpanElement, MouseEvent>) => { evn.stopPropagation(); $dom.current?.setAttribute('contentEditable', 'true'); $dom.current?.focus(); }; const onBlur = (evn: React.FocusEvent<HTMLSpanElement, Element>) => { $dom.current?.setAttribute('contentEditable', 'false'); const callback = onEdit && onEdit({ value: evn.target.textContent, oldValue: value, keyName }); if (callback) { setCurrentValue(evn.target.textContent); } }; const spanProps: React.HTMLAttributes<HTMLSpanElement> = { ...reset, onKeyDown, onClick, onBlur, spellCheck: false, contentEditable: 'false', suppressContentEditableWarning: true, children: currentValue, }; return <span {...spanProps} ref={$dom} />; }; |