@qaiddev/thumbs-embed 1.0.9 → 1.0.11
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/console-capture.d.ts +20 -0
- package/dist/dom-utils.d.ts +37 -0
- package/dist/element-selector.d.ts +33 -0
- package/dist/embed.d.ts +109 -0
- package/dist/icons.d.ts +6 -0
- package/dist/index.d.ts +38 -411
- package/dist/modal-positioning.d.ts +46 -0
- package/dist/network-capture.d.ts +13 -0
- package/dist/qaid.js +254 -209
- package/dist/qaid.js.map +1 -1
- package/dist/qaid.umd.cjs +6 -6
- package/dist/qaid.umd.cjs.map +1 -1
- package/dist/screenshot-dom.d.ts +27 -0
- package/dist/screenshot.d.ts +17 -0
- package/dist/styles.d.ts +44 -0
- package/dist/types.d.ts +237 -0
- package/dist/video-capture.d.ts +34 -0
- package/package.json +2 -3
package/dist/qaid.js
CHANGED
|
@@ -2,26 +2,26 @@ const E = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none"
|
|
|
2
2
|
<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"/>
|
|
3
3
|
</svg>`, T = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
4
4
|
<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"/>
|
|
5
|
-
</svg>`,
|
|
5
|
+
</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">
|
|
6
6
|
<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"/>
|
|
7
|
-
</svg>`, Q = "button{cursor:pointer}.qaid-buttons{display:flex;gap:.5rem}.qaid-buttons.qaid-vertical{flex-direction:column}.qaid-buttons.qaid-auto-container{position:fixed;z-index:50}.qaid-buttons.qaid-auto-container.qaid-bottom-right{bottom:1rem;right:1rem}.qaid-buttons.qaid-auto-container.qaid-bottom-left{bottom:1rem;left:1rem}.qaid-buttons.qaid-auto-container.qaid-top-right{top:1rem;right:1rem}.qaid-buttons.qaid-auto-container.qaid-top-left{top:1rem;left:1rem}.qaid-buttons.qaid-incognito{opacity:0;transition:opacity .2s ease-in-out}.qaid-buttons.qaid-incognito:hover{opacity:1}button.qaid-btn-structural{display:inline-flex;align-items:center;justify-content:center;cursor:pointer;-webkit-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-buttons,.qaid-buttons *,.qaid-modal-container,.qaid-modal-container *{cursor:pointer!important}.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;inset:0;z-index:40;pointer-events:none}.qaid-capture-layer{position:fixed;inset:0;pointer-events:none;z-index:9999}@keyframes qaid-slideDown{0%{transform:translateY(-100%)}to{transform:translateY(0)}}.qaid-vignette{position:fixed;inset: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-highlight-box{position:fixed;top:0;left:0;pointer-events:none;z-index:41;display:none;border:3px solid color-mix(in srgb,var(--qaid-negative) 80%,transparent);border-radius:2px;background:color-mix(in srgb,var(--qaid-negative) 8%,transparent);will-change:transform,width,height}.qaid-type-up .qaid-highlight-box{border-color:color-mix(in srgb,var(--qaid-positive) 80%,transparent);background:color-mix(in srgb,var(--qaid-positive) 8%,transparent)}.qaid-scope{position:fixed;width:80px;height:80px;pointer-events:none;z-index:43;transform:translate(-50%,-50%)}.qaid-scope-ring{position:absolute;inset: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;inset: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-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;inset: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;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;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;appearance:none}button.qaid-recording-stop:hover{background:#b91c1c}.qaid-video-preview{position:fixed;inset: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;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)}", tt = "body.qaid-targeting,body.qaid-targeting *{cursor:none!important}";
|
|
7
|
+
</svg>`, et = "button{cursor:pointer}.qaid-buttons{display:flex;gap:.5rem}.qaid-buttons.qaid-vertical{flex-direction:column}.qaid-buttons.qaid-auto-container{position:fixed;z-index:50}.qaid-buttons.qaid-auto-container.qaid-bottom-right{bottom:1rem;right:1rem}.qaid-buttons.qaid-auto-container.qaid-bottom-left{bottom:1rem;left:1rem}.qaid-buttons.qaid-auto-container.qaid-top-right{top:1rem;right:1rem}.qaid-buttons.qaid-auto-container.qaid-top-left{top:1rem;left:1rem}.qaid-buttons.qaid-incognito{opacity:0;transition:opacity .2s ease-in-out}.qaid-buttons.qaid-incognito:hover{opacity:1}.qaid-buttons{position:relative}.qaid-dismiss-btn{position:absolute;width:20px;height:20px;padding:0;border:none;border-radius:50%;background:#0006;color:#fff;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .15s,background .15s;cursor:pointer;-webkit-appearance:none;appearance:none}.qaid-dismiss-btn:hover{background:#0009}.qaid-buttons:hover .qaid-dismiss-btn{opacity:1}.qaid-bottom-right .qaid-dismiss-btn{bottom:100%;right:0;margin-bottom:4px}.qaid-bottom-left .qaid-dismiss-btn{bottom:100%;left:0;margin-bottom:4px}.qaid-top-right .qaid-dismiss-btn{top:100%;right:0;margin-top:4px}.qaid-top-left .qaid-dismiss-btn{top:100%;left:0;margin-top:4px}button.qaid-btn-structural{display:inline-flex;align-items:center;justify-content:center;cursor:pointer;-webkit-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-buttons,.qaid-buttons *,.qaid-modal-container,.qaid-modal-container *{cursor:pointer!important}.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;inset:0;z-index:40;pointer-events:none}.qaid-capture-layer{position:fixed;inset:0;pointer-events:none;z-index:9999}@keyframes qaid-slideDown{0%{transform:translateY(-100%)}to{transform:translateY(0)}}.qaid-vignette{position:fixed;inset: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-highlight-box{position:fixed;top:0;left:0;pointer-events:none;z-index:41;display:none;border:3px solid color-mix(in srgb,var(--qaid-negative) 80%,transparent);border-radius:2px;background:color-mix(in srgb,var(--qaid-negative) 8%,transparent);will-change:transform,width,height}.qaid-type-up .qaid-highlight-box{border-color:color-mix(in srgb,var(--qaid-positive) 80%,transparent);background:color-mix(in srgb,var(--qaid-positive) 8%,transparent)}.qaid-scope{position:fixed;width:80px;height:80px;pointer-events:none;z-index:43;transform:translate(-50%,-50%)}.qaid-scope-ring{position:absolute;inset: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;inset: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-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;inset: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;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;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;appearance:none}button.qaid-recording-stop:hover{background:#b91c1c}.qaid-video-preview{position:fixed;inset: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;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)}", it = "body.qaid-targeting,body.qaid-targeting *{cursor:none!important}";
|
|
8
8
|
let w = 0;
|
|
9
|
-
const
|
|
9
|
+
const ot = "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;--qaid-hover-up-bg:var(--qaid-positive);--qaid-hover-up-color:#fff;--qaid-hover-down-bg:var(--qaid-negative);--qaid-hover-down-color:#fff}button.qaid-btn:hover{transform:scale(1.05)}button.qaid-btn-up:hover{background:var(--qaid-hover-up-bg);color:var(--qaid-hover-up-color)}button.qaid-btn-down:hover{background:var(--qaid-hover-down-bg);color:var(--qaid-hover-down-color)}button.qaid-btn svg{width:var(--qaid-icon-size);height:var(--qaid-icon-size)}", nt = {
|
|
10
10
|
small: 36,
|
|
11
11
|
medium: 48,
|
|
12
12
|
large: 64
|
|
13
|
-
},
|
|
13
|
+
}, st = {
|
|
14
14
|
small: 18,
|
|
15
15
|
medium: 24,
|
|
16
16
|
large: 32
|
|
17
17
|
};
|
|
18
|
-
function
|
|
19
|
-
const [o, n,
|
|
20
|
-
return 0.2126 * o + 0.7152 * n + 0.0722 *
|
|
18
|
+
function at(e, t, i) {
|
|
19
|
+
const [o, n, s] = [e, t, i].map((r) => (r = r / 255, r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4)));
|
|
20
|
+
return 0.2126 * o + 0.7152 * n + 0.0722 * s;
|
|
21
21
|
}
|
|
22
|
-
function
|
|
22
|
+
function rt(e) {
|
|
23
23
|
if (e.startsWith("#")) {
|
|
24
|
-
const i = e.slice(1), o = i.length === 3 ? i.split("").map((
|
|
24
|
+
const i = e.slice(1), o = i.length === 3 ? i.split("").map((s) => s + s).join("") : i, n = parseInt(o, 16);
|
|
25
25
|
return {
|
|
26
26
|
r: n >> 16 & 255,
|
|
27
27
|
g: n >> 8 & 255,
|
|
@@ -35,57 +35,57 @@ function at(e) {
|
|
|
35
35
|
b: parseInt(t[3])
|
|
36
36
|
} : null;
|
|
37
37
|
}
|
|
38
|
-
function
|
|
39
|
-
const t =
|
|
40
|
-
return t &&
|
|
38
|
+
function dt(e) {
|
|
39
|
+
const t = rt(e);
|
|
40
|
+
return t && at(t.r, t.g, t.b) > 0.4 ? "black" : "white";
|
|
41
41
|
}
|
|
42
|
-
function
|
|
42
|
+
function ct(e = {}) {
|
|
43
43
|
const {
|
|
44
44
|
positiveColor: t = "rgb(0, 200, 83)",
|
|
45
45
|
negativeColor: i = "rgb(255, 0, 0)",
|
|
46
46
|
markerColor: o = "#6366f1",
|
|
47
47
|
buttonSize: n = "medium",
|
|
48
|
-
modalWidth:
|
|
48
|
+
modalWidth: s = 400,
|
|
49
49
|
backdropOpacity: r = 0.3,
|
|
50
50
|
fontFamily: l = "system-ui, -apple-system, sans-serif",
|
|
51
51
|
fontSize: d = 16
|
|
52
|
-
} = e,
|
|
52
|
+
} = e, a = nt[n], c = st[n], h = dt(o);
|
|
53
53
|
return {
|
|
54
54
|
"--qaid-positive": t,
|
|
55
55
|
"--qaid-negative": i,
|
|
56
56
|
"--qaid-marker": o,
|
|
57
57
|
"--qaid-marker-text": h,
|
|
58
|
-
"--qaid-btn-size": `${
|
|
58
|
+
"--qaid-btn-size": `${a}px`,
|
|
59
59
|
"--qaid-icon-size": `${c}px`,
|
|
60
|
-
"--qaid-modal-width": `${
|
|
60
|
+
"--qaid-modal-width": `${s}px`,
|
|
61
61
|
"--qaid-backdrop-opacity": String(r),
|
|
62
62
|
"--qaid-font-family": l,
|
|
63
63
|
"--qaid-font-size": `${d}px`
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
-
function
|
|
66
|
+
function lt(e, t) {
|
|
67
67
|
for (const [i, o] of Object.entries(t))
|
|
68
68
|
e.style.setProperty(i, o);
|
|
69
69
|
}
|
|
70
70
|
function z() {
|
|
71
|
-
return
|
|
71
|
+
return et + ot;
|
|
72
72
|
}
|
|
73
|
-
function
|
|
73
|
+
function ht() {
|
|
74
74
|
if (w++, w > 1) return;
|
|
75
75
|
const e = document.createElement("style");
|
|
76
|
-
e.id = "qaid-styles", e.textContent =
|
|
76
|
+
e.id = "qaid-styles", e.textContent = it, document.head.appendChild(e);
|
|
77
77
|
}
|
|
78
|
-
function
|
|
78
|
+
function ut() {
|
|
79
79
|
if (!(w <= 0) && (w--, w === 0)) {
|
|
80
80
|
const e = document.getElementById("qaid-styles");
|
|
81
81
|
e && e.remove();
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
const
|
|
85
|
-
function
|
|
84
|
+
const pt = ["data-comp", "data-qa", "data-testid", "data-id"];
|
|
85
|
+
function F(e, t = document.body) {
|
|
86
86
|
let i = e;
|
|
87
87
|
for (; i && i !== t; ) {
|
|
88
|
-
for (const o of
|
|
88
|
+
for (const o of pt) {
|
|
89
89
|
const n = i.getAttribute(o);
|
|
90
90
|
if (n)
|
|
91
91
|
return `${o}="${n}"`;
|
|
@@ -94,35 +94,35 @@ function V(e, t = document.body) {
|
|
|
94
94
|
}
|
|
95
95
|
return null;
|
|
96
96
|
}
|
|
97
|
-
function
|
|
97
|
+
function mt(e, t = 100) {
|
|
98
98
|
const i = e.textContent?.trim().slice(0, t) || "";
|
|
99
99
|
return i.length === t ? i + "..." : i;
|
|
100
100
|
}
|
|
101
|
-
function
|
|
101
|
+
function ft(e) {
|
|
102
102
|
let t = 1, i = e.previousElementSibling;
|
|
103
103
|
for (; i; )
|
|
104
104
|
t++, i = i.previousElementSibling;
|
|
105
105
|
return t;
|
|
106
106
|
}
|
|
107
|
-
function
|
|
107
|
+
function bt(e) {
|
|
108
108
|
const t = [];
|
|
109
109
|
let i = e;
|
|
110
110
|
for (; i && i !== document.body && i !== document.documentElement; ) {
|
|
111
|
-
const o = i.tagName.toLowerCase(), n =
|
|
111
|
+
const o = i.tagName.toLowerCase(), n = ft(i);
|
|
112
112
|
t.unshift(`${o}:nth-child(${n})`), i = i.parentElement;
|
|
113
113
|
}
|
|
114
114
|
return t.length > 0 ? `body > ${t.join(" > ")}` : "body";
|
|
115
115
|
}
|
|
116
|
-
function
|
|
116
|
+
function gt(e) {
|
|
117
117
|
return e.replace(/([!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g, "\\$1");
|
|
118
118
|
}
|
|
119
|
-
function
|
|
120
|
-
const t =
|
|
121
|
-
return t ? `[${t}]` : e.id ? `#${
|
|
119
|
+
function vt(e) {
|
|
120
|
+
const t = F(e);
|
|
121
|
+
return t ? `[${t}]` : e.id ? `#${gt(e.id)}` : bt(e);
|
|
122
122
|
}
|
|
123
|
-
function
|
|
124
|
-
const t =
|
|
125
|
-
return { selector:
|
|
123
|
+
function yt(e) {
|
|
124
|
+
const t = mt(e), i = F(e);
|
|
125
|
+
return { selector: vt(e), text: t, dataAttr: i };
|
|
126
126
|
}
|
|
127
127
|
const U = {
|
|
128
128
|
width: 400,
|
|
@@ -131,79 +131,79 @@ const U = {
|
|
|
131
131
|
gap: 8,
|
|
132
132
|
viewportPadding: 16
|
|
133
133
|
};
|
|
134
|
-
function
|
|
135
|
-
const
|
|
134
|
+
function wt(e, t, i, o, n) {
|
|
135
|
+
const s = e.y, r = t - (e.y + e.height);
|
|
136
136
|
if (r >= i + o)
|
|
137
137
|
return {
|
|
138
138
|
top: e.y + e.height + o,
|
|
139
139
|
position: "below"
|
|
140
140
|
};
|
|
141
|
-
if (
|
|
141
|
+
if (s >= i + o)
|
|
142
142
|
return {
|
|
143
143
|
top: e.y - i - o,
|
|
144
144
|
position: "above"
|
|
145
145
|
};
|
|
146
|
-
const l = r >
|
|
146
|
+
const l = r > s ? "below" : "above";
|
|
147
147
|
let d;
|
|
148
148
|
return l === "below" ? d = Math.min(
|
|
149
149
|
e.y + e.height + o,
|
|
150
150
|
t - i - n
|
|
151
151
|
) : d = Math.max(n, e.y - i - o), { top: d, position: l };
|
|
152
152
|
}
|
|
153
|
-
function
|
|
154
|
-
let
|
|
155
|
-
return
|
|
153
|
+
function xt(e, t, i, o) {
|
|
154
|
+
let s = e.x + e.width / 2 - i / 2;
|
|
155
|
+
return s = Math.max(o, Math.min(s, t - i - o)), s;
|
|
156
156
|
}
|
|
157
|
-
function
|
|
157
|
+
function qt(e, t, i, o = 24, n = 24) {
|
|
158
158
|
const r = e.clickX - t - n / 2;
|
|
159
159
|
return Math.max(o, Math.min(r, i - o - n / 2));
|
|
160
160
|
}
|
|
161
|
-
function
|
|
162
|
-
const n = o.height + o.arrowHeight,
|
|
161
|
+
function kt(e, t, i, o = U) {
|
|
162
|
+
const n = o.height + o.arrowHeight, s = wt(
|
|
163
163
|
e,
|
|
164
164
|
i,
|
|
165
165
|
n,
|
|
166
166
|
o.gap,
|
|
167
167
|
o.viewportPadding
|
|
168
|
-
), r =
|
|
168
|
+
), r = xt(
|
|
169
169
|
e,
|
|
170
170
|
t,
|
|
171
171
|
o.width,
|
|
172
172
|
o.viewportPadding
|
|
173
173
|
);
|
|
174
174
|
return {
|
|
175
|
-
top:
|
|
175
|
+
top: s.top,
|
|
176
176
|
left: r,
|
|
177
|
-
position:
|
|
177
|
+
position: s.position
|
|
178
178
|
};
|
|
179
179
|
}
|
|
180
|
-
function
|
|
181
|
-
const n =
|
|
180
|
+
function Ct(e, t, i, o = U) {
|
|
181
|
+
const n = kt(e, t, i, o), s = qt(
|
|
182
182
|
e,
|
|
183
183
|
n.left,
|
|
184
184
|
o.width
|
|
185
185
|
);
|
|
186
186
|
return {
|
|
187
187
|
modal: n,
|
|
188
|
-
arrow: { left:
|
|
188
|
+
arrow: { left: s }
|
|
189
189
|
};
|
|
190
190
|
}
|
|
191
|
-
const
|
|
192
|
-
function
|
|
193
|
-
const t = [], i = console.error, o = console.warn, n = console.log,
|
|
191
|
+
const St = 20;
|
|
192
|
+
function Et(e) {
|
|
193
|
+
const t = [], i = console.error, o = console.warn, n = console.log, s = (r, l) => {
|
|
194
194
|
const d = {
|
|
195
|
-
message: l.map((
|
|
195
|
+
message: l.map((a) => String(a)).join(" "),
|
|
196
196
|
timestamp: Date.now(),
|
|
197
197
|
level: r
|
|
198
198
|
};
|
|
199
|
-
t.length >=
|
|
199
|
+
t.length >= St && t.shift(), t.push(d), e && e(d);
|
|
200
200
|
};
|
|
201
201
|
return console.error = function(...r) {
|
|
202
|
-
|
|
202
|
+
s("error", r), i.apply(console, r);
|
|
203
203
|
}, console.warn = function(...r) {
|
|
204
|
-
|
|
204
|
+
s("warn", r), o.apply(console, r);
|
|
205
205
|
}, console.log = function(...r) {
|
|
206
|
-
|
|
206
|
+
s("log", r), n.apply(console, r);
|
|
207
207
|
}, {
|
|
208
208
|
errors: t,
|
|
209
209
|
restore: () => {
|
|
@@ -211,16 +211,16 @@ function Ct(e) {
|
|
|
211
211
|
}
|
|
212
212
|
};
|
|
213
213
|
}
|
|
214
|
-
const
|
|
214
|
+
const Tt = 20, P = 4096;
|
|
215
215
|
function q(e) {
|
|
216
216
|
if (e == null) return;
|
|
217
217
|
const t = typeof e == "string" ? e : JSON.stringify(e);
|
|
218
|
-
return t.length >
|
|
218
|
+
return t.length > P ? t.slice(0, P) + "…[truncated]" : t;
|
|
219
219
|
}
|
|
220
|
-
function
|
|
221
|
-
e.length >=
|
|
220
|
+
function O(e, t) {
|
|
221
|
+
e.length >= Tt && e.shift(), e.push(t);
|
|
222
222
|
}
|
|
223
|
-
async function
|
|
223
|
+
async function It(e) {
|
|
224
224
|
try {
|
|
225
225
|
const t = await e.clone().text();
|
|
226
226
|
return q(t);
|
|
@@ -228,40 +228,40 @@ async function Et(e) {
|
|
|
228
228
|
return;
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
|
-
function
|
|
231
|
+
function Lt() {
|
|
232
232
|
const e = [], t = window.fetch;
|
|
233
|
-
window.fetch = async function(n,
|
|
234
|
-
const r = typeof n == "string" ? n : n instanceof URL ? n.toString() : n.url, l =
|
|
233
|
+
window.fetch = async function(n, s) {
|
|
234
|
+
const r = typeof n == "string" ? n : n instanceof URL ? n.toString() : n.url, l = s?.method ?? (typeof n == "object" && "method" in n ? n.method : "GET");
|
|
235
235
|
let d;
|
|
236
|
-
|
|
237
|
-
const
|
|
238
|
-
if (
|
|
239
|
-
const c = await
|
|
240
|
-
|
|
236
|
+
s?.body && (d = q(s.body));
|
|
237
|
+
const a = await t.apply(window, [n, s]);
|
|
238
|
+
if (a.status >= 400) {
|
|
239
|
+
const c = await It(a);
|
|
240
|
+
O(e, {
|
|
241
241
|
url: r,
|
|
242
242
|
method: l.toUpperCase(),
|
|
243
|
-
status:
|
|
244
|
-
statusText:
|
|
243
|
+
status: a.status,
|
|
244
|
+
statusText: a.statusText,
|
|
245
245
|
requestBody: d,
|
|
246
246
|
responseBody: c,
|
|
247
247
|
timestamp: Date.now()
|
|
248
248
|
});
|
|
249
249
|
}
|
|
250
|
-
return
|
|
250
|
+
return a;
|
|
251
251
|
};
|
|
252
252
|
const i = XMLHttpRequest.prototype.open, o = XMLHttpRequest.prototype.send;
|
|
253
|
-
return XMLHttpRequest.prototype.open = function(n,
|
|
254
|
-
return this._qaid_method = n, this._qaid_url = typeof
|
|
253
|
+
return XMLHttpRequest.prototype.open = function(n, s, ...r) {
|
|
254
|
+
return this._qaid_method = n, this._qaid_url = typeof s == "string" ? s : s.toString(), i.apply(this, [n, s, ...r]);
|
|
255
255
|
}, XMLHttpRequest.prototype.send = function(n) {
|
|
256
|
-
const
|
|
257
|
-
return
|
|
258
|
-
|
|
259
|
-
url:
|
|
260
|
-
method:
|
|
261
|
-
status:
|
|
262
|
-
statusText:
|
|
256
|
+
const s = this, r = n ? q(n) : void 0;
|
|
257
|
+
return s.addEventListener("load", function() {
|
|
258
|
+
s.status >= 400 && O(e, {
|
|
259
|
+
url: s._qaid_url,
|
|
260
|
+
method: s._qaid_method.toUpperCase(),
|
|
261
|
+
status: s.status,
|
|
262
|
+
statusText: s.statusText,
|
|
263
263
|
requestBody: r,
|
|
264
|
-
responseBody: q(
|
|
264
|
+
responseBody: q(s.responseText),
|
|
265
265
|
timestamp: Date.now()
|
|
266
266
|
});
|
|
267
267
|
}), o.apply(this, [n]);
|
|
@@ -272,10 +272,10 @@ function Tt() {
|
|
|
272
272
|
}
|
|
273
273
|
};
|
|
274
274
|
}
|
|
275
|
-
function
|
|
275
|
+
function Ht() {
|
|
276
276
|
return typeof navigator < "u" && !!navigator.mediaDevices && typeof navigator.mediaDevices.getDisplayMedia == "function" && typeof MediaRecorder < "u";
|
|
277
277
|
}
|
|
278
|
-
function
|
|
278
|
+
function Dt() {
|
|
279
279
|
if (typeof MediaRecorder > "u") return "";
|
|
280
280
|
const e = [
|
|
281
281
|
"video/webm;codecs=vp9",
|
|
@@ -288,19 +288,19 @@ function Lt() {
|
|
|
288
288
|
return t;
|
|
289
289
|
return "";
|
|
290
290
|
}
|
|
291
|
-
function
|
|
291
|
+
function Mt(e = {}) {
|
|
292
292
|
const t = e.maxDuration ?? 15, i = e.videoBitsPerSecond ?? 8e5;
|
|
293
|
-
let o = null, n = null,
|
|
294
|
-
function
|
|
295
|
-
d !== null && (clearInterval(d), d = null), p !== null && (clearTimeout(p), p = null), o && (o.getTracks().forEach((m) => m.stop()), o = null), n = null,
|
|
293
|
+
let o = null, n = null, s = [], r = null, l = null, d = null, a = 0, c = null, h = null, u = !1, p = null;
|
|
294
|
+
function g() {
|
|
295
|
+
d !== null && (clearInterval(d), d = null), p !== null && (clearTimeout(p), p = null), o && (o.getTracks().forEach((m) => m.stop()), o = null), n = null, s = [], r = null, l = null, c = null, h = null;
|
|
296
296
|
}
|
|
297
297
|
function f() {
|
|
298
298
|
u || (u = !0, n && n.state !== "inactive" && n.stop());
|
|
299
299
|
}
|
|
300
300
|
return {
|
|
301
301
|
async start() {
|
|
302
|
-
u = !1,
|
|
303
|
-
const m =
|
|
302
|
+
u = !1, s = [];
|
|
303
|
+
const m = Dt();
|
|
304
304
|
if (!m)
|
|
305
305
|
throw new Error("No supported video MIME type found");
|
|
306
306
|
o = await navigator.mediaDevices.getDisplayMedia({
|
|
@@ -317,16 +317,16 @@ function Rt(e = {}) {
|
|
|
317
317
|
}), n = new MediaRecorder(o, {
|
|
318
318
|
mimeType: m,
|
|
319
319
|
videoBitsPerSecond: i
|
|
320
|
-
}), n.ondataavailable = (
|
|
321
|
-
|
|
320
|
+
}), n.ondataavailable = (b) => {
|
|
321
|
+
b.data.size > 0 && s.push(b.data);
|
|
322
322
|
}, n.onstop = () => {
|
|
323
|
-
const
|
|
324
|
-
c && c(
|
|
323
|
+
const b = new Blob(s, { type: m });
|
|
324
|
+
c && c(b), l && l(b), o && o.getTracks().forEach((x) => x.stop());
|
|
325
325
|
}, n.onerror = () => {
|
|
326
326
|
h && h(new Error("MediaRecorder error"));
|
|
327
|
-
}, n.start(1e3),
|
|
328
|
-
const
|
|
329
|
-
r && r(
|
|
327
|
+
}, n.start(1e3), a = Date.now(), d = setInterval(() => {
|
|
328
|
+
const b = Math.floor((Date.now() - a) / 1e3);
|
|
329
|
+
r && r(b);
|
|
330
330
|
}, 1e3), p = setTimeout(() => {
|
|
331
331
|
f();
|
|
332
332
|
}, t * 1e3);
|
|
@@ -343,23 +343,23 @@ function Rt(e = {}) {
|
|
|
343
343
|
l = m;
|
|
344
344
|
},
|
|
345
345
|
destroy() {
|
|
346
|
-
f(),
|
|
346
|
+
f(), g();
|
|
347
347
|
}
|
|
348
348
|
};
|
|
349
349
|
}
|
|
350
|
-
function
|
|
350
|
+
function Bt(e = 640) {
|
|
351
351
|
return typeof window < "u" && window.innerWidth < e;
|
|
352
352
|
}
|
|
353
353
|
function A(e, t, i) {
|
|
354
|
-
const o = i.map((
|
|
355
|
-
i.forEach((
|
|
354
|
+
const o = i.map((s) => s.style.visibility);
|
|
355
|
+
i.forEach((s) => s.style.visibility = "hidden");
|
|
356
356
|
const n = document.elementFromPoint(e, t);
|
|
357
|
-
return i.forEach((
|
|
357
|
+
return i.forEach((s, r) => s.style.visibility = o[r]), n;
|
|
358
358
|
}
|
|
359
|
-
function
|
|
359
|
+
function $(e) {
|
|
360
360
|
return e ? e.hasAttribute("data-qaid-embed") || e.hasAttribute("data-qaid-embed-overlay") ? !0 : !!e.closest("[data-qaid-embed], [data-qaid-embed-overlay]") : !1;
|
|
361
361
|
}
|
|
362
|
-
function
|
|
362
|
+
function Rt(e, t = 0) {
|
|
363
363
|
const i = e.getBoundingClientRect();
|
|
364
364
|
return {
|
|
365
365
|
x: i.left - t,
|
|
@@ -368,7 +368,7 @@ function Dt(e, t = 0) {
|
|
|
368
368
|
height: i.height + t * 2
|
|
369
369
|
};
|
|
370
370
|
}
|
|
371
|
-
async function
|
|
371
|
+
async function zt(e = {}) {
|
|
372
372
|
const { quality: t = 1, maxWidth: i = 1280, maxHeight: o = 800 } = e;
|
|
373
373
|
try {
|
|
374
374
|
if (!navigator.mediaDevices?.getDisplayMedia)
|
|
@@ -378,7 +378,7 @@ async function Ht(e = {}) {
|
|
|
378
378
|
video: {
|
|
379
379
|
displaySurface: "browser"
|
|
380
380
|
}
|
|
381
|
-
}),
|
|
381
|
+
}), s = n.getVideoTracks()[0], r = s.getSettings(), l = document.createElement("video");
|
|
382
382
|
l.srcObject = n, l.muted = !0, await new Promise((f) => {
|
|
383
383
|
l.onloadedmetadata = () => {
|
|
384
384
|
l.play(), f();
|
|
@@ -389,50 +389,50 @@ async function Ht(e = {}) {
|
|
|
389
389
|
};
|
|
390
390
|
m();
|
|
391
391
|
}), await new Promise((f) => setTimeout(f, 100));
|
|
392
|
-
const d = r.width || l.videoWidth,
|
|
392
|
+
const d = r.width || l.videoWidth, a = r.height || l.videoHeight, c = Math.min(i / d, o / a, 1), h = Math.round(d * c), u = Math.round(a * c), p = document.createElement("canvas");
|
|
393
393
|
p.width = h, p.height = u;
|
|
394
|
-
const
|
|
395
|
-
return
|
|
394
|
+
const g = p.getContext("2d");
|
|
395
|
+
return g ? (g.drawImage(l, 0, 0, h, u), s.stop(), p.toDataURL("image/webp", t)) : (s.stop(), null);
|
|
396
396
|
} catch (n) {
|
|
397
397
|
return console.warn("Screenshot capture failed:", n), null;
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
|
-
const
|
|
400
|
+
const N = "https://qaid.dev/lib/html2canvas.min.js", Pt = 1e4, Ot = 50;
|
|
401
401
|
let y = null;
|
|
402
|
-
function
|
|
402
|
+
function Xt() {
|
|
403
403
|
if (typeof document > "u" || typeof window > "u")
|
|
404
404
|
return !1;
|
|
405
405
|
const e = document.createElement("canvas");
|
|
406
406
|
return typeof e.getContext == "function" && !!e.getContext("2d");
|
|
407
407
|
}
|
|
408
|
-
function
|
|
408
|
+
function At() {
|
|
409
409
|
return window.html2canvas ? Promise.resolve(!0) : y || (y = new Promise((e) => {
|
|
410
410
|
if (!document.querySelector(
|
|
411
|
-
`script[src="${
|
|
411
|
+
`script[src="${N}"]`
|
|
412
412
|
)) {
|
|
413
413
|
const n = document.createElement("script");
|
|
414
|
-
n.src =
|
|
414
|
+
n.src = N, n.async = !0, document.head.appendChild(n);
|
|
415
415
|
}
|
|
416
416
|
const i = Date.now(), o = () => {
|
|
417
417
|
if (window.html2canvas) {
|
|
418
418
|
e(!0);
|
|
419
419
|
return;
|
|
420
420
|
}
|
|
421
|
-
if (Date.now() - i >
|
|
421
|
+
if (Date.now() - i > Pt) {
|
|
422
422
|
y = null, e(!1);
|
|
423
423
|
return;
|
|
424
424
|
}
|
|
425
|
-
setTimeout(o,
|
|
425
|
+
setTimeout(o, Ot);
|
|
426
426
|
};
|
|
427
427
|
o();
|
|
428
428
|
}), y);
|
|
429
429
|
}
|
|
430
|
-
async function
|
|
430
|
+
async function $t(e = {}) {
|
|
431
431
|
const { quality: t = 0.8, maxWidth: i = 1280, maxHeight: o = 800 } = e;
|
|
432
432
|
try {
|
|
433
|
-
if (!await
|
|
433
|
+
if (!await At() || !window.html2canvas)
|
|
434
434
|
return console.warn("html2canvas failed to load"), null;
|
|
435
|
-
const
|
|
435
|
+
const s = await window.html2canvas(document.body, {
|
|
436
436
|
useCORS: !0,
|
|
437
437
|
allowTaint: !1,
|
|
438
438
|
logging: !1,
|
|
@@ -442,29 +442,45 @@ async function At(e = {}) {
|
|
|
442
442
|
height: document.documentElement.clientHeight,
|
|
443
443
|
x: window.scrollX,
|
|
444
444
|
y: window.scrollY,
|
|
445
|
-
ignoreElements: (
|
|
446
|
-
}), r =
|
|
445
|
+
ignoreElements: (a) => a instanceof HTMLElement ? a.classList.contains("qaid-buttons") || a.classList.contains("qaid-targeting-overlay") || a.classList.contains("qaid-modal-container") || a.classList.contains("qaid-bottom-sheet") || a.classList.contains("qaid-backdrop") || a.classList.contains("qaid-selected-marker") || a.classList.contains("qaid-tooltip-text") || a.classList.contains("qaid-recording-indicator") || a.classList.contains("qaid-video-preview") || a.className?.toString().startsWith?.("qaid-") : !1
|
|
446
|
+
}), r = s.width, l = s.height, d = Math.min(i / r, o / l, 1);
|
|
447
447
|
if (d < 1) {
|
|
448
|
-
const
|
|
449
|
-
h.width =
|
|
448
|
+
const a = Math.round(r * d), c = Math.round(l * d), h = document.createElement("canvas");
|
|
449
|
+
h.width = a, h.height = c;
|
|
450
450
|
const u = h.getContext("2d");
|
|
451
|
-
return u ? (u.drawImage(
|
|
451
|
+
return u ? (u.drawImage(s, 0, 0, a, c), h.toDataURL("image/webp", t)) : null;
|
|
452
452
|
}
|
|
453
|
-
return
|
|
453
|
+
return s.toDataURL("image/webp", t);
|
|
454
454
|
} catch (n) {
|
|
455
455
|
return console.warn("DOM screenshot capture failed:", n), null;
|
|
456
456
|
}
|
|
457
457
|
}
|
|
458
|
-
const
|
|
459
|
-
function
|
|
458
|
+
const V = "qaid_visitor_id", _ = "qaid_hide_feedback";
|
|
459
|
+
function I(e) {
|
|
460
|
+
return e ? `${_}_${e}` : _;
|
|
461
|
+
}
|
|
462
|
+
function Nt(e) {
|
|
463
|
+
try {
|
|
464
|
+
return localStorage.getItem(I(e)) === "1";
|
|
465
|
+
} catch {
|
|
466
|
+
return !1;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
function Vt(e, t = !0) {
|
|
470
|
+
try {
|
|
471
|
+
t ? localStorage.setItem(I(e), "1") : localStorage.removeItem(I(e));
|
|
472
|
+
} catch {
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
function _t() {
|
|
460
476
|
try {
|
|
461
|
-
let e = localStorage.getItem(
|
|
462
|
-
return e || (e = crypto.randomUUID(), localStorage.setItem(
|
|
477
|
+
let e = localStorage.getItem(V);
|
|
478
|
+
return e || (e = crypto.randomUUID(), localStorage.setItem(V, e)), e;
|
|
463
479
|
} catch {
|
|
464
480
|
return crypto.randomUUID();
|
|
465
481
|
}
|
|
466
482
|
}
|
|
467
|
-
class
|
|
483
|
+
class Ft {
|
|
468
484
|
config;
|
|
469
485
|
state = "IDLE";
|
|
470
486
|
feedbackData = {
|
|
@@ -514,6 +530,7 @@ class $t {
|
|
|
514
530
|
marker = null;
|
|
515
531
|
modalContainer = null;
|
|
516
532
|
backdrop = null;
|
|
533
|
+
dismissBtn = null;
|
|
517
534
|
// Per-instance CSS variables
|
|
518
535
|
cssVars = {};
|
|
519
536
|
// Bound event handlers
|
|
@@ -521,6 +538,10 @@ class $t {
|
|
|
521
538
|
boundMouseMove;
|
|
522
539
|
boundClick;
|
|
523
540
|
boundResize;
|
|
541
|
+
// DOM persistence (survives framework client-side navigation)
|
|
542
|
+
destroyed = !1;
|
|
543
|
+
domObserver = null;
|
|
544
|
+
boundBeforeSwap = null;
|
|
524
545
|
constructor(t) {
|
|
525
546
|
this.config = {
|
|
526
547
|
endpoint: t.endpoint,
|
|
@@ -570,13 +591,13 @@ class $t {
|
|
|
570
591
|
maxDuration: t.videoOptions?.maxDuration ?? 15
|
|
571
592
|
},
|
|
572
593
|
recordIcon: t.recordIcon ?? ""
|
|
573
|
-
}, 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 =
|
|
594
|
+
}, 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();
|
|
574
595
|
}
|
|
575
596
|
applyVars(t) {
|
|
576
|
-
|
|
597
|
+
lt(t, this.cssVars);
|
|
577
598
|
}
|
|
578
599
|
init() {
|
|
579
|
-
|
|
600
|
+
ht(), this.cssVars = ct({
|
|
580
601
|
positiveColor: this.config.colors.positive,
|
|
581
602
|
negativeColor: this.config.colors.negative,
|
|
582
603
|
markerColor: this.config.colors.marker,
|
|
@@ -585,12 +606,30 @@ class $t {
|
|
|
585
606
|
backdropOpacity: this.config.backdropOpacity,
|
|
586
607
|
fontFamily: this.config.fontFamily,
|
|
587
608
|
fontSize: this.config.fontSize
|
|
588
|
-
}), this.checkMobile(), window.addEventListener("resize", this.boundResize), this.createEmbed(), this.consoleCapture =
|
|
609
|
+
}), Nt(this.config.apiKey) && (this.config.incognito = !0), this.checkMobile(), window.addEventListener("resize", this.boundResize), this.createEmbed(), this.consoleCapture = Et((t) => {
|
|
589
610
|
this.feedbackData.consoleErrors = this.consoleCapture?.errors ?? [];
|
|
590
|
-
}), this.feedbackData.consoleErrors = this.consoleCapture.errors;
|
|
611
|
+
}), this.feedbackData.consoleErrors = this.consoleCapture.errors, this.observeDom();
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Watch for the shadow hosts being removed from the DOM by framework
|
|
615
|
+
* client-side navigation (e.g. Astro View Transitions swapping <body>
|
|
616
|
+
* contents, or any SPA router that replaces DOM subtrees). If the host
|
|
617
|
+
* is disconnected and destroy() wasn't called, re-append it.
|
|
618
|
+
*
|
|
619
|
+
* Also hooks into Astro's `astro:before-swap` when available, which
|
|
620
|
+
* lets us carry elements into the new document before the swap happens
|
|
621
|
+
* (avoids a flash of the widget disappearing and reappearing).
|
|
622
|
+
*/
|
|
623
|
+
observeDom() {
|
|
624
|
+
this.boundBeforeSwap = (t) => {
|
|
625
|
+
const i = t.newDocument;
|
|
626
|
+
!i || this.destroyed || (this.shadowHost && i.body.appendChild(this.shadowHost), this.overlayShadowHost && i.body.appendChild(this.overlayShadowHost));
|
|
627
|
+
}, document.addEventListener("astro:before-swap", this.boundBeforeSwap), this.domObserver = new MutationObserver(() => {
|
|
628
|
+
this.destroyed || (this.shadowHost && !this.shadowHost.isConnected && document.body.appendChild(this.shadowHost), this.overlayShadowHost && !this.overlayShadowHost.isConnected && document.body.appendChild(this.overlayShadowHost));
|
|
629
|
+
}), this.domObserver.observe(document.body, { childList: !0 });
|
|
591
630
|
}
|
|
592
631
|
checkMobile() {
|
|
593
|
-
this.isMobile =
|
|
632
|
+
this.isMobile = Bt();
|
|
594
633
|
}
|
|
595
634
|
handleResize() {
|
|
596
635
|
this.checkMobile();
|
|
@@ -601,35 +640,38 @@ class $t {
|
|
|
601
640
|
this.config.container && (t = document.querySelector(this.config.container)), t ? (t.appendChild(this.shadowHost), this.isUserProvidedContainer = !0) : (this.shadowHost.style.position = "fixed", this.shadowHost.style.display = "block", this.shadowHost.style.inset = "0", this.shadowHost.style.pointerEvents = "none", this.shadowHost.style.zIndex = String(this.config.zIndex), document.body.appendChild(this.shadowHost)), this.shadowRoot = this.shadowHost.attachShadow({ mode: "open" });
|
|
602
641
|
const i = document.createElement("style");
|
|
603
642
|
if (i.textContent = z(), this.shadowRoot.appendChild(i), this.config.css) {
|
|
604
|
-
const
|
|
605
|
-
|
|
643
|
+
const a = document.createElement("style");
|
|
644
|
+
a.textContent = this.config.css, this.shadowRoot.appendChild(a);
|
|
606
645
|
}
|
|
607
646
|
const o = this.config.direction === "vertical" ? "qaid-vertical" : "";
|
|
608
647
|
if (this.isUserProvidedContainer)
|
|
609
648
|
this.buttonsContainer = document.createElement("div"), this.buttonsContainer.className = `qaid-buttons qaid-${this.config.position} ${o}`.trim(), this.config.incognito && this.buttonsContainer.classList.add("qaid-incognito");
|
|
610
649
|
else {
|
|
611
650
|
this.buttonsContainer = document.createElement("div"), this.buttonsContainer.className = `qaid-buttons qaid-auto-container qaid-${this.config.position} ${o}${this.config.incognito ? " qaid-incognito" : ""}`.trim(), this.buttonsContainer.style.pointerEvents = "auto";
|
|
612
|
-
const { x:
|
|
613
|
-
this.config.position.includes("right") ? this.buttonsContainer.style.right = `${
|
|
651
|
+
const { x: a, y: c } = this.config.offset;
|
|
652
|
+
this.config.position.includes("right") ? this.buttonsContainer.style.right = `${a}px` : this.buttonsContainer.style.left = `${a}px`, this.config.position.includes("bottom") ? this.buttonsContainer.style.bottom = `${c}px` : this.buttonsContainer.style.top = `${c}px`;
|
|
614
653
|
}
|
|
615
654
|
this.applyVars(this.buttonsContainer), this.shadowRoot.appendChild(this.buttonsContainer);
|
|
616
|
-
const n = !!this.config.buttonClass,
|
|
655
|
+
const n = !!this.config.buttonClass, s = n ? `qaid-btn-structural ${this.config.buttonClass}` : "qaid-btn", l = this.config.text.tooltip || "Feedback for us?", d = document.createElement("div");
|
|
617
656
|
if (d.className = "qaid-tooltip-text", d.textContent = l, this.applyVars(d), this.shadowRoot.appendChild(d), this.tooltipElement = d, !this.config.hideThumbs) {
|
|
618
|
-
const
|
|
619
|
-
|
|
657
|
+
const a = document.createElement("div");
|
|
658
|
+
a.className = "qaid-tooltip-wrapper";
|
|
620
659
|
const c = document.createElement("button");
|
|
621
|
-
c.type = "button", c.className = n ? `${
|
|
660
|
+
c.type = "button", c.className = n ? `${s} qaid-btn-up` : "qaid-btn qaid-btn-up", c.innerHTML = this.config.positiveIcon || E, c.addEventListener("click", (p) => this.handleThumbClick("up", p.currentTarget, p)), c.addEventListener("mouseenter", () => this.showTooltip(c)), c.addEventListener("mouseleave", () => this.hideTooltip()), a.appendChild(c);
|
|
622
661
|
const h = document.createElement("div");
|
|
623
662
|
h.className = "qaid-tooltip-wrapper";
|
|
624
663
|
const u = document.createElement("button");
|
|
625
|
-
u.type = "button", u.className = n ? `${
|
|
664
|
+
u.type = "button", u.className = n ? `${s} qaid-btn-down` : "qaid-btn qaid-btn-down", u.innerHTML = this.config.negativeIcon || T, u.addEventListener("click", (p) => this.handleThumbClick("down", p.currentTarget, p)), u.addEventListener("mouseenter", () => this.showTooltip(u)), u.addEventListener("mouseleave", () => this.hideTooltip()), h.appendChild(u), this.buttonsContainer.appendChild(a), this.buttonsContainer.appendChild(h);
|
|
626
665
|
}
|
|
627
|
-
if (this.config.captureVideo &&
|
|
628
|
-
const
|
|
629
|
-
|
|
666
|
+
if (this.config.captureVideo && Ht()) {
|
|
667
|
+
const a = document.createElement("div");
|
|
668
|
+
a.className = "qaid-tooltip-wrapper";
|
|
630
669
|
const c = document.createElement("button");
|
|
631
|
-
c.type = "button", c.className = n ? `${
|
|
670
|
+
c.type = "button", c.className = n ? `${s} 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()), a.appendChild(c), this.buttonsContainer.appendChild(a);
|
|
632
671
|
}
|
|
672
|
+
this.dismissBtn = document.createElement("button"), this.dismissBtn.type = "button", this.dismissBtn.className = "qaid-dismiss-btn", this.dismissBtn.setAttribute("aria-label", "Hide Feedback"), this.dismissBtn.title = "Hide Feedback", this.dismissBtn.innerHTML = '<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 2l8 8M10 2l-8 8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>', this.dismissBtn.addEventListener("click", (a) => {
|
|
673
|
+
a.stopPropagation(), this.handleDismiss();
|
|
674
|
+
}), this.buttonsContainer.appendChild(this.dismissBtn);
|
|
633
675
|
}
|
|
634
676
|
/**
|
|
635
677
|
* Lazily create a separate overlay shadow host on document.body.
|
|
@@ -652,13 +694,16 @@ class $t {
|
|
|
652
694
|
if (!this.tooltipElement) return;
|
|
653
695
|
const i = this.tooltipElement, o = 8;
|
|
654
696
|
i.style.visibility = "hidden", i.classList.add("qaid-tooltip-visible");
|
|
655
|
-
const n = t.getBoundingClientRect(),
|
|
656
|
-
let d,
|
|
657
|
-
d = n.bottom + o, d +
|
|
697
|
+
const n = t.getBoundingClientRect(), s = i.getBoundingClientRect(), r = window.innerWidth, l = window.innerHeight;
|
|
698
|
+
let d, a;
|
|
699
|
+
d = n.bottom + o, d + s.height > l - o && (d = n.top - s.height - o), a = n.left, a < o ? a = o : a + s.width > r - o && (a = r - s.width - o), d < o ? d = o : d + s.height > l - o && (d = l - s.height - o), i.style.top = `${d}px`, i.style.left = `${a}px`, i.style.visibility = "visible";
|
|
658
700
|
}
|
|
659
701
|
hideTooltip() {
|
|
660
702
|
this.tooltipElement && this.tooltipElement.classList.remove("qaid-tooltip-visible");
|
|
661
703
|
}
|
|
704
|
+
handleDismiss() {
|
|
705
|
+
this.buttonsContainer && this.buttonsContainer.classList.add("qaid-incognito"), Vt(this.config.apiKey, !0);
|
|
706
|
+
}
|
|
662
707
|
handleThumbClick(t, i, o) {
|
|
663
708
|
this.config.skipTargeting ? this.submitDirectFeedback(t, i) : this.startTargeting(t, o);
|
|
664
709
|
}
|
|
@@ -698,7 +743,7 @@ class $t {
|
|
|
698
743
|
t.clientY,
|
|
699
744
|
i
|
|
700
745
|
);
|
|
701
|
-
if (o &&
|
|
746
|
+
if (o && !$(o)) {
|
|
702
747
|
if (this.highlightBox) {
|
|
703
748
|
const n = o.getBoundingClientRect();
|
|
704
749
|
this.highlightBox.style.transform = `translate(${n.left}px, ${n.top}px)`, this.highlightBox.style.width = `${n.width}px`, this.highlightBox.style.height = `${n.height}px`, this.highlightBox.style.display = "block";
|
|
@@ -715,17 +760,17 @@ class $t {
|
|
|
715
760
|
t.clientY,
|
|
716
761
|
i
|
|
717
762
|
);
|
|
718
|
-
if (!o ||
|
|
763
|
+
if (!o || $(o))
|
|
719
764
|
return;
|
|
720
|
-
const n =
|
|
765
|
+
const n = Rt(o, 8);
|
|
721
766
|
this.selectedBounds = {
|
|
722
767
|
...n,
|
|
723
768
|
clickX: t.clientX,
|
|
724
769
|
clickY: t.clientY,
|
|
725
770
|
visible: !0
|
|
726
771
|
};
|
|
727
|
-
const { selector:
|
|
728
|
-
this.feedbackData.elementSelector =
|
|
772
|
+
const { selector: s, text: r } = yt(o);
|
|
773
|
+
this.feedbackData.elementSelector = s, this.feedbackData.elementText = r, this.removeTargetingOverlay(), document.removeEventListener("mousemove", this.boundMouseMove), document.removeEventListener("click", this.boundClick, !0), document.removeEventListener("keydown", this.boundKeyDown), document.body.classList.remove("qaid-targeting", "qaid-type-up"), document.body.style.removeProperty("--qaid-positive"), document.body.style.removeProperty("--qaid-negative"), this.state = "SELECTED", this.showSelectedMarker(), this.submitFeedback();
|
|
729
774
|
}
|
|
730
775
|
cancelTargeting() {
|
|
731
776
|
this.removeTargetingOverlay(), document.removeEventListener("mousemove", this.boundMouseMove), document.removeEventListener("click", this.boundClick, !0), document.removeEventListener("keydown", this.boundKeyDown), document.body.classList.remove("qaid-targeting", "qaid-type-up"), document.body.style.removeProperty("--qaid-positive"), document.body.style.removeProperty("--qaid-negative"), this.state = "IDLE", this.feedbackData.feedbackType = null, this.feedbackData.elementSelector = null, this.feedbackData.elementText = null, this.selectedBounds.visible = !1;
|
|
@@ -744,7 +789,7 @@ class $t {
|
|
|
744
789
|
async submitFeedback() {
|
|
745
790
|
if (!this.feedbackData.feedbackType) return;
|
|
746
791
|
let t = null;
|
|
747
|
-
this.config.captureScreenshot && (this.config.screenshotMethod === "dom" ? t = await
|
|
792
|
+
this.config.captureScreenshot && (this.config.screenshotMethod === "dom" ? t = await $t(this.config.screenshotOptions) : t = await zt(this.config.screenshotOptions));
|
|
748
793
|
const i = this.feedbackData.elementSelector ? {
|
|
749
794
|
x: this.selectedBounds.x,
|
|
750
795
|
y: this.selectedBounds.y,
|
|
@@ -776,8 +821,8 @@ class $t {
|
|
|
776
821
|
body: JSON.stringify(o)
|
|
777
822
|
});
|
|
778
823
|
if (n.ok) {
|
|
779
|
-
const
|
|
780
|
-
this.feedbackId =
|
|
824
|
+
const s = await n.json();
|
|
825
|
+
this.feedbackId = s.id;
|
|
781
826
|
}
|
|
782
827
|
} catch (n) {
|
|
783
828
|
console.error("Failed to submit feedback:", n);
|
|
@@ -798,7 +843,7 @@ class $t {
|
|
|
798
843
|
`, this.applyVars(i), t.appendChild(i), this.modalContainer = i, this.setupModalInteractions();
|
|
799
844
|
}
|
|
800
845
|
showPositionedModal() {
|
|
801
|
-
const t = this.ensureOverlayHost(), { modal: i, arrow: o } =
|
|
846
|
+
const t = this.ensureOverlayHost(), { modal: i, arrow: o } = Ct(
|
|
802
847
|
this.selectedBounds,
|
|
803
848
|
window.innerWidth,
|
|
804
849
|
window.innerHeight,
|
|
@@ -813,8 +858,8 @@ class $t {
|
|
|
813
858
|
this.modalContainer = document.createElement("div"), this.modalContainer.className = `qaid-modal-container qaid-${i.position}`, this.modalContainer.style.top = `${i.top}px`, this.modalContainer.style.left = `${i.left}px`, this.modalContainer.style.zIndex = String(this.config.zIndex + 3);
|
|
814
859
|
const n = document.createElement("div");
|
|
815
860
|
n.className = "qaid-modal-arrow", n.style.left = `${o.left}px`;
|
|
816
|
-
const
|
|
817
|
-
|
|
861
|
+
const s = document.createElement("div");
|
|
862
|
+
s.className = "qaid-modal-box", s.innerHTML = this.getModalContent(), this.modalContainer.appendChild(n), this.modalContainer.appendChild(s), this.applyVars(this.modalContainer), t.appendChild(this.modalContainer), this.setupModalInteractions();
|
|
818
863
|
}
|
|
819
864
|
getModalContent() {
|
|
820
865
|
const t = this.feedbackData.feedbackType === "up", i = this.config.positiveIcon || E, o = this.config.negativeIcon || T;
|
|
@@ -847,8 +892,8 @@ class $t {
|
|
|
847
892
|
o && o.addEventListener("click", () => {
|
|
848
893
|
const n = this.feedbackData.feedbackType === "up" ? "down" : "up";
|
|
849
894
|
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"));
|
|
850
|
-
const
|
|
851
|
-
o.innerHTML = n === "up" ?
|
|
895
|
+
const s = this.config.positiveIcon || E, r = this.config.negativeIcon || T;
|
|
896
|
+
o.innerHTML = n === "up" ? s : r, this.feedbackId && fetch(`${this.config.endpoint}/${this.feedbackId}`, {
|
|
852
897
|
method: "PATCH",
|
|
853
898
|
headers: { "Content-Type": "application/json" },
|
|
854
899
|
body: JSON.stringify({ feedbackType: n })
|
|
@@ -881,7 +926,7 @@ class $t {
|
|
|
881
926
|
async startRecording() {
|
|
882
927
|
if (!(this.isRecording || this.state !== "IDLE"))
|
|
883
928
|
try {
|
|
884
|
-
this.networkCapture =
|
|
929
|
+
this.networkCapture = Lt(), this.videoRecorder = Mt({
|
|
885
930
|
maxDuration: this.config.videoOptions.maxDuration
|
|
886
931
|
}), this.videoRecorder.onTick((t) => {
|
|
887
932
|
this.updateRecordingTimer(t);
|
|
@@ -935,23 +980,23 @@ class $t {
|
|
|
935
980
|
o.className = "qaid-video-preview-box";
|
|
936
981
|
const n = document.createElement("h3");
|
|
937
982
|
n.textContent = "Review your recording";
|
|
938
|
-
const
|
|
939
|
-
|
|
983
|
+
const s = document.createElement("video");
|
|
984
|
+
s.src = i, s.controls = !0, s.autoplay = !0, s.muted = !0;
|
|
940
985
|
const r = document.createElement("textarea");
|
|
941
986
|
r.placeholder = "Optional: Describe the issue you recorded...";
|
|
942
987
|
const l = document.createElement("div");
|
|
943
988
|
l.className = "qaid-video-preview-actions";
|
|
944
989
|
const d = document.createElement("button");
|
|
945
990
|
d.type = "button", d.className = "qaid-video-btn qaid-video-btn-cancel", d.textContent = "Cancel", d.addEventListener("click", () => this.cancelRecordingPreview());
|
|
946
|
-
const
|
|
947
|
-
|
|
991
|
+
const a = document.createElement("button");
|
|
992
|
+
a.type = "button", a.className = "qaid-video-btn qaid-video-btn-rerecord", a.textContent = "Re-record", a.addEventListener("click", () => {
|
|
948
993
|
this.cancelRecordingPreview(), this.startRecording();
|
|
949
994
|
});
|
|
950
995
|
const c = document.createElement("button");
|
|
951
996
|
c.type = "button", c.className = "qaid-video-btn qaid-video-btn-send", c.textContent = "Send", c.addEventListener("click", () => {
|
|
952
997
|
const h = r.value.trim() || null;
|
|
953
998
|
this.submitVideoFeedback(h, c);
|
|
954
|
-
}), l.appendChild(d), l.appendChild(
|
|
999
|
+
}), l.appendChild(d), l.appendChild(a), l.appendChild(c), o.appendChild(n), o.appendChild(s), o.appendChild(r), o.appendChild(l), this.videoPreview.appendChild(o), this.applyVars(this.videoPreview), this.overlayShadowHost && (this.overlayShadowHost.style.pointerEvents = "auto"), t.appendChild(this.videoPreview), document.addEventListener("keydown", this.boundKeyDown);
|
|
955
1000
|
}
|
|
956
1001
|
cancelRecordingPreview() {
|
|
957
1002
|
this.removeVideoPreview(), this.cleanupRecording();
|
|
@@ -992,13 +1037,13 @@ class $t {
|
|
|
992
1037
|
* Destroy the embed and clean up all resources
|
|
993
1038
|
*/
|
|
994
1039
|
destroy() {
|
|
995
|
-
this.cleanupRecording(), this.removeVideoPreview(), this.consoleCapture && (this.consoleCapture.restore(), this.consoleCapture = null), window.removeEventListener("resize", this.boundResize), document.removeEventListener("keydown", this.boundKeyDown), document.removeEventListener("mousemove", this.boundMouseMove), document.removeEventListener("click", this.boundClick, !0), document.body.classList.remove("qaid-targeting", "qaid-type-up"), document.body.style.removeProperty("--qaid-positive"), document.body.style.removeProperty("--qaid-negative"), this.shadowHost && (this.shadowHost.remove(), this.shadowHost = null, this.shadowRoot = null), this.overlayShadowHost && (this.overlayShadowHost.remove(), this.overlayShadowHost = null, this.overlayShadowRoot = null), this.buttonsContainer = null, this.overlayContainer = null, this.captureLayer = null, this.crosshairH = null, this.crosshairV = null, this.scope = null, this.marker = null, this.modalContainer = null, this.backdrop = null, this.tooltipElement = null,
|
|
1040
|
+
this.destroyed = !0, this.domObserver && (this.domObserver.disconnect(), this.domObserver = null), this.boundBeforeSwap && (document.removeEventListener("astro:before-swap", this.boundBeforeSwap), this.boundBeforeSwap = null), this.cleanupRecording(), this.removeVideoPreview(), this.consoleCapture && (this.consoleCapture.restore(), this.consoleCapture = null), window.removeEventListener("resize", this.boundResize), document.removeEventListener("keydown", this.boundKeyDown), document.removeEventListener("mousemove", this.boundMouseMove), document.removeEventListener("click", this.boundClick, !0), document.body.classList.remove("qaid-targeting", "qaid-type-up"), document.body.style.removeProperty("--qaid-positive"), document.body.style.removeProperty("--qaid-negative"), this.shadowHost && (this.shadowHost.remove(), this.shadowHost = null, this.shadowRoot = null), this.overlayShadowHost && (this.overlayShadowHost.remove(), this.overlayShadowHost = null, this.overlayShadowRoot = null), this.buttonsContainer = null, this.overlayContainer = null, this.captureLayer = null, this.crosshairH = null, this.crosshairV = null, this.scope = null, this.marker = null, this.modalContainer = null, this.backdrop = null, this.dismissBtn = null, this.tooltipElement = null, ut();
|
|
996
1041
|
}
|
|
997
1042
|
}
|
|
998
|
-
function
|
|
1043
|
+
function W(e) {
|
|
999
1044
|
return document.querySelector(e)?.textContent?.trim() ?? "";
|
|
1000
1045
|
}
|
|
1001
|
-
function
|
|
1046
|
+
function Ut() {
|
|
1002
1047
|
const e = document.querySelector(
|
|
1003
1048
|
'script[type="application/json"][data-feedback-config]'
|
|
1004
1049
|
);
|
|
@@ -1007,20 +1052,20 @@ function Nt() {
|
|
|
1007
1052
|
if (!t) return null;
|
|
1008
1053
|
try {
|
|
1009
1054
|
const i = JSON.parse(t);
|
|
1010
|
-
return i.cssSelector && !i.css && (i.css =
|
|
1055
|
+
return i.cssSelector && !i.css && (i.css = W(i.cssSelector), delete i.cssSelector), i;
|
|
1011
1056
|
} catch {
|
|
1012
1057
|
return null;
|
|
1013
1058
|
}
|
|
1014
1059
|
}
|
|
1015
|
-
function
|
|
1060
|
+
function Wt(e) {
|
|
1016
1061
|
const t = e.getAttribute("data-endpoint");
|
|
1017
1062
|
if (!t) return null;
|
|
1018
|
-
const i = e.getAttribute("data-position"), o = e.getAttribute("data-zindex"), n = e.getAttribute("data-positive-color"),
|
|
1063
|
+
const i = e.getAttribute("data-position"), o = e.getAttribute("data-zindex"), n = e.getAttribute("data-positive-color"), s = e.getAttribute("data-negative-color"), r = e.getAttribute("data-marker-color"), l = e.getAttribute("data-container"), d = e.getAttribute("data-button-class"), a = e.getAttribute("data-skip-targeting"), c = e.getAttribute("data-incognito"), h = e.getAttribute("data-button-size"), u = e.getAttribute("data-offset-x"), p = e.getAttribute("data-offset-y"), g = e.getAttribute("data-modal-width"), f = e.getAttribute("data-backdrop-opacity"), m = e.getAttribute("data-font-family"), v = e.getAttribute("data-font-size"), b = e.getAttribute("data-tooltip"), x = e.getAttribute("data-modal-title"), L = e.getAttribute("data-modal-subtitle"), H = e.getAttribute("data-placeholder"), D = e.getAttribute("data-submit-button"), M = e.getAttribute("data-skip-button"), X = e.getAttribute("data-positive-icon"), j = e.getAttribute("data-negative-icon"), K = e.getAttribute("data-api-key"), Y = e.getAttribute("data-capture-screenshot"), k = e.getAttribute("data-screenshot-quality"), C = e.getAttribute("data-screenshot-max-width"), S = e.getAttribute("data-screenshot-max-height"), J = e.getAttribute("data-capture-video"), G = e.getAttribute("data-hide-thumbs"), B = e.getAttribute("data-video-max-duration"), Z = e.getAttribute("data-screenshot-method"), Q = e.getAttribute("data-direction"), R = e.getAttribute("data-css-selector");
|
|
1019
1064
|
return {
|
|
1020
1065
|
endpoint: t,
|
|
1021
|
-
css:
|
|
1022
|
-
apiKey:
|
|
1023
|
-
captureScreenshot:
|
|
1066
|
+
css: R ? W(R) : void 0,
|
|
1067
|
+
apiKey: K ?? void 0,
|
|
1068
|
+
captureScreenshot: Y === "true" ? !0 : void 0,
|
|
1024
1069
|
screenshotOptions: k || C || S ? {
|
|
1025
1070
|
quality: k ? parseFloat(k) : void 0,
|
|
1026
1071
|
maxWidth: C ? parseInt(C, 10) : void 0,
|
|
@@ -1028,57 +1073,57 @@ function Vt(e) {
|
|
|
1028
1073
|
} : void 0,
|
|
1029
1074
|
container: l ?? void 0,
|
|
1030
1075
|
buttonClass: d ?? void 0,
|
|
1031
|
-
direction:
|
|
1076
|
+
direction: Q ?? void 0,
|
|
1032
1077
|
position: i ?? void 0,
|
|
1033
1078
|
zIndex: o ? parseInt(o, 10) : void 0,
|
|
1034
|
-
skipTargeting:
|
|
1079
|
+
skipTargeting: a === "true" ? !0 : void 0,
|
|
1035
1080
|
incognito: c === "true" ? !0 : void 0,
|
|
1036
1081
|
buttonSize: h ?? void 0,
|
|
1037
1082
|
offset: u || p ? {
|
|
1038
1083
|
x: u ? parseInt(u, 10) : void 0,
|
|
1039
1084
|
y: p ? parseInt(p, 10) : void 0
|
|
1040
1085
|
} : void 0,
|
|
1041
|
-
modalWidth:
|
|
1086
|
+
modalWidth: g ? parseInt(g, 10) : void 0,
|
|
1042
1087
|
backdropOpacity: f ? parseFloat(f) : void 0,
|
|
1043
1088
|
fontFamily: m ?? void 0,
|
|
1044
1089
|
fontSize: v ? parseInt(v, 10) : void 0,
|
|
1045
1090
|
colors: {
|
|
1046
1091
|
positive: n ?? void 0,
|
|
1047
|
-
negative:
|
|
1092
|
+
negative: s ?? void 0,
|
|
1048
1093
|
marker: r ?? void 0
|
|
1049
1094
|
},
|
|
1050
|
-
text:
|
|
1051
|
-
tooltip:
|
|
1095
|
+
text: b || x || L || H || D || M ? {
|
|
1096
|
+
tooltip: b ?? void 0,
|
|
1052
1097
|
modalTitle: x ?? void 0,
|
|
1053
|
-
modalSubtitle:
|
|
1054
|
-
placeholder:
|
|
1055
|
-
submitButton:
|
|
1098
|
+
modalSubtitle: L ?? void 0,
|
|
1099
|
+
placeholder: H ?? void 0,
|
|
1100
|
+
submitButton: D ?? void 0,
|
|
1056
1101
|
skipButton: M ?? void 0
|
|
1057
1102
|
} : void 0,
|
|
1058
|
-
positiveIcon:
|
|
1059
|
-
negativeIcon:
|
|
1060
|
-
screenshotMethod:
|
|
1061
|
-
captureVideo:
|
|
1062
|
-
hideThumbs:
|
|
1063
|
-
videoOptions:
|
|
1064
|
-
maxDuration: parseInt(
|
|
1103
|
+
positiveIcon: X ?? void 0,
|
|
1104
|
+
negativeIcon: j ?? void 0,
|
|
1105
|
+
screenshotMethod: Z ?? void 0,
|
|
1106
|
+
captureVideo: J === "true" ? !0 : void 0,
|
|
1107
|
+
hideThumbs: G === "true" ? !0 : void 0,
|
|
1108
|
+
videoOptions: B ? {
|
|
1109
|
+
maxDuration: parseInt(B, 10)
|
|
1065
1110
|
} : void 0
|
|
1066
1111
|
};
|
|
1067
1112
|
}
|
|
1068
1113
|
if (typeof document < "u") {
|
|
1069
1114
|
const e = () => {
|
|
1070
|
-
const t = document.currentScript, i =
|
|
1071
|
-
n?.endpoint && new
|
|
1115
|
+
const t = document.currentScript, i = Ut(), o = t ? Wt(t) : null, n = i ?? o;
|
|
1116
|
+
n?.endpoint && new Ft(n);
|
|
1072
1117
|
};
|
|
1073
1118
|
document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", e) : e();
|
|
1074
1119
|
}
|
|
1075
1120
|
export {
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1121
|
+
Ft as QaidFeedback,
|
|
1122
|
+
$t as captureDomScreenshot,
|
|
1123
|
+
Lt as captureNetworkErrors,
|
|
1124
|
+
Mt as createVideoRecorder,
|
|
1125
|
+
Dt as getSupportedMimeType,
|
|
1126
|
+
Xt as isDomScreenshotSupported,
|
|
1127
|
+
Ht as isVideoRecordingSupported
|
|
1083
1128
|
};
|
|
1084
1129
|
//# sourceMappingURL=qaid.js.map
|