@designfever/web-review-kit 0.3.0 → 0.4.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/LICENSE +201 -0
- package/README.md +18 -1
- package/dist/{chunk-I76WEDLA.js → chunk-QFNYQCTA.js} +1046 -85
- package/dist/chunk-QFNYQCTA.js.map +1 -0
- package/dist/index.cjs +1045 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/react-shell.cjs +3058 -806
- package/dist/react-shell.cjs.map +1 -1
- package/dist/react-shell.d.cts +11 -3
- package/dist/react-shell.d.ts +11 -3
- package/dist/react-shell.js +1917 -622
- package/dist/react-shell.js.map +1 -1
- package/dist/{types-Cf2x5ky6.d.cts → types-D_qYtwTs.d.cts} +4 -1
- package/dist/{types-Cf2x5ky6.d.ts → types-D_qYtwTs.d.ts} +4 -1
- package/docs/architecture.md +3 -0
- package/docs/installation.md +7 -1
- package/docs/release-notes-0.3.0.md +94 -0
- package/docs/release-notes-0.4.0.md +144 -0
- package/package.json +2 -2
- package/dist/chunk-I76WEDLA.js.map +0 -1
|
@@ -301,19 +301,6 @@ function getPopoverPosition(point, environment, options) {
|
|
|
301
301
|
)
|
|
302
302
|
};
|
|
303
303
|
}
|
|
304
|
-
function getAreaPopoverPosition(selection, environment) {
|
|
305
|
-
return getPopoverPosition(
|
|
306
|
-
{
|
|
307
|
-
x: selection.left + selection.width,
|
|
308
|
-
y: selection.top
|
|
309
|
-
},
|
|
310
|
-
environment,
|
|
311
|
-
{
|
|
312
|
-
width: 360,
|
|
313
|
-
estimatedHeight: 206
|
|
314
|
-
}
|
|
315
|
-
);
|
|
316
|
-
}
|
|
317
304
|
function getPopoverBounds(environment) {
|
|
318
305
|
if (!environment) {
|
|
319
306
|
return {
|
|
@@ -378,6 +365,21 @@ function roundPoint(point) {
|
|
|
378
365
|
}
|
|
379
366
|
|
|
380
367
|
// src/core/dom.anchor.ts
|
|
368
|
+
var COMMON_ANCHOR_ATTRIBUTES = [
|
|
369
|
+
"data-testid",
|
|
370
|
+
"data-test-id",
|
|
371
|
+
"data-cy",
|
|
372
|
+
"data-test",
|
|
373
|
+
"data-qa",
|
|
374
|
+
"data-section-id",
|
|
375
|
+
"data-component"
|
|
376
|
+
];
|
|
377
|
+
var SEMANTIC_ANCHOR_ATTRIBUTES = [
|
|
378
|
+
"aria-label",
|
|
379
|
+
"title",
|
|
380
|
+
"name",
|
|
381
|
+
"href"
|
|
382
|
+
];
|
|
381
383
|
function getDomAnchor(selection, configuredAttribute = "data-qa-id", environment) {
|
|
382
384
|
const x = selection.left + selection.width / 2;
|
|
383
385
|
const y = selection.top + selection.height / 2;
|
|
@@ -467,46 +469,66 @@ function getAnchorElement(anchor, environment) {
|
|
|
467
469
|
return typeof anchor === "string" ? queryAnchorElement(anchor, environment) : resolveAnchorElement(anchor, environment)?.element;
|
|
468
470
|
}
|
|
469
471
|
function createAnchorCandidates(target, configuredAttribute) {
|
|
470
|
-
const
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
472
|
+
const targetCandidates = [];
|
|
473
|
+
const configuredAnchor = getExactAttributeAnchorCandidate(
|
|
474
|
+
target,
|
|
475
|
+
configuredAttribute,
|
|
476
|
+
0.98,
|
|
477
|
+
"configured-attribute"
|
|
478
|
+
);
|
|
479
|
+
if (configuredAnchor) targetCandidates.push(configuredAnchor);
|
|
480
|
+
const targetAttributeAnchor = getAttributeAnchorCandidate(
|
|
481
|
+
target,
|
|
482
|
+
COMMON_ANCHOR_ATTRIBUTES.filter((name) => name !== configuredAttribute),
|
|
483
|
+
0.9
|
|
484
|
+
);
|
|
485
|
+
if (targetAttributeAnchor) targetCandidates.push(targetAttributeAnchor);
|
|
483
486
|
if (isMeaningfulId(target.id)) {
|
|
484
|
-
|
|
487
|
+
targetCandidates.push({
|
|
485
488
|
selector: `#${cssEscape(target.id)}`,
|
|
486
489
|
strategy: "id",
|
|
487
490
|
confidence: 0.94,
|
|
488
491
|
textFingerprint: getTextFingerprint(target)
|
|
489
492
|
});
|
|
490
493
|
}
|
|
494
|
+
const semanticAnchor = getAttributeAnchorCandidate(
|
|
495
|
+
target,
|
|
496
|
+
SEMANTIC_ANCHOR_ATTRIBUTES,
|
|
497
|
+
0.84
|
|
498
|
+
);
|
|
499
|
+
if (semanticAnchor) targetCandidates.push(semanticAnchor);
|
|
491
500
|
const targetClassName = getMeaningfulClassName(target);
|
|
492
501
|
if (targetClassName) {
|
|
493
|
-
|
|
502
|
+
targetCandidates.push({
|
|
494
503
|
selector: `${target.tagName.toLowerCase()}.${cssEscape(targetClassName)}`,
|
|
495
504
|
strategy: "class",
|
|
496
505
|
confidence: 0.82,
|
|
497
506
|
textFingerprint: getTextFingerprint(target)
|
|
498
507
|
});
|
|
499
508
|
}
|
|
500
|
-
|
|
509
|
+
const scopedPath = getScopedDomPathCandidate(target, configuredAttribute);
|
|
510
|
+
if (scopedPath) targetCandidates.push(scopedPath);
|
|
511
|
+
const targetDomPath = {
|
|
501
512
|
selector: getDomPath(target),
|
|
502
513
|
strategy: "dom-path",
|
|
503
|
-
confidence: 0.
|
|
514
|
+
confidence: targetCandidates.length > 0 ? 0.8 : 0.5,
|
|
504
515
|
textFingerprint: getTextFingerprint(target)
|
|
505
|
-
}
|
|
516
|
+
};
|
|
517
|
+
const parentCandidates = [];
|
|
506
518
|
const parent = target.parentElement;
|
|
519
|
+
const parentConfiguredAnchor = parent ? findClosestAttributeAnchor(parent, [configuredAttribute], 0.72, {
|
|
520
|
+
strategy: "configured-attribute"
|
|
521
|
+
}) : void 0;
|
|
522
|
+
if (parentConfiguredAnchor) parentCandidates.push(parentConfiguredAnchor);
|
|
523
|
+
const anchoredByAttribute = parent ? findClosestAttributeAnchor(
|
|
524
|
+
parent,
|
|
525
|
+
COMMON_ANCHOR_ATTRIBUTES.filter((name) => name !== configuredAttribute),
|
|
526
|
+
0.7
|
|
527
|
+
) : void 0;
|
|
528
|
+
if (anchoredByAttribute) parentCandidates.push(anchoredByAttribute);
|
|
507
529
|
const anchoredById = parent ? findClosest(parent, (element) => isMeaningfulId(element.id)) : void 0;
|
|
508
530
|
if (anchoredById?.id) {
|
|
509
|
-
|
|
531
|
+
parentCandidates.push({
|
|
510
532
|
selector: `#${cssEscape(anchoredById.id)}`,
|
|
511
533
|
strategy: "id",
|
|
512
534
|
confidence: 0.72,
|
|
@@ -516,7 +538,7 @@ function createAnchorCandidates(target, configuredAttribute) {
|
|
|
516
538
|
const anchoredByClass = parent ? findClosest(parent, (element) => Boolean(getMeaningfulClassName(element))) : void 0;
|
|
517
539
|
const className = anchoredByClass ? getMeaningfulClassName(anchoredByClass) : void 0;
|
|
518
540
|
if (anchoredByClass && className) {
|
|
519
|
-
|
|
541
|
+
parentCandidates.push({
|
|
520
542
|
selector: `${anchoredByClass.tagName.toLowerCase()}.${cssEscape(
|
|
521
543
|
className
|
|
522
544
|
)}`,
|
|
@@ -525,8 +547,107 @@ function createAnchorCandidates(target, configuredAttribute) {
|
|
|
525
547
|
textFingerprint: getTextFingerprint(anchoredByClass)
|
|
526
548
|
});
|
|
527
549
|
}
|
|
550
|
+
const candidates = targetCandidates.length > 0 ? [...targetCandidates, targetDomPath, ...parentCandidates] : [...parentCandidates, targetDomPath];
|
|
528
551
|
return dedupeAnchorCandidates(candidates);
|
|
529
552
|
}
|
|
553
|
+
function findClosestAttributeAnchor(target, attributeNames, confidence, options) {
|
|
554
|
+
for (const attributeName of attributeNames) {
|
|
555
|
+
const selector = `[${attributeName}]`;
|
|
556
|
+
const element = safeClosest(target, selector);
|
|
557
|
+
if (!element) continue;
|
|
558
|
+
const value = getStableAttributeValue(element, attributeName);
|
|
559
|
+
if (!value) continue;
|
|
560
|
+
return {
|
|
561
|
+
selector: `[${attributeName}="${cssEscape(value)}"]`,
|
|
562
|
+
strategy: options?.strategy ?? "attribute",
|
|
563
|
+
confidence,
|
|
564
|
+
textFingerprint: getTextFingerprint(element)
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
return void 0;
|
|
568
|
+
}
|
|
569
|
+
function getExactAttributeAnchorCandidate(element, attributeName, confidence, strategy) {
|
|
570
|
+
const value = getStableAttributeValue(element, attributeName);
|
|
571
|
+
if (!value) return void 0;
|
|
572
|
+
return {
|
|
573
|
+
selector: `[${attributeName}="${cssEscape(value)}"]`,
|
|
574
|
+
strategy,
|
|
575
|
+
confidence,
|
|
576
|
+
textFingerprint: getTextFingerprint(element)
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
function getAttributeAnchorCandidate(element, attributeNames, confidence) {
|
|
580
|
+
for (const attributeName of attributeNames) {
|
|
581
|
+
const value = getStableAttributeValue(element, attributeName);
|
|
582
|
+
if (!value) continue;
|
|
583
|
+
return {
|
|
584
|
+
selector: `${element.tagName.toLowerCase()}[${attributeName}="${cssEscape(
|
|
585
|
+
value
|
|
586
|
+
)}"]`,
|
|
587
|
+
strategy: "attribute",
|
|
588
|
+
confidence,
|
|
589
|
+
textFingerprint: getTextFingerprint(element)
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
return void 0;
|
|
593
|
+
}
|
|
594
|
+
function getScopedDomPathCandidate(target, configuredAttribute) {
|
|
595
|
+
const parent = target.parentElement;
|
|
596
|
+
if (!parent) return void 0;
|
|
597
|
+
const anchor = findStableAncestorSelector(parent, configuredAttribute);
|
|
598
|
+
if (!anchor) return void 0;
|
|
599
|
+
const selector = getDomPathBetween(anchor.element, target, anchor.selector);
|
|
600
|
+
if (!selector) return void 0;
|
|
601
|
+
return {
|
|
602
|
+
selector,
|
|
603
|
+
strategy: "dom-path",
|
|
604
|
+
confidence: anchor.confidence,
|
|
605
|
+
textFingerprint: getTextFingerprint(target)
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
function findStableAncestorSelector(start, configuredAttribute) {
|
|
609
|
+
let element = start;
|
|
610
|
+
const root = start.ownerDocument.documentElement;
|
|
611
|
+
while (element && element !== root) {
|
|
612
|
+
const configuredValue = getStableAttributeValue(element, configuredAttribute);
|
|
613
|
+
if (configuredValue) {
|
|
614
|
+
return {
|
|
615
|
+
element,
|
|
616
|
+
selector: `[${configuredAttribute}="${cssEscape(configuredValue)}"]`,
|
|
617
|
+
confidence: 0.88
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
const attributeAnchor = getAttributeAnchorCandidate(
|
|
621
|
+
element,
|
|
622
|
+
COMMON_ANCHOR_ATTRIBUTES.filter((name) => name !== configuredAttribute),
|
|
623
|
+
0.84
|
|
624
|
+
);
|
|
625
|
+
if (attributeAnchor) {
|
|
626
|
+
return {
|
|
627
|
+
element,
|
|
628
|
+
selector: attributeAnchor.selector,
|
|
629
|
+
confidence: 0.84
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
if (isMeaningfulId(element.id)) {
|
|
633
|
+
return {
|
|
634
|
+
element,
|
|
635
|
+
selector: `#${cssEscape(element.id)}`,
|
|
636
|
+
confidence: 0.82
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
const className = getMeaningfulClassName(element);
|
|
640
|
+
if (className) {
|
|
641
|
+
return {
|
|
642
|
+
element,
|
|
643
|
+
selector: `${element.tagName.toLowerCase()}.${cssEscape(className)}`,
|
|
644
|
+
confidence: 0.76
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
element = element.parentElement;
|
|
648
|
+
}
|
|
649
|
+
return void 0;
|
|
650
|
+
}
|
|
530
651
|
function getAnchorSourceElement(target, candidate, configuredAttribute) {
|
|
531
652
|
if (candidate.strategy === "configured-attribute") {
|
|
532
653
|
return target.closest(`[${configuredAttribute}]`);
|
|
@@ -538,6 +659,13 @@ function getAnchorSourceElement(target, candidate, configuredAttribute) {
|
|
|
538
659
|
return target;
|
|
539
660
|
}
|
|
540
661
|
}
|
|
662
|
+
function safeClosest(element, selector) {
|
|
663
|
+
try {
|
|
664
|
+
return element.closest(selector);
|
|
665
|
+
} catch {
|
|
666
|
+
return null;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
541
669
|
function getElementHtmlSnippet(element, maxLength = 1e3) {
|
|
542
670
|
const html = decodeHtmlEntities(element.outerHTML.replace(/\s+/g, " ").trim());
|
|
543
671
|
if (html.length <= maxLength) return html;
|
|
@@ -659,10 +787,38 @@ function getDomPath(element) {
|
|
|
659
787
|
}
|
|
660
788
|
return `body > ${parts.join(" > ")}`;
|
|
661
789
|
}
|
|
790
|
+
function getDomPathBetween(ancestor, target, ancestorSelector) {
|
|
791
|
+
const parts = [];
|
|
792
|
+
let current = target;
|
|
793
|
+
while (current && current !== ancestor) {
|
|
794
|
+
parts.unshift(getDomPathPart(current));
|
|
795
|
+
current = current.parentElement;
|
|
796
|
+
}
|
|
797
|
+
if (current !== ancestor || parts.length === 0) return void 0;
|
|
798
|
+
return `${ancestorSelector} > ${parts.join(" > ")}`;
|
|
799
|
+
}
|
|
800
|
+
function getDomPathPart(element) {
|
|
801
|
+
const parent = element.parentElement;
|
|
802
|
+
const tag = element.tagName.toLowerCase();
|
|
803
|
+
if (!parent) return tag;
|
|
804
|
+
const currentTagName = element.tagName;
|
|
805
|
+
const siblings = Array.from(parent.children).filter(
|
|
806
|
+
(child) => child.tagName === currentTagName
|
|
807
|
+
);
|
|
808
|
+
const index = siblings.indexOf(element) + 1;
|
|
809
|
+
return `${tag}:nth-of-type(${index})`;
|
|
810
|
+
}
|
|
662
811
|
function getTextFingerprint(element) {
|
|
663
812
|
const text = element.textContent?.replace(/\s+/g, " ").trim();
|
|
664
813
|
return text ? text.slice(0, 120) : void 0;
|
|
665
814
|
}
|
|
815
|
+
function getStableAttributeValue(element, attributeName) {
|
|
816
|
+
const value = element.getAttribute(attributeName)?.trim();
|
|
817
|
+
if (!value || value.length > 160) return void 0;
|
|
818
|
+
if (/^(true|false)$/i.test(value)) return void 0;
|
|
819
|
+
if (/^\d+$/.test(value) && value.length < 3) return void 0;
|
|
820
|
+
return value;
|
|
821
|
+
}
|
|
666
822
|
function getTextFingerprintScore(expected, actual) {
|
|
667
823
|
if (!expected) return 1;
|
|
668
824
|
if (!actual) return 0.5;
|
|
@@ -1038,6 +1194,19 @@ function createStyleElement() {
|
|
|
1038
1194
|
display: block;
|
|
1039
1195
|
}
|
|
1040
1196
|
|
|
1197
|
+
.dfwr-shell.has-dismissible-draft {
|
|
1198
|
+
z-index: 900;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
.dfwr-draft-cancel-layer {
|
|
1202
|
+
position: fixed;
|
|
1203
|
+
inset: 0;
|
|
1204
|
+
z-index: 2;
|
|
1205
|
+
pointer-events: auto;
|
|
1206
|
+
background: transparent;
|
|
1207
|
+
cursor: default;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1041
1210
|
.dfwr-panel {
|
|
1042
1211
|
position: fixed;
|
|
1043
1212
|
right: 16px;
|
|
@@ -1531,6 +1700,40 @@ function createStyleElement() {
|
|
|
1531
1700
|
box-shadow: var(--df-review-shadow-popover);
|
|
1532
1701
|
}
|
|
1533
1702
|
|
|
1703
|
+
.dfwr-note-popover.is-composer,
|
|
1704
|
+
.dfwr-area-draft.is-composer {
|
|
1705
|
+
max-height: min(360px, calc(100vh - 32px));
|
|
1706
|
+
overflow: auto;
|
|
1707
|
+
border-color: rgba(99, 215, 199, 0.56);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
.dfwr-note-popover.is-dragging,
|
|
1711
|
+
.dfwr-area-draft.is-dragging {
|
|
1712
|
+
user-select: none;
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
.dfwr-draft-drag-handle {
|
|
1716
|
+
display: block;
|
|
1717
|
+
width: 42px;
|
|
1718
|
+
height: 6px;
|
|
1719
|
+
margin: 0 auto 10px;
|
|
1720
|
+
padding: 0;
|
|
1721
|
+
cursor: grab;
|
|
1722
|
+
pointer-events: auto;
|
|
1723
|
+
background: rgba(247, 247, 242, 0.28);
|
|
1724
|
+
border: 0;
|
|
1725
|
+
border-radius: 999px;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
.dfwr-draft-drag-handle:hover,
|
|
1729
|
+
.dfwr-draft-drag-handle:focus-visible {
|
|
1730
|
+
background: rgba(215, 255, 95, 0.62);
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
.dfwr-draft-drag-handle:active {
|
|
1734
|
+
cursor: grabbing;
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1534
1737
|
.dfwr-area-draft {
|
|
1535
1738
|
position: fixed;
|
|
1536
1739
|
right: 16px;
|
|
@@ -1552,6 +1755,14 @@ function createStyleElement() {
|
|
|
1552
1755
|
padding: 0;
|
|
1553
1756
|
}
|
|
1554
1757
|
|
|
1758
|
+
.dfwr-note-actions {
|
|
1759
|
+
justify-content: flex-end;
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
.dfwr-note-actions .dfwr-button:first-child {
|
|
1763
|
+
margin-right: auto;
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1555
1766
|
.dfwr-area-draft .dfwr-actions {
|
|
1556
1767
|
padding: 0;
|
|
1557
1768
|
}
|
|
@@ -1580,6 +1791,105 @@ function createStyleElement() {
|
|
|
1580
1791
|
outline-offset: 1px;
|
|
1581
1792
|
}
|
|
1582
1793
|
|
|
1794
|
+
.dfwr-adjust-panel {
|
|
1795
|
+
display: grid;
|
|
1796
|
+
gap: 4px;
|
|
1797
|
+
padding: 8px 10px;
|
|
1798
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
1799
|
+
border-radius: var(--df-review-radius-sm);
|
|
1800
|
+
background: rgba(255, 255, 255, 0.04);
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
.dfwr-adjust-panel-header {
|
|
1804
|
+
display: flex;
|
|
1805
|
+
align-items: center;
|
|
1806
|
+
justify-content: space-between;
|
|
1807
|
+
gap: 10px;
|
|
1808
|
+
min-width: 0;
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
.dfwr-adjust-panel-header .dfwr-adjust-help {
|
|
1812
|
+
flex: 1 1 auto;
|
|
1813
|
+
min-width: 0;
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
.dfwr-adjust-panel.is-active {
|
|
1817
|
+
border-color: rgba(215, 255, 95, 0.5);
|
|
1818
|
+
background: var(--df-review-color-accent-soft);
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
.dfwr-adjust-help,
|
|
1822
|
+
.dfwr-adjust-status {
|
|
1823
|
+
margin: 0;
|
|
1824
|
+
color: var(--df-review-color-text-muted);
|
|
1825
|
+
font-size: var(--df-review-font-size-xs);
|
|
1826
|
+
line-height: 1.35;
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
.dfwr-adjust-status {
|
|
1830
|
+
color: var(--df-review-color-text);
|
|
1831
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
.dfwr-adjust-toggle {
|
|
1835
|
+
flex: 0 0 auto;
|
|
1836
|
+
display: inline-flex;
|
|
1837
|
+
align-items: center;
|
|
1838
|
+
justify-content: center;
|
|
1839
|
+
width: 34px;
|
|
1840
|
+
height: 30px;
|
|
1841
|
+
padding: 0;
|
|
1842
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
1843
|
+
border-radius: var(--df-review-radius-sm);
|
|
1844
|
+
background: rgba(255, 255, 255, 0.04);
|
|
1845
|
+
color: var(--df-review-color-text);
|
|
1846
|
+
cursor: pointer;
|
|
1847
|
+
font: inherit;
|
|
1848
|
+
font-size: 14px;
|
|
1849
|
+
font-weight: 800;
|
|
1850
|
+
line-height: 1;
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
.dfwr-adjust-toggle:hover,
|
|
1854
|
+
.dfwr-adjust-toggle:focus-visible,
|
|
1855
|
+
.dfwr-adjust-toggle.is-active {
|
|
1856
|
+
border-color: rgba(215, 255, 95, 0.68);
|
|
1857
|
+
background: var(--df-review-color-accent-soft);
|
|
1858
|
+
outline: none;
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
.dfwr-adjust-toggle svg {
|
|
1862
|
+
width: 18px;
|
|
1863
|
+
height: 18px;
|
|
1864
|
+
pointer-events: none;
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
.dfwr-adjust-hud {
|
|
1868
|
+
position: fixed;
|
|
1869
|
+
z-index: 5;
|
|
1870
|
+
display: inline-flex;
|
|
1871
|
+
align-items: center;
|
|
1872
|
+
min-height: 22px;
|
|
1873
|
+
padding: 0 8px;
|
|
1874
|
+
border: 1px solid rgba(99, 215, 199, 0.72);
|
|
1875
|
+
border-radius: var(--df-review-radius-sm);
|
|
1876
|
+
background: rgba(21, 25, 29, 0.92);
|
|
1877
|
+
box-shadow:
|
|
1878
|
+
0 0 0 3px rgba(99, 215, 199, 0.14),
|
|
1879
|
+
0 8px 18px rgba(0, 0, 0, 0.26);
|
|
1880
|
+
color: #63d7c7;
|
|
1881
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
|
1882
|
+
font-size: var(--df-review-font-size-2xs);
|
|
1883
|
+
font-weight: 800;
|
|
1884
|
+
line-height: 1;
|
|
1885
|
+
pointer-events: none;
|
|
1886
|
+
white-space: nowrap;
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
.dfwr-adjust-hud[hidden] {
|
|
1890
|
+
display: none;
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1583
1893
|
.dfwr-empty,
|
|
1584
1894
|
.dfwr-error {
|
|
1585
1895
|
margin: 0;
|
|
@@ -1800,16 +2110,6 @@ function createStyleElement() {
|
|
|
1800
2110
|
}
|
|
1801
2111
|
|
|
1802
2112
|
// src/core/review/format.ts
|
|
1803
|
-
function formatAreaDraftMeta(draft) {
|
|
1804
|
-
const parts = [`viewport ${formatSize(draft.viewport)}`];
|
|
1805
|
-
if (draft.selection) {
|
|
1806
|
-
parts.push(`rect ${formatSelection(draft.selection.viewport)}`);
|
|
1807
|
-
}
|
|
1808
|
-
if (draft.marker) {
|
|
1809
|
-
parts.push(`point ${formatPoint(draft.marker.viewport)}`);
|
|
1810
|
-
}
|
|
1811
|
-
return parts.join(" / ");
|
|
1812
|
-
}
|
|
1813
2113
|
function formatNoteDraftMeta(draft) {
|
|
1814
2114
|
const parts = [
|
|
1815
2115
|
`viewport ${formatSize(draft.viewport)}`,
|
|
@@ -1875,17 +2175,29 @@ function formatAnchorMeta(anchor) {
|
|
|
1875
2175
|
}
|
|
1876
2176
|
|
|
1877
2177
|
// src/core/web.review.kit.view.ts
|
|
2178
|
+
var DEFAULT_ADJUSTMENT_LABEL = "Responsive CSS px adjustments";
|
|
1878
2179
|
var WebReviewKitView = class {
|
|
1879
2180
|
constructor(config) {
|
|
1880
2181
|
this.config = config;
|
|
1881
2182
|
}
|
|
2183
|
+
clearDraftPreview() {
|
|
2184
|
+
this.restoreDraftPreview();
|
|
2185
|
+
}
|
|
1882
2186
|
render(shadow, hiddenItemsStyle) {
|
|
1883
2187
|
const state = this.state;
|
|
2188
|
+
this.syncDraftPreview(
|
|
2189
|
+
state.isOpen && state.mode === "element" ? state.noteDraft : void 0
|
|
2190
|
+
);
|
|
1884
2191
|
shadow.replaceChildren();
|
|
1885
2192
|
shadow.append(createStyleElement());
|
|
1886
2193
|
shadow.append(hiddenItemsStyle);
|
|
2194
|
+
const hasDismissableDraft = Boolean(state.noteDraft || state.areaDraft);
|
|
1887
2195
|
const shell = document.createElement("div");
|
|
1888
|
-
shell.className =
|
|
2196
|
+
shell.className = [
|
|
2197
|
+
"dfwr-shell",
|
|
2198
|
+
state.isOpen ? "is-open" : "",
|
|
2199
|
+
hasDismissableDraft ? "has-dismissible-draft" : ""
|
|
2200
|
+
].filter(Boolean).join(" ");
|
|
1889
2201
|
shell.setAttribute("aria-hidden", state.isOpen ? "false" : "true");
|
|
1890
2202
|
if (this.config.options.ui?.panel !== false) {
|
|
1891
2203
|
const panel = document.createElement("div");
|
|
@@ -1901,6 +2213,9 @@ var WebReviewKitView = class {
|
|
|
1901
2213
|
shell.append(panel);
|
|
1902
2214
|
}
|
|
1903
2215
|
shell.append(this.createMarkerLayer());
|
|
2216
|
+
if (state.isOpen && hasDismissableDraft) {
|
|
2217
|
+
shell.append(this.createDraftCancelLayer());
|
|
2218
|
+
}
|
|
1904
2219
|
if (state.isOpen && (state.mode === "note" || state.mode === "element")) {
|
|
1905
2220
|
shell.append(
|
|
1906
2221
|
state.noteDraft ? this.createNotePopover(state.noteDraft) : state.mode === "element" ? this.createElementLayer() : this.createNoteLayer()
|
|
@@ -1920,6 +2235,294 @@ var WebReviewKitView = class {
|
|
|
1920
2235
|
get state() {
|
|
1921
2236
|
return this.config.getState();
|
|
1922
2237
|
}
|
|
2238
|
+
createDraftCancelLayer() {
|
|
2239
|
+
const layer = document.createElement("div");
|
|
2240
|
+
layer.className = "dfwr-draft-cancel-layer";
|
|
2241
|
+
layer.setAttribute("aria-hidden", "true");
|
|
2242
|
+
const cancel = (event) => {
|
|
2243
|
+
event.preventDefault();
|
|
2244
|
+
event.stopPropagation();
|
|
2245
|
+
event.stopImmediatePropagation();
|
|
2246
|
+
this.config.actions.setModeState("idle");
|
|
2247
|
+
this.config.actions.clearDrafts();
|
|
2248
|
+
this.config.actions.setSelectingArea(false);
|
|
2249
|
+
this.config.actions.render();
|
|
2250
|
+
};
|
|
2251
|
+
layer.addEventListener("pointerdown", (event) => {
|
|
2252
|
+
if (event.button !== 0) return;
|
|
2253
|
+
cancel(event);
|
|
2254
|
+
});
|
|
2255
|
+
layer.addEventListener("click", cancel);
|
|
2256
|
+
return layer;
|
|
2257
|
+
}
|
|
2258
|
+
getDraftAdjustmentMetrics(draft) {
|
|
2259
|
+
const adjustment = draft.adjustment;
|
|
2260
|
+
const x = adjustment?.x ?? 0;
|
|
2261
|
+
const y = adjustment?.y ?? 0;
|
|
2262
|
+
const scale = adjustment?.scale ?? 0;
|
|
2263
|
+
const {
|
|
2264
|
+
scale: viewportScale,
|
|
2265
|
+
designWidth,
|
|
2266
|
+
presetLabel
|
|
2267
|
+
} = this.getDraftViewportScale(draft.viewport);
|
|
2268
|
+
const selection = draft.selection ? toViewportSelection(draft.selection.viewport) : void 0;
|
|
2269
|
+
const scaleCssDelta = scale * viewportScale;
|
|
2270
|
+
const scaleFactor = selection && selection.width > 0 ? Math.max(
|
|
2271
|
+
1 / selection.width,
|
|
2272
|
+
(selection.width + scaleCssDelta) / selection.width
|
|
2273
|
+
) : 1;
|
|
2274
|
+
return {
|
|
2275
|
+
x,
|
|
2276
|
+
y,
|
|
2277
|
+
scale,
|
|
2278
|
+
cssX: x * viewportScale,
|
|
2279
|
+
cssY: y * viewportScale,
|
|
2280
|
+
scaleFactor,
|
|
2281
|
+
viewportScale,
|
|
2282
|
+
designWidth,
|
|
2283
|
+
presetLabel,
|
|
2284
|
+
viewportWidth: draft.viewport.width
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2287
|
+
hasDraftAdjustment(draft) {
|
|
2288
|
+
const metrics = this.getDraftAdjustmentMetrics(draft);
|
|
2289
|
+
return metrics.x !== 0 || metrics.y !== 0 || metrics.scale !== 0;
|
|
2290
|
+
}
|
|
2291
|
+
getAdjustedDraftPoint(point, draft) {
|
|
2292
|
+
const metrics = this.getDraftAdjustmentMetrics(draft);
|
|
2293
|
+
return {
|
|
2294
|
+
x: point.x + metrics.cssX,
|
|
2295
|
+
y: point.y + metrics.cssY
|
|
2296
|
+
};
|
|
2297
|
+
}
|
|
2298
|
+
getAdjustedDraftSelection(selection, draft) {
|
|
2299
|
+
const metrics = this.getDraftAdjustmentMetrics(draft);
|
|
2300
|
+
return {
|
|
2301
|
+
...selection,
|
|
2302
|
+
left: selection.left + metrics.cssX,
|
|
2303
|
+
top: selection.top + metrics.cssY,
|
|
2304
|
+
width: selection.width * metrics.scaleFactor,
|
|
2305
|
+
height: selection.height * metrics.scaleFactor
|
|
2306
|
+
};
|
|
2307
|
+
}
|
|
2308
|
+
getDraftViewportScale(viewport) {
|
|
2309
|
+
const preset = findReviewViewportPreset(
|
|
2310
|
+
viewport,
|
|
2311
|
+
this.config.options.viewports?.presets
|
|
2312
|
+
);
|
|
2313
|
+
const designWidth = typeof preset.designWidth === "number" && preset.designWidth > 0 ? preset.designWidth : viewport.width;
|
|
2314
|
+
const scale = designWidth > 0 ? viewport.width / designWidth : 1;
|
|
2315
|
+
return { scale, designWidth, presetLabel: preset.label };
|
|
2316
|
+
}
|
|
2317
|
+
getDraftComposerWidth(environment) {
|
|
2318
|
+
const bounds = environment.overlayRect;
|
|
2319
|
+
const margin = 12;
|
|
2320
|
+
return Math.min(360, Math.max(240, bounds.width - margin * 2));
|
|
2321
|
+
}
|
|
2322
|
+
getClampedComposerPosition(position, environment, size, bounds = environment.overlayRect) {
|
|
2323
|
+
const margin = 12;
|
|
2324
|
+
const width = size?.width ?? this.getDraftComposerWidth(environment);
|
|
2325
|
+
const height = size?.height ?? 236;
|
|
2326
|
+
return {
|
|
2327
|
+
x: clamp(
|
|
2328
|
+
position.x,
|
|
2329
|
+
bounds.left + margin,
|
|
2330
|
+
bounds.left + bounds.width - width - margin
|
|
2331
|
+
),
|
|
2332
|
+
y: clamp(
|
|
2333
|
+
position.y,
|
|
2334
|
+
bounds.top + margin,
|
|
2335
|
+
bounds.top + bounds.height - height - margin
|
|
2336
|
+
)
|
|
2337
|
+
};
|
|
2338
|
+
}
|
|
2339
|
+
getHostComposerBounds() {
|
|
2340
|
+
const root = document.documentElement;
|
|
2341
|
+
return {
|
|
2342
|
+
left: 0,
|
|
2343
|
+
top: 0,
|
|
2344
|
+
width: root.clientWidth || window.innerWidth,
|
|
2345
|
+
height: root.clientHeight || window.innerHeight
|
|
2346
|
+
};
|
|
2347
|
+
}
|
|
2348
|
+
getInitialDraftComposerPosition(selection, environment, size) {
|
|
2349
|
+
const bounds = this.getHostComposerBounds();
|
|
2350
|
+
const margin = 12;
|
|
2351
|
+
const gap = 20;
|
|
2352
|
+
if (!selection) {
|
|
2353
|
+
return this.getClampedComposerPosition(
|
|
2354
|
+
{
|
|
2355
|
+
x: environment.overlayRect.left + margin,
|
|
2356
|
+
y: environment.overlayRect.top + margin
|
|
2357
|
+
},
|
|
2358
|
+
environment,
|
|
2359
|
+
size,
|
|
2360
|
+
bounds
|
|
2361
|
+
);
|
|
2362
|
+
}
|
|
2363
|
+
const preferredX = selection.left + selection.width + gap;
|
|
2364
|
+
const maxX = bounds.left + bounds.width - size.width - margin;
|
|
2365
|
+
const x = preferredX <= maxX ? preferredX : selection.left - size.width - gap;
|
|
2366
|
+
return this.getClampedComposerPosition(
|
|
2367
|
+
{
|
|
2368
|
+
x,
|
|
2369
|
+
y: selection.top
|
|
2370
|
+
},
|
|
2371
|
+
environment,
|
|
2372
|
+
size,
|
|
2373
|
+
bounds
|
|
2374
|
+
);
|
|
2375
|
+
}
|
|
2376
|
+
getDraftComposerPosition({
|
|
2377
|
+
selection,
|
|
2378
|
+
environment,
|
|
2379
|
+
composerPosition,
|
|
2380
|
+
estimatedHeight
|
|
2381
|
+
}) {
|
|
2382
|
+
const width = this.getDraftComposerWidth(environment);
|
|
2383
|
+
if (composerPosition) {
|
|
2384
|
+
const clamped = this.getClampedComposerPosition(
|
|
2385
|
+
composerPosition,
|
|
2386
|
+
environment,
|
|
2387
|
+
{ width, height: estimatedHeight },
|
|
2388
|
+
this.getHostComposerBounds()
|
|
2389
|
+
);
|
|
2390
|
+
return { width, left: clamped.x, top: clamped.y };
|
|
2391
|
+
}
|
|
2392
|
+
const position = this.getInitialDraftComposerPosition(selection, environment, {
|
|
2393
|
+
width,
|
|
2394
|
+
height: estimatedHeight
|
|
2395
|
+
});
|
|
2396
|
+
return { width, left: position.x, top: position.y };
|
|
2397
|
+
}
|
|
2398
|
+
getSelectionMqMetrics(selection, viewport) {
|
|
2399
|
+
const { scale } = this.getDraftViewportScale(viewport);
|
|
2400
|
+
const ratio = scale > 0 ? 1 / scale : 1;
|
|
2401
|
+
return {
|
|
2402
|
+
x: selection.left * ratio,
|
|
2403
|
+
y: selection.top * ratio,
|
|
2404
|
+
width: selection.width * ratio,
|
|
2405
|
+
height: selection.height * ratio
|
|
2406
|
+
};
|
|
2407
|
+
}
|
|
2408
|
+
formatSignedPx(value) {
|
|
2409
|
+
if (value === 0) return "+0px";
|
|
2410
|
+
return `${value > 0 ? "+" : ""}${value}px`;
|
|
2411
|
+
}
|
|
2412
|
+
formatRoundedPx(value) {
|
|
2413
|
+
return `${Math.round(value)}px`;
|
|
2414
|
+
}
|
|
2415
|
+
getAdjustmentLabel() {
|
|
2416
|
+
return this.config.options.adjustmentLabel?.trim() || DEFAULT_ADJUSTMENT_LABEL;
|
|
2417
|
+
}
|
|
2418
|
+
getSelectionMetricLines(selection, viewport) {
|
|
2419
|
+
if (!selection) return ["area", "x none / y none", "w none / h none"];
|
|
2420
|
+
const metrics = this.getSelectionMqMetrics(selection, viewport);
|
|
2421
|
+
return [
|
|
2422
|
+
"area",
|
|
2423
|
+
`x ${this.formatRoundedPx(metrics.x)} / y ${this.formatRoundedPx(
|
|
2424
|
+
metrics.y
|
|
2425
|
+
)}`,
|
|
2426
|
+
`w ${this.formatRoundedPx(metrics.width)} / h ${this.formatRoundedPx(
|
|
2427
|
+
metrics.height
|
|
2428
|
+
)}`
|
|
2429
|
+
];
|
|
2430
|
+
}
|
|
2431
|
+
getAreaDraftMetricSelection(draft) {
|
|
2432
|
+
if (!draft.selection) return void 0;
|
|
2433
|
+
return toViewportSelection(draft.selection.viewport);
|
|
2434
|
+
}
|
|
2435
|
+
formatDraftAdjustmentStatus(draft) {
|
|
2436
|
+
const metrics = this.getDraftAdjustmentMetrics(draft);
|
|
2437
|
+
return [
|
|
2438
|
+
`x ${this.formatSignedPx(metrics.x)}`,
|
|
2439
|
+
`y ${this.formatSignedPx(metrics.y)}`,
|
|
2440
|
+
`scale ${this.formatSignedPx(metrics.scale)}`
|
|
2441
|
+
].join(" / ");
|
|
2442
|
+
}
|
|
2443
|
+
getDraftAdjustmentMetricLines(draft) {
|
|
2444
|
+
const metrics = this.getDraftAdjustmentMetrics(draft);
|
|
2445
|
+
return [
|
|
2446
|
+
`x ${this.formatSignedPx(metrics.x)} / y ${this.formatSignedPx(
|
|
2447
|
+
metrics.y
|
|
2448
|
+
)}`,
|
|
2449
|
+
`scale ${this.formatSignedPx(metrics.scale)}`
|
|
2450
|
+
];
|
|
2451
|
+
}
|
|
2452
|
+
withDraftAdjustmentComment(comment, draft) {
|
|
2453
|
+
if (!this.hasDraftAdjustment(draft)) return comment;
|
|
2454
|
+
const metrics = this.getDraftAdjustmentMetrics(draft);
|
|
2455
|
+
const adjustment = [
|
|
2456
|
+
`${this.getAdjustmentLabel()}: x ${this.formatSignedPx(
|
|
2457
|
+
metrics.x
|
|
2458
|
+
)}, y ${this.formatSignedPx(metrics.y)}, scale ${this.formatSignedPx(
|
|
2459
|
+
metrics.scale
|
|
2460
|
+
)}`,
|
|
2461
|
+
`(${metrics.presetLabel} viewport, ${Math.round(
|
|
2462
|
+
metrics.viewportWidth
|
|
2463
|
+
)}/design ${Math.round(metrics.designWidth)})`
|
|
2464
|
+
].join(" ");
|
|
2465
|
+
return `${comment.trim()}
|
|
2466
|
+
${adjustment}`;
|
|
2467
|
+
}
|
|
2468
|
+
getStyleableDraftElement(draft, environment) {
|
|
2469
|
+
if (!draft.anchor) return void 0;
|
|
2470
|
+
const element = resolveAnchorElement(draft.anchor, environment)?.element;
|
|
2471
|
+
if (!element) return void 0;
|
|
2472
|
+
if ("style" in element) return element;
|
|
2473
|
+
return void 0;
|
|
2474
|
+
}
|
|
2475
|
+
syncDraftPreview(draft) {
|
|
2476
|
+
const environment = this.config.getEnvironment();
|
|
2477
|
+
if (!draft || !environment || !this.hasDraftAdjustment(draft)) {
|
|
2478
|
+
this.restoreDraftPreview();
|
|
2479
|
+
return;
|
|
2480
|
+
}
|
|
2481
|
+
const element = this.getStyleableDraftElement(draft, environment);
|
|
2482
|
+
if (!element) {
|
|
2483
|
+
this.restoreDraftPreview();
|
|
2484
|
+
return;
|
|
2485
|
+
}
|
|
2486
|
+
if (this.draftPreview?.element !== element) {
|
|
2487
|
+
this.restoreDraftPreview();
|
|
2488
|
+
}
|
|
2489
|
+
if (!this.draftPreview) {
|
|
2490
|
+
const computedTransform = environment.window.getComputedStyle(element).transform;
|
|
2491
|
+
this.draftPreview = {
|
|
2492
|
+
element,
|
|
2493
|
+
transform: element.style.transform,
|
|
2494
|
+
transformOrigin: element.style.transformOrigin,
|
|
2495
|
+
transition: element.style.transition,
|
|
2496
|
+
willChange: element.style.willChange,
|
|
2497
|
+
baseTransform: element.style.transform || (computedTransform && computedTransform !== "none" ? computedTransform : "")
|
|
2498
|
+
};
|
|
2499
|
+
}
|
|
2500
|
+
const metrics = this.getDraftAdjustmentMetrics(draft);
|
|
2501
|
+
const translate = `translate(${this.toCssNumber(metrics.cssX)}px, ${this.toCssNumber(
|
|
2502
|
+
metrics.cssY
|
|
2503
|
+
)}px)`;
|
|
2504
|
+
const scale = metrics.scaleFactor === 1 ? "" : `scale(${this.toCssNumber(metrics.scaleFactor)})`;
|
|
2505
|
+
element.style.transition = "none";
|
|
2506
|
+
element.style.willChange = "transform";
|
|
2507
|
+
element.style.transformOrigin = "top left";
|
|
2508
|
+
element.style.transform = [
|
|
2509
|
+
this.draftPreview.baseTransform,
|
|
2510
|
+
translate,
|
|
2511
|
+
scale
|
|
2512
|
+
].filter(Boolean).join(" ");
|
|
2513
|
+
}
|
|
2514
|
+
restoreDraftPreview() {
|
|
2515
|
+
if (!this.draftPreview) return;
|
|
2516
|
+
const { element, transform, transformOrigin, transition, willChange } = this.draftPreview;
|
|
2517
|
+
element.style.transform = transform;
|
|
2518
|
+
element.style.transformOrigin = transformOrigin;
|
|
2519
|
+
element.style.transition = transition;
|
|
2520
|
+
element.style.willChange = willChange;
|
|
2521
|
+
this.draftPreview = void 0;
|
|
2522
|
+
}
|
|
2523
|
+
toCssNumber(value) {
|
|
2524
|
+
return Math.round(value * 1e3) / 1e3;
|
|
2525
|
+
}
|
|
1923
2526
|
createHeader() {
|
|
1924
2527
|
const header = document.createElement("div");
|
|
1925
2528
|
header.className = "dfwr-header";
|
|
@@ -2011,15 +2614,20 @@ var WebReviewKitView = class {
|
|
|
2011
2614
|
const group = document.createElement("div");
|
|
2012
2615
|
group.className = "dfwr-note-draft";
|
|
2013
2616
|
if (!environment) return group;
|
|
2014
|
-
const
|
|
2617
|
+
const isElementDraft = this.state.mode === "element" && Boolean(draft.selection);
|
|
2618
|
+
const hostPoint = toHostPoint(
|
|
2619
|
+
isElementDraft ? this.getAdjustedDraftPoint(draft.marker.viewport, draft) : draft.marker.viewport,
|
|
2620
|
+
environment
|
|
2621
|
+
);
|
|
2622
|
+
let selectionHighlight;
|
|
2015
2623
|
if (draft.selection) {
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
)
|
|
2624
|
+
const selection = toViewportSelection(draft.selection.viewport);
|
|
2625
|
+
selectionHighlight = this.createSelectionHighlight(
|
|
2626
|
+
isElementDraft ? this.getAdjustedDraftSelection(selection, draft) : selection,
|
|
2627
|
+
environment,
|
|
2628
|
+
true
|
|
2022
2629
|
);
|
|
2630
|
+
group.append(selectionHighlight);
|
|
2023
2631
|
}
|
|
2024
2632
|
const pin = document.createElement("button");
|
|
2025
2633
|
pin.className = "dfwr-note-pin";
|
|
@@ -2029,14 +2637,35 @@ var WebReviewKitView = class {
|
|
|
2029
2637
|
pin.style.top = `${hostPoint.y}px`;
|
|
2030
2638
|
const popover = document.createElement("div");
|
|
2031
2639
|
const position = getPopoverPosition(hostPoint, environment);
|
|
2032
|
-
popover.className =
|
|
2033
|
-
|
|
2034
|
-
|
|
2640
|
+
popover.className = `dfwr-note-popover${isElementDraft ? " is-composer" : ""}`;
|
|
2641
|
+
if (isElementDraft) {
|
|
2642
|
+
const selection = draft.selection ? toHostSelection(
|
|
2643
|
+
this.getAdjustedDraftSelection(
|
|
2644
|
+
toViewportSelection(draft.selection.viewport),
|
|
2645
|
+
draft
|
|
2646
|
+
),
|
|
2647
|
+
environment
|
|
2648
|
+
) : void 0;
|
|
2649
|
+
const composer = this.getDraftComposerPosition({
|
|
2650
|
+
selection,
|
|
2651
|
+
environment,
|
|
2652
|
+
composerPosition: draft.composerPosition,
|
|
2653
|
+
estimatedHeight: 252
|
|
2654
|
+
});
|
|
2655
|
+
popover.style.left = `${composer.left}px`;
|
|
2656
|
+
popover.style.top = `${composer.top}px`;
|
|
2657
|
+
popover.style.width = `${composer.width}px`;
|
|
2658
|
+
} else {
|
|
2659
|
+
popover.style.left = `${position.left}px`;
|
|
2660
|
+
popover.style.top = `${position.top}px`;
|
|
2661
|
+
}
|
|
2035
2662
|
const form = document.createElement("form");
|
|
2036
2663
|
form.className = "dfwr-form";
|
|
2037
|
-
const meta = document.createElement("div");
|
|
2038
|
-
meta
|
|
2039
|
-
|
|
2664
|
+
const meta = isElementDraft ? void 0 : document.createElement("div");
|
|
2665
|
+
if (meta) {
|
|
2666
|
+
meta.className = "dfwr-item-date";
|
|
2667
|
+
meta.textContent = formatNoteDraftMeta(draft);
|
|
2668
|
+
}
|
|
2040
2669
|
const textarea = document.createElement("textarea");
|
|
2041
2670
|
textarea.className = "dfwr-textarea";
|
|
2042
2671
|
textarea.placeholder = "Review comment";
|
|
@@ -2050,25 +2679,306 @@ var WebReviewKitView = class {
|
|
|
2050
2679
|
comment: textarea.value
|
|
2051
2680
|
});
|
|
2052
2681
|
});
|
|
2053
|
-
const
|
|
2682
|
+
const saveDraft = () => {
|
|
2054
2683
|
const comment = textarea.value.trim();
|
|
2055
2684
|
if (!comment) return;
|
|
2685
|
+
const currentDraft = this.state.noteDraft ?? draft;
|
|
2056
2686
|
void this.config.actions.createItem({
|
|
2057
2687
|
kind: "note",
|
|
2058
|
-
comment,
|
|
2059
|
-
viewport:
|
|
2060
|
-
anchor:
|
|
2061
|
-
marker:
|
|
2062
|
-
selection:
|
|
2688
|
+
comment: this.withDraftAdjustmentComment(comment, currentDraft),
|
|
2689
|
+
viewport: currentDraft.viewport,
|
|
2690
|
+
anchor: currentDraft.anchor,
|
|
2691
|
+
marker: currentDraft.marker,
|
|
2692
|
+
selection: currentDraft.selection
|
|
2063
2693
|
});
|
|
2064
|
-
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2694
|
+
};
|
|
2695
|
+
const adjustmentHud = isElementDraft ? this.createAdjustmentHud(draft, environment) : void 0;
|
|
2696
|
+
if (adjustmentHud) {
|
|
2697
|
+
group.append(adjustmentHud);
|
|
2698
|
+
}
|
|
2699
|
+
const adjustmentControls = isElementDraft ? this.createAdjustmentControls({
|
|
2700
|
+
draft,
|
|
2701
|
+
hud: adjustmentHud,
|
|
2702
|
+
pin,
|
|
2703
|
+
popover,
|
|
2704
|
+
selectionHighlight,
|
|
2705
|
+
textarea
|
|
2706
|
+
}) : void 0;
|
|
2707
|
+
const actions = this.createFormActions("Save note", saveDraft);
|
|
2708
|
+
form.append(
|
|
2709
|
+
...meta ? [meta] : [],
|
|
2710
|
+
...adjustmentControls ? [adjustmentControls.panel] : [],
|
|
2711
|
+
textarea,
|
|
2712
|
+
actions
|
|
2713
|
+
);
|
|
2714
|
+
const dragHandle = isElementDraft ? this.createDraftDragHandle("Move DOM composer") : void 0;
|
|
2715
|
+
popover.append(...dragHandle ? [dragHandle] : [], form);
|
|
2067
2716
|
group.append(pin, popover);
|
|
2068
|
-
|
|
2069
|
-
|
|
2717
|
+
if (dragHandle) {
|
|
2718
|
+
this.attachDraftComposerDrag(popover, dragHandle, (composerPosition) => {
|
|
2719
|
+
const noteDraft = this.state.noteDraft ?? draft;
|
|
2720
|
+
this.config.actions.setNoteDraft({
|
|
2721
|
+
...noteDraft,
|
|
2722
|
+
composerPosition,
|
|
2723
|
+
comment: textarea.value
|
|
2724
|
+
});
|
|
2725
|
+
});
|
|
2726
|
+
}
|
|
2727
|
+
this.attachDraftPinDrag(
|
|
2728
|
+
pin,
|
|
2729
|
+
isElementDraft ? void 0 : popover,
|
|
2730
|
+
meta,
|
|
2731
|
+
textarea
|
|
2732
|
+
);
|
|
2733
|
+
window.setTimeout(() => {
|
|
2734
|
+
if (draft.adjustment?.isActive) {
|
|
2735
|
+
adjustmentControls?.focusTarget.focus();
|
|
2736
|
+
return;
|
|
2737
|
+
}
|
|
2738
|
+
textarea.focus();
|
|
2739
|
+
}, 0);
|
|
2070
2740
|
return group;
|
|
2071
2741
|
}
|
|
2742
|
+
createDraftDragHandle(label) {
|
|
2743
|
+
const handle = document.createElement("button");
|
|
2744
|
+
handle.className = "dfwr-draft-drag-handle";
|
|
2745
|
+
handle.type = "button";
|
|
2746
|
+
handle.setAttribute("aria-label", label);
|
|
2747
|
+
return handle;
|
|
2748
|
+
}
|
|
2749
|
+
createIcon(paths) {
|
|
2750
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
2751
|
+
svg.setAttribute("aria-hidden", "true");
|
|
2752
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
2753
|
+
svg.setAttribute("fill", "none");
|
|
2754
|
+
svg.setAttribute("stroke", "currentColor");
|
|
2755
|
+
svg.setAttribute("stroke-width", "2.4");
|
|
2756
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
2757
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
2758
|
+
paths.forEach((d) => {
|
|
2759
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
2760
|
+
path.setAttribute("d", d);
|
|
2761
|
+
svg.append(path);
|
|
2762
|
+
});
|
|
2763
|
+
return svg;
|
|
2764
|
+
}
|
|
2765
|
+
setAdjustmentToggleIcon(button, isActive) {
|
|
2766
|
+
const paths = isActive ? ["M20 6 9 17l-5-5"] : [
|
|
2767
|
+
"M12 2v20",
|
|
2768
|
+
"M2 12h20",
|
|
2769
|
+
"m9 5 3-3 3 3",
|
|
2770
|
+
"m9 19 3 3 3-3",
|
|
2771
|
+
"m5 9-3 3 3 3",
|
|
2772
|
+
"m19 9 3 3-3 3"
|
|
2773
|
+
];
|
|
2774
|
+
button.replaceChildren(this.createIcon(paths));
|
|
2775
|
+
}
|
|
2776
|
+
attachDraftComposerDrag(popover, handle, onMove) {
|
|
2777
|
+
let isDragging = false;
|
|
2778
|
+
let offsetX = 0;
|
|
2779
|
+
let offsetY = 0;
|
|
2780
|
+
const movePopover = (event) => {
|
|
2781
|
+
const environment = this.config.getEnvironment();
|
|
2782
|
+
if (!environment) return;
|
|
2783
|
+
const position = this.getClampedComposerPosition(
|
|
2784
|
+
{
|
|
2785
|
+
x: event.clientX - offsetX,
|
|
2786
|
+
y: event.clientY - offsetY
|
|
2787
|
+
},
|
|
2788
|
+
environment,
|
|
2789
|
+
{
|
|
2790
|
+
width: popover.offsetWidth,
|
|
2791
|
+
height: popover.offsetHeight
|
|
2792
|
+
},
|
|
2793
|
+
this.getHostComposerBounds()
|
|
2794
|
+
);
|
|
2795
|
+
popover.style.left = `${position.x}px`;
|
|
2796
|
+
popover.style.top = `${position.y}px`;
|
|
2797
|
+
onMove(position);
|
|
2798
|
+
};
|
|
2799
|
+
handle.addEventListener("pointerdown", (event) => {
|
|
2800
|
+
if (event.button !== 0) return;
|
|
2801
|
+
const rect = popover.getBoundingClientRect();
|
|
2802
|
+
offsetX = event.clientX - rect.left;
|
|
2803
|
+
offsetY = event.clientY - rect.top;
|
|
2804
|
+
isDragging = true;
|
|
2805
|
+
event.preventDefault();
|
|
2806
|
+
event.stopPropagation();
|
|
2807
|
+
handle.setPointerCapture(event.pointerId);
|
|
2808
|
+
popover.classList.add("is-dragging");
|
|
2809
|
+
});
|
|
2810
|
+
handle.addEventListener("pointermove", (event) => {
|
|
2811
|
+
if (!isDragging || !handle.hasPointerCapture(event.pointerId)) return;
|
|
2812
|
+
event.preventDefault();
|
|
2813
|
+
movePopover(event);
|
|
2814
|
+
});
|
|
2815
|
+
const stopDrag = (event) => {
|
|
2816
|
+
if (!isDragging || !handle.hasPointerCapture(event.pointerId)) return;
|
|
2817
|
+
event.preventDefault();
|
|
2818
|
+
event.stopPropagation();
|
|
2819
|
+
isDragging = false;
|
|
2820
|
+
handle.releasePointerCapture(event.pointerId);
|
|
2821
|
+
popover.classList.remove("is-dragging");
|
|
2822
|
+
movePopover(event);
|
|
2823
|
+
};
|
|
2824
|
+
handle.addEventListener("pointerup", stopDrag);
|
|
2825
|
+
handle.addEventListener("pointercancel", stopDrag);
|
|
2826
|
+
}
|
|
2827
|
+
createAdjustmentControls({
|
|
2828
|
+
draft,
|
|
2829
|
+
hud,
|
|
2830
|
+
pin,
|
|
2831
|
+
popover,
|
|
2832
|
+
selectionHighlight,
|
|
2833
|
+
textarea
|
|
2834
|
+
}) {
|
|
2835
|
+
const panel = document.createElement("div");
|
|
2836
|
+
panel.className = "dfwr-adjust-panel is-dom-adjust-panel";
|
|
2837
|
+
const header = document.createElement("div");
|
|
2838
|
+
header.className = "dfwr-adjust-panel-header";
|
|
2839
|
+
const help = document.createElement("div");
|
|
2840
|
+
help.className = "dfwr-adjust-help";
|
|
2841
|
+
help.textContent = this.getAdjustmentLabel();
|
|
2842
|
+
const adjust = document.createElement("button");
|
|
2843
|
+
adjust.className = "dfwr-adjust-toggle";
|
|
2844
|
+
adjust.type = "button";
|
|
2845
|
+
adjust.title = "Adjust DOM element with keyboard arrows";
|
|
2846
|
+
adjust.setAttribute("aria-label", "Adjust DOM element with keyboard arrows");
|
|
2847
|
+
const xyStatus = document.createElement("div");
|
|
2848
|
+
xyStatus.className = "dfwr-adjust-status";
|
|
2849
|
+
const scaleStatus = document.createElement("div");
|
|
2850
|
+
scaleStatus.className = "dfwr-adjust-status";
|
|
2851
|
+
const syncControls = (nextDraft) => {
|
|
2852
|
+
const isActive = nextDraft.adjustment?.isActive === true;
|
|
2853
|
+
panel.classList.toggle("is-active", isActive);
|
|
2854
|
+
adjust.classList.toggle("is-active", isActive);
|
|
2855
|
+
adjust.setAttribute("aria-pressed", isActive ? "true" : "false");
|
|
2856
|
+
this.setAdjustmentToggleIcon(adjust, isActive);
|
|
2857
|
+
adjust.title = isActive ? "Finish DOM adjustment" : "Adjust DOM element with keyboard arrows";
|
|
2858
|
+
adjust.setAttribute(
|
|
2859
|
+
"aria-label",
|
|
2860
|
+
isActive ? "Finish DOM adjustment" : "Adjust DOM element with keyboard arrows"
|
|
2861
|
+
);
|
|
2862
|
+
const [xyLine, scaleLine] = this.getDraftAdjustmentMetricLines(nextDraft);
|
|
2863
|
+
xyStatus.textContent = xyLine;
|
|
2864
|
+
scaleStatus.textContent = scaleLine;
|
|
2865
|
+
this.syncDraftAdjustmentUi({
|
|
2866
|
+
draft: nextDraft,
|
|
2867
|
+
hud,
|
|
2868
|
+
pin,
|
|
2869
|
+
selectionHighlight
|
|
2870
|
+
});
|
|
2871
|
+
};
|
|
2872
|
+
const updateDraft = (updater) => {
|
|
2873
|
+
const currentDraft = this.state.noteDraft ?? draft;
|
|
2874
|
+
const nextDraft = updater(currentDraft);
|
|
2875
|
+
this.config.actions.setNoteDraft({
|
|
2876
|
+
...nextDraft,
|
|
2877
|
+
comment: textarea.value
|
|
2878
|
+
});
|
|
2879
|
+
syncControls(nextDraft);
|
|
2880
|
+
};
|
|
2881
|
+
adjust.addEventListener("click", () => {
|
|
2882
|
+
updateDraft((currentDraft) => ({
|
|
2883
|
+
...currentDraft,
|
|
2884
|
+
adjustment: {
|
|
2885
|
+
x: currentDraft.adjustment?.x ?? 0,
|
|
2886
|
+
y: currentDraft.adjustment?.y ?? 0,
|
|
2887
|
+
scale: currentDraft.adjustment?.scale ?? 0,
|
|
2888
|
+
isActive: currentDraft.adjustment?.isActive !== true
|
|
2889
|
+
}
|
|
2890
|
+
}));
|
|
2891
|
+
adjust.focus();
|
|
2892
|
+
});
|
|
2893
|
+
popover.addEventListener("keydown", (event) => {
|
|
2894
|
+
const currentDraft = this.state.noteDraft ?? draft;
|
|
2895
|
+
if (currentDraft.adjustment?.isActive !== true) return;
|
|
2896
|
+
const keyDelta = this.getAdjustmentKeyDelta(event);
|
|
2897
|
+
if (!keyDelta) return;
|
|
2898
|
+
event.preventDefault();
|
|
2899
|
+
event.stopPropagation();
|
|
2900
|
+
updateDraft((activeDraft) => ({
|
|
2901
|
+
...activeDraft,
|
|
2902
|
+
adjustment: {
|
|
2903
|
+
x: (activeDraft.adjustment?.x ?? 0) + keyDelta.x,
|
|
2904
|
+
y: (activeDraft.adjustment?.y ?? 0) + keyDelta.y,
|
|
2905
|
+
scale: (activeDraft.adjustment?.scale ?? 0) + keyDelta.scale,
|
|
2906
|
+
isActive: true
|
|
2907
|
+
}
|
|
2908
|
+
}));
|
|
2909
|
+
});
|
|
2910
|
+
header.append(help, adjust);
|
|
2911
|
+
panel.append(header, xyStatus, scaleStatus);
|
|
2912
|
+
syncControls(draft);
|
|
2913
|
+
return {
|
|
2914
|
+
panel,
|
|
2915
|
+
focusTarget: adjust
|
|
2916
|
+
};
|
|
2917
|
+
}
|
|
2918
|
+
getAdjustmentKeyDelta(event) {
|
|
2919
|
+
const step = event.shiftKey ? 10 : 1;
|
|
2920
|
+
if (event.key === "ArrowLeft") return { x: -step, y: 0, scale: 0 };
|
|
2921
|
+
if (event.key === "ArrowRight") return { x: step, y: 0, scale: 0 };
|
|
2922
|
+
if (event.key === "ArrowUp") return { x: 0, y: -step, scale: 0 };
|
|
2923
|
+
if (event.key === "ArrowDown") return { x: 0, y: step, scale: 0 };
|
|
2924
|
+
if (event.key.toLowerCase() === "w") return { x: 0, y: 0, scale: step };
|
|
2925
|
+
if (event.key.toLowerCase() === "s") return { x: 0, y: 0, scale: -step };
|
|
2926
|
+
return void 0;
|
|
2927
|
+
}
|
|
2928
|
+
createAdjustmentHud(draft, environment) {
|
|
2929
|
+
const hud = document.createElement("div");
|
|
2930
|
+
hud.className = "dfwr-adjust-hud";
|
|
2931
|
+
hud.setAttribute("aria-hidden", "true");
|
|
2932
|
+
this.syncAdjustmentHud(hud, draft, environment);
|
|
2933
|
+
return hud;
|
|
2934
|
+
}
|
|
2935
|
+
syncDraftAdjustmentUi({
|
|
2936
|
+
draft,
|
|
2937
|
+
hud,
|
|
2938
|
+
pin,
|
|
2939
|
+
selectionHighlight
|
|
2940
|
+
}) {
|
|
2941
|
+
const environment = this.config.getEnvironment();
|
|
2942
|
+
if (!environment) return;
|
|
2943
|
+
const hostPoint = toHostPoint(
|
|
2944
|
+
this.getAdjustedDraftPoint(draft.marker.viewport, draft),
|
|
2945
|
+
environment
|
|
2946
|
+
);
|
|
2947
|
+
pin.style.left = `${hostPoint.x}px`;
|
|
2948
|
+
pin.style.top = `${hostPoint.y}px`;
|
|
2949
|
+
if (draft.selection && selectionHighlight) {
|
|
2950
|
+
const rect = toHostSelection(
|
|
2951
|
+
this.getAdjustedDraftSelection(
|
|
2952
|
+
toViewportSelection(draft.selection.viewport),
|
|
2953
|
+
draft
|
|
2954
|
+
),
|
|
2955
|
+
environment
|
|
2956
|
+
);
|
|
2957
|
+
selectionHighlight.style.left = `${rect.left}px`;
|
|
2958
|
+
selectionHighlight.style.top = `${rect.top}px`;
|
|
2959
|
+
selectionHighlight.style.width = `${rect.width}px`;
|
|
2960
|
+
selectionHighlight.style.height = `${rect.height}px`;
|
|
2961
|
+
}
|
|
2962
|
+
if (hud) {
|
|
2963
|
+
this.syncAdjustmentHud(hud, draft, environment);
|
|
2964
|
+
}
|
|
2965
|
+
this.syncDraftPreview(draft);
|
|
2966
|
+
}
|
|
2967
|
+
syncAdjustmentHud(hud, draft, environment) {
|
|
2968
|
+
if (!draft.selection) return;
|
|
2969
|
+
const rect = toHostSelection(
|
|
2970
|
+
this.getAdjustedDraftSelection(
|
|
2971
|
+
toViewportSelection(draft.selection.viewport),
|
|
2972
|
+
draft
|
|
2973
|
+
),
|
|
2974
|
+
environment
|
|
2975
|
+
);
|
|
2976
|
+
const isVisible = draft.adjustment?.isActive === true || this.hasDraftAdjustment(draft);
|
|
2977
|
+
hud.hidden = !isVisible;
|
|
2978
|
+
hud.textContent = this.formatDraftAdjustmentStatus(draft);
|
|
2979
|
+
hud.style.left = `${Math.max(4, rect.left)}px`;
|
|
2980
|
+
hud.style.top = `${Math.max(4, rect.top - 28)}px`;
|
|
2981
|
+
}
|
|
2072
2982
|
createAreaForm() {
|
|
2073
2983
|
const form = document.createElement("form");
|
|
2074
2984
|
form.className = "dfwr-form";
|
|
@@ -2080,14 +2990,20 @@ var WebReviewKitView = class {
|
|
|
2080
2990
|
form.append(empty);
|
|
2081
2991
|
return form;
|
|
2082
2992
|
}
|
|
2083
|
-
|
|
2084
|
-
meta.className = "dfwr-item-date";
|
|
2085
|
-
meta.textContent = formatAreaDraftMeta(areaDraft);
|
|
2086
|
-
form.append(meta);
|
|
2993
|
+
form.append(this.createAreaMetricsPanel(areaDraft));
|
|
2087
2994
|
const textarea = document.createElement("textarea");
|
|
2088
2995
|
textarea.className = "dfwr-textarea";
|
|
2089
2996
|
textarea.placeholder = "Area comment";
|
|
2090
2997
|
textarea.rows = 4;
|
|
2998
|
+
textarea.value = areaDraft.comment ?? "";
|
|
2999
|
+
textarea.addEventListener("input", () => {
|
|
3000
|
+
const draft = this.state.areaDraft;
|
|
3001
|
+
if (!draft) return;
|
|
3002
|
+
this.config.actions.setAreaDraft({
|
|
3003
|
+
...draft,
|
|
3004
|
+
comment: textarea.value
|
|
3005
|
+
});
|
|
3006
|
+
});
|
|
2091
3007
|
const actions = this.createFormActions("Save area", () => {
|
|
2092
3008
|
const comment = textarea.value.trim();
|
|
2093
3009
|
const draft = this.state.areaDraft;
|
|
@@ -2104,6 +3020,25 @@ var WebReviewKitView = class {
|
|
|
2104
3020
|
form.append(textarea, actions);
|
|
2105
3021
|
return form;
|
|
2106
3022
|
}
|
|
3023
|
+
createAreaMetricsPanel(draft) {
|
|
3024
|
+
const panel = document.createElement("div");
|
|
3025
|
+
panel.className = "dfwr-adjust-panel is-area-metrics-panel";
|
|
3026
|
+
const help = document.createElement("div");
|
|
3027
|
+
help.className = "dfwr-adjust-help";
|
|
3028
|
+
const [labelLine, xyLine, sizeLine] = this.getSelectionMetricLines(
|
|
3029
|
+
this.getAreaDraftMetricSelection(draft),
|
|
3030
|
+
draft.viewport
|
|
3031
|
+
);
|
|
3032
|
+
help.textContent = labelLine;
|
|
3033
|
+
const xyStatus = document.createElement("div");
|
|
3034
|
+
xyStatus.className = "dfwr-adjust-status";
|
|
3035
|
+
xyStatus.textContent = xyLine;
|
|
3036
|
+
const sizeStatus = document.createElement("div");
|
|
3037
|
+
sizeStatus.className = "dfwr-adjust-status";
|
|
3038
|
+
sizeStatus.textContent = sizeLine;
|
|
3039
|
+
panel.append(help, xyStatus, sizeStatus);
|
|
3040
|
+
return panel;
|
|
3041
|
+
}
|
|
2107
3042
|
createAreaDraftOverlay(draft) {
|
|
2108
3043
|
const layer = document.createElement("div");
|
|
2109
3044
|
layer.className = "dfwr-area-preview-layer";
|
|
@@ -2132,23 +3067,37 @@ var WebReviewKitView = class {
|
|
|
2132
3067
|
createAreaDraftPopover(draft) {
|
|
2133
3068
|
const environment = this.config.getEnvironment();
|
|
2134
3069
|
const popover = document.createElement("div");
|
|
2135
|
-
popover.className = "dfwr-area-draft";
|
|
3070
|
+
popover.className = "dfwr-area-draft is-composer";
|
|
2136
3071
|
if (environment && draft.selection) {
|
|
2137
3072
|
const selection = toHostSelection(
|
|
2138
3073
|
toViewportSelection(draft.selection.viewport),
|
|
2139
3074
|
environment
|
|
2140
3075
|
);
|
|
2141
|
-
const
|
|
2142
|
-
|
|
2143
|
-
|
|
3076
|
+
const composer = this.getDraftComposerPosition({
|
|
3077
|
+
selection,
|
|
3078
|
+
environment,
|
|
3079
|
+
composerPosition: draft.composerPosition,
|
|
3080
|
+
estimatedHeight: 220
|
|
3081
|
+
});
|
|
3082
|
+
popover.style.left = `${composer.left}px`;
|
|
3083
|
+
popover.style.top = `${composer.top}px`;
|
|
3084
|
+
popover.style.width = `${composer.width}px`;
|
|
2144
3085
|
popover.style.right = "auto";
|
|
2145
3086
|
}
|
|
2146
|
-
|
|
3087
|
+
const dragHandle = this.createDraftDragHandle("Move area composer");
|
|
3088
|
+
popover.append(dragHandle, this.createAreaForm());
|
|
3089
|
+
this.attachDraftComposerDrag(popover, dragHandle, (composerPosition) => {
|
|
3090
|
+
const areaDraft = this.state.areaDraft ?? draft;
|
|
3091
|
+
this.config.actions.setAreaDraft({
|
|
3092
|
+
...areaDraft,
|
|
3093
|
+
composerPosition
|
|
3094
|
+
});
|
|
3095
|
+
});
|
|
2147
3096
|
return popover;
|
|
2148
3097
|
}
|
|
2149
|
-
createFormActions(saveLabel, onSave) {
|
|
3098
|
+
createFormActions(saveLabel, onSave, options) {
|
|
2150
3099
|
const actions = document.createElement("div");
|
|
2151
|
-
actions.className = "dfwr-actions";
|
|
3100
|
+
actions.className = ["dfwr-actions", options?.className].filter(Boolean).join(" ");
|
|
2152
3101
|
const save = document.createElement("button");
|
|
2153
3102
|
save.className = "dfwr-button is-primary";
|
|
2154
3103
|
save.type = "button";
|
|
@@ -2163,6 +3112,10 @@ var WebReviewKitView = class {
|
|
|
2163
3112
|
this.config.actions.clearDrafts();
|
|
2164
3113
|
this.config.actions.render();
|
|
2165
3114
|
});
|
|
3115
|
+
if (options?.beforeSave?.length || options?.className) {
|
|
3116
|
+
actions.append(cancel, ...options.beforeSave ?? [], save);
|
|
3117
|
+
return actions;
|
|
3118
|
+
}
|
|
2166
3119
|
actions.append(save, cancel);
|
|
2167
3120
|
return actions;
|
|
2168
3121
|
}
|
|
@@ -2367,11 +3320,13 @@ ${formatItemMeta(item)}`;
|
|
|
2367
3320
|
if (!environment) return;
|
|
2368
3321
|
const nextPoint = clampPoint(toTargetPoint(hostPoint, environment), environment);
|
|
2369
3322
|
const nextHostPoint = toHostPoint(nextPoint, environment);
|
|
2370
|
-
const position = getPopoverPosition(nextHostPoint, environment);
|
|
2371
3323
|
pin.style.left = `${nextHostPoint.x}px`;
|
|
2372
3324
|
pin.style.top = `${nextHostPoint.y}px`;
|
|
2373
|
-
popover
|
|
2374
|
-
|
|
3325
|
+
if (popover) {
|
|
3326
|
+
const position = getPopoverPosition(nextHostPoint, environment);
|
|
3327
|
+
popover.style.left = `${position.left}px`;
|
|
3328
|
+
popover.style.top = `${position.top}px`;
|
|
3329
|
+
}
|
|
2375
3330
|
const noteDraft = this.state.noteDraft;
|
|
2376
3331
|
if (!noteDraft) return;
|
|
2377
3332
|
const nextDraft = {
|
|
@@ -2383,7 +3338,9 @@ ${formatItemMeta(item)}`;
|
|
|
2383
3338
|
comment: textarea.value
|
|
2384
3339
|
};
|
|
2385
3340
|
this.config.actions.setNoteDraft(nextDraft);
|
|
2386
|
-
|
|
3341
|
+
if (meta) {
|
|
3342
|
+
meta.textContent = formatNoteDraftMeta(nextDraft);
|
|
3343
|
+
}
|
|
2387
3344
|
};
|
|
2388
3345
|
pin.addEventListener("pointerdown", (event) => {
|
|
2389
3346
|
if (event.button !== 0) return;
|
|
@@ -2616,6 +3573,9 @@ var WebReviewKitApp = class {
|
|
|
2616
3573
|
setNoteDraft: (draft) => {
|
|
2617
3574
|
this.noteDraft = draft;
|
|
2618
3575
|
},
|
|
3576
|
+
setAreaDraft: (draft) => {
|
|
3577
|
+
this.areaDraft = draft;
|
|
3578
|
+
},
|
|
2619
3579
|
setSelectingArea: (isSelectingArea) => {
|
|
2620
3580
|
this.isSelectingArea = isSelectingArea;
|
|
2621
3581
|
},
|
|
@@ -2641,6 +3601,7 @@ var WebReviewKitApp = class {
|
|
|
2641
3601
|
this.render();
|
|
2642
3602
|
}
|
|
2643
3603
|
destroy() {
|
|
3604
|
+
this.view.clearDraftPreview();
|
|
2644
3605
|
document.removeEventListener("keydown", this.handleKeyDown, true);
|
|
2645
3606
|
window.removeEventListener("scroll", this.handleViewportChange, true);
|
|
2646
3607
|
window.removeEventListener("resize", this.handleViewportChange);
|
|
@@ -2851,7 +3812,7 @@ var WebReviewKitApp = class {
|
|
|
2851
3812
|
);
|
|
2852
3813
|
const elementSelection = anchor ? getElementViewportSelection(anchor, environment) : void 0;
|
|
2853
3814
|
const selection = elementSelection ?? getPointSelection(nextPoint);
|
|
2854
|
-
const markerPoint = getSelectionCenter(selection);
|
|
3815
|
+
const markerPoint = elementSelection ? { x: selection.left, y: selection.top } : getSelectionCenter(selection);
|
|
2855
3816
|
const reviewSelection = elementSelection ? {
|
|
2856
3817
|
viewport: toPublicSelection(elementSelection),
|
|
2857
3818
|
relative: getRelativeSelection(
|
|
@@ -3009,4 +3970,4 @@ export {
|
|
|
3009
3970
|
getNumberedReviewItems,
|
|
3010
3971
|
createWebReviewKit
|
|
3011
3972
|
};
|
|
3012
|
-
//# sourceMappingURL=chunk-
|
|
3973
|
+
//# sourceMappingURL=chunk-QFNYQCTA.js.map
|