@triagly/sdk 0.1.2 → 1.3.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 +1 -24
- package/dist/api.d.ts +2 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +95 -131
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +95 -131
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/ui.d.ts.map +1 -1
- package/dist/utils.d.ts +0 -4
- package/dist/utils.d.ts.map +1 -1
- package/package.json +1 -2
package/dist/index.js
CHANGED
|
@@ -51,26 +51,23 @@
|
|
|
51
51
|
// Button orientation
|
|
52
52
|
const orientation = this.config.orientation || 'horizontal';
|
|
53
53
|
button.classList.add(`triagly-orientation-${orientation}`);
|
|
54
|
+
// Speech bubble SVG icon
|
|
55
|
+
const speechBubbleIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" class="triagly-icon"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/></svg>`;
|
|
56
|
+
const largeIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="currentColor" class="triagly-icon"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/></svg>`;
|
|
54
57
|
// Handle button text based on shape
|
|
55
|
-
const fullText = this.config.buttonText || '
|
|
58
|
+
const fullText = this.config.buttonText || 'Feedback';
|
|
56
59
|
if (shape === 'circular') {
|
|
57
|
-
button.innerHTML =
|
|
60
|
+
button.innerHTML = largeIcon;
|
|
58
61
|
button.setAttribute('aria-label', fullText);
|
|
59
62
|
}
|
|
60
63
|
else if (shape === 'expandable') {
|
|
61
|
-
// Expandable starts with
|
|
62
|
-
button.innerHTML =
|
|
64
|
+
// Expandable starts with icon, expands to full text on hover
|
|
65
|
+
button.innerHTML = `<span class="triagly-btn-icon">${largeIcon}</span><span class="triagly-btn-text"> ${this.config.buttonText || 'Feedback'}</span>`;
|
|
63
66
|
button.setAttribute('aria-label', fullText);
|
|
64
|
-
// Store custom text if provided
|
|
65
|
-
if (this.config.buttonText) {
|
|
66
|
-
const textSpan = button.querySelector('.triagly-btn-text');
|
|
67
|
-
if (textSpan) {
|
|
68
|
-
textSpan.textContent = ' ' + this.config.buttonText.replace('🐛', '').trim();
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
67
|
}
|
|
72
68
|
else {
|
|
73
|
-
|
|
69
|
+
// Default: icon + text
|
|
70
|
+
button.innerHTML = `${speechBubbleIcon}<span class="triagly-btn-label">${fullText}</span>`;
|
|
74
71
|
}
|
|
75
72
|
button.onclick = () => this.toggle();
|
|
76
73
|
// Position button
|
|
@@ -136,9 +133,9 @@
|
|
|
136
133
|
this.setupKeyboardEvents();
|
|
137
134
|
// Set up focus trap
|
|
138
135
|
this.setupFocusTrap();
|
|
139
|
-
// Focus on
|
|
140
|
-
const
|
|
141
|
-
|
|
136
|
+
// Focus on description field
|
|
137
|
+
const descInput = this.container?.querySelector('#triagly-description');
|
|
138
|
+
descInput?.focus();
|
|
142
139
|
}, 0);
|
|
143
140
|
}
|
|
144
141
|
/**
|
|
@@ -183,7 +180,7 @@
|
|
|
183
180
|
overlay.className = 'triagly-overlay';
|
|
184
181
|
overlay.setAttribute('role', 'dialog');
|
|
185
182
|
overlay.setAttribute('aria-modal', 'true');
|
|
186
|
-
overlay.setAttribute('aria-
|
|
183
|
+
overlay.setAttribute('aria-label', 'Send feedback');
|
|
187
184
|
overlay.onclick = (e) => {
|
|
188
185
|
if (e.target === overlay)
|
|
189
186
|
this.close('overlay');
|
|
@@ -194,7 +191,6 @@
|
|
|
194
191
|
const header = document.createElement('div');
|
|
195
192
|
header.className = 'triagly-header';
|
|
196
193
|
header.innerHTML = `
|
|
197
|
-
<h3 id="triagly-modal-title">Send Feedback</h3>
|
|
198
194
|
<button type="button" class="triagly-close" aria-label="Close feedback form">×</button>
|
|
199
195
|
`;
|
|
200
196
|
const closeBtn = header.querySelector('.triagly-close');
|
|
@@ -203,16 +199,7 @@
|
|
|
203
199
|
form.className = 'triagly-form';
|
|
204
200
|
form.innerHTML = `
|
|
205
201
|
<div class="triagly-field">
|
|
206
|
-
<label for="triagly-
|
|
207
|
-
<input
|
|
208
|
-
type="text"
|
|
209
|
-
id="triagly-title"
|
|
210
|
-
placeholder="Brief summary of your feedback"
|
|
211
|
-
/>
|
|
212
|
-
</div>
|
|
213
|
-
|
|
214
|
-
<div class="triagly-field">
|
|
215
|
-
<label for="triagly-description">Description *</label>
|
|
202
|
+
<label for="triagly-description">What's on your mind?</label>
|
|
216
203
|
<textarea
|
|
217
204
|
id="triagly-description"
|
|
218
205
|
required
|
|
@@ -221,6 +208,15 @@
|
|
|
221
208
|
></textarea>
|
|
222
209
|
</div>
|
|
223
210
|
|
|
211
|
+
<div class="triagly-field">
|
|
212
|
+
<label for="triagly-name">Name (optional)</label>
|
|
213
|
+
<input
|
|
214
|
+
type="text"
|
|
215
|
+
id="triagly-name"
|
|
216
|
+
placeholder="Your name"
|
|
217
|
+
/>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
224
220
|
<div class="triagly-field">
|
|
225
221
|
<label for="triagly-email">Email (optional)</label>
|
|
226
222
|
<input
|
|
@@ -230,13 +226,6 @@
|
|
|
230
226
|
/>
|
|
231
227
|
</div>
|
|
232
228
|
|
|
233
|
-
<div class="triagly-field triagly-checkbox">
|
|
234
|
-
<label>
|
|
235
|
-
<input type="checkbox" id="triagly-screenshot" checked />
|
|
236
|
-
<span>Include screenshot</span>
|
|
237
|
-
</label>
|
|
238
|
-
</div>
|
|
239
|
-
|
|
240
229
|
${this.config.turnstileSiteKey ? `
|
|
241
230
|
<div class="triagly-field triagly-turnstile">
|
|
242
231
|
<div class="cf-turnstile" data-sitekey="${this.config.turnstileSiteKey}" data-theme="light"></div>
|
|
@@ -260,8 +249,16 @@
|
|
|
260
249
|
e.preventDefault();
|
|
261
250
|
this.handleSubmit(form);
|
|
262
251
|
};
|
|
252
|
+
const footer = document.createElement('div');
|
|
253
|
+
footer.className = 'triagly-footer';
|
|
254
|
+
footer.innerHTML = `
|
|
255
|
+
<a href="https://triagly.com" target="_blank" rel="noopener noreferrer" class="triagly-branding">
|
|
256
|
+
Powered by <strong>Triagly</strong>
|
|
257
|
+
</a>
|
|
258
|
+
`;
|
|
263
259
|
modal.appendChild(header);
|
|
264
260
|
modal.appendChild(form);
|
|
261
|
+
modal.appendChild(footer);
|
|
265
262
|
overlay.appendChild(modal);
|
|
266
263
|
// Render Turnstile widget if available
|
|
267
264
|
if (this.config.turnstileSiteKey) {
|
|
@@ -303,17 +300,16 @@
|
|
|
303
300
|
turnstileContainer.setAttribute('data-widget-id', widgetId);
|
|
304
301
|
}
|
|
305
302
|
catch (error) {
|
|
306
|
-
console.error('Triagly: Failed to render Turnstile widget:', error);
|
|
303
|
+
console.error('Triagly: Failed to render Turnstile widget:', error instanceof Error ? error.message : 'Unknown error');
|
|
307
304
|
}
|
|
308
305
|
}
|
|
309
306
|
/**
|
|
310
307
|
* Handle form submission
|
|
311
308
|
*/
|
|
312
309
|
async handleSubmit(form) {
|
|
313
|
-
const titleInput = form.querySelector('#triagly-title');
|
|
314
310
|
const descInput = form.querySelector('#triagly-description');
|
|
311
|
+
const nameInput = form.querySelector('#triagly-name');
|
|
315
312
|
const emailInput = form.querySelector('#triagly-email');
|
|
316
|
-
const screenshotCheckbox = form.querySelector('#triagly-screenshot');
|
|
317
313
|
const statusDiv = form.querySelector('#triagly-status');
|
|
318
314
|
const submitBtn = form.querySelector('button[type="submit"]');
|
|
319
315
|
const turnstileContainer = form.querySelector('.cf-turnstile');
|
|
@@ -327,10 +323,9 @@
|
|
|
327
323
|
turnstileToken = turnstileContainer.getAttribute('data-turnstile-response') || undefined;
|
|
328
324
|
}
|
|
329
325
|
const data = {
|
|
330
|
-
title: titleInput.value.trim() || undefined,
|
|
331
326
|
description: descInput.value.trim(),
|
|
327
|
+
reporterName: nameInput.value.trim() || undefined,
|
|
332
328
|
reporterEmail: emailInput.value.trim() || undefined,
|
|
333
|
-
includeScreenshot: screenshotCheckbox.checked,
|
|
334
329
|
turnstileToken,
|
|
335
330
|
};
|
|
336
331
|
// Create a promise that waits for actual submission result
|
|
@@ -394,21 +389,32 @@
|
|
|
394
389
|
position: fixed;
|
|
395
390
|
z-index: 999999;
|
|
396
391
|
padding: 12px 20px;
|
|
397
|
-
background: var(--triagly-button-bg, #
|
|
392
|
+
background: var(--triagly-button-bg, #18181b);
|
|
398
393
|
color: var(--triagly-button-text, #ffffff);
|
|
399
394
|
border: none;
|
|
400
395
|
border-radius: var(--triagly-button-radius, 8px);
|
|
401
396
|
font-size: 14px;
|
|
402
397
|
font-weight: 500;
|
|
403
398
|
cursor: pointer;
|
|
404
|
-
box-shadow: var(--triagly-button-shadow, 0 4px 12px rgba(
|
|
399
|
+
box-shadow: var(--triagly-button-shadow, 0 4px 12px rgba(0, 0, 0, 0.15));
|
|
405
400
|
transition: all 0.2s;
|
|
401
|
+
display: inline-flex;
|
|
402
|
+
align-items: center;
|
|
403
|
+
gap: 8px;
|
|
406
404
|
}
|
|
407
405
|
|
|
408
406
|
.triagly-button:hover {
|
|
409
|
-
background: var(--triagly-button-bg-hover, #
|
|
407
|
+
background: var(--triagly-button-bg-hover, #27272a);
|
|
410
408
|
transform: translateY(-2px);
|
|
411
|
-
box-shadow: var(--triagly-button-shadow-hover, 0 6px 16px rgba(
|
|
409
|
+
box-shadow: var(--triagly-button-shadow-hover, 0 6px 16px rgba(0, 0, 0, 0.2));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.triagly-button .triagly-icon {
|
|
413
|
+
flex-shrink: 0;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.triagly-button .triagly-btn-label {
|
|
417
|
+
line-height: 1;
|
|
412
418
|
}
|
|
413
419
|
|
|
414
420
|
/* Prevent expandable buttons from shifting on hover */
|
|
@@ -502,8 +508,8 @@
|
|
|
502
508
|
min-width: auto;
|
|
503
509
|
padding: 12px 20px;
|
|
504
510
|
border-radius: 30px;
|
|
505
|
-
background: var(--triagly-button-bg-hover, #
|
|
506
|
-
box-shadow: var(--triagly-button-shadow-hover, 0 6px 16px rgba(
|
|
511
|
+
background: var(--triagly-button-bg-hover, #27272a);
|
|
512
|
+
box-shadow: var(--triagly-button-shadow-hover, 0 6px 16px rgba(0, 0, 0, 0.2));
|
|
507
513
|
}
|
|
508
514
|
.triagly-shape-expandable:hover .triagly-btn-text {
|
|
509
515
|
width: auto;
|
|
@@ -562,18 +568,10 @@
|
|
|
562
568
|
|
|
563
569
|
.triagly-header {
|
|
564
570
|
display: flex;
|
|
565
|
-
justify-content:
|
|
571
|
+
justify-content: flex-end;
|
|
566
572
|
align-items: center;
|
|
567
|
-
padding:
|
|
573
|
+
padding: 8px 12px 0;
|
|
568
574
|
background: var(--triagly-header-bg, #ffffff);
|
|
569
|
-
border-bottom: 1px solid var(--triagly-header-border, #e5e7eb);
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
.triagly-header h3 {
|
|
573
|
-
margin: 0;
|
|
574
|
-
font-size: 18px;
|
|
575
|
-
font-weight: 600;
|
|
576
|
-
color: var(--triagly-header-text, #111827);
|
|
577
575
|
}
|
|
578
576
|
|
|
579
577
|
.triagly-close {
|
|
@@ -631,46 +629,21 @@
|
|
|
631
629
|
.triagly-field input:focus,
|
|
632
630
|
.triagly-field textarea:focus {
|
|
633
631
|
outline: none;
|
|
634
|
-
border-color: var(--triagly-input-border-focus, #
|
|
635
|
-
box-shadow: 0 0 0
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
.triagly-checkbox label {
|
|
639
|
-
display: flex;
|
|
640
|
-
align-items: center;
|
|
641
|
-
gap: 8px;
|
|
642
|
-
cursor: pointer;
|
|
643
|
-
font-weight: 400;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
.triagly-checkbox label span {
|
|
647
|
-
user-select: none;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
.triagly-checkbox input {
|
|
651
|
-
width: 16px;
|
|
652
|
-
height: 16px;
|
|
653
|
-
margin: 0;
|
|
654
|
-
cursor: pointer;
|
|
632
|
+
border-color: var(--triagly-input-border-focus, #a1a1aa);
|
|
633
|
+
box-shadow: 0 0 0 2px rgba(161, 161, 170, 0.15);
|
|
655
634
|
}
|
|
656
635
|
|
|
657
636
|
/* Focus visible styles for accessibility */
|
|
658
637
|
.triagly-button:focus-visible,
|
|
659
638
|
.triagly-field input:focus-visible,
|
|
660
639
|
.triagly-field textarea:focus-visible,
|
|
661
|
-
.triagly-checkbox input:focus-visible,
|
|
662
640
|
.triagly-btn-primary:focus-visible,
|
|
663
641
|
.triagly-btn-secondary:focus-visible,
|
|
664
642
|
.triagly-close:focus-visible {
|
|
665
|
-
outline: 2px solid #
|
|
643
|
+
outline: 2px solid #a1a1aa;
|
|
666
644
|
outline-offset: 2px;
|
|
667
645
|
}
|
|
668
646
|
|
|
669
|
-
/* Checkbox label gets visual indicator when checkbox is focused */
|
|
670
|
-
.triagly-checkbox input:focus-visible + span {
|
|
671
|
-
text-decoration: underline;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
647
|
.triagly-turnstile {
|
|
675
648
|
display: flex;
|
|
676
649
|
justify-content: center;
|
|
@@ -696,12 +669,12 @@
|
|
|
696
669
|
}
|
|
697
670
|
|
|
698
671
|
.triagly-btn-primary {
|
|
699
|
-
background: var(--triagly-btn-primary-bg, #
|
|
672
|
+
background: var(--triagly-btn-primary-bg, #18181b);
|
|
700
673
|
color: var(--triagly-btn-primary-text, #ffffff);
|
|
701
674
|
}
|
|
702
675
|
|
|
703
676
|
.triagly-btn-primary:hover:not(:disabled) {
|
|
704
|
-
background: var(--triagly-btn-primary-bg-hover, #
|
|
677
|
+
background: var(--triagly-btn-primary-bg-hover, #27272a);
|
|
705
678
|
}
|
|
706
679
|
|
|
707
680
|
.triagly-btn-primary:disabled {
|
|
@@ -737,6 +710,29 @@
|
|
|
737
710
|
background: var(--triagly-error-bg, #fee2e2);
|
|
738
711
|
color: var(--triagly-error-text, #991b1b);
|
|
739
712
|
}
|
|
713
|
+
|
|
714
|
+
.triagly-footer {
|
|
715
|
+
padding: 12px 24px 16px;
|
|
716
|
+
text-align: right;
|
|
717
|
+
border-top: 1px solid var(--triagly-footer-border, #e5e7eb);
|
|
718
|
+
background: var(--triagly-footer-bg, #f9fafb);
|
|
719
|
+
border-radius: 0 0 var(--triagly-modal-radius, 12px) var(--triagly-modal-radius, 12px);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
.triagly-branding {
|
|
723
|
+
font-size: 12px;
|
|
724
|
+
color: var(--triagly-footer-text, #6b7280);
|
|
725
|
+
text-decoration: none;
|
|
726
|
+
transition: color 0.2s;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
.triagly-branding:hover {
|
|
730
|
+
color: var(--triagly-footer-text-hover, #18181b);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
.triagly-branding strong {
|
|
734
|
+
font-weight: 600;
|
|
735
|
+
}
|
|
740
736
|
`;
|
|
741
737
|
document.head.appendChild(style);
|
|
742
738
|
}
|
|
@@ -824,10 +820,14 @@
|
|
|
824
820
|
}
|
|
825
821
|
|
|
826
822
|
// API Client
|
|
827
|
-
const
|
|
823
|
+
const API_URLS = {
|
|
824
|
+
production: 'https://iipkklhhafrjesryscjh.supabase.co/functions/v1',
|
|
825
|
+
staging: 'https://bssghvinezdawvupcyci.supabase.co/functions/v1',
|
|
826
|
+
};
|
|
828
827
|
class TriaglyAPI {
|
|
829
|
-
constructor(publishableKey, apiUrl, getToken, turnstileSiteKey) {
|
|
830
|
-
|
|
828
|
+
constructor(publishableKey, environment = 'production', apiUrl, getToken, turnstileSiteKey) {
|
|
829
|
+
// apiUrl override takes precedence, then environment-based URL
|
|
830
|
+
this.apiUrl = (apiUrl || API_URLS[environment]).replace(/\/$/, ''); // Remove trailing slash
|
|
831
831
|
this.publishableKey = publishableKey;
|
|
832
832
|
this.getToken = getToken;
|
|
833
833
|
// Always use Triagly's Turnstile site key (can be overridden for testing)
|
|
@@ -865,7 +865,7 @@
|
|
|
865
865
|
}
|
|
866
866
|
}
|
|
867
867
|
catch (error) {
|
|
868
|
-
console.warn('Failed to get Turnstile token:', error);
|
|
868
|
+
console.warn('Failed to get Turnstile token:', error instanceof Error ? error.message : 'Unknown error');
|
|
869
869
|
}
|
|
870
870
|
}
|
|
871
871
|
return null;
|
|
@@ -889,7 +889,7 @@
|
|
|
889
889
|
hardenedToken = await this.getToken();
|
|
890
890
|
}
|
|
891
891
|
catch (error) {
|
|
892
|
-
console.error('Failed to get hardened token:', error);
|
|
892
|
+
console.error('Failed to get hardened token:', error instanceof Error ? error.message : 'Unknown error');
|
|
893
893
|
throw new Error('Failed to authenticate. Please try again.');
|
|
894
894
|
}
|
|
895
895
|
}
|
|
@@ -902,7 +902,6 @@
|
|
|
902
902
|
consoleLogs: data.consoleLogs,
|
|
903
903
|
},
|
|
904
904
|
tags: data.tags,
|
|
905
|
-
screenshot: data.screenshot,
|
|
906
905
|
reporterEmail: data.reporterEmail,
|
|
907
906
|
reporterName: data.reporterName,
|
|
908
907
|
turnstileToken,
|
|
@@ -989,34 +988,6 @@
|
|
|
989
988
|
}
|
|
990
989
|
return browser;
|
|
991
990
|
}
|
|
992
|
-
/**
|
|
993
|
-
* Capture screenshot of current page
|
|
994
|
-
*/
|
|
995
|
-
async function captureScreenshot() {
|
|
996
|
-
try {
|
|
997
|
-
// Use html2canvas library if available
|
|
998
|
-
if (typeof window.html2canvas !== 'undefined') {
|
|
999
|
-
const canvas = await window.html2canvas(document.body, {
|
|
1000
|
-
logging: false,
|
|
1001
|
-
useCORS: true,
|
|
1002
|
-
allowTaint: true,
|
|
1003
|
-
});
|
|
1004
|
-
return canvas.toDataURL('image/png');
|
|
1005
|
-
}
|
|
1006
|
-
// Fallback to native screenshot API if supported (limited browser support)
|
|
1007
|
-
if ('mediaDevices' in navigator && 'getDisplayMedia' in navigator.mediaDevices) {
|
|
1008
|
-
// This requires user interaction and shows a permission dialog
|
|
1009
|
-
// Not ideal for automatic screenshots
|
|
1010
|
-
console.warn('Screenshot capture requires html2canvas library');
|
|
1011
|
-
return null;
|
|
1012
|
-
}
|
|
1013
|
-
return null;
|
|
1014
|
-
}
|
|
1015
|
-
catch (error) {
|
|
1016
|
-
console.error('Screenshot capture failed:', error);
|
|
1017
|
-
return null;
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
991
|
/**
|
|
1021
992
|
* Simple rate limiter using localStorage
|
|
1022
993
|
*/
|
|
@@ -1069,7 +1040,7 @@
|
|
|
1069
1040
|
localStorage.setItem(this.key, JSON.stringify(data));
|
|
1070
1041
|
}
|
|
1071
1042
|
catch (error) {
|
|
1072
|
-
console.error('Failed to store rate limit data:', error);
|
|
1043
|
+
console.error('Failed to store rate limit data:', error instanceof Error ? error.message : 'Unknown error');
|
|
1073
1044
|
}
|
|
1074
1045
|
}
|
|
1075
1046
|
}
|
|
@@ -1174,7 +1145,7 @@
|
|
|
1174
1145
|
}
|
|
1175
1146
|
catch (error) {
|
|
1176
1147
|
// Don't let logging break the app
|
|
1177
|
-
this.originalConsole.error('Failed to capture log:', error);
|
|
1148
|
+
this.originalConsole.error('Failed to capture log:', error instanceof Error ? error.message : 'Unknown error');
|
|
1178
1149
|
}
|
|
1179
1150
|
}
|
|
1180
1151
|
/**
|
|
@@ -1237,7 +1208,7 @@
|
|
|
1237
1208
|
theme: 'auto',
|
|
1238
1209
|
position: 'bottom-right',
|
|
1239
1210
|
buttonShape: 'rounded',
|
|
1240
|
-
buttonText: '
|
|
1211
|
+
buttonText: 'Feedback',
|
|
1241
1212
|
placeholderText: 'Describe what happened...',
|
|
1242
1213
|
successMessage: 'Feedback sent successfully!',
|
|
1243
1214
|
errorMessage: 'Failed to send feedback. Please try again.',
|
|
@@ -1248,7 +1219,7 @@
|
|
|
1248
1219
|
apiKey,
|
|
1249
1220
|
publishableKey: apiKey, // Keep for backward compatibility
|
|
1250
1221
|
};
|
|
1251
|
-
this.api = new TriaglyAPI(apiKey, this.config.apiUrl, this.config.getToken, this.config.turnstileSiteKey);
|
|
1222
|
+
this.api = new TriaglyAPI(apiKey, this.config.environment || 'production', this.config.apiUrl, this.config.getToken, this.config.turnstileSiteKey);
|
|
1252
1223
|
// Always pass Turnstile site key to widget (from API which has default)
|
|
1253
1224
|
this.config.turnstileSiteKey = this.api.getTurnstileSiteKey();
|
|
1254
1225
|
this.widget = new FeedbackWidget(this.config);
|
|
@@ -1292,17 +1263,11 @@
|
|
|
1292
1263
|
}
|
|
1293
1264
|
// Collect metadata
|
|
1294
1265
|
const metadata = collectMetadata(this.config.metadata);
|
|
1295
|
-
// Capture screenshot if requested
|
|
1296
|
-
let screenshot = null;
|
|
1297
|
-
if (data.includeScreenshot) {
|
|
1298
|
-
screenshot = await captureScreenshot();
|
|
1299
|
-
}
|
|
1300
1266
|
// Prepare feedback data
|
|
1301
1267
|
const feedbackData = {
|
|
1302
1268
|
title: data.title,
|
|
1303
1269
|
description: data.description,
|
|
1304
1270
|
reporterEmail: data.reporterEmail,
|
|
1305
|
-
screenshot: screenshot || undefined,
|
|
1306
1271
|
consoleLogs: this.consoleLogger?.getLogs(),
|
|
1307
1272
|
};
|
|
1308
1273
|
// Submit to API with Turnstile token if provided
|
|
@@ -1317,10 +1282,9 @@
|
|
|
1317
1282
|
if (this.config.onSuccess) {
|
|
1318
1283
|
this.config.onSuccess(response.id);
|
|
1319
1284
|
}
|
|
1320
|
-
console.log('Feedback submitted successfully:', response.id);
|
|
1321
1285
|
}
|
|
1322
1286
|
catch (error) {
|
|
1323
|
-
console.error('Failed to submit feedback:', error);
|
|
1287
|
+
console.error('Failed to submit feedback:', error instanceof Error ? error.message : 'Unknown error');
|
|
1324
1288
|
// Dispatch error event for UI layer
|
|
1325
1289
|
document.dispatchEvent(new CustomEvent('triagly:error', {
|
|
1326
1290
|
detail: error
|