@uxbertlabs/reportly 1.0.18 → 1.0.19
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/features/n8n-integration.d.ts +8 -4
- package/dist/features/n8n-integration.d.ts.map +1 -1
- package/dist/reportly.cjs.js +140 -123
- package/dist/reportly.cjs.js.map +1 -1
- package/dist/reportly.esm.js +140 -123
- package/dist/reportly.esm.js.map +1 -1
- package/dist/reportly.js +140 -123
- package/dist/reportly.js.map +1 -1
- package/dist/reportly.min.js +2 -2
- package/dist/reportly.min.js.map +1 -1
- package/dist/ui/modal.d.ts +3 -3
- package/dist/ui/modal.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/reportly.js
CHANGED
@@ -185,11 +185,11 @@ var Reportly = (function () {
|
|
185
185
|
}
|
186
186
|
create() {
|
187
187
|
// Create overlay
|
188
|
-
this.overlay = document.createElement(
|
189
|
-
this.overlay.className =
|
188
|
+
this.overlay = document.createElement("div");
|
189
|
+
this.overlay.className = "uxbert-overlay";
|
190
190
|
// Create modal
|
191
|
-
this.modal = document.createElement(
|
192
|
-
this.modal.className =
|
191
|
+
this.modal = document.createElement("div");
|
192
|
+
this.modal.className = "uxbert-modal";
|
193
193
|
// Modal HTML
|
194
194
|
this.modal.innerHTML = `
|
195
195
|
<div class="uxbert-modal-header">
|
@@ -234,12 +234,13 @@ var Reportly = (function () {
|
|
234
234
|
|
235
235
|
<div class="uxbert-form-group">
|
236
236
|
<label class="uxbert-form-label" for="uxbert-priority">Priority</label>
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
</
|
237
|
+
<select id="uxbert-priority" class="uxbert-form-select">
|
238
|
+
<option value="5" selected>Lowest</option>
|
239
|
+
<option value="4">Low</option>
|
240
|
+
<option value="3" selected>Medium</option>
|
241
|
+
<option value="2">High</option>
|
242
|
+
<option value="1">Highest</option>
|
243
|
+
</select>
|
243
244
|
</div>
|
244
245
|
|
245
246
|
<div class="uxbert-capture-action" id="uxbert-capture-action">
|
@@ -283,67 +284,67 @@ var Reportly = (function () {
|
|
283
284
|
if (!this.modal)
|
284
285
|
return;
|
285
286
|
// Close button
|
286
|
-
const closeBtn = this.modal.querySelector(
|
287
|
-
closeBtn.addEventListener(
|
287
|
+
const closeBtn = this.modal.querySelector(".uxbert-modal-close");
|
288
|
+
closeBtn.addEventListener("click", () => this.close());
|
288
289
|
// Cancel button
|
289
|
-
const cancelBtn = this.modal.querySelector(
|
290
|
-
cancelBtn.addEventListener(
|
290
|
+
const cancelBtn = this.modal.querySelector("#uxbert-cancel-btn");
|
291
|
+
cancelBtn.addEventListener("click", () => this.close());
|
291
292
|
// Overlay click to close
|
292
|
-
this.overlay?.addEventListener(
|
293
|
+
this.overlay?.addEventListener("click", (e) => {
|
293
294
|
if (e.target === this.overlay) {
|
294
295
|
this.close();
|
295
296
|
}
|
296
297
|
});
|
297
298
|
// Form submit
|
298
|
-
const form = this.modal.querySelector(
|
299
|
-
form.addEventListener(
|
299
|
+
const form = this.modal.querySelector("#uxbert-issue-form");
|
300
|
+
form.addEventListener("submit", (e) => {
|
300
301
|
e.preventDefault();
|
301
302
|
this.handleSubmit();
|
302
303
|
});
|
303
304
|
// Capture button
|
304
|
-
const captureBtn = this.modal.querySelector(
|
305
|
-
captureBtn.addEventListener(
|
305
|
+
const captureBtn = this.modal.querySelector("#uxbert-capture-btn");
|
306
|
+
captureBtn.addEventListener("click", () => {
|
306
307
|
if (this.callbacks.onCapture) {
|
307
308
|
this.callbacks.onCapture();
|
308
309
|
}
|
309
310
|
});
|
310
311
|
// Annotate button
|
311
|
-
const annotateBtn = this.modal.querySelector(
|
312
|
-
annotateBtn.addEventListener(
|
312
|
+
const annotateBtn = this.modal.querySelector("#uxbert-annotate-btn");
|
313
|
+
annotateBtn.addEventListener("click", () => {
|
313
314
|
if (this.callbacks.onAnnotate) {
|
314
315
|
this.callbacks.onAnnotate();
|
315
316
|
}
|
316
317
|
});
|
317
318
|
// Retake button
|
318
|
-
const retakeBtn = this.modal.querySelector(
|
319
|
-
retakeBtn.addEventListener(
|
319
|
+
const retakeBtn = this.modal.querySelector("#uxbert-retake-btn");
|
320
|
+
retakeBtn.addEventListener("click", () => {
|
320
321
|
if (this.callbacks.onRetake) {
|
321
322
|
this.callbacks.onRetake();
|
322
323
|
}
|
323
324
|
});
|
324
325
|
// n8n button
|
325
|
-
const n8nBtn = this.modal.querySelector(
|
326
|
-
n8nBtn.addEventListener(
|
326
|
+
const n8nBtn = this.modal.querySelector("#uxbert-n8n-btn");
|
327
|
+
n8nBtn.addEventListener("click", () => {
|
327
328
|
this.handleN8nSubmit();
|
328
329
|
});
|
329
330
|
}
|
330
331
|
handleN8nSubmit() {
|
331
332
|
if (!this.modal)
|
332
333
|
return;
|
333
|
-
const titleInput = this.modal.querySelector(
|
334
|
-
const descriptionInput = this.modal.querySelector(
|
335
|
-
const prioritySelect = this.modal.querySelector(
|
334
|
+
const titleInput = this.modal.querySelector("#uxbert-title");
|
335
|
+
const descriptionInput = this.modal.querySelector("#uxbert-description");
|
336
|
+
const prioritySelect = this.modal.querySelector("#uxbert-priority");
|
336
337
|
const title = titleInput.value;
|
337
338
|
const description = descriptionInput.value;
|
338
339
|
const priority = prioritySelect.value;
|
339
340
|
if (!title.trim()) {
|
340
|
-
alert(
|
341
|
+
alert("Please enter an issue title");
|
341
342
|
return;
|
342
343
|
}
|
343
344
|
const issueData = {
|
344
345
|
title: title.trim(),
|
345
346
|
description: description.trim(),
|
346
|
-
priority
|
347
|
+
priority,
|
347
348
|
};
|
348
349
|
if (this.callbacks.onSendToN8n) {
|
349
350
|
this.callbacks.onSendToN8n(issueData);
|
@@ -352,30 +353,34 @@ var Reportly = (function () {
|
|
352
353
|
handleSubmit() {
|
353
354
|
if (!this.modal)
|
354
355
|
return;
|
355
|
-
const titleInput = this.modal.querySelector(
|
356
|
-
const descriptionInput = this.modal.querySelector(
|
357
|
-
const prioritySelect = this.modal.querySelector(
|
356
|
+
const titleInput = this.modal.querySelector("#uxbert-title");
|
357
|
+
const descriptionInput = this.modal.querySelector("#uxbert-description");
|
358
|
+
const prioritySelect = this.modal.querySelector("#uxbert-priority");
|
358
359
|
const title = titleInput.value;
|
359
360
|
const description = descriptionInput.value;
|
360
361
|
const priority = prioritySelect.value;
|
361
362
|
if (!title.trim()) {
|
362
|
-
alert(
|
363
|
+
alert("Please enter an issue title");
|
363
364
|
return;
|
364
365
|
}
|
365
366
|
const issueData = {
|
366
367
|
title: title.trim(),
|
367
368
|
description: description.trim(),
|
368
|
-
priority
|
369
|
+
priority,
|
369
370
|
};
|
370
371
|
if (this.callbacks.onSubmit) {
|
371
372
|
this.callbacks.onSubmit(issueData);
|
372
373
|
}
|
373
374
|
}
|
374
375
|
open() {
|
375
|
-
this.overlay?.classList.add(
|
376
|
+
this.overlay?.classList.add("active");
|
377
|
+
// Prevent body scroll when modal is open
|
378
|
+
document.body.style.overflow = "hidden";
|
376
379
|
}
|
377
380
|
close() {
|
378
|
-
this.overlay?.classList.remove(
|
381
|
+
this.overlay?.classList.remove("active");
|
382
|
+
// Restore body scroll when modal is closed
|
383
|
+
document.body.style.overflow = "";
|
379
384
|
this.reset();
|
380
385
|
if (this.callbacks.onClose) {
|
381
386
|
this.callbacks.onClose();
|
@@ -384,47 +389,49 @@ var Reportly = (function () {
|
|
384
389
|
setScreenshot(screenshot) {
|
385
390
|
if (!this.modal)
|
386
391
|
return;
|
387
|
-
const container = this.modal.querySelector(
|
388
|
-
const img = this.modal.querySelector(
|
389
|
-
const captureAction = this.modal.querySelector(
|
390
|
-
const submitBtn = this.modal.querySelector(
|
392
|
+
const container = this.modal.querySelector("#uxbert-screenshot-container");
|
393
|
+
const img = this.modal.querySelector("#uxbert-screenshot-img");
|
394
|
+
const captureAction = this.modal.querySelector("#uxbert-capture-action");
|
395
|
+
const submitBtn = this.modal.querySelector("#uxbert-submit-btn");
|
391
396
|
if (screenshot) {
|
392
397
|
img.src = screenshot;
|
393
|
-
container.style.display =
|
394
|
-
captureAction.style.display =
|
398
|
+
container.style.display = "block";
|
399
|
+
captureAction.style.display = "none";
|
395
400
|
submitBtn.disabled = false;
|
396
401
|
}
|
397
402
|
else {
|
398
|
-
container.style.display =
|
399
|
-
captureAction.style.display =
|
403
|
+
container.style.display = "none";
|
404
|
+
captureAction.style.display = "block";
|
400
405
|
submitBtn.disabled = true;
|
401
406
|
}
|
402
407
|
}
|
403
408
|
getCaptureMode() {
|
404
409
|
if (!this.modal)
|
405
|
-
return
|
406
|
-
const viewportRadio = this.modal.querySelector(
|
407
|
-
return viewportRadio.checked ?
|
410
|
+
return "viewport";
|
411
|
+
const viewportRadio = this.modal.querySelector("#uxbert-capture-viewport");
|
412
|
+
return viewportRadio.checked ? "viewport" : "fullpage";
|
408
413
|
}
|
409
414
|
setN8nButtonVisible(visible) {
|
410
415
|
if (!this.modal)
|
411
416
|
return;
|
412
|
-
const n8nBtn = this.modal.querySelector(
|
417
|
+
const n8nBtn = this.modal.querySelector("#uxbert-n8n-btn");
|
413
418
|
if (n8nBtn) {
|
414
|
-
n8nBtn.style.display = visible ?
|
419
|
+
n8nBtn.style.display = visible ? "inline-block" : "none";
|
415
420
|
}
|
416
421
|
}
|
417
422
|
reset() {
|
418
423
|
if (!this.modal)
|
419
424
|
return;
|
420
|
-
this.modal.querySelector(
|
421
|
-
this.modal.querySelector(
|
422
|
-
this.modal.querySelector(
|
425
|
+
this.modal.querySelector("#uxbert-title").value = "";
|
426
|
+
this.modal.querySelector("#uxbert-description").value = "";
|
427
|
+
this.modal.querySelector("#uxbert-priority").value = "Medium";
|
423
428
|
this.setScreenshot(null);
|
424
429
|
}
|
425
430
|
destroy() {
|
426
431
|
if (this.overlay && this.overlay.parentNode) {
|
427
432
|
this.overlay.parentNode.removeChild(this.overlay);
|
433
|
+
// Restore body scroll when destroying modal
|
434
|
+
document.body.style.overflow = "";
|
428
435
|
this.overlay = null;
|
429
436
|
this.modal = null;
|
430
437
|
}
|
@@ -10223,24 +10230,23 @@ var Reportly = (function () {
|
|
10223
10230
|
if (!this.config || !this.config.webhookUrl) {
|
10224
10231
|
return {
|
10225
10232
|
success: false,
|
10226
|
-
message:
|
10227
|
-
error:
|
10233
|
+
message: "n8n webhook URL is not configured",
|
10234
|
+
error: "MISSING_CONFIG",
|
10228
10235
|
};
|
10229
10236
|
}
|
10230
10237
|
if (!this.config.enabled) {
|
10231
10238
|
return {
|
10232
10239
|
success: false,
|
10233
|
-
message:
|
10234
|
-
error:
|
10240
|
+
message: "n8n integration is disabled",
|
10241
|
+
error: "DISABLED",
|
10235
10242
|
};
|
10236
10243
|
}
|
10237
10244
|
try {
|
10238
|
-
// Prepare
|
10239
|
-
const
|
10240
|
-
// Setup request headers
|
10245
|
+
// Prepare FormData with binary screenshot
|
10246
|
+
const formData = await this.prepareFormData(issueData);
|
10247
|
+
// Setup request headers (don't set Content-Type - browser will set it with boundary for FormData)
|
10241
10248
|
const headers = {
|
10242
|
-
|
10243
|
-
...this.config.headers
|
10249
|
+
...this.config.headers,
|
10244
10250
|
};
|
10245
10251
|
// Setup timeout
|
10246
10252
|
const timeout = this.config.timeout || 30000; // 30 seconds default
|
@@ -10248,19 +10254,19 @@ var Reportly = (function () {
|
|
10248
10254
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
10249
10255
|
// Send request
|
10250
10256
|
const response = await fetch(this.config.webhookUrl, {
|
10251
|
-
method:
|
10257
|
+
method: "POST",
|
10252
10258
|
headers,
|
10253
|
-
body:
|
10254
|
-
signal: controller.signal
|
10259
|
+
body: formData,
|
10260
|
+
signal: controller.signal,
|
10255
10261
|
});
|
10256
10262
|
clearTimeout(timeoutId);
|
10257
10263
|
// Check response
|
10258
10264
|
if (!response.ok) {
|
10259
|
-
const errorText = await response.text().catch(() =>
|
10265
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
10260
10266
|
return {
|
10261
10267
|
success: false,
|
10262
10268
|
message: `n8n webhook request failed: ${response.status} ${response.statusText}`,
|
10263
|
-
error: errorText
|
10269
|
+
error: errorText,
|
10264
10270
|
};
|
10265
10271
|
}
|
10266
10272
|
// Parse response
|
@@ -10270,76 +10276,87 @@ var Reportly = (function () {
|
|
10270
10276
|
}
|
10271
10277
|
catch (e) {
|
10272
10278
|
// Some webhooks don't return JSON
|
10273
|
-
responseData = { message:
|
10279
|
+
responseData = { message: "Success" };
|
10274
10280
|
}
|
10275
10281
|
return {
|
10276
10282
|
success: true,
|
10277
|
-
message:
|
10278
|
-
workflowId: responseData.workflowId || responseData.executionId
|
10283
|
+
message: "Issue sent to n8n successfully",
|
10284
|
+
workflowId: responseData.workflowId || responseData.executionId,
|
10279
10285
|
};
|
10280
10286
|
}
|
10281
10287
|
catch (error) {
|
10282
10288
|
if (error instanceof Error) {
|
10283
|
-
if (error.name ===
|
10289
|
+
if (error.name === "AbortError") {
|
10284
10290
|
return {
|
10285
10291
|
success: false,
|
10286
|
-
message:
|
10287
|
-
error:
|
10292
|
+
message: "Request to n8n webhook timed out",
|
10293
|
+
error: "TIMEOUT",
|
10288
10294
|
};
|
10289
10295
|
}
|
10290
10296
|
return {
|
10291
10297
|
success: false,
|
10292
10298
|
message: `Failed to send issue to n8n: ${error.message}`,
|
10293
|
-
error: error.message
|
10299
|
+
error: error.message,
|
10294
10300
|
};
|
10295
10301
|
}
|
10296
10302
|
return {
|
10297
10303
|
success: false,
|
10298
|
-
message:
|
10299
|
-
error:
|
10304
|
+
message: "Unknown error occurred while sending to n8n",
|
10305
|
+
error: "UNKNOWN",
|
10300
10306
|
};
|
10301
10307
|
}
|
10302
10308
|
}
|
10303
10309
|
/**
|
10304
|
-
*
|
10305
|
-
* This formats the data in a structure that's easy to work with in n8n
|
10310
|
+
* Convert base64 data URL to Blob
|
10306
10311
|
*/
|
10307
|
-
|
10308
|
-
|
10309
|
-
|
10310
|
-
|
10311
|
-
|
10312
|
-
|
10313
|
-
|
10314
|
-
|
10315
|
-
|
10316
|
-
|
10317
|
-
|
10318
|
-
|
10319
|
-
|
10320
|
-
|
10321
|
-
|
10322
|
-
|
10323
|
-
|
10324
|
-
|
10325
|
-
|
10326
|
-
|
10327
|
-
|
10328
|
-
|
10329
|
-
|
10330
|
-
|
10331
|
-
|
10332
|
-
|
10333
|
-
|
10334
|
-
|
10335
|
-
|
10336
|
-
|
10337
|
-
|
10338
|
-
|
10339
|
-
|
10340
|
-
|
10341
|
-
|
10342
|
-
|
10312
|
+
base64ToBlob(base64Data) {
|
10313
|
+
// Extract the base64 string and mime type
|
10314
|
+
const matches = base64Data.match(/^data:([^;]+);base64,(.+)$/);
|
10315
|
+
if (!matches) {
|
10316
|
+
throw new Error("Invalid base64 data URL");
|
10317
|
+
}
|
10318
|
+
const mimeType = matches[1];
|
10319
|
+
const base64String = matches[2];
|
10320
|
+
// Decode base64
|
10321
|
+
const byteCharacters = atob(base64String);
|
10322
|
+
const byteNumbers = new Array(byteCharacters.length);
|
10323
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
10324
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
10325
|
+
}
|
10326
|
+
const byteArray = new Uint8Array(byteNumbers);
|
10327
|
+
return new Blob([byteArray], { type: mimeType });
|
10328
|
+
}
|
10329
|
+
/**
|
10330
|
+
* Prepare FormData payload for n8n webhook
|
10331
|
+
* This sends the screenshot as a binary file instead of base64 JSON
|
10332
|
+
*/
|
10333
|
+
async prepareFormData(issueData) {
|
10334
|
+
const formData = new FormData();
|
10335
|
+
// Add issue data as JSON string
|
10336
|
+
formData.append("title", issueData.title);
|
10337
|
+
formData.append("description", issueData.description);
|
10338
|
+
formData.append("priority", issueData.priority);
|
10339
|
+
formData.append("createdAt", issueData.createdAt);
|
10340
|
+
// Convert base64 screenshot to binary Blob and add as file
|
10341
|
+
const screenshotBlob = this.base64ToBlob(issueData.screenshot);
|
10342
|
+
const filename = `screenshot-${Date.now()}.png`;
|
10343
|
+
formData.append("screenshot", screenshotBlob, filename);
|
10344
|
+
// Add device info as individual fields
|
10345
|
+
formData.append("browser", issueData.deviceInfo.browser);
|
10346
|
+
formData.append("os", issueData.deviceInfo.os);
|
10347
|
+
formData.append("screenResolution", issueData.deviceInfo.screenResolution);
|
10348
|
+
formData.append("viewport", issueData.deviceInfo.viewport);
|
10349
|
+
formData.append("url", issueData.deviceInfo.url);
|
10350
|
+
formData.append("userAgent", issueData.deviceInfo.userAgent);
|
10351
|
+
formData.append("language", issueData.deviceInfo.language || "");
|
10352
|
+
formData.append("platform", issueData.deviceInfo.platform);
|
10353
|
+
formData.append("cookiesEnabled", String(issueData.deviceInfo.cookiesEnabled));
|
10354
|
+
formData.append("onLine", String(issueData.deviceInfo.onLine));
|
10355
|
+
formData.append("timestamp", issueData.deviceInfo.timestamp);
|
10356
|
+
// Add metadata
|
10357
|
+
formData.append("source", "uxbert-reportly");
|
10358
|
+
formData.append("version", "1.0.0");
|
10359
|
+
return formData;
|
10343
10360
|
}
|
10344
10361
|
/**
|
10345
10362
|
* Test connection to n8n webhook
|
@@ -10348,28 +10365,28 @@ var Reportly = (function () {
|
|
10348
10365
|
if (!this.config || !this.config.webhookUrl) {
|
10349
10366
|
return {
|
10350
10367
|
success: false,
|
10351
|
-
message:
|
10352
|
-
error:
|
10368
|
+
message: "n8n webhook URL is not configured",
|
10369
|
+
error: "MISSING_CONFIG",
|
10353
10370
|
};
|
10354
10371
|
}
|
10355
10372
|
try {
|
10356
10373
|
const controller = new AbortController();
|
10357
10374
|
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout for test
|
10358
10375
|
await fetch(this.config.webhookUrl, {
|
10359
|
-
method:
|
10360
|
-
signal: controller.signal
|
10376
|
+
method: "HEAD",
|
10377
|
+
signal: controller.signal,
|
10361
10378
|
});
|
10362
10379
|
clearTimeout(timeoutId);
|
10363
10380
|
return {
|
10364
10381
|
success: true,
|
10365
|
-
message:
|
10382
|
+
message: "n8n webhook is reachable",
|
10366
10383
|
};
|
10367
10384
|
}
|
10368
10385
|
catch (error) {
|
10369
10386
|
return {
|
10370
10387
|
success: false,
|
10371
|
-
message:
|
10372
|
-
error: error instanceof Error ? error.message :
|
10388
|
+
message: "Failed to reach n8n webhook",
|
10389
|
+
error: error instanceof Error ? error.message : "UNKNOWN",
|
10373
10390
|
};
|
10374
10391
|
}
|
10375
10392
|
}
|
@@ -10386,7 +10403,7 @@ var Reportly = (function () {
|
|
10386
10403
|
if (!this.config) {
|
10387
10404
|
this.config = {
|
10388
10405
|
webhookUrl: url,
|
10389
|
-
enabled: true
|
10406
|
+
enabled: true,
|
10390
10407
|
};
|
10391
10408
|
}
|
10392
10409
|
else {
|
@@ -10552,7 +10569,7 @@ var Reportly = (function () {
|
|
10552
10569
|
}
|
10553
10570
|
}
|
10554
10571
|
|
10555
|
-
var css_248z = ":root{--uxbert-primary:#4f46e5;--uxbert-primary-hover:#4338ca;--uxbert-danger:#ef4444;--uxbert-success:#10b981;--uxbert-bg:#fff;--uxbert-text:#1f2937;--uxbert-border:#e5e7eb;--uxbert-shadow:0 10px 25px rgba(0,0,0,.1);--uxbert-z-button:999999;--uxbert-z-modal:1000000;--uxbert-z-canvas:1000001;--uxbert-z-toolbar:1000002}[data-theme=dark]{--uxbert-bg:#1f2937;--uxbert-text:#f9fafb;--uxbert-border:#374151}.uxbert-fab{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:flex;font-size:24px;height:56px;justify-content:center;position:fixed;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-button)}.uxbert-fab:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-fab.bottom-right{bottom:24px;right:24px}.uxbert-fab.bottom-left{bottom:24px;left:24px}.uxbert-fab.top-right{right:24px;top:24px}.uxbert-fab.top-left{left:24px;top:24px}.uxbert-overlay{align-items:center;animation:fadeIn .3s ease;background:rgba(0,0,0,.5);display:none;height:100%;justify-content:center;left:0;position:fixed;top:0;width:100%;z-index:var(--uxbert-z-modal)}.uxbert-overlay.active{display:flex}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.uxbert-modal{animation:slideUp .3s ease;background:var(--uxbert-bg);border-radius:12px;box-shadow:var(--uxbert-shadow);color:var(--uxbert-text);max-height:90vh;max-width:600px;overflow-y:auto;padding:24px;width:90%}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.uxbert-modal-header{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.uxbert-modal-title{font-size:20px;font-weight:600;margin:0}.uxbert-modal-close{align-items:center;background:none;border:none;border-radius:4px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:24px;height:32px;justify-content:center;padding:0;width:32px}.uxbert-modal-close:hover{background:var(--uxbert-border)}.uxbert-form-group{margin-bottom:16px}.uxbert-form-label{display:block;font-size:14px;font-weight:500;margin-bottom:8px}.uxbert-capture-mode{display:flex;flex-wrap:wrap;gap:12px}.uxbert-radio-label{align-items:center;border:2px solid var(--uxbert-border);border-radius:8px;cursor:pointer;display:flex;flex:1;gap:8px;min-width:140px;padding:10px 16px;transition:all .2s ease}.uxbert-radio-label:hover{background:rgba(79,70,229,.05);border-color:var(--uxbert-primary)}.uxbert-radio-label input[type=radio]{cursor:pointer;height:18px;margin:0;width:18px}.uxbert-radio-label input[type=radio]:checked{accent-color:var(--uxbert-primary)}.uxbert-radio-label:has(input[type=radio]:checked){background:rgba(79,70,229,.1);border-color:var(--uxbert-primary)}.uxbert-radio-label span{flex:1;font-size:14px;font-weight:500}.uxbert-form-input,.uxbert-form-select,.uxbert-form-textarea{background:var(--uxbert-bg);border:1px solid var(--uxbert-border);border-radius:6px;box-sizing:border-box;color:var(--uxbert-text);font-family:inherit;font-size:14px;padding:10px;width:100%}.uxbert-form-textarea{min-height:100px;resize:vertical}.uxbert-form-input:focus,.uxbert-form-select:focus,.uxbert-form-textarea:focus{border-color:var(--uxbert-primary);outline:none}.uxbert-capture-action{margin:16px 0;text-align:center}.uxbert-capture-action .uxbert-btn{min-width:200px}.uxbert-screenshot-preview{border:1px solid var(--uxbert-border);border-radius:8px;margin:16px 0;overflow:hidden}.uxbert-screenshot-preview img{display:block;width:100%}.uxbert-screenshot-actions{background:var(--uxbert-border);display:flex;gap:8px;padding:12px}.uxbert-btn{align-items:center;border:none;border-radius:6px;cursor:pointer;display:inline-flex;font-size:14px;font-weight:500;gap:8px;padding:10px 20px;transition:all .2s ease}.uxbert-btn-primary{background:var(--uxbert-primary);color:#fff}.uxbert-btn-primary:hover{background:var(--uxbert-primary-hover)}.uxbert-btn-secondary{background:var(--uxbert-border);color:var(--uxbert-text)}.uxbert-btn-secondary:hover{background:#d1d5db}.uxbert-btn-success{background:var(--uxbert-success);color:#fff}.uxbert-btn-success:hover{background:#059669}.uxbert-btn-danger{background:var(--uxbert-danger);color:#fff}.uxbert-btn-danger:hover{background:#dc2626}.uxbert-modal-actions{display:flex;gap:12px;justify-content:flex-end;margin-top:20px}.uxbert-toolbar-toggle{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;bottom:24px;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:none;font-size:24px;height:56px;justify-content:center;position:fixed;right:24px;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar-toggle.active{display:flex}.uxbert-toolbar-toggle.hidden{opacity:0;pointer-events:none;transform:scale(.8)}.uxbert-toolbar-toggle:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-toolbar{background:var(--uxbert-bg);border-radius:12px;bottom:24px;box-shadow:var(--uxbert-shadow);display:none;flex-direction:column;gap:8px;max-height:80vh;opacity:0;overflow-y:auto;padding:16px;pointer-events:none;position:fixed;right:24px;transform:translateY(20px);transition:all .3s ease;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar.active{display:flex}.uxbert-toolbar.expanded{opacity:1;pointer-events:all;transform:translateY(0)}.uxbert-toolbar-header{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-bottom:8px}.uxbert-toolbar-title{flex:1;font-size:14px;font-weight:600}.uxbert-toolbar-exit,.uxbert-toolbar-minimize{align-items:center;background:var(--uxbert-border);border:none;border-radius:6px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:20px;font-weight:700;height:32px;justify-content:center;transition:all .2s ease;width:32px}.uxbert-toolbar-exit{background:var(--uxbert-danger);color:#fff}.uxbert-toolbar-minimize:hover{background:#d1d5db;transform:scale(1.1)}.uxbert-toolbar-exit:hover{background:#dc2626;transform:scale(1.1)}.uxbert-toolbar-tools{display:flex;flex-wrap:wrap;gap:8px}.uxbert-tool-btn{align-items:center;background:var(--uxbert-bg);border:2px solid var(--uxbert-border);border-radius:6px;cursor:pointer;display:flex;font-family:Arial,sans-serif;font-size:18px;font-weight:700;height:40px;justify-content:center;transition:all .2s ease;width:40px}.uxbert-tool-btn.active,.uxbert-tool-btn:hover{background:var(--uxbert-primary);border-color:var(--uxbert-primary);color:#fff}.uxbert-color-picker{display:flex;gap:6px;margin:8px 0}.uxbert-color-option{border:2px solid var(--uxbert-border);border-radius:50%;cursor:pointer;height:32px;transition:transform .2s ease;width:32px}.uxbert-color-option:hover{transform:scale(1.1)}.uxbert-color-option.active{border:3px solid var(--uxbert-text)}.uxbert-canvas-overlay{cursor:crosshair;display:none;left:0;position:absolute;top:0;z-index:var(--uxbert-z-canvas)}.uxbert-canvas-overlay.active{display:block}.uxbert-canvas-overlay.viewport-mode{left:0;position:fixed;top:0}.uxbert-text-input{background:hsla(0,0%,100%,.95);border:2px solid var(--uxbert-primary);border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:var(--uxbert-text);font-family:Arial,sans-serif;font-size:16px;font-weight:700;min-width:200px;outline:none;padding:8px 12px;z-index:var(--uxbert-z-toolbar)}.uxbert-text-input:focus{border-color:var(--uxbert-primary-hover);box-shadow:0 4px 16px rgba(79,70,229,.3)}.uxbert-text-input::placeholder{color:#9ca3af;font-weight:400}@media (max-width:768px){.uxbert-modal{max-height:95vh;padding:16px;width:95%}.uxbert-toolbar{bottom:90px;left:16px;max-height:60vh;right:16px;width:auto}.uxbert-toolbar-toggle{bottom:16px;height:56px;right:16px;width:56px}.uxbert-fab{font-size:20px;height:48px;width:48px}.uxbert-color-picker,.uxbert-toolbar-tools{justify-content:center}}";
|
10572
|
+
var css_248z = ":root{--uxbert-primary:#4f46e5;--uxbert-primary-hover:#4338ca;--uxbert-danger:#ef4444;--uxbert-success:#10b981;--uxbert-bg:#fff;--uxbert-text:#1f2937;--uxbert-border:#e5e7eb;--uxbert-shadow:0 10px 25px rgba(0,0,0,.1);--uxbert-z-button:999999;--uxbert-z-modal:1000000;--uxbert-z-canvas:1000001;--uxbert-z-toolbar:1000002}[data-theme=dark]{--uxbert-bg:#1f2937;--uxbert-text:#f9fafb;--uxbert-border:#374151}.uxbert-fab{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:flex;font-size:24px;height:56px;justify-content:center;position:fixed;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-button)}.uxbert-fab:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-fab.bottom-right{bottom:24px;right:24px}.uxbert-fab.bottom-left{bottom:24px;left:24px}.uxbert-fab.top-right{right:24px;top:24px}.uxbert-fab.top-left{left:24px;top:24px}.uxbert-overlay{align-items:center;animation:fadeIn .3s ease;background:rgba(0,0,0,.5);display:none;height:100%;justify-content:center;left:0;overflow:hidden;position:fixed;top:0;width:100%;z-index:var(--uxbert-z-modal)}.uxbert-overlay.active{display:flex}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.uxbert-modal{animation:slideUp .3s ease;background:var(--uxbert-bg);border-radius:12px;box-shadow:var(--uxbert-shadow);color:var(--uxbert-text);max-height:90vh;max-width:600px;overflow-y:auto;padding:24px;width:90%}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.uxbert-modal-header{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.uxbert-modal-title{font-size:20px;font-weight:600;margin:0}.uxbert-modal-close{align-items:center;background:none;border:none;border-radius:4px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:24px;height:32px;justify-content:center;padding:0;width:32px}.uxbert-modal-close:hover{background:var(--uxbert-border)}.uxbert-form-group{margin-bottom:16px}.uxbert-form-label{display:block;font-size:14px;font-weight:500;margin-bottom:8px}.uxbert-capture-mode{display:flex;flex-wrap:wrap;gap:12px}.uxbert-radio-label{align-items:center;border:2px solid var(--uxbert-border);border-radius:8px;cursor:pointer;display:flex;flex:1;gap:8px;min-width:140px;padding:10px 16px;transition:all .2s ease}.uxbert-radio-label:hover{background:rgba(79,70,229,.05);border-color:var(--uxbert-primary)}.uxbert-radio-label input[type=radio]{cursor:pointer;height:18px;margin:0;width:18px}.uxbert-radio-label input[type=radio]:checked{accent-color:var(--uxbert-primary)}.uxbert-radio-label:has(input[type=radio]:checked){background:rgba(79,70,229,.1);border-color:var(--uxbert-primary)}.uxbert-radio-label span{flex:1;font-size:14px;font-weight:500}.uxbert-form-input,.uxbert-form-select,.uxbert-form-textarea{background:var(--uxbert-bg);border:1px solid var(--uxbert-border);border-radius:6px;box-sizing:border-box;color:var(--uxbert-text);font-family:inherit;font-size:14px;padding:10px;width:100%}.uxbert-form-textarea{min-height:100px;resize:vertical}.uxbert-form-input:focus,.uxbert-form-select:focus,.uxbert-form-textarea:focus{border-color:var(--uxbert-primary);outline:none}.uxbert-capture-action{margin:16px 0;text-align:center}.uxbert-capture-action .uxbert-btn{min-width:200px}.uxbert-screenshot-preview{border:1px solid var(--uxbert-border);border-radius:8px;margin:16px 0;overflow:hidden}.uxbert-screenshot-preview img{display:block;width:100%}.uxbert-screenshot-actions{background:var(--uxbert-border);display:flex;gap:8px;padding:12px}.uxbert-btn{align-items:center;border:none;border-radius:6px;cursor:pointer;display:inline-flex;font-size:14px;font-weight:500;gap:8px;padding:10px 20px;transition:all .2s ease}.uxbert-btn-primary{background:var(--uxbert-primary);color:#fff}.uxbert-btn-primary:hover{background:var(--uxbert-primary-hover)}.uxbert-btn-secondary{background:var(--uxbert-border);color:var(--uxbert-text)}.uxbert-btn-secondary:hover{background:#d1d5db}.uxbert-btn-success{background:var(--uxbert-success);color:#fff}.uxbert-btn-success:hover{background:#059669}.uxbert-btn-danger{background:var(--uxbert-danger);color:#fff}.uxbert-btn-danger:hover{background:#dc2626}.uxbert-modal-actions{display:flex;gap:12px;justify-content:flex-end;margin-top:20px}.uxbert-toolbar-toggle{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;bottom:24px;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:none;font-size:24px;height:56px;justify-content:center;position:fixed;right:24px;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar-toggle.active{display:flex}.uxbert-toolbar-toggle.hidden{opacity:0;pointer-events:none;transform:scale(.8)}.uxbert-toolbar-toggle:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-toolbar{background:var(--uxbert-bg);border-radius:12px;bottom:24px;box-shadow:var(--uxbert-shadow);display:none;flex-direction:column;gap:8px;max-height:80vh;opacity:0;overflow-y:auto;padding:16px;pointer-events:none;position:fixed;right:24px;transform:translateY(20px);transition:all .3s ease;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar.active{display:flex}.uxbert-toolbar.expanded{opacity:1;pointer-events:all;transform:translateY(0)}.uxbert-toolbar-header{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-bottom:8px}.uxbert-toolbar-title{flex:1;font-size:14px;font-weight:600}.uxbert-toolbar-exit,.uxbert-toolbar-minimize{align-items:center;background:var(--uxbert-border);border:none;border-radius:6px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:20px;font-weight:700;height:32px;justify-content:center;transition:all .2s ease;width:32px}.uxbert-toolbar-exit{background:var(--uxbert-danger);color:#fff}.uxbert-toolbar-minimize:hover{background:#d1d5db;transform:scale(1.1)}.uxbert-toolbar-exit:hover{background:#dc2626;transform:scale(1.1)}.uxbert-toolbar-tools{display:flex;flex-wrap:wrap;gap:8px}.uxbert-tool-btn{align-items:center;background:var(--uxbert-bg);border:2px solid var(--uxbert-border);border-radius:6px;cursor:pointer;display:flex;font-family:Arial,sans-serif;font-size:18px;font-weight:700;height:40px;justify-content:center;transition:all .2s ease;width:40px}.uxbert-tool-btn.active,.uxbert-tool-btn:hover{background:var(--uxbert-primary);border-color:var(--uxbert-primary);color:#fff}.uxbert-color-picker{display:flex;gap:6px;margin:8px 0}.uxbert-color-option{border:2px solid var(--uxbert-border);border-radius:50%;cursor:pointer;height:32px;transition:transform .2s ease;width:32px}.uxbert-color-option:hover{transform:scale(1.1)}.uxbert-color-option.active{border:3px solid var(--uxbert-text)}.uxbert-canvas-overlay{cursor:crosshair;display:none;left:0;position:absolute;top:0;z-index:var(--uxbert-z-canvas)}.uxbert-canvas-overlay.active{display:block}.uxbert-canvas-overlay.viewport-mode{left:0;position:fixed;top:0}.uxbert-text-input{background:hsla(0,0%,100%,.95);border:2px solid var(--uxbert-primary);border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:var(--uxbert-text);font-family:Arial,sans-serif;font-size:16px;font-weight:700;min-width:200px;outline:none;padding:8px 12px;z-index:var(--uxbert-z-toolbar)}.uxbert-text-input:focus{border-color:var(--uxbert-primary-hover);box-shadow:0 4px 16px rgba(79,70,229,.3)}.uxbert-text-input::placeholder{color:#9ca3af;font-weight:400}@media (max-width:768px){.uxbert-modal{max-height:95vh;padding:16px;width:95%}.uxbert-toolbar{bottom:90px;left:16px;max-height:60vh;right:16px;width:auto}.uxbert-toolbar-toggle{bottom:16px;height:56px;right:16px;width:56px}.uxbert-fab{font-size:20px;height:48px;width:48px}.uxbert-color-picker,.uxbert-toolbar-tools{justify-content:center}}";
|
10556
10573
|
styleInject(css_248z);
|
10557
10574
|
|
10558
10575
|
// Main initialization file
|