@draftbit/core 54.0.4-6c949a.2 → 54.0.4-982952.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.
Files changed (110) hide show
  1. package/lib/commonjs/components/DeckSwiper/DeckSwiper.js +1 -1
  2. package/lib/commonjs/components/DeckSwiper/DeckSwiperCard.js +1 -1
  3. package/lib/commonjs/components/Layout/Spacer.js +1 -1
  4. package/lib/commonjs/components/LottieAnimation.js +1 -1
  5. package/lib/commonjs/components/MediaPlayer/AudioPlayer/AudioPlayerWithInterface.js +1 -1
  6. package/lib/commonjs/components/MediaPlayer/AudioPlayer/HeadlessAudioPlayer.js +1 -1
  7. package/lib/commonjs/components/MediaPlayer/MediaPlaybackWrapper.js +1 -1
  8. package/lib/commonjs/components/MediaPlayer/MediaPlayerCommon.js +1 -1
  9. package/lib/commonjs/components/MediaPlayer/VideoPlayer/VideoPlayer.js +1 -1
  10. package/lib/commonjs/components/Picker/PickerInputContainer.js +1 -1
  11. package/lib/commonjs/components/Progress/CircularProgress/CircularProgress.js +1 -1
  12. package/lib/commonjs/components/Progress/LinearProgress/LinearProgress.js +1 -1
  13. package/lib/commonjs/components/SVG.js +1 -1
  14. package/lib/commonjs/components/SVG.native.js +1 -1
  15. package/lib/commonjs/components/SectionList/SectionHeader.js +1 -1
  16. package/lib/commonjs/components/SwipeableItem/SwipeableItem.js +1 -1
  17. package/lib/commonjs/components/Swiper/Swiper.js +1 -1
  18. package/lib/commonjs/components/Swiper/SwiperItem.js +1 -1
  19. package/lib/commonjs/components/Table/TableCell.js +1 -1
  20. package/lib/commonjs/components/Table/TableRow.js +1 -1
  21. package/lib/commonjs/components/YoutubePlayer/YoutubePlayer.js +1 -1
  22. package/lib/typescript/src/components/DeckSwiper/DeckSwiper.d.ts +1 -0
  23. package/lib/typescript/src/components/DeckSwiper/DeckSwiper.js +3 -2
  24. package/lib/typescript/src/components/DeckSwiper/DeckSwiper.js.map +1 -1
  25. package/lib/typescript/src/components/DeckSwiper/DeckSwiperCard.d.ts +2 -2
  26. package/lib/typescript/src/components/DeckSwiper/DeckSwiperCard.js +3 -3
  27. package/lib/typescript/src/components/DeckSwiper/DeckSwiperCard.js.map +1 -1
  28. package/lib/typescript/src/components/Layout/Spacer.d.ts +2 -2
  29. package/lib/typescript/src/components/Layout/Spacer.js +2 -2
  30. package/lib/typescript/src/components/Layout/Spacer.js.map +1 -1
  31. package/lib/typescript/src/components/LottieAnimation.js +2 -2
  32. package/lib/typescript/src/components/LottieAnimation.js.map +1 -1
  33. package/lib/typescript/src/components/MediaPlayer/AudioPlayer/AudioPlayerCommon.d.ts +1 -0
  34. package/lib/typescript/src/components/MediaPlayer/AudioPlayer/AudioPlayerWithInterface.js +4 -2
  35. package/lib/typescript/src/components/MediaPlayer/AudioPlayer/AudioPlayerWithInterface.js.map +1 -1
  36. package/lib/typescript/src/components/MediaPlayer/AudioPlayer/HeadlessAudioPlayer.d.ts +3 -1
  37. package/lib/typescript/src/components/MediaPlayer/AudioPlayer/HeadlessAudioPlayer.js +69 -54
  38. package/lib/typescript/src/components/MediaPlayer/AudioPlayer/HeadlessAudioPlayer.js.map +1 -1
  39. package/lib/typescript/src/components/MediaPlayer/MediaPlaybackWrapper.d.ts +3 -2
  40. package/lib/typescript/src/components/MediaPlayer/MediaPlaybackWrapper.js +19 -21
  41. package/lib/typescript/src/components/MediaPlayer/MediaPlaybackWrapper.js.map +1 -1
  42. package/lib/typescript/src/components/MediaPlayer/MediaPlayerCommon.d.ts +5 -4
  43. package/lib/typescript/src/components/MediaPlayer/MediaPlayerCommon.js +3 -26
  44. package/lib/typescript/src/components/MediaPlayer/MediaPlayerCommon.js.map +1 -1
  45. package/lib/typescript/src/components/MediaPlayer/VideoPlayer/VideoPlayer.d.ts +14 -4
  46. package/lib/typescript/src/components/MediaPlayer/VideoPlayer/VideoPlayer.js +129 -62
  47. package/lib/typescript/src/components/MediaPlayer/VideoPlayer/VideoPlayer.js.map +1 -1
  48. package/lib/typescript/src/components/Picker/PickerCommon.d.ts +1 -0
  49. package/lib/typescript/src/components/Picker/PickerCommon.js.map +1 -1
  50. package/lib/typescript/src/components/Picker/PickerInputContainer.js +4 -2
  51. package/lib/typescript/src/components/Picker/PickerInputContainer.js.map +1 -1
  52. package/lib/typescript/src/components/Progress/CircularProgress/CircularProgress.js +4 -2
  53. package/lib/typescript/src/components/Progress/CircularProgress/CircularProgress.js.map +1 -1
  54. package/lib/typescript/src/components/Progress/LinearProgress/LinearProgress.js +4 -2
  55. package/lib/typescript/src/components/Progress/LinearProgress/LinearProgress.js.map +1 -1
  56. package/lib/typescript/src/components/Progress/ProgressCommon.d.ts +1 -0
  57. package/lib/typescript/src/components/SVG.d.ts +1 -0
  58. package/lib/typescript/src/components/SVG.js +4 -2
  59. package/lib/typescript/src/components/SVG.js.map +1 -1
  60. package/lib/typescript/src/components/SVG.native.d.ts +1 -0
  61. package/lib/typescript/src/components/SVG.native.js +4 -2
  62. package/lib/typescript/src/components/SVG.native.js.map +1 -1
  63. package/lib/typescript/src/components/SectionList/SectionHeader.d.ts +2 -2
  64. package/lib/typescript/src/components/SectionList/SectionHeader.js +1 -1
  65. package/lib/typescript/src/components/SectionList/SectionHeader.js.map +1 -1
  66. package/lib/typescript/src/components/SwipeableItem/SwipeableItem.d.ts +1 -0
  67. package/lib/typescript/src/components/SwipeableItem/SwipeableItem.js +4 -2
  68. package/lib/typescript/src/components/SwipeableItem/SwipeableItem.js.map +1 -1
  69. package/lib/typescript/src/components/Swiper/Swiper.d.ts +2 -2
  70. package/lib/typescript/src/components/Swiper/Swiper.js +2 -2
  71. package/lib/typescript/src/components/Swiper/Swiper.js.map +1 -1
  72. package/lib/typescript/src/components/Swiper/SwiperItem.d.ts +3 -3
  73. package/lib/typescript/src/components/Swiper/SwiperItem.js +2 -2
  74. package/lib/typescript/src/components/Swiper/SwiperItem.js.map +1 -1
  75. package/lib/typescript/src/components/Table/TableCell.d.ts +1 -0
  76. package/lib/typescript/src/components/Table/TableCell.js +4 -2
  77. package/lib/typescript/src/components/Table/TableCell.js.map +1 -1
  78. package/lib/typescript/src/components/Table/TableRow.d.ts +1 -0
  79. package/lib/typescript/src/components/Table/TableRow.js +4 -2
  80. package/lib/typescript/src/components/Table/TableRow.js.map +1 -1
  81. package/lib/typescript/src/components/YoutubePlayer/YoutubePlayer.js +2 -2
  82. package/lib/typescript/src/components/YoutubePlayer/YoutubePlayer.js.map +1 -1
  83. package/lib/typescript/src/components/YoutubePlayer/YoutubePlayerProps.d.ts +1 -0
  84. package/lib/typescript/tsconfig.tsbuildinfo +1 -1
  85. package/package.json +5 -4
  86. package/src/components/DeckSwiper/DeckSwiper.tsx +5 -1
  87. package/src/components/DeckSwiper/DeckSwiperCard.tsx +11 -3
  88. package/src/components/Layout/Spacer.tsx +4 -2
  89. package/src/components/LottieAnimation.tsx +1 -2
  90. package/src/components/MediaPlayer/AudioPlayer/AudioPlayerCommon.ts +1 -0
  91. package/src/components/MediaPlayer/AudioPlayer/AudioPlayerWithInterface.tsx +3 -0
  92. package/src/components/MediaPlayer/AudioPlayer/HeadlessAudioPlayer.tsx +84 -72
  93. package/src/components/MediaPlayer/MediaPlaybackWrapper.tsx +21 -24
  94. package/src/components/MediaPlayer/MediaPlayerCommon.ts +8 -34
  95. package/src/components/MediaPlayer/VideoPlayer/VideoPlayer.tsx +220 -86
  96. package/src/components/Picker/PickerCommon.ts +1 -0
  97. package/src/components/Picker/PickerInputContainer.tsx +7 -1
  98. package/src/components/Progress/CircularProgress/CircularProgress.tsx +3 -0
  99. package/src/components/Progress/LinearProgress/LinearProgress.tsx +3 -0
  100. package/src/components/Progress/ProgressCommon.ts +1 -0
  101. package/src/components/SVG.native.tsx +7 -1
  102. package/src/components/SVG.tsx +10 -1
  103. package/src/components/SectionList/SectionHeader.tsx +8 -3
  104. package/src/components/SwipeableItem/SwipeableItem.tsx +4 -0
  105. package/src/components/Swiper/Swiper.tsx +4 -3
  106. package/src/components/Swiper/SwiperItem.tsx +12 -4
  107. package/src/components/Table/TableCell.tsx +4 -0
  108. package/src/components/Table/TableRow.tsx +4 -0
  109. package/src/components/YoutubePlayer/YoutubePlayer.tsx +5 -1
  110. package/src/components/YoutubePlayer/YoutubePlayerProps.ts +1 -0
@@ -1,136 +1,233 @@
1
1
  import React from "react";
2
- import { ImageResizeMode, Platform } from "react-native";
3
2
  import {
4
- Video as VideoPlayerComponent,
5
- VideoProps as ExpoVideoProps,
6
- ResizeMode as ExpoResizeMode,
7
- AVPlaybackStatus,
8
- VideoFullscreenUpdate,
9
- AVPlaybackSource,
10
- Audio,
11
- } from "expo-av";
3
+ Image,
4
+ ImageProps,
5
+ ImageResizeMode,
6
+ StyleSheet,
7
+ View,
8
+ } from "react-native";
9
+ import {
10
+ VideoView as VideoPlayerComponent,
11
+ VideoViewProps as ExpoVideoProps,
12
+ VideoContentFit,
13
+ useVideoPlayer,
14
+ TimeUpdateEventPayload,
15
+ VideoPlayer as VideoPlayerType,
16
+ VideoSource,
17
+ } from "expo-video";
18
+ import { setAudioModeAsync } from "expo-audio";
12
19
  import { extractSizeStyles } from "../../../utilities";
13
20
  import MediaPlaybackWrapper from "../MediaPlaybackWrapper";
14
- import type { Playback } from "expo-av/src/AV";
15
21
  import {
16
- mapToMediaPlayerStatus,
17
22
  normalizeBase64Source,
18
23
  useSourceDeepCompareEffect,
24
+ useSourceDeepCompareMemoize,
25
+ } from "../MediaPlayerCommon";
26
+ import type {
27
+ MediaPlayerRef,
28
+ MediaPlayerProps,
29
+ MediaPlayerStatus,
19
30
  } from "../MediaPlayerCommon";
20
- import type { MediaPlayerRef, MediaPlayerProps } from "../MediaPlayerCommon";
21
31
 
22
32
  type ResizeMode = "contain" | "cover" | "stretch";
23
- type ExpoVideoPropsOmitted = Omit<
24
- ExpoVideoProps,
25
- "videoStyle" | "resizeMode" | "onPlaybackStatusUpdate" | "source"
26
- >;
33
+ type ExpoVideoPropsOmitted = Omit<ExpoVideoProps, "player" | "nativeControls">;
27
34
 
28
35
  interface VideoPlayerProps extends ExpoVideoPropsOmitted, MediaPlayerProps {
29
36
  resizeMode?: ResizeMode;
30
37
  posterResizeMode?: ImageResizeMode;
38
+ posterSource?: ImageProps["source"];
39
+ usePoster?: boolean;
31
40
  playsInSilentModeIOS?: boolean;
41
+ isMuted?: boolean;
42
+ useNativeControls?: boolean;
43
+ shouldPlay?: boolean;
44
+ isLooping?: boolean;
45
+ positionMillis?: number;
46
+ rate?: number;
47
+ volume?: number;
32
48
  }
33
49
 
34
50
  export interface VideoPlayerRef extends MediaPlayerRef {
35
51
  toggleFullscreen: () => void;
36
52
  }
37
53
 
38
- // Setting playsInSilentModeIOS prop directly on Video component is unreliable,
39
- // so we need to set the audio mode globally before playing.
40
- // See:
41
- // https://github.com/expo/expo/issues/7485
42
- // https://stackoverflow.com/questions/57371543/how-to-fix-video-play-but-dont-have-sound-on-ios-with-expo
43
- const triggerAudio = async (ref: React.RefObject<MediaPlayerRef | null>) => {
44
- if (ref && ref?.current && Platform.OS === "ios") {
45
- await Audio.setAudioModeAsync({ playsInSilentModeIOS: true });
46
- ref.current.play();
47
- }
48
- };
49
-
50
54
  const VideoPlayer = React.forwardRef<VideoPlayerRef, VideoPlayerProps>(
51
55
  (
52
56
  {
53
57
  style,
54
58
  resizeMode = "contain",
55
59
  posterResizeMode = "cover",
60
+ posterSource,
61
+ usePoster = false,
56
62
  onPlaybackStatusUpdate: onPlaybackStatusUpdateProp,
57
63
  onPlaybackFinish,
58
64
  source,
59
65
  playsInSilentModeIOS = false,
66
+ isMuted = false,
67
+ useNativeControls = true,
68
+ shouldPlay = false,
69
+ isLooping = false,
70
+ positionMillis,
71
+ allowsFullscreen = true,
72
+ rate = 1,
73
+ volume = 1,
60
74
  ...rest
61
75
  },
62
76
  ref
63
77
  ) => {
64
- const [videoMediaObject, setVideoMediaObject] =
65
- React.useState<VideoPlayerComponent | null>();
78
+ // @ts-ignore
79
+ const { className, ...videoPlayerProps } = rest;
80
+
81
+ const stableSource = useSourceDeepCompareMemoize(
82
+ normalizeBase64Source(source, "video")
83
+ );
84
+
85
+ const player = useVideoPlayer(stableSource, (p) => {
86
+ p.loop = isLooping;
87
+ p.muted = isMuted;
88
+ p.volume = volume;
89
+ p.playbackRate = rate;
90
+ });
91
+
92
+ const videoPlayerRef = React.useRef<VideoPlayerComponent>(null);
66
93
  const [isPlaying, setIsPlaying] = React.useState(false);
67
94
  const [isFullscreen, setIsFullscreen] = React.useState(false);
68
- const [currentSource, setCurrentSource] =
69
- React.useState<AVPlaybackSource>();
95
+ const [showPoster, setShowPoster] = React.useState(
96
+ usePoster && !!posterSource
97
+ );
98
+
70
99
  const mediaPlaybackWrapperRef = React.useRef<MediaPlayerRef>(null);
71
100
 
72
101
  const sizeStyles = extractSizeStyles(style);
73
102
 
74
- let mappedResizeMode;
103
+ React.useEffect(() => {
104
+ player.muted = isMuted;
105
+ }, [player, isMuted]);
106
+
107
+ React.useEffect(() => {
108
+ player.loop = isLooping;
109
+ }, [player, isLooping]);
110
+
111
+ React.useEffect(() => {
112
+ player.volume = volume;
113
+ }, [player, volume]);
114
+
115
+ React.useEffect(() => {
116
+ player.playbackRate = rate;
117
+ }, [player, rate]);
118
+
119
+ // Refs so statusChange can read latest shouldPlay/positionMillis
120
+ const shouldPlayRef = React.useRef(shouldPlay);
121
+ const positionMillisRef = React.useRef(positionMillis);
122
+ shouldPlayRef.current = shouldPlay;
123
+ positionMillisRef.current = positionMillis;
124
+
125
+ const hasAppliedInitialState = React.useRef(false);
126
+
127
+ React.useEffect(() => {
128
+ const timeUpdateSub = player.addListener("timeUpdate", (status) => {
129
+ onPlaybackStatusUpdateProp?.(mapToMediaPlayerStatus(status, player));
130
+ });
131
+
132
+ const playingChangeSub = player.addListener(
133
+ "playingChange",
134
+ ({ isPlaying: playing }) => {
135
+ setIsPlaying(playing);
136
+ onPlaybackStatusUpdateProp?.(mapPlayerToMediaPlayerStatus(player));
137
+ }
138
+ );
139
+
140
+ const playToEndSub = player.addListener("playToEnd", () => {
141
+ onPlaybackFinish?.();
142
+ });
143
+
144
+ const statusChangeSub = player.addListener(
145
+ "statusChange",
146
+ ({ status, error }) => {
147
+ if (status === "readyToPlay") {
148
+ setShowPoster(false);
149
+ if (!hasAppliedInitialState.current) {
150
+ hasAppliedInitialState.current = true;
151
+ if (positionMillisRef.current) {
152
+ player.currentTime = positionMillisRef.current / 1000;
153
+ }
154
+ if (shouldPlayRef.current) {
155
+ player.play();
156
+ }
157
+ }
158
+ }
159
+ const mappedStatus = mapPlayerToMediaPlayerStatus(player);
160
+ onPlaybackStatusUpdateProp?.(
161
+ status === "error" && error
162
+ ? { ...mappedStatus, isError: true, error: error.message }
163
+ : mappedStatus
164
+ );
165
+ }
166
+ );
167
+
168
+ return () => {
169
+ timeUpdateSub.remove();
170
+ playingChangeSub.remove();
171
+ playToEndSub.remove();
172
+ statusChangeSub.remove();
173
+ };
174
+ }, []);
175
+
176
+ // Replace video source when it changes (deep comparison on URI to avoid unnecessary reloads)
177
+ const isFirstSourceRender = React.useRef(true);
178
+ useSourceDeepCompareEffect(() => {
179
+ if (isFirstSourceRender.current) {
180
+ isFirstSourceRender.current = false;
181
+ return;
182
+ }
183
+ hasAppliedInitialState.current = false;
184
+ player.replace(normalizeBase64Source(source, "video") as VideoSource);
185
+ }, [source]);
186
+
187
+ let mappedVideoContentFit: VideoContentFit;
75
188
  switch (resizeMode) {
76
189
  case "contain":
77
- mappedResizeMode = ExpoResizeMode.CONTAIN;
190
+ mappedVideoContentFit = "contain";
78
191
  break;
79
192
  case "cover":
80
- mappedResizeMode = ExpoResizeMode.COVER;
193
+ mappedVideoContentFit = "cover";
81
194
  break;
82
195
  case "stretch":
83
- mappedResizeMode = ExpoResizeMode.STRETCH;
196
+ mappedVideoContentFit = "fill";
84
197
  break;
85
198
  }
86
199
 
87
- const onPlaybackStatusUpdate = (status: AVPlaybackStatus) => {
88
- const mappedStatus = mapToMediaPlayerStatus(status);
89
- onPlaybackStatusUpdateProp?.(mappedStatus);
90
-
91
- if (status.isLoaded) {
92
- if (status.didJustFinish) {
93
- onPlaybackFinish?.();
94
- }
95
- setIsPlaying(status.isPlaying);
96
- }
97
- };
98
-
99
- const onFullscreenUpdate = (fullscreenUpdate: VideoFullscreenUpdate) => {
100
- switch (fullscreenUpdate) {
101
- case VideoFullscreenUpdate.PLAYER_DID_PRESENT:
102
- case VideoFullscreenUpdate.PLAYER_WILL_PRESENT:
200
+ const onFullscreenUpdate = (type: "entered" | "exited") => {
201
+ switch (type) {
202
+ case "entered":
103
203
  setIsFullscreen(true);
104
204
  break;
105
- case VideoFullscreenUpdate.PLAYER_DID_DISMISS:
106
- case VideoFullscreenUpdate.PLAYER_WILL_DISMISS:
205
+ case "exited":
107
206
  setIsFullscreen(false);
108
207
  break;
109
208
  }
110
209
  };
111
210
 
112
211
  const toggleFullscreen = React.useCallback(async () => {
113
- if (isFullscreen) {
114
- await videoMediaObject?.dismissFullscreenPlayer();
115
- } else {
116
- await videoMediaObject?.presentFullscreenPlayer();
212
+ if (videoPlayerRef) {
213
+ if (isFullscreen) {
214
+ await videoPlayerRef.current?.exitFullscreen();
215
+ } else {
216
+ await videoPlayerRef.current?.enterFullscreen();
217
+ }
117
218
  }
118
- }, [isFullscreen, videoMediaObject]);
219
+ }, [isFullscreen]);
119
220
 
120
221
  const updateAudioMode = React.useCallback(async () => {
121
222
  try {
122
- await Audio.setAudioModeAsync({
123
- playsInSilentModeIOS,
223
+ await setAudioModeAsync({
224
+ playsInSilentMode: playsInSilentModeIOS,
124
225
  });
125
226
  } catch (e) {
126
227
  console.error("Failed to set audio mode. Error details:", e);
127
228
  }
128
229
  }, [playsInSilentModeIOS]);
129
230
 
130
- React.useEffect(() => {
131
- if (isPlaying) triggerAudio(mediaPlaybackWrapperRef);
132
- }, [mediaPlaybackWrapperRef, isPlaying]);
133
-
134
231
  React.useImperativeHandle(
135
232
  ref,
136
233
  () => ({
@@ -147,36 +244,73 @@ const VideoPlayer = React.forwardRef<VideoPlayerRef, VideoPlayerProps>(
147
244
  [toggleFullscreen, isPlaying]
148
245
  );
149
246
 
150
- useSourceDeepCompareEffect(() => {
151
- const updateSource = async () => {
152
- const finalSource = await normalizeBase64Source(source, "video");
153
- setCurrentSource(finalSource);
154
- };
155
- updateSource();
156
- }, [source]);
157
-
158
247
  return (
159
248
  <MediaPlaybackWrapper
160
- media={videoMediaObject as Playback | undefined}
249
+ player={player}
161
250
  isPlaying={isPlaying}
162
251
  ref={mediaPlaybackWrapperRef}
163
252
  onTogglePlayback={updateAudioMode}
164
253
  >
165
- <VideoPlayerComponent
166
- // https://docs.expo.dev/versions/latest/sdk/av/#example-video to see why ref is handled this way
167
- ref={(component) => setVideoMediaObject(component)}
168
- style={style}
169
- videoStyle={sizeStyles}
170
- resizeMode={mappedResizeMode}
171
- posterStyle={[sizeStyles, { resizeMode: posterResizeMode }]}
172
- onPlaybackStatusUpdate={onPlaybackStatusUpdate}
173
- onFullscreenUpdate={(e) => onFullscreenUpdate(e.fullscreenUpdate)}
174
- source={currentSource}
175
- {...rest}
176
- />
254
+ <View
255
+ style={[style, styles.container]}
256
+ // @ts-ignore
257
+ className={className}
258
+ >
259
+ <VideoPlayerComponent
260
+ ref={videoPlayerRef}
261
+ player={player}
262
+ nativeControls={useNativeControls}
263
+ style={sizeStyles}
264
+ contentFit={mappedVideoContentFit}
265
+ onFullscreenEnter={() => onFullscreenUpdate("entered")}
266
+ onFullscreenExit={() => onFullscreenUpdate("exited")}
267
+ allowsFullscreen={allowsFullscreen}
268
+ {...videoPlayerProps}
269
+ />
270
+ {showPoster && posterSource && (
271
+ <View style={StyleSheet.absoluteFill} pointerEvents="none">
272
+ <Image
273
+ source={posterSource}
274
+ resizeMode={posterResizeMode}
275
+ style={[StyleSheet.absoluteFill, sizeStyles]}
276
+ />
277
+ </View>
278
+ )}
279
+ </View>
177
280
  </MediaPlaybackWrapper>
178
281
  );
179
282
  }
180
283
  );
181
284
 
285
+ const styles = StyleSheet.create({
286
+ container: {
287
+ overflow: "hidden",
288
+ },
289
+ });
290
+
291
+ function mapPlayerToMediaPlayerStatus(
292
+ player: VideoPlayerType
293
+ ): MediaPlayerStatus {
294
+ return {
295
+ isPlaying: player.playing,
296
+ isLoading: player.status === "loading",
297
+ isBuffering: player.status === "loading",
298
+ currentPositionMillis: player.currentTime * 1000,
299
+ durationMillis: player.duration * 1000,
300
+ bufferedDurationMillis: player.bufferedPosition * 1000,
301
+ isError: player.status === "error",
302
+ };
303
+ }
304
+
305
+ export function mapToMediaPlayerStatus(
306
+ status: TimeUpdateEventPayload,
307
+ player: VideoPlayerType
308
+ ): MediaPlayerStatus {
309
+ return {
310
+ ...mapPlayerToMediaPlayerStatus(player),
311
+ currentPositionMillis: status.currentTime * 1000,
312
+ bufferedDurationMillis: status.bufferedPosition * 1000,
313
+ };
314
+ }
315
+
182
316
  export default VideoPlayer;
@@ -12,6 +12,7 @@ export interface PickerOption {
12
12
  }
13
13
 
14
14
  export interface PickerInputContainerProps extends IconSlot {
15
+ className?: string;
15
16
  error?: boolean;
16
17
  placeholder?: string;
17
18
  disabled?: boolean;
@@ -33,6 +33,7 @@ const PickerInputContainer: React.FC<
33
33
  options = [],
34
34
  onPress,
35
35
  Icon,
36
+ className,
36
37
  style,
37
38
  selectedValue,
38
39
  disabled = false,
@@ -70,7 +71,12 @@ const PickerInputContainer: React.FC<
70
71
  }
71
72
 
72
73
  return (
73
- <View testID={testID} style={[containerStyle, { zIndex }]}>
74
+ <View
75
+ testID={testID}
76
+ style={[containerStyle, { zIndex }]}
77
+ // @ts-ignore
78
+ className={className}
79
+ >
74
80
  <TextField
75
81
  Icon={Icon}
76
82
  numberOfLines={1}
@@ -41,6 +41,7 @@ export const CircularProgress: React.FC<
41
41
  trackCustomDashArray,
42
42
  onFullPathWidth,
43
43
  startPosition = "top",
44
+ className,
44
45
  style,
45
46
  testID,
46
47
  }) => {
@@ -128,6 +129,8 @@ export const CircularProgress: React.FC<
128
129
  },
129
130
  style,
130
131
  ]}
132
+ // @ts-ignore
133
+ className={className}
131
134
  >
132
135
  <Svg testID={testID ?? "circular-progress-component"} style={{ flex: 1 }}>
133
136
  {showTrack && (
@@ -37,6 +37,7 @@ export const LinearProgress: React.FC<ValueProgressProps> = ({
37
37
  customDashArray,
38
38
  trackCustomDashArray,
39
39
  onFullPathWidth,
40
+ className,
40
41
  style,
41
42
  testID,
42
43
  }) => {
@@ -101,6 +102,8 @@ export const LinearProgress: React.FC<ValueProgressProps> = ({
101
102
  },
102
103
  style,
103
104
  ]}
105
+ // @ts-ignore
106
+ className={className}
104
107
  >
105
108
  <Svg testID={testID ?? "linear-progress-component"} style={{ flex: 1 }}>
106
109
  {showTrack && (
@@ -25,6 +25,7 @@ export interface BaseProgressProps {
25
25
  customDashArray?: string;
26
26
  trackCustomDashArray?: string;
27
27
  onFullPathWidth?: (width: number) => void;
28
+ className?: string;
28
29
  style?: StyleProp<ViewStyle>;
29
30
  theme: ReadTheme;
30
31
  testID?: string;
@@ -7,14 +7,20 @@ import Config from "./Config";
7
7
  type SVGComponentProps = {
8
8
  source: string;
9
9
  style?: StyleProp<ImageStyle>;
10
+ className?: string;
10
11
  };
11
12
 
12
13
  const SVG: React.FC<React.PropsWithChildren<SVGComponentProps>> = ({
13
14
  source = Config.placeholderSvgURL,
14
15
  style,
16
+ className,
15
17
  }) => {
16
18
  return (
17
- <View style={style as StyleProp<ViewStyle>}>
19
+ <View
20
+ style={style as StyleProp<ViewStyle>}
21
+ // @ts-ignore
22
+ className={className}
23
+ >
18
24
  <SvgUri width="100%" height="100%" uri={source} />
19
25
  </View>
20
26
  );
@@ -6,13 +6,22 @@ import Config from "./Config";
6
6
  type SVGComponentProps = {
7
7
  source: string;
8
8
  style?: StyleProp<ImageStyle>;
9
+ className?: string;
9
10
  };
10
11
 
11
12
  const SVG: React.FC<React.PropsWithChildren<SVGComponentProps>> = ({
12
13
  source = Config.placeholderSvgURL,
13
14
  style,
15
+ className,
14
16
  }) => {
15
- return <Image style={style} source={{ uri: source }} />;
17
+ return (
18
+ <Image
19
+ style={style}
20
+ source={{ uri: source }}
21
+ // @ts-ignore
22
+ className={className}
23
+ />
24
+ );
16
25
  };
17
26
 
18
27
  export default SVG;
@@ -1,16 +1,21 @@
1
1
  import React from "react";
2
- import { View, StyleProp, ViewStyle, Text } from "react-native";
2
+ import { View, ViewProps, StyleProp, ViewStyle, Text } from "react-native";
3
3
  import { withTheme } from "@draftbit/theme";
4
4
  import type { ReadTheme } from "@draftbit/theme";
5
5
 
6
- interface SectionHeaderProps {
6
+ interface SectionHeaderProps extends Omit<ViewProps, "style" | "children"> {
7
7
  style?: StyleProp<ViewStyle>;
8
8
  }
9
9
 
10
10
  const SectionHeader: React.FC<React.PropsWithChildren<SectionHeaderProps>> = ({
11
11
  style,
12
12
  children,
13
- }) => <View style={style}>{children}</View>;
13
+ ...rest
14
+ }) => (
15
+ <View style={style} {...rest}>
16
+ {children}
17
+ </View>
18
+ );
14
19
 
15
20
  interface DefaultSectionHeaderProps {
16
21
  title: string;
@@ -50,6 +50,7 @@ import {
50
50
  */
51
51
 
52
52
  export interface SwipeableItemProps extends IconSlot {
53
+ className?: string;
53
54
  closeOnPress?: boolean;
54
55
  leftOpenValue?: number;
55
56
  rightOpenValue?: number;
@@ -74,6 +75,7 @@ type Props = SwipeableItemProps & RightSwipeProps & LeftSwipeProps;
74
75
 
75
76
  const SwipeableItem: React.FC<React.PropsWithChildren<Props>> = ({
76
77
  theme,
78
+ className,
77
79
  style,
78
80
  children: childrenProp,
79
81
  Icon,
@@ -232,6 +234,8 @@ const SwipeableItem: React.FC<React.PropsWithChildren<Props>> = ({
232
234
  setComponentWidth(event.nativeEvent.layout.width);
233
235
  }}
234
236
  style={[styles.parentContainer, parentContainerStyles]}
237
+ // @ts-ignore
238
+ className={className}
235
239
  >
236
240
  {/*@ts-ignore*/}
237
241
  <SwipeRow
@@ -1,6 +1,6 @@
1
1
  import { ReadTheme, withTheme } from "@draftbit/theme";
2
2
  import React, { forwardRef, useImperativeHandle } from "react";
3
- import { View, StyleProp, ViewStyle } from "react-native";
3
+ import { View, StyleProp, ViewStyle, ViewProps } from "react-native";
4
4
  import SwiperComponent from "react-native-web-swiper";
5
5
 
6
6
  export interface SwiperRef {
@@ -9,7 +9,7 @@ export interface SwiperRef {
9
9
  swipePrev: () => void;
10
10
  }
11
11
 
12
- export interface SwiperProps<T> {
12
+ export interface SwiperProps<T> extends Omit<ViewProps, "style" | "children"> {
13
13
  onSwipe?: (index: number) => void;
14
14
  onSwipedNext?: (index: number) => void;
15
15
  onSwipedPrevious?: (index: number) => void;
@@ -63,6 +63,7 @@ const Swiper = forwardRef<SwiperRef, SwiperProps<any>>(
63
63
  minDistanceToCapture,
64
64
  style,
65
65
  hideDots = false,
66
+ ...rest
66
67
  }: SwiperProps<any>,
67
68
  ref
68
69
  ) => {
@@ -141,7 +142,7 @@ const Swiper = forwardRef<SwiperRef, SwiperProps<any>>(
141
142
  }));
142
143
 
143
144
  return (
144
- <View style={style}>
145
+ <View style={style} {...rest}>
145
146
  {/* @ts-ignore */}
146
147
  <SwiperComponent
147
148
  ref={swiperRef}
@@ -1,5 +1,11 @@
1
1
  import React from "react";
2
- import { View, StyleSheet, StyleProp, ViewStyle } from "react-native";
2
+ import {
3
+ View,
4
+ StyleSheet,
5
+ StyleProp,
6
+ ViewStyle,
7
+ ViewProps,
8
+ } from "react-native";
3
9
 
4
10
  const styles = StyleSheet.create({
5
11
  wrapper: {
@@ -7,13 +13,15 @@ const styles = StyleSheet.create({
7
13
  },
8
14
  });
9
15
 
10
- export interface SwiperProps {
16
+ export interface SwiperProps extends Omit<ViewProps, "style" | "children"> {
11
17
  children: React.ReactNode;
12
18
  style?: StyleProp<ViewStyle>;
13
19
  }
14
20
 
15
- const SwiperItem = ({ children, style }: SwiperProps) => (
16
- <View style={[styles.wrapper, style]}>{children}</View>
21
+ const SwiperItem = ({ children, style, ...rest }: SwiperProps) => (
22
+ <View style={[styles.wrapper, style]} {...rest}>
23
+ {children}
24
+ </View>
17
25
  );
18
26
 
19
27
  export default SwiperItem;
@@ -10,6 +10,7 @@ import Pressable from "../Pressable";
10
10
  export interface Props extends TableProps {
11
11
  onPress?: () => void;
12
12
  style?: StyleProp<ViewStyle>;
13
+ className?: string;
13
14
  }
14
15
 
15
16
  const TableCell: React.FC<React.PropsWithChildren<Props>> = ({
@@ -24,6 +25,7 @@ const TableCell: React.FC<React.PropsWithChildren<Props>> = ({
24
25
  cellHorizontalPadding,
25
26
  children,
26
27
  onPress,
28
+ className,
27
29
  style,
28
30
  }) => {
29
31
  const parentContextValue = React.useContext(TableStyleContext);
@@ -42,6 +44,8 @@ const TableCell: React.FC<React.PropsWithChildren<Props>> = ({
42
44
  return (
43
45
  <ContainerComponent
44
46
  onPress={onPress}
47
+ // @ts-ignore
48
+ className={className}
45
49
  style={[
46
50
  styles.cellContainer,
47
51
  borderViewStyle,
@@ -14,6 +14,7 @@ export interface Props extends TableProps {
14
14
  onPress?: () => void;
15
15
  isTableHeader?: boolean;
16
16
  style?: StyleProp<ViewStyle>;
17
+ className?: string;
17
18
  theme: ReadTheme;
18
19
  }
19
20
 
@@ -30,6 +31,7 @@ const TableRow: React.FC<React.PropsWithChildren<Props>> = ({
30
31
  isTableHeader = false,
31
32
  children,
32
33
  onPress,
34
+ className,
33
35
  style,
34
36
  theme,
35
37
  }) => {
@@ -61,6 +63,8 @@ const TableRow: React.FC<React.PropsWithChildren<Props>> = ({
61
63
  <TableStyleContext.Provider value={contextValue}>
62
64
  <ContainerComponent
63
65
  onPress={onPress}
66
+ // @ts-ignore
67
+ className={className}
64
68
  style={[
65
69
  borderViewStyle,
66
70
  isTableHeader