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.cjs
CHANGED
|
@@ -936,6 +936,12 @@ var CSS = `
|
|
|
936
936
|
|
|
937
937
|
.remarq-toolbar-btn:disabled { opacity: 0.3; cursor: default; }
|
|
938
938
|
.remarq-toolbar-btn:disabled:hover { background: transparent; }
|
|
939
|
+
|
|
940
|
+
.remarq-popup-hint {
|
|
941
|
+
font-size: 11px;
|
|
942
|
+
color: var(--remarq-text-secondary);
|
|
943
|
+
margin-top: 4px;
|
|
944
|
+
}
|
|
939
945
|
`;
|
|
940
946
|
function injectStyles() {
|
|
941
947
|
if (document.querySelector(`style[${STYLES_ID}]`)) return;
|
|
@@ -1166,15 +1172,13 @@ var Overlay = class {
|
|
|
1166
1172
|
this.overlayEl.style.height = `${rect.height}px`;
|
|
1167
1173
|
this.tooltipEl.textContent = describeElement(target);
|
|
1168
1174
|
this.tooltipEl.style.display = "block";
|
|
1169
|
-
this.
|
|
1170
|
-
this.tooltipEl.style.left = `${rect.left}px`;
|
|
1175
|
+
this.positionTooltip(rect.left, rect.top - 28);
|
|
1171
1176
|
} catch (e) {
|
|
1172
1177
|
this.hide();
|
|
1173
1178
|
}
|
|
1174
1179
|
}
|
|
1175
1180
|
updateTooltipPosition(x, y) {
|
|
1176
|
-
this.
|
|
1177
|
-
this.tooltipEl.style.top = `${y - 28}px`;
|
|
1181
|
+
this.positionTooltip(x + 12, y - 28);
|
|
1178
1182
|
}
|
|
1179
1183
|
hideHighlight() {
|
|
1180
1184
|
this.overlayEl.style.display = "none";
|
|
@@ -1187,6 +1191,16 @@ var Overlay = class {
|
|
|
1187
1191
|
this.overlayEl.remove();
|
|
1188
1192
|
this.tooltipEl.remove();
|
|
1189
1193
|
}
|
|
1194
|
+
positionTooltip(left, top) {
|
|
1195
|
+
this.tooltipEl.style.left = "0px";
|
|
1196
|
+
this.tooltipEl.style.top = "0px";
|
|
1197
|
+
const tooltipWidth = this.tooltipEl.offsetWidth;
|
|
1198
|
+
const tooltipHeight = this.tooltipEl.offsetHeight;
|
|
1199
|
+
const maxLeft = window.innerWidth - tooltipWidth - 8;
|
|
1200
|
+
const maxTop = window.innerHeight - tooltipHeight - 8;
|
|
1201
|
+
this.tooltipEl.style.left = `${Math.max(8, Math.min(left, maxLeft))}px`;
|
|
1202
|
+
this.tooltipEl.style.top = `${Math.max(8, Math.min(top, maxTop))}px`;
|
|
1203
|
+
}
|
|
1190
1204
|
};
|
|
1191
1205
|
function describeElement(el) {
|
|
1192
1206
|
const tag = el.tagName.toLowerCase();
|
|
@@ -1466,6 +1480,7 @@ var Popup = class {
|
|
|
1466
1480
|
this.container = container;
|
|
1467
1481
|
this.popupEl = null;
|
|
1468
1482
|
this.keyHandler = null;
|
|
1483
|
+
this.outsideClickHandler = null;
|
|
1469
1484
|
}
|
|
1470
1485
|
show(info, position, onSubmit, onCancel) {
|
|
1471
1486
|
this.hide();
|
|
@@ -1478,7 +1493,11 @@ var Popup = class {
|
|
|
1478
1493
|
body.className = "remarq-popup-body";
|
|
1479
1494
|
const textarea = document.createElement("textarea");
|
|
1480
1495
|
textarea.placeholder = "Add your comment...";
|
|
1496
|
+
const hint = document.createElement("div");
|
|
1497
|
+
hint.className = "remarq-popup-hint";
|
|
1498
|
+
hint.textContent = "Enter to submit \xB7 Shift+Enter for new line";
|
|
1481
1499
|
body.appendChild(textarea);
|
|
1500
|
+
body.appendChild(hint);
|
|
1482
1501
|
const actions = document.createElement("div");
|
|
1483
1502
|
actions.className = "remarq-popup-actions";
|
|
1484
1503
|
const cancelBtn = document.createElement("button");
|
|
@@ -1508,18 +1527,37 @@ var Popup = class {
|
|
|
1508
1527
|
textarea.focus();
|
|
1509
1528
|
});
|
|
1510
1529
|
this.keyHandler = (e) => {
|
|
1511
|
-
if (e.key === "
|
|
1530
|
+
if (e.key === "Escape") {
|
|
1531
|
+
this.hide();
|
|
1532
|
+
onCancel();
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
if (e.key === "Enter" && !e.shiftKey && e.target === textarea) {
|
|
1536
|
+
e.preventDefault();
|
|
1512
1537
|
const comment = textarea.value.trim();
|
|
1513
1538
|
if (!comment) return;
|
|
1514
1539
|
this.hide();
|
|
1515
1540
|
onSubmit(comment);
|
|
1541
|
+
return;
|
|
1516
1542
|
}
|
|
1517
|
-
if (e.key === "
|
|
1543
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
1544
|
+
const comment = textarea.value.trim();
|
|
1545
|
+
if (!comment) return;
|
|
1518
1546
|
this.hide();
|
|
1519
|
-
|
|
1547
|
+
onSubmit(comment);
|
|
1520
1548
|
}
|
|
1521
1549
|
};
|
|
1522
1550
|
document.addEventListener("keydown", this.keyHandler);
|
|
1551
|
+
setTimeout(() => {
|
|
1552
|
+
this.outsideClickHandler = (e) => {
|
|
1553
|
+
const target = e.target;
|
|
1554
|
+
if (target && !target.closest(".remarq-popup")) {
|
|
1555
|
+
this.hide();
|
|
1556
|
+
onCancel();
|
|
1557
|
+
}
|
|
1558
|
+
};
|
|
1559
|
+
document.addEventListener("mousedown", this.outsideClickHandler);
|
|
1560
|
+
}, 0);
|
|
1523
1561
|
}
|
|
1524
1562
|
showDetail(info, position, callbacks) {
|
|
1525
1563
|
this.hide();
|
|
@@ -1530,7 +1568,15 @@ var Popup = class {
|
|
|
1530
1568
|
header.textContent = `<${info.tag}>${info.text ? ` "${info.text}"` : ""} [${info.status}]`;
|
|
1531
1569
|
const body = document.createElement("div");
|
|
1532
1570
|
body.className = "remarq-popup-body";
|
|
1533
|
-
|
|
1571
|
+
const makeCommentEl = () => {
|
|
1572
|
+
const el = document.createElement("div");
|
|
1573
|
+
el.textContent = info.comment;
|
|
1574
|
+
el.style.cursor = "pointer";
|
|
1575
|
+
el.title = "Click to edit";
|
|
1576
|
+
el.addEventListener("click", () => this.enterEditMode(el, info, callbacks));
|
|
1577
|
+
return el;
|
|
1578
|
+
};
|
|
1579
|
+
body.appendChild(makeCommentEl());
|
|
1534
1580
|
const actions = document.createElement("div");
|
|
1535
1581
|
actions.className = "remarq-popup-actions";
|
|
1536
1582
|
if (info.status === "pending") {
|
|
@@ -1572,6 +1618,16 @@ var Popup = class {
|
|
|
1572
1618
|
}
|
|
1573
1619
|
};
|
|
1574
1620
|
document.addEventListener("keydown", this.keyHandler);
|
|
1621
|
+
setTimeout(() => {
|
|
1622
|
+
this.outsideClickHandler = (e) => {
|
|
1623
|
+
const target = e.target;
|
|
1624
|
+
if (target && !target.closest(".remarq-popup")) {
|
|
1625
|
+
this.hide();
|
|
1626
|
+
callbacks.onClose();
|
|
1627
|
+
}
|
|
1628
|
+
};
|
|
1629
|
+
document.addEventListener("mousedown", this.outsideClickHandler);
|
|
1630
|
+
}, 0);
|
|
1575
1631
|
}
|
|
1576
1632
|
hide() {
|
|
1577
1633
|
if (this.popupEl) {
|
|
@@ -1582,10 +1638,68 @@ var Popup = class {
|
|
|
1582
1638
|
document.removeEventListener("keydown", this.keyHandler);
|
|
1583
1639
|
this.keyHandler = null;
|
|
1584
1640
|
}
|
|
1641
|
+
if (this.outsideClickHandler) {
|
|
1642
|
+
document.removeEventListener("mousedown", this.outsideClickHandler);
|
|
1643
|
+
this.outsideClickHandler = null;
|
|
1644
|
+
}
|
|
1585
1645
|
}
|
|
1586
1646
|
destroy() {
|
|
1587
1647
|
this.hide();
|
|
1588
1648
|
}
|
|
1649
|
+
enterEditMode(commentEl, info, callbacks) {
|
|
1650
|
+
const textarea = document.createElement("textarea");
|
|
1651
|
+
textarea.value = info.comment;
|
|
1652
|
+
textarea.className = "remarq-popup-edit-textarea";
|
|
1653
|
+
textarea.style.width = "100%";
|
|
1654
|
+
textarea.style.minHeight = "60px";
|
|
1655
|
+
textarea.style.padding = "8px";
|
|
1656
|
+
textarea.style.border = "1px solid var(--remarq-border)";
|
|
1657
|
+
textarea.style.borderRadius = "4px";
|
|
1658
|
+
textarea.style.background = "var(--remarq-bg-secondary)";
|
|
1659
|
+
textarea.style.color = "var(--remarq-text)";
|
|
1660
|
+
textarea.style.fontFamily = "inherit";
|
|
1661
|
+
textarea.style.fontSize = "13px";
|
|
1662
|
+
textarea.style.resize = "vertical";
|
|
1663
|
+
textarea.style.boxSizing = "border-box";
|
|
1664
|
+
commentEl.replaceWith(textarea);
|
|
1665
|
+
textarea.focus();
|
|
1666
|
+
textarea.selectionStart = textarea.value.length;
|
|
1667
|
+
const saveEdit = () => {
|
|
1668
|
+
const newComment = textarea.value.trim();
|
|
1669
|
+
if (newComment && newComment !== info.comment) {
|
|
1670
|
+
info.comment = newComment;
|
|
1671
|
+
callbacks.onEdit(newComment);
|
|
1672
|
+
}
|
|
1673
|
+
const restored = document.createElement("div");
|
|
1674
|
+
restored.textContent = info.comment;
|
|
1675
|
+
restored.style.cursor = "pointer";
|
|
1676
|
+
restored.title = "Click to edit";
|
|
1677
|
+
restored.addEventListener("click", () => this.enterEditMode(restored, info, callbacks));
|
|
1678
|
+
textarea.replaceWith(restored);
|
|
1679
|
+
};
|
|
1680
|
+
textarea.addEventListener("keydown", (e) => {
|
|
1681
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
1682
|
+
e.preventDefault();
|
|
1683
|
+
saveEdit();
|
|
1684
|
+
}
|
|
1685
|
+
if (e.key === "Escape") {
|
|
1686
|
+
e.stopPropagation();
|
|
1687
|
+
const restored = document.createElement("div");
|
|
1688
|
+
restored.textContent = info.comment;
|
|
1689
|
+
restored.style.cursor = "pointer";
|
|
1690
|
+
restored.title = "Click to edit";
|
|
1691
|
+
restored.addEventListener("click", () => this.enterEditMode(restored, info, callbacks));
|
|
1692
|
+
textarea.replaceWith(restored);
|
|
1693
|
+
}
|
|
1694
|
+
});
|
|
1695
|
+
textarea.addEventListener("blur", () => {
|
|
1696
|
+
setTimeout(() => {
|
|
1697
|
+
if (textarea.isConnected) {
|
|
1698
|
+
saveEdit();
|
|
1699
|
+
}
|
|
1700
|
+
}, 50);
|
|
1701
|
+
});
|
|
1702
|
+
}
|
|
1589
1703
|
adjustPosition(popup2, position) {
|
|
1590
1704
|
const popupHeight = popup2.offsetHeight;
|
|
1591
1705
|
const viewportBottom = window.scrollY + window.innerHeight;
|
|
@@ -1684,14 +1798,40 @@ var MarkerManager = class {
|
|
|
1684
1798
|
}
|
|
1685
1799
|
};
|
|
1686
1800
|
|
|
1801
|
+
// src/ui/toast.ts
|
|
1802
|
+
var currentToast = null;
|
|
1803
|
+
var currentTimer = null;
|
|
1804
|
+
function showToast(container, message, duration = 3e3) {
|
|
1805
|
+
hideToast();
|
|
1806
|
+
const toast = document.createElement("div");
|
|
1807
|
+
toast.className = "remarq-toast";
|
|
1808
|
+
toast.textContent = message;
|
|
1809
|
+
container.appendChild(toast);
|
|
1810
|
+
currentToast = toast;
|
|
1811
|
+
currentTimer = setTimeout(() => {
|
|
1812
|
+
if (currentToast) {
|
|
1813
|
+
currentToast.classList.add("remarq-toast-fade");
|
|
1814
|
+
setTimeout(() => hideToast(), 300);
|
|
1815
|
+
}
|
|
1816
|
+
}, duration);
|
|
1817
|
+
}
|
|
1818
|
+
function hideToast() {
|
|
1819
|
+
if (currentTimer) {
|
|
1820
|
+
clearTimeout(currentTimer);
|
|
1821
|
+
currentTimer = null;
|
|
1822
|
+
}
|
|
1823
|
+
if (currentToast) {
|
|
1824
|
+
currentToast.remove();
|
|
1825
|
+
currentToast = null;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1687
1829
|
// src/ui/detached-panel.ts
|
|
1688
1830
|
var DetachedPanel = class {
|
|
1689
1831
|
constructor(container, onDelete) {
|
|
1690
1832
|
this.container = container;
|
|
1691
1833
|
this.onDelete = onDelete;
|
|
1692
1834
|
this.panelEl = null;
|
|
1693
|
-
this.toastEl = null;
|
|
1694
|
-
this.toastTimer = null;
|
|
1695
1835
|
}
|
|
1696
1836
|
update(otherBreakpoint, detached) {
|
|
1697
1837
|
this.remove();
|
|
@@ -1709,7 +1849,7 @@ var DetachedPanel = class {
|
|
|
1709
1849
|
}
|
|
1710
1850
|
destroy() {
|
|
1711
1851
|
this.remove();
|
|
1712
|
-
|
|
1852
|
+
hideToast();
|
|
1713
1853
|
}
|
|
1714
1854
|
renderSection(panel, title, annotations, type) {
|
|
1715
1855
|
const header = document.createElement("div");
|
|
@@ -1738,7 +1878,7 @@ var DetachedPanel = class {
|
|
|
1738
1878
|
if (type === "other") {
|
|
1739
1879
|
item.style.cursor = "pointer";
|
|
1740
1880
|
item.addEventListener("click", () => {
|
|
1741
|
-
this.
|
|
1881
|
+
showToast(this.container, `Annotation created at ${ann.viewportBucket}px width. Resize viewport to view.`);
|
|
1742
1882
|
});
|
|
1743
1883
|
} else {
|
|
1744
1884
|
const deleteBtn = document.createElement("button");
|
|
@@ -1753,30 +1893,6 @@ var DetachedPanel = class {
|
|
|
1753
1893
|
panel.appendChild(item);
|
|
1754
1894
|
}
|
|
1755
1895
|
}
|
|
1756
|
-
showToast(message) {
|
|
1757
|
-
this.hideToast();
|
|
1758
|
-
const toast = document.createElement("div");
|
|
1759
|
-
toast.className = "remarq-toast";
|
|
1760
|
-
toast.textContent = message;
|
|
1761
|
-
this.container.appendChild(toast);
|
|
1762
|
-
this.toastEl = toast;
|
|
1763
|
-
this.toastTimer = setTimeout(() => {
|
|
1764
|
-
if (this.toastEl) {
|
|
1765
|
-
this.toastEl.classList.add("remarq-toast-fade");
|
|
1766
|
-
setTimeout(() => this.hideToast(), 300);
|
|
1767
|
-
}
|
|
1768
|
-
}, 3e3);
|
|
1769
|
-
}
|
|
1770
|
-
hideToast() {
|
|
1771
|
-
if (this.toastTimer) {
|
|
1772
|
-
clearTimeout(this.toastTimer);
|
|
1773
|
-
this.toastTimer = null;
|
|
1774
|
-
}
|
|
1775
|
-
if (this.toastEl) {
|
|
1776
|
-
this.toastEl.remove();
|
|
1777
|
-
this.toastEl = null;
|
|
1778
|
-
}
|
|
1779
|
-
}
|
|
1780
1896
|
remove() {
|
|
1781
1897
|
if (this.panelEl) {
|
|
1782
1898
|
this.panelEl.remove();
|
|
@@ -1849,6 +1965,7 @@ var spacingOverlay;
|
|
|
1849
1965
|
var mutationObserver = null;
|
|
1850
1966
|
var unsubRoute = null;
|
|
1851
1967
|
var refreshScheduled = false;
|
|
1968
|
+
var savedCursor = "";
|
|
1852
1969
|
var elementCache = /* @__PURE__ */ new Map();
|
|
1853
1970
|
function describeTarget(el) {
|
|
1854
1971
|
var _a, _b, _c, _d;
|
|
@@ -1969,6 +2086,7 @@ function handleInspectClick(e) {
|
|
|
1969
2086
|
cacheElement(ann.id, target);
|
|
1970
2087
|
storage.add(ann);
|
|
1971
2088
|
refreshMarkers();
|
|
2089
|
+
showToast(themeManager.container, "Annotation added");
|
|
1972
2090
|
},
|
|
1973
2091
|
() => {
|
|
1974
2092
|
}
|
|
@@ -2001,8 +2119,22 @@ function handleInspectKeydown(e) {
|
|
|
2001
2119
|
toolbar.setSpacingActive(spacingMode);
|
|
2002
2120
|
if (!spacingMode) spacingOverlay.hide();
|
|
2003
2121
|
}
|
|
2122
|
+
if (e.key === "i") {
|
|
2123
|
+
setInspecting(!inspecting);
|
|
2124
|
+
if (!inspecting) {
|
|
2125
|
+
overlay.hide();
|
|
2126
|
+
spacingOverlay.hide();
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2004
2129
|
}
|
|
2005
2130
|
function setInspecting(value) {
|
|
2131
|
+
if (value && !inspecting) {
|
|
2132
|
+
savedCursor = document.body.style.cursor;
|
|
2133
|
+
document.body.style.cursor = "crosshair";
|
|
2134
|
+
}
|
|
2135
|
+
if (!value && inspecting) {
|
|
2136
|
+
document.body.style.cursor = savedCursor;
|
|
2137
|
+
}
|
|
2006
2138
|
inspecting = value;
|
|
2007
2139
|
toolbar.setInspectActive(value);
|
|
2008
2140
|
toolbar.setSpacingEnabled(value);
|
|
@@ -2043,6 +2175,10 @@ function handleMarkerClick(annotationId) {
|
|
|
2043
2175
|
refreshMarkers();
|
|
2044
2176
|
},
|
|
2045
2177
|
onClose: () => {
|
|
2178
|
+
},
|
|
2179
|
+
onEdit: (newComment) => {
|
|
2180
|
+
storage.update(ann.id, { comment: newComment });
|
|
2181
|
+
refreshMarkers();
|
|
2046
2182
|
}
|
|
2047
2183
|
}
|
|
2048
2184
|
);
|
|
@@ -2061,6 +2197,13 @@ function generateMarkdown() {
|
|
|
2061
2197
|
lines.push(elDesc);
|
|
2062
2198
|
lines.push(`Viewport: ${ann.viewportBucket}px`);
|
|
2063
2199
|
lines.push("");
|
|
2200
|
+
if (fp.sourceLocation) {
|
|
2201
|
+
lines.push(`Source: \`${fp.sourceLocation}\`${fp.componentName ? ` (${fp.componentName})` : ""}`);
|
|
2202
|
+
lines.push("");
|
|
2203
|
+
} else if (fp.detectedSource) {
|
|
2204
|
+
lines.push(`Source (detected): \`${fp.detectedSource}\`${fp.detectedComponent ? ` (${fp.detectedComponent})` : ""}`);
|
|
2205
|
+
lines.push("");
|
|
2206
|
+
}
|
|
2064
2207
|
lines.push("Search hints:");
|
|
2065
2208
|
if (fp.dataAnnotate) {
|
|
2066
2209
|
lines.push(`- \`data-annotate="${fp.dataAnnotate}"\` \u2014 in template files`);
|
|
@@ -2107,16 +2250,20 @@ function exportMarkdown() {
|
|
|
2107
2250
|
const md = generateMarkdown();
|
|
2108
2251
|
if (!md) return;
|
|
2109
2252
|
downloadFile(md, `remarq-annotations-${Date.now()}.md`, "text/markdown");
|
|
2253
|
+
showToast(themeManager.container, "Exported as Markdown");
|
|
2110
2254
|
}
|
|
2111
2255
|
function exportJSON() {
|
|
2112
2256
|
const data = storage.exportJSON();
|
|
2113
2257
|
const json = JSON.stringify(data, null, 2);
|
|
2114
2258
|
downloadFile(json, `remarq-annotations-${Date.now()}.json`, "application/json");
|
|
2259
|
+
showToast(themeManager.container, "Exported as JSON");
|
|
2115
2260
|
}
|
|
2116
2261
|
function copyToClipboard() {
|
|
2117
2262
|
const md = generateMarkdown();
|
|
2118
2263
|
if (!md) return;
|
|
2119
|
-
navigator.clipboard.writeText(md).
|
|
2264
|
+
navigator.clipboard.writeText(md).then(() => {
|
|
2265
|
+
showToast(themeManager.container, "Copied to clipboard");
|
|
2266
|
+
}).catch(() => {
|
|
2120
2267
|
console.warn("[web-remarq] Clipboard write failed");
|
|
2121
2268
|
});
|
|
2122
2269
|
}
|
|
@@ -2189,6 +2336,7 @@ var WebRemarq = {
|
|
|
2189
2336
|
elementCache.clear();
|
|
2190
2337
|
storage.clearAll();
|
|
2191
2338
|
refreshMarkers();
|
|
2339
|
+
showToast(themeManager.container, "All annotations cleared");
|
|
2192
2340
|
},
|
|
2193
2341
|
onThemeToggle: () => themeManager.toggle()
|
|
2194
2342
|
});
|
|
@@ -2217,6 +2365,10 @@ var WebRemarq = {
|
|
|
2217
2365
|
document.removeEventListener("keydown", handleInspectKeydown);
|
|
2218
2366
|
mutationObserver == null ? void 0 : mutationObserver.disconnect();
|
|
2219
2367
|
mutationObserver = null;
|
|
2368
|
+
if (inspecting) {
|
|
2369
|
+
document.body.style.cursor = savedCursor;
|
|
2370
|
+
}
|
|
2371
|
+
hideToast();
|
|
2220
2372
|
destroyViewportListener();
|
|
2221
2373
|
unsubRoute == null ? void 0 : unsubRoute();
|
|
2222
2374
|
routeObserver == null ? void 0 : routeObserver.destroy();
|