@journeeze/sdk 0.0.0-stage → 0.1.0-rc.3

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.
Files changed (90) hide show
  1. package/AGENTS.md +80 -0
  2. package/CHANGELOG.md +41 -0
  3. package/LICENSE.md +27 -0
  4. package/README.md +343 -2
  5. package/dist/THIRD_PARTY_LICENSES.txt +246 -0
  6. package/dist/anchor-cPvFFTOS.js +1 -0
  7. package/dist/attach-DpioALxW.js +21 -0
  8. package/dist/chat-BgmB0rnW.js +64 -0
  9. package/dist/consent-DckCUvYR.js +1 -0
  10. package/dist/context-UnG6_X61.js +17 -0
  11. package/dist/contract.js +10 -0
  12. package/dist/feedback-CtH1a_kQ.js +1 -0
  13. package/dist/help-w0O5Qu-4.js +105 -0
  14. package/dist/hook-DGWypoEO.js +1 -0
  15. package/dist/index-B_nob8S0.js +1 -0
  16. package/dist/index-CwG2LrhO.js +20 -0
  17. package/dist/index.js +10 -0
  18. package/dist/jobs-CAXbM5-g.js +45 -0
  19. package/dist/loader-BZiIDD1D.js +96 -0
  20. package/dist/mask-audit-Du3NPoG_.js +5 -0
  21. package/dist/react.js +71 -0
  22. package/dist/resolve-BfWByuTp.js +1 -0
  23. package/dist/script.js +14 -0
  24. package/dist/signals-amjMQyOy.js +1 -0
  25. package/dist/telemetry-CyRJDaVs.js +1 -0
  26. package/dist/transport-B64CfIcF.js +1 -0
  27. package/dist/types/chat/capture/attach.d.ts +41 -0
  28. package/dist/types/chat/capture/draw.d.ts +10 -0
  29. package/dist/types/chat/capture/geometry.d.ts +30 -0
  30. package/dist/types/chat/capture/styles.d.ts +1 -0
  31. package/dist/types/chat/shell/chat.d.ts +27 -0
  32. package/dist/types/chat/shell/converse.d.ts +95 -0
  33. package/dist/types/chat/shell/copy.d.ts +8 -0
  34. package/dist/types/chat/shell/model.d.ts +36 -0
  35. package/dist/types/chat/shell/session.d.ts +148 -0
  36. package/dist/types/chat/shell/styles.d.ts +1 -0
  37. package/dist/types/chat/shell/view.d.ts +18 -0
  38. package/dist/types/chat/transport.d.ts +5 -0
  39. package/dist/types/config.d.ts +34 -0
  40. package/dist/types/context.d.ts +6 -0
  41. package/dist/types/contract.d.ts +13 -0
  42. package/dist/types/help/core/client.d.ts +26 -0
  43. package/dist/types/help/core/controller.d.ts +184 -0
  44. package/dist/types/help/core/events.d.ts +32 -0
  45. package/dist/types/help/core/help.d.ts +25 -0
  46. package/dist/types/help/core/highlight.d.ts +38 -0
  47. package/dist/types/help/core/panel.d.ts +27 -0
  48. package/dist/types/help/core/routing.d.ts +21 -0
  49. package/dist/types/help/core/search.d.ts +7 -0
  50. package/dist/types/help/ui/callout.d.ts +2 -0
  51. package/dist/types/help/ui/jobs/jobs.d.ts +24 -0
  52. package/dist/types/help/ui/jobs/model.d.ts +33 -0
  53. package/dist/types/help/ui/jobs/styles.d.ts +1 -0
  54. package/dist/types/help/ui/panel.d.ts +3 -0
  55. package/dist/types/help/ui/request.d.ts +2 -0
  56. package/dist/types/help/ui/styles.d.ts +1 -0
  57. package/dist/types/index.d.ts +7 -0
  58. package/dist/types/invite.d.ts +4 -0
  59. package/dist/types/loader.d.ts +59 -0
  60. package/dist/types/mask-detector.d.ts +22 -0
  61. package/dist/types/mask.d.ts +10 -0
  62. package/dist/types/preview/flag.d.ts +2 -0
  63. package/dist/types/preview/mask-audit.d.ts +29 -0
  64. package/dist/types/react.d.ts +9 -0
  65. package/dist/types/resolve/resolve.d.ts +12 -0
  66. package/dist/types/schemas/feedback.d.ts +76 -0
  67. package/dist/types/schemas/finding.d.ts +22 -0
  68. package/dist/types/schemas/index.d.ts +6 -0
  69. package/dist/types/schemas/turn.d.ts +26 -0
  70. package/dist/types/script.d.ts +6 -0
  71. package/dist/types/signals/cel.d.ts +8 -0
  72. package/dist/types/signals/hook.d.ts +10 -0
  73. package/dist/types/signals/signals.d.ts +149 -0
  74. package/dist/types/signals/steps.d.ts +33 -0
  75. package/dist/types/telemetry/telemetry.d.ts +73 -0
  76. package/dist/types/transport.d.ts +30 -0
  77. package/dist/types/types.d.ts +462 -0
  78. package/dist/types/widget/anchor.d.ts +11 -0
  79. package/dist/types/widget/capture.d.ts +39 -0
  80. package/dist/types/widget/consent.d.ts +25 -0
  81. package/dist/types/widget/feedback.d.ts +36 -0
  82. package/dist/types/widget/icons.d.ts +14 -0
  83. package/dist/types/widget/outbox.d.ts +69 -0
  84. package/dist/types/widget/styles.d.ts +1 -0
  85. package/dist/types/widget/upload.d.ts +14 -0
  86. package/dist/types/widget.d.ts +7 -0
  87. package/dist/types/wire.d.ts +66 -0
  88. package/dist/upload-Fu2qvSJV.js +14 -0
  89. package/dist/widget-B6mR1J3P.js +118 -0
  90. package/package.json +70 -4
@@ -0,0 +1,45 @@
1
+ function J(r,n){const s=e=>!!n&&(e.commonFor??[]).includes(n);return{common:r.filter(s),more:r.filter(e=>!s(e))}}function E(r,n){const s=n?r.personaGuides?.find(e=>e.persona===n&&e.journeyId):void 0;return s?.journeyId?{journeyId:s.journeyId,stepCount:s.stepCount??0}:r.journeyId?{journeyId:r.journeyId,stepCount:r.stepCount??0}:void 0}function W(r,n){const s=n.toLowerCase().split(/\s+/).filter(Boolean);return r.filter(e=>s.every(l=>e.title.toLowerCase().includes(l)))}const D=/^[a-z0-9._:-]{1,96}$/;function H(r,n){return n&&D.test(n)?{...r,persona:n}:r}function Y(r){return r>0?`${r} step${r===1?"":"s"}`:""}const U=`
2
+ :host { --jz-polish:#9A6412; --jz-broken:#B42318; }
3
+ @media (prefers-color-scheme: dark) { :host { --jz-polish:#E0A54A; --jz-broken:#F07B70; } }
4
+ .head-title { flex:1; display:flex; align-items:baseline; gap:8px; min-width:0; }
5
+ .mono { font:11px/1.4 ui-monospace, "JetBrains Mono", monospace; color:var(--jz-faint); white-space:nowrap; }
6
+ .panel h3 { margin:12px 0 4px; padding:0 12px; font-size:11px; font-weight:600; letter-spacing:.06em; text-transform:uppercase; color:var(--jz-faint); }
7
+ .panel .jobs ul { margin:0; }
8
+ .panel .jobs li { margin:0 0 2px; }
9
+ .panel button.job { display:flex; align-items:center; justify-content:space-between; gap:8px; width:100%; min-height:48px;
10
+ padding:10px 12px; border:1px solid transparent; border-radius:6px; background:transparent; text-align:left; font-weight:500;
11
+ transition: background 180ms ease-out, border-color 180ms ease-out; }
12
+ .panel button.job:hover { background:var(--jz-raised); border-color:var(--jz-rule); }
13
+ .job .dim { color:var(--jz-faint); }
14
+ .chip { flex:none; padding:2px 6px; border-radius:4px; background:var(--jz-accent-soft); color:var(--jz-accent); font-size:10px; font-weight:600; }
15
+ .chip.none { background:var(--jz-raised); color:var(--jz-muted); }
16
+ .jobs-foot { margin-top:8px; padding-top:8px; border-top:1px solid var(--jz-rule); }
17
+ .row .not-possible { border-color:var(--jz-confused); color:var(--jz-confused); }
18
+ .else label { display:block; margin:12px 0 6px; font-size:11px; font-weight:500; color:var(--jz-faint); }
19
+ .else textarea { display:block; width:100%; min-height:88px; padding:8px 12px; border:1px solid var(--jz-rule); border-radius:6px;
20
+ background:var(--jz-canvas); color:var(--jz-ink); font:inherit; resize:vertical; }
21
+ .note { margin:12px 0; padding:8px 12px; border-radius:6px; background:var(--jz-raised); color:var(--jz-muted); font-size:11px; }
22
+ .panel .wide { width:100%; min-height:44px; padding:0 16px; border:1px solid var(--jz-accent); border-radius:6px;
23
+ background:var(--jz-accent); color:var(--jz-accent-ink); font-weight:500; }
24
+ .route { margin:12px 0; padding:12px; border:1px solid var(--jz-accent); border-radius:6px; background:var(--jz-accent-soft); }
25
+ .route p { margin:0 0 4px; }
26
+ .done .progress-fill { width:100%; background:var(--jz-polished); }
27
+ .answers { display:grid; grid-template-columns:repeat(3, 1fr); gap:8px; margin:12px 0 16px; }
28
+ .answers button { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; min-height:64px;
29
+ border:1px solid var(--jz-rule); border-radius:6px; background:var(--jz-surface); font-size:12px; font-weight:500;
30
+ transition: background 180ms ease-out, border-color 180ms ease-out; }
31
+ .answers button:hover { background:var(--jz-raised); }
32
+ .answers button[aria-pressed="true"] { border-color:var(--jz-accent); background:var(--jz-accent-soft); box-shadow:inset 0 0 0 1px var(--jz-accent); }
33
+ .answers svg { width:18px; height:18px; }
34
+ .a-YES svg { color:var(--jz-polished); }
35
+ .a-PARTLY svg { color:var(--jz-polish); }
36
+ .a-NO svg { color:var(--jz-broken); }
37
+ .harder { padding-top:12px; border-top:1px solid var(--jz-rule); }
38
+ .harder label { display:flex; align-items:center; gap:8px; min-height:44px; color:var(--jz-muted); font-weight:500; cursor:pointer; }
39
+ .panel .harder input { width:16px; height:16px; min-height:0; margin:0; padding:0; accent-color:var(--jz-accent); }
40
+ .harder p { margin:0; }
41
+ @media (max-width: 480px) {
42
+ .panel { left:0; right:0; bottom:0; width:100%; max-height:85vh; border-radius:10px 10px 0 0;
43
+ padding-bottom:calc(16px + env(safe-area-inset-bottom, 0px)); }
44
+ }
45
+ `,K={sent:"Thanks. We'll take a look.",queued:"Saved. It will send when you're back online.",dropped:"Your message couldn't be sent."},P="http://www.w3.org/2000/svg",Q={YES:"M6.2 11.4 3 8.2l1.1-1.1 2.1 2.1 4.6-4.6 1.1 1.1z",PARTLY:"M3 7.2h10v1.6H3z",NO:"M4.2 3.1 8 6.9l3.8-3.8 1.1 1.1L9.1 8l3.8 3.8-1.1 1.1L8 9.1l-3.8 3.8-1.1-1.1L6.9 8 3.1 4.2z"};function X(r){const n=document.createElementNS(P,"svg");n.setAttribute("viewBox","0 0 16 16"),n.setAttribute("aria-hidden","true"),n.setAttribute("focusable","false");const s=document.createElementNS(P,"path");return s.setAttribute("d",r),s.setAttribute("fill","currentColor"),n.append(s),n}function Z(r){const{controller:n,options:s,el:e,button:l}=r;s.addStyle?.(U);let v={kind:"list"},f,z,x,y;const V=n.subscribe(o=>{o.view==="closed"?(v={kind:"list"},f=void 0):o.view==="index"&&o.status==="loading"&&(f=void 0)}),I=o=>{v=o,r.rerender()},O=()=>I({kind:"list"}),k=()=>s.persona?.()||void 0,L=o=>s.jobEvent?.(H(o,k())),S=(o,t,d)=>e("div",{class:"panel-head"},t&&l("←",t,{id:"jz-jobs-back",class:"icon-btn","aria-label":"Back to the list"}),e("div",{class:"head-title"},e("h2",{id:"jz-jobs-title"},o),d),l("×",()=>n.close(),{class:"icon-btn","aria-label":"Close help"}));function B(o){L({event:"PICKED",jobId:o.jobId,jobVersion:o.version});const t=E(o,k());if(!t)return I({kind:"none",job:o});f={job:o,journeyId:t.journeyId},n.openGuide(t.journeyId)}function q(o){const t=k();if(z&&z.jobs===o.jobs&&z.persona===t)return z.nodes;const d=o.jobs??[],h=e("input",{id:"jz-jobs-search",type:"search","aria-label":"Search what you're trying to do",placeholder:"Search or describe it",autocomplete:"off","data-autofocus":""}),p=e("p",{class:"muted",role:"status"}),b=e("div",{class:"jobs"}),g=a=>{const i=E(a,t),m=i?Y(i.stepCount):"No guide yet",c=l("",()=>B(a),{id:`jz-job-${d.indexOf(a)}`,class:"job"});return c.replaceChildren(e("span",{},a.title),m&&e("span",{class:i?"chip":"chip none"},m)),e("li",{},c)},u=()=>{const{common:a,more:i}=J(W(d,h.value),t),m=(c,C,w)=>w.length>0&&e("section",{"aria-labelledby":`jz-jobs-${c}`},e("h3",{id:`jz-jobs-${c}`},C),e("ul",{},...w.map(g)));b.replaceChildren(...[m("common","Common for you",a),m("more","More",i)].filter(c=>!!c)),p.textContent=a.length+i.length===0?`Nothing matches “${h.value.trim()}”.`:"",p.hidden=!p.textContent};h.addEventListener("input",u),u();const j=n.canSignal()&&e("div",{class:"jobs-foot"},(()=>{const a=l("",()=>I({kind:"else",draft:h.value.trim()}),{id:"jz-job-else",class:"job"});return a.replaceChildren(e("span",{},e("span",{class:"dim","aria-hidden":"true"},"+ "),"Something else"),e("span",{class:"dim","aria-hidden":"true"},"›")),a})());return z={jobs:o.jobs,persona:t,nodes:[S("What are you trying to do?"),h,p,b,j]},z.nodes}function R(o){const t=()=>{L({event:"NOT_POSSIBLE",jobId:o.job.jobId,jobVersion:o.job.version}),I(n.canSignal()?{kind:"else",job:o.job,draft:""}:{...o,said:true})};return[S(o.job.title,O),e("p",{},"There's no guide for this here yet."),o.said?e("p",{class:"muted",role:"status"},"Thanks for telling us."):e("div",{class:"row"},l("Not possible here",t,{id:"jz-job-not-possible",class:"not-possible","data-autofocus":""}))]}function G(o,t){if(x?.mode!==t){const g=e("textarea",{id:"jz-else-text",rows:"3",maxlength:"4000",required:"","data-autofocus":""});g.value=t.draft;const u=e("input",{id:"jz-else-so",type:"text",maxlength:"500",autocomplete:"off"}),j=e("button",{type:"submit",id:"jz-else-send",class:"wide"},"Send"),a=e("form",{class:"else","aria-labelledby":"jz-jobs-title"},e("label",{for:"jz-else-text"},t.job?"What did you need to do?":"What are you trying to do?"),g,e("label",{for:"jz-else-so"},"So you can… (optional)"),u,e("p",{class:"note"},"Only your words and where you are in the app are sent, and only after you agree. Nothing from the page's forms."),j),i={mode:t,form:a,send:j,sent:false};a.addEventListener("submit",m=>{if(m.preventDefault(),i.checking)return;const c={},C=u.value.trim();C&&(c.soYouCan=C),t.job&&(c.jobId=t.job.jobId);const w=()=>{i.sent=true,i.suggest=void 0,n.sendRequest(g.value,c.soYouCan||c.jobId?c:void 0)},N=g.value.trim();if(t.job||!s.routeIntent||!N||i.routed===N||!n.canSignal()||!n.hasConsent())return w();i.routed=N,i.checking=true,r.rerender(),s.routeIntent(N).then(T=>{if(i.checking=false,x!==i||v!==t)return;const $=n.state,A=T&&($.view==="index"&&$.jobs||[]).find(_=>_.jobId===T.jobId);A&&E(A,k())?i.suggest={job:A,sendRequest:w}:w(),r.rerender()})}),x=i}const{form:d,sent:h,suggest:p}=x,b=h&&!o.signal&&(o.signalNotice==="sent"||o.signalNotice==="queued");return d.hidden=b,x.send.disabled=!!x.checking,[S(t.job?"Not possible here":"Something else",O),t.job&&!b&&e("p",{class:"muted"},`Thanks. Tell us what you needed for “${t.job.title}”, if you like.`),d,p?M(p.job,p.sendRequest):x.checking?e("p",{role:"status"},"Checking…"):o.signal==="needs-consent"?r.consentGroup():o.signal==="sending"?e("p",{role:"status"},"Sending…"):h&&o.signalNotice&&e("p",{class:"muted",role:"status"},K[o.signalNotice]??""),b&&e("div",{class:"row"},l("Back to the list",O,{id:"jz-else-done","data-autofocus":""}))]}function M(o,t){const d=Y(E(o,k())?.stepCount??0);return e("section",{class:"route","aria-labelledby":"jz-route-title"},e("p",{id:"jz-route-title"},"Did you mean: ",e("strong",{},o.title),"?"),e("p",{class:"muted"},d?`There's a guide for this (${d}).`:"There's a guide for this."),e("div",{class:"row"},l("Show me how",()=>B(o),{id:"jz-route-open",class:"primary","data-autofocus":""}),l("No, send my request",t,{id:"jz-route-send"})))}function F(o,t){if(y?.guide!==o.guide){const p=["YES","PARTLY","NO"].map(u=>{const j=l("",()=>{y&&(y.picked=u);for(const a of p)a.setAttribute("aria-pressed",String(a===j))},{id:`jz-done-${u.toLowerCase()}`,class:`a-${u}`,"aria-pressed":"false"});return j.replaceChildren(X(Q[u]),e("span",{},u==="YES"?"Yes":u==="NO"?"No":"Partly")),j}),b=e("input",{type:"checkbox",id:"jz-done-harder","aria-describedby":"jz-done-harder-hint"}),g=o.guide.steps.length;y={guide:o.guide,harder:b,nodes:[S("Got it done?",void 0,e("span",{class:"mono"},`Step ${g} of ${g}`)),e("div",{class:"progress done","aria-hidden":"true"},e("div",{class:"progress-fill"})),e("p",{class:"muted"},t.title),e("div",{class:"answers",role:"group","aria-labelledby":"jz-jobs-title"},...p),e("div",{class:"harder"},e("label",{for:"jz-done-harder"},b,e("span",{},"Harder than it should be")),e("p",{id:"jz-done-harder-hint",class:"muted"},"Optional: helps us find what to simplify."))]}}const d=y,h=()=>{d.picked&&L({event:"OUTCOME",jobId:t.jobId,jobVersion:t.version,answer:d.picked,harder:d.harder.checked||void 0}),f=void 0,n.close()};return[...d.nodes,o.notice&&e("p",{class:"muted",role:"status"},r.checkinNotice[o.notice]??""),e("div",{class:"row"},l("Finish",h,{id:"jz-done-finish",class:"primary"}),l("Back",()=>n.back()))]}return{owns(o){return o.view==="finished"?!!f&&o.guide.journeyId===f.journeyId:o.view==="index"&&o.status==="ready"&&!!o.jobs?.length},content(o){return o.view==="finished"?f?F(o,f.job):[]:o.view!=="index"?[]:v.kind==="none"?R(v):v.kind==="else"?G(o,v):q(o)},destroy:()=>{V()}}}export{Z as jobsUi};
@@ -0,0 +1,96 @@
1
+ function C(e) {
2
+ const c = `jz:reviewer:${e}`;
3
+ let r = null;
4
+ try {
5
+ const t = new URL(location.href);
6
+ r = t.searchParams.get("jz_invite"), r ? (t.searchParams.delete("jz_invite"), history.replaceState(history.state, "", t.href), sessionStorage.setItem(c, r)) : r = sessionStorage.getItem(c);
7
+ } catch {
8
+ }
9
+ return r || void 0;
10
+ }
11
+ function I(e) {
12
+ try {
13
+ sessionStorage.removeItem(`jz:reviewer:${e}`);
14
+ } catch {
15
+ }
16
+ }
17
+ const k = /^(?:[0-9a-f]{64}|[A-Za-z0-9_-]{43})$/, x = /^pk_[0-9a-f]{32}$/, S = () => import("./widget-B6mR1J3P.js"), T = () => import("./help-w0O5Qu-4.js"), z = () => import("./chat-BgmB0rnW.js").then((e) => e.c), g = /* @__PURE__ */ new Set();
18
+ function p(e) {
19
+ g.has(e) || (g.add(e), console.warn(`[journeeze] ${e}`));
20
+ }
21
+ function w(e) {
22
+ if (e === void 0 || k.test(e)) return e;
23
+ p("invalid userId ignored");
24
+ }
25
+ function b(e, c, r) {
26
+ let t, l, i = 0, u = -1;
27
+ const f = {
28
+ on() {
29
+ if (t) return Promise.resolve();
30
+ if (l && u === i) return l;
31
+ const s = u = i, n = e().then((a) => {
32
+ s === i && !t && (t = c(a, () => f.off()), r?.(!0));
33
+ }).finally(() => {
34
+ l === n && (l = void 0);
35
+ });
36
+ return l = n, n;
37
+ },
38
+ off(s) {
39
+ i++;
40
+ const n = t;
41
+ n && (t = void 0, n.unmount(s), r?.(!1));
42
+ },
43
+ mounted: () => t
44
+ };
45
+ return f;
46
+ }
47
+ const h = (e, c) => (...r) => {
48
+ try {
49
+ c(...r);
50
+ } catch (t) {
51
+ p(`${e} failed: ${String(t)}`);
52
+ }
53
+ };
54
+ function E(e, c = S, r = e.chat ? z : T) {
55
+ const { siteKey: t } = e, l = x.test(t);
56
+ l || p("invalid siteKey");
57
+ let i = w(e.userId), u = { ...e.context };
58
+ const f = () => u, s = { ...e };
59
+ Object.defineProperty(s, "userId", { get: () => i, enumerable: !0 }), e.respectGlobalPrivacyControl !== !1 && navigator.globalPrivacyControl && (s.noTelemetry = !0);
60
+ const n = b(c, (o, d) => o.mount(s, f, d), (o) => s.onModeChange?.(o)), a = b(r, (o, d) => o.mount(s, f, d)), v = (o) => async () => {
61
+ if (!l) throw new Error("[journeeze] invalid siteKey");
62
+ return o.on();
63
+ }, y = {
64
+ enable: v(n),
65
+ disable: h("disable", () => n.off()),
66
+ isEnabled: () => !!n.mounted(),
67
+ enableHelp: v(a),
68
+ disableHelp: h("disableHelp", () => a.off()),
69
+ isHelpEnabled: () => !!a.mounted(),
70
+ feedback: () => v(e.chat ? a : n)().then(() => a.mounted()?.report?.()),
71
+ setContext: h("setContext", (o) => {
72
+ u = { ...u, ...o }, n.mounted()?.contextChanged?.(), a.mounted()?.contextChanged?.();
73
+ }),
74
+ getContext: f,
75
+ setUser: h("setUser", (o, d) => {
76
+ const m = w(o);
77
+ i !== void 0 && m !== i && y.reset(), i = m, s.signature = m && d;
78
+ }),
79
+ reset: h("reset", () => {
80
+ const o = !!a.mounted(), d = { ...s, userId: i };
81
+ n.off(!0), a.off(!0), i = void 0, u = {}, delete s.reviewerToken, I(t), import("./feedback-CtH1a_kQ.js").then((m) => m.logout(d)).catch(() => {
82
+ }).then(() => {
83
+ o && !a.mounted() && a.on().catch(() => {
84
+ });
85
+ });
86
+ })
87
+ };
88
+ return y;
89
+ }
90
+ export {
91
+ x as S,
92
+ k as U,
93
+ E as c,
94
+ C as t,
95
+ p as w
96
+ };
@@ -0,0 +1,5 @@
1
+ import{s as u,c as f}from"./consent-DckCUvYR.js";import{w as d}from"./loader-BZiIDD1D.js";const i=50,m=/^[a-z0-9._:-]{1,96}$/,h=/^\[data-tflow-id="([^"\\]*)"\]$/,g=/^[\x20-\x7e]{1,200}$/,k=/[{};@\\<`]|\/\*|::/,s=new Set;function w(e,n,r){const t=h.exec(e.selector)?.[1];if(t!==void 0&&m.test(t))return{anchor:t,pagePath:n,rule:e.rule,detectedAt:r};if(!(!g.test(e.selector)||k.test(e.selector)))return{selector:e.selector,pagePath:n,rule:e.rule,detectedAt:r}}function $(e){return n=>n.hasAttribute("data-jz-mask")||e.some(r=>{try{return n.matches(r)}catch{return true}})}function y(e,n,r,t,o){const c=u(r),a=o.toISOString();return e(n,$(t)).map(l=>w(l,c,a)).filter(l=>l!==void 0)}async function T(e){const r=y(e.scan,document.body,location.href,e.maskSelectors??[],(e.now??(()=>new Date))()).filter(t=>{const o=`${t.pagePath}
2
+ ${t.anchor??t.selector}
3
+ ${t.rule}`;return s.has(o)?false:(s.add(o),true)});for(let t=0;t<r.length;t+=i){const o=r.slice(t,t+i);try{await f(e.endpoint,"SubmitMaskFindings",{siteKey:e.siteKey,reviewerToken:e.reviewerToken,findings:o},e.fetchImpl)}catch(c){for(const a of o)s.delete(`${a.pagePath}
4
+ ${a.anchor??a.selector}
5
+ ${a.rule}`);d(`mask audit not sent: ${String(c.code??c)}`)}}return r.length}function v(){s.clear()}export{y as auditPage,v as resetMaskAudit,T as runMaskAudit};
package/dist/react.js ADDED
@@ -0,0 +1,71 @@
1
+ import { jsx as I } from "react/jsx-runtime";
2
+ import { createContext as O, useRef as l, useMemo as j, useEffect as f, useContext as N } from "react";
3
+ import { t as M, c as R, w as U } from "./loader-BZiIDD1D.js";
4
+ import { CONTEXT_FIELDS as H } from "./contract.js";
5
+ const T = O(null), a = () => {
6
+ }, $ = Object.freeze({
7
+ enable: () => Promise.resolve(),
8
+ disable: a,
9
+ isEnabled: () => !1,
10
+ enableHelp: () => Promise.resolve(),
11
+ feedback: () => Promise.resolve(),
12
+ disableHelp: a,
13
+ isHelpEnabled: () => !1,
14
+ setContext: a,
15
+ getContext: () => ({}),
16
+ setUser: a,
17
+ reset: a
18
+ }), J = ["maskSelectors", "maskAllText", "nonce", "respectGlobalPrivacyControl", "pagePath", "signals", "chat"], D = (o, v) => JSON.stringify(o) === JSON.stringify(v);
19
+ function G(o) {
20
+ const { children: v, siteKey: c, endpoint: p, apiHost: m, apiPath: g, reviewerToken: b, context: u, userId: n, userIdSig: h, userIdExp: k, onModeChange: C, onHelpStatus: E } = o, P = l(C);
21
+ P.current = C;
22
+ const w = l(E);
23
+ w.current = E;
24
+ const y = l({}), t = j(() => {
25
+ const e = {};
26
+ for (const r of J) o[r] !== void 0 && Object.assign(e, { [r]: o[r] });
27
+ if (y.current = e, c === void 0) return $;
28
+ const i = b ?? M(c);
29
+ return R({
30
+ siteKey: c,
31
+ ...p === void 0 ? {} : { endpoint: p },
32
+ ...m === void 0 ? {} : { apiHost: m },
33
+ ...g === void 0 ? {} : { apiPath: g },
34
+ ...i === void 0 ? {} : { reviewerToken: i },
35
+ ...e,
36
+ onModeChange: (r) => P.current?.(r),
37
+ onHelpStatus: (r) => w.current?.(r)
38
+ });
39
+ }, [c, p, m, g, b]);
40
+ for (const e of J)
41
+ D(o[e], y.current[e]) || U(`\`${e}\` changed after the provider mounted and is ignored; pass a stable value or remount with a \`key\``);
42
+ f(
43
+ () => () => {
44
+ t.disable(), t.disableHelp();
45
+ },
46
+ [t]
47
+ );
48
+ const s = h === void 0 || k === void 0 ? void 0 : { sig: h, exp: k }, d = s ? `${s.sig}:${s.exp}` : "", x = l(void 0), S = (e) => s ? t.setUser(e, s) : t.setUser(e);
49
+ f(() => {
50
+ if (n !== void 0)
51
+ return S(n), x.current = d, () => t.reset();
52
+ }, [t, n]), f(() => {
53
+ n === void 0 || x.current === d || (S(n), x.current = d);
54
+ }, [t, n, d]);
55
+ const z = u === void 0 ? void 0 : H.map((e) => u[e] ?? "").join("\0");
56
+ return f(() => {
57
+ if (u === void 0) return;
58
+ const e = {};
59
+ for (const i of H) e[i] = u[i];
60
+ t.setContext(e);
61
+ }, [t, z, n]), /* @__PURE__ */ I(T.Provider, { value: t, children: v });
62
+ }
63
+ function L() {
64
+ const o = N(T);
65
+ if (!o) throw new Error("useJourneeze must be used inside <JourneezeProvider>");
66
+ return o;
67
+ }
68
+ export {
69
+ G as JourneezeProvider,
70
+ L as useJourneeze
71
+ };
@@ -0,0 +1 @@
1
+ import{T as c}from"./context-UnG6_X61.js";const p=/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/,b=/^[a-z]{2,32}$/,m="input:not([type]),input[type=text],input[type=email],input[type=tel],input[type=url],input[type=password]",f={button:"button,input[type=button],input[type=submit],input[type=reset],input[type=image],summary",link:"a[href],area[href]",textbox:`textarea,${m}`,searchbox:"input[type=search]",checkbox:"input[type=checkbox]",radio:"input[type=radio]",combobox:"select:not([multiple]):not([size]),input[list]",listbox:"select[multiple],select[size],datalist",option:"option",slider:"input[type=range]",spinbutton:"input[type=number]",progressbar:"progress",heading:"h1,h2,h3,h4,h5,h6",img:"img[alt]:not([alt='']),svg[aria-label]",list:"ul,ol,menu",listitem:"li",table:"table",row:"tr",cell:"td",columnheader:"th",navigation:"nav",main:"main",form:"form",dialog:"dialog",article:"article",separator:"hr",group:"fieldset,details,optgroup"},d=new Set(["button","link","heading","option","cell","columnheader","row","listitem","tab","menuitem","checkbox","radio","switch","treeitem","tooltip"]),r=t=>(t??"").replace(/\s+/g," ").trim(),h=t=>{const o=t.getBoundingClientRect();return o.width>0||o.height>0};function g(t){const o=t.ownerDocument,e=[],n=t.getAttribute("id");if(n)for(const s of o.querySelectorAll("label"))s.getAttribute("for")===n&&e.push(s);const a=t.parentElement?.closest("label");return a&&!e.includes(a)&&e.push(a),e}function y(t,o){const e=t.ownerDocument,n=t.getAttribute("aria-labelledby");if(n){const i=r(n.split(/\s+/).map(l=>e.getElementById(l)?.textContent??"").join(" "));if(i)return i}const a=r(t.getAttribute("aria-label"));if(a)return a;const s=r(g(t).map(i=>i.textContent).join(" "));if(s)return s;const u=r(t.getAttribute("alt"));if(u)return u;if(t instanceof HTMLInputElement&&/^(button|submit|reset)$/.test(t.type)){const i=r(t.value);if(i)return i}if(d.has(o)){const i=r(t.textContent);if(i)return i}return r(t.getAttribute("title"))||r(t.getAttribute("placeholder"))}function v(t,o){const e=n=>[...o.querySelectorAll(n)];try{switch(t.by){case"tflow":return c.test(t.value)?e(`[data-tflow-id="${t.value}"]`):[];case"testId":return p.test(t.value)?e(`[data-testid="${t.value}"]`):[];case"role":{if(!b.test(t.value))return[];const n=f[t.value],a=e(n?`[role="${t.value}"],${n}`:`[role="${t.value}"]`),s=r(t.name);return a.filter(u=>{const i=u.getAttribute("role");return i&&i.split(/\s+/)[0]!==t.value?false:!s||y(u,t.value)===s})}case"css":return e(t.value)}}catch{}return[]}function A(t,o=document){for(const e of t){const n=v(e,o).filter(h);if(n.length===1)return n[0]}}export{y as accessibleName,A as resolveTarget};
package/dist/script.js ADDED
@@ -0,0 +1,14 @@
1
+ import { t as c, c as u } from "./loader-BZiIDD1D.js";
2
+ const e = document.querySelector("script[data-journeeze-site-key]"), o = e?.dataset.journeezeSiteKey;
3
+ if (o && !window.Journeeze) {
4
+ const n = c(o), t = e?.dataset ?? {}, a = t.journeezeEndpoint, r = t.journeezeApiHost, i = t.journeezeApiPath, s = u({
5
+ siteKey: o,
6
+ ...a ? { endpoint: a } : {},
7
+ ...r ? { apiHost: r } : {},
8
+ ...i ? { apiPath: i } : {},
9
+ ...n ? { reviewerToken: n } : {},
10
+ ...e?.hasAttribute("data-journeeze-chat") ? { chat: !0 } : {}
11
+ });
12
+ window.Journeeze = s, e?.hasAttribute("data-journeeze-help") && s.enableHelp().catch(() => {
13
+ });
14
+ }
@@ -0,0 +1 @@
1
+ import{CONTEXT_ID_PATTERN as ye,CONTEXT_FIELDS as He}from"./contract.js";import{w as R}from"./loader-BZiIDD1D.js";import{p as Ze,s as Qe,j as we,m as Ye,M as Je,r as et}from"./transport-B64CfIcF.js";import{c as tt,C as _e}from"./consent-DckCUvYR.js";const nt=/[A-Za-z0-9_]/,ot=/^[A-Za-z_]\w{0,63}$/,Z=o=>!!o&&nt.test(o),ae=o=>!!o&&o>="0"&&o<="9";function je(o,n,s){const f=typeof o==typeof s;return n==="=="?f&&o===s:n==="!="?!(f&&o===s):!f||typeof o=="boolean"?false:n==="<"?o<s:n==="<="?o<=s:n===">"?o>s:o>=s}function it(o){if(!(o?.length<=1024))return;let n=0,s=0,f=0;const m=()=>{for(;n<o.length&&o[n]<=" ";)n++},p=()=>{const a=n;for(;n<o.length&&Z(o[n]);)n++;if(o.slice(a,n)!=="event"||o[n]!==".")return;n++;const d=n;for(;n<o.length&&Z(o[n]);)n++;const c=o.slice(d,n);if(c==="kind")return[true,""];if(c!=="fields"||o[n]!==".")return;n++;const v=n;for(;n<o.length&&Z(o[n]);)n++;const h=o.slice(v,n);return ot.test(h)?[false,h]:void 0},I=a=>{let d="";for(n++;n<o.length;){const c=o[n];if(c===a)return n++,d;if(c==="\\"){const v=o[n+1];if(v===void 0||!`\\"'`.includes(v))return;d+=v,n+=2;continue}if(c<" ")return;d+=c,n++}},O=()=>{const a=n;o[n]==="-"&&n++;const d=n;for(;n<o.length&&ae(o[n]);)n++;if(n!==d){if(o[n]==="."){n++;const c=n;for(;n<o.length&&ae(o[n]);)n++;if(n===c)return}return Number(o.slice(a,n))}},L=()=>{const a=o[n];if(a==='"'||a==="'")return I(a);if(a==="-"||ae(a))return O();const d=n;for(;n<o.length&&Z(o[n]);)n++;const c=o.slice(d,n);return c==="true"?true:c==="false"?false:void 0},k=()=>{const a=o[n],d=o[n+1];if(a==="="&&d==="=")return n+=2,"==";if(a==="!"&&d==="=")return n+=2,"!=";if(a==="<"||a===">")return n+=d==="="?2:1,d==="="?a+"=":a},N=()=>{if(m(),o[n]==="("){if(++f>8)return;n++;const h=F();return m(),!h||o[n]!==")"?void 0:(n++,f--,h)}const a=o[n]==="e",d=a?p():L();if(d===void 0)return;m();const c=k();if(!c)return;if(m(),a){const h=L();if(h===void 0||++s>32)return;const E=d;return S=>je(E[0]?S.kind:S.fields[E[1]],c,h)}const v=p();if(v&&!(++s>32))return h=>je(d,c,v[0]?h.kind:h.fields[v[1]])},b=(a,d,c)=>{let v=a();if(v)for(;;){if(m(),o[n]!==d||o[n+1]!==d)return v;n+=2;const h=a();if(!h)return;const E=v;v=c?S=>E(S)&&h(S):S=>E(S)||h(S)}},g=()=>b(N,"&",true),F=()=>b(g,"|",false),$=F();return m(),$&&n===o.length?$:void 0}const Q="step_completed",st=["lt5s","lt15s","lt60s","lt5m","ge5m"],rt=[5e3,15e3,6e4,3e5];function at(o){const n=rt.findIndex(s=>o<s);return st[n<0?4:n]}function ct(o){let n,s=0,f=-1;return{sync(m,p){if(m!==n&&(n=m,s=o(),f=-1),!p||p.journey!==n||p.index<=f)return;const I=o(),O=at(I-s);return s=I,f=p.index,{journey:p.journey,step:p.step,duration_bucket:O}}}}const dt="jz-platform@2",ce={abandoned_step:{step:"int"},hesitation:{dwell_ms:"int"},rage_click:{clicks:"int"},dead_click:{},step_target_missing:{journey:"id",step:"int",rev:"int",tried:"id"},[Q]:{step:"id",journey:"id",duration_bucket:"id"}},Se=/^[a-z][a-z0-9_]{0,63}$/,Pe=/^[a-z0-9._:-]{1,96}$/,lt=/^[a-z0-9._:-]{1,64}$/,ke=700,It=3,be=3e3,de=1e3,ut=12e4,ft=1e3,pt=1e4,mt=300,ht=64,Ee=50,Te=32*1024,ze=5e3,Ae=200,gt=256*1024,Ie=(o,n)=>typeof o=="function"&&n.every(s=>typeof o.prototype?.[s]=="function");function Me(o){const n=o;return!!n&&Ie(n.TFloBrowser,["init","addPattern","removePattern","ingest","flush","destroy"])&&Ie(n.Pattern,["when","then","notThen","within","emit"])}const vt=()=>import("./index-B_nob8S0.js");async function yt(o,n=vt){if(o!==void 0)try{const s=typeof o=="function"?await o():o;if(Me(s))return s;R("signals.tflo lacks the TFloBrowser/Pattern surface; using the SDK's own")}catch{R("signals.tflo failed to load; using the SDK's own")}try{const s=await n();if(Me(s))return s}catch{}R("tflo failed to load; signals off")}const xe="[data-jz-mask],[data-jz-block],input,textarea,select,[contenteditable]:not([contenteditable='false'])";function Oe(o,n=[]){let s=o instanceof Element?o:o instanceof Node?o.parentElement:null;if(!s)return;const f=[xe,...n].join(",");try{if(s.closest(f))return}catch{if(s.closest(xe))return}const p=s.closest("[data-tflow-id]")?.getAttribute("data-tflow-id")??void 0;return p!==void 0&&Pe.test(p)?p:void 0}const wt=o=>Math.round(o/500)*500;function _t(){return crypto.randomUUID()}const jt=128;async function Mt(o){const n=o.site;if(n.signalsEnabled!==true)return;const s=o.options.signals??{},f=await yt(s.tflo,o.loadOwn);if(!f)return;const m=o.now??(()=>performance.now()),p=o.fetchImpl??((...e)=>fetch(...e)),I=o.newId??_t,O=o.options.maskSelectors??[],L=new Map;for(const e of n.siteSignals??[]){if(!Se.test(e.name)||e.name in ce||e.name.startsWith("jz_"))continue;const t={};for(const i of(e.params??[]).slice(0,8))t[i.name]=i.type==="string"?"id":i.type;L.set(e.name,t)}let k=false;const N=[],b=(e,t,i)=>{e.addEventListener(t,i,{capture:true,passive:true}),N.push(()=>e.removeEventListener(t,i,{capture:true}))};let g=[],F=0,$=0,a,d=0,c,v=Promise.resolve();const h=e=>{k||c!==void 0||(c=setTimeout(()=>{c=void 0,v=v.then(Ce)},e))},E=(e,t=0)=>({siteKey:o.options.siteKey,consentGiven:true,ruleSet:dt,signals:e,...t>0?{droppedAtUnload:t}:{}}),S=(e,t)=>{const i=[];for(const r of e){if(i.length>=Ee||we(E([...i,r]))>t)break;i.push(r)}return i},Ce=async()=>{let e=a;if(!e&&g.length>0){const t=S(g,Te);g=g.slice(t.length),e={signals:t,retries:0,firstAt:Date.now(),dropped:d},d=0}if(!(!e||e.signals.length===0)){a=void 0;try{await tt(o.endpoint,"RecordSignals",E(e.signals,e.dropped),p)}catch(t){const i=t instanceof _e?t.status:0,r=t instanceof _e?t.retryAfterMs:void 0;if(!k&&Ye(e.retries,i)&&Date.now()-e.firstAt<Je){a={...e,retries:e.retries+1},h(et(e.retries+1,r));return}}g.length>0&&h(g.length>=Ee?0:ze)}},De=(e,t)=>{if(!(k||$>=mt)){for($++,g.push({eventId:I(),seq:++F,...e}),g.length>Ae&&(g=g.slice(-Ae));g.length>1&&we(g)>gt;)g=g.slice(1);t?(c!==void 0&&clearTimeout(c),c=void 0,h(0)):h(ze)}},le=new Map,W=new Map,K=new Map,ue=typeof s.appVersion=="string"&&ye.test(s.appVersion)?s.appVersion:void 0,Re=()=>{const e=o.getContext(),t={};for(const i of He){const r=e[i];typeof r=="string"&&ye.test(r)&&(t[i]=r)}return ue&&(t.appVersion=ue),t},Le=(e,t)=>{if(e==="int"&&typeof t=="number"&&Number.isFinite(t))return{intValue:String(Math.trunc(t))};if(e==="double"&&typeof t=="number"&&Number.isFinite(t))return{doubleValue:t};if(e==="bool"&&typeof t=="boolean")return{boolValue:t};if(e==="id"&&typeof t=="string"&&lt.test(t))return{stringValue:t}},Y=e=>{const t=e.payload??{};if(t.__drop===true)return;const i=ce[e.name],r=i??L.get(e.name);if(!r)return;const l=typeof t.target=="string"&&Pe.test(t.target)?t.target:void 0;if(e.name==="rage_click"&&l){const x=K.get(l);queueMicrotask(()=>j(()=>x?.reset()))}const u=e.name===Q?`${e.name} ${String(t.journey)} ${String(t.step)}`:`${e.name} ${l??""}`,_=m(),y=le.get(u);if(y!==void 0&&_-y<pt){e.name==="rage_click"&&typeof t.clicks=="number"&&W.set(u,(W.get(u)??0)+t.clicks);return}le.set(u,_);const H={};let D=0;for(const[x,Ge]of Object.entries(r)){let re=t[x];x==="clicks"&&typeof re=="number"&&(re+=W.get(u)??0,W.delete(u));const ve=Le(Ge,re);ve&&D<8&&(H[x]=ve,D++)}e.name===Q&&D!==3||De({name:e.name,source:i?"SIGNAL_SOURCE_PLATFORM":"SIGNAL_SOURCE_SITE",context:Re(),...l?{target:l}:{},...D>0?{params:H}:{}},e.name==="abandoned_step")},J=f.Pattern;let w;const fe=async()=>{const e=new f.TFloBrowser({sinks:[{name:"journeeze",send:Y}],onSinkError:()=>{}});try{await e.init()}catch{return R("tflo failed to initialise; signals off"),false}return k?(e.destroy(),false):(w=e,Xe(e),true)},P=(e,t={})=>{!k&&w&&j(()=>w.ingest({kind:e,ts:m(),fields:t}))},ee=e=>e.kind==="jz.end",T=new Map;let Ne=0,M;const V=e=>{T.delete(e.name),j(()=>w?.removePattern(e.name))},te=(e,t,i,r,l,u)=>{if(!w)return;for(const x of T.values())if(x.key===t)return;T.size>=jt&&V(T.values().next().value);const _=++Ne,y=`${e}#${_}`,H=r(new J(y),_).within(i).emit(l),D=w.addPattern(H);T.set(y,{name:y,key:t,runtime:D,deadline:m()+i}),P("jz.window",{...u,w:_}),M??(M=setInterval($e,ft))};function $e(){const e=m();for(const t of[...T.values()]){if(t.deadline>e)continue;const i=j(()=>t.runtime.flush())??[];V(t);for(const r of i)Y(r)}T.size===0&&M!==void 0&&(clearInterval(M),M=void 0)}const C=(e,t)=>{for(const i of[...T.values()])i.name.startsWith(`${e}#`)&&(t===void 0||i.key===t)&&V(i)};let Ue=0;const z=new Map,Be=e=>{if(!w)return;const t=z.get(e);if(t){z.delete(e),z.set(e,t);return}if(z.size>=ht){const[u,_]=z.entries().next().value;j(()=>w?.removePattern(_)),z.delete(u),K.delete(u)}const i=u=>u.kind==="jz.click"&&u.fields.target===e,r=`rage_click#${++Ue}`,l=w.addPattern(new J(r).when(i).then(i).then(i).within(ke).emit(u=>u.last().ts-u.first().ts<=ke?{name:"rage_click",payload:{target:e,clicks:u.length}}:{name:"rage_click",payload:{__drop:true}}));z.set(e,r),K.set(e,l)},Fe=(e,t)=>te("hesitation",e,be,(i,r)=>i.when(l=>l.fields.w===r).notThen(l=>ee(l)||(l.kind==="jz.unhover"||l.kind==="jz.blur"||l.kind==="jz.click"||l.kind==="jz.change")&&l.fields.target===e),i=>({name:"hesitation",payload:{target:e,dwell_ms:Math.max(be,wt(m()-i.first().ts))}}),{target:e,kind:t}),We=e=>te("dead_click",e,de,(t,i)=>t.when(r=>r.fields.w===i).notThen(r=>ee(r)||r.kind==="jz.effect"),()=>({name:"dead_click",payload:{target:e}}),{target:e});let Ke=0;const pe=[];for(const e of s.rules??[]){if(!Se.test(e.name)||e.name in ce||e.name.startsWith("jz_")){R(`site rule ${e.name} refused (name)`);continue}const t=typeof e.when=="function"?e.when:it(e.when);if(!t){R(`site rule ${e.name} refused (outside the SDK's CEL subset)`);continue}pe.push({rule:e,pred:t})}const Ve=e=>St.has(e.kind);function Xe(e){for(const{rule:t,pred:i}of pe)e.addPattern(new J(`site:${t.name}#${++Ke}`).when(r=>Ve(r)&&j(()=>i({kind:r.kind.slice(3),ts:r.ts,fields:{target:r.fields.target}}))===true).emit(r=>{const l=r.first(),u={target:l.fields.target};for(const[_,y]of Object.entries(t.params??{}))_!=="target"&&(u[_]=bt(l,y));return{name:t.name,payload:u}}))}let A;const qe=ct(m),ne=()=>{const e=o.getContext();A&&e.journeyId!==A.journey&&(C("abandoned_step"),A=void 0);const t=kt(n,e,A),i=qe.sync(e.journeyId,t&&e.journeyStep?{journey:t.journey,index:t.index,step:e.journeyStep}:void 0);if(i&&Y({name:Q,payload:{...i}}),!t||A&&t.index<=A.index||(A&&P("jz.step",{journey:t.journey,index:t.index}),C("abandoned_step"),A=t,t.last))return;const{journey:r,index:l}=t;te("abandoned_step",r,ut,(u,_)=>u.when(y=>y.fields.w===_).notThen(y=>ee(y)||y.kind==="jz.step"&&y.fields.journey===r&&y.fields.index>l),()=>({name:"abandoned_step",payload:{step:l+1}}),{journey:r,index:l})};let me=0;const X=()=>{m()>me||(P("jz.effect"),C("dead_click"))},U=typeof MutationObserver=="function"?new MutationObserver(X):void 0;let B;const oe=typeof PerformanceObserver=="function"?j(()=>new PerformanceObserver(e=>e.getEntries().length>0&&X())):void 0;j(()=>oe?.observe({type:"resource"}));const ie=e=>Oe(e.composedPath?.()[0]??e.target,O);b(document,"click",e=>{const t=ie(e);t&&(Be(t),P("jz.click",{target:t}),C("hesitation",t),me=m()+de,U&&(U.observe(document.documentElement,{childList:true,attributes:true,subtree:true}),B!==void 0&&clearTimeout(B),B=setTimeout(()=>U.disconnect(),de)),We(t))});const q=(e,t)=>b(document,e,i=>{t==="jz.focus"&&X();const r=ie(i);r&&((t==="jz.hover"||t==="jz.unhover")&&Oe(i.relatedTarget,O)===r||(P(t,{target:r}),t==="jz.hover"||t==="jz.focus"?Fe(r,t):C("hesitation",r)))});q("pointerover","jz.hover"),q("pointerout","jz.unhover"),q("focusin","jz.focus"),q("focusout","jz.blur"),b(document,"change",e=>{const t=ie(e);t&&(P("jz.change",{target:t}),C("hesitation",t))});for(const e of["popstate","hashchange"])b(window,e,X);let G=false;const se=()=>{if(k||G)return;G=true;const e=[...a?.signals??[],...g];if(e.length===0)return;const t=(a?.dropped??0)+d,i=S(e,Math.min(Ze(),Te));i.length>0&&Qe(o.endpoint,"RecordSignals",E(i,t),p)&&(a=void 0,g=[],d=e.length-i.length)},he=()=>{for(const e of[...T.values()])V(e);A=void 0},ge=()=>{he();for(const t of z.values())j(()=>w?.removePattern(t));z.clear(),K.clear();const e=w;w=void 0,j(()=>e?.destroy())};if(b(window,"pagehide",()=>{ge(),se()}),b(document,"visibilitychange",()=>{document.visibilityState==="hidden"?se():G=false}),b(window,"pageshow",e=>{G=false,!(!e.persisted||w)&&fe().then(t=>t&&j(ne))}),!await fe()){for(const e of N.splice(0))e();U?.disconnect(),oe?.disconnect();return}return j(ne),{contextChanged:()=>j(ne),stop(e){if(!k){he(),e||se(),k=true;for(const t of N.splice(0))t();M!==void 0&&clearInterval(M),c!==void 0&&clearTimeout(c),B!==void 0&&clearTimeout(B),U?.disconnect(),oe?.disconnect(),g=[],a=void 0,ge()}},idle:()=>v}}const St=new Set(["jz.click","jz.hover","jz.unhover","jz.focus","jz.blur","jz.change"]);function kt(o,n,s){if(!n.journeyId||!n.journeyStep)return;const f=o.publishedJourneys?.find(I=>I.journeyId===n.journeyId)?.stepIds;if(!f||f.length===0)return;const m=s&&s.journey===n.journeyId?s.index+1:0;let p=f.indexOf(n.journeyStep,m);return p<0&&(p=f.indexOf(n.journeyStep)),p>=0?{journey:n.journeyId,index:p,last:p===f.length-1}:void 0}function j(o){try{return o()}catch{return}}function bt(o,n){if(n==="event.kind")return o.kind.slice(3);const s=/^event\.fields\.([A-Za-z_][A-Za-z0-9_]{0,63})$/.exec(n);return s?o.fields[s[1]]:void 0}export{ut as ABANDON_MS,ft as CLOCK_MS,de as DEAD_CLICK_MS,ze as FLUSH_MS,be as HESITATION_MS,Ee as MAX_BATCH,Te as MAX_BATCH_BYTES,Ae as MAX_QUEUED,gt as MAX_QUEUED_BYTES,ht as MAX_TARGETS,jt as MAX_WINDOWS,mt as PAGE_CAP,It as RAGE_CLICKS,ke as RAGE_WINDOW_MS,dt as RULE_SET,pt as THROTTLE_MS,Me as hasFloor,kt as matchCheckpoint,yt as resolveTflo,Mt as startSignals,Oe as trackedId};
@@ -0,0 +1 @@
1
+ import{h as P,c as W,C as Y}from"./consent-DckCUvYR.js";import{p as J,j as T,s as q,M as Q,m as z,r as Z}from"./transport-B64CfIcF.js";function ee(n,u=globalThis.navigator){return n.respectGlobalPrivacyControl!==false&&u?.globalPrivacyControl===true}const M=50,x=32*1024,te=5e3,ne=1e3,ie=1e4,$=200,re=256*1024,c="HELP_EVENT_";function C(n,u){return n.version?{journeyId:n.journeyId,stepIndex:u,guideVersion:n.version}:{journeyId:n.journeyId,stepIndex:u}}const L=new Set([`${c}GUIDE_ABANDONED`,`${c}JOB_OUTCOME`]);function oe(n){return Math.min(Math.max(n??te,ne),ie)}function se(){return crypto.randomUUID()}function le(n){if(ee(n))return{checkin:()=>{},job:()=>{},stop:()=>{}};const u=n.fetchImpl??fetch,m=oe(n.flushMs),B=n.random??Math.random,k=n.newId??se;let t=[],o,s,l=false,y=false,_=0,g=0,r,A,N=false,j;const f=e=>{l||s||(s=setTimeout(()=>{s=void 0,D()},e))},K=()=>{for(t.length>$&&(t=t.slice(-$));t.length>0&&T(t)>re;)t=t.slice(1)},v=e=>{l||(_=_+1>>>0||1,t.push({...e,eventId:k(),seq:_}),K(),L.has(e.event)?(s&&clearTimeout(s),s=void 0,D()):f(m))},G=()=>{if(o)return o;if(t.length===0)return;const e=[];for(const i of t){if(e.length===M||e.length>0&&T([...e,i])>x)break;e.push(i)}return t=t.slice(e.length),{events:e,firstAttempt:Date.now(),retries:0}},b=e=>{const i={siteKey:n.siteKey,consentGiven:true,events:e};return g>0&&(i.droppedAtUnload=g),i},D=async()=>{if(y||l)return;if(!P(n.siteKey)){t=[],o=void 0;return}if(typeof navigator<"u"&&navigator.onLine===false)return;const e=G();if(!e)return;if(o=void 0,Date.now()-e.firstAttempt>Q){t.length>0&&f(m);return}y=true;const i=g;try{await W(n.endpoint,"RecordHelpEvents",b(e.events),u),g-=i}catch(h){const d=h instanceof Y?h:void 0,a=d?.status??0;if(d?.code==="failed_precondition")l=true,t=[];else if(z(e.retries,a)){e.retries+=1,o=e,y=false,f(Z(e.retries,d?.retryAfterMs,B));return}}finally{y=false}!l&&(t.length>0||o)&&f(t.length>=M?0:m)},H=()=>{if(l&&t.length===0&&!o||(s&&clearTimeout(s),s=void 0,!P(n.siteKey)))return;const e=[...o?.events??[],...t];if(e.length===0)return;const i=[...e.filter(a=>L.has(a.event)),...e.filter(a=>!L.has(a.event))],h=Math.min(J(),x),d=[];for(const a of i){if(d.length===M||T(b([...d,a]))>h)break;d.push(a)}d.length!==0&&q(n.endpoint,"RecordHelpEvents",b(d),u)&&(g+=e.length-d.length,t=[],o=void 0)};let w=false;const I=()=>{w||(w=true,H())},R=()=>{typeof document<"u"&&document.visibilityState==="hidden"&&I()},p=()=>{typeof document<"u"&&document.visibilityState!=="visible"||(w=false,(t.length>0||o)&&f(0))},U=()=>{(t.length>0||o)&&f(0)},S=()=>{r&&!r.done&&r.last!==void 0&&v({event:`${c}GUIDE_ABANDONED`,...C(r.guide,r.last)}),r=void 0,A=void 0},X=e=>{const i=j;if(j=e,i===void 0)return;if(e.view==="disabled"){l=true,t=[];return}i.view==="closed"&&(e.view==="index"||e.view==="guide")&&v({event:`${c}HELP_OPENED`,entry:e.view==="index"?"HELP_ENTRY_LAUNCHER":"HELP_ENTRY_API"});const h=e.view==="guide"||e.view==="finished"?e.guide:void 0,d=e.view==="guide"?e.journeyId:h?.journeyId;if(r&&d!==r.guide.journeyId&&S(),e.view==="guide"&&e.status==="ready"&&e.guide){r||(r={guide:e.guide,seen:new Set,done:false});const E=e.guide.steps[e.step],O=E&&`${e.guide.journeyId}/${e.step}`;E&&O!==A&&(A=O,r.last=E.index,v({event:`${c}${r.seen.has(E.index)?"STEP_REPEATED":"STEP_REACHED"}`,...C(e.guide,E.index)}),r.seen.add(E.index))}else e.view==="finished"&&r&&(r.done=true,S());const a=e.view==="index"&&e.status==="ready"&&e.query.trim()!==""&&e.results.length===0;a&&!N&&v({event:`${c}SEARCH_NO_RESULT`}),N=a},F=n.subscribe(X);addEventListener("pagehide",I),addEventListener("visibilitychange",R),addEventListener("visibilitychange",p),addEventListener("pageshow",p),addEventListener("online",U);const V=()=>{removeEventListener("pagehide",I),removeEventListener("visibilitychange",R),removeEventListener("visibilitychange",p),removeEventListener("pageshow",p),removeEventListener("online",U)};return{checkin(e){v({event:`${c}CHECKIN_ANSWERED`,...C(e.guide,e.step.index),answer:e.answer==="confused"?"CHECKIN_ANSWER_CONFUSED":"CHECKIN_ANSWER_UNDERSTOOD"})},job(e){const i={event:`${c}JOB_${e.event}`,jobId:e.jobId};e.jobVersion&&(i.jobVersion=e.jobVersion),e.persona&&(i.persona=e.persona),e.event==="OUTCOME"&&(i.jobAnswer=`JOB_ANSWER_${e.answer}`,e.harder!==void 0&&(i.harderThanExpected=e.harder)),v(i)},stop(e){if(F(),V(),!l){if(e){t=[],o=void 0,s&&clearTimeout(s),s=void 0,l=true;return}S(),l=true,H()}}}}export{te as FLUSH_MS,M as MAX_BATCH,x as MAX_BATCH_BYTES,ie as MAX_FLUSH_MS,$ as MAX_QUEUED,re as MAX_QUEUED_BYTES,ne as MIN_FLUSH_MS,ee as gpcRefusesTelemetry,le as startTelemetry};
@@ -0,0 +1 @@
1
+ import{r as l,T as d,R as f}from"./consent-DckCUvYR.js";const E=1e3,p=5,y=3,S=55*6e4;function h(e){return e===0||e===408||e===429||e===500||e===502||e===503||e===504}function _(e,n){return h(n)&&e<(n===0?y:p)}function T(e,n,o=Math.random){const t=Math.min(E*2**Math.max(e-1,0),f)*(.5+o());return Math.round(Math.max(Math.min(t,f),n??0))}const m=32*1024;function v(){try{return typeof Request<"u"&&"keepalive"in new Request("https://journeeze.invalid/",{method:"POST",keepalive:true})}catch{return false}}let r=0,u=false;function R(){if(u||typeof addEventListener!="function")return;u=true;const e=()=>{(typeof document>"u"||document.visibilityState==="visible")&&(r=0)};addEventListener("pageshow",e),addEventListener("visibilitychange",e)}function g(){return R(),Math.max(m-r,0)}function A(e,n,o,a=fetch){const t=JSON.stringify(o),i=new TextEncoder().encode(t).length;if(i>g())return false;const c=l(e,n);if(v()){r+=i;try{return a(c,{method:"POST",headers:{"content-type":d},body:t,keepalive:true,credentials:"omit",cache:"no-store",referrerPolicy:"no-referrer"}).catch(()=>{}),true}catch{return false}}if(typeof navigator>"u"||typeof navigator.sendBeacon!="function")return false;const s=navigator.sendBeacon(c,new Blob([t],{type:d}));return s&&(r+=i),s}function b(e){return new TextEncoder().encode(JSON.stringify(e)).length}export{S as M,b as j,_ as m,g as p,T as r,A as s};
@@ -0,0 +1,41 @@
1
+ import type { MountOptions } from "../../loader";
2
+ import { type MaskOptions } from "../../widget/capture";
3
+ import type { GetWidgetConfigResponse } from "../../types";
4
+ import { type PlusItem } from "../shell/converse";
5
+ import type { Copy } from "../shell/copy";
6
+ import { type ChatSession } from "../shell/session";
7
+ export { maskedSnapshotSvg } from "../../widget/capture";
8
+ export interface PlusHost {
9
+ session: ChatSession;
10
+ /** The chat's shadow root: the drawing view and the picker render inside it. */
11
+ root: ShadowRoot;
12
+ options: MountOptions;
13
+ endpoint: string;
14
+ /** The chat's one `GetWidgetConfig` read (the site's mask selectors); rejects when it failed. */
15
+ config(): Promise<GetWidgetConfigResponse>;
16
+ /** Hides the chat while capturing or pointing; the result brings it back. */
17
+ suspend(): () => void;
18
+ }
19
+ export declare const IMAGE_TYPES: readonly string[];
20
+ export declare const MAX_FILE_BYTES: number;
21
+ /** Runs one "+" menu item. Never throws: every failure is a calm note in the conversation. */
22
+ export declare function plusItem(item: PlusItem, host: PlusHost): Promise<void>;
23
+ /** The host's masking plus the project's journey-configuration selectors. Without the site's
24
+ * selectors there is no capture: masking only widens, it never runs with fewer than configured. */
25
+ export declare function maskOptions(host: PlusHost): Promise<MaskOptions>;
26
+ /** The masked viewport, or `undefined` when masking could not be applied. */
27
+ export declare function maskedCapture(host: PlusHost): Promise<Blob | undefined>;
28
+ /** The page element under a point, never Journeeze's own UI. */
29
+ export declare function pageElementAt(x: number, y: number): Element | undefined;
30
+ /** Lets the user click or tap an element; resolves it, or `undefined` on Cancel/Esc. */
31
+ export declare function pick(root: ShadowRoot, t: Copy): Promise<Element | undefined>;
32
+ /** Validates and re-encodes a chosen image, then adds it to the draft. */
33
+ export declare function addFile(host: PlusHost, file: Blob): Promise<void>;
34
+ /** Decodes and re-encodes an image (dropping EXIF and any other metadata), ≤ 1600 px, ≤ 2 MB. */
35
+ export declare function reencode(file: Blob): Promise<{
36
+ blob: Blob;
37
+ size: {
38
+ w: number;
39
+ h: number;
40
+ };
41
+ } | undefined>;
@@ -0,0 +1,10 @@
1
+ import type { FeedbackShape } from "../../schemas/feedback";
2
+ import type { Copy } from "../shell/copy";
3
+ /**
4
+ * Opens the drawing view over `imageUrl` (`size` in image pixels) inside `root`, worded with the
5
+ * site's copy `t`. Resolves the shapes on Done, or `undefined` on Cancel/Esc.
6
+ */
7
+ export declare function drawView(root: ShadowRoot, imageUrl: string, size: {
8
+ w: number;
9
+ h: number;
10
+ }, t: Copy): Promise<FeedbackShape[] | undefined>;
@@ -0,0 +1,30 @@
1
+ import type { FeedbackShape, FeedbackShapeType } from "../../schemas/feedback";
2
+ /** Shapes per screenshot (feedback/v2 `shapes` maxItems). */
3
+ export declare const MAX_SHAPES = 10;
4
+ /** A keyboard step: 2% of the image side. */
5
+ export declare const STEP = 0.02;
6
+ export interface Point {
7
+ x: number;
8
+ y: number;
9
+ }
10
+ /** A pointer position over the image box as a point inside the image (0..1 on both axes). */
11
+ export declare function normalise(clientX: number, clientY: number, box: {
12
+ left: number;
13
+ top: number;
14
+ width: number;
15
+ height: number;
16
+ }): Point;
17
+ /** The shape a drag from `a` to `b` draws. */
18
+ export declare function shapeFrom(type: FeedbackShapeType, a: Point, b: Point): FeedbackShape;
19
+ /** A tap rather than a drag: smaller than 1% of the image on both sides. */
20
+ export declare function isTiny(s: FeedbackShape): boolean;
21
+ /** A shape in the middle of the image, for drawing with the keyboard. */
22
+ export declare function centred(type: FeedbackShapeType): FeedbackShape;
23
+ /** Moves the shape by (`dx`, `dy`), or resizes it, staying inside the image. */
24
+ export declare function nudge(s: FeedbackShape, dx: number, dy: number, resize: boolean): FeedbackShape;
25
+ /** Within feedback/v2's bounds: x, y in 0..1 and w, h in -1..1 (negative only for arrows). */
26
+ export declare function isValidShape(s: FeedbackShape): boolean;
27
+ /** Arrowhead points (image pixels) for an arrow from (x1, y1) to (x2, y2). */
28
+ export declare function arrowHead(x1: number, y1: number, x2: number, y2: number, size: number): string;
29
+ /** Paints shapes over an image of `w`×`h` pixels (thumbnails). */
30
+ export declare function paint(ctx: CanvasRenderingContext2D, shapes: readonly FeedbackShape[], w: number, h: number): void;
@@ -0,0 +1 @@
1
+ export declare const CAPTURE_CSS = "\n.jzd{position:fixed;inset:0;z-index:2147483647;display:flex;flex-direction:column;background:var(--c);color:var(--i)}\n.jzd header{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;padding:12px 16px;border-bottom:1px solid var(--l);background:var(--s)}\n.jzd h2{margin:0;font-size:14px;font-weight:600}\n.jzd header p{margin:0;font-size:12px;color:var(--m)}\n.jzd .bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:8px 16px;border-bottom:1px solid var(--l);background:var(--s)}\n.jzd .bar .sep{width:1px;height:28px;background:var(--l);margin:0 4px}\n.jzd .bar .end{margin-left:auto;display:flex;gap:6px}\n.jzd .tool{min-width:44px;min-height:44px;padding:0 12px;border:1px solid var(--l);border-radius:6px;background:var(--s)}\n.jzd .tool[aria-pressed=true]{background:var(--as);border-color:var(--a);color:var(--a);font-weight:600}\n.jzd .wrap{flex:1;min-height:0;display:grid;place-items:center;padding:16px}\n.jzd .stage{position:relative;border:1px solid var(--l);border-radius:6px;overflow:hidden;background:var(--r);touch-action:none;cursor:crosshair;user-select:none;-webkit-user-select:none}\n.jzd .stage img,.jzd .stage svg{position:absolute;inset:0;width:100%;height:100%;display:block}\n.jzd .stage svg{overflow:visible}\n.jzd .stage *{pointer-events:none}\n.jzd .msg{min-height:20px;margin:0;padding:0 16px 8px;font-size:12px;color:var(--m)}\n.pick{position:fixed;inset:0;z-index:2147483647;cursor:crosshair;touch-action:none}\n.pick .hl{position:fixed;border:2px solid var(--a);border-radius:4px;background:var(--as);pointer-events:none}\n.pick .hint{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);display:flex;align-items:center;gap:8px;max-width:calc(100vw - 32px);padding:4px 4px 4px 16px;border:1px solid var(--l);border-radius:10px;background:var(--s);box-shadow:var(--sh);font-size:13px}\n@media (max-width:640px){.jzd .bar .end{margin-left:0;width:100%}.jzd .bar .end .btn{flex:1}.jzd .wrap{padding:8px}}\n";
@@ -0,0 +1,27 @@
1
+ import type { MountedWidget, MountOptions, WidgetModule } from "../../loader";
2
+ import type { HelpJobEntry, JourneezeContext } from "../../types";
3
+ import type { ConverseTransport, PlusItem } from "./converse";
4
+ import { type Copy } from "./copy";
5
+ import { type Chip, type ReportFacts } from "./model";
6
+ import { type Attachment } from "./session";
7
+ export interface MountedChat extends MountedWidget {
8
+ /** Opens the chat at "Report a problem" (`Journeeze.feedback()`). */
9
+ report(): void;
10
+ /** The draft's attachments ("Show us where" adds its masked captures here); false past five
11
+ * (or before the chat has loaded the site's copy). */
12
+ addAttachment(a: Attachment): boolean;
13
+ removeAttachment(id: string): void;
14
+ }
15
+ export interface ChatDeps {
16
+ transport?: ConverseTransport;
17
+ /** Reads the site's jobs for the opening chips; default `GetHelpIndex`. */
18
+ loadJobs?: () => Promise<HelpJobEntry[]>;
19
+ /** A "+" menu item was chosen; default: the lazy capture chunk (`../capture/attach`). */
20
+ onPlusItem?: (item: PlusItem) => void;
21
+ }
22
+ /** The page facts a turn's context is built from (feedback/v2 `context`). */
23
+ export declare function pageFacts(options: MountOptions, ctx: Readonly<JourneezeContext>): ReportFacts;
24
+ /** The opening chips, badged with the site's `widget.ui.chip.*` copy. */
25
+ export declare function jobChips(jobs: readonly HelpJobEntry[], t: Copy): Chip[];
26
+ export declare function mountChat(options: MountOptions, getContext: () => Readonly<JourneezeContext>, deps?: ChatDeps): MountedChat;
27
+ export declare const mount: WidgetModule["mount"];
@@ -0,0 +1,95 @@
1
+ import type { FeedbackContext, FeedbackMessage, FeedbackTeam } from "../../schemas/feedback";
2
+ import type { TurnInput } from "../../schemas/turn";
3
+ /** `schema` of every Converse request. */
4
+ export declare const TURN_SCHEMA = "journeeze.turn/v1";
5
+ /** A guide step card on an assistant message. */
6
+ export interface ConverseCard {
7
+ jobId?: string;
8
+ step?: number;
9
+ of?: number;
10
+ title?: string;
11
+ instruction?: string;
12
+ }
13
+ /** An assistant message: rendered copy from the server's copy pack. */
14
+ export interface ConverseMessage {
15
+ copyId: string;
16
+ text: string;
17
+ card?: ConverseCard;
18
+ }
19
+ /** The `plus_menu` items (contract §2). */
20
+ export type PlusItem = "show_us_where" | "point_at_it" | "attach_file";
21
+ /** A "+" menu item with its copy (contract §2 `ConverseMenuItem`), in `items` order. */
22
+ export interface ConverseMenuItem {
23
+ id: PlusItem;
24
+ label: string;
25
+ hint?: string;
26
+ }
27
+ /** What the UI may offer next (contract §2 `actions`). `label` is the server's rendered copy
28
+ * (ADR 0020 §5); a chip's label is its job title. */
29
+ export type ConverseAction = {
30
+ label?: string;
31
+ } & ({
32
+ type: "chip";
33
+ jobId: string;
34
+ title: string;
35
+ badge?: string | null;
36
+ steps?: number;
37
+ } | {
38
+ type: "plus_menu";
39
+ items: PlusItem[];
40
+ menu?: ConverseMenuItem[];
41
+ } | {
42
+ type: "other_need" | "guide_next" | "guide_back" | "didnt_work" | "consent" | "send" | "talk_to_assistant";
43
+ });
44
+ /** Runtime over-masking for one detector rule (contract §2 `overMasked`): a count, never a value. */
45
+ export interface OverMaskCount {
46
+ rule: string;
47
+ count: number;
48
+ }
49
+ export interface ConverseRequest {
50
+ siteKey: string;
51
+ conversationId: string;
52
+ turnId: string;
53
+ consentGiven: boolean;
54
+ context: FeedbackContext;
55
+ schema: typeof TURN_SCHEMA;
56
+ payload: {
57
+ input: TurnInput;
58
+ draft?: FeedbackMessage;
59
+ team?: FeedbackTeam;
60
+ };
61
+ /** A reviewer session (as v1 `SubmitFeedbackRequest.reviewerToken`). */
62
+ reviewerToken?: string;
63
+ /** The host's signed opaque user id (C0a §4), sent with consented turns only. */
64
+ userId?: string;
65
+ userIdExp?: number;
66
+ userIdSig?: string;
67
+ overMasked?: OverMaskCount[];
68
+ }
69
+ export interface ConverseResponse {
70
+ state: string;
71
+ machine: string;
72
+ messages: ConverseMessage[];
73
+ actions: ConverseAction[];
74
+ filed?: {
75
+ feedbackId?: string;
76
+ kind?: string;
77
+ };
78
+ requiresConsent: boolean;
79
+ }
80
+ /** Why a turn failed, in the words the shell shows. */
81
+ export type FailureKind = "invalid" | "busy" | "unavailable";
82
+ export declare class ConverseFailure extends Error {
83
+ readonly kind: FailureKind;
84
+ readonly status: number;
85
+ constructor(kind: FailureKind, status: number);
86
+ }
87
+ /** A UUIDv4 (contract §2): `crypto.randomUUID` where it exists, else from random bytes. */
88
+ export declare function uuid4(): string;
89
+ /** The failure a status maps to: 429 busy, 400 invalid, everything else (503, network) unavailable. */
90
+ export declare function failureOf(err: unknown): ConverseFailure;
91
+ export interface ConverseTransport {
92
+ /** POSTs one turn; rejects with a {@link ConverseFailure}. */
93
+ turn(req: ConverseRequest): Promise<ConverseResponse>;
94
+ }
95
+ export declare function converseTransport(endpoint: string, fetchImpl?: typeof fetch): ConverseTransport;
@@ -0,0 +1,8 @@
1
+ /** The `widget.ui.*` keys the chat shows (the full key is `widget.ui.<UiKey>`). */
2
+ export type UiKey = "add_to_message" | "allow" | "attachment.image" | "attachment.screenshot" | "attachments" | "cancel" | "card.step" | "card.step_of" | "chip.no_guide" | "chip.one_step" | "chip.steps" | "close" | "consent_line" | "context.build" | "context.page" | "context.persona" | "context.step" | "context.title" | "conversation" | "draw.added.arrow" | "draw.added.box" | "draw.added.circle" | "draw.arrow" | "draw.box" | "draw.circle" | "draw.clear" | "draw.cleared" | "draw.done" | "draw.hint" | "draw.image" | "draw.keys" | "draw.removed_last" | "draw.shape_limit" | "draw.stage" | "draw.title" | "draw.tools" | "draw.undo" | "error.busy" | "error.invalid" | "error.unavailable" | "greeting" | "input.paused" | "input.placeholder" | "input.tap_only" | "launcher" | "message" | "note.attachment_limit" | "note.capture_unavailable" | "note.file_read" | "note.file_type" | "note.masking_failed" | "note.no_name" | "note.signed_out" | "note.unmet" | "note.upload_failed" | "other_need" | "point.hint" | "point.label" | "pointed_at" | "remove" | "report_problem" | "send" | "speaker.assistant" | "speaker.you" | "subtitle" | "suggestions" | "team.severity" | `team.severity.${"low" | "medium" | "high" | "critical"}` | "team.title" | "team.verdict" | `team.verdict.${"unreviewed" | "polished" | "needs_polish" | "broken"}` | "title" | "try_again";
3
+ /** A `widget.ui.*` text with its `{name}` placeholders filled; "" when the site's copy lacks it. */
4
+ export type Copy = (key: UiKey, params?: Record<string, string | number>) => string;
5
+ /** The launcher's accessible name when the site's copy could not be read (the only literal). */
6
+ export declare const LAST_RESORT_LAUNCHER = "Help";
7
+ /** The {@link Copy} over a `GetWidgetConfig` `copy` map (absent: every key is ""). */
8
+ export declare function copyOf(map: Readonly<Record<string, string>> | undefined): Copy;
@@ -0,0 +1,36 @@
1
+ import type { FeedbackContext, FeedbackDevice, FeedbackRemovedChip } from "../../schemas/feedback";
2
+ import type { ConverseAction } from "./converse";
3
+ import type { Copy } from "./copy";
4
+ export type Chip = Extract<ConverseAction, {
5
+ type: "chip";
6
+ }>;
7
+ /** Job chips whose title holds every typed word (case-insensitive); the query is never sent. */
8
+ export declare function filterChips(chips: readonly Chip[], query: string): Chip[];
9
+ /** A chip's guide length: its structured `steps` (contract #218), never its display `badge`. */
10
+ export declare function chipSteps(chip: Chip): number | undefined;
11
+ /** The browser family (never the full user agent). */
12
+ export declare function browserName(ua: string): string;
13
+ /** A removable chip of "Sent with this report". `removable: false` chips are shown, not sent as context. */
14
+ export interface ContextChip {
15
+ key: "job" | "step" | FeedbackRemovedChip;
16
+ label: string;
17
+ removable: boolean;
18
+ }
19
+ /** What the report carries about the page and the user's place in it. */
20
+ export interface ReportFacts {
21
+ pagePath: string;
22
+ persona?: string | undefined;
23
+ browser?: string | undefined;
24
+ device?: FeedbackDevice | undefined;
25
+ viewport?: {
26
+ w: number;
27
+ h: number;
28
+ } | undefined;
29
+ build?: string | undefined;
30
+ job?: string | undefined;
31
+ step?: number | undefined;
32
+ }
33
+ /** The chips of "Sent with this report", minus what the user removed (labels from the site's copy). */
34
+ export declare function contextChips(f: ReportFacts, removed: ReadonlySet<string>, t: Copy): ContextChip[];
35
+ /** The feedback/v2 `context` of a turn: removed chips' values are absent and listed in `removed`. */
36
+ export declare function turnContext(f: ReportFacts, removed: ReadonlySet<string>): FeedbackContext;