@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.
Files changed (40) hide show
  1. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +4 -1
  2. package/Components/ModalComponent/ActionsBottomSheet/ActionButton.tsx +56 -0
  3. package/Components/ModalComponent/ActionsBottomSheet/__tests__/openActionsBottomSheet.test.ts +38 -0
  4. package/Components/ModalComponent/ActionsBottomSheet/boundActionButton.tsx +24 -0
  5. package/Components/ModalComponent/ActionsBottomSheet/index.ts +9 -0
  6. package/Components/ModalComponent/ActionsBottomSheet/openActionsBottomSheet.ts +61 -0
  7. package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +33 -87
  8. package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +57 -74
  9. package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +142 -107
  10. package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +653 -0
  11. package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +427 -159
  12. package/Components/ModalComponent/AudioPlayer/Components/NowPlayingHeaderSection.tsx +89 -0
  13. package/Components/ModalComponent/AudioPlayer/Components/__tests__/Item.test.tsx +66 -0
  14. package/Components/ModalComponent/AudioPlayer/Components/index.ts +8 -4
  15. package/Components/ModalComponent/AudioPlayer/utils/__tests__/mergeStyles.test.ts +230 -0
  16. package/Components/ModalComponent/AudioPlayer/utils/mergeStyles.ts +332 -0
  17. package/Components/ModalComponent/BottomSheetModalContent.tsx +379 -61
  18. package/Components/ModalComponent/Button/index.tsx +5 -3
  19. package/Components/ModalComponent/Header/index.tsx +20 -7
  20. package/Components/ModalComponent/Header/utils.ts +1 -1
  21. package/Components/ModalComponent/ModalBlocksStyleContext.tsx +10 -0
  22. package/Components/ModalComponent/SortableList.tsx +142 -0
  23. package/Components/ModalComponent/SortableList.web.tsx +102 -0
  24. package/Components/ModalComponent/TextInputContent.tsx +112 -0
  25. package/Components/ModalComponent/__tests__/BottomSheetModalContent.test.tsx +238 -0
  26. package/Components/ModalComponent/__tests__/TextInputContent.test.tsx +156 -0
  27. package/Components/ModalComponent/__tests__/showTextInput.test.ts +95 -0
  28. package/Components/ModalComponent/index.tsx +11 -0
  29. package/Components/ModalComponent/presets/__tests__/getCell.test.ts +90 -0
  30. package/Components/ModalComponent/presets/dynamicCollectionCell.tsx +78 -0
  31. package/Components/ModalComponent/presets/index.ts +27 -0
  32. package/Components/ModalComponent/presets/selectableCell.tsx +28 -0
  33. package/Components/ModalComponent/presets/standardCell.tsx +41 -0
  34. package/Components/ModalComponent/presets/types.ts +35 -0
  35. package/Components/ModalComponent/showTextInput.ts +43 -0
  36. package/Components/ModalComponent/utils.ts +82 -21
  37. package/Components/VideoLive/LiveImageManager.ts +8 -2
  38. package/Hooks/useEntryActionsExpander.ts +63 -0
  39. package/package.json +6 -5
  40. /package/Decorators/ZappPipesDataConnector/__tests__/{Hero.js → Hero.tsx} +0 -0
@@ -9,7 +9,8 @@
9
9
  */
10
10
 
11
11
  import React, { useCallback, useState } from "react";
12
- import { Image, Platform, StyleSheet, Text, View } from "react-native";
12
+ import { Platform, Pressable, StyleSheet, Text, View } from "react-native";
13
+ import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
13
14
 
14
15
  const styles = StyleSheet.create({
15
16
  row: {
@@ -45,29 +46,6 @@ const styles = StyleSheet.create({
45
46
  alignItems: "center",
46
47
  justifyContent: "center",
47
48
  },
48
- demoScreen: {
49
- flex: 1,
50
- backgroundColor: "#1C1C1E",
51
- paddingTop: 64,
52
- paddingHorizontal: 0,
53
- gap: 24,
54
- },
55
- demoBlock: {
56
- gap: 8,
57
- paddingHorizontal: 0,
58
- },
59
- demoHeading: {
60
- color: "#FFFFFF",
61
- fontSize: 20,
62
- fontWeight: "600",
63
- marginBottom: 8,
64
- paddingHorizontal: 24,
65
- },
66
- demoLabel: {
67
- color: "#999999",
68
- fontSize: 13,
69
- paddingHorizontal: 24,
70
- },
71
49
  });
72
50
 
73
51
  // ---------------------------------------------------------------------------
@@ -123,6 +101,7 @@ export type ActionButtonsStyleConfiguration = {
123
101
  };
124
102
 
125
103
  export type HeaderConfiguration = {
104
+ paddingTop?: number;
126
105
  variant: HeaderVariant;
127
106
  title: TitleConfiguration;
128
107
  closeButton: CloseButtonConfiguration;
@@ -168,12 +147,17 @@ export type HeaderData = {
168
147
  title: string;
169
148
  };
170
149
 
171
- export type ItemProps = {
150
+ export type AudioPlayerHeaderProps = {
172
151
  configuration: HeaderConfiguration;
173
152
  data: HeaderData;
174
153
  focusedCloseButton?: boolean;
175
154
  focusedLeadingAction?: boolean;
176
155
  focusedTrailingAction?: boolean;
156
+ onClose?: () => void;
157
+ onBack?: () => void;
158
+ onCancel?: () => void;
159
+ onDone?: () => void;
160
+ onClear?: () => void;
177
161
  };
178
162
 
179
163
  // ---------------------------------------------------------------------------
@@ -202,9 +186,9 @@ type ActionButtonsBehaviorSpec = {
202
186
  const CONTAINER_SPEC: Record<HeaderVariant, ContainerSpec> = {
203
187
  singleLine: {
204
188
  horizontalGutter: 16,
205
- paddingTop: 0,
206
- paddingRight: 14,
207
- paddingBottom: 8,
189
+ paddingTop: 24,
190
+ paddingRight: 20,
191
+ paddingBottom: 12,
208
192
  paddingLeft: 20,
209
193
  },
210
194
  headerWithActions: {
@@ -256,9 +240,6 @@ const ACTION_BUTTONS_BEHAVIOR: Record<
256
240
  },
257
241
  };
258
242
 
259
- const DEFAULT_CLOSE_BUTTON_ASSET =
260
- "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAAl0lEQVR42u2YQQ7AIAgE/f+naQ899dDYyiLT7DyAnRijwBjGGLNEnKCy4qJCNlVYKZ2aETeUshLhTGlZbUVh5UGkB8hlM4PKZDMCy2VXgrfJfhHYLvtGpI3sjFA72SextrKz0m1bUYwsTvhX97f9C4F8g5G/HLKPQHZqyF4YOW0g5znkxCytjV6koFZVqGVg5Yc0jDFmiQNENiwNUMoCZAAAAABJRU5ErkJggg==";
261
-
262
243
  const CLOSE_BUTTON_SPEC = {
263
244
  width: 44,
264
245
  height: 44,
@@ -298,19 +279,34 @@ function shouldShowActionSlot(slot: ActionSlotSpec, sectionEnabled: boolean) {
298
279
 
299
280
  type HeaderContainerProps = {
300
281
  variant: HeaderVariant;
282
+ configuration: HeaderConfiguration;
301
283
  children: React.ReactNode;
302
284
  };
303
285
 
304
- function HeaderContainer({ variant, children }: HeaderContainerProps) {
286
+ const TRANSPARENT = "transparent";
287
+
288
+ function HeaderContainer({
289
+ variant,
290
+ configuration,
291
+ children,
292
+ }: HeaderContainerProps) {
305
293
  const container = CONTAINER_SPEC[variant];
306
294
 
295
+ const paddingTop =
296
+ configuration.paddingTop !== undefined
297
+ ? configuration.paddingTop
298
+ : container.paddingTop;
299
+
300
+ const backgroundColor = (configuration as any).backgroundColor || TRANSPARENT;
301
+
307
302
  return (
308
303
  <View
309
304
  style={{
310
- paddingTop: container.paddingTop,
305
+ paddingTop: paddingTop,
311
306
  paddingRight: container.paddingRight,
312
307
  paddingBottom: container.paddingBottom,
313
308
  paddingLeft: container.paddingLeft,
309
+ backgroundColor: backgroundColor,
314
310
  }}
315
311
  >
316
312
  {children}
@@ -325,17 +321,18 @@ type HeaderTitleProps = {
325
321
  };
326
322
 
327
323
  function HeaderTitle({ title, configuration, centered }: HeaderTitleProps) {
328
- const letterSpacing =
329
- Platform.OS === "ios"
330
- ? configuration.iosLetterSpacing
331
- : configuration.androidLetterSpacing;
324
+ const { fontColor, fontSize } = configuration;
325
+
326
+ const letterSpacing = isApplePlatform()
327
+ ? configuration.iosLetterSpacing
328
+ : configuration.androidLetterSpacing;
332
329
 
333
330
  return (
334
331
  <Text
335
332
  style={{
336
333
  flex: centered ? undefined : 1,
337
- color: configuration.fontColor,
338
- fontSize: configuration.fontSize,
334
+ color: fontColor,
335
+ fontSize: fontSize,
339
336
  lineHeight: configuration.lineHeight,
340
337
  letterSpacing,
341
338
  fontFamily: Platform.select({
@@ -356,21 +353,80 @@ function HeaderTitle({ title, configuration, centered }: HeaderTitleProps) {
356
353
  type HeaderCloseButtonProps = {
357
354
  configuration: CloseButtonConfiguration;
358
355
  focused?: boolean;
356
+ onPress?: () => void;
359
357
  };
360
358
 
361
359
  function HeaderCloseButton({
362
360
  configuration,
363
361
  focused = false,
362
+ onPress,
364
363
  }: HeaderCloseButtonProps) {
365
364
  if (!configuration.enabled) {
366
365
  return null;
367
366
  }
368
367
 
369
- const asset = configuration.asset ?? DEFAULT_CLOSE_BUTTON_ASSET;
368
+ const buttonSize = 32;
370
369
 
371
370
  return (
372
- <View
373
- style={[
371
+ <Pressable
372
+ onPress={onPress}
373
+ style={({ pressed }) => [
374
+ styles.closeButton,
375
+ {
376
+ width: buttonSize,
377
+ height: buttonSize,
378
+ borderRadius: buttonSize / 2,
379
+ borderWidth: 1.5,
380
+ borderColor: "rgba(255, 255, 255, 0.4)",
381
+ opacity: pressed || focused ? 0.7 : 1,
382
+ justifyContent: "center",
383
+ alignItems: "center",
384
+ },
385
+ ]}
386
+ >
387
+ <View
388
+ style={{
389
+ width: 14,
390
+ height: 14,
391
+ justifyContent: "center",
392
+ alignItems: "center",
393
+ }}
394
+ >
395
+ <View
396
+ style={{
397
+ position: "absolute",
398
+ width: 14,
399
+ height: 1.5,
400
+ backgroundColor: "#FFFFFF",
401
+ transform: [{ rotate: "45deg" }],
402
+ borderRadius: 1,
403
+ }}
404
+ />
405
+ <View
406
+ style={{
407
+ position: "absolute",
408
+ width: 14,
409
+ height: 1.5,
410
+ backgroundColor: "#FFFFFF",
411
+ transform: [{ rotate: "-45deg" }],
412
+ borderRadius: 1,
413
+ }}
414
+ />
415
+ </View>
416
+ </Pressable>
417
+ );
418
+ }
419
+
420
+ type HeaderBackButtonProps = {
421
+ focused?: boolean;
422
+ onPress?: () => void;
423
+ };
424
+
425
+ function HeaderBackButton({ focused = false, onPress }: HeaderBackButtonProps) {
426
+ return (
427
+ <Pressable
428
+ onPress={onPress}
429
+ style={({ pressed }) => [
374
430
  styles.closeButton,
375
431
  {
376
432
  width: CLOSE_BUTTON_SPEC.width,
@@ -382,19 +438,14 @@ function HeaderCloseButton({
382
438
  borderRadius: CLOSE_BUTTON_SPEC.width / 2,
383
439
  borderWidth: 1,
384
440
  borderColor: "#FFFFFF",
385
- opacity: focused ? 0.7 : 1,
441
+ opacity: pressed || focused ? 0.7 : 1,
386
442
  },
387
443
  ]}
388
444
  >
389
- <Image
390
- source={{ uri: asset }}
391
- style={{
392
- width: CLOSE_BUTTON_SPEC.width * 0.55,
393
- height: CLOSE_BUTTON_SPEC.height * 0.55,
394
- }}
395
- resizeMode="contain"
396
- />
397
- </View>
445
+ <Text style={{ color: "#FFFFFF", fontSize: 20, fontWeight: "bold" }}>
446
+ ‹
447
+ </Text>
448
+ </Pressable>
398
449
  );
399
450
  }
400
451
 
@@ -402,25 +453,29 @@ type HeaderActionButtonProps = {
402
453
  actionType: HeaderActionType;
403
454
  configuration: ActionButtonsStyleConfiguration;
404
455
  focused?: boolean;
456
+ onPress?: () => void;
405
457
  };
406
458
 
407
459
  function HeaderActionButton({
408
460
  actionType,
409
461
  configuration,
410
462
  focused = false,
463
+ onPress,
411
464
  }: HeaderActionButtonProps) {
412
465
  return (
413
- <View
414
- style={{
415
- backgroundColor: focused
416
- ? configuration.focusedBackgroundColor
417
- : configuration.defaultBackgroundColor,
466
+ <Pressable
467
+ onPress={onPress}
468
+ style={({ pressed }) => ({
469
+ backgroundColor:
470
+ pressed || focused
471
+ ? configuration.focusedBackgroundColor
472
+ : configuration.defaultBackgroundColor,
418
473
  borderRadius: ACTION_BUTTON_LAYOUT_SPEC.cornerRadius,
419
474
  paddingTop: ACTION_BUTTON_LAYOUT_SPEC.paddingTop,
420
475
  paddingRight: ACTION_BUTTON_LAYOUT_SPEC.paddingRight,
421
476
  paddingBottom: ACTION_BUTTON_LAYOUT_SPEC.paddingBottom,
422
477
  paddingLeft: ACTION_BUTTON_LAYOUT_SPEC.paddingLeft,
423
- }}
478
+ })}
424
479
  >
425
480
  <Text
426
481
  style={{
@@ -444,7 +499,7 @@ function HeaderActionButton({
444
499
  >
445
500
  {ACTION_LABELS[actionType]}
446
501
  </Text>
447
- </View>
502
+ </Pressable>
448
503
  );
449
504
  }
450
505
 
@@ -536,17 +591,32 @@ function CenterAlignedHeaderLayout({
536
591
  }
537
592
 
538
593
  // ---------------------------------------------------------------------------
539
- // Item
594
+ // AudioPlayerHeader
540
595
  // ---------------------------------------------------------------------------
541
596
 
542
- export function Item({
597
+ import { useModalBlocksStyle } from "../../ModalBlocksStyleContext";
598
+ import { mergeHeaderConfiguration } from "../utils/mergeStyles";
599
+
600
+ export function AudioPlayerHeader({
543
601
  configuration,
544
602
  data,
545
603
  focusedCloseButton = false,
546
604
  focusedLeadingAction = false,
547
605
  focusedTrailingAction = false,
548
- }: ItemProps) {
549
- const { variant, title, closeButton, actionButtons } = configuration;
606
+ onClose,
607
+ onBack,
608
+ onCancel,
609
+ onDone,
610
+ onClear,
611
+ }: AudioPlayerHeaderProps) {
612
+ const modalBlocksStyle = useModalBlocksStyle();
613
+ const headerBlock = modalBlocksStyle?.header;
614
+
615
+ const effectiveConfig = React.useMemo(() => {
616
+ return mergeHeaderConfiguration(configuration, headerBlock);
617
+ }, [configuration, headerBlock]);
618
+
619
+ const { variant, title, closeButton, actionButtons } = effectiveConfig;
550
620
  const { title: titleText } = data;
551
621
 
552
622
  const container = CONTAINER_SPEC[variant];
@@ -568,7 +638,10 @@ export function Item({
568
638
  actionType={behavior.leading.actionType}
569
639
  configuration={actionButtons}
570
640
  focused={focusedLeadingAction}
641
+ onPress={onCancel}
571
642
  />
643
+ ) : onBack ? (
644
+ <HeaderBackButton focused={focusedCloseButton} onPress={onBack} />
572
645
  ) : null;
573
646
 
574
647
  const trailingContent = showTrailingAction ? (
@@ -576,17 +649,19 @@ export function Item({
576
649
  actionType={behavior.trailing.actionType}
577
650
  configuration={actionButtons}
578
651
  focused={focusedTrailingAction}
652
+ onPress={behavior.trailing.actionType === "done" ? onDone : onClear}
579
653
  />
580
654
  ) : closeButton.enabled && !isCenterAligned ? (
581
655
  <HeaderCloseButton
582
656
  configuration={closeButton}
583
657
  focused={focusedCloseButton}
658
+ onPress={onClose}
584
659
  />
585
660
  ) : null;
586
661
 
587
662
  if (isCenterAligned) {
588
663
  return (
589
- <HeaderContainer variant={variant}>
664
+ <HeaderContainer variant={variant} configuration={configuration}>
590
665
  <CenterAlignedHeaderLayout
591
666
  horizontalGutter={container.horizontalGutter}
592
667
  title={title}
@@ -599,7 +674,7 @@ export function Item({
599
674
  }
600
675
 
601
676
  return (
602
- <HeaderContainer variant={variant}>
677
+ <HeaderContainer variant={variant} configuration={configuration}>
603
678
  <View style={styles.row}>
604
679
  {leadingContent ? (
605
680
  <>
@@ -647,6 +722,7 @@ export const VARIANT_HEADER_WITH_ACTIONS: HeaderConfiguration = {
647
722
  },
648
723
  closeButton: { enabled: false },
649
724
  actionButtons: DEFAULT_ACTION_BUTTONS_STYLE_CONFIGURATION,
725
+ paddingTop: 16,
650
726
  };
651
727
 
652
728
  /** Variant 2 — single side action (layout rule demo) */
@@ -665,6 +741,7 @@ export const VARIANT_HEADER_WITH_CANCEL_ONLY: HeaderConfiguration = {
665
741
  },
666
742
  closeButton: { enabled: false },
667
743
  actionButtons: DEFAULT_ACTION_BUTTONS_STYLE_CONFIGURATION,
744
+ paddingTop: 16,
668
745
  };
669
746
 
670
747
  /** Variant 3 — Section Header */
@@ -684,45 +761,3 @@ export const VARIANT_SECTION_HEADER: HeaderConfiguration = {
684
761
  closeButton: { enabled: false },
685
762
  actionButtons: DEFAULT_ACTION_BUTTONS_STYLE_CONFIGURATION,
686
763
  };
687
-
688
- export default function App() {
689
- return (
690
- <View style={styles.demoScreen}>
691
- <Text style={styles.demoHeading}>Modal Header Building Block</Text>
692
-
693
- <View style={styles.demoBlock}>
694
- <Text style={styles.demoLabel}>Single Line Header</Text>
695
- <Item
696
- configuration={VARIANT_SINGLE_LINE_HEADER}
697
- data={{ title: "Playback Speed" }}
698
- />
699
- </View>
700
-
701
- <View style={styles.demoBlock}>
702
- <Text style={styles.demoLabel}>Header With Actions</Text>
703
- <Item
704
- configuration={VARIANT_HEADER_WITH_ACTIONS}
705
- data={{ title: "Playback Speed" }}
706
- />
707
- </View>
708
-
709
- <View style={styles.demoBlock}>
710
- <Text style={styles.demoLabel}>
711
- Header With Actions — single side action
712
- </Text>
713
- <Item
714
- configuration={VARIANT_HEADER_WITH_CANCEL_ONLY}
715
- data={{ title: "Playback Speed" }}
716
- />
717
- </View>
718
-
719
- <View style={styles.demoBlock}>
720
- <Text style={styles.demoLabel}>Section Header</Text>
721
- <Item
722
- configuration={VARIANT_SECTION_HEADER}
723
- data={{ title: "Next in Queue" }}
724
- />
725
- </View>
726
- </View>
727
- );
728
- }