@applicaster/zapp-react-native-ui-components 15.1.10 → 15.1.11-alpha.7557142055

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 (30) hide show
  1. package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +33 -87
  2. package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +42 -71
  3. package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +142 -107
  4. package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +653 -0
  5. package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +319 -154
  6. package/Components/ModalComponent/AudioPlayer/Components/NowPlayingHeaderSection.tsx +89 -0
  7. package/Components/ModalComponent/AudioPlayer/Components/index.ts +8 -4
  8. package/Components/ModalComponent/AudioPlayer/utils/mergeStyles.ts +199 -0
  9. package/Components/ModalComponent/BottomSheetModalContent.tsx +379 -61
  10. package/Components/ModalComponent/Button/index.tsx +5 -3
  11. package/Components/ModalComponent/Header/index.tsx +20 -7
  12. package/Components/ModalComponent/Header/utils.ts +1 -1
  13. package/Components/ModalComponent/ModalBlocksStyleContext.tsx +10 -0
  14. package/Components/ModalComponent/SortableList.tsx +142 -0
  15. package/Components/ModalComponent/SortableList.web.tsx +102 -0
  16. package/Components/ModalComponent/TextInputContent.tsx +100 -0
  17. package/Components/ModalComponent/__tests__/BottomSheetModalContent.test.tsx +238 -0
  18. package/Components/ModalComponent/__tests__/TextInputContent.test.tsx +120 -0
  19. package/Components/ModalComponent/__tests__/showTextInput.test.ts +95 -0
  20. package/Components/ModalComponent/index.tsx +11 -0
  21. package/Components/ModalComponent/presets/__tests__/getCell.test.ts +66 -0
  22. package/Components/ModalComponent/presets/dynamicCollectionCell.tsx +78 -0
  23. package/Components/ModalComponent/presets/index.ts +27 -0
  24. package/Components/ModalComponent/presets/selectableCell.tsx +28 -0
  25. package/Components/ModalComponent/presets/standardCell.tsx +41 -0
  26. package/Components/ModalComponent/presets/types.ts +35 -0
  27. package/Components/ModalComponent/showTextInput.ts +43 -0
  28. package/Components/ModalComponent/utils.ts +76 -20
  29. package/package.json +6 -5
  30. /package/Decorators/ZappPipesDataConnector/__tests__/{Hero.js → Hero.tsx} +0 -0
@@ -11,31 +11,20 @@
11
11
  */
12
12
 
13
13
  import React from "react";
14
- import { Image, Platform, StyleSheet, Text, View } from "react-native";
14
+ import {
15
+ Image,
16
+ Platform,
17
+ Pressable,
18
+ StyleSheet,
19
+ Text,
20
+ View,
21
+ } from "react-native";
15
22
 
16
23
  const styles = StyleSheet.create({
17
24
  row: {
18
25
  flexDirection: "row",
19
26
  alignItems: "center",
20
27
  },
21
- demoScreen: {
22
- flex: 1,
23
- backgroundColor: "#1C1C1E",
24
- paddingTop: 64,
25
- paddingHorizontal: 16,
26
- gap: 12,
27
- },
28
- demoHeading: {
29
- color: "#FFFFFF",
30
- fontSize: 20,
31
- fontWeight: "600",
32
- marginBottom: 8,
33
- },
34
- demoLabel: {
35
- color: "#999999",
36
- fontSize: 13,
37
- marginTop: 8,
38
- },
39
28
  });
40
29
 
41
30
  // ---------------------------------------------------------------------------
@@ -123,10 +112,11 @@ export type ActionData = {
123
112
  showTrailingChevron?: boolean;
124
113
  };
125
114
 
126
- export type ItemProps = {
115
+ export type AudioPlayerActionProps = {
127
116
  configuration: ActionConfiguration;
128
117
  data: ActionData;
129
118
  focused?: boolean;
119
+ onPress?: () => void;
130
120
  };
131
121
 
132
122
  // ---------------------------------------------------------------------------
@@ -187,28 +177,32 @@ type ActionContainerProps = {
187
177
  configuration: BackgroundConfiguration;
188
178
  focused: boolean;
189
179
  children: React.ReactNode;
180
+ onPress?: () => void;
190
181
  };
191
182
 
192
183
  function ActionContainer({
193
184
  configuration,
194
185
  focused,
195
186
  children,
187
+ onPress,
196
188
  }: ActionContainerProps) {
197
189
  return (
198
- <View
199
- style={{
200
- backgroundColor: focused
201
- ? configuration.focusedColor
202
- : configuration.defaultColor,
190
+ <Pressable
191
+ onPress={onPress}
192
+ style={({ pressed }) => ({
193
+ backgroundColor:
194
+ pressed || focused
195
+ ? configuration.focusedColor
196
+ : configuration.defaultColor,
203
197
  borderRadius: configuration.cornerRadius,
204
198
  paddingTop: CONTAINER_SPEC.paddingTop,
205
199
  paddingRight: CONTAINER_SPEC.paddingRight,
206
200
  paddingBottom: CONTAINER_SPEC.paddingBottom,
207
201
  paddingLeft: CONTAINER_SPEC.paddingLeft,
208
- }}
202
+ })}
209
203
  >
210
204
  {children}
211
- </View>
205
+ </Pressable>
212
206
  );
213
207
  }
214
208
 
@@ -279,10 +273,15 @@ function ActionTrailingIcon({ configuration }: ActionTrailingIconProps) {
279
273
  }
280
274
 
281
275
  // ---------------------------------------------------------------------------
282
- // Item
276
+ // AudioPlayerAction
283
277
  // ---------------------------------------------------------------------------
284
278
 
285
- export function Item({ configuration, data, focused = false }: ItemProps) {
279
+ export function AudioPlayerAction({
280
+ configuration,
281
+ data,
282
+ focused = false,
283
+ onPress,
284
+ }: AudioPlayerActionProps) {
286
285
  const { background, title, trailingIcon } = configuration;
287
286
  const { title: label, leadingActionType, showTrailingChevron } = data;
288
287
 
@@ -290,7 +289,11 @@ export function Item({ configuration, data, focused = false }: ItemProps) {
290
289
  const showTrailing = shouldShowTrailingIcon(showTrailingChevron);
291
290
 
292
291
  return (
293
- <ActionContainer configuration={background} focused={focused}>
292
+ <ActionContainer
293
+ configuration={background}
294
+ focused={focused}
295
+ onPress={onPress}
296
+ >
294
297
  <View style={styles.row}>
295
298
  {showLeading ? (
296
299
  <>
@@ -309,60 +312,3 @@ export function Item({ configuration, data, focused = false }: ItemProps) {
309
312
  </ActionContainer>
310
313
  );
311
314
  }
312
-
313
- // ---------------------------------------------------------------------------
314
- // Demo
315
- // ---------------------------------------------------------------------------
316
-
317
- export default function App() {
318
- return (
319
- <View style={styles.demoScreen}>
320
- <Text style={styles.demoHeading}>Modal Action Building Block</Text>
321
-
322
- <Text style={styles.demoLabel}>
323
- Leading icon + text — Add To Queue (focused)
324
- </Text>
325
- <Item
326
- configuration={DEFAULT_ACTION_CONFIGURATION}
327
- data={{ title: "Add To Queue", leadingActionType: "addToQueue" }}
328
- focused
329
- />
330
-
331
- <Text style={styles.demoLabel}>
332
- Leading icon + text + trailing chevron — Add To Playlist
333
- </Text>
334
- <Item
335
- configuration={DEFAULT_ACTION_CONFIGURATION}
336
- data={{
337
- title: "Add To Playlist",
338
- leadingActionType: "addToPlaylist",
339
- showTrailingChevron: true,
340
- }}
341
- />
342
-
343
- <Text style={styles.demoLabel}>Text only — Go To Playlist</Text>
344
- <Item
345
- configuration={DEFAULT_ACTION_CONFIGURATION}
346
- data={{ title: "Go To Playlist" }}
347
- />
348
-
349
- <Text style={styles.demoLabel}>Leading icon + text — Favorite</Text>
350
- <Item
351
- configuration={DEFAULT_ACTION_CONFIGURATION}
352
- data={{ title: "Favorite", leadingActionType: "favorite" }}
353
- />
354
-
355
- <Text style={styles.demoLabel}>Leading icon + text — Share</Text>
356
- <Item
357
- configuration={DEFAULT_ACTION_CONFIGURATION}
358
- data={{ title: "Share", leadingActionType: "share" }}
359
- />
360
-
361
- <Text style={styles.demoLabel}>Text only — Go To Artist</Text>
362
- <Item
363
- configuration={DEFAULT_ACTION_CONFIGURATION}
364
- data={{ title: "Go To Artist" }}
365
- />
366
- </View>
367
- );
368
- }
@@ -9,7 +9,14 @@
9
9
  */
10
10
 
11
11
  import React from "react";
12
- import { Image, Platform, StyleSheet, Text, View } from "react-native";
12
+ import {
13
+ Image,
14
+ Platform,
15
+ Pressable,
16
+ StyleSheet,
17
+ Text,
18
+ View,
19
+ } from "react-native";
13
20
 
14
21
  const styles = StyleSheet.create({
15
22
  container: {
@@ -25,24 +32,6 @@ const styles = StyleSheet.create({
25
32
  title: {
26
33
  textAlign: "center",
27
34
  },
28
- demoScreen: {
29
- flex: 1,
30
- backgroundColor: "#1C1C1E",
31
- paddingTop: 64,
32
- paddingHorizontal: 24,
33
- gap: 12,
34
- },
35
- demoHeading: {
36
- color: "#FFFFFF",
37
- fontSize: 20,
38
- fontWeight: "600",
39
- marginBottom: 8,
40
- },
41
- demoLabel: {
42
- color: "#999999",
43
- fontSize: 13,
44
- marginTop: 8,
45
- },
46
35
  });
47
36
 
48
37
  // ---------------------------------------------------------------------------
@@ -148,11 +137,12 @@ export type ButtonData = {
148
137
  disabled?: boolean;
149
138
  };
150
139
 
151
- export type ItemProps = {
140
+ export type AudioPlayerButtonProps = {
152
141
  configuration: ButtonConfiguration;
153
142
  data: ButtonData;
154
143
  disabled?: boolean;
155
144
  focused?: boolean;
145
+ onPress?: () => void;
156
146
  };
157
147
 
158
148
  // ---------------------------------------------------------------------------
@@ -170,7 +160,7 @@ const ACTION_ICON_ASSETS: Record<ButtonActionType, string> = {
170
160
  confirm:
171
161
  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAJElEQVR42mNgGAWjYBSQCv4TwKMWDHELho/hNE/3o2AUDDcAAPv0QMAyy1CtAAAAAElFTkSuQmCC",
172
162
  cancel:
173
- "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAASElEQVR42mNgGAUjGvynkVoUTf+pqA6nxv8UqiHbEooNx2cQ1QzHZiDVDcdlCcOQsoCmQUTTSKZpMqV5RqNLUUHTwm4UDBMAALBLQ73LTvoyAAAAAElFTkSuQmCC",
163
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAASElEQVR42mNgGAWjGvynkVoUTf+pqA6nxv8UqiHbEooNx2cQ1QzHZiDVDcdlCcOQsoCmQUTTSKZpMqV5RqNLUUHTwm4UDBMAALBLQ73LTvoyAAAAAElFTkSuQmCC",
174
164
  };
175
165
 
176
166
  function getTextTransformStyle(
@@ -192,6 +182,7 @@ type ButtonContainerProps = {
192
182
  disabled: boolean;
193
183
  configuration: BackgroundConfiguration;
194
184
  children: React.ReactNode;
185
+ onPress?: () => void;
195
186
  };
196
187
 
197
188
  function ButtonContainer({
@@ -199,19 +190,22 @@ function ButtonContainer({
199
190
  disabled,
200
191
  configuration,
201
192
  children,
193
+ onPress,
202
194
  }: ButtonContainerProps) {
203
- const backgroundColor = disabled
195
+ const defaultBgColor = disabled
204
196
  ? configuration.inactiveColor
205
197
  : focused
206
198
  ? configuration.focusedColor
207
199
  : configuration.defaultColor;
208
200
 
209
201
  return (
210
- <View
211
- style={[
202
+ <Pressable
203
+ onPress={disabled ? undefined : onPress}
204
+ style={({ pressed }) => [
212
205
  styles.container,
213
206
  {
214
- backgroundColor,
207
+ backgroundColor:
208
+ pressed && !disabled ? configuration.focusedColor : defaultBgColor,
215
209
  borderRadius: configuration.cornerRadius,
216
210
  paddingTop: configuration.paddingTop,
217
211
  paddingRight: configuration.paddingRight,
@@ -221,7 +215,7 @@ function ButtonContainer({
221
215
  ]}
222
216
  >
223
217
  {children}
224
- </View>
218
+ </Pressable>
225
219
  );
226
220
  }
227
221
 
@@ -295,20 +289,32 @@ function ButtonLeadingIcon({
295
289
  }
296
290
 
297
291
  // ---------------------------------------------------------------------------
298
- // Item — single building block driven by configuration + data
292
+ // AudioPlayerButton — single building block driven by configuration + data
299
293
  // ---------------------------------------------------------------------------
300
294
 
301
- export function Item({
295
+ import { useModalBlocksStyle } from "../../ModalBlocksStyleContext";
296
+ import { mergeButtonConfiguration } from "../utils/mergeStyles";
297
+
298
+ export function AudioPlayerButton({
302
299
  configuration,
303
300
  data,
304
301
  disabled,
305
302
  focused = false,
306
- }: ItemProps) {
303
+ onPress,
304
+ }: AudioPlayerButtonProps) {
305
+ const modalBlocksStyle = useModalBlocksStyle();
306
+ const buttonBlock = modalBlocksStyle?.button;
307
+ const actionBlock = modalBlocksStyle?.action;
308
+
309
+ const effectiveConfig = React.useMemo(() => {
310
+ return mergeButtonConfiguration(configuration, buttonBlock, actionBlock);
311
+ }, [configuration, buttonBlock, actionBlock]);
312
+
307
313
  const {
308
- background: backgroundConfiguration,
309
- title: titleConfiguration,
314
+ background: effectiveBgConfig,
315
+ title: effectiveTitleConfig,
310
316
  icons: iconsConfiguration,
311
- } = configuration;
317
+ } = effectiveConfig;
312
318
 
313
319
  const { title } = data;
314
320
  const isDisabled = disabled ?? data.disabled ?? false;
@@ -320,7 +326,8 @@ export function Item({
320
326
  <ButtonContainer
321
327
  focused={focused}
322
328
  disabled={isDisabled}
323
- configuration={backgroundConfiguration}
329
+ configuration={effectiveBgConfig}
330
+ onPress={onPress}
324
331
  >
325
332
  <View style={styles.contentRow}>
326
333
  {showIcon ? (
@@ -329,14 +336,14 @@ export function Item({
329
336
  actionType={leadingIcon.actionType}
330
337
  configuration={iconsConfiguration}
331
338
  />
332
- <View style={{ width: backgroundConfiguration.horizontalGutter }} />
339
+ <View style={{ width: effectiveBgConfig.horizontalGutter }} />
333
340
  </>
334
341
  ) : null}
335
342
  <ButtonTitle
336
343
  title={title}
337
344
  focused={focused}
338
345
  disabled={isDisabled}
339
- configuration={titleConfiguration}
346
+ configuration={effectiveTitleConfig}
340
347
  />
341
348
  </View>
342
349
  </ButtonContainer>
@@ -386,39 +393,3 @@ export const VARIANT_LARGE_ICON: ButtonConfiguration = {
386
393
  },
387
394
  },
388
395
  };
389
-
390
- export default function App() {
391
- return (
392
- <View style={styles.demoScreen}>
393
- <Text style={styles.demoHeading}>Modal Button Building Block</Text>
394
-
395
- <Text style={styles.demoLabel}>Variant 1 — Text only (confirmation)</Text>
396
- <Item configuration={VARIANT_TEXT_ONLY} data={{ title: "Confirm" }} />
397
-
398
- <Text style={styles.demoLabel}>Variant 2 — Leading icon + text</Text>
399
- <Item
400
- configuration={VARIANT_WITH_ICON}
401
- data={{ title: "Add To Playlist" }}
402
- />
403
-
404
- <Text style={styles.demoLabel}>Inactive state</Text>
405
- <Item
406
- configuration={VARIANT_TEXT_ONLY}
407
- data={{ title: "Unavailable" }}
408
- disabled
409
- />
410
-
411
- <Text style={styles.demoLabel}>Custom title config — uppercase</Text>
412
- <Item
413
- configuration={VARIANT_UPPERCASE_TITLE}
414
- data={{ title: "Save Changes" }}
415
- />
416
-
417
- <Text style={styles.demoLabel}>Custom icons config — 32×32</Text>
418
- <Item
419
- configuration={VARIANT_LARGE_ICON}
420
- data={{ title: "Add To Queue" }}
421
- />
422
- </View>
423
- );
424
- }