qapture2 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-ESRQOU32.js → chunk-2CAMCMJP.js} +46 -7
- package/dist/{chunk-6KAXMN77.cjs → chunk-PIN23NW3.cjs} +46 -7
- package/dist/index.cjs +5 -5
- package/dist/index.js +1 -1
- package/dist/next.cjs +4 -4
- package/dist/next.js +1 -1
- package/dist/standalone.cjs +2 -2
- package/dist/standalone.js +1 -1
- package/package.json +1 -1
|
@@ -264,6 +264,31 @@ function coerceJourney(raw, warnings) {
|
|
|
264
264
|
}
|
|
265
265
|
return out;
|
|
266
266
|
}
|
|
267
|
+
function warnMissingArabic(loginField, credentials, journey, warnings) {
|
|
268
|
+
const hasAr = (v) => typeof v === "object" && v !== null && isNonEmptyString(v.ar);
|
|
269
|
+
const usesArabic = isNonEmptyString(loginField.ar) || credentials.some((c) => isNonEmptyString(c.roleAr) || hasAr(c.hint)) || journey.some((lane) => hasAr(lane.role) || lane.steps.some((s) => hasAr(s.what) || hasAr(s.expect)));
|
|
270
|
+
if (!usesArabic) return;
|
|
271
|
+
const missing = [];
|
|
272
|
+
for (const lane of journey) {
|
|
273
|
+
for (const step of lane.steps) {
|
|
274
|
+
if (!hasAr(step.what)) missing.push(`journey "${lane.id}" \u2192 ${step.path} (what)`);
|
|
275
|
+
if (step.expect !== void 0 && !hasAr(step.expect)) {
|
|
276
|
+
missing.push(`journey "${lane.id}" \u2192 ${step.path} (expect)`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
for (const c of credentials) {
|
|
281
|
+
if (!isNonEmptyString(c.roleAr)) missing.push(`credentials role="${c.role}" (roleAr)`);
|
|
282
|
+
if (c.hint !== void 0 && !hasAr(c.hint)) missing.push(`credentials role="${c.role}" (hint.ar)`);
|
|
283
|
+
}
|
|
284
|
+
if (!missing.length) return;
|
|
285
|
+
const LIMIT = 6;
|
|
286
|
+
const shown = missing.slice(0, LIMIT).join("; ");
|
|
287
|
+
const rest = missing.length > LIMIT ? ` (+${missing.length - LIMIT} more)` : "";
|
|
288
|
+
warnings.push(
|
|
289
|
+
`Arabic is used elsewhere in this config, but ${missing.length} bilingual field(s) have no "ar" and will show English to an Arabic-language tester: ${shown}${rest}. Every {en, ar} pair needs BOTH filled in \u2014 a plain string or an {en}-only object reads identically to a bilingual field that was simply never translated.`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
267
292
|
function coercePreamble(raw) {
|
|
268
293
|
if (raw === null || raw === void 0) return null;
|
|
269
294
|
if (typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
@@ -348,6 +373,7 @@ function validateConfig(input) {
|
|
|
348
373
|
warnings.push("visible: expected boolean \u2014 using default (dev-only)");
|
|
349
374
|
}
|
|
350
375
|
}
|
|
376
|
+
warnMissingArabic(loginField, credentials, journey, warnings);
|
|
351
377
|
return {
|
|
352
378
|
config: {
|
|
353
379
|
namespace,
|
|
@@ -4961,16 +4987,20 @@ function CaptureMode() {
|
|
|
4961
4987
|
};
|
|
4962
4988
|
const popStyleFor = useCallback((r) => {
|
|
4963
4989
|
if (typeof window === "undefined") return {};
|
|
4964
|
-
const
|
|
4965
|
-
const
|
|
4966
|
-
const
|
|
4990
|
+
const margin = 12;
|
|
4991
|
+
const spaceBelow = window.innerHeight - (r.top + r.height + margin);
|
|
4992
|
+
const spaceAbove = r.top - margin;
|
|
4993
|
+
const placeAbove = spaceBelow < spaceAbove;
|
|
4994
|
+
const top = placeAbove ? Math.max(margin, r.top - margin) : r.top + r.height + margin;
|
|
4967
4995
|
let left = r.left;
|
|
4968
4996
|
left = Math.min(left, window.innerWidth - 340);
|
|
4969
|
-
left = Math.max(
|
|
4997
|
+
left = Math.max(margin, left);
|
|
4998
|
+
const available = (placeAbove ? spaceAbove : spaceBelow) - margin;
|
|
4970
4999
|
return {
|
|
4971
5000
|
top,
|
|
4972
5001
|
left,
|
|
4973
|
-
transform: placeAbove ? "translateY(-100%)" : "none"
|
|
5002
|
+
transform: placeAbove ? "translateY(-100%)" : "none",
|
|
5003
|
+
maxHeight: `max(${margin * 4}px, ${Math.max(0, available)}px)`
|
|
4974
5004
|
};
|
|
4975
5005
|
}, []);
|
|
4976
5006
|
const popStyle = selection ? popStyleFor(selection.rect) : {};
|
|
@@ -5208,6 +5238,15 @@ function CaptureMode() {
|
|
|
5208
5238
|
className: `qa-fixed qa-z-10096 qa-w-320 qa-overflow-hidden qa-rounded-xl qa-border qa-border-subtle qa-elev-3 qa-card-anim${cardIn ? " qa-card-in" : ""}`,
|
|
5209
5239
|
style: {
|
|
5210
5240
|
...popStyle,
|
|
5241
|
+
// popStyle's maxHeight caps this to whatever room is actually
|
|
5242
|
+
// available above/below the target; overflowY lets the card
|
|
5243
|
+
// itself scroll internally rather than ever rendering content
|
|
5244
|
+
// (most importantly the Save button) somewhere the page's own
|
|
5245
|
+
// scroll — locked during capture — can't reach. overflowX stays
|
|
5246
|
+
// hidden so the qa-overflow-hidden class's rounded-corner
|
|
5247
|
+
// clipping is preserved on that axis.
|
|
5248
|
+
overflowY: "auto",
|
|
5249
|
+
overflowX: "hidden",
|
|
5211
5250
|
background: "var(--qa-surface-1)"
|
|
5212
5251
|
},
|
|
5213
5252
|
children: [
|
|
@@ -5484,5 +5523,5 @@ function Qapture({ config }) {
|
|
|
5484
5523
|
}
|
|
5485
5524
|
|
|
5486
5525
|
export { Qapture, deleteQaDatabase, initQaStudio };
|
|
5487
|
-
//# sourceMappingURL=chunk-
|
|
5488
|
-
//# sourceMappingURL=chunk-
|
|
5526
|
+
//# sourceMappingURL=chunk-2CAMCMJP.js.map
|
|
5527
|
+
//# sourceMappingURL=chunk-2CAMCMJP.js.map
|
|
@@ -271,6 +271,31 @@ function coerceJourney(raw, warnings) {
|
|
|
271
271
|
}
|
|
272
272
|
return out;
|
|
273
273
|
}
|
|
274
|
+
function warnMissingArabic(loginField, credentials, journey, warnings) {
|
|
275
|
+
const hasAr = (v) => typeof v === "object" && v !== null && isNonEmptyString(v.ar);
|
|
276
|
+
const usesArabic = isNonEmptyString(loginField.ar) || credentials.some((c) => isNonEmptyString(c.roleAr) || hasAr(c.hint)) || journey.some((lane) => hasAr(lane.role) || lane.steps.some((s) => hasAr(s.what) || hasAr(s.expect)));
|
|
277
|
+
if (!usesArabic) return;
|
|
278
|
+
const missing = [];
|
|
279
|
+
for (const lane of journey) {
|
|
280
|
+
for (const step of lane.steps) {
|
|
281
|
+
if (!hasAr(step.what)) missing.push(`journey "${lane.id}" \u2192 ${step.path} (what)`);
|
|
282
|
+
if (step.expect !== void 0 && !hasAr(step.expect)) {
|
|
283
|
+
missing.push(`journey "${lane.id}" \u2192 ${step.path} (expect)`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
for (const c of credentials) {
|
|
288
|
+
if (!isNonEmptyString(c.roleAr)) missing.push(`credentials role="${c.role}" (roleAr)`);
|
|
289
|
+
if (c.hint !== void 0 && !hasAr(c.hint)) missing.push(`credentials role="${c.role}" (hint.ar)`);
|
|
290
|
+
}
|
|
291
|
+
if (!missing.length) return;
|
|
292
|
+
const LIMIT = 6;
|
|
293
|
+
const shown = missing.slice(0, LIMIT).join("; ");
|
|
294
|
+
const rest = missing.length > LIMIT ? ` (+${missing.length - LIMIT} more)` : "";
|
|
295
|
+
warnings.push(
|
|
296
|
+
`Arabic is used elsewhere in this config, but ${missing.length} bilingual field(s) have no "ar" and will show English to an Arabic-language tester: ${shown}${rest}. Every {en, ar} pair needs BOTH filled in \u2014 a plain string or an {en}-only object reads identically to a bilingual field that was simply never translated.`
|
|
297
|
+
);
|
|
298
|
+
}
|
|
274
299
|
function coercePreamble(raw) {
|
|
275
300
|
if (raw === null || raw === void 0) return null;
|
|
276
301
|
if (typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
@@ -355,6 +380,7 @@ function validateConfig(input) {
|
|
|
355
380
|
warnings.push("visible: expected boolean \u2014 using default (dev-only)");
|
|
356
381
|
}
|
|
357
382
|
}
|
|
383
|
+
warnMissingArabic(loginField, credentials, journey, warnings);
|
|
358
384
|
return {
|
|
359
385
|
config: {
|
|
360
386
|
namespace,
|
|
@@ -4968,16 +4994,20 @@ function CaptureMode() {
|
|
|
4968
4994
|
};
|
|
4969
4995
|
const popStyleFor = React.useCallback((r) => {
|
|
4970
4996
|
if (typeof window === "undefined") return {};
|
|
4971
|
-
const
|
|
4972
|
-
const
|
|
4973
|
-
const
|
|
4997
|
+
const margin = 12;
|
|
4998
|
+
const spaceBelow = window.innerHeight - (r.top + r.height + margin);
|
|
4999
|
+
const spaceAbove = r.top - margin;
|
|
5000
|
+
const placeAbove = spaceBelow < spaceAbove;
|
|
5001
|
+
const top = placeAbove ? Math.max(margin, r.top - margin) : r.top + r.height + margin;
|
|
4974
5002
|
let left = r.left;
|
|
4975
5003
|
left = Math.min(left, window.innerWidth - 340);
|
|
4976
|
-
left = Math.max(
|
|
5004
|
+
left = Math.max(margin, left);
|
|
5005
|
+
const available = (placeAbove ? spaceAbove : spaceBelow) - margin;
|
|
4977
5006
|
return {
|
|
4978
5007
|
top,
|
|
4979
5008
|
left,
|
|
4980
|
-
transform: placeAbove ? "translateY(-100%)" : "none"
|
|
5009
|
+
transform: placeAbove ? "translateY(-100%)" : "none",
|
|
5010
|
+
maxHeight: `max(${margin * 4}px, ${Math.max(0, available)}px)`
|
|
4981
5011
|
};
|
|
4982
5012
|
}, []);
|
|
4983
5013
|
const popStyle = selection ? popStyleFor(selection.rect) : {};
|
|
@@ -5215,6 +5245,15 @@ function CaptureMode() {
|
|
|
5215
5245
|
className: `qa-fixed qa-z-10096 qa-w-320 qa-overflow-hidden qa-rounded-xl qa-border qa-border-subtle qa-elev-3 qa-card-anim${cardIn ? " qa-card-in" : ""}`,
|
|
5216
5246
|
style: {
|
|
5217
5247
|
...popStyle,
|
|
5248
|
+
// popStyle's maxHeight caps this to whatever room is actually
|
|
5249
|
+
// available above/below the target; overflowY lets the card
|
|
5250
|
+
// itself scroll internally rather than ever rendering content
|
|
5251
|
+
// (most importantly the Save button) somewhere the page's own
|
|
5252
|
+
// scroll — locked during capture — can't reach. overflowX stays
|
|
5253
|
+
// hidden so the qa-overflow-hidden class's rounded-corner
|
|
5254
|
+
// clipping is preserved on that axis.
|
|
5255
|
+
overflowY: "auto",
|
|
5256
|
+
overflowX: "hidden",
|
|
5218
5257
|
background: "var(--qa-surface-1)"
|
|
5219
5258
|
},
|
|
5220
5259
|
children: [
|
|
@@ -5493,5 +5532,5 @@ function Qapture({ config }) {
|
|
|
5493
5532
|
exports.Qapture = Qapture;
|
|
5494
5533
|
exports.deleteQaDatabase = deleteQaDatabase;
|
|
5495
5534
|
exports.initQaStudio = initQaStudio;
|
|
5496
|
-
//# sourceMappingURL=chunk-
|
|
5497
|
-
//# sourceMappingURL=chunk-
|
|
5535
|
+
//# sourceMappingURL=chunk-PIN23NW3.cjs.map
|
|
5536
|
+
//# sourceMappingURL=chunk-PIN23NW3.cjs.map
|
package/dist/index.cjs
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkPIN23NW3_cjs = require('./chunk-PIN23NW3.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
Object.defineProperty(exports, "QaStudio", {
|
|
8
8
|
enumerable: true,
|
|
9
|
-
get: function () { return
|
|
9
|
+
get: function () { return chunkPIN23NW3_cjs.Qapture; }
|
|
10
10
|
});
|
|
11
11
|
Object.defineProperty(exports, "Qapture", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunkPIN23NW3_cjs.Qapture; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "deleteQaDatabase", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunkPIN23NW3_cjs.deleteQaDatabase; }
|
|
18
18
|
});
|
|
19
19
|
Object.defineProperty(exports, "initQaStudio", {
|
|
20
20
|
enumerable: true,
|
|
21
|
-
get: function () { return
|
|
21
|
+
get: function () { return chunkPIN23NW3_cjs.initQaStudio; }
|
|
22
22
|
});
|
|
23
23
|
//# sourceMappingURL=index.cjs.map
|
|
24
24
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.js
CHANGED
package/dist/next.cjs
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunkPIN23NW3_cjs = require('./chunk-PIN23NW3.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "QaStudio", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunkPIN23NW3_cjs.Qapture; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "Qapture", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunkPIN23NW3_cjs.Qapture; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "initQaStudio", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkPIN23NW3_cjs.initQaStudio; }
|
|
19
19
|
});
|
|
20
20
|
//# sourceMappingURL=next.cjs.map
|
|
21
21
|
//# sourceMappingURL=next.cjs.map
|
package/dist/next.js
CHANGED
package/dist/standalone.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkPIN23NW3_cjs = require('./chunk-PIN23NW3.cjs');
|
|
4
4
|
|
|
5
5
|
// src/standalone.ts
|
|
6
6
|
if (typeof window !== "undefined" && typeof customElements !== "undefined" && !customElements.get("qapture-widget")) {
|
|
@@ -38,7 +38,7 @@ if (typeof window !== "undefined" && typeof customElements !== "undefined" && !c
|
|
|
38
38
|
|
|
39
39
|
Object.defineProperty(exports, "initQaStudio", {
|
|
40
40
|
enumerable: true,
|
|
41
|
-
get: function () { return
|
|
41
|
+
get: function () { return chunkPIN23NW3_cjs.initQaStudio; }
|
|
42
42
|
});
|
|
43
43
|
//# sourceMappingURL=standalone.cjs.map
|
|
44
44
|
//# sourceMappingURL=standalone.cjs.map
|
package/dist/standalone.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qapture2",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Drop-in, AI-aware in-browser QA capture widget. A tester annotates the live app (element/region + auto-screenshot + note), tracks a graded testing journey, and exports a ZIP your own coding agent reads. Ships zero AI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|