[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/messages/th.json from the minicart VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.minicart.title": "รถเข็นขนาดเล็ก",
  "admin/editor.minicart.description": "รถเข็นขนาดเล็กที่แสดงผลิตถัณฑ์ทั้งหมดที่เพิ่มลงไป",
  "admin/editor.minicart.showDiscount.title": "แสดงจำนวนเงินที่ประหยัดได้",
  "admin/editor.minicart.iconLabel.title": "ข้อความจะปรากฏถัดจากไอคอน",
  "admin/editor.minicart.labelMiniCartEmpty.title": "ข้อความจะปรากฏเมื่อไม่มีสินค้าในรถเข็นขนาดเล็ก",
  "admin/editor.minicart.linkButtonFinishShopping.title": "ลิงก์เพื่อเปลี่ยนเส้นทางหลังคลิกปุ่มไปที่หน้าชำระเงิน",
  "admin/editor.minicart.labelButtonFinishShopping.title": "ข้อความจะปรากฏบนปุ่มซื้อสินค้าเสร็จ",
  "admin/editor.minicart.showShippingCost.title": "แสดงค่าจัดส่งเหนือส่วนท้ายของหน้า",
  "admin/editor.minicart.type.title": "ประเภทรถเข็นขนาดเล็ก",
  "admin/editor.minicart.type.popup": "ปรากฏขึ้นมา",
  "admin/editor.minicart.type.sidebar": "แถบด้านข้าง",
  "store/finish-shopping-button-label": "ไปที่หน้าชำระเงิน",
  "store/minicart-empty": "ไม่มีสินค้าในรถเข็นของคุณ!",
  "store/sidebar-title": "รถเข็นขนาดเล็กของฉัน",
  "store/minicart-content-footer-discount": "บันทึก",
  "store/minicart.error-removal": "ลบสินค้าไม่สำเร็จ กรุณาลองอีกครั้ง",
  "store/minicart.shipping-cost": "ค่าจัดส่งรวมทั้งหมด",
  "store/minicart.checkout-failure": "มีบางอย่างผิดพลาด กรุณาลองอีกครั้ง",
  "store/minicart.go-to-checkout": "ไปที่หน้าชำระเงิน",
  "store/minicart.empty-state": "ไม่มีสินค้าในรถเข็นของคุณ",
  "store/minicart.title": "รถเข็น"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/messages/sv.json from the minicart VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.minicart.title": "Mini kundvagn",
  "admin/editor.minicart.description": "En enkel mini kundvagn som visar alla produkter som läggs till i den",
  "admin/editor.minicart.showDiscount.title": "Visa mängden sparade pengar",
  "admin/editor.minicart.iconLabel.title": "Text som visas bredvid ikonen",
  "admin/editor.minicart.labelMiniCartEmpty.title": "Text som ska visas när mini kundvagnen är tom",
  "admin/editor.minicart.linkButtonFinishShopping.title": "Länk till omdirigering efter att man har klickat på knappen Gå till kassan",
  "admin/editor.minicart.labelButtonFinishShopping.title": "Text som ska visas på knappen slutför köp",
  "admin/editor.minicart.showShippingCost.title": "Visa fraktkostnaden ovanför sidfoten",
  "admin/editor.minicart.type.title": "Typ av mini kundvagn",
  "admin/editor.minicart.type.popup": "Pop Up",
  "admin/editor.minicart.type.sidebar": "Sidofält",
  "store/finish-shopping-button-label": "Gå till kassan",
  "store/minicart-empty": "Din kundvagn är tom!",
  "store/sidebar-title": "Min mini kundvagn",
  "store/minicart-content-footer-discount": "Spara",
  "store/minicart.error-removal": "Borttagning av föremål misslyckades, vänligen försök igen",
  "store/minicart.shipping-cost": "Total fraktkostnad",
  "store/minicart.checkout-failure": "Någonting gick fel, vänligen försök igen.",
  "store/minicart.go-to-checkout": "Gå till kassan",
  "store/minicart.empty-state": "Din kundvagn är tom.",
  "store/minicart.title": "Kundvagn"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/messages/nn.json from the minicart VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.minicart.title": "Minihandlevogn",
  "admin/editor.minicart.description": "En enkel minihandlevogn som viser alle produktene som er lagt til",
  "admin/editor.minicart.showDiscount.title": "Vis mengden sparte penger",
  "admin/editor.minicart.iconLabel.title": "Tekst som skal vises ved siden av ikonet",
  "admin/editor.minicart.labelMiniCartEmpty.title": "Tekst som skal vises når minihandlevognen er tom",
  "admin/editor.minicart.linkButtonFinishShopping.title": "Link til omdirigering etter å ha klikket på Gå til kassen-knappen",
  "admin/editor.minicart.labelButtonFinishShopping.title": "Tekst som skal vises i Ferdig å handle-knappen",
  "admin/editor.minicart.showShippingCost.title": "Vis fraktkostnaden over bunnteksten",
  "admin/editor.minicart.type.title": "Type minihandlevogn",
  "admin/editor.minicart.type.popup": "Popup",
  "admin/editor.minicart.type.sidebar": "Sidefelt",
  "store/finish-shopping-button-label": "Gå til kassen",
  "store/minicart-empty": "Handlevognen din er tom!",
  "store/sidebar-title": "Min minihandlevogn",
  "store/minicart-content-footer-discount": "Lagre",
  "store/minicart.error-removal": "Fjerning av vare mislyktes. Prøv igjen",
  "store/minicart.shipping-cost": "Total fraktkostnad",
  "store/minicart.checkout-failure": "Noe gikk galt. Prøv igjen.",
  "store/minicart.go-to-checkout": "Gå til kassen",
  "store/minicart.empty-state": "Handlevognen din er tom.",
  "store/minicart.title": "Handlevogn"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/messages/es.json from the minicart VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.minicart.title": "Minicart",
  "admin/editor.minicart.description": "Un simple resumen que muestra todos los productos agregados al carrito",
  "admin/editor.minicart.showDiscount.title": "Mostrar la cantidad de dinero ahorrado",
  "admin/editor.minicart.iconLabel.title": "Texto que aparecerá junto al ícono",
  "admin/editor.minicart.labelMiniCartEmpty.title": "Texto que aparecerá cuando el carrito esté vacío",
  "admin/editor.minicart.linkButtonFinishShopping.title": "Link de redirección al hacer clic en el botón \"Ir al checkout\"",
  "admin/editor.minicart.labelButtonFinishShopping.title": "Texto que aparecerá en el botón de finalizar la compra",
  "admin/editor.minicart.showShippingCost.title": "Mostrar los costos de envío sobre el pie de página",
  "admin/editor.minicart.type.title": "Tipo de carrito",
  "admin/editor.minicart.type.popup": "Ventana emergente",
  "admin/editor.minicart.type.sidebar": "Barra lateral",
  "store/finish-shopping-button-label": "Ir al checkout",
  "store/minicart-empty": "¡Tu carrito está vacío!",
  "store/sidebar-title": "Mi carrito",
  "store/minicart-content-footer-discount": "Guardar",
  "store/minicart.error-removal": "Error al eliminar el ítem. Por favor, vuelve a intentarlo.",
  "store/minicart.shipping-cost": "Costo total del envío",
  "store/minicart.checkout-failure": "Se produjo un error. Por favor, vuelve a intentarlo.",
  "store/minicart.go-to-checkout": "Ir al checkout",
  "store/minicart.empty-state": "Tu carrito está vacío.",
  "store/minicart.title": "Carrito"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/messages/ar.json from the minicart VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.minicart.title": "عربة شراء صغيرة",
  "admin/editor.minicart.description": "عربة صغيرة بسيطة تعرض جميع المنتجات المضافة إليها",
  "admin/editor.minicart.showDiscount.title": "اعرض كمية الأموال التي تم توفيرها",
  "admin/editor.minicart.iconLabel.title": "النص الذي سيظهر بجانب الرمز",
  "admin/editor.minicart.labelMiniCartEmpty.title": "النص الذي سيظهر عندما تكون العربة الصغيرة فارغة",
  "admin/editor.minicart.linkButtonFinishShopping.title": "رابط لإعادة التوجيه بعد النقر فوق الزر الذهاب إلى الدفع",
  "admin/editor.minicart.labelButtonFinishShopping.title": "النص الذي سيظهر في زر إنهاء التسوق",
  "admin/editor.minicart.showShippingCost.title": "إظهار تكلفة الشحن فوق التذييل",
  "admin/editor.minicart.type.title": "نوع عربة التسوق الصغيرة",
  "admin/editor.minicart.type.popup": "نافدة منبثقة",
  "admin/editor.minicart.type.sidebar": "الشريط الجانبي",
  "store/finish-shopping-button-label": "الذهاب إلى الدفع",
  "store/minicart-empty": "عربتك فارغة!",
  "store/sidebar-title": "عربة الشراء الصغيرة الخاصة بي",
  "store/minicart-content-footer-discount": "حفظ",
  "store/minicart.error-removal": "فشل إزالة العنصر، يرجى المحاولة مرة أخرى",
  "store/minicart.shipping-cost": "إجمالي تكلفة الشحن",
  "store/minicart.checkout-failure": "حدث خطأ ما. يرجى المحاولة مرة أخرى.",
  "store/minicart.go-to-checkout": "الذهاب إلى الدفع",
  "store/minicart.empty-state": "عربتك فارغة.",
  "store/minicart.title": "العربة"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/docs/README.md from the minicart VTEX app.

[Assistant]
Here's the implementation:

```markdown
📢 Use this project, [contribute](https://github.com/vtex-apps/minicart) to it or open issues to help evolve it using [Store Discussion](https://github.com/vtex-apps/store-discussion).

# Minicart

<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-3-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->

> ⚠ Minicart v1 block has been deprecated in favor of Minicart v2, which can be customized using the blocks defined by [Product List](https://developers.vtex.com/docs/apps/vtex.product-list) and [Checkout Summary](https://developers.vtex.com/docs/apps/vtex.checkout-summary). If you still use Minicart v1, see the [Minicart v1 documentation](https://github.com/vtex-apps/minicart/blob/383d7bbd3295f06d1b5854a0add561a872e1515c/docs/README.md).

The Minicart is a block that displays a summary list of all items added to the shopping cart, fetched from the Checkout OrderForm API.

![minicart-v2-gif](https://cdn.jsdelivr.net/gh/vtexdocs/dev-portal-content@main/images/vtex-minicart-0.gif)

## Configurating Minicart

1. Import the Minicart app to your theme dependencies in the `manifest.json`, as shown below:

```json
"dependencies": {
  "vtex.minicart": "2.x"
}
```

2. Add the `minicart.v2` block to your `header`. For example:

```json
"header.full": {
   "blocks": ["header-layout.desktop", "header-layout.mobile"]
 },

 "header-layout.desktop": {
   "children": [
     "header-row#1-desktop",
   ]
 },

 "header-row#1-desktop": {
   "children": ["minicart.v2"],
 },
```

> ⚠ Minicart v2 will only effectively function if the store uses the [`add-to-cart` app](https://developers.vtex.com/docs/apps/vtex.add-to-cart-button) instead of the [`buy-button` block](https://developers.vtex.com/docs/apps/vtex.store-components/buybutton) in blocks such as the Shelf and the Product Details page. This is because Minicart v2 was built based on an indirect dependency on the Add to Cart button. This means that even if Minicart v2 is correctly configured in the code, it cannot be rendered by other shopping buttons, such as the Buy button.

| Prop name              | Type               | Description                                                                                | Default value                                                                                |
| ---------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `variation`            | `enum`             | Minicart behavior when rendered. Possible values for displaying the VTEX Minicart are: `popup` (appears as a pop-up window on the homepage), `drawer` (appears as a sidebar), `link` (redirects the user to the Checkout page when clicked), `popupWithLink` (combines `link` and `popup` functionalities), and `block` (displays the Minicart as a fixed block on the page).                                                               | `drawer`                                                                                |
| `drawerSlideDirection` | `enum`             | Slide direction for the `drawer` Minicart opening. Possible values are: `rightToLeft` or `leftToRight`.                                                                                | `rightToLeft`                                                                                |
| `linkVariationUrl`     | `string`           | Link associated with the `link` Minicart.                                                                                | `undefined`                                                                                |
| `maxDrawerWidth`       | `number`           | Maximum width (in pixels) for the `drawer` Minicart when opened.                                                                                | `440`                                                                                |
| `openOnHover`          | `boolean`          | Indicates whether the `popup` Minicart should open when the user hovers over it.                                                                                | `false`                                                                                |
| `quantityDisplay`      | `enum`             | Shows the quantity badge even when the amount of products in the cart is zero. Possible values are: `always` or `not-empty` or `never`.                                                                                | `not-empty`                                                                                |
| `itemCountMode`        | `enum`             | Quantity badge behavior when displaying the total items added to Minicart. Possible values are: `total` (quantity badge displays the number of items added to the cart), `distinct` (only displays the number of different products added to the cart), `totalAvailable` (displays the number of available items added to the cart), and `distinctAvailable` (displays the number of different _and_ available products added to the cart). | `distinct`                                                                                |
| `backdropMode`         | `enum`             | Controls whether the backdrop should be displayed when the `drawer` Minicart is opened or not. Possible values are: `visible` (renders the backdrop) or `none` (renders the `drawer` without backdrop).                                                                                | `none`                                                                                |
| `MinicartIcon`         | `block`            | Icon displayed on the Minicart button. This prop value must match the block name responsible for rendering the desired icon.                                                                                | `icon-cart` (from the [Store Icons](https://developers.vtex.com/docs/guides/vtex-store-icons/) app) |
| `customPixelEventId`   | `string`           | Store event ID responsible for triggering the `minicart.v2` to automatically open on the interface.                                                                                | `undefined`                                                                                |
| `customPixelEventName` | `string`           | Store event name responsible for triggering the `minicart.v2` to automatically open on the interface. Some examples are: `'addToCart'` and `'removeFromCart'`. Note that using this prop will make the `minicart.v2` open in **every** event with the specified name if no `customPixelEventId` is specified.                                                                                | `undefined`                                                                                |
| `classes`              | `CustomCSSClasses` | Used to override default CSS handles. To better understand how this prop works, we recommend reading about it [here](https://github.com/vtex-apps/css-handles#usecustomclasses). Note that this is only useful when importing this block as a React component.                                                                                | `undefined`                                                                                |

### Advanced configurations

The default implementation for `minicart.v2` can be highly customizable by using other blocks. Currently, its default implementation is as follows:

```jsonc
// This is the default block implementation for the minicart-layout
{
  "minicart.v2": {
    "props": {
      "MinicartIcon": "icon-cart#minicart-icon"
    },
    "children": ["minicart-base-content"]
  },
  "icon-cart#minicart-icon": {
    "props": {
      "size": 24
    }
  },
  "minicart-base-content": {
    "blocks": ["minicart-empty-state"],
    "children": ["minicart-product-list", "flex-layout.row#minicart-footer"]
  },
  "flex-layout.row#minicart-footer": {
    "props": {
      "blockClass": "minicart-footer"
    },
    "children": ["flex-layout.col#minicart-footer"]
  },
  "flex-layout.col#minicart-footer": {
    "children": ["minicart-summary", "minicart-checkout-button"]
  },
  "minicart-product-list": {
    "blocks": ["product-list#minicart"]
  },
  "product-list#minicart": {
    "blocks": ["product-list-content-mobile"]
  },
  "minicart-summary": {
    "blocks": ["checkout-summary.compact#minicart"]
  },
  "minicart-checkout-button": {
    "props": {
      "finishShoppingButtonLink": "/checkout/#/orderform"
    }
  },

  "checkout-summary.compact#minicart": {
    "children": ["summary-totalizers#minicart"],
    "props": {
      "totalizersToShow": ["Items", "Discounts"]
    }
  },
  "summary-totalizers#minicart": {
    "props": {
      "showTotal": true,
      "showDeliveryTotal": false
    }
  },
  "minicart-empty-state": {
    "children": ["flex-layout.row#empty-state"]
  },
  "flex-layout.row#empty-state": {
    "children": ["flex-layout.col#empty-state"]
  },
  "flex-layout.col#empty-state": {
    "children": [
      "icon-cart#minicart-empty-state",
      "rich-text#minicart-default-empty-state"
    ],
    "props": {
      "horizontalAlign": "center",
      "verticalAlign": "middle",
      "rowGap": 5
    }
  },
  "icon-cart#minicart-empty-state": {
    "props": {
      "size": 64,
      "blockClass": "minicart-empty-state"
    }
  },
  "rich-text#minicart-default-empty-state": {
    "props": {
      "text": "Your cart is empty."
    }
  }
}
```

The default implementation of `minicart.v2` consists of the `JSON` code shown above, which is used behind the scenes whenever you use this block in your store.

To customize the Minicart configuration, you can copy the code and modify it to your needs.

For detailed instructions on how to configure each of the blocks that make up `minicart.v2`, read the [Product List](https://developers.vtex.com/docs/apps/vtex.product-list) and [Checkout Summary](https://developers.vtex.com/docs/apps/vtex.checkout-summary) documentations.

## Customization

To apply CSS customizations to this and other blocks, follow the instructions given in the recipe on [Using CSS handles for store customization](https://developers.vtex.com/docs/guides/vtex-io-documentation-using-css-handles-for-store-customization).

| CSS handles                     |
| ------------------------------- |
| `arrowUp`                       |
| `minicartCheckoutButton`        |
| `minicartContainer`             |
| `minicartContentContainer`      |
| `minicartFooter`                |
| `minicartIconContainer`         |
| `minicartProductListContainer`  |
| `minicartQuantityBadge`         |
| `minicartSideBarContentWrapper` |
| `minicartTitle`                 |
| `minicartWrapperContainer`      |
| `popupChildrenContainer`        |
| `popupContentContainer`         |
| `popupWrapper`                  |

## Contributors

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tr>
    <td align="center"><a href="https://github.com/lucasayb"><img src="https://avatars2.githubusercontent.com/u/17356081?v=4" width="100px;" alt=""/><br /><sub><b>Lucas Antônio Yamamoto Borges</b></sub></a><br /><a href="https://github.com/vtex-apps/minicart/commits?author=lucasayb" title="Code">💻</a></td>
    <td align="center"><a href="https://github.com/lucaspacheco-acct"><img src="https://avatars0.githubusercontent.com/u/59736416?v=4" width="100px;" alt=""/><br /><sub><b>lucaspacheco-acct</b></sub></a><br /><a href="https://github.com/vtex-apps/minicart/commits?author=lucaspacheco-acct" title="Code">💻</a></td>
    <td align="center"><a href="https://github.com/gustavopvasconcellos"><img src="https://avatars1.githubusercontent.com/u/49173685?v=4" width="100px;" alt=""/><br /><sub><b>gustavopvasconcellos</b></sub></a><br /><a href="https://github.com/vtex-apps/minicart/commits?author=gustavopvasconcellos" title="Code">💻</a></td>
  </tr>
</table>

<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/ProductList.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC, useCallback } from 'react'
import { useOrderForm } from 'vtex.order-manager/OrderForm'
import { useOrderItems } from 'vtex.order-items/OrderItems'
import { ExtensionPoint } from 'vtex.render-runtime'
import { usePixel } from 'vtex.pixel-manager'
import { CssHandlesTypes, useCssHandles } from 'vtex.css-handles'

import { mapCartItemToPixel } from './modules/pixelHelper'

const CSS_HANDLES = ['minicartProductListContainer'] as const

interface Props {
  renderAsChildren: boolean
  splitItem?: boolean
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

const ProductList: FC<Props> = ({
  renderAsChildren,
  splitItem = true,
  classes,
}) => {
  const {
    orderForm: { items },
  } = useOrderForm()
  const { updateQuantity, removeItem } = useOrderItems()
  const { push } = usePixel()
  const { handles } = useCssHandles(CSS_HANDLES, { classes })

  const options = {
    allowedOutdatedData: ['paymentData'],
    splitItem,
  }

  const handleQuantityChange = useCallback(
    (_: string, quantity: number, item: OrderFormItemWithIndex) => {
      if (quantity === item.quantity) {
        return
      }

      const quantityIncreased = quantity > item.quantity

      if (quantityIncreased) {
        const adjustedItem = {
          ...mapCartItemToPixel(item),
          quantity: quantity - item.quantity,
        }

        push({
          event: 'addToCart',
          items: [adjustedItem],
        })
      } else {
        const adjustedItem = {
          ...mapCartItemToPixel(item),
          quantity: item.quantity - quantity,
        }

        push({
          event: 'removeFromCart',
          items: [adjustedItem],
        })
      }

      updateQuantity({ index: item.index, quantity }, options)
    },
    [options, push, updateQuantity]
  )

  const handleRemove = useCallback(
    (uniqueId: string, item: OrderFormItem) => {
      const adjustedItem = mapCartItemToPixel(item)
      push({
        event: 'removeFromCart',
        items: [adjustedItem],
      })
      removeItem({ uniqueId }, options)
    },
    [options, push, removeItem]
  )

  return (
    <div
      /*
        This prevents an interaction with the quantity selector
        inside of a product in the ProductList to bubble up a
        mouseleave event to the Popup component, which would result
        in the minicart being closed (when openOnHover = true).
      */
      onMouseLeave={e => e.stopPropagation()}
      className={`${handles.minicartProductListContainer} ${
        renderAsChildren ? 'w-100 h-100' : ''
      } overflow-y-auto ph4 ph6-l`}
    >
      <ExtensionPoint
        id="product-list"
        items={items}
        onQuantityChange={handleQuantityChange}
        onRemove={handleRemove}
      />
    </div>
  )
}

export default ProductList

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/MinicartContext.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { createContext, useReducer, useContext, FC } from 'react'
import { useDevice } from 'vtex.device-detector'

interface OpenMinicartAction {
  type: 'OPEN_MINICART'
}
interface CloseMinicartAction {
  type: 'CLOSE_MINICART'
}
interface SetOpenBehaviorAction {
  type: 'SET_OPEN_BEHAVIOR'
  value: 'click' | 'hover'
}

interface State {
  variation: MinicartVariationType
  open: boolean
  hasBeenOpened: boolean
  /** Controls the minicart opening behavior */
  openBehavior: 'click' | 'hover'
  /** Value provided by the user to openOnHover prop */
  openOnHoverProp: boolean
}

interface Props {
  openOnHover?: boolean
  variation?: MinicartVariationType
}

type Action = OpenMinicartAction | CloseMinicartAction | SetOpenBehaviorAction
type Dispatch = (action: Action) => void

export const MinicartStateContext = createContext<State | undefined>(undefined)
const MinicartDispatchContext = createContext<Dispatch | undefined>(undefined)

function minicartContextReducer(state: State, action: Action): State {
  switch (action.type) {
    case 'OPEN_MINICART':
      return {
        ...state,
        open: true,
        hasBeenOpened: true,
      }
    case 'CLOSE_MINICART':
      return {
        ...state,
        open: false,
      }
    case 'SET_OPEN_BEHAVIOR':
      return {
        ...state,
        openBehavior: action.value,
      }
    default:
      return state
  }
}

const checkVariationIsPopup = (variation: string): boolean => {
  return variation === 'popup' || variation === 'popupWithLink'
}

const MinicartContextProvider: FC<Props> = ({
  variation = 'drawer',
  openOnHover: openOnHoverProp = false,
  children,
}) => {
  const { isMobile } = useDevice()
  const isPopup = checkVariationIsPopup(variation)

  // This prevents a popup minicart from being used on a mobile device
  const resolvedVariation =
    isPopup && (isMobile || (window && window.innerWidth <= 480))
      ? 'drawer'
      : variation

  const [state, dispatch] = useReducer(minicartContextReducer, {
    variation: resolvedVariation,
    open: false,
    hasBeenOpened: false,
    openOnHoverProp,
    openBehavior:
      checkVariationIsPopup(resolvedVariation) && openOnHoverProp
        ? 'hover'
        : 'click',
  })

  return (
    <MinicartStateContext.Provider value={state}>
      <MinicartDispatchContext.Provider value={dispatch}>
        {children}
      </MinicartDispatchContext.Provider>
    </MinicartStateContext.Provider>
  )
}

function useMinicartState() {
  const context = useContext(MinicartStateContext)
  if (context === undefined) {
    throw new Error(
      'useMinicartState must be used within a MinicartContextProvider'
    )
  }
  return context
}

function useMinicartDispatch() {
  const context = useContext(MinicartDispatchContext)

  if (context === undefined) {
    throw new Error(
      'useMinicartDispatch must be used within a MinicartContextProvider'
    )
  }
  return context
}

export { MinicartContextProvider, useMinicartDispatch, useMinicartState }

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/styles.css from the minicart VTEX app.

[Assistant]
Here's the implementation:

```css
.drawerStyles {
  height: 100%;
}

.popupStyles {
  max-height: 600px;
}

.minicartEmptyStateContainerDefault {
  width: 340px;
}

.minicartQuantityBadgeDefault {
  top: -0.7rem;
  right: -0.8rem;
}

.popupBoxPosition {
  right: -40px;
  width: 364px;
  top: 100%;
}

.popupArrowUp {
  right: 7px;
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/Minicart.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC, useCallback, useState } from 'react'
import { IconCart } from 'vtex.store-icons'
import { BackdropMode } from 'vtex.store-drawer'
import { useOrderForm } from 'vtex.order-manager/OrderForm'
import { ResponsiveValuesTypes } from 'vtex.responsive-values'
import { useCheckoutURL } from 'vtex.checkout-resources/Utils'
import { PixelEventTypes } from 'vtex.pixel-manager'
import { useCssHandles, CssHandlesTypes } from 'vtex.css-handles'

import PopupMode, {
  CSS_HANDLES as PopupModeCssHandles,
} from './components/Popup'
import DrawerMode, {
  CSS_HANDLES as DrawerModeCssHandles,
} from './components/DrawerMode'
import MinicartIconButton, {
  CSS_HANDLES as MinicartIconButtonCssHandles,
} from './components/MinicartIconButton'
import useCartIdPixel from './modules/useCartIdPixel'
import { MinicartCssHandlesProvider } from './components/CssHandlesContext'
import { MinicartContextProvider, useMinicartState } from './MinicartContext'
import useViewCartPixel from './modules/useViewCartPixel'

export const CSS_HANDLES = [
  ...PopupModeCssHandles,
  ...DrawerModeCssHandles,
  ...MinicartIconButtonCssHandles,
  'minicartWrapperContainer',
  'minicartContainer',
] as const

interface MinicartProps {
  variation?: MinicartVariationType
  openOnHover?: boolean
  linkVariationUrl?: string
  maxDrawerWidth?: number | string
  MinicartIcon?: React.ComponentType
  drawerSlideDirection?: SlideDirectionType
  quantityDisplay?: QuantityDisplayType
  itemCountMode?: MinicartTotalItemsType
  backdropMode?: ResponsiveValuesTypes.ResponsiveValue<BackdropMode>
  customPixelEventId?: string
  customPixelEventName?: PixelEventTypes.EventName
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

export const Minicart: FC<MinicartProps> = ({
  children,
  backdropMode,
  linkVariationUrl,
  maxDrawerWidth = 400,
  MinicartIcon = IconCart,
  quantityDisplay = 'not-empty',
  itemCountMode = 'distinct',
  drawerSlideDirection = 'rightToLeft',
  customPixelEventId,
  customPixelEventName,
  classes,
}) => {
  const { handles, withModifiers } = useCssHandles(CSS_HANDLES, { classes })

  const { orderForm }: OrderFormContext = useOrderForm()

  const { variation, open } = useMinicartState()
  const [isDrawerOpen, setIsDrawerOpen] = useState(open ?? false)
  const { url: checkoutUrl } = useCheckoutURL()

  const onDrawerVisibilityChanged = useCallback(
    (visible: boolean) => {
      setIsDrawerOpen(visible)
    },
    [setIsDrawerOpen]
  )

  // for Popup it uses "open" and for Drawer it uses "isDrawerOpen" to send view_cart pixel event
  useViewCartPixel(
    variation === 'drawer' ? isDrawerOpen : open,
    orderForm?.items
  )

  if (variation === 'link') {
    return (
      <aside
        className={`${handles.minicartWrapperContainer} relative fr flex items-center`}
      >
        <div className={`${handles.minicartContainer} flex flex-column`}>
          <a href={linkVariationUrl ?? checkoutUrl}>
            <MinicartCssHandlesProvider
              handles={handles}
              withModifiers={withModifiers}
            >
              <MinicartIconButton
                variation={variation}
                Icon={MinicartIcon}
                itemCountMode={itemCountMode}
                quantityDisplay={quantityDisplay}
              />
            </MinicartCssHandlesProvider>
          </a>
        </div>
      </aside>
    )
  }

  if (variation === 'block') {
    return (
      <aside
        className={`${handles.minicartWrapperContainer} relative fr flex items-center`}
      >
        <div className={`${handles.minicartContainer} flex flex-column`}>
          {children}
        </div>
      </aside>
    )
  }

  return (
    <aside
      className={`${handles.minicartWrapperContainer} relative fr flex items-center`}
    >
      <div className={`${handles.minicartContainer} flex flex-column`}>
        <MinicartCssHandlesProvider
          handles={handles}
          withModifiers={withModifiers}
        >
          {variation === 'drawer' ? (
            <DrawerMode
              Icon={MinicartIcon}
              backdropMode={backdropMode}
              itemCountMode={itemCountMode}
              maxDrawerWidth={maxDrawerWidth}
              quantityDisplay={quantityDisplay}
              drawerSlideDirection={drawerSlideDirection}
              customPixelEventId={customPixelEventId}
              customPixelEventName={customPixelEventName}
              onVisibilityChanged={onDrawerVisibilityChanged}
            >
              {children}
            </DrawerMode>
          ) : (
            <PopupMode
              Icon={MinicartIcon}
              itemCountMode={itemCountMode}
              quantityDisplay={quantityDisplay}
              customPixelEventId={customPixelEventId}
              customPixelEventName={customPixelEventName}
              variation={variation}
            >
              {children}
            </PopupMode>
          )}
        </MinicartCssHandlesProvider>
      </div>
    </aside>
  )
}

const CartIdPixel = () => {
  const { orderForm, loading }: OrderFormContext = useOrderForm()

  const orderFormId = !loading && orderForm ? orderForm.id : undefined

  useCartIdPixel(orderFormId)

  return null
}

const EnhancedMinicart = (props: MinicartProps) => (
  <MinicartContextProvider
    variation={props.variation}
    openOnHover={props.openOnHover}
  >
    <CartIdPixel />
    <Minicart {...props} />
  </MinicartContextProvider>
)

export default EnhancedMinicart

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/package.json from the minicart VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "vtex.minicart",
  "version": "2.68.0",
  "description": "A MiniCart Component.",
  "scripts": {
    "pretest": "yarn",
    "test": "vtex-test-tools test",
    "lint": "eslint --ext ts,tsx .",
    "lint:fix": "eslint --ext ts,tsx . --fix"
  },
  "devDependencies": {
    "@apollo/react-testing": "^3.1.3",
    "@types/debounce": "^1.2.0",
    "@types/jest": "^25.1.4",
    "@types/node": "^13.9.8",
    "@types/react": "^16.9.31",
    "@vtex/test-tools": "^3.1.0",
    "@vtex/tsconfig": "^0.4.4",
    "apollo-cache-inmemory": "^1.6.5",
    "babel-eslint": "^10.1.0",
    "typescript": "3.9.7",
    "vtex.checkout-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.66.0/public/@types/vtex.checkout-graphql",
    "vtex.checkout-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.49.0/public/@types/vtex.checkout-resources",
    "vtex.checkout-summary": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-summary@0.22.0/public/@types/vtex.checkout-summary",
    "vtex.css-handles": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@1.0.0/public/@types/vtex.css-handles",
    "vtex.device-detector": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.device-detector@0.2.6/public/@types/vtex.device-detector",
    "vtex.flex-layout": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.21.0/public/@types/vtex.flex-layout",
    "vtex.order-items": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.13.21/public/@types/vtex.order-items",
    "vtex.order-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.12.0/public/@types/vtex.order-manager",
    "vtex.pixel-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.9.0/public/@types/vtex.pixel-manager",
    "vtex.product-list": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-list@0.37.1/public/@types/vtex.product-list",
    "vtex.product-summary": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-summary@2.82.0/public/@types/vtex.product-summary",
    "vtex.react-portal": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.react-portal@0.4.1/public/@types/vtex.react-portal",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.133.0/public/@types/vtex.render-runtime",
    "vtex.responsive-values": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.responsive-values@0.4.2/public/@types/vtex.responsive-values",
    "vtex.rich-text": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.16.0/public/@types/vtex.rich-text",
    "vtex.sandbox": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.sandbox@0.5.1/public/@types/vtex.sandbox",
    "vtex.store-components": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-components@3.167.0/public/@types/vtex.store-components",
    "vtex.store-drawer": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-drawer@0.16.2/public/@types/vtex.store-drawer",
    "vtex.store-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.161.2/public/@types/vtex.store-graphql",
    "vtex.store-icons": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-icons@0.18.0/public/@types/vtex.store-icons",
    "vtex.store-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.89.0/public/@types/vtex.store-resources",
    "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.146.3/public/@types/vtex.styleguide"
  },
  "dependencies": {
    "apollo-client": "2.6.4",
    "classnames": "^2.2.6",
    "debounce": "^1.2.0",
    "graphql": "^14.6.0",
    "graphql-tag": "^2.10.1",
    "hoist-non-react-statics": "^3.3.0",
    "prop-types": "^15.7.2",
    "ramda": "^0.26.1",
    "react": "^16.8.4",
    "react-apollo": "3.1.3",
    "react-intl": "3.9.1",
    "react-outside-click-handler": "^1.2.2"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/index.jsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```jsx
/* eslint-disable no-shadow */
/* eslint-disable no-restricted-imports */
import classNames from 'classnames'
import { compose, map, partition, path, pathOr, pick, isNil, prop } from 'ramda'
import React, {
  useState,
  useEffect,
  useCallback,
  useRef,
  useContext,
  useMemo,
} from 'react'
import { graphql, withApollo } from 'react-apollo'
import { injectIntl } from 'react-intl'
import { ButtonWithIcon, ToastContext } from 'vtex.styleguide'
import { useRuntime } from 'vtex.render-runtime'
import { IconCart } from 'vtex.store-icons'
import orderFormQuery from 'vtex.store-resources/QueryOrderForm'
import addToCart from 'vtex.store-resources/MutationAddToCart'
import updateItems from 'vtex.store-resources/MutationUpdateItems'
import { usePixel } from 'vtex.pixel-manager/PixelContext'
import ProductPrice from 'vtex.store-components/ProductPrice'
import { useCheckoutURL } from 'vtex.checkout-resources/Utils'

import MiniCartContent from './legacy/components/MiniCartContent'
import Sidebar from './legacy/components/Sidebar'
import Popup from './legacy/components/Popup'
import { shouldShowItem } from './legacy/utils/itemsHelper'
import {
  mapBuyButtonItemToPixel,
  mapCartItemToPixel,
} from './modules/pixelHelper'
import fullMinicartQuery from './legacy/localState/graphql/fullMinicartQuery.gql'
import updateItemsMutation from './legacy/localState/graphql/updateItemsMutation.gql'
import updateOrderFormMutation from './legacy/localState/graphql/updateOrderFormMutation.gql'
import updateLocalItemStatusMutation from './legacy/localState/graphql/updateLocalItemStatusMutation.gql'
import setMinicartOpenMutation from './legacy/localState/graphql/setMinicartOpenMutation.gql'
import createLocalState, { ITEMS_STATUS } from './legacy/localState'
import styles from './legacy/minicart.css'
import useMarketingSessionParams from './legacy/hooks/useMarketingSessionParams'
import useCartIdPixel from './modules/useCartIdPixel'
import useViewCartPixel from './modules/useViewCartPixel'

const DEFAULT_LABEL_CLASSES = ''
const DEFAULT_ICON_CLASSES = 'gray'

const useOffline = () => {
  const [isOffline, setOffline] = useState(() =>
    typeof navigator !== 'undefined'
      ? !pathOr(true, ['onLine'], navigator)
      : false
  )

  useEffect(() => {
    const updateStatus = () => {
      if (navigator) {
        const offline = !pathOr(true, ['onLine'], navigator)
        setOffline(offline)
      }
    }

    window.addEventListener('online', updateStatus)
    window.addEventListener('offline', updateStatus)

    return () => {
      window.removeEventListener('online', updateStatus)
      window.removeEventListener('offline', updateStatus)
    }
  }, [])

  return isOffline
}

const useLinkState = client => {
  useEffect(() => {
    const { resolvers, initialState } = createLocalState(client)
    client.addResolvers(resolvers)
    // Add the initial state to if there is not there
    try {
      client.readQuery({ query: fullMinicartQuery })
    } catch (err) {
      client.writeData({ data: initialState })
    }

    const minicartData = JSON.parse(localStorage.getItem('minicart'))

    if (minicartData) {
      client.writeData({
        data: {
          minicart: {
            __typename: 'Minicart',
            items: JSON.stringify(minicartData),
          },
        },
      })
    }
  }, [client])
}

const useUpdateOrderFormOnState = (data, minicartState, updateOrderForm) => {
  // This ref guarantees that the first remote order form after mount will be saved on state, regardless of minicart state
  const hasSavedRemoteOrderFormRef = useRef(false)
  useEffect(
    () => {
      const updateLocalOrderForm = async () => {
        const orderFormData = JSON.parse(localStorage.getItem('orderForm'))

        const remoteOrderForm = data.orderForm

        if (remoteOrderForm || !orderFormData) {
          const forceRemoteOrderform =
            !hasSavedRemoteOrderFormRef.current && remoteOrderForm
          if (
            forceRemoteOrderform ||
            (!path(['orderForm'], minicartState) && remoteOrderForm)
          ) {
            hasSavedRemoteOrderFormRef.current = true
            await updateOrderForm(remoteOrderForm)
          }
        } else if (!path(['orderForm'], minicartState)) {
          await updateOrderForm(orderFormData)
        }
      }

      updateLocalOrderForm()
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [data, minicartState]
  )
}

const partitionItemsAddUpdate = clientItems => {
  return partition(compose(isNil, prop('cartIndex')), clientItems)
}

/**
 * Minicart component
 */
const MiniCart = ({
  labelClasses = DEFAULT_LABEL_CLASSES,
  iconClasses = DEFAULT_ICON_CLASSES,
  openOnHover = false,
  client,
  setMinicartOpen,
  labelMiniCartEmpty,
  linkButtonFinishShopping,
  labelButtonFinishShopping,
  iconSize,
  iconLabel,
  showTotalItemsQty,
  showPrice,
  showDiscount,
  data,
  linkState,
  type,
  hideContent,
  showShippingCost,
  updateOrderForm,
  intl,
  updateItemsMutation,
  addToCartMutation,
  updateLocalItemStatus,
  iconsProps,
}) => {
  useLinkState(client)

  const [isUpdatingOrderForm, setUpdatingOrderForm] = useState(false)
  const isOffline = useOffline()

  const {
    hints: { mobile },
    navigate,
  } = useRuntime()
  const { showToast } = useContext(ToastContext)

  const minicartState = linkState.minicart || {}

  const localOrderForm = useMemo(() => {
    try {
      return JSON.parse(minicartState.orderForm)
    } catch (e) {
      return undefined
    }
  }, [minicartState.orderForm])

  const orderForm = pathOr(localOrderForm, ['orderForm'], data)
  const orderFormId =
    orderForm && orderForm.orderFormId ? orderForm.orderFormId : undefined

  useCartIdPixel(orderFormId)

  const minicartItems = useMemo(() => {
    try {
      return JSON.parse(minicartState.items)
    } catch (e) {
      return []
    }
  }, [minicartState.items])

  const modifiedItems = useMemo(
    () =>
      minicartItems.filter(
        ({ localStatus }) => localStatus === ITEMS_STATUS.MODIFIED
      ),
    [minicartItems]
  )

  useUpdateOrderFormOnState(data, minicartState, updateOrderForm)

  // synchronize values with local storage
  useEffect(() => {
    if (orderForm) {
      localStorage.setItem('minicart', JSON.stringify(minicartItems))
      localStorage.setItem('orderForm', JSON.stringify(orderForm))
    }
  }, [minicartItems, orderForm])

  const { utmParams, utmiParams } = useMarketingSessionParams()

  const addItems = useCallback(
    items => {
      if (!items.length || !orderFormId) {
        return null
      }

      return addToCartMutation({
        variables: {
          orderFormId,
          items,
          ...(utmParams ? { utmParams } : {}),
          ...(utmiParams ? { utmiParams } : {}),
        },
      })
    },
    [orderFormId, addToCartMutation, utmParams, utmiParams]
  )

  const mutateUpdateItems = useCallback(
    items => {
      if (!items.length || !orderFormId) {
        return null
      }

      return updateItemsMutation({
        variables: { orderFormId, items },
      })
    },
    [orderFormId, updateItemsMutation]
  )

  const { push } = usePixel()

  const orderFormRef = useRef(orderForm)

  const { url: checkoutUrl } = useCheckoutURL()

  useEffect(() => {
    orderFormRef.current = orderForm
  }, [orderForm])

  useEffect(
    () => {
      if (!isOffline) {
        updateLocalItemStatus()
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [isOffline]
  )

  useEffect(
    () => {
      let isCurrent = true

      const syncItemsWithServer = async () => {
        if (!modifiedItems.length) {
          return
        }

        const prevOrderForm = orderFormRef.current

        try {
          setUpdatingOrderForm(true)

          const [itemsToAdd, itemsToUpdate] = partitionItemsAddUpdate(
            modifiedItems
          )
          const pickProps = map(
            pick(['id', 'index', 'quantity', 'seller', 'options'])
          )

          // server mutation
          const updateItemsResponse = await mutateUpdateItems(
            pickProps(itemsToUpdate)
          )

          // server mutation
          const addItemsResponse = await addItems(pickProps(itemsToAdd))

          if (itemsToAdd.length > 0) {
            push({
              event: 'addToCart',
              items: itemsToAdd.map(mapBuyButtonItemToPixel),
            })
          }

          if (!isCurrent) {
            return
          }

          const newOrderForm = pathOr(
            path(['data', 'updateItems'], updateItemsResponse),
            ['data', 'addItem'],
            addItemsResponse
          )

          push({
            event: 'cartChanged',
            items:
              newOrderForm && newOrderForm.items
                ? newOrderForm.items.map(mapCartItemToPixel)
                : [],
          })

          setUpdatingOrderForm(false)
          await updateOrderForm(newOrderForm, true)
        } catch (err) {
          // TODO: Toast error message into Alert
          console.error(err)

          if (!isCurrent) {
            return
          }

          // Rollback items and orderForm
          setUpdatingOrderForm(false)
          await updateOrderForm(prevOrderForm, true)

          showToast({
            message: intl.formatMessage({
              id: 'store/minicart.checkout-failure',
            }),
          })
        }
      }

      if (isOffline) {
        setUpdatingOrderForm(updating => (updating ? false : updating))
        return
      }

      syncItemsWithServer()

      return () => {
        isCurrent = false
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [
      intl,
      isOffline,
      showToast,
      addItems,
      mutateUpdateItems,
      modifiedItems,
      push,
    ]
  )

  const handleClickButton = event => {
    if (!hideContent) {
      setMinicartOpen(!minicartState.isOpen)
    }
    event.persist()
  }

  const handleUpdateContentVisibility = () => {
    setMinicartOpen(false)
  }

  const handleClickProduct = detailUrl => {
    setMinicartOpen(false)
    navigate({
      to: detailUrl,
    })
  }

  const getFilteredItems = () => {
    return minicartItems.filter(shouldShowItem)
  }

  const itemsToShow = getFilteredItems()
  const totalItemsSum = arr =>
    arr.reduce((sum, product) => sum + product.quantity, 0)
  const quantity = showTotalItemsQty
    ? totalItemsSum(itemsToShow)
    : itemsToShow.length

  const isSizeLarge =
    (type && type === 'sidebar') ||
    mobile ||
    (window && window.innerWidth <= 480)

  const isOpen = pathOr(false, ['isOpen'], minicartState)

  useViewCartPixel(isOpen, minicartItems)

  const miniCartContent = (
    <MiniCartContent
      isSizeLarge={isSizeLarge}
      itemsToShow={itemsToShow}
      orderForm={{
        ...orderForm,
        items: minicartItems,
      }}
      loading={data.loading}
      showDiscount={showDiscount}
      labelMiniCartEmpty={labelMiniCartEmpty}
      linkButton={linkButtonFinishShopping || checkoutUrl}
      labelButton={labelButtonFinishShopping}
      onClickProduct={handleClickProduct}
      onClickAction={handleUpdateContentVisibility}
      showShippingCost={showShippingCost}
      updatingOrderForm={isUpdatingOrderForm}
      iconsProps={iconsProps}
    />
  )

  const priceClasses = classNames(
    `${styles.label} dn-m db-l t-action--small ${labelClasses}`,
    {
      pl6: quantity > 0,
      pl4: quantity <= 0,
    }
  )

  const isPriceVisible = showPrice && orderForm && orderForm.value > 0
  const iconLabelClasses = classNames(
    `${styles.label} dn-m db-l ${
      isPriceVisible ? 't-mini' : 't-action--small'
    } ${labelClasses}`,
    {
      pl6: quantity > 0,
      pl4: quantity <= 0,
    }
  )

  // This feature should only work for the popup minicart
  const shouldOpenOnHover = openOnHover && !isSizeLarge

  return (
    <aside className={`${styles.container} relative fr flex items-center`}>
      <div
        onMouseEnter={
          shouldOpenOnHover ? () => setMinicartOpen(true) : undefined
        }
        className="flex flex-column"
      >
        <ButtonWithIcon
          icon={
            <span className={`relative ${iconClasses}`}>
              <IconCart size={iconSize} {...iconsProps} />
              {quantity > 0 && (
                <span
                  data-testid="item-qty"
                  className={`${styles.badge} c-on-emphasis absolute t-mini bg-emphasis br4 w1 h1 pa1 flex justify-center items-center lh-solid`}
                >
                  {quantity}
                </span>
              )}
            </span>
          }
          variation="tertiary"
          onClick={handleClickButton}
        >
          {(iconLabel || isPriceVisible) && (
            <span className="flex items-center">
              <span className="flex flex-column items-start">
                {iconLabel && (
                  <span className={iconLabelClasses}>{iconLabel}</span>
                )}
                {isPriceVisible && (
                  <span data-testid="total-price" className={priceClasses}>
                    <div>
                      <ProductPrice
                        showLabels={false}
                        showListPrice={false}
                        sellingPrice={orderForm.value}
                      />
                    </div>
                  </span>
                )}
              </span>
            </span>
          )}
        </ButtonWithIcon>
        {!hideContent &&
          (isSizeLarge ? (
            <Sidebar
              quantity={quantity}
              iconSize={iconSize}
              onOutsideClick={handleUpdateContentVisibility}
              isOpen={isOpen}
              iconsProps={iconsProps}
            >
              {miniCartContent}
            </Sidebar>
          ) : (
            isOpen && (
              <Popup onOutsideClick={handleUpdateContentVisibility}>
                {miniCartContent}
              </Popup>
            )
          ))}
      </div>
    </aside>
  )
}

const withLinkStateUpdateItemsMutation = graphql(updateItemsMutation, {
  name: 'updateLinkStateItems',
  props: ({ updateLinkStateItems }) => ({
    updateLinkStateItems: items =>
      updateLinkStateItems({ variables: { items } }),
  }),
})

const withLinkStateUpdateOrderFormMutation = graphql(updateOrderFormMutation, {
  name: 'updateOrderForm',
  props: ({ updateOrderForm }) => ({
    updateOrderForm: (orderForm, forceUpdateItems = false) =>
      updateOrderForm({ variables: { orderForm, forceUpdateItems } }),
  }),
})

const withLinkStateUpdateLocalItemStatusMutation = graphql(
  updateLocalItemStatusMutation,
  {
    name: 'updateLocalItemStatus',
  }
)

const withLinkStateSetIsOpenMutation = graphql(setMinicartOpenMutation, {
  name: 'setMinicartOpen',
  props: ({ setMinicartOpen }) => ({
    setMinicartOpen: isOpen => setMinicartOpen({ variables: { isOpen } }),
  }),
})

const EnhancedMinicart = compose(
  graphql(orderFormQuery, { options: { ssr: false } }),
  graphql(fullMinicartQuery, { name: 'linkState', ssr: false }),
  graphql(addToCart, { name: 'addToCartMutation' }),
  graphql(updateItems, { name: 'updateItemsMutation' }),
  withApollo,
  withLinkStateUpdateItemsMutation,
  withLinkStateUpdateOrderFormMutation,
  withLinkStateUpdateLocalItemStatusMutation,
  withLinkStateSetIsOpenMutation,
  injectIntl
)(MiniCart)

EnhancedMinicart.schema = {
  title: 'admin/editor.minicart.title',
  description: 'admin/editor.minicart.description',
  type: 'object',
  properties: {
    type: {
      title: 'admin/editor.minicart.type.title',
      type: 'string',
      default: 'popup',
      enum: ['popup', 'sidebar'],
      enumNames: [
        'admin/editor.minicart.type.popup',
        'admin/editor.minicart.type.sidebar',
      ],
      widget: {
        'ui:widget': 'radio',
        'ui:options': {
          inline: true,
        },
      },
      isLayout: true,
    },
    iconLabel: {
      title: 'admin/editor.minicart.iconLabel.title',
      type: 'string',
      isLayout: false,
    },
    showDiscount: {
      title: 'admin/editor.minicart.showDiscount.title',
      type: 'boolean',
      isLayout: true,
    },
    labelMiniCartEmpty: {
      title: 'admin/editor.minicart.labelMiniCartEmpty.title',
      type: 'string',
      isLayout: false,
    },
    linkButtonFinishShopping: {
      title: 'admin/editor.minicart.linkButtonFinishShopping.title',
      type: 'string',
      isLayout: false,
    },
    labelButtonFinishShopping: {
      title: 'admin/editor.minicart.labelButtonFinishShopping.title',
      type: 'string',
      isLayout: false,
    }
  },
}

export default EnhancedMinicart

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/BaseContent.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, {
  FC,
  useEffect,
  Children,
  ReactElement,
  Fragment,
  memo,
} from 'react'
import { FormattedMessage } from 'react-intl'
import {
  ExtensionPoint,
  useTreePath,
  useRuntime,
  RenderContext,
} from 'vtex.render-runtime'
import { useOrderForm } from 'vtex.order-manager/OrderForm'
import { CssHandlesTypes, useCssHandles } from 'vtex.css-handles'

import { useMinicartState } from './MinicartContext'
import styles from './styles.css'
import { mapCartItemToPixel } from './modules/pixelHelper'
import useDebouncedPush from './modules/debouncedPixelHook'
import CheckoutButton from './CheckoutButton'

const CSS_HANDLES = [
  'minicartContentContainer',
  'minicartProductListContainer',
  'minicartTitle',
  'minicartFooter',
] as const

interface Props {
  sideBarMode: boolean
  finishShoppingButtonLink: string
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

// eslint-disable-next-line react/display-name
const MinicartHeader: FC<{ minicartTitleHandle: string }> = memo(
  ({ minicartTitleHandle }) => (
    <h3
      className={`${minicartTitleHandle} t-heading-3 mv2 ph4 ph6-l c-on-base`}
    >
      <FormattedMessage id="store/minicart.title" />
    </h3>
  )
)

const Content: FC<Props> = ({
  finishShoppingButtonLink,
  classes,
  children,
}) => {
  const { orderForm, loading }: OrderFormContext = useOrderForm()
  const push = useDebouncedPush()
  const { handles } = useCssHandles(CSS_HANDLES, { classes })
  const { variation } = useMinicartState()
  const { extensions } = useRuntime() as RenderContext
  const { treePath } = useTreePath()

  useEffect(() => {
    if (loading) {
      return
    }

    // if additionalInfo is undefined for the most recent item, orderForm is still updating
    // and therefore we should not emit the pixel event yet
    if (
      orderForm.items.length > 0 &&
      orderForm.items[orderForm.items.length - 1].additionalInfo === undefined
    ) {
      return
    }

    push({
      event: 'cartChanged',
      items: orderForm.items.map(mapCartItemToPixel),
    })
  }, [push, loading, orderForm.items])

  const minicartContentClasses = `${handles.minicartContentContainer} ${
    variation === 'drawer' ? styles.drawerStyles : styles.popupStyles
  } flex flex-column justify-between`

  const minicartFooterClasses = `${handles.minicartFooter} ${
    variation === 'drawer' ? '' : 'pv3'
  } sticky`

  const isCartEmpty = !loading && orderForm.items.length === 0

  /**
   * The logic below is to check if the user provided the blocks
   * 'minicart-product-list' and 'minicart-summary' via 'blocks'
   * instead of 'children' in their implementation of 'minicart-base-content'.
   * The blocksFromUserImplementation variable represents the result of concatenating
   * the 'blocks' and the 'children' arrays from blocks.json.
   */
  const blocksFromUserImplementation = extensions[treePath].blocks
  const minicartBlocksFromUserImplementation = blocksFromUserImplementation?.filter(
    block =>
      !block.children &&
      (block.extensionPointId === 'minicart-product-list' ||
        block.extensionPointId === 'minicart-summary')
  )
  const shouldRenderUsingBlocks =
    minicartBlocksFromUserImplementation?.length === 2

  if (isCartEmpty) {
    return (
      <Fragment>
        <MinicartHeader minicartTitleHandle={handles.minicartTitle} />
        <ExtensionPoint id="minicart-empty-state" />
      </Fragment>
    )
  }

  if (shouldRenderUsingBlocks) {
    return (
      <div className={minicartContentClasses}>
        <div
          className={`w-100 h-100 overflow-y-auto ${handles.minicartProductListContainer}`}
        >
          <MinicartHeader minicartTitleHandle={handles.minicartTitle} />
          <ExtensionPoint id="minicart-product-list" />
        </div>
        <div className={minicartFooterClasses}>
          <ExtensionPoint id="minicart-summary" />
          <CheckoutButton finishShoppingButtonLink={finishShoppingButtonLink} />
        </div>
      </div>
    )
  }

  return (
    <div className={minicartContentClasses}>
      <MinicartHeader minicartTitleHandle={handles.minicartTitle} />
      {Children.map(children, child =>
        React.cloneElement(child as ReactElement, { renderAsChildren: true })
      )}
    </div>
  )
}

export default Content

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/EmptyState.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import { useCssHandles, CssHandlesTypes } from 'vtex.css-handles'

const CSS_HANDLES = ['minicartEmptyStateContainer'] as const

interface Props {
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

const EmptyState: FC<Props> = ({ classes, children }) => {
  const { handles } = useCssHandles(CSS_HANDLES, { classes })

  return (
    <div
      className={`${handles.minicartEmptyStateContainer} h-100 flex flex-column justify-center`}
    >
      {children}
    </div>
  )
}

export default EmptyState

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/CheckoutButton.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { FormattedMessage } from 'react-intl'
import { Button } from 'vtex.styleguide'
import { CssHandlesTypes, useCssHandles } from 'vtex.css-handles'
import { useCheckoutURL } from 'vtex.checkout-resources/Utils'

import useCheckout from './modules/checkoutHook'

const CSS_HANDLES = ['minicartCheckoutButton'] as const

interface Props {
  finishShoppingButtonLink: string
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

const CheckoutButton: StoreFunctionComponent<Props> = ({
  finishShoppingButtonLink,
  classes,
}): JSX.Element => {
  const { url: checkoutUrl } = useCheckoutURL()
  const { handles } = useCssHandles(CSS_HANDLES, { classes })
  const goToCheckout = useCheckout()

  return (
    <div className={`${handles.minicartCheckoutButton} mv3 ph4 ph6-l`}>
      <Button
        id="proceed-to-checkout"
        onClick={() => goToCheckout(finishShoppingButtonLink || checkoutUrl)}
        variation="primary"
        block
      >
        <FormattedMessage id="store/minicart.go-to-checkout" />
      </Button>
    </div>
  )
}

CheckoutButton.schema = {
  title: 'store/finish-shopping-button-label',
}

export default CheckoutButton

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/Summary.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import { ExtensionPoint } from 'vtex.render-runtime'
import { OrderForm as OrderFormComponent } from 'vtex.order-manager'
import { useCssHandles, CssHandlesTypes } from 'vtex.css-handles'

const CSS_HANDLES = ['minicartSummary'] as const

interface Props {
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

const Summary: FC<Props> = ({ classes }) => {
  const { useOrderForm } = OrderFormComponent

  const {
    orderForm: { totalizers, value, items, paymentData },
  } = useOrderForm()

  const { handles } = useCssHandles(CSS_HANDLES, { classes })

  const originalValue =
    items?.reduce(
      (total: number, item: OrderFormItem) =>
        (total as number) +
        ((item?.listPrice as number) ?? 0) * (item?.quantity ?? 1),
      0
    ) ?? 0

  return (
    <div className={`${handles.minicartSummary} ph4 ph6-l pt5`}>
      <ExtensionPoint
        id="checkout-summary"
        totalizers={totalizers}
        paymentData={paymentData}
        total={value}
        originalTotal={originalValue}
      />
    </div>
  )
}

export default Summary

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/store/blocks.jsonc from the minicart VTEX app.

[Assistant]
Here's the implementation:

```json
// This is the default blocks implementation for the minicart-layout
{
  "minicart.v2": {
    "children": ["minicart-base-content"]
  },
  "minicart-base-content": {
    "blocks": ["minicart-empty-state"],
    "children": ["minicart-product-list", "flex-layout.row#minicart-footer"]
  },
  "flex-layout.row#minicart-footer": {
    "props": {
      "blockClass": "minicart-footer"
    },
    "children": ["flex-layout.col#minicart-footer"]
  },
  "flex-layout.col#minicart-footer": {
    "children": ["minicart-summary", "minicart-checkout-button"]
  },
  "minicart-product-list": {
    "blocks": ["product-list#minicart"]
  },
  "product-list#minicart": {
    "blocks": ["product-list-content-mobile"]
  },
  "minicart-summary": {
    "blocks": ["checkout-summary.compact#minicart"]
  },

  "checkout-summary.compact#minicart": {
    "children": ["summary-totalizers#minicart"],
    "props": {
      "totalizersToShow": ["Items", "Discounts"]
    }
  },
  "summary-totalizers#minicart": {
    "props": {
      "showTotal": true,
      "showDeliveryTotal": false
    }
  },
  "minicart-empty-state": {
    "children": ["flex-layout.row#empty-state"]
  },
  "flex-layout.row#empty-state": {
    "children": ["flex-layout.col#empty-state"]
  },
  "flex-layout.col#empty-state": {
    "children": [
      "icon-cart#minicart-empty-state",
      "rich-text#minicart-default-empty-state"
    ],
    "props": {
      "horizontalAlign": "center",
      "verticalAlign": "middle",
      "rowGap": 5
    }
  },
  "icon-cart#minicart-empty-state": {
    "props": {
      "size": 64,
      "blockClass": "minicart-empty-state"
    }
  },
  "rich-text#minicart-default-empty-state": {
    "props": {
      "text": "Your cart is empty."
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/store/interfaces.json from the minicart VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "minicart": {
    "allowed": ["sandbox", "product-summary"],
    "component": "index"
  },
  "minicart.v2": {
    "component": "Minicart",
    "composition": "children"
  },
  "minicart-base-content": {
    "component": "BaseContent",
    "allowed": [
      "minicart-product-list",
      "minicart-summary",
      "minicart-empty-state"
    ],
    "composition": "children",
    "render": "lazy"
  },
  "minicart-product-list": {
    "component": "ProductList",
    "allowed": ["product-list"]
  },
  "minicart-checkout-button": {
    "component": "CheckoutButton",
    "content": {
      "title": "store/finish-shopping-button-label",
      "properties": {
        "finishShoppingButtonLink": {
          "type": "string",
          "title": "admin/editor.minicart.linkButtonFinishShopping.title",
          "default": "/checkout/#/cart"
        }
      }
    }
  },
  "minicart-summary": {
    "component": "Summary",
    "allowed": ["checkout-summary"],
    "render": "lazy"
  },
  "minicart-empty-state": {
    "component": "EmptyState",
    "composition": "children",
    "render": "lazy"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/styles/css/vtex.store-icons.css from the minicart VTEX app.

[Assistant]
Here's the implementation:

```css
.cartIcon--minicart-empty-state {
  color: #979899;
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/styles/css/vtex.flex-layout.css from the minicart VTEX app.

[Assistant]
Here's the implementation:

```css
.flexRow--minicart-footer {
  box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.15);
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/typings/OrderForm.ts from the minicart VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface OrderFormContext {
  orderForm: OrderForm
  loading: boolean
}

interface OrderFormItem {
  additionalInfo: ItemAdditionalInfo
  availability: string
  detailUrl: string
  id: string
  imageUrl: string
  listPrice: number
  measurementUnit: string
  name: string
  price: number
  productId: string
  quantity: number
  sellingPrice: number
  skuName: string
  skuSpecifications: SKUSpecification[]
  uniqueId: string
  productCategories: Record<string, string>
  productCategoryIds: string
  productRefId: string
  refId: string
  parentItemIndex: number | null
}

interface OrderFormItemWithIndex extends OrderFormItem {
  index: number
}

interface ItemAdditionalInfo {
  brandName: string
}

interface SKUSpecification {
  fieldName: string
  fieldValues: string[]
}

interface OrderForm {
  id: string
  items: OrderFormItem[]
  marketingData: MarketingData
  totalizers: Totalizer[]
  value: number
  messages: OrderFormMessages
}

interface MarketingData {
  coupon: string
}

interface Totalizer {
  id: string
  name: string
  value: number
}

interface OrderFormMessages {
  couponMessages: Message[]
  generalMessages: Message[]
}

interface Message {
  code: string
  status: string
  text: string
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/typings/vtex.store-drawer.d.ts from the minicart VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.store-drawer' {
  const Drawer: React.FC<any>
  type BackdropMode = 'visible' | 'none'
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/typings/css.ts from the minicart VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module '*.css' {
  const css: Record<string, string>
  export default css
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/typings/vtex.render-runtime.d.ts from the minicart VTEX app.

[Assistant]
Here's the implementation:

```typescript
export {}

declare module 'vtex.render-runtime' {
  export function useTreePath(): {
    treePath: string
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/typings/vtex.order-items.d.ts from the minicart VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.order-items'
declare module 'vtex.order-items/*'

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/typings/global.d.ts from the minicart VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { FC } from 'react'

declare global {
  interface StoreFunctionComponent<P = {}> extends FC<P> {
    schema?: object
  }

  type QuantityDisplayType = 'always' | 'never' | 'not-empty'

  type MinicartTotalItemsType =
    | 'total'
    | 'distinct'
    | 'totalAvailable'
    | 'distinctAvailable'

  type SlideDirectionType =
    | 'horizontal'
    | 'vertical'
    | 'rightToLeft'
    | 'leftToRight'

  type MinicartVariationType =
    | 'popup'
    | 'drawer'
    | 'link'
    | 'popupWithLink'
    | 'block'
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/legacy/minicart.css from the minicart VTEX app.

[Assistant]
Here's the implementation:

```css
.container {
}
.label {
}
.itemImage {
}
.item {
}
.itemContainer {
}
.itemDeleteIcon {
}
.itemDeleteIcon {
}
.itemDeleteIconLoader {
}
.content {
}
.contentDiscount {
}
.contentPrice {
}
.itemName {
}
.itemNameLarge {
}
.itemFooter {
}
.imgContainer {
}
.itemRemoveBtn {
}
.sidebarScrim {
}
.sidebarHeader {
}

.contentSmall {
  max-height: 383px;
}

.contentLarge {
  max-height: stretch;
}

.badge {
  top: -0.7rem;
  right: -0.8rem;
}

.arrowUp {
  right: 7px;
}

.box {
  width: 364px;
  top: 100%;
}

.itemImageLoader {
  width: 100%;
  height: 100%;
}

.contentFooter {
}

.footerSpacer {
}

.footerShippingPriceContainer {
}

.footerShippingPriceLabelContainer {
}

.popupContentContainer {
}

.popupChildrenContainer {
}

.sidebarRightCaretContainer {
}

.sidebarItemQuantityContainer {
}

.labelDiscountText{
}

@media only screen and (max-width: 40rem) {
  body.sidebarOpen {
    overflow: hidden;
  }
}

@media only screen and (min-width: 40em) {
  .sidebar {
    width: 340px;
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/components/DrawerMode.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import { Drawer, BackdropMode } from 'vtex.store-drawer'
import { ResponsiveValuesTypes } from 'vtex.responsive-values'
import { PixelEventTypes } from 'vtex.pixel-manager'

import MinicartIconButton from './MinicartIconButton'
import { useMinicartCssHandles } from './CssHandlesContext'

const DRAWER_CLOSE_ICON_HEIGHT = 58

export const CSS_HANDLES = ['minicartSideBarContentWrapper'] as const

interface Props {
  Icon: React.ComponentType
  maxDrawerWidth: number | string
  drawerSlideDirection: SlideDirectionType
  quantityDisplay: QuantityDisplayType
  itemCountMode: MinicartTotalItemsType
  backdropMode?: ResponsiveValuesTypes.ResponsiveValue<BackdropMode>
  customPixelEventId?: string
  customPixelEventName?: PixelEventTypes.EventName
  onVisibilityChanged?: (visible: boolean) => void
}

const DrawerMode: FC<Props> = ({
  Icon,
  children,
  maxDrawerWidth,
  quantityDisplay,
  itemCountMode,
  drawerSlideDirection,
  backdropMode = 'visible',
  customPixelEventId,
  customPixelEventName,
  onVisibilityChanged,
}) => {
  const { handles } = useMinicartCssHandles()

  return (
    <Drawer
      maxWidth={maxDrawerWidth}
      backdropMode={backdropMode}
      slideDirection={drawerSlideDirection}
      customPixelEventId={customPixelEventId}
      customPixelEventName={customPixelEventName}
      onVisibilityChanged={onVisibilityChanged}
      customIcon={
        <MinicartIconButton
          Icon={Icon}
          itemCountMode={itemCountMode}
          quantityDisplay={quantityDisplay}
        />
      }
    >
      <div
        className={`${handles.minicartSideBarContentWrapper} flex flex-column w-100 h-100`}
        style={{
          height: window.innerHeight - DRAWER_CLOSE_ICON_HEIGHT,
        }}
      >
        {children}
      </div>
    </Drawer>
  )
}

export default DrawerMode

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/components/Popup.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import { Overlay } from 'vtex.react-portal'
import { usePixelEventCallback, PixelEventTypes } from 'vtex.pixel-manager'

import MinicartIconButton from './MinicartIconButton'
import { useMinicartCssHandles } from './CssHandlesContext'
import { useMinicartState, useMinicartDispatch } from '../MinicartContext'
import styles from '../styles.css'

export const CSS_HANDLES = [
  'popupWrapper',
  'popupContentContainer',
  'arrowUp',
  'popupChildrenContainer',
] as const

interface Props {
  Icon: React.ComponentType
  quantityDisplay: QuantityDisplayType
  itemCountMode: MinicartTotalItemsType
  customPixelEventId?: string
  customPixelEventName?: PixelEventTypes.EventName
  variation?: string
}

const PopupMode: FC<Props> = props => {
  const {
    children,
    quantityDisplay,
    Icon,
    itemCountMode,
    customPixelEventId,
    customPixelEventName,
    variation,
  } = props

  const {
    open,
    openBehavior,
    hasBeenOpened,
    openOnHoverProp,
  } = useMinicartState()

  const dispatch = useMinicartDispatch()
  const { handles } = useMinicartCssHandles()

  usePixelEventCallback({
    eventId: customPixelEventId,
    eventName: customPixelEventName,
    handler: () => {
      dispatch({ type: 'OPEN_MINICART' })
    },
  })

  const handleClick = () => {
    if (openOnHoverProp) {
      dispatch({ type: 'SET_OPEN_BEHAVIOR', value: 'hover' })
    }

    dispatch({ type: 'CLOSE_MINICART' })
  }

  const handleMouseLeave = () => {
    dispatch({ type: 'CLOSE_MINICART' })
  }

  return (
    <div onMouseLeave={openBehavior === 'hover' ? handleMouseLeave : undefined}>
      <MinicartIconButton
        variation={variation}
        Icon={Icon}
        itemCountMode={itemCountMode}
        quantityDisplay={quantityDisplay}
      />
      {open && (
        <Overlay>
          {openBehavior === 'click' && (
            // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
            <div
              className="fixed top-0 left-0 w-100 h-100"
              onClick={handleClick}
            />
          )}
          <div
            className={`${handles.popupWrapper} ${styles.popupBoxPosition} absolute z-max flex flex-column`}
          >
            <div
              className={`${handles.popupContentContainer} w-100 shadow-3 bg-base`}
            >
              <div
                className={`${handles.arrowUp} ${styles.popupArrowUp} absolute top-0 bg-base h1 w1 pa4 rotate-45`}
              />
              <div
                className={`${handles.popupChildrenContainer} mt3 bg-base relative flex flex-column ph5 pv3`}
              >
                {hasBeenOpened && children}
              </div>
            </div>
          </div>
        </Overlay>
      )}
    </div>
  )
}

export default PopupMode

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/components/CssHandlesContext.ts from the minicart VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { createCssHandlesContext } from 'vtex.css-handles'

import { CSS_HANDLES as MinicartCssHandles } from '../Minicart'

const { CssHandlesProvider, useContextCssHandles } = createCssHandlesContext(
  MinicartCssHandles
)

export {
  CssHandlesProvider as MinicartCssHandlesProvider,
  useContextCssHandles as useMinicartCssHandles,
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/components/MinicartIconButton.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { ButtonWithIcon } from 'vtex.styleguide'
import { useOrderForm } from 'vtex.order-manager/OrderForm'
import { useCheckoutURL } from 'vtex.checkout-resources/Utils'

import styles from '../styles.css'
import { useMinicartCssHandles } from './CssHandlesContext'
import { useMinicartDispatch, useMinicartState } from '../MinicartContext'
import useCheckout from '../modules/checkoutHook'

export const CSS_HANDLES = [
  'minicartIconContainer',
  'minicartQuantityBadge',
] as const

interface Props {
  Icon: React.ComponentType
  quantityDisplay: QuantityDisplayType
  itemCountMode: MinicartTotalItemsType
  variation?: string
}

const countCartItems = (
  countMode: MinicartTotalItemsType,
  allItems: OrderFormItem[]
) => {
  // Filter only main products, remove assembly items from the count
  const items = allItems.filter(item => item.parentItemIndex === null)

  if (countMode === 'distinctAvailable') {
    return items.reduce((itemQuantity: number, item) => {
      if (item.availability === 'available') {
        return itemQuantity + 1
      }
      return itemQuantity
    }, 0)
  }

  if (countMode === 'totalAvailable') {
    return items.reduce((itemQuantity: number, item) => {
      if (item.availability === 'available') {
        return itemQuantity + item.quantity
      }
      return itemQuantity
    }, 0)
  }

  if (countMode === 'total') {
    return items.reduce((itemQuantity: number, item) => {
      return itemQuantity + item.quantity
    }, 0)
  }

  // countMode === 'distinct'
  return items.length
}

const MinicartIconButton: React.FC<Props> = props => {
  const { Icon, itemCountMode, quantityDisplay, variation } = props
  const { orderForm, loading }: OrderFormContext = useOrderForm()
  const { handles } = useMinicartCssHandles()
  const { open, openBehavior, openOnHoverProp } = useMinicartState()
  const dispatch = useMinicartDispatch()
  const quantity = countCartItems(itemCountMode, orderForm.items)
  const itemQuantity = loading ? 0 : quantity
  const { url: checkoutUrl } = useCheckoutURL()
  const goToCheckout = useCheckout()

  const handleClick = () => {
    if (openOnHoverProp) {
      if (variation === 'popupWithLink') {
        goToCheckout(checkoutUrl)
      }

      if (openBehavior === 'hover') {
        dispatch({
          type: 'SET_OPEN_BEHAVIOR',
          value: 'click',
        })

        return
      }
      dispatch({ type: 'CLOSE_MINICART' })
      dispatch({
        type: 'SET_OPEN_BEHAVIOR',
        value: 'hover',
      })

      return
    }

    dispatch({ type: open ? 'CLOSE_MINICART' : 'OPEN_MINICART' })
  }

  const showQuantityBadge =
    (itemQuantity > 0 && quantityDisplay === 'not-empty') ||
    quantityDisplay === 'always'

  return (
    <ButtonWithIcon
      icon={
        <span className={`${handles.minicartIconContainer} gray relative`}>
          <Icon />
          {showQuantityBadge && (
            <span
              style={{ userSelect: 'none' }}
              className={`${handles.minicartQuantityBadge} ${styles.minicartQuantityBadgeDefault} c-on-emphasis absolute t-mini bg-emphasis br4 w1 h1 pa1 flex justify-center items-center lh-solid`}
            >
              {itemQuantity}
            </span>
          )}
        </span>
      }
      variation="tertiary"
      onMouseEnter={
        openBehavior === 'hover'
          ? () => dispatch({ type: 'OPEN_MINICART' })
          : undefined
      }
      onClick={handleClick}
    />
  )
}

export default MinicartIconButton

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/modules/useCartIdPixel.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useEffect } from 'react'
import { usePixel } from 'vtex.pixel-manager'

const useCartIdPixel = (orderFormId?: string) => {
  const { push } = usePixel()

  useEffect(() => {
    if (!orderFormId) {
      return
    }

    push({
      event: 'cartId',
      cartId: orderFormId,
    })
  }, [push, orderFormId])
}

export default useCartIdPixel

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/modules/pixelHelper.ts from the minicart VTEX app.

[Assistant]
Here's the implementation:

```typescript
export function mapCartItemToPixel(item: CartItem): PixelCartItem {
  return {
    skuId: item.id,
    variant: item.skuName,
    price: item.sellingPrice,
    priceIsInt: true,
    name: getNameWithoutVariant(item),
    quantity: item.quantity,
    productId: item.productId,
    productRefId: item.productRefId,
    brand: item.additionalInfo ? item.additionalInfo.brandName : '',
    category: productCategory(item),
    detailUrl: item.detailUrl,
    imageUrl: item.imageUrls
      ? fixUrlProtocol(item.imageUrls.at3x)
      : item.imageUrl ?? '',
    referenceId: item.refId,
  }
}

export function mapBuyButtonItemToPixel(item: BuyButtonItem): PixelCartItem {
  // Change this `/Apparel & Accessories/Clothing/Tops/`
  // to this `Apparel & Accessories/Clothing/Tops`
  const category = item.category ? item.category.slice(1, -1) : ''

  return {
    skuId: item.id,
    variant: item.skuName,
    price: item.sellingPrice,
    priceIsInt: true,
    name: item.name,
    quantity: item.quantity,
    productId: item.productId,
    productRefId: item.productRefId,
    brand: item.brand,
    category,
    detailUrl: item.detailUrl,
    imageUrl: item.imageUrl,
    referenceId: item.refId,
  }
}

/**
 * URL comes like "//storecomponents.vteximg.com.br/arquivos/ids/155491"
 * this function guarantees it comes with protocol in it.
 */
function fixUrlProtocol(url: string) {
  if (!url || url.indexOf('http') === 0) {
    return url
  }

  return `https:${url}`
}

/**
 * Remove the variant from the end of the name.
 * Ex: from "Classic Shoes Pink" to "Classic Shoes"
 * Ps: Some products has the name of the variation the same as the item
 */
function getNameWithoutVariant(item: CartItem) {
  if (
    (item?.name && !item.name.includes(item.skuName)) ||
    item.name === item.skuName
  ) {
    return item.name
  }

  const leadingSpace = 1
  const variantLength = leadingSpace + item.skuName.length

  return item.name.slice(0, item.name.length - variantLength)
}

function productCategory(item: CartItem) {
  try {
    const categoryIds = item.productCategoryIds.split('/').filter(c => c.length)
    const category = categoryIds.map(id => item.productCategories[id]).join('/')

    return category
  } catch {
    return ''
  }
}

export function transformOrderFormItems(orderFormItems: OrderForm['items']) {
  if (!orderFormItems || !orderFormItems.length) return []
  return orderFormItems.map(item => mapCartItemToPixel(item))
}

export interface PixelCartItem {
  skuId: string
  variant: string
  price: number
  priceIsInt: boolean
  name: string
  quantity: number
  productId: string
  productRefId: string
  brand: string
  category: string
  detailUrl: string
  imageUrl: string
  referenceId: string
}

interface BuyButtonItem {
  id: string
  skuName: string
  sellingPrice: number
  name: string
  quantity: number
  productId: string
  productRefId: string
  brand: string
  category: string
  detailUrl: string
  imageUrl: string
  refId: string
}

interface CartItem {
  id: string
  skuName: string
  sellingPrice: number
  name: string
  quantity: number
  productId: string
  productRefId: string
  additionalInfo: {
    brandName: string
  }
  productCategoryIds: string
  productCategories: Record<string, string>
  detailUrl: string
  // Field from the usual orderForm API
  imageUrl?: string
  // Field from the order-manager orderForm API
  imageUrls?: {
    at1x: string
    at2x: string
    at3x: string
  }
  refId: string
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/modules/useViewCartPixel.tsx from the minicart VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useCallback, useEffect } from 'react'
import { usePixel } from 'vtex.pixel-manager'
import { debounce } from 'debounce'

import { PixelCartItem, transformOrderFormItems } from './pixelHelper'

const useViewCartPixel = (
  isOpen: boolean,
  orderFormItems: OrderForm['items']
) => {
  const { push } = usePixel()

  const transformedItems = transformOrderFormItems(orderFormItems)

  const pushViewCart = useCallback(
    debounce((items: PixelCartItem[]) => {
      push({
        event: 'viewCart',
        items,
      })
    }, 1000),
    [push]
  )

  useEffect(() => {
    if (!isOpen) {
      return
    }

    pushViewCart(transformedItems)
  }, [pushViewCart, isOpen, transformedItems])
}

export default useViewCartPixel

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/modules/debouncedPixelHook.ts from the minicart VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useRef } from 'react'
import { usePixel } from 'vtex.pixel-manager'
import debounce from 'debounce'

export default function useDebouncedPush() {
  const { push } = usePixel()
  const debouncedPush = useRef<typeof push>(debounce(push, 600))

  return debouncedPush.current
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/modules/checkoutHook.ts from the minicart VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useCheckoutURL } from 'vtex.checkout-resources/Utils'
import { useRuntime } from 'vtex.render-runtime'

export default function useCheckout() {
  const { url: checkoutUrl, major } = useCheckoutURL()
  const { navigate, rootPath = '' } = useRuntime()

  const goToCheckout = (url: string) => {
    if (major > 0 && url === checkoutUrl) {
      navigate({ to: url })
    } else {
      window.location.href = `${rootPath}${url}`
    }
  }

  return goToCheckout
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of minicart/react/legacy/__fixtures__/emptyOrderForm.js from the minicart VTEX app.

[Assistant]
Here's the implementation:

```javascript
export default {
  cacheId: '3335fe72057045398dd28bd2fa203b21',
  orderFormId: '3335fe72057045398dd28bd2fa203b21',
  value: 0,
  totalizers: [
    {
      id: 'Items',
      name: 'Items Total',
      value: 0,
      __typename: 'vtex_storegraphql_2_51_0_Totalizer',
    },
    {
      id: 'Shipping',
      name: 'Shipping Total',
      value: 0,
      __typename: 'vtex_storegraphql_2_51_0_Totalizer',
    },
  ],
  items: [],
  shippingData: {
    address: {
      id: null,
      neighborhood: 'Botafogo',
      complement: '',
      number: '300',
      street: 'Praia de Botafogo',
      postalCode: '22250-040',
      city: 'Rio de Janeiro',
      reference: null,
      addressName: null,
      addressType: 'residential',
      __typename: 'vtex_storegraphql_2_51_0_Address',
    },
    availableAddresses: [
      {
        id: null,
        neighborhood: 'Botafogo',
        complement: '',
        number: '300',
        street: 'Praia de Botafogo',
        postalCode: '22250-040',
        city: 'Rio de Janeiro',
        reference: null,
        addressName: null,
        addressType: 'residential',
        __typename: 'vtex_storegraphql_2_51_0_Address',
      },
    ],
    __typename: 'vtex_storegraphql_2_51_0_OrderFormShippingData',
  },
  clientProfileData: null,
  storePreferencesData: {
    countryCode: 'BRA',
    currencyCode: 'BRL',
    timeZone: 'E. South America Standard Time',
  },
  itemMetadata: {
    items: [],
  },
}

```