@applicaster/zapp-react-native-ui-components 15.1.13 → 15.1.15-alpha.4236143002
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.
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +4 -1
- package/Components/ModalComponent/ActionsBottomSheet/ActionButton.tsx +56 -0
- package/Components/ModalComponent/ActionsBottomSheet/__tests__/openActionsBottomSheet.test.ts +38 -0
- package/Components/ModalComponent/ActionsBottomSheet/boundActionButton.tsx +24 -0
- package/Components/ModalComponent/ActionsBottomSheet/index.ts +9 -0
- package/Components/ModalComponent/ActionsBottomSheet/openActionsBottomSheet.ts +61 -0
- package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +33 -87
- package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +57 -74
- package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +142 -107
- package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +653 -0
- package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +427 -159
- package/Components/ModalComponent/AudioPlayer/Components/NowPlayingHeaderSection.tsx +89 -0
- package/Components/ModalComponent/AudioPlayer/Components/__tests__/Item.test.tsx +66 -0
- package/Components/ModalComponent/AudioPlayer/Components/index.ts +8 -4
- package/Components/ModalComponent/AudioPlayer/utils/__tests__/mergeStyles.test.ts +230 -0
- package/Components/ModalComponent/AudioPlayer/utils/mergeStyles.ts +332 -0
- package/Components/ModalComponent/BottomSheetModalContent.tsx +379 -61
- package/Components/ModalComponent/Button/index.tsx +5 -3
- package/Components/ModalComponent/Header/index.tsx +20 -7
- package/Components/ModalComponent/Header/utils.ts +1 -1
- package/Components/ModalComponent/ModalBlocksStyleContext.tsx +10 -0
- package/Components/ModalComponent/SortableList.tsx +142 -0
- package/Components/ModalComponent/SortableList.web.tsx +102 -0
- package/Components/ModalComponent/TextInputContent.tsx +112 -0
- package/Components/ModalComponent/__tests__/BottomSheetModalContent.test.tsx +238 -0
- package/Components/ModalComponent/__tests__/TextInputContent.test.tsx +156 -0
- package/Components/ModalComponent/__tests__/showTextInput.test.ts +95 -0
- package/Components/ModalComponent/index.tsx +11 -0
- package/Components/ModalComponent/presets/__tests__/getCell.test.ts +90 -0
- package/Components/ModalComponent/presets/dynamicCollectionCell.tsx +78 -0
- package/Components/ModalComponent/presets/index.ts +27 -0
- package/Components/ModalComponent/presets/selectableCell.tsx +28 -0
- package/Components/ModalComponent/presets/standardCell.tsx +41 -0
- package/Components/ModalComponent/presets/types.ts +35 -0
- package/Components/ModalComponent/showTextInput.ts +43 -0
- package/Components/ModalComponent/utils.ts +82 -21
- package/Components/VideoLive/LiveImageManager.ts +8 -2
- package/Hooks/useEntryActionsExpander.ts +63 -0
- package/package.json +6 -5
- /package/Decorators/ZappPipesDataConnector/__tests__/{Hero.js → Hero.tsx} +0 -0
|
@@ -12,7 +12,20 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import React from "react";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
Image,
|
|
17
|
+
Platform,
|
|
18
|
+
Pressable,
|
|
19
|
+
StyleSheet,
|
|
20
|
+
Text,
|
|
21
|
+
View,
|
|
22
|
+
} from "react-native";
|
|
23
|
+
import {
|
|
24
|
+
MenuItem,
|
|
25
|
+
SelectionBehavior,
|
|
26
|
+
} from "@applicaster/zapp-react-native-utils/modalState/types";
|
|
27
|
+
import { useModalBlocksStyle } from "../../ModalBlocksStyleContext";
|
|
28
|
+
import { mergeItemConfiguration } from "../utils/mergeStyles";
|
|
16
29
|
|
|
17
30
|
const styles = StyleSheet.create({
|
|
18
31
|
row: {
|
|
@@ -27,25 +40,6 @@ const styles = StyleSheet.create({
|
|
|
27
40
|
flexDirection: "row",
|
|
28
41
|
alignItems: "center",
|
|
29
42
|
},
|
|
30
|
-
demoScreen: {
|
|
31
|
-
flex: 1,
|
|
32
|
-
backgroundColor: "#1C1C1E",
|
|
33
|
-
paddingTop: 64,
|
|
34
|
-
paddingHorizontal: 0,
|
|
35
|
-
gap: 16,
|
|
36
|
-
},
|
|
37
|
-
demoHeading: {
|
|
38
|
-
color: "#FFFFFF",
|
|
39
|
-
fontSize: 20,
|
|
40
|
-
fontWeight: "600",
|
|
41
|
-
marginBottom: 8,
|
|
42
|
-
paddingHorizontal: 16,
|
|
43
|
-
},
|
|
44
|
-
demoLabel: {
|
|
45
|
-
color: "#999999",
|
|
46
|
-
fontSize: 13,
|
|
47
|
-
paddingHorizontal: 16,
|
|
48
|
-
},
|
|
49
43
|
});
|
|
50
44
|
|
|
51
45
|
// ---------------------------------------------------------------------------
|
|
@@ -62,6 +56,10 @@ export type BackgroundConfiguration = {
|
|
|
62
56
|
defaultColor: string;
|
|
63
57
|
focusedColor: string;
|
|
64
58
|
cornerRadius: number;
|
|
59
|
+
paddingTop?: number;
|
|
60
|
+
paddingRight?: number;
|
|
61
|
+
paddingBottom?: number;
|
|
62
|
+
paddingLeft?: number;
|
|
65
63
|
};
|
|
66
64
|
|
|
67
65
|
export type ImageConfiguration = {
|
|
@@ -88,6 +86,20 @@ export type NowPlayingAssetConfiguration = {
|
|
|
88
86
|
asset?: string;
|
|
89
87
|
};
|
|
90
88
|
|
|
89
|
+
export type CheckboxAssetsConfiguration = {
|
|
90
|
+
/** Unchecked multiSelect control (item.checkbox_asset). */
|
|
91
|
+
asset?: string;
|
|
92
|
+
/** Checked multiSelect control (item.checked_checkbox_asset). */
|
|
93
|
+
checkedAsset?: string;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type ActionButtonAssetsConfiguration = {
|
|
97
|
+
/** Leading remove control on Edit Order rows. */
|
|
98
|
+
removeAsset?: string;
|
|
99
|
+
/** Trailing drag handle on Edit Order / queue rows. */
|
|
100
|
+
dragAsset?: string;
|
|
101
|
+
};
|
|
102
|
+
|
|
91
103
|
export type ItemConfiguration = {
|
|
92
104
|
background: BackgroundConfiguration;
|
|
93
105
|
image: ImageConfiguration;
|
|
@@ -95,52 +107,10 @@ export type ItemConfiguration = {
|
|
|
95
107
|
nowPlayingLabel: LabelConfiguration;
|
|
96
108
|
textLabel1: LabelConfiguration;
|
|
97
109
|
textLabel2: LabelConfiguration;
|
|
110
|
+
checkboxAssets?: CheckboxAssetsConfiguration;
|
|
111
|
+
actionButtonAssets?: ActionButtonAssetsConfiguration;
|
|
98
112
|
};
|
|
99
113
|
|
|
100
|
-
export interface Action {
|
|
101
|
-
type: string;
|
|
102
|
-
payload?: any;
|
|
103
|
-
options?: any;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export interface Header {
|
|
107
|
-
title: string;
|
|
108
|
-
subtitle?: string;
|
|
109
|
-
icon?: string;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export interface Content {
|
|
113
|
-
title: string;
|
|
114
|
-
stickyTitle?: boolean;
|
|
115
|
-
items: MenuItem[];
|
|
116
|
-
itemsUrl?: string;
|
|
117
|
-
action?: Action;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export interface Menu {
|
|
121
|
-
header?: Header;
|
|
122
|
-
content: Content;
|
|
123
|
-
closeButton?: boolean;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export interface PresentSubMenuAction extends Action {
|
|
127
|
-
menu: Menu;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export interface SecondaryAction {
|
|
131
|
-
action: Action | PresentSubMenuAction;
|
|
132
|
-
icon?: string;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export interface MenuItem {
|
|
136
|
-
title: string;
|
|
137
|
-
summary?: string;
|
|
138
|
-
icon?: string;
|
|
139
|
-
isSelected?: boolean;
|
|
140
|
-
action?: Action | PresentSubMenuAction;
|
|
141
|
-
secondaryAction?: SecondaryAction;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
114
|
export const DEFAULT_TEXT_LABEL_1_CONFIGURATION: LabelConfiguration = {
|
|
145
115
|
fontColor: "#FFFFFF",
|
|
146
116
|
focusedFontColor: "#FFFFFF",
|
|
@@ -191,14 +161,19 @@ export type ItemData = {
|
|
|
191
161
|
leadingButton?: ItemButtonAction;
|
|
192
162
|
/** Button 1 (right most) — hardcoded action decides icon. */
|
|
193
163
|
trailingButton?: ItemButtonAction;
|
|
164
|
+
isSelected?: boolean;
|
|
194
165
|
};
|
|
195
166
|
|
|
196
|
-
export type
|
|
167
|
+
export type AudioPlayerTrackItemProps = {
|
|
197
168
|
configuration: ItemConfiguration;
|
|
198
169
|
data: ItemData;
|
|
199
170
|
focused?: boolean;
|
|
200
171
|
focusedLeadingButton?: boolean;
|
|
201
172
|
focusedTrailingButton?: boolean;
|
|
173
|
+
onPress?: () => void;
|
|
174
|
+
onLeadingButtonPress?: () => void;
|
|
175
|
+
onTrailingButtonPress?: () => void;
|
|
176
|
+
renderHandle?: (element: React.ReactElement) => React.ReactElement;
|
|
202
177
|
};
|
|
203
178
|
|
|
204
179
|
// ---------------------------------------------------------------------------
|
|
@@ -234,9 +209,9 @@ const CONTAINER_SPEC_LARGE_IMAGE: ContainerSpec = {
|
|
|
234
209
|
|
|
235
210
|
const CONTAINER_SPEC_DEFAULT: ContainerSpec = {
|
|
236
211
|
paddingTop: 8,
|
|
237
|
-
paddingRight:
|
|
212
|
+
paddingRight: 20,
|
|
238
213
|
paddingBottom: 8,
|
|
239
|
-
paddingLeft:
|
|
214
|
+
paddingLeft: 20,
|
|
240
215
|
horizontalGutter: 12,
|
|
241
216
|
verticalGutter: 2,
|
|
242
217
|
};
|
|
@@ -297,16 +272,6 @@ const DEFAULT_THUMB_ASSET =
|
|
|
297
272
|
const DEFAULT_EQUALIZER_ASSET =
|
|
298
273
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAI0lEQVR42mNgGNTgPxTQzwB0DVQ3gKCBowbQwYAhkBIHBAAA9TvPMeOFaLMAAAAASUVORK5CYII=";
|
|
299
274
|
|
|
300
|
-
const BUTTON_ASSETS: Record<ItemButtonAction, string> = {
|
|
301
|
-
playPause:
|
|
302
|
-
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAAdklEQVR42u3ZwRUAERAEUfkn3TaF5TFTrSuCf3CgjZGg6ast7G8YaAlcB8JAj8F1MRR2G63CUNglNAqsRvmB1TAfsBoXcMABV4MFKEci4IADNrkAed2H80R66SHqvUvglh/ktoZcL5H7MHKBx/5xYH+RsP90t5t2UpF6+22a+AAAAABJRU5ErkJggg==",
|
|
303
|
-
drag: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAIklEQVR42mNgGAWjYGiC/2SCwWPBaByMxsFoHIyCUTDYAAAqhk7AVXdZJwAAAABJRU5ErkJggg==",
|
|
304
|
-
multiSelect:
|
|
305
|
-
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAWklEQVR42t2VUQ4AIAhCvf+lrQsULJJZbH7GM1cS0Uk5dd0Qqcz4GJSCSs0pSCkAHNoWBfkTgIxpgGK+ujyEKABqRGyn9FO1A+yfrf+qsGxTSx5YEs2WyU9oAKBJKg8Kfq4dAAAAAElFTkSuQmCC",
|
|
306
|
-
remove:
|
|
307
|
-
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAUklEQVR42mNgGPbgPx5AVYOJlSPJcGqrJU8DKXooCVui9FIacXj1UyNl4DWDLhYgc8nA+INpeFgwtCOZ5vmALjmZ5mURXUpTutQHdKnRRgEMAACwjWWprU1B+AAAAABJRU5ErkJggg==",
|
|
308
|
-
};
|
|
309
|
-
|
|
310
275
|
function getTextTransformStyle(
|
|
311
276
|
textTransform: TextTransform
|
|
312
277
|
): "none" | "lowercase" | "uppercase" | "capitalize" {
|
|
@@ -324,32 +289,49 @@ function resolveContainerSpec(image: ImageConfiguration): ContainerSpec {
|
|
|
324
289
|
: CONTAINER_SPEC_DEFAULT;
|
|
325
290
|
}
|
|
326
291
|
|
|
327
|
-
function mapMenuItemToNowPlayingData(
|
|
292
|
+
export function mapMenuItemToNowPlayingData(
|
|
293
|
+
item: MenuItem,
|
|
294
|
+
isPaused?: boolean
|
|
295
|
+
): ItemData {
|
|
328
296
|
return {
|
|
329
297
|
imageUri: item.icon,
|
|
330
298
|
textLabel1: item.title,
|
|
331
299
|
textLabel2: item.summary ?? "",
|
|
332
300
|
nowPlayingLabel: "Now Playing",
|
|
333
301
|
trailingButton: "playPause",
|
|
302
|
+
isSelected: isPaused !== undefined ? !isPaused : item.isSelected,
|
|
334
303
|
};
|
|
335
304
|
}
|
|
336
305
|
|
|
337
|
-
function mapMenuItemToQueuedData(item: MenuItem): ItemData {
|
|
306
|
+
export function mapMenuItemToQueuedData(item: MenuItem): ItemData {
|
|
338
307
|
return {
|
|
339
308
|
imageUri: item.icon,
|
|
340
309
|
textLabel1: item.title,
|
|
341
310
|
textLabel2: item.summary ?? "",
|
|
342
311
|
leadingButton: "remove",
|
|
343
312
|
trailingButton: "drag",
|
|
313
|
+
isSelected: item.isSelected,
|
|
344
314
|
};
|
|
345
315
|
}
|
|
346
316
|
|
|
347
|
-
function mapMenuItemToPlaylistData(
|
|
317
|
+
export function mapMenuItemToPlaylistData(
|
|
318
|
+
item: MenuItem,
|
|
319
|
+
behavior?: SelectionBehavior
|
|
320
|
+
): ItemData {
|
|
321
|
+
const showSelectionWidget =
|
|
322
|
+
behavior?.selectMode !== "none" && item.trailingButton !== "none";
|
|
323
|
+
|
|
324
|
+
const summary =
|
|
325
|
+
typeof item.summary === "string" ? item.summary.trim() : item.summary;
|
|
326
|
+
|
|
348
327
|
return {
|
|
349
328
|
imageUri: item.icon,
|
|
350
329
|
textLabel1: item.title,
|
|
351
|
-
textLabel2:
|
|
352
|
-
trailingButton:
|
|
330
|
+
textLabel2: summary || "",
|
|
331
|
+
trailingButton: showSelectionWidget
|
|
332
|
+
? item.trailingButton || ("multiSelect" as ItemButtonAction)
|
|
333
|
+
: undefined,
|
|
334
|
+
isSelected: item.isSelected,
|
|
353
335
|
};
|
|
354
336
|
}
|
|
355
337
|
|
|
@@ -362,6 +344,7 @@ type ItemContainerProps = {
|
|
|
362
344
|
background: BackgroundConfiguration;
|
|
363
345
|
focused: boolean;
|
|
364
346
|
children: React.ReactNode;
|
|
347
|
+
onPress?: () => void;
|
|
365
348
|
};
|
|
366
349
|
|
|
367
350
|
function ItemContainer({
|
|
@@ -369,23 +352,25 @@ function ItemContainer({
|
|
|
369
352
|
background,
|
|
370
353
|
focused,
|
|
371
354
|
children,
|
|
355
|
+
onPress,
|
|
372
356
|
}: ItemContainerProps) {
|
|
373
357
|
const container = resolveContainerSpec(image);
|
|
374
358
|
const bg = focused ? background.focusedColor : background.defaultColor;
|
|
375
359
|
|
|
376
360
|
return (
|
|
377
|
-
<
|
|
378
|
-
|
|
379
|
-
|
|
361
|
+
<Pressable
|
|
362
|
+
onPress={onPress}
|
|
363
|
+
style={({ pressed }) => ({
|
|
364
|
+
backgroundColor: pressed ? background.focusedColor : bg,
|
|
380
365
|
borderRadius: background.cornerRadius,
|
|
381
|
-
paddingTop: container.paddingTop,
|
|
382
|
-
paddingRight: container.paddingRight,
|
|
383
|
-
paddingBottom: container.paddingBottom,
|
|
384
|
-
paddingLeft: container.paddingLeft,
|
|
385
|
-
}}
|
|
366
|
+
paddingTop: background.paddingTop ?? container.paddingTop,
|
|
367
|
+
paddingRight: background.paddingRight ?? container.paddingRight,
|
|
368
|
+
paddingBottom: background.paddingBottom ?? container.paddingBottom,
|
|
369
|
+
paddingLeft: background.paddingLeft ?? container.paddingLeft,
|
|
370
|
+
})}
|
|
386
371
|
>
|
|
387
372
|
{children}
|
|
388
|
-
</
|
|
373
|
+
</Pressable>
|
|
389
374
|
);
|
|
390
375
|
}
|
|
391
376
|
|
|
@@ -486,27 +471,272 @@ function NowPlayingRow({
|
|
|
486
471
|
type ItemButtonProps = {
|
|
487
472
|
action: ItemButtonAction;
|
|
488
473
|
focused?: boolean;
|
|
474
|
+
onPress?: () => void;
|
|
475
|
+
isSelected?: boolean;
|
|
476
|
+
checkboxAssets?: CheckboxAssetsConfiguration;
|
|
477
|
+
actionButtonAssets?: ActionButtonAssetsConfiguration;
|
|
489
478
|
};
|
|
490
479
|
|
|
491
|
-
function ItemButton({
|
|
480
|
+
function ItemButton({
|
|
481
|
+
action,
|
|
482
|
+
focused = false,
|
|
483
|
+
onPress,
|
|
484
|
+
isSelected = false,
|
|
485
|
+
checkboxAssets,
|
|
486
|
+
actionButtonAssets,
|
|
487
|
+
}: ItemButtonProps) {
|
|
492
488
|
const layout = BUTTON_LAYOUT_SPEC[action];
|
|
493
489
|
|
|
490
|
+
if (!layout) {
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const renderIcon = () => {
|
|
495
|
+
switch (action) {
|
|
496
|
+
case "playPause": {
|
|
497
|
+
const iconSize = layout.assetWidth;
|
|
498
|
+
const iconRadius = iconSize / 2;
|
|
499
|
+
|
|
500
|
+
return (
|
|
501
|
+
<View
|
|
502
|
+
style={{
|
|
503
|
+
width: iconSize,
|
|
504
|
+
height: iconSize,
|
|
505
|
+
borderRadius: iconRadius,
|
|
506
|
+
backgroundColor: "#FFFFFF",
|
|
507
|
+
justifyContent: "center",
|
|
508
|
+
alignItems: "center",
|
|
509
|
+
}}
|
|
510
|
+
>
|
|
511
|
+
{isSelected ? (
|
|
512
|
+
<View
|
|
513
|
+
style={{
|
|
514
|
+
flexDirection: "row",
|
|
515
|
+
justifyContent: "space-between",
|
|
516
|
+
width: 10,
|
|
517
|
+
height: 16,
|
|
518
|
+
}}
|
|
519
|
+
>
|
|
520
|
+
<View
|
|
521
|
+
style={{
|
|
522
|
+
width: 3.5,
|
|
523
|
+
height: 16,
|
|
524
|
+
backgroundColor: "#1e1e1e",
|
|
525
|
+
borderRadius: 1,
|
|
526
|
+
}}
|
|
527
|
+
/>
|
|
528
|
+
<View
|
|
529
|
+
style={{
|
|
530
|
+
width: 3.5,
|
|
531
|
+
height: 16,
|
|
532
|
+
backgroundColor: "#1e1e1e",
|
|
533
|
+
borderRadius: 1,
|
|
534
|
+
}}
|
|
535
|
+
/>
|
|
536
|
+
</View>
|
|
537
|
+
) : (
|
|
538
|
+
<View
|
|
539
|
+
style={{
|
|
540
|
+
width: 0,
|
|
541
|
+
height: 0,
|
|
542
|
+
backgroundColor: "transparent",
|
|
543
|
+
borderStyle: "solid",
|
|
544
|
+
borderLeftWidth: 14,
|
|
545
|
+
borderRightWidth: 0,
|
|
546
|
+
borderTopWidth: 8,
|
|
547
|
+
borderBottomWidth: 8,
|
|
548
|
+
borderLeftColor: "#1e1e1e",
|
|
549
|
+
borderRightColor: "transparent",
|
|
550
|
+
borderTopColor: "transparent",
|
|
551
|
+
borderBottomColor: "transparent",
|
|
552
|
+
marginLeft: 3,
|
|
553
|
+
}}
|
|
554
|
+
/>
|
|
555
|
+
)}
|
|
556
|
+
</View>
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
case "drag": {
|
|
561
|
+
if (actionButtonAssets?.dragAsset) {
|
|
562
|
+
return (
|
|
563
|
+
<Image
|
|
564
|
+
source={{ uri: actionButtonAssets.dragAsset }}
|
|
565
|
+
style={{
|
|
566
|
+
width: layout.assetWidth,
|
|
567
|
+
height: layout.assetHeight,
|
|
568
|
+
}}
|
|
569
|
+
resizeMode="contain"
|
|
570
|
+
/>
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
return (
|
|
575
|
+
<View
|
|
576
|
+
style={{
|
|
577
|
+
width: 20,
|
|
578
|
+
height: 12,
|
|
579
|
+
justifyContent: "space-between",
|
|
580
|
+
}}
|
|
581
|
+
>
|
|
582
|
+
<View
|
|
583
|
+
style={{
|
|
584
|
+
height: 2,
|
|
585
|
+
backgroundColor: "rgba(255, 255, 255, 0.7)",
|
|
586
|
+
borderRadius: 1,
|
|
587
|
+
}}
|
|
588
|
+
/>
|
|
589
|
+
<View
|
|
590
|
+
style={{
|
|
591
|
+
height: 2,
|
|
592
|
+
backgroundColor: "rgba(255, 255, 255, 0.7)",
|
|
593
|
+
borderRadius: 1,
|
|
594
|
+
}}
|
|
595
|
+
/>
|
|
596
|
+
<View
|
|
597
|
+
style={{
|
|
598
|
+
height: 2,
|
|
599
|
+
backgroundColor: "rgba(255, 255, 255, 0.7)",
|
|
600
|
+
borderRadius: 1,
|
|
601
|
+
}}
|
|
602
|
+
/>
|
|
603
|
+
</View>
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
case "remove": {
|
|
608
|
+
if (actionButtonAssets?.removeAsset) {
|
|
609
|
+
return (
|
|
610
|
+
<Image
|
|
611
|
+
source={{ uri: actionButtonAssets.removeAsset }}
|
|
612
|
+
style={{
|
|
613
|
+
width: layout.assetWidth,
|
|
614
|
+
height: layout.assetHeight,
|
|
615
|
+
}}
|
|
616
|
+
resizeMode="contain"
|
|
617
|
+
/>
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
return (
|
|
622
|
+
<View
|
|
623
|
+
style={{
|
|
624
|
+
width: 24,
|
|
625
|
+
height: 24,
|
|
626
|
+
borderRadius: 12,
|
|
627
|
+
borderWidth: 1.5,
|
|
628
|
+
borderColor: "rgba(255, 255, 255, 0.7)",
|
|
629
|
+
justifyContent: "center",
|
|
630
|
+
alignItems: "center",
|
|
631
|
+
}}
|
|
632
|
+
>
|
|
633
|
+
<View
|
|
634
|
+
style={{
|
|
635
|
+
width: 10,
|
|
636
|
+
height: 1.5,
|
|
637
|
+
backgroundColor: "rgba(255, 255, 255, 0.7)",
|
|
638
|
+
borderRadius: 1,
|
|
639
|
+
}}
|
|
640
|
+
/>
|
|
641
|
+
</View>
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
case "multiSelect": {
|
|
646
|
+
const studioAsset = isSelected
|
|
647
|
+
? checkboxAssets?.checkedAsset
|
|
648
|
+
: checkboxAssets?.asset;
|
|
649
|
+
|
|
650
|
+
if (studioAsset) {
|
|
651
|
+
return (
|
|
652
|
+
<Image
|
|
653
|
+
source={{ uri: studioAsset }}
|
|
654
|
+
style={{
|
|
655
|
+
width: layout.assetWidth,
|
|
656
|
+
height: layout.assetHeight,
|
|
657
|
+
}}
|
|
658
|
+
resizeMode="contain"
|
|
659
|
+
/>
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
if (!isSelected) {
|
|
664
|
+
return (
|
|
665
|
+
<View
|
|
666
|
+
style={{
|
|
667
|
+
width: layout.assetWidth,
|
|
668
|
+
height: layout.assetHeight,
|
|
669
|
+
borderRadius: layout.assetWidth / 2,
|
|
670
|
+
borderWidth: 1.5,
|
|
671
|
+
borderColor: "rgba(255, 255, 255, 0.7)",
|
|
672
|
+
backgroundColor: "transparent",
|
|
673
|
+
}}
|
|
674
|
+
/>
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
return (
|
|
679
|
+
<View
|
|
680
|
+
style={{
|
|
681
|
+
width: 24,
|
|
682
|
+
height: 24,
|
|
683
|
+
borderRadius: 12,
|
|
684
|
+
backgroundColor: "#FFFFFF",
|
|
685
|
+
justifyContent: "center",
|
|
686
|
+
alignItems: "center",
|
|
687
|
+
}}
|
|
688
|
+
>
|
|
689
|
+
<View
|
|
690
|
+
style={{
|
|
691
|
+
width: 6,
|
|
692
|
+
height: 10,
|
|
693
|
+
borderBottomWidth: 2,
|
|
694
|
+
borderRightWidth: 2,
|
|
695
|
+
borderColor: "#1e1e1e",
|
|
696
|
+
transform: [{ rotate: "45deg" }],
|
|
697
|
+
marginTop: -2,
|
|
698
|
+
}}
|
|
699
|
+
/>
|
|
700
|
+
</View>
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
default:
|
|
705
|
+
return null;
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
const buttonPadding = {
|
|
710
|
+
paddingTop: layout.paddingTop,
|
|
711
|
+
paddingRight: layout.paddingRight,
|
|
712
|
+
paddingBottom: layout.paddingBottom,
|
|
713
|
+
paddingLeft: layout.paddingLeft,
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
// A nested Pressable with no handler swallows the parent row press.
|
|
717
|
+
if (!onPress) {
|
|
718
|
+
return (
|
|
719
|
+
<View pointerEvents="none" style={buttonPadding}>
|
|
720
|
+
{renderIcon()}
|
|
721
|
+
</View>
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
|
|
494
725
|
return (
|
|
495
|
-
<
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
paddingBottom: layout.paddingBottom,
|
|
500
|
-
paddingLeft: layout.paddingLeft,
|
|
501
|
-
opacity: focused ? 0.7 : 1,
|
|
726
|
+
<Pressable
|
|
727
|
+
onPress={(e: any) => {
|
|
728
|
+
e?.stopPropagation?.();
|
|
729
|
+
onPress();
|
|
502
730
|
}}
|
|
731
|
+
style={({ pressed }) => [
|
|
732
|
+
buttonPadding,
|
|
733
|
+
{
|
|
734
|
+
opacity: pressed || focused ? 0.7 : 1,
|
|
735
|
+
},
|
|
736
|
+
]}
|
|
503
737
|
>
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
style={{ width: layout.assetWidth, height: layout.assetHeight }}
|
|
507
|
-
resizeMode="contain"
|
|
508
|
-
/>
|
|
509
|
-
</View>
|
|
738
|
+
{renderIcon()}
|
|
739
|
+
</Pressable>
|
|
510
740
|
);
|
|
511
741
|
}
|
|
512
742
|
|
|
@@ -515,6 +745,12 @@ type ItemButtonsProps = {
|
|
|
515
745
|
trailingButton?: ItemButtonAction;
|
|
516
746
|
focusedLeadingButton?: boolean;
|
|
517
747
|
focusedTrailingButton?: boolean;
|
|
748
|
+
onLeadingButtonPress?: () => void;
|
|
749
|
+
onTrailingButtonPress?: () => void;
|
|
750
|
+
isSelected?: boolean;
|
|
751
|
+
renderHandle?: (element: React.ReactElement) => React.ReactElement;
|
|
752
|
+
checkboxAssets?: CheckboxAssetsConfiguration;
|
|
753
|
+
actionButtonAssets?: ActionButtonAssetsConfiguration;
|
|
518
754
|
};
|
|
519
755
|
|
|
520
756
|
function ItemButtons({
|
|
@@ -522,6 +758,12 @@ function ItemButtons({
|
|
|
522
758
|
trailingButton,
|
|
523
759
|
focusedLeadingButton = false,
|
|
524
760
|
focusedTrailingButton = false,
|
|
761
|
+
onLeadingButtonPress,
|
|
762
|
+
onTrailingButtonPress,
|
|
763
|
+
isSelected = false,
|
|
764
|
+
renderHandle,
|
|
765
|
+
checkboxAssets,
|
|
766
|
+
actionButtonAssets,
|
|
525
767
|
}: ItemButtonsProps) {
|
|
526
768
|
if (!leadingButton && !trailingButton) {
|
|
527
769
|
return null;
|
|
@@ -531,42 +773,106 @@ function ItemButtons({
|
|
|
531
773
|
<View style={styles.buttonsRow}>
|
|
532
774
|
{leadingButton ? (
|
|
533
775
|
<>
|
|
534
|
-
<ItemButton
|
|
776
|
+
<ItemButton
|
|
777
|
+
action={leadingButton}
|
|
778
|
+
focused={focusedLeadingButton}
|
|
779
|
+
onPress={onLeadingButtonPress}
|
|
780
|
+
isSelected={isSelected}
|
|
781
|
+
checkboxAssets={checkboxAssets}
|
|
782
|
+
actionButtonAssets={actionButtonAssets}
|
|
783
|
+
/>
|
|
535
784
|
<View style={{ width: BUTTONS_CONTAINER_HORIZONTAL_GUTTER }} />
|
|
536
785
|
</>
|
|
537
786
|
) : null}
|
|
538
787
|
{trailingButton ? (
|
|
539
|
-
|
|
788
|
+
trailingButton === "drag" ? (
|
|
789
|
+
renderHandle ? (
|
|
790
|
+
renderHandle(
|
|
791
|
+
<ItemButton
|
|
792
|
+
action={trailingButton}
|
|
793
|
+
focused={focusedTrailingButton}
|
|
794
|
+
onPress={onTrailingButtonPress}
|
|
795
|
+
isSelected={isSelected}
|
|
796
|
+
checkboxAssets={checkboxAssets}
|
|
797
|
+
actionButtonAssets={actionButtonAssets}
|
|
798
|
+
/>
|
|
799
|
+
)
|
|
800
|
+
) : (
|
|
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
|
+
)
|
|
540
820
|
) : null}
|
|
541
821
|
</View>
|
|
542
822
|
);
|
|
543
823
|
}
|
|
544
824
|
|
|
545
825
|
// ---------------------------------------------------------------------------
|
|
546
|
-
//
|
|
826
|
+
// AudioPlayerTrackItem
|
|
547
827
|
// ---------------------------------------------------------------------------
|
|
548
828
|
|
|
549
|
-
export function
|
|
829
|
+
export function AudioPlayerTrackItem({
|
|
550
830
|
configuration,
|
|
551
831
|
data,
|
|
552
832
|
focused = false,
|
|
553
833
|
focusedLeadingButton = false,
|
|
554
834
|
focusedTrailingButton = false,
|
|
555
|
-
|
|
835
|
+
onPress,
|
|
836
|
+
onLeadingButtonPress,
|
|
837
|
+
onTrailingButtonPress,
|
|
838
|
+
renderHandle,
|
|
839
|
+
}: AudioPlayerTrackItemProps) {
|
|
840
|
+
const modalBlocksStyle = useModalBlocksStyle();
|
|
841
|
+
const showNowPlaying = !!data.nowPlayingLabel;
|
|
842
|
+
|
|
843
|
+
const itemBlock =
|
|
844
|
+
showNowPlaying && modalBlocksStyle?.nowPlayingItem
|
|
845
|
+
? modalBlocksStyle.nowPlayingItem
|
|
846
|
+
: modalBlocksStyle?.item;
|
|
847
|
+
|
|
848
|
+
const effectiveConfig = React.useMemo(() => {
|
|
849
|
+
return mergeItemConfiguration(configuration, itemBlock);
|
|
850
|
+
}, [configuration, itemBlock]);
|
|
851
|
+
|
|
556
852
|
const {
|
|
557
853
|
background,
|
|
558
854
|
image,
|
|
559
|
-
nowPlayingAsset,
|
|
560
|
-
nowPlayingLabel,
|
|
561
855
|
textLabel1,
|
|
562
856
|
textLabel2,
|
|
563
|
-
|
|
857
|
+
nowPlayingLabel,
|
|
858
|
+
nowPlayingAsset,
|
|
859
|
+
checkboxAssets,
|
|
860
|
+
actionButtonAssets,
|
|
861
|
+
} = effectiveConfig;
|
|
564
862
|
|
|
565
863
|
const container = resolveContainerSpec(image);
|
|
566
|
-
|
|
864
|
+
|
|
865
|
+
const handleTrailingButtonPress =
|
|
866
|
+
onTrailingButtonPress ??
|
|
867
|
+
(data.trailingButton === "multiSelect" ? onPress : undefined);
|
|
567
868
|
|
|
568
869
|
return (
|
|
569
|
-
<ItemContainer
|
|
870
|
+
<ItemContainer
|
|
871
|
+
image={image}
|
|
872
|
+
background={background}
|
|
873
|
+
focused={focused}
|
|
874
|
+
onPress={onPress}
|
|
875
|
+
>
|
|
570
876
|
<View style={styles.row}>
|
|
571
877
|
<ItemThumbnail configuration={image} imageUri={data.imageUri} />
|
|
572
878
|
<View style={{ width: container.horizontalGutter }} />
|
|
@@ -594,6 +900,12 @@ export function Item({
|
|
|
594
900
|
trailingButton={data.trailingButton}
|
|
595
901
|
focusedLeadingButton={focusedLeadingButton}
|
|
596
902
|
focusedTrailingButton={focusedTrailingButton}
|
|
903
|
+
onLeadingButtonPress={onLeadingButtonPress}
|
|
904
|
+
onTrailingButtonPress={handleTrailingButtonPress}
|
|
905
|
+
isSelected={data.isSelected}
|
|
906
|
+
renderHandle={renderHandle}
|
|
907
|
+
checkboxAssets={checkboxAssets}
|
|
908
|
+
actionButtonAssets={actionButtonAssets}
|
|
597
909
|
/>
|
|
598
910
|
</View>
|
|
599
911
|
</ItemContainer>
|
|
@@ -663,47 +975,3 @@ export const VARIANT_PLAYLIST_ITEM: ItemConfiguration = {
|
|
|
663
975
|
textLabel1: DEFAULT_TEXT_LABEL_1_CONFIGURATION,
|
|
664
976
|
textLabel2: DEFAULT_TEXT_LABEL_2_CONFIGURATION,
|
|
665
977
|
};
|
|
666
|
-
|
|
667
|
-
export default function App() {
|
|
668
|
-
// Hardcoded core mock data objects matching user types framework
|
|
669
|
-
const sharedMockItem: MenuItem = {
|
|
670
|
-
title: "Content Title",
|
|
671
|
-
summary: "Artist",
|
|
672
|
-
icon: "https://picsum.photos/200",
|
|
673
|
-
action: { type: "PLAY_AUDIO" },
|
|
674
|
-
secondaryAction: { action: { type: "OPEN_CONTEXT_MENU" } },
|
|
675
|
-
};
|
|
676
|
-
|
|
677
|
-
const playlistMockItem: MenuItem = {
|
|
678
|
-
title: "Playlist Name",
|
|
679
|
-
summary: "12 Songs",
|
|
680
|
-
icon: "https://picsum.photos/201",
|
|
681
|
-
isSelected: true,
|
|
682
|
-
action: { type: "NAVIGATE_PLAYLIST" },
|
|
683
|
-
};
|
|
684
|
-
|
|
685
|
-
return (
|
|
686
|
-
<View style={styles.demoScreen}>
|
|
687
|
-
<Text style={styles.demoHeading}>Modal Item Building Block</Text>
|
|
688
|
-
|
|
689
|
-
<Text style={styles.demoLabel}>Now Playing</Text>
|
|
690
|
-
<Item
|
|
691
|
-
configuration={VARIANT_NOW_PLAYING}
|
|
692
|
-
data={mapMenuItemToNowPlayingData(sharedMockItem)}
|
|
693
|
-
/>
|
|
694
|
-
|
|
695
|
-
<Text style={styles.demoLabel}>Queued Item</Text>
|
|
696
|
-
<Item
|
|
697
|
-
configuration={VARIANT_QUEUED_ITEM}
|
|
698
|
-
data={mapMenuItemToQueuedData(sharedMockItem)}
|
|
699
|
-
focused
|
|
700
|
-
/>
|
|
701
|
-
|
|
702
|
-
<Text style={styles.demoLabel}>Playlist Item</Text>
|
|
703
|
-
<Item
|
|
704
|
-
configuration={VARIANT_PLAYLIST_ITEM}
|
|
705
|
-
data={mapMenuItemToPlaylistData(playlistMockItem)}
|
|
706
|
-
/>
|
|
707
|
-
</View>
|
|
708
|
-
);
|
|
709
|
-
}
|