@xhub-short/sdk 1.0.0-beta.18 → 1.0.0-beta.19

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/index.d.ts CHANGED
@@ -1718,6 +1718,130 @@ interface DefaultVideoSlotProps {
1718
1718
  }
1719
1719
  declare const DefaultVideoSlot: react.NamedExoticComponent<DefaultVideoSlotProps>;
1720
1720
 
1721
+ /**
1722
+ * Snap-back animation type
1723
+ * - 'none': Instant snap (no animation)
1724
+ * - 'ease': Smooth ease-out transition
1725
+ * - 'spring': Spring-like bounce effect
1726
+ */
1727
+ type SnapBackAnimation = 'none' | 'ease' | 'spring';
1728
+ /**
1729
+ * Configuration for useZoomGesture
1730
+ */
1731
+ interface UseZoomGestureConfig {
1732
+ /** Minimum scale factor (default: 1) */
1733
+ minScale?: number;
1734
+ /** Maximum scale factor (default: 5) */
1735
+ maxScale?: number;
1736
+ /** Whether to lock vertical swipe during zoom (default: true) */
1737
+ lockVerticalSwipe?: boolean;
1738
+ /**
1739
+ * Snap-back animation type (default: 'ease')
1740
+ * - 'none': Instant snap, onZoomEnd called immediately
1741
+ * - 'ease': Smooth ease-out, onZoomEnd called after duration
1742
+ * - 'spring': Spring bounce effect, onZoomEnd called after duration
1743
+ */
1744
+ snapBackAnimation?: SnapBackAnimation;
1745
+ /** Snap-back animation duration in ms (default: 200) */
1746
+ snapBackDuration?: number;
1747
+ /** Callback when zoom starts (scale > 1) */
1748
+ onZoomStart?: () => void;
1749
+ /** Callback when zoom ends (after snap-back animation completes) */
1750
+ onZoomEnd?: (finalScale: number) => void;
1751
+ /** Callback on scale change during gesture */
1752
+ onZoomChange?: (scale: number) => void;
1753
+ /** Whether zoom is enabled (default: true) */
1754
+ enabled?: boolean;
1755
+ }
1756
+ /**
1757
+ * Touch event handlers
1758
+ */
1759
+ interface ZoomGestureHandlers {
1760
+ onTouchStart: (e: react__default.TouchEvent) => void;
1761
+ onTouchMove: (e: react__default.TouchEvent) => void;
1762
+ onTouchEnd: (e: react__default.TouchEvent) => void;
1763
+ }
1764
+ /**
1765
+ * Return type for useZoomGesture
1766
+ */
1767
+ interface UseZoomGestureReturn {
1768
+ /** Current scale factor (1 = normal) */
1769
+ scale: number;
1770
+ /** Current X translation in pixels */
1771
+ translateX: number;
1772
+ /** Current Y translation in pixels */
1773
+ translateY: number;
1774
+ /** Whether actively zooming (2+ fingers) */
1775
+ isZooming: boolean;
1776
+ /** Whether currently panning while zoomed */
1777
+ isPanning: boolean;
1778
+ /** Whether snap-back animation is playing */
1779
+ isAnimating: boolean;
1780
+ /** Whether vertical swipe is locked */
1781
+ isSwipeLocked: boolean;
1782
+ /** Touch event handlers to spread on container */
1783
+ handlers: ZoomGestureHandlers;
1784
+ /** Manually reset to default state */
1785
+ reset: () => void;
1786
+ /** CSS transform string for convenience */
1787
+ transform: string;
1788
+ /** CSS transform-origin string */
1789
+ transformOrigin: string;
1790
+ /**
1791
+ * CSS styles for container element.
1792
+ * Includes `touchAction: 'none'` for proper gesture handling on mobile.
1793
+ * Always spread this on your container for best compatibility.
1794
+ */
1795
+ containerStyle: react__default.CSSProperties;
1796
+ /**
1797
+ * CSS transition string for snap-back animation.
1798
+ * Apply this to the transform property for smooth animations.
1799
+ */
1800
+ transitionStyle: react__default.CSSProperties;
1801
+ }
1802
+ /**
1803
+ * useZoomGesture - Pinch-to-zoom gesture handler
1804
+ *
1805
+ * Handles pinch gestures for video zoom with pan support.
1806
+ * Always snaps back to scale=1 on release (Instagram Reels behavior).
1807
+ *
1808
+ * @example
1809
+ * ```tsx
1810
+ * function VideoPlayer({ video }: { video: VideoItem }) {
1811
+ * const {
1812
+ * transform,
1813
+ * transformOrigin,
1814
+ * containerStyle,
1815
+ * handlers,
1816
+ * isZooming,
1817
+ * } = useZoomGesture({
1818
+ * onZoomStart: () => enterCleanMode('zoom'),
1819
+ * onZoomEnd: () => exitCleanMode(),
1820
+ * snapBackAnimation: 'ease', // smooth snap-back
1821
+ * });
1822
+ *
1823
+ * return (
1824
+ * <div
1825
+ * style={{
1826
+ * ...containerStyle, // includes touchAction: 'none' for proper gesture handling
1827
+ * transform,
1828
+ * transformOrigin,
1829
+ * }}
1830
+ * {...handlers}
1831
+ * >
1832
+ * <video src={video.url} />
1833
+ * </div>
1834
+ * );
1835
+ * }
1836
+ * ```
1837
+ *
1838
+ * @remarks
1839
+ * **Important:** Always spread `containerStyle` on your container element.
1840
+ * This sets `touchAction: 'none'` which is required for `preventDefault()` to work
1841
+ * on mobile browsers (Chrome 56+, Safari) where touch events are passive by default.
1842
+ */
1843
+ declare function useZoomGesture(config?: UseZoomGestureConfig): UseZoomGestureReturn;
1844
+
1721
1845
  /**
1722
1846
  * Minimum requirements for content used in SlotComposer
1723
1847
  */
@@ -1749,6 +1873,14 @@ interface ComposerState {
1749
1873
  isMenuOpen: boolean;
1750
1874
  /** Whether report sheet is open */
1751
1875
  isReportSheetOpen: boolean;
1876
+ /** Zoom transform property */
1877
+ zoomTransform: string;
1878
+ /** Zoom transform origin */
1879
+ zoomTransformOrigin: string;
1880
+ /** Zoom container style (includes touchAction: 'none') */
1881
+ zoomContainerStyle: React.CSSProperties;
1882
+ /** Zoom snap-back transition style */
1883
+ zoomTransitionStyle: React.CSSProperties;
1752
1884
  }
1753
1885
  /**
1754
1886
  * Handlers provided by SlotComposer
@@ -1772,6 +1904,8 @@ interface ComposerHandlers {
1772
1904
  setCommentSheetOpen: (open: boolean) => void;
1773
1905
  setMenuOpen: (open: boolean) => void;
1774
1906
  setReportSheetOpen: (open: boolean) => void;
1907
+ /** Pinch-to-zoom touch event handlers */
1908
+ zoomHandlers: ReturnType<typeof useZoomGesture>['handlers'];
1775
1909
  }
1776
1910
  /**
1777
1911
  * Pre-configured wired components
@@ -3725,130 +3859,6 @@ interface UseAdvancedControlsConfig {
3725
3859
  */
3726
3860
  declare function useAdvancedControls(config?: UseAdvancedControlsConfig): UseAdvancedControlsReturn;
3727
3861
 
3728
- /**
3729
- * Snap-back animation type
3730
- * - 'none': Instant snap (no animation)
3731
- * - 'ease': Smooth ease-out transition
3732
- * - 'spring': Spring-like bounce effect
3733
- */
3734
- type SnapBackAnimation = 'none' | 'ease' | 'spring';
3735
- /**
3736
- * Configuration for useZoomGesture
3737
- */
3738
- interface UseZoomGestureConfig {
3739
- /** Minimum scale factor (default: 1) */
3740
- minScale?: number;
3741
- /** Maximum scale factor (default: 5) */
3742
- maxScale?: number;
3743
- /** Whether to lock vertical swipe during zoom (default: true) */
3744
- lockVerticalSwipe?: boolean;
3745
- /**
3746
- * Snap-back animation type (default: 'ease')
3747
- * - 'none': Instant snap, onZoomEnd called immediately
3748
- * - 'ease': Smooth ease-out, onZoomEnd called after duration
3749
- * - 'spring': Spring bounce effect, onZoomEnd called after duration
3750
- */
3751
- snapBackAnimation?: SnapBackAnimation;
3752
- /** Snap-back animation duration in ms (default: 200) */
3753
- snapBackDuration?: number;
3754
- /** Callback when zoom starts (scale > 1) */
3755
- onZoomStart?: () => void;
3756
- /** Callback when zoom ends (after snap-back animation completes) */
3757
- onZoomEnd?: (finalScale: number) => void;
3758
- /** Callback on scale change during gesture */
3759
- onZoomChange?: (scale: number) => void;
3760
- /** Whether zoom is enabled (default: true) */
3761
- enabled?: boolean;
3762
- }
3763
- /**
3764
- * Touch event handlers
3765
- */
3766
- interface ZoomGestureHandlers {
3767
- onTouchStart: (e: react__default.TouchEvent) => void;
3768
- onTouchMove: (e: react__default.TouchEvent) => void;
3769
- onTouchEnd: (e: react__default.TouchEvent) => void;
3770
- }
3771
- /**
3772
- * Return type for useZoomGesture
3773
- */
3774
- interface UseZoomGestureReturn {
3775
- /** Current scale factor (1 = normal) */
3776
- scale: number;
3777
- /** Current X translation in pixels */
3778
- translateX: number;
3779
- /** Current Y translation in pixels */
3780
- translateY: number;
3781
- /** Whether actively zooming (2+ fingers) */
3782
- isZooming: boolean;
3783
- /** Whether currently panning while zoomed */
3784
- isPanning: boolean;
3785
- /** Whether snap-back animation is playing */
3786
- isAnimating: boolean;
3787
- /** Whether vertical swipe is locked */
3788
- isSwipeLocked: boolean;
3789
- /** Touch event handlers to spread on container */
3790
- handlers: ZoomGestureHandlers;
3791
- /** Manually reset to default state */
3792
- reset: () => void;
3793
- /** CSS transform string for convenience */
3794
- transform: string;
3795
- /** CSS transform-origin string */
3796
- transformOrigin: string;
3797
- /**
3798
- * CSS styles for container element.
3799
- * Includes `touchAction: 'none'` for proper gesture handling on mobile.
3800
- * Always spread this on your container for best compatibility.
3801
- */
3802
- containerStyle: react__default.CSSProperties;
3803
- /**
3804
- * CSS transition string for snap-back animation.
3805
- * Apply this to the transform property for smooth animations.
3806
- */
3807
- transitionStyle: react__default.CSSProperties;
3808
- }
3809
- /**
3810
- * useZoomGesture - Pinch-to-zoom gesture handler
3811
- *
3812
- * Handles pinch gestures for video zoom with pan support.
3813
- * Always snaps back to scale=1 on release (Instagram Reels behavior).
3814
- *
3815
- * @example
3816
- * ```tsx
3817
- * function VideoPlayer({ video }: { video: VideoItem }) {
3818
- * const {
3819
- * transform,
3820
- * transformOrigin,
3821
- * containerStyle,
3822
- * handlers,
3823
- * isZooming,
3824
- * } = useZoomGesture({
3825
- * onZoomStart: () => enterCleanMode('zoom'),
3826
- * onZoomEnd: () => exitCleanMode(),
3827
- * snapBackAnimation: 'ease', // smooth snap-back
3828
- * });
3829
- *
3830
- * return (
3831
- * <div
3832
- * style={{
3833
- * ...containerStyle, // includes touchAction: 'none' for proper gesture handling
3834
- * transform,
3835
- * transformOrigin,
3836
- * }}
3837
- * {...handlers}
3838
- * >
3839
- * <video src={video.url} />
3840
- * </div>
3841
- * );
3842
- * }
3843
- * ```
3844
- *
3845
- * @remarks
3846
- * **Important:** Always spread `containerStyle` on your container element.
3847
- * This sets `touchAction: 'none'` which is required for `preventDefault()` to work
3848
- * on mobile browsers (Chrome 56+, Safari) where touch events are passive by default.
3849
- */
3850
- declare function useZoomGesture(config?: UseZoomGestureConfig): UseZoomGestureReturn;
3851
-
3852
3862
  /**
3853
3863
  * useReportedVideo - Hook to check/manage reported video state
3854
3864
  *
package/dist/index.js CHANGED
@@ -4417,7 +4417,14 @@ function SlotComposer({
4417
4417
  const reactiveContent = useFeedSelector(
4418
4418
  (state) => state.itemsById.get(initialContent.id) ?? initialContent
4419
4419
  );
4420
- const { isZooming } = useZoomGesture({
4420
+ const {
4421
+ isZooming,
4422
+ transform,
4423
+ transformOrigin,
4424
+ containerStyle,
4425
+ transitionStyle,
4426
+ handlers: zoomHandlers
4427
+ } = useZoomGesture({
4421
4428
  enabled: true,
4422
4429
  maxScale: zoomMaxScale,
4423
4430
  snapBackAnimation: zoomSnapBackAnimation,
@@ -4498,6 +4505,10 @@ function SlotComposer({
4498
4505
  state: {
4499
4506
  cleanMode,
4500
4507
  isZoomActive: isZooming,
4508
+ zoomTransform: transform,
4509
+ zoomTransformOrigin: transformOrigin,
4510
+ zoomContainerStyle: containerStyle,
4511
+ zoomTransitionStyle: transitionStyle,
4501
4512
  isLiked: reactiveContent.isLiked ?? false,
4502
4513
  isBookmarked,
4503
4514
  isCommentSheetOpen,
@@ -4514,7 +4525,8 @@ function SlotComposer({
4514
4525
  handleCloseAll,
4515
4526
  setCommentSheetOpen,
4516
4527
  setMenuOpen,
4517
- setReportSheetOpen
4528
+ setReportSheetOpen,
4529
+ zoomHandlers
4518
4530
  },
4519
4531
  components: {
4520
4532
  ActionBarComponent: ({ icons, onOpenComments: onOpenC, onShare: onS }) => {
@@ -4577,6 +4589,11 @@ function SlotComposer({
4577
4589
  initialContent.id,
4578
4590
  cleanMode,
4579
4591
  isZooming,
4592
+ transform,
4593
+ transformOrigin,
4594
+ containerStyle,
4595
+ transitionStyle,
4596
+ zoomHandlers,
4580
4597
  isBookmarked,
4581
4598
  isCommentSheetOpen,
4582
4599
  isMenuOpen,
@@ -5438,7 +5455,23 @@ function DefaultVideoSlotContent(props) {
5438
5455
  disableTap: enableZoom && isZoomActive,
5439
5456
  onHidden: () => onContentHidden?.(video.id),
5440
5457
  children: [
5441
- renderPlayer ? renderPlayer({ muted: false }) : /* @__PURE__ */ jsx(VideoPlayer, { muted: false }),
5458
+ enableZoom ? /* @__PURE__ */ jsx(
5459
+ "div",
5460
+ {
5461
+ style: {
5462
+ ...state.zoomContainerStyle,
5463
+ transform: state.zoomTransform,
5464
+ transformOrigin: state.zoomTransformOrigin,
5465
+ transition: state.zoomTransitionStyle.transition,
5466
+ position: "absolute",
5467
+ inset: 0,
5468
+ width: "100%",
5469
+ height: "100%"
5470
+ },
5471
+ ...handlers.zoomHandlers,
5472
+ children: renderPlayer ? renderPlayer({ muted: false }) : /* @__PURE__ */ jsx(VideoPlayer, { muted: false })
5473
+ }
5474
+ ) : renderPlayer ? renderPlayer({ muted: false }) : /* @__PURE__ */ jsx(VideoPlayer, { muted: false }),
5442
5475
  showPoster && !isZoomActive && !cleanMode && /* @__PURE__ */ jsx(VideoSlotPoster, {}),
5443
5476
  showPlayIndicator && !isZoomActive && /* @__PURE__ */ jsx(VideoSlotPlayIndicator, { persistWhenPaused: persistPlayIndicatorWhenPaused }),
5444
5477
  showLikeAnimation && /* @__PURE__ */ jsx(
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xhub-short/sdk",
3
3
  "sideEffects": false,
4
- "version": "1.0.0-beta.18",
4
+ "version": "1.0.0-beta.19",
5
5
  "type": "module",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -21,13 +21,13 @@
21
21
  ],
22
22
  "dependencies": {
23
23
  "zustand": "^5.0.0",
24
- "@xhub-short/adapters": "1.0.0-beta.18",
25
- "@xhub-short/ui": "1.0.0-beta.18",
26
- "@xhub-short/core": "1.0.0-beta.18",
27
- "@xhub-short/contracts": "1.0.0-beta.18"
24
+ "@xhub-short/adapters": "1.0.0-beta.19",
25
+ "@xhub-short/contracts": "1.0.0-beta.19",
26
+ "@xhub-short/ui": "1.0.0-beta.19",
27
+ "@xhub-short/core": "1.0.0-beta.19"
28
28
  },
29
29
  "optionalDependencies": {
30
- "@xhub-short/bridge": "0.1.0-beta.17"
30
+ "@xhub-short/bridge": "0.1.0-beta.18"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "react": "^19.0.0",