npm package: @meaple-com/react-headless-components
Description: Headless React components for Meaple SDK
Latest version: 2.0.1

# @meaple-com/react-headless-components

Headless React components for the [Meaple](https://meaple.com) ticketing platform. They handle data (via `@meaple-com/react-query`) and cart logic; you supply the UI with render props.

## Installation

```bash
npm install @meaple-com/react-headless-components @meaple-com/react-query @meaple-com/core @meaple-com/types
# or
pnpm add @meaple-com/react-headless-components @meaple-com/react-query @meaple-com/core @meaple-com/types
# or
bun add @meaple-com/react-headless-components @meaple-com/react-query @meaple-com/core @meaple-com/types
```

**Peer dependencies:**

- `react` ^19.0.0  
- `@meaple-com/react-query` ^1.0.6  

Make sure the app is wrapped with `QueryClientProvider` and `MeapleSDKProvider` as described in [@meaple-com/react-query](https://www.npmjs.com/package/@meaple-com/react-query).

## Setup: Cart and coupon

For checkout flows, wrap the relevant tree with `CartProvider`:

```tsx
import { CartProvider } from '@meaple-com/react-headless-components';

<CartProvider initialCoupon={null}>
  {/* Components that use Cart, Coupon, ListEventTickets, etc. */}
</CartProvider>
```

## Components

Components use a **render-props** API: they call `children` with data and state so you can render your own UI.

### Lists (read-only)

| Component | Description | Render props |
|-----------|-------------|--------------|
| **`ListEvents`** | List events (uses `useEvents`) | `events`, `isPending`, `error` |
| **`ListCategories`** | List categories | `categories`, `isPending`, `error` |
| **`ListEventTickets`** | Tickets for an event | `tickets`, `isPending`, `error` |
| **`ListEventProducts`** | Products for an event | `products`, `isPending`, `error` |
| **`ListUserEvents`** | Current user’s events | `events`, `isPending`, `error` |
| **`ListUserEventTickets`** | Current user’s tickets for an event | `tickets`, `isPending`, `error` |
| **`ListUserOrders`** | Current user’s orders | `orders`, `isPending`, `error` |

### Order and coupon

| Component | Description | Render props |
|-----------|-------------|--------------|
| **`GetOrder`** | Single order by ID | order data, `isPending`, `error` |
| **`Coupon`** | Check and apply coupon | mutation + coupon state |
| **`Cart`** | Cart totals, items, clear | `items`, `totalAmount`, `totalPrice`, `totalDiscount`, `clearCart`, etc. |
| **`TicketQuantityController`** | Add/remove ticket to/from cart | quantity controls (uses `useTicketQuantity`) |

### Hooks

- **`useCart()`** – Cart context (items, increment, decrement, clear, coupon, applyCoupon, computeItemDiscount). Use inside `CartProvider`.  
- **`useTicketQuantity(ticket, options?)`** – Quantity in cart for a ticket (and optional seat), plus increment/decrement.

## Example: Event list and cart

```tsx
import {
  ListEvents,
  ListEventTickets,
  Cart,
  CartProvider,
  TicketQuantityController,
} from '@meaple-com/react-headless-components';

function EventsPage() {
  return (
    <ListEvents params={{ limit: 10 }}>
      {({ events, isPending, error }) => {
        if (isPending) return <p>Loading...</p>;
        if (error) return <p>Error: {error.message}</p>;
        return (
          <ul>
            {events.map((e) => (
              <li key={e.id}>
                <a href={`/event/${e.id}/${e.slug}`}>{e.name}</a>
              </li>
            ))}
          </ul>
        );
      }}
    </ListEvents>
  );
}

function TicketSelection({ eventId, slug }) {
  return (
    <CartProvider initialCoupon={null}>
      <ListEventTickets eventId={eventId} slug={slug}>
        {({ tickets, isPending, error }) => (
          // ... render tickets, each wrapped in TicketQuantityController
        )}
      </ListEventTickets>

      <Cart>
        {({ items, totalPrice, clearCart }) => (
          <div>
            <p>Items: {items.length}, Total: {totalPrice}</p>
            <button onClick={clearCart}>Clear</button>
          </div>
        )}
      </Cart>
    </CartProvider>
  );
}
```

## Styling

These components do not ship styles. You style the UI inside the render props (CSS, Tailwind, CSS-in-JS, etc.).

## Documentation

[https://docs.meaple.com.br/](https://docs.meaple.com.br/)