@emmaexcel/shakecursor 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/overlay.global.js +59 -10
- package/dist/overlay.js +84 -21
- package/dist/types.d.ts +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Framework-agnostic browser SDK for contextual AI selection overlays.
|
|
|
5
5
|
## NPM-style usage
|
|
6
6
|
|
|
7
7
|
```ts
|
|
8
|
-
import { AIOverlay } from '@shakecursor
|
|
8
|
+
import { AIOverlay } from '@emmaexcel/shakecursor'
|
|
9
9
|
|
|
10
10
|
const overlay = AIOverlay.init({
|
|
11
11
|
siteKey: 'pk_demo_shakecursor',
|
package/dist/overlay.global.js
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e,t,n){return Math.min(Math.max(e,t),n)}function n(e){return e.replace(/\s+/g,` `).trim()}function r(e,t=[]){return t.some(t=>{try{return e.matches(t)||!!e.closest(t)}catch{return!1}})}function i(){return/Mac|iPhone|iPad|iPod/i.test(window.navigator.platform)}function a(e){if(e.rangeCount===0)return null;let t=e.getRangeAt(0),n=t.getBoundingClientRect();return n.width>0||n.height>0?n:t.getClientRects()[0]??null}function o(e){return{rect:e,url:window.location.href,title:document.title}}function s(e){let t=n(e.innerText??``),r=e.tagName.toLowerCase(),i=e.getAttribute(`aria-label`),a=e.getAttribute(`title`),o=[i,a,t].find(Boolean);return{label:o?`${r}: ${o.slice(0,64)}`:r,content:[`Selected element: <${r}>`,i?`ARIA label: ${i}`:``,a?`Title: ${a}`:``,t?`Visible text: ${t.slice(0,5e3)}`:``].filter(Boolean).join(`
|
|
2
|
-
`)}}function c(e){let t=e.currentSrc||e.src,n=e.alt||`No alt text
|
|
3
|
-
`)}}function l(e,t){return!(r(e,t.blockedSelectors)||t.allowedSelectors.length>0&&!r(e,t.allowedSelectors))}function u(e){let t=t=>{if(!e.isActive())return;let n=t.target;if(!(n instanceof HTMLElement)||e.isOverlayElement(n)){e.onHover(null);return}if(!l(n,e.config)){e.onHover(null);return}e.onHover(n.getBoundingClientRect())},r=()=>{!e.isActive()||!e.config.text||window.setTimeout(()=>{let t=window.getSelection(),r=n(t?.toString()??``);if(!t||!r)return;let i=a(t),s=t.anchorNode?.parentElement;!i||!s||!l(s,e.config)||e.onSelection({kind:`text`,label:`highlighted text`,content:r,...o(i)})},0)},i=t=>{if(!e.isActive())return;let r=t.target;if(!(r instanceof HTMLElement)||e.isOverlayElement(r)||!l(r,e.config)||n(window.getSelection()?.toString()??``))return;let i=r instanceof HTMLImageElement?r:r.querySelector(`img`),a=!!i;if(a&&!e.config.images||!a&&!e.config.elements)return;t.preventDefault(),t.stopPropagation();let u=i?c(i):s(r),d=i?i.getBoundingClientRect():r.getBoundingClientRect();e.onSelection({kind:i?`image`:`element`,label:u.label,content:u.content,...o(d)})};return document.addEventListener(`pointerover`,t),document.addEventListener(`mouseup`,r),document.addEventListener(`click`,i,!0),()=>{document.removeEventListener(`pointerover`,t),document.removeEventListener(`mouseup`,r),document.removeEventListener(`click`,i,!0)}}function d(e){let t=e.windowMs??650,n=e.cooldownMs??1e3,r=e.minSamples??7,i=e.minReversals??5,a=e.minDistance??340,o=e.minDeltaX??16,s=[],c=0,l=l=>{let u=performance.now();if(s.push({x:l.clientX,y:l.clientY,time:u}),s=s.filter(e=>u-e.time<t),s.length<r||u-c<n)return;let d=0,f=0,p=0;for(let e=1;e<s.length;e+=1){let t=s[e].x-s[e-1].x,n=s[e].y-s[e-1].y;if(f+=Math.hypot(t,n),Math.abs(t)<o)continue;let r=Math.sign(t);p!==0&&r!==p&&(d+=1),p=r}d>=i&&f>a&&(c=u,s=[],e.onShake())};return document.addEventListener(`pointermove`,l),()=>{document.removeEventListener(`pointermove`,l)}}var f=`http://localhost:11434/api/chat`,p=`qwen3-coder:480b-cloud`,m=`https://shakeai.onrender.com`;async function h(e,t){let n=e.provider??`ollama`,r=e.endpoint??f,i=e.model??p;if(n===`custom`){let n=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,...e.headers},body:JSON.stringify(t)});if(!n.ok)throw Error(`Custom endpoint returned ${n.status}`);let i=await n.json();return typeof i==`string`?i:i&&typeof i==`object`&&`answer`in i&&typeof i.answer==`string`?i.answer:i&&typeof i==`object`&&`content`in i&&typeof i.content==`string`?i.content:JSON.stringify(i,null,2)}let a=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,...e.headers},body:JSON.stringify({model:i,stream:!1,messages:[{role:`system`,content:`You are an in-page AI assistant. Use the selected website context to answer or transform content. Be direct and practical.`},{role:`user`,content:[`Page title: ${t.selection.title}`,`Page URL: ${t.selection.url}`,`Selection type: ${t.selection.kind}`,`Selection label: ${t.selection.label}`,`Selected context:`,t.selection.content,``,`User request: ${t.question}`].join(`
|
|
4
|
-
`)}]})});if(!a.ok)throw Error(`Ollama returned ${a.status}`);let o=await a.json();if(o.error)throw Error(o.error);return o.message?.content?.trim()||`No response returned.`}async function g(e){let t=await fetch(`${e.apiBaseUrl??m}/v1/ask`,{method:`POST`,headers:{"Content-Type":`application/json`,"x-site-key":e.siteKey},body:JSON.stringify(e.payload)}),n=await t.json();if(!t.ok||n.error)throw Error(n.error??`Hosted API returned ${t.status}`);return n.answer??`No response returned.`}function _(e){let n=document.createElement(`div`);n.dataset.aiOverlayRoot=`true`;let r=document.createElement(`style`);r.dataset.aiOverlayStyle=`true`,r.textContent=`
|
|
1
|
+
(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e,t,n){return Math.min(Math.max(e,t),n)}function n(e){return e.replace(/\s+/g,` `).trim()}function r(e,t=[]){return t.some(t=>{try{return e.matches(t)||!!e.closest(t)}catch{return!1}})}function i(){return/Mac|iPhone|iPad|iPod/i.test(window.navigator.platform)}function a(e){if(e.rangeCount===0)return null;let t=e.getRangeAt(0),n=t.getBoundingClientRect();return n.width>0||n.height>0?n:t.getClientRects()[0]??null}function o(e){return{rect:e,url:window.location.href,title:document.title}}function s(e){let t=n(e.innerText??``),r=e.tagName.toLowerCase(),i=e.getAttribute(`aria-label`),a=e.getAttribute(`title`),o=[i,a,t].find(Boolean);return{label:o?`${r}: ${o.slice(0,64)}`:r,data:void 0,mimeType:void 0,content:[`Selected element: <${r}>`,i?`ARIA label: ${i}`:``,a?`Title: ${a}`:``,t?`Visible text: ${t.slice(0,5e3)}`:``].filter(Boolean).join(`
|
|
2
|
+
`)}}function c(e){let t=e.currentSrc||e.src,n=e.alt||`No alt text`,r,i;try{let t=document.createElement(`canvas`);t.width=e.naturalWidth,t.height=e.naturalHeight;let n=t.getContext(`2d`);if(n){n.drawImage(e,0,0);let[a,o]=t.toDataURL(`image/jpeg`,.8).split(`,`);r=o,i=a.split(`:`)[1].split(`;`)[0]}}catch(e){console.warn(`Failed to capture image data (likely CORS):`,e)}return{label:`image: ${n.slice(0,64)}`,data:r,mimeType:i,content:[`Selected image`,`Alt text: ${n}`,`Source: ${t}`,`Rendered size: ${Math.round(e.width)}x${Math.round(e.height)}`,`Natural size: ${e.naturalWidth}x${e.naturalHeight}`].join(`
|
|
3
|
+
`)}}function l(e,t){return!(r(e,t.blockedSelectors)||t.allowedSelectors.length>0&&!r(e,t.allowedSelectors))}function u(e){let t=t=>{if(!e.isActive())return;let n=t.target;if(!(n instanceof HTMLElement)||e.isOverlayElement(n)){e.onHover(null);return}if(!l(n,e.config)){e.onHover(null);return}e.onHover(n.getBoundingClientRect())},r=()=>{!e.isActive()||!e.config.text||window.setTimeout(()=>{let t=window.getSelection(),r=n(t?.toString()??``);if(!t||!r)return;let i=a(t),s=t.anchorNode?.parentElement;!i||!s||!l(s,e.config)||e.onSelection({kind:`text`,label:`highlighted text`,content:r,...o(i)})},0)},i=t=>{if(!e.isActive())return;let r=t.target;if(!(r instanceof HTMLElement)||e.isOverlayElement(r)||!l(r,e.config)||n(window.getSelection()?.toString()??``))return;let i=r instanceof HTMLImageElement?r:r.querySelector(`img`),a=!!i;if(a&&!e.config.images||!a&&!e.config.elements)return;t.preventDefault(),t.stopPropagation();let u=i?c(i):s(r),d=i?i.getBoundingClientRect():r.getBoundingClientRect();e.onSelection({kind:i?`image`:`element`,label:u.label,content:u.content,data:u.data,mimeType:u.mimeType,...o(d)})};return document.addEventListener(`pointerover`,t),document.addEventListener(`mouseup`,r),document.addEventListener(`click`,i,!0),()=>{document.removeEventListener(`pointerover`,t),document.removeEventListener(`mouseup`,r),document.removeEventListener(`click`,i,!0)}}function d(e){let t=e.windowMs??650,n=e.cooldownMs??1e3,r=e.minSamples??7,i=e.minReversals??5,a=e.minDistance??340,o=e.minDeltaX??16,s=[],c=0,l=l=>{let u=performance.now();if(s.push({x:l.clientX,y:l.clientY,time:u}),s=s.filter(e=>u-e.time<t),s.length<r||u-c<n)return;let d=0,f=0,p=0;for(let e=1;e<s.length;e+=1){let t=s[e].x-s[e-1].x,n=s[e].y-s[e-1].y;if(f+=Math.hypot(t,n),Math.abs(t)<o)continue;let r=Math.sign(t);p!==0&&r!==p&&(d+=1),p=r}d>=i&&f>a&&(c=u,s=[],e.onShake())};return document.addEventListener(`pointermove`,l),()=>{document.removeEventListener(`pointermove`,l)}}var f=`http://localhost:11434/api/chat`,p=`qwen3-coder:480b-cloud`,m=`https://shakeai.onrender.com`;async function h(e,t){let n=e.provider??`ollama`,r=e.endpoint??f,i=e.model??p;if(n===`custom`){let n=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,...e.headers},body:JSON.stringify(t)});if(!n.ok)throw Error(`Custom endpoint returned ${n.status}`);let i=await n.json();return typeof i==`string`?i:i&&typeof i==`object`&&`answer`in i&&typeof i.answer==`string`?i.answer:i&&typeof i==`object`&&`content`in i&&typeof i.content==`string`?i.content:JSON.stringify(i,null,2)}let a=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,...e.headers},body:JSON.stringify({model:i,stream:!1,messages:[{role:`system`,content:`You are an in-page AI assistant. Use the selected website context to answer or transform content. Be direct and practical.`},{role:`user`,content:[`Page title: ${t.selection.title}`,`Page URL: ${t.selection.url}`,`Selection type: ${t.selection.kind}`,`Selection label: ${t.selection.label}`,`Selected context:`,t.selection.content,``,`User request: ${t.question}`].join(`
|
|
4
|
+
`)}]})});if(!a.ok)throw Error(`Ollama returned ${a.status}`);let o=await a.json();if(o.error)throw Error(o.error);return o.message?.content?.trim()||`No response returned.`}async function g(e){let t=await fetch(`${e.apiBaseUrl??m}/v1/ask`,{method:`POST`,headers:{"Content-Type":`application/json`,"x-site-key":e.siteKey},body:JSON.stringify(e.payload)}),n=await t.json();if(!t.ok||n.error)throw Error(n.error??`Hosted API returned ${t.status}`);return n.answer??`No response returned.`}function _(e){let n=document.createElement(`div`);n.dataset.aiOverlayRoot=`true`;let r=document.createElement(`style`);r.dataset.aiOverlayStyle=`true`,r.textContent=`
|
|
5
|
+
body.ai-overlay-active {
|
|
6
|
+
cursor: none !important;
|
|
7
|
+
}
|
|
8
|
+
body.ai-overlay-active * {
|
|
9
|
+
cursor: none !important;
|
|
10
|
+
}
|
|
11
|
+
`;let i=n.attachShadow({mode:`open`});document.head.append(r),document.body.append(n),i.innerHTML=`
|
|
5
12
|
<style>
|
|
6
13
|
:host {
|
|
7
14
|
all: initial;
|
|
15
|
+
--ai-blue: #4285F4;
|
|
16
|
+
--ai-red: #DB4437;
|
|
17
|
+
--ai-yellow: #F4B400;
|
|
18
|
+
--ai-green: #0F9D58;
|
|
8
19
|
--ai-primary: ${e.theme.primaryColor};
|
|
9
20
|
--ai-panel: ${e.theme.panelBackground};
|
|
10
21
|
--ai-text: ${e.theme.textColor};
|
|
@@ -12,6 +23,37 @@
|
|
|
12
23
|
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
13
24
|
}
|
|
14
25
|
|
|
26
|
+
.custom-cursor {
|
|
27
|
+
position: fixed;
|
|
28
|
+
left: 0;
|
|
29
|
+
top: 0;
|
|
30
|
+
width: 24px;
|
|
31
|
+
height: 24px;
|
|
32
|
+
pointer-events: none;
|
|
33
|
+
z-index: 2147483647;
|
|
34
|
+
display: none;
|
|
35
|
+
transform: translate(-50%, -50%);
|
|
36
|
+
transition: transform 0.1s ease-out;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.custom-cursor.active {
|
|
40
|
+
display: block;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.cursor-dot {
|
|
44
|
+
width: 100%;
|
|
45
|
+
height: 100%;
|
|
46
|
+
background: conic-gradient(var(--ai-blue), var(--ai-red), var(--ai-yellow), var(--ai-green), var(--ai-blue));
|
|
47
|
+
border-radius: 50%;
|
|
48
|
+
box-shadow: 0 0 15px rgba(66, 133, 244, 0.8), 0 0 30px rgba(15, 157, 88, 0.4);
|
|
49
|
+
animation: rotate-gradient 2s linear infinite;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@keyframes rotate-gradient {
|
|
53
|
+
from { transform: rotate(0deg); }
|
|
54
|
+
to { transform: rotate(360deg); }
|
|
55
|
+
}
|
|
56
|
+
|
|
15
57
|
.toast {
|
|
16
58
|
position: fixed;
|
|
17
59
|
right: 18px;
|
|
@@ -53,11 +95,15 @@
|
|
|
53
95
|
z-index: 2147483644;
|
|
54
96
|
pointer-events: none;
|
|
55
97
|
display: none;
|
|
56
|
-
border: 2px solid
|
|
98
|
+
border: 2px solid transparent;
|
|
57
99
|
border-radius: var(--ai-radius);
|
|
100
|
+
background: linear-gradient(var(--ai-panel), var(--ai-panel)) padding-box,
|
|
101
|
+
conic-gradient(var(--ai-blue), var(--ai-red), var(--ai-yellow), var(--ai-green), var(--ai-blue)) border-box;
|
|
58
102
|
box-shadow:
|
|
59
|
-
0 0
|
|
103
|
+
0 0 20px color-mix(in srgb, var(--ai-blue), transparent 80%),
|
|
60
104
|
0 20px 52px rgba(15, 23, 42, 0.14);
|
|
105
|
+
opacity: 0.3;
|
|
106
|
+
transition: all 0.15s ease-out;
|
|
61
107
|
}
|
|
62
108
|
|
|
63
109
|
.panel {
|
|
@@ -90,7 +136,7 @@
|
|
|
90
136
|
.kind {
|
|
91
137
|
display: block;
|
|
92
138
|
margin-bottom: 4px;
|
|
93
|
-
color: var(--ai-
|
|
139
|
+
color: var(--ai-blue);
|
|
94
140
|
font: 800 11px/1 Inter, ui-sans-serif, system-ui, sans-serif;
|
|
95
141
|
text-transform: uppercase;
|
|
96
142
|
}
|
|
@@ -145,8 +191,8 @@
|
|
|
145
191
|
}
|
|
146
192
|
|
|
147
193
|
textarea:focus {
|
|
148
|
-
border-color: var(--ai-
|
|
149
|
-
outline: 3px solid color-mix(in srgb, var(--ai-
|
|
194
|
+
border-color: var(--ai-blue);
|
|
195
|
+
outline: 3px solid color-mix(in srgb, var(--ai-blue), transparent 86%);
|
|
150
196
|
}
|
|
151
197
|
|
|
152
198
|
.error,
|
|
@@ -191,6 +237,9 @@
|
|
|
191
237
|
100% { box-shadow: 0 0 0 0 transparent; }
|
|
192
238
|
}
|
|
193
239
|
</style>
|
|
240
|
+
<div class="custom-cursor">
|
|
241
|
+
<div class="cursor-dot"></div>
|
|
242
|
+
</div>
|
|
194
243
|
<div class="toast" role="status">
|
|
195
244
|
<span class="pulse"></span>
|
|
196
245
|
<span>AI mode active</span>
|
|
@@ -212,4 +261,4 @@
|
|
|
212
261
|
<p class="error"></p>
|
|
213
262
|
<div class="answer"></div>
|
|
214
263
|
</section>
|
|
215
|
-
`;let a=i.querySelector(`.
|
|
264
|
+
`;let a=i.querySelector(`.custom-cursor`),o=i.querySelector(`.toast`),s=i.querySelector(`.count`),c=i.querySelector(`.hover`),l=i.querySelector(`.panel`),u=i.querySelector(`.kind`),d=i.querySelector(`.label`),f=i.querySelector(`form`),p=i.querySelector(`textarea`),m=i.querySelector(`.submit`),h=i.querySelector(`.close`),g=i.querySelector(`.error`),_=i.querySelector(`.answer`);if(!a||!o||!s||!c||!l||!u||!d||!f||!p||!m||!h||!g||!_)throw Error(`AIOverlay UI failed to initialize`);let v=e=>{a.style.left=`${e.clientX}px`,a.style.top=`${e.clientY}px`};return f.addEventListener(`submit`,t=>{t.preventDefault();let n=p.value.trim();n&&e.onSubmit(n)}),h.addEventListener(`click`,()=>{e.onCancel()}),{root:n,contains:e=>e===n||n.contains(e),setActive:(e,t)=>{o.classList.toggle(`active`,e),a.classList.toggle(`active`,e),s.textContent=`shakes ${t}`,e?window.addEventListener(`mousemove`,v):window.removeEventListener(`mousemove`,v)},setHoverRect:e=>{if(!e){c.style.display=`none`;return}c.style.display=`block`,c.style.left=`${e.left}px`,c.style.top=`${e.top}px`,c.style.width=`${e.width}px`,c.style.height=`${e.height}px`},showPrompt:e=>{let n=t(e.rect.left+e.rect.width/2-190,16,window.innerWidth-396),r=t(e.rect.bottom+14,16,window.innerHeight-380);u.textContent=e.kind,d.textContent=e.label,p.value=``,m.disabled=!1,m.textContent=`Ask AI`,g.classList.remove(`visible`),_.classList.remove(`visible`),l.style.left=`${n}px`,l.style.top=`${r}px`,l.classList.add(`visible`),p.focus()},setThinking:e=>{m.disabled=e,m.textContent=e?`Thinking...`:`Ask AI`},setAnswer:e=>{_.textContent=e,_.classList.toggle(`visible`,!!e)},setError:e=>{g.textContent=e,g.classList.toggle(`visible`,!!e)},clearSelection:()=>{l.classList.remove(`visible`),g.classList.remove(`visible`),_.classList.remove(`visible`),p.value=``},destroy:()=>{r.remove(),n.remove(),window.removeEventListener(`mousemove`,v)}}}var v={primaryColor:`#14b8a6`,panelBackground:`rgba(255, 255, 255, 0.96)`,textColor:`#111827`,borderRadius:8},y={shake:!0,keyboardShortcut:`mod+k`},b={text:!0,images:!0,elements:!0,blockedSelectors:[`input[type="password"]`,`[data-ai-private]`,`[data-ai-overlay-ignore]`],allowedSelectors:[]},x=class{active=!1;shakeCount=0;selection=null;disposers=[];ui;config;trigger;constructor(e){this.config=e,this.trigger={...y,...e.trigger};let t={...b,...e.selection};this.ui=_({theme:{...v,...e.theme},onSubmit:e=>{this.ask(e)},onCancel:()=>{this.clearSelection()}}),this.trigger.shake&&this.disposers.push(d({onShake:()=>{this.shakeCount+=1,this.activate()}})),this.disposers.push(u({config:t,isActive:()=>this.active,isOverlayElement:e=>this.ui.contains(e),onHover:e=>{this.ui.setHoverRect(this.selection?null:e)},onSelection:e=>{this.selection=e,this.ui.setHoverRect(null),this.ui.showPrompt(e),this.config.onSelection?.(e)}})),this.disposers.push(this.bindKeyboardShortcut())}activate(){if(this.active){this.ui.setActive(!0,this.shakeCount);return}this.active=!0,document.body.classList.add(`ai-overlay-active`),this.ui.setActive(!0,this.shakeCount),this.config.onActivate?.()}deactivate(){this.active&&(this.active=!1,this.clearSelection(),this.ui.setHoverRect(null),this.ui.setActive(!1,this.shakeCount),document.body.classList.remove(`ai-overlay-active`),this.config.onDeactivate?.())}destroy(){for(let e of this.disposers)e();this.disposers=[],this.deactivate(),this.ui.destroy()}isActive(){return this.active}clearSelection(){this.selection=null,this.ui.clearSelection(),window.getSelection()?.removeAllRanges()}async ask(e){if(!this.selection)return;let t={question:e,selection:this.selection};this.config.onAsk?.(t),this.ui.setThinking(!0),this.ui.setAnswer(``),this.ui.setError(``);try{let e=this.config.siteKey?await g({apiBaseUrl:this.config.apiBaseUrl,siteKey:this.config.siteKey,payload:t}):await h(this.config.model??{},t);this.ui.setAnswer(e),this.config.onResponse?.(e,t)}catch(e){let t=e instanceof Error?e:Error(`Unknown AIOverlay error`);this.ui.setError(t.message),this.config.onError?.(t)}finally{this.ui.setThinking(!1)}}bindKeyboardShortcut(){let e=this.trigger.keyboardShortcut.toLowerCase(),t=t=>{let n=e.includes(`mod+`),r=e.split(`+`).at(-1),a=i()?t.metaKey:t.ctrlKey;n&&!a||r&&t.key.toLowerCase()===r&&(t.preventDefault(),this.active?this.deactivate():this.activate())};return document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`keydown`,t)}}},S={init(e={}){return new x(e)}};typeof window<`u`&&(window.AIOverlay=S),e.AIOverlay=S})(this.AIOverlayBundle=this.AIOverlayBundle||{});
|
package/dist/overlay.js
CHANGED
|
@@ -39,6 +39,8 @@ function o(e) {
|
|
|
39
39
|
].find(Boolean);
|
|
40
40
|
return {
|
|
41
41
|
label: o ? `${r}: ${o.slice(0, 64)}` : r,
|
|
42
|
+
data: void 0,
|
|
43
|
+
mimeType: void 0,
|
|
42
44
|
content: [
|
|
43
45
|
`Selected element: <${r}>`,
|
|
44
46
|
i ? `ARIA label: ${i}` : "",
|
|
@@ -48,9 +50,23 @@ function o(e) {
|
|
|
48
50
|
};
|
|
49
51
|
}
|
|
50
52
|
function s(e) {
|
|
51
|
-
let t = e.currentSrc || e.src, n = e.alt || "No alt text";
|
|
53
|
+
let t = e.currentSrc || e.src, n = e.alt || "No alt text", r, i;
|
|
54
|
+
try {
|
|
55
|
+
let t = document.createElement("canvas");
|
|
56
|
+
t.width = e.naturalWidth, t.height = e.naturalHeight;
|
|
57
|
+
let n = t.getContext("2d");
|
|
58
|
+
if (n) {
|
|
59
|
+
n.drawImage(e, 0, 0);
|
|
60
|
+
let [a, o] = t.toDataURL("image/jpeg", .8).split(",");
|
|
61
|
+
r = o, i = a.split(":")[1].split(";")[0];
|
|
62
|
+
}
|
|
63
|
+
} catch (e) {
|
|
64
|
+
console.warn("Failed to capture image data (likely CORS):", e);
|
|
65
|
+
}
|
|
52
66
|
return {
|
|
53
67
|
label: `image: ${n.slice(0, 64)}`,
|
|
68
|
+
data: r,
|
|
69
|
+
mimeType: i,
|
|
54
70
|
content: [
|
|
55
71
|
"Selected image",
|
|
56
72
|
`Alt text: ${n}`,
|
|
@@ -100,6 +116,8 @@ function l(e) {
|
|
|
100
116
|
kind: i ? "image" : "element",
|
|
101
117
|
label: u.label,
|
|
102
118
|
content: u.content,
|
|
119
|
+
data: u.data,
|
|
120
|
+
mimeType: u.mimeType,
|
|
103
121
|
...a(d)
|
|
104
122
|
});
|
|
105
123
|
};
|
|
@@ -198,12 +216,16 @@ function g(t) {
|
|
|
198
216
|
let n = document.createElement("div");
|
|
199
217
|
n.dataset.aiOverlayRoot = "true";
|
|
200
218
|
let r = document.createElement("style");
|
|
201
|
-
r.dataset.aiOverlayStyle = "true", r.textContent = "body.ai-overlay-active { cursor:
|
|
219
|
+
r.dataset.aiOverlayStyle = "true", r.textContent = "\n body.ai-overlay-active { \n cursor: none !important; \n }\n body.ai-overlay-active * { \n cursor: none !important; \n }\n ";
|
|
202
220
|
let i = n.attachShadow({ mode: "open" });
|
|
203
221
|
document.head.append(r), document.body.append(n), i.innerHTML = `
|
|
204
222
|
<style>
|
|
205
223
|
:host {
|
|
206
224
|
all: initial;
|
|
225
|
+
--ai-blue: #4285F4;
|
|
226
|
+
--ai-red: #DB4437;
|
|
227
|
+
--ai-yellow: #F4B400;
|
|
228
|
+
--ai-green: #0F9D58;
|
|
207
229
|
--ai-primary: ${t.theme.primaryColor};
|
|
208
230
|
--ai-panel: ${t.theme.panelBackground};
|
|
209
231
|
--ai-text: ${t.theme.textColor};
|
|
@@ -211,6 +233,37 @@ function g(t) {
|
|
|
211
233
|
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
212
234
|
}
|
|
213
235
|
|
|
236
|
+
.custom-cursor {
|
|
237
|
+
position: fixed;
|
|
238
|
+
left: 0;
|
|
239
|
+
top: 0;
|
|
240
|
+
width: 24px;
|
|
241
|
+
height: 24px;
|
|
242
|
+
pointer-events: none;
|
|
243
|
+
z-index: 2147483647;
|
|
244
|
+
display: none;
|
|
245
|
+
transform: translate(-50%, -50%);
|
|
246
|
+
transition: transform 0.1s ease-out;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.custom-cursor.active {
|
|
250
|
+
display: block;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.cursor-dot {
|
|
254
|
+
width: 100%;
|
|
255
|
+
height: 100%;
|
|
256
|
+
background: conic-gradient(var(--ai-blue), var(--ai-red), var(--ai-yellow), var(--ai-green), var(--ai-blue));
|
|
257
|
+
border-radius: 50%;
|
|
258
|
+
box-shadow: 0 0 15px rgba(66, 133, 244, 0.8), 0 0 30px rgba(15, 157, 88, 0.4);
|
|
259
|
+
animation: rotate-gradient 2s linear infinite;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@keyframes rotate-gradient {
|
|
263
|
+
from { transform: rotate(0deg); }
|
|
264
|
+
to { transform: rotate(360deg); }
|
|
265
|
+
}
|
|
266
|
+
|
|
214
267
|
.toast {
|
|
215
268
|
position: fixed;
|
|
216
269
|
right: 18px;
|
|
@@ -252,11 +305,15 @@ function g(t) {
|
|
|
252
305
|
z-index: 2147483644;
|
|
253
306
|
pointer-events: none;
|
|
254
307
|
display: none;
|
|
255
|
-
border: 2px solid
|
|
308
|
+
border: 2px solid transparent;
|
|
256
309
|
border-radius: var(--ai-radius);
|
|
310
|
+
background: linear-gradient(var(--ai-panel), var(--ai-panel)) padding-box,
|
|
311
|
+
conic-gradient(var(--ai-blue), var(--ai-red), var(--ai-yellow), var(--ai-green), var(--ai-blue)) border-box;
|
|
257
312
|
box-shadow:
|
|
258
|
-
0 0
|
|
313
|
+
0 0 20px color-mix(in srgb, var(--ai-blue), transparent 80%),
|
|
259
314
|
0 20px 52px rgba(15, 23, 42, 0.14);
|
|
315
|
+
opacity: 0.3;
|
|
316
|
+
transition: all 0.15s ease-out;
|
|
260
317
|
}
|
|
261
318
|
|
|
262
319
|
.panel {
|
|
@@ -289,7 +346,7 @@ function g(t) {
|
|
|
289
346
|
.kind {
|
|
290
347
|
display: block;
|
|
291
348
|
margin-bottom: 4px;
|
|
292
|
-
color: var(--ai-
|
|
349
|
+
color: var(--ai-blue);
|
|
293
350
|
font: 800 11px/1 Inter, ui-sans-serif, system-ui, sans-serif;
|
|
294
351
|
text-transform: uppercase;
|
|
295
352
|
}
|
|
@@ -344,8 +401,8 @@ function g(t) {
|
|
|
344
401
|
}
|
|
345
402
|
|
|
346
403
|
textarea:focus {
|
|
347
|
-
border-color: var(--ai-
|
|
348
|
-
outline: 3px solid color-mix(in srgb, var(--ai-
|
|
404
|
+
border-color: var(--ai-blue);
|
|
405
|
+
outline: 3px solid color-mix(in srgb, var(--ai-blue), transparent 86%);
|
|
349
406
|
}
|
|
350
407
|
|
|
351
408
|
.error,
|
|
@@ -390,6 +447,9 @@ function g(t) {
|
|
|
390
447
|
100% { box-shadow: 0 0 0 0 transparent; }
|
|
391
448
|
}
|
|
392
449
|
</style>
|
|
450
|
+
<div class="custom-cursor">
|
|
451
|
+
<div class="cursor-dot"></div>
|
|
452
|
+
</div>
|
|
393
453
|
<div class="toast" role="status">
|
|
394
454
|
<span class="pulse"></span>
|
|
395
455
|
<span>AI mode active</span>
|
|
@@ -412,45 +472,48 @@ function g(t) {
|
|
|
412
472
|
<div class="answer"></div>
|
|
413
473
|
</section>
|
|
414
474
|
`;
|
|
415
|
-
let a = i.querySelector(".
|
|
416
|
-
if (!a || !o || !s || !c || !l || !u || !d || !f || !p || !m || !h || !g) throw Error("AIOverlay UI failed to initialize");
|
|
417
|
-
|
|
475
|
+
let a = i.querySelector(".custom-cursor"), o = i.querySelector(".toast"), s = i.querySelector(".count"), c = i.querySelector(".hover"), l = i.querySelector(".panel"), u = i.querySelector(".kind"), d = i.querySelector(".label"), f = i.querySelector("form"), p = i.querySelector("textarea"), m = i.querySelector(".submit"), h = i.querySelector(".close"), g = i.querySelector(".error"), _ = i.querySelector(".answer");
|
|
476
|
+
if (!a || !o || !s || !c || !l || !u || !d || !f || !p || !m || !h || !g || !_) throw Error("AIOverlay UI failed to initialize");
|
|
477
|
+
let v = (e) => {
|
|
478
|
+
a.style.left = `${e.clientX}px`, a.style.top = `${e.clientY}px`;
|
|
479
|
+
};
|
|
480
|
+
return f.addEventListener("submit", (e) => {
|
|
418
481
|
e.preventDefault();
|
|
419
|
-
let n =
|
|
482
|
+
let n = p.value.trim();
|
|
420
483
|
n && t.onSubmit(n);
|
|
421
|
-
}),
|
|
484
|
+
}), h.addEventListener("click", () => {
|
|
422
485
|
t.onCancel();
|
|
423
486
|
}), {
|
|
424
487
|
root: n,
|
|
425
488
|
contains: (e) => e === n || n.contains(e),
|
|
426
489
|
setActive: (e, t) => {
|
|
427
|
-
a.classList.toggle("active", e),
|
|
490
|
+
o.classList.toggle("active", e), a.classList.toggle("active", e), s.textContent = `shakes ${t}`, e ? window.addEventListener("mousemove", v) : window.removeEventListener("mousemove", v);
|
|
428
491
|
},
|
|
429
492
|
setHoverRect: (e) => {
|
|
430
493
|
if (!e) {
|
|
431
|
-
|
|
494
|
+
c.style.display = "none";
|
|
432
495
|
return;
|
|
433
496
|
}
|
|
434
|
-
|
|
497
|
+
c.style.display = "block", c.style.left = `${e.left}px`, c.style.top = `${e.top}px`, c.style.width = `${e.width}px`, c.style.height = `${e.height}px`;
|
|
435
498
|
},
|
|
436
499
|
showPrompt: (t) => {
|
|
437
500
|
let n = e(t.rect.left + t.rect.width / 2 - 190, 16, window.innerWidth - 396), r = e(t.rect.bottom + 14, 16, window.innerHeight - 380);
|
|
438
|
-
|
|
501
|
+
u.textContent = t.kind, d.textContent = t.label, p.value = "", m.disabled = !1, m.textContent = "Ask AI", g.classList.remove("visible"), _.classList.remove("visible"), l.style.left = `${n}px`, l.style.top = `${r}px`, l.classList.add("visible"), p.focus();
|
|
439
502
|
},
|
|
440
503
|
setThinking: (e) => {
|
|
441
|
-
|
|
504
|
+
m.disabled = e, m.textContent = e ? "Thinking..." : "Ask AI";
|
|
442
505
|
},
|
|
443
506
|
setAnswer: (e) => {
|
|
444
|
-
|
|
507
|
+
_.textContent = e, _.classList.toggle("visible", !!e);
|
|
445
508
|
},
|
|
446
509
|
setError: (e) => {
|
|
447
|
-
|
|
510
|
+
g.textContent = e, g.classList.toggle("visible", !!e);
|
|
448
511
|
},
|
|
449
512
|
clearSelection: () => {
|
|
450
|
-
|
|
513
|
+
l.classList.remove("visible"), g.classList.remove("visible"), _.classList.remove("visible"), p.value = "";
|
|
451
514
|
},
|
|
452
515
|
destroy: () => {
|
|
453
|
-
r.remove(), n.remove();
|
|
516
|
+
r.remove(), n.remove(), window.removeEventListener("mousemove", v);
|
|
454
517
|
}
|
|
455
518
|
};
|
|
456
519
|
}
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@emmaexcel/shakecursor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Framework-agnostic browser SDK for contextual AI selection overlays.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/overlay.global.js",
|
|
@@ -37,4 +37,4 @@
|
|
|
37
37
|
],
|
|
38
38
|
"author": "EmmaExcel",
|
|
39
39
|
"license": "MIT"
|
|
40
|
-
}
|
|
40
|
+
}
|