web-remarq 0.3.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +189 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +189 -37
- package/dist/index.js.map +1 -1
- package/dist/web-remarq.global.global.js +189 -37
- package/dist/web-remarq.global.global.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -913,6 +913,12 @@ var CSS = `
|
|
|
913
913
|
|
|
914
914
|
.remarq-toolbar-btn:disabled { opacity: 0.3; cursor: default; }
|
|
915
915
|
.remarq-toolbar-btn:disabled:hover { background: transparent; }
|
|
916
|
+
|
|
917
|
+
.remarq-popup-hint {
|
|
918
|
+
font-size: 11px;
|
|
919
|
+
color: var(--remarq-text-secondary);
|
|
920
|
+
margin-top: 4px;
|
|
921
|
+
}
|
|
916
922
|
`;
|
|
917
923
|
function injectStyles() {
|
|
918
924
|
if (document.querySelector(`style[${STYLES_ID}]`)) return;
|
|
@@ -1143,15 +1149,13 @@ var Overlay = class {
|
|
|
1143
1149
|
this.overlayEl.style.height = `${rect.height}px`;
|
|
1144
1150
|
this.tooltipEl.textContent = describeElement(target);
|
|
1145
1151
|
this.tooltipEl.style.display = "block";
|
|
1146
|
-
this.
|
|
1147
|
-
this.tooltipEl.style.left = `${rect.left}px`;
|
|
1152
|
+
this.positionTooltip(rect.left, rect.top - 28);
|
|
1148
1153
|
} catch (e) {
|
|
1149
1154
|
this.hide();
|
|
1150
1155
|
}
|
|
1151
1156
|
}
|
|
1152
1157
|
updateTooltipPosition(x, y) {
|
|
1153
|
-
this.
|
|
1154
|
-
this.tooltipEl.style.top = `${y - 28}px`;
|
|
1158
|
+
this.positionTooltip(x + 12, y - 28);
|
|
1155
1159
|
}
|
|
1156
1160
|
hideHighlight() {
|
|
1157
1161
|
this.overlayEl.style.display = "none";
|
|
@@ -1164,6 +1168,16 @@ var Overlay = class {
|
|
|
1164
1168
|
this.overlayEl.remove();
|
|
1165
1169
|
this.tooltipEl.remove();
|
|
1166
1170
|
}
|
|
1171
|
+
positionTooltip(left, top) {
|
|
1172
|
+
this.tooltipEl.style.left = "0px";
|
|
1173
|
+
this.tooltipEl.style.top = "0px";
|
|
1174
|
+
const tooltipWidth = this.tooltipEl.offsetWidth;
|
|
1175
|
+
const tooltipHeight = this.tooltipEl.offsetHeight;
|
|
1176
|
+
const maxLeft = window.innerWidth - tooltipWidth - 8;
|
|
1177
|
+
const maxTop = window.innerHeight - tooltipHeight - 8;
|
|
1178
|
+
this.tooltipEl.style.left = `${Math.max(8, Math.min(left, maxLeft))}px`;
|
|
1179
|
+
this.tooltipEl.style.top = `${Math.max(8, Math.min(top, maxTop))}px`;
|
|
1180
|
+
}
|
|
1167
1181
|
};
|
|
1168
1182
|
function describeElement(el) {
|
|
1169
1183
|
const tag = el.tagName.toLowerCase();
|
|
@@ -1443,6 +1457,7 @@ var Popup = class {
|
|
|
1443
1457
|
this.container = container;
|
|
1444
1458
|
this.popupEl = null;
|
|
1445
1459
|
this.keyHandler = null;
|
|
1460
|
+
this.outsideClickHandler = null;
|
|
1446
1461
|
}
|
|
1447
1462
|
show(info, position, onSubmit, onCancel) {
|
|
1448
1463
|
this.hide();
|
|
@@ -1455,7 +1470,11 @@ var Popup = class {
|
|
|
1455
1470
|
body.className = "remarq-popup-body";
|
|
1456
1471
|
const textarea = document.createElement("textarea");
|
|
1457
1472
|
textarea.placeholder = "Add your comment...";
|
|
1473
|
+
const hint = document.createElement("div");
|
|
1474
|
+
hint.className = "remarq-popup-hint";
|
|
1475
|
+
hint.textContent = "Enter to submit \xB7 Shift+Enter for new line";
|
|
1458
1476
|
body.appendChild(textarea);
|
|
1477
|
+
body.appendChild(hint);
|
|
1459
1478
|
const actions = document.createElement("div");
|
|
1460
1479
|
actions.className = "remarq-popup-actions";
|
|
1461
1480
|
const cancelBtn = document.createElement("button");
|
|
@@ -1485,18 +1504,37 @@ var Popup = class {
|
|
|
1485
1504
|
textarea.focus();
|
|
1486
1505
|
});
|
|
1487
1506
|
this.keyHandler = (e) => {
|
|
1488
|
-
if (e.key === "
|
|
1507
|
+
if (e.key === "Escape") {
|
|
1508
|
+
this.hide();
|
|
1509
|
+
onCancel();
|
|
1510
|
+
return;
|
|
1511
|
+
}
|
|
1512
|
+
if (e.key === "Enter" && !e.shiftKey && e.target === textarea) {
|
|
1513
|
+
e.preventDefault();
|
|
1489
1514
|
const comment = textarea.value.trim();
|
|
1490
1515
|
if (!comment) return;
|
|
1491
1516
|
this.hide();
|
|
1492
1517
|
onSubmit(comment);
|
|
1518
|
+
return;
|
|
1493
1519
|
}
|
|
1494
|
-
if (e.key === "
|
|
1520
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
1521
|
+
const comment = textarea.value.trim();
|
|
1522
|
+
if (!comment) return;
|
|
1495
1523
|
this.hide();
|
|
1496
|
-
|
|
1524
|
+
onSubmit(comment);
|
|
1497
1525
|
}
|
|
1498
1526
|
};
|
|
1499
1527
|
document.addEventListener("keydown", this.keyHandler);
|
|
1528
|
+
setTimeout(() => {
|
|
1529
|
+
this.outsideClickHandler = (e) => {
|
|
1530
|
+
const target = e.target;
|
|
1531
|
+
if (target && !target.closest(".remarq-popup")) {
|
|
1532
|
+
this.hide();
|
|
1533
|
+
onCancel();
|
|
1534
|
+
}
|
|
1535
|
+
};
|
|
1536
|
+
document.addEventListener("mousedown", this.outsideClickHandler);
|
|
1537
|
+
}, 0);
|
|
1500
1538
|
}
|
|
1501
1539
|
showDetail(info, position, callbacks) {
|
|
1502
1540
|
this.hide();
|
|
@@ -1507,7 +1545,15 @@ var Popup = class {
|
|
|
1507
1545
|
header.textContent = `<${info.tag}>${info.text ? ` "${info.text}"` : ""} [${info.status}]`;
|
|
1508
1546
|
const body = document.createElement("div");
|
|
1509
1547
|
body.className = "remarq-popup-body";
|
|
1510
|
-
|
|
1548
|
+
const makeCommentEl = () => {
|
|
1549
|
+
const el = document.createElement("div");
|
|
1550
|
+
el.textContent = info.comment;
|
|
1551
|
+
el.style.cursor = "pointer";
|
|
1552
|
+
el.title = "Click to edit";
|
|
1553
|
+
el.addEventListener("click", () => this.enterEditMode(el, info, callbacks));
|
|
1554
|
+
return el;
|
|
1555
|
+
};
|
|
1556
|
+
body.appendChild(makeCommentEl());
|
|
1511
1557
|
const actions = document.createElement("div");
|
|
1512
1558
|
actions.className = "remarq-popup-actions";
|
|
1513
1559
|
if (info.status === "pending") {
|
|
@@ -1549,6 +1595,16 @@ var Popup = class {
|
|
|
1549
1595
|
}
|
|
1550
1596
|
};
|
|
1551
1597
|
document.addEventListener("keydown", this.keyHandler);
|
|
1598
|
+
setTimeout(() => {
|
|
1599
|
+
this.outsideClickHandler = (e) => {
|
|
1600
|
+
const target = e.target;
|
|
1601
|
+
if (target && !target.closest(".remarq-popup")) {
|
|
1602
|
+
this.hide();
|
|
1603
|
+
callbacks.onClose();
|
|
1604
|
+
}
|
|
1605
|
+
};
|
|
1606
|
+
document.addEventListener("mousedown", this.outsideClickHandler);
|
|
1607
|
+
}, 0);
|
|
1552
1608
|
}
|
|
1553
1609
|
hide() {
|
|
1554
1610
|
if (this.popupEl) {
|
|
@@ -1559,10 +1615,68 @@ var Popup = class {
|
|
|
1559
1615
|
document.removeEventListener("keydown", this.keyHandler);
|
|
1560
1616
|
this.keyHandler = null;
|
|
1561
1617
|
}
|
|
1618
|
+
if (this.outsideClickHandler) {
|
|
1619
|
+
document.removeEventListener("mousedown", this.outsideClickHandler);
|
|
1620
|
+
this.outsideClickHandler = null;
|
|
1621
|
+
}
|
|
1562
1622
|
}
|
|
1563
1623
|
destroy() {
|
|
1564
1624
|
this.hide();
|
|
1565
1625
|
}
|
|
1626
|
+
enterEditMode(commentEl, info, callbacks) {
|
|
1627
|
+
const textarea = document.createElement("textarea");
|
|
1628
|
+
textarea.value = info.comment;
|
|
1629
|
+
textarea.className = "remarq-popup-edit-textarea";
|
|
1630
|
+
textarea.style.width = "100%";
|
|
1631
|
+
textarea.style.minHeight = "60px";
|
|
1632
|
+
textarea.style.padding = "8px";
|
|
1633
|
+
textarea.style.border = "1px solid var(--remarq-border)";
|
|
1634
|
+
textarea.style.borderRadius = "4px";
|
|
1635
|
+
textarea.style.background = "var(--remarq-bg-secondary)";
|
|
1636
|
+
textarea.style.color = "var(--remarq-text)";
|
|
1637
|
+
textarea.style.fontFamily = "inherit";
|
|
1638
|
+
textarea.style.fontSize = "13px";
|
|
1639
|
+
textarea.style.resize = "vertical";
|
|
1640
|
+
textarea.style.boxSizing = "border-box";
|
|
1641
|
+
commentEl.replaceWith(textarea);
|
|
1642
|
+
textarea.focus();
|
|
1643
|
+
textarea.selectionStart = textarea.value.length;
|
|
1644
|
+
const saveEdit = () => {
|
|
1645
|
+
const newComment = textarea.value.trim();
|
|
1646
|
+
if (newComment && newComment !== info.comment) {
|
|
1647
|
+
info.comment = newComment;
|
|
1648
|
+
callbacks.onEdit(newComment);
|
|
1649
|
+
}
|
|
1650
|
+
const restored = document.createElement("div");
|
|
1651
|
+
restored.textContent = info.comment;
|
|
1652
|
+
restored.style.cursor = "pointer";
|
|
1653
|
+
restored.title = "Click to edit";
|
|
1654
|
+
restored.addEventListener("click", () => this.enterEditMode(restored, info, callbacks));
|
|
1655
|
+
textarea.replaceWith(restored);
|
|
1656
|
+
};
|
|
1657
|
+
textarea.addEventListener("keydown", (e) => {
|
|
1658
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
1659
|
+
e.preventDefault();
|
|
1660
|
+
saveEdit();
|
|
1661
|
+
}
|
|
1662
|
+
if (e.key === "Escape") {
|
|
1663
|
+
e.stopPropagation();
|
|
1664
|
+
const restored = document.createElement("div");
|
|
1665
|
+
restored.textContent = info.comment;
|
|
1666
|
+
restored.style.cursor = "pointer";
|
|
1667
|
+
restored.title = "Click to edit";
|
|
1668
|
+
restored.addEventListener("click", () => this.enterEditMode(restored, info, callbacks));
|
|
1669
|
+
textarea.replaceWith(restored);
|
|
1670
|
+
}
|
|
1671
|
+
});
|
|
1672
|
+
textarea.addEventListener("blur", () => {
|
|
1673
|
+
setTimeout(() => {
|
|
1674
|
+
if (textarea.isConnected) {
|
|
1675
|
+
saveEdit();
|
|
1676
|
+
}
|
|
1677
|
+
}, 50);
|
|
1678
|
+
});
|
|
1679
|
+
}
|
|
1566
1680
|
adjustPosition(popup2, position) {
|
|
1567
1681
|
const popupHeight = popup2.offsetHeight;
|
|
1568
1682
|
const viewportBottom = window.scrollY + window.innerHeight;
|
|
@@ -1661,14 +1775,40 @@ var MarkerManager = class {
|
|
|
1661
1775
|
}
|
|
1662
1776
|
};
|
|
1663
1777
|
|
|
1778
|
+
// src/ui/toast.ts
|
|
1779
|
+
var currentToast = null;
|
|
1780
|
+
var currentTimer = null;
|
|
1781
|
+
function showToast(container, message, duration = 3e3) {
|
|
1782
|
+
hideToast();
|
|
1783
|
+
const toast = document.createElement("div");
|
|
1784
|
+
toast.className = "remarq-toast";
|
|
1785
|
+
toast.textContent = message;
|
|
1786
|
+
container.appendChild(toast);
|
|
1787
|
+
currentToast = toast;
|
|
1788
|
+
currentTimer = setTimeout(() => {
|
|
1789
|
+
if (currentToast) {
|
|
1790
|
+
currentToast.classList.add("remarq-toast-fade");
|
|
1791
|
+
setTimeout(() => hideToast(), 300);
|
|
1792
|
+
}
|
|
1793
|
+
}, duration);
|
|
1794
|
+
}
|
|
1795
|
+
function hideToast() {
|
|
1796
|
+
if (currentTimer) {
|
|
1797
|
+
clearTimeout(currentTimer);
|
|
1798
|
+
currentTimer = null;
|
|
1799
|
+
}
|
|
1800
|
+
if (currentToast) {
|
|
1801
|
+
currentToast.remove();
|
|
1802
|
+
currentToast = null;
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1664
1806
|
// src/ui/detached-panel.ts
|
|
1665
1807
|
var DetachedPanel = class {
|
|
1666
1808
|
constructor(container, onDelete) {
|
|
1667
1809
|
this.container = container;
|
|
1668
1810
|
this.onDelete = onDelete;
|
|
1669
1811
|
this.panelEl = null;
|
|
1670
|
-
this.toastEl = null;
|
|
1671
|
-
this.toastTimer = null;
|
|
1672
1812
|
}
|
|
1673
1813
|
update(otherBreakpoint, detached) {
|
|
1674
1814
|
this.remove();
|
|
@@ -1686,7 +1826,7 @@ var DetachedPanel = class {
|
|
|
1686
1826
|
}
|
|
1687
1827
|
destroy() {
|
|
1688
1828
|
this.remove();
|
|
1689
|
-
|
|
1829
|
+
hideToast();
|
|
1690
1830
|
}
|
|
1691
1831
|
renderSection(panel, title, annotations, type) {
|
|
1692
1832
|
const header = document.createElement("div");
|
|
@@ -1715,7 +1855,7 @@ var DetachedPanel = class {
|
|
|
1715
1855
|
if (type === "other") {
|
|
1716
1856
|
item.style.cursor = "pointer";
|
|
1717
1857
|
item.addEventListener("click", () => {
|
|
1718
|
-
this.
|
|
1858
|
+
showToast(this.container, `Annotation created at ${ann.viewportBucket}px width. Resize viewport to view.`);
|
|
1719
1859
|
});
|
|
1720
1860
|
} else {
|
|
1721
1861
|
const deleteBtn = document.createElement("button");
|
|
@@ -1730,30 +1870,6 @@ var DetachedPanel = class {
|
|
|
1730
1870
|
panel.appendChild(item);
|
|
1731
1871
|
}
|
|
1732
1872
|
}
|
|
1733
|
-
showToast(message) {
|
|
1734
|
-
this.hideToast();
|
|
1735
|
-
const toast = document.createElement("div");
|
|
1736
|
-
toast.className = "remarq-toast";
|
|
1737
|
-
toast.textContent = message;
|
|
1738
|
-
this.container.appendChild(toast);
|
|
1739
|
-
this.toastEl = toast;
|
|
1740
|
-
this.toastTimer = setTimeout(() => {
|
|
1741
|
-
if (this.toastEl) {
|
|
1742
|
-
this.toastEl.classList.add("remarq-toast-fade");
|
|
1743
|
-
setTimeout(() => this.hideToast(), 300);
|
|
1744
|
-
}
|
|
1745
|
-
}, 3e3);
|
|
1746
|
-
}
|
|
1747
|
-
hideToast() {
|
|
1748
|
-
if (this.toastTimer) {
|
|
1749
|
-
clearTimeout(this.toastTimer);
|
|
1750
|
-
this.toastTimer = null;
|
|
1751
|
-
}
|
|
1752
|
-
if (this.toastEl) {
|
|
1753
|
-
this.toastEl.remove();
|
|
1754
|
-
this.toastEl = null;
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
1873
|
remove() {
|
|
1758
1874
|
if (this.panelEl) {
|
|
1759
1875
|
this.panelEl.remove();
|
|
@@ -1826,6 +1942,7 @@ var spacingOverlay;
|
|
|
1826
1942
|
var mutationObserver = null;
|
|
1827
1943
|
var unsubRoute = null;
|
|
1828
1944
|
var refreshScheduled = false;
|
|
1945
|
+
var savedCursor = "";
|
|
1829
1946
|
var elementCache = /* @__PURE__ */ new Map();
|
|
1830
1947
|
function describeTarget(el) {
|
|
1831
1948
|
var _a, _b, _c, _d;
|
|
@@ -1946,6 +2063,7 @@ function handleInspectClick(e) {
|
|
|
1946
2063
|
cacheElement(ann.id, target);
|
|
1947
2064
|
storage.add(ann);
|
|
1948
2065
|
refreshMarkers();
|
|
2066
|
+
showToast(themeManager.container, "Annotation added");
|
|
1949
2067
|
},
|
|
1950
2068
|
() => {
|
|
1951
2069
|
}
|
|
@@ -1978,8 +2096,22 @@ function handleInspectKeydown(e) {
|
|
|
1978
2096
|
toolbar.setSpacingActive(spacingMode);
|
|
1979
2097
|
if (!spacingMode) spacingOverlay.hide();
|
|
1980
2098
|
}
|
|
2099
|
+
if (e.key === "i") {
|
|
2100
|
+
setInspecting(!inspecting);
|
|
2101
|
+
if (!inspecting) {
|
|
2102
|
+
overlay.hide();
|
|
2103
|
+
spacingOverlay.hide();
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
1981
2106
|
}
|
|
1982
2107
|
function setInspecting(value) {
|
|
2108
|
+
if (value && !inspecting) {
|
|
2109
|
+
savedCursor = document.body.style.cursor;
|
|
2110
|
+
document.body.style.cursor = "crosshair";
|
|
2111
|
+
}
|
|
2112
|
+
if (!value && inspecting) {
|
|
2113
|
+
document.body.style.cursor = savedCursor;
|
|
2114
|
+
}
|
|
1983
2115
|
inspecting = value;
|
|
1984
2116
|
toolbar.setInspectActive(value);
|
|
1985
2117
|
toolbar.setSpacingEnabled(value);
|
|
@@ -2020,6 +2152,10 @@ function handleMarkerClick(annotationId) {
|
|
|
2020
2152
|
refreshMarkers();
|
|
2021
2153
|
},
|
|
2022
2154
|
onClose: () => {
|
|
2155
|
+
},
|
|
2156
|
+
onEdit: (newComment) => {
|
|
2157
|
+
storage.update(ann.id, { comment: newComment });
|
|
2158
|
+
refreshMarkers();
|
|
2023
2159
|
}
|
|
2024
2160
|
}
|
|
2025
2161
|
);
|
|
@@ -2038,6 +2174,13 @@ function generateMarkdown() {
|
|
|
2038
2174
|
lines.push(elDesc);
|
|
2039
2175
|
lines.push(`Viewport: ${ann.viewportBucket}px`);
|
|
2040
2176
|
lines.push("");
|
|
2177
|
+
if (fp.sourceLocation) {
|
|
2178
|
+
lines.push(`Source: \`${fp.sourceLocation}\`${fp.componentName ? ` (${fp.componentName})` : ""}`);
|
|
2179
|
+
lines.push("");
|
|
2180
|
+
} else if (fp.detectedSource) {
|
|
2181
|
+
lines.push(`Source (detected): \`${fp.detectedSource}\`${fp.detectedComponent ? ` (${fp.detectedComponent})` : ""}`);
|
|
2182
|
+
lines.push("");
|
|
2183
|
+
}
|
|
2041
2184
|
lines.push("Search hints:");
|
|
2042
2185
|
if (fp.dataAnnotate) {
|
|
2043
2186
|
lines.push(`- \`data-annotate="${fp.dataAnnotate}"\` \u2014 in template files`);
|
|
@@ -2084,16 +2227,20 @@ function exportMarkdown() {
|
|
|
2084
2227
|
const md = generateMarkdown();
|
|
2085
2228
|
if (!md) return;
|
|
2086
2229
|
downloadFile(md, `remarq-annotations-${Date.now()}.md`, "text/markdown");
|
|
2230
|
+
showToast(themeManager.container, "Exported as Markdown");
|
|
2087
2231
|
}
|
|
2088
2232
|
function exportJSON() {
|
|
2089
2233
|
const data = storage.exportJSON();
|
|
2090
2234
|
const json = JSON.stringify(data, null, 2);
|
|
2091
2235
|
downloadFile(json, `remarq-annotations-${Date.now()}.json`, "application/json");
|
|
2236
|
+
showToast(themeManager.container, "Exported as JSON");
|
|
2092
2237
|
}
|
|
2093
2238
|
function copyToClipboard() {
|
|
2094
2239
|
const md = generateMarkdown();
|
|
2095
2240
|
if (!md) return;
|
|
2096
|
-
navigator.clipboard.writeText(md).
|
|
2241
|
+
navigator.clipboard.writeText(md).then(() => {
|
|
2242
|
+
showToast(themeManager.container, "Copied to clipboard");
|
|
2243
|
+
}).catch(() => {
|
|
2097
2244
|
console.warn("[web-remarq] Clipboard write failed");
|
|
2098
2245
|
});
|
|
2099
2246
|
}
|
|
@@ -2166,6 +2313,7 @@ var WebRemarq = {
|
|
|
2166
2313
|
elementCache.clear();
|
|
2167
2314
|
storage.clearAll();
|
|
2168
2315
|
refreshMarkers();
|
|
2316
|
+
showToast(themeManager.container, "All annotations cleared");
|
|
2169
2317
|
},
|
|
2170
2318
|
onThemeToggle: () => themeManager.toggle()
|
|
2171
2319
|
});
|
|
@@ -2194,6 +2342,10 @@ var WebRemarq = {
|
|
|
2194
2342
|
document.removeEventListener("keydown", handleInspectKeydown);
|
|
2195
2343
|
mutationObserver == null ? void 0 : mutationObserver.disconnect();
|
|
2196
2344
|
mutationObserver = null;
|
|
2345
|
+
if (inspecting) {
|
|
2346
|
+
document.body.style.cursor = savedCursor;
|
|
2347
|
+
}
|
|
2348
|
+
hideToast();
|
|
2197
2349
|
destroyViewportListener();
|
|
2198
2350
|
unsubRoute == null ? void 0 : unsubRoute();
|
|
2199
2351
|
routeObserver == null ? void 0 : routeObserver.destroy();
|