# FeatureFlagList

> A feature flag list with a key, an on/off switch per environment, rollout percentage, state and last update, plus the pure bucketing and evaluation logic behind percentage rollouts.

Source: https://docs.nasaqui.com/components/feature-flags

## Install

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

FeatureFlagList is the overview of every flag. Each row has the name and key, one switch per environment that you can flip in place, the rollout percentage and a one-word state (on, partial, off or killed) for one environment, and when the flag last changed. A row opens the flag detail. The same package holds the model that decides what a user sees: a stable hash puts each user in a bucket from 0 to 100, so raising a rollout from 10% to 20% keeps the first 10% in.

The evaluation code is for releasing features. It is not a security boundary: do not use it to guard data.

## When to use

- The flag overview in an admin or developer area.
- Anywhere you need deterministic percentage rollouts in tests or a preview.

## When not to use

- One flag in depth: use [`FeatureFlagDetail`](https://docs.nasaqui.com/components/feature-flag-detail).
- Emergency stops for automations: use [`KillSwitch`](https://docs.nasaqui.com/components/kill-switch).

## Import

```tsx
import { FeatureFlagList, evaluateFlag } from "@fadymondy/nasaq/web";
```

## Quick start

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

<FeatureFlagList
  flags={flags}
  environments={[{ id: "dev", label: "Development" }, { id: "prod", label: "Production" }]}
  onToggle={async (key, env, enabled) => { await api.toggle(key, env, enabled); }}
  onOpen={(key) => navigate(`/flags/${key}`)}
/>;
```

## Anatomy

```
FeatureFlagList     data-slot="feature-flag-list"   (Card + DataTable)
  toolbar           search, state facet, New flag
  row               name and key, switch per environment (env-<id>), rollout, state, updated
  row actions       open, copy key, delete
```

## API

### FeatureFlagList

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `flags` | `FeatureFlag[]` | required | See below. |
| `environments` | `FlagEnvironmentDef[]` | required | `{ id, label }`, in column order. |
| `onToggle` | `(key, environmentId, enabled) => Promise<void \| { error?: string }>` | none | Makes the switches live; without it they are read only. A failure puts the switch back and shows the message. |
| `onOpen` | `(key) => void` | none | Row click and Open. |
| `onCreate` | `() => void` | none | Shows New flag. |
| `onDelete` | `(key) => Promise<...>` | none | Row action. |
| `rolloutEnvironment` | `string` | last environment | Which environment the rollout and state columns use. |
| `title / description / pageSize / loading / error / onRetry / className` | | | As in the other lists. |
| `labels` | `Partial<FeatureFlagsLabels>` | none | Strings. |

### FeatureFlag

`{ key, name, description?, killed?, environments: Record<id, { enabled, rollout }>, variants: { key, label?, weight }[], rules: RuleDefinition[], updatedAt, updatedBy?, tags? }`.

### Model

- `bucketFor(flagKey, userId)` is the user's bucket, 0 up to (not including) 100, stable per flag.
- `isInRollout(bucket, percent)`: 0% lets nobody in and 100% everybody.
- `evaluateFlag(flag, environmentId, { userId, ...context }, matches?)` returns `{ on, variant, reason, bucket }`. Order: killed, environment off, first matching targeting rule (serves its variant and skips the rollout), then the percentage. `matches` comes from `ruleMatcher(fields)`; without it rules are ignored.
- `pickVariant(flagKey, userId, variants)` uses an independent hash over normalised weights.
- `normalizeWeights(weights)` returns whole numbers that add up to 100.
- `flagState(flag, environmentId)`, `clampRollout`, `hash32`, `ruleVariant`, `isValidFlagKey`, `flagKeyFromName`.

## Examples

Check a user in code or a preview:

```tsx
import { evaluateFlag, ruleMatcher } from "@fadymondy/nasaq/web";

const matches = ruleMatcher(fields);
const { on, variant, reason } = evaluateFlag(flag, "prod", { userId: "u-42", plan: "pro" }, matches);
```

Show production only:

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

<FeatureFlagList flags={flags} environments={envs.filter((e) => e.id === "prod")} />;
```

## Accessibility

| Key | Action |
| --- | --- |
| Tab | Move between switches and rows. |
| Space | Flip a switch. |
| Enter | Open the flag. |

Each switch has a name that includes the flag and environment. State is a word, not just a colour.

## RTL & i18n

Flag keys are left-to-right (`<bdi dir="ltr">`) inside the RTL layout. Dates use `DateTime`. Built-in English and Arabic strings; override with `labels`.

## Styling & tokens

State uses the success, warning, danger and neutral tokens. Logical spacing only.

## Do / Don't

- Do keep environment order stable (dev, staging, production).
- Do treat killed as stronger than any switch.
- Don't use flags for permissions or data access.

## Related

- [FeatureFlagDetail](https://docs.nasaqui.com/components/feature-flag-detail)
- [RuleBuilder](https://docs.nasaqui.com/components/rule-builder)

## Lab

https://docs.nasaqui.com/?path=/docs/components-developer-tools-feature-flags--docs

## Code

### React

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

<FeatureFlagList
  flags={flags}
  environments={[{ id: "dev", label: "Development" }, { id: "prod", label: "Production" }]}
  onToggle={async (key, env, enabled) => { await api.toggle(key, env, enabled); }}
  onOpen={(key) => navigate(`/flags/${key}`)}
/>;
```

### shadcn

```tsx
import { FeatureFlagList } from "@/components/ui/feature-flags";

<FeatureFlagList
  flags={flags}
  environments={[{ id: "dev", label: "Development" }, { id: "prod", label: "Production" }]}
  onToggle={async (key, env, enabled) => { await api.toggle(key, env, enabled); }}
  onOpen={(key) => navigate(`/flags/${key}`)}
/>;
```

### Vue

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

const environments = [
  { id: "dev", label: "Development" },
  { id: "prod", label: "Production" },
];

const flags: FeatureFlag[] = [
  { key: "new-checkout", name: "New checkout", environments: { dev: { enabled: true, rollout: 100 }, prod: { enabled: true, rollout: 25 } }, variants: [], rules: [], updatedAt: "2026-09-28T10:00:00Z", updatedBy: "Mona" },
  { key: "dark-mode", name: "Dark mode", environments: { dev: { enabled: true, rollout: 100 }, prod: { enabled: false, rollout: 0 } }, variants: [], rules: [], updatedAt: "2026-09-20T10:00:00Z", updatedBy: "Omar" },
];

async function toggle(key: string, env: string, enabled: boolean) {
  await Promise.resolve([key, env, enabled]);
}
</script>

<template>
  <NqFeatureFlagList :flags="flags" :environments="environments" :on-toggle="toggle" :on-open="() => {}" />
</template>
```

### Blade

```blade
@php
    $flags = [
        ['key' => 'new-checkout', 'name' => 'New checkout', 'environments' => ['dev' => ['enabled' => true, 'rollout' => 100], 'prod' => ['enabled' => true, 'rollout' => 25]], 'updatedAt' => '2026-09-28T10:00:00Z', 'updatedBy' => 'Mona', 'tags' => ['checkout']],
        ['key' => 'dark-mode', 'name' => 'Dark mode', 'environments' => ['dev' => ['enabled' => true, 'rollout' => 100], 'prod' => ['enabled' => false, 'rollout' => 0]], 'updatedAt' => '2026-09-20T10:00:00Z', 'updatedBy' => 'Omar'],
        ['key' => 'legacy-search', 'name' => 'Legacy search', 'killed' => true, 'environments' => ['dev' => ['enabled' => true, 'rollout' => 100], 'prod' => ['enabled' => true, 'rollout' => 100]], 'updatedAt' => '2026-09-10T08:00:00Z'],
        ['key' => 'beta-reports', 'name' => 'Beta reports', 'environments' => ['dev' => ['enabled' => true, 'rollout' => 100], 'prod' => ['enabled' => true, 'rollout' => 100]], 'updatedAt' => '2026-09-01T08:00:00Z', 'updatedBy' => 'Mona'],
    ];
    $environments = [['id' => 'dev', 'label' => 'Development'], ['id' => 'prod', 'label' => 'Production']];
@endphp
<x-nq::feature-flags :flags="$flags" :environments="$environments"
    x-on:toggle="window.__toggled = $event.detail.key + ':' + $event.detail.environment + ':' + $event.detail.enabled; $event.detail.wait(Promise.resolve())"
    x-on:open="window.__opened = $event.detail.key"
    x-on:create="window.__created = true"
    x-on:delete="$event.detail.wait(Promise.resolve())" />
```

### HTML + Alpine

```html
<div data-slot="feature-flag-list" x-data="nqFeatureFlagList(JSON.parse('{\u0022rows\u0022:[{\u0022id\u0022:\u0022new-checkout\u0022,\u0022key\u0022:\u0022new-checkout\u0022,\u0022name\u0022:\u0022New checkout\u0022,\u0022killed\u0022:false,\u0022search\u0022:\u0022New checkout new-checkout checkout\u0022,\u0022updated\u0022:\u00222026-09-28T10:00:00Z\u0022,\u0022updatedByText\u0022:\u0022by Mona\u0022,\u0022env_0\u0022:true,\u0022env_1\u0022:true,\u0022rollout\u0022:25,\u0022state\u0022:\u0022partial\u0022},{\u0022id\u0022:\u0022dark-mode\u0022,\u0022key\u0022:\u0022dark-mode\u0022,\u0022name\u0022:\u0022Dark mode\u0022,\u0022killed\u0022:false,\u0022search\u0022:\u0022Dark mode dark-mode\u0022,\u0022updated\u0022:\u00222026-09-20T10:00:00Z\u0022,\u0022updatedByText\u0022:\u0022by Omar\u0022,\u0022env_0\u0022:true,\u0022env_1\u0022:false,\u0022rollout\u0022:0,\u0022state\u0022:\u0022off\u0022},{\u0022id\u0022:\u0022legacy-search\u0022,\u0022key\u0022:\u0022legacy-search\u0022,\u0022name\u0022:\u0022Legacy search\u0022,\u0022killed\u0022:true,\u0022search\u0022:\u0022Legacy search legacy-search\u0022,\u0022updated\u0022:\u00222026-09-10T08:00:00Z\u0022,\u0022updatedByText\u0022:\u0022\u0022,\u0022env_0\u0022:true,\u0022env_1\u0022:true,\u0022rollout\u0022:100,\u0022state\u0022:\u0022killed\u0022},{\u0022id\u0022:\u0022beta-reports\u0022,\u0022key\u0022:\u0022beta-reports\u0022,\u0022name\u0022:\u0022Beta reports\u0022,\u0022killed\u0022:false,\u0022search\u0022:\u0022Beta reports beta-reports\u0022,\u0022updated\u0022:\u00222026-09-01T08:00:00Z\u0022,\u0022updatedByText\u0022:\u0022by Mona\u0022,\u0022env_0\u0022:true,\u0022env_1\u0022:true,\u0022rollout\u0022:100,\u0022state\u0022:\u0022on\u0022}],\u0022envs\u0022:[\u0022dev\u0022,\u0022prod\u0022],\u0022labels\u0022:{\u0022failed\u0022:\u0022Could not save this. Try again.\u0022}}'))"
    x-on:nq-data-table-action="onAction($event)" x-on:nq-data-table-row-click="onRow($event)" x-on:nq-data-table-edit="onEdit($event)"
    x-on:toggle="window.__toggled = $event.detail.key + &#039;:&#039; + $event.detail.environment + &#039;:&#039; + $event.detail.enabled; $event.detail.wait(Promise.resolve())" x-on:open="window.__opened = $event.detail.key" x-on:create="window.__created = true" 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">Feature flags</h3>
        <div data-slot="card-description" class="text-body-sm text-muted-foreground">Turn features on per environment, roll them out gradually and stop them fast.</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 flag</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:\u0022new-checkout\u0022,\u0022key\u0022:\u0022new-checkout\u0022,\u0022name\u0022:\u0022New checkout\u0022,\u0022killed\u0022:false,\u0022search\u0022:\u0022New checkout new-checkout checkout\u0022,\u0022updated\u0022:\u00222026-09-28T10:00:00Z\u0022,\u0022updatedByText\u0022:\u0022by Mona\u0022,\u0022env_0\u0022:true,\u0022env_1\u0022:true,\u0022rollout\u0022:25,\u0022state\u0022:\u0022partial\u0022},{\u0022id\u0022:\u0022dark-mode\u0022,\u0022key\u0022:\u0022dark-mode\u0022,\u0022name\u0022:\u0022Dark mode\u0022,\u0022killed\u0022:false,\u0022search\u0022:\u0022Dark mode dark-mode\u0022,\u0022updated\u0022:\u00222026-09-20T10:00:00Z\u0022,\u0022updatedByText\u0022:\u0022by Omar\u0022,\u0022env_0\u0022:true,\u0022env_1\u0022:false,\u0022rollout\u0022:0,\u0022state\u0022:\u0022off\u0022},{\u0022id\u0022:\u0022legacy-search\u0022,\u0022key\u0022:\u0022legacy-search\u0022,\u0022name\u0022:\u0022Legacy search\u0022,\u0022killed\u0022:true,\u0022search\u0022:\u0022Legacy search legacy-search\u0022,\u0022updated\u0022:\u00222026-09-10T08:00:00Z\u0022,\u0022updatedByText\u0022:\u0022\u0022,\u0022env_0\u0022:true,\u0022env_1\u0022:true,\u0022rollout\u0022:100,\u0022state\u0022:\u0022killed\u0022},{\u0022id\u0022:\u0022beta-reports\u0022,\u0022key\u0022:\u0022beta-reports\u0022,\u0022name\u0022:\u0022Beta reports\u0022,\u0022killed\u0022:false,\u0022search\u0022:\u0022Beta reports beta-reports\u0022,\u0022updated\u0022:\u00222026-09-01T08:00:00Z\u0022,\u0022updatedByText\u0022:\u0022by Mona\u0022,\u0022env_0\u0022:true,\u0022env_1\u0022:true,\u0022rollout\u0022:100,\u0022state\u0022:\u0022on\u0022}]'), JSON.parse('[{\u0022id\u0022:\u0022flag\u0022,\u0022header\u0022:\u0022Flag\u0022,\u0022key\u0022:\u0022search\u0022,\u0022sortable\u0022:true,\u0022searchable\u0022:true,\u0022hideable\u0022:false,\u0022type\u0022:\u0022text\u0022},{\u0022id\u0022:\u0022env_0\u0022,\u0022header\u0022:\u0022Development\u0022,\u0022type\u0022:\u0022boolean\u0022,\u0022edit\u0022:\u0022switch\u0022,\u0022editDisabledWhen\u0022:{\u0022field\u0022:\u0022killed\u0022,\u0022eq\u0022:true},\u0022align\u0022:\u0022center\u0022,\u0022sortable\u0022:true},{\u0022id\u0022:\u0022env_1\u0022,\u0022header\u0022:\u0022Production\u0022,\u0022type\u0022:\u0022boolean\u0022,\u0022edit\u0022:\u0022switch\u0022,\u0022editDisabledWhen\u0022:{\u0022field\u0022:\u0022killed\u0022,\u0022eq\u0022:true},\u0022align\u0022:\u0022center\u0022,\u0022sortable\u0022:true},{\u0022id\u0022:\u0022rollout\u0022,\u0022header\u0022:\u0022Rollout in Production\u0022,\u0022type\u0022:\u0022number\u0022,\u0022sortable\u0022:true,\u0022align\u0022:\u0022end\u0022},{\u0022id\u0022:\u0022state\u0022,\u0022header\u0022:\u0022State\u0022,\u0022type\u0022:\u0022status\u0022,\u0022sortable\u0022:true,\u0022filter\u0022:true,\u0022options\u0022:[{\u0022value\u0022:\u0022on\u0022,\u0022label\u0022:\u0022On\u0022,\u0022tone\u0022:\u0022success\u0022},{\u0022value\u0022:\u0022partial\u0022,\u0022label\u0022:\u0022Rolling out\u0022,\u0022tone\u0022:\u0022warning\u0022},{\u0022value\u0022:\u0022off\u0022,\u0022label\u0022:\u0022Off\u0022,\u0022tone\u0022:\u0022neutral\u0022},{\u0022value\u0022:\u0022killed\u0022,\u0022label\u0022:\u0022Killed\u0022,\u0022tone\u0022:\u0022danger\u0022}]},{\u0022id\u0022:\u0022updated\u0022,\u0022header\u0022:\u0022Updated\u0022,\u0022type\u0022:\u0022datetime\u0022,\u0022format\u0022:\u0022relative\u0022,\u0022sortable\u0022:true}]'), JSON.parse('{\u0022pageSize\u0022:8,\u0022locale\u0022:\u0022en\u0022,\u0022actions\u0022:[{\u0022id\u0022:\u0022open\u0022},{\u0022id\u0022:\u0022copy\u0022},{\u0022id\u0022:\u0022delete\u0022,\u0022group\u0022:\u0022z\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 flags by name or key…" aria-label="Filter flags by name or key…" 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 data-slot="dropdown-menu" x-data="nqDropdownMenu(false)" x-modelable="open" class="contents"><button data-slot="dropdown-menu-trigger"
     type="button"                         x-bind="trigger" x-ref="trigger" x-bind:class="facetCount(&#039;state&#039;) ? &#039;&#039; : &#039;border-dashed text-muted-foreground&#039;" data-facet="state" 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="M2 5h20"/>
  <path d="M6 12h12"/>
  <path d="M9 19h6"/>
</svg>                        State
                        <span data-slot="badge" x-show="facetCount('state')" x-text="facetSummary('state')" style="display: none"
                            class="-me-1 inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border border-border px-1.5 text-caption font-medium tabular-nums text-muted-foreground"></span></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-start.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-48"><div data-slot="dropdown-menu-group" role="group" ><div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet[&#039;state|on&#039;]" 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 ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg 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="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    On
</div>
                                                            <div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet[&#039;state|partial&#039;]" 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 ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg 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="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    Rolling out
</div>
                                                            <div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet[&#039;state|off&#039;]" 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 ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg 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="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    Off
</div>
                                                            <div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet[&#039;state|killed&#039;]" 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 ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg 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="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    Killed
</div></div>
                        <div x-show="facetCount('state')" style="display: none">
                            <div data-slot="dropdown-menu-separator" role="separator" aria-orientation="horizontal" class="-mx-1.5 my-1.5 h-px bg-border"></div>
                            <div data-slot="dropdown-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-on:click="resetFacet(&#039;state&#039;)" 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">Reset</div>
                        </div></div>
</template></div>
                    </div>
    <div data-slot="table-container" role="region" tabindex="0" aria-label="Feature flags"                 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="Feature flags"  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="flag" x-show="shown['flag']"  x-bind:class="pad"  x-bind:aria-sort="ariaSort('flag')"                             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('flag', $event.shiftKey)"
                                    x-bind:class="sortOf('flag') ? '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 >Flag</span>
                                    <svg aria-hidden="true" x-show="! sortOf('flag')" 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('flag') === 'asc'" style="display: none" />
                                    <x-lucide-arrow-down aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('flag') === 'desc'" style="display: none" />
                                                                    </button>
                                                                                </div>
                                                                    <div role="columnheader" data-slot="table-head" data-col="env_0" x-show="shown['env_0']"  x-bind:class="pad"  x-bind:aria-sort="ariaSort('env_0')"                             class="flex items-center h-row text-center justify-center align-middle text-caption font-medium whitespace-nowrap text-muted-foreground">
                                                            <button type="button"  x-on:click="toggleSort('env_0', $event.shiftKey)"
                                    x-bind:class="sortOf('env_0') ? '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 >Development</span>
                                    <svg aria-hidden="true" x-show="! sortOf('env_0')" 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('env_0') === 'asc'" style="display: none" />
                                    <x-lucide-arrow-down aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('env_0') === 'desc'" style="display: none" />
                                                                    </button>
                                                                                </div>
                                                                    <div role="columnheader" data-slot="table-head" data-col="env_1" x-show="shown['env_1']"  x-bind:class="pad"  x-bind:aria-sort="ariaSort('env_1')"                             class="flex items-center h-row text-center justify-center align-middle text-caption font-medium whitespace-nowrap text-muted-foreground">
                                                            <button type="button"  x-on:click="toggleSort('env_1', $event.shiftKey)"
                                    x-bind:class="sortOf('env_1') ? '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 >Production</span>
                                    <svg aria-hidden="true" x-show="! sortOf('env_1')" 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('env_1') === 'asc'" style="display: none" />
                                    <x-lucide-arrow-down aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('env_1') === 'desc'" style="display: none" />
                                                                    </button>
                                                                                </div>
                                                                    <div role="columnheader" data-slot="table-head" data-col="rollout" x-show="shown['rollout']"  x-bind:class="pad"  x-bind:aria-sort="ariaSort('rollout')"                             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('rollout', $event.shiftKey)"
                                    x-bind:class="sortOf('rollout') ? '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 >Rollout in Production</span>
                                    <svg aria-hidden="true" x-show="! sortOf('rollout')" 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('rollout') === 'asc'" style="display: none" />
                                    <x-lucide-arrow-down aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('rollout') === 'desc'" style="display: none" />
                                                                    </button>
                                                                                </div>
                                                                    <div role="columnheader" data-slot="table-head" data-col="state" x-show="shown['state']"  x-bind:class="pad"  x-bind:aria-sort="ariaSort('state')"                             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('state', $event.shiftKey)"
                                    x-bind:class="sortOf('state') ? '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 >State</span>
                                    <svg aria-hidden="true" x-show="! sortOf('state')" 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('state') === 'asc'" style="display: none" />
                                    <x-lucide-arrow-down aria-hidden="true" class="size-3.5 shrink-0" x-show="sortOf('state') === '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 feature flags 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="flag" x-show="shown['flag']"  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="flex min-w-0 flex-col">
                    <span dir="auto" class="block max-w-[28ch] truncate text-label text-foreground" x-text="row.name"></span>
                    <bdi dir="ltr" class="block max-w-[28ch] truncate font-mono text-caption text-muted-foreground" x-text="row.key"></bdi>
                </span>
                                                                                                                                </span>
                                                                    </div>
                                                                                            <div role="cell" data-slot="table-cell" data-cell-col="env_0" x-show="shown['env_0']"  x-bind:class="pad"
                                                                            x-bind:data-cell-row="rid(row)" tabindex="-1" x-bind:data-editable="editable(row, col(&#039;env_0&#039;)) ? '' : null" x-bind:data-editing="isEditing(row, col(&#039;env_0&#039;)) ? '' : null"
                                        x-bind:aria-busy="isPending(row, col(&#039;env_0&#039;)) ? 'true' : null" x-bind:aria-invalid="failure(row, col(&#039;env_0&#039;)) ? 'true' : null"
                                        x-on:dblclick="beginEdit(row, col(&#039;env_0&#039;), $event)" x-on:keydown.enter.self.prevent="beginEdit(row, col(&#039;env_0&#039;), $event)" x-on:keydown.f2.self.prevent="beginEdit(row, col(&#039;env_0&#039;), $event)"
                                        x-bind:class="failure(row, col(&#039;env_0&#039;)) ? 'bg-nq-danger-soft' : ''"
                                                                        class="flex items-center relative h-row align-middle whitespace-nowrap text-center justify-center outline-none focus:outline-2 focus:-outline-offset-2 focus:outline-nq-focus">
                                                                            <button type="button" role="switch" data-slot="switch" x-bind:aria-label="editName(row, col(&#039;env_0&#039;))" x-on:click="toggleSwitch(row, col(&#039;env_0&#039;))"
                                            x-bind:aria-checked="shownValue(row, col(&#039;env_0&#039;)) === true ? 'true' : 'false'" aria-checked="false"
                                            x-bind:data-checked="shownValue(row, col(&#039;env_0&#039;)) === true ? '' : null" x-bind:data-unchecked="shownValue(row, col(&#039;env_0&#039;)) === true ? null : ''"
                                            x-bind:disabled="editable(row, col(&#039;env_0&#039;)) ? null : ''" x-bind:data-disabled="editable(row, col(&#039;env_0&#039;)) ? null : ''"
                                            class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent bg-nq-line-strong p-0.5 outline-none transition-colors duration-150 ease-nq data-checked:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50">
                                            <span data-slot="switch-thumb" x-bind:data-checked="shownValue(row, col(&#039;env_0&#039;)) === true ? '' : null" x-bind:data-unchecked="shownValue(row, col(&#039;env_0&#039;)) === true ? null : ''"
                                                class="block size-4 rounded-full bg-background shadow-xs data-checked:bg-primary-foreground transition-[translate] duration-150 ease-nq data-checked:translate-x-3.5 rtl:data-checked:-translate-x-3.5"></span>
                                        </button>
                                                                    </div>
                                                                                            <div role="cell" data-slot="table-cell" data-cell-col="env_1" x-show="shown['env_1']"  x-bind:class="pad"
                                                                            x-bind:data-cell-row="rid(row)" tabindex="-1" x-bind:data-editable="editable(row, col(&#039;env_1&#039;)) ? '' : null" x-bind:data-editing="isEditing(row, col(&#039;env_1&#039;)) ? '' : null"
                                        x-bind:aria-busy="isPending(row, col(&#039;env_1&#039;)) ? 'true' : null" x-bind:aria-invalid="failure(row, col(&#039;env_1&#039;)) ? 'true' : null"
                                        x-on:dblclick="beginEdit(row, col(&#039;env_1&#039;), $event)" x-on:keydown.enter.self.prevent="beginEdit(row, col(&#039;env_1&#039;), $event)" x-on:keydown.f2.self.prevent="beginEdit(row, col(&#039;env_1&#039;), $event)"
                                        x-bind:class="failure(row, col(&#039;env_1&#039;)) ? 'bg-nq-danger-soft' : ''"
                                                                        class="flex items-center relative h-row align-middle whitespace-nowrap text-center justify-center outline-none focus:outline-2 focus:-outline-offset-2 focus:outline-nq-focus">
                                                                            <button type="button" role="switch" data-slot="switch" x-bind:aria-label="editName(row, col(&#039;env_1&#039;))" x-on:click="toggleSwitch(row, col(&#039;env_1&#039;))"
                                            x-bind:aria-checked="shownValue(row, col(&#039;env_1&#039;)) === true ? 'true' : 'false'" aria-checked="false"
                                            x-bind:data-checked="shownValue(row, col(&#039;env_1&#039;)) === true ? '' : null" x-bind:data-unchecked="shownValue(row, col(&#039;env_1&#039;)) === true ? null : ''"
                                            x-bind:disabled="editable(row, col(&#039;env_1&#039;)) ? null : ''" x-bind:data-disabled="editable(row, col(&#039;env_1&#039;)) ? null : ''"
                                            class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent bg-nq-line-strong p-0.5 outline-none transition-colors duration-150 ease-nq data-checked:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50">
                                            <span data-slot="switch-thumb" x-bind:data-checked="shownValue(row, col(&#039;env_1&#039;)) === true ? '' : null" x-bind:data-unchecked="shownValue(row, col(&#039;env_1&#039;)) === true ? null : ''"
                                                class="block size-4 rounded-full bg-background shadow-xs data-checked:bg-primary-foreground transition-[translate] duration-150 ease-nq data-checked:translate-x-3.5 rtl:data-checked:-translate-x-3.5"></span>
                                        </button>
                                                                    </div>
                                                                                            <div role="cell" data-slot="table-cell" data-cell-col="rollout" x-show="shown['rollout']"  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="flex items-center justify-end gap-2">
                    <span aria-hidden="true" class="h-1.5 w-16 overflow-hidden rounded-full bg-muted">
                        <span class="block h-full rounded-full bg-primary" x-bind:style="'inline-size:' + row.rollout + '%'"></span>
                    </span>
                    <span class="w-10 text-end tabular-nums" x-text="nf(row.rollout / 100, { style: 'percent', maximumFractionDigits: 0 })"></span>
                </span>
                                                                                                                                </span>
                                                                    </div>
                                                                                            <div role="cell" data-slot="table-cell" data-cell-col="state" x-show="shown['state']"  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 data-slot="status" data-tone="neutral" x-show="shownText(row, col(&#039;state&#039;)) !== '' && tone(row, col(&#039;state&#039;)) === 'neutral'" style="display: none" class="inline-flex min-w-0 items-center gap-1.5 text-body-sm text-foreground">
                                                        <svg aria-hidden="true" class="size-3.5 shrink-0 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">
  <circle cx="12" cy="12" r="10"/>
</svg>                                                        <span class="truncate" x-text="shownText(row, col(&#039;state&#039;))"></span>
                                                    </span>
                                                                                                    <span data-slot="status" data-tone="info" x-show="shownText(row, col(&#039;state&#039;)) !== '' && tone(row, col(&#039;state&#039;)) === 'info'" style="display: none" class="inline-flex min-w-0 items-center gap-1.5 text-body-sm text-foreground">
                                                        <svg aria-hidden="true" class="size-3.5 shrink-0 text-nq-info-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"/>
  <circle cx="12" cy="12" r="1"/>
</svg>                                                        <span class="truncate" x-text="shownText(row, col(&#039;state&#039;))"></span>
                                                    </span>
                                                                                                    <span data-slot="status" data-tone="success" x-show="shownText(row, col(&#039;state&#039;)) !== '' && tone(row, col(&#039;state&#039;)) === 'success'" style="display: none" class="inline-flex min-w-0 items-center gap-1.5 text-body-sm text-foreground">
                                                        <svg aria-hidden="true" class="size-3.5 shrink-0 text-nq-success-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="m9 12 2 2 4-4"/>
</svg>                                                        <span class="truncate" x-text="shownText(row, col(&#039;state&#039;))"></span>
                                                    </span>
                                                                                                    <span data-slot="status" data-tone="warning" x-show="shownText(row, col(&#039;state&#039;)) !== '' && tone(row, col(&#039;state&#039;)) === 'warning'" style="display: none" class="inline-flex min-w-0 items-center gap-1.5 text-body-sm text-foreground">
                                                        <svg aria-hidden="true" class="size-3.5 shrink-0 text-nq-warning-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"/>
  <line x1="12" x2="12" y1="8" y2="12"/>
  <line x1="12" x2="12.01" y1="16" y2="16"/>
</svg>                                                        <span class="truncate" x-text="shownText(row, col(&#039;state&#039;))"></span>
                                                    </span>
                                                                                                    <span data-slot="status" data-tone="danger" x-show="shownText(row, col(&#039;state&#039;)) !== '' && tone(row, col(&#039;state&#039;)) === 'danger'" style="display: none" class="inline-flex min-w-0 items-center gap-1.5 text-body-sm text-foreground">
                                                        <svg aria-hidden="true" class="size-3.5 shrink-0 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>                                                        <span class="truncate" x-text="shownText(row, col(&#039;state&#039;))"></span>
                                                    </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="flex flex-col">
                    <time class="tabular-nums" x-bind:datetime="isoOf(row, col('updated'))" x-bind:title="absoluteOf(row, col('updated'))" x-text="shownText(row, col('updated'))"></time>
                    <span class="text-caption text-muted-foreground" x-show="row.updatedByText" style="display: none" x-text="row.updatedByText"></span>
                </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;open&#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="M15 3h6v6"/>
  <path d="M10 14 21 3"/>
  <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
</svg>                                                                Open</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;copy&#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>                                                                Copy key</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;open&#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="M15 3h6v6"/>
  <path d="M10 14 21 3"/>
  <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
</svg>                                Open</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;copy&#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>                                Copy key</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>
```
