add-pen-input について
Power Apps モバイルプロジェクトで、ネイティブペン入力用ラッパーを追加・確認する内部スキルです。React Native API で手書きや署名を PNG データ URI として取得し、Dataverse への任意保存方法も案内します。
主な機能
- 01手書きと署名のキャプチャ
- 02PNG データ URI の出力
- 03データ URI プレフィックスの除去
- 04キャンセルを通常結果として処理
- 05Dataverse Image または File への保存対応
活用シーン
- 01モバイル画面で署名を取得
- 02手書きの証拠を収集
- 03取得した PNG 画像を表示
- 04署名データを Dataverse に保存
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill add-pen-inputインストール後、Claude Code で/add-pen-inputを入力して読み込まれたか確認します。
詳細
📋 共有指示:shared-instructions.md — 最初に読んでください。
作業ディレクトリ: プロジェクトのファイルを読み込んだり、コマンドを実行したりする前に、
native-artifact-compatibility.md Step 0 を実行してください。
/add-native で解決された絶対パスの working_dir を引き継ぎ、別のディレクトリからこのヘルパーが起動された場合も含め、すべてのシェル呼び出しとファイルツールをそのディレクトリに紐付けてください。
ペン入力の追加
内部ヘルパーです。 ユーザーは /add-native pen-input、/add-native signature、または /add-native @microsoft/power-apps-native-pen-input を呼び出してください。/add-native は機能を解決した後、ここに処理を引き継ぎます。
ネイティブのペン入力ラッパーを生成または検証し、その ネイティブ React Native API の呼び出し方法を示します。パッケージ README に記載された HostingSDK / PCF の方法は使用しないでください。これは別の用途向けです。
手順
1. アプリを検証する
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
test -f app.config.js && test -f power.config.json && test -f package.json && test -d src || { echo "BLOCKED: working_dir is not an initialized app" >&2; exit 1; }
失敗した場合は、先に /create-mobile-app を実行するようユーザーに伝え、そこで STOP してください。
2. パッケージがすでに存在することを確認する
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node -e "const p=require('./package.json'); const m='@microsoft/power-apps-native-pen-input'; if (!p.dependencies?.[m]) { console.error('MISSING: ' + m + ' is not in package.json. The template/app must already ship this native extension. This skill will not install it or edit native config.'); process.exit(1); } console.log('OK: pen input package present');"
確認に失敗した場合は STOP してください。npm install、npx expo install、pod install を実行したり、app.config.js を編集したりしないでください。このパッケージにはネイティブの iOS/Android コードが含まれているため、アプリのネイティブビルドにすでに含まれている必要があります。
2a. 要求された成果物を照合する
書き込みや再利用の前に、native-artifact-compatibility.md のステップ 1~3 をペン入力の項目に対して読み、実行してください。
/add-native で決定された現在の承認/モードを引き継いでください。有効なスコープ付き承認を繰り返し確認する必要はありません。
src/native/penInput.ts の captureSignature、stripDataUriPrefix、PenInputResult、要求されたオプション、PNG データ URI の出力、およびエラーではない USER_CANCELLED を確認してください。キャプチャだけでなく、承認済みの Image/File ペイロード要件も確認してください。不足しているノーマライザーや、必要な生成済みサービスのシグネチャが不明な場合は、無視できません。必要なストレージが不足している場合、または承認範囲外の互換性のない成果物がある場合は、NEEDS_CONTEXT をオーナーに返すか、単独で実行している場合はユーザーに確認してください。
3. src/native/penInput.ts を作成または検証する
src/native/penInput.ts について、手順 2a の判断に従ってください。要求されていてファイルがない場合は作成し、互換性がある場合にのみ変更せず再利用するか、承認されたスコープ内の更新だけを行ってください。カスタムコード、エクスポート、呼び出し元を維持し、例を使って上書きしないでください。
ラッパーは必ず次を満たす必要があります。
- 判別可能なユニオン型を返し、例外をスローしないこと。
- ユーザーがキャンセルした場合、
{ ok: false, reason: 'USER_CANCELLED' }を返すこと。これはエラーではない経路です。 - 拡張機能が JavaScript にインストールされているものの、ネイティブビルドで利用できない場合は
NATIVE_MODULE_MISSINGを返すこと。 - 成功時に PNG データ URI(
data:image/png;base64,...)を返すこと。
// src/native/penInput.ts
import {
PenInputNative,
PenInputStatus,
PenInputErrorCode,
} from '@microsoft/power-apps-native-pen-input';
export type PenInputResult =
| { ok: true; dataUri: string }
| { ok: false; reason: 'USER_CANCELLED' | 'NATIVE_MODULE_MISSING' | 'CAPTURE_FAILED'; message?: string };
export async function captureSignature(options?: {
backgroundColor?: string;
strokeColor?: string;
strokeWidth?: number;
}): Promise<PenInputResult> {
if (!PenInputNative?.capturePenInput) {
return { ok: false, reason: 'NATIVE_MODULE_MISSING', message: 'Pen input module is not available in this build.' };
}
try {
const result = await PenInputNative.capturePenInput({
backgroundColor: '#ffffff',
strokeColor: '#0078d4',
strokeWidth: 2,
...options,
});
if (result.status === PenInputStatus.Ok && result.result) {
return { ok: true, dataUri: result.result };
}
if (result.error === PenInputErrorCode.UserCancelled) {
return { ok: false, reason: 'USER_CANCELLED' };
}
return { ok: false, reason: 'CAPTURE_FAILED', message: result.error };
} catch (error: any) {
return { ok: false, reason: 'CAPTURE_FAILED', message: error?.message ?? String(error) };
}
}
export function stripDataUriPrefix(dataUri: string): string {
return dataUri.replace(/^data:image\/png;base64,/, '');
}
4. ラッパーを使用する
オーナー向けの統合ガイダンスです。このヘルパーでは画面を編集しないでください。
画面ではネイティブパッケージを直接ではなく、ラッパーをインポートします。
import { captureSignature } from '@/native/penInput';
const result = await captureSignature({
backgroundColor: "#ffffff",
strokeColor: "#0078d4",
strokeWidth: 2,
});
if (result.ok) {
setSignatureUri(result.dataUri);
} else if (result.reason === 'USER_CANCELLED') {
// User cancelled; do not show this as an app error.
} else {
console.warn("Failed to capture pen input:", result.reason, result.message);
}
キャプチャした PNG は、通常の React Native 画像として表示します。
{signatureUri ? (
<Image
source={{ uri: signatureUri }}
style={{ width: "100%", height: 160 }}
resizeMode="contain"
/>
) : null}
注:
- 結果は PNG データ URI です:
data:image/png;base64,...。 - 色の入力では
#RGBと#RRGGBBに対応しています。 - キャンセルは通常の操作であり、
USER_CANCELLEDを返します。画面では現在の状態を変更せず、失敗を示すバナーも表示しないでください。 @microsoft/power-apps-native-pen-inputは、ネイティブのフリーハンド描画、インク、手書き、署名のキャプチャにのみ使用してください。これ以外のネイティブ用途には、該当する Expo モジュールか、package.jsonにすでに含まれている別の依存関係を使用してください。
5. Dataverse への任意の保存
任意とは、依頼されていないことを意味し、保持が承認された場合に省略できるという意味ではありません。ステップ 2a では、ラッパーのペイロード対応と生成されたシグネチャを確認します。所有者は以下の画面側の保存/アップロード処理を実装します。ヘルパー側で必要なサポートが不足している場合や、必要なストレージが不明な場合は、キャプチャのみの成功として返さず、NEEDS_CONTEXT を返してください。
ユーザーがシグネチャを Dataverse の Image/File 列に保存したい場合は、生成されたサービスのみを使用してください。Dataverse Web API を直接呼び出してはいけません。
Image 列のパターン:データ URI を、生成されたサービスが想定する画像ペイロードに正規化します。生の base64 が必要な場合は、プレフィックスを削除してください。
import { stripDataUriPrefix } from '@/native/penInput';
const signatureBase64 = stripDataUriPrefix(result.dataUri);
const update = await Cr123_evidenceService.update(id, {
cr123_signatureimage: signatureBase64,
cr123_signedat: new Date().toISOString(),
});
if (!update.success) {
showError(update.error?.message ?? 'Signature was not saved.');
}
File 列のパターン:先に親行を保存または更新し、その後、生成されたサービスのヘルパーを通じて PNG バイト列/File をアップロードします。File 列のバイト列を作成/更新 JSON 本文に含めてはいけません。
6. 型チェック
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
npx --no-install tsc --noEmit
対象範囲内のヘルパーエラーのみを修正し、共有互換性コントラクトのステップ 4 を実行してください。ユーザーによるキャンセル、ネイティブモジュールの不足、キャプチャの失敗、Image と File のペイロードの違いを含め、依頼されたキャプチャ/正規化/保存の動作を再確認してください。型チェックの成功だけでは不十分です。画面/生成ファイルを修正してはいけません。
7. ネイティブ再ビルドに関する注意
このスキルはネイティブコードをインストールしません。スキル外でパッケージを追加したばかりの場合、このワークフロー外でアプリをネイティブ再ビルドする必要があります。パッケージがすでにビルドに含まれていた場合は、ラッパーの編集には Metro のホットリロードで十分です。
8. HostingSDK/PCF を使用しない
以下をインポートまたは登録しないでください。
import { PenInputExtension } from "@microsoft/power-apps-native-pen-input";
Companion PCF または PenInputExtension を組み込まないでください。Power Apps のネイティブコードアプリでは、上記のネイティブ React Native API を使用してください。
9. 要約
この要約の前に、共有互換性の結果と、実際に作成/更新/再利用したパスを返してください。所有者側の保存/統合については別途報告してください。成功した場合に限り memory-bank を更新し、オーケストレーションされている場合は、最終更新を所有者に委ねてください。
ユーザーに次のように伝えてください。
Pen input added
Package present : @microsoft/power-apps-native-pen-input
Wrapper : src/native/penInput.ts
Output : PNG data URI
Type-check : PASS
Native rebuild : not performed by this skill
Usage : captureSignature(...)
HostingSDK / PCF : not used
Controls の下にある memory-bank.md を更新してください。
- Pen input added — @microsoft/power-apps-native-pen-input (<ISO date>)