reflet-sdk 0.6.4 → 0.6.6

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.
Files changed (59) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +100 -2
  3. package/dist/{client-DAdWdIFY.js → client-oFFfRxAM.js} +135 -59
  4. package/dist/client-oFFfRxAM.js.map +1 -0
  5. package/dist/client-transport-B7BdVU7J.d.ts +150 -0
  6. package/dist/client-transport-B7BdVU7J.d.ts.map +1 -0
  7. package/dist/{devtools-layer-DgmM3RhW.js → devtools-layer-B91EVgqg.js} +417 -916
  8. package/dist/devtools-layer-B91EVgqg.js.map +1 -0
  9. package/dist/devtools-next.js +1 -1
  10. package/dist/devtools-vite.js +2 -2
  11. package/dist/feedback.d.ts +7 -1
  12. package/dist/feedback.d.ts.map +1 -1
  13. package/dist/feedback.js +105 -57
  14. package/dist/feedback.js.map +1 -1
  15. package/dist/{handler-BSNmdHXv.js → handler-yA_knIf3.js} +4 -4
  16. package/dist/{handler-BSNmdHXv.js.map → handler-yA_knIf3.js.map} +1 -1
  17. package/dist/index-Buum9tIY.d.ts +230 -0
  18. package/dist/index-Buum9tIY.d.ts.map +1 -0
  19. package/dist/index.d.ts +3 -3
  20. package/dist/index.js +1 -1
  21. package/dist/options-CIBazDPp.d.ts.map +1 -1
  22. package/dist/protocol-vJhQHTcB.js +390 -0
  23. package/dist/protocol-vJhQHTcB.js.map +1 -0
  24. package/dist/{react-context-Caq1fodf.js → react-context-Kazo_JCz.js} +3 -14
  25. package/dist/react-context-Kazo_JCz.js.map +1 -0
  26. package/dist/react.d.ts +43 -3
  27. package/dist/react.d.ts.map +1 -1
  28. package/dist/react.js +389 -3
  29. package/dist/react.js.map +1 -1
  30. package/dist/selection-outline-NzAAAZXR.js +51 -0
  31. package/dist/selection-outline-NzAAAZXR.js.map +1 -0
  32. package/dist/server.js +1 -1
  33. package/dist/server.js.map +1 -1
  34. package/dist/sessions-panel-DVyWzZ3C.js +6011 -0
  35. package/dist/sessions-panel-DVyWzZ3C.js.map +1 -0
  36. package/dist/{submit-Cd-g1Dtg.js → submit-DYGZQVdG.js} +49 -74
  37. package/dist/submit-DYGZQVdG.js.map +1 -0
  38. package/dist/surveys.d.ts +3 -0
  39. package/dist/surveys.js +2 -0
  40. package/dist/team-activation-DCqh71bl.js +24 -0
  41. package/dist/team-activation-DCqh71bl.js.map +1 -0
  42. package/dist/team-layer-F-9BE4hc.js +423 -0
  43. package/dist/team-layer-F-9BE4hc.js.map +1 -0
  44. package/dist/{types-DnaDEN9Y.d.ts → types-B3XiHPqy.d.ts} +4 -9
  45. package/dist/types-B3XiHPqy.d.ts.map +1 -0
  46. package/dist/use-survey-session-LK6sN1Fg.js +1247 -0
  47. package/dist/use-survey-session-LK6sN1Fg.js.map +1 -0
  48. package/dist/z-index-CwokqVq_.js +15 -0
  49. package/dist/z-index-CwokqVq_.js.map +1 -0
  50. package/package.json +6 -2
  51. package/dist/client-DAdWdIFY.js.map +0 -1
  52. package/dist/client-DF1fdsSC.d.ts +0 -131
  53. package/dist/client-DF1fdsSC.d.ts.map +0 -1
  54. package/dist/devtools-layer-DgmM3RhW.js.map +0 -1
  55. package/dist/protocol-ClqTFzwR.js +0 -35
  56. package/dist/protocol-ClqTFzwR.js.map +0 -1
  57. package/dist/react-context-Caq1fodf.js.map +0 -1
  58. package/dist/submit-Cd-g1Dtg.js.map +0 -1
  59. package/dist/types-DnaDEN9Y.d.ts.map +0 -1
@@ -1,4 +1,4 @@
1
- import { c as ElementSelection, u as FeedbackContext, w as RefletUser } from "./types-DnaDEN9Y.js";
1
+ import { c as ElementSelection, u as FeedbackContext, w as RefletUser } from "./types-B3XiHPqy.js";
2
2
  import { ReactNode, RefObject } from "react";
3
3
  //#region src/feedback/types.d.ts
4
4
  declare const ANNOTATION_TOOLS: readonly ["pen", "arrow", "rectangle", "text", "spotlight", "highlight", "blur"];
@@ -72,6 +72,8 @@ interface FeedbackTriggerProps {
72
72
  ref: RefObject<HTMLButtonElement | null>;
73
73
  }
74
74
  interface RefletFeedbackProps {
75
+ /** Hosts the team sign-in page. Defaults to https://www.reflet.app. */
76
+ appUrl?: string;
75
77
  baseUrl?: string;
76
78
  captureConsole?: boolean;
77
79
  captureOnOpen?: boolean;
@@ -94,6 +96,8 @@ interface RefletFeedbackProps {
94
96
  primaryColor?: string;
95
97
  publicKey?: string;
96
98
  renderTrigger?: (props: FeedbackTriggerProps) => ReactNode;
99
+ /** Shown once activated by the `reflet-team` URL parameter or a stored sign-in. Defaults to true. */
100
+ teamTools?: boolean;
97
101
  theme?: "auto" | "dark" | "light";
98
102
  user?: RefletUser;
99
103
  userToken?: string;
@@ -105,6 +109,8 @@ interface CaptureOptions {
105
109
  element?: Element;
106
110
  excludeSelectors?: string[];
107
111
  maxWidth?: number;
112
+ /** Edits the detached clone, never the live page. */
113
+ prepareClone?: (clone: Element) => void;
108
114
  /** Hard cap for one capture attempt before falling back. Default 10s. */
109
115
  timeout?: number;
110
116
  }
@@ -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":";;;cAMM;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;EACA;;UAiDe;EACf;EACA,KAAK,UAAU;;UAGA;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA,SAAS,QAAQ;EACjB,WAAW;EACX;EACA;EACA,aAAa;IAAU;;EACvB;EACA,YAAY;IAAU;;EACtB;EACA;EACA;EACA,iBAAiB,OAAO,yBAAyB;EACjD;EACA,OAAO;EACP;;;;UCiEe;;EAEf,UAAU;EACV;EACA;;EAEA;;;;;;;;;;wBAoHoB,gBACpB,UAAS,iBACR,QAAQ;wBAiDK,eAAe,OAAO;;;;wBC1HtB,sBAAsB,SAAS,UAAU;;;;wBCjMzC,mBAAmB;EACjC;IACE;;;wBCnEY,eAAe,OAAO,sCAAmB,IAAA"}
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":";;;cAMM;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;EACA;;UAiDe;EACf;EACA,KAAK,UAAU;;UAGA;;EAEf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,SAAS,QAAQ;EACjB,WAAW;EACX;EACA;EACA,aAAa;IAAU;;EACvB;EACA,YAAY;IAAU;;EACtB;EACA;EACA;EACA,iBAAiB,OAAO,yBAAyB;;EAEjD;EACA;EACA,OAAO;EACP;;;;UC6De;;EAEf,UAAU;EACV;EACA;;EAEA,gBAAgB,OAAO;;EAEvB;;;;;;;;;;wBAoIoB,gBACpB,UAAS,iBACR,QAAQ;wBAkDK,eAAe,OAAO;;;;wBC7ItB,sBAAsB,SAAS,UAAU;;;;wBCjMzC,mBAAmB;EACjC;IACE;;;wBC3BY,eAAe,OAAO,sCAAmB,IAAA"}
package/dist/feedback.js CHANGED
@@ -1,7 +1,10 @@
1
1
  "use client";
2
- import { n as Reflet } from "./client-DAdWdIFY.js";
3
- import { A as SquareIcon, B as collectPageContext, C as ChevronDownIcon, D as MoreIcon, E as HighlightIcon, F as UndoIcon, H as buildElementSelection, I as isDegenerate, J as captureViewport, L as normalizeRect, M as TargetIcon, N as TextIcon, O as PencilIcon, P as TrashIcon, R as DEFAULT_WIDGET_LABELS, S as CheckIcon, T as GripIcon, V as MAX_SELECTION_COMMENT_LENGTH, X as capturedViewportSize, Z as releaseCapture, _ as matchesHotkey, b as CameraIcon, c as useFloatingPosition, d as SelectionOutline, f as drawAnnotations, g as isSubmitEnter, h as stopClicksAtHost, i as submitWidgetFeedback, k as SpotlightIcon, m as listenToKeydown, n as createFeedbackTransport, o as ElementPicker, p as listenOnPageAndWidget, q as WIDGET_MARKER, t as attachPreparedScreenshots, v as ArrowIcon, w as CloseIcon, x as ChatIcon, y as BlurIcon, z as SDK_VERSION } from "./submit-Cd-g1Dtg.js";
4
- import { a as REFLET_Z_INDEX, t as RefletContext } from "./react-context-Caq1fodf.js";
2
+ import { n as Reflet } from "./client-oFFfRxAM.js";
3
+ import { A as SquareIcon, C as ChevronDownIcon, D as MoreIcon, E as HighlightIcon, F as UndoIcon, H as MAX_SELECTION_COMMENT_LENGTH, I as isDegenerate, J as maskSecrets, L as normalizeRect, M as TargetIcon, N as TextIcon, O as PencilIcon, P as TrashIcon, R as DEFAULT_WIDGET_LABELS, S as CheckIcon, T as GripIcon, U as buildElementSelection, V as collectPageContext, _ as matchesHotkey, b as CameraIcon, c as useFloatingPosition, d as drawAnnotations, et as WIDGET_MARKER, f as listenOnPageAndWidget, g as isSubmitEnter, h as stopClicksAtHost, i as submitWidgetFeedback, it as releaseCapture, k as SpotlightIcon, n as createFeedbackTransport, o as ElementPicker, p as listenToKeydown, rt as capturedViewportSize, t as attachPreparedScreenshots, tt as captureViewport, v as ArrowIcon, w as CloseIcon, x as ChatIcon, y as BlurIcon, z as SDK_VERSION } from "./submit-DYGZQVdG.js";
4
+ import { t as RefletContext } from "./react-context-Kazo_JCz.js";
5
+ import { t as hasTeamActivation } from "./team-activation-DCqh71bl.js";
6
+ import { t as SelectionOutline } from "./selection-outline-NzAAAZXR.js";
7
+ import { t as REFLET_Z_INDEX } from "./z-index-CwokqVq_.js";
5
8
  import { Suspense, lazy, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
6
9
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
10
  import { Slider } from "@base-ui/react/slider";
@@ -666,42 +669,6 @@ function Annotator({ capture, labels, editor, note }) {
666
669
  });
667
670
  }
668
671
  //#endregion
669
- //#region src/feedback/ui/devtools-owner.ts
670
- const claims = /* @__PURE__ */ new Map();
671
- const listeners = /* @__PURE__ */ new Set();
672
- function notify() {
673
- for (const listener of listeners) listener();
674
- }
675
- function subscribe(listener) {
676
- listeners.add(listener);
677
- return () => listeners.delete(listener);
678
- }
679
- function currentOwner() {
680
- for (const [token, claim] of claims) if (claim.hasWidget) return token;
681
- return claims.keys().next().value;
682
- }
683
- /**
684
- * One devtools bar per page, however many RefletFeedback instances mount:
685
- * the one with a visible widget wins, so its bar can step aside for its panel.
686
- */
687
- function useOwnsDevtools(wantsDevtools, hasWidget) {
688
- const [token] = useState(() => Symbol("reflet-devtools"));
689
- useEffect(() => {
690
- if (!wantsDevtools) return;
691
- claims.set(token, { hasWidget });
692
- notify();
693
- return () => {
694
- claims.delete(token);
695
- notify();
696
- };
697
- }, [
698
- hasWidget,
699
- token,
700
- wantsDevtools
701
- ]);
702
- return useSyncExternalStore(subscribe, () => currentOwner() === token, () => false);
703
- }
704
- //#endregion
705
672
  //#region src/feedback/ui/launcher.tsx
706
673
  function Launcher({ isOpen, label, onClick, buttonRef }) {
707
674
  return /* @__PURE__ */ jsxs("button", {
@@ -1281,6 +1248,52 @@ function useWidgetLauncher(state) {
1281
1248
  };
1282
1249
  }
1283
1250
  //#endregion
1251
+ //#region src/feedback/ui/page-ownership.ts
1252
+ function createPageOwnership(name) {
1253
+ const claims = /* @__PURE__ */ new Map();
1254
+ const listeners = /* @__PURE__ */ new Set();
1255
+ const notify = () => {
1256
+ for (const listener of listeners) listener();
1257
+ };
1258
+ const subscribe = (listener) => {
1259
+ listeners.add(listener);
1260
+ return () => listeners.delete(listener);
1261
+ };
1262
+ const currentOwner = () => {
1263
+ for (const [token, claim] of claims) if (claim.hasWidget) return token;
1264
+ return claims.keys().next().value;
1265
+ };
1266
+ function useOwns(wants, hasWidget) {
1267
+ const [token] = useState(() => Symbol(name));
1268
+ useEffect(() => {
1269
+ if (!wants) return;
1270
+ claims.set(token, { hasWidget });
1271
+ notify();
1272
+ return () => {
1273
+ claims.delete(token);
1274
+ notify();
1275
+ };
1276
+ }, [
1277
+ hasWidget,
1278
+ token,
1279
+ wants
1280
+ ]);
1281
+ return useSyncExternalStore(subscribe, () => currentOwner() === token, () => false);
1282
+ }
1283
+ function useIsClaimed() {
1284
+ return useSyncExternalStore(subscribe, () => claims.size > 0, () => false);
1285
+ }
1286
+ return {
1287
+ useIsClaimed,
1288
+ useOwns
1289
+ };
1290
+ }
1291
+ const devtoolsOwnership = createPageOwnership("reflet-devtools");
1292
+ const teamToolsOwnership = createPageOwnership("reflet-team-tools");
1293
+ const useOwnsDevtools = devtoolsOwnership.useOwns;
1294
+ const useHasDevtoolsOnPage = devtoolsOwnership.useIsClaimed;
1295
+ const useOwnsTeamTools = teamToolsOwnership.useOwns;
1296
+ //#endregion
1284
1297
  //#region src/feedback/ui/annotation/styles.ts
1285
1298
  const ANNOTATOR_STYLES = `
1286
1299
  .overlay { margin: 0; border: 0; padding: 0; width: 100vw; max-width: none; height: 100dvh; max-height: none; position: fixed; inset: 0; z-index: ${REFLET_Z_INDEX.annotatorOverlay}; display: flex; flex-direction: column; background: transparent; color: var(--rf-text); font: 13px/1.45 ui-sans-serif, system-ui, sans-serif; }
@@ -1822,8 +1835,7 @@ function serializeArgument(value) {
1822
1835
  if (typeof value === "function") return "[function]";
1823
1836
  return String(value);
1824
1837
  }
1825
- function formatMessage(args) {
1826
- const message = args.map(serializeArgument).join(" ");
1838
+ function clip(message) {
1827
1839
  return message.length > MAX_MESSAGE_LENGTH ? `${message.slice(0, 999)}…` : message;
1828
1840
  }
1829
1841
  /**
@@ -1838,7 +1850,7 @@ function startConsoleRecorder(options) {
1838
1850
  if (!(active && message)) return;
1839
1851
  buffer.push({
1840
1852
  level,
1841
- message,
1853
+ message: clip(maskSecrets(message)),
1842
1854
  timestamp: Date.now()
1843
1855
  });
1844
1856
  if (buffer.length > limit) buffer.splice(0, buffer.length - limit);
@@ -1848,7 +1860,7 @@ function startConsoleRecorder(options) {
1848
1860
  for (const method of RECORDED_METHODS) {
1849
1861
  const original = console[method];
1850
1862
  const wrapper = (...args) => {
1851
- push(method, formatMessage(args));
1863
+ push(method, args.map(serializeArgument).join(" "));
1852
1864
  Reflect.apply(original, console, args);
1853
1865
  };
1854
1866
  originals.set(method, original);
@@ -2291,7 +2303,7 @@ function useWidgetState(props) {
2291
2303
  setStep("compose");
2292
2304
  return submission.submit({
2293
2305
  context: {
2294
- ...activeScreenshot?.context ?? collectPageContext({ sdkVersion: "0.6.4" }),
2306
+ ...activeScreenshot?.context ?? collectPageContext({ sdkVersion: "0.6.6" }),
2295
2307
  consoleEvents: consoleRef.current?.events(),
2296
2308
  metadata: props.metadata,
2297
2309
  selections
@@ -2357,31 +2369,67 @@ function useWidgetState(props) {
2357
2369
  }
2358
2370
  //#endregion
2359
2371
  //#region src/feedback/widget.tsx
2360
- const DevtoolsLayer = process.env.NODE_ENV === "development" ? lazy(() => import("./devtools-layer-DgmM3RhW.js").then((module) => ({ default: module.DevtoolsLayer }))) : null;
2372
+ const DevtoolsLayer = process.env.NODE_ENV === "development" ? lazy(() => import("./devtools-layer-B91EVgqg.js").then((module) => ({ default: module.DevtoolsLayer }))) : null;
2373
+ const TeamLayer = lazy(() => import("./team-layer-F-9BE4hc.js").then((module) => ({ default: module.TeamLayer })));
2374
+ const DEFAULT_APP_URL = "https://www.reflet.app";
2375
+ const ignoreChanges = () => () => void 0;
2376
+ /** Activation reads the URL and storage, which only exist in the browser: the server renders without team tools. */
2377
+ function useTeamToolsKey(options) {
2378
+ const { props, publicKey } = options;
2379
+ const hasDevtoolsOnPage = useHasDevtoolsOnPage();
2380
+ const isActivated = useSyncExternalStore(ignoreChanges, () => props.teamTools !== false && publicKey !== null && hasTeamActivation(publicKey), () => false);
2381
+ return useOwnsTeamTools(isActivated && !hasDevtoolsOnPage, options.hasWidget) ? publicKey : null;
2382
+ }
2361
2383
  function RefletFeedback(props) {
2362
2384
  const state = useWidgetState(props);
2363
2385
  const launcher = useWidgetLauncher(state);
2364
2386
  const showsWidget = props.enabled !== false && !state.isDismissed;
2365
2387
  const showsDevtools = useOwnsDevtools(props.devtools !== false && DevtoolsLayer !== null, showsWidget) && DevtoolsLayer !== null;
2366
- if (!(showsWidget || showsDevtools)) return null;
2388
+ const teamToolsKey = useTeamToolsKey({
2389
+ hasWidget: showsWidget,
2390
+ props,
2391
+ publicKey: state.publicKey
2392
+ });
2393
+ if (!(showsWidget || showsDevtools || teamToolsKey)) return null;
2367
2394
  return /* @__PURE__ */ jsxs(Fragment, { children: [showsWidget && props.renderTrigger?.(launcher.triggerProps), /* @__PURE__ */ jsxs(ShadowPortal, {
2368
2395
  offset: props.offset ?? 20,
2369
2396
  primaryColor: props.primaryColor,
2370
2397
  theme: props.theme ?? "auto",
2371
- children: [showsWidget && /* @__PURE__ */ jsx(WidgetContents, {
2372
- launcher,
2373
- props,
2374
- state
2375
- }), showsDevtools && /* @__PURE__ */ jsx(Suspense, {
2376
- fallback: null,
2377
- children: /* @__PURE__ */ jsx(DevtoolsLayer, {
2378
- isWidgetOpen: showsWidget && state.isOpen,
2379
- position: props.position ?? "bottom-right",
2380
- publicKey: state.publicKey
2398
+ children: [
2399
+ showsWidget && /* @__PURE__ */ jsx(WidgetContents, {
2400
+ launcher,
2401
+ props,
2402
+ state
2403
+ }),
2404
+ showsDevtools && /* @__PURE__ */ jsx(Suspense, {
2405
+ fallback: null,
2406
+ children: /* @__PURE__ */ jsx(DevtoolsLayer, {
2407
+ isWidgetOpen: showsWidget && state.isOpen,
2408
+ position: props.position ?? "bottom-right",
2409
+ publicKey: state.publicKey
2410
+ })
2411
+ }),
2412
+ teamToolsKey && /* @__PURE__ */ jsx(TeamTools, {
2413
+ props,
2414
+ publicKey: teamToolsKey
2381
2415
  })
2382
- })]
2416
+ ]
2383
2417
  })] });
2384
2418
  }
2419
+ function TeamTools({ props, publicKey }) {
2420
+ const context = useContext(RefletContext);
2421
+ return /* @__PURE__ */ jsx(Suspense, {
2422
+ fallback: null,
2423
+ children: /* @__PURE__ */ jsx(TeamLayer, {
2424
+ connection: {
2425
+ apiUrl: props.baseUrl ?? context?.baseUrl ?? "https://harmless-clam-802.convex.site",
2426
+ appUrl: props.appUrl ?? DEFAULT_APP_URL,
2427
+ publicKey
2428
+ },
2429
+ position: props.position ?? "bottom-right"
2430
+ })
2431
+ });
2432
+ }
2385
2433
  function WidgetContents({ launcher, props, state }) {
2386
2434
  const labels = {
2387
2435
  ...DEFAULT_WIDGET_LABELS,