All files / src/editor KeyName.tsx

0% Statements 0/23
0% Branches 0/8
0% Functions 0/5
0% Lines 0/23

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} />;
};