@applicaster/zapp-react-native-ui-components 16.0.0-alpha.1535029240 → 16.0.0-alpha.1701179921

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 (92) 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/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +15 -0
  7. package/Components/GeneralContentScreen/hookAdapter/__tests__/skipExpression.test.ts +294 -0
  8. package/Components/GeneralContentScreen/hookAdapter/__tests__/validationHelper.test.ts +64 -0
  9. package/Components/GeneralContentScreen/hookAdapter/skipExpression.ts +252 -0
  10. package/Components/GeneralContentScreen/hookAdapter/validationHelper.ts +18 -0
  11. package/Components/LinkHandler/LinkHandler.tsx +2 -7
  12. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +5 -1
  13. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/ActionButtonController.tsx +19 -4
  14. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +43 -1
  15. package/Components/MasterCell/DefaultComponents/Button.tsx +1 -0
  16. package/Components/MasterCell/DefaultComponents/Image/hoc/utils/__tests__/withDimensions.test.ts +420 -125
  17. package/Components/MasterCell/DefaultComponents/Image/hoc/utils/index.ts +114 -19
  18. package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +19 -8
  19. package/Components/MasterCell/DefaultComponents/LiveImage/executePreloadHooks.ts +2 -4
  20. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +2 -3
  21. package/Components/MasterCell/DefaultComponents/Toggle.tsx +36 -14
  22. package/Components/MasterCell/DefaultComponents/__tests__/Toggle.test.tsx +167 -0
  23. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/factory.test.ts +32 -0
  24. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -2
  25. package/Components/ModalComponent/ActionsBottomSheet/ActionButton.tsx +56 -0
  26. package/Components/ModalComponent/ActionsBottomSheet/__tests__/openActionsBottomSheet.test.ts +38 -0
  27. package/Components/ModalComponent/ActionsBottomSheet/boundActionButton.tsx +24 -0
  28. package/Components/ModalComponent/ActionsBottomSheet/index.ts +9 -0
  29. package/Components/ModalComponent/ActionsBottomSheet/openActionsBottomSheet.ts +61 -0
  30. package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +87 -97
  31. package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +87 -126
  32. package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +140 -83
  33. package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +252 -123
  34. package/Components/ModalComponent/AudioPlayer/Components/NowPlayingHeaderSection.tsx +205 -0
  35. package/Components/ModalComponent/AudioPlayer/Components/__tests__/Item.test.tsx +113 -0
  36. package/Components/ModalComponent/AudioPlayer/Components/__tests__/NowPlayingHeaderSection.test.tsx +36 -0
  37. package/Components/ModalComponent/AudioPlayer/Components/index.ts +3 -3
  38. package/Components/ModalComponent/AudioPlayer/utils/__tests__/mergeStyles.test.ts +356 -0
  39. package/Components/ModalComponent/AudioPlayer/utils/mergeStyles.ts +521 -0
  40. package/Components/ModalComponent/BottomSheetDragArea.tsx +33 -0
  41. package/Components/ModalComponent/BottomSheetModalContent.tsx +505 -66
  42. package/Components/ModalComponent/Button/index.tsx +5 -3
  43. package/Components/ModalComponent/Header/CloseButton.tsx +12 -0
  44. package/Components/ModalComponent/Header/__tests__/CloseButton.test.tsx +72 -0
  45. package/Components/ModalComponent/Header/index.tsx +20 -7
  46. package/Components/ModalComponent/Header/utils.ts +1 -1
  47. package/Components/ModalComponent/ModalBlocksStyleContext.tsx +10 -0
  48. package/Components/ModalComponent/SortableList.tsx +156 -0
  49. package/Components/ModalComponent/SortableList.web.tsx +34 -0
  50. package/Components/ModalComponent/TextInputContent.tsx +135 -0
  51. package/Components/ModalComponent/__tests__/BottomSheetDragArea.test.tsx +74 -0
  52. package/Components/ModalComponent/__tests__/BottomSheetModalContent.test.tsx +343 -0
  53. package/Components/ModalComponent/__tests__/SortableList.web.test.tsx +16 -0
  54. package/Components/ModalComponent/__tests__/TextInputContent.test.tsx +169 -0
  55. package/Components/ModalComponent/__tests__/showTextInput.test.ts +95 -0
  56. package/Components/ModalComponent/index.tsx +18 -9
  57. package/Components/ModalComponent/presets/__tests__/getCell.test.ts +90 -0
  58. package/Components/ModalComponent/presets/dynamicCollectionCell.tsx +78 -0
  59. package/Components/ModalComponent/presets/index.ts +27 -0
  60. package/Components/ModalComponent/presets/selectableCell.tsx +28 -0
  61. package/Components/ModalComponent/presets/standardCell.tsx +41 -0
  62. package/Components/ModalComponent/presets/types.ts +35 -0
  63. package/Components/ModalComponent/showTextInput.ts +52 -0
  64. package/Components/ModalComponent/utils.ts +82 -21
  65. package/Components/OfflineHandler/hooks.ts +0 -12
  66. package/Components/PlayerContainer/PlayerContainer.tsx +19 -8
  67. package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -4
  68. package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +66 -13
  69. package/Components/River/ComponentsMap/ComponentsMap.tsx +85 -59
  70. package/Components/River/River.tsx +4 -0
  71. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +138 -75
  72. package/Components/River/__tests__/componentsMap.test.js +8 -3
  73. package/Components/River/__tests__/resultCallback.test.tsx +47 -0
  74. package/Components/Screen/__tests__/Screen.test.tsx +24 -0
  75. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -0
  76. package/Components/Screen/index.tsx +5 -0
  77. package/Components/Screen/navigationHandler.ts +8 -8
  78. package/Components/ScreenRevealManager/ScreenRevealManager.ts +18 -2
  79. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +36 -0
  80. package/Components/ScreenRevealManager/__tests__/withScreenRevealManager.test.tsx +56 -0
  81. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +21 -4
  82. package/Components/Transitioner/Transitioner.tsx +2 -3
  83. package/Components/Transitioner/__tests__/transitioner.test.js +83 -2
  84. package/Components/VideoLive/LiveImageManager.ts +9 -3
  85. package/Components/VideoLive/__tests__/LiveImageManager.test.ts +59 -0
  86. package/Contexts/ModalNavigationContext/__tests__/index.test.tsx +15 -0
  87. package/Contexts/ModalNavigationContext/index.tsx +2 -2
  88. package/Hooks/useEntryActionsExpander.ts +63 -0
  89. package/assets/empty-Info.png +0 -0
  90. package/package.json +6 -5
  91. package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +0 -332
  92. /package/Decorators/ZappPipesDataConnector/__tests__/{Hero.js → Hero.tsx} +0 -0
@@ -12,14 +12,14 @@
12
12
  */
13
13
 
14
14
  import React from "react";
15
+ import { QBImage as Image } from "@applicaster/zapp-react-native-ui-components/Components/Image";
16
+ import { Platform, Pressable, StyleSheet, Text, View } from "react-native";
15
17
  import {
16
- Image,
17
- Platform,
18
- Pressable,
19
- StyleSheet,
20
- Text,
21
- View,
22
- } from "react-native";
18
+ MenuItem,
19
+ SelectionBehavior,
20
+ } from "@applicaster/zapp-react-native-utils/modalState/types";
21
+ import { useModalBlocksStyle } from "../../ModalBlocksStyleContext";
22
+ import { mergeItemConfiguration } from "../utils/mergeStyles";
23
23
 
24
24
  const styles = StyleSheet.create({
25
25
  row: {
@@ -34,25 +34,6 @@ const styles = StyleSheet.create({
34
34
  flexDirection: "row",
35
35
  alignItems: "center",
36
36
  },
37
- demoScreen: {
38
- flex: 1,
39
- backgroundColor: "#1C1C1E",
40
- paddingTop: 64,
41
- paddingHorizontal: 0,
42
- gap: 16,
43
- },
44
- demoHeading: {
45
- color: "#FFFFFF",
46
- fontSize: 20,
47
- fontWeight: "600",
48
- marginBottom: 8,
49
- paddingHorizontal: 16,
50
- },
51
- demoLabel: {
52
- color: "#999999",
53
- fontSize: 13,
54
- paddingHorizontal: 16,
55
- },
56
37
  });
57
38
 
58
39
  // ---------------------------------------------------------------------------
@@ -69,6 +50,12 @@ export type BackgroundConfiguration = {
69
50
  defaultColor: string;
70
51
  focusedColor: string;
71
52
  cornerRadius: number;
53
+ paddingTop?: number;
54
+ paddingRight?: number;
55
+ paddingBottom?: number;
56
+ paddingLeft?: number;
57
+ highlightInsetLeft?: number;
58
+ highlightInsetRight?: number;
72
59
  };
73
60
 
74
61
  export type ImageConfiguration = {
@@ -95,6 +82,20 @@ export type NowPlayingAssetConfiguration = {
95
82
  asset?: string;
96
83
  };
97
84
 
85
+ export type CheckboxAssetsConfiguration = {
86
+ /** Unchecked multiSelect control (item.checkbox_asset). */
87
+ asset?: string;
88
+ /** Checked multiSelect control (item.checked_checkbox_asset). */
89
+ checkedAsset?: string;
90
+ };
91
+
92
+ export type ActionButtonAssetsConfiguration = {
93
+ /** Leading remove control on Edit Order rows. */
94
+ removeAsset?: string;
95
+ /** Trailing drag handle on Edit Order / queue rows. */
96
+ dragAsset?: string;
97
+ };
98
+
98
99
  export type ItemConfiguration = {
99
100
  background: BackgroundConfiguration;
100
101
  image: ImageConfiguration;
@@ -102,53 +103,10 @@ export type ItemConfiguration = {
102
103
  nowPlayingLabel: LabelConfiguration;
103
104
  textLabel1: LabelConfiguration;
104
105
  textLabel2: LabelConfiguration;
106
+ checkboxAssets?: CheckboxAssetsConfiguration;
107
+ actionButtonAssets?: ActionButtonAssetsConfiguration;
105
108
  };
106
109
 
107
- export interface Action {
108
- type: string;
109
- payload?: any;
110
- options?: any;
111
- }
112
-
113
- export interface Header {
114
- title: string;
115
- subtitle?: string;
116
- icon?: string;
117
- }
118
-
119
- export interface Content {
120
- title: string;
121
- stickyTitle?: boolean;
122
- items: MenuItem[];
123
- itemsUrl?: string;
124
- action?: Action;
125
- }
126
-
127
- export interface Menu {
128
- header?: Header;
129
- content: Content;
130
- closeButton?: boolean;
131
- }
132
-
133
- export interface PresentSubMenuAction extends Action {
134
- menu: Menu;
135
- }
136
-
137
- export interface SecondaryAction {
138
- action: Action | PresentSubMenuAction;
139
- icon?: string;
140
- }
141
-
142
- export interface MenuItem {
143
- trailingButton?: ItemButtonAction;
144
- title: string;
145
- summary?: string;
146
- icon?: string;
147
- isSelected?: boolean;
148
- action?: Action | PresentSubMenuAction;
149
- secondaryAction?: SecondaryAction;
150
- }
151
-
152
110
  export const DEFAULT_TEXT_LABEL_1_CONFIGURATION: LabelConfiguration = {
153
111
  fontColor: "#FFFFFF",
154
112
  focusedFontColor: "#FFFFFF",
@@ -211,6 +169,7 @@ export type AudioPlayerTrackItemProps = {
211
169
  onPress?: () => void;
212
170
  onLeadingButtonPress?: () => void;
213
171
  onTrailingButtonPress?: () => void;
172
+ renderHandle?: (element: React.ReactElement) => React.ReactElement;
214
173
  };
215
174
 
216
175
  // ---------------------------------------------------------------------------
@@ -246,9 +205,9 @@ const CONTAINER_SPEC_LARGE_IMAGE: ContainerSpec = {
246
205
 
247
206
  const CONTAINER_SPEC_DEFAULT: ContainerSpec = {
248
207
  paddingTop: 8,
249
- paddingRight: 20,
208
+ paddingRight: 10,
250
209
  paddingBottom: 8,
251
- paddingLeft: 20,
210
+ paddingLeft: 10,
252
211
  horizontalGutter: 12,
253
212
  verticalGutter: 2,
254
213
  };
@@ -326,14 +285,18 @@ function resolveContainerSpec(image: ImageConfiguration): ContainerSpec {
326
285
  : CONTAINER_SPEC_DEFAULT;
327
286
  }
328
287
 
329
- export function mapMenuItemToNowPlayingData(item: MenuItem): ItemData {
288
+ export function mapMenuItemToNowPlayingData(
289
+ item: MenuItem,
290
+ isPaused?: boolean,
291
+ nowPlayingLabel = "Now Playing"
292
+ ): ItemData {
330
293
  return {
331
294
  imageUri: item.icon,
332
295
  textLabel1: item.title,
333
296
  textLabel2: item.summary ?? "",
334
- nowPlayingLabel: "Now Playing",
297
+ nowPlayingLabel,
335
298
  trailingButton: "playPause",
336
- isSelected: item.isSelected,
299
+ isSelected: isPaused !== undefined ? !isPaused : item.isSelected,
337
300
  };
338
301
  }
339
302
 
@@ -348,12 +311,23 @@ export function mapMenuItemToQueuedData(item: MenuItem): ItemData {
348
311
  };
349
312
  }
350
313
 
351
- export function mapMenuItemToPlaylistData(item: MenuItem): ItemData {
314
+ export function mapMenuItemToPlaylistData(
315
+ item: MenuItem,
316
+ behavior?: SelectionBehavior
317
+ ): ItemData {
318
+ const showSelectionWidget =
319
+ behavior?.selectMode !== "none" && item.trailingButton !== "none";
320
+
321
+ const summary =
322
+ typeof item.summary === "string" ? item.summary.trim() : item.summary;
323
+
352
324
  return {
353
325
  imageUri: item.icon,
354
326
  textLabel1: item.title,
355
- textLabel2: item.summary ?? "",
356
- trailingButton: item.trailingButton || ("multiSelect" as ItemButtonAction),
327
+ textLabel2: summary || "",
328
+ trailingButton: showSelectionWidget
329
+ ? item.trailingButton || ("multiSelect" as ItemButtonAction)
330
+ : undefined,
357
331
  isSelected: item.isSelected,
358
332
  };
359
333
  }
@@ -378,21 +352,30 @@ function ItemContainer({
378
352
  onPress,
379
353
  }: ItemContainerProps) {
380
354
  const container = resolveContainerSpec(image);
381
- const bg = focused ? background.focusedColor : background.defaultColor;
355
+ const insetLeft = background.highlightInsetLeft ?? 0;
356
+ const insetRight = background.highlightInsetRight ?? 0;
382
357
 
383
358
  return (
384
- <Pressable
385
- onPress={onPress}
386
- style={({ pressed }) => ({
387
- backgroundColor: pressed ? background.focusedColor : bg,
388
- borderRadius: background.cornerRadius,
389
- paddingTop: container.paddingTop,
390
- paddingRight: container.paddingRight,
391
- paddingBottom: container.paddingBottom,
392
- paddingLeft: container.paddingLeft,
393
- })}
394
- >
395
- {children}
359
+ <Pressable onPress={onPress}>
360
+ {({ pressed }) => (
361
+ <View
362
+ style={{
363
+ marginLeft: insetLeft,
364
+ marginRight: insetRight,
365
+ backgroundColor:
366
+ pressed || focused
367
+ ? background.focusedColor
368
+ : background.defaultColor,
369
+ borderRadius: background.cornerRadius,
370
+ paddingTop: background.paddingTop ?? container.paddingTop,
371
+ paddingRight: background.paddingRight ?? container.paddingRight,
372
+ paddingBottom: background.paddingBottom ?? container.paddingBottom,
373
+ paddingLeft: background.paddingLeft ?? container.paddingLeft,
374
+ }}
375
+ >
376
+ {children}
377
+ </View>
378
+ )}
396
379
  </Pressable>
397
380
  );
398
381
  }
@@ -425,6 +408,10 @@ type ItemLabelProps = {
425
408
  };
426
409
 
427
410
  function ItemLabel({ text, configuration, focused = false }: ItemLabelProps) {
411
+ if (!text) {
412
+ return null;
413
+ }
414
+
428
415
  const color =
429
416
  focused && configuration.focusedFontColor
430
417
  ? configuration.focusedFontColor
@@ -496,6 +483,8 @@ type ItemButtonProps = {
496
483
  focused?: boolean;
497
484
  onPress?: () => void;
498
485
  isSelected?: boolean;
486
+ checkboxAssets?: CheckboxAssetsConfiguration;
487
+ actionButtonAssets?: ActionButtonAssetsConfiguration;
499
488
  };
500
489
 
501
490
  function ItemButton({
@@ -503,9 +492,15 @@ function ItemButton({
503
492
  focused = false,
504
493
  onPress,
505
494
  isSelected = false,
495
+ checkboxAssets,
496
+ actionButtonAssets,
506
497
  }: ItemButtonProps) {
507
498
  const layout = BUTTON_LAYOUT_SPEC[action];
508
499
 
500
+ if (!layout) {
501
+ return null;
502
+ }
503
+
509
504
  const renderIcon = () => {
510
505
  switch (action) {
511
506
  case "playPause": {
@@ -573,6 +568,19 @@ function ItemButton({
573
568
  }
574
569
 
575
570
  case "drag": {
571
+ if (actionButtonAssets?.dragAsset) {
572
+ return (
573
+ <Image
574
+ source={{ uri: actionButtonAssets.dragAsset }}
575
+ style={{
576
+ width: layout.assetWidth,
577
+ height: layout.assetHeight,
578
+ }}
579
+ resizeMode="contain"
580
+ />
581
+ );
582
+ }
583
+
576
584
  return (
577
585
  <View
578
586
  style={{
@@ -607,6 +615,19 @@ function ItemButton({
607
615
  }
608
616
 
609
617
  case "remove": {
618
+ if (actionButtonAssets?.removeAsset) {
619
+ return (
620
+ <Image
621
+ source={{ uri: actionButtonAssets.removeAsset }}
622
+ style={{
623
+ width: layout.assetWidth,
624
+ height: layout.assetHeight,
625
+ }}
626
+ resizeMode="contain"
627
+ />
628
+ );
629
+ }
630
+
610
631
  return (
611
632
  <View
612
633
  style={{
@@ -632,6 +653,23 @@ function ItemButton({
632
653
  }
633
654
 
634
655
  case "multiSelect": {
656
+ const studioAsset = isSelected
657
+ ? checkboxAssets?.checkedAsset
658
+ : checkboxAssets?.asset;
659
+
660
+ if (studioAsset) {
661
+ return (
662
+ <Image
663
+ source={{ uri: studioAsset }}
664
+ style={{
665
+ width: layout.assetWidth,
666
+ height: layout.assetHeight,
667
+ }}
668
+ resizeMode="contain"
669
+ />
670
+ );
671
+ }
672
+
635
673
  if (!isSelected) {
636
674
  return (
637
675
  <View
@@ -678,15 +716,31 @@ function ItemButton({
678
716
  }
679
717
  };
680
718
 
719
+ const buttonPadding = {
720
+ paddingTop: layout.paddingTop,
721
+ paddingRight: layout.paddingRight,
722
+ paddingBottom: layout.paddingBottom,
723
+ paddingLeft: layout.paddingLeft,
724
+ };
725
+
726
+ // A nested Pressable with no handler swallows the parent row press.
727
+ if (!onPress) {
728
+ return (
729
+ <View pointerEvents="none" style={buttonPadding}>
730
+ {renderIcon()}
731
+ </View>
732
+ );
733
+ }
734
+
681
735
  return (
682
736
  <Pressable
683
- onPress={onPress}
737
+ onPress={(e: any) => {
738
+ e?.stopPropagation?.();
739
+ onPress();
740
+ }}
684
741
  style={({ pressed }) => [
742
+ buttonPadding,
685
743
  {
686
- paddingTop: layout.paddingTop,
687
- paddingRight: layout.paddingRight,
688
- paddingBottom: layout.paddingBottom,
689
- paddingLeft: layout.paddingLeft,
690
744
  opacity: pressed || focused ? 0.7 : 1,
691
745
  },
692
746
  ]}
@@ -704,6 +758,9 @@ type ItemButtonsProps = {
704
758
  onLeadingButtonPress?: () => void;
705
759
  onTrailingButtonPress?: () => void;
706
760
  isSelected?: boolean;
761
+ renderHandle?: (element: React.ReactElement) => React.ReactElement;
762
+ checkboxAssets?: CheckboxAssetsConfiguration;
763
+ actionButtonAssets?: ActionButtonAssetsConfiguration;
707
764
  };
708
765
 
709
766
  function ItemButtons({
@@ -714,6 +771,9 @@ function ItemButtons({
714
771
  onLeadingButtonPress,
715
772
  onTrailingButtonPress,
716
773
  isSelected = false,
774
+ renderHandle,
775
+ checkboxAssets,
776
+ actionButtonAssets,
717
777
  }: ItemButtonsProps) {
718
778
  if (!leadingButton && !trailingButton) {
719
779
  return null;
@@ -728,17 +788,45 @@ function ItemButtons({
728
788
  focused={focusedLeadingButton}
729
789
  onPress={onLeadingButtonPress}
730
790
  isSelected={isSelected}
791
+ checkboxAssets={checkboxAssets}
792
+ actionButtonAssets={actionButtonAssets}
731
793
  />
732
794
  <View style={{ width: BUTTONS_CONTAINER_HORIZONTAL_GUTTER }} />
733
795
  </>
734
796
  ) : null}
735
797
  {trailingButton ? (
736
- <ItemButton
737
- action={trailingButton}
738
- focused={focusedTrailingButton}
739
- onPress={onTrailingButtonPress}
740
- isSelected={isSelected}
741
- />
798
+ trailingButton === "drag" ? (
799
+ renderHandle ? (
800
+ renderHandle(
801
+ <ItemButton
802
+ action={trailingButton}
803
+ focused={focusedTrailingButton}
804
+ onPress={onTrailingButtonPress}
805
+ isSelected={isSelected}
806
+ checkboxAssets={checkboxAssets}
807
+ actionButtonAssets={actionButtonAssets}
808
+ />
809
+ )
810
+ ) : (
811
+ <ItemButton
812
+ action={trailingButton}
813
+ focused={focusedTrailingButton}
814
+ onPress={onTrailingButtonPress}
815
+ isSelected={isSelected}
816
+ checkboxAssets={checkboxAssets}
817
+ actionButtonAssets={actionButtonAssets}
818
+ />
819
+ )
820
+ ) : (
821
+ <ItemButton
822
+ action={trailingButton}
823
+ focused={focusedTrailingButton}
824
+ onPress={onTrailingButtonPress}
825
+ isSelected={isSelected}
826
+ checkboxAssets={checkboxAssets}
827
+ actionButtonAssets={actionButtonAssets}
828
+ />
829
+ )
742
830
  ) : null}
743
831
  </View>
744
832
  );
@@ -757,18 +845,36 @@ export function AudioPlayerTrackItem({
757
845
  onPress,
758
846
  onLeadingButtonPress,
759
847
  onTrailingButtonPress,
848
+ renderHandle,
760
849
  }: AudioPlayerTrackItemProps) {
850
+ const modalBlocksStyle = useModalBlocksStyle();
851
+ const showNowPlaying = !!data.nowPlayingLabel;
852
+
853
+ const itemBlock =
854
+ showNowPlaying && modalBlocksStyle?.nowPlayingItem
855
+ ? modalBlocksStyle.nowPlayingItem
856
+ : modalBlocksStyle?.item;
857
+
858
+ const effectiveConfig = React.useMemo(() => {
859
+ return mergeItemConfiguration(configuration, itemBlock);
860
+ }, [configuration, itemBlock]);
861
+
761
862
  const {
762
863
  background,
763
864
  image,
764
- nowPlayingAsset,
765
- nowPlayingLabel,
766
865
  textLabel1,
767
866
  textLabel2,
768
- } = configuration;
867
+ nowPlayingLabel,
868
+ nowPlayingAsset,
869
+ checkboxAssets,
870
+ actionButtonAssets,
871
+ } = effectiveConfig;
769
872
 
770
873
  const container = resolveContainerSpec(image);
771
- const showNowPlaying = !!data.nowPlayingLabel;
874
+
875
+ const handleTrailingButtonPress =
876
+ onTrailingButtonPress ??
877
+ (data.trailingButton === "multiSelect" ? onPress : undefined);
772
878
 
773
879
  return (
774
880
  <ItemContainer
@@ -782,22 +888,28 @@ export function AudioPlayerTrackItem({
782
888
  <View style={{ width: container.horizontalGutter }} />
783
889
  <View style={styles.contentColumn}>
784
890
  {showNowPlaying ? (
785
- <>
786
- <NowPlayingRow
787
- assetConfiguration={nowPlayingAsset}
788
- labelConfiguration={nowPlayingLabel}
789
- label={data.nowPlayingLabel}
790
- />
791
- <View style={{ height: container.verticalGutter }} />
792
- </>
891
+ <NowPlayingRow
892
+ assetConfiguration={nowPlayingAsset}
893
+ labelConfiguration={nowPlayingLabel}
894
+ label={data.nowPlayingLabel}
895
+ />
896
+ ) : null}
897
+ {showNowPlaying && (data.textLabel1 || data.textLabel2) ? (
898
+ <View style={{ height: container.verticalGutter }} />
899
+ ) : null}
900
+ {data.textLabel1 ? (
901
+ <ItemLabel
902
+ text={data.textLabel1}
903
+ configuration={textLabel1}
904
+ focused={focused}
905
+ />
906
+ ) : null}
907
+ {data.textLabel1 && data.textLabel2 ? (
908
+ <View style={{ height: container.verticalGutter }} />
909
+ ) : null}
910
+ {data.textLabel2 ? (
911
+ <ItemLabel text={data.textLabel2} configuration={textLabel2} />
793
912
  ) : null}
794
- <ItemLabel
795
- text={data.textLabel1}
796
- configuration={textLabel1}
797
- focused={focused}
798
- />
799
- <View style={{ height: container.verticalGutter }} />
800
- <ItemLabel text={data.textLabel2} configuration={textLabel2} />
801
913
  </View>
802
914
  <ItemButtons
803
915
  leadingButton={data.leadingButton}
@@ -805,8 +917,11 @@ export function AudioPlayerTrackItem({
805
917
  focusedLeadingButton={focusedLeadingButton}
806
918
  focusedTrailingButton={focusedTrailingButton}
807
919
  onLeadingButtonPress={onLeadingButtonPress}
808
- onTrailingButtonPress={onTrailingButtonPress}
920
+ onTrailingButtonPress={handleTrailingButtonPress}
809
921
  isSelected={data.isSelected}
922
+ renderHandle={renderHandle}
923
+ checkboxAssets={checkboxAssets}
924
+ actionButtonAssets={actionButtonAssets}
810
925
  />
811
926
  </View>
812
927
  </ItemContainer>
@@ -823,6 +938,10 @@ export const VARIANT_NOW_PLAYING: ItemConfiguration = {
823
938
  defaultColor: "transparent",
824
939
  focusedColor: "transparent",
825
940
  cornerRadius: 0,
941
+ paddingTop: 8,
942
+ paddingRight: 20,
943
+ paddingBottom: 8,
944
+ paddingLeft: 20,
826
945
  },
827
946
  image: {
828
947
  width: 72,
@@ -843,6 +962,12 @@ export const VARIANT_QUEUED_ITEM: ItemConfiguration = {
843
962
  defaultColor: "transparent",
844
963
  focusedColor: "rgba(62, 62, 62, 1)",
845
964
  cornerRadius: 12,
965
+ paddingTop: 8,
966
+ paddingRight: 10,
967
+ paddingBottom: 8,
968
+ paddingLeft: 10,
969
+ highlightInsetLeft: 10,
970
+ highlightInsetRight: 10,
846
971
  },
847
972
  image: {
848
973
  width: 48,
@@ -863,6 +988,10 @@ export const VARIANT_PLAYLIST_ITEM: ItemConfiguration = {
863
988
  defaultColor: "transparent",
864
989
  focusedColor: "rgba(62, 62, 62, 1)",
865
990
  cornerRadius: 12,
991
+ paddingTop: 8,
992
+ paddingRight: 10,
993
+ paddingBottom: 8,
994
+ paddingLeft: 10,
866
995
  },
867
996
  image: {
868
997
  width: 48,