glitchgrab 1.58.2 → 1.59.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/README.md CHANGED
@@ -371,6 +371,42 @@ function MyReports() {
371
371
  }
372
372
  ```
373
373
 
374
+ ### Show the conversation on a report
375
+
376
+ Let your user see what the team said on their report and reply — no GitHub account needed. Replies land on the GitHub issue as the Glitchgrab app, with "Commented by: <name>" underneath.
377
+
378
+ ```tsx
379
+ import { useGlitchgrabReportThread } from "glitchgrab";
380
+
381
+ function ReportThread({ reportId }: { reportId: string }) {
382
+ const { report, comments, addComment, isPosting, error } = useGlitchgrabReportThread({
383
+ token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,
384
+ reportId, // from useGlitchgrabReports
385
+ reporterName: session.user.name, // optional, defaults to the name it was filed under
386
+ });
387
+ const [text, setText] = useState("");
388
+
389
+ return (
390
+ <div>
391
+ <h3>{report?.issue?.title} — {report?.issue?.githubState ?? "open"}</h3>
392
+ {comments.map((c, i) => (
393
+ <p key={i}><b>{c.author}</b>: {c.body}</p>
394
+ ))}
395
+ <textarea value={text} onChange={(e) => setText(e.target.value)} />
396
+ <button
397
+ disabled={isPosting || !text.trim()}
398
+ onClick={async () => { if (await addComment(text)) setText(""); }}
399
+ >
400
+ {isPosting ? "Sending…" : "Reply"}
401
+ </button>
402
+ {error && <p>{error}</p>}
403
+ </div>
404
+ );
405
+ }
406
+ ```
407
+
408
+ `addComment` never throws: it resolves `true` once the reply is posted and the thread reloaded, `false` with `error` set otherwise. Without the hook, use `fetchGlitchgrabReportThread` / `postGlitchgrabReportComment` (both throw) with your own data layer.
409
+
374
410
  ### With TanStack Query
375
411
 
376
412
  ```tsx
@@ -715,6 +751,10 @@ hydrateRoot(document, <App />, {
715
751
 
716
752
  Next.js does not expose `hydrateRoot` options, so App Router apps should use the `error.tsx` snippets above.
717
753
 
754
+ ### Hydration errors (React #418 family)
755
+
756
+ Nothing to wire. In production the provider catches React #418/#419/#422/#423/#425 with the **component stack** React built for them (Next.js normally throws it away), the server HTML React replaced, any extension or Translate nodes found in the page, and fetch timing. The issue is labelled `gg:hydration` and its title names the element that mismatched. The same mismatch groups into one issue across pages, browsers and deploys. If your site serves source maps (`productionBrowserSourceMaps: true`), Glitchgrab also maps the stack to your source files, so the issue names the nearest component file too.
757
+
718
758
  ### captureError options
719
759
 
720
760
  ```ts
package/dist/index.d.mts CHANGED
@@ -280,6 +280,82 @@ declare function useGlitchgrabActions({ token, onSuccess, onError, }: {
280
280
  isPending: boolean;
281
281
  error: string | null;
282
282
  };
283
+ interface GlitchgrabComment {
284
+ /** GitHub login. Replies from your users post as the Glitchgrab app, with their name in the body. */
285
+ author: string;
286
+ body: string;
287
+ createdAt: string;
288
+ }
289
+ interface GlitchgrabReportThread {
290
+ id: string;
291
+ status: string;
292
+ rawInput: string | null;
293
+ createdAt: string;
294
+ issue: {
295
+ githubNumber: number;
296
+ githubUrl: string;
297
+ title: string;
298
+ body: string;
299
+ labels: string[];
300
+ severity: string | null;
301
+ /** "open" | "closed", or null when GitHub did not answer. */
302
+ githubState: string | null;
303
+ } | null;
304
+ /** Oldest first. Empty when no issue is linked yet. */
305
+ comments: GlitchgrabComment[];
306
+ }
307
+ /**
308
+ * Fetch one report with its GitHub issue and every comment on it — the team's
309
+ * replies and your user's. Throws on failure; pair it with your own data layer.
310
+ */
311
+ declare function fetchGlitchgrabReportThread({ token, reportId, }: {
312
+ token: string;
313
+ reportId: string;
314
+ }): Promise<GlitchgrabReportThread>;
315
+ /**
316
+ * Post a reply on the report's GitHub issue. It lands as the Glitchgrab app
317
+ * with "Commented by: <name>" underneath, so the team knows who said it.
318
+ * Throws on failure.
319
+ */
320
+ declare function postGlitchgrabReportComment({ token, reportId, message, reporterName, reporterEmail, }: {
321
+ token: string;
322
+ reportId: string;
323
+ message: string;
324
+ /** Defaults to the name the report was filed under. */
325
+ reporterName?: string;
326
+ reporterEmail?: string;
327
+ }): Promise<GlitchgrabComment>;
328
+ /**
329
+ * The conversation on one report: where it stands, what the team said, and a
330
+ * way for your user to reply — without a GitHub account.
331
+ *
332
+ * ```tsx
333
+ * const { report, comments, addComment, isPosting } = useGlitchgrabReportThread({
334
+ * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,
335
+ * reportId,
336
+ * reporterName: session.user.name,
337
+ * });
338
+ * ```
339
+ *
340
+ * Never throws. `addComment` resolves `true` once the reply is on the issue
341
+ * (and the thread has reloaded), `false` with `error` set otherwise.
342
+ */
343
+ declare function useGlitchgrabReportThread({ token, reportId, reporterName, reporterEmail, }: {
344
+ token: string;
345
+ /** `reportId` from `useGlitchgrabReports` or the report submit result. Null waits. */
346
+ reportId: string | null;
347
+ reporterName?: string;
348
+ reporterEmail?: string;
349
+ }): {
350
+ report: GlitchgrabReportThread | null;
351
+ comments: GlitchgrabComment[];
352
+ isLoading: boolean;
353
+ isFetching: boolean;
354
+ isPosting: boolean;
355
+ error: string | null;
356
+ refetch: () => Promise<void>;
357
+ addComment: (message: string) => Promise<boolean>;
358
+ };
283
359
 
284
360
  interface FeedbackQuery {
285
361
  token: string;
@@ -422,4 +498,4 @@ declare function computeSignature(params: {
422
498
  declare function shouldSkipDuplicate(signature: string, windowMs?: number, now?: number): boolean;
423
499
  declare function clearDedupCache(): void;
424
500
 
425
- export { BookDemoButton, BookingDialog, Breadcrumb, BreadcrumbType, CaptureErrorOptions, CapturedContext, DeviceInfo, FeedbackButton, FeedbackButtonProps, FeedbackPayload, type FeedbackQuery, FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, GlitchgrabErrorBoundary, GlitchgrabFeedback, GlitchgrabProvider, GlitchgrabProviderProps, type GlitchgrabReport, GlitchgrabSession, LeadInput, LeadResult, ReportButton, ReportButtonProps, ReportPayload, ReportResult, UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, sanitizeUrl, sendFeedback, sendLead, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReports };
501
+ export { BookDemoButton, BookingDialog, Breadcrumb, BreadcrumbType, CaptureErrorOptions, CapturedContext, DeviceInfo, FeedbackButton, FeedbackButtonProps, FeedbackPayload, type FeedbackQuery, FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, type GlitchgrabComment, GlitchgrabErrorBoundary, GlitchgrabFeedback, GlitchgrabProvider, GlitchgrabProviderProps, type GlitchgrabReport, type GlitchgrabReportThread, GlitchgrabSession, LeadInput, LeadResult, ReportButton, ReportButtonProps, ReportPayload, ReportResult, UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReportThread, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, postGlitchgrabReportComment, sanitizeUrl, sendFeedback, sendLead, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReportThread, useGlitchgrabReports };
package/dist/index.d.ts CHANGED
@@ -280,6 +280,82 @@ declare function useGlitchgrabActions({ token, onSuccess, onError, }: {
280
280
  isPending: boolean;
281
281
  error: string | null;
282
282
  };
283
+ interface GlitchgrabComment {
284
+ /** GitHub login. Replies from your users post as the Glitchgrab app, with their name in the body. */
285
+ author: string;
286
+ body: string;
287
+ createdAt: string;
288
+ }
289
+ interface GlitchgrabReportThread {
290
+ id: string;
291
+ status: string;
292
+ rawInput: string | null;
293
+ createdAt: string;
294
+ issue: {
295
+ githubNumber: number;
296
+ githubUrl: string;
297
+ title: string;
298
+ body: string;
299
+ labels: string[];
300
+ severity: string | null;
301
+ /** "open" | "closed", or null when GitHub did not answer. */
302
+ githubState: string | null;
303
+ } | null;
304
+ /** Oldest first. Empty when no issue is linked yet. */
305
+ comments: GlitchgrabComment[];
306
+ }
307
+ /**
308
+ * Fetch one report with its GitHub issue and every comment on it — the team's
309
+ * replies and your user's. Throws on failure; pair it with your own data layer.
310
+ */
311
+ declare function fetchGlitchgrabReportThread({ token, reportId, }: {
312
+ token: string;
313
+ reportId: string;
314
+ }): Promise<GlitchgrabReportThread>;
315
+ /**
316
+ * Post a reply on the report's GitHub issue. It lands as the Glitchgrab app
317
+ * with "Commented by: <name>" underneath, so the team knows who said it.
318
+ * Throws on failure.
319
+ */
320
+ declare function postGlitchgrabReportComment({ token, reportId, message, reporterName, reporterEmail, }: {
321
+ token: string;
322
+ reportId: string;
323
+ message: string;
324
+ /** Defaults to the name the report was filed under. */
325
+ reporterName?: string;
326
+ reporterEmail?: string;
327
+ }): Promise<GlitchgrabComment>;
328
+ /**
329
+ * The conversation on one report: where it stands, what the team said, and a
330
+ * way for your user to reply — without a GitHub account.
331
+ *
332
+ * ```tsx
333
+ * const { report, comments, addComment, isPosting } = useGlitchgrabReportThread({
334
+ * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,
335
+ * reportId,
336
+ * reporterName: session.user.name,
337
+ * });
338
+ * ```
339
+ *
340
+ * Never throws. `addComment` resolves `true` once the reply is on the issue
341
+ * (and the thread has reloaded), `false` with `error` set otherwise.
342
+ */
343
+ declare function useGlitchgrabReportThread({ token, reportId, reporterName, reporterEmail, }: {
344
+ token: string;
345
+ /** `reportId` from `useGlitchgrabReports` or the report submit result. Null waits. */
346
+ reportId: string | null;
347
+ reporterName?: string;
348
+ reporterEmail?: string;
349
+ }): {
350
+ report: GlitchgrabReportThread | null;
351
+ comments: GlitchgrabComment[];
352
+ isLoading: boolean;
353
+ isFetching: boolean;
354
+ isPosting: boolean;
355
+ error: string | null;
356
+ refetch: () => Promise<void>;
357
+ addComment: (message: string) => Promise<boolean>;
358
+ };
283
359
 
284
360
  interface FeedbackQuery {
285
361
  token: string;
@@ -422,4 +498,4 @@ declare function computeSignature(params: {
422
498
  declare function shouldSkipDuplicate(signature: string, windowMs?: number, now?: number): boolean;
423
499
  declare function clearDedupCache(): void;
424
500
 
425
- export { BookDemoButton, BookingDialog, Breadcrumb, BreadcrumbType, CaptureErrorOptions, CapturedContext, DeviceInfo, FeedbackButton, FeedbackButtonProps, FeedbackPayload, type FeedbackQuery, FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, GlitchgrabErrorBoundary, GlitchgrabFeedback, GlitchgrabProvider, GlitchgrabProviderProps, type GlitchgrabReport, GlitchgrabSession, LeadInput, LeadResult, ReportButton, ReportButtonProps, ReportPayload, ReportResult, UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, sanitizeUrl, sendFeedback, sendLead, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReports };
501
+ export { BookDemoButton, BookingDialog, Breadcrumb, BreadcrumbType, CaptureErrorOptions, CapturedContext, DeviceInfo, FeedbackButton, FeedbackButtonProps, FeedbackPayload, type FeedbackQuery, FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, type GlitchgrabComment, GlitchgrabErrorBoundary, GlitchgrabFeedback, GlitchgrabProvider, GlitchgrabProviderProps, type GlitchgrabReport, type GlitchgrabReportThread, GlitchgrabSession, LeadInput, LeadResult, ReportButton, ReportButtonProps, ReportPayload, ReportResult, UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReportThread, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, postGlitchgrabReportComment, sanitizeUrl, sendFeedback, sendLead, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReportThread, useGlitchgrabReports };