@diegotsi/flint-react 0.1.6 → 0.2.0

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 CHANGED
@@ -270,7 +270,7 @@ function FlintModal({
270
270
  boxShadow: colors.shadow,
271
271
  border: `1px solid ${colors.border}`,
272
272
  width: "100%",
273
- maxWidth: "480px",
273
+ maxWidth: "600px",
274
274
  maxHeight: "92vh",
275
275
  overflowY: "auto",
276
276
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
@@ -284,7 +284,7 @@ function FlintModal({
284
284
  border: `1px solid ${inputBorder}`,
285
285
  background: colors.backgroundSecondary,
286
286
  color: colors.text,
287
- fontSize: "14px",
287
+ fontSize: "16px",
288
288
  outline: "none",
289
289
  boxSizing: "border-box",
290
290
  fontFamily: "inherit",
@@ -359,7 +359,7 @@ function FlintModal({
359
359
  display: "flex",
360
360
  alignItems: "center",
361
361
  justifyContent: "center",
362
- fontSize: 17,
362
+ fontSize: 19,
363
363
  fontWeight: 700,
364
364
  color: colors.text,
365
365
  letterSpacing: "-0.02em",
@@ -373,7 +373,7 @@ function FlintModal({
373
373
  display: "flex",
374
374
  alignItems: "center",
375
375
  justifyContent: "center",
376
- fontSize: 17,
376
+ fontSize: 19,
377
377
  fontWeight: 700,
378
378
  color: colors.text,
379
379
  letterSpacing: "-0.02em",
@@ -392,7 +392,7 @@ function FlintModal({
392
392
  justifyContent: "center",
393
393
  gap: 6,
394
394
  color: colors.textMuted,
395
- fontSize: 13,
395
+ fontSize: 15,
396
396
  opacity: isSuccess ? 0 : 1,
397
397
  transition: "opacity 0.2s ease",
398
398
  pointerEvents: "none"
@@ -412,7 +412,7 @@ function FlintModal({
412
412
  transition: "opacity 0.35s ease 0.35s, transform 0.35s ease 0.35s",
413
413
  pointerEvents: isSuccess ? "auto" : "none"
414
414
  }, children: [
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
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 15, color: colors.textMuted, margin: 0 }, children: result?.isDuplicate ? t("successDuplicate") : result ? `ID: ${result.id}` : "" }),
416
416
  result?.slackMessageUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
417
417
  "a",
418
418
  {
@@ -428,7 +428,7 @@ function FlintModal({
428
428
  background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,
429
429
  color: colors.buttonText,
430
430
  textDecoration: "none",
431
- fontSize: "13px",
431
+ fontSize: "15px",
432
432
  fontWeight: 600,
433
433
  boxShadow: accentGlow
434
434
  },
@@ -446,7 +446,7 @@ function FlintModal({
446
446
  background: "none",
447
447
  border: "none",
448
448
  cursor: "pointer",
449
- fontSize: 13,
449
+ fontSize: 15,
450
450
  color: colors.textMuted,
451
451
  padding: "4px 8px",
452
452
  fontFamily: "inherit"
@@ -532,7 +532,7 @@ function FlintModal({
532
532
  borderRadius: 10,
533
533
  border: `1px dashed ${inputBorder}`,
534
534
  cursor: "pointer",
535
- fontSize: 13,
535
+ fontSize: 15,
536
536
  color: colors.textMuted,
537
537
  background: colors.backgroundSecondary
538
538
  },
@@ -564,8 +564,8 @@ function FlintModal({
564
564
  border: `1px solid ${isDark ? "rgba(255,255,255,0.08)" : "rgba(0,77,240,0.1)"}`,
565
565
  marginBottom: 16
566
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") })
567
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 16 }, children: "\u{1F3A5}" }),
568
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 14, color: colors.textMuted, lineHeight: 1.4 }, children: t("replayInfo") })
569
569
  ] }),
570
570
  status === "error" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
571
571
  padding: "10px 13px",
@@ -573,7 +573,7 @@ function FlintModal({
573
573
  background: "rgba(239,68,68,0.08)",
574
574
  border: "1px solid rgba(239,68,68,0.2)",
575
575
  color: "#f87171",
576
- fontSize: 12,
576
+ fontSize: 14,
577
577
  marginBottom: 16
578
578
  }, children: [
579
579
  "\u26A0\uFE0F ",
@@ -590,7 +590,7 @@ function FlintModal({
590
590
  border: "none",
591
591
  background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,
592
592
  color: colors.buttonText,
593
- fontSize: 15,
593
+ fontSize: 17,
594
594
  fontWeight: 700,
595
595
  cursor: "pointer",
596
596
  letterSpacing: "-0.01em",
@@ -619,7 +619,7 @@ function FlintModal({
619
619
  background: "none",
620
620
  border: "none",
621
621
  cursor: "pointer",
622
- fontSize: 13,
622
+ fontSize: 15,
623
623
  color: colors.textMuted,
624
624
  fontFamily: "inherit",
625
625
  borderRadius: 8
@@ -656,7 +656,7 @@ function ModalHeader({
656
656
  justifyContent: "center",
657
657
  flexShrink: 0
658
658
  }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SparkIcon, { color: colors.accent, size: 13 }) }),
659
- titleId && title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { id: titleId, style: { margin: 0, fontSize: 14, fontWeight: 600, color: colors.text, letterSpacing: "-0.01em", flex: 1 }, children: title }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { flex: 1, fontSize: 13, fontWeight: 600, color: colors.textMuted }, children: "Flint" }),
659
+ titleId && title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { id: titleId, style: { margin: 0, fontSize: 16, fontWeight: 600, color: colors.text, letterSpacing: "-0.01em", flex: 1 }, children: title }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { flex: 1, fontSize: 15, fontWeight: 600, color: colors.textMuted }, children: "Flint" }),
660
660
  showClose && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
661
661
  "button",
662
662
  {
@@ -668,7 +668,7 @@ function ModalHeader({
668
668
  cursor: "pointer",
669
669
  padding: 4,
670
670
  color: colors.textMuted,
671
- fontSize: 20,
671
+ fontSize: 22,
672
672
  lineHeight: 1,
673
673
  borderRadius: 6,
674
674
  display: "flex",
@@ -693,7 +693,7 @@ function FieldLabel({
693
693
  htmlFor,
694
694
  style: {
695
695
  display: "block",
696
- fontSize: "10px",
696
+ fontSize: "12px",
697
697
  fontWeight: 700,
698
698
  color: colors.textMuted,
699
699
  marginBottom: 6,
@@ -742,8 +742,8 @@ function SeverityButton({ sev, label, selected, hint, color, accent, border, bg,
742
742
  },
743
743
  children: [
744
744
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { width: 8, height: 8, borderRadius: "50%", background: color, display: "block" } }),
745
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 11, fontWeight: selected ? 700 : 500, color: selected ? accent : text, letterSpacing: "0.02em" }, children: sev }),
746
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 9, color: selected ? accent : text, opacity: 0.6, letterSpacing: "0.02em" }, children: label })
745
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 13, fontWeight: selected ? 700 : 500, color: selected ? accent : text, letterSpacing: "0.02em" }, children: sev }),
746
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 11, color: selected ? accent : text, opacity: 0.6, letterSpacing: "0.02em" }, children: label })
747
747
  ]
748
748
  }
749
749
  );
@@ -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","../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"]}
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: \"600px\",\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: \"16px\",\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: 19, 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: 19, 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: 15,\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: 15, 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: \"15px\",\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: 15,\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: 15,\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: 16 }}>🎥</span>\n <span style={{ fontSize: 14, 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: 14,\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: 17,\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: 15,\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: 16, fontWeight: 600, color: colors.text, letterSpacing: \"-0.01em\", flex: 1 }}>\n {title}\n </h2>\n ) : (\n <span style={{ flex: 1, fontSize: 15, 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: 22,\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: \"12px\",\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: 13, fontWeight: selected ? 700 : 500, color: selected ? accent : text, letterSpacing: \"0.02em\" }}>\n {sev}\n </span>\n <span style={{ fontSize: 11, 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.js CHANGED
@@ -242,7 +242,7 @@ function FlintModal({
242
242
  boxShadow: colors.shadow,
243
243
  border: `1px solid ${colors.border}`,
244
244
  width: "100%",
245
- maxWidth: "480px",
245
+ maxWidth: "600px",
246
246
  maxHeight: "92vh",
247
247
  overflowY: "auto",
248
248
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
@@ -256,7 +256,7 @@ function FlintModal({
256
256
  border: `1px solid ${inputBorder}`,
257
257
  background: colors.backgroundSecondary,
258
258
  color: colors.text,
259
- fontSize: "14px",
259
+ fontSize: "16px",
260
260
  outline: "none",
261
261
  boxSizing: "border-box",
262
262
  fontFamily: "inherit",
@@ -331,7 +331,7 @@ function FlintModal({
331
331
  display: "flex",
332
332
  alignItems: "center",
333
333
  justifyContent: "center",
334
- fontSize: 17,
334
+ fontSize: 19,
335
335
  fontWeight: 700,
336
336
  color: colors.text,
337
337
  letterSpacing: "-0.02em",
@@ -345,7 +345,7 @@ function FlintModal({
345
345
  display: "flex",
346
346
  alignItems: "center",
347
347
  justifyContent: "center",
348
- fontSize: 17,
348
+ fontSize: 19,
349
349
  fontWeight: 700,
350
350
  color: colors.text,
351
351
  letterSpacing: "-0.02em",
@@ -364,7 +364,7 @@ function FlintModal({
364
364
  justifyContent: "center",
365
365
  gap: 6,
366
366
  color: colors.textMuted,
367
- fontSize: 13,
367
+ fontSize: 15,
368
368
  opacity: isSuccess ? 0 : 1,
369
369
  transition: "opacity 0.2s ease",
370
370
  pointerEvents: "none"
@@ -384,7 +384,7 @@ function FlintModal({
384
384
  transition: "opacity 0.35s ease 0.35s, transform 0.35s ease 0.35s",
385
385
  pointerEvents: isSuccess ? "auto" : "none"
386
386
  }, children: [
387
- /* @__PURE__ */ jsx("p", { style: { fontSize: 13, color: colors.textMuted, margin: 0 }, children: result?.isDuplicate ? t("successDuplicate") : result ? `ID: ${result.id}` : "" }),
387
+ /* @__PURE__ */ jsx("p", { style: { fontSize: 15, color: colors.textMuted, margin: 0 }, children: result?.isDuplicate ? t("successDuplicate") : result ? `ID: ${result.id}` : "" }),
388
388
  result?.slackMessageUrl && /* @__PURE__ */ jsxs(
389
389
  "a",
390
390
  {
@@ -400,7 +400,7 @@ function FlintModal({
400
400
  background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,
401
401
  color: colors.buttonText,
402
402
  textDecoration: "none",
403
- fontSize: "13px",
403
+ fontSize: "15px",
404
404
  fontWeight: 600,
405
405
  boxShadow: accentGlow
406
406
  },
@@ -418,7 +418,7 @@ function FlintModal({
418
418
  background: "none",
419
419
  border: "none",
420
420
  cursor: "pointer",
421
- fontSize: 13,
421
+ fontSize: 15,
422
422
  color: colors.textMuted,
423
423
  padding: "4px 8px",
424
424
  fontFamily: "inherit"
@@ -504,7 +504,7 @@ function FlintModal({
504
504
  borderRadius: 10,
505
505
  border: `1px dashed ${inputBorder}`,
506
506
  cursor: "pointer",
507
- fontSize: 13,
507
+ fontSize: 15,
508
508
  color: colors.textMuted,
509
509
  background: colors.backgroundSecondary
510
510
  },
@@ -536,8 +536,8 @@ function FlintModal({
536
536
  border: `1px solid ${isDark ? "rgba(255,255,255,0.08)" : "rgba(0,77,240,0.1)"}`,
537
537
  marginBottom: 16
538
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") })
539
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 16 }, children: "\u{1F3A5}" }),
540
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 14, color: colors.textMuted, lineHeight: 1.4 }, children: t("replayInfo") })
541
541
  ] }),
542
542
  status === "error" && /* @__PURE__ */ jsxs("div", { style: {
543
543
  padding: "10px 13px",
@@ -545,7 +545,7 @@ function FlintModal({
545
545
  background: "rgba(239,68,68,0.08)",
546
546
  border: "1px solid rgba(239,68,68,0.2)",
547
547
  color: "#f87171",
548
- fontSize: 12,
548
+ fontSize: 14,
549
549
  marginBottom: 16
550
550
  }, children: [
551
551
  "\u26A0\uFE0F ",
@@ -562,7 +562,7 @@ function FlintModal({
562
562
  border: "none",
563
563
  background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentHover})`,
564
564
  color: colors.buttonText,
565
- fontSize: 15,
565
+ fontSize: 17,
566
566
  fontWeight: 700,
567
567
  cursor: "pointer",
568
568
  letterSpacing: "-0.01em",
@@ -591,7 +591,7 @@ function FlintModal({
591
591
  background: "none",
592
592
  border: "none",
593
593
  cursor: "pointer",
594
- fontSize: 13,
594
+ fontSize: 15,
595
595
  color: colors.textMuted,
596
596
  fontFamily: "inherit",
597
597
  borderRadius: 8
@@ -628,7 +628,7 @@ function ModalHeader({
628
628
  justifyContent: "center",
629
629
  flexShrink: 0
630
630
  }, children: /* @__PURE__ */ jsx(SparkIcon, { color: colors.accent, size: 13 }) }),
631
- titleId && title ? /* @__PURE__ */ jsx("h2", { id: titleId, style: { margin: 0, fontSize: 14, fontWeight: 600, color: colors.text, letterSpacing: "-0.01em", flex: 1 }, children: title }) : /* @__PURE__ */ jsx("span", { style: { flex: 1, fontSize: 13, fontWeight: 600, color: colors.textMuted }, children: "Flint" }),
631
+ titleId && title ? /* @__PURE__ */ jsx("h2", { id: titleId, style: { margin: 0, fontSize: 16, fontWeight: 600, color: colors.text, letterSpacing: "-0.01em", flex: 1 }, children: title }) : /* @__PURE__ */ jsx("span", { style: { flex: 1, fontSize: 15, fontWeight: 600, color: colors.textMuted }, children: "Flint" }),
632
632
  showClose && /* @__PURE__ */ jsx(
633
633
  "button",
634
634
  {
@@ -640,7 +640,7 @@ function ModalHeader({
640
640
  cursor: "pointer",
641
641
  padding: 4,
642
642
  color: colors.textMuted,
643
- fontSize: 20,
643
+ fontSize: 22,
644
644
  lineHeight: 1,
645
645
  borderRadius: 6,
646
646
  display: "flex",
@@ -665,7 +665,7 @@ function FieldLabel({
665
665
  htmlFor,
666
666
  style: {
667
667
  display: "block",
668
- fontSize: "10px",
668
+ fontSize: "12px",
669
669
  fontWeight: 700,
670
670
  color: colors.textMuted,
671
671
  marginBottom: 6,
@@ -714,8 +714,8 @@ function SeverityButton({ sev, label, selected, hint, color, accent, border, bg,
714
714
  },
715
715
  children: [
716
716
  /* @__PURE__ */ jsx("span", { style: { width: 8, height: 8, borderRadius: "50%", background: color, display: "block" } }),
717
- /* @__PURE__ */ jsx("span", { style: { fontSize: 11, fontWeight: selected ? 700 : 500, color: selected ? accent : text, letterSpacing: "0.02em" }, children: sev }),
718
- /* @__PURE__ */ jsx("span", { style: { fontSize: 9, color: selected ? accent : text, opacity: 0.6, letterSpacing: "0.02em" }, children: label })
717
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: selected ? 700 : 500, color: selected ? accent : text, letterSpacing: "0.02em" }, children: sev }),
718
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 11, color: selected ? accent : text, opacity: 0.6, letterSpacing: "0.02em" }, children: label })
719
719
  ]
720
720
  }
721
721
  );
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","../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"]}
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: \"600px\",\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: \"16px\",\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: 19, 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: 19, 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: 15,\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: 15, 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: \"15px\",\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: 15,\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: 15,\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: 16 }}>🎥</span>\n <span style={{ fontSize: 14, 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: 14,\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: 17,\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: 15,\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: 16, fontWeight: 600, color: colors.text, letterSpacing: \"-0.01em\", flex: 1 }}>\n {title}\n </h2>\n ) : (\n <span style={{ flex: 1, fontSize: 15, 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: 22,\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: \"12px\",\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: 13, fontWeight: selected ? 700 : 500, color: selected ? accent : text, letterSpacing: \"0.02em\" }}>\n {sev}\n </span>\n <span style={{ fontSize: 11, 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegotsi/flint-react",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "description": "Self-contained bug report widget for any React project",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",