{"version":3,"sources":["../../../../src/sensors/usePointerLock/core.ts"],"sourcesContent":["import { observable, ObservableHint, type OpaqueObject } from \"@legendapp/state\";\nimport { type ReadonlyObservable, type Supportable, createSupported, onUnmount } from \"@usels/core\";\nimport { defaultDocument } from \"@shared/configurable\";\nimport { createEventListener } from \"../../browser/useEventListener/core\";\n\nexport interface UsePointerLockReturn extends Supportable {\n  /** Currently locked element */\n  element$: ReadonlyObservable<OpaqueObject<Element> | null>;\n  /** Request pointer lock on a target element or event's currentTarget */\n  lock: (target: Element | Event) => void;\n  /** Release pointer lock */\n  unlock: () => void;\n}\n\n/**\n * Framework-agnostic reactive pointer-lock controller.\n *\n * Listens to `pointerlockchange` / `pointerlockerror` on `document` and\n * exposes the currently locked element as an Observable. `lock()` / `unlock()`\n * request and release the pointer lock via the Pointer Lock API.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function createPointerLock(): UsePointerLockReturn {\n  const isSupported$ = createSupported(\n    () => !!defaultDocument && \"pointerLockElement\" in defaultDocument\n  );\n\n  const element$ = observable<OpaqueObject<Element> | null>(null);\n\n  const onChange = () => {\n    if (!defaultDocument) return;\n    const locked = defaultDocument.pointerLockElement as Element | null;\n    element$.set(locked ? ObservableHint.opaque(locked) : null);\n  };\n\n  const onError = () => {\n    element$.set(null);\n  };\n\n  createEventListener(defaultDocument ?? null, \"pointerlockchange\", onChange, { passive: true });\n  createEventListener(defaultDocument ?? null, \"pointerlockerror\", onError, { passive: true });\n\n  const lock = (target: Element | Event) => {\n    if (!isSupported$.peek()) return;\n    const el = target instanceof Event ? (target.currentTarget as Element | null) : target;\n    if (!el) return;\n    const result = el.requestPointerLock();\n    if (result instanceof Promise) {\n      result.catch(() => {});\n    }\n  };\n\n  const unlock = () => {\n    if (!defaultDocument || !element$.peek()) return;\n    defaultDocument.exitPointerLock();\n  };\n\n  onUnmount(() => {\n    if (defaultDocument && element$.peek()) {\n      defaultDocument.exitPointerLock();\n    }\n  });\n\n  return {\n    isSupported$,\n    element$: element$ as ReadonlyObservable<OpaqueObject<Element> | null>,\n    lock,\n    unlock,\n  };\n}\n"],"mappings":"AAAA,SAAS,YAAY,sBAAyC;AAC9D,SAAoD,iBAAiB,iBAAiB;AACtF,SAAS,uBAAuB;AAChC,SAAS,2BAA2B;AAAA;AAmB7B,SAAS,oBAA0C;AACxD,QAAM,eAAe;AAAA,IACnB,MAAM,CAAC,CAAC,mBAAmB,wBAAwB;AAAA,EACrD;AAEA,QAAM,WAAW,WAAyC,IAAI;AAE9D,QAAM,WAAW,MAAM;AACrB,QAAI,CAAC,gBAAiB;AACtB,UAAM,SAAS,gBAAgB;AAC/B,aAAS,IAAI,SAAS,eAAe,OAAO,MAAM,IAAI,IAAI;AAAA,EAC5D;AAEA,QAAM,UAAU,MAAM;AACpB,aAAS,IAAI,IAAI;AAAA,EACnB;AAEA,sBAAoB,mBAAmB,MAAM,qBAAqB,UAAU,EAAE,SAAS,KAAK,CAAC;AAC7F,sBAAoB,mBAAmB,MAAM,oBAAoB,SAAS,EAAE,SAAS,KAAK,CAAC;AAE3F,QAAM,OAAO,CAAC,WAA4B;AACxC,QAAI,CAAC,aAAa,KAAK,EAAG;AAC1B,UAAM,KAAK,kBAAkB,QAAS,OAAO,gBAAmC;AAChF,QAAI,CAAC,GAAI;AACT,UAAM,SAAS,GAAG,mBAAmB;AACrC,QAAI,kBAAkB,SAAS;AAC7B,aAAO,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,SAAS,MAAM;AACnB,QAAI,CAAC,mBAAmB,CAAC,SAAS,KAAK,EAAG;AAC1C,oBAAgB,gBAAgB;AAAA,EAClC;AAEA,YAAU,MAAM;AACd,QAAI,mBAAmB,SAAS,KAAK,GAAG;AACtC,sBAAgB,gBAAgB;AAAA,IAClC;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}