@alikhalilll/a-smart-skeleton 1.0.0 → 2.0.0
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 +248 -186
- package/dist/_chunks/core.js +142 -15
- package/dist/_chunks/core.js.map +1 -1
- package/dist/_chunks/index.d.ts +30 -5
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/styles.css +136 -2
- package/package.json +2 -2
- package/src/core/fade.ts +3 -3
- package/src/core/index.ts +1 -1
- package/src/core/inline.generated.ts +1 -1
- package/src/core/measure.ts +117 -0
- package/src/core/plan.ts +1 -1
- package/src/core/reveals.ts +12 -3
- package/src/core/shimmer.ts +71 -15
- package/src/core/styles.ts +20 -0
- package/web-types.json +1 -1
package/dist/_chunks/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","names":["host","MEDIA","restore","restore","noop","wipe"],"sources":["../../src/core/constants.ts","../../src/core/styles.ts","../../src/core/inline.generated.ts","../../src/core/theme.ts","../../src/core/debug.ts","../../src/core/canvas.ts","../../src/core/snapshot.ts","../../src/core/dev.ts","../../src/core/measure.ts","../../src/core/motion.ts","../../src/core/shimmer.ts","../../src/core/plan.ts","../../src/core/shapes.ts","../../src/core/ghost.ts","../../src/core/memory.ts","../../src/core/skeleton.ts","../../src/core/images.ts","../../src/core/sweep.ts","../../src/core/reveals.ts","../../src/core/fade.ts","../../src/core/reveal.ts"],"sourcesContent":["export const ATTR_REVEAL = 'ask-reveal';\nexport const ATTR_PANE = 'ask-pane';\nexport const ATTR_LOADING = 'ask-loading';\nexport const ATTR_GHOST = 'ask-ghost'; // The framework's render of the content, laid out but never seen\nexport const ATTR_SNAPSHOT = 'ask-snapshot'; // A remembered or fallback shape, standing in for the ghost\nexport const ATTR_LAYER = 'ask-layer';\nexport const ATTR_RECT = 'ask-rect';\nexport const ATTR_BAR = 'ask-bar';\nexport const ATTR_INACTIVE = 'ask-inactive';\nexport const ATTR_EXITING = 'ask-exiting'; // On a pane fading out — its skeleton holds still\nexport const ATTR_COVERED = 'ask-covered'; // Drawn as one block by a bone, so its own paint is hidden\nexport const ATTR_OWN = 'ask-own'; // A subtree that draws its own skeleton — measuring stops at it\nexport const ATTR_IGNORE = 'ask-ignore';\nexport const ATTR_BLOCK = 'ask-block';\n\nexport const GHOSTED = Symbol.for('a-smart-skeleton.ghost'); // On a loading root once its Ghost runs: the inline script stands down\nexport const UNCOVER = Symbol.for('a-smart-skeleton.uncover'); // On a served loading root: drops the inline script's sheet hiding covered paint, once Ghost marks it\nexport const BOOT = 'a-smart-skeleton.boot'; // Symbol.for key on window: the inline script's measuring, sent once a page — later skeletons' stubs call it, or queue for it\nexport const ATTR_STATUS = 'ask-status'; // Read to screen readers in place of the skeleton\nexport const ATTR_XRAY = 'ask-xray'; // Debug, on any ancestor: shows the ghost through its bones\nexport const ATTR_DEBUG = 'ask-debug'; // Debug outlines for this subtree alone\n\n// Themed by ASmartSkeletonProvider; the fallbacks are translucent so one grey reads on light and dark pages alike\nexport const BASE = 'var(--ask-base, rgb(128 128 128 / 0.2))';\nexport const HIGHLIGHT = 'var(--ask-highlight, rgb(255 255 255 / 0.12))';\nexport const FADE_DURATION = 200;\nexport const CASCADE_SPREAD = 320; // From the first piece of a sequenced reveal to the last\nexport const RESIZE_DURATION = 280; // A reveal easing to its new height, when its skeleton guessed the content wrong\nexport const IMAGE_TIMEOUT = 10000; // Longest a reveal holds for an image — a stalled request mustn't keep a skeleton up for good\n// One loop of each animation, by `speed`; a shimmer's is across a 1280px-wide screen\nexport const DURATIONS = {\n shimmer: { slow: 4000, fast: 2000 },\n pulse: { slow: 2400, fast: 1200 },\n} as const;\n\n// Leaves that hold text, so an empty one still stands for a line of it\nexport const TEXT_TAGS = [\n 'a',\n 'b',\n 'code',\n 'dd',\n 'dt',\n 'em',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'i',\n 'label',\n 'li',\n 'p',\n 'small',\n 'span',\n 'strong',\n 'td',\n 'th',\n 'time',\n];\n\n// Drawn as one block at their box — there is no text inside to measure\nexport const MEDIA_TAGS = [\n 'audio',\n 'canvas',\n 'embed',\n 'iframe',\n 'img',\n 'input',\n 'object',\n 'picture',\n 'select',\n 'svg',\n 'textarea',\n 'video',\n];\n","import {\n ATTR_BAR,\n ATTR_BLOCK,\n ATTR_LAYER,\n ATTR_COVERED,\n ATTR_GHOST,\n ATTR_INACTIVE,\n ATTR_LOADING,\n ATTR_OWN,\n ATTR_PANE,\n ATTR_REVEAL,\n ATTR_STATUS,\n ATTR_XRAY,\n BASE,\n MEDIA_TAGS,\n TEXT_TAGS,\n} from './constants';\n\nconst media = MEDIA_TAGS.join(', ');\nconst text = TEXT_TAGS.join(', ');\n\n/** The whole stylesheet, for rendering into a page yourself. */\nexport const SMART_SKELETON_CSS = `\n[${ATTR_REVEAL}] {\n position: relative;\n}\n\na-smart-skeleton-reveal,\nask-reveal {\n display: block;\n}\n\na-smart-skeleton-reveal[loading]:not(:defined),\nask-reveal[loading]:not(:defined) {\n visibility: hidden;\n}\n\n[${ATTR_PANE}] {\n display: block;\n}\n\n[${ATTR_LOADING}] {\n position: relative;\n -webkit-user-select: none;\n user-select: none;\n pointer-events: none;\n}\n\n[${ATTR_INACTIVE}] {\n display: none !important;\n}\n\n[${ATTR_LAYER}] {\n position: absolute;\n inset: 0;\n overflow: visible;\n}\n\n[${ATTR_BAR}] {\n display: block;\n background-color: ${BASE};\n background-repeat: no-repeat;\n}\n\n/* Containers keep their surface; what they hold is drawn by bones, measured before the first paint */\n@scope ([${ATTR_LOADING}]) to ([${ATTR_OWN}], [${ATTR_LAYER}]) {\n :scope,\n :scope * {\n color: transparent !important;\n -webkit-text-fill-color: transparent !important;\n text-shadow: none !important;\n text-decoration-color: transparent !important;\n }\n\n :scope ::placeholder {\n color: transparent !important;\n }\n\n /* A line to measure in empty text; content only, never a size, or a dot-sized span would grow round it */\n :scope :is(${text}):empty:not(svg *)::before {\n content: \"000000\";\n }\n\n /* Leaves are drawn by bones, so their own paint never shows; visibility, as measuring reads it */\n :scope :is(:not(:has(*)), ${media}, [${ATTR_COVERED}], [${ATTR_BLOCK}]):not(svg *) {\n visibility: hidden !important;\n }\n\n /* No script to measure: a bar struck through each line of text instead */\n @media (scripting: none) {\n :scope :not(:has(*)):not(svg *) {\n visibility: visible !important;\n }\n\n :scope,\n :scope * {\n text-decoration: line-through ${BASE} !important;\n text-decoration-thickness: 0.72em !important;\n text-decoration-skip-ink: none !important;\n }\n\n :scope :is(${media}, [${ATTR_BLOCK}]):not(svg *) {\n visibility: visible !important;\n background: ${BASE} !important;\n }\n\n :scope svg * {\n fill: transparent !important;\n stroke: transparent !important;\n }\n\n :scope :is(img, video) {\n object-position: -100vw 0;\n }\n }\n}\n\n/* Read by screen readers in the skeleton's place, never seen */\n[${ATTR_STATUS}] {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n/* Debug x-ray: the ghost shown through its bones, to see what was measured */\n[${ATTR_XRAY}] [${ATTR_LOADING}] [${ATTR_GHOST}],\n[${ATTR_XRAY}] [${ATTR_LOADING}] [${ATTR_GHOST}] *:not(svg *) {\n visibility: visible !important;\n color: rgb(255 0 80 / 0.7) !important;\n -webkit-text-fill-color: rgb(255 0 80 / 0.7) !important;\n}\n\n/* Lets addStyles see a stylesheet already on the page, from styles.css or a server render */\n:root {\n --ask: 1;\n}`;\n\nlet styleEl: HTMLStyleElement | null = null;\nlet refCount = 0;\n\nlet present: boolean | undefined;\n\nexport function addStyles() {\n refCount++;\n if (styleEl) return;\n\n // Already on the page — server-rendered, hoisted by React, or imported as styles.css\n present ??= !!getComputedStyle(document.documentElement).getPropertyValue('--ask');\n if (present) return;\n\n styleEl = document.createElement('style');\n styleEl.dataset.aSmartSkeleton = 'true';\n styleEl.textContent = SMART_SKELETON_CSS;\n document.head.appendChild(styleEl);\n}\n\nexport function removeStyles() {\n refCount--;\n if (refCount > 0 || !styleEl) return;\n\n styleEl.remove();\n styleEl = null;\n}\n","// Generated by scripts/build-inline.mjs from boot.ts — don't edit\nexport const INLINE_SCRIPT = \"\\\"use strict\\\";(()=>{var B=\\\"ask-ghost\\\";var D=\\\"ask-layer\\\",L=\\\"ask-rect\\\";var R=\\\"ask-covered\\\",$=\\\"ask-own\\\",v=\\\"ask-ignore\\\",H=\\\"ask-block\\\",I=Symbol.for(\\\"a-smart-skeleton.ghost\\\"),G=Symbol.for(\\\"a-smart-skeleton.uncover\\\"),P=\\\"a-smart-skeleton.boot\\\";var W=\\\"var(--ask-base, rgb(128 128 128 / 0.2))\\\",z=\\\"var(--ask-highlight, rgb(255 255 255 / 0.12))\\\";var F={shimmer:{slow:4e3,fast:2e3},pulse:{slow:2400,fast:1200}},X=[\\\"a\\\",\\\"b\\\",\\\"code\\\",\\\"dd\\\",\\\"dt\\\",\\\"em\\\",\\\"h1\\\",\\\"h2\\\",\\\"h3\\\",\\\"h4\\\",\\\"h5\\\",\\\"h6\\\",\\\"i\\\",\\\"label\\\",\\\"li\\\",\\\"p\\\",\\\"small\\\",\\\"span\\\",\\\"strong\\\",\\\"td\\\",\\\"th\\\",\\\"time\\\"],U=[\\\"audio\\\",\\\"canvas\\\",\\\"embed\\\",\\\"iframe\\\",\\\"img\\\",\\\"input\\\",\\\"object\\\",\\\"picture\\\",\\\"select\\\",\\\"svg\\\",\\\"textarea\\\",\\\"video\\\"];var gt,V=()=>gt??(gt=/jsdom/.test(navigator.userAgent)?null:document.createElement(\\\"canvas\\\").getContext(\\\"2d\\\"));var J=(t,n)=>t?{left:Math.max(t.left,n.left),right:Math.min(t.right,n.right),top:Math.max(t.top,n.top),bottom:Math.min(t.bottom,n.bottom)}:n,A=t=>[[t.left,t.top],[t.right,t.top],[t.right,t.bottom],[t.left,t.bottom]],k=(t,n)=>Math.abs(t[0]-n[0])<1&&Math.abs(t[1]-n[1])<1;function Q(t,n){let e=Math.min(n.right-n.left,n.bottom-n.top),o=r=>r.endsWith(\\\"%\\\")?parseFloat(r)/100*e:parseFloat(r)||0;return[o(t.borderTopLeftRadius),o(t.borderTopRightRadius),o(t.borderBottomRightRadius),o(t.borderBottomLeftRadius)]}function bt(t,n,e){let o=J(t,n),r=Q(e,n),c=t?A(t):[],a=A(n),m=A(o).map((f,T)=>k(f,a[T])?r[T]:t&&k(f,c[T])?t.corners[T]:0),{left:s,right:i,top:l,bottom:h}=o;return{left:s,right:i,top:l,bottom:h,corners:m}}function Tt(t,n,e,o){if(!t)return e;let r=A(t),c=A(n).map((m,s)=>t.corners[s]>0&&k(m,r[s]));if(!c.some(Boolean))return e;let a=Q(o,n);return c.map((m,s)=>m?Math.max(a[s],t.corners[s]):a[s]).map(m=>`${m}px`).join(\\\" \\\")}var j=(t,n)=>{let e=J(n,t);return e.right-e.left>=2&&e.bottom-e.top>=2?e:null},q={top:\\\"ascender\\\",bottom:\\\"descender\\\"},C=new Map,tt=t=>[...t.getClientRects?.()??[]];function St(t){let n=`${t.fontStyle} ${t.fontWeight} ${t.fontSize} ${t.fontFamily}`;if(C.has(n))return C.get(n);let e=V(),o=null;if(e){e.font=n;let r=e.measureText(\\\"H\\\"),c=a=>e.measureText(a).actualBoundingBoxAscent;o={ascent:r.fontBoundingBoxAscent,descent:r.fontBoundingBoxDescent,ascender:c(\\\"bdfhkl\\\"),capHeight:r.actualBoundingBoxAscent,xHeight:c(\\\"xz\\\"),descender:e.measureText(\\\"gjpqy\\\").actualBoundingBoxDescent}}return C.set(n,o),o}var Y={ascender:\\\"ascender\\\",\\\"cap-height\\\":\\\"capHeight\\\",\\\"x-height\\\":\\\"xHeight\\\"},K=(t,n,e,o)=>{let r=t.getPropertyValue(n).trim();return e.includes(r)?r:o};function xt(t,n,e){let o=St(n);if(!o){let s=Math.min(e*.72,t.bottom-t.top),i=(t.top+t.bottom)/2;return{barTop:i-s/2,barBottom:i+s/2}}let r=K(n,\\\"--ask-text-top\\\",Object.keys(Y),q.top),c=K(n,\\\"--ask-text-bottom\\\",[\\\"baseline\\\",\\\"descender\\\"],q.bottom),a=o.ascent+o.descent,m=t.top+(t.bottom-t.top-a)/2+o.ascent;return{barTop:m-o[Y[r]],barBottom:m+(c===\\\"descender\\\"?o.descender:0)}}var Et=new Set(U),Rt=new Set(X),et=.4,At=/[,/]\\\\s*0\\\\)$/,y=(t,n)=>t!==\\\"\\\"&&t!==n,yt=[\\\"Top\\\",\\\"Right\\\",\\\"Bottom\\\",\\\"Left\\\"],Mt=t=>yt.every(n=>y(t[`border${n}Style`],\\\"none\\\")&&y(t[`border${n}Width`],\\\"0px\\\")),Ct=t=>{let[n=0,e=0,o=0,r=0]=(t.replace(/rgba?\\\\([^)]*\\\\)|#\\\\w+/g,\\\"\\\").match(/-?[\\\\d.]+px/g)??[]).map(parseFloat);return t.includes(\\\"inset\\\")&&!o&&!r&&n===0!=(e===0)&&Math.abs(n+e)<=2},kt=t=>y(t,\\\"none\\\")&&!t.split(/,(?![^(]*\\\\))/).every(Ct),Ot=t=>y(t.backgroundColor,\\\"transparent\\\")&&!At.test(t.backgroundColor)||y(t.backgroundImage,\\\"none\\\")||kt(t.boxShadow)||Mt(t),ot=t=>Et.has(t.localName),nt=t=>Rt.has(t.localName)&&!t.firstElementChild&&!t.textContent?.trim(),wt=t=>{let n=document.createTreeWalker(t,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT),e=document.createRange(),o=[],r=0;for(;n.nextNode();){let i=n.currentNode;if(i.nodeType===Node.TEXT_NODE){let l=i.parentElement;if(!i.textContent?.trim()||!l)continue;r++;let h=l.getBoundingClientRect();if(h.width<=1||h.height<=1)continue;e.selectNodeContents(i),o.push(tt(e).filter(f=>f.width||f.height))}else nt(i)&&(r++,o.push([...i.getClientRects()]))}if(!o.some(i=>i.length))return r;let c=(parseFloat(getComputedStyle(t).fontSize)||16)*et,a=(i,l)=>Math.min(i.bottom,l.bottom)-Math.max(i.top,l.top)>=Math.min(i.height,l.height)/2&&Math.max(i.left,l.left)-Math.min(i.right,l.right)<=c,m=o.map((i,l)=>l),s=i=>m[i]===i?i:m[i]=s(m[i]);for(let i=0;i<o.length;i++)for(let l=i+1;l<o.length;l++)o[i].some(h=>o[l].some(f=>a(h,f)))&&(m[s(l)]=s(i));return new Set(o.map((i,l)=>s(l))).size},Nt=(t,n)=>t.hasAttribute(H)||ot(t)||Ot(n)&&wt(t)<=1;function _t(t,n){if(parseFloat(n.borderRadius)||!t.parentElement)return n.borderRadius||\\\"0px\\\";let e=t.parentElement,o=getComputedStyle(e),r=t.getBoundingClientRect(),c=e.getBoundingClientRect();return Math.abs(r.width-c.width)<1&&Math.abs(r.height-c.height)<1&&o.overflow!==\\\"visible\\\"?o.borderRadius:n.borderRadius||\\\"0px\\\"}function Z(t){t.sort((e,o)=>e.left-o.left);let n=[];for(let e of t){let o=n.find(r=>{let c=Math.min(r.bottom,e.bottom)-Math.max(r.top,e.top),a=Math.min(r.bottom-r.top,e.bottom-e.top),m=e.left-r.right;return c>=a/2&&m<=Math.max(r.fontSize,e.fontSize)*et});o?(o.left=Math.min(o.left,e.left),o.right=Math.max(o.right,e.right),o.top=Math.min(o.top,e.top),o.bottom=Math.max(o.bottom,e.bottom),o.fontSize=Math.max(o.fontSize,e.fontSize),o.barTop=Math.min(o.barTop,e.barTop),o.barBottom=Math.max(o.barBottom,e.barBottom)):n.push({...e})}return n.map(e=>{let o=e.barBottom-e.barTop;return{x:e.left,y:e.barTop,width:e.right-e.left,height:o,radius:e.radius||`${Math.round(o/3)}px`}})}function rt(t,n,{mark:e=!0,onCovered:o}={}){let r=n.getBoundingClientRect(),c=n.offsetWidth?r.width/n.offsetWidth:1,a=n.offsetHeight?r.height/n.offsetHeight:1,m=d=>({left:(d.left-r.left)/c,right:(d.right-r.left)/c,top:(d.top-r.top)/a,bottom:(d.bottom-r.top)/a}),s=[],i=[],l=new Set,h=document.createRange(),f=(d,g,b)=>{let u=j(d,b);if(!u)return;let p=parseFloat(g.fontSize)||16,M=m(u);i.push({...M,fontSize:p,...xt(M,g,p),radius:g.getPropertyValue(\\\"--ask-radius\\\").trim()})},T=(d,g)=>{let b=d.data.search(/\\\\S/);if(b<0||!d.parentElement)return;h.setStart(d,b),h.setEnd(d,d.data.trimEnd().length);let u=getComputedStyle(d.parentElement);for(let p of tt(h))f(p,u,g)},_=(d,g)=>{for(let b of d.childNodes){if(b.nodeType===Node.TEXT_NODE){T(b,g);continue}if(b.nodeType!==Node.ELEMENT_NODE)continue;let u=b;if(u.hasAttribute(v)||u.hasAttribute($))continue;let p=getComputedStyle(u);if(p.display===\\\"none\\\")continue;if(Nt(u,p)){let E=j(u.getBoundingClientRect(),g);if(E){let S=m(E);s.push({x:S.left,y:S.top,width:S.right-S.left,height:S.bottom-S.top,radius:Tt(g,E,_t(u,p),p)})}ot(u)||l.add(u);continue}if(nt(u)){for(let E of u.getClientRects())f(E,p,g);continue}let M=p.overflowX!==\\\"visible\\\"||p.overflowY!==\\\"visible\\\";_(u,M?bt(g,u.getBoundingClientRect(),p):g)}};if(_(t,null),o?.(l),!e)return[...s,...Z(i)];for(let d of t.querySelectorAll(`[${R}]`))l.has(d)||d.removeAttribute(R);for(let d of l)d.hasAttribute(R)||d.setAttribute(R,\\\"\\\");return[...s,...Z(i)]}var Bt=t=>typeof matchMedia<\\\"u\\\"&&matchMedia(t).matches,Dt=()=>typeof Element<\\\"u\\\"&&typeof Element.prototype.animate==\\\"function\\\",st=()=>!Dt()||Bt(\\\"(prefers-reduced-motion: reduce)\\\");var it=t=>t.getAnimations?.()??[];var Lt=.7,$t=1280,at=320,vt=2.5,Ht=.45,It=[\\\"shimmer\\\",\\\"group-shimmer\\\",\\\"pulse\\\",\\\"none\\\"];function mt(t){let n=getComputedStyle(t),e=(c,a,m)=>{let s=n.getPropertyValue(c).trim();return a.includes(s)?s:m},o=e(\\\"--ask-animation\\\",It,\\\"shimmer\\\"),r=e(\\\"--ask-speed\\\",[\\\"slow\\\",\\\"fast\\\"],\\\"slow\\\");return{animation:o,duration:F[o===\\\"pulse\\\"?\\\"pulse\\\":\\\"shimmer\\\"][r]}}var w=20,Gt=Math.sin(w*Math.PI/180),lt=Math.cos(w*Math.PI/180),Pt=Gt/lt;var Wt=`${90+w}deg`,O=.85,x=12,ct=t=>(1-Math.cos(Math.PI*t))/2;function zt(t){let n=t*vt,e=(r,c)=>`color-mix(in srgb, ${z} ${(c*100).toFixed(1)}%, transparent) ${(r*t).toFixed(2)}px`,o=[];for(let r=0;r<=x;r++)o.push(e(r/x*O,ct(r/x)));for(let r=1;r<=x;r++)o.push(e(O+r/x*(1-O),ct(1-r/x)));return{width:n/lt,image:`repeating-linear-gradient(${Wt}, ${o.join(\\\", \\\")}, transparent ${n.toFixed(2)}px)`}}function Ft(t,n,e=mt(t)){for(let f of it(t))f.cancel();if(t.style.backgroundImage=\\\"\\\",t.style.backgroundRepeat=\\\"\\\",st()||typeof t.animate!=\\\"function\\\"||e.animation===\\\"none\\\")return;let o={duration:e.duration,iterations:1/0};if(e.animation===\\\"pulse\\\"){t.animate([{opacity:1,easing:\\\"ease-in-out\\\"},{opacity:Ht,easing:\\\"ease-in-out\\\"},{opacity:1}],o).startTime=0;return}let r=t.getBoundingClientRect(),c=r.left+scrollX,a=e.animation===\\\"group-shimmer\\\"?n??{left:c,top:r.top,width:r.width,height:r.height}:{left:0,top:0,width:document.documentElement.clientWidth||innerWidth,height:innerHeight},m=Math.min(Math.max(a.width*.4,80),at),{width:s,image:i}=zt(m),l=c-a.left+(r.top-a.top)*Pt,h=e.duration*Lt/($t+at);t.style.backgroundImage=i,t.style.backgroundSize=`${s}px 100%`,t.style.backgroundRepeat=\\\"repeat-x\\\",t.animate([{backgroundPosition:`${-l}px 0`},{backgroundPosition:`${s-l}px 0`}],{duration:s*h,iterations:1/0}).startTime=0}var Xt=t=>t.shadowRoot??t.attachShadow({mode:\\\"open\\\"});function dt(t,n){let e=Xt(t),o=t.getBoundingClientRect(),r={left:o.left+scrollX,top:o.top,width:o.width,height:o.height},c=mt(t);for(n.forEach((a,m)=>{let s=e.children[m];s||(s=document.createElement(\\\"div\\\"),s.setAttribute(L,\\\"\\\"),s.style.cssText=`position:absolute;display:block;pointer-events:none;background-color:${W};background-repeat:no-repeat`,e.append(s)),Object.assign(s.style,{left:`${a.x}px`,top:`${a.y}px`,width:`${a.width}px`,height:`${a.height}px`,borderRadius:a.radius});let i=`${Math.round(r.left+a.x)}|${Math.round(a.y)}|${Math.round(a.height)}|${Math.round(r.left)}|${Math.round(r.width)}|${Math.round(r.height)}|${document.documentElement.clientWidth}|${c.animation}|${c.duration}`;s.dataset.motion!==i&&(s.dataset.motion=i,Ft(s,r,c))});e.children.length>n.length;)e.lastElementChild.remove()}var pt=t=>t.parentElement?`${pt(t.parentElement)} > :nth-child(${[...t.parentElement.children].indexOf(t)+1})`:\\\":root\\\";function N(t){let n=t?.previousElementSibling,e=n?.querySelector(`:scope > [${B}]`),o=n?.querySelector(`:scope > [${D}]`);if(!n||!e||!o)return;let r=typeof CSSStyleSheet==\\\"function\\\"&&\\\"replaceSync\\\"in CSSStyleSheet.prototype?new CSSStyleSheet:null;r&&(document.adoptedStyleSheets=[...document.adoptedStyleSheets,r],n[G]=()=>{document.adoptedStyleSheets=document.adoptedStyleSheets.filter(s=>s!==r)});let c=s=>r?.replaceSync(s.size?`${[...s].map(pt).join(\\\", \\\")} { visibility: hidden !important; }`:\\\"\\\"),a=()=>{if(!o.isConnected||n[I])return m.disconnect();e.getClientRects().length&&dt(o,rt(e,o,{mark:!1,onCovered:c}))},m=new ResizeObserver(a);m.observe(n),document.fonts?.ready.then(a)}var ht=self,ft=Symbol.for(P),ut=ht[ft];ht[ft]=N;Array.isArray(ut)&&ut.forEach(N);N(document.currentScript);})();\";\n\n/** For every skeleton after a page's first: calls the boot INLINE_SCRIPT left on window. */\nexport const INLINE_STUB = \"(s=>{let k=Symbol.for(\\\"a-smart-skeleton.boot\\\"),b=self[k];typeof b==\\\"function\\\"?b(s):(self[k]=b||[]).push(s)})(document.currentScript)\";\n\n/** Either, as a whole element — for templates where a literal script tag would be read as the component's own. */\nexport const inlineScriptTag = (nonce?: string, stub = false) =>\n `<script${nonce ? ` nonce=\"${nonce.replace(/\"/g, \""\")}\"` : \"\"}>${stub ? INLINE_STUB : INLINE_SCRIPT}</script>`;\n","import type { TextBottom, TextTop } from './measure';\n\nexport type SkeletonColors = {\n /** The skeleton's fill. */\n base: string;\n /** The shimmer sweeping across it. */\n highlight: string;\n};\n\n/** `shimmer` sweeps the whole page, `group-shimmer` each skeleton, `pulse` fades; all hold still under reduced motion. */\nexport type SkeletonAnimation = 'shimmer' | 'group-shimmer' | 'pulse' | 'none';\n\n/** How quickly the animation loops — each animation has its own slow and fast. */\nexport type SkeletonSpeed = 'slow' | 'fast';\n\n/** How much of each line of text is drawn: from the font's `top` line down to its `bottom` line. */\nexport type SkeletonText = { top?: TextTop; bottom?: TextBottom };\n\n/** `system` follows `prefers-color-scheme`; the others pin one set of colours. */\nexport type SkeletonMode = 'light' | 'dark' | 'system';\n\nexport type SkeletonTheme = {\n light?: SkeletonColors;\n dark?: SkeletonColors;\n /** How round each line of text, and any other single bar, is drawn — any CSS length; `999px` for pills. Images and chips keep their own. */\n radius?: string;\n animation?: SkeletonAnimation;\n speed?: SkeletonSpeed;\n text?: SkeletonText;\n};\n\nexport const DEFAULT_COLORS: { light: SkeletonColors; dark: SkeletonColors } = {\n light: { base: 'rgb(0 0 0 / 0.07)', highlight: 'rgb(255 255 255 / 0.6)' },\n dark: {\n base: 'rgb(255 255 255 / 0.08)',\n highlight: 'rgb(255 255 255 / 0.1)',\n },\n};\n\nexport const DEFAULT_THEME = {\n ...DEFAULT_COLORS,\n animation: 'shimmer',\n speed: 'slow',\n text: { top: 'ascender', bottom: 'descender' },\n} as const satisfies SkeletonTheme;\n\n// Colours pass through getComputedStyle without ever reaching the stylesheet, so\n// the custom-property declarations are the only path a string takes directly into\n// CSS text. A value with `;` or `}` would close its declaration and inject rules,\n// so the four keyword props are gated against their own enums and length-like props\n// are gated against a conservative length regex — anything else is dropped.\nconst ANIMATION = new Set<SkeletonAnimation>(['shimmer', 'group-shimmer', 'pulse', 'none']);\nconst SPEED = new Set<SkeletonSpeed>(['slow', 'fast']);\nconst TEXT_TOP = new Set<TextTop>(['ascender', 'cap-height', 'x-height']);\nconst TEXT_BOTTOM = new Set<TextBottom>(['baseline', 'descender']);\n\n// A CSS <length>, <percentage>, calc(), or the whitespace-separated list of them that\n// border-radius allows — digits, dots, whitespace, parens, and unit letters only.\n// Reject angle brackets and semicolons so no value can break out of the declaration.\nconst LENGTH = /^[\\d.\\s,%()+\\-*/a-z]+$/i;\n\nconst safeLength = (value: string): string | null => {\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > 100) return null;\n if (/[<>;}{\"'`]/.test(trimmed)) return null;\n return LENGTH.test(trimmed) ? trimmed : null;\n};\n\nconst safeColor = (value: string): string | null => {\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > 200) return null;\n if (/[;}<>]/.test(trimmed)) return null;\n return trimmed;\n};\n\n/** A theme's custom properties for one set of colours, for a style attribute. */\nexport function themeVariables(\n theme: SkeletonTheme = {},\n mode: 'light' | 'dark' | null = null\n): Record<string, string> {\n const variables: Record<string, string> = {};\n const colors = mode && (theme[mode] ?? DEFAULT_COLORS[mode]);\n if (colors) {\n const base = safeColor(colors.base);\n const highlight = safeColor(colors.highlight);\n if (base) variables['--ask-base'] = base;\n if (highlight) variables['--ask-highlight'] = highlight;\n }\n if (theme.radius) {\n const radius = safeLength(theme.radius);\n if (radius) variables['--ask-radius'] = radius;\n }\n if (theme.animation && ANIMATION.has(theme.animation)) {\n variables['--ask-animation'] = theme.animation;\n }\n if (theme.speed && SPEED.has(theme.speed)) {\n variables['--ask-speed'] = theme.speed;\n }\n if (theme.text?.top && TEXT_TOP.has(theme.text.top)) {\n variables['--ask-text-top'] = theme.text.top;\n }\n if (theme.text?.bottom && TEXT_BOTTOM.has(theme.text.bottom)) {\n variables['--ask-text-bottom'] = theme.text.bottom;\n }\n return variables;\n}\n\nconst declarations = (variables: Record<string, string>) =>\n Object.entries(variables)\n .map(([name, value]) => `${name}: ${value};`)\n .join(' ');\n\n/** CSS for a theme on `selector`; colours follow `mode`, and are left out when neither is given. */\nexport function skeletonCSS({\n theme = {},\n mode,\n text,\n selector = ':root',\n}: {\n theme?: SkeletonTheme;\n mode?: SkeletonMode;\n text?: SkeletonText;\n selector?: string;\n}): string {\n const resolved = { ...theme, text: { ...theme.text, ...text } };\n const colored = mode ?? (theme.light || theme.dark ? 'system' : null);\n const base = themeVariables(resolved, colored === 'dark' ? 'dark' : colored ? 'light' : null);\n\n const rules: string[] = [];\n if (Object.keys(base).length) {\n rules.push(`${selector} { ${declarations(base)} }`);\n }\n if (colored === 'system') {\n const dark = themeVariables({ dark: theme.dark }, 'dark');\n rules.push(`@media (prefers-color-scheme: dark) { ${selector} { ${declarations(dark)} } }`);\n }\n return rules.join('\\n');\n}\n\nlet themeEl: HTMLStyleElement | null = null;\n\n/** Sets a theme for the whole page, for setups without a provider. */\nexport function applyTheme(\n theme?: SkeletonTheme,\n mode?: SkeletonMode,\n { nonce }: { nonce?: string } = {}\n) {\n themeEl ??= document.head.appendChild(document.createElement('style'));\n if (nonce) themeEl.nonce = nonce;\n themeEl.textContent = skeletonCSS({ theme, mode });\n}\n\n/** The same CSS as a whole element, for templates that can only render HTML strings. */\nexport const themeStyleTag = (\n config: { theme?: SkeletonTheme; mode?: SkeletonMode; text?: SkeletonText },\n nonce?: string\n) => {\n const css = skeletonCSS(config);\n return css\n ? `<style${nonce ? ` nonce=\"${nonce.replace(/\"/g, '"')}\"` : ''}>${css}</style>`\n : '';\n};\n","import { ATTR_DEBUG, ATTR_XRAY } from './constants';\n\ntype Entry = {\n state: 'loading' | 'shown';\n source?: string;\n moved?: { width: number; height: number };\n};\n\nconst entries = new Map<Element, Entry>();\nlet enabled: boolean | undefined;\nlet host: HTMLElement | null = null;\nlet frame = 0;\n\nfunction fromPage() {\n try {\n return (\n new URLSearchParams(location.search).has('ask-debug') ||\n localStorage.getItem('a-smart-skeleton:debug') === '1'\n );\n } catch {\n return false;\n }\n}\n\nconst everywhere = () => (enabled ??= typeof window !== 'undefined' && fromPage());\n\n/** On with `?ask-debug`, `a-smart-skeleton:debug` = \"1\" in localStorage or `setDebug(true)`; for `element`, also inside `[ask-debug]`. */\nexport const debugging = (element?: Element | null) =>\n everywhere() || !!element?.closest(`[${ATTR_DEBUG}]`);\n\nexport function setDebug(on: boolean) {\n enabled = on;\n if (on) start();\n else stop();\n}\n\nexport function reportLoading(reveal: Element | null, source: string) {\n if (!reveal || !debugging(reveal)) return;\n entries.set(reveal, { state: 'loading', source });\n show();\n}\n\nexport function reportReveal(reveal: Element | null, moved: { width: number; height: number }) {\n if (!reveal || !debugging(reveal)) return;\n entries.set(reveal, { ...entries.get(reveal), state: 'shown', moved });\n show();\n}\n\n// Drawn at once, not on the next frame: a throttled page, like a test's iframe, may wait long for one\nfunction show() {\n start();\n cancelAnimationFrame(frame);\n draw();\n}\n\nconst PANEL_CSS = `\n:host { all: initial; }\n.box { position: fixed; box-sizing: border-box; border: 1px dashed; border-radius: 4px; }\n.label {\n position: absolute; left: -1px; bottom: 100%; margin-bottom: 2px;\n padding: 1px 6px; border-radius: 4px; white-space: nowrap;\n font: 500 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace; color: #fff;\n}\n.loading { border-color: #3b82f6; } .loading .label { background: #3b82f6; }\n.still { border-color: #22c55e; } .still .label { background: #16a34a; }\n.moved { border-color: #ef4444; border-style: solid; } .moved .label { background: #dc2626; }\n.panel {\n position: fixed; right: 12px; bottom: 12px; display: flex; gap: 8px; align-items: center;\n padding: 6px 10px; border-radius: 8px; background: #111; color: #fff; pointer-events: auto;\n font: 500 12px/16px ui-sans-serif, system-ui, sans-serif; box-shadow: 0 4px 16px rgb(0 0 0 / 0.3);\n}\n.panel label { display: flex; gap: 4px; align-items: center; cursor: pointer; }\n`;\n\nfunction start() {\n if (typeof document === 'undefined') return;\n if (!host?.isConnected) {\n host = document.createElement('div');\n host.style.cssText = 'position:fixed;inset:0;pointer-events:none;z-index:2147483647';\n const shadow = host.attachShadow({ mode: 'open' });\n shadow.innerHTML = `<style>${PANEL_CSS}</style><div class=\"boxes\"></div>`;\n document.body.append(host);\n }\n // The panel, and its x-ray toggle, are for the whole page only\n const shadow = host.shadowRoot!;\n if (enabled && !shadow.querySelector('.panel')) {\n const panel = document.createElement('div');\n panel.className = 'panel';\n panel.innerHTML = `a-smart-skeleton debug <label><input type=\"checkbox\" class=\"xray\"> x-ray</label>`;\n panel.querySelector('.xray')!.addEventListener('change', (event) => {\n document.documentElement.toggleAttribute(\n ATTR_XRAY,\n (event.target as HTMLInputElement).checked\n );\n });\n shadow.append(panel);\n }\n if (!frame) frame = requestAnimationFrame(draw);\n}\n\nfunction stop() {\n host?.shadowRoot?.querySelector('.panel')?.remove();\n document.documentElement.removeAttribute(ATTR_XRAY);\n if ([...entries.keys()].some((reveal) => debugging(reveal))) return;\n cancelAnimationFrame(frame);\n frame = 0;\n host?.remove();\n host = null;\n}\n\nconst describe = ({ state, source, moved }: Entry) => {\n const from = source ? ` · ${source}` : '';\n if (state === 'loading') return { kind: 'loading', text: `skeleton${from}` };\n if (!moved || (moved.width === 0 && moved.height === 0)) {\n return { kind: 'still', text: `✓ no movement${from}` };\n }\n return {\n kind: 'moved',\n text: `✗ moved ${moved.width}×${moved.height}px${from}`,\n };\n};\n\n// Follows every tracked reveal each frame, so scrolling and layout never leave a box behind\nfunction draw() {\n frame = 0;\n if (!host?.shadowRoot) return;\n const boxes = host.shadowRoot.querySelector('.boxes')!;\n\n for (const reveal of entries.keys()) {\n if (!reveal.isConnected || !debugging(reveal)) entries.delete(reveal);\n }\n\n const items = [...entries];\n while (boxes.children.length > items.length) boxes.lastElementChild!.remove();\n items.forEach(([reveal, entry], index) => {\n let box = boxes.children[index] as HTMLElement | undefined;\n if (!box) {\n box = boxes.appendChild(document.createElement('div'));\n box.innerHTML = `<span class=\"label\"></span>`;\n }\n const rect = reveal.getBoundingClientRect();\n const { kind, text } = describe(entry);\n box.className = `box ${kind}`;\n Object.assign(box.style, {\n left: `${rect.left - 2}px`,\n top: `${rect.top - 2}px`,\n width: `${rect.width + 4}px`,\n height: `${rect.height + 4}px`,\n });\n box.firstElementChild!.textContent = text;\n });\n\n if (enabled || entries.size) frame = requestAnimationFrame(draw);\n}\n","let context: CanvasRenderingContext2D | null | undefined;\n\n// jsdom has no canvas, and logs an error for every context asked of it\nexport const textContext = () =>\n (context ??= /jsdom/.test(navigator.userAgent)\n ? null\n : document.createElement('canvas').getContext('2d'));\n","import { textContext } from './canvas';\nimport { ATTR_COVERED, MEDIA_TAGS } from './constants';\n\nconst MEDIA = new Set(MEDIA_TAGS);\nconst REMOVED = 'script, noscript, template, base, meta, link';\nconst REPLACED = new Set(['iframe', 'object', 'embed']);\nconst STRIPPED = new Set([\n 'src',\n 'srcset',\n 'sizes',\n 'poster',\n 'data',\n 'srcdoc',\n 'action',\n 'formaction',\n 'formtarget',\n 'background',\n 'ping',\n 'dynsrc',\n 'lowsrc',\n 'value',\n 'alt',\n ATTR_COVERED,\n]);\n\n// A style attribute saved from an unknown origin can carry `url(javascript:…)`,\n// `expression(…)` (legacy IE), or close the attribute to inject rules; drop the whole\n// attribute if any show up — `data:` URLs in CSS are left alone because they render\n// as images, not documents, and are a routine way to inline background art.\nconst STYLE_UNSAFE = /url\\s*\\(\\s*['\"]?\\s*(javascript|vbscript):|expression\\s*\\(|<|>/i;\n\nexport const fill = (value: string) =>\n value.replace(/[A-Z]/g, 'X').replace(/[a-z]/g, 'x').replace(/\\d/g, '0');\n\n// Filler has different glyphs to the text it replaces; letter-spacing makes up the difference, so it wraps the same\nfunction fillText(original: Text, copy: Text) {\n const filled = fill(copy.data);\n copy.data = filled;\n\n const parent = original.parentElement;\n const context = textContext();\n if (!parent || !context || !filled.trim()) return;\n\n const style = getComputedStyle(parent);\n context.font = `${style.fontStyle} ${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;\n const shape = (value: string) => {\n const collapsed = value.replace(/\\s+/g, ' ');\n if (style.textTransform === 'uppercase') return collapsed.toUpperCase();\n if (style.textTransform === 'lowercase') return collapsed.toLowerCase();\n return collapsed;\n };\n\n const target = context.measureText(shape(original.data)).width;\n const current = context.measureText(shape(filled)).width;\n const delta = (target - current) / shape(filled).length;\n if (Math.abs(delta) < 0.01) return;\n\n const span = document.createElement('span');\n span.style.letterSpacing = `${(parseFloat(style.letterSpacing) || 0) + delta}px`;\n copy.replaceWith(span);\n span.append(copy);\n}\n\nfunction sanitize(root: ParentNode) {\n for (const element of root.querySelectorAll(REMOVED)) element.remove();\n\n for (const element of root.querySelectorAll('*')) {\n if (REPLACED.has(element.localName)) {\n const stand = document.createElement('span');\n stand.style.cssText = element.getAttribute('style') ?? '';\n stand.style.display ||= 'inline-block';\n element.replaceWith(stand);\n continue;\n }\n\n for (const { name, value } of [...element.attributes]) {\n const lower = name.toLowerCase();\n const unsafe =\n lower.startsWith('on') ||\n STRIPPED.has(lower) ||\n (lower.endsWith('href') && /^\\s*(javascript|vbscript|data):/i.test(value)) ||\n (lower === 'style' && STYLE_UNSAFE.test(value));\n if (unsafe) element.removeAttribute(name);\n }\n\n if (element.localName === 'img') element.setAttribute('alt', '');\n }\n\n for (const source of root.querySelectorAll('video source, picture source')) {\n source.remove();\n }\n}\n\n/** The markup in `root`, safe to keep: no scripts, handlers or media sources; `filler` replaces its text too. */\nexport function serialize(root: HTMLElement, filler: boolean): string {\n const clone = root.cloneNode(true) as HTMLElement;\n const show = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT;\n const original = document.createTreeWalker(root, show);\n const copy = document.createTreeWalker(clone, show);\n\n const texts: [Text, Text][] = [];\n const media: [Element, HTMLElement][] = [];\n while (original.nextNode() && copy.nextNode()) {\n const a = original.currentNode;\n const b = copy.currentNode;\n if (a.nodeType === Node.TEXT_NODE) {\n if (filler) texts.push([a as Text, b as Text]);\n } else if (MEDIA.has((a as Element).localName) || REPLACED.has((a as Element).localName)) {\n media.push([a as Element, b as HTMLElement]);\n }\n }\n\n // Applied after the walk, which would lose its place in a tree changing under it\n for (const [a, b] of media) {\n const rect = a.getBoundingClientRect();\n b.style.boxSizing = 'border-box';\n b.style.width = `${rect.width}px`;\n if (rect.width && rect.height) {\n // Its proportions, not its pixels: restored somewhere narrower, it scales down as the real one would\n b.style.maxWidth = '100%';\n b.style.height = 'auto';\n b.style.aspectRatio = `${rect.width} / ${rect.height}`;\n } else {\n b.style.height = `${rect.height}px`;\n }\n }\n for (const [a, b] of texts) fillText(a, b);\n\n sanitize(clone);\n return clone.innerHTML;\n}\n\nexport function restore(html: string): DocumentFragment {\n const template = document.createElement('template');\n template.innerHTML = html;\n sanitize(template.content);\n return template.content;\n}\n\nconst signature = (element: Element, depth: number): string =>\n [...element.children]\n .map((child) => {\n const classes = [...child.classList].sort().join('.');\n const inner = depth > 1 && child.firstElementChild ? `(${signature(child, depth - 1)})` : '';\n return `${child.localName}${classes ? `.${classes}` : ''}${inner}`;\n })\n .join(',');\n\nconst hash = (value: string) => {\n let h = 5381;\n for (let i = 0; i < value.length; i++) h = (h * 33) ^ value.charCodeAt(i);\n return (h >>> 0).toString(36);\n};\n\n/** Identifies content by its page and the shape of its top two levels — the parts that rarely hang on data. */\nexport function autoKey(element: Element): string | null {\n const shape = signature(element, 2);\n return shape ? `${location.pathname}|${hash(shape)}` : null;\n}\n","import { fill } from './snapshot';\n\ndeclare const process: { env: { NODE_ENV?: string } };\n\nlet dev = false;\ntry {\n // Bundlers replace the whole expression; with none, `process` doesn't exist\n dev = process.env.NODE_ENV !== 'production';\n} catch {\n dev = false;\n}\n\nexport const isDev = dev;\n\nconst warned = new Set<string>();\n\nexport function warnOnce(id: string, message: string) {\n if (!isDev || warned.has(id)) return;\n warned.add(id);\n // eslint-disable-next-line no-console\n console.warn(`[a-smart-skeleton] ${message}`);\n}\n\nconst URL_LIKE = /^(https?:|\\/|data:|blob:)/;\n\n/**\n * Warns once per app if the page has a meta CSP that restricts inline scripts and\n * the consumer did not pass a nonce through the provider. Silent when CSP is absent\n * or when the loading pane isn't on the client yet — we can't read CSP headers from\n * script, so the meta-tag check is a best-effort signal to developers.\n */\nexport function checkNonce(nonce: string | undefined): void {\n if (!isDev || typeof document === 'undefined' || nonce) return;\n const meta = document.querySelector('meta[http-equiv=\"Content-Security-Policy\" i]');\n const content = meta?.getAttribute('content') ?? '';\n if (!/script-src/i.test(content)) return;\n if (/'unsafe-inline'/.test(content) || /\\*/.test(content)) return;\n warnOnce(\n 'csp:missing-nonce',\n 'ASmartSkeleton ships an inline boot script that measures the server-rendered skeleton before first paint. Your page has a Content-Security-Policy with script-src but no nonce was passed to <ASmartSkeletonProvider :nonce=\"…\">, so the browser will block it and first paint will be blank. Pass the same nonce you used for the response header.'\n );\n}\n\n/** Same keys and lengths as `data`, with every string replaced by filler. */\nexport function sampleFrom(data: unknown): unknown {\n if (typeof data === 'string') return URL_LIKE.test(data) ? '' : fill(data);\n if (Array.isArray(data)) return data.map(sampleFrom);\n if (data instanceof Date) return data;\n if (data && typeof data === 'object') {\n return Object.fromEntries(Object.entries(data).map(([key, value]) => [key, sampleFrom(value)]));\n }\n return data;\n}\n","import { textContext } from './canvas';\nimport {\n ATTR_BLOCK,\n ATTR_COVERED,\n ATTR_IGNORE,\n ATTR_OWN,\n MEDIA_TAGS,\n TEXT_TAGS,\n} from './constants';\n\n/** A box to draw, relative to the layer it was measured against. */\nexport type SkeletonRect = {\n x: number;\n y: number;\n width: number;\n height: number;\n radius: string;\n};\n\ntype Rect = { left: number; right: number; top: number; bottom: number };\n\n// Corner radii in px: top left, top right, bottom right, bottom left\ntype Corners = [number, number, number, number];\n\n// Overflow a box hides, which a bone must not paint past, with the corners it rounds; null while nothing clips\ntype Clip = (Rect & { corners: Corners }) | null;\n\nconst intersect = (clip: Clip, rect: Rect): Rect =>\n clip\n ? {\n left: Math.max(clip.left, rect.left),\n right: Math.min(clip.right, rect.right),\n top: Math.max(clip.top, rect.top),\n bottom: Math.min(clip.bottom, rect.bottom),\n }\n : rect;\n\nconst cornersOf = (rect: Rect): [number, number][] => [\n [rect.left, rect.top],\n [rect.right, rect.top],\n [rect.right, rect.bottom],\n [rect.left, rect.bottom],\n];\n\nconst near = (a: [number, number], b: [number, number]) =>\n Math.abs(a[0] - b[0]) < 1 && Math.abs(a[1] - b[1]) < 1;\n\nfunction radiiOf(style: CSSStyleDeclaration, rect: Rect): Corners {\n const size = Math.min(rect.right - rect.left, rect.bottom - rect.top);\n const px = (value: string) =>\n value.endsWith('%') ? (parseFloat(value) / 100) * size : parseFloat(value) || 0;\n return [\n px(style.borderTopLeftRadius),\n px(style.borderTopRightRadius),\n px(style.borderBottomRightRadius),\n px(style.borderBottomLeftRadius),\n ];\n}\n\n// A clip within a clip: each corner rounds as whichever box's corner it is\nfunction clipWithin(clip: Clip, rect: Rect, style: CSSStyleDeclaration): Clip {\n const box = intersect(clip, rect);\n const own = radiiOf(style, rect);\n const outer = clip ? cornersOf(clip) : [];\n const ownCorners = cornersOf(rect);\n const corners = cornersOf(box).map((corner, i) =>\n near(corner, ownCorners[i]!) ? own[i]! : clip && near(corner, outer[i]!) ? clip.corners[i]! : 0\n ) as Corners;\n // Sides by name: a DOMRect's are getters, which spreading leaves behind\n const { left, right, top, bottom } = box;\n return { left, right, top, bottom, corners };\n}\n\n// A block in a rounded corner of what clips it is cut by that corner, so takes it\nfunction roundedBy(clip: Clip, box: Rect, own: string, style: CSSStyleDeclaration) {\n if (!clip) return own;\n const clipCorners = cornersOf(clip);\n const touching = cornersOf(box).map(\n (corner, i) => clip.corners[i]! > 0 && near(corner, clipCorners[i]!)\n );\n if (!touching.some(Boolean)) return own;\n const mine = radiiOf(style, box);\n return touching\n .map((touches, i) => (touches ? Math.max(mine[i]!, clip.corners[i]!) : mine[i]!))\n .map((r) => `${r}px`)\n .join(' ');\n}\n\n// Clipped to a sliver, it isn't seen: a visually hidden label, say, cut to a 1px box\nconst clipped = (rect: Rect, clip: Clip): Rect | null => {\n const box = intersect(clip, rect);\n return box.right - box.left >= 2 && box.bottom - box.top >= 2 ? box : null;\n};\n\ntype Line = {\n left: number;\n right: number;\n top: number;\n bottom: number;\n fontSize: number;\n /** Where the bar goes, by the typography rules — within the line's box. */\n barTop: number;\n barBottom: number;\n /** The theme's `--ask-radius`, if it sets one. */\n radius: string;\n};\n\n/** The font line each line of text is drawn from. */\nexport type TextTop = 'ascender' | 'cap-height' | 'x-height';\n/** The font line each line of text is drawn down to. */\nexport type TextBottom = 'baseline' | 'descender';\n\nexport const DEFAULT_TEXT = {\n top: 'ascender',\n bottom: 'descender',\n} as const satisfies { top: TextTop; bottom: TextBottom };\n\ntype Metrics = {\n ascent: number; // the font's own box, above and below the baseline\n descent: number;\n ascender: number; // ink of b, d, h, l\n capHeight: number;\n xHeight: number;\n descender: number; // ink of g, p, y\n};\n\nconst metricsByFont = new Map<string, Metrics | null>();\n\n// A range has no layout in jsdom\nconst lineRects = (range: Range) => [...(range.getClientRects?.() ?? [])];\n\nfunction metricsOf(style: CSSStyleDeclaration): Metrics | null {\n const font = `${style.fontStyle} ${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;\n if (metricsByFont.has(font)) return metricsByFont.get(font)!;\n\n const context = textContext();\n let metrics: Metrics | null = null;\n if (context) {\n context.font = font;\n const box = context.measureText('H');\n const up = (text: string) => context!.measureText(text).actualBoundingBoxAscent;\n metrics = {\n ascent: box.fontBoundingBoxAscent,\n descent: box.fontBoundingBoxDescent,\n ascender: up('bdfhkl'),\n capHeight: box.actualBoundingBoxAscent,\n xHeight: up('xz'),\n descender: context.measureText('gjpqy').actualBoundingBoxDescent,\n };\n }\n metricsByFont.set(font, metrics);\n return metrics;\n}\n\nconst TOPS: Record<TextTop, keyof Metrics> = {\n ascender: 'ascender',\n 'cap-height': 'capHeight',\n 'x-height': 'xHeight',\n};\n\nconst rule = <T extends string>(\n style: CSSStyleDeclaration,\n name: string,\n allowed: readonly T[],\n fallback: T\n): T => {\n const value = style.getPropertyValue(name).trim() as T;\n return allowed.includes(value) ? value : fallback;\n};\n\n// Between the font lines `--ask-text-top` and `--ask-text-bottom` name, the baseline half-leading in\nfunction barOf(rect: Rect, style: CSSStyleDeclaration, fontSize: number) {\n const metrics = metricsOf(style);\n if (!metrics) {\n // No canvas to read the type with: a bar centred in the line\n const height = Math.min(fontSize * 0.72, rect.bottom - rect.top);\n const middle = (rect.top + rect.bottom) / 2;\n return { barTop: middle - height / 2, barBottom: middle + height / 2 };\n }\n\n const top = rule(style, '--ask-text-top', Object.keys(TOPS) as TextTop[], DEFAULT_TEXT.top);\n const bottom = rule(\n style,\n '--ask-text-bottom',\n ['baseline', 'descender'] as const,\n DEFAULT_TEXT.bottom\n );\n\n const box = metrics.ascent + metrics.descent;\n const baseline = rect.top + (rect.bottom - rect.top - box) / 2 + metrics.ascent;\n return {\n barTop: baseline - metrics[TOPS[top]],\n barBottom: baseline + (bottom === 'descender' ? metrics.descender : 0),\n };\n}\n\nconst MEDIA = new Set(MEDIA_TAGS);\nconst TEXT = new Set(TEXT_TAGS);\n\nconst LINE_GAP = 0.4; // of the font size — wider than a space, so one line of text stays one bar\n\n// matches a zero alpha in both `rgba(0, 0, 0, 0)` and `color(srgb 0 0 0 / 0)`\nconst TRANSPARENT = /[,/]\\s*0\\)$/;\n\n// Unset reads as \"\" outside a browser engine, which is no paint either\nconst isSet = (value: string, none: string) => value !== '' && value !== none;\n\n// All the way round: a rule along one side divides, it doesn't make a box a chip\nconst SIDES = ['Top', 'Right', 'Bottom', 'Left'] as const;\nconst bordered = (style: CSSStyleDeclaration) =>\n SIDES.every(\n (side) =>\n isSet(style[`border${side}Style`], 'none') && isSet(style[`border${side}Width`], '0px')\n );\n\n// An inset hairline along one side, drawn as a shadow, is a divider like a one-sided border\nconst isRule = (shadow: string) => {\n const [x = 0, y = 0, blur = 0, spread = 0] = (\n shadow.replace(/rgba?\\([^)]*\\)|#\\w+/g, '').match(/-?[\\d.]+px/g) ?? []\n ).map(parseFloat);\n return (\n shadow.includes('inset') && !blur && !spread && (x === 0) !== (y === 0) && Math.abs(x + y) <= 2\n );\n};\n\nconst shadowPaints = (boxShadow: string) =>\n isSet(boxShadow, 'none') && !boxShadow.split(/,(?![^(]*\\))/).every(isRule);\n\nconst isPainted = (style: CSSStyleDeclaration) =>\n (isSet(style.backgroundColor, 'transparent') && !TRANSPARENT.test(style.backgroundColor)) ||\n isSet(style.backgroundImage, 'none') ||\n shadowPaints(style.boxShadow) ||\n bordered(style);\n\nconst isMedia = (element: Element) => MEDIA.has(element.localName);\n\nconst isEmptyText = (element: Element) =>\n TEXT.has(element.localName) && !element.firstElementChild && !element.textContent?.trim();\n\n/** Labels inside: one per piece of text, however many lines it wraps to or nodes it's split into. */\nconst countLabels = (element: Element) => {\n const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT);\n const range = document.createRange();\n const pieces: DOMRect[][] = [];\n let nodes = 0;\n while (walker.nextNode()) {\n const node = walker.currentNode;\n if (node.nodeType === Node.TEXT_NODE) {\n const parent = node.parentElement;\n if (!node.textContent?.trim() || !parent) continue;\n nodes++;\n // Visually hidden text, read to screen readers only\n const box = parent.getBoundingClientRect();\n if (box.width <= 1 || box.height <= 1) continue;\n range.selectNodeContents(node);\n pieces.push(lineRects(range).filter((r) => r.width || r.height));\n } else if (isEmptyText(node as Element)) {\n nodes++;\n pieces.push([...(node as Element).getClientRects()]);\n }\n }\n // No layout to go by\n if (!pieces.some((rects) => rects.length)) return nodes;\n\n const reach = (parseFloat(getComputedStyle(element).fontSize) || 16) * LINE_GAP;\n const beside = (a: DOMRect, b: DOMRect) =>\n Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top) >= Math.min(a.height, b.height) / 2 &&\n Math.max(a.left, b.left) - Math.min(a.right, b.right) <= reach;\n\n // Pieces joined into labels: each starts as its own, and merges with any beside it\n const label = pieces.map((_, i) => i);\n const find = (i: number): number => (label[i] === i ? i : (label[i] = find(label[i]!)));\n for (let i = 0; i < pieces.length; i++) {\n for (let j = i + 1; j < pieces.length; j++) {\n if (pieces[i]!.some((a) => pieces[j]!.some((b) => beside(a, b)))) {\n label[find(j)] = find(i);\n }\n }\n }\n return new Set(pieces.map((_, i) => find(i))).size;\n};\n\n// A painted box around one label (a button, a chip) fills as a block, a card keeps its surface\nconst isBlock = (element: Element, style: CSSStyleDeclaration) =>\n element.hasAttribute(ATTR_BLOCK) ||\n isMedia(element) ||\n (isPainted(style) && countLabels(element) <= 1);\n\n// Media clipped by a rounded parent of the same size, like an avatar, takes the parent's corners\nfunction radiusOf(element: Element, style: CSSStyleDeclaration) {\n if (parseFloat(style.borderRadius) || !element.parentElement) {\n return style.borderRadius || '0px';\n }\n const parent = element.parentElement;\n const parentStyle = getComputedStyle(parent);\n const a = element.getBoundingClientRect();\n const b = parent.getBoundingClientRect();\n const same = Math.abs(a.width - b.width) < 1 && Math.abs(a.height - b.height) < 1;\n return same && parentStyle.overflow !== 'visible'\n ? parentStyle.borderRadius\n : style.borderRadius || '0px';\n}\n\nfunction toBars(lines: Line[]): SkeletonRect[] {\n // Left to right, so each fragment only ever extends a bar to its left\n lines.sort((a, b) => a.left - b.left);\n\n const merged: Line[] = [];\n for (const line of lines) {\n const last = merged.find((m) => {\n const overlap = Math.min(m.bottom, line.bottom) - Math.max(m.top, line.top);\n const shorter = Math.min(m.bottom - m.top, line.bottom - line.top);\n const gap = line.left - m.right;\n return overlap >= shorter / 2 && gap <= Math.max(m.fontSize, line.fontSize) * LINE_GAP;\n });\n\n if (last) {\n last.left = Math.min(last.left, line.left);\n last.right = Math.max(last.right, line.right);\n last.top = Math.min(last.top, line.top);\n last.bottom = Math.max(last.bottom, line.bottom);\n last.fontSize = Math.max(last.fontSize, line.fontSize);\n last.barTop = Math.min(last.barTop, line.barTop);\n last.barBottom = Math.max(last.barBottom, line.barBottom);\n } else {\n merged.push({ ...line });\n }\n }\n\n return merged.map((line) => {\n const height = line.barBottom - line.barTop;\n return {\n x: line.left,\n y: line.barTop,\n width: line.right - line.left,\n height,\n radius: line.radius || `${Math.round(height / 3)}px`,\n };\n });\n}\n\n/** Measures what `root` holds into rects relative to `layer`; without `mark`, `root` is left untouched. */\nexport function measureSkeleton(\n root: HTMLElement,\n layer: HTMLElement,\n {\n mark = true,\n onCovered,\n }: {\n mark?: boolean;\n /** What's drawn as one block, its own paint to hide — for a caller that can't mark it. */\n onCovered?: (covered: Set<Element>) => void;\n } = {}\n): SkeletonRect[] {\n const origin = layer.getBoundingClientRect();\n // Rects are post-transform; bones are drawn inside the same transform\n const scaleX = layer.offsetWidth ? origin.width / layer.offsetWidth : 1;\n const scaleY = layer.offsetHeight ? origin.height / layer.offsetHeight : 1;\n\n const local = (rect: Rect) => ({\n left: (rect.left - origin.left) / scaleX,\n right: (rect.right - origin.left) / scaleX,\n top: (rect.top - origin.top) / scaleY,\n bottom: (rect.bottom - origin.top) / scaleY,\n });\n\n const blocks: SkeletonRect[] = [];\n const lines: Line[] = [];\n const covered = new Set<Element>();\n const range = document.createRange();\n\n const addLine = (rect: DOMRect, style: CSSStyleDeclaration, clip: Clip) => {\n const box = clipped(rect, clip);\n if (!box) return;\n const fontSize = parseFloat(style.fontSize) || 16;\n const line = local(box);\n lines.push({\n ...line,\n fontSize,\n ...barOf(line, style, fontSize),\n radius: style.getPropertyValue('--ask-radius').trim(),\n });\n };\n\n const addText = (node: Text, clip: Clip) => {\n const start = node.data.search(/\\S/);\n if (start < 0 || !node.parentElement) return;\n range.setStart(node, start);\n range.setEnd(node, node.data.trimEnd().length);\n const style = getComputedStyle(node.parentElement);\n for (const rect of lineRects(range)) addLine(rect, style, clip);\n };\n\n const visit = (parent: Element, clip: Clip) => {\n for (const node of parent.childNodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n addText(node as Text, clip);\n continue;\n }\n if (node.nodeType !== Node.ELEMENT_NODE) continue;\n\n const element = node as Element;\n if (element.hasAttribute(ATTR_IGNORE) || element.hasAttribute(ATTR_OWN)) {\n continue;\n }\n\n const style = getComputedStyle(element);\n if (style.display === 'none') continue;\n\n if (isBlock(element, style)) {\n const visible = clipped(element.getBoundingClientRect(), clip);\n if (visible) {\n const box = local(visible);\n blocks.push({\n x: box.left,\n y: box.top,\n width: box.right - box.left,\n height: box.bottom - box.top,\n radius: roundedBy(clip, visible, radiusOf(element, style), style),\n });\n }\n if (!isMedia(element)) covered.add(element);\n continue;\n }\n\n if (isEmptyText(element)) {\n for (const rect of element.getClientRects()) {\n addLine(rect, style, clip);\n }\n continue;\n }\n\n const clips = style.overflowX !== 'visible' || style.overflowY !== 'visible';\n visit(element, clips ? clipWithin(clip, element.getBoundingClientRect(), style) : clip);\n }\n };\n\n visit(root, null);\n onCovered?.(covered);\n\n if (!mark) return [...blocks, ...toBars(lines)];\n\n // Only touched when they change, so a MutationObserver watching `root` settles\n for (const element of root.querySelectorAll(`[${ATTR_COVERED}]`)) {\n if (!covered.has(element)) element.removeAttribute(ATTR_COVERED);\n }\n for (const element of covered) {\n if (!element.hasAttribute(ATTR_COVERED)) {\n element.setAttribute(ATTR_COVERED, '');\n }\n }\n\n return [...blocks, ...toBars(lines)];\n}\n","const prefers = (query: string) => typeof matchMedia !== 'undefined' && matchMedia(query).matches;\n\n// Not in jsdom, where every fade is instant\nexport const canAnimate = () =>\n typeof Element !== 'undefined' && typeof Element.prototype.animate === 'function';\n\nexport const prefersReducedMotion = () =>\n !canAnimate() || prefers('(prefers-reduced-motion: reduce)');\n\nexport const prefersReducedTransparency = () => prefers('(prefers-reduced-transparency: reduce)');\n\nexport const animationsOf = (element: Element): Animation[] => element.getAnimations?.() ?? [];\n","import { ATTR_RECT, BASE, DURATIONS, HIGHLIGHT } from './constants';\nimport type { SkeletonAnimation, SkeletonSpeed } from './theme';\nimport { animationsOf, prefersReducedMotion } from './motion';\nimport type { SkeletonRect } from './measure';\n\nconst SWEEP = 0.7; // of a duration a sweep takes at the reference width — sweeps run back to back, so this sets the pace\nconst REFERENCE_WIDTH = 1280; // A shimmer's duration is one loop across this; any other width keeps its pace\nconst MAX_BAND = 320; // The highlight's width, so it doesn't grow heavier on a wide screen\nconst SPACING = 2.5; // bands follow each other this many band-widths apart, start to start — the gap between sweeps\nconst PULSE_LOW = 0.45; // opacity at the bottom of a pulse\n\nconst ANIMATIONS: readonly SkeletonAnimation[] = ['shimmer', 'group-shimmer', 'pulse', 'none'];\n\nexport type Motion = { animation: SkeletonAnimation; duration: number };\n\n/** The animation an element inherits from the theme: `--ask-animation` and `--ask-speed`. */\nexport function motionOf(element: Element): Motion {\n const style = getComputedStyle(element);\n const read = <T extends string>(name: string, allowed: readonly T[], fallback: T): T => {\n const value = style.getPropertyValue(name).trim() as T;\n return allowed.includes(value) ? value : fallback;\n };\n const animation = read('--ask-animation', ANIMATIONS, 'shimmer');\n const speed = read<SkeletonSpeed>('--ask-speed', ['slow', 'fast'], 'slow');\n return {\n animation,\n duration: DURATIONS[animation === 'pulse' ? 'pulse' : 'shimmer'][speed],\n };\n}\n\ntype Span = { left: number; top: number; width: number; height: number };\n\nconst SLANT = 20; // degrees from vertical: the highlight is a diagonal, top right to bottom left\nconst SIN = Math.sin((SLANT * Math.PI) / 180);\nconst COS = Math.cos((SLANT * Math.PI) / 180);\nexport const SLANT_TAN = SIN / COS;\nexport const SLANT_COS = COS;\nexport const SLANT_ANGLE = `${90 + SLANT}deg`;\nexport const PEAK = 0.85; // Where across the band the highlight is brightest: 0 → PEAK eases up, PEAK → 1 eases down — later is a harder leading edge\nexport const STEPS = 12; // stops per ramp — enough for an eased curve to read as one, with no banding\n\n// Every gradient ramps on this (a scrim), so no stop shows as a hard line\nexport const ease = (t: number) => (1 - Math.cos(Math.PI * t)) / 2;\n\n/** Highlights `SPACING` band-widths apart, in px from the box's corner, so every rect draws the same stream. */\nfunction highlights(band: number) {\n const period = band * SPACING;\n const stop = (at: number, alpha: number) =>\n `color-mix(in srgb, ${HIGHLIGHT} ${(alpha * 100).toFixed(1)}%, transparent) ${(at * band).toFixed(2)}px`;\n const stops: string[] = [];\n for (let i = 0; i <= STEPS; i++) stops.push(stop((i / STEPS) * PEAK, ease(i / STEPS)));\n for (let i = 1; i <= STEPS; i++) {\n stops.push(stop(PEAK + (i / STEPS) * (1 - PEAK), ease(1 - i / STEPS)));\n }\n\n return {\n // Across, the stream repeats every `period` along the slant\n width: period / COS,\n image: `repeating-linear-gradient(${SLANT_ANGLE}, ${stops.join(', ')}, transparent ${period.toFixed(2)}px)`,\n };\n}\n\n/** Animates `element` as its slice of one sweep, on the document clock, so however late it mounts it joins the sweep under way. */\nexport function shimmer(element: HTMLElement, group?: Span, motion: Motion = motionOf(element)) {\n for (const animation of animationsOf(element)) animation.cancel();\n element.style.backgroundImage = '';\n element.style.backgroundRepeat = '';\n if (prefersReducedMotion() || typeof element.animate !== 'function') return;\n if (motion.animation === 'none') return;\n\n const timing = { duration: motion.duration, iterations: Infinity };\n\n if (motion.animation === 'pulse') {\n element.animate(\n [\n { opacity: 1, easing: 'ease-in-out' },\n { opacity: PULSE_LOW, easing: 'ease-in-out' },\n { opacity: 1 },\n ],\n timing\n ).startTime = 0;\n return;\n }\n\n const rect = element.getBoundingClientRect();\n const x = rect.left + scrollX;\n const area: Span =\n motion.animation === 'group-shimmer'\n ? (group ?? {\n left: x,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n })\n : {\n left: 0,\n top: 0,\n width: document.documentElement.clientWidth || innerWidth,\n height: innerHeight,\n };\n const band = Math.min(Math.max(area.width * 0.4, 80), MAX_BAND);\n const { width: tile, image } = highlights(band);\n\n // Where this bone sits in the area's one stream: further right, and lower down the slant, is further along it\n const along = x - area.left + (rect.top - area.top) * SLANT_TAN;\n // One pace on any screen, as a sweep across the reference width took\n const pace = (motion.duration * SWEEP) / (REFERENCE_WIDTH + MAX_BAND);\n\n element.style.backgroundImage = image;\n element.style.backgroundSize = `${tile}px 100%`;\n element.style.backgroundRepeat = 'repeat-x';\n element.animate(\n [{ backgroundPosition: `${-along}px 0` }, { backgroundPosition: `${tile - along}px 0` }],\n { duration: tile * pace, iterations: Infinity }\n ).startTime = 0;\n}\n\n/** ms per px of the band in `element`'s shimmer; null when it has no band. */\nexport function paceOf(element: Element): number | null {\n if (prefersReducedMotion()) return null;\n const motion = motionOf(element);\n if (motion.animation !== 'shimmer' && motion.animation !== 'group-shimmer') return null;\n return (motion.duration * SWEEP) / (REFERENCE_WIDTH + MAX_BAND);\n}\n\n// In a shadow root, so a framework hydrating `layer` never meets bones it didn't render\nconst shadow = (layer: HTMLElement) => layer.shadowRoot ?? layer.attachShadow({ mode: 'open' });\n\n/** The rect elements drawn into `layer`. */\nexport const rectsOf = (layer: Element): HTMLElement[] =>\n layer.shadowRoot ? ([...layer.shadowRoot.children] as HTMLElement[]) : [];\n\n/** Draws `rects` into `layer`, reusing the elements already there. */\nexport function drawSkeleton(layer: HTMLElement, rects: SkeletonRect[]) {\n const root = shadow(layer);\n const rect = layer.getBoundingClientRect();\n const group = {\n left: rect.left + scrollX,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n };\n // Read once for the layer: every rect in it inherits the same theme\n const motion = motionOf(layer);\n\n rects.forEach((part, index) => {\n let element = root.children[index] as HTMLElement | undefined;\n if (!element) {\n element = document.createElement('div');\n element.setAttribute(ATTR_RECT, '');\n // Inline: no page stylesheet reaches into the shadow root\n element.style.cssText = `position:absolute;display:block;pointer-events:none;background-color:${BASE};background-repeat:no-repeat`;\n root.append(element);\n }\n\n Object.assign(element.style, {\n left: `${part.x}px`,\n top: `${part.y}px`,\n width: `${part.width}px`,\n height: `${part.height}px`,\n borderRadius: part.radius,\n });\n\n // Restarted only when its place, group, the page's width or the motion changes\n const key = `${Math.round(group.left + part.x)}|${Math.round(part.y)}|${Math.round(part.height)}|${Math.round(group.left)}|${Math.round(group.width)}|${Math.round(group.height)}|${document.documentElement.clientWidth}|${motion.animation}|${motion.duration}`;\n if (element.dataset.motion !== key) {\n element.dataset.motion = key;\n shimmer(element, group, motion);\n }\n });\n\n while (root.children.length > rects.length) root.lastElementChild!.remove();\n}\n","import { ATTR_EXITING, CASCADE_SPREAD, FADE_DURATION } from './constants';\n\n/** Where one piece of a reveal sits: a piece of content arriving, or a rect of the skeleton leaving. */\nexport type Piece = {\n rect: DOMRect;\n /** Its row or card: the nearest ancestor with two or more siblings like it. Null for a rect outside any. */\n unit: DOMRect | null;\n /** Smaller text than the largest in its unit. */\n secondary: boolean;\n /** The whole reveal. */\n reveal: DOMRect;\n /** ms since the first of the reveals landing alongside this one. */\n late: number;\n};\n\n/** What a reveal knows as its content lands, for `choose`. */\nexport type RevealContext = {\n content: HTMLElement;\n reveal: HTMLElement;\n /** ms the skeleton was up; Infinity when it was server-rendered or there was none. */\n waited: number;\n /** Someone scrolled or typed in the last 400ms. */\n input: boolean;\n /** The skeleton was drawn from the data on screen. */\n refetch: boolean;\n height: number;\n /** How many pieces the content arrives in. */\n pieces: number;\n};\n\n/** One pane under a wipe: `rect` is its own box, `reveal` the box the front crosses, both in viewport px. */\nexport type WipePane = { rect: DOMRect; reveal: DOMRect };\n\n/** A front crossing the whole reveal, as a mask drawn each frame. */\nexport type Wipe = {\n /** The incoming pane's `mask-image` at `progress`, 0 to 1. */\n mask: (progress: number, pane: WipePane) => string;\n /** The outgoing pane's; the inverse of `mask` when left out. */\n out?: (progress: number, pane: WipePane) => string;\n /** Runs once on the incoming pane; `progress` keeps counting past 1. */\n effect?: (element: HTMLElement, front: WipePane & { progress: () => number }) => void;\n};\n\n/** How content replaces its skeleton; what `choose` returns as content lands wins over the fields beside it. */\nexport type RevealSpec = {\n order?: 'together' | ((piece: Piece) => number | null);\n /** Where each piece starts from, on top of the fade: `{ filter: \"blur(6px)\" }`. */\n enter?: Keyframe;\n wipe?: Wipe;\n delay?: number;\n /** 0 is instant. */\n duration?: number;\n /** ms a skeleton waits before it shows, so data that beats it never shows one. */\n hold?: number;\n choose?: (context: RevealContext) => RevealSpec;\n};\n\n/** A built-in reveal by name, or one of your own. */\nexport type RevealMode = 'together' | 'sequence' | 'smart' | 'sweep' | RevealSpec;\n\nexport const SKELETON_DELAY = 150; // A skeleton up for less than this is a flash — smart holds it back\nconst QUICK_FADE = 120; // A refetch, already familiar\nconst SMALL_HEIGHT = 72;\nconst SMALL_PIECES = 3;\nconst SECONDARY_DELAY = 60; // Smaller text follows the text it sits under\nexport const BATCH_WINDOW = 150; // Reveals landing this close share one top-to-bottom order\nconst ACTIVE_WINDOW = 400; // Input this recent means someone is mid-gesture\nexport const MAX_SWEEP_AREA = 1.5; // in screens — a wipe bigger than this crossfades: a front across it is mostly off screen, and costly\nexport const MAX_DELAY = 1000; // A custom order's latest piece\nexport const MAX_DURATION = 1000;\n\n// What `enter` may set: nothing that changes layout, so no reveal moves the page\nconst ENTER = new Set([\n 'filter',\n 'transform',\n 'translate',\n 'scale',\n 'rotate',\n 'clipPath',\n 'easing',\n 'composite',\n]);\n\nexport type SequencePlan = {\n kind: 'sequence';\n /** When a piece of content appears; null to appear at once. */\n pieceDelay: (piece: Element) => number | null;\n /** When a skeleton rect at `rect` goes; null to go at once. */\n boneDelay: (rect: DOMRect) => number | null;\n duration: number;\n enter?: Keyframe;\n};\n\nexport type WipePlan = {\n kind: 'wipe';\n wipe: Wipe;\n /** performance.now() at progress 0. */\n start: number;\n duration: number;\n reveal: DOMRect;\n enter?: Keyframe;\n /** Set when frames drop mid-wipe: both panes finish as a crossfade instead. */\n stalled?: boolean;\n};\n\nexport type Plan =\n | { kind: 'instant' }\n | { kind: 'together'; delay: number; duration: number; enter?: Keyframe }\n | SequencePlan\n | WipePlan;\n\n// Input, not scroll: a page restoring its scroll position isn't someone using it. No clicks: a click doesn't move what's being read\nlet lastInput = -Infinity;\nlet listening = false;\nfunction listen() {\n if (listening || typeof addEventListener === 'undefined') return;\n listening = true;\n for (const type of ['wheel', 'touchmove', 'keydown']) {\n addEventListener(type, () => (lastInput = performance.now()), {\n passive: true,\n capture: true,\n });\n }\n}\n\nconst loading = new WeakMap<Element, { since: number; refetch: boolean }>();\n\n/** Notes a skeleton going up in `reveal` — when, and whether it's a refetch over the data on screen. */\nexport function noteSkeleton(\n reveal: Element,\n { served, refetch }: { served: boolean; refetch: boolean }\n) {\n listen();\n const since = loading.get(reveal)?.since ?? performance.now();\n // Server-rendered: up since the page began, so never a flash\n loading.set(reveal, { since: served ? -Infinity : since, refetch });\n}\n\n// What a reveal brings in one by one: anything holding text or media of its own\nexport function pieces(root: Element): Element[] {\n const found: Element[] = [];\n const visit = (element: Element) => {\n for (const child of element.children) {\n const ownText = [...child.childNodes].some(\n (node) => node.nodeType === Node.TEXT_NODE && node.textContent?.trim()\n );\n if (!child.firstElementChild || ownText || child.localName === 'svg') {\n found.push(child);\n } else {\n visit(child);\n }\n }\n };\n visit(root);\n return found;\n}\n\n// A row of a list or a card of a grid: the piece's nearest ancestor with two or more siblings like it\nfunction unitOf(piece: Element, root: Element): Element {\n for (\n let element: Element | null = piece;\n element && element !== root;\n element = element.parentElement\n ) {\n const parent = element.parentElement;\n if (!parent) break;\n const alike = [...parent.children].filter(\n (sibling) =>\n sibling.localName === element!.localName && sibling.className === element!.className\n );\n if (alike.length >= 3) return element;\n }\n return piece;\n}\n\nconst contains = (outer: DOMRect, inner: DOMRect) => {\n const x = inner.left + inner.width / 2;\n const y = inner.top + inner.height / 2;\n return x >= outer.left && x <= outer.right && y >= outer.top && y <= outer.bottom;\n};\n\n/** The box a wipe crosses: the reveal, and any pane leaving it that stands taller or wider. */\nexport function revealBox(root: Element): DOMRect {\n let { left, top, right, bottom } = root.getBoundingClientRect();\n for (const pane of root.querySelectorAll(`:scope > [${ATTR_EXITING}]`)) {\n const rect = pane.getBoundingClientRect();\n left = Math.min(left, rect.left);\n top = Math.min(top, rect.top);\n right = Math.max(right, rect.right);\n bottom = Math.max(bottom, rect.bottom);\n }\n return new DOMRect(left, top, right - left, bottom - top);\n}\n\nconst clamp = (value: number, max: number) => Math.min(Math.max(value, 0), max);\n\nlet batch = -Infinity;\n\n/** Times each piece of `content`, and each skeleton rect it replaces, by `order`. */\nfunction sequencePlan(\n content: Element,\n root: Element,\n order: (piece: Piece) => number | null,\n spec: RevealSpec,\n duration: number\n): SequencePlan {\n const now = performance.now();\n if (now - batch > BATCH_WINDOW) batch = now;\n const late = now - batch;\n const reveal = root.getBoundingClientRect();\n\n type Unit = { rect: DOMRect; size: number };\n const units = new Map<Element, Unit>();\n const found = new Map<Element, { unit: Unit; size: number }>();\n const sizeOf = (element: Element) => parseFloat(getComputedStyle(element).fontSize) || 16;\n\n for (const piece of pieces(content)) {\n const element = unitOf(piece, content);\n let unit = units.get(element);\n if (!unit) {\n unit = { rect: element.getBoundingClientRect(), size: 0 };\n units.set(element, unit);\n }\n const size = sizeOf(piece);\n unit.size = Math.max(unit.size, size);\n found.set(piece, { unit, size });\n }\n\n const at = (piece: Piece) => {\n const delay = order(piece);\n return delay === null ? null : clamp(delay, MAX_DELAY) + Math.max(spec.delay ?? 0, 0);\n };\n\n return {\n kind: 'sequence',\n duration,\n enter: spec.enter,\n pieceDelay: (element) => {\n const piece = found.get(element);\n if (!piece) return null;\n return at({\n rect: element.getBoundingClientRect(),\n unit: piece.unit.rect,\n secondary: piece.size < piece.unit.size,\n reveal,\n late,\n });\n },\n boneDelay: (rect) => {\n const unit = [...units.values()].find((unit) => contains(unit.rect, rect));\n return at({\n rect,\n unit: unit?.rect ?? null,\n // A bar shorter than its row's largest type stands for smaller text\n secondary: !!unit && rect.height < unit.size * 0.8,\n reveal,\n late,\n });\n },\n };\n}\n\n/** Keeps `enter` to what paints, warning in development about anything that would move the page. */\nfunction enterOf(enter: Keyframe | undefined, warn: (key: string) => void) {\n if (!enter) return undefined;\n const kept: Keyframe = {};\n for (const [key, value] of Object.entries(enter)) {\n if (ENTER.has(key)) kept[key] = value;\n else if (key !== 'opacity') warn(key);\n }\n return kept;\n}\n\n/** Decides how `content` replaces the skeleton in `root`, now that it has arrived. */\nexport function planReveal(\n content: HTMLElement,\n root: HTMLElement,\n reveal: RevealSpec,\n warn: (key: string) => void = () => {}\n): Plan {\n const info = loading.get(root);\n loading.delete(root);\n\n let spec = reveal;\n while (spec.choose) {\n const { choose, ...rest } = spec;\n spec = {\n ...rest,\n ...choose({\n content,\n reveal: root,\n waited: info ? performance.now() - info.since : Infinity,\n input: performance.now() - lastInput < ACTIVE_WINDOW,\n refetch: !!info?.refetch,\n height: content.getBoundingClientRect().height,\n pieces: pieces(content).length,\n }),\n };\n }\n\n const duration = clamp(spec.duration ?? FADE_DURATION, MAX_DURATION);\n // No floor: a wipe joining one under way starts partway, before now\n spec = { ...spec, delay: Math.min(spec.delay ?? 0, MAX_DELAY) };\n if (!duration) return { kind: 'instant' };\n const enter = enterOf(spec.enter, warn);\n\n if (spec.wipe) {\n const rect = revealBox(root);\n if (rect.width * rect.height <= innerWidth * innerHeight * MAX_SWEEP_AREA) {\n return {\n kind: 'wipe',\n wipe: spec.wipe,\n start: performance.now() + (spec.delay ?? 0),\n duration,\n reveal: rect,\n enter,\n };\n }\n } else if (typeof spec.order === 'function') {\n return sequencePlan(content, root, spec.order, { ...spec, enter }, duration);\n }\n return {\n kind: 'together',\n delay: Math.max(spec.delay ?? 0, 0),\n duration,\n enter,\n };\n}\n\n/** `sequence`: each piece timed by its place in the reveal, top to bottom, then a little left to right. */\nexport const byPosition = ({ rect, reveal }: Piece) => {\n const down = (rect.top - reveal.top) / Math.max(reveal.height, 1);\n const across = (rect.left - reveal.left) / Math.max(reveal.width, 1);\n return clamp(down * 0.8 + across * 0.2, 1) * CASCADE_SPREAD;\n};\n\nconst onScreen = (rect: DOMRect) => rect.bottom > 0 && rect.top < innerHeight;\n\n/** `smart`'s order: rows arrive whole, in page order, on screen only, main text first. */\nexport const byRow = ({ rect, unit, secondary, late }: Piece) => {\n if (!unit) return onScreen(rect) ? 0 : null;\n if (!onScreen(unit)) return null;\n // Timed against the screen, not the reveal, so reveals landing together read as one page\n const at = clamp(unit.top / innerHeight, 1) * CASCADE_SPREAD;\n return Math.max(at - late, 0) + (secondary ? SECONDARY_DELAY : 0);\n};\n\nexport const instant: RevealSpec = { duration: 0 };\nexport const together: RevealSpec = { order: 'together' };\nexport const sequence: RevealSpec = { order: byPosition };\n\n/** The cases `smart` settles before looking at the content: instant, or a quick crossfade. */\nexport const quickly = (context: RevealContext): RevealSpec | null =>\n context.input || context.waited < SKELETON_DELAY\n ? instant\n : context.refetch\n ? { order: 'together', duration: QUICK_FADE }\n : null;\n\n/** `together` for a small reveal, else `byRow`. */\nexport const byContent = (context: RevealContext): RevealSpec =>\n context.height < SMALL_HEIGHT || context.pieces <= SMALL_PIECES ? together : { order: byRow };\n\n/** Picks for each reveal from how it loaded and what it holds, holding its skeleton back a moment. */\nexport const smart: RevealSpec = {\n hold: SKELETON_DELAY,\n choose: (context) => quickly(context) ?? byContent(context),\n};\n","import { serialize } from './snapshot';\n\nconst STORAGE_KEY = 'a-smart-skeleton:shapes';\nconst VERSION = 2; // Bumped whenever the stored markup changes meaning\nconst MAX_SHAPES = 50;\nconst MAX_LENGTH = 20_000;\n\ntype Stored = Record<string, string>; // Oldest first\n\n// Real text, kept in memory only — exact for a reload within the same visit\nconst session = new Map<string, string>();\nconst shown = new Map<string, Set<() => void>>();\n\n/** Registers a save for content on screen under `key`; returns its unregister. */\nexport function trackShape(key: string, save: () => void) {\n if (!shown.has(key)) shown.set(key, new Set());\n shown.get(key)!.add(save);\n return () => shown.get(key)?.delete(save);\n}\n\n/** Saves every shown copy of `key` now, so a skeleton about to recall it gets the latest. */\nexport function flushShapes(key: string) {\n for (const save of shown.get(key) ?? []) save();\n}\n\n// Treats anything parsed from localStorage as hostile: must be the expected envelope,\n// `shapes` must be a plain string-to-string dictionary, and the output is a null-prototype\n// object so no later lookup can be confused by an inherited key.\nfunction read(): Stored {\n try {\n const raw = JSON.parse(localStorage.getItem(STORAGE_KEY) ?? 'null');\n if (!raw || typeof raw !== 'object' || raw.v !== VERSION) return Object.create(null);\n const incoming = raw.shapes;\n if (!incoming || typeof incoming !== 'object') return Object.create(null);\n const out: Stored = Object.create(null);\n for (const key of Object.keys(incoming)) {\n const value = (incoming as Record<string, unknown>)[key];\n if (typeof value === 'string') out[key] = value;\n }\n return out;\n } catch {\n return Object.create(null);\n }\n}\n\nfunction write(shapes: Stored) {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify({ v: VERSION, shapes }));\n } catch {\n // Storage full or blocked; the session copy still covers this visit\n }\n}\n\nexport function rememberShape(key: string, element: HTMLElement) {\n session.set(key, serialize(element, false));\n\n const html = serialize(element, true);\n if (html.length > MAX_LENGTH) return;\n\n const shapes = read();\n // Re-inserted so it moves to the end: key order is recency\n delete shapes[key];\n shapes[key] = html;\n const keys = Object.keys(shapes);\n for (const stale of keys.slice(0, keys.length - MAX_SHAPES)) {\n delete shapes[stale];\n }\n write(shapes);\n}\n\nexport function recallShape(key: string): string | null {\n return session.get(key) ?? read()[key] ?? null;\n}\n\n/** Forgets remembered shapes — call it on sign-out. */\nexport function forgetShapes({ persisted = true } = {}) {\n session.clear();\n if (!persisted) return;\n try {\n localStorage.removeItem(STORAGE_KEY);\n } catch {\n // Nothing stored to forget\n }\n}\n","import {\n ATTR_BLOCK,\n ATTR_LAYER,\n ATTR_EXITING,\n ATTR_GHOST,\n ATTR_INACTIVE,\n ATTR_LOADING,\n ATTR_OWN,\n ATTR_REVEAL,\n ATTR_SNAPSHOT,\n GHOSTED,\n UNCOVER,\n} from './constants';\nimport { reportLoading } from './debug';\nimport { noteSkeleton } from './plan';\nimport { warnOnce } from './dev';\nimport { measureSkeleton } from './measure';\nimport { flushShapes, recallShape } from './shapes';\nimport { drawSkeleton } from './shimmer';\nimport { autoKey, restore } from './snapshot';\nimport { addStyles, removeStyles } from './styles';\n\nexport type GhostOptions = {\n /** Remembers the shape under this key; without it, one is derived from the markup. */\n id?: string;\n /** The ghost was rendered from real data, so it beats any remembered shape. */\n exact?: boolean;\n /** Its data is still set: a refetch over what's on screen, not a new load. */\n refetch?: boolean;\n};\n\ntype Source = 'ghost' | 'recall' | 'fallback';\n\nconst FALLBACK = [100, 90, 60]\n .map(\n (width) =>\n `<div ${ATTR_BLOCK} style=\"width:${width}%;height:0.75em;margin:0.5em 0;border-radius:0.25em\"></div>`\n )\n .join('');\n\n// In the document before any script ran: server-rendered, so already painted at the shape it has\nconst served = new WeakSet<Element>(\n typeof document === 'undefined' ? [] : document.querySelectorAll(`[${ATTR_LOADING}]`)\n);\n\nconst loadingSizes = new WeakMap<\n Element,\n {\n width: number;\n height: number;\n guessed: boolean;\n /** Each image's height in the skeleton, in document order — 0 for one nothing sizes until it loads. */\n images: number[];\n }\n>();\n\n/** The size a reveal's skeleton last measured at, taken once by whatever replaces it. */\nexport function takeLoadingSize(reveal: Element | null) {\n if (!reveal) return undefined;\n const size = loadingSizes.get(reveal);\n loadingSizes.delete(reveal);\n return size;\n}\n\nfunction child(root: HTMLElement, attribute: string) {\n for (const element of root.children) {\n if (element.hasAttribute(attribute)) return element as HTMLElement;\n }\n const element = document.createElement('div');\n element.setAttribute(attribute, '');\n root.append(element);\n return element;\n}\n\nconst hasContent = (element: Element) =>\n !!element.firstElementChild || !!element.textContent?.trim();\n\n/** Draws a skeleton over content laid out unseen in `root`, so it takes exactly the content's space. */\nexport class Ghost {\n private ghost: HTMLElement;\n private snapshot: HTMLElement;\n private layer: HTMLElement;\n private source: Source | null = null;\n private hadContent = false;\n private frame = 0;\n private mutations: MutationObserver;\n private resize: ResizeObserver | null;\n\n constructor(\n private root: HTMLElement,\n private options: GhostOptions = {}\n ) {\n addStyles();\n (root as HTMLElement & { [GHOSTED]?: boolean })[GHOSTED] = true;\n root.setAttribute(ATTR_LOADING, '');\n root.setAttribute('aria-hidden', 'true');\n root.inert = true;\n\n this.ghost = child(root, ATTR_GHOST);\n this.snapshot = child(root, ATTR_SNAPSHOT);\n this.layer = child(root, ATTR_LAYER);\n\n this.hadContent = hasContent(this.ghost);\n\n this.note();\n this.choose();\n this.measure();\n // Covered paint is marked now; the inline script's stand-in sheet can go\n (root as HTMLElement & { [UNCOVER]?: () => void })[UNCOVER]?.();\n\n this.mutations = new MutationObserver(this.schedule);\n this.mutations.observe(this.ghost, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n });\n // None in jsdom, which has no layout to follow\n this.resize = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(this.schedule);\n this.resize?.observe(root);\n root.addEventListener('load', this.schedule, true);\n addEventListener('resize', this.schedule);\n document.fonts?.ready.then(this.schedule);\n }\n\n /** Swaps in fresh options without tearing down the observers or stylesheet refcount. */\n update(options: GhostOptions = {}) {\n this.options = options;\n this.note();\n this.choose();\n this.measure();\n }\n\n private note() {\n const reveal = this.root.closest(`[${ATTR_REVEAL}]`);\n if (!reveal) return;\n noteSkeleton(reveal, {\n served: served.has(this.root),\n refetch: !!this.options.refetch && this.hadContent,\n });\n }\n\n private schedule = () => {\n // Leaving: re-measuring a pane pinned at its last size would redraw what's fading out\n if (this.root.closest(`[${ATTR_EXITING}]`)) return;\n cancelAnimationFrame(this.frame);\n this.frame = requestAnimationFrame(() => {\n const has = hasContent(this.ghost);\n if (has !== this.hadContent) {\n this.hadContent = has;\n this.choose();\n }\n this.measure();\n });\n };\n\n private choose() {\n let next: Source = 'fallback';\n let html: string | null = null;\n\n // Re-shaping a skeleton already on screen would move the page — keep it\n const settled = this.options.exact || served.has(this.root);\n // A remembered shape is the shown content, which has none of the author's own skeletons\n const own = !!this.ghost.querySelector(`[${ATTR_OWN}]`);\n if ((settled || own) && this.hadContent) {\n next = 'ghost';\n } else {\n const key = this.options.id ?? autoKey(this.ghost);\n if (key) {\n flushShapes(key);\n html = recallShape(key);\n }\n if (html) next = 'recall';\n else if (this.hadContent) next = 'ghost';\n }\n\n if (next !== this.source) {\n if (next === 'recall' && html) {\n this.snapshot.replaceChildren(restore(html));\n } else if (next === 'fallback') {\n this.snapshot.innerHTML = FALLBACK;\n warnOnce(\n `fallback:${this.options.id}`,\n `Nothing to draw a skeleton from${this.options.id ? ` for \"${this.options.id}\"` : ''}. Pass \\`sample\\` data, or an \\`id\\` so its shape is remembered after the first load. For a lone placeholder box, use \\`SkeletonBox\\`.`\n );\n } else {\n this.snapshot.replaceChildren();\n }\n }\n\n this.ghost.toggleAttribute(ATTR_INACTIVE, next !== 'ghost');\n this.snapshot.toggleAttribute(ATTR_INACTIVE, next === 'ghost');\n this.source = next;\n\n reportLoading(\n this.root.closest(`[${ATTR_REVEAL}]`),\n next === 'recall'\n ? 'remembered shape'\n : next === 'fallback'\n ? 'fallback'\n : this.options.exact\n ? 'data'\n : served.has(this.root)\n ? 'server render'\n : 'sample'\n );\n }\n\n private measure() {\n const active = this.source === 'ghost' ? this.ghost : this.snapshot;\n drawSkeleton(this.layer, measureSkeleton(active, this.layer));\n\n const reveal = this.root.closest(`[${ATTR_REVEAL}]`);\n if (reveal) {\n loadingSizes.set(reveal, {\n width: this.root.offsetWidth,\n height: this.root.offsetHeight,\n // Drawn from real data, so a sample would have changed nothing\n guessed: !(this.options.exact && this.source === 'ghost'),\n images: [...active.querySelectorAll('img')].map(\n (image) => image.getBoundingClientRect().height\n ),\n });\n }\n }\n\n // Bones keep shimmering until they are removed, so a skeleton fading out stays alive\n destroy() {\n cancelAnimationFrame(this.frame);\n this.mutations.disconnect();\n this.resize?.disconnect();\n this.root.removeEventListener('load', this.schedule, true);\n removeEventListener('resize', this.schedule);\n removeStyles();\n }\n}\n","import { ATTR_REVEAL } from './constants';\nimport { debugging, reportReveal } from './debug';\nimport { isDev, sampleFrom, warnOnce } from './dev';\nimport { takeLoadingSize } from './ghost';\nimport { rememberShape, trackShape } from './shapes';\nimport { autoKey } from './snapshot';\n\nexport type MemoryOptions = {\n id?: string;\n /** What the content was rendered from, for the `sample` dev hint. */\n data?: unknown;\n /** The content is rendered from data by a function, which only `sample` or an `id` can stand in for. */\n rendered?: boolean;\n /** A `sample` was passed. */\n sample?: boolean;\n};\n\nconst SAVE_DELAY = 250;\n\n// Synthetic, per-element id for `warnOnce` dedupe when the consumer didn't pass one.\n// Without this every id-less skeleton shares the same `sample:null` / `jump:null` bucket,\n// so only the first warning across the whole app ever fires.\nconst anonIds = new WeakMap<HTMLElement, string>();\nlet anonSeq = 0;\nconst anonId = (element: HTMLElement) => {\n let id = anonIds.get(element);\n if (!id) {\n id = `anon:${++anonSeq}`;\n anonIds.set(element, id);\n }\n return id;\n};\n\n/** Remembers the shape of shown content, so its next skeleton can be drawn from it. */\nexport class Memory {\n private key: string | null;\n private warnKey: string;\n private timer: ReturnType<typeof setTimeout> | undefined;\n private mutations: MutationObserver;\n private resize: ResizeObserver | null;\n private untrack: () => void;\n\n constructor(\n private element: HTMLElement,\n private options: MemoryOptions = {}\n ) {\n this.key = options.id ?? autoKey(element);\n this.warnKey = this.key ?? anonId(element);\n this.untrack = this.key ? trackShape(this.key, () => this.save()) : () => {};\n\n if (isDev || debugging(element)) this.check();\n this.save();\n\n this.mutations = new MutationObserver(this.schedule);\n this.mutations.observe(element, {\n childList: true,\n subtree: true,\n characterData: true,\n });\n // None in jsdom, which has no layout to follow\n this.resize = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(this.schedule);\n this.resize?.observe(element);\n element.addEventListener('load', this.schedule, true);\n }\n\n private schedule = () => {\n clearTimeout(this.timer);\n this.timer = setTimeout(() => this.save(), SAVE_DELAY);\n };\n\n save() {\n clearTimeout(this.timer);\n if (this.key && this.element.isConnected && this.element.offsetHeight) {\n rememberShape(this.key, this.element);\n }\n }\n\n private check() {\n const { data, id, rendered, sample } = this.options;\n const name = id ? `<Skeleton id=\"${id}\">` : '<Skeleton>';\n\n const reveal = this.element.closest(`[${ATTR_REVEAL}]`);\n const before = takeLoadingSize(reveal);\n // Shown without a skeleton first, so nothing was guessed and nothing could move\n if (!before) return;\n\n if (before.guessed && rendered && !sample && data != null) {\n warnOnce(\n `sample:${this.warnKey}`,\n `${name} has no \\`sample\\`, so a first load guesses its shape${id ? '' : \" and it can't be remembered\"}. Pass this to make it exact:\\n sample={${JSON.stringify(sampleFrom(data))}}`\n );\n }\n\n // Unsized images settle late; compare once they have\n const images = [...this.element.querySelectorAll('img')].filter((image) => !image.complete);\n Promise.all(\n images.map(\n (image) =>\n new Promise((resolve) => {\n image.addEventListener('load', resolve, { once: true });\n image.addEventListener('error', resolve, { once: true });\n })\n )\n ).then(() => {\n // Gone before it settled: a detached element measures nothing\n if (!this.element.isConnected) return;\n const width = this.element.offsetWidth;\n const height = this.element.offsetHeight;\n reportReveal(reveal, {\n width: width - before.width,\n height: height - before.height,\n });\n if (Math.abs(width - before.width) <= 1 && Math.abs(height - before.height) <= 1) {\n return;\n }\n // Flat in the skeleton, tall now: nothing sized them before they loaded\n const unsized = [...this.element.querySelectorAll('img')]\n .filter(\n (image, i) => (before.images[i] ?? 0) < 1 && image.getBoundingClientRect().height >= 1\n )\n .map((image) => image.currentSrc.split('/').pop() || 'an image');\n if (unsized.length) {\n warnOnce(\n `unsized:${this.warnKey}`,\n `${name}'s skeleton had no room for ${unsized.length === 1 ? 'an image' : `${unsized.length} images`} (${unsized.slice(0, 3).join(', ')}${unsized.length > 3 ? ', …' : ''}), so the layout jumped when they loaded. Give each \\`width\\` and \\`height\\` attributes, or an \\`aspect-ratio\\`, so its space is known before it loads.`\n );\n return;\n }\n warnOnce(\n `jump:${this.warnKey}`,\n before.guessed\n ? `${name}'s skeleton was ${before.width}×${before.height}px but its content is ${width}×${height}px, so the layout jumped on reveal. ${rendered ? 'Pass `sample` data shaped like the real thing' : 'Pass an `id` so its shape is remembered'}, and give images a size.`\n : `${name}'s skeleton was drawn from the data on screen (${before.width}×${before.height}px), but the new data is ${width}×${height}px, so the layout jumped on reveal. When new data adds to what's shown — another page of a list — give the addition a reveal of its own.`\n );\n });\n }\n\n destroy() {\n this.save();\n clearTimeout(this.timer);\n this.mutations.disconnect();\n this.resize?.disconnect();\n this.element.removeEventListener('load', this.schedule, true);\n this.untrack();\n }\n}\n","import { ATTR_BAR } from './constants';\nimport { shimmer } from './shimmer';\nimport { addStyles } from './styles';\n\ntype Length = string | number;\n\nexport type SkeletonBoxOptions = {\n height?: Length;\n width?: Length;\n radius?: Length;\n};\n\nexport const DEFAULT_SKELETON_BOX_OPTIONS = {\n height: '1em',\n width: '60%',\n radius: 'var(--ask-radius, 0.25em)',\n} satisfies Required<SkeletonBoxOptions>;\n\nconst toCSS = (value: Length) => (typeof value === 'number' ? `${value}px` : value);\n\nexport function skeletonBoxStyle({\n height = DEFAULT_SKELETON_BOX_OPTIONS.height,\n width = DEFAULT_SKELETON_BOX_OPTIONS.width,\n radius = DEFAULT_SKELETON_BOX_OPTIONS.radius,\n}: SkeletonBoxOptions = {}) {\n return {\n height: toCSS(height),\n width: toCSS(width),\n borderRadius: toCSS(radius),\n };\n}\n\n/** A single bar, shimmering in step with every skeleton on the page once it is in the document. */\nexport function createSkeletonBox(options?: SkeletonBoxOptions): HTMLSpanElement {\n addStyles();\n const element = document.createElement('span');\n element.setAttribute(ATTR_BAR, '');\n Object.assign(element.style, skeletonBoxStyle(options));\n requestAnimationFrame(() => {\n if (element.isConnected) shimmer(element);\n });\n return element;\n}\n","import { IMAGE_TIMEOUT } from './constants';\n\nconst noop = () => {};\n\n// Lazy and well off screen, it won't load until scrolled to — nothing to wait for\nconst deferred = (image: HTMLImageElement) => {\n if (image.loading !== 'lazy') return false;\n const rect = image.getBoundingClientRect();\n return rect.bottom < -innerHeight || rect.top > innerHeight * 2;\n};\n\n/** Images inside still on their way. */\nexport const pendingImages = (element: Element) =>\n [...element.querySelectorAll('img')].filter((image) => !image.complete && !deferred(image));\n\n/** Loaded and decoded, so its first frame on screen is the picture; failing counts, as nothing more is coming. */\nexport function imageReady(image: HTMLImageElement): Promise<void> {\n const loaded = image.complete\n ? Promise.resolve()\n : new Promise<void>((resolve) => {\n image.addEventListener('load', () => resolve(), { once: true });\n image.addEventListener('error', () => resolve(), { once: true });\n });\n return Promise.race([\n loaded.then(() => image.decode?.()).then(noop, noop),\n new Promise<void>((resolve) => setTimeout(resolve, IMAGE_TIMEOUT)),\n ]);\n}\n","import { ATTR_LAYER, ATTR_EXITING } from './constants';\nimport { prefersReducedTransparency } from './motion';\nimport {\n BATCH_WINDOW,\n byContent,\n MAX_SWEEP_AREA,\n quickly,\n revealBox,\n SKELETON_DELAY,\n type RevealContext,\n type RevealSpec,\n type Wipe,\n type WipePane,\n} from './plan';\nimport { ease, paceOf, SLANT_ANGLE, SLANT_COS, SLANT_TAN, STEPS } from './shimmer';\n\nconst WAVE_SPREAD = 360; // Most a sweep takes across the reveal that starts it\nconst WAVE_PACE = 2; // A sweep's front runs this many times the shimmer's pace\nexport const SWEEP_SPREAD = 600; // Most a sweep takes across a reveal that joins one under way\nconst FEATHER = 40; // px either side of the front, across the slant\nconst PAD = FEATHER / SLANT_COS; // The feather, along `u`\nconst GLOSS = 320; // px across the slant: the band trailing the front, as wide as the shimmer's widest\nconst GLOSS_LAG = 120; // px its centre trails the front by\nconst GLOSS_LIFT = 0.45; // How far, at its peak, it lifts the content it crosses toward white\n\n// `u` is a point's x plus its y along the slant, in viewport px: the front is a line of one `u`\nconst uOf = (rect: DOMRect) => rect.left + rect.top * SLANT_TAN;\nconst spanOf = (rect: DOMRect) => rect.width + rect.height * SLANT_TAN;\n\n// The front's `u` at `progress` — crossing the reveal from a feather before it to a feather past it\nconst frontAt = (progress: number, reveal: DOMRect) =>\n uOf(reveal) - PAD + (spanOf(reveal) + 2 * PAD) * progress;\n\nlet wave = { start: -Infinity, origin: 0, speed: 1 };\n\n/** When the shared front reaches `reveal`, and how long it takes across — null without a shimmer to match. */\nfunction timing(reveal: HTMLElement) {\n const layer = reveal.querySelector(`:scope > [${ATTR_EXITING}] [${ATTR_LAYER}]`);\n const pace = layer && paceOf(layer);\n if (!pace) return null;\n\n const rect = revealBox(reveal);\n if (rect.width * rect.height > innerWidth * innerHeight * MAX_SWEEP_AREA) {\n return null;\n }\n const from = uOf(rect);\n const to = from + spanOf(rect);\n const now = performance.now();\n // Reveals landing together share one front — if it hasn't reached this one yet, and won't keep it waiting\n const elapsed = now - wave.start;\n const joined =\n elapsed <= BATCH_WINDOW &&\n (from - wave.origin) / wave.speed >= elapsed &&\n (to - wave.origin) / wave.speed - elapsed <= SWEEP_SPREAD;\n if (!joined) {\n wave = {\n start: now,\n origin: from,\n speed: Math.max(WAVE_PACE / pace, (to - from) / WAVE_SPREAD),\n };\n }\n const { start, origin, speed } = wave;\n return {\n delay: (from - PAD - origin) / speed - (now - start),\n duration: (to - from + 2 * PAD) / speed,\n };\n}\n\n// The front's stops in the pane's own gradient, the content behind it and the skeleton ahead\nconst stops =\n (incoming: boolean) =>\n (progress: number, { rect, reveal }: WipePane) => {\n const at = (frontAt(progress, reveal) - uOf(rect)) * SLANT_COS;\n const ramp = Array.from({ length: STEPS + 1 }, (_, i) => {\n const shown = incoming ? 1 - ease(i / STEPS) : ease(i / STEPS);\n const offset = -FEATHER + (2 * FEATHER * i) / STEPS;\n return `rgb(0 0 0 / ${shown.toFixed(3)}) ${(at + offset).toFixed(2)}px`;\n });\n return `linear-gradient(${SLANT_ANGLE}, ${ramp.join(', ')})`;\n };\n\nconst SVG = 'http://www.w3.org/2000/svg';\nlet host: SVGSVGElement | null = null;\nlet glosses = 0;\n\n// One hidden svg on the page for the filters: `filter: url(#…)` can't reach into a shadow root\nfunction filterHost() {\n if (!host?.isConnected) {\n host = document.createElementNS(SVG, 'svg');\n host.setAttribute('aria-hidden', 'true');\n host.style.cssText = 'position:absolute;width:0;height:0;overflow:hidden';\n document.body.append(host);\n }\n return host;\n}\n\nconst svg = (tag: string, attributes: Record<string, string | number>) => {\n const node = document.createElementNS(SVG, tag);\n for (const [name, value] of Object.entries(attributes)) {\n node.setAttribute(name, String(value));\n }\n return node;\n};\n\n// The band trailing the front: a filter lifting what the content paints toward white, never the surface around it\nconst gloss: Wipe['effect'] = (element, { rect, reveal, progress }) => {\n if (prefersReducedTransparency()) return;\n const from = uOf(rect);\n const span = spanOf(rect);\n const half = GLOSS / 2 / SLANT_COS;\n // The band's centre, in `u` from the pane's corner\n const centre = () => frontAt(progress(), reveal) - from - GLOSS_LAG / SLANT_COS;\n if (centre() - half > span) return;\n\n // The band drawn once, slanted, in an image as tall as the pane; moving it along x moves it along the slant\n const width = 2 * half + rect.height * SLANT_TAN;\n const cx = width / 2;\n const cy = rect.height / 2;\n const dx = (GLOSS / 2) * SLANT_COS;\n const dy = (GLOSS / 2) * SLANT_TAN * SLANT_COS;\n // Drawn to a PNG: Safari's feImage renders no SVG, and the filter then hides what it's on\n const canvas = document.createElement('canvas');\n canvas.width = Math.ceil(width);\n canvas.height = Math.ceil(rect.height);\n const context = canvas.getContext('2d');\n if (!context) return;\n const gradient = context.createLinearGradient(cx - dx, cy - dy, cx + dx, cy + dy);\n for (let i = 0; i <= STEPS; i++) {\n const t = i / STEPS;\n gradient.addColorStop(t, `rgb(255 255 255 / ${ease(1 - Math.abs(t * 2 - 1)).toFixed(3)})`);\n }\n context.fillStyle = gradient;\n context.fillRect(0, 0, canvas.width, canvas.height);\n\n const id = `ask-gloss-${++glosses}`;\n // In the pane's own box: WebKit doesn't measure a primitive's x and y from an HTML element's corner, and blanks it\n const filter = svg('filter', {\n id,\n 'color-interpolation-filters': 'sRGB',\n primitiveUnits: 'objectBoundingBox',\n });\n const lit = svg('feComponentTransfer', {\n in: 'SourceGraphic',\n result: 'lit',\n });\n for (const channel of ['R', 'G', 'B']) {\n lit.append(\n svg(`feFunc${channel}`, {\n type: 'linear',\n slope: 1 - GLOSS_LIFT,\n intercept: GLOSS_LIFT,\n })\n );\n }\n const image = svg('feImage', {\n href: canvas.toDataURL(),\n y: 0,\n width: width / rect.width,\n height: 1,\n preserveAspectRatio: 'none',\n result: 'band',\n });\n filter.append(\n lit,\n image,\n svg('feComposite', {\n in: 'lit',\n in2: 'band',\n operator: 'in',\n result: 'shine',\n }),\n svg('feComposite', { in: 'shine', in2: 'SourceGraphic', operator: 'over' })\n );\n filterHost().append(filter);\n element.style.filter = `url(#${id})`;\n\n const tick = () => {\n const at = centre();\n if (at - half > span || !element.isConnected) {\n // Cleared first, matched by id: Safari won't draw an element whose filter is gone, and the style reads back quoted\n if (element.style.filter.includes(id)) element.style.filter = '';\n filter.remove();\n return;\n }\n image.setAttribute('x', ((at - cx - cy * SLANT_TAN) / rect.width).toFixed(4));\n requestAnimationFrame(tick);\n };\n tick();\n};\n\n// Its own outgoing mask rather than a composited inverse: Safari 18 masks only the plainest gradient reliably\nconst wipe: Wipe = { mask: stops(true), out: stops(false), effect: gloss };\n\n/** `smart`, wiping content in behind one band of the shimmer. */\nexport const sweep: RevealSpec = {\n hold: SKELETON_DELAY,\n choose: (context: RevealContext) => {\n const quick = quickly(context);\n if (quick) return quick;\n const swept = timing(context.reveal);\n return swept ? { wipe, ...swept } : byContent(context);\n },\n};\n","import { CASCADE_SPREAD, FADE_DURATION } from './constants';\nimport {\n MAX_DELAY,\n MAX_DURATION,\n sequence,\n smart,\n together,\n type RevealMode,\n type RevealSpec,\n} from './plan';\nimport { sweep, SWEEP_SPREAD } from './sweep';\n\nconst NAMED = { together, sequence, smart, sweep };\n\nexport const revealSpec = (mode: RevealMode = 'smart'): RevealSpec =>\n typeof mode === 'string' ? NAMED[mode] : mode;\n\n/** Longest a pane can take to leave under `mode`, for a framework that has to know up front. */\nexport function exitDuration(mode?: RevealMode) {\n const spec = revealSpec(mode);\n const hold = spec.hold ?? 0;\n if (spec === together) return FADE_DURATION;\n if (spec === sequence) return CASCADE_SPREAD + FADE_DURATION;\n if (spec === smart) return hold + CASCADE_SPREAD + FADE_DURATION;\n if (spec === sweep) return hold + SWEEP_SPREAD + FADE_DURATION;\n if (spec.duration === 0) return 0;\n // A choice can bring its own delay, as long as the cap allows\n const delay = spec.choose ? MAX_DELAY : Math.min(Math.max(spec.delay ?? 0, 0), MAX_DELAY);\n return hold + delay + MAX_DELAY + MAX_DURATION;\n}\n","import {\n ATTR_RECT,\n ATTR_LAYER,\n ATTR_EXITING,\n ATTR_GHOST,\n ATTR_OWN,\n ATTR_PANE,\n ATTR_SNAPSHOT,\n BASE,\n FADE_DURATION,\n RESIZE_DURATION,\n} from './constants';\nimport { imageReady, pendingImages } from './images';\nimport { animationsOf, canAnimate, prefersReducedMotion } from './motion';\nimport { warnOnce } from './dev';\nimport {\n planReveal,\n pieces,\n type Plan,\n type RevealMode,\n type SequencePlan,\n type WipePlan,\n} from './plan';\nimport { revealSpec } from './reveals';\nimport { rectsOf, shimmer } from './shimmer';\n\nexport { prefersReducedMotion };\n\nconst noop = () => {};\n\nconst settle = (animation: Animation) => animation.finished.then(noop, noop);\n\n// How a reveal's incoming pane decided to arrive, for its outgoing pane to match\nconst plans = new WeakMap<Element, Plan | { kind: 'skeleton'; hold: number }>();\n\nfunction appear(element: Element, delay = 0, duration = FADE_DURATION, from = 0, enter?: Keyframe) {\n if (prefersReducedMotion()) return Promise.resolve();\n return settle(\n element.animate([{ ...enter, opacity: from }, { opacity: 1 }], {\n duration,\n delay,\n easing: 'ease',\n fill: 'backwards',\n })\n );\n}\n\n// The bones layer, or the ghost a skeleton is drawn from — vanilla adds its layer a moment later\nconst isSkeleton = (element: Element) =>\n !!element.querySelector(`[${ATTR_LAYER}], [${ATTR_GHOST}], :scope > [${ATTR_OWN}]`);\n\nconst sameBox = (a: DOMRect, b: DOMRect) =>\n Math.abs(a.left - b.left) < 2 &&\n Math.abs(a.top - b.top) < 2 &&\n Math.abs(a.width - b.width) < 2 &&\n Math.abs(a.height - b.height) < 2;\n\n// Bones standing in for images still loading, by reveal\nconst standIns = new WeakMap<Element, Set<HTMLElement>>();\n\nfunction clearStandIns(root: Element) {\n for (const stand of standIns.get(root) ?? []) stand.remove();\n standIns.delete(root);\n}\n\n// Each image still loading stays hidden behind a bone of its own until it's ready, so nothing else waits on it\nfunction holdImages(element: HTMLElement, root: HTMLElement) {\n const images = pendingImages(element);\n const overSkeleton = [...root.children].some(\n (pane) => pane !== element && pane.hasAttribute(ATTR_PANE) && isSkeleton(pane)\n );\n if (!images.length || !overSkeleton) return;\n for (const image of images) image.style.opacity = '0';\n\n // A microtask on, once the skeleton has popped out — layout read any sooner moves the page\n queueMicrotask(() => {\n if (!element.isConnected) return;\n const origin = root.getBoundingClientRect();\n const bones = [...root.querySelectorAll(`:scope > [${ATTR_EXITING}] [${ATTR_LAYER}]`)].flatMap(\n rectsOf\n );\n const stands = standIns.get(root) ?? new Set<HTMLElement>();\n standIns.set(root, stands);\n\n for (const image of images) {\n const rect = image.getBoundingClientRect();\n // Its bone in the skeleton, which the stand-in takes over exactly\n const bone = bones.find((b) => sameBox(b.getBoundingClientRect(), rect));\n const box = bone?.getBoundingClientRect() ?? rect;\n const stand = document.createElement('div');\n stand.setAttribute(ATTR_RECT, '');\n Object.assign(stand.style, {\n position: 'absolute',\n left: `${box.left - origin.left - root.clientLeft}px`,\n top: `${box.top - origin.top - root.clientTop}px`,\n width: `${box.width}px`,\n height: `${box.height}px`,\n borderRadius: bone?.style.borderRadius || getComputedStyle(image).borderRadius,\n backgroundColor: BASE,\n backgroundRepeat: 'no-repeat',\n pointerEvents: 'none',\n });\n root.append(stand);\n stands.add(stand);\n if (bone) bone.style.visibility = 'hidden';\n shimmer(stand);\n\n imageReady(image).then(() => {\n if (!stands.has(stand)) return;\n stands.delete(stand);\n image.style.opacity = '';\n appear(image);\n if (prefersReducedMotion()) return stand.remove();\n settle(\n stand.animate([{ opacity: 1 }, { opacity: 0 }], {\n duration: FADE_DURATION,\n easing: 'ease',\n fill: 'forwards',\n })\n ).then(() => stand.remove());\n });\n }\n });\n}\n\nfunction sequenceIn(element: HTMLElement, plan: SequencePlan) {\n if (prefersReducedMotion()) return Promise.resolve();\n return Promise.all(\n pieces(element).map((piece) => {\n const delay = plan.pieceDelay(piece);\n if (delay === null) return;\n return appear(piece, delay, plan.duration, 0, plan.enter);\n })\n ).then(noop);\n}\n\n// Content arriving at once: anything still on its way out goes now too\nfunction clearExiting(root: Element) {\n for (const pane of root.querySelectorAll<HTMLElement>(`:scope > [${ATTR_EXITING}]`)) {\n for (const animation of animationsOf(pane)) animation.finish();\n pane.style.opacity = '0';\n }\n}\n\n// Content still fading out as content lands again — what the new pane takes over from, so the two never dip together\nfunction takeOver(root: Element) {\n let from = 0;\n for (const pane of root.querySelectorAll<HTMLElement>(`:scope > [${ATTR_EXITING}]`)) {\n if (isSkeleton(pane)) continue;\n from = Math.max(from, parseFloat(getComputedStyle(pane).opacity) || 0);\n for (const animation of animationsOf(pane)) animation.finish();\n pane.style.opacity = '0';\n }\n return from;\n}\n\n/** Brings a pane in: a skeleton after the reveal's `hold`, content as `reveal` plans; `initial` has nothing to replace. */\nexport function fadeIn(\n element: HTMLElement,\n reveal: RevealMode = 'smart',\n { initial = false } = {}\n): Promise<void> {\n let arriving = arrivals.get(element);\n if (!arriving) {\n arriving = arrive(element, reveal, initial);\n arrivals.set(element, arriving);\n }\n return arriving;\n}\n\n// One arrival per pane: StrictMode mounts twice, and a second plan would part from the first, which the outgoing pane already matched\nconst arrivals = new WeakMap<HTMLElement, Promise<void>>();\n\nfunction arrive(element: HTMLElement, reveal: RevealMode, initial: boolean): Promise<void> {\n const root = element.parentElement;\n const spec = revealSpec(reveal);\n\n if (isSkeleton(element)) {\n if (root) clearStandIns(root);\n const hold = Math.max(spec.hold ?? 0, 0);\n if (!hold) {\n if (root) plans.delete(root);\n return initial ? Promise.resolve() : appear(element);\n }\n if (root) plans.set(root, { kind: 'skeleton', hold });\n // A reveal's first skeleton has nothing on screen to hold back for — held, it would only be a blank\n if (initial) return Promise.resolve();\n return appear(element, hold);\n }\n if (initial || !root) return Promise.resolve();\n\n const from = takeOver(root);\n if (from > 0.01) {\n const duration = FADE_DURATION * (1 - from);\n plans.set(root, { kind: 'together', delay: 0, duration });\n return appear(element, 0, duration, from);\n }\n\n holdImages(element, root);\n\n const plan = planReveal(element, root, spec, (key) =>\n warnOnce(\n `enter:${key}`,\n `\\`enter\\` can't set \\`${key}\\`: only properties that change nothing's layout animate, so the reveal never moves the page.`\n )\n );\n plans.set(root, plan);\n if (plan.kind === 'instant') {\n clearExiting(root);\n return Promise.resolve();\n }\n if (plan.kind === 'sequence') return sequenceIn(element, plan);\n if (plan.kind === 'wipe') return wipe(element, plan, true);\n return appear(element, plan.delay, plan.duration, 0, plan.enter);\n}\n\n/** Where a pane stands within its reveal — what it's pinned to when it pops out. */\nexport type PaneBox = {\n top: number;\n left: number;\n width: number;\n height: number;\n};\n\n/** Measures `element` for `fadeOut`: before its replacement is inserted, or scroll anchoring moves the page. */\nexport function boxOf(element: HTMLElement): PaneBox {\n // Fractional, not offset*: a width rounded down rewraps a shrink-to-fit pane's text as it leaves\n const rect = element.getBoundingClientRect();\n const parent = element.offsetParent ?? document.documentElement;\n const origin = parent.getBoundingClientRect();\n return {\n top: rect.top - origin.top - parent.clientTop,\n left: rect.left - origin.left - parent.clientLeft,\n width: rect.width,\n height: rect.height,\n };\n}\n\n// Takes the element out of flow where it stands, so what replaces it lays out at once\nfunction popOut(element: HTMLElement, box = boxOf(element)) {\n Object.assign(element.style, {\n position: 'absolute',\n top: `${box.top}px`,\n left: `${box.left}px`,\n width: `${box.width}px`,\n height: `${box.height}px`,\n margin: '0',\n boxSizing: 'border-box',\n pointerEvents: 'none',\n });\n element.inert = true;\n element.setAttribute(ATTR_EXITING, '');\n return box;\n}\n\ntype Resize = { animation: Animation; overflow: string; boxSizing: string };\n\n// A reveal's running resize, so the next starts from where it got to and restores the styles it found\nconst resizes = new WeakMap<HTMLElement, Resize>();\n\n// Eases a reveal from the height the outgoing pane gave it to the incoming one's; the outgoing pane is already out of flow\nfunction resize(root: HTMLElement, box: PaneBox) {\n const incoming = root.querySelector<HTMLElement>(\n `:scope > [${ATTR_PANE}]:not([${ATTR_EXITING}])`\n );\n if (!incoming) return;\n const running = resizes.get(root);\n const shown = root.getBoundingClientRect().height;\n running?.animation.cancel();\n const to = root.getBoundingClientRect().height;\n const from = running ? shown : to - incoming.getBoundingClientRect().height + box.height;\n if (Math.abs(from - to) < 0.5) {\n if (running) restore(root, running);\n return;\n }\n\n const { overflow, boxSizing } = running ?? root.style;\n Object.assign(root.style, { overflow: 'clip', boxSizing: 'border-box' });\n const animation = root.animate([{ height: `${from}px` }, { height: `${to}px` }], {\n duration: RESIZE_DURATION,\n easing: 'cubic-bezier(0.2, 0, 0, 1)',\n });\n const current = { animation, overflow, boxSizing };\n resizes.set(root, current);\n settle(animation).then(() => {\n if (resizes.get(root) === current) restore(root, current);\n });\n}\n\nfunction restore(root: HTMLElement, { overflow, boxSizing }: Resize) {\n resizes.delete(root);\n Object.assign(root.style, { overflow, boxSizing });\n}\n\n/** Resolves once `element` can be removed, leaving as the pane replacing it decides; its parent must be positioned. */\nexport function fadeOut(element: HTMLElement, box?: PaneBox): Promise<void> {\n // Read before cancelling, so an interrupted fade-in leaves from where it got to\n const opacity = parseFloat(getComputedStyle(element).opacity);\n const from = Number.isNaN(opacity) ? 1 : opacity;\n for (const animation of animationsOf(element)) animation.cancel();\n clearMask(element);\n element.style.filter = '';\n\n const parent = element.parentElement;\n // Content moving on: the bones standing in for its images go with it\n if (parent && !isSkeleton(element)) clearStandIns(parent);\n const stood = popOut(element, box);\n\n const fade = (delay: number, duration: number) => {\n if (!canAnimate()) {\n element.style.opacity = '0';\n return Promise.resolve();\n }\n return settle(\n element.animate([{ opacity: from }, { opacity: 0 }], {\n duration: duration * from,\n delay,\n easing: 'ease',\n fill: 'forwards',\n })\n );\n };\n\n // A microtask on, so the pane replacing it has registered how it arrives\n return Promise.resolve().then(() => {\n const plan = parent && plans.get(parent);\n const instant = prefersReducedMotion() || plan?.kind === 'instant';\n if (parent && !instant) resize(parent, stood);\n\n // Content stays until the skeleton replacing it shows — which may be never\n if (plan?.kind === 'skeleton') return fade(plan.hold, FADE_DURATION);\n if (instant) {\n element.style.opacity = '0';\n return;\n }\n if (plan?.kind === 'sequence' && isSkeleton(element)) {\n return sequenceOut(element, plan);\n }\n if (plan?.kind === 'wipe' && isSkeleton(element)) {\n return wipe(element, plan, false);\n }\n if (plan?.kind === 'together') return fade(plan.delay, plan.duration);\n return fade(0, FADE_DURATION);\n });\n}\n\nfunction sequenceOut(element: HTMLElement, plan: SequencePlan) {\n // The content's own surfaces arrive whole; only the bones go piece by piece\n for (const ghost of element.querySelectorAll<HTMLElement>(\n `[${ATTR_GHOST}], [${ATTR_SNAPSHOT}]`\n )) {\n ghost.style.visibility = 'hidden';\n }\n\n // A skeleton the content draws itself sits in the ghost, but leaves like a bone\n const own = [...element.querySelectorAll<HTMLElement>(`[${ATTR_GHOST}] [${ATTR_OWN}]`)].filter(\n (part) => !part.parentElement?.closest(`[${ATTR_OWN}]`)\n );\n for (const part of own) part.style.visibility = 'visible';\n\n const bones = [...[...element.querySelectorAll(`[${ATTR_LAYER}]`)].flatMap(rectsOf), ...own];\n return Promise.all(\n bones.map((bone) => {\n const rect = bone.getBoundingClientRect();\n const go = (delay: number) =>\n settle(\n bone.animate([{ opacity: 1 }, { opacity: 0 }], {\n duration: plan.duration,\n delay,\n easing: 'ease',\n fill: 'forwards',\n })\n );\n const delay = plan.boneDelay(rect);\n if (delay === null) {\n bone.style.opacity = '0';\n return;\n }\n return go(delay);\n })\n ).then(noop);\n}\n\nconst STALL = 100; // ms between frames that counts as frames dropping — the wipe gives way to a crossfade\n\n// Running fronts, by pane — stopped when the pane's mask is cleared\nconst fronts = new WeakMap<HTMLElement, () => void>();\n\n// Prefixed too: Safari before 15.4 masks with -webkit- only\nfunction setMask(element: HTMLElement, image: string) {\n element.style.setProperty('mask-image', image);\n element.style.setProperty('-webkit-mask-image', image);\n}\n\n// The inverse of `image`: a full layer with `image` cut out of it\nfunction setInverseMask(element: HTMLElement, image: string) {\n setMask(element, `linear-gradient(#000 0 0), ${image}`);\n // Prefixed first: WebKit aliases the two, and the later wins\n element.style.setProperty('-webkit-mask-composite', 'xor');\n element.style.setProperty('mask-composite', 'exclude');\n}\n\nfunction clearMask(element: HTMLElement) {\n fronts.get(element)?.();\n for (const property of [\n 'mask-image',\n '-webkit-mask-image',\n 'mask-composite',\n '-webkit-mask-composite',\n ]) {\n element.style.removeProperty(property);\n }\n}\n\n// A wipe across one pane on the plan's shared clock; the plainest mask, rewritten each frame, for Safari 18\nfunction wipe(element: HTMLElement, plan: WipePlan, incoming: boolean) {\n const pane = { rect: element.getBoundingClientRect(), reveal: plan.reveal };\n const { mask, out } = plan.wipe;\n const draw = (at: number) => {\n if (incoming) setMask(element, mask(at, pane));\n else if (out) setMask(element, out(at, pane));\n else setInverseMask(element, mask(at, pane));\n };\n const progress = () => (performance.now() - plan.start) / plan.duration;\n if (progress() >= 1) {\n if (!incoming) element.style.opacity = '0';\n return Promise.resolve();\n }\n if (incoming) {\n plan.wipe.effect?.(element, { ...pane, progress });\n if (plan.enter) {\n element.animate([plan.enter, {}], {\n duration: plan.duration,\n delay: Math.max(plan.start - performance.now(), 0),\n easing: 'ease',\n fill: 'backwards',\n });\n }\n }\n\n // Resolves null once crossed, or with how far it got when frames dropped and the wipe gave way\n const run = new Promise<number | null>((resolve) => {\n let frame = 0;\n let last = performance.now();\n let at = 0;\n const tick = () => {\n const now = performance.now();\n if (now - last > STALL) plan.stalled = true;\n last = now;\n if (plan.stalled) return done(at);\n at = Math.min(Math.max(progress(), 0), 1);\n draw(at);\n if (at < 1) frame = requestAnimationFrame(tick);\n else done(null);\n };\n const done = (stalledAt: number | null = null) => {\n cancelAnimationFrame(frame);\n clearTimeout(deadline);\n fronts.delete(element);\n resolve(stalledAt);\n };\n // Frames can stop altogether, as in a hidden tab: the wipe still ends when its time is up\n const deadline = setTimeout(\n () => done(null),\n Math.max(plan.start + plan.duration - performance.now(), 0) + STALL\n );\n fronts.set(element, done);\n tick();\n });\n\n return run.then((stalledAt) => {\n clearMask(element);\n if (stalledAt === null) {\n if (!incoming) element.style.opacity = '0';\n return;\n }\n // Frames dropped: the rest as a crossfade, from as far as the front got\n const rest = FADE_DURATION * (1 - stalledAt);\n if (incoming) return appear(element, 0, rest, stalledAt);\n return settle(\n element.animate([{ opacity: 1 - stalledAt }, { opacity: 0 }], {\n duration: rest,\n easing: 'ease',\n fill: 'forwards',\n })\n ).then(() => {\n element.style.opacity = '0';\n });\n });\n}\n","import { ATTR_GHOST, ATTR_PANE, ATTR_REVEAL, ATTR_STATUS } from './constants';\nimport { fadeIn, fadeOut } from './fade';\nimport type { RevealMode } from './plan';\nimport { Ghost } from './ghost';\nimport { Memory } from './memory';\nimport { addStyles, removeStyles } from './styles';\n\nexport type RevealOptions = {\n /** Remembers the shape under this key; without it, one is derived from the markup. */\n id?: string;\n /** How content replaces its skeleton: `smart` (the default), `together`, `sequence`, `sweep`, or a `RevealSpec` of your own. */\n reveal?: RevealMode;\n /** Read to screen readers while loading, in place of the skeleton — \"Loading profile\". */\n label?: string;\n /** Called once content has come in over a skeleton. */\n onReveal?: () => void;\n};\n\n/** Shows a skeleton of content while it loads, then crossfades to the content itself. */\nexport class Reveal {\n private current: HTMLElement | null = null;\n private ghost: Ghost | null = null;\n private memory: Memory | null = null;\n private arrival: Promise<void> = Promise.resolve();\n\n constructor(\n private element: HTMLElement,\n private options: RevealOptions = {}\n ) {\n addStyles();\n element.setAttribute(ATTR_REVEAL, '');\n }\n\n /** Shows a skeleton measured from `content`, rendered from sample data, or else the shape last shown. */\n load(content?: Node | string): HTMLElement {\n const loading = document.createElement('div');\n const ghost = document.createElement('div');\n ghost.setAttribute(ATTR_GHOST, '');\n if (content) ghost.append(content);\n loading.append(ghost);\n\n const pane = this.swap(loading);\n // Outside the skeleton, which is hidden from screen readers\n if (this.options.label) {\n const status = document.createElement('span');\n status.setAttribute(ATTR_STATUS, '');\n status.textContent = this.options.label;\n pane.prepend(status);\n }\n this.element.setAttribute('aria-busy', 'true');\n this.ghost = new Ghost(loading, { id: this.options.id });\n return pane;\n }\n\n show(content: Node | string): HTMLElement {\n const loading = this.element.getAttribute('aria-busy') === 'true';\n const pane = this.swap(content);\n if (loading && this.options.onReveal) this.arrival.then(this.options.onReveal);\n this.element.removeAttribute('aria-busy');\n this.memory = new Memory(pane, { id: this.options.id });\n return pane;\n }\n\n private swap(content: Node | string) {\n this.memory?.destroy();\n this.ghost?.destroy();\n this.memory = this.ghost = null;\n\n const pane = document.createElement('div');\n pane.setAttribute(ATTR_PANE, '');\n pane.append(content);\n\n const previous = this.current;\n this.current = pane;\n\n // Popped out before the new pane lands, while it still measures where it stood\n if (previous) fadeOut(previous).then(() => previous.remove());\n this.element.append(pane);\n this.arrival = fadeIn(pane, this.options.reveal, { initial: !previous });\n\n return pane;\n }\n\n destroy() {\n this.memory?.destroy();\n this.ghost?.destroy();\n removeStyles();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core.js","names":["host","MEDIA","restore","restore","noop","wipe"],"sources":["../../src/core/constants.ts","../../src/core/styles.ts","../../src/core/inline.generated.ts","../../src/core/theme.ts","../../src/core/debug.ts","../../src/core/canvas.ts","../../src/core/snapshot.ts","../../src/core/dev.ts","../../src/core/measure.ts","../../src/core/motion.ts","../../src/core/shimmer.ts","../../src/core/plan.ts","../../src/core/shapes.ts","../../src/core/ghost.ts","../../src/core/memory.ts","../../src/core/skeleton.ts","../../src/core/images.ts","../../src/core/sweep.ts","../../src/core/reveals.ts","../../src/core/fade.ts","../../src/core/reveal.ts"],"sourcesContent":["export const ATTR_REVEAL = 'ask-reveal';\nexport const ATTR_PANE = 'ask-pane';\nexport const ATTR_LOADING = 'ask-loading';\nexport const ATTR_GHOST = 'ask-ghost'; // The framework's render of the content, laid out but never seen\nexport const ATTR_SNAPSHOT = 'ask-snapshot'; // A remembered or fallback shape, standing in for the ghost\nexport const ATTR_LAYER = 'ask-layer';\nexport const ATTR_RECT = 'ask-rect';\nexport const ATTR_BAR = 'ask-bar';\nexport const ATTR_INACTIVE = 'ask-inactive';\nexport const ATTR_EXITING = 'ask-exiting'; // On a pane fading out — its skeleton holds still\nexport const ATTR_COVERED = 'ask-covered'; // Drawn as one block by a bone, so its own paint is hidden\nexport const ATTR_OWN = 'ask-own'; // A subtree that draws its own skeleton — measuring stops at it\nexport const ATTR_IGNORE = 'ask-ignore';\nexport const ATTR_BLOCK = 'ask-block';\n\nexport const GHOSTED = Symbol.for('a-smart-skeleton.ghost'); // On a loading root once its Ghost runs: the inline script stands down\nexport const UNCOVER = Symbol.for('a-smart-skeleton.uncover'); // On a served loading root: drops the inline script's sheet hiding covered paint, once Ghost marks it\nexport const BOOT = 'a-smart-skeleton.boot'; // Symbol.for key on window: the inline script's measuring, sent once a page — later skeletons' stubs call it, or queue for it\nexport const ATTR_STATUS = 'ask-status'; // Read to screen readers in place of the skeleton\nexport const ATTR_XRAY = 'ask-xray'; // Debug, on any ancestor: shows the ghost through its bones\nexport const ATTR_DEBUG = 'ask-debug'; // Debug outlines for this subtree alone\n\n// Themed by ASmartSkeletonProvider; the fallbacks are translucent so one grey reads on light and dark pages alike\nexport const BASE = 'var(--ask-base, rgb(128 128 128 / 0.2))';\nexport const HIGHLIGHT = 'var(--ask-highlight, rgb(255 255 255 / 0.12))';\nexport const FADE_DURATION = 200;\nexport const CASCADE_SPREAD = 320; // From the first piece of a sequenced reveal to the last\nexport const RESIZE_DURATION = 280; // A reveal easing to its new height, when its skeleton guessed the content wrong\nexport const IMAGE_TIMEOUT = 10000; // Longest a reveal holds for an image — a stalled request mustn't keep a skeleton up for good\n// One loop of each animation, by `speed`; a shimmer's is across a 1280px-wide screen\nexport const DURATIONS = {\n shimmer: { slow: 4000, fast: 2000 },\n pulse: { slow: 2400, fast: 1200 },\n} as const;\n\n// Leaves that hold text, so an empty one still stands for a line of it\nexport const TEXT_TAGS = [\n 'a',\n 'b',\n 'code',\n 'dd',\n 'dt',\n 'em',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'i',\n 'label',\n 'li',\n 'p',\n 'small',\n 'span',\n 'strong',\n 'td',\n 'th',\n 'time',\n];\n\n// Drawn as one block at their box — there is no text inside to measure\nexport const MEDIA_TAGS = [\n 'audio',\n 'canvas',\n 'embed',\n 'iframe',\n 'img',\n 'input',\n 'object',\n 'picture',\n 'select',\n 'svg',\n 'textarea',\n 'video',\n];\n","import {\n ATTR_BAR,\n ATTR_BLOCK,\n ATTR_LAYER,\n ATTR_COVERED,\n ATTR_GHOST,\n ATTR_INACTIVE,\n ATTR_LOADING,\n ATTR_OWN,\n ATTR_PANE,\n ATTR_RECT,\n ATTR_REVEAL,\n ATTR_STATUS,\n ATTR_XRAY,\n BASE,\n MEDIA_TAGS,\n TEXT_TAGS,\n} from './constants';\n\nconst media = MEDIA_TAGS.join(', ');\nconst text = TEXT_TAGS.join(', ');\n\n/** The whole stylesheet, for rendering into a page yourself. */\nexport const SMART_SKELETON_CSS = `\n[${ATTR_REVEAL}] {\n position: relative;\n}\n\na-smart-skeleton-reveal,\nask-reveal {\n display: block;\n}\n\na-smart-skeleton-reveal[loading]:not(:defined),\nask-reveal[loading]:not(:defined) {\n visibility: hidden;\n}\n\n[${ATTR_PANE}] {\n display: block;\n}\n\n[${ATTR_LOADING}] {\n position: relative;\n -webkit-user-select: none;\n user-select: none;\n pointer-events: none;\n}\n\n[${ATTR_INACTIVE}] {\n display: none !important;\n}\n\n[${ATTR_LAYER}] {\n position: absolute;\n inset: 0;\n overflow: visible;\n}\n\n[${ATTR_BAR}] {\n display: block;\n background-color: ${BASE};\n background-repeat: no-repeat;\n}\n\n/*\n * Bones drawn by \\`drawSkeleton\\` live in the light DOM (no shadow root), so a\n * consumer can target them with their own stylesheet. Positioning stays inline\n * (per-bone), but the fill colour reads from a CSS custom property so the\n * consumer's theme flows through — set \\`--ask-base\\` on any ancestor to\n * recolour every bone inside it, or use the type modifier to style text / media\n * / box bones separately.\n *\n * Chrome bones are excluded: they reproduce the consumer's own container paint\n * (background, border, shadow) that \\`captureChrome\\` snapshotted, so they must\n * NOT get a generic fill underneath. Without the \\`:not()\\`, a bordered-only\n * container (e.g. a footer with \\`border-t\\`) would show as a solid filled\n * rectangle instead of just its captured divider.\n */\n[${ATTR_RECT}]:not([${ATTR_RECT}=\"chrome\"]) {\n background-color: var(--ask-base, var(--ask-block, var(--ak-skeleton-block, rgb(128 128 128 / 0.2))));\n background-repeat: no-repeat;\n}\n\n/* Containers keep their surface; what they hold is drawn by bones, measured before the first paint */\n@scope ([${ATTR_LOADING}]) to ([${ATTR_OWN}], [${ATTR_LAYER}]) {\n :scope,\n :scope * {\n color: transparent !important;\n -webkit-text-fill-color: transparent !important;\n text-shadow: none !important;\n text-decoration-color: transparent !important;\n }\n\n :scope ::placeholder {\n color: transparent !important;\n }\n\n /* A line to measure in empty text; content only, never a size, or a dot-sized span would grow round it */\n :scope :is(${text}):empty:not(svg *)::before {\n content: \"000000\";\n }\n\n /* Leaves are drawn by bones, so their own paint never shows; visibility, as measuring reads it */\n :scope :is(:not(:has(*)), ${media}, [${ATTR_COVERED}], [${ATTR_BLOCK}]):not(svg *) {\n visibility: hidden !important;\n }\n\n /* No script to measure: a bar struck through each line of text instead */\n @media (scripting: none) {\n :scope :not(:has(*)):not(svg *) {\n visibility: visible !important;\n }\n\n :scope,\n :scope * {\n text-decoration: line-through ${BASE} !important;\n text-decoration-thickness: 0.72em !important;\n text-decoration-skip-ink: none !important;\n }\n\n :scope :is(${media}, [${ATTR_BLOCK}]):not(svg *) {\n visibility: visible !important;\n background: ${BASE} !important;\n }\n\n :scope svg * {\n fill: transparent !important;\n stroke: transparent !important;\n }\n\n :scope :is(img, video) {\n object-position: -100vw 0;\n }\n }\n}\n\n/* Read by screen readers in the skeleton's place, never seen */\n[${ATTR_STATUS}] {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n/* Debug x-ray: the ghost shown through its bones, to see what was measured */\n[${ATTR_XRAY}] [${ATTR_LOADING}] [${ATTR_GHOST}],\n[${ATTR_XRAY}] [${ATTR_LOADING}] [${ATTR_GHOST}] *:not(svg *) {\n visibility: visible !important;\n color: rgb(255 0 80 / 0.7) !important;\n -webkit-text-fill-color: rgb(255 0 80 / 0.7) !important;\n}\n\n/* Lets addStyles see a stylesheet already on the page, from styles.css or a server render */\n:root {\n --ask: 1;\n}`;\n\nlet styleEl: HTMLStyleElement | null = null;\nlet refCount = 0;\n\nlet present: boolean | undefined;\n\nexport function addStyles() {\n refCount++;\n if (styleEl) return;\n\n // Already on the page — server-rendered, hoisted by React, or imported as styles.css\n present ??= !!getComputedStyle(document.documentElement).getPropertyValue('--ask');\n if (present) return;\n\n styleEl = document.createElement('style');\n styleEl.dataset.aSmartSkeleton = 'true';\n styleEl.textContent = SMART_SKELETON_CSS;\n document.head.appendChild(styleEl);\n}\n\nexport function removeStyles() {\n refCount--;\n if (refCount > 0 || !styleEl) return;\n\n styleEl.remove();\n styleEl = null;\n}\n","// Generated by scripts/build-inline.mjs from boot.ts — don't edit\nexport const INLINE_SCRIPT = \"\\\"use strict\\\";(()=>{var H=\\\"ask-ghost\\\";var G=\\\"ask-layer\\\",M=\\\"ask-rect\\\";var A=\\\"ask-covered\\\",P=\\\"ask-own\\\",W=\\\"ask-ignore\\\",F=\\\"ask-block\\\",z=Symbol.for(\\\"a-smart-skeleton.ghost\\\"),U=Symbol.for(\\\"a-smart-skeleton.uncover\\\"),X=\\\"a-smart-skeleton.boot\\\";var j=\\\"var(--ask-highlight, rgb(255 255 255 / 0.12))\\\";var V={shimmer:{slow:4e3,fast:2e3},pulse:{slow:2400,fast:1200}},q=[\\\"a\\\",\\\"b\\\",\\\"code\\\",\\\"dd\\\",\\\"dt\\\",\\\"em\\\",\\\"h1\\\",\\\"h2\\\",\\\"h3\\\",\\\"h4\\\",\\\"h5\\\",\\\"h6\\\",\\\"i\\\",\\\"label\\\",\\\"li\\\",\\\"p\\\",\\\"small\\\",\\\"span\\\",\\\"strong\\\",\\\"td\\\",\\\"th\\\",\\\"time\\\"],Y=[\\\"audio\\\",\\\"canvas\\\",\\\"embed\\\",\\\"iframe\\\",\\\"img\\\",\\\"input\\\",\\\"object\\\",\\\"picture\\\",\\\"select\\\",\\\"svg\\\",\\\"textarea\\\",\\\"video\\\"];var Et,K=()=>Et??(Et=/jsdom/.test(navigator.userAgent)?null:document.createElement(\\\"canvas\\\").getContext(\\\"2d\\\"));var nt=(t,e)=>t?{left:Math.max(t.left,e.left),right:Math.min(t.right,e.right),top:Math.max(t.top,e.top),bottom:Math.min(t.bottom,e.bottom)}:e,k=t=>[[t.left,t.top],[t.right,t.top],[t.right,t.bottom],[t.left,t.bottom]],$=(t,e)=>Math.abs(t[0]-e[0])<1&&Math.abs(t[1]-e[1])<1;function rt(t,e){let r=Math.min(e.right-e.left,e.bottom-e.top),o=n=>n.endsWith(\\\"%\\\")?parseFloat(n)/100*r:parseFloat(n)||0;return[o(t.borderTopLeftRadius),o(t.borderTopRightRadius),o(t.borderBottomRightRadius),o(t.borderBottomLeftRadius)]}function At(t,e,r){let o=nt(t,e),n=rt(r,e),c=t?k(t):[],i=k(e),l=k(o).map((b,R)=>$(b,i[R])?n[R]:t&&$(b,c[R])?t.corners[R]:0),{left:s,right:a,top:d,bottom:h}=o;return{left:s,right:a,top:d,bottom:h,corners:l}}function Z(t,e,r,o){if(!t)return r;let n=k(t),c=k(e).map((l,s)=>t.corners[s]>0&&$(l,n[s]));if(!c.some(Boolean))return r;let i=rt(o,e);return c.map((l,s)=>l?Math.max(i[s],t.corners[s]):i[s]).map(l=>`${l}px`).join(\\\" \\\")}var O=(t,e)=>{let r=nt(e,t);return r.right-r.left>=2&&r.bottom-r.top>=2?r:null},J={top:\\\"ascender\\\",bottom:\\\"descender\\\"},w=new Map,st=t=>[...t.getClientRects?.()??[]];function kt(t){let e=`${t.fontStyle} ${t.fontWeight} ${t.fontSize} ${t.fontFamily}`;if(w.has(e))return w.get(e);let r=K(),o=null;if(r){r.font=e;let n=r.measureText(\\\"H\\\"),c=i=>r.measureText(i).actualBoundingBoxAscent;o={ascent:n.fontBoundingBoxAscent,descent:n.fontBoundingBoxDescent,ascender:c(\\\"bdfhkl\\\"),capHeight:n.actualBoundingBoxAscent,xHeight:c(\\\"xz\\\"),descender:r.measureText(\\\"gjpqy\\\").actualBoundingBoxDescent}}return w.set(e,o),o}var Q={ascender:\\\"ascender\\\",\\\"cap-height\\\":\\\"capHeight\\\",\\\"x-height\\\":\\\"xHeight\\\"},tt=(t,e,r,o)=>{let n=t.getPropertyValue(e).trim();return r.includes(n)?n:o};function Ct(t,e,r){let o=kt(e);if(!o){let s=Math.min(r*.72,t.bottom-t.top),a=(t.top+t.bottom)/2;return{barTop:a-s/2,barBottom:a+s/2}}let n=tt(e,\\\"--ask-text-top\\\",Object.keys(Q),J.top),c=tt(e,\\\"--ask-text-bottom\\\",[\\\"baseline\\\",\\\"descender\\\"],J.bottom),i=o.ascent+o.descent,l=t.top+(t.bottom-t.top-i)/2+o.ascent;return{barTop:l-o[Q[n]],barBottom:l+(c===\\\"descender\\\"?o.descender:0)}}var Mt=new Set(Y),Ot=new Set(q),it=.4,at=/[,/]\\\\s*0\\\\)$/,g=(t,e)=>t!==\\\"\\\"&&t!==e,N=[\\\"Top\\\",\\\"Right\\\",\\\"Bottom\\\",\\\"Left\\\"],wt=t=>N.every(e=>g(t[`border${e}Style`],\\\"none\\\")&&g(t[`border${e}Width`],\\\"0px\\\")),$t=t=>N.some(e=>g(t[`border${e}Style`],\\\"none\\\")&&g(t[`border${e}Width`],\\\"0px\\\")),Bt=t=>{let[e=0,r=0,o=0,n=0]=(t.replace(/rgba?\\\\([^)]*\\\\)|#\\\\w+/g,\\\"\\\").match(/-?[\\\\d.]+px/g)??[]).map(parseFloat);return t.includes(\\\"inset\\\")&&!o&&!n&&e===0!=(r===0)&&Math.abs(e+r)<=2},ct=t=>g(t,\\\"none\\\")&&!t.split(/,(?![^(]*\\\\))/).every(Bt);function Nt(t){let e=[],r=0,o=0;for(let n=0;n<t.length;n++){let c=t[n];c===\\\"(\\\"?r++:c===\\\")\\\"?r--:c===\\\",\\\"&&r===0&&(e.push(t.slice(o,n)),o=n+1)}return e.push(t.slice(o)),e.map(n=>n.trim()).filter(n=>n&&!n.startsWith(\\\"url(\\\")).join(\\\", \\\")}var dt=t=>g(t.backgroundColor,\\\"transparent\\\")&&!at.test(t.backgroundColor)||g(t.backgroundImage,\\\"none\\\")||ct(t.boxShadow)||wt(t);function _t(t){let e={},r=t.backgroundColor;g(r,\\\"transparent\\\")&&!at.test(r)&&(e.background=r);let o=t.backgroundImage;if(g(o,\\\"none\\\")){let n=Nt(o);n&&(e.background=e.background?`${n}, ${e.background}`:n)}for(let n of N){let c=t[`border${n}Width`],i=t[`border${n}Style`],l=t[`border${n}Color`];if(g(i,\\\"none\\\")&&g(c,\\\"0px\\\")&&parseFloat(c)>0){let s=`border${n}`;e[s]=`${c} ${i} ${l}`}}return ct(t.boxShadow)&&(e.boxShadow=t.boxShadow),Object.keys(e).length?e:void 0}var B=t=>Mt.has(t.localName),lt=t=>Ot.has(t.localName)&&!t.firstElementChild&&!t.textContent?.trim(),Dt=t=>{let e=document.createTreeWalker(t,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT),r=document.createRange(),o=[],n=0;for(;e.nextNode();){let a=e.currentNode;if(a.nodeType===Node.TEXT_NODE){let d=a.parentElement;if(!a.textContent?.trim()||!d)continue;n++;let h=d.getBoundingClientRect();if(h.width<=1||h.height<=1)continue;r.selectNodeContents(a),o.push(st(r).filter(b=>b.width||b.height))}else lt(a)&&(n++,o.push([...a.getClientRects()]))}if(!o.some(a=>a.length))return n;let c=(parseFloat(getComputedStyle(t).fontSize)||16)*it,i=(a,d)=>Math.min(a.bottom,d.bottom)-Math.max(a.top,d.top)>=Math.min(a.height,d.height)/2&&Math.max(a.left,d.left)-Math.min(a.right,d.right)<=c,l=o.map((a,d)=>d),s=a=>l[a]===a?a:l[a]=s(l[a]);for(let a=0;a<o.length;a++)for(let d=a+1;d<o.length;d++)o[a].some(h=>o[d].some(b=>i(h,b)))&&(l[s(d)]=s(a));return new Set(o.map((a,d)=>s(d))).size},Lt=(t,e)=>t.hasAttribute(F)||B(t)||dt(e)&&Dt(t)<=1;function et(t,e){if(parseFloat(e.borderRadius)||!t.parentElement)return e.borderRadius||\\\"0px\\\";let r=t.parentElement,o=getComputedStyle(r),n=t.getBoundingClientRect(),c=r.getBoundingClientRect();return Math.abs(n.width-c.width)<1&&Math.abs(n.height-c.height)<1&&o.overflow!==\\\"visible\\\"?o.borderRadius:e.borderRadius||\\\"0px\\\"}function ot(t){t.sort((r,o)=>r.left-o.left);let e=[];for(let r of t){let o=e.find(n=>{let c=Math.min(n.bottom,r.bottom)-Math.max(n.top,r.top),i=Math.min(n.bottom-n.top,r.bottom-r.top),l=r.left-n.right;return c>=i/2&&l<=Math.max(n.fontSize,r.fontSize)*it});o?(o.left=Math.min(o.left,r.left),o.right=Math.max(o.right,r.right),o.top=Math.min(o.top,r.top),o.bottom=Math.max(o.bottom,r.bottom),o.fontSize=Math.max(o.fontSize,r.fontSize),o.barTop=Math.min(o.barTop,r.barTop),o.barBottom=Math.max(o.barBottom,r.barBottom)):e.push({...r})}return e.map(r=>{let o=r.barBottom-r.barTop;return{type:\\\"text\\\",x:r.left,y:r.barTop,width:r.right-r.left,height:o,radius:r.radius||`${Math.round(o/3)}px`}})}function mt(t,e,{mark:r=!0,onCovered:o}={}){let n=e.getBoundingClientRect(),c=e.offsetWidth?n.width/e.offsetWidth:1,i=e.offsetHeight?n.height/e.offsetHeight:1,l=m=>({left:(m.left-n.left)/c,right:(m.right-n.left)/c,top:(m.top-n.top)/i,bottom:(m.bottom-n.top)/i}),s=[],a=[],d=new Set,h=document.createRange(),b=(m,f,T)=>{let u=O(m,T);if(!u)return;let p=parseFloat(f.fontSize)||16,C=l(u);a.push({...C,fontSize:p,...Ct(C,f,p),radius:f.getPropertyValue(\\\"--ask-radius\\\").trim()})},R=(m,f)=>{let T=m.data.search(/\\\\S/);if(T<0||!m.parentElement)return;h.setStart(m,T),h.setEnd(m,m.data.trimEnd().length);let u=getComputedStyle(m.parentElement);for(let p of st(h))b(p,u,f)},I=(m,f)=>{for(let T of m.childNodes){if(T.nodeType===Node.TEXT_NODE){R(T,f);continue}if(T.nodeType!==Node.ELEMENT_NODE)continue;let u=T;if(u.hasAttribute(W)||u.hasAttribute(P))continue;let p=getComputedStyle(u);if(p.display===\\\"none\\\")continue;if(Lt(u,p)){let x=O(u.getBoundingClientRect(),f);if(x){let S=l(x);s.push({type:B(u)?\\\"media\\\":\\\"box\\\",x:S.left,y:S.top,width:S.right-S.left,height:S.bottom-S.top,radius:Z(f,x,et(u,p),p)})}B(u)||d.add(u);continue}if(lt(u)){for(let x of u.getClientRects())b(x,p,f);continue}if(dt(p)||$t(p)){let x=_t(p);if(x){let S=O(u.getBoundingClientRect(),f);if(S){let y=l(S);s.push({type:\\\"chrome\\\",x:y.left,y:y.top,width:y.right-y.left,height:y.bottom-y.top,radius:Z(f,S,et(u,p),p),chrome:x})}}}let C=p.overflowX!==\\\"visible\\\"||p.overflowY!==\\\"visible\\\";I(u,C?At(f,u.getBoundingClientRect(),p):f)}};if(I(t,null),o?.(d),!r)return[...s,...ot(a)];for(let m of t.querySelectorAll(`[${A}]`))d.has(m)||m.removeAttribute(A);for(let m of d)m.hasAttribute(A)||m.setAttribute(A,\\\"\\\");return[...s,...ot(a)]}var vt=t=>typeof matchMedia<\\\"u\\\"&&matchMedia(t).matches,It=()=>typeof Element<\\\"u\\\"&&typeof Element.prototype.animate==\\\"function\\\",ut=()=>!It()||vt(\\\"(prefers-reduced-motion: reduce)\\\");var _=t=>t.getAnimations?.()??[];var Ht=.7,Gt=1280,pt=320,Pt=2.5,Wt=.45,Ft=[\\\"shimmer\\\",\\\"group-shimmer\\\",\\\"pulse\\\",\\\"none\\\"];function bt(t){let e=getComputedStyle(t),r=(c,i,l)=>{let s=e.getPropertyValue(c).trim();return i.includes(s)?s:l},o=r(\\\"--ask-animation\\\",Ft,\\\"shimmer\\\"),n=r(\\\"--ask-speed\\\",[\\\"slow\\\",\\\"fast\\\"],\\\"slow\\\");return{animation:o,duration:V[o===\\\"pulse\\\"?\\\"pulse\\\":\\\"shimmer\\\"][n]}}var L=20,zt=Math.sin(L*Math.PI/180),gt=Math.cos(L*Math.PI/180),Ut=zt/gt;var Xt=`${90+L}deg`,D=.85,E=12,ht=t=>(1-Math.cos(Math.PI*t))/2;function jt(t){let e=t*Pt,r=(n,c)=>`color-mix(in srgb, ${j} ${(c*100).toFixed(1)}%, transparent) ${(n*t).toFixed(2)}px`,o=[];for(let n=0;n<=E;n++)o.push(r(n/E*D,ht(n/E)));for(let n=1;n<=E;n++)o.push(r(D+n/E*(1-D),ht(1-n/E)));return{width:e/gt,image:`repeating-linear-gradient(${Xt}, ${o.join(\\\", \\\")}, transparent ${e.toFixed(2)}px)`}}function Vt(t,e,r=bt(t)){for(let b of _(t))b.cancel();if(t.style.backgroundImage=\\\"\\\",t.style.backgroundRepeat=\\\"\\\",ut()||typeof t.animate!=\\\"function\\\"||r.animation===\\\"none\\\")return;let o={duration:r.duration,iterations:1/0};if(r.animation===\\\"pulse\\\"){t.animate([{opacity:1,easing:\\\"ease-in-out\\\"},{opacity:Wt,easing:\\\"ease-in-out\\\"},{opacity:1}],o).startTime=0;return}let n=t.getBoundingClientRect(),c=n.left+scrollX,i=r.animation===\\\"group-shimmer\\\"?e??{left:c,top:n.top,width:n.width,height:n.height}:{left:0,top:0,width:document.documentElement.clientWidth||innerWidth,height:innerHeight},l=Math.min(Math.max(i.width*.4,80),pt),{width:s,image:a}=jt(l),d=c-i.left+(n.top-i.top)*Ut,h=r.duration*Ht/(Gt+pt);t.style.backgroundImage=a,t.style.backgroundSize=`${s}px 100%`,t.style.backgroundRepeat=\\\"repeat-x\\\",t.animate([{backgroundPosition:`${-d}px 0`},{backgroundPosition:`${s-d}px 0`}],{duration:s*h,iterations:1/0}).startTime=0}var qt=t=>[...t.querySelectorAll(`:scope > [${M}]`)],ft=4,Yt=t=>t.replace(/(\\\\d+(?:\\\\.\\\\d+)?)px/g,(e,r)=>{let o=parseFloat(r);return Number.isFinite(o)&&o<ft?`${ft}px`:`${o}px`});function St(t,e){let r=qt(t),o=t.getBoundingClientRect(),n={left:o.left+scrollX,top:o.top,width:o.width,height:o.height},c=bt(t);e.forEach((i,l)=>{let s=r[l];if(s||(s=document.createElement(\\\"div\\\"),s.style.cssText=\\\"position:absolute;display:block;pointer-events:none;background-repeat:no-repeat\\\",t.append(s)),s.setAttribute(M,i.type),Object.assign(s.style,{left:`${i.x}px`,top:`${i.y}px`,width:`${i.width}px`,height:`${i.height}px`,borderRadius:i.type===\\\"chrome\\\"?i.radius:Yt(i.radius)}),i.type===\\\"chrome\\\"){for(let h of _(s))h.cancel();s.style.backgroundImage=\\\"\\\",s.style.backgroundSize=\\\"\\\",s.style.backgroundRepeat=\\\"\\\";let d=i.chrome;s.style.background=d?.background??\\\"\\\",s.style.borderTop=d?.borderTop??\\\"\\\",s.style.borderRight=d?.borderRight??\\\"\\\",s.style.borderBottom=d?.borderBottom??\\\"\\\",s.style.borderLeft=d?.borderLeft??\\\"\\\",s.style.boxShadow=d?.boxShadow??\\\"\\\",s.dataset.motion=\\\"chrome\\\";return}s.dataset.motion===\\\"chrome\\\"&&(s.style.background=\\\"\\\",s.style.borderTop=\\\"\\\",s.style.borderRight=\\\"\\\",s.style.borderBottom=\\\"\\\",s.style.borderLeft=\\\"\\\",s.style.boxShadow=\\\"\\\");let a=`${Math.round(n.left+i.x)}|${Math.round(i.y)}|${Math.round(i.height)}|${Math.round(n.left)}|${Math.round(n.width)}|${Math.round(n.height)}|${document.documentElement.clientWidth}|${c.animation}|${c.duration}`;s.dataset.motion!==a&&(s.dataset.motion=a,Vt(s,n,c))});for(let i=r.length-1;i>=e.length;i--)r[i].remove()}var xt=t=>t.parentElement?`${xt(t.parentElement)} > :nth-child(${[...t.parentElement.children].indexOf(t)+1})`:\\\":root\\\";function v(t){let e=t?.previousElementSibling,r=e?.querySelector(`:scope > [${H}]`),o=e?.querySelector(`:scope > [${G}]`);if(!e||!r||!o)return;let n=typeof CSSStyleSheet==\\\"function\\\"&&\\\"replaceSync\\\"in CSSStyleSheet.prototype?new CSSStyleSheet:null;n&&(document.adoptedStyleSheets=[...document.adoptedStyleSheets,n],e[U]=()=>{document.adoptedStyleSheets=document.adoptedStyleSheets.filter(s=>s!==n)});let c=s=>n?.replaceSync(s.size?`${[...s].map(xt).join(\\\", \\\")} { visibility: hidden !important; }`:\\\"\\\"),i=()=>{if(!o.isConnected||e[z])return l.disconnect();r.getClientRects().length&&St(o,mt(r,o,{mark:!1,onCovered:c}))},l=new ResizeObserver(i);l.observe(e),document.fonts?.ready.then(i)}var Rt=self,yt=Symbol.for(X),Tt=Rt[yt];Rt[yt]=v;Array.isArray(Tt)&&Tt.forEach(v);v(document.currentScript);})();\";\n\n/** For every skeleton after a page's first: calls the boot INLINE_SCRIPT left on window. */\nexport const INLINE_STUB = \"(s=>{let k=Symbol.for(\\\"a-smart-skeleton.boot\\\"),b=self[k];typeof b==\\\"function\\\"?b(s):(self[k]=b||[]).push(s)})(document.currentScript)\";\n\n/** Either, as a whole element — for templates where a literal script tag would be read as the component's own. */\nexport const inlineScriptTag = (nonce?: string, stub = false) =>\n `<script${nonce ? ` nonce=\"${nonce.replace(/\"/g, \""\")}\"` : \"\"}>${stub ? INLINE_STUB : INLINE_SCRIPT}</script>`;\n","import type { TextBottom, TextTop } from './measure';\n\nexport type SkeletonColors = {\n /** The skeleton's fill. */\n base: string;\n /** The shimmer sweeping across it. */\n highlight: string;\n};\n\n/** `shimmer` sweeps the whole page, `group-shimmer` each skeleton, `pulse` fades; all hold still under reduced motion. */\nexport type SkeletonAnimation = 'shimmer' | 'group-shimmer' | 'pulse' | 'none';\n\n/** How quickly the animation loops — each animation has its own slow and fast. */\nexport type SkeletonSpeed = 'slow' | 'fast';\n\n/** How much of each line of text is drawn: from the font's `top` line down to its `bottom` line. */\nexport type SkeletonText = { top?: TextTop; bottom?: TextBottom };\n\n/** `system` follows `prefers-color-scheme`; the others pin one set of colours. */\nexport type SkeletonMode = 'light' | 'dark' | 'system';\n\nexport type SkeletonTheme = {\n light?: SkeletonColors;\n dark?: SkeletonColors;\n /** How round each line of text, and any other single bar, is drawn — any CSS length; `999px` for pills. Images and chips keep their own. */\n radius?: string;\n animation?: SkeletonAnimation;\n speed?: SkeletonSpeed;\n text?: SkeletonText;\n};\n\nexport const DEFAULT_COLORS: { light: SkeletonColors; dark: SkeletonColors } = {\n light: { base: 'rgb(0 0 0 / 0.07)', highlight: 'rgb(255 255 255 / 0.6)' },\n dark: {\n base: 'rgb(255 255 255 / 0.08)',\n highlight: 'rgb(255 255 255 / 0.1)',\n },\n};\n\nexport const DEFAULT_THEME = {\n ...DEFAULT_COLORS,\n animation: 'shimmer',\n speed: 'slow',\n text: { top: 'ascender', bottom: 'descender' },\n} as const satisfies SkeletonTheme;\n\n// Colours pass through getComputedStyle without ever reaching the stylesheet, so\n// the custom-property declarations are the only path a string takes directly into\n// CSS text. A value with `;` or `}` would close its declaration and inject rules,\n// so the four keyword props are gated against their own enums and length-like props\n// are gated against a conservative length regex — anything else is dropped.\nconst ANIMATION = new Set<SkeletonAnimation>(['shimmer', 'group-shimmer', 'pulse', 'none']);\nconst SPEED = new Set<SkeletonSpeed>(['slow', 'fast']);\nconst TEXT_TOP = new Set<TextTop>(['ascender', 'cap-height', 'x-height']);\nconst TEXT_BOTTOM = new Set<TextBottom>(['baseline', 'descender']);\n\n// A CSS <length>, <percentage>, calc(), or the whitespace-separated list of them that\n// border-radius allows — digits, dots, whitespace, parens, and unit letters only.\n// Reject angle brackets and semicolons so no value can break out of the declaration.\nconst LENGTH = /^[\\d.\\s,%()+\\-*/a-z]+$/i;\n\nconst safeLength = (value: string): string | null => {\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > 100) return null;\n if (/[<>;}{\"'`]/.test(trimmed)) return null;\n return LENGTH.test(trimmed) ? trimmed : null;\n};\n\nconst safeColor = (value: string): string | null => {\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > 200) return null;\n if (/[;}<>]/.test(trimmed)) return null;\n return trimmed;\n};\n\n/** A theme's custom properties for one set of colours, for a style attribute. */\nexport function themeVariables(\n theme: SkeletonTheme = {},\n mode: 'light' | 'dark' | null = null\n): Record<string, string> {\n const variables: Record<string, string> = {};\n const colors = mode && (theme[mode] ?? DEFAULT_COLORS[mode]);\n if (colors) {\n const base = safeColor(colors.base);\n const highlight = safeColor(colors.highlight);\n if (base) variables['--ask-base'] = base;\n if (highlight) variables['--ask-highlight'] = highlight;\n }\n if (theme.radius) {\n const radius = safeLength(theme.radius);\n if (radius) variables['--ask-radius'] = radius;\n }\n if (theme.animation && ANIMATION.has(theme.animation)) {\n variables['--ask-animation'] = theme.animation;\n }\n if (theme.speed && SPEED.has(theme.speed)) {\n variables['--ask-speed'] = theme.speed;\n }\n if (theme.text?.top && TEXT_TOP.has(theme.text.top)) {\n variables['--ask-text-top'] = theme.text.top;\n }\n if (theme.text?.bottom && TEXT_BOTTOM.has(theme.text.bottom)) {\n variables['--ask-text-bottom'] = theme.text.bottom;\n }\n return variables;\n}\n\nconst declarations = (variables: Record<string, string>) =>\n Object.entries(variables)\n .map(([name, value]) => `${name}: ${value};`)\n .join(' ');\n\n/** CSS for a theme on `selector`; colours follow `mode`, and are left out when neither is given. */\nexport function skeletonCSS({\n theme = {},\n mode,\n text,\n selector = ':root',\n}: {\n theme?: SkeletonTheme;\n mode?: SkeletonMode;\n text?: SkeletonText;\n selector?: string;\n}): string {\n const resolved = { ...theme, text: { ...theme.text, ...text } };\n const colored = mode ?? (theme.light || theme.dark ? 'system' : null);\n const base = themeVariables(resolved, colored === 'dark' ? 'dark' : colored ? 'light' : null);\n\n const rules: string[] = [];\n if (Object.keys(base).length) {\n rules.push(`${selector} { ${declarations(base)} }`);\n }\n if (colored === 'system') {\n const dark = themeVariables({ dark: theme.dark }, 'dark');\n rules.push(`@media (prefers-color-scheme: dark) { ${selector} { ${declarations(dark)} } }`);\n }\n return rules.join('\\n');\n}\n\nlet themeEl: HTMLStyleElement | null = null;\n\n/** Sets a theme for the whole page, for setups without a provider. */\nexport function applyTheme(\n theme?: SkeletonTheme,\n mode?: SkeletonMode,\n { nonce }: { nonce?: string } = {}\n) {\n themeEl ??= document.head.appendChild(document.createElement('style'));\n if (nonce) themeEl.nonce = nonce;\n themeEl.textContent = skeletonCSS({ theme, mode });\n}\n\n/** The same CSS as a whole element, for templates that can only render HTML strings. */\nexport const themeStyleTag = (\n config: { theme?: SkeletonTheme; mode?: SkeletonMode; text?: SkeletonText },\n nonce?: string\n) => {\n const css = skeletonCSS(config);\n return css\n ? `<style${nonce ? ` nonce=\"${nonce.replace(/\"/g, '"')}\"` : ''}>${css}</style>`\n : '';\n};\n","import { ATTR_DEBUG, ATTR_XRAY } from './constants';\n\ntype Entry = {\n state: 'loading' | 'shown';\n source?: string;\n moved?: { width: number; height: number };\n};\n\nconst entries = new Map<Element, Entry>();\nlet enabled: boolean | undefined;\nlet host: HTMLElement | null = null;\nlet frame = 0;\n\nfunction fromPage() {\n try {\n return (\n new URLSearchParams(location.search).has('ask-debug') ||\n localStorage.getItem('a-smart-skeleton:debug') === '1'\n );\n } catch {\n return false;\n }\n}\n\nconst everywhere = () => (enabled ??= typeof window !== 'undefined' && fromPage());\n\n/** On with `?ask-debug`, `a-smart-skeleton:debug` = \"1\" in localStorage or `setDebug(true)`; for `element`, also inside `[ask-debug]`. */\nexport const debugging = (element?: Element | null) =>\n everywhere() || !!element?.closest(`[${ATTR_DEBUG}]`);\n\nexport function setDebug(on: boolean) {\n enabled = on;\n if (on) start();\n else stop();\n}\n\nexport function reportLoading(reveal: Element | null, source: string) {\n if (!reveal || !debugging(reveal)) return;\n entries.set(reveal, { state: 'loading', source });\n show();\n}\n\nexport function reportReveal(reveal: Element | null, moved: { width: number; height: number }) {\n if (!reveal || !debugging(reveal)) return;\n entries.set(reveal, { ...entries.get(reveal), state: 'shown', moved });\n show();\n}\n\n// Drawn at once, not on the next frame: a throttled page, like a test's iframe, may wait long for one\nfunction show() {\n start();\n cancelAnimationFrame(frame);\n draw();\n}\n\nconst PANEL_CSS = `\n:host { all: initial; }\n.box { position: fixed; box-sizing: border-box; border: 1px dashed; border-radius: 4px; }\n.label {\n position: absolute; left: -1px; bottom: 100%; margin-bottom: 2px;\n padding: 1px 6px; border-radius: 4px; white-space: nowrap;\n font: 500 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace; color: #fff;\n}\n.loading { border-color: #3b82f6; } .loading .label { background: #3b82f6; }\n.still { border-color: #22c55e; } .still .label { background: #16a34a; }\n.moved { border-color: #ef4444; border-style: solid; } .moved .label { background: #dc2626; }\n.panel {\n position: fixed; right: 12px; bottom: 12px; display: flex; gap: 8px; align-items: center;\n padding: 6px 10px; border-radius: 8px; background: #111; color: #fff; pointer-events: auto;\n font: 500 12px/16px ui-sans-serif, system-ui, sans-serif; box-shadow: 0 4px 16px rgb(0 0 0 / 0.3);\n}\n.panel label { display: flex; gap: 4px; align-items: center; cursor: pointer; }\n`;\n\nfunction start() {\n if (typeof document === 'undefined') return;\n if (!host?.isConnected) {\n host = document.createElement('div');\n host.style.cssText = 'position:fixed;inset:0;pointer-events:none;z-index:2147483647';\n const shadow = host.attachShadow({ mode: 'open' });\n shadow.innerHTML = `<style>${PANEL_CSS}</style><div class=\"boxes\"></div>`;\n document.body.append(host);\n }\n // The panel, and its x-ray toggle, are for the whole page only\n const shadow = host.shadowRoot!;\n if (enabled && !shadow.querySelector('.panel')) {\n const panel = document.createElement('div');\n panel.className = 'panel';\n panel.innerHTML = `a-smart-skeleton debug <label><input type=\"checkbox\" class=\"xray\"> x-ray</label>`;\n panel.querySelector('.xray')!.addEventListener('change', (event) => {\n document.documentElement.toggleAttribute(\n ATTR_XRAY,\n (event.target as HTMLInputElement).checked\n );\n });\n shadow.append(panel);\n }\n if (!frame) frame = requestAnimationFrame(draw);\n}\n\nfunction stop() {\n host?.shadowRoot?.querySelector('.panel')?.remove();\n document.documentElement.removeAttribute(ATTR_XRAY);\n if ([...entries.keys()].some((reveal) => debugging(reveal))) return;\n cancelAnimationFrame(frame);\n frame = 0;\n host?.remove();\n host = null;\n}\n\nconst describe = ({ state, source, moved }: Entry) => {\n const from = source ? ` · ${source}` : '';\n if (state === 'loading') return { kind: 'loading', text: `skeleton${from}` };\n if (!moved || (moved.width === 0 && moved.height === 0)) {\n return { kind: 'still', text: `✓ no movement${from}` };\n }\n return {\n kind: 'moved',\n text: `✗ moved ${moved.width}×${moved.height}px${from}`,\n };\n};\n\n// Follows every tracked reveal each frame, so scrolling and layout never leave a box behind\nfunction draw() {\n frame = 0;\n if (!host?.shadowRoot) return;\n const boxes = host.shadowRoot.querySelector('.boxes')!;\n\n for (const reveal of entries.keys()) {\n if (!reveal.isConnected || !debugging(reveal)) entries.delete(reveal);\n }\n\n const items = [...entries];\n while (boxes.children.length > items.length) boxes.lastElementChild!.remove();\n items.forEach(([reveal, entry], index) => {\n let box = boxes.children[index] as HTMLElement | undefined;\n if (!box) {\n box = boxes.appendChild(document.createElement('div'));\n box.innerHTML = `<span class=\"label\"></span>`;\n }\n const rect = reveal.getBoundingClientRect();\n const { kind, text } = describe(entry);\n box.className = `box ${kind}`;\n Object.assign(box.style, {\n left: `${rect.left - 2}px`,\n top: `${rect.top - 2}px`,\n width: `${rect.width + 4}px`,\n height: `${rect.height + 4}px`,\n });\n box.firstElementChild!.textContent = text;\n });\n\n if (enabled || entries.size) frame = requestAnimationFrame(draw);\n}\n","let context: CanvasRenderingContext2D | null | undefined;\n\n// jsdom has no canvas, and logs an error for every context asked of it\nexport const textContext = () =>\n (context ??= /jsdom/.test(navigator.userAgent)\n ? null\n : document.createElement('canvas').getContext('2d'));\n","import { textContext } from './canvas';\nimport { ATTR_COVERED, MEDIA_TAGS } from './constants';\n\nconst MEDIA = new Set(MEDIA_TAGS);\nconst REMOVED = 'script, noscript, template, base, meta, link';\nconst REPLACED = new Set(['iframe', 'object', 'embed']);\nconst STRIPPED = new Set([\n 'src',\n 'srcset',\n 'sizes',\n 'poster',\n 'data',\n 'srcdoc',\n 'action',\n 'formaction',\n 'formtarget',\n 'background',\n 'ping',\n 'dynsrc',\n 'lowsrc',\n 'value',\n 'alt',\n ATTR_COVERED,\n]);\n\n// A style attribute saved from an unknown origin can carry `url(javascript:…)`,\n// `expression(…)` (legacy IE), or close the attribute to inject rules; drop the whole\n// attribute if any show up — `data:` URLs in CSS are left alone because they render\n// as images, not documents, and are a routine way to inline background art.\nconst STYLE_UNSAFE = /url\\s*\\(\\s*['\"]?\\s*(javascript|vbscript):|expression\\s*\\(|<|>/i;\n\nexport const fill = (value: string) =>\n value.replace(/[A-Z]/g, 'X').replace(/[a-z]/g, 'x').replace(/\\d/g, '0');\n\n// Filler has different glyphs to the text it replaces; letter-spacing makes up the difference, so it wraps the same\nfunction fillText(original: Text, copy: Text) {\n const filled = fill(copy.data);\n copy.data = filled;\n\n const parent = original.parentElement;\n const context = textContext();\n if (!parent || !context || !filled.trim()) return;\n\n const style = getComputedStyle(parent);\n context.font = `${style.fontStyle} ${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;\n const shape = (value: string) => {\n const collapsed = value.replace(/\\s+/g, ' ');\n if (style.textTransform === 'uppercase') return collapsed.toUpperCase();\n if (style.textTransform === 'lowercase') return collapsed.toLowerCase();\n return collapsed;\n };\n\n const target = context.measureText(shape(original.data)).width;\n const current = context.measureText(shape(filled)).width;\n const delta = (target - current) / shape(filled).length;\n if (Math.abs(delta) < 0.01) return;\n\n const span = document.createElement('span');\n span.style.letterSpacing = `${(parseFloat(style.letterSpacing) || 0) + delta}px`;\n copy.replaceWith(span);\n span.append(copy);\n}\n\nfunction sanitize(root: ParentNode) {\n for (const element of root.querySelectorAll(REMOVED)) element.remove();\n\n for (const element of root.querySelectorAll('*')) {\n if (REPLACED.has(element.localName)) {\n const stand = document.createElement('span');\n stand.style.cssText = element.getAttribute('style') ?? '';\n stand.style.display ||= 'inline-block';\n element.replaceWith(stand);\n continue;\n }\n\n for (const { name, value } of [...element.attributes]) {\n const lower = name.toLowerCase();\n const unsafe =\n lower.startsWith('on') ||\n STRIPPED.has(lower) ||\n (lower.endsWith('href') && /^\\s*(javascript|vbscript|data):/i.test(value)) ||\n (lower === 'style' && STYLE_UNSAFE.test(value));\n if (unsafe) element.removeAttribute(name);\n }\n\n if (element.localName === 'img') element.setAttribute('alt', '');\n }\n\n for (const source of root.querySelectorAll('video source, picture source')) {\n source.remove();\n }\n}\n\n/** The markup in `root`, safe to keep: no scripts, handlers or media sources; `filler` replaces its text too. */\nexport function serialize(root: HTMLElement, filler: boolean): string {\n const clone = root.cloneNode(true) as HTMLElement;\n const show = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT;\n const original = document.createTreeWalker(root, show);\n const copy = document.createTreeWalker(clone, show);\n\n const texts: [Text, Text][] = [];\n const media: [Element, HTMLElement][] = [];\n while (original.nextNode() && copy.nextNode()) {\n const a = original.currentNode;\n const b = copy.currentNode;\n if (a.nodeType === Node.TEXT_NODE) {\n if (filler) texts.push([a as Text, b as Text]);\n } else if (MEDIA.has((a as Element).localName) || REPLACED.has((a as Element).localName)) {\n media.push([a as Element, b as HTMLElement]);\n }\n }\n\n // Applied after the walk, which would lose its place in a tree changing under it\n for (const [a, b] of media) {\n const rect = a.getBoundingClientRect();\n b.style.boxSizing = 'border-box';\n b.style.width = `${rect.width}px`;\n if (rect.width && rect.height) {\n // Its proportions, not its pixels: restored somewhere narrower, it scales down as the real one would\n b.style.maxWidth = '100%';\n b.style.height = 'auto';\n b.style.aspectRatio = `${rect.width} / ${rect.height}`;\n } else {\n b.style.height = `${rect.height}px`;\n }\n }\n for (const [a, b] of texts) fillText(a, b);\n\n sanitize(clone);\n return clone.innerHTML;\n}\n\nexport function restore(html: string): DocumentFragment {\n const template = document.createElement('template');\n template.innerHTML = html;\n sanitize(template.content);\n return template.content;\n}\n\nconst signature = (element: Element, depth: number): string =>\n [...element.children]\n .map((child) => {\n const classes = [...child.classList].sort().join('.');\n const inner = depth > 1 && child.firstElementChild ? `(${signature(child, depth - 1)})` : '';\n return `${child.localName}${classes ? `.${classes}` : ''}${inner}`;\n })\n .join(',');\n\nconst hash = (value: string) => {\n let h = 5381;\n for (let i = 0; i < value.length; i++) h = (h * 33) ^ value.charCodeAt(i);\n return (h >>> 0).toString(36);\n};\n\n/** Identifies content by its page and the shape of its top two levels — the parts that rarely hang on data. */\nexport function autoKey(element: Element): string | null {\n const shape = signature(element, 2);\n return shape ? `${location.pathname}|${hash(shape)}` : null;\n}\n","import { fill } from './snapshot';\n\ndeclare const process: { env: { NODE_ENV?: string } };\n\nlet dev = false;\ntry {\n // Bundlers replace the whole expression; with none, `process` doesn't exist\n dev = process.env.NODE_ENV !== 'production';\n} catch {\n dev = false;\n}\n\nexport const isDev = dev;\n\nconst warned = new Set<string>();\n\nexport function warnOnce(id: string, message: string) {\n if (!isDev || warned.has(id)) return;\n warned.add(id);\n // eslint-disable-next-line no-console\n console.warn(`[a-smart-skeleton] ${message}`);\n}\n\nconst URL_LIKE = /^(https?:|\\/|data:|blob:)/;\n\n/**\n * Warns once per app if the page has a meta CSP that restricts inline scripts and\n * the consumer did not pass a nonce through the provider. Silent when CSP is absent\n * or when the loading pane isn't on the client yet — we can't read CSP headers from\n * script, so the meta-tag check is a best-effort signal to developers.\n */\nexport function checkNonce(nonce: string | undefined): void {\n if (!isDev || typeof document === 'undefined' || nonce) return;\n const meta = document.querySelector('meta[http-equiv=\"Content-Security-Policy\" i]');\n const content = meta?.getAttribute('content') ?? '';\n if (!/script-src/i.test(content)) return;\n if (/'unsafe-inline'/.test(content) || /\\*/.test(content)) return;\n warnOnce(\n 'csp:missing-nonce',\n 'ASmartSkeleton ships an inline boot script that measures the server-rendered skeleton before first paint. Your page has a Content-Security-Policy with script-src but no nonce was passed to <ASmartSkeletonProvider :nonce=\"…\">, so the browser will block it and first paint will be blank. Pass the same nonce you used for the response header.'\n );\n}\n\n/** Same keys and lengths as `data`, with every string replaced by filler. */\nexport function sampleFrom(data: unknown): unknown {\n if (typeof data === 'string') return URL_LIKE.test(data) ? '' : fill(data);\n if (Array.isArray(data)) return data.map(sampleFrom);\n if (data instanceof Date) return data;\n if (data && typeof data === 'object') {\n return Object.fromEntries(Object.entries(data).map(([key, value]) => [key, sampleFrom(value)]));\n }\n return data;\n}\n","import { textContext } from './canvas';\nimport {\n ATTR_BLOCK,\n ATTR_COVERED,\n ATTR_IGNORE,\n ATTR_OWN,\n MEDIA_TAGS,\n TEXT_TAGS,\n} from './constants';\n\n/** Captured paint from a container — background / borders / box-shadow — reproduced on\n * the chrome bone so the outline survives shape recall from storage, SSR pre-paint, and\n * any path where the real DOM isn't visible under the layer. */\nexport type SkeletonChrome = {\n background?: string;\n borderTop?: string;\n borderRight?: string;\n borderBottom?: string;\n borderLeft?: string;\n boxShadow?: string;\n};\n\n/** A box to draw, relative to the layer it was measured against. */\nexport type SkeletonRect = {\n /** Which kind of leaf this bone stands in for — exposed as `[ask-rect=\"<type>\"]` so\n * consumers can style text / media / box / chrome bones differently in their own CSS. */\n type: 'text' | 'media' | 'box' | 'chrome';\n x: number;\n y: number;\n width: number;\n height: number;\n radius: string;\n /** Present on `type === 'chrome'` bones — the container's own paint, captured verbatim from `getComputedStyle`. */\n chrome?: SkeletonChrome;\n};\n\ntype Rect = { left: number; right: number; top: number; bottom: number };\n\n// Corner radii in px: top left, top right, bottom right, bottom left\ntype Corners = [number, number, number, number];\n\n// Overflow a box hides, which a bone must not paint past, with the corners it rounds; null while nothing clips\ntype Clip = (Rect & { corners: Corners }) | null;\n\nconst intersect = (clip: Clip, rect: Rect): Rect =>\n clip\n ? {\n left: Math.max(clip.left, rect.left),\n right: Math.min(clip.right, rect.right),\n top: Math.max(clip.top, rect.top),\n bottom: Math.min(clip.bottom, rect.bottom),\n }\n : rect;\n\nconst cornersOf = (rect: Rect): [number, number][] => [\n [rect.left, rect.top],\n [rect.right, rect.top],\n [rect.right, rect.bottom],\n [rect.left, rect.bottom],\n];\n\nconst near = (a: [number, number], b: [number, number]) =>\n Math.abs(a[0] - b[0]) < 1 && Math.abs(a[1] - b[1]) < 1;\n\nfunction radiiOf(style: CSSStyleDeclaration, rect: Rect): Corners {\n const size = Math.min(rect.right - rect.left, rect.bottom - rect.top);\n const px = (value: string) =>\n value.endsWith('%') ? (parseFloat(value) / 100) * size : parseFloat(value) || 0;\n return [\n px(style.borderTopLeftRadius),\n px(style.borderTopRightRadius),\n px(style.borderBottomRightRadius),\n px(style.borderBottomLeftRadius),\n ];\n}\n\n// A clip within a clip: each corner rounds as whichever box's corner it is\nfunction clipWithin(clip: Clip, rect: Rect, style: CSSStyleDeclaration): Clip {\n const box = intersect(clip, rect);\n const own = radiiOf(style, rect);\n const outer = clip ? cornersOf(clip) : [];\n const ownCorners = cornersOf(rect);\n const corners = cornersOf(box).map((corner, i) =>\n near(corner, ownCorners[i]!) ? own[i]! : clip && near(corner, outer[i]!) ? clip.corners[i]! : 0\n ) as Corners;\n // Sides by name: a DOMRect's are getters, which spreading leaves behind\n const { left, right, top, bottom } = box;\n return { left, right, top, bottom, corners };\n}\n\n// A block in a rounded corner of what clips it is cut by that corner, so takes it\nfunction roundedBy(clip: Clip, box: Rect, own: string, style: CSSStyleDeclaration) {\n if (!clip) return own;\n const clipCorners = cornersOf(clip);\n const touching = cornersOf(box).map(\n (corner, i) => clip.corners[i]! > 0 && near(corner, clipCorners[i]!)\n );\n if (!touching.some(Boolean)) return own;\n const mine = radiiOf(style, box);\n return touching\n .map((touches, i) => (touches ? Math.max(mine[i]!, clip.corners[i]!) : mine[i]!))\n .map((r) => `${r}px`)\n .join(' ');\n}\n\n// Clipped to a sliver, it isn't seen: a visually hidden label, say, cut to a 1px box\nconst clipped = (rect: Rect, clip: Clip): Rect | null => {\n const box = intersect(clip, rect);\n return box.right - box.left >= 2 && box.bottom - box.top >= 2 ? box : null;\n};\n\ntype Line = {\n left: number;\n right: number;\n top: number;\n bottom: number;\n fontSize: number;\n /** Where the bar goes, by the typography rules — within the line's box. */\n barTop: number;\n barBottom: number;\n /** The theme's `--ask-radius`, if it sets one. */\n radius: string;\n};\n\n/** The font line each line of text is drawn from. */\nexport type TextTop = 'ascender' | 'cap-height' | 'x-height';\n/** The font line each line of text is drawn down to. */\nexport type TextBottom = 'baseline' | 'descender';\n\nexport const DEFAULT_TEXT = {\n top: 'ascender',\n bottom: 'descender',\n} as const satisfies { top: TextTop; bottom: TextBottom };\n\ntype Metrics = {\n ascent: number; // the font's own box, above and below the baseline\n descent: number;\n ascender: number; // ink of b, d, h, l\n capHeight: number;\n xHeight: number;\n descender: number; // ink of g, p, y\n};\n\nconst metricsByFont = new Map<string, Metrics | null>();\n\n// A range has no layout in jsdom\nconst lineRects = (range: Range) => [...(range.getClientRects?.() ?? [])];\n\nfunction metricsOf(style: CSSStyleDeclaration): Metrics | null {\n const font = `${style.fontStyle} ${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;\n if (metricsByFont.has(font)) return metricsByFont.get(font)!;\n\n const context = textContext();\n let metrics: Metrics | null = null;\n if (context) {\n context.font = font;\n const box = context.measureText('H');\n const up = (text: string) => context!.measureText(text).actualBoundingBoxAscent;\n metrics = {\n ascent: box.fontBoundingBoxAscent,\n descent: box.fontBoundingBoxDescent,\n ascender: up('bdfhkl'),\n capHeight: box.actualBoundingBoxAscent,\n xHeight: up('xz'),\n descender: context.measureText('gjpqy').actualBoundingBoxDescent,\n };\n }\n metricsByFont.set(font, metrics);\n return metrics;\n}\n\nconst TOPS: Record<TextTop, keyof Metrics> = {\n ascender: 'ascender',\n 'cap-height': 'capHeight',\n 'x-height': 'xHeight',\n};\n\nconst rule = <T extends string>(\n style: CSSStyleDeclaration,\n name: string,\n allowed: readonly T[],\n fallback: T\n): T => {\n const value = style.getPropertyValue(name).trim() as T;\n return allowed.includes(value) ? value : fallback;\n};\n\n// Between the font lines `--ask-text-top` and `--ask-text-bottom` name, the baseline half-leading in\nfunction barOf(rect: Rect, style: CSSStyleDeclaration, fontSize: number) {\n const metrics = metricsOf(style);\n if (!metrics) {\n // No canvas to read the type with: a bar centred in the line\n const height = Math.min(fontSize * 0.72, rect.bottom - rect.top);\n const middle = (rect.top + rect.bottom) / 2;\n return { barTop: middle - height / 2, barBottom: middle + height / 2 };\n }\n\n const top = rule(style, '--ask-text-top', Object.keys(TOPS) as TextTop[], DEFAULT_TEXT.top);\n const bottom = rule(\n style,\n '--ask-text-bottom',\n ['baseline', 'descender'] as const,\n DEFAULT_TEXT.bottom\n );\n\n const box = metrics.ascent + metrics.descent;\n const baseline = rect.top + (rect.bottom - rect.top - box) / 2 + metrics.ascent;\n return {\n barTop: baseline - metrics[TOPS[top]],\n barBottom: baseline + (bottom === 'descender' ? metrics.descender : 0),\n };\n}\n\nconst MEDIA = new Set(MEDIA_TAGS);\nconst TEXT = new Set(TEXT_TAGS);\n\nconst LINE_GAP = 0.4; // of the font size — wider than a space, so one line of text stays one bar\n\n// matches a zero alpha in both `rgba(0, 0, 0, 0)` and `color(srgb 0 0 0 / 0)`\nconst TRANSPARENT = /[,/]\\s*0\\)$/;\n\n// Unset reads as \"\" outside a browser engine, which is no paint either\nconst isSet = (value: string, none: string) => value !== '' && value !== none;\n\n// All the way round: a rule along one side divides, it doesn't make a box a chip\nconst SIDES = ['Top', 'Right', 'Bottom', 'Left'] as const;\nconst bordered = (style: CSSStyleDeclaration) =>\n SIDES.every(\n (side) =>\n isSet(style[`border${side}Style`], 'none') && isSet(style[`border${side}Width`], '0px')\n );\n\n// Dividers (`border-t` on a footer, `border-b` on a heading) still need to show\n// up in the skeleton, even though they don't make the container a solid block.\n// This looser check feeds chrome capture; `bordered` above remains what\n// `isPainted` reads so single-side borders keep their \"divider\" semantics for\n// the isBlock classifier.\nconst anyBordered = (style: CSSStyleDeclaration) =>\n SIDES.some(\n (side) =>\n isSet(style[`border${side}Style`], 'none') && isSet(style[`border${side}Width`], '0px')\n );\n\n// An inset hairline along one side, drawn as a shadow, is a divider like a one-sided border\nconst isRule = (shadow: string) => {\n const [x = 0, y = 0, blur = 0, spread = 0] = (\n shadow.replace(/rgba?\\([^)]*\\)|#\\w+/g, '').match(/-?[\\d.]+px/g) ?? []\n ).map(parseFloat);\n return (\n shadow.includes('inset') && !blur && !spread && (x === 0) !== (y === 0) && Math.abs(x + y) <= 2\n );\n};\n\nconst shadowPaints = (boxShadow: string) =>\n isSet(boxShadow, 'none') && !boxShadow.split(/,(?![^(]*\\))/).every(isRule);\n\n/** Splits `background-image` on its top-level commas (respecting nested parens, which\n * gradient stops abuse heavily) and drops any layer that starts with `url(`. Returns\n * an empty string when nothing survives — the caller treats that as \"no background\". */\nfunction stripUrlLayers(bgImage: string): string {\n const layers: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < bgImage.length; i++) {\n const ch = bgImage[i];\n if (ch === '(') depth++;\n else if (ch === ')') depth--;\n else if (ch === ',' && depth === 0) {\n layers.push(bgImage.slice(start, i));\n start = i + 1;\n }\n }\n layers.push(bgImage.slice(start));\n return layers\n .map((l) => l.trim())\n .filter((l) => l && !l.startsWith('url('))\n .join(', ');\n}\n\nconst isPainted = (style: CSSStyleDeclaration) =>\n (isSet(style.backgroundColor, 'transparent') && !TRANSPARENT.test(style.backgroundColor)) ||\n isSet(style.backgroundImage, 'none') ||\n shadowPaints(style.boxShadow) ||\n bordered(style);\n\n/** Reads the painted chrome off a container so the skeleton can reproduce it exactly —\n * background, four border sides, and box-shadow, but only the properties that are set.\n * Returns `undefined` when nothing paints, so callers can skip emitting a chrome bone. */\nfunction captureChrome(style: CSSStyleDeclaration): SkeletonChrome | undefined {\n const chrome: SkeletonChrome = {};\n\n const bg = style.backgroundColor;\n if (isSet(bg, 'transparent') && !TRANSPARENT.test(bg)) chrome.background = bg;\n // Keep gradient layers (Tailwind ring utilities, shadcn chrome, etc.) but drop\n // `url(...)` layers — a hero bitmap re-downloaded into the skeleton is wasteful\n // and almost always wrong.\n const bgImage = style.backgroundImage;\n if (isSet(bgImage, 'none')) {\n const gradientsOnly = stripUrlLayers(bgImage);\n if (gradientsOnly) {\n chrome.background = chrome.background\n ? `${gradientsOnly}, ${chrome.background}`\n : gradientsOnly;\n }\n }\n\n for (const side of SIDES) {\n const width = style[`border${side}Width`];\n const styleProp = style[`border${side}Style`];\n const color = style[`border${side}Color`];\n if (isSet(styleProp, 'none') && isSet(width, '0px') && parseFloat(width) > 0) {\n const key = `border${side}` as 'borderTop' | 'borderRight' | 'borderBottom' | 'borderLeft';\n chrome[key] = `${width} ${styleProp} ${color}`;\n }\n }\n\n if (shadowPaints(style.boxShadow)) chrome.boxShadow = style.boxShadow;\n\n return Object.keys(chrome).length ? chrome : undefined;\n}\n\nconst isMedia = (element: Element) => MEDIA.has(element.localName);\n\nconst isEmptyText = (element: Element) =>\n TEXT.has(element.localName) && !element.firstElementChild && !element.textContent?.trim();\n\n/** Labels inside: one per piece of text, however many lines it wraps to or nodes it's split into. */\nconst countLabels = (element: Element) => {\n const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT);\n const range = document.createRange();\n const pieces: DOMRect[][] = [];\n let nodes = 0;\n while (walker.nextNode()) {\n const node = walker.currentNode;\n if (node.nodeType === Node.TEXT_NODE) {\n const parent = node.parentElement;\n if (!node.textContent?.trim() || !parent) continue;\n nodes++;\n // Visually hidden text, read to screen readers only\n const box = parent.getBoundingClientRect();\n if (box.width <= 1 || box.height <= 1) continue;\n range.selectNodeContents(node);\n pieces.push(lineRects(range).filter((r) => r.width || r.height));\n } else if (isEmptyText(node as Element)) {\n nodes++;\n pieces.push([...(node as Element).getClientRects()]);\n }\n }\n // No layout to go by\n if (!pieces.some((rects) => rects.length)) return nodes;\n\n const reach = (parseFloat(getComputedStyle(element).fontSize) || 16) * LINE_GAP;\n const beside = (a: DOMRect, b: DOMRect) =>\n Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top) >= Math.min(a.height, b.height) / 2 &&\n Math.max(a.left, b.left) - Math.min(a.right, b.right) <= reach;\n\n // Pieces joined into labels: each starts as its own, and merges with any beside it\n const label = pieces.map((_, i) => i);\n const find = (i: number): number => (label[i] === i ? i : (label[i] = find(label[i]!)));\n for (let i = 0; i < pieces.length; i++) {\n for (let j = i + 1; j < pieces.length; j++) {\n if (pieces[i]!.some((a) => pieces[j]!.some((b) => beside(a, b)))) {\n label[find(j)] = find(i);\n }\n }\n }\n return new Set(pieces.map((_, i) => find(i))).size;\n};\n\n// A painted box around one label (a button, a chip) fills as a block, a card keeps its surface\nconst isBlock = (element: Element, style: CSSStyleDeclaration) =>\n element.hasAttribute(ATTR_BLOCK) ||\n isMedia(element) ||\n (isPainted(style) && countLabels(element) <= 1);\n\n// Media clipped by a rounded parent of the same size, like an avatar, takes the parent's corners\nfunction radiusOf(element: Element, style: CSSStyleDeclaration) {\n if (parseFloat(style.borderRadius) || !element.parentElement) {\n return style.borderRadius || '0px';\n }\n const parent = element.parentElement;\n const parentStyle = getComputedStyle(parent);\n const a = element.getBoundingClientRect();\n const b = parent.getBoundingClientRect();\n const same = Math.abs(a.width - b.width) < 1 && Math.abs(a.height - b.height) < 1;\n return same && parentStyle.overflow !== 'visible'\n ? parentStyle.borderRadius\n : style.borderRadius || '0px';\n}\n\nfunction toBars(lines: Line[]): SkeletonRect[] {\n // Left to right, so each fragment only ever extends a bar to its left\n lines.sort((a, b) => a.left - b.left);\n\n const merged: Line[] = [];\n for (const line of lines) {\n const last = merged.find((m) => {\n const overlap = Math.min(m.bottom, line.bottom) - Math.max(m.top, line.top);\n const shorter = Math.min(m.bottom - m.top, line.bottom - line.top);\n const gap = line.left - m.right;\n return overlap >= shorter / 2 && gap <= Math.max(m.fontSize, line.fontSize) * LINE_GAP;\n });\n\n if (last) {\n last.left = Math.min(last.left, line.left);\n last.right = Math.max(last.right, line.right);\n last.top = Math.min(last.top, line.top);\n last.bottom = Math.max(last.bottom, line.bottom);\n last.fontSize = Math.max(last.fontSize, line.fontSize);\n last.barTop = Math.min(last.barTop, line.barTop);\n last.barBottom = Math.max(last.barBottom, line.barBottom);\n } else {\n merged.push({ ...line });\n }\n }\n\n return merged.map((line) => {\n const height = line.barBottom - line.barTop;\n return {\n type: 'text' as const,\n x: line.left,\n y: line.barTop,\n width: line.right - line.left,\n height,\n radius: line.radius || `${Math.round(height / 3)}px`,\n };\n });\n}\n\n/** Measures what `root` holds into rects relative to `layer`; without `mark`, `root` is left untouched. */\nexport function measureSkeleton(\n root: HTMLElement,\n layer: HTMLElement,\n {\n mark = true,\n onCovered,\n }: {\n mark?: boolean;\n /** What's drawn as one block, its own paint to hide — for a caller that can't mark it. */\n onCovered?: (covered: Set<Element>) => void;\n } = {}\n): SkeletonRect[] {\n const origin = layer.getBoundingClientRect();\n // Rects are post-transform; bones are drawn inside the same transform\n const scaleX = layer.offsetWidth ? origin.width / layer.offsetWidth : 1;\n const scaleY = layer.offsetHeight ? origin.height / layer.offsetHeight : 1;\n\n const local = (rect: Rect) => ({\n left: (rect.left - origin.left) / scaleX,\n right: (rect.right - origin.left) / scaleX,\n top: (rect.top - origin.top) / scaleY,\n bottom: (rect.bottom - origin.top) / scaleY,\n });\n\n const blocks: SkeletonRect[] = [];\n const lines: Line[] = [];\n const covered = new Set<Element>();\n const range = document.createRange();\n\n const addLine = (rect: DOMRect, style: CSSStyleDeclaration, clip: Clip) => {\n const box = clipped(rect, clip);\n if (!box) return;\n const fontSize = parseFloat(style.fontSize) || 16;\n const line = local(box);\n lines.push({\n ...line,\n fontSize,\n ...barOf(line, style, fontSize),\n radius: style.getPropertyValue('--ask-radius').trim(),\n });\n };\n\n const addText = (node: Text, clip: Clip) => {\n const start = node.data.search(/\\S/);\n if (start < 0 || !node.parentElement) return;\n range.setStart(node, start);\n range.setEnd(node, node.data.trimEnd().length);\n const style = getComputedStyle(node.parentElement);\n for (const rect of lineRects(range)) addLine(rect, style, clip);\n };\n\n const visit = (parent: Element, clip: Clip) => {\n for (const node of parent.childNodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n addText(node as Text, clip);\n continue;\n }\n if (node.nodeType !== Node.ELEMENT_NODE) continue;\n\n const element = node as Element;\n if (element.hasAttribute(ATTR_IGNORE) || element.hasAttribute(ATTR_OWN)) {\n continue;\n }\n\n const style = getComputedStyle(element);\n if (style.display === 'none') continue;\n\n if (isBlock(element, style)) {\n const visible = clipped(element.getBoundingClientRect(), clip);\n if (visible) {\n const box = local(visible);\n blocks.push({\n type: isMedia(element) ? 'media' : 'box',\n x: box.left,\n y: box.top,\n width: box.right - box.left,\n height: box.bottom - box.top,\n radius: roundedBy(clip, visible, radiusOf(element, style), style),\n });\n }\n if (!isMedia(element)) covered.add(element);\n continue;\n }\n\n if (isEmptyText(element)) {\n for (const rect of element.getClientRects()) {\n addLine(rect, style, clip);\n }\n continue;\n }\n\n // A painted container (a card, a chip) doesn't become a solid block — it still\n // has interior bones to measure — but its own paint (bg / border / radius / shadow)\n // is captured as a `chrome` bone so the outline survives shape recall and SSR\n // pre-paint, when the real DOM isn't painted under the layer yet. Emitted BEFORE\n // the recursion so it draws underneath the interior bones in document order.\n //\n // Single-side borders (`border-t` on a footer divider) deliberately fail\n // `isPainted` — they're dividers, not chip paint — but they still need to\n // appear in the skeleton, so `anyBordered` widens the capture trigger.\n if (isPainted(style) || anyBordered(style)) {\n const chrome = captureChrome(style);\n if (chrome) {\n const visible = clipped(element.getBoundingClientRect(), clip);\n if (visible) {\n const box = local(visible);\n blocks.push({\n type: 'chrome',\n x: box.left,\n y: box.top,\n width: box.right - box.left,\n height: box.bottom - box.top,\n radius: roundedBy(clip, visible, radiusOf(element, style), style),\n chrome,\n });\n }\n }\n }\n\n const clips = style.overflowX !== 'visible' || style.overflowY !== 'visible';\n visit(element, clips ? clipWithin(clip, element.getBoundingClientRect(), style) : clip);\n }\n };\n\n visit(root, null);\n onCovered?.(covered);\n\n if (!mark) return [...blocks, ...toBars(lines)];\n\n // Only touched when they change, so a MutationObserver watching `root` settles\n for (const element of root.querySelectorAll(`[${ATTR_COVERED}]`)) {\n if (!covered.has(element)) element.removeAttribute(ATTR_COVERED);\n }\n for (const element of covered) {\n if (!element.hasAttribute(ATTR_COVERED)) {\n element.setAttribute(ATTR_COVERED, '');\n }\n }\n\n return [...blocks, ...toBars(lines)];\n}\n","const prefers = (query: string) => typeof matchMedia !== 'undefined' && matchMedia(query).matches;\n\n// Not in jsdom, where every fade is instant\nexport const canAnimate = () =>\n typeof Element !== 'undefined' && typeof Element.prototype.animate === 'function';\n\nexport const prefersReducedMotion = () =>\n !canAnimate() || prefers('(prefers-reduced-motion: reduce)');\n\nexport const prefersReducedTransparency = () => prefers('(prefers-reduced-transparency: reduce)');\n\nexport const animationsOf = (element: Element): Animation[] => element.getAnimations?.() ?? [];\n","import { ATTR_RECT, DURATIONS, HIGHLIGHT } from './constants';\nimport type { SkeletonAnimation, SkeletonSpeed } from './theme';\nimport { animationsOf, prefersReducedMotion } from './motion';\nimport type { SkeletonRect } from './measure';\n\nconst SWEEP = 0.7; // of a duration a sweep takes at the reference width — sweeps run back to back, so this sets the pace\nconst REFERENCE_WIDTH = 1280; // A shimmer's duration is one loop across this; any other width keeps its pace\nconst MAX_BAND = 320; // The highlight's width, so it doesn't grow heavier on a wide screen\nconst SPACING = 2.5; // bands follow each other this many band-widths apart, start to start — the gap between sweeps\nconst PULSE_LOW = 0.45; // opacity at the bottom of a pulse\n\nconst ANIMATIONS: readonly SkeletonAnimation[] = ['shimmer', 'group-shimmer', 'pulse', 'none'];\n\nexport type Motion = { animation: SkeletonAnimation; duration: number };\n\n/** The animation an element inherits from the theme: `--ask-animation` and `--ask-speed`. */\nexport function motionOf(element: Element): Motion {\n const style = getComputedStyle(element);\n const read = <T extends string>(name: string, allowed: readonly T[], fallback: T): T => {\n const value = style.getPropertyValue(name).trim() as T;\n return allowed.includes(value) ? value : fallback;\n };\n const animation = read('--ask-animation', ANIMATIONS, 'shimmer');\n const speed = read<SkeletonSpeed>('--ask-speed', ['slow', 'fast'], 'slow');\n return {\n animation,\n duration: DURATIONS[animation === 'pulse' ? 'pulse' : 'shimmer'][speed],\n };\n}\n\ntype Span = { left: number; top: number; width: number; height: number };\n\nconst SLANT = 20; // degrees from vertical: the highlight is a diagonal, top right to bottom left\nconst SIN = Math.sin((SLANT * Math.PI) / 180);\nconst COS = Math.cos((SLANT * Math.PI) / 180);\nexport const SLANT_TAN = SIN / COS;\nexport const SLANT_COS = COS;\nexport const SLANT_ANGLE = `${90 + SLANT}deg`;\nexport const PEAK = 0.85; // Where across the band the highlight is brightest: 0 → PEAK eases up, PEAK → 1 eases down — later is a harder leading edge\nexport const STEPS = 12; // stops per ramp — enough for an eased curve to read as one, with no banding\n\n// Every gradient ramps on this (a scrim), so no stop shows as a hard line\nexport const ease = (t: number) => (1 - Math.cos(Math.PI * t)) / 2;\n\n/** Highlights `SPACING` band-widths apart, in px from the box's corner, so every rect draws the same stream. */\nfunction highlights(band: number) {\n const period = band * SPACING;\n const stop = (at: number, alpha: number) =>\n `color-mix(in srgb, ${HIGHLIGHT} ${(alpha * 100).toFixed(1)}%, transparent) ${(at * band).toFixed(2)}px`;\n const stops: string[] = [];\n for (let i = 0; i <= STEPS; i++) stops.push(stop((i / STEPS) * PEAK, ease(i / STEPS)));\n for (let i = 1; i <= STEPS; i++) {\n stops.push(stop(PEAK + (i / STEPS) * (1 - PEAK), ease(1 - i / STEPS)));\n }\n\n return {\n // Across, the stream repeats every `period` along the slant\n width: period / COS,\n image: `repeating-linear-gradient(${SLANT_ANGLE}, ${stops.join(', ')}, transparent ${period.toFixed(2)}px)`,\n };\n}\n\n/** Animates `element` as its slice of one sweep, on the document clock, so however late it mounts it joins the sweep under way. */\nexport function shimmer(element: HTMLElement, group?: Span, motion: Motion = motionOf(element)) {\n for (const animation of animationsOf(element)) animation.cancel();\n element.style.backgroundImage = '';\n element.style.backgroundRepeat = '';\n if (prefersReducedMotion() || typeof element.animate !== 'function') return;\n if (motion.animation === 'none') return;\n\n const timing = { duration: motion.duration, iterations: Infinity };\n\n if (motion.animation === 'pulse') {\n element.animate(\n [\n { opacity: 1, easing: 'ease-in-out' },\n { opacity: PULSE_LOW, easing: 'ease-in-out' },\n { opacity: 1 },\n ],\n timing\n ).startTime = 0;\n return;\n }\n\n const rect = element.getBoundingClientRect();\n const x = rect.left + scrollX;\n const area: Span =\n motion.animation === 'group-shimmer'\n ? (group ?? {\n left: x,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n })\n : {\n left: 0,\n top: 0,\n width: document.documentElement.clientWidth || innerWidth,\n height: innerHeight,\n };\n const band = Math.min(Math.max(area.width * 0.4, 80), MAX_BAND);\n const { width: tile, image } = highlights(band);\n\n // Where this bone sits in the area's one stream: further right, and lower down the slant, is further along it\n const along = x - area.left + (rect.top - area.top) * SLANT_TAN;\n // One pace on any screen, as a sweep across the reference width took\n const pace = (motion.duration * SWEEP) / (REFERENCE_WIDTH + MAX_BAND);\n\n element.style.backgroundImage = image;\n element.style.backgroundSize = `${tile}px 100%`;\n element.style.backgroundRepeat = 'repeat-x';\n element.animate(\n [{ backgroundPosition: `${-along}px 0` }, { backgroundPosition: `${tile - along}px 0` }],\n { duration: tile * pace, iterations: Infinity }\n ).startTime = 0;\n}\n\n/** ms per px of the band in `element`'s shimmer; null when it has no band. */\nexport function paceOf(element: Element): number | null {\n if (prefersReducedMotion()) return null;\n const motion = motionOf(element);\n if (motion.animation !== 'shimmer' && motion.animation !== 'group-shimmer') return null;\n return (motion.duration * SWEEP) / (REFERENCE_WIDTH + MAX_BAND);\n}\n\n/** The rect elements drawn into `layer`. */\nexport const rectsOf = (layer: Element): HTMLElement[] => [\n ...layer.querySelectorAll<HTMLElement>(`:scope > [${ATTR_RECT}]`),\n];\n\n/** Soft floor on skeleton bone corners — anything sharper than this reads as a glyph,\n * not a placeholder, which fights the whole point of a skeleton. 4 px is the smallest\n * radius that still reads as \"rounded\" at typical display DPI. Applied only to\n * text / media / box bones; chrome bones carry the consumer's own radius verbatim. */\nconst MIN_BONE_RADIUS = 4;\nconst clampRadius = (radius: string): string =>\n radius.replace(/(\\d+(?:\\.\\d+)?)px/g, (_, raw) => {\n const n = parseFloat(raw);\n return Number.isFinite(n) && n < MIN_BONE_RADIUS ? `${MIN_BONE_RADIUS}px` : `${n}px`;\n });\n\n/** Draws `rects` into `layer`, reusing the elements already there.\n *\n * Bones live in the light DOM (not a shadow root) so a consumer's stylesheet\n * can reach them — selectors like `[ask-rect=\"text\"]`, `[ask-rect=\"media\"]`,\n * `[ask-rect=\"box\"]`, or the `--ask-base` / `--ask-highlight` custom\n * properties — and theme the skeleton with the consumer's own tokens rather\n * than plugin defaults. Positioning (x/y/width/height/radius) stays inline\n * because it is per-bone; fill colour comes from the stylesheet.\n *\n * Added after mount, so Vue/React hydration never sees them.\n */\nexport function drawSkeleton(layer: HTMLElement, rects: SkeletonRect[]) {\n const existing = rectsOf(layer);\n const rect = layer.getBoundingClientRect();\n const group = {\n left: rect.left + scrollX,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n };\n // Read once for the layer: every rect in it inherits the same theme\n const motion = motionOf(layer);\n\n rects.forEach((part, index) => {\n let element = existing[index];\n if (!element) {\n element = document.createElement('div');\n // Positioning-only: the stylesheet owns colour so the consumer can retheme\n element.style.cssText = `position:absolute;display:block;pointer-events:none;background-repeat:no-repeat`;\n layer.append(element);\n }\n // Type attribute set every pass — bone reuse across renders may change type\n element.setAttribute(ATTR_RECT, part.type);\n\n Object.assign(element.style, {\n left: `${part.x}px`,\n top: `${part.y}px`,\n width: `${part.width}px`,\n height: `${part.height}px`,\n // Chrome reproduces the real element's border-radius exactly (0 stays 0);\n // placeholder bones get a 4-px floor so sharp-cornered text / media / box\n // bones still read as rounded skeletons, not glyphs of the real content.\n borderRadius: part.type === 'chrome' ? part.radius : clampRadius(part.radius),\n });\n\n if (part.type === 'chrome') {\n // Chrome bones reproduce the container's painted surface (bg / borders / shadow),\n // captured from the consumer's own CSS. Reset shimmer side-effects so an element\n // reused across draws isn't left with a shimmer background from a previous pass,\n // then apply the captured paint inline — the stylesheet default fill would obscure\n // the real colour.\n for (const anim of animationsOf(element)) anim.cancel();\n element.style.backgroundImage = '';\n element.style.backgroundSize = '';\n element.style.backgroundRepeat = '';\n const chrome = part.chrome;\n element.style.background = chrome?.background ?? '';\n element.style.borderTop = chrome?.borderTop ?? '';\n element.style.borderRight = chrome?.borderRight ?? '';\n element.style.borderBottom = chrome?.borderBottom ?? '';\n element.style.borderLeft = chrome?.borderLeft ?? '';\n element.style.boxShadow = chrome?.boxShadow ?? '';\n // Chrome never shimmers — it's the outline, not a loading placeholder\n element.dataset.motion = 'chrome';\n return;\n }\n\n // Non-chrome bones: drop any chrome state left on a reused element, then shimmer.\n if (element.dataset.motion === 'chrome') {\n element.style.background = '';\n element.style.borderTop = '';\n element.style.borderRight = '';\n element.style.borderBottom = '';\n element.style.borderLeft = '';\n element.style.boxShadow = '';\n }\n\n // Restarted only when its place, group, the page's width or the motion changes\n const key = `${Math.round(group.left + part.x)}|${Math.round(part.y)}|${Math.round(part.height)}|${Math.round(group.left)}|${Math.round(group.width)}|${Math.round(group.height)}|${document.documentElement.clientWidth}|${motion.animation}|${motion.duration}`;\n if (element.dataset.motion !== key) {\n element.dataset.motion = key;\n shimmer(element, group, motion);\n }\n });\n\n // Trim excess bones left over from a previous, longer draw\n for (let i = existing.length - 1; i >= rects.length; i--) existing[i]!.remove();\n}\n","import { ATTR_EXITING, CASCADE_SPREAD, FADE_DURATION } from './constants';\n\n/** Where one piece of a reveal sits: a piece of content arriving, or a rect of the skeleton leaving. */\nexport type Piece = {\n rect: DOMRect;\n /** Its row or card: the nearest ancestor with two or more siblings like it. Null for a rect outside any. */\n unit: DOMRect | null;\n /** Smaller text than the largest in its unit. */\n secondary: boolean;\n /** The whole reveal. */\n reveal: DOMRect;\n /** ms since the first of the reveals landing alongside this one. */\n late: number;\n};\n\n/** What a reveal knows as its content lands, for `choose`. */\nexport type RevealContext = {\n content: HTMLElement;\n reveal: HTMLElement;\n /** ms the skeleton was up; Infinity when it was server-rendered or there was none. */\n waited: number;\n /** Someone scrolled or typed in the last 400ms. */\n input: boolean;\n /** The skeleton was drawn from the data on screen. */\n refetch: boolean;\n height: number;\n /** How many pieces the content arrives in. */\n pieces: number;\n};\n\n/** One pane under a wipe: `rect` is its own box, `reveal` the box the front crosses, both in viewport px. */\nexport type WipePane = { rect: DOMRect; reveal: DOMRect };\n\n/** A front crossing the whole reveal, as a mask drawn each frame. */\nexport type Wipe = {\n /** The incoming pane's `mask-image` at `progress`, 0 to 1. */\n mask: (progress: number, pane: WipePane) => string;\n /** The outgoing pane's; the inverse of `mask` when left out. */\n out?: (progress: number, pane: WipePane) => string;\n /** Runs once on the incoming pane; `progress` keeps counting past 1. */\n effect?: (element: HTMLElement, front: WipePane & { progress: () => number }) => void;\n};\n\n/** How content replaces its skeleton; what `choose` returns as content lands wins over the fields beside it. */\nexport type RevealSpec = {\n order?: 'together' | ((piece: Piece) => number | null);\n /** Where each piece starts from, on top of the fade: `{ filter: \"blur(6px)\" }`. */\n enter?: Keyframe;\n wipe?: Wipe;\n delay?: number;\n /** 0 is instant. */\n duration?: number;\n /** ms a skeleton waits before it shows, so data that beats it never shows one. */\n hold?: number;\n choose?: (context: RevealContext) => RevealSpec;\n};\n\n/** A built-in reveal by name, or one of your own. */\nexport type RevealMode = 'together' | 'sequence' | 'smart' | 'sweep' | 'instant' | RevealSpec;\n\nexport const SKELETON_DELAY = 150; // A skeleton up for less than this is a flash — smart holds it back\nconst QUICK_FADE = 120; // A refetch, already familiar\nconst SMALL_HEIGHT = 72;\nconst SMALL_PIECES = 3;\nconst SECONDARY_DELAY = 60; // Smaller text follows the text it sits under\nexport const BATCH_WINDOW = 150; // Reveals landing this close share one top-to-bottom order\nconst ACTIVE_WINDOW = 400; // Input this recent means someone is mid-gesture\nexport const MAX_SWEEP_AREA = 1.5; // in screens — a wipe bigger than this crossfades: a front across it is mostly off screen, and costly\nexport const MAX_DELAY = 1000; // A custom order's latest piece\nexport const MAX_DURATION = 1000;\n\n// What `enter` may set: nothing that changes layout, so no reveal moves the page\nconst ENTER = new Set([\n 'filter',\n 'transform',\n 'translate',\n 'scale',\n 'rotate',\n 'clipPath',\n 'easing',\n 'composite',\n]);\n\nexport type SequencePlan = {\n kind: 'sequence';\n /** When a piece of content appears; null to appear at once. */\n pieceDelay: (piece: Element) => number | null;\n /** When a skeleton rect at `rect` goes; null to go at once. */\n boneDelay: (rect: DOMRect) => number | null;\n duration: number;\n enter?: Keyframe;\n};\n\nexport type WipePlan = {\n kind: 'wipe';\n wipe: Wipe;\n /** performance.now() at progress 0. */\n start: number;\n duration: number;\n reveal: DOMRect;\n enter?: Keyframe;\n /** Set when frames drop mid-wipe: both panes finish as a crossfade instead. */\n stalled?: boolean;\n};\n\nexport type Plan =\n | { kind: 'instant' }\n | { kind: 'together'; delay: number; duration: number; enter?: Keyframe }\n | SequencePlan\n | WipePlan;\n\n// Input, not scroll: a page restoring its scroll position isn't someone using it. No clicks: a click doesn't move what's being read\nlet lastInput = -Infinity;\nlet listening = false;\nfunction listen() {\n if (listening || typeof addEventListener === 'undefined') return;\n listening = true;\n for (const type of ['wheel', 'touchmove', 'keydown']) {\n addEventListener(type, () => (lastInput = performance.now()), {\n passive: true,\n capture: true,\n });\n }\n}\n\nconst loading = new WeakMap<Element, { since: number; refetch: boolean }>();\n\n/** Notes a skeleton going up in `reveal` — when, and whether it's a refetch over the data on screen. */\nexport function noteSkeleton(\n reveal: Element,\n { served, refetch }: { served: boolean; refetch: boolean }\n) {\n listen();\n const since = loading.get(reveal)?.since ?? performance.now();\n // Server-rendered: up since the page began, so never a flash\n loading.set(reveal, { since: served ? -Infinity : since, refetch });\n}\n\n// What a reveal brings in one by one: anything holding text or media of its own\nexport function pieces(root: Element): Element[] {\n const found: Element[] = [];\n const visit = (element: Element) => {\n for (const child of element.children) {\n const ownText = [...child.childNodes].some(\n (node) => node.nodeType === Node.TEXT_NODE && node.textContent?.trim()\n );\n if (!child.firstElementChild || ownText || child.localName === 'svg') {\n found.push(child);\n } else {\n visit(child);\n }\n }\n };\n visit(root);\n return found;\n}\n\n// A row of a list or a card of a grid: the piece's nearest ancestor with two or more siblings like it\nfunction unitOf(piece: Element, root: Element): Element {\n for (\n let element: Element | null = piece;\n element && element !== root;\n element = element.parentElement\n ) {\n const parent = element.parentElement;\n if (!parent) break;\n const alike = [...parent.children].filter(\n (sibling) =>\n sibling.localName === element!.localName && sibling.className === element!.className\n );\n if (alike.length >= 3) return element;\n }\n return piece;\n}\n\nconst contains = (outer: DOMRect, inner: DOMRect) => {\n const x = inner.left + inner.width / 2;\n const y = inner.top + inner.height / 2;\n return x >= outer.left && x <= outer.right && y >= outer.top && y <= outer.bottom;\n};\n\n/** The box a wipe crosses: the reveal, and any pane leaving it that stands taller or wider. */\nexport function revealBox(root: Element): DOMRect {\n let { left, top, right, bottom } = root.getBoundingClientRect();\n for (const pane of root.querySelectorAll(`:scope > [${ATTR_EXITING}]`)) {\n const rect = pane.getBoundingClientRect();\n left = Math.min(left, rect.left);\n top = Math.min(top, rect.top);\n right = Math.max(right, rect.right);\n bottom = Math.max(bottom, rect.bottom);\n }\n return new DOMRect(left, top, right - left, bottom - top);\n}\n\nconst clamp = (value: number, max: number) => Math.min(Math.max(value, 0), max);\n\nlet batch = -Infinity;\n\n/** Times each piece of `content`, and each skeleton rect it replaces, by `order`. */\nfunction sequencePlan(\n content: Element,\n root: Element,\n order: (piece: Piece) => number | null,\n spec: RevealSpec,\n duration: number\n): SequencePlan {\n const now = performance.now();\n if (now - batch > BATCH_WINDOW) batch = now;\n const late = now - batch;\n const reveal = root.getBoundingClientRect();\n\n type Unit = { rect: DOMRect; size: number };\n const units = new Map<Element, Unit>();\n const found = new Map<Element, { unit: Unit; size: number }>();\n const sizeOf = (element: Element) => parseFloat(getComputedStyle(element).fontSize) || 16;\n\n for (const piece of pieces(content)) {\n const element = unitOf(piece, content);\n let unit = units.get(element);\n if (!unit) {\n unit = { rect: element.getBoundingClientRect(), size: 0 };\n units.set(element, unit);\n }\n const size = sizeOf(piece);\n unit.size = Math.max(unit.size, size);\n found.set(piece, { unit, size });\n }\n\n const at = (piece: Piece) => {\n const delay = order(piece);\n return delay === null ? null : clamp(delay, MAX_DELAY) + Math.max(spec.delay ?? 0, 0);\n };\n\n return {\n kind: 'sequence',\n duration,\n enter: spec.enter,\n pieceDelay: (element) => {\n const piece = found.get(element);\n if (!piece) return null;\n return at({\n rect: element.getBoundingClientRect(),\n unit: piece.unit.rect,\n secondary: piece.size < piece.unit.size,\n reveal,\n late,\n });\n },\n boneDelay: (rect) => {\n const unit = [...units.values()].find((unit) => contains(unit.rect, rect));\n return at({\n rect,\n unit: unit?.rect ?? null,\n // A bar shorter than its row's largest type stands for smaller text\n secondary: !!unit && rect.height < unit.size * 0.8,\n reveal,\n late,\n });\n },\n };\n}\n\n/** Keeps `enter` to what paints, warning in development about anything that would move the page. */\nfunction enterOf(enter: Keyframe | undefined, warn: (key: string) => void) {\n if (!enter) return undefined;\n const kept: Keyframe = {};\n for (const [key, value] of Object.entries(enter)) {\n if (ENTER.has(key)) kept[key] = value;\n else if (key !== 'opacity') warn(key);\n }\n return kept;\n}\n\n/** Decides how `content` replaces the skeleton in `root`, now that it has arrived. */\nexport function planReveal(\n content: HTMLElement,\n root: HTMLElement,\n reveal: RevealSpec,\n warn: (key: string) => void = () => {}\n): Plan {\n const info = loading.get(root);\n loading.delete(root);\n\n let spec = reveal;\n while (spec.choose) {\n const { choose, ...rest } = spec;\n spec = {\n ...rest,\n ...choose({\n content,\n reveal: root,\n waited: info ? performance.now() - info.since : Infinity,\n input: performance.now() - lastInput < ACTIVE_WINDOW,\n refetch: !!info?.refetch,\n height: content.getBoundingClientRect().height,\n pieces: pieces(content).length,\n }),\n };\n }\n\n const duration = clamp(spec.duration ?? FADE_DURATION, MAX_DURATION);\n // No floor: a wipe joining one under way starts partway, before now\n spec = { ...spec, delay: Math.min(spec.delay ?? 0, MAX_DELAY) };\n if (!duration) return { kind: 'instant' };\n const enter = enterOf(spec.enter, warn);\n\n if (spec.wipe) {\n const rect = revealBox(root);\n if (rect.width * rect.height <= innerWidth * innerHeight * MAX_SWEEP_AREA) {\n return {\n kind: 'wipe',\n wipe: spec.wipe,\n start: performance.now() + (spec.delay ?? 0),\n duration,\n reveal: rect,\n enter,\n };\n }\n } else if (typeof spec.order === 'function') {\n return sequencePlan(content, root, spec.order, { ...spec, enter }, duration);\n }\n return {\n kind: 'together',\n delay: Math.max(spec.delay ?? 0, 0),\n duration,\n enter,\n };\n}\n\n/** `sequence`: each piece timed by its place in the reveal, top to bottom, then a little left to right. */\nexport const byPosition = ({ rect, reveal }: Piece) => {\n const down = (rect.top - reveal.top) / Math.max(reveal.height, 1);\n const across = (rect.left - reveal.left) / Math.max(reveal.width, 1);\n return clamp(down * 0.8 + across * 0.2, 1) * CASCADE_SPREAD;\n};\n\nconst onScreen = (rect: DOMRect) => rect.bottom > 0 && rect.top < innerHeight;\n\n/** `smart`'s order: rows arrive whole, in page order, on screen only, main text first. */\nexport const byRow = ({ rect, unit, secondary, late }: Piece) => {\n if (!unit) return onScreen(rect) ? 0 : null;\n if (!onScreen(unit)) return null;\n // Timed against the screen, not the reveal, so reveals landing together read as one page\n const at = clamp(unit.top / innerHeight, 1) * CASCADE_SPREAD;\n return Math.max(at - late, 0) + (secondary ? SECONDARY_DELAY : 0);\n};\n\nexport const instant: RevealSpec = { duration: 0 };\nexport const together: RevealSpec = { order: 'together' };\nexport const sequence: RevealSpec = { order: byPosition };\n\n/** The cases `smart` settles before looking at the content: instant, or a quick crossfade. */\nexport const quickly = (context: RevealContext): RevealSpec | null =>\n context.input || context.waited < SKELETON_DELAY\n ? instant\n : context.refetch\n ? { order: 'together', duration: QUICK_FADE }\n : null;\n\n/** `together` for a small reveal, else `byRow`. */\nexport const byContent = (context: RevealContext): RevealSpec =>\n context.height < SMALL_HEIGHT || context.pieces <= SMALL_PIECES ? together : { order: byRow };\n\n/** Picks for each reveal from how it loaded and what it holds, holding its skeleton back a moment. */\nexport const smart: RevealSpec = {\n hold: SKELETON_DELAY,\n choose: (context) => quickly(context) ?? byContent(context),\n};\n","import { serialize } from './snapshot';\n\nconst STORAGE_KEY = 'a-smart-skeleton:shapes';\nconst VERSION = 2; // Bumped whenever the stored markup changes meaning\nconst MAX_SHAPES = 50;\nconst MAX_LENGTH = 20_000;\n\ntype Stored = Record<string, string>; // Oldest first\n\n// Real text, kept in memory only — exact for a reload within the same visit\nconst session = new Map<string, string>();\nconst shown = new Map<string, Set<() => void>>();\n\n/** Registers a save for content on screen under `key`; returns its unregister. */\nexport function trackShape(key: string, save: () => void) {\n if (!shown.has(key)) shown.set(key, new Set());\n shown.get(key)!.add(save);\n return () => shown.get(key)?.delete(save);\n}\n\n/** Saves every shown copy of `key` now, so a skeleton about to recall it gets the latest. */\nexport function flushShapes(key: string) {\n for (const save of shown.get(key) ?? []) save();\n}\n\n// Treats anything parsed from localStorage as hostile: must be the expected envelope,\n// `shapes` must be a plain string-to-string dictionary, and the output is a null-prototype\n// object so no later lookup can be confused by an inherited key.\nfunction read(): Stored {\n try {\n const raw = JSON.parse(localStorage.getItem(STORAGE_KEY) ?? 'null');\n if (!raw || typeof raw !== 'object' || raw.v !== VERSION) return Object.create(null);\n const incoming = raw.shapes;\n if (!incoming || typeof incoming !== 'object') return Object.create(null);\n const out: Stored = Object.create(null);\n for (const key of Object.keys(incoming)) {\n const value = (incoming as Record<string, unknown>)[key];\n if (typeof value === 'string') out[key] = value;\n }\n return out;\n } catch {\n return Object.create(null);\n }\n}\n\nfunction write(shapes: Stored) {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify({ v: VERSION, shapes }));\n } catch {\n // Storage full or blocked; the session copy still covers this visit\n }\n}\n\nexport function rememberShape(key: string, element: HTMLElement) {\n session.set(key, serialize(element, false));\n\n const html = serialize(element, true);\n if (html.length > MAX_LENGTH) return;\n\n const shapes = read();\n // Re-inserted so it moves to the end: key order is recency\n delete shapes[key];\n shapes[key] = html;\n const keys = Object.keys(shapes);\n for (const stale of keys.slice(0, keys.length - MAX_SHAPES)) {\n delete shapes[stale];\n }\n write(shapes);\n}\n\nexport function recallShape(key: string): string | null {\n return session.get(key) ?? read()[key] ?? null;\n}\n\n/** Forgets remembered shapes — call it on sign-out. */\nexport function forgetShapes({ persisted = true } = {}) {\n session.clear();\n if (!persisted) return;\n try {\n localStorage.removeItem(STORAGE_KEY);\n } catch {\n // Nothing stored to forget\n }\n}\n","import {\n ATTR_BLOCK,\n ATTR_LAYER,\n ATTR_EXITING,\n ATTR_GHOST,\n ATTR_INACTIVE,\n ATTR_LOADING,\n ATTR_OWN,\n ATTR_REVEAL,\n ATTR_SNAPSHOT,\n GHOSTED,\n UNCOVER,\n} from './constants';\nimport { reportLoading } from './debug';\nimport { noteSkeleton } from './plan';\nimport { warnOnce } from './dev';\nimport { measureSkeleton } from './measure';\nimport { flushShapes, recallShape } from './shapes';\nimport { drawSkeleton } from './shimmer';\nimport { autoKey, restore } from './snapshot';\nimport { addStyles, removeStyles } from './styles';\n\nexport type GhostOptions = {\n /** Remembers the shape under this key; without it, one is derived from the markup. */\n id?: string;\n /** The ghost was rendered from real data, so it beats any remembered shape. */\n exact?: boolean;\n /** Its data is still set: a refetch over what's on screen, not a new load. */\n refetch?: boolean;\n};\n\ntype Source = 'ghost' | 'recall' | 'fallback';\n\nconst FALLBACK = [100, 90, 60]\n .map(\n (width) =>\n `<div ${ATTR_BLOCK} style=\"width:${width}%;height:0.75em;margin:0.5em 0;border-radius:0.25em\"></div>`\n )\n .join('');\n\n// In the document before any script ran: server-rendered, so already painted at the shape it has\nconst served = new WeakSet<Element>(\n typeof document === 'undefined' ? [] : document.querySelectorAll(`[${ATTR_LOADING}]`)\n);\n\nconst loadingSizes = new WeakMap<\n Element,\n {\n width: number;\n height: number;\n guessed: boolean;\n /** Each image's height in the skeleton, in document order — 0 for one nothing sizes until it loads. */\n images: number[];\n }\n>();\n\n/** The size a reveal's skeleton last measured at, taken once by whatever replaces it. */\nexport function takeLoadingSize(reveal: Element | null) {\n if (!reveal) return undefined;\n const size = loadingSizes.get(reveal);\n loadingSizes.delete(reveal);\n return size;\n}\n\nfunction child(root: HTMLElement, attribute: string) {\n for (const element of root.children) {\n if (element.hasAttribute(attribute)) return element as HTMLElement;\n }\n const element = document.createElement('div');\n element.setAttribute(attribute, '');\n root.append(element);\n return element;\n}\n\nconst hasContent = (element: Element) =>\n !!element.firstElementChild || !!element.textContent?.trim();\n\n/** Draws a skeleton over content laid out unseen in `root`, so it takes exactly the content's space. */\nexport class Ghost {\n private ghost: HTMLElement;\n private snapshot: HTMLElement;\n private layer: HTMLElement;\n private source: Source | null = null;\n private hadContent = false;\n private frame = 0;\n private mutations: MutationObserver;\n private resize: ResizeObserver | null;\n\n constructor(\n private root: HTMLElement,\n private options: GhostOptions = {}\n ) {\n addStyles();\n (root as HTMLElement & { [GHOSTED]?: boolean })[GHOSTED] = true;\n root.setAttribute(ATTR_LOADING, '');\n root.setAttribute('aria-hidden', 'true');\n root.inert = true;\n\n this.ghost = child(root, ATTR_GHOST);\n this.snapshot = child(root, ATTR_SNAPSHOT);\n this.layer = child(root, ATTR_LAYER);\n\n this.hadContent = hasContent(this.ghost);\n\n this.note();\n this.choose();\n this.measure();\n // Covered paint is marked now; the inline script's stand-in sheet can go\n (root as HTMLElement & { [UNCOVER]?: () => void })[UNCOVER]?.();\n\n this.mutations = new MutationObserver(this.schedule);\n this.mutations.observe(this.ghost, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n });\n // None in jsdom, which has no layout to follow\n this.resize = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(this.schedule);\n this.resize?.observe(root);\n root.addEventListener('load', this.schedule, true);\n addEventListener('resize', this.schedule);\n document.fonts?.ready.then(this.schedule);\n }\n\n /** Swaps in fresh options without tearing down the observers or stylesheet refcount. */\n update(options: GhostOptions = {}) {\n this.options = options;\n this.note();\n this.choose();\n this.measure();\n }\n\n private note() {\n const reveal = this.root.closest(`[${ATTR_REVEAL}]`);\n if (!reveal) return;\n noteSkeleton(reveal, {\n served: served.has(this.root),\n refetch: !!this.options.refetch && this.hadContent,\n });\n }\n\n private schedule = () => {\n // Leaving: re-measuring a pane pinned at its last size would redraw what's fading out\n if (this.root.closest(`[${ATTR_EXITING}]`)) return;\n cancelAnimationFrame(this.frame);\n this.frame = requestAnimationFrame(() => {\n const has = hasContent(this.ghost);\n if (has !== this.hadContent) {\n this.hadContent = has;\n this.choose();\n }\n this.measure();\n });\n };\n\n private choose() {\n let next: Source = 'fallback';\n let html: string | null = null;\n\n // Re-shaping a skeleton already on screen would move the page — keep it\n const settled = this.options.exact || served.has(this.root);\n // A remembered shape is the shown content, which has none of the author's own skeletons\n const own = !!this.ghost.querySelector(`[${ATTR_OWN}]`);\n if ((settled || own) && this.hadContent) {\n next = 'ghost';\n } else {\n const key = this.options.id ?? autoKey(this.ghost);\n if (key) {\n flushShapes(key);\n html = recallShape(key);\n }\n if (html) next = 'recall';\n else if (this.hadContent) next = 'ghost';\n }\n\n if (next !== this.source) {\n if (next === 'recall' && html) {\n this.snapshot.replaceChildren(restore(html));\n } else if (next === 'fallback') {\n this.snapshot.innerHTML = FALLBACK;\n warnOnce(\n `fallback:${this.options.id}`,\n `Nothing to draw a skeleton from${this.options.id ? ` for \"${this.options.id}\"` : ''}. Pass \\`sample\\` data, or an \\`id\\` so its shape is remembered after the first load. For a lone placeholder box, use \\`SkeletonBox\\`.`\n );\n } else {\n this.snapshot.replaceChildren();\n }\n }\n\n this.ghost.toggleAttribute(ATTR_INACTIVE, next !== 'ghost');\n this.snapshot.toggleAttribute(ATTR_INACTIVE, next === 'ghost');\n this.source = next;\n\n reportLoading(\n this.root.closest(`[${ATTR_REVEAL}]`),\n next === 'recall'\n ? 'remembered shape'\n : next === 'fallback'\n ? 'fallback'\n : this.options.exact\n ? 'data'\n : served.has(this.root)\n ? 'server render'\n : 'sample'\n );\n }\n\n private measure() {\n const active = this.source === 'ghost' ? this.ghost : this.snapshot;\n drawSkeleton(this.layer, measureSkeleton(active, this.layer));\n\n const reveal = this.root.closest(`[${ATTR_REVEAL}]`);\n if (reveal) {\n loadingSizes.set(reveal, {\n width: this.root.offsetWidth,\n height: this.root.offsetHeight,\n // Drawn from real data, so a sample would have changed nothing\n guessed: !(this.options.exact && this.source === 'ghost'),\n images: [...active.querySelectorAll('img')].map(\n (image) => image.getBoundingClientRect().height\n ),\n });\n }\n }\n\n // Bones keep shimmering until they are removed, so a skeleton fading out stays alive\n destroy() {\n cancelAnimationFrame(this.frame);\n this.mutations.disconnect();\n this.resize?.disconnect();\n this.root.removeEventListener('load', this.schedule, true);\n removeEventListener('resize', this.schedule);\n removeStyles();\n }\n}\n","import { ATTR_REVEAL } from './constants';\nimport { debugging, reportReveal } from './debug';\nimport { isDev, sampleFrom, warnOnce } from './dev';\nimport { takeLoadingSize } from './ghost';\nimport { rememberShape, trackShape } from './shapes';\nimport { autoKey } from './snapshot';\n\nexport type MemoryOptions = {\n id?: string;\n /** What the content was rendered from, for the `sample` dev hint. */\n data?: unknown;\n /** The content is rendered from data by a function, which only `sample` or an `id` can stand in for. */\n rendered?: boolean;\n /** A `sample` was passed. */\n sample?: boolean;\n};\n\nconst SAVE_DELAY = 250;\n\n// Synthetic, per-element id for `warnOnce` dedupe when the consumer didn't pass one.\n// Without this every id-less skeleton shares the same `sample:null` / `jump:null` bucket,\n// so only the first warning across the whole app ever fires.\nconst anonIds = new WeakMap<HTMLElement, string>();\nlet anonSeq = 0;\nconst anonId = (element: HTMLElement) => {\n let id = anonIds.get(element);\n if (!id) {\n id = `anon:${++anonSeq}`;\n anonIds.set(element, id);\n }\n return id;\n};\n\n/** Remembers the shape of shown content, so its next skeleton can be drawn from it. */\nexport class Memory {\n private key: string | null;\n private warnKey: string;\n private timer: ReturnType<typeof setTimeout> | undefined;\n private mutations: MutationObserver;\n private resize: ResizeObserver | null;\n private untrack: () => void;\n\n constructor(\n private element: HTMLElement,\n private options: MemoryOptions = {}\n ) {\n this.key = options.id ?? autoKey(element);\n this.warnKey = this.key ?? anonId(element);\n this.untrack = this.key ? trackShape(this.key, () => this.save()) : () => {};\n\n if (isDev || debugging(element)) this.check();\n this.save();\n\n this.mutations = new MutationObserver(this.schedule);\n this.mutations.observe(element, {\n childList: true,\n subtree: true,\n characterData: true,\n });\n // None in jsdom, which has no layout to follow\n this.resize = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(this.schedule);\n this.resize?.observe(element);\n element.addEventListener('load', this.schedule, true);\n }\n\n private schedule = () => {\n clearTimeout(this.timer);\n this.timer = setTimeout(() => this.save(), SAVE_DELAY);\n };\n\n save() {\n clearTimeout(this.timer);\n if (this.key && this.element.isConnected && this.element.offsetHeight) {\n rememberShape(this.key, this.element);\n }\n }\n\n private check() {\n const { data, id, rendered, sample } = this.options;\n const name = id ? `<Skeleton id=\"${id}\">` : '<Skeleton>';\n\n const reveal = this.element.closest(`[${ATTR_REVEAL}]`);\n const before = takeLoadingSize(reveal);\n // Shown without a skeleton first, so nothing was guessed and nothing could move\n if (!before) return;\n\n if (before.guessed && rendered && !sample && data != null) {\n warnOnce(\n `sample:${this.warnKey}`,\n `${name} has no \\`sample\\`, so a first load guesses its shape${id ? '' : \" and it can't be remembered\"}. Pass this to make it exact:\\n sample={${JSON.stringify(sampleFrom(data))}}`\n );\n }\n\n // Unsized images settle late; compare once they have\n const images = [...this.element.querySelectorAll('img')].filter((image) => !image.complete);\n Promise.all(\n images.map(\n (image) =>\n new Promise((resolve) => {\n image.addEventListener('load', resolve, { once: true });\n image.addEventListener('error', resolve, { once: true });\n })\n )\n ).then(() => {\n // Gone before it settled: a detached element measures nothing\n if (!this.element.isConnected) return;\n const width = this.element.offsetWidth;\n const height = this.element.offsetHeight;\n reportReveal(reveal, {\n width: width - before.width,\n height: height - before.height,\n });\n if (Math.abs(width - before.width) <= 1 && Math.abs(height - before.height) <= 1) {\n return;\n }\n // Flat in the skeleton, tall now: nothing sized them before they loaded\n const unsized = [...this.element.querySelectorAll('img')]\n .filter(\n (image, i) => (before.images[i] ?? 0) < 1 && image.getBoundingClientRect().height >= 1\n )\n .map((image) => image.currentSrc.split('/').pop() || 'an image');\n if (unsized.length) {\n warnOnce(\n `unsized:${this.warnKey}`,\n `${name}'s skeleton had no room for ${unsized.length === 1 ? 'an image' : `${unsized.length} images`} (${unsized.slice(0, 3).join(', ')}${unsized.length > 3 ? ', …' : ''}), so the layout jumped when they loaded. Give each \\`width\\` and \\`height\\` attributes, or an \\`aspect-ratio\\`, so its space is known before it loads.`\n );\n return;\n }\n warnOnce(\n `jump:${this.warnKey}`,\n before.guessed\n ? `${name}'s skeleton was ${before.width}×${before.height}px but its content is ${width}×${height}px, so the layout jumped on reveal. ${rendered ? 'Pass `sample` data shaped like the real thing' : 'Pass an `id` so its shape is remembered'}, and give images a size.`\n : `${name}'s skeleton was drawn from the data on screen (${before.width}×${before.height}px), but the new data is ${width}×${height}px, so the layout jumped on reveal. When new data adds to what's shown — another page of a list — give the addition a reveal of its own.`\n );\n });\n }\n\n destroy() {\n this.save();\n clearTimeout(this.timer);\n this.mutations.disconnect();\n this.resize?.disconnect();\n this.element.removeEventListener('load', this.schedule, true);\n this.untrack();\n }\n}\n","import { ATTR_BAR } from './constants';\nimport { shimmer } from './shimmer';\nimport { addStyles } from './styles';\n\ntype Length = string | number;\n\nexport type SkeletonBoxOptions = {\n height?: Length;\n width?: Length;\n radius?: Length;\n};\n\nexport const DEFAULT_SKELETON_BOX_OPTIONS = {\n height: '1em',\n width: '60%',\n radius: 'var(--ask-radius, 0.25em)',\n} satisfies Required<SkeletonBoxOptions>;\n\nconst toCSS = (value: Length) => (typeof value === 'number' ? `${value}px` : value);\n\nexport function skeletonBoxStyle({\n height = DEFAULT_SKELETON_BOX_OPTIONS.height,\n width = DEFAULT_SKELETON_BOX_OPTIONS.width,\n radius = DEFAULT_SKELETON_BOX_OPTIONS.radius,\n}: SkeletonBoxOptions = {}) {\n return {\n height: toCSS(height),\n width: toCSS(width),\n borderRadius: toCSS(radius),\n };\n}\n\n/** A single bar, shimmering in step with every skeleton on the page once it is in the document. */\nexport function createSkeletonBox(options?: SkeletonBoxOptions): HTMLSpanElement {\n addStyles();\n const element = document.createElement('span');\n element.setAttribute(ATTR_BAR, '');\n Object.assign(element.style, skeletonBoxStyle(options));\n requestAnimationFrame(() => {\n if (element.isConnected) shimmer(element);\n });\n return element;\n}\n","import { IMAGE_TIMEOUT } from './constants';\n\nconst noop = () => {};\n\n// Lazy and well off screen, it won't load until scrolled to — nothing to wait for\nconst deferred = (image: HTMLImageElement) => {\n if (image.loading !== 'lazy') return false;\n const rect = image.getBoundingClientRect();\n return rect.bottom < -innerHeight || rect.top > innerHeight * 2;\n};\n\n/** Images inside still on their way. */\nexport const pendingImages = (element: Element) =>\n [...element.querySelectorAll('img')].filter((image) => !image.complete && !deferred(image));\n\n/** Loaded and decoded, so its first frame on screen is the picture; failing counts, as nothing more is coming. */\nexport function imageReady(image: HTMLImageElement): Promise<void> {\n const loaded = image.complete\n ? Promise.resolve()\n : new Promise<void>((resolve) => {\n image.addEventListener('load', () => resolve(), { once: true });\n image.addEventListener('error', () => resolve(), { once: true });\n });\n return Promise.race([\n loaded.then(() => image.decode?.()).then(noop, noop),\n new Promise<void>((resolve) => setTimeout(resolve, IMAGE_TIMEOUT)),\n ]);\n}\n","import { ATTR_LAYER, ATTR_EXITING } from './constants';\nimport { prefersReducedTransparency } from './motion';\nimport {\n BATCH_WINDOW,\n byContent,\n MAX_SWEEP_AREA,\n quickly,\n revealBox,\n SKELETON_DELAY,\n type RevealContext,\n type RevealSpec,\n type Wipe,\n type WipePane,\n} from './plan';\nimport { ease, paceOf, SLANT_ANGLE, SLANT_COS, SLANT_TAN, STEPS } from './shimmer';\n\nconst WAVE_SPREAD = 360; // Most a sweep takes across the reveal that starts it\nconst WAVE_PACE = 2; // A sweep's front runs this many times the shimmer's pace\nexport const SWEEP_SPREAD = 600; // Most a sweep takes across a reveal that joins one under way\nconst FEATHER = 40; // px either side of the front, across the slant\nconst PAD = FEATHER / SLANT_COS; // The feather, along `u`\nconst GLOSS = 320; // px across the slant: the band trailing the front, as wide as the shimmer's widest\nconst GLOSS_LAG = 120; // px its centre trails the front by\nconst GLOSS_LIFT = 0.45; // How far, at its peak, it lifts the content it crosses toward white\n\n// `u` is a point's x plus its y along the slant, in viewport px: the front is a line of one `u`\nconst uOf = (rect: DOMRect) => rect.left + rect.top * SLANT_TAN;\nconst spanOf = (rect: DOMRect) => rect.width + rect.height * SLANT_TAN;\n\n// The front's `u` at `progress` — crossing the reveal from a feather before it to a feather past it\nconst frontAt = (progress: number, reveal: DOMRect) =>\n uOf(reveal) - PAD + (spanOf(reveal) + 2 * PAD) * progress;\n\nlet wave = { start: -Infinity, origin: 0, speed: 1 };\n\n/** When the shared front reaches `reveal`, and how long it takes across — null without a shimmer to match. */\nfunction timing(reveal: HTMLElement) {\n const layer = reveal.querySelector(`:scope > [${ATTR_EXITING}] [${ATTR_LAYER}]`);\n const pace = layer && paceOf(layer);\n if (!pace) return null;\n\n const rect = revealBox(reveal);\n if (rect.width * rect.height > innerWidth * innerHeight * MAX_SWEEP_AREA) {\n return null;\n }\n const from = uOf(rect);\n const to = from + spanOf(rect);\n const now = performance.now();\n // Reveals landing together share one front — if it hasn't reached this one yet, and won't keep it waiting\n const elapsed = now - wave.start;\n const joined =\n elapsed <= BATCH_WINDOW &&\n (from - wave.origin) / wave.speed >= elapsed &&\n (to - wave.origin) / wave.speed - elapsed <= SWEEP_SPREAD;\n if (!joined) {\n wave = {\n start: now,\n origin: from,\n speed: Math.max(WAVE_PACE / pace, (to - from) / WAVE_SPREAD),\n };\n }\n const { start, origin, speed } = wave;\n return {\n delay: (from - PAD - origin) / speed - (now - start),\n duration: (to - from + 2 * PAD) / speed,\n };\n}\n\n// The front's stops in the pane's own gradient, the content behind it and the skeleton ahead\nconst stops =\n (incoming: boolean) =>\n (progress: number, { rect, reveal }: WipePane) => {\n const at = (frontAt(progress, reveal) - uOf(rect)) * SLANT_COS;\n const ramp = Array.from({ length: STEPS + 1 }, (_, i) => {\n const shown = incoming ? 1 - ease(i / STEPS) : ease(i / STEPS);\n const offset = -FEATHER + (2 * FEATHER * i) / STEPS;\n return `rgb(0 0 0 / ${shown.toFixed(3)}) ${(at + offset).toFixed(2)}px`;\n });\n return `linear-gradient(${SLANT_ANGLE}, ${ramp.join(', ')})`;\n };\n\nconst SVG = 'http://www.w3.org/2000/svg';\nlet host: SVGSVGElement | null = null;\nlet glosses = 0;\n\n// One hidden svg on the page for the filters: `filter: url(#…)` can't reach into a shadow root\nfunction filterHost() {\n if (!host?.isConnected) {\n host = document.createElementNS(SVG, 'svg');\n host.setAttribute('aria-hidden', 'true');\n host.style.cssText = 'position:absolute;width:0;height:0;overflow:hidden';\n document.body.append(host);\n }\n return host;\n}\n\nconst svg = (tag: string, attributes: Record<string, string | number>) => {\n const node = document.createElementNS(SVG, tag);\n for (const [name, value] of Object.entries(attributes)) {\n node.setAttribute(name, String(value));\n }\n return node;\n};\n\n// The band trailing the front: a filter lifting what the content paints toward white, never the surface around it\nconst gloss: Wipe['effect'] = (element, { rect, reveal, progress }) => {\n if (prefersReducedTransparency()) return;\n const from = uOf(rect);\n const span = spanOf(rect);\n const half = GLOSS / 2 / SLANT_COS;\n // The band's centre, in `u` from the pane's corner\n const centre = () => frontAt(progress(), reveal) - from - GLOSS_LAG / SLANT_COS;\n if (centre() - half > span) return;\n\n // The band drawn once, slanted, in an image as tall as the pane; moving it along x moves it along the slant\n const width = 2 * half + rect.height * SLANT_TAN;\n const cx = width / 2;\n const cy = rect.height / 2;\n const dx = (GLOSS / 2) * SLANT_COS;\n const dy = (GLOSS / 2) * SLANT_TAN * SLANT_COS;\n // Drawn to a PNG: Safari's feImage renders no SVG, and the filter then hides what it's on\n const canvas = document.createElement('canvas');\n canvas.width = Math.ceil(width);\n canvas.height = Math.ceil(rect.height);\n const context = canvas.getContext('2d');\n if (!context) return;\n const gradient = context.createLinearGradient(cx - dx, cy - dy, cx + dx, cy + dy);\n for (let i = 0; i <= STEPS; i++) {\n const t = i / STEPS;\n gradient.addColorStop(t, `rgb(255 255 255 / ${ease(1 - Math.abs(t * 2 - 1)).toFixed(3)})`);\n }\n context.fillStyle = gradient;\n context.fillRect(0, 0, canvas.width, canvas.height);\n\n const id = `ask-gloss-${++glosses}`;\n // In the pane's own box: WebKit doesn't measure a primitive's x and y from an HTML element's corner, and blanks it\n const filter = svg('filter', {\n id,\n 'color-interpolation-filters': 'sRGB',\n primitiveUnits: 'objectBoundingBox',\n });\n const lit = svg('feComponentTransfer', {\n in: 'SourceGraphic',\n result: 'lit',\n });\n for (const channel of ['R', 'G', 'B']) {\n lit.append(\n svg(`feFunc${channel}`, {\n type: 'linear',\n slope: 1 - GLOSS_LIFT,\n intercept: GLOSS_LIFT,\n })\n );\n }\n const image = svg('feImage', {\n href: canvas.toDataURL(),\n y: 0,\n width: width / rect.width,\n height: 1,\n preserveAspectRatio: 'none',\n result: 'band',\n });\n filter.append(\n lit,\n image,\n svg('feComposite', {\n in: 'lit',\n in2: 'band',\n operator: 'in',\n result: 'shine',\n }),\n svg('feComposite', { in: 'shine', in2: 'SourceGraphic', operator: 'over' })\n );\n filterHost().append(filter);\n element.style.filter = `url(#${id})`;\n\n const tick = () => {\n const at = centre();\n if (at - half > span || !element.isConnected) {\n // Cleared first, matched by id: Safari won't draw an element whose filter is gone, and the style reads back quoted\n if (element.style.filter.includes(id)) element.style.filter = '';\n filter.remove();\n return;\n }\n image.setAttribute('x', ((at - cx - cy * SLANT_TAN) / rect.width).toFixed(4));\n requestAnimationFrame(tick);\n };\n tick();\n};\n\n// Its own outgoing mask rather than a composited inverse: Safari 18 masks only the plainest gradient reliably\nconst wipe: Wipe = { mask: stops(true), out: stops(false), effect: gloss };\n\n/** `smart`, wiping content in behind one band of the shimmer. */\nexport const sweep: RevealSpec = {\n hold: SKELETON_DELAY,\n choose: (context: RevealContext) => {\n const quick = quickly(context);\n if (quick) return quick;\n const swept = timing(context.reveal);\n return swept ? { wipe, ...swept } : byContent(context);\n },\n};\n","import { CASCADE_SPREAD, FADE_DURATION } from './constants';\nimport {\n instant,\n MAX_DELAY,\n MAX_DURATION,\n sequence,\n smart,\n together,\n type RevealMode,\n type RevealSpec,\n} from './plan';\nimport { sweep, SWEEP_SPREAD } from './sweep';\n\n// `instant` is advertised as a string mode in the README and is exported as a\n// `RevealSpec`, but was previously missing from this map, so passing\n// `reveal=\"instant\"` returned `undefined` and crashed `arrive()` with\n// \"Cannot read properties of undefined (reading 'hold')\".\nconst NAMED = { together, sequence, smart, sweep, instant };\n\n// Unknown strings fall back to `smart` instead of crashing — a stale template\n// or a typo should quietly do the right thing, not blow up the reveal.\nexport const revealSpec = (mode: RevealMode = 'smart'): RevealSpec => {\n if (typeof mode !== 'string') return mode;\n return (NAMED as Record<string, RevealSpec>)[mode] ?? smart;\n};\n\n/** Longest a pane can take to leave under `mode`, for a framework that has to know up front. */\nexport function exitDuration(mode?: RevealMode) {\n const spec = revealSpec(mode);\n const hold = spec.hold ?? 0;\n if (spec === together) return FADE_DURATION;\n if (spec === sequence) return CASCADE_SPREAD + FADE_DURATION;\n if (spec === smart) return hold + CASCADE_SPREAD + FADE_DURATION;\n if (spec === sweep) return hold + SWEEP_SPREAD + FADE_DURATION;\n if (spec.duration === 0) return 0;\n // A choice can bring its own delay, as long as the cap allows\n const delay = spec.choose ? MAX_DELAY : Math.min(Math.max(spec.delay ?? 0, 0), MAX_DELAY);\n return hold + delay + MAX_DELAY + MAX_DURATION;\n}\n","import {\n ATTR_RECT,\n ATTR_LAYER,\n ATTR_EXITING,\n ATTR_GHOST,\n ATTR_OWN,\n ATTR_PANE,\n ATTR_SNAPSHOT,\n FADE_DURATION,\n RESIZE_DURATION,\n} from './constants';\nimport { imageReady, pendingImages } from './images';\nimport { animationsOf, canAnimate, prefersReducedMotion } from './motion';\nimport { warnOnce } from './dev';\nimport {\n planReveal,\n pieces,\n type Plan,\n type RevealMode,\n type SequencePlan,\n type WipePlan,\n} from './plan';\nimport { revealSpec } from './reveals';\nimport { rectsOf, shimmer } from './shimmer';\n\nexport { prefersReducedMotion };\n\nconst noop = () => {};\n\nconst settle = (animation: Animation) => animation.finished.then(noop, noop);\n\n// How a reveal's incoming pane decided to arrive, for its outgoing pane to match\nconst plans = new WeakMap<Element, Plan | { kind: 'skeleton'; hold: number }>();\n\nfunction appear(element: Element, delay = 0, duration = FADE_DURATION, from = 0, enter?: Keyframe) {\n if (prefersReducedMotion()) return Promise.resolve();\n return settle(\n element.animate([{ ...enter, opacity: from }, { opacity: 1 }], {\n duration,\n delay,\n easing: 'ease',\n fill: 'backwards',\n })\n );\n}\n\n// The bones layer, or the ghost a skeleton is drawn from — vanilla adds its layer a moment later\nconst isSkeleton = (element: Element) =>\n !!element.querySelector(`[${ATTR_LAYER}], [${ATTR_GHOST}], :scope > [${ATTR_OWN}]`);\n\nconst sameBox = (a: DOMRect, b: DOMRect) =>\n Math.abs(a.left - b.left) < 2 &&\n Math.abs(a.top - b.top) < 2 &&\n Math.abs(a.width - b.width) < 2 &&\n Math.abs(a.height - b.height) < 2;\n\n// Bones standing in for images still loading, by reveal\nconst standIns = new WeakMap<Element, Set<HTMLElement>>();\n\nfunction clearStandIns(root: Element) {\n for (const stand of standIns.get(root) ?? []) stand.remove();\n standIns.delete(root);\n}\n\n// Each image still loading stays hidden behind a bone of its own until it's ready, so nothing else waits on it\nfunction holdImages(element: HTMLElement, root: HTMLElement) {\n const images = pendingImages(element);\n const overSkeleton = [...root.children].some(\n (pane) => pane !== element && pane.hasAttribute(ATTR_PANE) && isSkeleton(pane)\n );\n if (!images.length || !overSkeleton) return;\n for (const image of images) image.style.opacity = '0';\n\n // A microtask on, once the skeleton has popped out — layout read any sooner moves the page\n queueMicrotask(() => {\n if (!element.isConnected) return;\n const origin = root.getBoundingClientRect();\n const bones = [...root.querySelectorAll(`:scope > [${ATTR_EXITING}] [${ATTR_LAYER}]`)].flatMap(\n rectsOf\n );\n const stands = standIns.get(root) ?? new Set<HTMLElement>();\n standIns.set(root, stands);\n\n for (const image of images) {\n const rect = image.getBoundingClientRect();\n // Its bone in the skeleton, which the stand-in takes over exactly\n const bone = bones.find((b) => sameBox(b.getBoundingClientRect(), rect));\n const box = bone?.getBoundingClientRect() ?? rect;\n const stand = document.createElement('div');\n // Same \"media\"-type bone the main pass produces — fill colour comes from the\n // stylesheet (`[ask-rect]` → `var(--ask-base)`) so a consumer theme reaches it.\n stand.setAttribute(ATTR_RECT, 'media');\n Object.assign(stand.style, {\n position: 'absolute',\n left: `${box.left - origin.left - root.clientLeft}px`,\n top: `${box.top - origin.top - root.clientTop}px`,\n width: `${box.width}px`,\n height: `${box.height}px`,\n borderRadius: bone?.style.borderRadius || getComputedStyle(image).borderRadius,\n backgroundRepeat: 'no-repeat',\n pointerEvents: 'none',\n });\n root.append(stand);\n stands.add(stand);\n if (bone) bone.style.visibility = 'hidden';\n shimmer(stand);\n\n imageReady(image).then(() => {\n if (!stands.has(stand)) return;\n stands.delete(stand);\n image.style.opacity = '';\n appear(image);\n if (prefersReducedMotion()) return stand.remove();\n settle(\n stand.animate([{ opacity: 1 }, { opacity: 0 }], {\n duration: FADE_DURATION,\n easing: 'ease',\n fill: 'forwards',\n })\n ).then(() => stand.remove());\n });\n }\n });\n}\n\nfunction sequenceIn(element: HTMLElement, plan: SequencePlan) {\n if (prefersReducedMotion()) return Promise.resolve();\n return Promise.all(\n pieces(element).map((piece) => {\n const delay = plan.pieceDelay(piece);\n if (delay === null) return;\n return appear(piece, delay, plan.duration, 0, plan.enter);\n })\n ).then(noop);\n}\n\n// Content arriving at once: anything still on its way out goes now too\nfunction clearExiting(root: Element) {\n for (const pane of root.querySelectorAll<HTMLElement>(`:scope > [${ATTR_EXITING}]`)) {\n for (const animation of animationsOf(pane)) animation.finish();\n pane.style.opacity = '0';\n }\n}\n\n// Content still fading out as content lands again — what the new pane takes over from, so the two never dip together\nfunction takeOver(root: Element) {\n let from = 0;\n for (const pane of root.querySelectorAll<HTMLElement>(`:scope > [${ATTR_EXITING}]`)) {\n if (isSkeleton(pane)) continue;\n from = Math.max(from, parseFloat(getComputedStyle(pane).opacity) || 0);\n for (const animation of animationsOf(pane)) animation.finish();\n pane.style.opacity = '0';\n }\n return from;\n}\n\n/** Brings a pane in: a skeleton after the reveal's `hold`, content as `reveal` plans; `initial` has nothing to replace. */\nexport function fadeIn(\n element: HTMLElement,\n reveal: RevealMode = 'smart',\n { initial = false } = {}\n): Promise<void> {\n let arriving = arrivals.get(element);\n if (!arriving) {\n arriving = arrive(element, reveal, initial);\n arrivals.set(element, arriving);\n }\n return arriving;\n}\n\n// One arrival per pane: StrictMode mounts twice, and a second plan would part from the first, which the outgoing pane already matched\nconst arrivals = new WeakMap<HTMLElement, Promise<void>>();\n\nfunction arrive(element: HTMLElement, reveal: RevealMode, initial: boolean): Promise<void> {\n const root = element.parentElement;\n const spec = revealSpec(reveal);\n\n if (isSkeleton(element)) {\n if (root) clearStandIns(root);\n const hold = Math.max(spec.hold ?? 0, 0);\n if (!hold) {\n if (root) plans.delete(root);\n return initial ? Promise.resolve() : appear(element);\n }\n if (root) plans.set(root, { kind: 'skeleton', hold });\n // A reveal's first skeleton has nothing on screen to hold back for — held, it would only be a blank\n if (initial) return Promise.resolve();\n return appear(element, hold);\n }\n if (initial || !root) return Promise.resolve();\n\n const from = takeOver(root);\n if (from > 0.01) {\n const duration = FADE_DURATION * (1 - from);\n plans.set(root, { kind: 'together', delay: 0, duration });\n return appear(element, 0, duration, from);\n }\n\n holdImages(element, root);\n\n const plan = planReveal(element, root, spec, (key) =>\n warnOnce(\n `enter:${key}`,\n `\\`enter\\` can't set \\`${key}\\`: only properties that change nothing's layout animate, so the reveal never moves the page.`\n )\n );\n plans.set(root, plan);\n if (plan.kind === 'instant') {\n clearExiting(root);\n return Promise.resolve();\n }\n if (plan.kind === 'sequence') return sequenceIn(element, plan);\n if (plan.kind === 'wipe') return wipe(element, plan, true);\n return appear(element, plan.delay, plan.duration, 0, plan.enter);\n}\n\n/** Where a pane stands within its reveal — what it's pinned to when it pops out. */\nexport type PaneBox = {\n top: number;\n left: number;\n width: number;\n height: number;\n};\n\n/** Measures `element` for `fadeOut`: before its replacement is inserted, or scroll anchoring moves the page. */\nexport function boxOf(element: HTMLElement): PaneBox {\n // Fractional, not offset*: a width rounded down rewraps a shrink-to-fit pane's text as it leaves\n const rect = element.getBoundingClientRect();\n const parent = element.offsetParent ?? document.documentElement;\n const origin = parent.getBoundingClientRect();\n return {\n top: rect.top - origin.top - parent.clientTop,\n left: rect.left - origin.left - parent.clientLeft,\n width: rect.width,\n height: rect.height,\n };\n}\n\n// Takes the element out of flow where it stands, so what replaces it lays out at once\nfunction popOut(element: HTMLElement, box = boxOf(element)) {\n Object.assign(element.style, {\n position: 'absolute',\n top: `${box.top}px`,\n left: `${box.left}px`,\n width: `${box.width}px`,\n height: `${box.height}px`,\n margin: '0',\n boxSizing: 'border-box',\n pointerEvents: 'none',\n });\n element.inert = true;\n element.setAttribute(ATTR_EXITING, '');\n return box;\n}\n\ntype Resize = { animation: Animation; overflow: string; boxSizing: string };\n\n// A reveal's running resize, so the next starts from where it got to and restores the styles it found\nconst resizes = new WeakMap<HTMLElement, Resize>();\n\n// Eases a reveal from the height the outgoing pane gave it to the incoming one's; the outgoing pane is already out of flow\nfunction resize(root: HTMLElement, box: PaneBox) {\n const incoming = root.querySelector<HTMLElement>(\n `:scope > [${ATTR_PANE}]:not([${ATTR_EXITING}])`\n );\n if (!incoming) return;\n const running = resizes.get(root);\n const shown = root.getBoundingClientRect().height;\n running?.animation.cancel();\n const to = root.getBoundingClientRect().height;\n const from = running ? shown : to - incoming.getBoundingClientRect().height + box.height;\n if (Math.abs(from - to) < 0.5) {\n if (running) restore(root, running);\n return;\n }\n\n const { overflow, boxSizing } = running ?? root.style;\n Object.assign(root.style, { overflow: 'clip', boxSizing: 'border-box' });\n const animation = root.animate([{ height: `${from}px` }, { height: `${to}px` }], {\n duration: RESIZE_DURATION,\n easing: 'cubic-bezier(0.2, 0, 0, 1)',\n });\n const current = { animation, overflow, boxSizing };\n resizes.set(root, current);\n settle(animation).then(() => {\n if (resizes.get(root) === current) restore(root, current);\n });\n}\n\nfunction restore(root: HTMLElement, { overflow, boxSizing }: Resize) {\n resizes.delete(root);\n Object.assign(root.style, { overflow, boxSizing });\n}\n\n/** Resolves once `element` can be removed, leaving as the pane replacing it decides; its parent must be positioned. */\nexport function fadeOut(element: HTMLElement, box?: PaneBox): Promise<void> {\n // Read before cancelling, so an interrupted fade-in leaves from where it got to\n const opacity = parseFloat(getComputedStyle(element).opacity);\n const from = Number.isNaN(opacity) ? 1 : opacity;\n for (const animation of animationsOf(element)) animation.cancel();\n clearMask(element);\n element.style.filter = '';\n\n const parent = element.parentElement;\n // Content moving on: the bones standing in for its images go with it\n if (parent && !isSkeleton(element)) clearStandIns(parent);\n const stood = popOut(element, box);\n\n const fade = (delay: number, duration: number) => {\n if (!canAnimate()) {\n element.style.opacity = '0';\n return Promise.resolve();\n }\n return settle(\n element.animate([{ opacity: from }, { opacity: 0 }], {\n duration: duration * from,\n delay,\n easing: 'ease',\n fill: 'forwards',\n })\n );\n };\n\n // A microtask on, so the pane replacing it has registered how it arrives\n return Promise.resolve().then(() => {\n const plan = parent && plans.get(parent);\n const instant = prefersReducedMotion() || plan?.kind === 'instant';\n if (parent && !instant) resize(parent, stood);\n\n // Content stays until the skeleton replacing it shows — which may be never\n if (plan?.kind === 'skeleton') return fade(plan.hold, FADE_DURATION);\n if (instant) {\n element.style.opacity = '0';\n return;\n }\n if (plan?.kind === 'sequence' && isSkeleton(element)) {\n return sequenceOut(element, plan);\n }\n if (plan?.kind === 'wipe' && isSkeleton(element)) {\n return wipe(element, plan, false);\n }\n if (plan?.kind === 'together') return fade(plan.delay, plan.duration);\n return fade(0, FADE_DURATION);\n });\n}\n\nfunction sequenceOut(element: HTMLElement, plan: SequencePlan) {\n // The content's own surfaces arrive whole; only the bones go piece by piece\n for (const ghost of element.querySelectorAll<HTMLElement>(\n `[${ATTR_GHOST}], [${ATTR_SNAPSHOT}]`\n )) {\n ghost.style.visibility = 'hidden';\n }\n\n // A skeleton the content draws itself sits in the ghost, but leaves like a bone\n const own = [...element.querySelectorAll<HTMLElement>(`[${ATTR_GHOST}] [${ATTR_OWN}]`)].filter(\n (part) => !part.parentElement?.closest(`[${ATTR_OWN}]`)\n );\n for (const part of own) part.style.visibility = 'visible';\n\n const bones = [...[...element.querySelectorAll(`[${ATTR_LAYER}]`)].flatMap(rectsOf), ...own];\n return Promise.all(\n bones.map((bone) => {\n const rect = bone.getBoundingClientRect();\n const go = (delay: number) =>\n settle(\n bone.animate([{ opacity: 1 }, { opacity: 0 }], {\n duration: plan.duration,\n delay,\n easing: 'ease',\n fill: 'forwards',\n })\n );\n const delay = plan.boneDelay(rect);\n if (delay === null) {\n bone.style.opacity = '0';\n return;\n }\n return go(delay);\n })\n ).then(noop);\n}\n\nconst STALL = 100; // ms between frames that counts as frames dropping — the wipe gives way to a crossfade\n\n// Running fronts, by pane — stopped when the pane's mask is cleared\nconst fronts = new WeakMap<HTMLElement, () => void>();\n\n// Prefixed too: Safari before 15.4 masks with -webkit- only\nfunction setMask(element: HTMLElement, image: string) {\n element.style.setProperty('mask-image', image);\n element.style.setProperty('-webkit-mask-image', image);\n}\n\n// The inverse of `image`: a full layer with `image` cut out of it\nfunction setInverseMask(element: HTMLElement, image: string) {\n setMask(element, `linear-gradient(#000 0 0), ${image}`);\n // Prefixed first: WebKit aliases the two, and the later wins\n element.style.setProperty('-webkit-mask-composite', 'xor');\n element.style.setProperty('mask-composite', 'exclude');\n}\n\nfunction clearMask(element: HTMLElement) {\n fronts.get(element)?.();\n for (const property of [\n 'mask-image',\n '-webkit-mask-image',\n 'mask-composite',\n '-webkit-mask-composite',\n ]) {\n element.style.removeProperty(property);\n }\n}\n\n// A wipe across one pane on the plan's shared clock; the plainest mask, rewritten each frame, for Safari 18\nfunction wipe(element: HTMLElement, plan: WipePlan, incoming: boolean) {\n const pane = { rect: element.getBoundingClientRect(), reveal: plan.reveal };\n const { mask, out } = plan.wipe;\n const draw = (at: number) => {\n if (incoming) setMask(element, mask(at, pane));\n else if (out) setMask(element, out(at, pane));\n else setInverseMask(element, mask(at, pane));\n };\n const progress = () => (performance.now() - plan.start) / plan.duration;\n if (progress() >= 1) {\n if (!incoming) element.style.opacity = '0';\n return Promise.resolve();\n }\n if (incoming) {\n plan.wipe.effect?.(element, { ...pane, progress });\n if (plan.enter) {\n element.animate([plan.enter, {}], {\n duration: plan.duration,\n delay: Math.max(plan.start - performance.now(), 0),\n easing: 'ease',\n fill: 'backwards',\n });\n }\n }\n\n // Resolves null once crossed, or with how far it got when frames dropped and the wipe gave way\n const run = new Promise<number | null>((resolve) => {\n let frame = 0;\n let last = performance.now();\n let at = 0;\n const tick = () => {\n const now = performance.now();\n if (now - last > STALL) plan.stalled = true;\n last = now;\n if (plan.stalled) return done(at);\n at = Math.min(Math.max(progress(), 0), 1);\n draw(at);\n if (at < 1) frame = requestAnimationFrame(tick);\n else done(null);\n };\n const done = (stalledAt: number | null = null) => {\n cancelAnimationFrame(frame);\n clearTimeout(deadline);\n fronts.delete(element);\n resolve(stalledAt);\n };\n // Frames can stop altogether, as in a hidden tab: the wipe still ends when its time is up\n const deadline = setTimeout(\n () => done(null),\n Math.max(plan.start + plan.duration - performance.now(), 0) + STALL\n );\n fronts.set(element, done);\n tick();\n });\n\n return run.then((stalledAt) => {\n clearMask(element);\n if (stalledAt === null) {\n if (!incoming) element.style.opacity = '0';\n return;\n }\n // Frames dropped: the rest as a crossfade, from as far as the front got\n const rest = FADE_DURATION * (1 - stalledAt);\n if (incoming) return appear(element, 0, rest, stalledAt);\n return settle(\n element.animate([{ opacity: 1 - stalledAt }, { opacity: 0 }], {\n duration: rest,\n easing: 'ease',\n fill: 'forwards',\n })\n ).then(() => {\n element.style.opacity = '0';\n });\n });\n}\n","import { ATTR_GHOST, ATTR_PANE, ATTR_REVEAL, ATTR_STATUS } from './constants';\nimport { fadeIn, fadeOut } from './fade';\nimport type { RevealMode } from './plan';\nimport { Ghost } from './ghost';\nimport { Memory } from './memory';\nimport { addStyles, removeStyles } from './styles';\n\nexport type RevealOptions = {\n /** Remembers the shape under this key; without it, one is derived from the markup. */\n id?: string;\n /** How content replaces its skeleton: `smart` (the default), `together`, `sequence`, `sweep`, or a `RevealSpec` of your own. */\n reveal?: RevealMode;\n /** Read to screen readers while loading, in place of the skeleton — \"Loading profile\". */\n label?: string;\n /** Called once content has come in over a skeleton. */\n onReveal?: () => void;\n};\n\n/** Shows a skeleton of content while it loads, then crossfades to the content itself. */\nexport class Reveal {\n private current: HTMLElement | null = null;\n private ghost: Ghost | null = null;\n private memory: Memory | null = null;\n private arrival: Promise<void> = Promise.resolve();\n\n constructor(\n private element: HTMLElement,\n private options: RevealOptions = {}\n ) {\n addStyles();\n element.setAttribute(ATTR_REVEAL, '');\n }\n\n /** Shows a skeleton measured from `content`, rendered from sample data, or else the shape last shown. */\n load(content?: Node | string): HTMLElement {\n const loading = document.createElement('div');\n const ghost = document.createElement('div');\n ghost.setAttribute(ATTR_GHOST, '');\n if (content) ghost.append(content);\n loading.append(ghost);\n\n const pane = this.swap(loading);\n // Outside the skeleton, which is hidden from screen readers\n if (this.options.label) {\n const status = document.createElement('span');\n status.setAttribute(ATTR_STATUS, '');\n status.textContent = this.options.label;\n pane.prepend(status);\n }\n this.element.setAttribute('aria-busy', 'true');\n this.ghost = new Ghost(loading, { id: this.options.id });\n return pane;\n }\n\n show(content: Node | string): HTMLElement {\n const loading = this.element.getAttribute('aria-busy') === 'true';\n const pane = this.swap(content);\n if (loading && this.options.onReveal) this.arrival.then(this.options.onReveal);\n this.element.removeAttribute('aria-busy');\n this.memory = new Memory(pane, { id: this.options.id });\n return pane;\n }\n\n private swap(content: Node | string) {\n this.memory?.destroy();\n this.ghost?.destroy();\n this.memory = this.ghost = null;\n\n const pane = document.createElement('div');\n pane.setAttribute(ATTR_PANE, '');\n pane.append(content);\n\n const previous = this.current;\n this.current = pane;\n\n // Popped out before the new pane lands, while it still measures where it stood\n if (previous) fadeOut(previous).then(() => previous.remove());\n this.element.append(pane);\n this.arrival = fadeIn(pane, this.options.reveal, { initial: !previous });\n\n return pane;\n }\n\n destroy() {\n this.memory?.destroy();\n this.ghost?.destroy();\n removeStyles();\n }\n}\n"],"mappings":"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"}
|