reflet-sdk 0.6.5 → 0.6.7

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-CEjzYGBB.js → devtools-layer-OjTo9_eb.js} +417 -916
  8. package/dist/devtools-layer-OjTo9_eb.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-CkxIekZX.js +6010 -0
  35. package/dist/sessions-panel-CkxIekZX.js.map +1 -0
  36. package/dist/{submit-MvVjNdYc.js → submit-DZX0f2_0.js} +44 -70
  37. package/dist/submit-DZX0f2_0.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-DyyGqmxs.js +423 -0
  43. package/dist/team-layer-DyyGqmxs.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-CEjzYGBB.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-MvVjNdYc.js.map +0 -1
  59. package/dist/types-DnaDEN9Y.d.ts.map +0 -1
@@ -0,0 +1,423 @@
1
+ import { l as sessionApiErrorSchema } from "./protocol-vJhQHTcB.js";
2
+ import { n as teamAccessStorageKey } from "./team-activation-DCqh71bl.js";
3
+ import { _ as teamTransport, a as DevtoolsBar, d as PersonIcon, f as SessionWorkspaceProvider, h as purgeAccount, i as BarButton, j as reportFailure, k as Notices, l as SESSIONS_STYLES, m as useWorkspaceLoader, n as DEVTOOLS_STYLES, p as failureMessage, r as DevtoolsSheet, s as SessionsBarButton, t as SessionsPanel, u as RecordingLayer } from "./sessions-panel-CkxIekZX.js";
4
+ import { z } from "zod";
5
+ import { useState } from "react";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/sessions/team/team-auth.ts
8
+ const TEAM_ACCESS_MESSAGE_TYPE = "reflet:team-access";
9
+ const POPUP_NAME = "reflet-team-access";
10
+ const POPUP_WIDTH_PX = 480;
11
+ const POPUP_HEIGHT_PX = 680;
12
+ const POPUP_CLOSED_POLL_MS = 500;
13
+ const SIGN_IN_TIMEOUT_MS = 3e5;
14
+ const PKCE_RANDOM_BYTES = 32;
15
+ const TRAILING_SLASHES = /\/+$/;
16
+ const BASE64_PADDING = /[=]+$/;
17
+ const teamAccessSchema = z.object({
18
+ expiresAt: z.number(),
19
+ organizationName: z.string(),
20
+ token: z.string().startsWith("fb_team_")
21
+ });
22
+ const teamAccessMessageSchema = z.union([z.object({
23
+ code: z.string().min(1),
24
+ state: z.string(),
25
+ type: z.literal(TEAM_ACCESS_MESSAGE_TYPE)
26
+ }), z.object({
27
+ error: z.literal("cancelled"),
28
+ state: z.string(),
29
+ type: z.literal(TEAM_ACCESS_MESSAGE_TYPE)
30
+ })]);
31
+ const SIGN_IN_FAILURE_MESSAGES = {
32
+ cancelled: "Sign-in was cancelled.",
33
+ exchange_failed: "Couldn't finish signing in to Reflet. Try again.",
34
+ popup_blocked: "Your browser blocked the Reflet sign-in window. Allow pop-ups for this site, then try again.",
35
+ timeout: "Signing in took too long. Try again."
36
+ };
37
+ var TeamSignInError = class extends Error {
38
+ reason;
39
+ constructor(reason, message) {
40
+ super(message ?? SIGN_IN_FAILURE_MESSAGES[reason]);
41
+ this.name = "TeamSignInError";
42
+ this.reason = reason;
43
+ }
44
+ };
45
+ function base64Url(bytes) {
46
+ return btoa(String.fromCharCode(...bytes)).replaceAll("+", "-").replaceAll("/", "_").replace(BASE64_PADDING, "");
47
+ }
48
+ function randomBase64Url() {
49
+ return base64Url(crypto.getRandomValues(new Uint8Array(PKCE_RANDOM_BYTES)));
50
+ }
51
+ async function pkceChallengeFor(codeVerifier) {
52
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(codeVerifier));
53
+ return base64Url(new Uint8Array(digest));
54
+ }
55
+ function apiEndpoint(apiUrl, path) {
56
+ return `${apiUrl.replace(TRAILING_SLASHES, "")}${path}`;
57
+ }
58
+ function parseStoredJson(raw) {
59
+ try {
60
+ return JSON.parse(raw);
61
+ } catch {
62
+ return null;
63
+ }
64
+ }
65
+ function storedTeamAccess(publicKey) {
66
+ try {
67
+ const raw = localStorage.getItem(teamAccessStorageKey(publicKey));
68
+ const parsed = teamAccessSchema.safeParse(raw === null ? null : parseStoredJson(raw));
69
+ return parsed.success ? parsed.data : null;
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+ function persistTeamAccess(publicKey, access) {
75
+ try {
76
+ if (access) localStorage.setItem(teamAccessStorageKey(publicKey), JSON.stringify(access));
77
+ else localStorage.removeItem(teamAccessStorageKey(publicKey));
78
+ } catch {}
79
+ }
80
+ function readTeamAccess(publicKey) {
81
+ const access = storedTeamAccess(publicKey);
82
+ if (access && access.expiresAt > Date.now()) return access;
83
+ persistTeamAccess(publicKey, null);
84
+ return null;
85
+ }
86
+ function centeredPopupFeatures() {
87
+ const left = Math.round(window.screenX + (window.outerWidth - POPUP_WIDTH_PX) / 2);
88
+ const top = Math.round(window.screenY + (window.outerHeight - POPUP_HEIGHT_PX) / 2);
89
+ return `popup,width=${POPUP_WIDTH_PX},height=${POPUP_HEIGHT_PX},left=${left},top=${top}`;
90
+ }
91
+ function waitForApprovedCode(options) {
92
+ return new Promise((resolve, reject) => {
93
+ const listening = new AbortController();
94
+ let closedOnLastPoll = false;
95
+ const settle = (outcome) => {
96
+ listening.abort();
97
+ window.clearInterval(closedPoll);
98
+ window.clearTimeout(timeout);
99
+ if (outcome instanceof TeamSignInError) reject(outcome);
100
+ else resolve(outcome.code);
101
+ };
102
+ const closedPoll = window.setInterval(() => {
103
+ if (closedOnLastPoll) settle(new TeamSignInError("cancelled"));
104
+ closedOnLastPoll = options.popup.closed;
105
+ }, POPUP_CLOSED_POLL_MS);
106
+ const timeout = window.setTimeout(() => {
107
+ options.popup.close();
108
+ settle(new TeamSignInError("timeout"));
109
+ }, SIGN_IN_TIMEOUT_MS);
110
+ window.addEventListener("message", (event) => {
111
+ if (event.origin !== options.appOrigin) return;
112
+ const message = teamAccessMessageSchema.safeParse(event.data);
113
+ if (message.success && message.data.state === options.state) settle("code" in message.data ? { code: message.data.code } : new TeamSignInError("cancelled"));
114
+ }, { signal: listening.signal });
115
+ });
116
+ }
117
+ async function exchangeCode(options) {
118
+ const response = await fetch(apiEndpoint(options.apiUrl, "/api/v1/team/token"), {
119
+ body: JSON.stringify({
120
+ code: options.code,
121
+ codeVerifier: options.codeVerifier
122
+ }),
123
+ headers: { "Content-Type": "application/json" },
124
+ method: "POST"
125
+ });
126
+ if (!response.ok) {
127
+ const failure = sessionApiErrorSchema.safeParse(await response.json().catch(() => null));
128
+ throw new TeamSignInError("exchange_failed", failure.success ? failure.data.error : void 0);
129
+ }
130
+ const access = teamAccessSchema.safeParse(await response.json().catch(() => null));
131
+ if (!access.success) throw new TeamSignInError("exchange_failed");
132
+ return access.data;
133
+ }
134
+ /** Call from a click handler: the popup opens before anything is awaited so browsers don't block it. */
135
+ async function signInTeam(options) {
136
+ const popup = window.open("about:blank", POPUP_NAME, centeredPopupFeatures());
137
+ if (!popup) throw new TeamSignInError("popup_blocked");
138
+ const codeVerifier = randomBase64Url();
139
+ const state = randomBase64Url();
140
+ const consentUrl = new URL("/auth/team", options.appUrl);
141
+ consentUrl.search = new URLSearchParams({
142
+ code_challenge: await pkceChallengeFor(codeVerifier),
143
+ origin: window.location.origin,
144
+ public_key: options.publicKey,
145
+ state
146
+ }).toString();
147
+ popup.location.href = consentUrl.href;
148
+ const code = await waitForApprovedCode({
149
+ appOrigin: consentUrl.origin,
150
+ popup,
151
+ state
152
+ });
153
+ const access = await exchangeCode({
154
+ apiUrl: options.apiUrl,
155
+ code,
156
+ codeVerifier
157
+ });
158
+ persistTeamAccess(options.publicKey, access);
159
+ return access;
160
+ }
161
+ async function forgetTeamAccess(options) {
162
+ const access = storedTeamAccess(options.publicKey);
163
+ persistTeamAccess(options.publicKey, null);
164
+ if (!access) return;
165
+ await fetch(apiEndpoint(options.apiUrl, "/api/v1/team/revoke"), {
166
+ headers: { Authorization: `Bearer ${access.token}` },
167
+ method: "POST"
168
+ });
169
+ }
170
+ //#endregion
171
+ //#region src/sessions/team/team-sign-in-card.tsx
172
+ function useTeamSignIn(connection, onSignedIn) {
173
+ const [isSigningIn, setIsSigningIn] = useState(false);
174
+ const [failure, setFailure] = useState(null);
175
+ const signIn = async () => {
176
+ setIsSigningIn(true);
177
+ setFailure(null);
178
+ try {
179
+ onSignedIn(await signInTeam(connection));
180
+ } catch (error) {
181
+ setFailure(failureMessage(error));
182
+ }
183
+ setIsSigningIn(false);
184
+ };
185
+ return {
186
+ failure,
187
+ isSigningIn,
188
+ signIn
189
+ };
190
+ }
191
+ function SignInActions({ isSigningIn, onHide, onSignIn }) {
192
+ return /* @__PURE__ */ jsxs("div", {
193
+ className: "dt-actions",
194
+ children: [/* @__PURE__ */ jsx("button", {
195
+ className: "dt-btn",
196
+ "data-variant": "primary",
197
+ disabled: isSigningIn,
198
+ onClick: onSignIn,
199
+ type: "button",
200
+ children: "Sign in with Reflet"
201
+ }), /* @__PURE__ */ jsx("button", {
202
+ className: "dt-btn",
203
+ onClick: onHide,
204
+ type: "button",
205
+ children: "Hide"
206
+ })]
207
+ });
208
+ }
209
+ function TeamSignInCard({ connection, notice, onSignedIn }) {
210
+ const [isHidden, setIsHidden] = useState(false);
211
+ const { failure, isSigningIn, signIn } = useTeamSignIn(connection, onSignedIn);
212
+ if (isHidden) return null;
213
+ return /* @__PURE__ */ jsxs("section", {
214
+ "aria-labelledby": "rf-team-title",
215
+ className: "dt-team-card glass",
216
+ children: [
217
+ /* @__PURE__ */ jsx("h2", {
218
+ className: "dt-ses-subhead",
219
+ id: "rf-team-title",
220
+ children: "Reflet team tools"
221
+ }),
222
+ /* @__PURE__ */ jsx("p", {
223
+ className: "dt-meta",
224
+ children: "Sign in with your Reflet account to record a session on this app."
225
+ }),
226
+ /* @__PURE__ */ jsx("p", {
227
+ className: "dt-meta",
228
+ children: "Only members of the app's Reflet organization can sign in."
229
+ }),
230
+ notice && /* @__PURE__ */ jsx("p", {
231
+ className: "dt-meta",
232
+ children: notice
233
+ }),
234
+ failure && /* @__PURE__ */ jsx("p", {
235
+ className: "dt-error",
236
+ role: "alert",
237
+ children: failure
238
+ }),
239
+ /* @__PURE__ */ jsx(SignInActions, {
240
+ isSigningIn,
241
+ onHide: () => setIsHidden(true),
242
+ onSignIn: signIn
243
+ })
244
+ ]
245
+ });
246
+ }
247
+ //#endregion
248
+ //#region src/sessions/team/team-layer.tsx
249
+ const TEAM_TOOLS_LABEL = "Reflet team tools";
250
+ const REFUSED_SIGN_IN_COPY = "Reflet no longer accepts this sign-in. Sign in again to record.";
251
+ function AccountControls({ access, onSignOut, workspace }) {
252
+ const [isOpen, setIsOpen] = useState(false);
253
+ const user = workspace?.account.userName ?? workspace?.account.userEmail;
254
+ const label = user ? `Signed in as ${user} · ${access.organizationName}` : `Signed in · ${access.organizationName}`;
255
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(BarButton, {
256
+ label,
257
+ onClick: () => setIsOpen(!isOpen),
258
+ pressed: isOpen,
259
+ children: /* @__PURE__ */ jsx(PersonIcon, {})
260
+ }), isOpen && /* @__PURE__ */ jsx("button", {
261
+ className: "dt-btn",
262
+ onClick: onSignOut,
263
+ type: "button",
264
+ children: "Sign out"
265
+ })] });
266
+ }
267
+ function SessionsBody({ navigation, onStarted, state }) {
268
+ if (state.kind === "ready") return /* @__PURE__ */ jsx(SessionsPanel, {
269
+ navigation,
270
+ onStarted
271
+ });
272
+ if (state.kind === "failed") return /* @__PURE__ */ jsxs("div", {
273
+ className: "dt-empty",
274
+ role: "alert",
275
+ children: [/* @__PURE__ */ jsxs("p", { children: ["Sessions did not open: ", state.message] }), /* @__PURE__ */ jsx("button", {
276
+ className: "dt-btn",
277
+ onClick: state.retry,
278
+ type: "button",
279
+ children: "Try again"
280
+ })]
281
+ });
282
+ return /* @__PURE__ */ jsx("p", {
283
+ className: "dt-status",
284
+ children: "Opening your sessions…"
285
+ });
286
+ }
287
+ function TeamSheet({ navigation, onOpenChange, side, state }) {
288
+ return /* @__PURE__ */ jsx(DevtoolsSheet, {
289
+ label: TEAM_TOOLS_LABEL,
290
+ onClose: () => onOpenChange(false),
291
+ onSelectTab: () => onOpenChange(true),
292
+ side,
293
+ tab: "sessions",
294
+ tabs: ["sessions"],
295
+ children: /* @__PURE__ */ jsx(SessionsBody, {
296
+ navigation,
297
+ onStarted: () => onOpenChange(false),
298
+ state
299
+ })
300
+ });
301
+ }
302
+ function useTeamTransport(team) {
303
+ const createTransport = () => ({
304
+ apiUrl: team.apiUrl,
305
+ transport: teamTransport({
306
+ apiUrl: team.apiUrl,
307
+ token: team.access.token
308
+ })
309
+ });
310
+ const [current, setCurrent] = useState(createTransport);
311
+ if (current.apiUrl !== team.apiUrl) {
312
+ const next = createTransport();
313
+ setCurrent(next);
314
+ return next.transport;
315
+ }
316
+ return current.transport;
317
+ }
318
+ function useTeamWorkspace(team) {
319
+ const { onSignOut } = team;
320
+ const transport = useTeamTransport(team);
321
+ const state = useWorkspaceLoader({
322
+ onUnauthorized: () => onSignOut(REFUSED_SIGN_IN_COPY),
323
+ surface: "app",
324
+ transport
325
+ });
326
+ const workspace = state.kind === "ready" ? state.workspace : null;
327
+ const signOut = async () => {
328
+ if (workspace) await purgeAccount(workspace.account.key).catch((error) => reportFailure("This device's session data was not removed", error));
329
+ onSignOut(null);
330
+ };
331
+ return {
332
+ signOut,
333
+ state,
334
+ workspace
335
+ };
336
+ }
337
+ function TeamTools({ team, placement }) {
338
+ const { signOut, state, workspace } = useTeamWorkspace(team);
339
+ const [isSheetOpen, setIsSheetOpen] = useState(false);
340
+ const [open, setOpen] = useState(null);
341
+ return /* @__PURE__ */ jsxs(SessionWorkspaceProvider, {
342
+ workspace,
343
+ children: [
344
+ isSheetOpen && /* @__PURE__ */ jsx(TeamSheet, {
345
+ navigation: {
346
+ onOpen: setOpen,
347
+ open
348
+ },
349
+ onOpenChange: setIsSheetOpen,
350
+ side: placement.side,
351
+ state
352
+ }),
353
+ /* @__PURE__ */ jsxs(DevtoolsBar, {
354
+ edge: placement.edge,
355
+ label: TEAM_TOOLS_LABEL,
356
+ side: placement.side,
357
+ children: [/* @__PURE__ */ jsx(SessionsBarButton, {
358
+ isOpen: isSheetOpen,
359
+ onToggle: () => setIsSheetOpen(!isSheetOpen)
360
+ }), /* @__PURE__ */ jsx(AccountControls, {
361
+ access: team.access,
362
+ onSignOut: signOut,
363
+ workspace
364
+ })]
365
+ }),
366
+ workspace && /* @__PURE__ */ jsx(RecordingLayer, { onFinished: (target) => {
367
+ setOpen(target);
368
+ setIsSheetOpen(true);
369
+ } })
370
+ ]
371
+ });
372
+ }
373
+ function placementFor(position) {
374
+ return {
375
+ edge: position.startsWith("top") ? "top" : "bottom",
376
+ side: position.endsWith("right") ? "right" : "left"
377
+ };
378
+ }
379
+ function TeamLayer({ connection, position }) {
380
+ const { apiUrl, publicKey } = connection;
381
+ const [access, setAccess] = useState(() => readTeamAccess(publicKey));
382
+ const [notice, setNotice] = useState(null);
383
+ const signOut = (reason) => {
384
+ setAccess(null);
385
+ setNotice(reason);
386
+ forgetTeamAccess({
387
+ apiUrl,
388
+ publicKey
389
+ }).catch((error) => reportFailure("Signing out of Reflet did not finish", error));
390
+ };
391
+ const placement = placementFor(position);
392
+ return /* @__PURE__ */ jsxs("div", {
393
+ className: "dt",
394
+ children: [
395
+ /* @__PURE__ */ jsx("style", { children: `${DEVTOOLS_STYLES}${SESSIONS_STYLES}` }),
396
+ access ? /* @__PURE__ */ jsx(TeamTools, {
397
+ placement,
398
+ team: {
399
+ access,
400
+ apiUrl,
401
+ onSignOut: signOut
402
+ }
403
+ }) : /* @__PURE__ */ jsx("div", {
404
+ className: "dt-team-anchor",
405
+ "data-edge": placement.edge,
406
+ "data-side": placement.side,
407
+ children: /* @__PURE__ */ jsx(TeamSignInCard, {
408
+ connection,
409
+ notice,
410
+ onSignedIn: (signedIn) => {
411
+ setAccess(signedIn);
412
+ setNotice(null);
413
+ }
414
+ })
415
+ }),
416
+ /* @__PURE__ */ jsx(Notices, {})
417
+ ]
418
+ });
419
+ }
420
+ //#endregion
421
+ export { TeamLayer };
422
+
423
+ //# sourceMappingURL=team-layer-DyyGqmxs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-layer-DyyGqmxs.js","names":[],"sources":["../src/sessions/team/team-auth.ts","../src/sessions/team/team-sign-in-card.tsx","../src/sessions/team/team-layer.tsx"],"sourcesContent":["import { z } from \"zod\";\nimport { sessionApiErrorSchema } from \"../protocol\";\nimport { teamAccessStorageKey } from \"./team-activation\";\n\nconst TEAM_ACCESS_MESSAGE_TYPE = \"reflet:team-access\";\nconst POPUP_NAME = \"reflet-team-access\";\nconst POPUP_WIDTH_PX = 480;\nconst POPUP_HEIGHT_PX = 680;\nconst POPUP_CLOSED_POLL_MS = 500;\nconst SIGN_IN_TIMEOUT_MS = 5 * 60_000;\nconst PKCE_RANDOM_BYTES = 32;\nconst TRAILING_SLASHES = /\\/+$/;\nconst BASE64_PADDING = /[=]+$/;\n\nconst teamAccessSchema = z.object({\n expiresAt: z.number(),\n organizationName: z.string(),\n token: z.string().startsWith(\"fb_team_\"),\n});\n\nexport type TeamAccess = z.infer<typeof teamAccessSchema>;\n\nconst teamAccessMessageSchema = z.union([\n z.object({\n code: z.string().min(1),\n state: z.string(),\n type: z.literal(TEAM_ACCESS_MESSAGE_TYPE),\n }),\n z.object({\n error: z.literal(\"cancelled\"),\n state: z.string(),\n type: z.literal(TEAM_ACCESS_MESSAGE_TYPE),\n }),\n]);\n\nconst SIGN_IN_FAILURE_MESSAGES = {\n cancelled: \"Sign-in was cancelled.\",\n exchange_failed: \"Couldn't finish signing in to Reflet. Try again.\",\n popup_blocked:\n \"Your browser blocked the Reflet sign-in window. Allow pop-ups for this site, then try again.\",\n timeout: \"Signing in took too long. Try again.\",\n} as const;\n\nexport type TeamSignInFailure = keyof typeof SIGN_IN_FAILURE_MESSAGES;\n\nexport class TeamSignInError extends Error {\n readonly reason: TeamSignInFailure;\n\n constructor(reason: TeamSignInFailure, message?: string) {\n super(message ?? SIGN_IN_FAILURE_MESSAGES[reason]);\n this.name = \"TeamSignInError\";\n this.reason = reason;\n }\n}\n\nfunction base64Url(bytes: Uint8Array): string {\n return btoa(String.fromCharCode(...bytes))\n .replaceAll(\"+\", \"-\")\n .replaceAll(\"/\", \"_\")\n .replace(BASE64_PADDING, \"\");\n}\n\nfunction randomBase64Url(): string {\n return base64Url(crypto.getRandomValues(new Uint8Array(PKCE_RANDOM_BYTES)));\n}\n\nasync function pkceChallengeFor(codeVerifier: string): Promise<string> {\n const digest = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(codeVerifier)\n );\n return base64Url(new Uint8Array(digest));\n}\n\nfunction apiEndpoint(apiUrl: string, path: string): string {\n return `${apiUrl.replace(TRAILING_SLASHES, \"\")}${path}`;\n}\n\nfunction parseStoredJson(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\nfunction storedTeamAccess(publicKey: string): TeamAccess | null {\n try {\n const raw = localStorage.getItem(teamAccessStorageKey(publicKey));\n const parsed = teamAccessSchema.safeParse(\n raw === null ? null : parseStoredJson(raw)\n );\n return parsed.success ? parsed.data : null;\n } catch {\n return null;\n }\n}\n\nfunction persistTeamAccess(publicKey: string, access: TeamAccess | null): void {\n try {\n if (access) {\n localStorage.setItem(\n teamAccessStorageKey(publicKey),\n JSON.stringify(access)\n );\n } else {\n localStorage.removeItem(teamAccessStorageKey(publicKey));\n }\n } catch {\n // Storage disabled by browser policy: access then only lasts for this page.\n }\n}\n\nexport function readTeamAccess(publicKey: string): TeamAccess | null {\n const access = storedTeamAccess(publicKey);\n if (access && access.expiresAt > Date.now()) {\n return access;\n }\n persistTeamAccess(publicKey, null);\n return null;\n}\n\nfunction centeredPopupFeatures(): string {\n const left = Math.round(\n window.screenX + (window.outerWidth - POPUP_WIDTH_PX) / 2\n );\n const top = Math.round(\n window.screenY + (window.outerHeight - POPUP_HEIGHT_PX) / 2\n );\n return `popup,width=${POPUP_WIDTH_PX},height=${POPUP_HEIGHT_PX},left=${left},top=${top}`;\n}\n\nfunction waitForApprovedCode(options: {\n appOrigin: string;\n popup: Window;\n state: string;\n}): Promise<string> {\n // Executor form: the SDK targets ES2022, before `Promise.withResolvers`.\n return new Promise((resolve, reject) => {\n const listening = new AbortController();\n let closedOnLastPoll = false;\n const settle = (outcome: { code: string } | TeamSignInError) => {\n listening.abort();\n window.clearInterval(closedPoll);\n window.clearTimeout(timeout);\n if (outcome instanceof TeamSignInError) {\n reject(outcome);\n } else {\n resolve(outcome.code);\n }\n };\n const closedPoll = window.setInterval(() => {\n if (closedOnLastPoll) {\n settle(new TeamSignInError(\"cancelled\"));\n }\n closedOnLastPoll = options.popup.closed;\n }, POPUP_CLOSED_POLL_MS);\n const timeout = window.setTimeout(() => {\n options.popup.close();\n settle(new TeamSignInError(\"timeout\"));\n }, SIGN_IN_TIMEOUT_MS);\n window.addEventListener(\n \"message\",\n (event: MessageEvent) => {\n if (event.origin !== options.appOrigin) {\n return;\n }\n const message = teamAccessMessageSchema.safeParse(event.data);\n if (message.success && message.data.state === options.state) {\n settle(\n \"code\" in message.data\n ? { code: message.data.code }\n : new TeamSignInError(\"cancelled\")\n );\n }\n },\n { signal: listening.signal }\n );\n });\n}\n\nasync function exchangeCode(options: {\n apiUrl: string;\n code: string;\n codeVerifier: string;\n}): Promise<TeamAccess> {\n const response = await fetch(\n apiEndpoint(options.apiUrl, \"/api/v1/team/token\"),\n {\n body: JSON.stringify({\n code: options.code,\n codeVerifier: options.codeVerifier,\n }),\n headers: { \"Content-Type\": \"application/json\" },\n method: \"POST\",\n }\n );\n if (!response.ok) {\n const failure = sessionApiErrorSchema.safeParse(\n await response.json().catch(() => null)\n );\n throw new TeamSignInError(\n \"exchange_failed\",\n failure.success ? failure.data.error : undefined\n );\n }\n const access = teamAccessSchema.safeParse(\n await response.json().catch(() => null)\n );\n if (!access.success) {\n throw new TeamSignInError(\"exchange_failed\");\n }\n return access.data;\n}\n\n/** Call from a click handler: the popup opens before anything is awaited so browsers don't block it. */\nexport async function signInTeam(options: {\n apiUrl: string;\n appUrl: string;\n publicKey: string;\n}): Promise<TeamAccess> {\n const popup = window.open(\"about:blank\", POPUP_NAME, centeredPopupFeatures());\n if (!popup) {\n throw new TeamSignInError(\"popup_blocked\");\n }\n const codeVerifier = randomBase64Url();\n const state = randomBase64Url();\n const consentUrl = new URL(\"/auth/team\", options.appUrl);\n consentUrl.search = new URLSearchParams({\n code_challenge: await pkceChallengeFor(codeVerifier),\n origin: window.location.origin,\n public_key: options.publicKey,\n state,\n }).toString();\n popup.location.href = consentUrl.href;\n\n const code = await waitForApprovedCode({\n appOrigin: consentUrl.origin,\n popup,\n state,\n });\n const access = await exchangeCode({\n apiUrl: options.apiUrl,\n code,\n codeVerifier,\n });\n persistTeamAccess(options.publicKey, access);\n return access;\n}\n\nexport async function forgetTeamAccess(options: {\n apiUrl: string;\n publicKey: string;\n}): Promise<void> {\n const access = storedTeamAccess(options.publicKey);\n persistTeamAccess(options.publicKey, null);\n if (!access) {\n return;\n }\n await fetch(apiEndpoint(options.apiUrl, \"/api/v1/team/revoke\"), {\n headers: { Authorization: `Bearer ${access.token}` },\n method: \"POST\",\n });\n}\n","import { useState } from \"react\";\nimport { failureMessage } from \"../ui/session-workspace\";\nimport { signInTeam, type TeamAccess } from \"./team-auth\";\n\nexport interface TeamConnection {\n apiUrl: string;\n appUrl: string;\n publicKey: string;\n}\n\nfunction useTeamSignIn(\n connection: TeamConnection,\n onSignedIn: (access: TeamAccess) => void\n) {\n const [isSigningIn, setIsSigningIn] = useState(false);\n const [failure, setFailure] = useState<string | null>(null);\n\n const signIn = async () => {\n setIsSigningIn(true);\n setFailure(null);\n try {\n onSignedIn(await signInTeam(connection));\n } catch (error) {\n setFailure(failureMessage(error));\n }\n setIsSigningIn(false);\n };\n\n return { failure, isSigningIn, signIn };\n}\n\nfunction SignInActions({\n isSigningIn,\n onHide,\n onSignIn,\n}: {\n isSigningIn: boolean;\n onHide: () => void;\n onSignIn: () => void;\n}) {\n return (\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={isSigningIn}\n onClick={onSignIn}\n type=\"button\"\n >\n Sign in with Reflet\n </button>\n <button className=\"dt-btn\" onClick={onHide} type=\"button\">\n Hide\n </button>\n </div>\n );\n}\n\nexport function TeamSignInCard({\n connection,\n notice,\n onSignedIn,\n}: {\n connection: TeamConnection;\n notice: string | null;\n onSignedIn: (access: TeamAccess) => void;\n}) {\n const [isHidden, setIsHidden] = useState(false);\n const { failure, isSigningIn, signIn } = useTeamSignIn(\n connection,\n onSignedIn\n );\n\n if (isHidden) {\n return null;\n }\n return (\n <section aria-labelledby=\"rf-team-title\" className=\"dt-team-card glass\">\n <h2 className=\"dt-ses-subhead\" id=\"rf-team-title\">\n Reflet team tools\n </h2>\n <p className=\"dt-meta\">\n Sign in with your Reflet account to record a session on this app.\n </p>\n <p className=\"dt-meta\">\n Only members of the app's Reflet organization can sign in.\n </p>\n {notice && <p className=\"dt-meta\">{notice}</p>}\n {failure && (\n <p className=\"dt-error\" role=\"alert\">\n {failure}\n </p>\n )}\n <SignInActions\n isSigningIn={isSigningIn}\n onHide={() => setIsHidden(true)}\n onSignIn={signIn}\n />\n </section>\n );\n}\n","import { useState } from \"react\";\nimport {\n BarButton,\n DevtoolsBar,\n SessionsBarButton,\n} from \"../../devtools/client/devtools-bar\";\nimport { DevtoolsSheet } from \"../../devtools/client/devtools-sheet\";\nimport { DEVTOOLS_STYLES } from \"../../devtools/client/devtools-styles\";\nimport { Notices, reportFailure } from \"../../devtools/client/notices\";\nimport type { RefletFeedbackProps } from \"../../feedback/types\";\nimport { teamTransport } from \"../api/session-transports\";\nimport { purgeAccount } from \"../local/local-sessions\";\nimport { RecordingLayer } from \"../ui/recording/recording-layer\";\nimport { PersonIcon } from \"../ui/session-icons\";\nimport {\n type SessionWorkspace,\n SessionWorkspaceProvider,\n useWorkspaceLoader,\n type WorkspaceState,\n} from \"../ui/session-workspace\";\nimport { type SessionNavigation, SessionsPanel } from \"../ui/sessions-panel\";\nimport { SESSIONS_STYLES } from \"../ui/sessions-styles\";\nimport type { SessionTarget } from \"../ui/start/session-list\";\nimport { forgetTeamAccess, readTeamAccess, type TeamAccess } from \"./team-auth\";\nimport { type TeamConnection, TeamSignInCard } from \"./team-sign-in-card\";\n\nconst TEAM_TOOLS_LABEL = \"Reflet team tools\";\nconst REFUSED_SIGN_IN_COPY =\n \"Reflet no longer accepts this sign-in. Sign in again to record.\";\n\ninterface TeamPlacement {\n edge: \"bottom\" | \"top\";\n side: \"left\" | \"right\";\n}\n\nfunction AccountControls({\n access,\n onSignOut,\n workspace,\n}: {\n access: TeamAccess;\n onSignOut: () => void;\n workspace: SessionWorkspace | null;\n}) {\n const [isOpen, setIsOpen] = useState(false);\n const user = workspace?.account.userName ?? workspace?.account.userEmail;\n const label = user\n ? `Signed in as ${user} · ${access.organizationName}`\n : `Signed in · ${access.organizationName}`;\n return (\n <>\n <BarButton\n label={label}\n onClick={() => setIsOpen(!isOpen)}\n pressed={isOpen}\n >\n <PersonIcon />\n </BarButton>\n {isOpen && (\n <button className=\"dt-btn\" onClick={onSignOut} type=\"button\">\n Sign out\n </button>\n )}\n </>\n );\n}\n\nfunction SessionsBody({\n navigation,\n onStarted,\n state,\n}: {\n navigation: SessionNavigation;\n onStarted: () => void;\n state: WorkspaceState;\n}) {\n if (state.kind === \"ready\") {\n return <SessionsPanel navigation={navigation} onStarted={onStarted} />;\n }\n if (state.kind === \"failed\") {\n return (\n <div className=\"dt-empty\" role=\"alert\">\n <p>Sessions did not open: {state.message}</p>\n <button className=\"dt-btn\" onClick={state.retry} type=\"button\">\n Try again\n </button>\n </div>\n );\n }\n return <p className=\"dt-status\">Opening your sessions…</p>;\n}\n\nfunction TeamSheet({\n navigation,\n onOpenChange,\n side,\n state,\n}: {\n navigation: SessionNavigation;\n onOpenChange: (isOpen: boolean) => void;\n side: TeamPlacement[\"side\"];\n state: WorkspaceState;\n}) {\n return (\n <DevtoolsSheet\n label={TEAM_TOOLS_LABEL}\n onClose={() => onOpenChange(false)}\n onSelectTab={() => onOpenChange(true)}\n side={side}\n tab=\"sessions\"\n tabs={[\"sessions\"]}\n >\n <SessionsBody\n navigation={navigation}\n onStarted={() => onOpenChange(false)}\n state={state}\n />\n </DevtoolsSheet>\n );\n}\n\ninterface TeamSession {\n access: TeamAccess;\n apiUrl: string;\n onSignOut: (reason: string | null) => void;\n}\n\nfunction useTeamTransport(team: TeamSession) {\n const createTransport = () => ({\n apiUrl: team.apiUrl,\n transport: teamTransport({ apiUrl: team.apiUrl, token: team.access.token }),\n });\n const [current, setCurrent] = useState(createTransport);\n if (current.apiUrl !== team.apiUrl) {\n const next = createTransport();\n setCurrent(next);\n return next.transport;\n }\n return current.transport;\n}\n\nfunction useTeamWorkspace(team: TeamSession) {\n const { onSignOut } = team;\n const transport = useTeamTransport(team);\n const state = useWorkspaceLoader({\n onUnauthorized: () => onSignOut(REFUSED_SIGN_IN_COPY),\n surface: \"app\",\n transport,\n });\n const workspace = state.kind === \"ready\" ? state.workspace : null;\n\n const signOut = async () => {\n if (workspace) {\n await purgeAccount(workspace.account.key).catch((error: unknown) =>\n reportFailure(\"This device's session data was not removed\", error)\n );\n }\n onSignOut(null);\n };\n\n return { signOut, state, workspace };\n}\n\nfunction TeamTools({\n team,\n placement,\n}: {\n placement: TeamPlacement;\n team: TeamSession;\n}) {\n const { signOut, state, workspace } = useTeamWorkspace(team);\n const [isSheetOpen, setIsSheetOpen] = useState(false);\n const [open, setOpen] = useState<SessionTarget | null>(null);\n\n return (\n <SessionWorkspaceProvider workspace={workspace}>\n {isSheetOpen && (\n <TeamSheet\n navigation={{ onOpen: setOpen, open }}\n onOpenChange={setIsSheetOpen}\n side={placement.side}\n state={state}\n />\n )}\n <DevtoolsBar\n edge={placement.edge}\n label={TEAM_TOOLS_LABEL}\n side={placement.side}\n >\n <SessionsBarButton\n isOpen={isSheetOpen}\n onToggle={() => setIsSheetOpen(!isSheetOpen)}\n />\n <AccountControls\n access={team.access}\n onSignOut={signOut}\n workspace={workspace}\n />\n </DevtoolsBar>\n {workspace && (\n <RecordingLayer\n onFinished={(target) => {\n setOpen(target);\n setIsSheetOpen(true);\n }}\n />\n )}\n </SessionWorkspaceProvider>\n );\n}\n\nfunction placementFor(\n position: NonNullable<RefletFeedbackProps[\"position\"]>\n): TeamPlacement {\n return {\n edge: position.startsWith(\"top\") ? \"top\" : \"bottom\",\n side: position.endsWith(\"right\") ? \"right\" : \"left\",\n };\n}\n\nexport function TeamLayer({\n connection,\n position,\n}: {\n connection: TeamConnection;\n position: NonNullable<RefletFeedbackProps[\"position\"]>;\n}) {\n const { apiUrl, publicKey } = connection;\n const [access, setAccess] = useState(() => readTeamAccess(publicKey));\n const [notice, setNotice] = useState<string | null>(null);\n const signOut = (reason: string | null) => {\n setAccess(null);\n setNotice(reason);\n forgetTeamAccess({ apiUrl, publicKey }).catch((error: unknown) =>\n reportFailure(\"Signing out of Reflet did not finish\", error)\n );\n };\n const placement = placementFor(position);\n\n return (\n <div className=\"dt\">\n <style>{`${DEVTOOLS_STYLES}${SESSIONS_STYLES}`}</style>\n {access ? (\n <TeamTools\n placement={placement}\n team={{ access, apiUrl, onSignOut: signOut }}\n />\n ) : (\n <div\n className=\"dt-team-anchor\"\n data-edge={placement.edge}\n data-side={placement.side}\n >\n <TeamSignInCard\n connection={connection}\n notice={notice}\n onSignedIn={(signedIn) => {\n setAccess(signedIn);\n setNotice(null);\n }}\n />\n </div>\n )}\n <Notices />\n </div>\n );\n}\n"],"mappings":";;;;;;;AAIA,MAAM,2BAA2B;AACjC,MAAM,aAAa;AACnB,MAAM,iBAAiB;AACvB,MAAM,kBAAkB;AACxB,MAAM,uBAAuB;AAC7B,MAAM,qBAAqB;AAC3B,MAAM,oBAAoB;AAC1B,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AAEvB,MAAM,mBAAmB,EAAE,OAAO;CAChC,WAAW,EAAE,OAAO;CACpB,kBAAkB,EAAE,OAAO;CAC3B,OAAO,EAAE,OAAO,CAAC,CAAC,WAAW,UAAU;AACzC,CAAC;AAID,MAAM,0BAA0B,EAAE,MAAM,CACtC,EAAE,OAAO;CACP,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACtB,OAAO,EAAE,OAAO;CAChB,MAAM,EAAE,QAAQ,wBAAwB;AAC1C,CAAC,GACD,EAAE,OAAO;CACP,OAAO,EAAE,QAAQ,WAAW;CAC5B,OAAO,EAAE,OAAO;CAChB,MAAM,EAAE,QAAQ,wBAAwB;AAC1C,CAAC,CACH,CAAC;AAED,MAAM,2BAA2B;CAC/B,WAAW;CACX,iBAAiB;CACjB,eACE;CACF,SAAS;AACX;AAIA,IAAa,kBAAb,cAAqC,MAAM;CACzC;CAEA,YAAY,QAA2B,SAAkB;EACvD,MAAM,WAAW,yBAAyB,OAAO;EACjD,KAAK,OAAO;EACZ,KAAK,SAAS;CAChB;AACF;AAEA,SAAS,UAAU,OAA2B;CAC5C,OAAO,KAAK,OAAO,aAAa,GAAG,KAAK,CAAC,CAAC,CACvC,WAAW,KAAK,GAAG,CAAC,CACpB,WAAW,KAAK,GAAG,CAAC,CACpB,QAAQ,gBAAgB,EAAE;AAC/B;AAEA,SAAS,kBAA0B;CACjC,OAAO,UAAU,OAAO,gBAAgB,IAAI,WAAW,iBAAiB,CAAC,CAAC;AAC5E;AAEA,eAAe,iBAAiB,cAAuC;CACrE,MAAM,SAAS,MAAM,OAAO,OAAO,OACjC,WACA,IAAI,YAAY,CAAC,CAAC,OAAO,YAAY,CACvC;CACA,OAAO,UAAU,IAAI,WAAW,MAAM,CAAC;AACzC;AAEA,SAAS,YAAY,QAAgB,MAAsB;CACzD,OAAO,GAAG,OAAO,QAAQ,kBAAkB,EAAE,IAAI;AACnD;AAEA,SAAS,gBAAgB,KAAsB;CAC7C,IAAI;EACF,OAAO,KAAK,MAAM,GAAG;CACvB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,iBAAiB,WAAsC;CAC9D,IAAI;EACF,MAAM,MAAM,aAAa,QAAQ,qBAAqB,SAAS,CAAC;EAChE,MAAM,SAAS,iBAAiB,UAC9B,QAAQ,OAAO,OAAO,gBAAgB,GAAG,CAC3C;EACA,OAAO,OAAO,UAAU,OAAO,OAAO;CACxC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,kBAAkB,WAAmB,QAAiC;CAC7E,IAAI;EACF,IAAI,QACF,aAAa,QACX,qBAAqB,SAAS,GAC9B,KAAK,UAAU,MAAM,CACvB;OAEA,aAAa,WAAW,qBAAqB,SAAS,CAAC;CAE3D,QAAQ,CAER;AACF;AAEA,SAAgB,eAAe,WAAsC;CACnE,MAAM,SAAS,iBAAiB,SAAS;CACzC,IAAI,UAAU,OAAO,YAAY,KAAK,IAAI,GACxC,OAAO;CAET,kBAAkB,WAAW,IAAI;CACjC,OAAO;AACT;AAEA,SAAS,wBAAgC;CACvC,MAAM,OAAO,KAAK,MAChB,OAAO,WAAW,OAAO,aAAa,kBAAkB,CAC1D;CACA,MAAM,MAAM,KAAK,MACf,OAAO,WAAW,OAAO,cAAc,mBAAmB,CAC5D;CACA,OAAO,eAAe,eAAe,UAAU,gBAAgB,QAAQ,KAAK,OAAO;AACrF;AAEA,SAAS,oBAAoB,SAIT;CAElB,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,YAAY,IAAI,gBAAgB;EACtC,IAAI,mBAAmB;EACvB,MAAM,UAAU,YAAgD;GAC9D,UAAU,MAAM;GAChB,OAAO,cAAc,UAAU;GAC/B,OAAO,aAAa,OAAO;GAC3B,IAAI,mBAAmB,iBACrB,OAAO,OAAO;QAEd,QAAQ,QAAQ,IAAI;EAExB;EACA,MAAM,aAAa,OAAO,kBAAkB;GAC1C,IAAI,kBACF,OAAO,IAAI,gBAAgB,WAAW,CAAC;GAEzC,mBAAmB,QAAQ,MAAM;EACnC,GAAG,oBAAoB;EACvB,MAAM,UAAU,OAAO,iBAAiB;GACtC,QAAQ,MAAM,MAAM;GACpB,OAAO,IAAI,gBAAgB,SAAS,CAAC;EACvC,GAAG,kBAAkB;EACrB,OAAO,iBACL,YACC,UAAwB;GACvB,IAAI,MAAM,WAAW,QAAQ,WAC3B;GAEF,MAAM,UAAU,wBAAwB,UAAU,MAAM,IAAI;GAC5D,IAAI,QAAQ,WAAW,QAAQ,KAAK,UAAU,QAAQ,OACpD,OACE,UAAU,QAAQ,OACd,EAAE,MAAM,QAAQ,KAAK,KAAK,IAC1B,IAAI,gBAAgB,WAAW,CACrC;EAEJ,GACA,EAAE,QAAQ,UAAU,OAAO,CAC7B;CACF,CAAC;AACH;AAEA,eAAe,aAAa,SAIJ;CACtB,MAAM,WAAW,MAAM,MACrB,YAAY,QAAQ,QAAQ,oBAAoB,GAChD;EACE,MAAM,KAAK,UAAU;GACnB,MAAM,QAAQ;GACd,cAAc,QAAQ;EACxB,CAAC;EACD,SAAS,EAAE,gBAAgB,mBAAmB;EAC9C,QAAQ;CACV,CACF;CACA,IAAI,CAAC,SAAS,IAAI;EAChB,MAAM,UAAU,sBAAsB,UACpC,MAAM,SAAS,KAAK,CAAC,CAAC,YAAY,IAAI,CACxC;EACA,MAAM,IAAI,gBACR,mBACA,QAAQ,UAAU,QAAQ,KAAK,QAAQ,KAAA,CACzC;CACF;CACA,MAAM,SAAS,iBAAiB,UAC9B,MAAM,SAAS,KAAK,CAAC,CAAC,YAAY,IAAI,CACxC;CACA,IAAI,CAAC,OAAO,SACV,MAAM,IAAI,gBAAgB,iBAAiB;CAE7C,OAAO,OAAO;AAChB;;AAGA,eAAsB,WAAW,SAIT;CACtB,MAAM,QAAQ,OAAO,KAAK,eAAe,YAAY,sBAAsB,CAAC;CAC5E,IAAI,CAAC,OACH,MAAM,IAAI,gBAAgB,eAAe;CAE3C,MAAM,eAAe,gBAAgB;CACrC,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,aAAa,IAAI,IAAI,cAAc,QAAQ,MAAM;CACvD,WAAW,SAAS,IAAI,gBAAgB;EACtC,gBAAgB,MAAM,iBAAiB,YAAY;EACnD,QAAQ,OAAO,SAAS;EACxB,YAAY,QAAQ;EACpB;CACF,CAAC,CAAC,CAAC,SAAS;CACZ,MAAM,SAAS,OAAO,WAAW;CAEjC,MAAM,OAAO,MAAM,oBAAoB;EACrC,WAAW,WAAW;EACtB;EACA;CACF,CAAC;CACD,MAAM,SAAS,MAAM,aAAa;EAChC,QAAQ,QAAQ;EAChB;EACA;CACF,CAAC;CACD,kBAAkB,QAAQ,WAAW,MAAM;CAC3C,OAAO;AACT;AAEA,eAAsB,iBAAiB,SAGrB;CAChB,MAAM,SAAS,iBAAiB,QAAQ,SAAS;CACjD,kBAAkB,QAAQ,WAAW,IAAI;CACzC,IAAI,CAAC,QACH;CAEF,MAAM,MAAM,YAAY,QAAQ,QAAQ,qBAAqB,GAAG;EAC9D,SAAS,EAAE,eAAe,UAAU,OAAO,QAAQ;EACnD,QAAQ;CACV,CAAC;AACH;;;AC7PA,SAAS,cACP,YACA,YACA;CACA,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,CAAC,SAAS,cAAc,SAAwB,IAAI;CAE1D,MAAM,SAAS,YAAY;EACzB,eAAe,IAAI;EACnB,WAAW,IAAI;EACf,IAAI;GACF,WAAW,MAAM,WAAW,UAAU,CAAC;EACzC,SAAS,OAAO;GACd,WAAW,eAAe,KAAK,CAAC;EAClC;EACA,eAAe,KAAK;CACtB;CAEA,OAAO;EAAE;EAAS;EAAa;CAAO;AACxC;AAEA,SAAS,cAAc,EACrB,aACA,QACA,YAKC;CACD,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,oBAAC,UAAD;GACE,WAAU;GACV,gBAAa;GACb,UAAU;GACV,SAAS;GACT,MAAK;GACN,UAAA;EAEO,CAAA,GACR,oBAAC,UAAD;GAAQ,WAAU;GAAS,SAAS;GAAQ,MAAK;GAAS,UAAA;EAElD,CAAA,CACL;;AAET;AAEA,SAAgB,eAAe,EAC7B,YACA,QACA,cAKC;CACD,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAC9C,MAAM,EAAE,SAAS,aAAa,WAAW,cACvC,YACA,UACF;CAEA,IAAI,UACF,OAAO;CAET,OACE,qBAAC,WAAD;EAAS,mBAAgB;EAAgB,WAAU;EAAnD,UAAA;GACE,oBAAC,MAAD;IAAI,WAAU;IAAiB,IAAG;IAAgB,UAAA;GAE9C,CAAA;GACJ,oBAAC,KAAD;IAAG,WAAU;IAAU,UAAA;GAEpB,CAAA;GACH,oBAAC,KAAD;IAAG,WAAU;IAAU,UAAA;GAEpB,CAAA;GACF,UAAU,oBAAC,KAAD;IAAG,WAAU;IAAW,UAAA;GAAU,CAAA;GAC5C,WACC,oBAAC,KAAD;IAAG,WAAU;IAAW,MAAK;IAC1B,UAAA;GACA,CAAA;GAEL,oBAAC,eAAD;IACe;IACb,cAAc,YAAY,IAAI;IAC9B,UAAU;GACX,CAAA;EACM;;AAEb;;;AC1EA,MAAM,mBAAmB;AACzB,MAAM,uBACJ;AAOF,SAAS,gBAAgB,EACvB,QACA,WACA,aAKC;CACD,MAAM,CAAC,QAAQ,aAAa,SAAS,KAAK;CAC1C,MAAM,OAAO,WAAW,QAAQ,YAAY,WAAW,QAAQ;CAC/D,MAAM,QAAQ,OACV,gBAAgB,KAAK,KAAK,OAAO,qBACjC,eAAe,OAAO;CAC1B,OACE,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,WAAD;EACS;EACP,eAAe,UAAU,CAAC,MAAM;EAChC,SAAS;EAET,UAAA,oBAAC,YAAD,CAAa,CAAA;CACJ,CAAA,GACV,UACC,oBAAC,UAAD;EAAQ,WAAU;EAAS,SAAS;EAAW,MAAK;EAAS,UAAA;CAErD,CAAA,CAEV,EAAA,CAAA;AAEN;AAEA,SAAS,aAAa,EACpB,YACA,WACA,SAKC;CACD,IAAI,MAAM,SAAS,SACjB,OAAO,oBAAC,eAAD;EAA2B;EAAuB;CAAY,CAAA;CAEvE,IAAI,MAAM,SAAS,UACjB,OACE,qBAAC,OAAD;EAAK,WAAU;EAAW,MAAK;EAA/B,UAAA,CACE,qBAAC,KAAD,EAAA,UAAA,CAAG,2BAAwB,MAAM,OAAW,EAAA,CAAA,GAC5C,oBAAC,UAAD;GAAQ,WAAU;GAAS,SAAS,MAAM;GAAO,MAAK;GAAS,UAAA;EAEvD,CAAA,CACL;;CAGT,OAAO,oBAAC,KAAD;EAAG,WAAU;EAAY,UAAA;CAAyB,CAAA;AAC3D;AAEA,SAAS,UAAU,EACjB,YACA,cACA,MACA,SAMC;CACD,OACE,oBAAC,eAAD;EACE,OAAO;EACP,eAAe,aAAa,KAAK;EACjC,mBAAmB,aAAa,IAAI;EAC9B;EACN,KAAI;EACJ,MAAM,CAAC,UAAU;EAEjB,UAAA,oBAAC,cAAD;GACc;GACZ,iBAAiB,aAAa,KAAK;GAC5B;EACR,CAAA;CACY,CAAA;AAEnB;AAQA,SAAS,iBAAiB,MAAmB;CAC3C,MAAM,yBAAyB;EAC7B,QAAQ,KAAK;EACb,WAAW,cAAc;GAAE,QAAQ,KAAK;GAAQ,OAAO,KAAK,OAAO;EAAM,CAAC;CAC5E;CACA,MAAM,CAAC,SAAS,cAAc,SAAS,eAAe;CACtD,IAAI,QAAQ,WAAW,KAAK,QAAQ;EAClC,MAAM,OAAO,gBAAgB;EAC7B,WAAW,IAAI;EACf,OAAO,KAAK;CACd;CACA,OAAO,QAAQ;AACjB;AAEA,SAAS,iBAAiB,MAAmB;CAC3C,MAAM,EAAE,cAAc;CACtB,MAAM,YAAY,iBAAiB,IAAI;CACvC,MAAM,QAAQ,mBAAmB;EAC/B,sBAAsB,UAAU,oBAAoB;EACpD,SAAS;EACT;CACF,CAAC;CACD,MAAM,YAAY,MAAM,SAAS,UAAU,MAAM,YAAY;CAE7D,MAAM,UAAU,YAAY;EAC1B,IAAI,WACF,MAAM,aAAa,UAAU,QAAQ,GAAG,CAAC,CAAC,OAAO,UAC/C,cAAc,8CAA8C,KAAK,CACnE;EAEF,UAAU,IAAI;CAChB;CAEA,OAAO;EAAE;EAAS;EAAO;CAAU;AACrC;AAEA,SAAS,UAAU,EACjB,MACA,aAIC;CACD,MAAM,EAAE,SAAS,OAAO,cAAc,iBAAiB,IAAI;CAC3D,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,CAAC,MAAM,WAAW,SAA+B,IAAI;CAE3D,OACE,qBAAC,0BAAD;EAAqC;EAArC,UAAA;GACG,eACC,oBAAC,WAAD;IACE,YAAY;KAAE,QAAQ;KAAS;IAAK;IACpC,cAAc;IACd,MAAM,UAAU;IACT;GACR,CAAA;GAEH,qBAAC,aAAD;IACE,MAAM,UAAU;IAChB,OAAO;IACP,MAAM,UAAU;IAHlB,UAAA,CAKE,oBAAC,mBAAD;KACE,QAAQ;KACR,gBAAgB,eAAe,CAAC,WAAW;IAC5C,CAAA,GACD,oBAAC,iBAAD;KACE,QAAQ,KAAK;KACb,WAAW;KACA;IACZ,CAAA,CACU;;GACZ,aACC,oBAAC,gBAAD,EACE,aAAa,WAAW;IACtB,QAAQ,MAAM;IACd,eAAe,IAAI;GACrB,EACD,CAAA;EAEqB;;AAE9B;AAEA,SAAS,aACP,UACe;CACf,OAAO;EACL,MAAM,SAAS,WAAW,KAAK,IAAI,QAAQ;EAC3C,MAAM,SAAS,SAAS,OAAO,IAAI,UAAU;CAC/C;AACF;AAEA,SAAgB,UAAU,EACxB,YACA,YAIC;CACD,MAAM,EAAE,QAAQ,cAAc;CAC9B,MAAM,CAAC,QAAQ,aAAa,eAAe,eAAe,SAAS,CAAC;CACpE,MAAM,CAAC,QAAQ,aAAa,SAAwB,IAAI;CACxD,MAAM,WAAW,WAA0B;EACzC,UAAU,IAAI;EACd,UAAU,MAAM;EAChB,iBAAiB;GAAE;GAAQ;EAAU,CAAC,CAAC,CAAC,OAAO,UAC7C,cAAc,wCAAwC,KAAK,CAC7D;CACF;CACA,MAAM,YAAY,aAAa,QAAQ;CAEvC,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,oBAAC,SAAD,EAAA,UAAQ,GAAG,kBAAkB,kBAAyB,CAAA;GACrD,SACC,oBAAC,WAAD;IACa;IACX,MAAM;KAAE;KAAQ;KAAQ,WAAW;IAAQ;GAC5C,CAAA,IAED,oBAAC,OAAD;IACE,WAAU;IACV,aAAW,UAAU;IACrB,aAAW,UAAU;IAErB,UAAA,oBAAC,gBAAD;KACc;KACJ;KACR,aAAa,aAAa;MACxB,UAAU,QAAQ;MAClB,UAAU,IAAI;KAChB;IACD,CAAA;GACE,CAAA;GAEP,oBAAC,SAAD,CAAU,CAAA;EACP;;AAET"}
@@ -36,7 +36,6 @@ interface OrganizationConfig {
36
36
  statuses: OrganizationStatus[];
37
37
  }
38
38
  interface OrganizationSettings {
39
- allowAnonymousVoting?: boolean;
40
39
  defaultStatus?: FeedbackStatus;
41
40
  requireApproval?: boolean;
42
41
  }
@@ -141,11 +140,6 @@ interface PageContext {
141
140
  height: number;
142
141
  width: number;
143
142
  };
144
- /** Where the viewport sat in the page when the screenshot was taken. */
145
- scroll?: {
146
- x: number;
147
- y: number;
148
- };
149
143
  timezone?: string;
150
144
  url?: string;
151
145
  userAgent?: string;
@@ -254,11 +248,12 @@ interface RoadmapItem {
254
248
  }
255
249
  interface ChangelogEntry {
256
250
  description?: string;
257
- feedback: {
251
+ id: string;
252
+ items: {
258
253
  id: string;
254
+ status: FeedbackStatus;
259
255
  title: string;
260
256
  }[];
261
- id: string;
262
257
  publishedAt?: number;
263
258
  title: string;
264
259
  version?: string;
@@ -279,4 +274,4 @@ declare class RefletNotFoundError extends RefletError {
279
274
  }
280
275
  //#endregion
281
276
  export { SubscribeResponse as A, RefletNotFoundError as C, RoadmapItem as D, Roadmap as E, VoteResponse as M, RoadmapLane as O, RefletError as S, RefletValidationError as T, OrganizationConfig as _, CommentReply as a, RefletAuthError as b, ElementSelection as c, FeedbackDetail as d, FeedbackItem as f, FeedbackTag as g, FeedbackStatus as h, Comment as i, UnsubscribeResponse as j, SaveScreenshotParams as k, FeedbackAuthor as l, FeedbackListResponse as m, AddCommentResponse as n, CreateFeedbackParams as o, FeedbackListParams as p, ChangelogEntry as r, CreateFeedbackResponse as s, AddCommentParams as t, FeedbackContext as u, OrganizationSettings as v, RefletUser as w, RefletConfig as x, OrganizationStatus as y };
282
- //# sourceMappingURL=types-DnaDEN9Y.d.ts.map
277
+ //# sourceMappingURL=types-B3XiHPqy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-B3XiHPqy.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;;UAQiB;;EAEf;;EAEA;;EAEA,OAAO;;EAEP;;UAGe;;EAEf;;EAEA;;EAEA;;EAEA,WAAW;;EAEX;;UAOe;EACf;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EACX;EACA,UAAU;;UAGK;EACf,gBAAgB;EAChB;;UAGe;EACf;EACA;EACA;EACA;EACA;;KAGU;UAYK;EACf,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;IACE;IACA;IACA;;EAEF,QAAQ;EACR,MAAM;EACN;EACA;EACA;;UAGe,uBAAuB;EACtC;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA,OAAO;EACP;;UAGe;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA,SAAS;;EAET;;UAGe;EACf;EACA;EACA;EACA;;UAGe;;EAEf;;EAEA;;EAEA;;EAEA;EACA,MAAM;;EAEN;EACA;;EAEA;;EAEA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;IAAW;IAAgB;;EAC3B;EACA;EACA;EACA;IAAa;IAA0B;IAAgB;;;;UAIxC,wBAAwB;EACvC,gBAAgB;EAChB,WAAW;EACX;EACA,aAAa;;UAGE;EACf,UAAU;EACV;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA,SAAS;IAAQ;IAAW;;EAC5B;EACA;EAQA;EACA;EACA;;UAGe;EACf;EACA,cAAc;;EAEd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;;UAOe;EACf,QAAQ;EACR;EACA;EACA;EACA;EACA,SAAS;EACT;;UAGe;EACf,QAAQ;EACR;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;;UAOe;EACf;EACA;;UAGe;EACf;EACA;;UAOe;EACf,OAAO;;UAGQ;EACf;EACA;EACA,OAAO;EACP;;UAGe;EACf;EACA,QAAQ;EACR;EACA;;UAOe;EACf;EACA;EACA;IAAS;IAAY,QAAQ;IAAgB;;EAC7C;EACA;EACA;;cAOW,oBAAoB;WACtB;WACA;EAET,YAAY,iBAAiB,gBAAgB;;cAQlC,wBAAwB;EACnC,YAAY;;cAMD,8BAA8B;EACzC,YAAY;;cAMD,4BAA4B;EACvC,YAAY"}