@loupekit/sdk 0.9.3-next.38 → 0.9.3

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.
@@ -335,14 +335,6 @@ var Loupe = (() => {
335
335
  page stays visible and tappable; the list returns when the tool closes. */
336
336
  .dock.inspecting { height: auto !important; }
337
337
  .dock.inspecting .listhead, .dock.inspecting .list { display: none; }
338
- /* The composer is a bottom sheet on a phone: full width, thumb-reachable, and it
339
- scrolls when the on-screen keyboard is up. JS sets its position inline (hence the
340
- !important) \u2014 on small screens the sheet wins. */
341
- .composer {
342
- top: auto !important; left: 0 !important; right: 0 !important; bottom: 0 !important;
343
- width: auto !important; max-height: 80vh; overflow-y: auto;
344
- border-radius: 16px 16px 0 0; padding-bottom: 16px;
345
- }
346
338
  }
347
339
  `
348
340
  );
@@ -2466,26 +2458,6 @@ var Loupe = (() => {
2466
2458
  for (let i = 0; i < s.length; i++) h = h * 31 + s.charCodeAt(i) | 0;
2467
2459
  return h;
2468
2460
  }
2469
- function isTouchDevice() {
2470
- try {
2471
- return typeof window.matchMedia === "function" && window.matchMedia("(pointer: coarse)").matches;
2472
- } catch {
2473
- return false;
2474
- }
2475
- }
2476
- function dataUrlToFile(dataUrl, name) {
2477
- const m = /^data:([^;,]+)(;base64)?,([\s\S]*)$/.exec(dataUrl);
2478
- if (!m) return null;
2479
- const [, type, b64, payload = ""] = m;
2480
- try {
2481
- const raw = b64 ? atob(payload) : decodeURIComponent(payload);
2482
- const bytes = new Uint8Array(raw.length);
2483
- for (let i = 0; i < raw.length; i++) bytes[i] = raw.charCodeAt(i);
2484
- return new File([bytes], name, { type: type || "image/png" });
2485
- } catch {
2486
- return null;
2487
- }
2488
- }
2489
2461
  var LoupeApp = class {
2490
2462
  constructor(cfg) {
2491
2463
  this.comments = [];
@@ -2854,7 +2826,7 @@ var Loupe = (() => {
2854
2826
  const recordBtn = this.toolBtn(RECORD_ICON, "Record", "record");
2855
2827
  recordBtn.title = "Drag a box, record a screen video of it, and comment";
2856
2828
  recordBtn.onclick = () => this.setMode(this.mode === "record" ? "off" : "record");
2857
- const canRecord = !isTouchDevice() && typeof navigator.mediaDevices?.getDisplayMedia === "function";
2829
+ const canRecord = typeof navigator.mediaDevices?.getDisplayMedia === "function";
2858
2830
  tools.append(inspectBtn, freeBtn, regionBtn, ...canRecord ? [recordBtn] : []);
2859
2831
  const listHead = el("div", "listhead");
2860
2832
  listHead.append(document.createTextNode("Comments"));
@@ -3002,34 +2974,6 @@ var Loupe = (() => {
3002
2974
  const region = { x: vp.x + window.scrollX, y: vp.y + window.scrollY, w: vp.w, h: vp.h, rel };
3003
2975
  return { region, element: centerEl };
3004
2976
  }
3005
- /**
3006
- * Touch path for the Region tool: capture what is on screen right now and open the
3007
- * composer with it already attached. The reporter scrolls to the part of the page they
3008
- * mean FIRST, then taps Region — no drag, so nothing fights the page scroll.
3009
- */
3010
- async captureViewportForComposer() {
3011
- const vp = { x: 0, y: 0, w: window.innerWidth, h: window.innerHeight };
3012
- const capture = this.cfg.captureRegion ?? captureRegionScreenshot;
3013
- let shot;
3014
- try {
3015
- shot = await capture(vp);
3016
- } catch {
3017
- shot = void 0;
3018
- }
3019
- const file = shot ? dataUrlToFile(shot, "screenshot.png") : null;
3020
- const docX = window.scrollX + vp.w / 2;
3021
- const docY = window.scrollY + vp.h / 2;
3022
- const docW = Math.max(1, document.documentElement.scrollWidth);
3023
- const docH = Math.max(1, document.documentElement.scrollHeight);
3024
- const offset = { x: clamp(docX / docW), y: clamp(docY / docH) };
3025
- this.setMode("off");
3026
- this.openComposer(
3027
- { kind: "free", offset, point: { x: docX, y: docY }, label: "Screenshot \xB7 attached" },
3028
- 8,
3029
- window.innerHeight / 2,
3030
- file ? [file] : []
3031
- );
3032
- }
3033
2977
  /** Capture the selected viewport rect, then open the composer for a region comment. */
3034
2978
  async finishRegion(vp) {
3035
2979
  this.selbox.style.display = "none";
@@ -3113,6 +3057,7 @@ var Loupe = (() => {
3113
3057
  document.removeEventListener("click", this.onClick, true);
3114
3058
  document.removeEventListener("click", this.onFreeClick, true);
3115
3059
  document.removeEventListener("pointerdown", this.onRegionDown, true);
3060
+ document.documentElement.style.touchAction = mode === "region" || mode === "record" ? "none" : "";
3116
3061
  if (mode === "off") return;
3117
3062
  document.addEventListener("keydown", this.onKey, true);
3118
3063
  this.closeComposer();
@@ -3122,14 +3067,12 @@ var Loupe = (() => {
3122
3067
  document.addEventListener("click", this.onClick, true);
3123
3068
  } else if (mode === "free") {
3124
3069
  document.addEventListener("click", this.onFreeClick, true);
3125
- } else if (mode === "region" && isTouchDevice()) {
3126
- void this.captureViewportForComposer();
3127
3070
  } else if (mode === "region" || mode === "record") {
3128
3071
  document.addEventListener("pointerdown", this.onRegionDown, true);
3129
3072
  }
3130
3073
  }
3131
3074
  // ---- composer -------------------------------------------------------------
3132
- openComposer(target, x, y, seedFiles = []) {
3075
+ openComposer(target, x, y) {
3133
3076
  this.pending = target;
3134
3077
  const isRecording = target.kind === "region" && !!target.recording;
3135
3078
  const c = this.composer;
@@ -3137,14 +3080,14 @@ var Loupe = (() => {
3137
3080
  const label = el(
3138
3081
  "div",
3139
3082
  "target",
3140
- target.kind === "element" ? describe(target.element) : target.kind === "region" ? isRecording ? `\u23FA Recording \xB7 ${Math.round(target.region.w)}\xD7${Math.round(target.region.h)} px` : `Region \xB7 ${Math.round(target.region.w)}\xD7${Math.round(target.region.h)} px` : target.label ?? "Free note \xB7 anywhere on the page"
3083
+ target.kind === "element" ? describe(target.element) : target.kind === "region" ? isRecording ? `\u23FA Recording \xB7 ${Math.round(target.region.w)}\xD7${Math.round(target.region.h)} px` : `Region \xB7 ${Math.round(target.region.w)}\xD7${Math.round(target.region.h)} px` : "Free note \xB7 anywhere on the page"
3141
3084
  );
3142
3085
  const title = el("input", "title");
3143
3086
  title.type = "text";
3144
3087
  title.placeholder = "Title \u2014 one line: what's wrong, or what you need";
3145
3088
  const ta = el("textarea");
3146
3089
  ta.placeholder = isRecording ? "Describe the issue in this recording\u2026" : target.kind === "region" ? "Describe the issue in this area\u2026" : target.kind === "free" ? "Describe this note\u2026" : "Describe what should change here\u2026";
3147
- const files = seedFiles.slice();
3090
+ const files = [];
3148
3091
  const attach = el("div", "attach");
3149
3092
  const pick = el("button", "pick", "\uFF0B Attach images / videos");
3150
3093
  const input = document.createElement("input");
@@ -3186,7 +3129,6 @@ var Loupe = (() => {
3186
3129
  };
3187
3130
  pick.onclick = () => input.click();
3188
3131
  attach.append(pick, input, chips, err);
3189
- if (files.length) drawChips();
3190
3132
  const row = el("div", "row");
3191
3133
  let box = null;
3192
3134
  if (target.kind !== "free" && !isRecording) {
@@ -3218,7 +3160,7 @@ var Loupe = (() => {
3218
3160
  const left = Math.min(Math.max(8, x + 12), window.innerWidth - w - 8);
3219
3161
  const top = Math.min(Math.max(8, y + 12), window.innerHeight - h - 8);
3220
3162
  Object.assign(c.style, { display: "block", left: left + "px", top: top + "px" });
3221
- if (!isTouchDevice()) ta.focus();
3163
+ ta.focus();
3222
3164
  }
3223
3165
  closeComposer() {
3224
3166
  this.composer.style.display = "none";