@wyxos/vibe 2.1.3 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -0
- package/lib/index.cjs +1 -1
- package/lib/index.js +614 -572
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,66 @@ It’s built for large, scroll-heavy media feeds and aims to stay smooth with th
|
|
|
23
23
|
```bash
|
|
24
24
|
npm i @wyxos/vibe
|
|
25
25
|
```
|
|
26
|
+
|
|
27
|
+
## Simple integration (minimal)
|
|
28
|
+
|
|
29
|
+
Minimal example with the required scrolling container CSS and a simple `getContent(page)`.
|
|
30
|
+
|
|
31
|
+
```vue
|
|
32
|
+
<script setup lang="ts">
|
|
33
|
+
import { ref } from 'vue'
|
|
34
|
+
import { Masonry, MasonryItem } from '@wyxos/vibe'
|
|
35
|
+
|
|
36
|
+
type Item = { id: string; width: number; height: number }
|
|
37
|
+
|
|
38
|
+
const items = ref<Item[]>([])
|
|
39
|
+
|
|
40
|
+
async function getContent(page: number) {
|
|
41
|
+
// Replace with your server/API call.
|
|
42
|
+
const pageSize = 20
|
|
43
|
+
const newItems: Item[] = Array.from({ length: pageSize }, (_, i) => ({
|
|
44
|
+
id: `${page}-${i}`,
|
|
45
|
+
width: 640,
|
|
46
|
+
height: 480,
|
|
47
|
+
}))
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
items: newItems,
|
|
51
|
+
nextPage: page + 1,
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<template>
|
|
57
|
+
<div class="app">
|
|
58
|
+
<Masonry class="masonry" v-model:items="items" :get-content="getContent" :page="1">
|
|
59
|
+
<MasonryItem>
|
|
60
|
+
<template #default="{ item }">
|
|
61
|
+
<div>{{ item.id }}</div>
|
|
62
|
+
</template>
|
|
63
|
+
</MasonryItem>
|
|
64
|
+
</Masonry>
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
67
|
+
|
|
68
|
+
<style>
|
|
69
|
+
.app {
|
|
70
|
+
height: 100vh;
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-direction: column;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* Required: gives the Masonry internal scroll viewport a real height */
|
|
76
|
+
.masonry {
|
|
77
|
+
flex: 1 1 auto;
|
|
78
|
+
min-height: 0;
|
|
79
|
+
}
|
|
80
|
+
</style>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
> **Warning**
|
|
84
|
+
> Each item must include `{ id, width, height }` so the layout can be calculated.
|
|
85
|
+
|
|
26
86
|
## Local library build
|
|
27
87
|
|
|
28
88
|
- JS bundles: `npm run build:lib`
|
package/lib/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),Qe={mode:"default",pageSize:20,backfillRequestDelayMs:2e3,page:1,itemWidth:300,prefetchThresholdPx:200,gapX:16,gapY:16,headerHeight:0,footerHeight:0,overscanPx:600},kt={key:0,"data-testid":"masonry-loader-spinner",class:"absolute inset-0 flex items-center justify-center"},xt={key:1,"data-testid":"masonry-loader-error",class:"absolute inset-0 flex flex-col items-center justify-center gap-2 p-3"},bt=["src","width","height","alt"],Bt=["poster"],Mt=["src"],We=e.defineComponent({__name:"MasonryLoader",props:{item:{},timeoutMs:{default:15e3}},emits:["success","error"],setup(l,{emit:g}){const u=l,s=g,c=e.ref(null),p=e.ref(!1),f=e.ref(!1),i=e.ref(!1),k=e.ref(0),x=e.computed(()=>{const E=u.item?.width,S=u.item?.height;return{aspectRatio:`${E} / ${S}`}}),B=e.computed(()=>u.item?.type==="image");let M=null,I=null;function F(){I!=null&&(window.clearTimeout(I),I=null)}function b(){F();const E=typeof u.timeoutMs=="number"&&Number.isFinite(u.timeoutMs)?u.timeoutMs:0;E<=0||(I=window.setTimeout(()=>{p.value&&(f.value||i.value||C(new Error("timeout")))},E))}function _(){p.value||(p.value=!0,f.value=!1,i.value=!1,b())}e.onMounted(()=>{if(typeof IntersectionObserver>"u"){_();return}M=new IntersectionObserver(E=>{for(const S of E)if(S.isIntersecting&&!((S.intersectionRatio??0)<.5)){_(),M?.disconnect(),M=null;return}},{threshold:[0,.5,1]}),c.value&&M.observe(c.value)}),e.onUnmounted(()=>{M?.disconnect(),M=null,F()});function N(){f.value||(f.value=!0,i.value=!1,F(),s("success",u.item))}function C(E){i.value||(f.value=!1,i.value=!0,F(),s("error",{item:u.item,error:E}))}function T(){p.value&&(f.value=!1,i.value=!1,k.value+=1,b())}return(E,S)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"rootEl",ref:c,class:"relative bg-slate-100",style:e.normalizeStyle(x.value)},[p.value&&!f.value&&!i.value?(e.openBlock(),e.createElementBlock("div",kt,S[2]||(S[2]=[e.createElementVNode("svg",{class:"h-5 w-5 animate-spin text-slate-500",viewBox:"0 0 24 24","aria-hidden":"true"},[e.createElementVNode("circle",{class:"opacity-25",cx:"12",cy:"12",r:"10",fill:"none",stroke:"currentColor","stroke-width":"4"}),e.createElementVNode("path",{class:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 0 1 8-8v4a4 4 0 0 0-4 4H4z"})],-1)]))):p.value&&i.value?(e.openBlock(),e.createElementBlock("div",xt,[S[3]||(S[3]=e.createElementVNode("p",{class:"text-center text-xs font-medium text-red-700"},"Failed to load",-1)),e.createElementVNode("button",{type:"button","data-testid":"masonry-loader-retry",class:"inline-flex items-center rounded-md border border-slate-200 bg-white px-2 py-1 text-xs font-medium text-slate-700",onClick:T}," Retry ")])):e.createCommentVNode("",!0),p.value&&B.value&&!i.value?(e.openBlock(),e.createElementBlock("img",{key:u.item.id+":img:"+k.value,class:e.normalizeClass(["h-full w-full object-cover transition-opacity duration-300",f.value?"opacity-100":"opacity-0"]),src:u.item.preview,width:u.item.width,height:u.item.height,loading:"lazy",alt:u.item.id,onLoad:N,onError:S[0]||(S[0]=z=>C(z))},null,42,bt)):p.value&&!i.value?(e.openBlock(),e.createElementBlock("video",{key:u.item.id+":vid:"+k.value,class:e.normalizeClass(["h-full w-full object-cover transition-opacity duration-300",f.value?"opacity-100":"opacity-0"]),poster:u.item.preview,controls:"",preload:"metadata",onLoadedmetadata:N,onError:S[1]||(S[1]=z=>C(z))},[e.createElementVNode("source",{src:u.item.original,type:"video/mp4"},null,8,Mt)],42,Bt)):e.createCommentVNode("",!0)],4))}}),Ze=Symbol("masonryItemRegistry");function St(l,g){return!l||l<=0||!g||g<=0?1:Math.max(1,Math.floor(l/g))}function It(l,g,u,s=0){if(!l||l<=0||!g||g<=0)return u;const c=typeof s=="number"&&s>0?s:0,p=Math.max(0,g-1)*c,f=l-p;return!f||f<=0?u:f/g}function Et(l,g){const u=l?.width,s=l?.height;return typeof u=="number"&&typeof s=="number"&&u>0&&s>0?s/u*g:g}function et(l){return Number.isFinite(l)&&l>0?Math.floor(l):1}function pe(l){return Number.isFinite(l)&&l>0?Math.floor(l):0}function Nt(l){async function g(s){const c=pe(s);if(c<=0)return;l.stats.value={...l.stats.value,cooldownMsTotal:c,cooldownMsRemaining:c};const p=Date.now(),f=100;await new Promise(i=>{const k=setInterval(()=>{const x=Date.now()-p,B=Math.max(0,c-x);l.stats.value={...l.stats.value,cooldownMsTotal:c,cooldownMsRemaining:B},B<=0&&(clearInterval(k),i())},f)})}async function u(s){const c=et(l.getPageSize()),p=l.isEnabled(),f=pe(l.getRequestDelayMs()),i=[];let k=0;l.buffer.value.length&&(k=l.buffer.value.length,i.push(...l.buffer.value),l.buffer.value=[]),l.stats.value={...l.stats.value,enabled:p,isBackfillActive:!1,isRequestInFlight:!1,requestPage:null,cooldownMsTotal:f,cooldownMsRemaining:0,progress:{collected:0,target:0},pageSize:c,bufferSize:0};const x=[];let B=s,M=0,I=!1;for(;i.length<c&&B!=null;){const _=B;I&&(l.stats.value={...l.stats.value,enabled:p,isBackfillActive:!0,isRequestInFlight:!0,requestPage:_,progress:{collected:Math.min(i.length,c),target:c},cooldownMsTotal:f,cooldownMsRemaining:0,pageSize:c});const N=await l.getContent(_);x.push(_),I&&(l.stats.value={...l.stats.value,enabled:p,isBackfillActive:!0,isRequestInFlight:!1,requestPage:null}),M+=N.items.length,l.markEnterFromLeft(N.items),i.push(...N.items),B=N.nextPage,!I&&i.length<c&&B!=null?(I=!0,l.stats.value={...l.stats.value,enabled:p,isBackfillActive:!0,isRequestInFlight:!1,requestPage:null,progress:{collected:Math.min(i.length,c),target:c},cooldownMsTotal:f,cooldownMsRemaining:0,pageSize:c}):I&&(l.stats.value={...l.stats.value,enabled:p,isBackfillActive:!0,progress:{collected:Math.min(i.length,c),target:c}}),I&&i.length<c&&B!=null&&await g(f)}const F=i.slice(0,c),b=i.slice(c);return l.buffer.value=b,l.stats.value={...l.stats.value,enabled:p,isBackfillActive:!1,isRequestInFlight:!1,requestPage:null,progress:{collected:0,target:0},cooldownMsTotal:f,cooldownMsRemaining:0,pageSize:c,bufferSize:b.length,lastBatch:{startPage:s,pages:x,usedFromBuffer:k,fetchedFromNetwork:M,collectedTotal:i.length,emitted:F.length,carried:b.length},totals:{pagesFetched:l.stats.value.totals.pagesFetched+x.length,itemsFetchedFromNetwork:l.stats.value.totals.itemsFetchedFromNetwork+M}},{batchItems:F,pages:x,nextPage:B}}return{loadBackfillBatch:u}}function Ft(l){const g=l.columnCount,u=l.columnWidth,s=l.gapX,c=l.gapY,p=l.headerHeight,f=l.footerHeight,i=l.bucketPx,k=Array.from({length:g},()=>0),x=new Array(l.items.length),B=new Array(l.items.length),M=new Map,I=new Map;let F=0;for(let b=0;b<l.items.length;b+=1){const _=l.items[b];_?.id&&I.set(_.id,b);let N=0;for(let A=1;A<k.length;A+=1)k[A]<k[N]&&(N=A);const C=N*(u+s),T=k[N],E=Et(_,u)+p+f;x[b]={x:C,y:T},B[b]=E,k[N]=T+E+c,F=Math.max(F,T+E);const S=Math.floor(T/i),z=Math.floor((T+E)/i);for(let A=S;A<=z;A+=1){const K=M.get(A);K?K.push(b):M.set(A,[b])}}return{positions:x,heights:B,buckets:M,contentHeight:F,indexById:I}}function Pt(l){const g=l.itemCount;if(!g)return[];if(l.viewportHeight<=0)return Array.from({length:g},(k,x)=>x);const u=Math.max(0,l.scrollTop-l.overscanPx),s=l.scrollTop+l.viewportHeight+l.overscanPx,c=Math.floor(u/l.bucketPx),p=Math.floor(s/l.bucketPx),f=new Set;for(let k=c;k<=p;k+=1){const x=l.buckets.get(k);if(x)for(const B of x)f.add(B)}const i=Array.from(f);return i.sort((k,x)=>k-x),i}const Tt={class:"hidden"},Rt={key:0,class:"flex h-full items-center justify-center"},_t={key:1,class:"text-sm font-medium text-red-700"},Ct={class:"mt-4 pb-2 text-center text-xs text-slate-600"},At={key:0,class:"inline-flex items-center justify-center gap-2"},Vt={key:1},zt={key:2},Lt=200,Ue=600,Ge=300,Ke=600,Je=600,Ht=5,qt=1e3,tt=e.defineComponent({inheritAttrs:!1,__name:"Masonry",props:e.mergeDefaults({getContent:{},mode:{},pageSize:{},backfillRequestDelayMs:{},items:{},page:{},restoredPagesLoaded:{},itemWidth:{},prefetchThresholdPx:{},gapX:{},gapY:{},headerHeight:{},footerHeight:{},overscanPx:{}},Qe),emits:["update:items"],setup(l,{expose:g,emit:u}){const s=l,c=u,p=e.useAttrs(),f=e.defineComponent({name:"SlotRenderer",props:{slotFn:{type:Function,required:!1},slotProps:{type:Object,required:!0}},setup(t){return()=>{const o=t.slotFn;return o?o(t.slotProps):null}}}),i=e.shallowRef(null);e.provide(Ze,t=>{i.value||(i.value=t)}),e.onMounted(()=>{if(!i.value)throw new Error("[Masonry] Missing <MasonryItem> definition. Add <MasonryItem> as a child of <Masonry>.")});const k=e.computed(()=>{const{class:t,...o}=p;return o}),x=e.ref(null),B=e.ref(0),M=e.ref(0),I=e.ref(0);let F;const b=e.computed(()=>s.gapX),_=e.computed(()=>s.gapY);function N(t){if(!t)return 0;const o=Math.max(0,b.value);return Math.max(0,t.clientWidth-o)}const C=e.computed(()=>s.headerHeight),T=e.computed(()=>s.footerHeight),E=e.computed(()=>i.value?.header),S=e.computed(()=>i.value?.footer),z=e.computed(()=>i.value?.default),A=e.computed(()=>!!E.value),K=e.computed(()=>!!S.value),ye=e.computed(()=>{if(C.value>0)return{height:`${C.value}px`}}),we=e.computed(()=>{if(T.value>0)return{height:`${T.value}px`}}),J=e.ref([]),se=e.ref([]),ke=e.ref(new Map),xe=e.ref(0),oe=e.ref(new Map);function be(t){const o=typeof t=="number"&&Number.isFinite(t)?t:0;return He.value+Math.max(0,o)}const $=e.ref(new Set),Y=e.ref(new Set),le=new Set,ae=e.ref(new Map),H=e.ref(new Set),q=e.ref([]);function ot(t){const o=ae.value.get(t);return o||{dx:0,dy:0}}function lt(t){if(Y.value.has(t))return`transform ${Ke}ms ease-out`;if(H.value.has(t))return`transform ${Ge}ms ease-out`}function at(t){const n=d.value[t]?.id,a=J.value[t]??{x:0,y:0},r=se.value[t]??0,m=r>0?r:te.value,v=a.x,y=n&&$.value.has(n)?be(m):a.y,w=n?ot(n):{dx:0,dy:0};return`translate3d(${v+w.dx}px,${y+w.dy}px,0)`}function X(t){(typeof requestAnimationFrame=="function"?requestAnimationFrame:n=>setTimeout(()=>n(0),0))(()=>t())}function rt(t){X(()=>X(t))}const Be=new Set;function Me(t){return typeof t=="number"&&Number.isFinite(t)&&t>0}function ie(t){if(!Array.isArray(t)||t.length===0)return;const o=new Set($.value);let n=!1;for(const a of t){const r=a?.id;if(r){if(!Be.has(r)){const m=a?.width,v=a?.height;(!Me(m)||!Me(v))&&(Be.add(r),console.warn(`[Masonry] Item "${r}" has invalid dimensions (width=${String(m)}, height=${String(v)}); layout expects { id, width, height }.`))}o.has(r)||(o.add(r),n=!0)}}n&&($.value=o)}function Se(){const t=new Map;for(const o of he.value){const a=d.value[o]?.id;if(!a)continue;const r=J.value[o];r&&t.set(a,{x:r.x,y:r.y})}return t}function Ie(t,o){if(!t.size)return;const n=new Map,a=[];for(const[m,v]of t.entries()){if(o?.has(m))continue;const y=oe.value.get(m);if(y==null)continue;const w=J.value[y];if(!w)continue;const h=v.x-w.x,V=v.y-w.y;(h||V)&&(n.set(m,{dx:h,dy:V}),a.push(m))}if(!n.size)return;ae.value=n;const r=new Set(H.value);for(const m of a)r.delete(m);H.value=r,X(()=>{H.value=new Set([...H.value,...a]),X(()=>{ae.value=new Map})}),setTimeout(()=>{const m=new Set(H.value);for(const v of a)m.delete(v);H.value=m},Ge)}const Q=e.ref(!0),Z=e.ref(!1),j=e.ref("");let P=0;function Ee(t){return t instanceof Error&&t.name==="AbortError"}function Ne(){const t=new Error("aborted");return t.name="AbortError",t}function st(t){return new Promise(o=>setTimeout(o,t))}async function Fe(t,o){let n=0;for(;;){if(o!==P)throw Ne();try{return await s.getContent(t)}catch(a){if(o!==P)throw Ne();if(n>=Ht)throw a;n+=1,await st(n*qt)}}}const L=e.ref([]),Pe=e.ref([]),ue=e.ref([]),R=e.ref(s.page),ce=e.ref([]);let W=null,U=null,re=0;function it(t){let o=-1;for(const n of t){const a=n?.originalIndex;ee(a)&&a>o&&(o=a)}re=o+1}function G(t){for(const o of t)!o||typeof o!="object"||o.id&&o.originalIndex==null&&(o.originalIndex=re,re+=1)}const D=new Map,O=[];function ee(t){return typeof t=="number"&&Number.isFinite(t)}function ut(t,o){if(!o.length)return t;const n=new Set;for(const v of t){const y=v?.id;y&&n.add(y)}const a=[];for(const v of o){const y=v?.id;y&&(n.has(y)||(a.push(v),n.add(y)))}if(!a.length)return t;const r=a.slice().sort((v,y)=>{const w=ee(v.originalIndex)?v.originalIndex:Number.POSITIVE_INFINITY,h=ee(y.originalIndex)?y.originalIndex:Number.POSITIVE_INFINITY;return w-h}),m=t.slice();for(const v of r){const y=v.originalIndex;if(!ee(y)){m.push(v);continue}let w=0,h=m.length;for(;w<h;){const V=w+h>>1,ne=m[V]?.originalIndex;(ee(ne)?ne:Number.POSITIVE_INFINITY)<=y?w=V+1:h=V}m.splice(w,0,v)}return m}async function Te(t){if(!t.length)return;ie(t);const o=Se();d.value=ut(d.value,t),await e.nextTick(),Ie(o)}async function Re(t){const n=(Array.isArray(t)?t:[t]).map(me).filter(Boolean);if(!n.length)return;const a=[];for(const r of n){const m=D.get(r);m&&a.push(m)}if(a.length){await Te(a);for(const r of a)r?.id&&D.delete(r.id)}}async function _e(){const t=O.pop();if(!t?.length)return;const o=[];for(const n of t){const a=D.get(n);a&&o.push(a)}if(o.length){await Te(o);for(const n of o)n?.id&&D.delete(n.id)}}async function ct(t){return Re(t)}async function ft(){return _e()}function Ce(t){const n=(Array.isArray(t)?t:[t]).map(me).filter(Boolean);if(!n.length)return;const a=new Set(n);for(const r of a)D.delete(r);for(let r=O.length-1;r>=0;r-=1){const v=O[r].filter(y=>!a.has(y));v.length?O[r]=v:O.splice(r,1)}}const fe=e.shallowRef({enabled:!1,isBackfillActive:!1,isRequestInFlight:!1,requestPage:null,progress:{collected:0,target:0},cooldownMsRemaining:0,cooldownMsTotal:2e3,pageSize:20,bufferSize:0,lastBatch:null,totals:{pagesFetched:0,itemsFetchedFromNetwork:0}}),Ae=Nt({getContent:t=>Fe(t,P),markEnterFromLeft:ie,buffer:ce,stats:fe,isEnabled:()=>s.mode==="backfill",getPageSize:()=>s.pageSize,getRequestDelayMs:()=>s.backfillRequestDelayMs}),de=e.computed(()=>s.items!==void 0);e.watch(()=>s.items,t=>{de.value&&(ue.value=Array.isArray(t)?t:[])},{immediate:!0});const d=e.computed({get(){return de.value?ue.value:Pe.value},set(t){de.value?(ue.value=t,c("update:items",t)):Pe.value=t}});async function Ve(t){const o=await Fe(t,P);return G(o.items),ie(o.items),{items:o.items,nextPage:o.nextPage}}function me(t){return t?typeof t=="string"?t:t?.id:null}async function ze(t){const n=(Array.isArray(t)?t:[t]).map(me).filter(Boolean);if(!n.length)return;const a=new Set(n),r=[];for(const w of a){const h=oe.value.get(w);if(h==null)continue;const V=d.value[h];V&&(D.set(w,V),r.push(w))}r.length&&O.push(r);const m=Se(),v=te.value,y=[];for(const w of a){const h=oe.value.get(w);if(h==null)continue;const V=d.value[h];if(!V)continue;const ne=J.value[h]??{x:0,y:0},je=se.value[h]??v;y.push({id:w,item:V,fromX:ne.x,fromY:ne.y,width:v,height:je,leaving:!0})}if(y.length&&(q.value=[...q.value,...y]),d.value=d.value.filter(w=>{const h=w?.id;return!h||!a.has(h)}),await e.nextTick(),Ie(m,a),y.length){const w=new Set(y.map(h=>h.id));X(()=>{q.value=q.value.map(h=>w.has(h.id)?{...h,leaving:!1}:h),setTimeout(()=>{q.value=q.value.filter(h=>!w.has(h.id))},Je)})}}async function ve(t){return ze(t)}g({remove:ze,restore:ct,undo:ft,forget:Ce,pagesLoaded:L,nextPage:R,restoreRemoved:Re,undoLastRemoval:_e,forgetRemoved:Ce,backfillStats:fe});function Le(){const t=Ft({items:d.value,columnCount:ge.value,columnWidth:te.value,gapX:b.value,gapY:_.value,headerHeight:C.value,footerHeight:T.value,bucketPx:Ue});J.value=t.positions,se.value=t.heights,ke.value=t.buckets,xe.value=t.contentHeight,oe.value=t.indexById}const He=e.computed(()=>Math.max(xe.value,M.value)+Lt),he=e.computed(()=>Pt({itemCount:d.value.length,viewportHeight:M.value,scrollTop:I.value,overscanPx:s.overscanPx,bucketPx:Ue,buckets:ke.value}));e.watch(he,t=>{if(!t?.length)return;const o=[];for(const n of t){const a=d.value[n]?.id;a&&$.value.has(a)&&(le.has(a)||(le.add(a),o.push(a)))}o.length&&(X(()=>{const n=new Set(Y.value);for(const a of o)n.add(a);Y.value=n}),rt(()=>{const n=new Set($.value);for(const a of o)n.delete(a);$.value=n,setTimeout(()=>{const a=new Set(Y.value);for(const r of o)a.delete(r),le.delete(r);Y.value=a},Ke)}))},{flush:"post"});async function dt(){if(W)return W;if(Q.value||Z.value||s.mode!=="backfill"&&R.value==null||s.mode==="backfill"&&R.value==null&&ce.value.length===0)return;const t=P;let o=null;return o=(async()=>{try{if(Z.value=!0,j.value="",s.mode==="backfill"){const r=await Ae.loadBackfillBatch(R.value);if(t!==P)return;r.pages.length&&(L.value=[...L.value,...r.pages]),G(r.batchItems),d.value=[...d.value,...r.batchItems],R.value=r.nextPage;return}const n=R.value;if(n==null)return;const a=await Ve(n);if(t!==P)return;L.value=[...L.value,n],G(a.items),d.value=[...d.value,...a.items],R.value=a.nextPage}catch(n){if(t!==P||Ee(n))return;j.value=n instanceof Error?n.message:String(n)}finally{t===P&&(Z.value=!1),W===o&&(W=null)}})(),W=o,o}function mt(){const t=x.value;if(!t)return;I.value=t.scrollTop,M.value=t.clientHeight,t.scrollHeight-(t.scrollTop+t.clientHeight)<=s.prefetchThresholdPx&&dt()}function qe(){return x.value}function $e(t){B.value=N(t),M.value=t.clientHeight}function vt(){typeof ResizeObserver>"u"||(F=new ResizeObserver(()=>{const t=qe();t&&$e(t)}))}function ht(){return{enabled:s.mode==="backfill",isBackfillActive:!1,isRequestInFlight:!1,requestPage:null,progress:{collected:0,target:0},cooldownMsRemaining:0,cooldownMsTotal:pe(s.backfillRequestDelayMs),pageSize:et(s.pageSize),bufferSize:0,lastBatch:null,totals:{pagesFetched:0,itemsFetchedFromNetwork:0}}}function De(){P+=1,W=null,U=null,re=0,D.clear(),O.length=0,$.value=new Set,Y.value=new Set,le.clear(),ae.value=new Map,H.value=new Set,q.value=[],L.value=[],R.value=null,ce.value=[],fe.value=ht(),Q.value=!0,Z.value=!1,j.value=""}function Oe(t){De(),d.value=[],R.value=t}function gt(t){const o=Array.isArray(t)?t:[t],n=[],a=new Set;for(const r of o){if(r==null)continue;const m=typeof r=="string"?`s:${r}`:`n:${String(r)}`;a.has(m)||(a.add(m),n.push(r))}return n}function pt(t){const o=[];for(const n of t){if(typeof n=="number"&&Number.isFinite(n)){o.push(n);continue}if(typeof n=="string"){const a=Number.parseInt(n,10);Number.isFinite(a)&&o.push(a)}}return o.length?Math.max(...o)+1:null}function Ye(t){De();const o=gt(t);L.value=o,R.value=pt(o),Q.value=!1,it(d.value),G(d.value)}async function Xe(t){if(U)return U;const o=P;let n=null;return n=(async()=>{try{if(s.mode==="backfill"){const a=await Ae.loadBackfillBatch(t);if(o!==P)return;L.value=a.pages.length?a.pages:[t],G(a.batchItems),d.value=a.batchItems,R.value=a.nextPage}else{const a=await Ve(t);if(o!==P)return;L.value=[t],G(a.items),d.value=a.items,R.value=a.nextPage}}catch(a){if(o!==P||Ee(a))return;j.value=a instanceof Error?a.message:String(a)}finally{o===P&&(Q.value=!1),U===n&&(U=null)}})(),U=n,n}function yt(){const t=qe();t&&($e(t),I.value=t.scrollTop,F?.observe(t))}e.onMounted(async()=>{if(vt(),yt(),s.restoredPagesLoaded!=null){Ye(s.restoredPagesLoaded);return}Oe(s.page),await Xe(s.page)}),e.onUnmounted(()=>{F?.disconnect()}),e.watch(()=>s.page,async t=>{s.restoredPagesLoaded==null&&(Oe(t),await Xe(t))}),e.watch(()=>s.restoredPagesLoaded,t=>{t&&Ye(t)}),e.watch(b,()=>{const t=x.value;t&&(B.value=N(t))},{immediate:!1});const ge=e.computed(()=>St(B.value,s.itemWidth)),te=e.computed(()=>It(B.value,ge.value,s.itemWidth,b.value));e.watch([ge,te,b,_,C,T],()=>{Le()},{immediate:!0}),e.watch(()=>[d.value,d.value.length],()=>Le(),{immediate:!0});const wt=e.computed(()=>["mt-8 flex min-h-0 flex-1 flex-col rounded-2xl border border-slate-200/70 bg-white/70 p-5 shadow-sm backdrop-blur",p.class]);return(t,o)=>(e.openBlock(),e.createElementBlock("section",e.mergeProps(k.value,{class:wt.value}),[e.createElementVNode("div",Tt,[e.renderSlot(t.$slots,"default")]),e.createElementVNode("div",{ref_key:"scrollViewportRef",ref:x,"data-testid":"items-scroll-container",class:"mt-4 min-h-0 flex-1 overflow-auto",style:e.normalizeStyle({paddingRight:b.value+"px"}),onScroll:mt},[Q.value?(e.openBlock(),e.createElementBlock("div",Rt,o[0]||(o[0]=[e.createElementVNode("div",{class:"inline-flex items-center gap-3 text-sm text-slate-600"},[e.createElementVNode("svg",{class:"h-5 w-5 animate-spin text-slate-500",viewBox:"0 0 24 24","aria-hidden":"true"},[e.createElementVNode("circle",{class:"opacity-25",cx:"12",cy:"12",r:"10",fill:"none",stroke:"currentColor","stroke-width":"4"}),e.createElementVNode("path",{class:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 0 1 8-8v4a4 4 0 0 0-4 4H4z"})]),e.createElementVNode("span",null,"Loading…")],-1)]))):j.value?(e.openBlock(),e.createElementBlock("p",_t,"Error: "+e.toDisplayString(j.value),1)):(e.openBlock(),e.createElementBlock("div",{key:2,class:"relative",style:e.normalizeStyle({height:He.value+"px"})},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(he.value,n=>(e.openBlock(),e.createElementBlock("article",{key:d.value[n].id,"data-testid":"item-card",class:"absolute overflow-hidden rounded-xl border border-slate-200/60 bg-white shadow-sm",style:e.normalizeStyle({width:te.value+"px",transition:lt(d.value[n].id),transform:at(n)})},[A.value||C.value>0?(e.openBlock(),e.createElementBlock("div",{key:0,"data-testid":"item-header-container",class:"w-full",style:e.normalizeStyle(ye.value)},[e.createVNode(e.unref(f),{"slot-fn":E.value,"slot-props":{item:d.value[n],remove:()=>ve(d.value[n])}},null,8,["slot-fn","slot-props"])],4)):e.createCommentVNode("",!0),z.value?(e.openBlock(),e.createBlock(e.unref(f),{key:1,"slot-fn":z.value,"slot-props":{item:d.value[n],remove:()=>ve(d.value[n])}},null,8,["slot-fn","slot-props"])):(e.openBlock(),e.createBlock(We,{key:2,item:d.value[n]},null,8,["item"])),K.value||T.value>0?(e.openBlock(),e.createElementBlock("div",{key:3,"data-testid":"item-footer-container",class:"w-full",style:e.normalizeStyle(we.value)},[e.createVNode(e.unref(f),{"slot-fn":S.value,"slot-props":{item:d.value[n],remove:()=>ve(d.value[n])}},null,8,["slot-fn","slot-props"])],4)):e.createCommentVNode("",!0)],4))),128)),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(q.value,n=>(e.openBlock(),e.createElementBlock("article",{key:n.id+":leaving","data-testid":"item-card-leaving",class:"pointer-events-none absolute overflow-hidden rounded-xl border border-slate-200/60 bg-white shadow-sm",style:e.normalizeStyle({width:n.width+"px",transition:"transform "+Je+"ms ease-out",transform:n.leaving?"translate3d("+n.fromX+"px,"+n.fromY+"px,0)":"translate3d("+n.fromX+"px,"+be(n.height)+"px,0)"})},[A.value||C.value>0?(e.openBlock(),e.createElementBlock("div",{key:0,"data-testid":"item-header-container",class:"w-full",style:e.normalizeStyle(ye.value)},[e.createVNode(e.unref(f),{"slot-fn":E.value,"slot-props":{item:n.item,remove:()=>{}}},null,8,["slot-fn","slot-props"])],4)):e.createCommentVNode("",!0),z.value?(e.openBlock(),e.createBlock(e.unref(f),{key:1,"slot-fn":z.value,"slot-props":{item:n.item,remove:()=>{}}},null,8,["slot-fn","slot-props"])):(e.openBlock(),e.createBlock(We,{key:2,item:n.item},null,8,["item"])),K.value||T.value>0?(e.openBlock(),e.createElementBlock("div",{key:3,"data-testid":"item-footer-container",class:"w-full",style:e.normalizeStyle(we.value)},[e.createVNode(e.unref(f),{"slot-fn":S.value,"slot-props":{item:n.item,remove:()=>{}}},null,8,["slot-fn","slot-props"])],4)):e.createCommentVNode("",!0)],4))),128))],4)),e.createElementVNode("div",Ct,[Z.value?(e.openBlock(),e.createElementBlock("span",At,o[1]||(o[1]=[e.createElementVNode("svg",{class:"h-4 w-4 animate-spin text-slate-500",viewBox:"0 0 24 24","aria-hidden":"true"},[e.createElementVNode("circle",{class:"opacity-25",cx:"12",cy:"12",r:"10",fill:"none",stroke:"currentColor","stroke-width":"4"}),e.createElementVNode("path",{class:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 0 1 8-8v4a4 4 0 0 0-4 4H4z"})],-1),e.createElementVNode("span",null,"Loading more…",-1)]))):R.value==null?(e.openBlock(),e.createElementBlock("span",Vt,"End of list")):(e.openBlock(),e.createElementBlock("span",zt,"Scroll to load page "+e.toDisplayString(R.value),1))])],36)],16))}}),nt=e.defineComponent({name:"MasonryItem",setup(l,{slots:g}){const u=e.inject(Ze,null);return u?(u({header:g.header,default:g.default,footer:g.footer}),()=>null):()=>null}}),$t={install(l){l.component("Masonry",tt),l.component("MasonryItem",nt)}};exports.Masonry=tt;exports.MasonryItem=nt;exports.VibePlugin=$t;exports.masonryDefaults=Qe;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),ut={mode:"default",pageSize:20,backfillRequestDelayMs:2e3,page:1,itemWidth:300,prefetchThresholdPx:200,gapX:16,gapY:16,headerHeight:0,footerHeight:0,overscanPx:600},Tt={key:0,"data-testid":"masonry-loader-spinner",class:"absolute inset-0 flex items-center justify-center"},Rt={key:1,"data-testid":"masonry-loader-error",class:"absolute inset-0 flex flex-col items-center justify-center gap-2 p-3"},At=["src","width","height","alt"],_t=["poster"],Ct=["src"],ot=e.defineComponent({__name:"MasonryLoader",props:{item:{},timeoutMs:{default:15e3}},emits:["success","error"],setup(l,{emit:p}){const f=l,r=p,u=e.ref(null),d=e.ref(!1),c=e.ref(!1),i=e.ref(!1),y=e.ref(0),x=e.computed(()=>{const S=f.item?.width,M=f.item?.height;return{aspectRatio:`${S} / ${M}`}}),b=e.computed(()=>f.item?.type==="image");let B=null,I=null;function N(){I!=null&&(window.clearTimeout(I),I=null)}function E(){N();const S=typeof f.timeoutMs=="number"&&Number.isFinite(f.timeoutMs)?f.timeoutMs:0;S<=0||(I=window.setTimeout(()=>{d.value&&(c.value||i.value||q(new Error("timeout")))},S))}function A(){d.value||(d.value=!0,c.value=!1,i.value=!1,E())}e.onMounted(()=>{if(typeof IntersectionObserver>"u"){A();return}B=new IntersectionObserver(S=>{for(const M of S)if(M.isIntersecting&&!((M.intersectionRatio??0)<.5)){A(),B?.disconnect(),B=null;return}},{threshold:[0,.5,1]}),u.value&&B.observe(u.value)}),e.onUnmounted(()=>{B?.disconnect(),B=null,N()});function F(){c.value||(c.value=!0,i.value=!1,N(),r("success",f.item))}function q(S){i.value||(c.value=!1,i.value=!0,N(),r("error",{item:f.item,error:S}))}function V(){d.value&&(c.value=!1,i.value=!1,y.value+=1,E())}return(S,M)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"rootEl",ref:u,class:"relative bg-slate-100",style:e.normalizeStyle(x.value)},[d.value&&!c.value&&!i.value?(e.openBlock(),e.createElementBlock("div",Tt,M[2]||(M[2]=[e.createElementVNode("svg",{class:"h-5 w-5 animate-spin text-slate-500",viewBox:"0 0 24 24","aria-hidden":"true"},[e.createElementVNode("circle",{class:"opacity-25",cx:"12",cy:"12",r:"10",fill:"none",stroke:"currentColor","stroke-width":"4"}),e.createElementVNode("path",{class:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 0 1 8-8v4a4 4 0 0 0-4 4H4z"})],-1)]))):d.value&&i.value?(e.openBlock(),e.createElementBlock("div",Rt,[M[3]||(M[3]=e.createElementVNode("p",{class:"text-center text-xs font-medium text-red-700"},"Failed to load",-1)),e.createElementVNode("button",{type:"button","data-testid":"masonry-loader-retry",class:"inline-flex items-center rounded-md border border-slate-200 bg-white px-2 py-1 text-xs font-medium text-slate-700",onClick:V}," Retry ")])):e.createCommentVNode("",!0),d.value&&b.value&&!i.value?(e.openBlock(),e.createElementBlock("img",{key:f.item.id+":img:"+y.value,class:e.normalizeClass(["h-full w-full object-cover transition-opacity duration-300",c.value?"opacity-100":"opacity-0"]),src:f.item.preview,width:f.item.width,height:f.item.height,loading:"lazy",alt:f.item.id,onLoad:F,onError:M[0]||(M[0]=C=>q(C))},null,42,At)):d.value&&!i.value?(e.openBlock(),e.createElementBlock("video",{key:f.item.id+":vid:"+y.value,class:e.normalizeClass(["h-full w-full object-cover transition-opacity duration-300",c.value?"opacity-100":"opacity-0"]),poster:f.item.preview,controls:"",preload:"metadata",onLoadedmetadata:F,onError:M[1]||(M[1]=C=>q(C))},[e.createElementVNode("source",{src:f.item.original,type:"video/mp4"},null,8,Ct)],42,_t)):e.createCommentVNode("",!0)],4))}}),ct=Symbol("masonryItemRegistry");function Vt(l,p){return!l||l<=0||!p||p<=0?1:Math.max(1,Math.floor(l/p))}function zt(l,p,f,r=0){if(!l||l<=0||!p||p<=0)return f;const u=typeof r=="number"&&r>0?r:0,d=Math.max(0,p-1)*u,c=l-d;return!c||c<=0?f:c/p}function Lt(l,p){const f=l?.width,r=l?.height;return typeof f=="number"&&typeof r=="number"&&f>0&&r>0?r/f*p:p}function ft(l){return Number.isFinite(l)&&l>0?Math.floor(l):1}function Be(l){return Number.isFinite(l)&&l>0?Math.floor(l):0}function Ht(l){async function p(r){const u=Be(r);if(u<=0)return;l.stats.value={...l.stats.value,cooldownMsTotal:u,cooldownMsRemaining:u};const d=Date.now(),c=100;await new Promise(i=>{const y=setInterval(()=>{const x=Date.now()-d,b=Math.max(0,u-x);l.stats.value={...l.stats.value,cooldownMsTotal:u,cooldownMsRemaining:b},b<=0&&(clearInterval(y),i())},c)})}async function f(r){const u=ft(l.getPageSize()),d=l.isEnabled(),c=Be(l.getRequestDelayMs()),i=[];let y=0;l.buffer.value.length&&(y=l.buffer.value.length,i.push(...l.buffer.value),l.buffer.value=[]),l.stats.value={...l.stats.value,enabled:d,isBackfillActive:!1,isRequestInFlight:!1,requestPage:null,cooldownMsTotal:c,cooldownMsRemaining:0,progress:{collected:0,target:0},pageSize:u,bufferSize:0};const x=[];let b=r,B=0,I=!1;for(;i.length<u&&b!=null;){const A=b;I&&(l.stats.value={...l.stats.value,enabled:d,isBackfillActive:!0,isRequestInFlight:!0,requestPage:A,progress:{collected:Math.min(i.length,u),target:u},cooldownMsTotal:c,cooldownMsRemaining:0,pageSize:u});const F=await l.getContent(A);x.push(A),I&&(l.stats.value={...l.stats.value,enabled:d,isBackfillActive:!0,isRequestInFlight:!1,requestPage:null}),B+=F.items.length,l.markEnterFromLeft(F.items),i.push(...F.items),b=F.nextPage,!I&&i.length<u&&b!=null?(I=!0,l.stats.value={...l.stats.value,enabled:d,isBackfillActive:!0,isRequestInFlight:!1,requestPage:null,progress:{collected:Math.min(i.length,u),target:u},cooldownMsTotal:c,cooldownMsRemaining:0,pageSize:u}):I&&(l.stats.value={...l.stats.value,enabled:d,isBackfillActive:!0,progress:{collected:Math.min(i.length,u),target:u}}),I&&i.length<u&&b!=null&&await p(c)}const N=i.slice(0,u),E=i.slice(u);return l.buffer.value=E,l.stats.value={...l.stats.value,enabled:d,isBackfillActive:!1,isRequestInFlight:!1,requestPage:null,progress:{collected:0,target:0},cooldownMsTotal:c,cooldownMsRemaining:0,pageSize:u,bufferSize:E.length,lastBatch:{startPage:r,pages:x,usedFromBuffer:y,fetchedFromNetwork:B,collectedTotal:i.length,emitted:N.length,carried:E.length},totals:{pagesFetched:l.stats.value.totals.pagesFetched+x.length,itemsFetchedFromNetwork:l.stats.value.totals.itemsFetchedFromNetwork+B}},{batchItems:N,pages:x,nextPage:b}}return{loadBackfillBatch:f}}function qt(l){const p=l.columnCount,f=l.columnWidth,r=l.gapX,u=l.gapY,d=l.headerHeight,c=l.footerHeight,i=l.bucketPx,y=Array.from({length:p},()=>0),x=new Array(l.items.length),b=new Array(l.items.length),B=new Map,I=new Map;let N=0;for(let E=0;E<l.items.length;E+=1){const A=l.items[E];A?.id&&I.set(A.id,E);let F=0;for(let R=1;R<y.length;R+=1)y[R]<y[F]&&(F=R);const q=F*(f+r),V=y[F],S=Lt(A,f)+d+c;x[E]={x:q,y:V},b[E]=S,y[F]=V+S+u,N=Math.max(N,V+S);const M=Math.floor(V/i),C=Math.floor((V+S)/i);for(let R=M;R<=C;R+=1){const Y=B.get(R);Y?Y.push(E):B.set(R,[E])}}return{positions:x,heights:b,buckets:B,contentHeight:N,indexById:I}}function Dt(l){const p=l.itemCount;if(!p)return[];if(l.viewportHeight<=0)return Array.from({length:p},(y,x)=>x);const f=Math.max(0,l.scrollTop-l.overscanPx),r=l.scrollTop+l.viewportHeight+l.overscanPx,u=Math.floor(f/l.bucketPx),d=Math.floor(r/l.bucketPx),c=new Set;for(let y=u;y<=d;y+=1){const x=l.buckets.get(y);if(x)for(const b of x)c.add(b)}const i=Array.from(c);return i.sort((y,x)=>y-x),i}const Ot={class:"hidden"},$t={key:0,class:"flex h-full items-center justify-center"},Yt={key:1,class:"text-sm font-medium text-red-700"},Xt={class:"mt-4 pb-2 text-center text-xs text-slate-600"},jt={key:0,class:"inline-flex items-center justify-center gap-2"},Wt={key:1},Ut={key:2},lt=100,Gt=200,at=600,rt=300,st=600,it=600,Kt=5,Jt=1e3,dt=e.defineComponent({inheritAttrs:!1,__name:"Masonry",props:e.mergeDefaults({getContent:{},mode:{},pageSize:{},backfillRequestDelayMs:{},items:{},page:{},restoredPagesLoaded:{},itemWidth:{},prefetchThresholdPx:{},gapX:{},gapY:{},headerHeight:{},footerHeight:{},overscanPx:{}},ut),emits:["update:items","preloaded","failures"],setup(l,{expose:p,emit:f}){const r=l,u=f,d=e.useAttrs(),c=e.defineComponent({name:"SlotRenderer",props:{slotFn:{type:Function,required:!1},slotProps:{type:Object,required:!0}},setup(t){return()=>{const o=t.slotFn;return o?o(t.slotProps):null}}}),i=e.shallowRef(null);e.provide(ct,t=>{i.value||(i.value=t)});const y=[],x=[];let b=null,B=null;function I(){if(!y.length)return;const t=y.splice(0,y.length);u("preloaded",t)}function N(){if(!x.length)return;const t=x.splice(0,x.length);u("failures",t)}function E(){b||(b=setTimeout(()=>{b=null,I()},lt))}function A(){B||(B=setTimeout(()=>{B=null,N()},lt))}function F(t){i.value?.onPreloaded?.(t),y.push(t),E()}function q(t){i.value?.onFailed?.(t),x.push(t),A()}e.onMounted(()=>{if(!i.value)throw new Error("[Masonry] Missing <MasonryItem> definition. Add <MasonryItem> as a child of <Masonry>.")});const V=e.computed(()=>{const{class:t,...o}=d;return o}),S=e.ref(null),M=e.ref(0),C=e.ref(0),R=e.ref(0);let Y;const X=e.computed(()=>r.gapX),Me=e.computed(()=>r.gapY);function Se(t){if(!t)return 0;const o=Math.max(0,X.value);return Math.max(0,t.clientWidth-o)}const j=e.computed(()=>r.headerHeight),W=e.computed(()=>r.footerHeight),fe=e.computed(()=>i.value?.header),de=e.computed(()=>i.value?.footer),re=e.computed(()=>i.value?.default),Ie=e.computed(()=>!!fe.value),Ee=e.computed(()=>!!de.value),Fe=e.computed(()=>{if(j.value>0)return{height:`${j.value}px`}}),Pe=e.computed(()=>{if(W.value>0)return{height:`${W.value}px`}}),ee=e.ref([]),me=e.ref([]),Ne=e.ref(new Map),Te=e.ref(0),se=e.ref(new Map);function Re(t){const o=typeof t=="number"&&Number.isFinite(t)?t:0;return Ge.value+Math.max(0,o)}const D=e.ref(new Set),U=e.ref(new Set),ie=new Set,ue=e.ref(new Map),L=e.ref(new Set),H=e.ref([]);function vt(t){const o=ue.value.get(t);return o||{dx:0,dy:0}}function ht(t){if(U.value.has(t))return`transform ${st}ms ease-out`;if(L.value.has(t))return`transform ${rt}ms ease-out`}function gt(t){const n=m.value[t]?.id,a=ee.value[t]??{x:0,y:0},s=me.value[t]??0,v=s>0?s:le.value,h=a.x,w=n&&D.value.has(n)?Re(v):a.y,k=n?vt(n):{dx:0,dy:0};return`translate3d(${h+k.dx}px,${w+k.dy}px,0)`}function G(t){(typeof requestAnimationFrame=="function"?requestAnimationFrame:n=>setTimeout(()=>n(0),0))(()=>t())}function pt(t){G(()=>G(t))}const Ae=new Set;function _e(t){return typeof t=="number"&&Number.isFinite(t)&&t>0}function ve(t){if(!Array.isArray(t)||t.length===0)return;const o=new Set(D.value);let n=!1;for(const a of t){const s=a?.id;if(s){if(!Ae.has(s)){const v=a?.width,h=a?.height;(!_e(v)||!_e(h))&&(Ae.add(s),console.warn(`[Masonry] Item "${s}" has invalid dimensions (width=${String(v)}, height=${String(h)}); layout expects { id, width, height }.`))}o.has(s)||(o.add(s),n=!0)}}n&&(D.value=o)}function Ce(){const t=new Map;for(const o of xe.value){const a=m.value[o]?.id;if(!a)continue;const s=ee.value[o];s&&t.set(a,{x:s.x,y:s.y})}return t}function Ve(t,o){if(!t.size)return;const n=new Map,a=[];for(const[v,h]of t.entries()){if(o?.has(v))continue;const w=se.value.get(v);if(w==null)continue;const k=ee.value[w];if(!k)continue;const g=h.x-k.x,_=h.y-k.y;(g||_)&&(n.set(v,{dx:g,dy:_}),a.push(v))}if(!n.size)return;ue.value=n;const s=new Set(L.value);for(const v of a)s.delete(v);L.value=s,G(()=>{L.value=new Set([...L.value,...a]),G(()=>{ue.value=new Map})}),setTimeout(()=>{const v=new Set(L.value);for(const h of a)v.delete(h);L.value=v},rt)}const te=e.ref(!0),ne=e.ref(!1),K=e.ref("");let P=0;function ze(t){return t instanceof Error&&t.name==="AbortError"}function Le(){const t=new Error("aborted");return t.name="AbortError",t}function yt(t){return new Promise(o=>setTimeout(o,t))}async function He(t,o){let n=0;for(;;){if(o!==P)throw Le();try{return await r.getContent(t)}catch(a){if(o!==P)throw Le();if(n>=Kt)throw a;n+=1,await yt(n*Jt)}}}const z=e.ref([]),qe=e.ref([]),he=e.ref([]),T=e.ref(r.page),ge=e.ref([]);let J=null,Q=null,ce=0;function wt(t){let o=-1;for(const n of t){const a=n?.originalIndex;oe(a)&&a>o&&(o=a)}ce=o+1}function Z(t){for(const o of t)!o||typeof o!="object"||o.id&&o.originalIndex==null&&(o.originalIndex=ce,ce+=1)}const O=new Map,$=[];function oe(t){return typeof t=="number"&&Number.isFinite(t)}function kt(t,o){if(!o.length)return t;const n=new Set;for(const h of t){const w=h?.id;w&&n.add(w)}const a=[];for(const h of o){const w=h?.id;w&&(n.has(w)||(a.push(h),n.add(w)))}if(!a.length)return t;const s=a.slice().sort((h,w)=>{const k=oe(h.originalIndex)?h.originalIndex:Number.POSITIVE_INFINITY,g=oe(w.originalIndex)?w.originalIndex:Number.POSITIVE_INFINITY;return k-g}),v=t.slice();for(const h of s){const w=h.originalIndex;if(!oe(w)){v.push(h);continue}let k=0,g=v.length;for(;k<g;){const _=k+g>>1,ae=v[_]?.originalIndex;(oe(ae)?ae:Number.POSITIVE_INFINITY)<=w?k=_+1:g=_}v.splice(k,0,h)}return v}async function De(t){if(!t.length)return;ve(t);const o=Ce();m.value=kt(m.value,t),await e.nextTick(),Ve(o)}async function Oe(t){const n=(Array.isArray(t)?t:[t]).map(we).filter(Boolean);if(!n.length)return;const a=[];for(const s of n){const v=O.get(s);v&&a.push(v)}if(a.length){await De(a);for(const s of a)s?.id&&O.delete(s.id)}}async function $e(){const t=$.pop();if(!t?.length)return;const o=[];for(const n of t){const a=O.get(n);a&&o.push(a)}if(o.length){await De(o);for(const n of o)n?.id&&O.delete(n.id)}}async function xt(t){return Oe(t)}async function bt(){return $e()}function Ye(t){const n=(Array.isArray(t)?t:[t]).map(we).filter(Boolean);if(!n.length)return;const a=new Set(n);for(const s of a)O.delete(s);for(let s=$.length-1;s>=0;s-=1){const h=$[s].filter(w=>!a.has(w));h.length?$[s]=h:$.splice(s,1)}}const pe=e.shallowRef({enabled:!1,isBackfillActive:!1,isRequestInFlight:!1,requestPage:null,progress:{collected:0,target:0},cooldownMsRemaining:0,cooldownMsTotal:2e3,pageSize:20,bufferSize:0,lastBatch:null,totals:{pagesFetched:0,itemsFetchedFromNetwork:0}}),Xe=Ht({getContent:t=>He(t,P),markEnterFromLeft:ve,buffer:ge,stats:pe,isEnabled:()=>r.mode==="backfill",getPageSize:()=>r.pageSize,getRequestDelayMs:()=>r.backfillRequestDelayMs}),ye=e.computed(()=>r.items!==void 0);e.watch(()=>r.items,t=>{ye.value&&(he.value=Array.isArray(t)?t:[])},{immediate:!0});const m=e.computed({get(){return ye.value?he.value:qe.value},set(t){ye.value?(he.value=t,u("update:items",t)):qe.value=t}});async function je(t){const o=await He(t,P);return Z(o.items),ve(o.items),{items:o.items,nextPage:o.nextPage}}function we(t){return t?typeof t=="string"?t:t?.id:null}async function We(t){const n=(Array.isArray(t)?t:[t]).map(we).filter(Boolean);if(!n.length)return;const a=new Set(n),s=[];for(const k of a){const g=se.value.get(k);if(g==null)continue;const _=m.value[g];_&&(O.set(k,_),s.push(k))}s.length&&$.push(s);const v=Ce(),h=le.value,w=[];for(const k of a){const g=se.value.get(k);if(g==null)continue;const _=m.value[g];if(!_)continue;const ae=ee.value[g]??{x:0,y:0},nt=me.value[g]??h;w.push({id:k,item:_,fromX:ae.x,fromY:ae.y,width:h,height:nt,leaving:!0})}if(w.length&&(H.value=[...H.value,...w]),m.value=m.value.filter(k=>{const g=k?.id;return!g||!a.has(g)}),await e.nextTick(),Ve(v,a),w.length){const k=new Set(w.map(g=>g.id));G(()=>{H.value=H.value.map(g=>k.has(g.id)?{...g,leaving:!1}:g),setTimeout(()=>{H.value=H.value.filter(g=>!k.has(g.id))},it)})}}async function ke(t){return We(t)}p({remove:We,restore:xt,undo:bt,forget:Ye,pagesLoaded:z,nextPage:T,restoreRemoved:Oe,undoLastRemoval:$e,forgetRemoved:Ye,backfillStats:pe});function Ue(){const t=qt({items:m.value,columnCount:be.value,columnWidth:le.value,gapX:X.value,gapY:Me.value,headerHeight:j.value,footerHeight:W.value,bucketPx:at});ee.value=t.positions,me.value=t.heights,Ne.value=t.buckets,Te.value=t.contentHeight,se.value=t.indexById}const Ge=e.computed(()=>Math.max(Te.value,C.value)+Gt),xe=e.computed(()=>Dt({itemCount:m.value.length,viewportHeight:C.value,scrollTop:R.value,overscanPx:r.overscanPx,bucketPx:at,buckets:Ne.value}));e.watch(xe,t=>{if(!t?.length)return;const o=[];for(const n of t){const a=m.value[n]?.id;a&&D.value.has(a)&&(ie.has(a)||(ie.add(a),o.push(a)))}o.length&&(G(()=>{const n=new Set(U.value);for(const a of o)n.add(a);U.value=n}),pt(()=>{const n=new Set(D.value);for(const a of o)n.delete(a);D.value=n,setTimeout(()=>{const a=new Set(U.value);for(const s of o)a.delete(s),ie.delete(s);U.value=a},st)}))},{flush:"post"});async function Bt(){if(J)return J;if(te.value||ne.value||r.mode!=="backfill"&&T.value==null||r.mode==="backfill"&&T.value==null&&ge.value.length===0)return;const t=P;let o=null;return o=(async()=>{try{if(ne.value=!0,K.value="",r.mode==="backfill"){const s=await Xe.loadBackfillBatch(T.value);if(t!==P)return;s.pages.length&&(z.value=[...z.value,...s.pages]),Z(s.batchItems),m.value=[...m.value,...s.batchItems],T.value=s.nextPage;return}const n=T.value;if(n==null)return;const a=await je(n);if(t!==P)return;z.value=[...z.value,n],Z(a.items),m.value=[...m.value,...a.items],T.value=a.nextPage}catch(n){if(t!==P||ze(n))return;K.value=n instanceof Error?n.message:String(n)}finally{t===P&&(ne.value=!1),J===o&&(J=null)}})(),J=o,o}function Mt(){const t=S.value;if(!t)return;R.value=t.scrollTop,C.value=t.clientHeight,t.scrollHeight-(t.scrollTop+t.clientHeight)<=r.prefetchThresholdPx&&Bt()}function Ke(){return S.value}function Je(t){M.value=Se(t),C.value=t.clientHeight}function St(){typeof ResizeObserver>"u"||(Y=new ResizeObserver(()=>{const t=Ke();t&&Je(t)}))}function It(){return{enabled:r.mode==="backfill",isBackfillActive:!1,isRequestInFlight:!1,requestPage:null,progress:{collected:0,target:0},cooldownMsRemaining:0,cooldownMsTotal:Be(r.backfillRequestDelayMs),pageSize:ft(r.pageSize),bufferSize:0,lastBatch:null,totals:{pagesFetched:0,itemsFetchedFromNetwork:0}}}function Qe(){P+=1,J=null,Q=null,ce=0,O.clear(),$.length=0,D.value=new Set,U.value=new Set,ie.clear(),ue.value=new Map,L.value=new Set,H.value=[],z.value=[],T.value=null,ge.value=[],pe.value=It(),te.value=!0,ne.value=!1,K.value=""}function Ze(t){Qe(),m.value=[],T.value=t}function Et(t){const o=Array.isArray(t)?t:[t],n=[],a=new Set;for(const s of o){if(s==null)continue;const v=typeof s=="string"?`s:${s}`:`n:${String(s)}`;a.has(v)||(a.add(v),n.push(s))}return n}function Ft(t){const o=[];for(const n of t){if(typeof n=="number"&&Number.isFinite(n)){o.push(n);continue}if(typeof n=="string"){const a=Number.parseInt(n,10);Number.isFinite(a)&&o.push(a)}}return o.length?Math.max(...o)+1:null}function et(t){Qe();const o=Et(t);z.value=o,T.value=Ft(o),te.value=!1,wt(m.value),Z(m.value)}async function tt(t){if(Q)return Q;const o=P;let n=null;return n=(async()=>{try{if(r.mode==="backfill"){const a=await Xe.loadBackfillBatch(t);if(o!==P)return;z.value=a.pages.length?a.pages:[t],Z(a.batchItems),m.value=a.batchItems,T.value=a.nextPage}else{const a=await je(t);if(o!==P)return;z.value=[t],Z(a.items),m.value=a.items,T.value=a.nextPage}}catch(a){if(o!==P||ze(a))return;K.value=a instanceof Error?a.message:String(a)}finally{o===P&&(te.value=!1),Q===n&&(Q=null)}})(),Q=n,n}function Pt(){const t=Ke();t&&(Je(t),R.value=t.scrollTop,Y?.observe(t))}e.onMounted(async()=>{if(St(),Pt(),r.restoredPagesLoaded!=null){et(r.restoredPagesLoaded);return}Ze(r.page),await tt(r.page)}),e.onUnmounted(()=>{Y?.disconnect(),b&&(clearTimeout(b),b=null),B&&(clearTimeout(B),B=null),I(),N()}),e.watch(()=>r.page,async t=>{r.restoredPagesLoaded==null&&(Ze(t),await tt(t))}),e.watch(()=>r.restoredPagesLoaded,t=>{t&&et(t)}),e.watch(X,()=>{const t=S.value;t&&(M.value=Se(t))},{immediate:!1});const be=e.computed(()=>Vt(M.value,r.itemWidth)),le=e.computed(()=>zt(M.value,be.value,r.itemWidth,X.value));e.watch([be,le,X,Me,j,W],()=>{Ue()},{immediate:!0}),e.watch(()=>[m.value,m.value.length],()=>Ue(),{immediate:!0});const Nt=e.computed(()=>["mt-8 flex min-h-0 flex-1 flex-col rounded-2xl border border-slate-200/70 bg-white/70 p-5 shadow-sm backdrop-blur",d.class]);return(t,o)=>(e.openBlock(),e.createElementBlock("section",e.mergeProps(V.value,{class:Nt.value}),[e.createElementVNode("div",Ot,[e.renderSlot(t.$slots,"default")]),e.createElementVNode("div",{ref_key:"scrollViewportRef",ref:S,"data-testid":"items-scroll-container",class:"mt-4 min-h-0 flex-1 overflow-auto",style:e.normalizeStyle({paddingRight:X.value+"px"}),onScroll:Mt},[te.value?(e.openBlock(),e.createElementBlock("div",$t,o[0]||(o[0]=[e.createElementVNode("div",{class:"inline-flex items-center gap-3 text-sm text-slate-600"},[e.createElementVNode("svg",{class:"h-5 w-5 animate-spin text-slate-500",viewBox:"0 0 24 24","aria-hidden":"true"},[e.createElementVNode("circle",{class:"opacity-25",cx:"12",cy:"12",r:"10",fill:"none",stroke:"currentColor","stroke-width":"4"}),e.createElementVNode("path",{class:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 0 1 8-8v4a4 4 0 0 0-4 4H4z"})]),e.createElementVNode("span",null,"Loading…")],-1)]))):K.value?(e.openBlock(),e.createElementBlock("p",Yt,"Error: "+e.toDisplayString(K.value),1)):(e.openBlock(),e.createElementBlock("div",{key:2,class:"relative",style:e.normalizeStyle({height:Ge.value+"px"})},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(xe.value,n=>(e.openBlock(),e.createElementBlock("article",{key:m.value[n].id,"data-testid":"item-card",class:"absolute overflow-hidden rounded-xl border border-slate-200/60 bg-white shadow-sm",style:e.normalizeStyle({width:le.value+"px",transition:ht(m.value[n].id),transform:gt(n)})},[Ie.value||j.value>0?(e.openBlock(),e.createElementBlock("div",{key:0,"data-testid":"item-header-container",class:"w-full",style:e.normalizeStyle(Fe.value)},[e.createVNode(e.unref(c),{"slot-fn":fe.value,"slot-props":{item:m.value[n],remove:()=>ke(m.value[n])}},null,8,["slot-fn","slot-props"])],4)):e.createCommentVNode("",!0),re.value?(e.openBlock(),e.createBlock(e.unref(c),{key:1,"slot-fn":re.value,"slot-props":{item:m.value[n],remove:()=>ke(m.value[n])}},null,8,["slot-fn","slot-props"])):(e.openBlock(),e.createBlock(ot,{key:2,item:m.value[n],onSuccess:F,onError:q},null,8,["item"])),Ee.value||W.value>0?(e.openBlock(),e.createElementBlock("div",{key:3,"data-testid":"item-footer-container",class:"w-full",style:e.normalizeStyle(Pe.value)},[e.createVNode(e.unref(c),{"slot-fn":de.value,"slot-props":{item:m.value[n],remove:()=>ke(m.value[n])}},null,8,["slot-fn","slot-props"])],4)):e.createCommentVNode("",!0)],4))),128)),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(H.value,n=>(e.openBlock(),e.createElementBlock("article",{key:n.id+":leaving","data-testid":"item-card-leaving",class:"pointer-events-none absolute overflow-hidden rounded-xl border border-slate-200/60 bg-white shadow-sm",style:e.normalizeStyle({width:n.width+"px",transition:"transform "+it+"ms ease-out",transform:n.leaving?"translate3d("+n.fromX+"px,"+n.fromY+"px,0)":"translate3d("+n.fromX+"px,"+Re(n.height)+"px,0)"})},[Ie.value||j.value>0?(e.openBlock(),e.createElementBlock("div",{key:0,"data-testid":"item-header-container",class:"w-full",style:e.normalizeStyle(Fe.value)},[e.createVNode(e.unref(c),{"slot-fn":fe.value,"slot-props":{item:n.item,remove:()=>{}}},null,8,["slot-fn","slot-props"])],4)):e.createCommentVNode("",!0),re.value?(e.openBlock(),e.createBlock(e.unref(c),{key:1,"slot-fn":re.value,"slot-props":{item:n.item,remove:()=>{}}},null,8,["slot-fn","slot-props"])):(e.openBlock(),e.createBlock(ot,{key:2,item:n.item},null,8,["item"])),Ee.value||W.value>0?(e.openBlock(),e.createElementBlock("div",{key:3,"data-testid":"item-footer-container",class:"w-full",style:e.normalizeStyle(Pe.value)},[e.createVNode(e.unref(c),{"slot-fn":de.value,"slot-props":{item:n.item,remove:()=>{}}},null,8,["slot-fn","slot-props"])],4)):e.createCommentVNode("",!0)],4))),128))],4)),e.createElementVNode("div",Xt,[ne.value?(e.openBlock(),e.createElementBlock("span",jt,o[1]||(o[1]=[e.createElementVNode("svg",{class:"h-4 w-4 animate-spin text-slate-500",viewBox:"0 0 24 24","aria-hidden":"true"},[e.createElementVNode("circle",{class:"opacity-25",cx:"12",cy:"12",r:"10",fill:"none",stroke:"currentColor","stroke-width":"4"}),e.createElementVNode("path",{class:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 0 1 8-8v4a4 4 0 0 0-4 4H4z"})],-1),e.createElementVNode("span",null,"Loading more…",-1)]))):T.value==null?(e.openBlock(),e.createElementBlock("span",Wt,"End of list")):(e.openBlock(),e.createElementBlock("span",Ut,"Scroll to load page "+e.toDisplayString(T.value),1))])],36)],16))}}),mt=e.defineComponent({name:"MasonryItem",setup(l,{slots:p,attrs:f}){const r=e.inject(ct,null);if(!r)return()=>null;const u=f.onPreloaded,d=f.onFailed;return r({header:p.header,default:p.default,footer:p.footer,onPreloaded:typeof u=="function"?u:Array.isArray(u)?c=>{for(const i of u)typeof i=="function"&&i(c)}:void 0,onFailed:typeof d=="function"?d:Array.isArray(d)?c=>{for(const i of d)typeof i=="function"&&i(c)}:void 0}),()=>null}}),Qt={install(l){l.component("Masonry",dt),l.component("MasonryItem",mt)}};exports.Masonry=dt;exports.MasonryItem=mt;exports.VibePlugin=Qt;exports.masonryDefaults=ut;
|