@applicaster/zapp-react-native-utils 16.0.0-alpha.9530606740 → 16.0.0-alpha.9739533780
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/actionsExecutor/ActionExecutorContext.tsx +2 -2
- package/actionsExecutor/actions/index.ts +1 -1
- package/actionsExecutor/actions/showToast.ts +31 -0
- package/actionsExecutor/types.ts +1 -1
- package/modalState/index.ts +74 -25
- package/package.json +2 -2
- package/reactHooks/navigation/__mocks__/index.ts +4 -0
- package/reactHooks/navigation/__tests__/useIsScreenActive.test.ts +42 -0
- package/reactHooks/navigation/index.ts +1 -1
- package/reactHooks/navigation/useIsScreenActive.ts +29 -8
- package/reactHooks/state/useComponentScreenState.ts +1 -1
- package/actionsExecutor/actions/openBottomSheet.ts +0 -177
- package/modalState/ContentViewModel.ts +0 -59
- package/modalState/ModalOrchestrator.ts +0 -204
- package/modalState/__tests__/ContentViewModel.test.ts +0 -107
- package/modalState/components/ActionItem.tsx +0 -155
- package/modalState/components/BottomSheetHeader.tsx +0 -245
- package/modalState/components/PrimaryButton.tsx +0 -54
- package/modalState/components/TrackItem.tsx +0 -241
- package/modalState/store.ts +0 -102
- package/modalState/types.ts +0 -55
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Text, StyleSheet, Pressable } from "react-native";
|
|
3
|
-
|
|
4
|
-
const styles = StyleSheet.create({
|
|
5
|
-
primaryButton: {
|
|
6
|
-
flexDirection: "row",
|
|
7
|
-
backgroundColor: "#FFFFFF",
|
|
8
|
-
borderRadius: 12,
|
|
9
|
-
padding: 12,
|
|
10
|
-
marginHorizontal: 16,
|
|
11
|
-
alignItems: "center",
|
|
12
|
-
justifyContent: "center",
|
|
13
|
-
marginTop: 16,
|
|
14
|
-
marginBottom: 8,
|
|
15
|
-
},
|
|
16
|
-
primaryButtonText: {
|
|
17
|
-
color: "#000000",
|
|
18
|
-
fontSize: 15,
|
|
19
|
-
fontWeight: "bold",
|
|
20
|
-
},
|
|
21
|
-
primaryButtonIcon: {
|
|
22
|
-
color: "#000000",
|
|
23
|
-
fontSize: 18,
|
|
24
|
-
marginRight: 8,
|
|
25
|
-
},
|
|
26
|
-
pressedState: {
|
|
27
|
-
opacity: 0.8,
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
export interface PrimaryButtonProps {
|
|
32
|
-
title: string;
|
|
33
|
-
icon?: string;
|
|
34
|
-
onPress?: () => void;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export const PrimaryButton: React.FC<PrimaryButtonProps> = ({
|
|
38
|
-
title,
|
|
39
|
-
icon,
|
|
40
|
-
onPress,
|
|
41
|
-
}) => {
|
|
42
|
-
return (
|
|
43
|
-
<Pressable
|
|
44
|
-
style={({ pressed }) => [
|
|
45
|
-
styles.primaryButton,
|
|
46
|
-
pressed && styles.pressedState,
|
|
47
|
-
]}
|
|
48
|
-
onPress={onPress}
|
|
49
|
-
>
|
|
50
|
-
{icon ? <Text style={styles.primaryButtonIcon}>{icon}</Text> : null}
|
|
51
|
-
<Text style={styles.primaryButtonText}>{title}</Text>
|
|
52
|
-
</Pressable>
|
|
53
|
-
);
|
|
54
|
-
};
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { View, Text, StyleSheet, Pressable, Image } from "react-native";
|
|
3
|
-
|
|
4
|
-
const styles = StyleSheet.create({
|
|
5
|
-
trackItem: {
|
|
6
|
-
flexDirection: "row",
|
|
7
|
-
alignItems: "center",
|
|
8
|
-
paddingVertical: 10,
|
|
9
|
-
paddingHorizontal: 12,
|
|
10
|
-
borderBottomWidth: 1,
|
|
11
|
-
borderBottomColor: "#2a2a2a",
|
|
12
|
-
backgroundColor: "#1e1e1e",
|
|
13
|
-
},
|
|
14
|
-
trackItemFocused: {
|
|
15
|
-
backgroundColor: "#2d2d2d",
|
|
16
|
-
},
|
|
17
|
-
trackImage: {
|
|
18
|
-
width: 48,
|
|
19
|
-
height: 48,
|
|
20
|
-
borderRadius: 6,
|
|
21
|
-
marginRight: 12,
|
|
22
|
-
backgroundColor: "#2a2a2a",
|
|
23
|
-
},
|
|
24
|
-
trackImagePlaceholder: {
|
|
25
|
-
width: 48,
|
|
26
|
-
height: 48,
|
|
27
|
-
borderRadius: 6,
|
|
28
|
-
borderWidth: 1,
|
|
29
|
-
borderColor: "rgba(255, 255, 255, 0.1)",
|
|
30
|
-
backgroundColor: "#333",
|
|
31
|
-
marginRight: 12,
|
|
32
|
-
alignItems: "center",
|
|
33
|
-
justifyContent: "center",
|
|
34
|
-
},
|
|
35
|
-
trackImageText: {
|
|
36
|
-
color: "#fff",
|
|
37
|
-
fontSize: 20,
|
|
38
|
-
},
|
|
39
|
-
trackTextContainer: {
|
|
40
|
-
flex: 1,
|
|
41
|
-
justifyContent: "center",
|
|
42
|
-
},
|
|
43
|
-
nowPlayingLabel: {
|
|
44
|
-
color: "#30d158",
|
|
45
|
-
fontSize: 11,
|
|
46
|
-
fontWeight: "600",
|
|
47
|
-
marginBottom: 2,
|
|
48
|
-
textTransform: "uppercase",
|
|
49
|
-
},
|
|
50
|
-
trackTitle: {
|
|
51
|
-
color: "#FFFFFF",
|
|
52
|
-
fontSize: 15,
|
|
53
|
-
fontWeight: "600",
|
|
54
|
-
},
|
|
55
|
-
trackSubtitle: {
|
|
56
|
-
color: "#999999",
|
|
57
|
-
fontSize: 13,
|
|
58
|
-
fontWeight: "500",
|
|
59
|
-
marginTop: 2,
|
|
60
|
-
},
|
|
61
|
-
trackActions: {
|
|
62
|
-
flexDirection: "row",
|
|
63
|
-
alignItems: "center",
|
|
64
|
-
},
|
|
65
|
-
queuedActionsContainer: {
|
|
66
|
-
flexDirection: "row",
|
|
67
|
-
alignItems: "center",
|
|
68
|
-
},
|
|
69
|
-
trackActionButton: {
|
|
70
|
-
padding: 10,
|
|
71
|
-
marginLeft: 4,
|
|
72
|
-
},
|
|
73
|
-
trackActionIcon: {
|
|
74
|
-
color: "#FFFFFF",
|
|
75
|
-
fontSize: 18,
|
|
76
|
-
},
|
|
77
|
-
playPauseButton: {
|
|
78
|
-
width: 36,
|
|
79
|
-
height: 36,
|
|
80
|
-
backgroundColor: "#FFFFFF",
|
|
81
|
-
borderRadius: 18,
|
|
82
|
-
alignItems: "center",
|
|
83
|
-
justifyContent: "center",
|
|
84
|
-
marginLeft: 8,
|
|
85
|
-
},
|
|
86
|
-
playPauseText: {
|
|
87
|
-
color: "#000000",
|
|
88
|
-
fontWeight: "bold",
|
|
89
|
-
fontSize: 12,
|
|
90
|
-
},
|
|
91
|
-
radioContainer: {
|
|
92
|
-
padding: 10,
|
|
93
|
-
},
|
|
94
|
-
radioUnselected: {
|
|
95
|
-
width: 24,
|
|
96
|
-
height: 24,
|
|
97
|
-
borderRadius: 12,
|
|
98
|
-
borderWidth: 1,
|
|
99
|
-
borderColor: "#999",
|
|
100
|
-
},
|
|
101
|
-
radioSelected: {
|
|
102
|
-
width: 24,
|
|
103
|
-
height: 24,
|
|
104
|
-
borderRadius: 12,
|
|
105
|
-
backgroundColor: "#FFFFFF",
|
|
106
|
-
alignItems: "center",
|
|
107
|
-
justifyContent: "center",
|
|
108
|
-
},
|
|
109
|
-
radioCheck: {
|
|
110
|
-
color: "#000000",
|
|
111
|
-
fontSize: 14,
|
|
112
|
-
fontWeight: "bold",
|
|
113
|
-
},
|
|
114
|
-
pressedState: {
|
|
115
|
-
opacity: 0.7,
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
export interface TrackItemProps {
|
|
120
|
-
variant: "nowPlaying" | "queued" | "playlist";
|
|
121
|
-
title: string;
|
|
122
|
-
subtitle?: string;
|
|
123
|
-
icon?: string;
|
|
124
|
-
isSelected?: boolean;
|
|
125
|
-
isPlaying?: boolean;
|
|
126
|
-
onPress?: () => void;
|
|
127
|
-
onSecondaryPress?: () => void;
|
|
128
|
-
onRemovePress?: () => void;
|
|
129
|
-
onPlayPausePress?: () => void;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export const TrackItem: React.FC<TrackItemProps> = ({
|
|
133
|
-
variant,
|
|
134
|
-
title,
|
|
135
|
-
subtitle,
|
|
136
|
-
icon,
|
|
137
|
-
isSelected = false,
|
|
138
|
-
isPlaying = false,
|
|
139
|
-
onPress,
|
|
140
|
-
onSecondaryPress,
|
|
141
|
-
onRemovePress,
|
|
142
|
-
onPlayPausePress,
|
|
143
|
-
}) => {
|
|
144
|
-
const [isFocused, setIsFocused] = useState(false);
|
|
145
|
-
|
|
146
|
-
const isIconUri =
|
|
147
|
-
icon &&
|
|
148
|
-
(icon.startsWith("http") ||
|
|
149
|
-
icon.startsWith("file") ||
|
|
150
|
-
icon.includes("/") ||
|
|
151
|
-
icon.includes("."));
|
|
152
|
-
|
|
153
|
-
return (
|
|
154
|
-
<Pressable
|
|
155
|
-
style={({ pressed }) => [
|
|
156
|
-
styles.trackItem,
|
|
157
|
-
(pressed || isFocused) && styles.trackItemFocused,
|
|
158
|
-
]}
|
|
159
|
-
onPress={onPress}
|
|
160
|
-
onPressIn={() => setIsFocused(true)}
|
|
161
|
-
onPressOut={() => setIsFocused(false)}
|
|
162
|
-
>
|
|
163
|
-
{icon ? (
|
|
164
|
-
isIconUri ? (
|
|
165
|
-
<Image source={{ uri: icon }} style={styles.trackImage} />
|
|
166
|
-
) : (
|
|
167
|
-
<View style={styles.trackImagePlaceholder}>
|
|
168
|
-
<Text style={styles.trackImageText}>{icon}</Text>
|
|
169
|
-
</View>
|
|
170
|
-
)
|
|
171
|
-
) : (
|
|
172
|
-
<View style={styles.trackImagePlaceholder} />
|
|
173
|
-
)}
|
|
174
|
-
|
|
175
|
-
<View style={styles.trackTextContainer}>
|
|
176
|
-
{variant === "nowPlaying" ? (
|
|
177
|
-
<Text style={styles.nowPlayingLabel}>♪ Now Playing</Text>
|
|
178
|
-
) : null}
|
|
179
|
-
<Text numberOfLines={1} style={styles.trackTitle}>
|
|
180
|
-
{title}
|
|
181
|
-
</Text>
|
|
182
|
-
{subtitle ? (
|
|
183
|
-
<Text numberOfLines={1} style={styles.trackSubtitle}>
|
|
184
|
-
{subtitle}
|
|
185
|
-
</Text>
|
|
186
|
-
) : null}
|
|
187
|
-
</View>
|
|
188
|
-
|
|
189
|
-
<View style={styles.trackActions}>
|
|
190
|
-
{variant === "nowPlaying" ? (
|
|
191
|
-
<Pressable
|
|
192
|
-
style={({ pressed }) => [
|
|
193
|
-
styles.playPauseButton,
|
|
194
|
-
pressed && styles.pressedState,
|
|
195
|
-
]}
|
|
196
|
-
onPress={onPlayPausePress || onPress}
|
|
197
|
-
>
|
|
198
|
-
<Text style={styles.playPauseText}>{isPlaying ? "II" : "▶"}</Text>
|
|
199
|
-
</Pressable>
|
|
200
|
-
) : null}
|
|
201
|
-
|
|
202
|
-
{variant === "queued" ? (
|
|
203
|
-
<View style={styles.queuedActionsContainer}>
|
|
204
|
-
{onRemovePress ? (
|
|
205
|
-
<Pressable
|
|
206
|
-
style={({ pressed }) => [
|
|
207
|
-
styles.trackActionButton,
|
|
208
|
-
pressed && styles.pressedState,
|
|
209
|
-
]}
|
|
210
|
-
onPress={onRemovePress}
|
|
211
|
-
>
|
|
212
|
-
<Text style={styles.trackActionIcon}>⊖</Text>
|
|
213
|
-
</Pressable>
|
|
214
|
-
) : null}
|
|
215
|
-
<Pressable
|
|
216
|
-
style={({ pressed }) => [
|
|
217
|
-
styles.trackActionButton,
|
|
218
|
-
pressed && styles.pressedState,
|
|
219
|
-
]}
|
|
220
|
-
onPress={onSecondaryPress || onPress}
|
|
221
|
-
>
|
|
222
|
-
<Text style={styles.trackActionIcon}>≡</Text>
|
|
223
|
-
</Pressable>
|
|
224
|
-
</View>
|
|
225
|
-
) : null}
|
|
226
|
-
|
|
227
|
-
{variant === "playlist" ? (
|
|
228
|
-
<View style={styles.radioContainer}>
|
|
229
|
-
{isSelected ? (
|
|
230
|
-
<View style={styles.radioSelected}>
|
|
231
|
-
<Text style={styles.radioCheck}>✓</Text>
|
|
232
|
-
</View>
|
|
233
|
-
) : (
|
|
234
|
-
<View style={styles.radioUnselected} />
|
|
235
|
-
)}
|
|
236
|
-
</View>
|
|
237
|
-
) : null}
|
|
238
|
-
</View>
|
|
239
|
-
</Pressable>
|
|
240
|
-
);
|
|
241
|
-
};
|
package/modalState/store.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { createStore, useStore } from "zustand";
|
|
2
|
-
|
|
3
|
-
export interface ModalState {
|
|
4
|
-
visible: boolean;
|
|
5
|
-
screen: any;
|
|
6
|
-
options: Record<string, unknown>;
|
|
7
|
-
props: Record<string, unknown>;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface ModalStore {
|
|
11
|
-
modalState: ModalState;
|
|
12
|
-
setModalState: (newState: Partial<ModalState>) => void;
|
|
13
|
-
openModal: (
|
|
14
|
-
item: any,
|
|
15
|
-
options?: Record<string, unknown>,
|
|
16
|
-
props?: Record<string, unknown>
|
|
17
|
-
) => void;
|
|
18
|
-
dismissModal: () => void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const initialModalState: ModalState = {
|
|
22
|
-
visible: false,
|
|
23
|
-
screen: null,
|
|
24
|
-
options: {},
|
|
25
|
-
props: {},
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const modalStore = createStore<ModalStore>((set, get) => ({
|
|
29
|
-
modalState: initialModalState,
|
|
30
|
-
setModalState: (newState) =>
|
|
31
|
-
set((state) => ({
|
|
32
|
-
modalState: { ...state.modalState, ...newState },
|
|
33
|
-
})),
|
|
34
|
-
openModal: ({ item, options = {}, props }: OpenModalArg) => {
|
|
35
|
-
const resetStore = () => set({ modalState: initialModalState });
|
|
36
|
-
const { onDismiss, onRequestClose, ...restOptions } = options as any;
|
|
37
|
-
|
|
38
|
-
set({
|
|
39
|
-
modalState: {
|
|
40
|
-
visible: true,
|
|
41
|
-
screen: item,
|
|
42
|
-
options: {
|
|
43
|
-
animated: true,
|
|
44
|
-
animationType: "slide",
|
|
45
|
-
onShow: () => {},
|
|
46
|
-
presentationStyle: "overFullScreen",
|
|
47
|
-
transparent: true,
|
|
48
|
-
...restOptions,
|
|
49
|
-
// Compose caller-provided callbacks with the store reset so both run
|
|
50
|
-
onDismiss: () => {
|
|
51
|
-
resetStore();
|
|
52
|
-
onDismiss?.();
|
|
53
|
-
},
|
|
54
|
-
onRequestClose: () => {
|
|
55
|
-
resetStore();
|
|
56
|
-
onRequestClose?.();
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
props,
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
},
|
|
63
|
-
dismissModal: () => {
|
|
64
|
-
const onDismiss = (get().modalState?.options as any)?.onDismiss;
|
|
65
|
-
|
|
66
|
-
if (typeof onDismiss === "function") {
|
|
67
|
-
onDismiss();
|
|
68
|
-
} else {
|
|
69
|
-
set({ modalState: initialModalState });
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
}));
|
|
73
|
-
|
|
74
|
-
export const useModalStore = <T>(selector: (state: ModalStore) => T) =>
|
|
75
|
-
useStore(modalStore, selector);
|
|
76
|
-
|
|
77
|
-
export const openModal = modalStore.getInitialState().openModal;
|
|
78
|
-
|
|
79
|
-
export const dismissModal = modalStore.getInitialState().dismissModal;
|
|
80
|
-
|
|
81
|
-
export const openBottomSheetModal = ({
|
|
82
|
-
ModalBottomSheetContent,
|
|
83
|
-
modalBottomSheetContentProps,
|
|
84
|
-
props = {},
|
|
85
|
-
options = {},
|
|
86
|
-
}: OpenModalBottomSheetArgs) => {
|
|
87
|
-
openModal({
|
|
88
|
-
item: {
|
|
89
|
-
ModalBottomSheetContent,
|
|
90
|
-
modalBottomSheetContentProps,
|
|
91
|
-
},
|
|
92
|
-
props,
|
|
93
|
-
options: {
|
|
94
|
-
animationType: "none",
|
|
95
|
-
animated: false,
|
|
96
|
-
...options,
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
export const useModalStoreState = (): ModalState =>
|
|
102
|
-
useModalStore<ModalState>((state) => state.modalState);
|
package/modalState/types.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
export interface Header {
|
|
2
|
-
title: string;
|
|
3
|
-
subtitle?: string;
|
|
4
|
-
icon?: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface Action {
|
|
8
|
-
type: string;
|
|
9
|
-
payload?: any;
|
|
10
|
-
options?: any;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Represented as 3 dots icon on top menu (opens new second level menu on desktop
|
|
14
|
-
// or a new bottom sheet on mobile)
|
|
15
|
-
export interface PresentSubMenuAction extends Action {
|
|
16
|
-
menu: Menu;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface SecondaryAction {
|
|
20
|
-
action: Action | PresentSubMenuAction;
|
|
21
|
-
icon?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface MenuItem {
|
|
25
|
-
title: string;
|
|
26
|
-
summary?: string;
|
|
27
|
-
icon?: string;
|
|
28
|
-
isSelected?: boolean;
|
|
29
|
-
// When item represents an audio item, clicking on it will start playback
|
|
30
|
-
// and secondary action will allow to add it to queue or playlist
|
|
31
|
-
action?: Action | PresentSubMenuAction;
|
|
32
|
-
secondaryAction?: SecondaryAction;
|
|
33
|
-
submenu?: MenuItem[]; // todo: not needed. Must be replaced with PresentSubMenuAction
|
|
34
|
-
trailingButton?: any;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface Content {
|
|
38
|
-
title: string;
|
|
39
|
-
stickyTitle?: boolean;
|
|
40
|
-
items: MenuItem[];
|
|
41
|
-
itemsUrl?: string;
|
|
42
|
-
action?: Action;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface Menu {
|
|
46
|
-
header?: Header;
|
|
47
|
-
content: Content;
|
|
48
|
-
closeButton?: boolean;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function isPresentSubMenuAction(
|
|
52
|
-
action: any
|
|
53
|
-
): action is PresentSubMenuAction {
|
|
54
|
-
return !!action && typeof action === "object" && "menu" in action;
|
|
55
|
-
}
|