@designfever/web-review-kit 0.6.0 → 0.7.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/.env.sample +29 -0
- package/README.md +35 -10
- package/dist/chunk-AB5B6O77.js +584 -0
- package/dist/chunk-AB5B6O77.js.map +1 -0
- package/dist/{chunk-IN36JHEU.js → chunk-RPVLRULC.js} +504 -143
- package/dist/chunk-RPVLRULC.js.map +1 -0
- package/dist/image.types-BmzkFSPX.d.cts +71 -0
- package/dist/image.types-BmzkFSPX.d.ts +71 -0
- package/dist/index.cjs +1019 -144
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -3
- package/dist/index.d.ts +27 -3
- package/dist/index.js +50 -3
- package/dist/index.js.map +1 -1
- package/dist/react-shell.cjs +10293 -5185
- package/dist/react-shell.cjs.map +1 -1
- package/dist/react-shell.d.cts +37 -4
- package/dist/react-shell.d.ts +37 -4
- package/dist/react-shell.js +9624 -4856
- package/dist/react-shell.js.map +1 -1
- package/dist/token-Dt-ZH-YO.d.cts +88 -0
- package/dist/token-nJXPPdYX.d.ts +88 -0
- package/dist/{types-DFHHVRBc.d.cts → types-DT9Z66mV.d.cts} +13 -1
- package/dist/{types-DFHHVRBc.d.ts → types-DT9Z66mV.d.ts} +13 -1
- package/dist/vite.cjs +1116 -5
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +45 -1
- package/dist/vite.d.ts +45 -1
- package/dist/vite.js +800 -5
- package/dist/vite.js.map +1 -1
- package/docs/README.md +11 -7
- package/docs/adapters.md +126 -0
- package/docs/adaptor.sample.ts +13 -1
- package/docs/architecture.md +2 -1
- package/docs/code-review-0.6.0.md +232 -0
- package/docs/db-setup.md +4 -2
- package/docs/figma-image-mvp-0.7.0.md +327 -0
- package/docs/installation.md +39 -7
- package/docs/release-notes-0.7.0.md +128 -0
- package/package.json +6 -2
- package/dist/chunk-IN36JHEU.js.map +0 -1
|
@@ -111,6 +111,9 @@ function normalizeStoredReviewItem(value) {
|
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
// src/figma/image.types.ts
|
|
115
|
+
var DEFAULT_REVIEW_FIGMA_IMAGE_FORMAT = "webp";
|
|
116
|
+
|
|
114
117
|
// src/core/review/scope.ts
|
|
115
118
|
var DEFAULT_REVIEW_VIEWPORTS = [
|
|
116
119
|
{ label: "Mobile", width: 390, height: 720, scope: "mobile" },
|
|
@@ -389,13 +392,13 @@ function getDomAnchorFromPoint(point, configuredAttribute = "data-qa-id", enviro
|
|
|
389
392
|
const target = environment.document.elementFromPoint(point.x, point.y);
|
|
390
393
|
if (!target) return void 0;
|
|
391
394
|
const candidates = createAnchorCandidates(target, configuredAttribute);
|
|
392
|
-
const
|
|
393
|
-
if (!
|
|
395
|
+
const primaryCandidate = candidates[0];
|
|
396
|
+
if (!primaryCandidate) return void 0;
|
|
394
397
|
return {
|
|
395
|
-
...
|
|
398
|
+
...primaryCandidate,
|
|
396
399
|
candidates,
|
|
397
400
|
htmlSnippet: getElementHtmlSnippet(
|
|
398
|
-
getAnchorSourceElement(target,
|
|
401
|
+
getAnchorSourceElement(target, primaryCandidate, configuredAttribute) ?? target
|
|
399
402
|
),
|
|
400
403
|
source: getDomSourceHint(target)
|
|
401
404
|
};
|
|
@@ -403,13 +406,13 @@ function getDomAnchorFromPoint(point, configuredAttribute = "data-qa-id", enviro
|
|
|
403
406
|
function getDomAnchorFromElement(target, configuredAttribute = "data-qa-id", environment) {
|
|
404
407
|
if (target.ownerDocument !== environment.document) return void 0;
|
|
405
408
|
const candidates = createAnchorCandidates(target, configuredAttribute);
|
|
406
|
-
const
|
|
407
|
-
if (!
|
|
409
|
+
const primaryCandidate = candidates[0];
|
|
410
|
+
if (!primaryCandidate) return void 0;
|
|
408
411
|
return {
|
|
409
|
-
...
|
|
412
|
+
...primaryCandidate,
|
|
410
413
|
candidates,
|
|
411
414
|
htmlSnippet: getElementHtmlSnippet(
|
|
412
|
-
getAnchorSourceElement(target,
|
|
415
|
+
getAnchorSourceElement(target, primaryCandidate, configuredAttribute) ?? target
|
|
413
416
|
),
|
|
414
417
|
source: getDomSourceHint(target)
|
|
415
418
|
};
|
|
@@ -580,7 +583,7 @@ function createAnchorCandidates(target, configuredAttribute) {
|
|
|
580
583
|
function findClosestAttributeAnchor(target, attributeNames, confidence, options) {
|
|
581
584
|
for (const attributeName of attributeNames) {
|
|
582
585
|
const selector = `[${attributeName}]`;
|
|
583
|
-
const element =
|
|
586
|
+
const element = tryClosest(target, selector);
|
|
584
587
|
if (!element) continue;
|
|
585
588
|
const value = getStableAttributeValue(element, attributeName);
|
|
586
589
|
if (!value) continue;
|
|
@@ -686,7 +689,7 @@ function getAnchorSourceElement(target, candidate, configuredAttribute) {
|
|
|
686
689
|
return target;
|
|
687
690
|
}
|
|
688
691
|
}
|
|
689
|
-
function
|
|
692
|
+
function tryClosest(element, selector) {
|
|
690
693
|
try {
|
|
691
694
|
return element.closest(selector);
|
|
692
695
|
} catch {
|
|
@@ -1190,18 +1193,90 @@ function setDocumentScrollInstantly(environment, position) {
|
|
|
1190
1193
|
);
|
|
1191
1194
|
}
|
|
1192
1195
|
|
|
1196
|
+
// src/core/draft.metrics.ts
|
|
1197
|
+
function getDraftViewportScale(viewport, presets) {
|
|
1198
|
+
const preset = findReviewViewportPreset(viewport, presets);
|
|
1199
|
+
const designWidth = typeof preset.designWidth === "number" && preset.designWidth > 0 ? preset.designWidth : viewport.width;
|
|
1200
|
+
const scale = designWidth > 0 ? viewport.width / designWidth : 1;
|
|
1201
|
+
return { scale, designWidth, presetLabel: preset.label };
|
|
1202
|
+
}
|
|
1203
|
+
function getDraftAdjustmentMetrics(draft, presets) {
|
|
1204
|
+
const adjustment = draft.adjustment;
|
|
1205
|
+
const x = adjustment?.x ?? 0;
|
|
1206
|
+
const y = adjustment?.y ?? 0;
|
|
1207
|
+
const scale = adjustment?.scale ?? 0;
|
|
1208
|
+
const {
|
|
1209
|
+
scale: viewportScale,
|
|
1210
|
+
designWidth,
|
|
1211
|
+
presetLabel
|
|
1212
|
+
} = getDraftViewportScale(draft.viewport, presets);
|
|
1213
|
+
const selection = draft.selection ? toViewportSelection(draft.selection.viewport) : void 0;
|
|
1214
|
+
const scaleCssDelta = scale * viewportScale;
|
|
1215
|
+
const scaleFactor = selection && selection.width > 0 ? Math.max(
|
|
1216
|
+
1 / selection.width,
|
|
1217
|
+
(selection.width + scaleCssDelta) / selection.width
|
|
1218
|
+
) : 1;
|
|
1219
|
+
return {
|
|
1220
|
+
x,
|
|
1221
|
+
y,
|
|
1222
|
+
scale,
|
|
1223
|
+
cssX: x * viewportScale,
|
|
1224
|
+
cssY: y * viewportScale,
|
|
1225
|
+
scaleFactor,
|
|
1226
|
+
viewportScale,
|
|
1227
|
+
designWidth,
|
|
1228
|
+
presetLabel,
|
|
1229
|
+
viewportWidth: draft.viewport.width
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
function hasDraftAdjustment(draft, presets) {
|
|
1233
|
+
const metrics = getDraftAdjustmentMetrics(draft, presets);
|
|
1234
|
+
return metrics.x !== 0 || metrics.y !== 0 || metrics.scale !== 0;
|
|
1235
|
+
}
|
|
1236
|
+
function getAdjustedDraftPoint(point, draft, presets) {
|
|
1237
|
+
const metrics = getDraftAdjustmentMetrics(draft, presets);
|
|
1238
|
+
return {
|
|
1239
|
+
x: point.x + metrics.cssX,
|
|
1240
|
+
y: point.y + metrics.cssY
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
function getAdjustedDraftSelection(selection, draft, presets) {
|
|
1244
|
+
const metrics = getDraftAdjustmentMetrics(draft, presets);
|
|
1245
|
+
return {
|
|
1246
|
+
...selection,
|
|
1247
|
+
left: selection.left + metrics.cssX,
|
|
1248
|
+
top: selection.top + metrics.cssY,
|
|
1249
|
+
width: selection.width * metrics.scaleFactor,
|
|
1250
|
+
height: selection.height * metrics.scaleFactor
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// src/core/typography.tokens.ts
|
|
1255
|
+
var reviewTypographyTokens = `
|
|
1256
|
+
--df-review-font-sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
1257
|
+
--df-review-font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
|
|
1258
|
+
--df-review-font-size-3xs: 9px;
|
|
1259
|
+
--df-review-font-size-2xs: 10px;
|
|
1260
|
+
--df-review-font-size-xs: 11px;
|
|
1261
|
+
--df-review-font-size-sm: 12px;
|
|
1262
|
+
--df-review-font-size-md: 13px;
|
|
1263
|
+
--df-review-font-size-lg: 14px;
|
|
1264
|
+
--df-review-font-size-xl: 15px;
|
|
1265
|
+
--df-review-font-size-2xl: 18px;
|
|
1266
|
+
--df-review-font-weight-normal: 400;
|
|
1267
|
+
--df-review-font-weight-emphasis: 500;
|
|
1268
|
+
--df-review-line-height-tight: 1.25;
|
|
1269
|
+
--df-review-line-height-base: 1.42;
|
|
1270
|
+
--df-review-line-height-relaxed: 1.55;
|
|
1271
|
+
`;
|
|
1272
|
+
|
|
1193
1273
|
// src/core/overlay.style.ts
|
|
1194
1274
|
function createStyleElement() {
|
|
1195
1275
|
const style = document.createElement("style");
|
|
1196
1276
|
style.textContent = `
|
|
1197
1277
|
:host {
|
|
1198
1278
|
color-scheme: dark;
|
|
1199
|
-
|
|
1200
|
-
--df-review-font-size-2xs: 10px;
|
|
1201
|
-
--df-review-font-size-xs: 11px;
|
|
1202
|
-
--df-review-font-size-sm: 12px;
|
|
1203
|
-
--df-review-font-size-md: 13px;
|
|
1204
|
-
--df-review-font-size-xl: 15px;
|
|
1279
|
+
${reviewTypographyTokens}
|
|
1205
1280
|
--df-review-space-1: 4px;
|
|
1206
1281
|
--df-review-space-1-5: 6px;
|
|
1207
1282
|
--df-review-space-2: 8px;
|
|
@@ -1300,8 +1375,8 @@ function createStyleElement() {
|
|
|
1300
1375
|
}
|
|
1301
1376
|
|
|
1302
1377
|
.dfwr-title {
|
|
1303
|
-
font-size:
|
|
1304
|
-
font-weight:
|
|
1378
|
+
font-size: var(--df-review-font-size-xl);
|
|
1379
|
+
font-weight: var(--df-review-font-weight-emphasis);
|
|
1305
1380
|
line-height: 1.25;
|
|
1306
1381
|
}
|
|
1307
1382
|
|
|
@@ -1345,11 +1420,15 @@ function createStyleElement() {
|
|
|
1345
1420
|
}
|
|
1346
1421
|
|
|
1347
1422
|
.dfwr-button {
|
|
1423
|
+
display: inline-flex;
|
|
1424
|
+
align-items: center;
|
|
1425
|
+
justify-content: center;
|
|
1426
|
+
gap: 6px;
|
|
1348
1427
|
min-height: var(--df-review-control-height-md);
|
|
1349
1428
|
padding: 0 12px;
|
|
1350
1429
|
border-radius: var(--df-review-radius-sm);
|
|
1351
1430
|
font-size: var(--df-review-font-size-sm);
|
|
1352
|
-
font-weight:
|
|
1431
|
+
font-weight: var(--df-review-font-weight-emphasis);
|
|
1353
1432
|
}
|
|
1354
1433
|
|
|
1355
1434
|
.dfwr-button:hover,
|
|
@@ -1365,6 +1444,21 @@ function createStyleElement() {
|
|
|
1365
1444
|
color: var(--df-review-color-accent-contrast);
|
|
1366
1445
|
}
|
|
1367
1446
|
|
|
1447
|
+
.dfwr-button:disabled {
|
|
1448
|
+
cursor: default;
|
|
1449
|
+
opacity: 0.62;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
.dfwr-spinner {
|
|
1453
|
+
display: inline-block;
|
|
1454
|
+
width: 12px;
|
|
1455
|
+
height: 12px;
|
|
1456
|
+
border: 2px solid currentColor;
|
|
1457
|
+
border-right-color: transparent;
|
|
1458
|
+
border-radius: 999px;
|
|
1459
|
+
animation: dfwr-spin 720ms linear infinite;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1368
1462
|
.dfwr-icon-button {
|
|
1369
1463
|
display: inline-flex;
|
|
1370
1464
|
align-items: center;
|
|
@@ -1374,7 +1468,7 @@ function createStyleElement() {
|
|
|
1374
1468
|
padding: 0 8px;
|
|
1375
1469
|
border-radius: var(--df-review-radius-sm);
|
|
1376
1470
|
font-size: var(--df-review-font-size-xs);
|
|
1377
|
-
font-weight:
|
|
1471
|
+
font-weight: var(--df-review-font-weight-emphasis);
|
|
1378
1472
|
line-height: 1;
|
|
1379
1473
|
text-transform: uppercase;
|
|
1380
1474
|
}
|
|
@@ -1529,7 +1623,7 @@ function createStyleElement() {
|
|
|
1529
1623
|
0 8px 18px rgba(0, 0, 0, 0.28);
|
|
1530
1624
|
color: #111820;
|
|
1531
1625
|
font-size: var(--df-review-font-size-2xs);
|
|
1532
|
-
font-weight:
|
|
1626
|
+
font-weight: var(--df-review-font-weight-emphasis);
|
|
1533
1627
|
line-height: 1;
|
|
1534
1628
|
pointer-events: none;
|
|
1535
1629
|
}
|
|
@@ -1555,7 +1649,7 @@ function createStyleElement() {
|
|
|
1555
1649
|
box-shadow: 0 0 0 4px rgba(var(--dfwr-scope-rgb), 0.18);
|
|
1556
1650
|
color: var(--dfwr-scope);
|
|
1557
1651
|
font-size: var(--df-review-font-size-2xs);
|
|
1558
|
-
font-weight:
|
|
1652
|
+
font-weight: var(--df-review-font-weight-emphasis);
|
|
1559
1653
|
}
|
|
1560
1654
|
|
|
1561
1655
|
.dfwr-bound-marker.is-highlighted {
|
|
@@ -1897,10 +1991,18 @@ function createStyleElement() {
|
|
|
1897
1991
|
gap: 10px;
|
|
1898
1992
|
}
|
|
1899
1993
|
|
|
1994
|
+
.dfwr-form-error {
|
|
1995
|
+
margin: 0;
|
|
1996
|
+
color: #ff8f61;
|
|
1997
|
+
font-size: var(--df-review-font-size-sm);
|
|
1998
|
+
line-height: 1.4;
|
|
1999
|
+
overflow-wrap: anywhere;
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
.dfwr-input,
|
|
2003
|
+
.dfwr-select,
|
|
1900
2004
|
.dfwr-textarea {
|
|
1901
2005
|
width: 100%;
|
|
1902
|
-
min-height: 92px;
|
|
1903
|
-
resize: vertical;
|
|
1904
2006
|
border: 1px solid rgba(255, 255, 255, 0.16);
|
|
1905
2007
|
border-radius: var(--df-review-radius-sm);
|
|
1906
2008
|
padding: 10px;
|
|
@@ -1911,14 +2013,39 @@ function createStyleElement() {
|
|
|
1911
2013
|
line-height: 1.45;
|
|
1912
2014
|
}
|
|
1913
2015
|
|
|
2016
|
+
.dfwr-input,
|
|
2017
|
+
.dfwr-select {
|
|
2018
|
+
min-height: 38px;
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
.dfwr-select {
|
|
2022
|
+
appearance: none;
|
|
2023
|
+
cursor: pointer;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
.dfwr-textarea {
|
|
2027
|
+
min-height: 92px;
|
|
2028
|
+
resize: vertical;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
.dfwr-input:focus,
|
|
2032
|
+
.dfwr-select:focus,
|
|
1914
2033
|
.dfwr-textarea:focus {
|
|
1915
2034
|
outline: 2px solid var(--df-review-color-accent-ring);
|
|
1916
2035
|
outline-offset: 1px;
|
|
1917
2036
|
}
|
|
1918
2037
|
|
|
1919
2038
|
@media (hover: none) and (pointer: coarse) {
|
|
2039
|
+
.dfwr-input,
|
|
2040
|
+
.dfwr-select,
|
|
1920
2041
|
.dfwr-textarea {
|
|
1921
|
-
font-size:
|
|
2042
|
+
font-size: var(--df-review-font-size-xl);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
@keyframes dfwr-spin {
|
|
2047
|
+
to {
|
|
2048
|
+
transform: rotate(360deg);
|
|
1922
2049
|
}
|
|
1923
2050
|
}
|
|
1924
2051
|
|
|
@@ -1976,8 +2103,8 @@ function createStyleElement() {
|
|
|
1976
2103
|
color: var(--df-review-color-text);
|
|
1977
2104
|
cursor: pointer;
|
|
1978
2105
|
font: inherit;
|
|
1979
|
-
font-size:
|
|
1980
|
-
font-weight:
|
|
2106
|
+
font-size: var(--df-review-font-size-lg);
|
|
2107
|
+
font-weight: var(--df-review-font-weight-emphasis);
|
|
1981
2108
|
line-height: 1;
|
|
1982
2109
|
}
|
|
1983
2110
|
|
|
@@ -2030,7 +2157,7 @@ function createStyleElement() {
|
|
|
2030
2157
|
margin-bottom: 10px;
|
|
2031
2158
|
color: rgba(247, 247, 242, 0.74);
|
|
2032
2159
|
font-size: var(--df-review-font-size-sm);
|
|
2033
|
-
font-weight:
|
|
2160
|
+
font-weight: var(--df-review-font-weight-emphasis);
|
|
2034
2161
|
}
|
|
2035
2162
|
|
|
2036
2163
|
.dfwr-item {
|
|
@@ -2052,6 +2179,8 @@ function createStyleElement() {
|
|
|
2052
2179
|
}
|
|
2053
2180
|
|
|
2054
2181
|
.dfwr-item-body {
|
|
2182
|
+
display: grid;
|
|
2183
|
+
gap: 4px;
|
|
2055
2184
|
min-width: 0;
|
|
2056
2185
|
flex: 1;
|
|
2057
2186
|
}
|
|
@@ -2071,7 +2200,7 @@ function createStyleElement() {
|
|
|
2071
2200
|
border-radius: var(--df-review-radius-pill);
|
|
2072
2201
|
padding: 0 7px;
|
|
2073
2202
|
font-size: var(--df-review-font-size-2xs);
|
|
2074
|
-
font-weight:
|
|
2203
|
+
font-weight: var(--df-review-font-weight-emphasis);
|
|
2075
2204
|
line-height: 1;
|
|
2076
2205
|
letter-spacing: 0;
|
|
2077
2206
|
text-transform: uppercase;
|
|
@@ -2089,13 +2218,29 @@ function createStyleElement() {
|
|
|
2089
2218
|
color: rgba(247, 247, 242, 0.64);
|
|
2090
2219
|
}
|
|
2091
2220
|
|
|
2221
|
+
.dfwr-item-title {
|
|
2222
|
+
margin: 4px 0 0;
|
|
2223
|
+
color: var(--df-review-color-text);
|
|
2224
|
+
font-size: var(--df-review-font-size-md);
|
|
2225
|
+
font-weight: var(--df-review-font-weight-normal);
|
|
2226
|
+
line-height: 1.35;
|
|
2227
|
+
overflow-wrap: anywhere;
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2092
2230
|
.dfwr-item-comment {
|
|
2231
|
+
margin: 0;
|
|
2232
|
+
color: var(--df-review-color-text-muted);
|
|
2233
|
+
font-size: var(--df-review-font-size-sm);
|
|
2234
|
+
line-height: 1.45;
|
|
2235
|
+
overflow-wrap: anywhere;
|
|
2236
|
+
white-space: pre-wrap;
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2239
|
+
.dfwr-item-comment.is-primary {
|
|
2093
2240
|
margin: 4px 0;
|
|
2094
2241
|
color: var(--df-review-color-text);
|
|
2095
2242
|
font-size: var(--df-review-font-size-md);
|
|
2096
2243
|
line-height: 1.42;
|
|
2097
|
-
overflow-wrap: anywhere;
|
|
2098
|
-
white-space: pre-wrap;
|
|
2099
2244
|
}
|
|
2100
2245
|
|
|
2101
2246
|
.dfwr-item-date {
|
|
@@ -2339,7 +2484,7 @@ var WebReviewKitView = class {
|
|
|
2339
2484
|
);
|
|
2340
2485
|
}
|
|
2341
2486
|
}
|
|
2342
|
-
if (state.isOpen && state.mode === "area" && !state.areaDraft) {
|
|
2487
|
+
if (state.isOpen && state.mode === "area" && !state.areaDraft && !state.isSelectingArea) {
|
|
2343
2488
|
shell.append(this.createAreaLayer());
|
|
2344
2489
|
}
|
|
2345
2490
|
if (state.isOpen && state.mode === "area" && state.areaDraft && this.config.options.ui?.panel === false) {
|
|
@@ -2413,64 +2558,29 @@ var WebReviewKitView = class {
|
|
|
2413
2558
|
this.config.actions.setSelectingArea(false);
|
|
2414
2559
|
this.config.actions.render();
|
|
2415
2560
|
}
|
|
2561
|
+
// Draft adjustment geometry lives in draft.metrics.ts; these thin wrappers
|
|
2562
|
+
// supply the configured viewport presets so call sites stay unchanged.
|
|
2563
|
+
get viewportPresets() {
|
|
2564
|
+
return this.config.options.viewports?.presets;
|
|
2565
|
+
}
|
|
2416
2566
|
getDraftAdjustmentMetrics(draft) {
|
|
2417
|
-
|
|
2418
|
-
const x = adjustment?.x ?? 0;
|
|
2419
|
-
const y = adjustment?.y ?? 0;
|
|
2420
|
-
const scale = adjustment?.scale ?? 0;
|
|
2421
|
-
const {
|
|
2422
|
-
scale: viewportScale,
|
|
2423
|
-
designWidth,
|
|
2424
|
-
presetLabel
|
|
2425
|
-
} = this.getDraftViewportScale(draft.viewport);
|
|
2426
|
-
const selection = draft.selection ? toViewportSelection(draft.selection.viewport) : void 0;
|
|
2427
|
-
const scaleCssDelta = scale * viewportScale;
|
|
2428
|
-
const scaleFactor = selection && selection.width > 0 ? Math.max(
|
|
2429
|
-
1 / selection.width,
|
|
2430
|
-
(selection.width + scaleCssDelta) / selection.width
|
|
2431
|
-
) : 1;
|
|
2432
|
-
return {
|
|
2433
|
-
x,
|
|
2434
|
-
y,
|
|
2435
|
-
scale,
|
|
2436
|
-
cssX: x * viewportScale,
|
|
2437
|
-
cssY: y * viewportScale,
|
|
2438
|
-
scaleFactor,
|
|
2439
|
-
viewportScale,
|
|
2440
|
-
designWidth,
|
|
2441
|
-
presetLabel,
|
|
2442
|
-
viewportWidth: draft.viewport.width
|
|
2443
|
-
};
|
|
2567
|
+
return getDraftAdjustmentMetrics(draft, this.viewportPresets);
|
|
2444
2568
|
}
|
|
2445
2569
|
hasDraftAdjustment(draft) {
|
|
2446
|
-
|
|
2447
|
-
return metrics.x !== 0 || metrics.y !== 0 || metrics.scale !== 0;
|
|
2570
|
+
return hasDraftAdjustment(draft, this.viewportPresets);
|
|
2448
2571
|
}
|
|
2449
2572
|
getAdjustedDraftPoint(point, draft) {
|
|
2450
|
-
|
|
2451
|
-
return {
|
|
2452
|
-
x: point.x + metrics.cssX,
|
|
2453
|
-
y: point.y + metrics.cssY
|
|
2454
|
-
};
|
|
2573
|
+
return getAdjustedDraftPoint(point, draft, this.viewportPresets);
|
|
2455
2574
|
}
|
|
2456
2575
|
getAdjustedDraftSelection(selection, draft) {
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
width: selection.width * metrics.scaleFactor,
|
|
2463
|
-
height: selection.height * metrics.scaleFactor
|
|
2464
|
-
};
|
|
2576
|
+
return getAdjustedDraftSelection(
|
|
2577
|
+
selection,
|
|
2578
|
+
draft,
|
|
2579
|
+
this.viewportPresets
|
|
2580
|
+
);
|
|
2465
2581
|
}
|
|
2466
2582
|
getDraftViewportScale(viewport) {
|
|
2467
|
-
|
|
2468
|
-
viewport,
|
|
2469
|
-
this.config.options.viewports?.presets
|
|
2470
|
-
);
|
|
2471
|
-
const designWidth = typeof preset.designWidth === "number" && preset.designWidth > 0 ? preset.designWidth : viewport.width;
|
|
2472
|
-
const scale = designWidth > 0 ? viewport.width / designWidth : 1;
|
|
2473
|
-
return { scale, designWidth, presetLabel: preset.label };
|
|
2583
|
+
return getDraftViewportScale(viewport, this.viewportPresets);
|
|
2474
2584
|
}
|
|
2475
2585
|
getDraftComposerWidth(environment) {
|
|
2476
2586
|
const bounds = environment.overlayRect;
|
|
@@ -2616,6 +2726,67 @@ var WebReviewKitView = class {
|
|
|
2616
2726
|
return trimmedComment ? `${trimmedComment}
|
|
2617
2727
|
${adjustment}` : adjustment;
|
|
2618
2728
|
}
|
|
2729
|
+
getAssigneeOption(assigneeId) {
|
|
2730
|
+
if (!assigneeId) return void 0;
|
|
2731
|
+
return this.config.options.assigneeOptions?.find(
|
|
2732
|
+
(option) => option.value === assigneeId
|
|
2733
|
+
);
|
|
2734
|
+
}
|
|
2735
|
+
getAssigneeName(assigneeId) {
|
|
2736
|
+
return this.getAssigneeOption(assigneeId)?.label;
|
|
2737
|
+
}
|
|
2738
|
+
createDraftTitleInput(value, onInput) {
|
|
2739
|
+
const input = document.createElement("input");
|
|
2740
|
+
input.className = "dfwr-input";
|
|
2741
|
+
input.placeholder = "Title";
|
|
2742
|
+
input.type = "text";
|
|
2743
|
+
input.value = value ?? "";
|
|
2744
|
+
input.addEventListener("input", () => onInput(input.value));
|
|
2745
|
+
return input;
|
|
2746
|
+
}
|
|
2747
|
+
isTitleFieldEnabled() {
|
|
2748
|
+
return this.config.options.fields?.title === true;
|
|
2749
|
+
}
|
|
2750
|
+
createDraftAssigneeSelect(value, fallbackLabel, onChange) {
|
|
2751
|
+
const assigneeOptions = this.config.options.assigneeOptions ?? [];
|
|
2752
|
+
if (assigneeOptions.length === 0) return void 0;
|
|
2753
|
+
const assigneeTitle = this.config.options.assigneeTitle?.trim() || "Assignee";
|
|
2754
|
+
const select = document.createElement("select");
|
|
2755
|
+
select.className = "dfwr-select";
|
|
2756
|
+
const emptyOption = document.createElement("option");
|
|
2757
|
+
emptyOption.value = "";
|
|
2758
|
+
emptyOption.textContent = assigneeTitle;
|
|
2759
|
+
select.append(emptyOption);
|
|
2760
|
+
const hasUnknownAssignee = Boolean(value) && !assigneeOptions.some((option) => option.value === value);
|
|
2761
|
+
if (hasUnknownAssignee && value) {
|
|
2762
|
+
const option = document.createElement("option");
|
|
2763
|
+
option.value = value;
|
|
2764
|
+
option.textContent = fallbackLabel ?? value;
|
|
2765
|
+
select.append(option);
|
|
2766
|
+
}
|
|
2767
|
+
assigneeOptions.forEach((assigneeOption) => {
|
|
2768
|
+
const option = document.createElement("option");
|
|
2769
|
+
option.value = assigneeOption.value;
|
|
2770
|
+
option.textContent = assigneeOption.label;
|
|
2771
|
+
select.append(option);
|
|
2772
|
+
});
|
|
2773
|
+
select.value = value ?? "";
|
|
2774
|
+
select.addEventListener("change", () => {
|
|
2775
|
+
onChange(select.value || null, this.getAssigneeName(select.value));
|
|
2776
|
+
});
|
|
2777
|
+
return select;
|
|
2778
|
+
}
|
|
2779
|
+
getDraftFields(titleInput, textarea, assigneeSelect) {
|
|
2780
|
+
const title = titleInput?.value.trim();
|
|
2781
|
+
const comment = textarea.value.trim();
|
|
2782
|
+
const assigneeId = assigneeSelect?.value.trim() || void 0;
|
|
2783
|
+
return {
|
|
2784
|
+
title: title || void 0,
|
|
2785
|
+
comment,
|
|
2786
|
+
assigneeId,
|
|
2787
|
+
assigneeName: this.getAssigneeName(assigneeId)
|
|
2788
|
+
};
|
|
2789
|
+
}
|
|
2619
2790
|
getStyleableDraftElement(draft, environment) {
|
|
2620
2791
|
if (draft.previewElement && draft.previewElement.ownerDocument === environment.document && "style" in draft.previewElement) {
|
|
2621
2792
|
return draft.previewElement;
|
|
@@ -2806,6 +2977,9 @@ ${adjustment}` : adjustment;
|
|
|
2806
2977
|
empty.textContent = this.state.noteDraft ? "Write the note in the page box." : this.state.mode === "element" ? "Click an element to add QA." : "Click on the page to place a note.";
|
|
2807
2978
|
return empty;
|
|
2808
2979
|
}
|
|
2980
|
+
// Builds the note draft layer: the on-page marker/highlight plus its composer
|
|
2981
|
+
// popover. When dockComposer is set the composer renders into the side panel
|
|
2982
|
+
// instead of floating next to the marker (used for the docked review mode).
|
|
2809
2983
|
createNotePopover(draft, options = {}) {
|
|
2810
2984
|
const environment = this.config.getEnvironment();
|
|
2811
2985
|
const group = document.createElement("div");
|
|
@@ -2869,6 +3043,14 @@ ${adjustment}` : adjustment;
|
|
|
2869
3043
|
meta.className = "dfwr-item-date";
|
|
2870
3044
|
meta.textContent = formatNoteDraftMeta(draft);
|
|
2871
3045
|
}
|
|
3046
|
+
const titleInput = this.isTitleFieldEnabled() ? this.createDraftTitleInput(draft.title, (title) => {
|
|
3047
|
+
const noteDraft = this.state.noteDraft;
|
|
3048
|
+
if (!noteDraft) return;
|
|
3049
|
+
this.config.actions.setNoteDraft({
|
|
3050
|
+
...noteDraft,
|
|
3051
|
+
title
|
|
3052
|
+
});
|
|
3053
|
+
}) : void 0;
|
|
2872
3054
|
const textarea = document.createElement("textarea");
|
|
2873
3055
|
textarea.className = "dfwr-textarea";
|
|
2874
3056
|
textarea.placeholder = "Review comment";
|
|
@@ -2882,13 +3064,30 @@ ${adjustment}` : adjustment;
|
|
|
2882
3064
|
comment: textarea.value
|
|
2883
3065
|
});
|
|
2884
3066
|
});
|
|
3067
|
+
const assigneeSelect = this.createDraftAssigneeSelect(
|
|
3068
|
+
draft.assigneeId,
|
|
3069
|
+
draft.assigneeName,
|
|
3070
|
+
(assigneeId, assigneeName) => {
|
|
3071
|
+
const noteDraft = this.state.noteDraft;
|
|
3072
|
+
if (!noteDraft) return;
|
|
3073
|
+
this.config.actions.setNoteDraft({
|
|
3074
|
+
...noteDraft,
|
|
3075
|
+
assigneeId,
|
|
3076
|
+
assigneeName
|
|
3077
|
+
});
|
|
3078
|
+
}
|
|
3079
|
+
);
|
|
2885
3080
|
const saveDraft = () => {
|
|
2886
|
-
const comment = textarea.value.trim();
|
|
2887
3081
|
const currentDraft = this.state.noteDraft ?? draft;
|
|
3082
|
+
const fields = this.getDraftFields(titleInput, textarea, assigneeSelect);
|
|
3083
|
+
const comment = fields.comment;
|
|
2888
3084
|
if (!comment && !this.hasDraftAdjustment(currentDraft)) return;
|
|
2889
3085
|
void this.config.actions.createItem({
|
|
2890
3086
|
kind: "note",
|
|
3087
|
+
title: fields.title,
|
|
2891
3088
|
comment: this.withDraftAdjustmentComment(comment, currentDraft),
|
|
3089
|
+
assigneeId: fields.assigneeId,
|
|
3090
|
+
assigneeName: fields.assigneeName,
|
|
2892
3091
|
viewport: currentDraft.viewport,
|
|
2893
3092
|
anchor: currentDraft.anchor,
|
|
2894
3093
|
marker: currentDraft.marker,
|
|
@@ -2906,10 +3105,14 @@ ${adjustment}` : adjustment;
|
|
|
2906
3105
|
const actions = this.createFormActions("Save note", saveDraft, {
|
|
2907
3106
|
leading: adjustmentControls?.actionButton ? [adjustmentControls.actionButton] : void 0
|
|
2908
3107
|
});
|
|
3108
|
+
const error = this.createDraftError();
|
|
2909
3109
|
form.append(
|
|
2910
3110
|
...meta ? [meta] : [],
|
|
2911
3111
|
...adjustmentControls ? [adjustmentControls.panel] : [],
|
|
3112
|
+
...titleInput ? [titleInput] : [],
|
|
2912
3113
|
textarea,
|
|
3114
|
+
...assigneeSelect ? [assigneeSelect] : [],
|
|
3115
|
+
...error ? [error] : [],
|
|
2913
3116
|
actions
|
|
2914
3117
|
);
|
|
2915
3118
|
const dragHandle = isElementDraft && !options.dockComposer ? this.createDraftDragHandle("Move DOM composer") : void 0;
|
|
@@ -3036,6 +3239,9 @@ ${adjustment}` : adjustment;
|
|
|
3036
3239
|
handle.addEventListener("pointerup", stopDrag);
|
|
3037
3240
|
handle.addEventListener("pointercancel", stopDrag);
|
|
3038
3241
|
}
|
|
3242
|
+
// Builds the element-adjustment controls (nudge the previewed element via
|
|
3243
|
+
// arrow keys / buttons). Wires keyboard deltas to the draft transform and
|
|
3244
|
+
// keeps the pin, popover, highlight and textarea in sync as the value changes.
|
|
3039
3245
|
createAdjustmentControls({
|
|
3040
3246
|
draft,
|
|
3041
3247
|
pin,
|
|
@@ -3180,6 +3386,14 @@ ${adjustment}` : adjustment;
|
|
|
3180
3386
|
return form;
|
|
3181
3387
|
}
|
|
3182
3388
|
form.append(this.createAreaMetricsPanel(areaDraft));
|
|
3389
|
+
const titleInput = this.isTitleFieldEnabled() ? this.createDraftTitleInput(areaDraft.title, (title) => {
|
|
3390
|
+
const draft = this.state.areaDraft;
|
|
3391
|
+
if (!draft) return;
|
|
3392
|
+
this.config.actions.setAreaDraft({
|
|
3393
|
+
...draft,
|
|
3394
|
+
title
|
|
3395
|
+
});
|
|
3396
|
+
}) : void 0;
|
|
3183
3397
|
const textarea = document.createElement("textarea");
|
|
3184
3398
|
textarea.className = "dfwr-textarea";
|
|
3185
3399
|
textarea.placeholder = "Area comment";
|
|
@@ -3193,20 +3407,44 @@ ${adjustment}` : adjustment;
|
|
|
3193
3407
|
comment: textarea.value
|
|
3194
3408
|
});
|
|
3195
3409
|
});
|
|
3410
|
+
const assigneeSelect = this.createDraftAssigneeSelect(
|
|
3411
|
+
areaDraft.assigneeId,
|
|
3412
|
+
areaDraft.assigneeName,
|
|
3413
|
+
(assigneeId, assigneeName) => {
|
|
3414
|
+
const draft = this.state.areaDraft;
|
|
3415
|
+
if (!draft) return;
|
|
3416
|
+
this.config.actions.setAreaDraft({
|
|
3417
|
+
...draft,
|
|
3418
|
+
assigneeId,
|
|
3419
|
+
assigneeName
|
|
3420
|
+
});
|
|
3421
|
+
}
|
|
3422
|
+
);
|
|
3196
3423
|
const actions = this.createFormActions("Save area", () => {
|
|
3197
|
-
const comment = textarea.value.trim();
|
|
3198
3424
|
const draft = this.state.areaDraft;
|
|
3425
|
+
const fields = this.getDraftFields(titleInput, textarea, assigneeSelect);
|
|
3426
|
+
const comment = fields.comment;
|
|
3199
3427
|
if (!comment || !draft) return;
|
|
3200
3428
|
void this.config.actions.createItem({
|
|
3201
3429
|
kind: "area",
|
|
3430
|
+
title: fields.title,
|
|
3202
3431
|
comment,
|
|
3432
|
+
assigneeId: fields.assigneeId,
|
|
3433
|
+
assigneeName: fields.assigneeName,
|
|
3203
3434
|
viewport: draft.viewport,
|
|
3204
3435
|
anchor: draft.anchor,
|
|
3205
3436
|
marker: draft.marker,
|
|
3206
3437
|
selection: draft.selection
|
|
3207
3438
|
});
|
|
3208
3439
|
});
|
|
3209
|
-
|
|
3440
|
+
const error = this.createDraftError();
|
|
3441
|
+
form.append(
|
|
3442
|
+
...titleInput ? [titleInput] : [],
|
|
3443
|
+
textarea,
|
|
3444
|
+
...assigneeSelect ? [assigneeSelect] : [],
|
|
3445
|
+
...error ? [error] : [],
|
|
3446
|
+
actions
|
|
3447
|
+
);
|
|
3210
3448
|
return form;
|
|
3211
3449
|
}
|
|
3212
3450
|
createAreaMetricsPanel(draft) {
|
|
@@ -3298,18 +3536,27 @@ ${adjustment}` : adjustment;
|
|
|
3298
3536
|
createFormActions(saveLabel, onSave, options) {
|
|
3299
3537
|
const actions = document.createElement("div");
|
|
3300
3538
|
actions.className = ["dfwr-actions", options?.className].filter(Boolean).join(" ");
|
|
3539
|
+
const isSaving = this.state.isCreatingItem;
|
|
3301
3540
|
const save = document.createElement("button");
|
|
3302
3541
|
save.className = "dfwr-button is-primary";
|
|
3303
3542
|
save.type = "button";
|
|
3304
|
-
save.
|
|
3543
|
+
save.disabled = isSaving;
|
|
3544
|
+
save.setAttribute("aria-busy", isSaving ? "true" : "false");
|
|
3545
|
+
if (isSaving) {
|
|
3546
|
+
save.append(this.createSpinner("dfwr-spinner"), "Saving...");
|
|
3547
|
+
} else {
|
|
3548
|
+
save.textContent = saveLabel;
|
|
3549
|
+
}
|
|
3305
3550
|
save.addEventListener("click", (event) => {
|
|
3306
3551
|
event.preventDefault();
|
|
3307
3552
|
event.stopPropagation();
|
|
3553
|
+
if (this.state.isCreatingItem) return;
|
|
3308
3554
|
onSave();
|
|
3309
3555
|
});
|
|
3310
3556
|
const cancel = document.createElement("button");
|
|
3311
3557
|
cancel.className = "dfwr-button";
|
|
3312
3558
|
cancel.type = "button";
|
|
3559
|
+
cancel.disabled = isSaving;
|
|
3313
3560
|
cancel.textContent = "Cancel";
|
|
3314
3561
|
cancel.addEventListener("click", (event) => {
|
|
3315
3562
|
this.cancelDraft(event);
|
|
@@ -3332,6 +3579,20 @@ ${adjustment}` : adjustment;
|
|
|
3332
3579
|
actions.append(save, cancel);
|
|
3333
3580
|
return actions;
|
|
3334
3581
|
}
|
|
3582
|
+
createSpinner(className) {
|
|
3583
|
+
const spinner = document.createElement("span");
|
|
3584
|
+
spinner.className = className;
|
|
3585
|
+
spinner.setAttribute("aria-hidden", "true");
|
|
3586
|
+
return spinner;
|
|
3587
|
+
}
|
|
3588
|
+
createDraftError() {
|
|
3589
|
+
if (!this.state.draftError) return void 0;
|
|
3590
|
+
const error = document.createElement("p");
|
|
3591
|
+
error.className = "dfwr-form-error";
|
|
3592
|
+
error.setAttribute("role", "alert");
|
|
3593
|
+
error.textContent = this.state.draftError;
|
|
3594
|
+
return error;
|
|
3595
|
+
}
|
|
3335
3596
|
createList() {
|
|
3336
3597
|
const section = document.createElement("div");
|
|
3337
3598
|
section.className = "dfwr-list";
|
|
@@ -3384,14 +3645,20 @@ ${adjustment}` : adjustment;
|
|
|
3384
3645
|
kind.className = "dfwr-item-kind";
|
|
3385
3646
|
kind.textContent = item.kind;
|
|
3386
3647
|
badges.append(scope, kind);
|
|
3648
|
+
const title = this.isTitleFieldEnabled() ? item.title?.trim() : "";
|
|
3649
|
+
const titleElement = title ? document.createElement("strong") : void 0;
|
|
3650
|
+
if (title && titleElement) {
|
|
3651
|
+
titleElement.className = "dfwr-item-title";
|
|
3652
|
+
titleElement.textContent = title;
|
|
3653
|
+
}
|
|
3387
3654
|
const comment = document.createElement("p");
|
|
3388
|
-
comment.className =
|
|
3655
|
+
comment.className = `dfwr-item-comment${title ? "" : " is-primary"}`;
|
|
3389
3656
|
comment.textContent = item.comment;
|
|
3390
3657
|
const date = document.createElement("time");
|
|
3391
3658
|
date.className = "dfwr-item-date";
|
|
3392
3659
|
date.dateTime = item.createdAt;
|
|
3393
3660
|
date.textContent = formatItemMeta(item);
|
|
3394
|
-
body.append(badges, comment, date);
|
|
3661
|
+
body.append(badges, ...titleElement ? [titleElement] : [], comment, date);
|
|
3395
3662
|
const actions = document.createElement("div");
|
|
3396
3663
|
actions.className = "dfwr-item-actions";
|
|
3397
3664
|
actions.addEventListener("click", (event) => event.stopPropagation());
|
|
@@ -3580,7 +3847,14 @@ ${formatItemMeta(item)}`;
|
|
|
3580
3847
|
event,
|
|
3581
3848
|
this.config.getEnvironment()
|
|
3582
3849
|
);
|
|
3583
|
-
|
|
3850
|
+
const currentDraft = this.state.noteDraft;
|
|
3851
|
+
const fields = {
|
|
3852
|
+
title: currentDraft?.title,
|
|
3853
|
+
comment: textarea.value,
|
|
3854
|
+
assigneeId: currentDraft?.assigneeId,
|
|
3855
|
+
assigneeName: currentDraft?.assigneeName
|
|
3856
|
+
};
|
|
3857
|
+
void (this.state.mode === "element" ? this.config.actions.bindElementDraftToPoint(nextPoint, fields) : this.config.actions.bindNoteDraftToPoint(nextPoint, fields));
|
|
3584
3858
|
});
|
|
3585
3859
|
}
|
|
3586
3860
|
createNoteLayer() {
|
|
@@ -3658,10 +3932,14 @@ ${formatItemMeta(item)}`;
|
|
|
3658
3932
|
let startX = 0;
|
|
3659
3933
|
let startY = 0;
|
|
3660
3934
|
let selection;
|
|
3935
|
+
let activePointerId;
|
|
3936
|
+
let isDragging = false;
|
|
3937
|
+
const ownerWindow = layer.ownerDocument.defaultView ?? window;
|
|
3661
3938
|
const updateBox = (event) => {
|
|
3939
|
+
const nextEnvironment = this.config.getEnvironment();
|
|
3662
3940
|
const nextPoint = toTargetPointFromHostEvent(
|
|
3663
3941
|
event,
|
|
3664
|
-
|
|
3942
|
+
nextEnvironment
|
|
3665
3943
|
);
|
|
3666
3944
|
const left = Math.min(startX, nextPoint.x);
|
|
3667
3945
|
const top = Math.min(startY, nextPoint.y);
|
|
@@ -3669,7 +3947,7 @@ ${formatItemMeta(item)}`;
|
|
|
3669
3947
|
const height = Math.abs(nextPoint.y - startY);
|
|
3670
3948
|
const hostPoint = toHostPoint(
|
|
3671
3949
|
{ x: left, y: top },
|
|
3672
|
-
|
|
3950
|
+
nextEnvironment
|
|
3673
3951
|
);
|
|
3674
3952
|
selection = { left, top, width, height };
|
|
3675
3953
|
box.style.left = `${hostPoint.x}px`;
|
|
@@ -3677,9 +3955,68 @@ ${formatItemMeta(item)}`;
|
|
|
3677
3955
|
box.style.width = `${width}px`;
|
|
3678
3956
|
box.style.height = `${height}px`;
|
|
3679
3957
|
};
|
|
3958
|
+
const addDragListeners = () => {
|
|
3959
|
+
ownerWindow.addEventListener("pointermove", handlePointerMove, true);
|
|
3960
|
+
ownerWindow.addEventListener("pointerup", handlePointerUp, true);
|
|
3961
|
+
ownerWindow.addEventListener("pointercancel", handlePointerCancel, true);
|
|
3962
|
+
};
|
|
3963
|
+
const removeDragListeners = () => {
|
|
3964
|
+
ownerWindow.removeEventListener("pointermove", handlePointerMove, true);
|
|
3965
|
+
ownerWindow.removeEventListener("pointerup", handlePointerUp, true);
|
|
3966
|
+
ownerWindow.removeEventListener(
|
|
3967
|
+
"pointercancel",
|
|
3968
|
+
handlePointerCancel,
|
|
3969
|
+
true
|
|
3970
|
+
);
|
|
3971
|
+
};
|
|
3972
|
+
const releasePointerCapture = (event) => {
|
|
3973
|
+
try {
|
|
3974
|
+
if (layer.hasPointerCapture(event.pointerId)) {
|
|
3975
|
+
layer.releasePointerCapture(event.pointerId);
|
|
3976
|
+
}
|
|
3977
|
+
} catch {
|
|
3978
|
+
}
|
|
3979
|
+
};
|
|
3980
|
+
function isActivePointer(event) {
|
|
3981
|
+
return isDragging && event.pointerId === activePointerId;
|
|
3982
|
+
}
|
|
3983
|
+
const finishAreaSelection = (event) => {
|
|
3984
|
+
if (!isActivePointer(event)) return;
|
|
3985
|
+
event.preventDefault();
|
|
3986
|
+
updateBox(event);
|
|
3987
|
+
releasePointerCapture(event);
|
|
3988
|
+
removeDragListeners();
|
|
3989
|
+
isDragging = false;
|
|
3990
|
+
activePointerId = void 0;
|
|
3991
|
+
if (!selection || selection.width < 8 || selection.height < 8) return;
|
|
3992
|
+
this.config.actions.setSelectingArea(true);
|
|
3993
|
+
this.config.actions.render();
|
|
3994
|
+
void this.config.actions.createAreaDraft(selection);
|
|
3995
|
+
};
|
|
3996
|
+
function handlePointerMove(event) {
|
|
3997
|
+
if (!isActivePointer(event)) return;
|
|
3998
|
+
event.preventDefault();
|
|
3999
|
+
updateBox(event);
|
|
4000
|
+
}
|
|
4001
|
+
const handlePointerUp = (event) => {
|
|
4002
|
+
finishAreaSelection(event);
|
|
4003
|
+
};
|
|
4004
|
+
const handlePointerCancel = (event) => {
|
|
4005
|
+
if (!isActivePointer(event)) return;
|
|
4006
|
+
releasePointerCapture(event);
|
|
4007
|
+
removeDragListeners();
|
|
4008
|
+
isDragging = false;
|
|
4009
|
+
activePointerId = void 0;
|
|
4010
|
+
};
|
|
3680
4011
|
layer.addEventListener("pointerdown", (event) => {
|
|
4012
|
+
if (event.button !== 0) return;
|
|
3681
4013
|
event.preventDefault();
|
|
3682
|
-
|
|
4014
|
+
activePointerId = event.pointerId;
|
|
4015
|
+
isDragging = true;
|
|
4016
|
+
try {
|
|
4017
|
+
layer.setPointerCapture(event.pointerId);
|
|
4018
|
+
} catch {
|
|
4019
|
+
}
|
|
3683
4020
|
const startPoint = toTargetPointFromHostEvent(
|
|
3684
4021
|
event,
|
|
3685
4022
|
this.config.getEnvironment()
|
|
@@ -3687,20 +4024,11 @@ ${formatItemMeta(item)}`;
|
|
|
3687
4024
|
startX = startPoint.x;
|
|
3688
4025
|
startY = startPoint.y;
|
|
3689
4026
|
updateBox(event);
|
|
4027
|
+
addDragListeners();
|
|
3690
4028
|
});
|
|
3691
|
-
layer.addEventListener("pointermove",
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
});
|
|
3695
|
-
layer.addEventListener("pointerup", (event) => {
|
|
3696
|
-
if (!layer.hasPointerCapture(event.pointerId)) return;
|
|
3697
|
-
layer.releasePointerCapture(event.pointerId);
|
|
3698
|
-
updateBox(event);
|
|
3699
|
-
if (!selection || selection.width < 8 || selection.height < 8) return;
|
|
3700
|
-
this.config.actions.setSelectingArea(true);
|
|
3701
|
-
this.config.actions.render();
|
|
3702
|
-
void this.config.actions.createAreaDraft(selection);
|
|
3703
|
-
});
|
|
4029
|
+
layer.addEventListener("pointermove", handlePointerMove);
|
|
4030
|
+
layer.addEventListener("pointerup", handlePointerUp);
|
|
4031
|
+
layer.addEventListener("pointercancel", handlePointerCancel);
|
|
3704
4032
|
return layer;
|
|
3705
4033
|
}
|
|
3706
4034
|
};
|
|
@@ -3740,6 +4068,8 @@ var WebReviewKitApp = class {
|
|
|
3740
4068
|
this.isOpen = false;
|
|
3741
4069
|
this.mode = "idle";
|
|
3742
4070
|
this.items = [];
|
|
4071
|
+
this.draftError = "";
|
|
4072
|
+
this.isCreatingItem = false;
|
|
3743
4073
|
this.isSelectingArea = false;
|
|
3744
4074
|
this.handleKeyDown = (event) => {
|
|
3745
4075
|
if (event.key === "Escape" && this.cancelMode()) {
|
|
@@ -3770,6 +4100,8 @@ var WebReviewKitApp = class {
|
|
|
3770
4100
|
items: this.items,
|
|
3771
4101
|
noteDraft: this.noteDraft,
|
|
3772
4102
|
areaDraft: this.areaDraft,
|
|
4103
|
+
draftError: this.draftError,
|
|
4104
|
+
isCreatingItem: this.isCreatingItem,
|
|
3773
4105
|
isSelectingArea: this.isSelectingArea,
|
|
3774
4106
|
highlightedItemId: this.highlightedItemId
|
|
3775
4107
|
}),
|
|
@@ -3784,19 +4116,22 @@ var WebReviewKitApp = class {
|
|
|
3784
4116
|
clearDrafts: () => {
|
|
3785
4117
|
this.noteDraft = void 0;
|
|
3786
4118
|
this.areaDraft = void 0;
|
|
4119
|
+
this.draftError = "";
|
|
3787
4120
|
},
|
|
3788
4121
|
setNoteDraft: (draft) => {
|
|
3789
4122
|
this.noteDraft = draft;
|
|
4123
|
+
this.draftError = "";
|
|
3790
4124
|
},
|
|
3791
4125
|
setAreaDraft: (draft) => {
|
|
3792
4126
|
this.areaDraft = draft;
|
|
4127
|
+
this.draftError = "";
|
|
3793
4128
|
},
|
|
3794
4129
|
setSelectingArea: (isSelectingArea) => {
|
|
3795
4130
|
this.isSelectingArea = isSelectingArea;
|
|
3796
4131
|
},
|
|
3797
4132
|
createItem: (input) => this.createItem(input),
|
|
3798
|
-
bindNoteDraftToPoint: (point,
|
|
3799
|
-
bindElementDraftToPoint: (point,
|
|
4133
|
+
bindNoteDraftToPoint: (point, fields) => this.bindNoteDraftToPoint(point, fields),
|
|
4134
|
+
bindElementDraftToPoint: (point, fields) => this.bindElementDraftToPoint(point, fields),
|
|
3800
4135
|
createAreaDraft: (selection) => this.createAreaDraft(selection)
|
|
3801
4136
|
}
|
|
3802
4137
|
});
|
|
@@ -3865,7 +4200,7 @@ var WebReviewKitApp = class {
|
|
|
3865
4200
|
this.noteDraft = void 0;
|
|
3866
4201
|
this.areaDraft = void 0;
|
|
3867
4202
|
this.isSelectingArea = false;
|
|
3868
|
-
await this.bindElementDraftToElement(element, comment);
|
|
4203
|
+
await this.bindElementDraftToElement(element, { comment });
|
|
3869
4204
|
}
|
|
3870
4205
|
getMode() {
|
|
3871
4206
|
return this.mode;
|
|
@@ -4008,7 +4343,7 @@ var WebReviewKitApp = class {
|
|
|
4008
4343
|
if (!this.shadow) return;
|
|
4009
4344
|
this.view.render(this.shadow, this.createHiddenItemsStyleElement());
|
|
4010
4345
|
}
|
|
4011
|
-
async bindNoteDraftToPoint(point,
|
|
4346
|
+
async bindNoteDraftToPoint(point, fields = {}) {
|
|
4012
4347
|
const environment = this.getEnvironment();
|
|
4013
4348
|
if (!environment) return;
|
|
4014
4349
|
const viewport = getViewportSize(environment);
|
|
@@ -4028,13 +4363,13 @@ var WebReviewKitApp = class {
|
|
|
4028
4363
|
viewport,
|
|
4029
4364
|
anchor,
|
|
4030
4365
|
marker,
|
|
4031
|
-
|
|
4366
|
+
...fields
|
|
4032
4367
|
};
|
|
4033
4368
|
});
|
|
4034
4369
|
this.noteDraft = draft;
|
|
4035
4370
|
this.render();
|
|
4036
4371
|
}
|
|
4037
|
-
async bindElementDraftToPoint(point,
|
|
4372
|
+
async bindElementDraftToPoint(point, fields = {}) {
|
|
4038
4373
|
const environment = this.getEnvironment();
|
|
4039
4374
|
if (!environment) return;
|
|
4040
4375
|
const viewport = getViewportSize(environment);
|
|
@@ -4078,14 +4413,14 @@ var WebReviewKitApp = class {
|
|
|
4078
4413
|
anchor,
|
|
4079
4414
|
marker,
|
|
4080
4415
|
selection: reviewSelection,
|
|
4081
|
-
|
|
4416
|
+
...fields,
|
|
4082
4417
|
previewElement
|
|
4083
4418
|
};
|
|
4084
4419
|
});
|
|
4085
4420
|
this.noteDraft = draft;
|
|
4086
4421
|
this.render();
|
|
4087
4422
|
}
|
|
4088
|
-
async bindElementDraftToElement(element,
|
|
4423
|
+
async bindElementDraftToElement(element, fields = {}) {
|
|
4089
4424
|
const environment = this.getEnvironment();
|
|
4090
4425
|
if (!environment || element.ownerDocument !== environment.document) return;
|
|
4091
4426
|
const viewport = getViewportSize(environment);
|
|
@@ -4118,7 +4453,7 @@ var WebReviewKitApp = class {
|
|
|
4118
4453
|
anchor,
|
|
4119
4454
|
marker,
|
|
4120
4455
|
selection: reviewSelection,
|
|
4121
|
-
|
|
4456
|
+
...fields,
|
|
4122
4457
|
previewElement
|
|
4123
4458
|
};
|
|
4124
4459
|
});
|
|
@@ -4128,26 +4463,33 @@ var WebReviewKitApp = class {
|
|
|
4128
4463
|
}
|
|
4129
4464
|
async createAreaDraft(selection) {
|
|
4130
4465
|
const environment = this.getEnvironment();
|
|
4131
|
-
if (!environment)
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
)
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4466
|
+
if (!environment) {
|
|
4467
|
+
this.isSelectingArea = false;
|
|
4468
|
+
this.render();
|
|
4469
|
+
return;
|
|
4470
|
+
}
|
|
4471
|
+
try {
|
|
4472
|
+
const viewport = getViewportSize(environment);
|
|
4473
|
+
this.areaDraft = await this.withOverlayHidden(() => {
|
|
4474
|
+
const marker = createSelectionCenterMarker(
|
|
4475
|
+
selection,
|
|
4476
|
+
void 0,
|
|
4477
|
+
environment
|
|
4478
|
+
);
|
|
4479
|
+
const reviewSelection = {
|
|
4480
|
+
viewport: toPublicSelection(selection)
|
|
4481
|
+
};
|
|
4482
|
+
return {
|
|
4483
|
+
viewport,
|
|
4484
|
+
marker,
|
|
4485
|
+
selection: reviewSelection
|
|
4486
|
+
};
|
|
4487
|
+
});
|
|
4488
|
+
this.setModeState("area");
|
|
4489
|
+
} finally {
|
|
4490
|
+
this.isSelectingArea = false;
|
|
4491
|
+
this.render();
|
|
4492
|
+
}
|
|
4151
4493
|
}
|
|
4152
4494
|
async withOverlayHidden(callback) {
|
|
4153
4495
|
if (!this.root) return callback();
|
|
@@ -4161,11 +4503,16 @@ var WebReviewKitApp = class {
|
|
|
4161
4503
|
}
|
|
4162
4504
|
async createItem(input) {
|
|
4163
4505
|
const environment = this.getEnvironment();
|
|
4164
|
-
if (!environment) return;
|
|
4506
|
+
if (!environment || this.isCreatingItem) return;
|
|
4165
4507
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4166
4508
|
const routeKey = getRouteKey(environment);
|
|
4167
4509
|
const viewport = input.viewport ?? getViewportSize(environment);
|
|
4168
4510
|
const createdBy = this.options.userId?.trim();
|
|
4511
|
+
const title = input.title?.trim();
|
|
4512
|
+
const assigneeId = input.assigneeId?.trim() || void 0;
|
|
4513
|
+
const assigneeOption = this.options.assigneeOptions?.find(
|
|
4514
|
+
(option) => option.value === assigneeId
|
|
4515
|
+
);
|
|
4169
4516
|
const item = {
|
|
4170
4517
|
id: createId(),
|
|
4171
4518
|
projectId: this.options.projectId,
|
|
@@ -4175,8 +4522,10 @@ var WebReviewKitApp = class {
|
|
|
4175
4522
|
normalizedPath: routeKey,
|
|
4176
4523
|
scope: input.scope ?? getReviewViewportScope(viewport, this.options.viewports?.presets),
|
|
4177
4524
|
kind: input.kind,
|
|
4178
|
-
title:
|
|
4525
|
+
title: title || void 0,
|
|
4179
4526
|
comment: input.comment,
|
|
4527
|
+
assigneeId,
|
|
4528
|
+
assigneeName: input.assigneeName ?? assigneeOption?.label,
|
|
4180
4529
|
createdBy: createdBy || void 0,
|
|
4181
4530
|
status: "todo",
|
|
4182
4531
|
viewport,
|
|
@@ -4191,13 +4540,23 @@ var WebReviewKitApp = class {
|
|
|
4191
4540
|
createdAt: now,
|
|
4192
4541
|
updatedAt: now
|
|
4193
4542
|
};
|
|
4194
|
-
|
|
4195
|
-
this.
|
|
4196
|
-
this.
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4543
|
+
this.draftError = "";
|
|
4544
|
+
this.isCreatingItem = true;
|
|
4545
|
+
this.render();
|
|
4546
|
+
try {
|
|
4547
|
+
const createdItem = await this.adapter.create(item);
|
|
4548
|
+
this.setModeState("idle");
|
|
4549
|
+
this.noteDraft = void 0;
|
|
4550
|
+
this.areaDraft = void 0;
|
|
4551
|
+
this.highlightItem(createdItem.id);
|
|
4552
|
+
await this.reload();
|
|
4553
|
+
await this.options.onCreateItem?.(createdItem);
|
|
4554
|
+
} catch (error) {
|
|
4555
|
+
this.draftError = error instanceof Error ? error.message : "Failed to save QA.";
|
|
4556
|
+
} finally {
|
|
4557
|
+
this.isCreatingItem = false;
|
|
4558
|
+
this.render();
|
|
4559
|
+
}
|
|
4201
4560
|
}
|
|
4202
4561
|
async restoreItem(item) {
|
|
4203
4562
|
this.setModeState("idle");
|
|
@@ -4254,6 +4613,7 @@ export {
|
|
|
4254
4613
|
REVIEW_WORKFLOW_STATUS_OPTIONS,
|
|
4255
4614
|
normalizeReviewItemStatus,
|
|
4256
4615
|
localAdapter,
|
|
4616
|
+
DEFAULT_REVIEW_FIGMA_IMAGE_FORMAT,
|
|
4257
4617
|
clamp,
|
|
4258
4618
|
DEFAULT_REVIEW_VIEWPORTS,
|
|
4259
4619
|
findReviewViewportPreset,
|
|
@@ -4262,6 +4622,7 @@ export {
|
|
|
4262
4622
|
getReviewItemScopeLabel,
|
|
4263
4623
|
getNumberedReviewItems,
|
|
4264
4624
|
runWithAutoScrollBehavior,
|
|
4625
|
+
reviewTypographyTokens,
|
|
4265
4626
|
createWebReviewKit
|
|
4266
4627
|
};
|
|
4267
|
-
//# sourceMappingURL=chunk-
|
|
4628
|
+
//# sourceMappingURL=chunk-RPVLRULC.js.map
|