@holdyapp/sdk 0.2.1 → 1.0.1
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 +20 -147
- package/dist/auto-capture.d.ts +12 -16
- package/dist/auto-capture.d.ts.map +1 -0
- package/dist/browser.d.ts +23 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/core.d.ts +42 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/holdy.js +2 -0
- package/dist/holdy.js.map +7 -0
- package/dist/index.cjs +430 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +5 -46
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +399 -0
- package/dist/index.mjs.map +7 -0
- package/dist/server.cjs +177 -0
- package/dist/server.cjs.map +7 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.mjs +148 -0
- package/dist/server.mjs.map +7 -0
- package/dist/types.d.ts +41 -109
- package/dist/types.d.ts.map +1 -0
- package/dist/web-context.d.ts +51 -0
- package/dist/web-context.d.ts.map +1 -0
- package/dist/web.d.ts +41 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.mjs +389 -0
- package/dist/web.mjs.map +7 -0
- package/package.json +24 -20
- package/src/auto-capture.ts +51 -78
- package/src/browser.ts +55 -0
- package/src/core.test.ts +147 -0
- package/src/core.ts +172 -0
- package/src/index.ts +4 -427
- package/src/server.ts +19 -0
- package/src/types.ts +38 -162
- package/src/web-context.test.ts +71 -0
- package/src/web-context.ts +227 -0
- package/src/web.ts +108 -0
- package/LICENSE +0 -21
- package/dist/anchor.d.ts +0 -8
- package/dist/holdy.cjs.js +0 -255
- package/dist/holdy.cjs.js.map +0 -7
- package/dist/holdy.esm.js +0 -255
- package/dist/holdy.esm.js.map +0 -7
- package/dist/holdy.iife.js +0 -255
- package/dist/holdy.iife.js.map +0 -7
- package/dist/outcome.d.ts +0 -19
- package/dist/queue.d.ts +0 -54
- package/dist/render/kinds/banner.d.ts +0 -3
- package/dist/render/kinds/checklist.d.ts +0 -19
- package/dist/render/kinds/cta.d.ts +0 -8
- package/dist/render/kinds/modal.d.ts +0 -16
- package/dist/render/kinds/shared.d.ts +0 -16
- package/dist/render/kinds/spotlight.d.ts +0 -17
- package/dist/render/kinds/tooltip.d.ts +0 -3
- package/dist/render/root.d.ts +0 -3
- package/dist/render/styles.d.ts +0 -5
- package/dist/store.d.ts +0 -36
- package/dist/transport.d.ts +0 -59
- package/src/anchor.ts +0 -72
- package/src/outcome.ts +0 -51
- package/src/queue.ts +0 -296
- package/src/render/kinds/banner.ts +0 -52
- package/src/render/kinds/checklist.ts +0 -175
- package/src/render/kinds/cta.ts +0 -53
- package/src/render/kinds/modal.ts +0 -129
- package/src/render/kinds/shared.ts +0 -67
- package/src/render/kinds/spotlight.ts +0 -176
- package/src/render/kinds/tooltip.ts +0 -82
- package/src/render/root.ts +0 -69
- package/src/render/styles.ts +0 -280
- package/src/store.ts +0 -106
- package/src/transport.ts +0 -182
package/dist/holdy.iife.js
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
"use strict";var Holdy=(()=>{var $=Object.defineProperty;var ye=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var ve=Object.prototype.hasOwnProperty;var we=(i,e)=>{for(var t in e)$(i,t,{get:e[t],enumerable:!0})},be=(i,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of ge(e))!ve.call(i,o)&&o!==t&&$(i,o,{get:()=>e[o],enumerable:!(n=ye(e,o))||n.enumerable});return i};var _e=i=>be($({},"__esModule",{value:!0}),i);var Be={};we(Be,{Holdy:()=>me,default:()=>Oe});var xe="holdy_sdk_v1",O="event_queue";function ke(){return typeof indexedDB!="undefined"}var D=null;function Ee(){return D||(D=new Promise((i,e)=>{let t=indexedDB.open(xe,1);t.onupgradeneeded=()=>{let n=t.result;n.objectStoreNames.contains(O)||n.createObjectStore(O,{keyPath:"id",autoIncrement:!0})},t.onsuccess=()=>i(t.result),t.onerror=()=>e(t.error)}),D)}function R(i,e){return Ee().then(t=>new Promise((n,o)=>{let r=t.transaction(O,i),s=r.objectStore(O),d;try{let l=e(s);l instanceof IDBRequest?(l.onsuccess=()=>{d=l.result},l.onerror=()=>o(l.error)):l.then(y=>d=y)}catch(l){o(l);return}r.oncomplete=()=>n(d),r.onerror=()=>o(r.error),r.onabort=()=>o(r.error)}))}var Ce={async add(i){await R("readwrite",e=>e.add(i))},async pickDue(i,e){let t=await R("readonly",n=>n.getAll());return(t!=null?t:[]).filter(n=>n.next_retry_at<=i).sort((n,o)=>n.next_retry_at-o.next_retry_at).slice(0,e)},async update(i){await R("readwrite",e=>e.put(i))},async remove(i){await R("readwrite",e=>e.delete(i))},async count(){return R("readonly",i=>i.count())},async dropOldest(i){let e=await R("readonly",n=>n.getAll()),t=(e!=null?e:[]).sort((n,o)=>n.created_at-o.created_at).slice(0,i);for(let n of t)n.id!==void 0&&await R("readwrite",o=>o.delete(n.id))},async all(){var i;return(i=await R("readonly",e=>e.getAll()))!=null?i:[]}},z=class{constructor(){this.items=[];this.nextId=1}async add(e){this.items.push({...e,id:this.nextId++})}async pickDue(e,t){return this.items.filter(n=>n.next_retry_at<=e).sort((n,o)=>n.next_retry_at-o.next_retry_at).slice(0,t)}async update(e){let t=this.items.findIndex(n=>n.id===e.id);t>=0&&(this.items[t]=e)}async remove(e){this.items=this.items.filter(t=>t.id!==e)}async count(){return this.items.length}async dropOldest(e){this.items.sort((t,n)=>t.created_at-n.created_at),this.items.splice(0,e)}async all(){return[...this.items]}},B=class{constructor(e,t=()=>{}){this.flushTimer=null;this.flushing=!1;this.driver=ke()?Ce:new z,this.send=e,this.log=t,this.startFlusher(),this.bindPagehide()}async enqueue(e){if(e.length===0)return;let t=await this.driver.count().catch(()=>0);if(t===0&&await this.send({events:e}).catch(()=>!1))return;if(t>=1e3){let o=t-1e3+1;await this.driver.dropOldest(o).catch(()=>{}),this.log("queue full \xB7 dropped",o,"oldest batches")}let n=Date.now();await this.driver.add({events:e,attempts:0,next_retry_at:n+1e3,created_at:n}).catch(o=>this.log("queue add failed",o))}startFlusher(){this.flushTimer||typeof setInterval!="undefined"&&(this.flushTimer=setInterval(()=>{this.flushOnce()},5e3))}async flushOnce(){if(!this.flushing){this.flushing=!0;try{let e=Date.now(),t=await this.driver.pickDue(e,10).catch(()=>[]);for(let n of t){if(await this.send({events:n.events}).catch(()=>!1)&&n.id!==void 0){await this.driver.remove(n.id).catch(()=>{});continue}let r=n.attempts+1;if(r>=5){n.id!==void 0&&await this.driver.remove(n.id).catch(()=>{}),this.log("dropped batch after max attempts",{events:n.events.length});continue}let s=1e3*Math.pow(2,r);await this.driver.update({...n,attempts:r,next_retry_at:Date.now()+s}).catch(()=>{})}}finally{this.flushing=!1}}}bindPagehide(){if(typeof window=="undefined")return;let e=()=>{this.driver.all().then(t=>{for(let n of t)this.send({events:n.events}).catch(()=>{})}).catch(()=>{})};window.addEventListener("pagehide",e),window.addEventListener("beforeunload",e)}destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null)}};var Te="https://app.holdy.com.br/api/v1",H=class{constructor(e){var t,n;this.apiKey=e.apiKey,this.apiUrl=((t=e.apiUrl)!=null?t:Te).replace(/\/$/,""),this.debug=(n=e.debug)!=null?n:!1,this.queue=new B(o=>this.sendBatch(o.events),(...o)=>this.log(...o))}headers(){return{"content-type":"application/json",authorization:`Bearer ${this.apiKey}`}}async fetchRuntimeConfig(){try{let e=await fetch(`${this.apiUrl}/runtime/config`,{method:"GET",headers:this.headers(),credentials:"omit",mode:"cors"});return e.ok?await e.json():(this.log("runtime/config failed",e.status),null)}catch(e){return this.log("runtime/config error",e),null}}async evaluate(e){try{let t=await fetch(`${this.apiUrl}/decisions/evaluate`,{method:"POST",headers:this.headers(),body:JSON.stringify({consumer:"ui",...e}),credentials:"omit",mode:"cors"});return t.ok?await t.json():(this.log("decisions/evaluate failed",t.status),null)}catch(t){return this.log("decisions/evaluate error",t),null}}ingestBatch(e){e.length!==0&&this.queue.enqueue(e)}async sendBatch(e){try{return(await fetch(`${this.apiUrl}/events/batch`,{method:"POST",headers:this.headers(),body:JSON.stringify({events:e}),credentials:"omit",mode:"cors",keepalive:!0})).ok}catch(t){return this.log("events/batch network error",t),!1}}async upsertAccount(e){try{let t=await fetch(`${this.apiUrl}/accounts/upsert`,{method:"POST",headers:this.headers(),body:JSON.stringify(e),credentials:"omit",mode:"cors",keepalive:!0});return t.ok?await t.json():(this.log("accounts/upsert failed",t.status),null)}catch(t){return this.log("accounts/upsert error",t),null}}reportOutcome(e,t,n){let o=`${this.apiUrl}/decisions/${encodeURIComponent(e)}/outcome`;fetch(o,{method:"POST",headers:this.headers(),body:JSON.stringify({outcome:t,metadata:n}),credentials:"omit",mode:"cors",keepalive:!0}).catch(r=>this.log("decisions/outcome error",r))}log(...e){this.debug&&typeof console!="undefined"&&console.warn("[holdy]",...e)}destroy(){this.queue.destroy()}};var M=class{constructor(e){this.pending=new Map;this.transport=e}registerPending(e,t){this.pending.set(e,{id:e,workflow:t,startedAt:Date.now()})}dispatch(e,t,n){var o,r,s;if(!this.pending.has(e)&&t!=="failed"){this.transport.reportOutcome(e,t,n);return}this.pending.delete(e),this.transport.reportOutcome(e,t,{...n,latency_ms:(s=n==null?void 0:n.latency_ms)!=null?s:Date.now()-((r=(o=this.pending.get(e))==null?void 0:o.startedAt)!=null?r:Date.now())})}hasPending(e){return this.pending.has(e)}};var N=class{constructor(){this.tooltipsByAnchor=new Map;this.spotlightsByAnchor=new Map;this.banner=null;this.modal=null;this.checklist=null;this.cta=null}claim(e,t,n,o,r){let s={decisionId:t,confidence:n,kind:e,dismiss:r};if(e==="tooltip"){let d=o!=null?o:"__no_anchor__",l=this.tooltipsByAnchor.get(d);return l&&l.confidence>=n?s:(this.tooltipsByAnchor.set(d,s),l!=null?l:null)}if(e==="spotlight"){let d=o!=null?o:"__no_anchor__",l=this.spotlightsByAnchor.get(d);return l&&l.confidence>=n?s:(this.spotlightsByAnchor.set(d,s),l!=null?l:null)}if(e==="banner"){let d=this.banner;return d&&d.confidence>=n?s:(this.banner=s,d!=null?d:null)}if(e==="modal"){let d=this.modal;return d&&d.confidence>=n?s:(this.modal=s,d!=null?d:null)}if(e==="checklist"){let d=this.checklist;return d&&d.confidence>=n?s:(this.checklist=s,d!=null?d:null)}if(e==="cta"){let d=this.cta;return d&&d.confidence>=n?s:(this.cta=s,d!=null?d:null)}return null}release(e){var t,n,o,r;((t=this.banner)==null?void 0:t.decisionId)===e&&(this.banner=null),((n=this.modal)==null?void 0:n.decisionId)===e&&(this.modal=null),((o=this.checklist)==null?void 0:o.decisionId)===e&&(this.checklist=null),((r=this.cta)==null?void 0:r.decisionId)===e&&(this.cta=null);for(let s of[this.tooltipsByAnchor,this.spotlightsByAnchor])for(let[d,l]of s)if(l.decisionId===e){s.delete(d);break}}};var I=new Set,S=null;function Re(){S||typeof MutationObserver=="undefined"||typeof document=="undefined"||(S=new MutationObserver(()=>{I.size!==0&&(I.forEach(i=>{let e=document.querySelector(i.selector);e&&(i.cleanup(),i.resolve(e))}),I.size===0&&Z())}),S.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["id","class","data-holdy-anchor"]}))}function Z(){S&&(S.disconnect(),S=null)}function q(i){if(!i||typeof document=="undefined")return Promise.resolve(null);let e=document.querySelector(i);return e?Promise.resolve(e):new Promise(t=>{let n=!1,o={selector:i,resolve:t,cleanup:()=>{n||(n=!0,I.delete(o),clearTimeout(r),I.size===0&&Z())}},r=setTimeout(()=>{o.cleanup(),t(null)},5e3);I.add(o),Re()})}var Q="__holdy_autocapture_installed__";function Y(i){if(typeof window=="undefined"||typeof history=="undefined")return()=>{};let e=window;if(e[Q])return()=>{};e[Q]=!0;let t=[],n=K(),o=null;function r(u){try{let g=K(),a=typeof document!="undefined"?document.title:void 0,h=typeof document!="undefined"&&document.referrer||void 0;i(g,a,h,u)}catch(g){}}function s(){o&&clearTimeout(o),o=setTimeout(()=>{let u=K();u!==n&&(n=u,r("route_change")),o=null},50)}r("initial_load");let d=history.pushState,l=history.replaceState;history.pushState=function(...g){let a=d.apply(this,g);return s(),a},history.replaceState=function(...g){let a=l.apply(this,g);return s(),a},t.push(()=>{history.pushState=d,history.replaceState=l});let y=()=>s();window.addEventListener("popstate",y),t.push(()=>window.removeEventListener("popstate",y));let p=()=>s();window.addEventListener("hashchange",p),t.push(()=>window.removeEventListener("hashchange",p));let v=null,f=()=>{if(typeof document!="undefined"){if(document.visibilityState==="hidden")v=Date.now();else if(document.visibilityState==="visible"&&v){let u=Date.now()-v;v=null,u>5*6e4&&r("visibility_change")}}};return typeof document!="undefined"&&(document.addEventListener("visibilitychange",f),t.push(()=>document.removeEventListener("visibilitychange",f))),()=>{o&&clearTimeout(o);for(let u of t)u();e[Q]=!1}}function K(){return typeof window=="undefined"||!window.location?"/":window.location.pathname+window.location.search+window.location.hash}var ee={primary_color:"#ca2121",font_family:"inherit",border_radius_px:8,position_offset_px:8};var te=`
|
|
2
|
-
:host {
|
|
3
|
-
--holdy-primary: var(--holdy-cfg-primary, #ca2121);
|
|
4
|
-
--holdy-font: var(--holdy-cfg-font, system-ui, -apple-system, sans-serif);
|
|
5
|
-
--holdy-radius: var(--holdy-cfg-radius, 8px);
|
|
6
|
-
--holdy-offset: var(--holdy-cfg-offset, 8px);
|
|
7
|
-
--holdy-bg: #ffffff;
|
|
8
|
-
--holdy-fg: #1a1a1a;
|
|
9
|
-
--holdy-muted: #737373;
|
|
10
|
-
--holdy-border: rgba(0, 0, 0, 0.08);
|
|
11
|
-
--holdy-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
|
12
|
-
all: initial;
|
|
13
|
-
font-family: var(--holdy-font);
|
|
14
|
-
color: var(--holdy-fg);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
@media (prefers-color-scheme: dark) {
|
|
18
|
-
:host {
|
|
19
|
-
--holdy-bg: #111111;
|
|
20
|
-
--holdy-fg: #f5f5f5;
|
|
21
|
-
--holdy-muted: #a3a3a3;
|
|
22
|
-
--holdy-border: rgba(255, 255, 255, 0.12);
|
|
23
|
-
--holdy-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.holdy-card {
|
|
28
|
-
background: var(--holdy-bg);
|
|
29
|
-
color: var(--holdy-fg);
|
|
30
|
-
border: 1px solid var(--holdy-border);
|
|
31
|
-
border-radius: var(--holdy-radius);
|
|
32
|
-
box-shadow: var(--holdy-shadow);
|
|
33
|
-
padding: 12px 14px;
|
|
34
|
-
font-size: 14px;
|
|
35
|
-
line-height: 1.45;
|
|
36
|
-
max-width: 320px;
|
|
37
|
-
pointer-events: auto;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.holdy-card-text {
|
|
41
|
-
margin: 0;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.holdy-card-actions {
|
|
45
|
-
display: flex;
|
|
46
|
-
gap: 8px;
|
|
47
|
-
margin-top: 10px;
|
|
48
|
-
align-items: center;
|
|
49
|
-
justify-content: flex-end;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.holdy-btn {
|
|
53
|
-
font-family: var(--holdy-font);
|
|
54
|
-
font-size: 13px;
|
|
55
|
-
font-weight: 500;
|
|
56
|
-
padding: 6px 12px;
|
|
57
|
-
border-radius: 6px;
|
|
58
|
-
border: none;
|
|
59
|
-
cursor: pointer;
|
|
60
|
-
background: var(--holdy-primary);
|
|
61
|
-
color: #ffffff;
|
|
62
|
-
text-decoration: none;
|
|
63
|
-
display: inline-flex;
|
|
64
|
-
align-items: center;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.holdy-btn:focus-visible {
|
|
68
|
-
outline: 2px solid var(--holdy-primary);
|
|
69
|
-
outline-offset: 2px;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.holdy-btn-ghost {
|
|
73
|
-
background: transparent;
|
|
74
|
-
color: var(--holdy-muted);
|
|
75
|
-
border: 1px solid var(--holdy-border);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.holdy-close {
|
|
79
|
-
background: transparent;
|
|
80
|
-
border: none;
|
|
81
|
-
color: var(--holdy-muted);
|
|
82
|
-
font-size: 16px;
|
|
83
|
-
line-height: 1;
|
|
84
|
-
cursor: pointer;
|
|
85
|
-
padding: 4px;
|
|
86
|
-
border-radius: 4px;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.holdy-close:hover {
|
|
90
|
-
color: var(--holdy-fg);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.holdy-tooltip {
|
|
94
|
-
position: fixed;
|
|
95
|
-
z-index: 2147483647;
|
|
96
|
-
max-width: 280px;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.holdy-banner {
|
|
100
|
-
position: fixed;
|
|
101
|
-
top: 0;
|
|
102
|
-
left: 50%;
|
|
103
|
-
transform: translateX(-50%);
|
|
104
|
-
margin-top: var(--holdy-offset);
|
|
105
|
-
z-index: 2147483647;
|
|
106
|
-
max-width: min(560px, calc(100vw - 32px));
|
|
107
|
-
display: flex;
|
|
108
|
-
align-items: center;
|
|
109
|
-
gap: 12px;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.holdy-banner .holdy-card-text {
|
|
113
|
-
flex: 1;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.holdy-cta {
|
|
117
|
-
position: fixed;
|
|
118
|
-
right: var(--holdy-offset);
|
|
119
|
-
bottom: var(--holdy-offset);
|
|
120
|
-
z-index: 2147483647;
|
|
121
|
-
max-width: 320px;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
.holdy-card-title {
|
|
125
|
-
margin: 0 0 6px;
|
|
126
|
-
font-size: 15px;
|
|
127
|
-
font-weight: 600;
|
|
128
|
-
line-height: 1.3;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/* \u2500\u2500 Modal (Wave 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
132
|
-
.holdy-modal-backdrop {
|
|
133
|
-
position: fixed;
|
|
134
|
-
inset: 0;
|
|
135
|
-
background: rgba(0, 0, 0, 0.5);
|
|
136
|
-
display: flex;
|
|
137
|
-
align-items: center;
|
|
138
|
-
justify-content: center;
|
|
139
|
-
z-index: 2147483647;
|
|
140
|
-
padding: 20px;
|
|
141
|
-
pointer-events: auto;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.holdy-modal {
|
|
145
|
-
max-width: 480px;
|
|
146
|
-
width: 100%;
|
|
147
|
-
padding: 20px 22px;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.holdy-modal:focus {
|
|
151
|
-
outline: none;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/* \u2500\u2500 Checklist (Wave 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
155
|
-
.holdy-checklist {
|
|
156
|
-
position: fixed;
|
|
157
|
-
right: var(--holdy-offset);
|
|
158
|
-
bottom: var(--holdy-offset);
|
|
159
|
-
z-index: 2147483647;
|
|
160
|
-
max-width: 320px;
|
|
161
|
-
padding: 14px 16px;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
.holdy-checklist-header {
|
|
165
|
-
display: flex;
|
|
166
|
-
align-items: flex-start;
|
|
167
|
-
justify-content: space-between;
|
|
168
|
-
gap: 8px;
|
|
169
|
-
margin-bottom: 4px;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.holdy-checklist-title {
|
|
173
|
-
margin: 0;
|
|
174
|
-
font-size: 14px;
|
|
175
|
-
font-weight: 600;
|
|
176
|
-
line-height: 1.3;
|
|
177
|
-
flex: 1;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.holdy-checklist-list {
|
|
181
|
-
list-style: none;
|
|
182
|
-
padding: 0;
|
|
183
|
-
margin: 8px 0 0;
|
|
184
|
-
display: flex;
|
|
185
|
-
flex-direction: column;
|
|
186
|
-
gap: 6px;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
.holdy-checklist-item {
|
|
190
|
-
display: flex;
|
|
191
|
-
align-items: center;
|
|
192
|
-
gap: 8px;
|
|
193
|
-
font-size: 13px;
|
|
194
|
-
line-height: 1.4;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
.holdy-checklist-item.is-done .holdy-checklist-label {
|
|
198
|
-
text-decoration: line-through;
|
|
199
|
-
color: var(--holdy-muted);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
.holdy-checklist-checkbox {
|
|
203
|
-
accent-color: var(--holdy-primary);
|
|
204
|
-
cursor: pointer;
|
|
205
|
-
flex-shrink: 0;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.holdy-checklist-label {
|
|
209
|
-
color: var(--holdy-fg);
|
|
210
|
-
text-decoration: none;
|
|
211
|
-
cursor: pointer;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
.holdy-checklist-label:hover {
|
|
215
|
-
color: var(--holdy-primary);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/* \u2500\u2500 Spotlight (Wave 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
219
|
-
.holdy-spotlight-container {
|
|
220
|
-
position: fixed;
|
|
221
|
-
inset: 0;
|
|
222
|
-
z-index: 2147483647;
|
|
223
|
-
pointer-events: none;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
.holdy-spotlight-backdrop {
|
|
227
|
-
position: absolute;
|
|
228
|
-
inset: 0;
|
|
229
|
-
background: rgba(0, 0, 0, 0.55);
|
|
230
|
-
pointer-events: auto;
|
|
231
|
-
transition: clip-path 120ms ease-out;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
.holdy-spotlight-ring {
|
|
235
|
-
position: absolute;
|
|
236
|
-
border-radius: 8px;
|
|
237
|
-
box-shadow: 0 0 0 2px var(--holdy-primary), 0 0 24px rgba(202, 33, 33, 0.4);
|
|
238
|
-
pointer-events: none;
|
|
239
|
-
transition: top 120ms, left 120ms, width 120ms, height 120ms;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
.holdy-spotlight-tooltip {
|
|
243
|
-
position: absolute;
|
|
244
|
-
max-width: 320px;
|
|
245
|
-
pointer-events: auto;
|
|
246
|
-
}
|
|
247
|
-
`,W=null;function ne(){if(typeof CSSStyleSheet=="undefined")return null;if(W)return W;try{let i=new CSSStyleSheet;return i.replaceSync(te),W=i,i}catch(i){return null}}function V(i,e){let t=e!=null?e:ee;i.style.setProperty("--holdy-cfg-primary",t.primary_color),i.style.setProperty("--holdy-cfg-font",t.font_family),i.style.setProperty("--holdy-cfg-radius",`${t.border_radius_px}px`),i.style.setProperty("--holdy-cfg-offset",`${t.position_offset_px}px`)}function j(i){let e=document.createElement("style");e.textContent=te,i.appendChild(e)}var G="holdy-root",b=null,A=null;function Ie(){if(typeof customElements=="undefined"||customElements.get(G))return;class i extends HTMLElement{}try{customElements.define(G,i)}catch(e){}}function ie(i){if(typeof document=="undefined")return null;if(A)return b&&V(b,i),A;Ie(),b=document.createElement(G),b.setAttribute("aria-live","polite"),b.setAttribute("data-holdy-root","1"),b.style.position="fixed",b.style.top="0",b.style.left="0",b.style.width="0",b.style.height="0",b.style.zIndex="2147483647",b.style.pointerEvents="none";let e=b.attachShadow({mode:"closed"});A=e;let t=ne();if(t&&"adoptedStyleSheets"in e)try{e.adoptedStyleSheets=[t]}catch(n){j(e)}else j(e);return V(b,i),document.body?document.body.appendChild(b):document.addEventListener("DOMContentLoaded",()=>{b&&!b.isConnected&&document.body.appendChild(b)}),A}function oe(i){A&&(i.style.pointerEvents="auto",A.appendChild(i))}function k(i){let e=document.createElement("button");return e.type="button",e.className="holdy-close",e.setAttribute("aria-label","Fechar"),e.textContent="\xD7",e.addEventListener("click",t=>{t.stopPropagation(),i()}),e}function E(i,e){if(!i.cta_text)return null;let t;if(i.cta_href){let n=document.createElement("a");n.href=i.cta_href,n.rel="noopener noreferrer",n.target="_self",t=n}else t=document.createElement("button"),t.type="button";return t.className="holdy-btn",t.textContent=i.cta_text,t.addEventListener("click",()=>e()),t}function C(i){let e=document.createElement("p");return e.className="holdy-card-text",e.textContent=i,e}function T(...i){let e=i.filter(n=>n!==null);if(e.length===0)return null;let t=document.createElement("div");return t.className="holdy-card-actions",e.forEach(n=>t.appendChild(n)),t}var re=8;function se(i,e,t){let n=document.createElement("div");n.className="holdy-card holdy-tooltip",n.setAttribute("role","tooltip");let o=C(i.text);n.appendChild(o);let r=k(()=>p("dismissed")),s=E(i,()=>{t.onExecuted(),y()}),d=T(s,r);d?n.appendChild(d):n.appendChild(r);let l=!1,y=()=>{l||(l=!0,n.remove(),window.removeEventListener("scroll",v,!0),window.removeEventListener("resize",v))},p=(f="dismissed")=>{l||(f==="dismissed"&&t.onDismissed(),f==="failed"&&t.onFailed(),y())},v=()=>{if(!e)return;let f=e.getBoundingClientRect();if(f.width===0&&f.height===0)return;let u=n.getBoundingClientRect(),g=f.bottom+re,a=f.left+f.width/2-u.width/2,h=window.innerWidth-u.width-8;a<8&&(a=8),a>h&&(a=h),g+u.height>window.innerHeight-8&&(g=f.top-u.height-re),n.style.top=`${Math.max(8,g)}px`,n.style.left=`${a}px`};return n.style.top="-9999px",n.style.left="-9999px",requestAnimationFrame(()=>{v(),window.addEventListener("scroll",v,!0),window.addEventListener("resize",v)}),{el:n,dismiss:f=>p(f==="failed"||f==="no_show"?f:"dismissed")}}function de(i,e){let t=document.createElement("div");t.className="holdy-card holdy-banner",t.setAttribute("role","status");let n=C(i.text);t.appendChild(n);let o=k(()=>y("dismissed")),r=E(i,()=>{e.onExecuted(),l()}),s=T(r,o);s?(s.style.marginTop="0",t.appendChild(s)):t.appendChild(o);let d=!1,l=()=>{d||(d=!0,t.remove())},y=(p="dismissed")=>{d||(p==="dismissed"&&e.onDismissed(),p==="failed"&&e.onFailed(),l())};return{el:t,dismiss:p=>y(p==="failed"||p==="no_show"?p:"dismissed")}}function ae(i,e){let t=document.createElement("div");t.className="holdy-card holdy-cta",t.setAttribute("role","dialog"),t.setAttribute("aria-label","Sugest\xE3o Holdy");let n=C(i.text);t.appendChild(n);let o=k(()=>y("dismissed")),r=E(i,()=>{e.onExecuted(),l()}),s=T(r,o);s?t.appendChild(s):t.appendChild(o);let d=!1,l=()=>{d||(d=!0,t.remove())},y=(p="dismissed")=>{d||(p==="dismissed"&&e.onDismissed(),p==="failed"&&e.onFailed(),l())};return{el:t,dismiss:p=>y(p==="failed"||p==="no_show"?p:"dismissed")}}function le(i,e){let t=document.createElement("div");t.className="holdy-modal-backdrop";let n=document.createElement("div");if(n.className="holdy-card holdy-modal",n.setAttribute("role","dialog"),n.setAttribute("aria-modal","true"),n.tabIndex=-1,i.title){let a=document.createElement("h2");a.className="holdy-card-title",a.textContent=i.title,n.appendChild(a)}let o=C(i.text);n.appendChild(o);let r=k(()=>g("dismissed")),s=E(i,()=>{e.onExecuted(),u()}),d=T(s,r);d?n.appendChild(d):n.appendChild(r),t.appendChild(n);let l=document.body.style.overflow;document.body.style.overflow="hidden",t.addEventListener("click",a=>{a.target===t&&g("dismissed",{reason:"backdrop_click"})});let y=document.activeElement;(()=>{requestAnimationFrame(()=>{let a=n.querySelector('a, button, [tabindex]:not([tabindex="-1"])');(a!=null?a:n).focus()})})();let v=a=>{if(a.key==="Escape"){a.stopPropagation(),g("dismissed",{reason:"esc"});return}if(a.key!=="Tab")return;let h=Array.from(n.querySelectorAll('a, button, [tabindex]:not([tabindex="-1"])'));if(h.length===0)return;let m=h[0],c=h[h.length-1],w=document.activeElement;a.shiftKey&&w===m?(a.preventDefault(),c.focus()):!a.shiftKey&&w===c&&(a.preventDefault(),m.focus())};document.addEventListener("keydown",v,!0);let f=!1,u=()=>{f||(f=!0,document.body.style.overflow=l,document.removeEventListener("keydown",v,!0),t.remove(),y&&typeof y.focus=="function"&&y.focus())},g=(a="dismissed",h)=>{f||(a==="dismissed"&&e.onDismissed(h),a==="failed"&&e.onFailed(h),u())};return{el:t,dismiss:a=>g(a==="failed"||a==="no_show"?a:"dismissed")}}var ce="holdy_checklist_";function ue(i,e,t){var h,m;let n=(h=i.items)!=null?h:[];if(n.length===0)return t.onFailed({reason:"empty_items"}),{el:document.createElement("div"),dismiss:()=>{}};let o=Se(e,n),r=document.createElement("div");r.className="holdy-card holdy-checklist",r.setAttribute("role","region"),r.setAttribute("aria-label",(m=i.title)!=null?m:"Lista de tarefas");let s=document.createElement("div");if(s.className="holdy-checklist-header",i.title){let c=document.createElement("h3");c.className="holdy-checklist-title",c.textContent=i.title,s.appendChild(c)}let d=k(()=>a("dismissed"));if(s.appendChild(d),r.appendChild(s),i.text){let c=document.createElement("p");c.className="holdy-card-text",c.textContent=i.text,r.appendChild(c)}let l=document.createElement("ul");l.className="holdy-checklist-list";let y=!1,p=!1,v=()=>{l.textContent="",n.forEach(c=>{let w=document.createElement("li");w.className=o[c.id]?"holdy-checklist-item is-done":"holdy-checklist-item";let _=document.createElement("input");_.type="checkbox",_.className="holdy-checklist-checkbox",_.checked=!!o[c.id],_.setAttribute("aria-label",`Marcar ${c.label}`),_.addEventListener("change",()=>f(c,_.checked));let x=c.href?document.createElement("a"):document.createElement("span");x.className="holdy-checklist-label",x.textContent=c.label,c.href&&(x.href=c.href,x.rel="noopener noreferrer",x.addEventListener("click",()=>f(c,!0))),w.appendChild(_),w.appendChild(x),l.appendChild(w)})},f=(c,w)=>{o[c.id]=w,Ae(e,o),w&&!y&&(y=!0,t.onExecuted({item_id:c.id})),n.every(x=>o[x.id])&&!p&&(p=!0,t.onExecuted({completed:!0})),v()};v(),r.appendChild(l);let u=!1,g=()=>{u||(u=!0,r.remove())},a=(c="dismissed")=>{u||(c==="dismissed"&&t.onDismissed(),c==="failed"&&t.onFailed(),g())};return{el:r,dismiss:c=>a(c==="failed"||c==="no_show"?c:"dismissed")}}function Se(i,e){let t={};if(e.forEach(n=>{t[n.id]=!!n.completed}),typeof localStorage=="undefined")return t;try{let n=localStorage.getItem(ce+i);if(!n)return t;let o=JSON.parse(n);return e.forEach(r=>{typeof o[r.id]=="boolean"&&(t[r.id]=o[r.id])}),t}catch(n){return t}}function Ae(i,e){if(typeof localStorage!="undefined")try{localStorage.setItem(ce+i,JSON.stringify(e))}catch(t){}}var F=6,he=12;function pe(i,e,t){if(!e)return t.onFailed({reason:"anchor_unresolved"}),{el:document.createElement("div"),dismiss:()=>{}};let n=document.createElement("div");n.className="holdy-spotlight-container";let o=document.createElement("div");o.className="holdy-spotlight-backdrop",n.appendChild(o);let r=document.createElement("div");r.className="holdy-spotlight-ring",n.appendChild(r);let s=document.createElement("div");if(s.className="holdy-card holdy-spotlight-tooltip",s.setAttribute("role","dialog"),i.title){let m=document.createElement("h3");m.className="holdy-card-title",m.textContent=i.title,s.appendChild(m)}let d=C(i.text);s.appendChild(d);let l=k(()=>h("dismissed")),y=E(i,()=>{t.onExecuted(),a()}),p=T(y,l);p?s.appendChild(p):s.appendChild(l),n.appendChild(s);let v=()=>{t.onExecuted({via:"anchor_click"}),a()};e.addEventListener("click",v,{once:!0,capture:!0}),o.addEventListener("click",()=>h("dismissed",{reason:"backdrop_click"}));let f=m=>{m.key==="Escape"&&(m.stopPropagation(),h("dismissed",{reason:"esc"}))};document.addEventListener("keydown",f,!0);let u=()=>{let m=e.getBoundingClientRect();if(m.width===0&&m.height===0){h("no_show",{reason:"anchor_disappeared"});return}let c=Math.max(0,m.top-F),w=Math.max(0,m.left-F),_=m.width+F*2,x=m.height+F*2;r.style.top=`${c}px`,r.style.left=`${w}px`,r.style.width=`${_}px`,r.style.height=`${x}px`,o.style.clipPath=`polygon(
|
|
248
|
-
0 0, 100% 0, 100% 100%, 0 100%, 0 0,
|
|
249
|
-
${w}px ${c}px,
|
|
250
|
-
${w}px ${c+x}px,
|
|
251
|
-
${w+_}px ${c+x}px,
|
|
252
|
-
${w+_}px ${c}px,
|
|
253
|
-
${w}px ${c}px
|
|
254
|
-
)`;let L=s.getBoundingClientRect(),U=c+x+he,P=w+_/2-L.width/2;P<8&&(P=8);let J=window.innerWidth-L.width-8;P>J&&(P=J),U+L.height>window.innerHeight-8&&(U=c-L.height-he),s.style.top=`${Math.max(8,U)}px`,s.style.left=`${P}px`};s.style.top="-9999px",s.style.left="-9999px",requestAnimationFrame(()=>{u(),window.addEventListener("scroll",u,!0),window.addEventListener("resize",u)});let g=!1,a=()=>{g||(g=!0,n.remove(),document.removeEventListener("keydown",f,!0),window.removeEventListener("scroll",u,!0),window.removeEventListener("resize",u),e.removeEventListener("click",v,!0))},h=(m="dismissed",c)=>{g||(m==="dismissed"&&t.onDismissed(c),m==="failed"&&t.onFailed(c),a())};return{el:n,dismiss:m=>h(m==="failed"||m==="no_show"?m:"dismissed")}}var Pe=20,fe="__holdy_runtime_config_v1",Le=3600*1e3,De=1500,X=class{constructor(){this.config=null;this.transport=null;this.outcomeTracker=null;this.store=new N;this.runtime=null;this.activeWorkflow=null;this.sentiment=null;this.ring=[];this.listeners=[];this.lastEvalAt=0;this.initialized=!1;this.autoCaptureCleanup=null}async init(e){if(this.initialized){this.log("init called twice \xB7 ignoring");return}if(!e.apiKey)throw new Error("[holdy] apiKey is required");this.config=e,this.transport=new H(e),this.outcomeTracker=new M(this.transport),this.initialized=!0;let t=this.readCachedConfig();t&&(this.runtime=t);let n=await this.transport.fetchRuntimeConfig();n&&(this.runtime=n,this.writeCachedConfig(n)),this.shouldRender()&&ie(this.themeFromRuntime()),e.autoCapture&&(this.autoCaptureCleanup=Y((o,r,s,d)=>{this.track("session.activity",{kind:d,path:o,...r?{title:r}:{},...s?{referrer:s}:{}},{skipEval:d!=="route_change"})}))}identify(e){this.config&&(e.accountId!==void 0&&(this.config.accountId=e.accountId),e.userId!==void 0&&(this.config.userId=e.userId),e.sessionId!==void 0&&(this.config.sessionId=e.sessionId),(e.account||e.user)&&this.upsertIdentityRich(e.account,e.user))}async upsertIdentityRich(e,t){if(!this.transport||!e)return;let n=await this.transport.upsertAccount({account:e,user:t});!n||!this.config||(this.config.accountId||(this.config.accountId=n.account_id),!this.config.userId&&n.account_user_id&&(this.config.userId=n.account_user_id))}setWorkflow(e){this.activeWorkflow=e!=null?e:null}setSentiment(e){this.sentiment=e}async track(e,t={},n={}){if(!this.config||!this.transport){this.log("track called before init");return}let o=new Date().toISOString(),r={primitive:e,payload:t,occurred_at:o};this.pushRing(r),e==="workflow.started"&&typeof t.workflow=="string"&&(this.activeWorkflow=t.workflow),(e==="workflow.completed"||e==="workflow.abandoned")&&typeof t.workflow=="string"&&this.activeWorkflow===t.workflow&&(this.activeWorkflow=null),n.workflow!==void 0&&(this.activeWorkflow=n.workflow),this.transport.ingestBatch([{primitive:e,occurred_at:o,account_id:this.config.accountId,user_id:this.config.userId,session_id:this.config.sessionId,payload:t}]),!n.skipEval&&this.shouldTriggerEval(e)&&await this.evaluateInternal()}async evaluate(){return this.evaluateInternal(!0)}onDecision(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e)}}reportOutcome(e,t,n){var o;(o=this.outcomeTracker)==null||o.dispatch(e,t,n)}destroy(){var e;if((e=this.transport)==null||e.destroy(),this.autoCaptureCleanup){try{this.autoCaptureCleanup()}catch(t){}this.autoCaptureCleanup=null}this.config=null,this.transport=null,this.outcomeTracker=null,this.runtime=null,this.activeWorkflow=null,this.listeners=[],this.ring.length=0,this.initialized=!1}async evaluateInternal(e=!1){var r,s;if(!this.transport||!((r=this.config)!=null&&r.accountId))return this.log("evaluate skipped \xB7 no accountId set \xB7 call identify first"),null;let t=Date.now();if(!e&&t-this.lastEvalAt<De)return null;this.lastEvalAt=t;let n={account_id:this.config.accountId,recent_primitives:[...this.ring],consumer:(s=this.config.consumer)!=null?s:"ui"};this.activeWorkflow&&(n.current_workflow=this.activeWorkflow),this.sentiment&&(n.recent_sentiment=this.sentiment);let o=await this.transport.evaluate(n);return o?(this.listeners.forEach(d=>{try{d(o)}catch(l){this.log("listener error",l)}}),o.decision_type==="intervention"&&this.shouldRender()&&this.renderDecision(o),o):null}async renderDecision(e){var s,d,l,y,p,v,f,u,g;let t=e.decision_payload;if(!t||typeof t.kind!="string"||typeof t.text!="string"){(s=this.outcomeTracker)==null||s.dispatch(e.decision_id,"failed",{reason:"invalid_payload"});return}let n={onExecuted:a=>{var h;return(h=this.outcomeTracker)==null?void 0:h.dispatch(e.decision_id,"executed",a)},onDismissed:a=>{var h;return(h=this.outcomeTracker)==null?void 0:h.dispatch(e.decision_id,"dismissed",a)},onFailed:a=>{var h;return(h=this.outcomeTracker)==null?void 0:h.dispatch(e.decision_id,"failed",a)}},o=null;try{switch(t.kind){case"tooltip":{let a=await q(t.anchor_selector);if(!a){(l=this.outcomeTracker)==null||l.dispatch(e.decision_id,"no_show",{reason:"anchor_unresolved",selector:(d=t.anchor_selector)!=null?d:null});return}o=se(t,a,n);break}case"banner":o=de(t,n);break;case"cta":o=ae(t,n);break;case"modal":o=le(t,n);break;case"checklist":o=ue(t,e.decision_id,n);break;case"spotlight":{let a=await q(t.anchor_selector);if(!a){(p=this.outcomeTracker)==null||p.dispatch(e.decision_id,"no_show",{reason:"anchor_unresolved",selector:(y=t.anchor_selector)!=null?y:null});return}o=pe(t,a,n);break}default:(v=this.outcomeTracker)==null||v.dispatch(e.decision_id,"no_show",{reason:"kind_not_supported",kind:t.kind});return}}catch(a){this.log("render error",a),n.onFailed({error:String(a)});return}if(!o)return;let r=this.store.claim(t.kind,e.decision_id,e.confidence,t.anchor_selector,()=>o.dismiss("dismissed"));r&&r.decisionId!==e.decision_id&&(r.dismiss(),(f=this.outcomeTracker)==null||f.dispatch(r.decisionId,"dismissed",{reason:"superseded",by:e.decision_id})),(g=this.outcomeTracker)==null||g.registerPending(e.decision_id,(u=this.activeWorkflow)!=null?u:void 0),oe(o.el)}shouldRender(){var e,t;return((e=this.config)==null?void 0:e.renderInterventions)===!1||(t=this.runtime)!=null&&t.features&&this.runtime.features.interventions_enabled===!1?!1:typeof document!="undefined"}shouldTriggerEval(e){return e==="workflow.started"||e==="workflow.blocked"||e==="workflow.completed"||e==="workflow.abandoned"||e==="friction.detected"||e==="support.sentiment_negative"||e==="expansion.intent_detected"||e==="expansion.ceiling_hit"}pushRing(e){for(this.ring.push(e);this.ring.length>Pe;)this.ring.shift()}themeFromRuntime(){var e;return(e=this.runtime)==null?void 0:e.theme}readCachedConfig(){if(typeof localStorage=="undefined")return null;try{let e=localStorage.getItem(fe);if(!e)return null;let t=JSON.parse(e);return Date.now()-t.at>Le?null:t.data}catch(e){return null}}writeCachedConfig(e){if(typeof localStorage!="undefined")try{localStorage.setItem(fe,JSON.stringify({at:Date.now(),data:e}))}catch(t){}}log(...e){var t;(t=this.config)!=null&&t.debug&&typeof console!="undefined"&&console.warn("[holdy]",...e)}},me=new X,Oe=me;return _e(Be);})();
|
|
255
|
-
//# sourceMappingURL=holdy.iife.js.map
|
package/dist/holdy.iife.js.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts", "../src/queue.ts", "../src/transport.ts", "../src/outcome.ts", "../src/store.ts", "../src/anchor.ts", "../src/auto-capture.ts", "../src/types.ts", "../src/render/styles.ts", "../src/render/root.ts", "../src/render/kinds/shared.ts", "../src/render/kinds/tooltip.ts", "../src/render/kinds/banner.ts", "../src/render/kinds/cta.ts", "../src/render/kinds/modal.ts", "../src/render/kinds/checklist.ts", "../src/render/kinds/spotlight.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n AccountIdentity,\n CanonicalPrimitive,\n DecisionListener,\n DecisionResult,\n HoldyConfig,\n IdentifyOptions,\n InterventionPayload,\n OutcomeValue,\n RuntimeConfig,\n ThemeConfig,\n TrackOptions,\n UserIdentity,\n} from './types'\nimport { Transport } from './transport'\nimport { OutcomeTracker } from './outcome'\nimport { InterventionStore } from './store'\nimport { resolveAnchor } from './anchor'\nimport { installAutoCapture } from './auto-capture'\nimport { appendToRoot, ensureRoot } from './render/root'\nimport { renderTooltip } from './render/kinds/tooltip'\nimport { renderBanner } from './render/kinds/banner'\nimport { renderCta } from './render/kinds/cta'\nimport { renderModal } from './render/kinds/modal'\nimport { renderChecklist } from './render/kinds/checklist'\nimport { renderSpotlight } from './render/kinds/spotlight'\nimport type { RenderControl, RenderHandlers } from './render/kinds/shared'\n\nconst RING_BUFFER_LIMIT = 20\nconst CONFIG_CACHE_KEY = '__holdy_runtime_config_v1'\nconst CONFIG_CACHE_TTL_MS = 60 * 60 * 1000\nconst EVAL_THROTTLE_MS = 1500\n\ninterface RingEntry {\n primitive: CanonicalPrimitive\n payload: Record<string, unknown>\n occurred_at: string\n}\n\nclass HoldySdk {\n private config: HoldyConfig | null = null\n private transport: Transport | null = null\n private outcomeTracker: OutcomeTracker | null = null\n private store: InterventionStore = new InterventionStore()\n private runtime: RuntimeConfig | null = null\n private activeWorkflow: string | null = null\n private sentiment: 'positivo' | 'neutro' | 'negativo' | 'urgente' | null = null\n private readonly ring: RingEntry[] = []\n private listeners: DecisionListener[] = []\n private lastEvalAt = 0\n private initialized = false\n private autoCaptureCleanup: (() => void) | null = null\n\n async init(config: HoldyConfig): Promise<void> {\n if (this.initialized) {\n this.log('init called twice \u00B7 ignoring')\n return\n }\n if (!config.apiKey) {\n throw new Error('[holdy] apiKey is required')\n }\n this.config = config\n this.transport = new Transport(config)\n this.outcomeTracker = new OutcomeTracker(this.transport)\n this.initialized = true\n\n const cached = this.readCachedConfig()\n if (cached) this.runtime = cached\n\n const fresh = await this.transport.fetchRuntimeConfig()\n if (fresh) {\n this.runtime = fresh\n this.writeCachedConfig(fresh)\n }\n\n if (this.shouldRender()) {\n ensureRoot(this.themeFromRuntime())\n }\n\n // Stage 28 G_auto \u00B7 auto-capture de page views.\n // Habilita s\u00F3 quando customer pediu explicitamente \u00B7 default off pra\n // back-compat. Ring buffer + transport recebem session.activity igual\n // se viesse de track() manual \u00B7 decision engine consome no contexto.\n if (config.autoCapture) {\n this.autoCaptureCleanup = installAutoCapture((path, title, referrer, kind) => {\n void this.track('session.activity', {\n kind,\n path,\n ...(title ? { title } : {}),\n ...(referrer ? { referrer } : {}),\n }, { skipEval: kind !== 'route_change' })\n })\n }\n }\n\n /**\n * Identifica conta + usu\u00E1rio corrente.\n *\n * - `accountId/userId/sessionId` hidratam config local pra evaluate/track.\n * - `account/user` (metadata rica) disparam upsert best-effort em\n * /v1/accounts/upsert. Backend COALESCE \u2192 nunca sobrescreve campos do\n * wizard manual. Em sucesso, account_id Holdy retornado hidrata config\n * local automaticamente (cliente n\u00E3o precisa saber UUID).\n */\n identify(opts: IdentifyOptions): void {\n if (!this.config) return\n if (opts.accountId !== undefined) this.config.accountId = opts.accountId\n if (opts.userId !== undefined) this.config.userId = opts.userId\n if (opts.sessionId !== undefined) this.config.sessionId = opts.sessionId\n\n if (opts.account || opts.user) {\n void this.upsertIdentityRich(opts.account, opts.user)\n }\n }\n\n private async upsertIdentityRich(\n account: AccountIdentity | undefined,\n user: UserIdentity | undefined,\n ): Promise<void> {\n if (!this.transport || !account) return\n const result = await this.transport.upsertAccount({ account, user })\n if (!result || !this.config) return\n if (!this.config.accountId) this.config.accountId = result.account_id\n if (!this.config.userId && result.account_user_id) {\n this.config.userId = result.account_user_id\n }\n }\n\n setWorkflow(workflowKey: string | null | undefined): void {\n this.activeWorkflow = workflowKey ?? null\n }\n\n setSentiment(sentiment: 'positivo' | 'neutro' | 'negativo' | 'urgente' | null): void {\n this.sentiment = sentiment\n }\n\n async track(\n primitive: CanonicalPrimitive,\n payload: Record<string, unknown> = {},\n opts: TrackOptions = {},\n ): Promise<void> {\n if (!this.config || !this.transport) {\n this.log('track called before init')\n return\n }\n const occurred_at = new Date().toISOString()\n const entry: RingEntry = { primitive, payload, occurred_at }\n this.pushRing(entry)\n\n // workflow tracking auto-sync\n if (primitive === 'workflow.started' && typeof payload.workflow === 'string') {\n this.activeWorkflow = payload.workflow\n }\n if (\n (primitive === 'workflow.completed' || primitive === 'workflow.abandoned') &&\n typeof payload.workflow === 'string' &&\n this.activeWorkflow === payload.workflow\n ) {\n this.activeWorkflow = null\n }\n if (opts.workflow !== undefined) this.activeWorkflow = opts.workflow\n\n // ingest fire-and-forget\n this.transport.ingestBatch([\n {\n primitive,\n occurred_at,\n account_id: this.config.accountId,\n user_id: this.config.userId,\n session_id: this.config.sessionId,\n payload,\n },\n ])\n\n if (opts.skipEval) return\n if (!this.shouldTriggerEval(primitive)) return\n\n await this.evaluateInternal()\n }\n\n async evaluate(): Promise<DecisionResult | null> {\n return this.evaluateInternal(true)\n }\n\n onDecision(listener: DecisionListener): () => void {\n this.listeners.push(listener)\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener)\n }\n }\n\n reportOutcome(\n decisionId: string,\n outcome: OutcomeValue,\n metadata?: Record<string, unknown>,\n ): void {\n this.outcomeTracker?.dispatch(decisionId, outcome, metadata)\n }\n\n destroy(): void {\n this.transport?.destroy()\n if (this.autoCaptureCleanup) {\n try { this.autoCaptureCleanup() } catch { /* ignore */ }\n this.autoCaptureCleanup = null\n }\n this.config = null\n this.transport = null\n this.outcomeTracker = null\n this.runtime = null\n this.activeWorkflow = null\n this.listeners = []\n this.ring.length = 0\n this.initialized = false\n }\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n private async evaluateInternal(force = false): Promise<DecisionResult | null> {\n if (!this.transport || !this.config?.accountId) {\n this.log('evaluate skipped \u00B7 no accountId set \u00B7 call identify first')\n return null\n }\n const now = Date.now()\n if (!force && now - this.lastEvalAt < EVAL_THROTTLE_MS) {\n return null\n }\n this.lastEvalAt = now\n\n const evalInput: {\n account_id: string\n current_workflow?: string\n recent_primitives: Array<{\n primitive: CanonicalPrimitive\n payload: Record<string, unknown>\n occurred_at: string\n }>\n consumer: 'ui' | 'csm' | 'agent'\n recent_sentiment?: 'positivo' | 'neutro' | 'negativo' | 'urgente'\n } = {\n account_id: this.config.accountId,\n recent_primitives: [...this.ring],\n consumer: this.config.consumer ?? 'ui',\n }\n if (this.activeWorkflow) evalInput.current_workflow = this.activeWorkflow\n if (this.sentiment) evalInput.recent_sentiment = this.sentiment\n\n const result = await this.transport.evaluate(evalInput)\n if (!result) return null\n\n this.listeners.forEach((l) => {\n try {\n l(result)\n } catch (e) {\n this.log('listener error', e)\n }\n })\n\n if (result.decision_type === 'intervention' && this.shouldRender()) {\n void this.renderDecision(result)\n }\n\n return result\n }\n\n private async renderDecision(decision: DecisionResult): Promise<void> {\n const payload = decision.decision_payload as InterventionPayload\n if (!payload || typeof payload.kind !== 'string' || typeof payload.text !== 'string') {\n this.outcomeTracker?.dispatch(decision.decision_id, 'failed', { reason: 'invalid_payload' })\n return\n }\n\n const handlers: RenderHandlers = {\n onExecuted: (meta) => this.outcomeTracker?.dispatch(decision.decision_id, 'executed', meta),\n onDismissed: (meta) => this.outcomeTracker?.dispatch(decision.decision_id, 'dismissed', meta),\n onFailed: (meta) => this.outcomeTracker?.dispatch(decision.decision_id, 'failed', meta),\n }\n\n let control: RenderControl | null = null\n try {\n switch (payload.kind) {\n case 'tooltip': {\n const anchor = await resolveAnchor(payload.anchor_selector)\n if (!anchor) {\n this.outcomeTracker?.dispatch(decision.decision_id, 'no_show', {\n reason: 'anchor_unresolved',\n selector: payload.anchor_selector ?? null,\n })\n return\n }\n control = renderTooltip(payload, anchor, handlers)\n break\n }\n case 'banner':\n control = renderBanner(payload, handlers)\n break\n case 'cta':\n control = renderCta(payload, handlers)\n break\n case 'modal':\n control = renderModal(payload, handlers)\n break\n case 'checklist':\n control = renderChecklist(payload, decision.decision_id, handlers)\n break\n case 'spotlight': {\n const anchor = await resolveAnchor(payload.anchor_selector)\n if (!anchor) {\n this.outcomeTracker?.dispatch(decision.decision_id, 'no_show', {\n reason: 'anchor_unresolved',\n selector: payload.anchor_selector ?? null,\n })\n return\n }\n control = renderSpotlight(payload, anchor, handlers)\n break\n }\n default:\n this.outcomeTracker?.dispatch(decision.decision_id, 'no_show', {\n reason: 'kind_not_supported',\n kind: payload.kind,\n })\n return\n }\n } catch (e) {\n this.log('render error', e)\n handlers.onFailed({ error: String(e) })\n return\n }\n\n if (!control) return\n\n // Slot collision: store decide quem fica \u00B7 sup ersedido \u00E9 dismissado.\n const superseded = this.store.claim(\n payload.kind,\n decision.decision_id,\n decision.confidence,\n payload.anchor_selector,\n () => control!.dismiss('dismissed'),\n )\n if (superseded && superseded.decisionId !== decision.decision_id) {\n superseded.dismiss()\n this.outcomeTracker?.dispatch(superseded.decisionId, 'dismissed', {\n reason: 'superseded',\n by: decision.decision_id,\n })\n }\n\n this.outcomeTracker?.registerPending(decision.decision_id, this.activeWorkflow ?? undefined)\n appendToRoot(control.el)\n }\n\n private shouldRender(): boolean {\n if (this.config?.renderInterventions === false) return false\n if (this.runtime?.features && this.runtime.features.interventions_enabled === false) return false\n return typeof document !== 'undefined'\n }\n\n private shouldTriggerEval(primitive: CanonicalPrimitive): boolean {\n // Eventos que tipicamente disparam decis\u00E3o (state-change ou friction).\n return (\n primitive === 'workflow.started' ||\n primitive === 'workflow.blocked' ||\n primitive === 'workflow.completed' ||\n primitive === 'workflow.abandoned' ||\n primitive === 'friction.detected' ||\n primitive === 'support.sentiment_negative' ||\n primitive === 'expansion.intent_detected' ||\n primitive === 'expansion.ceiling_hit'\n )\n }\n\n private pushRing(entry: RingEntry): void {\n this.ring.push(entry)\n while (this.ring.length > RING_BUFFER_LIMIT) this.ring.shift()\n }\n\n private themeFromRuntime(): ThemeConfig | undefined {\n return this.runtime?.theme\n }\n\n private readCachedConfig(): RuntimeConfig | null {\n if (typeof localStorage === 'undefined') return null\n try {\n const raw = localStorage.getItem(CONFIG_CACHE_KEY)\n if (!raw) return null\n const parsed = JSON.parse(raw) as { at: number; data: RuntimeConfig }\n if (Date.now() - parsed.at > CONFIG_CACHE_TTL_MS) return null\n return parsed.data\n } catch {\n return null\n }\n }\n\n private writeCachedConfig(config: RuntimeConfig): void {\n if (typeof localStorage === 'undefined') return\n try {\n localStorage.setItem(CONFIG_CACHE_KEY, JSON.stringify({ at: Date.now(), data: config }))\n } catch {\n // storage quota \u00B7 ignore\n }\n }\n\n private log(...args: unknown[]): void {\n if (this.config?.debug && typeof console !== 'undefined') {\n console.warn('[holdy]', ...args)\n }\n }\n}\n\nexport const Holdy = new HoldySdk()\n\nexport type {\n AccountIdentity,\n CanonicalPrimitive,\n DecisionResult,\n DecisionListener,\n HoldyConfig,\n IdentifyOptions,\n InterventionPayload,\n OutcomeValue,\n RuntimeConfig,\n ThemeConfig,\n TrackOptions,\n UserIdentity,\n} from './types'\n\nexport default Holdy\n", "/**\n * Event queue \u00B7 IndexedDB-backed retry com exponential backoff.\n *\n * Por que existe: SDK fire-and-forget perde eventos quando rede falha\n * (offline \u00B7 429 \u00B7 500 transit\u00F3rio \u00B7 pagehide mid-flight). Sem fila, drop\n * silencioso \u00B7 learning loop pega s\u00F3 os 80-90% que chegam.\n *\n * Comportamento:\n * \u00B7 enqueue(events) tenta enviar imediatamente. Se falha (ou j\u00E1 tinha fila),\n * grava em IndexedDB com nextRetryAt = agora + 1s.\n * \u00B7 flusher background polla a cada 5s, dequeue ordenado por nextRetryAt,\n * manda batch. Sucesso \u2192 delete da fila. Falha \u2192 backoff pr\u00F3ximo.\n * \u00B7 Backoff: 1s \u2192 2s \u2192 4s \u2192 8s \u2192 16s. Ap\u00F3s 5 tentativas, drop com log.\n * \u00B7 Cap 1000 itens (rough proxy 50KB cada \u00B7 50MB max). Quando cheio, drop\n * o mais antigo (FIFO).\n * \u00B7 pagehide: tenta drain s\u00EDncrono final via keepalive fetch (browser\n * entrega depois mesmo se aba fechou).\n *\n * Fallback: ambientes sem IndexedDB (SSR \u00B7 Privacy mode em Safari r\u00EDgido) caem\n * pra fila em mem\u00F3ria \u2014 perde tudo no reload, mas SDK ainda funciona.\n */\n\nconst DB_NAME = 'holdy_sdk_v1'\nconst STORE_NAME = 'event_queue'\nconst MAX_QUEUE_SIZE = 1000\nconst MAX_ATTEMPTS = 5\nconst FLUSH_INTERVAL_MS = 5000\nconst BACKOFF_BASE_MS = 1000\n\nexport interface QueuedBatch {\n /** Auto-increment key. */\n id?: number\n /** Eventos serializados (j\u00E1 com idempotency_key gerado). */\n events: unknown[]\n attempts: number\n next_retry_at: number\n created_at: number\n}\n\nexport interface SendFn {\n /** Retorna true em sucesso, false em falha (caller decide retry). */\n (body: { events: unknown[] }): Promise<boolean>\n}\n\ninterface QueueDriver {\n add(batch: Omit<QueuedBatch, 'id'>): Promise<void>\n /** Retorna itens eleg\u00EDveis pra retry (next_retry_at <= now), ordenados. */\n pickDue(now: number, limit: number): Promise<QueuedBatch[]>\n update(item: QueuedBatch): Promise<void>\n remove(id: number): Promise<void>\n count(): Promise<number>\n dropOldest(n: number): Promise<void>\n /** Pra pagehide drain. */\n all(): Promise<QueuedBatch[]>\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * IndexedDB driver\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 isIdbAvailable(): boolean {\n return typeof indexedDB !== 'undefined'\n}\n\nlet dbPromise: Promise<IDBDatabase> | null = null\n\nfunction openDb(): Promise<IDBDatabase> {\n if (dbPromise) return dbPromise\n dbPromise = new Promise((resolve, reject) => {\n const req = indexedDB.open(DB_NAME, 1)\n req.onupgradeneeded = () => {\n const db = req.result\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: 'id', autoIncrement: true })\n }\n }\n req.onsuccess = () => resolve(req.result)\n req.onerror = () => reject(req.error)\n })\n return dbPromise\n}\n\nfunction withStore<T>(\n mode: IDBTransactionMode,\n fn: (store: IDBObjectStore) => IDBRequest | Promise<T>,\n): Promise<T> {\n return openDb().then(\n (db) =>\n new Promise<T>((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, mode)\n const store = tx.objectStore(STORE_NAME)\n let result: T | undefined\n try {\n const out = fn(store)\n if (out instanceof IDBRequest) {\n out.onsuccess = () => {\n result = out.result as T\n }\n out.onerror = () => reject(out.error)\n } else {\n void out.then((v) => (result = v))\n }\n } catch (e) {\n reject(e)\n return\n }\n tx.oncomplete = () => resolve(result as T)\n tx.onerror = () => reject(tx.error)\n tx.onabort = () => reject(tx.error)\n }),\n )\n}\n\nconst idbDriver: QueueDriver = {\n async add(batch) {\n await withStore('readwrite', (store) => store.add(batch))\n },\n async pickDue(now, limit) {\n const all = await withStore<QueuedBatch[]>('readonly', (store) => store.getAll())\n return (all ?? [])\n .filter((b) => b.next_retry_at <= now)\n .sort((a, b) => a.next_retry_at - b.next_retry_at)\n .slice(0, limit)\n },\n async update(item) {\n await withStore('readwrite', (store) => store.put(item))\n },\n async remove(id) {\n await withStore('readwrite', (store) => store.delete(id))\n },\n async count() {\n return withStore<number>('readonly', (store) => store.count())\n },\n async dropOldest(n) {\n const all = await withStore<QueuedBatch[]>('readonly', (store) => store.getAll())\n const sorted = (all ?? []).sort((a, b) => a.created_at - b.created_at).slice(0, n)\n for (const item of sorted) {\n if (item.id !== undefined) {\n await withStore('readwrite', (store) => store.delete(item.id as number))\n }\n }\n },\n async all() {\n return (await withStore<QueuedBatch[]>('readonly', (store) => store.getAll())) ?? []\n },\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * In-memory fallback driver\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nclass MemoryDriver implements QueueDriver {\n private items: QueuedBatch[] = []\n private nextId = 1\n\n async add(batch: Omit<QueuedBatch, 'id'>): Promise<void> {\n this.items.push({ ...batch, id: this.nextId++ })\n }\n async pickDue(now: number, limit: number): Promise<QueuedBatch[]> {\n return this.items\n .filter((b) => b.next_retry_at <= now)\n .sort((a, b) => a.next_retry_at - b.next_retry_at)\n .slice(0, limit)\n }\n async update(item: QueuedBatch): Promise<void> {\n const idx = this.items.findIndex((i) => i.id === item.id)\n if (idx >= 0) this.items[idx] = item\n }\n async remove(id: number): Promise<void> {\n this.items = this.items.filter((i) => i.id !== id)\n }\n async count(): Promise<number> {\n return this.items.length\n }\n async dropOldest(n: number): Promise<void> {\n this.items.sort((a, b) => a.created_at - b.created_at)\n this.items.splice(0, n)\n }\n async all(): Promise<QueuedBatch[]> {\n return [...this.items]\n }\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * EventQueue \u00B7 facade\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport class EventQueue {\n private readonly driver: QueueDriver\n private readonly send: SendFn\n private flushTimer: ReturnType<typeof setInterval> | null = null\n private flushing = false\n private readonly log: (...args: unknown[]) => void\n\n constructor(send: SendFn, log: (...args: unknown[]) => void = () => undefined) {\n this.driver = isIdbAvailable() ? idbDriver : new MemoryDriver()\n this.send = send\n this.log = log\n this.startFlusher()\n this.bindPagehide()\n }\n\n /**\n * Tenta enviar imediato; se falhar OU j\u00E1 houver fila pendente (ordem),\n * adiciona com next_retry_at = agora + 1s.\n */\n async enqueue(events: unknown[]): Promise<void> {\n if (events.length === 0) return\n\n // Se j\u00E1 h\u00E1 fila, vai pro final pra preservar ordem temporal.\n const pending = await this.driver.count().catch(() => 0)\n if (pending === 0) {\n const ok = await this.send({ events }).catch(() => false)\n if (ok) return\n }\n\n // Cap \u00B7 drop oldest se cheia\n if (pending >= MAX_QUEUE_SIZE) {\n const overflow = pending - MAX_QUEUE_SIZE + 1\n await this.driver.dropOldest(overflow).catch(() => undefined)\n this.log('queue full \u00B7 dropped', overflow, 'oldest batches')\n }\n\n const now = Date.now()\n await this.driver\n .add({\n events,\n attempts: 0,\n next_retry_at: now + BACKOFF_BASE_MS,\n created_at: now,\n })\n .catch((e) => this.log('queue add failed', e))\n }\n\n private startFlusher(): void {\n if (this.flushTimer) return\n if (typeof setInterval === 'undefined') return\n this.flushTimer = setInterval(() => {\n void this.flushOnce()\n }, FLUSH_INTERVAL_MS)\n }\n\n private async flushOnce(): Promise<void> {\n if (this.flushing) return\n this.flushing = true\n try {\n const now = Date.now()\n const due = await this.driver.pickDue(now, 10).catch(() => [])\n for (const item of due) {\n const ok = await this.send({ events: item.events }).catch(() => false)\n if (ok && item.id !== undefined) {\n await this.driver.remove(item.id).catch(() => undefined)\n continue\n }\n const attempts = item.attempts + 1\n if (attempts >= MAX_ATTEMPTS) {\n if (item.id !== undefined) await this.driver.remove(item.id).catch(() => undefined)\n this.log('dropped batch after max attempts', { events: item.events.length })\n continue\n }\n const backoff = BACKOFF_BASE_MS * Math.pow(2, attempts)\n await this.driver\n .update({ ...item, attempts, next_retry_at: Date.now() + backoff })\n .catch(() => undefined)\n }\n } finally {\n this.flushing = false\n }\n }\n\n private bindPagehide(): void {\n if (typeof window === 'undefined') return\n const drain = (): void => {\n // Pagehide \u00E9 sincr\u00F4nico \u00B7 n\u00E3o podemos await IDB. Em vez disso, dispara\n // 1 fetch keepalive por batch pendente. Browser entrega ap\u00F3s close.\n void this.driver\n .all()\n .then((items) => {\n for (const item of items) {\n void this.send({ events: item.events }).catch(() => undefined)\n }\n })\n .catch(() => undefined)\n }\n window.addEventListener('pagehide', drain)\n window.addEventListener('beforeunload', drain)\n }\n\n /** Pra testes. */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer)\n this.flushTimer = null\n }\n }\n}\n", "import type {\n AccountIdentity,\n CanonicalPrimitive,\n DecisionResult,\n HoldyConfig,\n RuntimeConfig,\n UserIdentity,\n} from './types'\nimport { EventQueue } from './queue'\n\nconst DEFAULT_API_URL = 'https://app.holdy.com.br/api/v1'\n\nexport class Transport {\n private readonly apiKey: string\n private readonly apiUrl: string\n private readonly debug: boolean\n private readonly queue: EventQueue\n\n constructor(config: HoldyConfig) {\n this.apiKey = config.apiKey\n this.apiUrl = (config.apiUrl ?? DEFAULT_API_URL).replace(/\\/$/, '')\n this.debug = config.debug ?? false\n this.queue = new EventQueue(\n (body) => this.sendBatch(body.events),\n (...args) => this.log(...args),\n )\n }\n\n private headers(): Record<string, string> {\n return {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.apiKey}`,\n }\n }\n\n async fetchRuntimeConfig(): Promise<RuntimeConfig | null> {\n try {\n const res = await fetch(`${this.apiUrl}/runtime/config`, {\n method: 'GET',\n headers: this.headers(),\n credentials: 'omit',\n mode: 'cors',\n })\n if (!res.ok) {\n this.log('runtime/config failed', res.status)\n return null\n }\n return (await res.json()) as RuntimeConfig\n } catch (e) {\n this.log('runtime/config error', e)\n return null\n }\n }\n\n async evaluate(input: {\n account_id: string\n current_workflow?: string\n recent_primitives?: Array<{\n primitive: CanonicalPrimitive\n payload: Record<string, unknown>\n occurred_at: string\n }>\n recent_sentiment?: 'positivo' | 'neutro' | 'negativo' | 'urgente'\n consumer?: 'ui' | 'csm' | 'agent'\n }): Promise<DecisionResult | null> {\n try {\n const res = await fetch(`${this.apiUrl}/decisions/evaluate`, {\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify({ consumer: 'ui', ...input }),\n credentials: 'omit',\n mode: 'cors',\n })\n if (!res.ok) {\n this.log('decisions/evaluate failed', res.status)\n return null\n }\n return (await res.json()) as DecisionResult\n } catch (e) {\n this.log('decisions/evaluate error', e)\n return null\n }\n }\n\n /**\n * Event ingest \u00B7 delegado pra EventQueue (IndexedDB + exponential backoff).\n * Tenta envio imediato; se falhar, persiste e retry em background.\n */\n ingestBatch(events: Array<{\n primitive: CanonicalPrimitive\n occurred_at: string\n account_id?: string\n user_id?: string\n session_id?: string\n payload: Record<string, unknown>\n idempotency_key?: string\n }>): void {\n if (events.length === 0) return\n void this.queue.enqueue(events)\n }\n\n /**\n * Send raw \u00B7 usado pelo queue. Retorna true em sucesso (2xx), false em\n * falha (rede ou 4xx/5xx).\n *\n * IMPORTANTE: 4xx \u00E9 tratado como falha permanente \u2014 n\u00E3o vale retry. Mas\n * a fila n\u00E3o distingue (mant\u00E9m pra retry simples). MAX_ATTEMPTS = 5 limita\n * o desperd\u00EDcio. Refinamento (4xx \u2192 drop imediato) fica pra Wave 3.\n */\n private async sendBatch(events: unknown[]): Promise<boolean> {\n try {\n const res = await fetch(`${this.apiUrl}/events/batch`, {\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify({ events }),\n credentials: 'omit',\n mode: 'cors',\n keepalive: true,\n })\n return res.ok\n } catch (e) {\n this.log('events/batch network error', e)\n return false\n }\n }\n\n /**\n * Upsert account + opcional user via /v1/accounts/upsert.\n *\n * Best-effort fire-and-forget. Backend COALESCE n\u00E3o sobrescreve campos n\u00E3o-nulos.\n * Retorna account_id (UUID Holdy) pra hidratar config local; null em falha.\n */\n async upsertAccount(payload: {\n account: AccountIdentity\n user?: UserIdentity\n }): Promise<{ account_id: string; account_user_id: string | null } | null> {\n try {\n const res = await fetch(`${this.apiUrl}/accounts/upsert`, {\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(payload),\n credentials: 'omit',\n mode: 'cors',\n keepalive: true,\n })\n if (!res.ok) {\n this.log('accounts/upsert failed', res.status)\n return null\n }\n return (await res.json()) as { account_id: string; account_user_id: string | null }\n } catch (e) {\n this.log('accounts/upsert error', e)\n return null\n }\n }\n\n reportOutcome(\n decisionId: string,\n outcome: 'executed' | 'dismissed' | 'converted' | 'no_show' | 'failed',\n metadata?: Record<string, unknown>,\n ): void {\n const url = `${this.apiUrl}/decisions/${encodeURIComponent(decisionId)}/outcome`\n fetch(url, {\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify({ outcome, metadata }),\n credentials: 'omit',\n mode: 'cors',\n keepalive: true,\n }).catch((e) => this.log('decisions/outcome error', e))\n }\n\n private log(...args: unknown[]): void {\n if (this.debug && typeof console !== 'undefined') {\n console.warn('[holdy]', ...args)\n }\n }\n\n destroy(): void {\n this.queue.destroy()\n }\n}\n", "import type { OutcomeValue } from './types'\nimport type { Transport } from './transport'\n\ninterface PendingDecision {\n id: string\n workflow?: string | undefined\n startedAt: number\n}\n\n/**\n * Outcome tracker \u00B7 explicit only.\n *\n * - executed \u2192 ack via UI handler.\n * - dismissed \u2192 ack via UI handler.\n * - no_show \u2192 SDK detecta anchor n\u00E3o resolvido em 5s.\n * - failed \u2192 exception capturada pelo render boundary.\n * - converted \u2192 conversion cron server-side faz join workflow.completed.\n */\nexport class OutcomeTracker {\n private readonly transport: Transport\n private readonly pending = new Map<string, PendingDecision>()\n\n constructor(transport: Transport) {\n this.transport = transport\n }\n\n registerPending(decisionId: string, workflow: string | undefined): void {\n this.pending.set(decisionId, {\n id: decisionId,\n workflow,\n startedAt: Date.now(),\n })\n }\n\n dispatch(decisionId: string, outcome: OutcomeValue, metadata?: Record<string, unknown>): void {\n if (!this.pending.has(decisionId) && outcome !== 'failed') {\n // unknown decision \u00B7 still report failed/dismissed since they're idempotent\n this.transport.reportOutcome(decisionId, outcome, metadata)\n return\n }\n this.pending.delete(decisionId)\n this.transport.reportOutcome(decisionId, outcome, {\n ...metadata,\n latency_ms: metadata?.latency_ms ?? Date.now() - (this.pending.get(decisionId)?.startedAt ?? Date.now()),\n })\n }\n\n hasPending(decisionId: string): boolean {\n return this.pending.has(decisionId)\n }\n}\n", "import type { InterventionKind } from './types'\n\ninterface ActiveSlot {\n decisionId: string\n confidence: number\n kind: InterventionKind\n dismiss: () => void\n}\n\n/**\n * Active intervention slots \u00B7 prioridade por confidence.\n *\n * Caps globais:\n * - 1 banner global\n * - 1 modal global (Wave 2 \u00B7 UX bloqueia tudo, \u00FAnico)\n * - 1 checklist global (Wave 2 \u00B7 sticky bottom-right)\n * - N tooltips, 1 por anchor\n * - N spotlights, 1 por anchor (Wave 2)\n * - 1 CTA global (sticky bottom-right)\n *\n * Modal e checklist + cta competem pelo mesmo \"espa\u00E7o mental\" do usu\u00E1rio \u00B7\n * a pr\u00F3xima implementa\u00E7\u00E3o pode consolidar (1 floating element no canto).\n * Wave 2 mant\u00E9m slots separados pra simplicidade.\n *\n * Quando 2 decisions reivindicam o mesmo slot, a de menor confidence perde.\n */\nexport class InterventionStore {\n private readonly tooltipsByAnchor = new Map<string, ActiveSlot>()\n private readonly spotlightsByAnchor = new Map<string, ActiveSlot>()\n private banner: ActiveSlot | null = null\n private modal: ActiveSlot | null = null\n private checklist: ActiveSlot | null = null\n private cta: ActiveSlot | null = null\n\n /** Tenta reivindicar slot. Retorna previous slot que precisa ser dismissado (caller). */\n claim(\n kind: InterventionKind,\n decisionId: string,\n confidence: number,\n anchorSelector: string | undefined,\n dismiss: () => void,\n ): ActiveSlot | null {\n const slot: ActiveSlot = { decisionId, confidence, kind, dismiss }\n\n if (kind === 'tooltip') {\n const key = anchorSelector ?? '__no_anchor__'\n const prev = this.tooltipsByAnchor.get(key)\n if (prev && prev.confidence >= confidence) return slot\n this.tooltipsByAnchor.set(key, slot)\n return prev ?? null\n }\n\n if (kind === 'spotlight') {\n const key = anchorSelector ?? '__no_anchor__'\n const prev = this.spotlightsByAnchor.get(key)\n if (prev && prev.confidence >= confidence) return slot\n this.spotlightsByAnchor.set(key, slot)\n return prev ?? null\n }\n\n if (kind === 'banner') {\n const prev = this.banner\n if (prev && prev.confidence >= confidence) return slot\n this.banner = slot\n return prev ?? null\n }\n\n if (kind === 'modal') {\n const prev = this.modal\n if (prev && prev.confidence >= confidence) return slot\n this.modal = slot\n return prev ?? null\n }\n\n if (kind === 'checklist') {\n const prev = this.checklist\n if (prev && prev.confidence >= confidence) return slot\n this.checklist = slot\n return prev ?? null\n }\n\n if (kind === 'cta') {\n const prev = this.cta\n if (prev && prev.confidence >= confidence) return slot\n this.cta = slot\n return prev ?? null\n }\n\n return null\n }\n\n release(decisionId: string): void {\n if (this.banner?.decisionId === decisionId) this.banner = null\n if (this.modal?.decisionId === decisionId) this.modal = null\n if (this.checklist?.decisionId === decisionId) this.checklist = null\n if (this.cta?.decisionId === decisionId) this.cta = null\n for (const map of [this.tooltipsByAnchor, this.spotlightsByAnchor]) {\n for (const [k, slot] of map) {\n if (slot.decisionId === decisionId) {\n map.delete(k)\n break\n }\n }\n }\n }\n}\n", "/**\n * Anchor resolver \u00B7 MutationObserver-based.\n *\n * Cliente do produto pode renderizar o anchor depois do decision chegar\n * (SPA route, lazy mount). Resolver espera at\u00E9 5s antes de desistir.\n * Single observer global \u00B7 cap retries por selector.\n */\n\nconst RESOLVE_TIMEOUT_MS = 5000\n\ninterface PendingAnchor {\n selector: string\n resolve: (el: Element | null) => void\n cleanup: () => void\n}\n\nconst pending = new Set<PendingAnchor>()\nlet observer: MutationObserver | null = null\n\nfunction ensureObserver(): void {\n if (observer || typeof MutationObserver === 'undefined' || typeof document === 'undefined') return\n observer = new MutationObserver(() => {\n if (pending.size === 0) return\n pending.forEach((entry) => {\n const el = document.querySelector(entry.selector)\n if (el) {\n entry.cleanup()\n entry.resolve(el)\n }\n })\n if (pending.size === 0) stopObserver()\n })\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['id', 'class', 'data-holdy-anchor'] })\n}\n\nfunction stopObserver(): void {\n if (observer) {\n observer.disconnect()\n observer = null\n }\n}\n\nexport function resolveAnchor(selector: string | undefined): Promise<Element | null> {\n if (!selector) return Promise.resolve(null)\n if (typeof document === 'undefined') return Promise.resolve(null)\n\n // Try sync first\n const existing = document.querySelector(selector)\n if (existing) return Promise.resolve(existing)\n\n return new Promise<Element | null>((resolve) => {\n let resolved = false\n const entry: PendingAnchor = {\n selector,\n resolve,\n cleanup: () => {\n if (resolved) return\n resolved = true\n pending.delete(entry)\n clearTimeout(timeoutId)\n if (pending.size === 0) stopObserver()\n },\n }\n const timeoutId = setTimeout(() => {\n entry.cleanup()\n resolve(null)\n }, RESOLVE_TIMEOUT_MS)\n\n pending.add(entry)\n ensureObserver()\n })\n}\n", "/**\n * Auto-capture \u00B7 Stage 28 G_auto.\n *\n * Quando HoldyConfig.autoCapture=true, instalamos hooks globais que\n * emitem `session.activity` automaticamente:\n *\n * \u00B7 initial_load \u00B7 1x ao init\n * \u00B7 route_change \u00B7 cada history.pushState/replaceState/popstate\n * \u00B7 visibility_change \u00B7 p\u00E1gina voltou a ficar vis\u00EDvel\n *\n * Tudo client-side \u00B7 n\u00E3o precisa que o customer declare nada. Permite que\n * o widget de install do Holdy mostre \"\u2713 conectado\" segundos ap\u00F3s o user\n * carregar a p\u00E1gina.\n *\n * Idempotente \u00B7 re-rodar `installAutoCapture` \u00E9 no-op via guard global.\n * Cleanup ao destroy via array de unsubscribers retornado.\n */\n\nexport interface AutoCaptureEmit {\n (path: string, title: string | undefined, referrer: string | undefined, kind: 'initial_load' | 'route_change' | 'visibility_change'): void\n}\n\nconst INSTALLED_FLAG = '__holdy_autocapture_installed__'\nconst ROUTE_DEBOUNCE_MS = 50\n\ninterface GlobalWithFlag {\n [INSTALLED_FLAG]?: boolean\n history?: History\n}\n\nexport function installAutoCapture(emit: AutoCaptureEmit): () => void {\n if (typeof window === 'undefined' || typeof history === 'undefined') {\n return () => undefined\n }\n const w = window as unknown as GlobalWithFlag\n if (w[INSTALLED_FLAG]) {\n return () => undefined\n }\n w[INSTALLED_FLAG] = true\n\n const cleanups: Array<() => void> = []\n let lastPath = currentPath()\n let pendingRouteEmit: ReturnType<typeof setTimeout> | null = null\n\n function safeEmit(kind: 'initial_load' | 'route_change' | 'visibility_change'): void {\n try {\n const path = currentPath()\n const title = typeof document !== 'undefined' ? document.title : undefined\n const referrer = typeof document !== 'undefined' ? document.referrer || undefined : undefined\n emit(path, title, referrer, kind)\n } catch {\n // never throw from auto-capture \u00B7 n\u00E3o pode quebrar a app do cliente\n }\n }\n\n function scheduleRouteEmit(): void {\n // Debounce: pushState seguido de replaceState \u00E9 1 mudan\u00E7a l\u00F3gica.\n if (pendingRouteEmit) clearTimeout(pendingRouteEmit)\n pendingRouteEmit = setTimeout(() => {\n const path = currentPath()\n if (path !== lastPath) {\n lastPath = path\n safeEmit('route_change')\n }\n pendingRouteEmit = null\n }, ROUTE_DEBOUNCE_MS)\n }\n\n // 1) Initial load\n safeEmit('initial_load')\n\n // 2) Monkeypatch history.pushState/replaceState (SPA SDR navigation)\n const origPush = history.pushState\n const origReplace = history.replaceState\n history.pushState = function patchedPush(...args: Parameters<History['pushState']>) {\n const result = origPush.apply(this, args)\n scheduleRouteEmit()\n return result\n }\n history.replaceState = function patchedReplace(...args: Parameters<History['replaceState']>) {\n const result = origReplace.apply(this, args)\n scheduleRouteEmit()\n return result\n }\n cleanups.push(() => {\n history.pushState = origPush\n history.replaceState = origReplace\n })\n\n // 3) popstate \u00B7 bot\u00E3o voltar/avan\u00E7ar do browser\n const popHandler = (): void => scheduleRouteEmit()\n window.addEventListener('popstate', popHandler)\n cleanups.push(() => window.removeEventListener('popstate', popHandler))\n\n // 4) hashchange \u00B7 single-page apps que usam hash routing (router antigo)\n const hashHandler = (): void => scheduleRouteEmit()\n window.addEventListener('hashchange', hashHandler)\n cleanups.push(() => window.removeEventListener('hashchange', hashHandler))\n\n // 5) visibility_change \u00B7 tab voltou a ficar vis\u00EDvel depois de >5min\n let hiddenAt: number | null = null\n const visHandler = (): void => {\n if (typeof document === 'undefined') return\n if (document.visibilityState === 'hidden') {\n hiddenAt = Date.now()\n } else if (document.visibilityState === 'visible' && hiddenAt) {\n const elapsed = Date.now() - hiddenAt\n hiddenAt = null\n // Re-emit s\u00F3 se ficou hidden >5min \u00B7 evita flood quando user troca aba rapidinho\n if (elapsed > 5 * 60_000) safeEmit('visibility_change')\n }\n }\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', visHandler)\n cleanups.push(() => document.removeEventListener('visibilitychange', visHandler))\n }\n\n // Final cleanup function \u00B7 usado pelo destroy()\n return () => {\n if (pendingRouteEmit) clearTimeout(pendingRouteEmit)\n for (const c of cleanups) c()\n w[INSTALLED_FLAG] = false\n }\n}\n\nfunction currentPath(): string {\n if (typeof window === 'undefined' || !window.location) return '/'\n return window.location.pathname + window.location.search + window.location.hash\n}\n", "// Public types \u2014 keep in sync with backend canonical-v1.ts + decisions/engine.ts.\n\nexport type CanonicalPrimitive =\n | 'workflow.started'\n | 'workflow.progressed'\n | 'workflow.blocked'\n | 'workflow.completed'\n | 'workflow.abandoned'\n | 'outcome.progressed'\n | 'outcome.completed'\n | 'outcome.regressed'\n | 'friction.detected'\n | 'collaboration.invited'\n | 'collaboration.joined'\n | 'collaboration.deepened'\n | 'collaboration.weakened'\n | 'collaboration.champion_lost'\n | 'support.escalated'\n | 'support.sentiment_negative'\n | 'support.theme_detected'\n | 'expansion.intent_detected'\n | 'expansion.ceiling_hit'\n | 'memory.append'\n | 'session.activity'\n\nexport type DecisionType =\n | 'intervention'\n | 'briefing'\n | 'cs_task'\n | 'track_journey'\n | 'no_action'\n\nexport type InterventionKind =\n | 'tooltip'\n | 'banner'\n | 'modal'\n | 'checklist'\n | 'spotlight'\n | 'cta'\n\nexport interface ChecklistItem {\n /** ID est\u00E1vel \u00B7 persist\u00EAncia local + dedup. */\n id: string\n label: string\n /** Opcional \u00B7 link aberto ao clicar. Sem href, item s\u00F3 marca completed. */\n href?: string\n /** Workflow ou outcome primitive que marca esse item como completed quando emitido. */\n completed_event?: string\n /** Pr\u00E9-marcado \u00B7 server pode indicar que cliente j\u00E1 fez essa etapa. */\n completed?: boolean\n}\n\nexport interface InterventionPayload {\n kind: InterventionKind\n text: string\n /** T\u00EDtulo opcional \u00B7 usado em modal/checklist headers. */\n title?: string\n cta_text?: string\n cta_href?: string\n anchor_selector?: string\n /** Items pro kind=checklist. */\n items?: ChecklistItem[]\n}\n\nexport interface DecisionResult {\n decision_id: string\n decision_type: DecisionType\n decision_payload: InterventionPayload | Record<string, unknown>\n rule_key: string\n confidence: number\n reason: string\n decided_at: string\n}\n\nexport type OutcomeValue =\n | 'executed'\n | 'dismissed'\n | 'converted'\n | 'no_show'\n | 'failed'\n\nexport interface RuntimeConfig {\n api_version: string\n taxonomy_version: string\n organization_id: string\n thresholds: Record<string, number | string>\n features: {\n auto_attribution: boolean\n interventions_enabled: boolean\n consent_required: boolean\n }\n theme?: ThemeConfig\n}\n\nexport interface ThemeConfig {\n primary_color: string\n font_family: string\n border_radius_px: number\n position_offset_px: number\n}\n\nexport const DEFAULT_THEME: ThemeConfig = {\n primary_color: '#ca2121',\n font_family: 'inherit',\n border_radius_px: 8,\n position_offset_px: 8,\n}\n\nexport interface HoldyConfig {\n apiKey: string\n apiUrl?: string\n accountId?: string\n userId?: string\n sessionId?: string\n consumer?: 'ui' | 'csm' | 'agent'\n debug?: boolean\n /** Disables render runtime \u00B7 SDK s\u00F3 captura telemetry. */\n renderInterventions?: boolean\n /**\n * Stage 28 \u00B7 auto-capture de page views (initial_load + route_change +\n * visibility_change). Quando true, SDK monkeypatcha history.pushState/\n * replaceState + escuta popstate/visibilitychange e emite session.activity\n * sem c\u00F3digo manual. Default false pra back-compat.\n */\n autoCapture?: boolean\n}\n\n/**\n * Rich account metadata enviado pra /v1/accounts/upsert.\n * Backend usa COALESCE \u2014 n\u00E3o sobrescreve campos preenchidos no wizard manual.\n *\n * `external_id` \u00E9 o identificador do cliente (string opaca \u00B7 ex \"acct_abc123\").\n * Backend resolve via customer_identities(source='sdk') \u2192 accounts.id.\n */\nexport interface AccountIdentity {\n external_id: string\n name?: string\n logo_url?: string\n domain?: string\n plan?: string\n mrr?: number\n contract_start?: string\n contract_end?: string\n lifecycle_stage?: 'onboarding' | 'adoption' | 'expansion' | 'renewal' | 'churned'\n traits?: Record<string, string | number | boolean | null>\n}\n\nexport interface UserIdentity {\n external_id: string\n email?: string\n name?: string\n job_title?: string\n role?: 'decision_maker' | 'champion' | 'admin' | 'user' | 'unknown'\n}\n\nexport interface IdentifyOptions {\n /** ID interno Holdy (UUID) \u00B7 opcional \u00B7 usado pra retro-compat. */\n accountId?: string\n userId?: string\n sessionId?: string\n /** Metadata rica \u00B7 gera best-effort upsert em /v1/accounts/upsert. */\n account?: AccountIdentity\n user?: UserIdentity\n}\n\nexport interface TrackOptions {\n /** Pula chamada impl\u00EDcita ao decisions/evaluate. */\n skipEval?: boolean\n /** Workflow corrente \u00B7 override do estado interno. */\n workflow?: string\n}\n\nexport type DecisionListener = (decision: DecisionResult) => void\n", "import type { ThemeConfig } from '../types'\nimport { DEFAULT_THEME } from '../types'\n\nconst BASE_CSS = `\n:host {\n --holdy-primary: var(--holdy-cfg-primary, #ca2121);\n --holdy-font: var(--holdy-cfg-font, system-ui, -apple-system, sans-serif);\n --holdy-radius: var(--holdy-cfg-radius, 8px);\n --holdy-offset: var(--holdy-cfg-offset, 8px);\n --holdy-bg: #ffffff;\n --holdy-fg: #1a1a1a;\n --holdy-muted: #737373;\n --holdy-border: rgba(0, 0, 0, 0.08);\n --holdy-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);\n all: initial;\n font-family: var(--holdy-font);\n color: var(--holdy-fg);\n}\n\n@media (prefers-color-scheme: dark) {\n :host {\n --holdy-bg: #111111;\n --holdy-fg: #f5f5f5;\n --holdy-muted: #a3a3a3;\n --holdy-border: rgba(255, 255, 255, 0.12);\n --holdy-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\n }\n}\n\n.holdy-card {\n background: var(--holdy-bg);\n color: var(--holdy-fg);\n border: 1px solid var(--holdy-border);\n border-radius: var(--holdy-radius);\n box-shadow: var(--holdy-shadow);\n padding: 12px 14px;\n font-size: 14px;\n line-height: 1.45;\n max-width: 320px;\n pointer-events: auto;\n}\n\n.holdy-card-text {\n margin: 0;\n}\n\n.holdy-card-actions {\n display: flex;\n gap: 8px;\n margin-top: 10px;\n align-items: center;\n justify-content: flex-end;\n}\n\n.holdy-btn {\n font-family: var(--holdy-font);\n font-size: 13px;\n font-weight: 500;\n padding: 6px 12px;\n border-radius: 6px;\n border: none;\n cursor: pointer;\n background: var(--holdy-primary);\n color: #ffffff;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n}\n\n.holdy-btn:focus-visible {\n outline: 2px solid var(--holdy-primary);\n outline-offset: 2px;\n}\n\n.holdy-btn-ghost {\n background: transparent;\n color: var(--holdy-muted);\n border: 1px solid var(--holdy-border);\n}\n\n.holdy-close {\n background: transparent;\n border: none;\n color: var(--holdy-muted);\n font-size: 16px;\n line-height: 1;\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n}\n\n.holdy-close:hover {\n color: var(--holdy-fg);\n}\n\n.holdy-tooltip {\n position: fixed;\n z-index: 2147483647;\n max-width: 280px;\n}\n\n.holdy-banner {\n position: fixed;\n top: 0;\n left: 50%;\n transform: translateX(-50%);\n margin-top: var(--holdy-offset);\n z-index: 2147483647;\n max-width: min(560px, calc(100vw - 32px));\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.holdy-banner .holdy-card-text {\n flex: 1;\n}\n\n.holdy-cta {\n position: fixed;\n right: var(--holdy-offset);\n bottom: var(--holdy-offset);\n z-index: 2147483647;\n max-width: 320px;\n}\n\n.holdy-card-title {\n margin: 0 0 6px;\n font-size: 15px;\n font-weight: 600;\n line-height: 1.3;\n}\n\n/* \u2500\u2500 Modal (Wave 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.holdy-modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 2147483647;\n padding: 20px;\n pointer-events: auto;\n}\n\n.holdy-modal {\n max-width: 480px;\n width: 100%;\n padding: 20px 22px;\n}\n\n.holdy-modal:focus {\n outline: none;\n}\n\n/* \u2500\u2500 Checklist (Wave 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.holdy-checklist {\n position: fixed;\n right: var(--holdy-offset);\n bottom: var(--holdy-offset);\n z-index: 2147483647;\n max-width: 320px;\n padding: 14px 16px;\n}\n\n.holdy-checklist-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 8px;\n margin-bottom: 4px;\n}\n\n.holdy-checklist-title {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n line-height: 1.3;\n flex: 1;\n}\n\n.holdy-checklist-list {\n list-style: none;\n padding: 0;\n margin: 8px 0 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.holdy-checklist-item {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n line-height: 1.4;\n}\n\n.holdy-checklist-item.is-done .holdy-checklist-label {\n text-decoration: line-through;\n color: var(--holdy-muted);\n}\n\n.holdy-checklist-checkbox {\n accent-color: var(--holdy-primary);\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.holdy-checklist-label {\n color: var(--holdy-fg);\n text-decoration: none;\n cursor: pointer;\n}\n\n.holdy-checklist-label:hover {\n color: var(--holdy-primary);\n}\n\n/* \u2500\u2500 Spotlight (Wave 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.holdy-spotlight-container {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n pointer-events: none;\n}\n\n.holdy-spotlight-backdrop {\n position: absolute;\n inset: 0;\n background: rgba(0, 0, 0, 0.55);\n pointer-events: auto;\n transition: clip-path 120ms ease-out;\n}\n\n.holdy-spotlight-ring {\n position: absolute;\n border-radius: 8px;\n box-shadow: 0 0 0 2px var(--holdy-primary), 0 0 24px rgba(202, 33, 33, 0.4);\n pointer-events: none;\n transition: top 120ms, left 120ms, width 120ms, height 120ms;\n}\n\n.holdy-spotlight-tooltip {\n position: absolute;\n max-width: 320px;\n pointer-events: auto;\n}\n`\n\nlet cachedSheet: CSSStyleSheet | null = null\n\nexport function getStyleSheet(): CSSStyleSheet | null {\n if (typeof CSSStyleSheet === 'undefined') return null\n if (cachedSheet) return cachedSheet\n try {\n const sheet = new CSSStyleSheet()\n sheet.replaceSync(BASE_CSS)\n cachedSheet = sheet\n return sheet\n } catch {\n return null\n }\n}\n\nexport function applyThemeVars(host: HTMLElement, theme: ThemeConfig | undefined): void {\n const t = theme ?? DEFAULT_THEME\n host.style.setProperty('--holdy-cfg-primary', t.primary_color)\n host.style.setProperty('--holdy-cfg-font', t.font_family)\n host.style.setProperty('--holdy-cfg-radius', `${t.border_radius_px}px`)\n host.style.setProperty('--holdy-cfg-offset', `${t.position_offset_px}px`)\n}\n\n/** Fallback pra browsers sem adoptedStyleSheets (Safari <16.4). */\nexport function injectFallbackStyle(root: ShadowRoot): void {\n const el = document.createElement('style')\n el.textContent = BASE_CSS\n root.appendChild(el)\n}\n", "import type { ThemeConfig } from '../types'\nimport { applyThemeVars, getStyleSheet, injectFallbackStyle } from './styles'\n\nconst HOST_TAG = 'holdy-root'\nlet hostEl: HTMLElement | null = null\nlet shadow: ShadowRoot | null = null\n\nfunction defineCustomElement(): void {\n if (typeof customElements === 'undefined') return\n if (customElements.get(HOST_TAG)) return\n // Minimal subclass \u00B7 we keep behavior in plain functions.\n class HoldyRoot extends HTMLElement {}\n try {\n customElements.define(HOST_TAG, HoldyRoot)\n } catch {\n // Already defined by another instance \u00B7 safe to ignore.\n }\n}\n\nexport function ensureRoot(theme: ThemeConfig | undefined): ShadowRoot | null {\n if (typeof document === 'undefined') return null\n if (shadow) {\n if (hostEl) applyThemeVars(hostEl, theme)\n return shadow\n }\n defineCustomElement()\n\n hostEl = document.createElement(HOST_TAG)\n hostEl.setAttribute('aria-live', 'polite')\n hostEl.setAttribute('data-holdy-root', '1')\n hostEl.style.position = 'fixed'\n hostEl.style.top = '0'\n hostEl.style.left = '0'\n hostEl.style.width = '0'\n hostEl.style.height = '0'\n hostEl.style.zIndex = '2147483647'\n hostEl.style.pointerEvents = 'none'\n\n const root = hostEl.attachShadow({ mode: 'closed' })\n shadow = root\n const sheet = getStyleSheet()\n if (sheet && 'adoptedStyleSheets' in root) {\n try {\n ;(root as ShadowRoot & { adoptedStyleSheets: CSSStyleSheet[] }).adoptedStyleSheets = [sheet]\n } catch {\n injectFallbackStyle(root)\n }\n } else {\n injectFallbackStyle(root)\n }\n\n applyThemeVars(hostEl, theme)\n\n if (document.body) {\n document.body.appendChild(hostEl)\n } else {\n document.addEventListener('DOMContentLoaded', () => {\n if (hostEl && !hostEl.isConnected) document.body.appendChild(hostEl)\n })\n }\n return shadow\n}\n\nexport function appendToRoot(node: HTMLElement): void {\n if (!shadow) return\n // Re-enable pointer events on actual cards (root host is pointer-events:none).\n node.style.pointerEvents = 'auto'\n shadow.appendChild(node)\n}\n", "import type { InterventionPayload, OutcomeValue } from '../../types'\n\nexport interface RenderHandlers {\n onExecuted(metadata?: Record<string, unknown>): void\n onDismissed(metadata?: Record<string, unknown>): void\n onFailed(metadata?: Record<string, unknown>): void\n}\n\nexport interface RenderControl {\n el: HTMLElement\n dismiss: (outcome?: OutcomeValue, metadata?: Record<string, unknown>) => void\n}\n\n/** Cria bot\u00E3o fechar SDK-owned \u00B7 dispatch dismissed. */\nexport function buildCloseButton(onDismiss: () => void): HTMLButtonElement {\n const btn = document.createElement('button')\n btn.type = 'button'\n btn.className = 'holdy-close'\n btn.setAttribute('aria-label', 'Fechar')\n btn.textContent = '\u00D7'\n btn.addEventListener('click', (e) => {\n e.stopPropagation()\n onDismiss()\n })\n return btn\n}\n\n/** Cria CTA button OU anchor SDK-owned \u00B7 dispatch executed. */\nexport function buildCtaButton(\n payload: InterventionPayload,\n onExecuted: () => void,\n): HTMLElement | null {\n if (!payload.cta_text) return null\n\n let el: HTMLElement\n if (payload.cta_href) {\n const a = document.createElement('a')\n a.href = payload.cta_href\n a.rel = 'noopener noreferrer'\n a.target = '_self'\n el = a\n } else {\n el = document.createElement('button')\n ;(el as HTMLButtonElement).type = 'button'\n }\n el.className = 'holdy-btn'\n // textContent only \u00B7 NEVER innerHTML.\n el.textContent = payload.cta_text\n el.addEventListener('click', () => onExecuted())\n return el\n}\n\nexport function buildTextNode(text: string): HTMLParagraphElement {\n const p = document.createElement('p')\n p.className = 'holdy-card-text'\n p.textContent = text\n return p\n}\n\nexport function buildActionsRow(...children: Array<HTMLElement | null>): HTMLDivElement | null {\n const filtered = children.filter((c): c is HTMLElement => c !== null)\n if (filtered.length === 0) return null\n const row = document.createElement('div')\n row.className = 'holdy-card-actions'\n filtered.forEach((c) => row.appendChild(c))\n return row\n}\n", "import type { InterventionPayload } from '../../types'\nimport {\n buildActionsRow,\n buildCloseButton,\n buildCtaButton,\n buildTextNode,\n type RenderControl,\n type RenderHandlers,\n} from './shared'\n\nconst TOOLTIP_GAP_PX = 8\n\nexport function renderTooltip(\n payload: InterventionPayload,\n anchor: Element | null,\n handlers: RenderHandlers,\n): RenderControl {\n const card = document.createElement('div')\n card.className = 'holdy-card holdy-tooltip'\n card.setAttribute('role', 'tooltip')\n\n const text = buildTextNode(payload.text)\n card.appendChild(text)\n\n const close = buildCloseButton(() => dismiss('dismissed'))\n const cta = buildCtaButton(payload, () => {\n handlers.onExecuted()\n cleanup()\n })\n\n const actions = buildActionsRow(cta, close)\n if (actions) card.appendChild(actions)\n else card.appendChild(close)\n\n let dismissed = false\n const cleanup = (): void => {\n if (dismissed) return\n dismissed = true\n card.remove()\n window.removeEventListener('scroll', position, true)\n window.removeEventListener('resize', position)\n }\n\n const dismiss = (outcome: 'dismissed' | 'no_show' | 'failed' = 'dismissed'): void => {\n if (dismissed) return\n if (outcome === 'dismissed') handlers.onDismissed()\n if (outcome === 'failed') handlers.onFailed()\n cleanup()\n }\n\n const position = (): void => {\n if (!anchor) return\n const rect = anchor.getBoundingClientRect()\n if (rect.width === 0 && rect.height === 0) return\n const cardRect = card.getBoundingClientRect()\n let top = rect.bottom + TOOLTIP_GAP_PX\n let left = rect.left + rect.width / 2 - cardRect.width / 2\n // Keep in viewport\n const maxLeft = window.innerWidth - cardRect.width - 8\n if (left < 8) left = 8\n if (left > maxLeft) left = maxLeft\n if (top + cardRect.height > window.innerHeight - 8) {\n // Flip above\n top = rect.top - cardRect.height - TOOLTIP_GAP_PX\n }\n card.style.top = `${Math.max(8, top)}px`\n card.style.left = `${left}px`\n }\n\n // Initial render off-screen pra medir antes de posicionar.\n card.style.top = '-9999px'\n card.style.left = '-9999px'\n\n // Caller anexa ao shadow root, ent\u00E3o retornamos card + ativador.\n requestAnimationFrame(() => {\n position()\n window.addEventListener('scroll', position, true)\n window.addEventListener('resize', position)\n })\n\n return { el: card, dismiss: (o) => dismiss(o === 'failed' || o === 'no_show' ? o : 'dismissed') }\n}\n", "import type { InterventionPayload } from '../../types'\nimport {\n buildActionsRow,\n buildCloseButton,\n buildCtaButton,\n buildTextNode,\n type RenderControl,\n type RenderHandlers,\n} from './shared'\n\nexport function renderBanner(\n payload: InterventionPayload,\n handlers: RenderHandlers,\n): RenderControl {\n const card = document.createElement('div')\n card.className = 'holdy-card holdy-banner'\n card.setAttribute('role', 'status')\n\n const text = buildTextNode(payload.text)\n card.appendChild(text)\n\n const close = buildCloseButton(() => dismiss('dismissed'))\n const cta = buildCtaButton(payload, () => {\n handlers.onExecuted()\n cleanup()\n })\n\n // Banner mant\u00E9m actions inline (n\u00E3o em row separada) pra economizar altura.\n const inlineActions = buildActionsRow(cta, close)\n if (inlineActions) {\n inlineActions.style.marginTop = '0'\n card.appendChild(inlineActions)\n } else {\n card.appendChild(close)\n }\n\n let dismissed = false\n const cleanup = (): void => {\n if (dismissed) return\n dismissed = true\n card.remove()\n }\n\n const dismiss = (outcome: 'dismissed' | 'no_show' | 'failed' = 'dismissed'): void => {\n if (dismissed) return\n if (outcome === 'dismissed') handlers.onDismissed()\n if (outcome === 'failed') handlers.onFailed()\n cleanup()\n }\n\n return { el: card, dismiss: (o) => dismiss(o === 'failed' || o === 'no_show' ? o : 'dismissed') }\n}\n", "import type { InterventionPayload } from '../../types'\nimport {\n buildActionsRow,\n buildCloseButton,\n buildCtaButton,\n buildTextNode,\n type RenderControl,\n type RenderHandlers,\n} from './shared'\n\n/**\n * CTA sticky bottom-right \u00B7 usado quando n\u00E3o h\u00E1 anchor espec\u00EDfico mas a\n * intervention precisa de presen\u00E7a persistente (ex: convite pra rodar\n * onboarding workflow).\n */\nexport function renderCta(\n payload: InterventionPayload,\n handlers: RenderHandlers,\n): RenderControl {\n const card = document.createElement('div')\n card.className = 'holdy-card holdy-cta'\n card.setAttribute('role', 'dialog')\n card.setAttribute('aria-label', 'Sugest\u00E3o Holdy')\n\n const text = buildTextNode(payload.text)\n card.appendChild(text)\n\n const close = buildCloseButton(() => dismiss('dismissed'))\n const cta = buildCtaButton(payload, () => {\n handlers.onExecuted()\n cleanup()\n })\n\n const actions = buildActionsRow(cta, close)\n if (actions) card.appendChild(actions)\n else card.appendChild(close)\n\n let dismissed = false\n const cleanup = (): void => {\n if (dismissed) return\n dismissed = true\n card.remove()\n }\n\n const dismiss = (outcome: 'dismissed' | 'no_show' | 'failed' = 'dismissed'): void => {\n if (dismissed) return\n if (outcome === 'dismissed') handlers.onDismissed()\n if (outcome === 'failed') handlers.onFailed()\n cleanup()\n }\n\n return { el: card, dismiss: (o) => dismiss(o === 'failed' || o === 'no_show' ? o : 'dismissed') }\n}\n", "import type { InterventionPayload } from '../../types'\nimport {\n buildActionsRow,\n buildCloseButton,\n buildCtaButton,\n buildTextNode,\n type RenderControl,\n type RenderHandlers,\n} from './shared'\n\n/**\n * Modal \u00B7 overlay centralizado com backdrop.\n *\n * UX:\n * \u00B7 backdrop click dismissa (igual padr\u00E3o Apple/Stripe)\n * \u00B7 ESC dismissa\n * \u00B7 focus trap entre primeiro/\u00FAltimo focusable\n * \u00B7 scroll body bloqueado enquanto aberto\n * \u00B7 role=dialog + aria-modal pra acessibilidade\n *\n * Uso: intervention de alto peso (renewal aproximando, churn risk\n * cr\u00EDtico, expansion oferecida com 1 click). Limite global de 1.\n */\nexport function renderModal(\n payload: InterventionPayload,\n handlers: RenderHandlers,\n): RenderControl {\n const backdrop = document.createElement('div')\n backdrop.className = 'holdy-modal-backdrop'\n\n const card = document.createElement('div')\n card.className = 'holdy-card holdy-modal'\n card.setAttribute('role', 'dialog')\n card.setAttribute('aria-modal', 'true')\n card.tabIndex = -1\n\n if (payload.title) {\n const h = document.createElement('h2')\n h.className = 'holdy-card-title'\n h.textContent = payload.title\n card.appendChild(h)\n }\n\n const text = buildTextNode(payload.text)\n card.appendChild(text)\n\n const close = buildCloseButton(() => dismiss('dismissed'))\n const cta = buildCtaButton(payload, () => {\n handlers.onExecuted()\n cleanup()\n })\n\n const actions = buildActionsRow(cta, close)\n if (actions) card.appendChild(actions)\n else card.appendChild(close)\n\n backdrop.appendChild(card)\n\n // Body scroll lock\n const prevBodyOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n\n // Backdrop click dismissa (mas s\u00F3 se for clique direto no backdrop, n\u00E3o no card)\n backdrop.addEventListener('click', (e) => {\n if (e.target === backdrop) dismiss('dismissed', { reason: 'backdrop_click' })\n })\n\n // Focus management\n const previouslyFocused = document.activeElement as HTMLElement | null\n const focusFirst = (): void => {\n requestAnimationFrame(() => {\n const focusable = card.querySelector<HTMLElement>('a, button, [tabindex]:not([tabindex=\"-1\"])')\n ;(focusable ?? card).focus()\n })\n }\n focusFirst()\n\n const onKeydown = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n dismiss('dismissed', { reason: 'esc' })\n return\n }\n if (e.key !== 'Tab') return\n // Focus trap simples \u00B7 s\u00F3 dentro do card\n const focusables = Array.from(\n card.querySelectorAll<HTMLElement>('a, button, [tabindex]:not([tabindex=\"-1\"])'),\n )\n if (focusables.length === 0) return\n const first = focusables[0]\n const last = focusables[focusables.length - 1]\n const active = document.activeElement\n if (e.shiftKey && active === first) {\n e.preventDefault()\n last.focus()\n } else if (!e.shiftKey && active === last) {\n e.preventDefault()\n first.focus()\n }\n }\n document.addEventListener('keydown', onKeydown, true)\n\n let dismissed = false\n const cleanup = (): void => {\n if (dismissed) return\n dismissed = true\n document.body.style.overflow = prevBodyOverflow\n document.removeEventListener('keydown', onKeydown, true)\n backdrop.remove()\n if (previouslyFocused && typeof previouslyFocused.focus === 'function') {\n previouslyFocused.focus()\n }\n }\n\n const dismiss = (\n outcome: 'dismissed' | 'no_show' | 'failed' = 'dismissed',\n metadata?: Record<string, unknown>,\n ): void => {\n if (dismissed) return\n if (outcome === 'dismissed') handlers.onDismissed(metadata)\n if (outcome === 'failed') handlers.onFailed(metadata)\n cleanup()\n }\n\n return {\n el: backdrop,\n dismiss: (o) => dismiss(o === 'failed' || o === 'no_show' ? o : 'dismissed'),\n }\n}\n", "import type { ChecklistItem, InterventionPayload } from '../../types'\nimport {\n buildCloseButton,\n type RenderControl,\n type RenderHandlers,\n} from './shared'\n\nconst STATE_KEY_PREFIX = 'holdy_checklist_'\n\n/**\n * Checklist \u00B7 sticky bottom-right com lista de tarefas.\n *\n * Persist\u00EAncia: estado por decision_id em localStorage (chave\n * `holdy_checklist_{decision_id}`). Rehidratado em re-render.\n *\n * UX:\n * \u00B7 cada item tem checkbox \u00B7 clique marca/desmarca\n * \u00B7 item com href abre em _self quando label clicado (ap\u00F3s marcar)\n * \u00B7 primeiro completed dispara onExecuted UMA vez (n\u00E3o a cada check)\n * \u00B7 todos completed dispara onExecuted com metadata={completed:true}\n * \u00B7 close button dispara onDismissed\n *\n * N\u00C3O h\u00E1 outcome 'converted' aqui \u2014 fica pro caller (Holdy backend) detectar\n * via workflow.completed downstream.\n */\nexport function renderChecklist(\n payload: InterventionPayload,\n decisionId: string,\n handlers: RenderHandlers,\n): RenderControl {\n const items = payload.items ?? []\n if (items.length === 0) {\n // payload inv\u00E1lido \u00B7 checklist sem items\n handlers.onFailed({ reason: 'empty_items' })\n const empty = document.createElement('div')\n return { el: empty, dismiss: () => undefined }\n }\n\n const state = readState(decisionId, items)\n\n const card = document.createElement('div')\n card.className = 'holdy-card holdy-checklist'\n card.setAttribute('role', 'region')\n card.setAttribute('aria-label', payload.title ?? 'Lista de tarefas')\n\n // Header com title + close\n const header = document.createElement('div')\n header.className = 'holdy-checklist-header'\n\n if (payload.title) {\n const h = document.createElement('h3')\n h.className = 'holdy-checklist-title'\n h.textContent = payload.title\n header.appendChild(h)\n }\n\n const close = buildCloseButton(() => dismiss('dismissed'))\n header.appendChild(close)\n card.appendChild(header)\n\n if (payload.text) {\n const text = document.createElement('p')\n text.className = 'holdy-card-text'\n text.textContent = payload.text\n card.appendChild(text)\n }\n\n // Lista\n const list = document.createElement('ul')\n list.className = 'holdy-checklist-list'\n\n let firedExecuted = false\n let firedCompleted = false\n\n const renderItems = (): void => {\n list.textContent = ''\n items.forEach((item) => {\n const li = document.createElement('li')\n li.className = state[item.id] ? 'holdy-checklist-item is-done' : 'holdy-checklist-item'\n\n const checkbox = document.createElement('input')\n checkbox.type = 'checkbox'\n checkbox.className = 'holdy-checklist-checkbox'\n checkbox.checked = !!state[item.id]\n checkbox.setAttribute('aria-label', `Marcar ${item.label}`)\n checkbox.addEventListener('change', () => toggleItem(item, checkbox.checked))\n\n const labelEl = item.href\n ? document.createElement('a')\n : document.createElement('span')\n labelEl.className = 'holdy-checklist-label'\n labelEl.textContent = item.label\n if (item.href) {\n ;(labelEl as HTMLAnchorElement).href = item.href\n ;(labelEl as HTMLAnchorElement).rel = 'noopener noreferrer'\n labelEl.addEventListener('click', () => toggleItem(item, true))\n }\n\n li.appendChild(checkbox)\n li.appendChild(labelEl)\n list.appendChild(li)\n })\n }\n\n const toggleItem = (item: ChecklistItem, completed: boolean): void => {\n state[item.id] = completed\n persistState(decisionId, state)\n\n if (completed && !firedExecuted) {\n firedExecuted = true\n handlers.onExecuted({ item_id: item.id })\n }\n\n const allDone = items.every((i) => state[i.id])\n if (allDone && !firedCompleted) {\n firedCompleted = true\n handlers.onExecuted({ completed: true })\n }\n\n renderItems()\n }\n\n renderItems()\n card.appendChild(list)\n\n let dismissed = false\n const cleanup = (): void => {\n if (dismissed) return\n dismissed = true\n card.remove()\n }\n\n const dismiss = (outcome: 'dismissed' | 'no_show' | 'failed' = 'dismissed'): void => {\n if (dismissed) return\n if (outcome === 'dismissed') handlers.onDismissed()\n if (outcome === 'failed') handlers.onFailed()\n cleanup()\n }\n\n return { el: card, dismiss: (o) => dismiss(o === 'failed' || o === 'no_show' ? o : 'dismissed') }\n}\n\nfunction readState(\n decisionId: string,\n items: ChecklistItem[],\n): Record<string, boolean> {\n // Default: respeitar `completed` do payload (server pode pr\u00E9-marcar items)\n const initial: Record<string, boolean> = {}\n items.forEach((i) => {\n initial[i.id] = !!i.completed\n })\n\n if (typeof localStorage === 'undefined') return initial\n try {\n const raw = localStorage.getItem(STATE_KEY_PREFIX + decisionId)\n if (!raw) return initial\n const parsed = JSON.parse(raw) as Record<string, boolean>\n // Merge \u00B7 localStorage tem prioridade sobre server pre-marks\n items.forEach((i) => {\n if (typeof parsed[i.id] === 'boolean') initial[i.id] = parsed[i.id]\n })\n return initial\n } catch {\n return initial\n }\n}\n\nfunction persistState(decisionId: string, state: Record<string, boolean>): void {\n if (typeof localStorage === 'undefined') return\n try {\n localStorage.setItem(STATE_KEY_PREFIX + decisionId, JSON.stringify(state))\n } catch {\n // quota \u00B7 silent\n }\n}\n", "import type { InterventionPayload } from '../../types'\nimport {\n buildActionsRow,\n buildCloseButton,\n buildCtaButton,\n buildTextNode,\n type RenderControl,\n type RenderHandlers,\n} from './shared'\n\nconst SPOTLIGHT_PADDING = 6\nconst TOOLTIP_GAP_PX = 12\n\n/**\n * Spotlight \u00B7 backdrop escurecido com \"buraco\" recortado no anchor +\n * tooltip apontando.\n *\n * UX:\n * \u00B7 backdrop tem clip-path criando ring around o elemento\n * \u00B7 tooltip aparece abaixo (ou acima se sem espa\u00E7o)\n * \u00B7 clique no anchor original (atravessa o buraco via pointer-events:none\n * na \u00E1rea do hole) executa\n * \u00B7 backdrop click fora do hole dismissa\n * \u00B7 ESC dismissa\n *\n * Uso: onboarding step \"veja esse bot\u00E3o\", first-time UI guidance.\n */\nexport function renderSpotlight(\n payload: InterventionPayload,\n anchor: Element | null,\n handlers: RenderHandlers,\n): RenderControl {\n if (!anchor) {\n handlers.onFailed({ reason: 'anchor_unresolved' })\n const empty = document.createElement('div')\n return { el: empty, dismiss: () => undefined }\n }\n\n const container = document.createElement('div')\n container.className = 'holdy-spotlight-container'\n\n const backdrop = document.createElement('div')\n backdrop.className = 'holdy-spotlight-backdrop'\n container.appendChild(backdrop)\n\n const ring = document.createElement('div')\n ring.className = 'holdy-spotlight-ring'\n container.appendChild(ring)\n\n const card = document.createElement('div')\n card.className = 'holdy-card holdy-spotlight-tooltip'\n card.setAttribute('role', 'dialog')\n\n if (payload.title) {\n const h = document.createElement('h3')\n h.className = 'holdy-card-title'\n h.textContent = payload.title\n card.appendChild(h)\n }\n const text = buildTextNode(payload.text)\n card.appendChild(text)\n\n const close = buildCloseButton(() => dismiss('dismissed'))\n const cta = buildCtaButton(payload, () => {\n handlers.onExecuted()\n cleanup()\n })\n\n const actions = buildActionsRow(cta, close)\n if (actions) card.appendChild(actions)\n else card.appendChild(close)\n\n container.appendChild(card)\n\n // Anchor click intercept \u00B7 marca executed tamb\u00E9m (sem precisar do CTA)\n const onAnchorClick = (): void => {\n handlers.onExecuted({ via: 'anchor_click' })\n cleanup()\n }\n ;(anchor as HTMLElement).addEventListener('click', onAnchorClick, { once: true, capture: true })\n\n // Backdrop click dismissa\n backdrop.addEventListener('click', () => dismiss('dismissed', { reason: 'backdrop_click' }))\n\n const onKeydown = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n dismiss('dismissed', { reason: 'esc' })\n }\n }\n document.addEventListener('keydown', onKeydown, true)\n\n const position = (): void => {\n const rect = anchor.getBoundingClientRect()\n if (rect.width === 0 && rect.height === 0) {\n // Anchor sumiu \u00B7 dismiss silencioso (no_show)\n dismiss('no_show', { reason: 'anchor_disappeared' })\n return\n }\n\n const top = Math.max(0, rect.top - SPOTLIGHT_PADDING)\n const left = Math.max(0, rect.left - SPOTLIGHT_PADDING)\n const width = rect.width + SPOTLIGHT_PADDING * 2\n const height = rect.height + SPOTLIGHT_PADDING * 2\n\n ring.style.top = `${top}px`\n ring.style.left = `${left}px`\n ring.style.width = `${width}px`\n ring.style.height = `${height}px`\n\n // Clip-path no backdrop pra criar buraco\n backdrop.style.clipPath = `polygon(\n 0 0, 100% 0, 100% 100%, 0 100%, 0 0,\n ${left}px ${top}px,\n ${left}px ${top + height}px,\n ${left + width}px ${top + height}px,\n ${left + width}px ${top}px,\n ${left}px ${top}px\n )`\n\n // Tooltip abaixo ou acima do ring\n const cardRect = card.getBoundingClientRect()\n let cardTop = top + height + TOOLTIP_GAP_PX\n let cardLeft = left + width / 2 - cardRect.width / 2\n\n if (cardLeft < 8) cardLeft = 8\n const maxLeft = window.innerWidth - cardRect.width - 8\n if (cardLeft > maxLeft) cardLeft = maxLeft\n if (cardTop + cardRect.height > window.innerHeight - 8) {\n cardTop = top - cardRect.height - TOOLTIP_GAP_PX\n }\n card.style.top = `${Math.max(8, cardTop)}px`\n card.style.left = `${cardLeft}px`\n }\n\n // Init off-screen\n card.style.top = '-9999px'\n card.style.left = '-9999px'\n\n requestAnimationFrame(() => {\n position()\n window.addEventListener('scroll', position, true)\n window.addEventListener('resize', position)\n })\n\n let dismissed = false\n const cleanup = (): void => {\n if (dismissed) return\n dismissed = true\n container.remove()\n document.removeEventListener('keydown', onKeydown, true)\n window.removeEventListener('scroll', position, true)\n window.removeEventListener('resize', position)\n ;(anchor as HTMLElement).removeEventListener('click', onAnchorClick, true)\n }\n\n const dismiss = (\n outcome: 'dismissed' | 'no_show' | 'failed' = 'dismissed',\n metadata?: Record<string, unknown>,\n ): void => {\n if (dismissed) return\n if (outcome === 'dismissed') handlers.onDismissed(metadata)\n if (outcome === 'no_show') {\n // N\u00E3o dispara onFailed \u00B7 no_show \u00E9 caso normal de anchor desaparecer\n // mid-render. Caller (HoldySdk.renderDecision) j\u00E1 reporta no_show via\n // outcomeTracker antes mesmo de chamar render. Aqui apenas cleanup.\n }\n if (outcome === 'failed') handlers.onFailed(metadata)\n cleanup()\n }\n\n return {\n el: container,\n dismiss: (o) => dismiss(o === 'failed' || o === 'no_show' ? o : 'dismissed'),\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["index_exports", "__export", "Holdy", "index_default", "DB_NAME", "STORE_NAME", "isIdbAvailable", "dbPromise", "openDb", "resolve", "reject", "req", "DB_NAME", "db", "STORE_NAME", "withStore", "mode", "fn", "tx", "store", "result", "out", "v", "e", "idbDriver", "batch", "now", "limit", "all", "b", "a", "item", "id", "n", "sorted", "_a", "MemoryDriver", "idx", "i", "EventQueue", "send", "log", "events", "pending", "overflow", "due", "attempts", "backoff", "drain", "items", "DEFAULT_API_URL", "Transport", "config", "_a", "_b", "EventQueue", "body", "args", "res", "input", "e", "events", "payload", "decisionId", "outcome", "metadata", "url", "OutcomeTracker", "transport", "decisionId", "workflow", "outcome", "metadata", "_a", "_b", "_c", "InterventionStore", "kind", "decisionId", "confidence", "anchorSelector", "dismiss", "slot", "key", "prev", "_a", "_b", "_c", "_d", "map", "k", "pending", "observer", "ensureObserver", "entry", "el", "stopObserver", "resolveAnchor", "selector", "existing", "resolve", "resolved", "timeoutId", "INSTALLED_FLAG", "installAutoCapture", "emit", "w", "INSTALLED_FLAG", "cleanups", "lastPath", "currentPath", "pendingRouteEmit", "safeEmit", "kind", "path", "title", "referrer", "e", "scheduleRouteEmit", "origPush", "origReplace", "args", "result", "popHandler", "hashHandler", "hiddenAt", "visHandler", "elapsed", "c", "DEFAULT_THEME", "BASE_CSS", "cachedSheet", "getStyleSheet", "sheet", "e", "applyThemeVars", "host", "theme", "DEFAULT_THEME", "injectFallbackStyle", "root", "el", "HOST_TAG", "hostEl", "shadow", "defineCustomElement", "HoldyRoot", "ensureRoot", "theme", "applyThemeVars", "root", "sheet", "getStyleSheet", "e", "injectFallbackStyle", "appendToRoot", "node", "buildCloseButton", "onDismiss", "btn", "e", "buildCtaButton", "payload", "onExecuted", "el", "a", "buildTextNode", "text", "p", "buildActionsRow", "children", "filtered", "c", "row", "TOOLTIP_GAP_PX", "renderTooltip", "payload", "anchor", "handlers", "card", "text", "buildTextNode", "close", "buildCloseButton", "dismiss", "cta", "buildCtaButton", "cleanup", "actions", "buildActionsRow", "dismissed", "position", "outcome", "rect", "cardRect", "top", "left", "maxLeft", "o", "renderBanner", "payload", "handlers", "card", "text", "buildTextNode", "close", "buildCloseButton", "dismiss", "cta", "buildCtaButton", "cleanup", "inlineActions", "buildActionsRow", "dismissed", "outcome", "o", "renderCta", "payload", "handlers", "card", "text", "buildTextNode", "close", "buildCloseButton", "dismiss", "cta", "buildCtaButton", "cleanup", "actions", "buildActionsRow", "dismissed", "outcome", "o", "renderModal", "payload", "handlers", "backdrop", "card", "h", "text", "buildTextNode", "close", "buildCloseButton", "dismiss", "cta", "buildCtaButton", "cleanup", "actions", "buildActionsRow", "prevBodyOverflow", "e", "previouslyFocused", "focusable", "onKeydown", "focusables", "first", "last", "active", "dismissed", "outcome", "metadata", "o", "STATE_KEY_PREFIX", "renderChecklist", "payload", "decisionId", "handlers", "_a", "_b", "items", "state", "readState", "card", "header", "h", "close", "buildCloseButton", "dismiss", "text", "list", "firedExecuted", "firedCompleted", "renderItems", "item", "li", "checkbox", "toggleItem", "labelEl", "completed", "persistState", "i", "dismissed", "cleanup", "outcome", "o", "initial", "raw", "parsed", "e", "SPOTLIGHT_PADDING", "TOOLTIP_GAP_PX", "renderSpotlight", "payload", "anchor", "handlers", "container", "backdrop", "ring", "card", "h", "text", "buildTextNode", "close", "buildCloseButton", "dismiss", "cta", "buildCtaButton", "cleanup", "actions", "buildActionsRow", "onAnchorClick", "onKeydown", "e", "position", "rect", "top", "left", "width", "height", "cardRect", "cardTop", "cardLeft", "maxLeft", "dismissed", "outcome", "metadata", "o", "RING_BUFFER_LIMIT", "CONFIG_CACHE_KEY", "CONFIG_CACHE_TTL_MS", "EVAL_THROTTLE_MS", "HoldySdk", "InterventionStore", "config", "Transport", "OutcomeTracker", "cached", "fresh", "ensureRoot", "installAutoCapture", "path", "title", "referrer", "kind", "opts", "account", "user", "result", "workflowKey", "sentiment", "primitive", "payload", "occurred_at", "entry", "listener", "l", "decisionId", "outcome", "metadata", "_a", "e", "force", "_b", "now", "evalInput", "decision", "_c", "_d", "_e", "_f", "_g", "_h", "_i", "handlers", "meta", "control", "anchor", "resolveAnchor", "renderTooltip", "renderBanner", "renderCta", "renderModal", "renderChecklist", "renderSpotlight", "superseded", "appendToRoot", "raw", "parsed", "args", "Holdy", "index_default"]
|
|
7
|
-
}
|