{"version":3,"sources":["../src/vue.ts"],"sourcesContent":["/**\n * @cross-deck/web/vue — Vue 3 composables for the Crossdeck SDK.\n *\n * Mirrors @cross-deck/web/react in spirit: ties the entitlement cache\n * to Vue's reactive system so components re-render the moment the\n * server-side cache populates.\n *\n *   import { useEntitlement } from \"@cross-deck/web/vue\";\n *   const isPro = useEntitlement(\"pro\");  // Ref<boolean>\n *\n * Why a separate subpackage: Vue is an optional peer dependency. The\n * core SDK has zero runtime deps; pulling Vue in unconditionally would\n * make non-Vue consumers pay for code they don't use. Same pattern as\n * `@cross-deck/web/react`.\n *\n * SSR safety: `onMounted` / `onScopeDispose` only run on the client.\n * The initial Ref value is the cache's current state (`false` pre-init),\n * so server output never claims a non-existent entitlement.\n */\n\nimport { ref, onMounted, onScopeDispose, type Ref } from \"vue\";\nimport { Crossdeck } from \"./singleton\";\nimport type { TrustTokenStatus } from \"./trust\";\nexport type { TrustTokenStatus };\n\n/**\n * Reactive entitlement check. Returns a `Ref<boolean>` that updates\n * automatically whenever the cache mutates.\n *\n *   const isPro = useEntitlement(\"pro\");\n *   // template: <span v-if=\"isPro\">Pro</span>\n */\nexport function useEntitlement(key: string): Ref<boolean> {\n  const r = ref<boolean>(safeIsEntitled(key));\n\n  onMounted(() => {\n    r.value = safeIsEntitled(key);\n    let unsubscribe: (() => void) | null = null;\n    try {\n      unsubscribe = Crossdeck.onEntitlementsChange(() => {\n        r.value = safeIsEntitled(key);\n      });\n    } catch {\n      // Pre-init — the SDK isn't started yet. The composable just\n      // returns false until something mutates the cache via a\n      // post-init call.\n    }\n    onScopeDispose(() => {\n      if (unsubscribe) unsubscribe();\n    });\n  });\n\n  return r;\n}\n\n/**\n * Reactive list of active entitlement keys. Updates on every cache\n * mutation. Useful for rendering a \"you have unlocked: ...\" block.\n */\nexport function useEntitlements(): Ref<readonly string[]> {\n  const r = ref<readonly string[]>(safeListKeys());\n\n  onMounted(() => {\n    r.value = safeListKeys();\n    let unsubscribe: (() => void) | null = null;\n    try {\n      unsubscribe = Crossdeck.onEntitlementsChange((entitlements) => {\n        r.value = entitlements.filter((e) => e.isActive).map((e) => e.key);\n      });\n    } catch {\n      // Pre-init.\n    }\n    onScopeDispose(() => {\n      if (unsubscribe) unsubscribe();\n    });\n  });\n\n  return r;\n}\n\n/**\n * Crossdeck Trust — the human-proof panel as a Vue composable.\n *\n * Bind `el` to the element the panel mounts into; read `token` / `status`\n * reactively. Sits on `Crossdeck.trust.panel(...)`, takes the publishable key\n * from `init()`, and is fail-open (can't mint → status \"unavailable\", signup\n * still proceeds, server scores the absent token). Never throws.\n *\n * @example\n * <script setup>\n * import { useTrustToken } from \"@cross-deck/web/vue\";\n * const { el, token, status } = useTrustToken();\n * </script>\n * <template><div ref=\"el\" /></template>\n */\nexport function useTrustToken(opts?: {\n  /** Explicit publishable key (cd_pub_…) — no `init()` needed. Falls back to init's key. */\n  publicKey?: string;\n}): {\n  /** Template ref — bind to the mount element: `<div ref=\"el\" />`. */\n  el: Ref<HTMLElement | null>;\n  /** The minted token, or null until it mints (or if the panel failed open). */\n  token: Ref<string | null>;\n  /** Lifecycle: pending → ready (minted) or unavailable (failed open). */\n  status: Ref<TrustTokenStatus>;\n} {\n  const el = ref<HTMLElement | null>(null);\n  const token = ref<string | null>(null);\n  const status = ref<TrustTokenStatus>(\"pending\");\n\n  onMounted(() => {\n    if (!el.value) return;\n    const handle = Crossdeck.trust.panel({\n      target: el.value,\n      publicKey: opts?.publicKey,\n      onToken: (t) => {\n        token.value = t.token;\n        status.value = \"ready\";\n      },\n      onUnavailable: () => {\n        status.value = \"unavailable\";\n      },\n    });\n    onScopeDispose(() => handle.destroy());\n  });\n\n  return { el, token, status };\n}\n\nfunction safeIsEntitled(key: string): boolean {\n  try {\n    return Crossdeck.isEntitled(key);\n  } catch {\n    return false;\n  }\n}\n\nfunction safeListKeys(): readonly string[] {\n  try {\n    return Crossdeck.listEntitlements()\n      .filter((e) => e.isActive)\n      .map((e) => e.key);\n  } catch {\n    return [];\n  }\n}\n"],"mappings":";;;;;AAoBA,SAAS,KAAK,WAAW,sBAAgC;AAYlD,SAAS,eAAe,KAA2B;AACxD,QAAM,IAAI,IAAa,eAAe,GAAG,CAAC;AAE1C,YAAU,MAAM;AACd,MAAE,QAAQ,eAAe,GAAG;AAC5B,QAAI,cAAmC;AACvC,QAAI;AACF,oBAAc,UAAU,qBAAqB,MAAM;AACjD,UAAE,QAAQ,eAAe,GAAG;AAAA,MAC9B,CAAC;AAAA,IACH,QAAQ;AAAA,IAIR;AACA,mBAAe,MAAM;AACnB,UAAI,YAAa,aAAY;AAAA,IAC/B,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AACT;AAMO,SAAS,kBAA0C;AACxD,QAAM,IAAI,IAAuB,aAAa,CAAC;AAE/C,YAAU,MAAM;AACd,MAAE,QAAQ,aAAa;AACvB,QAAI,cAAmC;AACvC,QAAI;AACF,oBAAc,UAAU,qBAAqB,CAAC,iBAAiB;AAC7D,UAAE,QAAQ,aAAa,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG;AAAA,MACnE,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AACA,mBAAe,MAAM;AACnB,UAAI,YAAa,aAAY;AAAA,IAC/B,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AACT;AAiBO,SAAS,cAAc,MAU5B;AACA,QAAM,KAAK,IAAwB,IAAI;AACvC,QAAM,QAAQ,IAAmB,IAAI;AACrC,QAAM,SAAS,IAAsB,SAAS;AAE9C,YAAU,MAAM;AACd,QAAI,CAAC,GAAG,MAAO;AACf,UAAM,SAAS,UAAU,MAAM,MAAM;AAAA,MACnC,QAAQ,GAAG;AAAA,MACX,WAAW,MAAM;AAAA,MACjB,SAAS,CAAC,MAAM;AACd,cAAM,QAAQ,EAAE;AAChB,eAAO,QAAQ;AAAA,MACjB;AAAA,MACA,eAAe,MAAM;AACnB,eAAO,QAAQ;AAAA,MACjB;AAAA,IACF,CAAC;AACD,mBAAe,MAAM,OAAO,QAAQ,CAAC;AAAA,EACvC,CAAC;AAED,SAAO,EAAE,IAAI,OAAO,OAAO;AAC7B;AAEA,SAAS,eAAe,KAAsB;AAC5C,MAAI;AACF,WAAO,UAAU,WAAW,GAAG;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,eAAkC;AACzC,MAAI;AACF,WAAO,UAAU,iBAAiB,EAC/B,OAAO,CAAC,MAAM,EAAE,QAAQ,EACxB,IAAI,CAAC,MAAM,EAAE,GAAG;AAAA,EACrB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;","names":[]}