@qaiddev/thumbs-embed 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -3
- package/dist/annotate.d.ts +9 -1
- package/dist/chunks/{annotate-BNibaDg3.js → annotate-pSxJNPPL.js} +154 -102
- package/dist/chunks/annotate-pSxJNPPL.js.map +1 -0
- package/dist/chunks/{bootstrap-U4yiPm5-.js → bootstrap-rINL2pCt.js} +280 -254
- package/dist/chunks/bootstrap-rINL2pCt.js.map +1 -0
- package/dist/chunks/{modal-BX5wqy4s.js → modal-Br-8TcEE.js} +30 -30
- package/dist/chunks/modal-Br-8TcEE.js.map +1 -0
- package/dist/chunks/{recording--IwOtRL2.js → recording-BRvu1Vkh.js} +2 -2
- package/dist/chunks/{recording--IwOtRL2.js.map → recording-BRvu1Vkh.js.map} +1 -1
- package/dist/chunks/{targeting-DwdDr9Cm.js → targeting-_aii7qgw.js} +2 -2
- package/dist/chunks/targeting-_aii7qgw.js.map +1 -0
- package/dist/{auto.d.ts → embed-loader.d.ts} +7 -4
- package/dist/embed.js +2 -0
- package/dist/embed.js.map +1 -0
- package/dist/icons.d.ts +2 -0
- package/dist/index.js +3 -3
- package/dist/loader.js +2 -2
- package/dist/qaid.umd.cjs +19 -17
- package/dist/qaid.umd.cjs.map +1 -1
- package/dist/targeting.d.ts +3 -3
- package/dist/types.d.ts +39 -2
- package/package.json +4 -4
- package/dist/auto.js +0 -2
- package/dist/auto.js.map +0 -1
- package/dist/chunks/annotate-BNibaDg3.js.map +0 -1
- package/dist/chunks/bootstrap-U4yiPm5-.js.map +0 -1
- package/dist/chunks/modal-BX5wqy4s.js.map +0 -1
- package/dist/chunks/targeting-DwdDr9Cm.js.map +0 -1
package/README.md
CHANGED
|
@@ -26,13 +26,21 @@ const feedback = new QaidEmbed({
|
|
|
26
26
|
|
|
27
27
|
```html
|
|
28
28
|
<script
|
|
29
|
-
src="https://unpkg.com/@qaiddev/thumbs-embed/dist/
|
|
29
|
+
src="https://unpkg.com/@qaiddev/thumbs-embed/dist/embed.js"
|
|
30
30
|
data-endpoint="https://qaid.dev/api/feedback"
|
|
31
31
|
data-api-key="YOUR_API_KEY"
|
|
32
32
|
></script>
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
`embed.js` is a tiny classic loader that works in every browser: it feature-detects
|
|
36
|
+
ES-module support and pulls in the right build automatically — the **progressive
|
|
37
|
+
loader** (`loader.js`, a small core with screenshot/video/annotation/targeting loading
|
|
38
|
+
on demand) on modern browsers, or the all-in-one UMD bundle (`qaid.umd.cjs`) on older
|
|
39
|
+
ones. The injected build auto-initializes when it detects a `data-endpoint` attribute.
|
|
40
|
+
|
|
41
|
+
> Prefer to skip the loader's feature-detect hop? Point straight at
|
|
42
|
+
> `dist/loader.js` with `type="module"` (modern browsers only), or
|
|
43
|
+
> `dist/qaid.umd.cjs` as a classic script (works everywhere, no code-splitting).
|
|
36
44
|
|
|
37
45
|
### JSON Config (Script Tag)
|
|
38
46
|
|
|
@@ -55,7 +63,7 @@ For complex configurations, use a separate JSON config element:
|
|
|
55
63
|
}
|
|
56
64
|
}
|
|
57
65
|
</script>
|
|
58
|
-
<script src="https://unpkg.com/@qaiddev/thumbs-embed/dist/
|
|
66
|
+
<script src="https://unpkg.com/@qaiddev/thumbs-embed/dist/embed.js"></script>
|
|
59
67
|
```
|
|
60
68
|
|
|
61
69
|
## How It Works
|
package/dist/annotate.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export interface AnnotationLabels {
|
|
|
42
42
|
undo: string;
|
|
43
43
|
skip: string;
|
|
44
44
|
done: string;
|
|
45
|
+
colors: string;
|
|
45
46
|
}
|
|
46
47
|
/**
|
|
47
48
|
* Normalise two drag corners into a top-left origin plus positive width/height,
|
|
@@ -78,6 +79,8 @@ export interface AnnotationEditorOptions {
|
|
|
78
79
|
quality?: number;
|
|
79
80
|
/** Default stroke colour for rectangle/arrow/pen. */
|
|
80
81
|
color?: string;
|
|
82
|
+
/** Colour swatches offered in the toolbar. The active `color` is ensured present. */
|
|
83
|
+
palette?: string[];
|
|
81
84
|
/** Default stroke width. */
|
|
82
85
|
strokeWidth?: number;
|
|
83
86
|
/** Label overrides. */
|
|
@@ -104,7 +107,8 @@ export declare class AnnotationEditor {
|
|
|
104
107
|
tool: ShapeType;
|
|
105
108
|
private readonly opts;
|
|
106
109
|
private readonly labels;
|
|
107
|
-
private
|
|
110
|
+
private color;
|
|
111
|
+
private readonly palette;
|
|
108
112
|
private readonly strokeWidth;
|
|
109
113
|
private readonly uid;
|
|
110
114
|
private container;
|
|
@@ -121,6 +125,8 @@ export declare class AnnotationEditor {
|
|
|
121
125
|
/** Mount the editor and resolve when the user commits (Done) or skips. */
|
|
122
126
|
open(): Promise<string | null>;
|
|
123
127
|
private toolButton;
|
|
128
|
+
/** A round colour swatch button for the toolbar's colour group. */
|
|
129
|
+
private swatchButton;
|
|
124
130
|
private actionButton;
|
|
125
131
|
private mount;
|
|
126
132
|
/** Convert a pointer event's client coordinates into natural image pixels. */
|
|
@@ -129,6 +135,8 @@ export declare class AnnotationEditor {
|
|
|
129
135
|
redraw(): void;
|
|
130
136
|
/** Select the active drawing tool and reflect it on the toolbar. */
|
|
131
137
|
selectTool(tool: ShapeType): void;
|
|
138
|
+
/** Set the active drawing colour; subsequent shapes use it. */
|
|
139
|
+
selectColor(color: string): void;
|
|
132
140
|
private onToolbarClick;
|
|
133
141
|
onPointerDown: (e: PointerEvent) => void;
|
|
134
142
|
onPointerMove: (e: PointerEvent) => void;
|
|
@@ -1,44 +1,46 @@
|
|
|
1
|
-
const
|
|
1
|
+
const j = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
2
2
|
<path stroke-linecap="round" stroke-linejoin="round" d="M14 10h4.764a2 2 0 011.789 2.894l-3.5 7A2 2 0 0115.263 21h-4.017c-.163 0-.326-.02-.485-.06L7 20m7-10V5a2 2 0 00-2-2h-.095c-.5 0-.905.405-.905.905 0 .714-.211 1.412-.608 2.006L7 11v9m7-10h-2M7 20H5a2 2 0 01-2-2v-6a2 2 0 012-2h2.5"/>
|
|
3
|
-
</svg>`,
|
|
3
|
+
</svg>`, W = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
4
4
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10 14H5.236a2 2 0 01-1.789-2.894l3.5-7A2 2 0 018.737 3h4.018a2 2 0 01.485.06l3.76.94m-7 10v5a2 2 0 002 2h.095c.5 0 .905-.405.905-.905 0-.714.211-1.412.608-2.006L17 13V4m-7 10h2m5-10h2a2 2 0 012 2v6a2 2 0 01-2 2h-2.5"/>
|
|
5
|
-
</svg>`,
|
|
5
|
+
</svg>`, $ = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
6
6
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 10.5l4.72-4.72a.75.75 0 011.28.53v11.38a.75.75 0 01-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25h-9A2.25 2.25 0 002.25 7.5v9a2.25 2.25 0 002.25 2.25z"/>
|
|
7
|
-
</svg>`,
|
|
7
|
+
</svg>`, H = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
8
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M8 10h8M8 14h5m-9 6l3.5-3.5H18a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v14z"/>
|
|
9
|
+
</svg>`, m = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
8
10
|
<rect x="4" y="6" width="16" height="12" rx="1" stroke-linejoin="round"/>
|
|
9
|
-
</svg>`,
|
|
11
|
+
</svg>`, C = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
10
12
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5 19L19 5m0 0h-8m8 0v8"/>
|
|
11
|
-
</svg>`, m = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
12
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M12 20h9M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z"/>
|
|
13
13
|
</svg>`, y = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
14
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 20h9M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z"/>
|
|
15
|
+
</svg>`, q = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
14
16
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3s6 6.4 6 10a6 6 0 01-12 0c0-3.6 6-10 6-10z"/>
|
|
15
|
-
</svg>`,
|
|
17
|
+
</svg>`, E = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
16
18
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 14L4 9l5-5M4 9h11a5 5 0 010 10h-4"/>
|
|
17
|
-
</svg>`,
|
|
19
|
+
</svg>`, L = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
18
20
|
<path stroke-linecap="round" stroke-linejoin="round" d="M20 6L9 17l-5-5"/>
|
|
19
|
-
</svg>`,
|
|
21
|
+
</svg>`, M = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
20
22
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 6l12 12M18 6L6 18"/>
|
|
21
23
|
</svg>`;
|
|
22
24
|
function r(n, t, e) {
|
|
23
25
|
const o = document.createElement(n);
|
|
24
26
|
if (t)
|
|
25
|
-
for (const [
|
|
26
|
-
|
|
27
|
+
for (const [s, i] of Object.entries(t))
|
|
28
|
+
s === "className" ? o.className = i : o.setAttribute(s, i);
|
|
27
29
|
return o;
|
|
28
30
|
}
|
|
29
|
-
function
|
|
31
|
+
function F(n = 640) {
|
|
30
32
|
return typeof window < "u" && window.innerWidth < n;
|
|
31
33
|
}
|
|
32
|
-
function
|
|
33
|
-
const o = e.map((
|
|
34
|
-
e.forEach((
|
|
35
|
-
const
|
|
36
|
-
return e.forEach((
|
|
34
|
+
function K(n, t, e) {
|
|
35
|
+
const o = e.map((i) => i.style.visibility);
|
|
36
|
+
e.forEach((i) => i.style.visibility = "hidden");
|
|
37
|
+
const s = document.elementFromPoint(n, t);
|
|
38
|
+
return e.forEach((i, a) => i.style.visibility = o[a]), s;
|
|
37
39
|
}
|
|
38
|
-
function
|
|
40
|
+
function z(n) {
|
|
39
41
|
return n ? n.hasAttribute("data-qaid-embed") || n.hasAttribute("data-qaid-embed-overlay") ? !0 : !!n.closest("[data-qaid-embed], [data-qaid-embed-overlay]") : !1;
|
|
40
42
|
}
|
|
41
|
-
function
|
|
43
|
+
function V(n, t = 0) {
|
|
42
44
|
const e = n.getBoundingClientRect();
|
|
43
45
|
return {
|
|
44
46
|
x: e.left - t,
|
|
@@ -47,7 +49,19 @@ function H(n, t = 0) {
|
|
|
47
49
|
height: e.height + t * 2
|
|
48
50
|
};
|
|
49
51
|
}
|
|
50
|
-
const
|
|
52
|
+
const h = 12, A = "#ef4444", B = ["#ef4444", "#f59e0b", "#22c55e", "#3b82f6", "#111827", "#ffffff"], T = {
|
|
53
|
+
"#ef4444": "red",
|
|
54
|
+
"#f59e0b": "amber",
|
|
55
|
+
"#22c55e": "green",
|
|
56
|
+
"#3b82f6": "blue",
|
|
57
|
+
"#111827": "black",
|
|
58
|
+
"#ffffff": "white",
|
|
59
|
+
"#6366f1": "indigo"
|
|
60
|
+
};
|
|
61
|
+
function w(n) {
|
|
62
|
+
return T[n.toLowerCase()] ?? n;
|
|
63
|
+
}
|
|
64
|
+
const I = 4, D = 0.8, P = {
|
|
51
65
|
title: "Annotate screenshot",
|
|
52
66
|
instructions: "Draw on the screenshot to highlight or hide details, then choose Done to attach it or Skip to send the original.",
|
|
53
67
|
rectangle: "Rectangle",
|
|
@@ -56,7 +70,8 @@ const l = 12, M = "#ef4444", B = 4, L = 0.8, A = {
|
|
|
56
70
|
blur: "Blur or redact",
|
|
57
71
|
undo: "Undo last",
|
|
58
72
|
skip: "Skip annotation",
|
|
59
|
-
done: "Done"
|
|
73
|
+
done: "Done",
|
|
74
|
+
colors: "Drawing colour"
|
|
60
75
|
};
|
|
61
76
|
function u(n, t) {
|
|
62
77
|
return {
|
|
@@ -66,23 +81,23 @@ function u(n, t) {
|
|
|
66
81
|
h: Math.abs(n.y - t.y)
|
|
67
82
|
};
|
|
68
83
|
}
|
|
69
|
-
function
|
|
84
|
+
function x(n) {
|
|
70
85
|
if (n.type === "pen") return n.points.length < 2;
|
|
71
86
|
const t = u(n.points[0], n.points[1]);
|
|
72
87
|
return t.w < 3 && t.h < 3;
|
|
73
88
|
}
|
|
74
|
-
function
|
|
89
|
+
function _(n, t, e, o) {
|
|
75
90
|
n.beginPath(), n.moveTo(t.x, t.y), n.lineTo(e.x, e.y), n.stroke();
|
|
76
|
-
const
|
|
91
|
+
const s = Math.atan2(e.y - t.y, e.x - t.x), i = Math.max(10, o * 3);
|
|
77
92
|
n.beginPath(), n.moveTo(e.x, e.y), n.lineTo(
|
|
78
|
-
e.x -
|
|
79
|
-
e.y -
|
|
93
|
+
e.x - i * Math.cos(s - Math.PI / 6),
|
|
94
|
+
e.y - i * Math.sin(s - Math.PI / 6)
|
|
80
95
|
), n.moveTo(e.x, e.y), n.lineTo(
|
|
81
|
-
e.x -
|
|
82
|
-
e.y -
|
|
96
|
+
e.x - i * Math.cos(s + Math.PI / 6),
|
|
97
|
+
e.y - i * Math.sin(s + Math.PI / 6)
|
|
83
98
|
), n.stroke();
|
|
84
99
|
}
|
|
85
|
-
function
|
|
100
|
+
function O(n, t) {
|
|
86
101
|
if (t.length !== 0) {
|
|
87
102
|
n.beginPath(), n.moveTo(t[0].x, t[0].y);
|
|
88
103
|
for (let e = 1; e < t.length; e++)
|
|
@@ -90,15 +105,15 @@ function P(n, t) {
|
|
|
90
105
|
n.stroke();
|
|
91
106
|
}
|
|
92
107
|
}
|
|
93
|
-
function
|
|
94
|
-
n.fillStyle = "rgb(15, 23, 42)", n.fillRect(t, e, o,
|
|
95
|
-
for (let
|
|
96
|
-
for (let a = t; a < t + o; a +=
|
|
97
|
-
(Math.floor((a - t) /
|
|
108
|
+
function R(n, t, e, o, s) {
|
|
109
|
+
n.fillStyle = "rgb(15, 23, 42)", n.fillRect(t, e, o, s), n.fillStyle = "rgb(37, 47, 63)";
|
|
110
|
+
for (let i = e; i < e + s; i += h)
|
|
111
|
+
for (let a = t; a < t + o; a += h)
|
|
112
|
+
(Math.floor((a - t) / h) + Math.floor((i - e) / h)) % 2 === 0 && n.fillRect(
|
|
98
113
|
a,
|
|
99
|
-
|
|
100
|
-
Math.min(
|
|
101
|
-
Math.min(
|
|
114
|
+
i,
|
|
115
|
+
Math.min(h, t + o - a),
|
|
116
|
+
Math.min(h, e + s - i)
|
|
102
117
|
);
|
|
103
118
|
}
|
|
104
119
|
function p(n, t) {
|
|
@@ -109,51 +124,52 @@ function p(n, t) {
|
|
|
109
124
|
break;
|
|
110
125
|
}
|
|
111
126
|
case "arrow":
|
|
112
|
-
|
|
127
|
+
_(n, t.points[0], t.points[1], t.strokeWidth);
|
|
113
128
|
break;
|
|
114
129
|
case "pen":
|
|
115
|
-
|
|
130
|
+
O(n, t.points);
|
|
116
131
|
break;
|
|
117
132
|
case "blur": {
|
|
118
133
|
const e = u(t.points[0], t.points[1]);
|
|
119
|
-
|
|
134
|
+
R(n, e.x, e.y, e.w, e.h);
|
|
120
135
|
break;
|
|
121
136
|
}
|
|
122
137
|
}
|
|
123
138
|
n.restore();
|
|
124
139
|
}
|
|
125
|
-
function
|
|
140
|
+
function v(n) {
|
|
126
141
|
return new Promise((t, e) => {
|
|
127
142
|
const o = new Image();
|
|
128
143
|
o.onload = () => t(o), o.onerror = () => e(new Error("Failed to load screenshot")), o.src = n;
|
|
129
144
|
});
|
|
130
145
|
}
|
|
131
|
-
async function
|
|
132
|
-
const o = e.quality ??
|
|
133
|
-
let
|
|
146
|
+
async function g(n, t, e = {}) {
|
|
147
|
+
const o = e.quality ?? D;
|
|
148
|
+
let s;
|
|
134
149
|
try {
|
|
135
|
-
|
|
150
|
+
s = await v(n);
|
|
136
151
|
} catch {
|
|
137
152
|
return n;
|
|
138
153
|
}
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
const a =
|
|
154
|
+
const i = document.createElement("canvas");
|
|
155
|
+
i.width = s.naturalWidth || s.width || 1, i.height = s.naturalHeight || s.height || 1;
|
|
156
|
+
const a = i.getContext("2d");
|
|
142
157
|
if (!a) return n;
|
|
143
|
-
a.drawImage(
|
|
144
|
-
for (const
|
|
145
|
-
p(a,
|
|
146
|
-
return
|
|
158
|
+
a.drawImage(s, 0, 0, i.width, i.height);
|
|
159
|
+
for (const c of t)
|
|
160
|
+
p(a, c);
|
|
161
|
+
return i.toDataURL("image/webp", o);
|
|
147
162
|
}
|
|
148
|
-
let
|
|
149
|
-
class
|
|
163
|
+
let N = 0;
|
|
164
|
+
class f {
|
|
150
165
|
shapes = [];
|
|
151
166
|
tool = "rect";
|
|
152
167
|
opts;
|
|
153
168
|
labels;
|
|
154
169
|
color;
|
|
170
|
+
palette;
|
|
155
171
|
strokeWidth;
|
|
156
|
-
uid = `qaid-annotate-${++
|
|
172
|
+
uid = `qaid-annotate-${++N}`;
|
|
157
173
|
container;
|
|
158
174
|
canvas;
|
|
159
175
|
ctx = null;
|
|
@@ -167,7 +183,7 @@ class g {
|
|
|
167
183
|
// after the editor is mounted).
|
|
168
184
|
resolveResult;
|
|
169
185
|
constructor(t) {
|
|
170
|
-
this.opts = t, this.labels = { ...
|
|
186
|
+
this.opts = t, this.labels = { ...P, ...t.labels ?? {} }, this.color = t.color ?? A, this.palette = (t.palette && t.palette.length ? t.palette : B).slice(), this.palette.some((e) => e.toLowerCase() === this.color.toLowerCase()) || this.palette.unshift(this.color), this.strokeWidth = t.strokeWidth ?? I;
|
|
171
187
|
}
|
|
172
188
|
/** Mount the editor and resolve when the user commits (Done) or skips. */
|
|
173
189
|
open() {
|
|
@@ -177,7 +193,7 @@ class g {
|
|
|
177
193
|
return this.mount(), t;
|
|
178
194
|
}
|
|
179
195
|
toolButton(t, e, o) {
|
|
180
|
-
const
|
|
196
|
+
const s = r("button", {
|
|
181
197
|
type: "button",
|
|
182
198
|
class: "qaid-annotate-tool",
|
|
183
199
|
"data-qaid-tool": t,
|
|
@@ -185,17 +201,29 @@ class g {
|
|
|
185
201
|
"aria-label": `${o} tool`,
|
|
186
202
|
title: o
|
|
187
203
|
});
|
|
188
|
-
return
|
|
204
|
+
return s.innerHTML = `${e}<span class="qaid-annotate-btn-text">${o}</span>`, s;
|
|
189
205
|
}
|
|
190
|
-
|
|
191
|
-
|
|
206
|
+
/** A round colour swatch button for the toolbar's colour group. */
|
|
207
|
+
swatchButton(t) {
|
|
208
|
+
const e = w(t), o = r("button", {
|
|
209
|
+
type: "button",
|
|
210
|
+
class: "qaid-annotate-swatch",
|
|
211
|
+
"data-qaid-color": t,
|
|
212
|
+
"aria-pressed": t.toLowerCase() === this.color.toLowerCase() ? "true" : "false",
|
|
213
|
+
"aria-label": `Draw in ${e}`,
|
|
214
|
+
title: e
|
|
215
|
+
});
|
|
216
|
+
return o.style.setProperty("--qaid-swatch", t), o;
|
|
217
|
+
}
|
|
218
|
+
actionButton(t, e, o, s) {
|
|
219
|
+
const i = r("button", {
|
|
192
220
|
type: "button",
|
|
193
|
-
class: `qaid-annotate-action ${
|
|
221
|
+
class: `qaid-annotate-action ${s}`,
|
|
194
222
|
"data-qaid-action": t,
|
|
195
223
|
"aria-label": o,
|
|
196
224
|
title: o
|
|
197
225
|
});
|
|
198
|
-
return
|
|
226
|
+
return i.innerHTML = `${e}<span class="qaid-annotate-btn-text">${o}</span>`, i;
|
|
199
227
|
}
|
|
200
228
|
mount() {
|
|
201
229
|
const t = `${this.uid}-title`, e = `${this.uid}-desc`;
|
|
@@ -205,35 +233,42 @@ class g {
|
|
|
205
233
|
class: "qaid-annotate-title"
|
|
206
234
|
});
|
|
207
235
|
o.textContent = this.labels.title;
|
|
208
|
-
const
|
|
236
|
+
const s = r("p", {
|
|
209
237
|
id: e,
|
|
210
238
|
class: "qaid-annotate-desc"
|
|
211
239
|
});
|
|
212
|
-
|
|
213
|
-
const
|
|
214
|
-
this.canvas = document.createElement("canvas"), this.canvas.className = "qaid-annotate-canvas", this.canvas.width = 1, this.canvas.height = 1, this.canvas.setAttribute("role", "img"), this.canvas.setAttribute("aria-label", this.labels.title), this.ctx = this.canvas.getContext("2d"),
|
|
240
|
+
s.textContent = this.labels.instructions;
|
|
241
|
+
const i = r("div", { class: "qaid-annotate-stage" });
|
|
242
|
+
this.canvas = document.createElement("canvas"), this.canvas.className = "qaid-annotate-canvas", this.canvas.width = 1, this.canvas.height = 1, this.canvas.setAttribute("role", "img"), this.canvas.setAttribute("aria-label", this.labels.title), this.ctx = this.canvas.getContext("2d"), i.appendChild(this.canvas), this.toolbar = r("div", {
|
|
215
243
|
class: "qaid-annotate-toolbar",
|
|
216
244
|
role: "toolbar",
|
|
217
245
|
"aria-label": this.labels.title
|
|
218
246
|
});
|
|
219
247
|
const a = r("div", { class: "qaid-annotate-tools" });
|
|
220
|
-
a.appendChild(this.toolButton("rect",
|
|
221
|
-
const
|
|
222
|
-
|
|
248
|
+
a.appendChild(this.toolButton("rect", m, this.labels.rectangle)), a.appendChild(this.toolButton("arrow", C, this.labels.arrow)), a.appendChild(this.toolButton("pen", y, this.labels.pen)), a.appendChild(this.toolButton("blur", q, this.labels.blur));
|
|
249
|
+
const c = r("div", {
|
|
250
|
+
class: "qaid-annotate-colors",
|
|
251
|
+
role: "group",
|
|
252
|
+
"aria-label": this.labels.colors
|
|
253
|
+
});
|
|
254
|
+
for (const l of this.palette) c.appendChild(this.swatchButton(l));
|
|
255
|
+
this.undoBtn = this.actionButton("undo", E, this.labels.undo, "qaid-annotate-undo"), this.undoBtn.disabled = !0;
|
|
256
|
+
const b = this.actionButton("skip", M, this.labels.skip, "qaid-annotate-skip"), k = this.actionButton("done", L, this.labels.done, "qaid-annotate-done"), d = r("div", { class: "qaid-annotate-actions" });
|
|
257
|
+
d.appendChild(this.undoBtn), d.appendChild(b), d.appendChild(k), this.toolbar.appendChild(a), this.toolbar.appendChild(c), this.toolbar.appendChild(d), this.container.appendChild(o), this.container.appendChild(s), this.container.appendChild(i), this.container.appendChild(this.toolbar), this.opts.root.appendChild(this.container), this.toolbar.addEventListener("click", this.onToolbarClick), this.canvas.addEventListener("pointerdown", this.onPointerDown), this.container.addEventListener("pointermove", this.onPointerMove), this.container.addEventListener("pointerup", this.onPointerUp), this.container.addEventListener("keydown", this.onKeyDown), this.opts.openDialog?.(this.container, {
|
|
223
258
|
labelledbyId: t,
|
|
224
259
|
describedbyId: e
|
|
225
|
-
}), this.opts.announce?.(this.labels.instructions),
|
|
226
|
-
this.img =
|
|
260
|
+
}), this.opts.announce?.(this.labels.instructions), v(this.opts.dataUrl).then((l) => {
|
|
261
|
+
this.img = l, this.canvas.width = l.naturalWidth || l.width || 1, this.canvas.height = l.naturalHeight || l.height || 1, this.redraw();
|
|
227
262
|
}).catch(() => {
|
|
228
263
|
this.img = null, this.redraw();
|
|
229
264
|
});
|
|
230
265
|
}
|
|
231
266
|
/** Convert a pointer event's client coordinates into natural image pixels. */
|
|
232
267
|
toImageCoords(t) {
|
|
233
|
-
const e = this.canvas.getBoundingClientRect(), o = this.canvas.width / (e.width || this.canvas.width),
|
|
268
|
+
const e = this.canvas.getBoundingClientRect(), o = this.canvas.width / (e.width || this.canvas.width), s = this.canvas.height / (e.height || this.canvas.height);
|
|
234
269
|
return {
|
|
235
270
|
x: (t.clientX - e.left) * o,
|
|
236
|
-
y: (t.clientY - e.top) *
|
|
271
|
+
y: (t.clientY - e.top) * s
|
|
237
272
|
};
|
|
238
273
|
}
|
|
239
274
|
/** Repaint the display canvas: base image (if loaded) then every shape. */
|
|
@@ -248,25 +283,41 @@ class g {
|
|
|
248
283
|
}
|
|
249
284
|
/** Select the active drawing tool and reflect it on the toolbar. */
|
|
250
285
|
selectTool(t) {
|
|
251
|
-
this.tool = t, this.toolbar.querySelectorAll("[data-qaid-tool]").forEach((
|
|
252
|
-
|
|
286
|
+
this.tool = t, this.toolbar.querySelectorAll("[data-qaid-tool]").forEach((s) => {
|
|
287
|
+
s.setAttribute(
|
|
253
288
|
"aria-pressed",
|
|
254
|
-
|
|
289
|
+
s.getAttribute("data-qaid-tool") === t ? "true" : "false"
|
|
255
290
|
);
|
|
256
291
|
});
|
|
257
|
-
const o = this.labels[
|
|
292
|
+
const o = this.labels[S[t]];
|
|
258
293
|
this.opts.announce?.(`${o} tool selected`);
|
|
259
294
|
}
|
|
295
|
+
/** Set the active drawing colour; subsequent shapes use it. */
|
|
296
|
+
selectColor(t) {
|
|
297
|
+
this.color = t, this.toolbar.querySelectorAll("[data-qaid-color]").forEach((o) => {
|
|
298
|
+
o.setAttribute(
|
|
299
|
+
"aria-pressed",
|
|
300
|
+
(o.getAttribute("data-qaid-color") ?? "").toLowerCase() === t.toLowerCase() ? "true" : "false"
|
|
301
|
+
);
|
|
302
|
+
}), this.opts.announce?.(`${w(t)} colour selected`);
|
|
303
|
+
}
|
|
260
304
|
onToolbarClick = (t) => {
|
|
261
|
-
const o = t.target?.closest(
|
|
305
|
+
const o = t.target?.closest(
|
|
306
|
+
"[data-qaid-tool],[data-qaid-action],[data-qaid-color]"
|
|
307
|
+
);
|
|
262
308
|
if (!o) return;
|
|
309
|
+
const s = o.getAttribute("data-qaid-color");
|
|
310
|
+
if (s) {
|
|
311
|
+
this.selectColor(s);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
263
314
|
const i = o.getAttribute("data-qaid-tool");
|
|
264
315
|
if (i) {
|
|
265
316
|
this.selectTool(i);
|
|
266
317
|
return;
|
|
267
318
|
}
|
|
268
|
-
const
|
|
269
|
-
|
|
319
|
+
const a = o.getAttribute("data-qaid-action");
|
|
320
|
+
a === "undo" ? this.undo() : a === "skip" ? this.skip() : a === "done" && this.done();
|
|
270
321
|
};
|
|
271
322
|
onPointerDown = (t) => {
|
|
272
323
|
t.preventDefault?.(), this.drawing = !0;
|
|
@@ -287,7 +338,7 @@ class g {
|
|
|
287
338
|
if (!this.drawing || !this.current) return;
|
|
288
339
|
this.drawing = !1;
|
|
289
340
|
const t = this.current;
|
|
290
|
-
if (this.current = null,
|
|
341
|
+
if (this.current = null, x(t)) {
|
|
291
342
|
this.redraw();
|
|
292
343
|
return;
|
|
293
344
|
}
|
|
@@ -316,7 +367,7 @@ class g {
|
|
|
316
367
|
/** Composite the annotations and resolve with the new WebP data URL. */
|
|
317
368
|
async done() {
|
|
318
369
|
if (this.settled) return;
|
|
319
|
-
const t = await
|
|
370
|
+
const t = await g(this.opts.dataUrl, this.shapes, {
|
|
320
371
|
quality: this.opts.quality
|
|
321
372
|
});
|
|
322
373
|
this.opts.announce?.("Annotated screenshot attached"), this.settle(t);
|
|
@@ -332,36 +383,37 @@ class g {
|
|
|
332
383
|
this.toolbar.removeEventListener("click", this.onToolbarClick), this.canvas.removeEventListener("pointerdown", this.onPointerDown), this.container.removeEventListener("pointermove", this.onPointerMove), this.container.removeEventListener("pointerup", this.onPointerUp), this.container.removeEventListener("keydown", this.onKeyDown), this.opts.closeDialog?.(), this.container.remove();
|
|
333
384
|
}
|
|
334
385
|
}
|
|
335
|
-
const
|
|
386
|
+
const S = {
|
|
336
387
|
rect: "rectangle",
|
|
337
388
|
arrow: "arrow",
|
|
338
389
|
pen: "pen",
|
|
339
390
|
blur: "blur"
|
|
340
391
|
};
|
|
341
|
-
function
|
|
342
|
-
return new
|
|
392
|
+
function U(n) {
|
|
393
|
+
return new f(n).open();
|
|
343
394
|
}
|
|
344
|
-
const
|
|
395
|
+
const Y = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
345
396
|
__proto__: null,
|
|
346
|
-
AnnotationEditor:
|
|
347
|
-
compositeAnnotations:
|
|
397
|
+
AnnotationEditor: f,
|
|
398
|
+
compositeAnnotations: g,
|
|
348
399
|
drawShape: p,
|
|
349
|
-
openAnnotationEditor:
|
|
400
|
+
openAnnotationEditor: U,
|
|
350
401
|
rectFromPoints: u
|
|
351
402
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
352
403
|
export {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
404
|
+
f as A,
|
|
405
|
+
H as F,
|
|
406
|
+
$ as R,
|
|
407
|
+
j as T,
|
|
408
|
+
W as a,
|
|
409
|
+
z as b,
|
|
410
|
+
g as c,
|
|
359
411
|
p as d,
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
412
|
+
K as e,
|
|
413
|
+
Y as f,
|
|
414
|
+
V as g,
|
|
415
|
+
F as i,
|
|
416
|
+
U as o,
|
|
365
417
|
u as r
|
|
366
418
|
};
|
|
367
|
-
//# sourceMappingURL=annotate-
|
|
419
|
+
//# sourceMappingURL=annotate-pSxJNPPL.js.map
|