{"version":3,"sources":["../../../../src/sensors/usePointer/core.ts"],"sourcesContent":["import { batch, type Observable } from \"@legendapp/state\";\nimport { peek, observable, type DeepMaybeObservable, type ReadonlyObservable } from \"@usels/core\";\nimport { resolveWindowSource, type ConfigurableWindow } from \"@shared/configurable\";\nimport type { MaybeEventTarget } from \"../../types\";\nimport { createEventListener } from \"../../browser/useEventListener/core\";\n\nexport type UsePointerType = \"mouse\" | \"touch\" | \"pen\";\n\nexport interface UsePointerOptions extends ConfigurableWindow {\n  /** Target element to listen on. Default: window */\n  target?: MaybeEventTarget;\n  /** Pointer types to listen for. Default: all types */\n  pointerTypes?: UsePointerType[];\n}\n\nexport interface UsePointerReturn {\n  /** X coordinate */\n  x$: ReadonlyObservable<number>;\n  /** Y coordinate */\n  y$: ReadonlyObservable<number>;\n  /** Pointer pressure (0-1) */\n  pressure$: ReadonlyObservable<number>;\n  /** Unique pointer identifier */\n  pointerId$: ReadonlyObservable<number>;\n  /** Tilt angle on X axis (-90 to 90) */\n  tiltX$: ReadonlyObservable<number>;\n  /** Tilt angle on Y axis (-90 to 90) */\n  tiltY$: ReadonlyObservable<number>;\n  /** Contact geometry width */\n  width$: ReadonlyObservable<number>;\n  /** Contact geometry height */\n  height$: ReadonlyObservable<number>;\n  /** Clockwise rotation (0-359) */\n  twist$: ReadonlyObservable<number>;\n  /** Pointer device type */\n  pointerType$: ReadonlyObservable<UsePointerType | null>;\n  /** Whether pointer is inside the target */\n  isInside$: ReadonlyObservable<boolean>;\n}\n\n/**\n * Framework-agnostic reactive pointer tracker.\n *\n * Listens to `pointerdown` / `pointermove` / `pointerup` / `pointerleave`\n * on a target (default: window resolved via `resolveWindowSource`) and\n * exposes position, pressure, tilt, dimensions, twist, pointer type, and\n * inside state as observables.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function createPointer(options?: DeepMaybeObservable<UsePointerOptions>): UsePointerReturn {\n  // Wrap options into a single observable so both `target` and `window` are\n  // tracked reactively. The hook wrapper passes `target`/`window` via toObs\n  // with the `\"opaque\"` hint, which prevents Legend-State from deep-proxying\n  // DOM nodes / Window references stored inside.\n  const opts$ = observable(options);\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- window field type varies by hint map\n  const win$ = resolveWindowSource(opts$.window as any);\n\n  // Decide at mount time whether the caller supplied a `target` option. If so,\n  // pass the `opts$.target` observable (not a peeked value) so that Ref$/\n  // Observable target changes propagate reactively through `normalizeTargets`\n  // inside `createEventListener`. Otherwise, fall back to the reactive `win$`.\n  const hasTarget =\n    options != null &&\n    typeof options === \"object\" &&\n    \"target\" in (options as Record<string, unknown>);\n  const eventTarget: Observable<unknown> = hasTarget\n    ? (opts$.target as unknown as Observable<unknown>)\n    : (win$ as unknown as Observable<unknown>);\n\n  // pointerTypes is mount-time-only — a filter array snapshot is enough.\n  const pointerTypes = peek(opts$.pointerTypes);\n\n  const x$ = observable(0);\n  const y$ = observable(0);\n  const pressure$ = observable(0);\n  const pointerId$ = observable(0);\n  const tiltX$ = observable(0);\n  const tiltY$ = observable(0);\n  const width$ = observable(1);\n  const height$ = observable(1);\n  const twist$ = observable(0);\n  const pointerType$ = observable<UsePointerType | null>(null);\n  const isInside$ = observable(false);\n\n  const handler = (e: PointerEvent) => {\n    // isInside$ is set before pointerTypes filtering — any pointer entering\n    // the target is considered \"inside\" regardless of its type.\n    isInside$.set(true);\n    if (pointerTypes && !pointerTypes.includes(e.pointerType as UsePointerType)) return;\n    batch(() => {\n      x$.set(e.clientX);\n      y$.set(e.clientY);\n      pressure$.set(e.pressure);\n      pointerId$.set(e.pointerId);\n      tiltX$.set(e.tiltX);\n      tiltY$.set(e.tiltY);\n      width$.set(e.width);\n      height$.set(e.height);\n      twist$.set(e.twist);\n      pointerType$.set(e.pointerType as UsePointerType);\n    });\n  };\n\n  const onPointerLeave = () => {\n    isInside$.set(false);\n  };\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- union of MaybeEventTarget and reactive win$\n  const target = eventTarget as any;\n  createEventListener(target, \"pointerdown\", handler, { passive: true });\n  createEventListener(target, \"pointermove\", handler, { passive: true });\n  createEventListener(target, \"pointerup\", handler, { passive: true });\n  createEventListener(target, \"pointerleave\", onPointerLeave, { passive: true });\n\n  return {\n    x$,\n    y$,\n    pressure$,\n    pointerId$,\n    tiltX$,\n    tiltY$,\n    width$,\n    height$,\n    twist$,\n    pointerType$,\n    isInside$,\n  };\n}\n"],"mappings":"AAAA,SAAS,aAA8B;AACvC,SAAS,MAAM,kBAAqE;AACpF,SAAS,2BAAoD;AAE7D,SAAS,2BAA2B;AAAA;AA6C7B,SAAS,cAAc,SAAoE;AAKhG,QAAM,QAAQ,WAAW,OAAO;AAGhC,QAAM,OAAO,oBAAoB,MAAM,MAAa;AAMpD,QAAM,YACJ,WAAW,QACX,OAAO,YAAY,YACnB,YAAa;AACf,QAAM,cAAmC,YACpC,MAAM,SACN;AAGL,QAAM,eAAe,KAAK,MAAM,YAAY;AAE5C,QAAM,KAAK,WAAW,CAAC;AACvB,QAAM,KAAK,WAAW,CAAC;AACvB,QAAM,YAAY,WAAW,CAAC;AAC9B,QAAM,aAAa,WAAW,CAAC;AAC/B,QAAM,SAAS,WAAW,CAAC;AAC3B,QAAM,SAAS,WAAW,CAAC;AAC3B,QAAM,SAAS,WAAW,CAAC;AAC3B,QAAM,UAAU,WAAW,CAAC;AAC5B,QAAM,SAAS,WAAW,CAAC;AAC3B,QAAM,eAAe,WAAkC,IAAI;AAC3D,QAAM,YAAY,WAAW,KAAK;AAElC,QAAM,UAAU,CAAC,MAAoB;AAGnC,cAAU,IAAI,IAAI;AAClB,QAAI,gBAAgB,CAAC,aAAa,SAAS,EAAE,WAA6B,EAAG;AAC7E,UAAM,MAAM;AACV,SAAG,IAAI,EAAE,OAAO;AAChB,SAAG,IAAI,EAAE,OAAO;AAChB,gBAAU,IAAI,EAAE,QAAQ;AACxB,iBAAW,IAAI,EAAE,SAAS;AAC1B,aAAO,IAAI,EAAE,KAAK;AAClB,aAAO,IAAI,EAAE,KAAK;AAClB,aAAO,IAAI,EAAE,KAAK;AAClB,cAAQ,IAAI,EAAE,MAAM;AACpB,aAAO,IAAI,EAAE,KAAK;AAClB,mBAAa,IAAI,EAAE,WAA6B;AAAA,IAClD,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB,MAAM;AAC3B,cAAU,IAAI,KAAK;AAAA,EACrB;AAGA,QAAM,SAAS;AACf,sBAAoB,QAAQ,eAAe,SAAS,EAAE,SAAS,KAAK,CAAC;AACrE,sBAAoB,QAAQ,eAAe,SAAS,EAAE,SAAS,KAAK,CAAC;AACrE,sBAAoB,QAAQ,aAAa,SAAS,EAAE,SAAS,KAAK,CAAC;AACnE,sBAAoB,QAAQ,gBAAgB,gBAAgB,EAAE,SAAS,KAAK,CAAC;AAE7E,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}