{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "data-data-toolbar",
  "type": "registry:component",
  "title": "Data toolbars",
  "description": "The row of controls a data surface acts from",
  "author": "sudo-kw <https://github.com/sudo-kw>",
  "dependencies": [
    "@gpuix/native@0.11.0",
    "@gpuix/react@0.11.0",
    "@tanstack/pacer@0.23.1",
    "effect@4.1.2",
    "react@^19.2.4"
  ],
  "registryDependencies": [
    "https://gpuixui.sudokw.com/gpuix-primitives.json",
    "https://gpuixui.sudokw.com/gpuix-tokens.json",
    "https://gpuixui.sudokw.com/gpuix-tw.json"
  ],
  "files": [
    {
      "path": "packages/data/src/recipe.ts",
      "target": "@ui/gpuixui/data/recipe.ts",
      "type": "registry:lib",
      "content": "import type { StyleDesc } from \"@gpuix/react\";\nimport { createRecipeCache } from \"../tw/index.js\";\nimport type { Theme } from \"./theme.js\";\n\nexport const recipeStyle: (recipe: string, theme: Theme) => StyleDesc =\n  createRecipeCache(256);\n"
    },
    {
      "path": "packages/data/src/surfaces/recipe.ts",
      "target": "@ui/gpuixui/data/surfaces/recipe.ts",
      "type": "registry:lib",
      "content": "export const SURFACE_PANEL =\n  \"flex flex-col rounded-lg border border-input bg-card text-foreground\";\n\nexport const SURFACE_HEADER =\n  \"flex flex-row items-center justify-between gap-2 border-b border-input px-3 py-2\";\n\nexport const KEY_VALUE_ROW = \"flex flex-row items-center gap-2 py-1\";\n\nexport const KEY_VALUE_LABEL = \"text-xs text-muted-foreground\";\n\nexport const KEY_VALUE_VALUE = \"text-xs text-foreground\";\n\nexport const STAT_CARD =\n  \"flex flex-col gap-1 rounded-lg border border-input bg-card px-3 py-2\";\n\nexport const STAT_VALUE = \"text-2xl font-semibold text-foreground\";\n\nexport const STAT_LABEL = \"text-xs text-muted-foreground\";\n\nexport const STAT_HINT = \"text-xs text-muted-foreground\";\n\nexport const DATA_TOOLBAR =\n  \"flex flex-row items-center gap-2 rounded-md border border-input bg-muted px-2 py-1\";\n\nexport const FILTER_CLAUSE = \"flex flex-row items-center gap-2 py-1\";\n\nexport const FILTER_GROUP = \"flex flex-col gap-1 border-l border-input pl-2\";\n\nexport const ADVANCED_FILTER =\n  \"flex flex-col gap-2 rounded-lg border border-input bg-card px-3 py-2\";\n\nexport const FILTER_SENTENCE = \"text-xs text-foreground\";\n"
    },
    {
      "path": "packages/data/src/surfaces/toolbar.tsx",
      "target": "@ui/gpuixui/data/surfaces/toolbar.tsx",
      "type": "registry:component",
      "content": "/** @jsxImportSource @gpuix/react */\nimport type { Props } from \"@gpuix/react\";\nimport { mergeStyles } from \"@gpuix/react/floating\";\nimport { Input } from \"../../primitives/index.js\";\nimport { spokenText, visibleCopy } from \"../../primitives/core/index.js\";\nimport { cn } from \"../../tw/index.js\";\nimport { Debouncer } from \"@tanstack/pacer\";\nimport * as Option from \"effect/Option\";\nimport { useEffect, useMemo, useRef, type ReactNode } from \"react\";\nimport { recipeStyle } from \"../recipe.js\";\nimport { useTheme } from \"../theme.js\";\nimport { DATA_TOOLBAR } from \"./recipe.js\";\n\nexport interface ToolbarSearch {\n  readonly value: string;\n\n  readonly onValueChange: (next: string) => void;\n\n  readonly placeholder?: string;\n\n  readonly label?: string;\n\n  readonly debounceMs?: number;\n}\n\nexport interface DataToolbarProps extends Omit<Props, \"children\"> {\n  readonly children?: ReactNode;\n\n  readonly search?: ToolbarSearch;\n  readonly className?: string;\n\n  readonly testId?: string;\n}\n\nexport const DEFAULT_SEARCH_DEBOUNCE_MS = 150;\n\nexport const DEFAULT_SEARCH_LABEL = \"Search\";\n\nexport const DEFAULT_SEARCH_PLACEHOLDER = \"Search…\";\n\nconst searchWait = (milliseconds: number | undefined): number =>\n  milliseconds === undefined ||\n  !Number.isFinite(milliseconds) ||\n  milliseconds < 0\n    ? DEFAULT_SEARCH_DEBOUNCE_MS\n    : milliseconds;\n\nexport const DataToolbar = ({\n  children,\n  search,\n  className,\n  style,\n  testId,\n  ...rest\n}: DataToolbarProps) => {\n  const theme = useTheme();\n\n  const field = Option.fromNullishOr(search);\n  const wait = searchWait(search?.debounceMs);\n\n  const report = useRef<(next: string) => void>(() => {});\n  report.current = search?.onValueChange ?? (() => {});\n  const debouncer = useMemo(\n    () => new Debouncer((next: string) => report.current(next), { wait }),\n    [wait],\n  );\n\n  useEffect(() => () => debouncer.cancel(), [debouncer]);\n\n  return (\n    <div\n      {...rest}\n      style={mergeStyles(\n        recipeStyle(cn(DATA_TOOLBAR, className), theme),\n        style,\n      )}\n    >\n      {Option.match(field, {\n        onNone: () => undefined,\n        onSome: (query) => (\n          <Input\n            label={spokenText(\n              Option.fromNullishOr(query.label),\n              DEFAULT_SEARCH_LABEL,\n            )}\n            placeholder={\n              visibleCopy(query.placeholder) ?? DEFAULT_SEARCH_PLACEHOLDER\n            }\n            value={query.value}\n            onValueChange={(next) => {\n              if (wait <= 0) report.current(next);\n              else debouncer.maybeExecute(next);\n            }}\n            size=\"sm\"\n            testId={\n              testId === undefined ? \"toolbar-search\" : `${testId}-search`\n            }\n          />\n        ),\n      })}\n      {children}\n    </div>\n  );\n};\n"
    },
    {
      "path": "packages/data/src/theme.ts",
      "target": "@ui/gpuixui/data/theme.ts",
      "type": "registry:lib",
      "content": "import type { Theme } from \"../tokens/index.js\";\nimport { useTheme as useTokenTheme } from \"../tokens/react.js\";\n\nexport {\n  controlFocusRing,\n  dividerOn,\n  pointerWash,\n  textStyle,\n  themeColors,\n} from \"../tokens/index.js\";\nexport type { Theme };\n\nexport const useTheme = (): Theme => useTokenTheme();\n"
    }
  ],
  "docs": "[Data toolbars](https://gpuixui.sudokw.com/data-display/data-toolbar) — These are GPUix native components: the files render through GPUix's reconciler against `@gpuix/react`, not the DOM, and need the per-platform `@gpuix/native` binding. The CLI installs the `@gpuixui/*` runtime the components import as registry items, so the copied tree resolves on its own; wrap it in `ThemeProvider` before it renders.",
  "meta": {
    "url": "/data-display/data-toolbar",
    "kind": "component",
    "runtime": "gpuix",
    "registry": "gpuixui"
  }
}