{"version":3,"sources":["../../../../src/elements/useElementVisibility/core.ts"],"sourcesContent":["import { observable, ObservableHint, type Observable } from \"@legendapp/state\";\nimport { get, createObserve, type DeepMaybeObservable } from \"@usels/core\";\nimport {\n  createIntersectionObserver,\n  type UseIntersectionObserverOptions,\n} from \"@elements/useIntersectionObserver/core\";\nimport { normalizeTargets } from \"@shared/normalizeTargets\";\nimport type { MaybeEventTarget } from \"../../types\";\n\nexport interface UseElementVisibilityOptions {\n  /** Initial visibility value. Default: false */\n  initialValue?: boolean;\n  /** Element used as the viewport for intersection. Maps to IntersectionObserver `root`. */\n  scrollTarget?: MaybeEventTarget;\n  /** Margin around the root. Accepts CSS-style values. Default: \"0px\" */\n  rootMargin?: string;\n  /** Threshold(s) at which to trigger. Default: 0 */\n  threshold?: number | number[];\n  /**\n   * Stop observing after the element becomes visible for the first time. Default: false.\n   * Must be set at mount time; changing dynamically has no effect.\n   */\n  once?: boolean;\n}\n\n/**\n * Framework-agnostic reactive element visibility tracker.\n *\n * Tracks whether a DOM element is intersecting the viewport (or a specified\n * scroll container). Returns a reactive `Observable<boolean>` that updates\n * automatically via the IntersectionObserver API.\n *\n * @param element - Element to observe (Ref$, Observable element, or raw element).\n * @param options - Optional configuration — plain, per-field Observable, or fully Observable.\n * @returns `Observable<boolean>` — true when element is intersecting.\n */\nexport function createElementVisibility(\n  element: MaybeEventTarget,\n  options?: DeepMaybeObservable<UseElementVisibilityOptions>\n): Observable<boolean> {\n  const opts$ = observable(options);\n  const isVisible$ = observable<boolean>(\n    (opts$.peek()?.initialValue as boolean | undefined) ?? false\n  );\n\n  // Map scrollTarget → root for createIntersectionObserver. Use a computed\n  // observable so per-field changes propagate through a single reactive path.\n  // Wrap the resolved root element with `ObservableHint.opaque` so Legend-State\n  // does not deep-proxy the HTMLElement when caching the computed value.\n  const ioOpts$ = observable<UseIntersectionObserverOptions>(() => {\n    const raw = get(opts$);\n    const rootVal = get(raw?.scrollTarget) as UseIntersectionObserverOptions[\"root\"];\n    return {\n      root: rootVal != null ? ObservableHint.opaque(rootVal as object) : rootVal,\n      rootMargin: get(raw?.rootMargin) as string | undefined,\n      threshold: get(raw?.threshold) as number | number[] | undefined,\n    };\n  });\n\n  const { stop } = createIntersectionObserver(\n    element,\n    (entries) => {\n      if (entries.length === 0) return;\n      const latest = entries.reduce((a, b) => (a.time > b.time ? a : b));\n      isVisible$.set(latest.isIntersecting);\n\n      if ((opts$.peek()?.once as boolean | undefined) && latest.isIntersecting) {\n        stop();\n      }\n    },\n    ioOpts$ as Observable<UseIntersectionObserverOptions>\n  );\n\n  // Reset visibility when target element is removed\n  createObserve(() => {\n    const targets = normalizeTargets(element);\n    if (!targets.length) {\n      isVisible$.set((opts$.peek()?.initialValue as boolean | undefined) ?? false);\n    }\n  });\n\n  return isVisible$;\n}\n"],"mappings":"AAAA,SAAS,YAAY,sBAAuC;AAC5D,SAAS,KAAK,qBAA+C;AAC7D;AAAA,EACE;AAAA,OAEK;AACP,SAAS,wBAAwB;AA8B1B,SAAS,wBACd,SACA,SACqB;AACrB,QAAM,QAAQ,WAAW,OAAO;AAChC,QAAM,aAAa;AAAA,IAChB,MAAM,KAAK,GAAG,gBAAwC;AAAA,EACzD;AAMA,QAAM,UAAU,WAA2C,MAAM;AAC/D,UAAM,MAAM,IAAI,KAAK;AACrB,UAAM,UAAU,IAAI,KAAK,YAAY;AACrC,WAAO;AAAA,MACL,MAAM,WAAW,OAAO,eAAe,OAAO,OAAiB,IAAI;AAAA,MACnE,YAAY,IAAI,KAAK,UAAU;AAAA,MAC/B,WAAW,IAAI,KAAK,SAAS;AAAA,IAC/B;AAAA,EACF,CAAC;AAED,QAAM,EAAE,KAAK,IAAI;AAAA,IACf;AAAA,IACA,CAAC,YAAY;AACX,UAAI,QAAQ,WAAW,EAAG;AAC1B,YAAM,SAAS,QAAQ,OAAO,CAAC,GAAG,MAAO,EAAE,OAAO,EAAE,OAAO,IAAI,CAAE;AACjE,iBAAW,IAAI,OAAO,cAAc;AAEpC,UAAK,MAAM,KAAK,GAAG,QAAgC,OAAO,gBAAgB;AACxE,aAAK;AAAA,MACP;AAAA,IACF;AAAA,IACA;AAAA,EACF;AAGA,gBAAc,MAAM;AAClB,UAAM,UAAU,iBAAiB,OAAO;AACxC,QAAI,CAAC,QAAQ,QAAQ;AACnB,iBAAW,IAAK,MAAM,KAAK,GAAG,gBAAwC,KAAK;AAAA,IAC7E;AAAA,EACF,CAAC;AAED,SAAO;AACT;","names":[]}