@designfever/web-review-kit 0.2.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 +40 -0
- package/dist/{chunk-EJDROXJM.js → chunk-QFNYQCTA.js} +1081 -92
- package/dist/chunk-QFNYQCTA.js.map +1 -0
- package/dist/index.cjs +1081 -92
- 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 +2 -2
- package/dist/index.js.map +1 -1
- package/dist/react-shell.cjs +3637 -777
- package/dist/react-shell.cjs.map +1 -1
- package/dist/react-shell.d.cts +12 -3
- package/dist/react-shell.d.ts +12 -3
- package/dist/react-shell.js +2520 -643
- package/dist/react-shell.js.map +1 -1
- package/dist/{types-NiCp9JJQ.d.cts → types-D_qYtwTs.d.cts} +6 -1
- package/dist/{types-NiCp9JJQ.d.ts → types-D_qYtwTs.d.ts} +6 -1
- package/dist/vite.cjs +186 -0
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.cts +16 -0
- package/dist/vite.d.ts +16 -0
- package/dist/vite.js +161 -0
- package/dist/vite.js.map +1 -0
- package/docs/architecture.md +3 -0
- package/docs/installation.md +39 -0
- package/docs/release-notes-0.3.0.md +94 -0
- package/docs/release-notes-0.4.0.md +144 -0
- package/package.json +16 -5
- package/dist/chunk-EJDROXJM.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;
|
|
@@ -560,18 +688,39 @@ function decodeHtmlEntities(value) {
|
|
|
560
688
|
}
|
|
561
689
|
function getDomSourceHint(target) {
|
|
562
690
|
const sourceElement = target.closest(
|
|
563
|
-
|
|
691
|
+
[
|
|
692
|
+
"[data-wrk-source-file]",
|
|
693
|
+
"[data-wrk-source-component]",
|
|
694
|
+
"[data-wrk-source-line]",
|
|
695
|
+
"[data-wrk-source-column]",
|
|
696
|
+
"[data-file]",
|
|
697
|
+
"[data-component]",
|
|
698
|
+
"[data-section-index]",
|
|
699
|
+
"[data-section-id]"
|
|
700
|
+
].join(", ")
|
|
564
701
|
);
|
|
565
702
|
if (!sourceElement) return void 0;
|
|
566
|
-
const dataset = sourceElement.dataset;
|
|
567
703
|
const source = {
|
|
568
|
-
component:
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
704
|
+
component: getSourceAttribute(
|
|
705
|
+
sourceElement,
|
|
706
|
+
"data-wrk-source-component",
|
|
707
|
+
"data-component"
|
|
708
|
+
),
|
|
709
|
+
file: getSourceAttribute(sourceElement, "data-wrk-source-file", "data-file"),
|
|
710
|
+
line: getSourceAttribute(sourceElement, "data-wrk-source-line"),
|
|
711
|
+
column: getSourceAttribute(sourceElement, "data-wrk-source-column"),
|
|
712
|
+
sectionId: getSourceAttribute(sourceElement, "data-section-id"),
|
|
713
|
+
sectionIndex: getSourceAttribute(sourceElement, "data-section-index")
|
|
572
714
|
};
|
|
573
715
|
return Object.values(source).some(Boolean) ? source : void 0;
|
|
574
716
|
}
|
|
717
|
+
function getSourceAttribute(element, ...names) {
|
|
718
|
+
for (const name of names) {
|
|
719
|
+
const value = element.getAttribute(name)?.trim();
|
|
720
|
+
if (value) return value;
|
|
721
|
+
}
|
|
722
|
+
return void 0;
|
|
723
|
+
}
|
|
575
724
|
function dedupeAnchorCandidates(candidates) {
|
|
576
725
|
const seen = /* @__PURE__ */ new Set();
|
|
577
726
|
return candidates.filter((candidate) => {
|
|
@@ -638,10 +787,38 @@ function getDomPath(element) {
|
|
|
638
787
|
}
|
|
639
788
|
return `body > ${parts.join(" > ")}`;
|
|
640
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
|
+
}
|
|
641
811
|
function getTextFingerprint(element) {
|
|
642
812
|
const text = element.textContent?.replace(/\s+/g, " ").trim();
|
|
643
813
|
return text ? text.slice(0, 120) : void 0;
|
|
644
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
|
+
}
|
|
645
822
|
function getTextFingerprintScore(expected, actual) {
|
|
646
823
|
if (!expected) return 1;
|
|
647
824
|
if (!actual) return 0.5;
|
|
@@ -1017,6 +1194,19 @@ function createStyleElement() {
|
|
|
1017
1194
|
display: block;
|
|
1018
1195
|
}
|
|
1019
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
|
+
|
|
1020
1210
|
.dfwr-panel {
|
|
1021
1211
|
position: fixed;
|
|
1022
1212
|
right: 16px;
|
|
@@ -1510,6 +1700,40 @@ function createStyleElement() {
|
|
|
1510
1700
|
box-shadow: var(--df-review-shadow-popover);
|
|
1511
1701
|
}
|
|
1512
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
|
+
|
|
1513
1737
|
.dfwr-area-draft {
|
|
1514
1738
|
position: fixed;
|
|
1515
1739
|
right: 16px;
|
|
@@ -1531,6 +1755,14 @@ function createStyleElement() {
|
|
|
1531
1755
|
padding: 0;
|
|
1532
1756
|
}
|
|
1533
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
|
+
|
|
1534
1766
|
.dfwr-area-draft .dfwr-actions {
|
|
1535
1767
|
padding: 0;
|
|
1536
1768
|
}
|
|
@@ -1559,6 +1791,105 @@ function createStyleElement() {
|
|
|
1559
1791
|
outline-offset: 1px;
|
|
1560
1792
|
}
|
|
1561
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
|
+
|
|
1562
1893
|
.dfwr-empty,
|
|
1563
1894
|
.dfwr-error {
|
|
1564
1895
|
margin: 0;
|
|
@@ -1779,16 +2110,6 @@ function createStyleElement() {
|
|
|
1779
2110
|
}
|
|
1780
2111
|
|
|
1781
2112
|
// src/core/review/format.ts
|
|
1782
|
-
function formatAreaDraftMeta(draft) {
|
|
1783
|
-
const parts = [`viewport ${formatSize(draft.viewport)}`];
|
|
1784
|
-
if (draft.selection) {
|
|
1785
|
-
parts.push(`rect ${formatSelection(draft.selection.viewport)}`);
|
|
1786
|
-
}
|
|
1787
|
-
if (draft.marker) {
|
|
1788
|
-
parts.push(`point ${formatPoint(draft.marker.viewport)}`);
|
|
1789
|
-
}
|
|
1790
|
-
return parts.join(" / ");
|
|
1791
|
-
}
|
|
1792
2113
|
function formatNoteDraftMeta(draft) {
|
|
1793
2114
|
const parts = [
|
|
1794
2115
|
`viewport ${formatSize(draft.viewport)}`,
|
|
@@ -1854,17 +2175,29 @@ function formatAnchorMeta(anchor) {
|
|
|
1854
2175
|
}
|
|
1855
2176
|
|
|
1856
2177
|
// src/core/web.review.kit.view.ts
|
|
2178
|
+
var DEFAULT_ADJUSTMENT_LABEL = "Responsive CSS px adjustments";
|
|
1857
2179
|
var WebReviewKitView = class {
|
|
1858
2180
|
constructor(config) {
|
|
1859
2181
|
this.config = config;
|
|
1860
2182
|
}
|
|
2183
|
+
clearDraftPreview() {
|
|
2184
|
+
this.restoreDraftPreview();
|
|
2185
|
+
}
|
|
1861
2186
|
render(shadow, hiddenItemsStyle) {
|
|
1862
2187
|
const state = this.state;
|
|
2188
|
+
this.syncDraftPreview(
|
|
2189
|
+
state.isOpen && state.mode === "element" ? state.noteDraft : void 0
|
|
2190
|
+
);
|
|
1863
2191
|
shadow.replaceChildren();
|
|
1864
2192
|
shadow.append(createStyleElement());
|
|
1865
2193
|
shadow.append(hiddenItemsStyle);
|
|
2194
|
+
const hasDismissableDraft = Boolean(state.noteDraft || state.areaDraft);
|
|
1866
2195
|
const shell = document.createElement("div");
|
|
1867
|
-
shell.className =
|
|
2196
|
+
shell.className = [
|
|
2197
|
+
"dfwr-shell",
|
|
2198
|
+
state.isOpen ? "is-open" : "",
|
|
2199
|
+
hasDismissableDraft ? "has-dismissible-draft" : ""
|
|
2200
|
+
].filter(Boolean).join(" ");
|
|
1868
2201
|
shell.setAttribute("aria-hidden", state.isOpen ? "false" : "true");
|
|
1869
2202
|
if (this.config.options.ui?.panel !== false) {
|
|
1870
2203
|
const panel = document.createElement("div");
|
|
@@ -1880,6 +2213,9 @@ var WebReviewKitView = class {
|
|
|
1880
2213
|
shell.append(panel);
|
|
1881
2214
|
}
|
|
1882
2215
|
shell.append(this.createMarkerLayer());
|
|
2216
|
+
if (state.isOpen && hasDismissableDraft) {
|
|
2217
|
+
shell.append(this.createDraftCancelLayer());
|
|
2218
|
+
}
|
|
1883
2219
|
if (state.isOpen && (state.mode === "note" || state.mode === "element")) {
|
|
1884
2220
|
shell.append(
|
|
1885
2221
|
state.noteDraft ? this.createNotePopover(state.noteDraft) : state.mode === "element" ? this.createElementLayer() : this.createNoteLayer()
|
|
@@ -1899,6 +2235,294 @@ var WebReviewKitView = class {
|
|
|
1899
2235
|
get state() {
|
|
1900
2236
|
return this.config.getState();
|
|
1901
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
|
+
}
|
|
1902
2526
|
createHeader() {
|
|
1903
2527
|
const header = document.createElement("div");
|
|
1904
2528
|
header.className = "dfwr-header";
|
|
@@ -1990,15 +2614,20 @@ var WebReviewKitView = class {
|
|
|
1990
2614
|
const group = document.createElement("div");
|
|
1991
2615
|
group.className = "dfwr-note-draft";
|
|
1992
2616
|
if (!environment) return group;
|
|
1993
|
-
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;
|
|
1994
2623
|
if (draft.selection) {
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
)
|
|
2624
|
+
const selection = toViewportSelection(draft.selection.viewport);
|
|
2625
|
+
selectionHighlight = this.createSelectionHighlight(
|
|
2626
|
+
isElementDraft ? this.getAdjustedDraftSelection(selection, draft) : selection,
|
|
2627
|
+
environment,
|
|
2628
|
+
true
|
|
2001
2629
|
);
|
|
2630
|
+
group.append(selectionHighlight);
|
|
2002
2631
|
}
|
|
2003
2632
|
const pin = document.createElement("button");
|
|
2004
2633
|
pin.className = "dfwr-note-pin";
|
|
@@ -2008,14 +2637,35 @@ var WebReviewKitView = class {
|
|
|
2008
2637
|
pin.style.top = `${hostPoint.y}px`;
|
|
2009
2638
|
const popover = document.createElement("div");
|
|
2010
2639
|
const position = getPopoverPosition(hostPoint, environment);
|
|
2011
|
-
popover.className =
|
|
2012
|
-
|
|
2013
|
-
|
|
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
|
+
}
|
|
2014
2662
|
const form = document.createElement("form");
|
|
2015
2663
|
form.className = "dfwr-form";
|
|
2016
|
-
const meta = document.createElement("div");
|
|
2017
|
-
meta
|
|
2018
|
-
|
|
2664
|
+
const meta = isElementDraft ? void 0 : document.createElement("div");
|
|
2665
|
+
if (meta) {
|
|
2666
|
+
meta.className = "dfwr-item-date";
|
|
2667
|
+
meta.textContent = formatNoteDraftMeta(draft);
|
|
2668
|
+
}
|
|
2019
2669
|
const textarea = document.createElement("textarea");
|
|
2020
2670
|
textarea.className = "dfwr-textarea";
|
|
2021
2671
|
textarea.placeholder = "Review comment";
|
|
@@ -2029,25 +2679,306 @@ var WebReviewKitView = class {
|
|
|
2029
2679
|
comment: textarea.value
|
|
2030
2680
|
});
|
|
2031
2681
|
});
|
|
2032
|
-
const
|
|
2682
|
+
const saveDraft = () => {
|
|
2033
2683
|
const comment = textarea.value.trim();
|
|
2034
2684
|
if (!comment) return;
|
|
2685
|
+
const currentDraft = this.state.noteDraft ?? draft;
|
|
2035
2686
|
void this.config.actions.createItem({
|
|
2036
2687
|
kind: "note",
|
|
2037
|
-
comment,
|
|
2038
|
-
viewport:
|
|
2039
|
-
anchor:
|
|
2040
|
-
marker:
|
|
2041
|
-
selection:
|
|
2688
|
+
comment: this.withDraftAdjustmentComment(comment, currentDraft),
|
|
2689
|
+
viewport: currentDraft.viewport,
|
|
2690
|
+
anchor: currentDraft.anchor,
|
|
2691
|
+
marker: currentDraft.marker,
|
|
2692
|
+
selection: currentDraft.selection
|
|
2042
2693
|
});
|
|
2043
|
-
}
|
|
2044
|
-
|
|
2045
|
-
|
|
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);
|
|
2046
2716
|
group.append(pin, popover);
|
|
2047
|
-
|
|
2048
|
-
|
|
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);
|
|
2049
2740
|
return group;
|
|
2050
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
|
+
}
|
|
2051
2982
|
createAreaForm() {
|
|
2052
2983
|
const form = document.createElement("form");
|
|
2053
2984
|
form.className = "dfwr-form";
|
|
@@ -2059,14 +2990,20 @@ var WebReviewKitView = class {
|
|
|
2059
2990
|
form.append(empty);
|
|
2060
2991
|
return form;
|
|
2061
2992
|
}
|
|
2062
|
-
|
|
2063
|
-
meta.className = "dfwr-item-date";
|
|
2064
|
-
meta.textContent = formatAreaDraftMeta(areaDraft);
|
|
2065
|
-
form.append(meta);
|
|
2993
|
+
form.append(this.createAreaMetricsPanel(areaDraft));
|
|
2066
2994
|
const textarea = document.createElement("textarea");
|
|
2067
2995
|
textarea.className = "dfwr-textarea";
|
|
2068
2996
|
textarea.placeholder = "Area comment";
|
|
2069
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
|
+
});
|
|
2070
3007
|
const actions = this.createFormActions("Save area", () => {
|
|
2071
3008
|
const comment = textarea.value.trim();
|
|
2072
3009
|
const draft = this.state.areaDraft;
|
|
@@ -2083,6 +3020,25 @@ var WebReviewKitView = class {
|
|
|
2083
3020
|
form.append(textarea, actions);
|
|
2084
3021
|
return form;
|
|
2085
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
|
+
}
|
|
2086
3042
|
createAreaDraftOverlay(draft) {
|
|
2087
3043
|
const layer = document.createElement("div");
|
|
2088
3044
|
layer.className = "dfwr-area-preview-layer";
|
|
@@ -2111,23 +3067,37 @@ var WebReviewKitView = class {
|
|
|
2111
3067
|
createAreaDraftPopover(draft) {
|
|
2112
3068
|
const environment = this.config.getEnvironment();
|
|
2113
3069
|
const popover = document.createElement("div");
|
|
2114
|
-
popover.className = "dfwr-area-draft";
|
|
3070
|
+
popover.className = "dfwr-area-draft is-composer";
|
|
2115
3071
|
if (environment && draft.selection) {
|
|
2116
3072
|
const selection = toHostSelection(
|
|
2117
3073
|
toViewportSelection(draft.selection.viewport),
|
|
2118
3074
|
environment
|
|
2119
3075
|
);
|
|
2120
|
-
const
|
|
2121
|
-
|
|
2122
|
-
|
|
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`;
|
|
2123
3085
|
popover.style.right = "auto";
|
|
2124
3086
|
}
|
|
2125
|
-
|
|
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
|
+
});
|
|
2126
3096
|
return popover;
|
|
2127
3097
|
}
|
|
2128
|
-
createFormActions(saveLabel, onSave) {
|
|
3098
|
+
createFormActions(saveLabel, onSave, options) {
|
|
2129
3099
|
const actions = document.createElement("div");
|
|
2130
|
-
actions.className = "dfwr-actions";
|
|
3100
|
+
actions.className = ["dfwr-actions", options?.className].filter(Boolean).join(" ");
|
|
2131
3101
|
const save = document.createElement("button");
|
|
2132
3102
|
save.className = "dfwr-button is-primary";
|
|
2133
3103
|
save.type = "button";
|
|
@@ -2142,6 +3112,10 @@ var WebReviewKitView = class {
|
|
|
2142
3112
|
this.config.actions.clearDrafts();
|
|
2143
3113
|
this.config.actions.render();
|
|
2144
3114
|
});
|
|
3115
|
+
if (options?.beforeSave?.length || options?.className) {
|
|
3116
|
+
actions.append(cancel, ...options.beforeSave ?? [], save);
|
|
3117
|
+
return actions;
|
|
3118
|
+
}
|
|
2145
3119
|
actions.append(save, cancel);
|
|
2146
3120
|
return actions;
|
|
2147
3121
|
}
|
|
@@ -2346,11 +3320,13 @@ ${formatItemMeta(item)}`;
|
|
|
2346
3320
|
if (!environment) return;
|
|
2347
3321
|
const nextPoint = clampPoint(toTargetPoint(hostPoint, environment), environment);
|
|
2348
3322
|
const nextHostPoint = toHostPoint(nextPoint, environment);
|
|
2349
|
-
const position = getPopoverPosition(nextHostPoint, environment);
|
|
2350
3323
|
pin.style.left = `${nextHostPoint.x}px`;
|
|
2351
3324
|
pin.style.top = `${nextHostPoint.y}px`;
|
|
2352
|
-
popover
|
|
2353
|
-
|
|
3325
|
+
if (popover) {
|
|
3326
|
+
const position = getPopoverPosition(nextHostPoint, environment);
|
|
3327
|
+
popover.style.left = `${position.left}px`;
|
|
3328
|
+
popover.style.top = `${position.top}px`;
|
|
3329
|
+
}
|
|
2354
3330
|
const noteDraft = this.state.noteDraft;
|
|
2355
3331
|
if (!noteDraft) return;
|
|
2356
3332
|
const nextDraft = {
|
|
@@ -2362,7 +3338,9 @@ ${formatItemMeta(item)}`;
|
|
|
2362
3338
|
comment: textarea.value
|
|
2363
3339
|
};
|
|
2364
3340
|
this.config.actions.setNoteDraft(nextDraft);
|
|
2365
|
-
|
|
3341
|
+
if (meta) {
|
|
3342
|
+
meta.textContent = formatNoteDraftMeta(nextDraft);
|
|
3343
|
+
}
|
|
2366
3344
|
};
|
|
2367
3345
|
pin.addEventListener("pointerdown", (event) => {
|
|
2368
3346
|
if (event.button !== 0) return;
|
|
@@ -2516,6 +3494,13 @@ ${formatItemMeta(item)}`;
|
|
|
2516
3494
|
|
|
2517
3495
|
// src/core/web.review.kit.app.ts
|
|
2518
3496
|
var ROOT_ID = "df-web-review-kit-root";
|
|
3497
|
+
function isEditableEventTarget(event) {
|
|
3498
|
+
const path = event.composedPath?.() ?? [];
|
|
3499
|
+
const element = path[0] ?? event.target;
|
|
3500
|
+
if (!element || typeof element.tagName !== "string") return false;
|
|
3501
|
+
const tag = element.tagName;
|
|
3502
|
+
return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || element.isContentEditable === true;
|
|
3503
|
+
}
|
|
2519
3504
|
function createWebReviewKit(options) {
|
|
2520
3505
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2521
3506
|
return createNoopController();
|
|
@@ -2548,7 +3533,7 @@ var WebReviewKitApp = class {
|
|
|
2548
3533
|
event.stopPropagation();
|
|
2549
3534
|
return;
|
|
2550
3535
|
}
|
|
2551
|
-
if (!isHotkey(event, this.hotkey)) return;
|
|
3536
|
+
if (isEditableEventTarget(event) || !isHotkey(event, this.hotkey)) return;
|
|
2552
3537
|
event.preventDefault();
|
|
2553
3538
|
event.stopPropagation();
|
|
2554
3539
|
this.toggle();
|
|
@@ -2588,6 +3573,9 @@ var WebReviewKitApp = class {
|
|
|
2588
3573
|
setNoteDraft: (draft) => {
|
|
2589
3574
|
this.noteDraft = draft;
|
|
2590
3575
|
},
|
|
3576
|
+
setAreaDraft: (draft) => {
|
|
3577
|
+
this.areaDraft = draft;
|
|
3578
|
+
},
|
|
2591
3579
|
setSelectingArea: (isSelectingArea) => {
|
|
2592
3580
|
this.isSelectingArea = isSelectingArea;
|
|
2593
3581
|
},
|
|
@@ -2613,6 +3601,7 @@ var WebReviewKitApp = class {
|
|
|
2613
3601
|
this.render();
|
|
2614
3602
|
}
|
|
2615
3603
|
destroy() {
|
|
3604
|
+
this.view.clearDraftPreview();
|
|
2616
3605
|
document.removeEventListener("keydown", this.handleKeyDown, true);
|
|
2617
3606
|
window.removeEventListener("scroll", this.handleViewportChange, true);
|
|
2618
3607
|
window.removeEventListener("resize", this.handleViewportChange);
|
|
@@ -2823,7 +3812,7 @@ var WebReviewKitApp = class {
|
|
|
2823
3812
|
);
|
|
2824
3813
|
const elementSelection = anchor ? getElementViewportSelection(anchor, environment) : void 0;
|
|
2825
3814
|
const selection = elementSelection ?? getPointSelection(nextPoint);
|
|
2826
|
-
const markerPoint = getSelectionCenter(selection);
|
|
3815
|
+
const markerPoint = elementSelection ? { x: selection.left, y: selection.top } : getSelectionCenter(selection);
|
|
2827
3816
|
const reviewSelection = elementSelection ? {
|
|
2828
3817
|
viewport: toPublicSelection(elementSelection),
|
|
2829
3818
|
relative: getRelativeSelection(
|
|
@@ -2981,4 +3970,4 @@ export {
|
|
|
2981
3970
|
getNumberedReviewItems,
|
|
2982
3971
|
createWebReviewKit
|
|
2983
3972
|
};
|
|
2984
|
-
//# sourceMappingURL=chunk-
|
|
3973
|
+
//# sourceMappingURL=chunk-QFNYQCTA.js.map
|