blocfeed 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ - (none)
6
+
7
+ ## 0.2.0 — 2026-02-17
8
+
9
+ - **Breaking**: `blocfeed_id` is now required for `BlocFeedWidget`, `BlocFeedProvider`, and all submissions.
10
+ - **Breaking**: removed `submit.onSubmit` / `submit.webhook`; the SDK always submits to the BlocFeed ingestion API (`POST https://www.blocfeed.com/api/feedback`).
11
+
12
+ ## 0.1.1 — 2026-02-16
13
+
14
+ - Next.js App Router: clarified Server Component constraints (serializable props) and added webhook-first examples.
15
+ - Build: published `dist/main.*` now includes a `"use client";` banner so `BlocFeedWidget` can be mounted directly from `app/layout.tsx` when using serializable config.
16
+ - Docs: synced `docs/modules.md`, `docs/lifecycle.md`, and `docs/api.md` with the implementation.
package/README.md CHANGED
@@ -5,9 +5,11 @@ Drop-in in-app feedback widget for **Next.js** and **React**:
5
5
  - Safe “feedback mode” with **DOM element picking** (blocks host app clicks while active)
6
6
  - Optional **element** + **full page** screenshots (capture code is lazy-loaded)
7
7
  - Typed, JSON-serializable `FeedbackPayload` with contextual metadata
8
- - Submit via `submit.onSubmit(payload)` and/or `submit.webhook`
8
+ - Submits directly to the BlocFeed platform via `blocfeed_id`
9
9
  - Optional `selection.componentName` + `selection.testId` for faster triage
10
10
 
11
+ Docs live in `docs/` (start at `docs/index.md`). Architecture pointers are in `ARCHITECTURE.md`.
12
+
11
13
  ## Install
12
14
 
13
15
  ```bash
@@ -16,6 +18,14 @@ npm install blocfeed
16
18
 
17
19
  Peer deps: `react`, `react-dom`.
18
20
 
21
+ ## Get your `blocfeed_id`
22
+
23
+ Create a project in the BlocFeed dashboard (`https://www.blocfeed.com`). Each project has a unique `blocfeed_id` that the SDK uses to link incoming feedback to the correct project.
24
+
25
+ ## Submission endpoint
26
+
27
+ Submissions are sent to the BlocFeed platform ingestion API at `https://www.blocfeed.com/api/feedback`. Custom/external endpoints are intentionally not supported.
28
+
19
29
  ## Next.js (App Router) — copy/paste
20
30
 
21
31
  `app/layout.tsx`
@@ -23,44 +33,19 @@ Peer deps: `react`, `react-dom`.
23
33
  ```tsx
24
34
  import type { ReactNode } from "react";
25
35
  import { BlocFeedWidget } from "blocfeed";
26
- import type { FeedbackPayload } from "blocfeed";
27
36
 
28
37
  export default function RootLayout({ children }: { children: ReactNode }) {
29
38
  return (
30
39
  <html lang="en">
31
40
  <body>
32
41
  {children}
33
- <BlocFeedWidget
34
- config={{
35
- submit: {
36
- onSubmit: async (payload: FeedbackPayload) => {
37
- await fetch("/api/feedback", {
38
- method: "POST",
39
- headers: { "content-type": "application/json" },
40
- body: JSON.stringify(payload)
41
- });
42
- }
43
- }
44
- }}
45
- />
42
+ <BlocFeedWidget blocfeed_id="bf_your_project_blocfeed_id" />
46
43
  </body>
47
44
  </html>
48
45
  );
49
46
  }
50
47
  ```
51
48
 
52
- `app/api/feedback/route.ts`
53
-
54
- ```ts
55
- import { NextResponse } from "next/server";
56
-
57
- export async function POST(req: Request) {
58
- const payload = await req.json();
59
- // Persist, forward to your tracker, etc.
60
- return NextResponse.json({ ok: true });
61
- }
62
- ```
63
-
64
49
  ## Next.js (Pages Router)
65
50
 
66
51
  Use a client-only dynamic import:
@@ -77,7 +62,7 @@ export default function App({ Component, pageProps }) {
77
62
  return (
78
63
  <>
79
64
  <Component {...pageProps} />
80
- <BlocFeedWidget config={{ submit: { onSubmit: console.log } }} />
65
+ <BlocFeedWidget blocfeed_id="bf_your_project_blocfeed_id" />
81
66
  </>
82
67
  );
83
68
  }
@@ -92,29 +77,12 @@ export function App() {
92
77
  return (
93
78
  <>
94
79
  {/* your app */}
95
- <BlocFeedWidget config={{ submit: { onSubmit: console.log } }} />
80
+ <BlocFeedWidget blocfeed_id="bf_your_project_blocfeed_id" />
96
81
  </>
97
82
  );
98
83
  }
99
84
  ```
100
85
 
101
- ## Webhook mode
102
-
103
- ```tsx
104
- <BlocFeedWidget
105
- config={{
106
- submit: {
107
- webhook: {
108
- url: "https://example.com/api/feedback",
109
- headers: async () => ({ Authorization: `Bearer ${token}` }),
110
- timeoutMs: 12_000,
111
- retry: { attempts: 2, backoffMs: 500 }
112
- }
113
- }
114
- }}
115
- />
116
- ```
117
-
118
86
  ## Picking rules (ignore / filter)
119
87
 
120
88
  ### Ignore a subtree (recommended)
@@ -181,7 +149,7 @@ function FeedbackButton() {
181
149
 
182
150
  export function App() {
183
151
  return (
184
- <BlocFeedProvider config={{ submit: { onSubmit: console.log } }}>
152
+ <BlocFeedProvider blocfeed_id="bf_your_project_blocfeed_id">
185
153
  {/* your app */}
186
154
  <FeedbackButton />
187
155
  </BlocFeedProvider>
@@ -193,6 +161,8 @@ export function App() {
193
161
 
194
162
  ```ts
195
163
  import { createBlocFeedController } from "blocfeed/engine";
164
+
165
+ const controller = createBlocFeedController({ blocfeed_id: "bf_your_project_blocfeed_id" });
196
166
  ```
197
167
 
198
168
  ## Local development
@@ -0,0 +1,2 @@
1
+ function b(){return typeof window<"u"&&typeof document<"u"}function W(e){let n=globalThis.CSS;return typeof n?.escape=="function"?n.escape(e):e.replace(/[^a-zA-Z0-9_-]/g,t=>{let r=t.codePointAt(0);return r===void 0?"":`\\${r.toString(16)} `})}function H(e){return {x:e.x,y:e.y,width:e.width,height:e.height}}function de(e){return {x:e.x+window.scrollX,y:e.y+window.scrollY,width:e.width,height:e.height}}function fe(e){return e.replace(/\s+/g," ").trim()}function me(e,n=140){let t=e.textContent;if(!t)return;let r=fe(t);if(r)return r.length<=n?r:`${r.slice(0,n-1)}\u2026`}function pe(e){let n=1;for(let t=e.previousElementSibling;t;t=t.previousElementSibling)t.tagName===e.tagName&&(n+=1);return n}var K=["data-testid","data-test-id","data-test","data-qa","data-cy"],z="data-blocfeed-component";function ge(e){let n=e.closest(`[${z}]`);if(!n)return;let r=n.getAttribute(z)?.trim();return r||void 0}function we(e){for(let n of K){let t=e.closest(`[${n}]`);if(!t)continue;let o=t.getAttribute(n)?.trim();if(o)return o}}function he(e){try{let n=e,t=Object.getOwnPropertyNames(n);for(let r of t)if(r.startsWith("__reactFiber$")||r.startsWith("__reactInternalInstance$")){let o=n[r];if(o&&typeof o=="object")return o}}catch{}return null}function C(e){if(e&&typeof e!="string"){if(typeof e=="function"){let n=e;return typeof n.displayName=="string"&&n.displayName?n.displayName:typeof n.name=="string"&&n.name?n.name:void 0}if(typeof e=="object"){let n=e,t=n.displayName;if(typeof t=="string"&&t)return t;let r=n.render;if(typeof r=="function"){let i=r;if(typeof i.displayName=="string"&&i.displayName)return i.displayName;if(typeof i.name=="string"&&i.name)return i.name}let o=n.type;return C(o)}}}function be(e){let n=he(e);if(!n)return;let t=n._debugOwner;for(let o=0;t&&o<50;o+=1){let i=C(t.type)??C(t.elementType);if(i)return i;t=t._debugOwner;}let r=n;for(let o=0;r&&o<80;o+=1){let i=C(r.type)??C(r.elementType);if(i)return i;r=r.return;}}function ye(e){let n=e.tagName.toLowerCase(),t=e.getAttribute("id");if(t)return `#${W(t)}`;for(let r of K){let o=e.getAttribute(r);if(o)return `${n}[${r}="${W(o)}"]`}return `${n}:nth-of-type(${pe(e)})`}function Ee(e,n=10){let t=[],r=e;for(;r&&t.length<n;){let o=ye(r);if(t.unshift(o),o.startsWith("#"))break;r=r.parentElement;}return t.join(" > ")}function Y(e,n){if(!n||n.length===0)return false;for(let t of n)if(e.closest(t))return true;return false}function N(e,n){if(!e||Y(e,n.ignoreSelectors))return null;let t=e;for(;t;){if(Y(t,n.ignoreSelectors))return null;if(n.isSelectable?.(t)??ve(t))return t;t=t.parentElement;}return null}function ve(e){let n=e.tagName;return !(n==="HTML"||n==="BODY")}function Q(e){let n=e.getBoundingClientRect(),t={selector:Ee(e),tagName:e.tagName.toLowerCase(),rect:H(n),pageRect:de(n)},r=e.getAttribute("id");r&&(t.id=r);let o=e.className;typeof o=="string"&&o.trim()&&(t.className=o);let i=me(e);i&&(t.textSnippet=i);let l=ge(e)??be(e);l&&(t.componentName=l);let s=we(e);return s&&(t.testId=s),t}var O=null;async function X(){return O||(O=import('html-to-image')),O}async function Se(e){return await new Promise((n,t)=>{let r=new Image;r.onload=()=>n({width:r.naturalWidth,height:r.naturalHeight}),r.onerror=()=>t(new Error("Failed to load generated screenshot")),r.src=e;})}async function J(e,n){let{width:t,height:r}=await Se(e);return {dataUrl:e,mime:n,width:t,height:r}}function T(e){if(e?.aborted)throw new Error("Aborted")}function G(){return {async captureElement(e,n){if(!b())throw new Error("captureElement can only run in the browser");T(n.signal);let t=await X();T(n.signal);let r=n.mime==="image/jpeg"?await t.toJpeg(e,{quality:n.quality??.92,pixelRatio:n.pixelRatio}):await t.toPng(e,{pixelRatio:n.pixelRatio});return T(n.signal),await J(r,n.mime)},async captureFullPage(e){if(!b())throw new Error("captureFullPage can only run in the browser");T(e.signal);let n=document.documentElement,t=Math.max(n.scrollWidth,n.clientWidth),r=Math.max(n.scrollHeight,n.clientHeight),o=Math.min(1,e.maxDimension/Math.max(t,r)),i=Math.max(1,Math.round(t*o)),l=Math.max(1,Math.round(r*o)),s=await X();T(e.signal);let u=e.mime==="image/jpeg"?await s.toJpeg(n,{width:i,height:l,quality:e.quality??.92,pixelRatio:e.pixelRatio}):await s.toPng(n,{width:i,height:l,pixelRatio:e.pixelRatio});return T(e.signal),await J(u,e.mime)}}}function ke(e){if(e instanceof Error)return e.message;if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return "Unknown error"}}function m(e,n,t){let r={kind:e,message:ke(n)};return t&&(r.detail=t),r}var Fe=12e3,xe=2048,Pe=.92;function Z(){return Date.now()}function Te(e){return new Promise((n,t)=>{let r=()=>t(new Error("Aborted"));if(e.aborted){r();return}e.addEventListener("abort",r,{once:true});})}async function V(e,n,t){let r=new Promise((i,l)=>{let s=setTimeout(()=>l(new Error("Timeout")),n);typeof s.unref=="function"&&s.unref();}),o=[e,r];return t&&o.push(Te(t)),await Promise.race(o)}function Ae(e){if(!b())return 1;let n=window.devicePixelRatio||1,t=e?.pixelRatio??Math.min(n,2);return Math.max(.1,t)}function Ce(e){return !!(e?.element||e?.fullPage)}function ee(e){let n={mime:e.mime,pixelRatio:e.pixelRatio,maxDimension:e.maxDimension};return e.includeQuality&&(n.quality=e.quality),e.signal&&(n.signal=e.signal),n}async function te(e){let{selectionElement:n,capture:t,signal:r}=e;if(!b()||!Ce(t))return;let o=Z(),i=[],l=t?.timeoutMs??Fe,s=t?.maxDimension??xe,u=t?.mime??"image/png",d=t?.quality??Pe,v=t?.adapter??G(),y={},p=Ae(t);if(t?.element&&n)try{let f=n.getBoundingClientRect(),g=Math.min(1,s/Math.max(f.width,f.height)),c=Math.min(p,p*g),E=await V(Promise.resolve(v.captureElement(n,{...ee({mime:u,quality:d,pixelRatio:c,maxDimension:s,includeQuality:u==="image/jpeg",...r?{signal:r}:{}})})),l,r);y.element=E;}catch(f){if(r?.aborted)throw f;i.push(m("capture_failed",f,{target:"element"}));}if(t?.fullPage)try{let f=await V(Promise.resolve(v.captureFullPage(ee({mime:u,quality:d,pixelRatio:p,maxDimension:s,includeQuality:u==="image/jpeg",...r?{signal:r}:{}}))),l,r);y.fullPage=f;}catch(f){if(r?.aborted)throw f;i.push(m("capture_failed",f,{target:"fullPage"}));}let S=Z(),a={startedAt:o,finishedAt:S,durationMs:Math.max(0,S-o)};return i.length>0&&(a.errors=i),{...y,diagnostics:a}}function Re(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{return}}function Me(){return b()?{url:window.location.href,title:document.title,referrer:document.referrer||void 0,userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height},scroll:{x:window.scrollX,y:window.scrollY},devicePixelRatio:window.devicePixelRatio||1,timezone:Re()}:{}}async function ne(e){let{config:n,context:t}=e;if(n?.enabled===false)return {};let r=Me(),o=n?.enrich;if(!o)return r;try{let i=await o(t);return {...r,...i}}catch(i){let l=m("unknown",i);return {...r,blocfeedMetadataError:l.message}}}function U(e){let n=null,t=null,r=(...o)=>{t=o,n===null&&(n=requestAnimationFrame(()=>{if(n=null,!t)return;let i=t;t=null,e(...i);}));};return r.cancel=()=>{n!==null&&cancelAnimationFrame(n),n=null,t=null;},r}function M(e){return e instanceof Element?!!e.closest("[data-blocfeed-ui]"):false}function B(e){e.stopPropagation(),e.stopImmediatePropagation?.();}function re(e,n){if(!b())throw new Error("BlocFeed picker can only run in a browser environment.");let t=e.ignoreSelectors,r=e.isSelectable,o={};t&&t.length>0&&(o.ignoreSelectors=t),r&&(o.isSelectable=r);let i=null,l=null,s=(a,f=false)=>{if(!a){i=null,l=null,n.onHover(null);return}let g=H(a.getBoundingClientRect()),c=`${Math.round(g.x)}:${Math.round(g.y)}:${Math.round(g.width)}:${Math.round(g.height)}`;!f&&a===i&&c===l||(i=a,l=c,n.onHover({element:a,rect:g}));},u=U(a=>{if(M(a.target))return;let f=document.elementFromPoint(a.clientX,a.clientY),g=N(f,o);s(g);}),d=U(()=>{i&&s(i,true);}),v=a=>{M(a.target)||(B(a),a.pointerType==="mouse"&&a.preventDefault());},y=a=>{M(a.target)||(B(a),a.pointerType==="mouse"&&a.preventDefault());},p=a=>{if(M(a.target))return;B(a),a.preventDefault();let f=document.elementFromPoint(a.clientX,a.clientY),g=N(f,o);g&&n.onSelect({element:g,descriptor:Q(g)});},S=a=>{a.key==="Escape"&&(B(a),a.preventDefault(),n.onCancel());};return window.addEventListener("pointermove",u,{capture:true,passive:true}),window.addEventListener("pointerdown",v,{capture:true}),window.addEventListener("pointerup",y,{capture:true}),window.addEventListener("click",p,{capture:true}),window.addEventListener("keydown",S,{capture:true}),window.addEventListener("scroll",d,{capture:true,passive:true}),window.addEventListener("resize",d,{passive:true}),{stop(){window.removeEventListener("pointermove",u,{capture:true}),window.removeEventListener("pointerdown",v,{capture:true}),window.removeEventListener("pointerup",y,{capture:true}),window.removeEventListener("click",p,{capture:true}),window.removeEventListener("keydown",S,{capture:true}),window.removeEventListener("scroll",d,{capture:true}),window.removeEventListener("resize",d),u.cancel(),d.cancel(),n.onHover(null);}}}var Be=12e3,$=2,oe=500,_e="https://www.blocfeed.com/api/feedback";function ie(e,n){return new Promise((t,r)=>{if(n?.aborted){r(new Error("Aborted"));return}let o=setTimeout(t,e),i=()=>{clearTimeout(o),r(new Error("Aborted"));};n?.addEventListener("abort",i,{once:true});})}function Le(e){return e>=500&&e<=599}async function ae(e){let{payload:n,signal:t}=e;for(let r=1;r<=$;r+=1){let o=new AbortController,i=setTimeout(()=>o.abort(),Be),l=()=>o.abort();t&&t.addEventListener("abort",l,{once:true});try{let s=await fetch(_e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n),signal:o.signal});if(s.ok)return {ok:!0,status:s.status};if(r<$&&Le(s.status)){let u=.85+Math.random()*.3,d=Math.round(oe*2**(r-1)*u);await ie(d,t);continue}return {ok:!1,status:s.status,error:m("api_failed",new Error(`HTTP ${s.status}`))}}catch(s){if(o.signal.aborted||t?.aborted)return {ok:false,error:m("aborted",s)};if(r<$){let u=.85+Math.random()*.3,d=Math.round(oe*2**(r-1)*u);await ie(d,t);continue}return {ok:false,error:m("api_failed",s)}}finally{clearTimeout(i),t&&t.removeEventListener("abort",l);}}return {ok:false,error:m("api_failed",new Error("Failed"))}}async function se(e){let{signal:n}=e,t={ok:false};try{let r=n?{payload:e.payload,signal:n}:{payload:e.payload};t.api=await ae(r),t.ok=!!t.api?.ok;}catch(r){t.api={ok:false,error:m("api_failed",r)},t.ok=false;}return {payload:e.payload,result:t}}var Ie=["[data-blocfeed-ui]","[data-blocfeed-ignore]"];function De(e){let n=[...Ie,...e?.ignoreSelectors??[]],t=Array.from(new Set(n));return {...e,ignoreSelectors:t}}function le(){return {phase:"idle"}}function ut(e){let n=e,t=le(),r=new Set,o=new Set,i=null,l=null,s=null,u=null,d=0,v=()=>{for(let c of r)c(t);},y=c=>{for(let E of o)E(c);},p=c=>{t=c,v();},S=()=>{d+=1,u?.abort(),u=null;},a=()=>{i?.stop(),i=null,y(null),s!==null&&b()&&(document.documentElement.style.cursor=s,s=null);},f=()=>{S(),a(),l=null,p(le());},g=()=>{if(!b())return;a(),l=null;let c=De(n.picker);s=document.documentElement.style.cursor,document.documentElement.style.cursor="crosshair",p({phase:"picking"}),i=re(c,{onHover:y,onSelect:({element:E,descriptor:R})=>{l=E,a(),p({phase:"review",selection:R});},onCancel:()=>{f();}});};return {getState:()=>t,subscribe(c){return r.add(c),()=>r.delete(c)},subscribeHover(c){return o.add(c),()=>o.delete(c)},start(){t.phase==="capturing"||t.phase==="submitting"||t.phase!=="picking"&&g();},stop(){f();},clearSelection(){t.phase==="capturing"||t.phase==="submitting"||g();},setConfig(c){n=c;},async submit(c,E){if(!b()){let w=m("configuration",new Error("BlocFeed submit can only run in the browser"));return p({phase:"error",lastError:w}),{ok:false}}let R=n.blocfeed_id?.trim?.()??"";if(!R){let k={phase:"error",lastError:m("configuration",new Error("Missing blocfeed_id. Create a project in BlocFeed and pass its blocfeed_id."))};return t.selection&&(k.selection=t.selection),p(k),{ok:false}}if(t.phase==="capturing"||t.phase==="submitting")return {ok:false};let A=d+1;d=A,u?.abort(),u=new AbortController;let x=u.signal,h=t.selection,_=E?.capture?{...n.capture,...E.capture}:n.capture,q=!!(_?.element||_?.fullPage),j={phase:q?"capturing":"submitting"};h&&(j.selection=h),p(j);try{let w=q?await te({selectionElement:l,capture:_,signal:x}):void 0;if(x.aborted||d!==A)return {ok:!1};let k={phase:"submitting"};h&&(k.selection=h),w&&(k.capture=w),p(k);let P={};h&&(P.selection=h),w&&(P.capture=w);let ce=await ne({config:n.metadata,context:P}),L={version:1,createdAt:new Date().toISOString(),blocfeed_id:R,message:c,metadata:ce};h&&(L.selection=h),w&&(L.screenshots=w);let{result:F}=await se({payload:L,signal:x});if(x.aborted||d!==A)return F;if(F.ok){let D={phase:"success",lastSubmit:F};return h&&(D.selection=h),w&&(D.capture=w),p(D),F}let ue=F.api?.error??m("unknown",new Error("Submission failed")),I={phase:"error",lastSubmit:F,lastError:ue};return h&&(I.selection=h),w&&(I.capture=w),p(I),F}catch(w){if(x.aborted||d!==A)return {ok:false};let P={phase:"error",lastError:x.aborted?m("aborted",w):m("unknown",w)};return h&&(P.selection=h),p(P),{ok:false}}finally{d===A&&(u=null);}},__unsafeGetSelectedElement(){return l},destroy(){f(),r.clear(),o.clear();}}}
2
+ export{b as a,H as b,G as c,te as d,ne as e,ut as f};
@@ -0,0 +1,2 @@
1
+ 'use strict';function b(){return typeof window<"u"&&typeof document<"u"}function W(e){let n=globalThis.CSS;return typeof n?.escape=="function"?n.escape(e):e.replace(/[^a-zA-Z0-9_-]/g,t=>{let r=t.codePointAt(0);return r===void 0?"":`\\${r.toString(16)} `})}function H(e){return {x:e.x,y:e.y,width:e.width,height:e.height}}function de(e){return {x:e.x+window.scrollX,y:e.y+window.scrollY,width:e.width,height:e.height}}function fe(e){return e.replace(/\s+/g," ").trim()}function me(e,n=140){let t=e.textContent;if(!t)return;let r=fe(t);if(r)return r.length<=n?r:`${r.slice(0,n-1)}\u2026`}function pe(e){let n=1;for(let t=e.previousElementSibling;t;t=t.previousElementSibling)t.tagName===e.tagName&&(n+=1);return n}var K=["data-testid","data-test-id","data-test","data-qa","data-cy"],z="data-blocfeed-component";function ge(e){let n=e.closest(`[${z}]`);if(!n)return;let r=n.getAttribute(z)?.trim();return r||void 0}function we(e){for(let n of K){let t=e.closest(`[${n}]`);if(!t)continue;let o=t.getAttribute(n)?.trim();if(o)return o}}function he(e){try{let n=e,t=Object.getOwnPropertyNames(n);for(let r of t)if(r.startsWith("__reactFiber$")||r.startsWith("__reactInternalInstance$")){let o=n[r];if(o&&typeof o=="object")return o}}catch{}return null}function C(e){if(e&&typeof e!="string"){if(typeof e=="function"){let n=e;return typeof n.displayName=="string"&&n.displayName?n.displayName:typeof n.name=="string"&&n.name?n.name:void 0}if(typeof e=="object"){let n=e,t=n.displayName;if(typeof t=="string"&&t)return t;let r=n.render;if(typeof r=="function"){let i=r;if(typeof i.displayName=="string"&&i.displayName)return i.displayName;if(typeof i.name=="string"&&i.name)return i.name}let o=n.type;return C(o)}}}function be(e){let n=he(e);if(!n)return;let t=n._debugOwner;for(let o=0;t&&o<50;o+=1){let i=C(t.type)??C(t.elementType);if(i)return i;t=t._debugOwner;}let r=n;for(let o=0;r&&o<80;o+=1){let i=C(r.type)??C(r.elementType);if(i)return i;r=r.return;}}function ye(e){let n=e.tagName.toLowerCase(),t=e.getAttribute("id");if(t)return `#${W(t)}`;for(let r of K){let o=e.getAttribute(r);if(o)return `${n}[${r}="${W(o)}"]`}return `${n}:nth-of-type(${pe(e)})`}function Ee(e,n=10){let t=[],r=e;for(;r&&t.length<n;){let o=ye(r);if(t.unshift(o),o.startsWith("#"))break;r=r.parentElement;}return t.join(" > ")}function Y(e,n){if(!n||n.length===0)return false;for(let t of n)if(e.closest(t))return true;return false}function N(e,n){if(!e||Y(e,n.ignoreSelectors))return null;let t=e;for(;t;){if(Y(t,n.ignoreSelectors))return null;if(n.isSelectable?.(t)??ve(t))return t;t=t.parentElement;}return null}function ve(e){let n=e.tagName;return !(n==="HTML"||n==="BODY")}function Q(e){let n=e.getBoundingClientRect(),t={selector:Ee(e),tagName:e.tagName.toLowerCase(),rect:H(n),pageRect:de(n)},r=e.getAttribute("id");r&&(t.id=r);let o=e.className;typeof o=="string"&&o.trim()&&(t.className=o);let i=me(e);i&&(t.textSnippet=i);let l=ge(e)??be(e);l&&(t.componentName=l);let s=we(e);return s&&(t.testId=s),t}var O=null;async function X(){return O||(O=import('html-to-image')),O}async function Se(e){return await new Promise((n,t)=>{let r=new Image;r.onload=()=>n({width:r.naturalWidth,height:r.naturalHeight}),r.onerror=()=>t(new Error("Failed to load generated screenshot")),r.src=e;})}async function J(e,n){let{width:t,height:r}=await Se(e);return {dataUrl:e,mime:n,width:t,height:r}}function T(e){if(e?.aborted)throw new Error("Aborted")}function G(){return {async captureElement(e,n){if(!b())throw new Error("captureElement can only run in the browser");T(n.signal);let t=await X();T(n.signal);let r=n.mime==="image/jpeg"?await t.toJpeg(e,{quality:n.quality??.92,pixelRatio:n.pixelRatio}):await t.toPng(e,{pixelRatio:n.pixelRatio});return T(n.signal),await J(r,n.mime)},async captureFullPage(e){if(!b())throw new Error("captureFullPage can only run in the browser");T(e.signal);let n=document.documentElement,t=Math.max(n.scrollWidth,n.clientWidth),r=Math.max(n.scrollHeight,n.clientHeight),o=Math.min(1,e.maxDimension/Math.max(t,r)),i=Math.max(1,Math.round(t*o)),l=Math.max(1,Math.round(r*o)),s=await X();T(e.signal);let u=e.mime==="image/jpeg"?await s.toJpeg(n,{width:i,height:l,quality:e.quality??.92,pixelRatio:e.pixelRatio}):await s.toPng(n,{width:i,height:l,pixelRatio:e.pixelRatio});return T(e.signal),await J(u,e.mime)}}}function ke(e){if(e instanceof Error)return e.message;if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return "Unknown error"}}function m(e,n,t){let r={kind:e,message:ke(n)};return t&&(r.detail=t),r}var Fe=12e3,xe=2048,Pe=.92;function Z(){return Date.now()}function Te(e){return new Promise((n,t)=>{let r=()=>t(new Error("Aborted"));if(e.aborted){r();return}e.addEventListener("abort",r,{once:true});})}async function V(e,n,t){let r=new Promise((i,l)=>{let s=setTimeout(()=>l(new Error("Timeout")),n);typeof s.unref=="function"&&s.unref();}),o=[e,r];return t&&o.push(Te(t)),await Promise.race(o)}function Ae(e){if(!b())return 1;let n=window.devicePixelRatio||1,t=e?.pixelRatio??Math.min(n,2);return Math.max(.1,t)}function Ce(e){return !!(e?.element||e?.fullPage)}function ee(e){let n={mime:e.mime,pixelRatio:e.pixelRatio,maxDimension:e.maxDimension};return e.includeQuality&&(n.quality=e.quality),e.signal&&(n.signal=e.signal),n}async function te(e){let{selectionElement:n,capture:t,signal:r}=e;if(!b()||!Ce(t))return;let o=Z(),i=[],l=t?.timeoutMs??Fe,s=t?.maxDimension??xe,u=t?.mime??"image/png",d=t?.quality??Pe,v=t?.adapter??G(),y={},p=Ae(t);if(t?.element&&n)try{let f=n.getBoundingClientRect(),g=Math.min(1,s/Math.max(f.width,f.height)),c=Math.min(p,p*g),E=await V(Promise.resolve(v.captureElement(n,{...ee({mime:u,quality:d,pixelRatio:c,maxDimension:s,includeQuality:u==="image/jpeg",...r?{signal:r}:{}})})),l,r);y.element=E;}catch(f){if(r?.aborted)throw f;i.push(m("capture_failed",f,{target:"element"}));}if(t?.fullPage)try{let f=await V(Promise.resolve(v.captureFullPage(ee({mime:u,quality:d,pixelRatio:p,maxDimension:s,includeQuality:u==="image/jpeg",...r?{signal:r}:{}}))),l,r);y.fullPage=f;}catch(f){if(r?.aborted)throw f;i.push(m("capture_failed",f,{target:"fullPage"}));}let S=Z(),a={startedAt:o,finishedAt:S,durationMs:Math.max(0,S-o)};return i.length>0&&(a.errors=i),{...y,diagnostics:a}}function Re(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{return}}function Me(){return b()?{url:window.location.href,title:document.title,referrer:document.referrer||void 0,userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height},scroll:{x:window.scrollX,y:window.scrollY},devicePixelRatio:window.devicePixelRatio||1,timezone:Re()}:{}}async function ne(e){let{config:n,context:t}=e;if(n?.enabled===false)return {};let r=Me(),o=n?.enrich;if(!o)return r;try{let i=await o(t);return {...r,...i}}catch(i){let l=m("unknown",i);return {...r,blocfeedMetadataError:l.message}}}function U(e){let n=null,t=null,r=(...o)=>{t=o,n===null&&(n=requestAnimationFrame(()=>{if(n=null,!t)return;let i=t;t=null,e(...i);}));};return r.cancel=()=>{n!==null&&cancelAnimationFrame(n),n=null,t=null;},r}function M(e){return e instanceof Element?!!e.closest("[data-blocfeed-ui]"):false}function B(e){e.stopPropagation(),e.stopImmediatePropagation?.();}function re(e,n){if(!b())throw new Error("BlocFeed picker can only run in a browser environment.");let t=e.ignoreSelectors,r=e.isSelectable,o={};t&&t.length>0&&(o.ignoreSelectors=t),r&&(o.isSelectable=r);let i=null,l=null,s=(a,f=false)=>{if(!a){i=null,l=null,n.onHover(null);return}let g=H(a.getBoundingClientRect()),c=`${Math.round(g.x)}:${Math.round(g.y)}:${Math.round(g.width)}:${Math.round(g.height)}`;!f&&a===i&&c===l||(i=a,l=c,n.onHover({element:a,rect:g}));},u=U(a=>{if(M(a.target))return;let f=document.elementFromPoint(a.clientX,a.clientY),g=N(f,o);s(g);}),d=U(()=>{i&&s(i,true);}),v=a=>{M(a.target)||(B(a),a.pointerType==="mouse"&&a.preventDefault());},y=a=>{M(a.target)||(B(a),a.pointerType==="mouse"&&a.preventDefault());},p=a=>{if(M(a.target))return;B(a),a.preventDefault();let f=document.elementFromPoint(a.clientX,a.clientY),g=N(f,o);g&&n.onSelect({element:g,descriptor:Q(g)});},S=a=>{a.key==="Escape"&&(B(a),a.preventDefault(),n.onCancel());};return window.addEventListener("pointermove",u,{capture:true,passive:true}),window.addEventListener("pointerdown",v,{capture:true}),window.addEventListener("pointerup",y,{capture:true}),window.addEventListener("click",p,{capture:true}),window.addEventListener("keydown",S,{capture:true}),window.addEventListener("scroll",d,{capture:true,passive:true}),window.addEventListener("resize",d,{passive:true}),{stop(){window.removeEventListener("pointermove",u,{capture:true}),window.removeEventListener("pointerdown",v,{capture:true}),window.removeEventListener("pointerup",y,{capture:true}),window.removeEventListener("click",p,{capture:true}),window.removeEventListener("keydown",S,{capture:true}),window.removeEventListener("scroll",d,{capture:true}),window.removeEventListener("resize",d),u.cancel(),d.cancel(),n.onHover(null);}}}var Be=12e3,$=2,oe=500,_e="https://www.blocfeed.com/api/feedback";function ie(e,n){return new Promise((t,r)=>{if(n?.aborted){r(new Error("Aborted"));return}let o=setTimeout(t,e),i=()=>{clearTimeout(o),r(new Error("Aborted"));};n?.addEventListener("abort",i,{once:true});})}function Le(e){return e>=500&&e<=599}async function ae(e){let{payload:n,signal:t}=e;for(let r=1;r<=$;r+=1){let o=new AbortController,i=setTimeout(()=>o.abort(),Be),l=()=>o.abort();t&&t.addEventListener("abort",l,{once:true});try{let s=await fetch(_e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n),signal:o.signal});if(s.ok)return {ok:!0,status:s.status};if(r<$&&Le(s.status)){let u=.85+Math.random()*.3,d=Math.round(oe*2**(r-1)*u);await ie(d,t);continue}return {ok:!1,status:s.status,error:m("api_failed",new Error(`HTTP ${s.status}`))}}catch(s){if(o.signal.aborted||t?.aborted)return {ok:false,error:m("aborted",s)};if(r<$){let u=.85+Math.random()*.3,d=Math.round(oe*2**(r-1)*u);await ie(d,t);continue}return {ok:false,error:m("api_failed",s)}}finally{clearTimeout(i),t&&t.removeEventListener("abort",l);}}return {ok:false,error:m("api_failed",new Error("Failed"))}}async function se(e){let{signal:n}=e,t={ok:false};try{let r=n?{payload:e.payload,signal:n}:{payload:e.payload};t.api=await ae(r),t.ok=!!t.api?.ok;}catch(r){t.api={ok:false,error:m("api_failed",r)},t.ok=false;}return {payload:e.payload,result:t}}var Ie=["[data-blocfeed-ui]","[data-blocfeed-ignore]"];function De(e){let n=[...Ie,...e?.ignoreSelectors??[]],t=Array.from(new Set(n));return {...e,ignoreSelectors:t}}function le(){return {phase:"idle"}}function ut(e){let n=e,t=le(),r=new Set,o=new Set,i=null,l=null,s=null,u=null,d=0,v=()=>{for(let c of r)c(t);},y=c=>{for(let E of o)E(c);},p=c=>{t=c,v();},S=()=>{d+=1,u?.abort(),u=null;},a=()=>{i?.stop(),i=null,y(null),s!==null&&b()&&(document.documentElement.style.cursor=s,s=null);},f=()=>{S(),a(),l=null,p(le());},g=()=>{if(!b())return;a(),l=null;let c=De(n.picker);s=document.documentElement.style.cursor,document.documentElement.style.cursor="crosshair",p({phase:"picking"}),i=re(c,{onHover:y,onSelect:({element:E,descriptor:R})=>{l=E,a(),p({phase:"review",selection:R});},onCancel:()=>{f();}});};return {getState:()=>t,subscribe(c){return r.add(c),()=>r.delete(c)},subscribeHover(c){return o.add(c),()=>o.delete(c)},start(){t.phase==="capturing"||t.phase==="submitting"||t.phase!=="picking"&&g();},stop(){f();},clearSelection(){t.phase==="capturing"||t.phase==="submitting"||g();},setConfig(c){n=c;},async submit(c,E){if(!b()){let w=m("configuration",new Error("BlocFeed submit can only run in the browser"));return p({phase:"error",lastError:w}),{ok:false}}let R=n.blocfeed_id?.trim?.()??"";if(!R){let k={phase:"error",lastError:m("configuration",new Error("Missing blocfeed_id. Create a project in BlocFeed and pass its blocfeed_id."))};return t.selection&&(k.selection=t.selection),p(k),{ok:false}}if(t.phase==="capturing"||t.phase==="submitting")return {ok:false};let A=d+1;d=A,u?.abort(),u=new AbortController;let x=u.signal,h=t.selection,_=E?.capture?{...n.capture,...E.capture}:n.capture,q=!!(_?.element||_?.fullPage),j={phase:q?"capturing":"submitting"};h&&(j.selection=h),p(j);try{let w=q?await te({selectionElement:l,capture:_,signal:x}):void 0;if(x.aborted||d!==A)return {ok:!1};let k={phase:"submitting"};h&&(k.selection=h),w&&(k.capture=w),p(k);let P={};h&&(P.selection=h),w&&(P.capture=w);let ce=await ne({config:n.metadata,context:P}),L={version:1,createdAt:new Date().toISOString(),blocfeed_id:R,message:c,metadata:ce};h&&(L.selection=h),w&&(L.screenshots=w);let{result:F}=await se({payload:L,signal:x});if(x.aborted||d!==A)return F;if(F.ok){let D={phase:"success",lastSubmit:F};return h&&(D.selection=h),w&&(D.capture=w),p(D),F}let ue=F.api?.error??m("unknown",new Error("Submission failed")),I={phase:"error",lastSubmit:F,lastError:ue};return h&&(I.selection=h),w&&(I.capture=w),p(I),F}catch(w){if(x.aborted||d!==A)return {ok:false};let P={phase:"error",lastError:x.aborted?m("aborted",w):m("unknown",w)};return h&&(P.selection=h),p(P),{ok:false}}finally{d===A&&(u=null);}},__unsafeGetSelectedElement(){return l},destroy(){f(),r.clear(),o.clear();}}}
2
+ exports.a=b;exports.b=H;exports.c=G;exports.d=te;exports.e=ne;exports.f=ut;
@@ -49,7 +49,7 @@ interface CaptureResult {
49
49
  diagnostics: CaptureDiagnostics;
50
50
  }
51
51
  interface BlocFeedError {
52
- kind: "unknown" | "configuration" | "capture_failed" | "webhook_failed" | "callback_failed" | "aborted";
52
+ kind: "unknown" | "configuration" | "capture_failed" | "api_failed" | "aborted";
53
53
  message: string;
54
54
  detail?: Record<string, unknown>;
55
55
  }
@@ -110,52 +110,17 @@ interface MetadataConfig {
110
110
  */
111
111
  enrich?: (context: MetadataContext) => MaybePromise<Record<string, unknown>>;
112
112
  }
113
- interface WebhookConfig {
114
- url: string;
115
- headers?: Record<string, string> | (() => MaybePromise<Record<string, string>>);
116
- timeoutMs?: number;
117
- /**
118
- * Optional: set fetch credentials mode for the request.
119
- */
120
- credentials?: RequestCredentials;
121
- /**
122
- * Basic retry behavior for transient failures (network errors, 5xx).
123
- */
124
- retry?: {
125
- /**
126
- * Total attempts including the initial request. Default: 2.
127
- */
128
- attempts?: number;
129
- /**
130
- * Base delay used for exponential backoff. Default: 500ms.
131
- */
132
- backoffMs?: number;
133
- };
134
- }
135
- interface SubmitConfig {
136
- /**
137
- * Local delivery mode. If provided, called with the final payload.
138
- */
139
- onSubmit?: (payload: FeedbackPayload) => MaybePromise<void>;
140
- /**
141
- * Remote delivery mode. If provided, BlocFeed will POST the payload to the webhook.
142
- */
143
- webhook?: WebhookConfig;
144
- /**
145
- * If both `onSubmit` and `webhook` are present, require both to succeed.
146
- * Default: false (success if at least one succeeds).
147
- */
148
- requireAll?: boolean;
113
+ interface BlocFeedConfig {
149
114
  /**
150
- * Last chance to transform/redact the payload before delivery.
115
+ * Unique identifier for the project in BlocFeed.
116
+ *
117
+ * This value is issued by the BlocFeed platform when you create a project.
118
+ * It is required for all feedback submissions.
151
119
  */
152
- beforeSubmit?: (payload: FeedbackPayload) => MaybePromise<FeedbackPayload>;
153
- }
154
- interface BlocFeedConfig {
120
+ blocfeed_id: string;
155
121
  capture?: CaptureConfig;
156
122
  picker?: PickerConfig;
157
123
  metadata?: MetadataConfig;
158
- submit?: SubmitConfig;
159
124
  ui?: {
160
125
  /**
161
126
  * z-index for the widget overlay/panel.
@@ -166,6 +131,7 @@ interface BlocFeedConfig {
166
131
  interface FeedbackPayload {
167
132
  version: 1;
168
133
  createdAt: string;
134
+ blocfeed_id: string;
169
135
  message: string;
170
136
  selection?: ElementDescriptor;
171
137
  screenshots?: CaptureResult;
@@ -178,8 +144,7 @@ interface TransportResult {
178
144
  }
179
145
  interface SubmitResult {
180
146
  ok: boolean;
181
- callback?: TransportResult;
182
- webhook?: TransportResult;
147
+ api?: TransportResult;
183
148
  }
184
149
  type SessionPhase = "idle" | "picking" | "review" | "capturing" | "submitting" | "success" | "error";
185
150
  interface BlocFeedState {
@@ -214,4 +179,4 @@ interface BlocFeedController {
214
179
  }
215
180
  declare function createBlocFeedController(config: BlocFeedConfig): BlocFeedController;
216
181
 
217
- export { type BlocFeedConfig as B, type CaptureConfig as C, type ElementDescriptor as E, type FeedbackPayload as F, type HoverListener as H, type ImageAsset as I, type MaybePromise as M, type PickerConfig as P, type Rect as R, type SubmitResult as S, type TransportResult as T, type WebhookConfig as W, type BlocFeedState as a, type BlocFeedController as b, type BlocFeedError as c, type CaptureDiagnostics as d, type CaptureResult as e, type MetadataConfig as f, type MetadataContext as g, type ScreenshotAdapter as h, type ScreenshotAdapterOptions as i, type ScreenshotMime as j, type SessionPhase as k, type SubmitConfig as l, type StateListener as m, createBlocFeedController as n };
182
+ export { type BlocFeedConfig as B, type CaptureConfig as C, type ElementDescriptor as E, type FeedbackPayload as F, type HoverListener as H, type ImageAsset as I, type MaybePromise as M, type PickerConfig as P, type Rect as R, type SubmitResult as S, type TransportResult as T, type BlocFeedState as a, type BlocFeedController as b, type BlocFeedError as c, type CaptureDiagnostics as d, type CaptureResult as e, type MetadataConfig as f, type MetadataContext as g, type ScreenshotAdapter as h, type ScreenshotAdapterOptions as i, type ScreenshotMime as j, type SessionPhase as k, type StateListener as l, createBlocFeedController as m };
@@ -49,7 +49,7 @@ interface CaptureResult {
49
49
  diagnostics: CaptureDiagnostics;
50
50
  }
51
51
  interface BlocFeedError {
52
- kind: "unknown" | "configuration" | "capture_failed" | "webhook_failed" | "callback_failed" | "aborted";
52
+ kind: "unknown" | "configuration" | "capture_failed" | "api_failed" | "aborted";
53
53
  message: string;
54
54
  detail?: Record<string, unknown>;
55
55
  }
@@ -110,52 +110,17 @@ interface MetadataConfig {
110
110
  */
111
111
  enrich?: (context: MetadataContext) => MaybePromise<Record<string, unknown>>;
112
112
  }
113
- interface WebhookConfig {
114
- url: string;
115
- headers?: Record<string, string> | (() => MaybePromise<Record<string, string>>);
116
- timeoutMs?: number;
117
- /**
118
- * Optional: set fetch credentials mode for the request.
119
- */
120
- credentials?: RequestCredentials;
121
- /**
122
- * Basic retry behavior for transient failures (network errors, 5xx).
123
- */
124
- retry?: {
125
- /**
126
- * Total attempts including the initial request. Default: 2.
127
- */
128
- attempts?: number;
129
- /**
130
- * Base delay used for exponential backoff. Default: 500ms.
131
- */
132
- backoffMs?: number;
133
- };
134
- }
135
- interface SubmitConfig {
136
- /**
137
- * Local delivery mode. If provided, called with the final payload.
138
- */
139
- onSubmit?: (payload: FeedbackPayload) => MaybePromise<void>;
140
- /**
141
- * Remote delivery mode. If provided, BlocFeed will POST the payload to the webhook.
142
- */
143
- webhook?: WebhookConfig;
144
- /**
145
- * If both `onSubmit` and `webhook` are present, require both to succeed.
146
- * Default: false (success if at least one succeeds).
147
- */
148
- requireAll?: boolean;
113
+ interface BlocFeedConfig {
149
114
  /**
150
- * Last chance to transform/redact the payload before delivery.
115
+ * Unique identifier for the project in BlocFeed.
116
+ *
117
+ * This value is issued by the BlocFeed platform when you create a project.
118
+ * It is required for all feedback submissions.
151
119
  */
152
- beforeSubmit?: (payload: FeedbackPayload) => MaybePromise<FeedbackPayload>;
153
- }
154
- interface BlocFeedConfig {
120
+ blocfeed_id: string;
155
121
  capture?: CaptureConfig;
156
122
  picker?: PickerConfig;
157
123
  metadata?: MetadataConfig;
158
- submit?: SubmitConfig;
159
124
  ui?: {
160
125
  /**
161
126
  * z-index for the widget overlay/panel.
@@ -166,6 +131,7 @@ interface BlocFeedConfig {
166
131
  interface FeedbackPayload {
167
132
  version: 1;
168
133
  createdAt: string;
134
+ blocfeed_id: string;
169
135
  message: string;
170
136
  selection?: ElementDescriptor;
171
137
  screenshots?: CaptureResult;
@@ -178,8 +144,7 @@ interface TransportResult {
178
144
  }
179
145
  interface SubmitResult {
180
146
  ok: boolean;
181
- callback?: TransportResult;
182
- webhook?: TransportResult;
147
+ api?: TransportResult;
183
148
  }
184
149
  type SessionPhase = "idle" | "picking" | "review" | "capturing" | "submitting" | "success" | "error";
185
150
  interface BlocFeedState {
@@ -214,4 +179,4 @@ interface BlocFeedController {
214
179
  }
215
180
  declare function createBlocFeedController(config: BlocFeedConfig): BlocFeedController;
216
181
 
217
- export { type BlocFeedConfig as B, type CaptureConfig as C, type ElementDescriptor as E, type FeedbackPayload as F, type HoverListener as H, type ImageAsset as I, type MaybePromise as M, type PickerConfig as P, type Rect as R, type SubmitResult as S, type TransportResult as T, type WebhookConfig as W, type BlocFeedState as a, type BlocFeedController as b, type BlocFeedError as c, type CaptureDiagnostics as d, type CaptureResult as e, type MetadataConfig as f, type MetadataContext as g, type ScreenshotAdapter as h, type ScreenshotAdapterOptions as i, type ScreenshotMime as j, type SessionPhase as k, type SubmitConfig as l, type StateListener as m, createBlocFeedController as n };
182
+ export { type BlocFeedConfig as B, type CaptureConfig as C, type ElementDescriptor as E, type FeedbackPayload as F, type HoverListener as H, type ImageAsset as I, type MaybePromise as M, type PickerConfig as P, type Rect as R, type SubmitResult as S, type TransportResult as T, type BlocFeedState as a, type BlocFeedController as b, type BlocFeedError as c, type CaptureDiagnostics as d, type CaptureResult as e, type MetadataConfig as f, type MetadataContext as g, type ScreenshotAdapter as h, type ScreenshotAdapterOptions as i, type ScreenshotMime as j, type SessionPhase as k, type StateListener as l, createBlocFeedController as m };
package/dist/engine.cjs CHANGED
@@ -1 +1 @@
1
- 'use strict';var chunk52FWOTRN_cjs=require('./chunk-52FWOTRN.cjs');function d(n){let[r,o]=n.split(",",2);if(!r||!o)throw new Error("Invalid data URL");let c=/data:(.*?);base64/.exec(r)?.[1]||"application/octet-stream",t=atob(o),a=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)a[e]=t.charCodeAt(e);return new Blob([a],{type:c})}Object.defineProperty(exports,"collectMetadata",{enumerable:true,get:function(){return chunk52FWOTRN_cjs.e}});Object.defineProperty(exports,"createBlocFeedController",{enumerable:true,get:function(){return chunk52FWOTRN_cjs.f}});Object.defineProperty(exports,"createHtmlToImageAdapter",{enumerable:true,get:function(){return chunk52FWOTRN_cjs.c}});Object.defineProperty(exports,"runCapture",{enumerable:true,get:function(){return chunk52FWOTRN_cjs.d}});exports.dataUrlToBlob=d;
1
+ 'use strict';var chunkNMFAZKHE_cjs=require('./chunk-NMFAZKHE.cjs');function d(n){let[r,o]=n.split(",",2);if(!r||!o)throw new Error("Invalid data URL");let c=/data:(.*?);base64/.exec(r)?.[1]||"application/octet-stream",t=atob(o),a=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)a[e]=t.charCodeAt(e);return new Blob([a],{type:c})}Object.defineProperty(exports,"collectMetadata",{enumerable:true,get:function(){return chunkNMFAZKHE_cjs.e}});Object.defineProperty(exports,"createBlocFeedController",{enumerable:true,get:function(){return chunkNMFAZKHE_cjs.f}});Object.defineProperty(exports,"createHtmlToImageAdapter",{enumerable:true,get:function(){return chunkNMFAZKHE_cjs.c}});Object.defineProperty(exports,"runCapture",{enumerable:true,get:function(){return chunkNMFAZKHE_cjs.d}});exports.dataUrlToBlob=d;
package/dist/engine.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { h as ScreenshotAdapter, C as CaptureConfig, e as CaptureResult, f as MetadataConfig, g as MetadataContext } from './controller-5O3OHUFm.cjs';
2
- export { B as BlocFeedConfig, b as BlocFeedController, c as BlocFeedError, a as BlocFeedState, E as ElementDescriptor, F as FeedbackPayload, H as HoverListener, I as ImageAsset, R as Rect, i as ScreenshotAdapterOptions, j as ScreenshotMime, k as SessionPhase, m as StateListener, S as SubmitResult, n as createBlocFeedController } from './controller-5O3OHUFm.cjs';
1
+ import { h as ScreenshotAdapter, C as CaptureConfig, e as CaptureResult, f as MetadataConfig, g as MetadataContext } from './controller-DmWFVHoj.cjs';
2
+ export { B as BlocFeedConfig, b as BlocFeedController, c as BlocFeedError, a as BlocFeedState, E as ElementDescriptor, F as FeedbackPayload, H as HoverListener, I as ImageAsset, R as Rect, i as ScreenshotAdapterOptions, j as ScreenshotMime, k as SessionPhase, l as StateListener, S as SubmitResult, m as createBlocFeedController } from './controller-DmWFVHoj.cjs';
3
3
 
4
4
  declare function createHtmlToImageAdapter(): ScreenshotAdapter;
5
5
 
package/dist/engine.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { h as ScreenshotAdapter, C as CaptureConfig, e as CaptureResult, f as MetadataConfig, g as MetadataContext } from './controller-5O3OHUFm.js';
2
- export { B as BlocFeedConfig, b as BlocFeedController, c as BlocFeedError, a as BlocFeedState, E as ElementDescriptor, F as FeedbackPayload, H as HoverListener, I as ImageAsset, R as Rect, i as ScreenshotAdapterOptions, j as ScreenshotMime, k as SessionPhase, m as StateListener, S as SubmitResult, n as createBlocFeedController } from './controller-5O3OHUFm.js';
1
+ import { h as ScreenshotAdapter, C as CaptureConfig, e as CaptureResult, f as MetadataConfig, g as MetadataContext } from './controller-DmWFVHoj.js';
2
+ export { B as BlocFeedConfig, b as BlocFeedController, c as BlocFeedError, a as BlocFeedState, E as ElementDescriptor, F as FeedbackPayload, H as HoverListener, I as ImageAsset, R as Rect, i as ScreenshotAdapterOptions, j as ScreenshotMime, k as SessionPhase, l as StateListener, S as SubmitResult, m as createBlocFeedController } from './controller-DmWFVHoj.js';
3
3
 
4
4
  declare function createHtmlToImageAdapter(): ScreenshotAdapter;
5
5
 
package/dist/engine.js CHANGED
@@ -1 +1 @@
1
- export{e as collectMetadata,f as createBlocFeedController,c as createHtmlToImageAdapter,d as runCapture}from'./chunk-4EGJPVEG.js';function d(n){let[r,o]=n.split(",",2);if(!r||!o)throw new Error("Invalid data URL");let c=/data:(.*?);base64/.exec(r)?.[1]||"application/octet-stream",t=atob(o),a=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)a[e]=t.charCodeAt(e);return new Blob([a],{type:c})}export{d as dataUrlToBlob};
1
+ export{e as collectMetadata,f as createBlocFeedController,c as createHtmlToImageAdapter,d as runCapture}from'./chunk-H36VLJXX.js';function d(n){let[r,o]=n.split(",",2);if(!r||!o)throw new Error("Invalid data URL");let c=/data:(.*?);base64/.exec(r)?.[1]||"application/octet-stream",t=atob(o),a=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)a[e]=t.charCodeAt(e);return new Blob([a],{type:c})}export{d as dataUrlToBlob};
package/dist/main.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- 'use strict';var chunk52FWOTRN_cjs=require('./chunk-52FWOTRN.cjs'),react=require('react'),jsxRuntime=require('react/jsx-runtime'),reactDom=require('react-dom');var m=react.createContext(null);function w(t){let e=react.useMemo(()=>chunk52FWOTRN_cjs.f(t.config??{}),[]),[a,l]=react.useState(()=>e.getState());return react.useEffect(()=>e.subscribe(l),[e]),react.useEffect(()=>e.setConfig(t.config??{}),[e,t.config]),react.useEffect(()=>()=>e.destroy(),[e]),jsxRuntime.jsx(m.Provider,{value:{controller:e,state:a},children:t.children})}var T="blocfeed-styles-v1",_=`
2
+ 'use strict';var chunkNMFAZKHE_cjs=require('./chunk-NMFAZKHE.cjs'),react=require('react'),jsxRuntime=require('react/jsx-runtime'),reactDom=require('react-dom');var g=react.createContext(null);function w(t){let e=react.useMemo(()=>chunkNMFAZKHE_cjs.f({...t.config??{},blocfeed_id:t.blocfeed_id}),[]),[a,l]=react.useState(()=>e.getState());return react.useEffect(()=>e.subscribe(l),[e]),react.useEffect(()=>e.setConfig({...t.config??{},blocfeed_id:t.blocfeed_id}),[e,t.config,t.blocfeed_id]),react.useEffect(()=>()=>e.destroy(),[e]),jsxRuntime.jsx(g.Provider,{value:{controller:e,state:a},children:t.children})}var H="blocfeed-styles-v1",D=`
3
3
  :where([data-blocfeed-ui-root]),
4
4
  :where([data-blocfeed-ui-root]) * {
5
5
  box-sizing: border-box;
@@ -220,4 +220,4 @@
220
220
  font-size: 13px;
221
221
  color: rgba(243, 244, 246, 0.9);
222
222
  }
223
- `;function A(){if(!chunk52FWOTRN_cjs.a()||document.getElementById(T))return;let t=document.createElement("style");t.id=T,t.textContent=_,document.head.appendChild(t);}function y(){let t=react.useContext(m);if(!t)throw new Error("useBlocFeed must be used within a <BlocFeedProvider />");return {state:t.state,controller:t.controller,start:t.controller.start,stop:t.controller.stop,clearSelection:t.controller.clearSelection,submit:t.controller.submit}}function G(t,e,a){return Math.max(e,Math.min(a,t))}function O(t,e){let l=window.innerWidth,r=window.innerHeight,d=G(t.x,12,Math.max(12,l-e-12)),f=t.y+t.height+12,g=Math.max(12,t.y-240);return {top:f+240<=r?f:g,left:d}}function V(t){let{rect:e}=t,a={left:`${e.x}px`,top:`${e.y}px`,width:`${Math.max(0,e.width)}px`,height:`${Math.max(0,e.height)}px`};return jsxRuntime.jsx("div",{className:"bf-highlight",style:a})}function Y(t){let{state:e,controller:a,start:l,stop:r,clearSelection:d,submit:f}=y(),[g,C]=react.useState(null),[h,F]=react.useState(""),[B,k]=react.useState(t.config.capture?.element??true),[S,P]=react.useState(t.config.capture?.fullPage??false),[I,N]=react.useState(null);react.useEffect(()=>a.subscribeHover(C),[a]),react.useEffect(()=>{let i=a.__unsafeGetSelectedElement();if(!i||e.phase==="idle"||e.phase==="picking"){N(null);return}let z=()=>{N(chunk52FWOTRN_cjs.b(i.getBoundingClientRect()));};z();let u=()=>z();return window.addEventListener("scroll",u,{capture:true,passive:true}),window.addEventListener("resize",u,{passive:true}),()=>{window.removeEventListener("scroll",u,{capture:true}),window.removeEventListener("resize",u);}},[a,e.phase,e.selection?.selector]),react.useEffect(()=>{e.phase==="review"&&(F(""),k(t.config.capture?.element??true),P(t.config.capture?.fullPage??false));},[e.phase,e.selection?.selector,t.config.capture?.element,t.config.capture?.fullPage]),react.useEffect(()=>{if(e.phase!=="success")return;let i=window.setTimeout(()=>r(),1200);return ()=>window.clearTimeout(i)},[e.phase,r]);let c=e.phase==="capturing"||e.phase==="submitting",s=e.phase==="picking"?g?.rect??null:I??e.selection?.rect??null,x=react.useMemo(()=>s?O(s,360):null,[s?.x,s?.y,s?.width,s?.height]),R=e.lastError?.message;return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[e.phase==="idle"&&jsxRuntime.jsxs("button",{className:"bf-trigger",type:"button",onClick:()=>l(),"aria-label":"Give feedback",children:[jsxRuntime.jsx("span",{className:"bf-dot","aria-hidden":"true"}),"Feedback"]}),e.phase!=="idle"&&jsxRuntime.jsxs("div",{className:"bf-overlay",children:[e.phase!=="picking"&&jsxRuntime.jsx("div",{className:"bf-blocker",role:"presentation",onClick:()=>r()}),s&&jsxRuntime.jsx(V,{rect:s}),e.phase==="picking"&&jsxRuntime.jsxs("div",{className:"bf-hint",children:[jsxRuntime.jsxs("p",{children:["Click an element to attach your feedback. Press ",jsxRuntime.jsx("strong",{children:"Esc"})," to cancel."]}),jsxRuntime.jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),children:"Cancel"})]}),(e.phase==="review"||e.phase==="capturing"||e.phase==="submitting"||e.phase==="error"||e.phase==="success")&&x&&jsxRuntime.jsxs("div",{className:"bf-panel",style:{left:x.left,top:x.top},children:[jsxRuntime.jsxs("div",{className:"bf-panelHeader",children:[jsxRuntime.jsx("div",{className:"bf-title",children:"Feedback"}),jsxRuntime.jsxs("div",{className:"bf-row",style:{justifyContent:"flex-end"},children:[jsxRuntime.jsx("button",{type:"button",className:"bf-btn",onClick:()=>d(),disabled:c,children:"Re-pick"}),jsxRuntime.jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),disabled:c,children:"Close"})]})]}),jsxRuntime.jsxs("div",{className:"bf-panelBody",children:[jsxRuntime.jsx("textarea",{className:"bf-textarea",placeholder:"What\u2019s happening? What did you expect?",value:h,onChange:i=>F(i.target.value),disabled:c}),jsxRuntime.jsxs("div",{className:"bf-row",children:[jsxRuntime.jsxs("label",{children:[jsxRuntime.jsx("input",{type:"checkbox",checked:B,onChange:i=>k(i.target.checked),disabled:c}),"Screenshot element"]}),jsxRuntime.jsxs("label",{children:[jsxRuntime.jsx("input",{type:"checkbox",checked:S,onChange:i=>P(i.target.checked),disabled:c}),"Full page"]})]}),e.phase==="capturing"&&jsxRuntime.jsx("div",{className:"bf-status",children:"Capturing screenshots\u2026"}),e.phase==="submitting"&&jsxRuntime.jsx("div",{className:"bf-status",children:"Submitting\u2026"}),e.phase==="success"&&jsxRuntime.jsx("div",{className:"bf-status",children:"Sent. Thank you!"}),e.phase==="error"&&R&&jsxRuntime.jsx("div",{className:"bf-error",children:R}),jsxRuntime.jsxs("div",{className:"bf-actions",children:[jsxRuntime.jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),disabled:c,children:"Cancel"}),jsxRuntime.jsx("button",{type:"button",className:"bf-btn bf-btnPrimary",onClick:()=>f(h,{capture:{element:B,fullPage:S}}),disabled:c||h.trim().length===0,children:"Send"})]})]})]})]}),e.phase==="success"&&jsxRuntime.jsx("div",{className:"bf-toast","aria-live":"polite",children:"Feedback sent"})]})}function q(t){let e=t.config??{},[a,l]=react.useState(null);return react.useEffect(()=>{A();let r=document.createElement("div");r.setAttribute("data-blocfeed-ui-root","true"),r.setAttribute("data-blocfeed-ui","true");let d=e.ui?.zIndex;return typeof d=="number"&&r.style.setProperty("--bf-z",String(d)),document.body.appendChild(r),l(r),()=>{r.remove(),l(null);}},[e.ui?.zIndex]),a?reactDom.createPortal(jsxRuntime.jsx(w,{config:e,children:jsxRuntime.jsx(Y,{config:e})}),a):null}exports.BlocFeedProvider=w;exports.BlocFeedWidget=q;exports.useBlocFeed=y;
223
+ `;function T(){if(!chunkNMFAZKHE_cjs.a()||document.getElementById(H))return;let t=document.createElement("style");t.id=H,t.textContent=D,document.head.appendChild(t);}function y(){let t=react.useContext(g);if(!t)throw new Error("useBlocFeed must be used within a <BlocFeedProvider />");return {state:t.state,controller:t.controller,start:t.controller.start,stop:t.controller.stop,clearSelection:t.controller.clearSelection,submit:t.controller.submit}}function X(t,e,a){return Math.max(e,Math.min(a,t))}function G(t,e){let l=window.innerWidth,r=window.innerHeight,s=X(t.x,12,Math.max(12,l-e-12)),p=t.y+t.height+12,m=Math.max(12,t.y-240);return {top:p+240<=r?p:m,left:s}}function V(t){let{rect:e}=t,a={left:`${e.x}px`,top:`${e.y}px`,width:`${Math.max(0,e.width)}px`,height:`${Math.max(0,e.height)}px`};return jsxRuntime.jsx("div",{className:"bf-highlight",style:a})}function Y(t){let{state:e,controller:a,start:l,stop:r,clearSelection:s,submit:p}=y(),[m,C]=react.useState(null),[h,F]=react.useState(""),[B,k]=react.useState(t.config.capture?.element??true),[S,P]=react.useState(t.config.capture?.fullPage??false),[A,N]=react.useState(null);react.useEffect(()=>a.subscribeHover(C),[a]),react.useEffect(()=>{let n=a.__unsafeGetSelectedElement();if(!n||e.phase==="idle"||e.phase==="picking"){N(null);return}let z=()=>{N(chunkNMFAZKHE_cjs.b(n.getBoundingClientRect()));};z();let u=()=>z();return window.addEventListener("scroll",u,{capture:true,passive:true}),window.addEventListener("resize",u,{passive:true}),()=>{window.removeEventListener("scroll",u,{capture:true}),window.removeEventListener("resize",u);}},[a,e.phase,e.selection?.selector]),react.useEffect(()=>{e.phase==="review"&&(F(""),k(t.config.capture?.element??true),P(t.config.capture?.fullPage??false));},[e.phase,e.selection?.selector,t.config.capture?.element,t.config.capture?.fullPage]),react.useEffect(()=>{if(e.phase!=="success")return;let n=window.setTimeout(()=>r(),1200);return ()=>window.clearTimeout(n)},[e.phase,r]);let d=e.phase==="capturing"||e.phase==="submitting",c=e.phase==="picking"?m?.rect??null:A??e.selection?.rect??null,x=react.useMemo(()=>c?G(c,360):null,[c?.x,c?.y,c?.width,c?.height]),R=e.lastError?.message;return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[e.phase==="idle"&&jsxRuntime.jsxs("button",{className:"bf-trigger",type:"button",onClick:()=>l(),"aria-label":"Give feedback",children:[jsxRuntime.jsx("span",{className:"bf-dot","aria-hidden":"true"}),"Feedback"]}),e.phase!=="idle"&&jsxRuntime.jsxs("div",{className:"bf-overlay",children:[e.phase!=="picking"&&jsxRuntime.jsx("div",{className:"bf-blocker",role:"presentation",onClick:()=>r()}),c&&jsxRuntime.jsx(V,{rect:c}),e.phase==="picking"&&jsxRuntime.jsxs("div",{className:"bf-hint",children:[jsxRuntime.jsxs("p",{children:["Click an element to attach your feedback. Press ",jsxRuntime.jsx("strong",{children:"Esc"})," to cancel."]}),jsxRuntime.jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),children:"Cancel"})]}),(e.phase==="review"||e.phase==="capturing"||e.phase==="submitting"||e.phase==="error"||e.phase==="success")&&x&&jsxRuntime.jsxs("div",{className:"bf-panel",style:{left:x.left,top:x.top},children:[jsxRuntime.jsxs("div",{className:"bf-panelHeader",children:[jsxRuntime.jsx("div",{className:"bf-title",children:"Feedback"}),jsxRuntime.jsxs("div",{className:"bf-row",style:{justifyContent:"flex-end"},children:[jsxRuntime.jsx("button",{type:"button",className:"bf-btn",onClick:()=>s(),disabled:d,children:"Re-pick"}),jsxRuntime.jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),disabled:d,children:"Close"})]})]}),jsxRuntime.jsxs("div",{className:"bf-panelBody",children:[jsxRuntime.jsx("textarea",{className:"bf-textarea",placeholder:"What\u2019s happening? What did you expect?",value:h,onChange:n=>F(n.target.value),disabled:d}),jsxRuntime.jsxs("div",{className:"bf-row",children:[jsxRuntime.jsxs("label",{children:[jsxRuntime.jsx("input",{type:"checkbox",checked:B,onChange:n=>k(n.target.checked),disabled:d}),"Screenshot element"]}),jsxRuntime.jsxs("label",{children:[jsxRuntime.jsx("input",{type:"checkbox",checked:S,onChange:n=>P(n.target.checked),disabled:d}),"Full page"]})]}),e.phase==="capturing"&&jsxRuntime.jsx("div",{className:"bf-status",children:"Capturing screenshots\u2026"}),e.phase==="submitting"&&jsxRuntime.jsx("div",{className:"bf-status",children:"Submitting\u2026"}),e.phase==="success"&&jsxRuntime.jsx("div",{className:"bf-status",children:"Sent. Thank you!"}),e.phase==="error"&&R&&jsxRuntime.jsx("div",{className:"bf-error",children:R}),jsxRuntime.jsxs("div",{className:"bf-actions",children:[jsxRuntime.jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),disabled:d,children:"Cancel"}),jsxRuntime.jsx("button",{type:"button",className:"bf-btn bf-btnPrimary",onClick:()=>p(h,{capture:{element:B,fullPage:S}}),disabled:d||h.trim().length===0,children:"Send"})]})]})]})]}),e.phase==="success"&&jsxRuntime.jsx("div",{className:"bf-toast","aria-live":"polite",children:"Feedback sent"})]})}function q(t){let e={...t.config??{},blocfeed_id:t.blocfeed_id},[a,l]=react.useState(null);return react.useEffect(()=>{T();let r=document.createElement("div");r.setAttribute("data-blocfeed-ui-root","true"),r.setAttribute("data-blocfeed-ui","true");let s=e.ui?.zIndex;return typeof s=="number"&&r.style.setProperty("--bf-z",String(s)),document.body.appendChild(r),l(r),()=>{r.remove(),l(null);}},[e.ui?.zIndex]),a?reactDom.createPortal(jsxRuntime.jsx(w,{blocfeed_id:e.blocfeed_id,...t.config?{config:t.config}:{},children:jsxRuntime.jsx(Y,{config:e})}),a):null}exports.BlocFeedProvider=w;exports.BlocFeedWidget=q;exports.useBlocFeed=y;
package/dist/main.d.cts CHANGED
@@ -1,17 +1,19 @@
1
- import { B as BlocFeedConfig, a as BlocFeedState, b as BlocFeedController, C as CaptureConfig, S as SubmitResult } from './controller-5O3OHUFm.cjs';
2
- export { c as BlocFeedError, d as CaptureDiagnostics, e as CaptureResult, E as ElementDescriptor, F as FeedbackPayload, I as ImageAsset, M as MaybePromise, f as MetadataConfig, g as MetadataContext, P as PickerConfig, R as Rect, h as ScreenshotAdapter, i as ScreenshotAdapterOptions, j as ScreenshotMime, k as SessionPhase, l as SubmitConfig, T as TransportResult, W as WebhookConfig } from './controller-5O3OHUFm.cjs';
1
+ import { B as BlocFeedConfig, a as BlocFeedState, b as BlocFeedController, C as CaptureConfig, S as SubmitResult } from './controller-DmWFVHoj.cjs';
2
+ export { c as BlocFeedError, d as CaptureDiagnostics, e as CaptureResult, E as ElementDescriptor, F as FeedbackPayload, I as ImageAsset, M as MaybePromise, f as MetadataConfig, g as MetadataContext, P as PickerConfig, R as Rect, h as ScreenshotAdapter, i as ScreenshotAdapterOptions, j as ScreenshotMime, k as SessionPhase, T as TransportResult } from './controller-DmWFVHoj.cjs';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import * as react from 'react';
5
5
  import { ReactNode } from 'react';
6
6
 
7
7
  type BlocFeedProviderProps = {
8
- config?: BlocFeedConfig;
8
+ blocfeed_id: string;
9
+ config?: Omit<BlocFeedConfig, "blocfeed_id">;
9
10
  children: ReactNode;
10
11
  };
11
12
  declare function BlocFeedProvider(props: BlocFeedProviderProps): react_jsx_runtime.JSX.Element;
12
13
 
13
14
  type BlocFeedWidgetProps = {
14
- config?: BlocFeedConfig;
15
+ blocfeed_id: string;
16
+ config?: Omit<BlocFeedConfig, "blocfeed_id">;
15
17
  };
16
18
  declare function BlocFeedWidget(props: BlocFeedWidgetProps): react.ReactPortal | null;
17
19
 
package/dist/main.d.ts CHANGED
@@ -1,17 +1,19 @@
1
- import { B as BlocFeedConfig, a as BlocFeedState, b as BlocFeedController, C as CaptureConfig, S as SubmitResult } from './controller-5O3OHUFm.js';
2
- export { c as BlocFeedError, d as CaptureDiagnostics, e as CaptureResult, E as ElementDescriptor, F as FeedbackPayload, I as ImageAsset, M as MaybePromise, f as MetadataConfig, g as MetadataContext, P as PickerConfig, R as Rect, h as ScreenshotAdapter, i as ScreenshotAdapterOptions, j as ScreenshotMime, k as SessionPhase, l as SubmitConfig, T as TransportResult, W as WebhookConfig } from './controller-5O3OHUFm.js';
1
+ import { B as BlocFeedConfig, a as BlocFeedState, b as BlocFeedController, C as CaptureConfig, S as SubmitResult } from './controller-DmWFVHoj.js';
2
+ export { c as BlocFeedError, d as CaptureDiagnostics, e as CaptureResult, E as ElementDescriptor, F as FeedbackPayload, I as ImageAsset, M as MaybePromise, f as MetadataConfig, g as MetadataContext, P as PickerConfig, R as Rect, h as ScreenshotAdapter, i as ScreenshotAdapterOptions, j as ScreenshotMime, k as SessionPhase, T as TransportResult } from './controller-DmWFVHoj.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import * as react from 'react';
5
5
  import { ReactNode } from 'react';
6
6
 
7
7
  type BlocFeedProviderProps = {
8
- config?: BlocFeedConfig;
8
+ blocfeed_id: string;
9
+ config?: Omit<BlocFeedConfig, "blocfeed_id">;
9
10
  children: ReactNode;
10
11
  };
11
12
  declare function BlocFeedProvider(props: BlocFeedProviderProps): react_jsx_runtime.JSX.Element;
12
13
 
13
14
  type BlocFeedWidgetProps = {
14
- config?: BlocFeedConfig;
15
+ blocfeed_id: string;
16
+ config?: Omit<BlocFeedConfig, "blocfeed_id">;
15
17
  };
16
18
  declare function BlocFeedWidget(props: BlocFeedWidgetProps): react.ReactPortal | null;
17
19
 
package/dist/main.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import {f,a,b}from'./chunk-4EGJPVEG.js';import {createContext,useMemo,useState,useEffect,useContext}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {createPortal}from'react-dom';var m=createContext(null);function w(t){let e=useMemo(()=>f(t.config??{}),[]),[a,l]=useState(()=>e.getState());return useEffect(()=>e.subscribe(l),[e]),useEffect(()=>e.setConfig(t.config??{}),[e,t.config]),useEffect(()=>()=>e.destroy(),[e]),jsx(m.Provider,{value:{controller:e,state:a},children:t.children})}var T="blocfeed-styles-v1",_=`
2
+ import {f,a,b}from'./chunk-H36VLJXX.js';import {createContext,useMemo,useState,useEffect,useContext}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {createPortal}from'react-dom';var g=createContext(null);function w(t){let e=useMemo(()=>f({...t.config??{},blocfeed_id:t.blocfeed_id}),[]),[a,l]=useState(()=>e.getState());return useEffect(()=>e.subscribe(l),[e]),useEffect(()=>e.setConfig({...t.config??{},blocfeed_id:t.blocfeed_id}),[e,t.config,t.blocfeed_id]),useEffect(()=>()=>e.destroy(),[e]),jsx(g.Provider,{value:{controller:e,state:a},children:t.children})}var H="blocfeed-styles-v1",D=`
3
3
  :where([data-blocfeed-ui-root]),
4
4
  :where([data-blocfeed-ui-root]) * {
5
5
  box-sizing: border-box;
@@ -220,4 +220,4 @@ import {f,a,b}from'./chunk-4EGJPVEG.js';import {createContext,useMemo,useState,u
220
220
  font-size: 13px;
221
221
  color: rgba(243, 244, 246, 0.9);
222
222
  }
223
- `;function A(){if(!a()||document.getElementById(T))return;let t=document.createElement("style");t.id=T,t.textContent=_,document.head.appendChild(t);}function y(){let t=useContext(m);if(!t)throw new Error("useBlocFeed must be used within a <BlocFeedProvider />");return {state:t.state,controller:t.controller,start:t.controller.start,stop:t.controller.stop,clearSelection:t.controller.clearSelection,submit:t.controller.submit}}function G(t,e,a){return Math.max(e,Math.min(a,t))}function O(t,e){let l=window.innerWidth,r=window.innerHeight,d=G(t.x,12,Math.max(12,l-e-12)),f=t.y+t.height+12,g=Math.max(12,t.y-240);return {top:f+240<=r?f:g,left:d}}function V(t){let{rect:e}=t,a={left:`${e.x}px`,top:`${e.y}px`,width:`${Math.max(0,e.width)}px`,height:`${Math.max(0,e.height)}px`};return jsx("div",{className:"bf-highlight",style:a})}function Y(t){let{state:e,controller:a,start:l,stop:r,clearSelection:d,submit:f}=y(),[g,C]=useState(null),[h,F]=useState(""),[B,k]=useState(t.config.capture?.element??true),[S,P]=useState(t.config.capture?.fullPage??false),[I,N]=useState(null);useEffect(()=>a.subscribeHover(C),[a]),useEffect(()=>{let i=a.__unsafeGetSelectedElement();if(!i||e.phase==="idle"||e.phase==="picking"){N(null);return}let z=()=>{N(b(i.getBoundingClientRect()));};z();let u=()=>z();return window.addEventListener("scroll",u,{capture:true,passive:true}),window.addEventListener("resize",u,{passive:true}),()=>{window.removeEventListener("scroll",u,{capture:true}),window.removeEventListener("resize",u);}},[a,e.phase,e.selection?.selector]),useEffect(()=>{e.phase==="review"&&(F(""),k(t.config.capture?.element??true),P(t.config.capture?.fullPage??false));},[e.phase,e.selection?.selector,t.config.capture?.element,t.config.capture?.fullPage]),useEffect(()=>{if(e.phase!=="success")return;let i=window.setTimeout(()=>r(),1200);return ()=>window.clearTimeout(i)},[e.phase,r]);let c=e.phase==="capturing"||e.phase==="submitting",s=e.phase==="picking"?g?.rect??null:I??e.selection?.rect??null,x=useMemo(()=>s?O(s,360):null,[s?.x,s?.y,s?.width,s?.height]),R=e.lastError?.message;return jsxs(Fragment,{children:[e.phase==="idle"&&jsxs("button",{className:"bf-trigger",type:"button",onClick:()=>l(),"aria-label":"Give feedback",children:[jsx("span",{className:"bf-dot","aria-hidden":"true"}),"Feedback"]}),e.phase!=="idle"&&jsxs("div",{className:"bf-overlay",children:[e.phase!=="picking"&&jsx("div",{className:"bf-blocker",role:"presentation",onClick:()=>r()}),s&&jsx(V,{rect:s}),e.phase==="picking"&&jsxs("div",{className:"bf-hint",children:[jsxs("p",{children:["Click an element to attach your feedback. Press ",jsx("strong",{children:"Esc"})," to cancel."]}),jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),children:"Cancel"})]}),(e.phase==="review"||e.phase==="capturing"||e.phase==="submitting"||e.phase==="error"||e.phase==="success")&&x&&jsxs("div",{className:"bf-panel",style:{left:x.left,top:x.top},children:[jsxs("div",{className:"bf-panelHeader",children:[jsx("div",{className:"bf-title",children:"Feedback"}),jsxs("div",{className:"bf-row",style:{justifyContent:"flex-end"},children:[jsx("button",{type:"button",className:"bf-btn",onClick:()=>d(),disabled:c,children:"Re-pick"}),jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),disabled:c,children:"Close"})]})]}),jsxs("div",{className:"bf-panelBody",children:[jsx("textarea",{className:"bf-textarea",placeholder:"What\u2019s happening? What did you expect?",value:h,onChange:i=>F(i.target.value),disabled:c}),jsxs("div",{className:"bf-row",children:[jsxs("label",{children:[jsx("input",{type:"checkbox",checked:B,onChange:i=>k(i.target.checked),disabled:c}),"Screenshot element"]}),jsxs("label",{children:[jsx("input",{type:"checkbox",checked:S,onChange:i=>P(i.target.checked),disabled:c}),"Full page"]})]}),e.phase==="capturing"&&jsx("div",{className:"bf-status",children:"Capturing screenshots\u2026"}),e.phase==="submitting"&&jsx("div",{className:"bf-status",children:"Submitting\u2026"}),e.phase==="success"&&jsx("div",{className:"bf-status",children:"Sent. Thank you!"}),e.phase==="error"&&R&&jsx("div",{className:"bf-error",children:R}),jsxs("div",{className:"bf-actions",children:[jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),disabled:c,children:"Cancel"}),jsx("button",{type:"button",className:"bf-btn bf-btnPrimary",onClick:()=>f(h,{capture:{element:B,fullPage:S}}),disabled:c||h.trim().length===0,children:"Send"})]})]})]})]}),e.phase==="success"&&jsx("div",{className:"bf-toast","aria-live":"polite",children:"Feedback sent"})]})}function q(t){let e=t.config??{},[a,l]=useState(null);return useEffect(()=>{A();let r=document.createElement("div");r.setAttribute("data-blocfeed-ui-root","true"),r.setAttribute("data-blocfeed-ui","true");let d=e.ui?.zIndex;return typeof d=="number"&&r.style.setProperty("--bf-z",String(d)),document.body.appendChild(r),l(r),()=>{r.remove(),l(null);}},[e.ui?.zIndex]),a?createPortal(jsx(w,{config:e,children:jsx(Y,{config:e})}),a):null}export{w as BlocFeedProvider,q as BlocFeedWidget,y as useBlocFeed};
223
+ `;function T(){if(!a()||document.getElementById(H))return;let t=document.createElement("style");t.id=H,t.textContent=D,document.head.appendChild(t);}function y(){let t=useContext(g);if(!t)throw new Error("useBlocFeed must be used within a <BlocFeedProvider />");return {state:t.state,controller:t.controller,start:t.controller.start,stop:t.controller.stop,clearSelection:t.controller.clearSelection,submit:t.controller.submit}}function X(t,e,a){return Math.max(e,Math.min(a,t))}function G(t,e){let l=window.innerWidth,r=window.innerHeight,s=X(t.x,12,Math.max(12,l-e-12)),p=t.y+t.height+12,m=Math.max(12,t.y-240);return {top:p+240<=r?p:m,left:s}}function V(t){let{rect:e}=t,a={left:`${e.x}px`,top:`${e.y}px`,width:`${Math.max(0,e.width)}px`,height:`${Math.max(0,e.height)}px`};return jsx("div",{className:"bf-highlight",style:a})}function Y(t){let{state:e,controller:a,start:l,stop:r,clearSelection:s,submit:p}=y(),[m,C]=useState(null),[h,F]=useState(""),[B,k]=useState(t.config.capture?.element??true),[S,P]=useState(t.config.capture?.fullPage??false),[A,N]=useState(null);useEffect(()=>a.subscribeHover(C),[a]),useEffect(()=>{let n=a.__unsafeGetSelectedElement();if(!n||e.phase==="idle"||e.phase==="picking"){N(null);return}let z=()=>{N(b(n.getBoundingClientRect()));};z();let u=()=>z();return window.addEventListener("scroll",u,{capture:true,passive:true}),window.addEventListener("resize",u,{passive:true}),()=>{window.removeEventListener("scroll",u,{capture:true}),window.removeEventListener("resize",u);}},[a,e.phase,e.selection?.selector]),useEffect(()=>{e.phase==="review"&&(F(""),k(t.config.capture?.element??true),P(t.config.capture?.fullPage??false));},[e.phase,e.selection?.selector,t.config.capture?.element,t.config.capture?.fullPage]),useEffect(()=>{if(e.phase!=="success")return;let n=window.setTimeout(()=>r(),1200);return ()=>window.clearTimeout(n)},[e.phase,r]);let d=e.phase==="capturing"||e.phase==="submitting",c=e.phase==="picking"?m?.rect??null:A??e.selection?.rect??null,x=useMemo(()=>c?G(c,360):null,[c?.x,c?.y,c?.width,c?.height]),R=e.lastError?.message;return jsxs(Fragment,{children:[e.phase==="idle"&&jsxs("button",{className:"bf-trigger",type:"button",onClick:()=>l(),"aria-label":"Give feedback",children:[jsx("span",{className:"bf-dot","aria-hidden":"true"}),"Feedback"]}),e.phase!=="idle"&&jsxs("div",{className:"bf-overlay",children:[e.phase!=="picking"&&jsx("div",{className:"bf-blocker",role:"presentation",onClick:()=>r()}),c&&jsx(V,{rect:c}),e.phase==="picking"&&jsxs("div",{className:"bf-hint",children:[jsxs("p",{children:["Click an element to attach your feedback. Press ",jsx("strong",{children:"Esc"})," to cancel."]}),jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),children:"Cancel"})]}),(e.phase==="review"||e.phase==="capturing"||e.phase==="submitting"||e.phase==="error"||e.phase==="success")&&x&&jsxs("div",{className:"bf-panel",style:{left:x.left,top:x.top},children:[jsxs("div",{className:"bf-panelHeader",children:[jsx("div",{className:"bf-title",children:"Feedback"}),jsxs("div",{className:"bf-row",style:{justifyContent:"flex-end"},children:[jsx("button",{type:"button",className:"bf-btn",onClick:()=>s(),disabled:d,children:"Re-pick"}),jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),disabled:d,children:"Close"})]})]}),jsxs("div",{className:"bf-panelBody",children:[jsx("textarea",{className:"bf-textarea",placeholder:"What\u2019s happening? What did you expect?",value:h,onChange:n=>F(n.target.value),disabled:d}),jsxs("div",{className:"bf-row",children:[jsxs("label",{children:[jsx("input",{type:"checkbox",checked:B,onChange:n=>k(n.target.checked),disabled:d}),"Screenshot element"]}),jsxs("label",{children:[jsx("input",{type:"checkbox",checked:S,onChange:n=>P(n.target.checked),disabled:d}),"Full page"]})]}),e.phase==="capturing"&&jsx("div",{className:"bf-status",children:"Capturing screenshots\u2026"}),e.phase==="submitting"&&jsx("div",{className:"bf-status",children:"Submitting\u2026"}),e.phase==="success"&&jsx("div",{className:"bf-status",children:"Sent. Thank you!"}),e.phase==="error"&&R&&jsx("div",{className:"bf-error",children:R}),jsxs("div",{className:"bf-actions",children:[jsx("button",{type:"button",className:"bf-btn",onClick:()=>r(),disabled:d,children:"Cancel"}),jsx("button",{type:"button",className:"bf-btn bf-btnPrimary",onClick:()=>p(h,{capture:{element:B,fullPage:S}}),disabled:d||h.trim().length===0,children:"Send"})]})]})]})]}),e.phase==="success"&&jsx("div",{className:"bf-toast","aria-live":"polite",children:"Feedback sent"})]})}function q(t){let e={...t.config??{},blocfeed_id:t.blocfeed_id},[a,l]=useState(null);return useEffect(()=>{T();let r=document.createElement("div");r.setAttribute("data-blocfeed-ui-root","true"),r.setAttribute("data-blocfeed-ui","true");let s=e.ui?.zIndex;return typeof s=="number"&&r.style.setProperty("--bf-z",String(s)),document.body.appendChild(r),l(r),()=>{r.remove(),l(null);}},[e.ui?.zIndex]),a?createPortal(jsx(w,{blocfeed_id:e.blocfeed_id,...t.config?{config:t.config}:{},children:jsx(Y,{config:e})}),a):null}export{w as BlocFeedProvider,q as BlocFeedWidget,y as useBlocFeed};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blocfeed",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Drop-in feedback + screenshot widget for React.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,6 +23,7 @@
23
23
  "dist/**/*.cjs",
24
24
  "dist/**/*.d.ts",
25
25
  "dist/**/*.d.cts",
26
+ "CHANGELOG.md",
26
27
  "README.md",
27
28
  "LICENSE"
28
29
  ],
@@ -67,5 +68,10 @@
67
68
  "tsup": "^8.0.2",
68
69
  "typescript": "^5.5.4",
69
70
  "vitest": "^1.6.0"
70
- }
71
+ },
72
+ "directories": {
73
+ "doc": "docs",
74
+ "test": "tests"
75
+ },
76
+ "author": ""
71
77
  }
@@ -1 +0,0 @@
1
- function y(){return typeof window<"u"&&typeof document<"u"}function W(e){let t=globalThis.CSS;return typeof t?.escape=="function"?t.escape(e):e.replace(/[^a-zA-Z0-9_-]/g,n=>{let r=n.codePointAt(0);return r===void 0?"":`\\${r.toString(16)} `})}function O(e){return {x:e.x,y:e.y,width:e.width,height:e.height}}function ce(e){return {x:e.x+window.scrollX,y:e.y+window.scrollY,width:e.width,height:e.height}}function ue(e){return e.replace(/\s+/g," ").trim()}function de(e,t=140){let n=e.textContent;if(!n)return;let r=ue(n);if(r)return r.length<=t?r:`${r.slice(0,t-1)}\u2026`}function fe(e){let t=1;for(let n=e.previousElementSibling;n;n=n.previousElementSibling)n.tagName===e.tagName&&(t+=1);return t}var Y=["data-testid","data-test-id","data-test","data-qa","data-cy"],j="data-blocfeed-component";function me(e){let t=e.closest(`[${j}]`);if(!t)return;let r=t.getAttribute(j)?.trim();return r||void 0}function pe(e){for(let t of Y){let n=e.closest(`[${t}]`);if(!n)continue;let o=n.getAttribute(t)?.trim();if(o)return o}}function ge(e){try{let t=e,n=Object.getOwnPropertyNames(t);for(let r of n)if(r.startsWith("__reactFiber$")||r.startsWith("__reactInternalInstance$")){let o=t[r];if(o&&typeof o=="object")return o}}catch{}return null}function R(e){if(e&&typeof e!="string"){if(typeof e=="function"){let t=e;return typeof t.displayName=="string"&&t.displayName?t.displayName:typeof t.name=="string"&&t.name?t.name:void 0}if(typeof e=="object"){let t=e,n=t.displayName;if(typeof n=="string"&&n)return n;let r=t.render;if(typeof r=="function"){let i=r;if(typeof i.displayName=="string"&&i.displayName)return i.displayName;if(typeof i.name=="string"&&i.name)return i.name}let o=t.type;return R(o)}}}function we(e){let t=ge(e);if(!t)return;let n=t._debugOwner;for(let o=0;n&&o<50;o+=1){let i=R(n.type)??R(n.elementType);if(i)return i;n=n._debugOwner;}let r=t;for(let o=0;r&&o<80;o+=1){let i=R(r.type)??R(r.elementType);if(i)return i;r=r.return;}}function be(e){let t=e.tagName.toLowerCase(),n=e.getAttribute("id");if(n)return `#${W(n)}`;for(let r of Y){let o=e.getAttribute(r);if(o)return `${t}[${r}="${W(o)}"]`}return `${t}:nth-of-type(${fe(e)})`}function he(e,t=10){let n=[],r=e;for(;r&&n.length<t;){let o=be(r);if(n.unshift(o),o.startsWith("#"))break;r=r.parentElement;}return n.join(" > ")}function z(e,t){if(!t||t.length===0)return false;for(let n of t)if(e.closest(n))return true;return false}function _(e,t){if(!e||z(e,t.ignoreSelectors))return null;let n=e;for(;n;){if(z(n,t.ignoreSelectors))return null;if(t.isSelectable?.(n)??ye(n))return n;n=n.parentElement;}return null}function ye(e){let t=e.tagName;return !(t==="HTML"||t==="BODY")}function Q(e){let t=e.getBoundingClientRect(),n={selector:he(e),tagName:e.tagName.toLowerCase(),rect:O(t),pageRect:ce(t)},r=e.getAttribute("id");r&&(n.id=r);let o=e.className;typeof o=="string"&&o.trim()&&(n.className=o);let i=de(e);i&&(n.textSnippet=i);let s=me(e)??we(e);s&&(n.componentName=s);let l=pe(e);return l&&(n.testId=l),n}var D=null;async function X(){return D||(D=import('html-to-image')),D}async function Ee(e){return await new Promise((t,n)=>{let r=new Image;r.onload=()=>t({width:r.naturalWidth,height:r.naturalHeight}),r.onerror=()=>n(new Error("Failed to load generated screenshot")),r.src=e;})}async function J(e,t){let{width:n,height:r}=await Ee(e);return {dataUrl:e,mime:t,width:n,height:r}}function F(e){if(e?.aborted)throw new Error("Aborted")}function G(){return {async captureElement(e,t){if(!y())throw new Error("captureElement can only run in the browser");F(t.signal);let n=await X();F(t.signal);let r=t.mime==="image/jpeg"?await n.toJpeg(e,{quality:t.quality??.92,pixelRatio:t.pixelRatio}):await n.toPng(e,{pixelRatio:t.pixelRatio});return F(t.signal),await J(r,t.mime)},async captureFullPage(e){if(!y())throw new Error("captureFullPage can only run in the browser");F(e.signal);let t=document.documentElement,n=Math.max(t.scrollWidth,t.clientWidth),r=Math.max(t.scrollHeight,t.clientHeight),o=Math.min(1,e.maxDimension/Math.max(n,r)),i=Math.max(1,Math.round(n*o)),s=Math.max(1,Math.round(r*o)),l=await X();F(e.signal);let c=e.mime==="image/jpeg"?await l.toJpeg(t,{width:i,height:s,quality:e.quality??.92,pixelRatio:e.pixelRatio}):await l.toPng(t,{width:i,height:s,pixelRatio:e.pixelRatio});return F(e.signal),await J(c,e.mime)}}}function ke(e){if(e instanceof Error)return e.message;if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return "Unknown error"}}function p(e,t,n){let r={kind:e,message:ke(t)};return n&&(r.detail=n),r}var Se=12e3,ve=2048,xe=.92;function K(){return Date.now()}function Pe(e){return new Promise((t,n)=>{let r=()=>n(new Error("Aborted"));if(e.aborted){r();return}e.addEventListener("abort",r,{once:true});})}async function Z(e,t,n){let r=new Promise((i,s)=>{let l=setTimeout(()=>s(new Error("Timeout")),t);typeof l.unref=="function"&&l.unref();}),o=[e,r];return n&&o.push(Pe(n)),await Promise.race(o)}function Ce(e){if(!y())return 1;let t=window.devicePixelRatio||1,n=e?.pixelRatio??Math.min(t,2);return Math.max(.1,n)}function Fe(e){return !!(e?.element||e?.fullPage)}function V(e){let t={mime:e.mime,pixelRatio:e.pixelRatio,maxDimension:e.maxDimension};return e.includeQuality&&(t.quality=e.quality),e.signal&&(t.signal=e.signal),t}async function ee(e){let{selectionElement:t,capture:n,signal:r}=e;if(!y()||!Fe(n))return;let o=K(),i=[],s=n?.timeoutMs??Se,l=n?.maxDimension??ve,c=n?.mime??"image/png",m=n?.quality??xe,k=n?.adapter??G(),E={},u=Ce(n);if(n?.element&&t)try{let d=t.getBoundingClientRect(),g=Math.min(1,l/Math.max(d.width,d.height)),f=Math.min(u,u*g),S=await Z(Promise.resolve(k.captureElement(t,{...V({mime:c,quality:m,pixelRatio:f,maxDimension:l,includeQuality:c==="image/jpeg",...r?{signal:r}:{}})})),s,r);E.element=S;}catch(d){if(r?.aborted)throw d;i.push(p("capture_failed",d,{target:"element"}));}if(n?.fullPage)try{let d=await Z(Promise.resolve(k.captureFullPage(V({mime:c,quality:m,pixelRatio:u,maxDimension:l,includeQuality:c==="image/jpeg",...r?{signal:r}:{}}))),s,r);E.fullPage=d;}catch(d){if(r?.aborted)throw d;i.push(p("capture_failed",d,{target:"fullPage"}));}let b=K(),a={startedAt:o,finishedAt:b,durationMs:Math.max(0,b-o)};return i.length>0&&(a.errors=i),{...E,diagnostics:a}}function Te(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{return}}function Ae(){return y()?{url:window.location.href,title:document.title,referrer:document.referrer||void 0,userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height},scroll:{x:window.scrollX,y:window.scrollY},devicePixelRatio:window.devicePixelRatio||1,timezone:Te()}:{}}async function te(e){let{config:t,context:n}=e;if(t?.enabled===false)return {};let r=Ae(),o=t?.enrich;if(!o)return r;try{let i=await o(n);return {...r,...i}}catch(i){let s=p("unknown",i);return {...r,blocfeedMetadataError:s.message}}}function $(e){let t=null,n=null,r=(...o)=>{n=o,t===null&&(t=requestAnimationFrame(()=>{if(t=null,!n)return;let i=n;n=null,e(...i);}));};return r.cancel=()=>{t!==null&&cancelAnimationFrame(t),t=null,n=null;},r}function M(e){return e instanceof Element?!!e.closest("[data-blocfeed-ui]"):false}function B(e){e.stopPropagation(),e.stopImmediatePropagation?.();}function ne(e,t){if(!y())throw new Error("BlocFeed picker can only run in a browser environment.");let n=e.ignoreSelectors,r=e.isSelectable,o={};n&&n.length>0&&(o.ignoreSelectors=n),r&&(o.isSelectable=r);let i=null,s=null,l=(a,d=false)=>{if(!a){i=null,s=null,t.onHover(null);return}let g=O(a.getBoundingClientRect()),f=`${Math.round(g.x)}:${Math.round(g.y)}:${Math.round(g.width)}:${Math.round(g.height)}`;!d&&a===i&&f===s||(i=a,s=f,t.onHover({element:a,rect:g}));},c=$(a=>{if(M(a.target))return;let d=document.elementFromPoint(a.clientX,a.clientY),g=_(d,o);l(g);}),m=$(()=>{i&&l(i,true);}),k=a=>{M(a.target)||(B(a),a.pointerType==="mouse"&&a.preventDefault());},E=a=>{M(a.target)||(B(a),a.pointerType==="mouse"&&a.preventDefault());},u=a=>{if(M(a.target))return;B(a),a.preventDefault();let d=document.elementFromPoint(a.clientX,a.clientY),g=_(d,o);g&&t.onSelect({element:g,descriptor:Q(g)});},b=a=>{a.key==="Escape"&&(B(a),a.preventDefault(),t.onCancel());};return window.addEventListener("pointermove",c,{capture:true,passive:true}),window.addEventListener("pointerdown",k,{capture:true}),window.addEventListener("pointerup",E,{capture:true}),window.addEventListener("click",u,{capture:true}),window.addEventListener("keydown",b,{capture:true}),window.addEventListener("scroll",m,{capture:true,passive:true}),window.addEventListener("resize",m,{passive:true}),{stop(){window.removeEventListener("pointermove",c,{capture:true}),window.removeEventListener("pointerdown",k,{capture:true}),window.removeEventListener("pointerup",E,{capture:true}),window.removeEventListener("click",u,{capture:true}),window.removeEventListener("keydown",b,{capture:true}),window.removeEventListener("scroll",m,{capture:true}),window.removeEventListener("resize",m),c.cancel(),m.cancel(),t.onHover(null);}}}var Re=12e3;function re(e,t){return new Promise((n,r)=>{if(t?.aborted){r(new Error("Aborted"));return}let o=setTimeout(n,e),i=()=>{clearTimeout(o),r(new Error("Aborted"));};t?.addEventListener("abort",i,{once:true});})}async function Me(e){return e?typeof e=="function"?await e():e:{}}function Be(e){return e>=500&&e<=599}async function oe(e){let{payload:t,webhook:n,signal:r}=e,o=Math.max(1,n.retry?.attempts??2),i=Math.max(0,n.retry?.backoffMs??500);for(let s=1;s<=o;s+=1){let l=n.timeoutMs??Re,c=new AbortController,m=setTimeout(()=>c.abort(),l),k=()=>c.abort();r&&r.addEventListener("abort",k,{once:true});try{let u={method:"POST",headers:{"content-type":"application/json",...await Me(n.headers)},body:JSON.stringify(t),signal:c.signal};n.credentials!==void 0&&(u.credentials=n.credentials);let b=await fetch(n.url,u);if(b.ok)return {ok:!0,status:b.status};if(s<o&&Be(b.status)){let a=.85+Math.random()*.3,d=Math.round(i*2**(s-1)*a);await re(d,r);continue}return {ok:!1,status:b.status,error:p("webhook_failed",new Error(`HTTP ${b.status}`))}}catch(E){if(c.signal.aborted||r?.aborted)return {ok:false,error:p("aborted",E)};if(s<o){let u=.85+Math.random()*.3,b=Math.round(i*2**(s-1)*u);await re(b,r);continue}return {ok:false,error:p("webhook_failed",E)}}finally{clearTimeout(m),r&&r.removeEventListener("abort",k);}}return {ok:false,error:p("webhook_failed",new Error("Failed"))}}function Ie(e,t){let n=e.callback?.ok,r=e.webhook?.ok;return n===void 0&&r===void 0?false:n===void 0?!!r:r===void 0?!!n:t?n&&r:n||r}async function ie(e){let{submit:t,signal:n}=e,r=t.beforeSubmit?await t.beforeSubmit(e.payload):e.payload,o={ok:false};if(t.onSubmit)try{await t.onSubmit(r),o.callback={ok:!0};}catch(i){o.callback={ok:false,error:p("callback_failed",i)};}if(t.webhook){let i={payload:r,webhook:t.webhook};o.webhook=await oe(n?{...i,signal:n}:i);}return o.ok=Ie(o,t.requireAll??false),{payload:r,result:o}}var Le=["[data-blocfeed-ui]","[data-blocfeed-ignore]"];function He(e){let t=[...Le,...e?.ignoreSelectors??[]],n=Array.from(new Set(t));return {...e,ignoreSelectors:n}}function ae(){return {phase:"idle"}}function ct(e){let t=e,n=ae(),r=new Set,o=new Set,i=null,s=null,l=null,c=null,m=0,k=()=>{for(let f of r)f(n);},E=f=>{for(let S of o)S(f);},u=f=>{n=f,k();},b=()=>{m+=1,c?.abort(),c=null;},a=()=>{i?.stop(),i=null,E(null),l!==null&&y()&&(document.documentElement.style.cursor=l,l=null);},d=()=>{b(),a(),s=null,u(ae());},g=()=>{if(!y())return;a(),s=null;let f=He(t.picker);l=document.documentElement.style.cursor,document.documentElement.style.cursor="crosshair",u({phase:"picking"}),i=ne(f,{onHover:E,onSelect:({element:S,descriptor:T})=>{s=S,a(),u({phase:"review",selection:T});},onCancel:()=>{d();}});};return {getState:()=>n,subscribe(f){return r.add(f),()=>r.delete(f)},subscribeHover(f){return o.add(f),()=>o.delete(f)},start(){n.phase==="capturing"||n.phase==="submitting"||n.phase!=="picking"&&g();},stop(){d();},clearSelection(){n.phase==="capturing"||n.phase==="submitting"||g();},setConfig(f){t=f;},async submit(f,S){if(!y()){let w=p("configuration",new Error("BlocFeed submit can only run in the browser"));return u({phase:"error",lastError:w}),{ok:false}}let T=t.submit;if(!T?.onSubmit&&!T?.webhook){let x={phase:"error",lastError:p("configuration",new Error("BlocFeed requires submit.onSubmit and/or submit.webhook"))};return n.selection&&(x.selection=n.selection),u(x),{ok:false}}if(n.phase==="capturing"||n.phase==="submitting")return {ok:false};let A=m+1;m=A,c?.abort(),c=new AbortController;let P=c.signal,h=n.selection,I=S?.capture?{...t.capture,...S.capture}:t.capture,q=!!(I?.element||I?.fullPage),U={phase:q?"capturing":"submitting"};h&&(U.selection=h),u(U);try{let w=q?await ee({selectionElement:s,capture:I,signal:P}):void 0;if(P.aborted||m!==A)return {ok:!1};let x={phase:"submitting"};h&&(x.selection=h),w&&(x.capture=w),u(x);let C={};h&&(C.selection=h),w&&(C.capture=w);let se=await te({config:t.metadata,context:C}),L={version:1,createdAt:new Date().toISOString(),message:f,metadata:se};h&&(L.selection=h),w&&(L.screenshots=w);let{result:v}=await ie({payload:L,submit:T,signal:P});if(P.aborted||m!==A)return v;if(v.ok){let N={phase:"success",lastSubmit:v};return h&&(N.selection=h),w&&(N.capture=w),u(N),v}let le=v.webhook?.error??v.callback?.error??p("unknown",new Error("Submission failed")),H={phase:"error",lastSubmit:v,lastError:le};return h&&(H.selection=h),w&&(H.capture=w),u(H),v}catch(w){if(P.aborted||m!==A)return {ok:false};let C={phase:"error",lastError:P.aborted?p("aborted",w):p("unknown",w)};return h&&(C.selection=h),u(C),{ok:false}}finally{m===A&&(c=null);}},__unsafeGetSelectedElement(){return s},destroy(){d(),r.clear(),o.clear();}}}export{y as a,O as b,G as c,ee as d,te as e,ct as f};
@@ -1 +0,0 @@
1
- 'use strict';function y(){return typeof window<"u"&&typeof document<"u"}function W(e){let t=globalThis.CSS;return typeof t?.escape=="function"?t.escape(e):e.replace(/[^a-zA-Z0-9_-]/g,n=>{let r=n.codePointAt(0);return r===void 0?"":`\\${r.toString(16)} `})}function O(e){return {x:e.x,y:e.y,width:e.width,height:e.height}}function ce(e){return {x:e.x+window.scrollX,y:e.y+window.scrollY,width:e.width,height:e.height}}function ue(e){return e.replace(/\s+/g," ").trim()}function de(e,t=140){let n=e.textContent;if(!n)return;let r=ue(n);if(r)return r.length<=t?r:`${r.slice(0,t-1)}\u2026`}function fe(e){let t=1;for(let n=e.previousElementSibling;n;n=n.previousElementSibling)n.tagName===e.tagName&&(t+=1);return t}var Y=["data-testid","data-test-id","data-test","data-qa","data-cy"],j="data-blocfeed-component";function me(e){let t=e.closest(`[${j}]`);if(!t)return;let r=t.getAttribute(j)?.trim();return r||void 0}function pe(e){for(let t of Y){let n=e.closest(`[${t}]`);if(!n)continue;let o=n.getAttribute(t)?.trim();if(o)return o}}function ge(e){try{let t=e,n=Object.getOwnPropertyNames(t);for(let r of n)if(r.startsWith("__reactFiber$")||r.startsWith("__reactInternalInstance$")){let o=t[r];if(o&&typeof o=="object")return o}}catch{}return null}function R(e){if(e&&typeof e!="string"){if(typeof e=="function"){let t=e;return typeof t.displayName=="string"&&t.displayName?t.displayName:typeof t.name=="string"&&t.name?t.name:void 0}if(typeof e=="object"){let t=e,n=t.displayName;if(typeof n=="string"&&n)return n;let r=t.render;if(typeof r=="function"){let i=r;if(typeof i.displayName=="string"&&i.displayName)return i.displayName;if(typeof i.name=="string"&&i.name)return i.name}let o=t.type;return R(o)}}}function we(e){let t=ge(e);if(!t)return;let n=t._debugOwner;for(let o=0;n&&o<50;o+=1){let i=R(n.type)??R(n.elementType);if(i)return i;n=n._debugOwner;}let r=t;for(let o=0;r&&o<80;o+=1){let i=R(r.type)??R(r.elementType);if(i)return i;r=r.return;}}function be(e){let t=e.tagName.toLowerCase(),n=e.getAttribute("id");if(n)return `#${W(n)}`;for(let r of Y){let o=e.getAttribute(r);if(o)return `${t}[${r}="${W(o)}"]`}return `${t}:nth-of-type(${fe(e)})`}function he(e,t=10){let n=[],r=e;for(;r&&n.length<t;){let o=be(r);if(n.unshift(o),o.startsWith("#"))break;r=r.parentElement;}return n.join(" > ")}function z(e,t){if(!t||t.length===0)return false;for(let n of t)if(e.closest(n))return true;return false}function _(e,t){if(!e||z(e,t.ignoreSelectors))return null;let n=e;for(;n;){if(z(n,t.ignoreSelectors))return null;if(t.isSelectable?.(n)??ye(n))return n;n=n.parentElement;}return null}function ye(e){let t=e.tagName;return !(t==="HTML"||t==="BODY")}function Q(e){let t=e.getBoundingClientRect(),n={selector:he(e),tagName:e.tagName.toLowerCase(),rect:O(t),pageRect:ce(t)},r=e.getAttribute("id");r&&(n.id=r);let o=e.className;typeof o=="string"&&o.trim()&&(n.className=o);let i=de(e);i&&(n.textSnippet=i);let s=me(e)??we(e);s&&(n.componentName=s);let l=pe(e);return l&&(n.testId=l),n}var D=null;async function X(){return D||(D=import('html-to-image')),D}async function Ee(e){return await new Promise((t,n)=>{let r=new Image;r.onload=()=>t({width:r.naturalWidth,height:r.naturalHeight}),r.onerror=()=>n(new Error("Failed to load generated screenshot")),r.src=e;})}async function J(e,t){let{width:n,height:r}=await Ee(e);return {dataUrl:e,mime:t,width:n,height:r}}function F(e){if(e?.aborted)throw new Error("Aborted")}function G(){return {async captureElement(e,t){if(!y())throw new Error("captureElement can only run in the browser");F(t.signal);let n=await X();F(t.signal);let r=t.mime==="image/jpeg"?await n.toJpeg(e,{quality:t.quality??.92,pixelRatio:t.pixelRatio}):await n.toPng(e,{pixelRatio:t.pixelRatio});return F(t.signal),await J(r,t.mime)},async captureFullPage(e){if(!y())throw new Error("captureFullPage can only run in the browser");F(e.signal);let t=document.documentElement,n=Math.max(t.scrollWidth,t.clientWidth),r=Math.max(t.scrollHeight,t.clientHeight),o=Math.min(1,e.maxDimension/Math.max(n,r)),i=Math.max(1,Math.round(n*o)),s=Math.max(1,Math.round(r*o)),l=await X();F(e.signal);let c=e.mime==="image/jpeg"?await l.toJpeg(t,{width:i,height:s,quality:e.quality??.92,pixelRatio:e.pixelRatio}):await l.toPng(t,{width:i,height:s,pixelRatio:e.pixelRatio});return F(e.signal),await J(c,e.mime)}}}function ke(e){if(e instanceof Error)return e.message;if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return "Unknown error"}}function p(e,t,n){let r={kind:e,message:ke(t)};return n&&(r.detail=n),r}var Se=12e3,ve=2048,xe=.92;function K(){return Date.now()}function Pe(e){return new Promise((t,n)=>{let r=()=>n(new Error("Aborted"));if(e.aborted){r();return}e.addEventListener("abort",r,{once:true});})}async function Z(e,t,n){let r=new Promise((i,s)=>{let l=setTimeout(()=>s(new Error("Timeout")),t);typeof l.unref=="function"&&l.unref();}),o=[e,r];return n&&o.push(Pe(n)),await Promise.race(o)}function Ce(e){if(!y())return 1;let t=window.devicePixelRatio||1,n=e?.pixelRatio??Math.min(t,2);return Math.max(.1,n)}function Fe(e){return !!(e?.element||e?.fullPage)}function V(e){let t={mime:e.mime,pixelRatio:e.pixelRatio,maxDimension:e.maxDimension};return e.includeQuality&&(t.quality=e.quality),e.signal&&(t.signal=e.signal),t}async function ee(e){let{selectionElement:t,capture:n,signal:r}=e;if(!y()||!Fe(n))return;let o=K(),i=[],s=n?.timeoutMs??Se,l=n?.maxDimension??ve,c=n?.mime??"image/png",m=n?.quality??xe,k=n?.adapter??G(),E={},u=Ce(n);if(n?.element&&t)try{let d=t.getBoundingClientRect(),g=Math.min(1,l/Math.max(d.width,d.height)),f=Math.min(u,u*g),S=await Z(Promise.resolve(k.captureElement(t,{...V({mime:c,quality:m,pixelRatio:f,maxDimension:l,includeQuality:c==="image/jpeg",...r?{signal:r}:{}})})),s,r);E.element=S;}catch(d){if(r?.aborted)throw d;i.push(p("capture_failed",d,{target:"element"}));}if(n?.fullPage)try{let d=await Z(Promise.resolve(k.captureFullPage(V({mime:c,quality:m,pixelRatio:u,maxDimension:l,includeQuality:c==="image/jpeg",...r?{signal:r}:{}}))),s,r);E.fullPage=d;}catch(d){if(r?.aborted)throw d;i.push(p("capture_failed",d,{target:"fullPage"}));}let b=K(),a={startedAt:o,finishedAt:b,durationMs:Math.max(0,b-o)};return i.length>0&&(a.errors=i),{...E,diagnostics:a}}function Te(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{return}}function Ae(){return y()?{url:window.location.href,title:document.title,referrer:document.referrer||void 0,userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height},scroll:{x:window.scrollX,y:window.scrollY},devicePixelRatio:window.devicePixelRatio||1,timezone:Te()}:{}}async function te(e){let{config:t,context:n}=e;if(t?.enabled===false)return {};let r=Ae(),o=t?.enrich;if(!o)return r;try{let i=await o(n);return {...r,...i}}catch(i){let s=p("unknown",i);return {...r,blocfeedMetadataError:s.message}}}function $(e){let t=null,n=null,r=(...o)=>{n=o,t===null&&(t=requestAnimationFrame(()=>{if(t=null,!n)return;let i=n;n=null,e(...i);}));};return r.cancel=()=>{t!==null&&cancelAnimationFrame(t),t=null,n=null;},r}function M(e){return e instanceof Element?!!e.closest("[data-blocfeed-ui]"):false}function B(e){e.stopPropagation(),e.stopImmediatePropagation?.();}function ne(e,t){if(!y())throw new Error("BlocFeed picker can only run in a browser environment.");let n=e.ignoreSelectors,r=e.isSelectable,o={};n&&n.length>0&&(o.ignoreSelectors=n),r&&(o.isSelectable=r);let i=null,s=null,l=(a,d=false)=>{if(!a){i=null,s=null,t.onHover(null);return}let g=O(a.getBoundingClientRect()),f=`${Math.round(g.x)}:${Math.round(g.y)}:${Math.round(g.width)}:${Math.round(g.height)}`;!d&&a===i&&f===s||(i=a,s=f,t.onHover({element:a,rect:g}));},c=$(a=>{if(M(a.target))return;let d=document.elementFromPoint(a.clientX,a.clientY),g=_(d,o);l(g);}),m=$(()=>{i&&l(i,true);}),k=a=>{M(a.target)||(B(a),a.pointerType==="mouse"&&a.preventDefault());},E=a=>{M(a.target)||(B(a),a.pointerType==="mouse"&&a.preventDefault());},u=a=>{if(M(a.target))return;B(a),a.preventDefault();let d=document.elementFromPoint(a.clientX,a.clientY),g=_(d,o);g&&t.onSelect({element:g,descriptor:Q(g)});},b=a=>{a.key==="Escape"&&(B(a),a.preventDefault(),t.onCancel());};return window.addEventListener("pointermove",c,{capture:true,passive:true}),window.addEventListener("pointerdown",k,{capture:true}),window.addEventListener("pointerup",E,{capture:true}),window.addEventListener("click",u,{capture:true}),window.addEventListener("keydown",b,{capture:true}),window.addEventListener("scroll",m,{capture:true,passive:true}),window.addEventListener("resize",m,{passive:true}),{stop(){window.removeEventListener("pointermove",c,{capture:true}),window.removeEventListener("pointerdown",k,{capture:true}),window.removeEventListener("pointerup",E,{capture:true}),window.removeEventListener("click",u,{capture:true}),window.removeEventListener("keydown",b,{capture:true}),window.removeEventListener("scroll",m,{capture:true}),window.removeEventListener("resize",m),c.cancel(),m.cancel(),t.onHover(null);}}}var Re=12e3;function re(e,t){return new Promise((n,r)=>{if(t?.aborted){r(new Error("Aborted"));return}let o=setTimeout(n,e),i=()=>{clearTimeout(o),r(new Error("Aborted"));};t?.addEventListener("abort",i,{once:true});})}async function Me(e){return e?typeof e=="function"?await e():e:{}}function Be(e){return e>=500&&e<=599}async function oe(e){let{payload:t,webhook:n,signal:r}=e,o=Math.max(1,n.retry?.attempts??2),i=Math.max(0,n.retry?.backoffMs??500);for(let s=1;s<=o;s+=1){let l=n.timeoutMs??Re,c=new AbortController,m=setTimeout(()=>c.abort(),l),k=()=>c.abort();r&&r.addEventListener("abort",k,{once:true});try{let u={method:"POST",headers:{"content-type":"application/json",...await Me(n.headers)},body:JSON.stringify(t),signal:c.signal};n.credentials!==void 0&&(u.credentials=n.credentials);let b=await fetch(n.url,u);if(b.ok)return {ok:!0,status:b.status};if(s<o&&Be(b.status)){let a=.85+Math.random()*.3,d=Math.round(i*2**(s-1)*a);await re(d,r);continue}return {ok:!1,status:b.status,error:p("webhook_failed",new Error(`HTTP ${b.status}`))}}catch(E){if(c.signal.aborted||r?.aborted)return {ok:false,error:p("aborted",E)};if(s<o){let u=.85+Math.random()*.3,b=Math.round(i*2**(s-1)*u);await re(b,r);continue}return {ok:false,error:p("webhook_failed",E)}}finally{clearTimeout(m),r&&r.removeEventListener("abort",k);}}return {ok:false,error:p("webhook_failed",new Error("Failed"))}}function Ie(e,t){let n=e.callback?.ok,r=e.webhook?.ok;return n===void 0&&r===void 0?false:n===void 0?!!r:r===void 0?!!n:t?n&&r:n||r}async function ie(e){let{submit:t,signal:n}=e,r=t.beforeSubmit?await t.beforeSubmit(e.payload):e.payload,o={ok:false};if(t.onSubmit)try{await t.onSubmit(r),o.callback={ok:!0};}catch(i){o.callback={ok:false,error:p("callback_failed",i)};}if(t.webhook){let i={payload:r,webhook:t.webhook};o.webhook=await oe(n?{...i,signal:n}:i);}return o.ok=Ie(o,t.requireAll??false),{payload:r,result:o}}var Le=["[data-blocfeed-ui]","[data-blocfeed-ignore]"];function He(e){let t=[...Le,...e?.ignoreSelectors??[]],n=Array.from(new Set(t));return {...e,ignoreSelectors:n}}function ae(){return {phase:"idle"}}function ct(e){let t=e,n=ae(),r=new Set,o=new Set,i=null,s=null,l=null,c=null,m=0,k=()=>{for(let f of r)f(n);},E=f=>{for(let S of o)S(f);},u=f=>{n=f,k();},b=()=>{m+=1,c?.abort(),c=null;},a=()=>{i?.stop(),i=null,E(null),l!==null&&y()&&(document.documentElement.style.cursor=l,l=null);},d=()=>{b(),a(),s=null,u(ae());},g=()=>{if(!y())return;a(),s=null;let f=He(t.picker);l=document.documentElement.style.cursor,document.documentElement.style.cursor="crosshair",u({phase:"picking"}),i=ne(f,{onHover:E,onSelect:({element:S,descriptor:T})=>{s=S,a(),u({phase:"review",selection:T});},onCancel:()=>{d();}});};return {getState:()=>n,subscribe(f){return r.add(f),()=>r.delete(f)},subscribeHover(f){return o.add(f),()=>o.delete(f)},start(){n.phase==="capturing"||n.phase==="submitting"||n.phase!=="picking"&&g();},stop(){d();},clearSelection(){n.phase==="capturing"||n.phase==="submitting"||g();},setConfig(f){t=f;},async submit(f,S){if(!y()){let w=p("configuration",new Error("BlocFeed submit can only run in the browser"));return u({phase:"error",lastError:w}),{ok:false}}let T=t.submit;if(!T?.onSubmit&&!T?.webhook){let x={phase:"error",lastError:p("configuration",new Error("BlocFeed requires submit.onSubmit and/or submit.webhook"))};return n.selection&&(x.selection=n.selection),u(x),{ok:false}}if(n.phase==="capturing"||n.phase==="submitting")return {ok:false};let A=m+1;m=A,c?.abort(),c=new AbortController;let P=c.signal,h=n.selection,I=S?.capture?{...t.capture,...S.capture}:t.capture,q=!!(I?.element||I?.fullPage),U={phase:q?"capturing":"submitting"};h&&(U.selection=h),u(U);try{let w=q?await ee({selectionElement:s,capture:I,signal:P}):void 0;if(P.aborted||m!==A)return {ok:!1};let x={phase:"submitting"};h&&(x.selection=h),w&&(x.capture=w),u(x);let C={};h&&(C.selection=h),w&&(C.capture=w);let se=await te({config:t.metadata,context:C}),L={version:1,createdAt:new Date().toISOString(),message:f,metadata:se};h&&(L.selection=h),w&&(L.screenshots=w);let{result:v}=await ie({payload:L,submit:T,signal:P});if(P.aborted||m!==A)return v;if(v.ok){let N={phase:"success",lastSubmit:v};return h&&(N.selection=h),w&&(N.capture=w),u(N),v}let le=v.webhook?.error??v.callback?.error??p("unknown",new Error("Submission failed")),H={phase:"error",lastSubmit:v,lastError:le};return h&&(H.selection=h),w&&(H.capture=w),u(H),v}catch(w){if(P.aborted||m!==A)return {ok:false};let C={phase:"error",lastError:P.aborted?p("aborted",w):p("unknown",w)};return h&&(C.selection=h),u(C),{ok:false}}finally{m===A&&(c=null);}},__unsafeGetSelectedElement(){return s},destroy(){d(),r.clear(),o.clear();}}}exports.a=y;exports.b=O;exports.c=G;exports.d=ee;exports.e=te;exports.f=ct;