@mindbowser_inc/ui-feedback-plugin 0.3.1 → 0.3.2
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/dist/index.d.ts +6 -1
- package/dist/local-CqZPr-Eb.mjs +66 -0
- package/dist/local-CqZPr-Eb.mjs.map +1 -0
- package/dist/ui-feedback-plugin.es.js +105 -101
- package/dist/ui-feedback-plugin.es.js.map +1 -1
- package/dist/ui-feedback-plugin.umd.js +26 -26
- package/dist/ui-feedback-plugin.umd.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ declare interface AWSProviderConfig {
|
|
|
23
23
|
pollInterval?: number;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
declare type BackendConfig = FirebaseProviderConfig | SupabaseProviderConfig | AWSProviderConfig;
|
|
26
|
+
declare type BackendConfig = FirebaseProviderConfig | SupabaseProviderConfig | AWSProviderConfig | LocalProviderConfig;
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Firebase backend — Firestore for comments/replies, Firebase Storage for screenshots.
|
|
@@ -42,12 +42,17 @@ declare interface FirebaseProviderConfig {
|
|
|
42
42
|
|
|
43
43
|
export declare function initFeedbackPlugin(config: PluginConfig): () => void;
|
|
44
44
|
|
|
45
|
+
declare interface LocalProviderConfig {
|
|
46
|
+
provider: 'local';
|
|
47
|
+
}
|
|
48
|
+
|
|
45
49
|
export declare interface PluginConfig {
|
|
46
50
|
/**
|
|
47
51
|
* Storage backend. Pick one:
|
|
48
52
|
* - `firebase` — Firestore + Firebase Storage
|
|
49
53
|
* - `supabase` — Postgres + Supabase Storage
|
|
50
54
|
* - `aws` — Everything in AWS S3 via Cognito Identity Pool (no backend needed)
|
|
55
|
+
* - `local` — In-memory / sessionStorage local storage
|
|
51
56
|
*/
|
|
52
57
|
backend: BackendConfig;
|
|
53
58
|
/** Namespace comments by project (default: 'default'). */
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
var a = Object.defineProperty;
|
|
2
|
+
var g = (n, e, t) => e in n ? a(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
|
|
3
|
+
var i = (n, e, t) => g(n, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
class l {
|
|
5
|
+
constructor() {
|
|
6
|
+
i(this, "listeners", /* @__PURE__ */ new Set());
|
|
7
|
+
}
|
|
8
|
+
getCommentsFromStorage() {
|
|
9
|
+
const e = sessionStorage.getItem("ufp_comments");
|
|
10
|
+
return e ? JSON.parse(e) : [];
|
|
11
|
+
}
|
|
12
|
+
saveCommentsToStorage(e) {
|
|
13
|
+
sessionStorage.setItem("ufp_comments", JSON.stringify(e)), this.notifyListeners();
|
|
14
|
+
}
|
|
15
|
+
getRepliesFromStorage() {
|
|
16
|
+
const e = sessionStorage.getItem("ufp_replies");
|
|
17
|
+
return e ? JSON.parse(e) : [];
|
|
18
|
+
}
|
|
19
|
+
saveRepliesToStorage(e) {
|
|
20
|
+
sessionStorage.setItem("ufp_replies", JSON.stringify(e));
|
|
21
|
+
}
|
|
22
|
+
notifyListeners() {
|
|
23
|
+
const e = this.getCommentsFromStorage();
|
|
24
|
+
for (const t of this.listeners)
|
|
25
|
+
t(e);
|
|
26
|
+
}
|
|
27
|
+
async addComment(e) {
|
|
28
|
+
const t = this.getCommentsFromStorage(), s = Math.random().toString(36).substring(2, 9), o = { ...e, id: s };
|
|
29
|
+
return t.push(o), this.saveCommentsToStorage(t), s;
|
|
30
|
+
}
|
|
31
|
+
async getComments(e, t) {
|
|
32
|
+
return this.getCommentsFromStorage().filter((o) => o.pageUrl === e && o.projectKey === t);
|
|
33
|
+
}
|
|
34
|
+
async updateComment(e, t) {
|
|
35
|
+
const s = this.getCommentsFromStorage(), o = s.findIndex((m) => m.id === e);
|
|
36
|
+
o !== -1 && (s[o] = { ...s[o], ...t }, this.saveCommentsToStorage(s));
|
|
37
|
+
}
|
|
38
|
+
async deleteComment(e) {
|
|
39
|
+
const s = this.getCommentsFromStorage().filter((r) => r.id !== e);
|
|
40
|
+
this.saveCommentsToStorage(s);
|
|
41
|
+
const m = this.getRepliesFromStorage().filter((r) => r.commentId !== e);
|
|
42
|
+
this.saveRepliesToStorage(m);
|
|
43
|
+
}
|
|
44
|
+
async addReply(e) {
|
|
45
|
+
const t = this.getRepliesFromStorage(), s = Math.random().toString(36).substring(2, 9), o = { ...e, id: s };
|
|
46
|
+
return t.push(o), this.saveRepliesToStorage(t), s;
|
|
47
|
+
}
|
|
48
|
+
async getReplies(e) {
|
|
49
|
+
return this.getRepliesFromStorage().filter((s) => s.commentId === e);
|
|
50
|
+
}
|
|
51
|
+
subscribeToComments(e, t, s) {
|
|
52
|
+
const o = (m) => {
|
|
53
|
+
s(m.filter((r) => r.pageUrl === e && r.projectKey === t));
|
|
54
|
+
};
|
|
55
|
+
return this.listeners.add(o), o(this.getCommentsFromStorage()), () => {
|
|
56
|
+
this.listeners.delete(o);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async uploadScreenshot(e, t) {
|
|
60
|
+
return t;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export {
|
|
64
|
+
l as LocalAdapter
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=local-CqZPr-Eb.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-CqZPr-Eb.mjs","sources":["../src/adapters/local.ts"],"sourcesContent":["import type {\n FeedbackComment,\n Reply,\n DatabaseAdapter,\n ScreenshotAdapter,\n} from '../core/types'\n\nexport class LocalAdapter implements DatabaseAdapter, ScreenshotAdapter {\n private listeners: Set<(comments: FeedbackComment[]) => void> = new Set()\n\n private getCommentsFromStorage(): FeedbackComment[] {\n const data = sessionStorage.getItem('ufp_comments')\n return data ? JSON.parse(data) : []\n }\n\n private saveCommentsToStorage(comments: FeedbackComment[]) {\n sessionStorage.setItem('ufp_comments', JSON.stringify(comments))\n this.notifyListeners()\n }\n\n private getRepliesFromStorage(): Reply[] {\n const data = sessionStorage.getItem('ufp_replies')\n return data ? JSON.parse(data) : []\n }\n\n private saveRepliesToStorage(replies: Reply[]) {\n sessionStorage.setItem('ufp_replies', JSON.stringify(replies))\n }\n\n private notifyListeners() {\n const comments = this.getCommentsFromStorage()\n for (const listener of this.listeners) {\n listener(comments)\n }\n }\n\n async addComment(comment: Omit<FeedbackComment, 'id'>): Promise<string> {\n const comments = this.getCommentsFromStorage()\n const id = Math.random().toString(36).substring(2, 9)\n const newComment: FeedbackComment = { ...comment, id }\n comments.push(newComment)\n this.saveCommentsToStorage(comments)\n return id\n }\n\n async getComments(pageUrl: string, projectKey: string): Promise<FeedbackComment[]> {\n const comments = this.getCommentsFromStorage()\n return comments.filter(c => c.pageUrl === pageUrl && c.projectKey === projectKey)\n }\n\n async updateComment(id: string, data: Partial<FeedbackComment>): Promise<void> {\n const comments = this.getCommentsFromStorage()\n const index = comments.findIndex(c => c.id === id)\n if (index !== -1) {\n comments[index] = { ...comments[index], ...data }\n this.saveCommentsToStorage(comments)\n }\n }\n\n async deleteComment(id: string): Promise<void> {\n const comments = this.getCommentsFromStorage()\n const filtered = comments.filter(c => c.id !== id)\n this.saveCommentsToStorage(filtered)\n\n const replies = this.getRepliesFromStorage()\n const filteredReplies = replies.filter(r => r.commentId !== id)\n this.saveRepliesToStorage(filteredReplies)\n }\n\n async addReply(reply: Omit<Reply, 'id'>): Promise<string> {\n const replies = this.getRepliesFromStorage()\n const id = Math.random().toString(36).substring(2, 9)\n const newReply: Reply = { ...reply, id }\n replies.push(newReply)\n this.saveRepliesToStorage(replies)\n return id\n }\n\n async getReplies(commentId: string): Promise<Reply[]> {\n const replies = this.getRepliesFromStorage()\n return replies.filter(r => r.commentId === commentId)\n }\n\n subscribeToComments(\n pageUrl: string,\n projectKey: string,\n callback: (comments: FeedbackComment[]) => void\n ): () => void {\n const wrapper = (comments: FeedbackComment[]) => {\n callback(comments.filter(c => c.pageUrl === pageUrl && c.projectKey === projectKey))\n }\n this.listeners.add(wrapper)\n wrapper(this.getCommentsFromStorage())\n\n return () => {\n this.listeners.delete(wrapper)\n }\n }\n\n async uploadScreenshot(commentId: string, dataUrl: string): Promise<string> {\n // Return base64 URL directly, which gets stored in the comment's screenshotUrl.\n return dataUrl\n }\n}\n"],"names":["LocalAdapter","__publicField","data","comments","replies","listener","comment","id","newComment","pageUrl","projectKey","c","index","filtered","filteredReplies","reply","newReply","commentId","r","callback","wrapper","dataUrl"],"mappings":";;;AAOO,MAAMA,EAA2D;AAAA,EAAjE;AACG,IAAAC,EAAA,uCAA4D,IAAA;AAAA;AAAA,EAE5D,yBAA4C;AAClD,UAAMC,IAAO,eAAe,QAAQ,cAAc;AAClD,WAAOA,IAAO,KAAK,MAAMA,CAAI,IAAI,CAAA;AAAA,EACnC;AAAA,EAEQ,sBAAsBC,GAA6B;AACzD,mBAAe,QAAQ,gBAAgB,KAAK,UAAUA,CAAQ,CAAC,GAC/D,KAAK,gBAAA;AAAA,EACP;AAAA,EAEQ,wBAAiC;AACvC,UAAMD,IAAO,eAAe,QAAQ,aAAa;AACjD,WAAOA,IAAO,KAAK,MAAMA,CAAI,IAAI,CAAA;AAAA,EACnC;AAAA,EAEQ,qBAAqBE,GAAkB;AAC7C,mBAAe,QAAQ,eAAe,KAAK,UAAUA,CAAO,CAAC;AAAA,EAC/D;AAAA,EAEQ,kBAAkB;AACxB,UAAMD,IAAW,KAAK,uBAAA;AACtB,eAAWE,KAAY,KAAK;AAC1B,MAAAA,EAASF,CAAQ;AAAA,EAErB;AAAA,EAEA,MAAM,WAAWG,GAAuD;AACtE,UAAMH,IAAW,KAAK,uBAAA,GAChBI,IAAK,KAAK,SAAS,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC,GAC9CC,IAA8B,EAAE,GAAGF,GAAS,IAAAC,EAAA;AAClD,WAAAJ,EAAS,KAAKK,CAAU,GACxB,KAAK,sBAAsBL,CAAQ,GAC5BI;AAAA,EACT;AAAA,EAEA,MAAM,YAAYE,GAAiBC,GAAgD;AAEjF,WADiB,KAAK,uBAAA,EACN,OAAO,CAAAC,MAAKA,EAAE,YAAYF,KAAWE,EAAE,eAAeD,CAAU;AAAA,EAClF;AAAA,EAEA,MAAM,cAAcH,GAAYL,GAA+C;AAC7E,UAAMC,IAAW,KAAK,uBAAA,GAChBS,IAAQT,EAAS,UAAU,CAAAQ,MAAKA,EAAE,OAAOJ,CAAE;AACjD,IAAIK,MAAU,OACZT,EAASS,CAAK,IAAI,EAAE,GAAGT,EAASS,CAAK,GAAG,GAAGV,EAAA,GAC3C,KAAK,sBAAsBC,CAAQ;AAAA,EAEvC;AAAA,EAEA,MAAM,cAAcI,GAA2B;AAE7C,UAAMM,IADW,KAAK,uBAAA,EACI,OAAO,CAAAF,MAAKA,EAAE,OAAOJ,CAAE;AACjD,SAAK,sBAAsBM,CAAQ;AAGnC,UAAMC,IADU,KAAK,sBAAA,EACW,OAAO,CAAA,MAAK,EAAE,cAAcP,CAAE;AAC9D,SAAK,qBAAqBO,CAAe;AAAA,EAC3C;AAAA,EAEA,MAAM,SAASC,GAA2C;AACxD,UAAMX,IAAU,KAAK,sBAAA,GACfG,IAAK,KAAK,SAAS,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC,GAC9CS,IAAkB,EAAE,GAAGD,GAAO,IAAAR,EAAA;AACpC,WAAAH,EAAQ,KAAKY,CAAQ,GACrB,KAAK,qBAAqBZ,CAAO,GAC1BG;AAAA,EACT;AAAA,EAEA,MAAM,WAAWU,GAAqC;AAEpD,WADgB,KAAK,sBAAA,EACN,OAAO,CAAAC,MAAKA,EAAE,cAAcD,CAAS;AAAA,EACtD;AAAA,EAEA,oBACER,GACAC,GACAS,GACY;AACZ,UAAMC,IAAU,CAACjB,MAAgC;AAC/C,MAAAgB,EAAShB,EAAS,OAAO,CAAAQ,MAAKA,EAAE,YAAYF,KAAWE,EAAE,eAAeD,CAAU,CAAC;AAAA,IACrF;AACA,gBAAK,UAAU,IAAIU,CAAO,GAC1BA,EAAQ,KAAK,wBAAwB,GAE9B,MAAM;AACX,WAAK,UAAU,OAAOA,CAAO;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiBH,GAAmBI,GAAkC;AAE1E,WAAOA;AAAA,EACT;AACF;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
var K = Object.defineProperty;
|
|
2
|
-
var J = (e, t,
|
|
3
|
-
var H = (e, t,
|
|
2
|
+
var J = (e, t, r) => t in e ? K(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
|
|
3
|
+
var H = (e, t, r) => J(e, typeof t != "symbol" ? t + "" : t, r);
|
|
4
4
|
const O = /* @__PURE__ */ new Set();
|
|
5
5
|
let T = {
|
|
6
6
|
active: !1,
|
|
@@ -18,7 +18,7 @@ function L() {
|
|
|
18
18
|
function y(e) {
|
|
19
19
|
T = { ...T, ...e }, O.forEach((t) => t(T));
|
|
20
20
|
}
|
|
21
|
-
function
|
|
21
|
+
function _(e) {
|
|
22
22
|
return O.add(e), () => O.delete(e);
|
|
23
23
|
}
|
|
24
24
|
function X() {
|
|
@@ -598,9 +598,9 @@ const Z = {
|
|
|
598
598
|
"top-right": { top: "24px", right: "24px" },
|
|
599
599
|
"top-left": { top: "24px", left: "24px" }
|
|
600
600
|
}, $ = "#6366f1", U = "#4f46e5", j = "#4338ca";
|
|
601
|
-
function ee(e, t,
|
|
602
|
-
const
|
|
603
|
-
Object.assign(
|
|
601
|
+
function ee(e, t, r, n) {
|
|
602
|
+
const o = document.createElement("div");
|
|
603
|
+
Object.assign(o.style, {
|
|
604
604
|
position: "fixed",
|
|
605
605
|
zIndex: "2147483647",
|
|
606
606
|
display: "flex",
|
|
@@ -627,18 +627,18 @@ function ee(e, t, o, n) {
|
|
|
627
627
|
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
|
|
628
628
|
</svg>
|
|
629
629
|
<span id="ufp-panel-count" style="font-size:13px;font-weight:600;min-width:8px;text-align:center;"></span>
|
|
630
|
-
`,
|
|
631
|
-
const p =
|
|
630
|
+
`, o.appendChild(a), o.appendChild(d), o.appendChild(l), e.appendChild(o);
|
|
631
|
+
const p = o.querySelector("#ufp-annotate-label"), s = o.querySelector("#ufp-panel-count");
|
|
632
632
|
return a.addEventListener("click", (i) => {
|
|
633
|
-
if (i.stopPropagation(),
|
|
633
|
+
if (i.stopPropagation(), o._dragged) return;
|
|
634
634
|
const u = L();
|
|
635
|
-
u.active || (u.panelOpen ? (n(), setTimeout(
|
|
635
|
+
u.active || (u.panelOpen ? (n(), setTimeout(r, 220)) : r());
|
|
636
636
|
}), l.addEventListener("click", (i) => {
|
|
637
|
-
i.stopPropagation(), !
|
|
638
|
-
}),
|
|
637
|
+
i.stopPropagation(), !o._dragged && (L().active || n());
|
|
638
|
+
}), P(a, () => (L().panelOpen, $), U), P(l, () => L().panelOpen ? j : $, U), _((i) => {
|
|
639
639
|
const u = i.comments.filter((w) => !w.resolved).length;
|
|
640
640
|
s.textContent = u > 0 ? String(u) : "", i.active ? (p.textContent = "Drawing…", a.style.opacity = "0.65", l.style.opacity = "0.65", a.style.pointerEvents = "none", l.style.pointerEvents = "none") : (p.textContent = "Feedback", a.style.opacity = "1", l.style.opacity = "1", a.style.pointerEvents = "auto", l.style.pointerEvents = "auto"), l.style.background = i.panelOpen ? j : $;
|
|
641
|
-
}), te(
|
|
641
|
+
}), te(o), o;
|
|
642
642
|
}
|
|
643
643
|
function D(e) {
|
|
644
644
|
Object.assign(e.style, {
|
|
@@ -654,23 +654,23 @@ function D(e) {
|
|
|
654
654
|
transition: "background 0.12s"
|
|
655
655
|
});
|
|
656
656
|
}
|
|
657
|
-
function
|
|
657
|
+
function P(e, t, r) {
|
|
658
658
|
e.addEventListener("mouseenter", () => {
|
|
659
|
-
e.style.background =
|
|
659
|
+
e.style.background = r;
|
|
660
660
|
}), e.addEventListener("mouseleave", () => {
|
|
661
661
|
e.style.background = t();
|
|
662
662
|
});
|
|
663
663
|
}
|
|
664
664
|
function te(e) {
|
|
665
|
-
let t = 0,
|
|
665
|
+
let t = 0, r = 0, n = 0, o = 0;
|
|
666
666
|
e.addEventListener("pointerdown", (a) => {
|
|
667
667
|
if (a.button !== 0) return;
|
|
668
|
-
t = a.clientX,
|
|
668
|
+
t = a.clientX, r = a.clientY;
|
|
669
669
|
const d = e.getBoundingClientRect();
|
|
670
|
-
n = d.left,
|
|
670
|
+
n = d.left, o = d.top, e._dragged = !1;
|
|
671
671
|
const l = (s) => {
|
|
672
|
-
const i = s.clientX - t, u = s.clientY -
|
|
673
|
-
!e._dragged && Math.sqrt(i * i + u * u) < 5 || (e._dragged = !0, e.style.left = `${Math.max(0, Math.min(window.innerWidth - e.offsetWidth, n + i))}px`, e.style.top = `${Math.max(0, Math.min(window.innerHeight - e.offsetHeight,
|
|
672
|
+
const i = s.clientX - t, u = s.clientY - r;
|
|
673
|
+
!e._dragged && Math.sqrt(i * i + u * u) < 5 || (e._dragged = !0, e.style.left = `${Math.max(0, Math.min(window.innerWidth - e.offsetWidth, n + i))}px`, e.style.top = `${Math.max(0, Math.min(window.innerHeight - e.offsetHeight, o + u))}px`, e.style.right = "auto", e.style.bottom = "auto");
|
|
674
674
|
}, p = () => {
|
|
675
675
|
document.removeEventListener("pointermove", l), document.removeEventListener("pointerup", p), requestAnimationFrame(() => {
|
|
676
676
|
e._dragged = !1;
|
|
@@ -681,8 +681,8 @@ function te(e) {
|
|
|
681
681
|
}
|
|
682
682
|
function ne(e) {
|
|
683
683
|
return new Promise((t) => {
|
|
684
|
-
const
|
|
685
|
-
|
|
684
|
+
const r = document.createElement("div");
|
|
685
|
+
r.className = "ufp-modal-backdrop", r.innerHTML = `
|
|
686
686
|
<div class="ufp-modal" role="dialog" aria-modal="true" aria-labelledby="ufp-modal-title">
|
|
687
687
|
<h2 id="ufp-modal-title">Welcome to Feedback Mode</h2>
|
|
688
688
|
<p>Enter your name so others can see who left the comment.</p>
|
|
@@ -698,43 +698,43 @@ function ne(e) {
|
|
|
698
698
|
<button class="ufp-btn ufp-btn-primary" id="ufp-name-submit" disabled>Continue</button>
|
|
699
699
|
</div>
|
|
700
700
|
</div>
|
|
701
|
-
`, e.appendChild(
|
|
702
|
-
const n =
|
|
701
|
+
`, e.appendChild(r);
|
|
702
|
+
const n = r.querySelector("#ufp-name-input"), o = r.querySelector("#ufp-name-submit");
|
|
703
703
|
n.addEventListener("input", () => {
|
|
704
|
-
|
|
704
|
+
o.disabled = n.value.trim().length === 0;
|
|
705
705
|
});
|
|
706
706
|
const a = () => {
|
|
707
707
|
const d = n.value.trim();
|
|
708
|
-
d && (Y(d),
|
|
708
|
+
d && (Y(d), r.remove(), t(d));
|
|
709
709
|
};
|
|
710
|
-
|
|
710
|
+
o.addEventListener("click", a), n.addEventListener("keydown", (d) => {
|
|
711
711
|
d.key === "Enter" && a();
|
|
712
712
|
}), requestAnimationFrame(() => n.focus());
|
|
713
713
|
});
|
|
714
714
|
}
|
|
715
715
|
const C = "#6366f1", M = 3;
|
|
716
|
-
function z(e, t = 1,
|
|
716
|
+
function z(e, t = 1, r = 1) {
|
|
717
717
|
switch (e.type) {
|
|
718
718
|
case "pen": {
|
|
719
719
|
const n = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
720
|
-
return n.setAttribute("d", oe(e.points, t,
|
|
720
|
+
return n.setAttribute("d", oe(e.points, t, r)), n.setAttribute("stroke", e.color), n.setAttribute("stroke-width", String(e.width * Math.min(t, r))), n.setAttribute("fill", "none"), n.setAttribute("stroke-linecap", "round"), n.setAttribute("stroke-linejoin", "round"), n;
|
|
721
721
|
}
|
|
722
722
|
case "rect": {
|
|
723
723
|
const n = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
724
|
-
return n.setAttribute("x", String(e.x * t)), n.setAttribute("y", String(e.y *
|
|
724
|
+
return n.setAttribute("x", String(e.x * t)), n.setAttribute("y", String(e.y * r)), n.setAttribute("width", String(e.width * t)), n.setAttribute("height", String(e.height * r)), n.setAttribute("stroke", e.color), n.setAttribute("stroke-width", String(e.strokeWidth * Math.min(t, r))), n.setAttribute("fill", "none"), n.setAttribute("rx", "3"), n;
|
|
725
725
|
}
|
|
726
726
|
case "circle": {
|
|
727
727
|
const n = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
|
|
728
|
-
return n.setAttribute("cx", String(e.cx * t)), n.setAttribute("cy", String(e.cy *
|
|
728
|
+
return n.setAttribute("cx", String(e.cx * t)), n.setAttribute("cy", String(e.cy * r)), n.setAttribute("rx", String(e.rx * t)), n.setAttribute("ry", String(e.ry * r)), n.setAttribute("stroke", e.color), n.setAttribute("stroke-width", String(e.strokeWidth * Math.min(t, r))), n.setAttribute("fill", "none"), n;
|
|
729
729
|
}
|
|
730
730
|
case "arrow": {
|
|
731
|
-
const n = document.createElementNS("http://www.w3.org/2000/svg", "g"),
|
|
732
|
-
return
|
|
731
|
+
const n = document.createElementNS("http://www.w3.org/2000/svg", "g"), o = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
|
732
|
+
return o.setAttribute("x1", String(e.x1 * t)), o.setAttribute("y1", String(e.y1 * r)), o.setAttribute("x2", String(e.x2 * t)), o.setAttribute("y2", String(e.y2 * r)), o.setAttribute("stroke", e.color), o.setAttribute("stroke-width", String(e.width * Math.min(t, r))), o.setAttribute("marker-end", "url(#ufp-arrowhead)"), n.appendChild(o), n;
|
|
733
733
|
}
|
|
734
734
|
}
|
|
735
735
|
}
|
|
736
|
-
function re(e, t,
|
|
737
|
-
const
|
|
736
|
+
function re(e, t, r, n) {
|
|
737
|
+
const o = r / t.pageWidth, a = n / t.pageHeight;
|
|
738
738
|
e.innerHTML = "";
|
|
739
739
|
const d = document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
|
740
740
|
d.innerHTML = `
|
|
@@ -742,25 +742,25 @@ function re(e, t, o, n) {
|
|
|
742
742
|
<polygon points="0 0, 10 3.5, 0 7" fill="${C}" />
|
|
743
743
|
</marker>
|
|
744
744
|
`, e.appendChild(d), t.shapes.forEach((l) => {
|
|
745
|
-
e.appendChild(z(l,
|
|
745
|
+
e.appendChild(z(l, o, a));
|
|
746
746
|
});
|
|
747
747
|
}
|
|
748
|
-
function oe(e, t,
|
|
748
|
+
function oe(e, t, r) {
|
|
749
749
|
if (e.length === 0) return "";
|
|
750
750
|
if (e.length === 1) {
|
|
751
|
-
const
|
|
752
|
-
return `M ${
|
|
751
|
+
const o = e[0];
|
|
752
|
+
return `M ${o.x * t} ${o.y * r}`;
|
|
753
753
|
}
|
|
754
|
-
let n = `M ${e[0].x * t} ${e[0].y *
|
|
755
|
-
for (let
|
|
756
|
-
n += ` L ${e[
|
|
754
|
+
let n = `M ${e[0].x * t} ${e[0].y * r}`;
|
|
755
|
+
for (let o = 1; o < e.length; o++)
|
|
756
|
+
n += ` L ${e[o].x * t} ${e[o].y * r}`;
|
|
757
757
|
return n;
|
|
758
758
|
}
|
|
759
759
|
function ie(e) {
|
|
760
760
|
return new Promise((t) => {
|
|
761
|
-
let
|
|
761
|
+
let r = "pen";
|
|
762
762
|
const n = [];
|
|
763
|
-
let
|
|
763
|
+
let o = !1, a = 0, d = 0, l = [], p = null, s = null;
|
|
764
764
|
const i = document.createElement("div");
|
|
765
765
|
i.style.cssText = "position:fixed;inset:0;z-index:2147483645;cursor:crosshair;background:rgba(99,102,241,0.04);";
|
|
766
766
|
const u = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
@@ -836,7 +836,7 @@ function ie(e) {
|
|
|
836
836
|
const b = ae(
|
|
837
837
|
e,
|
|
838
838
|
(m) => {
|
|
839
|
-
|
|
839
|
+
r = m;
|
|
840
840
|
},
|
|
841
841
|
() => {
|
|
842
842
|
w(), t(null);
|
|
@@ -846,41 +846,41 @@ function ie(e) {
|
|
|
846
846
|
}
|
|
847
847
|
);
|
|
848
848
|
e.appendChild(i), i.addEventListener("pointerdown", (m) => {
|
|
849
|
-
m.button === 0 && (i.setPointerCapture(m.pointerId),
|
|
849
|
+
m.button === 0 && (i.setPointerCapture(m.pointerId), o = !0, a = m.clientX + window.scrollX, d = m.clientY + window.scrollY, r === "pen" && (l = [{ x: a, y: d }]));
|
|
850
850
|
}), i.addEventListener("pointermove", (m) => {
|
|
851
|
-
if (!
|
|
851
|
+
if (!o) return;
|
|
852
852
|
const x = m.clientX + window.scrollX, g = m.clientY + window.scrollY;
|
|
853
|
-
if (p && p.remove(),
|
|
853
|
+
if (p && p.remove(), r === "pen")
|
|
854
854
|
l.push({ x, y: g }), p = z({ type: "pen", points: [...l], color: C, width: M });
|
|
855
|
-
else if (
|
|
855
|
+
else if (r === "rect") {
|
|
856
856
|
const c = { type: "rect", x: Math.min(a, x), y: Math.min(d, g), width: Math.abs(x - a), height: Math.abs(g - d), color: C, strokeWidth: M };
|
|
857
857
|
p = z(c);
|
|
858
|
-
} else if (
|
|
858
|
+
} else if (r === "circle") {
|
|
859
859
|
const c = Math.abs(x - a) / 2, v = Math.abs(g - d) / 2, S = { type: "circle", cx: Math.min(a, x) + c, cy: Math.min(d, g) + v, rx: c, ry: v, color: C, strokeWidth: M };
|
|
860
860
|
p = z(S);
|
|
861
|
-
} else
|
|
861
|
+
} else r === "arrow" && (p = z({ type: "arrow", x1: a, y1: d, x2: x, y2: g, color: C, width: M }));
|
|
862
862
|
p && u.appendChild(p);
|
|
863
863
|
}), i.addEventListener("pointerup", (m) => {
|
|
864
|
-
if (!
|
|
865
|
-
|
|
864
|
+
if (!o) return;
|
|
865
|
+
o = !1, p && (p.remove(), p = null);
|
|
866
866
|
const x = m.clientX + window.scrollX, g = m.clientY + window.scrollY;
|
|
867
867
|
let c = !1;
|
|
868
|
-
if (
|
|
868
|
+
if (r === "pen" && l.length > 1)
|
|
869
869
|
n.push({ type: "pen", points: [...l], color: C, width: M }), l = [], c = !0;
|
|
870
|
-
else if (
|
|
870
|
+
else if (r === "rect") {
|
|
871
871
|
const v = Math.abs(x - a), S = Math.abs(g - d);
|
|
872
872
|
v > 4 && S > 4 && (n.push({ type: "rect", x: Math.min(a, x), y: Math.min(d, g), width: v, height: S, color: C, strokeWidth: M }), c = !0);
|
|
873
|
-
} else if (
|
|
873
|
+
} else if (r === "circle") {
|
|
874
874
|
const v = Math.abs(x - a) / 2, S = Math.abs(g - d) / 2;
|
|
875
875
|
v > 4 && S > 4 && (n.push({ type: "circle", cx: Math.min(a, x) + v, cy: Math.min(d, g) + S, rx: v, ry: S, color: C, strokeWidth: M }), c = !0);
|
|
876
|
-
} else
|
|
876
|
+
} else r === "arrow" && Math.sqrt((x - a) ** 2 + (g - d) ** 2) > 10 && (n.push({ type: "arrow", x1: a, y1: d, x2: x, y2: g, color: C, width: M }), c = !0);
|
|
877
877
|
c && (h(), E());
|
|
878
878
|
});
|
|
879
879
|
});
|
|
880
880
|
}
|
|
881
|
-
function ae(e, t,
|
|
882
|
-
const
|
|
883
|
-
return
|
|
881
|
+
function ae(e, t, r, n) {
|
|
882
|
+
const o = document.createElement("div");
|
|
883
|
+
return o.className = "ufp-toolbar", o.innerHTML = `
|
|
884
884
|
<span class="ufp-toolbar-label">Draw to annotate</span>
|
|
885
885
|
<div class="ufp-toolbar-sep"></div>
|
|
886
886
|
<button class="ufp-btn-icon active" data-tool="pen" title="Pen">
|
|
@@ -907,20 +907,20 @@ function ae(e, t, o, n) {
|
|
|
907
907
|
</button>
|
|
908
908
|
<div class="ufp-toolbar-sep"></div>
|
|
909
909
|
<button class="ufp-btn ufp-btn-ghost" id="ufp-cancel-btn">Cancel</button>
|
|
910
|
-
`,
|
|
910
|
+
`, o.querySelectorAll("[data-tool]").forEach((a) => {
|
|
911
911
|
a.addEventListener("click", () => {
|
|
912
|
-
|
|
912
|
+
o.querySelectorAll("[data-tool]").forEach((d) => d.classList.remove("active")), a.classList.add("active"), t(a.dataset.tool);
|
|
913
913
|
});
|
|
914
|
-
}),
|
|
914
|
+
}), o.querySelector("#ufp-undo-btn").addEventListener("click", n), o.querySelector("#ufp-cancel-btn").addEventListener("click", r), e.appendChild(o), o;
|
|
915
915
|
}
|
|
916
916
|
function W(e) {
|
|
917
|
-
const t = Date.now() - e,
|
|
918
|
-
if (
|
|
919
|
-
const n = Math.floor(
|
|
917
|
+
const t = Date.now() - e, r = Math.floor(t / 1e3);
|
|
918
|
+
if (r < 60) return "just now";
|
|
919
|
+
const n = Math.floor(r / 60);
|
|
920
920
|
if (n < 60) return `${n}m ago`;
|
|
921
|
-
const
|
|
922
|
-
if (
|
|
923
|
-
const a = Math.floor(
|
|
921
|
+
const o = Math.floor(n / 60);
|
|
922
|
+
if (o < 24) return `${o}h ago`;
|
|
923
|
+
const a = Math.floor(o / 24);
|
|
924
924
|
return a < 7 ? `${a}d ago` : new Date(e).toLocaleDateString();
|
|
925
925
|
}
|
|
926
926
|
function F(e) {
|
|
@@ -929,8 +929,8 @@ function F(e) {
|
|
|
929
929
|
function A(e) {
|
|
930
930
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
931
931
|
}
|
|
932
|
-
function se(e, t,
|
|
933
|
-
let
|
|
932
|
+
function se(e, t, r, n) {
|
|
933
|
+
let o = [...t];
|
|
934
934
|
const a = document.createElement("div");
|
|
935
935
|
a.className = "ufp-replies";
|
|
936
936
|
const d = (h) => {
|
|
@@ -992,16 +992,16 @@ function se(e, t, o, n) {
|
|
|
992
992
|
createdAt: Date.now()
|
|
993
993
|
};
|
|
994
994
|
try {
|
|
995
|
-
const b = { id: await
|
|
996
|
-
i.value = "", u.textContent = "Reply", u.disabled = !0,
|
|
995
|
+
const b = { id: await r.addReply(E), ...E };
|
|
996
|
+
i.value = "", u.textContent = "Reply", u.disabled = !0, o = [...o, b], d(o), n(b);
|
|
997
997
|
} catch (f) {
|
|
998
998
|
console.error("[ui-feedback-plugin] Failed to save reply:", f), u.disabled = !1, u.textContent = "Reply";
|
|
999
999
|
}
|
|
1000
|
-
}), a.appendChild(l), d(
|
|
1001
|
-
|
|
1000
|
+
}), a.appendChild(l), d(o), a.addReply = (h) => {
|
|
1001
|
+
o = [...o, h], d(o);
|
|
1002
1002
|
}, a;
|
|
1003
1003
|
}
|
|
1004
|
-
function le(e, t,
|
|
1004
|
+
function le(e, t, r, n, o, a, d, l) {
|
|
1005
1005
|
const p = document.createElement("div");
|
|
1006
1006
|
p.className = "ufp-detail", p.innerHTML = `
|
|
1007
1007
|
<div class="ufp-detail-image-area">
|
|
@@ -1066,14 +1066,14 @@ function le(e, t, o, n, r, a, d, l) {
|
|
|
1066
1066
|
style="vertical-align:middle;margin-right:4px"><polyline points="20 6 9 17 4 12"/></svg>
|
|
1067
1067
|
Mark Resolved
|
|
1068
1068
|
`, f.addEventListener("click", async () => {
|
|
1069
|
-
f.disabled = !0, f.textContent = "Resolving…", await n.updateComment(t.id, { resolved: !0 }),
|
|
1069
|
+
f.disabled = !0, f.textContent = "Resolving…", await n.updateComment(t.id, { resolved: !0 }), o(t.id), p.remove(), y({ panelOpen: !0 });
|
|
1070
1070
|
}), s.appendChild(f);
|
|
1071
1071
|
}
|
|
1072
1072
|
const i = document.createElement("button");
|
|
1073
1073
|
i.className = "ufp-btn ufp-btn-ghost", i.style.fontSize = "13px", i.textContent = "Delete", i.addEventListener("click", async () => {
|
|
1074
1074
|
confirm("Delete this comment and all its replies?") && (i.disabled = !0, await n.deleteComment(t.id), d(t.id), p.remove(), y({ panelOpen: !0 }));
|
|
1075
1075
|
}), s.appendChild(i);
|
|
1076
|
-
const u = p.querySelector("#ufp-detail-replies"), w = se(t.id,
|
|
1076
|
+
const u = p.querySelector("#ufp-detail-replies"), w = se(t.id, r, n, (f) => {
|
|
1077
1077
|
var b;
|
|
1078
1078
|
(b = w.addReply) == null || b.call(w, f), l == null || l(f);
|
|
1079
1079
|
});
|
|
@@ -1086,7 +1086,7 @@ function le(e, t, o, n, r, a, d, l) {
|
|
|
1086
1086
|
};
|
|
1087
1087
|
h.complete && h.naturalWidth > 0 ? E() : h.addEventListener("load", E);
|
|
1088
1088
|
}
|
|
1089
|
-
function pe(e, t,
|
|
1089
|
+
function pe(e, t, r) {
|
|
1090
1090
|
const n = document.createElement("div");
|
|
1091
1091
|
n.className = "ufp-panel", n.innerHTML = `
|
|
1092
1092
|
<div class="ufp-panel-header">
|
|
@@ -1111,16 +1111,16 @@ function pe(e, t, o) {
|
|
|
1111
1111
|
`, e.appendChild(n), n.querySelector("#ufp-panel-close").addEventListener("click", () => {
|
|
1112
1112
|
y({ panelOpen: !1 });
|
|
1113
1113
|
}), n.querySelector("#ufp-new-feedback").addEventListener("click", () => {
|
|
1114
|
-
y({ panelOpen: !1 }),
|
|
1114
|
+
y({ panelOpen: !1 }), r();
|
|
1115
1115
|
}), n.querySelectorAll(".ufp-filter-tab").forEach((l) => {
|
|
1116
1116
|
l.addEventListener("click", () => {
|
|
1117
1117
|
n.querySelectorAll(".ufp-filter-tab").forEach((p) => p.classList.remove("active")), l.classList.add("active"), y({ filter: l.dataset.filter });
|
|
1118
1118
|
});
|
|
1119
1119
|
});
|
|
1120
|
-
const
|
|
1120
|
+
const o = n.querySelector("#ufp-comment-list"), a = /* @__PURE__ */ new Map(), d = async (l, p) => {
|
|
1121
1121
|
const s = l.filter((i) => p === "open" ? !i.resolved : i.resolved);
|
|
1122
|
-
if (
|
|
1123
|
-
|
|
1122
|
+
if (o.innerHTML = "", s.length === 0) {
|
|
1123
|
+
o.innerHTML = `
|
|
1124
1124
|
<div class="ufp-panel-empty">
|
|
1125
1125
|
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" opacity="0.4">
|
|
1126
1126
|
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
|
|
@@ -1138,16 +1138,16 @@ function pe(e, t, o) {
|
|
|
1138
1138
|
} catch {
|
|
1139
1139
|
a.set(i.id, []);
|
|
1140
1140
|
}
|
|
1141
|
-
|
|
1141
|
+
o.appendChild(
|
|
1142
1142
|
de(i, a, e, t)
|
|
1143
1143
|
);
|
|
1144
1144
|
}
|
|
1145
1145
|
};
|
|
1146
|
-
return
|
|
1146
|
+
return _(async (l) => {
|
|
1147
1147
|
n.classList.toggle("open", l.panelOpen), l.panelOpen && await d(l.comments, l.filter);
|
|
1148
1148
|
}), n;
|
|
1149
1149
|
}
|
|
1150
|
-
function de(e, t,
|
|
1150
|
+
function de(e, t, r, n, o) {
|
|
1151
1151
|
const a = t.get(e.id) ?? [], d = document.createElement("div");
|
|
1152
1152
|
return d.className = "ufp-comment-card", d.dataset.id = e.id, d.innerHTML = `
|
|
1153
1153
|
<div class="ufp-comment-card-header">
|
|
@@ -1175,7 +1175,7 @@ function de(e, t, o, n, r) {
|
|
|
1175
1175
|
console.error("[ui-feedback-plugin] Failed to fetch replies:", p);
|
|
1176
1176
|
}
|
|
1177
1177
|
le(
|
|
1178
|
-
|
|
1178
|
+
r,
|
|
1179
1179
|
e,
|
|
1180
1180
|
l,
|
|
1181
1181
|
n,
|
|
@@ -1205,19 +1205,19 @@ async function ce() {
|
|
|
1205
1205
|
try {
|
|
1206
1206
|
const e = await ue();
|
|
1207
1207
|
return await fe(e);
|
|
1208
|
-
} catch {
|
|
1209
|
-
return me();
|
|
1208
|
+
} catch (e) {
|
|
1209
|
+
return console.error("[ui-feedback-plugin] capturePageScreenshot failed:", e), me();
|
|
1210
1210
|
}
|
|
1211
1211
|
}
|
|
1212
1212
|
async function ue() {
|
|
1213
1213
|
return (await import("./html2canvas-pro.esm-QETbiPYt.mjs")).default;
|
|
1214
1214
|
}
|
|
1215
1215
|
async function fe(e) {
|
|
1216
|
-
const t = window.scrollX,
|
|
1216
|
+
const t = window.scrollX, r = window.scrollY;
|
|
1217
1217
|
window.scrollTo(0, 0);
|
|
1218
1218
|
try {
|
|
1219
1219
|
return (await e(document.body, {
|
|
1220
|
-
allowTaint: !
|
|
1220
|
+
allowTaint: !1,
|
|
1221
1221
|
useCORS: !0,
|
|
1222
1222
|
logging: !1,
|
|
1223
1223
|
scale: Math.min(window.devicePixelRatio, 2),
|
|
@@ -1227,10 +1227,10 @@ async function fe(e) {
|
|
|
1227
1227
|
windowHeight: document.documentElement.scrollHeight,
|
|
1228
1228
|
x: 0,
|
|
1229
1229
|
y: 0,
|
|
1230
|
-
ignoreElements: (
|
|
1230
|
+
ignoreElements: (o) => o.tagName === "UI-FEEDBACK-PLUGIN"
|
|
1231
1231
|
})).toDataURL("image/png");
|
|
1232
1232
|
} finally {
|
|
1233
|
-
window.scrollTo(t,
|
|
1233
|
+
window.scrollTo(t, r);
|
|
1234
1234
|
}
|
|
1235
1235
|
}
|
|
1236
1236
|
function me() {
|
|
@@ -1243,15 +1243,19 @@ const q = "ui-feedback-plugin";
|
|
|
1243
1243
|
async function he(e) {
|
|
1244
1244
|
const { backend: t } = e;
|
|
1245
1245
|
if (t.provider === "firebase") {
|
|
1246
|
-
const { FirebaseAdapter:
|
|
1246
|
+
const { FirebaseAdapter: r } = await import("./firebase-BGU5KpRU.mjs"), n = new r(t);
|
|
1247
1247
|
return { db: n, screenshot: n };
|
|
1248
1248
|
}
|
|
1249
1249
|
if (t.provider === "supabase") {
|
|
1250
|
-
const { SupabaseAdapter:
|
|
1250
|
+
const { SupabaseAdapter: r } = await import("./supabase-CbB80UVb.mjs"), n = new r(t.url, t.anonKey);
|
|
1251
1251
|
return { db: n, screenshot: n };
|
|
1252
1252
|
}
|
|
1253
1253
|
if (t.provider === "aws") {
|
|
1254
|
-
const { AWSAdapter:
|
|
1254
|
+
const { AWSAdapter: r } = await import("./aws-CkWYvUhs.mjs"), n = new r(t);
|
|
1255
|
+
return { db: n, screenshot: n };
|
|
1256
|
+
}
|
|
1257
|
+
if (t.provider === "local") {
|
|
1258
|
+
const { LocalAdapter: r } = await import("./local-CqZPr-Eb.mjs"), n = new r();
|
|
1255
1259
|
return { db: n, screenshot: n };
|
|
1256
1260
|
}
|
|
1257
1261
|
throw new Error("[ui-feedback-plugin] Unknown backend provider");
|
|
@@ -1261,9 +1265,9 @@ function xe(e) {
|
|
|
1261
1265
|
if (customElements.get(q))
|
|
1262
1266
|
return console.warn("[ui-feedback-plugin] Already initialized."), () => {
|
|
1263
1267
|
};
|
|
1264
|
-
const t = ((d = e.theme) == null ? void 0 : d.primaryColor) ?? "#6366f1",
|
|
1268
|
+
const t = ((d = e.theme) == null ? void 0 : d.primaryColor) ?? "#6366f1", r = e.projectKey ?? "default", n = e.position ?? "bottom-right";
|
|
1265
1269
|
y({ config: e });
|
|
1266
|
-
class
|
|
1270
|
+
class o extends HTMLElement {
|
|
1267
1271
|
constructor() {
|
|
1268
1272
|
super();
|
|
1269
1273
|
H(this, "shadow");
|
|
@@ -1295,7 +1299,7 @@ function xe(e) {
|
|
|
1295
1299
|
n,
|
|
1296
1300
|
() => this.startAnnotation(),
|
|
1297
1301
|
() => y({ panelOpen: !L().panelOpen })
|
|
1298
|
-
), this.unsubscribe = this.db.subscribeToComments(s,
|
|
1302
|
+
), this.unsubscribe = this.db.subscribeToComments(s, r, (i) => {
|
|
1299
1303
|
y({ comments: i });
|
|
1300
1304
|
});
|
|
1301
1305
|
}
|
|
@@ -1333,7 +1337,7 @@ function xe(e) {
|
|
|
1333
1337
|
}
|
|
1334
1338
|
const E = {
|
|
1335
1339
|
pageUrl: w,
|
|
1336
|
-
projectKey:
|
|
1340
|
+
projectKey: r,
|
|
1337
1341
|
authorName: s,
|
|
1338
1342
|
text: i,
|
|
1339
1343
|
screenshotUrl: "",
|
|
@@ -1357,7 +1361,7 @@ function xe(e) {
|
|
|
1357
1361
|
`, h.textContent = s, this.shadow.appendChild(h), setTimeout(() => h.remove(), i === "error" ? 6e3 : 2500);
|
|
1358
1362
|
}
|
|
1359
1363
|
}
|
|
1360
|
-
customElements.define(q,
|
|
1364
|
+
customElements.define(q, o);
|
|
1361
1365
|
const a = document.createElement(q);
|
|
1362
1366
|
return document.body.appendChild(a), () => a.remove();
|
|
1363
1367
|
}
|