@applicaster/zapp-react-native-ui-components 16.0.0-alpha.8443457654 → 16.0.0-alpha.8525514228

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