Setting the file. One moment.
Live Browser DOM · Impeccable · pbakaus/impeccable · Skills Docs
ContentsBack to the top of the page (opens in a new tab)
scripts/ live-browser-dom.js
JavaScript · 167 lines · 5 KB
({
13 prefix ,
14 skipTags ,
15 document : doc = root.document,
16 css = root. CSS ,
17 crypto = root.crypto,
18 } = {}) {
19 if ( ! prefix) throw new Error ( 'prefix required' );
20 if ( ! doc) throw new Error ( 'document required' );
21 const tagsToSkip = skipTags || new Set ();
22
23 function own ( el ) {
24 return el && (el.id?. startsWith (prefix) || el. closest ?.( '[id^="' + prefix + '"]' ));
25 }
26
27 function pickable ( el ) {
28 if ( ! el || el.nodeType !== 1 ) return false ;
29 if (tagsToSkip. has ( String (el.tagName || '' ). toLowerCase ())) return false ;
30 if ( own (el)) return false ;
31 const r = el. getBoundingClientRect ();
32 return r.width >= 20 && r.height >= 20 ;
33 }
34
35 function desc ( el ) {
36 if ( ! el) return '' ;
37 let s = el.tagName. toLowerCase ();
38 if (el.id) s += '#' + el.id;
39 else if (el.classList. length ) s += '.' + [ ... el.classList]. slice ( 0 , 2 ). join ( '.' );
40 return s;
41 }
42
43 function rectIsUsableAnchor ( rect ) {
44 return !! rect && rect.width > 0.5 && rect.height > 0.5 ;
45 }
46
47 function makeFrozenAnchor ( el ) {
48 if ( ! el || ! el.getBoundingClientRect) return null ;
49 const r = el. getBoundingClientRect ();
50 if ( ! rectIsUsableAnchor (r)) return null ;
51 const rect = {
52 x: r.x, y: r.y,
53 top: r.top, left: r.left,
54 right: r.right, bottom: r.bottom,
55 width: r.width, height: r.height,
56 };
57 return {
58 __impeccableFrozenAnchor: true ,
59 tagName: el.tagName || 'DIV' ,
60 id: el.id || '' ,
61 classList: el.classList ? [ ... el.classList] : [],
62 hasAttribute : () => false ,
63 getBoundingClientRect : () => rect,
64 };
65 }
66
67 function hasFrameworkHmrOwnership ( el ) {
68 for ( let node = el; node; node = node.parentElement) {
69 let keys = [];
70 try { keys = Object. getOwnPropertyNames (node); } catch {}
71 if (keys. some (( key ) => (
72 key. startsWith ( '__reactFiber$' )
73 || key. startsWith ( '__reactProps$' )
74 || key. startsWith ( '__reactContainer$' )
75 || key === '_reactRootContainer'
76 || key === '__vueParentComponent'
77 || key === '__vue_app__'
78 || key === '__vnode'
79 || key === '__svelte_meta'
80 ))) {
81 return true ;
82 }
83 }
84 return false ;
85 }
86
87 function id8 () {
88 if (crypto?.randomUUID) return crypto. randomUUID (). replace ( /-/ g , '' ). slice ( 0 , 8 );
89 return (Math. random (). toString ( 16 ). slice ( 2 ) + Date. now (). toString ( 16 )). slice ( 0 , 8 );
90 }
91
92 function cssId ( id ) {
93 if (css?.escape) return css. escape (id);
94 return String (id). replace ( /( [ !"#$%&'()*+,./:;<=>?@[ \\\] ^`{|}~] )/ g , ' \\ $1' );
95 }
96
97 function liveUiRoot () {
98 const uiRoot = root.__IMPECCABLE_LIVE_UI_ROOT__;
99 if (uiRoot && typeof uiRoot.appendChild === 'function' ) return uiRoot;
100 return doc.body;
101 }
102
103 function uiAppend ( el ) {
104 liveUiRoot (). appendChild (el);
105 return el;
106 }
107
108 function uiAppendStyle ( styleEl ) {
109 const uiRoot = liveUiRoot ();
110 if (uiRoot && uiRoot !== doc.body) uiRoot. appendChild (styleEl);
111 else doc.head. appendChild (styleEl);
112 return styleEl;
113 }
114
115 function uiGetById ( id ) {
116 const uiRoot = liveUiRoot ();
117 if (uiRoot?.getElementById) {
118 const found = uiRoot. getElementById (id);
119 if (found) return found;
120 }
121 if (uiRoot?.querySelector) {
122 const found = uiRoot. querySelector ( '#' + cssId (id));
123 if (found) return found;
124 }
125 return doc. getElementById (id);
126 }
127
128 function activeElementDeep () {
129 let active = doc.activeElement;
130 while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
131 return active;
132 }
133
134 function defangOutsideHandlers ( rootEl , { setPointerEvents = true } = {}) {
135 if ( ! rootEl) return ;
136 if (setPointerEvents) {
137 rootEl.style. setProperty ( 'pointer-events' , 'auto' , 'important' );
138 }
139 const stop = ( e ) => e. stopPropagation ();
140 rootEl. addEventListener ( 'pointerdown' , stop);
141 rootEl. addEventListener ( 'mousedown' , stop);
142 rootEl. addEventListener ( 'focusin' , stop);
143 }
144
145 return {
146 own,
147 pickable,
148 desc,
149 rectIsUsableAnchor,
150 makeFrozenAnchor,
151 hasFrameworkHmrOwnership,
152 id8,
153 cssId,
154 liveUiRoot,
155 uiAppend,
156 uiAppendStyle,
157 uiGetById,
158 activeElementDeep,
159 defangOutsideHandlers,
160 };
161 }
162
163 root.__IMPECCABLE_LIVE_DOM__ = {
164 version: 1 ,
165 createLiveBrowserDomHelpers,
166 };
167 })( typeof window !== 'undefined' ? window : globalThis);