@koderlabs/tasks-sdk-web-reporter 0.1.1 → 0.1.3

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.d.cts CHANGED
@@ -118,6 +118,25 @@ interface WidgetOptions {
118
118
  exposeGlobal?: boolean;
119
119
  /** Network recording settings. */
120
120
  networkRecording?: NetworkRecordingSettings;
121
+ /**
122
+ * When true (or when the project's `defaultReporterBehavior` is
123
+ * `current_user` from the remote config fetch), the modal refuses
124
+ * submission unless `client.options.user` carries an `id` or `email`.
125
+ * An anonymous click on the FAB renders a "Please sign in" CTA that
126
+ * navigates the user to `loginUrl` (default: `/login?next=<url>`).
127
+ *
128
+ * Set to `false` to override the remote config and always allow
129
+ * anonymous submissions (e.g. a public landing page collecting bug
130
+ * reports from logged-out visitors).
131
+ */
132
+ requireUser?: boolean;
133
+ /**
134
+ * Destination for the "Sign in to report a bug" CTA when `requireUser`
135
+ * is active and no user is set. Receives a `next` query param so the
136
+ * user lands back on the originating page after authenticating.
137
+ * Default: `/login?next=<current pathname+search>`.
138
+ */
139
+ loginUrl?: string;
121
140
  }
122
141
 
123
142
  /**
@@ -328,6 +347,10 @@ declare class WidgetIntegration implements Integration {
328
347
  private _wireRuntime;
329
348
  teardown(): void;
330
349
  show(): void;
350
+ /** True when the client carries a logged-in user (id or email present). */
351
+ private _hasIdentity;
352
+ /** Build a minimal "Please sign in" modal — no form, just a CTA + cancel. */
353
+ private _openLoginPrompt;
331
354
  hide(): void;
332
355
  isVisible(): boolean;
333
356
  capture(mode?: 'fullscreen' | 'advanced'): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -118,6 +118,25 @@ interface WidgetOptions {
118
118
  exposeGlobal?: boolean;
119
119
  /** Network recording settings. */
120
120
  networkRecording?: NetworkRecordingSettings;
121
+ /**
122
+ * When true (or when the project's `defaultReporterBehavior` is
123
+ * `current_user` from the remote config fetch), the modal refuses
124
+ * submission unless `client.options.user` carries an `id` or `email`.
125
+ * An anonymous click on the FAB renders a "Please sign in" CTA that
126
+ * navigates the user to `loginUrl` (default: `/login?next=<url>`).
127
+ *
128
+ * Set to `false` to override the remote config and always allow
129
+ * anonymous submissions (e.g. a public landing page collecting bug
130
+ * reports from logged-out visitors).
131
+ */
132
+ requireUser?: boolean;
133
+ /**
134
+ * Destination for the "Sign in to report a bug" CTA when `requireUser`
135
+ * is active and no user is set. Receives a `next` query param so the
136
+ * user lands back on the originating page after authenticating.
137
+ * Default: `/login?next=<current pathname+search>`.
138
+ */
139
+ loginUrl?: string;
121
140
  }
122
141
 
123
142
  /**
@@ -328,6 +347,10 @@ declare class WidgetIntegration implements Integration {
328
347
  private _wireRuntime;
329
348
  teardown(): void;
330
349
  show(): void;
350
+ /** True when the client carries a logged-in user (id or email present). */
351
+ private _hasIdentity;
352
+ /** Build a minimal "Please sign in" modal — no form, just a CTA + cancel. */
353
+ private _openLoginPrompt;
331
354
  hide(): void;
332
355
  isVisible(): boolean;
333
356
  capture(mode?: 'fullscreen' | 'advanced'): Promise<void>;
package/dist/index.js CHANGED
@@ -1390,6 +1390,9 @@ var WidgetIntegration = class WidgetIntegration2 {
1390
1390
  this.opts.hotkey = false;
1391
1391
  this.opts.autoInject = false;
1392
1392
  }
1393
+ if (init.requireUser === void 0 && typeof cfg.defaultReporterBehavior === "string") {
1394
+ this.opts.requireUser = cfg.defaultReporterBehavior === "current_user";
1395
+ }
1393
1396
  } catch {
1394
1397
  }
1395
1398
  }
@@ -1438,11 +1441,66 @@ var WidgetIntegration = class WidgetIntegration2 {
1438
1441
  if (this._visible) return;
1439
1442
  if (!this.client) return;
1440
1443
  this._visible = true;
1441
- this._openModal();
1444
+ if (this.opts.requireUser && !this._hasIdentity()) {
1445
+ this._openLoginPrompt();
1446
+ } else {
1447
+ this._openModal();
1448
+ }
1442
1449
  this._emit({
1443
1450
  name: "show"
1444
1451
  });
1445
1452
  }
1453
+ /** True when the client carries a logged-in user (id or email present). */
1454
+ _hasIdentity() {
1455
+ const u = this.client?.options.user;
1456
+ return Boolean(u && (u.id || u.email));
1457
+ }
1458
+ /** Build a minimal "Please sign in" modal — no form, just a CTA + cancel. */
1459
+ _openLoginPrompt() {
1460
+ const shell = new ModalShell({
1461
+ onClose: /* @__PURE__ */ __name(() => {
1462
+ this._visible = false;
1463
+ this._emit({
1464
+ name: "hide"
1465
+ });
1466
+ }, "onClose")
1467
+ });
1468
+ this.shell?.destroy();
1469
+ this.shell = shell;
1470
+ const here = typeof window !== "undefined" ? window.location.pathname + window.location.search : "/";
1471
+ const loginUrl = this.opts.loginUrl ?? `/login?next=${encodeURIComponent(here)}`;
1472
+ const wrapper = document.createElement("div");
1473
+ wrapper.style.cssText = "padding:24px;font-family:system-ui,-apple-system,sans-serif;text-align:center;max-width:340px;";
1474
+ wrapper.innerHTML = `
1475
+ <div style="font-size:32px;margin-bottom:8px">\u{1F512}</div>
1476
+ <div style="font-size:18px;font-weight:600;color:#111827;margin-bottom:6px">Sign in to report a bug</div>
1477
+ <div style="font-size:13px;color:#6b7280;margin-bottom:18px;line-height:1.5">This project requires reporters to be signed in so bug reports can be linked to your account.</div>
1478
+ `;
1479
+ const signInBtn = document.createElement("button");
1480
+ signInBtn.type = "button";
1481
+ signInBtn.textContent = "Sign in";
1482
+ signInBtn.style.cssText = "width:100%;padding:10px 16px;background:#2563eb;color:#fff;border:0;border-radius:6px;font-size:14px;font-weight:600;cursor:pointer;margin-bottom:8px;";
1483
+ signInBtn.addEventListener("click", () => {
1484
+ try {
1485
+ window.location.assign(loginUrl);
1486
+ } catch {
1487
+ }
1488
+ });
1489
+ const cancelBtn = document.createElement("button");
1490
+ cancelBtn.type = "button";
1491
+ cancelBtn.textContent = "Cancel";
1492
+ cancelBtn.style.cssText = "width:100%;padding:10px 16px;background:transparent;color:#6b7280;border:1px solid #e5e7eb;border-radius:6px;font-size:14px;cursor:pointer;";
1493
+ cancelBtn.addEventListener("click", () => {
1494
+ shell.close();
1495
+ this._visible = false;
1496
+ this._emit({
1497
+ name: "feedbackdiscarded"
1498
+ });
1499
+ });
1500
+ wrapper.appendChild(signInBtn);
1501
+ wrapper.appendChild(cancelBtn);
1502
+ shell.open(wrapper);
1503
+ }
1446
1504
  hide() {
1447
1505
  if (!this._visible) return;
1448
1506
  this.shell?.close();