@nicmeriano/spool-inject 0.0.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.
Files changed (2) hide show
  1. package/dist/inject.js +21 -0
  2. package/package.json +37 -0
package/dist/inject.js ADDED
@@ -0,0 +1,21 @@
1
+ (function(){"use strict";const T="__spool-hover-overlay__",C="__spool-select-overlay__",M="__spool-select-label__",l={hoverOverlay:null,selectOverlay:null,hoveredElement:null,selectedElement:null,isHiddenForScroll:!1};function N(t,e,n){const o=document.createElement("div");return o.id=t,o.style.cssText=`
2
+ position: fixed;
3
+ pointer-events: none;
4
+ z-index: 2147483646;
5
+ border: ${n} solid ${e};
6
+ background-color: ${e}20;
7
+ display: none;
8
+ `,document.body.appendChild(o),o}function B(t){const e=t.tagName.toLowerCase();if(t.id)return`${e}#${t.id}`;const n=Array.from(t.classList).slice(0,2).join(".");return n?`${e}.${n}`:e}function Y(){I(),l.hoverOverlay=N(T,"#3b82f6","2px"),l.selectOverlay=N(C,"#3b82f6","1px");const t=document.createElement("div");t.id=M,t.style.cssText=`
9
+ position: absolute;
10
+ top: -20px;
11
+ left: -1px;
12
+ padding: 1px 6px;
13
+ background: #3b82f6;
14
+ color: #fff;
15
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
16
+ font-size: 10px;
17
+ line-height: 16px;
18
+ white-space: nowrap;
19
+ border-radius: 3px 3px 0 0;
20
+ pointer-events: none;
21
+ `,l.selectOverlay.appendChild(t)}function I(){var t,e,n,o;(t=l.hoverOverlay)==null||t.remove(),(e=l.selectOverlay)==null||e.remove(),l.hoverOverlay=null,l.selectOverlay=null,(n=document.getElementById(T))==null||n.remove(),(o=document.getElementById(C))==null||o.remove()}function R(t){if(!l.hoverOverlay)return;if(l.hoveredElement=t,!t||l.isHiddenForScroll){l.hoverOverlay.style.display="none";return}const e=t.getBoundingClientRect();l.hoverOverlay.style.display="block",l.hoverOverlay.style.top=`${e.top}px`,l.hoverOverlay.style.left=`${e.left}px`,l.hoverOverlay.style.width=`${e.width}px`,l.hoverOverlay.style.height=`${e.height}px`}function g(){l.hoverOverlay&&(l.hoverOverlay.style.display="none")}function w(t,e){if(!l.selectOverlay)return;if(l.selectedElement=t,!t||l.isHiddenForScroll){l.selectOverlay.style.display="none";return}g();const n=t.getBoundingClientRect();l.selectOverlay.style.display="block",l.selectOverlay.style.top=`${n.top}px`,l.selectOverlay.style.left=`${n.left}px`,l.selectOverlay.style.width=`${n.width}px`,l.selectOverlay.style.height=`${n.height}px`;const o=l.selectOverlay.querySelector(`#${M}`);o&&(o.textContent=B(t))}function G(){l.selectOverlay&&(l.selectOverlay.style.display="none")}function W(t){const e=document.querySelector(t);w(e)}function z(){g(),G()}function U(){l.isHiddenForScroll=!0,l.hoverOverlay&&(l.hoverOverlay.style.display="none"),l.selectOverlay&&(l.selectOverlay.style.display="none")}function K(){l.isHiddenForScroll=!1,l.hoveredElement&&R(l.hoveredElement),l.selectedElement&&w(l.selectedElement)}function X(t){if(t.id)return`#${CSS.escape(t.id)}`;const e=[];let n=t;for(;n&&n!==document.body&&n!==document.documentElement;){let o=n.tagName.toLowerCase();if(n.id){o=`#${CSS.escape(n.id)}`,e.unshift(o);break}if(n.classList.length>0){const i=Array.from(n.classList).slice(0,2).map(s=>`.${CSS.escape(s)}`).join("");o+=i}const r=n.parentElement;if(r){const i=Array.from(r.children).filter(s=>s.tagName===n.tagName);if(i.length>1){const s=i.indexOf(n)+1;o+=`:nth-of-type(${s})`}}e.unshift(o),n=n.parentElement}return e.join(" > ")}function Z(t){const e=[];let n=t;for(;n&&n.nodeType===Node.ELEMENT_NODE;){let o=1,r=n.previousElementSibling;for(;r;)r.tagName===n.tagName&&o++,r=r.previousElementSibling;const i=n.tagName.toLowerCase(),s=o>1?`${i}[${o}]`:i;e.unshift(s),n=n.parentElement}return"/"+e.join("/")}function J(t){const e=Object.keys(t).find(o=>o.startsWith("__reactFiber$"));if(!e)return{};let n=t[e];for(;n;){if(typeof n.type=="function"){const o=n.type.displayName||n.type.name,r=n._debugSource;return{name:o||void 0,file:r==null?void 0:r.fileName,lineNumber:r==null?void 0:r.lineNumber}}n=n.return}return{}}function $(t){const e=window.getComputedStyle(t);return{backgroundColor:e.backgroundColor,color:e.color,padding:e.padding,paddingTop:e.paddingTop,paddingRight:e.paddingRight,paddingBottom:e.paddingBottom,paddingLeft:e.paddingLeft,margin:e.margin,marginTop:e.marginTop,marginRight:e.marginRight,marginBottom:e.marginBottom,marginLeft:e.marginLeft,borderWidth:e.borderWidth,borderColor:e.borderColor,borderRadius:e.borderRadius,borderStyle:e.borderStyle,fontSize:e.fontSize,fontWeight:e.fontWeight,fontFamily:e.fontFamily,lineHeight:e.lineHeight,width:e.width,height:e.height}}function Q(t){const e=t,n={};if(e.style)for(let o=0;o<e.style.length;o++){const r=e.style[o];n[r]=e.style.getPropertyValue(r)}return n}function k(t){var o;const e=t.getBoundingClientRect(),n=J(t);return{selector:X(t),xpath:Z(t),tagName:t.tagName.toLowerCase(),id:t.id||void 0,className:t.className||void 0,textContent:((o=t.textContent)==null?void 0:o.trim().slice(0,100))||void 0,rect:{top:e.top,left:e.left,width:e.width,height:e.height},computedStyles:$(t),inlineStyles:Q(t),reactComponent:n.name?{name:n.name,file:n.file,lineNumber:n.lineNumber}:void 0}}function x(t){var n,o;if((n=t.id)!=null&&n.startsWith("__spool-"))return!0;let e=t;for(;e;){if((o=e.id)!=null&&o.startsWith("__spool-"))return!0;e=e.parentElement}return!1}const a={enabled:!1,hoveredElement:null,selectedElement:null};let u=null;function ee(t){u=t}function P(t){if(!a.enabled)return;const e=t.target;if(!x(e)&&e!==a.hoveredElement&&(a.hoveredElement=e,R(e),u)){const n=k(e);u("ELEMENT_HOVERED",n)}}function H(){a.enabled&&(a.hoveredElement=null,g(),u&&u("ELEMENT_HOVERED",null))}function A(t){if(!a.enabled)return;const e=t.target;if(!x(e)&&(t.preventDefault(),t.stopPropagation(),a.selectedElement=e,w(e),u)){const n=k(e),o=e.getBoundingClientRect(),r={x:t.clientX-o.left,y:t.clientY-o.top};u("ELEMENT_SELECTED",{...n,clickOffset:r})}}function te(){a.enabled||(a.enabled=!0,document.addEventListener("mousemove",P,!0),document.addEventListener("mouseleave",H,!0),document.addEventListener("click",A,!0),document.body.style.cursor="crosshair")}function ne(){a.enabled&&(a.enabled=!1,a.hoveredElement=null,document.removeEventListener("mousemove",P,!0),document.removeEventListener("mouseleave",H,!0),document.removeEventListener("click",A,!0),document.body.style.cursor="",g())}function oe(t){t?te():ne()}const y=new Map,v=new Map,E=new Map;function m(t){return t.replace(/([A-Z])/g,"-$1").toLowerCase()}function re(t,e){const n=new Map;for(const o of e){const r=m(o),i=t.style.getPropertyValue(r);n.set(o,i)}return n}function le(t,e){const n=document.querySelector(t);if(!n)return console.warn(`[spool-inject] Element not found: ${t}`),!1;if(y.has(t)){const r=y.get(t);for(const i of Object.keys(e))if(!r.has(i)){const s=m(i);r.set(i,n.style.getPropertyValue(s))}}else{const r=Object.keys(e);y.set(t,re(n,r))}for(const[r,i]of Object.entries(e))i!==void 0&&i!==""&&n.style.setProperty(m(r),i);const o=v.get(t)||{};if(v.set(t,{...o,...e}),!E.has(t)){const r=new MutationObserver(()=>{const s=v.get(t);if(s){const p=document.querySelector(t);if(p)for(const[me,_]of Object.entries(s))_!==void 0&&_!==""&&p.style.setProperty(m(me),_)}}),i=n.parentElement;i&&(r.observe(i,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["style","class"]}),E.set(t,r))}return!0}function D(t){const e=document.querySelector(t),n=y.get(t),o=E.get(t);if(o&&(o.disconnect(),E.delete(t)),e&&n)for(const[r,i]of n){const s=m(r);i===""?e.style.removeProperty(s):e.style.setProperty(s,i)}y.delete(t),v.delete(t)}function ie(){for(const t of v.keys())D(t)}const O="data-variant-preview-id",h=new Map,L=new Map,b=new Map;function se(t,e){const n=t.match(/^(\s*<\w+)([^>]*)(>)/);if(n){const[,o,r,i]=n,s=r.replace(new RegExp(`\\s*${O}="[^"]*"`,"g"),"");return t.replace(n[0],`${o}${s} ${O}="${e}"${i}`)}return t}function V(t){let e=document.querySelector(t);if(e)return e;const n=b.get(t);return n&&(e=document.querySelector(`[${O}="${n}"]`)),e}function ae(t,e){const n=V(t);if(!n)return console.warn(`[spool-inject] Element not found: ${t}`),!1;let o=b.get(t);o||(o=`preview_${Date.now()}_${Math.random().toString(36).slice(2,9)}`,b.set(t,o)),h.has(t)||h.set(t,n.outerHTML);const r=se(e,o);return L.set(t,r),n.outerHTML=r,!0}function j(t){const e=V(t),n=h.get(t);e&&n!==void 0&&(e.outerHTML=n),h.delete(t),L.delete(t),b.delete(t)}function ce(){const t=Array.from(L.keys());for(const e of t)j(e)}let c=null,S=!1,d=null;const ue=150;function de(t){c=t,window.addEventListener("scroll",q,{capture:!0,passive:!0})}function fe(){window.removeEventListener("scroll",q,{capture:!0}),d!==null&&(clearTimeout(d),d=null),S=!1,c=null}function q(){S||(S=!0,U(),c==null||c("SCROLL_START",null)),d!==null&&clearTimeout(d),d=window.setTimeout(pe,ue)}function pe(){S=!1,d=null,K(),c==null||c("SCROLL_END",null)}const ye="spool-inject";function f(t,e){const n={type:t,payload:e,source:ye};window.parent.postMessage(n,"*")}function ve(t){const e=t.data;if((e==null?void 0:e.source)==="spool-shell")switch(e.type){case"TOGGLE_SELECTION_MODE":oe(e.payload);break;case"APPLY_STYLE_CHANGE":{const{selector:n,styles:o}=e.payload;le(n,o)&&f("STYLES_UPDATED",{selector:n,styles:o});break}case"REVERT_STYLE_CHANGE":{const{selector:n}=e.payload;D(n);break}case"APPLY_VARIANT_PREVIEW":{const{selector:n,html:o}=e.payload;ae(n,o);break}case"REVERT_VARIANT_PREVIEW":{const{selector:n}=e.payload;j(n);break}case"HIGHLIGHT_ELEMENT":{const{selector:n}=e.payload;W(n);break}case"CLEAR_HIGHLIGHT":z();break;case"GET_ELEMENT_HTML":{const{selector:n,requestId:o}=e.payload,r=document.querySelector(n);f("ELEMENT_HTML",{requestId:o,html:(r==null?void 0:r.outerHTML)||null});break}case"GET_COMPUTED_STYLES":{const{selector:n,requestId:o}=e.payload,r=document.querySelector(n);f("COMPUTED_STYLES",{requestId:o,styles:r?$(r):null});break}case"GET_ELEMENT_POSITIONS":{const{selectors:n,requestId:o}=e.payload,r=n.map(i=>{const s=document.querySelector(i);if(!s)return{selector:i,rect:null};const p=s.getBoundingClientRect();return{selector:i,rect:{top:p.top,left:p.left,width:p.width,height:p.height}}});f("ELEMENT_POSITIONS",{requestId:o,positions:r});break}}}function F(){if(window.__spoolInjectInitialized){console.log("[spool-inject] Already initialized, skipping");return}console.log("[spool-inject] Initializing..."),window.__spoolInjectInitialized=!0,Y(),ee(f),de(f),window.addEventListener("message",ve),f("IFRAME_READY",null),console.log("[spool-inject] Ready"),window.addEventListener("beforeunload",()=>{ie(),ce(),I(),fe()})}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",F):F()})();
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@nicmeriano/spool-inject",
3
+ "version": "0.0.1",
4
+ "description": "Injection script for Spool iframe communication",
5
+ "type": "module",
6
+ "main": "./dist/inject.js",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "keywords": [
11
+ "spool",
12
+ "iframe",
13
+ "injection"
14
+ ],
15
+ "license": "UNLICENSED",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/nicmeriano/react-inspect.git",
19
+ "directory": "packages/inject"
20
+ },
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "devDependencies": {
25
+ "typescript": "^5.7.0",
26
+ "vite": "^6.0.0"
27
+ },
28
+ "engines": {
29
+ "node": ">=18.0.0"
30
+ },
31
+ "scripts": {
32
+ "build": "vite build",
33
+ "dev": "vite build --watch",
34
+ "clean": "rm -rf dist",
35
+ "typecheck": "tsc --noEmit"
36
+ }
37
+ }