@applicaster/zapp-react-native-ui-components 15.1.12 → 15.1.13-alpha.1034774223
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/ModalComponent/ActionsBottomSheet/ActionButton.tsx +54 -0
- package/Components/ModalComponent/ActionsBottomSheet/boundActionButton.tsx +21 -0
- package/Components/ModalComponent/ActionsBottomSheet/index.ts +9 -0
- package/Components/ModalComponent/ActionsBottomSheet/openActionsBottomSheet.ts +58 -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 +410 -159
- package/Components/ModalComponent/AudioPlayer/Components/NowPlayingHeaderSection.tsx +89 -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 +100 -0
- package/Components/ModalComponent/__tests__/BottomSheetModalContent.test.tsx +238 -0
- package/Components/ModalComponent/__tests__/TextInputContent.test.tsx +120 -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 +66 -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/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,259 @@ 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
|
+
|
|
494
709
|
return (
|
|
495
|
-
<
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
paddingBottom: layout.paddingBottom,
|
|
500
|
-
paddingLeft: layout.paddingLeft,
|
|
501
|
-
opacity: focused ? 0.7 : 1,
|
|
710
|
+
<Pressable
|
|
711
|
+
onPress={(e: any) => {
|
|
712
|
+
e?.stopPropagation?.();
|
|
713
|
+
onPress?.();
|
|
502
714
|
}}
|
|
715
|
+
style={({ pressed }) => [
|
|
716
|
+
{
|
|
717
|
+
paddingTop: layout.paddingTop,
|
|
718
|
+
paddingRight: layout.paddingRight,
|
|
719
|
+
paddingBottom: layout.paddingBottom,
|
|
720
|
+
paddingLeft: layout.paddingLeft,
|
|
721
|
+
opacity: pressed || focused ? 0.7 : 1,
|
|
722
|
+
},
|
|
723
|
+
]}
|
|
503
724
|
>
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
style={{ width: layout.assetWidth, height: layout.assetHeight }}
|
|
507
|
-
resizeMode="contain"
|
|
508
|
-
/>
|
|
509
|
-
</View>
|
|
725
|
+
{renderIcon()}
|
|
726
|
+
</Pressable>
|
|
510
727
|
);
|
|
511
728
|
}
|
|
512
729
|
|
|
@@ -515,6 +732,12 @@ type ItemButtonsProps = {
|
|
|
515
732
|
trailingButton?: ItemButtonAction;
|
|
516
733
|
focusedLeadingButton?: boolean;
|
|
517
734
|
focusedTrailingButton?: boolean;
|
|
735
|
+
onLeadingButtonPress?: () => void;
|
|
736
|
+
onTrailingButtonPress?: () => void;
|
|
737
|
+
isSelected?: boolean;
|
|
738
|
+
renderHandle?: (element: React.ReactElement) => React.ReactElement;
|
|
739
|
+
checkboxAssets?: CheckboxAssetsConfiguration;
|
|
740
|
+
actionButtonAssets?: ActionButtonAssetsConfiguration;
|
|
518
741
|
};
|
|
519
742
|
|
|
520
743
|
function ItemButtons({
|
|
@@ -522,6 +745,12 @@ function ItemButtons({
|
|
|
522
745
|
trailingButton,
|
|
523
746
|
focusedLeadingButton = false,
|
|
524
747
|
focusedTrailingButton = false,
|
|
748
|
+
onLeadingButtonPress,
|
|
749
|
+
onTrailingButtonPress,
|
|
750
|
+
isSelected = false,
|
|
751
|
+
renderHandle,
|
|
752
|
+
checkboxAssets,
|
|
753
|
+
actionButtonAssets,
|
|
525
754
|
}: ItemButtonsProps) {
|
|
526
755
|
if (!leadingButton && !trailingButton) {
|
|
527
756
|
return null;
|
|
@@ -531,42 +760,102 @@ function ItemButtons({
|
|
|
531
760
|
<View style={styles.buttonsRow}>
|
|
532
761
|
{leadingButton ? (
|
|
533
762
|
<>
|
|
534
|
-
<ItemButton
|
|
763
|
+
<ItemButton
|
|
764
|
+
action={leadingButton}
|
|
765
|
+
focused={focusedLeadingButton}
|
|
766
|
+
onPress={onLeadingButtonPress}
|
|
767
|
+
isSelected={isSelected}
|
|
768
|
+
checkboxAssets={checkboxAssets}
|
|
769
|
+
actionButtonAssets={actionButtonAssets}
|
|
770
|
+
/>
|
|
535
771
|
<View style={{ width: BUTTONS_CONTAINER_HORIZONTAL_GUTTER }} />
|
|
536
772
|
</>
|
|
537
773
|
) : null}
|
|
538
774
|
{trailingButton ? (
|
|
539
|
-
|
|
775
|
+
trailingButton === "drag" ? (
|
|
776
|
+
renderHandle ? (
|
|
777
|
+
renderHandle(
|
|
778
|
+
<ItemButton
|
|
779
|
+
action={trailingButton}
|
|
780
|
+
focused={focusedTrailingButton}
|
|
781
|
+
onPress={onTrailingButtonPress}
|
|
782
|
+
isSelected={isSelected}
|
|
783
|
+
checkboxAssets={checkboxAssets}
|
|
784
|
+
actionButtonAssets={actionButtonAssets}
|
|
785
|
+
/>
|
|
786
|
+
)
|
|
787
|
+
) : (
|
|
788
|
+
<ItemButton
|
|
789
|
+
action={trailingButton}
|
|
790
|
+
focused={focusedTrailingButton}
|
|
791
|
+
onPress={onTrailingButtonPress}
|
|
792
|
+
isSelected={isSelected}
|
|
793
|
+
checkboxAssets={checkboxAssets}
|
|
794
|
+
actionButtonAssets={actionButtonAssets}
|
|
795
|
+
/>
|
|
796
|
+
)
|
|
797
|
+
) : (
|
|
798
|
+
<ItemButton
|
|
799
|
+
action={trailingButton}
|
|
800
|
+
focused={focusedTrailingButton}
|
|
801
|
+
onPress={onTrailingButtonPress}
|
|
802
|
+
isSelected={isSelected}
|
|
803
|
+
checkboxAssets={checkboxAssets}
|
|
804
|
+
actionButtonAssets={actionButtonAssets}
|
|
805
|
+
/>
|
|
806
|
+
)
|
|
540
807
|
) : null}
|
|
541
808
|
</View>
|
|
542
809
|
);
|
|
543
810
|
}
|
|
544
811
|
|
|
545
812
|
// ---------------------------------------------------------------------------
|
|
546
|
-
//
|
|
813
|
+
// AudioPlayerTrackItem
|
|
547
814
|
// ---------------------------------------------------------------------------
|
|
548
815
|
|
|
549
|
-
export function
|
|
816
|
+
export function AudioPlayerTrackItem({
|
|
550
817
|
configuration,
|
|
551
818
|
data,
|
|
552
819
|
focused = false,
|
|
553
820
|
focusedLeadingButton = false,
|
|
554
821
|
focusedTrailingButton = false,
|
|
555
|
-
|
|
822
|
+
onPress,
|
|
823
|
+
onLeadingButtonPress,
|
|
824
|
+
onTrailingButtonPress,
|
|
825
|
+
renderHandle,
|
|
826
|
+
}: AudioPlayerTrackItemProps) {
|
|
827
|
+
const modalBlocksStyle = useModalBlocksStyle();
|
|
828
|
+
const showNowPlaying = !!data.nowPlayingLabel;
|
|
829
|
+
|
|
830
|
+
const itemBlock =
|
|
831
|
+
showNowPlaying && modalBlocksStyle?.nowPlayingItem
|
|
832
|
+
? modalBlocksStyle.nowPlayingItem
|
|
833
|
+
: modalBlocksStyle?.item;
|
|
834
|
+
|
|
835
|
+
const effectiveConfig = React.useMemo(() => {
|
|
836
|
+
return mergeItemConfiguration(configuration, itemBlock);
|
|
837
|
+
}, [configuration, itemBlock]);
|
|
838
|
+
|
|
556
839
|
const {
|
|
557
840
|
background,
|
|
558
841
|
image,
|
|
559
|
-
nowPlayingAsset,
|
|
560
|
-
nowPlayingLabel,
|
|
561
842
|
textLabel1,
|
|
562
843
|
textLabel2,
|
|
563
|
-
|
|
844
|
+
nowPlayingLabel,
|
|
845
|
+
nowPlayingAsset,
|
|
846
|
+
checkboxAssets,
|
|
847
|
+
actionButtonAssets,
|
|
848
|
+
} = effectiveConfig;
|
|
564
849
|
|
|
565
850
|
const container = resolveContainerSpec(image);
|
|
566
|
-
const showNowPlaying = !!data.nowPlayingLabel;
|
|
567
851
|
|
|
568
852
|
return (
|
|
569
|
-
<ItemContainer
|
|
853
|
+
<ItemContainer
|
|
854
|
+
image={image}
|
|
855
|
+
background={background}
|
|
856
|
+
focused={focused}
|
|
857
|
+
onPress={onPress}
|
|
858
|
+
>
|
|
570
859
|
<View style={styles.row}>
|
|
571
860
|
<ItemThumbnail configuration={image} imageUri={data.imageUri} />
|
|
572
861
|
<View style={{ width: container.horizontalGutter }} />
|
|
@@ -594,6 +883,12 @@ export function Item({
|
|
|
594
883
|
trailingButton={data.trailingButton}
|
|
595
884
|
focusedLeadingButton={focusedLeadingButton}
|
|
596
885
|
focusedTrailingButton={focusedTrailingButton}
|
|
886
|
+
onLeadingButtonPress={onLeadingButtonPress}
|
|
887
|
+
onTrailingButtonPress={onTrailingButtonPress}
|
|
888
|
+
isSelected={data.isSelected}
|
|
889
|
+
renderHandle={renderHandle}
|
|
890
|
+
checkboxAssets={checkboxAssets}
|
|
891
|
+
actionButtonAssets={actionButtonAssets}
|
|
597
892
|
/>
|
|
598
893
|
</View>
|
|
599
894
|
</ItemContainer>
|
|
@@ -663,47 +958,3 @@ export const VARIANT_PLAYLIST_ITEM: ItemConfiguration = {
|
|
|
663
958
|
textLabel1: DEFAULT_TEXT_LABEL_1_CONFIGURATION,
|
|
664
959
|
textLabel2: DEFAULT_TEXT_LABEL_2_CONFIGURATION,
|
|
665
960
|
};
|
|
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
|
-
}
|