@qaiddev/thumbs-embed 1.2.0 → 1.2.1
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/embed.d.ts +14 -0
- package/dist/qaid.js +354 -259
- package/dist/qaid.js.map +1 -1
- package/dist/qaid.umd.cjs +6 -6
- package/dist/qaid.umd.cjs.map +1 -1
- package/dist/video-orientation.d.ts +48 -0
- package/package.json +1 -1
package/dist/qaid.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
const
|
|
1
|
+
const I = `<svg xmlns="http://www.w3.org/2000/svg" class="qaid-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
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
|
-
</svg>`,
|
|
3
|
+
</svg>`, A = `<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
5
|
</svg>`, bt = `<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>`, gt = "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.qaid-dismissed{display:none!important}.qaid-dismiss-btn{width:20px;height:20px;padding:0;border:none;border-radius:50%;background:#0006;color:#fff;display:flex;align-items:center;justify-content:center;align-self:center;opacity:0;transition:opacity .15s,background .15s;cursor:pointer;pointer-events:auto;-webkit-appearance:none;appearance:none}.qaid-dismiss-btn:hover{background:#0009}.qaid-buttons:hover .qaid-dismiss-btn{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)}button:focus-visible,textarea:focus-visible,a:focus-visible,[tabindex]:focus-visible,[role=button]:focus-visible{outline:2px solid var(--qaid-marker, #6366f1);outline-offset:2px}.qaid-textarea:focus-visible,button.qaid-btn-submit:focus-visible,.qaid-video-preview-box textarea:focus-visible{outline:2px solid var(--qaid-marker, #6366f1);outline-offset:2px}.qaid-buttons.qaid-incognito:focus-within{opacity:1}.qaid-buttons:focus-within .qaid-dismiss-btn,.qaid-dismiss-btn:focus-visible{opacity:1}.qaid-dismiss-btn{min-width:24px;min-height:24px}button.qaid-recording-stop{min-height:24px}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}@media(forced-colors:active){button:focus-visible,textarea:focus-visible,a:focus-visible,[tabindex]:focus-visible,[role=button]:focus-visible,.qaid-textarea:focus,button.qaid-btn-submit:focus,.qaid-video-preview-box textarea:focus{outline:2px solid CanvasText;outline-offset:2px}.qaid-selected-marker,.qaid-highlight-box{border-color:Highlight}}", vt = "body.qaid-targeting,body.qaid-targeting *{cursor:none!important}";
|
|
8
|
-
let
|
|
7
|
+
</svg>`, gt = "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.qaid-dismissed{display:none!important}.qaid-dismiss-btn{width:20px;height:20px;padding:0;border:none;border-radius:50%;background:#0006;color:#fff;display:flex;align-items:center;justify-content:center;align-self:center;opacity:0;transition:opacity .15s,background .15s;cursor:pointer;pointer-events:auto;-webkit-appearance:none;appearance:none}.qaid-dismiss-btn:hover{background:#0009}.qaid-buttons:hover .qaid-dismiss-btn{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 0 auto;height:100vh;height:100dvh;display:flex;align-items:center;justify-content:center;padding:16px;padding-top:max(16px,env(safe-area-inset-top));padding-bottom:max(16px,env(safe-area-inset-bottom));box-sizing:border-box;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:100%;max-height:100%;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%;max-height:50vh;max-height:50dvh;object-fit:contain;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)}button:focus-visible,textarea:focus-visible,a:focus-visible,[tabindex]:focus-visible,[role=button]:focus-visible{outline:2px solid var(--qaid-marker, #6366f1);outline-offset:2px}.qaid-textarea:focus-visible,button.qaid-btn-submit:focus-visible,.qaid-video-preview-box textarea:focus-visible{outline:2px solid var(--qaid-marker, #6366f1);outline-offset:2px}.qaid-buttons.qaid-incognito:focus-within{opacity:1}.qaid-buttons:focus-within .qaid-dismiss-btn,.qaid-dismiss-btn:focus-visible{opacity:1}.qaid-dismiss-btn{min-width:24px;min-height:24px}button.qaid-recording-stop{min-height:24px}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}@media(forced-colors:active){button:focus-visible,textarea:focus-visible,a:focus-visible,[tabindex]:focus-visible,[role=button]:focus-visible,.qaid-textarea:focus,button.qaid-btn-submit:focus,.qaid-video-preview-box textarea:focus{outline:2px solid CanvasText;outline-offset:2px}.qaid-selected-marker,.qaid-highlight-box{border-color:Highlight}}", vt = "body.qaid-targeting,body.qaid-targeting *{cursor:none!important}";
|
|
8
|
+
let k = 0;
|
|
9
9
|
const yt = "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)}", wt = {
|
|
10
10
|
small: 36,
|
|
11
11
|
medium: 48,
|
|
@@ -39,7 +39,7 @@ function Ct(e) {
|
|
|
39
39
|
const t = kt(e);
|
|
40
40
|
return t && qt(t.r, t.g, t.b) > 0.4 ? "black" : "white";
|
|
41
41
|
}
|
|
42
|
-
function
|
|
42
|
+
function St(e = {}) {
|
|
43
43
|
const {
|
|
44
44
|
positiveColor: t = "rgb(0, 200, 83)",
|
|
45
45
|
negativeColor: i = "rgb(255, 0, 0)",
|
|
@@ -47,23 +47,23 @@ function Et(e = {}) {
|
|
|
47
47
|
buttonSize: n = "medium",
|
|
48
48
|
modalWidth: s = 400,
|
|
49
49
|
backdropOpacity: a = 0.3,
|
|
50
|
-
fontFamily:
|
|
51
|
-
fontSize:
|
|
52
|
-
} = e, r = wt[n],
|
|
50
|
+
fontFamily: d = "system-ui, -apple-system, sans-serif",
|
|
51
|
+
fontSize: l = 16
|
|
52
|
+
} = e, r = wt[n], c = xt[n], p = Ct(o);
|
|
53
53
|
return {
|
|
54
54
|
"--qaid-positive": t,
|
|
55
55
|
"--qaid-negative": i,
|
|
56
56
|
"--qaid-marker": o,
|
|
57
57
|
"--qaid-marker-text": p,
|
|
58
58
|
"--qaid-btn-size": `${r}px`,
|
|
59
|
-
"--qaid-icon-size": `${
|
|
59
|
+
"--qaid-icon-size": `${c}px`,
|
|
60
60
|
"--qaid-modal-width": `${s}px`,
|
|
61
61
|
"--qaid-backdrop-opacity": String(a),
|
|
62
|
-
"--qaid-font-family":
|
|
63
|
-
"--qaid-font-size": `${
|
|
62
|
+
"--qaid-font-family": d,
|
|
63
|
+
"--qaid-font-size": `${l}px`
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
-
function
|
|
66
|
+
function Et(e, t) {
|
|
67
67
|
for (const [i, o] of Object.entries(t))
|
|
68
68
|
e.style.setProperty(i, o);
|
|
69
69
|
}
|
|
@@ -71,12 +71,12 @@ function N() {
|
|
|
71
71
|
return gt + yt;
|
|
72
72
|
}
|
|
73
73
|
function Tt() {
|
|
74
|
-
if (
|
|
74
|
+
if (k++, k > 1) return;
|
|
75
75
|
const e = document.createElement("style");
|
|
76
76
|
e.id = "qaid-styles", e.textContent = vt, document.head.appendChild(e);
|
|
77
77
|
}
|
|
78
78
|
function Lt() {
|
|
79
|
-
|
|
79
|
+
k <= 0 || (k--, k === 0 && document.getElementById("qaid-styles").remove());
|
|
80
80
|
}
|
|
81
81
|
const G = ["data-comp", "data-qa", "data-testid", "data-id"];
|
|
82
82
|
function J(e, t = document.body) {
|
|
@@ -117,7 +117,7 @@ function Rt(e) {
|
|
|
117
117
|
const t = J(e);
|
|
118
118
|
return t ? `[${t}]` : e.id ? `#${Mt(e.id)}` : Dt(e);
|
|
119
119
|
}
|
|
120
|
-
function
|
|
120
|
+
function D(e) {
|
|
121
121
|
const t = It(e), i = J(e);
|
|
122
122
|
return { selector: Rt(e), text: t, dataAttr: i };
|
|
123
123
|
}
|
|
@@ -142,7 +142,7 @@ const Ht = [
|
|
|
142
142
|
"label",
|
|
143
143
|
...G.map((e) => `[${e}]`)
|
|
144
144
|
].join(","), Bt = /^(?:A|BUTTON|INPUT|SELECT|TEXTAREA|SUMMARY)$/;
|
|
145
|
-
function
|
|
145
|
+
function Pt(e) {
|
|
146
146
|
if (e.hasAttribute("hidden") || e.getAttribute("aria-hidden") === "true") return !1;
|
|
147
147
|
const t = e.ownerDocument?.defaultView;
|
|
148
148
|
if (t && typeof t.getComputedStyle == "function") {
|
|
@@ -151,67 +151,67 @@ function zt(e) {
|
|
|
151
151
|
}
|
|
152
152
|
return !0;
|
|
153
153
|
}
|
|
154
|
-
function
|
|
155
|
-
const t = e.root ?? document.body, i = e.selector ?? Ht, o = e.isExcluded ?? (() => !1), n = e.isVisible ??
|
|
154
|
+
function zt(e = {}) {
|
|
155
|
+
const t = e.root ?? document.body, i = e.selector ?? Ht, o = e.isExcluded ?? (() => !1), n = e.isVisible ?? Pt;
|
|
156
156
|
return Array.from(t.querySelectorAll(i)).filter(
|
|
157
157
|
(s) => !o(s) && n(s)
|
|
158
158
|
);
|
|
159
159
|
}
|
|
160
|
-
function
|
|
161
|
-
const t = e.candidates ??
|
|
160
|
+
function Ot(e) {
|
|
161
|
+
const t = e.candidates ?? zt({
|
|
162
162
|
root: e.root,
|
|
163
163
|
selector: e.selector,
|
|
164
164
|
isExcluded: e.isExcluded,
|
|
165
165
|
isVisible: e.isVisible
|
|
166
166
|
}), i = e.moveFocus ?? !0, o = e.eventTarget ?? document, n = /* @__PURE__ */ new Set();
|
|
167
167
|
let s = -1, a = !1;
|
|
168
|
-
const
|
|
169
|
-
if (
|
|
170
|
-
const h = t.indexOf(
|
|
168
|
+
const d = e.initial !== void 0 ? e.initial : typeof document < "u" ? document.activeElement : null;
|
|
169
|
+
if (d) {
|
|
170
|
+
const h = t.indexOf(d);
|
|
171
171
|
h >= 0 && (s = h);
|
|
172
172
|
}
|
|
173
173
|
s < 0 && t.length > 0 && (s = 0);
|
|
174
|
-
function
|
|
174
|
+
function l(h) {
|
|
175
175
|
if (!i) return;
|
|
176
|
-
const
|
|
177
|
-
if (typeof
|
|
176
|
+
const w = h;
|
|
177
|
+
if (typeof w.focus == "function") {
|
|
178
178
|
h.getAttribute("tabindex") === null && !Bt.test(h.tagName) && (h.setAttribute("tabindex", "-1"), n.add(h));
|
|
179
179
|
try {
|
|
180
|
-
|
|
180
|
+
w.focus();
|
|
181
181
|
} catch {
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
function r() {
|
|
186
186
|
const h = t[s];
|
|
187
|
-
h && (
|
|
187
|
+
h && (l(h), e.onHighlight?.(h, s));
|
|
188
188
|
}
|
|
189
|
-
function
|
|
189
|
+
function c(h) {
|
|
190
190
|
if (a || t.length === 0) return;
|
|
191
|
-
const
|
|
192
|
-
s = (h %
|
|
191
|
+
const w = t.length;
|
|
192
|
+
s = (h % w + w) % w, r();
|
|
193
193
|
}
|
|
194
194
|
function p() {
|
|
195
|
-
|
|
195
|
+
c(s + 1);
|
|
196
196
|
}
|
|
197
197
|
function u() {
|
|
198
|
-
|
|
198
|
+
c(s - 1);
|
|
199
199
|
}
|
|
200
200
|
function m() {
|
|
201
201
|
return t[s] ?? null;
|
|
202
202
|
}
|
|
203
|
-
function g() {
|
|
204
|
-
a || (a = !0, o.removeEventListener("keydown", v, !0), n.forEach((h) => h.removeAttribute("tabindex")), n.clear());
|
|
205
|
-
}
|
|
206
203
|
function b() {
|
|
204
|
+
a || (a = !0, o.removeEventListener("keydown", f, !0), n.forEach((h) => h.removeAttribute("tabindex")), n.clear());
|
|
205
|
+
}
|
|
206
|
+
function v() {
|
|
207
207
|
if (a) return;
|
|
208
208
|
const h = m();
|
|
209
|
-
|
|
209
|
+
b(), h && e.onSelect(h);
|
|
210
210
|
}
|
|
211
|
-
function
|
|
212
|
-
a || (
|
|
211
|
+
function y() {
|
|
212
|
+
a || (b(), e.onCancel?.());
|
|
213
213
|
}
|
|
214
|
-
function
|
|
214
|
+
function f(h) {
|
|
215
215
|
if (!a)
|
|
216
216
|
switch (h.key) {
|
|
217
217
|
case "Tab":
|
|
@@ -228,28 +228,28 @@ function $t(e) {
|
|
|
228
228
|
case "Enter":
|
|
229
229
|
case " ":
|
|
230
230
|
case "Spacebar":
|
|
231
|
-
h.preventDefault(), h.stopPropagation(),
|
|
231
|
+
h.preventDefault(), h.stopPropagation(), v();
|
|
232
232
|
break;
|
|
233
233
|
case "Escape":
|
|
234
234
|
case "Esc":
|
|
235
|
-
h.preventDefault(), h.stopPropagation(),
|
|
235
|
+
h.preventDefault(), h.stopPropagation(), y();
|
|
236
236
|
break;
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
|
-
return o.addEventListener("keydown",
|
|
239
|
+
return o.addEventListener("keydown", f, !0), s >= 0 && r(), {
|
|
240
240
|
candidates: t,
|
|
241
241
|
getIndex: () => s,
|
|
242
242
|
getCurrent: m,
|
|
243
243
|
next: p,
|
|
244
244
|
prev: u,
|
|
245
|
-
moveTo:
|
|
246
|
-
select:
|
|
247
|
-
cancel:
|
|
248
|
-
handleKey:
|
|
249
|
-
stop:
|
|
245
|
+
moveTo: c,
|
|
246
|
+
select: v,
|
|
247
|
+
cancel: y,
|
|
248
|
+
handleKey: f,
|
|
249
|
+
stop: b
|
|
250
250
|
};
|
|
251
251
|
}
|
|
252
|
-
const
|
|
252
|
+
const F = "data-qaid-a11y-live", $t = "position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;", Nt = [
|
|
253
253
|
"a[href]",
|
|
254
254
|
"button",
|
|
255
255
|
"input",
|
|
@@ -257,19 +257,19 @@ const V = "data-qaid-a11y-live", Ot = "position:absolute;width:1px;height:1px;ma
|
|
|
257
257
|
"select",
|
|
258
258
|
"[tabindex]"
|
|
259
259
|
].join(",");
|
|
260
|
-
function
|
|
260
|
+
function Ft(e) {
|
|
261
261
|
return e.ownerDocument || document;
|
|
262
262
|
}
|
|
263
|
-
function
|
|
263
|
+
function Vt(e, t) {
|
|
264
264
|
const i = t ? "assertive" : "polite", o = e.querySelector(
|
|
265
|
-
`[${
|
|
265
|
+
`[${F}="${i}"]`
|
|
266
266
|
);
|
|
267
267
|
if (o) return o;
|
|
268
|
-
const s =
|
|
269
|
-
return s.setAttribute(
|
|
268
|
+
const s = Ft(e).createElement("div");
|
|
269
|
+
return s.setAttribute(F, i), s.setAttribute("role", t ? "alert" : "status"), s.setAttribute("aria-live", t ? "assertive" : "polite"), s.setAttribute("aria-atomic", "true"), s.style.cssText = $t, e.appendChild(s), s;
|
|
270
270
|
}
|
|
271
271
|
function Ut(e, t, i = {}) {
|
|
272
|
-
const o =
|
|
272
|
+
const o = Vt(e, !!i.assertive);
|
|
273
273
|
o.textContent = "", o.textContent = t;
|
|
274
274
|
}
|
|
275
275
|
function _t(e) {
|
|
@@ -286,7 +286,7 @@ function Kt(e) {
|
|
|
286
286
|
}
|
|
287
287
|
return !1;
|
|
288
288
|
}
|
|
289
|
-
function
|
|
289
|
+
function V(e) {
|
|
290
290
|
return Array.from(
|
|
291
291
|
e.querySelectorAll(Nt)
|
|
292
292
|
).filter((i) => !(i.getAttribute("tabindex") === "-1" || i instanceof HTMLInputElement && i.type === "hidden" || i instanceof HTMLAnchorElement && !i.getAttribute("href") || _t(i) || Kt(i)));
|
|
@@ -297,28 +297,28 @@ function Z(e) {
|
|
|
297
297
|
t = t.shadowRoot.activeElement;
|
|
298
298
|
return t instanceof HTMLElement ? t : null;
|
|
299
299
|
}
|
|
300
|
-
function
|
|
300
|
+
function jt(e) {
|
|
301
301
|
const t = e.ownerDocument || document;
|
|
302
302
|
let i = !1;
|
|
303
303
|
const o = (s) => {
|
|
304
304
|
if (s.key !== "Tab") return;
|
|
305
|
-
const a =
|
|
305
|
+
const a = V(e);
|
|
306
306
|
if (a.length === 0) {
|
|
307
307
|
s.preventDefault(), e.focus();
|
|
308
308
|
return;
|
|
309
309
|
}
|
|
310
|
-
const
|
|
311
|
-
s.shiftKey ? (!
|
|
310
|
+
const d = a[0], l = a[a.length - 1], r = Z(t), c = r ? a.indexOf(r) !== -1 : !1;
|
|
311
|
+
s.shiftKey ? (!c || r === d) && (s.preventDefault(), l.focus()) : (!c || r === l) && (s.preventDefault(), d.focus());
|
|
312
312
|
};
|
|
313
313
|
e.addEventListener("keydown", o);
|
|
314
|
-
const n =
|
|
314
|
+
const n = V(e);
|
|
315
315
|
return n.length > 0 ? n[0].focus() : (e.hasAttribute("tabindex") || (e.setAttribute("tabindex", "-1"), i = !0), e.focus()), {
|
|
316
316
|
release() {
|
|
317
317
|
e.removeEventListener("keydown", o), i && (e.removeAttribute("tabindex"), i = !1);
|
|
318
318
|
}
|
|
319
319
|
};
|
|
320
320
|
}
|
|
321
|
-
function
|
|
321
|
+
function Xt() {
|
|
322
322
|
return Z(document);
|
|
323
323
|
}
|
|
324
324
|
function Wt(e) {
|
|
@@ -352,8 +352,8 @@ function Gt(e) {
|
|
|
352
352
|
const o = Qt(e, i), n = [];
|
|
353
353
|
return Array.from(i.children).forEach((s) => {
|
|
354
354
|
if (!(s instanceof HTMLElement) || o && s === o) return;
|
|
355
|
-
const a = s.inert === !0,
|
|
356
|
-
a &&
|
|
355
|
+
const a = s.inert === !0, d = s.getAttribute("aria-hidden");
|
|
356
|
+
a && d === "true" || (s.inert = !0, s.setAttribute("aria-hidden", "true"), n.push({ el: s, prevInert: a, prevAriaHidden: d }));
|
|
357
357
|
}), function() {
|
|
358
358
|
for (; n.length; ) {
|
|
359
359
|
const a = n.pop();
|
|
@@ -380,12 +380,12 @@ function Jt(e, t, i, o, n) {
|
|
|
380
380
|
top: e.y - i - o,
|
|
381
381
|
position: "above"
|
|
382
382
|
};
|
|
383
|
-
const
|
|
384
|
-
let
|
|
385
|
-
return
|
|
383
|
+
const d = a > s ? "below" : "above";
|
|
384
|
+
let l;
|
|
385
|
+
return d === "below" ? l = Math.min(
|
|
386
386
|
e.y + e.height + o,
|
|
387
387
|
t - i - n
|
|
388
|
-
) :
|
|
388
|
+
) : l = Math.max(n, e.y - i - o), { top: l, position: d };
|
|
389
389
|
}
|
|
390
390
|
function Zt(e, t, i, o) {
|
|
391
391
|
let s = e.x + e.width / 2 - i / 2;
|
|
@@ -434,13 +434,13 @@ function oe(e, t, i, o = tt) {
|
|
|
434
434
|
}
|
|
435
435
|
const ne = 20;
|
|
436
436
|
function se(e) {
|
|
437
|
-
const t = [], i = console.error, o = console.warn, n = console.log, s = (a,
|
|
438
|
-
const
|
|
439
|
-
message:
|
|
437
|
+
const t = [], i = console.error, o = console.warn, n = console.log, s = (a, d) => {
|
|
438
|
+
const l = {
|
|
439
|
+
message: d.map((r) => String(r)).join(" "),
|
|
440
440
|
timestamp: Date.now(),
|
|
441
441
|
level: a
|
|
442
442
|
};
|
|
443
|
-
t.length >= ne && t.shift(), t.push(
|
|
443
|
+
t.length >= ne && t.shift(), t.push(l), e && e(l);
|
|
444
444
|
};
|
|
445
445
|
return console.error = function(...a) {
|
|
446
446
|
s("error", a), i.apply(console, a);
|
|
@@ -456,7 +456,7 @@ function se(e) {
|
|
|
456
456
|
};
|
|
457
457
|
}
|
|
458
458
|
const ae = 20, U = 4096;
|
|
459
|
-
function
|
|
459
|
+
function S(e) {
|
|
460
460
|
const t = typeof e == "string" ? e : JSON.stringify(e);
|
|
461
461
|
return t.length > U ? t.slice(0, U) + "…[truncated]" : t;
|
|
462
462
|
}
|
|
@@ -466,7 +466,7 @@ function _(e, t) {
|
|
|
466
466
|
async function re(e) {
|
|
467
467
|
try {
|
|
468
468
|
const t = await e.clone().text();
|
|
469
|
-
return
|
|
469
|
+
return S(t);
|
|
470
470
|
} catch {
|
|
471
471
|
return;
|
|
472
472
|
}
|
|
@@ -474,19 +474,19 @@ async function re(e) {
|
|
|
474
474
|
function de() {
|
|
475
475
|
const e = [], t = window.fetch;
|
|
476
476
|
window.fetch = async function(n, s) {
|
|
477
|
-
const a = typeof n == "string" ? n : n instanceof URL ? n.toString() : n.url,
|
|
478
|
-
let
|
|
479
|
-
s?.body && (
|
|
477
|
+
const a = typeof n == "string" ? n : n instanceof URL ? n.toString() : n.url, d = s?.method ?? (typeof n == "object" && "method" in n ? n.method : "GET");
|
|
478
|
+
let l;
|
|
479
|
+
s?.body && (l = S(s.body));
|
|
480
480
|
const r = await t.apply(window, [n, s]);
|
|
481
481
|
if (r.status >= 400) {
|
|
482
|
-
const
|
|
482
|
+
const c = await re(r);
|
|
483
483
|
_(e, {
|
|
484
484
|
url: a,
|
|
485
|
-
method:
|
|
485
|
+
method: d.toUpperCase(),
|
|
486
486
|
status: r.status,
|
|
487
487
|
statusText: r.statusText,
|
|
488
|
-
requestBody:
|
|
489
|
-
responseBody:
|
|
488
|
+
requestBody: l,
|
|
489
|
+
responseBody: c,
|
|
490
490
|
timestamp: Date.now()
|
|
491
491
|
});
|
|
492
492
|
}
|
|
@@ -496,7 +496,7 @@ function de() {
|
|
|
496
496
|
return XMLHttpRequest.prototype.open = function(n, s, ...a) {
|
|
497
497
|
return this._qaid_method = n, this._qaid_url = typeof s == "string" ? s : s.toString(), i.apply(this, [n, s, ...a]);
|
|
498
498
|
}, XMLHttpRequest.prototype.send = function(n) {
|
|
499
|
-
const s = this, a = n ?
|
|
499
|
+
const s = this, a = n ? S(n) : void 0;
|
|
500
500
|
return s.addEventListener("load", function() {
|
|
501
501
|
s.status >= 400 && _(e, {
|
|
502
502
|
url: s._qaid_url,
|
|
@@ -504,7 +504,7 @@ function de() {
|
|
|
504
504
|
status: s.status,
|
|
505
505
|
statusText: s.statusText,
|
|
506
506
|
requestBody: a,
|
|
507
|
-
responseBody:
|
|
507
|
+
responseBody: S(s.responseText),
|
|
508
508
|
timestamp: Date.now()
|
|
509
509
|
});
|
|
510
510
|
}), o.apply(this, [n]);
|
|
@@ -515,10 +515,73 @@ function de() {
|
|
|
515
515
|
}
|
|
516
516
|
};
|
|
517
517
|
}
|
|
518
|
-
function
|
|
518
|
+
function ce() {
|
|
519
|
+
const e = navigator.userAgent || "";
|
|
520
|
+
return /iP(hone|ad|od)/.test(e) || // iPadOS 13+ masquerades as "MacIntel" but is a multi-touch device.
|
|
521
|
+
navigator.platform === "MacIntel" && (navigator.maxTouchPoints || 0) > 1;
|
|
522
|
+
}
|
|
523
|
+
function le(e, t, i, o, n) {
|
|
524
|
+
const s = e >= t, a = i >= o;
|
|
525
|
+
return s === a ? { width: e, height: t, rotate: 0 } : { width: t, height: e, rotate: n === 270 ? -90 : 90 };
|
|
526
|
+
}
|
|
527
|
+
function he(e, t, i) {
|
|
528
|
+
if (i.rotate === 0) {
|
|
529
|
+
e.drawImage(t, 0, 0, i.width, i.height);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
e.save(), i.rotate === 90 ? (e.translate(i.width, 0), e.rotate(Math.PI / 2)) : (e.translate(0, i.height), e.rotate(-Math.PI / 2)), e.drawImage(t, 0, 0, i.height, i.width), e.restore();
|
|
533
|
+
}
|
|
534
|
+
function ue() {
|
|
535
|
+
const e = typeof screen < "u" ? screen.orientation : void 0;
|
|
536
|
+
return e && typeof e.angle == "number" ? e.angle : 0;
|
|
537
|
+
}
|
|
538
|
+
function pe(e) {
|
|
539
|
+
return new Promise((t) => {
|
|
540
|
+
if (e.videoWidth > 0) {
|
|
541
|
+
t();
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
e.addEventListener("loadedmetadata", () => t(), { once: !0 });
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
async function me(e) {
|
|
548
|
+
try {
|
|
549
|
+
await e.play();
|
|
550
|
+
} catch {
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
async function fe(e, t = 15) {
|
|
554
|
+
const i = document.createElement("canvas");
|
|
555
|
+
if (typeof i.captureStream != "function") return null;
|
|
556
|
+
const o = i.getContext("2d");
|
|
557
|
+
if (!o) return null;
|
|
558
|
+
const n = document.createElement("video");
|
|
559
|
+
n.muted = !0, n.playsInline = !0, n.srcObject = e, await pe(n);
|
|
560
|
+
const s = le(
|
|
561
|
+
n.videoWidth,
|
|
562
|
+
n.videoHeight,
|
|
563
|
+
window.innerWidth,
|
|
564
|
+
window.innerHeight,
|
|
565
|
+
ue()
|
|
566
|
+
);
|
|
567
|
+
i.width = s.width, i.height = s.height, await me(n);
|
|
568
|
+
let a = 0;
|
|
569
|
+
const d = () => {
|
|
570
|
+
he(o, n, s), a = requestAnimationFrame(d);
|
|
571
|
+
};
|
|
572
|
+
d();
|
|
573
|
+
const l = i.captureStream(t);
|
|
574
|
+
return {
|
|
575
|
+
stream: l,
|
|
576
|
+
stop: () => {
|
|
577
|
+
a && cancelAnimationFrame(a), a = 0, l.getTracks().forEach((r) => r.stop()), n.pause(), n.srcObject = null;
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
function be() {
|
|
519
582
|
return typeof navigator < "u" && !!navigator.mediaDevices && typeof navigator.mediaDevices.getDisplayMedia == "function" && typeof MediaRecorder < "u";
|
|
520
583
|
}
|
|
521
|
-
function
|
|
584
|
+
function ge() {
|
|
522
585
|
if (typeof MediaRecorder > "u") return "";
|
|
523
586
|
const e = [
|
|
524
587
|
"video/webm;codecs=vp9",
|
|
@@ -531,19 +594,19 @@ function ce() {
|
|
|
531
594
|
return t;
|
|
532
595
|
return "";
|
|
533
596
|
}
|
|
534
|
-
function
|
|
597
|
+
function ve(e = {}) {
|
|
535
598
|
const t = e.maxDuration ?? 15, i = e.videoBitsPerSecond ?? 8e5;
|
|
536
|
-
let o = null, n = null, s = [],
|
|
537
|
-
function
|
|
538
|
-
|
|
599
|
+
let o = null, n = null, s = null, a = [], d = null, l = null, r = null, c = 0, p = null, u = null, m = !1, b = null;
|
|
600
|
+
function v() {
|
|
601
|
+
r !== null && (clearInterval(r), r = null), b !== null && (clearTimeout(b), b = null), n && (n.stop(), n = null), o && (o.getTracks().forEach((f) => f.stop()), o = null), s = null, a = [], d = null, l = null, p = null, u = null;
|
|
539
602
|
}
|
|
540
|
-
function
|
|
541
|
-
|
|
603
|
+
function y() {
|
|
604
|
+
m || (m = !0, s && s.state !== "inactive" && s.stop());
|
|
542
605
|
}
|
|
543
606
|
return {
|
|
544
607
|
async start() {
|
|
545
|
-
|
|
546
|
-
const f =
|
|
608
|
+
m = !1, a = [];
|
|
609
|
+
const f = ge();
|
|
547
610
|
if (!f)
|
|
548
611
|
throw new Error("No supported video MIME type found");
|
|
549
612
|
o = await navigator.mediaDevices.getDisplayMedia({
|
|
@@ -554,43 +617,49 @@ function he(e = {}) {
|
|
|
554
617
|
// @ts-expect-error preferCurrentTab is not in the TS types yet
|
|
555
618
|
preferCurrentTab: !0
|
|
556
619
|
});
|
|
557
|
-
const
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
})
|
|
620
|
+
const h = o.getVideoTracks()[0];
|
|
621
|
+
h && h.addEventListener("ended", () => {
|
|
622
|
+
y();
|
|
623
|
+
});
|
|
624
|
+
let w = o;
|
|
625
|
+
if (ce()) {
|
|
626
|
+
const g = await fe(o);
|
|
627
|
+
g && (n = g, w = g.stream);
|
|
628
|
+
}
|
|
629
|
+
s = new MediaRecorder(w, {
|
|
561
630
|
mimeType: f,
|
|
562
631
|
videoBitsPerSecond: i
|
|
563
|
-
}),
|
|
564
|
-
|
|
565
|
-
},
|
|
566
|
-
const
|
|
567
|
-
|
|
568
|
-
},
|
|
569
|
-
|
|
570
|
-
},
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
}, 1e3),
|
|
574
|
-
|
|
632
|
+
}), s.ondataavailable = (g) => {
|
|
633
|
+
g.data.size > 0 && a.push(g.data);
|
|
634
|
+
}, s.onstop = () => {
|
|
635
|
+
const g = new Blob(a, { type: f });
|
|
636
|
+
p && p(g), l && l(g), n && (n.stop(), n = null), o && o.getTracks().forEach((C) => C.stop());
|
|
637
|
+
}, s.onerror = () => {
|
|
638
|
+
u && u(new Error("MediaRecorder error"));
|
|
639
|
+
}, s.start(1e3), c = Date.now(), r = setInterval(() => {
|
|
640
|
+
const g = Math.floor((Date.now() - c) / 1e3);
|
|
641
|
+
d && d(g);
|
|
642
|
+
}, 1e3), b = setTimeout(() => {
|
|
643
|
+
y();
|
|
575
644
|
}, t * 1e3);
|
|
576
645
|
},
|
|
577
646
|
stop() {
|
|
578
|
-
return new Promise((f,
|
|
579
|
-
|
|
647
|
+
return new Promise((f, h) => {
|
|
648
|
+
p = f, u = h, y();
|
|
580
649
|
});
|
|
581
650
|
},
|
|
582
651
|
onTick(f) {
|
|
583
|
-
|
|
652
|
+
d = f;
|
|
584
653
|
},
|
|
585
654
|
onStop(f) {
|
|
586
655
|
l = f;
|
|
587
656
|
},
|
|
588
657
|
destroy() {
|
|
589
|
-
|
|
658
|
+
y(), v();
|
|
590
659
|
}
|
|
591
660
|
};
|
|
592
661
|
}
|
|
593
|
-
function
|
|
662
|
+
function ye(e = 640) {
|
|
594
663
|
return typeof window < "u" && window.innerWidth < e;
|
|
595
664
|
}
|
|
596
665
|
function K(e, t, i) {
|
|
@@ -599,10 +668,10 @@ function K(e, t, i) {
|
|
|
599
668
|
const n = document.elementFromPoint(e, t);
|
|
600
669
|
return i.forEach((s, a) => s.style.visibility = o[a]), n;
|
|
601
670
|
}
|
|
602
|
-
function
|
|
671
|
+
function M(e) {
|
|
603
672
|
return e ? e.hasAttribute("data-qaid-embed") || e.hasAttribute("data-qaid-embed-overlay") ? !0 : !!e.closest("[data-qaid-embed], [data-qaid-embed-overlay]") : !1;
|
|
604
673
|
}
|
|
605
|
-
function
|
|
674
|
+
function j(e, t = 0) {
|
|
606
675
|
const i = e.getBoundingClientRect();
|
|
607
676
|
return {
|
|
608
677
|
x: i.left - t,
|
|
@@ -611,7 +680,7 @@ function X(e, t = 0) {
|
|
|
611
680
|
height: i.height + t * 2
|
|
612
681
|
};
|
|
613
682
|
}
|
|
614
|
-
async function
|
|
683
|
+
async function we(e = {}) {
|
|
615
684
|
const { quality: t = 1, maxWidth: i = 1280, maxHeight: o = 800 } = e;
|
|
616
685
|
try {
|
|
617
686
|
if (!navigator.mediaDevices?.getDisplayMedia)
|
|
@@ -621,59 +690,59 @@ async function pe(e = {}) {
|
|
|
621
690
|
video: {
|
|
622
691
|
displaySurface: "browser"
|
|
623
692
|
}
|
|
624
|
-
}), s = n.getVideoTracks()[0], a = s.getSettings(),
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
693
|
+
}), s = n.getVideoTracks()[0], a = s.getSettings(), d = document.createElement("video");
|
|
694
|
+
d.srcObject = n, d.muted = !0, await new Promise((v) => {
|
|
695
|
+
d.onloadedmetadata = () => {
|
|
696
|
+
d.play(), v();
|
|
628
697
|
};
|
|
629
|
-
}), await new Promise((
|
|
630
|
-
const
|
|
631
|
-
|
|
698
|
+
}), await new Promise((v) => {
|
|
699
|
+
const y = () => {
|
|
700
|
+
d.readyState >= 2 ? v() : requestAnimationFrame(y);
|
|
632
701
|
};
|
|
633
|
-
|
|
634
|
-
}), await new Promise((
|
|
635
|
-
const
|
|
702
|
+
y();
|
|
703
|
+
}), await new Promise((v) => setTimeout(v, 100));
|
|
704
|
+
const l = a.width || d.videoWidth, r = a.height || d.videoHeight, c = Math.min(i / l, o / r, 1), p = Math.round(l * c), u = Math.round(r * c), m = document.createElement("canvas");
|
|
636
705
|
m.width = p, m.height = u;
|
|
637
|
-
const
|
|
638
|
-
return
|
|
706
|
+
const b = m.getContext("2d");
|
|
707
|
+
return b ? (b.drawImage(d, 0, 0, p, u), s.stop(), m.toDataURL("image/webp", t)) : (s.stop(), null);
|
|
639
708
|
} catch (n) {
|
|
640
709
|
return console.warn("Screenshot capture failed:", n), null;
|
|
641
710
|
}
|
|
642
711
|
}
|
|
643
|
-
const
|
|
644
|
-
let
|
|
645
|
-
function
|
|
712
|
+
const X = "https://qaid.dev/lib/html2canvas.min.js", xe = 1e4, qe = 50;
|
|
713
|
+
let x = null;
|
|
714
|
+
function Pe() {
|
|
646
715
|
if (typeof document > "u" || typeof window > "u")
|
|
647
716
|
return !1;
|
|
648
717
|
const e = document.createElement("canvas");
|
|
649
718
|
return typeof e.getContext == "function" && !!e.getContext("2d");
|
|
650
719
|
}
|
|
651
|
-
function
|
|
652
|
-
return window.html2canvas ? Promise.resolve(!0) :
|
|
720
|
+
function ke() {
|
|
721
|
+
return window.html2canvas ? Promise.resolve(!0) : x || (x = new Promise((e) => {
|
|
653
722
|
if (!document.querySelector(
|
|
654
|
-
`script[src="${
|
|
723
|
+
`script[src="${X}"]`
|
|
655
724
|
)) {
|
|
656
725
|
const n = document.createElement("script");
|
|
657
|
-
n.src =
|
|
726
|
+
n.src = X, n.async = !0, document.head.appendChild(n);
|
|
658
727
|
}
|
|
659
728
|
const i = Date.now(), o = () => {
|
|
660
729
|
if (window.html2canvas) {
|
|
661
730
|
e(!0);
|
|
662
731
|
return;
|
|
663
732
|
}
|
|
664
|
-
if (Date.now() - i >
|
|
665
|
-
|
|
733
|
+
if (Date.now() - i > xe) {
|
|
734
|
+
x = null, e(!1);
|
|
666
735
|
return;
|
|
667
736
|
}
|
|
668
|
-
setTimeout(o,
|
|
737
|
+
setTimeout(o, qe);
|
|
669
738
|
};
|
|
670
739
|
o();
|
|
671
|
-
}),
|
|
740
|
+
}), x);
|
|
672
741
|
}
|
|
673
|
-
async function
|
|
742
|
+
async function Ce(e = {}) {
|
|
674
743
|
const { quality: t = 0.8, maxWidth: i = 1280, maxHeight: o = 800 } = e;
|
|
675
744
|
try {
|
|
676
|
-
if (!await
|
|
745
|
+
if (!await ke() || !window.html2canvas)
|
|
677
746
|
return console.warn("html2canvas failed to load"), null;
|
|
678
747
|
const s = await window.html2canvas(document.body, {
|
|
679
748
|
useCORS: !0,
|
|
@@ -686,19 +755,19 @@ async function ge(e = {}) {
|
|
|
686
755
|
x: window.scrollX,
|
|
687
756
|
y: window.scrollY,
|
|
688
757
|
ignoreElements: (r) => r instanceof HTMLElement ? r.classList.contains("qaid-buttons") || r.classList.contains("qaid-targeting-overlay") || r.classList.contains("qaid-modal-container") || r.classList.contains("qaid-bottom-sheet") || r.classList.contains("qaid-backdrop") || r.classList.contains("qaid-selected-marker") || r.classList.contains("qaid-tooltip-text") || r.classList.contains("qaid-recording-indicator") || r.classList.contains("qaid-video-preview") || r.className?.toString().startsWith?.("qaid-") : !1
|
|
689
|
-
}), a = s.width,
|
|
690
|
-
if (
|
|
691
|
-
const r = Math.round(a *
|
|
692
|
-
p.width = r, p.height =
|
|
758
|
+
}), a = s.width, d = s.height, l = Math.min(i / a, o / d, 1);
|
|
759
|
+
if (l < 1) {
|
|
760
|
+
const r = Math.round(a * l), c = Math.round(d * l), p = document.createElement("canvas");
|
|
761
|
+
p.width = r, p.height = c;
|
|
693
762
|
const u = p.getContext("2d");
|
|
694
|
-
return u ? (u.drawImage(s, 0, 0, r,
|
|
763
|
+
return u ? (u.drawImage(s, 0, 0, r, c), p.toDataURL("image/webp", t)) : null;
|
|
695
764
|
}
|
|
696
765
|
return s.toDataURL("image/webp", t);
|
|
697
766
|
} catch (n) {
|
|
698
767
|
return console.warn("DOM screenshot capture failed:", n), null;
|
|
699
768
|
}
|
|
700
769
|
}
|
|
701
|
-
const
|
|
770
|
+
const Se = "https://unpkg.com/@qaiddev/quests-embed@1/dist/qaid-quests.js", Ee = (e) => (
|
|
702
771
|
// The URL is a runtime value, not a static specifier — keep Vite from
|
|
703
772
|
// trying to analyze/bundle it.
|
|
704
773
|
import(
|
|
@@ -706,19 +775,19 @@ const ve = "https://unpkg.com/@qaiddev/quests-embed@1/dist/qaid-quests.js", ye =
|
|
|
706
775
|
e
|
|
707
776
|
)
|
|
708
777
|
);
|
|
709
|
-
let
|
|
710
|
-
function
|
|
711
|
-
return
|
|
778
|
+
let Te = Ee, q = null, R = null;
|
|
779
|
+
function Le(e) {
|
|
780
|
+
return q && R === e || (R = e, q = Promise.resolve(Te(e)).then((t) => {
|
|
712
781
|
const i = t;
|
|
713
782
|
if (!i || typeof i.QaidQuests != "function")
|
|
714
783
|
throw new Error("quests module has no QaidQuests export");
|
|
715
784
|
return i;
|
|
716
785
|
}).catch((t) => {
|
|
717
|
-
throw
|
|
718
|
-
})),
|
|
786
|
+
throw q = null, R = null, t;
|
|
787
|
+
})), q;
|
|
719
788
|
}
|
|
720
|
-
async function
|
|
721
|
-
const t = await
|
|
789
|
+
async function Ie(e) {
|
|
790
|
+
const t = await Le(e.moduleUrl), i = e.base.replace(/\/+$/, ""), o = e.feedbackId != null ? { feedbackId: e.feedbackId } : void 0;
|
|
722
791
|
return new t.QaidQuests({
|
|
723
792
|
endpoint: `${i}/responses`,
|
|
724
793
|
configUrl: `${i}/${encodeURIComponent(e.questId)}/definition`,
|
|
@@ -727,24 +796,24 @@ async function qe(e) {
|
|
|
727
796
|
onClose: e.onClose
|
|
728
797
|
});
|
|
729
798
|
}
|
|
730
|
-
const W = "qaid_visitor_id", Y = "qaid_hide_feedback";
|
|
731
|
-
function
|
|
799
|
+
const W = "qaid_visitor_id", Y = "qaid_hide_feedback", Ae = 12;
|
|
800
|
+
function H(e) {
|
|
732
801
|
return e ? `${Y}_${e}` : Y;
|
|
733
802
|
}
|
|
734
|
-
function
|
|
803
|
+
function De(e) {
|
|
735
804
|
try {
|
|
736
|
-
return localStorage.getItem(
|
|
805
|
+
return localStorage.getItem(H(e)) === "1";
|
|
737
806
|
} catch {
|
|
738
807
|
return !1;
|
|
739
808
|
}
|
|
740
809
|
}
|
|
741
810
|
function Q(e, t = !0) {
|
|
742
811
|
try {
|
|
743
|
-
t ? localStorage.setItem(
|
|
812
|
+
t ? localStorage.setItem(H(e), "1") : localStorage.removeItem(H(e));
|
|
744
813
|
} catch {
|
|
745
814
|
}
|
|
746
815
|
}
|
|
747
|
-
function
|
|
816
|
+
function Me() {
|
|
748
817
|
try {
|
|
749
818
|
let e = localStorage.getItem(W);
|
|
750
819
|
return e || (e = crypto.randomUUID(), localStorage.setItem(W, e)), e;
|
|
@@ -752,7 +821,7 @@ function Ce() {
|
|
|
752
821
|
return crypto.randomUUID();
|
|
753
822
|
}
|
|
754
823
|
}
|
|
755
|
-
class
|
|
824
|
+
class Re {
|
|
756
825
|
config;
|
|
757
826
|
state = "IDLE";
|
|
758
827
|
feedbackData = {
|
|
@@ -823,6 +892,13 @@ class Ee {
|
|
|
823
892
|
boundKeyDown;
|
|
824
893
|
boundMouseMove;
|
|
825
894
|
boundClick;
|
|
895
|
+
// Touch equivalents for targeting. iOS/iPadOS does not synthesise `click`
|
|
896
|
+
// (or `mousemove`) for taps on non-interactive page elements, so targeting
|
|
897
|
+
// must be driven by touch events there.
|
|
898
|
+
boundTouchStart;
|
|
899
|
+
boundTouchEnd;
|
|
900
|
+
// Where the current targeting touch began, to tell a tap from a scroll.
|
|
901
|
+
touchStartPos = null;
|
|
826
902
|
boundResize;
|
|
827
903
|
// Start with buttons slid off-screen (localStorage dismiss, no animation)
|
|
828
904
|
_startDismissed = !1;
|
|
@@ -891,12 +967,12 @@ class Ee {
|
|
|
891
967
|
video: t.quests?.video ?? "",
|
|
892
968
|
// Quest service reuses the feedback API key unless overridden.
|
|
893
969
|
apiKey: t.quests?.apiKey ?? t.apiKey ?? "",
|
|
894
|
-
moduleUrl: t.quests?.moduleUrl ??
|
|
970
|
+
moduleUrl: t.quests?.moduleUrl ?? Se
|
|
895
971
|
}
|
|
896
|
-
}, 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 =
|
|
972
|
+
}, this.boundKeyDown = this.handleKeyDown.bind(this), this.boundMouseMove = this.handleMouseMove.bind(this), this.boundClick = this.handleClick.bind(this), this.boundTouchStart = this.handleTouchStart.bind(this), this.boundTouchEnd = this.handleTouchEnd.bind(this), this.boundResize = this.handleResize.bind(this), this.visitorId = Me(), this.init();
|
|
897
973
|
}
|
|
898
974
|
applyVars(t) {
|
|
899
|
-
|
|
975
|
+
Et(t, this.cssVars);
|
|
900
976
|
}
|
|
901
977
|
/**
|
|
902
978
|
* Announce a message via the shared visually-hidden live regions.
|
|
@@ -914,7 +990,7 @@ class Ee {
|
|
|
914
990
|
* background. Paired with closeDialogA11y() on every close path.
|
|
915
991
|
*/
|
|
916
992
|
openDialogA11y(t, i) {
|
|
917
|
-
this.dialogTrigger =
|
|
993
|
+
this.dialogTrigger = Xt(), Yt(t, i), this.dialogTrap = jt(t), this.dialogRestoreInert = Gt(t);
|
|
918
994
|
}
|
|
919
995
|
closeDialogA11y() {
|
|
920
996
|
this.dialogTrap?.release(), this.dialogTrap = null, this.dialogRestoreInert && (this.dialogRestoreInert(), this.dialogRestoreInert = null), Wt(this.dialogTrigger), this.dialogTrigger = null;
|
|
@@ -923,7 +999,7 @@ class Ee {
|
|
|
923
999
|
this.activeThumbBtn && (this.activeThumbBtn.setAttribute("aria-pressed", "false"), this.activeThumbBtn = null);
|
|
924
1000
|
}
|
|
925
1001
|
init() {
|
|
926
|
-
Tt(), this.cssVars =
|
|
1002
|
+
Tt(), this.cssVars = St({
|
|
927
1003
|
positiveColor: this.config.colors.positive,
|
|
928
1004
|
negativeColor: this.config.colors.negative,
|
|
929
1005
|
markerColor: this.config.colors.marker,
|
|
@@ -932,7 +1008,7 @@ class Ee {
|
|
|
932
1008
|
backdropOpacity: this.config.backdropOpacity,
|
|
933
1009
|
fontFamily: this.config.fontFamily,
|
|
934
1010
|
fontSize: this.config.fontSize
|
|
935
|
-
}), !this.config.hideDismiss &&
|
|
1011
|
+
}), !this.config.hideDismiss && De(this.config.apiKey) && (this._startDismissed = !0), this.checkMobile(), window.addEventListener("resize", this.boundResize), this.createEmbed(), this.consoleCapture = se((t) => {
|
|
936
1012
|
this.feedbackData.consoleErrors = this.consoleCapture?.errors ?? [];
|
|
937
1013
|
}), this.feedbackData.consoleErrors = this.consoleCapture.errors, this.observeDom();
|
|
938
1014
|
}
|
|
@@ -955,7 +1031,7 @@ class Ee {
|
|
|
955
1031
|
}), this.domObserver.observe(document.body, { childList: !0 });
|
|
956
1032
|
}
|
|
957
1033
|
checkMobile() {
|
|
958
|
-
this.isMobile =
|
|
1034
|
+
this.isMobile = ye();
|
|
959
1035
|
}
|
|
960
1036
|
handleResize() {
|
|
961
1037
|
this.checkMobile();
|
|
@@ -974,8 +1050,8 @@ class Ee {
|
|
|
974
1050
|
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");
|
|
975
1051
|
else {
|
|
976
1052
|
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";
|
|
977
|
-
const { x: r, y:
|
|
978
|
-
this.config.position.includes("right") ? this.buttonsContainer.style.right = `${r}px` : this.buttonsContainer.style.left = `${r}px`, this.config.position.includes("bottom") ? this.buttonsContainer.style.bottom = `${
|
|
1053
|
+
const { x: r, y: c } = this.config.offset;
|
|
1054
|
+
this.config.position.includes("right") ? this.buttonsContainer.style.right = `${r}px` : this.buttonsContainer.style.left = `${r}px`, this.config.position.includes("bottom") ? this.buttonsContainer.style.bottom = `${c}px` : this.buttonsContainer.style.top = `${c}px`;
|
|
979
1055
|
}
|
|
980
1056
|
this.applyVars(this.buttonsContainer), this.shadowRoot.appendChild(this.buttonsContainer), this.buttonsContainer.addEventListener("keydown", (r) => {
|
|
981
1057
|
(r.key === "Enter" || r.key === " " || r.key === "Spacebar") && (this.keyboardActivation = !0);
|
|
@@ -984,22 +1060,22 @@ class Ee {
|
|
|
984
1060
|
}), this.buttonsContainer.addEventListener("pointerdown", () => {
|
|
985
1061
|
this.keyboardActivation = !1;
|
|
986
1062
|
});
|
|
987
|
-
const n = !!this.config.buttonClass, s = n ? `qaid-btn-structural ${this.config.buttonClass}` : "qaid-btn",
|
|
988
|
-
if (
|
|
1063
|
+
const n = !!this.config.buttonClass, s = n ? `qaid-btn-structural ${this.config.buttonClass}` : "qaid-btn", d = this.config.text.tooltip || "Feedback for us?", l = document.createElement("div");
|
|
1064
|
+
if (l.className = "qaid-tooltip-text", l.textContent = d, this.applyVars(l), this.shadowRoot.appendChild(l), this.tooltipElement = l, !this.config.hideThumbs) {
|
|
989
1065
|
const r = document.createElement("div");
|
|
990
1066
|
r.className = "qaid-tooltip-wrapper";
|
|
991
|
-
const
|
|
992
|
-
|
|
1067
|
+
const c = document.createElement("button");
|
|
1068
|
+
c.type = "button", c.className = n ? `${s} qaid-btn-up` : "qaid-btn qaid-btn-up", c.setAttribute("aria-label", this.config.text.positiveLabel), c.innerHTML = this.config.positiveIcon || I, c.addEventListener("click", (m) => this.handleThumbClick("up", m.currentTarget, m)), c.addEventListener("mouseenter", () => this.showTooltip(c)), c.addEventListener("mouseleave", () => this.hideTooltip()), r.appendChild(c);
|
|
993
1069
|
const p = document.createElement("div");
|
|
994
1070
|
p.className = "qaid-tooltip-wrapper";
|
|
995
1071
|
const u = document.createElement("button");
|
|
996
|
-
u.type = "button", u.className = n ? `${s} qaid-btn-down` : "qaid-btn qaid-btn-down", u.setAttribute("aria-label", this.config.text.negativeLabel), u.innerHTML = this.config.negativeIcon ||
|
|
1072
|
+
u.type = "button", u.className = n ? `${s} qaid-btn-down` : "qaid-btn qaid-btn-down", u.setAttribute("aria-label", this.config.text.negativeLabel), u.innerHTML = this.config.negativeIcon || A, u.addEventListener("click", (m) => this.handleThumbClick("down", m.currentTarget, m)), u.addEventListener("mouseenter", () => this.showTooltip(u)), u.addEventListener("mouseleave", () => this.hideTooltip()), p.appendChild(u), this.buttonsContainer.appendChild(r), this.buttonsContainer.appendChild(p);
|
|
997
1073
|
}
|
|
998
|
-
if (this.config.captureVideo &&
|
|
1074
|
+
if (this.config.captureVideo && be()) {
|
|
999
1075
|
const r = document.createElement("div");
|
|
1000
1076
|
r.className = "qaid-tooltip-wrapper";
|
|
1001
|
-
const
|
|
1002
|
-
|
|
1077
|
+
const c = document.createElement("button");
|
|
1078
|
+
c.type = "button", c.className = n ? `${s} qaid-btn-record` : "qaid-btn qaid-btn-record", c.setAttribute("aria-label", this.config.text.recordLabel), c.innerHTML = this.config.recordIcon || bt, c.addEventListener("click", () => this.startRecording()), c.addEventListener("mouseenter", () => this.showTooltip(c)), c.addEventListener("mouseleave", () => this.hideTooltip()), r.appendChild(c), this.buttonsContainer.appendChild(r);
|
|
1003
1079
|
}
|
|
1004
1080
|
this.config.hideDismiss || (this.dismissBtn = document.createElement("button"), this.dismissBtn.type = "button", this.dismissBtn.className = "qaid-dismiss-btn", this.dismissBtn.setAttribute("aria-label", this.config.text.dismissLabel), this.dismissBtn.title = this.config.text.dismissLabel, 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", (r) => {
|
|
1005
1081
|
r.stopPropagation(), this.handleDismiss();
|
|
@@ -1061,7 +1137,7 @@ class Ee {
|
|
|
1061
1137
|
}, this.submitFeedback();
|
|
1062
1138
|
}
|
|
1063
1139
|
startTargeting(t, i) {
|
|
1064
|
-
this.state = "TARGETING", this.feedbackData.feedbackType = t, this.feedbackData.elementSelector = null, this.feedbackData.elementText = null, this.selectedBounds.visible = !1, this.mousePos.x = i.clientX, this.mousePos.y = i.clientY, document.body.classList.add("qaid-targeting"), t === "up" ? document.body.classList.add("qaid-type-up") : document.body.classList.remove("qaid-type-up"), document.body.style.setProperty("--qaid-positive", this.cssVars["--qaid-positive"]), document.body.style.setProperty("--qaid-negative", this.cssVars["--qaid-negative"]), this.createTargetingOverlay(), document.addEventListener("keydown", this.boundKeyDown), document.addEventListener("mousemove", this.boundMouseMove), document.addEventListener("click", this.boundClick, !0);
|
|
1140
|
+
this.state = "TARGETING", this.feedbackData.feedbackType = t, this.feedbackData.elementSelector = null, this.feedbackData.elementText = null, this.selectedBounds.visible = !1, this.mousePos.x = i.clientX, this.mousePos.y = i.clientY, document.body.classList.add("qaid-targeting"), t === "up" ? document.body.classList.add("qaid-type-up") : document.body.classList.remove("qaid-type-up"), document.body.style.setProperty("--qaid-positive", this.cssVars["--qaid-positive"]), document.body.style.setProperty("--qaid-negative", this.cssVars["--qaid-negative"]), this.createTargetingOverlay(), document.addEventListener("keydown", this.boundKeyDown), document.addEventListener("mousemove", this.boundMouseMove), document.addEventListener("click", this.boundClick, !0), document.addEventListener("touchstart", this.boundTouchStart, { passive: !0 }), document.addEventListener("touchend", this.boundTouchEnd, { passive: !1 });
|
|
1065
1141
|
}
|
|
1066
1142
|
/**
|
|
1067
1143
|
* Keyboard-driven targeting. Mirrors startTargeting minus the mouse
|
|
@@ -1070,12 +1146,12 @@ class Ee {
|
|
|
1070
1146
|
* The KeyboardTargetingController owns Tab/Arrow/Enter/Space/Escape.
|
|
1071
1147
|
*/
|
|
1072
1148
|
startKeyboardTargetingFlow(t) {
|
|
1073
|
-
this.state = "TARGETING", this.feedbackData.feedbackType = t, this.feedbackData.elementSelector = null, this.feedbackData.elementText = null, this.selectedBounds.visible = !1, document.body.style.setProperty("--qaid-positive", this.cssVars["--qaid-positive"]), document.body.style.setProperty("--qaid-negative", this.cssVars["--qaid-negative"]), this.createTargetingOverlay(), this.crosshairH && (this.crosshairH.style.display = "none"), this.crosshairV && (this.crosshairV.style.display = "none"), this.scope && (this.scope.style.display = "none"), this.keyboardController =
|
|
1074
|
-
isExcluded: (i) =>
|
|
1149
|
+
this.state = "TARGETING", this.feedbackData.feedbackType = t, this.feedbackData.elementSelector = null, this.feedbackData.elementText = null, this.selectedBounds.visible = !1, document.body.style.setProperty("--qaid-positive", this.cssVars["--qaid-positive"]), document.body.style.setProperty("--qaid-negative", this.cssVars["--qaid-negative"]), this.createTargetingOverlay(), this.crosshairH && (this.crosshairH.style.display = "none"), this.crosshairV && (this.crosshairV.style.display = "none"), this.scope && (this.scope.style.display = "none"), this.keyboardController = Ot({
|
|
1150
|
+
isExcluded: (i) => M(i),
|
|
1075
1151
|
onHighlight: (i) => {
|
|
1076
1152
|
const o = i.getBoundingClientRect(), n = this.highlightBox;
|
|
1077
1153
|
n && (n.style.transform = `translate(${o.left}px, ${o.top}px)`, n.style.width = `${o.width}px`, n.style.height = `${o.height}px`, n.style.display = "block");
|
|
1078
|
-
const { text: s } =
|
|
1154
|
+
const { text: s } = D(i);
|
|
1079
1155
|
this.announceMsg(`Targeting ${s || i.tagName.toLowerCase()}`);
|
|
1080
1156
|
},
|
|
1081
1157
|
onSelect: (i) => this.selectKeyboardTarget(i),
|
|
@@ -1083,14 +1159,14 @@ class Ee {
|
|
|
1083
1159
|
});
|
|
1084
1160
|
}
|
|
1085
1161
|
selectKeyboardTarget(t) {
|
|
1086
|
-
const i =
|
|
1162
|
+
const i = j(t, 8);
|
|
1087
1163
|
this.selectedBounds = {
|
|
1088
1164
|
...i,
|
|
1089
1165
|
clickX: i.x + i.width / 2,
|
|
1090
1166
|
clickY: i.y + i.height / 2,
|
|
1091
1167
|
visible: !0
|
|
1092
1168
|
};
|
|
1093
|
-
const { selector: o, text: n } =
|
|
1169
|
+
const { selector: o, text: n } = D(t);
|
|
1094
1170
|
this.feedbackData.elementSelector = o, this.feedbackData.elementText = n, this.removeTargetingOverlay(), document.body.classList.remove("qaid-targeting", "qaid-type-up"), document.body.style.removeProperty("--qaid-positive"), document.body.style.removeProperty("--qaid-negative"), this.keyboardController = null, this.clearActiveThumb(), this.state = "SELECTED", this.showSelectedMarker(), this.submitFeedback();
|
|
1095
1171
|
}
|
|
1096
1172
|
createTargetingOverlay() {
|
|
@@ -1107,42 +1183,61 @@ class Ee {
|
|
|
1107
1183
|
t.key === "Escape" && (this.isRecording ? this.stopRecording() : this.videoPreview ? this.cancelRecordingPreview() : this.state === "TARGETING" ? this.cancelTargeting() : this.state === "MODAL_OPEN" && this.closeModal());
|
|
1108
1184
|
}
|
|
1109
1185
|
handleMouseMove(t) {
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1186
|
+
this.updateReticleAt(t.clientX, t.clientY);
|
|
1187
|
+
}
|
|
1188
|
+
/** Move the crosshair/scope reticle and highlight the element under (x, y).
|
|
1189
|
+
* Shared by the mouse (hover) and touch (drag) targeting paths. */
|
|
1190
|
+
updateReticleAt(t, i) {
|
|
1191
|
+
if (this.mousePos.x = t, this.mousePos.y = i, this.crosshairH && (this.crosshairH.style.top = `${i}px`), this.crosshairV && (this.crosshairV.style.left = `${t}px`), this.scope && (this.scope.style.left = `${t}px`, this.scope.style.top = `${i}px`), this.captureLayer && this.shadowHost) {
|
|
1192
|
+
const o = [this.shadowHost, this.overlayShadowHost].filter(Boolean), n = K(t, i, o);
|
|
1193
|
+
if (n && !M(n)) {
|
|
1117
1194
|
if (this.highlightBox) {
|
|
1118
|
-
const
|
|
1119
|
-
this.highlightBox.style.transform = `translate(${
|
|
1195
|
+
const s = n.getBoundingClientRect();
|
|
1196
|
+
this.highlightBox.style.transform = `translate(${s.left}px, ${s.top}px)`, this.highlightBox.style.width = `${s.width}px`, this.highlightBox.style.height = `${s.height}px`, this.highlightBox.style.display = "block";
|
|
1120
1197
|
}
|
|
1121
1198
|
} else
|
|
1122
1199
|
this.highlightBox && (this.highlightBox.style.display = "none");
|
|
1123
1200
|
}
|
|
1124
1201
|
}
|
|
1125
1202
|
handleClick(t) {
|
|
1126
|
-
t.preventDefault(), t.stopPropagation();
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1203
|
+
t.preventDefault(), t.stopPropagation(), this.selectAt(t.clientX, t.clientY);
|
|
1204
|
+
}
|
|
1205
|
+
// ---- Touch targeting (iOS/iPadOS) ----
|
|
1206
|
+
// iOS/iPadOS taps on non-interactive elements don't fire click, so touch
|
|
1207
|
+
// drives targeting here. Scrolling stays enabled (the page may need to scroll
|
|
1208
|
+
// to bring the target into view); a low-movement touch is treated as a tap
|
|
1209
|
+
// that selects, distinguishing it from a scroll/drag.
|
|
1210
|
+
handleTouchStart(t) {
|
|
1211
|
+
const i = t.touches[0];
|
|
1212
|
+
i && (this.touchStartPos = { x: i.clientX, y: i.clientY }, this.updateReticleAt(i.clientX, i.clientY));
|
|
1213
|
+
}
|
|
1214
|
+
handleTouchEnd(t) {
|
|
1215
|
+
const i = t.changedTouches[0], o = this.touchStartPos;
|
|
1216
|
+
this.touchStartPos = null, !(!i || !o || Math.hypot(i.clientX - o.x, i.clientY - o.y) > Ae) && (t.preventDefault(), this.selectAt(i.clientX, i.clientY));
|
|
1217
|
+
}
|
|
1218
|
+
/** Select the element under (x, y) and tear down targeting.
|
|
1219
|
+
* Shared by the mouse (click) and touch (touchend) targeting paths. */
|
|
1220
|
+
selectAt(t, i) {
|
|
1221
|
+
const o = [this.shadowHost, this.overlayShadowHost].filter(Boolean), n = K(t, i, o);
|
|
1222
|
+
if (!n || M(n))
|
|
1133
1223
|
return;
|
|
1134
|
-
const
|
|
1224
|
+
const s = j(n, 8);
|
|
1135
1225
|
this.selectedBounds = {
|
|
1136
|
-
...
|
|
1137
|
-
clickX: t
|
|
1138
|
-
clickY:
|
|
1226
|
+
...s,
|
|
1227
|
+
clickX: t,
|
|
1228
|
+
clickY: i,
|
|
1139
1229
|
visible: !0
|
|
1140
1230
|
};
|
|
1141
|
-
const { selector:
|
|
1142
|
-
this.feedbackData.elementSelector =
|
|
1231
|
+
const { selector: a, text: d } = D(n);
|
|
1232
|
+
this.feedbackData.elementSelector = a, this.feedbackData.elementText = d, this.stopTargetingListeners(), 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.clearActiveThumb(), this.showSelectedMarker(), this.submitFeedback();
|
|
1233
|
+
}
|
|
1234
|
+
/** Remove the targeting overlay and every mouse/touch/keyboard listener the
|
|
1235
|
+
* pointer-targeting flow attaches to the document. */
|
|
1236
|
+
stopTargetingListeners() {
|
|
1237
|
+
this.removeTargetingOverlay(), this.touchStartPos = null, document.removeEventListener("mousemove", this.boundMouseMove), document.removeEventListener("click", this.boundClick, !0), document.removeEventListener("touchstart", this.boundTouchStart), document.removeEventListener("touchend", this.boundTouchEnd), document.removeEventListener("keydown", this.boundKeyDown);
|
|
1143
1238
|
}
|
|
1144
1239
|
cancelTargeting() {
|
|
1145
|
-
this.keyboardController?.stop(), this.keyboardController = null, this.
|
|
1240
|
+
this.keyboardController?.stop(), this.keyboardController = null, this.stopTargetingListeners(), document.body.classList.remove("qaid-targeting", "qaid-type-up"), document.body.style.removeProperty("--qaid-positive"), document.body.style.removeProperty("--qaid-negative"), this.clearActiveThumb(), this.state = "IDLE", this.feedbackData.feedbackType = null, this.feedbackData.elementSelector = null, this.feedbackData.elementText = null, this.selectedBounds.visible = !1;
|
|
1146
1241
|
}
|
|
1147
1242
|
removeTargetingOverlay() {
|
|
1148
1243
|
this.overlayContainer && (this.overlayContainer.remove(), this.overlayContainer = null), this.captureLayer = null, this.crosshairH = null, this.crosshairV = null, this.scope = null;
|
|
@@ -1156,7 +1251,7 @@ class Ee {
|
|
|
1156
1251
|
}
|
|
1157
1252
|
async submitFeedback() {
|
|
1158
1253
|
let t = null;
|
|
1159
|
-
this.config.captureScreenshot && (this.config.screenshotMethod === "dom" ? t = await
|
|
1254
|
+
this.config.captureScreenshot && (this.config.screenshotMethod === "dom" ? t = await Ce(this.config.screenshotOptions) : t = await we(this.config.screenshotOptions), t && this.announceMsg("Screenshot captured"));
|
|
1160
1255
|
const i = this.feedbackData.elementSelector ? {
|
|
1161
1256
|
x: this.selectedBounds.x,
|
|
1162
1257
|
y: this.selectedBounds.y,
|
|
@@ -1220,7 +1315,7 @@ class Ee {
|
|
|
1220
1315
|
const o = this.questIdFor(t);
|
|
1221
1316
|
if (!o) return !1;
|
|
1222
1317
|
try {
|
|
1223
|
-
return this.activeQuest?.destroy(), this.activeQuest = await
|
|
1318
|
+
return this.activeQuest?.destroy(), this.activeQuest = await Ie({
|
|
1224
1319
|
questId: o,
|
|
1225
1320
|
base: this.config.quests.base,
|
|
1226
1321
|
apiKey: this.config.quests.apiKey || void 0,
|
|
@@ -1275,7 +1370,7 @@ class Ee {
|
|
|
1275
1370
|
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();
|
|
1276
1371
|
}
|
|
1277
1372
|
getModalContent() {
|
|
1278
|
-
const t = this.feedbackData.feedbackType === "up", i = this.config.positiveIcon ||
|
|
1373
|
+
const t = this.feedbackData.feedbackType === "up", i = this.config.positiveIcon || I, o = this.config.negativeIcon || A;
|
|
1279
1374
|
return `
|
|
1280
1375
|
<div class="qaid-modal-header">
|
|
1281
1376
|
<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" aria-pressed="${t}" aria-label="${t ? "Feedback type: positive" : "Feedback type: negative"}">
|
|
@@ -1308,14 +1403,14 @@ class Ee {
|
|
|
1308
1403
|
o && o.addEventListener("click", () => {
|
|
1309
1404
|
const n = this.feedbackData.feedbackType === "up" ? "down" : "up";
|
|
1310
1405
|
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"));
|
|
1311
|
-
const s = this.config.positiveIcon ||
|
|
1406
|
+
const s = this.config.positiveIcon || I, a = this.config.negativeIcon || A;
|
|
1312
1407
|
o.innerHTML = n === "up" ? s : a;
|
|
1313
|
-
const
|
|
1314
|
-
o.setAttribute("aria-pressed", String(n === "up")), o.setAttribute("aria-label",
|
|
1408
|
+
const d = n === "up" ? "Feedback type: positive" : "Feedback type: negative";
|
|
1409
|
+
o.setAttribute("aria-pressed", String(n === "up")), o.setAttribute("aria-label", d), this.announceMsg(d), this.feedbackId && fetch(`${this.config.endpoint}/${this.feedbackId}`, {
|
|
1315
1410
|
method: "PATCH",
|
|
1316
1411
|
headers: { "Content-Type": "application/json" },
|
|
1317
1412
|
body: JSON.stringify({ feedbackType: n })
|
|
1318
|
-
}).catch((
|
|
1413
|
+
}).catch((l) => console.error("Failed to update feedback type:", l));
|
|
1319
1414
|
});
|
|
1320
1415
|
}
|
|
1321
1416
|
async submitMessage(t) {
|
|
@@ -1344,7 +1439,7 @@ class Ee {
|
|
|
1344
1439
|
async startRecording() {
|
|
1345
1440
|
if (!(this.isRecording || this.state !== "IDLE"))
|
|
1346
1441
|
try {
|
|
1347
|
-
this.networkCapture = de(), this.videoRecorder =
|
|
1442
|
+
this.networkCapture = de(), this.videoRecorder = ve({
|
|
1348
1443
|
maxDuration: this.config.videoOptions.maxDuration
|
|
1349
1444
|
}), this.videoRecorder.onTick((t) => {
|
|
1350
1445
|
this.updateRecordingTimer(t);
|
|
@@ -1399,19 +1494,19 @@ class Ee {
|
|
|
1399
1494
|
s.src = i, s.controls = !0, s.autoplay = !0, s.muted = !0;
|
|
1400
1495
|
const a = document.createElement("textarea");
|
|
1401
1496
|
a.placeholder = "Optional: Describe the issue you recorded...", a.setAttribute("aria-label", "Describe the issue you recorded");
|
|
1402
|
-
const
|
|
1403
|
-
|
|
1404
|
-
const
|
|
1405
|
-
|
|
1497
|
+
const d = document.createElement("div");
|
|
1498
|
+
d.className = "qaid-video-preview-actions";
|
|
1499
|
+
const l = document.createElement("button");
|
|
1500
|
+
l.type = "button", l.className = "qaid-video-btn qaid-video-btn-cancel", l.textContent = "Cancel", l.addEventListener("click", () => this.cancelRecordingPreview());
|
|
1406
1501
|
const r = document.createElement("button");
|
|
1407
1502
|
r.type = "button", r.className = "qaid-video-btn qaid-video-btn-rerecord", r.textContent = "Re-record", r.addEventListener("click", () => {
|
|
1408
1503
|
this.cancelRecordingPreview(), this.startRecording();
|
|
1409
1504
|
});
|
|
1410
|
-
const
|
|
1411
|
-
|
|
1505
|
+
const c = document.createElement("button");
|
|
1506
|
+
c.type = "button", c.className = "qaid-video-btn qaid-video-btn-send", c.textContent = "Send", c.addEventListener("click", () => {
|
|
1412
1507
|
const p = a.value.trim() || null;
|
|
1413
|
-
this.submitVideoFeedback(p,
|
|
1414
|
-
}),
|
|
1508
|
+
this.submitVideoFeedback(p, c);
|
|
1509
|
+
}), d.appendChild(l), d.appendChild(r), d.appendChild(c), o.appendChild(n), o.appendChild(s), o.appendChild(a), o.appendChild(d), this.videoPreview.appendChild(o), this.applyVars(this.videoPreview), this.overlayShadowHost && (this.overlayShadowHost.style.pointerEvents = "auto"), t.appendChild(this.videoPreview), this.openDialogA11y(o, { labelledbyId: n.id }), document.addEventListener("keydown", this.boundKeyDown);
|
|
1415
1510
|
}
|
|
1416
1511
|
cancelRecordingPreview() {
|
|
1417
1512
|
this.removeVideoPreview(), this.cleanupRecording();
|
|
@@ -1460,13 +1555,13 @@ class Ee {
|
|
|
1460
1555
|
* Destroy the embed and clean up all resources
|
|
1461
1556
|
*/
|
|
1462
1557
|
destroy() {
|
|
1463
|
-
this.destroyed = !0, this.domObserver && (this.domObserver.disconnect(), this.domObserver = null), this.boundBeforeSwap && (document.removeEventListener("astro:before-swap", this.boundBeforeSwap), this.boundBeforeSwap = null), this.keyboardController?.stop(), this.keyboardController = null, this.clearActiveThumb(), this.closeDialogA11y(), this.cleanupRecording(), this.removeVideoPreview(), this.activeQuest?.destroy(), this.activeQuest = null, 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, Lt();
|
|
1558
|
+
this.destroyed = !0, this.domObserver && (this.domObserver.disconnect(), this.domObserver = null), this.boundBeforeSwap && (document.removeEventListener("astro:before-swap", this.boundBeforeSwap), this.boundBeforeSwap = null), this.keyboardController?.stop(), this.keyboardController = null, this.clearActiveThumb(), this.closeDialogA11y(), this.cleanupRecording(), this.removeVideoPreview(), this.activeQuest?.destroy(), this.activeQuest = null, 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.removeEventListener("touchstart", this.boundTouchStart), document.removeEventListener("touchend", this.boundTouchEnd), 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, Lt();
|
|
1464
1559
|
}
|
|
1465
1560
|
}
|
|
1466
1561
|
function et(e) {
|
|
1467
1562
|
return document.querySelector(e)?.textContent?.trim() ?? "";
|
|
1468
1563
|
}
|
|
1469
|
-
function
|
|
1564
|
+
function He() {
|
|
1470
1565
|
const e = document.querySelector(
|
|
1471
1566
|
'script[type="application/json"][data-feedback-config]'
|
|
1472
1567
|
);
|
|
@@ -1480,60 +1575,60 @@ function Se() {
|
|
|
1480
1575
|
return null;
|
|
1481
1576
|
}
|
|
1482
1577
|
}
|
|
1483
|
-
function
|
|
1578
|
+
function Be(e) {
|
|
1484
1579
|
const t = e.getAttribute("data-endpoint");
|
|
1485
1580
|
if (!t) return null;
|
|
1486
|
-
const i = e.getAttribute("data-position"), o = e.getAttribute("data-zindex"), n = e.getAttribute("data-positive-color"), s = e.getAttribute("data-negative-color"), a = e.getAttribute("data-marker-color"),
|
|
1581
|
+
const i = e.getAttribute("data-position"), o = e.getAttribute("data-zindex"), n = e.getAttribute("data-positive-color"), s = e.getAttribute("data-negative-color"), a = e.getAttribute("data-marker-color"), d = e.getAttribute("data-container"), l = e.getAttribute("data-button-class"), r = e.getAttribute("data-skip-targeting"), c = e.getAttribute("data-incognito"), p = e.getAttribute("data-button-size"), u = e.getAttribute("data-offset-x"), m = e.getAttribute("data-offset-y"), b = e.getAttribute("data-modal-width"), v = e.getAttribute("data-backdrop-opacity"), y = e.getAttribute("data-font-family"), f = e.getAttribute("data-font-size"), h = e.getAttribute("data-tooltip"), w = e.getAttribute("data-modal-title"), g = e.getAttribute("data-modal-subtitle"), C = e.getAttribute("data-placeholder"), B = e.getAttribute("data-submit-button"), P = e.getAttribute("data-skip-button"), it = e.getAttribute("data-positive-icon"), ot = e.getAttribute("data-negative-icon"), nt = e.getAttribute("data-api-key"), st = e.getAttribute("data-capture-screenshot"), E = e.getAttribute("data-screenshot-quality"), T = e.getAttribute("data-screenshot-max-width"), L = e.getAttribute("data-screenshot-max-height"), at = e.getAttribute("data-capture-video"), rt = e.getAttribute("data-hide-thumbs"), dt = e.getAttribute("data-hide-dismiss"), z = e.getAttribute("data-video-max-duration"), ct = e.getAttribute("data-screenshot-method"), lt = e.getAttribute("data-direction"), O = e.getAttribute("data-css-selector"), $ = e.getAttribute("data-quest-base"), ht = e.getAttribute("data-quest-up"), ut = e.getAttribute("data-quest-down"), pt = e.getAttribute("data-quest-video"), mt = e.getAttribute("data-quest-api-key"), ft = e.getAttribute("data-quest-module-url");
|
|
1487
1582
|
return {
|
|
1488
1583
|
endpoint: t,
|
|
1489
|
-
css:
|
|
1584
|
+
css: O ? et(O) : void 0,
|
|
1490
1585
|
apiKey: nt ?? void 0,
|
|
1491
1586
|
captureScreenshot: st === "true" ? !0 : void 0,
|
|
1492
|
-
screenshotOptions:
|
|
1493
|
-
quality:
|
|
1494
|
-
maxWidth:
|
|
1495
|
-
maxHeight:
|
|
1587
|
+
screenshotOptions: E || T || L ? {
|
|
1588
|
+
quality: E ? parseFloat(E) : void 0,
|
|
1589
|
+
maxWidth: T ? parseInt(T, 10) : void 0,
|
|
1590
|
+
maxHeight: L ? parseInt(L, 10) : void 0
|
|
1496
1591
|
} : void 0,
|
|
1497
|
-
container:
|
|
1498
|
-
buttonClass:
|
|
1499
|
-
direction:
|
|
1592
|
+
container: d ?? void 0,
|
|
1593
|
+
buttonClass: l ?? void 0,
|
|
1594
|
+
direction: lt ?? void 0,
|
|
1500
1595
|
position: i ?? void 0,
|
|
1501
1596
|
zIndex: o ? parseInt(o, 10) : void 0,
|
|
1502
1597
|
skipTargeting: r === "true" ? !0 : void 0,
|
|
1503
|
-
incognito:
|
|
1598
|
+
incognito: c === "true" ? !0 : void 0,
|
|
1504
1599
|
buttonSize: p ?? void 0,
|
|
1505
1600
|
offset: u || m ? {
|
|
1506
1601
|
x: u ? parseInt(u, 10) : void 0,
|
|
1507
1602
|
y: m ? parseInt(m, 10) : void 0
|
|
1508
1603
|
} : void 0,
|
|
1509
|
-
modalWidth:
|
|
1510
|
-
backdropOpacity:
|
|
1511
|
-
fontFamily:
|
|
1512
|
-
fontSize:
|
|
1604
|
+
modalWidth: b ? parseInt(b, 10) : void 0,
|
|
1605
|
+
backdropOpacity: v ? parseFloat(v) : void 0,
|
|
1606
|
+
fontFamily: y ?? void 0,
|
|
1607
|
+
fontSize: f ? parseInt(f, 10) : void 0,
|
|
1513
1608
|
colors: {
|
|
1514
1609
|
positive: n ?? void 0,
|
|
1515
1610
|
negative: s ?? void 0,
|
|
1516
1611
|
marker: a ?? void 0
|
|
1517
1612
|
},
|
|
1518
|
-
text: h ||
|
|
1613
|
+
text: h || w || g || C || B || P ? {
|
|
1519
1614
|
tooltip: h ?? void 0,
|
|
1520
|
-
modalTitle:
|
|
1521
|
-
modalSubtitle:
|
|
1522
|
-
placeholder:
|
|
1615
|
+
modalTitle: w ?? void 0,
|
|
1616
|
+
modalSubtitle: g ?? void 0,
|
|
1617
|
+
placeholder: C ?? void 0,
|
|
1523
1618
|
submitButton: B ?? void 0,
|
|
1524
|
-
skipButton:
|
|
1619
|
+
skipButton: P ?? void 0
|
|
1525
1620
|
} : void 0,
|
|
1526
1621
|
positiveIcon: it ?? void 0,
|
|
1527
1622
|
negativeIcon: ot ?? void 0,
|
|
1528
|
-
screenshotMethod:
|
|
1623
|
+
screenshotMethod: ct ?? void 0,
|
|
1529
1624
|
captureVideo: at === "true" ? !0 : void 0,
|
|
1530
1625
|
hideThumbs: rt === "true" ? !0 : void 0,
|
|
1531
1626
|
hideDismiss: dt === "true" ? !0 : void 0,
|
|
1532
|
-
videoOptions:
|
|
1533
|
-
maxDuration: parseInt(
|
|
1627
|
+
videoOptions: z ? {
|
|
1628
|
+
maxDuration: parseInt(z, 10)
|
|
1534
1629
|
} : void 0,
|
|
1535
|
-
quests:
|
|
1536
|
-
base:
|
|
1630
|
+
quests: $ ? {
|
|
1631
|
+
base: $,
|
|
1537
1632
|
up: ht ?? void 0,
|
|
1538
1633
|
down: ut ?? void 0,
|
|
1539
1634
|
video: pt ?? void 0,
|
|
@@ -1544,18 +1639,18 @@ function Te(e) {
|
|
|
1544
1639
|
}
|
|
1545
1640
|
if (typeof document < "u") {
|
|
1546
1641
|
const e = () => {
|
|
1547
|
-
const t = document.currentScript, i =
|
|
1548
|
-
n?.endpoint && new
|
|
1642
|
+
const t = document.currentScript, i = He(), o = t ? Be(t) : null, n = i ?? o;
|
|
1643
|
+
n?.endpoint && new Re(n);
|
|
1549
1644
|
};
|
|
1550
1645
|
document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", e) : e();
|
|
1551
1646
|
}
|
|
1552
1647
|
export {
|
|
1553
|
-
|
|
1554
|
-
|
|
1648
|
+
Re as QaidFeedback,
|
|
1649
|
+
Ce as captureDomScreenshot,
|
|
1555
1650
|
de as captureNetworkErrors,
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1651
|
+
ve as createVideoRecorder,
|
|
1652
|
+
ge as getSupportedMimeType,
|
|
1653
|
+
Pe as isDomScreenshotSupported,
|
|
1654
|
+
be as isVideoRecordingSupported
|
|
1560
1655
|
};
|
|
1561
1656
|
//# sourceMappingURL=qaid.js.map
|