# Bone Flow #120 Trigger

## Overview
#120 Trigger は「何が起きたら Motion を開始するか」を決める Motion UI Component です。State は現在状態、Transition は状態遷移、Timeline は時間順序、KeyFrame は途中値を担当し、Trigger はそれらの責務を持ちません。

## Trigger責務
入力となるイベントを検出し、条件が成立した時だけ callback を1回発火して Motion Start を通知します。Trigger 自体は Motion の時間・補間・状態値を変更しません。

## 10 Trigger一覧
- Mouse Enter: `mouse-enter`。対象領域へ入る。
- Mouse Leave: `mouse-leave`。対象領域から出る。
- Click: `click`。1回クリック。
- Double Click: `double-click`。ダブルクリック。
- Focus: `focus`。INPUT等へFocus。
- Blur: `blur`。Focusを外す。
- Change: `change`。SELECT/INPUT値を変更。
- Parent Event: `parent-event`。親要素へ正式CustomEventを発行。
- Runtime Event: `runtime-event`。`BoneTrigger.emitRuntimeEvent()` を使用。
- Command: `command`。`BoneTrigger.executeCommand()` を使用。

## 操作方法
テストページの4列表で、Triggerごとの実際の操作場所を操作します。成功判定はテスト用ボタンの押下ではなく、BoneTrigger callbackの到達、Last Trigger更新、Motion Start=`START`で確認します。

## Property
### type
- 目的: 10種類のどのTriggerを監視するか指定します。
- 型: string
- 許容値: 上記10種類のみ。
- 無効値: `TRIGGER_TYPE_INVALID`。
- HTML: `data-trigger="click"`。

### enabled
- 目的: Triggerを一時的に有効/無効にします。
- Runtime Default: `true`
- 型: boolean
- `false`時: イベントを受けてもcallbackを発火しません。
- HTML: `data-enabled="false"`。

### eventName
- Runtime Event専用。
- `runtime-event`では空文字不可。
- HTML: `data-event-name="order.updated"`。

### commandId
- Command専用。
- `command`では空文字不可。
- HTML: `data-command-id="save"`。

### signalType
- 論理イベントの型制約。payload側 `signalType` と不一致ならcallbackを発火しません。

## Preview
PropertyのTrigger Type / Enabledを変更し「Previewへ適用」を押すと、Preview Sourceへ正式BoneTrigger instanceを付け直します。Last Trigger / Motion Start / Countはcallback到達時に更新されます。

## 接続イメージ
Connection Imageは #002 Bone Joint v1.1.36 の描画APIを使用します。ページ側で独自SVG path、独自marker、独自spinner、独自ban iconを描きません。通常線は `BoneJoint.drawLine()`、異常表示は `BoneJoint.drawError()` / `BoneJoint.drawCompatibilityMarker()` を使用します。

## Security
payloadはデータとしてcallbackへ渡します。文字列を `eval`、`Function`、`innerHTML` として実行しません。Untrusted INテストでは `<img ... onerror=...>` を文字列のままRuntime Eventへ投入し、DOMへ実行可能HTMLとして生成されないことを確認します。

## OUT WAIT / FIFO / BLOCKED — #002正式Delivery Channel
#017正式画面と同じ表示順を使用します。見出し、説明文、1本のSource→Targetステージ、Joint State / Target / Queue / Deliveredの4状態、3ボタン、Target受信ログ、2つの目視確認をこの順に表示します。独自の2カラム表示、右側ログ枠、Target状態select、payload select、独立FIFOボタンは置きません。

WAIT / FIFO: 「WAIT / FIFO 実行」1回で、Target BUSYの実 #002 Delivery Channelへ実際の #120 Click Trigger callbackを2件投入し、Queue=2 / WAITING を画面に3秒間表示します。その後、同じ操作内で #002 Delivery Channel の `setTargetReady(true)` を呼び、#002 が `Trigger #1 → Trigger #2` の順にFIFO自動flushしてREADYへ戻ります。3秒は #002 の正式「Target Busy 3秒 目視テスト」と同じ目視確認時間です。独立したTarget READYボタン、FIFOボタン、Target状態selector、Payload selectorは追加しません。

BLOCKED: 「BLOCKED 実行」で実際の #120 Click Trigger callbackを #002 guardへ渡し、接続を維持したままTarget配送を停止します。正式BLOCKED markerは前面overlayに表示します。「Reset」でREADYへ戻します。

## Smoke / Validation
SmokeはRuntime identity、10 Trigger実callback、Functional Class mount、#002 Relation、WAIT/FIFO/BLOCKEDを検査します。Validationは無効type、enabled=false、signal type mismatch、DOM Trigger spoof防止、detach/reattach/destroy、Untrusted payload、#002正式API、Guide/Functional Classを検査します。

## Completion
Completeボタンは **Smoke / Validation 全件成功 + 9項目の必須目視確認** が揃った場合だけ有効になります。

必須目視確認:
1. 10 Trigger 実操作
2. Property
3. Preview
4. 接続イメージ（#002）
5. Security
6. OUT WAIT / FIFO / BLOCKED（#002正式Delivery Channel）
7. Guide / 日本語・英語
8. Smoke Test
9. Validation

Complete→Release Ready、Reopen→Developmentを実DOMで確認できます。目視チェックはテスト結果の代用品ではありません。ユーザーlocalhost確認前にPackage自体をCompleted / Specification Frozenとは扱いません。

## HTML Functional Class {#bone-doc-section-html-functional-class}
一般利用Classは `bf-trigger` 1件です。`bf-trigger` はTriggerのイベント接続だけを担当し、Target UIの外観・Transition・State・Timelineを所有しません。

### 読み込み順
```html
<script src="/boneflow/js/bone-trigger.js"></script>
<script src="/boneflow/js/bone-trigger-functional-class.js"></script>
```
Functional Class bridgeはDOM読込後に `.bf-trigger` をscanし、後から追加された要素もMutationObserverでmountします。

### 属性
- `class="bf-trigger"`: 必須。正式HTML Functional Class。
- `data-trigger`: 必須。10種類のRuntime type。
- `data-enabled`: 任意。`true` / `false`。省略時true。
- `data-event-name`: Runtime Eventで指定。
- `data-command-id`: Commandで指定。
- `data-signal-type`: 任意。論理payloadの型制約。

### 10 TriggerのHTML対応
`data-trigger` は `mouse-enter`, `mouse-leave`, `click`, `double-click`, `focus`, `blur`, `change`, `parent-event`, `runtime-event`, `command` の10値です。Runtime Eventは `data-event-name`、Commandは `data-command-id` を追加します。

### 最小HTML
```html
<button class="bf-trigger" data-trigger="click">Run</button>
```
DOM scanで自動mountされ、click到達時に要素へ `bone-trigger:fire` CustomEventを発行します。

### Parent Event
```html
<div id="parent">
  <button class="bf-trigger" data-trigger="parent-event">Child</button>
</div>
<script>
const child = document.querySelector('.bf-trigger[data-trigger="parent-event"]');
const instance = BoneTriggerHTMLClass.getInstance(child);
BoneTrigger.dispatchParentEvent(child.parentElement, { source: 'parent' });
</script>
```
Parent Eventは実CustomEventで親要素から発生させます。

### Runtime Event
```html
<div class="bf-trigger"
     data-trigger="runtime-event"
     data-event-name="order.updated"></div>
<script>
BoneTrigger.emitRuntimeEvent('order.updated', { id: 10 });
</script>
```

### Command
```html
<div class="bf-trigger"
     data-trigger="command"
     data-command-id="save"></div>
<script>
BoneTrigger.executeCommand('save', { source: 'toolbar' });
</script>
```

### callback到達の受け取り
HTML Functional Class利用時はanchor自身から `bone-trigger:fire` が発行されます。
```html
<script>
document.querySelector('.bf-trigger').addEventListener('bone-trigger:fire', (event) => {
  console.log(event.detail.type, event.detail.motionStart); // motionStart = START
});
</script>
```

### 状態確認
mount後のanchorには以下を設定します。
- `data-bf-trigger-mounted="true"`
- `data-bf-trigger-runtime="1.0.0"`
- `data-bf-trigger-functional-class="1.0.4"`
- callback後: `data-bf-trigger-last`, `data-bf-trigger-motion`, `data-bf-trigger-count`

`BoneTriggerHTMLClass.getInstance(element)` でRuntime instanceを取得できます。

## Public API
Public Object: `BoneTrigger`。Class constructorは公開しません。Factory方式です。

### `create(options)`
いつ使うか: Trigger instanceを生成する時。`type`と`callback`が必須です。生成だけではDOM監視を開始しません。

### `attach(instance, target?)`
いつ使うか: 生成したTriggerを実Event sourceへ接続する時。DOM TriggerはtargetへaddEventListenerし、Runtime Event / Commandは内部正式channelへ登録します。

### `detach(instance)`
いつ使うか: instanceを破棄せず監視だけ停止する時。再attach可能です。

### `destroy(instance)`
いつ使うか: Triggerを完全終了する時。detach後にinstanceを無効化します。

### `setEnabled(instance, enabled)`
いつ使うか: 接続を維持したまま発火だけ停止/再開する時。

### `getState(instance)`
いつ使うか: type / enabled / attached / fireCount / lastTrigger等を監査する時。

### `emitRuntimeEvent(eventName, payload)`
いつ使うか: Runtime Eventを正式に発行する時。同名eventNameに登録されたTriggerだけを発火します。

### `dispatchParentEvent(parent, payload)`
いつ使うか: 親要素にParent Eventを実際のCustomEventとして発生させる時。

### `executeCommand(commandId, payload)`
いつ使うか: Command Triggerを実行する時。同じcommandIdのTriggerだけを発火します。

### `list()`
いつ使うか: 現在生存しているTrigger instanceの状態一覧を監査する時。

### `isInstance(value)`
いつ使うか: 値が現在のBoneTrigger instanceか確認する時。

### `validateOptions(options)`
いつ使うか: create前にtype/callback/eventName/commandIdの基本契約を検証する時。例外を投げず `{valid, code}` を返します。
