@triagly/sdk 1.4.0-beta.5 → 1.4.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAOjB,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,SAAS,CAAC;AAEnD,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,CAAwB;IACzC,OAAO,CAAC,gBAAgB,CAAC,CAAS;gBAGhC,cAAc,EAAE,MAAM,EACtB,WAAW,GAAE,WAA0B,EACvC,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAChC,gBAAgB,CAAC,EAAE,MAAM;IAU3B;;OAEG;IACH,mBAAmB,IAAI,MAAM,GAAG,SAAS;IAIzC;;OAEG;YACW,iBAAiB;IA4B/B;;OAEG;IACG,cAAc,CAClB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,gBAAgB,EAC1B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,gBAAgB,CAAC;CA2E7B"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAOjB,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,SAAS,CAAC;AAEnD,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,CAAwB;IACzC,OAAO,CAAC,gBAAgB,CAAC,CAAS;gBAGhC,cAAc,EAAE,MAAM,EACtB,WAAW,GAAE,WAA0B,EACvC,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAChC,gBAAgB,CAAC,EAAE,MAAM;IAU3B;;OAEG;IACH,mBAAmB,IAAI,MAAM,GAAG,SAAS;IAIzC;;OAEG;YACW,iBAAiB;IA4B/B;;OAEG;IACG,cAAc,CAClB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,gBAAgB,EAC1B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,gBAAgB,CAAC;CA4E7B"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { TriaglyConfig, FeedbackData } from './types';
1
+ import { TriaglyConfig, TriaglyUser, FeedbackData } from './types';
2
2
  export declare class Triagly {
3
3
  private config;
4
4
  private widget;
5
5
  private api;
6
6
  private rateLimiter;
7
7
  private consoleLogger;
8
+ private submitHandler;
8
9
  constructor(config: TriaglyConfig);
9
10
  /**
10
11
  * Initialize the SDK
@@ -22,6 +23,12 @@ export declare class Triagly {
22
23
  * Programmatically close the feedback widget
23
24
  */
24
25
  close(): void;
26
+ /**
27
+ * Identify the current user. Call this after authentication to attach
28
+ * user context to future feedback submissions. If the widget is open,
29
+ * the form fields will update immediately.
30
+ */
31
+ identify(user: TriaglyUser): void;
25
32
  /**
26
33
  * Submit feedback programmatically without UI
27
34
  * Note: When Turnstile is enabled, you must use the widget UI or provide a token
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,YAAY,EACb,MAAM,SAAS,CAAC;AAKjB,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,aAAa,CAA8B;gBAEvC,MAAM,EAAE,aAAa;IAsDjC;;OAEG;IACH,OAAO,CAAC,IAAI;IAkBZ;;OAEG;YACW,YAAY;IAwD1B;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;OAGG;IACG,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBxE;;OAEG;IACH,OAAO,IAAI,IAAI;CAKhB;AAGD,cAAc,SAAS,CAAC;AAexB,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACb,MAAM,SAAS,CAAC;AAKjB,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,aAAa,CAAqB;gBAE9B,MAAM,EAAE,aAAa;IAyDjC;;OAEG;IACH,OAAO,CAAC,IAAI;IAkBZ;;OAEG;YACW,YAAY;IA0D1B;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAKjC;;;OAGG;IACG,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBxE;;OAEG;IACH,OAAO,IAAI,IAAI;CAKhB;AAGD,cAAc,SAAS,CAAC;AAexB,eAAe,OAAO,CAAC"}
package/dist/index.esm.js CHANGED
@@ -1077,6 +1077,7 @@ class FeedbackWidget {
1077
1077
  type="text"
1078
1078
  id="triagly-name"
1079
1079
  placeholder="Your name"
1080
+ ${this.config.user?.name ? `value="${this.escapeHtml(this.config.user.name)}"` : ''}
1080
1081
  />
1081
1082
  </div>
1082
1083
 
@@ -1086,9 +1087,16 @@ class FeedbackWidget {
1086
1087
  type="email"
1087
1088
  id="triagly-email"
1088
1089
  placeholder="your@email.com"
1090
+ ${this.config.user?.email ? `value="${this.escapeHtml(this.config.user.email)}"` : ''}
1089
1091
  />
1090
1092
  </div>
1091
1093
 
1094
+ ${this.config.user?.email || this.config.user?.name ? `
1095
+ <div class="triagly-identified-user" id="triagly-identified-user">
1096
+ Submitting as ${this.escapeHtml(this.config.user.name || this.config.user.email || '')}
1097
+ </div>
1098
+ ` : ''}
1099
+
1092
1100
  ${this.config.enableScreenshot ? `
1093
1101
  <div class="triagly-field triagly-screenshot-field">
1094
1102
  <label>Screenshot (optional)</label>
@@ -1388,9 +1396,13 @@ class FeedbackWidget {
1388
1396
  document.dispatchEvent(event);
1389
1397
  // Wait for actual submission result
1390
1398
  await submissionPromise;
1391
- // Show success
1399
+ // Show success — personalize if we know the user's name
1392
1400
  statusDiv.className = 'triagly-status triagly-success';
1393
- statusDiv.textContent = this.config.successMessage || 'Feedback sent successfully!';
1401
+ const userName = this.config.user?.name;
1402
+ const firstName = userName ? userName.split(' ')[0] : null;
1403
+ statusDiv.textContent = firstName
1404
+ ? `Thanks, ${firstName}! Your feedback was received.`
1405
+ : (this.config.successMessage || 'Feedback sent successfully!');
1394
1406
  // Close after delay
1395
1407
  setTimeout(() => {
1396
1408
  this.close();
@@ -1888,6 +1900,15 @@ class FeedbackWidget {
1888
1900
  .triagly-spin {
1889
1901
  animation: triagly-spin 1s linear infinite;
1890
1902
  }
1903
+
1904
+ .triagly-identified-user {
1905
+ font-size: 12px;
1906
+ color: var(--triagly-label-text, #6b7280);
1907
+ margin-bottom: 16px;
1908
+ padding: 6px 10px;
1909
+ background: var(--triagly-btn-secondary-bg, #f3f4f6);
1910
+ border-radius: 4px;
1911
+ }
1891
1912
  `;
1892
1913
  document.head.appendChild(style);
1893
1914
  }
@@ -1953,6 +1974,44 @@ class FeedbackWidget {
1953
1974
  document.addEventListener('keydown', handleTab, true);
1954
1975
  this.container._tabHandler = handleTab;
1955
1976
  }
1977
+ /**
1978
+ * Update the identified user. If the widget is currently open, updates
1979
+ * the live form fields and indicator. Otherwise stores for next open.
1980
+ */
1981
+ updateUser(user) {
1982
+ this.config.user = { ...this.config.user, ...user };
1983
+ if (!this.isOpen || !this.container)
1984
+ return;
1985
+ const nameInput = this.container.querySelector('#triagly-name');
1986
+ const emailInput = this.container.querySelector('#triagly-email');
1987
+ const indicator = this.container.querySelector('#triagly-identified-user');
1988
+ if (nameInput && user.name !== undefined) {
1989
+ nameInput.value = user.name;
1990
+ }
1991
+ if (emailInput && user.email !== undefined) {
1992
+ emailInput.value = user.email;
1993
+ }
1994
+ const displayName = this.config.user?.name || this.config.user?.email;
1995
+ if (indicator) {
1996
+ if (displayName) {
1997
+ indicator.textContent = `Submitting as ${displayName}`;
1998
+ indicator.style.display = '';
1999
+ }
2000
+ else {
2001
+ indicator.style.display = 'none';
2002
+ }
2003
+ }
2004
+ }
2005
+ /**
2006
+ * Escape HTML special characters to prevent XSS when injecting into innerHTML
2007
+ */
2008
+ escapeHtml(str) {
2009
+ return str
2010
+ .replace(/&/g, '&amp;')
2011
+ .replace(/"/g, '&quot;')
2012
+ .replace(/</g, '&lt;')
2013
+ .replace(/>/g, '&gt;');
2014
+ }
1956
2015
  /**
1957
2016
  * Destroy the widget
1958
2017
  */
@@ -2069,6 +2128,7 @@ class TriaglyAPI {
2069
2128
  tags: data.tags,
2070
2129
  reporterEmail: data.reporterEmail,
2071
2130
  reporterName: data.reporterName,
2131
+ reporterUserId: data.reporterUserId,
2072
2132
  screenshot: data.screenshot,
2073
2133
  turnstileToken,
2074
2134
  hardenedToken,
@@ -2386,6 +2446,9 @@ class Triagly {
2386
2446
  this.api = new TriaglyAPI(apiKey, this.config.environment || 'production', this.config.apiUrl, this.config.getToken, this.config.turnstileSiteKey);
2387
2447
  this.widget = new FeedbackWidget(this.config);
2388
2448
  this.rateLimiter = new RateLimiter(apiKey, 3, 5 * 60 * 1000);
2449
+ this.submitHandler = (e) => {
2450
+ this.handleSubmit(e.detail);
2451
+ };
2389
2452
  // Initialize console logger if enabled
2390
2453
  if (this.config.captureConsole !== false) {
2391
2454
  this.consoleLogger = new ConsoleLogger(this.config.consoleLogLimit, this.config.consoleLogLevels);
@@ -2407,11 +2470,11 @@ class Triagly {
2407
2470
  // DOM is already ready
2408
2471
  this.widget.init();
2409
2472
  }
2410
- // Listen for form submissions
2411
- document.addEventListener('triagly:submit', (e) => {
2412
- const customEvent = e;
2413
- this.handleSubmit(customEvent.detail);
2414
- });
2473
+ // Remove any previously registered listener before adding a fresh one.
2474
+ // This prevents stacked listeners when the SDK is re-initialized (e.g. React
2475
+ // re-renders) which would cause duplicate submissions.
2476
+ document.removeEventListener('triagly:submit', this.submitHandler);
2477
+ document.addEventListener('triagly:submit', this.submitHandler);
2415
2478
  }
2416
2479
  /**
2417
2480
  * Handle feedback submission
@@ -2425,11 +2488,13 @@ class Triagly {
2425
2488
  }
2426
2489
  // Collect metadata
2427
2490
  const metadata = collectMetadata(this.config.metadata);
2428
- // Prepare feedback data
2491
+ // Prepare feedback data, merging config.user as defaults
2429
2492
  const feedbackData = {
2430
2493
  title: data.title,
2431
2494
  description: data.description,
2432
- reporterEmail: data.reporterEmail,
2495
+ reporterEmail: data.reporterEmail || this.config.user?.email,
2496
+ reporterName: data.reporterName || this.config.user?.name,
2497
+ reporterUserId: this.config.user?.id,
2433
2498
  consoleLogs: this.consoleLogger?.getLogs(),
2434
2499
  screenshot: data.screenshot,
2435
2500
  };
@@ -2471,6 +2536,15 @@ class Triagly {
2471
2536
  close() {
2472
2537
  this.widget.close();
2473
2538
  }
2539
+ /**
2540
+ * Identify the current user. Call this after authentication to attach
2541
+ * user context to future feedback submissions. If the widget is open,
2542
+ * the form fields will update immediately.
2543
+ */
2544
+ identify(user) {
2545
+ this.config.user = { ...this.config.user, ...user };
2546
+ this.widget.updateUser(this.config.user);
2547
+ }
2474
2548
  /**
2475
2549
  * Submit feedback programmatically without UI
2476
2550
  * Note: When Turnstile is enabled, you must use the widget UI or provide a token
@@ -2496,7 +2570,7 @@ class Triagly {
2496
2570
  destroy() {
2497
2571
  this.widget.destroy();
2498
2572
  this.consoleLogger?.stop();
2499
- document.removeEventListener('triagly:submit', () => { });
2573
+ document.removeEventListener('triagly:submit', this.submitHandler);
2500
2574
  }
2501
2575
  }
2502
2576
  // Auto-initialize if config is in window