@qaiddev/thumbs-embed 1.0.5 → 1.0.6

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/qaid.js CHANGED
@@ -1,26 +1,28 @@
1
- var j = Object.defineProperty;
2
- var X = (i, t, e) => t in i ? j(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
3
- var d = (i, t, e) => X(i, typeof t != "symbol" ? t + "" : t, e);
4
- const k = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
1
+ var Z = Object.defineProperty;
2
+ var Q = (i, t, e) => t in i ? Z(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
3
+ var h = (i, t, e) => Q(i, typeof t != "symbol" ? t + "" : t, e);
4
+ const T = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
5
5
  <path stroke-linecap="round" stroke-linejoin="round" d="M14 10h4.764a2 2 0 011.789 2.894l-3.5 7A2 2 0 0115.263 21h-4.017c-.163 0-.326-.02-.485-.06L7 20m7-10V5a2 2 0 00-2-2h-.095c-.5 0-.905.405-.905.905 0 .714-.211 1.412-.608 2.006L7 11v9m7-10h-2M7 20H5a2 2 0 01-2-2v-6a2 2 0 012-2h2.5"/>
6
- </svg>`, w = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
6
+ </svg>`, S = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
7
7
  <path stroke-linecap="round" stroke-linejoin="round" d="M10 14H5.236a2 2 0 01-1.789-2.894l3.5-7A2 2 0 018.737 3h4.018a2 2 0 01.485.06l3.76.94m-7 10v5a2 2 0 002 2h.095c.5 0 .905-.405.905-.905 0-.714.211-1.412.608-2.006L17 13V4m-7 10h2m5-10h2a2 2 0 012 2v6a2 2 0 01-2 2h-2.5"/>
8
- </svg>`, Y = "body.qaid-targeting,body.qaid-targeting *{cursor:none!important}.qaid-widget,.qaid-widget *,.qaid-modal-container,.qaid-modal-container *{cursor:pointer!important}.qaid-widget.qaid-auto-container{position:fixed;z-index:50;display:flex;gap:.5rem}.qaid-widget.qaid-auto-container.qaid-bottom-right{bottom:1rem;right:1rem}.qaid-widget.qaid-auto-container.qaid-bottom-left{bottom:1rem;left:1rem}.qaid-widget.qaid-auto-container.qaid-top-right{top:1rem;right:1rem}.qaid-widget.qaid-auto-container.qaid-top-left{top:1rem;left:1rem}.qaid-widget.qaid-incognito{opacity:0;transition:opacity .2s ease-in-out}.qaid-widget.qaid-incognito:hover{opacity:1}button.qaid-btn-structural{display:inline-flex;align-items:center;justify-content:center;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}.qaid-icon{width:24px;height:24px}.qaid-btn-structural:not(:has(svg)),.qaid-btn:not(:has(svg)){font-size:var(--qaid-icon-size, 24px);line-height:1}.qaid-emoji-icon{font-size:var(--qaid-icon-size, 24px);line-height:1}.qaid-tooltip-wrapper{position:relative}.qaid-tooltip-text{position:fixed;padding:.5rem .75rem;background:#1f2937;color:#fff;font-size:1rem;font-weight:600;border-radius:.5rem;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .15s;z-index:99999}.qaid-tooltip-text.qaid-tooltip-visible{opacity:1}.qaid-targeting-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:40;pointer-events:none}.qaid-capture-layer{position:fixed;top:0;right:0;bottom:0;left:0;cursor:crosshair;pointer-events:auto;z-index:9999}.qaid-banner{position:fixed;top:0;left:0;right:0;padding:.75rem 1rem;text-align:center;z-index:10000;font-family:var(--qaid-font-family, system-ui, -apple-system, sans-serif);font-size:var(--qaid-font-size, 16px);animation:qaid-slideDown .2s ease-out}.qaid-banner-up{background:color-mix(in srgb,var(--qaid-positive) 90%,transparent);color:#fff}.qaid-banner-down{background:color-mix(in srgb,var(--qaid-negative) 90%,transparent);color:#fff}.qaid-banner-text{font-weight:500}.qaid-banner-hint{margin-left:.5rem;opacity:.75}@keyframes qaid-slideDown{0%{transform:translateY(-100%)}to{transform:translateY(0)}}.qaid-vignette{position:fixed;top:0;right:0;bottom:0;left:0;pointer-events:none;background:radial-gradient(ellipse at center,transparent 30%,rgba(0,0,0,.3) 70%,rgba(0,0,0,.6) 100%);z-index:41}.qaid-crosshair-h,.qaid-crosshair-v{position:fixed;pointer-events:none;z-index:42}.qaid-crosshair-h{left:0;right:0;height:1px;background:color-mix(in srgb,var(--qaid-negative) 60%,transparent)}.qaid-crosshair-v{top:0;bottom:0;width:1px;background:color-mix(in srgb,var(--qaid-negative) 60%,transparent)}.qaid-type-up .qaid-crosshair-h,.qaid-type-up .qaid-crosshair-v{background:color-mix(in srgb,var(--qaid-positive) 60%,transparent)}.qaid-scope{position:fixed;width:80px;height:80px;pointer-events:none;z-index:43;transform:translate(-50%,-50%)}.qaid-scope-ring{position:absolute;top:10px;right:10px;bottom:10px;left:10px;border:2px solid color-mix(in srgb,var(--qaid-negative) 80%,transparent);border-radius:50%}.qaid-type-up .qaid-scope-ring{border-color:color-mix(in srgb,var(--qaid-positive) 80%,transparent)}.qaid-scope-ring-inner{position:absolute;top:20px;right:20px;bottom:20px;left:20px;border:1px solid color-mix(in srgb,var(--qaid-negative) 50%,transparent);border-radius:50%}.qaid-type-up .qaid-scope-ring-inner{border-color:color-mix(in srgb,var(--qaid-positive) 50%,transparent)}.qaid-scope-dot{position:absolute;top:50%;left:50%;width:4px;height:4px;background:var(--qaid-negative);border-radius:50%;transform:translate(-50%,-50%)}.qaid-type-up .qaid-scope-dot{background:var(--qaid-positive)}.qaid-highlight{outline:3px solid color-mix(in srgb,var(--qaid-negative) 80%,transparent)!important;outline-offset:2px!important;background-color:color-mix(in srgb,var(--qaid-negative) 10%,transparent)!important;transition:outline .1s ease,background-color .1s ease}body.qaid-targeting.qaid-type-up .qaid-highlight{outline-color:color-mix(in srgb,var(--qaid-positive) 80%,transparent)!important;background-color:color-mix(in srgb,var(--qaid-positive) 10%,transparent)!important}.qaid-selected-marker{position:fixed;border:3px solid var(--qaid-marker, #6366f1);border-radius:50%;pointer-events:none;z-index:44;animation:qaid-markerPulse 1.5s ease-in-out infinite}@keyframes qaid-markerPulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.7;transform:scale(1.05)}}.qaid-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:45;background:#0000004d}.qaid-modal-container{position:fixed;z-index:50;display:flex;flex-direction:column;align-items:flex-start;max-height:calc(100vh - 32px);font-family:var(--qaid-font-family, system-ui, -apple-system, sans-serif);font-size:var(--qaid-font-size, 16px)}.qaid-modal-container.qaid-above{flex-direction:column-reverse}.qaid-modal-arrow{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;position:relative;align-self:flex-start}.qaid-modal-container.qaid-below .qaid-modal-arrow{border-bottom:12px solid light-dark(#ffffff,#1f2937)}.qaid-modal-container.qaid-above .qaid-modal-arrow{border-top:12px solid light-dark(#ffffff,#1f2937)}.qaid-modal-box{color-scheme:inherit;background:light-dark(#ffffff,#1f2937);border-radius:1rem;padding:1.5rem;box-shadow:0 25px 50px -12px light-dark(rgba(0,0,0,.25),rgba(0,0,0,.5));width:var(--qaid-modal-width, 400px);max-width:calc(100vw - 32px);max-height:calc(100vh - 60px);overflow-y:auto}.qaid-modal-header{display:flex;align-items:flex-start;gap:.75rem;margin-bottom:1rem}button.qaid-type-toggle{border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s;flex-shrink:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}button.qaid-type-toggle:hover{transform:scale(1.1)}button.qaid-type-toggle:not(.qaid-type-toggle-custom){width:2.5rem;height:2.5rem;border-radius:50%}button.qaid-type-toggle:not(.qaid-type-toggle-custom) svg{width:1.25rem;height:1.25rem}button.qaid-type-toggle.qaid-type-up{background:var(--qaid-positive);color:#fff}button.qaid-type-toggle.qaid-type-down{background:var(--qaid-negative);color:#fff}.qaid-modal-header-text{flex:1;min-width:0}.qaid-modal-title{font-size:1.125rem;font-weight:700;margin:0 0 .25rem;color:light-dark(#1f2937,#f9fafb)}.qaid-modal-subtitle{color:light-dark(#6b7280,#9ca3af);margin:0;font-size:.875rem}.qaid-textarea{width:100%;height:6rem;padding:.75rem;border:1px solid light-dark(#d1d5db,#374151);border-radius:.5rem;font-family:inherit;font-size:1rem;resize:vertical;margin-bottom:1rem;box-sizing:border-box;background:light-dark(#ffffff,#111827);color:light-dark(#1f2937,#f9fafb)}.qaid-textarea:focus{outline:none;border-color:var(--qaid-marker);box-shadow:0 0 0 3px color-mix(in srgb,var(--qaid-marker) 20%,transparent)}.qaid-btn-row{display:flex;gap:.5rem;justify-content:flex-end}button.qaid-btn-submit{padding:.5rem 1rem;background:var(--qaid-marker);color:var(--qaid-marker-text, white);border:none;border-radius:.5rem;font-size:.875rem;font-weight:500;cursor:pointer;transition:background-color .2s,filter .2s;-webkit-appearance:none;-moz-appearance:none;appearance:none}button.qaid-btn-submit:hover{filter:brightness(.85)}button.qaid-btn-submit:focus{outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--qaid-marker) 30%,transparent)}.qaid-bottom-sheet{position:fixed;bottom:0;left:0;right:0;z-index:50;animation:qaid-slideUpSheet .3s ease-out;font-family:var(--qaid-font-family, system-ui, -apple-system, sans-serif);font-size:var(--qaid-font-size, 16px)}.qaid-bottom-sheet-content{background:light-dark(#ffffff,#1f2937);border-radius:1rem 1rem 0 0;padding:1.5rem;padding-bottom:max(1.5rem,env(safe-area-inset-bottom))}.qaid-bottom-sheet-handle{width:36px;height:4px;background:light-dark(rgba(0,0,0,.2),rgba(255,255,255,.2));border-radius:2px;margin:0 auto 1rem}@keyframes qaid-slideUpSheet{0%{transform:translateY(100%)}to{transform:translateY(0)}}";
9
- let T = !1;
10
- const K = {
8
+ </svg>`, tt = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
9
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 10.5l4.72-4.72a.75.75 0 011.28.53v11.38a.75.75 0 01-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25h-9A2.25 2.25 0 002.25 7.5v9a2.25 2.25 0 002.25 2.25z"/>
10
+ </svg>`, et = "body.qaid-targeting,body.qaid-targeting *{cursor:none!important}.qaid-widget,.qaid-widget *,.qaid-modal-container,.qaid-modal-container *{cursor:pointer!important}.qaid-widget.qaid-auto-container{position:fixed;z-index:50;display:flex;gap:.5rem}.qaid-widget.qaid-auto-container.qaid-bottom-right{bottom:1rem;right:1rem}.qaid-widget.qaid-auto-container.qaid-bottom-left{bottom:1rem;left:1rem}.qaid-widget.qaid-auto-container.qaid-top-right{top:1rem;right:1rem}.qaid-widget.qaid-auto-container.qaid-top-left{top:1rem;left:1rem}.qaid-widget.qaid-incognito{opacity:0;transition:opacity .2s ease-in-out}.qaid-widget.qaid-incognito:hover{opacity:1}button.qaid-btn-structural{display:inline-flex;align-items:center;justify-content:center;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}.qaid-icon{width:24px;height:24px}.qaid-btn-structural:not(:has(svg)),.qaid-btn:not(:has(svg)){font-size:var(--qaid-icon-size, 24px);line-height:1}.qaid-emoji-icon{font-size:var(--qaid-icon-size, 24px);line-height:1}.qaid-tooltip-wrapper{position:relative}.qaid-tooltip-text{position:fixed;padding:.5rem .75rem;background:#1f2937;color:#fff;font-size:1rem;font-weight:600;border-radius:.5rem;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .15s;z-index:99999}.qaid-tooltip-text.qaid-tooltip-visible{opacity:1}.qaid-targeting-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:40;pointer-events:none}.qaid-capture-layer{position:fixed;top:0;right:0;bottom:0;left:0;cursor:crosshair;pointer-events:auto;z-index:9999}.qaid-banner{position:fixed;top:0;left:0;right:0;padding:.75rem 1rem;text-align:center;z-index:10000;font-family:var(--qaid-font-family, system-ui, -apple-system, sans-serif);font-size:var(--qaid-font-size, 16px);animation:qaid-slideDown .2s ease-out}.qaid-banner-up{background:color-mix(in srgb,var(--qaid-positive) 90%,transparent);color:#fff}.qaid-banner-down{background:color-mix(in srgb,var(--qaid-negative) 90%,transparent);color:#fff}.qaid-banner-text{font-weight:500}.qaid-banner-hint{margin-left:.5rem;opacity:.75}@keyframes qaid-slideDown{0%{transform:translateY(-100%)}to{transform:translateY(0)}}.qaid-vignette{position:fixed;top:0;right:0;bottom:0;left:0;pointer-events:none;background:radial-gradient(ellipse at center,transparent 30%,rgba(0,0,0,.3) 70%,rgba(0,0,0,.6) 100%);z-index:41}.qaid-crosshair-h,.qaid-crosshair-v{position:fixed;pointer-events:none;z-index:42}.qaid-crosshair-h{left:0;right:0;height:1px;background:color-mix(in srgb,var(--qaid-negative) 60%,transparent)}.qaid-crosshair-v{top:0;bottom:0;width:1px;background:color-mix(in srgb,var(--qaid-negative) 60%,transparent)}.qaid-type-up .qaid-crosshair-h,.qaid-type-up .qaid-crosshair-v{background:color-mix(in srgb,var(--qaid-positive) 60%,transparent)}.qaid-scope{position:fixed;width:80px;height:80px;pointer-events:none;z-index:43;transform:translate(-50%,-50%)}.qaid-scope-ring{position:absolute;top:10px;right:10px;bottom:10px;left:10px;border:2px solid color-mix(in srgb,var(--qaid-negative) 80%,transparent);border-radius:50%}.qaid-type-up .qaid-scope-ring{border-color:color-mix(in srgb,var(--qaid-positive) 80%,transparent)}.qaid-scope-ring-inner{position:absolute;top:20px;right:20px;bottom:20px;left:20px;border:1px solid color-mix(in srgb,var(--qaid-negative) 50%,transparent);border-radius:50%}.qaid-type-up .qaid-scope-ring-inner{border-color:color-mix(in srgb,var(--qaid-positive) 50%,transparent)}.qaid-scope-dot{position:absolute;top:50%;left:50%;width:4px;height:4px;background:var(--qaid-negative);border-radius:50%;transform:translate(-50%,-50%)}.qaid-type-up .qaid-scope-dot{background:var(--qaid-positive)}.qaid-highlight{outline:3px solid color-mix(in srgb,var(--qaid-negative) 80%,transparent)!important;outline-offset:2px!important;background-color:color-mix(in srgb,var(--qaid-negative) 10%,transparent)!important;transition:outline .1s ease,background-color .1s ease}body.qaid-targeting.qaid-type-up .qaid-highlight{outline-color:color-mix(in srgb,var(--qaid-positive) 80%,transparent)!important;background-color:color-mix(in srgb,var(--qaid-positive) 10%,transparent)!important}.qaid-selected-marker{position:fixed;border:3px solid var(--qaid-marker, #6366f1);border-radius:50%;pointer-events:none;z-index:44;animation:qaid-markerPulse 1.5s ease-in-out infinite}@keyframes qaid-markerPulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.7;transform:scale(1.05)}}.qaid-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:45;background:#0000004d}.qaid-modal-container{position:fixed;z-index:50;display:flex;flex-direction:column;align-items:flex-start;max-height:calc(100vh - 32px);font-family:var(--qaid-font-family, system-ui, -apple-system, sans-serif);font-size:var(--qaid-font-size, 16px)}.qaid-modal-container.qaid-above{flex-direction:column-reverse}.qaid-modal-arrow{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;position:relative;align-self:flex-start}.qaid-modal-container.qaid-below .qaid-modal-arrow{border-bottom:12px solid light-dark(#ffffff,#1f2937)}.qaid-modal-container.qaid-above .qaid-modal-arrow{border-top:12px solid light-dark(#ffffff,#1f2937)}.qaid-modal-box{color-scheme:inherit;background:light-dark(#ffffff,#1f2937);border-radius:1rem;padding:1.5rem;box-shadow:0 25px 50px -12px light-dark(rgba(0,0,0,.25),rgba(0,0,0,.5));width:var(--qaid-modal-width, 400px);max-width:calc(100vw - 32px);max-height:calc(100vh - 60px);overflow-y:auto}.qaid-modal-header{display:flex;align-items:flex-start;gap:.75rem;margin-bottom:1rem}button.qaid-type-toggle{border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s;flex-shrink:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}button.qaid-type-toggle:hover{transform:scale(1.1)}button.qaid-type-toggle:not(.qaid-type-toggle-custom){width:2.5rem;height:2.5rem;border-radius:50%}button.qaid-type-toggle:not(.qaid-type-toggle-custom) svg{width:1.25rem;height:1.25rem}button.qaid-type-toggle.qaid-type-up{background:var(--qaid-positive);color:#fff}button.qaid-type-toggle.qaid-type-down{background:var(--qaid-negative);color:#fff}.qaid-modal-header-text{flex:1;min-width:0}.qaid-modal-title{font-size:1.125rem;font-weight:700;margin:0 0 .25rem;color:light-dark(#1f2937,#f9fafb)}.qaid-modal-subtitle{color:light-dark(#6b7280,#9ca3af);margin:0;font-size:.875rem}.qaid-textarea{width:100%;height:6rem;padding:.75rem;border:1px solid light-dark(#d1d5db,#374151);border-radius:.5rem;font-family:inherit;font-size:1rem;resize:vertical;margin-bottom:1rem;box-sizing:border-box;background:light-dark(#ffffff,#111827);color:light-dark(#1f2937,#f9fafb)}.qaid-textarea:focus{outline:none;border-color:var(--qaid-marker);box-shadow:0 0 0 3px color-mix(in srgb,var(--qaid-marker) 20%,transparent)}.qaid-btn-row{display:flex;gap:.5rem;justify-content:flex-end}button.qaid-btn-submit{padding:.5rem 1rem;background:var(--qaid-marker);color:var(--qaid-marker-text, white);border:none;border-radius:.5rem;font-size:.875rem;font-weight:500;cursor:pointer;transition:background-color .2s,filter .2s;-webkit-appearance:none;-moz-appearance:none;appearance:none}button.qaid-btn-submit:hover{filter:brightness(.85)}button.qaid-btn-submit:focus{outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--qaid-marker) 30%,transparent)}.qaid-bottom-sheet{position:fixed;bottom:0;left:0;right:0;z-index:50;animation:qaid-slideUpSheet .3s ease-out;font-family:var(--qaid-font-family, system-ui, -apple-system, sans-serif);font-size:var(--qaid-font-size, 16px)}.qaid-bottom-sheet-content{background:light-dark(#ffffff,#1f2937);border-radius:1rem 1rem 0 0;padding:1.5rem;padding-bottom:max(1.5rem,env(safe-area-inset-bottom))}.qaid-bottom-sheet-handle{width:36px;height:4px;background:light-dark(rgba(0,0,0,.2),rgba(255,255,255,.2));border-radius:2px;margin:0 auto 1rem}@keyframes qaid-slideUpSheet{0%{transform:translateY(100%)}to{transform:translateY(0)}}button.qaid-btn-record:hover{background:#dc2626;color:#fff}.qaid-recording-indicator{position:fixed;top:12px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:.5rem;padding:.5rem 1rem;background:light-dark(#1f2937,#374151);color:#fff;border-radius:9999px;font-family:var(--qaid-font-family, system-ui, -apple-system, sans-serif);font-size:.875rem;font-weight:500;box-shadow:0 4px 12px #0000004d;z-index:99999;animation:qaid-slideDown .2s ease-out}.qaid-recording-dot{width:10px;height:10px;background:#dc2626;border-radius:50%;animation:qaid-dotPulse 1.5s ease-in-out infinite}@keyframes qaid-dotPulse{0%,to{opacity:1}50%{opacity:.3}}.qaid-recording-time{font-variant-numeric:tabular-nums;min-width:2.5rem;text-align:center}button.qaid-recording-stop{padding:.25rem .75rem;background:#dc2626;color:#fff;border:none;border-radius:9999px;font-size:.75rem;font-weight:600;cursor:pointer;transition:background-color .2s;-webkit-appearance:none;-moz-appearance:none;appearance:none}button.qaid-recording-stop:hover{background:#b91c1c}.qaid-video-preview{position:fixed;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;background:#0009;z-index:99998;animation:qaid-fadeIn .2s ease-out}@keyframes qaid-fadeIn{0%{opacity:0}to{opacity:1}}.qaid-video-preview-box{color-scheme:inherit;background:light-dark(#ffffff,#1f2937);border-radius:1rem;padding:1.5rem;box-shadow:0 25px 50px -12px #00000080;width:560px;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);overflow-y:auto;font-family:var(--qaid-font-family, system-ui, -apple-system, sans-serif);font-size:var(--qaid-font-size, 16px)}.qaid-video-preview-box h3{font-size:1.125rem;font-weight:700;margin:0 0 1rem;color:light-dark(#1f2937,#f9fafb)}.qaid-video-preview-box video{width:100%;border-radius:.5rem;background:#000;margin-bottom:1rem}.qaid-video-preview-box textarea{width:100%;height:4rem;padding:.75rem;border:1px solid light-dark(#d1d5db,#374151);border-radius:.5rem;font-family:inherit;font-size:.875rem;resize:vertical;margin-bottom:1rem;box-sizing:border-box;background:light-dark(#ffffff,#111827);color:light-dark(#1f2937,#f9fafb)}.qaid-video-preview-box textarea:focus{outline:none;border-color:var(--qaid-marker);box-shadow:0 0 0 3px color-mix(in srgb,var(--qaid-marker) 20%,transparent)}.qaid-video-preview-actions{display:flex;gap:.5rem;justify-content:flex-end}button.qaid-video-btn{padding:.5rem 1rem;border:none;border-radius:.5rem;font-size:.875rem;font-weight:500;cursor:pointer;transition:background-color .2s,filter .2s;-webkit-appearance:none;-moz-appearance:none;appearance:none}button.qaid-video-btn-cancel{background:light-dark(#f3f4f6,#374151);color:light-dark(#374151,#d1d5db)}button.qaid-video-btn-cancel:hover{background:light-dark(#e5e7eb,#4b5563)}button.qaid-video-btn-rerecord{background:light-dark(#fef3c7,#78350f);color:light-dark(#92400e,#fde68a)}button.qaid-video-btn-rerecord:hover{filter:brightness(.9)}button.qaid-video-btn-send{background:var(--qaid-marker);color:var(--qaid-marker-text, white)}button.qaid-video-btn-send:hover{filter:brightness(.85)}button.qaid-video-btn-send:disabled{opacity:.5;cursor:not-allowed}.qaid-video-sending{display:flex;align-items:center;gap:.5rem;font-size:.875rem;color:light-dark(#6b7280,#9ca3af)}";
11
+ let L = !1;
12
+ const it = {
11
13
  small: 36,
12
14
  medium: 48,
13
15
  large: 64
14
- }, R = {
16
+ }, ot = {
15
17
  small: 18,
16
18
  medium: 24,
17
19
  large: 32
18
20
  };
19
- function _(i, t, e) {
20
- const [o, n, a] = [i, t, e].map((s) => (s = s / 255, s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4)));
21
+ function nt(i, t, e) {
22
+ const [o, n, a] = [i, t, e].map((r) => (r = r / 255, r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4)));
21
23
  return 0.2126 * o + 0.7152 * n + 0.0722 * a;
22
24
  }
23
- function V(i) {
25
+ function at(i) {
24
26
  if (i.startsWith("#")) {
25
27
  const e = i.slice(1), o = e.length === 3 ? e.split("").map((a) => a + a).join("") : e, n = parseInt(o, 16);
26
28
  return {
@@ -36,13 +38,13 @@ function V(i) {
36
38
  b: parseInt(t[3])
37
39
  } : null;
38
40
  }
39
- function J(i) {
40
- const t = V(i);
41
- return t && _(t.r, t.g, t.b) > 0.4 ? "black" : "white";
41
+ function rt(i) {
42
+ const t = at(i);
43
+ return t && nt(t.r, t.g, t.b) > 0.4 ? "black" : "white";
42
44
  }
43
- function G(i = {}) {
44
- if (T) return;
45
- T = !0;
45
+ function st(i = {}) {
46
+ if (L) return;
47
+ L = !0;
46
48
  const {
47
49
  positiveColor: t = "rgb(0, 200, 83)",
48
50
  negativeColor: e = "rgb(255, 0, 0)",
@@ -50,21 +52,21 @@ function G(i = {}) {
50
52
  // skipButtonStyles kept for backwards compatibility but no longer used
51
53
  buttonSize: n = "medium",
52
54
  modalWidth: a = 400,
53
- backdropOpacity: s = 0.3,
55
+ backdropOpacity: r = 0.3,
54
56
  fontFamily: l = "system-ui, -apple-system, sans-serif",
55
- fontSize: r = 16
56
- } = i, c = K[n], p = R[n], g = J(o), h = `:root{--qaid-positive:${t};--qaid-negative:${e};--qaid-marker:${o};--qaid-marker-text:${g};--qaid-btn-size:${c}px;--qaid-icon-size:${p}px;--qaid-modal-width:${a}px;--qaid-backdrop-opacity:${s};--qaid-font-family:${l};--qaid-font-size:${r}px}`, u = "button.qaid-btn{width:var(--qaid-btn-size);height:var(--qaid-btn-size);border-radius:50%;border:none;background:#f3f4f6;color:#374151;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);transition:background-color .2s,color .2s,transform .2s;-webkit-appearance:none;appearance:none}button.qaid-btn:hover{transform:scale(1.05)}button.qaid-btn-up:hover{background:var(--qaid-positive);color:#fff}button.qaid-btn-down:hover{background:var(--qaid-negative);color:#fff}button.qaid-btn svg{width:var(--qaid-icon-size);height:var(--qaid-icon-size)}", m = document.createElement("style");
57
- m.id = "qaid-styles", m.textContent = h + Y + u, document.head.appendChild(m);
57
+ fontSize: d = 16
58
+ } = i, s = it[n], c = ot[n], p = rt(o), u = `:root{--qaid-positive:${t};--qaid-negative:${e};--qaid-marker:${o};--qaid-marker-text:${p};--qaid-btn-size:${s}px;--qaid-icon-size:${c}px;--qaid-modal-width:${a}px;--qaid-backdrop-opacity:${r};--qaid-font-family:${l};--qaid-font-size:${d}px}`, f = "button.qaid-btn{width:var(--qaid-btn-size);height:var(--qaid-btn-size);border-radius:50%;border:none;background:#f3f4f6;color:#374151;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);transition:background-color .2s,color .2s,transform .2s;-webkit-appearance:none;appearance:none}button.qaid-btn:hover{transform:scale(1.05)}button.qaid-btn-up:hover{background:var(--qaid-positive);color:#fff}button.qaid-btn-down:hover{background:var(--qaid-negative);color:#fff}button.qaid-btn svg{width:var(--qaid-icon-size);height:var(--qaid-icon-size)}", g = document.createElement("style");
59
+ g.id = "qaid-styles", g.textContent = u + et + f, document.head.appendChild(g);
58
60
  }
59
- function Z() {
61
+ function dt() {
60
62
  const i = document.getElementById("qaid-styles");
61
- i && (i.remove(), T = !1);
63
+ i && (i.remove(), L = !1);
62
64
  }
63
- const Q = ["data-comp", "data-qa", "data-testid", "data-id"];
64
- function F(i, t = document.body) {
65
+ const ct = ["data-comp", "data-qa", "data-testid", "data-id"];
66
+ function W(i, t = document.body) {
65
67
  let e = i;
66
68
  for (; e && e !== t; ) {
67
- for (const o of Q) {
69
+ for (const o of ct) {
68
70
  const n = e.getAttribute(o);
69
71
  if (n)
70
72
  return `${o}="${n}"`;
@@ -73,47 +75,47 @@ function F(i, t = document.body) {
73
75
  }
74
76
  return null;
75
77
  }
76
- function tt(i, t = 100) {
78
+ function lt(i, t = 100) {
77
79
  var o;
78
80
  const e = ((o = i.textContent) == null ? void 0 : o.trim().slice(0, t)) || "";
79
81
  return e.length === t ? e + "..." : e;
80
82
  }
81
- function et(i) {
83
+ function ht(i) {
82
84
  let t = 1, e = i.previousElementSibling;
83
85
  for (; e; )
84
86
  t++, e = e.previousElementSibling;
85
87
  return t;
86
88
  }
87
- function it(i) {
89
+ function ut(i) {
88
90
  const t = [];
89
91
  let e = i;
90
92
  for (; e && e !== document.body && e !== document.documentElement; ) {
91
- const o = e.tagName.toLowerCase(), n = et(e);
93
+ const o = e.tagName.toLowerCase(), n = ht(e);
92
94
  t.unshift(`${o}:nth-child(${n})`), e = e.parentElement;
93
95
  }
94
96
  return t.length > 0 ? `body > ${t.join(" > ")}` : "body";
95
97
  }
96
- function ot(i) {
98
+ function pt(i) {
97
99
  return i.replace(/([!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g, "\\$1");
98
100
  }
99
- function nt(i) {
100
- const t = F(i);
101
- return t ? `[${t}]` : i.id ? `#${ot(i.id)}` : it(i);
101
+ function mt(i) {
102
+ const t = W(i);
103
+ return t ? `[${t}]` : i.id ? `#${pt(i.id)}` : ut(i);
102
104
  }
103
- function at(i) {
104
- const t = tt(i), e = F(i);
105
- return { selector: nt(i), text: t, dataAttr: e };
105
+ function ft(i) {
106
+ const t = lt(i), e = W(i);
107
+ return { selector: mt(i), text: t, dataAttr: e };
106
108
  }
107
- const O = {
109
+ const U = {
108
110
  width: 400,
109
111
  height: 280,
110
112
  arrowHeight: 12,
111
113
  gap: 8,
112
114
  viewportPadding: 16
113
115
  };
114
- function st(i, t, e, o, n) {
115
- const a = i.y, s = t - (i.y + i.height);
116
- if (s >= e + o)
116
+ function gt(i, t, e, o, n) {
117
+ const a = i.y, r = t - (i.y + i.height);
118
+ if (r >= e + o)
117
119
  return {
118
120
  top: i.y + i.height + o,
119
121
  position: "below"
@@ -123,29 +125,29 @@ function st(i, t, e, o, n) {
123
125
  top: i.y - e - o,
124
126
  position: "above"
125
127
  };
126
- const l = s > a ? "below" : "above";
127
- let r;
128
- return l === "below" ? r = Math.min(
128
+ const l = r > a ? "below" : "above";
129
+ let d;
130
+ return l === "below" ? d = Math.min(
129
131
  i.y + i.height + o,
130
132
  t - e - n
131
- ) : r = Math.max(n, i.y - e - o), { top: r, position: l };
133
+ ) : d = Math.max(n, i.y - e - o), { top: d, position: l };
132
134
  }
133
- function rt(i, t, e, o) {
135
+ function bt(i, t, e, o) {
134
136
  let a = i.x + i.width / 2 - e / 2;
135
137
  return a = Math.max(o, Math.min(a, t - e - o)), a;
136
138
  }
137
- function dt(i, t, e, o = 24, n = 24) {
138
- const s = i.clickX - t - n / 2;
139
- return Math.max(o, Math.min(s, e - o - n / 2));
139
+ function vt(i, t, e, o = 24, n = 24) {
140
+ const r = i.clickX - t - n / 2;
141
+ return Math.max(o, Math.min(r, e - o - n / 2));
140
142
  }
141
- function lt(i, t, e, o = O) {
142
- const n = o.height + o.arrowHeight, a = st(
143
+ function yt(i, t, e, o = U) {
144
+ const n = o.height + o.arrowHeight, a = gt(
143
145
  i,
144
146
  e,
145
147
  n,
146
148
  o.gap,
147
149
  o.viewportPadding
148
- ), s = rt(
150
+ ), r = bt(
149
151
  i,
150
152
  t,
151
153
  o.width,
@@ -153,12 +155,12 @@ function lt(i, t, e, o = O) {
153
155
  );
154
156
  return {
155
157
  top: a.top,
156
- left: s,
158
+ left: r,
157
159
  position: a.position
158
160
  };
159
161
  }
160
- function ct(i, t, e, o = O) {
161
- const n = lt(i, t, e, o), a = dt(
162
+ function wt(i, t, e, o = U) {
163
+ const n = yt(i, t, e, o), a = vt(
162
164
  i,
163
165
  n.left,
164
166
  o.width
@@ -168,22 +170,22 @@ function ct(i, t, e, o = O) {
168
170
  arrow: { left: a }
169
171
  };
170
172
  }
171
- const ht = 20;
172
- function pt(i) {
173
- const t = [], e = console.error, o = console.warn, n = console.log, a = (s, l) => {
174
- const r = {
175
- message: l.map((c) => String(c)).join(" "),
173
+ const qt = 20;
174
+ function xt(i) {
175
+ const t = [], e = console.error, o = console.warn, n = console.log, a = (r, l) => {
176
+ const d = {
177
+ message: l.map((s) => String(s)).join(" "),
176
178
  timestamp: Date.now(),
177
- level: s
179
+ level: r
178
180
  };
179
- t.length >= ht && t.shift(), t.push(r), i && i(r);
181
+ t.length >= qt && t.shift(), t.push(d), i && i(d);
180
182
  };
181
- return console.error = function(...s) {
182
- a("error", s), e.apply(console, s);
183
- }, console.warn = function(...s) {
184
- a("warn", s), o.apply(console, s);
185
- }, console.log = function(...s) {
186
- a("log", s), n.apply(console, s);
183
+ return console.error = function(...r) {
184
+ a("error", r), e.apply(console, r);
185
+ }, console.warn = function(...r) {
186
+ a("warn", r), o.apply(console, r);
187
+ }, console.log = function(...r) {
188
+ a("log", r), n.apply(console, r);
187
189
  }, {
188
190
  errors: t,
189
191
  restore: () => {
@@ -191,19 +193,155 @@ function pt(i) {
191
193
  }
192
194
  };
193
195
  }
194
- function ut(i = 640) {
196
+ const kt = 20, P = 4096;
197
+ function x(i) {
198
+ if (i == null) return;
199
+ const t = typeof i == "string" ? i : JSON.stringify(i);
200
+ return t.length > P ? t.slice(0, P) + "…[truncated]" : t;
201
+ }
202
+ function H(i, t) {
203
+ i.length >= kt && i.shift(), i.push(t);
204
+ }
205
+ async function Ct(i) {
206
+ try {
207
+ const t = await i.clone().text();
208
+ return x(t);
209
+ } catch {
210
+ return;
211
+ }
212
+ }
213
+ function Et() {
214
+ const i = [], t = window.fetch;
215
+ window.fetch = async function(n, a) {
216
+ const r = typeof n == "string" ? n : n instanceof URL ? n.toString() : n.url, l = (a == null ? void 0 : a.method) ?? (typeof n == "object" && "method" in n ? n.method : "GET");
217
+ let d;
218
+ a != null && a.body && (d = x(a.body));
219
+ const s = await t.apply(window, [n, a]);
220
+ if (s.status >= 400) {
221
+ const c = await Ct(s);
222
+ H(i, {
223
+ url: r,
224
+ method: l.toUpperCase(),
225
+ status: s.status,
226
+ statusText: s.statusText,
227
+ requestBody: d,
228
+ responseBody: c,
229
+ timestamp: Date.now()
230
+ });
231
+ }
232
+ return s;
233
+ };
234
+ const e = XMLHttpRequest.prototype.open, o = XMLHttpRequest.prototype.send;
235
+ return XMLHttpRequest.prototype.open = function(n, a, ...r) {
236
+ return this._qaid_method = n, this._qaid_url = typeof a == "string" ? a : a.toString(), e.apply(this, [n, a, ...r]);
237
+ }, XMLHttpRequest.prototype.send = function(n) {
238
+ const a = this, r = n ? x(n) : void 0;
239
+ return a.addEventListener("load", function() {
240
+ a.status >= 400 && H(i, {
241
+ url: a._qaid_url,
242
+ method: a._qaid_method.toUpperCase(),
243
+ status: a.status,
244
+ statusText: a.statusText,
245
+ requestBody: r,
246
+ responseBody: x(a.responseText),
247
+ timestamp: Date.now()
248
+ });
249
+ }), o.apply(this, [n]);
250
+ }, {
251
+ errors: i,
252
+ restore: () => {
253
+ window.fetch = t, XMLHttpRequest.prototype.open = e, XMLHttpRequest.prototype.send = o;
254
+ }
255
+ };
256
+ }
257
+ function Tt() {
258
+ return typeof navigator < "u" && !!navigator.mediaDevices && typeof navigator.mediaDevices.getDisplayMedia == "function" && typeof MediaRecorder < "u";
259
+ }
260
+ function St() {
261
+ if (typeof MediaRecorder > "u") return "";
262
+ const i = [
263
+ "video/webm;codecs=vp9",
264
+ "video/webm;codecs=vp8",
265
+ "video/webm",
266
+ "video/mp4"
267
+ ];
268
+ for (const t of i)
269
+ if (MediaRecorder.isTypeSupported(t))
270
+ return t;
271
+ return "";
272
+ }
273
+ function It(i = {}) {
274
+ const t = i.maxDuration ?? 15, e = i.videoBitsPerSecond ?? 8e5;
275
+ let o = null, n = null, a = [], r = null, l = null, d = null, s = 0, c = null, p = null, u = !1, f = null;
276
+ function g() {
277
+ d !== null && (clearInterval(d), d = null), f !== null && (clearTimeout(f), f = null), o && (o.getTracks().forEach((m) => m.stop()), o = null), n = null, a = [], r = null, l = null, c = null, p = null;
278
+ }
279
+ function b() {
280
+ u || (u = !0, n && n.state !== "inactive" && n.stop());
281
+ }
282
+ return {
283
+ async start() {
284
+ u = !1, a = [];
285
+ const m = St();
286
+ if (!m)
287
+ throw new Error("No supported video MIME type found");
288
+ o = await navigator.mediaDevices.getDisplayMedia({
289
+ video: {
290
+ frameRate: 15
291
+ },
292
+ audio: !1,
293
+ // @ts-expect-error preferCurrentTab is not in the TS types yet
294
+ preferCurrentTab: !0
295
+ });
296
+ const v = o.getVideoTracks()[0];
297
+ v && v.addEventListener("ended", () => {
298
+ b();
299
+ }), n = new MediaRecorder(o, {
300
+ mimeType: m,
301
+ videoBitsPerSecond: e
302
+ }), n.ondataavailable = (y) => {
303
+ y.data.size > 0 && a.push(y.data);
304
+ }, n.onstop = () => {
305
+ const y = new Blob(a, { type: m });
306
+ c && c(y), l && l(y), o && o.getTracks().forEach((q) => q.stop());
307
+ }, n.onerror = () => {
308
+ p && p(new Error("MediaRecorder error"));
309
+ }, n.start(1e3), s = Date.now(), d = setInterval(() => {
310
+ const y = Math.floor((Date.now() - s) / 1e3);
311
+ r && r(y);
312
+ }, 1e3), f = setTimeout(() => {
313
+ b();
314
+ }, t * 1e3);
315
+ },
316
+ stop() {
317
+ return new Promise((m, v) => {
318
+ c = m, p = v, b();
319
+ });
320
+ },
321
+ onTick(m) {
322
+ r = m;
323
+ },
324
+ onStop(m) {
325
+ l = m;
326
+ },
327
+ destroy() {
328
+ b(), g();
329
+ }
330
+ };
331
+ }
332
+ function Lt(i = 640) {
195
333
  return typeof window < "u" && window.innerWidth < i;
196
334
  }
197
- function D(i, t, e) {
335
+ function O(i, t, e) {
198
336
  const o = e.style.pointerEvents;
199
337
  e.style.pointerEvents = "none";
200
338
  const n = document.elementFromPoint(i, t);
201
339
  return e.style.pointerEvents = o, n;
202
340
  }
203
- function B(i) {
341
+ function N(i) {
204
342
  return i ? !!(i.closest(".qaid-widget") || i.closest(".qaid-targeting-overlay") || i.closest(".qaid-modal-container") || i.closest(".qaid-bottom-sheet")) : !1;
205
343
  }
206
- function mt(i, t = 0) {
344
+ function Mt(i, t = 0) {
207
345
  const e = i.getBoundingClientRect();
208
346
  return {
209
347
  x: e.left - t,
@@ -212,12 +350,12 @@ function mt(i, t = 0) {
212
350
  height: e.height + t * 2
213
351
  };
214
352
  }
215
- function C(i) {
353
+ function I(i) {
216
354
  document.querySelectorAll(`.${i}`).forEach((t) => {
217
355
  t.classList.remove(i);
218
356
  });
219
357
  }
220
- async function gt(i = {}) {
358
+ async function Dt(i = {}) {
221
359
  var n;
222
360
  const { quality: t = 1, maxWidth: e = 1280, maxHeight: o = 800 } = i;
223
361
  try {
@@ -228,45 +366,106 @@ async function gt(i = {}) {
228
366
  video: {
229
367
  displaySurface: "browser"
230
368
  }
231
- }), s = a.getVideoTracks()[0], l = s.getSettings(), r = document.createElement("video");
232
- r.srcObject = a, r.muted = !0, await new Promise((f) => {
233
- r.onloadedmetadata = () => {
234
- r.play(), f();
369
+ }), r = a.getVideoTracks()[0], l = r.getSettings(), d = document.createElement("video");
370
+ d.srcObject = a, d.muted = !0, await new Promise((m) => {
371
+ d.onloadedmetadata = () => {
372
+ d.play(), m();
235
373
  };
236
- }), await new Promise((f) => {
374
+ }), await new Promise((m) => {
237
375
  const v = () => {
238
- r.readyState >= 2 ? f() : requestAnimationFrame(v);
376
+ d.readyState >= 2 ? m() : requestAnimationFrame(v);
239
377
  };
240
378
  v();
241
- }), await new Promise((f) => setTimeout(f, 100));
242
- const c = l.width || r.videoWidth, p = l.height || r.videoHeight, g = Math.min(e / c, o / p, 1), h = Math.round(c * g), u = Math.round(p * g), m = document.createElement("canvas");
243
- m.width = h, m.height = u;
244
- const b = m.getContext("2d");
245
- return b ? (b.drawImage(r, 0, 0, h, u), s.stop(), m.toDataURL("image/webp", t)) : (s.stop(), null);
379
+ }), await new Promise((m) => setTimeout(m, 100));
380
+ const s = l.width || d.videoWidth, c = l.height || d.videoHeight, p = Math.min(e / s, o / c, 1), u = Math.round(s * p), f = Math.round(c * p), g = document.createElement("canvas");
381
+ g.width = u, g.height = f;
382
+ const b = g.getContext("2d");
383
+ return b ? (b.drawImage(d, 0, 0, u, f), r.stop(), g.toDataURL("image/webp", t)) : (r.stop(), null);
246
384
  } catch (a) {
247
385
  return console.warn("Screenshot capture failed:", a), null;
248
386
  }
249
387
  }
250
- const H = "qaid_visitor_id";
251
- function ft() {
388
+ const F = "https://qaid.dev/lib/html2canvas.min.js", zt = 1e4, Rt = 50;
389
+ let w = null;
390
+ function Ft() {
391
+ if (typeof document > "u" || typeof window > "u")
392
+ return !1;
393
+ const i = document.createElement("canvas");
394
+ return typeof i.getContext == "function" && !!i.getContext("2d");
395
+ }
396
+ function Bt() {
397
+ return window.html2canvas ? Promise.resolve(!0) : w || (w = new Promise((i) => {
398
+ if (!document.querySelector(
399
+ `script[src="${F}"]`
400
+ )) {
401
+ const n = document.createElement("script");
402
+ n.src = F, n.async = !0, document.head.appendChild(n);
403
+ }
404
+ const e = Date.now(), o = () => {
405
+ if (window.html2canvas) {
406
+ i(!0);
407
+ return;
408
+ }
409
+ if (Date.now() - e > zt) {
410
+ w = null, i(!1);
411
+ return;
412
+ }
413
+ setTimeout(o, Rt);
414
+ };
415
+ o();
416
+ }), w);
417
+ }
418
+ async function At(i = {}) {
419
+ const { quality: t = 0.8, maxWidth: e = 1280, maxHeight: o = 800 } = i;
252
420
  try {
253
- let i = localStorage.getItem(H);
254
- return i || (i = crypto.randomUUID(), localStorage.setItem(H, i)), i;
421
+ if (!await Bt() || !window.html2canvas)
422
+ return console.warn("html2canvas failed to load"), null;
423
+ const a = await window.html2canvas(document.body, {
424
+ useCORS: !0,
425
+ allowTaint: !1,
426
+ logging: !1,
427
+ windowWidth: document.documentElement.clientWidth,
428
+ windowHeight: document.documentElement.clientHeight,
429
+ width: document.documentElement.clientWidth,
430
+ height: document.documentElement.clientHeight,
431
+ x: window.scrollX,
432
+ y: window.scrollY,
433
+ ignoreElements: (s) => {
434
+ var c, p, u;
435
+ return s instanceof HTMLElement ? s.classList.contains("qaid-widget") || s.classList.contains("qaid-targeting-overlay") || s.classList.contains("qaid-modal-container") || s.classList.contains("qaid-bottom-sheet") || s.classList.contains("qaid-backdrop") || s.classList.contains("qaid-selected-marker") || s.classList.contains("qaid-tooltip-text") || s.classList.contains("qaid-recording-indicator") || s.classList.contains("qaid-video-preview") || ((u = (c = s.className) == null ? void 0 : (p = c.toString()).startsWith) == null ? void 0 : u.call(p, "qaid-")) : !1;
436
+ }
437
+ }), r = a.width, l = a.height, d = Math.min(e / r, o / l, 1);
438
+ if (d < 1) {
439
+ const s = Math.round(r * d), c = Math.round(l * d), p = document.createElement("canvas");
440
+ p.width = s, p.height = c;
441
+ const u = p.getContext("2d");
442
+ return u ? (u.drawImage(a, 0, 0, s, c), p.toDataURL("image/webp", t)) : null;
443
+ }
444
+ return a.toDataURL("image/webp", t);
445
+ } catch (n) {
446
+ return console.warn("DOM screenshot capture failed:", n), null;
447
+ }
448
+ }
449
+ const V = "qaid_visitor_id";
450
+ function $t() {
451
+ try {
452
+ let i = localStorage.getItem(V);
453
+ return i || (i = crypto.randomUUID(), localStorage.setItem(V, i)), i;
255
454
  } catch {
256
455
  return crypto.randomUUID();
257
456
  }
258
457
  }
259
- class bt {
458
+ class Pt {
260
459
  constructor(t) {
261
- d(this, "config");
262
- d(this, "state", "IDLE");
263
- d(this, "feedbackData", {
460
+ h(this, "config");
461
+ h(this, "state", "IDLE");
462
+ h(this, "feedbackData", {
264
463
  feedbackType: null,
265
464
  elementSelector: null,
266
465
  elementText: null,
267
466
  consoleErrors: []
268
467
  });
269
- d(this, "selectedBounds", {
468
+ h(this, "selectedBounds", {
270
469
  x: 0,
271
470
  y: 0,
272
471
  width: 0,
@@ -275,33 +474,39 @@ class bt {
275
474
  clickY: 0,
276
475
  visible: !1
277
476
  });
278
- d(this, "feedbackId", null);
279
- d(this, "mousePos", { x: 0, y: 0 });
280
- d(this, "lastHighlighted", null);
281
- d(this, "isMobile", !1);
282
- d(this, "visitorId");
477
+ h(this, "feedbackId", null);
478
+ h(this, "mousePos", { x: 0, y: 0 });
479
+ h(this, "lastHighlighted", null);
480
+ h(this, "isMobile", !1);
481
+ h(this, "visitorId");
283
482
  // Console capture
284
- d(this, "consoleCapture", null);
285
- // Server-side feature flags
286
- d(this, "allowedFeatures", null);
483
+ h(this, "consoleCapture", null);
484
+ // Video recording
485
+ h(this, "videoRecorder", null);
486
+ h(this, "networkCapture", null);
487
+ h(this, "recordedBlob", null);
488
+ h(this, "recordingIndicator", null);
489
+ h(this, "videoPreview", null);
490
+ h(this, "isRecording", !1);
491
+ h(this, "isSendingVideo", !1);
287
492
  // DOM elements
288
- d(this, "container", null);
289
- d(this, "isUserProvidedContainer", !1);
290
- d(this, "overlayContainer", null);
291
- d(this, "captureLayer", null);
292
- d(this, "crosshairH", null);
293
- d(this, "crosshairV", null);
294
- d(this, "scope", null);
295
- d(this, "marker", null);
296
- d(this, "modalContainer", null);
297
- d(this, "backdrop", null);
493
+ h(this, "container", null);
494
+ h(this, "isUserProvidedContainer", !1);
495
+ h(this, "overlayContainer", null);
496
+ h(this, "captureLayer", null);
497
+ h(this, "crosshairH", null);
498
+ h(this, "crosshairV", null);
499
+ h(this, "scope", null);
500
+ h(this, "marker", null);
501
+ h(this, "modalContainer", null);
502
+ h(this, "backdrop", null);
298
503
  // Bound event handlers
299
- d(this, "boundKeyDown");
300
- d(this, "boundMouseMove");
301
- d(this, "boundClick");
302
- d(this, "boundResize");
303
- d(this, "tooltipElement", null);
304
- var e, o, n, a, s, l, r, c, p, g, h, u, m, b, f, v;
504
+ h(this, "boundKeyDown");
505
+ h(this, "boundMouseMove");
506
+ h(this, "boundClick");
507
+ h(this, "boundResize");
508
+ h(this, "tooltipElement", null);
509
+ var e, o, n, a, r, l, d, s, c, p, u, f, g, b, m, v, y;
305
510
  this.config = {
306
511
  endpoint: t.endpoint,
307
512
  apiKey: t.apiKey ?? "",
@@ -317,36 +522,43 @@ class bt {
317
522
  colors: {
318
523
  positive: ((n = t.colors) == null ? void 0 : n.positive) ?? "rgb(0, 200, 83)",
319
524
  negative: ((a = t.colors) == null ? void 0 : a.negative) ?? "rgb(255, 0, 0)",
320
- marker: ((s = t.colors) == null ? void 0 : s.marker) ?? "#6366f1"
525
+ marker: ((r = t.colors) == null ? void 0 : r.marker) ?? "#6366f1"
321
526
  },
322
527
  buttonSize: t.buttonSize ?? "medium",
323
528
  text: {
324
529
  tooltip: ((l = t.text) == null ? void 0 : l.tooltip) ?? "",
325
- bannerText: ((r = t.text) == null ? void 0 : r.bannerText) ?? "Click on any element to target it with your feedback",
326
- bannerHint: ((c = t.text) == null ? void 0 : c.bannerHint) ?? "(Press Escape to cancel)",
327
- modalTitle: ((p = t.text) == null ? void 0 : p.modalTitle) ?? "Thank you for your feedback!",
328
- modalSubtitle: ((g = t.text) == null ? void 0 : g.modalSubtitle) ?? "Would you like to add a message to help us understand your feedback better?",
329
- placeholder: ((h = t.text) == null ? void 0 : h.placeholder) ?? "Optional: Tell us more about your experience...",
330
- submitButton: ((u = t.text) == null ? void 0 : u.submitButton) ?? "Submit",
331
- skipButton: ((m = t.text) == null ? void 0 : m.skipButton) ?? "Skip"
530
+ bannerText: ((d = t.text) == null ? void 0 : d.bannerText) ?? "Click on any element to target it with your feedback",
531
+ bannerHint: ((s = t.text) == null ? void 0 : s.bannerHint) ?? "(Press Escape to cancel)",
532
+ modalTitle: ((c = t.text) == null ? void 0 : c.modalTitle) ?? "Thank you for your feedback!",
533
+ modalSubtitle: ((p = t.text) == null ? void 0 : p.modalSubtitle) ?? "Would you like to add a message to help us understand your feedback better?",
534
+ placeholder: ((u = t.text) == null ? void 0 : u.placeholder) ?? "Optional: Tell us more about your experience...",
535
+ submitButton: ((f = t.text) == null ? void 0 : f.submitButton) ?? "Submit",
536
+ skipButton: ((g = t.text) == null ? void 0 : g.skipButton) ?? "Skip"
332
537
  },
333
538
  modalWidth: t.modalWidth ?? 400,
334
539
  backdropOpacity: t.backdropOpacity ?? 0.3,
335
540
  fontFamily: t.fontFamily ?? "system-ui, -apple-system, sans-serif",
336
541
  fontSize: t.fontSize ?? 16,
337
542
  captureScreenshot: t.captureScreenshot ?? !1,
543
+ screenshotMethod: t.screenshotMethod ?? "permission",
338
544
  screenshotOptions: {
339
545
  quality: ((b = t.screenshotOptions) == null ? void 0 : b.quality) ?? 0.8,
340
- maxWidth: ((f = t.screenshotOptions) == null ? void 0 : f.maxWidth) ?? 1280,
546
+ maxWidth: ((m = t.screenshotOptions) == null ? void 0 : m.maxWidth) ?? 1280,
341
547
  maxHeight: ((v = t.screenshotOptions) == null ? void 0 : v.maxHeight) ?? 800
342
548
  },
343
549
  incognito: t.incognito ?? !1,
344
550
  positiveIcon: t.positiveIcon ?? "",
345
- negativeIcon: t.negativeIcon ?? ""
346
- }, this.boundKeyDown = this.handleKeyDown.bind(this), this.boundMouseMove = this.handleMouseMove.bind(this), this.boundClick = this.handleClick.bind(this), this.boundResize = this.handleResize.bind(this), this.visitorId = ft(), this.init();
551
+ negativeIcon: t.negativeIcon ?? "",
552
+ hideThumbs: t.hideThumbs ?? !1,
553
+ captureVideo: t.captureVideo ?? !1,
554
+ videoOptions: {
555
+ maxDuration: ((y = t.videoOptions) == null ? void 0 : y.maxDuration) ?? 15
556
+ },
557
+ recordIcon: t.recordIcon ?? ""
558
+ }, this.boundKeyDown = this.handleKeyDown.bind(this), this.boundMouseMove = this.handleMouseMove.bind(this), this.boundClick = this.handleClick.bind(this), this.boundResize = this.handleResize.bind(this), this.visitorId = $t(), this.init();
347
559
  }
348
560
  init() {
349
- G({
561
+ st({
350
562
  positiveColor: this.config.colors.positive,
351
563
  negativeColor: this.config.colors.negative,
352
564
  markerColor: this.config.colors.marker,
@@ -356,21 +568,13 @@ class bt {
356
568
  backdropOpacity: this.config.backdropOpacity,
357
569
  fontFamily: this.config.fontFamily,
358
570
  fontSize: this.config.fontSize
359
- }), this.checkMobile(), window.addEventListener("resize", this.boundResize), this.createEmbed(), this.fetchAllowedFeatures(), this.consoleCapture = pt((t) => {
571
+ }), this.checkMobile(), window.addEventListener("resize", this.boundResize), this.createEmbed(), this.consoleCapture = xt((t) => {
360
572
  var e;
361
573
  this.feedbackData.consoleErrors = ((e = this.consoleCapture) == null ? void 0 : e.errors) ?? [];
362
574
  }), this.feedbackData.consoleErrors = this.consoleCapture.errors;
363
575
  }
364
- async fetchAllowedFeatures() {
365
- if (this.config.apiKey)
366
- try {
367
- const e = `${this.config.endpoint.replace(/\/feedback\/?$/, "")}/features?apiKey=${encodeURIComponent(this.config.apiKey)}`, o = await fetch(e);
368
- o.ok && (this.allowedFeatures = await o.json());
369
- } catch {
370
- }
371
- }
372
576
  checkMobile() {
373
- this.isMobile = ut();
577
+ this.isMobile = Lt();
374
578
  }
375
579
  handleResize() {
376
580
  this.checkMobile();
@@ -381,29 +585,36 @@ class bt {
381
585
  this.container = t, this.container.classList.add("qaid-widget", `qaid-${this.config.position}`), this.config.incognito && this.container.classList.add("qaid-incognito"), this.isUserProvidedContainer = !0;
382
586
  else {
383
587
  this.container = document.createElement("div"), this.container.className = `qaid-widget qaid-auto-container qaid-${this.config.position}${this.config.incognito ? " qaid-incognito" : ""}`, this.container.style.zIndex = String(this.config.zIndex);
384
- const { x: u, y: m } = this.config.offset;
385
- this.config.position.includes("right") ? this.container.style.right = `${u}px` : this.container.style.left = `${u}px`, this.config.position.includes("bottom") ? this.container.style.bottom = `${m}px` : this.container.style.top = `${m}px`, document.body.appendChild(this.container);
588
+ const { x: s, y: c } = this.config.offset;
589
+ this.config.position.includes("right") ? this.container.style.right = `${s}px` : this.container.style.left = `${s}px`, this.config.position.includes("bottom") ? this.container.style.bottom = `${c}px` : this.container.style.top = `${c}px`, document.body.appendChild(this.container);
386
590
  }
387
591
  const e = this.config.fontFamily, o = e && e !== "system-ui, -apple-system, sans-serif";
388
592
  o && (this.container.style.fontFamily = e);
389
- const n = !!this.config.buttonClass, a = n ? `qaid-btn-structural ${this.config.buttonClass}` : "qaid-btn", s = this.config.skipTargeting ? "Send feedback" : "Any feedback? Click to start, Esc to cancel", l = this.config.text.tooltip || s, r = document.createElement("div");
390
- r.className = "qaid-tooltip-text", r.textContent = l, o && (r.style.fontFamily = e), document.body.appendChild(r), this.tooltipElement = r;
391
- const c = document.createElement("div");
392
- c.className = "qaid-tooltip-wrapper";
393
- const p = document.createElement("button");
394
- p.type = "button", p.className = n ? `${a} qaid-btn-up` : "qaid-btn qaid-btn-up", p.innerHTML = this.config.positiveIcon || k, p.addEventListener("click", (u) => this.handleThumbClick("up", u.currentTarget)), p.addEventListener("mouseenter", () => this.showTooltip(p)), p.addEventListener("mouseleave", () => this.hideTooltip()), c.appendChild(p);
395
- const g = document.createElement("div");
396
- g.className = "qaid-tooltip-wrapper";
397
- const h = document.createElement("button");
398
- h.type = "button", h.className = n ? `${a} qaid-btn-down` : "qaid-btn qaid-btn-down", h.innerHTML = this.config.negativeIcon || w, h.addEventListener("click", (u) => this.handleThumbClick("down", u.currentTarget)), h.addEventListener("mouseenter", () => this.showTooltip(h)), h.addEventListener("mouseleave", () => this.hideTooltip()), g.appendChild(h), this.container.appendChild(c), this.container.appendChild(g);
593
+ const n = !!this.config.buttonClass, a = n ? `qaid-btn-structural ${this.config.buttonClass}` : "qaid-btn", r = (this.config.skipTargeting, "Feedback for us?"), l = this.config.text.tooltip || r, d = document.createElement("div");
594
+ if (d.className = "qaid-tooltip-text", d.textContent = l, o && (d.style.fontFamily = e), document.body.appendChild(d), this.tooltipElement = d, !this.config.hideThumbs) {
595
+ const s = document.createElement("div");
596
+ s.className = "qaid-tooltip-wrapper";
597
+ const c = document.createElement("button");
598
+ c.type = "button", c.className = n ? `${a} qaid-btn-up` : "qaid-btn qaid-btn-up", c.innerHTML = this.config.positiveIcon || T, c.addEventListener("click", (f) => this.handleThumbClick("up", f.currentTarget)), c.addEventListener("mouseenter", () => this.showTooltip(c)), c.addEventListener("mouseleave", () => this.hideTooltip()), s.appendChild(c);
599
+ const p = document.createElement("div");
600
+ p.className = "qaid-tooltip-wrapper";
601
+ const u = document.createElement("button");
602
+ u.type = "button", u.className = n ? `${a} qaid-btn-down` : "qaid-btn qaid-btn-down", u.innerHTML = this.config.negativeIcon || S, u.addEventListener("click", (f) => this.handleThumbClick("down", f.currentTarget)), u.addEventListener("mouseenter", () => this.showTooltip(u)), u.addEventListener("mouseleave", () => this.hideTooltip()), p.appendChild(u), this.container.appendChild(s), this.container.appendChild(p);
603
+ }
604
+ if (this.config.captureVideo && Tt()) {
605
+ const s = document.createElement("div");
606
+ s.className = "qaid-tooltip-wrapper";
607
+ const c = document.createElement("button");
608
+ c.type = "button", c.className = n ? `${a} qaid-btn-record` : "qaid-btn qaid-btn-record", c.innerHTML = this.config.recordIcon || tt, c.addEventListener("click", () => this.startRecording()), c.addEventListener("mouseenter", () => this.showTooltip(c)), c.addEventListener("mouseleave", () => this.hideTooltip()), s.appendChild(c), this.container.appendChild(s);
609
+ }
399
610
  }
400
611
  showTooltip(t) {
401
612
  if (!this.tooltipElement) return;
402
613
  const e = this.tooltipElement, o = 8;
403
614
  e.style.visibility = "hidden", e.classList.add("qaid-tooltip-visible");
404
- const n = t.getBoundingClientRect(), a = e.getBoundingClientRect(), s = window.innerWidth, l = window.innerHeight;
405
- let r, c;
406
- r = n.bottom + o, r + a.height > l - o && (r = n.top - a.height - o), c = n.left, c < o ? c = o : c + a.width > s - o && (c = s - a.width - o), r < o ? r = o : r + a.height > l - o && (r = l - a.height - o), e.style.top = `${r}px`, e.style.left = `${c}px`, e.style.visibility = "visible";
615
+ const n = t.getBoundingClientRect(), a = e.getBoundingClientRect(), r = window.innerWidth, l = window.innerHeight;
616
+ let d, s;
617
+ d = n.bottom + o, d + a.height > l - o && (d = n.top - a.height - o), s = n.left, s < o ? s = o : s + a.width > r - o && (s = r - a.width - o), d < o ? d = o : d + a.height > l - o && (d = l - a.height - o), e.style.top = `${d}px`, e.style.left = `${s}px`, e.style.visibility = "visible";
407
618
  }
408
619
  hideTooltip() {
409
620
  this.tooltipElement && this.tooltipElement.classList.remove("qaid-tooltip-visible");
@@ -444,40 +655,40 @@ class bt {
444
655
  `, this.overlayContainer.appendChild(this.captureLayer), this.overlayContainer.appendChild(t), this.overlayContainer.appendChild(o), this.overlayContainer.appendChild(this.crosshairH), this.overlayContainer.appendChild(this.crosshairV), this.overlayContainer.appendChild(this.scope), document.body.appendChild(this.overlayContainer);
445
656
  }
446
657
  handleKeyDown(t) {
447
- t.key === "Escape" && (this.state === "TARGETING" ? this.cancelTargeting() : this.state === "MODAL_OPEN" && this.closeModal());
658
+ t.key === "Escape" && (this.isRecording ? this.stopRecording() : this.videoPreview ? this.cancelRecordingPreview() : this.state === "TARGETING" ? this.cancelTargeting() : this.state === "MODAL_OPEN" && this.closeModal());
448
659
  }
449
660
  handleMouseMove(t) {
450
661
  if (this.mousePos.x = t.clientX, this.mousePos.y = t.clientY, this.crosshairH && (this.crosshairH.style.top = `${t.clientY}px`), this.crosshairV && (this.crosshairV.style.left = `${t.clientX}px`), this.scope && (this.scope.style.left = `${t.clientX}px`, this.scope.style.top = `${t.clientY}px`), this.captureLayer) {
451
- const e = D(
662
+ const e = O(
452
663
  t.clientX,
453
664
  t.clientY,
454
665
  this.captureLayer
455
666
  );
456
- e && !B(e) ? (this.lastHighlighted && this.lastHighlighted !== e && this.lastHighlighted.classList.remove("qaid-highlight"), e.classList.add("qaid-highlight"), this.lastHighlighted = e) : this.lastHighlighted && (this.lastHighlighted.classList.remove("qaid-highlight"), this.lastHighlighted = null);
667
+ e && !N(e) ? (this.lastHighlighted && this.lastHighlighted !== e && this.lastHighlighted.classList.remove("qaid-highlight"), e.classList.add("qaid-highlight"), this.lastHighlighted = e) : this.lastHighlighted && (this.lastHighlighted.classList.remove("qaid-highlight"), this.lastHighlighted = null);
457
668
  }
458
669
  }
459
670
  handleClick(t) {
460
671
  if (!this.captureLayer) return;
461
- const e = D(
672
+ const e = O(
462
673
  t.clientX,
463
674
  t.clientY,
464
675
  this.captureLayer
465
676
  );
466
- if (!e || B(e))
677
+ if (!e || N(e))
467
678
  return;
468
679
  e.classList.remove("qaid-highlight");
469
- const o = mt(e, 8);
680
+ const o = Mt(e, 8);
470
681
  this.selectedBounds = {
471
682
  ...o,
472
683
  clickX: t.clientX,
473
684
  clickY: t.clientY,
474
685
  visible: !0
475
686
  };
476
- const { selector: n, text: a } = at(e);
477
- this.feedbackData.elementSelector = n, this.feedbackData.elementText = a, C("qaid-highlight"), this.removeTargetingOverlay(), document.body.classList.remove("qaid-targeting", "qaid-type-up"), this.state = "SELECTED", this.showSelectedMarker(), this.submitFeedback();
687
+ const { selector: n, text: a } = ft(e);
688
+ this.feedbackData.elementSelector = n, this.feedbackData.elementText = a, I("qaid-highlight"), this.removeTargetingOverlay(), document.body.classList.remove("qaid-targeting", "qaid-type-up"), this.state = "SELECTED", this.showSelectedMarker(), this.submitFeedback();
478
689
  }
479
690
  cancelTargeting() {
480
- C("qaid-highlight"), this.removeTargetingOverlay(), document.body.classList.remove("qaid-targeting", "qaid-type-up"), document.removeEventListener("keydown", this.boundKeyDown), this.state = "IDLE", this.feedbackData.feedbackType = null, this.feedbackData.elementSelector = null, this.feedbackData.elementText = null, this.selectedBounds.visible = !1, this.lastHighlighted = null;
691
+ I("qaid-highlight"), this.removeTargetingOverlay(), document.body.classList.remove("qaid-targeting", "qaid-type-up"), document.removeEventListener("keydown", this.boundKeyDown), this.state = "IDLE", this.feedbackData.feedbackType = null, this.feedbackData.elementSelector = null, this.feedbackData.elementText = null, this.selectedBounds.visible = !1, this.lastHighlighted = null;
481
692
  }
482
693
  removeTargetingOverlay() {
483
694
  this.overlayContainer && (this.overlayContainer.remove(), this.overlayContainer = null), this.captureLayer = null, this.crosshairH = null, this.crosshairV = null, this.scope = null;
@@ -489,17 +700,15 @@ class bt {
489
700
  this.marker && (this.marker.remove(), this.marker = null);
490
701
  }
491
702
  async submitFeedback() {
492
- var a;
493
703
  if (!this.feedbackData.feedbackType) return;
494
704
  let t = null;
495
- const e = ((a = this.allowedFeatures) == null ? void 0 : a.screenshots) !== !1;
496
- this.config.captureScreenshot && e && (t = await gt(this.config.screenshotOptions));
497
- const o = this.feedbackData.elementSelector ? {
705
+ this.config.captureScreenshot && (this.config.screenshotMethod === "dom" ? t = await At(this.config.screenshotOptions) : t = await Dt(this.config.screenshotOptions));
706
+ const e = this.feedbackData.elementSelector ? {
498
707
  x: this.selectedBounds.x,
499
708
  y: this.selectedBounds.y,
500
709
  width: this.selectedBounds.width,
501
710
  height: this.selectedBounds.height
502
- } : null, n = {
711
+ } : null, o = {
503
712
  feedbackType: this.feedbackData.feedbackType,
504
713
  pageUrl: window.location.href,
505
714
  apiKey: this.config.apiKey || void 0,
@@ -515,21 +724,21 @@ class bt {
515
724
  screenshot: t,
516
725
  visitorId: this.visitorId,
517
726
  // Include element bounds and user agent for server-side screenshot fallback
518
- elementBounds: o,
727
+ elementBounds: e,
519
728
  userAgent: navigator.userAgent
520
729
  };
521
730
  try {
522
- const s = await fetch(this.config.endpoint, {
731
+ const n = await fetch(this.config.endpoint, {
523
732
  method: "POST",
524
733
  headers: { "Content-Type": "application/json" },
525
- body: JSON.stringify(n)
734
+ body: JSON.stringify(o)
526
735
  });
527
- if (s.ok) {
528
- const l = await s.json();
529
- this.feedbackId = l.id;
736
+ if (n.ok) {
737
+ const a = await n.json();
738
+ this.feedbackId = a.id;
530
739
  }
531
- } catch (s) {
532
- console.error("Failed to submit feedback:", s);
740
+ } catch (n) {
741
+ console.error("Failed to submit feedback:", n);
533
742
  }
534
743
  this.state = "MODAL_OPEN", this.showModal();
535
744
  }
@@ -548,7 +757,7 @@ class bt {
548
757
  `, document.body.appendChild(t), this.modalContainer = t, this.setupModalInteractions();
549
758
  }
550
759
  showPositionedModal() {
551
- const { modal: t, arrow: e } = ct(
760
+ const { modal: t, arrow: e } = wt(
552
761
  this.selectedBounds,
553
762
  window.innerWidth,
554
763
  window.innerHeight,
@@ -569,7 +778,7 @@ class bt {
569
778
  a.className = "qaid-modal-box", a.innerHTML = this.getModalContent(), this.modalContainer.appendChild(n), this.modalContainer.appendChild(a), document.body.appendChild(this.modalContainer), this.setupModalInteractions();
570
779
  }
571
780
  getModalContent() {
572
- const t = this.feedbackData.feedbackType === "up", e = this.config.positiveIcon || k, o = this.config.negativeIcon || w;
781
+ const t = this.feedbackData.feedbackType === "up", e = this.config.positiveIcon || T, o = this.config.negativeIcon || S;
573
782
  return `
574
783
  <div class="qaid-modal-header">
575
784
  <button type="button" class="${this.config.buttonClass ? `qaid-type-toggle qaid-type-toggle-custom ${this.config.buttonClass} ${t ? "qaid-btn-up" : "qaid-btn-down"}` : `qaid-type-toggle ${t ? "qaid-type-up" : "qaid-type-down"}`}" title="Click to switch">
@@ -599,8 +808,8 @@ class bt {
599
808
  o && o.addEventListener("click", () => {
600
809
  const n = this.feedbackData.feedbackType === "up" ? "down" : "up";
601
810
  this.feedbackData.feedbackType = n, this.config.buttonClass ? (o.classList.toggle("qaid-btn-up", n === "up"), o.classList.toggle("qaid-btn-down", n === "down")) : (o.classList.toggle("qaid-type-up", n === "up"), o.classList.toggle("qaid-type-down", n === "down"));
602
- const a = this.config.positiveIcon || k, s = this.config.negativeIcon || w;
603
- o.innerHTML = n === "up" ? a : s, this.feedbackId && fetch(`${this.config.endpoint}/${this.feedbackId}`, {
811
+ const a = this.config.positiveIcon || T, r = this.config.negativeIcon || S;
812
+ o.innerHTML = n === "up" ? a : r, this.feedbackId && fetch(`${this.config.endpoint}/${this.feedbackId}`, {
604
813
  method: "PATCH",
605
814
  headers: { "Content-Type": "application/json" },
606
815
  body: JSON.stringify({ feedbackType: n })
@@ -629,14 +838,124 @@ class bt {
629
838
  body: JSON.stringify({ message: null })
630
839
  }).catch((t) => console.error("Failed to finalize feedback:", t)), this.modalContainer && (this.modalContainer.remove(), this.modalContainer = null), this.backdrop && (this.backdrop.remove(), this.backdrop = null), document.removeEventListener("keydown", this.boundKeyDown), this.hideSelectedMarker(), this.state = "IDLE", this.feedbackId = null, this.feedbackData.feedbackType = null, this.feedbackData.elementSelector = null, this.feedbackData.elementText = null, this.selectedBounds.visible = !1;
631
840
  }
841
+ // ==================== Video Recording ====================
842
+ async startRecording() {
843
+ if (!(this.isRecording || this.state !== "IDLE"))
844
+ try {
845
+ this.networkCapture = Et(), this.videoRecorder = It({
846
+ maxDuration: this.config.videoOptions.maxDuration
847
+ }), this.videoRecorder.onTick((t) => {
848
+ this.updateRecordingTimer(t);
849
+ }), this.videoRecorder.onStop((t) => {
850
+ this.isRecording && (this.recordedBlob = t, this.isRecording = !1, this.removeRecordingIndicator(), document.removeEventListener("keydown", this.boundKeyDown), this.setButtonsDisabled(!1), t && t.size > 0 ? this.showRecordingPreview() : this.cleanupRecording());
851
+ }), await this.videoRecorder.start(), this.isRecording = !0, this.setButtonsDisabled(!0), this.showRecordingIndicator(), document.addEventListener("keydown", this.boundKeyDown);
852
+ } catch {
853
+ this.cleanupRecording();
854
+ }
855
+ }
856
+ async stopRecording() {
857
+ if (!(!this.isRecording || !this.videoRecorder)) {
858
+ try {
859
+ this.recordedBlob = await this.videoRecorder.stop();
860
+ } catch {
861
+ this.recordedBlob = null;
862
+ }
863
+ this.isRecording = !1, this.removeRecordingIndicator(), document.removeEventListener("keydown", this.boundKeyDown), this.recordedBlob && this.recordedBlob.size > 0 ? this.showRecordingPreview() : this.cleanupRecording();
864
+ }
865
+ }
866
+ showRecordingIndicator() {
867
+ this.recordingIndicator = document.createElement("div"), this.recordingIndicator.className = "qaid-recording-indicator", this.recordingIndicator.style.zIndex = String(this.config.zIndex + 100);
868
+ const t = document.createElement("div");
869
+ t.className = "qaid-recording-dot";
870
+ const e = document.createElement("span");
871
+ e.className = "qaid-recording-time", e.textContent = this.formatTime(this.config.videoOptions.maxDuration);
872
+ const o = document.createElement("button");
873
+ o.type = "button", o.className = "qaid-recording-stop", o.textContent = "Stop", o.addEventListener("click", () => this.stopRecording()), this.recordingIndicator.appendChild(t), this.recordingIndicator.appendChild(e), this.recordingIndicator.appendChild(o), document.body.appendChild(this.recordingIndicator);
874
+ }
875
+ updateRecordingTimer(t) {
876
+ if (!this.recordingIndicator) return;
877
+ const e = this.recordingIndicator.querySelector(".qaid-recording-time");
878
+ if (e) {
879
+ const o = Math.max(0, this.config.videoOptions.maxDuration - t);
880
+ e.textContent = this.formatTime(o);
881
+ }
882
+ }
883
+ formatTime(t) {
884
+ const e = Math.floor(t / 60), o = t % 60;
885
+ return `${e}:${o.toString().padStart(2, "0")}`;
886
+ }
887
+ removeRecordingIndicator() {
888
+ this.recordingIndicator && (this.recordingIndicator.remove(), this.recordingIndicator = null);
889
+ }
890
+ showRecordingPreview() {
891
+ if (!this.recordedBlob) return;
892
+ const t = URL.createObjectURL(this.recordedBlob);
893
+ this.videoPreview = document.createElement("div"), this.videoPreview.className = "qaid-video-preview", this.videoPreview.style.zIndex = String(this.config.zIndex + 100);
894
+ const e = document.createElement("div");
895
+ e.className = "qaid-video-preview-box";
896
+ const o = document.createElement("h3");
897
+ o.textContent = "Review your recording";
898
+ const n = document.createElement("video");
899
+ n.src = t, n.controls = !0, n.autoplay = !0, n.muted = !0;
900
+ const a = document.createElement("textarea");
901
+ a.placeholder = "Optional: Describe the issue you recorded...";
902
+ const r = document.createElement("div");
903
+ r.className = "qaid-video-preview-actions";
904
+ const l = document.createElement("button");
905
+ l.type = "button", l.className = "qaid-video-btn qaid-video-btn-cancel", l.textContent = "Cancel", l.addEventListener("click", () => this.cancelRecordingPreview());
906
+ const d = document.createElement("button");
907
+ d.type = "button", d.className = "qaid-video-btn qaid-video-btn-rerecord", d.textContent = "Re-record", d.addEventListener("click", () => {
908
+ this.cancelRecordingPreview(), this.startRecording();
909
+ });
910
+ const s = document.createElement("button");
911
+ s.type = "button", s.className = "qaid-video-btn qaid-video-btn-send", s.textContent = "Send", s.addEventListener("click", () => {
912
+ const c = a.value.trim() || null;
913
+ this.submitVideoFeedback(c, s);
914
+ }), r.appendChild(l), r.appendChild(d), r.appendChild(s), e.appendChild(o), e.appendChild(n), e.appendChild(a), e.appendChild(r), this.videoPreview.appendChild(e), document.body.appendChild(this.videoPreview), document.addEventListener("keydown", this.boundKeyDown);
915
+ }
916
+ cancelRecordingPreview() {
917
+ this.removeVideoPreview(), this.cleanupRecording();
918
+ }
919
+ removeVideoPreview() {
920
+ if (this.videoPreview) {
921
+ const t = this.videoPreview.querySelector("video");
922
+ t != null && t.src && URL.revokeObjectURL(t.src), this.videoPreview.remove(), this.videoPreview = null;
923
+ }
924
+ document.removeEventListener("keydown", this.boundKeyDown);
925
+ }
926
+ async submitVideoFeedback(t, e) {
927
+ if (!this.recordedBlob || this.isSendingVideo) return;
928
+ this.isSendingVideo = !0, e.disabled = !0, e.textContent = "Sending...";
929
+ const o = new FormData();
930
+ o.append("video", this.recordedBlob, `recording.${this.recordedBlob.type.includes("mp4") ? "mp4" : "webm"}`), o.append("pageUrl", window.location.href), o.append("visitorId", this.visitorId), this.config.apiKey && o.append("apiKey", this.config.apiKey), t && o.append("message", t), this.consoleCapture && o.append("consoleErrors", JSON.stringify(this.consoleCapture.errors)), this.networkCapture && o.append("networkErrors", JSON.stringify(this.networkCapture.errors));
931
+ try {
932
+ const n = await fetch(`${this.config.endpoint}/video`, {
933
+ method: "POST",
934
+ body: o
935
+ });
936
+ n.ok || console.error("Failed to submit video feedback:", await n.text());
937
+ } catch (n) {
938
+ console.error("Failed to submit video feedback:", n);
939
+ }
940
+ this.isSendingVideo = !1, this.removeVideoPreview(), this.cleanupRecording();
941
+ }
942
+ cleanupRecording() {
943
+ this.isRecording = !1, this.removeRecordingIndicator(), this.videoRecorder && (this.videoRecorder.destroy(), this.videoRecorder = null), this.networkCapture && (this.networkCapture.restore(), this.networkCapture = null), this.recordedBlob && (this.recordedBlob = null), this.setButtonsDisabled(!1);
944
+ }
945
+ setButtonsDisabled(t) {
946
+ if (!this.container) return;
947
+ this.container.querySelectorAll("button.qaid-btn, button.qaid-btn-structural").forEach((o) => {
948
+ t ? o.classList.contains("qaid-btn-record") || (o.disabled = !0, o.style.opacity = "0.5") : (o.disabled = !1, o.style.opacity = "");
949
+ });
950
+ }
632
951
  /**
633
952
  * Destroy the embed and clean up all resources
634
953
  */
635
954
  destroy() {
636
- this.consoleCapture && (this.consoleCapture.restore(), this.consoleCapture = null), window.removeEventListener("resize", this.boundResize), document.removeEventListener("keydown", this.boundKeyDown), C("qaid-highlight"), document.body.classList.remove("qaid-targeting", "qaid-type-up"), this.container && (this.isUserProvidedContainer ? (this.container.innerHTML = "", this.container.classList.remove("qaid-widget", `qaid-${this.config.position}`)) : this.container.remove(), this.container = null), this.removeTargetingOverlay(), this.hideSelectedMarker(), this.modalContainer && (this.modalContainer.remove(), this.modalContainer = null), this.backdrop && (this.backdrop.remove(), this.backdrop = null), this.tooltipElement && (this.tooltipElement.remove(), this.tooltipElement = null), Z();
955
+ this.cleanupRecording(), this.removeVideoPreview(), this.consoleCapture && (this.consoleCapture.restore(), this.consoleCapture = null), window.removeEventListener("resize", this.boundResize), document.removeEventListener("keydown", this.boundKeyDown), I("qaid-highlight"), document.body.classList.remove("qaid-targeting", "qaid-type-up"), this.container && (this.isUserProvidedContainer ? (this.container.innerHTML = "", this.container.classList.remove("qaid-widget", `qaid-${this.config.position}`, "qaid-incognito")) : this.container.remove(), this.container = null), this.removeTargetingOverlay(), this.hideSelectedMarker(), this.modalContainer && (this.modalContainer.remove(), this.modalContainer = null), this.backdrop && (this.backdrop.remove(), this.backdrop = null), this.tooltipElement && (this.tooltipElement.remove(), this.tooltipElement = null), dt();
637
956
  }
638
957
  }
639
- function vt() {
958
+ function Ht() {
640
959
  var e;
641
960
  const i = document.querySelector(
642
961
  'script[type="application/json"][data-feedback-config]'
@@ -650,61 +969,73 @@ function vt() {
650
969
  return null;
651
970
  }
652
971
  }
653
- function yt(i) {
972
+ function Ot(i) {
654
973
  const t = i.getAttribute("data-endpoint");
655
974
  if (!t) return null;
656
- const e = i.getAttribute("data-position"), o = i.getAttribute("data-zindex"), n = i.getAttribute("data-positive-color"), a = i.getAttribute("data-negative-color"), s = i.getAttribute("data-marker-color"), l = i.getAttribute("data-container"), r = i.getAttribute("data-button-class"), c = i.getAttribute("data-skip-targeting"), p = i.getAttribute("data-incognito"), g = i.getAttribute("data-button-size"), h = i.getAttribute("data-offset-x"), u = i.getAttribute("data-offset-y"), m = i.getAttribute("data-modal-width"), b = i.getAttribute("data-backdrop-opacity"), f = i.getAttribute("data-font-family"), v = i.getAttribute("data-font-size"), S = i.getAttribute("data-tooltip"), E = i.getAttribute("data-banner-text"), I = i.getAttribute("data-banner-hint"), z = i.getAttribute("data-modal-title"), L = i.getAttribute("data-modal-subtitle"), M = i.getAttribute("data-placeholder"), $ = i.getAttribute("data-submit-button"), A = i.getAttribute("data-skip-button"), N = i.getAttribute("data-positive-icon"), P = i.getAttribute("data-negative-icon"), W = i.getAttribute("data-api-key"), U = i.getAttribute("data-capture-screenshot"), y = i.getAttribute("data-screenshot-quality"), q = i.getAttribute("data-screenshot-max-width"), x = i.getAttribute("data-screenshot-max-height");
975
+ const e = i.getAttribute("data-position"), o = i.getAttribute("data-zindex"), n = i.getAttribute("data-positive-color"), a = i.getAttribute("data-negative-color"), r = i.getAttribute("data-marker-color"), l = i.getAttribute("data-container"), d = i.getAttribute("data-button-class"), s = i.getAttribute("data-skip-targeting"), c = i.getAttribute("data-incognito"), p = i.getAttribute("data-button-size"), u = i.getAttribute("data-offset-x"), f = i.getAttribute("data-offset-y"), g = i.getAttribute("data-modal-width"), b = i.getAttribute("data-backdrop-opacity"), m = i.getAttribute("data-font-family"), v = i.getAttribute("data-font-size"), y = i.getAttribute("data-tooltip"), q = i.getAttribute("data-banner-text"), M = i.getAttribute("data-banner-hint"), D = i.getAttribute("data-modal-title"), z = i.getAttribute("data-modal-subtitle"), R = i.getAttribute("data-placeholder"), B = i.getAttribute("data-submit-button"), A = i.getAttribute("data-skip-button"), X = i.getAttribute("data-positive-icon"), _ = i.getAttribute("data-negative-icon"), j = i.getAttribute("data-api-key"), K = i.getAttribute("data-capture-screenshot"), k = i.getAttribute("data-screenshot-quality"), C = i.getAttribute("data-screenshot-max-width"), E = i.getAttribute("data-screenshot-max-height"), Y = i.getAttribute("data-capture-video"), J = i.getAttribute("data-hide-thumbs"), $ = i.getAttribute("data-video-max-duration"), G = i.getAttribute("data-screenshot-method");
657
976
  return {
658
977
  endpoint: t,
659
- apiKey: W ?? void 0,
660
- captureScreenshot: U === "true" ? !0 : void 0,
661
- screenshotOptions: y || q || x ? {
662
- quality: y ? parseFloat(y) : void 0,
663
- maxWidth: q ? parseInt(q, 10) : void 0,
664
- maxHeight: x ? parseInt(x, 10) : void 0
978
+ apiKey: j ?? void 0,
979
+ captureScreenshot: K === "true" ? !0 : void 0,
980
+ screenshotOptions: k || C || E ? {
981
+ quality: k ? parseFloat(k) : void 0,
982
+ maxWidth: C ? parseInt(C, 10) : void 0,
983
+ maxHeight: E ? parseInt(E, 10) : void 0
665
984
  } : void 0,
666
985
  container: l ?? void 0,
667
- buttonClass: r ?? void 0,
986
+ buttonClass: d ?? void 0,
668
987
  position: e ?? void 0,
669
988
  zIndex: o ? parseInt(o, 10) : void 0,
670
- skipTargeting: c === "true" ? !0 : void 0,
671
- incognito: p === "true" ? !0 : void 0,
672
- buttonSize: g ?? void 0,
673
- offset: h || u ? {
674
- x: h ? parseInt(h, 10) : void 0,
675
- y: u ? parseInt(u, 10) : void 0
989
+ skipTargeting: s === "true" ? !0 : void 0,
990
+ incognito: c === "true" ? !0 : void 0,
991
+ buttonSize: p ?? void 0,
992
+ offset: u || f ? {
993
+ x: u ? parseInt(u, 10) : void 0,
994
+ y: f ? parseInt(f, 10) : void 0
676
995
  } : void 0,
677
- modalWidth: m ? parseInt(m, 10) : void 0,
996
+ modalWidth: g ? parseInt(g, 10) : void 0,
678
997
  backdropOpacity: b ? parseFloat(b) : void 0,
679
- fontFamily: f ?? void 0,
998
+ fontFamily: m ?? void 0,
680
999
  fontSize: v ? parseInt(v, 10) : void 0,
681
1000
  colors: {
682
1001
  positive: n ?? void 0,
683
1002
  negative: a ?? void 0,
684
- marker: s ?? void 0
1003
+ marker: r ?? void 0
685
1004
  },
686
- text: S || E || I || z || L || M || $ || A ? {
687
- tooltip: S ?? void 0,
688
- bannerText: E ?? void 0,
689
- bannerHint: I ?? void 0,
690
- modalTitle: z ?? void 0,
691
- modalSubtitle: L ?? void 0,
692
- placeholder: M ?? void 0,
693
- submitButton: $ ?? void 0,
1005
+ text: y || q || M || D || z || R || B || A ? {
1006
+ tooltip: y ?? void 0,
1007
+ bannerText: q ?? void 0,
1008
+ bannerHint: M ?? void 0,
1009
+ modalTitle: D ?? void 0,
1010
+ modalSubtitle: z ?? void 0,
1011
+ placeholder: R ?? void 0,
1012
+ submitButton: B ?? void 0,
694
1013
  skipButton: A ?? void 0
695
1014
  } : void 0,
696
- positiveIcon: N ?? void 0,
697
- negativeIcon: P ?? void 0
1015
+ positiveIcon: X ?? void 0,
1016
+ negativeIcon: _ ?? void 0,
1017
+ screenshotMethod: G ?? void 0,
1018
+ captureVideo: Y === "true" ? !0 : void 0,
1019
+ hideThumbs: J === "true" ? !0 : void 0,
1020
+ videoOptions: $ ? {
1021
+ maxDuration: parseInt($, 10)
1022
+ } : void 0
698
1023
  };
699
1024
  }
700
1025
  if (typeof document < "u") {
701
1026
  const i = () => {
702
- const t = document.currentScript, e = vt(), o = t ? yt(t) : null, n = e ?? o;
703
- n != null && n.endpoint && new bt(n);
1027
+ const t = document.currentScript, e = Ht(), o = t ? Ot(t) : null, n = e ?? o;
1028
+ n != null && n.endpoint && new Pt(n);
704
1029
  };
705
1030
  document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", i) : i();
706
1031
  }
707
1032
  export {
708
- bt as FeedbackEmbed
1033
+ Pt as FeedbackEmbed,
1034
+ At as captureDomScreenshot,
1035
+ Et as captureNetworkErrors,
1036
+ It as createVideoRecorder,
1037
+ St as getSupportedMimeType,
1038
+ Ft as isDomScreenshotSupported,
1039
+ Tt as isVideoRecordingSupported
709
1040
  };
710
1041
  //# sourceMappingURL=qaid.js.map