MimoProvider

Fluxlay SDK に同梱されている合成入力フォワーダ Mimo で壁紙ツリーを包み、OS カーソルが壁紙ウィンドウに入っていなくても通常の React の DOM イベント(onClick, onPointerDown, onKeyDown, ドラッグ&ドロップライブラリ、フォーカスリング等)が発火するようにします。

Mimo がそもそも何で、なぜ壁紙に必要かは Mimo: 壁紙内のインタラクティブ UI を参照してください。

インポート

MimoProvider はメインエントリと別の subpath に置かれており、Mimo の依存ツリーがメインエントリに混ざらないようになっています。

import { MimoProvider } from "@fluxlay/react/mimo";

クイックスタート

壁紙のルートに置くだけで、OS の pointer / keyboard イベントが自動的にフォワーダへ流れます。

import { MimoProvider } from "@fluxlay/react/mimo";
 
export function Root() {
  return (
    <MimoProvider cursor>
      <App />
    </MimoProvider>
  );
}

これで <App /> 内では普通の React ハンドラ(<button onClick={...}>、dnd-kit、Framer Motion drag、useIsFocused を使った <input> のフォーカスリング等)がそのまま使えます。cursor prop は合成 pointer に追従する仮想カーソル div を表示します。壁紙ウィンドウには OS カーソルが描画されないため、ユーザがどこを指しているかを示すのに便利です。

IME(日本語・中国語・韓国語などの変換入力)も自動でハンドリングされます。<input> / <textarea> にフォーカスすると IME プロキシが有効化され、確定文字列がフィールドに書き込まれます。直接制御したい場合のみ useImeInput を参照してください。

シグネチャ

function MimoProvider(props: MimoProviderProps): ReactNode;
 
interface MimoProviderProps extends Omit<MimoForwarderOptions, "pointerSource" | "keyboardSource"> {
  pointer?: boolean;
  keyboard?: boolean;
  children?: ReactNode;
}

pointerSource / keyboardSource は意図的に省かれています。MimoProvider は input source の所有権を持ち、Fluxlay の OS フック(useMousePosition, useMouseEvents, useKeyboard)と接続するためです。独自 source を差し込みたい場合(テスト、リプレイ、Fluxlay デスクトップアプリ外での実行)は後述の MimoForwarderProvider を使ってください。

Props

Prop既定値説明
pointerbooleantruefalse にすると OS pointer イベントをフォワーダへ injection しません。一時的にカーソルを切り離したいデモトグルやモーダル時に有用です。
keyboardbooleantruefalse にすると OS keyboard イベントを injection しません。
cursorboolean | CursorOptionsfalse合成 pointer に追従する仮想カーソル要素を描画します。壁紙ウィンドウ内に OS カーソルは表示されないため有用。
autoFocusbooleantruepointerdown 時に最も近い focusable な祖先にフォーカスを移します。実ブラウザの挙動の再現。
doubleClickThresholdMsnumber500ダブルクリックとして扱う最大間隔(ms)。
clickMoveThresholdPxnumber5この距離以上カーソルが動いた up は drag と見なし、click を抑制します。
keyboardTargetKeyboardTargetStrategy"active-element"キーボードイベントの dispatch 先。"active-element"(既定 — useIsFocused<input> フォーカスと連携)/ "pointer-target""document" から選択。
pointerCapturebooleantrueElement.prototype.{set,release,has}PointerCapture をプロセスワイドにパッチして capture をフォワーダ経由にします。dnd-kit, react-dnd Pointer backend, Framer Motion drag に必要。
childrenReactNode壁紙のツリー。

useMimoForwarder

直近の provider が所有する MimoForwarder インスタンスを返します。provider の外で使うと例外を投げます。injectPointer / injectKeyboard のような命令的 API をテストやリプレイから呼びたい場合に便利です。

import { useMimoForwarder } from "@fluxlay/react/mimo";
 
function ReplayButton() {
  const forwarder = useMimoForwarder();
  return (
    <button
      onClick={() => {
        forwarder.injectPointer({ kind: "move", x: 100, y: 100 });
        forwarder.injectPointer({ kind: "button", x: 100, y: 100, button: "left", pressed: true });
        forwarder.injectPointer({ kind: "button", x: 100, y: 100, button: "left", pressed: false });
      }}
    >
      クリックを再生
    </button>
  );
}

provider の外でも null を許容したい場合は MimoForwarderContext を直接購読できます。

カスタム入力 source: MimoForwarderProvider

MimoProvider は常に Fluxlay の OS フックをフォワーダに送り込みます。独自の pointerSource / keyboardSource を差し込みたい場合(合成ストリームでのユニットテスト、録画したセッションのリプレイ、Fluxlay デスクトップアプリ外での組み込み等)は、低レベルの MimoForwarderProvider を使います。

import { MimoForwarderProvider, type PointerSource, type KeyboardSource } from "@fluxlay/react/mimo";
 
const pointerSource: PointerSource = handler => {
  const ws = new WebSocket("ws://localhost:9999/pointer");
  ws.onmessage = ev => handler(JSON.parse(ev.data));
  return () => ws.close();
};
 
const keyboardSource: KeyboardSource = handler => {
  // ...
  return () => {};
};
 
export function ReplayRoot() {
  return (
    <MimoForwarderProvider pointerSource={pointerSource} keyboardSource={keyboardSource}>
      <App />
    </MimoForwarderProvider>
  );
}

MimoForwarderProviderMimoForwarderOptions の全 prop(MimoProvider の prop に加えて pointerSource / keyboardSource)を受け付けます。PointerSource は handler を受け取って unsubscribe を返す関数で、座標は対象 document の viewport に対する CSS px です。KeyboardSource も同じ形をしています。

エクスポートされている型

@fluxlay/react/mimo から以下がエクスポートされています。

  • MimoForwarder, MimoForwarderContext, useMimoForwarder
  • MimoForwarderProvider, MimoForwarderProviderProps
  • MimoForwarderOptions, CursorOptions, KeyboardTargetStrategy
  • PointerSource, PointerSourceEvent, PointerSourceMoveEvent, PointerSourceButtonEvent, PointerSourceWheelEvent, PointerSourceCancelEvent, PointerButton, PointerType
  • KeyboardSource, KeyboardSourceEvent, KeyboardModifiers
  • Unsubscribe

備考

  • MimoProvider は壁紙ウィンドウあたり 1 つの forwarder をマウントします。複数マウント自体は許容されています(最後に start したものが capture を取る)が一般的ではありません。
  • 合成イベントを使用するため、ブラウザの isTrusted ゲートに引っかかる挙動(HTML5 のネイティブ drag-and-drop、<input> / <textarea> への生テキスト入力、OS のコンテキストメニュー、autoplay 解除等)は trigger できません。多くは Fluxlay 側で代替が用意されています。IME 合成は useImeInput が、OS カーソル不在のフォーカスリングは useIsFocused と仮想カーソルがそれぞれカバーします。