@shortkitsdk/react-native 0.2.26 → 0.2.28

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 (36) hide show
  1. package/android/libs/shortkit-release.aar +0 -0
  2. package/android/src/main/java/com/shortkit/reactnative/ShortKitBridge.kt +8 -0
  3. package/android/src/main/java/com/shortkit/reactnative/ShortKitModule.kt +10 -0
  4. package/android/src/main/java/com/shortkit/reactnative/ShortKitPlayerNativeView.kt +4 -0
  5. package/android/src/main/java/com/shortkit/reactnative/ShortKitWidgetNativeView.kt +45 -33
  6. package/ios/ShortKitBridge.swift +8 -0
  7. package/ios/ShortKitFeedView.swift +10 -4
  8. package/ios/ShortKitModule.mm +11 -0
  9. package/ios/ShortKitPlayerNativeView.swift +7 -1
  10. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Info.plist +2 -2
  11. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.abi.json +213 -23
  12. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +6 -2
  13. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  14. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios.swiftinterface +6 -2
  15. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/ShortKitSDK +0 -0
  16. package/ios/ShortKitSDK.xcframework/ios-arm64/ShortKitSDK.framework/_CodeSignature/CodeResources +9 -9
  17. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Info.plist +2 -2
  18. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +213 -23
  19. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +6 -2
  20. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  21. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +6 -2
  22. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/x86_64-apple-ios-simulator.abi.json +213 -23
  23. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +6 -2
  24. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  25. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/Modules/ShortKitSDK.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +6 -2
  26. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/ShortKitSDK +0 -0
  27. package/ios/ShortKitSDK.xcframework/ios-arm64_x86_64-simulator/ShortKitSDK.framework/_CodeSignature/CodeResources +17 -17
  28. package/ios/ShortKitWidgetNativeView.swift +33 -12
  29. package/package.json +1 -1
  30. package/src/ShortKitFeed.tsx +3 -0
  31. package/src/ShortKitPlayer.tsx +25 -15
  32. package/src/ShortKitWidget.tsx +24 -18
  33. package/src/index.ts +1 -0
  34. package/src/serialization.ts +38 -0
  35. package/src/specs/NativeShortKitModule.ts +1 -0
  36. package/src/types.ts +19 -1
@@ -76,6 +76,9 @@ export const ShortKitFeed = forwardRef<ShortKitFeedHandle, ShortKitFeedProps>(
76
76
  applyFilter: (filter: FeedFilter | null) => {
77
77
  NativeShortKitModule?.applyFilter(feedId, filter ? JSON.stringify(filter) : null);
78
78
  },
79
+ refresh: () => {
80
+ NativeShortKitModule?.refresh(feedId);
81
+ },
79
82
  }), [feedId]);
80
83
 
81
84
  // Subscribe to per-feed remaining content count events
@@ -1,7 +1,11 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useLayoutEffect, useMemo } from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
3
  import type { ShortKitPlayerProps } from './types';
4
4
  import ShortKitPlayerView from './specs/ShortKitPlayerViewNativeComponent';
5
+ import { serializePlayerConfig } from './serialization';
6
+ import { registerOverlayComponent } from './ShortKitOverlaySurface';
7
+ import { registerCarouselOverlayComponent } from './ShortKitCarouselOverlaySurface';
8
+ import { registerVideoCarouselOverlayComponent } from './ShortKitVideoCarouselOverlaySurface';
5
9
 
6
10
  /**
7
11
  * Single-video player component. Displays one video with thumbnail fallback
@@ -19,21 +23,27 @@ export function ShortKitPlayer(props: ShortKitPlayerProps) {
19
23
 
20
24
  const clickAction = config?.clickAction ?? 'feed';
21
25
 
26
+ useLayoutEffect(() => {
27
+ if (config?.overlay && config.overlay !== 'none') {
28
+ registerOverlayComponent(config.overlay.name, config.overlay.component);
29
+ }
30
+ if (config?.feedConfig) {
31
+ const fc = config.feedConfig;
32
+ if (fc.overlay && fc.overlay !== 'none') {
33
+ registerOverlayComponent(fc.overlay.name, fc.overlay.component);
34
+ }
35
+ if (fc.carouselOverlay && fc.carouselOverlay !== 'none') {
36
+ registerCarouselOverlayComponent(fc.carouselOverlay.name, fc.carouselOverlay.component);
37
+ }
38
+ if (fc.videoCarouselOverlay && fc.videoCarouselOverlay !== 'none') {
39
+ registerVideoCarouselOverlayComponent(fc.videoCarouselOverlay.name, fc.videoCarouselOverlay.component);
40
+ }
41
+ }
42
+ }, [config?.overlay, config?.feedConfig]);
43
+
22
44
  const serializedConfig = useMemo(() => {
23
- const cfg = config ?? {};
24
- return JSON.stringify({
25
- cornerRadius: cfg.cornerRadius ?? 12,
26
- clickAction: clickAction,
27
- autoplay: cfg.autoplay ?? true,
28
- loop: cfg.loop ?? true,
29
- muteOnStart: cfg.muteOnStart ?? true,
30
- overlay: cfg.overlay
31
- ? typeof cfg.overlay === 'string'
32
- ? cfg.overlay
33
- : { type: 'custom' }
34
- : 'none',
35
- });
36
- }, [config, clickAction]);
45
+ return serializePlayerConfig(config ?? {});
46
+ }, [config]);
37
47
 
38
48
  const serializedItem = useMemo(() => {
39
49
  if (!contentItem) return undefined;
@@ -1,8 +1,12 @@
1
- import React, { useContext, useMemo } from 'react';
1
+ import React, { useContext, useLayoutEffect, useMemo } from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
3
  import type { ShortKitWidgetProps } from './types';
4
4
  import ShortKitWidgetView from './specs/ShortKitWidgetViewNativeComponent';
5
5
  import { ShortKitInitContext } from './ShortKitContext';
6
+ import { serializeWidgetConfig } from './serialization';
7
+ import { registerOverlayComponent } from './ShortKitOverlaySurface';
8
+ import { registerCarouselOverlayComponent } from './ShortKitCarouselOverlaySurface';
9
+ import { registerVideoCarouselOverlayComponent } from './ShortKitVideoCarouselOverlaySurface';
6
10
 
7
11
  /**
8
12
  * Horizontal carousel widget component. Displays a row of video cards
@@ -18,24 +22,26 @@ export function ShortKitWidget(props: ShortKitWidgetProps) {
18
22
  throw new Error('ShortKitWidget must be used within a ShortKitProvider');
19
23
  }
20
24
 
25
+ useLayoutEffect(() => {
26
+ if (config?.overlay && config.overlay !== 'none') {
27
+ registerOverlayComponent(config.overlay.name, config.overlay.component);
28
+ }
29
+ if (config?.feedConfig) {
30
+ const fc = config.feedConfig;
31
+ if (fc.overlay && fc.overlay !== 'none') {
32
+ registerOverlayComponent(fc.overlay.name, fc.overlay.component);
33
+ }
34
+ if (fc.carouselOverlay && fc.carouselOverlay !== 'none') {
35
+ registerCarouselOverlayComponent(fc.carouselOverlay.name, fc.carouselOverlay.component);
36
+ }
37
+ if (fc.videoCarouselOverlay && fc.videoCarouselOverlay !== 'none') {
38
+ registerVideoCarouselOverlayComponent(fc.videoCarouselOverlay.name, fc.videoCarouselOverlay.component);
39
+ }
40
+ }
41
+ }, [config?.overlay, config?.feedConfig]);
42
+
21
43
  const serializedConfig = useMemo(() => {
22
- const cfg = config ?? {};
23
- return JSON.stringify({
24
- cardCount: cfg.cardCount ?? 3,
25
- cardSpacing: cfg.cardSpacing ?? 8,
26
- cornerRadius: cfg.cornerRadius ?? 12,
27
- autoplay: cfg.autoplay ?? true,
28
- muteOnStart: cfg.muteOnStart ?? true,
29
- loop: cfg.loop ?? true,
30
- rotationInterval: cfg.rotationInterval ?? 10000,
31
- clickAction: cfg.clickAction ?? 'feed',
32
- overlay: cfg.overlay
33
- ? typeof cfg.overlay === 'string'
34
- ? cfg.overlay
35
- : { type: 'custom' }
36
- : 'none',
37
- filter: cfg.filter ? JSON.stringify(cfg.filter) : undefined,
38
- });
44
+ return serializeWidgetConfig(config ?? {});
39
45
  }, [config]);
40
46
 
41
47
  const serializedItems = useMemo(() => {
package/src/index.ts CHANGED
@@ -16,6 +16,7 @@ export type {
16
16
  PlayerConfig,
17
17
  PlayerClickAction,
18
18
  WidgetConfig,
19
+ WidgetInput,
19
20
 
20
21
  ContentItem,
21
22
  CarouselImage,
@@ -4,6 +4,9 @@ import type {
4
4
  FeedInput,
5
5
  PlayerState,
6
6
  PlayerTime,
7
+ WidgetConfig,
8
+ PlayerConfig,
9
+ OverlayConfig,
7
10
  VideoCarouselVideoInput,
8
11
  } from './types';
9
12
 
@@ -130,3 +133,38 @@ export function serializeFeedInputs(items: FeedInput[]): string {
130
133
  });
131
134
  return JSON.stringify(serialized);
132
135
  }
136
+
137
+ function serializeOverlay(overlay: OverlayConfig | undefined): string | { type: 'custom'; name: string } {
138
+ if (!overlay || overlay === 'none') return 'none';
139
+ return { type: 'custom', name: overlay.name };
140
+ }
141
+
142
+ export function serializeWidgetConfig(config: WidgetConfig): string {
143
+ const cfg = config ?? {};
144
+ return JSON.stringify({
145
+ cardCount: cfg.cardCount ?? 3,
146
+ cardSpacing: cfg.cardSpacing ?? 8,
147
+ cornerRadius: cfg.cornerRadius ?? 12,
148
+ autoplay: cfg.autoplay ?? true,
149
+ muteOnStart: cfg.muteOnStart ?? true,
150
+ loop: cfg.loop ?? true,
151
+ rotationInterval: cfg.rotationInterval ?? 10000,
152
+ clickAction: cfg.clickAction ?? 'feed',
153
+ overlay: serializeOverlay(cfg.overlay),
154
+ filter: cfg.filter ? JSON.stringify(cfg.filter) : undefined,
155
+ feedConfig: cfg.feedConfig ? serializeFeedConfig(cfg.feedConfig) : undefined,
156
+ });
157
+ }
158
+
159
+ export function serializePlayerConfig(config: PlayerConfig): string {
160
+ const cfg = config ?? {};
161
+ return JSON.stringify({
162
+ cornerRadius: cfg.cornerRadius ?? 12,
163
+ clickAction: cfg.clickAction ?? 'feed',
164
+ autoplay: cfg.autoplay ?? true,
165
+ loop: cfg.loop ?? true,
166
+ muteOnStart: cfg.muteOnStart ?? true,
167
+ overlay: serializeOverlay(cfg.overlay),
168
+ feedConfig: cfg.feedConfig ? serializeFeedConfig(cfg.feedConfig) : undefined,
169
+ });
170
+ }
@@ -284,6 +284,7 @@ export interface Spec extends TurboModule {
284
284
  appendFeedItems(feedId: string, items: string): void;
285
285
  fetchContent(limit: Int32, filterJSON: string | null): Promise<string>;
286
286
  applyFilter(feedId: string, filterJSON: string | null): void;
287
+ refresh(feedId: string): void;
287
288
  preloadFeed(configJSON: string, itemsJSON: string | null): Promise<string>;
288
289
 
289
290
  // --- Storyboard / seek thumbnails ---
package/src/types.ts CHANGED
@@ -408,6 +408,8 @@ export interface ShortKitFeedHandle {
408
408
  appendFeedItems: (items: FeedInput[]) => void;
409
409
  /** Apply a content filter to this feed instance. Pass null to clear. */
410
410
  applyFilter: (filter: FeedFilter | null) => void;
411
+ /** Programmatically trigger a feed refresh. No-op if already refreshing. */
412
+ refresh: () => void;
411
413
  }
412
414
 
413
415
  // --- Single Player Config ---
@@ -421,6 +423,7 @@ export interface PlayerConfig {
421
423
  loop?: boolean;
422
424
  muteOnStart?: boolean;
423
425
  overlay?: OverlayConfig;
426
+ feedConfig?: FeedConfig;
424
427
  }
425
428
 
426
429
  // --- Widget Config ---
@@ -436,8 +439,17 @@ export interface WidgetConfig {
436
439
  clickAction?: PlayerClickAction;
437
440
  overlay?: OverlayConfig;
438
441
  filter?: FeedFilter;
442
+ feedConfig?: FeedConfig;
439
443
  }
440
444
 
445
+ /**
446
+ * Compact input for widget items. Mirrors the video variant of `FeedInput` —
447
+ * host apps pass a playback ID and the SDK hydrates it into a full
448
+ * `ContentItem` internally (same resolver the feed uses).
449
+ */
450
+ export type WidgetInput =
451
+ | { type: 'video'; playbackId: string; origin?: ContentOrigin; fallbackUrl?: string };
452
+
441
453
  // --- Single Player Props ---
442
454
 
443
455
  export interface ShortKitPlayerProps {
@@ -455,7 +467,13 @@ export interface ShortKitPlayerProps {
455
467
 
456
468
  export interface ShortKitWidgetProps {
457
469
  config?: WidgetConfig;
458
- items?: ContentItem[];
470
+ /**
471
+ * Optional list of widget items to render. When provided, the widget
472
+ * skips its internal server fetch and renders these videos in order.
473
+ * Compact playback-ID form — the SDK hydrates URLs internally, matching
474
+ * how `<ShortKitFeed feedItems={...} />` works.
475
+ */
476
+ items?: WidgetInput[];
459
477
  style?: ViewStyle;
460
478
  }
461
479