> ## 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.

# Blok Cart items

> Blok Cart items: lista pozycji zamówienia, wiersz Product i kontener dla zagnieżdżonych sub-bloków.

> Blok **Cart items** to lista pozycji w koszyku, renderująca każdy produkt dodany przez kupującego wraz z obrazem, tytułem, wariantem, ceną, selektorem ilości i przyciskiem usunięcia. To blok wymagany i zarazem kontener obsługujący sub-bloki koszyka (wiersz **Product**, [**Subscription upgrade**](/pl/aftersell/cart/subscription-upgrade-block) i [**Custom code**](/pl/aftersell/cart/custom-code-blocks)), zapewniający strukturę, do której przypinają się sub-bloki per linia.

<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="Blok Cart items pokazujący pozycje z obrazem produktu, tytułem, wariantem, ceną, selektorem ilości i przyciskiem usunięcia" width="1420" height="486" data-path="images/aftersell/cart-items-block-line-product-title-variant.png" />
</Frame>

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

Wewnątrz Cart items znajduje się sub-blok **Product**: właściwy wiersz pozycji. Jest zablokowany i dodawany automatycznie, więc każdy blok Cart items zawsze ma dokładnie jeden wiersz Product, którego nie możesz usunąć; inne sub-bloki pozycjonujesz wokół niego. Jego ustawienia kontrolują sposób wyświetlania cen każdej linii:

| Ustawienie                                 | Co kontroluje                                                                                                                                                                                                                                                                                                                            | Domyślnie                                       |
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| **Strike-through price**                   | Która cena jest pokazywana jako przekreślona: **Compare-at or pre-discount, whichever is higher**, **Compare-at price**, **Pre-discount price** lub **No strike-through**.                                                                                                                                                               | Compare-at or pre-discount, whichever is higher |
| **Strike-through price for subscriptions** | Ten sam wybór dla linii subskrypcyjnych, z dwiema różnicami: dodatkową opcją **Subscription compare-at price** oraz zmianą nazwy **Compare-at price** na **Product compare-at, then subscription compare-at**.                                                                                                                           | Compare-at or pre-discount, whichever is higher |
| **Savings label**                          | Czy oszczędności pokazują się jako **Amount**, **Percentage**, czy są **Hidden**.                                                                                                                                                                                                                                                        | Amount                                          |
| **Bundle price**                           | Jak wyliczana jest wyświetlana cena dla linii pakietowych. **Automatic** pokazuje sumę wszystkich pozycji w pakiecie (lub cenę pozycji głównej, gdy pozostałe są darmowe). **Main item price only** pokazuje tylko cenę pozycji głównej (kotwicy). To wyłącznie etykieta wyświetlania — suma koszyka Shopify jest zawsze rozstrzygająca. | Automatic                                       |
| **Savings text**                           | Etykieta oszczędności. Obsługuje token `{{value}}`.                                                                                                                                                                                                                                                                                      | `Save {{value}}`                                |

Sam wiersz renderuje obraz produktu (z linkiem do strony produktu, gdy jest dostępna), tytuł, wariant, cenę i ewentualną przekreśloną cenę compare-at, selektor ilości i przycisk usunięcia. Linie pakietowe pokazują rozwijaną listę swoich składników.

<div id="text-styling">
  ### Stylizacja tekstu
</div>

Wiersz Product zawiera sekcję **Text** w swoich ustawieniach Design. Użyj jej, aby kontrolować typografię poszczególnych elementów tekstowych w każdej pozycji. Wybierz element tekstowy z selektora, aby dostosować jego ustawienia:

| Ustawienie         | Co kontroluje                                                                                                                                    |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Text color**     | Kolor wybranego elementu tekstowego.                                                                                                             |
| **Font**           | **Theme font** (dziedziczy krój z motywu) lub **Custom font** (wpisz nazwę kroju, który motyw już ładuje). Dostępne tylko dla **Product title**. |
| **Size**           | Rozmiar czcionki w pikselach.                                                                                                                    |
| **Weight**         | Grubość czcionki: Light, Regular, Medium, Semibold lub Bold.                                                                                     |
| **Line height**    | Wysokość wiersza jako mnożnik rozmiaru czcionki (na przykład `1.4`).                                                                             |
| **Letter spacing** | Odstęp między literami w pikselach. Wartości ujemne zwężają tekst.                                                                               |

Elementy tekstowe, które możesz stylizować, są pogrupowane według kategorii:

**Product**

* **Product title** — nazwa produktu na każdej linii. Obsługuje też niestandardowy krój.
* **Variant** — etykieta wariantu (na przykład *Size: Medium*).
* **Subscription plan** — etykieta planu tylko do odczytu pokazywana na liniach subskrypcyjnych.

**Pricing**

* **Price** — bieżąca cena linii.
* **Compare-at price** — przekreślona cena oryginalna.
* **Savings** — etykieta oszczędności (na przykład *Save \$5.00*). Tylko rozmiar i wysokość wiersza — pogrubienie i kolor ustawiasz w Rich Text Editor powyżej.

**Bundle**

* **Bundle toggle** — nagłówek rozwijany otwierający listę składników pakietu.
* **Bundle item title** — tytuł każdego składnika w pakiecie.
* **Bundle item variant** — etykieta wariantu dla każdego składnika pakietu.

Pozostawienie dowolnego pola pustego zachowuje domyślną wartość elementu.

<Tip>
  Kliknięcie elementu tekstowego bezpośrednio w podglądzie koszyka podświetla go i automatycznie otwiera jego kontrolki w panelu.
</Tip>

<div id="discount-tags-design">
  ### Design tagów rabatowych
</div>

Wiersz Product zawiera sekcję **Discount tags** w swoich ustawieniach Design. Użyj jej do stylizacji plakietek tagów rabatowych pojawiających się na każdej pozycji:

| Ustawienie           | Co kontroluje                                    | Domyślnie |
| -------------------- | ------------------------------------------------ | --------- |
| **Background color** | Kolor wypełnienia plakietki tagu rabatowego.     | `#F1F1F1` |
| **Text color**       | Kolor tekstu wewnątrz plakietki tagu rabatowego. | `#585858` |
| **Border radius**    | Zaokrąglenie rogów plakietki tagu rabatowego.    | `6px`     |

Te ustawienia dotyczą wyłącznie tagów rabatowych pozycji w bloku Cart items. Tagi kodów rabatowych w [bloku Summary](/pl/aftersell/cart/summary-block) są stylizowane osobno.

<div id="sub-blocks-and-how-they-position">
  ## Sub-bloki i ich pozycjonowanie
</div>

Cart items to jedyny blok obsługujący sub-bloki. **Sub-bloki renderują się raz per linia, wewnątrz każdego wiersza produktu**, pozycjonowane względem przypiętego wiersza Product:

* Sub-bloki ustawione **przed** wierszem Product pojawiają się **nad** treścią produktu w każdej linii.
* Sub-bloki ustawione **po** wierszu Product pojawiają się **pod** treścią produktu w każdej linii.

Zatem [Subscription upgrade](/pl/aftersell/cart/subscription-upgrade-block) umieszczony po wierszu Product pokazuje się pod każdą kwalifikującą się linią, a nie raz na dole całej listy.

<div id="behavior">
  ## Działanie
</div>

* Gdy koszyk nie ma pozycji, szuflada przełącza się na stan pusty i ten blok nie jest pokazywany.
* **Jedna zmiana koszyka naraz.** Podczas trwającej aktualizacji ilości lub usuwania kontrolki wiersza są wyłączone, aby zachować spójność koszyka, a potem ponownie włączone po zakończeniu zmiany.
* Obniżenie ilości linii poniżej 1 usuwa ją. Ilość odrzucona przez sklep (na przykład powyżej dostępnego stanu magazynowego) ponownie synchronizuje się z ostatnią prawidłową wartością.
* **Pakiety zmieniają się jako całość.** Zmiana ilości na linii kotwicy pakietu skaluje cały pakiet w jednej operacji — jeśli element podrzędny jest dołączony w liczbie 3 na kotwicę, zwiększenie kotwicy z 1 do 2 zwiększa ten element do 6. Usunięcie kotwicy usuwa naraz wszystkie elementy pakietu.
* **Niektórych pakietów nie można przeliczać.** Jeśli którykolwiek element podrzędny pakietu jest dołączony w ułamkowej proporcji (np. 1,5 na kotwicę), selektor ilości na tym pakiecie jest zablokowany: przyciski +/− i pole ilości są wyłączone, a wpisane ilości nie są akceptowane. Pakiet nadal można usunąć.
* **Linie subskrypcyjne pokazują swój plan.** Gdy linia ma plan sprzedaży, a sub-blok [Subscription upgrade](/pl/aftersell/cart/subscription-upgrade-block) jest wyłączony lub niedodany, wiersz Product pokazuje etykietę planu tylko do odczytu pod wariantem — na przykład *Delivers every month (save 30%)*. Gdy ten sub-blok jest włączony, prezentuje plan we własnym selektorze, więc etykieta tylko do odczytu jest ukrywana, a nie duplikowana.

<div id="placement-and-limits">
  ## Umiejscowienie i limity
</div>

* **Region:** treść (body).
* **Maksimum:** 1 na stan koszyka.
* **Stan:** tylko wypełniony koszyk.
* **Zablokowany i dodawany domyślnie.** Cart items nie można usunąć ani ukryć, można tylko zmienić jego pozycję.

<div id="custom-template">
  ## Szablon niestandardowy
</div>

Obsługuje [szablon niestandardowy](/pl/aftersell/cart/custom-templates) z karty Code, który zastępuje wbudowaną strukturę tego bloku twoim JSX. Oto propsy, które otrzymuje.

Kontener **Cart items** nie ma szablonu niestandardowego. Ma go wiersz **Product** wewnątrz niego — to najbogatsza powierzchnia w koszyku: twój szablon renderuje się raz per linia.

<div id="line-content">
  ### Treść linii
</div>

| Prop               | Typ                         | Do czego służy                                                                                                                                                                                                            |
| ------------------ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title`            | `string`                    | Tytuł produktu, jako zwykły tekst.                                                                                                                                                                                        |
| `variantTitle`     | `string \| null`            | Etykieta wariantu. `null` dla produktów z jednym wariantem i natywnych pakietów.                                                                                                                                          |
| `url`              | `string \| null`            | URL strony produktu. `null`, gdy linia nie powinna linkować na zewnątrz.                                                                                                                                                  |
| `imageUrl`         | `string \| null`            | Obraz linii. `null`, gdy produkt go nie ma.                                                                                                                                                                               |
| `quantity`         | `number`                    | Bieżąca ilość na linii.                                                                                                                                                                                                   |
| `price`            | `string`                    | Cena linii, **już sformatowana**.                                                                                                                                                                                         |
| `compareAtPrice`   | `string \| null`            | Przekreślona cena „było”, już sformatowana. `null`, gdy nie ma czego przekreślać.                                                                                                                                         |
| `savingsHtml`      | `string \| null`            | Etykieta oszczędności jako oczyszczony HTML. `null`, gdy ukryta lub brak oszczędności.                                                                                                                                    |
| `discountTags`     | `string[]`                  | Tytuły rabatów na tej linii, np. `['Spring Sale']`. `[]`, gdy brak.                                                                                                                                                       |
| `sellingPlanLabel` | `string \| null`            | Nazwa planu subskrypcji tylko do odczytu. `null`, gdy to linia jednorazowa lub gdy sub-blok [Subscription upgrade](/pl/aftersell/cart/subscription-upgrade-block#custom-template) renderuje interfejs planu zamiast tego. |
| `bundle`           | `object \| null`            | Model widoku [pakietu](/pl/aftersell/cart/sdk-cart-object#bundles) na linii kotwicy. W pozostałych przypadkach `null`.                                                                                                    |
| `productId`        | `number`                    | ID produktu Shopify.                                                                                                                                                                                                      |
| `variantId`        | `number`                    | ID wariantu Shopify.                                                                                                                                                                                                      |
| `line`             | `AftersellCartLine`         | Pełna [linia koszyka](/pl/aftersell/cart/sdk-cart-object#cart-lines), do wszystkiego, czego nie pokrywają powyższe propsy.                                                                                                |
| `formatMoney`      | `(cents: number) => string` | Formatuje kwotę w jednostkach podrzędnych. Używaj do cen odczytanych z `line`.                                                                                                                                            |

<Warning>
  **`price` i `compareAtPrice` to sformatowane ciągi znaków; wszystko w `line` jest w centach.** Nie wykonuj obliczeń na `price`. Licz na `line.finalLinePrice` i pokrewnych, a wynik przepuść przez `formatMoney`.
</Warning>

<div id="quantity-and-removal">
  ### Ilość i usuwanie
</div>

| Prop                | Typ                                              | Do czego służy                                                                                                                                                                                                                           |
| ------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `increment`         | `() => void`                                     | Dodaje jedną sztukę do linii.                                                                                                                                                                                                            |
| `decrement`         | `() => void`                                     | Usuwa jedną sztukę z linii.                                                                                                                                                                                                              |
| `remove`            | `() => void`                                     | Całkowicie usuwa linię.                                                                                                                                                                                                                  |
| `quantityInput`     | `string`                                         | Bieżąca wartość dla kontrolowanego `<input>` ilości. Ciąg znaków, więc stany w trakcie wpisywania przetrwają.                                                                                                                            |
| `onQuantityInput`   | `(event: Event) => void`                         | Handler `onInput` dla tego pola.                                                                                                                                                                                                         |
| `commitQuantity`    | `() => void`                                     | Stosuje wpisaną ilość. Podłącz do `onBlur`.                                                                                                                                                                                              |
| `onQuantityKeyDown` | `(event: KeyboardEvent) => void`                 | Handler `onKeyDown`, aby Enter zatwierdzał.                                                                                                                                                                                              |
| `busy`              | `boolean`                                        | `true`, gdy dowolna mutacja koszyka jest w toku. Wyłącz na tej podstawie swoje kontrolki.                                                                                                                                                |
| `pending`           | `'increment' \| 'decrement' \| 'remove' \| null` | Która akcja jest obecnie w toku, na potrzeby ukierunkowanego spinnera.                                                                                                                                                                   |
| `stepperLocked`     | `boolean`                                        | `true`, gdy ilości nie można zmienić, ponieważ linia jest kotwicą pakietu z elementem podrzędnym dołączonym w ułamkowej proporcji na kotwicę. Ukryj lub wyłącz selektor — wbudowane handlery i tak odrzucają zmiany, gdy jest ustawiony. |

```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">
  ### Renderowanie pakietu
</div>

Na linii kotwicy pakietu `bundle.children` zawiera jego zawartość. Elementy podrzędne nigdy nie pojawiają się jako własne wiersze, więc jeśli ich nie wyrenderujesz, kupujący nie zobaczy, co jest w pakiecie:

```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>
  );
}
```

`key` elementu podrzędnego jest `null` dla składnika natywnego pakietu Shopify, więc użyj indeksu jako wartości zapasowej, jak powyżej.

<div id="design">
  ## Design
</div>

Stylizuj ten blok w sekcji **Design** w panelu ustawień. To nadpisania per blok, które nakładają się na twój globalny design i wracają do niego, gdy są puste.

Czym są ustawienia designu? Dowiedz się więcej tutaj: [Ustawienia designu](/pl/aftersell/cart/design-settings).
