@wyxos/vibe 4.5.0 → 4.5.1

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/lib/index.js CHANGED
@@ -34,6 +34,7 @@ function F(e) {
34
34
  next: e.next,
35
35
  nextPageError: e.nextPageError,
36
36
  reelAutoAdvance: { ...e.reelAutoAdvance },
37
+ reelForward: { ...e.reelForward },
37
38
  reelInfoSheet: { ...e.reelInfoSheet },
38
39
  reelOrigin: e.reelOrigin,
39
40
  total: e.total
@@ -84,7 +85,7 @@ var I = {
84
85
  onClick: n[0] ||= (e) => t.$emit("retryEnd")
85
86
  }, " Check for more ", 8, B)]))])) : a("", !0);
86
87
  }
87
- }), H = /* @__PURE__ */ u({
88
+ }), ee = /* @__PURE__ */ u({
88
89
  __name: "FeedFooter",
89
90
  props: {
90
91
  actions: {},
@@ -135,7 +136,7 @@ var I = {
135
136
  "load-more-locked"
136
137
  ]));
137
138
  }
138
- }), U = ["role"], W = { class: "gallery-status" }, ee = /* @__PURE__ */ u({
139
+ }), H = ["role"], U = { class: "gallery-status" }, te = /* @__PURE__ */ u({
139
140
  __name: "FeedStatus",
140
141
  props: {
141
142
  actions: {},
@@ -149,7 +150,7 @@ var I = {
149
150
  return (n, u) => (y(), o("main", {
150
151
  class: "gallery-shell",
151
152
  role: r.state.error ? "alert" : r.state.isLoading ? "status" : void 0
152
- }, [s("p", W, [r.state.error ? (y(), o(e, { key: 0 }, [c(" Unable to load media. ")], 64)) : r.state.isLoading ? (y(), o(e, { key: 1 }, [c(" Loading media… ")], 64)) : (y(), o(e, { key: 2 }, [c(" No media found. ")], 64))]), t.feedFooter ? (y(), i(H, {
153
+ }, [s("p", U, [r.state.error ? (y(), o(e, { key: 0 }, [c(" Unable to load media. ")], 64)) : r.state.isLoading ? (y(), o(e, { key: 1 }, [c(" Loading media… ")], 64)) : (y(), o(e, { key: 2 }, [c(" No media found. ")], 64))]), t.feedFooter ? (y(), i(ee, {
153
154
  key: 0,
154
155
  actions: t.actions,
155
156
  "can-retry-end": t.canRetryEnd,
@@ -170,36 +171,36 @@ var I = {
170
171
  "is-loading",
171
172
  "load-more-locked",
172
173
  "state"
173
- ])) : a("", !0)], 8, U));
174
+ ])) : a("", !0)], 8, H));
174
175
  }
175
176
  });
176
- function G(e) {
177
+ function W(e) {
177
178
  return e.scrollHeight - e.scrollTop - e.clientHeight <= 240;
178
179
  }
179
180
  //#endregion
180
181
  //#region src/core/masonry.ts
181
- function te(e) {
182
+ function ne(e) {
182
183
  let t = e.preview.width ?? e.width, n = e.preview.height ?? e.height;
183
184
  return !t || !n || t <= 0 || n <= 0 ? 1 : n / t;
184
185
  }
185
- function ne(e) {
186
+ function re(e) {
186
187
  return e.reduce((t, n, r) => n < e[t] ? r : t, 0);
187
188
  }
188
- function K(e) {
189
+ function ie(e) {
189
190
  return Math.max(0, e.containerHeight) + Math.max(0, e.gap);
190
191
  }
191
- function q(e, t) {
192
+ function G(e, t) {
192
193
  let n = Math.max(0, t.overscan), r = t.scrollTop - n, i = t.scrollTop + Math.max(0, t.viewportHeight) + n;
193
194
  return e.reduce((e, t, n) => (t.y + t.height >= r && t.y <= i && e.push(n), e), []);
194
195
  }
195
- function J(e, t, n) {
196
+ function K(e, t, n) {
196
197
  if (t <= 0 || e.length === 0) return {
197
198
  columns: 0,
198
199
  height: 0,
199
200
  items: []
200
201
  };
201
202
  let r = Math.max(0, n.gap), i = Number.isFinite(n.additionalHeight) ? Math.max(0, n.additionalHeight ?? 0) : 0, a = Math.max(1, n.minColumnWidth), o = Math.max(1, Math.floor((t + r) / (a + r))), s = (t - r * (o - 1)) / o, c = Array.from({ length: o }, () => 0), l = e.map((e) => {
202
- let t = ne(c), n = s * te(e) + i, a = {
203
+ let t = re(c), n = s * ne(e) + i, a = {
203
204
  x: t * (s + r),
204
205
  y: c[t],
205
206
  width: s,
@@ -215,10 +216,10 @@ function J(e, t, n) {
215
216
  }
216
217
  //#endregion
217
218
  //#region src/core/scrollbar.ts
218
- function Y(e, t, n) {
219
+ function q(e, t, n) {
219
220
  return Math.min(n, Math.max(t, e));
220
221
  }
221
- function X({ contentSize: e, minimumThumbSize: t, scrollPosition: n, trackSize: r, viewportSize: i }) {
222
+ function J({ contentSize: e, minimumThumbSize: t, scrollPosition: n, trackSize: r, viewportSize: i }) {
222
223
  let a = Math.max(0, e), o = Math.max(0, r), s = Math.max(0, i), c = Math.max(0, a - s);
223
224
  if (!(c > 0 && o > 0)) return {
224
225
  maximumScrollPosition: c,
@@ -227,23 +228,23 @@ function X({ contentSize: e, minimumThumbSize: t, scrollPosition: n, trackSize:
227
228
  thumbSize: o,
228
229
  thumbTravel: 0
229
230
  };
230
- let l = Y(s / a * o, Math.min(Math.max(0, t), o), o), u = Math.max(0, o - l);
231
+ let l = q(s / a * o, Math.min(Math.max(0, t), o), o), u = Math.max(0, o - l);
231
232
  return {
232
233
  maximumScrollPosition: c,
233
234
  scrollable: !0,
234
- thumbOffset: u * (Y(n, 0, c) / c),
235
+ thumbOffset: u * (q(n, 0, c) / c),
235
236
  thumbSize: l,
236
237
  thumbTravel: u
237
238
  };
238
239
  }
239
240
  //#endregion
240
241
  //#region src/components/GalleryScrollbar.vue?vue&type=script&setup=true&lang.ts
241
- var re = ["aria-hidden"], ie = [
242
+ var ae = ["aria-hidden"], oe = [
242
243
  "aria-controls",
243
244
  "aria-valuemax",
244
245
  "aria-valuenow",
245
246
  "tabindex"
246
- ], ae = 32, Z = 40, oe = 120, se = /* @__PURE__ */ u({
247
+ ], Y = 32, X = 40, Z = 120, se = /* @__PURE__ */ u({
247
248
  __name: "GalleryScrollbar",
248
249
  props: {
249
250
  contentSize: {},
@@ -265,16 +266,16 @@ var re = ["aria-hidden"], ie = [
265
266
  function k() {
266
267
  v !== null && clearTimeout(v), v = setTimeout(() => {
267
268
  v = null, c.value || (l.value = !1);
268
- }, oe);
269
+ }, Z);
269
270
  }
270
271
  function A() {
271
272
  l.value = !0, k();
272
273
  }
273
274
  function j() {
274
275
  let e = t.scrollElement, n = i.value;
275
- return !e || !n ? r : X({
276
+ return !e || !n ? r : J({
276
277
  contentSize: e.scrollHeight,
277
- minimumThumbSize: ae,
278
+ minimumThumbSize: Y,
278
279
  scrollPosition: e.scrollTop,
279
280
  trackSize: n.clientHeight,
280
281
  viewportSize: e.clientHeight
@@ -327,7 +328,7 @@ var re = ["aria-hidden"], ie = [
327
328
  }
328
329
  function z(e) {
329
330
  if (!E.value) return;
330
- let n = t.scrollElement?.clientHeight ?? 0, r = t.scrollElement?.scrollTop ?? 0, i = e.key === "ArrowUp" ? r - Z : e.key === "ArrowDown" ? r + Z : e.key === "PageUp" ? r - n : e.key === "PageDown" ? r + n : e.key === "Home" ? 0 : e.key === "End" ? a.value.maximumScrollPosition : null;
331
+ let n = t.scrollElement?.clientHeight ?? 0, r = t.scrollElement?.scrollTop ?? 0, i = e.key === "ArrowUp" ? r - X : e.key === "ArrowDown" ? r + X : e.key === "PageUp" ? r - n : e.key === "PageDown" ? r + n : e.key === "Home" ? 0 : e.key === "End" ? a.value.maximumScrollPosition : null;
331
332
  i !== null && (e.preventDefault(), A(), P(i));
332
333
  }
333
334
  function B(e) {
@@ -373,7 +374,7 @@ var re = ["aria-hidden"], ie = [
373
374
  onPointerdown: I,
374
375
  onPointermove: L,
375
376
  onPointerup: R
376
- }, null, 44, ie)], 42, re));
377
+ }, null, 44, oe)], 42, ae));
377
378
  }
378
379
  }), ce = (e) => {
379
380
  for (let t in e) if (t.startsWith("aria-") || t === "role" || t === "title") return !0;
@@ -692,45 +693,45 @@ var Oe = /* @__PURE__ */ u({
692
693
  function x(e = !1, t = "pointer") {
693
694
  e && b("activate", t);
694
695
  }
695
- let S = n(() => j(c.item)), E = n(() => M(c.item, c.mediaIndex)), D = n(() => N(c.item, E.value)), P = n(() => c.mediaSource === "original" ? D.value.src : D.value.preview.src), F = n(() => c.mediaSource === "original" ? D.value.width : D.value.preview.width), I = n(() => c.mediaSource === "original" ? D.value.height : D.value.preview.height), L = C(null), R = C(0), z = C(0), B = C(!0), V = C(!1), H = C(1), U = 1, W = n(() => c.interactive && !!(c.cardHeader || c.cardFooter));
696
- function ee(e) {
696
+ let S = n(() => j(c.item)), E = n(() => M(c.item, c.mediaIndex)), D = n(() => N(c.item, E.value)), P = n(() => c.mediaSource === "original" ? D.value.src : D.value.preview.src), F = n(() => c.mediaSource === "original" ? D.value.width : D.value.preview.width), I = n(() => c.mediaSource === "original" ? D.value.height : D.value.preview.height), L = C(null), R = C(0), z = C(0), B = C(!0), V = C(!1), ee = C(1), H = 1, U = n(() => c.interactive && !!(c.cardHeader || c.cardFooter));
697
+ function te(e) {
697
698
  return e.detail === 0 ? "keyboard" : "pointer";
698
699
  }
699
- function G(e, t) {
700
+ function W(e, t) {
700
701
  let n = S.value.length, r = (e + n) % n;
701
702
  r !== E.value && (v.value = e < E.value ? "previous" : "next", b("mediaChange", r), t && t.detail > 0 && t.currentTarget?.blur());
702
703
  }
703
- function te(e, t, n) {
704
+ function ne(e, t, n) {
704
705
  return t === 1 ? e * 16 : t === 2 ? e * n : e;
705
706
  }
706
- function ne() {
707
+ function re() {
707
708
  d = 0, f = !1, u !== null && clearTimeout(u), u = null;
708
709
  }
709
- function K() {
710
- u !== null && clearTimeout(u), u = setTimeout(ne, Xe);
710
+ function ie() {
711
+ u !== null && clearTimeout(u), u = setTimeout(re, Xe);
711
712
  }
712
- function q(e) {
713
+ function G(e) {
713
714
  if (S.value.length <= 1) return;
714
- let t = e.currentTarget?.clientWidth || 1, n = te(e.deltaX, e.deltaMode, t);
715
- if (n === 0 || (e.preventDefault(), K(), f) || (d += n, Math.abs(d) < Ze)) return;
715
+ let t = e.currentTarget?.clientWidth || 1, n = ne(e.deltaX, e.deltaMode, t);
716
+ if (n === 0 || (e.preventDefault(), ie(), f) || (d += n, Math.abs(d) < Ze)) return;
716
717
  let r = Math.sign(d);
717
- d = 0, f = !0, G(E.value + r);
718
+ d = 0, f = !0, W(E.value + r);
718
719
  }
719
- function J(e) {
720
+ function K(e) {
720
721
  let t = e.touches[0];
721
722
  c.layout !== "reel" || !t || (p = t.clientX, h = t.clientY);
722
723
  }
723
- function Y(e) {
724
+ function q(e) {
724
725
  let t = e.changedTouches[0];
725
726
  if (p === null || h === null || !t) return;
726
727
  let n = p - t.clientX, r = h - t.clientY;
727
- p = null, h = null, !(Math.abs(n) <= Math.abs(r)) && (Math.abs(n) < Ye || G(E.value + Math.sign(n)));
728
+ p = null, h = null, !(Math.abs(n) <= Math.abs(r)) && (Math.abs(n) < Ye || W(E.value + Math.sign(n)));
728
729
  }
729
- let X = n(() => De(P.value));
730
- function re(e) {
731
- c.layout === "reel" && (e.stopPropagation(), ie());
730
+ let J = n(() => De(P.value));
731
+ function ae(e) {
732
+ c.layout === "reel" && (e.stopPropagation(), oe());
732
733
  }
733
- async function ie() {
734
+ async function oe() {
734
735
  if (L.value) {
735
736
  if (V.value) {
736
737
  L.value.pause();
@@ -743,35 +744,35 @@ var Oe = /* @__PURE__ */ u({
743
744
  }
744
745
  }
745
746
  }
746
- function ae(e) {
747
+ function Y(e) {
747
748
  return Number.isFinite(e) ? Math.max(0, e) : 0;
748
749
  }
749
- function Z(e) {
750
+ function X(e) {
750
751
  let t = e?.currentTarget ?? L.value;
751
- t && (R.value = ae(t.currentTime), z.value = ae(t.duration), B.value = t.muted, H.value = t.volume, t.volume > 0 && (U = t.volume));
752
+ t && (R.value = Y(t.currentTime), z.value = Y(t.duration), B.value = t.muted, ee.value = t.volume, t.volume > 0 && (H = t.volume));
752
753
  }
753
- function oe(e) {
754
- Z(e), b("ready", E.value);
754
+ function Z(e) {
755
+ X(e), b("ready", E.value);
755
756
  }
756
757
  function se() {
757
758
  V.value = !1, b("ended", E.value);
758
759
  }
759
760
  function ce(e) {
760
761
  let t = L.value;
761
- !t || !Number.isFinite(e) || (t.currentTime = Math.min(ae(t.duration), Math.max(0, e)), R.value = t.currentTime);
762
+ !t || !Number.isFinite(e) || (t.currentTime = Math.min(Y(t.duration), Math.max(0, e)), R.value = t.currentTime);
762
763
  }
763
764
  function le(e) {
764
765
  let t = L.value;
765
766
  if (!t || !Number.isFinite(e)) return;
766
767
  let n = Math.min(1, Math.max(0, e));
767
- t.volume = n, t.muted = n === 0, n > 0 && (U = n), Z();
768
+ t.volume = n, t.muted = n === 0, n > 0 && (H = n), X();
768
769
  }
769
770
  function ue() {
770
771
  let e = L.value;
771
- e && (e.muted && e.volume === 0 && (e.volume = U), e.muted = !e.muted, Z());
772
+ e && (e.muted && e.volume === 0 && (e.volume = H), e.muted = !e.muted, X());
772
773
  }
773
774
  return _(() => {
774
- ne();
775
+ re();
775
776
  }), (n, r) => (y(), o("article", {
776
777
  "data-post-id": e.item.postId,
777
778
  "data-media-index": E.value,
@@ -785,10 +786,10 @@ var Oe = /* @__PURE__ */ u({
785
786
  "aria-hidden": e.leaving || void 0,
786
787
  "aria-busy": e.previewState === "loading",
787
788
  inert: e.leaving || void 0,
788
- role: e.interactive && !e.leaving && !W.value ? "button" : void 0,
789
- tabindex: e.interactive && !e.leaving && !W.value ? 0 : void 0,
790
- onClick: r[11] ||= (t) => x(e.interactive && !W.value, ee(t)),
791
- onKeydown: [r[12] ||= k((t) => x(e.interactive && !W.value, "keyboard"), ["enter"]), r[13] ||= k(A((t) => x(e.interactive && !W.value, "keyboard"), ["prevent"]), ["space"])]
789
+ role: e.interactive && !e.leaving && !U.value ? "button" : void 0,
790
+ tabindex: e.interactive && !e.leaving && !U.value ? 0 : void 0,
791
+ onClick: r[11] ||= (t) => x(e.interactive && !U.value, te(t)),
792
+ onKeydown: [r[12] ||= k((t) => x(e.interactive && !U.value, "keyboard"), ["enter"]), r[13] ||= k(A((t) => x(e.interactive && !U.value, "keyboard"), ["prevent"]), ["space"])]
792
793
  }, [s("div", Re, [
793
794
  e.cardHeader ? (y(), i(Oe, {
794
795
  key: 0,
@@ -816,9 +817,9 @@ var Oe = /* @__PURE__ */ u({
816
817
  s("div", {
817
818
  class: m(["media-card-media", { "media-card-media--carousel": e.layout === "reel" && S.value.length > 1 }]),
818
819
  "data-media-direction": v.value,
819
- onWheel: q,
820
- onTouchstartPassive: J,
821
- onTouchendPassive: Y
820
+ onWheel: G,
821
+ onTouchstartPassive: K,
822
+ onTouchendPassive: q
822
823
  }, [
823
824
  l(t, { name: `media-slide-${v.value}` }, {
824
825
  default: O(() => [(y(), o("div", {
@@ -831,7 +832,7 @@ var Oe = /* @__PURE__ */ u({
831
832
  class: "media-error",
832
833
  role: "img",
833
834
  "aria-label": `${T(we)(P.value)} ${T(Te)(P.value)}`
834
- }, [s("strong", Ue, w(T(we)(P.value)), 1), s("span", null, w(T(Te)(P.value)), 1)], 8, He)) : a("", !0), X.value ? (y(), o("video", {
835
+ }, [s("strong", Ue, w(T(we)(P.value)), 1), s("span", null, w(T(Te)(P.value)), 1)], 8, He)) : a("", !0), J.value ? (y(), o("video", {
835
836
  key: 2,
836
837
  ref_key: "videoElement",
837
838
  ref: L,
@@ -847,14 +848,14 @@ var Oe = /* @__PURE__ */ u({
847
848
  muted: B.value,
848
849
  playsinline: "",
849
850
  preload: e.fetchPriority === "high" ? "auto" : "metadata",
850
- onLoadedmetadata: oe,
851
- onDurationchange: Z,
852
- onTimeupdate: Z,
853
- onVolumechange: Z,
851
+ onLoadedmetadata: Z,
852
+ onDurationchange: X,
853
+ onTimeupdate: X,
854
+ onVolumechange: X,
854
855
  onPlaying: r[0] ||= (e) => V.value = !0,
855
856
  onPause: r[1] ||= (e) => V.value = !1,
856
857
  onEnded: se,
857
- onClick: re,
858
+ onClick: ae,
858
859
  onError: r[2] ||= (e) => n.$emit("error", E.value)
859
860
  }, null, 42, We)) : (y(), o("img", {
860
861
  key: 3,
@@ -871,17 +872,17 @@ var Oe = /* @__PURE__ */ u({
871
872
  }, null, 42, Ge))], 8, Be))]),
872
873
  _: 1
873
874
  }, 8, ["name"]),
874
- X.value && e.previewState === "ready" ? (y(), i(Ie, {
875
+ J.value && e.previewState === "ready" ? (y(), i(Ie, {
875
876
  key: 0,
876
877
  "current-time": R.value,
877
878
  duration: z.value,
878
879
  layout: e.layout,
879
880
  muted: B.value,
880
881
  playing: V.value,
881
- volume: H.value,
882
+ volume: ee.value,
882
883
  onSeek: ce,
883
884
  onToggleMute: ue,
884
- onTogglePlayback: ie,
885
+ onTogglePlayback: oe,
885
886
  onVolumeChange: le
886
887
  }, null, 8, [
887
888
  "current-time",
@@ -899,21 +900,21 @@ var Oe = /* @__PURE__ */ u({
899
900
  type: "button",
900
901
  class: "media-carousel-control media-carousel-control--previous",
901
902
  "aria-label": `Previous media for post ${e.item.postId}`,
902
- onClick: r[5] ||= A((e) => G(E.value - 1, e), ["stop"]),
903
+ onClick: r[5] ||= A((e) => W(E.value - 1, e), ["stop"]),
903
904
  onKeydown: r[6] ||= A(() => {}, ["stop"])
904
905
  }, [l(T(_e), { size: 20 })], 40, Ke), s("button", {
905
906
  type: "button",
906
907
  class: "media-carousel-control media-carousel-control--next",
907
908
  "aria-label": `Next media for post ${e.item.postId}`,
908
- onClick: r[7] ||= A((e) => G(E.value + 1, e), ["stop"]),
909
+ onClick: r[7] ||= A((e) => W(E.value + 1, e), ["stop"]),
909
910
  onKeydown: r[8] ||= A(() => {}, ["stop"])
910
911
  }, [l(T(ve), { size: 20 })], 40, qe)], 2)) : a("", !0),
911
- W.value ? (y(), o("button", {
912
+ U.value ? (y(), o("button", {
912
913
  key: 2,
913
914
  class: "media-card-activator",
914
915
  type: "button",
915
916
  "aria-label": `Open post ${e.item.postId}`,
916
- onClick: r[9] ||= A((e) => n.$emit("activate", ee(e)), ["stop"]),
917
+ onClick: r[9] ||= A((e) => n.$emit("activate", te(e)), ["stop"]),
917
918
  onKeydown: r[10] ||= A(() => {}, ["stop"])
918
919
  }, null, 40, Je)) : a("", !0)
919
920
  ], 42, ze),
@@ -976,14 +977,14 @@ var Oe = /* @__PURE__ */ u({
976
977
  "retryEnd"
977
978
  ],
978
979
  setup(t, { expose: r, emit: a }) {
979
- let c = t, u = a, d = C(null), f = `vibe-masonry-${E()}`, p = C(null), h = C(0), v = C(nt), b = C(0), S = C(0), w = C(0), O = null, k = null, A = null, j = n(() => J(c.items, h.value, {
980
+ let c = t, u = a, d = C(null), f = `vibe-masonry-${E()}`, p = C(null), h = C(0), v = C(nt), b = C(0), S = C(0), w = C(0), O = null, k = null, A = null, j = n(() => K(c.items, h.value, {
980
981
  additionalHeight: (c.cardHeader?.height ?? 0) + (c.cardFooter?.height ?? 0),
981
982
  gap: v.value,
982
983
  minColumnWidth: tt
983
984
  })), M = n(() => {
984
985
  let e = j.value;
985
986
  if (c.leavingPostIds.size === 0) return e;
986
- let t = c.items.filter((e) => !c.leavingPostIds.has(e.postId)), n = J(t, h.value, {
987
+ let t = c.items.filter((e) => !c.leavingPostIds.has(e.postId)), n = K(t, h.value, {
987
988
  additionalHeight: (c.cardHeader?.height ?? 0) + (c.cardFooter?.height ?? 0),
988
989
  gap: v.value,
989
990
  minColumnWidth: tt
@@ -996,16 +997,16 @@ var Oe = /* @__PURE__ */ u({
996
997
  let e = Math.max(it, S.value * at), t = {
997
998
  scrollTop: b.value - w.value,
998
999
  viewportHeight: S.value
999
- }, n = q(M.value.items, {
1000
+ }, n = G(M.value.items, {
1000
1001
  ...t,
1001
1002
  overscan: e
1002
- }), r = c.leavingPostIds.size === 0 ? [] : q(j.value.items, {
1003
+ }), r = c.leavingPostIds.size === 0 ? [] : G(j.value.items, {
1003
1004
  ...t,
1004
1005
  overscan: e
1005
- }), i = [...new Set([...n, ...r])].sort((e, t) => e - t), a = q(M.value.items, {
1006
+ }), i = [...new Set([...n, ...r])].sort((e, t) => e - t), a = G(M.value.items, {
1006
1007
  ...t,
1007
1008
  overscan: 0
1008
- }), o = c.leavingPostIds.size === 0 ? [] : q(j.value.items, {
1009
+ }), o = c.leavingPostIds.size === 0 ? [] : G(j.value.items, {
1009
1010
  ...t,
1010
1011
  overscan: 0
1011
1012
  }), s = new Set([...a, ...o]);
@@ -1021,7 +1022,7 @@ var Oe = /* @__PURE__ */ u({
1021
1022
  function I(e) {
1022
1023
  let t = M.value.items[e], n = c.items[e]?.postId;
1023
1024
  if (!t) return {};
1024
- let r = n !== void 0 && c.enteringPostIds.has(n), i = n !== void 0 && c.leavingPostIds.has(n), a = r || i ? K({
1025
+ let r = n !== void 0 && c.enteringPostIds.has(n), i = n !== void 0 && c.leavingPostIds.has(n), a = r || i ? ie({
1025
1026
  containerHeight: j.value.height,
1026
1027
  gap: v.value
1027
1028
  }) : 0, o = n === void 0 ? 0 : i ? c.removalDelays.get(n) ?? 0 : r ? c.entryDelays.get(n) ?? 0 : 0;
@@ -1045,11 +1046,11 @@ var Oe = /* @__PURE__ */ u({
1045
1046
  }
1046
1047
  function z(e) {
1047
1048
  let t = e.currentTarget;
1048
- t && (b.value = t.scrollTop, !c.loadMoreLocked && c.infiniteScroll && G(t) && u("loadMore"));
1049
+ t && (b.value = t.scrollTop, !c.loadMoreLocked && c.infiniteScroll && W(t) && u("loadMore"));
1049
1050
  }
1050
1051
  function B() {
1051
1052
  let e = d.value;
1052
- !c.loadMoreLocked && e && G(e) && u("loadMore");
1053
+ !c.loadMoreLocked && e && W(e) && u("loadMore");
1053
1054
  }
1054
1055
  function V() {
1055
1056
  return d.value;
@@ -1123,7 +1124,7 @@ var Oe = /* @__PURE__ */ u({
1123
1124
  "onMediaChange",
1124
1125
  "onReady",
1125
1126
  "onError"
1126
- ]))), 128))], 6), l(H, {
1127
+ ]))), 128))], 6), l(ee, {
1127
1128
  actions: t.feedFooterActions,
1128
1129
  "can-retry-end": t.canRetryEnd,
1129
1130
  "feed-footer": t.feedFooter,
@@ -1174,12 +1175,16 @@ var Oe = /* @__PURE__ */ u({
1174
1175
  onAnimationend: n[0] ||= (e) => i("complete")
1175
1176
  }, null, 36)], 8, st));
1176
1177
  }
1177
- }), lt = ["data-active-post-id", "data-active-media-index"], ut = 2, dt = /* @__PURE__ */ u({
1178
+ }), lt = ["data-active-post-id", "data-active-media-index"], ut = ["role", "data-status"], dt = 2, ft = /* @__PURE__ */ u({
1178
1179
  __name: "ReelFeed",
1179
1180
  props: {
1180
1181
  initialPostId: {},
1181
1182
  mediaSource: {},
1182
1183
  reelAutoAdvance: {},
1184
+ reelForward: { default: () => ({
1185
+ error: null,
1186
+ status: "idle"
1187
+ }) },
1183
1188
  canRetryEnd: { type: Boolean },
1184
1189
  cardFooter: {},
1185
1190
  cardHeader: {},
@@ -1203,95 +1208,96 @@ var Oe = /* @__PURE__ */ u({
1203
1208
  "loadMore",
1204
1209
  "mediaChange",
1205
1210
  "ready",
1206
- "retryEnd"
1211
+ "retryEnd",
1212
+ "retryForward"
1207
1213
  ],
1208
1214
  setup(t, { expose: r, emit: c }) {
1209
- let u = t, d = c, f = C(null), h = u.initialPostId === null || u.initialPostId === void 0 ? -1 : u.items.findIndex((e) => e.postId === u.initialPostId), b = C(Math.max(0, h)), S = C(!1), w = 0, E = null, O = null, k = null, A = n(() => ({ gridTemplateRows: `repeat(${u.items.length}, 100cqh)` })), M = n(() => {
1210
- let e = Math.max(0, b.value - ut), t = Math.min(u.items.length - 1, b.value + ut);
1211
- return u.items.slice(e, t + 1).map((t, n) => ({
1212
- fetchPriority: e + n === b.value ? "high" : "low",
1215
+ let l = t, u = c, d = C(null), f = l.initialPostId === null || l.initialPostId === void 0 ? -1 : l.items.findIndex((e) => e.postId === l.initialPostId), h = C(Math.max(0, f)), b = C(!1), S = 0, E = null, O = null, k = null, A = n(() => ({ gridTemplateRows: `repeat(${l.items.length}, 100cqh)` })), M = n(() => {
1216
+ let e = Math.max(0, h.value - dt), t = Math.min(l.items.length - 1, h.value + dt);
1217
+ return l.items.slice(e, t + 1).map((t, n) => ({
1218
+ fetchPriority: e + n === h.value ? "high" : "low",
1213
1219
  index: e + n,
1214
1220
  item: t
1215
1221
  }));
1216
- }), F = n(() => u.items[b.value]?.postId), I = n(() => u.items[b.value]), L = n(() => {
1222
+ }), F = n(() => l.items[h.value]?.postId), I = n(() => l.items[h.value]), L = n(() => {
1217
1223
  let e = F.value;
1218
- return e === void 0 ? 0 : u.mediaIndices.get(e) ?? 0;
1224
+ return e === void 0 ? 0 : l.mediaIndices.get(e) ?? 0;
1219
1225
  }), R = n(() => {
1220
1226
  let e = F.value;
1221
- return e === void 0 ? "loading" : u.previewStates.get(P(e, L.value)) ?? "loading";
1227
+ return e === void 0 ? "loading" : l.previewStates.get(P(e, L.value)) ?? "loading";
1222
1228
  }), z = n(() => {
1223
1229
  let e = I.value;
1224
1230
  if (!e) return "";
1225
1231
  let t = N(e, L.value);
1226
- return u.mediaSource === "original" ? t.src : t.preview.src;
1232
+ return l.mediaSource === "original" ? t.src : t.preview.src;
1227
1233
  }), B = n(() => R.value === "ready" && De(z.value)), V = n(() => [
1228
1234
  F.value,
1229
1235
  L.value,
1230
- u.items.length,
1231
- u.loadMoreLocked,
1232
- u.reelAutoAdvance.enabled,
1233
- u.reelAutoAdvance.includePostItems,
1234
- u.reelAutoAdvance.intervalMs
1235
- ].join(":")), U = n(() => {
1236
- let e = I.value, t = !!(e && u.reelAutoAdvance.includePostItems && L.value < j(e).length - 1), n = u.reelAutoAdvance.intervalMs / 1e3;
1236
+ l.items.length,
1237
+ l.loadMoreLocked,
1238
+ l.reelAutoAdvance.enabled,
1239
+ l.reelAutoAdvance.includePostItems,
1240
+ l.reelAutoAdvance.intervalMs
1241
+ ].join(":")), H = n(() => {
1242
+ let e = I.value, t = !!(e && l.reelAutoAdvance.includePostItems && L.value < j(e).length - 1), n = l.reelAutoAdvance.intervalMs / 1e3;
1237
1243
  return `Auto advance to the next ${t ? "post item" : "post"} in ${n}s`;
1238
- }), W = n(() => u.reelAutoAdvance.enabled && I.value !== void 0 && R.value !== "loading" && !B.value);
1239
- function ee(e) {
1244
+ }), U = n(() => l.reelAutoAdvance.enabled && l.reelForward.status === "idle" && I.value !== void 0 && R.value !== "loading" && !B.value), te = n(() => l.reelForward.status === "loading" ? "Loading the next media…" : l.reelForward.status === "error" ? "Unable to load the next media." : "You reached the end of this feed.");
1245
+ function ne(e) {
1240
1246
  return { gridRow: `${e + 1}` };
1241
1247
  }
1242
- function te(e) {
1243
- let t = w || e.clientHeight;
1244
- return t <= 0 || u.items.length === 0 ? 0 : Math.min(u.items.length - 1, Math.max(0, Math.round(e.scrollTop / t)));
1248
+ function re(e) {
1249
+ let t = S || e.clientHeight;
1250
+ return t <= 0 || l.items.length === 0 ? 0 : Math.min(l.items.length - 1, Math.max(0, Math.round(e.scrollTop / t)));
1245
1251
  }
1246
- function ne(e) {
1252
+ function ie(e) {
1247
1253
  let t = e.currentTarget;
1248
- t && (S.value || (b.value = te(t)), !u.loadMoreLocked && u.infiniteScroll && G(t) && d("loadMore"));
1254
+ t && (b.value || (h.value = re(t)), !l.loadMoreLocked && l.infiniteScroll && W(t) && u("loadMore"));
1249
1255
  }
1250
- function K() {
1251
- let e = f.value;
1252
- e && (Y(!0), w = e.clientHeight, e.scrollTop = b.value * w, O !== null && cancelAnimationFrame(O), O = requestAnimationFrame(() => {
1253
- e.scrollTop = b.value * e.clientHeight, w = e.clientHeight, O = null;
1254
- }), q());
1256
+ function G() {
1257
+ let e = d.value;
1258
+ e && (J(!0), S = e.clientHeight, e.scrollTop = h.value * S, O !== null && cancelAnimationFrame(O), O = requestAnimationFrame(() => {
1259
+ e.scrollTop = h.value * e.clientHeight, S = e.clientHeight, O = null;
1260
+ }), K());
1255
1261
  }
1256
- function q() {
1262
+ function K() {
1257
1263
  k !== null && clearTimeout(k), k = setTimeout(() => {
1258
1264
  k = null;
1259
- let e = f.value;
1260
- e && (w = e.clientHeight, e.scrollTop = b.value * w), Y(!1);
1265
+ let e = d.value;
1266
+ e && (S = e.clientHeight, e.scrollTop = h.value * S), J(!1);
1261
1267
  }, 120);
1262
1268
  }
1263
- function J() {
1264
- Y(!0);
1265
- let e = f.value;
1266
- e && (w = e.clientHeight, e.scrollTop = b.value * w), q();
1269
+ function q() {
1270
+ J(!0);
1271
+ let e = d.value;
1272
+ e && (S = e.clientHeight, e.scrollTop = h.value * S), K();
1267
1273
  }
1268
- function Y(e) {
1269
- S.value = e, f.value?.toggleAttribute("data-resizing", e);
1274
+ function J(e) {
1275
+ b.value = e, d.value?.toggleAttribute("data-resizing", e);
1270
1276
  }
1271
- function X() {
1272
- let e = f.value;
1273
- !u.loadMoreLocked && e && G(e) && d("loadMore");
1277
+ function ae() {
1278
+ let e = d.value;
1279
+ !l.loadMoreLocked && e && W(e) && u("loadMore");
1274
1280
  }
1275
- function re(e) {
1281
+ function oe(e) {
1276
1282
  let t = I.value;
1277
1283
  if (!t) return !1;
1278
1284
  let n = j(t).length;
1279
1285
  if (n <= 1) return !1;
1280
1286
  let r = (L.value + e + n) % n;
1281
- return d("mediaChange", t.postId, r), !0;
1287
+ return u("mediaChange", t.postId, r), !0;
1282
1288
  }
1283
- function ie(e) {
1284
- let t = b.value + e;
1285
- return !f.value || t < 0 || t >= u.items.length ? !1 : (Z(t), !0);
1289
+ function Y(e) {
1290
+ let t = h.value + e;
1291
+ return !d.value || t < 0 || t >= l.items.length ? !1 : (Z(t), !0);
1286
1292
  }
1287
- function ae() {
1293
+ function X() {
1288
1294
  return typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1289
1295
  }
1290
1296
  function Z(e) {
1291
- let t = f.value;
1297
+ let t = d.value;
1292
1298
  if (!t) return;
1293
- let n = e * (w || t.clientHeight);
1294
- if (b.value = e, !ae() && typeof t.scrollTo == "function") {
1299
+ let n = e * (S || t.clientHeight);
1300
+ if (h.value = e, !X() && typeof t.scrollTo == "function") {
1295
1301
  t.scrollTo({
1296
1302
  behavior: "smooth",
1297
1303
  top: n
@@ -1300,40 +1306,40 @@ var Oe = /* @__PURE__ */ u({
1300
1306
  }
1301
1307
  t.scrollTop = n;
1302
1308
  }
1303
- function oe() {
1304
- if (!u.reelAutoAdvance.enabled) return;
1309
+ function se() {
1310
+ if (!l.reelAutoAdvance.enabled) return;
1305
1311
  let e = I.value;
1306
1312
  if (!e) return;
1307
- if (u.reelAutoAdvance.includePostItems && L.value < j(e).length - 1) {
1308
- d("mediaChange", e.postId, L.value + 1);
1313
+ if (l.reelAutoAdvance.includePostItems && L.value < j(e).length - 1) {
1314
+ u("mediaChange", e.postId, L.value + 1);
1309
1315
  return;
1310
1316
  }
1311
- let t = b.value + 1, n = u.items[t];
1317
+ let t = h.value + 1, n = l.items[t];
1312
1318
  if (!n) {
1313
- u.hasNext && !u.loadMoreLocked && d("loadMore");
1319
+ l.hasNext && !l.loadMoreLocked && u("loadMore");
1314
1320
  return;
1315
1321
  }
1316
- u.reelAutoAdvance.includePostItems && (u.mediaIndices.get(n.postId) ?? 0) !== 0 && d("mediaChange", n.postId, 0), Z(t);
1322
+ l.reelAutoAdvance.includePostItems && (l.mediaIndices.get(n.postId) ?? 0) !== 0 && u("mediaChange", n.postId, 0), Z(t);
1317
1323
  }
1318
- function se(e, t) {
1319
- !u.reelAutoAdvance.enabled || e !== F.value || t !== L.value || !B.value || oe();
1324
+ function ce(e, t) {
1325
+ !l.reelAutoAdvance.enabled || e !== F.value || t !== L.value || !B.value || se();
1320
1326
  }
1321
- return D(f, (e) => {
1322
- E?.disconnect(), E = null, e && (w = e.clientHeight, !(typeof ResizeObserver > "u") && (E = new ResizeObserver(K), E.observe(e)));
1323
- }), D(() => u.items.length, async (e) => {
1324
- b.value = Math.min(b.value, Math.max(0, e - 1)), await p(), K();
1327
+ return D(d, (e) => {
1328
+ E?.disconnect(), E = null, e && (S = e.clientHeight, !(typeof ResizeObserver > "u") && (E = new ResizeObserver(G), E.observe(e)));
1329
+ }), D(() => l.items.length, async (e) => {
1330
+ h.value = Math.min(h.value, Math.max(0, e - 1)), await p(), G();
1325
1331
  }), D(F, (e) => {
1326
- e !== void 0 && d("activeChange", e);
1332
+ e !== void 0 && u("activeChange", e);
1327
1333
  }, { immediate: !0 }), v(() => {
1328
- window.addEventListener("resize", J), window.addEventListener("orientationchange", J), h >= 0 && p(K);
1334
+ window.addEventListener("resize", q), window.addEventListener("orientationchange", q), f >= 0 && p(G);
1329
1335
  }), _(() => {
1330
- window.removeEventListener("resize", J), window.removeEventListener("orientationchange", J), E?.disconnect(), O !== null && cancelAnimationFrame(O), k !== null && clearTimeout(k);
1336
+ window.removeEventListener("resize", q), window.removeEventListener("orientationchange", q), E?.disconnect(), O !== null && cancelAnimationFrame(O), k !== null && clearTimeout(k);
1331
1337
  }), r({
1332
- activeIndex: b,
1338
+ activeIndex: h,
1333
1339
  activePostId: F,
1334
- changeActiveMedia: re,
1335
- loadIfNearBottom: X,
1336
- moveActivePost: ie
1340
+ changeActiveMedia: oe,
1341
+ loadIfNearBottom: ae,
1342
+ moveActivePost: Y
1337
1343
  }), (n, r) => (y(), o("main", {
1338
1344
  class: m(["reel-shell", {
1339
1345
  "reel-shell--has-footer": !!t.cardFooter,
@@ -1341,9 +1347,9 @@ var Oe = /* @__PURE__ */ u({
1341
1347
  }]),
1342
1348
  "data-layout-mode": "reel"
1343
1349
  }, [
1344
- t.cardHeader && I.value ? (y(), i(Oe, {
1350
+ t.cardHeader && I.value && t.reelForward.status === "idle" ? (y(), i(Oe, {
1345
1351
  key: 0,
1346
- index: b.value,
1352
+ index: h.value,
1347
1353
  item: I.value,
1348
1354
  layout: "reel",
1349
1355
  "loaded-count": t.items.length,
@@ -1365,24 +1371,25 @@ var Oe = /* @__PURE__ */ u({
1365
1371
  ])) : a("", !0),
1366
1372
  s("div", {
1367
1373
  ref_key: "galleryElement",
1368
- ref: f,
1374
+ ref: d,
1369
1375
  class: "gallery-shell reel-feed",
1370
1376
  "data-active-post-id": F.value,
1371
1377
  "data-active-media-index": L.value,
1372
- onScrollPassive: ne
1373
- }, [s("section", {
1378
+ onScrollPassive: ie
1379
+ }, [t.reelForward.status === "idle" ? (y(), o("section", {
1380
+ key: 1,
1374
1381
  class: "reel-track",
1375
1382
  style: g(A.value),
1376
1383
  "aria-label": "Media gallery"
1377
1384
  }, [(y(!0), o(e, null, x(M.value, ({ fetchPriority: e, item: n, index: r }) => (y(), i(Qe, {
1378
1385
  key: n.postId,
1379
- "advance-on-media-end": u.reelAutoAdvance.enabled && r === b.value,
1386
+ "advance-on-media-end": l.reelAutoAdvance.enabled && r === h.value,
1380
1387
  class: "reel-item",
1381
1388
  entering: !1,
1382
1389
  "fetch-priority": e,
1383
1390
  index: r,
1384
1391
  item: n,
1385
- "item-style": ee(r),
1392
+ "item-style": ne(r),
1386
1393
  "media-card": t.mediaCard,
1387
1394
  layout: "reel",
1388
1395
  "loaded-count": t.items.length,
@@ -1390,10 +1397,10 @@ var Oe = /* @__PURE__ */ u({
1390
1397
  "media-source": t.mediaSource,
1391
1398
  "preview-state": t.previewStates.get(T(P)(n.postId, t.mediaIndices.get(n.postId) ?? 0)) ?? "loading",
1392
1399
  total: t.total,
1393
- onMediaChange: (e) => d("mediaChange", n.postId, e),
1394
- onEnded: (e) => se(n.postId, e),
1395
- onReady: (e) => d("ready", n.postId, e),
1396
- onError: (e) => d("error", n.postId, e)
1400
+ onMediaChange: (e) => u("mediaChange", n.postId, e),
1401
+ onEnded: (e) => ce(n.postId, e),
1402
+ onReady: (e) => u("ready", n.postId, e),
1403
+ onError: (e) => u("error", n.postId, e)
1397
1404
  }, null, 8, [
1398
1405
  "advance-on-media-end",
1399
1406
  "fetch-priority",
@@ -1410,7 +1417,18 @@ var Oe = /* @__PURE__ */ u({
1410
1417
  "onEnded",
1411
1418
  "onReady",
1412
1419
  "onError"
1413
- ]))), 128))], 4), l(H, {
1420
+ ]))), 128))], 4)) : (y(), o("div", {
1421
+ key: 0,
1422
+ class: "reel-forward-status",
1423
+ role: t.reelForward.status === "error" ? "alert" : "status",
1424
+ "data-status": t.reelForward.status
1425
+ }, [s("p", null, w(te.value), 1), t.reelForward.status === "error" || t.reelForward.status === "end" ? (y(), o("button", {
1426
+ key: 0,
1427
+ class: "reel-forward-retry",
1428
+ type: "button",
1429
+ onClick: r[0] ||= (e) => u("retryForward")
1430
+ }, " Retry ")) : a("", !0)], 8, ut)), t.reelForward.status === "idle" ? (y(), i(ee, {
1431
+ key: 2,
1414
1432
  actions: t.feedFooterActions,
1415
1433
  "can-retry-end": t.canRetryEnd,
1416
1434
  "feed-footer": t.feedFooter,
@@ -1419,8 +1437,8 @@ var Oe = /* @__PURE__ */ u({
1419
1437
  "is-loading": t.isLoadingMore,
1420
1438
  "load-more-locked": t.loadMoreLocked,
1421
1439
  state: t.state,
1422
- onLoadMore: r[0] ||= (e) => d("loadMore"),
1423
- onRetryEnd: r[1] ||= (e) => d("retryEnd")
1440
+ onLoadMore: r[1] ||= (e) => u("loadMore"),
1441
+ onRetryEnd: r[2] ||= (e) => u("retryEnd")
1424
1442
  }, null, 8, [
1425
1443
  "actions",
1426
1444
  "can-retry-end",
@@ -1430,10 +1448,10 @@ var Oe = /* @__PURE__ */ u({
1430
1448
  "is-loading",
1431
1449
  "load-more-locked",
1432
1450
  "state"
1433
- ])], 40, lt),
1434
- t.cardFooter && I.value ? (y(), i(Oe, {
1451
+ ])) : a("", !0)], 40, lt),
1452
+ t.cardFooter && I.value && t.reelForward.status === "idle" ? (y(), i(Oe, {
1435
1453
  key: 1,
1436
- index: b.value,
1454
+ index: h.value,
1437
1455
  item: I.value,
1438
1456
  layout: "reel",
1439
1457
  "loaded-count": t.items.length,
@@ -1453,26 +1471,28 @@ var Oe = /* @__PURE__ */ u({
1453
1471
  "style",
1454
1472
  "total"
1455
1473
  ])) : a("", !0),
1456
- W.value ? (y(), i(ct, {
1474
+ U.value ? (y(), i(ct, {
1457
1475
  key: V.value,
1458
1476
  "duration-ms": t.reelAutoAdvance.intervalMs,
1459
- label: U.value,
1460
- onComplete: oe
1477
+ label: H.value,
1478
+ onComplete: se
1461
1479
  }, null, 8, ["duration-ms", "label"])) : a("", !0)
1462
1480
  ], 2));
1463
1481
  }
1464
- }), ft = ["data-info-sheet-open", "data-info-sheet-mode"], pt = ["aria-hidden", "inert"], mt = {
1482
+ }), pt = ["data-info-sheet-open", "data-info-sheet-mode"], mt = ["aria-hidden", "inert"], ht = {
1465
1483
  key: 0,
1466
1484
  class: "reel-info-sheet-layer",
1467
1485
  "data-test": "reel-info-sheet"
1468
- }, ht = [
1486
+ }, gt = [
1469
1487
  "role",
1470
1488
  "aria-modal",
1471
1489
  "tabindex",
1472
1490
  "data-active-post-id"
1473
- ], gt = /* @__PURE__ */ u({
1491
+ ], _t = /* @__PURE__ */ u({
1474
1492
  __name: "ReelLayout",
1475
1493
  props: {
1494
+ forwardIndex: { default: null },
1495
+ forwardItem: { default: null },
1476
1496
  infoSheet: {},
1477
1497
  infoSheetEnabled: { type: Boolean },
1478
1498
  infoSheetOverlay: { type: Boolean },
@@ -1480,6 +1500,10 @@ var Oe = /* @__PURE__ */ u({
1480
1500
  initialPostId: {},
1481
1501
  mediaSource: {},
1482
1502
  reelAutoAdvance: {},
1503
+ reelForward: { default: () => ({
1504
+ error: null,
1505
+ status: "idle"
1506
+ }) },
1483
1507
  canRetryEnd: { type: Boolean },
1484
1508
  cardFooter: {},
1485
1509
  cardHeader: {},
@@ -1504,55 +1528,56 @@ var Oe = /* @__PURE__ */ u({
1504
1528
  "loadMore",
1505
1529
  "mediaChange",
1506
1530
  "ready",
1507
- "retryEnd"
1531
+ "retryEnd",
1532
+ "retryForward"
1508
1533
  ],
1509
1534
  setup(e, { expose: r, emit: c }) {
1510
1535
  let u = e, f = c, g = C(null), v = C(null), b = null, x = n(() => {
1511
1536
  let e = u.initialPostId === null || u.initialPostId === void 0 ? -1 : u.items.findIndex((e) => e.postId === u.initialPostId);
1512
1537
  return Math.max(0, e);
1513
- }), w = n(() => u.items[x.value]), T = n(() => {
1514
- let e = w.value?.postId;
1538
+ }), w = n(() => u.items[x.value]), T = n(() => w.value ?? (u.reelForward.status === "idle" ? void 0 : u.forwardItem ?? void 0)), E = n(() => w.value ? x.value : u.forwardIndex ?? 0), k = n(() => {
1539
+ let e = T.value?.postId;
1515
1540
  return e === void 0 ? 0 : u.mediaIndices.get(e) ?? 0;
1516
- }), E = n(() => !!(u.infoSheet && u.infoSheetEnabled && w.value)), k = n(() => {
1517
- let e = w.value;
1541
+ }), A = n(() => !!(u.infoSheet && u.infoSheetEnabled && T.value)), M = n(() => {
1542
+ let e = T.value;
1518
1543
  return e ? {
1519
- close: A,
1520
- index: x.value,
1544
+ close: P,
1545
+ index: E.value,
1521
1546
  item: e,
1522
1547
  layout: "reel",
1523
1548
  loadedCount: u.items.length,
1524
1549
  mediaCount: j(e).length,
1525
- mediaIndex: T.value,
1526
- mediaItem: N(e, T.value),
1550
+ mediaIndex: k.value,
1551
+ mediaItem: N(e, k.value),
1527
1552
  mediaSource: u.mediaSource ?? "preview",
1528
1553
  origin: u.origin,
1529
1554
  total: u.total
1530
1555
  } : null;
1531
1556
  });
1532
- function A() {
1557
+ function P() {
1533
1558
  f("closeInfoSheet");
1534
1559
  }
1535
- function M(e) {
1560
+ function F(e) {
1536
1561
  return g.value?.changeActiveMedia(e) ?? !1;
1537
1562
  }
1538
- function P() {
1563
+ function I() {
1539
1564
  g.value?.loadIfNearBottom();
1540
1565
  }
1541
- function F(e) {
1566
+ function L(e) {
1542
1567
  return g.value?.moveActivePost(e) ?? !1;
1543
1568
  }
1544
- function I(e, t) {
1569
+ function R(e, t) {
1545
1570
  f("error", e, t);
1546
1571
  }
1547
- function L(e, t) {
1572
+ function z(e, t) {
1548
1573
  f("mediaChange", e, t);
1549
1574
  }
1550
- function R(e, t) {
1575
+ function B(e, t) {
1551
1576
  f("ready", e, t);
1552
1577
  }
1553
1578
  return D(() => ({
1554
1579
  overlay: u.infoSheetOverlay,
1555
- visible: E.value
1580
+ visible: A.value
1556
1581
  }), async (e, t) => {
1557
1582
  if (e.visible && !t?.visible) {
1558
1583
  b = document.activeElement instanceof HTMLElement ? document.activeElement : null, e.overlay && (await p(), v.value?.focus({ preventScroll: !0 }));
@@ -1565,18 +1590,18 @@ var Oe = /* @__PURE__ */ u({
1565
1590
  }), _(() => {
1566
1591
  b = null;
1567
1592
  }), r({
1568
- changeActiveMedia: M,
1569
- loadIfNearBottom: P,
1570
- moveActivePost: F
1593
+ changeActiveMedia: F,
1594
+ loadIfNearBottom: I,
1595
+ moveActivePost: L
1571
1596
  }), (n, r) => (y(), o("section", {
1572
1597
  class: m(["reel-layout", `reel-layout--${e.infoSheetOverlay ? "overlay" : "layout"}`]),
1573
- "data-info-sheet-open": E.value || void 0,
1598
+ "data-info-sheet-open": A.value || void 0,
1574
1599
  "data-info-sheet-mode": e.infoSheetOverlay ? "overlay" : "layout"
1575
1600
  }, [s("div", {
1576
1601
  class: "reel-layout-main",
1577
- "aria-hidden": e.infoSheetOverlay && E.value || void 0,
1578
- inert: e.infoSheetOverlay && E.value || void 0
1579
- }, [l(dt, {
1602
+ "aria-hidden": e.infoSheetOverlay && A.value || void 0,
1603
+ inert: e.infoSheetOverlay && A.value || void 0
1604
+ }, [l(ft, {
1580
1605
  ref_key: "reelFeed",
1581
1606
  ref: g,
1582
1607
  "can-retry-end": e.canRetryEnd,
@@ -1596,14 +1621,16 @@ var Oe = /* @__PURE__ */ u({
1596
1621
  "next-page-error": e.nextPageError,
1597
1622
  "preview-states": e.previewStates,
1598
1623
  "reel-auto-advance": e.reelAutoAdvance,
1624
+ "reel-forward": e.reelForward,
1599
1625
  state: e.state,
1600
1626
  total: e.total,
1601
1627
  onActiveChange: r[0] ||= (e) => f("activeChange", e),
1602
- onError: I,
1628
+ onError: R,
1603
1629
  onLoadMore: r[1] ||= (e) => f("loadMore"),
1604
- onMediaChange: L,
1605
- onReady: R,
1606
- onRetryEnd: r[2] ||= (e) => f("retryEnd")
1630
+ onMediaChange: z,
1631
+ onReady: B,
1632
+ onRetryEnd: r[2] ||= (e) => f("retryEnd"),
1633
+ onRetryForward: r[3] ||= (e) => f("retryForward")
1607
1634
  }, null, 8, [
1608
1635
  "can-retry-end",
1609
1636
  "card-footer",
@@ -1622,10 +1649,11 @@ var Oe = /* @__PURE__ */ u({
1622
1649
  "next-page-error",
1623
1650
  "preview-states",
1624
1651
  "reel-auto-advance",
1652
+ "reel-forward",
1625
1653
  "state",
1626
1654
  "total"
1627
- ])], 8, pt), l(t, { name: "vibe-info-sheet" }, {
1628
- default: O(() => [E.value && e.infoSheet && k.value ? (y(), o("div", mt, [s("aside", {
1655
+ ])], 8, mt), l(t, { name: "vibe-info-sheet" }, {
1656
+ default: O(() => [A.value && e.infoSheet && M.value ? (y(), o("div", ht, [s("aside", {
1629
1657
  ref_key: "sheetElement",
1630
1658
  ref: v,
1631
1659
  class: "reel-info-sheet",
@@ -1633,12 +1661,12 @@ var Oe = /* @__PURE__ */ u({
1633
1661
  "aria-label": "Reel information",
1634
1662
  "aria-modal": e.infoSheetOverlay ? "true" : void 0,
1635
1663
  tabindex: e.infoSheetOverlay ? -1 : void 0,
1636
- "data-active-post-id": w.value?.postId
1637
- }, [(y(), i(S(e.infoSheet.component), h(d(k.value)), null, 16))], 8, ht)])) : a("", !0)]),
1664
+ "data-active-post-id": T.value?.postId
1665
+ }, [(y(), i(S(e.infoSheet.component), h(d(M.value)), null, 16))], 8, gt)])) : a("", !0)]),
1638
1666
  _: 1
1639
- })], 10, ft));
1667
+ })], 10, pt));
1640
1668
  }
1641
- }), _t = 35, vt = 420, yt = /* @__PURE__ */ u({
1669
+ }), vt = 35, yt = 420, bt = /* @__PURE__ */ u({
1642
1670
  __name: "VibeSurface",
1643
1671
  props: {
1644
1672
  canRetryEnd: { type: Boolean },
@@ -1656,96 +1684,97 @@ var Oe = /* @__PURE__ */ u({
1656
1684
  "loadMore",
1657
1685
  "openReel",
1658
1686
  "reelInfoSheetChange",
1659
- "retryEnd"
1687
+ "retryEnd",
1688
+ "retryForward"
1660
1689
  ],
1661
1690
  setup(r, { expose: s, emit: c }) {
1662
- let u = r, d = c, f = C(null), m = C(null), h = C(null), b = C(null), x = C({}), S = C(!1), w = C(/* @__PURE__ */ new Set()), T = C(/* @__PURE__ */ new Map()), E = C(/* @__PURE__ */ new Set()), k = C(/* @__PURE__ */ new Map()), A = C(/* @__PURE__ */ new Map()), j = C(/* @__PURE__ */ new Map()), N = C(/* @__PURE__ */ new Map()), I = n(() => F(u.state)), L = n(() => u.state.reelMediaSource === "original" ? N.value : j.value), R = new Set(u.state.items.map((e) => e.postId)), z = null, B = null, V = !1;
1663
- function H() {
1691
+ let u = r, d = c, f = C(null), m = C(null), h = C(null), b = C(null), x = C({}), S = C(!1), w = C(/* @__PURE__ */ new Set()), T = C(/* @__PURE__ */ new Map()), E = C(/* @__PURE__ */ new Set()), k = C(/* @__PURE__ */ new Map()), A = C(/* @__PURE__ */ new Map()), j = C(/* @__PURE__ */ new Map()), N = n(() => F(u.state)), I = n(() => u.state.reelMediaSource === "original" ? j.value : A.value), L = new Set(u.state.items.map((e) => e.postId)), R = null, z = null, B = !1;
1692
+ function V() {
1664
1693
  return typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1665
1694
  }
1666
- function U() {
1667
- z !== null && cancelAnimationFrame(z), z = requestAnimationFrame(() => {
1668
- z = requestAnimationFrame(() => {
1669
- z = null, w.value = /* @__PURE__ */ new Set();
1695
+ function ee() {
1696
+ R !== null && cancelAnimationFrame(R), R = requestAnimationFrame(() => {
1697
+ R = requestAnimationFrame(() => {
1698
+ R = null, w.value = /* @__PURE__ */ new Set();
1670
1699
  });
1671
1700
  });
1672
1701
  }
1673
- function W(e, t, n) {
1702
+ function H(e, t, n) {
1674
1703
  let r = P(e, t);
1675
- j.value.get(r) !== n && (j.value = new Map(j.value).set(r, n));
1704
+ A.value.get(r) !== n && (A.value = new Map(A.value).set(r, n));
1676
1705
  }
1677
- function G(e, t, n) {
1706
+ function U(e, t, n) {
1678
1707
  let r = P(e, t);
1679
- N.value.get(r) !== n && (N.value = new Map(N.value).set(r, n));
1708
+ j.value.get(r) !== n && (j.value = new Map(j.value).set(r, n));
1680
1709
  }
1681
- function te(e, t) {
1682
- W(e, t, "error");
1710
+ function W(e, t) {
1711
+ H(e, t, "error");
1683
1712
  }
1684
1713
  function ne(e, t) {
1685
- W(e, t, "ready");
1714
+ H(e, t, "ready");
1686
1715
  }
1687
- function K(e, t) {
1688
- G(e, t, "error");
1716
+ function re(e, t) {
1717
+ U(e, t, "error");
1689
1718
  }
1690
- function q(e, t) {
1691
- G(e, t, "ready");
1719
+ function ie(e, t) {
1720
+ U(e, t, "ready");
1692
1721
  }
1693
- function J(e, t) {
1722
+ function G(e, t) {
1694
1723
  if (u.state.reelMediaSource === "original") {
1695
- K(e, t);
1724
+ re(e, t);
1696
1725
  return;
1697
1726
  }
1698
- te(e, t);
1727
+ W(e, t);
1699
1728
  }
1700
- function Y(e, t) {
1729
+ function K(e, t) {
1701
1730
  if (u.state.reelMediaSource === "original") {
1702
- q(e, t);
1731
+ ie(e, t);
1703
1732
  return;
1704
1733
  }
1705
1734
  ne(e, t);
1706
1735
  }
1707
- function X(e, t) {
1736
+ function q(e, t) {
1708
1737
  let n = u.state.items.find((t) => t.postId === e);
1709
1738
  if (!n) return;
1710
1739
  let r = M(n, t);
1711
- (A.value.get(e) ?? 0) !== r && (A.value = new Map(A.value).set(e, r));
1740
+ (u.state.mediaIndices.get(e) ?? 0) !== r && (u.state.mediaIndices = new Map(u.state.mediaIndices).set(e, r));
1712
1741
  }
1713
- async function re() {
1742
+ async function J() {
1714
1743
  await p(), (u.state.layout === "reel" || u.state.reelOrigin === "masonry" ? m.value : f.value)?.loadIfNearBottom();
1715
1744
  }
1716
- function ie(e) {
1745
+ function ae(e) {
1717
1746
  return u.state.isLoading || u.state.items.length === 0 || u.state.layout !== "reel" && u.state.reelOrigin !== "masonry" ? !1 : m.value?.changeActiveMedia?.(e) ?? !1;
1718
1747
  }
1719
- function ae(e) {
1748
+ function oe(e) {
1720
1749
  return u.state.isLoading || u.state.items.length === 0 || u.state.layout !== "reel" && u.state.reelOrigin !== "masonry" ? !1 : m.value?.moveActivePost?.(e) ?? !1;
1721
1750
  }
1722
- function Z() {
1751
+ function Y() {
1723
1752
  return u.state.layout !== "masonry" || u.state.reelOrigin === "masonry" ? null : f.value?.getScrollElement?.() ?? null;
1724
1753
  }
1725
- function oe(e, t) {
1726
- B = e, V = t === "keyboard", x.value = ue(e), d("openReel", e), p(() => h.value?.focus());
1754
+ function X(e, t) {
1755
+ z = e, B = t === "keyboard", x.value = le(e), d("openReel", e), p(() => h.value?.focus());
1727
1756
  }
1728
- function se(e) {
1757
+ function Z(e) {
1729
1758
  let t = b.value?.querySelectorAll(".masonry-feed [data-post-id]") ?? [];
1730
1759
  return Array.from(t).find((t) => t.dataset.postId === String(e)) ?? null;
1731
1760
  }
1732
- function ce(e) {
1733
- if (u.state.layout !== "masonry" || u.state.reelOrigin !== null || H()) return 0;
1734
- let t = [...new Set(e)], n = t.filter(se);
1761
+ function se(e) {
1762
+ if (u.state.layout !== "masonry" || u.state.reelOrigin !== null || V()) return 0;
1763
+ let t = [...new Set(e)], n = t.filter(Z);
1735
1764
  if (n.length === 0) return 0;
1736
1765
  let r = new Map(k.value);
1737
1766
  return n.forEach((e, t) => {
1738
- r.set(e, t * _t);
1739
- }), w.value = new Set([...w.value].filter((e) => !n.includes(e))), E.value = new Set([...E.value, ...t]), k.value = r, vt + (n.length - 1) * _t;
1767
+ r.set(e, t * vt);
1768
+ }), w.value = new Set([...w.value].filter((e) => !n.includes(e))), E.value = new Set([...E.value, ...t]), k.value = r, yt + (n.length - 1) * vt;
1740
1769
  }
1741
- function le(e, t) {
1742
- let n = se(e), r = n?.querySelector(".media-card-activator") ?? n;
1770
+ function ce(e, t) {
1771
+ let n = Z(e), r = n?.querySelector(".media-card-activator") ?? n;
1743
1772
  r && (r.classList.toggle("media-card-focus-silent", !t), t || r.addEventListener("blur", () => {
1744
1773
  r.classList.remove("media-card-focus-silent");
1745
1774
  }, { once: !0 }), r?.focus({ preventScroll: !0 }));
1746
1775
  }
1747
- function ue(e) {
1748
- let t = b.value, n = se(e);
1776
+ function le(e) {
1777
+ let t = b.value, n = Z(e);
1749
1778
  if (t === null || n === null) return {};
1750
1779
  let r = t.getBoundingClientRect(), i = n.getBoundingClientRect();
1751
1780
  return {
@@ -1755,19 +1784,19 @@ var Oe = /* @__PURE__ */ u({
1755
1784
  "--vibe-reel-origin-left": `${Math.max(0, i.left - r.left)}px`
1756
1785
  };
1757
1786
  }
1758
- function de() {
1759
- u.state.reelOrigin === "masonry" && (B ??= u.state.activeReelPostId, S.value = !0, d("closeReel"));
1787
+ function ue() {
1788
+ u.state.reelOrigin === "masonry" && (z ??= u.state.activeReelPostId, S.value = !0, d("closeReel"));
1760
1789
  }
1761
- function fe() {
1762
- let e = B, t = V;
1763
- S.value = !1, B = null, V = !1, x.value = {}, p(() => {
1764
- e !== null && le(e, t);
1790
+ function de() {
1791
+ let e = z, t = B;
1792
+ S.value = !1, z = null, B = !1, x.value = {}, p(() => {
1793
+ e !== null && ce(e, t);
1765
1794
  });
1766
1795
  }
1767
- function pe(e) {
1796
+ function fe(e) {
1768
1797
  let t = u.state.layout === "reel" || u.state.reelOrigin === "masonry";
1769
1798
  if (e.key === "Escape" && u.state.reelOrigin === "masonry") {
1770
- e.preventDefault(), de();
1799
+ e.preventDefault(), ue();
1771
1800
  return;
1772
1801
  }
1773
1802
  if (e.key === "Escape" && t && u.state.reelInfoSheet.enabled) {
@@ -1785,42 +1814,29 @@ var Oe = /* @__PURE__ */ u({
1785
1814
  r !== 0 && m.value?.changeActiveMedia?.(r) && e.preventDefault();
1786
1815
  }
1787
1816
  return D(() => u.state.items.map((e) => e.postId), (e) => {
1788
- let t = e.filter((e) => !R.has(e)), n = new Set(e);
1789
- if (R = new Set(e), E.value = new Set([...E.value].filter((e) => n.has(e))), k.value = new Map([...k.value].filter(([e]) => n.has(e))), t.length === 0 || H()) return;
1817
+ let t = e.filter((e) => !L.has(e)), n = new Set(e);
1818
+ if (L = new Set(e), E.value = new Set([...E.value].filter((e) => n.has(e))), k.value = new Map([...k.value].filter(([e]) => n.has(e))), t.length === 0 || V()) return;
1790
1819
  let r = /* @__PURE__ */ new Map();
1791
1820
  e.forEach((e) => {
1792
1821
  let t = T.value.get(e);
1793
1822
  t !== void 0 && r.set(e, t);
1794
1823
  }), t.forEach((e, t) => {
1795
- r.set(e, t * _t);
1796
- }), T.value = r, w.value = new Set([...w.value, ...t]), U();
1797
- }, { flush: "sync" }), v(() => window.addEventListener("keydown", pe)), _(() => {
1798
- window.removeEventListener("keydown", pe), z !== null && cancelAnimationFrame(z);
1824
+ r.set(e, t * vt);
1825
+ }), T.value = r, w.value = new Set([...w.value, ...t]), ee();
1826
+ }, { flush: "sync" }), v(() => window.addEventListener("keydown", fe)), _(() => {
1827
+ window.removeEventListener("keydown", fe), R !== null && cancelAnimationFrame(R);
1799
1828
  }), s({
1800
- changeActiveReelMedia: ie,
1801
- getAutoScrollElement: Z,
1802
- loadIfNearBottom: re,
1803
- moveActiveReelPost: ae,
1804
- startItemRemoval: ce
1829
+ changeActiveReelMedia: ae,
1830
+ getAutoScrollElement: Y,
1831
+ loadIfNearBottom: J,
1832
+ moveActiveReelPost: oe,
1833
+ startItemRemoval: se
1805
1834
  }), (n, s) => (y(), o("div", {
1806
1835
  ref_key: "surfaceElement",
1807
1836
  ref: b,
1808
1837
  class: "vibe-surface"
1809
- }, [r.state.error || r.state.isLoading || r.state.items.length === 0 ? (y(), i(ee, {
1838
+ }, [r.state.layout === "reel" && (r.state.items.length > 0 || r.state.reelForward.status !== "idle") ? (y(), i(_t, {
1810
1839
  key: 0,
1811
- actions: r.feedFooterActions,
1812
- "can-retry-end": r.canRetryEnd,
1813
- "feed-footer": r.feedFooter,
1814
- state: I.value,
1815
- onLoadMore: s[0] ||= (e) => d("loadMore"),
1816
- onRetryEnd: s[1] ||= (e) => d("retryEnd")
1817
- }, null, 8, [
1818
- "actions",
1819
- "can-retry-end",
1820
- "feed-footer",
1821
- "state"
1822
- ])) : r.state.layout === "reel" ? (y(), i(gt, {
1823
- key: 1,
1824
1840
  ref_key: "reelRenderer",
1825
1841
  ref: m,
1826
1842
  "can-retry-end": r.canRetryEnd,
@@ -1829,30 +1845,34 @@ var Oe = /* @__PURE__ */ u({
1829
1845
  "card-header": r.cardHeader,
1830
1846
  "feed-footer": r.feedFooter,
1831
1847
  "feed-footer-actions": r.feedFooterActions,
1848
+ "forward-index": r.state.reelForwardIndex,
1849
+ "forward-item": r.state.reelForwardItem,
1832
1850
  "media-card": r.mediaCard,
1833
1851
  "infinite-scroll": r.state.infiniteScroll,
1834
1852
  "is-loading-more": r.state.isLoadingMore,
1835
1853
  items: r.state.items,
1836
1854
  "load-more-locked": r.state.loadMoreLocked,
1837
1855
  "media-source": r.state.reelMediaSource,
1838
- "media-indices": A.value,
1856
+ "media-indices": r.state.mediaIndices,
1839
1857
  "initial-post-id": r.state.activeReelPostId,
1840
1858
  "info-sheet": r.reelInfoSheet,
1841
1859
  "info-sheet-enabled": r.state.reelInfoSheet.enabled,
1842
1860
  "info-sheet-overlay": r.state.reelInfoSheetOverlay,
1843
1861
  "next-page-error": !!r.state.nextPageError,
1844
1862
  origin: "reel",
1845
- "preview-states": L.value,
1863
+ "preview-states": I.value,
1846
1864
  "reel-auto-advance": r.state.reelAutoAdvance,
1847
- state: I.value,
1865
+ "reel-forward": r.state.reelForward,
1866
+ state: N.value,
1848
1867
  total: r.state.total,
1849
- onActiveChange: s[2] ||= (e) => d("activeReelChange", e),
1850
- onCloseInfoSheet: s[3] ||= (e) => d("reelInfoSheetChange", !1),
1851
- onError: J,
1852
- onLoadMore: s[4] ||= (e) => d("loadMore"),
1853
- onMediaChange: X,
1854
- onReady: Y,
1855
- onRetryEnd: s[5] ||= (e) => d("retryEnd")
1868
+ onActiveChange: s[0] ||= (e) => d("activeReelChange", e),
1869
+ onCloseInfoSheet: s[1] ||= (e) => d("reelInfoSheetChange", !1),
1870
+ onError: G,
1871
+ onLoadMore: s[2] ||= (e) => d("loadMore"),
1872
+ onMediaChange: q,
1873
+ onReady: K,
1874
+ onRetryEnd: s[3] ||= (e) => d("retryEnd"),
1875
+ onRetryForward: s[4] ||= (e) => d("retryForward")
1856
1876
  }, null, 8, [
1857
1877
  "can-retry-end",
1858
1878
  "has-next",
@@ -1860,6 +1880,8 @@ var Oe = /* @__PURE__ */ u({
1860
1880
  "card-header",
1861
1881
  "feed-footer",
1862
1882
  "feed-footer-actions",
1883
+ "forward-index",
1884
+ "forward-item",
1863
1885
  "media-card",
1864
1886
  "infinite-scroll",
1865
1887
  "is-loading-more",
@@ -1874,8 +1896,22 @@ var Oe = /* @__PURE__ */ u({
1874
1896
  "next-page-error",
1875
1897
  "preview-states",
1876
1898
  "reel-auto-advance",
1899
+ "reel-forward",
1877
1900
  "state",
1878
1901
  "total"
1902
+ ])) : r.state.error || r.state.isLoading || r.state.items.length === 0 && r.state.reelForward.status === "idle" ? (y(), i(te, {
1903
+ key: 1,
1904
+ actions: r.feedFooterActions,
1905
+ "can-retry-end": r.canRetryEnd,
1906
+ "feed-footer": r.feedFooter,
1907
+ state: N.value,
1908
+ onLoadMore: s[5] ||= (e) => d("loadMore"),
1909
+ onRetryEnd: s[6] ||= (e) => d("retryEnd")
1910
+ }, null, 8, [
1911
+ "actions",
1912
+ "can-retry-end",
1913
+ "feed-footer",
1914
+ "state"
1879
1915
  ])) : (y(), o(e, { key: 2 }, [l(ot, {
1880
1916
  ref_key: "masonryRenderer",
1881
1917
  ref: f,
@@ -1894,18 +1930,18 @@ var Oe = /* @__PURE__ */ u({
1894
1930
  "is-loading-more": r.state.isLoadingMore,
1895
1931
  items: r.state.items,
1896
1932
  "load-more-locked": r.state.loadMoreLocked,
1897
- "media-indices": A.value,
1933
+ "media-indices": r.state.mediaIndices,
1898
1934
  "next-page-error": !!r.state.nextPageError,
1899
- "preview-states": j.value,
1935
+ "preview-states": A.value,
1900
1936
  suspended: r.state.reelOrigin === "masonry" || S.value,
1901
- state: I.value,
1937
+ state: N.value,
1902
1938
  total: r.state.total,
1903
- onActivate: oe,
1904
- onError: te,
1905
- onLoadMore: s[6] ||= (e) => d("loadMore"),
1906
- onMediaChange: X,
1939
+ onActivate: X,
1940
+ onError: W,
1941
+ onLoadMore: s[7] ||= (e) => d("loadMore"),
1942
+ onMediaChange: q,
1907
1943
  onReady: ne,
1908
- onRetryEnd: s[7] ||= (e) => d("retryEnd")
1944
+ onRetryEnd: s[8] ||= (e) => d("retryEnd")
1909
1945
  }, null, 8, [
1910
1946
  "can-retry-end",
1911
1947
  "entering-post-ids",
@@ -1930,7 +1966,7 @@ var Oe = /* @__PURE__ */ u({
1930
1966
  "total"
1931
1967
  ]), l(t, {
1932
1968
  name: "vibe-reel-viewer",
1933
- onAfterLeave: fe
1969
+ onAfterLeave: de
1934
1970
  }, {
1935
1971
  default: O(() => [r.state.reelOrigin === "masonry" ? (y(), o("section", {
1936
1972
  key: 0,
@@ -1942,7 +1978,7 @@ var Oe = /* @__PURE__ */ u({
1942
1978
  "aria-modal": "true",
1943
1979
  tabindex: "-1",
1944
1980
  style: g(x.value)
1945
- }, [l(gt, {
1981
+ }, [l(_t, {
1946
1982
  ref_key: "reelRenderer",
1947
1983
  ref: m,
1948
1984
  "can-retry-end": r.canRetryEnd,
@@ -1950,6 +1986,8 @@ var Oe = /* @__PURE__ */ u({
1950
1986
  "card-header": r.cardHeader,
1951
1987
  "feed-footer": r.feedFooter,
1952
1988
  "feed-footer-actions": r.feedFooterActions,
1989
+ "forward-index": r.state.reelForwardIndex,
1990
+ "forward-item": r.state.reelForwardItem,
1953
1991
  "media-card": r.mediaCard,
1954
1992
  "has-next": r.state.next !== null,
1955
1993
  "infinite-scroll": r.state.infiniteScroll,
@@ -1960,27 +1998,31 @@ var Oe = /* @__PURE__ */ u({
1960
1998
  "is-loading-more": r.state.isLoadingMore,
1961
1999
  items: r.state.items,
1962
2000
  "load-more-locked": r.state.loadMoreLocked,
1963
- "media-indices": A.value,
2001
+ "media-indices": r.state.mediaIndices,
1964
2002
  "media-source": "original",
1965
2003
  "next-page-error": !!r.state.nextPageError,
1966
2004
  origin: "masonry",
1967
- "preview-states": N.value,
2005
+ "preview-states": j.value,
1968
2006
  "reel-auto-advance": r.state.reelAutoAdvance,
1969
- state: I.value,
2007
+ "reel-forward": r.state.reelForward,
2008
+ state: N.value,
1970
2009
  total: r.state.total,
1971
- onActiveChange: s[8] ||= (e) => d("activeReelChange", e),
1972
- onCloseInfoSheet: s[9] ||= (e) => d("reelInfoSheetChange", !1),
1973
- onError: K,
1974
- onLoadMore: s[10] ||= (e) => d("loadMore"),
1975
- onMediaChange: X,
1976
- onReady: q,
1977
- onRetryEnd: s[11] ||= (e) => d("retryEnd")
2010
+ onActiveChange: s[9] ||= (e) => d("activeReelChange", e),
2011
+ onCloseInfoSheet: s[10] ||= (e) => d("reelInfoSheetChange", !1),
2012
+ onError: re,
2013
+ onLoadMore: s[11] ||= (e) => d("loadMore"),
2014
+ onMediaChange: q,
2015
+ onReady: ie,
2016
+ onRetryEnd: s[12] ||= (e) => d("retryEnd"),
2017
+ onRetryForward: s[13] ||= (e) => d("retryForward")
1978
2018
  }, null, 8, [
1979
2019
  "can-retry-end",
1980
2020
  "card-footer",
1981
2021
  "card-header",
1982
2022
  "feed-footer",
1983
2023
  "feed-footer-actions",
2024
+ "forward-index",
2025
+ "forward-item",
1984
2026
  "media-card",
1985
2027
  "has-next",
1986
2028
  "infinite-scroll",
@@ -1995,6 +2037,7 @@ var Oe = /* @__PURE__ */ u({
1995
2037
  "next-page-error",
1996
2038
  "preview-states",
1997
2039
  "reel-auto-advance",
2040
+ "reel-forward",
1998
2041
  "state",
1999
2042
  "total"
2000
2043
  ])], 4)) : a("", !0)]),
@@ -2004,7 +2047,7 @@ var Oe = /* @__PURE__ */ u({
2004
2047
  });
2005
2048
  //#endregion
2006
2049
  //#region src/core/page.ts
2007
- function bt(e) {
2050
+ function xt(e) {
2008
2051
  if (!e || typeof e != "object" || !Array.isArray(e.items)) throw TypeError("Vibe loadPage must resolve to a page with an items array.");
2009
2052
  if (e.next !== null && typeof e.next != "string" && typeof e.next != "number") throw TypeError("Vibe page next must be a string, number, or null.");
2010
2053
  if (e.total !== void 0 && (!Number.isFinite(e.total) || e.total < 0)) throw TypeError("Vibe page total must be a non-negative number when provided.");
@@ -2016,32 +2059,32 @@ function Q(e, t) {
2016
2059
  }
2017
2060
  //#endregion
2018
2061
  //#region src/core/requestDelay.ts
2019
- var xt = 2e3, St = 1e4, Ct = 250, wt = {
2062
+ var St = 2e3, Ct = 1e4, wt = 250, Tt = {
2020
2063
  delayRemainingMs: null,
2021
2064
  nextRequestAt: null
2022
2065
  };
2023
- function Tt(e, t) {
2066
+ function Et(e, t) {
2024
2067
  return e === void 0 ? t : Math.floor(e);
2025
2068
  }
2026
- function Et(e, t) {
2069
+ function Dt(e, t) {
2027
2070
  for (let [n, r] of [["delayStepMs", e.delayStepMs], ["delayMaxMs", e.delayMaxMs]]) if (r !== void 0 && (!Number.isFinite(r) || r < 0)) throw TypeError(`Vibe ${t} ${n} must be a non-negative number.`);
2028
2071
  }
2029
- function Dt(e, t = {}) {
2030
- let n = Tt(t.delayStepMs, xt), r = Tt(t.delayMaxMs, St);
2072
+ function Ot(e, t = {}) {
2073
+ let n = Et(t.delayStepMs, St), r = Et(t.delayMaxMs, Ct);
2031
2074
  return Math.min(Math.max(0, e) * n, r);
2032
2075
  }
2033
2076
  function $(e) {
2034
- if (e == null || !Number.isFinite(e)) return { ...wt };
2077
+ if (e == null || !Number.isFinite(e)) return { ...Tt };
2035
2078
  let t = Math.max(0, Math.floor(e - Date.now()));
2036
2079
  return t > 0 ? {
2037
2080
  delayRemainingMs: t,
2038
2081
  nextRequestAt: e
2039
- } : { ...wt };
2082
+ } : { ...Tt };
2040
2083
  }
2041
- async function Ot({ delayMs: e, onChange: t, signal: n }) {
2084
+ async function kt({ delayMs: e, onChange: t, signal: n }) {
2042
2085
  if (n.aborted) throw new DOMException("Aborted", "AbortError");
2043
2086
  if (e <= 0) {
2044
- t({ ...wt });
2087
+ t({ ...Tt });
2045
2088
  return;
2046
2089
  }
2047
2090
  let r = Date.now() + e;
@@ -2049,9 +2092,9 @@ async function Ot({ delayMs: e, onChange: t, signal: n }) {
2049
2092
  delayRemainingMs: e,
2050
2093
  nextRequestAt: r
2051
2094
  }), await new Promise((i, a) => {
2052
- let o = !1, s = setInterval(f, Ct), c = setTimeout(() => u(), e);
2095
+ let o = !1, s = setInterval(f, wt), c = setTimeout(() => u(), e);
2053
2096
  function l() {
2054
- clearInterval(s), clearTimeout(c), n.removeEventListener("abort", d), t({ ...wt });
2097
+ clearInterval(s), clearTimeout(c), n.removeEventListener("abort", d), t({ ...Tt });
2055
2098
  }
2056
2099
  function u(e) {
2057
2100
  o || (o = !0, l(), e ? a(e) : i());
@@ -2066,13 +2109,13 @@ async function Ot({ delayMs: e, onChange: t, signal: n }) {
2066
2109
  n.addEventListener("abort", d, { once: !0 });
2067
2110
  });
2068
2111
  }
2069
- var kt = class {
2112
+ var At = class {
2070
2113
  interval = null;
2071
2114
  constructor(e) {
2072
2115
  this.onChange = e;
2073
2116
  }
2074
2117
  clear() {
2075
- this.interval !== null && clearInterval(this.interval), this.interval = null, this.onChange({ ...wt });
2118
+ this.interval !== null && clearInterval(this.interval), this.interval = null, this.onChange({ ...Tt });
2076
2119
  }
2077
2120
  sync(e) {
2078
2121
  this.clear();
@@ -2080,22 +2123,22 @@ var kt = class {
2080
2123
  this.onChange(t), t.delayRemainingMs !== null && (this.interval = setInterval(() => {
2081
2124
  let t = $(e);
2082
2125
  this.onChange(t), t.delayRemainingMs === null && this.clear();
2083
- }, Ct));
2126
+ }, wt));
2084
2127
  }
2085
2128
  };
2086
- function At(e, t = !0) {
2129
+ function jt(e, t = !0) {
2087
2130
  return e.maxAdditionalPages === "unlimited" ? Infinity : (e.maxAdditionalPages ?? 10) + (t ? 1 : 0);
2088
2131
  }
2089
- function jt(e) {
2132
+ function Mt(e) {
2090
2133
  return `${typeof e}:${String(e)}`;
2091
2134
  }
2092
- function Mt(e, t) {
2135
+ function Nt(e, t) {
2093
2136
  if (!Number.isInteger(e) || e <= 0) throw TypeError(`Vibe ${t} must be a positive integer.`);
2094
2137
  }
2095
- function Nt(e) {
2138
+ function Pt(e) {
2096
2139
  if (!e) return;
2097
- if (Mt(e.pageSize, "autofill pageSize"), e.strategy === "frontend") {
2098
- Et(e, "frontend autofill");
2140
+ if (Nt(e.pageSize, "autofill pageSize"), e.strategy === "frontend") {
2141
+ Dt(e, "frontend autofill");
2099
2142
  let t = e.maxAdditionalPages;
2100
2143
  if (t !== void 0 && t !== "unlimited" && (!Number.isInteger(t) || t < 0)) throw TypeError("Vibe autofill maxAdditionalPages must be a non-negative integer or \"unlimited\".");
2101
2144
  return;
@@ -2107,7 +2150,7 @@ function Nt(e) {
2107
2150
  if (t.pageSize !== e.pageSize) throw TypeError("Vibe backend autofill initialSession pageSize must match autofill pageSize.");
2108
2151
  }
2109
2152
  }
2110
- function Pt(e, t, n = !0) {
2153
+ function Ft(e, t, n = !0) {
2111
2154
  if (!e) return {
2112
2155
  cycleId: null,
2113
2156
  delayRemainingMs: null,
@@ -2141,7 +2184,7 @@ function Pt(e, t, n = !0) {
2141
2184
  strategy: e.strategy
2142
2185
  };
2143
2186
  }
2144
- function Ft(e) {
2187
+ function It(e) {
2145
2188
  return [
2146
2189
  "cancelling",
2147
2190
  "filling",
@@ -2149,9 +2192,9 @@ function Ft(e) {
2149
2192
  "waiting"
2150
2193
  ].includes(e.status);
2151
2194
  }
2152
- async function It(e, t, n) {
2195
+ async function Lt(e, t, n) {
2153
2196
  let r = t.autofill;
2154
- if (!Ft(r) || !r.cycleId) return;
2197
+ if (!It(r) || !r.cycleId) return;
2155
2198
  let i = {
2156
2199
  cycleId: r.cycleId,
2157
2200
  feedKey: r.feedKey ?? "",
@@ -2164,20 +2207,20 @@ async function It(e, t, n) {
2164
2207
  throw r.error = e, r.status = "error", e;
2165
2208
  }
2166
2209
  }
2167
- function Lt(e, t, n) {
2210
+ function Rt(e, t, n) {
2168
2211
  return e?.strategy === "backend" && t.feedKey === e.feedKey && t.sessionId === n.sessionId;
2169
2212
  }
2170
- async function Rt({ existingItems: e, initialCursor: t, loadPage: n, maximumRequests: r, onDelayChange: i, onProgress: a, options: o, receivedOffset: s = 0, requestOffset: c = 0, signal: l }) {
2171
- let u = [], d = [...e], f = /* @__PURE__ */ new Set(), p = r ?? At(o), m = t, h = t, g = 0, _;
2213
+ async function zt({ existingItems: e, initialCursor: t, loadPage: n, maximumRequests: r, onDelayChange: i, onProgress: a, options: o, receivedOffset: s = 0, requestOffset: c = 0, signal: l }) {
2214
+ let u = [], d = [...e], f = /* @__PURE__ */ new Set(), p = r ?? jt(o), m = t, h = t, g = 0, _;
2172
2215
  for (; g < p;) {
2173
- let e = jt(m);
2216
+ let e = Mt(m);
2174
2217
  if (f.has(e)) throw Error("Vibe autofill received a repeated cursor.");
2175
- f.add(e), await Ot({
2176
- delayMs: Dt(c + g, o),
2218
+ f.add(e), await kt({
2219
+ delayMs: Ot(c + g, o),
2177
2220
  onChange: i,
2178
2221
  signal: l
2179
2222
  });
2180
- let t = bt(await n({
2223
+ let t = xt(await n({
2181
2224
  cursor: m,
2182
2225
  signal: l
2183
2226
  }));
@@ -2217,30 +2260,30 @@ async function Rt({ existingItems: e, initialCursor: t, loadPage: n, maximumRequ
2217
2260
  total: _
2218
2261
  };
2219
2262
  }
2220
- var zt = 100;
2221
- function Bt(e, t) {
2263
+ var Bt = 100;
2264
+ function Vt(e, t) {
2222
2265
  if (!Number.isFinite(t) || t <= 0) throw TypeError(`Vibe ${e} must be a positive number.`);
2223
2266
  }
2224
- function Vt(e, t, n) {
2267
+ function Ht(e, t, n) {
2225
2268
  return Math.min(n, Math.max(t, e));
2226
2269
  }
2227
- function Ht(e) {
2270
+ function Ut(e) {
2228
2271
  if (!e) return;
2229
2272
  let t = e.minSpeedPxPerSecond ?? 20, n = e.maxSpeedPxPerSecond ?? 240;
2230
- if (Bt("autoScroll.minSpeedPxPerSecond", t), Bt("autoScroll.maxSpeedPxPerSecond", n), t > n) throw TypeError("Vibe autoScroll.minSpeedPxPerSecond cannot exceed maxSpeedPxPerSecond.");
2231
- e.speedPxPerSecond !== void 0 && Bt("autoScroll.speedPxPerSecond", e.speedPxPerSecond);
2273
+ if (Vt("autoScroll.minSpeedPxPerSecond", t), Vt("autoScroll.maxSpeedPxPerSecond", n), t > n) throw TypeError("Vibe autoScroll.minSpeedPxPerSecond cannot exceed maxSpeedPxPerSecond.");
2274
+ e.speedPxPerSecond !== void 0 && Vt("autoScroll.speedPxPerSecond", e.speedPxPerSecond);
2232
2275
  }
2233
- function Ut(e) {
2276
+ function Wt(e) {
2234
2277
  let t = e?.minSpeedPxPerSecond ?? 20, n = e?.maxSpeedPxPerSecond ?? 240;
2235
2278
  return {
2236
2279
  enabled: e?.enabled ?? !1,
2237
2280
  maxSpeedPxPerSecond: n,
2238
2281
  minSpeedPxPerSecond: t,
2239
2282
  paused: !1,
2240
- speedPxPerSecond: Vt(e?.speedPxPerSecond ?? 80, t, n)
2283
+ speedPxPerSecond: Ht(e?.speedPxPerSecond ?? 80, t, n)
2241
2284
  };
2242
2285
  }
2243
- var Wt = class {
2286
+ var Gt = class {
2244
2287
  frame = null;
2245
2288
  lastTimestamp = null;
2246
2289
  mounted = !1;
@@ -2260,9 +2303,9 @@ var Wt = class {
2260
2303
  this.options.state.enabled && (this.options.state.paused = e, this.lastTimestamp = null, e ? this.cancelFrame() : this.schedule());
2261
2304
  }
2262
2305
  setSpeed(e) {
2263
- Bt("auto-scroll speed", e);
2306
+ Vt("auto-scroll speed", e);
2264
2307
  let t = this.options.state;
2265
- t.speedPxPerSecond = Vt(e, t.minSpeedPxPerSecond, t.maxSpeedPxPerSecond);
2308
+ t.speedPxPerSecond = Ht(e, t.minSpeedPxPerSecond, t.maxSpeedPxPerSecond);
2266
2309
  }
2267
2310
  tick = (e) => {
2268
2311
  this.frame = null;
@@ -2274,7 +2317,7 @@ var Wt = class {
2274
2317
  return;
2275
2318
  }
2276
2319
  if (this.lastTimestamp !== null) {
2277
- let r = Math.min(zt, Math.max(0, e - this.lastTimestamp)), i = Math.max(0, n.scrollHeight - n.clientHeight);
2320
+ let r = Math.min(Bt, Math.max(0, e - this.lastTimestamp)), i = Math.max(0, n.scrollHeight - n.clientHeight);
2278
2321
  n.scrollTop = Math.min(i, n.scrollTop + t.speedPxPerSecond * r / 1e3);
2279
2322
  }
2280
2323
  this.lastTimestamp = e, this.schedule();
@@ -2288,7 +2331,7 @@ var Wt = class {
2288
2331
  };
2289
2332
  //#endregion
2290
2333
  //#region src/core/backendAutofill.ts
2291
- async function Gt(e, t, n, r) {
2334
+ async function Kt(e, t, n, r) {
2292
2335
  let i = await e.onUnderfilled(n);
2293
2336
  if (!r()) return;
2294
2337
  if (!i.sessionId.trim()) throw TypeError("Vibe backend autofill requires a sessionId.");
@@ -2302,19 +2345,19 @@ async function Gt(e, t, n, r) {
2302
2345
  status: "waiting"
2303
2346
  });
2304
2347
  }
2305
- function Kt(e, t) {
2348
+ function qt(e, t) {
2306
2349
  ["complete", "exhausted"].includes(t.status) && t.items && (e.items = Q(e.items, t.items)), t.next !== void 0 && (e.next = t.next), t.total !== void 0 && (e.total = t.total);
2307
2350
  }
2308
- function qt(e, t, n) {
2351
+ function Jt(e, t, n) {
2309
2352
  let r = t.autofill;
2310
- return !Lt(e, n, r) || n.sequence <= r.sequence || ["cancelled", "cancelling"].includes(r.status) || ["complete", "exhausted"].includes(n.status) && n.next === void 0 ? !1 : (Kt(t, n), Object.assign(r, $(n.status === "waiting" ? n.nextRequestAt : null)), r.error = n.error ?? null, r.missing = Math.max(0, (r.pageSize ?? 0) - n.received), r.received = n.received, n.requests !== void 0 && (r.requests = n.requests), r.sequence = n.sequence, r.status = n.status, !0);
2353
+ return !Rt(e, n, r) || n.sequence <= r.sequence || ["cancelled", "cancelling"].includes(r.status) || ["complete", "exhausted"].includes(n.status) && n.next === void 0 ? !1 : (qt(t, n), Object.assign(r, $(n.status === "waiting" ? n.nextRequestAt : null)), r.error = n.error ?? null, r.missing = Math.max(0, (r.pageSize ?? 0) - n.received), r.received = n.received, n.requests !== void 0 && (r.requests = n.requests), r.sequence = n.sequence, r.status = n.status, !0);
2311
2354
  }
2312
- function Jt(e, t, n) {
2313
- return e?.strategy !== "backend" || n.feedKey !== e.feedKey || n.pageSize !== e.pageSize ? !1 : (t.autofill = Pt(e, n), Kt(t, n), !0);
2355
+ function Yt(e, t, n) {
2356
+ return e?.strategy !== "backend" || n.feedKey !== e.feedKey || n.pageSize !== e.pageSize ? !1 : (t.autofill = Ft(e, n), qt(t, n), !0);
2314
2357
  }
2315
2358
  //#endregion
2316
2359
  //#region src/core/initialAutofill.ts
2317
- async function Yt({ cycleId: e, isCurrent: t, onLastCursor: n, options: r, signal: i, state: a }) {
2360
+ async function Xt({ cycleId: e, isCurrent: t, onLastCursor: n, options: r, signal: i, state: a }) {
2318
2361
  let o = r.autofill;
2319
2362
  if (!o) return;
2320
2363
  let s = a.items.length;
@@ -2327,7 +2370,7 @@ async function Yt({ cycleId: e, isCurrent: t, onLastCursor: n, options: r, signa
2327
2370
  return;
2328
2371
  }
2329
2372
  if (o.strategy === "backend") {
2330
- await Gt(o, a, {
2373
+ await Kt(o, a, {
2331
2374
  cycleId: e,
2332
2375
  feedKey: o.feedKey,
2333
2376
  items: [...a.items],
@@ -2344,11 +2387,11 @@ async function Yt({ cycleId: e, isCurrent: t, onLastCursor: n, options: r, signa
2344
2387
  a.autofill.status = "exhausted";
2345
2388
  return;
2346
2389
  }
2347
- let c = await Rt({
2390
+ let c = await zt({
2348
2391
  existingItems: a.items,
2349
2392
  initialCursor: a.next,
2350
2393
  loadPage: r.loadPage,
2351
- maximumRequests: At(o, !1),
2394
+ maximumRequests: jt(o, !1),
2352
2395
  onDelayChange: (e) => {
2353
2396
  t() && Object.assign(a.autofill, e);
2354
2397
  },
@@ -2368,14 +2411,163 @@ async function Yt({ cycleId: e, isCurrent: t, onLastCursor: n, options: r, signa
2368
2411
  }));
2369
2412
  }
2370
2413
  //#endregion
2414
+ //#region src/core/activeItemRemoval.ts
2415
+ function Zt(e, t, n, r, i) {
2416
+ let a = new Set(n.map(({ item: e }) => e.postId));
2417
+ if (e.activeReelPostId === null || !a.has(e.activeReelPostId)) return;
2418
+ if (e.reelOrigin === "masonry") {
2419
+ i();
2420
+ return;
2421
+ }
2422
+ let o = e.items[Math.min(Math.max(r, 0), e.items.length - 1)];
2423
+ e.activeReelPostId = o?.postId ?? null, o ? t.syncReel(o.postId) : t.syncFeed();
2424
+ }
2425
+ //#endregion
2426
+ //#region src/core/exactMediaRemovalController.ts
2427
+ function Qt(e, t) {
2428
+ let [n, ...r] = t;
2429
+ if (!n) throw Error("Vibe items must contain at least one media asset.");
2430
+ return {
2431
+ ...e,
2432
+ ...n,
2433
+ items: r
2434
+ };
2435
+ }
2436
+ function $t(e) {
2437
+ if (!Number.isInteger(e.mediaIndex) || e.mediaIndex < 0) throw TypeError("Vibe mediaIndex must be a non-negative integer.");
2438
+ }
2439
+ var en = class {
2440
+ forward = null;
2441
+ forwardPromise = null;
2442
+ forwardVersion = 0;
2443
+ generation = 0;
2444
+ metadata = /* @__PURE__ */ new WeakMap();
2445
+ state;
2446
+ constructor(e) {
2447
+ this.options = e, this.state = e.state;
2448
+ }
2449
+ remove(e) {
2450
+ $t(e);
2451
+ let t = this.state.items.findIndex(({ postId: t }) => t === e.postId), n = this.state.items[t];
2452
+ if (!n) return null;
2453
+ let r = [...j(n)], i = r[e.mediaIndex];
2454
+ if (!i) return null;
2455
+ let a = Object.freeze({
2456
+ media: i,
2457
+ mediaIndex: e.mediaIndex,
2458
+ postId: e.postId,
2459
+ postIndex: t
2460
+ });
2461
+ this.metadata.set(a, {
2462
+ generation: this.generation,
2463
+ originalItem: n,
2464
+ restored: !1
2465
+ });
2466
+ let o = this.state.mediaIndices.get(n.postId) ?? 0, s = this.isReelOpen() && this.state.activeReelPostId === n.postId, c = s && o === e.mediaIndex;
2467
+ return r.splice(e.mediaIndex, 1), r.length > 0 ? (this.state.items[t] = Qt(n, r), this.updateMediaIndexAfterRemoval(n.postId, e.mediaIndex, c), a) : (this.state.items.splice(t, 1), this.state.mediaIndices.delete(n.postId), s && this.advanceFromRemovedPost(a, n), a);
2468
+ }
2469
+ reset() {
2470
+ this.generation += 1, this.forwardVersion += 1, this.forward = null, this.forwardPromise = null, this.clearForwardState();
2471
+ }
2472
+ restore(e) {
2473
+ let t = this.metadata.get(e);
2474
+ if (!t) throw TypeError("Vibe media removal does not belong to this instance.");
2475
+ if (t.generation !== this.generation || t.restored) return !1;
2476
+ t.restored = !0;
2477
+ let n = this.state.items.findIndex(({ postId: t }) => t === e.postId);
2478
+ return n >= 0 ? this.restoreIntoPost(n, e) : this.state.items.splice(Math.min(e.postIndex, this.state.items.length), 0, t.originalItem), this.forward?.removal === e && this.state.reelForward.status !== "idle" && (this.forwardVersion += 1, this.forward = null, this.clearForwardState(), this.state.mediaIndices.set(e.postId, e.mediaIndex), this.options.onActivate(e.postId)), !0;
2479
+ }
2480
+ retryForward() {
2481
+ return !this.forward || this.state.reelForward.status === "idle" ? Promise.resolve() : (this.state.nextPageError = null, this.state.reelForward = {
2482
+ error: null,
2483
+ status: "loading"
2484
+ }, this.startForwardRequest(this.state.next === null));
2485
+ }
2486
+ advanceFromRemovedPost(e, t) {
2487
+ let n = this.state.items[e.postIndex];
2488
+ if (n) {
2489
+ this.options.onActivate(n.postId);
2490
+ return;
2491
+ }
2492
+ this.forward = {
2493
+ postIndex: e.postIndex,
2494
+ removal: e,
2495
+ version: ++this.forwardVersion
2496
+ }, this.state.reelForward = {
2497
+ error: null,
2498
+ status: "loading"
2499
+ }, this.state.reelForwardIndex = e.postIndex, this.state.reelForwardItem = t, this.startForwardRequest(!1);
2500
+ }
2501
+ clearForwardState() {
2502
+ this.state.reelForward = {
2503
+ error: null,
2504
+ status: "idle"
2505
+ }, this.state.reelForwardIndex = null, this.state.reelForwardItem = null;
2506
+ }
2507
+ isReelOpen() {
2508
+ return this.state.layout === "reel" || this.state.reelOrigin === "masonry";
2509
+ }
2510
+ restoreIntoPost(e, t) {
2511
+ let n = this.state.items[e], r = [...j(n)], i = Math.min(t.mediaIndex, r.length);
2512
+ if (r.splice(i, 0, t.media), this.state.items[e] = Qt(n, r), this.state.activeReelPostId !== t.postId) return;
2513
+ let a = this.state.mediaIndices.get(t.postId) ?? 0;
2514
+ a >= i && this.state.mediaIndices.set(t.postId, a + 1);
2515
+ }
2516
+ startForwardRequest(e) {
2517
+ if (this.forwardPromise) return this.forwardPromise;
2518
+ let t = this.loadForward(e);
2519
+ return this.forwardPromise = t, t.finally(() => {
2520
+ this.forwardPromise === t && (this.forwardPromise = null, this.forward && this.state.reelForward.status === "loading" && this.startForwardRequest(!1));
2521
+ });
2522
+ }
2523
+ async loadForward(e) {
2524
+ let t = this.forward;
2525
+ if (t) for (e && await this.options.retryEnd(); this.forward === t && t.version === this.forwardVersion;) {
2526
+ let e = this.state.items[t.postIndex];
2527
+ if (e) {
2528
+ this.forward = null, this.clearForwardState(), this.options.onActivate(e.postId);
2529
+ return;
2530
+ }
2531
+ if (this.state.nextPageError) {
2532
+ this.state.reelForward = {
2533
+ error: this.state.nextPageError,
2534
+ status: "error"
2535
+ };
2536
+ return;
2537
+ }
2538
+ if (this.state.next === null) {
2539
+ this.state.reelForward = {
2540
+ error: null,
2541
+ status: "end"
2542
+ };
2543
+ return;
2544
+ }
2545
+ let n = this.state.next;
2546
+ if (await this.options.loadNext(), this.state.next === n && !this.state.nextPageError && !this.state.items[t.postIndex]) {
2547
+ this.state.reelForward = {
2548
+ error: /* @__PURE__ */ Error("Vibe could not advance while page loading is unavailable."),
2549
+ status: "error"
2550
+ };
2551
+ return;
2552
+ }
2553
+ }
2554
+ }
2555
+ updateMediaIndexAfterRemoval(e, t, n) {
2556
+ let r = this.state.items.find((t) => t.postId === e);
2557
+ if (!r) return;
2558
+ let i = j(r).length, a = this.state.mediaIndices.get(e) ?? 0, o = a;
2559
+ n ? o = t < i ? t : 0 : t < a && (o = a - 1), this.state.mediaIndices.set(e, Math.min(o, i - 1));
2560
+ }
2561
+ };
2562
+ //#endregion
2371
2563
  //#region src/core/fill.ts
2372
- function Xt(e) {
2564
+ function tn(e) {
2373
2565
  return "pages" in e ? { pages: e.pages } : { until: "end" };
2374
2566
  }
2375
- function Zt(e) {
2567
+ function nn(e) {
2376
2568
  return `${typeof e}:${String(e)}`;
2377
2569
  }
2378
- function Qt(e) {
2570
+ function rn(e) {
2379
2571
  if (!e || typeof e != "object") throw TypeError("Vibe fill target must be an object.");
2380
2572
  if ("pages" in e) {
2381
2573
  if (!Number.isInteger(e.pages) || e.pages <= 0) throw TypeError("Vibe fill pages must be a positive integer.");
@@ -2384,20 +2576,20 @@ function Qt(e) {
2384
2576
  if ("until" in e && e.until === "end") return { until: "end" };
2385
2577
  throw TypeError("Vibe fill target must be { pages } or { until: 'end' }.");
2386
2578
  }
2387
- function $t(e) {
2579
+ function an(e) {
2388
2580
  if (!e) return;
2389
2581
  if (e.strategy === "frontend") {
2390
- Et(e, "frontend fill");
2582
+ Dt(e, "frontend fill");
2391
2583
  return;
2392
2584
  }
2393
2585
  if (!e.feedKey.trim()) throw TypeError("Vibe backend fill requires a feedKey.");
2394
2586
  let t = e.initialSession;
2395
2587
  if (t) {
2396
2588
  if (t.feedKey !== e.feedKey) throw TypeError("Vibe backend fill initialSession feedKey must match fill feedKey.");
2397
- Qt(t.target);
2589
+ rn(t.target);
2398
2590
  }
2399
2591
  }
2400
- function en(e, t, n = !0) {
2592
+ function on(e, t, n = !0) {
2401
2593
  let r = e?.strategy === "backend" && n ? e.initialSession : void 0, i = t ?? r, a = $(i?.nextRequestAt);
2402
2594
  return {
2403
2595
  completedPages: i?.completedPages ?? 0,
@@ -2411,10 +2603,10 @@ function en(e, t, n = !0) {
2411
2603
  sessionId: i?.sessionId ?? null,
2412
2604
  status: i?.status ?? "idle",
2413
2605
  strategy: e?.strategy ?? null,
2414
- target: i ? Xt(i.target) : null
2606
+ target: i ? tn(i.target) : null
2415
2607
  };
2416
2608
  }
2417
- function tn(e) {
2609
+ function sn(e) {
2418
2610
  return [
2419
2611
  "cancelling",
2420
2612
  "filling",
@@ -2422,17 +2614,17 @@ function tn(e) {
2422
2614
  "waiting"
2423
2615
  ].includes(e.status);
2424
2616
  }
2425
- async function nn({ existingItems: e, initialCursor: t, loadPage: n, onDelayChange: r, onProgress: i, options: a, signal: o, target: s }) {
2617
+ async function cn({ existingItems: e, initialCursor: t, loadPage: n, onDelayChange: r, onProgress: i, options: a, signal: o, target: s }) {
2426
2618
  let c = [], l = [...e], u = /* @__PURE__ */ new Set(), d = 0, f = t, p = t, m = 0, h;
2427
2619
  for (; p !== null;) {
2428
- let e = Zt(f);
2620
+ let e = nn(f);
2429
2621
  if (u.has(e)) throw Error("Vibe fill received a repeated cursor.");
2430
- u.add(e), await Ot({
2431
- delayMs: Dt(d, a),
2622
+ u.add(e), await kt({
2623
+ delayMs: Ot(d, a),
2432
2624
  onChange: r,
2433
2625
  signal: o
2434
2626
  });
2435
- let t = bt(await n({
2627
+ let t = xt(await n({
2436
2628
  cursor: f,
2437
2629
  signal: o
2438
2630
  }));
@@ -2474,7 +2666,7 @@ async function nn({ existingItems: e, initialCursor: t, loadPage: n, onDelayChan
2474
2666
  }
2475
2667
  //#endregion
2476
2668
  //#region src/core/backendFill.ts
2477
- async function rn(e, t, n, r) {
2669
+ async function ln(e, t, n, r) {
2478
2670
  let i = await e.onStart(n);
2479
2671
  if (r()) {
2480
2672
  if (!i.sessionId.trim()) throw TypeError("Vibe backend fill requires a sessionId.");
@@ -2488,22 +2680,22 @@ async function rn(e, t, n, r) {
2488
2680
  });
2489
2681
  }
2490
2682
  }
2491
- function an(e, t, n) {
2683
+ function un(e, t, n) {
2492
2684
  return e?.strategy === "backend" && n.feedKey === e.feedKey && n.sessionId === t.fill.sessionId;
2493
2685
  }
2494
- function on(e) {
2686
+ function dn(e) {
2495
2687
  return Number.isInteger(e.completedPages) && e.completedPages >= 0 && Number.isInteger(e.received) && e.received >= 0 && Number.isInteger(e.sequence) && e.sequence >= 0;
2496
2688
  }
2497
- function sn(e, t) {
2689
+ function fn(e, t) {
2498
2690
  if (!["complete", "exhausted"].includes(t.status)) return !0;
2499
2691
  let n = e.fill.target;
2500
2692
  return !n || !Array.isArray(t.items) || t.next === void 0 || t.lastCursor === void 0 ? !1 : t.status === "exhausted" ? "pages" in n && t.completedPages < n.pages && t.next === null : "pages" in n ? t.completedPages === n.pages : t.next === null;
2501
2693
  }
2502
- function cn(e, t, n) {
2694
+ function pn(e, t, n) {
2503
2695
  t.total !== void 0 && (e.total = t.total), ["complete", "exhausted"].includes(t.status) && (e.items = Q(e.items, t.items ?? []), e.next = t.next ?? null, n(t.lastCursor ?? null));
2504
2696
  }
2505
- function ln(e, t, n, r) {
2506
- return !an(e, t, n) || !on(n) || n.sequence <= t.fill.sequence || ["cancelled", "cancelling"].includes(t.fill.status) || !sn(t, n) ? !1 : (cn(t, n, r), Object.assign(t.fill, {
2697
+ function mn(e, t, n, r) {
2698
+ return !un(e, t, n) || !dn(n) || n.sequence <= t.fill.sequence || ["cancelled", "cancelling"].includes(t.fill.status) || !fn(t, n) ? !1 : (pn(t, n, r), Object.assign(t.fill, {
2507
2699
  ...$(n.status === "waiting" ? n.nextRequestAt : null),
2508
2700
  completedPages: n.completedPages,
2509
2701
  error: n.error ?? null,
@@ -2512,41 +2704,41 @@ function ln(e, t, n, r) {
2512
2704
  status: n.status
2513
2705
  }), !0);
2514
2706
  }
2515
- function un(e, t, n, r) {
2707
+ function hn(e, t, n, r) {
2516
2708
  if (e?.strategy !== "backend" || n.feedKey !== e.feedKey) return !1;
2517
2709
  let i = t.fill;
2518
- return t.fill = en(e, n), !on(n) || !sn(t, n) ? (t.fill = i, !1) : (cn(t, n, r), !0);
2710
+ return t.fill = on(e, n), !dn(n) || !fn(t, n) ? (t.fill = i, !1) : (pn(t, n, r), !0);
2519
2711
  }
2520
2712
  //#endregion
2521
2713
  //#region src/core/fillController.ts
2522
- var dn = class {
2714
+ var gn = class {
2523
2715
  abortController = null;
2524
2716
  cycle = 0;
2525
2717
  delayCountdown;
2526
2718
  requestVersion = 0;
2527
2719
  constructor(e) {
2528
- this.options = e, this.delayCountdown = new kt((e) => {
2720
+ this.options = e, this.delayCountdown = new At((e) => {
2529
2721
  Object.assign(this.options.state.fill, e);
2530
2722
  }), this.syncBackendCountdown();
2531
2723
  }
2532
2724
  isActive() {
2533
- return tn(this.options.state.fill);
2725
+ return sn(this.options.state.fill);
2534
2726
  }
2535
2727
  applyUpdate(e) {
2536
- let t = ln(this.options.fill, this.options.state, e, this.options.onLastCursor);
2728
+ let t = mn(this.options.fill, this.options.state, e, this.options.onLastCursor);
2537
2729
  return t && this.syncBackendCountdown(), t;
2538
2730
  }
2539
2731
  restoreSession(e) {
2540
- let t = un(this.options.fill, this.options.state, e, this.options.onLastCursor);
2732
+ let t = hn(this.options.fill, this.options.state, e, this.options.onLastCursor);
2541
2733
  return t && this.syncBackendCountdown(), t;
2542
2734
  }
2543
2735
  async start(e) {
2544
2736
  let t = this.options.fill;
2545
2737
  if (!t) throw Error("Vibe fill is not configured.");
2546
2738
  if (this.isActive()) throw Error("Vibe fill is already active.");
2547
- let n = Qt(e), r = `vibe-fill-${Date.now().toString(36)}-${++this.cycle}`;
2739
+ let n = rn(e), r = `vibe-fill-${Date.now().toString(36)}-${++this.cycle}`;
2548
2740
  if (this.options.state.fill = {
2549
- ...en(t, void 0, !1),
2741
+ ...on(t, void 0, !1),
2550
2742
  cycleId: r,
2551
2743
  status: "filling",
2552
2744
  target: n
@@ -2557,7 +2749,7 @@ var dn = class {
2557
2749
  let i = ++this.requestVersion, a = new AbortController();
2558
2750
  this.abortController = a;
2559
2751
  try {
2560
- t.strategy === "frontend" ? await this.startFrontend(t, n, a, i) : (await rn(t, this.options.state, {
2752
+ t.strategy === "frontend" ? await this.startFrontend(t, n, a, i) : (await ln(t, this.options.state, {
2561
2753
  cycleId: r,
2562
2754
  feedKey: t.feedKey,
2563
2755
  items: [...this.options.state.items],
@@ -2575,7 +2767,7 @@ var dn = class {
2575
2767
  }
2576
2768
  async cancel() {
2577
2769
  let { fill: e, state: t } = this.options;
2578
- if (!tn(t.fill) || !t.fill.cycleId) return;
2770
+ if (!sn(t.fill) || !t.fill.cycleId) return;
2579
2771
  let n = {
2580
2772
  cycleId: t.fill.cycleId,
2581
2773
  feedKey: t.fill.feedKey ?? "",
@@ -2589,7 +2781,7 @@ var dn = class {
2589
2781
  }
2590
2782
  }
2591
2783
  reset() {
2592
- this.abortLocalRequest(), this.delayCountdown.clear(), this.options.state.fill = en(this.options.fill, void 0, !1);
2784
+ this.abortLocalRequest(), this.delayCountdown.clear(), this.options.state.fill = on(this.options.fill, void 0, !1);
2593
2785
  }
2594
2786
  destroy() {
2595
2787
  this.abortLocalRequest(), this.delayCountdown.clear();
@@ -2605,7 +2797,7 @@ var dn = class {
2605
2797
  if (!i) throw Error("Vibe frontend fill requires loadPage.");
2606
2798
  let a = this.options.state;
2607
2799
  a.isLoadingMore = !0;
2608
- let o = await nn({
2800
+ let o = await cn({
2609
2801
  existingItems: a.items,
2610
2802
  initialCursor: a.next,
2611
2803
  loadPage: i,
@@ -2632,7 +2824,7 @@ var dn = class {
2632
2824
  };
2633
2825
  //#endregion
2634
2826
  //#region src/core/feedFooter.ts
2635
- function fn(e) {
2827
+ function _n(e) {
2636
2828
  return {
2637
2829
  cancelAutofill: () => e.cancelAutofill(),
2638
2830
  loadMore: () => e.loadNext(),
@@ -2640,55 +2832,62 @@ function fn(e) {
2640
2832
  retryEnd: () => e.retryEnd()
2641
2833
  };
2642
2834
  }
2643
- function pn(e) {
2835
+ function vn(e) {
2644
2836
  if (!Number.isFinite(e) || e <= 0) throw TypeError("Vibe reelAutoAdvance.intervalMs must be a positive number.");
2645
2837
  }
2646
- function mn(e) {
2647
- e?.intervalMs !== void 0 && pn(e.intervalMs);
2838
+ function yn(e) {
2839
+ e?.intervalMs !== void 0 && vn(e.intervalMs);
2648
2840
  }
2649
- function hn(e) {
2841
+ function bn(e) {
2650
2842
  return {
2651
2843
  enabled: e?.enabled ?? !1,
2652
2844
  includePostItems: e?.includePostItems ?? !1,
2653
2845
  intervalMs: e?.intervalMs ?? 5e3
2654
2846
  };
2655
2847
  }
2656
- function gn(e, t) {
2848
+ function xn(e, t) {
2657
2849
  if (typeof t == "boolean") {
2658
2850
  e.enabled = t;
2659
2851
  return;
2660
2852
  }
2661
- mn(t), t.enabled !== void 0 && (e.enabled = t.enabled), t.includePostItems !== void 0 && (e.includePostItems = t.includePostItems), t.intervalMs !== void 0 && (e.intervalMs = t.intervalMs);
2853
+ yn(t), t.enabled !== void 0 && (e.enabled = t.enabled), t.includePostItems !== void 0 && (e.includePostItems = t.includePostItems), t.intervalMs !== void 0 && (e.intervalMs = t.intervalMs);
2662
2854
  }
2663
2855
  //#endregion
2664
2856
  //#region src/core/reelInfoSheet.ts
2665
- function _n(e) {
2857
+ function Sn(e) {
2666
2858
  return { enabled: e?.enabled ?? !1 };
2667
2859
  }
2668
- function vn(e, t, n) {
2860
+ function Cn(e, t, n) {
2669
2861
  if (n && !t) throw Error("Vibe cannot enable reelInfoSheet without a configured component.");
2670
2862
  e.enabled = n;
2671
2863
  }
2672
2864
  //#endregion
2673
2865
  //#region src/core/initialRuntimeState.ts
2674
- function yn(e, t) {
2866
+ function wn(e, t) {
2675
2867
  let n = e.initialPage;
2676
2868
  return {
2677
2869
  activeReelPostId: null,
2678
- autoScroll: Ut(e.autoScroll),
2679
- autofill: Pt(e.autofill),
2870
+ autoScroll: Wt(e.autoScroll),
2871
+ autofill: Ft(e.autofill),
2680
2872
  error: null,
2681
- fill: en(e.fill),
2873
+ fill: on(e.fill),
2682
2874
  infiniteScroll: e.infiniteScroll ?? !0,
2683
2875
  isLoading: !n,
2684
2876
  isLoadingMore: !1,
2685
2877
  items: n ? Q([], n.items) : [],
2686
2878
  layout: t === "reel" ? "reel" : "masonry",
2687
2879
  loadMoreLocked: !1,
2880
+ mediaIndices: /* @__PURE__ */ new Map(),
2688
2881
  next: n?.next ?? null,
2689
2882
  nextPageError: null,
2690
- reelAutoAdvance: hn(e.reelAutoAdvance),
2691
- reelInfoSheet: _n(e.reelInfoSheet),
2883
+ reelAutoAdvance: bn(e.reelAutoAdvance),
2884
+ reelForward: {
2885
+ error: null,
2886
+ status: "idle"
2887
+ },
2888
+ reelForwardIndex: null,
2889
+ reelForwardItem: null,
2890
+ reelInfoSheet: Sn(e.reelInfoSheet),
2692
2891
  reelInfoSheetOverlay: !1,
2693
2892
  reelMediaSource: "original",
2694
2893
  reelOrigin: null,
@@ -2697,18 +2896,18 @@ function yn(e, t) {
2697
2896
  }
2698
2897
  //#endregion
2699
2898
  //#region src/core/itemPlacement.ts
2700
- function bn(e, t) {
2899
+ function Tn(e, t) {
2701
2900
  let n = new Set(t);
2702
2901
  return e.flatMap((e, t) => n.has(e.postId) ? [{
2703
2902
  index: t,
2704
2903
  item: e
2705
2904
  }] : []);
2706
2905
  }
2707
- function xn(e, t) {
2906
+ function En(e, t) {
2708
2907
  let n = new Set(t.map(({ item: e }) => e.postId));
2709
2908
  return e.filter((e) => !n.has(e.postId));
2710
2909
  }
2711
- function Sn(e, t) {
2910
+ function Dn(e, t) {
2712
2911
  t.forEach(({ index: e }) => {
2713
2912
  if (!Number.isInteger(e) || e < 0) throw Error("Vibe item restore indexes must be non-negative integers.");
2714
2913
  });
@@ -2719,7 +2918,7 @@ function Sn(e, t) {
2719
2918
  }
2720
2919
  //#endregion
2721
2920
  //#region src/core/itemRemovalController.ts
2722
- var Cn = 20, wn = class {
2921
+ var On = 20, kn = class {
2723
2922
  generation = 0;
2724
2923
  historyLimit;
2725
2924
  metadata = /* @__PURE__ */ new WeakMap();
@@ -2728,7 +2927,7 @@ var Cn = 20, wn = class {
2728
2927
  itemOrder;
2729
2928
  stopItemsWatcher;
2730
2929
  constructor(e) {
2731
- this.options = e, this.historyLimit = e.historyLimit ?? Cn, this.state = e.state, this.itemOrder = this.state.items.map(({ postId: e }) => e), this.stopItemsWatcher = D(() => this.state.items, (e) => this.appendUnknownItems(e), { flush: "sync" });
2930
+ this.options = e, this.historyLimit = e.historyLimit ?? On, this.state = e.state, this.itemOrder = this.state.items.map(({ postId: e }) => e), this.stopItemsWatcher = D(() => this.state.items, (e) => this.appendUnknownItems(e), { flush: "sync" });
2732
2931
  }
2733
2932
  destroy() {
2734
2933
  this.reset(), this.stopItemsWatcher();
@@ -2739,7 +2938,7 @@ var Cn = 20, wn = class {
2739
2938
  let r = t.map(({ item: e }) => e.postId), i = this.options.startRemoval(r);
2740
2939
  if (i > 0 && await new Promise((e) => setTimeout(e, i)), this.metadata.get(n)?.generation !== this.generation) return n;
2741
2940
  let a = this.state.items.findIndex((e) => e.postId === this.state.activeReelPostId);
2742
- return this.state.items = xn(this.state.items, t), this.options.onItemsRemoved(t, a), this.record(n), n;
2941
+ return this.state.items = En(this.state.items, t), this.options.onItemsRemoved(t, a), this.record(n), n;
2743
2942
  }
2744
2943
  reset() {
2745
2944
  this.generation += 1, this.history = [], this.itemOrder = [];
@@ -2750,7 +2949,7 @@ var Cn = 20, wn = class {
2750
2949
  this.restoreRemoval(t);
2751
2950
  return;
2752
2951
  }
2753
- let n = Sn(this.state.items, e);
2952
+ let n = Dn(this.state.items, e);
2754
2953
  this.registerExternalPlacements(e), this.state.items = n;
2755
2954
  }
2756
2955
  restoreRemoval(e) {
@@ -2773,7 +2972,7 @@ var Cn = 20, wn = class {
2773
2972
  }
2774
2973
  collectOrderedPlacements(e) {
2775
2974
  let t = new Map(this.itemOrder.map((e, t) => [e, t]));
2776
- return bn(this.state.items, e).map((e) => ({
2975
+ return Tn(this.state.items, e).map((e) => ({
2777
2976
  index: t.get(e.item.postId) ?? e.index,
2778
2977
  item: e.item
2779
2978
  }));
@@ -2807,43 +3006,43 @@ var Cn = 20, wn = class {
2807
3006
  };
2808
3007
  //#endregion
2809
3008
  //#region src/core/options.ts
2810
- function Tn(e, t) {
3009
+ function An(e, t) {
2811
3010
  if (t) {
2812
3011
  if (!Number.isFinite(t.height) || t.height <= 0) throw TypeError(`Vibe ${e} height must be a positive number.`);
2813
3012
  if (t.background !== void 0 && t.background !== "default" && t.background !== "transparent") throw TypeError(`Vibe ${e} background must be "default" or "transparent".`);
2814
3013
  }
2815
3014
  }
2816
- function En(e, t) {
3015
+ function jn(e, t) {
2817
3016
  if (t) {
2818
3017
  if (t.background !== void 0 && t.background !== "default" && t.background !== "transparent") throw TypeError(`Vibe mediaCard ${e} background must be "default" or "transparent".`);
2819
3018
  for (let [n, r] of [["paddingX", t.paddingX], ["paddingY", t.paddingY]]) if (r !== void 0 && (!Number.isFinite(r) || r < 0)) throw TypeError(`Vibe mediaCard ${e} ${n} must be a non-negative number.`);
2820
3019
  }
2821
3020
  }
2822
- function Dn(e) {
2823
- if (Ht(e.autoScroll), Tn("cardHeader", e.cardHeader), Tn("cardFooter", e.cardFooter), En("header", e.mediaCard?.header), En("footer", e.mediaCard?.footer), Nt(e.autofill), $t(e.fill), mn(e.reelAutoAdvance), e.removalHistoryLimit !== void 0 && (!Number.isInteger(e.removalHistoryLimit) || e.removalHistoryLimit < 0)) throw TypeError("Vibe removalHistoryLimit must be a non-negative integer.");
3021
+ function Mn(e) {
3022
+ if (Ut(e.autoScroll), An("cardHeader", e.cardHeader), An("cardFooter", e.cardFooter), jn("header", e.mediaCard?.header), jn("footer", e.mediaCard?.footer), Pt(e.autofill), an(e.fill), yn(e.reelAutoAdvance), e.removalHistoryLimit !== void 0 && (!Number.isInteger(e.removalHistoryLimit) || e.removalHistoryLimit < 0)) throw TypeError("Vibe removalHistoryLimit must be a non-negative integer.");
2824
3023
  if (!e.initialPage && !e.loadPage) throw TypeError("Vibe requires either initialPage or loadPage.");
2825
3024
  if (e.initialPage?.next !== null && !e.loadPage) throw TypeError("Vibe requires loadPage when initialPage has a next cursor.");
2826
3025
  if (e.fill?.strategy === "frontend" && !e.loadPage) throw TypeError("Vibe frontend fill requires loadPage.");
2827
3026
  if (e.fill?.strategy === "backend" && e.fill.initialSession && !e.initialPage) throw TypeError("Vibe backend fill restoration requires initialPage.");
2828
3027
  }
2829
- function On(e) {
3028
+ function Nn(e) {
2830
3029
  if (typeof e != "string") return e;
2831
3030
  if (typeof document > "u") throw Error("Vibe cannot resolve a selector without a document.");
2832
3031
  let t = document.querySelector(e);
2833
3032
  if (!t) throw Error(`Vibe target not found: ${e}`);
2834
3033
  return t;
2835
3034
  }
2836
- var kn = 1.5;
2837
- function An(e) {
3035
+ var Pn = 1.5;
3036
+ function Fn(e) {
2838
3037
  let t = Math.min(e.screenWidth, e.screenHeight);
2839
3038
  if (t > 0 && t < 600) return !0;
2840
- let n = Math.min(e.viewportWidth, e.viewportHeight), r = t >= n * kn;
3039
+ let n = Math.min(e.viewportWidth, e.viewportHeight), r = t >= n * Pn;
2841
3040
  return !e.hasHover && n > 0 && n < 600 && r;
2842
3041
  }
2843
- function jn(e) {
2844
- return An(e) ? "reel" : "masonry";
3042
+ function In(e) {
3043
+ return Fn(e) ? "reel" : "masonry";
2845
3044
  }
2846
- function Mn(e) {
3045
+ function Ln(e) {
2847
3046
  let t = e.ownerDocument.defaultView, n = e.ownerDocument.documentElement;
2848
3047
  return {
2849
3048
  hasHover: typeof t?.matchMedia == "function" && t.matchMedia("(hover: hover)").matches,
@@ -2853,15 +3052,15 @@ function Mn(e) {
2853
3052
  viewportWidth: n.clientWidth
2854
3053
  };
2855
3054
  }
2856
- function Nn(e) {
2857
- return An(Mn(e));
3055
+ function Rn(e) {
3056
+ return Fn(Ln(e));
2858
3057
  }
2859
- function Pn(e) {
2860
- return jn(Mn(e));
3058
+ function zn(e) {
3059
+ return In(Ln(e));
2861
3060
  }
2862
3061
  //#endregion
2863
3062
  //#region src/core/responsiveLayoutController.ts
2864
- var Fn = class {
3063
+ var Bn = class {
2865
3064
  layoutMode;
2866
3065
  resizeObserver = null;
2867
3066
  target = null;
@@ -2886,10 +3085,10 @@ var Fn = class {
2886
3085
  }
2887
3086
  handleResponsiveLayout = () => {
2888
3087
  if (!this.target) return;
2889
- let e = Pn(this.target);
2890
- this.state.reelInfoSheetOverlay = Nn(this.target), this.state.reelMediaSource = e === "reel" ? "preview" : "original", this.layoutMode === "responsive" && this.applyLayout(e);
3088
+ let e = zn(this.target);
3089
+ this.state.reelInfoSheetOverlay = Rn(this.target), this.state.reelMediaSource = e === "reel" ? "preview" : "original", this.layoutMode === "responsive" && this.applyLayout(e);
2891
3090
  };
2892
- }, In = class {
3091
+ }, Vn = class {
2893
3092
  routedReelPostId = null;
2894
3093
  reelRouteIsActive = !1;
2895
3094
  constructor(e, t) {
@@ -2916,7 +3115,7 @@ var Fn = class {
2916
3115
  let i = this.reelRouteIsActive ? "replace" : "push";
2917
3116
  this.reelRouteIsActive = !0, this.routedReelPostId = e, this.options.router[i](r);
2918
3117
  }
2919
- }, Ln = class {
3118
+ }, Hn = class {
2920
3119
  app = null;
2921
3120
  autoScroll;
2922
3121
  autofillDelayCountdown;
@@ -2927,45 +3126,51 @@ var Fn = class {
2927
3126
  responsiveLayout;
2928
3127
  routing;
2929
3128
  fillController;
3129
+ exactMediaRemoval;
2930
3130
  itemRemoval;
2931
3131
  surface = null;
2932
3132
  stopStateWatcher = null;
2933
3133
  lastLoadedCursor = null;
2934
3134
  state;
2935
3135
  constructor(e) {
2936
- this.options = e, Dn(e);
3136
+ this.options = e, Mn(e);
2937
3137
  let t = e.layout ?? "masonry";
2938
- this.state = b(yn(e, t)), this.autoScroll = new Wt({
3138
+ this.state = b(wn(e, t)), this.autoScroll = new Gt({
2939
3139
  getScrollElement: () => this.surface?.getAutoScrollElement() ?? null,
2940
3140
  state: this.state.autoScroll
2941
- }), this.autofillDelayCountdown = new kt((e) => Object.assign(this.state.autofill, e)), this.syncAutofillCountdown(), this.fillController = new dn({
3141
+ }), this.autofillDelayCountdown = new At((e) => Object.assign(this.state.autofill, e)), this.syncAutofillCountdown(), this.fillController = new gn({
2942
3142
  fill: e.fill,
2943
3143
  loadPage: e.loadPage,
2944
3144
  onLastCursor: (e) => {
2945
3145
  this.lastLoadedCursor = e;
2946
3146
  },
2947
3147
  state: this.state
2948
- }), this.routing = new In(e.routing, this.state), this.itemRemoval = new wn({
3148
+ }), this.routing = new Vn(e.routing, this.state), this.exactMediaRemoval = new en({
3149
+ loadNext: () => this.loadNext(),
3150
+ onActivate: (e) => this.setActiveReelPost(e),
3151
+ retryEnd: () => this.retryEnd(),
3152
+ state: this.state
3153
+ }), this.itemRemoval = new kn({
2949
3154
  historyLimit: e.removalHistoryLimit,
2950
3155
  onItemsRemoved: (e, t) => {
2951
- this.restoreActiveItemAfterRemoval(e, t);
3156
+ Zt(this.state, this.routing, e, t, () => this.closeMasonryReel());
2952
3157
  },
2953
3158
  startRemoval: (e) => this.surface?.startItemRemoval(e) ?? 0,
2954
3159
  state: this.state
2955
- }), this.responsiveLayout = new Fn(t, this.state, () => {
3160
+ }), this.responsiveLayout = new Bn(t, this.state, () => {
2956
3161
  this.routing.syncFeed();
2957
3162
  }), this.startStateNotifications();
2958
3163
  }
2959
3164
  async mount() {
2960
3165
  if (this.app) throw Error("Vibe is already mounted.");
2961
3166
  this.startStateNotifications();
2962
- let e = On(this.options.target);
2963
- this.responsiveLayout.mount(e), this.app = r(yt, {
3167
+ let e = Nn(this.options.target);
3168
+ this.responsiveLayout.mount(e), this.app = r(bt, {
2964
3169
  canRetryEnd: !!this.options.loadPage,
2965
3170
  cardFooter: this.options.cardFooter,
2966
3171
  cardHeader: this.options.cardHeader,
2967
3172
  feedFooter: this.options.feedFooter,
2968
- feedFooterActions: fn(this),
3173
+ feedFooterActions: _n(this),
2969
3174
  mediaCard: this.options.mediaCard,
2970
3175
  reelInfoSheet: this.options.reelInfoSheet,
2971
3176
  state: this.state,
@@ -2978,24 +3183,36 @@ var Fn = class {
2978
3183
  onReelInfoSheetChange: (e) => this.setReelInfoSheet(e),
2979
3184
  onRetryEnd: () => {
2980
3185
  this.retryEnd();
3186
+ },
3187
+ onRetryForward: () => {
3188
+ this.retryReelForward();
2981
3189
  }
2982
3190
  }), this.surface = this.app.mount(e), this.autoScroll.mount(), this.options.initialPage ? this.options.autofill && this.state.autofill.status === "idle" && !this.fillController.isActive() && await this.startInitialAutofill() : await this.reload();
2983
3191
  }
2984
3192
  destroy() {
2985
- this.autoScroll.destroy(), this.fillController.destroy(), this.cancelRequest(), this.itemRemoval.destroy(), this.responsiveLayout.destroy(), this.stopStateWatcher?.(), this.stopStateWatcher = null, this.app?.unmount(), this.app = null, this.surface = null;
3193
+ this.autoScroll.destroy(), this.fillController.destroy(), this.cancelRequest(), this.exactMediaRemoval.reset(), this.itemRemoval.destroy(), this.responsiveLayout.destroy(), this.stopStateWatcher?.(), this.stopStateWatcher = null, this.app?.unmount(), this.app = null, this.surface = null;
2986
3194
  }
2987
3195
  getState() {
2988
3196
  return F(this.state);
2989
3197
  }
3198
+ removeMedia(e) {
3199
+ return this.exactMediaRemoval.remove(e);
3200
+ }
2990
3201
  removeItems(e) {
2991
3202
  return this.itemRemoval.remove(e);
2992
3203
  }
2993
3204
  restoreItems(e) {
2994
3205
  this.itemRemoval.restoreItems(e);
2995
3206
  }
3207
+ restoreMediaRemoval(e) {
3208
+ return this.exactMediaRemoval.restore(e);
3209
+ }
2996
3210
  restoreRemoval(e) {
2997
3211
  return this.itemRemoval.restoreRemoval(e);
2998
3212
  }
3213
+ retryReelForward() {
3214
+ return this.exactMediaRemoval.retryForward();
3215
+ }
2999
3216
  undoLastRemoval() {
3000
3217
  return this.itemRemoval.undoLast();
3001
3218
  }
@@ -3024,11 +3241,11 @@ var Fn = class {
3024
3241
  this.autoScroll.setSpeed(e);
3025
3242
  }
3026
3243
  applyAutofillUpdate(e) {
3027
- let t = qt(this.options.autofill, this.state, e);
3244
+ let t = Jt(this.options.autofill, this.state, e);
3028
3245
  return t && this.syncAutofillCountdown(), t;
3029
3246
  }
3030
3247
  async cancelAutofill() {
3031
- await It(this.options.autofill, this.state, () => this.cancelRequest());
3248
+ await Lt(this.options.autofill, this.state, () => this.cancelRequest());
3032
3249
  }
3033
3250
  applyFillUpdate(e) {
3034
3251
  return this.fillController.applyUpdate(e);
@@ -3037,11 +3254,11 @@ var Fn = class {
3037
3254
  return this.fillController.cancel();
3038
3255
  }
3039
3256
  async fill(e) {
3040
- if (this.pendingRequest || Ft(this.state.autofill)) throw Error("Vibe cannot fill while another page operation is active.");
3257
+ if (this.pendingRequest || It(this.state.autofill)) throw Error("Vibe cannot fill while another page operation is active.");
3041
3258
  await this.fillController.start(e);
3042
3259
  }
3043
3260
  restoreAutofillSession(e) {
3044
- let t = Jt(this.options.autofill, this.state, e);
3261
+ let t = Yt(this.options.autofill, this.state, e);
3045
3262
  return t && this.syncAutofillCountdown(), t;
3046
3263
  }
3047
3264
  restoreFillSession(e) {
@@ -3049,7 +3266,7 @@ var Fn = class {
3049
3266
  }
3050
3267
  async loadNext() {
3051
3268
  if (this.pendingRequest) return this.pendingRequest;
3052
- if (!this.state.loadMoreLocked && !(Ft(this.state.autofill) || this.fillController.isActive()) && !(this.state.next === null || !this.options.loadPage)) return this.state.isLoadingMore = !0, this.state.nextPageError = null, this.startRequest(this.state.next, !0);
3269
+ if (!this.state.loadMoreLocked && !(It(this.state.autofill) || this.fillController.isActive()) && !(this.state.next === null || !this.options.loadPage)) return this.state.isLoadingMore = !0, this.state.nextPageError = null, this.startRequest(this.state.next, !0);
3053
3270
  }
3054
3271
  async refresh() {
3055
3272
  return this.replaceFeed(this.state.next ?? this.lastLoadedCursor, "refresh");
@@ -3059,11 +3276,11 @@ var Fn = class {
3059
3276
  }
3060
3277
  async replaceFeed(e, t) {
3061
3278
  if (!this.options.loadPage) throw Error(`Vibe cannot ${t} without loadPage.`);
3062
- return Ft(this.state.autofill) && await this.cancelAutofill(), this.fillController.isActive() && await this.cancelFill(), this.cancelRequest(), this.state.autofill = Pt(this.options.autofill, void 0, !1), this.fillController.reset(), this.itemRemoval.reset(), this.state.error = null, this.state.isLoading = !0, this.state.items = [], this.state.next = null, this.state.nextPageError = null, this.state.total = null, this.startRequest(e, !1);
3279
+ return It(this.state.autofill) && await this.cancelAutofill(), this.fillController.isActive() && await this.cancelFill(), this.cancelRequest(), this.state.autofill = Ft(this.options.autofill, void 0, !1), this.fillController.reset(), this.exactMediaRemoval.reset(), this.itemRemoval.reset(), this.state.error = null, this.state.isLoading = !0, this.state.items = [], this.state.next = null, this.state.nextPageError = null, this.state.total = null, this.startRequest(e, !1);
3063
3280
  }
3064
3281
  async retryEnd() {
3065
3282
  if (this.pendingRequest) return this.pendingRequest;
3066
- if (!this.state.loadMoreLocked && !(Ft(this.state.autofill) || this.fillController.isActive()) && !(this.state.next !== null || !this.options.loadPage)) return this.state.isLoadingMore = !0, this.state.nextPageError = null, this.startRequest(this.lastLoadedCursor, !0);
3283
+ if (!this.state.loadMoreLocked && !(It(this.state.autofill) || this.fillController.isActive()) && !(this.state.next !== null || !this.options.loadPage)) return this.state.isLoadingMore = !0, this.state.nextPageError = null, this.startRequest(this.lastLoadedCursor, !0);
3067
3284
  }
3068
3285
  setInfiniteScroll(e) {
3069
3286
  this.state.infiniteScroll = e, e && p(() => this.surface?.loadIfNearBottom());
@@ -3072,10 +3289,10 @@ var Fn = class {
3072
3289
  this.state.loadMoreLocked !== e && (this.state.loadMoreLocked = e, !e && this.state.infiniteScroll && p(() => this.surface?.loadIfNearBottom()));
3073
3290
  }
3074
3291
  setReelAutoAdvance(e) {
3075
- gn(this.state.reelAutoAdvance, e);
3292
+ xn(this.state.reelAutoAdvance, e);
3076
3293
  }
3077
3294
  setReelInfoSheet(e) {
3078
- vn(this.state.reelInfoSheet, this.options.reelInfoSheet, e);
3295
+ Cn(this.state.reelInfoSheet, this.options.reelInfoSheet, e);
3079
3296
  }
3080
3297
  setLayout(e) {
3081
3298
  this.responsiveLayout.setLayout(e);
@@ -3083,16 +3300,6 @@ var Fn = class {
3083
3300
  closeMasonryReel() {
3084
3301
  this.state.reelOrigin === "masonry" && (this.state.activeReelPostId = null, this.state.reelOrigin = null, this.routing.syncFeed());
3085
3302
  }
3086
- restoreActiveItemAfterRemoval(e, t) {
3087
- let n = new Set(e.map(({ item: e }) => e.postId));
3088
- if (this.state.activeReelPostId === null || !n.has(this.state.activeReelPostId)) return;
3089
- if (this.state.reelOrigin === "masonry") {
3090
- this.closeMasonryReel();
3091
- return;
3092
- }
3093
- let r = this.state.items[Math.min(Math.max(t, 0), this.state.items.length - 1)];
3094
- this.state.activeReelPostId = r?.postId ?? null, r ? this.routing.syncReel(r.postId) : this.routing.syncFeed();
3095
- }
3096
3303
  openMasonryReel(e) {
3097
3304
  this.state.layout === "masonry" && this.state.items.some((t) => t.postId === e) && (this.state.activeReelPostId = e, this.state.reelOrigin = "masonry", this.routing.syncReel(e));
3098
3305
  }
@@ -3109,7 +3316,7 @@ var Fn = class {
3109
3316
  this.abortController = i;
3110
3317
  try {
3111
3318
  if (a?.strategy === "frontend") {
3112
- let o = await Rt({
3319
+ let o = await zt({
3113
3320
  existingItems: t ? this.state.items : [],
3114
3321
  initialCursor: e,
3115
3322
  loadPage: n,
@@ -3131,7 +3338,7 @@ var Fn = class {
3131
3338
  });
3132
3339
  return;
3133
3340
  }
3134
- let c = bt(await n({
3341
+ let c = xt(await n({
3135
3342
  cursor: e,
3136
3343
  signal: i.signal
3137
3344
  }));
@@ -3146,7 +3353,7 @@ var Fn = class {
3146
3353
  this.state.autofill.status = "complete";
3147
3354
  return;
3148
3355
  }
3149
- await Gt(a, this.state, {
3356
+ await Kt(a, this.state, {
3150
3357
  cycleId: o,
3151
3358
  feedKey: a.feedKey,
3152
3359
  items: u.slice(l.length),
@@ -3171,7 +3378,7 @@ var Fn = class {
3171
3378
  this.autofillDelayCountdown.clear();
3172
3379
  let t = `vibe-autofill-${Date.now().toString(36)}-${++this.autofillCycle}`;
3173
3380
  return this.state.autofill = {
3174
- ...Pt(e, void 0, !1),
3381
+ ...Ft(e, void 0, !1),
3175
3382
  cycleId: t,
3176
3383
  status: "filling"
3177
3384
  }, t;
@@ -3189,7 +3396,7 @@ var Fn = class {
3189
3396
  startInitialAutofill() {
3190
3397
  let e = ++this.requestVersion, t = new AbortController(), n = this.beginAutofillCycle();
3191
3398
  this.abortController = t, this.state.isLoadingMore = !0;
3192
- let r = Yt({
3399
+ let r = Xt({
3193
3400
  cycleId: n,
3194
3401
  isCurrent: () => e === this.requestVersion,
3195
3402
  onLastCursor: (e) => {
@@ -3213,8 +3420,8 @@ var Fn = class {
3213
3420
  }));
3214
3421
  }
3215
3422
  };
3216
- function Rn(e) {
3217
- return new Ln(e);
3423
+ function Un(e) {
3424
+ return new Hn(e);
3218
3425
  }
3219
3426
  //#endregion
3220
- export { Rn as createVibe };
3427
+ export { Un as createVibe };