@wyxos/vibe 5.5.1 → 5.5.2

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
@@ -3031,37 +3031,42 @@ var Mn = class {
3031
3031
  let t = jn(this.options.fill, this.options.state, e, this.options.onLastCursor);
3032
3032
  return t && this.syncBackendCountdown(), t;
3033
3033
  }
3034
- async start(e) {
3035
- let t = this.options.fill;
3036
- if (!t) throw Error("Vibe fill is not configured.");
3034
+ async start(e, t = {}) {
3035
+ let n = this.options.fill;
3036
+ if (!n) throw Error("Vibe fill is not configured.");
3037
3037
  if (this.isActive()) throw Error("Vibe fill is already active.");
3038
- let n = bn(e), r = `vibe-fill-${Date.now().toString(36)}-${++this.cycle}`;
3038
+ let r = bn(e), i = bn(t.target ?? r), a = t.progressOffset ?? {
3039
+ completedPages: 0,
3040
+ received: 0
3041
+ }, o = t.cycleId ?? `vibe-fill-${Date.now().toString(36)}-${++this.cycle}`;
3039
3042
  if (this.options.state.fill = {
3040
- ...Sn(t, void 0, !1),
3041
- cycleId: r,
3043
+ ...Sn(n, void 0, !1),
3044
+ completedPages: a.completedPages,
3045
+ cycleId: o,
3046
+ received: a.received,
3042
3047
  status: "filling",
3043
- target: n
3044
- }, this.options.state.next === null) {
3045
- this.options.state.fill.status = "pages" in n ? "exhausted" : "complete";
3048
+ target: i
3049
+ }, n.strategy === "backend" && this.options.state.next === null) {
3050
+ this.options.state.fill.status = "pages" in r ? "exhausted" : "complete";
3046
3051
  return;
3047
3052
  }
3048
- let i = ++this.requestVersion, a = new AbortController();
3049
- this.abortController = a;
3053
+ let s = ++this.requestVersion, c = new AbortController();
3054
+ this.abortController = c;
3050
3055
  try {
3051
- t.strategy === "frontend" ? await this.startFrontend(t, n, a, i) : (await Tn(t, this.options.state, {
3052
- cycleId: r,
3053
- feedKey: t.feedKey,
3056
+ n.strategy === "frontend" ? await this.startFrontend(n, r, c, s, t.prepareFrontend !== !1, a) : (await Tn(n, this.options.state, {
3057
+ cycleId: o,
3058
+ feedKey: n.feedKey,
3054
3059
  items: [...this.options.state.items],
3055
3060
  next: this.options.state.next,
3056
- signal: a.signal,
3057
- target: n,
3061
+ signal: c.signal,
3062
+ target: r,
3058
3063
  total: this.options.state.total
3059
- }, () => this.isCurrent(i)), this.syncBackendCountdown());
3064
+ }, () => this.isCurrent(s)), this.syncBackendCountdown());
3060
3065
  } catch (e) {
3061
- if (a.signal.aborted || !this.isCurrent(i)) return;
3066
+ if (c.signal.aborted || !this.isCurrent(s)) return;
3062
3067
  throw this.options.state.fill.error = e, this.options.state.fill.status = "error", e;
3063
3068
  } finally {
3064
- this.isCurrent(i) && (this.abortController = null, this.options.state.isLoadingMore = !1);
3069
+ this.isCurrent(s) && (this.abortController = null, this.options.state.isLoadingMore = !1);
3065
3070
  }
3066
3071
  }
3067
3072
  async cancel() {
@@ -3079,6 +3084,22 @@ var Mn = class {
3079
3084
  throw t.fill.error = e, t.fill.status = "error", e;
3080
3085
  }
3081
3086
  }
3087
+ resume(e) {
3088
+ let { fill: t } = this.options.state;
3089
+ if (t.status !== "paused" || !t.target) return Promise.resolve();
3090
+ let n = t.target, r = "pages" in n ? n.pages - t.completedPages : null;
3091
+ if (r !== null && r <= 0) return t.status = "complete", Promise.resolve();
3092
+ let i = r === null ? { until: "end" } : { pages: r };
3093
+ return t.strategy === "backend" ? this.start(i) : this.start(i, {
3094
+ cycleId: t.cycleId ?? void 0,
3095
+ prepareFrontend: e,
3096
+ progressOffset: {
3097
+ completedPages: t.completedPages,
3098
+ received: t.received
3099
+ },
3100
+ target: n
3101
+ });
3102
+ }
3082
3103
  reset() {
3083
3104
  this.abortLocalRequest(), this.delayCountdown.clear(), this.options.state.fill = Sn(this.options.fill, void 0, !1), this.collection = null;
3084
3105
  }
@@ -3091,33 +3112,60 @@ var Mn = class {
3091
3112
  isCurrent(e) {
3092
3113
  return e === this.requestVersion && !["cancelled", "cancelling"].includes(this.options.state.fill.status);
3093
3114
  }
3094
- async startFrontend(e, t, n, r) {
3095
- let i = this.options.loadPage;
3096
- if (!i) throw Error("Vibe frontend fill requires loadPage.");
3097
- let a = this.options.state;
3098
- a.isLoadingMore = !0;
3099
- let o = await wn({
3100
- existingItems: a.items,
3101
- initialCursor: a.next,
3102
- loadPage: i,
3115
+ async startFrontend(e, t, n, r, i, a) {
3116
+ let o = this.options.loadPage;
3117
+ if (!o) throw Error("Vibe frontend fill requires loadPage.");
3118
+ let s = this.options.state;
3119
+ if (s.isLoadingMore = !0, i && this.options.prepareFrontend && (this.options.needsFrontendPreparation?.() ?? !0)) {
3120
+ s.fill.status = "restoring";
3121
+ let e = await this.options.prepareFrontend({
3122
+ isCurrent: () => this.isCurrent(r),
3123
+ onDelayChange: (e) => {
3124
+ this.isCurrent(r) && Object.assign(s.fill, e);
3125
+ },
3126
+ signal: n.signal
3127
+ });
3128
+ if (!this.isCurrent(r)) return;
3129
+ if (e === "paused" || s.loadMoreLocked) {
3130
+ s.fill.status = "paused";
3131
+ return;
3132
+ }
3133
+ s.fill.status = "filling";
3134
+ }
3135
+ if (s.next === null) {
3136
+ s.fill.status = "pages" in t ? "exhausted" : "complete";
3137
+ return;
3138
+ }
3139
+ let c = await wn({
3140
+ existingItems: s.items,
3141
+ initialCursor: s.next,
3142
+ loadPage: o,
3103
3143
  onCollection: (e) => {
3104
- this.isCurrent(r) && (this.collection = e);
3144
+ this.isCurrent(r) && (this.collection = {
3145
+ ...e,
3146
+ completedPages: a.completedPages + e.completedPages,
3147
+ received: a.received + e.received
3148
+ });
3105
3149
  },
3106
3150
  onDelayChange: (e) => {
3107
- this.isCurrent(r) && Object.assign(a.fill, e);
3151
+ this.isCurrent(r) && Object.assign(s.fill, e);
3108
3152
  },
3109
3153
  onProgress: (e) => {
3110
- this.isCurrent(r) && Object.assign(a.fill, e);
3154
+ this.isCurrent(r) && Object.assign(s.fill, {
3155
+ ...e,
3156
+ completedPages: a.completedPages + e.completedPages,
3157
+ received: a.received + e.received
3158
+ });
3111
3159
  },
3112
3160
  options: e,
3113
- shouldPause: () => a.loadMoreLocked,
3161
+ shouldPause: () => s.loadMoreLocked,
3114
3162
  signal: n.signal,
3115
3163
  target: t
3116
3164
  });
3117
- this.isCurrent(r) && (a.items = Z(a.items, o.items), a.next = o.next, o.total !== void 0 && (a.total = o.total), this.options.onLastCursor(o.lastCursor), this.options.onPages(o.pages), Object.assign(a.fill, {
3118
- completedPages: o.completedPages,
3119
- received: o.received,
3120
- status: o.status
3165
+ this.isCurrent(r) && (s.items = Z(s.items, c.items), s.next = c.next, c.total !== void 0 && (s.total = c.total), this.options.onLastCursor(c.lastCursor), this.options.onPages(c.pages), Object.assign(s.fill, {
3166
+ completedPages: a.completedPages + c.completedPages,
3167
+ received: a.received + c.received,
3168
+ status: c.status
3121
3169
  }), this.collection = null);
3122
3170
  }
3123
3171
  commitCollection() {
@@ -3135,8 +3183,21 @@ var Mn = class {
3135
3183
  }
3136
3184
  };
3137
3185
  //#endregion
3186
+ //#region src/core/fillReconciliation.ts
3187
+ async function Nn({ controller: e, isCurrent: t, loadPage: n, onDelayChange: r, setLastCursor: i, signal: a, state: o }) {
3188
+ if (!e.needsReconciliation(o.items)) return "skipped";
3189
+ let s = await e.reconcile({
3190
+ existingItems: o.items,
3191
+ loadPage: n,
3192
+ onDelayChange: r,
3193
+ shouldPause: () => o.loadMoreLocked,
3194
+ signal: a
3195
+ });
3196
+ return t() ? (o.items = Z(o.items, s.items), o.next = s.next, i(s.lastCursor), s.total !== void 0 && (o.total = s.total), e.completeReconciliation(s), s.status) : s.status;
3197
+ }
3198
+ //#endregion
3138
3199
  //#region src/core/feedFooter.ts
3139
- function Nn(e) {
3200
+ function Pn(e) {
3140
3201
  return {
3141
3202
  cancelAutofill: () => e.cancelAutofill(),
3142
3203
  loadMore: () => e.loadNext(),
@@ -3144,38 +3205,38 @@ function Nn(e) {
3144
3205
  retryEnd: () => e.retryEnd()
3145
3206
  };
3146
3207
  }
3147
- function Pn(e) {
3148
- if (!Number.isFinite(e) || e <= 0) throw TypeError("Vibe reelAutoAdvance.intervalMs must be a positive number.");
3149
- }
3150
3208
  function Fn(e) {
3151
- e?.intervalMs !== void 0 && Pn(e.intervalMs);
3209
+ if (!Number.isFinite(e) || e <= 0) throw TypeError("Vibe reelAutoAdvance.intervalMs must be a positive number.");
3152
3210
  }
3153
3211
  function In(e) {
3212
+ e?.intervalMs !== void 0 && Fn(e.intervalMs);
3213
+ }
3214
+ function Ln(e) {
3154
3215
  return {
3155
3216
  enabled: e?.enabled ?? !1,
3156
3217
  includePostItems: e?.includePostItems ?? !1,
3157
3218
  intervalMs: e?.intervalMs ?? 5e3
3158
3219
  };
3159
3220
  }
3160
- function Ln(e, t) {
3221
+ function Rn(e, t) {
3161
3222
  if (typeof t == "boolean") {
3162
3223
  e.enabled = t;
3163
3224
  return;
3164
3225
  }
3165
- Fn(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);
3226
+ In(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);
3166
3227
  }
3167
3228
  //#endregion
3168
3229
  //#region src/core/reelInfoSheet.ts
3169
- function Rn(e) {
3230
+ function zn(e) {
3170
3231
  return { enabled: e?.enabled ?? !1 };
3171
3232
  }
3172
- function zn(e, t, n) {
3233
+ function Bn(e, t, n) {
3173
3234
  if (n && !t) throw Error("Vibe cannot enable reelInfoSheet without a configured component.");
3174
3235
  e.enabled = n;
3175
3236
  }
3176
3237
  //#endregion
3177
3238
  //#region src/core/initialRuntimeState.ts
3178
- function Bn(e, t) {
3239
+ function Vn(e, t) {
3179
3240
  let n = e.initialPage;
3180
3241
  return {
3181
3242
  activeReelPostId: null,
@@ -3193,14 +3254,14 @@ function Bn(e, t) {
3193
3254
  next: n?.next ?? null,
3194
3255
  nextPageError: null,
3195
3256
  phoneMode: !1,
3196
- reelAutoAdvance: In(e.reelAutoAdvance),
3257
+ reelAutoAdvance: Ln(e.reelAutoAdvance),
3197
3258
  reelForward: {
3198
3259
  error: null,
3199
3260
  status: "idle"
3200
3261
  },
3201
3262
  reelForwardIndex: null,
3202
3263
  reelForwardItem: null,
3203
- reelInfoSheet: Rn(e.reelInfoSheet),
3264
+ reelInfoSheet: zn(e.reelInfoSheet),
3204
3265
  reelInfoSheetOverlay: !1,
3205
3266
  reelMediaSource: "original",
3206
3267
  reelOrigin: null,
@@ -3209,20 +3270,20 @@ function Bn(e, t) {
3209
3270
  }
3210
3271
  //#endregion
3211
3272
  //#region src/core/options.ts
3212
- function Vn(e, t) {
3273
+ function Hn(e, t) {
3213
3274
  if (t) {
3214
3275
  if (!Number.isFinite(t.height) || t.height <= 0) throw TypeError(`Vibe ${e} height must be a positive number.`);
3215
3276
  if (t.background !== void 0 && t.background !== "default" && t.background !== "transparent") throw TypeError(`Vibe ${e} background must be "default" or "transparent".`);
3216
3277
  }
3217
3278
  }
3218
- function Hn(e, t) {
3279
+ function Un(e, t) {
3219
3280
  if (t) {
3220
3281
  if (t.background !== void 0 && t.background !== "default" && t.background !== "transparent") throw TypeError(`Vibe mediaCard ${e} background must be "default" or "transparent".`);
3221
3282
  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.`);
3222
3283
  }
3223
3284
  }
3224
- function Un(e) {
3225
- if (un(e.autoScroll), Vn("cardHeader", e.cardHeader), Vn("cardFooter", e.cardFooter), Hn("header", e.mediaCard?.header), Hn("footer", e.mediaCard?.footer), $t(e.autofill), xn(e.fill), J(e.masonry), Fn(e.reelAutoAdvance), e.removalReconciliation) {
3285
+ function Wn(e) {
3286
+ if (un(e.autoScroll), Hn("cardHeader", e.cardHeader), Hn("cardFooter", e.cardFooter), Un("header", e.mediaCard?.header), Un("footer", e.mediaCard?.footer), $t(e.autofill), xn(e.fill), J(e.masonry), In(e.reelAutoAdvance), e.removalReconciliation) {
3226
3287
  if (!Number.isInteger(e.removalReconciliation.pageSize) || e.removalReconciliation.pageSize <= 0) throw TypeError("Vibe removalReconciliation pageSize must be a positive integer.");
3227
3288
  let t = e.removalReconciliation.maxReplayPages ?? 5;
3228
3289
  if (!Number.isInteger(t) || t <= 0) throw TypeError("Vibe removalReconciliation maxReplayPages must be a positive integer.");
@@ -3236,7 +3297,7 @@ function Un(e) {
3236
3297
  if (e.fill?.strategy === "frontend" && !e.loadPage) throw TypeError("Vibe frontend fill requires loadPage.");
3237
3298
  if (e.fill?.strategy === "backend" && e.fill.initialSession && !e.initialPage) throw TypeError("Vibe backend fill restoration requires initialPage.");
3238
3299
  }
3239
- function Wn(e) {
3300
+ function Gn(e) {
3240
3301
  if (typeof e != "string") return e;
3241
3302
  if (typeof document > "u") throw Error("Vibe cannot resolve a selector without a document.");
3242
3303
  let t = document.querySelector(e);
@@ -3245,7 +3306,7 @@ function Wn(e) {
3245
3306
  }
3246
3307
  //#endregion
3247
3308
  //#region src/core/pageRequest.ts
3248
- async function Gn({ append: e, autofillController: t, cursor: n, isCurrent: r, loadPage: i, onLastCursor: a, onPages: o, options: s, signal: c, state: l }) {
3309
+ async function Kn({ append: e, autofillController: t, cursor: n, isCurrent: r, loadPage: i, onLastCursor: a, onPages: o, options: s, signal: c, state: l }) {
3249
3310
  let u = s.autofill, d = e && u?.strategy === "frontend" && l.autofill.status === "paused", f = d ? {
3250
3311
  received: l.autofill.received,
3251
3312
  requests: l.autofill.requests
@@ -3328,13 +3389,13 @@ async function Gn({ append: e, autofillController: t, cursor: n, isCurrent: r, l
3328
3389
  function $(e) {
3329
3390
  return `${typeof e}:${String(e)}`;
3330
3391
  }
3331
- function Kn(e) {
3392
+ function qn(e) {
3332
3393
  return `${typeof e}:${String(e)}`;
3333
3394
  }
3334
- function qn(e) {
3395
+ function Jn(e) {
3335
3396
  return e.map(({ postId: e }) => e);
3336
3397
  }
3337
- var Jn = class {
3398
+ var Yn = class {
3338
3399
  delay;
3339
3400
  enabled;
3340
3401
  maxReplayPages;
@@ -3373,33 +3434,33 @@ var Jn = class {
3373
3434
  restore(e) {
3374
3435
  this.enabled && e.forEach((e) => this.tombstones.delete($(e)));
3375
3436
  }
3376
- async reconcile({ existingItems: e, loadPage: t, shouldPause: n = () => !1, signal: r }) {
3377
- let i = this.pending ?? this.createSession(e);
3378
- for (this.pending = i; i.remainingRequests > 0;) {
3379
- let e = Kn(i.cursor);
3380
- if (i.seenCursors.has(e)) throw Error("Vibe removal reconciliation received a repeated cursor.");
3437
+ async reconcile({ existingItems: e, loadPage: t, onDelayChange: n = () => void 0, shouldPause: r = () => !1, signal: i }) {
3438
+ let a = this.pending ?? this.createSession(e);
3439
+ for (this.pending = a; a.remainingRequests > 0;) {
3440
+ let e = qn(a.cursor);
3441
+ if (a.seenCursors.has(e)) throw Error("Vibe removal reconciliation received a repeated cursor.");
3381
3442
  if (await Jt({
3382
- delayMs: qt(i.pages.length, this.delay),
3383
- onChange: () => void 0,
3384
- signal: r
3385
- }), i.pages.length > 0 && n()) return this.result(i, "paused");
3386
- let a = Bt(await t({
3387
- cursor: i.cursor,
3388
- signal: r
3443
+ delayMs: qt(a.pages.length, this.delay),
3444
+ onChange: n,
3445
+ signal: i
3446
+ }), a.pages.length > 0 && r()) return this.result(a, "paused");
3447
+ let o = Bt(await t({
3448
+ cursor: a.cursor,
3449
+ signal: i
3389
3450
  }));
3390
- i.seenCursors.add(e);
3391
- let o = this.filterItems(a.items), s = [];
3392
- if (o.forEach((e) => {
3451
+ a.seenCursors.add(e);
3452
+ let s = this.filterItems(o.items), c = [];
3453
+ if (s.forEach((e) => {
3393
3454
  let t = $(e.postId);
3394
- i.attributed.has(t) || (i.attributed.add(t), s.push(e.postId)), i.appended.has(t) || (i.appended.add(t), i.items.push(e));
3395
- }), i.pages.push({
3396
- contributionIds: s,
3397
- cursor: i.cursor,
3398
- next: a.next,
3399
- returnedIds: qn(o)
3400
- }), i.lastCursor = i.cursor, i.next = a.next, --i.remainingRequests, a.total !== void 0 && (i.total = a.total), i.next === null ? i.remainingRequests = 0 : i.cursor = i.next, i.remainingRequests > 0 && n()) return this.result(i, "paused");
3455
+ a.attributed.has(t) || (a.attributed.add(t), c.push(e.postId)), a.appended.has(t) || (a.appended.add(t), a.items.push(e));
3456
+ }), a.pages.push({
3457
+ contributionIds: c,
3458
+ cursor: a.cursor,
3459
+ next: o.next,
3460
+ returnedIds: Jn(s)
3461
+ }), a.lastCursor = a.cursor, a.next = o.next, --a.remainingRequests, o.total !== void 0 && (a.total = o.total), a.next === null ? a.remainingRequests = 0 : a.cursor = a.next, a.remainingRequests > 0 && r()) return this.result(a, "paused");
3401
3462
  }
3402
- return this.result(i, "complete");
3463
+ return this.result(a, "complete");
3403
3464
  }
3404
3465
  createSession(e) {
3405
3466
  let t = this.findUnderfilledPage(e), n = t < 0 ? [] : this.pages.slice(t), r = n[0];
@@ -3435,7 +3496,7 @@ var Jn = class {
3435
3496
  return this.pages.findIndex(({ contributionIds: e }) => e.filter((e) => t.has($(e))).length < this.pageSize);
3436
3497
  }
3437
3498
  recordPage(e) {
3438
- let t = Kn(e.cursor), n = this.pages.findIndex(({ cursor: e }) => Kn(e) === t);
3499
+ let t = qn(e.cursor), n = this.pages.findIndex(({ cursor: e }) => qn(e) === t);
3439
3500
  n >= 0 && (this.pages = this.pages.slice(0, n)), this.pages.push({
3440
3501
  ...e,
3441
3502
  contributionIds: [...e.contributionIds],
@@ -3445,7 +3506,7 @@ var Jn = class {
3445
3506
  };
3446
3507
  //#endregion
3447
3508
  //#region src/core/activeItemRemoval.ts
3448
- function Yn(e, t, n, r, i) {
3509
+ function Xn(e, t, n, r, i) {
3449
3510
  let a = new Set(t.map(({ item: e }) => e.postId));
3450
3511
  if (e.activeReelPostId === null || !a.has(e.activeReelPostId)) return;
3451
3512
  let o = e.items[Math.max(n, 0)];
@@ -3458,7 +3519,7 @@ function Yn(e, t, n, r, i) {
3458
3519
  }
3459
3520
  //#endregion
3460
3521
  //#region src/core/exactMediaRemovalController.ts
3461
- function Xn(e, t) {
3522
+ function Zn(e, t) {
3462
3523
  let [n, ...r] = t;
3463
3524
  if (!n) throw Error("Vibe items must contain at least one media asset.");
3464
3525
  return {
@@ -3467,10 +3528,10 @@ function Xn(e, t) {
3467
3528
  items: r
3468
3529
  };
3469
3530
  }
3470
- function Zn(e) {
3531
+ function Qn(e) {
3471
3532
  if (!Number.isInteger(e.mediaIndex) || e.mediaIndex < 0) throw TypeError("Vibe mediaIndex must be a non-negative integer.");
3472
3533
  }
3473
- var Qn = class {
3534
+ var $n = class {
3474
3535
  generation = 0;
3475
3536
  metadata = /* @__PURE__ */ new WeakMap();
3476
3537
  state;
@@ -3478,7 +3539,7 @@ var Qn = class {
3478
3539
  this.options = e, this.state = e.state;
3479
3540
  }
3480
3541
  remove(e) {
3481
- Zn(e);
3542
+ Qn(e);
3482
3543
  let t = this.state.items.findIndex(({ postId: t }) => t === e.postId), n = this.state.items[t];
3483
3544
  if (!n) return null;
3484
3545
  let r = [...M(n)], i = r[e.mediaIndex];
@@ -3495,7 +3556,7 @@ var Qn = class {
3495
3556
  restored: !1
3496
3557
  });
3497
3558
  let o = this.state.mediaIndices.get(n.postId) ?? 0, s = this.isReelOpen() && this.state.activeReelPostId === n.postId, c = s && o === e.mediaIndex;
3498
- return r.splice(e.mediaIndex, 1), r.length > 0 ? (this.state.items[t] = Xn(n, r), this.updateMediaIndexAfterRemoval(n.postId, e.mediaIndex, c), a) : (this.state.items.splice(t, 1), this.options.onPostRemoved(n.postId), this.state.mediaIndices.delete(n.postId), s && this.advanceFromRemovedPost(a, n), a);
3559
+ return r.splice(e.mediaIndex, 1), r.length > 0 ? (this.state.items[t] = Zn(n, r), this.updateMediaIndexAfterRemoval(n.postId, e.mediaIndex, c), a) : (this.state.items.splice(t, 1), this.options.onPostRemoved(n.postId), this.state.mediaIndices.delete(n.postId), s && this.advanceFromRemovedPost(a, n), a);
3499
3560
  }
3500
3561
  reset() {
3501
3562
  this.generation += 1;
@@ -3521,7 +3582,7 @@ var Qn = class {
3521
3582
  }
3522
3583
  restoreIntoPost(e, t) {
3523
3584
  let n = this.state.items[e], r = [...M(n)], i = Math.min(t.mediaIndex, r.length);
3524
- if (r.splice(i, 0, t.media), this.state.items[e] = Xn(n, r), this.state.activeReelPostId !== t.postId) return;
3585
+ if (r.splice(i, 0, t.media), this.state.items[e] = Zn(n, r), this.state.activeReelPostId !== t.postId) return;
3525
3586
  let a = this.state.mediaIndices.get(t.postId) ?? 0;
3526
3587
  a >= i && this.state.mediaIndices.set(t.postId, a + 1);
3527
3588
  }
@@ -3534,18 +3595,18 @@ var Qn = class {
3534
3595
  };
3535
3596
  //#endregion
3536
3597
  //#region src/core/itemPlacement.ts
3537
- function $n(e, t) {
3598
+ function er(e, t) {
3538
3599
  let n = new Set(t);
3539
3600
  return e.flatMap((e, t) => n.has(e.postId) ? [{
3540
3601
  index: t,
3541
3602
  item: e
3542
3603
  }] : []);
3543
3604
  }
3544
- function er(e, t) {
3605
+ function tr(e, t) {
3545
3606
  let n = new Set(t.map(({ item: e }) => e.postId));
3546
3607
  return e.filter((e) => !n.has(e.postId));
3547
3608
  }
3548
- function tr(e, t) {
3609
+ function nr(e, t) {
3549
3610
  t.forEach(({ index: e }) => {
3550
3611
  if (!Number.isInteger(e) || e < 0) throw Error("Vibe item restore indexes must be non-negative integers.");
3551
3612
  });
@@ -3556,7 +3617,7 @@ function tr(e, t) {
3556
3617
  }
3557
3618
  //#endregion
3558
3619
  //#region src/core/itemRemovalController.ts
3559
- var nr = 20, rr = class {
3620
+ var rr = 20, ir = class {
3560
3621
  generation = 0;
3561
3622
  historyLimit;
3562
3623
  metadata = /* @__PURE__ */ new WeakMap();
@@ -3565,7 +3626,7 @@ var nr = 20, rr = class {
3565
3626
  itemOrder;
3566
3627
  stopItemsWatcher;
3567
3628
  constructor(e) {
3568
- this.options = e, this.historyLimit = e.historyLimit ?? nr, this.state = e.state, this.itemOrder = this.state.items.map(({ postId: e }) => e), this.stopItemsWatcher = O(() => this.state.items, (e) => this.appendUnknownItems(e), { flush: "sync" });
3629
+ this.options = e, this.historyLimit = e.historyLimit ?? rr, this.state = e.state, this.itemOrder = this.state.items.map(({ postId: e }) => e), this.stopItemsWatcher = O(() => this.state.items, (e) => this.appendUnknownItems(e), { flush: "sync" });
3569
3630
  }
3570
3631
  destroy() {
3571
3632
  this.reset(), this.stopItemsWatcher();
@@ -3579,7 +3640,7 @@ var nr = 20, rr = class {
3579
3640
  let a = this.options.startRemoval(i, t);
3580
3641
  if (a > 0 && await new Promise((e) => setTimeout(e, a)), this.metadata.get(r)?.generation !== this.generation) return r;
3581
3642
  let o = this.state.items.findIndex((e) => e.postId === this.state.activeReelPostId), s = new Set(n.map(({ item: e }) => e.postId)), c = o < 0 ? 0 : this.state.items.slice(0, o).filter(({ postId: e }) => s.has(e)).length, l = Math.max(o - c, 0);
3582
- return this.state.items = er(this.state.items, n), this.options.onItemsRemoved(r, n, l), this.record(r), r;
3643
+ return this.state.items = tr(this.state.items, n), this.options.onItemsRemoved(r, n, l), this.record(r), r;
3583
3644
  }
3584
3645
  reset() {
3585
3646
  this.generation += 1, this.history = [], this.itemOrder = [];
@@ -3590,7 +3651,7 @@ var nr = 20, rr = class {
3590
3651
  this.restoreRemoval(t);
3591
3652
  return;
3592
3653
  }
3593
- let n = new Set(this.state.items.map(({ postId: e }) => e)), r = e.filter(({ item: e }) => n.has(e.postId) ? !1 : (n.add(e.postId), !0)), i = tr(this.state.items, r);
3654
+ let n = new Set(this.state.items.map(({ postId: e }) => e)), r = e.filter(({ item: e }) => n.has(e.postId) ? !1 : (n.add(e.postId), !0)), i = nr(this.state.items, r);
3594
3655
  this.registerExternalPlacements(r), this.state.items = i, r.length > 0 && this.options.onRemovalRestored(r);
3595
3656
  }
3596
3657
  restoreRemoval(e) {
@@ -3616,7 +3677,7 @@ var nr = 20, rr = class {
3616
3677
  }
3617
3678
  collectOrderedPlacements(e) {
3618
3679
  let t = new Map(this.itemOrder.map((e, t) => [e, t]));
3619
- return $n(this.state.items, e).map((e) => ({
3680
+ return er(this.state.items, e).map((e) => ({
3620
3681
  index: t.get(e.item.postId) ?? e.index,
3621
3682
  item: e.item
3622
3683
  }));
@@ -3647,7 +3708,7 @@ var nr = 20, rr = class {
3647
3708
  let r = new Map(this.itemOrder.map((e, t) => [e, t]));
3648
3709
  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;
3649
3710
  }
3650
- }, ir = class {
3711
+ }, ar = class {
3651
3712
  forward = null;
3652
3713
  forwardPromise = null;
3653
3714
  forwardVersion = 0;
@@ -3725,7 +3786,7 @@ var nr = 20, rr = class {
3725
3786
  }
3726
3787
  }
3727
3788
  }
3728
- }, ar = class {
3789
+ }, or = class {
3729
3790
  generation = 0;
3730
3791
  pending = Promise.resolve();
3731
3792
  constructor(e) {
@@ -3775,24 +3836,24 @@ var nr = 20, rr = class {
3775
3836
  };
3776
3837
  //#endregion
3777
3838
  //#region src/core/removalControllers.ts
3778
- function or(e) {
3779
- let t = new ir(e), n = new ar({
3839
+ function sr(e) {
3840
+ let t = new ar(e), n = new or({
3780
3841
  state: e.state,
3781
3842
  transitionMedia: (t) => e.surface()?.transitionActiveReelMedia(t) ?? Promise.resolve(!1),
3782
3843
  transitionPost: (t) => e.surface()?.transitionActiveReelPost(t) ?? Promise.resolve(!1)
3783
3844
  });
3784
3845
  return {
3785
- exactMediaRemoval: new Qn({
3846
+ exactMediaRemoval: new $n({
3786
3847
  onActivate: e.onActivate,
3787
3848
  onPostRemoved: (t) => e.onItemsRemoved([t]),
3788
3849
  onPostRestored: (t) => e.onItemsRestored([t]),
3789
3850
  reelForward: t,
3790
3851
  state: e.state
3791
3852
  }),
3792
- itemRemoval: new rr({
3853
+ itemRemoval: new ir({
3793
3854
  historyLimit: e.historyLimit,
3794
3855
  onItemsRemoved: (n, r, i) => {
3795
- e.onItemsRemoved(r.map(({ item: e }) => e.postId)), Yn(e.state, r, i, e.onActivate, (e, r) => t.start(n, e, r));
3856
+ e.onItemsRemoved(r.map(({ item: e }) => e.postId)), Xn(e.state, r, i, e.onActivate, (e, r) => t.start(n, e, r));
3796
3857
  },
3797
3858
  onRemovalRestored: (n) => {
3798
3859
  e.onItemsRestored(n.map(({ item: e }) => e.postId));
@@ -3807,17 +3868,17 @@ function or(e) {
3807
3868
  reelRemoval: n
3808
3869
  };
3809
3870
  }
3810
- var sr = 1.5;
3811
- function cr(e) {
3871
+ var cr = 1.5;
3872
+ function lr(e) {
3812
3873
  let t = Math.min(e.screenWidth, e.screenHeight);
3813
3874
  if (t > 0 && t < 600) return !0;
3814
- let n = Math.min(e.viewportWidth, e.viewportHeight), r = t >= n * sr;
3875
+ let n = Math.min(e.viewportWidth, e.viewportHeight), r = t >= n * cr;
3815
3876
  return !e.hasHover && n > 0 && n < 600 && r;
3816
3877
  }
3817
- function lr(e) {
3818
- return cr(e) ? "reel" : "masonry";
3819
- }
3820
3878
  function ur(e) {
3879
+ return lr(e) ? "reel" : "masonry";
3880
+ }
3881
+ function dr(e) {
3821
3882
  let t = e.ownerDocument.defaultView, n = e.ownerDocument.documentElement;
3822
3883
  return {
3823
3884
  hasHover: typeof t?.matchMedia == "function" && t.matchMedia("(hover: hover)").matches,
@@ -3827,15 +3888,15 @@ function ur(e) {
3827
3888
  viewportWidth: n.clientWidth
3828
3889
  };
3829
3890
  }
3830
- function dr(e) {
3831
- return cr(ur(e));
3832
- }
3833
3891
  function fr(e) {
3834
- return lr(ur(e));
3892
+ return lr(dr(e));
3893
+ }
3894
+ function pr(e) {
3895
+ return ur(dr(e));
3835
3896
  }
3836
3897
  //#endregion
3837
3898
  //#region src/core/responsiveLayoutController.ts
3838
- var pr = class {
3899
+ var mr = class {
3839
3900
  layoutMode;
3840
3901
  resizeObserver = null;
3841
3902
  target = null;
@@ -3860,10 +3921,10 @@ var pr = class {
3860
3921
  }
3861
3922
  handleResponsiveLayout = () => {
3862
3923
  if (!this.target) return;
3863
- let e = fr(this.target);
3864
- this.state.phoneMode = dr(this.target), this.state.reelInfoSheetOverlay = this.state.phoneMode, this.state.reelMediaSource = e === "reel" ? "preview" : "original", this.layoutMode === "responsive" && this.applyLayout(e);
3924
+ let e = pr(this.target);
3925
+ this.state.phoneMode = fr(this.target), this.state.reelInfoSheetOverlay = this.state.phoneMode, this.state.reelMediaSource = e === "reel" ? "preview" : "original", this.layoutMode === "responsive" && this.applyLayout(e);
3865
3926
  };
3866
- }, mr = class {
3927
+ }, hr = class {
3867
3928
  routedReelPostId = null;
3868
3929
  reelRouteIsActive = !1;
3869
3930
  constructor(e, t) {
@@ -3890,7 +3951,7 @@ var pr = class {
3890
3951
  let i = this.reelRouteIsActive ? "replace" : "push";
3891
3952
  this.reelRouteIsActive = !0, this.routedReelPostId = e, this.options.router[i](r);
3892
3953
  }
3893
- }, hr = class {
3954
+ }, gr = class {
3894
3955
  app = null;
3895
3956
  autoScroll;
3896
3957
  autofillController;
@@ -3911,9 +3972,9 @@ var pr = class {
3911
3972
  notificationItems;
3912
3973
  state;
3913
3974
  constructor(e) {
3914
- this.options = e, Un(e);
3975
+ this.options = e, Wn(e);
3915
3976
  let t = e.layout ?? "masonry";
3916
- this.state = x(Bn(e, t)), this.notificationItems = I(this.state), this.autoScroll = new fn({
3977
+ this.state = x(Vn(e, t)), this.notificationItems = I(this.state), this.autoScroll = new fn({
3917
3978
  getScrollElement: () => this.surface?.getAutoScrollElement() ?? null,
3918
3979
  state: this.state.autoScroll
3919
3980
  }), this.autofillController = new on({
@@ -3924,16 +3985,28 @@ var pr = class {
3924
3985
  onPages: (e) => this.removalReconciliation.recordPages(e),
3925
3986
  options: e.autofill,
3926
3987
  state: this.state
3927
- }), this.removalReconciliation = new Jn(e), this.fillController = new Mn({
3988
+ }), this.removalReconciliation = new Yn(e), this.fillController = new Mn({
3928
3989
  fill: e.fill,
3929
3990
  loadPage: e.loadPage ? (e) => this.loadFilteredPage(e) : void 0,
3991
+ needsFrontendPreparation: () => this.removalReconciliation.needsReconciliation(this.state.items),
3930
3992
  onLastCursor: (e) => {
3931
3993
  this.lastLoadedCursor = e;
3932
3994
  },
3933
3995
  onPages: (e) => this.removalReconciliation.recordPages(e),
3996
+ prepareFrontend: ({ isCurrent: t, onDelayChange: n, signal: r }) => Nn({
3997
+ controller: this.removalReconciliation,
3998
+ isCurrent: t,
3999
+ loadPage: e.loadPage,
4000
+ onDelayChange: n,
4001
+ setLastCursor: (e) => {
4002
+ this.lastLoadedCursor = e;
4003
+ },
4004
+ signal: r,
4005
+ state: this.state
4006
+ }),
3934
4007
  state: this.state
3935
- }), this.routing = new mr(e.routing, this.state);
3936
- let n = or({
4008
+ }), this.routing = new hr(e.routing, this.state);
4009
+ let n = sr({
3937
4010
  historyLimit: e.removalHistoryLimit,
3938
4011
  loadNext: () => this.loadNext(),
3939
4012
  onActivate: (e) => this.setActiveReelPost(e),
@@ -3943,20 +4016,20 @@ var pr = class {
3943
4016
  state: this.state,
3944
4017
  surface: () => this.surface
3945
4018
  });
3946
- this.exactMediaRemoval = n.exactMediaRemoval, this.itemRemoval = n.itemRemoval, this.reelForward = n.reelForward, this.reelRemoval = n.reelRemoval, this.responsiveLayout = new pr(t, this.state, () => {
4019
+ this.exactMediaRemoval = n.exactMediaRemoval, this.itemRemoval = n.itemRemoval, this.reelForward = n.reelForward, this.reelRemoval = n.reelRemoval, this.responsiveLayout = new mr(t, this.state, () => {
3947
4020
  this.routing.syncFeed();
3948
4021
  }), this.startStateNotifications();
3949
4022
  }
3950
4023
  async mount() {
3951
4024
  if (this.app) throw Error("Vibe is already mounted.");
3952
4025
  this.startStateNotifications();
3953
- let e = Wn(this.options.target);
4026
+ let e = Gn(this.options.target);
3954
4027
  this.responsiveLayout.mount(e), this.app = i(zt, {
3955
4028
  canRetryEnd: !!this.options.loadPage,
3956
4029
  cardFooter: this.options.cardFooter,
3957
4030
  cardHeader: this.options.cardHeader,
3958
4031
  feedFooter: this.options.feedFooter,
3959
- feedFooterActions: Nn(this),
4032
+ feedFooterActions: Pn(this),
3960
4033
  mediaCard: this.options.mediaCard,
3961
4034
  masonry: this.options.masonry,
3962
4035
  onMediaReady: this.options.onMediaReady,
@@ -4112,13 +4185,18 @@ var pr = class {
4112
4185
  let t = ++this.requestVersion, n = new AbortController();
4113
4186
  this.abortController = n;
4114
4187
  try {
4115
- let r = await this.removalReconciliation.reconcile({
4116
- existingItems: this.state.items,
4188
+ let r = await Nn({
4189
+ controller: this.removalReconciliation,
4190
+ isCurrent: () => t === this.requestVersion,
4117
4191
  loadPage: e,
4118
- shouldPause: () => this.state.loadMoreLocked,
4119
- signal: n.signal
4192
+ onDelayChange: () => void 0,
4193
+ setLastCursor: (e) => {
4194
+ this.lastLoadedCursor = e;
4195
+ },
4196
+ signal: n.signal,
4197
+ state: this.state
4120
4198
  });
4121
- return t === this.requestVersion ? (this.state.items = Z(this.state.items, r.items), this.state.next = r.next, this.lastLoadedCursor = r.lastCursor, r.total !== void 0 && (this.state.total = r.total), this.removalReconciliation.completeReconciliation(r), r.status === "complete") : !1;
4199
+ return t === this.requestVersion && r === "complete";
4122
4200
  } catch (e) {
4123
4201
  return !n.signal.aborted && t === this.requestVersion && (this.state.nextPageError = e), !1;
4124
4202
  } finally {
@@ -4134,13 +4212,9 @@ var pr = class {
4134
4212
  }
4135
4213
  setLoadMoreLocked(e) {
4136
4214
  if (this.state.loadMoreLocked !== e && (this.state.loadMoreLocked = e, !e)) {
4137
- let e = this.state.fill.status === "paused" ? this.state.fill.target : null;
4138
- if (e) {
4139
- let t = "pages" in e ? e.pages - this.state.fill.completedPages : null;
4140
- if (t === null || t > 0) {
4141
- this.fillController.start(t === null ? { until: "end" } : { pages: t });
4142
- return;
4143
- }
4215
+ if (this.state.fill.status === "paused" && this.state.fill.target) {
4216
+ this.fillController.resume(this.removalReconciliation.hasPendingSession());
4217
+ return;
4144
4218
  }
4145
4219
  if (this.state.autofill.status === "paused" || this.removalReconciliation.hasPendingSession()) {
4146
4220
  let e = this.pendingRequest;
@@ -4155,10 +4229,10 @@ var pr = class {
4155
4229
  this.state.total = e;
4156
4230
  }
4157
4231
  setReelAutoAdvance(e) {
4158
- Ln(this.state.reelAutoAdvance, e);
4232
+ Rn(this.state.reelAutoAdvance, e);
4159
4233
  }
4160
4234
  setReelInfoSheet(e) {
4161
- zn(this.state.reelInfoSheet, this.options.reelInfoSheet, e);
4235
+ Bn(this.state.reelInfoSheet, this.options.reelInfoSheet, e);
4162
4236
  }
4163
4237
  setLayout(e) {
4164
4238
  this.responsiveLayout.setLayout(e);
@@ -4178,7 +4252,7 @@ var pr = class {
4178
4252
  async fetchPage(e, t) {
4179
4253
  if (!this.options.loadPage) return;
4180
4254
  let n = ++this.requestVersion, r = new AbortController();
4181
- this.abortController = r, await Gn({
4255
+ this.abortController = r, await Kn({
4182
4256
  append: t,
4183
4257
  autofillController: this.autofillController,
4184
4258
  cursor: e,
@@ -4228,8 +4302,8 @@ var pr = class {
4228
4302
  }));
4229
4303
  }
4230
4304
  };
4231
- function gr(e) {
4232
- return new hr(e);
4305
+ function _r(e) {
4306
+ return new gr(e);
4233
4307
  }
4234
4308
  //#endregion
4235
- export { gr as createVibe };
4309
+ export { _r as createVibe };