@wyxos/vibe 4.2.1 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -114,12 +114,17 @@ var I = {
114
114
  return (t, n) => e.feedFooter && e.actions && e.state ? (y(), i(S(e.feedFooter.component), {
115
115
  key: 0,
116
116
  actions: e.actions,
117
+ "can-retry-end": e.canRetryEnd,
117
118
  state: e.state,
118
119
  onAutofillCancel: a,
119
120
  onLoadMore: n[0] ||= (e) => r("loadMore"),
120
121
  onRetry: o,
121
122
  onRetryEnd: n[1] ||= (e) => r("retryEnd")
122
- }, null, 40, ["actions", "state"])) : (y(), i(H, {
123
+ }, null, 40, [
124
+ "actions",
125
+ "can-retry-end",
126
+ "state"
127
+ ])) : (y(), i(H, {
123
128
  key: 1,
124
129
  "can-retry-end": e.canRetryEnd,
125
130
  "has-error": e.hasError,
@@ -138,7 +143,7 @@ var I = {
138
143
  "load-more-locked"
139
144
  ]));
140
145
  }
141
- }), W = ["role"], ee = { class: "gallery-status" }, G = /* @__PURE__ */ u({
146
+ }), W = ["role"], ee = { class: "gallery-status" }, te = /* @__PURE__ */ u({
142
147
  __name: "FeedStatus",
143
148
  props: {
144
149
  actions: {},
@@ -178,33 +183,33 @@ var I = {
178
183
  ])) : a("", !0)], 8, W));
179
184
  }
180
185
  });
181
- function K(e) {
186
+ function G(e) {
182
187
  return e.scrollHeight - e.scrollTop - e.clientHeight <= 240;
183
188
  }
184
189
  //#endregion
185
190
  //#region src/core/masonry.ts
186
- function te(e) {
191
+ function ne(e) {
187
192
  let t = e.preview.width ?? e.width, n = e.preview.height ?? e.height;
188
193
  return !t || !n || t <= 0 || n <= 0 ? 1 : n / t;
189
194
  }
190
- function ne(e) {
195
+ function K(e) {
191
196
  return e.reduce((t, n, r) => n < e[t] ? r : t, 0);
192
197
  }
193
- function re(e) {
198
+ function q(e) {
194
199
  return Math.max(0, e.containerHeight) + Math.max(0, e.gap);
195
200
  }
196
- function q(e, t) {
201
+ function J(e, t) {
197
202
  let n = Math.max(0, t.overscan), r = t.scrollTop - n, i = t.scrollTop + Math.max(0, t.viewportHeight) + n;
198
203
  return e.reduce((e, t, n) => (t.y + t.height >= r && t.y <= i && e.push(n), e), []);
199
204
  }
200
- function J(e, t, n) {
205
+ function Y(e, t, n) {
201
206
  if (t <= 0 || e.length === 0) return {
202
207
  columns: 0,
203
208
  height: 0,
204
209
  items: []
205
210
  };
206
211
  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) => {
207
- let t = ne(c), n = s * te(e) + i, a = {
212
+ let t = K(c), n = s * ne(e) + i, a = {
208
213
  x: t * (s + r),
209
214
  y: c[t],
210
215
  width: s,
@@ -220,10 +225,10 @@ function J(e, t, n) {
220
225
  }
221
226
  //#endregion
222
227
  //#region src/core/scrollbar.ts
223
- function Y(e, t, n) {
228
+ function X(e, t, n) {
224
229
  return Math.min(n, Math.max(t, e));
225
230
  }
226
- function ie({ contentSize: e, minimumThumbSize: t, scrollPosition: n, trackSize: r, viewportSize: i }) {
231
+ function re({ contentSize: e, minimumThumbSize: t, scrollPosition: n, trackSize: r, viewportSize: i }) {
227
232
  let a = Math.max(0, e), o = Math.max(0, r), s = Math.max(0, i), c = Math.max(0, a - s);
228
233
  if (!(c > 0 && o > 0)) return {
229
234
  maximumScrollPosition: c,
@@ -232,18 +237,18 @@ function ie({ contentSize: e, minimumThumbSize: t, scrollPosition: n, trackSize:
232
237
  thumbSize: o,
233
238
  thumbTravel: 0
234
239
  };
235
- let l = Y(s / a * o, Math.min(Math.max(0, t), o), o), u = Math.max(0, o - l);
240
+ let l = X(s / a * o, Math.min(Math.max(0, t), o), o), u = Math.max(0, o - l);
236
241
  return {
237
242
  maximumScrollPosition: c,
238
243
  scrollable: !0,
239
- thumbOffset: u * (Y(n, 0, c) / c),
244
+ thumbOffset: u * (X(n, 0, c) / c),
240
245
  thumbSize: l,
241
246
  thumbTravel: u
242
247
  };
243
248
  }
244
249
  //#endregion
245
250
  //#region src/components/GalleryScrollbar.vue?vue&type=script&setup=true&lang.ts
246
- var ae = ["aria-hidden"], X = [
251
+ var ie = ["aria-hidden"], ae = [
247
252
  "aria-controls",
248
253
  "aria-valuemax",
249
254
  "aria-valuenow",
@@ -277,7 +282,7 @@ var ae = ["aria-hidden"], X = [
277
282
  }
278
283
  function j() {
279
284
  let e = t.scrollElement, n = i.value;
280
- return !e || !n ? r : ie({
285
+ return !e || !n ? r : re({
281
286
  contentSize: e.scrollHeight,
282
287
  minimumThumbSize: Z,
283
288
  scrollPosition: e.scrollTop,
@@ -378,7 +383,7 @@ var ae = ["aria-hidden"], X = [
378
383
  onPointerdown: I,
379
384
  onPointermove: L,
380
385
  onPointerup: R
381
- }, null, 44, X)], 42, ae));
386
+ }, null, 44, ae)], 42, ie));
382
387
  }
383
388
  }), le = (e) => {
384
389
  for (let t in e) if (t.startsWith("aria-") || t === "role" || t === "title") return !0;
@@ -501,13 +506,18 @@ var ke = /* @__PURE__ */ u({
501
506
  mediaSource: {},
502
507
  placement: {},
503
508
  region: {},
509
+ style: {},
504
510
  total: {}
505
511
  },
506
512
  setup(e) {
507
- let t = e, r = n(() => M(t.item, t.mediaIndex)), a = n(() => j(t.item)), s = n(() => N(t.item, r.value));
513
+ let t = e, r = n(() => M(t.item, t.mediaIndex)), a = n(() => j(t.item)), s = n(() => N(t.item, r.value)), c = n(() => ({
514
+ height: `${t.region.height}px`,
515
+ paddingBlock: t.style?.paddingY === void 0 ? void 0 : `${t.style.paddingY}px`,
516
+ paddingInline: t.style?.paddingX === void 0 ? void 0 : `${t.style.paddingX}px`
517
+ })), l = n(() => t.style?.background ?? t.region.background);
508
518
  return (t, n) => (y(), o("div", {
509
- class: m(["media-card-region", [`media-card-${e.placement}`, { "media-card-region--transparent": e.region.background === "transparent" }]]),
510
- style: g({ height: `${e.region.height}px` }),
519
+ class: m(["media-card-region", [`media-card-${e.placement}`, { "media-card-region--transparent": l.value === "transparent" }]]),
520
+ style: g(c.value),
511
521
  onClick: n[0] ||= A(() => {}, ["stop"]),
512
522
  onKeydown: n[1] ||= A(() => {}, ["stop"])
513
523
  }, [(y(), i(S(e.region.component), {
@@ -637,7 +647,9 @@ var ke = /* @__PURE__ */ u({
637
647
  }), Re = [
638
648
  "data-post-id",
639
649
  "data-media-index",
650
+ "aria-hidden",
640
651
  "aria-busy",
652
+ "inert",
641
653
  "role",
642
654
  "tabindex"
643
655
  ], ze = { class: "media-card-content" }, Be = ["data-media-direction"], Ve = ["data-media-index"], He = {
@@ -669,9 +681,11 @@ var ke = /* @__PURE__ */ u({
669
681
  item: {},
670
682
  itemStyle: {},
671
683
  interactive: { type: Boolean },
684
+ leaving: { type: Boolean },
672
685
  layout: {},
673
686
  loadedCount: {},
674
687
  mediaIndex: {},
688
+ mediaCard: {},
675
689
  mediaSource: {},
676
690
  previewState: {},
677
691
  total: {}
@@ -692,41 +706,41 @@ var ke = /* @__PURE__ */ u({
692
706
  function ee(e) {
693
707
  return e.detail === 0 ? "keyboard" : "pointer";
694
708
  }
695
- function G(e, t) {
709
+ function te(e, t) {
696
710
  let n = S.value.length, r = (e + n) % n;
697
711
  r !== E.value && (v.value = e < E.value ? "previous" : "next", b("mediaChange", r), t && t.detail > 0 && t.currentTarget?.blur());
698
712
  }
699
- function K(e, t, n) {
713
+ function G(e, t, n) {
700
714
  return t === 1 ? e * 16 : t === 2 ? e * n : e;
701
715
  }
702
- function te() {
716
+ function ne() {
703
717
  d = 0, f = !1, u !== null && clearTimeout(u), u = null;
704
718
  }
705
- function ne() {
706
- u !== null && clearTimeout(u), u = setTimeout(te, Ze);
719
+ function K() {
720
+ u !== null && clearTimeout(u), u = setTimeout(ne, Ze);
707
721
  }
708
- function re(e) {
722
+ function q(e) {
709
723
  if (S.value.length <= 1) return;
710
- let t = e.currentTarget?.clientWidth || 1, n = K(e.deltaX, e.deltaMode, t);
711
- if (n === 0 || (e.preventDefault(), ne(), f) || (d += n, Math.abs(d) < Qe)) return;
724
+ let t = e.currentTarget?.clientWidth || 1, n = G(e.deltaX, e.deltaMode, t);
725
+ if (n === 0 || (e.preventDefault(), K(), f) || (d += n, Math.abs(d) < Qe)) return;
712
726
  let r = Math.sign(d);
713
- d = 0, f = !0, G(E.value + r);
727
+ d = 0, f = !0, te(E.value + r);
714
728
  }
715
- function q(e) {
729
+ function J(e) {
716
730
  let t = e.touches[0];
717
731
  c.layout !== "reel" || !t || (p = t.clientX, h = t.clientY);
718
732
  }
719
- function J(e) {
733
+ function Y(e) {
720
734
  let t = e.changedTouches[0];
721
735
  if (p === null || h === null || !t) return;
722
736
  let n = p - t.clientX, r = h - t.clientY;
723
- p = null, h = null, !(Math.abs(n) <= Math.abs(r)) && (Math.abs(n) < Xe || G(E.value + Math.sign(n)));
737
+ p = null, h = null, !(Math.abs(n) <= Math.abs(r)) && (Math.abs(n) < Xe || te(E.value + Math.sign(n)));
724
738
  }
725
- let Y = n(() => Oe(P.value));
726
- function ie(e) {
727
- c.layout === "reel" && (e.stopPropagation(), ae());
739
+ let X = n(() => Oe(P.value));
740
+ function re(e) {
741
+ c.layout === "reel" && (e.stopPropagation(), ie());
728
742
  }
729
- async function ae() {
743
+ async function ie() {
730
744
  if (L.value) {
731
745
  if (V.value) {
732
746
  L.value.pause();
@@ -739,12 +753,12 @@ var ke = /* @__PURE__ */ u({
739
753
  }
740
754
  }
741
755
  }
742
- function X(e) {
756
+ function ae(e) {
743
757
  return Number.isFinite(e) ? Math.max(0, e) : 0;
744
758
  }
745
759
  function Z(e) {
746
760
  let t = e?.currentTarget ?? L.value;
747
- t && (R.value = X(t.currentTime), z.value = X(t.duration), B.value = t.muted, H.value = t.volume, t.volume > 0 && (U = t.volume));
761
+ 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));
748
762
  }
749
763
  function oe(e) {
750
764
  Z(e), b("ready", E.value);
@@ -754,7 +768,7 @@ var ke = /* @__PURE__ */ u({
754
768
  }
755
769
  function ce(e) {
756
770
  let t = L.value;
757
- !t || !Number.isFinite(e) || (t.currentTime = Math.min(X(t.duration), Math.max(0, e)), R.value = t.currentTime);
771
+ !t || !Number.isFinite(e) || (t.currentTime = Math.min(ae(t.duration), Math.max(0, e)), R.value = t.currentTime);
758
772
  }
759
773
  function le(e) {
760
774
  let t = L.value;
@@ -767,19 +781,22 @@ var ke = /* @__PURE__ */ u({
767
781
  e && (e.muted && e.volume === 0 && (e.volume = U), e.muted = !e.muted, Z());
768
782
  }
769
783
  return _(() => {
770
- te();
784
+ ne();
771
785
  }), (n, r) => (y(), o("article", {
772
786
  "data-post-id": e.item.postId,
773
787
  "data-media-index": E.value,
774
788
  class: m(["media-card", {
775
789
  "media-card--entering": e.entering,
790
+ "media-card--leaving": e.leaving,
776
791
  "media-card--error": e.previewState === "error",
777
- "media-card--transparent-chrome": e.cardHeader?.background === "transparent" || e.cardFooter?.background === "transparent"
792
+ "media-card--transparent-chrome": e.mediaCard?.header?.background === "transparent" || e.mediaCard?.footer?.background === "transparent" || e.cardHeader?.background === "transparent" || e.cardFooter?.background === "transparent"
778
793
  }]),
779
794
  style: g(e.itemStyle),
795
+ "aria-hidden": e.leaving || void 0,
780
796
  "aria-busy": e.previewState === "loading",
781
- role: e.interactive && !W.value ? "button" : void 0,
782
- tabindex: e.interactive && !W.value ? 0 : void 0,
797
+ inert: e.leaving || void 0,
798
+ role: e.interactive && !e.leaving && !W.value ? "button" : void 0,
799
+ tabindex: e.interactive && !e.leaving && !W.value ? 0 : void 0,
783
800
  onClick: r[11] ||= (t) => x(e.interactive && !W.value, ee(t)),
784
801
  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"])]
785
802
  }, [s("div", ze, [
@@ -793,6 +810,7 @@ var ke = /* @__PURE__ */ u({
793
810
  "media-source": e.mediaSource,
794
811
  placement: "header",
795
812
  region: e.cardHeader,
813
+ style: g(e.mediaCard?.header),
796
814
  total: e.total
797
815
  }, null, 8, [
798
816
  "index",
@@ -802,14 +820,15 @@ var ke = /* @__PURE__ */ u({
802
820
  "media-index",
803
821
  "media-source",
804
822
  "region",
823
+ "style",
805
824
  "total"
806
825
  ])) : a("", !0),
807
826
  s("div", {
808
827
  class: m(["media-card-media", { "media-card-media--carousel": e.layout === "reel" && S.value.length > 1 }]),
809
828
  "data-media-direction": v.value,
810
- onWheel: re,
811
- onTouchstartPassive: q,
812
- onTouchendPassive: J
829
+ onWheel: q,
830
+ onTouchstartPassive: J,
831
+ onTouchendPassive: Y
813
832
  }, [
814
833
  l(t, { name: `media-slide-${v.value}` }, {
815
834
  default: O(() => [(y(), o("div", {
@@ -822,7 +841,7 @@ var ke = /* @__PURE__ */ u({
822
841
  class: "media-error",
823
842
  role: "img",
824
843
  "aria-label": `${T(Te)(P.value)} ${T(Ee)(P.value)}`
825
- }, [s("strong", We, w(T(Te)(P.value)), 1), s("span", null, w(T(Ee)(P.value)), 1)], 8, Ue)) : a("", !0), Y.value ? (y(), o("video", {
844
+ }, [s("strong", We, w(T(Te)(P.value)), 1), s("span", null, w(T(Ee)(P.value)), 1)], 8, Ue)) : a("", !0), X.value ? (y(), o("video", {
826
845
  key: 2,
827
846
  ref_key: "videoElement",
828
847
  ref: L,
@@ -845,7 +864,7 @@ var ke = /* @__PURE__ */ u({
845
864
  onPlaying: r[0] ||= (e) => V.value = !0,
846
865
  onPause: r[1] ||= (e) => V.value = !1,
847
866
  onEnded: se,
848
- onClick: ie,
867
+ onClick: re,
849
868
  onError: r[2] ||= (e) => n.$emit("error", E.value)
850
869
  }, null, 42, Ge)) : (y(), o("img", {
851
870
  key: 3,
@@ -862,7 +881,7 @@ var ke = /* @__PURE__ */ u({
862
881
  }, null, 42, Ke))], 8, Ve))]),
863
882
  _: 1
864
883
  }, 8, ["name"]),
865
- Y.value && e.previewState === "ready" ? (y(), i(Le, {
884
+ X.value && e.previewState === "ready" ? (y(), i(Le, {
866
885
  key: 0,
867
886
  "current-time": R.value,
868
887
  duration: z.value,
@@ -872,7 +891,7 @@ var ke = /* @__PURE__ */ u({
872
891
  volume: H.value,
873
892
  onSeek: ce,
874
893
  onToggleMute: ue,
875
- onTogglePlayback: ae,
894
+ onTogglePlayback: ie,
876
895
  onVolumeChange: le
877
896
  }, null, 8, [
878
897
  "current-time",
@@ -890,13 +909,13 @@ var ke = /* @__PURE__ */ u({
890
909
  type: "button",
891
910
  class: "media-carousel-control media-carousel-control--previous",
892
911
  "aria-label": `Previous media for post ${e.item.postId}`,
893
- onClick: r[5] ||= A((e) => G(E.value - 1, e), ["stop"]),
912
+ onClick: r[5] ||= A((e) => te(E.value - 1, e), ["stop"]),
894
913
  onKeydown: r[6] ||= A(() => {}, ["stop"])
895
914
  }, [l(T(ve), { size: 20 })], 40, qe), s("button", {
896
915
  type: "button",
897
916
  class: "media-carousel-control media-carousel-control--next",
898
917
  "aria-label": `Next media for post ${e.item.postId}`,
899
- onClick: r[7] ||= A((e) => G(E.value + 1, e), ["stop"]),
918
+ onClick: r[7] ||= A((e) => te(E.value + 1, e), ["stop"]),
900
919
  onKeydown: r[8] ||= A(() => {}, ["stop"])
901
920
  }, [l(T(ye), { size: 20 })], 40, Je)], 2)) : a("", !0),
902
921
  W.value ? (y(), o("button", {
@@ -918,6 +937,7 @@ var ke = /* @__PURE__ */ u({
918
937
  "media-source": e.mediaSource,
919
938
  placement: "footer",
920
939
  region: e.cardFooter,
940
+ style: g(e.mediaCard?.footer),
921
941
  total: e.total
922
942
  }, null, 8, [
923
943
  "index",
@@ -927,6 +947,7 @@ var ke = /* @__PURE__ */ u({
927
947
  "media-index",
928
948
  "media-source",
929
949
  "region",
950
+ "style",
930
951
  "total"
931
952
  ])) : a("", !0)
932
953
  ])], 46, Re));
@@ -936,6 +957,8 @@ var ke = /* @__PURE__ */ u({
936
957
  props: {
937
958
  enteringPostIds: {},
938
959
  entryDelays: {},
960
+ leavingPostIds: { default: () => /* @__PURE__ */ new Set() },
961
+ removalDelays: { default: () => /* @__PURE__ */ new Map() },
939
962
  suspended: { type: Boolean },
940
963
  canRetryEnd: { type: Boolean },
941
964
  cardFooter: {},
@@ -947,6 +970,7 @@ var ke = /* @__PURE__ */ u({
947
970
  isLoadingMore: { type: Boolean },
948
971
  items: {},
949
972
  loadMoreLocked: { type: Boolean },
973
+ mediaCard: {},
950
974
  mediaIndices: {},
951
975
  nextPageError: { type: Boolean },
952
976
  previewStates: {},
@@ -962,82 +986,98 @@ var ke = /* @__PURE__ */ u({
962
986
  "retryEnd"
963
987
  ],
964
988
  setup(t, { expose: r, emit: a }) {
965
- let c = t, u = a, d = C(null), f = `vibe-masonry-${E()}`, p = C(null), h = C(0), v = C(rt), b = C(0), S = C(0), w = C(0), O = null, k = null, A = null, j = n(() => J(c.items, h.value, {
989
+ let c = t, u = a, d = C(null), f = `vibe-masonry-${E()}`, p = C(null), h = C(0), v = C(rt), b = C(0), S = C(0), w = C(0), O = null, k = null, A = null, j = n(() => Y(c.items, h.value, {
966
990
  additionalHeight: (c.cardHeader?.height ?? 0) + (c.cardFooter?.height ?? 0),
967
991
  gap: v.value,
968
992
  minColumnWidth: nt
969
- })), M = n(() => ({ height: `${j.value.height}px` })), N = n(() => {
993
+ })), M = n(() => {
994
+ let e = j.value;
995
+ if (c.leavingPostIds.size === 0) return e;
996
+ let t = c.items.filter((e) => !c.leavingPostIds.has(e.postId)), n = Y(t, h.value, {
997
+ additionalHeight: (c.cardHeader?.height ?? 0) + (c.cardFooter?.height ?? 0),
998
+ gap: v.value,
999
+ minColumnWidth: nt
1000
+ }), r = new Map(t.map((e, t) => [e.postId, n.items[t]]));
1001
+ return {
1002
+ ...n,
1003
+ items: c.items.map((t, n) => c.leavingPostIds.has(t.postId) ? e.items[n] : r.get(t.postId) ?? e.items[n])
1004
+ };
1005
+ }), N = n(() => ({ height: `${c.leavingPostIds.size === 0 ? M.value.height : j.value.height}px` })), F = n(() => {
970
1006
  let e = Math.max(at, S.value * ot), t = {
971
1007
  scrollTop: b.value - w.value,
972
1008
  viewportHeight: S.value
973
- }, n = q(j.value.items, {
1009
+ }, n = J(M.value.items, {
974
1010
  ...t,
975
1011
  overscan: e
976
- }), r = new Set(q(j.value.items, {
1012
+ }), r = c.leavingPostIds.size === 0 ? [] : J(j.value.items, {
1013
+ ...t,
1014
+ overscan: e
1015
+ }), i = [...new Set([...n, ...r])].sort((e, t) => e - t), a = J(M.value.items, {
977
1016
  ...t,
978
1017
  overscan: 0
979
- }));
980
- return n.flatMap((e) => {
1018
+ }), o = c.leavingPostIds.size === 0 ? [] : J(j.value.items, {
1019
+ ...t,
1020
+ overscan: 0
1021
+ }), s = new Set([...a, ...o]);
1022
+ return i.flatMap((e) => {
981
1023
  let t = c.items[e];
982
1024
  return t ? [{
983
- fetchPriority: r.has(e) ? "high" : "low",
1025
+ fetchPriority: s.has(e) ? "high" : "low",
984
1026
  index: e,
985
1027
  item: t
986
1028
  }] : [];
987
1029
  });
988
1030
  });
989
- function F(e) {
990
- let t = j.value.items[e], n = c.items[e]?.postId;
1031
+ function I(e) {
1032
+ let t = M.value.items[e], n = c.items[e]?.postId;
991
1033
  if (!t) return {};
992
- let r = n !== void 0 && c.enteringPostIds.has(n) ? re({
1034
+ let r = n !== void 0 && c.enteringPostIds.has(n), i = n !== void 0 && c.leavingPostIds.has(n), a = r || i ? q({
993
1035
  containerHeight: j.value.height,
994
1036
  gap: v.value
995
- }) : 0;
1037
+ }) : 0, o = n === void 0 ? 0 : i ? c.removalDelays.get(n) ?? 0 : r ? c.entryDelays.get(n) ?? 0 : 0;
996
1038
  return {
997
- "--masonry-entry-delay": `${n === void 0 ? 0 : c.entryDelays.get(n) ?? 0}ms`,
998
- top: `${t.y}px`,
999
- left: `${t.x}px`,
1039
+ "--masonry-entry-delay": `${o}ms`,
1000
1040
  width: `${t.width}px`,
1001
1041
  height: `${t.height}px`,
1002
- transform: `translate3d(0, ${r}px, 0)`
1042
+ transform: `translate3d(${t.x}px, ${t.y + a}px, 0)`
1003
1043
  };
1004
1044
  }
1005
- function I() {
1045
+ function L() {
1006
1046
  let e = d.value;
1007
1047
  if (!e) return;
1008
1048
  b.value = e.scrollTop, S.value = e.clientHeight;
1009
1049
  let t = p.value;
1010
1050
  t && (w.value = t.getBoundingClientRect().top - e.getBoundingClientRect().top + e.scrollTop);
1011
1051
  }
1012
- function L(e) {
1052
+ function R(e) {
1013
1053
  let t = e.ownerDocument.documentElement.clientWidth;
1014
- h.value = e.clientWidth, v.value = Math.min(it, Math.max(rt, t * .0075)), I();
1054
+ h.value = e.clientWidth, v.value = Math.min(it, Math.max(rt, t * .0075)), L();
1015
1055
  }
1016
- function R(e) {
1056
+ function z(e) {
1017
1057
  let t = e.currentTarget;
1018
- t && (b.value = t.scrollTop, !c.loadMoreLocked && c.infiniteScroll && K(t) && u("loadMore"));
1058
+ t && (b.value = t.scrollTop, !c.loadMoreLocked && c.infiniteScroll && G(t) && u("loadMore"));
1019
1059
  }
1020
- function z() {
1060
+ function B() {
1021
1061
  let e = d.value;
1022
- !c.loadMoreLocked && e && K(e) && u("loadMore");
1062
+ !c.loadMoreLocked && e && G(e) && u("loadMore");
1023
1063
  }
1024
- function B() {
1064
+ function V() {
1025
1065
  return d.value;
1026
1066
  }
1027
1067
  return D(p, (e) => {
1028
- O?.disconnect(), O = null, A !== null && cancelAnimationFrame(A), e && (L(e), !(typeof ResizeObserver > "u") && (O = new ResizeObserver(([t]) => {
1068
+ O?.disconnect(), O = null, A !== null && cancelAnimationFrame(A), e && (R(e), !(typeof ResizeObserver > "u") && (O = new ResizeObserver(([t]) => {
1029
1069
  let n = t?.contentRect.width ?? e.clientWidth;
1030
1070
  Math.abs(n - h.value) < .5 || (A = requestAnimationFrame(() => {
1031
- A = null, L(e);
1071
+ A = null, R(e);
1032
1072
  }));
1033
1073
  }), O.observe(e)));
1034
1074
  }), D(d, (e) => {
1035
- k?.disconnect(), k = null, e && (I(), !(typeof ResizeObserver > "u") && (k = new ResizeObserver(I), k.observe(e)));
1075
+ k?.disconnect(), k = null, e && (L(), !(typeof ResizeObserver > "u") && (k = new ResizeObserver(L), k.observe(e)));
1036
1076
  }), _(() => {
1037
1077
  O?.disconnect(), k?.disconnect(), A !== null && cancelAnimationFrame(A);
1038
1078
  }), r({
1039
- getScrollElement: B,
1040
- loadIfNearBottom: z
1079
+ getScrollElement: V,
1080
+ loadIfNearBottom: B
1041
1081
  }), (n, r) => (y(), o("div", et, [s("main", {
1042
1082
  id: f,
1043
1083
  ref_key: "galleryElement",
@@ -1046,23 +1086,25 @@ var ke = /* @__PURE__ */ u({
1046
1086
  "data-layout-mode": "masonry",
1047
1087
  "aria-hidden": t.suspended || void 0,
1048
1088
  inert: t.suspended || void 0,
1049
- onScrollPassive: R
1089
+ onScrollPassive: z
1050
1090
  }, [s("section", {
1051
1091
  ref_key: "masonryElement",
1052
1092
  ref: p,
1053
1093
  class: m(["masonry", { "masonry--ready": h.value > 0 }]),
1054
- style: g(M.value),
1094
+ style: g(N.value),
1055
1095
  "aria-label": "Media gallery"
1056
- }, [(y(!0), o(e, null, x(N.value, ({ fetchPriority: e, item: n, index: r }) => (y(), i($e, {
1096
+ }, [(y(!0), o(e, null, x(F.value, ({ fetchPriority: e, item: n, index: r }) => (y(), i($e, {
1057
1097
  key: n.postId,
1058
1098
  class: "masonry-item",
1059
1099
  entering: t.enteringPostIds.has(n.postId),
1100
+ leaving: t.leavingPostIds.has(n.postId),
1060
1101
  "fetch-priority": e,
1061
1102
  "card-footer": t.cardFooter,
1062
1103
  "card-header": t.cardHeader,
1104
+ "media-card": t.mediaCard,
1063
1105
  index: r,
1064
1106
  item: n,
1065
- "item-style": F(r),
1107
+ "item-style": I(r),
1066
1108
  interactive: "",
1067
1109
  layout: "masonry",
1068
1110
  "loaded-count": t.items.length,
@@ -1075,9 +1117,11 @@ var ke = /* @__PURE__ */ u({
1075
1117
  onError: (e) => u("error", n.postId, e)
1076
1118
  }, null, 8, [
1077
1119
  "entering",
1120
+ "leaving",
1078
1121
  "fetch-priority",
1079
1122
  "card-footer",
1080
1123
  "card-header",
1124
+ "media-card",
1081
1125
  "index",
1082
1126
  "item",
1083
1127
  "item-style",
@@ -1112,7 +1156,7 @@ var ke = /* @__PURE__ */ u({
1112
1156
  "load-more-locked",
1113
1157
  "state"
1114
1158
  ])], 42, tt), l(ce, {
1115
- "content-size": j.value.height,
1159
+ "content-size": M.value.height,
1116
1160
  "controls-id": f,
1117
1161
  "scroll-element": d.value,
1118
1162
  suspended: t.suspended
@@ -1158,6 +1202,7 @@ var ke = /* @__PURE__ */ u({
1158
1202
  isLoadingMore: { type: Boolean },
1159
1203
  items: {},
1160
1204
  loadMoreLocked: { type: Boolean },
1205
+ mediaCard: {},
1161
1206
  mediaIndices: {},
1162
1207
  nextPageError: { type: Boolean },
1163
1208
  previewStates: {},
@@ -1206,40 +1251,40 @@ var ke = /* @__PURE__ */ u({
1206
1251
  function ee(e) {
1207
1252
  return { gridRow: `${e + 1}` };
1208
1253
  }
1209
- function G(e) {
1254
+ function te(e) {
1210
1255
  let t = w || e.clientHeight;
1211
1256
  return t <= 0 || u.items.length === 0 ? 0 : Math.min(u.items.length - 1, Math.max(0, Math.round(e.scrollTop / t)));
1212
1257
  }
1213
- function te(e) {
1258
+ function ne(e) {
1214
1259
  let t = e.currentTarget;
1215
- t && (S.value || (b.value = G(t)), !u.loadMoreLocked && u.infiniteScroll && K(t) && d("loadMore"));
1260
+ t && (S.value || (b.value = te(t)), !u.loadMoreLocked && u.infiniteScroll && G(t) && d("loadMore"));
1216
1261
  }
1217
- function ne() {
1262
+ function K() {
1218
1263
  let e = f.value;
1219
- e && (J(!0), w = e.clientHeight, e.scrollTop = b.value * w, O !== null && cancelAnimationFrame(O), O = requestAnimationFrame(() => {
1264
+ e && (Y(!0), w = e.clientHeight, e.scrollTop = b.value * w, O !== null && cancelAnimationFrame(O), O = requestAnimationFrame(() => {
1220
1265
  e.scrollTop = b.value * e.clientHeight, w = e.clientHeight, O = null;
1221
- }), re());
1266
+ }), q());
1222
1267
  }
1223
- function re() {
1268
+ function q() {
1224
1269
  k !== null && clearTimeout(k), k = setTimeout(() => {
1225
1270
  k = null;
1226
1271
  let e = f.value;
1227
- e && (w = e.clientHeight, e.scrollTop = b.value * w), J(!1);
1272
+ e && (w = e.clientHeight, e.scrollTop = b.value * w), Y(!1);
1228
1273
  }, 120);
1229
1274
  }
1230
- function q() {
1231
- J(!0);
1275
+ function J() {
1276
+ Y(!0);
1232
1277
  let e = f.value;
1233
- e && (w = e.clientHeight, e.scrollTop = b.value * w), re();
1278
+ e && (w = e.clientHeight, e.scrollTop = b.value * w), q();
1234
1279
  }
1235
- function J(e) {
1280
+ function Y(e) {
1236
1281
  S.value = e, f.value?.toggleAttribute("data-resizing", e);
1237
1282
  }
1238
- function Y() {
1283
+ function X() {
1239
1284
  let e = f.value;
1240
- !u.loadMoreLocked && e && K(e) && d("loadMore");
1285
+ !u.loadMoreLocked && e && G(e) && d("loadMore");
1241
1286
  }
1242
- function ie(e) {
1287
+ function re(e) {
1243
1288
  let t = I.value;
1244
1289
  if (!t) return !1;
1245
1290
  let n = j(t).length;
@@ -1247,18 +1292,18 @@ var ke = /* @__PURE__ */ u({
1247
1292
  let r = (L.value + e + n) % n;
1248
1293
  return d("mediaChange", t.postId, r), !0;
1249
1294
  }
1250
- function ae(e) {
1295
+ function ie(e) {
1251
1296
  let t = b.value + e;
1252
1297
  return !f.value || t < 0 || t >= u.items.length ? !1 : (Z(t), !0);
1253
1298
  }
1254
- function X() {
1299
+ function ae() {
1255
1300
  return typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1256
1301
  }
1257
1302
  function Z(e) {
1258
1303
  let t = f.value;
1259
1304
  if (!t) return;
1260
1305
  let n = e * (w || t.clientHeight);
1261
- if (b.value = e, !X() && typeof t.scrollTo == "function") {
1306
+ if (b.value = e, !ae() && typeof t.scrollTo == "function") {
1262
1307
  t.scrollTo({
1263
1308
  behavior: "smooth",
1264
1309
  top: n
@@ -1286,21 +1331,21 @@ var ke = /* @__PURE__ */ u({
1286
1331
  !u.reelAutoAdvance.enabled || e !== F.value || t !== L.value || !B.value || oe();
1287
1332
  }
1288
1333
  return D(f, (e) => {
1289
- E?.disconnect(), E = null, e && (w = e.clientHeight, !(typeof ResizeObserver > "u") && (E = new ResizeObserver(ne), E.observe(e)));
1334
+ E?.disconnect(), E = null, e && (w = e.clientHeight, !(typeof ResizeObserver > "u") && (E = new ResizeObserver(K), E.observe(e)));
1290
1335
  }), D(() => u.items.length, async (e) => {
1291
- b.value = Math.min(b.value, Math.max(0, e - 1)), await p(), ne();
1336
+ b.value = Math.min(b.value, Math.max(0, e - 1)), await p(), K();
1292
1337
  }), D(F, (e) => {
1293
1338
  e !== void 0 && d("activeChange", e);
1294
1339
  }, { immediate: !0 }), v(() => {
1295
- window.addEventListener("resize", q), window.addEventListener("orientationchange", q), h >= 0 && p(ne);
1340
+ window.addEventListener("resize", J), window.addEventListener("orientationchange", J), h >= 0 && p(K);
1296
1341
  }), _(() => {
1297
- window.removeEventListener("resize", q), window.removeEventListener("orientationchange", q), E?.disconnect(), O !== null && cancelAnimationFrame(O), k !== null && clearTimeout(k);
1342
+ window.removeEventListener("resize", J), window.removeEventListener("orientationchange", J), E?.disconnect(), O !== null && cancelAnimationFrame(O), k !== null && clearTimeout(k);
1298
1343
  }), r({
1299
1344
  activeIndex: b,
1300
1345
  activePostId: F,
1301
- changeActiveMedia: ie,
1302
- loadIfNearBottom: Y,
1303
- moveActivePost: ae
1346
+ changeActiveMedia: re,
1347
+ loadIfNearBottom: X,
1348
+ moveActivePost: ie
1304
1349
  }), (n, r) => (y(), o("main", {
1305
1350
  class: m(["reel-shell", {
1306
1351
  "reel-shell--has-footer": !!t.cardFooter,
@@ -1318,6 +1363,7 @@ var ke = /* @__PURE__ */ u({
1318
1363
  "media-source": t.mediaSource,
1319
1364
  placement: "header",
1320
1365
  region: t.cardHeader,
1366
+ style: g(t.mediaCard?.header),
1321
1367
  total: t.total
1322
1368
  }, null, 8, [
1323
1369
  "index",
@@ -1326,6 +1372,7 @@ var ke = /* @__PURE__ */ u({
1326
1372
  "media-index",
1327
1373
  "media-source",
1328
1374
  "region",
1375
+ "style",
1329
1376
  "total"
1330
1377
  ])) : a("", !0),
1331
1378
  s("div", {
@@ -1334,7 +1381,7 @@ var ke = /* @__PURE__ */ u({
1334
1381
  class: "gallery-shell reel-feed",
1335
1382
  "data-active-post-id": F.value,
1336
1383
  "data-active-media-index": L.value,
1337
- onScrollPassive: te
1384
+ onScrollPassive: ne
1338
1385
  }, [s("section", {
1339
1386
  class: "reel-track",
1340
1387
  style: g(A.value),
@@ -1348,6 +1395,7 @@ var ke = /* @__PURE__ */ u({
1348
1395
  index: r,
1349
1396
  item: n,
1350
1397
  "item-style": ee(r),
1398
+ "media-card": t.mediaCard,
1351
1399
  layout: "reel",
1352
1400
  "loaded-count": t.items.length,
1353
1401
  "media-index": t.mediaIndices.get(n.postId) ?? 0,
@@ -1364,6 +1412,7 @@ var ke = /* @__PURE__ */ u({
1364
1412
  "index",
1365
1413
  "item",
1366
1414
  "item-style",
1415
+ "media-card",
1367
1416
  "loaded-count",
1368
1417
  "media-index",
1369
1418
  "media-source",
@@ -1406,6 +1455,7 @@ var ke = /* @__PURE__ */ u({
1406
1455
  "media-source": t.mediaSource,
1407
1456
  placement: "footer",
1408
1457
  region: t.cardFooter,
1458
+ style: g(t.mediaCard?.footer),
1409
1459
  total: t.total
1410
1460
  }, null, 8, [
1411
1461
  "index",
@@ -1414,6 +1464,7 @@ var ke = /* @__PURE__ */ u({
1414
1464
  "media-index",
1415
1465
  "media-source",
1416
1466
  "region",
1467
+ "style",
1417
1468
  "total"
1418
1469
  ])) : a("", !0),
1419
1470
  W.value ? (y(), i(lt, {
@@ -1453,6 +1504,7 @@ var ke = /* @__PURE__ */ u({
1453
1504
  isLoadingMore: { type: Boolean },
1454
1505
  items: {},
1455
1506
  loadMoreLocked: { type: Boolean },
1507
+ mediaCard: {},
1456
1508
  mediaIndices: {},
1457
1509
  nextPageError: { type: Boolean },
1458
1510
  previewStates: {},
@@ -1546,6 +1598,7 @@ var ke = /* @__PURE__ */ u({
1546
1598
  "card-header": e.cardHeader,
1547
1599
  "feed-footer": e.feedFooter,
1548
1600
  "feed-footer-actions": e.feedFooterActions,
1601
+ "media-card": e.mediaCard,
1549
1602
  "has-next": e.hasNext,
1550
1603
  "infinite-scroll": e.infiniteScroll,
1551
1604
  "initial-post-id": e.initialPostId,
@@ -1571,6 +1624,7 @@ var ke = /* @__PURE__ */ u({
1571
1624
  "card-header",
1572
1625
  "feed-footer",
1573
1626
  "feed-footer-actions",
1627
+ "media-card",
1574
1628
  "has-next",
1575
1629
  "infinite-scroll",
1576
1630
  "initial-post-id",
@@ -1598,7 +1652,7 @@ var ke = /* @__PURE__ */ u({
1598
1652
  _: 1
1599
1653
  })], 10, pt));
1600
1654
  }
1601
- }), vt = 35, yt = /* @__PURE__ */ u({
1655
+ }), vt = 35, yt = 420, bt = /* @__PURE__ */ u({
1602
1656
  __name: "VibeSurface",
1603
1657
  props: {
1604
1658
  canRetryEnd: { type: Boolean },
@@ -1606,6 +1660,7 @@ var ke = /* @__PURE__ */ u({
1606
1660
  cardHeader: {},
1607
1661
  feedFooter: {},
1608
1662
  feedFooterActions: {},
1663
+ mediaCard: {},
1609
1664
  reelInfoSheet: {},
1610
1665
  state: {}
1611
1666
  },
@@ -1618,84 +1673,93 @@ var ke = /* @__PURE__ */ u({
1618
1673
  "retryEnd"
1619
1674
  ],
1620
1675
  setup(r, { expose: s, emit: c }) {
1621
- 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 Map()), k = C(/* @__PURE__ */ new Map()), A = C(/* @__PURE__ */ new Map()), j = n(() => F(u.state)), N = n(() => u.state.reelMediaSource === "original" ? A.value : k.value), I = new Set(u.state.items.map((e) => e.postId)), L = null, R = null, z = !1;
1622
- function B() {
1676
+ 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;
1677
+ function H() {
1623
1678
  return typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1624
1679
  }
1625
- function V() {
1626
- L !== null && cancelAnimationFrame(L), L = requestAnimationFrame(() => {
1627
- L = requestAnimationFrame(() => {
1628
- L = null, w.value = /* @__PURE__ */ new Set();
1680
+ function U() {
1681
+ z !== null && cancelAnimationFrame(z), z = requestAnimationFrame(() => {
1682
+ z = requestAnimationFrame(() => {
1683
+ z = null, w.value = /* @__PURE__ */ new Set();
1629
1684
  });
1630
1685
  });
1631
1686
  }
1632
- function H(e, t, n) {
1687
+ function W(e, t, n) {
1633
1688
  let r = P(e, t);
1634
- k.value.get(r) !== n && (k.value = new Map(k.value).set(r, n));
1689
+ j.value.get(r) !== n && (j.value = new Map(j.value).set(r, n));
1635
1690
  }
1636
- function U(e, t, n) {
1691
+ function ee(e, t, n) {
1637
1692
  let r = P(e, t);
1638
- A.value.get(r) !== n && (A.value = new Map(A.value).set(r, n));
1693
+ N.value.get(r) !== n && (N.value = new Map(N.value).set(r, n));
1639
1694
  }
1640
- function W(e, t) {
1641
- H(e, t, "error");
1695
+ function G(e, t) {
1696
+ W(e, t, "error");
1642
1697
  }
1643
- function ee(e, t) {
1644
- H(e, t, "ready");
1698
+ function ne(e, t) {
1699
+ W(e, t, "ready");
1645
1700
  }
1646
1701
  function K(e, t) {
1647
- U(e, t, "error");
1702
+ ee(e, t, "error");
1648
1703
  }
1649
- function te(e, t) {
1650
- U(e, t, "ready");
1704
+ function q(e, t) {
1705
+ ee(e, t, "ready");
1651
1706
  }
1652
- function ne(e, t) {
1707
+ function J(e, t) {
1653
1708
  if (u.state.reelMediaSource === "original") {
1654
1709
  K(e, t);
1655
1710
  return;
1656
1711
  }
1657
- W(e, t);
1712
+ G(e, t);
1658
1713
  }
1659
- function re(e, t) {
1714
+ function Y(e, t) {
1660
1715
  if (u.state.reelMediaSource === "original") {
1661
- te(e, t);
1716
+ q(e, t);
1662
1717
  return;
1663
1718
  }
1664
- ee(e, t);
1719
+ ne(e, t);
1665
1720
  }
1666
- function q(e, t) {
1721
+ function X(e, t) {
1667
1722
  let n = u.state.items.find((t) => t.postId === e);
1668
1723
  if (!n) return;
1669
1724
  let r = M(n, t);
1670
- (E.value.get(e) ?? 0) !== r && (E.value = new Map(E.value).set(e, r));
1725
+ (A.value.get(e) ?? 0) !== r && (A.value = new Map(A.value).set(e, r));
1671
1726
  }
1672
- async function J() {
1727
+ async function re() {
1673
1728
  await p(), (u.state.layout === "reel" || u.state.reelOrigin === "masonry" ? m.value : f.value)?.loadIfNearBottom();
1674
1729
  }
1675
- function Y(e) {
1730
+ function ie(e) {
1676
1731
  return u.state.isLoading || u.state.items.length === 0 || u.state.layout !== "reel" && u.state.reelOrigin !== "masonry" ? !1 : m.value?.changeActiveMedia?.(e) ?? !1;
1677
1732
  }
1678
- function ie(e) {
1733
+ function ae(e) {
1679
1734
  return u.state.isLoading || u.state.items.length === 0 || u.state.layout !== "reel" && u.state.reelOrigin !== "masonry" ? !1 : m.value?.moveActivePost?.(e) ?? !1;
1680
1735
  }
1681
- function ae() {
1736
+ function Z() {
1682
1737
  return u.state.layout !== "masonry" || u.state.reelOrigin === "masonry" ? null : f.value?.getScrollElement?.() ?? null;
1683
1738
  }
1684
- function X(e, t) {
1685
- R = e, z = t === "keyboard", x.value = se(e), d("openReel", e), p(() => h.value?.focus());
1739
+ function oe(e, t) {
1740
+ B = e, V = t === "keyboard", x.value = ue(e), d("openReel", e), p(() => h.value?.focus());
1686
1741
  }
1687
- function Z(e) {
1742
+ function se(e) {
1688
1743
  let t = b.value?.querySelectorAll(".masonry-feed [data-post-id]") ?? [];
1689
1744
  return Array.from(t).find((t) => t.dataset.postId === String(e)) ?? null;
1690
1745
  }
1691
- function oe(e, t) {
1692
- let n = Z(e), r = n?.querySelector(".media-card-activator") ?? n;
1746
+ function ce(e) {
1747
+ if (u.state.layout !== "masonry" || u.state.reelOrigin !== null || H()) return 0;
1748
+ let t = [...new Set(e)], n = t.filter(se);
1749
+ if (n.length === 0) return 0;
1750
+ let r = new Map(k.value);
1751
+ return n.forEach((e, t) => {
1752
+ r.set(e, t * vt);
1753
+ }), 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;
1754
+ }
1755
+ function le(e, t) {
1756
+ let n = se(e), r = n?.querySelector(".media-card-activator") ?? n;
1693
1757
  r && (r.classList.toggle("media-card-focus-silent", !t), t || r.addEventListener("blur", () => {
1694
1758
  r.classList.remove("media-card-focus-silent");
1695
1759
  }, { once: !0 }), r?.focus({ preventScroll: !0 }));
1696
1760
  }
1697
- function se(e) {
1698
- let t = b.value, n = Z(e);
1761
+ function ue(e) {
1762
+ let t = b.value, n = se(e);
1699
1763
  if (t === null || n === null) return {};
1700
1764
  let r = t.getBoundingClientRect(), i = n.getBoundingClientRect();
1701
1765
  return {
@@ -1705,19 +1769,19 @@ var ke = /* @__PURE__ */ u({
1705
1769
  "--vibe-reel-origin-left": `${Math.max(0, i.left - r.left)}px`
1706
1770
  };
1707
1771
  }
1708
- function ce() {
1709
- u.state.reelOrigin === "masonry" && (R ??= u.state.activeReelPostId, S.value = !0, d("closeReel"));
1772
+ function de() {
1773
+ u.state.reelOrigin === "masonry" && (B ??= u.state.activeReelPostId, S.value = !0, d("closeReel"));
1710
1774
  }
1711
- function le() {
1712
- let e = R, t = z;
1713
- S.value = !1, R = null, z = !1, x.value = {}, p(() => {
1714
- e !== null && oe(e, t);
1775
+ function fe() {
1776
+ let e = B, t = V;
1777
+ S.value = !1, B = null, V = !1, x.value = {}, p(() => {
1778
+ e !== null && le(e, t);
1715
1779
  });
1716
1780
  }
1717
- function ue(e) {
1781
+ function pe(e) {
1718
1782
  let t = u.state.layout === "reel" || u.state.reelOrigin === "masonry";
1719
1783
  if (e.key === "Escape" && u.state.reelOrigin === "masonry") {
1720
- e.preventDefault(), ce();
1784
+ e.preventDefault(), de();
1721
1785
  return;
1722
1786
  }
1723
1787
  if (e.key === "Escape" && t && u.state.reelInfoSheet.enabled) {
@@ -1735,32 +1799,33 @@ var ke = /* @__PURE__ */ u({
1735
1799
  r !== 0 && m.value?.changeActiveMedia?.(r) && e.preventDefault();
1736
1800
  }
1737
1801
  return D(() => u.state.items.map((e) => e.postId), (e) => {
1738
- let t = e.filter((e) => !I.has(e));
1739
- if (I = new Set(e), t.length === 0 || B()) return;
1740
- let n = /* @__PURE__ */ new Map();
1802
+ let t = e.filter((e) => !R.has(e)), n = new Set(e);
1803
+ 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;
1804
+ let r = /* @__PURE__ */ new Map();
1741
1805
  e.forEach((e) => {
1742
1806
  let t = T.value.get(e);
1743
- t !== void 0 && n.set(e, t);
1807
+ t !== void 0 && r.set(e, t);
1744
1808
  }), t.forEach((e, t) => {
1745
- n.set(e, t * vt);
1746
- }), T.value = n, w.value = new Set([...w.value, ...t]), V();
1747
- }, { flush: "sync" }), v(() => window.addEventListener("keydown", ue)), _(() => {
1748
- window.removeEventListener("keydown", ue), L !== null && cancelAnimationFrame(L);
1809
+ r.set(e, t * vt);
1810
+ }), T.value = r, w.value = new Set([...w.value, ...t]), U();
1811
+ }, { flush: "sync" }), v(() => window.addEventListener("keydown", pe)), _(() => {
1812
+ window.removeEventListener("keydown", pe), z !== null && cancelAnimationFrame(z);
1749
1813
  }), s({
1750
- changeActiveReelMedia: Y,
1751
- getAutoScrollElement: ae,
1752
- loadIfNearBottom: J,
1753
- moveActiveReelPost: ie
1814
+ changeActiveReelMedia: ie,
1815
+ getAutoScrollElement: Z,
1816
+ loadIfNearBottom: re,
1817
+ moveActiveReelPost: ae,
1818
+ startItemRemoval: ce
1754
1819
  }), (n, s) => (y(), o("div", {
1755
1820
  ref_key: "surfaceElement",
1756
1821
  ref: b,
1757
1822
  class: "vibe-surface"
1758
- }, [r.state.error || r.state.isLoading || r.state.items.length === 0 ? (y(), i(G, {
1823
+ }, [r.state.error || r.state.isLoading || r.state.items.length === 0 ? (y(), i(te, {
1759
1824
  key: 0,
1760
1825
  actions: r.feedFooterActions,
1761
1826
  "can-retry-end": r.canRetryEnd,
1762
1827
  "feed-footer": r.feedFooter,
1763
- state: j.value,
1828
+ state: I.value,
1764
1829
  onLoadMore: s[0] ||= (e) => d("loadMore"),
1765
1830
  onRetryEnd: s[1] ||= (e) => d("retryEnd")
1766
1831
  }, null, 8, [
@@ -1778,28 +1843,29 @@ var ke = /* @__PURE__ */ u({
1778
1843
  "card-header": r.cardHeader,
1779
1844
  "feed-footer": r.feedFooter,
1780
1845
  "feed-footer-actions": r.feedFooterActions,
1846
+ "media-card": r.mediaCard,
1781
1847
  "infinite-scroll": r.state.infiniteScroll,
1782
1848
  "is-loading-more": r.state.isLoadingMore,
1783
1849
  items: r.state.items,
1784
1850
  "load-more-locked": r.state.loadMoreLocked,
1785
1851
  "media-source": r.state.reelMediaSource,
1786
- "media-indices": E.value,
1852
+ "media-indices": A.value,
1787
1853
  "initial-post-id": r.state.activeReelPostId,
1788
1854
  "info-sheet": r.reelInfoSheet,
1789
1855
  "info-sheet-enabled": r.state.reelInfoSheet.enabled,
1790
1856
  "info-sheet-overlay": r.state.reelInfoSheetOverlay,
1791
1857
  "next-page-error": !!r.state.nextPageError,
1792
1858
  origin: "reel",
1793
- "preview-states": N.value,
1859
+ "preview-states": L.value,
1794
1860
  "reel-auto-advance": r.state.reelAutoAdvance,
1795
- state: j.value,
1861
+ state: I.value,
1796
1862
  total: r.state.total,
1797
1863
  onActiveChange: s[2] ||= (e) => d("activeReelChange", e),
1798
1864
  onCloseInfoSheet: s[3] ||= (e) => d("reelInfoSheetChange", !1),
1799
- onError: ne,
1865
+ onError: J,
1800
1866
  onLoadMore: s[4] ||= (e) => d("loadMore"),
1801
- onMediaChange: q,
1802
- onReady: re,
1867
+ onMediaChange: X,
1868
+ onReady: Y,
1803
1869
  onRetryEnd: s[5] ||= (e) => d("retryEnd")
1804
1870
  }, null, 8, [
1805
1871
  "can-retry-end",
@@ -1808,6 +1874,7 @@ var ke = /* @__PURE__ */ u({
1808
1874
  "card-header",
1809
1875
  "feed-footer",
1810
1876
  "feed-footer-actions",
1877
+ "media-card",
1811
1878
  "infinite-scroll",
1812
1879
  "is-loading-more",
1813
1880
  "items",
@@ -1829,35 +1896,41 @@ var ke = /* @__PURE__ */ u({
1829
1896
  "can-retry-end": r.canRetryEnd,
1830
1897
  "entering-post-ids": w.value,
1831
1898
  "entry-delays": T.value,
1899
+ "leaving-post-ids": E.value,
1900
+ "removal-delays": k.value,
1832
1901
  "card-footer": r.cardFooter,
1833
1902
  "card-header": r.cardHeader,
1834
1903
  "feed-footer": r.feedFooter,
1835
1904
  "feed-footer-actions": r.feedFooterActions,
1905
+ "media-card": r.mediaCard,
1836
1906
  "has-next": r.state.next !== null,
1837
1907
  "infinite-scroll": r.state.infiniteScroll,
1838
1908
  "is-loading-more": r.state.isLoadingMore,
1839
1909
  items: r.state.items,
1840
1910
  "load-more-locked": r.state.loadMoreLocked,
1841
- "media-indices": E.value,
1911
+ "media-indices": A.value,
1842
1912
  "next-page-error": !!r.state.nextPageError,
1843
- "preview-states": k.value,
1913
+ "preview-states": j.value,
1844
1914
  suspended: r.state.reelOrigin === "masonry" || S.value,
1845
- state: j.value,
1915
+ state: I.value,
1846
1916
  total: r.state.total,
1847
- onActivate: X,
1848
- onError: W,
1917
+ onActivate: oe,
1918
+ onError: G,
1849
1919
  onLoadMore: s[6] ||= (e) => d("loadMore"),
1850
- onMediaChange: q,
1851
- onReady: ee,
1920
+ onMediaChange: X,
1921
+ onReady: ne,
1852
1922
  onRetryEnd: s[7] ||= (e) => d("retryEnd")
1853
1923
  }, null, 8, [
1854
1924
  "can-retry-end",
1855
1925
  "entering-post-ids",
1856
1926
  "entry-delays",
1927
+ "leaving-post-ids",
1928
+ "removal-delays",
1857
1929
  "card-footer",
1858
1930
  "card-header",
1859
1931
  "feed-footer",
1860
1932
  "feed-footer-actions",
1933
+ "media-card",
1861
1934
  "has-next",
1862
1935
  "infinite-scroll",
1863
1936
  "is-loading-more",
@@ -1871,7 +1944,7 @@ var ke = /* @__PURE__ */ u({
1871
1944
  "total"
1872
1945
  ]), l(t, {
1873
1946
  name: "vibe-reel-viewer",
1874
- onAfterLeave: le
1947
+ onAfterLeave: fe
1875
1948
  }, {
1876
1949
  default: O(() => [r.state.reelOrigin === "masonry" ? (y(), o("section", {
1877
1950
  key: 0,
@@ -1891,6 +1964,7 @@ var ke = /* @__PURE__ */ u({
1891
1964
  "card-header": r.cardHeader,
1892
1965
  "feed-footer": r.feedFooter,
1893
1966
  "feed-footer-actions": r.feedFooterActions,
1967
+ "media-card": r.mediaCard,
1894
1968
  "has-next": r.state.next !== null,
1895
1969
  "infinite-scroll": r.state.infiniteScroll,
1896
1970
  "initial-post-id": r.state.activeReelPostId,
@@ -1900,20 +1974,20 @@ var ke = /* @__PURE__ */ u({
1900
1974
  "is-loading-more": r.state.isLoadingMore,
1901
1975
  items: r.state.items,
1902
1976
  "load-more-locked": r.state.loadMoreLocked,
1903
- "media-indices": E.value,
1977
+ "media-indices": A.value,
1904
1978
  "media-source": "original",
1905
1979
  "next-page-error": !!r.state.nextPageError,
1906
1980
  origin: "masonry",
1907
- "preview-states": A.value,
1981
+ "preview-states": N.value,
1908
1982
  "reel-auto-advance": r.state.reelAutoAdvance,
1909
- state: j.value,
1983
+ state: I.value,
1910
1984
  total: r.state.total,
1911
1985
  onActiveChange: s[8] ||= (e) => d("activeReelChange", e),
1912
1986
  onCloseInfoSheet: s[9] ||= (e) => d("reelInfoSheetChange", !1),
1913
1987
  onError: K,
1914
1988
  onLoadMore: s[10] ||= (e) => d("loadMore"),
1915
- onMediaChange: q,
1916
- onReady: te,
1989
+ onMediaChange: X,
1990
+ onReady: q,
1917
1991
  onRetryEnd: s[11] ||= (e) => d("retryEnd")
1918
1992
  }, null, 8, [
1919
1993
  "can-retry-end",
@@ -1921,6 +1995,7 @@ var ke = /* @__PURE__ */ u({
1921
1995
  "card-header",
1922
1996
  "feed-footer",
1923
1997
  "feed-footer-actions",
1998
+ "media-card",
1924
1999
  "has-next",
1925
2000
  "infinite-scroll",
1926
2001
  "initial-post-id",
@@ -1943,7 +2018,7 @@ var ke = /* @__PURE__ */ u({
1943
2018
  });
1944
2019
  //#endregion
1945
2020
  //#region src/core/page.ts
1946
- function bt(e) {
2021
+ function xt(e) {
1947
2022
  if (!e || typeof e != "object" || !Array.isArray(e.items)) throw TypeError("Vibe loadPage must resolve to a page with an items array.");
1948
2023
  if (e.next !== null && typeof e.next != "string" && typeof e.next != "number") throw TypeError("Vibe page next must be a string, number, or null.");
1949
2024
  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.");
@@ -1955,32 +2030,32 @@ function Q(e, t) {
1955
2030
  }
1956
2031
  //#endregion
1957
2032
  //#region src/core/requestDelay.ts
1958
- var xt = 2e3, St = 1e4, Ct = 250, wt = {
2033
+ var St = 2e3, Ct = 1e4, wt = 250, Tt = {
1959
2034
  delayRemainingMs: null,
1960
2035
  nextRequestAt: null
1961
2036
  };
1962
- function Tt(e, t) {
2037
+ function Et(e, t) {
1963
2038
  return e === void 0 ? t : Math.floor(e);
1964
2039
  }
1965
- function Et(e, t) {
2040
+ function Dt(e, t) {
1966
2041
  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.`);
1967
2042
  }
1968
- function Dt(e, t = {}) {
1969
- let n = Tt(t.delayStepMs, xt), r = Tt(t.delayMaxMs, St);
2043
+ function Ot(e, t = {}) {
2044
+ let n = Et(t.delayStepMs, St), r = Et(t.delayMaxMs, Ct);
1970
2045
  return Math.min(Math.max(0, e) * n, r);
1971
2046
  }
1972
2047
  function $(e) {
1973
- if (e == null || !Number.isFinite(e)) return { ...wt };
2048
+ if (e == null || !Number.isFinite(e)) return { ...Tt };
1974
2049
  let t = Math.max(0, Math.floor(e - Date.now()));
1975
2050
  return t > 0 ? {
1976
2051
  delayRemainingMs: t,
1977
2052
  nextRequestAt: e
1978
- } : { ...wt };
2053
+ } : { ...Tt };
1979
2054
  }
1980
- async function Ot({ delayMs: e, onChange: t, signal: n }) {
2055
+ async function kt({ delayMs: e, onChange: t, signal: n }) {
1981
2056
  if (n.aborted) throw new DOMException("Aborted", "AbortError");
1982
2057
  if (e <= 0) {
1983
- t({ ...wt });
2058
+ t({ ...Tt });
1984
2059
  return;
1985
2060
  }
1986
2061
  let r = Date.now() + e;
@@ -1988,9 +2063,9 @@ async function Ot({ delayMs: e, onChange: t, signal: n }) {
1988
2063
  delayRemainingMs: e,
1989
2064
  nextRequestAt: r
1990
2065
  }), await new Promise((i, a) => {
1991
- let o = !1, s = setInterval(f, Ct), c = setTimeout(() => u(), e);
2066
+ let o = !1, s = setInterval(f, wt), c = setTimeout(() => u(), e);
1992
2067
  function l() {
1993
- clearInterval(s), clearTimeout(c), n.removeEventListener("abort", d), t({ ...wt });
2068
+ clearInterval(s), clearTimeout(c), n.removeEventListener("abort", d), t({ ...Tt });
1994
2069
  }
1995
2070
  function u(e) {
1996
2071
  o || (o = !0, l(), e ? a(e) : i());
@@ -2005,13 +2080,13 @@ async function Ot({ delayMs: e, onChange: t, signal: n }) {
2005
2080
  n.addEventListener("abort", d, { once: !0 });
2006
2081
  });
2007
2082
  }
2008
- var kt = class {
2083
+ var At = class {
2009
2084
  interval = null;
2010
2085
  constructor(e) {
2011
2086
  this.onChange = e;
2012
2087
  }
2013
2088
  clear() {
2014
- this.interval !== null && clearInterval(this.interval), this.interval = null, this.onChange({ ...wt });
2089
+ this.interval !== null && clearInterval(this.interval), this.interval = null, this.onChange({ ...Tt });
2015
2090
  }
2016
2091
  sync(e) {
2017
2092
  this.clear();
@@ -2019,22 +2094,22 @@ var kt = class {
2019
2094
  this.onChange(t), t.delayRemainingMs !== null && (this.interval = setInterval(() => {
2020
2095
  let t = $(e);
2021
2096
  this.onChange(t), t.delayRemainingMs === null && this.clear();
2022
- }, Ct));
2097
+ }, wt));
2023
2098
  }
2024
2099
  };
2025
- function At(e, t = !0) {
2100
+ function jt(e, t = !0) {
2026
2101
  return e.maxAdditionalPages === "unlimited" ? Infinity : (e.maxAdditionalPages ?? 10) + (t ? 1 : 0);
2027
2102
  }
2028
- function jt(e) {
2103
+ function Mt(e) {
2029
2104
  return `${typeof e}:${String(e)}`;
2030
2105
  }
2031
- function Mt(e, t) {
2106
+ function Nt(e, t) {
2032
2107
  if (!Number.isInteger(e) || e <= 0) throw TypeError(`Vibe ${t} must be a positive integer.`);
2033
2108
  }
2034
- function Nt(e) {
2109
+ function Pt(e) {
2035
2110
  if (!e) return;
2036
- if (Mt(e.pageSize, "autofill pageSize"), e.strategy === "frontend") {
2037
- Et(e, "frontend autofill");
2111
+ if (Nt(e.pageSize, "autofill pageSize"), e.strategy === "frontend") {
2112
+ Dt(e, "frontend autofill");
2038
2113
  let t = e.maxAdditionalPages;
2039
2114
  if (t !== void 0 && t !== "unlimited" && (!Number.isInteger(t) || t < 0)) throw TypeError("Vibe autofill maxAdditionalPages must be a non-negative integer or \"unlimited\".");
2040
2115
  return;
@@ -2046,7 +2121,7 @@ function Nt(e) {
2046
2121
  if (t.pageSize !== e.pageSize) throw TypeError("Vibe backend autofill initialSession pageSize must match autofill pageSize.");
2047
2122
  }
2048
2123
  }
2049
- function Pt(e, t, n = !0) {
2124
+ function Ft(e, t, n = !0) {
2050
2125
  if (!e) return {
2051
2126
  cycleId: null,
2052
2127
  delayRemainingMs: null,
@@ -2080,7 +2155,7 @@ function Pt(e, t, n = !0) {
2080
2155
  strategy: e.strategy
2081
2156
  };
2082
2157
  }
2083
- function Ft(e) {
2158
+ function It(e) {
2084
2159
  return [
2085
2160
  "cancelling",
2086
2161
  "filling",
@@ -2088,9 +2163,9 @@ function Ft(e) {
2088
2163
  "waiting"
2089
2164
  ].includes(e.status);
2090
2165
  }
2091
- async function It(e, t, n) {
2166
+ async function Lt(e, t, n) {
2092
2167
  let r = t.autofill;
2093
- if (!Ft(r) || !r.cycleId) return;
2168
+ if (!It(r) || !r.cycleId) return;
2094
2169
  let i = {
2095
2170
  cycleId: r.cycleId,
2096
2171
  feedKey: r.feedKey ?? "",
@@ -2103,20 +2178,20 @@ async function It(e, t, n) {
2103
2178
  throw r.error = e, r.status = "error", e;
2104
2179
  }
2105
2180
  }
2106
- function Lt(e, t, n) {
2181
+ function Rt(e, t, n) {
2107
2182
  return e?.strategy === "backend" && t.feedKey === e.feedKey && t.sessionId === n.sessionId;
2108
2183
  }
2109
- 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 }) {
2110
- let u = [], d = [...e], f = /* @__PURE__ */ new Set(), p = r ?? At(o), m = t, h = t, g = 0, _;
2184
+ 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 }) {
2185
+ let u = [], d = [...e], f = /* @__PURE__ */ new Set(), p = r ?? jt(o), m = t, h = t, g = 0, _;
2111
2186
  for (; g < p;) {
2112
- let e = jt(m);
2187
+ let e = Mt(m);
2113
2188
  if (f.has(e)) throw Error("Vibe autofill received a repeated cursor.");
2114
- f.add(e), await Ot({
2115
- delayMs: Dt(c + g, o),
2189
+ f.add(e), await kt({
2190
+ delayMs: Ot(c + g, o),
2116
2191
  onChange: i,
2117
2192
  signal: l
2118
2193
  });
2119
- let t = bt(await n({
2194
+ let t = xt(await n({
2120
2195
  cursor: m,
2121
2196
  signal: l
2122
2197
  }));
@@ -2156,30 +2231,30 @@ async function Rt({ existingItems: e, initialCursor: t, loadPage: n, maximumRequ
2156
2231
  total: _
2157
2232
  };
2158
2233
  }
2159
- var zt = 100;
2160
- function Bt(e, t) {
2234
+ var Bt = 100;
2235
+ function Vt(e, t) {
2161
2236
  if (!Number.isFinite(t) || t <= 0) throw TypeError(`Vibe ${e} must be a positive number.`);
2162
2237
  }
2163
- function Vt(e, t, n) {
2238
+ function Ht(e, t, n) {
2164
2239
  return Math.min(n, Math.max(t, e));
2165
2240
  }
2166
- function Ht(e) {
2241
+ function Ut(e) {
2167
2242
  if (!e) return;
2168
2243
  let t = e.minSpeedPxPerSecond ?? 20, n = e.maxSpeedPxPerSecond ?? 240;
2169
- if (Bt("autoScroll.minSpeedPxPerSecond", t), Bt("autoScroll.maxSpeedPxPerSecond", n), t > n) throw TypeError("Vibe autoScroll.minSpeedPxPerSecond cannot exceed maxSpeedPxPerSecond.");
2170
- e.speedPxPerSecond !== void 0 && Bt("autoScroll.speedPxPerSecond", e.speedPxPerSecond);
2244
+ if (Vt("autoScroll.minSpeedPxPerSecond", t), Vt("autoScroll.maxSpeedPxPerSecond", n), t > n) throw TypeError("Vibe autoScroll.minSpeedPxPerSecond cannot exceed maxSpeedPxPerSecond.");
2245
+ e.speedPxPerSecond !== void 0 && Vt("autoScroll.speedPxPerSecond", e.speedPxPerSecond);
2171
2246
  }
2172
- function Ut(e) {
2247
+ function Wt(e) {
2173
2248
  let t = e?.minSpeedPxPerSecond ?? 20, n = e?.maxSpeedPxPerSecond ?? 240;
2174
2249
  return {
2175
2250
  enabled: e?.enabled ?? !1,
2176
2251
  maxSpeedPxPerSecond: n,
2177
2252
  minSpeedPxPerSecond: t,
2178
2253
  paused: !1,
2179
- speedPxPerSecond: Vt(e?.speedPxPerSecond ?? 80, t, n)
2254
+ speedPxPerSecond: Ht(e?.speedPxPerSecond ?? 80, t, n)
2180
2255
  };
2181
2256
  }
2182
- var Wt = class {
2257
+ var Gt = class {
2183
2258
  frame = null;
2184
2259
  lastTimestamp = null;
2185
2260
  mounted = !1;
@@ -2199,9 +2274,9 @@ var Wt = class {
2199
2274
  this.options.state.enabled && (this.options.state.paused = e, this.lastTimestamp = null, e ? this.cancelFrame() : this.schedule());
2200
2275
  }
2201
2276
  setSpeed(e) {
2202
- Bt("auto-scroll speed", e);
2277
+ Vt("auto-scroll speed", e);
2203
2278
  let t = this.options.state;
2204
- t.speedPxPerSecond = Vt(e, t.minSpeedPxPerSecond, t.maxSpeedPxPerSecond);
2279
+ t.speedPxPerSecond = Ht(e, t.minSpeedPxPerSecond, t.maxSpeedPxPerSecond);
2205
2280
  }
2206
2281
  tick = (e) => {
2207
2282
  this.frame = null;
@@ -2213,7 +2288,7 @@ var Wt = class {
2213
2288
  return;
2214
2289
  }
2215
2290
  if (this.lastTimestamp !== null) {
2216
- let r = Math.min(zt, Math.max(0, e - this.lastTimestamp)), i = Math.max(0, n.scrollHeight - n.clientHeight);
2291
+ let r = Math.min(Bt, Math.max(0, e - this.lastTimestamp)), i = Math.max(0, n.scrollHeight - n.clientHeight);
2217
2292
  n.scrollTop = Math.min(i, n.scrollTop + t.speedPxPerSecond * r / 1e3);
2218
2293
  }
2219
2294
  this.lastTimestamp = e, this.schedule();
@@ -2227,7 +2302,7 @@ var Wt = class {
2227
2302
  };
2228
2303
  //#endregion
2229
2304
  //#region src/core/backendAutofill.ts
2230
- async function Gt(e, t, n, r) {
2305
+ async function Kt(e, t, n, r) {
2231
2306
  let i = await e.onUnderfilled(n);
2232
2307
  if (!r()) return;
2233
2308
  if (!i.sessionId.trim()) throw TypeError("Vibe backend autofill requires a sessionId.");
@@ -2241,45 +2316,19 @@ async function Gt(e, t, n, r) {
2241
2316
  status: "waiting"
2242
2317
  });
2243
2318
  }
2244
- function Kt(e, t) {
2319
+ function qt(e, t) {
2245
2320
  ["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);
2246
2321
  }
2247
- function qt(e, t, n) {
2248
- let r = t.autofill;
2249
- 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);
2250
- }
2251
2322
  function Jt(e, t, n) {
2252
- return e?.strategy !== "backend" || n.feedKey !== e.feedKey || n.pageSize !== e.pageSize ? !1 : (t.autofill = Pt(e, n), Kt(t, n), !0);
2253
- }
2254
- var Yt = 1.5;
2255
- function Xt(e) {
2256
- let t = Math.min(e.screenWidth, e.screenHeight);
2257
- if (t > 0 && t < 600) return !0;
2258
- let n = Math.min(e.viewportWidth, e.viewportHeight), r = t >= n * Yt;
2259
- return !e.hasHover && n > 0 && n < 600 && r;
2260
- }
2261
- function Zt(e) {
2262
- return Xt(e) ? "reel" : "masonry";
2263
- }
2264
- function Qt(e) {
2265
- let t = e.ownerDocument.defaultView, n = e.ownerDocument.documentElement;
2266
- return {
2267
- hasHover: typeof t?.matchMedia == "function" && t.matchMedia("(hover: hover)").matches,
2268
- screenHeight: t?.screen.height ?? 0,
2269
- screenWidth: t?.screen.width ?? 0,
2270
- viewportHeight: n.clientHeight,
2271
- viewportWidth: n.clientWidth
2272
- };
2273
- }
2274
- function $t(e) {
2275
- return Xt(Qt(e));
2323
+ let r = t.autofill;
2324
+ 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);
2276
2325
  }
2277
- function en(e) {
2278
- return Zt(Qt(e));
2326
+ function Yt(e, t, n) {
2327
+ return e?.strategy !== "backend" || n.feedKey !== e.feedKey || n.pageSize !== e.pageSize ? !1 : (t.autofill = Ft(e, n), qt(t, n), !0);
2279
2328
  }
2280
2329
  //#endregion
2281
2330
  //#region src/core/initialAutofill.ts
2282
- async function tn({ cycleId: e, isCurrent: t, onLastCursor: n, options: r, signal: i, state: a }) {
2331
+ async function Xt({ cycleId: e, isCurrent: t, onLastCursor: n, options: r, signal: i, state: a }) {
2283
2332
  let o = r.autofill;
2284
2333
  if (!o) return;
2285
2334
  let s = a.items.length;
@@ -2292,7 +2341,7 @@ async function tn({ cycleId: e, isCurrent: t, onLastCursor: n, options: r, signa
2292
2341
  return;
2293
2342
  }
2294
2343
  if (o.strategy === "backend") {
2295
- await Gt(o, a, {
2344
+ await Kt(o, a, {
2296
2345
  cycleId: e,
2297
2346
  feedKey: o.feedKey,
2298
2347
  items: [...a.items],
@@ -2309,11 +2358,11 @@ async function tn({ cycleId: e, isCurrent: t, onLastCursor: n, options: r, signa
2309
2358
  a.autofill.status = "exhausted";
2310
2359
  return;
2311
2360
  }
2312
- let c = await Rt({
2361
+ let c = await zt({
2313
2362
  existingItems: a.items,
2314
2363
  initialCursor: a.next,
2315
2364
  loadPage: r.loadPage,
2316
- maximumRequests: At(o, !1),
2365
+ maximumRequests: jt(o, !1),
2317
2366
  onDelayChange: (e) => {
2318
2367
  t() && Object.assign(a.autofill, e);
2319
2368
  },
@@ -2334,13 +2383,13 @@ async function tn({ cycleId: e, isCurrent: t, onLastCursor: n, options: r, signa
2334
2383
  }
2335
2384
  //#endregion
2336
2385
  //#region src/core/fill.ts
2337
- function nn(e) {
2386
+ function Zt(e) {
2338
2387
  return "pages" in e ? { pages: e.pages } : { until: "end" };
2339
2388
  }
2340
- function rn(e) {
2389
+ function Qt(e) {
2341
2390
  return `${typeof e}:${String(e)}`;
2342
2391
  }
2343
- function an(e) {
2392
+ function $t(e) {
2344
2393
  if (!e || typeof e != "object") throw TypeError("Vibe fill target must be an object.");
2345
2394
  if ("pages" in e) {
2346
2395
  if (!Number.isInteger(e.pages) || e.pages <= 0) throw TypeError("Vibe fill pages must be a positive integer.");
@@ -2349,20 +2398,20 @@ function an(e) {
2349
2398
  if ("until" in e && e.until === "end") return { until: "end" };
2350
2399
  throw TypeError("Vibe fill target must be { pages } or { until: 'end' }.");
2351
2400
  }
2352
- function on(e) {
2401
+ function en(e) {
2353
2402
  if (!e) return;
2354
2403
  if (e.strategy === "frontend") {
2355
- Et(e, "frontend fill");
2404
+ Dt(e, "frontend fill");
2356
2405
  return;
2357
2406
  }
2358
2407
  if (!e.feedKey.trim()) throw TypeError("Vibe backend fill requires a feedKey.");
2359
2408
  let t = e.initialSession;
2360
2409
  if (t) {
2361
2410
  if (t.feedKey !== e.feedKey) throw TypeError("Vibe backend fill initialSession feedKey must match fill feedKey.");
2362
- an(t.target);
2411
+ $t(t.target);
2363
2412
  }
2364
2413
  }
2365
- function sn(e, t, n = !0) {
2414
+ function tn(e, t, n = !0) {
2366
2415
  let r = e?.strategy === "backend" && n ? e.initialSession : void 0, i = t ?? r, a = $(i?.nextRequestAt);
2367
2416
  return {
2368
2417
  completedPages: i?.completedPages ?? 0,
@@ -2376,10 +2425,10 @@ function sn(e, t, n = !0) {
2376
2425
  sessionId: i?.sessionId ?? null,
2377
2426
  status: i?.status ?? "idle",
2378
2427
  strategy: e?.strategy ?? null,
2379
- target: i ? nn(i.target) : null
2428
+ target: i ? Zt(i.target) : null
2380
2429
  };
2381
2430
  }
2382
- function cn(e) {
2431
+ function nn(e) {
2383
2432
  return [
2384
2433
  "cancelling",
2385
2434
  "filling",
@@ -2387,17 +2436,17 @@ function cn(e) {
2387
2436
  "waiting"
2388
2437
  ].includes(e.status);
2389
2438
  }
2390
- async function ln({ existingItems: e, initialCursor: t, loadPage: n, onDelayChange: r, onProgress: i, options: a, signal: o, target: s }) {
2439
+ async function rn({ existingItems: e, initialCursor: t, loadPage: n, onDelayChange: r, onProgress: i, options: a, signal: o, target: s }) {
2391
2440
  let c = [], l = [...e], u = /* @__PURE__ */ new Set(), d = 0, f = t, p = t, m = 0, h;
2392
2441
  for (; p !== null;) {
2393
- let e = rn(f);
2442
+ let e = Qt(f);
2394
2443
  if (u.has(e)) throw Error("Vibe fill received a repeated cursor.");
2395
- u.add(e), await Ot({
2396
- delayMs: Dt(d, a),
2444
+ u.add(e), await kt({
2445
+ delayMs: Ot(d, a),
2397
2446
  onChange: r,
2398
2447
  signal: o
2399
2448
  });
2400
- let t = bt(await n({
2449
+ let t = xt(await n({
2401
2450
  cursor: f,
2402
2451
  signal: o
2403
2452
  }));
@@ -2439,7 +2488,7 @@ async function ln({ existingItems: e, initialCursor: t, loadPage: n, onDelayChan
2439
2488
  }
2440
2489
  //#endregion
2441
2490
  //#region src/core/backendFill.ts
2442
- async function un(e, t, n, r) {
2491
+ async function an(e, t, n, r) {
2443
2492
  let i = await e.onStart(n);
2444
2493
  if (r()) {
2445
2494
  if (!i.sessionId.trim()) throw TypeError("Vibe backend fill requires a sessionId.");
@@ -2453,22 +2502,22 @@ async function un(e, t, n, r) {
2453
2502
  });
2454
2503
  }
2455
2504
  }
2456
- function dn(e, t, n) {
2505
+ function on(e, t, n) {
2457
2506
  return e?.strategy === "backend" && n.feedKey === e.feedKey && n.sessionId === t.fill.sessionId;
2458
2507
  }
2459
- function fn(e) {
2508
+ function sn(e) {
2460
2509
  return Number.isInteger(e.completedPages) && e.completedPages >= 0 && Number.isInteger(e.received) && e.received >= 0 && Number.isInteger(e.sequence) && e.sequence >= 0;
2461
2510
  }
2462
- function pn(e, t) {
2511
+ function cn(e, t) {
2463
2512
  if (!["complete", "exhausted"].includes(t.status)) return !0;
2464
2513
  let n = e.fill.target;
2465
2514
  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;
2466
2515
  }
2467
- function mn(e, t, n) {
2516
+ function ln(e, t, n) {
2468
2517
  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));
2469
2518
  }
2470
- function hn(e, t, n, r) {
2471
- return !dn(e, t, n) || !fn(n) || n.sequence <= t.fill.sequence || ["cancelled", "cancelling"].includes(t.fill.status) || !pn(t, n) ? !1 : (mn(t, n, r), Object.assign(t.fill, {
2519
+ function un(e, t, n, r) {
2520
+ return !on(e, t, n) || !sn(n) || n.sequence <= t.fill.sequence || ["cancelled", "cancelling"].includes(t.fill.status) || !cn(t, n) ? !1 : (ln(t, n, r), Object.assign(t.fill, {
2472
2521
  ...$(n.status === "waiting" ? n.nextRequestAt : null),
2473
2522
  completedPages: n.completedPages,
2474
2523
  error: n.error ?? null,
@@ -2477,41 +2526,41 @@ function hn(e, t, n, r) {
2477
2526
  status: n.status
2478
2527
  }), !0);
2479
2528
  }
2480
- function gn(e, t, n, r) {
2529
+ function dn(e, t, n, r) {
2481
2530
  if (e?.strategy !== "backend" || n.feedKey !== e.feedKey) return !1;
2482
2531
  let i = t.fill;
2483
- return t.fill = sn(e, n), !fn(n) || !pn(t, n) ? (t.fill = i, !1) : (mn(t, n, r), !0);
2532
+ return t.fill = tn(e, n), !sn(n) || !cn(t, n) ? (t.fill = i, !1) : (ln(t, n, r), !0);
2484
2533
  }
2485
2534
  //#endregion
2486
2535
  //#region src/core/fillController.ts
2487
- var _n = class {
2536
+ var fn = class {
2488
2537
  abortController = null;
2489
2538
  cycle = 0;
2490
2539
  delayCountdown;
2491
2540
  requestVersion = 0;
2492
2541
  constructor(e) {
2493
- this.options = e, this.delayCountdown = new kt((e) => {
2542
+ this.options = e, this.delayCountdown = new At((e) => {
2494
2543
  Object.assign(this.options.state.fill, e);
2495
2544
  }), this.syncBackendCountdown();
2496
2545
  }
2497
2546
  isActive() {
2498
- return cn(this.options.state.fill);
2547
+ return nn(this.options.state.fill);
2499
2548
  }
2500
2549
  applyUpdate(e) {
2501
- let t = hn(this.options.fill, this.options.state, e, this.options.onLastCursor);
2550
+ let t = un(this.options.fill, this.options.state, e, this.options.onLastCursor);
2502
2551
  return t && this.syncBackendCountdown(), t;
2503
2552
  }
2504
2553
  restoreSession(e) {
2505
- let t = gn(this.options.fill, this.options.state, e, this.options.onLastCursor);
2554
+ let t = dn(this.options.fill, this.options.state, e, this.options.onLastCursor);
2506
2555
  return t && this.syncBackendCountdown(), t;
2507
2556
  }
2508
2557
  async start(e) {
2509
2558
  let t = this.options.fill;
2510
2559
  if (!t) throw Error("Vibe fill is not configured.");
2511
2560
  if (this.isActive()) throw Error("Vibe fill is already active.");
2512
- let n = an(e), r = `vibe-fill-${Date.now().toString(36)}-${++this.cycle}`;
2561
+ let n = $t(e), r = `vibe-fill-${Date.now().toString(36)}-${++this.cycle}`;
2513
2562
  if (this.options.state.fill = {
2514
- ...sn(t, void 0, !1),
2563
+ ...tn(t, void 0, !1),
2515
2564
  cycleId: r,
2516
2565
  status: "filling",
2517
2566
  target: n
@@ -2522,7 +2571,7 @@ var _n = class {
2522
2571
  let i = ++this.requestVersion, a = new AbortController();
2523
2572
  this.abortController = a;
2524
2573
  try {
2525
- t.strategy === "frontend" ? await this.startFrontend(t, n, a, i) : (await un(t, this.options.state, {
2574
+ t.strategy === "frontend" ? await this.startFrontend(t, n, a, i) : (await an(t, this.options.state, {
2526
2575
  cycleId: r,
2527
2576
  feedKey: t.feedKey,
2528
2577
  items: [...this.options.state.items],
@@ -2540,7 +2589,7 @@ var _n = class {
2540
2589
  }
2541
2590
  async cancel() {
2542
2591
  let { fill: e, state: t } = this.options;
2543
- if (!cn(t.fill) || !t.fill.cycleId) return;
2592
+ if (!nn(t.fill) || !t.fill.cycleId) return;
2544
2593
  let n = {
2545
2594
  cycleId: t.fill.cycleId,
2546
2595
  feedKey: t.fill.feedKey ?? "",
@@ -2554,7 +2603,7 @@ var _n = class {
2554
2603
  }
2555
2604
  }
2556
2605
  reset() {
2557
- this.abortLocalRequest(), this.delayCountdown.clear(), this.options.state.fill = sn(this.options.fill, void 0, !1);
2606
+ this.abortLocalRequest(), this.delayCountdown.clear(), this.options.state.fill = tn(this.options.fill, void 0, !1);
2558
2607
  }
2559
2608
  destroy() {
2560
2609
  this.abortLocalRequest(), this.delayCountdown.clear();
@@ -2570,7 +2619,7 @@ var _n = class {
2570
2619
  if (!i) throw Error("Vibe frontend fill requires loadPage.");
2571
2620
  let a = this.options.state;
2572
2621
  a.isLoadingMore = !0;
2573
- let o = await ln({
2622
+ let o = await rn({
2574
2623
  existingItems: a.items,
2575
2624
  initialCursor: a.next,
2576
2625
  loadPage: i,
@@ -2597,7 +2646,7 @@ var _n = class {
2597
2646
  };
2598
2647
  //#endregion
2599
2648
  //#region src/core/feedFooter.ts
2600
- function vn(e) {
2649
+ function pn(e) {
2601
2650
  return {
2602
2651
  cancelAutofill: () => e.cancelAutofill(),
2603
2652
  loadMore: () => e.loadNext(),
@@ -2605,45 +2654,45 @@ function vn(e) {
2605
2654
  retryEnd: () => e.retryEnd()
2606
2655
  };
2607
2656
  }
2608
- function yn(e) {
2657
+ function mn(e) {
2609
2658
  if (!Number.isFinite(e) || e <= 0) throw TypeError("Vibe reelAutoAdvance.intervalMs must be a positive number.");
2610
2659
  }
2611
- function bn(e) {
2612
- e?.intervalMs !== void 0 && yn(e.intervalMs);
2660
+ function hn(e) {
2661
+ e?.intervalMs !== void 0 && mn(e.intervalMs);
2613
2662
  }
2614
- function xn(e) {
2663
+ function gn(e) {
2615
2664
  return {
2616
2665
  enabled: e?.enabled ?? !1,
2617
2666
  includePostItems: e?.includePostItems ?? !1,
2618
2667
  intervalMs: e?.intervalMs ?? 5e3
2619
2668
  };
2620
2669
  }
2621
- function Sn(e, t) {
2670
+ function _n(e, t) {
2622
2671
  if (typeof t == "boolean") {
2623
2672
  e.enabled = t;
2624
2673
  return;
2625
2674
  }
2626
- bn(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);
2675
+ hn(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);
2627
2676
  }
2628
2677
  //#endregion
2629
2678
  //#region src/core/reelInfoSheet.ts
2630
- function Cn(e) {
2679
+ function vn(e) {
2631
2680
  return { enabled: e?.enabled ?? !1 };
2632
2681
  }
2633
- function wn(e, t, n) {
2682
+ function yn(e, t, n) {
2634
2683
  if (n && !t) throw Error("Vibe cannot enable reelInfoSheet without a configured component.");
2635
2684
  e.enabled = n;
2636
2685
  }
2637
2686
  //#endregion
2638
2687
  //#region src/core/initialRuntimeState.ts
2639
- function Tn(e, t) {
2688
+ function bn(e, t) {
2640
2689
  let n = e.initialPage;
2641
2690
  return {
2642
2691
  activeReelPostId: null,
2643
- autoScroll: Ut(e.autoScroll),
2644
- autofill: Pt(e.autofill),
2692
+ autoScroll: Wt(e.autoScroll),
2693
+ autofill: Ft(e.autofill),
2645
2694
  error: null,
2646
- fill: sn(e.fill),
2695
+ fill: tn(e.fill),
2647
2696
  infiniteScroll: e.infiniteScroll ?? !0,
2648
2697
  isLoading: !n,
2649
2698
  isLoadingMore: !1,
@@ -2652,8 +2701,8 @@ function Tn(e, t) {
2652
2701
  loadMoreLocked: !1,
2653
2702
  next: n?.next ?? null,
2654
2703
  nextPageError: null,
2655
- reelAutoAdvance: xn(e.reelAutoAdvance),
2656
- reelInfoSheet: Cn(e.reelInfoSheet),
2704
+ reelAutoAdvance: gn(e.reelAutoAdvance),
2705
+ reelInfoSheet: vn(e.reelInfoSheet),
2657
2706
  reelInfoSheetOverlay: !1,
2658
2707
  reelMediaSource: "original",
2659
2708
  reelOrigin: null,
@@ -2661,6 +2710,116 @@ function Tn(e, t) {
2661
2710
  };
2662
2711
  }
2663
2712
  //#endregion
2713
+ //#region src/core/itemPlacement.ts
2714
+ function xn(e, t) {
2715
+ let n = new Set(t);
2716
+ return e.flatMap((e, t) => n.has(e.postId) ? [{
2717
+ index: t,
2718
+ item: e
2719
+ }] : []);
2720
+ }
2721
+ function Sn(e, t) {
2722
+ let n = new Set(t.map(({ item: e }) => e.postId));
2723
+ return e.filter((e) => !n.has(e.postId));
2724
+ }
2725
+ function Cn(e, t) {
2726
+ t.forEach(({ index: e }) => {
2727
+ if (!Number.isInteger(e) || e < 0) throw Error("Vibe item restore indexes must be non-negative integers.");
2728
+ });
2729
+ let n = [...e], r = new Set(e.map((e) => e.postId));
2730
+ return [...t].sort((e, t) => e.index - t.index).forEach(({ index: e, item: t }) => {
2731
+ r.has(t.postId) || (n.splice(Math.min(e, n.length), 0, t), r.add(t.postId));
2732
+ }), n;
2733
+ }
2734
+ //#endregion
2735
+ //#region src/core/itemRemovalController.ts
2736
+ var wn = 20, Tn = class {
2737
+ generation = 0;
2738
+ historyLimit;
2739
+ metadata = /* @__PURE__ */ new WeakMap();
2740
+ state;
2741
+ history = [];
2742
+ itemOrder;
2743
+ stopItemsWatcher;
2744
+ constructor(e) {
2745
+ this.options = e, this.historyLimit = e.historyLimit ?? wn, 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" });
2746
+ }
2747
+ destroy() {
2748
+ this.reset(), this.stopItemsWatcher();
2749
+ }
2750
+ async remove(e) {
2751
+ let t = this.collectOrderedPlacements(e), n = this.createRemoval(t);
2752
+ if (t.length === 0) return n;
2753
+ let r = t.map(({ item: e }) => e.postId), i = this.options.startRemoval(r);
2754
+ if (i > 0 && await new Promise((e) => setTimeout(e, i)), this.metadata.get(n)?.generation !== this.generation) return n;
2755
+ let a = this.state.items.findIndex((e) => e.postId === this.state.activeReelPostId);
2756
+ return this.state.items = Sn(this.state.items, t), this.options.onItemsRemoved(t, a), this.record(n), n;
2757
+ }
2758
+ reset() {
2759
+ this.generation += 1, this.history = [], this.itemOrder = [];
2760
+ }
2761
+ restoreItems(e) {
2762
+ let t = e;
2763
+ if (this.metadata.has(t)) {
2764
+ this.restoreRemoval(t);
2765
+ return;
2766
+ }
2767
+ let n = Cn(this.state.items, e);
2768
+ this.registerExternalPlacements(e), this.state.items = n;
2769
+ }
2770
+ restoreRemoval(e) {
2771
+ let t = this.metadata.get(e);
2772
+ if (!t) throw TypeError("Vibe removal does not belong to this instance.");
2773
+ return t.generation !== this.generation || t.restored ? !1 : (t.restored = !0, this.removeFromHistory(e), this.restoreOrderedPlacements(e));
2774
+ }
2775
+ undoLast() {
2776
+ for (; this.history.length > 0;) {
2777
+ let e = this.history.pop();
2778
+ if (this.restoreRemoval(e)) return e;
2779
+ }
2780
+ return null;
2781
+ }
2782
+ appendUnknownItems(e) {
2783
+ let t = new Set(this.itemOrder);
2784
+ e.forEach(({ postId: e }) => {
2785
+ t.has(e) || (this.itemOrder.push(e), t.add(e));
2786
+ });
2787
+ }
2788
+ collectOrderedPlacements(e) {
2789
+ let t = new Map(this.itemOrder.map((e, t) => [e, t]));
2790
+ return xn(this.state.items, e).map((e) => ({
2791
+ index: t.get(e.item.postId) ?? e.index,
2792
+ item: e.item
2793
+ }));
2794
+ }
2795
+ createRemoval(e) {
2796
+ let t = Object.freeze(e.map((e) => Object.freeze({ ...e })));
2797
+ return this.metadata.set(t, {
2798
+ generation: this.generation,
2799
+ restored: e.length === 0
2800
+ }), t;
2801
+ }
2802
+ record(e) {
2803
+ this.historyLimit !== 0 && (this.history.push(e), this.history.length > this.historyLimit && this.history.shift());
2804
+ }
2805
+ registerExternalPlacements(e) {
2806
+ let t = new Set(this.itemOrder);
2807
+ [...e].sort((e, t) => e.index - t.index).forEach(({ index: e, item: n }) => {
2808
+ t.has(n.postId) || (this.itemOrder.splice(Math.min(e, this.itemOrder.length), 0, n.postId), t.add(n.postId));
2809
+ });
2810
+ }
2811
+ removeFromHistory(e) {
2812
+ let t = this.history.indexOf(e);
2813
+ t >= 0 && this.history.splice(t, 1);
2814
+ }
2815
+ restoreOrderedPlacements(e) {
2816
+ let t = new Set(this.state.items.map(({ postId: e }) => e)), n = e.map(({ item: e }) => e).filter(({ postId: e }) => !t.has(e));
2817
+ if (n.length === 0) return !1;
2818
+ let r = new Map(this.itemOrder.map((e, t) => [e, t]));
2819
+ return this.state.items = [...this.state.items, ...n].sort((e, t) => (r.get(e.postId) ?? 2 ** 53 - 1) - (r.get(t.postId) ?? 2 ** 53 - 1)), !0;
2820
+ }
2821
+ };
2822
+ //#endregion
2664
2823
  //#region src/core/options.ts
2665
2824
  function En(e, t) {
2666
2825
  if (t) {
@@ -2668,22 +2827,83 @@ function En(e, t) {
2668
2827
  if (t.background !== void 0 && t.background !== "default" && t.background !== "transparent") throw TypeError(`Vibe ${e} background must be "default" or "transparent".`);
2669
2828
  }
2670
2829
  }
2671
- function Dn(e) {
2672
- if (Ht(e.autoScroll), En("cardHeader", e.cardHeader), En("cardFooter", e.cardFooter), Nt(e.autofill), on(e.fill), bn(e.reelAutoAdvance), !e.initialPage && !e.loadPage) throw TypeError("Vibe requires either initialPage or loadPage.");
2830
+ function Dn(e, t) {
2831
+ if (t) {
2832
+ if (t.background !== void 0 && t.background !== "default" && t.background !== "transparent") throw TypeError(`Vibe mediaCard ${e} background must be "default" or "transparent".`);
2833
+ 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.`);
2834
+ }
2835
+ }
2836
+ function On(e) {
2837
+ if (Ut(e.autoScroll), En("cardHeader", e.cardHeader), En("cardFooter", e.cardFooter), Dn("header", e.mediaCard?.header), Dn("footer", e.mediaCard?.footer), Pt(e.autofill), en(e.fill), hn(e.reelAutoAdvance), e.removalHistoryLimit !== void 0 && (!Number.isInteger(e.removalHistoryLimit) || e.removalHistoryLimit < 0)) throw TypeError("Vibe removalHistoryLimit must be a non-negative integer.");
2838
+ if (!e.initialPage && !e.loadPage) throw TypeError("Vibe requires either initialPage or loadPage.");
2673
2839
  if (e.initialPage?.next !== null && !e.loadPage) throw TypeError("Vibe requires loadPage when initialPage has a next cursor.");
2674
2840
  if (e.fill?.strategy === "frontend" && !e.loadPage) throw TypeError("Vibe frontend fill requires loadPage.");
2675
2841
  if (e.fill?.strategy === "backend" && e.fill.initialSession && !e.initialPage) throw TypeError("Vibe backend fill restoration requires initialPage.");
2676
2842
  }
2677
- function On(e) {
2843
+ function kn(e) {
2678
2844
  if (typeof e != "string") return e;
2679
2845
  if (typeof document > "u") throw Error("Vibe cannot resolve a selector without a document.");
2680
2846
  let t = document.querySelector(e);
2681
2847
  if (!t) throw Error(`Vibe target not found: ${e}`);
2682
2848
  return t;
2683
2849
  }
2850
+ var An = 1.5;
2851
+ function jn(e) {
2852
+ let t = Math.min(e.screenWidth, e.screenHeight);
2853
+ if (t > 0 && t < 600) return !0;
2854
+ let n = Math.min(e.viewportWidth, e.viewportHeight), r = t >= n * An;
2855
+ return !e.hasHover && n > 0 && n < 600 && r;
2856
+ }
2857
+ function Mn(e) {
2858
+ return jn(e) ? "reel" : "masonry";
2859
+ }
2860
+ function Nn(e) {
2861
+ let t = e.ownerDocument.defaultView, n = e.ownerDocument.documentElement;
2862
+ return {
2863
+ hasHover: typeof t?.matchMedia == "function" && t.matchMedia("(hover: hover)").matches,
2864
+ screenHeight: t?.screen.height ?? 0,
2865
+ screenWidth: t?.screen.width ?? 0,
2866
+ viewportHeight: n.clientHeight,
2867
+ viewportWidth: n.clientWidth
2868
+ };
2869
+ }
2870
+ function Pn(e) {
2871
+ return jn(Nn(e));
2872
+ }
2873
+ function Fn(e) {
2874
+ return Mn(Nn(e));
2875
+ }
2684
2876
  //#endregion
2685
- //#region src/core/vibeRouting.ts
2686
- var kn = class {
2877
+ //#region src/core/responsiveLayoutController.ts
2878
+ var In = class {
2879
+ layoutMode;
2880
+ resizeObserver = null;
2881
+ target = null;
2882
+ constructor(e, t, n) {
2883
+ this.state = t, this.onFeedLayout = n, this.layoutMode = e;
2884
+ }
2885
+ mount(e) {
2886
+ this.target = e, this.handleResponsiveLayout();
2887
+ let t = e.ownerDocument.defaultView;
2888
+ t?.addEventListener("resize", this.handleResponsiveLayout);
2889
+ let n = t?.ResizeObserver ?? globalThis.ResizeObserver;
2890
+ n !== void 0 && (this.resizeObserver = new n(this.handleResponsiveLayout), this.resizeObserver.observe(e));
2891
+ }
2892
+ destroy() {
2893
+ this.target?.ownerDocument.defaultView?.removeEventListener("resize", this.handleResponsiveLayout), this.resizeObserver?.disconnect(), this.resizeObserver = null, this.target = null;
2894
+ }
2895
+ setLayout(e) {
2896
+ e !== this.layoutMode && (this.layoutMode = e, e === "responsive" ? this.handleResponsiveLayout() : this.applyLayout(e));
2897
+ }
2898
+ applyLayout(e) {
2899
+ e !== this.state.layout && (e === "masonry" && (this.state.activeReelPostId = null, this.onFeedLayout()), this.state.reelOrigin = null, this.state.layout = e);
2900
+ }
2901
+ handleResponsiveLayout = () => {
2902
+ if (!this.target) return;
2903
+ let e = Fn(this.target);
2904
+ this.state.reelInfoSheetOverlay = Pn(this.target), this.state.reelMediaSource = e === "reel" ? "preview" : "original", this.layoutMode === "responsive" && this.applyLayout(e);
2905
+ };
2906
+ }, Ln = class {
2687
2907
  routedReelPostId = null;
2688
2908
  reelRouteIsActive = !1;
2689
2909
  constructor(e, t) {
@@ -2710,7 +2930,7 @@ var kn = class {
2710
2930
  let i = this.reelRouteIsActive ? "replace" : "push";
2711
2931
  this.reelRouteIsActive = !0, this.routedReelPostId = e, this.options.router[i](r);
2712
2932
  }
2713
- }, An = class {
2933
+ }, Rn = class {
2714
2934
  app = null;
2715
2935
  autoScroll;
2716
2936
  autofillDelayCountdown;
@@ -2718,38 +2938,49 @@ var kn = class {
2718
2938
  abortController = null;
2719
2939
  pendingRequest = null;
2720
2940
  requestVersion = 0;
2721
- resizeObserver = null;
2941
+ responsiveLayout;
2722
2942
  routing;
2723
2943
  fillController;
2944
+ itemRemoval;
2724
2945
  surface = null;
2725
2946
  stopStateWatcher = null;
2726
- target = null;
2727
- layoutMode;
2728
2947
  lastLoadedCursor = null;
2729
2948
  state;
2730
2949
  constructor(e) {
2731
- this.options = e, Dn(e), this.layoutMode = e.layout ?? "masonry", this.state = b(Tn(e, this.layoutMode)), this.autoScroll = new Wt({
2950
+ this.options = e, On(e);
2951
+ let t = e.layout ?? "masonry";
2952
+ this.state = b(bn(e, t)), this.autoScroll = new Gt({
2732
2953
  getScrollElement: () => this.surface?.getAutoScrollElement() ?? null,
2733
2954
  state: this.state.autoScroll
2734
- }), this.autofillDelayCountdown = new kt((e) => Object.assign(this.state.autofill, e)), this.syncAutofillCountdown(), this.fillController = new _n({
2955
+ }), this.autofillDelayCountdown = new At((e) => Object.assign(this.state.autofill, e)), this.syncAutofillCountdown(), this.fillController = new fn({
2735
2956
  fill: e.fill,
2736
2957
  loadPage: e.loadPage,
2737
2958
  onLastCursor: (e) => {
2738
2959
  this.lastLoadedCursor = e;
2739
2960
  },
2740
2961
  state: this.state
2741
- }), this.routing = new kn(e.routing, this.state), this.startStateNotifications();
2962
+ }), this.routing = new Ln(e.routing, this.state), this.itemRemoval = new Tn({
2963
+ historyLimit: e.removalHistoryLimit,
2964
+ onItemsRemoved: (e, t) => {
2965
+ this.restoreActiveItemAfterRemoval(e, t);
2966
+ },
2967
+ startRemoval: (e) => this.surface?.startItemRemoval(e) ?? 0,
2968
+ state: this.state
2969
+ }), this.responsiveLayout = new In(t, this.state, () => {
2970
+ this.routing.syncFeed();
2971
+ }), this.startStateNotifications();
2742
2972
  }
2743
2973
  async mount() {
2744
2974
  if (this.app) throw Error("Vibe is already mounted.");
2745
2975
  this.startStateNotifications();
2746
- let e = On(this.options.target);
2747
- this.target = e, this.startResponsiveLayout(), this.app = r(yt, {
2976
+ let e = kn(this.options.target);
2977
+ this.responsiveLayout.mount(e), this.app = r(bt, {
2748
2978
  canRetryEnd: !!this.options.loadPage,
2749
2979
  cardFooter: this.options.cardFooter,
2750
2980
  cardHeader: this.options.cardHeader,
2751
2981
  feedFooter: this.options.feedFooter,
2752
- feedFooterActions: vn(this),
2982
+ feedFooterActions: pn(this),
2983
+ mediaCard: this.options.mediaCard,
2753
2984
  reelInfoSheet: this.options.reelInfoSheet,
2754
2985
  state: this.state,
2755
2986
  onActiveReelChange: (e) => this.setActiveReelPost(e),
@@ -2765,11 +2996,23 @@ var kn = class {
2765
2996
  }), 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();
2766
2997
  }
2767
2998
  destroy() {
2768
- this.autoScroll.destroy(), this.fillController.destroy(), this.cancelRequest(), this.stopResponsiveLayout(), this.stopStateWatcher?.(), this.stopStateWatcher = null, this.app?.unmount(), this.app = null, this.surface = null, this.target = null;
2999
+ 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;
2769
3000
  }
2770
3001
  getState() {
2771
3002
  return F(this.state);
2772
3003
  }
3004
+ removeItems(e) {
3005
+ return this.itemRemoval.remove(e);
3006
+ }
3007
+ restoreItems(e) {
3008
+ this.itemRemoval.restoreItems(e);
3009
+ }
3010
+ restoreRemoval(e) {
3011
+ return this.itemRemoval.restoreRemoval(e);
3012
+ }
3013
+ undoLastRemoval() {
3014
+ return this.itemRemoval.undoLast();
3015
+ }
2773
3016
  nextReelMediaItem() {
2774
3017
  return this.surface?.changeActiveReelMedia(1) ?? !1;
2775
3018
  }
@@ -2795,11 +3038,11 @@ var kn = class {
2795
3038
  this.autoScroll.setSpeed(e);
2796
3039
  }
2797
3040
  applyAutofillUpdate(e) {
2798
- let t = qt(this.options.autofill, this.state, e);
3041
+ let t = Jt(this.options.autofill, this.state, e);
2799
3042
  return t && this.syncAutofillCountdown(), t;
2800
3043
  }
2801
3044
  async cancelAutofill() {
2802
- await It(this.options.autofill, this.state, () => this.cancelRequest());
3045
+ await Lt(this.options.autofill, this.state, () => this.cancelRequest());
2803
3046
  }
2804
3047
  applyFillUpdate(e) {
2805
3048
  return this.fillController.applyUpdate(e);
@@ -2808,11 +3051,11 @@ var kn = class {
2808
3051
  return this.fillController.cancel();
2809
3052
  }
2810
3053
  async fill(e) {
2811
- if (this.pendingRequest || Ft(this.state.autofill)) throw Error("Vibe cannot fill while another page operation is active.");
3054
+ if (this.pendingRequest || It(this.state.autofill)) throw Error("Vibe cannot fill while another page operation is active.");
2812
3055
  await this.fillController.start(e);
2813
3056
  }
2814
3057
  restoreAutofillSession(e) {
2815
- let t = Jt(this.options.autofill, this.state, e);
3058
+ let t = Yt(this.options.autofill, this.state, e);
2816
3059
  return t && this.syncAutofillCountdown(), t;
2817
3060
  }
2818
3061
  restoreFillSession(e) {
@@ -2820,15 +3063,15 @@ var kn = class {
2820
3063
  }
2821
3064
  async loadNext() {
2822
3065
  if (this.pendingRequest) return this.pendingRequest;
2823
- 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);
3066
+ 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);
2824
3067
  }
2825
3068
  async reload() {
2826
3069
  if (!this.options.loadPage) throw Error("Vibe cannot reload without loadPage.");
2827
- 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.state.error = null, this.state.isLoading = !0, this.state.items = [], this.state.next = null, this.state.nextPageError = null, this.state.total = null, this.startRequest(null, !1);
3070
+ 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.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(null, !1);
2828
3071
  }
2829
3072
  async retryEnd() {
2830
3073
  if (this.pendingRequest) return this.pendingRequest;
2831
- 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);
3074
+ 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);
2832
3075
  }
2833
3076
  setInfiniteScroll(e) {
2834
3077
  this.state.infiniteScroll = e, e && p(() => this.surface?.loadIfNearBottom());
@@ -2837,36 +3080,27 @@ var kn = class {
2837
3080
  this.state.loadMoreLocked !== e && (this.state.loadMoreLocked = e, !e && this.state.infiniteScroll && p(() => this.surface?.loadIfNearBottom()));
2838
3081
  }
2839
3082
  setReelAutoAdvance(e) {
2840
- Sn(this.state.reelAutoAdvance, e);
3083
+ _n(this.state.reelAutoAdvance, e);
2841
3084
  }
2842
3085
  setReelInfoSheet(e) {
2843
- wn(this.state.reelInfoSheet, this.options.reelInfoSheet, e);
3086
+ yn(this.state.reelInfoSheet, this.options.reelInfoSheet, e);
2844
3087
  }
2845
3088
  setLayout(e) {
2846
- e !== this.layoutMode && (this.layoutMode = e, e === "responsive" ? this.handleResponsiveLayout() : this.applyLayout(e));
2847
- }
2848
- applyLayout(e) {
2849
- e !== this.state.layout && (e === "masonry" && (this.state.activeReelPostId = null, this.routing.syncFeed()), this.state.reelOrigin = null, this.state.layout = e);
2850
- }
2851
- handleResponsiveLayout = () => {
2852
- if (!this.target) return;
2853
- let e = en(this.target);
2854
- this.state.reelInfoSheetOverlay = $t(this.target), this.state.reelMediaSource = e === "reel" ? "preview" : "original", this.layoutMode === "responsive" && this.applyLayout(e);
2855
- };
2856
- startResponsiveLayout() {
2857
- if (!this.target) return;
2858
- this.handleResponsiveLayout();
2859
- let e = this.target.ownerDocument.defaultView;
2860
- e?.addEventListener("resize", this.handleResponsiveLayout);
2861
- let t = e?.ResizeObserver ?? globalThis.ResizeObserver;
2862
- t !== void 0 && (this.resizeObserver = new t(this.handleResponsiveLayout), this.resizeObserver.observe(this.target));
2863
- }
2864
- stopResponsiveLayout() {
2865
- this.target?.ownerDocument.defaultView?.removeEventListener("resize", this.handleResponsiveLayout), this.resizeObserver?.disconnect(), this.resizeObserver = null;
3089
+ this.responsiveLayout.setLayout(e);
2866
3090
  }
2867
3091
  closeMasonryReel() {
2868
3092
  this.state.reelOrigin === "masonry" && (this.state.activeReelPostId = null, this.state.reelOrigin = null, this.routing.syncFeed());
2869
3093
  }
3094
+ restoreActiveItemAfterRemoval(e, t) {
3095
+ let n = new Set(e.map(({ item: e }) => e.postId));
3096
+ if (this.state.activeReelPostId === null || !n.has(this.state.activeReelPostId)) return;
3097
+ if (this.state.reelOrigin === "masonry") {
3098
+ this.closeMasonryReel();
3099
+ return;
3100
+ }
3101
+ let r = this.state.items[Math.min(Math.max(t, 0), this.state.items.length - 1)];
3102
+ this.state.activeReelPostId = r?.postId ?? null, r ? this.routing.syncReel(r.postId) : this.routing.syncFeed();
3103
+ }
2870
3104
  openMasonryReel(e) {
2871
3105
  this.state.layout === "masonry" && this.state.items.some((t) => t.postId === e) && (this.state.activeReelPostId = e, this.state.reelOrigin = "masonry", this.routing.syncReel(e));
2872
3106
  }
@@ -2883,7 +3117,7 @@ var kn = class {
2883
3117
  this.abortController = i;
2884
3118
  try {
2885
3119
  if (a?.strategy === "frontend") {
2886
- let o = await Rt({
3120
+ let o = await zt({
2887
3121
  existingItems: t ? this.state.items : [],
2888
3122
  initialCursor: e,
2889
3123
  loadPage: n,
@@ -2905,7 +3139,7 @@ var kn = class {
2905
3139
  });
2906
3140
  return;
2907
3141
  }
2908
- let c = bt(await n({
3142
+ let c = xt(await n({
2909
3143
  cursor: e,
2910
3144
  signal: i.signal
2911
3145
  }));
@@ -2920,7 +3154,7 @@ var kn = class {
2920
3154
  this.state.autofill.status = "complete";
2921
3155
  return;
2922
3156
  }
2923
- await Gt(a, this.state, {
3157
+ await Kt(a, this.state, {
2924
3158
  cycleId: o,
2925
3159
  feedKey: a.feedKey,
2926
3160
  items: u.slice(l.length),
@@ -2945,7 +3179,7 @@ var kn = class {
2945
3179
  this.autofillDelayCountdown.clear();
2946
3180
  let t = `vibe-autofill-${Date.now().toString(36)}-${++this.autofillCycle}`;
2947
3181
  return this.state.autofill = {
2948
- ...Pt(e, void 0, !1),
3182
+ ...Ft(e, void 0, !1),
2949
3183
  cycleId: t,
2950
3184
  status: "filling"
2951
3185
  }, t;
@@ -2963,7 +3197,7 @@ var kn = class {
2963
3197
  startInitialAutofill() {
2964
3198
  let e = ++this.requestVersion, t = new AbortController(), n = this.beginAutofillCycle();
2965
3199
  this.abortController = t, this.state.isLoadingMore = !0;
2966
- let r = tn({
3200
+ let r = Xt({
2967
3201
  cycleId: n,
2968
3202
  isCurrent: () => e === this.requestVersion,
2969
3203
  onLastCursor: (e) => {
@@ -2987,8 +3221,8 @@ var kn = class {
2987
3221
  }));
2988
3222
  }
2989
3223
  };
2990
- function jn(e) {
2991
- return new An(e);
3224
+ function zn(e) {
3225
+ return new Rn(e);
2992
3226
  }
2993
3227
  //#endregion
2994
- export { jn as createVibe };
3228
+ export { zn as createVibe };