@ericmhalvorsen/aperture 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.
@@ -0,0 +1,457 @@
1
+ var N=[],w=[];function V(){return N}function J(){return w}function Y(){let a=["log","warn","error","info","debug"];for(let e of a){let t=console[e];console[e]=(...r)=>{let i=r.map(o=>typeof o=="string"?o:JSON.stringify(o)).join(" ");N.push({level:e,message:i,timestamp:Date.now()}),N.length>500&&N.shift(),t(...r)}}}function K(){let a=window.fetch;window.fetch=async(...e)=>{let t={url:String(e[0]),method:"GET",start:Date.now(),end:0,status:0,responseText:""};e[1]&&(t.method=e[1].method||"GET");try{let r=await a(...e);return t.status=r.status,t.end=Date.now(),w.push(t),w.length>100&&w.shift(),r}catch(r){throw t.end=Date.now(),t.error=String(r),w.push(t),w.length>100&&w.shift(),r}}}var X={browser_dom_query:(a,{selector:e,includeHtml:t=!1})=>Array.from(document.querySelectorAll(String(e))).map(i=>({tag:i.tagName.toLowerCase(),text:i.textContent?.slice(0,200)||"",visible:!!i.offsetParent,attributes:Object.fromEntries(Array.from(i.attributes).map(o=>[o.name,o.value])),html:t?i.outerHTML.slice(0,500):void 0})),browser_network_requests:(a,{limit:e=20})=>J().slice(-Number(e)),browser_page_info:(a,{logLimit:e=20,logLevel:t="all"})=>{let r=V();return t!=="all"&&(r=r.filter(i=>i.level===t)),{url:window.location.href,title:document.title,width:window.innerWidth,height:window.innerHeight,scrollX:window.scrollX,scrollY:window.scrollY,userAgent:navigator.userAgent,logs:r.slice(-Number(e))}},browser_storage_get:(a,{type:e,key:t,prefix:r,name:i})=>{if(e==="localStorage"){let o={};if(t&&(o[String(t)]=localStorage.getItem(String(t))),r)for(let n=0;n<localStorage.length;n++){let l=localStorage.key(n);l?.startsWith(String(r))&&(o[l]=localStorage.getItem(l))}return o}if(e==="cookie"){let o={},n=document.cookie;if(n)for(let l of n.split(";")){let[s,p]=l.split("=").map(c=>c.trim());s&&(o[s]=decodeURIComponent(p||""))}if(i){let l=String(i);return{[l]:o[l]||null}}return o}return{error:`Unknown type: ${e}. Use 'localStorage' or 'cookie'.`}},browser_screenshot:async a=>{try{return{base64:(await a.captureScreenshotFromStream()).split(",")[1],format:"png"}}catch(e){return{error:e instanceof Error?e.message:String(e)}}},browser_evaluate:(a,{expression:e})=>{let t=window.eval(String(e));return{result:typeof t=="object"?JSON.stringify(t):String(t)}},browser_click:(a,{selector:e})=>{let t=document.querySelector(String(e));if(!t)return{error:`Element not found matching selector: ${e}`};t.focus();let r=["pointerdown","mousedown","pointerup","mouseup","click"];for(let i of r){let o=new MouseEvent(i,{bubbles:!0,cancelable:!0});t.dispatchEvent(o)}return{success:!0}},browser_type:(a,{selector:e,text:t})=>{let r=document.querySelector(String(e));if(!r)return{error:`Element not found matching selector: ${e}`};let i=r instanceof HTMLInputElement,o=r instanceof HTMLTextAreaElement;if(i||o){let n=i?HTMLInputElement.prototype:HTMLTextAreaElement.prototype,l=Object.getOwnPropertyDescriptor(n,"value")?.set;l?l.call(r,String(t)):r.value=String(t)}else if(r.isContentEditable)r.textContent=String(t);else return{error:"Element is not an input, textarea, or contenteditable."};return r.dispatchEvent(new Event("input",{bubbles:!0})),r.dispatchEvent(new Event("change",{bubbles:!0})),{success:!0}},browser_scroll:(a,{selector:e,x:t,y:r,scrollIntoView:i})=>{if(e){let o=document.querySelector(String(e));return o?i?(o.scrollIntoView({behavior:"smooth",block:"center",inline:"nearest"}),{success:!0}):(t!==void 0&&(o.scrollLeft=Number(t)),r!==void 0&&(o.scrollTop=Number(r)),{success:!0,scrollLeft:o.scrollLeft,scrollTop:o.scrollTop}):{error:`Element not found matching selector: ${e}`}}else{let o=t!==void 0?Number(t):window.scrollX,n=r!==void 0?Number(r):window.scrollY;return window.scrollTo({left:o,top:n,behavior:"smooth"}),{success:!0,scrollX:window.scrollX,scrollY:window.scrollY}}}};var u={get(a){if(typeof window>"u"||typeof localStorage>"u")return null;try{return localStorage.getItem(a)}catch{return null}},set(a,e){if(!(typeof window>"u"||typeof localStorage>"u"))try{localStorage.setItem(a,e)}catch{}},remove(a){if(!(typeof window>"u"||typeof localStorage>"u"))try{localStorage.removeItem(a)}catch{}}};var D=globalThis,Z=a=>a,P=D.trustedTypes,G=P?P.createPolicy("lit-html",{createHTML:a=>a}):void 0,ae="$lit$",v=`lit$${Math.random().toFixed(9).slice(2)}$`,oe="?"+v,ue=`<${oe}>`,_=D.document===void 0?{createTreeWalker:()=>({})}:document,k=()=>_.createComment(""),E=a=>a===null||typeof a!="object"&&typeof a!="function",j=Array.isArray,he=a=>j(a)||typeof a?.[Symbol.iterator]=="function",B=`[
2
+ \f\r]`,S=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Q=/-->/g,ee=/>/g,y=RegExp(`>|${B}(?:([^\\s"'>=/]+)(${B}*=${B}*(?:[^
3
+ \f\r"'\`<>=]|("|')|))|$)`,"g"),te=/'/g,re=/"/g,ne=/^(?:script|style|textarea|title)$/i,W=a=>(e,...t)=>({_$litType$:a,strings:e,values:t}),m=W(1),ye=W(2),xe=W(3),C=Symbol.for("lit-noChange"),h=Symbol.for("lit-nothing"),ie=new WeakMap,x=_.createTreeWalker(_,129);function se(a,e){if(!j(a)||!a.hasOwnProperty("raw"))throw Error("invalid template strings array");return G!==void 0?G.createHTML(e):e}var ge=(a,e)=>{let t=a.length-1,r=[],i,o=e===2?"<svg>":e===3?"<math>":"",n=S;for(let l=0;l<t;l++){let s=a[l],p,c,d=-1,f=0;for(;f<s.length&&(n.lastIndex=f,c=n.exec(s),c!==null);)f=n.lastIndex,n===S?c[1]==="!--"?n=Q:c[1]!==void 0?n=ee:c[2]!==void 0?(ne.test(c[2])&&(i=RegExp("</"+c[2],"g")),n=y):c[3]!==void 0&&(n=y):n===y?c[0]===">"?(n=i??S,d=-1):c[1]===void 0?d=-2:(d=n.lastIndex-c[2].length,p=c[1],n=c[3]===void 0?y:c[3]==='"'?re:te):n===re||n===te?n=y:n===Q||n===ee?n=S:(n=y,i=void 0);let b=n===y&&a[l+1].startsWith("/>")?" ":"";o+=n===S?s+ue:d>=0?(r.push(p),s.slice(0,d)+ae+s.slice(d)+v+b):s+v+(d===-2?l:b)}return[se(a,o+(a[t]||"<?>")+(e===2?"</svg>":e===3?"</math>":"")),r]},T=class a{constructor({strings:e,_$litType$:t},r){let i;this.parts=[];let o=0,n=0,l=e.length-1,s=this.parts,[p,c]=ge(e,t);if(this.el=a.createElement(p,r),x.currentNode=this.el.content,t===2||t===3){let d=this.el.content.firstChild;d.replaceWith(...d.childNodes)}for(;(i=x.nextNode())!==null&&s.length<l;){if(i.nodeType===1){if(i.hasAttributes())for(let d of i.getAttributeNames())if(d.endsWith(ae)){let f=c[n++],b=i.getAttribute(d).split(v),g=/([.?@])?(.*)/.exec(f);s.push({type:1,index:o,name:g[2],strings:b,ctor:g[1]==="."?I:g[1]==="?"?O:g[1]==="@"?U:$}),i.removeAttribute(d)}else d.startsWith(v)&&(s.push({type:6,index:o}),i.removeAttribute(d));if(ne.test(i.tagName)){let d=i.textContent.split(v),f=d.length-1;if(f>0){i.textContent=P?P.emptyScript:"";for(let b=0;b<f;b++)i.append(d[b],k()),x.nextNode(),s.push({type:2,index:++o});i.append(d[f],k())}}}else if(i.nodeType===8)if(i.data===oe)s.push({type:2,index:o});else{let d=-1;for(;(d=i.data.indexOf(v,d+1))!==-1;)s.push({type:7,index:o}),d+=v.length-1}o++}}static createElement(e,t){let r=_.createElement("template");return r.innerHTML=e,r}};function A(a,e,t=a,r){if(e===C)return e;let i=r!==void 0?t._$Co?.[r]:t._$Cl,o=E(e)?void 0:e._$litDirective$;return i?.constructor!==o&&(i?._$AO?.(!1),o===void 0?i=void 0:(i=new o(a),i._$AT(a,t,r)),r!==void 0?(t._$Co??=[])[r]=i:t._$Cl=i),i!==void 0&&(e=A(a,i._$AS(a,e.values),i,r)),e}var L=class{constructor(e,t){this._$AV=[],this._$AN=void 0,this._$AD=e,this._$AM=t}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(e){let{el:{content:t},parts:r}=this._$AD,i=(e?.creationScope??_).importNode(t,!0);x.currentNode=i;let o=x.nextNode(),n=0,l=0,s=r[0];for(;s!==void 0;){if(n===s.index){let p;s.type===2?p=new M(o,o.nextSibling,this,e):s.type===1?p=new s.ctor(o,s.name,s.strings,this,e):s.type===6&&(p=new q(o,this,e)),this._$AV.push(p),s=r[++l]}n!==s?.index&&(o=x.nextNode(),n++)}return x.currentNode=_,i}p(e){let t=0;for(let r of this._$AV)r!==void 0&&(r.strings!==void 0?(r._$AI(e,r,t),t+=r.strings.length-2):r._$AI(e[t])),t++}},M=class a{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(e,t,r,i){this.type=2,this._$AH=h,this._$AN=void 0,this._$AA=e,this._$AB=t,this._$AM=r,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let e=this._$AA.parentNode,t=this._$AM;return t!==void 0&&e?.nodeType===11&&(e=t.parentNode),e}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(e,t=this){e=A(this,e,t),E(e)?e===h||e==null||e===""?(this._$AH!==h&&this._$AR(),this._$AH=h):e!==this._$AH&&e!==C&&this._(e):e._$litType$!==void 0?this.$(e):e.nodeType!==void 0?this.T(e):he(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==h&&E(this._$AH)?this._$AA.nextSibling.data=e:this.T(_.createTextNode(e)),this._$AH=e}$(e){let{values:t,_$litType$:r}=e,i=typeof r=="number"?this._$AC(e):(r.el===void 0&&(r.el=T.createElement(se(r.h,r.h[0]),this.options)),r);if(this._$AH?._$AD===i)this._$AH.p(t);else{let o=new L(i,this),n=o.u(this.options);o.p(t),this.T(n),this._$AH=o}}_$AC(e){let t=ie.get(e.strings);return t===void 0&&ie.set(e.strings,t=new T(e)),t}k(e){j(this._$AH)||(this._$AH=[],this._$AR());let t=this._$AH,r,i=0;for(let o of e)i===t.length?t.push(r=new a(this.O(k()),this.O(k()),this,this.options)):r=t[i],r._$AI(o),i++;i<t.length&&(this._$AR(r&&r._$AB.nextSibling,i),t.length=i)}_$AR(e=this._$AA.nextSibling,t){for(this._$AP?.(!1,!0,t);e!==this._$AB;){let r=Z(e).nextSibling;Z(e).remove(),e=r}}setConnected(e){this._$AM===void 0&&(this._$Cv=e,this._$AP?.(e))}},$=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(e,t,r,i,o){this.type=1,this._$AH=h,this._$AN=void 0,this.element=e,this.name=t,this._$AM=i,this.options=o,r.length>2||r[0]!==""||r[1]!==""?(this._$AH=Array(r.length-1).fill(new String),this.strings=r):this._$AH=h}_$AI(e,t=this,r,i){let o=this.strings,n=!1;if(o===void 0)e=A(this,e,t,0),n=!E(e)||e!==this._$AH&&e!==C,n&&(this._$AH=e);else{let l=e,s,p;for(e=o[0],s=0;s<o.length-1;s++)p=A(this,l[r+s],t,s),p===C&&(p=this._$AH[s]),n||=!E(p)||p!==this._$AH[s],p===h?e=h:e!==h&&(e+=(p??"")+o[s+1]),this._$AH[s]=p}n&&!i&&this.j(e)}j(e){e===h?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,e??"")}},I=class extends ${constructor(){super(...arguments),this.type=3}j(e){this.element[this.name]=e===h?void 0:e}},O=class extends ${constructor(){super(...arguments),this.type=4}j(e){this.element.toggleAttribute(this.name,!!e&&e!==h)}},U=class extends ${constructor(e,t,r,i,o){super(e,t,r,i,o),this.type=5}_$AI(e,t=this){if((e=A(this,e,t,0)??h)===C)return;let r=this._$AH,i=e===h&&r!==h||e.capture!==r.capture||e.once!==r.once||e.passive!==r.passive,o=e!==h&&(r===h||i);i&&this.element.removeEventListener(this.name,this,r),o&&this.element.addEventListener(this.name,this,e),this._$AH=e}handleEvent(e){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,e):this._$AH.handleEvent(e)}},q=class{constructor(e,t,r){this.element=e,this.type=6,this._$AN=void 0,this._$AM=t,this.options=r}get _$AU(){return this._$AM._$AU}_$AI(e){A(this,e)}};var be=D.litHtmlPolyfillSupport;be?.(T,M),(D.litHtmlVersions??=[]).push("3.3.3");var z=(a,e,t)=>{let r=t?.renderBefore??e,i=r._$litPart$;if(i===void 0){let o=t?.renderBefore??null;r._$litPart$=i=new M(e.insertBefore(k(),o),o,void 0,t??{})}return i._$AI(a),i};function le(){if(typeof document>"u")return;let a="aperture-styles";if(document.getElementById(a))return;let e=document.createElement("style");e.id=a,e.textContent=`
4
+ :root {
5
+ --ap-bg: #0f0f10;
6
+ --ap-bg-glass: rgba(15, 15, 16, 0.92);
7
+ --ap-border: rgba(255, 255, 255, 0.10);
8
+ --ap-text: #f3f4f6;
9
+ --ap-text-secondary: #9ca3af;
10
+ --ap-text-muted: #6b7280;
11
+ --ap-accent: #6366f1;
12
+ --ap-accent-hover: #4f46e5;
13
+ --ap-btn-deny-bg: rgba(255, 255, 255, 0.06);
14
+ --ap-btn-deny-border: rgba(255, 255, 255, 0.12);
15
+ --ap-btn-deny-text: #d1d5db;
16
+ --ap-warning-bg: rgba(239, 68, 68, 0.10);
17
+ --ap-warning-border: rgba(239, 68, 68, 0.25);
18
+ --ap-warning-text: #fca5a5;
19
+ --ap-shadow: 0 24px 64px rgba(0, 0, 0, 0.50);
20
+ }
21
+
22
+ @media (prefers-color-scheme: light) {
23
+ :root {
24
+ --ap-bg: #ffffff;
25
+ --ap-bg-glass: rgba(255, 255, 255, 0.96);
26
+ --ap-border: rgba(0, 0, 0, 0.10);
27
+ --ap-text: #111827;
28
+ --ap-text-secondary: #4b5563;
29
+ --ap-text-muted: #9ca3af;
30
+ --ap-btn-deny-bg: rgba(0, 0, 0, 0.04);
31
+ --ap-btn-deny-border: rgba(0, 0, 0, 0.10);
32
+ --ap-btn-deny-text: #374151;
33
+ --ap-warning-bg: rgba(239, 68, 68, 0.06);
34
+ --ap-warning-border: rgba(239, 68, 68, 0.18);
35
+ --ap-warning-text: #b91c1c;
36
+ --ap-shadow: 0 24px 64px rgba(0, 0, 0, 0.15);
37
+ }
38
+ }
39
+
40
+ #aperture-badge,
41
+ #aperture-dialog-overlay,
42
+ #aperture-dialog,
43
+ #aperture-dialog .aperture-header,
44
+ #aperture-dialog .aperture-icon,
45
+ #aperture-dialog .aperture-title-container,
46
+ #aperture-dialog .aperture-title,
47
+ #aperture-dialog .aperture-subtitle,
48
+ #aperture-dialog .aperture-body,
49
+ #aperture-dialog .aperture-list,
50
+ #aperture-dialog .aperture-list li,
51
+ #aperture-dialog .aperture-options,
52
+ #aperture-dialog .aperture-checkbox-label,
53
+ #aperture-dialog .aperture-checkbox-label input,
54
+ #aperture-dialog .aperture-checkbox-desc,
55
+ #aperture-dialog .aperture-warning-box,
56
+ #aperture-dialog .aperture-footer,
57
+ #aperture-dialog .aperture-btn {
58
+ all: initial;
59
+ box-sizing: border-box;
60
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
61
+ }
62
+
63
+ #aperture-badge {
64
+ position: fixed;
65
+ bottom: 12px;
66
+ right: 12px;
67
+ z-index: 2147483646;
68
+ display: flex;
69
+ align-items: center;
70
+ gap: 8px;
71
+ padding: 6px 12px;
72
+ border-radius: 20px;
73
+ background: var(--ap-bg-glass);
74
+ backdrop-filter: blur(12px);
75
+ -webkit-backdrop-filter: blur(12px);
76
+ border: 1px solid var(--ap-border);
77
+ color: var(--ap-text);
78
+ font-size: 11px;
79
+ font-weight: 500;
80
+ box-shadow: var(--ap-shadow);
81
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
82
+ cursor: pointer;
83
+ user-select: none;
84
+ }
85
+
86
+ #aperture-badge:hover {
87
+ transform: translateY(-2px);
88
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.30);
89
+ }
90
+
91
+ #aperture-badge .dot {
92
+ width: 8px;
93
+ height: 8px;
94
+ border-radius: 50%;
95
+ transition: background-color 0.3s ease;
96
+ }
97
+
98
+ #aperture-badge .dot.connected {
99
+ background-color: #10b981;
100
+ box-shadow: 0 0 8px #10b981;
101
+ animation: aperture-pulse 2s infinite;
102
+ }
103
+
104
+ #aperture-badge .dot.connecting {
105
+ background-color: #f59e0b;
106
+ box-shadow: 0 0 8px #f59e0b;
107
+ }
108
+
109
+ #aperture-badge .dot.disconnected {
110
+ background-color: #ef4444;
111
+ box-shadow: 0 0 8px #ef4444;
112
+ }
113
+
114
+ @keyframes aperture-pulse {
115
+ 0% { transform: scale(1); opacity: 1; }
116
+ 50% { transform: scale(1.2); opacity: 0.7; }
117
+ 100% { transform: scale(1); opacity: 1; }
118
+ }
119
+
120
+ #aperture-dialog-overlay {
121
+ position: fixed;
122
+ inset: 0;
123
+ background: rgba(0, 0, 0, 0.45);
124
+ backdrop-filter: blur(6px);
125
+ -webkit-backdrop-filter: blur(6px);
126
+ z-index: 2147483647;
127
+ display: flex;
128
+ align-items: center;
129
+ justify-content: center;
130
+ opacity: 0;
131
+ transition: opacity 0.2s ease;
132
+ color-scheme: light dark;
133
+ }
134
+
135
+ #aperture-dialog {
136
+ background: var(--ap-bg-glass);
137
+ backdrop-filter: blur(20px);
138
+ -webkit-backdrop-filter: blur(20px);
139
+ border: 1px solid var(--ap-border);
140
+ border-radius: 16px;
141
+ width: 400px;
142
+ max-width: 92vw;
143
+ max-height: 90vh;
144
+ overflow-y: auto;
145
+ box-shadow: var(--ap-shadow);
146
+ padding: 24px;
147
+ color: var(--ap-text);
148
+ transform: scale(0.96);
149
+ transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
150
+ line-height: 1.5;
151
+ }
152
+
153
+ #aperture-dialog-overlay.active {
154
+ opacity: 1;
155
+ }
156
+
157
+ #aperture-dialog-overlay.active #aperture-dialog {
158
+ transform: scale(1);
159
+ }
160
+
161
+ #aperture-dialog .aperture-header {
162
+ display: flex;
163
+ align-items: center;
164
+ gap: 14px;
165
+ margin-bottom: 20px;
166
+ }
167
+
168
+ #aperture-dialog .aperture-icon {
169
+ width: 42px;
170
+ height: 42px;
171
+ border-radius: 12px;
172
+ background: linear-gradient(135deg, var(--ap-accent), var(--ap-accent-hover));
173
+ display: flex;
174
+ align-items: center;
175
+ justify-content: center;
176
+ font-size: 20px;
177
+ line-height: 1;
178
+ flex-shrink: 0;
179
+ }
180
+
181
+ #aperture-dialog .aperture-title-container {
182
+ display: flex;
183
+ flex-direction: column;
184
+ }
185
+
186
+ #aperture-dialog .aperture-title {
187
+ font-size: 16px;
188
+ font-weight: 600;
189
+ color: var(--ap-text);
190
+ margin: 0;
191
+ }
192
+
193
+ #aperture-dialog .aperture-subtitle {
194
+ font-size: 12px;
195
+ color: var(--ap-text-secondary);
196
+ margin: 2px 0 0 0;
197
+ }
198
+
199
+ #aperture-dialog .aperture-body {
200
+ display: block;
201
+ font-size: 13px;
202
+ color: var(--ap-text-secondary);
203
+ margin-bottom: 20px;
204
+ }
205
+
206
+ #aperture-dialog .aperture-list {
207
+ display: block;
208
+ margin: 12px 0 0 24px;
209
+ padding: 0;
210
+ color: var(--ap-text-secondary);
211
+ list-style-type: disc;
212
+ }
213
+
214
+ #aperture-dialog .aperture-list li {
215
+ display: list-item;
216
+ color: inherit;
217
+ margin-bottom: 6px;
218
+ font-size: 13px;
219
+ line-height: 1.4;
220
+ }
221
+
222
+ #aperture-dialog .aperture-options {
223
+ display: flex;
224
+ flex-direction: column;
225
+ gap: 14px;
226
+ margin-bottom: 20px;
227
+ border-top: 1px solid var(--ap-border);
228
+ border-bottom: 1px solid var(--ap-border);
229
+ padding: 16px 0;
230
+ }
231
+
232
+ #aperture-dialog .aperture-checkbox-label {
233
+ display: flex;
234
+ align-items: flex-start;
235
+ gap: 10px;
236
+ font-size: 13px;
237
+ color: var(--ap-text);
238
+ cursor: pointer;
239
+ user-select: none;
240
+ line-height: 1.4;
241
+ }
242
+
243
+ #aperture-dialog .aperture-checkbox-label input[type="checkbox"] {
244
+ margin-top: 2px;
245
+ width: 16px;
246
+ height: 16px;
247
+ accent-color: var(--ap-accent);
248
+ cursor: pointer;
249
+ flex-shrink: 0;
250
+ appearance: auto;
251
+ -webkit-appearance: checkbox;
252
+ }
253
+
254
+ #aperture-dialog .aperture-checkbox-desc {
255
+ font-size: 11px;
256
+ color: var(--ap-text-muted);
257
+ margin-top: 2px;
258
+ display: block;
259
+ line-height: 1.35;
260
+ }
261
+
262
+ #aperture-dialog .aperture-warning-box {
263
+ background: var(--ap-warning-bg);
264
+ border: 1px solid var(--ap-warning-border);
265
+ border-radius: 8px;
266
+ padding: 10px 12px;
267
+ margin-top: 6px;
268
+ margin-left: 26px;
269
+ font-size: 12px;
270
+ color: var(--ap-warning-text);
271
+ display: none;
272
+ line-height: 1.4;
273
+ }
274
+
275
+ #aperture-dialog .aperture-warning-box.visible {
276
+ display: block;
277
+ }
278
+
279
+ #aperture-dialog .aperture-footer {
280
+ display: flex;
281
+ gap: 10px;
282
+ justify-content: flex-end;
283
+ flex-wrap: wrap;
284
+ }
285
+
286
+ #aperture-dialog .aperture-btn {
287
+ display: inline-block;
288
+ padding: 8px 14px;
289
+ font-size: 13px;
290
+ font-weight: 500;
291
+ border-radius: 8px;
292
+ cursor: pointer;
293
+ transition: all 0.15s ease;
294
+ border: 1px solid transparent;
295
+ white-space: nowrap;
296
+ line-height: 1;
297
+ }
298
+
299
+ #aperture-dialog .aperture-btn-deny {
300
+ background: var(--ap-btn-deny-bg);
301
+ color: var(--ap-btn-deny-text);
302
+ border-color: var(--ap-btn-deny-border);
303
+ }
304
+
305
+ #aperture-dialog .aperture-btn-deny:hover {
306
+ background: var(--ap-btn-deny-text);
307
+ color: var(--ap-bg);
308
+ border-color: var(--ap-btn-deny-text);
309
+ }
310
+
311
+ #aperture-dialog .aperture-btn-allow {
312
+ background: linear-gradient(135deg, var(--ap-accent), var(--ap-accent-hover));
313
+ color: #fff;
314
+ border-color: transparent;
315
+ }
316
+
317
+ #aperture-dialog .aperture-btn-allow:hover {
318
+ transform: translateY(-1px);
319
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.35);
320
+ }
321
+ `,document.head.appendChild(e)}function de(a){let e=document.createElement("div");e.id="aperture-dialog-overlay",document.body.appendChild(e);let t=()=>{e.classList.remove("active"),setTimeout(()=>{e.remove()},300),document.removeEventListener("keydown",r)},r=n=>{n.key==="Escape"&&(t(),a?.())};document.addEventListener("keydown",r);let i=n=>{n.target===e&&(t(),a?.())};return e.addEventListener("click",i),{overlay:e,cleanup:t,activate:()=>{setTimeout(()=>{e.classList.add("active")},10)}}}async function F(){try{return await navigator.mediaDevices.getDisplayMedia({video:{displaySurface:"browser"},audio:!1})}catch(a){return console.warn("[Aperture] Failed to acquire screen share stream for screenshots:",a),null}}function pe(a,e){return new Promise(t=>{if(typeof document>"u"){t({approved:!1,capabilities:[]});return}let{overlay:r,cleanup:i,activate:o}=de(()=>{t({approved:!1,capabilities:[],dismissed:!0})}),n=!0,l=!0,s=!0,p=()=>{i(),t({approved:!1,capabilities:[],dismissed:!0})},c=()=>{i(),t({approved:!1,capabilities:[]})},d=async()=>{let b=s?864e5:36e5,g=["console","dom","network","storage"];if(l&&g.push("evaluate"),n){let H=await F();H&&(e({stream:H}),g.push("screenshot"))}i(),t({approved:!0,capabilities:g,ttlMs:b})};(()=>{let b=m`
322
+ <div id="aperture-dialog">
323
+ <div class="aperture-header">
324
+ <div class="aperture-icon">🔌</div>
325
+ <div class="aperture-title-container">
326
+ <h3 class="aperture-title">Agent Bridge</h3>
327
+ <p class="aperture-subtitle">${a} wants to access this tab</p>
328
+ </div>
329
+ </div>
330
+
331
+ <div class="aperture-body">
332
+ By allowing, the agent will be able to:
333
+ <ul class="aperture-list">
334
+ <li>Read the current page URL, title, and visible text</li>
335
+ <li>Query the DOM and read element attributes / contents</li>
336
+ <li>View console logs (errors, warnings, info, debug)</li>
337
+ <li>Monitor network requests made by this page</li>
338
+ <li>Read localStorage and cookies for this origin</li>
339
+ ${n?m`<li id="aperture-perm-screenshot">Capture screenshots of the page</li>`:""}
340
+ ${l?m`<li id="aperture-perm-eval">Execute arbitrary JavaScript in this page</li>`:""}
341
+ </ul>
342
+ </div>
343
+
344
+ <div class="aperture-options">
345
+ <label class="aperture-checkbox-label">
346
+ <input
347
+ type="checkbox"
348
+ id="aperture-allow-screenshot"
349
+ .checked=${n}
350
+ @change=${g=>{n=g.target.checked}}
351
+ />
352
+ <div>
353
+ <strong>Allow screenshot capture</strong>
354
+ <div class="aperture-checkbox-desc">Requests browser tab/screen sharing for live views</div>
355
+ </div>
356
+ </label>
357
+
358
+ <label class="aperture-checkbox-label">
359
+ <input
360
+ type="checkbox"
361
+ id="aperture-allow-eval"
362
+ .checked=${l}
363
+ @change=${g=>{l=g.target.checked}}
364
+ />
365
+ <div>
366
+ <strong>Allow JavaScript evaluation</strong>
367
+ <div class="aperture-checkbox-desc">Enables arbitrary JS execution in this page (dangerous)</div>
368
+ </div>
369
+ </label>
370
+
371
+ <label class="aperture-checkbox-label">
372
+ <input
373
+ type="checkbox"
374
+ id="aperture-remember-24h"
375
+ .checked=${s}
376
+ @change=${g=>{s=g.target.checked}}
377
+ />
378
+ <div>
379
+ <strong>Trust this device for 24 hours</strong>
380
+ <div class="aperture-checkbox-desc">Otherwise approval resets after 1 hour</div>
381
+ </div>
382
+ </label>
383
+
384
+ <div id="aperture-eval-warning" class="aperture-warning-box ${l?"visible":""}">
385
+ ⚠️ Warning: Allowing evaluation lets the agent run any command or access any sensitive data on this origin.
386
+ </div>
387
+ </div>
388
+
389
+ <div class="aperture-footer">
390
+ <button id="aperture-btn-dismiss" class="aperture-btn aperture-btn-deny" @click=${p}>Dismiss</button>
391
+ <button id="aperture-btn-deny" class="aperture-btn aperture-btn-deny" @click=${c}>Deny</button>
392
+ <button id="aperture-btn-allow" class="aperture-btn aperture-btn-allow" @click=${d}>Allow for this session</button>
393
+ </div>
394
+ </div>
395
+ `;z(b,r)})(),o()})}function ce(a){if(typeof document>"u"||document.getElementById("aperture-dialog-overlay"))return;let{overlay:e,cleanup:t}=de(),i=navigator.platform.toLowerCase().includes("mac")?"Cmd+Shift+A":"Ctrl+Shift+A",o=()=>t(),n=()=>{a.revokeApproval(),a.onApprovalStateChange({approved:!1,capabilities:[],stream:null}),t()},l=()=>{a.isBadgeHidden()?a.showBadge():a.hideBadgeFor24h(),t()};(()=>{let p=a.wsReadyState===WebSocket.OPEN?"Connected":"Disconnected",c=a.denied?"Denied":a.approved?"Approved":"Pending Approval",d=a.capabilities.includes("screenshot"),f=a.capabilities.includes("evaluate"),g=a.isBadgeHidden()?"Show badge":"Hide badge for 24 hours",H=m`
396
+ <div id="aperture-dialog">
397
+ <div class="aperture-header">
398
+ <div class="aperture-icon">⚙️</div>
399
+ <div class="aperture-title-container">
400
+ <h3 class="aperture-title">Agent Bridge</h3>
401
+ <p class="aperture-subtitle">${a.approved?"Session active":"Waiting for approval"}</p>
402
+ </div>
403
+ </div>
404
+
405
+ <div class="aperture-body">
406
+ <div style="margin-bottom: 12px; display: flex; justify-content: space-between; font-size: 13px;">
407
+ <span>Connection:</span>
408
+ <strong style="color: ${p==="Connected"?"#10b981":"#ef4444"};">${p}</strong>
409
+ </div>
410
+ <div style="margin-bottom: 12px; display: flex; justify-content: space-between; font-size: 13px;">
411
+ <span>Status:</span>
412
+ <strong style="color: ${c==="Approved"?"#10b981":c==="Denied"?"#ef4444":"#f59e0b"};">${c}</strong>
413
+ </div>
414
+
415
+ ${a.approved?m`
416
+ <div style="margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--ap-border);">
417
+ <div style="font-size: 12px; color: var(--ap-text-muted); margin-bottom: 8px;">Enabled capabilities:</div>
418
+ <ul style="font-size: 13px; margin: 0; padding-left: 20px; color: var(--ap-text);">
419
+ <li>Console logs</li>
420
+ <li>DOM queries</li>
421
+ <li>Network requests</li>
422
+ <li>Storage access</li>
423
+ ${d?m`<li>Screenshots</li>`:""}
424
+ ${f?m`<li>JavaScript evaluation</li>`:""}
425
+ </ul>
426
+ </div>
427
+ `:""}
428
+ </div>
429
+
430
+ <div class="aperture-footer">
431
+ ${a.approved?m`
432
+ <button id="aperture-status-btn-revoke" class="aperture-btn aperture-btn-deny" @click=${n}>Revoke</button>
433
+ <button id="aperture-status-btn-close" class="aperture-btn aperture-btn-allow" @click=${o}>Close</button>
434
+ `:m`
435
+ <div style="width: 100%; text-align: center; color: var(--ap-text-muted); font-size: 13px;">
436
+ Waiting for agent connection...
437
+ </div>
438
+ `}
439
+ </div>
440
+
441
+ <div style="margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--ap-border); text-align: center;">
442
+ <button id="aperture-status-btn-hide" class="aperture-btn aperture-btn-deny" style="width: 100%;" @click=${l}>${g}</button>
443
+ <div style="margin-top: 8px; font-size: 11px; color: var(--ap-text-muted);">
444
+ Re-open with <kbd style="font-family: monospace; background: var(--ap-btn-deny-bg); border: 1px solid var(--ap-btn-deny-border); border-radius: 4px; padding: 1px 4px; font-size: 10px;">${i}</kbd>
445
+ </div>
446
+ </div>
447
+ </div>
448
+ `;z(H,e)})(),setTimeout(()=>{e.classList.add("active")},10)}var R=class{ws=null;config;approved=!1;denied=!1;capabilities=[];screenCaptureStream=null;badgeElement=null;focusListenersAdded=!1;constructor(e){this.config=e,window.__apertureInstance__=this,le(),Y(),K(),this.loadCachedApproval(),this.registerKeyboardShortcut(),typeof window<"u"&&window.addEventListener("beforeunload",()=>{this.stopScreenCapture()})}registerKeyboardShortcut(){typeof document>"u"||document.addEventListener("keydown",e=>{(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey)&&e.shiftKey&&(e.key==="a"||e.key==="A")&&(e.preventDefault(),this.openStatusDialog())})}isBadgeHidden(){let e=u.get("aperture_badge_hidden_until");return e?Date.now()<Number(e):!1}hideBadgeFor24h(){let e=String(Date.now()+864e5);u.set("aperture_badge_hidden_until",e),this.badgeElement&&(this.badgeElement.remove(),this.badgeElement=null)}showBadge(){if(u.remove("aperture_badge_hidden_until"),this.ws){let e=this.ws.readyState===WebSocket.OPEN?"connected":"connecting";this.updateBadge(e)}}loadCachedApproval(){let e=u.get("aperture_approved"),t=u.get("aperture_approved_at"),r=u.get("aperture_ttl_ms"),i=3600*1e3,o=r?Number(r):i,n=t?Date.now()-Number(t)>o:!0;e==="true"&&!n?(this.approved=!0,this.denied=!1,this.capabilities=JSON.parse(u.get("aperture_capabilities")||"[]")):e==="false"&&(this.denied=!0,this.approved=!1),n&&(u.remove("aperture_approved"),u.remove("aperture_approved_at"),u.remove("aperture_capabilities"),u.remove("aperture_ttl_ms"))}saveApproval(e,t,r){e?(u.set("aperture_approved","true"),u.set("aperture_approved_at",String(Date.now())),u.set("aperture_capabilities",JSON.stringify(t)),r&&u.set("aperture_ttl_ms",String(r))):(u.set("aperture_approved","false"),u.remove("aperture_approved_at"),u.remove("aperture_capabilities"),u.remove("aperture_ttl_ms"))}revokeApproval(){u.remove("aperture_approved"),u.remove("aperture_approved_at"),u.remove("aperture_capabilities"),u.remove("aperture_ttl_ms"),this.approved=!1,this.denied=!1,this.capabilities=[]}connect(){let e=new URL("/mcp",this.config.serverUrl);e.searchParams.set("type","browser"),this.updateBadge("connecting"),this.ws=new WebSocket(e.toString()),this.ws.onopen=()=>{let t=this.config.customTools?Object.entries(this.config.customTools).map(([r,i])=>({name:r,description:i.description,inputSchema:i.inputSchema})):[];this.send({type:"register",url:window.location.href,title:document.title,customTools:t}),console.log("[Aperture] Connected to server"),this.updateBadge("connected"),this.approved&&this.send({type:"approval",approved:this.approved,capabilities:this.capabilities}),this.reportFocusState(),typeof window<"u"&&!this.focusListenersAdded&&(this.focusListenersAdded=!0,window.addEventListener("focus",()=>this.reportFocusState()),window.addEventListener("blur",()=>this.reportFocusState()))},this.ws.onmessage=async t=>{try{let r=JSON.parse(t.data);r.type==="tool_call"?await this.handleToolCall(r):r.type==="agent_connected"&&await this.getOrWaitApproval()}catch{}},this.ws.onclose=()=>{console.log("[Aperture] Disconnected. Retrying in 3s..."),this.updateBadge("disconnected"),this.stopScreenCapture(),setTimeout(()=>this.connect(),3e3)}}disconnect(){this.ws&&(this.ws.onclose=null,this.ws.close(),this.ws=null),this.stopScreenCapture(),this.badgeElement&&(this.badgeElement.remove(),this.badgeElement=null)}reportFocusState(){if(typeof document>"u")return;let e=document.hasFocus();this.send({type:"focus",focused:e})}send(e){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(e))}updateBadge(e){if(typeof document>"u")return;if(this.isBadgeHidden()){this.badgeElement&&(this.badgeElement.remove(),this.badgeElement=null);return}if(!this.badgeElement){this.badgeElement=document.createElement("div"),this.badgeElement.id="aperture-badge",this.badgeElement.title="Manage Aperture session (Ctrl+Shift+A)";let r=document.createElement("span");r.className="dot",this.badgeElement.appendChild(r),this.badgeElement.addEventListener("click",()=>{this.openStatusDialog()}),document.body.appendChild(this.badgeElement)}let t=this.badgeElement.querySelector(".dot");t&&(t.className=`dot ${e}`)}async handleToolCall(e){if(this.denied){this.send({type:"result",requestId:e.requestId,result:{error:"User denied browser access"}});return}if(!this.approved&&(await this.getOrWaitApproval(),!this.approved)){this.send({type:"result",requestId:e.requestId,result:{error:this.denied?"User denied browser access":"User dismissed the approval request"}});return}let t=X[e.tool],r=this.config.customTools?.[e.tool]?.handler,i=t||r;if(!i){this.send({type:"result",requestId:e.requestId,result:{error:`Unknown tool: ${e.tool}`}});return}try{let o=await i(this,e.args);this.send({type:"result",requestId:e.requestId,result:o})}catch(o){this.send({type:"result",requestId:e.requestId,result:{error:o instanceof Error?o.message:String(o)}})}}approvalPendingPromise=null;getOrWaitApproval(){return this.approved||this.denied?Promise.resolve():this.approvalPendingPromise?this.approvalPendingPromise:(this.approvalPendingPromise=(async()=>{let e=await this.getApproval("MCP Agent");e.dismissed||(this.approved=e.approved,this.denied=!e.approved,this.capabilities=e.capabilities,this.saveApproval(this.approved,this.capabilities,e.ttlMs),this.send({type:"approval",approved:this.approved,capabilities:this.capabilities}))})(),this.approvalPendingPromise.finally(()=>{this.approvalPendingPromise=null}),this.approvalPendingPromise)}async getApproval(e){return this.config.onApprovalRequest?{...await this.config.onApprovalRequest(e),dismissed:!1}:pe(e,t=>{t.stream!==void 0&&(this.screenCaptureStream=t.stream)})}async captureScreenshotFromStream(){if(!this.screenCaptureStream?.active){if(!this.approved||!this.capabilities.includes("screenshot"))throw new Error("Screenshot access was not granted. Please approve the connection with screenshot capability enabled.");let n=await this.requestScreenCapture();if(!n)throw new Error("Failed to acquire screen capture. Please try again or re-approve the connection.");this.screenCaptureStream=n}if(!this.screenCaptureStream.getVideoTracks()[0])throw new Error("No video tracks found in screen capture stream.");let t=document.createElement("video");t.srcObject=this.screenCaptureStream,t.autoplay=!0,t.playsInline=!0,t.muted=!0,await new Promise(n=>{t.onloadedmetadata=()=>n(null)}),await t.play().catch(()=>null),await new Promise(n=>{typeof t.requestVideoFrameCallback=="function"?(t.requestVideoFrameCallback(()=>n()),setTimeout(()=>n(),1e3)):setTimeout(()=>n(),300)});let r=document.createElement("canvas");r.width=t.videoWidth||800,r.height=t.videoHeight||600;let i=r.getContext("2d");if(!i)throw new Error("Could not get 2D context from canvas");i.drawImage(t,0,0);let o=r.toDataURL("image/png");return t.srcObject=null,t.load(),o}stopScreenCapture(){if(this.screenCaptureStream){for(let e of this.screenCaptureStream.getTracks())e.stop();this.screenCaptureStream=null}}setMediaStream(e){this.screenCaptureStream=e}async requestScreenCapture(){return F()}openStatusDialog(){ce({wsReadyState:this.ws?.readyState??WebSocket.CLOSED,approved:this.approved,denied:this.denied,capabilities:this.capabilities,isBadgeHidden:()=>this.isBadgeHidden(),showBadge:()=>this.showBadge(),hideBadgeFor24h:()=>this.hideBadgeFor24h(),revokeApproval:()=>this.revokeApproval(),onApprovalStateChange:e=>{this.approved=e.approved,e.approved?this.denied=!1:this.denied=!0,this.capabilities=e.capabilities,e.stream!==void 0&&(e.stream===null?this.stopScreenCapture():this.screenCaptureStream=e.stream),this.saveApproval(this.approved,this.capabilities),this.send({type:"approval",approved:this.approved,capabilities:this.capabilities})}})}};function Te(a){if(typeof window>"u"||!(location.hostname==="localhost"||location.hostname==="127.0.0.1"||location.hostname.endsWith(".localhost")||!!window.__vite_inject__))return;let t=a?.port||window.__APERTURE_PORT__||3456,r=a?.serverUrl||`ws://localhost:${t}`,i=window.__apertureInstance__;i&&typeof i.disconnect=="function"&&i.disconnect();let o=new R({serverUrl:r,customTools:a?.customTools});return o.connect(),window.__apertureInstance__=o,o}typeof window<"u"&&(location.hostname==="localhost"||location.hostname==="127.0.0.1"||location.hostname.endsWith(".localhost")||window.__vite_inject__)&&setTimeout(()=>{if(!window.__apertureInstance__){let e=window.__APERTURE_PORT__||3456,t=window.__APERTURE_URL__||`ws://localhost:${e}`;console.log("[Aperture] No manual initialization detected. Auto-connecting...");let r=new R({serverUrl:t});r.connect(),window.__apertureInstance__=r}},500);export{R as ApertureClient,Te as initAperture};
449
+ /*! Bundled license information:
450
+
451
+ lit-html/node/lit-html.js:
452
+ (**
453
+ * @license
454
+ * Copyright 2017 Google LLC
455
+ * SPDX-License-Identifier: BSD-3-Clause
456
+ *)
457
+ */
package/package.json ADDED
@@ -0,0 +1,123 @@
1
+ {
2
+ "name": "@ericmhalvorsen/aperture",
3
+ "version": "0.2.1",
4
+ "description": "Browser-to-agent bridge for AI agents. Auto-connects your dev browser to any MCP-capable agent.",
5
+ "license": "MIT",
6
+ "author": "Eric M. Halvorsen",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/ericmhalvorsen/aperture.git"
10
+ },
11
+ "homepage": "https://github.com/ericmhalvorsen/aperture#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/ericmhalvorsen/aperture/issues"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "browser",
18
+ "ai",
19
+ "agent",
20
+ "devtools",
21
+ "debugging",
22
+ "claude",
23
+ "cursor",
24
+ "opencode"
25
+ ],
26
+ "engines": {
27
+ "node": ">=18"
28
+ },
29
+ "type": "module",
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.js"
36
+ },
37
+ "./react": {
38
+ "types": "./dist/react.d.ts",
39
+ "default": "./dist/react.js"
40
+ },
41
+ "./client": {
42
+ "types": "./dist/client.d.ts",
43
+ "default": "./dist/client.js"
44
+ },
45
+ "./server": {
46
+ "types": "./dist/server.d.ts",
47
+ "default": "./dist/server.js"
48
+ },
49
+ "./register": {
50
+ "types": "./dist/register.d.ts",
51
+ "default": "./dist/register.js"
52
+ },
53
+ "./next": {
54
+ "types": "./dist/frameworks/next.d.ts",
55
+ "default": "./dist/frameworks/next.js"
56
+ },
57
+ "./vite": {
58
+ "types": "./dist/frameworks/vite.d.ts",
59
+ "default": "./dist/frameworks/vite.js"
60
+ }
61
+ },
62
+ "bin": {
63
+ "aperture": "./dist/bin.js"
64
+ },
65
+ "scripts": {
66
+ "build": "tsc -p tsconfig.build.json && pnpm exec tsup --config tsup.browser.ts",
67
+ "dev": "tsc -p tsconfig.build.json --watch",
68
+ "typecheck": "tsc --noEmit",
69
+ "lint": "biome lint .",
70
+ "format": "biome format --write .",
71
+ "check": "biome check .",
72
+ "knip": "knip",
73
+ "audit:deps": "pnpm audit",
74
+ "test": "vitest run",
75
+ "test:e2e": "playwright test",
76
+ "test:watch": "vitest",
77
+ "test:coverage": "vitest run --coverage",
78
+ "changeset": "changeset",
79
+ "version-packages": "changeset version",
80
+ "release": "pnpm build && changeset publish",
81
+ "publint": "publint",
82
+ "example": "cd samples/next-aperture && pnpm run dev"
83
+ },
84
+ "dependencies": {
85
+ "@modelcontextprotocol/sdk": "^1.29.0",
86
+ "lit-html": "^3.3.3",
87
+ "picocolors": "^1.1.1",
88
+ "ws": "^8"
89
+ },
90
+ "devDependencies": {
91
+ "@biomejs/biome": "^2.4.16",
92
+ "@changesets/cli": "^2.31.0",
93
+ "@playwright/test": "^1.60.0",
94
+ "@types/node": "^20",
95
+ "@types/react": "^19",
96
+ "@types/ws": "^8",
97
+ "@vitest/coverage-v8": "^4.1.7",
98
+ "jsdom": "^29.1.1",
99
+ "knip": "^6.14.2",
100
+ "publint": "^0.3.21",
101
+ "tsup": "^8.5.1",
102
+ "typescript": "^5",
103
+ "vitest": "^4.1.7"
104
+ },
105
+ "peerDependencies": {
106
+ "react": ">=18",
107
+ "react-dom": ">=18"
108
+ },
109
+ "peerDependenciesMeta": {
110
+ "react": { "optional": true },
111
+ "react-dom": { "optional": true }
112
+ },
113
+ "files": [
114
+ "dist",
115
+ "dist-browser",
116
+ "README.md"
117
+ ],
118
+ "pnpm": {
119
+ "overrides": {
120
+ "postcss": "^8.5.10"
121
+ }
122
+ }
123
+ }