> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aftersell.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cart itemsブロック

> Cart itemsブロック: ラインアイテムのリスト、Product行、ネストされたサブブロックのホスト。

> **Cart items** ブロックはカート内のラインアイテムのリストで、購入者が追加した各商品を、画像、タイトル、バリエーション、価格、数量ステッパー、削除ボタンとともに表示します。必須ブロックであり、カートのサブブロック（**Product** 行、[**Subscription upgrade**](/ja/aftersell/cart/subscription-upgrade-block)、[**Custom code**](/ja/aftersell/cart/custom-code-blocks)）をホストするコンテナとして、行ごとのサブブロックが取り付けられる構造を提供します。

<Frame>
  <img src="https://mintcdn.com/aftersell/1Y3gBpUfxv16VGSW/images/aftersell/cart-items-block-line-product-title-variant.png?fit=max&auto=format&n=1Y3gBpUfxv16VGSW&q=85&s=3c9f088b55cfd8450dcb8670dfe0728a" alt="商品画像、タイトル、バリエーション、価格、数量ステッパー、削除ボタン付きのラインアイテムを表示するCart itemsブロック" width="1420" height="486" data-path="images/aftersell/cart-items-block-line-product-title-variant.png" />
</Frame>

<div id="the-product-row">
  ## Product行
</div>

Cart itemsの中には **Product** サブブロック（実際のラインアイテム行）があります。ロックされていて自動的に追加されるため、すべてのCart itemsブロックには常にちょうど1つの削除できないProduct行があり、他のサブブロックはその周りに配置します。その設定では、各行の価格表示を制御します。

| 設定                                         | 制御する内容                                                                                                                                                                 | デフォルト                  |
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| **Strike-through price**                   | 取り消し線付きで表示する価格: **Compare-atまたは割引前のうち高い方**、**Compare-at価格**、**割引前価格**、**取り消し線なし**。                                                                                     | Compare-atまたは割引前のうち高い方 |
| **Strike-through price for subscriptions** | サブスクリプション行に対する同様の選択。2つの違いがあります: **Subscription compare-at price** オプションが追加され、**Compare-at price** は **Product compare-at, then subscription compare-at** という名称になります。   | Compare-atまたは割引前のうち高い方 |
| **Savings label**                          | 節約額を**金額（Amount）**、\*\*パーセンテージ（Percentage）\*\*で表示するか、\*\*非表示（Hidden）\*\*にするか。                                                                                          | Amount                 |
| **Bundle price**                           | バンドル行の表示価格の計算方法。**Automatic** はバンドル内の全アイテムの合計（他のアイテムが無料の場合はメインアイテムの価格）を表示します。**Main item price only** はメイン（アンカー）アイテムの価格のみを表示します。これは表示上のラベルにすぎず、Shopifyのカート合計が常に正となります。 | Automatic              |
| **Savings text**                           | 節約ラベル。`{{value}}` トークンに対応。                                                                                                                                             | `Save {{value}}`       |

行自体は、商品画像（可能な場合は商品ページへのリンク付き）、タイトル、バリエーション、価格と取り消し線付きのcompare-at価格、数量ステッパー、削除ボタンを表示します。バンドル行は、その構成品の開閉式リストを表示します。

<div id="text-styling">
  ### テキストスタイリング
</div>

Product行のDesign設定には **Text** セクションがあります。各ラインアイテム内の個々のテキスト要素のタイポグラフィを制御するために使用します。ピッカーからテキスト要素を選択して、その設定を調整します。

| 設定                 | 制御する内容                                                                                            |
| ------------------ | ------------------------------------------------------------------------------------------------- |
| **Text color**     | 選択したテキスト要素の色。                                                                                     |
| **Font**           | **Theme font**（テーマのフォントを継承）または **Custom font**（テーマがすでに読み込んでいるフォント名を入力）。**Product title** のみで利用可能。 |
| **Size**           | フォントサイズ（ピクセル単位）。                                                                                  |
| **Weight**         | フォントの太さ: Light、Regular、Medium、Semibold、または Bold。                                                  |
| **Line height**    | フォントサイズに対する倍率としての行の高さ（例: `1.4`）。                                                                  |
| **Letter spacing** | 文字間隔（ピクセル単位）。負の値でテキストを詰めます。                                                                       |

スタイリングできるテキスト要素はカテゴリごとにグループ化されています。

**Product**

* **Product title** — 各行の商品名。カスタムフォントファミリーにも対応。
* **Variant** — バリエーションラベル（例: *Size: Medium*）。
* **Subscription plan** — サブスクリプション行に表示される読み取り専用のプランラベル。

**Pricing**

* **Price** — 行の現在価格。
* **Compare-at price** — 取り消し線付きの元の価格。
* **Savings** — 節約ラベル（例: *Save \$5.00*）。サイズと行の高さのみ設定可能 — 太字と色は上のリッチテキストエディタで設定します。

**Bundle**

* **Bundle toggle** — バンドルの構成品リストを展開する開閉ヘッダー。
* **Bundle item title** — バンドル内の各構成品のタイトル。
* **Bundle item variant** — 各バンドル構成品のバリエーションラベル。

いずれかのフィールドを空欄のままにすると、その要素はデフォルト値のままになります。

<Tip>
  カートプレビュー内のテキスト要素を直接クリックすると、その要素がハイライトされ、パネルのコントロールが自動的に開きます。
</Tip>

<div id="discount-tags-design">
  ### 割引タグのデザイン
</div>

Product行のDesign設定には **Discount tags** セクションがあります。各ラインアイテムに表示される割引タグのピルをスタイリングするのに使用します。

| 設定                   | 制御する内容         | デフォルト     |
| -------------------- | -------------- | --------- |
| **Background color** | 割引タグピルの塗りつぶし色。 | `#F1F1F1` |
| **Text color**       | 割引タグピル内のテキスト色。 | `#585858` |
| **Border radius**    | 割引タグピルの角丸。     | `6px`     |

これらの設定は、Cart itemsブロック内のラインアイテムの割引タグにのみ適用されます。[Summaryブロック](/ja/aftersell/cart/summary-block)の割引コードタグは別途スタイリングします。

<div id="sub-blocks-and-how-they-position">
  ## サブブロックとその配置
</div>

Cart itemsは、サブブロックをホストする唯一のブロックです。**サブブロックは行ごとに1回、すべての商品行の中に**レンダリングされ、固定されたProduct行を基準に配置されます。

* Product行より**前**に並べたサブブロックは、各行の商品コンテンツの**上**に表示されます。
* Product行より**後**に並べたサブブロックは、各行の商品コンテンツの**下**に表示されます。

そのため、Product行の後に配置した[Subscription upgrade](/ja/aftersell/cart/subscription-upgrade-block)は、リスト全体の一番下に1回表示されるのではなく、対象となる各行の下に表示されます。

<div id="behavior">
  ## 動作
</div>

* カートにアイテムがない場合、ドロワーは空の状態に切り替わり、このブロックは表示されません。
* **カートの変更は一度に1つずつ実行されます。** 数量の更新や削除が処理中の間、カートの整合性を保つため行のコントロールは無効になり、変更が確定すると再び有効になります。
* 行の数量を1未満に下げると、その行は削除されます。ストアが拒否する数量（たとえば在庫を超える数量）は、最後の有効な値に再同期されます。
* **バンドルは一体として変化します。** バンドルのアンカー行の数量を調整すると、バンドル全体が1回の操作でスケールします。子アイテムがアンカー1つにつき3個含まれている場合、アンカーを1から2にするとその子アイテムは6になります。アンカーを削除すると、バンドルのすべてのメンバーが一度に削除されます。
* **一部のバンドルは数量を変更できません。** バンドルの子アイテムのいずれかが小数の割合（たとえばアンカー1つにつき1.5個）で含まれている場合、そのバンドルの数量ステッパーはロックされます。+/−ボタンと数量フィールドは両方とも無効になり、入力された数量も受け付けられません。バンドルの削除は引き続き可能です。
* **サブスクリプション行にはプランが表示されます。** 行に販売プランがあり、[Subscription upgrade](/ja/aftersell/cart/subscription-upgrade-block)サブブロックがオフまたは未追加の場合、Product行はバリエーションの下に読み取り専用のプランラベル（たとえば *Delivers every month (save 30%)*）を表示します。そのサブブロックが有効な場合は、独自のピッカーでプランを表示するため、読み取り専用ラベルは重複せずに非表示になります。

<div id="placement-and-limits">
  ## 配置と制限
</div>

* **リージョン:** 本体（body）。
* **最大数:** カート状態ごとに1つ。
* **状態:** 商品が入ったカートのみ。
* **ロックされており、デフォルトで追加されます。** Cart itemsは削除や非表示にできず、位置の変更のみ可能です。

<div id="custom-template">
  ## カスタムテンプレート
</div>

Codeタブから[カスタムテンプレート](/ja/aftersell/cart/custom-templates)に対応しており、このブロックの組み込みマークアップを独自のJSXに置き換えます。受け取るpropsは次のとおりです。

**Cart items** コンテナ自体にはカスタムテンプレートがありません。その中の **Product** 行にはあり、カート内で最も豊富な情報を持つ画面です。テンプレートは行ごとに1回レンダリングされます。

<div id="line-content">
  ### 行のコンテンツ
</div>

| Prop               | 型                           | 用途                                                                                                                                                        |
| ------------------ | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title`            | `string`                    | プレーンテキストの商品タイトル。                                                                                                                                          |
| `variantTitle`     | `string \| null`            | バリエーションのラベル。単一バリエーションの商品とネイティブバンドルでは `null`。                                                                                                              |
| `url`              | `string \| null`            | 商品ページのURL。行がリンクすべきでない場合は `null`。                                                                                                                          |
| `imageUrl`         | `string \| null`            | 行の画像。商品に画像がない場合は `null`。                                                                                                                                  |
| `quantity`         | `number`                    | 行の現在の数量。                                                                                                                                                  |
| `price`            | `string`                    | **フォーマット済み**の行の価格。                                                                                                                                        |
| `compareAtPrice`   | `string \| null`            | 取り消し線付きの「元の」価格（フォーマット済み）。取り消すものがない場合は `null`。                                                                                                             |
| `savingsHtml`      | `string \| null`            | サニタイズ済みHTMLとしての節約ラベル。非表示または節約がない場合は `null`。                                                                                                               |
| `discountTags`     | `string[]`                  | この行の割引のタイトル。例: `['Spring Sale']`。ない場合は `[]`。                                                                                                              |
| `sellingPlanLabel` | `string \| null`            | 読み取り専用のサブスクリプションプラン名。1回限りの行の場合、または[Subscription upgrade](/ja/aftersell/cart/subscription-upgrade-block#custom-template)サブブロックがプランUIをレンダリングしている場合は `null`。 |
| `bundle`           | `object \| null`            | アンカー行での[バンドル](/ja/aftersell/cart/sdk-cart-object#bundles)ビューモデル。それ以外は `null`。                                                                             |
| `productId`        | `number`                    | Shopifyの商品ID。                                                                                                                                             |
| `variantId`        | `number`                    | ShopifyのバリエーションID。                                                                                                                                        |
| `line`             | `AftersellCartLine`         | 上記のpropsでカバーされない情報のための完全な[カートライン](/ja/aftersell/cart/sdk-cart-object#cart-lines)。                                                                         |
| `formatMoney`      | `(cents: number) => string` | 最小通貨単位の金額をフォーマットします。`line` から読み取った価格に使用してください。                                                                                                            |

<Warning>
  **`price` と `compareAtPrice` はフォーマット済みの文字列で、`line` 上のすべての値はセント単位です。** `price` で計算を行わないでください。`line.finalLinePrice` などから計算し、結果を `formatMoney` に通してください。
</Warning>

<div id="quantity-and-removal">
  ### 数量と削除
</div>

| Prop                | 型                                                | 用途                                                                                                                   |
| ------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| `increment`         | `() => void`                                     | 行に1つ追加します。                                                                                                           |
| `decrement`         | `() => void`                                     | 行から1つ減らします。                                                                                                          |
| `remove`            | `() => void`                                     | 行を完全に削除します。                                                                                                          |
| `quantityInput`     | `string`                                         | 制御された数量 `<input>` の現在値。文字列のため、入力途中の状態が保持されます。                                                                        |
| `onQuantityInput`   | `(event: Event) => void`                         | そのフィールドの `onInput` ハンドラ。                                                                                             |
| `commitQuantity`    | `() => void`                                     | 入力された数量を適用します。`onBlur` に接続してください。                                                                                    |
| `onQuantityKeyDown` | `(event: KeyboardEvent) => void`                 | Enterで確定できるようにする `onKeyDown` ハンドラ。                                                                                   |
| `busy`              | `boolean`                                        | カートの変更が処理中の間 `true`。これを使ってコントロールを無効にしてください。                                                                          |
| `pending`           | `'increment' \| 'decrement' \| 'remove' \| null` | 現在処理中のアクション。対象を絞ったスピナー表示に使用します。                                                                                      |
| `stepperLocked`     | `boolean`                                        | 数量を変更できない場合に `true`。行が、小数のアンカーあたり割合で子アイテムを含むバンドルのアンカーである場合です。ステッパーを非表示または無効にしてください。組み込みハンドラは、これが設定されている間すでに変更を拒否します。 |

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomTemplate(props) {
  return (
    <div className="cart-external-cart-items__row" style={{ display: 'flex', gap: '12px', opacity: props.busy ? 0.6 : 1 }}>
      {props.imageUrl && <img src={props.imageUrl} alt="" width={64} height={64} />}

      <div style={{ flex: 1 }}>
        {props.url ? <a href={props.url}>{props.title}</a> : <span>{props.title}</span>}
        {props.variantTitle && <div style={{ opacity: 0.6 }}>{props.variantTitle}</div>}
        {props.sellingPlanLabel && <div style={{ opacity: 0.6 }}>{props.sellingPlanLabel}</div>}

        {props.discountTags.map((tag) => (
          <span key={tag} style={{ fontSize: '11px', border: '1px solid', borderRadius: '4px', padding: '1px 5px' }}>
            {tag}
          </span>
        ))}

        {!props.stepperLocked && (
          <div style={{ display: 'flex', alignItems: 'center', gap: '6px', marginTop: '6px' }}>
            <button type="button" onClick={props.decrement} disabled={props.busy}>&minus;</button>
            <input
              value={props.quantityInput}
              onInput={props.onQuantityInput}
              onBlur={props.commitQuantity}
              onKeyDown={props.onQuantityKeyDown}
              size={2}
            />
            <button type="button" onClick={props.increment} disabled={props.busy}>+</button>
            <button type="button" onClick={props.remove} disabled={props.busy}>
              {props.pending === 'remove' ? 'Removing…' : 'Remove'}
            </button>
          </div>
        )}
      </div>

      <div style={{ textAlign: 'right' }}>
        <div>{props.price}</div>
        {props.compareAtPrice && <s style={{ opacity: 0.5 }}>{props.compareAtPrice}</s>}
        {props.savingsHtml && <div dangerouslySetInnerHTML={{ __html: props.savingsHtml }} />}
      </div>
    </div>
  );
}
```

<div id="rendering-a-bundle">
  ### バンドルのレンダリング
</div>

バンドルのアンカー行では、`bundle.children` にその内容が入っています。子アイテムが独立した行として表示されることはないため、レンダリングしないと購入者はバンドルの中身を確認できません。

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomTemplate(props) {
  return (
    <div>
      <div>{props.title} {props.price}</div>

      {props.bundle && (
        <ul style={{ margin: '4px 0 0 12px', fontSize: '12px', opacity: 0.7 }}>
          {props.bundle.children.map((child, i) => (
            <li key={child.key ?? i}>{child.quantity} × {child.title}</li>
          ))}
        </ul>
      )}
    </div>
  );
}
```

Shopifyネイティブバンドルのコンポーネントでは子アイテムの `key` が `null` になるため、上記のようにインデックスにフォールバックしてください。

<div id="design">
  ## デザイン
</div>

このブロックのスタイルは、設定パネルの **Design** セクションで調整します。これらはブロックごとのオーバーライドで、グローバルデザインの上に重なり、空欄の場合はグローバルデザインにフォールバックします。

デザイン設定とは何でしょうか? 詳しくはこちら: [デザイン設定](/ja/aftersell/cart/design-settings)。
