[{"data":1,"prerenderedAt":7606},["ShallowReactive",2],{"\u002Fui\u002Fghost-skeleton":3},{"id":4,"title":5,"body":6,"description":7573,"extension":7574,"meta":7575,"navigation":224,"order":108,"package":16,"path":7602,"seo":7603,"stem":7604,"__hash__":7605},"docs\u002Fui\u002Fghost-skeleton.md","AGhostSkeleton — Vue 3 \u002F Nuxt skeleton loader",{"type":7,"value":8,"toc":7504},"minimark",[9,17,29,32,35,72,77,80,85,88,150,154,161,181,264,289,293,304,313,361,365,382,385,391,394,504,511,520,620,631,654,758,762,780,850,856,882,1042,1050,1054,1073,1440,1450,1453,1457,1473,1626,1657,1672,1682,1685,1689,1700,1770,1787,1790,1807,1810,1813,1817,1856,1860,1863,1936,2001,2024,2042,2045,2049,2055,2077,2080,2093,2096,2100,2171,2177,2181,2226,2302,2306,2309,2312,2316,2319,2333,2358,2368,2468,2516,2528,2532,2557,2564,2567,2595,2606,2619,2622,2625,2684,2695,2811,2832,2843,2847,2981,3004,3008,3019,3105,3196,3202,3208,3265,3271,3277,3298,3362,3366,3419,3478,3482,3492,3496,3499,3532,3536,3545,3552,3559,3562,3658,3671,3674,3684,3867,3871,3878,3888,3892,3895,4261,4273,4277,4280,4667,4677,4681,4694,5094,5106,5110,5116,5514,5522,5526,5533,5988,5992,5999,6475,6478,6485,6495,6658,6665,6669,6675,6854,6858,6938,6956,6960,6988,6993,7092,7097,7165,7170,7222,7226,7296,7301,7317,7409,7418,7469,7500],[10,11,13],"h1",{"id":12},"alikhalillla-ghost-skeleton",[14,15,16],"code",{},"@alikhalilll\u002Fa-ghost-skeleton",[18,19,20],"blockquote",{},[21,22,23,24,28],"p",{},"A skeleton that ",[25,26,27],"strong",{},"measures itself"," from your real component. One template, pixel-aligned chrome, no second DOM tree to maintain.",[30,31],"demo-overview-tile-row",{},[21,33,34],{},"Every grey rectangle above was measured from the component rendered beneath it. There is no parallel placeholder file. Padding changes on the real card and the skeleton follows; text wraps differently and the bars re-flow; a card gains a shadow and the outline copies it.",[36,37,40],"alert",{"title":38,"type":39},"What this package is — and isn't","note",[21,41,42,45,46,49,50,53,54,57,58,61,62,65,66,71],{},[14,43,44],{},"AGhostSkeleton"," ",[25,47,48],{},"owns a loading state",". It is not a hand-authored shape library (",[14,51,52],{},"\u003CRectBone \u002F>"," \u002F ",[14,55,56],{},"\u003CCircleBone \u002F>","), and it does nothing useful without a real component plus a representative ",[14,59,60],{},"sample"," to measure. If you want to draw an arbitrary pill or bar with no measurement, that's ",[14,63,64],{},"\u003CAGhostSkeletonBox>"," — covered ",[67,68,70],"a",{"href":69},"#standalone-box","below",".",[73,74,76],"h2",{"id":75},"install","Install",[78,79],"doc-install",{"pkg":16},[81,82,84],"h3",{"id":83},"nuxt-3-4","Nuxt 3 \u002F 4",[21,86,87],{},"Register the module. The four components auto-import, the stylesheet is injected, and the pre-paint boot script is wired for you.",[89,90,95],"pre",{"className":91,"code":92,"language":93,"meta":94,"style":94},"language-ts shiki shiki-themes github-light-default github-dark-default","\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  modules: ['@alikhalilll\u002Fa-ghost-skeleton\u002Fnuxt'],\n});\n","ts","",[14,96,97,106,124,141],{"__ignoreMap":94},[98,99,102],"span",{"class":100,"line":101},"line",1,[98,103,105],{"class":104},"sU953","\u002F\u002F nuxt.config.ts\n",[98,107,109,113,116,120],{"class":100,"line":108},2,[98,110,112],{"class":111},"sjeE4","export",[98,114,115],{"class":111}," default",[98,117,119],{"class":118},"sbjLL"," defineNuxtConfig",[98,121,123],{"class":122},"sTDnQ","({\n",[98,125,127,131,135,138],{"class":100,"line":126},3,[98,128,130],{"class":129},"s4rv2","  modules: [",[98,132,134],{"class":133},"sSVrQ","'@alikhalilll\u002Fa-ghost-skeleton\u002Fnuxt'",[98,136,137],{"class":129},"]",[98,139,140],{"class":122},",\n",[98,142,144,147],{"class":100,"line":143},4,[98,145,146],{"class":122},"})",[98,148,149],{"class":129},";\n",[81,151,153],{"id":152},"vue-3-vite","Vue 3 + Vite",[21,155,156,157,160],{},"Import the stylesheet once in your entry. Optionally wire the resolver so ",[14,158,159],{},"unplugin-vue-components"," auto-imports the four components the first time you use them.",[89,162,164],{"className":91,"code":163,"language":93,"meta":94,"style":94},"\u002F\u002F main.ts\nimport '@alikhalilll\u002Fa-ghost-skeleton\u002Fstyles.css';\n",[14,165,166,171],{"__ignoreMap":94},[98,167,168],{"class":100,"line":101},[98,169,170],{"class":104},"\u002F\u002F main.ts\n",[98,172,173,176,179],{"class":100,"line":108},[98,174,175],{"class":111},"import",[98,177,178],{"class":133}," '@alikhalilll\u002Fa-ghost-skeleton\u002Fstyles.css'",[98,180,149],{"class":129},[89,182,184],{"className":91,"code":183,"language":93,"meta":94,"style":94},"\u002F\u002F vite.config.ts\nimport Components from 'unplugin-vue-components\u002Fvite';\nimport AGhostSkeletonResolver from '@alikhalilll\u002Fa-ghost-skeleton\u002Fresolver';\n\nexport default {\n  plugins: [Components({ resolvers: [AGhostSkeletonResolver()] })],\n};\n",[14,185,186,191,206,220,226,236,256],{"__ignoreMap":94},[98,187,188],{"class":100,"line":101},[98,189,190],{"class":104},"\u002F\u002F vite.config.ts\n",[98,192,193,195,198,201,204],{"class":100,"line":108},[98,194,175],{"class":111},[98,196,197],{"class":129}," Components ",[98,199,200],{"class":111},"from",[98,202,203],{"class":133}," 'unplugin-vue-components\u002Fvite'",[98,205,149],{"class":129},[98,207,208,210,213,215,218],{"class":100,"line":126},[98,209,175],{"class":111},[98,211,212],{"class":129}," AGhostSkeletonResolver ",[98,214,200],{"class":111},[98,216,217],{"class":133}," '@alikhalilll\u002Fa-ghost-skeleton\u002Fresolver'",[98,219,149],{"class":129},[98,221,222],{"class":100,"line":143},[98,223,225],{"emptyLinePlaceholder":224},true,"\n",[98,227,229,231,233],{"class":100,"line":228},5,[98,230,112],{"class":111},[98,232,115],{"class":111},[98,234,235],{"class":122}," {\n",[98,237,239,242,245,248,251,254],{"class":100,"line":238},6,[98,240,241],{"class":129},"  plugins: [",[98,243,244],{"class":118},"Components",[98,246,247],{"class":129},"({ resolvers: [",[98,249,250],{"class":118},"AGhostSkeletonResolver",[98,252,253],{"class":129},"()] })]",[98,255,140],{"class":122},[98,257,259,262],{"class":100,"line":258},7,[98,260,261],{"class":122},"}",[98,263,149],{"class":129},[36,265,268],{"title":266,"type":267},"Four components ship","info",[21,269,270,273,274,276,277,280,281,284,285,288],{},[14,271,272],{},"\u003CAGhostSkeleton>"," (the measured loader), ",[14,275,64],{}," (a standalone bar), ",[14,278,279],{},"\u003CAGhostSkeletonSuspense>"," (a ",[14,282,283],{},"\u003CSuspense>"," wrapper that measures its fallback), and ",[14,286,287],{},"\u003CAGhostSkeletonProvider>"," (app-wide theme + reveal defaults).",[73,290,292],{"id":291},"why-this-exists","Why this exists",[21,294,295,296,299,300,303],{},"A hand-authored ",[14,297,298],{},"\u003CProductCardSkeleton>"," next to ",[14,301,302],{},"\u003CProductCard>"," is a second template that drifts: padding diverges, fonts change, images start loading later and the reveal jumps.",[21,305,306,308,309,312],{},[14,307,44],{}," sidesteps that by laying the real component out invisibly, reading the DOM it produced with ",[14,310,311],{},"getBoundingClientRect()"," and Canvas 2D font metrics, then reconstructing a placeholder from what it saw. One template — the real one — stays the source of truth.",[314,315,316,323,329,335,341,355],"ul",{},[317,318,319,322],"li",{},[25,320,321],{},"Zero layout shift."," Bone positions come from the actual DOM, not a copy.",[317,324,325,328],{},[25,326,327],{},"Painted chrome is reproduced",", not re-drawn. Backgrounds, borders, radii, and box-shadows copy over verbatim onto chrome bones.",[317,330,331,334],{},[25,332,333],{},"Text follows the font's ascender \u002F descender",", not a guessed line-height.",[317,336,337,340],{},[25,338,339],{},"One document clock"," drives every shimmer, so skeletons mounted at different times still sweep in phase.",[317,342,343,346,347,350,351,354],{},[25,344,345],{},"Direction-aware animations."," The shimmer, the content-reveal sweep, and the ",[14,348,349],{},"byPosition"," sequence order all follow the inherited CSS ",[14,352,353],{},"direction"," — an RTL page flows right-to-left with no prop or custom property.",[317,356,357,360],{},[25,358,359],{},"One component, four states"," — loading, content, empty, error — plus the reveal transition between them.",[73,362,364],{"id":363},"quick-start","Quick start",[21,366,367,368,370,371,373,374,377,378,381],{},"Wrap a component with ",[14,369,272],{},". Pass the data ref and a representative ",[14,372,60],{},". While ",[14,375,376],{},"data"," is ",[14,379,380],{},"null",", the plugin renders the sample out of sight, measures it, and paints the skeleton. When data arrives, it reveals.",[21,383,384],{},"Five rules keep the measurement honest and the paint on-brand. Each one has a short section below with a tiny before\u002Fafter; the full example at the end puts them together.",[73,386,388,389],{"id":387},"rule-1-always-pass-a-sample","Rule 1 — Always pass a ",[14,390,60],{},[21,392,393],{},"The sample is the shape the plugin measures while real data is loading. Its structure should mirror the real response: same number of lines of text, same avatar size, same list length. Skip it and there's nothing to measure, so the skeleton has no shape to draw.",[89,395,399],{"className":396,"code":397,"language":398,"meta":94,"style":94},"language-vue shiki shiki-themes github-light-default github-dark-default","\u003C!-- ❌ no sample — the skeleton has nothing to measure -->\n\u003CAGhostSkeleton :data=\"user\">\n  \u003Ctemplate #default=\"{ data }\">\u003CUserCard :user=\"data\" \u002F>\u003C\u002Ftemplate>\n\u003C\u002FAGhostSkeleton>\n\n\u003C!-- ✅ sample matches real-response shape -->\n\u003CAGhostSkeleton :data=\"user\" :sample=\"SAMPLE_USER\">\n  \u003Ctemplate #default=\"{ data }\">\u003CUserCard :user=\"data\" \u002F>\u003C\u002Ftemplate>\n\u003C\u002FAGhostSkeleton>\n","vue",[14,400,401,406,434,439,448,452,457,490,495],{"__ignoreMap":94},[98,402,403],{"class":100,"line":101},[98,404,405],{"class":104},"\u003C!-- ❌ no sample — the skeleton has nothing to measure -->\n",[98,407,408,411,414,417,420,423,426,429,431],{"class":100,"line":108},[98,409,410],{"class":129},"\u003C",[98,412,44],{"class":413},"sjgCt",[98,415,416],{"class":129}," :",[98,418,376],{"class":419},"sHrmB",[98,421,422],{"class":129},"=",[98,424,425],{"class":129},"\"",[98,427,428],{"class":129},"user",[98,430,425],{"class":129},[98,432,433],{"class":129},">\n",[98,435,436],{"class":100,"line":126},[98,437,438],{"class":129},"  \u003Ctemplate #default=\"{ data }\">\u003CUserCard :user=\"data\" \u002F>\u003C\u002Ftemplate>\n",[98,440,441,444,446],{"class":100,"line":143},[98,442,443],{"class":129},"\u003C\u002F",[98,445,44],{"class":413},[98,447,433],{"class":129},[98,449,450],{"class":100,"line":228},[98,451,225],{"emptyLinePlaceholder":224},[98,453,454],{"class":100,"line":238},[98,455,456],{"class":104},"\u003C!-- ✅ sample matches real-response shape -->\n",[98,458,459,461,463,465,467,469,471,473,475,477,479,481,483,486,488],{"class":100,"line":258},[98,460,410],{"class":129},[98,462,44],{"class":413},[98,464,416],{"class":129},[98,466,376],{"class":419},[98,468,422],{"class":129},[98,470,425],{"class":129},[98,472,428],{"class":129},[98,474,425],{"class":129},[98,476,416],{"class":129},[98,478,60],{"class":419},[98,480,422],{"class":129},[98,482,425],{"class":129},[98,484,485],{"class":419},"SAMPLE_USER",[98,487,425],{"class":129},[98,489,433],{"class":129},[98,491,493],{"class":100,"line":492},8,[98,494,438],{"class":129},[98,496,498,500,502],{"class":100,"line":497},9,[98,499,443],{"class":129},[98,501,44],{"class":413},[98,503,433],{"class":129},[73,505,507,508],{"id":506},"rule-2-give-the-skeleton-a-stable-id","Rule 2 — Give the skeleton a stable ",[14,509,510],{},"id",[21,512,513,514,516,517,519],{},"Shape memory is keyed by ",[14,515,510],{}," across visits. A returning user sees last session's measured shape immediately — no fresh measurement delay, no generic fallback. Omit the ",[14,518,510],{}," and every mount is a cold start.",[89,521,523],{"className":396,"code":522,"language":398,"meta":94,"style":94},"\u003C!-- ❌ no id — cold measurement every mount -->\n\u003CAGhostSkeleton :data=\"user\" :sample=\"SAMPLE_USER\">…\u003C\u002FAGhostSkeleton>\n\n\u003C!-- ✅ stable id — shape is recalled across visits -->\n\u003CAGhostSkeleton id=\"user-card\" :data=\"user\" :sample=\"SAMPLE_USER\">…\u003C\u002FAGhostSkeleton>\n",[14,524,525,530,567,571,576],{"__ignoreMap":94},[98,526,527],{"class":100,"line":101},[98,528,529],{"class":104},"\u003C!-- ❌ no id — cold measurement every mount -->\n",[98,531,532,534,536,538,540,542,544,546,548,550,552,554,556,558,560,563,565],{"class":100,"line":108},[98,533,410],{"class":129},[98,535,44],{"class":413},[98,537,416],{"class":129},[98,539,376],{"class":419},[98,541,422],{"class":129},[98,543,425],{"class":129},[98,545,428],{"class":129},[98,547,425],{"class":129},[98,549,416],{"class":129},[98,551,60],{"class":419},[98,553,422],{"class":129},[98,555,425],{"class":129},[98,557,485],{"class":419},[98,559,425],{"class":129},[98,561,562],{"class":129},">…\u003C\u002F",[98,564,44],{"class":413},[98,566,433],{"class":129},[98,568,569],{"class":100,"line":126},[98,570,225],{"emptyLinePlaceholder":224},[98,572,573],{"class":100,"line":143},[98,574,575],{"class":104},"\u003C!-- ✅ stable id — shape is recalled across visits -->\n",[98,577,578,580,582,585,587,590,592,594,596,598,600,602,604,606,608,610,612,614,616,618],{"class":100,"line":228},[98,579,410],{"class":129},[98,581,44],{"class":413},[98,583,584],{"class":419}," id",[98,586,422],{"class":129},[98,588,589],{"class":133},"\"user-card\"",[98,591,416],{"class":129},[98,593,376],{"class":419},[98,595,422],{"class":129},[98,597,425],{"class":129},[98,599,428],{"class":129},[98,601,425],{"class":129},[98,603,416],{"class":129},[98,605,60],{"class":419},[98,607,422],{"class":129},[98,609,425],{"class":129},[98,611,485],{"class":419},[98,613,425],{"class":129},[98,615,562],{"class":129},[98,617,44],{"class":413},[98,619,433],{"class":129},[73,621,623,624,627,628],{"id":622},"rule-3-destructure-data-in-default","Rule 3 — Destructure ",[14,625,626],{},"{ data }"," in ",[14,629,630],{},"#default",[21,632,633,634,637,638,640,641,645,646,653],{},"The plugin invokes the slot with ",[14,635,636],{},"{ data: SAMPLE }"," during measurement. If the slot ignores that argument and reads an outer ref instead, that ref is still ",[14,639,380],{}," while loading — children receive empty data, the ghost captures a half-drawn shape, and the cold-load skeleton is wrong. Warm visits hide the bug because the cache was written ",[642,643,644],"em",{},"after"," real data arrived. See ",[67,647,649,650,652],{"href":648},"#thread-data-through-the-slot","Thread ",[14,651,376],{}," through the slot"," for the full walkthrough.",[89,655,657],{"className":396,"code":656,"language":398,"meta":94,"style":94},"\u003C!-- ❌ reads the outer ref → rows=[] during measurement -->\n\u003Ctemplate #default>\n  \u003CPagesTable :rows=\"content?.rows ?? []\" \u002F>\n\u003C\u002Ftemplate>\n\n\u003C!-- ✅ destructures the slot prop → rows=SAMPLE.rows during measurement -->\n\u003Ctemplate #default=\"{ data }\">\n  \u003CPagesTable :rows=\"data?.rows ?? []\" \u002F>\n\u003C\u002Ftemplate>\n",[14,658,659,664,679,698,706,710,715,735,750],{"__ignoreMap":94},[98,660,661],{"class":100,"line":101},[98,662,663],{"class":104},"\u003C!-- ❌ reads the outer ref → rows=[] during measurement -->\n",[98,665,666,668,671,674,677],{"class":100,"line":108},[98,667,410],{"class":129},[98,669,670],{"class":413},"template",[98,672,673],{"class":129}," #",[98,675,676],{"class":419},"default",[98,678,433],{"class":129},[98,680,681,684,687,690,692,695],{"class":100,"line":126},[98,682,683],{"class":129},"  \u003C",[98,685,686],{"class":413},"PagesTable",[98,688,689],{"class":419}," :rows",[98,691,422],{"class":129},[98,693,694],{"class":133},"\"content?.rows ?? []\"",[98,696,697],{"class":129}," \u002F>\n",[98,699,700,702,704],{"class":100,"line":143},[98,701,443],{"class":129},[98,703,670],{"class":413},[98,705,433],{"class":129},[98,707,708],{"class":100,"line":228},[98,709,225],{"emptyLinePlaceholder":224},[98,711,712],{"class":100,"line":238},[98,713,714],{"class":104},"\u003C!-- ✅ destructures the slot prop → rows=SAMPLE.rows during measurement -->\n",[98,716,717,719,721,723,725,727,729,731,733],{"class":100,"line":258},[98,718,410],{"class":129},[98,720,670],{"class":413},[98,722,673],{"class":129},[98,724,676],{"class":419},[98,726,422],{"class":129},[98,728,425],{"class":129},[98,730,626],{"class":129},[98,732,425],{"class":129},[98,734,433],{"class":129},[98,736,737,739,741,743,745,748],{"class":100,"line":492},[98,738,683],{"class":129},[98,740,686],{"class":413},[98,742,689],{"class":419},[98,744,422],{"class":129},[98,746,747],{"class":133},"\"data?.rows ?? []\"",[98,749,697],{"class":129},[98,751,752,754,756],{"class":100,"line":497},[98,753,443],{"class":129},[98,755,670],{"class":413},[98,757,433],{"class":129},[73,759,761],{"id":760},"rule-4-give-images-explicit-dimensions","Rule 4 — Give images explicit dimensions",[21,763,764,765,768,769,53,772,775,776,779],{},"An ",[14,766,767],{},"\u003Cimg>"," without ",[14,770,771],{},"width",[14,773,774],{},"height"," or ",[14,777,778],{},"aspect-ratio"," reports zero height until the pixels arrive. The skeleton measures that zero and reserves no space, so the reveal jumps when the image finally loads.",[89,781,783],{"className":396,"code":782,"language":398,"meta":94,"style":94},"\u003C!-- ❌ no dimensions — reserved height is 0 until load -->\n\u003Cimg :src=\"user.avatar\" \u002F>\n\n\u003C!-- ✅ aspect-ratio pins the reserved space -->\n\u003Cimg :src=\"user.avatar\" class=\"aspect-square w-16\" \u002F>\n",[14,784,785,790,813,817,822],{"__ignoreMap":94},[98,786,787],{"class":100,"line":101},[98,788,789],{"class":104},"\u003C!-- ❌ no dimensions — reserved height is 0 until load -->\n",[98,791,792,794,797,799,802,804,806,809,811],{"class":100,"line":108},[98,793,410],{"class":129},[98,795,796],{"class":413},"img",[98,798,416],{"class":129},[98,800,801],{"class":419},"src",[98,803,422],{"class":129},[98,805,425],{"class":129},[98,807,808],{"class":129},"user.avatar",[98,810,425],{"class":129},[98,812,697],{"class":129},[98,814,815],{"class":100,"line":126},[98,816,225],{"emptyLinePlaceholder":224},[98,818,819],{"class":100,"line":143},[98,820,821],{"class":104},"\u003C!-- ✅ aspect-ratio pins the reserved space -->\n",[98,823,824,826,828,830,832,834,836,838,840,843,845,848],{"class":100,"line":228},[98,825,410],{"class":129},[98,827,796],{"class":413},[98,829,416],{"class":129},[98,831,801],{"class":419},[98,833,422],{"class":129},[98,835,425],{"class":129},[98,837,808],{"class":129},[98,839,425],{"class":129},[98,841,842],{"class":419}," class",[98,844,422],{"class":129},[98,846,847],{"class":133},"\"aspect-square w-16\"",[98,849,697],{"class":129},[73,851,853,854],{"id":852},"rule-5-theme-to-your-design-with-aghostskeletonprovider","Rule 5 — Theme to your design with ",[14,855,287],{},[21,857,858,859,862,863,866,867,869,870,873,874,877,878,881],{},"The raw fallback greys (",[14,860,861],{},"rgb(128 128 128 \u002F 0.2)"," base, ",[14,864,865],{},"rgb(255 255 255 \u002F 0.12)"," highlight) are translucent so they read on both light and dark pages — they're a stand-in, not a production look. Wrap your app once in ",[14,868,287],{}," to set the bone fill and shimmer colour against your real surface, and the provider's ",[14,871,872],{},"mode=\"system\""," toggle keeps the theme in step with ",[14,875,876],{},"prefers-color-scheme",". Per-skeleton overrides work too: any ancestor can declare the ",[14,879,880],{},"--ask-*"," variables and the cascade carries them down.",[89,883,885],{"className":396,"code":884,"language":398,"meta":94,"style":94},"\u003C!-- ❌ no provider — bones use the fallback greys regardless of your design -->\n\u003CAGhostSkeleton :data=\"user\" :sample=\"SAMPLE_USER\">…\u003C\u002FAGhostSkeleton>\n\n\u003C!-- ✅ app-wide provider, light and dark themed against real surfaces -->\n\u003CAGhostSkeletonProvider\n  mode=\"system\"\n  :theme=\"{\n    light: { base: '#d1d4dc', highlight: '#ffffff' },\n    dark: { base: '#31363f', highlight: 'rgba(255,255,255,0.08)' },\n    radius: '6px',\n  }\"\n>\n  \u003CAGhostSkeleton :data=\"user\" :sample=\"SAMPLE_USER\">…\u003C\u002FAGhostSkeleton>\n\u003C\u002FAGhostSkeletonProvider>\n",[14,886,887,892,928,932,937,944,954,969,986,1001,1012,1021,1026,1032],{"__ignoreMap":94},[98,888,889],{"class":100,"line":101},[98,890,891],{"class":104},"\u003C!-- ❌ no provider — bones use the fallback greys regardless of your design -->\n",[98,893,894,896,898,900,902,904,906,908,910,912,914,916,918,920,922,924,926],{"class":100,"line":108},[98,895,410],{"class":129},[98,897,44],{"class":413},[98,899,416],{"class":129},[98,901,376],{"class":419},[98,903,422],{"class":129},[98,905,425],{"class":129},[98,907,428],{"class":129},[98,909,425],{"class":129},[98,911,416],{"class":129},[98,913,60],{"class":419},[98,915,422],{"class":129},[98,917,425],{"class":129},[98,919,485],{"class":419},[98,921,425],{"class":129},[98,923,562],{"class":129},[98,925,44],{"class":413},[98,927,433],{"class":129},[98,929,930],{"class":100,"line":126},[98,931,225],{"emptyLinePlaceholder":224},[98,933,934],{"class":100,"line":143},[98,935,936],{"class":104},"\u003C!-- ✅ app-wide provider, light and dark themed against real surfaces -->\n",[98,938,939,941],{"class":100,"line":228},[98,940,410],{"class":129},[98,942,943],{"class":413},"AGhostSkeletonProvider\n",[98,945,946,949,951],{"class":100,"line":238},[98,947,948],{"class":419},"  mode",[98,950,422],{"class":129},[98,952,953],{"class":133},"\"system\"\n",[98,955,956,959,962,964,966],{"class":100,"line":258},[98,957,958],{"class":129},"  :",[98,960,961],{"class":419},"theme",[98,963,422],{"class":129},[98,965,425],{"class":129},[98,967,968],{"class":129},"{\n",[98,970,971,974,977,980,983],{"class":100,"line":492},[98,972,973],{"class":129},"    light: { base: ",[98,975,976],{"class":133},"'#d1d4dc'",[98,978,979],{"class":129},", highlight: ",[98,981,982],{"class":133},"'#ffffff'",[98,984,985],{"class":129}," },\n",[98,987,988,991,994,996,999],{"class":100,"line":497},[98,989,990],{"class":129},"    dark: { base: ",[98,992,993],{"class":133},"'#31363f'",[98,995,979],{"class":129},[98,997,998],{"class":133},"'rgba(255,255,255,0.08)'",[98,1000,985],{"class":129},[98,1002,1004,1007,1010],{"class":100,"line":1003},10,[98,1005,1006],{"class":129},"    radius: ",[98,1008,1009],{"class":133},"'6px'",[98,1011,140],{"class":129},[98,1013,1015,1018],{"class":100,"line":1014},11,[98,1016,1017],{"class":129},"  }",[98,1019,1020],{"class":129},"\"\n",[98,1022,1024],{"class":100,"line":1023},12,[98,1025,433],{"class":129},[98,1027,1029],{"class":100,"line":1028},13,[98,1030,1031],{"class":129},"  \u003CAGhostSkeleton :data=\"user\" :sample=\"SAMPLE_USER\">…\u003C\u002FAGhostSkeleton>\n",[98,1033,1035,1037,1040],{"class":100,"line":1034},14,[98,1036,443],{"class":129},[98,1038,1039],{"class":413},"AGhostSkeletonProvider",[98,1041,433],{"class":129},[21,1043,1044,1045,1049],{},"See ",[67,1046,1048],{"href":1047},"#theming","Theming"," for the full token table and chrome-bone rules.",[73,1051,1053],{"id":1052},"putting-it-together","Putting it together",[21,1055,1056,1057,1059,1060,1062,1063,1065,1066,1069,1070,1072],{},"All five rules applied — provider wraps the app with themed bones, each skeleton has a stable ",[14,1058,510],{},", a matching ",[14,1061,60],{},", ",[14,1064,626],{}," destructured in the slot, and the avatar's dimensions pinned via the class on ",[14,1067,1068],{},"\u003CUserCard>","'s own ",[14,1071,767],{},":",[89,1074,1076],{"className":396,"code":1075,"language":398,"meta":94,"style":94},"\u003Cscript setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\n\nconst user = ref\u003CUser | null>(null);\n\nconst SAMPLE_USER = {\n  name: 'Sarah Connor',\n  role: 'Chief Mitigation Officer',\n  avatar: 'https:\u002F\u002Fexample.com\u002Favatar.jpg',\n};\n\nonMounted(async () => {\n  user.value = await $fetch('\u002Fapi\u002Fme');\n});\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CAGhostSkeletonProvider\n    mode=\"system\"\n    :theme=\"{\n      light: { base: '#d1d4dc', highlight: '#ffffff' },\n      dark: { base: '#31363f', highlight: 'rgba(255,255,255,0.08)' },\n      radius: '6px',\n    }\"\n  >\n    \u003CAGhostSkeleton id=\"user-card\" :data=\"user\" :sample=\"SAMPLE_USER\">\n      \u003Ctemplate #default=\"{ data }\">\n        \u003CUserCard :user=\"data\" \u002F>\n      \u003C\u002Ftemplate>\n    \u003C\u002FAGhostSkeleton>\n  \u003C\u002FAGhostSkeletonProvider>\n\u003C\u002Ftemplate>\n",[14,1077,1078,1098,1112,1116,1149,1153,1164,1174,1184,1194,1199,1203,1222,1242,1247,1256,1261,1270,1277,1287,1298,1304,1310,1316,1322,1328,1360,1382,1401,1411,1421,1431],{"__ignoreMap":94},[98,1079,1080,1082,1085,1088,1091,1093,1096],{"class":100,"line":101},[98,1081,410],{"class":129},[98,1083,1084],{"class":413},"script",[98,1086,1087],{"class":419}," setup",[98,1089,1090],{"class":419}," lang",[98,1092,422],{"class":129},[98,1094,1095],{"class":133},"\"ts\"",[98,1097,433],{"class":129},[98,1099,1100,1102,1105,1107,1110],{"class":100,"line":108},[98,1101,175],{"class":111},[98,1103,1104],{"class":129}," { ref, onMounted } ",[98,1106,200],{"class":111},[98,1108,1109],{"class":133}," 'vue'",[98,1111,149],{"class":129},[98,1113,1114],{"class":100,"line":126},[98,1115,225],{"emptyLinePlaceholder":224},[98,1117,1118,1121,1124,1127,1130,1132,1135,1138,1141,1144,1146],{"class":100,"line":143},[98,1119,1120],{"class":111},"const",[98,1122,1123],{"class":419}," user",[98,1125,1126],{"class":111}," =",[98,1128,1129],{"class":118}," ref",[98,1131,410],{"class":129},[98,1133,1134],{"class":122},"User",[98,1136,1137],{"class":111}," |",[98,1139,1140],{"class":419}," null",[98,1142,1143],{"class":129},">(",[98,1145,380],{"class":419},[98,1147,1148],{"class":129},");\n",[98,1150,1151],{"class":100,"line":228},[98,1152,225],{"emptyLinePlaceholder":224},[98,1154,1155,1157,1160,1162],{"class":100,"line":238},[98,1156,1120],{"class":111},[98,1158,1159],{"class":419}," SAMPLE_USER",[98,1161,1126],{"class":111},[98,1163,235],{"class":129},[98,1165,1166,1169,1172],{"class":100,"line":258},[98,1167,1168],{"class":129},"  name: ",[98,1170,1171],{"class":133},"'Sarah Connor'",[98,1173,140],{"class":129},[98,1175,1176,1179,1182],{"class":100,"line":492},[98,1177,1178],{"class":129},"  role: ",[98,1180,1181],{"class":133},"'Chief Mitigation Officer'",[98,1183,140],{"class":129},[98,1185,1186,1189,1192],{"class":100,"line":497},[98,1187,1188],{"class":129},"  avatar: ",[98,1190,1191],{"class":133},"'https:\u002F\u002Fexample.com\u002Favatar.jpg'",[98,1193,140],{"class":129},[98,1195,1196],{"class":100,"line":1003},[98,1197,1198],{"class":129},"};\n",[98,1200,1201],{"class":100,"line":1014},[98,1202,225],{"emptyLinePlaceholder":224},[98,1204,1205,1208,1211,1214,1217,1220],{"class":100,"line":1023},[98,1206,1207],{"class":118},"onMounted",[98,1209,1210],{"class":129},"(",[98,1212,1213],{"class":111},"async",[98,1215,1216],{"class":129}," () ",[98,1218,1219],{"class":111},"=>",[98,1221,235],{"class":129},[98,1223,1224,1227,1229,1232,1235,1237,1240],{"class":100,"line":1028},[98,1225,1226],{"class":129},"  user.value ",[98,1228,422],{"class":111},[98,1230,1231],{"class":111}," await",[98,1233,1234],{"class":118}," $fetch",[98,1236,1210],{"class":129},[98,1238,1239],{"class":133},"'\u002Fapi\u002Fme'",[98,1241,1148],{"class":129},[98,1243,1244],{"class":100,"line":1034},[98,1245,1246],{"class":129},"});\n",[98,1248,1250,1252,1254],{"class":100,"line":1249},15,[98,1251,443],{"class":129},[98,1253,1084],{"class":413},[98,1255,433],{"class":129},[98,1257,1259],{"class":100,"line":1258},16,[98,1260,225],{"emptyLinePlaceholder":224},[98,1262,1264,1266,1268],{"class":100,"line":1263},17,[98,1265,410],{"class":129},[98,1267,670],{"class":413},[98,1269,433],{"class":129},[98,1271,1273,1275],{"class":100,"line":1272},18,[98,1274,683],{"class":129},[98,1276,943],{"class":413},[98,1278,1280,1283,1285],{"class":100,"line":1279},19,[98,1281,1282],{"class":419},"    mode",[98,1284,422],{"class":129},[98,1286,953],{"class":133},[98,1288,1290,1293,1295],{"class":100,"line":1289},20,[98,1291,1292],{"class":419},"    :theme",[98,1294,422],{"class":129},[98,1296,1297],{"class":133},"\"{\n",[98,1299,1301],{"class":100,"line":1300},21,[98,1302,1303],{"class":133},"      light: { base: '#d1d4dc', highlight: '#ffffff' },\n",[98,1305,1307],{"class":100,"line":1306},22,[98,1308,1309],{"class":133},"      dark: { base: '#31363f', highlight: 'rgba(255,255,255,0.08)' },\n",[98,1311,1313],{"class":100,"line":1312},23,[98,1314,1315],{"class":133},"      radius: '6px',\n",[98,1317,1319],{"class":100,"line":1318},24,[98,1320,1321],{"class":133},"    }\"\n",[98,1323,1325],{"class":100,"line":1324},25,[98,1326,1327],{"class":129},"  >\n",[98,1329,1331,1334,1336,1338,1340,1342,1345,1347,1350,1353,1355,1358],{"class":100,"line":1330},26,[98,1332,1333],{"class":129},"    \u003C",[98,1335,44],{"class":413},[98,1337,584],{"class":419},[98,1339,422],{"class":129},[98,1341,589],{"class":133},[98,1343,1344],{"class":419}," :data",[98,1346,422],{"class":129},[98,1348,1349],{"class":133},"\"user\"",[98,1351,1352],{"class":419}," :sample",[98,1354,422],{"class":129},[98,1356,1357],{"class":133},"\"SAMPLE_USER\"",[98,1359,433],{"class":129},[98,1361,1363,1366,1368,1370,1372,1374,1376,1378,1380],{"class":100,"line":1362},27,[98,1364,1365],{"class":129},"      \u003C",[98,1367,670],{"class":413},[98,1369,673],{"class":129},[98,1371,676],{"class":419},[98,1373,422],{"class":129},[98,1375,425],{"class":129},[98,1377,626],{"class":129},[98,1379,425],{"class":129},[98,1381,433],{"class":129},[98,1383,1385,1388,1391,1394,1396,1399],{"class":100,"line":1384},28,[98,1386,1387],{"class":129},"        \u003C",[98,1389,1390],{"class":413},"UserCard",[98,1392,1393],{"class":419}," :user",[98,1395,422],{"class":129},[98,1397,1398],{"class":133},"\"data\"",[98,1400,697],{"class":129},[98,1402,1404,1407,1409],{"class":100,"line":1403},29,[98,1405,1406],{"class":129},"      \u003C\u002F",[98,1408,670],{"class":413},[98,1410,433],{"class":129},[98,1412,1414,1417,1419],{"class":100,"line":1413},30,[98,1415,1416],{"class":129},"    \u003C\u002F",[98,1418,44],{"class":413},[98,1420,433],{"class":129},[98,1422,1424,1427,1429],{"class":100,"line":1423},31,[98,1425,1426],{"class":129},"  \u003C\u002F",[98,1428,1039],{"class":413},[98,1430,433],{"class":129},[98,1432,1434,1436,1438],{"class":100,"line":1433},32,[98,1435,443],{"class":129},[98,1437,670],{"class":413},[98,1439,433],{"class":129},[21,1441,1442,1443,1446,1447,1072],{},"A product card driven by ",[14,1444,1445],{},":data"," + ",[14,1448,1449],{},":sample",[1451,1452],"demo-overview-tile",{},[73,1454,1456],{"id":1455},"state-machine","State machine",[21,1458,1459,1460,1463,1464,1463,1467,1463,1470,1072],{},"One component resolves four mutually-exclusive states. Resolution order is ",[14,1461,1462],{},"loading"," → ",[14,1465,1466],{},"error",[14,1468,1469],{},"empty",[14,1471,1472],{},"content",[89,1474,1476],{"className":396,"code":1475,"language":398,"meta":94,"style":94},"\u003CAGhostSkeleton\n  :data=\"posts\"\n  :sample=\"SAMPLE_POSTS\"\n  :error=\"fetchError\"\n  :empty=\"posts?.length === 0\"\n  @reveal=\"onContentRevealed\"\n>\n  \u003Ctemplate #default=\"{ data }\">\n    \u003CPostList :posts=\"data\" \u002F>\n  \u003C\u002Ftemplate>\n  \u003Ctemplate #empty>\n    \u003CEmptyIllustration message=\"No posts yet\" \u002F>\n  \u003C\u002Ftemplate>\n  \u003Ctemplate #error=\"{ error }\">\n    \u003CErrorBanner :error=\"error\" @retry=\"reload\" \u002F>\n  \u003C\u002Ftemplate>\n\u003C\u002FAGhostSkeleton>\n",[14,1477,1478,1485,1500,1515,1530,1554,1571,1575,1580,1585,1590,1595,1600,1604,1609,1614,1618],{"__ignoreMap":94},[98,1479,1480,1482],{"class":100,"line":101},[98,1481,410],{"class":129},[98,1483,1484],{"class":413},"AGhostSkeleton\n",[98,1486,1487,1489,1491,1493,1495,1498],{"class":100,"line":108},[98,1488,958],{"class":129},[98,1490,376],{"class":419},[98,1492,422],{"class":129},[98,1494,425],{"class":129},[98,1496,1497],{"class":129},"posts",[98,1499,1020],{"class":129},[98,1501,1502,1504,1506,1508,1510,1513],{"class":100,"line":126},[98,1503,958],{"class":129},[98,1505,60],{"class":419},[98,1507,422],{"class":129},[98,1509,425],{"class":129},[98,1511,1512],{"class":419},"SAMPLE_POSTS",[98,1514,1020],{"class":129},[98,1516,1517,1519,1521,1523,1525,1528],{"class":100,"line":143},[98,1518,958],{"class":129},[98,1520,1466],{"class":419},[98,1522,422],{"class":129},[98,1524,425],{"class":129},[98,1526,1527],{"class":129},"fetchError",[98,1529,1020],{"class":129},[98,1531,1532,1534,1536,1538,1540,1543,1546,1549,1552],{"class":100,"line":228},[98,1533,958],{"class":129},[98,1535,1469],{"class":419},[98,1537,422],{"class":129},[98,1539,425],{"class":129},[98,1541,1542],{"class":129},"posts?.",[98,1544,1545],{"class":419},"length",[98,1547,1548],{"class":111}," ===",[98,1550,1551],{"class":419}," 0",[98,1553,1020],{"class":129},[98,1555,1556,1559,1562,1564,1566,1569],{"class":100,"line":238},[98,1557,1558],{"class":129},"  @",[98,1560,1561],{"class":419},"reveal",[98,1563,422],{"class":129},[98,1565,425],{"class":129},[98,1567,1568],{"class":129},"onContentRevealed",[98,1570,1020],{"class":129},[98,1572,1573],{"class":100,"line":258},[98,1574,433],{"class":129},[98,1576,1577],{"class":100,"line":492},[98,1578,1579],{"class":129},"  \u003Ctemplate #default=\"{ data }\">\n",[98,1581,1582],{"class":100,"line":497},[98,1583,1584],{"class":129},"    \u003CPostList :posts=\"data\" \u002F>\n",[98,1586,1587],{"class":100,"line":1003},[98,1588,1589],{"class":129},"  \u003C\u002Ftemplate>\n",[98,1591,1592],{"class":100,"line":1014},[98,1593,1594],{"class":129},"  \u003Ctemplate #empty>\n",[98,1596,1597],{"class":100,"line":1023},[98,1598,1599],{"class":129},"    \u003CEmptyIllustration message=\"No posts yet\" \u002F>\n",[98,1601,1602],{"class":100,"line":1028},[98,1603,1589],{"class":129},[98,1605,1606],{"class":100,"line":1034},[98,1607,1608],{"class":129},"  \u003Ctemplate #error=\"{ error }\">\n",[98,1610,1611],{"class":100,"line":1249},[98,1612,1613],{"class":129},"    \u003CErrorBanner :error=\"error\" @retry=\"reload\" \u002F>\n",[98,1615,1616],{"class":100,"line":1258},[98,1617,1589],{"class":129},[98,1619,1620,1622,1624],{"class":100,"line":1263},[98,1621,443],{"class":129},[98,1623,44],{"class":413},[98,1625,433],{"class":129},[36,1627,1629],{"title":1628,"type":267},"When does the skeleton activate?",[21,1630,1631,1632,1634,1635,1638,1639,53,1641,1644,1645,1647,1648,1651,1652,1654,1655,71],{},"Only when ",[14,1633,1445],{}," is passed as a bound prop ",[25,1636,1637],{},"and"," its value is ",[14,1640,380],{},[14,1642,1643],{},"undefined",", or when ",[14,1646,1462],{}," is explicitly ",[14,1649,1650],{},"true",". Passing nothing (no ",[14,1653,1445],{}," prop at all) treats the slot as always-rendered content — the escape hatch is ",[14,1656,1462],{},[36,1658,1660],{"title":1659,"type":39},"Prefer `data` + `sample` over `loading`",[21,1661,1662,1663,1665,1666,1668,1669,1671],{},"The ",[14,1664,1462],{}," prop is an escape hatch for state you can't model as \"data is ",[14,1667,380],{},"\". Default to binding ",[14,1670,1445],{}," and let the skeleton auto-activate — you get shape memory, the ghost measurement, and the reveal transitions for free.",[21,1673,1674,1677,1678,1681],{},[14,1675,1676],{},"@reveal"," fires once per ",[14,1679,1680],{},"skeleton → content"," transition. It does not fire on error \u002F empty transitions or on subsequent re-renders.",[1683,1684],"demo-overview-states",{},[73,1686,1688],{"id":1687},"reveal-transitions","Reveal transitions",[21,1690,1662,1691,1693,1694,1696,1697,1699],{},[14,1692,1561],{}," prop picks how the skeleton gives way to real content. Set it on ",[14,1695,272],{}," to override one skeleton, or on ",[14,1698,287],{}," as the app-wide default.",[1701,1702,1703,1716],"table",{},[1704,1705,1706],"thead",{},[1707,1708,1709,1713],"tr",{},[1710,1711,1712],"th",{},"Mode",[1710,1714,1715],{},"Behaviour",[1717,1718,1719,1730,1740,1750,1760],"tbody",{},[1707,1720,1721,1727],{},[1722,1723,1724],"td",{},[14,1725,1726],{},"smart",[1722,1728,1729],{},"Instant if content lands under ~150 ms, otherwise a crossfade. The default.",[1707,1731,1732,1737],{},[1722,1733,1734],{},[14,1735,1736],{},"together",[1722,1738,1739],{},"A single crossfade. Recommended for lists — per-piece staggers read as noise there.",[1707,1741,1742,1747],{},[1722,1743,1744],{},[14,1745,1746],{},"sequence",[1722,1748,1749],{},"Top-to-bottom cascade across pieces.",[1707,1751,1752,1757],{},[1722,1753,1754],{},[14,1755,1756],{},"sweep",[1722,1758,1759],{},"A highlight beam traverses the transition edge. Reads best on wide cards.",[1707,1761,1762,1767],{},[1722,1763,1764],{},[14,1765,1766],{},"instant",[1722,1768,1769],{},"Snap with no crossfade. The height ease still runs.",[36,1771,1774],{"title":1772,"type":1773},"Reduced motion wins","warning",[21,1775,1776,1777,1780,1781,1783,1784,1786],{},"When the user has ",[14,1778,1779],{},"(prefers-reduced-motion: reduce)",", the reveal is forced to ",[14,1782,1766],{}," and the shimmer freezes. Your chosen ",[14,1785,1561],{}," prop is a preference, not a guarantee.",[21,1788,1789],{},"Every option above the \"Motion\" control in the playground below is wired to the provider in real time. The \"Mode\" row tracks the docs' own theme toggle, so flipping the site to dark re-tints the entire demo — including the chrome bones.",[21,1791,1792,1793,1796,1797,1799,1800,1803,1804,1806],{},"::alert{type=\"note\" title=\"",[14,1794,1795],{},"reveal=\\\"together\\\""," on lists\"}\nThe default ",[14,1798,1726],{}," picks ",[14,1801,1802],{},"byRow"," for lists with more than a few pieces, which stacks a per-card cascade on top of the pane fade and the height ease — three animations fighting each other. ",[14,1805,1736],{}," collapses the list entry into one crossfade that lands with the resize.\n::",[1808,1809],"demo-overview-chart",{},[1811,1812],"demo-overview-distribution",{},[81,1814,1816],{"id":1815},"custom-reveals","Custom reveals",[21,1818,1819,1820,1822,1823,1826,1827,1830,1831,1062,1833,1062,1835,1062,1837,1062,1839,1062,1841,1062,1843,1062,1845,1062,1848,1851,1852,71],{},"For one-off needs, ",[14,1821,1561],{}," also accepts a ",[14,1824,1825],{},"RevealSpec"," object: ",[14,1828,1829],{},"{ order, enter, wipe, delay, duration, hold, choose }",". The built-in modes are exported as helpers (",[14,1832,1736],{},[14,1834,1746],{},[14,1836,1726],{},[14,1838,1756],{},[14,1840,1766],{},[14,1842,1802],{},[14,1844,349],{},[14,1846,1847],{},"byContent",[14,1849,1850],{},"quickly",") if you want to compose on top of them — see ",[67,1853,1855],{"href":1854},"#timing--helpers","Timing & helpers",[73,1857,1859],{"id":1858},"layout-hints","Layout hints",[21,1861,1862],{},"The DOM walker is accurate by default. Three attributes let you override its decisions where it matters.",[1701,1864,1865,1881],{},[1704,1866,1867],{},[1707,1868,1869,1872,1878],{},[1710,1870,1871],{},"Hint",[1710,1873,1874,1877],{},[14,1875,1876],{},"data-*"," alias",[1710,1879,1880],{},"Effect",[1717,1882,1883,1902,1921],{},[1707,1884,1885,1890,1895],{},[1722,1886,1887],{},[14,1888,1889],{},"ask-block",[1722,1891,1892],{},[14,1893,1894],{},"data-skeleton-block",[1722,1896,1897,1898,1901],{},"Draws the element as ",[25,1899,1900],{},"one"," bone sized to its box + border-radius. The walker does not recurse. Use for action buttons where the icon + count should read as one pill.",[1707,1903,1904,1909,1914],{},[1722,1905,1906],{},[14,1907,1908],{},"ask-ignore",[1722,1910,1911],{},[14,1912,1913],{},"data-skeleton-ignore",[1722,1915,1916,1917,1920],{},"Keeps the layout footprint but emits ",[25,1918,1919],{},"zero"," bones. Use for decorative dots, badges, or teleported modal shells that shouldn't appear in the ghost tree.",[1707,1922,1923,1928,1933],{},[1722,1924,1925],{},[14,1926,1927],{},"ask-own",[1722,1929,1930],{},[14,1931,1932],{},"data-skeleton-own",[1722,1934,1935],{},"The subtree opts out of measurement — you're drawing its own skeleton. The walker stops at this boundary.",[89,1937,1939],{"className":396,"code":1938,"language":398,"meta":94,"style":94},"\u003Carticle>\n  \u003CHeader \u002F>\n\n  \u003C!-- icon + count collapse to a single pill bone -->\n  \u003Cbutton type=\"button\" data-ask-block class=\"rounded-full\">\n    \u003CHeartIcon \u002F> {{ count }}\n  \u003C\u002Fbutton>\n\n  \u003C!-- decorative dot: leaves the layout slot, no bone -->\n  \u003Cspan data-ask-ignore class=\"status-dot\" \u002F>\n\u003C\u002Farticle>\n",[14,1940,1941,1950,1955,1959,1964,1969,1974,1979,1983,1988,1993],{"__ignoreMap":94},[98,1942,1943,1945,1948],{"class":100,"line":101},[98,1944,410],{"class":129},[98,1946,1947],{"class":413},"article",[98,1949,433],{"class":129},[98,1951,1952],{"class":100,"line":108},[98,1953,1954],{"class":129},"  \u003CHeader \u002F>\n",[98,1956,1957],{"class":100,"line":126},[98,1958,225],{"emptyLinePlaceholder":224},[98,1960,1961],{"class":100,"line":143},[98,1962,1963],{"class":129},"  \u003C!-- icon + count collapse to a single pill bone -->\n",[98,1965,1966],{"class":100,"line":228},[98,1967,1968],{"class":129},"  \u003Cbutton type=\"button\" data-ask-block class=\"rounded-full\">\n",[98,1970,1971],{"class":100,"line":238},[98,1972,1973],{"class":129},"    \u003CHeartIcon \u002F> {{ count }}\n",[98,1975,1976],{"class":100,"line":258},[98,1977,1978],{"class":129},"  \u003C\u002Fbutton>\n",[98,1980,1981],{"class":100,"line":492},[98,1982,225],{"emptyLinePlaceholder":224},[98,1984,1985],{"class":100,"line":497},[98,1986,1987],{"class":129},"  \u003C!-- decorative dot: leaves the layout slot, no bone -->\n",[98,1989,1990],{"class":100,"line":1003},[98,1991,1992],{"class":129},"  \u003Cspan data-ask-ignore class=\"status-dot\" \u002F>\n",[98,1994,1995,1997,1999],{"class":100,"line":1014},[98,1996,443],{"class":129},[98,1998,1947],{"class":413},[98,2000,433],{"class":129},[36,2002,2004],{"title":2003,"type":39},"`ask-own` + `#skeleton` slot",[21,2005,2006,2007,2010,2011,2013,2014,2016,2017,2019,2020,2023],{},"If you pass your own skeleton via the ",[14,2008,2009],{},"#skeleton"," slot on ",[14,2012,272],{},", measurement is skipped entirely — no need to annotate it with ",[14,2015,1927],{},". ",[14,2018,1927],{}," is only for carving a hand-authored island ",[25,2021,2022],{},"inside"," a measured tree.",[36,2025,2028],{"title":2026,"type":2027},"`v-if`-gate teleported modals inside the ghost tree","danger",[21,2029,2030,2031,775,2034,2037,2038,2041],{},"Dialogs with ",[14,2032,2033],{},"\u003CTeleport to=\"body\">",[14,2035,2036],{},"\u003CClientOnly>"," roots render children inline at their declared location until they move to the target on hydration — the walker measures that inline shell and emits ghost bones for it. Wrap them in ",[14,2039,2040],{},"v-if=\"open\""," so they don't exist in the DOM until needed.",[2043,2044],"demo-skeleton-hints",{},[73,2046,2048],{"id":2047},"resizing-between-skeleton-and-content","Resizing between skeleton and content",[21,2050,2051,2052,2054],{},"A skeleton drawn from ",[14,2053,60],{}," data or remembered shape is a guess. When the real data arrives with a different body length, image count, or line wrap, the frame around the swap doesn't snap — it eases from the outgoing pane's measured box to the incoming pane's live box.",[314,2056,2057,2065],{},[317,2058,2059,2064],{},[25,2060,2061],{},[14,2062,2063],{},"RESIZE_DURATION"," = 260 ms",[317,2066,2067,2072,2073,2076],{},[25,2068,2069],{},[14,2070,2071],{},"REVEAL_EASING"," = ",[14,2074,2075],{},"cubic-bezier(0.32, 0.72, 0, 1)"," (Apple's SF Pro curve)",[21,2078,2079],{},"A card that goes from 200 px to 600 px, or the other way, never jerks the viewer's eye.",[36,2081,2083],{"title":2082,"type":1773},"Match sample height to real height",[21,2084,2085,2086,2089,2090,2092],{},"The plugin warns ",[14,2087,2088],{},"layout jumped on reveal"," when the real data differs from the measured sample by more than 1 px. Fix by making the ",[14,2091,60],{}," shape mimic the real response — same number of text lines, same avatar size — not by silencing the warning.",[2094,2095],"demo-skeleton-resizing",{},[81,2097,2099],{"id":2098},"timings-at-a-glance","Timings at a glance",[1701,2101,2102,2115],{},[1704,2103,2104],{},[1707,2105,2106,2109,2112],{},[1710,2107,2108],{},"Constant",[1710,2110,2111],{},"Default",[1710,2113,2114],{},"What it drives",[1717,2116,2117,2130,2143,2158],{},[1707,2118,2119,2124,2127],{},[1722,2120,2121],{},[14,2122,2123],{},"FADE_DURATION",[1722,2125,2126],{},"260 ms",[1722,2128,2129],{},"Content pane fade-in — ends on the same frame as the resize.",[1707,2131,2132,2137,2140],{},[1722,2133,2134],{},[14,2135,2136],{},"SKELETON_FADE_DURATION",[1722,2138,2139],{},"160 ms",[1722,2141,2142],{},"Skeleton pane fade-out — shorter so bones clear while the frame is still settling.",[1707,2144,2145,2149,2151],{},[1722,2146,2147],{},[14,2148,2063],{},[1722,2150,2126],{},[1722,2152,2153,2154,2157],{},"Height ease on the ",[14,2155,2156],{},"[ask-reveal]"," container and the outgoing pane's lockstep shrink.",[1707,2159,2160,2164,2168],{},[1722,2161,2162],{},[14,2163,2071],{},[1722,2165,2166],{},[14,2167,2075],{},[1722,2169,2170],{},"Shared curve for every reveal animation.",[21,2172,2173,2174,2176],{},"All four are exported from ",[14,2175,16],{}," so a consumer can match their own animations to the skeleton's rhythm.",[81,2178,2180],{"id":2179},"how-the-resize-is-wired","How the resize is wired",[2182,2183,2184,2194,2197,2214,2220],"ol",{},[317,2185,2186,2187,2190,2191,71],{},"The outgoing pane is taken out of flow (",[14,2188,2189],{},"position: absolute"," at its measured box) via ",[14,2192,2193],{},"fadeOut()",[317,2195,2196],{},"The parent momentarily lays out at the incoming pane's natural height — that reading is the resize target.",[317,2198,2199,2200,2202,2203,1062,2206,2209,2210,2213],{},"A Web Animation on the parent's ",[14,2201,774],{}," interpolates from the outgoing box's height to the incoming pane's live height. ",[14,2204,2205],{},"overflow: clip",[14,2207,2208],{},"will-change: height",", and ",[14,2211,2212],{},"contain: layout"," are applied inline so the browser promotes the element onto its own compositor layer.",[317,2215,2216,2217,2219],{},"In lockstep, when the outgoing pane was taller than the incoming one, a second animation runs on the outgoing pane's own ",[14,2218,774],{}," with the same duration and easing, clipping its bones so nothing is painted below where the real content settles.",[317,2221,2222,2223,2225],{},"The skeleton's fade (",[14,2224,2136],{},", 160 ms) finishes before the resize settles — the viewer's eye isn't fighting a fading skeleton on top of content that's already laid out.",[36,2227,2229,2295],{"title":2228,"type":267},"`easeHeight()` for custom code paths",[89,2230,2232],{"className":91,"code":2231,"language":93,"meta":94,"style":94},"import { easeHeight } from '@alikhalilll\u002Fa-ghost-skeleton';\n\nconst from = panel.getBoundingClientRect().height;\npanel.style.height = '480px';\neaseHeight(panel, from, 480);\n",[14,2233,2234,2248,2252,2270,2282],{"__ignoreMap":94},[98,2235,2236,2238,2241,2243,2246],{"class":100,"line":101},[98,2237,175],{"class":111},[98,2239,2240],{"class":129}," { easeHeight } ",[98,2242,200],{"class":111},[98,2244,2245],{"class":133}," '@alikhalilll\u002Fa-ghost-skeleton'",[98,2247,149],{"class":129},[98,2249,2250],{"class":100,"line":108},[98,2251,225],{"emptyLinePlaceholder":224},[98,2253,2254,2256,2259,2261,2264,2267],{"class":100,"line":126},[98,2255,1120],{"class":111},[98,2257,2258],{"class":419}," from",[98,2260,1126],{"class":111},[98,2262,2263],{"class":129}," panel.",[98,2265,2266],{"class":118},"getBoundingClientRect",[98,2268,2269],{"class":129},"().height;\n",[98,2271,2272,2275,2277,2280],{"class":100,"line":143},[98,2273,2274],{"class":129},"panel.style.height ",[98,2276,422],{"class":111},[98,2278,2279],{"class":133}," '480px'",[98,2281,149],{"class":129},[98,2283,2284,2287,2290,2293],{"class":100,"line":228},[98,2285,2286],{"class":118},"easeHeight",[98,2288,2289],{"class":129},"(panel, from, ",[98,2291,2292],{"class":419},"480",[98,2294,1148],{"class":129},[21,2296,2297,2298,2301],{},"The height ease runs with ",[14,2299,2300],{},"prefers-reduced-motion: reduce"," honoured automatically — reduced-motion visitors see a snap.",[73,2303,2305],{"id":2304},"synchronized-shimmer","Synchronized shimmer",[21,2307,2308],{},"Six cards, each mounted a beat after the last, every bone sharing the same document-clock sweep. Nothing resets, nothing pops in out of phase. The same pattern scales to paginated feeds, async grid cells, staggered data fetches.",[2310,2311],"demo-skeleton-shimmer-sync",{},[73,2313,2315],{"id":2314},"direction-aware-animations","Direction-aware animations",[2317,2318],"demo-skeleton-direction",{},[21,2320,2321,2322,2324,2325,2328,2329,2332],{},"Every directional animation in the skeleton reads the inherited CSS ",[14,2323,353],{}," and flips to match. Set ",[14,2326,2327],{},"\u003Chtml dir=\"rtl\">"," once — or scope it with ",[14,2330,2331],{},"style=\"direction: rtl\""," on any ancestor — and three things flip together:",[314,2334,2335,2341,2347],{},[317,2336,2337,2340],{},[25,2338,2339],{},"Shimmer"," — the sweep across each bone travels right-to-left instead of left-to-right. Every bone in a group stays in phase; the shared stream is preserved.",[317,2342,2343,2346],{},[25,2344,2345],{},"Sweep reveal"," — the content-wipe front enters from the right edge and crosses to the left, with its trailing gloss band staying behind the front in motion direction.",[317,2348,2349,2354,2355,2357],{},[25,2350,2351,2353],{},[14,2352,1746],{}," cascade"," — the horizontal component of ",[14,2356,349],{}," reads right-to-left, so a top-to-bottom cascade tilts in reading order rather than always running toward the right.",[21,2359,2360,2361,2363,2364,2367],{},"There is no prop, no new CSS variable, and no provider setting. The reason: the browser already owns writing direction through ",[14,2362,353],{}," and ",[14,2365,2366],{},"dir",", every other UI library you use is reading the same signal, and adding a parallel knob would just drift from it.",[89,2369,2373],{"className":2370,"code":2371,"language":2372,"meta":94,"style":94},"language-html shiki shiki-themes github-light-default github-dark-default","\u003C!-- An entire page in RTL: shimmer, sweep, and sequence cascade all follow. -->\n\u003Chtml dir=\"rtl\">\n  \u003Cbody>\n    \u003CAGhostSkeleton :data=\"profile\" :sample=\"SAMPLE_PROFILE\">\n      \u003CProfileCard :profile=\"profile\" \u002F>\n    \u003C\u002FAGhostSkeleton>\n  \u003C\u002Fbody>\n\u003C\u002Fhtml>\n","html",[14,2374,2375,2380,2396,2405,2428,2444,2452,2460],{"__ignoreMap":94},[98,2376,2377],{"class":100,"line":101},[98,2378,2379],{"class":104},"\u003C!-- An entire page in RTL: shimmer, sweep, and sequence cascade all follow. -->\n",[98,2381,2382,2384,2386,2389,2391,2394],{"class":100,"line":108},[98,2383,410],{"class":129},[98,2385,2372],{"class":413},[98,2387,2388],{"class":419}," dir",[98,2390,422],{"class":129},[98,2392,2393],{"class":133},"\"rtl\"",[98,2395,433],{"class":129},[98,2397,2398,2400,2403],{"class":100,"line":126},[98,2399,683],{"class":129},[98,2401,2402],{"class":413},"body",[98,2404,433],{"class":129},[98,2406,2407,2409,2412,2414,2416,2419,2421,2423,2426],{"class":100,"line":143},[98,2408,1333],{"class":129},[98,2410,44],{"class":2411},"sZcZs",[98,2413,1344],{"class":419},[98,2415,422],{"class":129},[98,2417,2418],{"class":133},"\"profile\"",[98,2420,1352],{"class":419},[98,2422,422],{"class":129},[98,2424,2425],{"class":133},"\"SAMPLE_PROFILE\"",[98,2427,433],{"class":129},[98,2429,2430,2432,2435,2438,2440,2442],{"class":100,"line":228},[98,2431,1365],{"class":129},[98,2433,2434],{"class":2411},"ProfileCard",[98,2436,2437],{"class":419}," :profile",[98,2439,422],{"class":129},[98,2441,2418],{"class":133},[98,2443,697],{"class":129},[98,2445,2446,2448,2450],{"class":100,"line":238},[98,2447,1416],{"class":129},[98,2449,44],{"class":2411},[98,2451,433],{"class":129},[98,2453,2454,2456,2458],{"class":100,"line":258},[98,2455,1426],{"class":129},[98,2457,2402],{"class":413},[98,2459,433],{"class":129},[98,2461,2462,2464,2466],{"class":100,"line":492},[98,2463,443],{"class":129},[98,2465,2372],{"class":413},[98,2467,433],{"class":129},[89,2469,2471],{"className":396,"code":2470,"language":398,"meta":94,"style":94},"\u003C!-- Or scope it to one subtree, e.g. a localised comment thread. -->\n\u003Csection dir=\"rtl\">\n  \u003CAGhostSkeleton :data=\"thread\" :sample=\"SAMPLE_THREAD\">\n    \u003CCommentThread :thread=\"thread\" \u002F>\n  \u003C\u002FAGhostSkeleton>\n\u003C\u002Fsection>\n",[14,2472,2473,2478,2493,2498,2503,2508],{"__ignoreMap":94},[98,2474,2475],{"class":100,"line":101},[98,2476,2477],{"class":104},"\u003C!-- Or scope it to one subtree, e.g. a localised comment thread. -->\n",[98,2479,2480,2482,2485,2487,2489,2491],{"class":100,"line":108},[98,2481,410],{"class":129},[98,2483,2484],{"class":413},"section",[98,2486,2388],{"class":419},[98,2488,422],{"class":129},[98,2490,2393],{"class":133},[98,2492,433],{"class":129},[98,2494,2495],{"class":100,"line":126},[98,2496,2497],{"class":129},"  \u003CAGhostSkeleton :data=\"thread\" :sample=\"SAMPLE_THREAD\">\n",[98,2499,2500],{"class":100,"line":143},[98,2501,2502],{"class":129},"    \u003CCommentThread :thread=\"thread\" \u002F>\n",[98,2504,2505],{"class":100,"line":228},[98,2506,2507],{"class":129},"  \u003C\u002FAGhostSkeleton>\n",[98,2509,2510,2512,2514],{"class":100,"line":238},[98,2511,443],{"class":129},[98,2513,2484],{"class":413},[98,2515,433],{"class":129},[36,2517,2519],{"title":2518,"type":39},"What stays unchanged",[21,2520,2521,2524,2525,2527],{},[14,2522,2523],{},"pulse"," is an opacity fade — non-directional, so it looks identical in LTR and RTL. The content fades, the height-ease between panes, and the ",[14,2526,1802],{}," sequence order are purely vertical or non-spatial, so they don't flip. The gradient's 20° slant is kept as-is in RTL (the motion direction flips, the band's visual slant doesn't) because mirroring it crosses from \"noticeable\" into \"sub-threshold\" at that angle and would double the geometry the sweep has to reason about.",[73,2529,2531],{"id":2530},"chrome-capture","Chrome capture",[21,2533,2534,2535,2538,2539,2542,2543,2546,2547,1062,2550,2209,2553,2556],{},"When the walker crosses a ",[25,2536,2537],{},"painted container"," — anything with a background, a border, or a box-shadow — it emits an extra ",[14,2540,2541],{},"chrome"," bone that reproduces that paint verbatim. The bone carries the captured ",[14,2544,2545],{},"background",", per-side ",[14,2548,2549],{},"border-*",[14,2551,2552],{},"border-radius",[14,2554,2555],{},"box-shadow"," inline, and skips the shimmer animation so it reads as an outline, not a placeholder fill.",[21,2558,2559,2560,2563],{},"This is why cards look right from the first frame: a ",[14,2561,2562],{},"border-t"," footer divider survives as a hairline, and the card's radius is preserved even when the outer wrapper clips it.",[21,2565,2566],{},"What chrome capture tracks:",[314,2568,2569,2579,2582,2591],{},[317,2570,2571,2574,2575,2578],{},[14,2572,2573],{},"backgroundColor"," and gradient ",[14,2576,2577],{},"backgroundImage"," layers",[317,2580,2581],{},"Four border sides captured separately — a one-sided border reads as a divider, not a box",[317,2583,2584,2586,2587,2590],{},[14,2585,2552],{},", per-corner when the parent's ",[14,2588,2589],{},"overflow"," clips it",[317,2592,2593],{},[14,2594,2555],{},[21,2596,2597,2598,2601,2602,2605],{},"Chrome bones ignore ",[14,2599,2600],{},"--ask-base"," (they aren't placeholders) and carry ",[14,2603,2604],{},"[ask-rect=\"chrome\"]"," so stylesheets can target them separately.",[36,2607,2609],{"title":2608,"type":1773},"`url(…)` backgrounds are stripped",[21,2610,2611,2612,2614,2615,2618],{},"Bitmap ",[14,2613,2577],{}," layers (",[14,2616,2617],{},"url('\u002Fhero.jpg')",") are filtered out so the skeleton doesn't re-download them. Gradient layers come through as normal. If your card's \"background\" is a hero bitmap, the skeleton will show the solid fallback colour where the image would have been — which is almost always what you want.",[73,2620,1048],{"id":2621},"theming",[21,2623,2624],{},"Everything is driven by CSS custom properties. A single declaration anywhere above the skeleton re-tints every bone inside.",[89,2626,2630],{"className":2627,"code":2628,"language":2629,"meta":94,"style":94},"language-css shiki shiki-themes github-light-default github-dark-default",".my-feed {\n  --ask-base: #d1d4dc;\n  --ask-highlight: #ffffff;\n  --ask-radius: 6px;\n}\n","css",[14,2631,2632,2639,2652,2664,2679],{"__ignoreMap":94},[98,2633,2634,2637],{"class":100,"line":101},[98,2635,2636],{"class":419},".my-feed",[98,2638,235],{"class":129},[98,2640,2641,2644,2647,2650],{"class":100,"line":108},[98,2642,2643],{"class":122},"  --ask-base",[98,2645,2646],{"class":129},": ",[98,2648,2649],{"class":419},"#d1d4dc",[98,2651,149],{"class":129},[98,2653,2654,2657,2659,2662],{"class":100,"line":126},[98,2655,2656],{"class":122},"  --ask-highlight",[98,2658,2646],{"class":129},[98,2660,2661],{"class":419},"#ffffff",[98,2663,149],{"class":129},[98,2665,2666,2669,2671,2674,2677],{"class":100,"line":143},[98,2667,2668],{"class":122},"  --ask-radius",[98,2670,2646],{"class":129},[98,2672,2673],{"class":419},"6",[98,2675,2676],{"class":111},"px",[98,2678,149],{"class":129},[98,2680,2681],{"class":100,"line":228},[98,2682,2683],{"class":129},"}\n",[21,2685,2686,2687,2689,2690,2692,2693,1072],{},"For app-wide defaults, wrap your app in ",[14,2688,287],{},". The provider supports ",[14,2691,872],{}," which reads ",[14,2694,876],{},[89,2696,2698],{"className":396,"code":2697,"language":398,"meta":94,"style":94},"\u003CAGhostSkeletonProvider\n  mode=\"system\"\n  :theme=\"{\n    light: { base: '#d1d4dc', highlight: '#ffffff' },\n    dark: { base: '#31363f', highlight: 'rgba(255,255,255,0.08)' },\n    radius: '6px',\n    animation: 'shimmer',\n    speed: 'slow',\n  }\"\n  reveal=\"smart\"\n>\n  \u003CApp \u002F>\n\u003C\u002FAGhostSkeletonProvider>\n",[14,2699,2700,2706,2714,2726,2738,2750,2758,2768,2778,2784,2794,2798,2803],{"__ignoreMap":94},[98,2701,2702,2704],{"class":100,"line":101},[98,2703,410],{"class":129},[98,2705,943],{"class":413},[98,2707,2708,2710,2712],{"class":100,"line":108},[98,2709,948],{"class":419},[98,2711,422],{"class":129},[98,2713,953],{"class":133},[98,2715,2716,2718,2720,2722,2724],{"class":100,"line":126},[98,2717,958],{"class":129},[98,2719,961],{"class":419},[98,2721,422],{"class":129},[98,2723,425],{"class":129},[98,2725,968],{"class":129},[98,2727,2728,2730,2732,2734,2736],{"class":100,"line":143},[98,2729,973],{"class":129},[98,2731,976],{"class":133},[98,2733,979],{"class":129},[98,2735,982],{"class":133},[98,2737,985],{"class":129},[98,2739,2740,2742,2744,2746,2748],{"class":100,"line":228},[98,2741,990],{"class":129},[98,2743,993],{"class":133},[98,2745,979],{"class":129},[98,2747,998],{"class":133},[98,2749,985],{"class":129},[98,2751,2752,2754,2756],{"class":100,"line":238},[98,2753,1006],{"class":129},[98,2755,1009],{"class":133},[98,2757,140],{"class":129},[98,2759,2760,2763,2766],{"class":100,"line":258},[98,2761,2762],{"class":129},"    animation: ",[98,2764,2765],{"class":133},"'shimmer'",[98,2767,140],{"class":129},[98,2769,2770,2773,2776],{"class":100,"line":492},[98,2771,2772],{"class":129},"    speed: ",[98,2774,2775],{"class":133},"'slow'",[98,2777,140],{"class":129},[98,2779,2780,2782],{"class":100,"line":497},[98,2781,1017],{"class":129},[98,2783,1020],{"class":129},[98,2785,2786,2789,2791],{"class":100,"line":1003},[98,2787,2788],{"class":419},"  reveal",[98,2790,422],{"class":129},[98,2792,2793],{"class":133},"\"smart\"\n",[98,2795,2796],{"class":100,"line":1014},[98,2797,433],{"class":129},[98,2799,2800],{"class":100,"line":1023},[98,2801,2802],{"class":129},"  \u003CApp \u002F>\n",[98,2804,2805,2807,2809],{"class":100,"line":1028},[98,2806,443],{"class":129},[98,2808,1039],{"class":413},[98,2810,433],{"class":129},[36,2812,2814],{"title":2813,"type":267},"Light and dark are the same component tree",[21,2815,2816,2817,2819,2820,2823,2824,2827,2828,2831],{},"The provider doesn't fork its slot into two renders. It flips the ",[14,2818,880],{}," variables based on ",[14,2821,2822],{},"mode"," and lets the cascade do the rest — which is why chrome bones also re-tint when you toggle the site theme, because they inherit from ",[14,2825,2826],{},"\u003Carticle>","'s computed ",[14,2829,2830],{},"background-color"," at measurement time.",[36,2833,2835],{"title":2834,"type":39},"Chrome bones ≠ bone fill",[21,2836,2837,2839,2840,2842],{},[14,2838,2600],{}," re-tints placeholder bones only. A card's outline keeps whatever colour the real ",[14,2841,2826],{}," had — that's chrome capture working as intended, reproducing real paint rather than re-colouring it.",[81,2844,2846],{"id":2845},"css-variables","CSS variables",[1701,2848,2849,2861],{},[1704,2850,2851],{},[1707,2852,2853,2856,2858],{},[1710,2854,2855],{},"Variable",[1710,2857,2111],{},[1710,2859,2860],{},"Description",[1717,2862,2863,2876,2890,2908,2932,2951,2966],{},[1707,2864,2865,2869,2873],{},[1722,2866,2867],{},[14,2868,2600],{},[1722,2870,2871],{},[14,2872,861],{},[1722,2874,2875],{},"Fill of placeholder bones. Chrome bones ignore this.",[1707,2877,2878,2883,2887],{},[1722,2879,2880],{},[14,2881,2882],{},"--ask-highlight",[1722,2884,2885],{},[14,2886,865],{},[1722,2888,2889],{},"Shimmer sweep colour.",[1707,2891,2892,2897,2903],{},[1722,2893,2894],{},[14,2895,2896],{},"--ask-radius",[1722,2898,2899,2902],{},[14,2900,2901],{},"0px"," (text bars pill by default)",[1722,2904,2905,2906,71],{},"Border-radius on text bars and ",[14,2907,64],{},[1707,2909,2910,2915,2920],{},[1722,2911,2912],{},[14,2913,2914],{},"--ask-animation",[1722,2916,2917],{},[14,2918,2919],{},"shimmer",[1722,2921,2922,53,2924,53,2927,53,2929,71],{},[14,2923,2919],{},[14,2925,2926],{},"group-shimmer",[14,2928,2523],{},[14,2930,2931],{},"none",[1707,2933,2934,2939,2944],{},[1722,2935,2936],{},[14,2937,2938],{},"--ask-speed",[1722,2940,2941],{},[14,2942,2943],{},"slow",[1722,2945,2946,53,2948,71],{},[14,2947,2943],{},[14,2949,2950],{},"fast",[1707,2952,2953,2958,2963],{},[1722,2954,2955],{},[14,2956,2957],{},"--ask-text-top",[1722,2959,2960],{},[14,2961,2962],{},"ascender",[1722,2964,2965],{},"Which font line each text bar starts at.",[1707,2967,2968,2973,2978],{},[1722,2969,2970],{},[14,2971,2972],{},"--ask-text-bottom",[1722,2974,2975],{},[14,2976,2977],{},"descender",[1722,2979,2980],{},"Which font line each text bar ends at.",[36,2982,2984],{"title":2983,"type":39},"Two layers of defaults",[21,2985,2986,2987,2989,2990,2993,2994,2997,2998,3001,3002,71],{},"Without a provider, the raw CSS fallbacks are the translucent greys shown above — they read on both light and dark pages. Wrap in ",[14,2988,287],{}," and the provider's own ",[14,2991,2992],{},"DEFAULT_COLORS"," (light ",[14,2995,2996],{},"rgb(0 0 0 \u002F 0.07)",", dark ",[14,2999,3000],{},"rgb(255 255 255 \u002F 0.08)",") win, keyed off ",[14,3003,2822],{},[81,3005,3007],{"id":3006},"per-type-bone-styling","Per-type bone styling",[21,3009,3010,3011,3014,3015,3018],{},"Bones ship as ",[14,3012,3013],{},"\u003Cdiv [ask-rect=\"text|media|box|chrome\"]>"," in the light DOM (no shadow root), so your stylesheet reaches them without ",[14,3016,3017],{},":deep()",". A 4-px minimum radius is applied to every non-chrome bone so nothing reads as a sharp glyph.",[89,3020,3022],{"className":2627,"code":3021,"language":2629,"meta":94,"style":94},"\u002F* Soft inset ring on placeholder bones. *\u002F\n[ask-rect='text'],\n[ask-rect='box'] {\n  box-shadow: inset 0 0 0 1px rgb(169 175 188 \u002F 0.35);\n}\n",[14,3023,3024,3029,3045,3059,3101],{"__ignoreMap":94},[98,3025,3026],{"class":100,"line":101},[98,3027,3028],{"class":104},"\u002F* Soft inset ring on placeholder bones. *\u002F\n",[98,3030,3031,3034,3037,3039,3042],{"class":100,"line":108},[98,3032,3033],{"class":129},"[",[98,3035,3036],{"class":419},"ask-rect",[98,3038,422],{"class":111},[98,3040,3041],{"class":133},"'text'",[98,3043,3044],{"class":129},"],\n",[98,3046,3047,3049,3051,3053,3056],{"class":100,"line":126},[98,3048,3033],{"class":129},[98,3050,3036],{"class":419},[98,3052,422],{"class":111},[98,3054,3055],{"class":133},"'box'",[98,3057,3058],{"class":129},"] {\n",[98,3060,3061,3064,3066,3069,3071,3073,3075,3078,3080,3083,3085,3088,3091,3094,3096,3099],{"class":100,"line":143},[98,3062,3063],{"class":419},"  box-shadow",[98,3065,2646],{"class":129},[98,3067,3068],{"class":419},"inset",[98,3070,1551],{"class":419},[98,3072,1551],{"class":419},[98,3074,1551],{"class":419},[98,3076,3077],{"class":419}," 1",[98,3079,2676],{"class":111},[98,3081,3082],{"class":419}," rgb",[98,3084,1210],{"class":129},[98,3086,3087],{"class":419},"169",[98,3089,3090],{"class":419}," 175",[98,3092,3093],{"class":419}," 188",[98,3095,53],{"class":129},[98,3097,3098],{"class":419},"0.35",[98,3100,1148],{"class":129},[98,3102,3103],{"class":100,"line":228},[98,3104,2683],{"class":129},[1701,3106,3107,3120],{},[1704,3108,3109],{},[1707,3110,3111,3117],{},[1710,3112,3113,3116],{},[14,3114,3115],{},"[ask-rect]"," value",[1710,3118,3119],{},"Emitted by",[1717,3121,3122,3135,3161,3180],{},[1707,3123,3124,3129],{},[1722,3125,3126],{},[14,3127,3128],{},"text",[1722,3130,3131,3132],{},"Text-node per-line bars via ",[14,3133,3134],{},"Range.getClientRects()",[1707,3136,3137,3142],{},[1722,3138,3139],{},[14,3140,3141],{},"media",[1722,3143,3144,53,3146,53,3149,53,3152,53,3155,53,3158],{},[14,3145,767],{},[14,3147,3148],{},"\u003Csvg>",[14,3150,3151],{},"\u003Cvideo>",[14,3153,3154],{},"\u003Ccanvas>",[14,3156,3157],{},"\u003Cpicture>",[14,3159,3160],{},"\u003Ciframe>",[1707,3162,3163,3168],{},[1722,3164,3165],{},[14,3166,3167],{},"box",[1722,3169,3170,53,3173,3176,3177],{},[14,3171,3172],{},"\u003Cbutton>",[14,3174,3175],{},"\u003Cinput>"," \u002F painted leaf elements \u002F anything with ",[14,3178,3179],{},"data-ask-block",[1707,3181,3182,3186],{},[1722,3183,3184],{},[14,3185,2541],{},[1722,3187,3188,3189,53,3191,53,3193,3195],{},"Painted or divider-bordered container — carries captured ",[14,3190,2545],{},[14,3192,2549],{},[14,3194,2555],{}," inline",[73,3197,3199,3201],{"id":3198},"aghostskeletonbox-standalone-bars-standalone-box",[14,3200,64],{}," — standalone bars {#standalone-box}",[21,3203,3204,3205,3207],{},"Use ",[14,3206,64],{}," when you need an explicit placeholder outside the measurement path — a loading indicator that doesn't wrap a component, an inline progress strip, or a composite skeleton you're hand-authoring.",[89,3209,3211],{"className":396,"code":3210,"language":398,"meta":94,"style":94},"\u003Cdiv class=\"flex items-center gap-3\">\n  \u003CAGhostSkeletonBox width=\"40px\" height=\"40px\" radius=\"999px\" \u002F>\n  \u003Cdiv class=\"flex-1 flex flex-col gap-1.5\">\n    \u003CAGhostSkeletonBox width=\"60%\" height=\"1rem\" radius=\"4px\" \u002F>\n    \u003CAGhostSkeletonBox width=\"40%\" height=\"0.75rem\" radius=\"4px\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\n",[14,3212,3213,3229,3234,3239,3244,3249,3257],{"__ignoreMap":94},[98,3214,3215,3217,3220,3222,3224,3227],{"class":100,"line":101},[98,3216,410],{"class":129},[98,3218,3219],{"class":413},"div",[98,3221,842],{"class":419},[98,3223,422],{"class":129},[98,3225,3226],{"class":133},"\"flex items-center gap-3\"",[98,3228,433],{"class":129},[98,3230,3231],{"class":100,"line":108},[98,3232,3233],{"class":129},"  \u003CAGhostSkeletonBox width=\"40px\" height=\"40px\" radius=\"999px\" \u002F>\n",[98,3235,3236],{"class":100,"line":126},[98,3237,3238],{"class":129},"  \u003Cdiv class=\"flex-1 flex flex-col gap-1.5\">\n",[98,3240,3241],{"class":100,"line":143},[98,3242,3243],{"class":129},"    \u003CAGhostSkeletonBox width=\"60%\" height=\"1rem\" radius=\"4px\" \u002F>\n",[98,3245,3246],{"class":100,"line":228},[98,3247,3248],{"class":129},"    \u003CAGhostSkeletonBox width=\"40%\" height=\"0.75rem\" radius=\"4px\" \u002F>\n",[98,3250,3251,3253,3255],{"class":100,"line":238},[98,3252,1426],{"class":129},[98,3254,3219],{"class":413},[98,3256,433],{"class":129},[98,3258,3259,3261,3263],{"class":100,"line":258},[98,3260,443],{"class":129},[98,3262,3219],{"class":413},[98,3264,433],{"class":129},[21,3266,3267,3268,3270],{},"It shares the document-clock shimmer, respects the provider, and honours the ",[14,3269,880],{}," variables.",[73,3272,3274,3276],{"id":3273},"aghostskeletonsuspense-for-suspense-boundaries",[14,3275,279],{}," — for Suspense boundaries",[21,3278,3279,3280,3282,3283,3285,3286,3289,3290,3293,3294,3297],{},"A thin wrapper around Vue's ",[14,3281,283],{}," that measures its fallback like any other ",[14,3284,272],{},". Use it when your loading surface is driven by an ",[14,3287,3288],{},"async setup()"," \u002F top-level ",[14,3291,3292],{},"await"," rather than a ",[14,3295,3296],{},"null → value"," transition.",[89,3299,3301],{"className":396,"code":3300,"language":398,"meta":94,"style":94},"\u003CAGhostSkeletonSuspense id=\"profile\" label=\"Loading profile\">\n  \u003Ctemplate #default>\n    \u003CAsyncProfile \u002F>\n  \u003C\u002Ftemplate>\n  \u003Ctemplate #skeleton>\n    \u003CProfilePlaceholder \u002F>\n  \u003C\u002Ftemplate>\n\u003C\u002FAGhostSkeletonSuspense>\n",[14,3302,3303,3326,3331,3336,3340,3345,3350,3354],{"__ignoreMap":94},[98,3304,3305,3307,3310,3312,3314,3316,3319,3321,3324],{"class":100,"line":101},[98,3306,410],{"class":129},[98,3308,3309],{"class":413},"AGhostSkeletonSuspense",[98,3311,584],{"class":419},[98,3313,422],{"class":129},[98,3315,2418],{"class":133},[98,3317,3318],{"class":419}," label",[98,3320,422],{"class":129},[98,3322,3323],{"class":133},"\"Loading profile\"",[98,3325,433],{"class":129},[98,3327,3328],{"class":100,"line":108},[98,3329,3330],{"class":129},"  \u003Ctemplate #default>\n",[98,3332,3333],{"class":100,"line":126},[98,3334,3335],{"class":129},"    \u003CAsyncProfile \u002F>\n",[98,3337,3338],{"class":100,"line":143},[98,3339,1589],{"class":129},[98,3341,3342],{"class":100,"line":228},[98,3343,3344],{"class":129},"  \u003Ctemplate #skeleton>\n",[98,3346,3347],{"class":100,"line":238},[98,3348,3349],{"class":129},"    \u003CProfilePlaceholder \u002F>\n",[98,3351,3352],{"class":100,"line":258},[98,3353,1589],{"class":129},[98,3355,3356,3358,3360],{"class":100,"line":492},[98,3357,443],{"class":129},[98,3359,3309],{"class":413},[98,3361,433],{"class":129},[73,3363,3365],{"id":3364},"accessibility","Accessibility",[314,3367,3368,3374,3387,3397,3404],{},[317,3369,3370,3373],{},[14,3371,3372],{},"aria-busy=\"true\""," is set on the outer wrapper while loading.",[317,3375,1662,3376,3379,3380,3383,3384,3386],{},[14,3377,3378],{},"label"," prop renders as visually hidden text inside an ",[14,3381,3382],{},"[ask-status]"," element — screen readers hear ",[14,3385,3378],{}," instead of silence.",[317,3388,3389,3390,2363,3393,3396],{},"Skeleton panes are ",[14,3391,3392],{},"aria-hidden=\"true\"",[14,3394,3395],{},"inert",", so assistive tech doesn't try to announce empty shapes.",[317,3398,3399,3401,3402,71],{},[14,3400,1779],{}," disables the shimmer and collapses the reveal to ",[14,3403,1766],{},[317,3405,3406,3407,3409,3410,3412,3413,3415,3416,3418],{},"The inherited CSS ",[14,3408,353],{}," is read at runtime, so a ",[14,3411,2327],{}," page (or any ",[14,3414,2366],{},"-scoped subtree) flips the shimmer sweep, the content reveal, and the ",[14,3417,1746],{}," cascade without any extra wiring — the skeleton reads the same writing-direction signal as the rest of the page.",[89,3420,3422],{"className":396,"code":3421,"language":398,"meta":94,"style":94},"\u003CAGhostSkeleton :data=\"profile\" :sample=\"SAMPLE_PROFILE\" label=\"Loading your profile\">\n  ...\n\u003C\u002FAGhostSkeleton>\n",[14,3423,3424,3465,3470],{"__ignoreMap":94},[98,3425,3426,3428,3430,3432,3434,3436,3438,3441,3443,3445,3447,3449,3451,3454,3456,3458,3460,3463],{"class":100,"line":101},[98,3427,410],{"class":129},[98,3429,44],{"class":413},[98,3431,416],{"class":129},[98,3433,376],{"class":419},[98,3435,422],{"class":129},[98,3437,425],{"class":129},[98,3439,3440],{"class":129},"profile",[98,3442,425],{"class":129},[98,3444,416],{"class":129},[98,3446,60],{"class":419},[98,3448,422],{"class":129},[98,3450,425],{"class":129},[98,3452,3453],{"class":419},"SAMPLE_PROFILE",[98,3455,425],{"class":129},[98,3457,3318],{"class":419},[98,3459,422],{"class":129},[98,3461,3462],{"class":133},"\"Loading your profile\"",[98,3464,433],{"class":129},[98,3466,3467],{"class":100,"line":108},[98,3468,3469],{"class":129},"  ...\n",[98,3471,3472,3474,3476],{"class":100,"line":126},[98,3473,443],{"class":129},[98,3475,44],{"class":413},[98,3477,433],{"class":129},[73,3479,3481],{"id":3480},"debugging-a-wrong-looking-skeleton","Debugging a wrong-looking skeleton",[21,3483,3484,3485,3488,3489,71],{},"If a measured skeleton doesn't line up with the real card — bones in the wrong places, padding missing, cards too narrow — turn on the built-in trace. The plugin ships a ",[14,3486,3487],{},"traceMeasurement()"," logger that fires once per element the walker touches, so you can see exactly what the DOM looked like ",[25,3490,3491],{},"at measurement time",[81,3493,3495],{"id":3494},"enable-it","Enable it",[21,3497,3498],{},"Any one of these flips the plugin into debug mode:",[314,3500,3501,3508,3515,3522],{},[317,3502,3503,3504,3507],{},"Add ",[14,3505,3506],{},"?ask-debug"," to the URL.",[317,3509,3510,3511,3514],{},"Run ",[14,3512,3513],{},"localStorage.setItem('a-ghost-skeleton:debug', '1')"," in DevTools, then reload.",[317,3516,3517,3518,3521],{},"Call ",[14,3519,3520],{},"setDebug(true)"," once from your app code.",[317,3523,3524,3525,3528,3529,3531],{},"Add an ",[14,3526,3527],{},"ask-debug"," attribute to any ancestor of the ",[14,3530,272],{}," you're investigating (scopes the trace to that subtree).",[81,3533,3535],{"id":3534},"reading-the-trace","Reading the trace",[21,3537,3538,3539,3541,3542,3544],{},"Open DevTools and trigger a skeleton render (cold refresh, sort change, anything that puts ",[14,3540,1445],{}," back to ",[14,3543,380],{},"). The console fills with lines like:",[89,3546,3550],{"className":3547,"code":3549,"language":3128},[3548],"language-text","[a-ghost-skeleton] \u003Cheader> 456×60  padding:4px 20px 16px 20px\n{ class: 'flex gap-3 items-start px-5 pb-4 pt-4', element: \u003Cheader…> }\n\n[a-ghost-skeleton] \u003Cdiv> 420×38  padding:0px 0px 0px 0px  · ⚠ 0-padding\n{ class: 'flex flex-col', element: \u003Cdiv…> }\n",[14,3551,3549],{"__ignoreMap":94},[21,3553,3554,3555,3558],{},"Each line is one element's measured box with its class list, computed padding, and width × height. The ",[14,3556,3557],{},"⚠ 0-padding"," marker appears on containers that have children but no inner padding — the common signal that something went wrong between what you wrote and what the browser rendered.",[21,3560,3561],{},"Pick the element you care about (usually one that should have padding but doesn't) and check three things:",[1701,3563,3564,3577],{},[1704,3565,3566],{},[1707,3567,3568,3571,3574],{},[1710,3569,3570],{},"What you see",[1710,3572,3573],{},"What it means",[1710,3575,3576],{},"Fix",[1717,3578,3579,3599,3618,3642],{},[1707,3580,3581,3590,3596],{},[1722,3582,3583,3584,45,3587,3589],{},"Expected class in ",[14,3585,3586],{},"class:",[25,3588,1637],{}," padding is non-zero",[1722,3591,3592,3593,3595],{},"Everything's fine. The visual problem is elsewhere (CSS specificity, parent ",[14,3594,2589],{},", a wrapper collapsing margins).",[1722,3597,3598],{},"Look upstream.",[1707,3600,3601,3612,3615],{},[1722,3602,3583,3603,45,3605,3608,3609],{},[14,3604,3586],{},[25,3606,3607],{},"but"," padding is ",[14,3610,3611],{},"0px 0px…",[1722,3613,3614],{},"The class reached the DOM but your CSS didn't emit the rule. Classic UnoCSS \u002F Tailwind lazy-scan miss — the utility isn't in the output bundle.",[1722,3616,3617],{},"Add the utility to your scanner's safelist, or widen the source globs so the component is covered.",[1707,3619,3620,3628,3631],{},[1722,3621,3622,3623,627,3626],{},"Expected class ",[25,3624,3625],{},"not",[14,3627,3586],{},[1722,3629,3630],{},"Vue dropped it. Happens when a child component has a true fragment root (multiple top-level elements). Vue can't auto-forward the class into a fragment.",[1722,3632,3633,3634,3637,3638,3641],{},"Collapse to a single root with ",[14,3635,3636],{},":class"," branching, or ",[14,3639,3640],{},"defineOptions({ inheritAttrs: false })"," + manual.",[1707,3643,3644,3649,3652],{},[1722,3645,3646,3648],{},[14,3647,3586],{}," is correct, padding is right in the real card, wrong only in the skeleton trace",[1722,3650,3651],{},"The ghost tree rendered before an async style settled (fonts, lazy CSS modules).",[1722,3653,3654,3655,3657],{},"Preload the font \u002F stylesheet, or set an ",[14,3656,778],{}," so the first-paint measurement is correct.",[36,3659,3661],{"title":3660,"type":1773},"Debug is for dev only",[21,3662,3663,3664,3666,3667,3670],{},"The trace is noisy by design and runs synchronously per element. Don't ship it enabled — either gate ",[14,3665,3520],{}," behind ",[14,3668,3669],{},"import.meta.dev"," or leave it off and use the URL \u002F localStorage switches when investigating.",[73,3672,1855],{"id":3673},"timing-helpers",[21,3675,3676,3677,3679,3680,3683],{},"Imported from ",[14,3678,16],{}," (or ",[14,3681,3682],{},"\u002Fcore","):",[1701,3685,3686,3699],{},[1704,3687,3688],{},[1707,3689,3690,3693,3696],{},[1710,3691,3692],{},"Export",[1710,3694,3695],{},"Signature \u002F value",[1710,3697,3698],{},"What it does",[1717,3700,3701,3715,3729,3742,3754,3772,3785,3800,3819,3831,3843],{},[1707,3702,3703,3707,3712],{},[1722,3704,3705],{},[14,3706,2123],{},[1722,3708,3709],{},[14,3710,3711],{},"260",[1722,3713,3714],{},"Content pane fade length.",[1707,3716,3717,3721,3726],{},[1722,3718,3719],{},[14,3720,2136],{},[1722,3722,3723],{},[14,3724,3725],{},"160",[1722,3727,3728],{},"Skeleton pane fade length (shorter — bones clear before the frame settles).",[1707,3730,3731,3735,3739],{},[1722,3732,3733],{},[14,3734,2063],{},[1722,3736,3737],{},[14,3738,3711],{},[1722,3740,3741],{},"Height ease length.",[1707,3743,3744,3748,3752],{},[1722,3745,3746],{},[14,3747,2071],{},[1722,3749,3750],{},[14,3751,2075],{},[1722,3753,2170],{},[1707,3755,3756,3761,3766],{},[1722,3757,3758],{},[14,3759,3760],{},"SKELETON_DELAY",[1722,3762,3763],{},[14,3764,3765],{},"150",[1722,3767,3768,3769,3771],{},"Minimum time a skeleton must be visible before ",[14,3770,1726],{}," swaps to a crossfade.",[1707,3773,3774,3779,3782],{},[1722,3775,3776],{},[14,3777,3778],{},"easeHeight(root, from, to)",[1722,3780,3781],{},"—",[1722,3783,3784],{},"Animate any element's height along the canonical curve. Reused internally by every pane swap.",[1707,3786,3787,3792,3797],{},[1722,3788,3789],{},[14,3790,3791],{},"prefersReducedMotion()",[1722,3793,3794],{},[14,3795,3796],{},"boolean",[1722,3798,3799],{},"Current reduced-motion preference.",[1707,3801,3802,3807,3809],{},[1722,3803,3804],{},[14,3805,3806],{},"forgetShapes(id?)",[1722,3808,3781],{},[1722,3810,3811,3812,3815,3816,3818],{},"Clear remembered shapes from ",[14,3813,3814],{},"localStorage",". Omit ",[14,3817,510],{}," to wipe all.",[1707,3820,3821,3826,3828],{},[1722,3822,3823],{},[14,3824,3825],{},"setDebug(on: boolean)",[1722,3827,3781],{},[1722,3829,3830],{},"Switch debug mode on or off globally.",[1707,3832,3833,3838,3840],{},[1722,3834,3835],{},[14,3836,3837],{},"traceMeasurement(el, …)",[1722,3839,3781],{},[1722,3841,3842],{},"Logs one element's class list, computed padding, and bounds. Called by the measure walker.",[1707,3844,3845,3850,3854],{},[1722,3846,3847],{},[14,3848,3849],{},"debugging(el?)",[1722,3851,3852],{},[14,3853,3796],{},[1722,3855,3856,3858,3859,3862,3863,3866],{},[14,3857,1650],{}," when the global flag is set, or when ",[14,3860,3861],{},"el"," has an ",[14,3864,3865],{},"[ask-debug]"," ancestor.",[73,3868,3870],{"id":3869},"recipes","Recipes",[21,3872,3873,3874,3877],{},"Six focused examples, derived from one realistic page — an analytics overview with a metrics row, a comparison chart, a distribution list, and a paginated table. They ",[25,3875,3876],{},"compose",": stack all six and you have the full page. Pick them apart and each one teaches a single pattern.",[21,3879,3880,3881,1062,3884,3887],{},"Nothing below is tied to a framework, chart library, or design system. Replace ",[14,3882,3883],{},"\u003CDataTable>",[14,3885,3886],{},"\u003CAreaChart>",", and the class names with whatever you use.",[81,3889,3891],{"id":3890},"_1-one-measured-tile","1. One measured tile",[21,3893,3894],{},"The smallest useful loader. One card, one data object, one measured skeleton.",[89,3896,3898],{"className":396,"code":3897,"language":398,"meta":94,"style":94},"\u003Cscript setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\n\ninterface Metric {\n  label: string;\n  value: number;\n  delta: number;\n}\n\nconst metric = ref\u003CMetric | null>(null);\nconst SAMPLE: Metric = { label: 'Visitors', value: 12_480, delta: 0.143 };\n\nonMounted(async () => {\n  metric.value = await $fetch('\u002Fapi\u002Fmetrics\u002Fvisitors');\n});\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CAGhostSkeleton id=\"metric-visitors\" :data=\"metric\" :sample=\"SAMPLE\">\n    \u003Ctemplate #default=\"{ data }\">\n      \u003Carticle class=\"card\">\n        \u003Cp class=\"label\">{{ data.label }}\u003C\u002Fp>\n        \u003Cp class=\"value\">{{ data.value.toLocaleString() }}\u003C\u002Fp>\n        \u003Cp class=\"delta\">{{ (data.delta * 100).toFixed(1) }}%\u003C\u002Fp>\n      \u003C\u002Farticle>\n    \u003C\u002Ftemplate>\n  \u003C\u002FAGhostSkeleton>\n\u003C\u002Ftemplate>\n",[14,3899,3900,3916,3928,3932,3942,3954,3966,3977,3981,3985,4011,4045,4049,4063,4081,4085,4093,4097,4105,4134,4154,4169,4189,4209,4229,4237,4245,4253],{"__ignoreMap":94},[98,3901,3902,3904,3906,3908,3910,3912,3914],{"class":100,"line":101},[98,3903,410],{"class":129},[98,3905,1084],{"class":413},[98,3907,1087],{"class":419},[98,3909,1090],{"class":419},[98,3911,422],{"class":129},[98,3913,1095],{"class":133},[98,3915,433],{"class":129},[98,3917,3918,3920,3922,3924,3926],{"class":100,"line":108},[98,3919,175],{"class":111},[98,3921,1104],{"class":129},[98,3923,200],{"class":111},[98,3925,1109],{"class":133},[98,3927,149],{"class":129},[98,3929,3930],{"class":100,"line":126},[98,3931,225],{"emptyLinePlaceholder":224},[98,3933,3934,3937,3940],{"class":100,"line":143},[98,3935,3936],{"class":111},"interface",[98,3938,3939],{"class":122}," Metric",[98,3941,235],{"class":129},[98,3943,3944,3947,3949,3952],{"class":100,"line":228},[98,3945,3946],{"class":122},"  label",[98,3948,1072],{"class":111},[98,3950,3951],{"class":419}," string",[98,3953,149],{"class":129},[98,3955,3956,3959,3961,3964],{"class":100,"line":238},[98,3957,3958],{"class":122},"  value",[98,3960,1072],{"class":111},[98,3962,3963],{"class":419}," number",[98,3965,149],{"class":129},[98,3967,3968,3971,3973,3975],{"class":100,"line":258},[98,3969,3970],{"class":122},"  delta",[98,3972,1072],{"class":111},[98,3974,3963],{"class":419},[98,3976,149],{"class":129},[98,3978,3979],{"class":100,"line":492},[98,3980,2683],{"class":129},[98,3982,3983],{"class":100,"line":497},[98,3984,225],{"emptyLinePlaceholder":224},[98,3986,3987,3989,3992,3994,3996,3998,4001,4003,4005,4007,4009],{"class":100,"line":1003},[98,3988,1120],{"class":111},[98,3990,3991],{"class":419}," metric",[98,3993,1126],{"class":111},[98,3995,1129],{"class":118},[98,3997,410],{"class":129},[98,3999,4000],{"class":122},"Metric",[98,4002,1137],{"class":111},[98,4004,1140],{"class":419},[98,4006,1143],{"class":129},[98,4008,380],{"class":419},[98,4010,1148],{"class":129},[98,4012,4013,4015,4018,4020,4022,4024,4027,4030,4033,4036,4039,4042],{"class":100,"line":1014},[98,4014,1120],{"class":111},[98,4016,4017],{"class":419}," SAMPLE",[98,4019,1072],{"class":111},[98,4021,3939],{"class":122},[98,4023,1126],{"class":111},[98,4025,4026],{"class":129}," { label: ",[98,4028,4029],{"class":133},"'Visitors'",[98,4031,4032],{"class":129},", value: ",[98,4034,4035],{"class":419},"12_480",[98,4037,4038],{"class":129},", delta: ",[98,4040,4041],{"class":419},"0.143",[98,4043,4044],{"class":129}," };\n",[98,4046,4047],{"class":100,"line":1023},[98,4048,225],{"emptyLinePlaceholder":224},[98,4050,4051,4053,4055,4057,4059,4061],{"class":100,"line":1028},[98,4052,1207],{"class":118},[98,4054,1210],{"class":129},[98,4056,1213],{"class":111},[98,4058,1216],{"class":129},[98,4060,1219],{"class":111},[98,4062,235],{"class":129},[98,4064,4065,4068,4070,4072,4074,4076,4079],{"class":100,"line":1034},[98,4066,4067],{"class":129},"  metric.value ",[98,4069,422],{"class":111},[98,4071,1231],{"class":111},[98,4073,1234],{"class":118},[98,4075,1210],{"class":129},[98,4077,4078],{"class":133},"'\u002Fapi\u002Fmetrics\u002Fvisitors'",[98,4080,1148],{"class":129},[98,4082,4083],{"class":100,"line":1249},[98,4084,1246],{"class":129},[98,4086,4087,4089,4091],{"class":100,"line":1258},[98,4088,443],{"class":129},[98,4090,1084],{"class":413},[98,4092,433],{"class":129},[98,4094,4095],{"class":100,"line":1263},[98,4096,225],{"emptyLinePlaceholder":224},[98,4098,4099,4101,4103],{"class":100,"line":1272},[98,4100,410],{"class":129},[98,4102,670],{"class":413},[98,4104,433],{"class":129},[98,4106,4107,4109,4111,4113,4115,4118,4120,4122,4125,4127,4129,4132],{"class":100,"line":1279},[98,4108,683],{"class":129},[98,4110,44],{"class":413},[98,4112,584],{"class":419},[98,4114,422],{"class":129},[98,4116,4117],{"class":133},"\"metric-visitors\"",[98,4119,1344],{"class":419},[98,4121,422],{"class":129},[98,4123,4124],{"class":133},"\"metric\"",[98,4126,1352],{"class":419},[98,4128,422],{"class":129},[98,4130,4131],{"class":133},"\"SAMPLE\"",[98,4133,433],{"class":129},[98,4135,4136,4138,4140,4142,4144,4146,4148,4150,4152],{"class":100,"line":1289},[98,4137,1333],{"class":129},[98,4139,670],{"class":413},[98,4141,673],{"class":129},[98,4143,676],{"class":419},[98,4145,422],{"class":129},[98,4147,425],{"class":129},[98,4149,626],{"class":129},[98,4151,425],{"class":129},[98,4153,433],{"class":129},[98,4155,4156,4158,4160,4162,4164,4167],{"class":100,"line":1300},[98,4157,1365],{"class":129},[98,4159,1947],{"class":413},[98,4161,842],{"class":419},[98,4163,422],{"class":129},[98,4165,4166],{"class":133},"\"card\"",[98,4168,433],{"class":129},[98,4170,4171,4173,4175,4177,4179,4182,4185,4187],{"class":100,"line":1306},[98,4172,1387],{"class":129},[98,4174,21],{"class":413},[98,4176,842],{"class":419},[98,4178,422],{"class":129},[98,4180,4181],{"class":133},"\"label\"",[98,4183,4184],{"class":129},">{{ data.label }}\u003C\u002F",[98,4186,21],{"class":413},[98,4188,433],{"class":129},[98,4190,4191,4193,4195,4197,4199,4202,4205,4207],{"class":100,"line":1312},[98,4192,1387],{"class":129},[98,4194,21],{"class":413},[98,4196,842],{"class":419},[98,4198,422],{"class":129},[98,4200,4201],{"class":133},"\"value\"",[98,4203,4204],{"class":129},">{{ data.value.toLocaleString() }}\u003C\u002F",[98,4206,21],{"class":413},[98,4208,433],{"class":129},[98,4210,4211,4213,4215,4217,4219,4222,4225,4227],{"class":100,"line":1318},[98,4212,1387],{"class":129},[98,4214,21],{"class":413},[98,4216,842],{"class":419},[98,4218,422],{"class":129},[98,4220,4221],{"class":133},"\"delta\"",[98,4223,4224],{"class":129},">{{ (data.delta * 100).toFixed(1) }}%\u003C\u002F",[98,4226,21],{"class":413},[98,4228,433],{"class":129},[98,4230,4231,4233,4235],{"class":100,"line":1324},[98,4232,1406],{"class":129},[98,4234,1947],{"class":413},[98,4236,433],{"class":129},[98,4238,4239,4241,4243],{"class":100,"line":1330},[98,4240,1416],{"class":129},[98,4242,670],{"class":413},[98,4244,433],{"class":129},[98,4246,4247,4249,4251],{"class":100,"line":1362},[98,4248,1426],{"class":129},[98,4250,44],{"class":413},[98,4252,433],{"class":129},[98,4254,4255,4257,4259],{"class":100,"line":1384},[98,4256,443],{"class":129},[98,4258,670],{"class":413},[98,4260,433],{"class":129},[21,4262,4263,4264,4266,4267,4269,4270,4272],{},"The three rules in one place: a stable ",[14,4265,510],{},", a ",[14,4268,60],{}," that mirrors the real response, a slot that destructures ",[14,4271,626],{}," so the sample reaches the card during measurement.",[81,4274,4276],{"id":4275},"_2-a-row-of-tiles-that-reveal-together","2. A row of tiles that reveal together",[21,4278,4279],{},"Wrap the whole grid in one skeleton so four cards fade in as a single unit instead of a stagger.",[89,4281,4283],{"className":396,"code":4282,"language":398,"meta":94,"style":94},"\u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue';\n\ninterface Overview {\n  metrics: Metric[];\n}\n\nconst overview = ref\u003COverview | null>(null);\nconst SAMPLE: Overview = {\n  metrics: [\n    { label: 'Visitors', value: 12_480, delta: 0.143 },\n    { label: 'Sessions', value: 18_206, delta: 0.101 },\n    { label: 'Page views', value: 41_372, delta: -0.06 },\n    { label: 'Engagement', value: 64.2, delta: 0.024 },\n  ],\n};\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CAGhostSkeleton id=\"metrics-row\" :data=\"overview\" :sample=\"SAMPLE\" reveal=\"together\">\n    \u003Ctemplate #default=\"{ data }\">\n      \u003Cdiv class=\"grid grid-cols-4 gap-4\">\n        \u003Carticle v-for=\"m in data.metrics\" :key=\"m.label\" class=\"card\">\n          \u003Cp>{{ m.label }}\u003C\u002Fp>\n          \u003Cp>{{ m.value.toLocaleString() }}\u003C\u002Fp>\n        \u003C\u002Farticle>\n      \u003C\u002Fdiv>\n    \u003C\u002Ftemplate>\n  \u003C\u002FAGhostSkeleton>\n\u003C\u002Ftemplate>\n",[14,4284,4285,4301,4314,4318,4327,4339,4343,4347,4373,4387,4392,4409,4428,4450,4469,4474,4478,4486,4490,4498,4534,4554,4569,4599,4613,4626,4635,4643,4651,4659],{"__ignoreMap":94},[98,4286,4287,4289,4291,4293,4295,4297,4299],{"class":100,"line":101},[98,4288,410],{"class":129},[98,4290,1084],{"class":413},[98,4292,1087],{"class":419},[98,4294,1090],{"class":419},[98,4296,422],{"class":129},[98,4298,1095],{"class":133},[98,4300,433],{"class":129},[98,4302,4303,4305,4308,4310,4312],{"class":100,"line":108},[98,4304,175],{"class":111},[98,4306,4307],{"class":129}," { ref } ",[98,4309,200],{"class":111},[98,4311,1109],{"class":133},[98,4313,149],{"class":129},[98,4315,4316],{"class":100,"line":126},[98,4317,225],{"emptyLinePlaceholder":224},[98,4319,4320,4322,4325],{"class":100,"line":143},[98,4321,3936],{"class":111},[98,4323,4324],{"class":122}," Overview",[98,4326,235],{"class":129},[98,4328,4329,4332,4334,4336],{"class":100,"line":228},[98,4330,4331],{"class":122},"  metrics",[98,4333,1072],{"class":111},[98,4335,3939],{"class":122},[98,4337,4338],{"class":129},"[];\n",[98,4340,4341],{"class":100,"line":238},[98,4342,2683],{"class":129},[98,4344,4345],{"class":100,"line":258},[98,4346,225],{"emptyLinePlaceholder":224},[98,4348,4349,4351,4354,4356,4358,4360,4363,4365,4367,4369,4371],{"class":100,"line":492},[98,4350,1120],{"class":111},[98,4352,4353],{"class":419}," overview",[98,4355,1126],{"class":111},[98,4357,1129],{"class":118},[98,4359,410],{"class":129},[98,4361,4362],{"class":122},"Overview",[98,4364,1137],{"class":111},[98,4366,1140],{"class":419},[98,4368,1143],{"class":129},[98,4370,380],{"class":419},[98,4372,1148],{"class":129},[98,4374,4375,4377,4379,4381,4383,4385],{"class":100,"line":497},[98,4376,1120],{"class":111},[98,4378,4017],{"class":419},[98,4380,1072],{"class":111},[98,4382,4324],{"class":122},[98,4384,1126],{"class":111},[98,4386,235],{"class":129},[98,4388,4389],{"class":100,"line":1003},[98,4390,4391],{"class":129},"  metrics: [\n",[98,4393,4394,4397,4399,4401,4403,4405,4407],{"class":100,"line":1014},[98,4395,4396],{"class":129},"    { label: ",[98,4398,4029],{"class":133},[98,4400,4032],{"class":129},[98,4402,4035],{"class":419},[98,4404,4038],{"class":129},[98,4406,4041],{"class":419},[98,4408,985],{"class":129},[98,4410,4411,4413,4416,4418,4421,4423,4426],{"class":100,"line":1023},[98,4412,4396],{"class":129},[98,4414,4415],{"class":133},"'Sessions'",[98,4417,4032],{"class":129},[98,4419,4420],{"class":419},"18_206",[98,4422,4038],{"class":129},[98,4424,4425],{"class":419},"0.101",[98,4427,985],{"class":129},[98,4429,4430,4432,4435,4437,4440,4442,4445,4448],{"class":100,"line":1028},[98,4431,4396],{"class":129},[98,4433,4434],{"class":133},"'Page views'",[98,4436,4032],{"class":129},[98,4438,4439],{"class":419},"41_372",[98,4441,4038],{"class":129},[98,4443,4444],{"class":111},"-",[98,4446,4447],{"class":419},"0.06",[98,4449,985],{"class":129},[98,4451,4452,4454,4457,4459,4462,4464,4467],{"class":100,"line":1034},[98,4453,4396],{"class":129},[98,4455,4456],{"class":133},"'Engagement'",[98,4458,4032],{"class":129},[98,4460,4461],{"class":419},"64.2",[98,4463,4038],{"class":129},[98,4465,4466],{"class":419},"0.024",[98,4468,985],{"class":129},[98,4470,4471],{"class":100,"line":1249},[98,4472,4473],{"class":129},"  ],\n",[98,4475,4476],{"class":100,"line":1258},[98,4477,1198],{"class":129},[98,4479,4480,4482,4484],{"class":100,"line":1263},[98,4481,443],{"class":129},[98,4483,1084],{"class":413},[98,4485,433],{"class":129},[98,4487,4488],{"class":100,"line":1272},[98,4489,225],{"emptyLinePlaceholder":224},[98,4491,4492,4494,4496],{"class":100,"line":1279},[98,4493,410],{"class":129},[98,4495,670],{"class":413},[98,4497,433],{"class":129},[98,4499,4500,4502,4504,4506,4508,4511,4513,4515,4518,4520,4522,4524,4527,4529,4532],{"class":100,"line":1289},[98,4501,683],{"class":129},[98,4503,44],{"class":413},[98,4505,584],{"class":419},[98,4507,422],{"class":129},[98,4509,4510],{"class":133},"\"metrics-row\"",[98,4512,1344],{"class":419},[98,4514,422],{"class":129},[98,4516,4517],{"class":133},"\"overview\"",[98,4519,1352],{"class":419},[98,4521,422],{"class":129},[98,4523,4131],{"class":133},[98,4525,4526],{"class":419}," reveal",[98,4528,422],{"class":129},[98,4530,4531],{"class":133},"\"together\"",[98,4533,433],{"class":129},[98,4535,4536,4538,4540,4542,4544,4546,4548,4550,4552],{"class":100,"line":1300},[98,4537,1333],{"class":129},[98,4539,670],{"class":413},[98,4541,673],{"class":129},[98,4543,676],{"class":419},[98,4545,422],{"class":129},[98,4547,425],{"class":129},[98,4549,626],{"class":129},[98,4551,425],{"class":129},[98,4553,433],{"class":129},[98,4555,4556,4558,4560,4562,4564,4567],{"class":100,"line":1306},[98,4557,1365],{"class":129},[98,4559,3219],{"class":413},[98,4561,842],{"class":419},[98,4563,422],{"class":129},[98,4565,4566],{"class":133},"\"grid grid-cols-4 gap-4\"",[98,4568,433],{"class":129},[98,4570,4571,4573,4575,4578,4580,4583,4586,4588,4591,4593,4595,4597],{"class":100,"line":1312},[98,4572,1387],{"class":129},[98,4574,1947],{"class":413},[98,4576,4577],{"class":419}," v-for",[98,4579,422],{"class":129},[98,4581,4582],{"class":133},"\"m in data.metrics\"",[98,4584,4585],{"class":419}," :key",[98,4587,422],{"class":129},[98,4589,4590],{"class":133},"\"m.label\"",[98,4592,842],{"class":419},[98,4594,422],{"class":129},[98,4596,4166],{"class":133},[98,4598,433],{"class":129},[98,4600,4601,4604,4606,4609,4611],{"class":100,"line":1318},[98,4602,4603],{"class":129},"          \u003C",[98,4605,21],{"class":413},[98,4607,4608],{"class":129},">{{ m.label }}\u003C\u002F",[98,4610,21],{"class":413},[98,4612,433],{"class":129},[98,4614,4615,4617,4619,4622,4624],{"class":100,"line":1324},[98,4616,4603],{"class":129},[98,4618,21],{"class":413},[98,4620,4621],{"class":129},">{{ m.value.toLocaleString() }}\u003C\u002F",[98,4623,21],{"class":413},[98,4625,433],{"class":129},[98,4627,4628,4631,4633],{"class":100,"line":1330},[98,4629,4630],{"class":129},"        \u003C\u002F",[98,4632,1947],{"class":413},[98,4634,433],{"class":129},[98,4636,4637,4639,4641],{"class":100,"line":1362},[98,4638,1406],{"class":129},[98,4640,3219],{"class":413},[98,4642,433],{"class":129},[98,4644,4645,4647,4649],{"class":100,"line":1384},[98,4646,1416],{"class":129},[98,4648,670],{"class":413},[98,4650,433],{"class":129},[98,4652,4653,4655,4657],{"class":100,"line":1403},[98,4654,1426],{"class":129},[98,4656,44],{"class":413},[98,4658,433],{"class":129},[98,4660,4661,4663,4665],{"class":100,"line":1413},[98,4662,443],{"class":129},[98,4664,670],{"class":413},[98,4666,433],{"class":129},[21,4668,4669,4670,4673,4674,4676],{},"Default ",[14,4671,4672],{},"reveal=\"smart\""," picks a per-card stagger for lists, which reads as noise on a tight grid. ",[14,4675,1736],{}," collapses four crossfades into one.",[81,4678,4680],{"id":4679},"_3-a-comparison-line-chart","3. A comparison line chart",[21,4682,4683,4684,4686,4687,4689,4690,4693],{},"Charts render out of SVG primitives that don't measure cleanly. Use the ",[14,4685,2009],{}," slot to opt out of measurement entirely, keep the chart under ",[14,4688,2036],{},", and reach for ",[14,4691,4692],{},"lineDashArray"," to distinguish overlaid series.",[89,4695,4697],{"className":396,"code":4696,"language":398,"meta":94,"style":94},"\u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue';\n\ninterface Point {\n  date: string;\n  current: number;\n  previous: number;\n}\n\nconst series = ref\u003CPoint[] | null>(null);\n\n\u002F\u002F First series solid, second series dashed — lineDashArray[i] applies per series.\nconst lineDashArray = [[], [4, 4]];\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CAGhostSkeleton id=\"comparison-chart\" :data=\"series\" :sample=\"[]\">\n    \u003Ctemplate #default>\n      \u003CClientOnly>\n        \u003CAreaChart\n          :data=\"series ?? []\"\n          :line-dash-array=\"lineDashArray\"\n          :height=\"288\"\n          :curve-type=\"'monotoneX'\"\n        \u002F>\n      \u003C\u002FClientOnly>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #skeleton>\n      \u003C!-- Hand-authored placeholder opts out of measurement. Size it to\n           match the real chart so the reveal doesn't shift. -->\n      \u003Cdiv class=\"h-72\" ask-block>\n        \u003CAGhostSkeletonBox width=\"100%\" height=\"100%\" radius=\"12px\" \u002F>\n      \u003C\u002Fdiv>\n    \u003C\u002Ftemplate>\n  \u003C\u002FAGhostSkeleton>\n\u003C\u002Ftemplate>\n",[14,4698,4699,4715,4727,4731,4740,4751,4762,4773,4777,4781,4811,4815,4820,4842,4850,4854,4862,4891,4903,4912,4919,4929,4939,4949,4959,4964,4972,4980,4984,4997,5002,5007,5025,5058,5067,5076,5085],{"__ignoreMap":94},[98,4700,4701,4703,4705,4707,4709,4711,4713],{"class":100,"line":101},[98,4702,410],{"class":129},[98,4704,1084],{"class":413},[98,4706,1087],{"class":419},[98,4708,1090],{"class":419},[98,4710,422],{"class":129},[98,4712,1095],{"class":133},[98,4714,433],{"class":129},[98,4716,4717,4719,4721,4723,4725],{"class":100,"line":108},[98,4718,175],{"class":111},[98,4720,4307],{"class":129},[98,4722,200],{"class":111},[98,4724,1109],{"class":133},[98,4726,149],{"class":129},[98,4728,4729],{"class":100,"line":126},[98,4730,225],{"emptyLinePlaceholder":224},[98,4732,4733,4735,4738],{"class":100,"line":143},[98,4734,3936],{"class":111},[98,4736,4737],{"class":122}," Point",[98,4739,235],{"class":129},[98,4741,4742,4745,4747,4749],{"class":100,"line":228},[98,4743,4744],{"class":122},"  date",[98,4746,1072],{"class":111},[98,4748,3951],{"class":419},[98,4750,149],{"class":129},[98,4752,4753,4756,4758,4760],{"class":100,"line":238},[98,4754,4755],{"class":122},"  current",[98,4757,1072],{"class":111},[98,4759,3963],{"class":419},[98,4761,149],{"class":129},[98,4763,4764,4767,4769,4771],{"class":100,"line":258},[98,4765,4766],{"class":122},"  previous",[98,4768,1072],{"class":111},[98,4770,3963],{"class":419},[98,4772,149],{"class":129},[98,4774,4775],{"class":100,"line":492},[98,4776,2683],{"class":129},[98,4778,4779],{"class":100,"line":497},[98,4780,225],{"emptyLinePlaceholder":224},[98,4782,4783,4785,4788,4790,4792,4794,4797,4800,4803,4805,4807,4809],{"class":100,"line":1003},[98,4784,1120],{"class":111},[98,4786,4787],{"class":419}," series",[98,4789,1126],{"class":111},[98,4791,1129],{"class":118},[98,4793,410],{"class":129},[98,4795,4796],{"class":122},"Point",[98,4798,4799],{"class":129},"[] ",[98,4801,4802],{"class":111},"|",[98,4804,1140],{"class":419},[98,4806,1143],{"class":129},[98,4808,380],{"class":419},[98,4810,1148],{"class":129},[98,4812,4813],{"class":100,"line":1014},[98,4814,225],{"emptyLinePlaceholder":224},[98,4816,4817],{"class":100,"line":1023},[98,4818,4819],{"class":104},"\u002F\u002F First series solid, second series dashed — lineDashArray[i] applies per series.\n",[98,4821,4822,4824,4827,4829,4832,4835,4837,4839],{"class":100,"line":1028},[98,4823,1120],{"class":111},[98,4825,4826],{"class":419}," lineDashArray",[98,4828,1126],{"class":111},[98,4830,4831],{"class":129}," [[], [",[98,4833,4834],{"class":419},"4",[98,4836,1062],{"class":129},[98,4838,4834],{"class":419},[98,4840,4841],{"class":129},"]];\n",[98,4843,4844,4846,4848],{"class":100,"line":1034},[98,4845,443],{"class":129},[98,4847,1084],{"class":413},[98,4849,433],{"class":129},[98,4851,4852],{"class":100,"line":1249},[98,4853,225],{"emptyLinePlaceholder":224},[98,4855,4856,4858,4860],{"class":100,"line":1258},[98,4857,410],{"class":129},[98,4859,670],{"class":413},[98,4861,433],{"class":129},[98,4863,4864,4866,4868,4870,4872,4875,4877,4879,4882,4884,4886,4889],{"class":100,"line":1263},[98,4865,683],{"class":129},[98,4867,44],{"class":413},[98,4869,584],{"class":419},[98,4871,422],{"class":129},[98,4873,4874],{"class":133},"\"comparison-chart\"",[98,4876,1344],{"class":419},[98,4878,422],{"class":129},[98,4880,4881],{"class":133},"\"series\"",[98,4883,1352],{"class":419},[98,4885,422],{"class":129},[98,4887,4888],{"class":133},"\"[]\"",[98,4890,433],{"class":129},[98,4892,4893,4895,4897,4899,4901],{"class":100,"line":1272},[98,4894,1333],{"class":129},[98,4896,670],{"class":413},[98,4898,673],{"class":129},[98,4900,676],{"class":419},[98,4902,433],{"class":129},[98,4904,4905,4907,4910],{"class":100,"line":1279},[98,4906,1365],{"class":129},[98,4908,4909],{"class":413},"ClientOnly",[98,4911,433],{"class":129},[98,4913,4914,4916],{"class":100,"line":1289},[98,4915,1387],{"class":129},[98,4917,4918],{"class":413},"AreaChart\n",[98,4920,4921,4924,4926],{"class":100,"line":1300},[98,4922,4923],{"class":419},"          :data",[98,4925,422],{"class":129},[98,4927,4928],{"class":133},"\"series ?? []\"\n",[98,4930,4931,4934,4936],{"class":100,"line":1306},[98,4932,4933],{"class":419},"          :line-dash-array",[98,4935,422],{"class":129},[98,4937,4938],{"class":133},"\"lineDashArray\"\n",[98,4940,4941,4944,4946],{"class":100,"line":1312},[98,4942,4943],{"class":419},"          :height",[98,4945,422],{"class":129},[98,4947,4948],{"class":133},"\"288\"\n",[98,4950,4951,4954,4956],{"class":100,"line":1318},[98,4952,4953],{"class":419},"          :curve-type",[98,4955,422],{"class":129},[98,4957,4958],{"class":133},"\"'monotoneX'\"\n",[98,4960,4961],{"class":100,"line":1324},[98,4962,4963],{"class":129},"        \u002F>\n",[98,4965,4966,4968,4970],{"class":100,"line":1330},[98,4967,1406],{"class":129},[98,4969,4909],{"class":413},[98,4971,433],{"class":129},[98,4973,4974,4976,4978],{"class":100,"line":1362},[98,4975,1416],{"class":129},[98,4977,670],{"class":413},[98,4979,433],{"class":129},[98,4981,4982],{"class":100,"line":1384},[98,4983,225],{"emptyLinePlaceholder":224},[98,4985,4986,4988,4990,4992,4995],{"class":100,"line":1403},[98,4987,1333],{"class":129},[98,4989,670],{"class":413},[98,4991,673],{"class":129},[98,4993,4994],{"class":419},"skeleton",[98,4996,433],{"class":129},[98,4998,4999],{"class":100,"line":1413},[98,5000,5001],{"class":104},"      \u003C!-- Hand-authored placeholder opts out of measurement. Size it to\n",[98,5003,5004],{"class":100,"line":1423},[98,5005,5006],{"class":104},"           match the real chart so the reveal doesn't shift. -->\n",[98,5008,5009,5011,5013,5015,5017,5020,5023],{"class":100,"line":1433},[98,5010,1365],{"class":129},[98,5012,3219],{"class":413},[98,5014,842],{"class":419},[98,5016,422],{"class":129},[98,5018,5019],{"class":133},"\"h-72\"",[98,5021,5022],{"class":419}," ask-block",[98,5024,433],{"class":129},[98,5026,5028,5030,5033,5036,5038,5041,5044,5046,5048,5051,5053,5056],{"class":100,"line":5027},33,[98,5029,1387],{"class":129},[98,5031,5032],{"class":413},"AGhostSkeletonBox",[98,5034,5035],{"class":419}," width",[98,5037,422],{"class":129},[98,5039,5040],{"class":133},"\"100%\"",[98,5042,5043],{"class":419}," height",[98,5045,422],{"class":129},[98,5047,5040],{"class":133},[98,5049,5050],{"class":419}," radius",[98,5052,422],{"class":129},[98,5054,5055],{"class":133},"\"12px\"",[98,5057,697],{"class":129},[98,5059,5061,5063,5065],{"class":100,"line":5060},34,[98,5062,1406],{"class":129},[98,5064,3219],{"class":413},[98,5066,433],{"class":129},[98,5068,5070,5072,5074],{"class":100,"line":5069},35,[98,5071,1416],{"class":129},[98,5073,670],{"class":413},[98,5075,433],{"class":129},[98,5077,5079,5081,5083],{"class":100,"line":5078},36,[98,5080,1426],{"class":129},[98,5082,44],{"class":413},[98,5084,433],{"class":129},[98,5086,5088,5090,5092],{"class":100,"line":5087},37,[98,5089,443],{"class":129},[98,5091,670],{"class":413},[98,5093,433],{"class":129},[21,5095,5096,5099,5100,5102,5103,5105],{},[14,5097,5098],{},"lineDashArray: [[], [4, 4]]"," draws series 0 solid and series 1 dashed — the shape a \"this period vs previous period\" overlay wants. The ",[14,5101,2009],{}," slot sets ",[14,5104,1927],{}," for you so the walker stops at the chart root.",[81,5107,5109],{"id":5108},"_4-a-paginated-table","4. A paginated table",[21,5111,5112,5113,5115],{},"The slot binding is doing the work here: the sample's rows reach the child table so the measurement captures a full table shape, not an empty single-column shell. Every column ",[14,5114,3883],{}," renders gets a bone.",[89,5117,5119],{"className":396,"code":5118,"language":398,"meta":94,"style":94},"\u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue';\n\ninterface Page {\n  url: string;\n  sessions: number;\n  bounce: number;\n}\ninterface Report {\n  rows: Page[];\n  total: number;\n}\n\nconst report = ref\u003CReport | null>(null);\nconst SAMPLE: Report = {\n  total: 5,\n  rows: [\n    { url: '\u002F', sessions: 8420, bounce: 0.42 },\n    { url: '\u002Fpricing', sessions: 3420, bounce: 0.51 },\n    { url: '\u002Fdocs', sessions: 2340, bounce: 0.38 },\n    { url: '\u002Fblog', sessions: 1730, bounce: 0.62 },\n    { url: '\u002Fabout', sessions: 1214, bounce: 0.58 },\n  ],\n};\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CAGhostSkeleton id=\"pages-report\" :data=\"report\" :sample=\"SAMPLE\">\n    \u003Ctemplate #default=\"{ data }\">\n      \u003CDataTable :rows=\"data?.rows ?? []\" :total=\"data?.total ?? 0\" \u002F>\n    \u003C\u002Ftemplate>\n  \u003C\u002FAGhostSkeleton>\n\u003C\u002Ftemplate>\n",[14,5120,5121,5137,5149,5153,5162,5173,5184,5195,5199,5208,5219,5230,5234,5238,5264,5278,5288,5293,5315,5334,5353,5372,5391,5395,5399,5407,5411,5419,5447,5467,5490,5498,5506],{"__ignoreMap":94},[98,5122,5123,5125,5127,5129,5131,5133,5135],{"class":100,"line":101},[98,5124,410],{"class":129},[98,5126,1084],{"class":413},[98,5128,1087],{"class":419},[98,5130,1090],{"class":419},[98,5132,422],{"class":129},[98,5134,1095],{"class":133},[98,5136,433],{"class":129},[98,5138,5139,5141,5143,5145,5147],{"class":100,"line":108},[98,5140,175],{"class":111},[98,5142,4307],{"class":129},[98,5144,200],{"class":111},[98,5146,1109],{"class":133},[98,5148,149],{"class":129},[98,5150,5151],{"class":100,"line":126},[98,5152,225],{"emptyLinePlaceholder":224},[98,5154,5155,5157,5160],{"class":100,"line":143},[98,5156,3936],{"class":111},[98,5158,5159],{"class":122}," Page",[98,5161,235],{"class":129},[98,5163,5164,5167,5169,5171],{"class":100,"line":228},[98,5165,5166],{"class":122},"  url",[98,5168,1072],{"class":111},[98,5170,3951],{"class":419},[98,5172,149],{"class":129},[98,5174,5175,5178,5180,5182],{"class":100,"line":238},[98,5176,5177],{"class":122},"  sessions",[98,5179,1072],{"class":111},[98,5181,3963],{"class":419},[98,5183,149],{"class":129},[98,5185,5186,5189,5191,5193],{"class":100,"line":258},[98,5187,5188],{"class":122},"  bounce",[98,5190,1072],{"class":111},[98,5192,3963],{"class":419},[98,5194,149],{"class":129},[98,5196,5197],{"class":100,"line":492},[98,5198,2683],{"class":129},[98,5200,5201,5203,5206],{"class":100,"line":497},[98,5202,3936],{"class":111},[98,5204,5205],{"class":122}," Report",[98,5207,235],{"class":129},[98,5209,5210,5213,5215,5217],{"class":100,"line":1003},[98,5211,5212],{"class":122},"  rows",[98,5214,1072],{"class":111},[98,5216,5159],{"class":122},[98,5218,4338],{"class":129},[98,5220,5221,5224,5226,5228],{"class":100,"line":1014},[98,5222,5223],{"class":122},"  total",[98,5225,1072],{"class":111},[98,5227,3963],{"class":419},[98,5229,149],{"class":129},[98,5231,5232],{"class":100,"line":1023},[98,5233,2683],{"class":129},[98,5235,5236],{"class":100,"line":1028},[98,5237,225],{"emptyLinePlaceholder":224},[98,5239,5240,5242,5245,5247,5249,5251,5254,5256,5258,5260,5262],{"class":100,"line":1034},[98,5241,1120],{"class":111},[98,5243,5244],{"class":419}," report",[98,5246,1126],{"class":111},[98,5248,1129],{"class":118},[98,5250,410],{"class":129},[98,5252,5253],{"class":122},"Report",[98,5255,1137],{"class":111},[98,5257,1140],{"class":419},[98,5259,1143],{"class":129},[98,5261,380],{"class":419},[98,5263,1148],{"class":129},[98,5265,5266,5268,5270,5272,5274,5276],{"class":100,"line":1249},[98,5267,1120],{"class":111},[98,5269,4017],{"class":419},[98,5271,1072],{"class":111},[98,5273,5205],{"class":122},[98,5275,1126],{"class":111},[98,5277,235],{"class":129},[98,5279,5280,5283,5286],{"class":100,"line":1258},[98,5281,5282],{"class":129},"  total: ",[98,5284,5285],{"class":419},"5",[98,5287,140],{"class":129},[98,5289,5290],{"class":100,"line":1263},[98,5291,5292],{"class":129},"  rows: [\n",[98,5294,5295,5298,5301,5304,5307,5310,5313],{"class":100,"line":1272},[98,5296,5297],{"class":129},"    { url: ",[98,5299,5300],{"class":133},"'\u002F'",[98,5302,5303],{"class":129},", sessions: ",[98,5305,5306],{"class":419},"8420",[98,5308,5309],{"class":129},", bounce: ",[98,5311,5312],{"class":419},"0.42",[98,5314,985],{"class":129},[98,5316,5317,5319,5322,5324,5327,5329,5332],{"class":100,"line":1279},[98,5318,5297],{"class":129},[98,5320,5321],{"class":133},"'\u002Fpricing'",[98,5323,5303],{"class":129},[98,5325,5326],{"class":419},"3420",[98,5328,5309],{"class":129},[98,5330,5331],{"class":419},"0.51",[98,5333,985],{"class":129},[98,5335,5336,5338,5341,5343,5346,5348,5351],{"class":100,"line":1289},[98,5337,5297],{"class":129},[98,5339,5340],{"class":133},"'\u002Fdocs'",[98,5342,5303],{"class":129},[98,5344,5345],{"class":419},"2340",[98,5347,5309],{"class":129},[98,5349,5350],{"class":419},"0.38",[98,5352,985],{"class":129},[98,5354,5355,5357,5360,5362,5365,5367,5370],{"class":100,"line":1300},[98,5356,5297],{"class":129},[98,5358,5359],{"class":133},"'\u002Fblog'",[98,5361,5303],{"class":129},[98,5363,5364],{"class":419},"1730",[98,5366,5309],{"class":129},[98,5368,5369],{"class":419},"0.62",[98,5371,985],{"class":129},[98,5373,5374,5376,5379,5381,5384,5386,5389],{"class":100,"line":1306},[98,5375,5297],{"class":129},[98,5377,5378],{"class":133},"'\u002Fabout'",[98,5380,5303],{"class":129},[98,5382,5383],{"class":419},"1214",[98,5385,5309],{"class":129},[98,5387,5388],{"class":419},"0.58",[98,5390,985],{"class":129},[98,5392,5393],{"class":100,"line":1312},[98,5394,4473],{"class":129},[98,5396,5397],{"class":100,"line":1318},[98,5398,1198],{"class":129},[98,5400,5401,5403,5405],{"class":100,"line":1324},[98,5402,443],{"class":129},[98,5404,1084],{"class":413},[98,5406,433],{"class":129},[98,5408,5409],{"class":100,"line":1330},[98,5410,225],{"emptyLinePlaceholder":224},[98,5412,5413,5415,5417],{"class":100,"line":1362},[98,5414,410],{"class":129},[98,5416,670],{"class":413},[98,5418,433],{"class":129},[98,5420,5421,5423,5425,5427,5429,5432,5434,5436,5439,5441,5443,5445],{"class":100,"line":1384},[98,5422,683],{"class":129},[98,5424,44],{"class":413},[98,5426,584],{"class":419},[98,5428,422],{"class":129},[98,5430,5431],{"class":133},"\"pages-report\"",[98,5433,1344],{"class":419},[98,5435,422],{"class":129},[98,5437,5438],{"class":133},"\"report\"",[98,5440,1352],{"class":419},[98,5442,422],{"class":129},[98,5444,4131],{"class":133},[98,5446,433],{"class":129},[98,5448,5449,5451,5453,5455,5457,5459,5461,5463,5465],{"class":100,"line":1403},[98,5450,1333],{"class":129},[98,5452,670],{"class":413},[98,5454,673],{"class":129},[98,5456,676],{"class":419},[98,5458,422],{"class":129},[98,5460,425],{"class":129},[98,5462,626],{"class":129},[98,5464,425],{"class":129},[98,5466,433],{"class":129},[98,5468,5469,5471,5474,5476,5478,5480,5483,5485,5488],{"class":100,"line":1413},[98,5470,1365],{"class":129},[98,5472,5473],{"class":413},"DataTable",[98,5475,689],{"class":419},[98,5477,422],{"class":129},[98,5479,747],{"class":133},[98,5481,5482],{"class":419}," :total",[98,5484,422],{"class":129},[98,5486,5487],{"class":133},"\"data?.total ?? 0\"",[98,5489,697],{"class":129},[98,5491,5492,5494,5496],{"class":100,"line":1423},[98,5493,1416],{"class":129},[98,5495,670],{"class":413},[98,5497,433],{"class":129},[98,5499,5500,5502,5504],{"class":100,"line":1433},[98,5501,1426],{"class":129},[98,5503,44],{"class":413},[98,5505,433],{"class":129},[98,5507,5508,5510,5512],{"class":100,"line":5027},[98,5509,443],{"class":129},[98,5511,670],{"class":413},[98,5513,433],{"class":129},[21,5515,5516,5517,5521],{},"The same markup without the destructure measures an empty table — see ",[67,5518,649,5519,652],{"href":648},[14,5520,376],{}," for the before \u002F after.",[81,5523,5525],{"id":5524},"_5-a-distribution-list","5. A distribution list",[21,5527,5528,5529,5532],{},"Lists of rows measure well out of the box. ",[14,5530,5531],{},"reveal=\"together\""," keeps them from staggering row-by-row.",[89,5534,5536],{"className":396,"code":5535,"language":398,"meta":94,"style":94},"\u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue';\n\ninterface Row {\n  label: string;\n  value: number;\n  share: number;\n}\n\nconst distribution = ref\u003CRow[] | null>(null);\nconst SAMPLE: Row[] = [\n  { label: 'Chrome', value: 6840, share: 0.55 },\n  { label: 'Safari', value: 3920, share: 0.31 },\n  { label: 'Edge', value: 980, share: 0.08 },\n  { label: 'Firefox', value: 420, share: 0.03 },\n  { label: 'Other', value: 310, share: 0.02 },\n];\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CAGhostSkeleton id=\"browser-distribution\" :data=\"distribution\" :sample=\"SAMPLE\" reveal=\"together\">\n    \u003Ctemplate #default=\"{ data }\">\n      \u003Cdiv class=\"flex flex-col gap-3\">\n        \u003Cdiv v-for=\"row in data\" :key=\"row.label\" class=\"row\">\n          \u003Cspan>{{ row.label }}\u003C\u002Fspan>\n          \u003Cspan>{{ row.value.toLocaleString() }}\u003C\u002Fspan>\n          \u003Cspan>{{ (row.share * 100).toFixed(0) }}%\u003C\u002Fspan>\n          \u003Cdiv class=\"bar\" :style=\"{ width: `${row.share * 100}%` }\" \u002F>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002Ftemplate>\n  \u003C\u002FAGhostSkeleton>\n\u003C\u002Ftemplate>\n",[14,5537,5538,5554,5566,5570,5579,5589,5599,5610,5614,5618,5646,5663,5684,5703,5722,5741,5760,5765,5773,5777,5785,5819,5839,5854,5883,5896,5909,5922,5948,5956,5964,5972,5980],{"__ignoreMap":94},[98,5539,5540,5542,5544,5546,5548,5550,5552],{"class":100,"line":101},[98,5541,410],{"class":129},[98,5543,1084],{"class":413},[98,5545,1087],{"class":419},[98,5547,1090],{"class":419},[98,5549,422],{"class":129},[98,5551,1095],{"class":133},[98,5553,433],{"class":129},[98,5555,5556,5558,5560,5562,5564],{"class":100,"line":108},[98,5557,175],{"class":111},[98,5559,4307],{"class":129},[98,5561,200],{"class":111},[98,5563,1109],{"class":133},[98,5565,149],{"class":129},[98,5567,5568],{"class":100,"line":126},[98,5569,225],{"emptyLinePlaceholder":224},[98,5571,5572,5574,5577],{"class":100,"line":143},[98,5573,3936],{"class":111},[98,5575,5576],{"class":122}," Row",[98,5578,235],{"class":129},[98,5580,5581,5583,5585,5587],{"class":100,"line":228},[98,5582,3946],{"class":122},[98,5584,1072],{"class":111},[98,5586,3951],{"class":419},[98,5588,149],{"class":129},[98,5590,5591,5593,5595,5597],{"class":100,"line":238},[98,5592,3958],{"class":122},[98,5594,1072],{"class":111},[98,5596,3963],{"class":419},[98,5598,149],{"class":129},[98,5600,5601,5604,5606,5608],{"class":100,"line":258},[98,5602,5603],{"class":122},"  share",[98,5605,1072],{"class":111},[98,5607,3963],{"class":419},[98,5609,149],{"class":129},[98,5611,5612],{"class":100,"line":492},[98,5613,2683],{"class":129},[98,5615,5616],{"class":100,"line":497},[98,5617,225],{"emptyLinePlaceholder":224},[98,5619,5620,5622,5625,5627,5629,5631,5634,5636,5638,5640,5642,5644],{"class":100,"line":1003},[98,5621,1120],{"class":111},[98,5623,5624],{"class":419}," distribution",[98,5626,1126],{"class":111},[98,5628,1129],{"class":118},[98,5630,410],{"class":129},[98,5632,5633],{"class":122},"Row",[98,5635,4799],{"class":129},[98,5637,4802],{"class":111},[98,5639,1140],{"class":419},[98,5641,1143],{"class":129},[98,5643,380],{"class":419},[98,5645,1148],{"class":129},[98,5647,5648,5650,5652,5654,5656,5658,5660],{"class":100,"line":1014},[98,5649,1120],{"class":111},[98,5651,4017],{"class":419},[98,5653,1072],{"class":111},[98,5655,5576],{"class":122},[98,5657,4799],{"class":129},[98,5659,422],{"class":111},[98,5661,5662],{"class":129}," [\n",[98,5664,5665,5668,5671,5673,5676,5679,5682],{"class":100,"line":1023},[98,5666,5667],{"class":129},"  { label: ",[98,5669,5670],{"class":133},"'Chrome'",[98,5672,4032],{"class":129},[98,5674,5675],{"class":419},"6840",[98,5677,5678],{"class":129},", share: ",[98,5680,5681],{"class":419},"0.55",[98,5683,985],{"class":129},[98,5685,5686,5688,5691,5693,5696,5698,5701],{"class":100,"line":1028},[98,5687,5667],{"class":129},[98,5689,5690],{"class":133},"'Safari'",[98,5692,4032],{"class":129},[98,5694,5695],{"class":419},"3920",[98,5697,5678],{"class":129},[98,5699,5700],{"class":419},"0.31",[98,5702,985],{"class":129},[98,5704,5705,5707,5710,5712,5715,5717,5720],{"class":100,"line":1034},[98,5706,5667],{"class":129},[98,5708,5709],{"class":133},"'Edge'",[98,5711,4032],{"class":129},[98,5713,5714],{"class":419},"980",[98,5716,5678],{"class":129},[98,5718,5719],{"class":419},"0.08",[98,5721,985],{"class":129},[98,5723,5724,5726,5729,5731,5734,5736,5739],{"class":100,"line":1249},[98,5725,5667],{"class":129},[98,5727,5728],{"class":133},"'Firefox'",[98,5730,4032],{"class":129},[98,5732,5733],{"class":419},"420",[98,5735,5678],{"class":129},[98,5737,5738],{"class":419},"0.03",[98,5740,985],{"class":129},[98,5742,5743,5745,5748,5750,5753,5755,5758],{"class":100,"line":1258},[98,5744,5667],{"class":129},[98,5746,5747],{"class":133},"'Other'",[98,5749,4032],{"class":129},[98,5751,5752],{"class":419},"310",[98,5754,5678],{"class":129},[98,5756,5757],{"class":419},"0.02",[98,5759,985],{"class":129},[98,5761,5762],{"class":100,"line":1263},[98,5763,5764],{"class":129},"];\n",[98,5766,5767,5769,5771],{"class":100,"line":1272},[98,5768,443],{"class":129},[98,5770,1084],{"class":413},[98,5772,433],{"class":129},[98,5774,5775],{"class":100,"line":1279},[98,5776,225],{"emptyLinePlaceholder":224},[98,5778,5779,5781,5783],{"class":100,"line":1289},[98,5780,410],{"class":129},[98,5782,670],{"class":413},[98,5784,433],{"class":129},[98,5786,5787,5789,5791,5793,5795,5798,5800,5802,5805,5807,5809,5811,5813,5815,5817],{"class":100,"line":1300},[98,5788,683],{"class":129},[98,5790,44],{"class":413},[98,5792,584],{"class":419},[98,5794,422],{"class":129},[98,5796,5797],{"class":133},"\"browser-distribution\"",[98,5799,1344],{"class":419},[98,5801,422],{"class":129},[98,5803,5804],{"class":133},"\"distribution\"",[98,5806,1352],{"class":419},[98,5808,422],{"class":129},[98,5810,4131],{"class":133},[98,5812,4526],{"class":419},[98,5814,422],{"class":129},[98,5816,4531],{"class":133},[98,5818,433],{"class":129},[98,5820,5821,5823,5825,5827,5829,5831,5833,5835,5837],{"class":100,"line":1306},[98,5822,1333],{"class":129},[98,5824,670],{"class":413},[98,5826,673],{"class":129},[98,5828,676],{"class":419},[98,5830,422],{"class":129},[98,5832,425],{"class":129},[98,5834,626],{"class":129},[98,5836,425],{"class":129},[98,5838,433],{"class":129},[98,5840,5841,5843,5845,5847,5849,5852],{"class":100,"line":1312},[98,5842,1365],{"class":129},[98,5844,3219],{"class":413},[98,5846,842],{"class":419},[98,5848,422],{"class":129},[98,5850,5851],{"class":133},"\"flex flex-col gap-3\"",[98,5853,433],{"class":129},[98,5855,5856,5858,5860,5862,5864,5867,5869,5871,5874,5876,5878,5881],{"class":100,"line":1318},[98,5857,1387],{"class":129},[98,5859,3219],{"class":413},[98,5861,4577],{"class":419},[98,5863,422],{"class":129},[98,5865,5866],{"class":133},"\"row in data\"",[98,5868,4585],{"class":419},[98,5870,422],{"class":129},[98,5872,5873],{"class":133},"\"row.label\"",[98,5875,842],{"class":419},[98,5877,422],{"class":129},[98,5879,5880],{"class":133},"\"row\"",[98,5882,433],{"class":129},[98,5884,5885,5887,5889,5892,5894],{"class":100,"line":1324},[98,5886,4603],{"class":129},[98,5888,98],{"class":413},[98,5890,5891],{"class":129},">{{ row.label }}\u003C\u002F",[98,5893,98],{"class":413},[98,5895,433],{"class":129},[98,5897,5898,5900,5902,5905,5907],{"class":100,"line":1330},[98,5899,4603],{"class":129},[98,5901,98],{"class":413},[98,5903,5904],{"class":129},">{{ row.value.toLocaleString() }}\u003C\u002F",[98,5906,98],{"class":413},[98,5908,433],{"class":129},[98,5910,5911,5913,5915,5918,5920],{"class":100,"line":1362},[98,5912,4603],{"class":129},[98,5914,98],{"class":413},[98,5916,5917],{"class":129},">{{ (row.share * 100).toFixed(0) }}%\u003C\u002F",[98,5919,98],{"class":413},[98,5921,433],{"class":129},[98,5923,5924,5926,5928,5930,5932,5935,5938,5940,5943,5946],{"class":100,"line":1384},[98,5925,4603],{"class":129},[98,5927,3219],{"class":413},[98,5929,842],{"class":419},[98,5931,422],{"class":129},[98,5933,5934],{"class":133},"\"bar\"",[98,5936,5937],{"class":419}," :style",[98,5939,422],{"class":129},[98,5941,5942],{"class":133},"\"{ width: `${row.share * 100}%` }\"",[98,5944,5945],{"class":2411}," \u002F",[98,5947,433],{"class":129},[98,5949,5950,5952,5954],{"class":100,"line":1403},[98,5951,4630],{"class":129},[98,5953,3219],{"class":413},[98,5955,433],{"class":129},[98,5957,5958,5960,5962],{"class":100,"line":1413},[98,5959,1406],{"class":129},[98,5961,3219],{"class":413},[98,5963,433],{"class":129},[98,5965,5966,5968,5970],{"class":100,"line":1423},[98,5967,1416],{"class":129},[98,5969,670],{"class":413},[98,5971,433],{"class":129},[98,5973,5974,5976,5978],{"class":100,"line":1433},[98,5975,1426],{"class":129},[98,5977,44],{"class":413},[98,5979,433],{"class":129},[98,5981,5982,5984,5986],{"class":100,"line":5027},[98,5983,443],{"class":129},[98,5985,670],{"class":413},[98,5987,433],{"class":129},[81,5989,5991],{"id":5990},"_6-four-states-one-component","6. Four states, one component",[21,5993,5994,5995,5998],{},"The same skeleton resolves ",[14,5996,5997],{},"loading → error → empty → content",". Wire all four slots and the component picks the right one.",[89,6000,6002],{"className":396,"code":6001,"language":398,"meta":94,"style":94},"\u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue';\n\nconst report = ref\u003CReport | null>(null);\nconst fetchError = ref\u003CError | null>(null);\n\nasync function load() {\n  report.value = null;\n  fetchError.value = null;\n  try {\n    report.value = await $fetch('\u002Fapi\u002Freport');\n  } catch (e) {\n    fetchError.value = e as Error;\n  }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CAGhostSkeleton\n    id=\"four-state-report\"\n    :data=\"report\"\n    :sample=\"SAMPLE\"\n    :error=\"fetchError\"\n    :empty=\"report?.rows.length === 0\"\n  >\n    \u003Ctemplate #default=\"{ data }\">\n      \u003CDataTable :rows=\"data.rows\" \u002F>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #empty>\n      \u003Carticle class=\"empty-card\">\n        \u003Cp>No data in this window.\u003C\u002Fp>\n      \u003C\u002Farticle>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #error>\n      \u003Carticle class=\"error-card\">\n        \u003Cp>Couldn't load the report.\u003C\u002Fp>\n        \u003Cbutton @click=\"load\">Retry\u003C\u002Fbutton>\n      \u003C\u002Farticle>\n    \u003C\u002Ftemplate>\n  \u003C\u002FAGhostSkeleton>\n\u003C\u002Ftemplate>\n",[14,6003,6004,6020,6032,6036,6060,6086,6090,6103,6114,6125,6132,6150,6161,6179,6184,6188,6196,6200,6208,6214,6224,6234,6244,6254,6264,6268,6288,6303,6311,6315,6327,6342,6355,6363,6371,6375,6387,6402,6416,6439,6448,6457,6466],{"__ignoreMap":94},[98,6005,6006,6008,6010,6012,6014,6016,6018],{"class":100,"line":101},[98,6007,410],{"class":129},[98,6009,1084],{"class":413},[98,6011,1087],{"class":419},[98,6013,1090],{"class":419},[98,6015,422],{"class":129},[98,6017,1095],{"class":133},[98,6019,433],{"class":129},[98,6021,6022,6024,6026,6028,6030],{"class":100,"line":108},[98,6023,175],{"class":111},[98,6025,4307],{"class":129},[98,6027,200],{"class":111},[98,6029,1109],{"class":133},[98,6031,149],{"class":129},[98,6033,6034],{"class":100,"line":126},[98,6035,225],{"emptyLinePlaceholder":224},[98,6037,6038,6040,6042,6044,6046,6048,6050,6052,6054,6056,6058],{"class":100,"line":143},[98,6039,1120],{"class":111},[98,6041,5244],{"class":419},[98,6043,1126],{"class":111},[98,6045,1129],{"class":118},[98,6047,410],{"class":129},[98,6049,5253],{"class":122},[98,6051,1137],{"class":111},[98,6053,1140],{"class":419},[98,6055,1143],{"class":129},[98,6057,380],{"class":419},[98,6059,1148],{"class":129},[98,6061,6062,6064,6067,6069,6071,6073,6076,6078,6080,6082,6084],{"class":100,"line":228},[98,6063,1120],{"class":111},[98,6065,6066],{"class":419}," fetchError",[98,6068,1126],{"class":111},[98,6070,1129],{"class":118},[98,6072,410],{"class":129},[98,6074,6075],{"class":122},"Error",[98,6077,1137],{"class":111},[98,6079,1140],{"class":419},[98,6081,1143],{"class":129},[98,6083,380],{"class":419},[98,6085,1148],{"class":129},[98,6087,6088],{"class":100,"line":238},[98,6089,225],{"emptyLinePlaceholder":224},[98,6091,6092,6094,6097,6100],{"class":100,"line":258},[98,6093,1213],{"class":111},[98,6095,6096],{"class":111}," function",[98,6098,6099],{"class":118}," load",[98,6101,6102],{"class":129},"() {\n",[98,6104,6105,6108,6110,6112],{"class":100,"line":492},[98,6106,6107],{"class":129},"  report.value ",[98,6109,422],{"class":111},[98,6111,1140],{"class":419},[98,6113,149],{"class":129},[98,6115,6116,6119,6121,6123],{"class":100,"line":497},[98,6117,6118],{"class":129},"  fetchError.value ",[98,6120,422],{"class":111},[98,6122,1140],{"class":419},[98,6124,149],{"class":129},[98,6126,6127,6130],{"class":100,"line":1003},[98,6128,6129],{"class":111},"  try",[98,6131,235],{"class":129},[98,6133,6134,6137,6139,6141,6143,6145,6148],{"class":100,"line":1014},[98,6135,6136],{"class":129},"    report.value ",[98,6138,422],{"class":111},[98,6140,1231],{"class":111},[98,6142,1234],{"class":118},[98,6144,1210],{"class":129},[98,6146,6147],{"class":133},"'\u002Fapi\u002Freport'",[98,6149,1148],{"class":129},[98,6151,6152,6155,6158],{"class":100,"line":1023},[98,6153,6154],{"class":129},"  } ",[98,6156,6157],{"class":111},"catch",[98,6159,6160],{"class":129}," (e) {\n",[98,6162,6163,6166,6168,6171,6174,6177],{"class":100,"line":1028},[98,6164,6165],{"class":129},"    fetchError.value ",[98,6167,422],{"class":111},[98,6169,6170],{"class":129}," e ",[98,6172,6173],{"class":111},"as",[98,6175,6176],{"class":122}," Error",[98,6178,149],{"class":129},[98,6180,6181],{"class":100,"line":1034},[98,6182,6183],{"class":129},"  }\n",[98,6185,6186],{"class":100,"line":1249},[98,6187,2683],{"class":129},[98,6189,6190,6192,6194],{"class":100,"line":1258},[98,6191,443],{"class":129},[98,6193,1084],{"class":413},[98,6195,433],{"class":129},[98,6197,6198],{"class":100,"line":1263},[98,6199,225],{"emptyLinePlaceholder":224},[98,6201,6202,6204,6206],{"class":100,"line":1272},[98,6203,410],{"class":129},[98,6205,670],{"class":413},[98,6207,433],{"class":129},[98,6209,6210,6212],{"class":100,"line":1279},[98,6211,683],{"class":129},[98,6213,1484],{"class":413},[98,6215,6216,6219,6221],{"class":100,"line":1289},[98,6217,6218],{"class":419},"    id",[98,6220,422],{"class":129},[98,6222,6223],{"class":133},"\"four-state-report\"\n",[98,6225,6226,6229,6231],{"class":100,"line":1300},[98,6227,6228],{"class":419},"    :data",[98,6230,422],{"class":129},[98,6232,6233],{"class":133},"\"report\"\n",[98,6235,6236,6239,6241],{"class":100,"line":1306},[98,6237,6238],{"class":419},"    :sample",[98,6240,422],{"class":129},[98,6242,6243],{"class":133},"\"SAMPLE\"\n",[98,6245,6246,6249,6251],{"class":100,"line":1312},[98,6247,6248],{"class":419},"    :error",[98,6250,422],{"class":129},[98,6252,6253],{"class":133},"\"fetchError\"\n",[98,6255,6256,6259,6261],{"class":100,"line":1318},[98,6257,6258],{"class":419},"    :empty",[98,6260,422],{"class":129},[98,6262,6263],{"class":133},"\"report?.rows.length === 0\"\n",[98,6265,6266],{"class":100,"line":1324},[98,6267,1327],{"class":129},[98,6269,6270,6272,6274,6276,6278,6280,6282,6284,6286],{"class":100,"line":1330},[98,6271,1333],{"class":129},[98,6273,670],{"class":413},[98,6275,673],{"class":129},[98,6277,676],{"class":419},[98,6279,422],{"class":129},[98,6281,425],{"class":129},[98,6283,626],{"class":129},[98,6285,425],{"class":129},[98,6287,433],{"class":129},[98,6289,6290,6292,6294,6296,6298,6301],{"class":100,"line":1362},[98,6291,1365],{"class":129},[98,6293,5473],{"class":413},[98,6295,689],{"class":419},[98,6297,422],{"class":129},[98,6299,6300],{"class":133},"\"data.rows\"",[98,6302,697],{"class":129},[98,6304,6305,6307,6309],{"class":100,"line":1384},[98,6306,1416],{"class":129},[98,6308,670],{"class":413},[98,6310,433],{"class":129},[98,6312,6313],{"class":100,"line":1403},[98,6314,225],{"emptyLinePlaceholder":224},[98,6316,6317,6319,6321,6323,6325],{"class":100,"line":1413},[98,6318,1333],{"class":129},[98,6320,670],{"class":413},[98,6322,673],{"class":129},[98,6324,1469],{"class":419},[98,6326,433],{"class":129},[98,6328,6329,6331,6333,6335,6337,6340],{"class":100,"line":1423},[98,6330,1365],{"class":129},[98,6332,1947],{"class":413},[98,6334,842],{"class":419},[98,6336,422],{"class":129},[98,6338,6339],{"class":133},"\"empty-card\"",[98,6341,433],{"class":129},[98,6343,6344,6346,6348,6351,6353],{"class":100,"line":1433},[98,6345,1387],{"class":129},[98,6347,21],{"class":413},[98,6349,6350],{"class":129},">No data in this window.\u003C\u002F",[98,6352,21],{"class":413},[98,6354,433],{"class":129},[98,6356,6357,6359,6361],{"class":100,"line":5027},[98,6358,1406],{"class":129},[98,6360,1947],{"class":413},[98,6362,433],{"class":129},[98,6364,6365,6367,6369],{"class":100,"line":5060},[98,6366,1416],{"class":129},[98,6368,670],{"class":413},[98,6370,433],{"class":129},[98,6372,6373],{"class":100,"line":5069},[98,6374,225],{"emptyLinePlaceholder":224},[98,6376,6377,6379,6381,6383,6385],{"class":100,"line":5078},[98,6378,1333],{"class":129},[98,6380,670],{"class":413},[98,6382,673],{"class":129},[98,6384,1466],{"class":419},[98,6386,433],{"class":129},[98,6388,6389,6391,6393,6395,6397,6400],{"class":100,"line":5087},[98,6390,1365],{"class":129},[98,6392,1947],{"class":413},[98,6394,842],{"class":419},[98,6396,422],{"class":129},[98,6398,6399],{"class":133},"\"error-card\"",[98,6401,433],{"class":129},[98,6403,6405,6407,6409,6412,6414],{"class":100,"line":6404},38,[98,6406,1387],{"class":129},[98,6408,21],{"class":413},[98,6410,6411],{"class":129},">Couldn't load the report.\u003C\u002F",[98,6413,21],{"class":413},[98,6415,433],{"class":129},[98,6417,6419,6421,6424,6427,6429,6432,6435,6437],{"class":100,"line":6418},39,[98,6420,1387],{"class":129},[98,6422,6423],{"class":413},"button",[98,6425,6426],{"class":419}," @click",[98,6428,422],{"class":129},[98,6430,6431],{"class":133},"\"load\"",[98,6433,6434],{"class":129},">Retry\u003C\u002F",[98,6436,6423],{"class":413},[98,6438,433],{"class":129},[98,6440,6442,6444,6446],{"class":100,"line":6441},40,[98,6443,1406],{"class":129},[98,6445,1947],{"class":413},[98,6447,433],{"class":129},[98,6449,6451,6453,6455],{"class":100,"line":6450},41,[98,6452,1416],{"class":129},[98,6454,670],{"class":413},[98,6456,433],{"class":129},[98,6458,6460,6462,6464],{"class":100,"line":6459},42,[98,6461,1426],{"class":129},[98,6463,44],{"class":413},[98,6465,433],{"class":129},[98,6467,6469,6471,6473],{"class":100,"line":6468},43,[98,6470,443],{"class":129},[98,6472,670],{"class":413},[98,6474,433],{"class":129},[21,6476,6477],{},"Error wins over empty, empty wins over content. A slot you forgot to wire is quietly unrendered.",[81,6479,6481,6482,6484],{"id":6480},"when-the-slot-cant-carry-data-compose-the-fallback","When the slot can't carry ",[14,6483,376],{}," — compose the fallback",[21,6486,6487,6488,6490,6491,6494],{},"Some pages render a slot from values a composable derives from several sources (a per-filter fetch, an aggregated fetch, an interactive refetch). You can't funnel all of those through the ",[14,6489,626],{}," slot argument; make ",[25,6492,6493],{},"every"," derivation fall back to the sample while the real payload is still null.",[89,6496,6498],{"className":91,"code":6497,"language":93,"meta":94,"style":94},"import { computed, ref } from 'vue';\nimport { SAMPLE } from '.\u002Fsample';\n\nexport function useReport() {\n  const aggregated = ref\u003CReport | null>(null);\n  const perFilter = ref\u003CRow[] | null>(null);\n\n  \u002F\u002F Falls back to SAMPLE.rows while both sources are null, so the skeleton\n  \u002F\u002F measures a full list instead of an empty one.\n  const rows = computed(() => perFilter.value ?? aggregated.value?.rows ?? SAMPLE.rows);\n\n  return { aggregated, perFilter, rows };\n}\n",[14,6499,6500,6513,6527,6531,6542,6568,6595,6599,6604,6609,6642,6646,6654],{"__ignoreMap":94},[98,6501,6502,6504,6507,6509,6511],{"class":100,"line":101},[98,6503,175],{"class":111},[98,6505,6506],{"class":129}," { computed, ref } ",[98,6508,200],{"class":111},[98,6510,1109],{"class":133},[98,6512,149],{"class":129},[98,6514,6515,6517,6520,6522,6525],{"class":100,"line":108},[98,6516,175],{"class":111},[98,6518,6519],{"class":129}," { SAMPLE } ",[98,6521,200],{"class":111},[98,6523,6524],{"class":133}," '.\u002Fsample'",[98,6526,149],{"class":129},[98,6528,6529],{"class":100,"line":126},[98,6530,225],{"emptyLinePlaceholder":224},[98,6532,6533,6535,6537,6540],{"class":100,"line":143},[98,6534,112],{"class":111},[98,6536,6096],{"class":111},[98,6538,6539],{"class":118}," useReport",[98,6541,6102],{"class":129},[98,6543,6544,6547,6550,6552,6554,6556,6558,6560,6562,6564,6566],{"class":100,"line":228},[98,6545,6546],{"class":111},"  const",[98,6548,6549],{"class":419}," aggregated",[98,6551,1126],{"class":111},[98,6553,1129],{"class":118},[98,6555,410],{"class":129},[98,6557,5253],{"class":122},[98,6559,1137],{"class":111},[98,6561,1140],{"class":419},[98,6563,1143],{"class":129},[98,6565,380],{"class":419},[98,6567,1148],{"class":129},[98,6569,6570,6572,6575,6577,6579,6581,6583,6585,6587,6589,6591,6593],{"class":100,"line":238},[98,6571,6546],{"class":111},[98,6573,6574],{"class":419}," perFilter",[98,6576,1126],{"class":111},[98,6578,1129],{"class":118},[98,6580,410],{"class":129},[98,6582,5633],{"class":122},[98,6584,4799],{"class":129},[98,6586,4802],{"class":111},[98,6588,1140],{"class":419},[98,6590,1143],{"class":129},[98,6592,380],{"class":419},[98,6594,1148],{"class":129},[98,6596,6597],{"class":100,"line":258},[98,6598,225],{"emptyLinePlaceholder":224},[98,6600,6601],{"class":100,"line":492},[98,6602,6603],{"class":104},"  \u002F\u002F Falls back to SAMPLE.rows while both sources are null, so the skeleton\n",[98,6605,6606],{"class":100,"line":497},[98,6607,6608],{"class":104},"  \u002F\u002F measures a full list instead of an empty one.\n",[98,6610,6611,6613,6616,6618,6621,6624,6626,6629,6632,6635,6637,6639],{"class":100,"line":1003},[98,6612,6546],{"class":111},[98,6614,6615],{"class":419}," rows",[98,6617,1126],{"class":111},[98,6619,6620],{"class":118}," computed",[98,6622,6623],{"class":129},"(() ",[98,6625,1219],{"class":111},[98,6627,6628],{"class":129}," perFilter.value ",[98,6630,6631],{"class":111},"??",[98,6633,6634],{"class":129}," aggregated.value?.rows ",[98,6636,6631],{"class":111},[98,6638,4017],{"class":419},[98,6640,6641],{"class":129},".rows);\n",[98,6643,6644],{"class":100,"line":1014},[98,6645,225],{"emptyLinePlaceholder":224},[98,6647,6648,6651],{"class":100,"line":1023},[98,6649,6650],{"class":111},"  return",[98,6652,6653],{"class":129}," { aggregated, perFilter, rows };\n",[98,6655,6656],{"class":100,"line":1028},[98,6657,2683],{"class":129},[21,6659,6660,6661,6664],{},"The slot then renders from ",[14,6662,6663],{},"rows"," directly and the skeleton captures a real shape even when the outer refs are still loading.",[73,6666,6668],{"id":6667},"api-reference","API reference",[81,6670,6672,6674],{"id":6671},"aghostskeleton-props",[14,6673,272],{}," props",[1701,6676,6677,6691],{},[1704,6678,6679],{},[1707,6680,6681,6684,6687,6689],{},[1710,6682,6683],{},"Prop",[1710,6685,6686],{},"Type",[1710,6688,2111],{},[1710,6690,2860],{},[1717,6692,6693,6715,6733,6753,6771,6788,6810,6831],{},[1707,6694,6695,6699,6704,6708],{},[1722,6696,6697],{},[14,6698,376],{},[1722,6700,6701],{},[14,6702,6703],{},"T | null",[1722,6705,6706],{},[14,6707,1643],{},[1722,6709,6710,6711,53,6713,71],{},"Your real data. The skeleton is active while this is ",[14,6712,380],{},[14,6714,1643],{},[1707,6716,6717,6721,6726,6730],{},[1722,6718,6719],{},[14,6720,60],{},[1722,6722,6723],{},[14,6724,6725],{},"T",[1722,6727,6728],{},[14,6729,1643],{},[1722,6731,6732],{},"Stand-in used to measure the layout before real data arrives.",[1707,6734,6735,6739,6743,6747],{},[1722,6736,6737],{},[14,6738,1462],{},[1722,6740,6741],{},[14,6742,3796],{},[1722,6744,6745],{},[14,6746,1643],{},[1722,6748,6749,6750,6752],{},"Force the skeleton on or off, overriding ",[14,6751,376],{}," detection.",[1707,6754,6755,6759,6764,6768],{},[1722,6756,6757],{},[14,6758,510],{},[1722,6760,6761],{},[14,6762,6763],{},"string",[1722,6765,6766],{},[14,6767,1643],{},[1722,6769,6770],{},"Key for cross-visit shape memory. Highly recommended.",[1707,6772,6773,6777,6781,6785],{},[1722,6774,6775],{},[14,6776,3378],{},[1722,6778,6779],{},[14,6780,6763],{},[1722,6782,6783],{},[14,6784,1643],{},[1722,6786,6787],{},"Screen-reader text announced in place of the skeleton.",[1707,6789,6790,6794,6798,6803],{},[1722,6791,6792],{},[14,6793,1469],{},[1722,6795,6796],{},[14,6797,3796],{},[1722,6799,6800],{},[14,6801,6802],{},"false",[1722,6804,6805,6806,6809],{},"Renders the ",[14,6807,6808],{},"#empty"," slot instead of content.",[1707,6811,6812,6816,6821,6825],{},[1722,6813,6814],{},[14,6815,1466],{},[1722,6817,6818],{},[14,6819,6820],{},"unknown",[1722,6822,6823],{},[14,6824,1643],{},[1722,6826,6827,6828,6809],{},"Renders ",[14,6829,6830],{},"#error=\"{ error }\"",[1707,6832,6833,6837,6842,6848],{},[1722,6834,6835],{},[14,6836,1561],{},[1722,6838,6839],{},[14,6840,6841],{},"RevealMode",[1722,6843,6844,6845],{},"provider \u002F ",[14,6846,6847],{},"'smart'",[1722,6849,6850,6851,71],{},"Reveal transition. See ",[67,6852,1688],{"href":6853},"#reveal-transitions",[81,6855,6857],{"id":6856},"slots","Slots",[1701,6859,6860,6873],{},[1704,6861,6862],{},[1707,6863,6864,6867,6870],{},[1710,6865,6866],{},"Slot",[1710,6868,6869],{},"Receives",[1710,6871,6872],{},"When",[1717,6874,6875,6898,6911,6927],{},[1707,6876,6877,6881,6885],{},[1722,6878,6879],{},[14,6880,676],{},[1722,6882,6883],{},[14,6884,626],{},[1722,6886,6887,6888,6890,6891,6893,6894,6897],{},"Always, with ",[14,6889,376],{}," = real payload OR the ",[14,6892,60],{}," during measurement. ",[25,6895,6896],{},"Destructure and use this binding"," — see pitfall.",[1707,6899,6900,6904,6906],{},[1722,6901,6902],{},[14,6903,1469],{},[1722,6905,3781],{},[1722,6907,6908,6910],{},[14,6909,1469],{}," is true.",[1707,6912,6913,6917,6922],{},[1722,6914,6915],{},[14,6916,1466],{},[1722,6918,6919],{},[14,6920,6921],{},"{ error }",[1722,6923,6924,6926],{},[14,6925,1466],{}," is truthy.",[1707,6928,6929,6933,6935],{},[1722,6930,6931],{},[14,6932,4994],{},[1722,6934,3781],{},[1722,6936,6937],{},"Optional hand-authored skeleton — opts out of measurement.",[36,6939,6941],{"title":6940,"type":1773},"`#default` must use its `{ data }` argument",[21,6942,6943,6944,6947,6948,6950,6951,6955],{},"The plugin invokes the slot with the sample during the measurement pass. A slot that doesn't destructure it (and instead reads an outer ",[14,6945,6946],{},"ref"," which is still ",[14,6949,380],{}," while loading) hands empty data to its children — the skeleton measures an empty shape and the cold reload is wrong. See ",[67,6952,649,6953,652],{"href":648},[14,6954,376],{}," for the before\u002Fafter.",[81,6957,6959],{"id":6958},"events","Events",[1701,6961,6962,6975],{},[1704,6963,6964],{},[1707,6965,6966,6969,6972],{},[1710,6967,6968],{},"Event",[1710,6970,6971],{},"Payload",[1710,6973,6974],{},"Fires when",[1717,6976,6977],{},[1707,6978,6979,6983,6985],{},[1722,6980,6981],{},[14,6982,1561],{},[1722,6984,3781],{},[1722,6986,6987],{},"Real content takes over from a skeleton, exactly once per cycle.",[81,6989,6991,6674],{"id":6990},"aghostskeletonprovider-props",[14,6992,287],{},[1701,6994,6995,7005],{},[1704,6996,6997],{},[1707,6998,6999,7001,7003],{},[1710,7000,6683],{},[1710,7002,6686],{},[1710,7004,2860],{},[1717,7006,7007,7023,7037,7050,7064,7078],{},[1707,7008,7009,7013,7018],{},[1722,7010,7011],{},[14,7012,961],{},[1722,7014,7015],{},[14,7016,7017],{},"SkeletonTheme",[1722,7019,7020,71],{},[14,7021,7022],{},"{ light, dark, radius, animation, speed, text }",[1707,7024,7025,7029,7034],{},[1722,7026,7027],{},[14,7028,2822],{},[1722,7030,7031],{},[14,7032,7033],{},"'light' | 'dark' | 'system'",[1722,7035,7036],{},"Which theme half to apply.",[1707,7038,7039,7043,7047],{},[1722,7040,7041],{},[14,7042,1561],{},[1722,7044,7045],{},[14,7046,6841],{},[1722,7048,7049],{},"Default reveal for every skeleton inside.",[1707,7051,7052,7056,7061],{},[1722,7053,7054],{},[14,7055,3128],{},[1722,7057,7058],{},[14,7059,7060],{},"{ top?, bottom? }",[1722,7062,7063],{},"Font line each text bar runs from \u002F to.",[1707,7065,7066,7071,7075],{},[1722,7067,7068],{},[14,7069,7070],{},"debug",[1722,7072,7073],{},[14,7074,3796],{},[1722,7076,7077],{},"Outlines every reveal pane and labels its source (sample \u002F data \u002F recall \u002F fallback).",[1707,7079,7080,7085,7089],{},[1722,7081,7082],{},[14,7083,7084],{},"nonce",[1722,7086,7087],{},[14,7088,6763],{},[1722,7090,7091],{},"CSP nonce for the inline boot script and injected stylesheet.",[81,7093,7095,6674],{"id":7094},"aghostskeletonbox-props",[14,7096,64],{},[1701,7098,7099,7111],{},[1704,7100,7101],{},[1707,7102,7103,7105,7107,7109],{},[1710,7104,6683],{},[1710,7106,6686],{},[1710,7108,2111],{},[1710,7110,2860],{},[1717,7112,7113,7131,7148],{},[1707,7114,7115,7119,7123,7128],{},[1722,7116,7117],{},[14,7118,771],{},[1722,7120,7121],{},[14,7122,6763],{},[1722,7124,7125],{},[14,7126,7127],{},"100%",[1722,7129,7130],{},"Any CSS length.",[1707,7132,7133,7137,7141,7146],{},[1722,7134,7135],{},[14,7136,774],{},[1722,7138,7139],{},[14,7140,6763],{},[1722,7142,7143],{},[14,7144,7145],{},"1em",[1722,7147,7130],{},[1707,7149,7150,7155,7159,7163],{},[1722,7151,7152],{},[14,7153,7154],{},"radius",[1722,7156,7157],{},[14,7158,6763],{},[1722,7160,7161],{},[14,7162,2896],{},[1722,7164,7130],{},[81,7166,7168,6674],{"id":7167},"aghostskeletonsuspense-props",[14,7169,279],{},[1701,7171,7172,7182],{},[1704,7173,7174],{},[1707,7175,7176,7178,7180],{},[1710,7177,6683],{},[1710,7179,6686],{},[1710,7181,2860],{},[1717,7183,7184,7197,7209],{},[1707,7185,7186,7190,7194],{},[1722,7187,7188],{},[14,7189,510],{},[1722,7191,7192],{},[14,7193,6763],{},[1722,7195,7196],{},"Key for cross-visit shape memory.",[1707,7198,7199,7203,7207],{},[1722,7200,7201],{},[14,7202,3378],{},[1722,7204,7205],{},[14,7206,6763],{},[1722,7208,6787],{},[1707,7210,7211,7215,7219],{},[1722,7212,7213],{},[14,7214,1561],{},[1722,7216,7217],{},[14,7218,6841],{},[1722,7220,7221],{},"Override for this boundary alone.",[81,7223,7225],{"id":7224},"author-hints-html-attributes","Author hints (HTML attributes)",[1701,7227,7228,7241],{},[1704,7229,7230],{},[1707,7231,7232,7235,7239],{},[1710,7233,7234],{},"Attribute",[1710,7236,7237,1877],{},[14,7238,1876],{},[1710,7240,1880],{},[1717,7242,7243,7256,7269,7282],{},[1707,7244,7245,7249,7253],{},[1722,7246,7247],{},[14,7248,1889],{},[1722,7250,7251],{},[14,7252,1894],{},[1722,7254,7255],{},"Draw as one bone, no recursion.",[1707,7257,7258,7262,7266],{},[1722,7259,7260],{},[14,7261,1908],{},[1722,7263,7264],{},[14,7265,1913],{},[1722,7267,7268],{},"Keep the layout footprint, emit no bones.",[1707,7270,7271,7275,7279],{},[1722,7272,7273],{},[14,7274,1927],{},[1722,7276,7277],{},[14,7278,1932],{},[1722,7280,7281],{},"Subtree draws its own skeleton.",[1707,7283,7284,7288,7293],{},[1722,7285,7286],{},[14,7287,3527],{},[1722,7289,7290],{},[14,7291,7292],{},"data-skeleton-debug",[1722,7294,7295],{},"Scope the measurement trace to this subtree.",[73,7297,649,7299,652],{"id":7298},"thread-data-through-the-slot",[14,7300,376],{},[21,7302,7303,7304,7307,7308,7310,7311,7313,7314,7316],{},"The sample reaches your child components ",[25,7305,7306],{},"only"," through the slot's ",[14,7309,626],{}," argument. Ignoring it and reading an outer ref directly means the ref is still ",[14,7312,380],{}," during measurement — children render empty, the ghost captures a half-drawn shape, and the cold-load skeleton is wrong. Warm visits hit the cache (written ",[642,7315,644],{}," real data arrived) and hide the bug.",[89,7318,7319],{"className":396,"code":656,"language":398,"meta":94,"style":94},[14,7320,7321,7325,7337,7351,7359,7363,7367,7387,7401],{"__ignoreMap":94},[98,7322,7323],{"class":100,"line":101},[98,7324,663],{"class":104},[98,7326,7327,7329,7331,7333,7335],{"class":100,"line":108},[98,7328,410],{"class":129},[98,7330,670],{"class":413},[98,7332,673],{"class":129},[98,7334,676],{"class":419},[98,7336,433],{"class":129},[98,7338,7339,7341,7343,7345,7347,7349],{"class":100,"line":126},[98,7340,683],{"class":129},[98,7342,686],{"class":413},[98,7344,689],{"class":419},[98,7346,422],{"class":129},[98,7348,694],{"class":133},[98,7350,697],{"class":129},[98,7352,7353,7355,7357],{"class":100,"line":143},[98,7354,443],{"class":129},[98,7356,670],{"class":413},[98,7358,433],{"class":129},[98,7360,7361],{"class":100,"line":228},[98,7362,225],{"emptyLinePlaceholder":224},[98,7364,7365],{"class":100,"line":238},[98,7366,714],{"class":104},[98,7368,7369,7371,7373,7375,7377,7379,7381,7383,7385],{"class":100,"line":258},[98,7370,410],{"class":129},[98,7372,670],{"class":413},[98,7374,673],{"class":129},[98,7376,676],{"class":419},[98,7378,422],{"class":129},[98,7380,425],{"class":129},[98,7382,626],{"class":129},[98,7384,425],{"class":129},[98,7386,433],{"class":129},[98,7388,7389,7391,7393,7395,7397,7399],{"class":100,"line":492},[98,7390,683],{"class":129},[98,7392,686],{"class":413},[98,7394,689],{"class":419},[98,7396,422],{"class":129},[98,7398,747],{"class":133},[98,7400,697],{"class":129},[98,7402,7403,7405,7407],{"class":100,"line":497},[98,7404,443],{"class":129},[98,7406,670],{"class":413},[98,7408,433],{"class":129},[21,7410,7411,7412,7415,7416,1072],{},"When the slot pulls from a composable-level ",[14,7413,7414],{},"computed"," instead, make sure every derivation falls back to the sample while the real payload is still ",[14,7417,380],{},[89,7419,7421],{"className":91,"code":7420,"language":93,"meta":94,"style":94},"const daily = computed\u003CIDailyPoint[]>(\n  () => kpiSeries.value ?? data.value?.daily ?? SAMPLE_PERFORMANCE.daily\n);\n",[14,7422,7423,7442,7465],{"__ignoreMap":94},[98,7424,7425,7427,7430,7432,7434,7436,7439],{"class":100,"line":101},[98,7426,1120],{"class":111},[98,7428,7429],{"class":419}," daily",[98,7431,1126],{"class":111},[98,7433,6620],{"class":118},[98,7435,410],{"class":129},[98,7437,7438],{"class":122},"IDailyPoint",[98,7440,7441],{"class":129},"[]>(\n",[98,7443,7444,7447,7449,7452,7454,7457,7459,7462],{"class":100,"line":108},[98,7445,7446],{"class":129},"  () ",[98,7448,1219],{"class":111},[98,7450,7451],{"class":129}," kpiSeries.value ",[98,7453,6631],{"class":111},[98,7455,7456],{"class":129}," data.value?.daily ",[98,7458,6631],{"class":111},[98,7460,7461],{"class":419}," SAMPLE_PERFORMANCE",[98,7463,7464],{"class":129},".daily\n",[98,7466,7467],{"class":100,"line":126},[98,7468,1148],{"class":129},[36,7470,7472,7497],{"title":7471,"type":39},"Symptom to pattern-match against",[21,7473,7474,7475,7478,7479,7482,7483,7485,7486,7488,7489,7492,7493,7496],{},"A tabbed admin panel rendered its data tables as ",[25,7476,7477],{},"half-drawn skeletons on cold reload"," — only the first column had bars, the rest were blank. Warm navigation painted correctly. Cause: ",[14,7480,7481],{},"\u003Ctemplate #default>"," was ignoring the slot prop and reading the composable's ",[14,7484,376],{}," ref, which was still ",[14,7487,380],{}," during measurement, so the data-table component received ",[14,7490,7491],{},"rows=[]"," and memory snapshotted an empty table. Fix was one line per tab — ",[14,7494,7495],{},"\u003Ctemplate #default=\"{ data }\">"," — then swap the ref reference for the slot binding.",[21,7498,7499],{},"If you see first-column-only bars on refresh that disappear on warm nav, it's this bug.",[7501,7502,7503],"style",{},"html pre.shiki code .sU953, html code.shiki .sU953{--shiki-default:#6E7781;--shiki-dark:#8B949E}html pre.shiki code .sjeE4, html code.shiki .sjeE4{--shiki-default:#CF222E;--shiki-dark:#FF7B72}html pre.shiki code .sbjLL, html code.shiki .sbjLL{--shiki-default:#8250DF;--shiki-dark:#D2A8FF}html pre.shiki code .sTDnQ, html code.shiki .sTDnQ{--shiki-default:#953800;--shiki-dark:#FFA657}html pre.shiki code .s4rv2, html code.shiki .s4rv2{--shiki-default:#1F2328;--shiki-dark:#E6EDF3}html pre.shiki code .sSVrQ, html code.shiki .sSVrQ{--shiki-default:#0A3069;--shiki-dark:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sjgCt, html code.shiki .sjgCt{--shiki-default:#116329;--shiki-dark:#7EE787}html pre.shiki code .sHrmB, html code.shiki .sHrmB{--shiki-default:#0550AE;--shiki-dark:#79C0FF}html pre.shiki code .sZcZs, html code.shiki .sZcZs{--shiki-default:#82071E;--shiki-default-font-style:italic;--shiki-dark:#FFA198;--shiki-dark-font-style:italic}",{"title":94,"searchDepth":108,"depth":108,"links":7505},[7506,7510,7511,7512,7514,7516,7518,7519,7521,7522,7523,7526,7527,7531,7532,7533,7534,7538,7540,7542,7543,7547,7548,7558,7571],{"id":75,"depth":108,"text":76,"children":7507},[7508,7509],{"id":83,"depth":126,"text":84},{"id":152,"depth":126,"text":153},{"id":291,"depth":108,"text":292},{"id":363,"depth":108,"text":364},{"id":387,"depth":108,"text":7513},"Rule 1 — Always pass a sample",{"id":506,"depth":108,"text":7515},"Rule 2 — Give the skeleton a stable id",{"id":622,"depth":108,"text":7517},"Rule 3 — Destructure { data } in #default",{"id":760,"depth":108,"text":761},{"id":852,"depth":108,"text":7520},"Rule 5 — Theme to your design with \u003CAGhostSkeletonProvider>",{"id":1052,"depth":108,"text":1053},{"id":1455,"depth":108,"text":1456},{"id":1687,"depth":108,"text":1688,"children":7524},[7525],{"id":1815,"depth":126,"text":1816},{"id":1858,"depth":108,"text":1859},{"id":2047,"depth":108,"text":2048,"children":7528},[7529,7530],{"id":2098,"depth":126,"text":2099},{"id":2179,"depth":126,"text":2180},{"id":2304,"depth":108,"text":2305},{"id":2314,"depth":108,"text":2315},{"id":2530,"depth":108,"text":2531},{"id":2621,"depth":108,"text":1048,"children":7535},[7536,7537],{"id":2845,"depth":126,"text":2846},{"id":3006,"depth":126,"text":3007},{"id":3198,"depth":108,"text":7539},"\u003CAGhostSkeletonBox> — standalone bars {#standalone-box}",{"id":3273,"depth":108,"text":7541},"\u003CAGhostSkeletonSuspense> — for Suspense boundaries",{"id":3364,"depth":108,"text":3365},{"id":3480,"depth":108,"text":3481,"children":7544},[7545,7546],{"id":3494,"depth":126,"text":3495},{"id":3534,"depth":126,"text":3535},{"id":3673,"depth":108,"text":1855},{"id":3869,"depth":108,"text":3870,"children":7549},[7550,7551,7552,7553,7554,7555,7556],{"id":3890,"depth":126,"text":3891},{"id":4275,"depth":126,"text":4276},{"id":4679,"depth":126,"text":4680},{"id":5108,"depth":126,"text":5109},{"id":5524,"depth":126,"text":5525},{"id":5990,"depth":126,"text":5991},{"id":6480,"depth":126,"text":7557},"When the slot can't carry data — compose the fallback",{"id":6667,"depth":108,"text":6668,"children":7559},[7560,7562,7563,7564,7566,7568,7570],{"id":6671,"depth":126,"text":7561},"\u003CAGhostSkeleton> props",{"id":6856,"depth":126,"text":6857},{"id":6958,"depth":126,"text":6959},{"id":6990,"depth":126,"text":7565},"\u003CAGhostSkeletonProvider> props",{"id":7094,"depth":126,"text":7567},"\u003CAGhostSkeletonBox> props",{"id":7167,"depth":126,"text":7569},"\u003CAGhostSkeletonSuspense> props",{"id":7224,"depth":126,"text":7225},{"id":7298,"depth":108,"text":7572},"Thread data through the slot","A content-aware Vue 3 skeleton loader and Nuxt 3 \u002F 4 module. Lays your real component out unseen, measures its live geometry, and replays it as a pixel-faithful placeholder — no second DOM tree, no hand-authored shapes, no cumulative layout shift.","md",{"keywords":7576},[7577,7578,7579,7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,2919,2523,7593,7594,7595,7596,7597,7598,7599,7600,7601],"vue skeleton","vue skeleton loader","vue 3 skeleton","nuxt skeleton","nuxt skeleton loader","nuxt 3 skeleton","nuxt 4 skeleton","skeleton loader","skeleton screen","skeleton component","content-aware skeleton","auto skeleton","automatic skeleton","ghost loader","ghost skeleton","measured skeleton","loading placeholder","suspense skeleton","ssr skeleton","headless skeleton","cls","layout shift","nuxt module","vue 3","typescript","\u002Fui\u002Fghost-skeleton",{"title":5,"description":7573},"ui\u002Fghost-skeleton","JmWROApKSxRslrnFUQh3sL18HlQLjxTqzbT0ky4Lx5Y",1794596989178]