@shortkitsdk/web 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/shortkit.cjs CHANGED
@@ -33849,7 +33849,7 @@ class FeedManager {
33849
33849
  }
33850
33850
  setMuted(muted) {
33851
33851
  this.isMuted = muted;
33852
- for (const [, player] of this.pool._players) {
33852
+ for (const [, player] of this.pool.assignments) {
33853
33853
  player.muted = muted;
33854
33854
  }
33855
33855
  this._pushPlayerState({ isMuted: muted });
@@ -33862,7 +33862,7 @@ class FeedManager {
33862
33862
  }
33863
33863
  setPlaybackRate(rate) {
33864
33864
  this.playbackRate = rate;
33865
- for (const [, player] of this.pool._players) {
33865
+ for (const [, player] of this.pool.assignments) {
33866
33866
  player.playbackRate = rate;
33867
33867
  }
33868
33868
  this._pushPlayerState({ playbackRate: rate });
@@ -34339,11 +34339,10 @@ class FeedManager {
34339
34339
  const player = this.pool.getPlayer(id);
34340
34340
  if (player) {
34341
34341
  player.pause();
34342
- player.style.opacity = "0";
34343
34342
  player._skRevealedFor = null;
34344
34343
  }
34345
34344
  this._stopTimeLoop(id);
34346
- this._clearOverlay(id);
34345
+ this._detachOverlay(id);
34347
34346
  this._sk._tracker.deactivateContent();
34348
34347
  }
34349
34348
  // --- Time loop ---
@@ -34525,14 +34524,20 @@ class FeedManager {
34525
34524
  }
34526
34525
  }
34527
34526
  /** Clear the overlay container's DOM and unsubscribe tracked listeners. */
34528
- _clearOverlay(itemId) {
34527
+ /** Unsubscribe overlay event listeners without clearing DOM. */
34528
+ _detachOverlay(itemId) {
34529
34529
  const entry = this._overlayContainers.get(itemId);
34530
34530
  if (!entry) return;
34531
34531
  if (entry.unsub) {
34532
34532
  entry.unsub();
34533
34533
  entry.unsub = null;
34534
34534
  }
34535
- entry.el.innerHTML = "";
34535
+ }
34536
+ /** Unsubscribe and clear overlay DOM (used on destroy). */
34537
+ _clearOverlay(itemId) {
34538
+ this._detachOverlay(itemId);
34539
+ const entry = this._overlayContainers.get(itemId);
34540
+ if (entry) entry.el.innerHTML = "";
34536
34541
  }
34537
34542
  }
34538
34543
  class EmbeddedFeedManager {
@@ -34646,7 +34651,7 @@ class EmbeddedFeedManager {
34646
34651
  }
34647
34652
  setMuted(muted) {
34648
34653
  this.isMuted = muted;
34649
- for (const [, player] of this.pool._players) {
34654
+ for (const [, player] of this.pool.assignments) {
34650
34655
  player.muted = muted;
34651
34656
  }
34652
34657
  this._pushPlayerState({ isMuted: muted });
@@ -34659,7 +34664,7 @@ class EmbeddedFeedManager {
34659
34664
  }
34660
34665
  setPlaybackRate(rate) {
34661
34666
  this.playbackRate = rate;
34662
- for (const [, player] of this.pool._players) {
34667
+ for (const [, player] of this.pool.assignments) {
34663
34668
  player.playbackRate = rate;
34664
34669
  }
34665
34670
  this._pushPlayerState({ playbackRate: rate });
@@ -34931,11 +34936,10 @@ class EmbeddedFeedManager {
34931
34936
  const p = this.pool.getPlayer(id);
34932
34937
  if (p) {
34933
34938
  p.pause();
34934
- p.style.opacity = "0";
34935
34939
  p._skRevealedFor = null;
34936
34940
  }
34937
34941
  this._stopTimeLoop(id);
34938
- this._clearOverlay(id);
34942
+ this._detachOverlay(id);
34939
34943
  }
34940
34944
  // --- Time loop (state emission only, no DOM updates) ---
34941
34945
  _startTimeLoop(id, el, player) {
@@ -35134,14 +35138,20 @@ class EmbeddedFeedManager {
35134
35138
  } catch (e) {
35135
35139
  }
35136
35140
  }
35137
- _clearOverlay(itemId) {
35141
+ /** Unsubscribe overlay event listeners without clearing DOM. */
35142
+ _detachOverlay(itemId) {
35138
35143
  const entry = this._overlayContainers.get(itemId);
35139
35144
  if (!entry) return;
35140
35145
  if (entry.unsub) {
35141
35146
  entry.unsub();
35142
35147
  entry.unsub = null;
35143
35148
  }
35144
- entry.el.innerHTML = "";
35149
+ }
35150
+ /** Unsubscribe and clear overlay DOM (used on destroy). */
35151
+ _clearOverlay(itemId) {
35152
+ this._detachOverlay(itemId);
35153
+ const entry = this._overlayContainers.get(itemId);
35154
+ if (entry) entry.el.innerHTML = "";
35145
35155
  }
35146
35156
  }
35147
35157
  const MuteOnSvg = '<svg viewBox="0 0 24 24"><path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/></svg>';
@@ -35491,6 +35501,7 @@ class PlayerFeedView {
35491
35501
  this._isOpen = true;
35492
35502
  this._onClose = onClose;
35493
35503
  this._openItemId = item.id;
35504
+ this._openThumbnailUrl = item.thumbnailUrl || null;
35494
35505
  const sourceRect = sourceEl.getBoundingClientRect();
35495
35506
  const sourceRadius = parseFloat(getComputedStyle(sourceEl).borderRadius) || 12;
35496
35507
  this.overlayEl.classList.add("skp-active");
@@ -35535,6 +35546,21 @@ class PlayerFeedView {
35535
35546
  feedEl.style.transform = "none";
35536
35547
  feedEl.style.borderRadius = `${targetRadius}px`;
35537
35548
  });
35549
+ this.feedManager.startObserver();
35550
+ this.feedManager._activateItem(item.id);
35551
+ this.overlayEl.classList.add("skp-feed-ready");
35552
+ const itemOverlay = feedItemEl?.querySelector('[data-ref="overlay"]');
35553
+ const chromeEls = [...this.overlayEl.querySelectorAll(".skp-feed-close, .sk-sidebar")];
35554
+ if (itemOverlay) chromeEls.push(itemOverlay);
35555
+ chromeEls.forEach((el) => {
35556
+ el.style.opacity = "0";
35557
+ el.style.transition = "none";
35558
+ });
35559
+ this.overlayEl.getBoundingClientRect();
35560
+ chromeEls.forEach((el) => {
35561
+ el.style.transition = "opacity .35s cubic-bezier(.32,.72,0,1)";
35562
+ el.style.opacity = "1";
35563
+ });
35538
35564
  await this._waitForTransitionEnd(feedEl, 450);
35539
35565
  feedEl.classList.remove("skp-flip-animating");
35540
35566
  feedEl.style.transformOrigin = "";
@@ -35542,9 +35568,10 @@ class PlayerFeedView {
35542
35568
  feedEl.style.scrollSnapType = "";
35543
35569
  feedEl.style.transform = "";
35544
35570
  feedEl.style.borderRadius = "";
35545
- this.feedManager.startObserver();
35546
- this.feedManager._activateItem(item.id);
35547
- this.overlayEl.classList.add("skp-feed-ready");
35571
+ chromeEls.forEach((el) => {
35572
+ el.style.opacity = "";
35573
+ el.style.transition = "";
35574
+ });
35548
35575
  this._escHandler = (e) => {
35549
35576
  if (e.key === "Escape") this.close();
35550
35577
  };
@@ -35557,33 +35584,44 @@ class PlayerFeedView {
35557
35584
  const feedWrapper = feedEl.parentNode;
35558
35585
  const feedRect = feedEl.getBoundingClientRect();
35559
35586
  const activeItemId = this.feedManager?.activeItemId;
35560
- let transferBack = false, transferVideo = null, transferHls = null;
35561
- if (activeItemId === this._openItemId) {
35562
- const ejected = this.feedManager?.pool.ejectPlayer(activeItemId);
35563
- if (ejected) {
35564
- transferBack = true;
35565
- transferVideo = ejected.video;
35566
- transferHls = ejected.hls;
35567
- }
35568
- }
35587
+ const canTransfer = activeItemId === this._openItemId;
35569
35588
  let targetRect = null;
35570
35589
  if (this._onClose) targetRect = this._onClose("getSourceRect");
35571
35590
  if (feedRect && targetRect) {
35572
- if (this.feedManager?.activeItemId && !transferBack) {
35591
+ if (this.feedManager?.activeItemId && !canTransfer) {
35573
35592
  this.feedManager._deactivateItem(this.feedManager.activeItemId);
35574
35593
  }
35594
+ const targetItemId = canTransfer ? this._openItemId : activeItemId;
35595
+ if (targetItemId && this.feedManager) {
35596
+ const targetEl = this.feedManager.itemEls.get(targetItemId);
35597
+ if (targetEl) targetEl.scrollIntoView({ behavior: "instant", block: "start" });
35598
+ }
35599
+ const savedScrollTop = feedEl.scrollTop;
35575
35600
  feedEl.style.position = "fixed";
35576
35601
  feedEl.style.left = `${feedRect.left}px`;
35577
35602
  feedEl.style.top = `${feedRect.top}px`;
35578
35603
  feedEl.style.width = `${feedRect.width}px`;
35579
35604
  feedEl.style.height = `${feedRect.height}px`;
35580
- feedEl.style.zIndex = "9999";
35605
+ feedEl.style.zIndex = String(getComputedStyle(this.overlayEl).zIndex || 9999);
35581
35606
  feedEl.style.margin = "0";
35582
35607
  feedEl.style.flex = "none";
35583
35608
  feedEl.style.aspectRatio = "unset";
35584
35609
  feedEl.style.maxHeight = "none";
35585
35610
  document.body.appendChild(feedEl);
35611
+ feedEl.scrollTop = savedScrollTop;
35586
35612
  this.overlayEl.classList.remove("skp-active", "skp-feed-ready");
35613
+ let thumbOverlay = null;
35614
+ if (this._openThumbnailUrl) {
35615
+ const crossfadeItemId = canTransfer ? this._openItemId : activeItemId;
35616
+ const crossfadeEl = crossfadeItemId && this.feedManager?.itemEls.get(crossfadeItemId);
35617
+ const videoContainer = crossfadeEl?.querySelector('[data-ref="videoContainer"]');
35618
+ if (videoContainer) {
35619
+ thumbOverlay = document.createElement("img");
35620
+ thumbOverlay.src = this._openThumbnailUrl;
35621
+ thumbOverlay.style.cssText = "position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .4s cubic-bezier(.32,.72,0,1);pointer-events:none;z-index:2;";
35622
+ videoContainer.appendChild(thumbOverlay);
35623
+ }
35624
+ }
35587
35625
  const scaleX = targetRect.width / feedRect.width;
35588
35626
  const scaleY = targetRect.height / feedRect.height;
35589
35627
  const translateX = targetRect.left - feedRect.left;
@@ -35593,29 +35631,58 @@ class PlayerFeedView {
35593
35631
  feedEl.style.transformOrigin = "0 0";
35594
35632
  feedEl.style.overflow = "hidden";
35595
35633
  feedEl.style.scrollSnapType = "none";
35634
+ feedEl.style.pointerEvents = "none";
35596
35635
  feedEl.getBoundingClientRect();
35597
35636
  feedEl.classList.add("skp-flip-animating");
35598
35637
  requestAnimationFrame(() => {
35599
35638
  feedEl.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
35600
35639
  feedEl.style.borderRadius = `${endRadius}px`;
35640
+ if (thumbOverlay) thumbOverlay.style.opacity = "1";
35601
35641
  });
35602
35642
  await this._waitForTransitionEnd(feedEl, 450);
35643
+ if (thumbOverlay) thumbOverlay.remove();
35644
+ let transferVideo = null;
35645
+ let transferHls = null;
35646
+ if (canTransfer) {
35647
+ const ejected = this.feedManager?.pool.ejectPlayer(this._openItemId);
35648
+ if (ejected) {
35649
+ transferVideo = ejected.video;
35650
+ transferHls = ejected.hls;
35651
+ }
35652
+ }
35603
35653
  feedEl.style.visibility = "hidden";
35604
35654
  feedEl.classList.remove("skp-flip-animating");
35605
- ["position", "left", "top", "width", "height", "zIndex", "margin", "flex", "aspectRatio", "maxHeight", "transformOrigin", "overflow", "scrollSnapType", "transform", "borderRadius"].forEach((p) => feedEl.style[p] = "");
35655
+ ["position", "left", "top", "width", "height", "zIndex", "margin", "flex", "aspectRatio", "maxHeight", "transformOrigin", "overflow", "scrollSnapType", "pointerEvents", "transform", "borderRadius"].forEach((p) => feedEl.style[p] = "");
35606
35656
  const sidebarEl = feedWrapper.querySelector(".sk-sidebar");
35607
35657
  feedWrapper.insertBefore(feedEl, sidebarEl);
35608
35658
  feedEl.style.visibility = "";
35659
+ if (this._onClose) {
35660
+ this._onClose("closed", {
35661
+ transferVideo,
35662
+ transferHls,
35663
+ transferItemId: transferVideo ? this._openItemId : null
35664
+ });
35665
+ this._onClose = null;
35666
+ }
35609
35667
  } else {
35610
35668
  this.overlayEl.classList.remove("skp-active", "skp-feed-ready");
35611
- }
35612
- if (this._onClose) {
35613
- this._onClose("closed", {
35614
- transferVideo: transferBack ? transferVideo : null,
35615
- transferHls: transferBack ? transferHls : null,
35616
- transferItemId: transferBack ? this._openItemId : null
35617
- });
35618
- this._onClose = null;
35669
+ if (this._onClose) {
35670
+ let transferVideo = null;
35671
+ let transferHls = null;
35672
+ if (canTransfer) {
35673
+ const ejected = this.feedManager?.pool.ejectPlayer(this._openItemId);
35674
+ if (ejected) {
35675
+ transferVideo = ejected.video;
35676
+ transferHls = ejected.hls;
35677
+ }
35678
+ }
35679
+ this._onClose("closed", {
35680
+ transferVideo,
35681
+ transferHls,
35682
+ transferItemId: transferVideo ? this._openItemId : null
35683
+ });
35684
+ this._onClose = null;
35685
+ }
35619
35686
  }
35620
35687
  if (this.feedManager) {
35621
35688
  this.feedManager.destroy();
@@ -35667,6 +35734,7 @@ class FeedView {
35667
35734
  this._onClose = onClose;
35668
35735
  this._openSlotIndex = startIndex;
35669
35736
  this._openItemId = item.id;
35737
+ this._openThumbnailUrl = item.thumbnailUrl || null;
35670
35738
  const slotRect = slotEl.getBoundingClientRect();
35671
35739
  const slotRadius = parseFloat(getComputedStyle(slotEl).borderRadius) || 12;
35672
35740
  if (_isPreview) {
@@ -35713,6 +35781,21 @@ class FeedView {
35713
35781
  feedEl.style.transform = "none";
35714
35782
  feedEl.style.borderRadius = `${targetRadius}px`;
35715
35783
  });
35784
+ this.feedManager.startObserver();
35785
+ this.feedManager._activateItem(item.id);
35786
+ this.overlayEl.classList.add("skw-feed-ready");
35787
+ const itemOverlay = feedItemEl?.querySelector('[data-ref="overlay"]');
35788
+ const chromeEls = [...this.overlayEl.querySelectorAll(".skw-feed-close, .sk-sidebar")];
35789
+ if (itemOverlay) chromeEls.push(itemOverlay);
35790
+ chromeEls.forEach((el) => {
35791
+ el.style.opacity = "0";
35792
+ el.style.transition = "none";
35793
+ });
35794
+ this.overlayEl.getBoundingClientRect();
35795
+ chromeEls.forEach((el) => {
35796
+ el.style.transition = "opacity .35s cubic-bezier(.32,.72,0,1)";
35797
+ el.style.opacity = "1";
35798
+ });
35716
35799
  await this._waitForTransitionEnd(feedEl, 450);
35717
35800
  feedEl.classList.remove("skw-flip-animating");
35718
35801
  feedEl.style.transformOrigin = "";
@@ -35720,9 +35803,10 @@ class FeedView {
35720
35803
  feedEl.style.scrollSnapType = "";
35721
35804
  feedEl.style.transform = "";
35722
35805
  feedEl.style.borderRadius = "";
35723
- this.feedManager.startObserver();
35724
- this.feedManager._activateItem(item.id);
35725
- this.overlayEl.classList.add("skw-feed-ready");
35806
+ chromeEls.forEach((el) => {
35807
+ el.style.opacity = "";
35808
+ el.style.transition = "";
35809
+ });
35726
35810
  this._escHandler = (e) => {
35727
35811
  if (e.key === "Escape") this.close();
35728
35812
  };
@@ -35749,6 +35833,12 @@ class FeedView {
35749
35833
  if (this.feedManager?.activeItemId && !canTransfer) {
35750
35834
  this.feedManager._deactivateItem(this.feedManager.activeItemId);
35751
35835
  }
35836
+ const targetItemId = canTransfer ? this._openItemId : activeItemId;
35837
+ if (targetItemId && this.feedManager) {
35838
+ const targetEl = this.feedManager.itemEls.get(targetItemId);
35839
+ if (targetEl) targetEl.scrollIntoView({ behavior: "instant", block: "start" });
35840
+ }
35841
+ const savedScrollTop = feedEl.scrollTop;
35752
35842
  feedEl.style.position = "fixed";
35753
35843
  feedEl.style.left = `${feedRect.left}px`;
35754
35844
  feedEl.style.top = `${feedRect.top}px`;
@@ -35760,7 +35850,20 @@ class FeedView {
35760
35850
  feedEl.style.aspectRatio = "unset";
35761
35851
  feedEl.style.maxHeight = "none";
35762
35852
  document.body.appendChild(feedEl);
35853
+ feedEl.scrollTop = savedScrollTop;
35763
35854
  this.overlayEl.classList.remove("skw-active", "skw-feed-ready");
35855
+ let thumbOverlay = null;
35856
+ if (this._openThumbnailUrl) {
35857
+ const targetItemId2 = canTransfer ? this._openItemId : activeItemId;
35858
+ const targetEl = targetItemId2 && this.feedManager?.itemEls.get(targetItemId2);
35859
+ const videoContainer = targetEl?.querySelector('[data-ref="videoContainer"]');
35860
+ if (videoContainer) {
35861
+ thumbOverlay = document.createElement("img");
35862
+ thumbOverlay.src = this._openThumbnailUrl;
35863
+ thumbOverlay.style.cssText = "position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .4s cubic-bezier(.32,.72,0,1);pointer-events:none;z-index:2;";
35864
+ videoContainer.appendChild(thumbOverlay);
35865
+ }
35866
+ }
35764
35867
  const slotRadius = parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--skw-radius").trim()) || 12;
35765
35868
  const scaleX = targetSlotRect.width / feedRect.width;
35766
35869
  const scaleY = targetSlotRect.height / feedRect.height;
@@ -35770,13 +35873,16 @@ class FeedView {
35770
35873
  feedEl.style.transformOrigin = "0 0";
35771
35874
  feedEl.style.overflow = "hidden";
35772
35875
  feedEl.style.scrollSnapType = "none";
35876
+ feedEl.style.pointerEvents = "none";
35773
35877
  feedEl.getBoundingClientRect();
35774
35878
  feedEl.classList.add("skw-flip-animating");
35775
35879
  requestAnimationFrame(() => {
35776
35880
  feedEl.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
35777
35881
  feedEl.style.borderRadius = `${endRadius}px`;
35882
+ if (thumbOverlay) thumbOverlay.style.opacity = "1";
35778
35883
  });
35779
35884
  await this._waitForTransitionEnd(feedEl, 450);
35885
+ if (thumbOverlay) thumbOverlay.remove();
35780
35886
  let transferVideo = null;
35781
35887
  let transferHls = null;
35782
35888
  if (canTransfer) {
@@ -35801,6 +35907,7 @@ class FeedView {
35801
35907
  feedEl.style.transformOrigin = "";
35802
35908
  feedEl.style.overflow = "";
35803
35909
  feedEl.style.scrollSnapType = "";
35910
+ feedEl.style.pointerEvents = "";
35804
35911
  feedEl.style.transform = "";
35805
35912
  feedEl.style.borderRadius = "";
35806
35913
  feedWrapper.insertBefore(feedEl, feedWrapper.firstChild);
@@ -36539,7 +36646,7 @@ const CSS = `
36539
36646
 
36540
36647
  /* Video container */
36541
36648
  .sk-video-container{position:absolute;inset:0;width:100%;height:100%;overflow:hidden;background-size:cover;background-position:center}
36542
- .sk-video-container video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .15s ease}
36649
+ .sk-video-container video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .35s ease}
36543
36650
 
36544
36651
  /* Tap zone */
36545
36652
  .sk-tap-zone{position:absolute;inset:0;z-index:3;cursor:pointer}
@@ -36555,7 +36662,7 @@ const CSS = `
36555
36662
 
36556
36663
  /* Widget slot */
36557
36664
  .skw-slot{position:relative;overflow:hidden;cursor:pointer}
36558
- .skw-slot video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .2s ease}
36665
+ .skw-slot video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .4s ease}
36559
36666
  .skw-slot-thumb{position:absolute;inset:0;background-size:cover;background-position:center}
36560
36667
  .skw-slot-overlay{position:absolute;inset:0;z-index:4;pointer-events:none}
36561
36668
  .skw-slot-overlay>*{pointer-events:auto}