refinekit 0.1.0 → 0.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/README.md +31 -61
- package/dist/overlay.d.ts +1 -0
- package/dist/refiner.js +1 -1
- package/dist/refiner.js.map +1 -1
- package/dist/refiner.mjs +1 -1
- package/dist/refiner.mjs.map +1 -1
- package/dist/toolbar.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,61 +1,43 @@
|
|
|
1
|
-
#
|
|
1
|
+
# refinekit
|
|
2
2
|
|
|
3
|
-
Leave visual feedback directly on any web page. Click an element, type what should change, and
|
|
3
|
+
Leave visual feedback directly on any web page. Click an element, type what should change, and refinekit saves your notes as structured annotations that AI coding tools can read and act on.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
2. A small toolbar appears on your page
|
|
9
|
-
3. Click any element to leave a note about what should change
|
|
10
|
-
4. Copy all your notes and paste them into an AI coding tool like [Claude Code](https://claude.com/claude-code) — it knows exactly which elements to fix
|
|
7
|
+
### With Claude Code (recommended)
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
If you're using [Claude Code](https://claude.com/claude-code), tell it:
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
> Add refinekit to my HTML files
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
Claude Code will add the script tag to your HTML files for you. You can also use the built-in skill:
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
```html
|
|
21
|
-
<script src="https://unpkg.com/refinekit/dist/refiner.js"></script>
|
|
15
|
+
```
|
|
16
|
+
/refinekit
|
|
22
17
|
```
|
|
23
18
|
|
|
24
|
-
|
|
19
|
+
### Manually
|
|
20
|
+
|
|
21
|
+
Add this line to your HTML file, just before the closing `</body>` tag:
|
|
25
22
|
|
|
26
23
|
```html
|
|
27
|
-
|
|
28
|
-
<html>
|
|
29
|
-
<head>
|
|
30
|
-
<title>My Page</title>
|
|
31
|
-
</head>
|
|
32
|
-
<body>
|
|
33
|
-
<!-- your page content here -->
|
|
34
|
-
|
|
35
|
-
<script src="https://unpkg.com/refinekit/dist/refiner.js"></script>
|
|
36
|
-
</body>
|
|
37
|
-
</html>
|
|
24
|
+
<script src="https://unpkg.com/refinekit/dist/refiner.js"></script>
|
|
38
25
|
```
|
|
39
26
|
|
|
40
|
-
|
|
27
|
+
Open the file in your browser and the refinekit toolbar will appear in the bottom-right corner.
|
|
41
28
|
|
|
42
|
-
|
|
29
|
+
## How to use it
|
|
43
30
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
1. Click the **pen icon** to expand the toolbar
|
|
31
|
+
1. Click the **pen icon** in the bottom-right corner to expand the toolbar
|
|
47
32
|
2. Click any element on the page — a heading, a button, an image, anything
|
|
48
|
-
3.
|
|
33
|
+
3. Type what should change (e.g. "Make this font bigger" or "Change this color to blue")
|
|
49
34
|
4. Click **Add** (or press `Cmd+Enter` on Mac / `Ctrl+Enter` on Windows)
|
|
50
|
-
5. A numbered marker appears on the element
|
|
51
|
-
|
|
52
|
-
Repeat for as many elements as you'd like to annotate.
|
|
35
|
+
5. A numbered marker appears on the element — repeat for as many elements as you'd like
|
|
36
|
+
6. Click the **copy icon** in the toolbar to copy all your annotations
|
|
53
37
|
|
|
54
|
-
|
|
38
|
+
Paste the copied annotations into [Claude Code](https://claude.com/claude-code) or any AI coding tool. It will know exactly which elements to change and what to do.
|
|
55
39
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
What gets copied looks like this:
|
|
40
|
+
### What gets copied
|
|
59
41
|
|
|
60
42
|
```
|
|
61
43
|
# Design Annotations — My Page Title
|
|
@@ -69,8 +51,6 @@ Element: #hero > .cta-button
|
|
|
69
51
|
Issue: Change this color to blue and add more padding
|
|
70
52
|
```
|
|
71
53
|
|
|
72
|
-
The AI agent uses the element selectors to find and fix exactly the right elements in your code.
|
|
73
|
-
|
|
74
54
|
## Toolbar guide
|
|
75
55
|
|
|
76
56
|
| Button | What it does |
|
|
@@ -87,19 +67,9 @@ The AI agent uses the element selectors to find and fix exactly the right elemen
|
|
|
87
67
|
- **Clear on copy** — automatically remove annotations after copying them
|
|
88
68
|
- **Block page interactions** — prevents you from accidentally clicking links or buttons while annotating (on by default)
|
|
89
69
|
|
|
90
|
-
## Using
|
|
91
|
-
|
|
92
|
-
[Claude Code](https://claude.com/claude-code) is an AI coding tool that can read your reFiner annotations and make the changes for you.
|
|
93
|
-
|
|
94
|
-
### Quick setup
|
|
95
|
-
|
|
96
|
-
If you already have Claude Code installed, just type:
|
|
97
|
-
|
|
98
|
-
```
|
|
99
|
-
/refiner
|
|
100
|
-
```
|
|
70
|
+
## Using refinekit with Claude Code
|
|
101
71
|
|
|
102
|
-
Claude Code
|
|
72
|
+
[Claude Code](https://claude.com/claude-code) is an AI coding tool that can read your refinekit annotations and make the changes for you.
|
|
103
73
|
|
|
104
74
|
### Autonomous design critique
|
|
105
75
|
|
|
@@ -113,13 +83,13 @@ Claude opens your page in a browser and drives through it like a design reviewer
|
|
|
113
83
|
|
|
114
84
|
### Real-time sync with MCP
|
|
115
85
|
|
|
116
|
-
By default, you copy annotations and paste them into Claude Code. But you can skip the copy-paste entirely by running the
|
|
86
|
+
By default, you copy annotations and paste them into Claude Code. But you can skip the copy-paste entirely by running the refinekit MCP server:
|
|
117
87
|
|
|
118
88
|
```bash
|
|
119
89
|
npx refinekit-mcp server
|
|
120
90
|
```
|
|
121
91
|
|
|
122
|
-
Once running, annotations flow directly to Claude Code as you add them. The settings panel
|
|
92
|
+
Once running, annotations flow directly to Claude Code as you add them. The settings panel will show "MCP Connected" to confirm the link is active.
|
|
123
93
|
|
|
124
94
|
To make this permanent in Claude Code:
|
|
125
95
|
|
|
@@ -140,7 +110,7 @@ You watch Session 1 critique the design while Session 2 implements the fixes —
|
|
|
140
110
|
|
|
141
111
|
## Advanced
|
|
142
112
|
|
|
143
|
-
Everything below is for developers who want more control over
|
|
113
|
+
Everything below is for developers who want more control over refinekit.
|
|
144
114
|
|
|
145
115
|
### npm install
|
|
146
116
|
|
|
@@ -163,8 +133,8 @@ const refiner = new Refiner();
|
|
|
163
133
|
src="https://unpkg.com/refinekit/dist/refiner.js"
|
|
164
134
|
data-refiner-enabled="true"
|
|
165
135
|
data-refiner-position="right"
|
|
166
|
-
data-
|
|
167
|
-
data-
|
|
136
|
+
data-refiner-mcp-enabled="true"
|
|
137
|
+
data-refiner-mcp-port="4848"
|
|
168
138
|
></script>
|
|
169
139
|
```
|
|
170
140
|
|
|
@@ -172,8 +142,8 @@ const refiner = new Refiner();
|
|
|
172
142
|
|-----------|--------|---------|-------------|
|
|
173
143
|
| `data-refiner-enabled` | `true` / `false` | `true` | Whether to activate on load |
|
|
174
144
|
| `data-refiner-position` | `left` / `right` | `right` | Which side of the viewport |
|
|
175
|
-
| `data-
|
|
176
|
-
| `data-
|
|
145
|
+
| `data-refiner-mcp-enabled` | `true` / `false` | `true` | Auto-discover MCP server |
|
|
146
|
+
| `data-refiner-mcp-port` | number | `4848` | MCP server HTTP port |
|
|
177
147
|
|
|
178
148
|
#### Constructor options
|
|
179
149
|
|
|
@@ -246,7 +216,7 @@ npx refinekit-mcp doctor
|
|
|
246
216
|
|
|
247
217
|
```bash
|
|
248
218
|
# From the refiner project directory
|
|
249
|
-
ln -sf "$(pwd)/skills/
|
|
219
|
+
ln -sf "$(pwd)/skills/refinekit" ~/.claude/skills/refinekit
|
|
250
220
|
ln -sf "$(pwd)/skills/refiner-self-driving" ~/.claude/skills/refiner-self-driving
|
|
251
221
|
```
|
|
252
222
|
|
package/dist/overlay.d.ts
CHANGED
package/dist/refiner.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var Refiner=function(t){"use strict";class e{constructor(){this.annotations=new Map,this.listeners=new Map}add(t,e,n){const i={id:crypto.randomUUID(),targetSelector:t,targetRect:{x:e.x,y:e.y,width:e.width,height:e.height},text:n,timestamp:Date.now(),resolved:!1};return this.annotations.set(i.id,i),this.emit("add",i),i}resolve(t){const e=this.annotations.get(t);e&&(e.resolved=!0,this.emit("resolve",e))}remove(t){const e=this.annotations.get(t);e&&(this.annotations.delete(t),this.emit("remove",e))}get(t){return this.annotations.get(t)}getAll(){return Array.from(this.annotations.values())}getPending(){return this.getAll().filter(t=>!t.resolved)}getCount(){return this.annotations.size}exportJSON(){return JSON.stringify(this.getAll(),null,2)}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){this.listeners.get(t)?.delete(e)}emit(t,e){this.listeners.get(t)?.forEach(t=>t(e))}}class n{constructor(t){this.root=t,this.collapsed=!0,this.settingsOpen=!1,this.el=document.createElement("div"),this.el.className="refiner-toolbar",this.el.setAttribute("data-refiner-toolbar",""),this.el.setAttribute("data-collapsed","true"),this.render(),t.appendChild(this.el),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.collapsed=!1,this.el.setAttribute("data-collapsed","false"),this.updateBadgeVisibility()})})}render(){const t=document.createElement("div");t.className="toolbar-pill",this.innerEl=document.createElement("div"),this.innerEl.className="toolbar-inner",this.countBadge=document.createElement("span"),this.countBadge.className="toolbar-count",this.countBadge.textContent="0",this.innerEl.appendChild(this.createBtn(this.countBadge,"Annotations",null));const e='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';this.copyBtn=this.createBtn(e,"Copy annotations",()=>{this.copyBtn.classList.contains("disabled")||(this.onCopy?.(),this.copyBtn.querySelector(".toolbar-icon").innerHTML='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="20 6 9 17 4 12"/></svg>',setTimeout(()=>{this.copyBtn.querySelector(".toolbar-icon").innerHTML=e},1500))}),this.copyBtn.classList.add("disabled"),this.innerEl.appendChild(this.copyBtn),this.clearBtn=this.createBtn('<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>',"Clear all",()=>{this.clearBtn.classList.contains("disabled")||this.onClear?.()}),this.clearBtn.classList.add("disabled"),this.innerEl.appendChild(this.clearBtn),this.innerEl.appendChild(this.createBtn('<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>',"Settings",()=>this.onSettings?.()));const n=document.createElement("div");n.className="toolbar-divider",this.innerEl.appendChild(n),t.appendChild(this.innerEl);const i='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>';this.toggleBtn=this.createBtn(i,"",()=>this.toggleCollapse()),this.toggleBtn.classList.add("toolbar-toggle-btn"),t.appendChild(this.toggleBtn),this.expandBadge=document.createElement("span"),this.expandBadge.className="toolbar-expand-badge hidden",this.expandBadge.textContent="0",t.appendChild(this.expandBadge),this.el.appendChild(t),this.el.addEventListener("transitionend",()=>{this.toggleBtn.querySelector(".toolbar-icon").innerHTML=this.collapsed?i:'<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>'})}createBtn(t,e,n){const i=document.createElement("button");i.className="toolbar-btn";const s=document.createElement("span");if(s.className="toolbar-icon","string"==typeof t?s.innerHTML=t:s.appendChild(t),i.appendChild(s),e){const t=document.createElement("span");t.className="toolbar-tooltip",t.textContent=e,i.appendChild(t)}return n&&i.addEventListener("click",n),i}toggleCollapse(){this.collapsed=!this.collapsed,this.el.setAttribute("data-collapsed",String(this.collapsed)),this.updateBadgeVisibility(),this.collapsed&&this.onCollapse?.()}setSettingsOpen(t){this.settingsOpen=t,this.el.classList.toggle("tooltips-hidden",t)}updateCount(t){this.countBadge.textContent=String(t),this.expandBadge.textContent=String(t),this.updateBadgeVisibility(t);const e=0===t;this.copyBtn.classList.toggle("disabled",e),this.clearBtn.classList.toggle("disabled",e)}updateBadgeVisibility(t){const e=t??parseInt(this.expandBadge.textContent||"0",10);this.expandBadge.classList.toggle("hidden",0===e||!this.collapsed)}}class i{constructor(t){this.root=t,this.enabled=!0,this.blocking=!0,this.currentTarget=null,this.highlightColor="#7C3AED",this.handleMouseMove=t=>{if(!this.enabled)return;if(this.isOverOwnUI(t.clientX,t.clientY))return void this.hideHighlight();const e=this.getElementAt(t.clientX,t.clientY);e&&e!==this.currentTarget&&(this.currentTarget=e,this.showHighlight(e))},this.handleClick=t=>{if(!this.enabled)return;if(this.isOverOwnUI(t.clientX,t.clientY))return;t.preventDefault(),t.stopPropagation();const e=this.getElementAt(t.clientX,t.clientY);if(e){const t=e.getBoundingClientRect();this.onClick?.(e,t)}},this.el=document.createElement("div"),this.el.className="refiner-overlay",this.el.setAttribute("data-blocking","true"),this.highlight=document.createElement("div"),this.highlight.className="refiner-highlight",this.highlight.style.display="none",t.appendChild(this.highlight),t.appendChild(this.el),this.el.addEventListener("mousemove",this.handleMouseMove),this.el.addEventListener("click",this.handleClick),this.el.addEventListener("mouseleave",()=>this.hideHighlight())}isOverOwnUI(t,e){const n=this.root.elementFromPoint(t,e);return!!n&&(n!==this.el&&n!==this.highlight)}getElementAt(t,e){this.el.style.pointerEvents="none",this.highlight.style.pointerEvents="none";const n=document.elementFromPoint(t,e);return this.el.style.pointerEvents="",this.highlight.style.pointerEvents="",n&&n===this.root.host?null:n}showHighlight(t){const e=t.getBoundingClientRect();this.highlight.style.display="block",this.highlight.style.top=e.top-2+"px",this.highlight.style.left=e.left-2+"px",this.highlight.style.width=`${e.width+4}px`,this.highlight.style.height=`${e.height+4}px`,this.highlight.style.borderColor=this.highlightColor}hideHighlight(){this.highlight.style.display="none",this.currentTarget=null}setHighlightColor(t){this.highlightColor=t}setBlocking(t){this.blocking=t,this.el.setAttribute("data-blocking",String(t)),t||this.hideHighlight()}setEnabled(t){this.enabled=t,this.el.classList.toggle("hidden",!t),t||this.hideHighlight()}}class s{constructor(t){this.root=t,this.el=document.createElement("div"),this.el.className="refiner-dialog hidden",this.render(),t.appendChild(this.el)}render(){const t=document.createElement("div");t.className="dialog-header";const e=document.createElement("span");e.textContent="What should change?",t.appendChild(e),this.el.appendChild(t),this.textarea=document.createElement("textarea"),this.textarea.className="dialog-textarea",this.textarea.placeholder="Describe the issue or improvement...",this.textarea.addEventListener("input",()=>{this.addBtn.disabled=0===this.textarea.value.trim().length}),this.textarea.addEventListener("keydown",t=>{"Enter"===t.key&&(t.metaKey||t.ctrlKey)&&this.textarea.value.trim()&&this.submit(),"Escape"===t.key&&(this.hide(),this.onCancel?.())}),this.el.appendChild(this.textarea);const n=document.createElement("div");n.className="dialog-actions";const i=document.createElement("button");i.className="dialog-btn dialog-btn-cancel",i.textContent="Cancel",i.addEventListener("click",()=>{this.hide(),this.onCancel?.()}),this.addBtn=document.createElement("button"),this.addBtn.className="dialog-btn dialog-btn-add",this.addBtn.textContent="Add",this.addBtn.disabled=!0,this.addBtn.addEventListener("click",()=>this.submit()),n.appendChild(i),n.appendChild(this.addBtn),this.el.appendChild(n)}submit(){const t=this.textarea.value.trim();t&&(this.onSubmit?.(t),this.hide())}show(t,e){let n=t+12,i=e+12;n+320>window.innerWidth-16&&(n=t-320-12),i+200>window.innerHeight-16&&(i=e-200-12),this.el.style.left=`${Math.max(16,n)}px`,this.el.style.top=`${Math.max(16,i)}px`,this.el.classList.remove("hidden"),this.textarea.value="",this.addBtn.disabled=!0,requestAnimationFrame(()=>this.textarea.focus())}hide(){this.el.classList.add("hidden"),this.textarea.value=""}isVisible(){return!this.el.classList.contains("hidden")}}class o{constructor(t,e){this.root=t,this.store=e,this.markers=new Map,this.rafId=null,this.color="#7C3AED",this.container=document.createElement("div"),this.container.className="refiner-markers",t.appendChild(this.container),e.on("add",t=>this.addMarker(t)),e.on("resolve",t=>this.updateMarker(t)),e.on("remove",t=>this.removeMarker(t.id));const n=()=>this.repositionAll();window.addEventListener("scroll",n,{passive:!0}),window.addEventListener("resize",n,{passive:!0})}addMarker(t){const e=document.createElement("div");e.className="refiner-marker",e.setAttribute("data-annotation-marker",t.id),e.setAttribute("data-resolved",String(t.resolved)),e.style.background=this.color;const n=this.markers.size+1;e.textContent=String(n);const i=document.createElement("div");i.className="marker-tooltip";const s=document.createElement("div");s.textContent=t.text,i.appendChild(s);const o=document.createElement("div");o.className="marker-tooltip-actions";const r=document.createElement("button");r.className="marker-tooltip-btn resolve",r.textContent="Resolve",r.addEventListener("click",e=>{e.stopPropagation(),this.store.resolve(t.id)});const a=document.createElement("button");a.className="marker-tooltip-btn delete",a.textContent="Delete",a.addEventListener("click",e=>{e.stopPropagation(),this.store.remove(t.id)}),o.appendChild(r),o.appendChild(a),i.appendChild(o),e.appendChild(i),this.positionMarker(e,t),this.container.appendChild(e),this.markers.set(t.id,{el:e,annotation:t})}updateMarker(t){const e=this.markers.get(t.id);e&&(e.annotation=t,e.el.setAttribute("data-resolved",String(t.resolved)))}removeMarker(t){const e=this.markers.get(t);e&&(e.el.remove(),this.markers.delete(t),this.renumber())}renumber(){let t=1;for(const[,e]of this.markers){const n=e.el.childNodes[0];n&&n.nodeType===Node.TEXT_NODE&&(n.textContent=String(t)),t++}}positionMarker(t,e){const n=this.queryTarget(e.targetSelector);if(n){const e=n.getBoundingClientRect();t.style.top=e.top-8+"px",t.style.left=e.right-8+"px"}else t.style.top=e.targetRect.y-8+"px",t.style.left=e.targetRect.x+e.targetRect.width-8+"px"}queryTarget(t){try{return document.querySelector(t)}catch{return null}}setColor(t){this.color=t;for(const[,e]of this.markers)e.el.style.background=t}clearAll(){for(const[t]of this.markers)this.removeMarker(t)}repositionAll(){null===this.rafId&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null;for(const[,t]of this.markers)this.positionMarker(t.el,t.annotation)}))}}const r=[{id:"purple",color:"#7C3AED"},{id:"blue",color:"#2563EB"},{id:"green",color:"#059669"},{id:"yellow",color:"#D97706"},{id:"orange",color:"#EA580C"},{id:"red",color:"#DC2626"},{id:"pink",color:"#DB2777"}];class a{constructor(t){this.root=t,this.visible=!1,this.settings={clearOnCopy:!1,blockInteractions:!0,markerColor:"#7C3AED"},this.el=document.createElement("div"),this.el.className="settings-panel hidden",this.render(),t.appendChild(this.el)}render(){const t=document.createElement("div");t.className="settings-header";const e=document.createElement("span");e.className="settings-title",e.textContent="reFiner";const n=document.createElement("span");n.className="settings-version",n.textContent="v0.1.0",t.appendChild(e),t.appendChild(n),this.el.appendChild(t),this.el.appendChild(this.createDivider());const i=document.createElement("div");i.className="settings-section";const s=document.createElement("span");s.className="settings-label",s.textContent="Marker Colour",i.appendChild(s);const o=document.createElement("div");o.className="settings-color-row";for(const t of r){const e=document.createElement("button");e.className="settings-swatch",e.style.background=t.color,e.setAttribute("data-color",t.color),t.color===this.settings.markerColor&&e.classList.add("selected"),e.addEventListener("click",()=>{o.querySelectorAll(".settings-swatch").forEach(t=>t.classList.remove("selected")),e.classList.add("selected"),this.settings.markerColor=t.color,this.emitChange()}),o.appendChild(e)}i.appendChild(o),this.el.appendChild(i),this.el.appendChild(this.createDivider()),this.el.appendChild(this.createCheckbox("Clear on copy",this.settings.clearOnCopy,t=>{this.settings.clearOnCopy=t,this.emitChange()})),this.el.appendChild(this.createCheckbox("Block page interactions",this.settings.blockInteractions,t=>{this.settings.blockInteractions=t,this.emitChange()})),this.el.appendChild(this.createDivider());const a=document.createElement("div");a.className="settings-mcp-row",this.mcpDot=document.createElement("span"),this.mcpDot.className="settings-mcp-dot disconnected",this.mcpLabel=document.createElement("span"),this.mcpLabel.className="settings-check-label",this.mcpLabel.textContent="MCP Disconnected",a.appendChild(this.mcpDot),a.appendChild(this.mcpLabel),this.el.appendChild(a)}createCheckbox(t,e,n){const i=document.createElement("label");i.className="settings-check-row";const s=document.createElement("input");s.type="checkbox",s.className="settings-checkbox",s.checked=e,s.addEventListener("change",()=>n(s.checked));const o=document.createElement("span");return o.className="settings-check-label",o.textContent=t,i.appendChild(s),i.appendChild(o),i}createDivider(){const t=document.createElement("div");return t.className="settings-divider",t}emitChange(){this.onChange?.({...this.settings})}toggle(){this.visible=!this.visible,this.el.classList.toggle("hidden",!this.visible)}hide(){this.visible=!1,this.el.classList.add("hidden")}isVisible(){return this.visible}setMcpStatus(t){this.mcpDot.className="settings-mcp-dot "+(t?"connected":"disconnected"),this.mcpLabel.textContent=t?"MCP Connected":"MCP Disconnected"}getSettings(){return{...this.settings}}}class l{constructor(t,e=4848){this.store=t,this.sessionId=null,this.connected=!1,this.retryTimer=null,this.baseUrl=`http://localhost:${e}`,this.discover(),this.store.on("add",t=>this.postAnnotation(t)),this.store.on("resolve",t=>this.patchAnnotation(t))}async discover(){try{const t=await fetch(`${this.baseUrl}/health`),e=await t.json();e&&"object"==typeof e&&"status"in e&&"ok"===e.status&&(this.connected=!0,this.onChange?.(!0),await this.createSession(),this.stopRetry())}catch{this.connected=!1,this.onChange?.(!1),this.startRetry()}}startRetry(){this.retryTimer||(this.retryTimer=setInterval(()=>this.discover(),5e3))}stopRetry(){this.retryTimer&&(clearInterval(this.retryTimer),this.retryTimer=null)}async createSession(){try{const t=await fetch(`${this.baseUrl}/sessions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:window.location.href,title:document.title||window.location.pathname})}),e=await t.json();this.sessionId=e.id}catch{}}async postAnnotation(t){if(this.connected&&this.sessionId)try{await fetch(`${this.baseUrl}/sessions/${this.sessionId}/annotations`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({targetSelector:t.targetSelector,targetRect:t.targetRect,text:t.text})})}catch{}}async patchAnnotation(t){if(this.connected)try{await fetch(`${this.baseUrl}/annotations/${t.id}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({resolved:!0,summary:"Resolved from browser"})})}catch{}}isConnected(){return this.connected}destroy(){this.stopRetry()}}class d{constructor(t={}){this.mcpBridge=null,this.currentTarget=null,this.currentRect=null,this.clearOnCopy=!1,this.host=document.createElement("div"),this.host.id="refiner-host",this.shadow=this.host.attachShadow({mode:"open"});const r=document.createElement("style");r.textContent='\n :host {\n all: initial;\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n z-index: 2147483647;\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', system-ui, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n color: #1a1a2e;\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ── Toolbar ── */\n\n .refiner-toolbar {\n position: fixed;\n bottom: 24px;\n right: 24px;\n z-index: 10;\n user-select: none;\n }\n\n .toolbar-pill {\n display: flex;\n align-items: center;\n position: relative;\n background: #1a1a2e;\n border-radius: 100px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15);\n padding: 6px;\n transform: scale(1);\n transform-origin: right center;\n transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .refiner-toolbar[data-collapsed="true"] .toolbar-pill {\n transform: scale(0.92);\n }\n\n .toolbar-inner {\n display: flex;\n align-items: center;\n gap: 2px;\n overflow: hidden;\n clip-path: inset(0);\n max-width: 300px;\n opacity: 1;\n padding-right: 2px;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s ease 0.1s,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .refiner-toolbar[data-collapsed="true"] .toolbar-inner {\n max-width: 0;\n opacity: 0;\n padding-right: 0;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.15s ease,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .toolbar-btn {\n position: relative;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: #a0a0b8;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n }\n\n .toolbar-btn:hover {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.1);\n }\n\n .toolbar-btn.active {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.15);\n }\n\n .toolbar-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .toolbar-count {\n font-size: 14px;\n font-weight: 700;\n min-width: 18px;\n text-align: center;\n }\n\n .toolbar-divider {\n width: 1px;\n height: 20px;\n background: rgba(255, 255, 255, 0.15);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Tooltip */\n .toolbar-tooltip {\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translateX(-50%);\n padding: 6px 10px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n }\n\n .toolbar-tooltip::after {\n content: \'\';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 5px solid transparent;\n border-top-color: #1a1a2e;\n }\n\n .toolbar-btn:hover .toolbar-tooltip {\n opacity: 1;\n }\n\n .tooltips-hidden .toolbar-tooltip {\n display: none;\n }\n\n .toolbar-btn.disabled {\n opacity: 0.3;\n cursor: default;\n }\n\n .toolbar-btn.disabled:hover {\n color: #a0a0b8;\n background: transparent;\n }\n\n /* Toggle button (always visible) */\n .toolbar-toggle-btn {\n flex-shrink: 0;\n }\n\n /* Badge for collapsed state */\n .toolbar-expand-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 20px;\n height: 20px;\n padding: 0 5px;\n border-radius: 10px;\n background: #DC2626;\n color: #ffffff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n }\n\n .toolbar-expand-badge.hidden {\n display: none;\n }\n\n /* ── Settings Panel ── */\n\n .settings-panel {\n position: fixed;\n bottom: 80px;\n right: 24px;\n width: 300px;\n z-index: 12;\n background: #1a1a2e;\n border-radius: 16px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 20px;\n color: #e8e8f0;\n transform-origin: bottom right;\n transition: transform 0.25s ease, opacity 0.1s ease;\n transform: scale(1);\n opacity: 1;\n }\n\n .settings-panel.hidden {\n transform: scale(0.4);\n opacity: 0;\n pointer-events: none;\n }\n\n .settings-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n }\n\n .settings-title {\n font-size: 16px;\n font-weight: 700;\n font-style: normal;\n color: #ffffff;\n }\n\n .settings-version {\n font-size: 12px;\n color: #6b6b80;\n font-weight: 500;\n }\n\n .settings-divider {\n height: 1px;\n background: rgba(255, 255, 255, 0.08);\n margin: 16px 0;\n }\n\n .settings-section {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .settings-label {\n font-size: 14px;\n font-weight: 500;\n color: #c0c0d0;\n }\n\n .settings-color-row {\n display: flex;\n gap: 8px;\n }\n\n .settings-swatch {\n width: 24px;\n height: 24px;\n border-radius: 4px;\n border: 2px solid transparent;\n cursor: pointer;\n transition: transform 0.15s, border-color 0.15s;\n outline: none;\n }\n\n .settings-swatch:hover {\n transform: scale(1.1);\n }\n\n .settings-swatch.selected {\n border-color: #ffffff;\n transform: scale(1.1);\n }\n\n .settings-check-row {\n display: flex;\n align-items: center;\n gap: 10px;\n cursor: pointer;\n padding: 2px 0;\n }\n\n .settings-checkbox {\n appearance: none;\n -webkit-appearance: none;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 2px solid #4a4a60;\n background: transparent;\n cursor: pointer;\n position: relative;\n flex-shrink: 0;\n transition: background 0.15s, border-color 0.15s;\n }\n\n .settings-checkbox:checked {\n background: #2563EB;\n border-color: #2563EB;\n }\n\n .settings-checkbox:checked::after {\n content: \'\';\n position: absolute;\n top: 2px;\n left: 5px;\n width: 5px;\n height: 9px;\n border: solid #ffffff;\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n }\n\n .settings-check-label {\n font-size: 14px;\n font-weight: 500;\n color: #e8e8f0;\n }\n\n /* ── Overlay ── */\n\n .refiner-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n cursor: crosshair;\n z-index: 1;\n }\n\n .refiner-overlay[data-blocking="true"] {\n pointer-events: all;\n }\n\n .refiner-overlay[data-blocking="false"] {\n pointer-events: none;\n }\n\n .refiner-overlay.hidden {\n display: none;\n }\n\n /* ── Highlight ── */\n\n .refiner-highlight {\n position: fixed;\n pointer-events: none;\n border: 2px dashed;\n border-radius: 3px;\n z-index: 2;\n transition: all 0.1s ease;\n }\n\n /* ── Dialog ── */\n\n .refiner-dialog {\n position: fixed;\n width: 320px;\n background: #1a1a2e;\n border: 1px solid rgba(255, 255, 255, 0.08);\n border-radius: 14px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 16px;\n z-index: 11;\n color: #e8e8f0;\n animation: dialog-in 0.2s ease;\n }\n\n @keyframes dialog-in {\n from { opacity: 0; transform: translateY(4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .refiner-dialog.hidden {\n display: none;\n }\n\n .dialog-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n }\n\n .dialog-header span {\n font-size: 12px;\n font-weight: 600;\n color: #c0c0d0;\n }\n\n .dialog-textarea {\n width: 100%;\n min-height: 72px;\n padding: 10px 12px;\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-radius: 10px;\n font-family: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: #e8e8f0;\n background: rgba(255, 255, 255, 0.06);\n resize: vertical;\n outline: none;\n transition: border-color 0.15s;\n }\n\n .dialog-textarea:focus {\n border-color: rgba(255, 255, 255, 0.25);\n }\n\n .dialog-textarea::placeholder {\n color: #6b6b80;\n }\n\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 12px;\n }\n\n .dialog-btn {\n height: 32px;\n padding: 0 14px;\n border-radius: 8px;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .dialog-btn-cancel {\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.12);\n color: #a0a0b8;\n }\n\n .dialog-btn-cancel:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #e8e8f0;\n }\n\n .dialog-btn-add {\n background: #2563EB;\n border: none;\n color: #ffffff;\n }\n\n .dialog-btn-add:hover {\n background: #3B82F6;\n }\n\n .dialog-btn-add:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n }\n\n /* ── Markers ── */\n\n .refiner-marker {\n position: fixed;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 700;\n color: #ffffff;\n cursor: pointer;\n z-index: 10;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n transition: transform 0.15s;\n pointer-events: all;\n }\n\n .refiner-marker:hover {\n transform: scale(1.2);\n }\n\n .refiner-marker[data-resolved="true"] {\n opacity: 0.4;\n }\n\n .marker-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n width: 220px;\n padding: 10px 12px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n line-height: 1.4;\n border-radius: 10px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .refiner-marker:hover .marker-tooltip {\n opacity: 1;\n }\n\n .marker-tooltip-actions {\n display: flex;\n gap: 6px;\n margin-top: 8px;\n border-top: 1px solid rgba(255,255,255,0.1);\n padding-top: 8px;\n }\n\n .marker-tooltip-btn {\n height: 22px;\n padding: 0 8px;\n border-radius: 5px;\n border: none;\n font-size: 10px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .marker-tooltip-btn.resolve {\n background: #34D399;\n color: #0a2e1f;\n }\n\n .marker-tooltip-btn.resolve:hover {\n background: #4ade80;\n }\n\n .marker-tooltip-btn.delete {\n background: rgba(255,255,255,0.1);\n color: #e8e8f0;\n }\n\n .marker-tooltip-btn.delete:hover {\n background: #FF6B6B;\n color: #fff;\n }\n\n /* MCP status */\n .settings-mcp-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n }\n\n .settings-mcp-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .settings-mcp-dot.connected {\n background: #34D399;\n box-shadow: 0 0 6px #34D39980;\n }\n\n .settings-mcp-dot.disconnected {\n background: #6B7280;\n }\n',this.shadow.appendChild(r),this.store=new e,this.toolbar=new n(this.shadow),this.settings=new a(this.shadow),this.overlay=new i(this.shadow),this.dialog=new s(this.shadow),this.markers=new o(this.shadow,this.store),this.toolbar.onCopy=()=>this.copyAnnotations(),this.toolbar.onClear=()=>this.clearAnnotations(),this.toolbar.onSettings=()=>{this.settings.toggle(),this.toolbar.setSettingsOpen(this.settings.isVisible())},this.toolbar.onCollapse=()=>{this.settings.hide(),this.toolbar.setSettingsOpen(!1)},this.settings.onChange=t=>{this.clearOnCopy=t.clearOnCopy,this.overlay.setBlocking(t.blockInteractions),this.markers.setColor(t.markerColor),this.overlay.setHighlightColor(t.markerColor)},this.overlay.onClick=(t,e)=>{if(this.settings.isVisible())return void this.settings.hide();if(this.dialog.isVisible())return void this.dialog.hide();this.currentTarget=t,this.currentRect=e;const n=e.left+e.width/2,i=e.top+e.height/2;this.dialog.show(n,i)},this.dialog.onSubmit=t=>{if(this.currentTarget&&this.currentRect){const e=function(t){if(t.id)return`#${CSS.escape(t.id)}`;if(t.classList.length>0){const e=`${t.tagName.toLowerCase()}.${Array.from(t.classList).map(CSS.escape).join(".")}`;if(1===document.querySelectorAll(e).length)return e}const e=[];let n=t;for(;n&&n!==document.documentElement;){const t=n.tagName.toLowerCase(),i=n.parentElement;if(n.id){e.unshift(`#${CSS.escape(n.id)}`);break}if(i){const s=Array.from(i.children).filter(t=>t.tagName===n.tagName);if(1===s.length)e.unshift(t);else{const i=s.indexOf(n)+1;e.unshift(`${t}:nth-child(${i})`)}}else e.unshift(t);n=i}return e.join(" > ")}(this.currentTarget);this.store.add(e,this.currentRect,t),this.toolbar.updateCount(this.store.getCount())}this.currentTarget=null,this.currentRect=null},this.dialog.onCancel=()=>{this.currentTarget=null,this.currentRect=null},this.store.on("resolve",()=>this.toolbar.updateCount(this.store.getCount())),this.store.on("remove",()=>this.toolbar.updateCount(this.store.getCount())),!1!==t.mcpEnabled&&(this.mcpBridge=new l(this.store,t.mcpPort),this.mcpBridge.onChange=t=>{this.settings.setMcpStatus(t)}),document.body.appendChild(this.host),!1===t.enabled&&this.disable()}enable(){this.host.style.display="",this.overlay.setEnabled(!0)}disable(){this.host.style.display="none",this.overlay.setEnabled(!1)}destroy(){this.mcpBridge?.destroy(),this.host.remove()}getAnnotations(){return this.store.getAll()}getAnnotationCount(){return this.store.getCount()}formatForAgent(){const t=this.store.getAll();if(0===t.length)return"No annotations.";const e=[`# Design Annotations — ${document.title||window.location.pathname}`,""];for(let n=0;n<t.length;n++){const i=t[n],s=i.resolved?" (resolved)":"";e.push(`## ${n+1}.${s}`),e.push(`**Element:** \`${i.targetSelector}\``),e.push(`**Issue:** ${i.text}`),e.push("")}return e.join("\n")}clearAnnotations(){const t=this.store.getAll();for(const e of t)this.store.remove(e.id);this.toolbar.updateCount(0)}copyAnnotations(){const t=this.formatForAgent();navigator.clipboard.writeText(t),this.clearOnCopy&&this.clearAnnotations()}}if("undefined"!=typeof window&&"undefined"!=typeof document){const t=()=>{if(window.__refiner)return;const t=document.currentScript,e=t?.dataset.refinerPosition??"right",n="false"!==t?.dataset.refinerEnabled,i=t?.dataset.refinerMcpPort?parseInt(t.dataset.refinerMcpPort,10):void 0,s="false"!==t?.dataset.refinerMcpEnabled,o=new d({position:e,enabled:n,mcpPort:i,mcpEnabled:s});window.__refiner=o};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}return t.Refiner=d,t}({});
|
|
1
|
+
var Refiner=function(t){"use strict";class e{constructor(){this.annotations=new Map,this.listeners=new Map}add(t,e,n){const i={id:crypto.randomUUID(),targetSelector:t,targetRect:{x:e.x,y:e.y,width:e.width,height:e.height},text:n,timestamp:Date.now(),resolved:!1};return this.annotations.set(i.id,i),this.emit("add",i),i}resolve(t){const e=this.annotations.get(t);e&&(e.resolved=!0,this.emit("resolve",e))}remove(t){const e=this.annotations.get(t);e&&(this.annotations.delete(t),this.emit("remove",e))}get(t){return this.annotations.get(t)}getAll(){return Array.from(this.annotations.values())}getPending(){return this.getAll().filter(t=>!t.resolved)}getCount(){return this.annotations.size}exportJSON(){return JSON.stringify(this.getAll(),null,2)}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){this.listeners.get(t)?.delete(e)}emit(t,e){this.listeners.get(t)?.forEach(t=>t(e))}}class n{constructor(t){this.root=t,this.collapsed=!0,this.settingsOpen=!1,this.el=document.createElement("div"),this.el.className="refiner-toolbar",this.el.setAttribute("data-refiner-toolbar",""),this.el.setAttribute("data-collapsed","true"),this.render(),t.appendChild(this.el),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.collapsed=!1,this.el.setAttribute("data-collapsed","false"),this.updateBadgeVisibility()})})}render(){const t=document.createElement("div");t.className="toolbar-pill",this.innerEl=document.createElement("div"),this.innerEl.className="toolbar-inner",this.countBadge=document.createElement("span"),this.countBadge.className="toolbar-count",this.countBadge.textContent="0",this.innerEl.appendChild(this.createBtn(this.countBadge,"Annotations",null));const e='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';this.copyBtn=this.createBtn(e,"Copy annotations",()=>{this.copyBtn.classList.contains("disabled")||(this.onCopy?.(),this.copyBtn.querySelector(".toolbar-icon").innerHTML='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="20 6 9 17 4 12"/></svg>',setTimeout(()=>{this.copyBtn.querySelector(".toolbar-icon").innerHTML=e},1500))}),this.copyBtn.classList.add("disabled"),this.innerEl.appendChild(this.copyBtn),this.clearBtn=this.createBtn('<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>',"Clear all",()=>{this.clearBtn.classList.contains("disabled")||this.onClear?.()}),this.clearBtn.classList.add("disabled"),this.innerEl.appendChild(this.clearBtn),this.innerEl.appendChild(this.createBtn('<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>',"Settings",()=>this.onSettings?.()));const n=document.createElement("div");n.className="toolbar-divider",this.innerEl.appendChild(n),t.appendChild(this.innerEl);const i='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>';this.toggleBtn=this.createBtn(i,"",()=>this.toggleCollapse()),this.toggleBtn.classList.add("toolbar-toggle-btn"),t.appendChild(this.toggleBtn),this.expandBadge=document.createElement("span"),this.expandBadge.className="toolbar-expand-badge hidden",this.expandBadge.textContent="0",t.appendChild(this.expandBadge),this.el.appendChild(t),this.el.addEventListener("transitionend",()=>{this.toggleBtn.querySelector(".toolbar-icon").innerHTML=this.collapsed?i:'<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>'})}createBtn(t,e,n){const i=document.createElement("button");i.className="toolbar-btn";const s=document.createElement("span");if(s.className="toolbar-icon","string"==typeof t?s.innerHTML=t:s.appendChild(t),i.appendChild(s),e){const t=document.createElement("span");t.className="toolbar-tooltip",t.textContent=e,i.appendChild(t)}return n&&i.addEventListener("click",n),i}toggleCollapse(){this.collapsed=!this.collapsed,this.el.setAttribute("data-collapsed",String(this.collapsed)),this.updateBadgeVisibility(),this.collapsed?this.onCollapse?.():this.onExpand?.()}setSettingsOpen(t){this.settingsOpen=t,this.el.classList.toggle("tooltips-hidden",t)}updateCount(t){this.countBadge.textContent=String(t),this.expandBadge.textContent=String(t),this.updateBadgeVisibility(t);const e=0===t;this.copyBtn.classList.toggle("disabled",e),this.clearBtn.classList.toggle("disabled",e)}updateBadgeVisibility(t){const e=t??parseInt(this.expandBadge.textContent||"0",10);this.expandBadge.classList.toggle("hidden",0===e||!this.collapsed)}}class i{constructor(t){this.root=t,this.enabled=!0,this.blocking=!0,this.currentTarget=null,this.highlightColor="#7C3AED",this.handleMouseMove=t=>{if(!this.enabled)return;if(this.isOverOwnUI(t.clientX,t.clientY))return void this.hideHighlight();const e=this.getElementAt(t.clientX,t.clientY);e&&e!==this.currentTarget&&(this.currentTarget=e,this.showHighlight(e))},this.handleClick=t=>{if(!this.enabled)return;if(this.isOverOwnUI(t.clientX,t.clientY))return;t.preventDefault(),t.stopPropagation();const e=this.getElementAt(t.clientX,t.clientY);if(e){const t=e.getBoundingClientRect();this.onClick?.(e,t)}},this.handleKeyBlock=t=>{if(!this.enabled||!this.blocking)return;const e=t.target;e&&(e===this.root.host||this.root.host.contains(e))||(t.preventDefault(),t.stopPropagation())},this.el=document.createElement("div"),this.el.className="refiner-overlay",this.el.setAttribute("data-blocking","true"),this.highlight=document.createElement("div"),this.highlight.className="refiner-highlight",this.highlight.style.display="none",t.appendChild(this.highlight),t.appendChild(this.el),this.el.addEventListener("mousemove",this.handleMouseMove),this.el.addEventListener("click",this.handleClick),this.el.addEventListener("mouseleave",()=>this.hideHighlight()),document.addEventListener("keydown",this.handleKeyBlock,!0)}isOverOwnUI(t,e){const n=this.root.elementFromPoint(t,e);return!!n&&(n!==this.el&&n!==this.highlight)}getElementAt(t,e){this.el.style.pointerEvents="none",this.highlight.style.pointerEvents="none";const n=document.elementFromPoint(t,e);return this.el.style.pointerEvents="",this.highlight.style.pointerEvents="",n&&n===this.root.host?null:n}showHighlight(t){const e=t.getBoundingClientRect();this.highlight.style.display="block",this.highlight.style.top=e.top-2+"px",this.highlight.style.left=e.left-2+"px",this.highlight.style.width=`${e.width+4}px`,this.highlight.style.height=`${e.height+4}px`,this.highlight.style.borderColor=this.highlightColor}hideHighlight(){this.highlight.style.display="none",this.currentTarget=null}setHighlightColor(t){this.highlightColor=t}setBlocking(t){this.blocking=t,this.el.setAttribute("data-blocking",String(t)),t||this.hideHighlight()}setEnabled(t){this.enabled=t,this.el.classList.toggle("hidden",!t),t||this.hideHighlight()}}class s{constructor(t){this.root=t,this.el=document.createElement("div"),this.el.className="refiner-dialog hidden",this.render(),t.appendChild(this.el)}render(){const t=document.createElement("div");t.className="dialog-header";const e=document.createElement("span");e.textContent="What should change?",t.appendChild(e),this.el.appendChild(t),this.textarea=document.createElement("textarea"),this.textarea.className="dialog-textarea",this.textarea.placeholder="Describe the issue or improvement...",this.textarea.addEventListener("input",()=>{this.addBtn.disabled=0===this.textarea.value.trim().length}),this.textarea.addEventListener("keydown",t=>{"Enter"===t.key&&(t.metaKey||t.ctrlKey)&&this.textarea.value.trim()&&this.submit(),"Escape"===t.key&&(this.hide(),this.onCancel?.())}),this.el.appendChild(this.textarea);const n=document.createElement("div");n.className="dialog-actions";const i=document.createElement("button");i.className="dialog-btn dialog-btn-cancel",i.textContent="Cancel",i.addEventListener("click",()=>{this.hide(),this.onCancel?.()}),this.addBtn=document.createElement("button"),this.addBtn.className="dialog-btn dialog-btn-add",this.addBtn.textContent="Add",this.addBtn.disabled=!0,this.addBtn.addEventListener("click",()=>this.submit()),n.appendChild(i),n.appendChild(this.addBtn),this.el.appendChild(n)}submit(){const t=this.textarea.value.trim();t&&(this.onSubmit?.(t),this.hide())}show(t,e){let n=t+12,i=e+12;n+320>window.innerWidth-16&&(n=t-320-12),i+200>window.innerHeight-16&&(i=e-200-12),this.el.style.left=`${Math.max(16,n)}px`,this.el.style.top=`${Math.max(16,i)}px`,this.el.classList.remove("hidden"),this.textarea.value="",this.addBtn.disabled=!0,requestAnimationFrame(()=>this.textarea.focus())}hide(){this.el.classList.add("hidden"),this.textarea.value=""}isVisible(){return!this.el.classList.contains("hidden")}}class o{constructor(t,e){this.root=t,this.store=e,this.markers=new Map,this.rafId=null,this.color="#7C3AED",this.container=document.createElement("div"),this.container.className="refiner-markers",t.appendChild(this.container),e.on("add",t=>this.addMarker(t)),e.on("resolve",t=>this.updateMarker(t)),e.on("remove",t=>this.removeMarker(t.id));const n=()=>this.repositionAll();window.addEventListener("scroll",n,{passive:!0}),window.addEventListener("resize",n,{passive:!0})}addMarker(t){const e=document.createElement("div");e.className="refiner-marker",e.setAttribute("data-annotation-marker",t.id),e.setAttribute("data-resolved",String(t.resolved)),e.style.background=this.color;const n=this.markers.size+1;e.textContent=String(n);const i=document.createElement("div");i.className="marker-tooltip";const s=document.createElement("div");s.textContent=t.text,i.appendChild(s);const o=document.createElement("div");o.className="marker-tooltip-actions";const r=document.createElement("button");r.className="marker-tooltip-btn resolve",r.textContent="Resolve",r.addEventListener("click",e=>{e.stopPropagation(),this.store.resolve(t.id)});const a=document.createElement("button");a.className="marker-tooltip-btn delete",a.textContent="Delete",a.addEventListener("click",e=>{e.stopPropagation(),this.store.remove(t.id)}),o.appendChild(r),o.appendChild(a),i.appendChild(o),e.appendChild(i),this.positionMarker(e,t),this.container.appendChild(e),this.markers.set(t.id,{el:e,annotation:t})}updateMarker(t){const e=this.markers.get(t.id);e&&(e.annotation=t,e.el.setAttribute("data-resolved",String(t.resolved)))}removeMarker(t){const e=this.markers.get(t);e&&(e.el.remove(),this.markers.delete(t),this.renumber())}renumber(){let t=1;for(const[,e]of this.markers){const n=e.el.childNodes[0];n&&n.nodeType===Node.TEXT_NODE&&(n.textContent=String(t)),t++}}positionMarker(t,e){const n=this.queryTarget(e.targetSelector);if(n){const e=n.getBoundingClientRect();t.style.top=e.top-8+"px",t.style.left=e.right-8+"px"}else t.style.top=e.targetRect.y-8+"px",t.style.left=e.targetRect.x+e.targetRect.width-8+"px"}queryTarget(t){try{return document.querySelector(t)}catch{return null}}setColor(t){this.color=t;for(const[,e]of this.markers)e.el.style.background=t}clearAll(){for(const[t]of this.markers)this.removeMarker(t)}repositionAll(){null===this.rafId&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null;for(const[,t]of this.markers)this.positionMarker(t.el,t.annotation)}))}}const r=[{id:"purple",color:"#7C3AED"},{id:"blue",color:"#2563EB"},{id:"green",color:"#059669"},{id:"yellow",color:"#D97706"},{id:"orange",color:"#EA580C"},{id:"red",color:"#DC2626"},{id:"pink",color:"#DB2777"}];class a{constructor(t){this.root=t,this.visible=!1,this.settings={clearOnCopy:!1,blockInteractions:!0,markerColor:"#7C3AED"},this.el=document.createElement("div"),this.el.className="settings-panel hidden",this.render(),t.appendChild(this.el)}render(){const t=document.createElement("div");t.className="settings-header";const e=document.createElement("span");e.className="settings-title",e.textContent="reFiner";const n=document.createElement("span");n.className="settings-version",n.textContent="v0.1.0",t.appendChild(e),t.appendChild(n),this.el.appendChild(t),this.el.appendChild(this.createDivider());const i=document.createElement("div");i.className="settings-section";const s=document.createElement("span");s.className="settings-label",s.textContent="Marker Colour",i.appendChild(s);const o=document.createElement("div");o.className="settings-color-row";for(const t of r){const e=document.createElement("button");e.className="settings-swatch",e.style.background=t.color,e.setAttribute("data-color",t.color),t.color===this.settings.markerColor&&e.classList.add("selected"),e.addEventListener("click",()=>{o.querySelectorAll(".settings-swatch").forEach(t=>t.classList.remove("selected")),e.classList.add("selected"),this.settings.markerColor=t.color,this.emitChange()}),o.appendChild(e)}i.appendChild(o),this.el.appendChild(i),this.el.appendChild(this.createDivider()),this.el.appendChild(this.createCheckbox("Clear on copy",this.settings.clearOnCopy,t=>{this.settings.clearOnCopy=t,this.emitChange()})),this.el.appendChild(this.createCheckbox("Block page interactions",this.settings.blockInteractions,t=>{this.settings.blockInteractions=t,this.emitChange()})),this.el.appendChild(this.createDivider());const a=document.createElement("div");a.className="settings-mcp-row",this.mcpDot=document.createElement("span"),this.mcpDot.className="settings-mcp-dot disconnected",this.mcpLabel=document.createElement("span"),this.mcpLabel.className="settings-check-label",this.mcpLabel.textContent="MCP Disconnected",a.appendChild(this.mcpDot),a.appendChild(this.mcpLabel),this.el.appendChild(a)}createCheckbox(t,e,n){const i=document.createElement("label");i.className="settings-check-row";const s=document.createElement("input");s.type="checkbox",s.className="settings-checkbox",s.checked=e,s.addEventListener("change",()=>n(s.checked));const o=document.createElement("span");return o.className="settings-check-label",o.textContent=t,i.appendChild(s),i.appendChild(o),i}createDivider(){const t=document.createElement("div");return t.className="settings-divider",t}emitChange(){this.onChange?.({...this.settings})}toggle(){this.visible=!this.visible,this.el.classList.toggle("hidden",!this.visible)}hide(){this.visible=!1,this.el.classList.add("hidden")}isVisible(){return this.visible}setMcpStatus(t){this.mcpDot.className="settings-mcp-dot "+(t?"connected":"disconnected"),this.mcpLabel.textContent=t?"MCP Connected":"MCP Disconnected"}getSettings(){return{...this.settings}}}class l{constructor(t,e=4848){this.store=t,this.sessionId=null,this.connected=!1,this.retryTimer=null,this.baseUrl=`http://localhost:${e}`,this.discover(),this.store.on("add",t=>this.postAnnotation(t)),this.store.on("resolve",t=>this.patchAnnotation(t))}async discover(){try{const t=await fetch(`${this.baseUrl}/health`),e=await t.json();e&&"object"==typeof e&&"status"in e&&"ok"===e.status&&(this.connected=!0,this.onChange?.(!0),await this.createSession(),this.stopRetry())}catch{this.connected=!1,this.onChange?.(!1),this.startRetry()}}startRetry(){this.retryTimer||(this.retryTimer=setInterval(()=>this.discover(),5e3))}stopRetry(){this.retryTimer&&(clearInterval(this.retryTimer),this.retryTimer=null)}async createSession(){try{const t=await fetch(`${this.baseUrl}/sessions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:window.location.href,title:document.title||window.location.pathname})}),e=await t.json();this.sessionId=e.id}catch{}}async postAnnotation(t){if(this.connected&&this.sessionId)try{await fetch(`${this.baseUrl}/sessions/${this.sessionId}/annotations`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({targetSelector:t.targetSelector,targetRect:t.targetRect,text:t.text})})}catch{}}async patchAnnotation(t){if(this.connected)try{await fetch(`${this.baseUrl}/annotations/${t.id}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({resolved:!0,summary:"Resolved from browser"})})}catch{}}isConnected(){return this.connected}destroy(){this.stopRetry()}}class d{constructor(t={}){this.mcpBridge=null,this.currentTarget=null,this.currentRect=null,this.clearOnCopy=!1,this.host=document.createElement("div"),this.host.id="refiner-host",this.shadow=this.host.attachShadow({mode:"open"});const r=document.createElement("style");r.textContent='\n :host {\n all: initial;\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n z-index: 2147483647;\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', system-ui, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n color: #1a1a2e;\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ── Toolbar ── */\n\n .refiner-toolbar {\n position: fixed;\n bottom: 24px;\n right: 24px;\n z-index: 10;\n user-select: none;\n }\n\n .toolbar-pill {\n display: flex;\n align-items: center;\n position: relative;\n background: #1a1a2e;\n border-radius: 100px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15);\n padding: 6px;\n transform: scale(1);\n transform-origin: right center;\n transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .refiner-toolbar[data-collapsed="true"] .toolbar-pill {\n transform: scale(0.92);\n }\n\n .toolbar-inner {\n display: flex;\n align-items: center;\n gap: 2px;\n overflow: hidden;\n clip-path: inset(0);\n max-width: 300px;\n opacity: 1;\n padding-right: 2px;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s ease 0.1s,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .refiner-toolbar[data-collapsed="true"] .toolbar-inner {\n max-width: 0;\n opacity: 0;\n padding-right: 0;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.15s ease,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .toolbar-btn {\n position: relative;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: #a0a0b8;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n }\n\n .toolbar-btn:hover {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.1);\n }\n\n .toolbar-btn.active {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.15);\n }\n\n .toolbar-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .toolbar-count {\n font-size: 14px;\n font-weight: 700;\n min-width: 18px;\n text-align: center;\n }\n\n .toolbar-divider {\n width: 1px;\n height: 20px;\n background: rgba(255, 255, 255, 0.15);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Tooltip */\n .toolbar-tooltip {\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translateX(-50%);\n padding: 6px 10px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n }\n\n .toolbar-tooltip::after {\n content: \'\';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 5px solid transparent;\n border-top-color: #1a1a2e;\n }\n\n .toolbar-btn:hover .toolbar-tooltip {\n opacity: 1;\n }\n\n .tooltips-hidden .toolbar-tooltip {\n display: none;\n }\n\n .toolbar-btn.disabled {\n opacity: 0.3;\n cursor: default;\n }\n\n .toolbar-btn.disabled:hover {\n color: #a0a0b8;\n background: transparent;\n }\n\n /* Toggle button (always visible) */\n .toolbar-toggle-btn {\n flex-shrink: 0;\n }\n\n /* Badge for collapsed state */\n .toolbar-expand-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 20px;\n height: 20px;\n padding: 0 5px;\n border-radius: 10px;\n background: #DC2626;\n color: #ffffff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n }\n\n .toolbar-expand-badge.hidden {\n display: none;\n }\n\n /* ── Settings Panel ── */\n\n .settings-panel {\n position: fixed;\n bottom: 80px;\n right: 24px;\n width: 300px;\n z-index: 12;\n background: #1a1a2e;\n border-radius: 16px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 20px;\n color: #e8e8f0;\n transform-origin: bottom right;\n transition: transform 0.25s ease, opacity 0.1s ease;\n transform: scale(1);\n opacity: 1;\n }\n\n .settings-panel.hidden {\n transform: scale(0.4);\n opacity: 0;\n pointer-events: none;\n }\n\n .settings-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n }\n\n .settings-title {\n font-size: 16px;\n font-weight: 700;\n font-style: normal;\n color: #ffffff;\n }\n\n .settings-version {\n font-size: 12px;\n color: #6b6b80;\n font-weight: 500;\n }\n\n .settings-divider {\n height: 1px;\n background: rgba(255, 255, 255, 0.08);\n margin: 16px 0;\n }\n\n .settings-section {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .settings-label {\n font-size: 14px;\n font-weight: 500;\n color: #c0c0d0;\n }\n\n .settings-color-row {\n display: flex;\n gap: 8px;\n }\n\n .settings-swatch {\n width: 24px;\n height: 24px;\n border-radius: 4px;\n border: 2px solid transparent;\n cursor: pointer;\n transition: transform 0.15s, border-color 0.15s;\n outline: none;\n }\n\n .settings-swatch:hover {\n transform: scale(1.1);\n }\n\n .settings-swatch.selected {\n border-color: #ffffff;\n transform: scale(1.1);\n }\n\n .settings-check-row {\n display: flex;\n align-items: center;\n gap: 10px;\n cursor: pointer;\n padding: 2px 0;\n }\n\n .settings-checkbox {\n appearance: none;\n -webkit-appearance: none;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 2px solid #4a4a60;\n background: transparent;\n cursor: pointer;\n position: relative;\n flex-shrink: 0;\n transition: background 0.15s, border-color 0.15s;\n }\n\n .settings-checkbox:checked {\n background: #2563EB;\n border-color: #2563EB;\n }\n\n .settings-checkbox:checked::after {\n content: \'\';\n position: absolute;\n top: 2px;\n left: 5px;\n width: 5px;\n height: 9px;\n border: solid #ffffff;\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n }\n\n .settings-check-label {\n font-size: 14px;\n font-weight: 500;\n color: #e8e8f0;\n }\n\n /* ── Overlay ── */\n\n .refiner-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n cursor: crosshair;\n z-index: 1;\n }\n\n .refiner-overlay[data-blocking="true"] {\n pointer-events: all;\n }\n\n .refiner-overlay[data-blocking="false"] {\n pointer-events: none;\n }\n\n .refiner-overlay.hidden {\n display: none;\n }\n\n /* ── Highlight ── */\n\n .refiner-highlight {\n position: fixed;\n pointer-events: none;\n border: 2px dashed;\n border-radius: 3px;\n z-index: 2;\n transition: all 0.1s ease;\n }\n\n /* ── Dialog ── */\n\n .refiner-dialog {\n position: fixed;\n width: 320px;\n background: #1a1a2e;\n border: 1px solid rgba(255, 255, 255, 0.08);\n border-radius: 14px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 16px;\n z-index: 11;\n color: #e8e8f0;\n animation: dialog-in 0.2s ease;\n }\n\n @keyframes dialog-in {\n from { opacity: 0; transform: translateY(4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .refiner-dialog.hidden {\n display: none;\n }\n\n .dialog-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n }\n\n .dialog-header span {\n font-size: 12px;\n font-weight: 600;\n color: #c0c0d0;\n }\n\n .dialog-textarea {\n width: 100%;\n min-height: 72px;\n padding: 10px 12px;\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-radius: 10px;\n font-family: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: #e8e8f0;\n background: rgba(255, 255, 255, 0.06);\n resize: vertical;\n outline: none;\n transition: border-color 0.15s;\n }\n\n .dialog-textarea:focus {\n border-color: rgba(255, 255, 255, 0.25);\n }\n\n .dialog-textarea::placeholder {\n color: #6b6b80;\n }\n\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 12px;\n }\n\n .dialog-btn {\n height: 32px;\n padding: 0 14px;\n border-radius: 8px;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .dialog-btn-cancel {\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.12);\n color: #a0a0b8;\n }\n\n .dialog-btn-cancel:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #e8e8f0;\n }\n\n .dialog-btn-add {\n background: #2563EB;\n border: none;\n color: #ffffff;\n }\n\n .dialog-btn-add:hover {\n background: #3B82F6;\n }\n\n .dialog-btn-add:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n }\n\n /* ── Markers ── */\n\n .refiner-marker {\n position: fixed;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 700;\n color: #ffffff;\n cursor: pointer;\n z-index: 10;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n transition: transform 0.15s;\n pointer-events: all;\n }\n\n .refiner-marker:hover {\n transform: scale(1.2);\n }\n\n .refiner-marker[data-resolved="true"] {\n opacity: 0.4;\n }\n\n .marker-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n width: 220px;\n padding: 10px 12px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n line-height: 1.4;\n border-radius: 10px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .refiner-marker:hover .marker-tooltip {\n opacity: 1;\n }\n\n .marker-tooltip-actions {\n display: flex;\n gap: 6px;\n margin-top: 8px;\n border-top: 1px solid rgba(255,255,255,0.1);\n padding-top: 8px;\n }\n\n .marker-tooltip-btn {\n height: 22px;\n padding: 0 8px;\n border-radius: 5px;\n border: none;\n font-size: 10px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .marker-tooltip-btn.resolve {\n background: #34D399;\n color: #0a2e1f;\n }\n\n .marker-tooltip-btn.resolve:hover {\n background: #4ade80;\n }\n\n .marker-tooltip-btn.delete {\n background: rgba(255,255,255,0.1);\n color: #e8e8f0;\n }\n\n .marker-tooltip-btn.delete:hover {\n background: #FF6B6B;\n color: #fff;\n }\n\n /* MCP status */\n .settings-mcp-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n }\n\n .settings-mcp-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .settings-mcp-dot.connected {\n background: #34D399;\n box-shadow: 0 0 6px #34D39980;\n }\n\n .settings-mcp-dot.disconnected {\n background: #6B7280;\n }\n',this.shadow.appendChild(r),this.store=new e,this.toolbar=new n(this.shadow),this.settings=new a(this.shadow),this.overlay=new i(this.shadow),this.dialog=new s(this.shadow),this.markers=new o(this.shadow,this.store),this.toolbar.onCopy=()=>this.copyAnnotations(),this.toolbar.onClear=()=>this.clearAnnotations(),this.toolbar.onSettings=()=>{this.settings.toggle(),this.toolbar.setSettingsOpen(this.settings.isVisible())},this.toolbar.onCollapse=()=>{this.settings.hide(),this.toolbar.setSettingsOpen(!1),this.overlay.setEnabled(!1)},this.toolbar.onExpand=()=>{this.overlay.setEnabled(!0)},this.settings.onChange=t=>{this.clearOnCopy=t.clearOnCopy,this.overlay.setBlocking(t.blockInteractions),this.markers.setColor(t.markerColor),this.overlay.setHighlightColor(t.markerColor)},this.overlay.onClick=(t,e)=>{if(this.settings.isVisible())return void this.settings.hide();if(this.dialog.isVisible())return void this.dialog.hide();this.currentTarget=t,this.currentRect=e;const n=e.left+e.width/2,i=e.top+e.height/2;this.dialog.show(n,i)},this.dialog.onSubmit=t=>{if(this.currentTarget&&this.currentRect){const e=function(t){if(t.id)return`#${CSS.escape(t.id)}`;if(t.classList.length>0){const e=`${t.tagName.toLowerCase()}.${Array.from(t.classList).map(CSS.escape).join(".")}`;if(1===document.querySelectorAll(e).length)return e}const e=[];let n=t;for(;n&&n!==document.documentElement;){const t=n.tagName.toLowerCase(),i=n.parentElement;if(n.id){e.unshift(`#${CSS.escape(n.id)}`);break}if(i){const s=Array.from(i.children).filter(t=>t.tagName===n.tagName);if(1===s.length)e.unshift(t);else{const i=s.indexOf(n)+1;e.unshift(`${t}:nth-child(${i})`)}}else e.unshift(t);n=i}return e.join(" > ")}(this.currentTarget);this.store.add(e,this.currentRect,t),this.toolbar.updateCount(this.store.getCount())}this.currentTarget=null,this.currentRect=null},this.dialog.onCancel=()=>{this.currentTarget=null,this.currentRect=null},this.store.on("resolve",()=>this.toolbar.updateCount(this.store.getCount())),this.store.on("remove",()=>this.toolbar.updateCount(this.store.getCount())),!1!==t.mcpEnabled&&(this.mcpBridge=new l(this.store,t.mcpPort),this.mcpBridge.onChange=t=>{this.settings.setMcpStatus(t)}),document.body.appendChild(this.host),!1===t.enabled&&this.disable()}enable(){this.host.style.display="",this.overlay.setEnabled(!0)}disable(){this.host.style.display="none",this.overlay.setEnabled(!1)}destroy(){this.mcpBridge?.destroy(),this.host.remove()}getAnnotations(){return this.store.getAll()}getAnnotationCount(){return this.store.getCount()}formatForAgent(){const t=this.store.getAll();if(0===t.length)return"No annotations.";const e=document.title||window.location.pathname,n=window.location.pathname,i=[`# Design Annotations — ${e}`,`**File:** \`${n.substring(n.lastIndexOf("/")+1)||"index.html"}\``,""];for(let e=0;e<t.length;e++){const n=t[e],s=n.resolved?" (resolved)":"";i.push(`## ${e+1}.${s}`),i.push(`**Element:** \`${n.targetSelector}\``),i.push(`**Issue:** ${n.text}`),i.push("")}return i.join("\n")}clearAnnotations(){const t=this.store.getAll();for(const e of t)this.store.remove(e.id);this.toolbar.updateCount(0)}copyAnnotations(){const t=this.formatForAgent();navigator.clipboard.writeText(t),this.clearOnCopy&&this.clearAnnotations()}}if("undefined"!=typeof window&&"undefined"!=typeof document){const t=()=>{if(window.__refiner)return;const t=document.currentScript,e=t?.dataset.refinerPosition??"right",n="false"!==t?.dataset.refinerEnabled,i=t?.dataset.refinerMcpPort?parseInt(t.dataset.refinerMcpPort,10):void 0,s="false"!==t?.dataset.refinerMcpEnabled,o=new d({position:e,enabled:n,mcpPort:i,mcpEnabled:s});window.__refiner=o};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}return t.Refiner=d,t}({});
|
|
2
2
|
//# sourceMappingURL=refiner.js.map
|