@david-xpn/llm-ui-feedback 0.1.1 → 0.1.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.
package/dist/index.js CHANGED
@@ -136,9 +136,7 @@ function getElementsBeneathRect(rect) {
136
136
  for (let x = rect.x; x <= rect.x + rect.width; x += step) {
137
137
  for (let y = rect.y; y <= rect.y + rect.height; y += step) {
138
138
  const el = document.elementFromPoint(x, y);
139
- if (el && !seen.has(el)) {
140
- seen.add(el);
141
- }
139
+ if (el && !seen.has(el)) seen.add(el);
142
140
  }
143
141
  }
144
142
  for (const [x, y] of [
@@ -154,55 +152,95 @@ function getElementsBeneathRect(rect) {
154
152
  if (container) container.style.display = "";
155
153
  return Array.from(seen).filter((el) => !container?.contains(el));
156
154
  }
155
+ function getElementAtPoint(x, y) {
156
+ const container = document.getElementById(WIDGET_CONTAINER_ID);
157
+ if (container) container.style.display = "none";
158
+ const el = document.elementFromPoint(x, y);
159
+ if (container) container.style.display = "";
160
+ if (el && container?.contains(el)) return null;
161
+ return el;
162
+ }
163
+ var DRAG_THRESHOLD = 10;
157
164
  function PickOverlay({ onPick, onCancel }) {
158
- const [dragging, setDragging] = (0, import_react.useState)(false);
159
- const [start, setStart] = (0, import_react.useState)(null);
160
- const [current, setCurrent] = (0, import_react.useState)(null);
161
- const overlayRef = (0, import_react.useRef)(null);
162
- const handleMouseDown = (0, import_react.useCallback)((e) => {
163
- if (e.button !== 0) return;
164
- e.preventDefault();
165
- e.stopPropagation();
166
- setStart({ x: e.clientX, y: e.clientY });
167
- setCurrent({ x: e.clientX, y: e.clientY });
168
- setDragging(true);
169
- }, []);
170
- const handleMouseMove = (0, import_react.useCallback)((e) => {
171
- if (!dragging) return;
172
- e.preventDefault();
173
- setCurrent({ x: e.clientX, y: e.clientY });
174
- }, [dragging]);
175
- const handleMouseUp = (0, import_react.useCallback)((e) => {
176
- if (!dragging || !start) return;
177
- e.preventDefault();
178
- e.stopPropagation();
179
- setDragging(false);
180
- const endX = e.clientX;
181
- const endY = e.clientY;
182
- const x = Math.min(start.x, endX);
183
- const y = Math.min(start.y, endY);
184
- const width = Math.abs(endX - start.x);
185
- const height = Math.abs(endY - start.y);
186
- if (width < 10 || height < 10) {
187
- setStart(null);
188
- setCurrent(null);
189
- return;
165
+ const activeRef = (0, import_react.useRef)(false);
166
+ const startRef = (0, import_react.useRef)(null);
167
+ const isDragRef = (0, import_react.useRef)(false);
168
+ const [hoverRect, setHoverRect] = (0, import_react.useState)(null);
169
+ const [selRect, setSelRect] = (0, import_react.useState)(null);
170
+ const onPickRef = (0, import_react.useRef)(onPick);
171
+ onPickRef.current = onPick;
172
+ const onCancelRef = (0, import_react.useRef)(onCancel);
173
+ onCancelRef.current = onCancel;
174
+ (0, import_react.useEffect)(() => {
175
+ function handleMouseMove(e) {
176
+ if (activeRef.current && startRef.current) {
177
+ const dx = Math.abs(e.clientX - startRef.current.x);
178
+ const dy = Math.abs(e.clientY - startRef.current.y);
179
+ if (dx >= DRAG_THRESHOLD || dy >= DRAG_THRESHOLD) {
180
+ isDragRef.current = true;
181
+ }
182
+ if (isDragRef.current) {
183
+ setHoverRect(null);
184
+ setSelRect({
185
+ left: Math.min(startRef.current.x, e.clientX),
186
+ top: Math.min(startRef.current.y, e.clientY),
187
+ width: Math.abs(e.clientX - startRef.current.x),
188
+ height: Math.abs(e.clientY - startRef.current.y)
189
+ });
190
+ }
191
+ e.preventDefault();
192
+ } else {
193
+ const el = getElementAtPoint(e.clientX, e.clientY);
194
+ if (el) {
195
+ const r = el.getBoundingClientRect();
196
+ setHoverRect({ x: r.left, y: r.top, width: r.width, height: r.height });
197
+ } else {
198
+ setHoverRect(null);
199
+ }
200
+ }
190
201
  }
191
- const rect = { x, y, width, height };
192
- const elements = getElementsBeneathRect(rect);
193
- setStart(null);
194
- setCurrent(null);
195
- onPick(rect, elements);
196
- }, [dragging, start, onPick]);
197
- const handleKeyDown = (0, import_react.useCallback)((e) => {
198
- if (e.key === "Escape") {
199
- setDragging(false);
200
- setStart(null);
201
- setCurrent(null);
202
- onCancel();
202
+ function handleMouseDown(e) {
203
+ if (e.button !== 0) return;
204
+ e.preventDefault();
205
+ e.stopPropagation();
206
+ startRef.current = { x: e.clientX, y: e.clientY };
207
+ isDragRef.current = false;
208
+ activeRef.current = true;
209
+ }
210
+ function handleMouseUp(e) {
211
+ if (!activeRef.current || !startRef.current) return;
212
+ e.preventDefault();
213
+ e.stopPropagation();
214
+ const start = startRef.current;
215
+ activeRef.current = false;
216
+ startRef.current = null;
217
+ setSelRect(null);
218
+ setHoverRect(null);
219
+ if (!isDragRef.current) {
220
+ const el = getElementAtPoint(e.clientX, e.clientY);
221
+ if (el) {
222
+ const r = el.getBoundingClientRect();
223
+ onPickRef.current({ x: r.left, y: r.top, width: r.width, height: r.height }, [el]);
224
+ }
225
+ return;
226
+ }
227
+ const x = Math.min(start.x, e.clientX);
228
+ const y = Math.min(start.y, e.clientY);
229
+ const width = Math.abs(e.clientX - start.x);
230
+ const height = Math.abs(e.clientY - start.y);
231
+ const rect = { x, y, width, height };
232
+ const elements = getElementsBeneathRect(rect);
233
+ onPickRef.current(rect, elements);
234
+ }
235
+ function handleKeyDown(e) {
236
+ if (e.key === "Escape") {
237
+ activeRef.current = false;
238
+ startRef.current = null;
239
+ setSelRect(null);
240
+ setHoverRect(null);
241
+ onCancelRef.current();
242
+ }
203
243
  }
204
- }, [onCancel]);
205
- (0, import_react.useEffect)(() => {
206
244
  document.addEventListener("mousedown", handleMouseDown, true);
207
245
  document.addEventListener("mousemove", handleMouseMove, true);
208
246
  document.addEventListener("mouseup", handleMouseUp, true);
@@ -213,21 +251,11 @@ function PickOverlay({ onPick, onCancel }) {
213
251
  document.removeEventListener("mouseup", handleMouseUp, true);
214
252
  document.removeEventListener("keydown", handleKeyDown, true);
215
253
  };
216
- }, [handleMouseDown, handleMouseMove, handleMouseUp, handleKeyDown]);
217
- let selRect = null;
218
- if (start && current && dragging) {
219
- selRect = {
220
- left: Math.min(start.x, current.x),
221
- top: Math.min(start.y, current.y),
222
- width: Math.abs(current.x - start.x),
223
- height: Math.abs(current.y - start.y)
224
- };
225
- }
254
+ }, []);
226
255
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
227
256
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
228
257
  "div",
229
258
  {
230
- ref: overlayRef,
231
259
  style: {
232
260
  position: "fixed",
233
261
  top: 0,
@@ -257,12 +285,30 @@ function PickOverlay({ onPick, onCancel }) {
257
285
  pointerEvents: "none"
258
286
  },
259
287
  children: [
260
- "Drag to select an area for feedback. Press ",
288
+ "Click an element or drag to select an area. Press ",
261
289
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "Esc" }),
262
290
  " to cancel."
263
291
  ]
264
292
  }
265
293
  ),
294
+ hoverRect && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
295
+ "div",
296
+ {
297
+ style: {
298
+ position: "fixed",
299
+ left: hoverRect.x,
300
+ top: hoverRect.y,
301
+ width: hoverRect.width,
302
+ height: hoverRect.height,
303
+ border: "2px solid #3b82f6",
304
+ background: "rgba(59, 130, 246, 0.08)",
305
+ zIndex: 99998,
306
+ pointerEvents: "none",
307
+ borderRadius: 2,
308
+ transition: "all 0.1s ease-out"
309
+ }
310
+ }
311
+ ),
266
312
  selRect && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
267
313
  "div",
268
314
  {
@@ -623,8 +669,25 @@ function SidePanel({
623
669
  // src/components/DraftModal.tsx
624
670
  var import_react4 = require("react");
625
671
  var import_jsx_runtime5 = require("react/jsx-runtime");
672
+ var WIDGET_CONTAINER_ID2 = "llm-ui-feedback-root";
626
673
  function DraftModal({ pendingContext, addingDraft, onAdd, onCancel }) {
627
674
  const [comment, setComment] = (0, import_react4.useState)("");
675
+ (0, import_react4.useEffect)(() => {
676
+ const container = document.getElementById(WIDGET_CONTAINER_ID2);
677
+ const inerted = [];
678
+ for (const child of Array.from(document.body.children)) {
679
+ if (child === container || child.id === WIDGET_CONTAINER_ID2) continue;
680
+ if (!child.hasAttribute("inert")) {
681
+ child.setAttribute("inert", "");
682
+ inerted.push(child);
683
+ }
684
+ }
685
+ return () => {
686
+ for (const el of inerted) {
687
+ el.removeAttribute("inert");
688
+ }
689
+ };
690
+ }, []);
628
691
  const handleAdd = () => {
629
692
  if (comment.trim() && !addingDraft) {
630
693
  onAdd(comment.trim());
@@ -974,10 +1037,9 @@ function dataUrlToBlob(dataUrl) {
974
1037
 
975
1038
  // src/hooks/useSession.ts
976
1039
  var import_react6 = require("react");
977
- var import_meta = {};
978
1040
  var SESSION_TOKEN_KEY = "llm_feedback_session_token";
979
1041
  var USER_KEY = "llm_feedback_user";
980
- var AUTH_BYPASS = typeof import_meta !== "undefined" && import_meta.env?.VITE_AUTH_BYPASS === "true";
1042
+ var AUTH_BYPASS = !!(typeof globalThis !== "undefined" && globalThis.__FEEDBACK_AUTH_BYPASS__);
981
1043
  function getSessionToken() {
982
1044
  if (AUTH_BYPASS) return "bypass-token";
983
1045
  return localStorage.getItem(SESSION_TOKEN_KEY);
@@ -1340,10 +1402,13 @@ function FeedbackWidget({
1340
1402
  clickX: centerX,
1341
1403
  clickY: centerY
1342
1404
  };
1405
+ const isDrag = rect.width > 20 && rect.height > 20;
1343
1406
  let screenshot = null;
1344
- try {
1345
- screenshot = await captureScreenshot(rect);
1346
- } catch {
1407
+ if (isDrag) {
1408
+ try {
1409
+ screenshot = await captureScreenshot(rect);
1410
+ } catch {
1411
+ }
1347
1412
  }
1348
1413
  dispatch({ type: "ELEMENT_PICKED", context, screenshot });
1349
1414
  }, []);