{"version":3,"sources":["../../../../src/sensors/useOnKeyStroke/core.ts"],"sourcesContent":["import { observable } from \"@legendapp/state\";\nimport { type Fn, type DeepMaybeObservable, onUnmount } from \"@usels/core\";\nimport { type ConfigurableWindow, defaultWindow } from \"@shared/configurable\";\nimport { createEventListener } from \"../../browser/useEventListener/core\";\n\nexport type KeyPredicate = (event: KeyboardEvent) => boolean;\nexport type KeyFilter = true | string | string[] | KeyPredicate;\nexport type KeyStrokeEventName = \"keydown\" | \"keypress\" | \"keyup\";\n\nexport interface UseOnKeyStrokeOptions extends ConfigurableWindow {\n  /**\n   * Event name to listen for.\n   * @default \"keydown\"\n   */\n  eventName?: KeyStrokeEventName;\n  /**\n   * Event target.\n   * @default window\n   */\n  target?: EventTarget | null;\n  /**\n   * Use passive event listener.\n   * @default false\n   */\n  passive?: boolean;\n  /**\n   * Ignore repeated events when a key is held down.\n   * @default false\n   */\n  dedupe?: boolean;\n}\n\nexport type UseOnKeyStrokeReturn = Fn;\n\nfunction createKeyPredicate(keyFilter: KeyFilter): KeyPredicate {\n  if (typeof keyFilter === \"function\") return keyFilter;\n  if (typeof keyFilter === \"string\") return (event: KeyboardEvent) => event.key === keyFilter;\n  if (Array.isArray(keyFilter)) return (event: KeyboardEvent) => keyFilter.includes(event.key);\n  // true — match everything\n  return () => true;\n}\n\n// ---------------------------------------------------------------------------\n// Overloads\n// ---------------------------------------------------------------------------\n\n/**\n * Framework-agnostic keyboard key stroke listener with key filtering.\n *\n * @param key - Key filter (string, string[], predicate, or `true` for all)\n * @param handler - Callback fired when a matching key event occurs\n * @param options - Configuration options\n * @returns A stop function that removes the event listener\n */\nexport function createOnKeyStroke(\n  key: KeyFilter,\n  handler: (event: KeyboardEvent) => void,\n  options?: DeepMaybeObservable<UseOnKeyStrokeOptions>\n): UseOnKeyStrokeReturn;\n\n/**\n * Framework-agnostic keyboard key stroke listener for all keys.\n *\n * @param handler - Callback fired on every key event\n * @param options - Configuration options\n * @returns A stop function that removes the event listener\n */\nexport function createOnKeyStroke(\n  handler: (event: KeyboardEvent) => void,\n  options?: DeepMaybeObservable<UseOnKeyStrokeOptions>\n): UseOnKeyStrokeReturn;\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\nexport function createOnKeyStroke(\n  keyOrHandler: KeyFilter | ((event: KeyboardEvent) => void),\n  handlerOrOptions?: ((event: KeyboardEvent) => void) | DeepMaybeObservable<UseOnKeyStrokeOptions>,\n  optionsArg?: DeepMaybeObservable<UseOnKeyStrokeOptions>\n): UseOnKeyStrokeReturn {\n  let key: KeyFilter;\n  let handler: (event: KeyboardEvent) => void;\n  let rawOptions: DeepMaybeObservable<UseOnKeyStrokeOptions> | undefined;\n\n  if (\n    typeof keyOrHandler === \"function\" &&\n    (handlerOrOptions == null || typeof handlerOrOptions === \"object\")\n  ) {\n    // Overload: (handler, options?)\n    key = true;\n    handler = keyOrHandler as (event: KeyboardEvent) => void;\n    rawOptions = handlerOrOptions as DeepMaybeObservable<UseOnKeyStrokeOptions> | undefined;\n  } else {\n    // Overload: (key, handler, options?)\n    key = keyOrHandler as KeyFilter;\n    handler = handlerOrOptions as (event: KeyboardEvent) => void;\n    rawOptions = optionsArg;\n  }\n\n  const opts$ = observable(rawOptions);\n\n  // Construction-time reads (mount-time-only: target, eventName, passive)\n  const target = opts$.peek()?.target ?? defaultWindow;\n  const eventName = opts$.peek()?.eventName ?? \"keydown\";\n  const passive = opts$.peek()?.passive ?? false;\n\n  // Stable predicate — created once from the initial key filter.\n  const predicate = createKeyPredicate(key);\n\n  const listener = (e: KeyboardEvent) => {\n    if (e.repeat && opts$.peek()?.dedupe) return;\n    if (predicate(e)) handler(e);\n  };\n\n  const stop = createEventListener(\n    target as EventTarget | null | undefined,\n    eventName,\n    listener as (ev: Event) => void,\n    { passive }\n  );\n\n  onUnmount(stop);\n\n  return stop;\n}\n\n// ---------------------------------------------------------------------------\n// Convenience functions\n// ---------------------------------------------------------------------------\n\n/**\n * Listen for `keydown` events with key filtering.\n */\nexport function createOnKeyDown(\n  key: KeyFilter,\n  handler: (event: KeyboardEvent) => void,\n  options: Omit<UseOnKeyStrokeOptions, \"eventName\"> = {}\n): UseOnKeyStrokeReturn {\n  return createOnKeyStroke(key, handler, { ...options, eventName: \"keydown\" });\n}\n\n/**\n * Listen for `keypress` events with key filtering.\n */\nexport function createOnKeyPressed(\n  key: KeyFilter,\n  handler: (event: KeyboardEvent) => void,\n  options: Omit<UseOnKeyStrokeOptions, \"eventName\"> = {}\n): UseOnKeyStrokeReturn {\n  return createOnKeyStroke(key, handler, { ...options, eventName: \"keypress\" });\n}\n\n/**\n * Listen for `keyup` events with key filtering.\n */\nexport function createOnKeyUp(\n  key: KeyFilter,\n  handler: (event: KeyboardEvent) => void,\n  options: Omit<UseOnKeyStrokeOptions, \"eventName\"> = {}\n): UseOnKeyStrokeReturn {\n  return createOnKeyStroke(key, handler, { ...options, eventName: \"keyup\" });\n}\n"],"mappings":"AAAA,SAAS,kBAAkB;AAC3B,SAA4C,iBAAiB;AAC7D,SAAkC,qBAAqB;AACvD,SAAS,2BAA2B;AA+BpC,SAAS,mBAAmB,WAAoC;AAC9D,MAAI,OAAO,cAAc,WAAY,QAAO;AAC5C,MAAI,OAAO,cAAc,SAAU,QAAO,CAAC,UAAyB,MAAM,QAAQ;AAClF,MAAI,MAAM,QAAQ,SAAS,EAAG,QAAO,CAAC,UAAyB,UAAU,SAAS,MAAM,GAAG;AAE3F,SAAO,MAAM;AACf;AAoCO,SAAS,kBACd,cACA,kBACA,YACsB;AACtB,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MACE,OAAO,iBAAiB,eACvB,oBAAoB,QAAQ,OAAO,qBAAqB,WACzD;AAEA,UAAM;AACN,cAAU;AACV,iBAAa;AAAA,EACf,OAAO;AAEL,UAAM;AACN,cAAU;AACV,iBAAa;AAAA,EACf;AAEA,QAAM,QAAQ,WAAW,UAAU;AAGnC,QAAM,SAAS,MAAM,KAAK,GAAG,UAAU;AACvC,QAAM,YAAY,MAAM,KAAK,GAAG,aAAa;AAC7C,QAAM,UAAU,MAAM,KAAK,GAAG,WAAW;AAGzC,QAAM,YAAY,mBAAmB,GAAG;AAExC,QAAM,WAAW,CAAC,MAAqB;AACrC,QAAI,EAAE,UAAU,MAAM,KAAK,GAAG,OAAQ;AACtC,QAAI,UAAU,CAAC,EAAG,SAAQ,CAAC;AAAA,EAC7B;AAEA,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE,QAAQ;AAAA,EACZ;AAEA,YAAU,IAAI;AAEd,SAAO;AACT;AASO,SAAS,gBACd,KACA,SACA,UAAoD,CAAC,GAC/B;AACtB,SAAO,kBAAkB,KAAK,SAAS,EAAE,GAAG,SAAS,WAAW,UAAU,CAAC;AAC7E;AAKO,SAAS,mBACd,KACA,SACA,UAAoD,CAAC,GAC/B;AACtB,SAAO,kBAAkB,KAAK,SAAS,EAAE,GAAG,SAAS,WAAW,WAAW,CAAC;AAC9E;AAKO,SAAS,cACd,KACA,SACA,UAAoD,CAAC,GAC/B;AACtB,SAAO,kBAAkB,KAAK,SAAS,EAAE,GAAG,SAAS,WAAW,QAAQ,CAAC;AAC3E;","names":[]}