`@flowpanel/react` is the component library the admin renders with. Most of it
is consumed indirectly — resources, widgets and forms compile down to these
components — but every export is public and safe to use directly when you
build a custom slot, page, or `"bare"`-shell chrome around FlowPanel.

```ts excerpt
import { AutoForm, DataTable, useAdminTable } from "@flowpanel/kit/react";
```

`@flowpanel/kit/react` is the specifier to reach for: `@flowpanel/kit` is what
`flowpanel init` installs, and it re-exports this whole surface. The
standalone `@flowpanel/react` package publishes the same exports and works
identically — use it only when you depend on it directly rather than through
the kit.

Two neighbouring subpaths are worth knowing about, because their exports are
*not* in the table below:

- **`@flowpanel/kit/next/client`** — the client components the Next.js runtime
  mounts around this library: `DrawerHost`, `CommandHost`,
  `DashboardActionsBar`, `DataTableWithDrawerRows`, `CreateDrawer`,
  `DetailTabsClient`, `SavedViewsDropdown`, `ResourceListSearch`,
  `ResourceListFilters`, `ResourceListDeletedToggle`, `DashboardDateRange`,
  `WidgetErrorBoundary`. Reach for it when you assemble a `"bare"`-shell
  layout by hand.
- **`@flowpanel/kit/client`** — the standalone `useAdminMutation` hook, which
  pulls in no component library at all. See
  [Client hooks](/docs/reference/client).

## Shell

Chrome, navigation and the pieces a custom layout composes around admin
content.

| Export | Purpose |
| --- | --- |
| `AdminShell` | Pure visual chrome — sidebar or tab-strip variant — around admin content. |
| `AdminNav` | Renders `NavGroup[]` (Dashboards, Pages, Resources, Queues) as the sidebar/tab nav. |
| `AdminTabs` | Tab-strip variant of the nav, used when `AdminShellVariant` is `"tabs"`. |
| `AccountMenu` | User menu (avatar, name, sign-out) shown in the shell header. |
| `Brand` | Renders a `ShellBrand` (logo/name) in the shell header. |
| `Breadcrumbs` | Breadcrumb trail from a `BreadcrumbItem[]`. |
| `CommandPalette` | The ⌘K command palette, built on `cmdk`. |
| `Drawer`, `DrawerHeader`, `DrawerContent`, `DrawerFooter` | Side-variant drawer built on Radix Dialog, and its section slots. |
| `DetailShell` | Chrome around a resource detail page. |
| `FlowpanelGlobals` | Mounts cross-cutting globals (toast host, theme script, shortcuts) once per admin. |
| `PageHeader`, `DefaultPageHeader` | Page title/description/actions header and its default renderer. |
| `ShortcutsCheatsheet`, `DEFAULT_SHORTCUTS` | The `?`-triggered keyboard shortcuts overlay and the shortcut list it ships with. |
| `ThemeScript` | Inline script that applies the stored theme class before hydration, avoiding a flash. |
| `ComponentsProvider`, `useComponents` | Provider/reader for the `FlowpanelComponentSlots` override map. |
| `useComponent` | Resolves a single slot — `useComponent("Pagination", DefaultPagination)` returns the host override when there is one, otherwise the default you passed. |
| `useComponentOverrides` | The raw override map from the nearest `ComponentsProvider`, without defaults filled in. |
| `LabelsProvider`, `useLabels` | Provider/reader for label overrides (pluralization, field labels). |
| `ApiBaseProvider`, `useApiBase` | Provider/reader for the route handlers' mount point. `FlowpanelGlobals` fills it from `paths.api`, so every client fetch — drawer, actions, inline edit, import, reference search, SSE — follows the admin wherever it is mounted. Standalone components fall back to `/api/flowpanel`. |

**AdminShellProps**
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `variant` | `AdminShellVariant` | no |  |
| `brand` | `object` | no |  |
| `user` | `object` | no |  |
| `navGroups` | `array` | yes |  |
| `currentPath` | `string` | yes |  |
| `showSkipLink` | `boolean` | no | Set false when the host layout already provides the page's skip link. |
| `children` | `ReactNode` | yes |  |

**DrawerProps**
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `open` | `boolean` | yes |  |
| `onOpenChange` | `function` | yes |  |
| `width` | `DrawerWidth` | no |  |
| `title` | `string` | no |  |
| `description` | `string` | no |  |
| `children` | `ReactNode` | no |  |
| `className` | `string` | no |  |

**CommandPaletteProps**
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `open` | `boolean` | yes |  |
| `onOpenChange` | `function` | yes |  |
| `groups` | `array` | yes |  |
| `placeholder` | `string` | no |  |
| `onSearch` | `function` | no |  |
| `itemsLoading` | `boolean` | no |  |

## Data table & filters

`DataTable` and the controls that surround it — column menus, filter inputs,
cell renderers.

| Export | Purpose |
| --- | --- |
| `DataTable` | The resource list table: sorting, pagination, selection, inline edit, realtime refresh. |
| `BulkBar` | Floating action bar shown when `DataTable` rows are selected. |
| `ColumnPinMenu` | Per-column menu for pinning left/right. |
| `ColumnVisibilityMenu` | Toolbar menu for showing/hiding columns. |
| `DensityToggle` | Toggles `DataTableDensity` (row spacing) in the toolbar. |
| `FilterBar` | Renders a `FilterBarSpec[]` as the filter row above the table. |
| `BooleanFilter`, `DateRangeFilter`, `MultiSelectFilter`, `NumericRangeFilter`, `SelectFilter`, `TagFilter`, `TextFilter` | One filter control per `ColumnMeta.type`, each driven by `FilterBar`. `DateRangeFilter` opens a two-month range calendar with presets. |
| `DateRangePicker` | Standalone preset dropdown (Today, Last 7 days, MTD, …) for dashboards. |
| `Pagination`, `DefaultPagination` | Page controls under the table and their default renderer. |
| `ArrayCell`, `JsonCell`, `ReferenceCell` | Read-only cell renderers for array, JSON, and reference columns. |
| `InlineEditCell` | Editable cell used when a column declares `editable: true`. |
| `JsonEditor` | Structured editor for a JSON column, used by `InlineEditCell` and forms. |
| `ReferencePicker` | Search-and-select control for picking a referenced row. |
| `MobileCardList` | Card layout `DataTable` switches to under the mobile breakpoint. |
| `KV`, `KVRow` | Key/value list layout, used by card and drawer field views. |
| `renderFormatCell` | Renders a declarative `ColumnFormat` value — the function `DataTable` cells call internally. |

**DataTableProps**
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `columns` | `array` | yes |  |
| `rows` | `array` | yes |  |
| `total` | `number` | yes |  |
| `page` | `number` | yes |  |
| `pageSize` | `number` | yes |  |
| `rowKey` | `string & keyof Row` | yes |  |
| `sort` | `object \| null` | no |  |
| `density` | `DataTableDensity` | no | Row spacing. |
| `loading` | `boolean` | no |  |
| `onRowClick` | `function` | no |  |
| `onSortChange` | `function` | no |  |
| `onPageChange` | `function` | no |  |
| `pageSizeOptions` | `array` | no | Offered by the pager as `n / page`; needs `onPageSizeChange` to render. |
| `onPageSizeChange` | `function` | no |  |
| `emptyTitle` | `string` | no |  |
| `emptyDescription` | `string` | no |  |
| `emptyAction` | `ReactNode` | no |  |
| `emptyIcon` | `ReactNode` | no | Decorative icon/emoji rendered above the empty-state title. |
| `className` | `string` | no |  |
| `selection` | `array` | no |  |
| `onSelectionChange` | `function` | no |  |
| `getRowKey` | `function` | no | When provided, the caller controls row-key extraction; defaults to String(row[rowKey]). |
| `prerenderedCells` | `array` | no |  |
| `columnVisibility` | `Record<string, boolean>` | no |  |
| `columnWidths` | `Record<string, number>` | no |  |
| `onColumnWidthsChange` | `function` | no |  |
| `pinnedColumns` | `object` | no |  |
| `onPinnedColumnsChange` | `function` | no |  |
| `realtime` | `object \| string` | no | Subscribe to an SSE channel and trigger `router.refresh()` on events. |
| `rowEndCell` | `function` | no |  |
| `rowEndCellLabel` | `string` | no | Accessible label for the trailing column header. Defaults to "Actions". |
| `onEditRow` | `function` | no | Triggered when the user presses `e` on a focused row. |
| `onDeleteRow` | `function` | no | Triggered when the user presses `d` on a focused row. |
| `onFocusSearch` | `function` | no | Triggered when the user presses `/`. Typically focuses the search input. |
| `onShowShortcuts` | `function` | no | Triggered when the user presses `?`. Typically opens the cheatsheet. |
| `inlineEditResource` | `string` | no |  |
| `mobileLayout` | `"scroll" \| "card" \| false` | no | Mobile layout when the viewport is narrower than 640px. |
| `enteringRowKeys` | `array` | no | Stable keys that should receive the one-shot, reduced-motion-safe entry treatment. |
| `exportable` | `object \| boolean` | no | When set, renders an "Export" button in the toolbar that downloads the rows currently on screen. |
| `importable` | `object` | no |  |
| `showDensityToggle` | `boolean` | no |  |

## Forms

`AutoForm` compiles a resource's declared fields into inputs; `Form` and
`Field` are the lower-level primitives it's built from, for hand-written
forms.

| Export | Purpose |
| --- | --- |
| `AutoForm` | Renders a resource's create/update fields from `ResolvedField[]` or `ColumnMeta[]`. |
| `Form` | Conform + Zod form wrapper — POSTs to a route and surfaces field errors. |
| `useFormContext` | Reads the current `Form`'s conform metadata; throws outside a `Form`. |
| `FormField` | One labeled input, switched on its `type` prop (see below). |
| `FormError` | Renders the form-level error from `useFormContext`. |
| `FormSection` | Labeled fieldset grouping for `AutoForm`/`Form` fields. |
| `FormSubmit` | Submit button that reflects the form's pending state. |
| `AsyncSelect` | Debounced async-search select, used by reference fields. |
| `ResolvedField` (type) | The server-resolved field shape `AutoForm` consumes — see `field-types.ts`. |

**AutoFormProps**
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `action` | `string` | yes | POST target for the submission — see `FormProps.action` (`Form.tsx`). |
| `fields` | `array` | no | Explicit field specs from a resource's `create.fields` / `update.fields` (resolved server-side). |
| `columns` | `array` | no |  |
| `hide` | `array` | no |  |
| `defaultValues` | `Record<string, unknown>` | no |  |
| `submitLabel` | `string` | no |  |
| `className` | `string` | no |  |
| `redirectTo` | `string` | no | Client-side navigation target on a successful submit — see `FormProps.redirectTo`. |

**FormProps**
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `action` | `string` | yes |  |
| `schema` | `S` | yes |  |
| `defaultValues` | `Partial<output<S>>` | no |  |
| `children` | `ReactNode` | yes |  |
| `className` | `string` | no |  |
| `id` | `string` | no |  |
| `redirectTo` | `string` | no | Where to navigate after a successful submit (e.g. back to the list, or to the created row). |

**FieldProps**
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | `string` | yes |  |
| `label` | `string` | no |  |
| `help` | `string` | no |  |
| `placeholder` | `string` | no |  |
| `type` | `FieldControlType` | no |  |
| `required` | `boolean` | no |  |
| `options` | `array` | no |  |
| `autoComplete` | `string` | no |  |
| `readOnly` | `boolean` | no | Render the control non-editable while keeping its value in the submission. |
| `referenceSearchUrl` | `string` | no |  |

The component is declared internally as `Field` with a `FieldProps` interface,
but the package **renames both on export**: the value is exported as
`FormField` and the type as `FormFieldProps`. `Field` and `FieldProps` are not
importable names — the prefix keeps them from colliding with the many other
`Field` components a consuming app is likely to have. The interface is
unchanged by the rename; the property table above is generated from it.

`FormField`'s `type` prop accepts:

```ts excerpt
"text" | "email" | "password" | "url" | "number" | "date" | "datetime" |
"datetime-local" | "time" | "color" | "search" | "textarea" | "markdown" |
"json" | "tags" | "select" | "multiselect" | "radio" | "reference" |
"boolean" | "switch" | "checkbox" | "hidden"
```

That union is internal — it has a name in the source (`FieldControlType`) but
is not exported, so type it inline or read it off
`ComponentProps<typeof FormField>["type"]`. It is a *superset* of the
config-level `FieldType`: `datetime-local` and `search` exist only here, which
is why a `ResolvedField` (typed `FieldType`) always assigns cleanly into it and
not the other way round.

## Feedback

Empty, error, loading and toast states.

| Export | Purpose |
| --- | --- |
| `EmptyState`, `DefaultEmptyState` | "Nothing here" placeholder and its default renderer. |
| `ErrorState` | Inline error placeholder with an optional retry action. |
| `ErrorCard` | Error display for a caught `Error`, with an optional retry callback. |
| `HealthBanner` | Toned banner (e.g. degraded queue, stale data) shown above content. |
| `ConfirmDialog`, `DefaultConfirmDialog` | Confirmation modal for destructive actions and its default renderer. |
| `SkeletonCard`, `SkeletonTable`, `DefaultSkeletonTable` | Loading placeholders for a card and a table, and the table's default renderer. |
| `ResourceListSkeleton`, `ResourceDetailSkeleton`, `DashboardSkeleton` | Page-level loading skeletons for the three page kinds. |
| `Toast`, `ToastProvider`, `useToast` | Toast host provider and the hook to fire toasts from anywhere under it. |

## Widgets

Dashboard widget renderers — the components a `widget()` builder's config
resolves into.

| Export | Purpose |
| --- | --- |
| `MetricCard`, `DefaultMetricCard` | Renders a `metric()` widget and its default look. |
| `StatGroupCard` | Renders a `statGroup()` widget. |
| `TableWidget` | Renders a `table()` widget, reusing `DataTable`. |
| `CustomWidget` | Wraps a `custom()` widget's component with the shared widget frame. |

### Layout primitives

Shared by widgets and by hand-built pages.

| Export | Purpose |
| --- | --- |
| `Card`, `CardHeader`, `CardContent`, `CardDescription` | Generic card shell and its section slots. |
| `MetricGrid` | Responsive grid for laying out `MetricCard`s. |
| `Section`, `SectionLabel`, `Divider`, `spanClass` | Section wrapper with a label/description, a divider rule, and the `Span` → CSS class map dashboards use for widget width. |

## Atoms

Small, single-purpose display components.

| Export | Purpose |
| --- | --- |
| `Avatar`, `DefaultAvatar` | User/entity avatar and its default renderer. |
| `Badge`, `DefaultBadge` | Toned inline badge and its default renderer. |
| `StatusBadge`, `DefaultStatusBadge` | Badge preset for status-like values, and its default renderer. |
| `StatusDot` | Small toned dot, e.g. for realtime/queue status. |
| `LiveIndicator` | Realtime connection status indicator (see `LiveStatus`). |
| `LocalTime` | Absolute timestamp rendered in the viewer's timezone. |
| `TimeAgo` | Relative timestamp that ticks (`"3m ago"`), re-rendering on an interval. |
| `Sparkline` | Minimal inline trend line for a numeric series. |
| `Mono` | Monospace inline text, for IDs and code-like values. |
| `FlowpanelIcon` | Renders a public `IconName` as the same decorative Lucide SVG used by nav and actions. |

**FlowpanelIconProps**
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | `IconName` | yes |  |
| `string` | `number \| string` | no |  |
| `suppressHydrationWarning` | `boolean` | no |  |
| `className` | `string` | no |  |
| `color` | `string` | no |  |
| `height` | `number \| string` | no |  |
| `id` | `string` | no |  |
| `lang` | `string` | no |  |
| `max` | `number \| string` | no |  |
| `media` | `string` | no |  |
| `method` | `string` | no |  |
| `min` | `number \| string` | no |  |
| `nonce` | `string` | no |  |
| `part` | `string` | no |  |
| `slot` | `string` | no |  |
| `style` | `object` | no |  |
| `target` | `string` | no |  |
| `type` | `string` | no |  |
| `width` | `number \| string` | no |  |
| `role` | `"treeitem" \| "treegrid" \| "tree" \| "tooltip" \| "toolbar" \| "timer" \| "textbox" \| "term" \| "tabpanel" \| "tablist" \| "table" \| "tab" \| "switch" \| "status" \| "spinbutton" \| "slider" \| "separator" \| "searchbox" \| "scrollbar" \| "rowheader" \| "rowgroup" \| "row" \| "region" \| "radiogroup" \| "radio" \| "progressbar" \| "presentation" \| "option" \| "note" \| "none" \| "navigation" \| "menuitemradio" \| "menuitemcheckbox" \| "menuitem" \| "menubar" \| "menu" \| "math" \| "marquee" \| "main" \| "log" \| "listitem" \| "listbox" \| "link" \| "img" \| "heading" \| "group" \| "gridcell" \| "grid" \| "form" \| "figure" \| "feed" \| "document" \| "directory" \| "dialog" \| "definition" \| "contentinfo" \| "complementary" \| "combobox" \| "columnheader" \| "checkbox" \| "cell" \| "button" \| "banner" \| "article" \| "application" \| "alertdialog" \| "alert" \| object & string \| "search" \| "list"` | no |  |
| `tabIndex` | `number` | no |  |
| `crossOrigin` | `CrossOrigin` | no |  |
| `accentHeight` | `number \| string` | no |  |
| `accumulate` | `"sum" \| "none"` | no |  |
| `additive` | `"replace" \| "sum"` | no |  |
| `alignmentBaseline` | `"inherit" \| "text-after-edge" \| "after-edge" \| "central" \| "middle" \| "text-before-edge" \| "before-edge" \| "baseline" \| "auto" \| "mathematical" \| "ideographic" \| "hanging" \| "alphabetic"` | no |  |
| `allowReorder` | `"yes" \| "no"` | no |  |
| `alphabetic` | `number \| string` | no |  |
| `amplitude` | `number \| string` | no |  |
| `arabicForm` | `"isolated" \| "terminal" \| "medial" \| "initial"` | no |  |
| `ascent` | `number \| string` | no |  |
| `attributeName` | `string` | no |  |
| `attributeType` | `string` | no |  |
| `autoReverse` | `"false" \| "true" \| boolean` | no |  |
| `azimuth` | `number \| string` | no |  |
| `baseFrequency` | `number \| string` | no |  |
| `baselineShift` | `number \| string` | no |  |
| `baseProfile` | `number \| string` | no |  |
| `bbox` | `number \| string` | no |  |
| `begin` | `number \| string` | no |  |
| `bias` | `number \| string` | no |  |
| `by` | `number \| string` | no |  |
| `calcMode` | `number \| string` | no |  |
| `capHeight` | `number \| string` | no |  |
| `clip` | `number \| string` | no |  |
| `clipPath` | `string` | no |  |
| `clipPathUnits` | `number \| string` | no |  |
| `clipRule` | `number \| string` | no |  |
| `colorInterpolation` | `number \| string` | no |  |
| `colorInterpolationFilters` | `"linearRGB" \| "sRGB" \| "inherit" \| "auto"` | no |  |
| `colorProfile` | `number \| string` | no |  |
| `colorRendering` | `number \| string` | no |  |
| `contentScriptType` | `number \| string` | no |  |
| `contentStyleType` | `number \| string` | no |  |
| `cursor` | `number \| string` | no |  |
| `cx` | `number \| string` | no |  |
| `cy` | `number \| string` | no |  |
| `d` | `string` | no |  |
| `decelerate` | `number \| string` | no |  |
| `descent` | `number \| string` | no |  |
| `diffuseConstant` | `number \| string` | no |  |
| `direction` | `number \| string` | no |  |
| `display` | `number \| string` | no |  |
| `divisor` | `number \| string` | no |  |
| `dominantBaseline` | `"reset-size" \| "no-change" \| "use-script" \| "inherit" \| "text-after-edge" \| "central" \| "middle" \| "text-before-edge" \| "auto" \| "mathematical" \| "ideographic" \| "hanging" \| "alphabetic"` | no |  |
| `dur` | `number \| string` | no |  |
| `dx` | `number \| string` | no |  |
| `dy` | `number \| string` | no |  |
| `edgeMode` | `number \| string` | no |  |
| `elevation` | `number \| string` | no |  |
| `enableBackground` | `number \| string` | no |  |
| `end` | `number \| string` | no |  |
| `exponent` | `number \| string` | no |  |
| `externalResourcesRequired` | `"false" \| "true" \| boolean` | no |  |
| `fill` | `string` | no |  |
| `fillOpacity` | `number \| string` | no |  |
| `fillRule` | `"evenodd" \| "nonzero" \| "inherit"` | no |  |
| `filter` | `string` | no |  |
| `filterRes` | `number \| string` | no |  |
| `filterUnits` | `number \| string` | no |  |
| `floodColor` | `number \| string` | no |  |
| `floodOpacity` | `number \| string` | no |  |
| `focusable` | `"false" \| "true" \| "auto" \| boolean` | no |  |
| `fontFamily` | `string` | no |  |
| `fontSize` | `number \| string` | no |  |
| `fontSizeAdjust` | `number \| string` | no |  |
| `fontStretch` | `number \| string` | no |  |
| `fontStyle` | `number \| string` | no |  |
| `fontVariant` | `number \| string` | no |  |
| `fontWeight` | `number \| string` | no |  |
| `format` | `number \| string` | no |  |
| `fr` | `number \| string` | no |  |
| `from` | `number \| string` | no |  |
| `fx` | `number \| string` | no |  |
| `fy` | `number \| string` | no |  |
| `g1` | `number \| string` | no |  |
| `g2` | `number \| string` | no |  |
| `glyphName` | `number \| string` | no |  |
| `glyphOrientationHorizontal` | `number \| string` | no |  |
| `glyphOrientationVertical` | `number \| string` | no |  |
| `glyphRef` | `number \| string` | no |  |
| `gradientTransform` | `string` | no |  |
| `gradientUnits` | `string` | no |  |
| `hanging` | `number \| string` | no |  |
| `horizAdvX` | `number \| string` | no |  |
| `horizOriginX` | `number \| string` | no |  |
| `href` | `string` | no |  |
| `ideographic` | `number \| string` | no |  |
| `imageRendering` | `number \| string` | no |  |
| `in2` | `number \| string` | no |  |
| `in` | `string` | no |  |
| `intercept` | `number \| string` | no |  |
| `k1` | `number \| string` | no |  |
| `k2` | `number \| string` | no |  |
| `k3` | `number \| string` | no |  |
| `k4` | `number \| string` | no |  |
| `k` | `number \| string` | no |  |
| `kernelMatrix` | `number \| string` | no |  |
| `kernelUnitLength` | `number \| string` | no |  |
| `kerning` | `number \| string` | no |  |
| `keyPoints` | `number \| string` | no |  |
| `keySplines` | `number \| string` | no |  |
| `keyTimes` | `number \| string` | no |  |
| `lengthAdjust` | `number \| string` | no |  |
| `letterSpacing` | `number \| string` | no |  |
| `lightingColor` | `number \| string` | no |  |
| `limitingConeAngle` | `number \| string` | no |  |
| `local` | `number \| string` | no |  |
| `markerEnd` | `string` | no |  |
| `markerHeight` | `number \| string` | no |  |
| `markerMid` | `string` | no |  |
| `markerStart` | `string` | no |  |
| `markerUnits` | `number \| string` | no |  |
| `markerWidth` | `number \| string` | no |  |
| `mask` | `string` | no |  |
| `maskContentUnits` | `number \| string` | no |  |
| `maskUnits` | `number \| string` | no |  |
| `mathematical` | `number \| string` | no |  |
| `mode` | `number \| string` | no |  |
| `numOctaves` | `number \| string` | no |  |
| `offset` | `number \| string` | no |  |
| `opacity` | `number \| string` | no |  |
| `operator` | `number \| string` | no |  |
| `order` | `number \| string` | no |  |
| `orient` | `number \| string` | no |  |
| `orientation` | `number \| string` | no |  |
| `origin` | `number \| string` | no |  |
| `overflow` | `number \| string` | no |  |
| `overlinePosition` | `number \| string` | no |  |
| `overlineThickness` | `number \| string` | no |  |
| `paintOrder` | `number \| string` | no |  |
| `panose1` | `number \| string` | no |  |
| `path` | `string` | no |  |
| `pathLength` | `number \| string` | no |  |
| `patternContentUnits` | `string` | no |  |
| `patternTransform` | `number \| string` | no |  |
| `patternUnits` | `string` | no |  |
| `pointerEvents` | `number \| string` | no |  |
| `points` | `string` | no |  |
| `pointsAtX` | `number \| string` | no |  |
| `pointsAtY` | `number \| string` | no |  |
| `pointsAtZ` | `number \| string` | no |  |
| `preserveAlpha` | `"false" \| "true" \| boolean` | no |  |
| `preserveAspectRatio` | `string` | no |  |
| `primitiveUnits` | `number \| string` | no |  |
| `r` | `number \| string` | no |  |
| `radius` | `number \| string` | no |  |
| `refX` | `number \| string` | no |  |
| `refY` | `number \| string` | no |  |
| `renderingIntent` | `number \| string` | no |  |
| `repeatCount` | `number \| string` | no |  |
| `repeatDur` | `number \| string` | no |  |
| `requiredExtensions` | `number \| string` | no |  |
| `requiredFeatures` | `number \| string` | no |  |
| `restart` | `number \| string` | no |  |
| `result` | `string` | no |  |
| `rotate` | `number \| string` | no |  |
| `rx` | `number \| string` | no |  |
| `ry` | `number \| string` | no |  |
| `scale` | `number \| string` | no |  |
| `seed` | `number \| string` | no |  |
| `shapeRendering` | `number \| string` | no |  |
| `slope` | `number \| string` | no |  |
| `spacing` | `number \| string` | no |  |
| `specularConstant` | `number \| string` | no |  |
| `specularExponent` | `number \| string` | no |  |
| `speed` | `number \| string` | no |  |
| `spreadMethod` | `string` | no |  |
| `startOffset` | `number \| string` | no |  |
| `stdDeviation` | `number \| string` | no |  |
| `stemh` | `number \| string` | no |  |
| `stemv` | `number \| string` | no |  |
| `stitchTiles` | `number \| string` | no |  |
| `stopColor` | `string` | no |  |
| `stopOpacity` | `number \| string` | no |  |
| `strikethroughPosition` | `number \| string` | no |  |
| `strikethroughThickness` | `number \| string` | no |  |
| `stroke` | `string` | no |  |
| `strokeDasharray` | `number \| string` | no |  |
| `strokeDashoffset` | `number \| string` | no |  |
| `strokeLinecap` | `"square" \| "round" \| "butt" \| "inherit"` | no |  |
| `strokeLinejoin` | `"bevel" \| "miter" \| "round" \| "inherit"` | no |  |
| `strokeMiterlimit` | `number \| string` | no |  |
| `strokeOpacity` | `number \| string` | no |  |
| `strokeWidth` | `number \| string` | no |  |
| `surfaceScale` | `number \| string` | no |  |
| `systemLanguage` | `number \| string` | no |  |
| `tableValues` | `number \| string` | no |  |
| `targetX` | `number \| string` | no |  |
| `targetY` | `number \| string` | no |  |
| `textAnchor` | `"start" \| "inherit" \| "middle" \| "end"` | no |  |
| `textDecoration` | `number \| string` | no |  |
| `textLength` | `number \| string` | no |  |
| `textRendering` | `number \| string` | no |  |
| `to` | `number \| string` | no |  |
| `transform` | `string` | no |  |
| `u1` | `number \| string` | no |  |
| `u2` | `number \| string` | no |  |
| `underlinePosition` | `number \| string` | no |  |
| `underlineThickness` | `number \| string` | no |  |
| `unicode` | `number \| string` | no |  |
| `unicodeBidi` | `number \| string` | no |  |
| `unicodeRange` | `number \| string` | no |  |
| `unitsPerEm` | `number \| string` | no |  |
| `vAlphabetic` | `number \| string` | no |  |
| `values` | `string` | no |  |
| `vectorEffect` | `number \| string` | no |  |
| `version` | `string` | no |  |
| `vertAdvY` | `number \| string` | no |  |
| `vertOriginX` | `number \| string` | no |  |
| `vertOriginY` | `number \| string` | no |  |
| `vHanging` | `number \| string` | no |  |
| `vIdeographic` | `number \| string` | no |  |
| `viewBox` | `string` | no |  |
| `viewTarget` | `number \| string` | no |  |
| `visibility` | `number \| string` | no |  |
| `vMathematical` | `number \| string` | no |  |
| `widths` | `number \| string` | no |  |
| `wordSpacing` | `number \| string` | no |  |
| `writingMode` | `number \| string` | no |  |
| `x1` | `number \| string` | no |  |
| `x2` | `number \| string` | no |  |
| `x` | `number \| string` | no |  |
| `xChannelSelector` | `string` | no |  |
| `xHeight` | `number \| string` | no |  |
| `xlinkActuate` | `string` | no |  |
| `xlinkArcrole` | `string` | no |  |
| `xlinkHref` | `string` | no |  |
| `xlinkRole` | `string` | no |  |
| `xlinkShow` | `string` | no |  |
| `xlinkTitle` | `string` | no |  |
| `xlinkType` | `string` | no |  |
| `xmlBase` | `string` | no |  |
| `xmlLang` | `string` | no |  |
| `xmlns` | `string` | no |  |
| `xmlnsXlink` | `string` | no |  |
| `xmlSpace` | `string` | no |  |
| `y1` | `number \| string` | no |  |
| `y2` | `number \| string` | no |  |
| `y` | `number \| string` | no |  |
| `yChannelSelector` | `string` | no |  |
| `z` | `number \| string` | no |  |
| `zoomAndPan` | `string` | no |  |
| `aria-activedescendant` | `string` | no | Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. |
| `aria-atomic` | `"false" \| "true" \| boolean` | no | Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute. |
| `aria-autocomplete` | `"both" \| "inline" \| "none" \| "list"` | no | Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be
presented if they are made. |
| `aria-braillelabel` | `string` | no | Defines a string value that labels the current element, which is intended to be converted into Braille. |
| `aria-brailleroledescription` | `string` | no | Defines a human-readable, author-localized abbreviated description for the role of an element, which is intended to be converted into Braille. |
| `aria-busy` | `"false" \| "true" \| boolean` | no |  |
| `aria-checked` | `"mixed" \| "false" \| "true" \| boolean` | no | Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. |
| `aria-colcount` | `number` | no | Defines the total number of columns in a table, grid, or treegrid. |
| `aria-colindex` | `number` | no | Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. |
| `aria-colindextext` | `string` | no | Defines a human readable text alternative of aria-colindex. |
| `aria-colspan` | `number` | no | Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. |
| `aria-controls` | `string` | no | Identifies the element (or elements) whose contents or presence are controlled by the current element. |
| `aria-current` | `"time" \| "date" \| "location" \| "step" \| "page" \| "false" \| "true" \| boolean` | no | Indicates the element that represents the current item within a container or set of related elements. |
| `aria-describedby` | `string` | no | Identifies the element (or elements) that describes the object. |
| `aria-description` | `string` | no | Defines a string value that describes or annotates the current element. |
| `aria-details` | `string` | no | Identifies the element that provides a detailed, extended description for the object. |
| `aria-disabled` | `"false" \| "true" \| boolean` | no | Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable. |
| `aria-dropeffect` | `"popup" \| "move" \| "execute" \| "copy" \| "none" \| "link"` | no | Indicates what functions can be performed when a dragged object is released on the drop target. |
| `aria-errormessage` | `string` | no | Identifies the element that provides an error message for the object. |
| `aria-expanded` | `"false" \| "true" \| boolean` | no | Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. |
| `aria-flowto` | `string` | no | Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion,
allows assistive technology to override the general default of reading in document source order. |
| `aria-grabbed` | `"false" \| "true" \| boolean` | no | Indicates an element's "grabbed" state in a drag-and-drop operation. |
| `aria-haspopup` | `"false" \| "true" \| "tree" \| "menu" \| "listbox" \| "grid" \| "dialog" \| boolean` | no | Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. |
| `aria-hidden` | `"false" \| "true" \| boolean` | no | Indicates whether the element is exposed to an accessibility API. |
| `aria-invalid` | `"spelling" \| "grammar" \| "false" \| "true" \| boolean` | no | Indicates the entered value does not conform to the format expected by the application. |
| `aria-keyshortcuts` | `string` | no | Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. |
| `aria-label` | `string` | no | Defines a string value that labels the current element. |
| `aria-labelledby` | `string` | no | Identifies the element (or elements) that labels the current element. |
| `aria-level` | `number` | no | Defines the hierarchical level of an element within a structure. |
| `aria-live` | `"polite" \| "assertive" \| "off"` | no | Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region. |
| `aria-modal` | `"false" \| "true" \| boolean` | no | Indicates whether an element is modal when displayed. |
| `aria-multiline` | `"false" \| "true" \| boolean` | no | Indicates whether a text box accepts multiple lines of input or only a single line. |
| `aria-multiselectable` | `"false" \| "true" \| boolean` | no | Indicates that the user may select more than one item from the current selectable descendants. |
| `aria-orientation` | `"vertical" \| "horizontal"` | no | Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous. |
| `aria-owns` | `string` | no | Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship
between DOM elements where the DOM hierarchy cannot be used to represent the relationship. |
| `aria-placeholder` | `string` | no | Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value.
A hint could be a sample value or a brief description of the expected format. |
| `aria-posinset` | `number` | no | Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. |
| `aria-pressed` | `"mixed" \| "false" \| "true" \| boolean` | no | Indicates the current "pressed" state of toggle buttons. |
| `aria-readonly` | `"false" \| "true" \| boolean` | no | Indicates that the element is not editable, but is otherwise operable. |
| `aria-relevant` | `"text removals" \| "text additions" \| "text" \| "removals text" \| "removals additions" \| "removals" \| "all" \| "additions text" \| "additions removals" \| "additions"` | no | Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. |
| `aria-required` | `"false" \| "true" \| boolean` | no | Indicates that user input is required on the element before a form may be submitted. |
| `aria-roledescription` | `string` | no | Defines a human-readable, author-localized description for the role of an element. |
| `aria-rowcount` | `number` | no | Defines the total number of rows in a table, grid, or treegrid. |
| `aria-rowindex` | `number` | no | Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. |
| `aria-rowindextext` | `string` | no | Defines a human readable text alternative of aria-rowindex. |
| `aria-rowspan` | `number` | no | Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. |
| `aria-selected` | `"false" \| "true" \| boolean` | no | Indicates the current "selected" state of various widgets. |
| `aria-setsize` | `number` | no | Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. |
| `aria-sort` | `"other" \| "descending" \| "ascending" \| "none"` | no | Indicates if items in a table or grid are sorted in ascending or descending order. |
| `aria-valuemax` | `number` | no | Defines the maximum allowed value for a range widget. |
| `aria-valuemin` | `number` | no | Defines the minimum allowed value for a range widget. |
| `aria-valuenow` | `number` | no | Defines the current value for a range widget. |
| `aria-valuetext` | `string` | no | Defines the human readable text alternative of aria-valuenow for a range widget. |
| `children` | `ReactNode` | no |  |
| `dangerouslySetInnerHTML` | `object` | no |  |
| `onCopy` | `ClipboardEventHandler<object>` | no |  |
| `onCopyCapture` | `ClipboardEventHandler<object>` | no |  |
| `onCut` | `ClipboardEventHandler<object>` | no |  |
| `onCutCapture` | `ClipboardEventHandler<object>` | no |  |
| `onPaste` | `ClipboardEventHandler<object>` | no |  |
| `onPasteCapture` | `ClipboardEventHandler<object>` | no |  |
| `onCompositionEnd` | `CompositionEventHandler<object>` | no |  |
| `onCompositionEndCapture` | `CompositionEventHandler<object>` | no |  |
| `onCompositionStart` | `CompositionEventHandler<object>` | no |  |
| `onCompositionStartCapture` | `CompositionEventHandler<object>` | no |  |
| `onCompositionUpdate` | `CompositionEventHandler<object>` | no |  |
| `onCompositionUpdateCapture` | `CompositionEventHandler<object>` | no |  |
| `onFocus` | `FocusEventHandler<object>` | no |  |
| `onFocusCapture` | `FocusEventHandler<object>` | no |  |
| `onBlur` | `FocusEventHandler<object>` | no |  |
| `onBlurCapture` | `FocusEventHandler<object>` | no |  |
| `onChange` | `ChangeEventHandler<object, object>` | no |  |
| `onChangeCapture` | `ChangeEventHandler<object, object>` | no |  |
| `onBeforeInput` | `InputEventHandler<object>` | no |  |
| `onBeforeInputCapture` | `InputEventHandler<object>` | no |  |
| `onInput` | `InputEventHandler<object>` | no |  |
| `onInputCapture` | `InputEventHandler<object>` | no |  |
| `onReset` | `ReactEventHandler<object>` | no |  |
| `onResetCapture` | `ReactEventHandler<object>` | no |  |
| `onSubmit` | `SubmitEventHandler<object>` | no |  |
| `onSubmitCapture` | `SubmitEventHandler<object>` | no |  |
| `onInvalid` | `ReactEventHandler<object>` | no |  |
| `onInvalidCapture` | `ReactEventHandler<object>` | no |  |
| `onLoad` | `ReactEventHandler<object>` | no |  |
| `onLoadCapture` | `ReactEventHandler<object>` | no |  |
| `onError` | `ReactEventHandler<object>` | no |  |
| `onErrorCapture` | `ReactEventHandler<object>` | no |  |
| `onKeyDown` | `KeyboardEventHandler<object>` | no |  |
| `onKeyDownCapture` | `KeyboardEventHandler<object>` | no |  |
| `onKeyPress` | `KeyboardEventHandler<object>` | no |  |
| `onKeyPressCapture` | `KeyboardEventHandler<object>` | no |  |
| `onKeyUp` | `KeyboardEventHandler<object>` | no |  |
| `onKeyUpCapture` | `KeyboardEventHandler<object>` | no |  |
| `onAbort` | `ReactEventHandler<object>` | no |  |
| `onAbortCapture` | `ReactEventHandler<object>` | no |  |
| `onCanPlay` | `ReactEventHandler<object>` | no |  |
| `onCanPlayCapture` | `ReactEventHandler<object>` | no |  |
| `onCanPlayThrough` | `ReactEventHandler<object>` | no |  |
| `onCanPlayThroughCapture` | `ReactEventHandler<object>` | no |  |
| `onDurationChange` | `ReactEventHandler<object>` | no |  |
| `onDurationChangeCapture` | `ReactEventHandler<object>` | no |  |
| `onEmptied` | `ReactEventHandler<object>` | no |  |
| `onEmptiedCapture` | `ReactEventHandler<object>` | no |  |
| `onEncrypted` | `ReactEventHandler<object>` | no |  |
| `onEncryptedCapture` | `ReactEventHandler<object>` | no |  |
| `onEnded` | `ReactEventHandler<object>` | no |  |
| `onEndedCapture` | `ReactEventHandler<object>` | no |  |
| `onLoadedData` | `ReactEventHandler<object>` | no |  |
| `onLoadedDataCapture` | `ReactEventHandler<object>` | no |  |
| `onLoadedMetadata` | `ReactEventHandler<object>` | no |  |
| `onLoadedMetadataCapture` | `ReactEventHandler<object>` | no |  |
| `onLoadStart` | `ReactEventHandler<object>` | no |  |
| `onLoadStartCapture` | `ReactEventHandler<object>` | no |  |
| `onPause` | `ReactEventHandler<object>` | no |  |
| `onPauseCapture` | `ReactEventHandler<object>` | no |  |
| `onPlay` | `ReactEventHandler<object>` | no |  |
| `onPlayCapture` | `ReactEventHandler<object>` | no |  |
| `onPlaying` | `ReactEventHandler<object>` | no |  |
| `onPlayingCapture` | `ReactEventHandler<object>` | no |  |
| `onProgress` | `ReactEventHandler<object>` | no |  |
| `onProgressCapture` | `ReactEventHandler<object>` | no |  |
| `onRateChange` | `ReactEventHandler<object>` | no |  |
| `onRateChangeCapture` | `ReactEventHandler<object>` | no |  |
| `onSeeked` | `ReactEventHandler<object>` | no |  |
| `onSeekedCapture` | `ReactEventHandler<object>` | no |  |
| `onSeeking` | `ReactEventHandler<object>` | no |  |
| `onSeekingCapture` | `ReactEventHandler<object>` | no |  |
| `onStalled` | `ReactEventHandler<object>` | no |  |
| `onStalledCapture` | `ReactEventHandler<object>` | no |  |
| `onSuspend` | `ReactEventHandler<object>` | no |  |
| `onSuspendCapture` | `ReactEventHandler<object>` | no |  |
| `onTimeUpdate` | `ReactEventHandler<object>` | no |  |
| `onTimeUpdateCapture` | `ReactEventHandler<object>` | no |  |
| `onVolumeChange` | `ReactEventHandler<object>` | no |  |
| `onVolumeChangeCapture` | `ReactEventHandler<object>` | no |  |
| `onWaiting` | `ReactEventHandler<object>` | no |  |
| `onWaitingCapture` | `ReactEventHandler<object>` | no |  |
| `onAuxClick` | `MouseEventHandler<object>` | no |  |
| `onAuxClickCapture` | `MouseEventHandler<object>` | no |  |
| `onClick` | `MouseEventHandler<object>` | no |  |
| `onClickCapture` | `MouseEventHandler<object>` | no |  |
| `onContextMenu` | `MouseEventHandler<object>` | no |  |
| `onContextMenuCapture` | `MouseEventHandler<object>` | no |  |
| `onDoubleClick` | `MouseEventHandler<object>` | no |  |
| `onDoubleClickCapture` | `MouseEventHandler<object>` | no |  |
| `onDrag` | `DragEventHandler<object>` | no |  |
| `onDragCapture` | `DragEventHandler<object>` | no |  |
| `onDragEnd` | `DragEventHandler<object>` | no |  |
| `onDragEndCapture` | `DragEventHandler<object>` | no |  |
| `onDragEnter` | `DragEventHandler<object>` | no |  |
| `onDragEnterCapture` | `DragEventHandler<object>` | no |  |
| `onDragExit` | `DragEventHandler<object>` | no |  |
| `onDragExitCapture` | `DragEventHandler<object>` | no |  |
| `onDragLeave` | `DragEventHandler<object>` | no |  |
| `onDragLeaveCapture` | `DragEventHandler<object>` | no |  |
| `onDragOver` | `DragEventHandler<object>` | no |  |
| `onDragOverCapture` | `DragEventHandler<object>` | no |  |
| `onDragStart` | `DragEventHandler<object>` | no |  |
| `onDragStartCapture` | `DragEventHandler<object>` | no |  |
| `onDrop` | `DragEventHandler<object>` | no |  |
| `onDropCapture` | `DragEventHandler<object>` | no |  |
| `onMouseDown` | `MouseEventHandler<object>` | no |  |
| `onMouseDownCapture` | `MouseEventHandler<object>` | no |  |
| `onMouseEnter` | `MouseEventHandler<object>` | no |  |
| `onMouseLeave` | `MouseEventHandler<object>` | no |  |
| `onMouseMove` | `MouseEventHandler<object>` | no |  |
| `onMouseMoveCapture` | `MouseEventHandler<object>` | no |  |
| `onMouseOut` | `MouseEventHandler<object>` | no |  |
| `onMouseOutCapture` | `MouseEventHandler<object>` | no |  |
| `onMouseOver` | `MouseEventHandler<object>` | no |  |
| `onMouseOverCapture` | `MouseEventHandler<object>` | no |  |
| `onMouseUp` | `MouseEventHandler<object>` | no |  |
| `onMouseUpCapture` | `MouseEventHandler<object>` | no |  |
| `onSelect` | `ReactEventHandler<object>` | no |  |
| `onSelectCapture` | `ReactEventHandler<object>` | no |  |
| `onTouchCancel` | `TouchEventHandler<object>` | no |  |
| `onTouchCancelCapture` | `TouchEventHandler<object>` | no |  |
| `onTouchEnd` | `TouchEventHandler<object>` | no |  |
| `onTouchEndCapture` | `TouchEventHandler<object>` | no |  |
| `onTouchMove` | `TouchEventHandler<object>` | no |  |
| `onTouchMoveCapture` | `TouchEventHandler<object>` | no |  |
| `onTouchStart` | `TouchEventHandler<object>` | no |  |
| `onTouchStartCapture` | `TouchEventHandler<object>` | no |  |
| `onPointerDown` | `PointerEventHandler<object>` | no |  |
| `onPointerDownCapture` | `PointerEventHandler<object>` | no |  |
| `onPointerMove` | `PointerEventHandler<object>` | no |  |
| `onPointerMoveCapture` | `PointerEventHandler<object>` | no |  |
| `onPointerUp` | `PointerEventHandler<object>` | no |  |
| `onPointerUpCapture` | `PointerEventHandler<object>` | no |  |
| `onPointerCancel` | `PointerEventHandler<object>` | no |  |
| `onPointerCancelCapture` | `PointerEventHandler<object>` | no |  |
| `onPointerEnter` | `PointerEventHandler<object>` | no |  |
| `onPointerLeave` | `PointerEventHandler<object>` | no |  |
| `onPointerOver` | `PointerEventHandler<object>` | no |  |
| `onPointerOverCapture` | `PointerEventHandler<object>` | no |  |
| `onPointerOut` | `PointerEventHandler<object>` | no |  |
| `onPointerOutCapture` | `PointerEventHandler<object>` | no |  |
| `onGotPointerCapture` | `PointerEventHandler<object>` | no |  |
| `onGotPointerCaptureCapture` | `PointerEventHandler<object>` | no |  |
| `onLostPointerCapture` | `PointerEventHandler<object>` | no |  |
| `onLostPointerCaptureCapture` | `PointerEventHandler<object>` | no |  |
| `onScroll` | `UIEventHandler<object>` | no |  |
| `onScrollCapture` | `UIEventHandler<object>` | no |  |
| `onScrollEnd` | `UIEventHandler<object>` | no |  |
| `onScrollEndCapture` | `UIEventHandler<object>` | no |  |
| `onWheel` | `WheelEventHandler<object>` | no |  |
| `onWheelCapture` | `WheelEventHandler<object>` | no |  |
| `onAnimationStart` | `AnimationEventHandler<object>` | no |  |
| `onAnimationStartCapture` | `AnimationEventHandler<object>` | no |  |
| `onAnimationEnd` | `AnimationEventHandler<object>` | no |  |
| `onAnimationEndCapture` | `AnimationEventHandler<object>` | no |  |
| `onAnimationIteration` | `AnimationEventHandler<object>` | no |  |
| `onAnimationIterationCapture` | `AnimationEventHandler<object>` | no |  |
| `onToggle` | `ToggleEventHandler<object>` | no |  |
| `onBeforeToggle` | `ToggleEventHandler<object>` | no |  |
| `onTransitionCancel` | `TransitionEventHandler<object>` | no |  |
| `onTransitionCancelCapture` | `TransitionEventHandler<object>` | no |  |
| `onTransitionEnd` | `TransitionEventHandler<object>` | no |  |
| `onTransitionEndCapture` | `TransitionEventHandler<object>` | no |  |
| `onTransitionRun` | `TransitionEventHandler<object>` | no |  |
| `onTransitionRunCapture` | `TransitionEventHandler<object>` | no |  |
| `onTransitionStart` | `TransitionEventHandler<object>` | no |  |
| `onTransitionStartCapture` | `TransitionEventHandler<object>` | no |  |
| `key` | `typeof optimisticKey \| bigint \| number \| string \| null` | no |  |
| `size` | `number \| string` | no |  |
| `absoluteStrokeWidth` | `boolean` | no |  |

## Hooks

Client hooks for building custom admin UI. All are `"use client"`.

**`useLiveChannel(channel, onMessage, options?)`** — subscribes to one SSE
channel served by `stream()`. Connection pooling: hook instances that share
the same `endpoint` + `channel` reuse one `EventSource`, refcounted, rather
than opening one per instance. The returned `LiveStatus` runs `idle` →
`connecting` → `live`, drops to `reconnecting` while a retry is pending, and
reaches `offline` after six consecutive failed attempts (~30s); it returns to
`idle` when the subscription is torn down. Retries continue while `offline`.

```tsx excerpt
const status = useLiveChannel("resource.orders", (payload) => {
  console.log("order event", payload);
});
```

**`useAdminTable()`** — reads and writes the list URL state (`?page=`,
`?perPage=`, `?q=`, `?sort=field:dir`, `?f_<field>=value`) that `DataTable` and
`FilterBar` render from. `pageSize` is `number | null`: `null` means no
`?perPage=` is present and the resource's configured `pageSize` applies.

```tsx excerpt
const { page, pageSize, sort, setPage, setSort } = useAdminTable();
```

Every setter navigates with `router.replace`, not `push`: filters change on
each keystroke, and pushing would turn Back into a walk through the filter
history instead of a way out of the list.

**`useUrlState()`** — general-purpose typed reader/writer for the current
route's search params. `useAdminDrawer` is built on it; `useAdminTable` is
not — it reads `next/navigation` directly.

**`useTheme(options?)`** — reads the resolved light/dark/auto theme and
returns a stable `toggle`/`setTheme` that persists to `localStorage`.

```tsx excerpt
const { theme, toggle } = useTheme();
```

**`useToast()`** — fires a toast from anywhere under `ToastProvider` /
`FlowpanelGlobals`.

```tsx excerpt
const toast = useToast();
toast.success("Saved");
```

**`useOptimisticAction(serverValue, applyPatch)`** — thin wrapper over
`React.useOptimistic` + `useTransition` for an optimistic value with a pending
flag. It is offered for your own components; nothing shipped uses it —
`InlineEditCell` keeps its draft in plain `useState`.

**`useAdminCommand()`** — controls the ⌘K command palette's open state and
binds the `⌘K`/`Ctrl+K` shortcut.

**`useAdminDrawer()`** — reads/writes `?drawer=<resource>:<id>` and `?tab=`,
the URL state a drawer's open/closed state and active tab live in.

**`useDashboardParam(key, schema, fallback)`** — type-safe reader/writer for
one dashboard URL search param, validated against a Zod schema.

**`useMediaQuery(query)`** — subscribes to a CSS media query via
`useSyncExternalStore`, with a server snapshot of `false` so SSR and first
paint agree. `DataTable` uses `useMediaQuery("(max-width: 639px)")` for its
card/table breakpoint; use the same query to match it in custom UI.

```tsx excerpt
const isMobile = useMediaQuery("(max-width: 639px)");
```

## Realtime

Realtime status flows through a shared bus so many components can subscribe
without opening one `EventSource` each.

**`RealtimeProvider`** — mounts one shared `EventSource` for every descendant
`useRealtimeRefresh` call. It routes incoming envelopes (`{ channel, payload
}`) to the subscribers of that channel, coalesces the resulting
`router.refresh()`, and reconnects with backoff on error. Mount it once near
the root of a `"bare"`-shell layout; `Flowpanel`/`AdminShell` mount it for you
otherwise.

**`useRealtimeRefresh(channels, options?)`** — subscribes a component to one
or more channels and triggers a debounced `router.refresh()` on any event.
Under a `RealtimeProvider` ancestor it joins the shared bus; standalone (no
provider), `debounceMs` and `endpoint` apply directly and it opens one pooled
`EventSource` carrying its whole channel set, shared with every other
standalone subscriber of the same set.

```tsx excerpt
useRealtimeRefresh("resource.orders");
```

**`RealtimeRefresh`** — the same thing as a component, for a server tree that
has no client component to hang the hook on: `<RealtimeRefresh channels={…}
debounceMs={…} />` renders nothing and subscribes its channels. This is what
the dashboard widget renderer emits for a widget's `realtime` option.

```tsx excerpt
<RealtimeRefresh channels={["resource.orders", "scraper:tick"]} />
```

**`DevToolsPanel`** — floating "fp" panel showing realtime status, the
active-channel list and event count. Development-only: it renders `null` when
`NODE_ENV === "production"`. Mount it once, in development builds:

```tsx excerpt
{process.env.NODE_ENV !== "production" && <DevToolsPanel />}
```

**DevToolsPanelProps**
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `defaultOpen` | `boolean` | no | Initial open state of the panel. Default `false`. |

Lower-level bus access: `useRealtimeBus` (the raw `RealtimeBus`, or `null`
outside a provider), `useRealtimeStatus`, `useRealtimeStats`
(`{ channels, eventCount }`).

## Theme utilities

Non-React helpers behind `useTheme` and `ThemeScript`, for code that needs the
theme outside a component.

| Export | Purpose |
| --- | --- |
| `resolveTheme`, `readStoredTheme`, `writeStoredTheme`, `THEME_STORAGE_KEY` | Resolve the effective theme from storage + system preference, and read/write the stored choice. |
| `applyThemeClass`, `toggleTheme` | Apply a theme class to `<html>`, and flip the stored choice. |
| `buildThemeInitScript` | Builds the inline script string `ThemeScript` renders. |

`cn` (class name merge), `formatNumber`, `humanize`, `resolveFieldLabel`, and
`triggerDownload` are general-purpose utilities exported alongside these for
the same reason: components elsewhere in the package, and custom slots, both
need them.

## Name collisions with `@flowpanel/kit`

A handful of identifiers exist in both the config surface (`@flowpanel/kit`,
re-exporting `@flowpanel/core`) and here. They are **different declarations**
with the same name, so importing both into one module needs an alias.

| Name | In `@flowpanel/kit` | In `@flowpanel/kit/react` |
| --- | --- | --- |
| `TableWidget` | The `table()` builder's return **type** (`{ kind: "table"; options }`). | The **component** that renders one. |
| `CustomWidget` | The `custom()` builder's return **type**. | The **component** that wraps one. |
| `Tone` | The config-level tone vocabulary used by `format: "badge"`, widget `tone`, … | The same vocabulary, re-declared next to `formatNumber`. |
| `NumericFormat` | The widget/metric format union. | The same union, re-declared next to `formatNumber`. |
| `DrawerWidth` | `DrawerConfig["width"]`, the config option. | `DrawerProps["width"]`, the component prop — an identical union, declared separately. |

```ts excerpt
import type { TableWidget } from "@flowpanel/kit";
import { TableWidget as TableWidgetRenderer } from "@flowpanel/kit/react";
```

`FormActionResult` is a fourth collision, and the harmless kind: it is
declared **twice with identical members** — once here (what `Form` reads back
from the route it POSTs to) and once in `@flowpanel/kit/next` (what
`makeActions`' form routes answer with). Both are
`{ ok: boolean; createdKey?: string; error?: string; fieldErrors?: Record<string, string> }`, so
either import satisfies the other. They are still two declarations: if one
ever gains a member, they stop being interchangeable.

## UI primitives

`Dialog`, `Popover`, `Select`, `DropdownMenu`, `Tabs*`,
plus `Button`, `Checkbox`, `Input`, `Label`, `Skeleton`, and `Switch`, are
shadcn-derived primitives re-exported so custom slots and pages can be built
in the same visual language as the rest of the admin. Each follows its
upstream shadcn/Radix API as-is — FlowPanel does not wrap or change their
props — so shadcn's own docs apply directly. `buttonVariants` and
`DefaultButton` are FlowPanel additions alongside `Button`.
