💬

LexicalでIMEの有効状態を取得する方法

2024/11/25に公開

Lexical で IME の有効状態を取得する方法

本記事では、Lexicalを使用してIMEの有効状態を取得する方法を解説します。

結論

editor.isComposing()true であればIMEが有効。
※後述しますが、内部的には editor._compositionKeynull 以外であるかを判定基準としているようです。

実装方法

editor.registerUpdateListener を使用して状態の変化を監視し、リスナー内で editor.isComposing() を呼ぶことでIMEの有効状態を判定できます。

サンプルコード

import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import type { FC } from 'react'
import { useEffect } from 'react'

export const ImePlugin: FC = () => {
  const [editor] = useLexicalComposerContext()

  useEffect(() => {
    // IMEの有効状態を監視してログに出力
    return editor.registerUpdateListener(() => {
      console.log('isComposing:', editor.isComposing()) // 有効であればtrue
      console.log('composition key:', editor._compositionKey) // null | string
    })
  }, [editor])

  return null
}

余談ですが以下のように LexicalEditorRefPlugin を併用することで、エディタ外部から参照できます。

import {
  InitialConfigType,
  LexicalComposer,
} from '@lexical/react/LexicalComposer'
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
import { EditorRefPlugin } from '@lexical/react/LexicalEditorRefPlugin'
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
import { LexicalEditor } from 'lexical'
import type { FC } from 'react'
import { useEffect, useRef } from 'react'

export const Editor: FC = () => {
  const initialConfig: InitialConfigType = {
    namespace: 'sample',
    onError: console.error,
  }

  const editorRef = useRef<LexicalEditor>(null)

  useEffect(() => {
    return editorRef.current?.registerUpdateListener(() => {
      console.log('isComposing: ', editorRef.current?.isComposing()) // 有効であればtrue
      console.log('composition key:', editor._compositionKey) // null | string
    })
  }, [editorRef.current])

  return (
    <LexicalComposer initialConfig={initialConfig}>
      <RichTextPlugin
        contentEditable={<ContentEditable />}
        ErrorBoundary={LexicalErrorBoundary}
      />
      <EditorRefPlugin editorRef={editorRef} />
    </LexicalComposer>
  )
}

実行結果

実際にエディタを起動し、テキストを入力すると以下のようなログが出力されます。

IME が無効なとき(通常の文字入力モード)

isComposing: false
composition key: null

IME が有効な状態(日本語入力などで変換候補を選択中)

isComposing: true
composition key: 7

補足

_compositionKey の値について

isComposing()editor._compositionKey !== null かどうかを判断しています。

editor._compositionKeyの値はそれぞれ

  • null
    • IMEが無効な状態(通常の文字入力モード)
  • null以外の文字列
    • IMEが有効な状態(日本語入力などで変換候補を選択中)

となります。

内部実装を見てみると、変換開始時のanchorに位置するNodeのKeyをセットしているようです。
https://github.com/facebook/lexical/blob/main/packages/lexical/src/LexicalEvents.ts#L900-L910

参考

https://lexical.dev/docs/api/classes/lexical.LexicalEditor#iscomposing

https://lexical.dev/docs/concepts/selection

Aprender Tech Blog

Discussion