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.
- package/CHANGELOG.md +23 -0
- package/README.md +100 -2
- package/dist/{client-DAdWdIFY.js → client-oFFfRxAM.js} +135 -59
- package/dist/client-oFFfRxAM.js.map +1 -0
- package/dist/client-transport-B7BdVU7J.d.ts +150 -0
- package/dist/client-transport-B7BdVU7J.d.ts.map +1 -0
- package/dist/{devtools-layer-CEjzYGBB.js → devtools-layer-OjTo9_eb.js} +417 -916
- package/dist/devtools-layer-OjTo9_eb.js.map +1 -0
- package/dist/devtools-next.js +1 -1
- package/dist/devtools-vite.js +2 -2
- package/dist/feedback.d.ts +7 -1
- package/dist/feedback.d.ts.map +1 -1
- package/dist/feedback.js +105 -57
- package/dist/feedback.js.map +1 -1
- package/dist/{handler-BSNmdHXv.js → handler-yA_knIf3.js} +4 -4
- package/dist/{handler-BSNmdHXv.js.map → handler-yA_knIf3.js.map} +1 -1
- package/dist/index-Buum9tIY.d.ts +230 -0
- package/dist/index-Buum9tIY.d.ts.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/options-CIBazDPp.d.ts.map +1 -1
- package/dist/protocol-vJhQHTcB.js +390 -0
- package/dist/protocol-vJhQHTcB.js.map +1 -0
- package/dist/{react-context-Caq1fodf.js → react-context-Kazo_JCz.js} +3 -14
- package/dist/react-context-Kazo_JCz.js.map +1 -0
- package/dist/react.d.ts +43 -3
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +389 -3
- package/dist/react.js.map +1 -1
- package/dist/selection-outline-NzAAAZXR.js +51 -0
- package/dist/selection-outline-NzAAAZXR.js.map +1 -0
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/sessions-panel-CkxIekZX.js +6010 -0
- package/dist/sessions-panel-CkxIekZX.js.map +1 -0
- package/dist/{submit-MvVjNdYc.js → submit-DZX0f2_0.js} +44 -70
- package/dist/submit-DZX0f2_0.js.map +1 -0
- package/dist/surveys.d.ts +3 -0
- package/dist/surveys.js +2 -0
- package/dist/team-activation-DCqh71bl.js +24 -0
- package/dist/team-activation-DCqh71bl.js.map +1 -0
- package/dist/team-layer-DyyGqmxs.js +423 -0
- package/dist/team-layer-DyyGqmxs.js.map +1 -0
- package/dist/{types-DnaDEN9Y.d.ts → types-B3XiHPqy.d.ts} +4 -9
- package/dist/types-B3XiHPqy.d.ts.map +1 -0
- package/dist/use-survey-session-LK6sN1Fg.js +1247 -0
- package/dist/use-survey-session-LK6sN1Fg.js.map +1 -0
- package/dist/z-index-CwokqVq_.js +15 -0
- package/dist/z-index-CwokqVq_.js.map +1 -0
- package/package.json +6 -2
- package/dist/client-DAdWdIFY.js.map +0 -1
- package/dist/client-DF1fdsSC.d.ts +0 -131
- package/dist/client-DF1fdsSC.d.ts.map +0 -1
- package/dist/devtools-layer-CEjzYGBB.js.map +0 -1
- package/dist/protocol-ClqTFzwR.js +0 -35
- package/dist/protocol-ClqTFzwR.js.map +0 -1
- package/dist/react-context-Caq1fodf.js.map +0 -1
- package/dist/submit-MvVjNdYc.js.map +0 -1
- 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":"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"}
|
|
@@ -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
|
-
|
|
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-
|
|
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"}
|