@wyxos/vibe 5.10.1 → 5.12.0
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 +22 -4
- package/lib/components/MasonryFeed.vue.d.ts +2 -0
- package/lib/components/VibeSurface.vue.d.ts +3 -0
- package/lib/components/useMasonryMediaVisibility.d.ts +13 -0
- package/lib/components/useMediaLifecycle.d.ts +3 -0
- package/lib/components/useReelVideoActivity.d.ts +1 -0
- package/lib/components/useTimedMediaCard.d.ts +1 -0
- package/lib/core/feed.d.ts +1 -0
- package/lib/core/masonry.d.ts +5 -0
- package/lib/index.cjs +2 -2
- package/lib/index.js +741 -703
- package/lib/types.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -170,8 +170,12 @@ need to select exact grouped media independently of its array position.
|
|
|
170
170
|
## Media lifecycle hooks
|
|
171
171
|
|
|
172
172
|
Use `onMediaReady` when an image has loaded or a video has enough metadata for
|
|
173
|
-
Vibe to render it
|
|
174
|
-
|
|
173
|
+
Vibe to render it. `onMediaVisible` reports each ready masonry media item once
|
|
174
|
+
per feed visit when it first intersects the viewport. `onMediaFullyVisible`
|
|
175
|
+
reports each ready media item once per layout and feed visit: after the masonry
|
|
176
|
+
card reaches its full visibility threshold, or after the media is active and
|
|
177
|
+
ready in a reel.
|
|
178
|
+
`onReelMediaChange` reports reel selection changes:
|
|
175
179
|
|
|
176
180
|
```ts
|
|
177
181
|
const vibe = createVibe({
|
|
@@ -180,19 +184,32 @@ const vibe = createVibe({
|
|
|
180
184
|
onMediaReady: ({ postId, mediaId, layout, origin }) => {
|
|
181
185
|
recordMediaReady({ postId, mediaId, layout, origin })
|
|
182
186
|
},
|
|
187
|
+
onMediaVisible: ({ postId, mediaIndex }) => {
|
|
188
|
+
recordMediaPreviewed({ postId, mediaIndex })
|
|
189
|
+
},
|
|
190
|
+
onMediaFullyVisible: ({ postId, mediaIndex, layout }) => {
|
|
191
|
+
recordMediaViewed({ postId, mediaIndex, layout })
|
|
192
|
+
},
|
|
183
193
|
onReelMediaChange: ({ postId, mediaId, postIndex, mediaIndex }) => {
|
|
184
194
|
updateActiveMedia({ postId, mediaId, postIndex, mediaIndex })
|
|
185
195
|
},
|
|
186
196
|
})
|
|
187
197
|
```
|
|
188
198
|
|
|
189
|
-
|
|
199
|
+
All lifecycle callbacks receive `VibeMediaLifecycleContext`: stable `postId`
|
|
190
200
|
and `mediaId` identity, zero-based `postIndex` and `mediaIndex`, the complete
|
|
191
201
|
`item` and selected `media`, the rendered `layout`, and `origin`. `mediaId` is
|
|
192
202
|
`null` when the source asset does not define one. `origin` is `null` for the
|
|
193
203
|
masonry grid, `reel` for the base reel, and `masonry` for a reel opened from a
|
|
194
204
|
masonry card. The readiness hook may run again if media remounts and becomes
|
|
195
|
-
ready again
|
|
205
|
+
ready again. A feed visit begins when Vibe mounts and restarts whenever
|
|
206
|
+
`refresh()` or `reload()` replaces the feed. Visibility callbacks stay
|
|
207
|
+
deduplicated while scrolling, loading more, or retrying pagination within that
|
|
208
|
+
visit.
|
|
209
|
+
Normal masonry cards require their complete height; cards taller than the
|
|
210
|
+
viewport require 80% of their maximum attainable visible height. Reel fully
|
|
211
|
+
visible events depend on active-and-ready state rather than intersection.
|
|
212
|
+
Reel-change events describe selection changes, not load state.
|
|
196
213
|
|
|
197
214
|
## Reel URLs with Vue Router
|
|
198
215
|
|
|
@@ -790,6 +807,7 @@ vibe.destroy()
|
|
|
790
807
|
`refresh()` replaces the visible feed from its current continuation cursor. At
|
|
791
808
|
the end of the feed, it requests the cursor that produced the last loaded page
|
|
792
809
|
again. Use `reload()` to replace the feed from its initial `null` cursor instead.
|
|
810
|
+
Both operations begin a new feed visit for media visibility callbacks.
|
|
793
811
|
|
|
794
812
|
Destroying an instance unmounts its Vue tree and aborts its active page request.
|
|
795
813
|
|
|
@@ -12,6 +12,7 @@ declare const __VLS_export: import("vue").DefineComponent<MasonryFeedProps, {
|
|
|
12
12
|
retryEnd: () => any;
|
|
13
13
|
activate: (postId: VibeItemId, input: "keyboard" | "pointer") => any;
|
|
14
14
|
mediaChange: (postId: VibeItemId, mediaIndex: number) => any;
|
|
15
|
+
fullyVisible: (postId: VibeItemId, mediaIndex: number) => any;
|
|
15
16
|
visible: (postId: VibeItemId, mediaIndex: number) => any;
|
|
16
17
|
}, string, import("vue").PublicProps, Readonly<MasonryFeedProps> & Readonly<{
|
|
17
18
|
onReady?: ((postId: VibeItemId, mediaIndex: number) => any) | undefined;
|
|
@@ -20,6 +21,7 @@ declare const __VLS_export: import("vue").DefineComponent<MasonryFeedProps, {
|
|
|
20
21
|
onRetryEnd?: (() => any) | undefined;
|
|
21
22
|
onActivate?: ((postId: VibeItemId, input: "keyboard" | "pointer") => any) | undefined;
|
|
22
23
|
onMediaChange?: ((postId: VibeItemId, mediaIndex: number) => any) | undefined;
|
|
24
|
+
onFullyVisible?: ((postId: VibeItemId, mediaIndex: number) => any) | undefined;
|
|
23
25
|
onVisible?: ((postId: VibeItemId, mediaIndex: number) => any) | undefined;
|
|
24
26
|
}>, {
|
|
25
27
|
leavingPostIds: ReadonlySet<VibeItemId>;
|
|
@@ -26,6 +26,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
|
26
26
|
loadIfNearBottom: typeof loadIfNearBottom;
|
|
27
27
|
moveActiveReelPost: typeof moveActiveReelPost;
|
|
28
28
|
navigateToReelItem: typeof navigateToReelItem;
|
|
29
|
+
resetMediaLifecycle: () => void;
|
|
29
30
|
startItemRemoval: typeof startItemRemoval;
|
|
30
31
|
transitionActiveReelMedia: (direction: -1 | 1) => Promise<boolean>;
|
|
31
32
|
transitionActiveReelPost: (postId: VibeItemId) => Promise<boolean>;
|
|
@@ -36,6 +37,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
|
36
37
|
retryForward: () => any;
|
|
37
38
|
activeReelChange: (postId: VibeItemId) => any;
|
|
38
39
|
closeReel: () => any;
|
|
40
|
+
mediaFullyVisible: (context: VibeMediaLifecycleContext) => any;
|
|
39
41
|
mediaReady: (context: VibeMediaLifecycleContext) => any;
|
|
40
42
|
mediaVisible: (context: VibeMediaLifecycleContext) => any;
|
|
41
43
|
openReel: (postId: VibeItemId) => any;
|
|
@@ -48,6 +50,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
|
48
50
|
onRetryForward?: (() => any) | undefined;
|
|
49
51
|
onActiveReelChange?: ((postId: VibeItemId) => any) | undefined;
|
|
50
52
|
onCloseReel?: (() => any) | undefined;
|
|
53
|
+
onMediaFullyVisible?: ((context: VibeMediaLifecycleContext) => any) | undefined;
|
|
51
54
|
onMediaReady?: ((context: VibeMediaLifecycleContext) => any) | undefined;
|
|
52
55
|
onMediaVisible?: ((context: VibeMediaLifecycleContext) => any) | undefined;
|
|
53
56
|
onOpenReel?: ((postId: VibeItemId) => any) | undefined;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MediaPreviewState } from '../core/mediaPreview';
|
|
2
|
+
import type { VibeItem, VibeItemId } from '../types';
|
|
3
|
+
interface MasonryMediaVisibilityOptions {
|
|
4
|
+
fullyVisibleIndices: () => readonly number[];
|
|
5
|
+
items: () => readonly VibeItem[];
|
|
6
|
+
mediaIndices: () => ReadonlyMap<VibeItemId, number>;
|
|
7
|
+
onFullyVisible: (postId: VibeItemId, mediaIndex: number) => void;
|
|
8
|
+
onVisible: (postId: VibeItemId, mediaIndex: number) => void;
|
|
9
|
+
previewStates: () => ReadonlyMap<string, MediaPreviewState>;
|
|
10
|
+
visibleIndices: () => readonly number[];
|
|
11
|
+
}
|
|
12
|
+
export declare function useMasonryMediaVisibility(options: MasonryMediaVisibilityOptions): void;
|
|
13
|
+
export {};
|
|
@@ -2,11 +2,13 @@ import type { MediaPreviewState } from '../core/mediaPreview';
|
|
|
2
2
|
import type { VibeRuntimeState } from '../core/runtime';
|
|
3
3
|
import type { VibeItemId, VibeMediaLifecycleContext } from '../types';
|
|
4
4
|
interface MediaLifecycleEvents {
|
|
5
|
+
fullyVisible: (context: VibeMediaLifecycleContext) => void;
|
|
5
6
|
ready: (context: VibeMediaLifecycleContext) => void;
|
|
6
7
|
reelChange: (context: VibeMediaLifecycleContext) => void;
|
|
7
8
|
visible: (context: VibeMediaLifecycleContext) => void;
|
|
8
9
|
}
|
|
9
10
|
export declare function useMediaLifecycle(state: VibeRuntimeState, events: MediaLifecycleEvents): {
|
|
11
|
+
markMasonryFullyVisible: (postId: VibeItemId, mediaIndex: number) => void;
|
|
10
12
|
markMasonryVisible: (postId: VibeItemId, mediaIndex: number) => void;
|
|
11
13
|
markPreviewError: (postId: VibeItemId, mediaIndex: number) => void;
|
|
12
14
|
markPreviewReady: (postId: VibeItemId, mediaIndex: number) => void;
|
|
@@ -15,5 +17,6 @@ export declare function useMediaLifecycle(state: VibeRuntimeState, events: Media
|
|
|
15
17
|
originalStates: import("vue").ShallowRef<ReadonlyMap<string, MediaPreviewState>, ReadonlyMap<string, MediaPreviewState>>;
|
|
16
18
|
previewStates: import("vue").ShallowRef<ReadonlyMap<string, MediaPreviewState>, ReadonlyMap<string, MediaPreviewState>>;
|
|
17
19
|
reelStates: import("vue").ComputedRef<ReadonlyMap<string, MediaPreviewState>>;
|
|
20
|
+
resetMediaLifecycle: () => void;
|
|
18
21
|
};
|
|
19
22
|
export {};
|
|
@@ -2,6 +2,7 @@ import { type Ref } from 'vue';
|
|
|
2
2
|
import type { VibeLayout } from '../types';
|
|
3
3
|
interface ReelTimedMediaActivityOptions {
|
|
4
4
|
active: () => boolean | undefined;
|
|
5
|
+
inViewport: () => boolean;
|
|
5
6
|
layout: () => VibeLayout;
|
|
6
7
|
mediaElement: Ref<HTMLMediaElement | null>;
|
|
7
8
|
mediaIsMuted: Ref<boolean>;
|
|
@@ -2,6 +2,7 @@ import { type Ref } from 'vue';
|
|
|
2
2
|
import type { VibeLayout, VibeMediaCardOptions, VibeReelAudioState } from '../types';
|
|
3
3
|
interface TimedMediaCardOptions {
|
|
4
4
|
active: () => boolean | undefined;
|
|
5
|
+
inViewport: () => boolean;
|
|
5
6
|
layout: () => VibeLayout;
|
|
6
7
|
mediaCard: () => VibeMediaCardOptions | undefined;
|
|
7
8
|
mediaElement: Ref<HTMLMediaElement | null>;
|
package/lib/core/feed.d.ts
CHANGED
|
@@ -58,6 +58,7 @@ export interface VibeSurfaceExpose {
|
|
|
58
58
|
loadIfNearBottom: () => Promise<void>;
|
|
59
59
|
moveActiveReelPost: (direction: -1 | 1) => boolean;
|
|
60
60
|
navigateToReelItem: (target: VibeReelItemTarget) => VibeReelNavigationResult;
|
|
61
|
+
resetMediaLifecycle: () => void;
|
|
61
62
|
startItemRemoval: (postIds: readonly VibeItemId[], options?: VibeItemRemovalOptions) => number;
|
|
62
63
|
transitionActiveReelMedia: (direction: -1 | 1) => Promise<boolean>;
|
|
63
64
|
transitionActiveReelPost: (postId: VibeItemId) => Promise<boolean>;
|
package/lib/core/masonry.d.ts
CHANGED
|
@@ -26,6 +26,10 @@ export interface MasonryViewportOptions {
|
|
|
26
26
|
viewportHeight: number;
|
|
27
27
|
overscan: number;
|
|
28
28
|
}
|
|
29
|
+
export interface MasonryVisibilityOptions {
|
|
30
|
+
scrollTop: number;
|
|
31
|
+
viewportHeight: number;
|
|
32
|
+
}
|
|
29
33
|
interface MasonryOptions {
|
|
30
34
|
additionalHeight?: number;
|
|
31
35
|
gap: number;
|
|
@@ -33,5 +37,6 @@ interface MasonryOptions {
|
|
|
33
37
|
}
|
|
34
38
|
export declare function calculateMasonryEntryOffset(options: MasonryEntryOptions): number;
|
|
35
39
|
export declare function calculateVisibleMasonryIndices(items: MasonryPosition[], options: MasonryViewportOptions): number[];
|
|
40
|
+
export declare function calculateFullyVisibleMasonryIndices(items: readonly MasonryPosition[], candidates: readonly number[], options: MasonryVisibilityOptions): number[];
|
|
36
41
|
export declare function calculateMasonryLayout(media: readonly MasonryMediaDimensions[], containerWidth: number, options: MasonryOptions): MasonryLayout;
|
|
37
42
|
export {};
|