reflet-sdk 0.6.0 → 0.6.2

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.
@@ -1,4 +1,5 @@
1
1
  import { c as ElementSelection, u as FeedbackContext, w as RefletUser } from "./types-DnaDEN9Y.js";
2
+ import { ReactNode, RefObject } from "react";
2
3
  //#region src/feedback/types.d.ts
3
4
  declare const ANNOTATION_TOOLS: readonly ["pen", "arrow", "rectangle", "text", "spotlight", "highlight", "blur"];
4
5
  type AnnotationTool = (typeof ANNOTATION_TOOLS)[number];
@@ -10,7 +11,6 @@ interface Annotation {
10
11
  color: string;
11
12
  end: Point;
12
13
  id: string;
13
- /** Freehand path, in image pixels. Only set for the pen tool. */
14
14
  points?: Point[];
15
15
  start: Point;
16
16
  text?: string;
@@ -20,7 +20,6 @@ interface CapturedImage {
20
20
  blob: Blob;
21
21
  height: number;
22
22
  mimeType: string;
23
- /** Object URL owned by the caller — revoke it when the capture is dropped. */
24
23
  objectUrl: string;
25
24
  width: number;
26
25
  }
@@ -67,28 +66,20 @@ interface FeedbackWidgetLabels {
67
66
  trigger: string;
68
67
  undo: string;
69
68
  }
69
+ interface FeedbackTriggerProps {
70
+ onClick: () => void;
71
+ ref: RefObject<HTMLButtonElement | null>;
72
+ }
70
73
  interface RefletFeedbackProps {
71
- /** API base URL override. Falls back to the RefletProvider value. */
72
74
  baseUrl?: string;
73
- /** Record console errors and warnings to attach to bug reports. */
74
75
  captureConsole?: boolean;
75
- /** Take a screenshot of the viewport as soon as the panel opens. */
76
76
  captureOnOpen?: boolean;
77
- /**
78
- * Dev-only tools for your team: inspect an element's code, keep notes, read
79
- * the board for the current page. Never loaded outside `NODE_ENV=development`.
80
- */
81
77
  devtools?: boolean;
82
- /** Let reporters hide the launcher for this many days. */
83
78
  dismissForDays?: number;
84
- /** Render nothing when false — lets an app gate the widget per user. */
85
79
  enabled?: boolean;
86
- /** Keyboard shortcut opening the panel. Set to null to disable. */
87
80
  hotkey?: string | null;
88
81
  labels?: Partial<FeedbackWidgetLabels>;
89
- /** Extra fields merged into the reported context. */
90
82
  metadata?: Record<string, string>;
91
- /** Distance in px from the viewport edges. */
92
83
  offset?: number;
93
84
  onClose?: () => void;
94
85
  onDismiss?: (result: {
@@ -101,6 +92,7 @@ interface RefletFeedbackProps {
101
92
  position?: "bottom-left" | "bottom-right" | "top-left" | "top-right";
102
93
  primaryColor?: string;
103
94
  publicKey?: string;
95
+ renderTrigger?: (props: FeedbackTriggerProps) => ReactNode;
104
96
  theme?: "auto" | "dark" | "light";
105
97
  user?: RefletUser;
106
98
  userToken?: string;
@@ -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;;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;;;wBCtEY,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;;UAgDe;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;;;;UCmEe;;EAEf,UAAU;EACV;EACA;;EAEA;;;;;;;;;;wBA2GoB,gBACpB,UAAS,iBACR,QAAQ;wBAiDK,eAAe,OAAO;;;;wBCjHtB,sBAAsB,SAAS,UAAU;;;;wBCjMzC,mBAAmB;EACjC;IACE;;;wBCnEY,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-DAdWdIFY.js";
3
- import { A as TargetIcon, B as buildElementSelection, C as GripIcon, D as SpotlightIcon, E as PencilIcon, F as normalizeRect, G as WIDGET_MARKER, I as DEFAULT_WIDGET_LABELS, J as releaseCapture, K as captureViewport, L as SDK_VERSION, M as TrashIcon, N as UndoIcon, O as SquareIcon, P as isDegenerate, R as collectPageContext, S as CloseIcon, T as MoreIcon, _ as BlurIcon, b as CheckIcon, d as SelectionOutline, f as drawAnnotations, g as ArrowIcon, h as stopClicksAtHost, j as TextIcon, l as submitWidgetFeedback, m as listenToKeydown, o as attachPreparedScreenshots, p as listenOnPageAndWidget, r as useFloatingPosition, s as createFeedbackTransport, t as ElementPicker, v as CameraIcon, w as HighlightIcon, x as ChevronDownIcon, y as ChatIcon, z as MAX_SELECTION_COMMENT_LENGTH } from "./picker-C7TkZcBE.js";
3
+ import { A as TargetIcon, B as buildElementSelection, C as GripIcon, D as SpotlightIcon, E as PencilIcon, F as normalizeRect, G as WIDGET_MARKER, I as DEFAULT_WIDGET_LABELS, J as releaseCapture, K as captureViewport, L as SDK_VERSION, M as TrashIcon, N as UndoIcon, O as SquareIcon, P as isDegenerate, R as collectPageContext, S as CloseIcon, T as MoreIcon, _ as BlurIcon, b as CheckIcon, c as useFloatingPosition, d as SelectionOutline, f as drawAnnotations, g as ArrowIcon, h as stopClicksAtHost, i as createFeedbackTransport, j as TextIcon, m as listenToKeydown, o as submitWidgetFeedback, p as listenOnPageAndWidget, r as attachPreparedScreenshots, t as ElementPicker, v as CameraIcon, w as HighlightIcon, x as ChevronDownIcon, y as ChatIcon, z as MAX_SELECTION_COMMENT_LENGTH } from "./picker-DCoAFX5y.js";
4
4
  import { n as RefletContext, t as REFLET_Z_INDEX } from "./z-index-BL0SGZEP.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";
@@ -1640,7 +1640,7 @@ function useWidgetState(props) {
1640
1640
  setStep("compose");
1641
1641
  return submission.submit({
1642
1642
  context: {
1643
- ...activeScreenshot?.context ?? collectPageContext({ sdkVersion: "0.6.0" }),
1643
+ ...activeScreenshot?.context ?? collectPageContext({ sdkVersion: "0.6.2" }),
1644
1644
  consoleEvents: consoleRef.current?.events(),
1645
1645
  metadata: props.metadata,
1646
1646
  selections
@@ -1705,94 +1705,141 @@ function useWidgetState(props) {
1705
1705
  };
1706
1706
  }
1707
1707
  //#endregion
1708
- //#region src/feedback/ui/floating/floating-widget.tsx
1709
- function FloatingWidget({ hotkey, labels, position, state }) {
1710
- const [minimized, setMinimized] = useState(false);
1711
- const launcherRef = useRef(null);
1712
- const showPanel = state.isOpen && !minimized;
1713
- const floating = useFloatingPosition(position, showPanel);
1714
- const minimize = () => {
1715
- setMinimized(true);
1716
- requestAnimationFrame(() => launcherRef.current?.focus());
1717
- };
1708
+ //#region src/feedback/ui/floating/use-floating-widget-keyboard.ts
1709
+ function useFloatingWidgetKeyboard(options) {
1710
+ const { anchorRef, hotkey, launcher, showPanel, state } = options;
1718
1711
  useEffect(() => {
1719
1712
  if (state.step === "compose") state.annotationTrigger?.button.focus({ preventScroll: true });
1720
1713
  }, [state.step, state.annotationTrigger]);
1714
+ const minimize = launcher.minimize;
1721
1715
  useEffect(() => {
1722
1716
  if (!showPanel || state.step !== "compose") return;
1723
- const onKeyDown = (event) => {
1724
- if (event.key === "Escape" && !event.defaultPrevented) {
1725
- setMinimized(true);
1726
- requestAnimationFrame(() => launcherRef.current?.focus());
1727
- }
1728
- };
1729
- return listenToKeydown(floating.rootRef.current, onKeyDown);
1717
+ return listenToKeydown(anchorRef.current, (event) => {
1718
+ if (event.key === "Escape" && !event.defaultPrevented) minimize();
1719
+ });
1730
1720
  }, [
1731
- floating.rootRef,
1721
+ anchorRef,
1722
+ minimize,
1732
1723
  showPanel,
1733
1724
  state.step
1734
1725
  ]);
1735
- const { close, isOpen, open } = state;
1726
+ useWidgetHotkey({
1727
+ anchorRef,
1728
+ hotkey,
1729
+ launcher,
1730
+ state
1731
+ });
1732
+ }
1733
+ function useWidgetHotkey({ anchorRef, hotkey, launcher, state }) {
1734
+ const { close, isOpen } = state;
1735
+ const open = launcher.triggerProps.onClick;
1736
1736
  useEffect(() => {
1737
1737
  if (!hotkey) return;
1738
- const toggleOnHotkey = (event) => {
1738
+ return listenToKeydown(anchorRef.current, (event) => {
1739
1739
  if (matchesHotkey(event, hotkey)) {
1740
1740
  event.preventDefault();
1741
1741
  if (isOpen) close();
1742
1742
  else open();
1743
1743
  }
1744
- };
1745
- return listenToKeydown(floating.rootRef.current, toggleOnHotkey, true);
1744
+ }, true);
1746
1745
  }, [
1746
+ anchorRef,
1747
1747
  close,
1748
- floating.rootRef,
1749
1748
  hotkey,
1750
1749
  isOpen,
1751
1750
  open
1752
1751
  ]);
1752
+ }
1753
+ //#endregion
1754
+ //#region src/feedback/ui/floating/floating-widget.tsx
1755
+ function FloatingWidget({ config, launcher, state }) {
1756
+ const { hotkey, position } = config;
1757
+ const showPanel = state.isOpen && !launcher.minimized;
1758
+ const floating = useFloatingPosition(position, showPanel);
1759
+ useFloatingWidgetKeyboard({
1760
+ anchorRef: floating.rootRef,
1761
+ hotkey,
1762
+ launcher,
1763
+ showPanel,
1764
+ state
1765
+ });
1753
1766
  return /* @__PURE__ */ jsxs("div", {
1754
1767
  className: "root",
1755
1768
  "data-editing": state.isOpen && (state.step === "picking" || state.step === "annotate"),
1756
1769
  "data-moved": Boolean(floating.position),
1757
1770
  "data-position": position,
1758
1771
  ref: floating.rootRef,
1759
- children: [
1760
- /* @__PURE__ */ jsx("style", { children: floating.styles }),
1761
- showPanel && state.step === "compose" && state.screenshots.map(({ id, selectedNode }) => selectedNode ? /* @__PURE__ */ jsx(SelectionOutline, { node: selectedNode }, id) : null),
1762
- showPanel ? /* @__PURE__ */ jsx(FeedbackPanel, {
1763
- floatingControls: /* @__PURE__ */ jsxs("div", {
1764
- className: "floating-controls",
1765
- children: [/* @__PURE__ */ jsx("button", {
1766
- "aria-label": labels.moveFeedback,
1767
- className: "icon-btn drag-handle",
1768
- title: labels.moveFeedback,
1769
- type: "button",
1770
- ...floating.handleProps,
1771
- children: /* @__PURE__ */ jsx(GripIcon, {})
1772
- }), /* @__PURE__ */ jsx("button", {
1773
- "aria-label": labels.minimize,
1774
- className: "icon-btn",
1775
- onClick: minimize,
1776
- title: labels.minimize,
1777
- type: "button",
1778
- children: /* @__PURE__ */ jsx(CloseIcon, {})
1779
- })]
1780
- }),
1781
- labels,
1772
+ children: [/* @__PURE__ */ jsx("style", { children: floating.styles }), /* @__PURE__ */ jsx(FloatingComposer, {
1773
+ config,
1774
+ launcher,
1775
+ panel: {
1776
+ floating,
1777
+ showPanel,
1782
1778
  state
1783
- }) : /* @__PURE__ */ jsx(Launcher, {
1784
- buttonRef: launcherRef,
1785
- isOpen: false,
1786
- label: state.isOpen ? labels.resume : labels.trigger,
1787
- onClick: () => {
1788
- setMinimized(false);
1789
- if (!state.isOpen) state.open();
1790
- }
1791
- })
1792
- ]
1779
+ }
1780
+ })]
1781
+ });
1782
+ }
1783
+ function FloatingComposer({ config, launcher, panel }) {
1784
+ const { labels } = config;
1785
+ const { floating, showPanel, state } = panel;
1786
+ if (!showPanel) return launcher.custom ? null : /* @__PURE__ */ jsx(Launcher, {
1787
+ buttonRef: launcher.triggerProps.ref,
1788
+ isOpen: false,
1789
+ label: state.isOpen ? labels.resume : labels.trigger,
1790
+ onClick: launcher.triggerProps.onClick
1791
+ });
1792
+ return /* @__PURE__ */ jsxs(Fragment, { children: [state.step === "compose" && state.screenshots.map(({ id, selectedNode }) => selectedNode ? /* @__PURE__ */ jsx(SelectionOutline, { node: selectedNode }, id) : null), /* @__PURE__ */ jsx(FeedbackPanel, {
1793
+ floatingControls: /* @__PURE__ */ jsx(FloatingControls, {
1794
+ floating,
1795
+ labels,
1796
+ minimize: launcher.minimize
1797
+ }),
1798
+ labels,
1799
+ state
1800
+ })] });
1801
+ }
1802
+ function FloatingControls({ labels, floating, minimize }) {
1803
+ return /* @__PURE__ */ jsxs("div", {
1804
+ className: "floating-controls",
1805
+ children: [/* @__PURE__ */ jsx("button", {
1806
+ "aria-label": labels.moveFeedback,
1807
+ className: "icon-btn drag-handle",
1808
+ title: labels.moveFeedback,
1809
+ type: "button",
1810
+ ...floating.handleProps,
1811
+ children: /* @__PURE__ */ jsx(GripIcon, {})
1812
+ }), /* @__PURE__ */ jsx("button", {
1813
+ "aria-label": labels.minimize,
1814
+ className: "icon-btn",
1815
+ onClick: minimize,
1816
+ title: labels.minimize,
1817
+ type: "button",
1818
+ children: /* @__PURE__ */ jsx(CloseIcon, {})
1819
+ })]
1793
1820
  });
1794
1821
  }
1795
1822
  //#endregion
1823
+ //#region src/feedback/ui/floating/use-widget-launcher.ts
1824
+ function useWidgetLauncher(state) {
1825
+ const [minimized, setMinimized] = useState(false);
1826
+ const triggerRef = useRef(null);
1827
+ return {
1828
+ minimize: () => {
1829
+ setMinimized(true);
1830
+ requestAnimationFrame(() => triggerRef.current?.focus());
1831
+ },
1832
+ minimized,
1833
+ triggerProps: {
1834
+ onClick: () => {
1835
+ setMinimized(false);
1836
+ if (!state.isOpen) state.open();
1837
+ },
1838
+ ref: triggerRef
1839
+ }
1840
+ };
1841
+ }
1842
+ //#endregion
1796
1843
  //#region src/feedback/ui/annotation/styles.ts
1797
1844
  const ANNOTATOR_STYLES = `
1798
1845
  .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; }
@@ -2252,7 +2299,7 @@ svg { flex-shrink: 0; }
2252
2299
  }
2253
2300
  .capture-halo { position: fixed; inset: 0; z-index: ${REFLET_Z_INDEX.captureHalo}; pointer-events: none; opacity: 0; transition: opacity 500ms var(--rf-ease); }
2254
2301
  .capture-halo[data-active="true"] { opacity: 1; transition-duration: 140ms; }
2255
- .capture-halo::before { content: ""; position: absolute; inset: 0; border-radius: 20px; box-shadow: inset 14px 0 36px -16px var(--rf-accent), inset -14px 0 36px -16px var(--rf-accent), inset 0 0 4px 1px color-mix(in srgb, var(--rf-accent) 35%, transparent); }
2302
+ .capture-halo::before { content: ""; position: absolute; inset: 0; box-shadow: inset 14px 0 36px -16px var(--rf-accent), inset -14px 0 36px -16px var(--rf-accent), inset 0 0 4px 1px color-mix(in srgb, var(--rf-accent) 35%, transparent); }
2256
2303
  .capture-halo::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, color-mix(in srgb, var(--rf-accent) 20%, transparent), transparent 5%, transparent 95%, color-mix(in srgb, var(--rf-accent) 20%, transparent)); }
2257
2304
  ${COMPOSER_STYLES}
2258
2305
  ${ANNOTATOR_STYLES}
@@ -2315,52 +2362,64 @@ function ShadowPortal({ children, offset, primaryColor, theme }) {
2315
2362
  }
2316
2363
  //#endregion
2317
2364
  //#region src/feedback/widget.tsx
2318
- const DevtoolsLayer = process.env.NODE_ENV === "development" ? lazy(() => import("./devtools-layer-D_0UL_Wd.js").then((module) => ({ default: module.DevtoolsLayer }))) : null;
2365
+ const DevtoolsLayer = process.env.NODE_ENV === "development" ? lazy(() => import("./devtools-layer-DOECMj0S.js").then((module) => ({ default: module.DevtoolsLayer }))) : null;
2319
2366
  function RefletFeedback(props) {
2320
- const { devtools = true, enabled = true, hotkey = null, offset = 20, position = "bottom-right", theme = "auto" } = props;
2321
- const labels = {
2322
- ...DEFAULT_WIDGET_LABELS,
2323
- ...props.labels
2324
- };
2325
2367
  const state = useWidgetState(props);
2326
- const { isOpen } = state;
2327
- const showsWidget = enabled && !state.isDismissed;
2328
- const showsDevtools = useOwnsDevtools(devtools && DevtoolsLayer !== null, showsWidget) && DevtoolsLayer !== null;
2368
+ const launcher = useWidgetLauncher(state);
2369
+ const showsWidget = props.enabled !== false && !state.isDismissed;
2370
+ const showsDevtools = useOwnsDevtools(props.devtools !== false && DevtoolsLayer !== null, showsWidget) && DevtoolsLayer !== null;
2329
2371
  if (!(showsWidget || showsDevtools)) return null;
2330
- return /* @__PURE__ */ jsxs(ShadowPortal, {
2331
- offset,
2372
+ return /* @__PURE__ */ jsxs(Fragment, { children: [showsWidget && props.renderTrigger?.(launcher.triggerProps), /* @__PURE__ */ jsxs(ShadowPortal, {
2373
+ offset: props.offset ?? 20,
2332
2374
  primaryColor: props.primaryColor,
2333
- theme,
2334
- children: [showsWidget && /* @__PURE__ */ jsxs(Fragment, { children: [
2335
- /* @__PURE__ */ jsx("div", {
2336
- "aria-hidden": "true",
2337
- className: "capture-halo",
2338
- "data-active": state.isCapturing
2339
- }),
2340
- /* @__PURE__ */ jsx(FloatingWidget, {
2341
- hotkey,
2342
- labels,
2343
- position,
2344
- state
2345
- }),
2346
- /* @__PURE__ */ jsx(WidgetAnnotation, {
2347
- labels,
2348
- state
2349
- }),
2350
- isOpen && state.step === "picking" && /* @__PURE__ */ jsx(ElementPicker, {
2351
- labels,
2352
- onCancel: () => state.setStep("compose"),
2353
- onPick: state.selectElement
2354
- })
2355
- ] }), showsDevtools && /* @__PURE__ */ jsx(Suspense, {
2375
+ theme: props.theme ?? "auto",
2376
+ children: [showsWidget && /* @__PURE__ */ jsx(WidgetContents, {
2377
+ launcher,
2378
+ props,
2379
+ state
2380
+ }), showsDevtools && /* @__PURE__ */ jsx(Suspense, {
2356
2381
  fallback: null,
2357
2382
  children: /* @__PURE__ */ jsx(DevtoolsLayer, {
2358
- isWidgetOpen: showsWidget && isOpen,
2359
- position,
2383
+ isWidgetOpen: showsWidget && state.isOpen,
2384
+ position: props.position ?? "bottom-right",
2360
2385
  publicKey: state.publicKey
2361
2386
  })
2362
2387
  })]
2363
- });
2388
+ })] });
2389
+ }
2390
+ function WidgetContents({ launcher, props, state }) {
2391
+ const labels = {
2392
+ ...DEFAULT_WIDGET_LABELS,
2393
+ ...props.labels
2394
+ };
2395
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2396
+ /* @__PURE__ */ jsx("div", {
2397
+ "aria-hidden": "true",
2398
+ className: "capture-halo",
2399
+ "data-active": state.isCapturing
2400
+ }),
2401
+ /* @__PURE__ */ jsx(FloatingWidget, {
2402
+ config: {
2403
+ hotkey: props.hotkey ?? null,
2404
+ labels,
2405
+ position: props.position ?? "bottom-right"
2406
+ },
2407
+ launcher: {
2408
+ ...launcher,
2409
+ custom: Boolean(props.renderTrigger)
2410
+ },
2411
+ state
2412
+ }),
2413
+ /* @__PURE__ */ jsx(WidgetAnnotation, {
2414
+ labels,
2415
+ state
2416
+ }),
2417
+ state.isOpen && state.step === "picking" && /* @__PURE__ */ jsx(ElementPicker, {
2418
+ labels,
2419
+ onCancel: () => state.setStep("compose"),
2420
+ onPick: state.selectElement
2421
+ })
2422
+ ] });
2364
2423
  }
2365
2424
  function WidgetAnnotation({ labels, state }) {
2366
2425
  const screenshot = state.activeScreenshot;