@diegotsi/flint-react 0.1.3 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +71 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -5
- package/dist/index.d.ts +11 -5
- package/dist/index.js +60 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -21,12 +21,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
FlintModal: () => FlintModal,
|
|
24
|
-
FlintWidget: () => FlintWidget
|
|
24
|
+
FlintWidget: () => FlintWidget,
|
|
25
|
+
flint: () => flint
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(index_exports);
|
|
27
28
|
|
|
28
29
|
// src/FlintWidget.tsx
|
|
29
|
-
var
|
|
30
|
+
var import_react3 = require("react");
|
|
30
31
|
var import_react_i18next3 = require("react-i18next");
|
|
31
32
|
|
|
32
33
|
// src/FlintModal.tsx
|
|
@@ -177,7 +178,7 @@ function FlintModal({
|
|
|
177
178
|
getConsoleLogs,
|
|
178
179
|
getNetworkErrors,
|
|
179
180
|
getReplayEvents,
|
|
180
|
-
|
|
181
|
+
getExternalReplayUrl
|
|
181
182
|
}) {
|
|
182
183
|
const { t } = (0, import_react_i18next.useTranslation)();
|
|
183
184
|
const colors = resolveTheme(theme);
|
|
@@ -227,7 +228,7 @@ function FlintModal({
|
|
|
227
228
|
reporterName: user?.name ?? "Anonymous",
|
|
228
229
|
description: description.trim(),
|
|
229
230
|
expectedBehavior: expectedBehavior.trim() || void 0,
|
|
230
|
-
externalReplayUrl:
|
|
231
|
+
externalReplayUrl: getExternalReplayUrl() || void 0,
|
|
231
232
|
severity,
|
|
232
233
|
url: window.location.href,
|
|
233
234
|
meta: collectedMeta
|
|
@@ -412,10 +413,10 @@ function FlintModal({
|
|
|
412
413
|
pointerEvents: isSuccess ? "auto" : "none"
|
|
413
414
|
}, children: [
|
|
414
415
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 13, color: colors.textMuted, margin: 0 }, children: result?.isDuplicate ? t("successDuplicate") : result ? `ID: ${result.id}` : "" }),
|
|
415
|
-
result?.
|
|
416
|
+
result?.slackMessageUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
416
417
|
"a",
|
|
417
418
|
{
|
|
418
|
-
href: result.
|
|
419
|
+
href: result.slackMessageUrl,
|
|
419
420
|
target: "_blank",
|
|
420
421
|
rel: "noreferrer",
|
|
421
422
|
style: {
|
|
@@ -432,7 +433,7 @@ function FlintModal({
|
|
|
432
433
|
boxShadow: accentGlow
|
|
433
434
|
},
|
|
434
435
|
children: [
|
|
435
|
-
t("
|
|
436
|
+
t("successSlack"),
|
|
436
437
|
" \u2197"
|
|
437
438
|
]
|
|
438
439
|
}
|
|
@@ -553,6 +554,19 @@ function FlintModal({
|
|
|
553
554
|
}
|
|
554
555
|
)
|
|
555
556
|
] }),
|
|
557
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
|
|
558
|
+
display: "flex",
|
|
559
|
+
alignItems: "center",
|
|
560
|
+
gap: 8,
|
|
561
|
+
padding: "9px 12px",
|
|
562
|
+
borderRadius: 10,
|
|
563
|
+
background: isDark ? "rgba(255,255,255,0.04)" : "rgba(0,77,240,0.04)",
|
|
564
|
+
border: `1px solid ${isDark ? "rgba(255,255,255,0.08)" : "rgba(0,77,240,0.1)"}`,
|
|
565
|
+
marginBottom: 16
|
|
566
|
+
}, children: [
|
|
567
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 14 }, children: "\u{1F3A5}" }),
|
|
568
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 12, color: colors.textMuted, lineHeight: 1.4 }, children: t("replayInfo") })
|
|
569
|
+
] }),
|
|
556
570
|
status === "error" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
|
|
557
571
|
padding: "10px 13px",
|
|
558
572
|
borderRadius: 10,
|
|
@@ -768,6 +782,8 @@ var en_default = {
|
|
|
768
782
|
successTitle: "Bug reported!",
|
|
769
783
|
successDuplicate: "Looks like a duplicate of an existing bug.",
|
|
770
784
|
successGitHub: "View GitHub issue",
|
|
785
|
+
successSlack: "View Slack message",
|
|
786
|
+
replayInfo: "No need to record your screen \u2014 we automatically capture a session replay when you submit.",
|
|
771
787
|
errorLabel: "Failed to submit. Please try again.",
|
|
772
788
|
cancel: "Cancel",
|
|
773
789
|
sending: "Sending report",
|
|
@@ -980,13 +996,41 @@ function createNetworkCollector() {
|
|
|
980
996
|
};
|
|
981
997
|
}
|
|
982
998
|
|
|
999
|
+
// src/store.ts
|
|
1000
|
+
var import_react2 = require("react");
|
|
1001
|
+
var state = { user: void 0, sessionReplay: void 0 };
|
|
1002
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1003
|
+
function emit() {
|
|
1004
|
+
listeners.forEach((fn) => fn());
|
|
1005
|
+
}
|
|
1006
|
+
function subscribeStore(fn) {
|
|
1007
|
+
listeners.add(fn);
|
|
1008
|
+
return () => listeners.delete(fn);
|
|
1009
|
+
}
|
|
1010
|
+
function getSnapshot() {
|
|
1011
|
+
return state;
|
|
1012
|
+
}
|
|
1013
|
+
function useFlintStore() {
|
|
1014
|
+
return (0, import_react2.useSyncExternalStore)(subscribeStore, getSnapshot);
|
|
1015
|
+
}
|
|
1016
|
+
var flint = {
|
|
1017
|
+
setUser(user) {
|
|
1018
|
+
state = { ...state, user: user ?? void 0 };
|
|
1019
|
+
emit();
|
|
1020
|
+
},
|
|
1021
|
+
setSessionReplay(url) {
|
|
1022
|
+
state = { ...state, sessionReplay: url };
|
|
1023
|
+
emit();
|
|
1024
|
+
}
|
|
1025
|
+
};
|
|
1026
|
+
|
|
983
1027
|
// src/FlintWidget.tsx
|
|
984
1028
|
var import_rrweb = require("rrweb");
|
|
985
1029
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
986
1030
|
var REPLAY_WINDOW_MS = 6e4;
|
|
987
1031
|
function FlintWidget(props) {
|
|
988
1032
|
const { locale = "en-US" } = props;
|
|
989
|
-
(0,
|
|
1033
|
+
(0, import_react3.useEffect)(() => {
|
|
990
1034
|
i18n_default.changeLanguage(locale);
|
|
991
1035
|
}, [locale]);
|
|
992
1036
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_i18next3.I18nextProvider, { i18n: i18n_default, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(WidgetContent, { ...props }) });
|
|
@@ -1001,15 +1045,21 @@ function WidgetContent({
|
|
|
1001
1045
|
theme = "dark",
|
|
1002
1046
|
zIndex = 9999
|
|
1003
1047
|
}) {
|
|
1004
|
-
const
|
|
1048
|
+
const globalState = useFlintStore();
|
|
1049
|
+
const resolvedUser = user ?? globalState.user;
|
|
1050
|
+
const resolvedSessionReplay = extraFields?.sessionReplay ?? globalState.sessionReplay;
|
|
1051
|
+
const getExternalReplayUrl = () => {
|
|
1052
|
+
const src = resolvedSessionReplay;
|
|
1053
|
+
return typeof src === "function" ? src() : src;
|
|
1054
|
+
};
|
|
1005
1055
|
const { t } = (0, import_react_i18next3.useTranslation)();
|
|
1006
|
-
const [open, setOpen] = (0,
|
|
1007
|
-
const [hovered, setHovered] = (0,
|
|
1056
|
+
const [open, setOpen] = (0, import_react3.useState)(false);
|
|
1057
|
+
const [hovered, setHovered] = (0, import_react3.useState)(false);
|
|
1008
1058
|
const colors = resolveTheme(theme);
|
|
1009
|
-
const consoleCollector = (0,
|
|
1010
|
-
const networkCollector = (0,
|
|
1011
|
-
const replayEvents = (0,
|
|
1012
|
-
const stopReplay = (0,
|
|
1059
|
+
const consoleCollector = (0, import_react3.useRef)(null);
|
|
1060
|
+
const networkCollector = (0, import_react3.useRef)(null);
|
|
1061
|
+
const replayEvents = (0, import_react3.useRef)([]);
|
|
1062
|
+
const stopReplay = (0, import_react3.useRef)(null);
|
|
1013
1063
|
if (!consoleCollector.current) {
|
|
1014
1064
|
consoleCollector.current = createConsoleCollector();
|
|
1015
1065
|
consoleCollector.current.start();
|
|
@@ -1018,7 +1068,7 @@ function WidgetContent({
|
|
|
1018
1068
|
networkCollector.current = createNetworkCollector();
|
|
1019
1069
|
networkCollector.current.start();
|
|
1020
1070
|
}
|
|
1021
|
-
(0,
|
|
1071
|
+
(0, import_react3.useEffect)(() => {
|
|
1022
1072
|
const stopFn = (0, import_rrweb.record)({
|
|
1023
1073
|
emit(event) {
|
|
1024
1074
|
replayEvents.current.push(event);
|
|
@@ -1046,7 +1096,7 @@ function WidgetContent({
|
|
|
1046
1096
|
"aria-label": label,
|
|
1047
1097
|
style: {
|
|
1048
1098
|
position: "fixed",
|
|
1049
|
-
bottom: "
|
|
1099
|
+
bottom: "40px",
|
|
1050
1100
|
right: "20px",
|
|
1051
1101
|
zIndex: zIndex - 1,
|
|
1052
1102
|
display: "flex",
|
|
@@ -1077,7 +1127,7 @@ function WidgetContent({
|
|
|
1077
1127
|
{
|
|
1078
1128
|
projectKey,
|
|
1079
1129
|
serverUrl,
|
|
1080
|
-
user,
|
|
1130
|
+
user: resolvedUser,
|
|
1081
1131
|
meta,
|
|
1082
1132
|
theme,
|
|
1083
1133
|
zIndex,
|
|
@@ -1086,7 +1136,7 @@ function WidgetContent({
|
|
|
1086
1136
|
getConsoleLogs: () => consoleCollector.current?.getEntries() ?? [],
|
|
1087
1137
|
getNetworkErrors: () => networkCollector.current?.getEntries() ?? [],
|
|
1088
1138
|
getReplayEvents: () => [...replayEvents.current],
|
|
1089
|
-
|
|
1139
|
+
getExternalReplayUrl
|
|
1090
1140
|
}
|
|
1091
1141
|
)
|
|
1092
1142
|
] });
|
|
@@ -1111,6 +1161,7 @@ function SparkIcon2() {
|
|
|
1111
1161
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1112
1162
|
0 && (module.exports = {
|
|
1113
1163
|
FlintModal,
|
|
1114
|
-
FlintWidget
|
|
1164
|
+
FlintWidget,
|
|
1165
|
+
flint
|
|
1115
1166
|
});
|
|
1116
1167
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/FlintWidget.tsx","../src/FlintModal.tsx","../src/api.ts","../src/theme.ts","../src/i18n/index.ts","../src/i18n/locales/en.json","../src/collectors/environment.ts","../src/collectors/console.ts","../src/collectors/network.ts"],"sourcesContent":["export { FlintWidget } from \"./FlintWidget.js\";\nexport { FlintModal } from \"./FlintModal.js\";\nexport type {\n FlintWidgetProps,\n FlintUser,\n Severity,\n Locale,\n Theme,\n ThemeOverride,\n ReportPayload,\n ReportResult,\n} from \"@flint/types\";\n","import { useState, useEffect, useRef } from \"react\";\nimport { I18nextProvider, useTranslation } from \"react-i18next\";\nimport { FlintModal } from \"./FlintModal.js\";\nimport type { FlintWidgetProps } from \"@flint/types\";\nimport { resolveTheme } from \"./theme.js\";\nimport widgetI18n from \"./i18n/index.js\";\nimport { collectEnvironment } from \"./collectors/environment.js\";\nimport { createConsoleCollector } from \"./collectors/console.js\";\nimport { createNetworkCollector } from \"./collectors/network.js\";\nimport { record } from \"rrweb\";\nimport type { eventWithTime } from \"@rrweb/types\";\n\nconst REPLAY_WINDOW_MS = 60_000; // rolling 60-second buffer\n\nexport function FlintWidget(props: FlintWidgetProps) {\n const { locale = \"en-US\" } = props;\n\n useEffect(() => {\n widgetI18n.changeLanguage(locale);\n }, [locale]);\n\n return (\n <I18nextProvider i18n={widgetI18n}>\n <WidgetContent {...props} />\n </I18nextProvider>\n );\n}\n\nfunction WidgetContent({\n projectKey,\n serverUrl,\n user,\n meta,\n extraFields,\n buttonLabel,\n theme = \"dark\",\n zIndex = 9999,\n}: FlintWidgetProps) {\n const externalReplayUrl = extraFields?.sessionReplay;\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const [hovered, setHovered] = useState(false);\n const colors = resolveTheme(theme);\n\n // ── Collectors ─────────────────────────────────────────────────────────────\n // Start synchronously so window.fetch is patched before React effects run,\n // ensuring the admin's initial API requests are captured.\n const consoleCollector = useRef<ReturnType<typeof createConsoleCollector> | null>(null);\n const networkCollector = useRef<ReturnType<typeof createNetworkCollector> | null>(null);\n const replayEvents = useRef<eventWithTime[]>([]);\n const stopReplay = useRef<(() => void) | null>(null);\n\n if (!consoleCollector.current) {\n consoleCollector.current = createConsoleCollector();\n consoleCollector.current.start();\n }\n if (!networkCollector.current) {\n networkCollector.current = createNetworkCollector();\n networkCollector.current.start();\n }\n\n useEffect(() => {\n // Start rrweb recording with rolling buffer (must be in effect for DOM access)\n const stopFn = record({\n emit(event) {\n replayEvents.current.push(event);\n // Trim to rolling window\n const cutoff = Date.now() - REPLAY_WINDOW_MS;\n while (\n replayEvents.current.length > 0 &&\n replayEvents.current[0].timestamp < cutoff\n ) {\n replayEvents.current.shift();\n }\n },\n });\n stopReplay.current = stopFn ?? null;\n\n return () => {\n consoleCollector.current?.stop();\n networkCollector.current?.stop();\n stopReplay.current?.();\n };\n }, []);\n\n const label = buttonLabel ?? t(\"buttonLabel\");\n\n return (\n <>\n {/* Floating trigger button */}\n <button\n onClick={() => setOpen(true)}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n aria-label={label}\n style={{\n position: \"fixed\",\n bottom: \"20px\",\n right: \"20px\",\n zIndex: zIndex - 1,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n padding: \"10px 18px\",\n borderRadius: \"24px\",\n border: \"none\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n fontSize: \"13px\",\n fontWeight: 600,\n cursor: \"pointer\",\n boxShadow: hovered\n ? `0 0 28px ${colors.accent}55, 0 8px 24px rgba(0,0,0,0.3)`\n : `0 0 16px ${colors.accent}33, 0 4px 16px rgba(0,0,0,0.2)`,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n transform: hovered ? \"translateY(-2px)\" : \"translateY(0)\",\n transition: \"transform 0.15s ease, box-shadow 0.15s ease\",\n letterSpacing: \"0.01em\",\n }}\n >\n <SparkIcon />\n {label}\n </button>\n\n {/* Modal */}\n {open && (\n <FlintModal\n projectKey={projectKey}\n serverUrl={serverUrl}\n user={user}\n meta={meta}\n theme={theme}\n zIndex={zIndex}\n onClose={() => setOpen(false)}\n getEnvironment={collectEnvironment}\n getConsoleLogs={() => consoleCollector.current?.getEntries() ?? []}\n getNetworkErrors={() => networkCollector.current?.getEntries() ?? []}\n getReplayEvents={() => [...replayEvents.current]}\n externalReplayUrl={externalReplayUrl}\n />\n )}\n </>\n );\n}\n\nfunction SparkIcon() {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n );\n}\n","import { useRef, useState, useEffect, useCallback } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport type {\n Severity,\n FlintUser,\n Theme,\n ReportResult,\n EnvironmentInfo,\n ConsoleEntry,\n NetworkEntry,\n} from \"@flint/types\";\nimport type { eventWithTime } from \"@rrweb/types\";\nimport { submitReport, submitReplay } from \"./api.js\";\nimport { resolveTheme } from \"./theme.js\";\n\ninterface Props {\n projectKey: string;\n serverUrl: string;\n user?: FlintUser;\n meta?: Record<string, unknown>;\n theme: Theme;\n zIndex: number;\n onClose: () => void;\n getEnvironment: () => EnvironmentInfo;\n getConsoleLogs: () => ConsoleEntry[];\n getNetworkErrors: () => NetworkEntry[];\n getReplayEvents: () => eventWithTime[];\n externalReplayUrl?: string;\n}\n\nconst SEVERITIES: Severity[] = [\"P1\", \"P2\", \"P3\", \"P4\"];\nconst SEV_COLOR: Record<Severity, string> = {\n P1: \"#ef4444\",\n P2: \"#f97316\",\n P3: \"#eab308\",\n P4: \"#22c55e\",\n};\n\ntype Status = \"idle\" | \"submitting\" | \"success\" | \"error\";\n\n// Inject CSS keyframes once — animations can't be done with inline styles alone\nfunction injectKeyframes() {\n if (typeof document === \"undefined\") return;\n if (document.getElementById(\"_flint_kf\")) return;\n const s = document.createElement(\"style\");\n s.id = \"_flint_kf\";\n s.textContent = `\n @keyframes _flint_in {\n from { opacity: 0; transform: scale(0.93) translateY(10px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n }\n @keyframes _flint_overlay_in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n @keyframes _flint_spin {\n to { transform: rotate(360deg); }\n }\n @keyframes _flint_pulse {\n 0%, 100% { opacity: 0.5; transform: scale(0.88); }\n 50% { opacity: 1; transform: scale(1.08); }\n }\n @keyframes _flint_ripple {\n 0% { opacity: 0.5; transform: scale(0.75); }\n 100% { opacity: 0; transform: scale(1.55); }\n }\n @keyframes _flint_sending_dot {\n 0%, 80%, 100% { opacity: 0.2; transform: scale(0.8); }\n 40% { opacity: 1; transform: scale(1); }\n }\n @keyframes _flint_success_up {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `;\n document.head.appendChild(s);\n}\n\nexport function FlintModal({\n projectKey,\n serverUrl,\n user,\n meta,\n theme,\n zIndex,\n onClose,\n getEnvironment,\n getConsoleLogs,\n getNetworkErrors,\n getReplayEvents,\n externalReplayUrl,\n}: Props) {\n const { t } = useTranslation();\n const colors = resolveTheme(theme);\n const isDark = theme === \"dark\";\n\n const [severity, setSeverity] = useState<Severity>(\"P2\");\n const [description, setDescription] = useState(\"\");\n const [expectedBehavior, setExpectedBehavior] = useState(\"\");\n const [screenshot, setScreenshot] = useState<File | null>(null);\n const [status, setStatus] = useState<Status>(\"idle\");\n const [result, setResult] = useState<ReportResult | null>(null);\n const [errorMsg, setErrorMsg] = useState(\"\");\n\n const fileRef = useRef<HTMLInputElement>(null);\n const overlayRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => { injectKeyframes(); }, []);\n\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && status !== \"submitting\") onClose();\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [onClose, status]);\n\n const handleOverlayClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === overlayRef.current && status !== \"submitting\") onClose();\n },\n [onClose, status],\n );\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!description.trim()) return;\n\n setStatus(\"submitting\");\n setErrorMsg(\"\");\n\n const collectedMeta: Record<string, unknown> = {\n ...meta,\n environment: getEnvironment(),\n consoleLogs: getConsoleLogs(),\n networkErrors: getNetworkErrors(),\n };\n\n try {\n const res = await submitReport(\n serverUrl,\n projectKey,\n {\n reporterId: user?.id ?? \"anonymous\",\n reporterName: user?.name ?? \"Anonymous\",\n description: description.trim(),\n expectedBehavior: expectedBehavior.trim() || undefined,\n externalReplayUrl: externalReplayUrl || undefined,\n severity,\n url: window.location.href,\n meta: collectedMeta,\n },\n screenshot ?? undefined,\n );\n setResult(res);\n setStatus(\"success\");\n\n const events = getReplayEvents();\n if (events.length > 0) {\n submitReplay(serverUrl, projectKey, res.id, events).catch(() => {});\n }\n } catch (err) {\n setErrorMsg(err instanceof Error ? err.message : t(\"errorLabel\"));\n setStatus(\"error\");\n }\n };\n\n // ── Shared style tokens ────────────────────────────────────────────────────\n const inputBorder = isDark ? \"rgba(255,255,255,0.1)\" : \"rgba(0,0,0,0.1)\";\n const accentGlow = `0 0 20px ${colors.accent}40, 0 4px 16px rgba(0,0,0,0.2)`;\n\n const overlayStyle: React.CSSProperties = {\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.5)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex,\n padding: \"16px\",\n backdropFilter: \"blur(10px)\",\n WebkitBackdropFilter: \"blur(10px)\",\n animation: \"_flint_overlay_in 0.2s ease\",\n };\n\n const modalStyle: React.CSSProperties = {\n background: colors.background,\n backdropFilter: colors.backdropFilter,\n WebkitBackdropFilter: colors.backdropFilter,\n borderRadius: \"20px\",\n boxShadow: colors.shadow,\n border: `1px solid ${colors.border}`,\n width: \"100%\",\n maxWidth: \"480px\",\n maxHeight: \"92vh\",\n overflowY: \"auto\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n color: colors.text,\n animation: \"_flint_in 0.28s cubic-bezier(0.16, 1, 0.3, 1)\",\n };\n\n const inputStyle: React.CSSProperties = {\n width: \"100%\",\n padding: \"11px 13px\",\n borderRadius: \"10px\",\n border: `1px solid ${inputBorder}`,\n background: colors.backgroundSecondary,\n color: colors.text,\n fontSize: \"14px\",\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"inherit\",\n transition: \"border-color 0.15s\",\n };\n\n // ── Loading + Success (unified animated state) ────────────────────────────\n if (status === \"submitting\" || status === \"success\") {\n const isSuccess = status === \"success\";\n const ringBorder = isSuccess\n ? \"3px solid #22c55e\"\n : `3px solid ${isDark ? \"rgba(255,255,255,0.08)\" : \"rgba(0,0,0,0.08)\"}`;\n const ringTopColor = isSuccess ? \"#22c55e\" : colors.accent;\n\n return (\n <div style={overlayStyle}>\n <div style={modalStyle} role=\"dialog\" aria-modal=\"true\" aria-label={isSuccess ? t(\"successTitle\") : t(\"sending\")}>\n <ModalHeader colors={colors} inputBorder={inputBorder} showClose={false} onClose={onClose} />\n\n <div style={{ padding: \"40px 32px 48px\", textAlign: \"center\", display: \"flex\", flexDirection: \"column\", alignItems: \"center\" }}>\n {/* Animated rings */}\n <div style={{ position: \"relative\", width: 80, height: 80, marginBottom: 28 }}>\n {/* Ripple 1 — fade out on success */}\n <div style={{\n position: \"absolute\", inset: -10,\n borderRadius: \"50%\",\n border: `1.5px solid ${colors.accent}`,\n animation: \"_flint_ripple 1.8s ease-out infinite\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }} />\n {/* Ripple 2 (delayed) */}\n <div style={{\n position: \"absolute\", inset: -10,\n borderRadius: \"50%\",\n border: `1.5px solid ${colors.accent}`,\n animation: \"_flint_ripple 1.8s ease-out infinite 0.6s\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }} />\n {/* Spinning ring — transitions to solid green on success */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n border: ringBorder,\n borderTopColor: ringTopColor,\n animation: isSuccess ? \"none\" : \"_flint_spin 0.85s linear infinite\",\n transition: \"border-color 0.45s ease, border-top-color 0.45s ease\",\n }} />\n {/* Center: spark fades out, check fades in */}\n <div style={{ position: \"absolute\", inset: 14, borderRadius: \"50%\" }}>\n {/* Spark */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n background: `linear-gradient(135deg, ${colors.accent}30, ${colors.accentHover}50)`,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n animation: isSuccess ? \"none\" : \"_flint_pulse 2s ease-in-out infinite\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }}>\n <SparkIcon color={colors.accent} size={20} />\n </div>\n {/* Checkmark */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n background: \"rgba(34,197,94,0.15)\",\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"scale(1)\" : \"scale(0.65)\",\n transition: \"opacity 0.35s ease 0.2s, transform 0.4s cubic-bezier(0.16,1,0.3,1) 0.2s\",\n }}>\n <CheckIcon size={20} />\n </div>\n </div>\n </div>\n\n {/* Title crossfade */}\n <div style={{ position: \"relative\", height: 26, width: \"100%\", marginBottom: 10 }}>\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n fontSize: 17, fontWeight: 700, color: colors.text, letterSpacing: \"-0.02em\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.25s ease\",\n pointerEvents: \"none\",\n }}>\n {t(\"sending\")}\n </div>\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n fontSize: 17, fontWeight: 700, color: colors.text, letterSpacing: \"-0.02em\",\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"translateY(0)\" : \"translateY(6px)\",\n transition: \"opacity 0.35s ease 0.25s, transform 0.35s ease 0.25s\",\n pointerEvents: isSuccess ? \"auto\" : \"none\",\n }}>\n {t(\"successTitle\")}\n </div>\n </div>\n\n {/* Subtitle crossfade */}\n <div style={{ position: \"relative\", minHeight: 76, width: \"100%\" }}>\n {/* Loading subtitle */}\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n gap: 6, color: colors.textMuted, fontSize: 13,\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.2s ease\",\n pointerEvents: \"none\",\n }}>\n <span>{t(\"capturingContext\")}</span>\n <SendingDots color={colors.accent} />\n </div>\n {/* Success subtitle */}\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", flexDirection: \"column\", alignItems: \"center\", gap: 10,\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"translateY(0)\" : \"translateY(8px)\",\n transition: \"opacity 0.35s ease 0.35s, transform 0.35s ease 0.35s\",\n pointerEvents: isSuccess ? \"auto\" : \"none\",\n }}>\n <p style={{ fontSize: 13, color: colors.textMuted, margin: 0 }}>\n {result?.isDuplicate ? t(\"successDuplicate\") : result ? `ID: ${result.id}` : \"\"}\n </p>\n {result?.githubIssueUrl && (\n <a\n href={result.githubIssueUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 6,\n padding: \"9px 18px\",\n borderRadius: \"10px\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n textDecoration: \"none\",\n fontSize: \"13px\",\n fontWeight: 600,\n boxShadow: accentGlow,\n }}\n >\n {t(\"successGitHub\")} ↗\n </a>\n )}\n <button\n onClick={onClose}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n padding: \"4px 8px\",\n fontFamily: \"inherit\",\n }}\n >\n {t(\"cancel\")}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n // ── Form ──────────────────────────────────────────────────────────────────\n return (\n <div ref={overlayRef} style={overlayStyle} onClick={handleOverlayClick}>\n <div style={modalStyle} role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"flint-modal-title\">\n <ModalHeader\n colors={colors}\n inputBorder={inputBorder}\n showClose\n onClose={onClose}\n titleId=\"flint-modal-title\"\n title={t(\"modalTitle\")}\n />\n\n <form onSubmit={handleSubmit} style={{ padding: \"20px 24px 24px\" }}>\n {/* Severity */}\n <div style={{ marginBottom: 18 }}>\n <FieldLabel colors={colors}>{t(\"severityLabel\")}</FieldLabel>\n <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(4,1fr)\", gap: 8 }}>\n {SEVERITIES.map((sev) => (\n <SeverityButton\n key={sev}\n sev={sev}\n label={t(`severity_${sev}_label`)}\n selected={severity === sev}\n hint={t(`severity_${sev}_hint`)}\n color={SEV_COLOR[sev]}\n accent={colors.accent}\n border={inputBorder}\n bg={colors.backgroundSecondary}\n text={colors.text}\n onClick={() => setSeverity(sev)}\n />\n ))}\n </div>\n </div>\n\n {/* What Is Broken */}\n <div style={{ marginBottom: 14 }}>\n <FieldLabel colors={colors} htmlFor=\"flint-description\">{t(\"whatIsBrokenLabel\")}</FieldLabel>\n <textarea\n id=\"flint-description\"\n style={{ ...inputStyle, resize: \"vertical\", minHeight: 80 }}\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder={t(\"whatIsBrokenPlaceholder\")}\n required\n />\n </div>\n\n {/* Expected Behavior (optional) */}\n <div style={{ marginBottom: 14 }}>\n <FieldLabel colors={colors} htmlFor=\"flint-expected\">{t(\"expectedBehaviorLabel\")}</FieldLabel>\n <textarea\n id=\"flint-expected\"\n style={{ ...inputStyle, resize: \"vertical\", minHeight: 72 }}\n value={expectedBehavior}\n onChange={(e) => setExpectedBehavior(e.target.value)}\n placeholder={t(\"expectedBehaviorPlaceholder\")}\n />\n </div>\n\n {/* Screenshot */}\n <div style={{ marginBottom: 20 }}>\n <FieldLabel colors={colors}>{t(\"screenshotLabel\")}</FieldLabel>\n <label\n htmlFor=\"flint-screenshot\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"10px 13px\",\n borderRadius: 10,\n border: `1px dashed ${inputBorder}`,\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n background: colors.backgroundSecondary,\n }}\n >\n 📎 {screenshot ? screenshot.name : t(\"screenshotPlaceholder\")}\n </label>\n <input\n id=\"flint-screenshot\"\n ref={fileRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={(e) => setScreenshot(e.target.files?.[0] ?? null)}\n />\n </div>\n\n {/* Error */}\n {status === \"error\" && (\n <div style={{\n padding: \"10px 13px\",\n borderRadius: 10,\n background: \"rgba(239,68,68,0.08)\",\n border: \"1px solid rgba(239,68,68,0.2)\",\n color: \"#f87171\",\n fontSize: 12,\n marginBottom: 16,\n }}>\n ⚠️ {errorMsg || t(\"errorLabel\")}\n </div>\n )}\n\n {/* Submit */}\n <button\n type=\"submit\"\n style={{\n width: \"100%\",\n padding: \"13px 20px\",\n borderRadius: 12,\n border: \"none\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n fontSize: 15,\n fontWeight: 700,\n cursor: \"pointer\",\n letterSpacing: \"-0.01em\",\n boxShadow: accentGlow,\n fontFamily: \"inherit\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 8,\n }}\n >\n <SparkIcon color={colors.buttonText} size={15} />\n {t(\"submitLabel\")}\n </button>\n\n {/* Cancel */}\n <button\n type=\"button\"\n onClick={onClose}\n style={{\n width: \"100%\",\n padding: \"10px\",\n marginTop: 8,\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n fontFamily: \"inherit\",\n borderRadius: 8,\n }}\n >\n {t(\"cancel\")}\n </button>\n </form>\n </div>\n </div>\n );\n}\n\n// ─── Sub-components ──────────────────────────────────────────────────────────\n\nfunction ModalHeader({\n colors,\n inputBorder,\n showClose,\n onClose,\n titleId,\n title,\n}: {\n colors: ReturnType<typeof resolveTheme>;\n inputBorder: string;\n showClose: boolean;\n onClose: () => void;\n titleId?: string;\n title?: string;\n}) {\n return (\n <div style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n padding: \"16px 20px 14px\",\n borderBottom: `1px solid ${inputBorder}`,\n }}>\n {/* Brand chip */}\n <div style={{\n width: 28, height: 28,\n borderRadius: 8,\n background: `linear-gradient(135deg, ${colors.accent}20, ${colors.accentHover}35)`,\n border: `1px solid ${colors.accent}30`,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n flexShrink: 0,\n }}>\n <SparkIcon color={colors.accent} size={13} />\n </div>\n\n {titleId && title ? (\n <h2 id={titleId} style={{ margin: 0, fontSize: 14, fontWeight: 600, color: colors.text, letterSpacing: \"-0.01em\", flex: 1 }}>\n {title}\n </h2>\n ) : (\n <span style={{ flex: 1, fontSize: 13, fontWeight: 600, color: colors.textMuted }}>Flint</span>\n )}\n\n {showClose && (\n <button\n onClick={onClose}\n aria-label=\"Close\"\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: 4,\n color: colors.textMuted,\n fontSize: 20,\n lineHeight: 1,\n borderRadius: 6,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n opacity: 0.6,\n fontFamily: \"inherit\",\n }}\n >\n ×\n </button>\n )}\n </div>\n );\n}\n\nfunction FieldLabel({\n children,\n colors,\n htmlFor,\n}: {\n children: React.ReactNode;\n colors: ReturnType<typeof resolveTheme>;\n htmlFor?: string;\n}) {\n return (\n <label\n htmlFor={htmlFor}\n style={{\n display: \"block\",\n fontSize: \"10px\",\n fontWeight: 700,\n color: colors.textMuted,\n marginBottom: 6,\n textTransform: \"uppercase\" as const,\n letterSpacing: \"0.07em\",\n }}\n >\n {children}\n </label>\n );\n}\n\nfunction SendingDots({ color }: { color: string }) {\n return (\n <span style={{ display: \"inline-flex\", gap: 3, alignItems: \"center\" }}>\n {[0, 1, 2].map((i) => (\n <span\n key={i}\n style={{\n width: 4, height: 4,\n borderRadius: \"50%\",\n background: color,\n display: \"inline-block\",\n animation: `_flint_sending_dot 1.4s ease-in-out infinite ${i * 0.2}s`,\n }}\n />\n ))}\n </span>\n );\n}\n\ninterface SevBtnProps {\n sev: Severity;\n label: string;\n selected: boolean;\n hint: string;\n color: string;\n accent: string;\n border: string;\n bg: string;\n text: string;\n onClick: () => void;\n}\n\nfunction SeverityButton({ sev, label, selected, hint, color, accent, border, bg, text, onClick }: SevBtnProps) {\n return (\n <button\n type=\"button\"\n title={hint}\n onClick={onClick}\n style={{\n padding: \"9px 6px 8px\",\n borderRadius: 10,\n border: selected ? `2px solid ${accent}` : `1.5px solid ${border}`,\n background: selected ? `${accent}15` : bg,\n cursor: \"pointer\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: 5,\n transition: \"border-color 0.12s, background 0.12s\",\n fontFamily: \"inherit\",\n }}\n >\n <span style={{ width: 8, height: 8, borderRadius: \"50%\", background: color, display: \"block\" }} />\n <span style={{ fontSize: 11, fontWeight: selected ? 700 : 500, color: selected ? accent : text, letterSpacing: \"0.02em\" }}>\n {sev}\n </span>\n <span style={{ fontSize: 9, color: selected ? accent : text, opacity: 0.6, letterSpacing: \"0.02em\" }}>\n {label}\n </span>\n </button>\n );\n}\n\nfunction SparkIcon({ color = \"currentColor\", size = 14 }: { color?: string; size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n );\n}\n\nfunction CheckIcon({ size = 20 }: { size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#22c55e\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n","import type { ReportPayload, ReportResult } from \"@flint/types\";\nimport { gzipSync } from \"fflate\";\nimport type { eventWithTime } from \"@rrweb/types\";\n\nexport async function submitReport(\n serverUrl: string,\n projectKey: string,\n payload: ReportPayload,\n screenshot?: File,\n): Promise<ReportResult> {\n const url = `${serverUrl.replace(/\\/$/, \"\")}/api/v1/bug-reports`;\n\n let body: BodyInit;\n let headers: Record<string, string> = {\n \"x-project-key\": projectKey,\n };\n\n if (screenshot) {\n const form = new FormData();\n form.append(\"reporterId\", payload.reporterId);\n form.append(\"reporterName\", payload.reporterName);\n form.append(\"description\", payload.description);\n if (payload.expectedBehavior) form.append(\"expectedBehavior\", payload.expectedBehavior);\n if (payload.stepsToReproduce) form.append(\"stepsToReproduce\", JSON.stringify(payload.stepsToReproduce));\n if (payload.externalReplayUrl) form.append(\"externalReplayUrl\", payload.externalReplayUrl);\n if (payload.additionalContext) form.append(\"additionalContext\", payload.additionalContext);\n form.append(\"severity\", payload.severity);\n if (payload.url) form.append(\"url\", payload.url);\n if (payload.meta) form.append(\"meta\", JSON.stringify(payload.meta));\n form.append(\"screenshot\", screenshot);\n body = form;\n } else {\n body = JSON.stringify(payload);\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const res = await fetch(url, { method: \"POST\", headers, body });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: \"Unknown error\" }));\n throw new Error((err as { error?: string }).error ?? `HTTP ${res.status}`);\n }\n\n return res.json() as Promise<ReportResult>;\n}\n\nexport async function submitReplay(\n serverUrl: string,\n projectKey: string,\n reportId: string,\n events: eventWithTime[],\n): Promise<void> {\n const json = JSON.stringify(events);\n const encoded = new TextEncoder().encode(json);\n const compressed = gzipSync(encoded);\n\n const url = `${serverUrl.replace(/\\/$/, \"\")}/api/v1/bug-reports/${reportId}/replay`;\n await fetch(url, {\n method: \"POST\",\n headers: {\n \"x-project-key\": projectKey,\n \"Content-Type\": \"application/octet-stream\",\n },\n body: compressed.buffer as ArrayBuffer,\n });\n}\n","import type { Theme, ThemeOverride } from \"@flint/types\";\n\nexport interface ResolvedTheme {\n background: string;\n backgroundSecondary: string;\n accent: string;\n accentHover: string;\n text: string;\n textMuted: string;\n border: string;\n shadow: string;\n buttonText: string;\n backdropFilter: string;\n}\n\nconst light: ResolvedTheme = {\n background: \"rgba(255,255,255,0.90)\",\n backgroundSecondary: \"rgba(249,250,251,0.75)\",\n accent: \"#2563eb\",\n accentHover: \"#1d4ed8\",\n text: \"#111827\",\n textMuted: \"#6b7280\",\n border: \"rgba(255,255,255,0.9)\",\n shadow:\n \"0 32px 80px rgba(0,0,0,0.18), 0 8px 32px rgba(0,0,0,0.1), 0 0 0 1px rgba(0,0,0,0.04)\",\n buttonText: \"#ffffff\",\n backdropFilter: \"blur(32px) saturate(1.8)\",\n};\n\nconst dark: ResolvedTheme = {\n background: \"rgba(15,20,35,0.88)\",\n backgroundSecondary: \"rgba(5,8,18,0.65)\",\n accent: \"#f97316\",\n accentHover: \"#ea6c0a\",\n text: \"#dde3ef\",\n textMuted: \"#6b7a93\",\n border: \"rgba(255,255,255,0.08)\",\n shadow:\n \"0 24px 60px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04)\",\n buttonText: \"#ffffff\",\n backdropFilter: \"blur(32px) saturate(1.6)\",\n};\n\nexport function resolveTheme(theme: Theme): ResolvedTheme {\n if (theme === \"dark\") return dark;\n if (theme === \"light\") return light;\n // ThemeOverride — merge over light base\n const override = theme as ThemeOverride;\n return {\n ...light,\n background: override.background ?? light.background,\n accent: override.accent ?? light.accent,\n accentHover: override.accent ?? light.accentHover,\n text: override.text ?? light.text,\n border: override.border ?? light.border,\n };\n}\n","import i18next, { createInstance } from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\nimport en from \"./locales/en.json\";\n\nexport const widgetI18n: ReturnType<typeof createInstance> = createInstance();\n\nwidgetI18n.use(initReactI18next).init({\n lng: \"en-US\",\n fallbackLng: \"en-US\",\n resources: { \"en-US\": { translation: en } },\n interpolation: { escapeValue: false },\n initImmediate: false,\n});\n\nexport default widgetI18n;\n","{\n \"buttonLabel\": \"Report bug\",\n \"modalTitle\": \"Report an issue\",\n \"severityLabel\": \"Severity\",\n \"severity_P1_hint\": \"Critical — system down\",\n \"severity_P2_hint\": \"High — core feature broken\",\n \"severity_P3_hint\": \"Medium — noticeable but workable\",\n \"severity_P4_hint\": \"Low — cosmetic or improvement\",\n \"severity_P1_label\": \"Critical\",\n \"severity_P2_label\": \"High\",\n \"severity_P3_label\": \"Medium\",\n \"severity_P4_label\": \"Low\",\n \"whatIsBrokenLabel\": \"What Is Broken\",\n \"whatIsBrokenPlaceholder\": \"1–2 sentences: what is currently happening that should NOT happen.\",\n \"expectedBehaviorLabel\": \"Expected Behavior (optional)\",\n \"expectedBehaviorPlaceholder\": \"Describe exactly what the user should see or receive after the fix.\",\n \"screenshotLabel\": \"Screenshot (optional)\",\n \"screenshotPlaceholder\": \"Click to attach...\",\n \"submitLabel\": \"Submit\",\n \"successTitle\": \"Bug reported!\",\n \"successDuplicate\": \"Looks like a duplicate of an existing bug.\",\n \"successGitHub\": \"View GitHub issue\",\n \"errorLabel\": \"Failed to submit. Please try again.\",\n \"cancel\": \"Cancel\",\n \"sending\": \"Sending report\",\n \"capturingContext\": \"Capturing context\"\n}\n","import type { EnvironmentInfo } from \"@flint/types\";\n\nexport function collectEnvironment(): EnvironmentInfo {\n const ua = navigator.userAgent;\n\n // ── Browser ──────────────────────────────────────────────────────────────\n let browser = \"Unknown\";\n const chromeM = ua.match(/Chrome\\/(\\d+)/);\n const firefoxM = ua.match(/Firefox\\/(\\d+)/);\n const edgeM = ua.match(/Edg\\/(\\d+)/);\n const safariM = ua.match(/Version\\/(\\d+)/);\n const operaM = ua.match(/OPR\\/(\\d+)/);\n\n if (operaM) {\n browser = `Opera ${operaM[1]}`;\n } else if (edgeM) {\n browser = `Edge ${edgeM[1]}`;\n } else if (chromeM && !/Edg|OPR/.test(ua)) {\n browser = `Chrome ${chromeM[1]}`;\n } else if (firefoxM) {\n browser = `Firefox ${firefoxM[1]}`;\n } else if (safariM && /Safari\\//.test(ua)) {\n browser = `Safari ${safariM[1]}`;\n }\n\n // ── OS ────────────────────────────────────────────────────────────────────\n let os = \"Unknown\";\n const macM = ua.match(/Mac OS X (\\d+[._]\\d+)/);\n const winM = ua.match(/Windows NT (\\d+\\.\\d+)/);\n const androidM = ua.match(/Android (\\d+)/);\n const iosM = ua.match(/iPhone OS (\\d+[._]\\d+)/);\n\n if (macM) {\n os = `macOS ${macM[1].replace(\"_\", \".\")}`;\n } else if (winM) {\n const winMap: Record<string, string> = {\n \"10.0\": \"10/11\",\n \"6.3\": \"8.1\",\n \"6.2\": \"8\",\n \"6.1\": \"7\",\n };\n os = `Windows ${winMap[winM[1]] ?? winM[1]}`;\n } else if (androidM) {\n os = `Android ${androidM[1]}`;\n } else if (iosM) {\n os = `iOS ${iosM[1].replace(/_/g, \".\")}`;\n } else if (/Linux/.test(ua)) {\n os = \"Linux\";\n }\n\n return {\n browser,\n os,\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n screen: `${screen.width}x${screen.height}`,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n online: navigator.onLine,\n };\n}\n","import type { ConsoleEntry } from \"@flint/types\";\n\nconst MAX_ENTRIES = 50;\n\nexport interface ConsoleCollector {\n start(): void;\n stop(): void;\n getEntries(): ConsoleEntry[];\n}\n\nexport function createConsoleCollector(): ConsoleCollector {\n const entries: ConsoleEntry[] = [];\n let active = false;\n\n const originals = {\n log: console.log.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n };\n\n let origOnerror: typeof window.onerror = null;\n let origUnhandled: typeof window.onunhandledrejection = null;\n\n function push(level: ConsoleEntry[\"level\"], args: unknown[]) {\n let str: string;\n try {\n str = args\n .map((a) => (typeof a === \"string\" ? a : JSON.stringify(a)))\n .join(\" \");\n } catch {\n str = String(args[0]);\n }\n if (str.length > 500) str = str.slice(0, 500) + \"…\";\n entries.push({ level, args: str, timestamp: Date.now() });\n if (entries.length > MAX_ENTRIES) entries.shift();\n }\n\n return {\n start() {\n if (active) return;\n active = true;\n\n console.log = (...args: unknown[]) => {\n push(\"log\", args);\n originals.log(...args);\n };\n console.warn = (...args: unknown[]) => {\n push(\"warn\", args);\n originals.warn(...args);\n };\n console.error = (...args: unknown[]) => {\n push(\"error\", args);\n originals.error(...args);\n };\n\n origOnerror = window.onerror;\n window.onerror = (msg, src, line, col, err) => {\n push(\"error\", [err?.message ?? String(msg), `${src}:${line}:${col}`]);\n if (typeof origOnerror === \"function\")\n return origOnerror(msg, src, line, col, err);\n return false;\n };\n\n origUnhandled = window.onunhandledrejection;\n window.onunhandledrejection = (event) => {\n const reason =\n event.reason instanceof Error\n ? event.reason.message\n : JSON.stringify(event.reason);\n push(\"error\", [\"UnhandledRejection:\", reason]);\n if (typeof origUnhandled === \"function\")\n origUnhandled.call(window, event);\n };\n },\n\n stop() {\n if (!active) return;\n active = false;\n console.log = originals.log;\n console.warn = originals.warn;\n console.error = originals.error;\n window.onerror = origOnerror;\n window.onunhandledrejection = origUnhandled;\n },\n\n getEntries() {\n return [...entries];\n },\n };\n}\n","import type { NetworkEntry } from \"@flint/types\";\n\nconst MAX_ENTRIES = 20;\n\nexport interface NetworkCollector {\n start(): void;\n stop(): void;\n getEntries(): NetworkEntry[];\n}\n\nfunction truncateUrl(url: string): string {\n try {\n const u = new URL(url, location.href);\n const base = `${u.origin}${u.pathname}`;\n return base.length > 200 ? base.slice(0, 200) + \"…\" : base;\n } catch {\n return url.length > 200 ? url.slice(0, 200) + \"…\" : url;\n }\n}\n\nexport function createNetworkCollector(): NetworkCollector {\n const entries: NetworkEntry[] = [];\n let origFetch: typeof window.fetch | null = null;\n let origXHROpen: typeof XMLHttpRequest.prototype.open | null = null;\n let active = false;\n\n function push(entry: NetworkEntry) {\n entries.push(entry);\n if (entries.length > MAX_ENTRIES) entries.shift();\n }\n\n return {\n start() {\n if (active) return;\n active = true;\n\n // ── Patch fetch ────────────────────────────────────────────────────────\n origFetch = window.fetch;\n window.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const method = ((init?.method ?? \"GET\") as string).toUpperCase();\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : (input as Request).url;\n const startTime = Date.now();\n const res = await origFetch!.call(window, input, init);\n push({\n method,\n url: truncateUrl(url),\n status: res.status,\n duration: Date.now() - startTime,\n timestamp: startTime,\n });\n return res;\n };\n\n // ── Patch XHR ─────────────────────────────────────────────────────────\n origXHROpen = XMLHttpRequest.prototype.open;\n XMLHttpRequest.prototype.open = function (\n method: string,\n url: string | URL,\n async?: boolean,\n username?: string | null,\n password?: string | null,\n ) {\n const startTime = Date.now();\n const urlStr =\n typeof url === \"string\" ? url : (url as URL).href;\n\n this.addEventListener(\"load\", () => {\n push({\n method: method.toUpperCase(),\n url: truncateUrl(urlStr),\n status: this.status,\n duration: Date.now() - startTime,\n timestamp: startTime,\n });\n });\n\n return origXHROpen!.apply(this, [\n method,\n url,\n async ?? true,\n username,\n password,\n ] as Parameters<typeof XMLHttpRequest.prototype.open>);\n };\n },\n\n stop() {\n if (!active) return;\n active = false;\n if (origFetch) window.fetch = origFetch;\n if (origXHROpen) XMLHttpRequest.prototype.open = origXHROpen;\n },\n\n getEntries() {\n return [...entries];\n },\n };\n}\n"],"mappings":"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","names":["import_react","import_react_i18next","import_react_i18next","MAX_ENTRIES","import_jsx_runtime","SparkIcon"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/FlintWidget.tsx","../src/FlintModal.tsx","../src/api.ts","../src/theme.ts","../src/i18n/index.ts","../src/i18n/locales/en.json","../src/collectors/environment.ts","../src/collectors/console.ts","../src/collectors/network.ts","../src/store.ts"],"sourcesContent":["export { FlintWidget } from \"./FlintWidget.js\";\nexport { FlintModal } from \"./FlintModal.js\";\nexport { flint } from \"./store.js\";\nexport type {\n FlintWidgetProps,\n FlintUser,\n Severity,\n Locale,\n Theme,\n ThemeOverride,\n ReportPayload,\n ReportResult,\n} from \"@flint/types\";\n","import { useState, useEffect, useRef } from \"react\";\nimport { I18nextProvider, useTranslation } from \"react-i18next\";\nimport { FlintModal } from \"./FlintModal.js\";\nimport type { FlintWidgetProps } from \"@flint/types\";\nimport { resolveTheme } from \"./theme.js\";\nimport widgetI18n from \"./i18n/index.js\";\nimport { collectEnvironment } from \"./collectors/environment.js\";\nimport { createConsoleCollector } from \"./collectors/console.js\";\nimport { createNetworkCollector } from \"./collectors/network.js\";\nimport { useFlintStore } from \"./store.js\";\nimport { record } from \"rrweb\";\nimport type { eventWithTime } from \"@rrweb/types\";\n\nconst REPLAY_WINDOW_MS = 60_000; // rolling 60-second buffer\n\nexport function FlintWidget(props: FlintWidgetProps) {\n const { locale = \"en-US\" } = props;\n\n useEffect(() => {\n widgetI18n.changeLanguage(locale);\n }, [locale]);\n\n return (\n <I18nextProvider i18n={widgetI18n}>\n <WidgetContent {...props} />\n </I18nextProvider>\n );\n}\n\nfunction WidgetContent({\n projectKey,\n serverUrl,\n user,\n meta,\n extraFields,\n buttonLabel,\n theme = \"dark\",\n zIndex = 9999,\n}: FlintWidgetProps) {\n const globalState = useFlintStore();\n const resolvedUser = user ?? globalState.user;\n const resolvedSessionReplay = extraFields?.sessionReplay ?? globalState.sessionReplay;\n const getExternalReplayUrl = () => {\n const src = resolvedSessionReplay;\n return typeof src === \"function\" ? src() : src;\n };\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const [hovered, setHovered] = useState(false);\n const colors = resolveTheme(theme);\n\n // ── Collectors ─────────────────────────────────────────────────────────────\n // Start synchronously so window.fetch is patched before React effects run,\n // ensuring the admin's initial API requests are captured.\n const consoleCollector = useRef<ReturnType<typeof createConsoleCollector> | null>(null);\n const networkCollector = useRef<ReturnType<typeof createNetworkCollector> | null>(null);\n const replayEvents = useRef<eventWithTime[]>([]);\n const stopReplay = useRef<(() => void) | null>(null);\n\n if (!consoleCollector.current) {\n consoleCollector.current = createConsoleCollector();\n consoleCollector.current.start();\n }\n if (!networkCollector.current) {\n networkCollector.current = createNetworkCollector();\n networkCollector.current.start();\n }\n\n useEffect(() => {\n // Start rrweb recording with rolling buffer (must be in effect for DOM access)\n const stopFn = record({\n emit(event) {\n replayEvents.current.push(event);\n // Trim to rolling window\n const cutoff = Date.now() - REPLAY_WINDOW_MS;\n while (\n replayEvents.current.length > 0 &&\n replayEvents.current[0].timestamp < cutoff\n ) {\n replayEvents.current.shift();\n }\n },\n });\n stopReplay.current = stopFn ?? null;\n\n return () => {\n consoleCollector.current?.stop();\n networkCollector.current?.stop();\n stopReplay.current?.();\n };\n }, []);\n\n const label = buttonLabel ?? t(\"buttonLabel\");\n\n return (\n <>\n {/* Floating trigger button */}\n <button\n onClick={() => setOpen(true)}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n aria-label={label}\n style={{\n position: \"fixed\",\n bottom: \"40px\",\n right: \"20px\",\n zIndex: zIndex - 1,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n padding: \"10px 18px\",\n borderRadius: \"24px\",\n border: \"none\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n fontSize: \"13px\",\n fontWeight: 600,\n cursor: \"pointer\",\n boxShadow: hovered\n ? `0 0 28px ${colors.accent}55, 0 8px 24px rgba(0,0,0,0.3)`\n : `0 0 16px ${colors.accent}33, 0 4px 16px rgba(0,0,0,0.2)`,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n transform: hovered ? \"translateY(-2px)\" : \"translateY(0)\",\n transition: \"transform 0.15s ease, box-shadow 0.15s ease\",\n letterSpacing: \"0.01em\",\n }}\n >\n <SparkIcon />\n {label}\n </button>\n\n {/* Modal */}\n {open && (\n <FlintModal\n projectKey={projectKey}\n serverUrl={serverUrl}\n user={resolvedUser}\n meta={meta}\n theme={theme}\n zIndex={zIndex}\n onClose={() => setOpen(false)}\n getEnvironment={collectEnvironment}\n getConsoleLogs={() => consoleCollector.current?.getEntries() ?? []}\n getNetworkErrors={() => networkCollector.current?.getEntries() ?? []}\n getReplayEvents={() => [...replayEvents.current]}\n getExternalReplayUrl={getExternalReplayUrl}\n />\n )}\n </>\n );\n}\n\nfunction SparkIcon() {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n );\n}\n","import { useRef, useState, useEffect, useCallback } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport type {\n Severity,\n FlintUser,\n Theme,\n ReportResult,\n EnvironmentInfo,\n ConsoleEntry,\n NetworkEntry,\n} from \"@flint/types\";\nimport type { eventWithTime } from \"@rrweb/types\";\nimport { submitReport, submitReplay } from \"./api.js\";\nimport { resolveTheme } from \"./theme.js\";\n\ninterface Props {\n projectKey: string;\n serverUrl: string;\n user?: FlintUser;\n meta?: Record<string, unknown>;\n theme: Theme;\n zIndex: number;\n onClose: () => void;\n getEnvironment: () => EnvironmentInfo;\n getConsoleLogs: () => ConsoleEntry[];\n getNetworkErrors: () => NetworkEntry[];\n getReplayEvents: () => eventWithTime[];\n getExternalReplayUrl: () => string | undefined;\n}\n\nconst SEVERITIES: Severity[] = [\"P1\", \"P2\", \"P3\", \"P4\"];\nconst SEV_COLOR: Record<Severity, string> = {\n P1: \"#ef4444\",\n P2: \"#f97316\",\n P3: \"#eab308\",\n P4: \"#22c55e\",\n};\n\ntype Status = \"idle\" | \"submitting\" | \"success\" | \"error\";\n\n// Inject CSS keyframes once — animations can't be done with inline styles alone\nfunction injectKeyframes() {\n if (typeof document === \"undefined\") return;\n if (document.getElementById(\"_flint_kf\")) return;\n const s = document.createElement(\"style\");\n s.id = \"_flint_kf\";\n s.textContent = `\n @keyframes _flint_in {\n from { opacity: 0; transform: scale(0.93) translateY(10px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n }\n @keyframes _flint_overlay_in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n @keyframes _flint_spin {\n to { transform: rotate(360deg); }\n }\n @keyframes _flint_pulse {\n 0%, 100% { opacity: 0.5; transform: scale(0.88); }\n 50% { opacity: 1; transform: scale(1.08); }\n }\n @keyframes _flint_ripple {\n 0% { opacity: 0.5; transform: scale(0.75); }\n 100% { opacity: 0; transform: scale(1.55); }\n }\n @keyframes _flint_sending_dot {\n 0%, 80%, 100% { opacity: 0.2; transform: scale(0.8); }\n 40% { opacity: 1; transform: scale(1); }\n }\n @keyframes _flint_success_up {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `;\n document.head.appendChild(s);\n}\n\nexport function FlintModal({\n projectKey,\n serverUrl,\n user,\n meta,\n theme,\n zIndex,\n onClose,\n getEnvironment,\n getConsoleLogs,\n getNetworkErrors,\n getReplayEvents,\n getExternalReplayUrl,\n}: Props) {\n const { t } = useTranslation();\n const colors = resolveTheme(theme);\n const isDark = theme === \"dark\";\n\n const [severity, setSeverity] = useState<Severity>(\"P2\");\n const [description, setDescription] = useState(\"\");\n const [expectedBehavior, setExpectedBehavior] = useState(\"\");\n const [screenshot, setScreenshot] = useState<File | null>(null);\n const [status, setStatus] = useState<Status>(\"idle\");\n const [result, setResult] = useState<ReportResult | null>(null);\n const [errorMsg, setErrorMsg] = useState(\"\");\n\n const fileRef = useRef<HTMLInputElement>(null);\n const overlayRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => { injectKeyframes(); }, []);\n\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && status !== \"submitting\") onClose();\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [onClose, status]);\n\n const handleOverlayClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === overlayRef.current && status !== \"submitting\") onClose();\n },\n [onClose, status],\n );\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!description.trim()) return;\n\n setStatus(\"submitting\");\n setErrorMsg(\"\");\n\n const collectedMeta: Record<string, unknown> = {\n ...meta,\n environment: getEnvironment(),\n consoleLogs: getConsoleLogs(),\n networkErrors: getNetworkErrors(),\n };\n\n try {\n const res = await submitReport(\n serverUrl,\n projectKey,\n {\n reporterId: user?.id ?? \"anonymous\",\n reporterName: user?.name ?? \"Anonymous\",\n description: description.trim(),\n expectedBehavior: expectedBehavior.trim() || undefined,\n externalReplayUrl: getExternalReplayUrl() || undefined,\n severity,\n url: window.location.href,\n meta: collectedMeta,\n },\n screenshot ?? undefined,\n );\n setResult(res);\n setStatus(\"success\");\n\n const events = getReplayEvents();\n if (events.length > 0) {\n submitReplay(serverUrl, projectKey, res.id, events).catch(() => {});\n }\n } catch (err) {\n setErrorMsg(err instanceof Error ? err.message : t(\"errorLabel\"));\n setStatus(\"error\");\n }\n };\n\n // ── Shared style tokens ────────────────────────────────────────────────────\n const inputBorder = isDark ? \"rgba(255,255,255,0.1)\" : \"rgba(0,0,0,0.1)\";\n const accentGlow = `0 0 20px ${colors.accent}40, 0 4px 16px rgba(0,0,0,0.2)`;\n\n const overlayStyle: React.CSSProperties = {\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.5)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex,\n padding: \"16px\",\n backdropFilter: \"blur(10px)\",\n WebkitBackdropFilter: \"blur(10px)\",\n animation: \"_flint_overlay_in 0.2s ease\",\n };\n\n const modalStyle: React.CSSProperties = {\n background: colors.background,\n backdropFilter: colors.backdropFilter,\n WebkitBackdropFilter: colors.backdropFilter,\n borderRadius: \"20px\",\n boxShadow: colors.shadow,\n border: `1px solid ${colors.border}`,\n width: \"100%\",\n maxWidth: \"480px\",\n maxHeight: \"92vh\",\n overflowY: \"auto\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n color: colors.text,\n animation: \"_flint_in 0.28s cubic-bezier(0.16, 1, 0.3, 1)\",\n };\n\n const inputStyle: React.CSSProperties = {\n width: \"100%\",\n padding: \"11px 13px\",\n borderRadius: \"10px\",\n border: `1px solid ${inputBorder}`,\n background: colors.backgroundSecondary,\n color: colors.text,\n fontSize: \"14px\",\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"inherit\",\n transition: \"border-color 0.15s\",\n };\n\n // ── Loading + Success (unified animated state) ────────────────────────────\n if (status === \"submitting\" || status === \"success\") {\n const isSuccess = status === \"success\";\n const ringBorder = isSuccess\n ? \"3px solid #22c55e\"\n : `3px solid ${isDark ? \"rgba(255,255,255,0.08)\" : \"rgba(0,0,0,0.08)\"}`;\n const ringTopColor = isSuccess ? \"#22c55e\" : colors.accent;\n\n return (\n <div style={overlayStyle}>\n <div style={modalStyle} role=\"dialog\" aria-modal=\"true\" aria-label={isSuccess ? t(\"successTitle\") : t(\"sending\")}>\n <ModalHeader colors={colors} inputBorder={inputBorder} showClose={false} onClose={onClose} />\n\n <div style={{ padding: \"40px 32px 48px\", textAlign: \"center\", display: \"flex\", flexDirection: \"column\", alignItems: \"center\" }}>\n {/* Animated rings */}\n <div style={{ position: \"relative\", width: 80, height: 80, marginBottom: 28 }}>\n {/* Ripple 1 — fade out on success */}\n <div style={{\n position: \"absolute\", inset: -10,\n borderRadius: \"50%\",\n border: `1.5px solid ${colors.accent}`,\n animation: \"_flint_ripple 1.8s ease-out infinite\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }} />\n {/* Ripple 2 (delayed) */}\n <div style={{\n position: \"absolute\", inset: -10,\n borderRadius: \"50%\",\n border: `1.5px solid ${colors.accent}`,\n animation: \"_flint_ripple 1.8s ease-out infinite 0.6s\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }} />\n {/* Spinning ring — transitions to solid green on success */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n border: ringBorder,\n borderTopColor: ringTopColor,\n animation: isSuccess ? \"none\" : \"_flint_spin 0.85s linear infinite\",\n transition: \"border-color 0.45s ease, border-top-color 0.45s ease\",\n }} />\n {/* Center: spark fades out, check fades in */}\n <div style={{ position: \"absolute\", inset: 14, borderRadius: \"50%\" }}>\n {/* Spark */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n background: `linear-gradient(135deg, ${colors.accent}30, ${colors.accentHover}50)`,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n animation: isSuccess ? \"none\" : \"_flint_pulse 2s ease-in-out infinite\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }}>\n <SparkIcon color={colors.accent} size={20} />\n </div>\n {/* Checkmark */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n background: \"rgba(34,197,94,0.15)\",\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"scale(1)\" : \"scale(0.65)\",\n transition: \"opacity 0.35s ease 0.2s, transform 0.4s cubic-bezier(0.16,1,0.3,1) 0.2s\",\n }}>\n <CheckIcon size={20} />\n </div>\n </div>\n </div>\n\n {/* Title crossfade */}\n <div style={{ position: \"relative\", height: 26, width: \"100%\", marginBottom: 10 }}>\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n fontSize: 17, fontWeight: 700, color: colors.text, letterSpacing: \"-0.02em\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.25s ease\",\n pointerEvents: \"none\",\n }}>\n {t(\"sending\")}\n </div>\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n fontSize: 17, fontWeight: 700, color: colors.text, letterSpacing: \"-0.02em\",\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"translateY(0)\" : \"translateY(6px)\",\n transition: \"opacity 0.35s ease 0.25s, transform 0.35s ease 0.25s\",\n pointerEvents: isSuccess ? \"auto\" : \"none\",\n }}>\n {t(\"successTitle\")}\n </div>\n </div>\n\n {/* Subtitle crossfade */}\n <div style={{ position: \"relative\", minHeight: 76, width: \"100%\" }}>\n {/* Loading subtitle */}\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n gap: 6, color: colors.textMuted, fontSize: 13,\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.2s ease\",\n pointerEvents: \"none\",\n }}>\n <span>{t(\"capturingContext\")}</span>\n <SendingDots color={colors.accent} />\n </div>\n {/* Success subtitle */}\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", flexDirection: \"column\", alignItems: \"center\", gap: 10,\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"translateY(0)\" : \"translateY(8px)\",\n transition: \"opacity 0.35s ease 0.35s, transform 0.35s ease 0.35s\",\n pointerEvents: isSuccess ? \"auto\" : \"none\",\n }}>\n <p style={{ fontSize: 13, color: colors.textMuted, margin: 0 }}>\n {result?.isDuplicate ? t(\"successDuplicate\") : result ? `ID: ${result.id}` : \"\"}\n </p>\n {result?.slackMessageUrl && (\n <a\n href={result.slackMessageUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 6,\n padding: \"9px 18px\",\n borderRadius: \"10px\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n textDecoration: \"none\",\n fontSize: \"13px\",\n fontWeight: 600,\n boxShadow: accentGlow,\n }}\n >\n {t(\"successSlack\")} ↗\n </a>\n )}\n <button\n onClick={onClose}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n padding: \"4px 8px\",\n fontFamily: \"inherit\",\n }}\n >\n {t(\"cancel\")}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n // ── Form ──────────────────────────────────────────────────────────────────\n return (\n <div ref={overlayRef} style={overlayStyle} onClick={handleOverlayClick}>\n <div style={modalStyle} role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"flint-modal-title\">\n <ModalHeader\n colors={colors}\n inputBorder={inputBorder}\n showClose\n onClose={onClose}\n titleId=\"flint-modal-title\"\n title={t(\"modalTitle\")}\n />\n\n <form onSubmit={handleSubmit} style={{ padding: \"20px 24px 24px\" }}>\n {/* Severity */}\n <div style={{ marginBottom: 18 }}>\n <FieldLabel colors={colors}>{t(\"severityLabel\")}</FieldLabel>\n <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(4,1fr)\", gap: 8 }}>\n {SEVERITIES.map((sev) => (\n <SeverityButton\n key={sev}\n sev={sev}\n label={t(`severity_${sev}_label`)}\n selected={severity === sev}\n hint={t(`severity_${sev}_hint`)}\n color={SEV_COLOR[sev]}\n accent={colors.accent}\n border={inputBorder}\n bg={colors.backgroundSecondary}\n text={colors.text}\n onClick={() => setSeverity(sev)}\n />\n ))}\n </div>\n </div>\n\n {/* What Is Broken */}\n <div style={{ marginBottom: 14 }}>\n <FieldLabel colors={colors} htmlFor=\"flint-description\">{t(\"whatIsBrokenLabel\")}</FieldLabel>\n <textarea\n id=\"flint-description\"\n style={{ ...inputStyle, resize: \"vertical\", minHeight: 80 }}\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder={t(\"whatIsBrokenPlaceholder\")}\n required\n />\n </div>\n\n {/* Expected Behavior (optional) */}\n <div style={{ marginBottom: 14 }}>\n <FieldLabel colors={colors} htmlFor=\"flint-expected\">{t(\"expectedBehaviorLabel\")}</FieldLabel>\n <textarea\n id=\"flint-expected\"\n style={{ ...inputStyle, resize: \"vertical\", minHeight: 72 }}\n value={expectedBehavior}\n onChange={(e) => setExpectedBehavior(e.target.value)}\n placeholder={t(\"expectedBehaviorPlaceholder\")}\n />\n </div>\n\n {/* Screenshot */}\n <div style={{ marginBottom: 20 }}>\n <FieldLabel colors={colors}>{t(\"screenshotLabel\")}</FieldLabel>\n <label\n htmlFor=\"flint-screenshot\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"10px 13px\",\n borderRadius: 10,\n border: `1px dashed ${inputBorder}`,\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n background: colors.backgroundSecondary,\n }}\n >\n 📎 {screenshot ? screenshot.name : t(\"screenshotPlaceholder\")}\n </label>\n <input\n id=\"flint-screenshot\"\n ref={fileRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={(e) => setScreenshot(e.target.files?.[0] ?? null)}\n />\n </div>\n\n {/* Session replay info */}\n <div style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"9px 12px\",\n borderRadius: 10,\n background: isDark ? \"rgba(255,255,255,0.04)\" : \"rgba(0,77,240,0.04)\",\n border: `1px solid ${isDark ? \"rgba(255,255,255,0.08)\" : \"rgba(0,77,240,0.1)\"}`,\n marginBottom: 16,\n }}>\n <span style={{ fontSize: 14 }}>🎥</span>\n <span style={{ fontSize: 12, color: colors.textMuted, lineHeight: 1.4 }}>\n {t(\"replayInfo\")}\n </span>\n </div>\n\n {/* Error */}\n {status === \"error\" && (\n <div style={{\n padding: \"10px 13px\",\n borderRadius: 10,\n background: \"rgba(239,68,68,0.08)\",\n border: \"1px solid rgba(239,68,68,0.2)\",\n color: \"#f87171\",\n fontSize: 12,\n marginBottom: 16,\n }}>\n ⚠️ {errorMsg || t(\"errorLabel\")}\n </div>\n )}\n\n {/* Submit */}\n <button\n type=\"submit\"\n style={{\n width: \"100%\",\n padding: \"13px 20px\",\n borderRadius: 12,\n border: \"none\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n fontSize: 15,\n fontWeight: 700,\n cursor: \"pointer\",\n letterSpacing: \"-0.01em\",\n boxShadow: accentGlow,\n fontFamily: \"inherit\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 8,\n }}\n >\n <SparkIcon color={colors.buttonText} size={15} />\n {t(\"submitLabel\")}\n </button>\n\n {/* Cancel */}\n <button\n type=\"button\"\n onClick={onClose}\n style={{\n width: \"100%\",\n padding: \"10px\",\n marginTop: 8,\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n fontFamily: \"inherit\",\n borderRadius: 8,\n }}\n >\n {t(\"cancel\")}\n </button>\n </form>\n </div>\n </div>\n );\n}\n\n// ─── Sub-components ──────────────────────────────────────────────────────────\n\nfunction ModalHeader({\n colors,\n inputBorder,\n showClose,\n onClose,\n titleId,\n title,\n}: {\n colors: ReturnType<typeof resolveTheme>;\n inputBorder: string;\n showClose: boolean;\n onClose: () => void;\n titleId?: string;\n title?: string;\n}) {\n return (\n <div style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n padding: \"16px 20px 14px\",\n borderBottom: `1px solid ${inputBorder}`,\n }}>\n {/* Brand chip */}\n <div style={{\n width: 28, height: 28,\n borderRadius: 8,\n background: `linear-gradient(135deg, ${colors.accent}20, ${colors.accentHover}35)`,\n border: `1px solid ${colors.accent}30`,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n flexShrink: 0,\n }}>\n <SparkIcon color={colors.accent} size={13} />\n </div>\n\n {titleId && title ? (\n <h2 id={titleId} style={{ margin: 0, fontSize: 14, fontWeight: 600, color: colors.text, letterSpacing: \"-0.01em\", flex: 1 }}>\n {title}\n </h2>\n ) : (\n <span style={{ flex: 1, fontSize: 13, fontWeight: 600, color: colors.textMuted }}>Flint</span>\n )}\n\n {showClose && (\n <button\n onClick={onClose}\n aria-label=\"Close\"\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: 4,\n color: colors.textMuted,\n fontSize: 20,\n lineHeight: 1,\n borderRadius: 6,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n opacity: 0.6,\n fontFamily: \"inherit\",\n }}\n >\n ×\n </button>\n )}\n </div>\n );\n}\n\nfunction FieldLabel({\n children,\n colors,\n htmlFor,\n}: {\n children: React.ReactNode;\n colors: ReturnType<typeof resolveTheme>;\n htmlFor?: string;\n}) {\n return (\n <label\n htmlFor={htmlFor}\n style={{\n display: \"block\",\n fontSize: \"10px\",\n fontWeight: 700,\n color: colors.textMuted,\n marginBottom: 6,\n textTransform: \"uppercase\" as const,\n letterSpacing: \"0.07em\",\n }}\n >\n {children}\n </label>\n );\n}\n\nfunction SendingDots({ color }: { color: string }) {\n return (\n <span style={{ display: \"inline-flex\", gap: 3, alignItems: \"center\" }}>\n {[0, 1, 2].map((i) => (\n <span\n key={i}\n style={{\n width: 4, height: 4,\n borderRadius: \"50%\",\n background: color,\n display: \"inline-block\",\n animation: `_flint_sending_dot 1.4s ease-in-out infinite ${i * 0.2}s`,\n }}\n />\n ))}\n </span>\n );\n}\n\ninterface SevBtnProps {\n sev: Severity;\n label: string;\n selected: boolean;\n hint: string;\n color: string;\n accent: string;\n border: string;\n bg: string;\n text: string;\n onClick: () => void;\n}\n\nfunction SeverityButton({ sev, label, selected, hint, color, accent, border, bg, text, onClick }: SevBtnProps) {\n return (\n <button\n type=\"button\"\n title={hint}\n onClick={onClick}\n style={{\n padding: \"9px 6px 8px\",\n borderRadius: 10,\n border: selected ? `2px solid ${accent}` : `1.5px solid ${border}`,\n background: selected ? `${accent}15` : bg,\n cursor: \"pointer\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: 5,\n transition: \"border-color 0.12s, background 0.12s\",\n fontFamily: \"inherit\",\n }}\n >\n <span style={{ width: 8, height: 8, borderRadius: \"50%\", background: color, display: \"block\" }} />\n <span style={{ fontSize: 11, fontWeight: selected ? 700 : 500, color: selected ? accent : text, letterSpacing: \"0.02em\" }}>\n {sev}\n </span>\n <span style={{ fontSize: 9, color: selected ? accent : text, opacity: 0.6, letterSpacing: \"0.02em\" }}>\n {label}\n </span>\n </button>\n );\n}\n\nfunction SparkIcon({ color = \"currentColor\", size = 14 }: { color?: string; size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n );\n}\n\nfunction CheckIcon({ size = 20 }: { size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#22c55e\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n","import type { ReportPayload, ReportResult } from \"@flint/types\";\nimport { gzipSync } from \"fflate\";\nimport type { eventWithTime } from \"@rrweb/types\";\n\nexport async function submitReport(\n serverUrl: string,\n projectKey: string,\n payload: ReportPayload,\n screenshot?: File,\n): Promise<ReportResult> {\n const url = `${serverUrl.replace(/\\/$/, \"\")}/api/v1/bug-reports`;\n\n let body: BodyInit;\n let headers: Record<string, string> = {\n \"x-project-key\": projectKey,\n };\n\n if (screenshot) {\n const form = new FormData();\n form.append(\"reporterId\", payload.reporterId);\n form.append(\"reporterName\", payload.reporterName);\n form.append(\"description\", payload.description);\n if (payload.expectedBehavior) form.append(\"expectedBehavior\", payload.expectedBehavior);\n if (payload.stepsToReproduce) form.append(\"stepsToReproduce\", JSON.stringify(payload.stepsToReproduce));\n if (payload.externalReplayUrl) form.append(\"externalReplayUrl\", payload.externalReplayUrl);\n if (payload.additionalContext) form.append(\"additionalContext\", payload.additionalContext);\n form.append(\"severity\", payload.severity);\n if (payload.url) form.append(\"url\", payload.url);\n if (payload.meta) form.append(\"meta\", JSON.stringify(payload.meta));\n form.append(\"screenshot\", screenshot);\n body = form;\n } else {\n body = JSON.stringify(payload);\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const res = await fetch(url, { method: \"POST\", headers, body });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: \"Unknown error\" }));\n throw new Error((err as { error?: string }).error ?? `HTTP ${res.status}`);\n }\n\n return res.json() as Promise<ReportResult>;\n}\n\nexport async function submitReplay(\n serverUrl: string,\n projectKey: string,\n reportId: string,\n events: eventWithTime[],\n): Promise<void> {\n const json = JSON.stringify(events);\n const encoded = new TextEncoder().encode(json);\n const compressed = gzipSync(encoded);\n\n const url = `${serverUrl.replace(/\\/$/, \"\")}/api/v1/bug-reports/${reportId}/replay`;\n await fetch(url, {\n method: \"POST\",\n headers: {\n \"x-project-key\": projectKey,\n \"Content-Type\": \"application/octet-stream\",\n },\n body: compressed.buffer as ArrayBuffer,\n });\n}\n","import type { Theme, ThemeOverride } from \"@flint/types\";\n\nexport interface ResolvedTheme {\n background: string;\n backgroundSecondary: string;\n accent: string;\n accentHover: string;\n text: string;\n textMuted: string;\n border: string;\n shadow: string;\n buttonText: string;\n backdropFilter: string;\n}\n\nconst light: ResolvedTheme = {\n background: \"rgba(255,255,255,0.90)\",\n backgroundSecondary: \"rgba(249,250,251,0.75)\",\n accent: \"#2563eb\",\n accentHover: \"#1d4ed8\",\n text: \"#111827\",\n textMuted: \"#6b7280\",\n border: \"rgba(255,255,255,0.9)\",\n shadow:\n \"0 32px 80px rgba(0,0,0,0.18), 0 8px 32px rgba(0,0,0,0.1), 0 0 0 1px rgba(0,0,0,0.04)\",\n buttonText: \"#ffffff\",\n backdropFilter: \"blur(32px) saturate(1.8)\",\n};\n\nconst dark: ResolvedTheme = {\n background: \"rgba(15,20,35,0.88)\",\n backgroundSecondary: \"rgba(5,8,18,0.65)\",\n accent: \"#f97316\",\n accentHover: \"#ea6c0a\",\n text: \"#dde3ef\",\n textMuted: \"#6b7a93\",\n border: \"rgba(255,255,255,0.08)\",\n shadow:\n \"0 24px 60px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04)\",\n buttonText: \"#ffffff\",\n backdropFilter: \"blur(32px) saturate(1.6)\",\n};\n\nexport function resolveTheme(theme: Theme): ResolvedTheme {\n if (theme === \"dark\") return dark;\n if (theme === \"light\") return light;\n // ThemeOverride — merge over light base\n const override = theme as ThemeOverride;\n return {\n ...light,\n background: override.background ?? light.background,\n accent: override.accent ?? light.accent,\n accentHover: override.accent ?? light.accentHover,\n text: override.text ?? light.text,\n border: override.border ?? light.border,\n };\n}\n","import i18next, { createInstance } from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\nimport en from \"./locales/en.json\";\n\nexport const widgetI18n: ReturnType<typeof createInstance> = createInstance();\n\nwidgetI18n.use(initReactI18next).init({\n lng: \"en-US\",\n fallbackLng: \"en-US\",\n resources: { \"en-US\": { translation: en } },\n interpolation: { escapeValue: false },\n initImmediate: false,\n});\n\nexport default widgetI18n;\n","{\n \"buttonLabel\": \"Report bug\",\n \"modalTitle\": \"Report an issue\",\n \"severityLabel\": \"Severity\",\n \"severity_P1_hint\": \"Critical — system down\",\n \"severity_P2_hint\": \"High — core feature broken\",\n \"severity_P3_hint\": \"Medium — noticeable but workable\",\n \"severity_P4_hint\": \"Low — cosmetic or improvement\",\n \"severity_P1_label\": \"Critical\",\n \"severity_P2_label\": \"High\",\n \"severity_P3_label\": \"Medium\",\n \"severity_P4_label\": \"Low\",\n \"whatIsBrokenLabel\": \"What Is Broken\",\n \"whatIsBrokenPlaceholder\": \"1–2 sentences: what is currently happening that should NOT happen.\",\n \"expectedBehaviorLabel\": \"Expected Behavior (optional)\",\n \"expectedBehaviorPlaceholder\": \"Describe exactly what the user should see or receive after the fix.\",\n \"screenshotLabel\": \"Screenshot (optional)\",\n \"screenshotPlaceholder\": \"Click to attach...\",\n \"submitLabel\": \"Submit\",\n \"successTitle\": \"Bug reported!\",\n \"successDuplicate\": \"Looks like a duplicate of an existing bug.\",\n \"successGitHub\": \"View GitHub issue\",\n \"successSlack\": \"View Slack message\",\n \"replayInfo\": \"No need to record your screen — we automatically capture a session replay when you submit.\",\n \"errorLabel\": \"Failed to submit. Please try again.\",\n \"cancel\": \"Cancel\",\n \"sending\": \"Sending report\",\n \"capturingContext\": \"Capturing context\"\n}\n","import type { EnvironmentInfo } from \"@flint/types\";\n\nexport function collectEnvironment(): EnvironmentInfo {\n const ua = navigator.userAgent;\n\n // ── Browser ──────────────────────────────────────────────────────────────\n let browser = \"Unknown\";\n const chromeM = ua.match(/Chrome\\/(\\d+)/);\n const firefoxM = ua.match(/Firefox\\/(\\d+)/);\n const edgeM = ua.match(/Edg\\/(\\d+)/);\n const safariM = ua.match(/Version\\/(\\d+)/);\n const operaM = ua.match(/OPR\\/(\\d+)/);\n\n if (operaM) {\n browser = `Opera ${operaM[1]}`;\n } else if (edgeM) {\n browser = `Edge ${edgeM[1]}`;\n } else if (chromeM && !/Edg|OPR/.test(ua)) {\n browser = `Chrome ${chromeM[1]}`;\n } else if (firefoxM) {\n browser = `Firefox ${firefoxM[1]}`;\n } else if (safariM && /Safari\\//.test(ua)) {\n browser = `Safari ${safariM[1]}`;\n }\n\n // ── OS ────────────────────────────────────────────────────────────────────\n let os = \"Unknown\";\n const macM = ua.match(/Mac OS X (\\d+[._]\\d+)/);\n const winM = ua.match(/Windows NT (\\d+\\.\\d+)/);\n const androidM = ua.match(/Android (\\d+)/);\n const iosM = ua.match(/iPhone OS (\\d+[._]\\d+)/);\n\n if (macM) {\n os = `macOS ${macM[1].replace(\"_\", \".\")}`;\n } else if (winM) {\n const winMap: Record<string, string> = {\n \"10.0\": \"10/11\",\n \"6.3\": \"8.1\",\n \"6.2\": \"8\",\n \"6.1\": \"7\",\n };\n os = `Windows ${winMap[winM[1]] ?? winM[1]}`;\n } else if (androidM) {\n os = `Android ${androidM[1]}`;\n } else if (iosM) {\n os = `iOS ${iosM[1].replace(/_/g, \".\")}`;\n } else if (/Linux/.test(ua)) {\n os = \"Linux\";\n }\n\n return {\n browser,\n os,\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n screen: `${screen.width}x${screen.height}`,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n online: navigator.onLine,\n };\n}\n","import type { ConsoleEntry } from \"@flint/types\";\n\nconst MAX_ENTRIES = 50;\n\nexport interface ConsoleCollector {\n start(): void;\n stop(): void;\n getEntries(): ConsoleEntry[];\n}\n\nexport function createConsoleCollector(): ConsoleCollector {\n const entries: ConsoleEntry[] = [];\n let active = false;\n\n const originals = {\n log: console.log.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n };\n\n let origOnerror: typeof window.onerror = null;\n let origUnhandled: typeof window.onunhandledrejection = null;\n\n function push(level: ConsoleEntry[\"level\"], args: unknown[]) {\n let str: string;\n try {\n str = args\n .map((a) => (typeof a === \"string\" ? a : JSON.stringify(a)))\n .join(\" \");\n } catch {\n str = String(args[0]);\n }\n if (str.length > 500) str = str.slice(0, 500) + \"…\";\n entries.push({ level, args: str, timestamp: Date.now() });\n if (entries.length > MAX_ENTRIES) entries.shift();\n }\n\n return {\n start() {\n if (active) return;\n active = true;\n\n console.log = (...args: unknown[]) => {\n push(\"log\", args);\n originals.log(...args);\n };\n console.warn = (...args: unknown[]) => {\n push(\"warn\", args);\n originals.warn(...args);\n };\n console.error = (...args: unknown[]) => {\n push(\"error\", args);\n originals.error(...args);\n };\n\n origOnerror = window.onerror;\n window.onerror = (msg, src, line, col, err) => {\n push(\"error\", [err?.message ?? String(msg), `${src}:${line}:${col}`]);\n if (typeof origOnerror === \"function\")\n return origOnerror(msg, src, line, col, err);\n return false;\n };\n\n origUnhandled = window.onunhandledrejection;\n window.onunhandledrejection = (event) => {\n const reason =\n event.reason instanceof Error\n ? event.reason.message\n : JSON.stringify(event.reason);\n push(\"error\", [\"UnhandledRejection:\", reason]);\n if (typeof origUnhandled === \"function\")\n origUnhandled.call(window, event);\n };\n },\n\n stop() {\n if (!active) return;\n active = false;\n console.log = originals.log;\n console.warn = originals.warn;\n console.error = originals.error;\n window.onerror = origOnerror;\n window.onunhandledrejection = origUnhandled;\n },\n\n getEntries() {\n return [...entries];\n },\n };\n}\n","import type { NetworkEntry } from \"@flint/types\";\n\nconst MAX_ENTRIES = 20;\n\nexport interface NetworkCollector {\n start(): void;\n stop(): void;\n getEntries(): NetworkEntry[];\n}\n\nfunction truncateUrl(url: string): string {\n try {\n const u = new URL(url, location.href);\n const base = `${u.origin}${u.pathname}`;\n return base.length > 200 ? base.slice(0, 200) + \"…\" : base;\n } catch {\n return url.length > 200 ? url.slice(0, 200) + \"…\" : url;\n }\n}\n\nexport function createNetworkCollector(): NetworkCollector {\n const entries: NetworkEntry[] = [];\n let origFetch: typeof window.fetch | null = null;\n let origXHROpen: typeof XMLHttpRequest.prototype.open | null = null;\n let active = false;\n\n function push(entry: NetworkEntry) {\n entries.push(entry);\n if (entries.length > MAX_ENTRIES) entries.shift();\n }\n\n return {\n start() {\n if (active) return;\n active = true;\n\n // ── Patch fetch ────────────────────────────────────────────────────────\n origFetch = window.fetch;\n window.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const method = ((init?.method ?? \"GET\") as string).toUpperCase();\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : (input as Request).url;\n const startTime = Date.now();\n const res = await origFetch!.call(window, input, init);\n push({\n method,\n url: truncateUrl(url),\n status: res.status,\n duration: Date.now() - startTime,\n timestamp: startTime,\n });\n return res;\n };\n\n // ── Patch XHR ─────────────────────────────────────────────────────────\n origXHROpen = XMLHttpRequest.prototype.open;\n XMLHttpRequest.prototype.open = function (\n method: string,\n url: string | URL,\n async?: boolean,\n username?: string | null,\n password?: string | null,\n ) {\n const startTime = Date.now();\n const urlStr =\n typeof url === \"string\" ? url : (url as URL).href;\n\n this.addEventListener(\"load\", () => {\n push({\n method: method.toUpperCase(),\n url: truncateUrl(urlStr),\n status: this.status,\n duration: Date.now() - startTime,\n timestamp: startTime,\n });\n });\n\n return origXHROpen!.apply(this, [\n method,\n url,\n async ?? true,\n username,\n password,\n ] as Parameters<typeof XMLHttpRequest.prototype.open>);\n };\n },\n\n stop() {\n if (!active) return;\n active = false;\n if (origFetch) window.fetch = origFetch;\n if (origXHROpen) XMLHttpRequest.prototype.open = origXHROpen;\n },\n\n getEntries() {\n return [...entries];\n },\n };\n}\n","import { useSyncExternalStore } from \"react\";\nimport type { FlintUser } from \"@flint/types\";\n\nexport interface FlintState {\n user: FlintUser | undefined;\n sessionReplay: string | (() => string) | undefined;\n}\n\nlet state: FlintState = { user: undefined, sessionReplay: undefined };\nconst listeners = new Set<() => void>();\n\nfunction emit() {\n listeners.forEach((fn) => fn());\n}\n\nfunction subscribeStore(fn: () => void) {\n listeners.add(fn);\n return () => listeners.delete(fn);\n}\n\nfunction getSnapshot(): FlintState {\n return state;\n}\n\nexport function useFlintStore() {\n return useSyncExternalStore(subscribeStore, getSnapshot);\n}\n\nexport const flint = {\n setUser(user: FlintUser | null) {\n state = { ...state, user: user ?? undefined };\n emit();\n },\n setSessionReplay(url: string | (() => string)) {\n state = { ...state, sessionReplay: url };\n emit();\n },\n};\n"],"mappings":"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","names":["import_react","import_react_i18next","import_react_i18next","MAX_ENTRIES","import_react","import_jsx_runtime","SparkIcon"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -35,8 +35,8 @@ interface FlintUser {
|
|
|
35
35
|
name: string;
|
|
36
36
|
}
|
|
37
37
|
interface FlintExtraFields {
|
|
38
|
-
/** Session replay URL from Datadog RUM, FullStory, LogRocket, etc. */
|
|
39
|
-
sessionReplay?: string;
|
|
38
|
+
/** Session replay URL from Datadog RUM, FullStory, LogRocket, etc. Pass a function for lazy evaluation. */
|
|
39
|
+
sessionReplay?: string | (() => string);
|
|
40
40
|
[key: string]: unknown;
|
|
41
41
|
}
|
|
42
42
|
interface FlintWidgetProps {
|
|
@@ -78,6 +78,7 @@ interface ReportResult {
|
|
|
78
78
|
id: string;
|
|
79
79
|
status: string;
|
|
80
80
|
githubIssueUrl?: string | null;
|
|
81
|
+
slackMessageUrl?: string | null;
|
|
81
82
|
isDuplicate: boolean;
|
|
82
83
|
duplicateOfId?: string | null;
|
|
83
84
|
}
|
|
@@ -513,8 +514,13 @@ interface Props {
|
|
|
513
514
|
getConsoleLogs: () => ConsoleEntry[];
|
|
514
515
|
getNetworkErrors: () => NetworkEntry[];
|
|
515
516
|
getReplayEvents: () => eventWithTime[];
|
|
516
|
-
|
|
517
|
+
getExternalReplayUrl: () => string | undefined;
|
|
517
518
|
}
|
|
518
|
-
declare function FlintModal({ projectKey, serverUrl, user, meta, theme, zIndex, onClose, getEnvironment, getConsoleLogs, getNetworkErrors, getReplayEvents,
|
|
519
|
+
declare function FlintModal({ projectKey, serverUrl, user, meta, theme, zIndex, onClose, getEnvironment, getConsoleLogs, getNetworkErrors, getReplayEvents, getExternalReplayUrl, }: Props): react_jsx_runtime.JSX.Element;
|
|
520
|
+
|
|
521
|
+
declare const flint: {
|
|
522
|
+
setUser(user: FlintUser | null): void;
|
|
523
|
+
setSessionReplay(url: string | (() => string)): void;
|
|
524
|
+
};
|
|
519
525
|
|
|
520
|
-
export { FlintModal, type FlintUser, FlintWidget, type FlintWidgetProps, type Locale, type ReportPayload, type ReportResult, type Severity, type Theme, type ThemeOverride };
|
|
526
|
+
export { FlintModal, type FlintUser, FlintWidget, type FlintWidgetProps, type Locale, type ReportPayload, type ReportResult, type Severity, type Theme, type ThemeOverride, flint };
|
package/dist/index.d.ts
CHANGED
|
@@ -35,8 +35,8 @@ interface FlintUser {
|
|
|
35
35
|
name: string;
|
|
36
36
|
}
|
|
37
37
|
interface FlintExtraFields {
|
|
38
|
-
/** Session replay URL from Datadog RUM, FullStory, LogRocket, etc. */
|
|
39
|
-
sessionReplay?: string;
|
|
38
|
+
/** Session replay URL from Datadog RUM, FullStory, LogRocket, etc. Pass a function for lazy evaluation. */
|
|
39
|
+
sessionReplay?: string | (() => string);
|
|
40
40
|
[key: string]: unknown;
|
|
41
41
|
}
|
|
42
42
|
interface FlintWidgetProps {
|
|
@@ -78,6 +78,7 @@ interface ReportResult {
|
|
|
78
78
|
id: string;
|
|
79
79
|
status: string;
|
|
80
80
|
githubIssueUrl?: string | null;
|
|
81
|
+
slackMessageUrl?: string | null;
|
|
81
82
|
isDuplicate: boolean;
|
|
82
83
|
duplicateOfId?: string | null;
|
|
83
84
|
}
|
|
@@ -513,8 +514,13 @@ interface Props {
|
|
|
513
514
|
getConsoleLogs: () => ConsoleEntry[];
|
|
514
515
|
getNetworkErrors: () => NetworkEntry[];
|
|
515
516
|
getReplayEvents: () => eventWithTime[];
|
|
516
|
-
|
|
517
|
+
getExternalReplayUrl: () => string | undefined;
|
|
517
518
|
}
|
|
518
|
-
declare function FlintModal({ projectKey, serverUrl, user, meta, theme, zIndex, onClose, getEnvironment, getConsoleLogs, getNetworkErrors, getReplayEvents,
|
|
519
|
+
declare function FlintModal({ projectKey, serverUrl, user, meta, theme, zIndex, onClose, getEnvironment, getConsoleLogs, getNetworkErrors, getReplayEvents, getExternalReplayUrl, }: Props): react_jsx_runtime.JSX.Element;
|
|
520
|
+
|
|
521
|
+
declare const flint: {
|
|
522
|
+
setUser(user: FlintUser | null): void;
|
|
523
|
+
setSessionReplay(url: string | (() => string)): void;
|
|
524
|
+
};
|
|
519
525
|
|
|
520
|
-
export { FlintModal, type FlintUser, FlintWidget, type FlintWidgetProps, type Locale, type ReportPayload, type ReportResult, type Severity, type Theme, type ThemeOverride };
|
|
526
|
+
export { FlintModal, type FlintUser, FlintWidget, type FlintWidgetProps, type Locale, type ReportPayload, type ReportResult, type Severity, type Theme, type ThemeOverride, flint };
|
package/dist/index.js
CHANGED
|
@@ -150,7 +150,7 @@ function FlintModal({
|
|
|
150
150
|
getConsoleLogs,
|
|
151
151
|
getNetworkErrors,
|
|
152
152
|
getReplayEvents,
|
|
153
|
-
|
|
153
|
+
getExternalReplayUrl
|
|
154
154
|
}) {
|
|
155
155
|
const { t } = useTranslation();
|
|
156
156
|
const colors = resolveTheme(theme);
|
|
@@ -200,7 +200,7 @@ function FlintModal({
|
|
|
200
200
|
reporterName: user?.name ?? "Anonymous",
|
|
201
201
|
description: description.trim(),
|
|
202
202
|
expectedBehavior: expectedBehavior.trim() || void 0,
|
|
203
|
-
externalReplayUrl:
|
|
203
|
+
externalReplayUrl: getExternalReplayUrl() || void 0,
|
|
204
204
|
severity,
|
|
205
205
|
url: window.location.href,
|
|
206
206
|
meta: collectedMeta
|
|
@@ -385,10 +385,10 @@ function FlintModal({
|
|
|
385
385
|
pointerEvents: isSuccess ? "auto" : "none"
|
|
386
386
|
}, children: [
|
|
387
387
|
/* @__PURE__ */ jsx("p", { style: { fontSize: 13, color: colors.textMuted, margin: 0 }, children: result?.isDuplicate ? t("successDuplicate") : result ? `ID: ${result.id}` : "" }),
|
|
388
|
-
result?.
|
|
388
|
+
result?.slackMessageUrl && /* @__PURE__ */ jsxs(
|
|
389
389
|
"a",
|
|
390
390
|
{
|
|
391
|
-
href: result.
|
|
391
|
+
href: result.slackMessageUrl,
|
|
392
392
|
target: "_blank",
|
|
393
393
|
rel: "noreferrer",
|
|
394
394
|
style: {
|
|
@@ -405,7 +405,7 @@ function FlintModal({
|
|
|
405
405
|
boxShadow: accentGlow
|
|
406
406
|
},
|
|
407
407
|
children: [
|
|
408
|
-
t("
|
|
408
|
+
t("successSlack"),
|
|
409
409
|
" \u2197"
|
|
410
410
|
]
|
|
411
411
|
}
|
|
@@ -526,6 +526,19 @@ function FlintModal({
|
|
|
526
526
|
}
|
|
527
527
|
)
|
|
528
528
|
] }),
|
|
529
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
530
|
+
display: "flex",
|
|
531
|
+
alignItems: "center",
|
|
532
|
+
gap: 8,
|
|
533
|
+
padding: "9px 12px",
|
|
534
|
+
borderRadius: 10,
|
|
535
|
+
background: isDark ? "rgba(255,255,255,0.04)" : "rgba(0,77,240,0.04)",
|
|
536
|
+
border: `1px solid ${isDark ? "rgba(255,255,255,0.08)" : "rgba(0,77,240,0.1)"}`,
|
|
537
|
+
marginBottom: 16
|
|
538
|
+
}, children: [
|
|
539
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14 }, children: "\u{1F3A5}" }),
|
|
540
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 12, color: colors.textMuted, lineHeight: 1.4 }, children: t("replayInfo") })
|
|
541
|
+
] }),
|
|
529
542
|
status === "error" && /* @__PURE__ */ jsxs("div", { style: {
|
|
530
543
|
padding: "10px 13px",
|
|
531
544
|
borderRadius: 10,
|
|
@@ -741,6 +754,8 @@ var en_default = {
|
|
|
741
754
|
successTitle: "Bug reported!",
|
|
742
755
|
successDuplicate: "Looks like a duplicate of an existing bug.",
|
|
743
756
|
successGitHub: "View GitHub issue",
|
|
757
|
+
successSlack: "View Slack message",
|
|
758
|
+
replayInfo: "No need to record your screen \u2014 we automatically capture a session replay when you submit.",
|
|
744
759
|
errorLabel: "Failed to submit. Please try again.",
|
|
745
760
|
cancel: "Cancel",
|
|
746
761
|
sending: "Sending report",
|
|
@@ -953,6 +968,34 @@ function createNetworkCollector() {
|
|
|
953
968
|
};
|
|
954
969
|
}
|
|
955
970
|
|
|
971
|
+
// src/store.ts
|
|
972
|
+
import { useSyncExternalStore } from "react";
|
|
973
|
+
var state = { user: void 0, sessionReplay: void 0 };
|
|
974
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
975
|
+
function emit() {
|
|
976
|
+
listeners.forEach((fn) => fn());
|
|
977
|
+
}
|
|
978
|
+
function subscribeStore(fn) {
|
|
979
|
+
listeners.add(fn);
|
|
980
|
+
return () => listeners.delete(fn);
|
|
981
|
+
}
|
|
982
|
+
function getSnapshot() {
|
|
983
|
+
return state;
|
|
984
|
+
}
|
|
985
|
+
function useFlintStore() {
|
|
986
|
+
return useSyncExternalStore(subscribeStore, getSnapshot);
|
|
987
|
+
}
|
|
988
|
+
var flint = {
|
|
989
|
+
setUser(user) {
|
|
990
|
+
state = { ...state, user: user ?? void 0 };
|
|
991
|
+
emit();
|
|
992
|
+
},
|
|
993
|
+
setSessionReplay(url) {
|
|
994
|
+
state = { ...state, sessionReplay: url };
|
|
995
|
+
emit();
|
|
996
|
+
}
|
|
997
|
+
};
|
|
998
|
+
|
|
956
999
|
// src/FlintWidget.tsx
|
|
957
1000
|
import { record } from "rrweb";
|
|
958
1001
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -974,7 +1017,13 @@ function WidgetContent({
|
|
|
974
1017
|
theme = "dark",
|
|
975
1018
|
zIndex = 9999
|
|
976
1019
|
}) {
|
|
977
|
-
const
|
|
1020
|
+
const globalState = useFlintStore();
|
|
1021
|
+
const resolvedUser = user ?? globalState.user;
|
|
1022
|
+
const resolvedSessionReplay = extraFields?.sessionReplay ?? globalState.sessionReplay;
|
|
1023
|
+
const getExternalReplayUrl = () => {
|
|
1024
|
+
const src = resolvedSessionReplay;
|
|
1025
|
+
return typeof src === "function" ? src() : src;
|
|
1026
|
+
};
|
|
978
1027
|
const { t } = useTranslation2();
|
|
979
1028
|
const [open, setOpen] = useState2(false);
|
|
980
1029
|
const [hovered, setHovered] = useState2(false);
|
|
@@ -1019,7 +1068,7 @@ function WidgetContent({
|
|
|
1019
1068
|
"aria-label": label,
|
|
1020
1069
|
style: {
|
|
1021
1070
|
position: "fixed",
|
|
1022
|
-
bottom: "
|
|
1071
|
+
bottom: "40px",
|
|
1023
1072
|
right: "20px",
|
|
1024
1073
|
zIndex: zIndex - 1,
|
|
1025
1074
|
display: "flex",
|
|
@@ -1050,7 +1099,7 @@ function WidgetContent({
|
|
|
1050
1099
|
{
|
|
1051
1100
|
projectKey,
|
|
1052
1101
|
serverUrl,
|
|
1053
|
-
user,
|
|
1102
|
+
user: resolvedUser,
|
|
1054
1103
|
meta,
|
|
1055
1104
|
theme,
|
|
1056
1105
|
zIndex,
|
|
@@ -1059,7 +1108,7 @@ function WidgetContent({
|
|
|
1059
1108
|
getConsoleLogs: () => consoleCollector.current?.getEntries() ?? [],
|
|
1060
1109
|
getNetworkErrors: () => networkCollector.current?.getEntries() ?? [],
|
|
1061
1110
|
getReplayEvents: () => [...replayEvents.current],
|
|
1062
|
-
|
|
1111
|
+
getExternalReplayUrl
|
|
1063
1112
|
}
|
|
1064
1113
|
)
|
|
1065
1114
|
] });
|
|
@@ -1083,6 +1132,7 @@ function SparkIcon2() {
|
|
|
1083
1132
|
}
|
|
1084
1133
|
export {
|
|
1085
1134
|
FlintModal,
|
|
1086
|
-
FlintWidget
|
|
1135
|
+
FlintWidget,
|
|
1136
|
+
flint
|
|
1087
1137
|
};
|
|
1088
1138
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/FlintWidget.tsx","../src/FlintModal.tsx","../src/api.ts","../src/theme.ts","../src/i18n/index.ts","../src/i18n/locales/en.json","../src/collectors/environment.ts","../src/collectors/console.ts","../src/collectors/network.ts"],"sourcesContent":["import { useState, useEffect, useRef } from \"react\";\nimport { I18nextProvider, useTranslation } from \"react-i18next\";\nimport { FlintModal } from \"./FlintModal.js\";\nimport type { FlintWidgetProps } from \"@flint/types\";\nimport { resolveTheme } from \"./theme.js\";\nimport widgetI18n from \"./i18n/index.js\";\nimport { collectEnvironment } from \"./collectors/environment.js\";\nimport { createConsoleCollector } from \"./collectors/console.js\";\nimport { createNetworkCollector } from \"./collectors/network.js\";\nimport { record } from \"rrweb\";\nimport type { eventWithTime } from \"@rrweb/types\";\n\nconst REPLAY_WINDOW_MS = 60_000; // rolling 60-second buffer\n\nexport function FlintWidget(props: FlintWidgetProps) {\n const { locale = \"en-US\" } = props;\n\n useEffect(() => {\n widgetI18n.changeLanguage(locale);\n }, [locale]);\n\n return (\n <I18nextProvider i18n={widgetI18n}>\n <WidgetContent {...props} />\n </I18nextProvider>\n );\n}\n\nfunction WidgetContent({\n projectKey,\n serverUrl,\n user,\n meta,\n extraFields,\n buttonLabel,\n theme = \"dark\",\n zIndex = 9999,\n}: FlintWidgetProps) {\n const externalReplayUrl = extraFields?.sessionReplay;\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const [hovered, setHovered] = useState(false);\n const colors = resolveTheme(theme);\n\n // ── Collectors ─────────────────────────────────────────────────────────────\n // Start synchronously so window.fetch is patched before React effects run,\n // ensuring the admin's initial API requests are captured.\n const consoleCollector = useRef<ReturnType<typeof createConsoleCollector> | null>(null);\n const networkCollector = useRef<ReturnType<typeof createNetworkCollector> | null>(null);\n const replayEvents = useRef<eventWithTime[]>([]);\n const stopReplay = useRef<(() => void) | null>(null);\n\n if (!consoleCollector.current) {\n consoleCollector.current = createConsoleCollector();\n consoleCollector.current.start();\n }\n if (!networkCollector.current) {\n networkCollector.current = createNetworkCollector();\n networkCollector.current.start();\n }\n\n useEffect(() => {\n // Start rrweb recording with rolling buffer (must be in effect for DOM access)\n const stopFn = record({\n emit(event) {\n replayEvents.current.push(event);\n // Trim to rolling window\n const cutoff = Date.now() - REPLAY_WINDOW_MS;\n while (\n replayEvents.current.length > 0 &&\n replayEvents.current[0].timestamp < cutoff\n ) {\n replayEvents.current.shift();\n }\n },\n });\n stopReplay.current = stopFn ?? null;\n\n return () => {\n consoleCollector.current?.stop();\n networkCollector.current?.stop();\n stopReplay.current?.();\n };\n }, []);\n\n const label = buttonLabel ?? t(\"buttonLabel\");\n\n return (\n <>\n {/* Floating trigger button */}\n <button\n onClick={() => setOpen(true)}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n aria-label={label}\n style={{\n position: \"fixed\",\n bottom: \"20px\",\n right: \"20px\",\n zIndex: zIndex - 1,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n padding: \"10px 18px\",\n borderRadius: \"24px\",\n border: \"none\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n fontSize: \"13px\",\n fontWeight: 600,\n cursor: \"pointer\",\n boxShadow: hovered\n ? `0 0 28px ${colors.accent}55, 0 8px 24px rgba(0,0,0,0.3)`\n : `0 0 16px ${colors.accent}33, 0 4px 16px rgba(0,0,0,0.2)`,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n transform: hovered ? \"translateY(-2px)\" : \"translateY(0)\",\n transition: \"transform 0.15s ease, box-shadow 0.15s ease\",\n letterSpacing: \"0.01em\",\n }}\n >\n <SparkIcon />\n {label}\n </button>\n\n {/* Modal */}\n {open && (\n <FlintModal\n projectKey={projectKey}\n serverUrl={serverUrl}\n user={user}\n meta={meta}\n theme={theme}\n zIndex={zIndex}\n onClose={() => setOpen(false)}\n getEnvironment={collectEnvironment}\n getConsoleLogs={() => consoleCollector.current?.getEntries() ?? []}\n getNetworkErrors={() => networkCollector.current?.getEntries() ?? []}\n getReplayEvents={() => [...replayEvents.current]}\n externalReplayUrl={externalReplayUrl}\n />\n )}\n </>\n );\n}\n\nfunction SparkIcon() {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n );\n}\n","import { useRef, useState, useEffect, useCallback } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport type {\n Severity,\n FlintUser,\n Theme,\n ReportResult,\n EnvironmentInfo,\n ConsoleEntry,\n NetworkEntry,\n} from \"@flint/types\";\nimport type { eventWithTime } from \"@rrweb/types\";\nimport { submitReport, submitReplay } from \"./api.js\";\nimport { resolveTheme } from \"./theme.js\";\n\ninterface Props {\n projectKey: string;\n serverUrl: string;\n user?: FlintUser;\n meta?: Record<string, unknown>;\n theme: Theme;\n zIndex: number;\n onClose: () => void;\n getEnvironment: () => EnvironmentInfo;\n getConsoleLogs: () => ConsoleEntry[];\n getNetworkErrors: () => NetworkEntry[];\n getReplayEvents: () => eventWithTime[];\n externalReplayUrl?: string;\n}\n\nconst SEVERITIES: Severity[] = [\"P1\", \"P2\", \"P3\", \"P4\"];\nconst SEV_COLOR: Record<Severity, string> = {\n P1: \"#ef4444\",\n P2: \"#f97316\",\n P3: \"#eab308\",\n P4: \"#22c55e\",\n};\n\ntype Status = \"idle\" | \"submitting\" | \"success\" | \"error\";\n\n// Inject CSS keyframes once — animations can't be done with inline styles alone\nfunction injectKeyframes() {\n if (typeof document === \"undefined\") return;\n if (document.getElementById(\"_flint_kf\")) return;\n const s = document.createElement(\"style\");\n s.id = \"_flint_kf\";\n s.textContent = `\n @keyframes _flint_in {\n from { opacity: 0; transform: scale(0.93) translateY(10px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n }\n @keyframes _flint_overlay_in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n @keyframes _flint_spin {\n to { transform: rotate(360deg); }\n }\n @keyframes _flint_pulse {\n 0%, 100% { opacity: 0.5; transform: scale(0.88); }\n 50% { opacity: 1; transform: scale(1.08); }\n }\n @keyframes _flint_ripple {\n 0% { opacity: 0.5; transform: scale(0.75); }\n 100% { opacity: 0; transform: scale(1.55); }\n }\n @keyframes _flint_sending_dot {\n 0%, 80%, 100% { opacity: 0.2; transform: scale(0.8); }\n 40% { opacity: 1; transform: scale(1); }\n }\n @keyframes _flint_success_up {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `;\n document.head.appendChild(s);\n}\n\nexport function FlintModal({\n projectKey,\n serverUrl,\n user,\n meta,\n theme,\n zIndex,\n onClose,\n getEnvironment,\n getConsoleLogs,\n getNetworkErrors,\n getReplayEvents,\n externalReplayUrl,\n}: Props) {\n const { t } = useTranslation();\n const colors = resolveTheme(theme);\n const isDark = theme === \"dark\";\n\n const [severity, setSeverity] = useState<Severity>(\"P2\");\n const [description, setDescription] = useState(\"\");\n const [expectedBehavior, setExpectedBehavior] = useState(\"\");\n const [screenshot, setScreenshot] = useState<File | null>(null);\n const [status, setStatus] = useState<Status>(\"idle\");\n const [result, setResult] = useState<ReportResult | null>(null);\n const [errorMsg, setErrorMsg] = useState(\"\");\n\n const fileRef = useRef<HTMLInputElement>(null);\n const overlayRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => { injectKeyframes(); }, []);\n\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && status !== \"submitting\") onClose();\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [onClose, status]);\n\n const handleOverlayClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === overlayRef.current && status !== \"submitting\") onClose();\n },\n [onClose, status],\n );\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!description.trim()) return;\n\n setStatus(\"submitting\");\n setErrorMsg(\"\");\n\n const collectedMeta: Record<string, unknown> = {\n ...meta,\n environment: getEnvironment(),\n consoleLogs: getConsoleLogs(),\n networkErrors: getNetworkErrors(),\n };\n\n try {\n const res = await submitReport(\n serverUrl,\n projectKey,\n {\n reporterId: user?.id ?? \"anonymous\",\n reporterName: user?.name ?? \"Anonymous\",\n description: description.trim(),\n expectedBehavior: expectedBehavior.trim() || undefined,\n externalReplayUrl: externalReplayUrl || undefined,\n severity,\n url: window.location.href,\n meta: collectedMeta,\n },\n screenshot ?? undefined,\n );\n setResult(res);\n setStatus(\"success\");\n\n const events = getReplayEvents();\n if (events.length > 0) {\n submitReplay(serverUrl, projectKey, res.id, events).catch(() => {});\n }\n } catch (err) {\n setErrorMsg(err instanceof Error ? err.message : t(\"errorLabel\"));\n setStatus(\"error\");\n }\n };\n\n // ── Shared style tokens ────────────────────────────────────────────────────\n const inputBorder = isDark ? \"rgba(255,255,255,0.1)\" : \"rgba(0,0,0,0.1)\";\n const accentGlow = `0 0 20px ${colors.accent}40, 0 4px 16px rgba(0,0,0,0.2)`;\n\n const overlayStyle: React.CSSProperties = {\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.5)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex,\n padding: \"16px\",\n backdropFilter: \"blur(10px)\",\n WebkitBackdropFilter: \"blur(10px)\",\n animation: \"_flint_overlay_in 0.2s ease\",\n };\n\n const modalStyle: React.CSSProperties = {\n background: colors.background,\n backdropFilter: colors.backdropFilter,\n WebkitBackdropFilter: colors.backdropFilter,\n borderRadius: \"20px\",\n boxShadow: colors.shadow,\n border: `1px solid ${colors.border}`,\n width: \"100%\",\n maxWidth: \"480px\",\n maxHeight: \"92vh\",\n overflowY: \"auto\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n color: colors.text,\n animation: \"_flint_in 0.28s cubic-bezier(0.16, 1, 0.3, 1)\",\n };\n\n const inputStyle: React.CSSProperties = {\n width: \"100%\",\n padding: \"11px 13px\",\n borderRadius: \"10px\",\n border: `1px solid ${inputBorder}`,\n background: colors.backgroundSecondary,\n color: colors.text,\n fontSize: \"14px\",\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"inherit\",\n transition: \"border-color 0.15s\",\n };\n\n // ── Loading + Success (unified animated state) ────────────────────────────\n if (status === \"submitting\" || status === \"success\") {\n const isSuccess = status === \"success\";\n const ringBorder = isSuccess\n ? \"3px solid #22c55e\"\n : `3px solid ${isDark ? \"rgba(255,255,255,0.08)\" : \"rgba(0,0,0,0.08)\"}`;\n const ringTopColor = isSuccess ? \"#22c55e\" : colors.accent;\n\n return (\n <div style={overlayStyle}>\n <div style={modalStyle} role=\"dialog\" aria-modal=\"true\" aria-label={isSuccess ? t(\"successTitle\") : t(\"sending\")}>\n <ModalHeader colors={colors} inputBorder={inputBorder} showClose={false} onClose={onClose} />\n\n <div style={{ padding: \"40px 32px 48px\", textAlign: \"center\", display: \"flex\", flexDirection: \"column\", alignItems: \"center\" }}>\n {/* Animated rings */}\n <div style={{ position: \"relative\", width: 80, height: 80, marginBottom: 28 }}>\n {/* Ripple 1 — fade out on success */}\n <div style={{\n position: \"absolute\", inset: -10,\n borderRadius: \"50%\",\n border: `1.5px solid ${colors.accent}`,\n animation: \"_flint_ripple 1.8s ease-out infinite\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }} />\n {/* Ripple 2 (delayed) */}\n <div style={{\n position: \"absolute\", inset: -10,\n borderRadius: \"50%\",\n border: `1.5px solid ${colors.accent}`,\n animation: \"_flint_ripple 1.8s ease-out infinite 0.6s\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }} />\n {/* Spinning ring — transitions to solid green on success */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n border: ringBorder,\n borderTopColor: ringTopColor,\n animation: isSuccess ? \"none\" : \"_flint_spin 0.85s linear infinite\",\n transition: \"border-color 0.45s ease, border-top-color 0.45s ease\",\n }} />\n {/* Center: spark fades out, check fades in */}\n <div style={{ position: \"absolute\", inset: 14, borderRadius: \"50%\" }}>\n {/* Spark */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n background: `linear-gradient(135deg, ${colors.accent}30, ${colors.accentHover}50)`,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n animation: isSuccess ? \"none\" : \"_flint_pulse 2s ease-in-out infinite\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }}>\n <SparkIcon color={colors.accent} size={20} />\n </div>\n {/* Checkmark */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n background: \"rgba(34,197,94,0.15)\",\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"scale(1)\" : \"scale(0.65)\",\n transition: \"opacity 0.35s ease 0.2s, transform 0.4s cubic-bezier(0.16,1,0.3,1) 0.2s\",\n }}>\n <CheckIcon size={20} />\n </div>\n </div>\n </div>\n\n {/* Title crossfade */}\n <div style={{ position: \"relative\", height: 26, width: \"100%\", marginBottom: 10 }}>\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n fontSize: 17, fontWeight: 700, color: colors.text, letterSpacing: \"-0.02em\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.25s ease\",\n pointerEvents: \"none\",\n }}>\n {t(\"sending\")}\n </div>\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n fontSize: 17, fontWeight: 700, color: colors.text, letterSpacing: \"-0.02em\",\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"translateY(0)\" : \"translateY(6px)\",\n transition: \"opacity 0.35s ease 0.25s, transform 0.35s ease 0.25s\",\n pointerEvents: isSuccess ? \"auto\" : \"none\",\n }}>\n {t(\"successTitle\")}\n </div>\n </div>\n\n {/* Subtitle crossfade */}\n <div style={{ position: \"relative\", minHeight: 76, width: \"100%\" }}>\n {/* Loading subtitle */}\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n gap: 6, color: colors.textMuted, fontSize: 13,\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.2s ease\",\n pointerEvents: \"none\",\n }}>\n <span>{t(\"capturingContext\")}</span>\n <SendingDots color={colors.accent} />\n </div>\n {/* Success subtitle */}\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", flexDirection: \"column\", alignItems: \"center\", gap: 10,\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"translateY(0)\" : \"translateY(8px)\",\n transition: \"opacity 0.35s ease 0.35s, transform 0.35s ease 0.35s\",\n pointerEvents: isSuccess ? \"auto\" : \"none\",\n }}>\n <p style={{ fontSize: 13, color: colors.textMuted, margin: 0 }}>\n {result?.isDuplicate ? t(\"successDuplicate\") : result ? `ID: ${result.id}` : \"\"}\n </p>\n {result?.githubIssueUrl && (\n <a\n href={result.githubIssueUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 6,\n padding: \"9px 18px\",\n borderRadius: \"10px\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n textDecoration: \"none\",\n fontSize: \"13px\",\n fontWeight: 600,\n boxShadow: accentGlow,\n }}\n >\n {t(\"successGitHub\")} ↗\n </a>\n )}\n <button\n onClick={onClose}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n padding: \"4px 8px\",\n fontFamily: \"inherit\",\n }}\n >\n {t(\"cancel\")}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n // ── Form ──────────────────────────────────────────────────────────────────\n return (\n <div ref={overlayRef} style={overlayStyle} onClick={handleOverlayClick}>\n <div style={modalStyle} role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"flint-modal-title\">\n <ModalHeader\n colors={colors}\n inputBorder={inputBorder}\n showClose\n onClose={onClose}\n titleId=\"flint-modal-title\"\n title={t(\"modalTitle\")}\n />\n\n <form onSubmit={handleSubmit} style={{ padding: \"20px 24px 24px\" }}>\n {/* Severity */}\n <div style={{ marginBottom: 18 }}>\n <FieldLabel colors={colors}>{t(\"severityLabel\")}</FieldLabel>\n <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(4,1fr)\", gap: 8 }}>\n {SEVERITIES.map((sev) => (\n <SeverityButton\n key={sev}\n sev={sev}\n label={t(`severity_${sev}_label`)}\n selected={severity === sev}\n hint={t(`severity_${sev}_hint`)}\n color={SEV_COLOR[sev]}\n accent={colors.accent}\n border={inputBorder}\n bg={colors.backgroundSecondary}\n text={colors.text}\n onClick={() => setSeverity(sev)}\n />\n ))}\n </div>\n </div>\n\n {/* What Is Broken */}\n <div style={{ marginBottom: 14 }}>\n <FieldLabel colors={colors} htmlFor=\"flint-description\">{t(\"whatIsBrokenLabel\")}</FieldLabel>\n <textarea\n id=\"flint-description\"\n style={{ ...inputStyle, resize: \"vertical\", minHeight: 80 }}\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder={t(\"whatIsBrokenPlaceholder\")}\n required\n />\n </div>\n\n {/* Expected Behavior (optional) */}\n <div style={{ marginBottom: 14 }}>\n <FieldLabel colors={colors} htmlFor=\"flint-expected\">{t(\"expectedBehaviorLabel\")}</FieldLabel>\n <textarea\n id=\"flint-expected\"\n style={{ ...inputStyle, resize: \"vertical\", minHeight: 72 }}\n value={expectedBehavior}\n onChange={(e) => setExpectedBehavior(e.target.value)}\n placeholder={t(\"expectedBehaviorPlaceholder\")}\n />\n </div>\n\n {/* Screenshot */}\n <div style={{ marginBottom: 20 }}>\n <FieldLabel colors={colors}>{t(\"screenshotLabel\")}</FieldLabel>\n <label\n htmlFor=\"flint-screenshot\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"10px 13px\",\n borderRadius: 10,\n border: `1px dashed ${inputBorder}`,\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n background: colors.backgroundSecondary,\n }}\n >\n 📎 {screenshot ? screenshot.name : t(\"screenshotPlaceholder\")}\n </label>\n <input\n id=\"flint-screenshot\"\n ref={fileRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={(e) => setScreenshot(e.target.files?.[0] ?? null)}\n />\n </div>\n\n {/* Error */}\n {status === \"error\" && (\n <div style={{\n padding: \"10px 13px\",\n borderRadius: 10,\n background: \"rgba(239,68,68,0.08)\",\n border: \"1px solid rgba(239,68,68,0.2)\",\n color: \"#f87171\",\n fontSize: 12,\n marginBottom: 16,\n }}>\n ⚠️ {errorMsg || t(\"errorLabel\")}\n </div>\n )}\n\n {/* Submit */}\n <button\n type=\"submit\"\n style={{\n width: \"100%\",\n padding: \"13px 20px\",\n borderRadius: 12,\n border: \"none\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n fontSize: 15,\n fontWeight: 700,\n cursor: \"pointer\",\n letterSpacing: \"-0.01em\",\n boxShadow: accentGlow,\n fontFamily: \"inherit\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 8,\n }}\n >\n <SparkIcon color={colors.buttonText} size={15} />\n {t(\"submitLabel\")}\n </button>\n\n {/* Cancel */}\n <button\n type=\"button\"\n onClick={onClose}\n style={{\n width: \"100%\",\n padding: \"10px\",\n marginTop: 8,\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n fontFamily: \"inherit\",\n borderRadius: 8,\n }}\n >\n {t(\"cancel\")}\n </button>\n </form>\n </div>\n </div>\n );\n}\n\n// ─── Sub-components ──────────────────────────────────────────────────────────\n\nfunction ModalHeader({\n colors,\n inputBorder,\n showClose,\n onClose,\n titleId,\n title,\n}: {\n colors: ReturnType<typeof resolveTheme>;\n inputBorder: string;\n showClose: boolean;\n onClose: () => void;\n titleId?: string;\n title?: string;\n}) {\n return (\n <div style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n padding: \"16px 20px 14px\",\n borderBottom: `1px solid ${inputBorder}`,\n }}>\n {/* Brand chip */}\n <div style={{\n width: 28, height: 28,\n borderRadius: 8,\n background: `linear-gradient(135deg, ${colors.accent}20, ${colors.accentHover}35)`,\n border: `1px solid ${colors.accent}30`,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n flexShrink: 0,\n }}>\n <SparkIcon color={colors.accent} size={13} />\n </div>\n\n {titleId && title ? (\n <h2 id={titleId} style={{ margin: 0, fontSize: 14, fontWeight: 600, color: colors.text, letterSpacing: \"-0.01em\", flex: 1 }}>\n {title}\n </h2>\n ) : (\n <span style={{ flex: 1, fontSize: 13, fontWeight: 600, color: colors.textMuted }}>Flint</span>\n )}\n\n {showClose && (\n <button\n onClick={onClose}\n aria-label=\"Close\"\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: 4,\n color: colors.textMuted,\n fontSize: 20,\n lineHeight: 1,\n borderRadius: 6,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n opacity: 0.6,\n fontFamily: \"inherit\",\n }}\n >\n ×\n </button>\n )}\n </div>\n );\n}\n\nfunction FieldLabel({\n children,\n colors,\n htmlFor,\n}: {\n children: React.ReactNode;\n colors: ReturnType<typeof resolveTheme>;\n htmlFor?: string;\n}) {\n return (\n <label\n htmlFor={htmlFor}\n style={{\n display: \"block\",\n fontSize: \"10px\",\n fontWeight: 700,\n color: colors.textMuted,\n marginBottom: 6,\n textTransform: \"uppercase\" as const,\n letterSpacing: \"0.07em\",\n }}\n >\n {children}\n </label>\n );\n}\n\nfunction SendingDots({ color }: { color: string }) {\n return (\n <span style={{ display: \"inline-flex\", gap: 3, alignItems: \"center\" }}>\n {[0, 1, 2].map((i) => (\n <span\n key={i}\n style={{\n width: 4, height: 4,\n borderRadius: \"50%\",\n background: color,\n display: \"inline-block\",\n animation: `_flint_sending_dot 1.4s ease-in-out infinite ${i * 0.2}s`,\n }}\n />\n ))}\n </span>\n );\n}\n\ninterface SevBtnProps {\n sev: Severity;\n label: string;\n selected: boolean;\n hint: string;\n color: string;\n accent: string;\n border: string;\n bg: string;\n text: string;\n onClick: () => void;\n}\n\nfunction SeverityButton({ sev, label, selected, hint, color, accent, border, bg, text, onClick }: SevBtnProps) {\n return (\n <button\n type=\"button\"\n title={hint}\n onClick={onClick}\n style={{\n padding: \"9px 6px 8px\",\n borderRadius: 10,\n border: selected ? `2px solid ${accent}` : `1.5px solid ${border}`,\n background: selected ? `${accent}15` : bg,\n cursor: \"pointer\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: 5,\n transition: \"border-color 0.12s, background 0.12s\",\n fontFamily: \"inherit\",\n }}\n >\n <span style={{ width: 8, height: 8, borderRadius: \"50%\", background: color, display: \"block\" }} />\n <span style={{ fontSize: 11, fontWeight: selected ? 700 : 500, color: selected ? accent : text, letterSpacing: \"0.02em\" }}>\n {sev}\n </span>\n <span style={{ fontSize: 9, color: selected ? accent : text, opacity: 0.6, letterSpacing: \"0.02em\" }}>\n {label}\n </span>\n </button>\n );\n}\n\nfunction SparkIcon({ color = \"currentColor\", size = 14 }: { color?: string; size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n );\n}\n\nfunction CheckIcon({ size = 20 }: { size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#22c55e\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n","import type { ReportPayload, ReportResult } from \"@flint/types\";\nimport { gzipSync } from \"fflate\";\nimport type { eventWithTime } from \"@rrweb/types\";\n\nexport async function submitReport(\n serverUrl: string,\n projectKey: string,\n payload: ReportPayload,\n screenshot?: File,\n): Promise<ReportResult> {\n const url = `${serverUrl.replace(/\\/$/, \"\")}/api/v1/bug-reports`;\n\n let body: BodyInit;\n let headers: Record<string, string> = {\n \"x-project-key\": projectKey,\n };\n\n if (screenshot) {\n const form = new FormData();\n form.append(\"reporterId\", payload.reporterId);\n form.append(\"reporterName\", payload.reporterName);\n form.append(\"description\", payload.description);\n if (payload.expectedBehavior) form.append(\"expectedBehavior\", payload.expectedBehavior);\n if (payload.stepsToReproduce) form.append(\"stepsToReproduce\", JSON.stringify(payload.stepsToReproduce));\n if (payload.externalReplayUrl) form.append(\"externalReplayUrl\", payload.externalReplayUrl);\n if (payload.additionalContext) form.append(\"additionalContext\", payload.additionalContext);\n form.append(\"severity\", payload.severity);\n if (payload.url) form.append(\"url\", payload.url);\n if (payload.meta) form.append(\"meta\", JSON.stringify(payload.meta));\n form.append(\"screenshot\", screenshot);\n body = form;\n } else {\n body = JSON.stringify(payload);\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const res = await fetch(url, { method: \"POST\", headers, body });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: \"Unknown error\" }));\n throw new Error((err as { error?: string }).error ?? `HTTP ${res.status}`);\n }\n\n return res.json() as Promise<ReportResult>;\n}\n\nexport async function submitReplay(\n serverUrl: string,\n projectKey: string,\n reportId: string,\n events: eventWithTime[],\n): Promise<void> {\n const json = JSON.stringify(events);\n const encoded = new TextEncoder().encode(json);\n const compressed = gzipSync(encoded);\n\n const url = `${serverUrl.replace(/\\/$/, \"\")}/api/v1/bug-reports/${reportId}/replay`;\n await fetch(url, {\n method: \"POST\",\n headers: {\n \"x-project-key\": projectKey,\n \"Content-Type\": \"application/octet-stream\",\n },\n body: compressed.buffer as ArrayBuffer,\n });\n}\n","import type { Theme, ThemeOverride } from \"@flint/types\";\n\nexport interface ResolvedTheme {\n background: string;\n backgroundSecondary: string;\n accent: string;\n accentHover: string;\n text: string;\n textMuted: string;\n border: string;\n shadow: string;\n buttonText: string;\n backdropFilter: string;\n}\n\nconst light: ResolvedTheme = {\n background: \"rgba(255,255,255,0.90)\",\n backgroundSecondary: \"rgba(249,250,251,0.75)\",\n accent: \"#2563eb\",\n accentHover: \"#1d4ed8\",\n text: \"#111827\",\n textMuted: \"#6b7280\",\n border: \"rgba(255,255,255,0.9)\",\n shadow:\n \"0 32px 80px rgba(0,0,0,0.18), 0 8px 32px rgba(0,0,0,0.1), 0 0 0 1px rgba(0,0,0,0.04)\",\n buttonText: \"#ffffff\",\n backdropFilter: \"blur(32px) saturate(1.8)\",\n};\n\nconst dark: ResolvedTheme = {\n background: \"rgba(15,20,35,0.88)\",\n backgroundSecondary: \"rgba(5,8,18,0.65)\",\n accent: \"#f97316\",\n accentHover: \"#ea6c0a\",\n text: \"#dde3ef\",\n textMuted: \"#6b7a93\",\n border: \"rgba(255,255,255,0.08)\",\n shadow:\n \"0 24px 60px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04)\",\n buttonText: \"#ffffff\",\n backdropFilter: \"blur(32px) saturate(1.6)\",\n};\n\nexport function resolveTheme(theme: Theme): ResolvedTheme {\n if (theme === \"dark\") return dark;\n if (theme === \"light\") return light;\n // ThemeOverride — merge over light base\n const override = theme as ThemeOverride;\n return {\n ...light,\n background: override.background ?? light.background,\n accent: override.accent ?? light.accent,\n accentHover: override.accent ?? light.accentHover,\n text: override.text ?? light.text,\n border: override.border ?? light.border,\n };\n}\n","import i18next, { createInstance } from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\nimport en from \"./locales/en.json\";\n\nexport const widgetI18n: ReturnType<typeof createInstance> = createInstance();\n\nwidgetI18n.use(initReactI18next).init({\n lng: \"en-US\",\n fallbackLng: \"en-US\",\n resources: { \"en-US\": { translation: en } },\n interpolation: { escapeValue: false },\n initImmediate: false,\n});\n\nexport default widgetI18n;\n","{\n \"buttonLabel\": \"Report bug\",\n \"modalTitle\": \"Report an issue\",\n \"severityLabel\": \"Severity\",\n \"severity_P1_hint\": \"Critical — system down\",\n \"severity_P2_hint\": \"High — core feature broken\",\n \"severity_P3_hint\": \"Medium — noticeable but workable\",\n \"severity_P4_hint\": \"Low — cosmetic or improvement\",\n \"severity_P1_label\": \"Critical\",\n \"severity_P2_label\": \"High\",\n \"severity_P3_label\": \"Medium\",\n \"severity_P4_label\": \"Low\",\n \"whatIsBrokenLabel\": \"What Is Broken\",\n \"whatIsBrokenPlaceholder\": \"1–2 sentences: what is currently happening that should NOT happen.\",\n \"expectedBehaviorLabel\": \"Expected Behavior (optional)\",\n \"expectedBehaviorPlaceholder\": \"Describe exactly what the user should see or receive after the fix.\",\n \"screenshotLabel\": \"Screenshot (optional)\",\n \"screenshotPlaceholder\": \"Click to attach...\",\n \"submitLabel\": \"Submit\",\n \"successTitle\": \"Bug reported!\",\n \"successDuplicate\": \"Looks like a duplicate of an existing bug.\",\n \"successGitHub\": \"View GitHub issue\",\n \"errorLabel\": \"Failed to submit. Please try again.\",\n \"cancel\": \"Cancel\",\n \"sending\": \"Sending report\",\n \"capturingContext\": \"Capturing context\"\n}\n","import type { EnvironmentInfo } from \"@flint/types\";\n\nexport function collectEnvironment(): EnvironmentInfo {\n const ua = navigator.userAgent;\n\n // ── Browser ──────────────────────────────────────────────────────────────\n let browser = \"Unknown\";\n const chromeM = ua.match(/Chrome\\/(\\d+)/);\n const firefoxM = ua.match(/Firefox\\/(\\d+)/);\n const edgeM = ua.match(/Edg\\/(\\d+)/);\n const safariM = ua.match(/Version\\/(\\d+)/);\n const operaM = ua.match(/OPR\\/(\\d+)/);\n\n if (operaM) {\n browser = `Opera ${operaM[1]}`;\n } else if (edgeM) {\n browser = `Edge ${edgeM[1]}`;\n } else if (chromeM && !/Edg|OPR/.test(ua)) {\n browser = `Chrome ${chromeM[1]}`;\n } else if (firefoxM) {\n browser = `Firefox ${firefoxM[1]}`;\n } else if (safariM && /Safari\\//.test(ua)) {\n browser = `Safari ${safariM[1]}`;\n }\n\n // ── OS ────────────────────────────────────────────────────────────────────\n let os = \"Unknown\";\n const macM = ua.match(/Mac OS X (\\d+[._]\\d+)/);\n const winM = ua.match(/Windows NT (\\d+\\.\\d+)/);\n const androidM = ua.match(/Android (\\d+)/);\n const iosM = ua.match(/iPhone OS (\\d+[._]\\d+)/);\n\n if (macM) {\n os = `macOS ${macM[1].replace(\"_\", \".\")}`;\n } else if (winM) {\n const winMap: Record<string, string> = {\n \"10.0\": \"10/11\",\n \"6.3\": \"8.1\",\n \"6.2\": \"8\",\n \"6.1\": \"7\",\n };\n os = `Windows ${winMap[winM[1]] ?? winM[1]}`;\n } else if (androidM) {\n os = `Android ${androidM[1]}`;\n } else if (iosM) {\n os = `iOS ${iosM[1].replace(/_/g, \".\")}`;\n } else if (/Linux/.test(ua)) {\n os = \"Linux\";\n }\n\n return {\n browser,\n os,\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n screen: `${screen.width}x${screen.height}`,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n online: navigator.onLine,\n };\n}\n","import type { ConsoleEntry } from \"@flint/types\";\n\nconst MAX_ENTRIES = 50;\n\nexport interface ConsoleCollector {\n start(): void;\n stop(): void;\n getEntries(): ConsoleEntry[];\n}\n\nexport function createConsoleCollector(): ConsoleCollector {\n const entries: ConsoleEntry[] = [];\n let active = false;\n\n const originals = {\n log: console.log.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n };\n\n let origOnerror: typeof window.onerror = null;\n let origUnhandled: typeof window.onunhandledrejection = null;\n\n function push(level: ConsoleEntry[\"level\"], args: unknown[]) {\n let str: string;\n try {\n str = args\n .map((a) => (typeof a === \"string\" ? a : JSON.stringify(a)))\n .join(\" \");\n } catch {\n str = String(args[0]);\n }\n if (str.length > 500) str = str.slice(0, 500) + \"…\";\n entries.push({ level, args: str, timestamp: Date.now() });\n if (entries.length > MAX_ENTRIES) entries.shift();\n }\n\n return {\n start() {\n if (active) return;\n active = true;\n\n console.log = (...args: unknown[]) => {\n push(\"log\", args);\n originals.log(...args);\n };\n console.warn = (...args: unknown[]) => {\n push(\"warn\", args);\n originals.warn(...args);\n };\n console.error = (...args: unknown[]) => {\n push(\"error\", args);\n originals.error(...args);\n };\n\n origOnerror = window.onerror;\n window.onerror = (msg, src, line, col, err) => {\n push(\"error\", [err?.message ?? String(msg), `${src}:${line}:${col}`]);\n if (typeof origOnerror === \"function\")\n return origOnerror(msg, src, line, col, err);\n return false;\n };\n\n origUnhandled = window.onunhandledrejection;\n window.onunhandledrejection = (event) => {\n const reason =\n event.reason instanceof Error\n ? event.reason.message\n : JSON.stringify(event.reason);\n push(\"error\", [\"UnhandledRejection:\", reason]);\n if (typeof origUnhandled === \"function\")\n origUnhandled.call(window, event);\n };\n },\n\n stop() {\n if (!active) return;\n active = false;\n console.log = originals.log;\n console.warn = originals.warn;\n console.error = originals.error;\n window.onerror = origOnerror;\n window.onunhandledrejection = origUnhandled;\n },\n\n getEntries() {\n return [...entries];\n },\n };\n}\n","import type { NetworkEntry } from \"@flint/types\";\n\nconst MAX_ENTRIES = 20;\n\nexport interface NetworkCollector {\n start(): void;\n stop(): void;\n getEntries(): NetworkEntry[];\n}\n\nfunction truncateUrl(url: string): string {\n try {\n const u = new URL(url, location.href);\n const base = `${u.origin}${u.pathname}`;\n return base.length > 200 ? base.slice(0, 200) + \"…\" : base;\n } catch {\n return url.length > 200 ? url.slice(0, 200) + \"…\" : url;\n }\n}\n\nexport function createNetworkCollector(): NetworkCollector {\n const entries: NetworkEntry[] = [];\n let origFetch: typeof window.fetch | null = null;\n let origXHROpen: typeof XMLHttpRequest.prototype.open | null = null;\n let active = false;\n\n function push(entry: NetworkEntry) {\n entries.push(entry);\n if (entries.length > MAX_ENTRIES) entries.shift();\n }\n\n return {\n start() {\n if (active) return;\n active = true;\n\n // ── Patch fetch ────────────────────────────────────────────────────────\n origFetch = window.fetch;\n window.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const method = ((init?.method ?? \"GET\") as string).toUpperCase();\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : (input as Request).url;\n const startTime = Date.now();\n const res = await origFetch!.call(window, input, init);\n push({\n method,\n url: truncateUrl(url),\n status: res.status,\n duration: Date.now() - startTime,\n timestamp: startTime,\n });\n return res;\n };\n\n // ── Patch XHR ─────────────────────────────────────────────────────────\n origXHROpen = XMLHttpRequest.prototype.open;\n XMLHttpRequest.prototype.open = function (\n method: string,\n url: string | URL,\n async?: boolean,\n username?: string | null,\n password?: string | null,\n ) {\n const startTime = Date.now();\n const urlStr =\n typeof url === \"string\" ? url : (url as URL).href;\n\n this.addEventListener(\"load\", () => {\n push({\n method: method.toUpperCase(),\n url: truncateUrl(urlStr),\n status: this.status,\n duration: Date.now() - startTime,\n timestamp: startTime,\n });\n });\n\n return origXHROpen!.apply(this, [\n method,\n url,\n async ?? true,\n username,\n password,\n ] as Parameters<typeof XMLHttpRequest.prototype.open>);\n };\n },\n\n stop() {\n if (!active) return;\n active = false;\n if (origFetch) window.fetch = origFetch;\n if (origXHROpen) XMLHttpRequest.prototype.open = origXHROpen;\n },\n\n getEntries() {\n return [...entries];\n },\n };\n}\n"],"mappings":"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","names":["useState","useEffect","useRef","useTranslation","MAX_ENTRIES","jsx","jsxs","useEffect","useTranslation","useState","useRef","SparkIcon"]}
|
|
1
|
+
{"version":3,"sources":["../src/FlintWidget.tsx","../src/FlintModal.tsx","../src/api.ts","../src/theme.ts","../src/i18n/index.ts","../src/i18n/locales/en.json","../src/collectors/environment.ts","../src/collectors/console.ts","../src/collectors/network.ts","../src/store.ts"],"sourcesContent":["import { useState, useEffect, useRef } from \"react\";\nimport { I18nextProvider, useTranslation } from \"react-i18next\";\nimport { FlintModal } from \"./FlintModal.js\";\nimport type { FlintWidgetProps } from \"@flint/types\";\nimport { resolveTheme } from \"./theme.js\";\nimport widgetI18n from \"./i18n/index.js\";\nimport { collectEnvironment } from \"./collectors/environment.js\";\nimport { createConsoleCollector } from \"./collectors/console.js\";\nimport { createNetworkCollector } from \"./collectors/network.js\";\nimport { useFlintStore } from \"./store.js\";\nimport { record } from \"rrweb\";\nimport type { eventWithTime } from \"@rrweb/types\";\n\nconst REPLAY_WINDOW_MS = 60_000; // rolling 60-second buffer\n\nexport function FlintWidget(props: FlintWidgetProps) {\n const { locale = \"en-US\" } = props;\n\n useEffect(() => {\n widgetI18n.changeLanguage(locale);\n }, [locale]);\n\n return (\n <I18nextProvider i18n={widgetI18n}>\n <WidgetContent {...props} />\n </I18nextProvider>\n );\n}\n\nfunction WidgetContent({\n projectKey,\n serverUrl,\n user,\n meta,\n extraFields,\n buttonLabel,\n theme = \"dark\",\n zIndex = 9999,\n}: FlintWidgetProps) {\n const globalState = useFlintStore();\n const resolvedUser = user ?? globalState.user;\n const resolvedSessionReplay = extraFields?.sessionReplay ?? globalState.sessionReplay;\n const getExternalReplayUrl = () => {\n const src = resolvedSessionReplay;\n return typeof src === \"function\" ? src() : src;\n };\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const [hovered, setHovered] = useState(false);\n const colors = resolveTheme(theme);\n\n // ── Collectors ─────────────────────────────────────────────────────────────\n // Start synchronously so window.fetch is patched before React effects run,\n // ensuring the admin's initial API requests are captured.\n const consoleCollector = useRef<ReturnType<typeof createConsoleCollector> | null>(null);\n const networkCollector = useRef<ReturnType<typeof createNetworkCollector> | null>(null);\n const replayEvents = useRef<eventWithTime[]>([]);\n const stopReplay = useRef<(() => void) | null>(null);\n\n if (!consoleCollector.current) {\n consoleCollector.current = createConsoleCollector();\n consoleCollector.current.start();\n }\n if (!networkCollector.current) {\n networkCollector.current = createNetworkCollector();\n networkCollector.current.start();\n }\n\n useEffect(() => {\n // Start rrweb recording with rolling buffer (must be in effect for DOM access)\n const stopFn = record({\n emit(event) {\n replayEvents.current.push(event);\n // Trim to rolling window\n const cutoff = Date.now() - REPLAY_WINDOW_MS;\n while (\n replayEvents.current.length > 0 &&\n replayEvents.current[0].timestamp < cutoff\n ) {\n replayEvents.current.shift();\n }\n },\n });\n stopReplay.current = stopFn ?? null;\n\n return () => {\n consoleCollector.current?.stop();\n networkCollector.current?.stop();\n stopReplay.current?.();\n };\n }, []);\n\n const label = buttonLabel ?? t(\"buttonLabel\");\n\n return (\n <>\n {/* Floating trigger button */}\n <button\n onClick={() => setOpen(true)}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n aria-label={label}\n style={{\n position: \"fixed\",\n bottom: \"40px\",\n right: \"20px\",\n zIndex: zIndex - 1,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n padding: \"10px 18px\",\n borderRadius: \"24px\",\n border: \"none\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n fontSize: \"13px\",\n fontWeight: 600,\n cursor: \"pointer\",\n boxShadow: hovered\n ? `0 0 28px ${colors.accent}55, 0 8px 24px rgba(0,0,0,0.3)`\n : `0 0 16px ${colors.accent}33, 0 4px 16px rgba(0,0,0,0.2)`,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n transform: hovered ? \"translateY(-2px)\" : \"translateY(0)\",\n transition: \"transform 0.15s ease, box-shadow 0.15s ease\",\n letterSpacing: \"0.01em\",\n }}\n >\n <SparkIcon />\n {label}\n </button>\n\n {/* Modal */}\n {open && (\n <FlintModal\n projectKey={projectKey}\n serverUrl={serverUrl}\n user={resolvedUser}\n meta={meta}\n theme={theme}\n zIndex={zIndex}\n onClose={() => setOpen(false)}\n getEnvironment={collectEnvironment}\n getConsoleLogs={() => consoleCollector.current?.getEntries() ?? []}\n getNetworkErrors={() => networkCollector.current?.getEntries() ?? []}\n getReplayEvents={() => [...replayEvents.current]}\n getExternalReplayUrl={getExternalReplayUrl}\n />\n )}\n </>\n );\n}\n\nfunction SparkIcon() {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n );\n}\n","import { useRef, useState, useEffect, useCallback } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport type {\n Severity,\n FlintUser,\n Theme,\n ReportResult,\n EnvironmentInfo,\n ConsoleEntry,\n NetworkEntry,\n} from \"@flint/types\";\nimport type { eventWithTime } from \"@rrweb/types\";\nimport { submitReport, submitReplay } from \"./api.js\";\nimport { resolveTheme } from \"./theme.js\";\n\ninterface Props {\n projectKey: string;\n serverUrl: string;\n user?: FlintUser;\n meta?: Record<string, unknown>;\n theme: Theme;\n zIndex: number;\n onClose: () => void;\n getEnvironment: () => EnvironmentInfo;\n getConsoleLogs: () => ConsoleEntry[];\n getNetworkErrors: () => NetworkEntry[];\n getReplayEvents: () => eventWithTime[];\n getExternalReplayUrl: () => string | undefined;\n}\n\nconst SEVERITIES: Severity[] = [\"P1\", \"P2\", \"P3\", \"P4\"];\nconst SEV_COLOR: Record<Severity, string> = {\n P1: \"#ef4444\",\n P2: \"#f97316\",\n P3: \"#eab308\",\n P4: \"#22c55e\",\n};\n\ntype Status = \"idle\" | \"submitting\" | \"success\" | \"error\";\n\n// Inject CSS keyframes once — animations can't be done with inline styles alone\nfunction injectKeyframes() {\n if (typeof document === \"undefined\") return;\n if (document.getElementById(\"_flint_kf\")) return;\n const s = document.createElement(\"style\");\n s.id = \"_flint_kf\";\n s.textContent = `\n @keyframes _flint_in {\n from { opacity: 0; transform: scale(0.93) translateY(10px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n }\n @keyframes _flint_overlay_in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n @keyframes _flint_spin {\n to { transform: rotate(360deg); }\n }\n @keyframes _flint_pulse {\n 0%, 100% { opacity: 0.5; transform: scale(0.88); }\n 50% { opacity: 1; transform: scale(1.08); }\n }\n @keyframes _flint_ripple {\n 0% { opacity: 0.5; transform: scale(0.75); }\n 100% { opacity: 0; transform: scale(1.55); }\n }\n @keyframes _flint_sending_dot {\n 0%, 80%, 100% { opacity: 0.2; transform: scale(0.8); }\n 40% { opacity: 1; transform: scale(1); }\n }\n @keyframes _flint_success_up {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `;\n document.head.appendChild(s);\n}\n\nexport function FlintModal({\n projectKey,\n serverUrl,\n user,\n meta,\n theme,\n zIndex,\n onClose,\n getEnvironment,\n getConsoleLogs,\n getNetworkErrors,\n getReplayEvents,\n getExternalReplayUrl,\n}: Props) {\n const { t } = useTranslation();\n const colors = resolveTheme(theme);\n const isDark = theme === \"dark\";\n\n const [severity, setSeverity] = useState<Severity>(\"P2\");\n const [description, setDescription] = useState(\"\");\n const [expectedBehavior, setExpectedBehavior] = useState(\"\");\n const [screenshot, setScreenshot] = useState<File | null>(null);\n const [status, setStatus] = useState<Status>(\"idle\");\n const [result, setResult] = useState<ReportResult | null>(null);\n const [errorMsg, setErrorMsg] = useState(\"\");\n\n const fileRef = useRef<HTMLInputElement>(null);\n const overlayRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => { injectKeyframes(); }, []);\n\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && status !== \"submitting\") onClose();\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [onClose, status]);\n\n const handleOverlayClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === overlayRef.current && status !== \"submitting\") onClose();\n },\n [onClose, status],\n );\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!description.trim()) return;\n\n setStatus(\"submitting\");\n setErrorMsg(\"\");\n\n const collectedMeta: Record<string, unknown> = {\n ...meta,\n environment: getEnvironment(),\n consoleLogs: getConsoleLogs(),\n networkErrors: getNetworkErrors(),\n };\n\n try {\n const res = await submitReport(\n serverUrl,\n projectKey,\n {\n reporterId: user?.id ?? \"anonymous\",\n reporterName: user?.name ?? \"Anonymous\",\n description: description.trim(),\n expectedBehavior: expectedBehavior.trim() || undefined,\n externalReplayUrl: getExternalReplayUrl() || undefined,\n severity,\n url: window.location.href,\n meta: collectedMeta,\n },\n screenshot ?? undefined,\n );\n setResult(res);\n setStatus(\"success\");\n\n const events = getReplayEvents();\n if (events.length > 0) {\n submitReplay(serverUrl, projectKey, res.id, events).catch(() => {});\n }\n } catch (err) {\n setErrorMsg(err instanceof Error ? err.message : t(\"errorLabel\"));\n setStatus(\"error\");\n }\n };\n\n // ── Shared style tokens ────────────────────────────────────────────────────\n const inputBorder = isDark ? \"rgba(255,255,255,0.1)\" : \"rgba(0,0,0,0.1)\";\n const accentGlow = `0 0 20px ${colors.accent}40, 0 4px 16px rgba(0,0,0,0.2)`;\n\n const overlayStyle: React.CSSProperties = {\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.5)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex,\n padding: \"16px\",\n backdropFilter: \"blur(10px)\",\n WebkitBackdropFilter: \"blur(10px)\",\n animation: \"_flint_overlay_in 0.2s ease\",\n };\n\n const modalStyle: React.CSSProperties = {\n background: colors.background,\n backdropFilter: colors.backdropFilter,\n WebkitBackdropFilter: colors.backdropFilter,\n borderRadius: \"20px\",\n boxShadow: colors.shadow,\n border: `1px solid ${colors.border}`,\n width: \"100%\",\n maxWidth: \"480px\",\n maxHeight: \"92vh\",\n overflowY: \"auto\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n color: colors.text,\n animation: \"_flint_in 0.28s cubic-bezier(0.16, 1, 0.3, 1)\",\n };\n\n const inputStyle: React.CSSProperties = {\n width: \"100%\",\n padding: \"11px 13px\",\n borderRadius: \"10px\",\n border: `1px solid ${inputBorder}`,\n background: colors.backgroundSecondary,\n color: colors.text,\n fontSize: \"14px\",\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"inherit\",\n transition: \"border-color 0.15s\",\n };\n\n // ── Loading + Success (unified animated state) ────────────────────────────\n if (status === \"submitting\" || status === \"success\") {\n const isSuccess = status === \"success\";\n const ringBorder = isSuccess\n ? \"3px solid #22c55e\"\n : `3px solid ${isDark ? \"rgba(255,255,255,0.08)\" : \"rgba(0,0,0,0.08)\"}`;\n const ringTopColor = isSuccess ? \"#22c55e\" : colors.accent;\n\n return (\n <div style={overlayStyle}>\n <div style={modalStyle} role=\"dialog\" aria-modal=\"true\" aria-label={isSuccess ? t(\"successTitle\") : t(\"sending\")}>\n <ModalHeader colors={colors} inputBorder={inputBorder} showClose={false} onClose={onClose} />\n\n <div style={{ padding: \"40px 32px 48px\", textAlign: \"center\", display: \"flex\", flexDirection: \"column\", alignItems: \"center\" }}>\n {/* Animated rings */}\n <div style={{ position: \"relative\", width: 80, height: 80, marginBottom: 28 }}>\n {/* Ripple 1 — fade out on success */}\n <div style={{\n position: \"absolute\", inset: -10,\n borderRadius: \"50%\",\n border: `1.5px solid ${colors.accent}`,\n animation: \"_flint_ripple 1.8s ease-out infinite\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }} />\n {/* Ripple 2 (delayed) */}\n <div style={{\n position: \"absolute\", inset: -10,\n borderRadius: \"50%\",\n border: `1.5px solid ${colors.accent}`,\n animation: \"_flint_ripple 1.8s ease-out infinite 0.6s\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }} />\n {/* Spinning ring — transitions to solid green on success */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n border: ringBorder,\n borderTopColor: ringTopColor,\n animation: isSuccess ? \"none\" : \"_flint_spin 0.85s linear infinite\",\n transition: \"border-color 0.45s ease, border-top-color 0.45s ease\",\n }} />\n {/* Center: spark fades out, check fades in */}\n <div style={{ position: \"absolute\", inset: 14, borderRadius: \"50%\" }}>\n {/* Spark */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n background: `linear-gradient(135deg, ${colors.accent}30, ${colors.accentHover}50)`,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n animation: isSuccess ? \"none\" : \"_flint_pulse 2s ease-in-out infinite\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.3s ease\",\n }}>\n <SparkIcon color={colors.accent} size={20} />\n </div>\n {/* Checkmark */}\n <div style={{\n position: \"absolute\", inset: 0,\n borderRadius: \"50%\",\n background: \"rgba(34,197,94,0.15)\",\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"scale(1)\" : \"scale(0.65)\",\n transition: \"opacity 0.35s ease 0.2s, transform 0.4s cubic-bezier(0.16,1,0.3,1) 0.2s\",\n }}>\n <CheckIcon size={20} />\n </div>\n </div>\n </div>\n\n {/* Title crossfade */}\n <div style={{ position: \"relative\", height: 26, width: \"100%\", marginBottom: 10 }}>\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n fontSize: 17, fontWeight: 700, color: colors.text, letterSpacing: \"-0.02em\",\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.25s ease\",\n pointerEvents: \"none\",\n }}>\n {t(\"sending\")}\n </div>\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n fontSize: 17, fontWeight: 700, color: colors.text, letterSpacing: \"-0.02em\",\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"translateY(0)\" : \"translateY(6px)\",\n transition: \"opacity 0.35s ease 0.25s, transform 0.35s ease 0.25s\",\n pointerEvents: isSuccess ? \"auto\" : \"none\",\n }}>\n {t(\"successTitle\")}\n </div>\n </div>\n\n {/* Subtitle crossfade */}\n <div style={{ position: \"relative\", minHeight: 76, width: \"100%\" }}>\n {/* Loading subtitle */}\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n gap: 6, color: colors.textMuted, fontSize: 13,\n opacity: isSuccess ? 0 : 1,\n transition: \"opacity 0.2s ease\",\n pointerEvents: \"none\",\n }}>\n <span>{t(\"capturingContext\")}</span>\n <SendingDots color={colors.accent} />\n </div>\n {/* Success subtitle */}\n <div style={{\n position: \"absolute\", inset: 0,\n display: \"flex\", flexDirection: \"column\", alignItems: \"center\", gap: 10,\n opacity: isSuccess ? 1 : 0,\n transform: isSuccess ? \"translateY(0)\" : \"translateY(8px)\",\n transition: \"opacity 0.35s ease 0.35s, transform 0.35s ease 0.35s\",\n pointerEvents: isSuccess ? \"auto\" : \"none\",\n }}>\n <p style={{ fontSize: 13, color: colors.textMuted, margin: 0 }}>\n {result?.isDuplicate ? t(\"successDuplicate\") : result ? `ID: ${result.id}` : \"\"}\n </p>\n {result?.slackMessageUrl && (\n <a\n href={result.slackMessageUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 6,\n padding: \"9px 18px\",\n borderRadius: \"10px\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n textDecoration: \"none\",\n fontSize: \"13px\",\n fontWeight: 600,\n boxShadow: accentGlow,\n }}\n >\n {t(\"successSlack\")} ↗\n </a>\n )}\n <button\n onClick={onClose}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n padding: \"4px 8px\",\n fontFamily: \"inherit\",\n }}\n >\n {t(\"cancel\")}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n // ── Form ──────────────────────────────────────────────────────────────────\n return (\n <div ref={overlayRef} style={overlayStyle} onClick={handleOverlayClick}>\n <div style={modalStyle} role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"flint-modal-title\">\n <ModalHeader\n colors={colors}\n inputBorder={inputBorder}\n showClose\n onClose={onClose}\n titleId=\"flint-modal-title\"\n title={t(\"modalTitle\")}\n />\n\n <form onSubmit={handleSubmit} style={{ padding: \"20px 24px 24px\" }}>\n {/* Severity */}\n <div style={{ marginBottom: 18 }}>\n <FieldLabel colors={colors}>{t(\"severityLabel\")}</FieldLabel>\n <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(4,1fr)\", gap: 8 }}>\n {SEVERITIES.map((sev) => (\n <SeverityButton\n key={sev}\n sev={sev}\n label={t(`severity_${sev}_label`)}\n selected={severity === sev}\n hint={t(`severity_${sev}_hint`)}\n color={SEV_COLOR[sev]}\n accent={colors.accent}\n border={inputBorder}\n bg={colors.backgroundSecondary}\n text={colors.text}\n onClick={() => setSeverity(sev)}\n />\n ))}\n </div>\n </div>\n\n {/* What Is Broken */}\n <div style={{ marginBottom: 14 }}>\n <FieldLabel colors={colors} htmlFor=\"flint-description\">{t(\"whatIsBrokenLabel\")}</FieldLabel>\n <textarea\n id=\"flint-description\"\n style={{ ...inputStyle, resize: \"vertical\", minHeight: 80 }}\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder={t(\"whatIsBrokenPlaceholder\")}\n required\n />\n </div>\n\n {/* Expected Behavior (optional) */}\n <div style={{ marginBottom: 14 }}>\n <FieldLabel colors={colors} htmlFor=\"flint-expected\">{t(\"expectedBehaviorLabel\")}</FieldLabel>\n <textarea\n id=\"flint-expected\"\n style={{ ...inputStyle, resize: \"vertical\", minHeight: 72 }}\n value={expectedBehavior}\n onChange={(e) => setExpectedBehavior(e.target.value)}\n placeholder={t(\"expectedBehaviorPlaceholder\")}\n />\n </div>\n\n {/* Screenshot */}\n <div style={{ marginBottom: 20 }}>\n <FieldLabel colors={colors}>{t(\"screenshotLabel\")}</FieldLabel>\n <label\n htmlFor=\"flint-screenshot\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"10px 13px\",\n borderRadius: 10,\n border: `1px dashed ${inputBorder}`,\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n background: colors.backgroundSecondary,\n }}\n >\n 📎 {screenshot ? screenshot.name : t(\"screenshotPlaceholder\")}\n </label>\n <input\n id=\"flint-screenshot\"\n ref={fileRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={(e) => setScreenshot(e.target.files?.[0] ?? null)}\n />\n </div>\n\n {/* Session replay info */}\n <div style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"9px 12px\",\n borderRadius: 10,\n background: isDark ? \"rgba(255,255,255,0.04)\" : \"rgba(0,77,240,0.04)\",\n border: `1px solid ${isDark ? \"rgba(255,255,255,0.08)\" : \"rgba(0,77,240,0.1)\"}`,\n marginBottom: 16,\n }}>\n <span style={{ fontSize: 14 }}>🎥</span>\n <span style={{ fontSize: 12, color: colors.textMuted, lineHeight: 1.4 }}>\n {t(\"replayInfo\")}\n </span>\n </div>\n\n {/* Error */}\n {status === \"error\" && (\n <div style={{\n padding: \"10px 13px\",\n borderRadius: 10,\n background: \"rgba(239,68,68,0.08)\",\n border: \"1px solid rgba(239,68,68,0.2)\",\n color: \"#f87171\",\n fontSize: 12,\n marginBottom: 16,\n }}>\n ⚠️ {errorMsg || t(\"errorLabel\")}\n </div>\n )}\n\n {/* Submit */}\n <button\n type=\"submit\"\n style={{\n width: \"100%\",\n padding: \"13px 20px\",\n borderRadius: 12,\n border: \"none\",\n background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,\n color: colors.buttonText,\n fontSize: 15,\n fontWeight: 700,\n cursor: \"pointer\",\n letterSpacing: \"-0.01em\",\n boxShadow: accentGlow,\n fontFamily: \"inherit\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 8,\n }}\n >\n <SparkIcon color={colors.buttonText} size={15} />\n {t(\"submitLabel\")}\n </button>\n\n {/* Cancel */}\n <button\n type=\"button\"\n onClick={onClose}\n style={{\n width: \"100%\",\n padding: \"10px\",\n marginTop: 8,\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 13,\n color: colors.textMuted,\n fontFamily: \"inherit\",\n borderRadius: 8,\n }}\n >\n {t(\"cancel\")}\n </button>\n </form>\n </div>\n </div>\n );\n}\n\n// ─── Sub-components ──────────────────────────────────────────────────────────\n\nfunction ModalHeader({\n colors,\n inputBorder,\n showClose,\n onClose,\n titleId,\n title,\n}: {\n colors: ReturnType<typeof resolveTheme>;\n inputBorder: string;\n showClose: boolean;\n onClose: () => void;\n titleId?: string;\n title?: string;\n}) {\n return (\n <div style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n padding: \"16px 20px 14px\",\n borderBottom: `1px solid ${inputBorder}`,\n }}>\n {/* Brand chip */}\n <div style={{\n width: 28, height: 28,\n borderRadius: 8,\n background: `linear-gradient(135deg, ${colors.accent}20, ${colors.accentHover}35)`,\n border: `1px solid ${colors.accent}30`,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n flexShrink: 0,\n }}>\n <SparkIcon color={colors.accent} size={13} />\n </div>\n\n {titleId && title ? (\n <h2 id={titleId} style={{ margin: 0, fontSize: 14, fontWeight: 600, color: colors.text, letterSpacing: \"-0.01em\", flex: 1 }}>\n {title}\n </h2>\n ) : (\n <span style={{ flex: 1, fontSize: 13, fontWeight: 600, color: colors.textMuted }}>Flint</span>\n )}\n\n {showClose && (\n <button\n onClick={onClose}\n aria-label=\"Close\"\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: 4,\n color: colors.textMuted,\n fontSize: 20,\n lineHeight: 1,\n borderRadius: 6,\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n opacity: 0.6,\n fontFamily: \"inherit\",\n }}\n >\n ×\n </button>\n )}\n </div>\n );\n}\n\nfunction FieldLabel({\n children,\n colors,\n htmlFor,\n}: {\n children: React.ReactNode;\n colors: ReturnType<typeof resolveTheme>;\n htmlFor?: string;\n}) {\n return (\n <label\n htmlFor={htmlFor}\n style={{\n display: \"block\",\n fontSize: \"10px\",\n fontWeight: 700,\n color: colors.textMuted,\n marginBottom: 6,\n textTransform: \"uppercase\" as const,\n letterSpacing: \"0.07em\",\n }}\n >\n {children}\n </label>\n );\n}\n\nfunction SendingDots({ color }: { color: string }) {\n return (\n <span style={{ display: \"inline-flex\", gap: 3, alignItems: \"center\" }}>\n {[0, 1, 2].map((i) => (\n <span\n key={i}\n style={{\n width: 4, height: 4,\n borderRadius: \"50%\",\n background: color,\n display: \"inline-block\",\n animation: `_flint_sending_dot 1.4s ease-in-out infinite ${i * 0.2}s`,\n }}\n />\n ))}\n </span>\n );\n}\n\ninterface SevBtnProps {\n sev: Severity;\n label: string;\n selected: boolean;\n hint: string;\n color: string;\n accent: string;\n border: string;\n bg: string;\n text: string;\n onClick: () => void;\n}\n\nfunction SeverityButton({ sev, label, selected, hint, color, accent, border, bg, text, onClick }: SevBtnProps) {\n return (\n <button\n type=\"button\"\n title={hint}\n onClick={onClick}\n style={{\n padding: \"9px 6px 8px\",\n borderRadius: 10,\n border: selected ? `2px solid ${accent}` : `1.5px solid ${border}`,\n background: selected ? `${accent}15` : bg,\n cursor: \"pointer\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: 5,\n transition: \"border-color 0.12s, background 0.12s\",\n fontFamily: \"inherit\",\n }}\n >\n <span style={{ width: 8, height: 8, borderRadius: \"50%\", background: color, display: \"block\" }} />\n <span style={{ fontSize: 11, fontWeight: selected ? 700 : 500, color: selected ? accent : text, letterSpacing: \"0.02em\" }}>\n {sev}\n </span>\n <span style={{ fontSize: 9, color: selected ? accent : text, opacity: 0.6, letterSpacing: \"0.02em\" }}>\n {label}\n </span>\n </button>\n );\n}\n\nfunction SparkIcon({ color = \"currentColor\", size = 14 }: { color?: string; size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n );\n}\n\nfunction CheckIcon({ size = 20 }: { size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#22c55e\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n","import type { ReportPayload, ReportResult } from \"@flint/types\";\nimport { gzipSync } from \"fflate\";\nimport type { eventWithTime } from \"@rrweb/types\";\n\nexport async function submitReport(\n serverUrl: string,\n projectKey: string,\n payload: ReportPayload,\n screenshot?: File,\n): Promise<ReportResult> {\n const url = `${serverUrl.replace(/\\/$/, \"\")}/api/v1/bug-reports`;\n\n let body: BodyInit;\n let headers: Record<string, string> = {\n \"x-project-key\": projectKey,\n };\n\n if (screenshot) {\n const form = new FormData();\n form.append(\"reporterId\", payload.reporterId);\n form.append(\"reporterName\", payload.reporterName);\n form.append(\"description\", payload.description);\n if (payload.expectedBehavior) form.append(\"expectedBehavior\", payload.expectedBehavior);\n if (payload.stepsToReproduce) form.append(\"stepsToReproduce\", JSON.stringify(payload.stepsToReproduce));\n if (payload.externalReplayUrl) form.append(\"externalReplayUrl\", payload.externalReplayUrl);\n if (payload.additionalContext) form.append(\"additionalContext\", payload.additionalContext);\n form.append(\"severity\", payload.severity);\n if (payload.url) form.append(\"url\", payload.url);\n if (payload.meta) form.append(\"meta\", JSON.stringify(payload.meta));\n form.append(\"screenshot\", screenshot);\n body = form;\n } else {\n body = JSON.stringify(payload);\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const res = await fetch(url, { method: \"POST\", headers, body });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: \"Unknown error\" }));\n throw new Error((err as { error?: string }).error ?? `HTTP ${res.status}`);\n }\n\n return res.json() as Promise<ReportResult>;\n}\n\nexport async function submitReplay(\n serverUrl: string,\n projectKey: string,\n reportId: string,\n events: eventWithTime[],\n): Promise<void> {\n const json = JSON.stringify(events);\n const encoded = new TextEncoder().encode(json);\n const compressed = gzipSync(encoded);\n\n const url = `${serverUrl.replace(/\\/$/, \"\")}/api/v1/bug-reports/${reportId}/replay`;\n await fetch(url, {\n method: \"POST\",\n headers: {\n \"x-project-key\": projectKey,\n \"Content-Type\": \"application/octet-stream\",\n },\n body: compressed.buffer as ArrayBuffer,\n });\n}\n","import type { Theme, ThemeOverride } from \"@flint/types\";\n\nexport interface ResolvedTheme {\n background: string;\n backgroundSecondary: string;\n accent: string;\n accentHover: string;\n text: string;\n textMuted: string;\n border: string;\n shadow: string;\n buttonText: string;\n backdropFilter: string;\n}\n\nconst light: ResolvedTheme = {\n background: \"rgba(255,255,255,0.90)\",\n backgroundSecondary: \"rgba(249,250,251,0.75)\",\n accent: \"#2563eb\",\n accentHover: \"#1d4ed8\",\n text: \"#111827\",\n textMuted: \"#6b7280\",\n border: \"rgba(255,255,255,0.9)\",\n shadow:\n \"0 32px 80px rgba(0,0,0,0.18), 0 8px 32px rgba(0,0,0,0.1), 0 0 0 1px rgba(0,0,0,0.04)\",\n buttonText: \"#ffffff\",\n backdropFilter: \"blur(32px) saturate(1.8)\",\n};\n\nconst dark: ResolvedTheme = {\n background: \"rgba(15,20,35,0.88)\",\n backgroundSecondary: \"rgba(5,8,18,0.65)\",\n accent: \"#f97316\",\n accentHover: \"#ea6c0a\",\n text: \"#dde3ef\",\n textMuted: \"#6b7a93\",\n border: \"rgba(255,255,255,0.08)\",\n shadow:\n \"0 24px 60px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04)\",\n buttonText: \"#ffffff\",\n backdropFilter: \"blur(32px) saturate(1.6)\",\n};\n\nexport function resolveTheme(theme: Theme): ResolvedTheme {\n if (theme === \"dark\") return dark;\n if (theme === \"light\") return light;\n // ThemeOverride — merge over light base\n const override = theme as ThemeOverride;\n return {\n ...light,\n background: override.background ?? light.background,\n accent: override.accent ?? light.accent,\n accentHover: override.accent ?? light.accentHover,\n text: override.text ?? light.text,\n border: override.border ?? light.border,\n };\n}\n","import i18next, { createInstance } from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\nimport en from \"./locales/en.json\";\n\nexport const widgetI18n: ReturnType<typeof createInstance> = createInstance();\n\nwidgetI18n.use(initReactI18next).init({\n lng: \"en-US\",\n fallbackLng: \"en-US\",\n resources: { \"en-US\": { translation: en } },\n interpolation: { escapeValue: false },\n initImmediate: false,\n});\n\nexport default widgetI18n;\n","{\n \"buttonLabel\": \"Report bug\",\n \"modalTitle\": \"Report an issue\",\n \"severityLabel\": \"Severity\",\n \"severity_P1_hint\": \"Critical — system down\",\n \"severity_P2_hint\": \"High — core feature broken\",\n \"severity_P3_hint\": \"Medium — noticeable but workable\",\n \"severity_P4_hint\": \"Low — cosmetic or improvement\",\n \"severity_P1_label\": \"Critical\",\n \"severity_P2_label\": \"High\",\n \"severity_P3_label\": \"Medium\",\n \"severity_P4_label\": \"Low\",\n \"whatIsBrokenLabel\": \"What Is Broken\",\n \"whatIsBrokenPlaceholder\": \"1–2 sentences: what is currently happening that should NOT happen.\",\n \"expectedBehaviorLabel\": \"Expected Behavior (optional)\",\n \"expectedBehaviorPlaceholder\": \"Describe exactly what the user should see or receive after the fix.\",\n \"screenshotLabel\": \"Screenshot (optional)\",\n \"screenshotPlaceholder\": \"Click to attach...\",\n \"submitLabel\": \"Submit\",\n \"successTitle\": \"Bug reported!\",\n \"successDuplicate\": \"Looks like a duplicate of an existing bug.\",\n \"successGitHub\": \"View GitHub issue\",\n \"successSlack\": \"View Slack message\",\n \"replayInfo\": \"No need to record your screen — we automatically capture a session replay when you submit.\",\n \"errorLabel\": \"Failed to submit. Please try again.\",\n \"cancel\": \"Cancel\",\n \"sending\": \"Sending report\",\n \"capturingContext\": \"Capturing context\"\n}\n","import type { EnvironmentInfo } from \"@flint/types\";\n\nexport function collectEnvironment(): EnvironmentInfo {\n const ua = navigator.userAgent;\n\n // ── Browser ──────────────────────────────────────────────────────────────\n let browser = \"Unknown\";\n const chromeM = ua.match(/Chrome\\/(\\d+)/);\n const firefoxM = ua.match(/Firefox\\/(\\d+)/);\n const edgeM = ua.match(/Edg\\/(\\d+)/);\n const safariM = ua.match(/Version\\/(\\d+)/);\n const operaM = ua.match(/OPR\\/(\\d+)/);\n\n if (operaM) {\n browser = `Opera ${operaM[1]}`;\n } else if (edgeM) {\n browser = `Edge ${edgeM[1]}`;\n } else if (chromeM && !/Edg|OPR/.test(ua)) {\n browser = `Chrome ${chromeM[1]}`;\n } else if (firefoxM) {\n browser = `Firefox ${firefoxM[1]}`;\n } else if (safariM && /Safari\\//.test(ua)) {\n browser = `Safari ${safariM[1]}`;\n }\n\n // ── OS ────────────────────────────────────────────────────────────────────\n let os = \"Unknown\";\n const macM = ua.match(/Mac OS X (\\d+[._]\\d+)/);\n const winM = ua.match(/Windows NT (\\d+\\.\\d+)/);\n const androidM = ua.match(/Android (\\d+)/);\n const iosM = ua.match(/iPhone OS (\\d+[._]\\d+)/);\n\n if (macM) {\n os = `macOS ${macM[1].replace(\"_\", \".\")}`;\n } else if (winM) {\n const winMap: Record<string, string> = {\n \"10.0\": \"10/11\",\n \"6.3\": \"8.1\",\n \"6.2\": \"8\",\n \"6.1\": \"7\",\n };\n os = `Windows ${winMap[winM[1]] ?? winM[1]}`;\n } else if (androidM) {\n os = `Android ${androidM[1]}`;\n } else if (iosM) {\n os = `iOS ${iosM[1].replace(/_/g, \".\")}`;\n } else if (/Linux/.test(ua)) {\n os = \"Linux\";\n }\n\n return {\n browser,\n os,\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n screen: `${screen.width}x${screen.height}`,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n online: navigator.onLine,\n };\n}\n","import type { ConsoleEntry } from \"@flint/types\";\n\nconst MAX_ENTRIES = 50;\n\nexport interface ConsoleCollector {\n start(): void;\n stop(): void;\n getEntries(): ConsoleEntry[];\n}\n\nexport function createConsoleCollector(): ConsoleCollector {\n const entries: ConsoleEntry[] = [];\n let active = false;\n\n const originals = {\n log: console.log.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n };\n\n let origOnerror: typeof window.onerror = null;\n let origUnhandled: typeof window.onunhandledrejection = null;\n\n function push(level: ConsoleEntry[\"level\"], args: unknown[]) {\n let str: string;\n try {\n str = args\n .map((a) => (typeof a === \"string\" ? a : JSON.stringify(a)))\n .join(\" \");\n } catch {\n str = String(args[0]);\n }\n if (str.length > 500) str = str.slice(0, 500) + \"…\";\n entries.push({ level, args: str, timestamp: Date.now() });\n if (entries.length > MAX_ENTRIES) entries.shift();\n }\n\n return {\n start() {\n if (active) return;\n active = true;\n\n console.log = (...args: unknown[]) => {\n push(\"log\", args);\n originals.log(...args);\n };\n console.warn = (...args: unknown[]) => {\n push(\"warn\", args);\n originals.warn(...args);\n };\n console.error = (...args: unknown[]) => {\n push(\"error\", args);\n originals.error(...args);\n };\n\n origOnerror = window.onerror;\n window.onerror = (msg, src, line, col, err) => {\n push(\"error\", [err?.message ?? String(msg), `${src}:${line}:${col}`]);\n if (typeof origOnerror === \"function\")\n return origOnerror(msg, src, line, col, err);\n return false;\n };\n\n origUnhandled = window.onunhandledrejection;\n window.onunhandledrejection = (event) => {\n const reason =\n event.reason instanceof Error\n ? event.reason.message\n : JSON.stringify(event.reason);\n push(\"error\", [\"UnhandledRejection:\", reason]);\n if (typeof origUnhandled === \"function\")\n origUnhandled.call(window, event);\n };\n },\n\n stop() {\n if (!active) return;\n active = false;\n console.log = originals.log;\n console.warn = originals.warn;\n console.error = originals.error;\n window.onerror = origOnerror;\n window.onunhandledrejection = origUnhandled;\n },\n\n getEntries() {\n return [...entries];\n },\n };\n}\n","import type { NetworkEntry } from \"@flint/types\";\n\nconst MAX_ENTRIES = 20;\n\nexport interface NetworkCollector {\n start(): void;\n stop(): void;\n getEntries(): NetworkEntry[];\n}\n\nfunction truncateUrl(url: string): string {\n try {\n const u = new URL(url, location.href);\n const base = `${u.origin}${u.pathname}`;\n return base.length > 200 ? base.slice(0, 200) + \"…\" : base;\n } catch {\n return url.length > 200 ? url.slice(0, 200) + \"…\" : url;\n }\n}\n\nexport function createNetworkCollector(): NetworkCollector {\n const entries: NetworkEntry[] = [];\n let origFetch: typeof window.fetch | null = null;\n let origXHROpen: typeof XMLHttpRequest.prototype.open | null = null;\n let active = false;\n\n function push(entry: NetworkEntry) {\n entries.push(entry);\n if (entries.length > MAX_ENTRIES) entries.shift();\n }\n\n return {\n start() {\n if (active) return;\n active = true;\n\n // ── Patch fetch ────────────────────────────────────────────────────────\n origFetch = window.fetch;\n window.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const method = ((init?.method ?? \"GET\") as string).toUpperCase();\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : (input as Request).url;\n const startTime = Date.now();\n const res = await origFetch!.call(window, input, init);\n push({\n method,\n url: truncateUrl(url),\n status: res.status,\n duration: Date.now() - startTime,\n timestamp: startTime,\n });\n return res;\n };\n\n // ── Patch XHR ─────────────────────────────────────────────────────────\n origXHROpen = XMLHttpRequest.prototype.open;\n XMLHttpRequest.prototype.open = function (\n method: string,\n url: string | URL,\n async?: boolean,\n username?: string | null,\n password?: string | null,\n ) {\n const startTime = Date.now();\n const urlStr =\n typeof url === \"string\" ? url : (url as URL).href;\n\n this.addEventListener(\"load\", () => {\n push({\n method: method.toUpperCase(),\n url: truncateUrl(urlStr),\n status: this.status,\n duration: Date.now() - startTime,\n timestamp: startTime,\n });\n });\n\n return origXHROpen!.apply(this, [\n method,\n url,\n async ?? true,\n username,\n password,\n ] as Parameters<typeof XMLHttpRequest.prototype.open>);\n };\n },\n\n stop() {\n if (!active) return;\n active = false;\n if (origFetch) window.fetch = origFetch;\n if (origXHROpen) XMLHttpRequest.prototype.open = origXHROpen;\n },\n\n getEntries() {\n return [...entries];\n },\n };\n}\n","import { useSyncExternalStore } from \"react\";\nimport type { FlintUser } from \"@flint/types\";\n\nexport interface FlintState {\n user: FlintUser | undefined;\n sessionReplay: string | (() => string) | undefined;\n}\n\nlet state: FlintState = { user: undefined, sessionReplay: undefined };\nconst listeners = new Set<() => void>();\n\nfunction emit() {\n listeners.forEach((fn) => fn());\n}\n\nfunction subscribeStore(fn: () => void) {\n listeners.add(fn);\n return () => listeners.delete(fn);\n}\n\nfunction getSnapshot(): FlintState {\n return state;\n}\n\nexport function useFlintStore() {\n return useSyncExternalStore(subscribeStore, getSnapshot);\n}\n\nexport const flint = {\n setUser(user: FlintUser | null) {\n state = { ...state, user: user ?? undefined };\n emit();\n },\n setSessionReplay(url: string | (() => string)) {\n state = { ...state, sessionReplay: url };\n emit();\n },\n};\n"],"mappings":"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","names":["useState","useEffect","useRef","useTranslation","MAX_ENTRIES","jsx","jsxs","useEffect","useTranslation","useState","useRef","SparkIcon"]}
|