@holdyapp/sdk 1.6.0 → 1.9.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.
- package/README.md +8 -1
- package/dist/changes.d.ts +16 -2
- package/dist/changes.d.ts.map +1 -1
- package/dist/core.d.ts +1 -0
- package/dist/core.d.ts.map +1 -1
- package/dist/friction.d.ts +2 -1
- package/dist/friction.d.ts.map +1 -1
- package/dist/holdy.js +25 -4
- package/dist/holdy.js.map +4 -4
- package/dist/index.cjs +420 -36
- package/dist/index.cjs.map +4 -4
- package/dist/index.mjs +420 -36
- package/dist/index.mjs.map +4 -4
- package/dist/server.cjs +3 -0
- package/dist/server.cjs.map +2 -2
- package/dist/server.mjs +3 -0
- package/dist/server.mjs.map +2 -2
- package/dist/skeleton.d.ts +3 -1
- package/dist/skeleton.d.ts.map +1 -1
- package/dist/theme.d.ts +43 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/tip-css.d.ts +9 -0
- package/dist/tip-css.d.ts.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/web-context.d.ts +1 -0
- package/dist/web-context.d.ts.map +1 -1
- package/dist/web.d.ts +2 -1
- package/dist/web.d.ts.map +1 -1
- package/dist/web.mjs +420 -36
- package/dist/web.mjs.map +4 -4
- package/package.json +1 -1
- package/src/changes.dom.test.ts +221 -0
- package/src/changes.test.ts +38 -0
- package/src/changes.ts +299 -26
- package/src/core.test.ts +15 -0
- package/src/core.ts +3 -0
- package/src/friction.dom.test.ts +54 -0
- package/src/friction.test.ts +43 -0
- package/src/friction.ts +44 -7
- package/src/skeleton.ts +12 -3
- package/src/theme.test.ts +118 -0
- package/src/theme.ts +120 -0
- package/src/tip-css.ts +32 -0
- package/src/types.ts +6 -0
- package/src/web-context.test.ts +18 -0
- package/src/web-context.ts +8 -0
- package/src/web.ts +8 -2
package/dist/web.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/core.ts", "../src/auto-capture.ts", "../src/friction.ts", "../src/skeleton.ts", "../src/web-context.ts", "../src/arm.ts", "../src/changes.ts", "../src/web.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Core do @holdyapp/sdk \u00B7 fila + flush pra POST /api/v1/events/bulk.\n *\n * Todo evento sai com `external_id` pr\u00F3prio, ent\u00E3o reenviar um lote nunca\n * duplica (dedupe server-side por source + external_id + occurred_at).\n * 429 respeita Retry-After; 5xx e rede esperam com backoff exponencial; o lote\n * volta pra frente da fila em vez de sumir. Chave inv\u00E1lida ou origem recusada\n * avisam uma vez no console, mesmo sem debug. Fila \u00E9 bounded: acima de\n * MAX_QUEUE dropa os mais antigos (telemetria nunca derruba o app do cliente \u2014\n * nenhum m\u00E9todo p\u00FAblico lan\u00E7a).\n */\n\nimport type { CanonicalEvent, HoldyOptions, Properties, TrackOverrides } from './types'\n\nexport const DEFAULT_BASE_URL = 'https://holdy.chat/api/v1'\nconst DEFAULT_FLUSH_AT = 20\nconst DEFAULT_FLUSH_INTERVAL_MS = 5000\nconst MAX_QUEUE = 1000\nconst BULK_LIMIT = 500\nconst MAX_BACKOFF_MS = 60_000\n\ntype SendOutcome = { kind: 'sent' } | { kind: 'dropped' } | { kind: 'retry'; afterMs: number | null }\n\nexport class HoldyCore {\n protected readonly apiKey: string\n protected readonly baseUrl: string\n private readonly flushAt: number\n private readonly debug: boolean\n private readonly source: 'sdk_web' | 'sdk_server'\n\n private queue: CanonicalEvent[] = []\n private timer: ReturnType<typeof setInterval> | null = null\n private flushing: Promise<void> | null = null\n private retryAt = 0\n private failures = 0\n private readonly warned = new Set<string>()\n\n protected userId: string | null = null\n protected anonymousId: string | null = null\n protected accountKey: string | null = null\n\n constructor(source: 'sdk_web' | 'sdk_server', opts: HoldyOptions) {\n this.source = source\n this.apiKey = opts.apiKey\n this.accountKey = opts.accountKey ?? null\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '')\n this.flushAt = Math.max(1, opts.flushAt ?? DEFAULT_FLUSH_AT)\n this.debug = opts.debug ?? false\n\n const intervalMs = opts.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS\n if (intervalMs > 0) {\n this.timer = setInterval(() => void this.flush(), intervalMs)\n // Node: n\u00E3o segura o processo vivo s\u00F3 pelo timer do SDK.\n if (typeof (this.timer as { unref?: () => void }).unref === 'function') {\n ;(this.timer as unknown as { unref: () => void }).unref()\n }\n }\n }\n\n track(name: string, properties?: Properties, overrides?: TrackOverrides): void {\n if (!name || typeof name !== 'string') return\n\n const userId = overrides?.userId ?? this.userId ?? undefined\n const accountKey = overrides?.accountKey ?? this.accountKey ?? undefined\n const occurredAt = overrides?.occurredAt\n ? new Date(overrides.occurredAt).toISOString()\n : new Date().toISOString()\n\n // Ordem: ambiente observado pelo SDK \u2192 context da chamada \u2192 carrier de\n // account. O que o caller passou vence o inferido; o carrier vence tudo,\n // porque \u00E9 o que a Data layer usa pra resolver a conta.\n const context: Properties = {\n ...this.environmentContext(),\n ...(overrides?.context ?? {}),\n }\n if (accountKey) context.account_external_id = accountKey\n\n const event: CanonicalEvent = {\n event: name,\n occurred_at: occurredAt,\n source: this.source,\n external_id: newEventId(),\n ...(userId ? { user_id: userId } : {}),\n ...(this.anonymousId ? { anonymous_id: this.anonymousId } : {}),\n properties: properties ?? {},\n ...(Object.keys(context).length > 0 ? { context } : {}),\n }\n\n this.queue.push(event)\n this.trimQueue()\n if (this.queue.length >= this.flushAt) void this.flush()\n }\n\n identify(userId: string, traits?: Properties): void {\n if (!userId || typeof userId !== 'string') return\n this.userId = userId\n this.track('$identify', traits ?? {})\n }\n\n group(accountKey: string, traits?: Properties): void {\n if (!accountKey || typeof accountKey !== 'string') return\n this.accountKey = accountKey\n this.track('$group', traits ?? {})\n }\n\n /** Drena a fila. Nunca lan\u00E7a \u2014 falha re-enfileira e espera antes de tentar de novo. */\n async flush(): Promise<void> {\n return this.startFlush(false)\n }\n\n /** Flush final + para o timer. Chamar em shutdown do server / unload do web. */\n async shutdown(): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer)\n this.timer = null\n }\n await this.startFlush(true)\n }\n\n private startFlush(force: boolean): Promise<void> {\n // Serializa flushes concorrentes (timer + flushAt + manual).\n if (this.flushing) return this.flushing\n if (this.queue.length === 0) return Promise.resolve()\n if (!force && Date.now() < this.retryAt) return Promise.resolve()\n\n this.flushing = this.drain().finally(() => {\n this.flushing = null\n })\n return this.flushing\n }\n\n private async drain(): Promise<void> {\n while (this.queue.length > 0) {\n const batch = this.queue.splice(0, BULK_LIMIT)\n const outcome = await this.send(batch)\n if (outcome.kind === 'retry') {\n this.queue.unshift(...batch)\n this.trimQueue()\n this.scheduleRetry(outcome.afterMs)\n return\n }\n this.failures = 0\n this.retryAt = 0\n }\n }\n\n private scheduleRetry(afterMs: number | null): void {\n this.failures += 1\n if (afterMs !== null) {\n this.retryAt = Date.now() + afterMs\n return\n }\n const backoff = Math.min(MAX_BACKOFF_MS, 1000 * 2 ** (this.failures - 1))\n this.retryAt = Date.now() + backoff + Math.floor(Math.random() * backoff * 0.2)\n }\n\n private trimQueue(): void {\n if (this.queue.length > MAX_QUEUE) this.queue.splice(0, this.queue.length - MAX_QUEUE)\n }\n\n private async send(events: CanonicalEvent[]): Promise<SendOutcome> {\n try {\n const res = await fetch(`${this.baseUrl}/events/bulk`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ events }),\n ...(this.source === 'sdk_web' ? { keepalive: true } : {}),\n })\n if (res.ok) return { kind: 'sent' }\n\n if (res.status === 429) {\n this.log('rate limited \u00B7 will retry after Retry-After')\n return { kind: 'retry', afterMs: retryAfterMs(res) }\n }\n if (res.status >= 500) {\n this.log(`bulk failed ${res.status} \u00B7 will retry with backoff`)\n return { kind: 'retry', afterMs: null }\n }\n if (res.status === 401) {\n this.warnOnce('401', 'API key inv\u00E1lida ou revogada \u00B7 eventos descartados. Confira a chave em Configura\u00E7\u00F5es \u203A SDK.')\n return { kind: 'dropped' }\n }\n if (res.status === 403) {\n this.warnOnce('403', 'Origem n\u00E3o permitida ou chave sem escopo events:write \u00B7 eventos descartados.')\n return { kind: 'dropped' }\n }\n this.log(`bulk rejected ${res.status} \u00B7 batch dropped`)\n return { kind: 'dropped' }\n } catch (err) {\n this.log(`bulk network error: ${(err as Error).message} \u00B7 will retry with backoff`)\n return { kind: 'retry', afterMs: null }\n }\n }\n\n private log(msg: string): void {\n if (this.debug) console.warn(`[holdy] ${msg}`)\n }\n\n private warnOnce(key: string, msg: string): void {\n if (this.warned.has(key)) return\n this.warned.add(key)\n console.warn(`[holdy] ${msg}`)\n }\n\n /**\n * Ambiente que o SDK observa sozinho (url, referrer, browser, utm\u2026).\n * Vazio no core; `HoldyWeb` preenche. O server n\u00E3o infere ambiente \u2014 n\u00E3o\n * existe \"p\u00E1gina atual\" num worker.\n */\n protected environmentContext(): Properties {\n return {}\n }\n\n /** Interno \u00B7 exposto pra testes. */\n get pending(): number {\n return this.queue.length\n }\n}\n\nfunction retryAfterMs(res: Response): number | null {\n const raw = typeof res.headers?.get === 'function' ? res.headers.get('Retry-After') : null\n if (!raw) return null\n const seconds = Number(raw)\n if (!Number.isFinite(seconds) || seconds < 0) return null\n return Math.min(MAX_BACKOFF_MS, seconds * 1000)\n}\n\nfunction newEventId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto\n if (typeof c?.randomUUID === 'function') return c.randomUUID()\n const rand = () => Math.random().toString(36).slice(2, 12)\n return `${Date.now().toString(36)}-${rand()}-${rand()}`\n}\n", "/**\n * Auto-capture de navega\u00E7\u00E3o \u00B7 @holdyapp/sdk/web.\n *\n * Emite pageview no carregamento e a cada mudan\u00E7a de rota, inclusive nas que\n * n\u00E3o recarregam a p\u00E1gina (SPA). Sem isto, instrumentar exige que o cliente\n * chame `page()` em cada tela \u2014 e o primeiro dado s\u00F3 aparece depois de um\n * trabalho que ele ainda n\u00E3o fez.\n *\n * Idempotente: reinstalar \u00E9 no-op (guard global). O retorno desfaz o patch de\n * `history`, ent\u00E3o `destroy()` devolve o browser como estava.\n */\n\nconst INSTALLED_FLAG = '__holdy_autocapture__'\n\n/** pushState seguido de replaceState \u00E9 uma mudan\u00E7a l\u00F3gica s\u00F3. */\nconst ROUTE_DEBOUNCE_MS = 50\n\nexport type NavigationKind = 'initial_load' | 'route_change'\n\nexport interface AutoCaptureOptions {\n onNavigate: (kind: NavigationKind) => void\n}\n\ninterface GlobalWithFlag {\n [INSTALLED_FLAG]?: boolean\n}\n\nexport function installAutoCapture(opts: AutoCaptureOptions): () => void {\n if (typeof window === 'undefined' || typeof history === 'undefined') {\n return () => undefined\n }\n\n const w = window as unknown as GlobalWithFlag\n if (w[INSTALLED_FLAG]) return () => undefined\n w[INSTALLED_FLAG] = true\n\n const cleanups: Array<() => void> = []\n let lastPath = currentPath()\n let pending: ReturnType<typeof setTimeout> | null = null\n\n function emit(kind: NavigationKind): void {\n try {\n opts.onNavigate(kind)\n } catch {\n // Telemetria nunca derruba a app do cliente.\n }\n }\n\n function scheduleRouteEmit(): void {\n if (pending) clearTimeout(pending)\n pending = setTimeout(() => {\n pending = null\n const path = currentPath()\n // S\u00F3 conta como pageview se a rota mudou de fato \u2014 replaceState de\n // estado interno (filtro, scroll) n\u00E3o \u00E9 navega\u00E7\u00E3o.\n if (path === lastPath) return\n lastPath = path\n emit('route_change')\n }, ROUTE_DEBOUNCE_MS)\n }\n\n emit('initial_load')\n\n const originalPush = history.pushState\n const originalReplace = history.replaceState\n\n history.pushState = function patchedPush(...args: Parameters<History['pushState']>) {\n const result = originalPush.apply(this, args)\n scheduleRouteEmit()\n return result\n }\n history.replaceState = function patchedReplace(...args: Parameters<History['replaceState']>) {\n const result = originalReplace.apply(this, args)\n scheduleRouteEmit()\n return result\n }\n cleanups.push(() => {\n history.pushState = originalPush\n history.replaceState = originalReplace\n })\n\n // Voltar/avan\u00E7ar do browser e routers baseados em hash.\n const onPop = (): void => scheduleRouteEmit()\n window.addEventListener('popstate', onPop)\n cleanups.push(() => window.removeEventListener('popstate', onPop))\n\n const onHash = (): void => scheduleRouteEmit()\n window.addEventListener('hashchange', onHash)\n cleanups.push(() => window.removeEventListener('hashchange', onHash))\n\n return () => {\n if (pending) clearTimeout(pending)\n for (const cleanup of cleanups) cleanup()\n w[INSTALLED_FLAG] = false\n }\n}\n\n/** Rota compar\u00E1vel \u00B7 path + query, sem hash de \u00E2ncora. */\nfunction currentPath(): string {\n if (typeof location === 'undefined') return '/'\n return `${location.pathname}${location.search}${location.hash}`\n}\n", "export type FrictionKind =\n | 'dead_click'\n | 'rage_click'\n | 'form_abandon'\n | 'js_error'\n | 'slow_request'\n | 'nav_loop'\n | 'http_error'\n\nexport interface FrictionSignal {\n kind: FrictionKind\n properties: Record<string, unknown>\n}\n\nexport interface FrictionCaptureOptions {\n onFriction: (signal: FrictionSignal) => void\n slowRequestMs?: number\n rageClicks?: number\n rageWindowMs?: number\n rageRadiusPx?: number\n navLoopWindowMs?: number\n ignoreUrls?: string[]\n /**\n * Origens que contam como o pr\u00F3prio produto al\u00E9m do dom\u00EDnio da p\u00E1gina \u2014\n * pro caso em que a API mora em outro dom\u00EDnio (`acme-api.io` servindo\n * `acme.com`). O subdom\u00EDnio j\u00E1 entra sozinho.\n */\n apiOrigins?: string[]\n}\n\nexport interface FrictionCapture {\n onNavigate: (path: string) => void\n teardown: () => void\n}\n\nconst INSTALLED_FLAG = '__holdy_friction__'\nconst INTERACTIVE_SELECTOR =\n 'button, a, input, select, textarea, summary, [role=\"button\"], [role=\"link\"], [role=\"menuitem\"], [role=\"tab\"]'\nconst INTERACTIVE_TAGS = new Set(['button', 'a', 'input', 'select', 'textarea', 'summary'])\nconst FORM_CONTROL_TAGS = new Set(['input', 'select', 'textarea'])\n\nexport class RageClickDetector {\n private clicks: Array<{ x: number; y: number; t: number }> = []\n\n constructor(\n private readonly threshold = 3,\n private readonly windowMs = 1000,\n private readonly radiusPx = 30,\n ) {}\n\n push(x: number, y: number, t: number): boolean {\n this.clicks = this.clicks.filter(\n (c) => t - c.t <= this.windowMs && Math.hypot(c.x - x, c.y - y) <= this.radiusPx,\n )\n this.clicks.push({ x, y, t })\n if (this.clicks.length >= this.threshold) {\n this.clicks = []\n return true\n }\n return false\n }\n}\n\nexport class NavLoopDetector {\n private visits: Array<{ path: string; t: number }> = []\n\n constructor(private readonly windowMs = 60_000) {}\n\n push(path: string, t: number): { from: string; to: string } | null {\n this.visits = [...this.visits, { path, t }].filter((v) => t - v.t <= this.windowMs).slice(-4)\n if (this.visits.length < 4) return null\n const [a, b, c, d] = this.visits.map((v) => v.path)\n if (a === c && b === d && a !== b) {\n this.visits = []\n return { from: a, to: b }\n }\n return null\n }\n}\n\nexport interface ElementLike {\n tagName: string\n id?: string\n disabled?: boolean\n textContent?: string | null\n getAttribute(name: string): string | null\n closest?(selector: string): ElementLike | null\n}\n\nexport function resolveInteractive(el: ElementLike | null): ElementLike | null {\n if (!el) return null\n const viaClosest = el.closest?.(INTERACTIVE_SELECTOR) ?? null\n if (viaClosest) return viaClosest\n const tag = el.tagName.toLowerCase()\n if (INTERACTIVE_TAGS.has(tag)) return el\n const role = el.getAttribute('role')\n if (role === 'button' || role === 'link' || role === 'menuitem' || role === 'tab') return el\n return null\n}\n\nexport function isDeadClickTarget(el: ElementLike | null): boolean {\n const target = resolveInteractive(el)\n if (!target) return false\n if (target.disabled === true) return true\n if (target.getAttribute('disabled') !== null) return true\n if (target.getAttribute('aria-disabled') === 'true') return true\n const tag = target.tagName.toLowerCase()\n if (tag === 'a') {\n const href = target.getAttribute('href')\n if (!href || href === '#' || href.startsWith('javascript:')) return true\n }\n return false\n}\n\nexport function describeElement(el: ElementLike | null): Record<string, string> {\n const target = resolveInteractive(el) ?? el\n if (!target) return {}\n const out: Record<string, string> = { element: target.tagName.toLowerCase() }\n if (target.id) out.element_id = target.id\n const role = target.getAttribute('role')\n if (role) out.element_role = role\n const label = target.getAttribute('aria-label') ?? target.textContent ?? ''\n const text = label.replace(/\\s+/g, ' ').trim().slice(0, 60)\n if (text) out.element_text = text\n const name = target.getAttribute('name') ?? target.getAttribute('data-testid')\n if (name) out.element_name = name\n return out\n}\n\nexport function stripRequestUrl(input: string, base?: string): string {\n try {\n const url = new URL(input, base)\n return `${url.origin}${url.pathname}`\n } catch {\n return input.split('?')[0].split('#')[0]\n }\n}\n\nexport function errorMessage(reason: unknown): string {\n if (reason instanceof Error) return reason.message\n if (typeof reason === 'string') return reason\n try {\n return JSON.stringify(reason)\n } catch {\n return String(reason)\n }\n}\n\nexport function isAbortError(err: unknown): boolean {\n return typeof err === 'object' && err !== null && (err as { name?: unknown }).name === 'AbortError'\n}\n\nexport function isIgnoredUrl(url: string, ignore: readonly string[]): boolean {\n return ignore.some((prefix) => prefix.length > 0 && url.startsWith(prefix))\n}\n\n/**\n * Dom\u00EDnio registr\u00E1vel aproximado \u2014 os dois \u00FAltimos r\u00F3tulos do host.\n *\n * `app.acme.com` e `api.acme.com` \u2192 `acme.com`: produto que fala com a pr\u00F3pria\n * API em outro subdom\u00EDnio continua sendo primeira parte. Sem lista de sufixos\n * p\u00FAblicos, `foo.co.uk` e `bar.co.uk` colidem \u2014 e a colis\u00E3o erra pro lado\n * seguro, incluindo como pr\u00F3prio o que hoje j\u00E1 \u00E9 inclu\u00EDdo.\n */\nexport function registrableDomain(host: string): string {\n const labels = host.toLowerCase().split('.').filter(Boolean)\n if (labels.length <= 2) return labels.join('.')\n return labels.slice(-2).join('.')\n}\n\n/**\n * A requisi\u00E7\u00E3o \u00E9 do produto de quem instalou, ou de um terceiro?\n *\n * Fric\u00E7\u00E3o \u00E9 fric\u00E7\u00E3o DO PRODUTO. Um `google-analytics.com/g/collect` morto por\n * ad blocker n\u00E3o \u00E9 o produto falhando \u2014 \u00E9 o navegador do visitante recusando\n * um script que nem \u00E9 seu. Em 2026-09-17 esses dois dom\u00EDnios respondiam por 36\n * dos eventos de fric\u00E7\u00E3o da janela: num cliente com GA instalado e usu\u00E1rios com\n * bloqueador, isso infla a fric\u00E7\u00E3o e pode abrir oportunidade em cima de nada.\n *\n * Localhost e IP entram pela compara\u00E7\u00E3o de host exato \u2014 em desenvolvimento n\u00E3o\n * h\u00E1 dom\u00EDnio registr\u00E1vel que valha.\n */\nexport function isFirstPartyRequest(url: string, pageUrl: string, extraOrigins: readonly string[] = []): boolean {\n let target: URL\n let page: URL\n try {\n target = new URL(url, pageUrl)\n page = new URL(pageUrl)\n } catch {\n return true\n }\n if (target.protocol !== 'http:' && target.protocol !== 'https:') return true\n if (target.host === page.host) return true\n if (extraOrigins.some((o) => o.length > 0 && target.origin === o)) return true\n const targetDomain = registrableDomain(target.hostname)\n return targetDomain.length > 0 && targetDomain === registrableDomain(page.hostname)\n}\n\nexport interface RequestOutcome {\n status: number | null\n durationMs: number\n slowMs: number\n aborted?: boolean\n opaque?: boolean\n}\n\nexport function classifyRequest(outcome: RequestOutcome): 'http_error' | 'slow_request' | null {\n if (outcome.aborted) return null\n if (!outcome.opaque && (outcome.status === null || outcome.status >= 400)) return 'http_error'\n return outcome.durationMs >= outcome.slowMs ? 'slow_request' : null\n}\n\nexport function documentStatus(\n perf: { getEntriesByType?: (type: string) => unknown[] } | undefined,\n): number | null {\n try {\n const entry = perf?.getEntriesByType?.('navigation')?.[0] as { responseStatus?: unknown } | undefined\n const status = entry?.responseStatus\n return typeof status === 'number' && status > 0 ? status : null\n } catch {\n return null\n }\n}\n\ninterface FormTouch {\n form: string\n fields: Set<string>\n}\n\nfunction formKey(form: HTMLFormElement): string {\n return (\n form.id ||\n form.getAttribute('name') ||\n form.getAttribute('data-testid') ||\n stripRequestUrl(form.getAttribute('action') ?? '', location.href).replace(location.origin, '') ||\n 'form'\n )\n}\n\nfunction currentPath(): string {\n return typeof location === 'undefined' ? '/' : location.pathname || '/'\n}\n\nexport function installFrictionCapture(opts: FrictionCaptureOptions): FrictionCapture {\n const noop: FrictionCapture = { onNavigate: () => undefined, teardown: () => undefined }\n if (typeof window === 'undefined' || typeof document === 'undefined') return noop\n\n const w = window as unknown as Record<string, boolean | undefined>\n if (w[INSTALLED_FLAG]) return noop\n w[INSTALLED_FLAG] = true\n\n const emit = (kind: FrictionKind, properties: Record<string, unknown>): void => {\n try {\n opts.onFriction({ kind, properties: { path: currentPath(), ...properties } })\n } catch {\n return\n }\n }\n\n const cleanups: Array<() => void> = []\n const rage = new RageClickDetector(opts.rageClicks, opts.rageWindowMs, opts.rageRadiusPx)\n const navLoop = new NavLoopDetector(opts.navLoopWindowMs)\n const slowMs = opts.slowRequestMs ?? 3000\n const touched = new Map<HTMLFormElement, FormTouch>()\n\n const onClick = (ev: MouseEvent): void => {\n const el = ev.target instanceof Element ? (ev.target as unknown as ElementLike) : null\n if (isDeadClickTarget(el)) emit('dead_click', describeElement(el))\n if (rage.push(ev.clientX, ev.clientY, ev.timeStamp || Date.now())) {\n emit('rage_click', describeElement(el))\n }\n }\n document.addEventListener('click', onClick, true)\n cleanups.push(() => document.removeEventListener('click', onClick, true))\n\n const onError = (ev: ErrorEvent): void => {\n emit('js_error', {\n message: String(ev.message ?? '').slice(0, 200),\n ...(ev.filename ? { source: stripRequestUrl(ev.filename, location.href) } : {}),\n ...(ev.lineno ? { line: ev.lineno } : {}),\n })\n }\n window.addEventListener('error', onError)\n cleanups.push(() => window.removeEventListener('error', onError))\n\n const onRejection = (ev: PromiseRejectionEvent): void => {\n emit('js_error', { message: errorMessage(ev.reason).slice(0, 200), unhandled_rejection: true })\n }\n window.addEventListener('unhandledrejection', onRejection)\n cleanups.push(() => window.removeEventListener('unhandledrejection', onRejection))\n\n const ignore = (opts.ignoreUrls ?? []).map((url) => stripRequestUrl(url, location.href))\n const apiOrigins = (opts.apiOrigins ?? []).map((o) => {\n try {\n return new URL(o, location.href).origin\n } catch {\n return ''\n }\n })\n const reportRequest = (\n url: string,\n method: string,\n started: number,\n status: number | null,\n flags: { aborted?: boolean; opaque?: boolean } = {},\n ): void => {\n const target = stripRequestUrl(url, location.href)\n if (isIgnoredUrl(target, ignore)) return\n if (!isFirstPartyRequest(target, location.href, apiOrigins)) return\n const durationMs = performance.now() - started\n const kind = classifyRequest({ status, durationMs, slowMs, ...flags })\n if (!kind) return\n emit(kind, {\n url: target,\n method,\n duration_ms: Math.round(durationMs),\n ...(flags.opaque ? {} : status !== null ? { status } : { failed: true }),\n })\n }\n\n const originalFetch = window.fetch\n if (typeof originalFetch === 'function') {\n const patched: typeof window.fetch = async (input, init) => {\n const started = performance.now()\n const url =\n typeof input === 'string' ? input : input instanceof URL ? input.href : input.url\n const method = (init?.method ?? (input instanceof Request ? input.method : 'GET')).toUpperCase()\n try {\n const res = await originalFetch(input, init)\n reportRequest(url, method, started, res.status, {\n opaque: res.type === 'opaque' || res.type === 'opaqueredirect',\n })\n return res\n } catch (err) {\n reportRequest(url, method, started, null, { aborted: isAbortError(err) })\n throw err\n }\n }\n window.fetch = patched\n cleanups.push(() => {\n window.fetch = originalFetch\n })\n }\n\n const xhrProto = typeof XMLHttpRequest === 'function' ? XMLHttpRequest.prototype : null\n if (xhrProto) {\n const originalOpen = xhrProto.open\n const originalSend = xhrProto.send\n const requests = new WeakMap<XMLHttpRequest, { method: string; url: string }>()\n xhrProto.open = function (this: XMLHttpRequest, method: string, url: string | URL, ...rest: unknown[]) {\n requests.set(this, { method: String(method).toUpperCase(), url: String(url) })\n return (originalOpen as (...args: unknown[]) => void).apply(this, [method, url, ...rest])\n } as typeof xhrProto.open\n xhrProto.send = function (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null) {\n const request = requests.get(this)\n if (request) {\n const started = performance.now()\n let aborted = false\n this.addEventListener('abort', () => {\n aborted = true\n })\n this.addEventListener('loadend', () => {\n reportRequest(request.url, request.method, started, this.status === 0 ? null : this.status, { aborted })\n })\n }\n return originalSend.call(this, body)\n }\n cleanups.push(() => {\n xhrProto.open = originalOpen\n xhrProto.send = originalSend\n })\n }\n\n const loadStatus = documentStatus(typeof performance === 'undefined' ? undefined : performance)\n if (loadStatus !== null && loadStatus >= 400) {\n emit('http_error', { document: true, status: loadStatus, url: stripRequestUrl(location.href) })\n }\n\n const onFocusIn = (ev: FocusEvent): void => {\n const el = ev.target as HTMLElement | null\n if (!el || !FORM_CONTROL_TAGS.has(el.tagName.toLowerCase())) return\n const form = (el as HTMLInputElement).form\n if (!form) return\n const entry = touched.get(form) ?? { form: formKey(form), fields: new Set<string>() }\n const field = (el as HTMLInputElement).name || el.id || el.tagName.toLowerCase()\n entry.fields.add(field)\n touched.set(form, entry)\n }\n document.addEventListener('focusin', onFocusIn, true)\n cleanups.push(() => document.removeEventListener('focusin', onFocusIn, true))\n\n const onSubmit = (ev: Event): void => {\n if (ev.target instanceof HTMLFormElement) touched.delete(ev.target)\n }\n document.addEventListener('submit', onSubmit, true)\n cleanups.push(() => document.removeEventListener('submit', onSubmit, true))\n\n const flushAbandons = (): void => {\n for (const entry of touched.values()) {\n emit('form_abandon', { form: entry.form, fields_touched: entry.fields.size })\n }\n touched.clear()\n }\n window.addEventListener('pagehide', flushAbandons)\n cleanups.push(() => window.removeEventListener('pagehide', flushAbandons))\n\n return {\n onNavigate: (path: string) => {\n flushAbandons()\n const loop = navLoop.push(path, Date.now())\n if (loop) emit('nav_loop', { from: loop.from, to: loop.to })\n },\n teardown: () => {\n for (const cleanup of cleanups) cleanup()\n touched.clear()\n w[INSTALLED_FLAG] = false\n },\n }\n}\n", "export const SKELETON_SELECTOR =\n 'a[href], button, input, select, textarea, [role=\"button\"], [role=\"link\"], [role=\"tab\"], [role=\"menuitem\"], [role=\"checkbox\"], [role=\"radio\"], [role=\"switch\"], [data-testid]'\nexport const SKELETON_MAX_ELEMENTS = 80\nexport const SKELETON_DELAY_MS = 1500\nconst SENT_STORAGE_KEY = 'holdy_skeletons'\nconst SENT_STORAGE_MAX = 200\n\nexport interface SkeletonRect {\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface SkeletonElementLike {\n tagName: string\n getAttribute(name: string): string | null\n getBoundingClientRect?(): SkeletonRect\n}\n\nexport interface SkeletonRootLike {\n querySelectorAll(selector: string): ArrayLike<SkeletonElementLike>\n}\n\nexport interface SkeletonViewport {\n width: number\n height: number\n scrollY: number\n}\n\nexport interface SkeletonElement {\n t: string\n r?: string\n id?: string\n n?: string\n l?: string\n k?: string\n b?: [number, number, number, number]\n}\n\nexport interface PageSkeleton {\n path: string\n hash: string\n count: number\n elements: SkeletonElement[]\n}\n\nexport function fnv1a(input: string): string {\n let hash = 0x811c9dc5\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i)\n hash = Math.imul(hash, 0x01000193) >>> 0\n }\n return hash.toString(16).padStart(8, '0')\n}\n\nfunction attr(el: SkeletonElementLike, name: string, max: number): string | undefined {\n const value = el.getAttribute(name)\n if (!value) return undefined\n const trimmed = value.replace(/\\s+/g, ' ').trim().slice(0, max)\n return trimmed || undefined\n}\n\nfunction isVisible(el: SkeletonElementLike): boolean {\n if (!el.getBoundingClientRect) return true\n const rect = el.getBoundingClientRect()\n return rect.width > 0 && rect.height > 0\n}\n\nfunction relativeBox(rect: SkeletonRect, viewport: SkeletonViewport): [number, number, number, number] {\n const pct = (value: number, base: number) => (base > 0 ? Math.max(0, Math.min(100, Math.round((value / base) * 100))) : 0)\n return [pct(rect.x, viewport.width), pct(rect.y + viewport.scrollY, viewport.height), pct(rect.width, viewport.width), pct(rect.height, viewport.height)]\n}\n\nexport function describeSkeletonElement(el: SkeletonElementLike, viewport: SkeletonViewport | null): SkeletonElement {\n const out: SkeletonElement = { t: el.tagName.toLowerCase() }\n const role = attr(el, 'role', 40)\n if (role) out.r = role\n const testid = attr(el, 'data-testid', 80)\n if (testid) out.id = testid\n const name = attr(el, 'name', 80)\n if (name) out.n = name\n const label = attr(el, 'aria-label', 80)\n if (label) out.l = label\n if (out.t === 'input' || out.t === 'button') {\n const type = attr(el, 'type', 20)\n if (type) out.k = type.toLowerCase()\n }\n if (viewport && el.getBoundingClientRect) out.b = relativeBox(el.getBoundingClientRect(), viewport)\n return out\n}\n\nexport function collectSkeleton(root: SkeletonRootLike, path: string, viewport: SkeletonViewport | null): PageSkeleton {\n const found = root.querySelectorAll(SKELETON_SELECTOR)\n const visible: SkeletonElementLike[] = []\n for (let i = 0; i < found.length; i++) {\n const el = found[i]\n if (el.tagName.toLowerCase() === 'input' && (el.getAttribute('type') ?? '').toLowerCase() === 'hidden') continue\n if (!isVisible(el)) continue\n visible.push(el)\n }\n const elements = visible.slice(0, SKELETON_MAX_ELEMENTS).map((el) => describeSkeletonElement(el, viewport))\n const structural = elements.map(({ b: _b, ...rest }) => rest)\n return { path, hash: fnv1a(JSON.stringify(structural)), count: visible.length, elements }\n}\n\nexport interface SkeletonCaptureOptions {\n onSkeleton: (skeleton: PageSkeleton) => void\n delayMs?: number\n}\n\nexport interface SkeletonCapture {\n onNavigate: (path: string) => void\n teardown: () => void\n}\n\nfunction loadSent(): Set<string> {\n try {\n const raw = sessionStorage.getItem(SENT_STORAGE_KEY)\n const list = raw ? (JSON.parse(raw) as unknown) : []\n return new Set(Array.isArray(list) ? list.filter((x): x is string => typeof x === 'string') : [])\n } catch {\n return new Set()\n }\n}\n\nfunction saveSent(sent: Set<string>): void {\n try {\n sessionStorage.setItem(SENT_STORAGE_KEY, JSON.stringify([...sent].slice(-SENT_STORAGE_MAX)))\n } catch {\n return\n }\n}\n\nexport function installSkeletonCapture(opts: SkeletonCaptureOptions): SkeletonCapture {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return { onNavigate: () => undefined, teardown: () => undefined }\n }\n const delay = opts.delayMs ?? SKELETON_DELAY_MS\n const sent = loadSent()\n let pending: ReturnType<typeof setTimeout> | null = null\n\n const capture = (path: string): void => {\n pending = null\n if (location.pathname !== path) return\n try {\n const viewport: SkeletonViewport = {\n width: window.innerWidth,\n height: Math.max(document.documentElement.scrollHeight, window.innerHeight),\n scrollY: window.scrollY,\n }\n const skeleton = collectSkeleton(document, path, viewport)\n const key = `${path}:${skeleton.hash}`\n if (sent.has(key)) return\n sent.add(key)\n saveSent(sent)\n opts.onSkeleton(skeleton)\n } catch {\n return\n }\n }\n\n return {\n onNavigate: (path: string) => {\n if (pending) clearTimeout(pending)\n pending = setTimeout(() => capture(path), delay)\n },\n teardown: () => {\n if (pending) clearTimeout(pending)\n pending = null\n },\n }\n}\n", "/**\n * Contexto de ambiente do browser \u00B7 @holdyapp/sdk/web.\n *\n * Vai em `context` de todo evento, nunca em `properties`: properties \u00E9 o\n * vocabul\u00E1rio do produto do cliente (`workflow_key`, `plan`), context \u00E9 o que o\n * SDK observou sozinho. A Data layer persiste os dois (facts.context, 00247) e\n * a leitura de dimens\u00E3o consulta os dois.\n *\n * Tr\u00EAs decis\u00F5es que definem se esse dado \u00E9 \u00FAtil ou lixo:\n * \u00B7 `url` sai sem query e sem hash. Href cru tem uma varia\u00E7\u00E3o por sess\u00E3o, e\n * dimens\u00E3o com cardinalidade quase-\u00FAnica \u00E9 descartada na leitura \u2014 a\n * p\u00E1gina vira ru\u00EDdo exatamente por excesso de precis\u00E3o.\n * \u00B7 utm \u00E9 capturado na primeira p\u00E1gina e carregado pelo resto da sess\u00E3o.\n * Atribui\u00E7\u00E3o que s\u00F3 existe no primeiro evento n\u00E3o responde nada.\n * \u00B7 referrer s\u00F3 quando \u00E9 externo. Navega\u00E7\u00E3o interna preenchendo \"Origem do\n * tr\u00E1fego\" com o pr\u00F3prio dom\u00EDnio esconde a origem real.\n *\n * Tudo aqui \u00E9 best-effort: browser em modo privativo, SSR e webview sem\n * storage precisam funcionar. Nenhuma fun\u00E7\u00E3o lan\u00E7a.\n */\n\nexport type WebContext = Record<string, string>\n\nconst UTM_KEYS = [\n 'utm_source',\n 'utm_medium',\n 'utm_campaign',\n 'utm_term',\n 'utm_content',\n] as const\n\nconst SESSION_STORAGE_KEY = 'holdy_session'\nconst ATTRIBUTION_STORAGE_KEY = 'holdy_attribution'\n\n/* \u2500\u2500 URL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/** `https://app.x.com/a/b?q=1#z` \u2192 `https://app.x.com/a/b`. */\nexport function stripUrl(href: string): string | null {\n try {\n const url = new URL(href)\n return `${url.origin}${url.pathname}`\n } catch {\n return null\n }\n}\n\n/** Par\u00E2metros de campanha presentes na URL, j\u00E1 em lowercase. */\nexport function parseUtm(href: string): WebContext {\n const out: WebContext = {}\n try {\n const params = new URL(href).searchParams\n for (const key of UTM_KEYS) {\n const value = params.get(key)?.trim()\n if (value) out[key] = value.toLowerCase().slice(0, 120)\n }\n } catch {\n // href inv\u00E1lido \u2014 sem utm, sem drama.\n }\n return out\n}\n\n/* \u2500\u2500 User agent \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\ninterface UaParts {\n browser?: string\n os?: string\n device?: string\n}\n\n/**\n * Fatia m\u00EDnima do UA: navegador, sistema e classe de dispositivo.\n *\n * N\u00E3o \u00E9 biblioteca de UA parsing e n\u00E3o deve virar uma \u2014 o valor est\u00E1 em\n * separar mobile de desktop e Safari de Chrome, n\u00E3o em cravar a vers\u00E3o.\n */\nexport function parseUserAgent(ua: string): UaParts {\n if (!ua) return {}\n const s = ua.toLowerCase()\n\n const browser = s.includes('edg/')\n ? 'Edge'\n : s.includes('opr/') || s.includes('opera')\n ? 'Opera'\n : s.includes('samsungbrowser')\n ? 'Samsung Internet'\n : s.includes('firefox') || s.includes('fxios')\n ? 'Firefox'\n : s.includes('chrome') || s.includes('crios')\n ? 'Chrome'\n : s.includes('safari')\n ? 'Safari'\n : undefined\n\n const os = s.includes('iphone') || s.includes('ipad') || s.includes('ipod')\n ? 'iOS'\n : s.includes('android')\n ? 'Android'\n : s.includes('windows')\n ? 'Windows'\n : s.includes('mac os') || s.includes('macintosh')\n ? 'macOS'\n : s.includes('cros')\n ? 'ChromeOS'\n : s.includes('linux')\n ? 'Linux'\n : undefined\n\n // iPad moderno se declara macOS; a pista que sobra \u00E9 o suporte a toque, que\n // o parser puro n\u00E3o v\u00EA. Tablet aqui cobre o caso declarado no UA.\n const device = s.includes('ipad') || (s.includes('android') && !s.includes('mobile'))\n ? 'tablet'\n : s.includes('mobi') || s.includes('iphone') || s.includes('ipod')\n ? 'mobile'\n : 'desktop'\n\n return {\n ...(browser ? { browser } : {}),\n ...(os ? { os } : {}),\n device,\n }\n}\n\n/* \u2500\u2500 Storage \u00B7 nunca lan\u00E7a \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction readStorage(storage: 'session' | 'local', key: string): string | null {\n try {\n const s = storage === 'session' ? sessionStorage : localStorage\n return s.getItem(key)\n } catch {\n return null\n }\n}\n\nfunction writeStorage(storage: 'session' | 'local', key: string, value: string): void {\n try {\n const s = storage === 'session' ? sessionStorage : localStorage\n s.setItem(key, value)\n } catch {\n // Modo privativo / storage bloqueado \u2014 o contexto degrada, o evento segue.\n }\n}\n\nfunction randomId(): string {\n try {\n return crypto.randomUUID()\n } catch {\n return `hol-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`\n }\n}\n\n/** ID da sess\u00E3o de browser \u00B7 vive enquanto a aba viver. */\nexport function resolveSessionId(): string {\n const existing = readStorage('session', SESSION_STORAGE_KEY)\n if (existing) return existing\n const fresh = randomId()\n writeStorage('session', SESSION_STORAGE_KEY, fresh)\n return fresh\n}\n\n/**\n * Atribui\u00E7\u00E3o da sess\u00E3o: utm da primeira p\u00E1gina + referrer externo de entrada.\n * Gravada uma vez e repetida em todo evento da sess\u00E3o.\n */\nexport function resolveAttribution(href: string, referrer: string, currentHost: string): WebContext {\n const stored = readStorage('session', ATTRIBUTION_STORAGE_KEY)\n if (stored) {\n try {\n return JSON.parse(stored) as WebContext\n } catch {\n // Valor corrompido \u2014 recalcula por cima.\n }\n }\n\n const attribution: WebContext = { ...parseUtm(href) }\n\n const referrerHost = hostOf(referrer)\n // Referrer interno n\u00E3o \u00E9 origem de tr\u00E1fego, \u00E9 navega\u00E7\u00E3o.\n if (referrerHost && referrerHost !== currentHost) {\n const clean = stripUrl(referrer)\n if (clean) attribution.referrer = clean\n attribution.referrer_host = referrerHost\n }\n\n writeStorage('session', ATTRIBUTION_STORAGE_KEY, JSON.stringify(attribution))\n return attribution\n}\n\nfunction hostOf(href: string): string | null {\n try {\n return new URL(href).hostname.toLowerCase() || null\n } catch {\n return null\n }\n}\n\n/* \u2500\u2500 Montagem \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/**\n * Contexto completo do evento atual. Fora do browser devolve `{}` \u2014 o SDK\n * server tem o pr\u00F3prio caminho e n\u00E3o deve inventar ambiente.\n */\nexport function buildWebContext(): WebContext {\n if (typeof window === 'undefined' || typeof location === 'undefined') return {}\n\n const href = location.href\n const referrer = typeof document !== 'undefined' ? document.referrer : ''\n const host = location.hostname.toLowerCase()\n\n const ua = typeof navigator !== 'undefined' ? navigator.userAgent : ''\n const { browser, os, device } = parseUserAgent(ua)\n\n const url = stripUrl(href)\n\n return {\n ...(url ? { url } : {}),\n path: location.pathname || '/',\n host,\n ...(browser ? { browser } : {}),\n ...(os ? { os } : {}),\n ...(device ? { device } : {}),\n ...(typeof navigator !== 'undefined' && navigator.language\n ? { locale: navigator.language }\n : {}),\n session_id: resolveSessionId(),\n ...resolveAttribution(href, referrer, host),\n }\n}\n", "export type ChangeArm = 'change' | 'holdout'\n\nfunction fnv1a(input: string): number {\n let hash = 0x811c9dc5\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i)\n hash = Math.imul(hash, 0x01000193) >>> 0\n }\n return hash >>> 0\n}\n\nexport function changeBucket(changeId: string, accountKey: string): number {\n return fnv1a(`${changeId}:${accountKey}`) % 100\n}\n\nexport function changeArm(changeId: string, accountKey: string, holdoutPct: number): ChangeArm {\n return changeBucket(changeId, accountKey) < holdoutPct ? 'holdout' : 'change'\n}\n\nexport function matchesPathTemplate(template: string, path: string): boolean {\n const t = template.split(/[?#]/)[0].split('/').filter(Boolean)\n const p = path.split(/[?#]/)[0].split('/').filter(Boolean)\n if (t.length !== p.length) return false\n return t.every((segment, i) => segment.startsWith(':') || segment === p[i])\n}\n", "import { changeArm, matchesPathTemplate, type ChangeArm } from './arm'\n\nexport type ChangeAnchor =\n | { kind: 'selector'; value: string }\n | { kind: 'text'; value: string }\n | { kind: 'page' }\n\nexport interface ProductChange {\n id: string\n kind: 'copy' | 'guidance'\n path: string\n anchor: ChangeAnchor\n expected_text: string | null\n content: { text: string }\n holdout_pct: number\n}\n\nexport interface ProductChangesOptions {\n baseUrl: string\n apiKey: string\n getAccountKey: () => string | null\n track: (name: string, properties: Record<string, unknown>) => void\n debug?: boolean\n}\n\nexport interface ProductChangesHandle {\n onNavigate(): void\n refresh(): Promise<void>\n teardown(): void\n}\n\nconst REFRESH_MS = 5 * 60 * 1000\nconst NAV_REFRESH_MS = 60 * 1000\nconst SCAN_DEBOUNCE_MS = 250\nconst SEEN_KEY = 'holdy_changes_seen'\nconst DISMISSED_KEY = 'holdy_changes_dismissed'\nconst TIP_GAP_PX = 8\n\nconst TIP_CSS = `:host{all:initial}\n.tip{position:fixed;box-sizing:border-box;max-width:280px;padding:10px 12px;border-radius:8px;background:#111;color:#fff;font:13px/1.45 system-ui,-apple-system,sans-serif;box-shadow:0 8px 24px rgba(0,0,0,.18);pointer-events:auto;display:flex;gap:10px;align-items:flex-start}\n.tip p{margin:0;flex:1}\n.tip button{all:unset;cursor:pointer;opacity:.7;font-size:15px;line-height:1}\n.tip button:hover,.tip button:focus-visible{opacity:1}\n@media (prefers-color-scheme:dark){.tip{background:#fff;color:#111}}`\n\nexport function normalizeText(text: string): string {\n return text.replace(/\\s+/g, ' ').trim()\n}\n\nexport function parseChanges(body: unknown): ProductChange[] {\n const list = (body as { changes?: unknown } | null)?.changes\n return Array.isArray(list) ? list.filter(isChange) : []\n}\n\nfunction isAnchor(value: unknown): value is ChangeAnchor {\n const a = value as { kind?: unknown; value?: unknown } | null\n if (a?.kind === 'page') return true\n return (a?.kind === 'selector' || a?.kind === 'text') && typeof a.value === 'string' && a.value.length > 0\n}\n\nfunction isChange(value: unknown): value is ProductChange {\n const c = value as ProductChange | null\n return (\n typeof c?.id === 'string' &&\n (c.kind === 'copy' || c.kind === 'guidance') &&\n typeof c.path === 'string' &&\n isAnchor(c.anchor) &&\n typeof c.content?.text === 'string' &&\n typeof c.holdout_pct === 'number'\n )\n}\n\nexport function changesForPage(\n changes: readonly ProductChange[],\n path: string,\n accountKey: string | null,\n): Array<{ change: ProductChange; arm: ChangeArm }> {\n if (!accountKey) return []\n return changes\n .filter((c) => matchesPathTemplate(c.path, path))\n .map((change) => ({ change, arm: changeArm(change.id, accountKey, change.holdout_pct) }))\n}\n\nfunction storage(kind: 'local' | 'session'): Storage | undefined {\n try {\n return kind === 'local' ? window.localStorage : window.sessionStorage\n } catch {\n return undefined\n }\n}\n\nfunction readSet(store: Storage | undefined, key: string): Set<string> {\n try {\n return new Set(JSON.parse(store?.getItem(key) ?? '[]') as string[])\n } catch {\n return new Set()\n }\n}\n\nfunction addToSet(store: Storage | undefined, key: string, value: string): void {\n try {\n const set = readSet(store, key)\n set.add(value)\n store?.setItem(key, JSON.stringify([...set].slice(-200)))\n } catch {\n return\n }\n}\n\nfunction query(selector: string): Element | null {\n try {\n return document.querySelector(selector)\n } catch {\n return null\n }\n}\n\nconst TEXT_ANCHOR_TAGS = 'button,a,[role=\"button\"],label,summary,h1,h2,h3,h4,li,td,th,p,span,strong'\nconst TEXT_ANCHOR_SCAN_LIMIT = 3000\n\nexport function findByText(value: string): Element | null {\n const wanted = normalizeText(value)\n let best: Element | null = null\n let bestLength = Number.POSITIVE_INFINITY\n const nodes = document.querySelectorAll(TEXT_ANCHOR_TAGS)\n const total = Math.min(nodes.length, TEXT_ANCHOR_SCAN_LIMIT)\n for (let i = 0; i < total; i += 1) {\n const el = nodes[i]\n const raw = el.textContent ?? ''\n if (raw.length >= bestLength || normalizeText(raw) !== wanted) continue\n best = el\n bestLength = raw.length\n }\n return best\n}\n\nfunction findAnchor(anchor: ChangeAnchor): Element | null {\n if (anchor.kind === 'page') return null\n return anchor.kind === 'selector' ? query(anchor.value) : findByText(anchor.value)\n}\n\nfunction findTextNode(el: Element, match: (text: string) => boolean): Text | null {\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT)\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n if (match(normalizeText(node.textContent ?? ''))) return node as Text\n }\n return null\n}\n\ninterface AppliedCopy {\n node: Text\n original: string\n next: string\n}\n\nexport function installProductChanges(opts: ProductChangesOptions): ProductChangesHandle {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return { onNavigate: () => undefined, refresh: async () => undefined, teardown: () => undefined }\n }\n\n let changes: ProductChange[] = []\n let lastFetch = 0\n let timer: ReturnType<typeof setTimeout> | null = null\n let root: ShadowRoot | null = null\n let host: HTMLElement | null = null\n const copies = new Map<string, AppliedCopy>()\n const tips = new Map<string, () => void>()\n\n const log = (message: string): void => {\n if (opts.debug) console.warn(`[holdy] ${message}`)\n }\n\n const expose = (change: ProductChange, arm: ChangeArm): void => {\n const key = `${change.id}:${arm}`\n const session = storage('session')\n if (readSet(session, SEEN_KEY).has(key)) return\n addToSet(session, SEEN_KEY, key)\n opts.track('$change_exposure', { change_id: change.id, arm, kind: change.kind })\n }\n\n const eligibleCopyNode = (el: Element, change: ProductChange): Text | null => {\n const expected = change.expected_text ? normalizeText(change.expected_text) : null\n const next = normalizeText(change.content.text)\n return findTextNode(el, (text) => text.length > 0 && (text === next || expected === null || text === expected))\n }\n\n const applyCopy = (el: Element, change: ProductChange): boolean => {\n const next = normalizeText(change.content.text)\n const current = copies.get(change.id)\n if (current && current.node.isConnected && normalizeText(current.node.textContent ?? '') === next) return true\n const node = eligibleCopyNode(el, change)\n if (!node) return false\n const text = node.textContent ?? ''\n if (normalizeText(text) !== next) {\n copies.set(change.id, { node, original: text, next: change.content.text })\n node.textContent = text.replace(text.trim(), change.content.text)\n }\n return true\n }\n\n const restoreCopy = (id: string): void => {\n const applied = copies.get(id)\n if (!applied) return\n if (applied.node.isConnected && normalizeText(applied.node.textContent ?? '') === normalizeText(applied.next)) {\n applied.node.textContent = applied.original\n }\n copies.delete(id)\n }\n\n const ensureRoot = (): ShadowRoot | null => {\n if (root) return root\n if (!document.body) return null\n host = document.createElement('holdy-changes')\n host.setAttribute('data-holdy-root', '1')\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none'\n root = host.attachShadow({ mode: 'closed' })\n const style = document.createElement('style')\n style.textContent = TIP_CSS\n root.appendChild(style)\n document.body.appendChild(host)\n return root\n }\n\n const showTip = (anchor: Element | null, change: ProductChange): boolean => {\n if (tips.has(change.id)) return true\n if (readSet(storage('local'), DISMISSED_KEY).has(change.id)) return true\n const shadow = ensureRoot()\n if (!shadow) return false\n\n const card = document.createElement('div')\n card.className = 'tip'\n card.setAttribute('role', 'tooltip')\n const text = document.createElement('p')\n text.textContent = change.content.text\n const close = document.createElement('button')\n close.type = 'button'\n close.setAttribute('aria-label', 'Fechar')\n close.textContent = '\u00D7'\n card.append(text, close)\n card.style.top = '-9999px'\n card.style.left = '-9999px'\n shadow.appendChild(card)\n\n const remove = (): void => {\n card.remove()\n window.removeEventListener('scroll', position, true)\n window.removeEventListener('resize', position)\n tips.delete(change.id)\n }\n\n function position(): void {\n if (!anchor) {\n const corner = card.getBoundingClientRect()\n card.style.top = `${Math.max(8, window.innerHeight - corner.height - 16)}px`\n card.style.left = `${Math.max(8, window.innerWidth - corner.width - 16)}px`\n return\n }\n if (!anchor.isConnected) {\n remove()\n return\n }\n const a = anchor.getBoundingClientRect()\n const c = card.getBoundingClientRect()\n let top = a.bottom + TIP_GAP_PX\n if (top + c.height > window.innerHeight - 8) top = a.top - c.height - TIP_GAP_PX\n const left = Math.min(Math.max(8, a.left + a.width / 2 - c.width / 2), window.innerWidth - c.width - 8)\n card.style.top = `${Math.max(8, top)}px`\n card.style.left = `${Math.max(8, left)}px`\n }\n\n close.addEventListener('click', () => {\n addToSet(storage('local'), DISMISSED_KEY, change.id)\n opts.track('$change_dismissed', { change_id: change.id, kind: change.kind })\n remove()\n })\n tips.set(change.id, remove)\n requestAnimationFrame(position)\n window.addEventListener('scroll', position, true)\n window.addEventListener('resize', position)\n return true\n }\n\n const scan = (): void => {\n timer = null\n const active = changesForPage(changes, location.pathname, opts.getAccountKey())\n const activeIds = new Set(active.map((a) => a.change.id))\n for (const id of [...copies.keys()]) if (!activeIds.has(id)) restoreCopy(id)\n for (const [id, remove] of [...tips]) if (!activeIds.has(id)) remove()\n\n for (const { change, arm } of active) {\n const el = findAnchor(change.anchor)\n if (!el && change.anchor.kind !== 'page') continue\n if (change.kind === 'copy') {\n if (!el) continue\n const shown = arm === 'change' ? applyCopy(el, change) : eligibleCopyNode(el, change) !== null\n if (shown) expose(change, arm)\n } else if (arm === 'holdout' || showTip(el, change)) {\n expose(change, arm)\n }\n }\n }\n\n const schedule = (): void => {\n if (timer === null) timer = setTimeout(scan, SCAN_DEBOUNCE_MS)\n }\n\n const refresh = async (): Promise<void> => {\n lastFetch = Date.now()\n try {\n const res = await fetch(`${opts.baseUrl}/runtime/changes`, {\n headers: { Authorization: `Bearer ${opts.apiKey}` },\n })\n if (!res.ok) {\n log(`changes ${res.status}`)\n return\n }\n changes = parseChanges(await res.json())\n schedule()\n } catch (err) {\n log(`changes network error: ${(err as Error).message}`)\n }\n }\n\n const observer =\n typeof MutationObserver !== 'undefined'\n ? new MutationObserver(() => {\n if (changes.length > 0 || copies.size > 0 || tips.size > 0) schedule()\n })\n : null\n const observe = (): void => {\n if (document.body) observer?.observe(document.body, { childList: true, subtree: true, characterData: true })\n }\n if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', observe, { once: true })\n else observe()\n\n const interval = setInterval(() => void refresh(), REFRESH_MS)\n void refresh()\n\n return {\n onNavigate: () => {\n if (Date.now() - lastFetch > NAV_REFRESH_MS) void refresh()\n schedule()\n },\n refresh,\n teardown: () => {\n clearInterval(interval)\n if (timer !== null) clearTimeout(timer)\n observer?.disconnect()\n for (const id of [...copies.keys()]) restoreCopy(id)\n for (const remove of [...tips.values()]) remove()\n host?.remove()\n host = null\n root = null\n changes = []\n },\n }\n}\n", "/**\n * @holdyapp/sdk/web \u00B7 browser (source: sdk_web).\n *\n * anonymous_id gerado e persistido em localStorage (holdy_anon_id) \u2014 enviado em\n * todo event at\u00E9 identify() promover pra user_id (identity graph faz o merge\n * downstream, nunca o SDK). Flush no pagehide via fetch keepalive.\n *\n * Todo evento carrega o contexto de ambiente (url, path, referrer externo,\n * utm da sess\u00E3o, browser, os, device, locale, session_id) em `context` \u2014\n * separado das properties do produto. Pageview \u00E9 autom\u00E1tico por default:\n * carregamento inicial e cada mudan\u00E7a de rota, inclusive em SPA.\n */\n\nimport { HoldyCore } from './core'\nimport { installAutoCapture, type NavigationKind } from './auto-capture'\nimport { installFrictionCapture, type FrictionCapture, type FrictionCaptureOptions } from './friction'\nimport { installSkeletonCapture, type SkeletonCapture } from './skeleton'\nimport { buildWebContext } from './web-context'\nimport { installProductChanges, type ProductChangesHandle } from './changes'\nimport type { HoldyOptions, Properties } from './types'\n\nconst ANON_STORAGE_KEY = 'holdy_anon_id'\n\nexport interface HoldyWebOptions extends HoldyOptions {\n /**\n * Emitir `$pageview` sozinho no load e a cada mudan\u00E7a de rota \u00B7 default true.\n * Desligue s\u00F3 se o produto j\u00E1 chama `page()` na m\u00E3o em cada tela.\n */\n autoCapture?: boolean\n /**\n * Capturar fric\u00E7\u00E3o sozinho \u00B7 default true. Emite `$dead_click`, `$rage_click`,\n * `$form_abandon`, `$js_error`, `$slow_request`, `$nav_loop` e `$http_error`\n * (requisi\u00E7\u00E3o com status \u2265 400 ou sem resposta, e a pr\u00F3pria p\u00E1gina que abre\n * com erro) \u2014 eventos determin\u00EDsticos, sem DOM nem replay. Objeto ajusta os\n * limiares; a URL da Holdy nunca conta como erro.\n */\n friction?: boolean | Omit<FrictionCaptureOptions, 'onFriction'>\n /**\n * Aplicar as mudan\u00E7as de texto e dica que a org p\u00F4s no ar na Holdy \u00B7 default\n * true. Parte das contas fica de fora por sorteio pra medir; sem conta\n * identificada (`group()` ou `accountKey`) nada \u00E9 aplicado.\n */\n productChanges?: boolean\n /**\n * Mandar o esqueleto da p\u00E1gina \u00B7 default true. Uma vez por (rota, estrutura)\n * por aba: `$page_skeleton` com os elementos interativos (tag, role,\n * data-testid, name, aria-label, tipo, posi\u00E7\u00E3o relativa). Sem texto livre,\n * sem valor de input, sem pixel.\n */\n skeleton?: boolean\n}\n\nexport class HoldyWeb extends HoldyCore {\n private teardownAutoCapture: (() => void) | null = null\n private friction: FrictionCapture | null = null\n private changes: ProductChangesHandle | null = null\n private skeleton: SkeletonCapture | null = null\n\n constructor(opts: HoldyWebOptions) {\n super('sdk_web', opts)\n this.anonymousId = resolveAnonymousId()\n\n if (typeof window !== 'undefined') {\n window.addEventListener('pagehide', () => void this.flush())\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') void this.flush()\n })\n }\n\n if (opts.friction !== false) {\n const frictionOpts = typeof opts.friction === 'object' ? opts.friction : {}\n this.friction = installFrictionCapture({\n ...frictionOpts,\n ignoreUrls: [...(frictionOpts.ignoreUrls ?? []), this.baseUrl],\n onFriction: (signal) => this.track(`$${signal.kind}`, signal.properties),\n })\n }\n\n if (opts.skeleton !== false) {\n this.skeleton = installSkeletonCapture({\n onSkeleton: (skeleton) => this.track('$page_skeleton', { ...skeleton }),\n })\n }\n\n if (opts.autoCapture !== false) {\n this.teardownAutoCapture = installAutoCapture({\n onNavigate: (kind: NavigationKind) => {\n this.page(undefined, { navigation: kind })\n const path = typeof location !== 'undefined' ? location.pathname : '/'\n this.friction?.onNavigate(path)\n this.changes?.onNavigate()\n this.skeleton?.onNavigate(path)\n },\n })\n }\n\n if (opts.productChanges !== false && typeof window !== 'undefined') {\n this.changes = installProductChanges({\n baseUrl: this.baseUrl,\n apiKey: this.apiKey,\n getAccountKey: () => this.accountKey,\n track: (name, properties) => this.track(name, properties),\n debug: opts.debug,\n })\n }\n }\n\n /**\n * Pageview. O `$` marca evento emitido pelo SDK, n\u00E3o pelo produto (mesma\n * conven\u00E7\u00E3o de `$identify`/`$group`); a canonicaliza\u00E7\u00E3o downstream remove o\n * sigilo, ent\u00E3o `$pageview` e `pageview` s\u00E3o o mesmo evento na leitura.\n * url/path/referrer/utm j\u00E1 v\u00EAm no context de todo evento \u2014 aqui s\u00F3 entra o\n * que \u00E9 da p\u00E1gina como conte\u00FAdo (nome e t\u00EDtulo).\n */\n page(name?: string, properties?: Properties): void {\n this.track('$pageview', {\n ...(properties ?? {}),\n ...(name ? { page_name: name } : {}),\n ...(typeof document !== 'undefined' && document.title ? { title: document.title } : {}),\n })\n }\n\n override group(accountKey: string, traits?: Properties): void {\n super.group(accountKey, traits)\n this.changes?.onNavigate()\n }\n\n reset(): void {\n this.userId = null\n this.accountKey = null\n try {\n localStorage.removeItem(ANON_STORAGE_KEY)\n } catch {\n // storage indispon\u00EDvel (SSR/privacy mode) \u2014 ok\n }\n this.anonymousId = resolveAnonymousId()\n this.changes?.onNavigate()\n }\n\n /** Flush final + desinstala o auto-capture (devolve `history` ao original). */\n override async shutdown(): Promise<void> {\n this.teardownAutoCapture?.()\n this.teardownAutoCapture = null\n this.friction?.teardown()\n this.friction = null\n this.changes?.teardown()\n this.changes = null\n this.skeleton?.teardown()\n this.skeleton = null\n await super.shutdown()\n }\n\n protected override environmentContext(): Properties {\n return buildWebContext()\n }\n}\n\nfunction resolveAnonymousId(): string {\n try {\n const existing = localStorage.getItem(ANON_STORAGE_KEY)\n if (existing) return existing\n const fresh = crypto.randomUUID()\n localStorage.setItem(ANON_STORAGE_KEY, fresh)\n return fresh\n } catch {\n return crypto.randomUUID()\n }\n}\n\nlet singleton: HoldyWeb | null = null\n\n/** Init idempotente \u2014 segunda chamada retorna a inst\u00E2ncia existente. */\nexport function initHoldy(opts: HoldyWebOptions): HoldyWeb {\n if (!singleton) {\n singleton = new HoldyWeb(opts)\n // Inst\u00E2ncia no window: track() inserido pelo `--instrument` do CLI n\u00E3o\n // precisa importar nada nem saber onde o init mora. Mesma superf\u00EDcie do\n // loader por script tag, ent\u00E3o o snippet \u00E9 um s\u00F3 nos dois caminhos.\n if (typeof window !== 'undefined') {\n const w = window as unknown as { Holdy?: HoldyWeb }\n if (!w.Holdy) w.Holdy = singleton\n }\n }\n return singleton\n}\n\nexport type { HoldyOptions, Properties }\n"],
|
|
5
|
-
"mappings": ";AAcO,IAAM,mBAAmB;AAChC,IAAM,mBAAmB;AACzB,IAAM,4BAA4B;AAClC,IAAM,YAAY;AAClB,IAAM,aAAa;AACnB,IAAM,iBAAiB;AAIhB,IAAM,YAAN,MAAgB;AAAA,EACF;AAAA,EACA;AAAA,EACF;AAAA,EACA;AAAA,EACA;AAAA,EAET,QAA0B,CAAC;AAAA,EAC3B,QAA+C;AAAA,EAC/C,WAAiC;AAAA,EACjC,UAAU;AAAA,EACV,WAAW;AAAA,EACF,SAAS,oBAAI,IAAY;AAAA,EAEhC,SAAwB;AAAA,EACxB,cAA6B;AAAA,EAC7B,aAA4B;AAAA,EAEtC,YAAY,QAAkC,MAAoB;AAChE,SAAK,SAAS;AACd,SAAK,SAAS,KAAK;AACnB,SAAK,aAAa,KAAK,cAAc;AACrC,SAAK,WAAW,KAAK,WAAW,kBAAkB,QAAQ,OAAO,EAAE;AACnE,SAAK,UAAU,KAAK,IAAI,GAAG,KAAK,WAAW,gBAAgB;AAC3D,SAAK,QAAQ,KAAK,SAAS;AAE3B,UAAM,aAAa,KAAK,mBAAmB;AAC3C,QAAI,aAAa,GAAG;AAClB,WAAK,QAAQ,YAAY,MAAM,KAAK,KAAK,MAAM,GAAG,UAAU;AAE5D,UAAI,OAAQ,KAAK,MAAiC,UAAU,YAAY;AACtE;AAAC,QAAC,KAAK,MAA2C,MAAM;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,MAAc,YAAyB,WAAkC;AAC7E,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AAEvC,UAAM,SAAS,WAAW,UAAU,KAAK,UAAU;AACnD,UAAM,aAAa,WAAW,cAAc,KAAK,cAAc;AAC/D,UAAM,aAAa,WAAW,aAC1B,IAAI,KAAK,UAAU,UAAU,EAAE,YAAY,KAC3C,oBAAI,KAAK,GAAE,YAAY;AAK3B,UAAM,UAAsB;AAAA,MAC1B,GAAG,KAAK,mBAAmB;AAAA,MAC3B,GAAI,WAAW,WAAW,CAAC;AAAA,IAC7B;AACA,QAAI,WAAY,SAAQ,sBAAsB;AAE9C,UAAM,QAAwB;AAAA,MAC5B,OAAO;AAAA,MACP,aAAa;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,aAAa,WAAW;AAAA,MACxB,GAAI,SAAS,EAAE,SAAS,OAAO,IAAI,CAAC;AAAA,MACpC,GAAI,KAAK,cAAc,EAAE,cAAc,KAAK,YAAY,IAAI,CAAC;AAAA,MAC7D,YAAY,cAAc,CAAC;AAAA,MAC3B,GAAI,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,EAAE,QAAQ,IAAI,CAAC;AAAA,IACvD;AAEA,SAAK,MAAM,KAAK,KAAK;AACrB,SAAK,UAAU;AACf,QAAI,KAAK,MAAM,UAAU,KAAK,QAAS,MAAK,KAAK,MAAM;AAAA,EACzD;AAAA,EAEA,SAAS,QAAgB,QAA2B;AAClD,QAAI,CAAC,UAAU,OAAO,WAAW,SAAU;AAC3C,SAAK,SAAS;AACd,SAAK,MAAM,aAAa,UAAU,CAAC,CAAC;AAAA,EACtC;AAAA,EAEA,MAAM,YAAoB,QAA2B;AACnD,QAAI,CAAC,cAAc,OAAO,eAAe,SAAU;AACnD,SAAK,aAAa;AAClB,SAAK,MAAM,UAAU,UAAU,CAAC,CAAC;AAAA,EACnC;AAAA;AAAA,EAGA,MAAM,QAAuB;AAC3B,WAAO,KAAK,WAAW,KAAK;AAAA,EAC9B;AAAA;AAAA,EAGA,MAAM,WAA0B;AAC9B,QAAI,KAAK,OAAO;AACd,oBAAc,KAAK,KAAK;AACxB,WAAK,QAAQ;AAAA,IACf;AACA,UAAM,KAAK,WAAW,IAAI;AAAA,EAC5B;AAAA,EAEQ,WAAW,OAA+B;AAEhD,QAAI,KAAK,SAAU,QAAO,KAAK;AAC/B,QAAI,KAAK,MAAM,WAAW,EAAG,QAAO,QAAQ,QAAQ;AACpD,QAAI,CAAC,SAAS,KAAK,IAAI,IAAI,KAAK,QAAS,QAAO,QAAQ,QAAQ;AAEhE,SAAK,WAAW,KAAK,MAAM,EAAE,QAAQ,MAAM;AACzC,WAAK,WAAW;AAAA,IAClB,CAAC;AACD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,QAAuB;AACnC,WAAO,KAAK,MAAM,SAAS,GAAG;AAC5B,YAAM,QAAQ,KAAK,MAAM,OAAO,GAAG,UAAU;AAC7C,YAAM,UAAU,MAAM,KAAK,KAAK,KAAK;AACrC,UAAI,QAAQ,SAAS,SAAS;AAC5B,aAAK,MAAM,QAAQ,GAAG,KAAK;AAC3B,aAAK,UAAU;AACf,aAAK,cAAc,QAAQ,OAAO;AAClC;AAAA,MACF;AACA,WAAK,WAAW;AAChB,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA,EAEQ,cAAc,SAA8B;AAClD,SAAK,YAAY;AACjB,QAAI,YAAY,MAAM;AACpB,WAAK,UAAU,KAAK,IAAI,IAAI;AAC5B;AAAA,IACF;AACA,UAAM,UAAU,KAAK,IAAI,gBAAgB,MAAO,MAAM,KAAK,WAAW,EAAE;AACxE,SAAK,UAAU,KAAK,IAAI,IAAI,UAAU,KAAK,MAAM,KAAK,OAAO,IAAI,UAAU,GAAG;AAAA,EAChF;AAAA,EAEQ,YAAkB;AACxB,QAAI,KAAK,MAAM,SAAS,UAAW,MAAK,MAAM,OAAO,GAAG,KAAK,MAAM,SAAS,SAAS;AAAA,EACvF;AAAA,EAEA,MAAc,KAAK,QAAgD;AACjE,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,gBAAgB;AAAA,QACrD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,eAAe,UAAU,KAAK,MAAM;AAAA,UACpC,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU,EAAE,OAAO,CAAC;AAAA,QAC/B,GAAI,KAAK,WAAW,YAAY,EAAE,WAAW,KAAK,IAAI,CAAC;AAAA,MACzD,CAAC;AACD,UAAI,IAAI,GAAI,QAAO,EAAE,MAAM,OAAO;AAElC,UAAI,IAAI,WAAW,KAAK;AACtB,aAAK,IAAI,gDAA6C;AACtD,eAAO,EAAE,MAAM,SAAS,SAAS,aAAa,GAAG,EAAE;AAAA,MACrD;AACA,UAAI,IAAI,UAAU,KAAK;AACrB,aAAK,IAAI,eAAe,IAAI,MAAM,+BAA4B;AAC9D,eAAO,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,MACxC;AACA,UAAI,IAAI,WAAW,KAAK;AACtB,aAAK,SAAS,OAAO,8GAA6F;AAClH,eAAO,EAAE,MAAM,UAAU;AAAA,MAC3B;AACA,UAAI,IAAI,WAAW,KAAK;AACtB,aAAK,SAAS,OAAO,oFAA8E;AACnG,eAAO,EAAE,MAAM,UAAU;AAAA,MAC3B;AACA,WAAK,IAAI,iBAAiB,IAAI,MAAM,qBAAkB;AACtD,aAAO,EAAE,MAAM,UAAU;AAAA,IAC3B,SAAS,KAAK;AACZ,WAAK,IAAI,uBAAwB,IAAc,OAAO,+BAA4B;AAClF,aAAO,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,IACxC;AAAA,EACF;AAAA,EAEQ,IAAI,KAAmB;AAC7B,QAAI,KAAK,MAAO,SAAQ,KAAK,WAAW,GAAG,EAAE;AAAA,EAC/C;AAAA,EAEQ,SAAS,KAAa,KAAmB;AAC/C,QAAI,KAAK,OAAO,IAAI,GAAG,EAAG;AAC1B,SAAK,OAAO,IAAI,GAAG;AACnB,YAAQ,KAAK,WAAW,GAAG,EAAE;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOU,qBAAiC;AACzC,WAAO,CAAC;AAAA,EACV;AAAA;AAAA,EAGA,IAAI,UAAkB;AACpB,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;AAEA,SAAS,aAAa,KAA8B;AAClD,QAAM,MAAM,OAAO,IAAI,SAAS,QAAQ,aAAa,IAAI,QAAQ,IAAI,aAAa,IAAI;AACtF,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,UAAU,OAAO,GAAG;AAC1B,MAAI,CAAC,OAAO,SAAS,OAAO,KAAK,UAAU,EAAG,QAAO;AACrD,SAAO,KAAK,IAAI,gBAAgB,UAAU,GAAI;AAChD;AAEA,SAAS,aAAqB;AAC5B,QAAM,IAAK,WAA0D;AACrE,MAAI,OAAO,GAAG,eAAe,WAAY,QAAO,EAAE,WAAW;AAC7D,QAAM,OAAO,MAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE;AACzD,SAAO,GAAG,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC;AACvD;;;AC/NA,IAAM,iBAAiB;AAGvB,IAAM,oBAAoB;AAYnB,SAAS,mBAAmB,MAAsC;AACvE,MAAI,OAAO,WAAW,eAAe,OAAO,YAAY,aAAa;AACnE,WAAO,MAAM;AAAA,EACf;AAEA,QAAM,IAAI;AACV,MAAI,EAAE,cAAc,EAAG,QAAO,MAAM;AACpC,IAAE,cAAc,IAAI;AAEpB,QAAM,WAA8B,CAAC;AACrC,MAAI,WAAW,YAAY;AAC3B,MAAI,UAAgD;AAEpD,WAAS,KAAK,MAA4B;AACxC,QAAI;AACF,WAAK,WAAW,IAAI;AAAA,IACtB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,WAAS,oBAA0B;AACjC,QAAI,QAAS,cAAa,OAAO;AACjC,cAAU,WAAW,MAAM;AACzB,gBAAU;AACV,YAAM,OAAO,YAAY;AAGzB,UAAI,SAAS,SAAU;AACvB,iBAAW;AACX,WAAK,cAAc;AAAA,IACrB,GAAG,iBAAiB;AAAA,EACtB;AAEA,OAAK,cAAc;AAEnB,QAAM,eAAe,QAAQ;AAC7B,QAAM,kBAAkB,QAAQ;AAEhC,UAAQ,YAAY,SAAS,eAAe,MAAwC;AAClF,UAAM,SAAS,aAAa,MAAM,MAAM,IAAI;AAC5C,sBAAkB;AAClB,WAAO;AAAA,EACT;AACA,UAAQ,eAAe,SAAS,kBAAkB,MAA2C;AAC3F,UAAM,SAAS,gBAAgB,MAAM,MAAM,IAAI;AAC/C,sBAAkB;AAClB,WAAO;AAAA,EACT;AACA,WAAS,KAAK,MAAM;AAClB,YAAQ,YAAY;AACpB,YAAQ,eAAe;AAAA,EACzB,CAAC;AAGD,QAAM,QAAQ,MAAY,kBAAkB;AAC5C,SAAO,iBAAiB,YAAY,KAAK;AACzC,WAAS,KAAK,MAAM,OAAO,oBAAoB,YAAY,KAAK,CAAC;AAEjE,QAAM,SAAS,MAAY,kBAAkB;AAC7C,SAAO,iBAAiB,cAAc,MAAM;AAC5C,WAAS,KAAK,MAAM,OAAO,oBAAoB,cAAc,MAAM,CAAC;AAEpE,SAAO,MAAM;AACX,QAAI,QAAS,cAAa,OAAO;AACjC,eAAW,WAAW,SAAU,SAAQ;AACxC,MAAE,cAAc,IAAI;AAAA,EACtB;AACF;AAGA,SAAS,cAAsB;AAC7B,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,SAAO,GAAG,SAAS,QAAQ,GAAG,SAAS,MAAM,GAAG,SAAS,IAAI;AAC/D;;;AClEA,IAAMA,kBAAiB;AACvB,IAAM,uBACJ;AACF,IAAM,mBAAmB,oBAAI,IAAI,CAAC,UAAU,KAAK,SAAS,UAAU,YAAY,SAAS,CAAC;AAC1F,IAAM,oBAAoB,oBAAI,IAAI,CAAC,SAAS,UAAU,UAAU,CAAC;AAE1D,IAAM,oBAAN,MAAwB;AAAA,EAG7B,YACmB,YAAY,GACZ,WAAW,KACX,WAAW,IAC5B;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EANK,SAAqD,CAAC;AAAA,EAQ9D,KAAK,GAAW,GAAW,GAAoB;AAC7C,SAAK,SAAS,KAAK,OAAO;AAAA,MACxB,CAAC,MAAM,IAAI,EAAE,KAAK,KAAK,YAAY,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,IAAI,CAAC,KAAK,KAAK;AAAA,IAC1E;AACA,SAAK,OAAO,KAAK,EAAE,GAAG,GAAG,EAAE,CAAC;AAC5B,QAAI,KAAK,OAAO,UAAU,KAAK,WAAW;AACxC,WAAK,SAAS,CAAC;AACf,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACF;AAEO,IAAM,kBAAN,MAAsB;AAAA,EAG3B,YAA6B,WAAW,KAAQ;AAAnB;AAAA,EAAoB;AAAA,EAFzC,SAA6C,CAAC;AAAA,EAItD,KAAK,MAAc,GAAgD;AACjE,SAAK,SAAS,CAAC,GAAG,KAAK,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE,KAAK,KAAK,QAAQ,EAAE,MAAM,EAAE;AAC5F,QAAI,KAAK,OAAO,SAAS,EAAG,QAAO;AACnC,UAAM,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AAClD,QAAI,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG;AACjC,WAAK,SAAS,CAAC;AACf,aAAO,EAAE,MAAM,GAAG,IAAI,EAAE;AAAA,IAC1B;AACA,WAAO;AAAA,EACT;AACF;AAWO,SAAS,mBAAmB,IAA4C;AAC7E,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,aAAa,GAAG,UAAU,oBAAoB,KAAK;AACzD,MAAI,WAAY,QAAO;AACvB,QAAM,MAAM,GAAG,QAAQ,YAAY;AACnC,MAAI,iBAAiB,IAAI,GAAG,EAAG,QAAO;AACtC,QAAM,OAAO,GAAG,aAAa,MAAM;AACnC,MAAI,SAAS,YAAY,SAAS,UAAU,SAAS,cAAc,SAAS,MAAO,QAAO;AAC1F,SAAO;AACT;AAEO,SAAS,kBAAkB,IAAiC;AACjE,QAAM,SAAS,mBAAmB,EAAE;AACpC,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,OAAO,aAAa,KAAM,QAAO;AACrC,MAAI,OAAO,aAAa,UAAU,MAAM,KAAM,QAAO;AACrD,MAAI,OAAO,aAAa,eAAe,MAAM,OAAQ,QAAO;AAC5D,QAAM,MAAM,OAAO,QAAQ,YAAY;AACvC,MAAI,QAAQ,KAAK;AACf,UAAM,OAAO,OAAO,aAAa,MAAM;AACvC,QAAI,CAAC,QAAQ,SAAS,OAAO,KAAK,WAAW,aAAa,EAAG,QAAO;AAAA,EACtE;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,IAAgD;AAC9E,QAAM,SAAS,mBAAmB,EAAE,KAAK;AACzC,MAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,QAAM,MAA8B,EAAE,SAAS,OAAO,QAAQ,YAAY,EAAE;AAC5E,MAAI,OAAO,GAAI,KAAI,aAAa,OAAO;AACvC,QAAM,OAAO,OAAO,aAAa,MAAM;AACvC,MAAI,KAAM,KAAI,eAAe;AAC7B,QAAM,QAAQ,OAAO,aAAa,YAAY,KAAK,OAAO,eAAe;AACzE,QAAM,OAAO,MAAM,QAAQ,QAAQ,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE;AAC1D,MAAI,KAAM,KAAI,eAAe;AAC7B,QAAM,OAAO,OAAO,aAAa,MAAM,KAAK,OAAO,aAAa,aAAa;AAC7E,MAAI,KAAM,KAAI,eAAe;AAC7B,SAAO;AACT;AAEO,SAAS,gBAAgB,OAAe,MAAuB;AACpE,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,OAAO,IAAI;AAC/B,WAAO,GAAG,IAAI,MAAM,GAAG,IAAI,QAAQ;AAAA,EACrC,QAAQ;AACN,WAAO,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EACzC;AACF;AAEO,SAAS,aAAa,QAAyB;AACpD,MAAI,kBAAkB,MAAO,QAAO,OAAO;AAC3C,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,MAAI;AACF,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B,QAAQ;AACN,WAAO,OAAO,MAAM;AAAA,EACtB;AACF;AAEO,SAAS,aAAa,KAAuB;AAClD,SAAO,OAAO,QAAQ,YAAY,QAAQ,QAAS,IAA2B,SAAS;AACzF;AAEO,SAAS,aAAa,KAAa,QAAoC;AAC5E,SAAO,OAAO,KAAK,CAAC,WAAW,OAAO,SAAS,KAAK,IAAI,WAAW,MAAM,CAAC;AAC5E;AAUO,SAAS,kBAAkB,MAAsB;AACtD,QAAM,SAAS,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AAC3D,MAAI,OAAO,UAAU,EAAG,QAAO,OAAO,KAAK,GAAG;AAC9C,SAAO,OAAO,MAAM,EAAE,EAAE,KAAK,GAAG;AAClC;AAcO,SAAS,oBAAoB,KAAa,SAAiB,eAAkC,CAAC,GAAY;AAC/G,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,KAAK,OAAO;AAC7B,WAAO,IAAI,IAAI,OAAO;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,OAAO,aAAa,WAAW,OAAO,aAAa,SAAU,QAAO;AACxE,MAAI,OAAO,SAAS,KAAK,KAAM,QAAO;AACtC,MAAI,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,WAAW,CAAC,EAAG,QAAO;AAC1E,QAAM,eAAe,kBAAkB,OAAO,QAAQ;AACtD,SAAO,aAAa,SAAS,KAAK,iBAAiB,kBAAkB,KAAK,QAAQ;AACpF;AAUO,SAAS,gBAAgB,SAA+D;AAC7F,MAAI,QAAQ,QAAS,QAAO;AAC5B,MAAI,CAAC,QAAQ,WAAW,QAAQ,WAAW,QAAQ,QAAQ,UAAU,KAAM,QAAO;AAClF,SAAO,QAAQ,cAAc,QAAQ,SAAS,iBAAiB;AACjE;AAEO,SAAS,eACd,MACe;AACf,MAAI;AACF,UAAM,QAAQ,MAAM,mBAAmB,YAAY,IAAI,CAAC;AACxD,UAAM,SAAS,OAAO;AACtB,WAAO,OAAO,WAAW,YAAY,SAAS,IAAI,SAAS;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOA,SAAS,QAAQ,MAA+B;AAC9C,SACE,KAAK,MACL,KAAK,aAAa,MAAM,KACxB,KAAK,aAAa,aAAa,KAC/B,gBAAgB,KAAK,aAAa,QAAQ,KAAK,IAAI,SAAS,IAAI,EAAE,QAAQ,SAAS,QAAQ,EAAE,KAC7F;AAEJ;AAEA,SAASC,eAAsB;AAC7B,SAAO,OAAO,aAAa,cAAc,MAAM,SAAS,YAAY;AACtE;AAEO,SAAS,uBAAuB,MAA+C;AACpF,QAAM,OAAwB,EAAE,YAAY,MAAM,QAAW,UAAU,MAAM,OAAU;AACvF,MAAI,OAAO,WAAW,eAAe,OAAO,aAAa,YAAa,QAAO;AAE7E,QAAM,IAAI;AACV,MAAI,EAAED,eAAc,EAAG,QAAO;AAC9B,IAAEA,eAAc,IAAI;AAEpB,QAAM,OAAO,CAAC,MAAoB,eAA8C;AAC9E,QAAI;AACF,WAAK,WAAW,EAAE,MAAM,YAAY,EAAE,MAAMC,aAAY,GAAG,GAAG,WAAW,EAAE,CAAC;AAAA,IAC9E,QAAQ;AACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAA8B,CAAC;AACrC,QAAM,OAAO,IAAI,kBAAkB,KAAK,YAAY,KAAK,cAAc,KAAK,YAAY;AACxF,QAAM,UAAU,IAAI,gBAAgB,KAAK,eAAe;AACxD,QAAM,SAAS,KAAK,iBAAiB;AACrC,QAAM,UAAU,oBAAI,IAAgC;AAEpD,QAAM,UAAU,CAAC,OAAyB;AACxC,UAAM,KAAK,GAAG,kBAAkB,UAAW,GAAG,SAAoC;AAClF,QAAI,kBAAkB,EAAE,EAAG,MAAK,cAAc,gBAAgB,EAAE,CAAC;AACjE,QAAI,KAAK,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,KAAK,IAAI,CAAC,GAAG;AACjE,WAAK,cAAc,gBAAgB,EAAE,CAAC;AAAA,IACxC;AAAA,EACF;AACA,WAAS,iBAAiB,SAAS,SAAS,IAAI;AAChD,WAAS,KAAK,MAAM,SAAS,oBAAoB,SAAS,SAAS,IAAI,CAAC;AAExE,QAAM,UAAU,CAAC,OAAyB;AACxC,SAAK,YAAY;AAAA,MACf,SAAS,OAAO,GAAG,WAAW,EAAE,EAAE,MAAM,GAAG,GAAG;AAAA,MAC9C,GAAI,GAAG,WAAW,EAAE,QAAQ,gBAAgB,GAAG,UAAU,SAAS,IAAI,EAAE,IAAI,CAAC;AAAA,MAC7E,GAAI,GAAG,SAAS,EAAE,MAAM,GAAG,OAAO,IAAI,CAAC;AAAA,IACzC,CAAC;AAAA,EACH;AACA,SAAO,iBAAiB,SAAS,OAAO;AACxC,WAAS,KAAK,MAAM,OAAO,oBAAoB,SAAS,OAAO,CAAC;AAEhE,QAAM,cAAc,CAAC,OAAoC;AACvD,SAAK,YAAY,EAAE,SAAS,aAAa,GAAG,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,qBAAqB,KAAK,CAAC;AAAA,EAChG;AACA,SAAO,iBAAiB,sBAAsB,WAAW;AACzD,WAAS,KAAK,MAAM,OAAO,oBAAoB,sBAAsB,WAAW,CAAC;AAEjF,QAAM,UAAU,KAAK,cAAc,CAAC,GAAG,IAAI,CAAC,QAAQ,gBAAgB,KAAK,SAAS,IAAI,CAAC;AACvF,QAAM,cAAc,KAAK,cAAc,CAAC,GAAG,IAAI,CAAC,MAAM;AACpD,QAAI;AACF,aAAO,IAAI,IAAI,GAAG,SAAS,IAAI,EAAE;AAAA,IACnC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,gBAAgB,CACpB,KACA,QACA,SACA,QACA,QAAiD,CAAC,MACzC;AACT,UAAM,SAAS,gBAAgB,KAAK,SAAS,IAAI;AACjD,QAAI,aAAa,QAAQ,MAAM,EAAG;AAClC,QAAI,CAAC,oBAAoB,QAAQ,SAAS,MAAM,UAAU,EAAG;AAC7D,UAAM,aAAa,YAAY,IAAI,IAAI;AACvC,UAAM,OAAO,gBAAgB,EAAE,QAAQ,YAAY,QAAQ,GAAG,MAAM,CAAC;AACrE,QAAI,CAAC,KAAM;AACX,SAAK,MAAM;AAAA,MACT,KAAK;AAAA,MACL;AAAA,MACA,aAAa,KAAK,MAAM,UAAU;AAAA,MAClC,GAAI,MAAM,SAAS,CAAC,IAAI,WAAW,OAAO,EAAE,OAAO,IAAI,EAAE,QAAQ,KAAK;AAAA,IACxE,CAAC;AAAA,EACH;AAEA,QAAM,gBAAgB,OAAO;AAC7B,MAAI,OAAO,kBAAkB,YAAY;AACvC,UAAM,UAA+B,OAAO,OAAO,SAAS;AAC1D,YAAM,UAAU,YAAY,IAAI;AAChC,YAAM,MACJ,OAAO,UAAU,WAAW,QAAQ,iBAAiB,MAAM,MAAM,OAAO,MAAM;AAChF,YAAM,UAAU,MAAM,WAAW,iBAAiB,UAAU,MAAM,SAAS,QAAQ,YAAY;AAC/F,UAAI;AACF,cAAM,MAAM,MAAM,cAAc,OAAO,IAAI;AAC3C,sBAAc,KAAK,QAAQ,SAAS,IAAI,QAAQ;AAAA,UAC9C,QAAQ,IAAI,SAAS,YAAY,IAAI,SAAS;AAAA,QAChD,CAAC;AACD,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,sBAAc,KAAK,QAAQ,SAAS,MAAM,EAAE,SAAS,aAAa,GAAG,EAAE,CAAC;AACxE,cAAM;AAAA,MACR;AAAA,IACF;AACA,WAAO,QAAQ;AACf,aAAS,KAAK,MAAM;AAClB,aAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,OAAO,mBAAmB,aAAa,eAAe,YAAY;AACnF,MAAI,UAAU;AACZ,UAAM,eAAe,SAAS;AAC9B,UAAM,eAAe,SAAS;AAC9B,UAAM,WAAW,oBAAI,QAAyD;AAC9E,aAAS,OAAO,SAAgC,QAAgB,QAAsB,MAAiB;AACrG,eAAS,IAAI,MAAM,EAAE,QAAQ,OAAO,MAAM,EAAE,YAAY,GAAG,KAAK,OAAO,GAAG,EAAE,CAAC;AAC7E,aAAQ,aAA8C,MAAM,MAAM,CAAC,QAAQ,KAAK,GAAG,IAAI,CAAC;AAAA,IAC1F;AACA,aAAS,OAAO,SAAgC,MAAiD;AAC/F,YAAM,UAAU,SAAS,IAAI,IAAI;AACjC,UAAI,SAAS;AACX,cAAM,UAAU,YAAY,IAAI;AAChC,YAAI,UAAU;AACd,aAAK,iBAAiB,SAAS,MAAM;AACnC,oBAAU;AAAA,QACZ,CAAC;AACD,aAAK,iBAAiB,WAAW,MAAM;AACrC,wBAAc,QAAQ,KAAK,QAAQ,QAAQ,SAAS,KAAK,WAAW,IAAI,OAAO,KAAK,QAAQ,EAAE,QAAQ,CAAC;AAAA,QACzG,CAAC;AAAA,MACH;AACA,aAAO,aAAa,KAAK,MAAM,IAAI;AAAA,IACrC;AACA,aAAS,KAAK,MAAM;AAClB,eAAS,OAAO;AAChB,eAAS,OAAO;AAAA,IAClB,CAAC;AAAA,EACH;AAEA,QAAM,aAAa,eAAe,OAAO,gBAAgB,cAAc,SAAY,WAAW;AAC9F,MAAI,eAAe,QAAQ,cAAc,KAAK;AAC5C,SAAK,cAAc,EAAE,UAAU,MAAM,QAAQ,YAAY,KAAK,gBAAgB,SAAS,IAAI,EAAE,CAAC;AAAA,EAChG;AAEA,QAAM,YAAY,CAAC,OAAyB;AAC1C,UAAM,KAAK,GAAG;AACd,QAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,GAAG,QAAQ,YAAY,CAAC,EAAG;AAC7D,UAAM,OAAQ,GAAwB;AACtC,QAAI,CAAC,KAAM;AACX,UAAM,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,GAAG,QAAQ,oBAAI,IAAY,EAAE;AACpF,UAAM,QAAS,GAAwB,QAAQ,GAAG,MAAM,GAAG,QAAQ,YAAY;AAC/E,UAAM,OAAO,IAAI,KAAK;AACtB,YAAQ,IAAI,MAAM,KAAK;AAAA,EACzB;AACA,WAAS,iBAAiB,WAAW,WAAW,IAAI;AACpD,WAAS,KAAK,MAAM,SAAS,oBAAoB,WAAW,WAAW,IAAI,CAAC;AAE5E,QAAM,WAAW,CAAC,OAAoB;AACpC,QAAI,GAAG,kBAAkB,gBAAiB,SAAQ,OAAO,GAAG,MAAM;AAAA,EACpE;AACA,WAAS,iBAAiB,UAAU,UAAU,IAAI;AAClD,WAAS,KAAK,MAAM,SAAS,oBAAoB,UAAU,UAAU,IAAI,CAAC;AAE1E,QAAM,gBAAgB,MAAY;AAChC,eAAW,SAAS,QAAQ,OAAO,GAAG;AACpC,WAAK,gBAAgB,EAAE,MAAM,MAAM,MAAM,gBAAgB,MAAM,OAAO,KAAK,CAAC;AAAA,IAC9E;AACA,YAAQ,MAAM;AAAA,EAChB;AACA,SAAO,iBAAiB,YAAY,aAAa;AACjD,WAAS,KAAK,MAAM,OAAO,oBAAoB,YAAY,aAAa,CAAC;AAEzE,SAAO;AAAA,IACL,YAAY,CAAC,SAAiB;AAC5B,oBAAc;AACd,YAAM,OAAO,QAAQ,KAAK,MAAM,KAAK,IAAI,CAAC;AAC1C,UAAI,KAAM,MAAK,YAAY,EAAE,MAAM,KAAK,MAAM,IAAI,KAAK,GAAG,CAAC;AAAA,IAC7D;AAAA,IACA,UAAU,MAAM;AACd,iBAAW,WAAW,SAAU,SAAQ;AACxC,cAAQ,MAAM;AACd,QAAED,eAAc,IAAI;AAAA,IACtB;AAAA,EACF;AACF;;;AClaO,IAAM,oBACX;AACK,IAAM,wBAAwB;AAC9B,IAAM,oBAAoB;AACjC,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AA0ClB,SAAS,MAAM,OAAuB;AAC3C,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAQ,MAAM,WAAW,CAAC;AAC1B,WAAO,KAAK,KAAK,MAAM,QAAU,MAAM;AAAA,EACzC;AACA,SAAO,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC1C;AAEA,SAAS,KAAK,IAAyB,MAAc,KAAiC;AACpF,QAAM,QAAQ,GAAG,aAAa,IAAI;AAClC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,MAAM,QAAQ,QAAQ,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG;AAC9D,SAAO,WAAW;AACpB;AAEA,SAAS,UAAU,IAAkC;AACnD,MAAI,CAAC,GAAG,sBAAuB,QAAO;AACtC,QAAM,OAAO,GAAG,sBAAsB;AACtC,SAAO,KAAK,QAAQ,KAAK,KAAK,SAAS;AACzC;AAEA,SAAS,YAAY,MAAoB,UAA8D;AACrG,QAAM,MAAM,CAAC,OAAe,SAAkB,OAAO,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAO,QAAQ,OAAQ,GAAG,CAAC,CAAC,IAAI;AACxH,SAAO,CAAC,IAAI,KAAK,GAAG,SAAS,KAAK,GAAG,IAAI,KAAK,IAAI,SAAS,SAAS,SAAS,MAAM,GAAG,IAAI,KAAK,OAAO,SAAS,KAAK,GAAG,IAAI,KAAK,QAAQ,SAAS,MAAM,CAAC;AAC1J;AAEO,SAAS,wBAAwB,IAAyB,UAAoD;AACnH,QAAM,MAAuB,EAAE,GAAG,GAAG,QAAQ,YAAY,EAAE;AAC3D,QAAM,OAAO,KAAK,IAAI,QAAQ,EAAE;AAChC,MAAI,KAAM,KAAI,IAAI;AAClB,QAAM,SAAS,KAAK,IAAI,eAAe,EAAE;AACzC,MAAI,OAAQ,KAAI,KAAK;AACrB,QAAM,OAAO,KAAK,IAAI,QAAQ,EAAE;AAChC,MAAI,KAAM,KAAI,IAAI;AAClB,QAAM,QAAQ,KAAK,IAAI,cAAc,EAAE;AACvC,MAAI,MAAO,KAAI,IAAI;AACnB,MAAI,IAAI,MAAM,WAAW,IAAI,MAAM,UAAU;AAC3C,UAAM,OAAO,KAAK,IAAI,QAAQ,EAAE;AAChC,QAAI,KAAM,KAAI,IAAI,KAAK,YAAY;AAAA,EACrC;AACA,MAAI,YAAY,GAAG,sBAAuB,KAAI,IAAI,YAAY,GAAG,sBAAsB,GAAG,QAAQ;AAClG,SAAO;AACT;AAEO,SAAS,gBAAgB,MAAwB,MAAc,UAAiD;AACrH,QAAM,QAAQ,KAAK,iBAAiB,iBAAiB;AACrD,QAAM,UAAiC,CAAC;AACxC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,KAAK,MAAM,CAAC;AAClB,QAAI,GAAG,QAAQ,YAAY,MAAM,YAAY,GAAG,aAAa,MAAM,KAAK,IAAI,YAAY,MAAM,SAAU;AACxG,QAAI,CAAC,UAAU,EAAE,EAAG;AACpB,YAAQ,KAAK,EAAE;AAAA,EACjB;AACA,QAAM,WAAW,QAAQ,MAAM,GAAG,qBAAqB,EAAE,IAAI,CAAC,OAAO,wBAAwB,IAAI,QAAQ,CAAC;AAC1G,QAAM,aAAa,SAAS,IAAI,CAAC,EAAE,GAAG,IAAI,GAAG,KAAK,MAAM,IAAI;AAC5D,SAAO,EAAE,MAAM,MAAM,MAAM,KAAK,UAAU,UAAU,CAAC,GAAG,OAAO,QAAQ,QAAQ,SAAS;AAC1F;AAYA,SAAS,WAAwB;AAC/B,MAAI;AACF,UAAM,MAAM,eAAe,QAAQ,gBAAgB;AACnD,UAAM,OAAO,MAAO,KAAK,MAAM,GAAG,IAAgB,CAAC;AACnD,WAAO,IAAI,IAAI,MAAM,QAAQ,IAAI,IAAI,KAAK,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IAAI,CAAC,CAAC;AAAA,EAClG,QAAQ;AACN,WAAO,oBAAI,IAAI;AAAA,EACjB;AACF;AAEA,SAAS,SAAS,MAAyB;AACzC,MAAI;AACF,mBAAe,QAAQ,kBAAkB,KAAK,UAAU,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAAA,EAC7F,QAAQ;AACN;AAAA,EACF;AACF;AAEO,SAAS,uBAAuB,MAA+C;AACpF,MAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AACpE,WAAO,EAAE,YAAY,MAAM,QAAW,UAAU,MAAM,OAAU;AAAA,EAClE;AACA,QAAM,QAAQ,KAAK,WAAW;AAC9B,QAAM,OAAO,SAAS;AACtB,MAAI,UAAgD;AAEpD,QAAM,UAAU,CAAC,SAAuB;AACtC,cAAU;AACV,QAAI,SAAS,aAAa,KAAM;AAChC,QAAI;AACF,YAAM,WAA6B;AAAA,QACjC,OAAO,OAAO;AAAA,QACd,QAAQ,KAAK,IAAI,SAAS,gBAAgB,cAAc,OAAO,WAAW;AAAA,QAC1E,SAAS,OAAO;AAAA,MAClB;AACA,YAAM,WAAW,gBAAgB,UAAU,MAAM,QAAQ;AACzD,YAAM,MAAM,GAAG,IAAI,IAAI,SAAS,IAAI;AACpC,UAAI,KAAK,IAAI,GAAG,EAAG;AACnB,WAAK,IAAI,GAAG;AACZ,eAAS,IAAI;AACb,WAAK,WAAW,QAAQ;AAAA,IAC1B,QAAQ;AACN;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,YAAY,CAAC,SAAiB;AAC5B,UAAI,QAAS,cAAa,OAAO;AACjC,gBAAU,WAAW,MAAM,QAAQ,IAAI,GAAG,KAAK;AAAA,IACjD;AAAA,IACA,UAAU,MAAM;AACd,UAAI,QAAS,cAAa,OAAO;AACjC,gBAAU;AAAA,IACZ;AAAA,EACF;AACF;;;ACrJA,IAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,sBAAsB;AAC5B,IAAM,0BAA0B;AAKzB,SAAS,SAAS,MAA6B;AACpD,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,IAAI;AACxB,WAAO,GAAG,IAAI,MAAM,GAAG,IAAI,QAAQ;AAAA,EACrC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,SAAS,MAA0B;AACjD,QAAM,MAAkB,CAAC;AACzB,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,IAAI,EAAE;AAC7B,eAAW,OAAO,UAAU;AAC1B,YAAM,QAAQ,OAAO,IAAI,GAAG,GAAG,KAAK;AACpC,UAAI,MAAO,KAAI,GAAG,IAAI,MAAM,YAAY,EAAE,MAAM,GAAG,GAAG;AAAA,IACxD;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAgBO,SAAS,eAAe,IAAqB;AAClD,MAAI,CAAC,GAAI,QAAO,CAAC;AACjB,QAAM,IAAI,GAAG,YAAY;AAEzB,QAAM,UAAU,EAAE,SAAS,MAAM,IAC7B,SACA,EAAE,SAAS,MAAM,KAAK,EAAE,SAAS,OAAO,IACtC,UACA,EAAE,SAAS,gBAAgB,IACzB,qBACA,EAAE,SAAS,SAAS,KAAK,EAAE,SAAS,OAAO,IACzC,YACA,EAAE,SAAS,QAAQ,KAAK,EAAE,SAAS,OAAO,IACxC,WACA,EAAE,SAAS,QAAQ,IACjB,WACA;AAEd,QAAM,KAAK,EAAE,SAAS,QAAQ,KAAK,EAAE,SAAS,MAAM,KAAK,EAAE,SAAS,MAAM,IACtE,QACA,EAAE,SAAS,SAAS,IAClB,YACA,EAAE,SAAS,SAAS,IAClB,YACA,EAAE,SAAS,QAAQ,KAAK,EAAE,SAAS,WAAW,IAC5C,UACA,EAAE,SAAS,MAAM,IACf,aACA,EAAE,SAAS,OAAO,IAChB,UACA;AAId,QAAM,SAAS,EAAE,SAAS,MAAM,KAAM,EAAE,SAAS,SAAS,KAAK,CAAC,EAAE,SAAS,QAAQ,IAC/E,WACA,EAAE,SAAS,MAAM,KAAK,EAAE,SAAS,QAAQ,KAAK,EAAE,SAAS,MAAM,IAC7D,WACA;AAEN,SAAO;AAAA,IACL,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7B,GAAI,KAAK,EAAE,GAAG,IAAI,CAAC;AAAA,IACnB;AAAA,EACF;AACF;AAIA,SAAS,YAAYE,UAA8B,KAA4B;AAC7E,MAAI;AACF,UAAM,IAAIA,aAAY,YAAY,iBAAiB;AACnD,WAAO,EAAE,QAAQ,GAAG;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAaA,UAA8B,KAAa,OAAqB;AACpF,MAAI;AACF,UAAM,IAAIA,aAAY,YAAY,iBAAiB;AACnD,MAAE,QAAQ,KAAK,KAAK;AAAA,EACtB,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,WAAmB;AAC1B,MAAI;AACF,WAAO,OAAO,WAAW;AAAA,EAC3B,QAAQ;AACN,WAAO,OAAO,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EAClF;AACF;AAGO,SAAS,mBAA2B;AACzC,QAAM,WAAW,YAAY,WAAW,mBAAmB;AAC3D,MAAI,SAAU,QAAO;AACrB,QAAM,QAAQ,SAAS;AACvB,eAAa,WAAW,qBAAqB,KAAK;AAClD,SAAO;AACT;AAMO,SAAS,mBAAmB,MAAc,UAAkB,aAAiC;AAClG,QAAM,SAAS,YAAY,WAAW,uBAAuB;AAC7D,MAAI,QAAQ;AACV,QAAI;AACF,aAAO,KAAK,MAAM,MAAM;AAAA,IAC1B,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,cAA0B,EAAE,GAAG,SAAS,IAAI,EAAE;AAEpD,QAAM,eAAe,OAAO,QAAQ;AAEpC,MAAI,gBAAgB,iBAAiB,aAAa;AAChD,UAAM,QAAQ,SAAS,QAAQ;AAC/B,QAAI,MAAO,aAAY,WAAW;AAClC,gBAAY,gBAAgB;AAAA,EAC9B;AAEA,eAAa,WAAW,yBAAyB,KAAK,UAAU,WAAW,CAAC;AAC5E,SAAO;AACT;AAEA,SAAS,OAAO,MAA6B;AAC3C,MAAI;AACF,WAAO,IAAI,IAAI,IAAI,EAAE,SAAS,YAAY,KAAK;AAAA,EACjD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,kBAA8B;AAC5C,MAAI,OAAO,WAAW,eAAe,OAAO,aAAa,YAAa,QAAO,CAAC;AAE9E,QAAM,OAAO,SAAS;AACtB,QAAM,WAAW,OAAO,aAAa,cAAc,SAAS,WAAW;AACvE,QAAM,OAAO,SAAS,SAAS,YAAY;AAE3C,QAAM,KAAK,OAAO,cAAc,cAAc,UAAU,YAAY;AACpE,QAAM,EAAE,SAAS,IAAI,OAAO,IAAI,eAAe,EAAE;AAEjD,QAAM,MAAM,SAAS,IAAI;AAEzB,SAAO;AAAA,IACL,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC;AAAA,IACrB,MAAM,SAAS,YAAY;AAAA,IAC3B;AAAA,IACA,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7B,GAAI,KAAK,EAAE,GAAG,IAAI,CAAC;AAAA,IACnB,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B,GAAI,OAAO,cAAc,eAAe,UAAU,WAC9C,EAAE,QAAQ,UAAU,SAAS,IAC7B,CAAC;AAAA,IACL,YAAY,iBAAiB;AAAA,IAC7B,GAAG,mBAAmB,MAAM,UAAU,IAAI;AAAA,EAC5C;AACF;;;AChOA,SAASC,OAAM,OAAuB;AACpC,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAQ,MAAM,WAAW,CAAC;AAC1B,WAAO,KAAK,KAAK,MAAM,QAAU,MAAM;AAAA,EACzC;AACA,SAAO,SAAS;AAClB;AAEO,SAAS,aAAa,UAAkB,YAA4B;AACzE,SAAOA,OAAM,GAAG,QAAQ,IAAI,UAAU,EAAE,IAAI;AAC9C;AAEO,SAAS,UAAU,UAAkB,YAAoB,YAA+B;AAC7F,SAAO,aAAa,UAAU,UAAU,IAAI,aAAa,YAAY;AACvE;AAEO,SAAS,oBAAoB,UAAkB,MAAuB;AAC3E,QAAM,IAAI,SAAS,MAAM,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AAC7D,QAAM,IAAI,KAAK,MAAM,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AACzD,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,SAAO,EAAE,MAAM,CAAC,SAAS,MAAM,QAAQ,WAAW,GAAG,KAAK,YAAY,EAAE,CAAC,CAAC;AAC5E;;;ACOA,IAAM,aAAa,IAAI,KAAK;AAC5B,IAAM,iBAAiB,KAAK;AAC5B,IAAM,mBAAmB;AACzB,IAAM,WAAW;AACjB,IAAM,gBAAgB;AACtB,IAAM,aAAa;AAEnB,IAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAOT,SAAS,cAAc,MAAsB;AAClD,SAAO,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AACxC;AAEO,SAAS,aAAa,MAAgC;AAC3D,QAAM,OAAQ,MAAuC;AACrD,SAAO,MAAM,QAAQ,IAAI,IAAI,KAAK,OAAO,QAAQ,IAAI,CAAC;AACxD;AAEA,SAAS,SAAS,OAAuC;AACvD,QAAM,IAAI;AACV,MAAI,GAAG,SAAS,OAAQ,QAAO;AAC/B,UAAQ,GAAG,SAAS,cAAc,GAAG,SAAS,WAAW,OAAO,EAAE,UAAU,YAAY,EAAE,MAAM,SAAS;AAC3G;AAEA,SAAS,SAAS,OAAwC;AACxD,QAAM,IAAI;AACV,SACE,OAAO,GAAG,OAAO,aAChB,EAAE,SAAS,UAAU,EAAE,SAAS,eACjC,OAAO,EAAE,SAAS,YAClB,SAAS,EAAE,MAAM,KACjB,OAAO,EAAE,SAAS,SAAS,YAC3B,OAAO,EAAE,gBAAgB;AAE7B;AAEO,SAAS,eACd,SACA,MACA,YACkD;AAClD,MAAI,CAAC,WAAY,QAAO,CAAC;AACzB,SAAO,QACJ,OAAO,CAAC,MAAM,oBAAoB,EAAE,MAAM,IAAI,CAAC,EAC/C,IAAI,CAAC,YAAY,EAAE,QAAQ,KAAK,UAAU,OAAO,IAAI,YAAY,OAAO,WAAW,EAAE,EAAE;AAC5F;AAEA,SAAS,QAAQ,MAAgD;AAC/D,MAAI;AACF,WAAO,SAAS,UAAU,OAAO,eAAe,OAAO;AAAA,EACzD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,QAAQ,OAA4B,KAA0B;AACrE,MAAI;AACF,WAAO,IAAI,IAAI,KAAK,MAAM,OAAO,QAAQ,GAAG,KAAK,IAAI,CAAa;AAAA,EACpE,QAAQ;AACN,WAAO,oBAAI,IAAI;AAAA,EACjB;AACF;AAEA,SAAS,SAAS,OAA4B,KAAa,OAAqB;AAC9E,MAAI;AACF,UAAM,MAAM,QAAQ,OAAO,GAAG;AAC9B,QAAI,IAAI,KAAK;AACb,WAAO,QAAQ,KAAK,KAAK,UAAU,CAAC,GAAG,GAAG,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,EAC1D,QAAQ;AACN;AAAA,EACF;AACF;AAEA,SAAS,MAAM,UAAkC;AAC/C,MAAI;AACF,WAAO,SAAS,cAAc,QAAQ;AAAA,EACxC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAM,mBAAmB;AACzB,IAAM,yBAAyB;AAExB,SAAS,WAAW,OAA+B;AACxD,QAAM,SAAS,cAAc,KAAK;AAClC,MAAI,OAAuB;AAC3B,MAAI,aAAa,OAAO;AACxB,QAAM,QAAQ,SAAS,iBAAiB,gBAAgB;AACxD,QAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,sBAAsB;AAC3D,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK,GAAG;AACjC,UAAM,KAAK,MAAM,CAAC;AAClB,UAAM,MAAM,GAAG,eAAe;AAC9B,QAAI,IAAI,UAAU,cAAc,cAAc,GAAG,MAAM,OAAQ;AAC/D,WAAO;AACP,iBAAa,IAAI;AAAA,EACnB;AACA,SAAO;AACT;AAEA,SAAS,WAAW,QAAsC;AACxD,MAAI,OAAO,SAAS,OAAQ,QAAO;AACnC,SAAO,OAAO,SAAS,aAAa,MAAM,OAAO,KAAK,IAAI,WAAW,OAAO,KAAK;AACnF;AAEA,SAAS,aAAa,IAAa,OAA+C;AAChF,QAAM,SAAS,SAAS,iBAAiB,IAAI,WAAW,SAAS;AACjE,WAAS,OAAO,OAAO,SAAS,GAAG,MAAM,OAAO,OAAO,SAAS,GAAG;AACjE,QAAI,MAAM,cAAc,KAAK,eAAe,EAAE,CAAC,EAAG,QAAO;AAAA,EAC3D;AACA,SAAO;AACT;AAQO,SAAS,sBAAsB,MAAmD;AACvF,MAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AACpE,WAAO,EAAE,YAAY,MAAM,QAAW,SAAS,YAAY,QAAW,UAAU,MAAM,OAAU;AAAA,EAClG;AAEA,MAAI,UAA2B,CAAC;AAChC,MAAI,YAAY;AAChB,MAAI,QAA8C;AAClD,MAAI,OAA0B;AAC9B,MAAI,OAA2B;AAC/B,QAAM,SAAS,oBAAI,IAAyB;AAC5C,QAAM,OAAO,oBAAI,IAAwB;AAEzC,QAAM,MAAM,CAAC,YAA0B;AACrC,QAAI,KAAK,MAAO,SAAQ,KAAK,WAAW,OAAO,EAAE;AAAA,EACnD;AAEA,QAAM,SAAS,CAAC,QAAuB,QAAyB;AAC9D,UAAM,MAAM,GAAG,OAAO,EAAE,IAAI,GAAG;AAC/B,UAAM,UAAU,QAAQ,SAAS;AACjC,QAAI,QAAQ,SAAS,QAAQ,EAAE,IAAI,GAAG,EAAG;AACzC,aAAS,SAAS,UAAU,GAAG;AAC/B,SAAK,MAAM,oBAAoB,EAAE,WAAW,OAAO,IAAI,KAAK,MAAM,OAAO,KAAK,CAAC;AAAA,EACjF;AAEA,QAAM,mBAAmB,CAAC,IAAa,WAAuC;AAC5E,UAAM,WAAW,OAAO,gBAAgB,cAAc,OAAO,aAAa,IAAI;AAC9E,UAAM,OAAO,cAAc,OAAO,QAAQ,IAAI;AAC9C,WAAO,aAAa,IAAI,CAAC,SAAS,KAAK,SAAS,MAAM,SAAS,QAAQ,aAAa,QAAQ,SAAS,SAAS;AAAA,EAChH;AAEA,QAAM,YAAY,CAAC,IAAa,WAAmC;AACjE,UAAM,OAAO,cAAc,OAAO,QAAQ,IAAI;AAC9C,UAAM,UAAU,OAAO,IAAI,OAAO,EAAE;AACpC,QAAI,WAAW,QAAQ,KAAK,eAAe,cAAc,QAAQ,KAAK,eAAe,EAAE,MAAM,KAAM,QAAO;AAC1G,UAAM,OAAO,iBAAiB,IAAI,MAAM;AACxC,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,OAAO,KAAK,eAAe;AACjC,QAAI,cAAc,IAAI,MAAM,MAAM;AAChC,aAAO,IAAI,OAAO,IAAI,EAAE,MAAM,UAAU,MAAM,MAAM,OAAO,QAAQ,KAAK,CAAC;AACzE,WAAK,cAAc,KAAK,QAAQ,KAAK,KAAK,GAAG,OAAO,QAAQ,IAAI;AAAA,IAClE;AACA,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,CAAC,OAAqB;AACxC,UAAM,UAAU,OAAO,IAAI,EAAE;AAC7B,QAAI,CAAC,QAAS;AACd,QAAI,QAAQ,KAAK,eAAe,cAAc,QAAQ,KAAK,eAAe,EAAE,MAAM,cAAc,QAAQ,IAAI,GAAG;AAC7G,cAAQ,KAAK,cAAc,QAAQ;AAAA,IACrC;AACA,WAAO,OAAO,EAAE;AAAA,EAClB;AAEA,QAAM,aAAa,MAAyB;AAC1C,QAAI,KAAM,QAAO;AACjB,QAAI,CAAC,SAAS,KAAM,QAAO;AAC3B,WAAO,SAAS,cAAc,eAAe;AAC7C,SAAK,aAAa,mBAAmB,GAAG;AACxC,SAAK,MAAM,UAAU;AACrB,WAAO,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3C,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,cAAc;AACpB,SAAK,YAAY,KAAK;AACtB,aAAS,KAAK,YAAY,IAAI;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,CAAC,QAAwB,WAAmC;AAC1E,QAAI,KAAK,IAAI,OAAO,EAAE,EAAG,QAAO;AAChC,QAAI,QAAQ,QAAQ,OAAO,GAAG,aAAa,EAAE,IAAI,OAAO,EAAE,EAAG,QAAO;AACpE,UAAM,SAAS,WAAW;AAC1B,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,OAAO,SAAS,cAAc,KAAK;AACzC,SAAK,YAAY;AACjB,SAAK,aAAa,QAAQ,SAAS;AACnC,UAAM,OAAO,SAAS,cAAc,GAAG;AACvC,SAAK,cAAc,OAAO,QAAQ;AAClC,UAAM,QAAQ,SAAS,cAAc,QAAQ;AAC7C,UAAM,OAAO;AACb,UAAM,aAAa,cAAc,QAAQ;AACzC,UAAM,cAAc;AACpB,SAAK,OAAO,MAAM,KAAK;AACvB,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,OAAO;AAClB,WAAO,YAAY,IAAI;AAEvB,UAAM,SAAS,MAAY;AACzB,WAAK,OAAO;AACZ,aAAO,oBAAoB,UAAU,UAAU,IAAI;AACnD,aAAO,oBAAoB,UAAU,QAAQ;AAC7C,WAAK,OAAO,OAAO,EAAE;AAAA,IACvB;AAEA,aAAS,WAAiB;AACxB,UAAI,CAAC,QAAQ;AACX,cAAM,SAAS,KAAK,sBAAsB;AAC1C,aAAK,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,OAAO,cAAc,OAAO,SAAS,EAAE,CAAC;AACxE,aAAK,MAAM,OAAO,GAAG,KAAK,IAAI,GAAG,OAAO,aAAa,OAAO,QAAQ,EAAE,CAAC;AACvE;AAAA,MACF;AACA,UAAI,CAAC,OAAO,aAAa;AACvB,eAAO;AACP;AAAA,MACF;AACA,YAAM,IAAI,OAAO,sBAAsB;AACvC,YAAM,IAAI,KAAK,sBAAsB;AACrC,UAAI,MAAM,EAAE,SAAS;AACrB,UAAI,MAAM,EAAE,SAAS,OAAO,cAAc,EAAG,OAAM,EAAE,MAAM,EAAE,SAAS;AACtE,YAAM,OAAO,KAAK,IAAI,KAAK,IAAI,GAAG,EAAE,OAAO,EAAE,QAAQ,IAAI,EAAE,QAAQ,CAAC,GAAG,OAAO,aAAa,EAAE,QAAQ,CAAC;AACtG,WAAK,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,GAAG,CAAC;AACpC,WAAK,MAAM,OAAO,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;AAAA,IACxC;AAEA,UAAM,iBAAiB,SAAS,MAAM;AACpC,eAAS,QAAQ,OAAO,GAAG,eAAe,OAAO,EAAE;AACnD,WAAK,MAAM,qBAAqB,EAAE,WAAW,OAAO,IAAI,MAAM,OAAO,KAAK,CAAC;AAC3E,aAAO;AAAA,IACT,CAAC;AACD,SAAK,IAAI,OAAO,IAAI,MAAM;AAC1B,0BAAsB,QAAQ;AAC9B,WAAO,iBAAiB,UAAU,UAAU,IAAI;AAChD,WAAO,iBAAiB,UAAU,QAAQ;AAC1C,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,MAAY;AACvB,YAAQ;AACR,UAAM,SAAS,eAAe,SAAS,SAAS,UAAU,KAAK,cAAc,CAAC;AAC9E,UAAM,YAAY,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AACxD,eAAW,MAAM,CAAC,GAAG,OAAO,KAAK,CAAC,EAAG,KAAI,CAAC,UAAU,IAAI,EAAE,EAAG,aAAY,EAAE;AAC3E,eAAW,CAAC,IAAI,MAAM,KAAK,CAAC,GAAG,IAAI,EAAG,KAAI,CAAC,UAAU,IAAI,EAAE,EAAG,QAAO;AAErE,eAAW,EAAE,QAAQ,IAAI,KAAK,QAAQ;AACpC,YAAM,KAAK,WAAW,OAAO,MAAM;AACnC,UAAI,CAAC,MAAM,OAAO,OAAO,SAAS,OAAQ;AAC1C,UAAI,OAAO,SAAS,QAAQ;AAC1B,YAAI,CAAC,GAAI;AACT,cAAM,QAAQ,QAAQ,WAAW,UAAU,IAAI,MAAM,IAAI,iBAAiB,IAAI,MAAM,MAAM;AAC1F,YAAI,MAAO,QAAO,QAAQ,GAAG;AAAA,MAC/B,WAAW,QAAQ,aAAa,QAAQ,IAAI,MAAM,GAAG;AACnD,eAAO,QAAQ,GAAG;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,MAAY;AAC3B,QAAI,UAAU,KAAM,SAAQ,WAAW,MAAM,gBAAgB;AAAA,EAC/D;AAEA,QAAM,UAAU,YAA2B;AACzC,gBAAY,KAAK,IAAI;AACrB,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,oBAAoB;AAAA,QACzD,SAAS,EAAE,eAAe,UAAU,KAAK,MAAM,GAAG;AAAA,MACpD,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,YAAI,WAAW,IAAI,MAAM,EAAE;AAC3B;AAAA,MACF;AACA,gBAAU,aAAa,MAAM,IAAI,KAAK,CAAC;AACvC,eAAS;AAAA,IACX,SAAS,KAAK;AACZ,UAAI,0BAA2B,IAAc,OAAO,EAAE;AAAA,IACxD;AAAA,EACF;AAEA,QAAM,WACJ,OAAO,qBAAqB,cACxB,IAAI,iBAAiB,MAAM;AACzB,QAAI,QAAQ,SAAS,KAAK,OAAO,OAAO,KAAK,KAAK,OAAO,EAAG,UAAS;AAAA,EACvE,CAAC,IACD;AACN,QAAM,UAAU,MAAY;AAC1B,QAAI,SAAS,KAAM,WAAU,QAAQ,SAAS,MAAM,EAAE,WAAW,MAAM,SAAS,MAAM,eAAe,KAAK,CAAC;AAAA,EAC7G;AACA,MAAI,SAAS,eAAe,UAAW,UAAS,iBAAiB,oBAAoB,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,MACvG,SAAQ;AAEb,QAAM,WAAW,YAAY,MAAM,KAAK,QAAQ,GAAG,UAAU;AAC7D,OAAK,QAAQ;AAEb,SAAO;AAAA,IACL,YAAY,MAAM;AAChB,UAAI,KAAK,IAAI,IAAI,YAAY,eAAgB,MAAK,QAAQ;AAC1D,eAAS;AAAA,IACX;AAAA,IACA;AAAA,IACA,UAAU,MAAM;AACd,oBAAc,QAAQ;AACtB,UAAI,UAAU,KAAM,cAAa,KAAK;AACtC,gBAAU,WAAW;AACrB,iBAAW,MAAM,CAAC,GAAG,OAAO,KAAK,CAAC,EAAG,aAAY,EAAE;AACnD,iBAAW,UAAU,CAAC,GAAG,KAAK,OAAO,CAAC,EAAG,QAAO;AAChD,YAAM,OAAO;AACb,aAAO;AACP,aAAO;AACP,gBAAU,CAAC;AAAA,IACb;AAAA,EACF;AACF;;;AC/UA,IAAM,mBAAmB;AA+BlB,IAAM,WAAN,cAAuB,UAAU;AAAA,EAC9B,sBAA2C;AAAA,EAC3C,WAAmC;AAAA,EACnC,UAAuC;AAAA,EACvC,WAAmC;AAAA,EAE3C,YAAY,MAAuB;AACjC,UAAM,WAAW,IAAI;AACrB,SAAK,cAAc,mBAAmB;AAEtC,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,iBAAiB,YAAY,MAAM,KAAK,KAAK,MAAM,CAAC;AAC3D,eAAS,iBAAiB,oBAAoB,MAAM;AAClD,YAAI,SAAS,oBAAoB,SAAU,MAAK,KAAK,MAAM;AAAA,MAC7D,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,aAAa,OAAO;AAC3B,YAAM,eAAe,OAAO,KAAK,aAAa,WAAW,KAAK,WAAW,CAAC;AAC1E,WAAK,WAAW,uBAAuB;AAAA,QACrC,GAAG;AAAA,QACH,YAAY,CAAC,GAAI,aAAa,cAAc,CAAC,GAAI,KAAK,OAAO;AAAA,QAC7D,YAAY,CAAC,WAAW,KAAK,MAAM,IAAI,OAAO,IAAI,IAAI,OAAO,UAAU;AAAA,MACzE,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,aAAa,OAAO;AAC3B,WAAK,WAAW,uBAAuB;AAAA,QACrC,YAAY,CAAC,aAAa,KAAK,MAAM,kBAAkB,EAAE,GAAG,SAAS,CAAC;AAAA,MACxE,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,gBAAgB,OAAO;AAC9B,WAAK,sBAAsB,mBAAmB;AAAA,QAC5C,YAAY,CAAC,SAAyB;AACpC,eAAK,KAAK,QAAW,EAAE,YAAY,KAAK,CAAC;AACzC,gBAAM,OAAO,OAAO,aAAa,cAAc,SAAS,WAAW;AACnE,eAAK,UAAU,WAAW,IAAI;AAC9B,eAAK,SAAS,WAAW;AACzB,eAAK,UAAU,WAAW,IAAI;AAAA,QAChC;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,mBAAmB,SAAS,OAAO,WAAW,aAAa;AAClE,WAAK,UAAU,sBAAsB;AAAA,QACnC,SAAS,KAAK;AAAA,QACd,QAAQ,KAAK;AAAA,QACb,eAAe,MAAM,KAAK;AAAA,QAC1B,OAAO,CAAC,MAAM,eAAe,KAAK,MAAM,MAAM,UAAU;AAAA,QACxD,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,KAAK,MAAe,YAA+B;AACjD,SAAK,MAAM,aAAa;AAAA,MACtB,GAAI,cAAc,CAAC;AAAA,MACnB,GAAI,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;AAAA,MAClC,GAAI,OAAO,aAAa,eAAe,SAAS,QAAQ,EAAE,OAAO,SAAS,MAAM,IAAI,CAAC;AAAA,IACvF,CAAC;AAAA,EACH;AAAA,EAES,MAAM,YAAoB,QAA2B;AAC5D,UAAM,MAAM,YAAY,MAAM;AAC9B,SAAK,SAAS,WAAW;AAAA,EAC3B;AAAA,EAEA,QAAc;AACZ,SAAK,SAAS;AACd,SAAK,aAAa;AAClB,QAAI;AACF,mBAAa,WAAW,gBAAgB;AAAA,IAC1C,QAAQ;AAAA,IAER;AACA,SAAK,cAAc,mBAAmB;AACtC,SAAK,SAAS,WAAW;AAAA,EAC3B;AAAA;AAAA,EAGA,MAAe,WAA0B;AACvC,SAAK,sBAAsB;AAC3B,SAAK,sBAAsB;AAC3B,SAAK,UAAU,SAAS;AACxB,SAAK,WAAW;AAChB,SAAK,SAAS,SAAS;AACvB,SAAK,UAAU;AACf,SAAK,UAAU,SAAS;AACxB,SAAK,WAAW;AAChB,UAAM,MAAM,SAAS;AAAA,EACvB;AAAA,EAEmB,qBAAiC;AAClD,WAAO,gBAAgB;AAAA,EACzB;AACF;AAEA,SAAS,qBAA6B;AACpC,MAAI;AACF,UAAM,WAAW,aAAa,QAAQ,gBAAgB;AACtD,QAAI,SAAU,QAAO;AACrB,UAAM,QAAQ,OAAO,WAAW;AAChC,iBAAa,QAAQ,kBAAkB,KAAK;AAC5C,WAAO;AAAA,EACT,QAAQ;AACN,WAAO,OAAO,WAAW;AAAA,EAC3B;AACF;AAEA,IAAI,YAA6B;AAG1B,SAAS,UAAU,MAAiC;AACzD,MAAI,CAAC,WAAW;AACd,gBAAY,IAAI,SAAS,IAAI;AAI7B,QAAI,OAAO,WAAW,aAAa;AACjC,YAAM,IAAI;AACV,UAAI,CAAC,EAAE,MAAO,GAAE,QAAQ;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;",
|
|
6
|
-
"names": ["INSTALLED_FLAG", "currentPath", "storage", "fnv1a"]
|
|
3
|
+
"sources": ["../src/core.ts", "../src/auto-capture.ts", "../src/friction.ts", "../src/theme.ts", "../src/skeleton.ts", "../src/web-context.ts", "../src/tip-css.ts", "../src/arm.ts", "../src/changes.ts", "../src/web.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Core do @holdyapp/sdk \u00B7 fila + flush pra POST /api/v1/events/bulk.\n *\n * Todo evento sai com `external_id` pr\u00F3prio, ent\u00E3o reenviar um lote nunca\n * duplica (dedupe server-side por source + external_id + occurred_at).\n * 429 respeita Retry-After; 5xx e rede esperam com backoff exponencial; o lote\n * volta pra frente da fila em vez de sumir. Chave inv\u00E1lida ou origem recusada\n * avisam uma vez no console, mesmo sem debug. Fila \u00E9 bounded: acima de\n * MAX_QUEUE dropa os mais antigos (telemetria nunca derruba o app do cliente \u2014\n * nenhum m\u00E9todo p\u00FAblico lan\u00E7a).\n */\n\nimport type { CanonicalEvent, HoldyOptions, Properties, TrackOverrides } from './types'\n\nexport const DEFAULT_BASE_URL = 'https://holdy.chat/api/v1'\nconst DEFAULT_FLUSH_AT = 20\nconst DEFAULT_FLUSH_INTERVAL_MS = 5000\nconst MAX_QUEUE = 1000\nconst BULK_LIMIT = 500\nconst MAX_BACKOFF_MS = 60_000\n\ntype SendOutcome = { kind: 'sent' } | { kind: 'dropped' } | { kind: 'retry'; afterMs: number | null }\n\nexport class HoldyCore {\n protected readonly apiKey: string\n protected readonly baseUrl: string\n private readonly flushAt: number\n private readonly debug: boolean\n private readonly source: 'sdk_web' | 'sdk_server'\n private readonly release: string | null\n\n private queue: CanonicalEvent[] = []\n private timer: ReturnType<typeof setInterval> | null = null\n private flushing: Promise<void> | null = null\n private retryAt = 0\n private failures = 0\n private readonly warned = new Set<string>()\n\n protected userId: string | null = null\n protected anonymousId: string | null = null\n protected accountKey: string | null = null\n\n constructor(source: 'sdk_web' | 'sdk_server', opts: HoldyOptions) {\n this.source = source\n this.apiKey = opts.apiKey\n this.accountKey = opts.accountKey ?? null\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '')\n this.flushAt = Math.max(1, opts.flushAt ?? DEFAULT_FLUSH_AT)\n this.debug = opts.debug ?? false\n this.release = typeof opts.release === 'string' && opts.release.trim() ? opts.release.trim().slice(0, 64) : null\n\n const intervalMs = opts.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS\n if (intervalMs > 0) {\n this.timer = setInterval(() => void this.flush(), intervalMs)\n // Node: n\u00E3o segura o processo vivo s\u00F3 pelo timer do SDK.\n if (typeof (this.timer as { unref?: () => void }).unref === 'function') {\n ;(this.timer as unknown as { unref: () => void }).unref()\n }\n }\n }\n\n track(name: string, properties?: Properties, overrides?: TrackOverrides): void {\n if (!name || typeof name !== 'string') return\n\n const userId = overrides?.userId ?? this.userId ?? undefined\n const accountKey = overrides?.accountKey ?? this.accountKey ?? undefined\n const occurredAt = overrides?.occurredAt\n ? new Date(overrides.occurredAt).toISOString()\n : new Date().toISOString()\n\n // Ordem: ambiente observado pelo SDK \u2192 context da chamada \u2192 carrier de\n // account. O que o caller passou vence o inferido; o carrier vence tudo,\n // porque \u00E9 o que a Data layer usa pra resolver a conta.\n const context: Properties = {\n ...this.environmentContext(),\n ...(this.release ? { release: this.release } : {}),\n ...(overrides?.context ?? {}),\n }\n if (accountKey) context.account_external_id = accountKey\n\n const event: CanonicalEvent = {\n event: name,\n occurred_at: occurredAt,\n source: this.source,\n external_id: newEventId(),\n ...(userId ? { user_id: userId } : {}),\n ...(this.anonymousId ? { anonymous_id: this.anonymousId } : {}),\n properties: properties ?? {},\n ...(Object.keys(context).length > 0 ? { context } : {}),\n }\n\n this.queue.push(event)\n this.trimQueue()\n if (this.queue.length >= this.flushAt) void this.flush()\n }\n\n identify(userId: string, traits?: Properties): void {\n if (!userId || typeof userId !== 'string') return\n this.userId = userId\n this.track('$identify', traits ?? {})\n }\n\n group(accountKey: string, traits?: Properties): void {\n if (!accountKey || typeof accountKey !== 'string') return\n this.accountKey = accountKey\n this.track('$group', traits ?? {})\n }\n\n /** Drena a fila. Nunca lan\u00E7a \u2014 falha re-enfileira e espera antes de tentar de novo. */\n async flush(): Promise<void> {\n return this.startFlush(false)\n }\n\n /** Flush final + para o timer. Chamar em shutdown do server / unload do web. */\n async shutdown(): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer)\n this.timer = null\n }\n await this.startFlush(true)\n }\n\n private startFlush(force: boolean): Promise<void> {\n // Serializa flushes concorrentes (timer + flushAt + manual).\n if (this.flushing) return this.flushing\n if (this.queue.length === 0) return Promise.resolve()\n if (!force && Date.now() < this.retryAt) return Promise.resolve()\n\n this.flushing = this.drain().finally(() => {\n this.flushing = null\n })\n return this.flushing\n }\n\n private async drain(): Promise<void> {\n while (this.queue.length > 0) {\n const batch = this.queue.splice(0, BULK_LIMIT)\n const outcome = await this.send(batch)\n if (outcome.kind === 'retry') {\n this.queue.unshift(...batch)\n this.trimQueue()\n this.scheduleRetry(outcome.afterMs)\n return\n }\n this.failures = 0\n this.retryAt = 0\n }\n }\n\n private scheduleRetry(afterMs: number | null): void {\n this.failures += 1\n if (afterMs !== null) {\n this.retryAt = Date.now() + afterMs\n return\n }\n const backoff = Math.min(MAX_BACKOFF_MS, 1000 * 2 ** (this.failures - 1))\n this.retryAt = Date.now() + backoff + Math.floor(Math.random() * backoff * 0.2)\n }\n\n private trimQueue(): void {\n if (this.queue.length > MAX_QUEUE) this.queue.splice(0, this.queue.length - MAX_QUEUE)\n }\n\n private async send(events: CanonicalEvent[]): Promise<SendOutcome> {\n try {\n const res = await fetch(`${this.baseUrl}/events/bulk`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ events }),\n ...(this.source === 'sdk_web' ? { keepalive: true } : {}),\n })\n if (res.ok) return { kind: 'sent' }\n\n if (res.status === 429) {\n this.log('rate limited \u00B7 will retry after Retry-After')\n return { kind: 'retry', afterMs: retryAfterMs(res) }\n }\n if (res.status >= 500) {\n this.log(`bulk failed ${res.status} \u00B7 will retry with backoff`)\n return { kind: 'retry', afterMs: null }\n }\n if (res.status === 401) {\n this.warnOnce('401', 'API key inv\u00E1lida ou revogada \u00B7 eventos descartados. Confira a chave em Configura\u00E7\u00F5es \u203A SDK.')\n return { kind: 'dropped' }\n }\n if (res.status === 403) {\n this.warnOnce('403', 'Origem n\u00E3o permitida ou chave sem escopo events:write \u00B7 eventos descartados.')\n return { kind: 'dropped' }\n }\n this.log(`bulk rejected ${res.status} \u00B7 batch dropped`)\n return { kind: 'dropped' }\n } catch (err) {\n this.log(`bulk network error: ${(err as Error).message} \u00B7 will retry with backoff`)\n return { kind: 'retry', afterMs: null }\n }\n }\n\n private log(msg: string): void {\n if (this.debug) console.warn(`[holdy] ${msg}`)\n }\n\n private warnOnce(key: string, msg: string): void {\n if (this.warned.has(key)) return\n this.warned.add(key)\n console.warn(`[holdy] ${msg}`)\n }\n\n /**\n * Ambiente que o SDK observa sozinho (url, referrer, browser, utm\u2026).\n * Vazio no core; `HoldyWeb` preenche. O server n\u00E3o infere ambiente \u2014 n\u00E3o\n * existe \"p\u00E1gina atual\" num worker.\n */\n protected environmentContext(): Properties {\n return {}\n }\n\n /** Interno \u00B7 exposto pra testes. */\n get pending(): number {\n return this.queue.length\n }\n}\n\nfunction retryAfterMs(res: Response): number | null {\n const raw = typeof res.headers?.get === 'function' ? res.headers.get('Retry-After') : null\n if (!raw) return null\n const seconds = Number(raw)\n if (!Number.isFinite(seconds) || seconds < 0) return null\n return Math.min(MAX_BACKOFF_MS, seconds * 1000)\n}\n\nfunction newEventId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto\n if (typeof c?.randomUUID === 'function') return c.randomUUID()\n const rand = () => Math.random().toString(36).slice(2, 12)\n return `${Date.now().toString(36)}-${rand()}-${rand()}`\n}\n", "/**\n * Auto-capture de navega\u00E7\u00E3o \u00B7 @holdyapp/sdk/web.\n *\n * Emite pageview no carregamento e a cada mudan\u00E7a de rota, inclusive nas que\n * n\u00E3o recarregam a p\u00E1gina (SPA). Sem isto, instrumentar exige que o cliente\n * chame `page()` em cada tela \u2014 e o primeiro dado s\u00F3 aparece depois de um\n * trabalho que ele ainda n\u00E3o fez.\n *\n * Idempotente: reinstalar \u00E9 no-op (guard global). O retorno desfaz o patch de\n * `history`, ent\u00E3o `destroy()` devolve o browser como estava.\n */\n\nconst INSTALLED_FLAG = '__holdy_autocapture__'\n\n/** pushState seguido de replaceState \u00E9 uma mudan\u00E7a l\u00F3gica s\u00F3. */\nconst ROUTE_DEBOUNCE_MS = 50\n\nexport type NavigationKind = 'initial_load' | 'route_change'\n\nexport interface AutoCaptureOptions {\n onNavigate: (kind: NavigationKind) => void\n}\n\ninterface GlobalWithFlag {\n [INSTALLED_FLAG]?: boolean\n}\n\nexport function installAutoCapture(opts: AutoCaptureOptions): () => void {\n if (typeof window === 'undefined' || typeof history === 'undefined') {\n return () => undefined\n }\n\n const w = window as unknown as GlobalWithFlag\n if (w[INSTALLED_FLAG]) return () => undefined\n w[INSTALLED_FLAG] = true\n\n const cleanups: Array<() => void> = []\n let lastPath = currentPath()\n let pending: ReturnType<typeof setTimeout> | null = null\n\n function emit(kind: NavigationKind): void {\n try {\n opts.onNavigate(kind)\n } catch {\n // Telemetria nunca derruba a app do cliente.\n }\n }\n\n function scheduleRouteEmit(): void {\n if (pending) clearTimeout(pending)\n pending = setTimeout(() => {\n pending = null\n const path = currentPath()\n // S\u00F3 conta como pageview se a rota mudou de fato \u2014 replaceState de\n // estado interno (filtro, scroll) n\u00E3o \u00E9 navega\u00E7\u00E3o.\n if (path === lastPath) return\n lastPath = path\n emit('route_change')\n }, ROUTE_DEBOUNCE_MS)\n }\n\n emit('initial_load')\n\n const originalPush = history.pushState\n const originalReplace = history.replaceState\n\n history.pushState = function patchedPush(...args: Parameters<History['pushState']>) {\n const result = originalPush.apply(this, args)\n scheduleRouteEmit()\n return result\n }\n history.replaceState = function patchedReplace(...args: Parameters<History['replaceState']>) {\n const result = originalReplace.apply(this, args)\n scheduleRouteEmit()\n return result\n }\n cleanups.push(() => {\n history.pushState = originalPush\n history.replaceState = originalReplace\n })\n\n // Voltar/avan\u00E7ar do browser e routers baseados em hash.\n const onPop = (): void => scheduleRouteEmit()\n window.addEventListener('popstate', onPop)\n cleanups.push(() => window.removeEventListener('popstate', onPop))\n\n const onHash = (): void => scheduleRouteEmit()\n window.addEventListener('hashchange', onHash)\n cleanups.push(() => window.removeEventListener('hashchange', onHash))\n\n return () => {\n if (pending) clearTimeout(pending)\n for (const cleanup of cleanups) cleanup()\n w[INSTALLED_FLAG] = false\n }\n}\n\n/** Rota compar\u00E1vel \u00B7 path + query, sem hash de \u00E2ncora. */\nfunction currentPath(): string {\n if (typeof location === 'undefined') return '/'\n return `${location.pathname}${location.search}${location.hash}`\n}\n", "export type FrictionKind =\n | 'dead_click'\n | 'rage_click'\n | 'form_abandon'\n | 'js_error'\n | 'slow_request'\n | 'nav_loop'\n | 'http_error'\n\nexport interface FrictionSignal {\n kind: FrictionKind\n properties: Record<string, unknown>\n}\n\nexport interface FrictionCaptureOptions {\n onFriction: (signal: FrictionSignal) => void\n slowRequestMs?: number\n rageClicks?: number\n rageWindowMs?: number\n rageRadiusPx?: number\n navLoopWindowMs?: number\n ignoreUrls?: string[]\n /**\n * Origens que contam como o pr\u00F3prio produto al\u00E9m do dom\u00EDnio da p\u00E1gina \u2014\n * pro caso em que a API mora em outro dom\u00EDnio (`acme-api.io` servindo\n * `acme.com`). O subdom\u00EDnio j\u00E1 entra sozinho.\n */\n apiOrigins?: string[]\n}\n\nexport interface FrictionCapture {\n onNavigate: (path: string) => void\n teardown: () => void\n}\n\nconst INSTALLED_FLAG = '__holdy_friction__'\nconst INTERACTIVE_SELECTOR =\n 'button, a, input, select, textarea, summary, [role=\"button\"], [role=\"link\"], [role=\"menuitem\"], [role=\"tab\"]'\nconst INTERACTIVE_TAGS = new Set(['button', 'a', 'input', 'select', 'textarea', 'summary'])\nconst FORM_CONTROL_TAGS = new Set(['input', 'select', 'textarea'])\n\nexport class RageClickDetector {\n private clicks: Array<{ x: number; y: number; t: number }> = []\n\n constructor(\n private readonly threshold = 3,\n private readonly windowMs = 1000,\n private readonly radiusPx = 30,\n ) {}\n\n push(x: number, y: number, t: number): boolean {\n this.clicks = this.clicks.filter(\n (c) => t - c.t <= this.windowMs && Math.hypot(c.x - x, c.y - y) <= this.radiusPx,\n )\n this.clicks.push({ x, y, t })\n if (this.clicks.length >= this.threshold) {\n this.clicks = []\n return true\n }\n return false\n }\n}\n\nexport class NavLoopDetector {\n private visits: Array<{ path: string; t: number }> = []\n\n constructor(private readonly windowMs = 60_000) {}\n\n push(path: string, t: number): { from: string; to: string } | null {\n this.visits = [...this.visits, { path, t }].filter((v) => t - v.t <= this.windowMs).slice(-4)\n if (this.visits.length < 4) return null\n const [a, b, c, d] = this.visits.map((v) => v.path)\n if (a === c && b === d && a !== b) {\n this.visits = []\n return { from: a, to: b }\n }\n return null\n }\n}\n\nexport interface ElementLike {\n tagName?: string\n id?: string\n disabled?: boolean\n textContent?: string | null\n getAttribute(name: string): string | null\n closest?(selector: string): ElementLike | null\n}\n\nfunction tagOf(el: { tagName?: unknown } | null | undefined): string {\n return typeof el?.tagName === 'string' ? el.tagName.toLowerCase() : ''\n}\n\nexport function resolveInteractive(el: ElementLike | null): ElementLike | null {\n if (!el) return null\n const viaClosest = el.closest?.(INTERACTIVE_SELECTOR) ?? null\n if (viaClosest) return viaClosest\n const tag = tagOf(el)\n if (INTERACTIVE_TAGS.has(tag)) return el\n const role = el.getAttribute('role')\n if (role === 'button' || role === 'link' || role === 'menuitem' || role === 'tab') return el\n return null\n}\n\nexport function isDeadClickTarget(el: ElementLike | null): boolean {\n const target = resolveInteractive(el)\n if (!target) return false\n if (target.disabled === true) return true\n if (target.getAttribute('disabled') !== null) return true\n if (target.getAttribute('aria-disabled') === 'true') return true\n const tag = tagOf(target)\n if (tag === 'a') {\n const href = target.getAttribute('href')\n if (!href || href === '#' || href.startsWith('javascript:')) return true\n }\n return false\n}\n\nexport function describeElement(el: ElementLike | null): Record<string, string> {\n const target = resolveInteractive(el) ?? el\n if (!target) return {}\n const out: Record<string, string> = { element: tagOf(target) }\n if (target.id) out.element_id = target.id\n const role = target.getAttribute('role')\n if (role) out.element_role = role\n const label = target.getAttribute('aria-label') ?? target.textContent ?? ''\n const text = label.replace(/\\s+/g, ' ').trim().slice(0, 60)\n if (text) out.element_text = text\n const name = target.getAttribute('name') ?? target.getAttribute('data-testid')\n if (name) out.element_name = name\n return out\n}\n\nexport function stripRequestUrl(input: string, base?: string): string {\n try {\n const url = new URL(input, base)\n return `${url.origin}${url.pathname}`\n } catch {\n return input.split('?')[0].split('#')[0]\n }\n}\n\nexport function errorMessage(reason: unknown): string {\n if (reason instanceof Error) return reason.message\n if (typeof reason === 'string') return reason\n try {\n return JSON.stringify(reason)\n } catch {\n return String(reason)\n }\n}\n\nconst STACK_MAX_FRAMES = 8\nconst STACK_MAX_FRAME_CHARS = 200\nconst STACK_FRAME = /^at\\s|^\\S*@\\S+:\\d+(?::\\d+)?$/\n\nexport function sanitizeStack(stack: unknown): string | null {\n if (typeof stack !== 'string' || !stack) return null\n const frames = stack\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && STACK_FRAME.test(line))\n .slice(0, STACK_MAX_FRAMES)\n .map((line) =>\n line\n .replace(/(https?:\\/\\/[^\\s)?#]+)[?#][^\\s)]*?(?=(?::\\d+){0,2}\\)?$)/, '$1')\n .slice(0, STACK_MAX_FRAME_CHARS),\n )\n return frames.length > 0 ? frames.join('\\n') : null\n}\n\nfunction withStack(stack: string | null): { stack?: string } {\n return stack ? { stack } : {}\n}\n\nfunction stackOf(reason: unknown): string | null {\n return typeof reason === 'object' && reason !== null ? sanitizeStack((reason as { stack?: unknown }).stack) : null\n}\n\nexport function isAbortError(err: unknown): boolean {\n return typeof err === 'object' && err !== null && (err as { name?: unknown }).name === 'AbortError'\n}\n\nexport function isIgnoredUrl(url: string, ignore: readonly string[]): boolean {\n return ignore.some((prefix) => prefix.length > 0 && url.startsWith(prefix))\n}\n\n/**\n * Dom\u00EDnio registr\u00E1vel aproximado \u2014 os dois \u00FAltimos r\u00F3tulos do host.\n *\n * `app.acme.com` e `api.acme.com` \u2192 `acme.com`: produto que fala com a pr\u00F3pria\n * API em outro subdom\u00EDnio continua sendo primeira parte. Sem lista de sufixos\n * p\u00FAblicos, `foo.co.uk` e `bar.co.uk` colidem \u2014 e a colis\u00E3o erra pro lado\n * seguro, incluindo como pr\u00F3prio o que hoje j\u00E1 \u00E9 inclu\u00EDdo.\n */\nexport function registrableDomain(host: string): string {\n const labels = host.toLowerCase().split('.').filter(Boolean)\n if (labels.length <= 2) return labels.join('.')\n return labels.slice(-2).join('.')\n}\n\n/**\n * A requisi\u00E7\u00E3o \u00E9 do produto de quem instalou, ou de um terceiro?\n *\n * Fric\u00E7\u00E3o \u00E9 fric\u00E7\u00E3o DO PRODUTO. Um `google-analytics.com/g/collect` morto por\n * ad blocker n\u00E3o \u00E9 o produto falhando \u2014 \u00E9 o navegador do visitante recusando\n * um script que nem \u00E9 seu. Em 2026-09-17 esses dois dom\u00EDnios respondiam por 36\n * dos eventos de fric\u00E7\u00E3o da janela: num cliente com GA instalado e usu\u00E1rios com\n * bloqueador, isso infla a fric\u00E7\u00E3o e pode abrir oportunidade em cima de nada.\n *\n * Localhost e IP entram pela compara\u00E7\u00E3o de host exato \u2014 em desenvolvimento n\u00E3o\n * h\u00E1 dom\u00EDnio registr\u00E1vel que valha.\n */\nexport function isFirstPartyRequest(url: string, pageUrl: string, extraOrigins: readonly string[] = []): boolean {\n let target: URL\n let page: URL\n try {\n target = new URL(url, pageUrl)\n page = new URL(pageUrl)\n } catch {\n return true\n }\n if (target.protocol !== 'http:' && target.protocol !== 'https:') return true\n if (target.host === page.host) return true\n if (extraOrigins.some((o) => o.length > 0 && target.origin === o)) return true\n const targetDomain = registrableDomain(target.hostname)\n return targetDomain.length > 0 && targetDomain === registrableDomain(page.hostname)\n}\n\nexport interface RequestOutcome {\n status: number | null\n durationMs: number\n slowMs: number\n aborted?: boolean\n opaque?: boolean\n}\n\nexport function classifyRequest(outcome: RequestOutcome): 'http_error' | 'slow_request' | null {\n if (outcome.aborted) return null\n if (!outcome.opaque && (outcome.status === null || outcome.status >= 400)) return 'http_error'\n return outcome.durationMs >= outcome.slowMs ? 'slow_request' : null\n}\n\nexport function documentStatus(\n perf: { getEntriesByType?: (type: string) => unknown[] } | undefined,\n): number | null {\n try {\n const entry = perf?.getEntriesByType?.('navigation')?.[0] as { responseStatus?: unknown } | undefined\n const status = entry?.responseStatus\n return typeof status === 'number' && status > 0 ? status : null\n } catch {\n return null\n }\n}\n\ninterface FormTouch {\n form: string\n fields: Set<string>\n}\n\nfunction formKey(form: HTMLFormElement): string {\n return (\n form.id ||\n form.getAttribute('name') ||\n form.getAttribute('data-testid') ||\n stripRequestUrl(form.getAttribute('action') ?? '', location.href).replace(location.origin, '') ||\n 'form'\n )\n}\n\nfunction currentPath(): string {\n return typeof location === 'undefined' ? '/' : location.pathname || '/'\n}\n\nexport function installFrictionCapture(opts: FrictionCaptureOptions): FrictionCapture {\n const noop: FrictionCapture = { onNavigate: () => undefined, teardown: () => undefined }\n if (typeof window === 'undefined' || typeof document === 'undefined') return noop\n\n const w = window as unknown as Record<string, boolean | undefined>\n if (w[INSTALLED_FLAG]) return noop\n w[INSTALLED_FLAG] = true\n\n const emit = (kind: FrictionKind, properties: Record<string, unknown>): void => {\n try {\n opts.onFriction({ kind, properties: { path: currentPath(), ...properties } })\n } catch {\n return\n }\n }\n\n const cleanups: Array<() => void> = []\n const rage = new RageClickDetector(opts.rageClicks, opts.rageWindowMs, opts.rageRadiusPx)\n const navLoop = new NavLoopDetector(opts.navLoopWindowMs)\n const slowMs = opts.slowRequestMs ?? 3000\n const touched = new Map<HTMLFormElement, FormTouch>()\n\n const onClick = (ev: MouseEvent): void => {\n const el = ev.target instanceof Element ? (ev.target as unknown as ElementLike) : null\n if (isDeadClickTarget(el)) emit('dead_click', describeElement(el))\n if (rage.push(ev.clientX, ev.clientY, ev.timeStamp || Date.now())) {\n emit('rage_click', describeElement(el))\n }\n }\n document.addEventListener('click', onClick, true)\n cleanups.push(() => document.removeEventListener('click', onClick, true))\n\n const onError = (ev: ErrorEvent): void => {\n emit('js_error', {\n message: String(ev.message ?? '').slice(0, 200),\n ...(ev.filename ? { source: stripRequestUrl(ev.filename, location.href) } : {}),\n ...(ev.lineno ? { line: ev.lineno } : {}),\n ...(ev.colno ? { column: ev.colno } : {}),\n ...withStack(stackOf(ev.error)),\n })\n }\n window.addEventListener('error', onError)\n cleanups.push(() => window.removeEventListener('error', onError))\n\n const onRejection = (ev: PromiseRejectionEvent): void => {\n emit('js_error', {\n message: errorMessage(ev.reason).slice(0, 200),\n unhandled_rejection: true,\n ...withStack(stackOf(ev.reason)),\n })\n }\n window.addEventListener('unhandledrejection', onRejection)\n cleanups.push(() => window.removeEventListener('unhandledrejection', onRejection))\n\n const ignore = (opts.ignoreUrls ?? []).map((url) => stripRequestUrl(url, location.href))\n const apiOrigins = (opts.apiOrigins ?? []).map((o) => {\n try {\n return new URL(o, location.href).origin\n } catch {\n return ''\n }\n })\n const reportRequest = (\n url: string,\n method: string,\n started: number,\n status: number | null,\n flags: { aborted?: boolean; opaque?: boolean } = {},\n ): void => {\n const target = stripRequestUrl(url, location.href)\n if (isIgnoredUrl(target, ignore)) return\n if (!isFirstPartyRequest(target, location.href, apiOrigins)) return\n const durationMs = performance.now() - started\n const kind = classifyRequest({ status, durationMs, slowMs, ...flags })\n if (!kind) return\n emit(kind, {\n url: target,\n method,\n duration_ms: Math.round(durationMs),\n ...(flags.opaque ? {} : status !== null ? { status } : { failed: true }),\n })\n }\n\n const originalFetch = window.fetch\n if (typeof originalFetch === 'function') {\n const patched: typeof window.fetch = async (input, init) => {\n const started = performance.now()\n const url =\n typeof input === 'string' ? input : input instanceof URL ? input.href : input.url\n const method = (init?.method ?? (input instanceof Request ? input.method : 'GET')).toUpperCase()\n try {\n const res = await originalFetch(input, init)\n reportRequest(url, method, started, res.status, {\n opaque: res.type === 'opaque' || res.type === 'opaqueredirect',\n })\n return res\n } catch (err) {\n reportRequest(url, method, started, null, { aborted: isAbortError(err) })\n throw err\n }\n }\n window.fetch = patched\n cleanups.push(() => {\n window.fetch = originalFetch\n })\n }\n\n const xhrProto = typeof XMLHttpRequest === 'function' ? XMLHttpRequest.prototype : null\n if (xhrProto) {\n const originalOpen = xhrProto.open\n const originalSend = xhrProto.send\n const requests = new WeakMap<XMLHttpRequest, { method: string; url: string }>()\n xhrProto.open = function (this: XMLHttpRequest, method: string, url: string | URL, ...rest: unknown[]) {\n requests.set(this, { method: String(method).toUpperCase(), url: String(url) })\n return (originalOpen as (...args: unknown[]) => void).apply(this, [method, url, ...rest])\n } as typeof xhrProto.open\n xhrProto.send = function (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null) {\n const request = requests.get(this)\n if (request) {\n const started = performance.now()\n let aborted = false\n this.addEventListener('abort', () => {\n aborted = true\n })\n this.addEventListener('loadend', () => {\n reportRequest(request.url, request.method, started, this.status === 0 ? null : this.status, { aborted })\n })\n }\n return originalSend.call(this, body)\n }\n cleanups.push(() => {\n xhrProto.open = originalOpen\n xhrProto.send = originalSend\n })\n }\n\n const loadStatus = documentStatus(typeof performance === 'undefined' ? undefined : performance)\n if (loadStatus !== null && loadStatus >= 400) {\n emit('http_error', { document: true, status: loadStatus, url: stripRequestUrl(location.href) })\n }\n\n const onFocusIn = (ev: FocusEvent): void => {\n const el = ev.target as HTMLElement | null\n if (!el || !FORM_CONTROL_TAGS.has(tagOf(el))) return\n const form = (el as HTMLInputElement).form\n if (!form) return\n const entry = touched.get(form) ?? { form: formKey(form), fields: new Set<string>() }\n const field = (el as HTMLInputElement).name || el.id || tagOf(el)\n entry.fields.add(field)\n touched.set(form, entry)\n }\n document.addEventListener('focusin', onFocusIn, true)\n cleanups.push(() => document.removeEventListener('focusin', onFocusIn, true))\n\n const onSubmit = (ev: Event): void => {\n if (ev.target instanceof HTMLFormElement) touched.delete(ev.target)\n }\n document.addEventListener('submit', onSubmit, true)\n cleanups.push(() => document.removeEventListener('submit', onSubmit, true))\n\n const flushAbandons = (): void => {\n for (const entry of touched.values()) {\n emit('form_abandon', { form: entry.form, fields_touched: entry.fields.size })\n }\n touched.clear()\n }\n window.addEventListener('pagehide', flushAbandons)\n cleanups.push(() => window.removeEventListener('pagehide', flushAbandons))\n\n return {\n onNavigate: (path: string) => {\n flushAbandons()\n const loop = navLoop.push(path, Date.now())\n if (loop) emit('nav_loop', { from: loop.from, to: loop.to })\n },\n teardown: () => {\n for (const cleanup of cleanups) cleanup()\n touched.clear()\n w[INSTALLED_FLAG] = false\n },\n }\n}\n", "export interface PageTheme {\n font?: string\n size?: string\n fg?: string\n bg?: string\n accent?: string\n accentFg?: string\n radius?: string\n}\n\nexport interface ThemeStyleLike {\n getPropertyValue(name: string): string\n}\n\nexport interface ThemeElementLike {\n tagName: string\n getBoundingClientRect?(): { width: number; height: number }\n}\n\nexport interface ThemeDocLike {\n body: ThemeElementLike | null\n documentElement: ThemeElementLike\n querySelectorAll(selector: string): ArrayLike<ThemeElementLike>\n}\n\nexport const THEME_BUTTON_SELECTOR = 'button[type=\"submit\"],[data-testid*=\"primary\"],.btn-primary,button,[role=\"button\"],a.button'\nexport const THEME_MAX_BUTTONS = 40\nexport const THEME_KEYS: readonly (keyof PageTheme)[] = ['font', 'size', 'fg', 'bg', 'accent', 'accentFg', 'radius']\n\nconst COLOR = /^(rgba?\\([\\d.,\\s%/]{1,40}\\)|#[0-9a-fA-F]{3,8}|(?:color|oklch|oklab|hsla?|lab|lch)\\([^()]{1,60}\\))$/\n/** Dist\u00E2ncia m\u00EDnima entre o bot\u00E3o e o fundo pra valer como cor prim\u00E1ria: um bot\u00E3o branco em fundo claro n\u00E3o \u00E9 acento. */\nexport const MIN_ACCENT_CONTRAST = 60\nconst RGB = /^rgba?\\(\\s*(\\d+)[\\s,]+(\\d+)[\\s,]+(\\d+)/\n\nexport function colorDistance(a: string, b: string | undefined): number {\n const x = RGB.exec(a)\n const y = b ? RGB.exec(b) : null\n if (!x) return MIN_ACCENT_CONTRAST + 1\n if (!y) return MIN_ACCENT_CONTRAST + 1\n return Math.abs(+x[1] - +y[1]) + Math.abs(+x[2] - +y[2]) + Math.abs(+x[3] - +y[3])\n}\n\nconst TRANSPARENT = /^(transparent|rgba\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*0\\s*\\)|rgba?\\(\\s*\\d+\\s+\\d+\\s+\\d+\\s*\\/\\s*0\\s*\\))$/\n\nexport function themeVarName(key: keyof PageTheme): string {\n return `--holdy-${key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`\n}\n\nexport function cleanColor(value: string | null | undefined): string | undefined {\n const v = (value ?? '').trim()\n return v && v.length <= 80 && !TRANSPARENT.test(v) && COLOR.test(v) ? v : undefined\n}\n\nexport function cleanFont(value: string | null | undefined): string | undefined {\n const first = (value ?? '').split(',')[0].trim().replace(/^[\"']|[\"']$/g, '').trim()\n return /^[\\w\\s-]{1,60}$/.test(first) ? first : undefined\n}\n\nexport function cleanPx(value: string | null | undefined, min: number, max: number): string | undefined {\n const m = /^(\\d+(?:\\.\\d+)?)px/.exec((value ?? '').trim())\n const n = m ? Math.round(Number(m[1])) : NaN\n return n >= min && n <= max ? `${n}px` : undefined\n}\n\nfunction visible(el: ThemeElementLike): boolean {\n const r = el.getBoundingClientRect?.()\n return !r || (r.width > 0 && r.height > 0)\n}\n\nexport function readTheme(\n doc: ThemeDocLike,\n getStyle: (el: ThemeElementLike) => ThemeStyleLike,\n anchor: ThemeElementLike | null = null,\n): PageTheme | null {\n const body = doc.body\n if (!body) return null\n const bodyStyle = getStyle(body)\n const theme: PageTheme = {}\n const put = (key: keyof PageTheme, value: string | undefined) => {\n if (value) theme[key] = value\n }\n put('font', cleanFont(bodyStyle.getPropertyValue('font-family')))\n put('size', cleanPx(bodyStyle.getPropertyValue('font-size'), 10, 20))\n put('fg', cleanColor(bodyStyle.getPropertyValue('color')))\n put('bg', cleanColor(bodyStyle.getPropertyValue('background-color')) ?? cleanColor(getStyle(doc.documentElement).getPropertyValue('background-color')))\n\n const candidates = doc.querySelectorAll(THEME_BUTTON_SELECTOR)\n let button: ThemeElementLike | null = null\n let best = MIN_ACCENT_CONTRAST\n for (let i = 0; i < candidates.length && i < THEME_MAX_BUTTONS; i++) {\n const el = candidates[i]\n if (!visible(el)) continue\n const s = getStyle(el)\n const accent = cleanColor(s.getPropertyValue('background-color'))\n if (!accent || accent === theme.bg) continue\n const contrast = colorDistance(accent, theme.bg)\n if (contrast <= best) continue\n best = contrast\n put('accent', accent)\n put('accentFg', cleanColor(s.getPropertyValue('color')))\n button = el\n }\n const radiusSource = anchor && anchor.tagName.toLowerCase() === 'button' ? anchor : button\n if (radiusSource) put('radius', cleanPx(getStyle(radiusSource).getPropertyValue('border-top-left-radius'), 0, 24))\n return Object.keys(theme).length > 0 ? theme : null\n}\n\nexport function themeVars(theme: PageTheme | null | undefined): Array<[string, string]> {\n const out: Array<[string, string]> = []\n for (const key of THEME_KEYS) {\n const value = theme?.[key]\n if (value) out.push([themeVarName(key), value])\n }\n return out\n}\n\nexport function applyThemeVars(el: { style: { setProperty(name: string, value: string): void; removeProperty(name: string): void } }, theme: PageTheme | null | undefined): void {\n for (const key of THEME_KEYS) el.style.removeProperty(themeVarName(key))\n for (const [name, value] of themeVars(theme)) el.style.setProperty(name, value)\n}\n", "import { readTheme, type PageTheme } from './theme'\n\nexport const SKELETON_SELECTOR =\n 'a[href], button, input, select, textarea, [role=\"button\"], [role=\"link\"], [role=\"tab\"], [role=\"menuitem\"], [role=\"checkbox\"], [role=\"radio\"], [role=\"switch\"], [data-testid]'\nexport const SKELETON_MAX_ELEMENTS = 80\nexport const SKELETON_DELAY_MS = 1500\nconst SENT_STORAGE_KEY = 'holdy_skeletons'\nconst SENT_STORAGE_MAX = 200\n\nexport interface SkeletonRect {\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface SkeletonElementLike {\n tagName: string\n getAttribute(name: string): string | null\n getBoundingClientRect?(): SkeletonRect\n}\n\nexport interface SkeletonRootLike {\n querySelectorAll(selector: string): ArrayLike<SkeletonElementLike>\n}\n\nexport interface SkeletonViewport {\n width: number\n height: number\n scrollY: number\n}\n\nexport interface SkeletonElement {\n t: string\n r?: string\n id?: string\n n?: string\n l?: string\n k?: string\n b?: [number, number, number, number]\n}\n\nexport interface PageSkeleton {\n path: string\n hash: string\n count: number\n elements: SkeletonElement[]\n theme?: PageTheme\n}\n\nexport function fnv1a(input: string): string {\n let hash = 0x811c9dc5\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i)\n hash = Math.imul(hash, 0x01000193) >>> 0\n }\n return hash.toString(16).padStart(8, '0')\n}\n\nfunction attr(el: SkeletonElementLike, name: string, max: number): string | undefined {\n const value = el.getAttribute(name)\n if (!value) return undefined\n const trimmed = value.replace(/\\s+/g, ' ').trim().slice(0, max)\n return trimmed || undefined\n}\n\nfunction isVisible(el: SkeletonElementLike): boolean {\n if (!el.getBoundingClientRect) return true\n const rect = el.getBoundingClientRect()\n return rect.width > 0 && rect.height > 0\n}\n\nfunction relativeBox(rect: SkeletonRect, viewport: SkeletonViewport): [number, number, number, number] {\n const pct = (value: number, base: number) => (base > 0 ? Math.max(0, Math.min(100, Math.round((value / base) * 100))) : 0)\n return [pct(rect.x, viewport.width), pct(rect.y + viewport.scrollY, viewport.height), pct(rect.width, viewport.width), pct(rect.height, viewport.height)]\n}\n\nexport function describeSkeletonElement(el: SkeletonElementLike, viewport: SkeletonViewport | null): SkeletonElement {\n const out: SkeletonElement = { t: el.tagName.toLowerCase() }\n const role = attr(el, 'role', 40)\n if (role) out.r = role\n const testid = attr(el, 'data-testid', 80)\n if (testid) out.id = testid\n const name = attr(el, 'name', 80)\n if (name) out.n = name\n const label = attr(el, 'aria-label', 80)\n if (label) out.l = label\n if (out.t === 'input' || out.t === 'button') {\n const type = attr(el, 'type', 20)\n if (type) out.k = type.toLowerCase()\n }\n if (viewport && el.getBoundingClientRect) out.b = relativeBox(el.getBoundingClientRect(), viewport)\n return out\n}\n\nexport function collectSkeleton(\n root: SkeletonRootLike,\n path: string,\n viewport: SkeletonViewport | null,\n theme: PageTheme | null = null,\n): PageSkeleton {\n const found = root.querySelectorAll(SKELETON_SELECTOR)\n const visible: SkeletonElementLike[] = []\n for (let i = 0; i < found.length; i++) {\n const el = found[i]\n if (el.tagName.toLowerCase() === 'input' && (el.getAttribute('type') ?? '').toLowerCase() === 'hidden') continue\n if (!isVisible(el)) continue\n visible.push(el)\n }\n const elements = visible.slice(0, SKELETON_MAX_ELEMENTS).map((el) => describeSkeletonElement(el, viewport))\n const structural = elements.map(({ b: _b, ...rest }) => rest)\n return { path, hash: fnv1a(JSON.stringify(structural)), count: visible.length, elements, ...(theme ? { theme } : {}) }\n}\n\nexport interface SkeletonCaptureOptions {\n onSkeleton: (skeleton: PageSkeleton) => void\n delayMs?: number\n}\n\nexport interface SkeletonCapture {\n onNavigate: (path: string) => void\n teardown: () => void\n}\n\nfunction loadSent(): Set<string> {\n try {\n const raw = sessionStorage.getItem(SENT_STORAGE_KEY)\n const list = raw ? (JSON.parse(raw) as unknown) : []\n return new Set(Array.isArray(list) ? list.filter((x): x is string => typeof x === 'string') : [])\n } catch {\n return new Set()\n }\n}\n\nfunction saveSent(sent: Set<string>): void {\n try {\n sessionStorage.setItem(SENT_STORAGE_KEY, JSON.stringify([...sent].slice(-SENT_STORAGE_MAX)))\n } catch {\n return\n }\n}\n\nexport function installSkeletonCapture(opts: SkeletonCaptureOptions): SkeletonCapture {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return { onNavigate: () => undefined, teardown: () => undefined }\n }\n const delay = opts.delayMs ?? SKELETON_DELAY_MS\n const sent = loadSent()\n let pending: ReturnType<typeof setTimeout> | null = null\n\n const capture = (path: string): void => {\n pending = null\n if (location.pathname !== path) return\n try {\n const viewport: SkeletonViewport = {\n width: window.innerWidth,\n height: Math.max(document.documentElement.scrollHeight, window.innerHeight),\n scrollY: window.scrollY,\n }\n const theme = readTheme(document, (el) => window.getComputedStyle(el as Element))\n const skeleton = collectSkeleton(document, path, viewport, theme)\n const key = `${path}:${skeleton.hash}`\n if (sent.has(key)) return\n sent.add(key)\n saveSent(sent)\n opts.onSkeleton(skeleton)\n } catch {\n return\n }\n }\n\n return {\n onNavigate: (path: string) => {\n if (pending) clearTimeout(pending)\n pending = setTimeout(() => capture(path), delay)\n },\n teardown: () => {\n if (pending) clearTimeout(pending)\n pending = null\n },\n }\n}\n", "/**\n * Contexto de ambiente do browser \u00B7 @holdyapp/sdk/web.\n *\n * Vai em `context` de todo evento, nunca em `properties`: properties \u00E9 o\n * vocabul\u00E1rio do produto do cliente (`workflow_key`, `plan`), context \u00E9 o que o\n * SDK observou sozinho. A Data layer persiste os dois (facts.context, 00247) e\n * a leitura de dimens\u00E3o consulta os dois.\n *\n * Tr\u00EAs decis\u00F5es que definem se esse dado \u00E9 \u00FAtil ou lixo:\n * \u00B7 `url` sai sem query e sem hash. Href cru tem uma varia\u00E7\u00E3o por sess\u00E3o, e\n * dimens\u00E3o com cardinalidade quase-\u00FAnica \u00E9 descartada na leitura \u2014 a\n * p\u00E1gina vira ru\u00EDdo exatamente por excesso de precis\u00E3o.\n * \u00B7 utm \u00E9 capturado na primeira p\u00E1gina e carregado pelo resto da sess\u00E3o.\n * Atribui\u00E7\u00E3o que s\u00F3 existe no primeiro evento n\u00E3o responde nada.\n * \u00B7 referrer s\u00F3 quando \u00E9 externo. Navega\u00E7\u00E3o interna preenchendo \"Origem do\n * tr\u00E1fego\" com o pr\u00F3prio dom\u00EDnio esconde a origem real.\n *\n * Tudo aqui \u00E9 best-effort: browser em modo privativo, SSR e webview sem\n * storage precisam funcionar. Nenhuma fun\u00E7\u00E3o lan\u00E7a.\n */\n\nexport type WebContext = Record<string, string>\n\nconst UTM_KEYS = [\n 'utm_source',\n 'utm_medium',\n 'utm_campaign',\n 'utm_term',\n 'utm_content',\n] as const\n\nconst SESSION_STORAGE_KEY = 'holdy_session'\nconst ATTRIBUTION_STORAGE_KEY = 'holdy_attribution'\n\n/* \u2500\u2500 URL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/** `https://app.x.com/a/b?q=1#z` \u2192 `https://app.x.com/a/b`. */\nexport function stripUrl(href: string): string | null {\n try {\n const url = new URL(href)\n return `${url.origin}${url.pathname}`\n } catch {\n return null\n }\n}\n\n/** Par\u00E2metros de campanha presentes na URL, j\u00E1 em lowercase. */\nexport function parseUtm(href: string): WebContext {\n const out: WebContext = {}\n try {\n const params = new URL(href).searchParams\n for (const key of UTM_KEYS) {\n const value = params.get(key)?.trim()\n if (value) out[key] = value.toLowerCase().slice(0, 120)\n }\n } catch {\n // href inv\u00E1lido \u2014 sem utm, sem drama.\n }\n return out\n}\n\n/* \u2500\u2500 User agent \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\ninterface UaParts {\n browser?: string\n os?: string\n device?: string\n}\n\n/**\n * Fatia m\u00EDnima do UA: navegador, sistema e classe de dispositivo.\n *\n * N\u00E3o \u00E9 biblioteca de UA parsing e n\u00E3o deve virar uma \u2014 o valor est\u00E1 em\n * separar mobile de desktop e Safari de Chrome, n\u00E3o em cravar a vers\u00E3o.\n */\nexport function parseUserAgent(ua: string): UaParts {\n if (!ua) return {}\n const s = ua.toLowerCase()\n\n const browser = s.includes('edg/')\n ? 'Edge'\n : s.includes('opr/') || s.includes('opera')\n ? 'Opera'\n : s.includes('samsungbrowser')\n ? 'Samsung Internet'\n : s.includes('firefox') || s.includes('fxios')\n ? 'Firefox'\n : s.includes('chrome') || s.includes('crios')\n ? 'Chrome'\n : s.includes('safari')\n ? 'Safari'\n : undefined\n\n const os = s.includes('iphone') || s.includes('ipad') || s.includes('ipod')\n ? 'iOS'\n : s.includes('android')\n ? 'Android'\n : s.includes('windows')\n ? 'Windows'\n : s.includes('mac os') || s.includes('macintosh')\n ? 'macOS'\n : s.includes('cros')\n ? 'ChromeOS'\n : s.includes('linux')\n ? 'Linux'\n : undefined\n\n // iPad moderno se declara macOS; a pista que sobra \u00E9 o suporte a toque, que\n // o parser puro n\u00E3o v\u00EA. Tablet aqui cobre o caso declarado no UA.\n const device = s.includes('ipad') || (s.includes('android') && !s.includes('mobile'))\n ? 'tablet'\n : s.includes('mobi') || s.includes('iphone') || s.includes('ipod')\n ? 'mobile'\n : 'desktop'\n\n return {\n ...(browser ? { browser } : {}),\n ...(os ? { os } : {}),\n device,\n }\n}\n\n/* \u2500\u2500 Storage \u00B7 nunca lan\u00E7a \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction readStorage(storage: 'session' | 'local', key: string): string | null {\n try {\n const s = storage === 'session' ? sessionStorage : localStorage\n return s.getItem(key)\n } catch {\n return null\n }\n}\n\nfunction writeStorage(storage: 'session' | 'local', key: string, value: string): void {\n try {\n const s = storage === 'session' ? sessionStorage : localStorage\n s.setItem(key, value)\n } catch {\n // Modo privativo / storage bloqueado \u2014 o contexto degrada, o evento segue.\n }\n}\n\nfunction randomId(): string {\n try {\n return crypto.randomUUID()\n } catch {\n return `hol-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`\n }\n}\n\nexport function clearSessionId(): void {\n try {\n sessionStorage.removeItem(SESSION_STORAGE_KEY)\n } catch {\n // storage indispon\u00EDvel (SSR/privacy mode) \u2014 ok\n }\n}\n\n/** ID da sess\u00E3o de browser \u00B7 vive enquanto a aba viver. */\nexport function resolveSessionId(): string {\n const existing = readStorage('session', SESSION_STORAGE_KEY)\n if (existing) return existing\n const fresh = randomId()\n writeStorage('session', SESSION_STORAGE_KEY, fresh)\n return fresh\n}\n\n/**\n * Atribui\u00E7\u00E3o da sess\u00E3o: utm da primeira p\u00E1gina + referrer externo de entrada.\n * Gravada uma vez e repetida em todo evento da sess\u00E3o.\n */\nexport function resolveAttribution(href: string, referrer: string, currentHost: string): WebContext {\n const stored = readStorage('session', ATTRIBUTION_STORAGE_KEY)\n if (stored) {\n try {\n return JSON.parse(stored) as WebContext\n } catch {\n // Valor corrompido \u2014 recalcula por cima.\n }\n }\n\n const attribution: WebContext = { ...parseUtm(href) }\n\n const referrerHost = hostOf(referrer)\n // Referrer interno n\u00E3o \u00E9 origem de tr\u00E1fego, \u00E9 navega\u00E7\u00E3o.\n if (referrerHost && referrerHost !== currentHost) {\n const clean = stripUrl(referrer)\n if (clean) attribution.referrer = clean\n attribution.referrer_host = referrerHost\n }\n\n writeStorage('session', ATTRIBUTION_STORAGE_KEY, JSON.stringify(attribution))\n return attribution\n}\n\nfunction hostOf(href: string): string | null {\n try {\n return new URL(href).hostname.toLowerCase() || null\n } catch {\n return null\n }\n}\n\n/* \u2500\u2500 Montagem \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/**\n * Contexto completo do evento atual. Fora do browser devolve `{}` \u2014 o SDK\n * server tem o pr\u00F3prio caminho e n\u00E3o deve inventar ambiente.\n */\nexport function buildWebContext(): WebContext {\n if (typeof window === 'undefined' || typeof location === 'undefined') return {}\n\n const href = location.href\n const referrer = typeof document !== 'undefined' ? document.referrer : ''\n const host = location.hostname.toLowerCase()\n\n const ua = typeof navigator !== 'undefined' ? navigator.userAgent : ''\n const { browser, os, device } = parseUserAgent(ua)\n\n const url = stripUrl(href)\n\n return {\n ...(url ? { url } : {}),\n path: location.pathname || '/',\n host,\n ...(browser ? { browser } : {}),\n ...(os ? { os } : {}),\n ...(device ? { device } : {}),\n ...(typeof navigator !== 'undefined' && navigator.language\n ? { locale: navigator.language }\n : {}),\n session_id: resolveSessionId(),\n ...resolveAttribution(href, referrer, host),\n }\n}\n", "/**\n * O card da dica e da pergunta, como o SDK desenha no produto do cliente.\n * O painel da Holdy importa daqui pra pr\u00E9via: a mesma folha, nunca uma c\u00F3pia.\n * As vari\u00E1veis --holdy-* chegam do tema lido na p\u00E1gina (theme.ts): fonte,\n * cores, raio e cor do bot\u00E3o prim\u00E1rio do produto do cliente. Sem tema, o\n * card cai no visual pr\u00F3prio (escuro no claro, claro no escuro).\n */\nexport const TIP_CSS = `:host{all:initial;--h-bg:#111;--h-fg:#fff;--h-accent:#fff;--h-accent-fg:#111;--h-border:transparent}\n@media (prefers-color-scheme:dark){:host{--h-bg:#fff;--h-fg:#111;--h-accent:#111;--h-accent-fg:#fff}}\n.tip{position:fixed;box-sizing:border-box;max-width:280px;padding:10px 12px;border-radius:var(--holdy-radius,8px);background:var(--holdy-bg,var(--h-bg));color:var(--holdy-fg,var(--h-fg));border:1px solid color-mix(in srgb,var(--holdy-fg,var(--h-fg)) 14%,transparent);font:var(--holdy-size,13px)/1.45 var(--holdy-font,system-ui),system-ui,-apple-system,sans-serif;box-shadow:0 8px 24px rgba(0,0,0,.18);pointer-events:auto;display:flex;gap:10px;align-items:flex-start}\n.tip p{margin:0;flex:1}\n.tip button{all:unset;cursor:pointer;opacity:.7;font-size:15px;line-height:1;color:inherit}\n.tip button:hover,.tip button:focus-visible{opacity:1}\n.ask{flex-direction:column;width:300px;max-width:calc(100vw - 16px);gap:8px}\n.ask .head{display:flex;gap:10px;align-items:flex-start;width:100%}\n.ask textarea{all:unset;box-sizing:border-box;width:100%;min-height:56px;padding:8px;border-radius:calc(var(--holdy-radius,8px) * .75);background:color-mix(in srgb,var(--holdy-fg,var(--h-fg)) 8%,transparent);color:inherit;font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;cursor:text}\n.ask textarea:focus-visible{outline:2px solid color-mix(in srgb,var(--holdy-fg,var(--h-fg)) 45%,transparent)}\n.ask .send{align-self:flex-end;padding:5px 12px;border-radius:calc(var(--holdy-radius,8px) * .75);background:var(--holdy-accent,var(--h-accent));color:var(--holdy-accent-fg,var(--h-accent-fg));font-size:12.5px;font-weight:500;opacity:1}\n.ask .send[disabled]{opacity:.4;cursor:default}\n.list{flex-direction:column;width:300px;max-width:calc(100vw - 16px);gap:8px}\n.list .head{display:flex;gap:10px;align-items:flex-start;width:100%}\n.list .head p{display:flex;justify-content:space-between;gap:10px;align-items:baseline}\n.list .count{opacity:.7;font-size:12px;white-space:nowrap}\n.list ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px;width:100%}\n.list li{display:flex;gap:8px;align-items:flex-start}\n.list li.done{opacity:.55;text-decoration:line-through}\n.list .mark{flex:none;width:16px;height:16px;border-radius:4px;border:1px solid color-mix(in srgb,var(--holdy-fg,var(--h-fg)) 45%,transparent);font-size:11px;line-height:16px;text-align:center}\n.list li.done .mark{background:var(--holdy-accent,var(--h-accent));color:var(--holdy-accent-fg,var(--h-accent-fg));border-color:var(--holdy-accent,var(--h-accent))}\n.list.folded ul{display:none}\n.list.folded{width:auto}\n.preview{flex:none;order:-1;width:100%;font-size:11px;opacity:.7}\n.tip:has(.preview){flex-wrap:wrap;row-gap:4px}`\n", "export type ChangeArm = 'change' | 'holdout'\n\nfunction fnv1a(input: string): number {\n let hash = 0x811c9dc5\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i)\n hash = Math.imul(hash, 0x01000193) >>> 0\n }\n return hash >>> 0\n}\n\nexport function changeBucket(changeId: string, accountKey: string): number {\n return fnv1a(`${changeId}:${accountKey}`) % 100\n}\n\nexport function changeArm(changeId: string, accountKey: string, holdoutPct: number): ChangeArm {\n return changeBucket(changeId, accountKey) < holdoutPct ? 'holdout' : 'change'\n}\n\nexport function matchesPathTemplate(template: string, path: string): boolean {\n const t = template.split(/[?#]/)[0].split('/').filter(Boolean)\n const p = path.split(/[?#]/)[0].split('/').filter(Boolean)\n if (t.length !== p.length) return false\n return t.every((segment, i) => segment.startsWith(':') || segment === p[i])\n}\n", "import { TIP_CSS } from './tip-css'\nimport { applyThemeVars, readTheme } from './theme'\nimport { changeArm, matchesPathTemplate, type ChangeArm } from './arm'\n\nexport type ChangeAnchor =\n | { kind: 'selector'; value: string }\n | { kind: 'text'; value: string }\n | { kind: 'page' }\n\nexport interface ChecklistItem {\n definition_name: string\n label: string\n events: string[]\n}\n\nexport interface ProductChange {\n id: string\n kind: 'copy' | 'guidance' | 'question' | 'checklist'\n path: string\n anchor: ChangeAnchor\n expected_text: string | null\n content: { text: string; items?: ChecklistItem[] }\n holdout_pct: number\n plan_id?: string\n}\n\nexport interface ProductChangesOptions {\n baseUrl: string\n apiKey: string\n getAccountKey: () => string | null\n track: (name: string, properties: Record<string, unknown>) => void\n debug?: boolean\n}\n\nexport interface ProductChangesHandle {\n onNavigate(): void\n /** Evento do produto: marca na hora o passo do checklist que ele satisfaz; o servidor confirma depois. */\n onEvent(name: string): void\n refresh(): Promise<void>\n teardown(): void\n}\n\nconst REFRESH_MS = 5 * 60 * 1000\nconst NAV_REFRESH_MS = 60 * 1000\nconst SCAN_DEBOUNCE_MS = 250\nconst SEEN_KEY = 'holdy_changes_seen'\nconst DISMISSED_KEY = 'holdy_changes_dismissed'\nconst TIP_GAP_PX = 8\nconst ANSWERED_KEY = 'holdy_questions_answered'\nconst FOLDED_KEY = 'holdy_checklist_folded'\nconst COMPLETED_KEY = 'holdy_checklist_completed'\nconst PROGRESS_REFRESH_MS = 60 * 1000\nexport const VOICE_EVENT = '$voice'\nexport const MAX_ANSWER_CHARS = 1000\nconst THANKS_MS = 1600\nexport const PREVIEW_PARAM = 'holdy_preview'\nconst PREVIEW_KEY = 'holdy_preview'\nconst PREVIEW_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\n\nexport function normalizeText(text: string): string {\n return text.replace(/\\s+/g, ' ').trim()\n}\n\nexport function parseChanges(body: unknown): ProductChange[] {\n const list = (body as { changes?: unknown } | null)?.changes\n return Array.isArray(list) ? list.filter(isChange) : []\n}\n\nfunction isAnchor(value: unknown): value is ChangeAnchor {\n const a = value as { kind?: unknown; value?: unknown } | null\n if (a?.kind === 'page') return true\n return (a?.kind === 'selector' || a?.kind === 'text') && typeof a.value === 'string' && a.value.length > 0\n}\n\nfunction isItem(value: unknown): value is ChecklistItem {\n const i = value as ChecklistItem | null\n return (\n typeof i?.definition_name === 'string' &&\n typeof i.label === 'string' &&\n Array.isArray(i.events) &&\n i.events.every((e) => typeof e === 'string')\n )\n}\n\nfunction isChange(value: unknown): value is ProductChange {\n const c = value as ProductChange | null\n return (\n typeof c?.id === 'string' &&\n (c.kind === 'copy' ||\n c.kind === 'guidance' ||\n (c.kind === 'question' && typeof c.plan_id === 'string') ||\n (c.kind === 'checklist' && Array.isArray(c.content?.items) && c.content.items.length > 0 && c.content.items.every(isItem))) &&\n typeof c.path === 'string' &&\n isAnchor(c.anchor) &&\n typeof c.content?.text === 'string' &&\n typeof c.holdout_pct === 'number'\n )\n}\n\nexport function changesForPage(\n changes: readonly ProductChange[],\n path: string,\n accountKey: string | null,\n previewId: string | null = null,\n): Array<{ change: ProductChange; arm: ChangeArm; preview: boolean }> {\n // O checklist acompanha a conta pelo produto inteiro: o molde de p\u00E1gina \u00E9\n // s\u00F3 onde ele nasceu, n\u00E3o onde aparece.\n return changes\n .filter((c) => c.kind === 'checklist' || matchesPathTemplate(c.path, path))\n .flatMap((change): Array<{ change: ProductChange; arm: ChangeArm; preview: boolean }> => {\n if (change.id === previewId) return [{ change, arm: 'change', preview: true }]\n if (!accountKey) return []\n return [{ change, arm: changeArm(change.id, accountKey, change.holdout_pct), preview: false }]\n })\n}\n\nexport function resolvePreviewId(search: string, store: Pick<Storage, 'getItem' | 'setItem' | 'removeItem'> | undefined): string | null {\n let asked: string | null = null\n try {\n asked = new URLSearchParams(search).get(PREVIEW_PARAM)\n } catch {\n asked = null\n }\n try {\n if (asked !== null) {\n if (PREVIEW_ID.test(asked)) {\n store?.setItem(PREVIEW_KEY, asked)\n return asked\n }\n store?.removeItem(PREVIEW_KEY)\n return null\n }\n const kept = store?.getItem(PREVIEW_KEY) ?? null\n return kept && PREVIEW_ID.test(kept) ? kept : null\n } catch {\n return asked !== null && PREVIEW_ID.test(asked) ? asked : null\n }\n}\n\nfunction storage(kind: 'local' | 'session'): Storage | undefined {\n try {\n return kind === 'local' ? window.localStorage : window.sessionStorage\n } catch {\n return undefined\n }\n}\n\nfunction readSet(store: Storage | undefined, key: string): Set<string> {\n try {\n return new Set(JSON.parse(store?.getItem(key) ?? '[]') as string[])\n } catch {\n return new Set()\n }\n}\n\nfunction addToSet(store: Storage | undefined, key: string, value: string): void {\n try {\n const set = readSet(store, key)\n set.add(value)\n store?.setItem(key, JSON.stringify([...set].slice(-200)))\n } catch {\n return\n }\n}\n\nfunction query(selector: string): Element | null {\n try {\n return document.querySelector(selector)\n } catch {\n return null\n }\n}\n\nconst TEXT_ANCHOR_TAGS = 'button,a,[role=\"button\"],label,summary,h1,h2,h3,h4,li,td,th,p,span,strong'\nconst TEXT_ANCHOR_SCAN_LIMIT = 3000\n\nexport function findByText(value: string): Element | null {\n const wanted = normalizeText(value)\n let best: Element | null = null\n let bestLength = Number.POSITIVE_INFINITY\n const nodes = document.querySelectorAll(TEXT_ANCHOR_TAGS)\n const total = Math.min(nodes.length, TEXT_ANCHOR_SCAN_LIMIT)\n for (let i = 0; i < total; i += 1) {\n const el = nodes[i]\n const raw = el.textContent ?? ''\n if (raw.length >= bestLength || normalizeText(raw) !== wanted) continue\n best = el\n bestLength = raw.length\n }\n return best\n}\n\nfunction findAnchor(anchor: ChangeAnchor): Element | null {\n if (anchor.kind === 'page') return null\n return anchor.kind === 'selector' ? query(anchor.value) : findByText(anchor.value)\n}\n\nfunction findTextNode(el: Element, match: (text: string) => boolean): Text | null {\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT)\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n if (match(normalizeText(node.textContent ?? ''))) return node as Text\n }\n return null\n}\n\ninterface AppliedCopy {\n node: Text\n original: string\n next: string\n}\n\nexport function installProductChanges(opts: ProductChangesOptions): ProductChangesHandle {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return { onNavigate: () => undefined, onEvent: () => undefined, refresh: async () => undefined, teardown: () => undefined }\n }\n\n let changes: ProductChange[] = []\n let lastFetch = 0\n let timer: ReturnType<typeof setTimeout> | null = null\n let root: ShadowRoot | null = null\n let host: HTMLElement | null = null\n const copies = new Map<string, AppliedCopy>()\n const tips = new Map<string, () => void>()\n const progress = new Map<string, Set<string>>()\n const progressAt = new Map<string, number>()\n const lists = new Map<string, () => void>()\n let fetchedForKey: string | null = null\n let previewId = resolvePreviewId(location.search, storage('session'))\n\n const log = (message: string): void => {\n if (opts.debug) console.warn(`[holdy] ${message}`)\n }\n\n const expose = (change: ProductChange, arm: ChangeArm): void => {\n const key = `${change.id}:${arm}`\n const session = storage('session')\n if (readSet(session, SEEN_KEY).has(key)) return\n addToSet(session, SEEN_KEY, key)\n opts.track('$change_exposure', { change_id: change.id, arm, kind: change.kind })\n }\n\n const eligibleCopyNode = (el: Element, change: ProductChange): Text | null => {\n const expected = change.expected_text ? normalizeText(change.expected_text) : null\n const next = normalizeText(change.content.text)\n return findTextNode(el, (text) => text.length > 0 && (text === next || expected === null || text === expected))\n }\n\n const applyCopy = (el: Element, change: ProductChange): boolean => {\n const next = normalizeText(change.content.text)\n const current = copies.get(change.id)\n if (current && current.node.isConnected && normalizeText(current.node.textContent ?? '') === next) return true\n const node = eligibleCopyNode(el, change)\n if (!node) return false\n const text = node.textContent ?? ''\n if (normalizeText(text) !== next) {\n copies.set(change.id, { node, original: text, next: change.content.text })\n node.textContent = text.replace(text.trim(), change.content.text)\n }\n return true\n }\n\n const restoreCopy = (id: string): void => {\n const applied = copies.get(id)\n if (!applied) return\n if (applied.node.isConnected && normalizeText(applied.node.textContent ?? '') === normalizeText(applied.next)) {\n applied.node.textContent = applied.original\n }\n copies.delete(id)\n }\n\n const ensureRoot = (): ShadowRoot | null => {\n if (root) return root\n if (!document.body) return null\n host = document.createElement('holdy-changes')\n host.setAttribute('data-holdy-root', '1')\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none'\n root = host.attachShadow({ mode: 'closed' })\n const style = document.createElement('style')\n style.textContent = TIP_CSS\n root.appendChild(style)\n document.body.appendChild(host)\n return root\n }\n\n let dismissedPreview = false\n\n const previewTag = (): HTMLElement => {\n const tag = document.createElement('span')\n tag.className = 'preview'\n tag.textContent = 'Pr\u00E9via, s\u00F3 voc\u00EA v\u00EA'\n return tag\n }\n\n const showTip = (anchor: Element | null, change: ProductChange, preview: boolean): boolean => {\n if (tips.has(change.id)) return true\n if (!preview && readSet(storage('local'), DISMISSED_KEY).has(change.id)) return true\n const asking = change.kind === 'question'\n if (!preview && asking && readSet(storage('local'), ANSWERED_KEY).has(change.id)) return true\n const shadow = ensureRoot()\n if (!shadow) return false\n if (host) applyThemeVars(host, readTheme(document, (el) => window.getComputedStyle(el as Element), anchor))\n\n const card = document.createElement('div')\n card.className = asking ? 'tip ask' : 'tip'\n card.setAttribute('role', asking ? 'dialog' : 'tooltip')\n const text = document.createElement('p')\n text.textContent = change.content.text\n const close = document.createElement('button')\n close.type = 'button'\n close.setAttribute('aria-label', 'Fechar')\n close.textContent = '\u00D7'\n if (asking) {\n const head = document.createElement('div')\n head.className = 'head'\n head.append(text, close)\n const input = document.createElement('textarea')\n input.maxLength = MAX_ANSWER_CHARS\n input.setAttribute('aria-label', change.content.text)\n const send = document.createElement('button')\n send.type = 'button'\n send.className = 'send'\n send.textContent = 'Enviar'\n send.disabled = true\n input.addEventListener('input', () => {\n send.disabled = input.value.trim().length === 0\n })\n send.addEventListener('click', () => {\n const answer = input.value.trim().slice(0, MAX_ANSWER_CHARS)\n if (!answer) return\n if (!preview) {\n addToSet(storage('local'), ANSWERED_KEY, change.id)\n opts.track(VOICE_EVENT, {\n question: change.content.text,\n text: answer,\n action_plan_id: change.plan_id,\n change_id: change.id,\n path: location.pathname,\n })\n }\n card.replaceChildren(Object.assign(document.createElement('p'), { textContent: 'Obrigado pela resposta.' }))\n setTimeout(remove, THANKS_MS)\n })\n card.append(head, input, send)\n } else {\n card.append(text, close)\n }\n if (preview) card.prepend(previewTag())\n card.style.top = '-9999px'\n card.style.left = '-9999px'\n shadow.appendChild(card)\n\n const remove = (): void => {\n card.remove()\n window.removeEventListener('scroll', position, true)\n window.removeEventListener('resize', position)\n tips.delete(change.id)\n }\n\n function position(): void {\n if (!anchor) {\n const corner = card.getBoundingClientRect()\n card.style.top = `${Math.max(8, window.innerHeight - corner.height - 16)}px`\n card.style.left = `${Math.max(8, window.innerWidth - corner.width - 16)}px`\n return\n }\n if (!anchor.isConnected) {\n remove()\n return\n }\n const a = anchor.getBoundingClientRect()\n const c = card.getBoundingClientRect()\n let top = a.bottom + TIP_GAP_PX\n if (top + c.height > window.innerHeight - 8) top = a.top - c.height - TIP_GAP_PX\n const left = Math.min(Math.max(8, a.left + a.width / 2 - c.width / 2), window.innerWidth - c.width - 8)\n card.style.top = `${Math.max(8, top)}px`\n card.style.left = `${Math.max(8, left)}px`\n }\n\n close.addEventListener('click', () => {\n if (preview) {\n dismissedPreview = true\n remove()\n return\n }\n addToSet(storage('local'), DISMISSED_KEY, change.id)\n opts.track('$change_dismissed', { change_id: change.id, kind: change.kind })\n remove()\n })\n tips.set(change.id, remove)\n requestAnimationFrame(position)\n window.addEventListener('scroll', position, true)\n window.addEventListener('resize', position)\n return true\n }\n\n const doneOf = (change: ProductChange): Set<string> => progress.get(change.id) ?? new Set()\n\n const allDone = (change: ProductChange): boolean => {\n const done = doneOf(change)\n return (change.content.items ?? []).every((i) => done.has(i.definition_name))\n }\n\n const fetchProgress = async (change: ProductChange): Promise<void> => {\n const account = opts.getAccountKey()\n if (!account) return\n const last = progressAt.get(change.id) ?? 0\n if (Date.now() - last < PROGRESS_REFRESH_MS) return\n progressAt.set(change.id, Date.now())\n try {\n const res = await fetch(\n `${opts.baseUrl}/runtime/checklist?change_id=${encodeURIComponent(change.id)}&account=${encodeURIComponent(account)}`,\n { headers: { Authorization: `Bearer ${opts.apiKey}` } },\n )\n if (!res.ok) return\n const body = (await res.json()) as { done?: unknown }\n const done = Array.isArray(body.done) ? body.done.filter((d): d is string => typeof d === 'string') : []\n const set = doneOf(change)\n for (const d of done) set.add(d)\n progress.set(change.id, set)\n lists.get(change.id)?.()\n } catch (err) {\n log(`checklist progress error: ${(err as Error).message}`)\n }\n }\n\n const showChecklist = (change: ProductChange, preview: boolean): boolean => {\n if (lists.has(change.id)) return true\n if (!preview && readSet(storage('local'), COMPLETED_KEY).has(change.id)) return true\n const shadow = ensureRoot()\n if (!shadow) return false\n const items = change.content.items ?? []\n\n const card = document.createElement('div')\n card.className = 'tip list'\n card.setAttribute('role', 'region')\n card.setAttribute('aria-label', change.content.text)\n const head = document.createElement('div')\n head.className = 'head'\n const title = document.createElement('p')\n const strong = document.createElement('strong')\n strong.textContent = change.content.text\n const count = document.createElement('span')\n count.className = 'count'\n title.append(strong, count)\n const fold = document.createElement('button')\n fold.type = 'button'\n head.append(title, fold)\n const list = document.createElement('ul')\n card.append(head, list)\n if (preview) card.prepend(previewTag())\n card.style.position = 'fixed'\n card.style.right = '16px'\n card.style.bottom = '16px'\n shadow.appendChild(card)\n\n const remove = (): void => {\n card.remove()\n lists.delete(change.id)\n }\n\n const render = (): void => {\n const done = doneOf(change)\n const n = items.filter((i) => done.has(i.definition_name)).length\n count.textContent = `${n} de ${items.length}`\n const folded = readSet(storage('local'), FOLDED_KEY).has(change.id)\n card.classList.toggle('folded', folded)\n fold.textContent = folded ? '+' : '\u2013'\n fold.setAttribute('aria-label', folded ? 'Abrir' : 'Recolher')\n list.replaceChildren(\n ...items.map((item) => {\n const li = document.createElement('li')\n const isDone = done.has(item.definition_name)\n if (isDone) li.className = 'done'\n const mark = document.createElement('span')\n mark.className = 'mark'\n mark.setAttribute('aria-hidden', 'true')\n mark.textContent = isDone ? '\u2713' : ''\n const label = document.createElement('span')\n label.textContent = item.label\n li.append(mark, label)\n return li\n }),\n )\n if (!preview && n === items.length && items.length > 0) {\n addToSet(storage('local'), COMPLETED_KEY, change.id)\n opts.track('$checklist_completed', { change_id: change.id })\n remove()\n }\n }\n\n fold.addEventListener('click', () => {\n const store = storage('local')\n const set = readSet(store, FOLDED_KEY)\n if (set.has(change.id)) set.delete(change.id)\n else set.add(change.id)\n try {\n store?.setItem(FOLDED_KEY, JSON.stringify([...set].slice(-200)))\n } catch {\n /* storage indispon\u00EDvel */\n }\n render()\n })\n\n lists.set(change.id, render)\n render()\n void fetchProgress(change)\n return true\n }\n\n const scan = (): void => {\n timer = null\n const active = changesForPage(changes, location.pathname, opts.getAccountKey(), previewId)\n const activeIds = new Set(active.map((a) => a.change.id))\n for (const id of [...copies.keys()]) if (!activeIds.has(id)) restoreCopy(id)\n for (const [id, remove] of [...tips]) if (!activeIds.has(id)) remove()\n for (const [id, render] of [...lists]) {\n if (!activeIds.has(id)) {\n lists.delete(id)\n render()\n }\n }\n\n for (const { change, arm, preview } of active) {\n const el = findAnchor(change.anchor)\n if (!el && change.anchor.kind !== 'page') {\n if (preview) log(`preview: \u00E2ncora n\u00E3o encontrada em ${location.pathname}`)\n continue\n }\n if (preview) {\n if (change.kind === 'checklist') showChecklist(change, true)\n else if (change.kind === 'copy') {\n if (el) applyCopy(el, change)\n } else if (!dismissedPreview) showTip(el, change, true)\n continue\n }\n if (change.kind === 'checklist') {\n if (arm === 'holdout' || allDone(change) || showChecklist(change, false)) expose(change, arm)\n if (arm === 'change') void fetchProgress(change)\n } else if (change.kind === 'copy') {\n if (!el) continue\n const shown = arm === 'change' ? applyCopy(el, change) : eligibleCopyNode(el, change) !== null\n if (shown) expose(change, arm)\n } else if (arm === 'holdout' || showTip(el, change, false)) {\n expose(change, arm)\n }\n }\n }\n\n const schedule = (): void => {\n if (timer === null) timer = setTimeout(scan, SCAN_DEBOUNCE_MS)\n }\n\n const refresh = async (): Promise<void> => {\n lastFetch = Date.now()\n const account = opts.getAccountKey()\n fetchedForKey = account\n const params = new URLSearchParams()\n if (account) params.set('account', account)\n if (previewId) params.set('preview', previewId)\n const qs = params.toString()\n try {\n const res = await fetch(`${opts.baseUrl}/runtime/changes${qs ? `?${qs}` : ''}`, {\n headers: { Authorization: `Bearer ${opts.apiKey}` },\n })\n if (!res.ok) {\n log(`changes ${res.status}`)\n return\n }\n changes = parseChanges(await res.json())\n schedule()\n } catch (err) {\n log(`changes network error: ${(err as Error).message}`)\n }\n }\n\n const observer =\n typeof MutationObserver !== 'undefined'\n ? new MutationObserver(() => {\n if (changes.length > 0 || copies.size > 0 || tips.size > 0) schedule()\n })\n : null\n const observe = (): void => {\n if (document.body) observer?.observe(document.body, { childList: true, subtree: true, characterData: true })\n }\n if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', observe, { once: true })\n else observe()\n\n const interval = setInterval(() => void refresh(), REFRESH_MS)\n void refresh()\n\n return {\n onNavigate: () => {\n const asked = resolvePreviewId(location.search, storage('session'))\n const previewChanged = asked !== previewId\n if (previewChanged) {\n previewId = asked\n dismissedPreview = false\n for (const id of [...copies.keys()]) restoreCopy(id)\n for (const remove of [...tips.values()]) remove()\n }\n if (previewChanged || Date.now() - lastFetch > NAV_REFRESH_MS || opts.getAccountKey() !== fetchedForKey) void refresh()\n schedule()\n },\n onEvent: (name) => {\n for (const change of changes) {\n if (change.kind !== 'checklist') continue\n const hit = (change.content.items ?? []).filter((i) => i.events.includes(name))\n if (hit.length === 0) continue\n const set = doneOf(change)\n for (const i of hit) set.add(i.definition_name)\n progress.set(change.id, set)\n lists.get(change.id)?.()\n }\n },\n refresh,\n teardown: () => {\n clearInterval(interval)\n if (timer !== null) clearTimeout(timer)\n observer?.disconnect()\n for (const id of [...copies.keys()]) restoreCopy(id)\n for (const remove of [...tips.values()]) remove()\n for (const id of [...lists.keys()]) lists.delete(id)\n host?.remove()\n host = null\n root = null\n changes = []\n },\n }\n}\n", "/**\n * @holdyapp/sdk/web \u00B7 browser (source: sdk_web).\n *\n * anonymous_id gerado e persistido em localStorage (holdy_anon_id) \u2014 enviado em\n * todo event at\u00E9 identify() promover pra user_id (identity graph faz o merge\n * downstream, nunca o SDK). Flush no pagehide via fetch keepalive.\n *\n * Todo evento carrega o contexto de ambiente (url, path, referrer externo,\n * utm da sess\u00E3o, browser, os, device, locale, session_id) em `context` \u2014\n * separado das properties do produto. Pageview \u00E9 autom\u00E1tico por default:\n * carregamento inicial e cada mudan\u00E7a de rota, inclusive em SPA.\n */\n\nimport { HoldyCore } from './core'\nimport { installAutoCapture, type NavigationKind } from './auto-capture'\nimport { installFrictionCapture, type FrictionCapture, type FrictionCaptureOptions } from './friction'\nimport { installSkeletonCapture, type SkeletonCapture } from './skeleton'\nimport { buildWebContext, clearSessionId } from './web-context'\nimport { installProductChanges, type ProductChangesHandle } from './changes'\nimport type { HoldyOptions, Properties, TrackOverrides } from './types'\n\nconst ANON_STORAGE_KEY = 'holdy_anon_id'\n\nexport interface HoldyWebOptions extends HoldyOptions {\n /**\n * Emitir `$pageview` sozinho no load e a cada mudan\u00E7a de rota \u00B7 default true.\n * Desligue s\u00F3 se o produto j\u00E1 chama `page()` na m\u00E3o em cada tela.\n */\n autoCapture?: boolean\n /**\n * Capturar fric\u00E7\u00E3o sozinho \u00B7 default true. Emite `$dead_click`, `$rage_click`,\n * `$form_abandon`, `$js_error`, `$slow_request`, `$nav_loop` e `$http_error`\n * (requisi\u00E7\u00E3o com status \u2265 400 ou sem resposta, e a pr\u00F3pria p\u00E1gina que abre\n * com erro) \u2014 eventos determin\u00EDsticos, sem DOM nem replay. Objeto ajusta os\n * limiares; a URL da Holdy nunca conta como erro.\n */\n friction?: boolean | Omit<FrictionCaptureOptions, 'onFriction'>\n /**\n * Aplicar as mudan\u00E7as de texto e dica que a org p\u00F4s no ar na Holdy \u00B7 default\n * true. Parte das contas fica de fora por sorteio pra medir; sem conta\n * identificada (`group()` ou `accountKey`) nada \u00E9 aplicado.\n */\n productChanges?: boolean\n /**\n * Mandar o esqueleto da p\u00E1gina \u00B7 default true. Uma vez por (rota, estrutura)\n * por aba: `$page_skeleton` com os elementos interativos (tag, role,\n * data-testid, name, aria-label, tipo, posi\u00E7\u00E3o relativa). Sem texto livre,\n * sem valor de input, sem pixel.\n */\n skeleton?: boolean\n}\n\nexport class HoldyWeb extends HoldyCore {\n private teardownAutoCapture: (() => void) | null = null\n private friction: FrictionCapture | null = null\n private changes: ProductChangesHandle | null = null\n private skeleton: SkeletonCapture | null = null\n\n constructor(opts: HoldyWebOptions) {\n super('sdk_web', opts)\n this.anonymousId = resolveAnonymousId()\n\n if (typeof window !== 'undefined') {\n window.addEventListener('pagehide', () => void this.flush())\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') void this.flush()\n })\n }\n\n if (opts.friction !== false) {\n const frictionOpts = typeof opts.friction === 'object' ? opts.friction : {}\n this.friction = installFrictionCapture({\n ...frictionOpts,\n ignoreUrls: [...(frictionOpts.ignoreUrls ?? []), this.baseUrl],\n onFriction: (signal) => this.track(`$${signal.kind}`, signal.properties),\n })\n }\n\n if (opts.skeleton !== false) {\n this.skeleton = installSkeletonCapture({\n onSkeleton: (skeleton) => this.track('$page_skeleton', { ...skeleton }),\n })\n }\n\n if (opts.autoCapture !== false) {\n this.teardownAutoCapture = installAutoCapture({\n onNavigate: (kind: NavigationKind) => {\n this.page(undefined, { navigation: kind })\n const path = typeof location !== 'undefined' ? location.pathname : '/'\n this.friction?.onNavigate(path)\n this.changes?.onNavigate()\n this.skeleton?.onNavigate(path)\n },\n })\n }\n\n if (opts.productChanges !== false && typeof window !== 'undefined') {\n this.changes = installProductChanges({\n baseUrl: this.baseUrl,\n apiKey: this.apiKey,\n getAccountKey: () => this.accountKey,\n track: (name, properties) => this.track(name, properties),\n debug: opts.debug,\n })\n }\n }\n\n /**\n * Pageview. O `$` marca evento emitido pelo SDK, n\u00E3o pelo produto (mesma\n * conven\u00E7\u00E3o de `$identify`/`$group`); a canonicaliza\u00E7\u00E3o downstream remove o\n * sigilo, ent\u00E3o `$pageview` e `pageview` s\u00E3o o mesmo evento na leitura.\n * url/path/referrer/utm j\u00E1 v\u00EAm no context de todo evento \u2014 aqui s\u00F3 entra o\n * que \u00E9 da p\u00E1gina como conte\u00FAdo (nome e t\u00EDtulo).\n */\n page(name?: string, properties?: Properties): void {\n this.track('$pageview', {\n ...(properties ?? {}),\n ...(name ? { page_name: name } : {}),\n ...(typeof document !== 'undefined' && document.title ? { title: document.title } : {}),\n })\n }\n\n override group(accountKey: string, traits?: Properties): void {\n super.group(accountKey, traits)\n this.changes?.onNavigate()\n }\n\n override track(name: string, properties?: Properties, overrides?: TrackOverrides): void {\n super.track(name, properties, overrides)\n if (!name.startsWith('$')) this.changes?.onEvent(name)\n }\n\n reset(): void {\n this.userId = null\n this.accountKey = null\n try {\n localStorage.removeItem(ANON_STORAGE_KEY)\n } catch {\n // storage indispon\u00EDvel (SSR/privacy mode) \u2014 ok\n }\n clearSessionId()\n this.anonymousId = resolveAnonymousId()\n this.changes?.onNavigate()\n }\n\n /** Flush final + desinstala o auto-capture (devolve `history` ao original). */\n override async shutdown(): Promise<void> {\n this.teardownAutoCapture?.()\n this.teardownAutoCapture = null\n this.friction?.teardown()\n this.friction = null\n this.changes?.teardown()\n this.changes = null\n this.skeleton?.teardown()\n this.skeleton = null\n await super.shutdown()\n }\n\n protected override environmentContext(): Properties {\n return buildWebContext()\n }\n}\n\nfunction resolveAnonymousId(): string {\n try {\n const existing = localStorage.getItem(ANON_STORAGE_KEY)\n if (existing) return existing\n const fresh = crypto.randomUUID()\n localStorage.setItem(ANON_STORAGE_KEY, fresh)\n return fresh\n } catch {\n return crypto.randomUUID()\n }\n}\n\nlet singleton: HoldyWeb | null = null\n\n/** Init idempotente \u2014 segunda chamada retorna a inst\u00E2ncia existente. */\nexport function initHoldy(opts: HoldyWebOptions): HoldyWeb {\n if (!singleton) {\n singleton = new HoldyWeb(opts)\n // Inst\u00E2ncia no window: track() inserido pelo `--instrument` do CLI n\u00E3o\n // precisa importar nada nem saber onde o init mora. Mesma superf\u00EDcie do\n // loader por script tag, ent\u00E3o o snippet \u00E9 um s\u00F3 nos dois caminhos.\n if (typeof window !== 'undefined') {\n const w = window as unknown as { Holdy?: HoldyWeb }\n if (!w.Holdy) w.Holdy = singleton\n }\n }\n return singleton\n}\n\nexport type { HoldyOptions, Properties }\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["INSTALLED_FLAG", "currentPath", "visible", "storage", "fnv1a"]
|
|
7
7
|
}
|
package/package.json
CHANGED