# 機能設計書 53-テキストウィジェット

## 概要

本ドキュメントは、Decap CMSにおけるテキストウィジェット（Text Widget）の設計を記述する。複数行のプレーンテキスト入力フィールド（textarea）を提供するウィジェットである。

### 本機能の処理概要

**業務上の目的・背景**：CMSでコンテンツを編集する際に、説明文・本文・コメントなど複数行にわたるテキスト入力が必要なフィールドに対して、自動高さ調整付きのtextareaを提供する。config.ymlで`widget: text`と指定することで利用される。文字列ウィジェット（string）が単行入力であるのに対し、テキストウィジェットは複数行入力に特化している。

**機能の利用シーン**：エントリ編集画面・エントリ新規作成画面において、`widget: text`が指定されたフィールドに対して自動リサイズ付きのtextarea要素をレンダリングする。Markdownウィジェットほどのリッチ機能は不要だが複数行入力が必要な場合に使用される。

**主要な処理内容**：
1. 自動高さ調整付きtextarea（react-textarea-autosize）のレンダリング
2. 最小行数5行でのtextarea表示
3. 入力値の変更時にonChangeコールバックで親コンポーネントに値を通知
4. プレビューコンポーネントでの値表示

**関連システム・外部連携**：react-textarea-autosizeライブラリに依存。

**権限による制御**：なし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | エントリ編集画面 | 主機能 | フィールドの複数行テキスト入力 |
| 7 | エントリ新規作成画面 | 主機能 | フィールドの複数行テキスト入力 |

## 機能種別

UI入力コンポーネント

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| onChange | function | Yes | 値変更時のコールバック関数 | - |
| forID | string | No | textarea要素のid属性 | - |
| value | node | No | 現在の入力値（デフォルト: ''） | - |
| classNameWrapper | string | Yes | ラッパーのCSSクラス名 | - |
| setActiveStyle | function | Yes | フォーカス時のスタイル設定関数 | - |
| setInactiveStyle | function | Yes | ブラー時のスタイル設定関数 | - |

### 入力データソース

エディタのコントロールペインから提供されるprops。Reduxストアのエントリドラフトから値が供給される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| value | string | ユーザーが入力した複数行テキスト値 |

### 出力先

onChangeコールバック経由でReduxストアのエントリドラフトに反映される。

## 処理フロー

### 処理シーケンス

```
1. コンポーネントマウント
   └─ PropTypesの手動バリデーション実行（React 19対応）
2. react-textarea-autosizeコンポーネントがレンダリング
   └─ 最小行数: 5行（minRows={5}）
3. ユーザーがテキスト入力
   └─ onChange(e.target.value) で値を通知
4. テキスト量に応じてtextareaの高さが自動調整
   └─ react-textarea-autosizeが処理
```

### フローチャート

```mermaid
flowchart TD
    A[Textarea要素レンダリング] --> B[最小5行で表示]
    B --> C[ユーザー入力]
    C --> D[onChange で値を通知]
    D --> E[React再レンダリング]
    E --> F[高さ自動調整]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-53-01 | デフォルト値 | valueが未指定の場合は空文字列をデフォルト値とする | value prop未指定時 |
| BR-53-02 | 最小行数 | textareaの最小表示行数は5行 | 常時 |
| BR-53-03 | 常時更新 | shouldComponentUpdateは常にtrueを返し、react-textarea-autosizeの高さ計算が正しく行われるようにする | 常時 |
| BR-53-04 | フォント継承 | fontFamily: 'inherit'でtextareaのフォントを親要素から継承 | 常時 |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

該当なし。本ウィジェットはUIコンポーネントであり、データベースを直接操作しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | PropType警告 | 必須propsが未提供の場合 | React 19対応のためcomponentDidMountで手動バリデーション |

### リトライ仕様

該当なし。

## トランザクション仕様

該当なし。

## パフォーマンス要件

shouldComponentUpdateが常にtrueを返すため、不要な再レンダリングが発生する可能性がある。ソースコードのコメントによれば、リスト内でのアイテム並べ替え時にtextareaの高さが最小値になるバグへの対処であり、将来的な最適化が推奨されている。

## セキュリティ考慮事項

HTML textarea要素を使用しているため、ブラウザのデフォルトのXSS対策が適用される。

## 備考

- react-textarea-autosizeライブラリに依存しており、テキスト量に応じてtextarea高さが動的に変化する
- Reactクラスコンポーネントとして実装されている

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.js | `packages/decap-cms-widget-text/src/index.js` | Widget関数がname: 'text'でcontrolComponentとpreviewComponentを返す（4-10行目） |

**読解のコツ**: 文字列ウィジェット（string）と構造は同一だが、名前が'text'である点に注意。

#### Step 2: コントロールコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TextControl.js | `packages/decap-cms-widget-text/src/TextControl.js` | react-textarea-autosizeを使用した自動リサイズtextarea（40-49行目） |

**主要処理フロー**:
1. **3行目**: react-textarea-autosizeからTextareaをimport
2. **6-13行目**: PropTypes定義
3. **15-17行目**: デフォルトprops（value: ''）
4. **19-22行目**: componentDidMount - React 19対応の手動PropTypesチェック
5. **31-33行目**: shouldComponentUpdate - 常にtrue（高さ計算のため）
6. **40-49行目**: render - Textarea（react-textarea-autosize）コンポーネント、minRows=5、fontFamily='inherit'
7. **48行目**: onChange - e.target.valueをonChangeに直接渡す

#### Step 3: プレビューコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TextPreview.js | `packages/decap-cms-widget-text/src/TextPreview.js` | StringPreviewと同一構造のWidgetPreviewContainer表示（5-7行目） |

### プログラム呼び出し階層図

```
DecapCmsWidgetText (index.js)
    |
    +-- Widget()
    |       └── { name: 'text', controlComponent, previewComponent }
    |
    +-- TextControl (TextControl.js)
    |       +-- componentDidMount() - PropTypes手動検証
    |       +-- shouldComponentUpdate() - 常にtrue
    |       └── render() - <Textarea minRows={5}> レンダリング
    |               └── react-textarea-autosize
    |
    └── TextPreview (TextPreview.js)
            └── WidgetPreviewContainer で値表示
```

### データフロー図

```
[入力]                     [処理]                     [出力]

ユーザーのキー入力  ──> Textarea onChange       onChange(value)
                        |                        |
                        v                        v
                   e.target.value取得       Reduxドラフト更新
                        |
                        v
                   react-textarea-autosize
                   が高さ自動調整
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `packages/decap-cms-widget-text/src/index.js` | ソース | ウィジェットエクスポート定義 |
| TextControl.js | `packages/decap-cms-widget-text/src/TextControl.js` | ソース | 入力コントロールコンポーネント |
| TextPreview.js | `packages/decap-cms-widget-text/src/TextPreview.js` | ソース | プレビューコンポーネント |
