@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.
@@ -1,9 +1,10 @@
1
1
  <template>
2
2
  <Masonry
3
3
  v-model:items="items"
4
- :get-next-page="getPage"
4
+ :get-page="getPage"
5
5
  :load-at-page="1"
6
6
  :layout="layout"
7
+ init="auto"
7
8
  />
8
9
  </template>
9
10
 
@@ -1,9 +1,10 @@
1
1
  <template>
2
2
  <Masonry
3
3
  v-model:items="items"
4
- :get-next-page="getPage"
4
+ :get-page="getPage"
5
5
  :load-at-page="1"
6
6
  :layout="layout"
7
+ init="auto"
7
8
  >
8
9
  <template #item="{ item, remove }">
9
10
  <div class="custom-card">
@@ -1,78 +1,79 @@
1
- <template>
2
- <Masonry
3
- v-model:items="items"
4
- :get-next-page="getPage"
5
- :load-at-page="1"
6
- :layout="layout"
7
- >
8
- <template #item-header="{ item }">
9
- <div class="h-full flex items-center justify-between px-3">
10
- <div class="flex items-center gap-2">
11
- <div class="w-6 h-6 rounded-full bg-white/80 backdrop-blur-sm flex items-center justify-center shadow-sm">
12
- <i :class="item.type === 'video' ? 'fas fa-video text-[10px] text-slate-500' : 'fas fa-image text-[10px] text-slate-500'"></i>
13
- </div>
14
- <span class="text-xs font-medium text-slate-700">#{{ String(item.id).split('-')[0] }}</span>
15
- </div>
16
- <span v-if="item.title" class="text-[11px] text-slate-600 truncate max-w-[160px]">{{ item.title }}</span>
17
- </div>
18
- </template>
19
-
20
- <template #item-footer="{ item, remove }">
21
- <div class="h-full flex items-center justify-between px-3">
22
- <div class="flex items-center gap-2">
23
- <button
24
- v-if="remove"
25
- class="px-2.5 py-1 rounded-full bg-white/90 text-slate-700 text-[11px] shadow-sm hover:bg-red-500 hover:text-white transition-colors"
26
- @click.stop="remove(item)"
27
- >
28
- Remove
29
- </button>
30
- </div>
31
- <div class="text-[11px] text-slate-600">
32
- {{ item.width }}×{{ item.height }}
33
- </div>
34
- </div>
35
- </template>
36
- </Masonry>
37
- </template>
38
-
39
- <script setup lang="ts">
40
- import { ref } from 'vue'
41
- import Masonry from '../../Masonry.vue'
42
- import fixture from '../../pages.json'
43
- import type { MasonryItem, GetPageResult } from '../../types'
44
-
45
- const items = ref<MasonryItem[]>([])
46
-
47
- const layout = {
48
- sizes: { base: 1, sm: 2, md: 3, lg: 4 },
49
- gutterX: 10,
50
- gutterY: 10,
51
- header: 36,
52
- footer: 40
53
- }
54
-
55
- const getPage = async (page: number): Promise<GetPageResult> => {
56
- return new Promise((resolve) => {
57
- setTimeout(() => {
58
- const pageData = (fixture as any[])[page - 1] as { items: MasonryItem[] } | undefined
59
-
60
- if (!pageData) {
61
- resolve({
62
- items: [],
63
- nextPage: null
64
- })
65
- return
66
- }
67
-
68
- resolve({
69
- items: pageData.items,
70
- nextPage: page < (fixture as any[]).length ? page + 1 : null
71
- })
72
- }, 300)
73
- })
74
- }
75
- </script>
76
-
77
-
78
-
1
+ <template>
2
+ <Masonry
3
+ v-model:items="items"
4
+ :get-page="getPage"
5
+ :load-at-page="1"
6
+ :layout="layout"
7
+ init="auto"
8
+ >
9
+ <template #item-header="{ item }">
10
+ <div class="h-full flex items-center justify-between px-3">
11
+ <div class="flex items-center gap-2">
12
+ <div class="w-6 h-6 rounded-full bg-white/80 backdrop-blur-sm flex items-center justify-center shadow-sm">
13
+ <i :class="item.type === 'video' ? 'fas fa-video text-[10px] text-slate-500' : 'fas fa-image text-[10px] text-slate-500'"></i>
14
+ </div>
15
+ <span class="text-xs font-medium text-slate-700">#{{ String(item.id).split('-')[0] }}</span>
16
+ </div>
17
+ <span v-if="item.title" class="text-[11px] text-slate-600 truncate max-w-[160px]">{{ item.title }}</span>
18
+ </div>
19
+ </template>
20
+
21
+ <template #item-footer="{ item, remove }">
22
+ <div class="h-full flex items-center justify-between px-3">
23
+ <div class="flex items-center gap-2">
24
+ <button
25
+ v-if="remove"
26
+ class="px-2.5 py-1 rounded-full bg-white/90 text-slate-700 text-[11px] shadow-sm hover:bg-red-500 hover:text-white transition-colors"
27
+ @click.stop="remove(item)"
28
+ >
29
+ Remove
30
+ </button>
31
+ </div>
32
+ <div class="text-[11px] text-slate-600">
33
+ {{ item.width }}×{{ item.height }}
34
+ </div>
35
+ </div>
36
+ </template>
37
+ </Masonry>
38
+ </template>
39
+
40
+ <script setup lang="ts">
41
+ import { ref } from 'vue'
42
+ import Masonry from '../../Masonry.vue'
43
+ import fixture from '../../pages.json'
44
+ import type { MasonryItem, GetPageResult } from '../../types'
45
+
46
+ const items = ref<MasonryItem[]>([])
47
+
48
+ const layout = {
49
+ sizes: { base: 1, sm: 2, md: 3, lg: 4 },
50
+ gutterX: 10,
51
+ gutterY: 10,
52
+ header: 36,
53
+ footer: 40
54
+ }
55
+
56
+ const getPage = async (page: number): Promise<GetPageResult> => {
57
+ return new Promise((resolve) => {
58
+ setTimeout(() => {
59
+ const pageData = (fixture as any[])[page - 1] as { items: MasonryItem[] } | undefined
60
+
61
+ if (!pageData) {
62
+ resolve({
63
+ items: [],
64
+ nextPage: null
65
+ })
66
+ return
67
+ }
68
+
69
+ resolve({
70
+ items: pageData.items,
71
+ nextPage: page < (fixture as any[]).length ? page + 1 : null
72
+ })
73
+ }, 300)
74
+ })
75
+ }
76
+ </script>
77
+
78
+
79
+
@@ -0,0 +1,78 @@
1
+ <template>
2
+ <div class="relative h-full">
3
+ <div
4
+ v-if="!isInitialized"
5
+ class="absolute inset-0 z-10 flex items-center justify-center bg-slate-900/40 backdrop-blur-sm"
6
+ >
7
+ <button
8
+ type="button"
9
+ class="inline-flex items-center gap-2 rounded-full bg-white px-5 py-2 text-sm font-semibold text-slate-900 shadow-sm ring-1 ring-slate-200 transition hover:-translate-y-0.5 hover:shadow-md"
10
+ @click="handleInit"
11
+ >
12
+ Load gallery
13
+ <span class="text-slate-400">-></span>
14
+ </button>
15
+ </div>
16
+
17
+ <Masonry
18
+ ref="masonryRef"
19
+ v-model:items="items"
20
+ :get-page="getPage"
21
+ :load-at-page="1"
22
+ :layout="layout"
23
+ init="manual"
24
+ />
25
+ </div>
26
+ </template>
27
+
28
+ <script setup lang="ts">
29
+ import { ref } from 'vue'
30
+ import Masonry from '../../Masonry.vue'
31
+ import fixture from '../../pages.json'
32
+ import type { MasonryItem, GetPageResult } from '../../types'
33
+
34
+ const items = ref<MasonryItem[]>([])
35
+ const isInitialized = ref(false)
36
+ const masonryRef = ref<InstanceType<typeof Masonry> | null>(null)
37
+
38
+ const layout = {
39
+ sizes: { base: 1, sm: 2, md: 3, lg: 4 },
40
+ gutterX: 10,
41
+ gutterY: 10
42
+ }
43
+
44
+ const getPage = async (page: number): Promise<GetPageResult> => {
45
+ return new Promise((resolve) => {
46
+ setTimeout(() => {
47
+ const pageData = (fixture as any[])[page - 1] as { items: MasonryItem[] } | undefined
48
+
49
+ if (!pageData) {
50
+ resolve({
51
+ items: [],
52
+ nextPage: null
53
+ })
54
+ return
55
+ }
56
+
57
+ resolve({
58
+ items: pageData.items,
59
+ nextPage: page < (fixture as any[]).length ? page + 1 : null
60
+ })
61
+ }, 300)
62
+ })
63
+ }
64
+
65
+ function handleInit() {
66
+ if (isInitialized.value) {
67
+ return
68
+ }
69
+
70
+ isInitialized.value = true
71
+ masonryRef.value?.loadPage(1)
72
+ }
73
+ </script>
74
+
75
+
76
+
77
+
78
+
@@ -1,9 +1,10 @@
1
1
  <template>
2
2
  <Masonry
3
3
  v-model:items="items"
4
- :get-next-page="getPage"
4
+ :get-page="getPage"
5
5
  :load-at-page="1"
6
6
  layout-mode="swipe"
7
+ init="auto"
7
8
  />
8
9
  </template>
9
10
 
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Composable for handling masonry item transitions (typed)
2
+ * Factory for masonry item transitions (typed)
3
3
  * Optimized for large item arrays by skipping DOM operations for items outside viewport
4
4
  */
5
- export function useMasonryTransitions(
5
+ export function createMasonryTransitions(
6
6
  refs: { container?: any; masonry?: any },
7
7
  opts?: { leaveDurationMs?: number; virtualizing?: { value: boolean } }
8
8
  ) {
@@ -80,7 +80,7 @@ export function useMasonryTransitions(
80
80
  function onBeforeEnter(el: HTMLElement) {
81
81
  const left = parseInt(el.dataset.left || '0', 10)
82
82
  const top = parseInt(el.dataset.top || '0', 10)
83
-
83
+
84
84
  // Skip animation during virtualization
85
85
  if (opts?.virtualizing?.value) {
86
86
  el.style.transition = 'none'
@@ -89,7 +89,7 @@ export function useMasonryTransitions(
89
89
  el.style.removeProperty('--masonry-opacity-delay')
90
90
  return
91
91
  }
92
-
92
+
93
93
  el.style.opacity = '0'
94
94
  el.style.transform = `translate3d(${left}px, ${top + 10}px, 0) scale(0.985)`
95
95
  }
@@ -141,8 +141,8 @@ export function useMasonryTransitions(
141
141
  }
142
142
 
143
143
  // Prefer explicit option, fallback to CSS variable for safety
144
- const fromOpts = typeof opts?.leaveDurationMs === 'number' ? opts!.leaveDurationMs : NaN
145
- let leaveMs = Number.isFinite(fromOpts) && fromOpts > 0 ? fromOpts : NaN
144
+ const fromOpts = typeof opts?.leaveDurationMs === 'number' ? opts!.leaveDurationMs : Number.NaN
145
+ let leaveMs = Number.isFinite(fromOpts) && fromOpts > 0 ? fromOpts : Number.NaN
146
146
  if (!Number.isFinite(leaveMs)) {
147
147
  const cs = getComputedStyle(el)
148
148
  const varVal = cs.getPropertyValue('--masonry-leave-duration') || ''