@applicaster/zapp-react-native-ui-components 16.0.0-rc.11 → 16.0.0-rc.111

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 (156) hide show
  1. package/Components/AudioPlayer/tv/__tests__/audioPlayer.test.js +19 -0
  2. package/Components/AudioPlayer/tv/__tests__/index.test.tsx +120 -0
  3. package/Components/AudioPlayer/tv/index.tsx +5 -1
  4. package/Components/Cell/Cell.tsx +3 -6
  5. package/Components/Cell/TvOSCellComponent.tsx +0 -1
  6. package/Components/CellRendererResolver/index.ts +2 -2
  7. package/Components/ComponentResolver/__tests__/componentResolver.test.js +1 -1
  8. package/Components/FocusableGroup/FocusableTvOS.tsx +11 -7
  9. package/Components/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +54 -0
  10. package/Components/GeneralContentScreen/__tests__/GeneralContentScreenHookAdapter.test.tsx +64 -0
  11. package/Components/GeneralContentScreen/__tests__/HookContentFocusGroup.web.test.tsx +91 -0
  12. package/Components/GeneralContentScreen/hookAdapter/__tests__/networkService.test.ts +74 -0
  13. package/Components/GeneralContentScreen/hookAdapter/__tests__/runInBackground.test.ts +139 -0
  14. package/Components/GeneralContentScreen/hookAdapter/__tests__/skipExpression.test.ts +294 -0
  15. package/Components/GeneralContentScreen/hookAdapter/__tests__/validationHelper.test.ts +188 -0
  16. package/Components/GeneralContentScreen/hookAdapter/logger.ts +6 -0
  17. package/Components/GeneralContentScreen/hookAdapter/networkService.ts +53 -0
  18. package/Components/GeneralContentScreen/hookAdapter/runInBackground.ts +48 -0
  19. package/Components/GeneralContentScreen/hookAdapter/skipExpression.ts +252 -0
  20. package/Components/GeneralContentScreen/hookAdapter/validationHelper.ts +90 -0
  21. package/Components/GeneralContentScreen/hookFocus/index.tsx +13 -0
  22. package/Components/GeneralContentScreen/hookFocus/index.web.tsx +69 -0
  23. package/Components/GeneralContentScreen/index.ts +2 -0
  24. package/Components/Layout/FullWidthRow.tsx +38 -0
  25. package/Components/LinkHandler/LinkHandler.tsx +2 -7
  26. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +5 -1
  27. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +47 -21
  28. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/ActionButtonController.tsx +19 -4
  29. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +43 -1
  30. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +34 -6
  31. package/Components/MasterCell/DefaultComponents/Button.tsx +1 -0
  32. package/Components/MasterCell/DefaultComponents/Image/hoc/utils/__tests__/withDimensions.test.ts +420 -125
  33. package/Components/MasterCell/DefaultComponents/Image/hoc/utils/index.ts +114 -19
  34. package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +19 -8
  35. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -3
  36. package/Components/MasterCell/DefaultComponents/LiveImage/executePreloadHooks.ts +2 -4
  37. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +2 -3
  38. package/Components/MasterCell/DefaultComponents/PressableView.tsx +29 -9
  39. package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +4 -0
  40. package/Components/MasterCell/DefaultComponents/Toggle.tsx +36 -14
  41. package/Components/MasterCell/DefaultComponents/__tests__/Toggle.test.tsx +167 -0
  42. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +154 -100
  43. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +15 -4
  44. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +56 -22
  45. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +6 -4
  46. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +3 -1
  47. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +32 -21
  48. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +15 -4
  49. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +23 -16
  50. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +8 -3
  51. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +2 -2
  52. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/insertButtonsBetweenLabels.test.ts +45 -13
  53. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +2 -2
  54. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/factory.test.ts +32 -0
  55. package/Components/MasterCell/contexts/PressedStateContext.ts +3 -0
  56. package/Components/MasterCell/dataAdapter.ts +15 -5
  57. package/Components/MasterCell/hooks/index.ts +2 -0
  58. package/Components/MasterCell/hooks/usePressedState.ts +4 -0
  59. package/Components/MasterCell/index.tsx +30 -5
  60. package/Components/MasterCell/utils/__tests__/resolveColor.test.js +169 -132
  61. package/Components/MasterCell/utils/__tests__/resolveColorForProp.test.js +92 -0
  62. package/Components/MasterCell/utils/index.ts +85 -46
  63. package/Components/ModalComponent/ActionsBottomSheet/ActionButton.tsx +56 -0
  64. package/Components/ModalComponent/ActionsBottomSheet/__tests__/openActionsBottomSheet.test.ts +38 -0
  65. package/Components/ModalComponent/ActionsBottomSheet/boundActionButton.tsx +24 -0
  66. package/Components/ModalComponent/ActionsBottomSheet/index.ts +9 -0
  67. package/Components/ModalComponent/ActionsBottomSheet/openActionsBottomSheet.ts +61 -0
  68. package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +392 -0
  69. package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +772 -0
  70. package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +728 -0
  71. package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +1028 -0
  72. package/Components/ModalComponent/AudioPlayer/Components/NowPlayingHeaderSection.tsx +205 -0
  73. package/Components/ModalComponent/AudioPlayer/Components/__tests__/Item.test.tsx +164 -0
  74. package/Components/ModalComponent/AudioPlayer/Components/__tests__/NowPlayingHeaderSection.test.tsx +36 -0
  75. package/Components/ModalComponent/AudioPlayer/Components/index.ts +9 -0
  76. package/Components/ModalComponent/AudioPlayer/utils/__tests__/mergeStyles.test.ts +393 -0
  77. package/Components/ModalComponent/AudioPlayer/utils/mergeStyles.ts +523 -0
  78. package/Components/ModalComponent/BottomSheetDragArea.tsx +33 -0
  79. package/Components/ModalComponent/BottomSheetModalContent.tsx +436 -50
  80. package/Components/ModalComponent/Button/index.tsx +5 -3
  81. package/Components/ModalComponent/Header/CloseButton.tsx +12 -0
  82. package/Components/ModalComponent/Header/__tests__/CloseButton.test.tsx +72 -0
  83. package/Components/ModalComponent/Header/index.tsx +20 -7
  84. package/Components/ModalComponent/Header/utils.ts +1 -1
  85. package/Components/ModalComponent/ModalBlocksStyleContext.tsx +10 -0
  86. package/Components/ModalComponent/SortableList.tsx +156 -0
  87. package/Components/ModalComponent/SortableList.web.tsx +34 -0
  88. package/Components/ModalComponent/TextInputContent.tsx +135 -0
  89. package/Components/ModalComponent/__tests__/BottomSheetDragArea.test.tsx +74 -0
  90. package/Components/ModalComponent/__tests__/BottomSheetModalContent.test.tsx +343 -0
  91. package/Components/ModalComponent/__tests__/SortableList.web.test.tsx +16 -0
  92. package/Components/ModalComponent/__tests__/TextInputContent.test.tsx +169 -0
  93. package/Components/ModalComponent/__tests__/showTextInput.test.ts +95 -0
  94. package/Components/ModalComponent/index.tsx +18 -9
  95. package/Components/ModalComponent/presets/__tests__/getCell.test.ts +90 -0
  96. package/Components/ModalComponent/presets/dynamicCollectionCell.tsx +78 -0
  97. package/Components/ModalComponent/presets/index.ts +27 -0
  98. package/Components/ModalComponent/presets/selectableCell.tsx +28 -0
  99. package/Components/ModalComponent/presets/standardCell.tsx +41 -0
  100. package/Components/ModalComponent/presets/types.ts +35 -0
  101. package/Components/ModalComponent/showTextInput.ts +52 -0
  102. package/Components/ModalComponent/utils.ts +82 -21
  103. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +4 -85
  104. package/Components/OfflineHandler/__tests__/index.test.tsx +186 -17
  105. package/Components/OfflineHandler/hooks.ts +111 -0
  106. package/Components/OfflineHandler/index.tsx +91 -75
  107. package/Components/OfflineHandler/utils/index.ts +1 -13
  108. package/Components/PlayerContainer/PlayerContainer.tsx +33 -18
  109. package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -4
  110. package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +337 -0
  111. package/Components/PreloaderWrapper/index.tsx +1 -1
  112. package/Components/River/ComponentsMap/ComponentsMap.tsx +87 -61
  113. package/Components/River/River.tsx +4 -0
  114. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +140 -89
  115. package/Components/River/__tests__/componentsMap.test.js +8 -3
  116. package/Components/River/__tests__/resultCallback.test.tsx +47 -0
  117. package/Components/Screen/__tests__/Screen.test.tsx +24 -0
  118. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -0
  119. package/Components/Screen/index.tsx +13 -4
  120. package/Components/Screen/navigationHandler.ts +8 -8
  121. package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +5 -3
  122. package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +1 -1
  123. package/Components/ScreenRevealManager/ScreenRevealManager.ts +18 -2
  124. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +36 -0
  125. package/Components/ScreenRevealManager/__tests__/withScreenRevealManager.test.tsx +56 -0
  126. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +21 -4
  127. package/Components/TopCutoffOverlay/index.tsx +2 -2
  128. package/Components/Transitioner/AnimationManager.js +1 -1
  129. package/Components/Transitioner/Scene.tsx +4 -3
  130. package/Components/Transitioner/Transitioner.tsx +98 -49
  131. package/Components/Transitioner/__tests__/transitioner.test.js +372 -3
  132. package/Components/VideoLive/LiveImageManager.ts +9 -3
  133. package/Components/VideoLive/__tests__/LiveImageManager.test.ts +59 -0
  134. package/Components/VideoModal/utils.ts +6 -1
  135. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +12 -5
  136. package/Components/ZappFrameworkComponents/BarView/__tests__/BarView.test.tsx +2 -2
  137. package/Contexts/CachedDimensionsContext/__tests__/index.test.ts +154 -0
  138. package/Contexts/CachedDimensionsContext/index.ts +17 -2
  139. package/Contexts/ModalNavigationContext/__tests__/index.test.tsx +15 -0
  140. package/Contexts/ModalNavigationContext/index.tsx +2 -2
  141. package/Helpers/ComponentCellSelectionHelper/index.js +0 -6
  142. package/Helpers/index.js +0 -39
  143. package/Hooks/useEntryActionsExpander.ts +63 -0
  144. package/assets/empty-Info.png +0 -0
  145. package/package.json +6 -5
  146. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +0 -112
  147. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +0 -107
  148. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +0 -153
  149. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -66
  150. package/Components/OfflineHandler/NotificationView/utils.ts +0 -34
  151. package/Components/Screen/utils.ts +0 -16
  152. package/Helpers/Analytics/index.js +0 -95
  153. /package/Components/BackgroundImage/{BackgroundImage.tv.android.tsx → BackgroundImage.android.tv.tsx} +0 -0
  154. /package/Components/BackgroundImage/{BackgroundImage.tv.ios.tsx → BackgroundImage.ios.tv.tsx} +0 -0
  155. /package/Components/MasterCell/DefaultComponents/ButtonContainerView/{index.tv.android.tsx → index.android.tv.tsx} +0 -0
  156. /package/Decorators/ZappPipesDataConnector/__tests__/{Hero.js → Hero.tsx} +0 -0
@@ -0,0 +1,523 @@
1
+ import {
2
+ BackgroundConfiguration as ItemBackgroundConfiguration,
3
+ ImageConfiguration as ItemImageConfiguration,
4
+ LabelConfiguration as ItemLabelConfiguration,
5
+ NowPlayingAssetConfiguration as ItemNowPlayingAssetConfiguration,
6
+ CheckboxAssetsConfiguration as ItemCheckboxAssetsConfiguration,
7
+ ActionButtonAssetsConfiguration as ItemActionButtonAssetsConfiguration,
8
+ ItemConfiguration,
9
+ } from "../Components/Item";
10
+ import {
11
+ TitleConfiguration as HeaderTitleConfiguration,
12
+ ActionButtonsStyleConfiguration as HeaderActionButtonsStyleConfiguration,
13
+ HeaderConfiguration,
14
+ } from "../Components/Header";
15
+ import {
16
+ BackgroundConfiguration as ButtonBackgroundConfiguration,
17
+ TitleConfiguration as ButtonTitleConfiguration,
18
+ ButtonConfiguration,
19
+ } from "../Components/Button";
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Item Merging Helpers
23
+ // ---------------------------------------------------------------------------
24
+
25
+ function mergeItemBackground(
26
+ base: ItemBackgroundConfiguration,
27
+ defaultOverride?: Record<string, any>,
28
+ focusedOverride?: Record<string, any>
29
+ ): ItemBackgroundConfiguration {
30
+ if (!defaultOverride && !focusedOverride) return base;
31
+
32
+ // Only take focused color from the focused/pressed bucket (or legacy
33
+ // mis-parsed focus* aliases). Never fall back to default background —
34
+ // that would overwrite base.focusedColor whenever Studio only sets default.
35
+ const focusedColor =
36
+ focusedOverride?.backgroundColor ??
37
+ defaultOverride?.focusColor ??
38
+ defaultOverride?.focusBackgroundColor;
39
+
40
+ return {
41
+ ...base,
42
+ ...(defaultOverride?.backgroundColor
43
+ ? { defaultColor: defaultOverride.backgroundColor }
44
+ : {}),
45
+ ...(focusedColor != null && focusedColor !== "" ? { focusedColor } : {}),
46
+ ...(defaultOverride?.borderRadius !== undefined
47
+ ? { cornerRadius: defaultOverride.borderRadius }
48
+ : {}),
49
+ };
50
+ }
51
+
52
+ function mergeItemImage(
53
+ base: ItemImageConfiguration,
54
+ override?: Record<string, any>
55
+ ): ItemImageConfiguration {
56
+ if (!override) return base;
57
+
58
+ return {
59
+ ...base,
60
+ ...(override.width !== undefined ? { width: override.width } : {}),
61
+ ...(override.height !== undefined ? { height: override.height } : {}),
62
+ ...(override.borderRadius !== undefined
63
+ ? { cornerRadius: override.borderRadius }
64
+ : {}),
65
+ ...(override.borderWidth !== undefined
66
+ ? { borderWidth: override.borderWidth }
67
+ : {}),
68
+ ...(override.borderColor ? { borderColor: override.borderColor } : {}),
69
+ };
70
+ }
71
+
72
+ function mergeItemLabel(
73
+ base: ItemLabelConfiguration,
74
+ override?: Record<string, any>
75
+ ): ItemLabelConfiguration {
76
+ if (!override) return base;
77
+
78
+ return {
79
+ ...base,
80
+ ...(override.fontColor ? { fontColor: override.fontColor } : {}),
81
+ ...(override.fontSize !== undefined ? { fontSize: override.fontSize } : {}),
82
+ ...(override.lineHeight !== undefined
83
+ ? { lineHeight: override.lineHeight }
84
+ : {}),
85
+ ...(typeof override.fontFamily === "string" && override.fontFamily
86
+ ? {
87
+ iosFontFamily: override.fontFamily,
88
+ androidFontFamily: override.fontFamily,
89
+ }
90
+ : {}),
91
+ ...(override.iosFontFamily
92
+ ? { iosFontFamily: override.iosFontFamily }
93
+ : {}),
94
+ ...(override.androidFontFamily
95
+ ? { androidFontFamily: override.androidFontFamily }
96
+ : {}),
97
+ ...(override.letterSpacing !== undefined
98
+ ? {
99
+ iosLetterSpacing: override.letterSpacing,
100
+ androidLetterSpacing: override.letterSpacing,
101
+ }
102
+ : {}),
103
+ ...(override.iosLetterSpacing !== undefined
104
+ ? { iosLetterSpacing: override.iosLetterSpacing }
105
+ : {}),
106
+ ...(override.androidLetterSpacing !== undefined
107
+ ? { androidLetterSpacing: override.androidLetterSpacing }
108
+ : {}),
109
+ ...(override.textTransform
110
+ ? { textTransform: override.textTransform }
111
+ : {}),
112
+ };
113
+ }
114
+
115
+ function mergeItemNowPlayingAsset(
116
+ base: ItemNowPlayingAssetConfiguration,
117
+ override?: Record<string, any>
118
+ ): ItemNowPlayingAssetConfiguration {
119
+ if (!override) return base;
120
+
121
+ return {
122
+ ...base,
123
+ ...(override.asset ? { asset: override.asset } : {}),
124
+ };
125
+ }
126
+
127
+ function mergeItemCheckboxAssets(
128
+ base: ItemCheckboxAssetsConfiguration,
129
+ override?: Record<string, any>
130
+ ): ItemCheckboxAssetsConfiguration {
131
+ if (!override) return base;
132
+
133
+ return {
134
+ ...base,
135
+ ...(override.asset ? { asset: override.asset } : {}),
136
+ ...(override.checkedAsset ? { checkedAsset: override.checkedAsset } : {}),
137
+ };
138
+ }
139
+
140
+ function mergeItemActionButtonAssets(
141
+ base: ItemActionButtonAssetsConfiguration,
142
+ override?: Record<string, any>
143
+ ): ItemActionButtonAssetsConfiguration {
144
+ if (!override) return base;
145
+
146
+ return {
147
+ ...base,
148
+ ...(override.removeAsset ? { removeAsset: override.removeAsset } : {}),
149
+ ...(override.dragAsset ? { dragAsset: override.dragAsset } : {}),
150
+ ...(override.playAsset ? { playAsset: override.playAsset } : {}),
151
+ ...(override.pauseAsset ? { pauseAsset: override.pauseAsset } : {}),
152
+ };
153
+ }
154
+
155
+ export function mergeItemConfiguration(
156
+ base: ItemConfiguration,
157
+ itemBlock?: Record<string, any>
158
+ ): ItemConfiguration {
159
+ if (!itemBlock) return base;
160
+
161
+ const bgDefault = itemBlock.background?.default || itemBlock.background;
162
+
163
+ const bgFocused =
164
+ itemBlock.background?.focused ||
165
+ itemBlock.background?.focus ||
166
+ itemBlock.background?.pressed;
167
+
168
+ const img = itemBlock.image?.default || itemBlock.image;
169
+ const label1 = itemBlock.textLabel1?.default || itemBlock.textLabel1;
170
+ const label2 = itemBlock.textLabel2?.default || itemBlock.textLabel2;
171
+
172
+ const npLabel =
173
+ itemBlock.nowPlayingLabel?.default || itemBlock.nowPlayingLabel;
174
+
175
+ const npAsset =
176
+ itemBlock.nowPlayingAsset?.default || itemBlock.nowPlayingAsset;
177
+
178
+ const checkbox = itemBlock.checkbox?.default || itemBlock.checkbox;
179
+
180
+ const actionButtons =
181
+ itemBlock.actionButtons?.default || itemBlock.actionButtons;
182
+
183
+ return {
184
+ ...base,
185
+ background: mergeItemBackground(base.background, bgDefault, bgFocused),
186
+ image: mergeItemImage(base.image, img),
187
+ textLabel1: mergeItemLabel(base.textLabel1, label1),
188
+ textLabel2: mergeItemLabel(base.textLabel2, label2),
189
+ nowPlayingLabel: mergeItemLabel(base.nowPlayingLabel, npLabel),
190
+ nowPlayingAsset: mergeItemNowPlayingAsset(base.nowPlayingAsset, npAsset),
191
+ checkboxAssets: mergeItemCheckboxAssets(
192
+ base.checkboxAssets || {},
193
+ checkbox
194
+ ),
195
+ actionButtonAssets: mergeItemActionButtonAssets(
196
+ base.actionButtonAssets || {},
197
+ actionButtons
198
+ ),
199
+ };
200
+ }
201
+
202
+ // ---------------------------------------------------------------------------
203
+ // Header Merging Helpers
204
+ // ---------------------------------------------------------------------------
205
+
206
+ function mergeHeaderTitle(
207
+ base: HeaderTitleConfiguration,
208
+ override?: Record<string, any>
209
+ ): HeaderTitleConfiguration {
210
+ if (!override) return base;
211
+
212
+ return {
213
+ ...base,
214
+ ...(override.fontColor ? { fontColor: override.fontColor } : {}),
215
+ ...(override.fontSize !== undefined ? { fontSize: override.fontSize } : {}),
216
+ ...(override.lineHeight !== undefined
217
+ ? { lineHeight: override.lineHeight }
218
+ : {}),
219
+ ...(typeof override.fontFamily === "string"
220
+ ? {
221
+ iosFontFamily: override.fontFamily,
222
+ androidFontFamily: override.fontFamily,
223
+ }
224
+ : {}),
225
+ ...(override.iosFontFamily
226
+ ? { iosFontFamily: override.iosFontFamily }
227
+ : {}),
228
+ ...(override.androidFontFamily
229
+ ? { androidFontFamily: override.androidFontFamily }
230
+ : {}),
231
+ ...(override.letterSpacing !== undefined
232
+ ? {
233
+ iosLetterSpacing: override.letterSpacing,
234
+ androidLetterSpacing: override.letterSpacing,
235
+ }
236
+ : {}),
237
+ ...(override.iosLetterSpacing !== undefined
238
+ ? { iosLetterSpacing: override.iosLetterSpacing }
239
+ : {}),
240
+ ...(override.androidLetterSpacing !== undefined
241
+ ? { androidLetterSpacing: override.androidLetterSpacing }
242
+ : {}),
243
+ ...(override.textTransform
244
+ ? { textTransform: override.textTransform }
245
+ : {}),
246
+ ...(override.alignment ? { alignment: override.alignment } : {}),
247
+ };
248
+ }
249
+
250
+ function mergeHeaderActionButtons(
251
+ base: HeaderActionButtonsStyleConfiguration,
252
+ defaultOverride?: Record<string, any>,
253
+ focusedOverride?: Record<string, any>
254
+ ): HeaderActionButtonsStyleConfiguration {
255
+ if (!defaultOverride && !focusedOverride) return base;
256
+
257
+ const focusedBackgroundColor =
258
+ focusedOverride?.backgroundColor ??
259
+ defaultOverride?.focusBackgroundColor ??
260
+ defaultOverride?.focusedBackgroundColor;
261
+
262
+ const focusedFontColor =
263
+ focusedOverride?.fontColor ??
264
+ defaultOverride?.focusFontColor ??
265
+ defaultOverride?.focusedFontColor;
266
+
267
+ return {
268
+ ...base,
269
+ ...(defaultOverride?.backgroundColor
270
+ ? { defaultBackgroundColor: defaultOverride.backgroundColor }
271
+ : {}),
272
+ ...(focusedBackgroundColor != null && focusedBackgroundColor !== ""
273
+ ? { focusedBackgroundColor }
274
+ : {}),
275
+ ...(defaultOverride?.fontColor
276
+ ? { fontColor: defaultOverride.fontColor }
277
+ : {}),
278
+ ...(focusedFontColor != null && focusedFontColor !== ""
279
+ ? { focusedFontColor }
280
+ : {}),
281
+ ...(defaultOverride?.fontSize !== undefined
282
+ ? { fontSize: defaultOverride.fontSize }
283
+ : {}),
284
+ ...(defaultOverride?.lineHeight !== undefined
285
+ ? { lineHeight: defaultOverride.lineHeight }
286
+ : {}),
287
+ ...(typeof defaultOverride?.fontFamily === "string"
288
+ ? {
289
+ iosFontFamily: defaultOverride.fontFamily,
290
+ androidFontFamily: defaultOverride.fontFamily,
291
+ }
292
+ : {}),
293
+ ...(defaultOverride?.iosFontFamily
294
+ ? { iosFontFamily: defaultOverride.iosFontFamily }
295
+ : {}),
296
+ ...(defaultOverride?.androidFontFamily
297
+ ? { androidFontFamily: defaultOverride.androidFontFamily }
298
+ : {}),
299
+ ...(defaultOverride?.letterSpacing !== undefined
300
+ ? {
301
+ iosLetterSpacing: defaultOverride.letterSpacing,
302
+ androidLetterSpacing: defaultOverride.letterSpacing,
303
+ }
304
+ : {}),
305
+ ...(defaultOverride?.iosLetterSpacing !== undefined
306
+ ? { iosLetterSpacing: defaultOverride.iosLetterSpacing }
307
+ : {}),
308
+ ...(defaultOverride?.androidLetterSpacing !== undefined
309
+ ? { androidLetterSpacing: defaultOverride.androidLetterSpacing }
310
+ : {}),
311
+ ...(defaultOverride?.textTransform
312
+ ? { textTransform: defaultOverride.textTransform }
313
+ : {}),
314
+ ...(defaultOverride?.borderRadius !== undefined
315
+ ? { cornerRadius: defaultOverride.borderRadius }
316
+ : {}),
317
+ ...(defaultOverride?.cornerRadius !== undefined
318
+ ? { cornerRadius: defaultOverride.cornerRadius }
319
+ : {}),
320
+ ...(defaultOverride?.paddingTop !== undefined
321
+ ? { paddingTop: defaultOverride.paddingTop }
322
+ : {}),
323
+ ...(defaultOverride?.paddingRight !== undefined
324
+ ? { paddingRight: defaultOverride.paddingRight }
325
+ : {}),
326
+ ...(defaultOverride?.paddingBottom !== undefined
327
+ ? { paddingBottom: defaultOverride.paddingBottom }
328
+ : {}),
329
+ ...(defaultOverride?.paddingLeft !== undefined
330
+ ? { paddingLeft: defaultOverride.paddingLeft }
331
+ : {}),
332
+ };
333
+ }
334
+
335
+ export function mergeHeaderConfiguration(
336
+ base: HeaderConfiguration,
337
+ headerBlock?: Record<string, any>
338
+ ): HeaderConfiguration & { backgroundColor?: string } {
339
+ if (!headerBlock) return base;
340
+
341
+ const bgOverride = headerBlock.container?.default?.backgroundColor;
342
+
343
+ const actionButtonsDefault =
344
+ headerBlock.actionButtons?.default || headerBlock.actionButtons;
345
+
346
+ const actionButtonsFocused =
347
+ headerBlock.actionButtons?.focused || headerBlock.actionButtons?.focus;
348
+
349
+ // Parser shape is title.default.*; hydrate() returns a flat title object.
350
+ const titleDefault = headerBlock.title?.default;
351
+
352
+ const titleOverride =
353
+ titleDefault &&
354
+ (titleDefault.fontColor !== undefined ||
355
+ titleDefault.fontSize !== undefined ||
356
+ titleDefault.lineHeight !== undefined ||
357
+ titleDefault.fontFamily ||
358
+ titleDefault.iosFontFamily ||
359
+ titleDefault.androidFontFamily ||
360
+ titleDefault.letterSpacing !== undefined ||
361
+ titleDefault.iosLetterSpacing !== undefined ||
362
+ titleDefault.androidLetterSpacing !== undefined ||
363
+ titleDefault.textTransform ||
364
+ titleDefault.alignment)
365
+ ? titleDefault
366
+ : headerBlock.title;
367
+
368
+ return {
369
+ ...base,
370
+ title: mergeHeaderTitle(base.title, titleOverride),
371
+ actionButtons: mergeHeaderActionButtons(
372
+ base.actionButtons,
373
+ actionButtonsDefault,
374
+ actionButtonsFocused
375
+ ),
376
+ ...(bgOverride ? { backgroundColor: bgOverride } : {}),
377
+ };
378
+ }
379
+
380
+ // ---------------------------------------------------------------------------
381
+ // Button Merging Helpers
382
+ // ---------------------------------------------------------------------------
383
+
384
+ function mergeButtonBackground(
385
+ base: ButtonBackgroundConfiguration,
386
+ defaultOverride?: Record<string, any>,
387
+ focusedOverride?: Record<string, any>
388
+ ): ButtonBackgroundConfiguration {
389
+ if (!defaultOverride && !focusedOverride) return base;
390
+
391
+ // Same as mergeItemBackground: do not use default background as focusedColor.
392
+ const focusedColor =
393
+ focusedOverride?.backgroundColor ??
394
+ defaultOverride?.focusColor ??
395
+ defaultOverride?.focusBackgroundColor;
396
+
397
+ return {
398
+ ...base,
399
+ ...(defaultOverride?.backgroundColor
400
+ ? { defaultColor: defaultOverride.backgroundColor }
401
+ : {}),
402
+ ...(focusedColor != null && focusedColor !== "" ? { focusedColor } : {}),
403
+ ...(defaultOverride?.borderRadius !== undefined
404
+ ? { cornerRadius: defaultOverride.borderRadius }
405
+ : {}),
406
+ ...(defaultOverride?.paddingTop !== undefined
407
+ ? { paddingTop: defaultOverride.paddingTop }
408
+ : {}),
409
+ ...(defaultOverride?.paddingRight !== undefined
410
+ ? { paddingRight: defaultOverride.paddingRight }
411
+ : {}),
412
+ ...(defaultOverride?.paddingBottom !== undefined
413
+ ? { paddingBottom: defaultOverride.paddingBottom }
414
+ : {}),
415
+ ...(defaultOverride?.paddingLeft !== undefined
416
+ ? { paddingLeft: defaultOverride.paddingLeft }
417
+ : {}),
418
+ };
419
+ }
420
+
421
+ function mergeButtonTitle(
422
+ base: ButtonTitleConfiguration,
423
+ override?: Record<string, any>
424
+ ): ButtonTitleConfiguration {
425
+ if (!override) return base;
426
+
427
+ return {
428
+ ...base,
429
+ ...(override.fontColor ? { fontColor: override.fontColor } : {}),
430
+ ...(override.fontSize !== undefined ? { fontSize: override.fontSize } : {}),
431
+ ...(override.lineHeight !== undefined
432
+ ? { lineHeight: override.lineHeight }
433
+ : {}),
434
+ ...(override.fontFamily
435
+ ? {
436
+ iosFontFamily: override.fontFamily,
437
+ androidFontFamily: override.fontFamily,
438
+ }
439
+ : {}),
440
+ ...(override.iosFontFamily
441
+ ? { iosFontFamily: override.iosFontFamily }
442
+ : {}),
443
+ ...(override.androidFontFamily
444
+ ? { androidFontFamily: override.androidFontFamily }
445
+ : {}),
446
+ ...(override.letterSpacing !== undefined
447
+ ? {
448
+ iosLetterSpacing: override.letterSpacing,
449
+ androidLetterSpacing: override.letterSpacing,
450
+ }
451
+ : {}),
452
+ ...(override.iosLetterSpacing !== undefined
453
+ ? { iosLetterSpacing: override.iosLetterSpacing }
454
+ : {}),
455
+ ...(override.androidLetterSpacing !== undefined
456
+ ? { androidLetterSpacing: override.androidLetterSpacing }
457
+ : {}),
458
+ ...(override.textTransform
459
+ ? { textTransform: override.textTransform }
460
+ : {}),
461
+ };
462
+ }
463
+
464
+ function mergeButtonIcons(
465
+ base: ButtonConfiguration["icons"],
466
+ iconsOverride?: Record<string, any>,
467
+ leadingOverride?: Record<string, any>
468
+ ): ButtonConfiguration["icons"] {
469
+ if (!iconsOverride && !leadingOverride) return base;
470
+
471
+ const iconsDefault = iconsOverride?.default || iconsOverride;
472
+ const leadingDefault = leadingOverride?.default || leadingOverride;
473
+
474
+ return {
475
+ ...base,
476
+ ...(iconsDefault?.width !== undefined ? { width: iconsDefault.width } : {}),
477
+ ...(iconsDefault?.height !== undefined
478
+ ? { height: iconsDefault.height }
479
+ : {}),
480
+ leadingIcon: {
481
+ ...base.leadingIcon,
482
+ ...(leadingDefault?.enabled !== undefined
483
+ ? { enabled: leadingDefault.enabled }
484
+ : {}),
485
+ ...(leadingDefault?.actionType
486
+ ? { actionType: leadingDefault.actionType }
487
+ : {}),
488
+ ...(leadingDefault?.asset ? { asset: leadingDefault.asset } : {}),
489
+ },
490
+ };
491
+ }
492
+
493
+ export function mergeButtonConfiguration(
494
+ base: ButtonConfiguration,
495
+ buttonBlock?: Record<string, any>,
496
+ actionBlock?: Record<string, any>
497
+ ): ButtonConfiguration {
498
+ if (!buttonBlock && !actionBlock) return base;
499
+
500
+ const bgDefault =
501
+ buttonBlock?.background?.default || actionBlock?.background?.default;
502
+
503
+ const bgFocused =
504
+ buttonBlock?.background?.focused ||
505
+ buttonBlock?.background?.focus ||
506
+ actionBlock?.background?.focused ||
507
+ actionBlock?.background?.focus ||
508
+ buttonBlock?.background?.pressed ||
509
+ actionBlock?.background?.pressed;
510
+
511
+ const titleOverride =
512
+ buttonBlock?.title?.default || actionBlock?.title?.default;
513
+
514
+ const iconsOverride = buttonBlock?.icons || actionBlock?.icons;
515
+ const leadingOverride = buttonBlock?.leadingIcon || actionBlock?.leadingIcon;
516
+
517
+ return {
518
+ ...base,
519
+ background: mergeButtonBackground(base.background, bgDefault, bgFocused),
520
+ title: mergeButtonTitle(base.title, titleOverride),
521
+ icons: mergeButtonIcons(base.icons, iconsOverride, leadingOverride),
522
+ };
523
+ }
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import { PanGestureHandler } from "react-native-gesture-handler";
3
+ import { View } from "react-native";
4
+ import { useBottomSheet } from "@applicaster/zapp-react-native-utils/bottomSheet";
5
+
6
+ /**
7
+ * Turns its children into a drag zone for the enclosing DraggableBottomSheet:
8
+ * dragging here moves/dismisses the sheet (used for the modal header bar).
9
+ * Outside a sheet (no context) it renders children unchanged.
10
+ */
11
+ export const BottomSheetDragArea = ({
12
+ children,
13
+ }: {
14
+ children: React.ReactElement;
15
+ }) => {
16
+ const sheet = useBottomSheet();
17
+
18
+ // Outside a sheet (no context) render children unchanged.
19
+ if (!sheet) return children;
20
+
21
+ return (
22
+ <PanGestureHandler
23
+ simultaneousHandlers={[sheet.masterDrawerRef]}
24
+ shouldCancelWhenOutside={false}
25
+ onGestureEvent={sheet.onDragGestureEvent}
26
+ onHandlerStateChange={sheet.onDragStateChange}
27
+ >
28
+ {/* Old-API PanGestureHandler needs a host-component child; children may
29
+ be a function component (e.g. ModalHeader), so wrap in a View. */}
30
+ <View>{children}</View>
31
+ </PanGestureHandler>
32
+ );
33
+ };