instruckt 0.4.4 → 0.4.9

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 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
@@ -225,6 +225,24 @@ var TOOLBAR_CSS = (
225
225
  box-shadow: var(--ik-shadow);
226
226
  border-radius: 8px;
227
227
  }
228
+ /* Instant tooltip */
229
+ .clear-all-btn::before {
230
+ content: attr(data-tooltip);
231
+ position: absolute;
232
+ right: calc(100% + 6px);
233
+ top: 50%;
234
+ transform: translateY(-50%);
235
+ white-space: nowrap;
236
+ font-size: 11px;
237
+ padding: 4px 8px;
238
+ border-radius: 6px;
239
+ background: var(--ik-text);
240
+ color: var(--ik-bg);
241
+ pointer-events: none;
242
+ opacity: 0;
243
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
244
+ }
245
+ .clear-all-btn:hover::before { opacity: 1; }
228
246
  /* Invisible bridge so hover doesn't break crossing the gap */
229
247
  .clear-all-btn::after {
230
248
  content: '';
@@ -511,13 +529,15 @@ var Toolbar = class {
511
529
  clearBtn.classList.add("danger-btn");
512
530
  const clearAllBtn = this.makeBtn(
513
531
  `<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
- "Clear ALL annotations across every page",
532
+ "Delete all instructions.",
515
533
  () => {
516
534
  var _a2, _b;
517
535
  return (_b = (_a2 = this.callbacks).onClearAll) == null ? void 0 : _b.call(_a2);
518
536
  }
519
537
  );
520
538
  clearAllBtn.classList.add("danger-btn", "clear-all-btn");
539
+ clearAllBtn.removeAttribute("title");
540
+ clearAllBtn.setAttribute("data-tooltip", "Delete all instructions.");
521
541
  clearWrap.appendChild(clearBtn);
522
542
  clearWrap.appendChild(clearAllBtn);
523
543
  const minimizeBtn = this.makeBtn(ICONS.minimize, "Minimize toolbar", () => {
@@ -760,6 +780,7 @@ var AnnotationPopup = class {
760
780
  submitBtn.disabled = textarea.value.trim().length === 0;
761
781
  });
762
782
  textarea.addEventListener("keydown", (e) => {
783
+ e.stopPropagation();
763
784
  if (e.key === "Enter" && !e.shiftKey) {
764
785
  e.preventDefault();
765
786
  if (!submitBtn.disabled) submitBtn.click();
@@ -820,6 +841,7 @@ var AnnotationPopup = class {
820
841
  const saveBtn = popup.querySelector('[data-action="save"]');
821
842
  const deleteBtn = popup.querySelector('[data-action="delete"]');
822
843
  textarea.addEventListener("keydown", (e) => {
844
+ e.stopPropagation();
823
845
  if (e.key === "Enter" && !e.shiftKey) {
824
846
  e.preventDefault();
825
847
  saveBtn.click();
@@ -846,9 +868,9 @@ var AnnotationPopup = class {
846
868
  textarea.setSelectionRange(textarea.value.length, textarea.value.length);
847
869
  }
848
870
  // ── Helpers ───────────────────────────────────────────────────
849
- /** Prevent popup interactions from reaching page handlers (e.g. @click.outside) */
871
+ /** Prevent popup interactions from reaching page handlers (e.g. @click.outside, form submit) */
850
872
  stopHostPropagation(host) {
851
- for (const evt of ["click", "mousedown", "pointerdown"]) {
873
+ for (const evt of ["click", "mousedown", "pointerdown", "keydown", "keyup", "keypress", "submit"]) {
852
874
  host.addEventListener(evt, (e) => e.stopPropagation());
853
875
  }
854
876
  }
@@ -1327,7 +1349,7 @@ var _Instruckt = class _Instruckt {
1327
1349
  onFreezeAnimations: (frozen) => {
1328
1350
  this.setFrozen(frozen);
1329
1351
  },
1330
- onCopy: () => this.copyAnnotations(),
1352
+ onCopy: () => this.copyToClipboard(true),
1331
1353
  onClearPage: () => this.clearPage(),
1332
1354
  onClearAll: () => this.clearEverything(),
1333
1355
  onMinimize: (min) => this.onMinimize(min)
@@ -1339,6 +1361,7 @@ var _Instruckt = class _Instruckt {
1339
1361
  window.addEventListener("scroll", this.boundReposition, { passive: true });
1340
1362
  window.addEventListener("resize", this.boundReposition, { passive: true });
1341
1363
  document.addEventListener("livewire:navigated", () => this.reattach());
1364
+ document.addEventListener("inertia:navigate", () => this.syncMarkers());
1342
1365
  window.addEventListener("popstate", () => {
1343
1366
  setTimeout(() => this.reattach(), 0);
1344
1367
  });
@@ -1354,7 +1377,7 @@ var _Instruckt = class _Instruckt {
1354
1377
  onFreezeAnimations: (frozen) => {
1355
1378
  this.setFrozen(frozen);
1356
1379
  },
1357
- onCopy: () => this.copyAnnotations(),
1380
+ onCopy: () => this.copyToClipboard(true),
1358
1381
  onClearPage: () => this.clearPage(),
1359
1382
  onClearAll: () => this.clearEverything(),
1360
1383
  onMinimize: (min) => this.onMinimize(min)
@@ -1740,17 +1763,28 @@ var _Instruckt = class _Instruckt {
1740
1763
  }
1741
1764
  }
1742
1765
  // ── Copy / export ─────────────────────────────────────────────
1766
+ /** Auto-copy on annotation submit — only in secure contexts to avoid focus side-effects */
1743
1767
  copyAnnotations() {
1768
+ this.copyToClipboard(false);
1769
+ }
1770
+ /** Copy to clipboard. With fallback=true, uses execCommand for non-secure contexts (user-initiated only). */
1771
+ copyToClipboard(fallback) {
1744
1772
  const md = this.exportMarkdown();
1745
- navigator.clipboard.writeText(md).catch(() => {
1746
- const el = document.createElement("textarea");
1747
- el.value = md;
1748
- el.style.cssText = "position:fixed;left:-9999px";
1749
- document.body.appendChild(el);
1750
- el.select();
1751
- document.execCommand("copy");
1752
- el.remove();
1753
- });
1773
+ if (window.isSecureContext) {
1774
+ navigator.clipboard.writeText(md).catch(() => {
1775
+ });
1776
+ } else if (fallback) {
1777
+ try {
1778
+ const el = document.createElement("textarea");
1779
+ el.value = md;
1780
+ el.style.cssText = "position:fixed;left:-9999px";
1781
+ document.body.appendChild(el);
1782
+ el.select();
1783
+ document.execCommand("copy");
1784
+ el.remove();
1785
+ } catch (e) {
1786
+ }
1787
+ }
1754
1788
  }
1755
1789
  exportMarkdown() {
1756
1790
  const pending = this.annotations.filter((a) => a.status !== "resolved" && a.status !== "dismissed");