@wyxos/vibe 1.6.4 → 1.6.6
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 +188 -139
- package/lib/index.js +196 -195
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,139 +1,188 @@
|
|
|
1
|
-
# VIBE — Vue Infinite Block Engine
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@wyxos/vibe)
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
[](https://wyxos.github.io/vibe/)
|
|
6
|
-
|
|
7
|
-
A high-performance, responsive masonry layout engine for Vue 3 with built-in infinite scrolling and virtualization.
|
|
8
|
-
|
|
9
|
-
VIBE (Vue Infinite Block Engine) is designed for applications that need to display large datasets in a masonry grid without compromising performance. Unlike other masonry libraries, VIBE leverages virtualization to render only what is visible on the screen, ensuring smooth scrolling even with thousands of items.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
:
|
|
61
|
-
:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
1
|
+
# VIBE — Vue Infinite Block Engine
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@wyxos/vibe)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://wyxos.github.io/vibe/)
|
|
6
|
+
|
|
7
|
+
A high-performance, responsive masonry layout engine for Vue 3 with built-in infinite scrolling and virtualization.
|
|
8
|
+
|
|
9
|
+
VIBE (Vue Infinite Block Engine) is designed for applications that need to display large datasets in a masonry grid without compromising performance. Unlike other masonry libraries, VIBE leverages virtualization to render only what is visible on the screen, ensuring smooth scrolling even with thousands of items.
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- **High Performance Virtualization**: Efficiently renders thousands of items by only mounting elements currently in the viewport.
|
|
18
|
+
- **Responsive Masonry Layout**: Automatically adjusts column counts and layout based on screen width and breakpoints.
|
|
19
|
+
- **Infinite Scrolling**: Seamlessly loads more content as the user scrolls, with built-in support for async data fetching.
|
|
20
|
+
- **Dynamic Updates**: Supports adding, removing, and reflowing items with smooth FLIP animations.
|
|
21
|
+
- **Scroll Position Maintenance**: Keeps the user's scroll position stable when new items are loaded or the layout changes.
|
|
22
|
+
- **Built-in Item Component**: Includes a production-ready `MasonryItem` with image preloading, error handling, and hover effects.
|
|
23
|
+
- **Customizable Rendering**: Full control over item markup via scoped slots.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @wyxos/vibe
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
### Basic Usage (Default Item)
|
|
38
|
+
|
|
39
|
+
By default, VIBE uses the built-in `MasonryItem` component, which handles image loading and provides a clean UI.
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<script setup>
|
|
43
|
+
import { ref } from 'vue'
|
|
44
|
+
import { Masonry } from '@wyxos/vibe'
|
|
45
|
+
|
|
46
|
+
const items = ref([])
|
|
47
|
+
|
|
48
|
+
// Layout configuration
|
|
49
|
+
const layout = {
|
|
50
|
+
gutterX: 12,
|
|
51
|
+
gutterY: 12,
|
|
52
|
+
sizes: { base: 1, sm: 2, md: 3, lg: 4 }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function getNextPage(page) {
|
|
56
|
+
const response = await fetch(`/api/items?page=${page}`)
|
|
57
|
+
const data = await response.json()
|
|
58
|
+
// Items must have a 'src' property for the default MasonryItem
|
|
59
|
+
return {
|
|
60
|
+
items: data.items,
|
|
61
|
+
nextPage: page + 1
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<template>
|
|
67
|
+
<Masonry
|
|
68
|
+
v-model:items="items"
|
|
69
|
+
:get-next-page="getNextPage"
|
|
70
|
+
:layout="layout"
|
|
71
|
+
/>
|
|
72
|
+
</template>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Custom Item Rendering
|
|
76
|
+
|
|
77
|
+
You can fully customize the item rendering using the `#item` slot. You can also import and use `MasonryItem` inside the slot if you want to wrap it or extend it.
|
|
78
|
+
|
|
79
|
+
```vue
|
|
80
|
+
<script setup>
|
|
81
|
+
import { Masonry, MasonryItem } from '@wyxos/vibe'
|
|
82
|
+
// ... setup code ...
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<template>
|
|
86
|
+
<Masonry
|
|
87
|
+
v-model:items="items"
|
|
88
|
+
:get-next-page="getNextPage"
|
|
89
|
+
:layout="layout"
|
|
90
|
+
>
|
|
91
|
+
<template #item="{ item, remove }">
|
|
92
|
+
<!-- Custom container -->
|
|
93
|
+
<div class="custom-card">
|
|
94
|
+
<!-- You can use the built-in item or your own -->
|
|
95
|
+
<MasonryItem :item="item" :remove="remove">
|
|
96
|
+
<!-- Optional: MasonryItem also has a default slot for overlays -->
|
|
97
|
+
<div class="absolute bottom-0 p-2 text-white">
|
|
98
|
+
{{ item.title }}
|
|
99
|
+
</div>
|
|
100
|
+
</MasonryItem>
|
|
101
|
+
</div>
|
|
102
|
+
</template>
|
|
103
|
+
</Masonry>
|
|
104
|
+
</template>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Props
|
|
110
|
+
|
|
111
|
+
| Prop | Type | Required | Description |
|
|
112
|
+
|------|------|----------|-------------|
|
|
113
|
+
| `items` | `Array` | Yes | Two-way bound item array. Each item must include `width`, `height`, and `id`. |
|
|
114
|
+
| `getNextPage` | `Function(page: Number)` | Yes | Async function to load the next page. Must return `{ items, nextPage }`. |
|
|
115
|
+
| `layout` | `Object` | No | Configuration object for layout, including sizes and gutters. |
|
|
116
|
+
| `loadAtPage` | `Number` | No | The starting page number (default: `1`). |
|
|
117
|
+
| `paginationType` | `String` | No | `'page'` or `'cursor'` (default: `'page'`). |
|
|
118
|
+
| `pageSize` | `Number` | No | Number of items per page, used for backfilling (default: `40`). |
|
|
119
|
+
|
|
120
|
+
### Layout Configuration Example
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
{
|
|
124
|
+
gutterX: 10,
|
|
125
|
+
gutterY: 10,
|
|
126
|
+
sizes: {
|
|
127
|
+
base: 1,
|
|
128
|
+
sm: 2,
|
|
129
|
+
md: 3,
|
|
130
|
+
lg: 4,
|
|
131
|
+
xl: 5,
|
|
132
|
+
'2xl': 6
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## MasonryItem Component
|
|
140
|
+
|
|
141
|
+
The built-in `MasonryItem` component is available for use within the `#item` slot or as a standalone component.
|
|
142
|
+
|
|
143
|
+
### Props
|
|
144
|
+
|
|
145
|
+
| Prop | Type | Description |
|
|
146
|
+
|------|------|-------------|
|
|
147
|
+
| `item` | `Object` | The item object. Must contain `src` for image loading. |
|
|
148
|
+
| `remove` | `Function` | Optional callback to remove the item. If provided, a remove button is shown. |
|
|
149
|
+
|
|
150
|
+
### Features
|
|
151
|
+
- **Image Preloading**: Shows a spinner while the image loads.
|
|
152
|
+
- **Error Handling**: Displays an error state if the image fails to load.
|
|
153
|
+
- **Hover Effects**: Includes a subtle zoom and overlay on hover.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Slots
|
|
158
|
+
|
|
159
|
+
| Slot Name | Props | Description |
|
|
160
|
+
|-----------|-------|-------------|
|
|
161
|
+
| `item` | `{ item, remove }` | Scoped slot for custom rendering of each masonry block. |
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Run Locally
|
|
166
|
+
|
|
167
|
+
To run the demo project locally:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
git clone https://github.com/wyxos/vibe
|
|
171
|
+
cd vibe
|
|
172
|
+
npm install
|
|
173
|
+
npm run dev
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Visit `http://localhost:5173` to view the demo.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Live Demo
|
|
181
|
+
|
|
182
|
+
[View Live Demo on GitHub Pages](https://wyxos.github.io/vibe/)
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## License
|
|
187
|
+
|
|
188
|
+
MIT © [@wyxos](https://github.com/wyxos)
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { nextTick as Q, defineComponent as
|
|
1
|
+
import { nextTick as Q, defineComponent as Le, ref as L, onMounted as He, watch as Ne, createElementBlock as q, openBlock as V, renderSlot as $e, createElementVNode as O, createCommentVNode as oe, withModifiers as ze, toDisplayString as de, computed as se, onUnmounted as Re, normalizeClass as we, normalizeStyle as Ce, createVNode as Me, TransitionGroup as _e, withCtx as qe, Fragment as Ve, renderList as Ge, mergeProps as Te, unref as Ue } from "vue";
|
|
2
2
|
let ue = null;
|
|
3
|
-
function
|
|
3
|
+
function Xe() {
|
|
4
4
|
if (ue != null) return ue;
|
|
5
5
|
const e = document.createElement("div");
|
|
6
6
|
e.style.visibility = "hidden", e.style.overflow = "scroll", e.style.msOverflowStyle = "scrollbar", e.style.width = "100px", e.style.height = "100px", document.body.appendChild(e);
|
|
@@ -9,7 +9,7 @@ function Ue() {
|
|
|
9
9
|
const l = e.offsetWidth - o.offsetWidth;
|
|
10
10
|
return document.body.removeChild(e), ue = l, l;
|
|
11
11
|
}
|
|
12
|
-
function
|
|
12
|
+
function Ye(e, o, l, s = {}) {
|
|
13
13
|
const {
|
|
14
14
|
gutterX: h = 0,
|
|
15
15
|
gutterY: v = 0,
|
|
@@ -26,7 +26,7 @@ function Xe(e, o, l, i = {}) {
|
|
|
26
26
|
"2xl": 6
|
|
27
27
|
},
|
|
28
28
|
placement: b = "masonry"
|
|
29
|
-
} =
|
|
29
|
+
} = s;
|
|
30
30
|
let m = 0, x = 0;
|
|
31
31
|
try {
|
|
32
32
|
if (o && o.nodeType === 1 && typeof window < "u" && window.getComputedStyle) {
|
|
@@ -35,19 +35,19 @@ function Xe(e, o, l, i = {}) {
|
|
|
35
35
|
}
|
|
36
36
|
} catch {
|
|
37
37
|
}
|
|
38
|
-
const F = (d || 0) + m, _ = (u || 0) + x, H = o.offsetWidth - o.clientWidth,
|
|
38
|
+
const F = (d || 0) + m, _ = (u || 0) + x, H = o.offsetWidth - o.clientWidth, M = H > 0 ? H + 2 : Xe() + 2, P = o.offsetWidth - M - F - _, U = h * (l - 1), S = Math.floor((P - U) / l), T = e.map((w) => {
|
|
39
39
|
const N = w.width, I = w.height;
|
|
40
40
|
return Math.round(S * I / N) + n + a;
|
|
41
41
|
});
|
|
42
42
|
if (b === "sequential-balanced") {
|
|
43
|
-
const w =
|
|
43
|
+
const w = T.length;
|
|
44
44
|
if (w === 0) return [];
|
|
45
45
|
const N = (p, k, B) => p + (k > 0 ? v : 0) + B;
|
|
46
|
-
let I = Math.max(...
|
|
46
|
+
let I = Math.max(...T), D = T.reduce((p, k) => p + k, 0) + v * Math.max(0, w - 1);
|
|
47
47
|
const Z = (p) => {
|
|
48
48
|
let k = 1, B = 0, z = 0;
|
|
49
49
|
for (let $ = 0; $ < w; $++) {
|
|
50
|
-
const G =
|
|
50
|
+
const G = T[$], R = N(B, z, G);
|
|
51
51
|
if (R <= p)
|
|
52
52
|
B = R, z++;
|
|
53
53
|
else if (k++, B = G, z = 1, G > p || k > l) return !1;
|
|
@@ -61,7 +61,7 @@ function Xe(e, o, l, i = {}) {
|
|
|
61
61
|
const ee = D, X = new Array(l).fill(0);
|
|
62
62
|
let te = l - 1, Y = 0, J = 0;
|
|
63
63
|
for (let p = w - 1; p >= 0; p--) {
|
|
64
|
-
const k =
|
|
64
|
+
const k = T[p], B = p < te;
|
|
65
65
|
!(N(Y, J, k) <= ee) || B ? (X[te] = p + 1, te--, Y = k, J = 1) : (Y = N(Y, J, k), J++);
|
|
66
66
|
}
|
|
67
67
|
X[0] = 0;
|
|
@@ -77,7 +77,7 @@ function Xe(e, o, l, i = {}) {
|
|
|
77
77
|
left: 0,
|
|
78
78
|
top: 0
|
|
79
79
|
};
|
|
80
|
-
R.imageHeight =
|
|
80
|
+
R.imageHeight = T[$] - (n + a), R.columnHeight = T[$], R.left = z, R.top = ae[p], ae[p] += R.columnHeight + ($ + 1 < B ? v : 0), j.push(R);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
return j;
|
|
@@ -96,120 +96,120 @@ function Xe(e, o, l, i = {}) {
|
|
|
96
96
|
}
|
|
97
97
|
return W;
|
|
98
98
|
}
|
|
99
|
-
var
|
|
100
|
-
function
|
|
101
|
-
var o =
|
|
99
|
+
var Je = typeof global == "object" && global && global.Object === Object && global, Ke = typeof self == "object" && self && self.Object === Object && self, Ae = Je || Ke || Function("return this")(), ie = Ae.Symbol, We = Object.prototype, Qe = We.hasOwnProperty, Ze = We.toString, re = ie ? ie.toStringTag : void 0;
|
|
100
|
+
function et(e) {
|
|
101
|
+
var o = Qe.call(e, re), l = e[re];
|
|
102
102
|
try {
|
|
103
103
|
e[re] = void 0;
|
|
104
|
-
var
|
|
104
|
+
var s = !0;
|
|
105
105
|
} catch {
|
|
106
106
|
}
|
|
107
|
-
var h =
|
|
108
|
-
return
|
|
107
|
+
var h = Ze.call(e);
|
|
108
|
+
return s && (o ? e[re] = l : delete e[re]), h;
|
|
109
109
|
}
|
|
110
|
-
var
|
|
111
|
-
function
|
|
112
|
-
return
|
|
113
|
-
}
|
|
114
|
-
var nt = "[object Null]", rt = "[object Undefined]", Me = se ? se.toStringTag : void 0;
|
|
115
|
-
function ot(e) {
|
|
116
|
-
return e == null ? e === void 0 ? rt : nt : Me && Me in Object(e) ? Ze(e) : at(e);
|
|
110
|
+
var tt = Object.prototype, at = tt.toString;
|
|
111
|
+
function nt(e) {
|
|
112
|
+
return at.call(e);
|
|
117
113
|
}
|
|
114
|
+
var rt = "[object Null]", ot = "[object Undefined]", Ie = ie ? ie.toStringTag : void 0;
|
|
118
115
|
function lt(e) {
|
|
116
|
+
return e == null ? e === void 0 ? ot : rt : Ie && Ie in Object(e) ? et(e) : nt(e);
|
|
117
|
+
}
|
|
118
|
+
function st(e) {
|
|
119
119
|
return e != null && typeof e == "object";
|
|
120
120
|
}
|
|
121
121
|
var it = "[object Symbol]";
|
|
122
|
-
function
|
|
123
|
-
return typeof e == "symbol" ||
|
|
122
|
+
function ut(e) {
|
|
123
|
+
return typeof e == "symbol" || st(e) && lt(e) == it;
|
|
124
124
|
}
|
|
125
|
-
var
|
|
126
|
-
function
|
|
127
|
-
for (var o = e.length; o-- &&
|
|
125
|
+
var ct = /\s/;
|
|
126
|
+
function ft(e) {
|
|
127
|
+
for (var o = e.length; o-- && ct.test(e.charAt(o)); )
|
|
128
128
|
;
|
|
129
129
|
return o;
|
|
130
130
|
}
|
|
131
|
-
var
|
|
132
|
-
function
|
|
133
|
-
return e && e.slice(0,
|
|
131
|
+
var dt = /^\s+/;
|
|
132
|
+
function gt(e) {
|
|
133
|
+
return e && e.slice(0, ft(e) + 1).replace(dt, "");
|
|
134
134
|
}
|
|
135
135
|
function ge(e) {
|
|
136
136
|
var o = typeof e;
|
|
137
137
|
return e != null && (o == "object" || o == "function");
|
|
138
138
|
}
|
|
139
|
-
var
|
|
140
|
-
function
|
|
139
|
+
var Pe = NaN, mt = /^[-+]0x[0-9a-f]+$/i, vt = /^0b[01]+$/i, pt = /^0o[0-7]+$/i, ht = parseInt;
|
|
140
|
+
function Se(e) {
|
|
141
141
|
if (typeof e == "number")
|
|
142
142
|
return e;
|
|
143
|
-
if (
|
|
144
|
-
return
|
|
143
|
+
if (ut(e))
|
|
144
|
+
return Pe;
|
|
145
145
|
if (ge(e)) {
|
|
146
146
|
var o = typeof e.valueOf == "function" ? e.valueOf() : e;
|
|
147
147
|
e = ge(o) ? o + "" : o;
|
|
148
148
|
}
|
|
149
149
|
if (typeof e != "string")
|
|
150
150
|
return e === 0 ? e : +e;
|
|
151
|
-
e =
|
|
152
|
-
var l =
|
|
153
|
-
return l ||
|
|
151
|
+
e = gt(e);
|
|
152
|
+
var l = vt.test(e);
|
|
153
|
+
return l || pt.test(e) ? ht(e.slice(2), l ? 2 : 8) : mt.test(e) ? Pe : +e;
|
|
154
154
|
}
|
|
155
155
|
var ce = function() {
|
|
156
|
-
return
|
|
157
|
-
},
|
|
158
|
-
function
|
|
159
|
-
var
|
|
156
|
+
return Ae.Date.now();
|
|
157
|
+
}, yt = "Expected a function", bt = Math.max, xt = Math.min;
|
|
158
|
+
function ke(e, o, l) {
|
|
159
|
+
var s, h, v, a, n, d, u = 0, c = !1, b = !1, m = !0;
|
|
160
160
|
if (typeof e != "function")
|
|
161
|
-
throw new TypeError(
|
|
162
|
-
o =
|
|
161
|
+
throw new TypeError(yt);
|
|
162
|
+
o = Se(o) || 0, ge(l) && (c = !!l.leading, b = "maxWait" in l, v = b ? bt(Se(l.maxWait) || 0, o) : v, m = "trailing" in l ? !!l.trailing : m);
|
|
163
163
|
function x(y) {
|
|
164
|
-
var W =
|
|
165
|
-
return
|
|
164
|
+
var W = s, w = h;
|
|
165
|
+
return s = h = void 0, u = y, a = e.apply(w, W), a;
|
|
166
166
|
}
|
|
167
167
|
function F(y) {
|
|
168
|
-
return u = y, n = setTimeout(
|
|
168
|
+
return u = y, n = setTimeout(M, o), c ? x(y) : a;
|
|
169
169
|
}
|
|
170
170
|
function _(y) {
|
|
171
171
|
var W = y - d, w = y - u, N = o - W;
|
|
172
|
-
return b ?
|
|
172
|
+
return b ? xt(N, v - w) : N;
|
|
173
173
|
}
|
|
174
174
|
function H(y) {
|
|
175
175
|
var W = y - d, w = y - u;
|
|
176
176
|
return d === void 0 || W >= o || W < 0 || b && w >= v;
|
|
177
177
|
}
|
|
178
|
-
function
|
|
178
|
+
function M() {
|
|
179
179
|
var y = ce();
|
|
180
180
|
if (H(y))
|
|
181
181
|
return P(y);
|
|
182
|
-
n = setTimeout(
|
|
182
|
+
n = setTimeout(M, _(y));
|
|
183
183
|
}
|
|
184
184
|
function P(y) {
|
|
185
|
-
return n = void 0, m &&
|
|
185
|
+
return n = void 0, m && s ? x(y) : (s = h = void 0, a);
|
|
186
186
|
}
|
|
187
187
|
function U() {
|
|
188
|
-
n !== void 0 && clearTimeout(n), u = 0,
|
|
188
|
+
n !== void 0 && clearTimeout(n), u = 0, s = d = h = n = void 0;
|
|
189
189
|
}
|
|
190
190
|
function S() {
|
|
191
191
|
return n === void 0 ? a : P(ce());
|
|
192
192
|
}
|
|
193
|
-
function
|
|
193
|
+
function T() {
|
|
194
194
|
var y = ce(), W = H(y);
|
|
195
|
-
if (
|
|
195
|
+
if (s = arguments, h = this, d = y, W) {
|
|
196
196
|
if (n === void 0)
|
|
197
197
|
return F(d);
|
|
198
198
|
if (b)
|
|
199
|
-
return clearTimeout(n), n = setTimeout(
|
|
199
|
+
return clearTimeout(n), n = setTimeout(M, o), x(d);
|
|
200
200
|
}
|
|
201
|
-
return n === void 0 && (n = setTimeout(
|
|
201
|
+
return n === void 0 && (n = setTimeout(M, o)), a;
|
|
202
202
|
}
|
|
203
|
-
return
|
|
203
|
+
return T.cancel = U, T.flush = S, T;
|
|
204
204
|
}
|
|
205
205
|
function fe(e) {
|
|
206
206
|
const o = window.innerWidth, l = e.sizes;
|
|
207
207
|
return o >= 1536 && l["2xl"] ? l["2xl"] : o >= 1280 && l.xl ? l.xl : o >= 1024 && l.lg ? l.lg : o >= 768 && l.md ? l.md : o >= 640 && l.sm ? l.sm : l.base;
|
|
208
208
|
}
|
|
209
|
-
function xt(e) {
|
|
210
|
-
return e.reduce((l, i) => Math.max(l, i.top + i.columnHeight), 0) + 500;
|
|
211
|
-
}
|
|
212
209
|
function wt(e) {
|
|
210
|
+
return e.reduce((l, s) => Math.max(l, s.top + s.columnHeight), 0) + 500;
|
|
211
|
+
}
|
|
212
|
+
function Mt(e) {
|
|
213
213
|
return {
|
|
214
214
|
transform: `translate3d(${e.left}px, ${e.top}px, 0)`,
|
|
215
215
|
top: "0px",
|
|
@@ -220,7 +220,7 @@ function wt(e) {
|
|
|
220
220
|
}
|
|
221
221
|
function Tt(e, o = 0) {
|
|
222
222
|
return {
|
|
223
|
-
style:
|
|
223
|
+
style: Mt(e),
|
|
224
224
|
"data-top": e.top,
|
|
225
225
|
"data-left": e.left,
|
|
226
226
|
"data-id": `${e.page}-${e.id}`,
|
|
@@ -230,9 +230,9 @@ function Tt(e, o = 0) {
|
|
|
230
230
|
function me(e, o) {
|
|
231
231
|
if (!e.length || o <= 0)
|
|
232
232
|
return new Array(Math.max(1, o)).fill(0);
|
|
233
|
-
const
|
|
234
|
-
for (let a = 0; a <
|
|
235
|
-
const v = new Array(
|
|
233
|
+
const s = Array.from(new Set(e.map((a) => a.left))).sort((a, n) => a - n).slice(0, o), h = /* @__PURE__ */ new Map();
|
|
234
|
+
for (let a = 0; a < s.length; a++) h.set(s[a], a);
|
|
235
|
+
const v = new Array(s.length).fill(0);
|
|
236
236
|
for (const a of e) {
|
|
237
237
|
const n = h.get(a.left);
|
|
238
238
|
n != null && (v[n] = Math.max(v[n], a.top + a.columnHeight));
|
|
@@ -240,7 +240,7 @@ function me(e, o) {
|
|
|
240
240
|
for (; v.length < o; ) v.push(0);
|
|
241
241
|
return v;
|
|
242
242
|
}
|
|
243
|
-
function
|
|
243
|
+
function It(e, o) {
|
|
244
244
|
function l(a, n) {
|
|
245
245
|
const d = parseInt(a.dataset.left || "0", 10), u = parseInt(a.dataset.top || "0", 10), c = parseInt(a.dataset.index || "0", 10), b = Math.min(c * 20, 160), m = a.style.getPropertyValue("--masonry-opacity-delay");
|
|
246
246
|
a.style.setProperty("--masonry-opacity-delay", `${b}ms`), requestAnimationFrame(() => {
|
|
@@ -251,7 +251,7 @@ function Mt(e, o) {
|
|
|
251
251
|
a.addEventListener("transitionend", x);
|
|
252
252
|
});
|
|
253
253
|
}
|
|
254
|
-
function
|
|
254
|
+
function s(a) {
|
|
255
255
|
const n = parseInt(a.dataset.left || "0", 10), d = parseInt(a.dataset.top || "0", 10);
|
|
256
256
|
a.style.opacity = "0", a.style.transform = `translate3d(${n}px, ${d + 10}px, 0) scale(0.985)`;
|
|
257
257
|
}
|
|
@@ -265,7 +265,7 @@ function Mt(e, o) {
|
|
|
265
265
|
const d = parseInt(a.dataset.left || "0", 10), u = parseInt(a.dataset.top || "0", 10), c = typeof (o == null ? void 0 : o.leaveDurationMs) == "number" ? o.leaveDurationMs : NaN;
|
|
266
266
|
let b = Number.isFinite(c) && c > 0 ? c : NaN;
|
|
267
267
|
if (!Number.isFinite(b)) {
|
|
268
|
-
const
|
|
268
|
+
const M = getComputedStyle(a).getPropertyValue("--masonry-leave-duration") || "", P = parseFloat(M);
|
|
269
269
|
b = Number.isFinite(P) && P > 0 ? P : 200;
|
|
270
270
|
}
|
|
271
271
|
const m = a.style.transitionDuration, x = () => {
|
|
@@ -281,16 +281,16 @@ function Mt(e, o) {
|
|
|
281
281
|
}
|
|
282
282
|
return {
|
|
283
283
|
onEnter: l,
|
|
284
|
-
onBeforeEnter:
|
|
284
|
+
onBeforeEnter: s,
|
|
285
285
|
onBeforeLeave: h,
|
|
286
286
|
onLeave: v
|
|
287
287
|
};
|
|
288
288
|
}
|
|
289
|
-
function
|
|
289
|
+
function Pt({
|
|
290
290
|
container: e,
|
|
291
291
|
masonry: o,
|
|
292
292
|
columns: l,
|
|
293
|
-
containerHeight:
|
|
293
|
+
containerHeight: s,
|
|
294
294
|
isLoading: h,
|
|
295
295
|
pageSize: v,
|
|
296
296
|
refreshLayout: a,
|
|
@@ -303,7 +303,7 @@ function It({
|
|
|
303
303
|
if (!e.value) return;
|
|
304
304
|
const x = m ?? me(o.value, l.value), F = x.length ? Math.max(...x) : 0, _ = e.value.scrollTop + e.value.clientHeight, H = e.value.scrollTop > c + 1;
|
|
305
305
|
c = e.value.scrollTop;
|
|
306
|
-
const
|
|
306
|
+
const M = typeof u == "number" ? u : 200, P = M >= 0 ? Math.max(0, F - M) : Math.max(0, F + M);
|
|
307
307
|
if (_ >= P && H && !h.value) {
|
|
308
308
|
await d(), await Q();
|
|
309
309
|
return;
|
|
@@ -313,20 +313,20 @@ function It({
|
|
|
313
313
|
handleScroll: b
|
|
314
314
|
};
|
|
315
315
|
}
|
|
316
|
-
const
|
|
316
|
+
const St = { class: "relative w-full h-full group" }, kt = { class: "w-full h-full rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-all duration-300 bg-white relative" }, Et = {
|
|
317
317
|
key: 0,
|
|
318
318
|
class: "absolute inset-0 flex items-center justify-center bg-slate-100"
|
|
319
|
-
},
|
|
319
|
+
}, Lt = {
|
|
320
320
|
key: 1,
|
|
321
321
|
class: "absolute inset-0 flex flex-col items-center justify-center bg-slate-50 text-slate-400 text-sm p-4 text-center"
|
|
322
|
-
},
|
|
322
|
+
}, Ht = ["src"], Nt = { class: "absolute bottom-0 left-0 right-0 p-3 opacity-0 group-hover:opacity-100 transform translate-y-2 group-hover:translate-y-0 transition-all duration-300 delay-75" }, $t = { class: "text-white text-xs font-medium truncate drop-shadow-md" }, ve = /* @__PURE__ */ Le({
|
|
323
323
|
__name: "MasonryItem",
|
|
324
324
|
props: {
|
|
325
325
|
item: {},
|
|
326
326
|
remove: { type: Function }
|
|
327
327
|
},
|
|
328
328
|
setup(e) {
|
|
329
|
-
const o = e, l = L(!1),
|
|
329
|
+
const o = e, l = L(!1), s = L(!1), h = L(null);
|
|
330
330
|
function v(a) {
|
|
331
331
|
return new Promise((n, d) => {
|
|
332
332
|
if (!a) {
|
|
@@ -337,50 +337,50 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
337
337
|
u.onload = () => {
|
|
338
338
|
const m = Date.now() - c, x = Math.max(0, b - m);
|
|
339
339
|
setTimeout(() => {
|
|
340
|
-
l.value = !0,
|
|
340
|
+
l.value = !0, s.value = !1, n();
|
|
341
341
|
}, x);
|
|
342
342
|
}, u.onerror = () => {
|
|
343
|
-
|
|
343
|
+
s.value = !0, l.value = !1, d(new Error("Failed to load image"));
|
|
344
344
|
}, u.src = a;
|
|
345
345
|
});
|
|
346
346
|
}
|
|
347
|
-
return
|
|
347
|
+
return He(async () => {
|
|
348
348
|
var n, d;
|
|
349
349
|
console.log("[MasonryItem] Component mounted", (n = o.item) == null ? void 0 : n.id);
|
|
350
350
|
const a = (d = o.item) == null ? void 0 : d.src;
|
|
351
351
|
if (a) {
|
|
352
|
-
h.value = a, l.value = !1,
|
|
352
|
+
h.value = a, l.value = !1, s.value = !1;
|
|
353
353
|
try {
|
|
354
354
|
await v(a);
|
|
355
355
|
} catch {
|
|
356
356
|
}
|
|
357
357
|
}
|
|
358
|
-
}),
|
|
358
|
+
}), Ne(
|
|
359
359
|
() => {
|
|
360
360
|
var a;
|
|
361
361
|
return (a = o.item) == null ? void 0 : a.src;
|
|
362
362
|
},
|
|
363
363
|
async (a) => {
|
|
364
364
|
if (a && a !== h.value) {
|
|
365
|
-
l.value = !1,
|
|
365
|
+
l.value = !1, s.value = !1, h.value = a;
|
|
366
366
|
try {
|
|
367
367
|
await v(a);
|
|
368
368
|
} catch {
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
371
|
}
|
|
372
|
-
), (a, n) => (V(), q("div",
|
|
373
|
-
|
|
372
|
+
), (a, n) => (V(), q("div", St, [
|
|
373
|
+
$e(a.$slots, "default", {
|
|
374
374
|
item: a.item,
|
|
375
375
|
remove: a.remove,
|
|
376
376
|
imageLoaded: l.value,
|
|
377
|
-
imageError:
|
|
377
|
+
imageError: s.value
|
|
378
378
|
}, () => [
|
|
379
|
-
O("div",
|
|
380
|
-
!l.value && !
|
|
379
|
+
O("div", kt, [
|
|
380
|
+
!l.value && !s.value ? (V(), q("div", Et, n[1] || (n[1] = [
|
|
381
381
|
O("div", { class: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500" }, null, -1)
|
|
382
382
|
]))) : oe("", !0),
|
|
383
|
-
|
|
383
|
+
s.value ? (V(), q("div", Lt, n[2] || (n[2] = [
|
|
384
384
|
O("i", { class: "fas fa-image text-2xl mb-2 opacity-50" }, null, -1),
|
|
385
385
|
O("span", null, "Failed to load image", -1)
|
|
386
386
|
]))) : oe("", !0),
|
|
@@ -390,24 +390,24 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
390
390
|
class: "w-full h-full object-cover transition-transform duration-500 group-hover:scale-105",
|
|
391
391
|
loading: "lazy",
|
|
392
392
|
decoding: "async"
|
|
393
|
-
}, null, 8,
|
|
393
|
+
}, null, 8, Ht)) : oe("", !0),
|
|
394
394
|
n[4] || (n[4] = O("div", { class: "absolute inset-0 bg-gradient-to-t from-black/50 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" }, null, -1)),
|
|
395
395
|
a.remove ? (V(), q("button", {
|
|
396
396
|
key: 3,
|
|
397
397
|
class: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center bg-white/90 backdrop-blur-sm text-slate-700 rounded-full shadow-sm opacity-0 group-hover:opacity-100 transform translate-y-2 group-hover:translate-y-0 transition-all duration-300 hover:bg-red-500 hover:text-white cursor-pointer",
|
|
398
|
-
onClick: n[0] || (n[0] =
|
|
398
|
+
onClick: n[0] || (n[0] = ze((d) => a.remove(a.item), ["stop"])),
|
|
399
399
|
"aria-label": "Remove item"
|
|
400
400
|
}, n[3] || (n[3] = [
|
|
401
401
|
O("i", { class: "fas fa-times text-sm" }, null, -1)
|
|
402
402
|
]))) : oe("", !0),
|
|
403
|
-
O("div",
|
|
404
|
-
O("p",
|
|
403
|
+
O("div", Nt, [
|
|
404
|
+
O("p", $t, "Item #" + de(String(a.item.id).split("-")[0]), 1)
|
|
405
405
|
])
|
|
406
406
|
])
|
|
407
407
|
])
|
|
408
408
|
]));
|
|
409
409
|
}
|
|
410
|
-
}), At = /* @__PURE__ */
|
|
410
|
+
}), At = /* @__PURE__ */ Le({
|
|
411
411
|
__name: "Masonry",
|
|
412
412
|
props: {
|
|
413
413
|
getNextPage: {
|
|
@@ -508,7 +508,7 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
508
508
|
"remove-all:complete"
|
|
509
509
|
],
|
|
510
510
|
setup(e, { expose: o, emit: l }) {
|
|
511
|
-
const
|
|
511
|
+
const s = e, h = {
|
|
512
512
|
sizes: { base: 1, sm: 2, md: 3, lg: 4, xl: 5, "2xl": 6 },
|
|
513
513
|
gutterX: 10,
|
|
514
514
|
gutterY: 10,
|
|
@@ -517,18 +517,18 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
517
517
|
paddingLeft: 0,
|
|
518
518
|
paddingRight: 0,
|
|
519
519
|
placement: "masonry"
|
|
520
|
-
}, v =
|
|
520
|
+
}, v = se(() => {
|
|
521
521
|
var t;
|
|
522
522
|
return {
|
|
523
523
|
...h,
|
|
524
|
-
...
|
|
524
|
+
...s.layout,
|
|
525
525
|
sizes: {
|
|
526
526
|
...h.sizes,
|
|
527
|
-
...((t =
|
|
527
|
+
...((t = s.layout) == null ? void 0 : t.sizes) || {}
|
|
528
528
|
}
|
|
529
529
|
};
|
|
530
|
-
}), a = l, n =
|
|
531
|
-
get: () =>
|
|
530
|
+
}), a = l, n = se({
|
|
531
|
+
get: () => s.items,
|
|
532
532
|
set: (t) => a("update:items", t)
|
|
533
533
|
}), d = L(7), u = L(null), c = L([]), b = L(null), m = L(!1), x = L(0), F = L(/* @__PURE__ */ new Set());
|
|
534
534
|
function _(t) {
|
|
@@ -537,10 +537,10 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
537
537
|
function H(t, r) {
|
|
538
538
|
try {
|
|
539
539
|
if (!Array.isArray(t) || t.length === 0) return;
|
|
540
|
-
const
|
|
541
|
-
if (
|
|
540
|
+
const i = t.filter((g) => !_(g == null ? void 0 : g.width) || !_(g == null ? void 0 : g.height));
|
|
541
|
+
if (i.length === 0) return;
|
|
542
542
|
const f = [];
|
|
543
|
-
for (const g of
|
|
543
|
+
for (const g of i) {
|
|
544
544
|
const A = (g == null ? void 0 : g.id) ?? `idx:${t.indexOf(g)}`;
|
|
545
545
|
F.value.has(A) || (F.value.add(A), f.push(A));
|
|
546
546
|
}
|
|
@@ -559,21 +559,21 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
559
559
|
} catch {
|
|
560
560
|
}
|
|
561
561
|
}
|
|
562
|
-
const
|
|
562
|
+
const M = L(0), P = L(0), U = s.virtualBufferPx, S = L(!1), T = L({
|
|
563
563
|
distanceToTrigger: 0,
|
|
564
564
|
isNearTrigger: !1
|
|
565
565
|
}), y = (t) => {
|
|
566
566
|
if (!u.value) return;
|
|
567
|
-
const { scrollTop: r, clientHeight:
|
|
568
|
-
|
|
569
|
-
distanceToTrigger: Math.round(
|
|
570
|
-
isNearTrigger:
|
|
567
|
+
const { scrollTop: r, clientHeight: i } = u.value, f = r + i, g = t ?? me(n.value, d.value), A = g.length ? Math.max(...g) : 0, C = typeof s.loadThresholdPx == "number" ? s.loadThresholdPx : 200, K = C >= 0 ? Math.max(0, A - C) : Math.max(0, A + C), xe = Math.max(0, K - f), je = xe <= 100;
|
|
568
|
+
T.value = {
|
|
569
|
+
distanceToTrigger: Math.round(xe),
|
|
570
|
+
isNearTrigger: je
|
|
571
571
|
};
|
|
572
|
-
}, { onEnter: W, onBeforeEnter: w, onBeforeLeave: N, onLeave: I } =
|
|
572
|
+
}, { onEnter: W, onBeforeEnter: w, onBeforeLeave: N, onLeave: I } = It(n, { leaveDurationMs: s.leaveDurationMs });
|
|
573
573
|
function D(t, r) {
|
|
574
574
|
if (S.value) {
|
|
575
|
-
const
|
|
576
|
-
t.style.transition = "none", t.style.opacity = "1", t.style.transform = `translate3d(${
|
|
575
|
+
const i = parseInt(t.dataset.left || "0", 10), f = parseInt(t.dataset.top || "0", 10);
|
|
576
|
+
t.style.transition = "none", t.style.opacity = "1", t.style.transform = `translate3d(${i}px, ${f}px, 0) scale(1)`, t.style.removeProperty("--masonry-opacity-delay"), requestAnimationFrame(() => {
|
|
577
577
|
t.style.transition = "", r();
|
|
578
578
|
});
|
|
579
579
|
} else
|
|
@@ -581,8 +581,8 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
581
581
|
}
|
|
582
582
|
function Z(t) {
|
|
583
583
|
if (S.value) {
|
|
584
|
-
const r = parseInt(t.dataset.left || "0", 10),
|
|
585
|
-
t.style.transition = "none", t.style.opacity = "1", t.style.transform = `translate3d(${r}px, ${
|
|
584
|
+
const r = parseInt(t.dataset.left || "0", 10), i = parseInt(t.dataset.top || "0", 10);
|
|
585
|
+
t.style.transition = "none", t.style.opacity = "1", t.style.transform = `translate3d(${r}px, ${i}px, 0) scale(1)`, t.style.removeProperty("--masonry-opacity-delay");
|
|
586
586
|
} else
|
|
587
587
|
w(t);
|
|
588
588
|
}
|
|
@@ -592,25 +592,25 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
592
592
|
function X(t, r) {
|
|
593
593
|
S.value ? r() : I(t, r);
|
|
594
594
|
}
|
|
595
|
-
const te =
|
|
596
|
-
const t =
|
|
597
|
-
return !
|
|
595
|
+
const te = se(() => {
|
|
596
|
+
const t = M.value - U, r = M.value + P.value + U, i = n.value;
|
|
597
|
+
return !i || i.length === 0 ? [] : i.filter((f) => {
|
|
598
598
|
const g = f.top;
|
|
599
599
|
return f.top + f.columnHeight >= t && g <= r;
|
|
600
600
|
});
|
|
601
|
-
}), { handleScroll: Y } =
|
|
601
|
+
}), { handleScroll: Y } = Pt({
|
|
602
602
|
container: u,
|
|
603
603
|
masonry: n,
|
|
604
604
|
columns: d,
|
|
605
605
|
containerHeight: x,
|
|
606
606
|
isLoading: m,
|
|
607
|
-
pageSize:
|
|
607
|
+
pageSize: s.pageSize,
|
|
608
608
|
refreshLayout: j,
|
|
609
609
|
setItemsRaw: (t) => {
|
|
610
610
|
n.value = t;
|
|
611
611
|
},
|
|
612
612
|
loadNext: z,
|
|
613
|
-
loadThresholdPx:
|
|
613
|
+
loadThresholdPx: s.loadThresholdPx
|
|
614
614
|
});
|
|
615
615
|
o({
|
|
616
616
|
isLoading: m,
|
|
@@ -618,25 +618,25 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
618
618
|
containerHeight: x,
|
|
619
619
|
remove: G,
|
|
620
620
|
removeMany: R,
|
|
621
|
-
removeAll:
|
|
621
|
+
removeAll: Be,
|
|
622
622
|
loadNext: z,
|
|
623
623
|
loadPage: B,
|
|
624
624
|
refreshCurrentPage: $,
|
|
625
|
-
reset:
|
|
626
|
-
init:
|
|
625
|
+
reset: Oe,
|
|
626
|
+
init: De,
|
|
627
627
|
paginationHistory: c,
|
|
628
|
-
cancelLoad:
|
|
629
|
-
scrollToTop:
|
|
630
|
-
totalItems:
|
|
628
|
+
cancelLoad: he,
|
|
629
|
+
scrollToTop: pe,
|
|
630
|
+
totalItems: se(() => n.value.length)
|
|
631
631
|
});
|
|
632
632
|
function J(t) {
|
|
633
|
-
const r =
|
|
634
|
-
let
|
|
633
|
+
const r = wt(t);
|
|
634
|
+
let i = 0;
|
|
635
635
|
if (u.value) {
|
|
636
636
|
const { scrollTop: f, clientHeight: g } = u.value;
|
|
637
|
-
|
|
637
|
+
i = f + g + 100;
|
|
638
638
|
}
|
|
639
|
-
x.value = Math.max(r,
|
|
639
|
+
x.value = Math.max(r, i);
|
|
640
640
|
}
|
|
641
641
|
function j(t) {
|
|
642
642
|
if (!u.value) return;
|
|
@@ -644,26 +644,26 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
644
644
|
const r = t.map((f, g) => ({
|
|
645
645
|
...f,
|
|
646
646
|
originalIndex: f.originalIndex ?? g
|
|
647
|
-
})),
|
|
648
|
-
J(
|
|
647
|
+
})), i = Ye(r, u.value, d.value, v.value);
|
|
648
|
+
J(i), n.value = i;
|
|
649
649
|
}
|
|
650
650
|
function ae(t, r) {
|
|
651
|
-
return new Promise((
|
|
651
|
+
return new Promise((i) => {
|
|
652
652
|
const f = Math.max(0, t | 0), g = Date.now();
|
|
653
653
|
r(f, f);
|
|
654
654
|
const A = setInterval(() => {
|
|
655
655
|
if (E.value) {
|
|
656
|
-
clearInterval(A),
|
|
656
|
+
clearInterval(A), i();
|
|
657
657
|
return;
|
|
658
658
|
}
|
|
659
659
|
const C = Date.now() - g, K = Math.max(0, f - C);
|
|
660
|
-
r(K, f), K <= 0 && (clearInterval(A),
|
|
660
|
+
r(K, f), K <= 0 && (clearInterval(A), i());
|
|
661
661
|
}, 100);
|
|
662
662
|
});
|
|
663
663
|
}
|
|
664
664
|
async function p(t) {
|
|
665
665
|
try {
|
|
666
|
-
const r = await k(() =>
|
|
666
|
+
const r = await k(() => s.getNextPage(t));
|
|
667
667
|
return j([...n.value, ...r.items]), r;
|
|
668
668
|
} catch (r) {
|
|
669
669
|
throw console.error("Error in getContent:", r), r;
|
|
@@ -671,18 +671,18 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
671
671
|
}
|
|
672
672
|
async function k(t) {
|
|
673
673
|
let r = 0;
|
|
674
|
-
const
|
|
675
|
-
let f =
|
|
674
|
+
const i = s.retryMaxAttempts;
|
|
675
|
+
let f = s.retryInitialDelayMs;
|
|
676
676
|
for (; ; )
|
|
677
677
|
try {
|
|
678
678
|
const g = await t();
|
|
679
679
|
return r > 0 && a("retry:stop", { attempt: r, success: !0 }), g;
|
|
680
680
|
} catch (g) {
|
|
681
|
-
if (r++, r >
|
|
681
|
+
if (r++, r > i)
|
|
682
682
|
throw a("retry:stop", { attempt: r - 1, success: !1 }), g;
|
|
683
|
-
a("retry:start", { attempt: r, max:
|
|
683
|
+
a("retry:start", { attempt: r, max: i, totalMs: f }), await ae(f, (A, C) => {
|
|
684
684
|
a("retry:tick", { attempt: r, remainingMs: A, totalMs: C });
|
|
685
|
-
}), f +=
|
|
685
|
+
}), f += s.retryBackoffStepMs;
|
|
686
686
|
}
|
|
687
687
|
}
|
|
688
688
|
async function B(t) {
|
|
@@ -691,8 +691,8 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
691
691
|
try {
|
|
692
692
|
const r = n.value.length;
|
|
693
693
|
if (E.value) return;
|
|
694
|
-
const
|
|
695
|
-
return E.value ? void 0 : (b.value = t, c.value.push(
|
|
694
|
+
const i = await p(t);
|
|
695
|
+
return E.value ? void 0 : (b.value = t, c.value.push(i.nextPage), await ne(r), i);
|
|
696
696
|
} catch (r) {
|
|
697
697
|
throw console.error("Error loading page:", r), r;
|
|
698
698
|
} finally {
|
|
@@ -706,8 +706,8 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
706
706
|
try {
|
|
707
707
|
const t = n.value.length;
|
|
708
708
|
if (E.value) return;
|
|
709
|
-
const r = c.value[c.value.length - 1],
|
|
710
|
-
return E.value ? void 0 : (b.value = r, c.value.push(
|
|
709
|
+
const r = c.value[c.value.length - 1], i = await p(r);
|
|
710
|
+
return E.value ? void 0 : (b.value = r, c.value.push(i.nextPage), await ne(t), i);
|
|
711
711
|
} catch (t) {
|
|
712
712
|
throw console.error("Error loading next page:", t), t;
|
|
713
713
|
} finally {
|
|
@@ -728,8 +728,8 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
728
728
|
const r = await p(t);
|
|
729
729
|
if (E.value) return;
|
|
730
730
|
b.value = t, c.value.push(r.nextPage);
|
|
731
|
-
const
|
|
732
|
-
return await ne(
|
|
731
|
+
const i = n.value.length;
|
|
732
|
+
return await ne(i), r;
|
|
733
733
|
} catch (t) {
|
|
734
734
|
throw console.error("[Masonry] Error refreshing current page:", t), t;
|
|
735
735
|
} finally {
|
|
@@ -738,9 +738,9 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
738
738
|
}
|
|
739
739
|
}
|
|
740
740
|
async function G(t) {
|
|
741
|
-
const r = n.value.filter((
|
|
741
|
+
const r = n.value.filter((i) => i.id !== t.id);
|
|
742
742
|
if (n.value = r, await Q(), console.log("[Masonry] remove - next.length:", r.length, "paginationHistory.length:", c.value.length), r.length === 0 && c.value.length > 0) {
|
|
743
|
-
if (
|
|
743
|
+
if (s.autoRefreshOnEmpty)
|
|
744
744
|
console.log("[Masonry] All items removed, calling refreshCurrentPage"), await $();
|
|
745
745
|
else {
|
|
746
746
|
console.log("[Masonry] All items removed, calling loadNext and forcing backfill");
|
|
@@ -751,15 +751,15 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
751
751
|
}
|
|
752
752
|
return;
|
|
753
753
|
}
|
|
754
|
-
await new Promise((
|
|
754
|
+
await new Promise((i) => requestAnimationFrame(() => i())), requestAnimationFrame(() => {
|
|
755
755
|
j(r);
|
|
756
756
|
});
|
|
757
757
|
}
|
|
758
758
|
async function R(t) {
|
|
759
759
|
if (!t || t.length === 0) return;
|
|
760
|
-
const r = new Set(t.map((f) => f.id)),
|
|
761
|
-
if (n.value =
|
|
762
|
-
if (
|
|
760
|
+
const r = new Set(t.map((f) => f.id)), i = n.value.filter((f) => !r.has(f.id));
|
|
761
|
+
if (n.value = i, await Q(), i.length === 0 && c.value.length > 0) {
|
|
762
|
+
if (s.autoRefreshOnEmpty)
|
|
763
763
|
await $();
|
|
764
764
|
else
|
|
765
765
|
try {
|
|
@@ -769,35 +769,35 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
769
769
|
return;
|
|
770
770
|
}
|
|
771
771
|
await new Promise((f) => requestAnimationFrame(() => f())), requestAnimationFrame(() => {
|
|
772
|
-
j(
|
|
772
|
+
j(i);
|
|
773
773
|
});
|
|
774
774
|
}
|
|
775
|
-
function
|
|
775
|
+
function pe(t) {
|
|
776
776
|
u.value && u.value.scrollTo({
|
|
777
777
|
top: 0,
|
|
778
778
|
behavior: (t == null ? void 0 : t.behavior) ?? "smooth",
|
|
779
779
|
...t
|
|
780
780
|
});
|
|
781
781
|
}
|
|
782
|
-
async function
|
|
783
|
-
|
|
782
|
+
async function Be() {
|
|
783
|
+
pe({ behavior: "smooth" }), n.value = [], x.value = 0, await Q(), a("remove-all:complete");
|
|
784
784
|
}
|
|
785
|
-
function
|
|
786
|
-
d.value = fe(v.value), j(n.value), u.value && (
|
|
785
|
+
function Fe() {
|
|
786
|
+
d.value = fe(v.value), j(n.value), u.value && (M.value = u.value.scrollTop, P.value = u.value.clientHeight);
|
|
787
787
|
}
|
|
788
788
|
let le = !1;
|
|
789
789
|
const E = L(!1);
|
|
790
790
|
async function ne(t, r = !1) {
|
|
791
|
-
if (!r && !
|
|
792
|
-
const
|
|
793
|
-
if (!(!
|
|
791
|
+
if (!r && !s.backfillEnabled || le || E.value) return;
|
|
792
|
+
const i = (t || 0) + (s.pageSize || 0);
|
|
793
|
+
if (!(!s.pageSize || s.pageSize <= 0 || c.value[c.value.length - 1] == null) && !(n.value.length >= i)) {
|
|
794
794
|
le = !0;
|
|
795
795
|
try {
|
|
796
796
|
let g = 0;
|
|
797
|
-
for (a("backfill:start", { target:
|
|
797
|
+
for (a("backfill:start", { target: i, fetched: n.value.length, calls: g }); n.value.length < i && g < s.backfillMaxCalls && c.value[c.value.length - 1] != null && !E.value && (await ae(s.backfillDelayMs, (C, K) => {
|
|
798
798
|
a("backfill:tick", {
|
|
799
799
|
fetched: n.value.length,
|
|
800
|
-
target:
|
|
800
|
+
target: i,
|
|
801
801
|
calls: g,
|
|
802
802
|
remainingMs: C,
|
|
803
803
|
totalMs: K
|
|
@@ -820,55 +820,55 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
820
820
|
}
|
|
821
821
|
}
|
|
822
822
|
}
|
|
823
|
-
function
|
|
823
|
+
function he() {
|
|
824
824
|
E.value = !0, m.value = !1, le = !1;
|
|
825
825
|
}
|
|
826
|
-
function
|
|
827
|
-
|
|
826
|
+
function Oe() {
|
|
827
|
+
he(), E.value = !1, u.value && u.value.scrollTo({
|
|
828
828
|
top: 0,
|
|
829
829
|
behavior: "smooth"
|
|
830
|
-
}), n.value = [], x.value = 0, b.value =
|
|
830
|
+
}), n.value = [], x.value = 0, b.value = s.loadAtPage, c.value = [s.loadAtPage], T.value = {
|
|
831
831
|
distanceToTrigger: 0,
|
|
832
832
|
isNearTrigger: !1
|
|
833
833
|
};
|
|
834
834
|
}
|
|
835
|
-
const
|
|
836
|
-
u.value && (
|
|
835
|
+
const ye = ke(async () => {
|
|
836
|
+
u.value && (M.value = u.value.scrollTop, P.value = u.value.clientHeight), S.value = !0, await Q(), await new Promise((r) => requestAnimationFrame(() => r())), S.value = !1;
|
|
837
837
|
const t = me(n.value, d.value);
|
|
838
838
|
Y(t), y(t);
|
|
839
|
-
}, 200),
|
|
840
|
-
function
|
|
841
|
-
b.value = r, c.value = [r], c.value.push(
|
|
839
|
+
}, 200), be = ke(Fe, 200);
|
|
840
|
+
function De(t, r, i) {
|
|
841
|
+
b.value = r, c.value = [r], c.value.push(i), H(t, "init"), j([...n.value, ...t]), y();
|
|
842
842
|
}
|
|
843
|
-
return
|
|
843
|
+
return Ne(
|
|
844
844
|
v,
|
|
845
845
|
() => {
|
|
846
846
|
u.value && (d.value = fe(v.value), j(n.value));
|
|
847
847
|
},
|
|
848
848
|
{ deep: !0 }
|
|
849
|
-
),
|
|
849
|
+
), He(async () => {
|
|
850
850
|
var t;
|
|
851
851
|
try {
|
|
852
|
-
d.value = fe(v.value), u.value && (
|
|
853
|
-
const r =
|
|
854
|
-
c.value = [r],
|
|
852
|
+
d.value = fe(v.value), u.value && (M.value = u.value.scrollTop, P.value = u.value.clientHeight);
|
|
853
|
+
const r = s.loadAtPage;
|
|
854
|
+
c.value = [r], s.skipInitialLoad || await B(c.value[0]), y();
|
|
855
855
|
} catch (r) {
|
|
856
856
|
console.error("Error during component initialization:", r), m.value = !1;
|
|
857
857
|
}
|
|
858
|
-
(t = u.value) == null || t.addEventListener("scroll",
|
|
859
|
-
}),
|
|
858
|
+
(t = u.value) == null || t.addEventListener("scroll", ye, { passive: !0 }), window.addEventListener("resize", be);
|
|
859
|
+
}), Re(() => {
|
|
860
860
|
var t;
|
|
861
|
-
(t = u.value) == null || t.removeEventListener("scroll",
|
|
861
|
+
(t = u.value) == null || t.removeEventListener("scroll", ye), window.removeEventListener("resize", be);
|
|
862
862
|
}), (t, r) => (V(), q("div", {
|
|
863
|
-
class:
|
|
863
|
+
class: we(["overflow-auto w-full flex-1 masonry-container", { "force-motion": s.forceMotion }]),
|
|
864
864
|
ref_key: "container",
|
|
865
865
|
ref: u
|
|
866
866
|
}, [
|
|
867
867
|
O("div", {
|
|
868
868
|
class: "relative",
|
|
869
|
-
style:
|
|
869
|
+
style: Ce({ height: `${x.value}px`, "--masonry-duration": `${e.transitionDurationMs}ms`, "--masonry-leave-duration": `${e.leaveDurationMs}ms`, "--masonry-ease": e.transitionEasing })
|
|
870
870
|
}, [
|
|
871
|
-
|
|
871
|
+
Me(_e, {
|
|
872
872
|
name: "masonry",
|
|
873
873
|
css: !1,
|
|
874
874
|
onEnter: D,
|
|
@@ -876,17 +876,17 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
876
876
|
onLeave: X,
|
|
877
877
|
onBeforeLeave: ee
|
|
878
878
|
}, {
|
|
879
|
-
default:
|
|
880
|
-
(V(!0), q(
|
|
881
|
-
key: `${
|
|
879
|
+
default: qe(() => [
|
|
880
|
+
(V(!0), q(Ve, null, Ge(te.value, (i, f) => (V(), q("div", Te({
|
|
881
|
+
key: `${i.page}-${i.id}`,
|
|
882
882
|
class: "absolute masonry-item",
|
|
883
883
|
ref_for: !0
|
|
884
|
-
},
|
|
884
|
+
}, Ue(Tt)(i, f), {
|
|
885
885
|
style: { paddingTop: `${v.value.header}px`, paddingBottom: `${v.value.footer}px` }
|
|
886
886
|
}), [
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
item:
|
|
887
|
+
$e(t.$slots, "item", Te({ ref_for: !0 }, { item: i, remove: G }), () => [
|
|
888
|
+
Me(ve, {
|
|
889
|
+
item: i,
|
|
890
890
|
remove: G
|
|
891
891
|
}, null, 8, ["item"])
|
|
892
892
|
], !0)
|
|
@@ -896,26 +896,27 @@ const Pt = { class: "relative w-full h-full group" }, St = { class: "w-full h-fu
|
|
|
896
896
|
}),
|
|
897
897
|
x.value > 0 ? (V(), q("div", {
|
|
898
898
|
key: 0,
|
|
899
|
-
class:
|
|
899
|
+
class: we(["fixed bottom-4 right-4 bg-gray-800 text-white text-xs rounded-full px-3 py-1.5 shadow-lg z-10 transition-opacity duration-300", { "opacity-50 hover:opacity-100": !T.value.isNearTrigger, "opacity-100": T.value.isNearTrigger }])
|
|
900
900
|
}, [
|
|
901
901
|
O("span", null, de(n.value.length) + " items", 1),
|
|
902
902
|
r[0] || (r[0] = O("span", { class: "mx-2" }, "|", -1)),
|
|
903
|
-
O("span", null, de(
|
|
903
|
+
O("span", null, de(T.value.distanceToTrigger) + "px to load", 1)
|
|
904
904
|
], 2)) : oe("", !0)
|
|
905
905
|
], 4)
|
|
906
906
|
], 2));
|
|
907
907
|
}
|
|
908
908
|
}), Wt = (e, o) => {
|
|
909
909
|
const l = e.__vccOpts || e;
|
|
910
|
-
for (const [
|
|
911
|
-
l[
|
|
910
|
+
for (const [s, h] of o)
|
|
911
|
+
l[s] = h;
|
|
912
912
|
return l;
|
|
913
|
-
},
|
|
913
|
+
}, Ee = /* @__PURE__ */ Wt(At, [["__scopeId", "data-v-08b0e6d9"]]), Ft = {
|
|
914
914
|
install(e) {
|
|
915
|
-
e.component("WyxosMasonry",
|
|
915
|
+
e.component("WyxosMasonry", Ee), e.component("WMasonry", Ee), e.component("WyxosMasonryItem", ve), e.component("WMasonryItem", ve);
|
|
916
916
|
}
|
|
917
917
|
};
|
|
918
918
|
export {
|
|
919
|
-
|
|
919
|
+
Ee as Masonry,
|
|
920
|
+
ve as MasonryItem,
|
|
920
921
|
Ft as default
|
|
921
922
|
};
|