# FunnelChart

> A marketing funnel chart with stages, counts, conversion and drop-off between steps, a breakdown by source or segment, and a list of saved funnels. Bars grow from the inline start, so it reads right to left in Arabic.

Source: https://docs.nasaqui.com/components/funnel-chart

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/funnel-chart.json
```

FunnelChart draws one bar per step, sized against the first step. Each row shows the count, the conversion from the previous step, the share of the first step that got this far and how many people dropped out. The step with the biggest drop is flagged. Pass `segments` to add a breakdown by source or segment underneath. FunnelList is the table of saved funnels with entrants, conversion and its trend.

## When to use

- Signup, checkout or campaign funnels.
- Comparing which source converts best.

## When not to use

- Time trends: use [`TimeSeriesPanel`](https://docs.nasaqui.com/components/time-series-panel).
- Creating or editing a funnel: use [`FunnelBuilder`](https://docs.nasaqui.com/components/funnel-builder).

## Import

```tsx
import { FunnelChart, FunnelList } from "@fadymondy/nasaq/web";
```

## Quick start

```tsx
import { FunnelChart } from "@fadymondy/nasaq/web";

<FunnelChart
  steps={[
    { id: "visit", label: "Visit", count: 12000 },
    { id: "signup", label: "Sign up", count: 3100 },
    { id: "paid", label: "Paid", count: 420 },
  ]}
/>;
```

## Anatomy

```
FunnelChart          data-slot="funnel-chart"
  header             title, description, action (for example a window select)
  step               label, detail, bar (inline-size), count, conversion, drop-off
  segments           BreakdownTable: segment, entered, converted, rate
FunnelList           data-slot="funnel-list"   (DataTable)
```

## API

### FunnelChart

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `steps` | `FunnelStep[]` | required | `{ id, label, count, detail? }`, in order. `detail` is an event name or path. |
| `title / description` | `ReactNode` | built-in | Header. |
| `segments` | `FunnelSegment[]` | none | `{ id, label, entered, converted }`. |
| `segmentLabel` | `ReactNode` | "Segment" | Heading of the segment column, for example "Source". |
| `action` | `ReactNode` | none | Header end slot. |
| `loading` | `boolean` | `false` | Skeleton. |
| `className / labels` | | none | Classes; `Partial<FunnelChartLabels>` strings. |

### FunnelList

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `funnels` | `FunnelSummary[]` | required | `{ id, name, steps, entered, conversion (0 to 1), window, updatedAt, previousConversion? }`. |
| `onOpen / onEdit` | `(id) => void` | none | Row click and actions. |
| `onCreate` | `() => void` | none | Shows a New funnel button. |
| `onDuplicate / onDelete` | `(id) => Promise<void \| { error?: string }>` | none | Row actions. |
| `title / description / pageSize / loading / error / onRetry / className / labels` | | | As in the other lists. |

### Helpers

`funnelRows(steps)` gives conversion from previous and first, dropped count and rate per step (never negative, safe with zeros). `overallConversion`, `biggestDropIndex` (-1 when nothing drops), `barWidth(count, max)` (0 to 1 with a small visible minimum), `windowMs`, `windowKey` (`7d`, `24h`, `2w`) and `moveStep`, `insertStep`, `removeStep`, which return new arrays.

## Examples

By source:

```tsx
import { FunnelChart } from "@fadymondy/nasaq/web";

<FunnelChart steps={steps} segmentLabel="Source" segments={[{ id: "g", label: "Google", entered: 6000, converted: 210 }, { id: "x", label: "Direct", entered: 2000, converted: 120 }]} />;
```

Saved funnels:

```tsx
import { FunnelList } from "@fadymondy/nasaq/web";

<FunnelList funnels={funnels} onOpen={(id) => navigate(`/funnels/${id}`)} onCreate={() => navigate("/funnels/new")} />;
```

## Accessibility

Each step is a list item that reads as "Step 2, Sign up, 3,100 people, 26% of the previous step, 8,900 dropped". The bar is decorative. The flagged drop has a text label, not only a colour.

## RTL & i18n

Bars use `inline-size` and start at the inline start, so in Arabic they grow from the right. Numbers use Latin digits. Event names and paths stay left-to-right. Built-in English and Arabic strings.

## Styling & tokens

Bars use the primary token with decreasing emphasis; the biggest drop uses the warning token. No hard-coded colours.

## Do / Don't

- Do keep steps in the order people actually go through them.
- Do state the time window next to the chart.
- Don't mix people and sessions in the same funnel.

## Related

- [FunnelBuilder](https://docs.nasaqui.com/components/funnel-builder)
- [BreakdownTable](https://docs.nasaqui.com/components/breakdown-table)

## Lab

https://docs.nasaqui.com/?path=/docs/components-analytics-funnel-chart--docs

## Code

### React

```tsx
import { FunnelChart } from "@fadymondy/nasaq/web";

<FunnelChart
  steps={[
    { id: "visit", label: "Visit", count: 12000 },
    { id: "signup", label: "Sign up", count: 3100 },
    { id: "paid", label: "Paid", count: 420 },
  ]}
/>;
```

### shadcn

```tsx
import { FunnelChart } from "@/components/ui/funnel-chart";

<FunnelChart
  steps={[
    { id: "visit", label: "Visit", count: 12000 },
    { id: "signup", label: "Sign up", count: 3100 },
    { id: "paid", label: "Paid", count: 420 },
  ]}
/>;
```

### Vue

```vue
<script setup lang="ts">
import { NqFunnelChart, NqFunnelList } from "@fadymondy/nasaq/vue";

const steps = [
  { id: "visit", label: "Visit", count: 12000, detail: "/" },
  { id: "signup", label: "Sign up", count: 3100, detail: "signup_completed" },
  { id: "activate", label: "Activate", count: 1480 },
  { id: "paid", label: "Paid", count: 420 },
];

const segments = [
  { id: "organic", label: "Organic search", entered: 5200, converted: 210 },
  { id: "paid-ads", label: "Paid ads", entered: 4100, converted: 130 },
  { id: "referral", label: "Referral", entered: 2700, converted: 80 },
];

const funnels = [
  { id: "f1", name: "Signup to paid", steps: 4, entered: 12000, conversion: 0.035, previousConversion: 0.031, window: "7 days", updatedAt: "2026-09-28" },
  { id: "f2", name: "Checkout", steps: 3, entered: 4800, conversion: 0.42, previousConversion: 0.45, window: "1 day", updatedAt: "2026-09-25" },
];
</script>

<template>
  <div class="grid gap-6">
    <NqFunnelChart :steps="steps" :segments="segments" segment-label="Source" />
    <NqFunnelList :funnels="funnels" :on-create="() => {}" :on-open="() => {}" :on-duplicate="async () => {}" :on-delete="async () => {}" />
  </div>
</template>
```

### Blade

```blade
@php
    $steps = [
        ['id' => 'visit', 'label' => 'Visit', 'count' => 12000, 'detail' => '/'],
        ['id' => 'signup', 'label' => 'Sign up', 'count' => 3100, 'detail' => 'signup_completed'],
        ['id' => 'activate', 'label' => 'Activate', 'count' => 1480],
        ['id' => 'paid', 'label' => 'Paid', 'count' => 420],
    ];
    $segments = [
        ['id' => 'organic', 'label' => 'Organic search', 'entered' => 5200, 'converted' => 210],
        ['id' => 'paid-ads', 'label' => 'Paid ads', 'entered' => 4100, 'converted' => 130],
        ['id' => 'referral', 'label' => 'Referral', 'entered' => 2700, 'converted' => 80],
    ];
    $funnels = [
        ['id' => 'f1', 'name' => 'Signup to paid', 'steps' => 4, 'entered' => 12000, 'conversion' => 0.035, 'previousConversion' => 0.031, 'window' => '7 days', 'updatedAt' => '2026-09-28'],
        ['id' => 'f2', 'name' => 'Checkout', 'steps' => 3, 'entered' => 4800, 'conversion' => 0.42, 'previousConversion' => 0.45, 'window' => '1 day', 'updatedAt' => '2026-09-25'],
        ['id' => 'f3', 'name' => 'Onboarding', 'steps' => 1, 'entered' => 900, 'conversion' => 0.8, 'window' => '30 days', 'updatedAt' => '2026-09-10'],
    ];
@endphp
<div class="grid gap-6">
    <x-nq::funnel-chart :steps="$steps" :segments="$segments" segment-label="Source" />
    <x-nq::funnel-chart.list :funnels="$funnels"
        x-on:open="window.__opened = $event.detail.id"
        x-on:create="window.__created = true"
        x-on:edit="window.__edited = $event.detail.id"
        x-on:duplicate="$event.detail.wait(Promise.resolve())"
        x-on:delete="$event.detail.wait(Promise.resolve())" />
</div>
```

### HTML + Alpine

```html
<div class="grid gap-6">
    <div data-slot="funnel-chart" class="flex w-full flex-col gap-4">
    <div data-slot="card" class="flex flex-col gap-4 rounded-card border border-border bg-card py-4 text-card-foreground"><div data-slot="card-header" class="grid auto-rows-min items-start gap-1 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto]"><h3 data-slot="card-title" class="text-label text-foreground">Conversion funnel</h3>
            <div data-slot="card-description" class="text-body-sm text-muted-foreground">How many people reach each step, and where they leave.</div></div>
        <div data-slot="card-content" class="px-4 flex flex-col gap-4"><div class="flex flex-wrap items-baseline gap-x-6 gap-y-1">
                    <div class="flex flex-col">
                        <span class="text-caption text-muted-foreground">Overall conversion</span>
                        <span class="text-heading-sm text-foreground" data-slot="funnel-overall"><bdi data-slot="num" data-numeric="" class="tabular-nums">3.5%</bdi>
</span>
                    </div>
                    <span class="text-body-sm text-muted-foreground">
                        Entered <bdi data-slot="num" data-numeric="" class="tabular-nums">12,000</bdi>
 · Completed <bdi data-slot="num" data-numeric="" class="tabular-nums">420</bdi>
                    </span>
                </div>
                <ol aria-label="Funnel steps" class="flex flex-col">
                                            <li data-slot="funnel-step" class="flex flex-col">
                                                        <div class="flex flex-col gap-1.5 rounded-card border border-border p-3">
                                <div class="flex items-baseline justify-between gap-3">
                                    <span class="flex min-w-0 flex-col">
                                        <span dir="auto" class="truncate text-label text-foreground">Visit</span>
                                        <bdi dir="ltr" class="truncate text-caption text-muted-foreground">/</bdi>                                    </span>
                                    <span class="flex shrink-0 flex-col items-end">
                                        <span class="text-label text-foreground"><bdi data-slot="num" data-numeric="" class="tabular-nums">12,000</bdi>
</span>
                                        <span class="text-caption text-muted-foreground"><bdi data-slot="num" data-numeric="" class="tabular-nums">100%</bdi>
 of first step</span>
                                    </span>
                                </div>
                                <div role="img" aria-label="Visit: 12,000 (100%)" class="h-3 w-full overflow-hidden rounded-full bg-muted">
                                    <div class="h-full rounded-full bg-primary" style="inline-size: 100%"></div>
                                </div>
                            </div>
                        </li>
                                            <li data-slot="funnel-step" class="flex flex-col">
                                                            <div class="flex items-center gap-2 py-1.5 ps-3 text-caption text-muted-foreground" data-slot="funnel-gap">
                                    <svg aria-hidden="true" class="size-3.5 shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12 5v14"/>
  <path d="m19 12-7 7-7-7"/>
</svg>                                    <span>26% continued</span>
                                    <span aria-hidden="true">·</span>
                                    <span class="text-nq-danger-text">8,900 left (74%)</span>
                                                                            <span data-slot="badge"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-nq-danger/40 bg-nq-danger-soft text-nq-danger-text"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/>
  <path d="M12 9v4"/>
  <path d="M12 17h.01"/>
</svg>Biggest drop</span>
                                                                    </div>
                                                        <div class="flex flex-col gap-1.5 rounded-card border border-border p-3">
                                <div class="flex items-baseline justify-between gap-3">
                                    <span class="flex min-w-0 flex-col">
                                        <span dir="auto" class="truncate text-label text-foreground">Sign up</span>
                                        <bdi dir="ltr" class="truncate text-caption text-muted-foreground">signup_completed</bdi>                                    </span>
                                    <span class="flex shrink-0 flex-col items-end">
                                        <span class="text-label text-foreground"><bdi data-slot="num" data-numeric="" class="tabular-nums">3,100</bdi>
</span>
                                        <span class="text-caption text-muted-foreground"><bdi data-slot="num" data-numeric="" class="tabular-nums">25.8%</bdi>
 of first step</span>
                                    </span>
                                </div>
                                <div role="img" aria-label="Sign up: 3,100 (26%)" class="h-3 w-full overflow-hidden rounded-full bg-muted">
                                    <div class="h-full rounded-full bg-primary" style="inline-size: 25.83%"></div>
                                </div>
                            </div>
                        </li>
                                            <li data-slot="funnel-step" class="flex flex-col">
                                                            <div class="flex items-center gap-2 py-1.5 ps-3 text-caption text-muted-foreground" data-slot="funnel-gap">
                                    <svg aria-hidden="true" class="size-3.5 shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12 5v14"/>
  <path d="m19 12-7 7-7-7"/>
</svg>                                    <span>48% continued</span>
                                    <span aria-hidden="true">·</span>
                                    <span class="">1,620 left (52%)</span>
                                                                    </div>
                                                        <div class="flex flex-col gap-1.5 rounded-card border border-border p-3">
                                <div class="flex items-baseline justify-between gap-3">
                                    <span class="flex min-w-0 flex-col">
                                        <span dir="auto" class="truncate text-label text-foreground">Activate</span>
                                                                            </span>
                                    <span class="flex shrink-0 flex-col items-end">
                                        <span class="text-label text-foreground"><bdi data-slot="num" data-numeric="" class="tabular-nums">1,480</bdi>
</span>
                                        <span class="text-caption text-muted-foreground"><bdi data-slot="num" data-numeric="" class="tabular-nums">12.3%</bdi>
 of first step</span>
                                    </span>
                                </div>
                                <div role="img" aria-label="Activate: 1,480 (12%)" class="h-3 w-full overflow-hidden rounded-full bg-muted">
                                    <div class="h-full rounded-full bg-primary" style="inline-size: 12.33%"></div>
                                </div>
                            </div>
                        </li>
                                            <li data-slot="funnel-step" class="flex flex-col">
                                                            <div class="flex items-center gap-2 py-1.5 ps-3 text-caption text-muted-foreground" data-slot="funnel-gap">
                                    <svg aria-hidden="true" class="size-3.5 shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12 5v14"/>
  <path d="m19 12-7 7-7-7"/>
</svg>                                    <span>28% continued</span>
                                    <span aria-hidden="true">·</span>
                                    <span class="">1,060 left (72%)</span>
                                                                    </div>
                                                        <div class="flex flex-col gap-1.5 rounded-card border border-border p-3">
                                <div class="flex items-baseline justify-between gap-3">
                                    <span class="flex min-w-0 flex-col">
                                        <span dir="auto" class="truncate text-label text-foreground">Paid</span>
                                                                            </span>
                                    <span class="flex shrink-0 flex-col items-end">
                                        <span class="text-label text-foreground"><bdi data-slot="num" data-numeric="" class="tabular-nums">420</bdi>
</span>
                                        <span class="text-caption text-muted-foreground"><bdi data-slot="num" data-numeric="" class="tabular-nums">3.5%</bdi>
 of first step</span>
                                    </span>
                                </div>
                                <div role="img" aria-label="Paid: 420 (3.5%)" class="h-3 w-full overflow-hidden rounded-full bg-muted">
                                    <div class="h-full rounded-full bg-primary" style="inline-size: 3.5%"></div>
                                </div>
                            </div>
                        </li>
                                    </ol></div></div>
            <div data-slot="breakdown-table"      class="flex flex-col gap-4 rounded-card border border-border bg-card py-4 text-card-foreground">
            <div data-slot="card-header" class="grid auto-rows-min items-start gap-1 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto]"><h3 data-slot="card-title" class="text-label text-foreground">Conversion by segment</h3>
            <div data-slot="card-description" class="text-body-sm text-muted-foreground">The same funnel split by who came in.</div></div>
        <div data-slot="card-content" class="px-0"><div data-slot="table-container" role="region" tabindex="0"  aria-label="Conversion by segment"     class="relative w-full overflow-x-auto outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus">
    <table data-slot="table" data-density="default"
                  class="w-full caption-bottom border-collapse text-body-sm">
        <thead data-slot="table-header" class="[&_tr]:border-b [&_tr]:hover:bg-transparent [&_tr]:even:bg-transparent"><tr data-slot="table-row"     class="border-b border-border transition-colors duration-150 ease-nq hover:bg-nq-hover data-[state=selected]:bg-nq-selected"><th data-slot="table-head" scope="col" class="h-row text-start align-middle text-caption font-medium whitespace-nowrap text-muted-foreground px-4 py-3">Source</th>
                        <th data-slot="table-head" scope="col" class="h-row align-middle text-caption font-medium whitespace-nowrap text-muted-foreground px-4 py-3 text-end">Converted</th>
                                                                                                    <th data-slot="table-head" scope="col" class="h-row align-middle text-caption font-medium whitespace-nowrap text-muted-foreground px-4 py-3 text-end">Conversion</th></tr></thead>
                <tbody data-slot="table-body" class="[&_tr:last-child]:border-0"><tr data-slot="table-row"     data-row="organic" class="border-b border-border transition-colors duration-150 ease-nq hover:bg-nq-hover data-[state=selected]:bg-nq-selected"><td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 min-w-40 max-w-0 sm:min-w-56"><span class="block truncate" dir="auto">Organic search</span>
                                                                                                <span aria-hidden="true" data-slot="breakdown-bar" class="mt-1.5 block h-1.5 rounded-full bg-nq-surface-soft">
                                    <span class="block h-full rounded-full bg-[var(--bar)]" style="--bar: var(--primary); width: 100%"></span>
                                </span></td>
                            <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 text-end tabular-nums"><bdi data-slot="num" data-numeric="" class="tabular-nums">210</bdi></td>
                                                                                                                    <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 text-end tabular-nums">4%</td></tr>
                                                                    <tr data-slot="table-row"     data-row="paid-ads" class="border-b border-border transition-colors duration-150 ease-nq hover:bg-nq-hover data-[state=selected]:bg-nq-selected"><td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 min-w-40 max-w-0 sm:min-w-56"><span class="block truncate" dir="auto">Paid ads</span>
                                                                                                <span aria-hidden="true" data-slot="breakdown-bar" class="mt-1.5 block h-1.5 rounded-full bg-nq-surface-soft">
                                    <span class="block h-full rounded-full bg-[var(--bar)]" style="--bar: var(--primary); width: 61.9048%"></span>
                                </span></td>
                            <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 text-end tabular-nums"><bdi data-slot="num" data-numeric="" class="tabular-nums">130</bdi></td>
                                                                                                                    <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 text-end tabular-nums">3.2%</td></tr>
                                                                    <tr data-slot="table-row"     data-row="referral" class="border-b border-border transition-colors duration-150 ease-nq hover:bg-nq-hover data-[state=selected]:bg-nq-selected"><td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 min-w-40 max-w-0 sm:min-w-56"><span class="block truncate" dir="auto">Referral</span>
                                                                                                <span aria-hidden="true" data-slot="breakdown-bar" class="mt-1.5 block h-1.5 rounded-full bg-nq-surface-soft">
                                    <span class="block h-full rounded-full bg-[var(--bar)]" style="--bar: var(--primary); width: 38.0952%"></span>
                                </span></td>
                            <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 text-end tabular-nums"><bdi data-slot="num" data-numeric="" class="tabular-nums">80</bdi></td>
                                                                                                                    <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 text-end tabular-nums">3%</td></tr></tbody>
    </table>
</div></div>
</div>
    </div>
    <div data-slot="funnel-list" x-data="nqFunnelList(JSON.parse('{\u0022rows\u0022:[{\u0022id\u0022:\u0022f1\u0022,\u0022name\u0022:\u0022Signup to paid\u0022,\u0022steps\u0022:\u00224 steps\u0022,\u0022entered\u0022:12000,\u0022conversion\u0022:\u00223.5% (+0.4)\u0022,\u0022conversionValue\u0022:0.035,\u0022window\u0022:\u00227 days\u0022,\u0022updated\u0022:\u00222026-09-28\u0022},{\u0022id\u0022:\u0022f2\u0022,\u0022name\u0022:\u0022Checkout\u0022,\u0022steps\u0022:\u00223 steps\u0022,\u0022entered\u0022:4800,\u0022conversion\u0022:\u002242.0% (-3.0)\u0022,\u0022conversionValue\u0022:0.42,\u0022window\u0022:\u00221 day\u0022,\u0022updated\u0022:\u00222026-09-25\u0022},{\u0022id\u0022:\u0022f3\u0022,\u0022name\u0022:\u0022Onboarding\u0022,\u0022steps\u0022:\u00221 step\u0022,\u0022entered\u0022:900,\u0022conversion\u0022:\u002280.0%\u0022,\u0022conversionValue\u0022:0.8,\u0022window\u0022:\u002230 days\u0022,\u0022updated\u0022:\u00222026-09-10\u0022}],\u0022labels\u0022:{\u0022failed\u0022:\u0022Could not do that. Try again.\u0022}}'))"
    x-on:nq-data-table-action="onAction($event)" x-on:nq-data-table-row-click="onRow($event)"
    x-on:open="window.__opened = $event.detail.id" x-on:create="window.__created = true" x-on:edit="window.__edited = $event.detail.id" x-on:duplicate="$event.detail.wait(Promise.resolve())" x-on:delete="$event.detail.wait(Promise.resolve())" class="flex flex-col gap-4 rounded-card border border-border bg-card py-4 text-card-foreground">
    <div data-slot="card-header" class="grid auto-rows-min items-start gap-1 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto]"><h3 data-slot="card-title" class="text-label text-foreground">Funnels</h3>
        <div data-slot="card-description" class="text-body-sm text-muted-foreground">Saved funnels and how each one converts right now.</div>
                    <div data-slot="card-action" class="col-start-2 row-span-2 row-start-1 self-start justify-self-end"><button data-slot="button"
     type="button"                         x-on:click="$el.dispatchEvent(new CustomEvent(&#039;create&#039;, { bubbles: true }))" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>                    New funnel</button></div></div>
    <div data-slot="card-content" class="px-4 flex flex-col gap-3"><template x-if="notice">
            <div data-slot="alert" data-tone="danger" role="alert"
     x-data="nqAlert()" x-modelable="open" x-show="open"     x-on:nq:dismiss="notice = null" class="relative grid grid-cols-[auto_1fr_auto] items-start gap-x-3 rounded-card border p-3 text-start border-nq-danger/30 bg-nq-danger-soft">
    <svg aria-hidden="true" data-slot="alert-icon" class="mt-0.5 size-4 text-nq-danger-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="10"/>
  <path d="m15 9-6 6"/>
  <path d="m9 9 6 6"/>
</svg>    <div data-slot="alert-body" class="flex min-w-0 flex-col gap-0.5">
                            <div data-slot="alert-description" class="text-body-sm text-foreground"><span x-text="notice"></span></div>
            </div>
            <div data-slot="alert-actions" class="ms-3 flex items-center gap-1">
                            <button data-slot="button"
     type="button"                         aria-label="Dismiss" x-on:click="dismiss()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 hover:bg-nq-hover size-control-sm p-0 text-muted-foreground [&_svg]:size-3.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                    </div>
    </div>
        </template>
        <div data-slot="data-table" x-data="nqDataTable(JSON.parse('[{\u0022id\u0022:\u0022f1\u0022,\u0022name\u0022:\u0022Signup to paid\u0022,\u0022steps\u0022:\u00224 steps\u0022,\u0022entered\u0022:12000,\u0022conversion\u0022:\u00223.5% (+0.4)\u0022,\u0022conversionValue\u0022:0.035,\u0022window\u0022:\u00227 days\u0022,\u0022updated\u0022:\u00222026-09-28\u0022},{\u0022id\u0022:\u0022f2\u0022,\u0022name\u0022:\u0022Checkout\u0022,\u0022steps\u0022:\u00223 steps\u0022,\u0022entered\u0022:4800,\u0022conversion\u0022:\u002242.0% (-3.0)\u0022,\u0022conversionValue\u0022:0.42,\u0022window\u0022:\u00221 day\u0022,\u0022updated\u0022:\u00222026-09-25\u0022},{\u0022id\u0022:\u0022f3\u0022,\u0022name\u0022:\u0022Onboarding\u0022,\u0022steps\u0022:\u00221 step\u0022,\u0022entered\u0022:900,\u0022conversion\u0022:\u002280.0%\u0022,\u0022conversionValue\u0022:0.8,\u0022window\u0022:\u002230 days\u0022,\u0022updated\u0022:\u00222026-09-10\u0022}]'), JSON.parse('[{\u0022id\u0022:\u0022name\u0022,\u0022header\u0022:\u0022Funnel\u0022,\u0022sortable\u0022:true,\u0022searchable\u0022:true,\u0022hideable\u0022:false,\u0022type\u0022:\u0022text\u0022},{\u0022id\u0022:\u0022steps\u0022,\u0022header\u0022:\u0022Steps\u0022,\u0022align\u0022:\u0022end\u0022,\u0022type\u0022:\u0022text\u0022},{\u0022id\u0022:\u0022entered\u0022,\u0022header\u0022:\u0022Entered\u0022,\u0022type\u0022:\u0022number\u0022,\u0022sortable\u0022:true,\u0022align\u0022:\u0022end\u0022},{\u0022id\u0022:\u0022conversion\u0022,\u0022header\u0022:\u0022Conversion\u0022,\u0022sortable\u0022:true,\u0022sortKey\u0022:\u0022conversionValue\u0022,\u0022align\u0022:\u0022end\u0022,\u0022type\u0022:\u0022text\u0022},{\u0022id\u0022:\u0022window\u0022,\u0022header\u0022:\u0022Window\u0022,\u0022sortable\u0022:true,\u0022type\u0022:\u0022text\u0022},{\u0022id\u0022:\u0022updated\u0022,\u0022header\u0022:\u0022Updated\u0022,\u0022type\u0022:\u0022date\u0022,\u0022sortable\u0022:true}]'), JSON.parse('{\u0022pageSize\u0022:8,\u0022locale\u0022:\u0022en\u0022,\u0022actions\u0022:[{\u0022id\u0022:\u0022edit\u0022},{\u0022id\u0022:\u0022duplicate\u0022},{\u0022id\u0022:\u0022delete\u0022,\u0022group\u0022:\u0022danger\u0022}],\u0022labels\u0022:{\u0022selectRow\u0022:\u0022Select {name}\u0022,\u0022rowActions\u0022:\u0022Actions for {name}\u0022,\u0022selected\u0022:\u0022{n} selected\u0022,\u0022range\u0022:\u0022{from}\\u2013{to} of {total}\u0022,\u0022editCell\u0022:\u0022{column}, {row}\u0022,\u0022invalidNumber\u0022:\u0022Enter a number\u0022,\u0022invalidDate\u0022:\u0022Enter a date\u0022,\u0022saving\u0022:\u0022Saving\\u2026\u0022,\u0022saved\u0022:\u0022Saved\u0022,\u0022saveFailed\u0022:\u0022Couldn\\u0027t save the change\u0022,\u0022saveFailedFor\u0022:\u0022Couldn\\u0027t save: {message}\u0022,\u0022expandRow\u0022:\u0022Show details for {name}\u0022,\u0022details\u0022:\u0022Details for {name}\u0022,\u0022ascending\u0022:\u0022ascending\u0022,\u0022descending\u0022:\u0022descending\u0022,\u0022rangeAtLeast\u0022:\u0022\\u2265 {v}\u0022,\u0022rangeAtMost\u0022:\u0022\\u2264 {v}\u0022,\u0022sortPriority\u0022:\u0022sort {n}, {dir}\u0022}}'))" x-modelable="rows"
    x-model="tableRows" class="flex min-w-0 flex-col gap-3">
            <div data-slot="data-table-toolbar" class="flex flex-wrap items-center gap-2">
                            <div data-slot="data-table-search" class="relative w-full sm:w-64">
                    <svg aria-hidden="true" class="pointer-events-none absolute start-2.5 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m21 21-4.34-4.34"/>
  <circle cx="11" cy="11" r="8"/>
</svg>                    <input data-slot="input" type="search"
                    x-model="query" x-on:keydown.escape="if (query) { $event.preventDefault(); query = &#039;&#039; }" placeholder="Filter funnels…" aria-label="Filter funnels…" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control-sm ps-8 pe-8 text-body-sm [&::-webkit-search-cancel-button]:hidden">
                    <button type="button" x-show="query" aria-label="Clear search" x-on:click="query = ''" style="display: none"
                        class="absolute end-1.5 top-1/2 inline-flex size-5 -translate-y-1/2 items-center justify-center rounded-full text-muted-foreground outline-none hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus">
                        <svg aria-hidden="true" class="size-3.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg>                    </button>
                </div>
                    </div>
    <div data-slot="table-container" role="region" tabindex="0" aria-label="Funnels"                 class="relative w-full overflow-x-auto outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus">
        <div data-slot="table" role="table" aria-label="Funnels"  x-bind:style="'grid-template-columns: repeat(' + (shownCount() + 1) + ', auto)'"  x-bind:data-density="density"               class="grid w-full min-w-max text-body-sm">
            <div data-slot="table-header" role="rowgroup" class="contents">
                <div role="row" data-slot="table-row" class="col-span-full grid grid-cols-subgrid border-b border-border">
                                                                                                            <div role="columnheader" data-slot="table-head" data-col="name" x-show="shown['name']"  x-bind:class="pad"  x-bind:aria-sort="ariaSort('name')"                             class="flex items-center h-row text-start align-middle text-caption font-medium whitespace-nowrap text-muted-foreground">
                                                            <button type="button"  x-on:click="toggleSort('name', $event.shiftKey)"
                                    x-bind:class="sortOf('name') ? 'text-foreground' : ''"
                                    class="-mx-1.5 inline-flex h-7 max-w-full items-center gap-1 rounded-control px-1.5 outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus ">
                                    <span >Funnel</span>
                                    <svg aria-hidden="true" x-show="! sortOf('name')" class="size-3.5 shrink-0 opacity-40" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg>                                    <x-lucide-arrow-up aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('name') === 'asc'" style="display: none" />
                                    <x-lucide-arrow-down aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('name') === 'desc'" style="display: none" />
                                                                    </button>
                                                                                </div>
                                                                    <div role="columnheader" data-slot="table-head" data-col="steps" x-show="shown['steps']"  x-bind:class="pad"                             class="flex items-center h-row text-end justify-end align-middle text-caption font-medium whitespace-nowrap text-muted-foreground">
                                                            Steps
                                                                                </div>
                                                                    <div role="columnheader" data-slot="table-head" data-col="entered" x-show="shown['entered']"  x-bind:class="pad"  x-bind:aria-sort="ariaSort('entered')"                             class="flex items-center h-row text-end justify-end align-middle text-caption font-medium whitespace-nowrap text-muted-foreground">
                                                            <button type="button"  x-on:click="toggleSort('entered', $event.shiftKey)"
                                    x-bind:class="sortOf('entered') ? 'text-foreground' : ''"
                                    class="-mx-1.5 inline-flex h-7 max-w-full items-center gap-1 rounded-control px-1.5 outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus flex-row-reverse">
                                    <span >Entered</span>
                                    <svg aria-hidden="true" x-show="! sortOf('entered')" class="size-3.5 shrink-0 opacity-40" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg>                                    <x-lucide-arrow-up aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('entered') === 'asc'" style="display: none" />
                                    <x-lucide-arrow-down aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('entered') === 'desc'" style="display: none" />
                                                                    </button>
                                                                                </div>
                                                                    <div role="columnheader" data-slot="table-head" data-col="conversion" x-show="shown['conversion']"  x-bind:class="pad"  x-bind:aria-sort="ariaSort('conversion')"                             class="flex items-center h-row text-end justify-end align-middle text-caption font-medium whitespace-nowrap text-muted-foreground">
                                                            <button type="button"  x-on:click="toggleSort('conversion', $event.shiftKey)"
                                    x-bind:class="sortOf('conversion') ? 'text-foreground' : ''"
                                    class="-mx-1.5 inline-flex h-7 max-w-full items-center gap-1 rounded-control px-1.5 outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus flex-row-reverse">
                                    <span >Conversion</span>
                                    <svg aria-hidden="true" x-show="! sortOf('conversion')" class="size-3.5 shrink-0 opacity-40" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg>                                    <x-lucide-arrow-up aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('conversion') === 'asc'" style="display: none" />
                                    <x-lucide-arrow-down aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('conversion') === 'desc'" style="display: none" />
                                                                    </button>
                                                                                </div>
                                                                    <div role="columnheader" data-slot="table-head" data-col="window" x-show="shown['window']"  x-bind:class="pad"  x-bind:aria-sort="ariaSort('window')"                             class="flex items-center h-row text-start align-middle text-caption font-medium whitespace-nowrap text-muted-foreground">
                                                            <button type="button"  x-on:click="toggleSort('window', $event.shiftKey)"
                                    x-bind:class="sortOf('window') ? 'text-foreground' : ''"
                                    class="-mx-1.5 inline-flex h-7 max-w-full items-center gap-1 rounded-control px-1.5 outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus ">
                                    <span >Window</span>
                                    <svg aria-hidden="true" x-show="! sortOf('window')" class="size-3.5 shrink-0 opacity-40" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg>                                    <x-lucide-arrow-up aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('window') === 'asc'" style="display: none" />
                                    <x-lucide-arrow-down aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('window') === 'desc'" style="display: none" />
                                                                    </button>
                                                                                </div>
                                                                    <div role="columnheader" data-slot="table-head" data-col="updated" x-show="shown['updated']"  x-bind:class="pad"  x-bind:aria-sort="ariaSort('updated')"                             class="flex items-center h-row text-start align-middle text-caption font-medium whitespace-nowrap text-muted-foreground">
                                                            <button type="button"  x-on:click="toggleSort('updated', $event.shiftKey)"
                                    x-bind:class="sortOf('updated') ? 'text-foreground' : ''"
                                    class="-mx-1.5 inline-flex h-7 max-w-full items-center gap-1 rounded-control px-1.5 outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus ">
                                    <span >Updated</span>
                                    <svg aria-hidden="true" x-show="! sortOf('updated')" class="size-3.5 shrink-0 opacity-40" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg>                                    <x-lucide-arrow-up aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('updated') === 'asc'" style="display: none" />
                                    <x-lucide-arrow-down aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('updated') === 'desc'" style="display: none" />
                                                                    </button>
                                                                                </div>
                                                                <div role="columnheader" data-slot="table-head"  x-bind:class="pad" class="flex items-center h-row w-12 text-start align-middle text-caption font-medium whitespace-nowrap text-muted-foreground"><span class="sr-only">Actions</span></div>
                                    </div>
            </div>
                            <div role="rowgroup" class="contents" data-slot="table-body" x-show="rowCount === 0" style="display: none">
                    <div role="row" data-slot="table-row" class="col-span-full grid grid-cols-subgrid border-0">
                        <div role="cell" data-slot="table-cell" class="col-span-full h-auto p-0 whitespace-normal">
                            <div x-show="isFiltered" style="display: none">
                                <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border-dashed border-border px-6 py-12 text-center rounded-card border-0">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m21 21-4.34-4.34"/>
  <circle cx="11" cy="11" r="8"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">No matching results</p>
                    <p class="text-body-sm text-muted-foreground">Try a different search or clear the filters.</p>
            </div>
    <button type="button" x-on:click="resetFilters()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-border bg-card text-foreground font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none hover:bg-nq-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus [&amp;_svg]:pointer-events-none [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 h-control-sm px-2.5">Clear filters</button>
    </div>
                            </div>
                            <div x-show="! isFiltered" style="display: none">
                                <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border-dashed border-border px-6 py-12 text-center rounded-card border-0">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/>
  <path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">No funnels yet</p>
            </div>
    </div>
                            </div>
                        </div>
                    </div>
                </div>
                <template x-for="(row, index) in pageRows" x-bind:key="rid(row)">
                    <div role="rowgroup" class="contents" data-slot="table-body">
                        <div role="row" data-slot="table-row" data-row tabindex="-1" x-bind:tabindex="index === Math.min(active, pageRows.length - 1) ? 0 : -1"
                            x-bind:data-state="isSelected(row) ? 'selected' : null" x-bind:aria-selected="isSelected(row) ? 'true' : null"
                            x-bind:aria-expanded="canExpand(row) ? String(isOpen(row)) : null" x-on:focus="if ($event.target === $event.currentTarget) active = index"
                            x-on:keydown="rowKey($event, row, index, true)"
                             x-on:contextmenu="rowContext(row, $event)" x-on:touchstart.passive="rowTouch(row, $event)" x-on:touchmove.passive="rowTouchEnd()" x-on:touchend="rowTouchEnd()" x-on:touchcancel="rowTouchEnd()"                              x-on:click="rowClick(row, $event)"                             x-bind:class="(isOpen(row) ? 'border-b-0 ' : '') + (ctxOpen && ctxRow === row ? 'bg-nq-hover' : '')"
                            class="col-span-full grid grid-cols-subgrid group/row border-b border-border outline-none transition-colors duration-150 ease-nq focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus data-[state=selected]:bg-nq-selected hover:bg-nq-hover cursor-pointer">
                                                                                            <div role="cell" data-slot="table-cell" data-cell-col="name" x-show="shown['name']"  x-bind:class="pad"
                                                                        class="flex items-center relative h-row align-middle whitespace-nowrap  ">
                                                                                                                    <span  class="flex min-w-0 items-center gap-1.5 " >
                                                                                            <span class="min-w-0 flex-1  " x-text="shownText(row, col(&#039;name&#039;))"></span>
                                                                                                                                </span>
                                                                    </div>
                                                                                            <div role="cell" data-slot="table-cell" data-cell-col="steps" x-show="shown['steps']"  x-bind:class="pad"
                                                                        class="flex items-center relative h-row align-middle whitespace-nowrap text-end justify-end ">
                                                                                                                    <span  class="flex min-w-0 items-center gap-1.5 justify-end" >
                                                                                            <span class="min-w-0 flex-1  " x-text="shownText(row, col(&#039;steps&#039;))"></span>
                                                                                                                                </span>
                                                                    </div>
                                                                                            <div role="cell" data-slot="table-cell" data-cell-col="entered" x-show="shown['entered']"  x-bind:class="pad"
                                                                        class="flex items-center relative h-row align-middle whitespace-nowrap text-end justify-end ">
                                                                                                                    <span  class="flex min-w-0 items-center gap-1.5 justify-end" >
                                                                                            <span class="min-w-0 flex-1  tabular-nums" x-text="shownText(row, col(&#039;entered&#039;))"></span>
                                                                                                                                </span>
                                                                    </div>
                                                                                            <div role="cell" data-slot="table-cell" data-cell-col="conversion" x-show="shown['conversion']"  x-bind:class="pad"
                                                                        class="flex items-center relative h-row align-middle whitespace-nowrap text-end justify-end ">
                                                                                                                    <span  class="flex min-w-0 items-center gap-1.5 justify-end" >
                                                                                            <span class="min-w-0 flex-1  " x-text="shownText(row, col(&#039;conversion&#039;))"></span>
                                                                                                                                </span>
                                                                    </div>
                                                                                            <div role="cell" data-slot="table-cell" data-cell-col="window" x-show="shown['window']"  x-bind:class="pad"
                                                                        class="flex items-center relative h-row align-middle whitespace-nowrap  ">
                                                                                                                    <span  class="flex min-w-0 items-center gap-1.5 " >
                                                                                            <span class="min-w-0 flex-1  " x-text="shownText(row, col(&#039;window&#039;))"></span>
                                                                                                                                </span>
                                                                    </div>
                                                                                            <div role="cell" data-slot="table-cell" data-cell-col="updated" x-show="shown['updated']"  x-bind:class="pad"
                                                                        class="flex items-center relative h-row align-middle whitespace-nowrap  ">
                                                                                                                    <span  class="flex min-w-0 items-center gap-1.5 " >
                                                                                            <span class="min-w-0 flex-1  " x-text="shownText(row, col(&#039;updated&#039;))"></span>
                                                                                                                                </span>
                                                                    </div>
                                                            <div role="cell" data-slot="table-cell"  x-bind:class="pad" class="flex items-center h-row w-12 pe-2 text-end align-middle whitespace-nowrap">
                                    <div data-slot="dropdown-menu" x-data="nqDropdownMenu(false)" x-modelable="open" class="contents"><button data-slot="data-table-row-actions"
     type="button"                         x-bind="trigger" x-ref="trigger" x-bind:aria-label="say(&#039;rowActions&#039;, row)" x-show="hasActions(row)" x-bind:tabindex="index === Math.min(active, pageRows.length - 1) ? 0 : -1" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-nq-hover size-control-sm p-0 text-muted-foreground opacity-0 group-hover/row:opacity-100 group-focus-within/row:opacity-100 group-data-[state=selected]/row:opacity-100 data-popup-open:opacity-100 pointer-coarse:opacity-100">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="1"/>
  <circle cx="19" cy="12" r="1"/>
  <circle cx="5" cy="12" r="1"/>
</svg></button>
                                        <template x-teleport="body">
    <div data-slot="dropdown-menu-content" x-bind="popup" x-init="popupEl = $el" x-nq-presence="open" x-anchor.bottom-end.offset.4="$refs.trigger"
        class="z-50 overflow-hidden rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none max-h-[var(--available-height)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 min-w-44"><div data-slot="dropdown-menu-group" role="group" ><template x-if="actionOn(row, 0)">
                                                        <div role="none" class="contents">
                                                                                                                        <div data-slot="dropdown-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-on:click="act(&#039;edit&#039;, row)" x-bind:data-disabled="actionOff(row, 0) ? &#039;&#039; : null" x-bind:aria-disabled="actionOff(row, 0) ? &#039;true&#039; : null" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>                                                                Edit</div>
                                                        </div>
                                                    </template>
                                                                                                    <template x-if="actionOn(row, 1)">
                                                        <div role="none" class="contents">
                                                            <template x-if="sepBefore(row, 1)"><div data-slot="dropdown-menu-separator" role="separator" aria-orientation="horizontal" class="-mx-1.5 my-1.5 h-px bg-border"></div>
</template>                                                            <div data-slot="dropdown-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-on:click="act(&#039;duplicate&#039;, row)" x-bind:data-disabled="actionOff(row, 1) ? &#039;&#039; : null" x-bind:aria-disabled="actionOff(row, 1) ? &#039;true&#039; : null" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="14" height="14" x="8" y="8" rx="2" ry="2"/>
  <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>
</svg>                                                                Duplicate</div>
                                                        </div>
                                                    </template>
                                                                                                    <template x-if="actionOn(row, 2)">
                                                        <div role="none" class="contents">
                                                            <template x-if="sepBefore(row, 2)"><div data-slot="dropdown-menu-separator" role="separator" aria-orientation="horizontal" class="-mx-1.5 my-1.5 h-px bg-border"></div>
</template>                                                            <div data-slot="dropdown-menu-item" role="menuitem" data-variant="danger" x-bind="item"
        x-on:click="act(&#039;delete&#039;, row)" x-bind:data-disabled="actionOff(row, 2) ? &#039;&#039; : null" x-bind:aria-disabled="actionOff(row, 2) ? &#039;true&#039; : null" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 text-nq-danger-text [&_svg]:text-current"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg>                                                                Delete</div>
                                                        </div>
                                                    </template></div></div>
</template></div>
                                </div>
                                                    </div>
                                            </div>
                </template>
                    </div>
    </div>
            <nav data-slot="data-table-pagination" aria-label="Pagination" x-show="paged" style="display: none" class="flex flex-wrap items-center justify-end gap-2">
                        <span class="text-caption tabular-nums text-muted-foreground" aria-live="polite" x-text="rangeText()"></span>
            <button type="button" aria-label="Previous page" x-bind:disabled="page === 0 ? '' : null" x-on:click="setPage(page - 1)"
                class="inline-flex size-control-sm shrink-0 items-center justify-center rounded-control text-foreground outline-none hover:bg-nq-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4"><svg aria-hidden="true" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m15 18-6-6 6-6"/>
</svg></button>
            <button type="button" aria-label="Next page" x-bind:disabled="page >= pageCount - 1 ? '' : null" x-on:click="setPage(page + 1)"
                class="inline-flex size-control-sm shrink-0 items-center justify-center rounded-control text-foreground outline-none hover:bg-nq-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4"><svg aria-hidden="true" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m9 18 6-6-6-6"/>
</svg></button>
        </nav>
                <div data-slot="data-table-context-menu" x-data="nqContextMenu()" x-effect="menuClosed(open)" class="contents">
            <template x-teleport="body">
    <div data-slot="context-menu-content" x-bind="popup" x-init="popupEl = $el" x-nq-presence="open"
        class="fixed z-50 overflow-hidden rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none max-h-[var(--available-height)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 min-w-44"><template x-if="ctxRow && actionOn(ctxRow, 0)">
                        <div role="none" class="contents">
                                                        <div data-slot="context-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-on:click="act(&#039;edit&#039;, ctxRow)" x-bind:data-disabled="actionOff(ctxRow, 0) ? &#039;&#039; : null" x-bind:aria-disabled="actionOff(ctxRow, 0) ? &#039;true&#039; : null" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>                                Edit</div>
                        </div>
                    </template>
                                    <template x-if="ctxRow && actionOn(ctxRow, 1)">
                        <div role="none" class="contents">
                            <template x-if="sepBefore(ctxRow, 1)"><div data-slot="context-menu-separator" role="separator" aria-orientation="horizontal" class="-mx-1.5 my-1.5 h-px bg-border"></div>
</template>                            <div data-slot="context-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-on:click="act(&#039;duplicate&#039;, ctxRow)" x-bind:data-disabled="actionOff(ctxRow, 1) ? &#039;&#039; : null" x-bind:aria-disabled="actionOff(ctxRow, 1) ? &#039;true&#039; : null" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="14" height="14" x="8" y="8" rx="2" ry="2"/>
  <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>
</svg>                                Duplicate</div>
                        </div>
                    </template>
                                    <template x-if="ctxRow && actionOn(ctxRow, 2)">
                        <div role="none" class="contents">
                            <template x-if="sepBefore(ctxRow, 2)"><div data-slot="context-menu-separator" role="separator" aria-orientation="horizontal" class="-mx-1.5 my-1.5 h-px bg-border"></div>
</template>                            <div data-slot="context-menu-item" role="menuitem" data-variant="danger" x-bind="item"
        x-on:click="act(&#039;delete&#039;, ctxRow)" x-bind:data-disabled="actionOff(ctxRow, 2) ? &#039;&#039; : null" x-bind:aria-disabled="actionOff(ctxRow, 2) ? &#039;true&#039; : null" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 text-nq-danger-text [&_svg]:text-current"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg>                                Delete</div>
                        </div>
                    </template></div>
</template>
        </div>
        <span role="status" aria-live="polite" class="sr-only" x-text="announce"></span>
</div></div>
</div>
</div>
```
