Open4

Notion×コードエディタを作る

BosonBoson

とりあえず、ドラッグドロップ形式のノートを完成させるために次のことを完成させる

  • ブロック形式で改行、削除が行えるようにする
  • ブロックをドラッグドロップできるようにする

ブロックは下のようにcontenteditableをcontenteditableで囲む。

<div id="blocks" contentEditable="true">
    <div className="block" contentEditable="true">{/* ここにテキスト */}</div>
    <div className="block" contentEditable="true">{/* ここにテキスト */}</div>
</div>

こうすることで自由にテキストを選択できるようになる。
contenteditableにする理由は、こうしないと文字の色を変えたりできないため。

BosonBoson

文字を削除する際に、一旦消してから消えたかどうか判定して反映する方法だとバグるため、backspaceを押された際に削除を反映する方法で行く。

BosonBoson

キャレットの位置復元方法

  1. キャレットの位置をuseStateに保存する
  2. 再レンダリングされるたびにキャレットの位置を元に戻す

useEffectのところが再レンダリングされるたびに動くところ。

  const [anchorSelection, setAnchorSelection] = useState<{
    id: string;
    offset: number;
  }>({ id: "", offset: 0 });

  useEffect(() => {
    if (document.getElementById(anchorSelection.id)) {
        let selection = window.getSelection();
        let anchorBlock: HTMLElement = document.getElementById(
          anchorSelection.id
        )!;
        let range: Range = document.createRange();
        range.setStart(anchorBlock.firstChild!, anchorSelection.offset);
        range.setEnd(anchorBlock.firstChild!, anchorSelection.offset);
        selection?.removeAllRanges();
        selection?.addRange(range);
    }
  });
BosonBoson

Notionを見て分かったが、一文字削除するだけならもともとある機能を使ってよさそう