{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "core-sampler-keyboard",
  "type": "registry:ui",
  "title": "Sampler Keyboard",
  "description": "The piano keyboard painted with a sampler instrument's own facts: exact mapped-key coverage with every unmapped key muted per key, per-group coverage in distinct zone colours for a kit-style mapping, authored key colour ranges as instrument formats write them, and a playable range that mutes what the instrument cannot sound. Strike velocity, glissando, the held map and computer-keyboard input are the piano keyboard's. The sampler module's face and the Studio sampler editor draw this one control.",
  "dependencies": [
    "maruaudio@>=0.0.3 <0.1.0"
  ],
  "registryDependencies": [
    "https://pluginui.com/r/core-piano-keyboard.json"
  ],
  "files": [
    {
      "path": "components/ui/sampler-keyboard.tsx",
      "content": "/**\n * Source: https://maru.audio/ui-kit/sampler-keyboard\n * Copyright © [Maru](https://maru.audio)\n *\n * Maru UI Kit — https://maru.audio/ui-kit\n *\n * Installed from the Maru UI registry. This file is yours now: edit it\n * freely, it will not be overwritten unless you re-run the add command.\n *\n * Keep this item’s companion files and CSS imports together. Dependencies\n * declared by the registry are installed with the source.\n */\n/**\n * SamplerKeyboard — the piano keyboard that eats a sampler instrument's own\n * keybed declaration.\n *\n * A sampler knows two things about its keys that a synth does not: which\n * spans the instrument's author coloured (Decent Sampler's `<keyboard>`\n * ranges, a kit's zone map) and which keys can sound at all (the program's\n * playable range). This component takes both in the shapes the import and\n * program layers already produce — hex-ARGB colour ranges and an inclusive\n * MIDI range — converts them once, and hands `PianoKeyboard` the resulting\n * `keySpans`. Everything else (playing, `held`, computer keyboard,\n * read-only mode) is the piano keyboard's own contract, forwarded untouched.\n *\n * The point of standardising this is the header of\n * `sampler-keyboard-model.ts`: a custom sampler face imports this one\n * component and feeds it the parsed instrument, rather than re-deriving key\n * washes from format data every time.\n */\n\nimport { useMemo } from \"react\"\nimport {\n  PianoKeyboard,\n  type PianoKeyboardProps,\n} from \"@/components/ui/piano-keyboard\"\nimport {\n  samplerGroupCoverage,\n  samplerKeySpans,\n  type SamplerColorRange,\n  type SamplerCoverageRange,\n  type SamplerKeyRange,\n} from \"maruaudio/ui/shared/sampler-keyboard-model\"\n\nexport interface SamplerKeyboardProps\n  extends Omit<PianoKeyboardProps, \"keySpans\"> {\n  /** Authored key colourings, hex ARGB as instrument formats write them. */\n  colorRanges?: readonly SamplerColorRange[]\n  /**\n   * Keys the instrument can sound. `undefined` mutes nothing; `null` — a\n   * program with nothing playable — mutes the whole keybed; a range mutes\n   * the keys outside it. Pass `program.playableRange()` straight in.\n   * Superseded by `coverage` when that is given.\n   */\n  playableRange?: SamplerKeyRange | null\n  /**\n   * EXACT mapped-key coverage — the regions' merged key ranges. When given,\n   * mapped keys get the coverage paint and every unmapped key is muted, per\n   * key rather than per bounding box (the Kontakt/Decent Sampler keybed\n   * presentation). Ranges may carry their own `color`. Overrides\n   * `playableRange` for muting.\n   */\n  coverage?: readonly SamplerCoverageRange[]\n  /**\n   * Per-group exact coverage (`ParsedInstrument.groupCoverage`): each group's\n   * zones paint a distinct colour from {@link SAMPLER_ZONE_COLORS}, the\n   * Kontakt kit-mapping presentation. Supersedes `coverage` when non-empty.\n   */\n  groupCoverage?: readonly (readonly SamplerKeyRange[])[]\n  /** CSS colour for the mapped-key paint; defaults to the classic blue. */\n  coverageColor?: string\n}\n\nexport function SamplerKeyboard({\n  colorRanges,\n  playableRange,\n  coverage,\n  groupCoverage,\n  coverageColor,\n  ...keyboard\n}: SamplerKeyboardProps) {\n  const keySpans = useMemo(() => {\n    const covered = groupCoverage !== undefined && groupCoverage.length > 0\n      ? samplerGroupCoverage(groupCoverage)\n      : coverage\n    return samplerKeySpans(colorRanges, playableRange, covered, coverageColor)\n  }, [colorRanges, playableRange, coverage, groupCoverage, coverageColor])\n  return <PianoKeyboard {...keyboard} keySpans={keySpans} />\n}\n",
      "type": "registry:component",
      "target": "@ui/sampler-keyboard.tsx"
    }
  ]
}
