reflet-sdk 0.5.0 → 0.5.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/CHANGELOG.md +6 -0
- package/dist/{devtools-layer-BYGuFmhg.js → devtools-layer-EyK7n9w3.js} +2 -2
- package/dist/{devtools-layer-BYGuFmhg.js.map → devtools-layer-EyK7n9w3.js.map} +1 -1
- package/dist/feedback.d.ts.map +1 -1
- package/dist/feedback.js +9 -113
- package/dist/feedback.js.map +1 -1
- package/dist/{picker-DDDpVcfr.js → picker-DFfC1uIY.js} +6 -17
- package/dist/picker-DFfC1uIY.js.map +1 -0
- package/package.json +1 -1
- package/dist/picker-DDDpVcfr.js.map +0 -1
package/dist/feedback.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feedback.d.ts","names":[],"sources":["../src/feedback/types.ts","../src/feedback/core/capture.ts","../src/feedback/core/element-selector.ts","../src/feedback/core/page-context.ts","../src/feedback/widget.tsx"],"mappings":";;cAKM;KAUM,yBAAyB;UAEpB;EACf;EACA;;UAGe;EACf;EACA,KAAK;EACL;;EAEA,SAAS;EACT,OAAO;EACP;EACA,MAAM;;UAGS;EACf,MAAM;EACN;EACA;;EAEA;EACA;;
|
|
1
|
+
{"version":3,"file":"feedback.d.ts","names":[],"sources":["../src/feedback/types.ts","../src/feedback/core/capture.ts","../src/feedback/core/element-selector.ts","../src/feedback/core/page-context.ts","../src/feedback/widget.tsx"],"mappings":";;cAKM;KAUM,yBAAyB;UAEpB;EACf;EACA;;UAGe;EACf;EACA,KAAK;EACL;;EAEA,SAAS;EACT,OAAO;EACP;EACA,MAAM;;UAGS;EACf,MAAM;EACN;EACA;;EAEA;EACA;;UAae;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAgDe;;EAEf;;EAEA;;EAEA;;;;;EAKA;;EAEA;;EAEA;;EAEA;EACA,SAAS,QAAQ;;EAEjB,WAAW;;EAEX;EACA;EACA,aAAa;IAAU;;EACvB;EACA,YAAY;IAAU;;EACtB;EACA;EACA;EACA;EACA,OAAO;EACP;;;;UC8De;;EAEf,UAAU;EACV;EACA;;EAEA;;;;;;;;;;wBA2GoB,gBACpB,UAAS,iBACR,QAAQ;wBAiDK,eAAe,OAAO;;;;wBCjHtB,sBAAsB,SAAS,UAAU;;;;wBCjMzC,mBAAmB;EACjC;IACE;;;wBCvEY,eAAe,OAAO,sCAAmB,IAAA"}
|
package/dist/feedback.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { n as Reflet } from "./client-BWEBWk1k.js";
|
|
3
|
-
import { A as TrashIcon, C as MoreIcon, E as SquareIcon, F as SDK_VERSION,
|
|
3
|
+
import { A as TrashIcon, C as MoreIcon, E as SquareIcon, F as SDK_VERSION, I as collectPageContext, K as releaseCapture, L as MAX_SELECTION_COMMENT_LENGTH, M as isDegenerate, N as normalizeRect, O as TargetIcon, P as DEFAULT_WIDGET_LABELS, R as buildElementSelection, S as HighlightIcon, T as SpotlightIcon, U as WIDGET_MARKER, W as captureViewport, _ as ChatIcon, b as CloseIcon, d as SelectionOutline, f as drawAnnotations, g as CameraIcon, h as BlurIcon, j as UndoIcon, k as TextIcon, l as submitWidgetFeedback, m as ArrowIcon, o as attachPreparedScreenshots, p as listenToKeydown, r as useFloatingPosition, s as createFeedbackTransport, t as ElementPicker, v as CheckIcon, w as PencilIcon, x as GripIcon, y as ChevronDownIcon } from "./picker-DFfC1uIY.js";
|
|
4
4
|
import { n as RefletContext, t as REFLET_Z_INDEX } from "./z-index-CKxBgZTG.js";
|
|
5
5
|
import { Suspense, lazy, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -743,45 +743,8 @@ function CaptureSlot({ labels, state }) {
|
|
|
743
743
|
}
|
|
744
744
|
//#endregion
|
|
745
745
|
//#region src/feedback/core/element-capture.ts
|
|
746
|
-
const MIN_CONTEXT_PADDING = 24;
|
|
747
|
-
const MAX_CONTEXT_WIDTH = 2e3;
|
|
748
|
-
const CLOSE_UP_MAX_WIDTH = 1200;
|
|
749
746
|
const SELECTION_COLOR = "#4f46e5";
|
|
750
747
|
const SELECTION_ANNOTATION_PREFIX = "selection-";
|
|
751
|
-
const OUTLINE_COLOR = "#4f46e5";
|
|
752
|
-
const OUTLINE_GLOW = "#ffffff";
|
|
753
|
-
const OUTLINE_WIDTH = 3;
|
|
754
|
-
const GLOW_WIDTH = 6;
|
|
755
|
-
const DIM_OVERLAY = "rgba(15, 23, 42, 0.45)";
|
|
756
|
-
/**
|
|
757
|
-
* Tightest ancestor that keeps some breathing room around the pick — the zoom
|
|
758
|
-
* stays zoomed instead of growing to a giant section. Only when nothing up
|
|
759
|
-
* the tree clears the minimum does the widest candidate below the cap win.
|
|
760
|
-
*/
|
|
761
|
-
function contextRootFor(element) {
|
|
762
|
-
const target = element.getBoundingClientRect();
|
|
763
|
-
const coversAtLeast = (box, margin) => box.left <= target.left - margin && box.right >= target.right + margin && box.top <= target.top - margin && box.bottom >= target.bottom + margin;
|
|
764
|
-
let tightest = null;
|
|
765
|
-
let current = element.parentElement;
|
|
766
|
-
while (current && current !== document.documentElement) {
|
|
767
|
-
const box = current.getBoundingClientRect();
|
|
768
|
-
if (coversAtLeast(box, MIN_CONTEXT_PADDING)) return current;
|
|
769
|
-
tightest ??= box.width < MAX_CONTEXT_WIDTH ? current : null;
|
|
770
|
-
current = current.parentElement;
|
|
771
|
-
}
|
|
772
|
-
return tightest ?? element;
|
|
773
|
-
}
|
|
774
|
-
/** Where the picked element sits inside the context shot, in image pixels. */
|
|
775
|
-
function closeUpGeometry(params) {
|
|
776
|
-
const scale = params.rootRect.width > 0 ? params.capture.width / params.rootRect.width : 1;
|
|
777
|
-
return {
|
|
778
|
-
height: Math.round(params.elementRect.height * scale),
|
|
779
|
-
scale,
|
|
780
|
-
width: Math.round(params.elementRect.width * scale),
|
|
781
|
-
x: Math.round((params.elementRect.left - params.rootRect.left) * scale),
|
|
782
|
-
y: Math.round((params.elementRect.top - params.rootRect.top) * scale)
|
|
783
|
-
};
|
|
784
|
-
}
|
|
785
748
|
function isSelectionAnnotation({ id }) {
|
|
786
749
|
return id.startsWith(SELECTION_ANNOTATION_PREFIX);
|
|
787
750
|
}
|
|
@@ -802,70 +765,6 @@ function highlightFor(selection, capture) {
|
|
|
802
765
|
tool: "rectangle"
|
|
803
766
|
};
|
|
804
767
|
}
|
|
805
|
-
function drawZoneOverlay(context, zone) {
|
|
806
|
-
context.save();
|
|
807
|
-
context.fillStyle = DIM_OVERLAY;
|
|
808
|
-
context.beginPath();
|
|
809
|
-
context.rect(0, 0, context.canvas.width, context.canvas.height);
|
|
810
|
-
context.rect(zone.x, zone.y, zone.width, zone.height);
|
|
811
|
-
context.fill("evenodd");
|
|
812
|
-
for (const [color, width] of [[OUTLINE_GLOW, GLOW_WIDTH], [OUTLINE_COLOR, OUTLINE_WIDTH]]) {
|
|
813
|
-
context.strokeStyle = color;
|
|
814
|
-
context.lineWidth = width * zone.scale;
|
|
815
|
-
context.strokeRect(zone.x, zone.y, zone.width, zone.height);
|
|
816
|
-
}
|
|
817
|
-
context.restore();
|
|
818
|
-
}
|
|
819
|
-
function drawCloseUp(capture, zone) {
|
|
820
|
-
return new Promise((resolve) => {
|
|
821
|
-
const canvas = document.createElement("canvas");
|
|
822
|
-
canvas.width = capture.width;
|
|
823
|
-
canvas.height = capture.height;
|
|
824
|
-
const context = canvas.getContext("2d");
|
|
825
|
-
const image = new Image();
|
|
826
|
-
image.onload = () => {
|
|
827
|
-
if (!context) {
|
|
828
|
-
resolve(null);
|
|
829
|
-
return;
|
|
830
|
-
}
|
|
831
|
-
context.drawImage(image, 0, 0, capture.width, capture.height);
|
|
832
|
-
drawZoneOverlay(context, zone);
|
|
833
|
-
resolve(capturedFromCanvas(canvas, CLOSE_UP_MAX_WIDTH));
|
|
834
|
-
};
|
|
835
|
-
image.onerror = () => resolve(null);
|
|
836
|
-
image.src = capture.objectUrl;
|
|
837
|
-
});
|
|
838
|
-
}
|
|
839
|
-
/**
|
|
840
|
-
* Zoomed view of the picked zone: the surrounding area captured for context,
|
|
841
|
-
* everything outside the selection dimmed and the zone framed with a glowing
|
|
842
|
-
* outline — unambiguous to eyes and vision models alike.
|
|
843
|
-
* Falls back to the plain context shot when the overlay cannot be drawn.
|
|
844
|
-
*/
|
|
845
|
-
async function captureElementCloseUp(element) {
|
|
846
|
-
try {
|
|
847
|
-
const root = contextRootFor(element);
|
|
848
|
-
const rootRect = root.getBoundingClientRect();
|
|
849
|
-
const elementRect = element.getBoundingClientRect();
|
|
850
|
-
const capture = await captureViewport({
|
|
851
|
-
element: root,
|
|
852
|
-
maxWidth: CLOSE_UP_MAX_WIDTH
|
|
853
|
-
});
|
|
854
|
-
if (!capture || root === element) return capture;
|
|
855
|
-
const outlined = await drawCloseUp(capture, closeUpGeometry({
|
|
856
|
-
capture,
|
|
857
|
-
elementRect,
|
|
858
|
-
rootRect
|
|
859
|
-
}));
|
|
860
|
-
if (outlined) {
|
|
861
|
-
releaseCapture(capture);
|
|
862
|
-
return outlined;
|
|
863
|
-
}
|
|
864
|
-
return capture;
|
|
865
|
-
} catch {
|
|
866
|
-
return null;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
768
|
//#endregion
|
|
870
769
|
//#region src/feedback/ui/annotation/screenshot-preview.tsx
|
|
871
770
|
function ScreenshotPreview({ annotations, capture }) {
|
|
@@ -1372,7 +1271,6 @@ function useFeedbackSubmission(options) {
|
|
|
1372
1271
|
//#region src/feedback/ui/state/use-screenshot-drafts.ts
|
|
1373
1272
|
function releaseDraft(draft) {
|
|
1374
1273
|
releaseCapture(draft?.image);
|
|
1375
|
-
releaseCapture(draft?.closeUp);
|
|
1376
1274
|
}
|
|
1377
1275
|
function useScreenshotDrafts(captureFailed, onError) {
|
|
1378
1276
|
const [screenshots, setScreenshots] = useState([]);
|
|
@@ -1474,9 +1372,12 @@ function useScreenshotDrafts(captureFailed, onError) {
|
|
|
1474
1372
|
}
|
|
1475
1373
|
} : item));
|
|
1476
1374
|
}, []);
|
|
1375
|
+
const activeScreenshot = screenshots.find(({ id }) => id === activeId) ?? screenshots.at(-1) ?? null;
|
|
1376
|
+
const firstCapture = pendingCapture ?? screenshots[0];
|
|
1477
1377
|
return {
|
|
1478
|
-
activeScreenshot
|
|
1378
|
+
activeScreenshot,
|
|
1479
1379
|
cancelPendingCapture,
|
|
1380
|
+
canRefreshAutomatically: screenshots.length <= 1 && firstCapture?.source === "automatic" && (activeScreenshot?.annotations.length ?? 0) === 0 && !screenshots.some((draft) => draft.selection),
|
|
1480
1381
|
pendingCapture,
|
|
1481
1382
|
refreshAutomatic,
|
|
1482
1383
|
removeCapture,
|
|
@@ -1645,9 +1546,7 @@ function useWidgetState(props) {
|
|
|
1645
1546
|
partialUploadMessage: props.labels?.attachmentUploadFailed ?? DEFAULT_WIDGET_LABELS.attachmentUploadFailed
|
|
1646
1547
|
});
|
|
1647
1548
|
const { resetSubmission } = submission;
|
|
1648
|
-
|
|
1649
|
-
const canRefreshAutomatically = gallery.screenshots.length <= 1 && firstCapture?.source === "automatic";
|
|
1650
|
-
useCaptureSync(isOpen && !submission.isEditingDisabled && step === "compose" && canRefreshAutomatically && annotations.length === 0 && !gallery.screenshots.some((draft) => draft.selection) && props.captureOnOpen !== false, refreshAutomatic);
|
|
1549
|
+
useCaptureSync(isOpen && !submission.isEditingDisabled && step === "compose" && gallery.canRefreshAutomatically && props.captureOnOpen !== false, refreshAutomatic);
|
|
1651
1550
|
const reset = useCallback(() => {
|
|
1652
1551
|
if (successTimer.current) clearTimeout(successTimer.current);
|
|
1653
1552
|
setAnnotationTrigger(null);
|
|
@@ -1700,21 +1599,18 @@ function useWidgetState(props) {
|
|
|
1700
1599
|
setStep("compose");
|
|
1701
1600
|
const pick = ++pickRef.current;
|
|
1702
1601
|
const context = collectPageContext({ sdkVersion: SDK_VERSION });
|
|
1703
|
-
const
|
|
1602
|
+
const fresh = await captureViewport().catch(() => null);
|
|
1704
1603
|
if (pickRef.current !== pick) {
|
|
1705
1604
|
releaseCapture(fresh);
|
|
1706
|
-
releaseCapture(closeUp);
|
|
1707
1605
|
return;
|
|
1708
1606
|
}
|
|
1709
1607
|
setIsElementCapturing(false);
|
|
1710
1608
|
if (!fresh) {
|
|
1711
|
-
releaseCapture(closeUp);
|
|
1712
1609
|
setError(captureFailed);
|
|
1713
1610
|
return;
|
|
1714
1611
|
}
|
|
1715
1612
|
storeScreenshot({
|
|
1716
1613
|
annotations: [highlightFor(picked, fresh)],
|
|
1717
|
-
closeUp,
|
|
1718
1614
|
context,
|
|
1719
1615
|
id: crypto.randomUUID(),
|
|
1720
1616
|
image: fresh,
|
|
@@ -1738,7 +1634,7 @@ function useWidgetState(props) {
|
|
|
1738
1634
|
setStep("compose");
|
|
1739
1635
|
return submission.submit({
|
|
1740
1636
|
context: {
|
|
1741
|
-
...activeScreenshot?.context ?? collectPageContext({ sdkVersion: "0.5.
|
|
1637
|
+
...activeScreenshot?.context ?? collectPageContext({ sdkVersion: "0.5.1" }),
|
|
1742
1638
|
consoleEvents: consoleRef.current?.events(),
|
|
1743
1639
|
metadata: props.metadata,
|
|
1744
1640
|
selections
|
|
@@ -2410,7 +2306,7 @@ function ShadowPortal({ children, offset, primaryColor, theme }) {
|
|
|
2410
2306
|
}
|
|
2411
2307
|
//#endregion
|
|
2412
2308
|
//#region src/feedback/widget.tsx
|
|
2413
|
-
const DevtoolsLayer = process.env.NODE_ENV === "development" ? lazy(() => import("./devtools-layer-
|
|
2309
|
+
const DevtoolsLayer = process.env.NODE_ENV === "development" ? lazy(() => import("./devtools-layer-EyK7n9w3.js").then((module) => ({ default: module.DevtoolsLayer }))) : null;
|
|
2414
2310
|
function RefletFeedback(props) {
|
|
2415
2311
|
const { devtools = true, enabled = true, hotkey = null, offset = 20, position = "bottom-right", theme = "auto" } = props;
|
|
2416
2312
|
const labels = {
|