@shortkitsdk/react-native 0.2.5 → 0.2.11

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.
Files changed (75) hide show
  1. package/ShortKitReactNative.podspec +1 -0
  2. package/android/build.gradle.kts +5 -1
  3. package/android/src/main/java/com/shortkit/reactnative/ReactCarouselOverlayHost.kt +319 -0
  4. package/android/src/main/java/com/shortkit/reactnative/ReactLoadingHost.kt +40 -0
  5. package/android/src/main/java/com/shortkit/reactnative/ReactOverlayHost.kt +559 -0
  6. package/android/src/main/java/com/shortkit/reactnative/ShortKitBridge.kt +984 -0
  7. package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedView.kt +88 -220
  8. package/android/src/main/java/com/shortkit/reactnative/ShortKitFeedViewManager.kt +12 -3
  9. package/android/src/main/java/com/shortkit/reactnative/ShortKitModule.kt +126 -706
  10. package/android/src/main/java/com/shortkit/reactnative/ShortKitPlayerNativeView.kt +2 -2
  11. package/android/src/main/java/com/shortkit/reactnative/ShortKitWidgetNativeView.kt +2 -2
  12. package/ios/ReactCarouselOverlayHost.swift +177 -0
  13. package/ios/ReactLoadingHost.swift +38 -0
  14. package/ios/ReactOverlayHost.swift +458 -0
  15. package/ios/SKFabricSurfaceWrapper.h +18 -0
  16. package/ios/SKFabricSurfaceWrapper.mm +57 -0
  17. package/ios/ShortKitBridge.swift +266 -65
  18. package/ios/ShortKitFeedView.swift +63 -207
  19. package/ios/ShortKitFeedViewManager.mm +3 -2
  20. package/ios/ShortKitModule.mm +86 -32
  21. package/ios/ShortKitPlayerNativeView.swift +39 -8
  22. package/ios/ShortKitReactNative-Bridging-Header.h +2 -0
  23. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +2 -1
  24. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +3998 -962
  25. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +85 -24
  26. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  27. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftinterface +85 -24
  28. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
  29. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +2 -1
  30. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +3998 -962
  31. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +85 -24
  32. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  33. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +85 -24
  34. package/ios/ShortKitSDK.xcframework/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
  35. package/ios/ShortKitSDK.xcframework.bak/Info.plist +43 -0
  36. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +418 -0
  37. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Info.plist +16 -0
  38. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +28917 -0
  39. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +824 -0
  40. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  41. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftinterface +824 -0
  42. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/Modules/module.modulemap +4 -0
  43. package/ios/ShortKitSDK.xcframework.bak/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
  44. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Headers/ShortKitSDK-Swift.h +418 -0
  45. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Info.plist +16 -0
  46. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +28917 -0
  47. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +824 -0
  48. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  49. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +824 -0
  50. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/Modules/module.modulemap +4 -0
  51. package/ios/ShortKitSDK.xcframework.bak/ios-arm64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
  52. package/ios/ShortKitWidgetNativeView.swift +3 -3
  53. package/package.json +1 -1
  54. package/src/ShortKitCarouselOverlaySurface.tsx +55 -0
  55. package/src/ShortKitCommands.ts +31 -0
  56. package/src/ShortKitContext.ts +11 -25
  57. package/src/ShortKitFeed.tsx +110 -41
  58. package/src/ShortKitLoadingSurface.tsx +24 -0
  59. package/src/ShortKitOverlaySurface.tsx +205 -0
  60. package/src/ShortKitPlayer.tsx +6 -7
  61. package/src/ShortKitProvider.tsx +65 -250
  62. package/src/index.ts +9 -4
  63. package/src/serialization.ts +22 -42
  64. package/src/specs/NativeShortKitModule.ts +67 -53
  65. package/src/specs/ShortKitFeedViewNativeComponent.ts +3 -2
  66. package/src/types.ts +104 -19
  67. package/src/useShortKit.ts +1 -3
  68. package/src/useShortKitPlayer.ts +7 -8
  69. package/android/src/main/java/com/shortkit/reactnative/ShortKitCarouselOverlayBridge.kt +0 -48
  70. package/android/src/main/java/com/shortkit/reactnative/ShortKitOverlayBridge.kt +0 -128
  71. package/ios/ShortKitCarouselOverlayBridge.swift +0 -54
  72. package/ios/ShortKitOverlayBridge.swift +0 -113
  73. package/src/CarouselOverlayManager.tsx +0 -71
  74. package/src/OverlayManager.tsx +0 -87
  75. package/src/useShortKitCarousel.ts +0 -29
@@ -1,54 +0,0 @@
1
- import UIKit
2
- import ShortKitSDK
3
-
4
- /// A transparent UIView that conforms to `CarouselOverlay` and bridges
5
- /// carousel overlay lifecycle calls to JS events via `ShortKitBridge`.
6
- ///
7
- /// The actual carousel overlay UI is rendered by React Native on the JS side
8
- /// through the `CarouselOverlayManager` component. This view simply relays
9
- /// the SDK lifecycle events so the JS carousel overlay knows when to
10
- /// configure, activate, reset, etc.
11
- @objc public class ShortKitCarouselOverlayBridge: UIView, @unchecked Sendable, CarouselOverlay {
12
-
13
- // MARK: - Bridge Reference
14
-
15
- /// Weak reference to the bridge, set by the factory closure in `parseFeedConfig`.
16
- weak var bridge: ShortKitBridge?
17
-
18
- // MARK: - State
19
-
20
- /// Stores the last configured ImageCarouselItem so we can pass it with
21
- /// lifecycle events that don't receive the item as a parameter.
22
- private var currentItem: ImageCarouselItem?
23
-
24
- // MARK: - Init
25
-
26
- override init(frame: CGRect) {
27
- super.init(frame: frame)
28
- backgroundColor = .clear
29
- isUserInteractionEnabled = true
30
- }
31
-
32
- required init?(coder: NSCoder) {
33
- fatalError("init(coder:) is not supported")
34
- }
35
-
36
- // MARK: - CarouselOverlay
37
-
38
- public func configure(with item: ImageCarouselItem) {
39
- currentItem = item
40
- bridge?.emitCarouselOverlayEvent("onCarouselOverlayConfigure", item: item)
41
- }
42
-
43
- public func resetState() {
44
- bridge?.emitCarouselOverlayEvent("onCarouselOverlayReset", body: [:])
45
- }
46
-
47
- public func fadeOutForTransition() {
48
- bridge?.emitCarouselOverlayEvent("onCarouselOverlayFadeOut", body: [:])
49
- }
50
-
51
- public func restoreFromTransition() {
52
- bridge?.emitCarouselOverlayEvent("onCarouselOverlayRestore", body: [:])
53
- }
54
- }
@@ -1,113 +0,0 @@
1
- import UIKit
2
- import ShortKitSDK
3
-
4
- /// A transparent UIView that conforms to `FeedOverlay` and bridges overlay
5
- /// lifecycle calls to JS events via `ShortKitBridge`.
6
- ///
7
- /// The actual overlay UI is rendered by React Native on the JS side through
8
- /// the `OverlayManager` component. This view simply relays the SDK lifecycle
9
- /// events so the JS overlay knows when to configure, activate, reset, etc.
10
- @objc public class ShortKitOverlayBridge: UIView, @unchecked Sendable, FeedOverlay {
11
-
12
- // MARK: - Bridge Reference
13
-
14
- /// Weak reference to the bridge, set by the factory closure in `parseFeedConfig`.
15
- weak var bridge: ShortKitBridge?
16
-
17
- // MARK: - State
18
-
19
- /// Stores the last configured ContentItem so we can pass it with lifecycle
20
- /// events that don't receive the item as a parameter.
21
- private var currentItem: ContentItem?
22
-
23
- /// Deferred configure emission — cancelled if `activatePlayback()` fires
24
- /// on the same run-loop iteration (meaning this was a handleSwipe
25
- /// re-configure of the active cell, not a prefetch for the next cell).
26
- private var pendingConfigureWorkItem: DispatchWorkItem?
27
-
28
- // MARK: - Init
29
-
30
- override init(frame: CGRect) {
31
- super.init(frame: frame)
32
- backgroundColor = .clear
33
- isUserInteractionEnabled = true
34
- setupGestures()
35
- }
36
-
37
- required init?(coder: NSCoder) {
38
- fatalError("init(coder:) is not supported")
39
- }
40
-
41
- // MARK: - Gestures
42
-
43
- private func setupGestures() {
44
- let doubleTap = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap(_:)))
45
- doubleTap.numberOfTapsRequired = 2
46
- addGestureRecognizer(doubleTap)
47
-
48
- let singleTap = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
49
- singleTap.require(toFail: doubleTap)
50
- addGestureRecognizer(singleTap)
51
- }
52
-
53
- @objc private func handleSingleTap() {
54
- bridge?.emitOverlayEvent("onOverlayTap", body: [:])
55
- }
56
-
57
- @objc private func handleDoubleTap(_ gesture: UITapGestureRecognizer) {
58
- let location = gesture.location(in: self)
59
- bridge?.emitOverlayEvent("onOverlayDoubleTap", body: [
60
- "x": location.x,
61
- "y": location.y,
62
- ])
63
- }
64
-
65
- // MARK: - FeedOverlay
66
-
67
- public func attach(player: ShortKitPlayer) {
68
- // No-op on the native side. The JS overlay subscribes to player
69
- // state via the TurboModule's Combine publishers.
70
- }
71
-
72
- public func configure(with item: ContentItem) {
73
- currentItem = item
74
-
75
- // Defer the configure event by one run-loop tick. If activatePlayback()
76
- // fires before then (handleSwipe sequence: configure → reset → activate),
77
- // the event is cancelled — preventing nextItem from being overwritten
78
- // with the current cell's data.
79
- pendingConfigureWorkItem?.cancel()
80
- let workItem = DispatchWorkItem { [weak self] in
81
- guard let self, let item = self.currentItem else { return }
82
- self.bridge?.emitOverlayEvent("onOverlayConfigure", item: item)
83
- self.pendingConfigureWorkItem = nil
84
- }
85
- pendingConfigureWorkItem = workItem
86
- DispatchQueue.main.async(execute: workItem)
87
- }
88
-
89
- public func resetPlaybackProgress() {
90
- guard let item = currentItem else { return }
91
- bridge?.emitOverlayEvent("onOverlayReset", item: item)
92
- }
93
-
94
- public func activatePlayback() {
95
- // Cancel the pending configure — it was for the current cell (part of
96
- // handleSwipe), not a prefetch for the next cell.
97
- pendingConfigureWorkItem?.cancel()
98
- pendingConfigureWorkItem = nil
99
-
100
- guard let item = currentItem else { return }
101
- bridge?.emitOverlayEvent("onOverlayActivate", item: item)
102
- }
103
-
104
- public func fadeOutForTransition() {
105
- guard let item = currentItem else { return }
106
- bridge?.emitOverlayEvent("onOverlayFadeOut", item: item)
107
- }
108
-
109
- public func restoreFromTransition() {
110
- guard let item = currentItem else { return }
111
- bridge?.emitOverlayEvent("onOverlayRestore", item: item)
112
- }
113
- }
@@ -1,71 +0,0 @@
1
- import React, { useContext, useMemo } from 'react';
2
- import { View, StyleSheet } from 'react-native';
3
- import type { CarouselOverlayConfig } from './types';
4
- import { ShortKitContext } from './ShortKitContext';
5
- import type { ShortKitContextValue } from './ShortKitContext';
6
-
7
- interface CarouselOverlayManagerProps {
8
- carouselOverlay: CarouselOverlayConfig;
9
- }
10
-
11
- /**
12
- * Internal component that renders TWO instances of the developer's custom
13
- * carousel overlay component — one for the current cell and one for the next.
14
- *
15
- * Works identically to `OverlayManager` but for image carousel cells.
16
- * The native side finds these views by their `nativeID` and applies
17
- * scroll-tracking transforms so each overlay moves with its respective
18
- * carousel cell during swipe transitions.
19
- */
20
- export function CarouselOverlayManager({ carouselOverlay }: CarouselOverlayManagerProps) {
21
- if (
22
- carouselOverlay === 'none' ||
23
- typeof carouselOverlay === 'string' ||
24
- carouselOverlay.type !== 'custom' ||
25
- !('component' in carouselOverlay)
26
- ) {
27
- return null;
28
- }
29
-
30
- const CarouselComponent = carouselOverlay.component;
31
-
32
- return (
33
- <>
34
- <View style={StyleSheet.absoluteFill} nativeID="carousel-overlay-current" pointerEvents="box-none">
35
- <CarouselComponent />
36
- </View>
37
- <View style={StyleSheet.absoluteFill} nativeID="carousel-overlay-next" pointerEvents="box-none">
38
- <NextCarouselOverlayProvider>
39
- <CarouselComponent />
40
- </NextCarouselOverlayProvider>
41
- </View>
42
- </>
43
- );
44
- }
45
-
46
- /**
47
- * Wraps children with a modified ShortKitContext where `currentCarouselItem`
48
- * is set to the provider's `nextCarouselItem`.
49
- */
50
- function NextCarouselOverlayProvider({ children }: { children: React.ReactNode }) {
51
- const context = useContext(ShortKitContext);
52
-
53
- const nextValue: ShortKitContextValue | null = useMemo(() => {
54
- if (!context) return null;
55
-
56
- return {
57
- ...context,
58
- currentCarouselItem: context.nextCarouselItem,
59
- isCarouselActive: context.nextCarouselItem != null,
60
- isCarouselTransitioning: false,
61
- };
62
- }, [context]);
63
-
64
- if (!nextValue) return <>{children}</>;
65
-
66
- return (
67
- <ShortKitContext.Provider value={nextValue}>
68
- {children}
69
- </ShortKitContext.Provider>
70
- );
71
- }
@@ -1,87 +0,0 @@
1
- import React, { useContext, useMemo } from 'react';
2
- import { View, StyleSheet } from 'react-native';
3
- import type { OverlayConfig, PlayerState } from './types';
4
- import { ShortKitContext } from './ShortKitContext';
5
- import type { ShortKitContextValue } from './ShortKitContext';
6
-
7
- interface OverlayManagerProps {
8
- overlay: OverlayConfig;
9
- }
10
-
11
- /**
12
- * Internal component that renders TWO instances of the developer's custom
13
- * overlay component — one for the current cell and one for the next cell.
14
- *
15
- * On the native side, `ShortKitFeedView` finds these views by their
16
- * `nativeID` and applies scroll-tracking transforms so each overlay moves
17
- * with its respective cell during swipe transitions — matching the native
18
- * iOS/Android SDK behavior where each cell has its own overlay instance.
19
- *
20
- * The "current" overlay uses the actual provider context.
21
- * The "next" overlay uses a context override where `currentItem = nextItem`
22
- * with initial playback state, so it renders the upcoming video's overlay
23
- * content before the user scrolls to it.
24
- */
25
- export function OverlayManager({ overlay }: OverlayManagerProps) {
26
- if (
27
- overlay === 'none' ||
28
- typeof overlay === 'string' ||
29
- overlay.type !== 'custom' ||
30
- !('component' in overlay)
31
- ) {
32
- return null;
33
- }
34
-
35
- const OverlayComponent = overlay.component;
36
-
37
- return (
38
- <>
39
- <View style={StyleSheet.absoluteFill} nativeID="overlay-current" pointerEvents="box-none">
40
- <OverlayComponent />
41
- </View>
42
- <View style={StyleSheet.absoluteFill} nativeID="overlay-next" pointerEvents="box-none">
43
- <NextOverlayProvider>
44
- <OverlayComponent />
45
- </NextOverlayProvider>
46
- </View>
47
- </>
48
- );
49
- }
50
-
51
- /**
52
- * Wraps children with a modified ShortKitContext where `currentItem` is
53
- * set to the provider's `nextItem` (the item configured for the upcoming
54
- * cell). Other state reflects an "about to play" initial state so the
55
- * overlay renders correctly before playback starts on that cell.
56
- */
57
- function NextOverlayProvider({ children }: { children: React.ReactNode }) {
58
- const context = useContext(ShortKitContext);
59
-
60
- const nextValue: ShortKitContextValue | null = useMemo(() => {
61
- if (!context) return null;
62
-
63
- return {
64
- ...context,
65
- currentItem: context.nextItem,
66
- isActive: context.nextItem != null,
67
- time: {
68
- current: 0,
69
- duration: context.nextItem?.duration ?? 0,
70
- buffered: 0,
71
- },
72
- playerState: 'idle' as PlayerState,
73
- isTransitioning: false,
74
- activeCue: null,
75
- lastOverlayTap: 0,
76
- lastOverlayDoubleTap: null,
77
- };
78
- }, [context]);
79
-
80
- if (!nextValue) return <>{children}</>;
81
-
82
- return (
83
- <ShortKitContext.Provider value={nextValue}>
84
- {children}
85
- </ShortKitContext.Provider>
86
- );
87
- }
@@ -1,29 +0,0 @@
1
- import { useContext } from 'react';
2
- import { ShortKitContext } from './ShortKitContext';
3
- import type { ImageCarouselItem } from './types';
4
-
5
- export interface ShortKitCarouselState {
6
- currentCarouselItem: ImageCarouselItem | null;
7
- isCarouselActive: boolean;
8
- isCarouselTransitioning: boolean;
9
- }
10
-
11
- /**
12
- * Hook to access carousel overlay state from the nearest ShortKitProvider.
13
- *
14
- * Use this inside a custom carousel overlay component to get the current
15
- * `ImageCarouselItem` data (images, title, description, etc.).
16
- *
17
- * Must be used within a `<ShortKitProvider>`.
18
- */
19
- export function useShortKitCarousel(): ShortKitCarouselState {
20
- const context = useContext(ShortKitContext);
21
- if (!context) {
22
- throw new Error('useShortKitCarousel must be used within a ShortKitProvider');
23
- }
24
- return {
25
- currentCarouselItem: context.currentCarouselItem,
26
- isCarouselActive: context.isCarouselActive,
27
- isCarouselTransitioning: context.isCarouselTransitioning,
28
- };
29
- }