@cross-deck/web 1.11.2 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Crossdeck Trust — the human-proof panel, native to the SDK.
3
+ *
4
+ * This is the browser half of Crossdeck Trust wired THROUGH the SDK the customer
5
+ * already runs, not bolted on beside it. It renders the SAME cross-origin iframe
6
+ * served from trust.cross-deck.com — the un-restylable, browser-enforced brand
7
+ * panel — and hands the minted attestation back PROGRAMMATICALLY (a Promise + an
8
+ * `onToken` callback) instead of the hidden-field/DOM handshake the raw
9
+ * `embed.js` loader uses. The iframe is the bouncer; the SDK is the premium front
10
+ * door to it. You pass the token to your server, which verifies it at the gate
11
+ * (`crossdeck.trust.gate(...)` in @cross-deck/node, or a raw POST /v1/trust/gate).
12
+ *
13
+ * Non-negotiables baked in (Stripe / Cloudflare / bank grade):
14
+ * - ISOLATED — every DOM / postMessage touch is wrapped; a stumble here can never
15
+ * throw into the host app, the rest of the SDK, or the customer's signup form.
16
+ * - FAIL-OPEN, never fail-allow — if the panel can't mint (adblocker, our outage,
17
+ * offline, timeout), `ready` resolves with NO token. The signup proceeds; the
18
+ * SERVER gate scores the ABSENCE. We never wave a tokenless request through, and
19
+ * we never block the form because our panel had a bad day. Failing CLOSED would
20
+ * hand an attacker a site-wide-outage weapon — so we never do.
21
+ * - ORIGIN-LOCKED — we only trust messages from OUR panel origin AND from this
22
+ * exact iframe's window. Nothing on the host page can forge a token.
23
+ * - The token is minted INSIDE our origin; the host page (even an XSS on it) never
24
+ * participates in the mint, it only receives the finished token.
25
+ */
26
+ /** The origin that serves the branded, un-restylable Trust panel. */
27
+ declare const TRUST_PANEL_ORIGIN = "https://trust.cross-deck.com";
28
+ /** A minted human-proof attestation. Pass `token` to your gate call. */
29
+ interface TrustToken {
30
+ /** The single-use, project-bound attestation to send to your server as `token`. */
31
+ token: string;
32
+ /** Epoch ms at which the token expires (mint fresh per signup attempt), or null. */
33
+ expiresAt: number | null;
34
+ }
35
+ /** Resolution of a panel that failed open — a token never minted. Not an error. */
36
+ interface TrustUnavailable {
37
+ token: null;
38
+ expiresAt: null;
39
+ /** Why no token was minted (for your logs) — e.g. "timeout", "blocked", "offline". */
40
+ reason: string;
41
+ }
42
+ type TrustResult = TrustToken | TrustUnavailable;
43
+ /** Lifecycle of a panel driven by a framework binding: pending → ready | unavailable. */
44
+ type TrustTokenStatus = "pending" | "ready" | "unavailable";
45
+ interface MountTrustPanelOptions {
46
+ /** The project's publishable key (cd_pub_…). The SDK client supplies this for you. */
47
+ publicKey: string;
48
+ /** Where to render the panel — an element or a selector resolved at mount time. */
49
+ target: HTMLElement | string;
50
+ /** Called once when a token is minted. Optional — you can await `ready` instead. */
51
+ onToken?: (t: TrustToken) => void;
52
+ /**
53
+ * Called if the panel could not mint (blocked, offline, timeout, our outage).
54
+ * INFORMATIONAL for your logs — NOT an error you must handle: `ready` still
55
+ * resolves and your signup proceeds. Fail-open is the contract.
56
+ */
57
+ onUnavailable?: (reason: string) => void;
58
+ /** Override the panel origin (tests / self-host). Defaults to production. */
59
+ origin?: string;
60
+ /** Max wait for a mint before failing open, in ms. Default 15000. */
61
+ timeoutMs?: number;
62
+ }
63
+ interface TrustPanelHandle {
64
+ /** The iframe we mounted — for layout/measurement only; never reach inside it. */
65
+ readonly frame: HTMLIFrameElement | null;
66
+ /**
67
+ * Resolves EXACTLY once: the token on success, or a {@link TrustUnavailable} if
68
+ * the panel failed open. NEVER rejects — a rejection would tempt callers to block
69
+ * the signup, which is precisely what fail-open forbids.
70
+ */
71
+ readonly ready: Promise<TrustResult>;
72
+ /** Tear down: remove the iframe + listeners. Idempotent. */
73
+ destroy(): void;
74
+ }
75
+ /**
76
+ * Options for `Crossdeck.trust.panel(...)` — the same as {@link MountTrustPanelOptions}
77
+ * but the SDK client injects `publicKey` from your `init()`, so you omit it.
78
+ */
79
+ type TrustPanelInput = Omit<MountTrustPanelOptions, "publicKey">;
80
+ /** The `Crossdeck.trust` namespace surfaced on the SDK client. */
81
+ interface CrossdeckTrustNamespace {
82
+ /** Render the branded Trust panel and mint an attestation. See {@link mountTrustPanel}. */
83
+ panel(input: TrustPanelInput): TrustPanelHandle;
84
+ }
85
+ /**
86
+ * Mount the Crossdeck Trust panel and mint an attestation. Framework-agnostic and
87
+ * guaranteed not to throw — any construction failure resolves `ready` fail-open.
88
+ */
89
+ declare function mountTrustPanel(opts: MountTrustPanelOptions): TrustPanelHandle;
90
+
91
+ export { type CrossdeckTrustNamespace as C, type MountTrustPanelOptions as M, TRUST_PANEL_ORIGIN as T, type TrustPanelHandle as a, type TrustPanelInput as b, type TrustResult as c, type TrustToken as d, type TrustTokenStatus as e, type TrustUnavailable as f, mountTrustPanel as m };
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Crossdeck Trust — the human-proof panel, native to the SDK.
3
+ *
4
+ * This is the browser half of Crossdeck Trust wired THROUGH the SDK the customer
5
+ * already runs, not bolted on beside it. It renders the SAME cross-origin iframe
6
+ * served from trust.cross-deck.com — the un-restylable, browser-enforced brand
7
+ * panel — and hands the minted attestation back PROGRAMMATICALLY (a Promise + an
8
+ * `onToken` callback) instead of the hidden-field/DOM handshake the raw
9
+ * `embed.js` loader uses. The iframe is the bouncer; the SDK is the premium front
10
+ * door to it. You pass the token to your server, which verifies it at the gate
11
+ * (`crossdeck.trust.gate(...)` in @cross-deck/node, or a raw POST /v1/trust/gate).
12
+ *
13
+ * Non-negotiables baked in (Stripe / Cloudflare / bank grade):
14
+ * - ISOLATED — every DOM / postMessage touch is wrapped; a stumble here can never
15
+ * throw into the host app, the rest of the SDK, or the customer's signup form.
16
+ * - FAIL-OPEN, never fail-allow — if the panel can't mint (adblocker, our outage,
17
+ * offline, timeout), `ready` resolves with NO token. The signup proceeds; the
18
+ * SERVER gate scores the ABSENCE. We never wave a tokenless request through, and
19
+ * we never block the form because our panel had a bad day. Failing CLOSED would
20
+ * hand an attacker a site-wide-outage weapon — so we never do.
21
+ * - ORIGIN-LOCKED — we only trust messages from OUR panel origin AND from this
22
+ * exact iframe's window. Nothing on the host page can forge a token.
23
+ * - The token is minted INSIDE our origin; the host page (even an XSS on it) never
24
+ * participates in the mint, it only receives the finished token.
25
+ */
26
+ /** The origin that serves the branded, un-restylable Trust panel. */
27
+ declare const TRUST_PANEL_ORIGIN = "https://trust.cross-deck.com";
28
+ /** A minted human-proof attestation. Pass `token` to your gate call. */
29
+ interface TrustToken {
30
+ /** The single-use, project-bound attestation to send to your server as `token`. */
31
+ token: string;
32
+ /** Epoch ms at which the token expires (mint fresh per signup attempt), or null. */
33
+ expiresAt: number | null;
34
+ }
35
+ /** Resolution of a panel that failed open — a token never minted. Not an error. */
36
+ interface TrustUnavailable {
37
+ token: null;
38
+ expiresAt: null;
39
+ /** Why no token was minted (for your logs) — e.g. "timeout", "blocked", "offline". */
40
+ reason: string;
41
+ }
42
+ type TrustResult = TrustToken | TrustUnavailable;
43
+ /** Lifecycle of a panel driven by a framework binding: pending → ready | unavailable. */
44
+ type TrustTokenStatus = "pending" | "ready" | "unavailable";
45
+ interface MountTrustPanelOptions {
46
+ /** The project's publishable key (cd_pub_…). The SDK client supplies this for you. */
47
+ publicKey: string;
48
+ /** Where to render the panel — an element or a selector resolved at mount time. */
49
+ target: HTMLElement | string;
50
+ /** Called once when a token is minted. Optional — you can await `ready` instead. */
51
+ onToken?: (t: TrustToken) => void;
52
+ /**
53
+ * Called if the panel could not mint (blocked, offline, timeout, our outage).
54
+ * INFORMATIONAL for your logs — NOT an error you must handle: `ready` still
55
+ * resolves and your signup proceeds. Fail-open is the contract.
56
+ */
57
+ onUnavailable?: (reason: string) => void;
58
+ /** Override the panel origin (tests / self-host). Defaults to production. */
59
+ origin?: string;
60
+ /** Max wait for a mint before failing open, in ms. Default 15000. */
61
+ timeoutMs?: number;
62
+ }
63
+ interface TrustPanelHandle {
64
+ /** The iframe we mounted — for layout/measurement only; never reach inside it. */
65
+ readonly frame: HTMLIFrameElement | null;
66
+ /**
67
+ * Resolves EXACTLY once: the token on success, or a {@link TrustUnavailable} if
68
+ * the panel failed open. NEVER rejects — a rejection would tempt callers to block
69
+ * the signup, which is precisely what fail-open forbids.
70
+ */
71
+ readonly ready: Promise<TrustResult>;
72
+ /** Tear down: remove the iframe + listeners. Idempotent. */
73
+ destroy(): void;
74
+ }
75
+ /**
76
+ * Options for `Crossdeck.trust.panel(...)` — the same as {@link MountTrustPanelOptions}
77
+ * but the SDK client injects `publicKey` from your `init()`, so you omit it.
78
+ */
79
+ type TrustPanelInput = Omit<MountTrustPanelOptions, "publicKey">;
80
+ /** The `Crossdeck.trust` namespace surfaced on the SDK client. */
81
+ interface CrossdeckTrustNamespace {
82
+ /** Render the branded Trust panel and mint an attestation. See {@link mountTrustPanel}. */
83
+ panel(input: TrustPanelInput): TrustPanelHandle;
84
+ }
85
+ /**
86
+ * Mount the Crossdeck Trust panel and mint an attestation. Framework-agnostic and
87
+ * guaranteed not to throw — any construction failure resolves `ready` fail-open.
88
+ */
89
+ declare function mountTrustPanel(opts: MountTrustPanelOptions): TrustPanelHandle;
90
+
91
+ export { type CrossdeckTrustNamespace as C, type MountTrustPanelOptions as M, TRUST_PANEL_ORIGIN as T, type TrustPanelHandle as a, type TrustPanelInput as b, type TrustResult as c, type TrustToken as d, type TrustTokenStatus as e, type TrustUnavailable as f, mountTrustPanel as m };
package/dist/vue.cjs CHANGED
@@ -21,7 +21,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var vue_exports = {};
22
22
  __export(vue_exports, {
23
23
  useEntitlement: () => useEntitlement,
24
- useEntitlements: () => useEntitlements
24
+ useEntitlements: () => useEntitlements,
25
+ useTrustToken: () => useTrustToken
25
26
  });
26
27
  module.exports = __toCommonJS(vue_exports);
27
28
  var import_vue = require("vue");
@@ -97,7 +98,7 @@ function typeMapForStatus(status) {
97
98
  }
98
99
 
99
100
  // src/_version.ts
100
- var SDK_VERSION = "1.11.2";
101
+ var SDK_VERSION = "1.13.0";
101
102
  var SDK_NAME = "@cross-deck/web";
102
103
 
103
104
  // src/http.ts
@@ -354,6 +355,125 @@ function randomChars(count) {
354
355
  return out.join("");
355
356
  }
356
357
 
358
+ // src/trust.ts
359
+ var TRUST_PANEL_ORIGIN = "https://trust.cross-deck.com";
360
+ var MAX_WIDTH_PX = 360;
361
+ var INITIAL_HEIGHT_PX = 132;
362
+ var MIN_HEIGHT_PX = 96;
363
+ var MAX_HEIGHT_PX = 220;
364
+ var DEFAULT_TIMEOUT_MS2 = 15e3;
365
+ function mountTrustPanel(opts) {
366
+ const origin = normalizeOrigin(opts.origin) || TRUST_PANEL_ORIGIN;
367
+ const timeoutMs = clampInt(opts.timeoutMs, DEFAULT_TIMEOUT_MS2, 1e3, 12e4);
368
+ let settled = false;
369
+ let onMessage = null;
370
+ let timer = null;
371
+ let frame = null;
372
+ let resolveReady;
373
+ const ready = new Promise((res) => {
374
+ resolveReady = res;
375
+ });
376
+ function settle(result, reason) {
377
+ if (settled) return;
378
+ settled = true;
379
+ if (timer) safe(() => clearTimeout(timer));
380
+ if (onMessage) safe(() => window.removeEventListener("message", onMessage));
381
+ if (result) {
382
+ safe(() => opts.onToken?.(result));
383
+ resolveReady(result);
384
+ } else {
385
+ const why = reason || "unavailable";
386
+ safe(() => opts.onUnavailable?.(why));
387
+ resolveReady({ token: null, expiresAt: null, reason: why });
388
+ }
389
+ }
390
+ try {
391
+ if (typeof window === "undefined" || typeof document === "undefined") {
392
+ queueMicrotask(() => settle(null, "no_dom"));
393
+ return makeHandle();
394
+ }
395
+ const host = resolveTarget(opts.target);
396
+ frame = createFrame(origin, opts.publicKey);
397
+ if (!host) {
398
+ queueMicrotask(() => settle(null, "no_mount_target"));
399
+ return makeHandle();
400
+ }
401
+ onMessage = (ev) => {
402
+ if (ev.origin !== origin) return;
403
+ if (!ev.data || !frame || ev.source !== frame.contentWindow) return;
404
+ const d = ev.data;
405
+ if (d.type === "cd-trust-size" && typeof d.height === "number") {
406
+ safe(() => {
407
+ if (frame) frame.style.height = clampInt(d.height, INITIAL_HEIGHT_PX, MIN_HEIGHT_PX, MAX_HEIGHT_PX) + "px";
408
+ });
409
+ } else if (d.type === "cd-trust-token" && typeof d.token === "string") {
410
+ settle({ token: d.token, expiresAt: typeof d.expMs === "number" ? d.expMs : null });
411
+ }
412
+ };
413
+ window.addEventListener("message", onMessage);
414
+ host.appendChild(frame);
415
+ timer = setTimeout(() => settle(null, "timeout"), timeoutMs);
416
+ } catch (err) {
417
+ queueMicrotask(() => settle(null, "mount_error:" + safeMessage(err)));
418
+ }
419
+ return makeHandle();
420
+ function makeHandle() {
421
+ return {
422
+ frame,
423
+ ready,
424
+ destroy() {
425
+ if (onMessage) safe(() => window.removeEventListener("message", onMessage));
426
+ if (timer) safe(() => clearTimeout(timer));
427
+ safe(() => frame?.parentNode?.removeChild(frame));
428
+ settle(null, "destroyed");
429
+ }
430
+ };
431
+ }
432
+ }
433
+ function createFrame(origin, publicKey) {
434
+ const frame = document.createElement("iframe");
435
+ frame.title = "Protected by Crossdeck Trust";
436
+ frame.setAttribute("aria-label", "Protected by Crossdeck Trust");
437
+ frame.setAttribute("scrolling", "no");
438
+ frame.setAttribute("allowtransparency", "true");
439
+ frame.style.cssText = "border:0;display:block;width:100%;max-width:" + MAX_WIDTH_PX + "px;height:" + INITIAL_HEIGHT_PX + "px;margin:0;background:transparent;color-scheme:light;";
440
+ frame.src = origin + "/panel?k=" + encodeURIComponent(publicKey || "");
441
+ return frame;
442
+ }
443
+ function resolveTarget(target) {
444
+ try {
445
+ if (typeof target === "string") return document.querySelector(target);
446
+ return target || null;
447
+ } catch {
448
+ return null;
449
+ }
450
+ }
451
+ function normalizeOrigin(o) {
452
+ if (!o || typeof o !== "string") return null;
453
+ try {
454
+ return new URL(o).origin;
455
+ } catch {
456
+ return null;
457
+ }
458
+ }
459
+ function clampInt(v, fallback, min, max) {
460
+ const n = typeof v === "number" && isFinite(v) ? v : fallback;
461
+ return Math.min(Math.max(n, min), max);
462
+ }
463
+ function safe(fn) {
464
+ try {
465
+ fn();
466
+ } catch {
467
+ }
468
+ }
469
+ function safeMessage(err) {
470
+ try {
471
+ return err instanceof Error ? err.message : String(err);
472
+ } catch {
473
+ return "unknown";
474
+ }
475
+ }
476
+
357
477
  // src/hash.ts
358
478
  var K = new Uint32Array([
359
479
  1116352408,
@@ -1587,6 +1707,7 @@ var AutoTracker = class {
1587
1707
  this.pageviewId = null;
1588
1708
  this.storage = opts?.storage ?? null;
1589
1709
  this.sessionKey = opts?.storageKey ?? SESSION_STORAGE_KEY;
1710
+ this.cookieStorage = opts?.cookieStorage ?? null;
1590
1711
  }
1591
1712
  install() {
1592
1713
  if (!isBrowserSafe()) return;
@@ -1738,9 +1859,74 @@ var AutoTracker = class {
1738
1859
  lastActivityAt: now,
1739
1860
  hiddenAt: null,
1740
1861
  endedSent: false,
1741
- acquisition: captureAcquisition()
1862
+ acquisition: this.resolveAcquisition()
1742
1863
  };
1743
1864
  }
1865
+ /**
1866
+ * Session acquisition, with FIRST-TOUCH survival across sessions.
1867
+ *
1868
+ * WHY: `captureAcquisition()` reads the CURRENT page. That is correct for a
1869
+ * fresh arrival, but a session boundary (30-min idle, or a return visit next
1870
+ * week) starts a new session — and a visitor returning directly has no utm_*
1871
+ * and no click id, so the acquisition that actually WON them was silently
1872
+ * replaced with empty. Someone who arrives from LinkedIn on Monday, returns
1873
+ * direct on Tuesday and signs up on Wednesday converted with no source at all.
1874
+ *
1875
+ * That is exactly the question the product exists to answer — "where did this
1876
+ * PAYING CUSTOMER come from" — so origin has to outlive the session that
1877
+ * captured it. We persist the first touch that carried a real signal and,
1878
+ * whenever a later session arrives with nothing, fall back to it.
1879
+ *
1880
+ * Deliberately NOT last-touch-wins: a real new campaign click overwrites
1881
+ * nothing, it simply records a newer touch for that session while the stored
1882
+ * first touch stays put. Write-once by design.
1883
+ */
1884
+ resolveAcquisition() {
1885
+ const current = captureAcquisition();
1886
+ if (!this.storage && !this.cookieStorage) return current;
1887
+ const key = `${this.sessionKey}_origin_first`;
1888
+ const readFirstTouch = () => {
1889
+ try {
1890
+ const v = this.storage?.getItem(key);
1891
+ if (v) return v;
1892
+ } catch {
1893
+ }
1894
+ try {
1895
+ return this.cookieStorage?.getItem(key) ?? null;
1896
+ } catch {
1897
+ return null;
1898
+ }
1899
+ };
1900
+ const writeFirstTouch = (v) => {
1901
+ try {
1902
+ this.storage?.setItem(key, v);
1903
+ } catch {
1904
+ }
1905
+ try {
1906
+ this.cookieStorage?.setItem(key, v);
1907
+ } catch {
1908
+ }
1909
+ };
1910
+ const hasSignal = (a) => Boolean(a.utm_source || a.utm_medium || a.utm_campaign || a.utm_content || a.utm_term || a.gclid || a.fbclid || a.msclkid || a.ttclid || a.li_fat_id || a.twclid);
1911
+ try {
1912
+ if (hasSignal(current)) {
1913
+ if (readFirstTouch() === null) writeFirstTouch(JSON.stringify(current));
1914
+ return current;
1915
+ }
1916
+ const raw = readFirstTouch();
1917
+ if (raw) {
1918
+ const stored = JSON.parse(raw);
1919
+ return {
1920
+ ...EMPTY_ACQUISITION,
1921
+ ...stored,
1922
+ // Referrer always describes THIS visit, never the remembered one.
1923
+ referrer: current.referrer
1924
+ };
1925
+ }
1926
+ } catch {
1927
+ }
1928
+ return current;
1929
+ }
1744
1930
  /**
1745
1931
  * Read the persisted session continuity record. Returns null on no
1746
1932
  * storage, no record, malformed JSON, or a record missing its required
@@ -4787,7 +4973,15 @@ var CrossdeckClient = class {
4787
4973
  // a visit survives full-page navigations (multi-page sites
4788
4974
  // re-install the SDK on every page) and honours the same consent
4789
4975
  // posture — MemoryStorage when identity persistence is off.
4790
- { storage: effectiveStorage, storageKey: opts.storagePrefix + "session" }
4976
+ // cookieStorage is the SAME registrable-domain cookie identity uses.
4977
+ // First-touch origin rides it so the campaign that won a visitor on the
4978
+ // marketing site is still known when they land on the app subdomain —
4979
+ // localStorage alone is per-origin and would lose it at exactly that hop.
4980
+ {
4981
+ storage: effectiveStorage,
4982
+ storageKey: opts.storagePrefix + "session",
4983
+ cookieStorage: cookieStore ?? void 0
4984
+ }
4791
4985
  );
4792
4986
  this.state.autoTracker = tracker;
4793
4987
  tracker.install();
@@ -5742,6 +5936,30 @@ var CrossdeckClient = class {
5742
5936
  getAnonymousId() {
5743
5937
  return this.state ? this.state.identity.anonymousId : null;
5744
5938
  }
5939
+ /**
5940
+ * **Crossdeck Trust** — human-proof at your signup, native to the SDK.
5941
+ *
5942
+ * `Crossdeck.trust.panel({ target, onToken })` renders the branded, un-restylable
5943
+ * Trust panel (the same cross-origin iframe on every install) and mints a
5944
+ * single-use attestation. Hand the token to your server and verify it at the gate
5945
+ * (`crossdeck.trust.gate(...)` in @cross-deck/node). The publishable key is taken
5946
+ * from your `init()` — you don't pass it again.
5947
+ *
5948
+ * Fail-open by contract: if the panel can't mint (adblocker, offline, our outage),
5949
+ * `ready` resolves with `{ token: null }` and your signup proceeds — the server
5950
+ * scores the missing token. It never throws and never blocks your form.
5951
+ *
5952
+ * @example
5953
+ * const { ready } = Crossdeck.trust.panel({ target: "#cd-trust" });
5954
+ * const result = await ready; // { token, expiresAt } | { token: null }
5955
+ * await createUser({ email, cdTrustToken: result.token });
5956
+ */
5957
+ get trust() {
5958
+ const publicKey = this.state ? this.state.options.publicKey : "";
5959
+ return {
5960
+ panel: (input) => mountTrustPanel({ ...input, publicKey })
5961
+ };
5962
+ }
5745
5963
  // ---------- private helpers ----------
5746
5964
  requireStarted() {
5747
5965
  if (!this.state) {
@@ -5901,6 +6119,26 @@ function useEntitlements() {
5901
6119
  });
5902
6120
  return r;
5903
6121
  }
6122
+ function useTrustToken() {
6123
+ const el = (0, import_vue.ref)(null);
6124
+ const token = (0, import_vue.ref)(null);
6125
+ const status = (0, import_vue.ref)("pending");
6126
+ (0, import_vue.onMounted)(() => {
6127
+ if (!el.value) return;
6128
+ const handle = Crossdeck.trust.panel({
6129
+ target: el.value,
6130
+ onToken: (t) => {
6131
+ token.value = t.token;
6132
+ status.value = "ready";
6133
+ },
6134
+ onUnavailable: () => {
6135
+ status.value = "unavailable";
6136
+ }
6137
+ });
6138
+ (0, import_vue.onScopeDispose)(() => handle.destroy());
6139
+ });
6140
+ return { el, token, status };
6141
+ }
5904
6142
  function safeIsEntitled(key) {
5905
6143
  try {
5906
6144
  return Crossdeck.isEntitled(key);
@@ -5918,6 +6156,7 @@ function safeListKeys() {
5918
6156
  // Annotate the CommonJS export names for ESM import in node:
5919
6157
  0 && (module.exports = {
5920
6158
  useEntitlement,
5921
- useEntitlements
6159
+ useEntitlements,
6160
+ useTrustToken
5922
6161
  });
5923
6162
  //# sourceMappingURL=vue.cjs.map