@wyxos/vibe 1.6.25 → 1.6.27
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 +287 -254
- package/lib/index.js +1201 -1115
- package/lib/vibe.css +1 -1
- package/package.json +1 -1
- package/src/Masonry.vue +159 -188
- package/src/components/MasonryItem.vue +501 -434
- package/src/components/examples/BasicExample.vue +2 -1
- package/src/components/examples/CustomItemExample.vue +2 -1
- package/src/components/examples/HeaderFooterExample.vue +79 -78
- package/src/components/examples/ManualInitExample.vue +78 -0
- package/src/components/examples/SwipeModeExample.vue +2 -1
- package/src/{useMasonryTransitions.ts → createMasonryTransitions.ts} +6 -6
- package/src/useMasonryItems.ts +234 -218
- package/src/useMasonryLayout.ts +4 -0
- package/src/useMasonryPagination.ts +465 -342
- package/src/views/Examples.vue +80 -32
- package/src/views/Home.vue +321 -321
package/src/views/Examples.vue
CHANGED
|
@@ -8,14 +8,10 @@
|
|
|
8
8
|
<h3 class="text-sm font-semibold text-slate-400 uppercase tracking-wider mb-4">Examples</h3>
|
|
9
9
|
<ul class="space-y-2">
|
|
10
10
|
<li v-for="example in examples" :key="example.id">
|
|
11
|
-
<a
|
|
12
|
-
:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
:class="activeSection === example.id
|
|
16
|
-
? 'bg-blue-50 text-blue-600 font-medium'
|
|
17
|
-
: 'text-slate-600 hover:bg-slate-50 hover:text-slate-900'"
|
|
18
|
-
>
|
|
11
|
+
<a :href="`#${example.id}`" @click.prevent="scrollTo(example.id)"
|
|
12
|
+
class="block px-3 py-2 text-sm rounded-md transition-colors" :class="activeSection === example.id
|
|
13
|
+
? 'bg-blue-50 text-blue-600 font-medium'
|
|
14
|
+
: 'text-slate-600 hover:bg-slate-50 hover:text-slate-900'">
|
|
19
15
|
{{ example.title }}
|
|
20
16
|
</a>
|
|
21
17
|
</li>
|
|
@@ -33,7 +29,7 @@
|
|
|
33
29
|
<h2 class="text-2xl font-bold text-slate-800">Basic Usage</h2>
|
|
34
30
|
<p class="text-slate-600 mt-1">Simple masonry grid with default MasonryItem component</p>
|
|
35
31
|
</div>
|
|
36
|
-
|
|
32
|
+
|
|
37
33
|
<!-- Live Example -->
|
|
38
34
|
<div class="p-6 bg-slate-50">
|
|
39
35
|
<div class="bg-white rounded-lg border border-slate-200 p-4" style="height: 500px;">
|
|
@@ -43,14 +39,58 @@
|
|
|
43
39
|
|
|
44
40
|
<!-- Code Tabs -->
|
|
45
41
|
<div class="px-6 pb-6">
|
|
46
|
-
<CodeTabs
|
|
47
|
-
|
|
42
|
+
<CodeTabs vue='<script setup>
|
|
43
|
+
import { ref } from "vue";
|
|
44
|
+
import { Masonry } from "@wyxos/vibe";
|
|
45
|
+
|
|
46
|
+
const items = ref([]);
|
|
47
|
+
|
|
48
|
+
async function getPage(page) {
|
|
49
|
+
const response = await fetch(`/api/items?page=${page}`);
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
return {
|
|
52
|
+
items: data.items,
|
|
53
|
+
nextPage: page + 1
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<template>
|
|
59
|
+
<Masonry
|
|
60
|
+
v-model:items="items"
|
|
61
|
+
:get-page="getPage"
|
|
62
|
+
:load-at-page="1"
|
|
63
|
+
/>
|
|
64
|
+
</template>' />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</section>
|
|
68
|
+
|
|
69
|
+
<!-- Manual Init Example -->
|
|
70
|
+
<section id="manual-init" ref="manualInitRef" class="scroll-mt-24">
|
|
71
|
+
<div class="bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
|
72
|
+
<div class="px-6 py-4 border-b border-slate-200 bg-slate-50">
|
|
73
|
+
<h2 class="text-2xl font-bold text-slate-800">Manual Init CTA</h2>
|
|
74
|
+
<p class="text-slate-600 mt-1">Delay initialization until the user clicks a call-to-action</p>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<!-- Live Example -->
|
|
78
|
+
<div class="p-6 bg-slate-50">
|
|
79
|
+
<div class="bg-white rounded-lg border border-slate-200 p-4" style="height: 500px;">
|
|
80
|
+
<ManualInitExample />
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<!-- Code Tabs -->
|
|
85
|
+
<div class="px-6 pb-6">
|
|
86
|
+
<CodeTabs vue='<script setup>
|
|
48
87
|
import { ref } from "vue";
|
|
49
88
|
import { Masonry } from "@wyxos/vibe";
|
|
50
89
|
|
|
51
90
|
const items = ref([]);
|
|
91
|
+
const masonryRef = ref(null);
|
|
52
92
|
|
|
53
|
-
async function
|
|
93
|
+
async function getPage(page) {
|
|
54
94
|
const response = await fetch(`/api/items?page=${page}`);
|
|
55
95
|
const data = await response.json();
|
|
56
96
|
return {
|
|
@@ -58,16 +98,23 @@ async function getNextPage(page) {
|
|
|
58
98
|
nextPage: page + 1
|
|
59
99
|
};
|
|
60
100
|
}
|
|
101
|
+
|
|
102
|
+
function handleInit() {
|
|
103
|
+
masonryRef.value?.loadPage(1);
|
|
104
|
+
}
|
|
61
105
|
</script>
|
|
62
106
|
|
|
63
107
|
<template>
|
|
108
|
+
<button @click="handleInit">Load gallery</button>
|
|
109
|
+
|
|
64
110
|
<Masonry
|
|
111
|
+
ref="masonryRef"
|
|
65
112
|
v-model:items="items"
|
|
66
|
-
:get-
|
|
113
|
+
:get-page="getPage"
|
|
67
114
|
:load-at-page="1"
|
|
115
|
+
init="manual"
|
|
68
116
|
/>
|
|
69
|
-
</template>'
|
|
70
|
-
/>
|
|
117
|
+
</template>' />
|
|
71
118
|
</div>
|
|
72
119
|
</div>
|
|
73
120
|
</section>
|
|
@@ -79,7 +126,7 @@ async function getNextPage(page) {
|
|
|
79
126
|
<h2 class="text-2xl font-bold text-slate-800">Custom Masonry Item</h2>
|
|
80
127
|
<p class="text-slate-600 mt-1">Customize item rendering with scoped slots</p>
|
|
81
128
|
</div>
|
|
82
|
-
|
|
129
|
+
|
|
83
130
|
<!-- Live Example -->
|
|
84
131
|
<div class="p-6 bg-slate-50">
|
|
85
132
|
<div class="bg-white rounded-lg border border-slate-200 p-4" style="height: 500px;">
|
|
@@ -89,14 +136,13 @@ async function getNextPage(page) {
|
|
|
89
136
|
|
|
90
137
|
<!-- Code Tabs -->
|
|
91
138
|
<div class="px-6 pb-6">
|
|
92
|
-
<CodeTabs
|
|
93
|
-
vue='<script setup>
|
|
139
|
+
<CodeTabs vue='<script setup>
|
|
94
140
|
import { ref } from "vue";
|
|
95
141
|
import { Masonry } from "@wyxos/vibe";
|
|
96
142
|
|
|
97
143
|
const items = ref([]);
|
|
98
144
|
|
|
99
|
-
async function
|
|
145
|
+
async function getPage(page) {
|
|
100
146
|
const response = await fetch(`/api/items?page=${page}`);
|
|
101
147
|
const data = await response.json();
|
|
102
148
|
return {
|
|
@@ -109,7 +155,7 @@ async function getNextPage(page) {
|
|
|
109
155
|
<template>
|
|
110
156
|
<Masonry
|
|
111
157
|
v-model:items="items"
|
|
112
|
-
:get-
|
|
158
|
+
:get-page="getPage"
|
|
113
159
|
:load-at-page="1"
|
|
114
160
|
>
|
|
115
161
|
<template #item="{ item, remove }">
|
|
@@ -122,8 +168,7 @@ async function getNextPage(page) {
|
|
|
122
168
|
</div>
|
|
123
169
|
</template>
|
|
124
170
|
</Masonry>
|
|
125
|
-
</template>'
|
|
126
|
-
/>
|
|
171
|
+
</template>' />
|
|
127
172
|
</div>
|
|
128
173
|
-->
|
|
129
174
|
</div>
|
|
@@ -135,10 +180,11 @@ async function getNextPage(page) {
|
|
|
135
180
|
<div class="px-6 py-4 border-b border-slate-200 bg-slate-50">
|
|
136
181
|
<h2 class="text-2xl font-bold text-slate-800">Header & Footer</h2>
|
|
137
182
|
<p class="text-slate-600 mt-1">
|
|
138
|
-
Use `layout.header` and `layout.footer` with slots to add per-item UI like badges, titles and
|
|
183
|
+
Use `layout.header` and `layout.footer` with slots to add per-item UI like badges, titles and
|
|
184
|
+
actions.
|
|
139
185
|
</p>
|
|
140
186
|
</div>
|
|
141
|
-
|
|
187
|
+
|
|
142
188
|
<!-- Live Example -->
|
|
143
189
|
<div class="p-6 bg-slate-50">
|
|
144
190
|
<div class="bg-white rounded-lg border border-slate-200 p-4" style="height: 500px;">
|
|
@@ -158,7 +204,7 @@ async function getNextPage(page) {
|
|
|
158
204
|
<h2 class="text-2xl font-bold text-slate-800">Swipe Mode</h2>
|
|
159
205
|
<p class="text-slate-600 mt-1">Vertical swipe feed for mobile devices</p>
|
|
160
206
|
</div>
|
|
161
|
-
|
|
207
|
+
|
|
162
208
|
<!-- Live Example -->
|
|
163
209
|
<div class="p-6 bg-slate-50">
|
|
164
210
|
<div class="bg-white rounded-lg border border-slate-200 p-4" style="height: 500px;">
|
|
@@ -168,14 +214,13 @@ async function getNextPage(page) {
|
|
|
168
214
|
|
|
169
215
|
<!-- Code Tabs -->
|
|
170
216
|
<div class="px-6 pb-6">
|
|
171
|
-
<CodeTabs
|
|
172
|
-
vue='<script setup>
|
|
217
|
+
<CodeTabs vue='<script setup>
|
|
173
218
|
import { ref } from "vue";
|
|
174
219
|
import { Masonry } from "@wyxos/vibe";
|
|
175
220
|
|
|
176
221
|
const items = ref([]);
|
|
177
222
|
|
|
178
|
-
async function
|
|
223
|
+
async function getPage(page) {
|
|
179
224
|
const response = await fetch(`/api/items?page=${page}`);
|
|
180
225
|
const data = await response.json();
|
|
181
226
|
return {
|
|
@@ -189,7 +234,7 @@ async function getNextPage(page) {
|
|
|
189
234
|
<!-- Auto mode: switches to swipe on mobile -->
|
|
190
235
|
<Masonry
|
|
191
236
|
v-model:items="items"
|
|
192
|
-
:get-
|
|
237
|
+
:get-page="getPage"
|
|
193
238
|
layout-mode="auto"
|
|
194
239
|
:mobile-breakpoint="768"
|
|
195
240
|
/>
|
|
@@ -197,11 +242,10 @@ async function getNextPage(page) {
|
|
|
197
242
|
<!-- Force swipe mode on all devices -->
|
|
198
243
|
<Masonry
|
|
199
244
|
v-model:items="items"
|
|
200
|
-
:get-
|
|
245
|
+
:get-page="getPage"
|
|
201
246
|
layout-mode="swipe"
|
|
202
247
|
/>
|
|
203
|
-
</template>'
|
|
204
|
-
/>
|
|
248
|
+
</template>' />
|
|
205
249
|
</div>
|
|
206
250
|
</div>
|
|
207
251
|
</section>
|
|
@@ -217,12 +261,14 @@ async function getNextPage(page) {
|
|
|
217
261
|
import { ref, onMounted, onUnmounted } from 'vue'
|
|
218
262
|
import CodeTabs from '../components/CodeTabs.vue'
|
|
219
263
|
import BasicExample from '../components/examples/BasicExample.vue'
|
|
264
|
+
import ManualInitExample from '../components/examples/ManualInitExample.vue'
|
|
220
265
|
import CustomItemExample from '../components/examples/CustomItemExample.vue'
|
|
221
266
|
import SwipeModeExample from '../components/examples/SwipeModeExample.vue'
|
|
222
267
|
import HeaderFooterExample from '../components/examples/HeaderFooterExample.vue'
|
|
223
268
|
|
|
224
269
|
const examples = [
|
|
225
270
|
{ id: 'basic', title: 'Basic Usage' },
|
|
271
|
+
{ id: 'manual-init', title: 'Manual Init CTA' },
|
|
226
272
|
{ id: 'custom-item', title: 'Custom Masonry Item' },
|
|
227
273
|
{ id: 'header-footer', title: 'Header & Footer' },
|
|
228
274
|
{ id: 'swipe-mode', title: 'Swipe Mode' }
|
|
@@ -230,6 +276,7 @@ const examples = [
|
|
|
230
276
|
|
|
231
277
|
const activeSection = ref('basic')
|
|
232
278
|
const basicRef = ref<HTMLElement | null>(null)
|
|
279
|
+
const manualInitRef = ref<HTMLElement | null>(null)
|
|
233
280
|
const customItemRef = ref<HTMLElement | null>(null)
|
|
234
281
|
const headerFooterRef = ref<HTMLElement | null>(null)
|
|
235
282
|
const swipeModeRef = ref<HTMLElement | null>(null)
|
|
@@ -245,6 +292,7 @@ function scrollTo(id: string) {
|
|
|
245
292
|
function updateActiveSection() {
|
|
246
293
|
const sections = [
|
|
247
294
|
{ id: 'basic', ref: basicRef },
|
|
295
|
+
{ id: 'manual-init', ref: manualInitRef },
|
|
248
296
|
{ id: 'custom-item', ref: customItemRef },
|
|
249
297
|
{ id: 'header-footer', ref: headerFooterRef },
|
|
250
298
|
{ id: 'swipe-mode', ref: swipeModeRef }
|