# Bone Flow #054 Display Timeline 操作ガイド

## Display Timelineとは
#054 Display Timeline は、時間軸上に予定・勤務時間・休憩時間などを表示するUIです。時間軸、タイムバー、Shape Comment表示、表示色、親要素への吸着、週報・月報での表示を担当します。

#054は表示を担当します。#121 Timeline の Delay / Duration / Loop / Repeat / Sequence / Parallel は #054 の責務ではありません。

## いつ使用するか
- 勤務時間や予定を横方向の時間軸で見せたいとき
- 週報・月報で同じ時間軸UIを複数行に並べたいとき
- 短い予定をタイムバー、コメントをShape Commentで見せたいとき
- 同一時間帯のBarを重ね、#125 Blendで視認性を調整したいとき

## テストページの使い方
1. 「プロパティ設定」でTheme、開始・終了、目盛、Bar高さ、重なり、時間ラベル、親要素設定を変更します。
2. 各データで表示方式、開始、終了、ラベル、背景色、文字色、Blendを設定します。
3. 「反映」を押してDisplay Timeline Previewを確認します。
4. 「接続イメージ」で#002 Bone JointによるIN / OUT描画を確認します。
5. Smoke Test / Validation Reportで実装検査を実行します。
6. 実装方法は画面最下部の「HTML Functional Class ガイドを開く」から確認します。

## 表示例
- 勤務時間: 09:00〜18:00 / タイムバー
- 休憩時間: 12:00〜13:00 / タイムバー
- 打ち合わせ: 10:00〜10:30 / Shape Comment
- 飲み会: 19:00〜21:00 / タイムバー

## Theme
正式Themeは `light / dark / neon` の3種です。既定値は `light` です。Lightでは#054本体と週報・月報の表面を白背景にし、印刷時も白背景を維持します。

## タイムバー重なり表示
既定値は `barLayout: "overlap"` です。同一時間帯のBarを同じ行に重ねます。勤務時間 09:00〜18:00 の上に休憩時間 12:00〜13:00 を重ね、#125 Blend の効果を確認できます。

必要な場合だけ `barLayout: "stack"` を選択すると、重なるBarを自動で別行へ配置します。

## Shape Comment
Shape Commentも `start` / `end` の開始〜終了を保持します。別の単一点時刻プロパティは持ちません。

既定例は 10:00〜10:30 の「打ち合わせ」です。Anchorは開始時刻10:00へ接続し、コメント枠には開始〜終了を表示します。コメント枠はドラッグ移動でき、リーダー線が追従します。

## #040 ColorPicker
背景色 / 文字色 / 1日枠線色は、正式 `BoneColorPicker.attachCaller(...)` 方式で選択します。#054は#040内部DOMを所有しません。

## #125 Blend
各Barには `blendMode` を設定できます。正式8種は Normal / Multiply / Screen / Overlay / Darken / Lighten / Difference / Add です。

## 週報 / 月報
外側の縦並びは #048 Table の利用イメージ、各行の予定表示は #054 Display Timeline です。

`timeAxisMode` は `all / group-first / none` を持ちます。`group-first` では一番上だけ時間ラベルを表示するため、週報・月報で各行の軸高さが重複しません。

日間隔、1日枠線、枠線太さ、枠線色、角丸を設定できます。

## 親要素への吸着
`snapToParent=true` の場合、#054自身の外枠・角丸・padding・背景を消し、親要素へ直接FITします。

`parentHeight=0` は内容ぴったり、1以上は親要素高さ(px)を固定します。

## Barの幅調整
Barの左右端には見えないResize領域があります。縦線ハンドルを表示せず、左右端をドラッグして開始・終了を調整できます。

## ラベル / 時間表示
Barラベルは省略記号ではなく、狭い場合も複数行で全文表示します。時間はtooltip / 下部ステータスで確認します。

## 接続イメージ
テストページの接続線は正式 #002 Bone Joint Runtimeを使用します。独自Jointは作りません。

- 正常接続: IN / OUT
- 異常例: Target不存在

## Smoke Test / Validation Report
Smoke TestはRuntime、依存Component、表示・操作・#002 Joint実描画などを確認します。Validationは不正範囲、不正色、不正Theme、不正Blendなどの拒否を確認します。

未実行状態をALL PASSとして表示しません。

## Completion
テストページのCompletionはSmoke TestとValidationの両方がALL PASSのときだけ操作可能です。USER localhost確認前に正式Completed / Specification Frozenとは扱いません。

## HTML Functional Class
一般利用の正式Classは `bf-display-timeline` 1件です。

**タイムバーとShape Commentは別Classではありません。** `bf-display-timeline` 本体の `data-timeline-items` にJSON配列を設定し、各Itemの `displayType` を `bar` または `shapeComment` にします。

### `data-timeline-items` の基本形

```html
<div class="bf-display-timeline"
     data-timeline-items='[
       {"id":"work","label":"勤務時間","displayType":"bar","start":"09:00","end":"18:00"},
       {"id":"meeting","label":"打ち合わせ","displayType":"shapeComment","start":"10:00","end":"10:30"}
     ]'></div>
```

HTML属性全体は `'...'`、JSON内部は `"..."` を使用します。

### Timeline本体 Property — 値の意味まで含む一覧

| HTML属性 | JS Property | 型 / 許容値 | 既定値 | 説明 |
|---|---|---|---|---|
| `data-timeline-orientation` | `orientation` | `horizontal / vertical` | `horizontal` | Timeline方向。正式サンプルはhorizontal。 |
| `data-timeline-start` | `start` | `HH:mm` | `09:00` | Timeline開始。Item startはこれ以上。 |
| `data-timeline-end` | `end` | `HH:mm` | `18:00` | Timeline終了。開始より後、Item endはこれ以下。 |
| `data-timeline-step` | `step` | 5–240 | `60` | 目盛/Grid間隔(分)。 |
| `data-timeline-snap` | `snap` | 1–240 | `15` | Drag/Resize時の吸着単位(分)。 |
| `data-timeline-bar-height` | `barHeight` | 24–160 | `64` | 1行のBar高さ(px)。 |
| — | `rowGap` | 0–48 | `8` | stack時の行間(px)。HTML属性はなくJS専用。 |
| `data-timeline-bar-layout` | `barLayout` | `overlap / stack` | `overlap` | overlap=同じ行に重ねる、stack=重なるBarを自動別行。 |
| `data-timeline-axis-mode` | `timeAxisMode` | `all / group-first / none` | `all` | all=毎行、group-first=groupIndex 0だけ、none=時間軸ラベルなし。 |
| `data-timeline-group-index` | `groupIndex` | 0–9999 | `0` | group-first判定用。0だけ時間軸表示。 |
| `data-timeline-snap-parent` | `snapToParent` | Boolean | `false` | true=親へFITし#054外枠/padding等を消す、false=通常フレーム。 |
| `data-timeline-parent-height` | `parentHeight` | 0–2000 | `0` | 0=内容自動、1以上=親高さ(px)固定。snapToParentと組み合わせる。 |
| `data-timeline-grid` | `showGrid` | Boolean | `true` | true=Grid表示、false=Grid非表示。 |
| `data-timeline-labels` | `showLabels` | Boolean | `true` | **現Runtimeでは時間軸ラベル表示のゲート。** falseで時間軸を隠す。Bar内labelを消す設定ではない。 |
| `data-timeline-editable` | `editable` | Boolean | `true` | true=Bar Drag/Resize + Comment Drag可、false=それらの編集を停止。 |
| `data-timeline-theme` | `theme` | `light / dark / neon` | `light` | Theme。 |
| `aria-label` | `ariaLabel` | 文字列 | `Display Timeline` | Timelineのアクセシビリティ名。 |
| `data-timeline-items` | `items` | JSON配列 | `[]` | Bar / Shape Comment一覧。 |

BooleanはHTMLでは `true / false` を明示してください。Functional Classは `false / 0 / off / no` をfalseとして解釈し、それ以外の属性値をtrueとして扱います。

### `kind` は何を指定するか

`kind` はItemの用途分類です。Barでは標準アクセント色にも使います。

| 値 | 意味 / 用途 | 背景色未指定時のBar標準アクセント |
|---|---|---|
| `work` | 勤務・作業 | 淡い緑 |
| `break` | 休憩・中断 | 淡い青 |
| `meeting` | 会議・打合せ | 黄 |
| `info` | 一般予定・情報 | 黄橙 |
| `warning` | 注意・警告 | 淡い赤 |
| `neutral` | その他・未分類 | 灰 |

未指定時は `neutral`。`backgroundColor` を指定するとその色が優先されます。Shape Commentでは `kind` は分類値として保持され、現RuntimeのComment配色は `backgroundColor / textColor` で決まります。

### タイムバーのPropertyと最小例 — 各値の意味

Barは `displayType:"bar"` です。省略時のdisplayTypeも `bar` ですが、実使用では明示を推奨します。

| Property | 型 | 必須 / 既定 | 許容値 | 説明 |
|---|---|---|---|---|
| `id` | string | 任意 / `item-N` | 英数 `_.:-`、1–80文字、重複不可 | APIで特定するID。明示推奨。 |
| `label` | string | **必須** | 1–120文字 | Bar中央に表示する名称。 |
| `kind` | enum | 任意 / `neutral` | 上記6種 | 用途分類 + Bar標準色。 |
| `displayType` | enum | 任意 / `bar` | `bar / shapeComment` | `bar`でタイムバー。 |
| `start` | time | **必須** | Timeline範囲内 `HH:mm` | Bar開始。 |
| `end` | time | **必須** | startより後の `HH:mm` | Bar終了。 |
| `backgroundColor` | color | 任意 / 空 | `#RGB / #RRGGBB` | Bar背景。省略時kind/Theme色。 |
| `textColor` | color | 任意 / 空 | `#RGB / #RRGGBB` | 文字色。省略時Theme色。 |
| `blendMode` | enum | 任意 / `normal` | `normal / multiply / screen / overlay / darken / lighten / difference / add` | 重なり合成。multiply=暗く、screen=明るく、overlay=コントラスト、darken/lighten=暗/明優先、difference=差分、add=加算系。 |
| `fullHeight` | Boolean | 任意 / `false` | `true / false` | true=full-height扱い + 前面優先(z-index 4)、false=通常(z-index 2)。**高さ自体はどちらもbarHeightを使用。** |
| `disabled` | Boolean | 任意 / `false` | `true / false` | Barではtrue=Drag/Resize停止 + 半透明、false=editable=trueなら操作可。クリック選択は可能。 |

```html
<div class="bf-display-timeline"
     data-timeline-start="09:00"
     data-timeline-end="18:00"
     data-timeline-theme="light"
     data-timeline-items='[
       {
         "id":"work",
         "label":"勤務時間",
         "kind":"work",
         "displayType":"bar",
         "start":"09:00",
         "end":"18:00",
         "backgroundColor":"#d9e5cf",
         "textColor":"#102030",
         "blendMode":"normal",
         "fullHeight":true,
         "disabled":false
       }
     ]'></div>
```

### Shape CommentのPropertyと最小例 — 各値の意味

Shape Commentは **必ず** `displayType:"shapeComment"` を指定します。省略するとBarになります。

| Property | 型 | 必須 / 既定 | 許容値 | 説明 |
|---|---|---|---|---|
| `id` | string | 任意 / `item-N` | Barと同じ | API用ID。 |
| `label` | string | **必須** | 1–120文字 | Item名。commentText省略時の本文。 |
| `kind` | enum | 任意 / `neutral` | 6種 | 分類値。現Comment配色には直接使わない。 |
| `displayType` | enum | **`shapeComment`** | `bar / shapeComment` | Comment描画の指定。 |
| `start` | time | **必須** | Timeline範囲内 | 開始時刻 + Leader線Anchor。 |
| `end` | time | **必須** | startより後 | 終了時刻。枠に `start–end` を表示。 |
| `commentText` | string | 任意 / `label` | 最大240文字 | Comment本文。 |
| `commentPosition` | enum | 任意 / `bottom` | `top / bottom / left / right` | Anchorに対する初期位置。 |
| `commentOffsetX` | number | 任意 / `0` | -1000～1000 | 初期位置から横へpx移動。Track内へClamp。 |
| `commentOffsetY` | number | 任意 / `0` | -1000～1000 | 初期位置から縦へpx移動。Track内へClamp。 |
| `commentWidth` | number | 任意 / `96` | 72–240 | Comment幅(px)。 |
| `backgroundColor` | color | 任意 / 空 | `#RGB / #RRGGBB` | Comment背景。省略時Theme Comment色。 |
| `textColor` | color | 任意 / 空 | `#RGB / #RRGGBB` | Comment文字。省略時Theme Comment文字色。 |
| `blendMode` | enum | 任意 / `normal` | Barと同じ8種 | 値は保持するが、**現#125 Blend実描画はBarへ適用しShape Commentへは適用しない。** |
| `disabled` | Boolean | 任意 / `false` | `true / false` | 値は保持。**現RuntimeでComment Dragを止める場合はTimeline全体を `editable:false` にする。** |

```html
<div class="bf-display-timeline"
     data-timeline-start="09:00"
     data-timeline-end="18:00"
     data-timeline-editable="true"
     data-timeline-theme="light"
     data-timeline-items='[
       {
         "id":"meeting",
         "label":"打ち合わせ",
         "kind":"meeting",
         "displayType":"shapeComment",
         "start":"10:00",
         "end":"10:30",
         "commentText":"打ち合わせ",
         "commentPosition":"bottom",
         "commentOffsetX":0,
         "commentOffsetY":0,
         "commentWidth":96,
         "backgroundColor":"#ffe500",
         "textColor":"#101010"
       }
     ]'></div>
```

### 実使用例

```html
<div id="schedule" class="bf-display-timeline"
     data-timeline-start="09:00"
     data-timeline-end="21:00"
     data-timeline-step="60"
     data-timeline-snap="15"
     data-timeline-bar-height="64"
     data-timeline-bar-layout="overlap"
     data-timeline-grid="true"
     data-timeline-labels="true"
     data-timeline-editable="true"
     data-timeline-theme="light"
     data-timeline-items='[
       {"id":"work","label":"勤務時間","kind":"work","displayType":"bar","start":"09:00","end":"18:00","backgroundColor":"#d9e5cf","textColor":"#102030","blendMode":"normal","fullHeight":true,"disabled":false},
       {"id":"break","label":"休憩時間","kind":"break","displayType":"bar","start":"12:00","end":"13:00","backgroundColor":"#d8e6f2","textColor":"#102030","blendMode":"multiply","fullHeight":false,"disabled":false},
       {"id":"meeting","label":"打ち合わせ","kind":"meeting","displayType":"shapeComment","start":"10:00","end":"10:30","commentText":"打ち合わせ","commentPosition":"bottom","commentOffsetX":0,"commentOffsetY":0,"commentWidth":96,"backgroundColor":"#ffe500","textColor":"#101010"},
       {"id":"party","label":"飲み会","kind":"info","displayType":"bar","start":"19:00","end":"21:00","backgroundColor":"#f2bd5d","textColor":"#102030","blendMode":"overlay","fullHeight":false,"disabled":false}
     ]'></div>
```

### JavaScript Property設定例

```js
BoneDisplayTimeline.create(document.getElementById("schedule-js"), {
  orientation: "horizontal",
  start: "09:00", end: "21:00",
  step: 60, snap: 15,
  barHeight: 64, rowGap: 8,
  barLayout: "overlap",
  timeAxisMode: "all", groupIndex: 0,
  snapToParent: false, parentHeight: 0,
  showGrid: true, showLabels: true, editable: true,
  theme: "light", ariaLabel: "勤務予定"
}, [
  { id:"work", label:"勤務時間", kind:"work", displayType:"bar", start:"09:00", end:"18:00", blendMode:"normal", fullHeight:true, disabled:false },
  { id:"meeting", label:"打ち合わせ", kind:"meeting", displayType:"shapeComment", start:"10:00", end:"10:30", commentText:"打ち合わせ", commentPosition:"bottom", commentOffsetX:0, commentOffsetY:0, commentWidth:96 }
]);
```

### 更新例

```js
const root = document.querySelector("#schedule");
BoneDisplayTimelineFunctionalClass.setOptions(root, {
  barLayout: "stack",
  showGrid: true,
  editable: false
});
```

`editable:false` ならBar Drag/ResizeとShape Comment Dragをまとめて停止します。

### 必須読み込み

```html
<link rel="stylesheet" href="/boneflow/css/bone-display-timeline.css">
<script src="/boneflow/js/bone-blend.js"></script>
<script src="/boneflow/js/bone-display-timeline.js"></script>
<script src="/boneflow/js/bone-display-timeline-functional-class.js"></script>
```

### 実行サンプル
Installer適用後、`http://localhost/boneflow/sample/054/` でBarのみ / Shape Commentのみ / 混在実使用例を実Runtimeで確認できます。

## Public API
- `create(root, options, items)`
- `setItems(root, items)`
- `setOptions(root, options)`
- `getItems(root)`
- `getOptions(root)`
- `moveItem(root, id, start)`
- `resizeItem(root, id, start, end)`
- `moveComment(root, id, offsetX, offsetY)`
- `getAnchorPoint(root, time)`

## Error / Troubleshooting
- #040が開かない: #020 Label → #022 Hover Border Effect → #118 Transition Runtime → #118 Functional Class → #040 Runtimeの読込を確認します。
- Blendが効かない: #125 BoneBlend 1.0.0が読み込まれているか確認します。
- 接続イメージが出ない: #002 Bone Joint 1.1.36と関連Runtimeの読込を確認します。
- `data-timeline-items` が読めない: JSON全体を `'...'`、内部のキー/文字列を `"..."` にして、末尾カンマを付けないでください。
- 変更が反映されない: Property変更後に「反映」を押します。反映は何度でも実行できます。


## Runtime Property Schema API

#054はConsumerがProperty名を再定義しなくてよいように、Runtimeから正式Property Schemaを公開します。

```js
const schema = BoneDisplayTimeline.getPropertySchema();
const defaults = BoneDisplayTimeline.getPropertyDefaults();
const timeAxis = BoneDisplayTimeline.getPropertyDefinition("timeAxisMode");
```

`timeAxisMode` が正式な「時間ラベル表示」Propertyです。値は `all / group-first / none`。`showLabels` は既存互換の共通ゲートで、通常の表示選択には `timeAxisMode` を使用します。Bar内のItem `label` とは別責務です。

#048 TableなどのConsumerは、#054のPropertyを独自にハードコードせず `getPropertySchema()` を参照します。これにより#054のProperty追加・修正をConsumer側で再定義する事故を防ぎます。


### 縦表示 (orientation: vertical) / v1.0.27
- 時間は上から下へ進みます。時間目盛は左側、Gridは横線、バーは時間に応じた縦長の矩形です。
- barLayout=stack は複数の縦レーンを左右へ配置します。Drag/ResizeはY軸で動作します。
- orientation=horizontal は従来どおり横向きです。

### 縦表示の幅と列数（v1.0.34）
「方向：縦」を選択したとき、「縦表示の列幅（px）」「縦表示の列数（#048 Table）」が表示されます。既定値は列幅140px、列数7。列数は1〜31、幅は100〜480pxです。#048 Tableの正式HTML Functional Class / Cell Rendererで各列を構成し、時刻は上から下です。#048の完成済みRuntimeは変更しません。


### v1.0.34 縦表示／#048 Table 列幅仕様
縦表示の「タイムバー表示幅」は #054 の表示領域だけの幅です（既定140px）。列数既定7列。「グループ先頭だけ表示」は最左列にのみ時間軸ラベルを設け、その列幅にはラベル62pxを追加します。2列目以降の列幅は指定表示幅そのままです。例：7列・140px・先頭のみ表示では 202px + 140px × 6 = 1042px。表示しない場合は140px × 7 = 980px。各Timelineに表示する場合は202px × 7 = 1414px。#048 正式Runtimeは変更しません。


## #054 タイムバー重なり（v1.0.34）
既定は「重ねて表示」です。縦表示では左側／右側、横表示では上側／下側を選択します。重複するバーを既存の同じ列または行の内部で並べ、自動で別行を作りません。旧 `stack` データは縦で左側、横で上側へ読み替えます。縦のシェイプコメントはタイムバー内の左上・中央・下に表示します。


## v1.0.34 変更：項目別の重なり／時間ラベルの初期値
時間ラベルの初期値は縦横とも `group-first`（グループ先頭だけ表示）。縦表示では左端列だけに62pxを追加します。#048 Tableの設定列幅（既定140px）をタイムバー全体に使用し、重なるバーでも幅を縮小しません。各Itemの `verticalOverlap` は `overlap`／`left`／`right`、`horizontalOverlap` は `overlap`／`top`／`bottom`。左右上下の指定はそのItemの前面表示（z-index）を意味し、列幅を分割しません。旧 `barLayout` は互換入力として扱います。


## v1.0.34 重なり時の吸着（#054独自）

通常のタイムバーは、縦では#048 Tableの設定列幅いっぱい、横では設定バー高さ全体を使います。
重なり指定は各Itemの `verticalOverlap` (`overlap`/`left`/`right`) と `horizontalOverlap` (`overlap`/`top`/`bottom`) で設定します。
縦の `left` / `right` は対象バーのみ**幅50%**にして、左端／右端へ吸着・最前面に配置します。
横の `top` / `bottom` は対象バーのみ**高さ50%**にして、上端／下端へ吸着・最前面に配置します。
指定のない背面バーは全幅・全高を保持し、追加行は作りません。
右端吸着したバーの右辺は列内Timeline表示領域の右辺に揃います。
※ 方向の指定は従来の `z-index` 変更だけではなく実際のDOM座標を変更します。


### v1.0.36 — 縦表示の文字収まり・親要素吸着・別画面Preview
- `verticalTextFitMode`（HTML: `data-timeline-text-fit`）：`shrink` 初期値 / `expand-column`。縦向きで短時間バーを左右吸着した場合も、バー実測幅・高さと文字の実測長からフォントを12pxから必要サイズへ縮小（下限7px）。内容が下限でも入り切らない極端な短時間・長文では、`title` の全文Tooltipで参照可能。
- `expand-column` はConsumer側の#048 Table列幅を拡張する方式。今回の正式Previewではサンプルデータを置く左端列だけ自動拡張し、他列は既定幅140pxを保つ。設定幅最大480px。#048 Runtime/Frozenは変更しない。
- 本体Property画面のPreview枠は右下ドラッグの `resize: both` で変更可能。吸着ONのときPreview親の高さに追従（時間目盛が読める最低高さ624pxまではスクロール）。縦7列の幅は保持し、狭くしても列を押しつぶさず横スクロールを表示。
- `別画面で表示` は `/boneflow/test/bone-display-timeline-preview.html` にPreview専用ウィンドウを開き、同一Origin内でProperty変更を反映。別画面自身に再「別画面」ボタンや開発ログは付けない。ウィンドウを縮小してもタイムバーの幅と時間軸を維持しスクロールで表示。

### v1.0.38 描画不具合修復
- `gridTicks()` 未定義によるPreview白画面を修正。横・縦の両方を実ブラウザ描画で検証。
- 主線（1時間）・補助線（編集snap）を区別。別画面は同じRuntime/CSSを使用。
- #040 CallerはVersion文字列固定ではなく互換APIと依存状態を検証。接続失敗は件数と理由を表示。


## v1.0.39 #026 TimePicker consumer integration

The #054 test UI uses the independently installed #026 `bf-timepicker` HTML Functional Class for Timeline and Item start/end inputs. It listens for `bone-timepicker:select`, commits the value in the #054 consumer, and redraws. #026 Runtime and Functional Class are not distributed or edited by this package.
