instruckt 0.4.8 → 0.4.13
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/README.md +3 -1
- package/dist/instruckt.cjs.js +63 -15
- package/dist/instruckt.cjs.js.map +1 -1
- package/dist/instruckt.d.mts +5 -0
- package/dist/instruckt.d.ts +5 -0
- package/dist/instruckt.esm.js +63 -15
- package/dist/instruckt.esm.js.map +1 -1
- package/dist/instruckt.iife.js +28 -10
- package/dist/instruckt.iife.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,10 +41,12 @@ Or with the IIFE build:
|
|
|
41
41
|
2. Press **A** or click the annotate button to enter annotation mode
|
|
42
42
|
3. Hover over any element — instruckt highlights it and detects its framework component
|
|
43
43
|
4. Click to annotate — type your feedback and save
|
|
44
|
-
5. Annotations auto-copy as structured markdown to your clipboard
|
|
44
|
+
5. Annotations auto-copy as structured markdown to your clipboard (requires secure context — `https://` or `localhost`)
|
|
45
45
|
6. Paste into any AI coding agent (Claude Code, Cursor, Codex, Copilot, OpenCode, etc.)
|
|
46
46
|
7. The agent reads the markdown and makes the requested code changes
|
|
47
47
|
|
|
48
|
+
> **Note:** Auto-copy requires a secure context (`https://` or `localhost`). On `http://` domains (e.g. `.test`), use the copy button in the toolbar instead.
|
|
49
|
+
|
|
48
50
|
### Example Output
|
|
49
51
|
|
|
50
52
|
```markdown
|
package/dist/instruckt.cjs.js
CHANGED
|
@@ -50,7 +50,8 @@ function getCsrfToken() {
|
|
|
50
50
|
function headers() {
|
|
51
51
|
const h = {
|
|
52
52
|
"Content-Type": "application/json",
|
|
53
|
-
Accept: "application/json"
|
|
53
|
+
Accept: "application/json",
|
|
54
|
+
"X-Requested-With": "XMLHttpRequest"
|
|
54
55
|
};
|
|
55
56
|
const csrf = getCsrfToken();
|
|
56
57
|
if (csrf) h["X-XSRF-TOKEN"] = csrf;
|
|
@@ -225,6 +226,24 @@ var TOOLBAR_CSS = (
|
|
|
225
226
|
box-shadow: var(--ik-shadow);
|
|
226
227
|
border-radius: 8px;
|
|
227
228
|
}
|
|
229
|
+
/* Instant tooltip */
|
|
230
|
+
.clear-all-btn::before {
|
|
231
|
+
content: attr(data-tooltip);
|
|
232
|
+
position: absolute;
|
|
233
|
+
right: calc(100% + 6px);
|
|
234
|
+
top: 50%;
|
|
235
|
+
transform: translateY(-50%);
|
|
236
|
+
white-space: nowrap;
|
|
237
|
+
font-size: 11px;
|
|
238
|
+
padding: 4px 8px;
|
|
239
|
+
border-radius: 6px;
|
|
240
|
+
background: var(--ik-text);
|
|
241
|
+
color: var(--ik-bg);
|
|
242
|
+
pointer-events: none;
|
|
243
|
+
opacity: 0;
|
|
244
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
245
|
+
}
|
|
246
|
+
.clear-all-btn:hover::before { opacity: 1; }
|
|
228
247
|
/* Invisible bridge so hover doesn't break crossing the gap */
|
|
229
248
|
.clear-all-btn::after {
|
|
230
249
|
content: '';
|
|
@@ -511,13 +530,15 @@ var Toolbar = class {
|
|
|
511
530
|
clearBtn.classList.add("danger-btn");
|
|
512
531
|
const clearAllBtn = this.makeBtn(
|
|
513
532
|
`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2"/><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"/></svg>`,
|
|
514
|
-
"
|
|
533
|
+
"Delete all instructions.",
|
|
515
534
|
() => {
|
|
516
535
|
var _a2, _b;
|
|
517
536
|
return (_b = (_a2 = this.callbacks).onClearAll) == null ? void 0 : _b.call(_a2);
|
|
518
537
|
}
|
|
519
538
|
);
|
|
520
539
|
clearAllBtn.classList.add("danger-btn", "clear-all-btn");
|
|
540
|
+
clearAllBtn.removeAttribute("title");
|
|
541
|
+
clearAllBtn.setAttribute("data-tooltip", "Delete all instructions.");
|
|
521
542
|
clearWrap.appendChild(clearBtn);
|
|
522
543
|
clearWrap.appendChild(clearAllBtn);
|
|
523
544
|
const minimizeBtn = this.makeBtn(ICONS.minimize, "Minimize toolbar", () => {
|
|
@@ -760,6 +781,7 @@ var AnnotationPopup = class {
|
|
|
760
781
|
submitBtn.disabled = textarea.value.trim().length === 0;
|
|
761
782
|
});
|
|
762
783
|
textarea.addEventListener("keydown", (e) => {
|
|
784
|
+
e.stopPropagation();
|
|
763
785
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
764
786
|
e.preventDefault();
|
|
765
787
|
if (!submitBtn.disabled) submitBtn.click();
|
|
@@ -820,6 +842,7 @@ var AnnotationPopup = class {
|
|
|
820
842
|
const saveBtn = popup.querySelector('[data-action="save"]');
|
|
821
843
|
const deleteBtn = popup.querySelector('[data-action="delete"]');
|
|
822
844
|
textarea.addEventListener("keydown", (e) => {
|
|
845
|
+
e.stopPropagation();
|
|
823
846
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
824
847
|
e.preventDefault();
|
|
825
848
|
saveBtn.click();
|
|
@@ -846,9 +869,9 @@ var AnnotationPopup = class {
|
|
|
846
869
|
textarea.setSelectionRange(textarea.value.length, textarea.value.length);
|
|
847
870
|
}
|
|
848
871
|
// ── Helpers ───────────────────────────────────────────────────
|
|
849
|
-
/** Prevent popup interactions from reaching page handlers (e.g. @click.outside) */
|
|
872
|
+
/** Prevent popup interactions from reaching page handlers (e.g. @click.outside, form submit) */
|
|
850
873
|
stopHostPropagation(host) {
|
|
851
|
-
for (const evt of ["click", "mousedown", "pointerdown"]) {
|
|
874
|
+
for (const evt of ["click", "mousedown", "pointerdown", "keydown", "keyup", "keypress", "submit"]) {
|
|
852
875
|
host.addEventListener(evt, (e) => e.stopPropagation());
|
|
853
876
|
}
|
|
854
877
|
}
|
|
@@ -1262,6 +1285,13 @@ var _Instruckt = class _Instruckt {
|
|
|
1262
1285
|
if (this.highlightLocked) return;
|
|
1263
1286
|
(_a = this.highlight) == null ? void 0 : _a.hide();
|
|
1264
1287
|
};
|
|
1288
|
+
/** Block mousedown/pointerdown in annotation mode so SPA frameworks can't navigate */
|
|
1289
|
+
this.boundAnnotateBlock = (e) => {
|
|
1290
|
+
if (this.isInstruckt(e.target)) return;
|
|
1291
|
+
e.preventDefault();
|
|
1292
|
+
e.stopPropagation();
|
|
1293
|
+
e.stopImmediatePropagation();
|
|
1294
|
+
};
|
|
1265
1295
|
this.boundClick = (e) => {
|
|
1266
1296
|
var _a, _b, _c, _d;
|
|
1267
1297
|
const target = e.target;
|
|
@@ -1327,7 +1357,7 @@ var _Instruckt = class _Instruckt {
|
|
|
1327
1357
|
onFreezeAnimations: (frozen) => {
|
|
1328
1358
|
this.setFrozen(frozen);
|
|
1329
1359
|
},
|
|
1330
|
-
onCopy: () => this.
|
|
1360
|
+
onCopy: () => this.copyToClipboard(true),
|
|
1331
1361
|
onClearPage: () => this.clearPage(),
|
|
1332
1362
|
onClearAll: () => this.clearEverything(),
|
|
1333
1363
|
onMinimize: (min) => this.onMinimize(min)
|
|
@@ -1339,6 +1369,7 @@ var _Instruckt = class _Instruckt {
|
|
|
1339
1369
|
window.addEventListener("scroll", this.boundReposition, { passive: true });
|
|
1340
1370
|
window.addEventListener("resize", this.boundReposition, { passive: true });
|
|
1341
1371
|
document.addEventListener("livewire:navigated", () => this.reattach());
|
|
1372
|
+
document.addEventListener("inertia:navigate", () => this.syncMarkers());
|
|
1342
1373
|
window.addEventListener("popstate", () => {
|
|
1343
1374
|
setTimeout(() => this.reattach(), 0);
|
|
1344
1375
|
});
|
|
@@ -1354,7 +1385,7 @@ var _Instruckt = class _Instruckt {
|
|
|
1354
1385
|
onFreezeAnimations: (frozen) => {
|
|
1355
1386
|
this.setFrozen(frozen);
|
|
1356
1387
|
},
|
|
1357
|
-
onCopy: () => this.
|
|
1388
|
+
onCopy: () => this.copyToClipboard(true),
|
|
1358
1389
|
onClearPage: () => this.clearPage(),
|
|
1359
1390
|
onClearAll: () => this.clearEverything(),
|
|
1360
1391
|
onMinimize: (min) => this.onMinimize(min)
|
|
@@ -1590,11 +1621,17 @@ var _Instruckt = class _Instruckt {
|
|
|
1590
1621
|
attachAnnotateListeners() {
|
|
1591
1622
|
document.addEventListener("mousemove", this.boundMouseMove);
|
|
1592
1623
|
document.addEventListener("mouseleave", this.boundMouseLeave);
|
|
1624
|
+
for (const evt of ["mousedown", "pointerdown"]) {
|
|
1625
|
+
window.addEventListener(evt, this.boundAnnotateBlock, true);
|
|
1626
|
+
}
|
|
1593
1627
|
window.addEventListener("click", this.boundClick, true);
|
|
1594
1628
|
}
|
|
1595
1629
|
detachAnnotateListeners() {
|
|
1596
1630
|
document.removeEventListener("mousemove", this.boundMouseMove);
|
|
1597
1631
|
document.removeEventListener("mouseleave", this.boundMouseLeave);
|
|
1632
|
+
for (const evt of ["mousedown", "pointerdown"]) {
|
|
1633
|
+
window.removeEventListener(evt, this.boundAnnotateBlock, true);
|
|
1634
|
+
}
|
|
1598
1635
|
window.removeEventListener("click", this.boundClick, true);
|
|
1599
1636
|
}
|
|
1600
1637
|
isInstruckt(el) {
|
|
@@ -1740,17 +1777,28 @@ var _Instruckt = class _Instruckt {
|
|
|
1740
1777
|
}
|
|
1741
1778
|
}
|
|
1742
1779
|
// ── Copy / export ─────────────────────────────────────────────
|
|
1780
|
+
/** Auto-copy on annotation submit — only in secure contexts to avoid focus side-effects */
|
|
1743
1781
|
copyAnnotations() {
|
|
1782
|
+
this.copyToClipboard(false);
|
|
1783
|
+
}
|
|
1784
|
+
/** Copy to clipboard. With fallback=true, uses execCommand for non-secure contexts (user-initiated only). */
|
|
1785
|
+
copyToClipboard(fallback) {
|
|
1744
1786
|
const md = this.exportMarkdown();
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1787
|
+
if (window.isSecureContext) {
|
|
1788
|
+
navigator.clipboard.writeText(md).catch(() => {
|
|
1789
|
+
});
|
|
1790
|
+
} else if (fallback) {
|
|
1791
|
+
try {
|
|
1792
|
+
const el = document.createElement("textarea");
|
|
1793
|
+
el.value = md;
|
|
1794
|
+
el.style.cssText = "position:fixed;left:-9999px";
|
|
1795
|
+
document.body.appendChild(el);
|
|
1796
|
+
el.select();
|
|
1797
|
+
document.execCommand("copy");
|
|
1798
|
+
el.remove();
|
|
1799
|
+
} catch (e) {
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1754
1802
|
}
|
|
1755
1803
|
exportMarkdown() {
|
|
1756
1804
|
const pending = this.annotations.filter((a) => a.status !== "resolved" && a.status !== "dismissed");
|