{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "gpuix-keyboard",
  "type": "registry:lib",
  "title": "Runtime: keyboard",
  "description": "The `@gpuixui/keyboard` modules the component items import. Installed automatically with the component; not a component itself.",
  "author": "Cyberistic <https://github.com/Cyberistic>",
  "dependencies": [
    "@gpuix/native@0.11.0",
    "@gpuix/react@0.11.0",
    "@tanstack/hotkeys@0.24.0",
    "effect@4.1.2"
  ],
  "files": [
    {
      "path": "packages/keyboard/src/chord.ts",
      "target": "@ui/gpuixui/keyboard/chord.ts",
      "type": "registry:lib",
      "content": "import {\n  normalizeKeyName,\n  parseHotkey,\n  type ParsedHotkeyChord,\n} from \"@tanstack/hotkeys\";\nimport { toDomKey } from \"./key-names.js\";\nimport { toTanstackPlatform, type Platform } from \"./platform.js\";\n\nexport const canonicalKey = (key: string): string =>\n  normalizeKeyName(toDomKey(key));\n\n/** A physical chord (`Mod+[KeyS]`) names a code, not a key, and stays as parsed. */\nconst canonicalChord = (chord: ParsedHotkeyChord): ParsedHotkeyChord =>\n  chord.key === undefined ? chord : { ...chord, key: canonicalKey(chord.key) };\n\n/** One chord of a binding, parsed with its key name in canonical spelling. */\nexport const parseChord = (\n  chord: string,\n  platform: Platform,\n): ParsedHotkeyChord =>\n  canonicalChord(parseHotkey(chord, toTanstackPlatform(platform)));\n\n/** A binding's chords in order: one for `\"mod+s\"`, two for `[\"g\", \"g\"]`. */\nexport const parseBinding = (\n  binding: string | ReadonlyArray<string>,\n  platform: Platform,\n): ReadonlyArray<ParsedHotkeyChord> =>\n  typeof binding === \"string\"\n    ? [parseChord(binding, platform)]\n    : binding.map((chord) => parseChord(chord, platform));\n"
    },
    {
      "path": "packages/keyboard/src/decode.ts",
      "target": "@ui/gpuixui/keyboard/decode.ts",
      "type": "registry:lib",
      "content": "import type { EventPayload } from \"@gpuix/react\";\nimport { parseHotkey, type ParsedHotkeyChord } from \"@tanstack/hotkeys\";\nimport { canonicalKey } from \"./chord.js\";\nimport { toTanstackPlatform, type Platform } from \"./platform.js\";\n\nexport const decodeGpuixEvent = (\n  event: EventPayload,\n  platform: Platform,\n): ParsedHotkeyChord =>\n  parseHotkey(\n    {\n      key: canonicalKey(event.key ?? \"\"),\n      ctrl: event.modifiers?.ctrl === true,\n      shift: event.modifiers?.shift === true,\n      alt: event.modifiers?.alt === true,\n      meta: event.modifiers?.cmd === true,\n    },\n    toTanstackPlatform(platform),\n  );\n"
    },
    {
      "path": "packages/keyboard/src/display.ts",
      "target": "@ui/gpuixui/keyboard/display.ts",
      "type": "registry:lib",
      "content": "import { formatForDisplay } from \"@tanstack/hotkeys\";\nimport { parseChord } from \"./chord.js\";\nimport { toTanstackPlatform, type Platform } from \"./platform.js\";\n\nexport const formatSymbols = (\n  accelerator: string,\n  platform: Platform,\n): ReadonlyArray<string> =>\n  formatForDisplay(parseChord(accelerator, platform), {\n    platform: toTanstackPlatform(platform),\n    parts: true,\n  });\n"
    },
    {
      "path": "packages/keyboard/src/index.ts",
      "target": "@ui/gpuixui/keyboard/index.ts",
      "type": "registry:lib",
      "content": "export { canonicalKey } from \"./chord.js\";\nexport { decodeGpuixEvent } from \"./decode.js\";\nexport { formatSymbols } from \"./display.js\";\nexport { toDomKey } from \"./key-names.js\";\nexport {\n  resolve,\n  type Binding,\n  type KeyBinding,\n  type Keymap,\n  type Scope,\n} from \"./keymap.js\";\nexport { match } from \"./match.js\";\nexport {\n  makeSequenceMatcher,\n  type SequenceMatcher,\n  type SequenceMatcherOptions,\n} from \"./sequence.js\";\nexport {\n  CommandRegistry,\n  commandRegistry,\n  makeCommandRegistry,\n  type Command,\n  type CommandRegistryService,\n} from \"./registry.js\";\nexport { toTanstackPlatform, type Platform } from \"./platform.js\";\nexport {\n  areHotkeysEqual,\n  formatForDisplay,\n  hasNonModifierKey,\n  normalizeHotkey,\n  parseHotkey,\n  validateHotkey,\n} from \"@tanstack/hotkeys\";\nexport type {\n  Hotkey,\n  HotkeyChord,\n  HotkeySequence,\n  ParsedHotkeyChord,\n} from \"@tanstack/hotkeys\";\n"
    },
    {
      "path": "packages/keyboard/src/key-names.ts",
      "target": "@ui/gpuixui/keyboard/key-names.ts",
      "type": "registry:lib",
      "content": "/** GPUI's named keys, as GPUix reports them, by the DOM value each one is. */\nconst GPUIX_NAMED_KEYS: Readonly<Record<string, string>> = {\n  backspace: \"Backspace\",\n  delete: \"Delete\",\n  down: \"ArrowDown\",\n  end: \"End\",\n  enter: \"Enter\",\n  escape: \"Escape\",\n  home: \"Home\",\n  insert: \"Insert\",\n  left: \"ArrowLeft\",\n  pagedown: \"PageDown\",\n  pageup: \"PageUp\",\n  right: \"ArrowRight\",\n  space: \" \",\n  tab: \"Tab\",\n  up: \"ArrowUp\",\n};\n\n/** Other spellings people write in a binding. */\nconst BINDING_ALIASES: Readonly<Record<string, string>> = {\n  del: \"Delete\",\n  esc: \"Escape\",\n  pgdn: \"PageDown\",\n  pgup: \"PageUp\",\n  return: \"Enter\",\n  spacebar: \" \",\n};\n\nconst DOM_KEY = new Map<string, string>([\n  ...Object.entries(GPUIX_NAMED_KEYS),\n  ...Object.entries(BINDING_ALIASES),\n  ...Object.values(GPUIX_NAMED_KEYS).map((dom): [string, string] => [\n    dom.toLowerCase(),\n    dom,\n  ]),\n]);\n\nconst FUNCTION_KEY = /^f([1-9]|[1-2]\\d|3[0-5])$/i;\n\nexport const toDomKey = (name: string): string => {\n  const named = DOM_KEY.get(name.toLowerCase());\n  if (named !== undefined) return named;\n  const fn = FUNCTION_KEY.exec(name);\n  return fn === null ? name : `F${fn[1]}`;\n};\n"
    },
    {
      "path": "packages/keyboard/src/keymap.ts",
      "target": "@ui/gpuixui/keyboard/keymap.ts",
      "type": "registry:lib",
      "content": "import * as Arr from \"effect/Array\";\nimport * as Option from \"effect/Option\";\nimport { areHotkeysEqual, type ParsedHotkeyChord } from \"@tanstack/hotkeys\";\nimport { parseBinding } from \"./chord.js\";\nimport { toTanstackPlatform, type Platform } from \"./platform.js\";\n\nconst singleChord = (\n  hotkey: Binding,\n  platform: Platform,\n): Option.Option<ParsedHotkeyChord> => {\n  const chords = parseBinding(hotkey, platform);\n  return chords.length === 1 ? Arr.head(chords) : Option.none();\n};\n\nexport type Scope = string;\n\nexport type Binding = string | ReadonlyArray<string>;\n\nexport interface KeyBinding {\n  readonly hotkey: Binding;\n  readonly commandId: string;\n  readonly scope: Scope;\n}\n\nexport interface Keymap {\n  readonly bindings: ReadonlyArray<KeyBinding>;\n}\n\nexport const resolve = (\n  keymap: Keymap,\n  scopes: ReadonlyArray<Scope>,\n  chord: ParsedHotkeyChord,\n  platform: Platform,\n): Option.Option<string> =>\n  Arr.reduce(scopes, Option.none<string>(), (command, scope) =>\n    Option.isSome(command)\n      ? command\n      : Option.map(\n          Arr.findFirst(\n            keymap.bindings,\n            (binding) =>\n              binding.scope === scope &&\n              singleChord(binding.hotkey, platform).pipe(\n                Option.exists((bound) =>\n                  areHotkeysEqual(bound, chord, toTanstackPlatform(platform)),\n                ),\n              ),\n          ),\n          (binding) => binding.commandId,\n        ),\n  );\n"
    },
    {
      "path": "packages/keyboard/src/match.ts",
      "target": "@ui/gpuixui/keyboard/match.ts",
      "type": "registry:lib",
      "content": "import type { EventPayload } from \"@gpuix/react\";\nimport { areHotkeysEqual } from \"@tanstack/hotkeys\";\nimport { parseBinding } from \"./chord.js\";\nimport { decodeGpuixEvent } from \"./decode.js\";\nimport type { Binding } from \"./keymap.js\";\nimport { toTanstackPlatform, type Platform } from \"./platform.js\";\n\nexport const match = (\n  binding: Binding,\n  event: EventPayload,\n  platform: Platform,\n): boolean => {\n  const chords = parseBinding(binding, platform);\n  const [only] = chords;\n  return (\n    chords.length === 1 &&\n    only !== undefined &&\n    areHotkeysEqual(\n      only,\n      decodeGpuixEvent(event, platform),\n      toTanstackPlatform(platform),\n    )\n  );\n};\n"
    },
    {
      "path": "packages/keyboard/src/platform.ts",
      "target": "@ui/gpuixui/keyboard/platform.ts",
      "type": "registry:lib",
      "content": "export type Platform = \"darwin\" | \"linux\" | \"win32\" | \"default\";\n\nexport type TanstackPlatform = \"mac\" | \"windows\" | \"linux\";\n\nexport const toTanstackPlatform = (platform: Platform): TanstackPlatform =>\n  platform === \"darwin\" ? \"mac\" : platform === \"win32\" ? \"windows\" : \"linux\";\n"
    },
    {
      "path": "packages/keyboard/src/registry.ts",
      "target": "@ui/gpuixui/keyboard/registry.ts",
      "type": "registry:lib",
      "content": "import { Effect } from \"effect\";\nimport * as Arr from \"effect/Array\";\nimport * as Context from \"effect/Context\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\nimport type { KeyEvent } from \"@gpuix/react\";\nimport { hasNonModifierKey } from \"@tanstack/hotkeys\";\nimport { decodeGpuixEvent } from \"./decode.js\";\nimport { resolve, type Binding, type Keymap, type Scope } from \"./keymap.js\";\nimport { toTanstackPlatform, type Platform } from \"./platform.js\";\n\nexport interface Command {\n  readonly id: string;\n  readonly title: string;\n  readonly scope: Scope;\n\n  readonly hotkey: Binding;\n\n  readonly handler: Effect.Effect<void>;\n}\n\nexport interface CommandRegistryService {\n  readonly resolve: (\n    event: KeyEvent,\n    scopes: ReadonlyArray<Scope>,\n    platform: Platform,\n  ) => Option.Option<Command>;\n}\n\n/** The command registry tag. One per runtime. */\nexport class CommandRegistry extends Context.Service<\n  CommandRegistry,\n  CommandRegistryService\n>()(\"gpuixui/keyboard/CommandRegistry\") {}\n\nconst keymapOf = (commands: ReadonlyArray<Command>): Keymap => ({\n  bindings: Arr.map(commands, (command) => ({\n    hotkey: command.hotkey,\n    commandId: command.id,\n    scope: command.scope,\n  })),\n});\n\nconst resolveCommand = (\n  commands: ReadonlyArray<Command>,\n  event: KeyEvent,\n  scopes: ReadonlyArray<Scope>,\n  platform: Platform,\n): Option.Option<Command> => {\n  const chord = decodeGpuixEvent(event, platform);\n  if (!hasNonModifierKey(chord, toTanstackPlatform(platform))) {\n    return Option.none();\n  }\n  return Option.flatMap(\n    resolve(keymapOf(commands), scopes, chord, platform),\n    (commandId) =>\n      Arr.findFirst(commands, (command) => command.id === commandId),\n  );\n};\n\n/** A read-only registry over the given commands, as plain data. */\nexport const commandRegistry = (\n  commands: ReadonlyArray<Command>,\n): CommandRegistryService => ({\n  resolve: (event, scopes, platform) =>\n    resolveCommand(commands, event, scopes, platform),\n});\n\n/** A layer holding one read-only registry. */\nexport const makeCommandRegistry = (\n  commands: ReadonlyArray<Command>,\n): Layer.Layer<CommandRegistry> =>\n  Layer.succeed(CommandRegistry, CommandRegistry.of(commandRegistry(commands)));\n"
    },
    {
      "path": "packages/keyboard/src/sequence.ts",
      "target": "@ui/gpuixui/keyboard/sequence.ts",
      "type": "registry:lib",
      "content": "import {\n  areHotkeysEqual,\n  hasNonModifierKey,\n  type ParsedHotkeyChord,\n} from \"@tanstack/hotkeys\";\nimport { parseBinding } from \"./chord.js\";\nimport { toTanstackPlatform, type Platform } from \"./platform.js\";\n\nexport interface SequenceMatcherOptions {\n  readonly timeoutMs: number;\n\n  readonly platform: Platform;\n}\n\nexport interface SequenceMatcher {\n  readonly advance: (chord: ParsedHotkeyChord, now: number) => boolean;\n\n  readonly reset: () => void;\n\n  readonly progress: () => number;\n}\n\nexport const makeSequenceMatcher = (\n  sequence: ReadonlyArray<string>,\n  options: SequenceMatcherOptions,\n): SequenceMatcher => {\n  const steps: ReadonlyArray<ParsedHotkeyChord> = parseBinding(\n    sequence,\n    options.platform,\n  );\n  const { timeoutMs, platform } = options;\n  let index = 0;\n  let lastStepAt = 0;\n\n  return {\n    advance: (chord, now) => {\n      if (!hasNonModifierKey(chord, toTanstackPlatform(platform))) return false;\n      if (index > 0 && now - lastStepAt > timeoutMs) index = 0;\n      const expected = steps[index];\n      if (expected === undefined) return false;\n      if (areHotkeysEqual(expected, chord, toTanstackPlatform(platform))) {\n        lastStepAt = now;\n        index += 1;\n        if (index >= steps.length) {\n          index = 0;\n          return true;\n        }\n      } else if (index > 0) {\n        const first = steps[0];\n        if (\n          first !== undefined &&\n          areHotkeysEqual(first, chord, toTanstackPlatform(platform))\n        ) {\n          index = 1;\n          lastStepAt = now;\n        } else {\n          index = 0;\n        }\n      }\n      return false;\n    },\n    reset: () => {\n      index = 0;\n      lastStepAt = 0;\n    },\n    progress: () => index,\n  };\n};\n"
    }
  ],
  "docs": "[Runtime: keyboard](https://gpuixui.sudokw.com/registry) — 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": "/registry",
    "kind": "runtime",
    "runtime": "gpuix",
    "registry": "gpuixui"
  }
}