@applicaster/zapp-react-native-ui-components 16.0.0-rc.4 → 16.0.0-rc.41

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 (100) hide show
  1. package/Components/BackgroundImage/BackgroundImage.android.tv.tsx +28 -0
  2. package/Components/BackgroundImage/BackgroundImage.ios.tv.tsx +24 -0
  3. package/Components/BackgroundImage/BackgroundImage.tsx +42 -0
  4. package/Components/BackgroundImage/index.ts +1 -0
  5. package/Components/CellRendererResolver/index.ts +2 -2
  6. package/Components/ComponentResolver/__tests__/componentResolver.test.js +1 -1
  7. package/Components/FocusableGroup/FocusableTvOS.tsx +11 -7
  8. package/Components/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +39 -0
  9. package/Components/GeneralContentScreen/__tests__/GeneralContentScreenHookAdapter.test.tsx +64 -0
  10. package/Components/GeneralContentScreen/__tests__/HookContentFocusGroup.web.test.tsx +91 -0
  11. package/Components/GeneralContentScreen/hookAdapter/__tests__/networkService.test.ts +74 -0
  12. package/Components/GeneralContentScreen/hookAdapter/__tests__/runInBackground.test.ts +139 -0
  13. package/Components/GeneralContentScreen/hookAdapter/__tests__/validationHelper.test.ts +124 -0
  14. package/Components/GeneralContentScreen/hookAdapter/logger.ts +6 -0
  15. package/Components/GeneralContentScreen/hookAdapter/networkService.ts +53 -0
  16. package/Components/GeneralContentScreen/hookAdapter/runInBackground.ts +48 -0
  17. package/Components/GeneralContentScreen/hookAdapter/validationHelper.ts +72 -0
  18. package/Components/GeneralContentScreen/hookFocus/index.tsx +13 -0
  19. package/Components/GeneralContentScreen/hookFocus/index.web.tsx +69 -0
  20. package/Components/GeneralContentScreen/index.ts +2 -0
  21. package/Components/Layout/FullWidthRow.tsx +38 -0
  22. package/Components/Layout/TV/ScreenContainer.tsx +5 -0
  23. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +0 -1
  24. package/Components/Layout/TV/index.tsx +3 -4
  25. package/Components/Layout/TV/index.web.tsx +2 -3
  26. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +16 -5
  27. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +47 -21
  28. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +34 -6
  29. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +1 -1
  30. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -3
  31. package/Components/MasterCell/DefaultComponents/PressableView.tsx +29 -9
  32. package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +4 -0
  33. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +154 -100
  34. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +15 -4
  35. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +56 -22
  36. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +6 -4
  37. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +3 -1
  38. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +32 -21
  39. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +15 -4
  40. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +23 -16
  41. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +8 -3
  42. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +2 -2
  43. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/insertButtonsBetweenLabels.test.ts +45 -13
  44. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +2 -2
  45. package/Components/MasterCell/contexts/PressedStateContext.ts +3 -0
  46. package/Components/MasterCell/dataAdapter.ts +15 -5
  47. package/Components/MasterCell/hooks/index.ts +2 -0
  48. package/Components/MasterCell/hooks/usePressedState.ts +4 -0
  49. package/Components/MasterCell/index.tsx +30 -5
  50. package/Components/MasterCell/utils/__tests__/resolveColor.test.js +169 -132
  51. package/Components/MasterCell/utils/__tests__/resolveColorForProp.test.js +92 -0
  52. package/Components/MasterCell/utils/index.ts +85 -46
  53. package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +332 -0
  54. package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +402 -0
  55. package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +811 -0
  56. package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +671 -0
  57. package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +878 -0
  58. package/Components/ModalComponent/AudioPlayer/Components/index.ts +9 -0
  59. package/Components/ModalComponent/BottomSheetModalContent.tsx +34 -18
  60. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +4 -85
  61. package/Components/OfflineHandler/__tests__/index.test.tsx +78 -18
  62. package/Components/OfflineHandler/hooks.ts +123 -0
  63. package/Components/OfflineHandler/index.tsx +51 -73
  64. package/Components/OfflineHandler/utils/index.ts +1 -13
  65. package/Components/PlayerContainer/PlayerContainer.tsx +14 -10
  66. package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +284 -0
  67. package/Components/PreloaderWrapper/index.tsx +1 -1
  68. package/Components/River/ComponentsMap/ComponentsMap.tsx +2 -2
  69. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +3 -15
  70. package/Components/Screen/TV/hooks/__tests__/useAfterPaint.test.ts +60 -0
  71. package/Components/Screen/TV/hooks/index.ts +2 -0
  72. package/Components/Screen/TV/hooks/useAfterPaint.ts +23 -0
  73. package/Components/Screen/TV/index.web.tsx +16 -7
  74. package/Components/Screen/index.tsx +8 -4
  75. package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +5 -3
  76. package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +1 -1
  77. package/Components/ScreenRevealManager/Overlay.tsx +34 -0
  78. package/Components/ScreenRevealManager/__tests__/Overlay.test.tsx +88 -0
  79. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +8 -19
  80. package/Components/TopCutoffOverlay/index.tsx +2 -2
  81. package/Components/Transitioner/Transitioner.tsx +28 -17
  82. package/Components/VideoLive/LiveImageManager.ts +56 -45
  83. package/Components/VideoLive/PlayerLiveImageComponent.tsx +4 -2
  84. package/Components/VideoModal/utils.ts +6 -1
  85. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +12 -5
  86. package/Components/ZappFrameworkComponents/BarView/__tests__/BarView.test.tsx +2 -2
  87. package/Contexts/CachedDimensionsContext/__tests__/index.test.ts +154 -0
  88. package/Contexts/CachedDimensionsContext/index.ts +17 -2
  89. package/Helpers/ComponentCellSelectionHelper/index.js +0 -6
  90. package/Helpers/index.js +7 -40
  91. package/package.json +5 -5
  92. package/Components/Layout/TV/LayoutBackground.tsx +0 -31
  93. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +0 -112
  94. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +0 -107
  95. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +0 -153
  96. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -66
  97. package/Components/OfflineHandler/NotificationView/utils.ts +0 -34
  98. package/Components/Screen/utils.ts +0 -16
  99. package/Helpers/Analytics/index.js +0 -95
  100. /package/Components/MasterCell/DefaultComponents/ButtonContainerView/{index.tv.android.tsx → index.android.tv.tsx} +0 -0
@@ -0,0 +1,332 @@
1
+ /**
2
+ * Modal Building Block — Action
3
+ *
4
+ * Single-file Expo Snack demo for the Action list item building block spec.
5
+ * Three forms (text only / leading icon + text / leading + text + trailing)
6
+ * are driven by data — no separate variants.
7
+ *
8
+ * Green (configurable): background, title, trailingIcon.chevronAsset
9
+ * White (hardcoded): container padding/gutter, icon size, leading icon assets,
10
+ * leading/trailing visibility logic from data
11
+ */
12
+
13
+ import React from "react";
14
+ import {
15
+ Image,
16
+ Platform,
17
+ Pressable,
18
+ StyleSheet,
19
+ Text,
20
+ View,
21
+ } from "react-native";
22
+
23
+ const styles = StyleSheet.create({
24
+ row: {
25
+ flexDirection: "row",
26
+ alignItems: "center",
27
+ },
28
+ demoScreen: {
29
+ flex: 1,
30
+ backgroundColor: "#1C1C1E",
31
+ paddingTop: 64,
32
+ paddingHorizontal: 16,
33
+ gap: 12,
34
+ },
35
+ demoHeading: {
36
+ color: "#FFFFFF",
37
+ fontSize: 20,
38
+ fontWeight: "600",
39
+ marginBottom: 8,
40
+ },
41
+ demoLabel: {
42
+ color: "#999999",
43
+ fontSize: 13,
44
+ marginTop: 8,
45
+ },
46
+ });
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // Configuration (green / editable fields from spec)
50
+ // ---------------------------------------------------------------------------
51
+
52
+ export type TextTransform =
53
+ | "default"
54
+ | "lowercase"
55
+ | "uppercase"
56
+ | "capitalize";
57
+
58
+ export type BackgroundConfiguration = {
59
+ defaultColor: string;
60
+ focusedColor: string;
61
+ cornerRadius: number;
62
+ };
63
+
64
+ export type TitleConfiguration = {
65
+ fontColor: string;
66
+ focusedFontColor: string;
67
+ iosFontFamily: string;
68
+ androidFontFamily: string;
69
+ fontSize: number;
70
+ lineHeight: number;
71
+ iosLetterSpacing: number;
72
+ androidLetterSpacing: number;
73
+ textTransform: TextTransform;
74
+ };
75
+
76
+ export type TrailingIconConfiguration = {
77
+ chevronAsset?: string;
78
+ };
79
+
80
+ export type ActionConfiguration = {
81
+ background: BackgroundConfiguration;
82
+ title: TitleConfiguration;
83
+ trailingIcon: TrailingIconConfiguration;
84
+ };
85
+
86
+ export const DEFAULT_BACKGROUND_CONFIGURATION: BackgroundConfiguration = {
87
+ defaultColor: "transparent",
88
+ focusedColor: "rgba(62, 62, 62, 1)",
89
+ cornerRadius: 12,
90
+ };
91
+
92
+ export const DEFAULT_TITLE_CONFIGURATION: TitleConfiguration = {
93
+ fontColor: "#FFFFFF",
94
+ focusedFontColor: "#FFFFFF",
95
+ iosFontFamily: "SFProText-Semibold",
96
+ androidFontFamily: "Roboto-Medium",
97
+ fontSize: 15,
98
+ lineHeight: 24,
99
+ iosLetterSpacing: -0.2,
100
+ androidLetterSpacing: 0,
101
+ textTransform: "default",
102
+ };
103
+
104
+ export const DEFAULT_TRAILING_ICON_CONFIGURATION: TrailingIconConfiguration =
105
+ {};
106
+
107
+ export const DEFAULT_ACTION_CONFIGURATION: ActionConfiguration = {
108
+ background: DEFAULT_BACKGROUND_CONFIGURATION,
109
+ title: DEFAULT_TITLE_CONFIGURATION,
110
+ trailingIcon: DEFAULT_TRAILING_ICON_CONFIGURATION,
111
+ };
112
+
113
+ // ---------------------------------------------------------------------------
114
+ // Data (runtime — controls which elements are shown)
115
+ // ---------------------------------------------------------------------------
116
+
117
+ export type LeadingActionType =
118
+ | "addToQueue"
119
+ | "addToPlaylist"
120
+ | "favorite"
121
+ | "share"
122
+ | "sleepTimer"
123
+ | "playbackSpeed";
124
+
125
+ export type ActionData = {
126
+ title: string;
127
+ /** When set, leading icon is shown (Enable: On). */
128
+ leadingActionType?: LeadingActionType;
129
+ /** When true, trailing chevron is shown (Enable: On). */
130
+ showTrailingChevron?: boolean;
131
+ };
132
+
133
+ export type AudioPlayerActionProps = {
134
+ configuration: ActionConfiguration;
135
+ data: ActionData;
136
+ focused?: boolean;
137
+ onPress?: () => void;
138
+ };
139
+
140
+ // ---------------------------------------------------------------------------
141
+ // Hardcoded spec values (white fields)
142
+ // ---------------------------------------------------------------------------
143
+
144
+ const CONTAINER_SPEC = {
145
+ paddingTop: 13,
146
+ paddingRight: 10,
147
+ paddingBottom: 13,
148
+ paddingLeft: 10,
149
+ horizontalGutter: 12,
150
+ };
151
+
152
+ const ICON_SPEC = {
153
+ width: 24,
154
+ height: 24,
155
+ };
156
+
157
+ const DEFAULT_CHEVRON_ASSET =
158
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAALElEQVR42mNgGAXUBlu2bPmPjIeWBeiGDy0Lhrbrh1/qGXqZaxSMglEw0gEA4c+IpUrpYX4AAAAASUVORK5CYII=";
159
+
160
+ /** Hardcoded: action type → leading icon asset (base64 PNG). */
161
+ const LEADING_ICON_ASSETS: Record<LeadingActionType, string> = {
162
+ addToQueue:
163
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAALElEQVR42mNgGAUjE/xHAzS3gFgweC0Y+nEwGslkBRFFwTj8LBjNyaNgmAMAJTf+EEEZcS0AAAAASUVORK5CYII=",
164
+ addToPlaylist:
165
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAKUlEQVR42mNgGAVDBvxHA6MWjFpAvEGkglELKLdgNJmOWkA7C0YBzQAAivu+UKRR1ZIAAAAASUVORK5CYII=",
166
+ favorite:
167
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAKklEQVR42mNgGAWjYBTgBP+xAGLkRi0YQhbgM4wqBo9aMHgsGAWjgCAAALyAZqh4yyZZAAAAAElFTkSuQmCC",
168
+ share:
169
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAK0lEQVR42mNgGAVDDvxHAqMWjFowUiz4TwQYgRYQYxBFlo1aMPAWjAK6AgD2g7pUUT7VeAAAAABJRU5ErkJggg==",
170
+ sleepTimer:
171
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAYUlEQVR42tWUSQ4AIAgD+f+n8eJRliIQ6MmEZTSxJZokvipdXgZpAbzOO17AglIXI7XULxmCoEMwRGuWam6AdRsN4IJYTRH4PIDkhxTA92zUPNBcFDDHaOVR0RJ2LXG9QgemFVK8tpo4PwAAAABJRU5ErkJggg==",
172
+ playbackSpeed:
173
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAK0lEQVR42mNgGAVDDvxHAqMWjFowUiz4TwQYgRYQYxBFlo1aMPAWjAK6AgD2g7pUUT7VeAAAAABJRU5ErkJggg==",
174
+ };
175
+
176
+ function getTextTransformStyle(
177
+ textTransform: TextTransform
178
+ ): "none" | "lowercase" | "uppercase" | "capitalize" {
179
+ return textTransform === "default" ? "none" : textTransform;
180
+ }
181
+
182
+ function shouldShowLeadingIcon(leadingActionType?: LeadingActionType) {
183
+ return !!leadingActionType;
184
+ }
185
+
186
+ function shouldShowTrailingIcon(showTrailingChevron?: boolean) {
187
+ return !!showTrailingChevron;
188
+ }
189
+
190
+ // ---------------------------------------------------------------------------
191
+ // Inner components
192
+ // ---------------------------------------------------------------------------
193
+
194
+ type ActionContainerProps = {
195
+ configuration: BackgroundConfiguration;
196
+ focused: boolean;
197
+ children: React.ReactNode;
198
+ onPress?: () => void;
199
+ };
200
+
201
+ function ActionContainer({
202
+ configuration,
203
+ focused,
204
+ children,
205
+ onPress,
206
+ }: ActionContainerProps) {
207
+ return (
208
+ <Pressable
209
+ onPress={onPress}
210
+ style={({ pressed }) => ({
211
+ backgroundColor:
212
+ pressed || focused
213
+ ? configuration.focusedColor
214
+ : configuration.defaultColor,
215
+ borderRadius: configuration.cornerRadius,
216
+ paddingTop: CONTAINER_SPEC.paddingTop,
217
+ paddingRight: CONTAINER_SPEC.paddingRight,
218
+ paddingBottom: CONTAINER_SPEC.paddingBottom,
219
+ paddingLeft: CONTAINER_SPEC.paddingLeft,
220
+ })}
221
+ >
222
+ {children}
223
+ </Pressable>
224
+ );
225
+ }
226
+
227
+ type ActionTitleProps = {
228
+ title: string;
229
+ configuration: TitleConfiguration;
230
+ focused: boolean;
231
+ };
232
+
233
+ function ActionTitle({ title, configuration, focused }: ActionTitleProps) {
234
+ const letterSpacing =
235
+ Platform.OS === "ios"
236
+ ? configuration.iosLetterSpacing
237
+ : configuration.androidLetterSpacing;
238
+
239
+ return (
240
+ <Text
241
+ style={{
242
+ flex: 1,
243
+ color: focused
244
+ ? configuration.focusedFontColor
245
+ : configuration.fontColor,
246
+ fontSize: configuration.fontSize,
247
+ lineHeight: configuration.lineHeight,
248
+ letterSpacing,
249
+ fontFamily: Platform.select({
250
+ ios: configuration.iosFontFamily,
251
+ android: configuration.androidFontFamily,
252
+ default: configuration.androidFontFamily,
253
+ }),
254
+ textTransform: getTextTransformStyle(configuration.textTransform),
255
+ }}
256
+ numberOfLines={1}
257
+ >
258
+ {title}
259
+ </Text>
260
+ );
261
+ }
262
+
263
+ type ActionLeadingIconProps = {
264
+ actionType: LeadingActionType;
265
+ };
266
+
267
+ function ActionLeadingIcon({ actionType }: ActionLeadingIconProps) {
268
+ return (
269
+ <Image
270
+ source={{ uri: LEADING_ICON_ASSETS[actionType] }}
271
+ style={{ width: ICON_SPEC.width, height: ICON_SPEC.height }}
272
+ resizeMode="contain"
273
+ />
274
+ );
275
+ }
276
+
277
+ type ActionTrailingIconProps = {
278
+ configuration: TrailingIconConfiguration;
279
+ };
280
+
281
+ function ActionTrailingIcon({ configuration }: ActionTrailingIconProps) {
282
+ const asset = configuration.chevronAsset ?? DEFAULT_CHEVRON_ASSET;
283
+
284
+ return (
285
+ <Image
286
+ source={{ uri: asset }}
287
+ style={{ width: ICON_SPEC.width, height: ICON_SPEC.height }}
288
+ resizeMode="contain"
289
+ />
290
+ );
291
+ }
292
+
293
+ // ---------------------------------------------------------------------------
294
+ // AudioPlayerAction
295
+ // ---------------------------------------------------------------------------
296
+
297
+ export function AudioPlayerAction({
298
+ configuration,
299
+ data,
300
+ focused = false,
301
+ onPress,
302
+ }: AudioPlayerActionProps) {
303
+ const { background, title, trailingIcon } = configuration;
304
+ const { title: label, leadingActionType, showTrailingChevron } = data;
305
+
306
+ const showLeading = shouldShowLeadingIcon(leadingActionType);
307
+ const showTrailing = shouldShowTrailingIcon(showTrailingChevron);
308
+
309
+ return (
310
+ <ActionContainer
311
+ configuration={background}
312
+ focused={focused}
313
+ onPress={onPress}
314
+ >
315
+ <View style={styles.row}>
316
+ {showLeading ? (
317
+ <>
318
+ <ActionLeadingIcon actionType={leadingActionType} />
319
+ <View style={{ width: CONTAINER_SPEC.horizontalGutter }} />
320
+ </>
321
+ ) : null}
322
+ <ActionTitle title={label} configuration={title} focused={focused} />
323
+ {showTrailing ? (
324
+ <>
325
+ <View style={{ width: CONTAINER_SPEC.horizontalGutter }} />
326
+ <ActionTrailingIcon configuration={trailingIcon} />
327
+ </>
328
+ ) : null}
329
+ </View>
330
+ </ActionContainer>
331
+ );
332
+ }