zudo-panel-designer docs
GitHub リポジトリ

検索したい単語を入力

いつでも検索バーを開ける

クリップボード

コピー/カット/複製/すべて選択と、バージョン付き OS クリップボードエンベロープ、そしてペースト専用の ⌘V セマンティクス。

use-clipboard.ts は、コピー・カット・複製・すべて選択をコマンドレジストリのコマンドとして配線し、加えて、ブラウザネイティブの paste イベントを最初から最後まで所有する、独立したペースト経路を持ちます。

コピー・カット・複製・すべて選択

ショートカット操作効果
⌘/Ctrl+Cコピー現在の選択を内部クリップボードにスナップショットし、ベストエフォートで OS クリップボードへも書き込む。
⌘/Ctrl+Xカットコピーしてから選択を削除する——1 つ の undo エントリとして。
⌘/Ctrl+D複製選択を新しい id で複製し、少しオフセットして選択する——1 つの undo エントリ。
⌘/Ctrl+Aすべて選択パターン以外のすべてのレイヤーを選択する。

コピー・カット・複製は 現在の選択 にそのまま働きます——選択された pattern レイヤー(その移動可能な xysize の正方形。ツール → 選択ツール → パターンの正方形を参照)は、ほかのどのレイヤー型とも同じようにコピー・カット・複製できます。そのため、この 3 つが何もしないのは、現在 何も 選択されていないときだけです。すべて選択だけが意図的な例外です——これは今もパターンレイヤーを除外します。背景のようなカバー正方形が ⌘/Ctrl+A のたびに加わってしまうと、「すべてを選択して移動する」が背景も一緒に引きずってしまうためです。そのため、パターンが選択に加わるのは、直接クリックする(二段階のヒットテスト)か、レイヤーリストからのときだけです。すべて選択は現在の選択をまったく参照しません——ドキュメント内のパターン以外のレイヤーを常にすべて選択します。そのため、何もしないのはドキュメントにパターン以外のレイヤーが 1 つもないときだけです。

これらのチョードはいずれも shift: false として登録されています——⌘⇧C は決してコピーしません。これはリファクタ前の挙動と完全に一致しています。

クローンがどこに置かれるか

ペーストと複製は、どちらも 1 つのクローン手法(@zpd/corecloneNodeWithFreshIds)を共有します。選択された通常サブツリー全体の新しい id と、全 leaf に適用される 2mm のカスケードオフセット により、 繰り返しても元の真上には重なりません。v3 のマテリアルタグが元のコンテナを 保持し、クローンはそのマテリアル内の上端に追加されて新しい選択になります。 固定 PCB ルート自体はコピーされません。

OS クリップボードのエンベロープ

コピーとカットは、navigator.clipboard.writeText を通じて、バージョン付きの JSON エンベロープを実際の OS クリップボードへ書き込みます。

interface ZpdClipboardEnvelope {
  app: 'zpd';
  kind: 'layers';
  version: 3;
  layers: Array<{
    material: 'copper' | 'solder-mask' | 'silkscreen';
    node: LayerNode;
  }>;
}

これが zpd のタブをまたいだ コピー&ペーストを可能にしています——あるタブでコピーし、別のタブに切り替えて、ペーストする。エンベロープの書き込みはベストエフォートです。navigator.clipboard.writeText は拒否されることもあれば、API そのものが存在しないこともあります(例: 非セキュアなコンテキスト)。どちらの場合も、サイレントに内部クリップボードのみへ縮退します——コピー・カット・複製・すべて選択が、クリップボードの権限問題だけで完全に失敗することはありません。

ペースト時には、OS クリップボードの text/plain ペイロードをエンベロープの マーカーに対して確認し、各通常ノードを core の防御的な fragment parser で 再検証します。v3 は最大の各選択ルート(leaf または group)と所有マテリアル を保持します。旧 v1 のフラット leaf と v2 の通常ツリーも受け付け、固定 マテリアルスタックへ決定的に分割します。それ以外——URL、文章、無関係な JSON、将来バージョン——は 完全にそのまま 残され、通常のテキスト ペーストを横取りしません。

ペースト

⌘/Ctrl+V は意図的に、keydown で処理されるショートカットでは ありませんuse-clipboard.tshandlePaste を一切公開していないため、キーボードハンドラが V のケースを配線できる先はどこにもありません——エディタのコマンドレジストリには edit-paste エントリが純粋に displayOnly として存在するだけです(ショートカット一覧が "⌘V — Paste" を表示できるように)。その run() は決して呼び出されません。実際のジェスチャーはブラウザのネイティブな paste イベントに乗ります。use-clipboard.ts は 1 つの window リスナーを通じてこれを所有し、次の優先順位でチェックします。

  1. OS クリップボード上の画像/SVG ファイル — 画像ビューアや別のアプリからコピーされたものなど。画像を追加… とドラッグ&ドロップインポートが使うのと同じ共有分類器を通り、ラスタ内容はデザイン用 image、実体が SVG ならベクター/マテリアルのインポートダイアログへ進みます。名前も MIME タイプもない匿名ファイルは、その判定前に内容 sniffing されます。

  2. OS クリップボード上のテキスト — zpd エンベロープとして解析されます。有効なエンベロープは、そのレイヤー群をペーストします(新しい id、カスケードオフセット、選択状態)。エンベロープでないテキストは、下記の内部クリップボードへのフォールバックも含めて 完全にそのまま残されます——OS クリップボードの現在の内容は、常に古い内部コピーより優先されます。唯一の例外は、直前のコピー/カットによる このセッション自身の writeText がまだ解決していない場合です(素早いコピー→ペーストは、非同期の書き込みより先に読み取ってしまうことがあります)。読み取られたテキストは単にその書き込みより古いだけかもしれないため、その場合は黙って何もしないのではなく、内部スナップショットへフォールバックします。

  3. 同一セッションの内部クリップボード — 最後の手段で、OS クリップボードに画像もテキストも一切ないとき(例えばコピー時に writeText が拒否されていた場合)に使われます。

<input><textarea><select>、または contenteditable 要素にフォーカスがある間、ペーストは無視されます。編集可能なフィールドへの通常のテキストペーストが横取りされることはありません。