{"version":3,"sources":["../../../src/shared/configurable.ts"],"sourcesContent":["import { isBrowser } from \"@usels/core/shared/utils\";\nimport type { Ref$ } from \"@usels/core\";\nimport { observable, ObservableHint, type Observable, type OpaqueObject } from \"@legendapp/state\";\n\n/** Window를 resolve할 수 있는 소스 타입 */\nexport type WindowSource = Window | Ref$<HTMLIFrameElement>;\n\nexport interface ConfigurableWindow {\n  /*\n   * Specify a custom `window` instance, e.g. working with iframes or in testing environments.\n   *\n   * Accepts a plain `Window`, a `Ref$<HTMLIFrameElement>` (reactive), or\n   * an `Observable<OpaqueObject<HTMLIFrameElement> | null>`.\n   */\n  window?: WindowSource;\n}\n\nexport interface ConfigurableDocumentOrShadowRoot {\n  document?: DocumentOrShadowRoot;\n}\n\nexport const defaultWindow = /* #__PURE__ */ isBrowser ? window : undefined;\n\nexport const defaultDocument = /* #__PURE__ */ isBrowser ? window.document : undefined;\n\nexport const defaultNavigator = /* #__PURE__ */ isBrowser ? window.navigator : undefined;\n\nexport const defaultLocation = /* #__PURE__ */ isBrowser ? window.location : undefined;\n\n/**\n * Internal raw resolver: takes the plain value held by an `opts$.window`\n * field and returns the real `Window` reference.\n *\n * Handles:\n * - `null` / `undefined` → `defaultWindow` (SSR-safe: `undefined`)\n * - plain `Window` → identity\n * - `OpaqueObject<Window>` → identity (opaque is only a Legend-State marker; `valueOf()` returns the window)\n * - `OpaqueObject<HTMLIFrameElement>` → `iframe.contentWindow` (or `undefined` if detached)\n *\n * Intentionally duck-typed on `.valueOf()` so plain and opaque-wrapped values\n * both work without importing `@legendapp/state` behavior.\n */\nfunction resolveWindowRaw(raw: unknown): Window | undefined {\n  if (raw == null) return defaultWindow;\n  const val =\n    typeof (raw as { valueOf?: () => unknown }).valueOf === \"function\"\n      ? (raw as { valueOf: () => unknown }).valueOf()\n      : raw;\n  if (typeof HTMLIFrameElement !== \"undefined\" && val instanceof HTMLIFrameElement) {\n    return val.contentWindow ?? undefined;\n  }\n  return val as Window;\n}\n\n/**\n * Reactive `WindowSource` resolver. Given the `window` field of an options\n * observable (e.g. `opts$.window`), returns a computed\n * `Observable<OpaqueObject<Window> | null>` that recomputes whenever the\n * source observable changes (iframe ref mounting/unmounting, observable\n * options replacement, etc.).\n *\n * Usage inside a scope-based core:\n * ```ts\n * const win$ = resolveWindowSource(opts$.window);\n * const isSupported$ = createSupported(() => {\n *   const win = win$.get(); // reactive\n *   return !!win && \"matchMedia\" in win;\n * });\n * onMount(() => {\n *   const win = win$.peek(); // non-reactive snapshot at mount\n *   if (!win) return;\n *   // ...\n * });\n * ```\n *\n * The returned observable holds `null` when no window can be resolved (SSR,\n * detached iframe) and an opaque-wrapped `Window` otherwise. The opaque\n * wrapping prevents Legend-State from deep-proxying the `Window` object —\n * property access (`win.matchMedia`, `win.speechSynthesis`, etc.) still works\n * directly because `OpaqueObject<T>` is `T & { [symbolOpaque]: true }`.\n */\nexport function resolveWindowSource(\n  source$: Observable<unknown>\n): Observable<OpaqueObject<Window> | null> {\n  return observable<OpaqueObject<Window> | null>(() => {\n    const win = resolveWindowRaw(source$.get());\n    return win ? ObservableHint.opaque(win) : null;\n  });\n}\n"],"mappings":"AAAA,SAAS,iBAAiB;AAE1B,SAAS,YAAY,sBAA0D;AAmBxE,MAAM,gBAAgC,YAAY,SAAS;AAE3D,MAAM,kBAAkC,YAAY,OAAO,WAAW;AAEtE,MAAM,mBAAmC,YAAY,OAAO,YAAY;AAExE,MAAM,kBAAkC,YAAY,OAAO,WAAW;AAe7E,SAAS,iBAAiB,KAAkC;AAC1D,MAAI,OAAO,KAAM,QAAO;AACxB,QAAM,MACJ,OAAQ,IAAoC,YAAY,aACnD,IAAmC,QAAQ,IAC5C;AACN,MAAI,OAAO,sBAAsB,eAAe,eAAe,mBAAmB;AAChF,WAAO,IAAI,iBAAiB;AAAA,EAC9B;AACA,SAAO;AACT;AA6BO,SAAS,oBACd,SACyC;AACzC,SAAO,WAAwC,MAAM;AACnD,UAAM,MAAM,iBAAiB,QAAQ,IAAI,CAAC;AAC1C,WAAO,MAAM,eAAe,OAAO,GAAG,IAAI;AAAA,EAC5C,CAAC;AACH;","names":[]}