@applicaster/zapp-react-native-ui-components 15.1.6-alpha.2015591222 → 15.1.6

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 (34) hide show
  1. package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +69 -33
  2. package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +47 -25
  3. package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +39 -122
  4. package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +131 -299
  5. package/Components/ModalComponent/AudioPlayer/Components/index.ts +4 -8
  6. package/Components/ModalComponent/BottomSheetModalContent.tsx +55 -290
  7. package/Components/ModalComponent/Button/index.tsx +3 -5
  8. package/Components/ModalComponent/Header/utils.ts +1 -1
  9. package/Components/ModalComponent/index.tsx +0 -11
  10. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +13 -82
  11. package/Components/OfflineHandler/__tests__/index.test.tsx +100 -35
  12. package/Components/OfflineHandler/hooks.ts +123 -0
  13. package/Components/OfflineHandler/index.tsx +51 -73
  14. package/Components/OfflineHandler/utils/index.ts +1 -13
  15. package/package.json +5 -6
  16. package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +0 -671
  17. package/Components/ModalComponent/AudioPlayer/Components/NowPlayingHeaderSection.tsx +0 -86
  18. package/Components/ModalComponent/SortableList.tsx +0 -142
  19. package/Components/ModalComponent/TextInputContent.tsx +0 -100
  20. package/Components/ModalComponent/__tests__/BottomSheetModalContent.test.tsx +0 -183
  21. package/Components/ModalComponent/__tests__/TextInputContent.test.tsx +0 -128
  22. package/Components/ModalComponent/__tests__/showTextInput.test.ts +0 -95
  23. package/Components/ModalComponent/presets/__tests__/getCell.test.ts +0 -66
  24. package/Components/ModalComponent/presets/dynamicCollectionCell.tsx +0 -74
  25. package/Components/ModalComponent/presets/index.ts +0 -27
  26. package/Components/ModalComponent/presets/selectableCell.tsx +0 -27
  27. package/Components/ModalComponent/presets/standardCell.tsx +0 -41
  28. package/Components/ModalComponent/presets/types.ts +0 -35
  29. package/Components/ModalComponent/showTextInput.ts +0 -43
  30. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +0 -112
  31. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +0 -107
  32. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +0 -153
  33. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -67
  34. package/Components/OfflineHandler/NotificationView/utils.ts +0 -34
@@ -1,46 +1,17 @@
1
1
  import React, { useCallback, useEffect, useMemo, useRef } from "react";
2
- import {
3
- ActivityIndicator,
4
- ScrollView,
5
- StyleSheet,
6
- View,
7
- Text,
8
- } from "react-native";
2
+ import { View, ScrollView } from "react-native";
9
3
  import { Button } from "./Button";
10
4
  import { ItemIconProps } from "./Button/ItemIcon";
11
5
  import { ItemProps } from "./Button/Item";
12
6
  import { ItemLabelProps } from "./Button/ItemLabel";
13
7
  import { getItemIconProps, getItemLabelProps, getItemProps } from "./utils";
14
8
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
15
- import {
16
- ContentViewModel,
17
- useBottomSheetContent,
18
- } from "@applicaster/zapp-react-native-utils/modalState";
19
- import { getCell } from "./presets";
20
9
  import type { PluginConfiguration } from "./";
10
+
21
11
  import { ModalHeader as DefaultModalHeader } from "./Header";
22
12
  import { useSafeAreaInsets } from "react-native-safe-area-context";
23
- import { SortableList } from "./SortableList";
24
- import {
25
- NowPlayingHeaderSection,
26
- AudioPlayerButton,
27
- VARIANT_WITH_ICON,
28
- } from "./AudioPlayer/Components";
29
13
  import { BottomSheetDragArea } from "./BottomSheetDragArea";
30
14
 
31
- const styles = StyleSheet.create({
32
- centered: {
33
- justifyContent: "center",
34
- alignItems: "center",
35
- padding: 16,
36
- },
37
- errorText: {
38
- color: "#ff453a",
39
- fontSize: 14,
40
- textAlign: "center",
41
- },
42
- });
43
-
44
15
  type ModalComponentProps = {
45
16
  items: any[];
46
17
  current_selection?: any;
@@ -52,6 +23,12 @@ type ModalComponentProps = {
52
23
  maxHeight?: number;
53
24
  dismiss: () => void;
54
25
  headerComponent?: React.ComponentType;
26
+
27
+ scrollViewContent?: {
28
+ renderItem: (item: any, index: number) => React.ReactNode;
29
+ items: any[];
30
+ } | null;
31
+
55
32
  buttonComponent?: React.ComponentType;
56
33
  iconProps?: ItemIconProps | ((theme: PluginConfiguration) => ItemIconProps);
57
34
  itemProps?:
@@ -60,17 +37,13 @@ type ModalComponentProps = {
60
37
  labelProps?:
61
38
  | ItemLabelProps
62
39
  | ((theme: PluginConfiguration, width: number) => ItemLabelProps);
63
- getSelectedItemIcon?: (
40
+ getSelectedItemIcon: (
64
41
  theme: PluginConfiguration
65
42
  ) => ItemIconProps["asset"] | null;
66
- getDefaultItemIcon?: (
43
+ getDefaultItemIcon: (
67
44
  theme: PluginConfiguration
68
45
  ) => ItemIconProps["asset"] | null;
69
46
  iconPlacement?: "left" | "right";
70
- viewModel?: ContentViewModel;
71
- /** Optional body that replaces the items list (header stays DefaultModalHeader). */
72
- contentComponent?: React.ComponentType<any>;
73
- contentComponentProps?: Record<string, any>;
74
47
  };
75
48
 
76
49
  export function BottomSheetModalContent(props: ModalComponentProps) {
@@ -82,16 +55,15 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
82
55
  dismiss,
83
56
  summary,
84
57
  title,
85
- headerComponent,
86
- viewModel = null,
58
+ headerComponent = DefaultModalHeader,
59
+ scrollViewContent = null,
60
+
87
61
  buttonComponent: ButtonComponent = Button,
88
62
  getSelectedItemIcon = ({
89
63
  modal_bottom_sheet_item_selected_icon,
90
64
  }: BaseThemePropertiesMobile) => modal_bottom_sheet_item_selected_icon,
91
65
  getDefaultItemIcon = () => null,
92
66
  iconPlacement,
93
- contentComponent: ContentComponent,
94
- contentComponentProps = {},
95
67
  } = props;
96
68
 
97
69
  const route = useRef(currentRoute);
@@ -99,29 +71,7 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
99
71
  const paddingTop = Number(theme.modal_bottom_sheet_padding_top);
100
72
  const paddingBottom = Number(theme.modal_bottom_sheet_padding_bottom);
101
73
 
102
- const {
103
- items: fetchedItems,
104
- showCentralLoading,
105
- error,
106
- handleItemPress,
107
- role,
108
- behavior,
109
- editableCollection,
110
- } = useBottomSheetContent({
111
- onPress,
112
- viewModel,
113
- });
114
-
115
- const itemsToRender = viewModel ? fetchedItems : items;
116
- const operations = editableCollection?.operations || [];
117
- const isSortable = operations.includes("reorder");
118
-
119
- const cell = getCell(
120
- viewModel ? role : undefined,
121
- viewModel ? behavior : undefined
122
- );
123
-
124
- const Header = headerComponent ?? DefaultModalHeader;
74
+ const Header = headerComponent;
125
75
 
126
76
  useEffect(() => {
127
77
  if (currentRoute !== route.current) {
@@ -141,7 +91,7 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
141
91
  return getItemLabelProps(theme, props.width, props.labelProps);
142
92
  }, [theme, props.width, props.labelProps]);
143
93
 
144
- const handleStaticPress = useCallback(
94
+ const handlePress = useCallback(
145
95
  (item: any) => {
146
96
  onPress(item);
147
97
  dismiss();
@@ -149,243 +99,58 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
149
99
  [onPress, dismiss]
150
100
  );
151
101
 
152
- const onItemPress = viewModel ? handleItemPress : handleStaticPress;
153
-
154
- const handleDragEnd = useCallback(
155
- (params: any) => {
156
- const from = params?.fromIndex ?? params?.from;
157
- const to = params?.toIndex ?? params?.to;
158
-
159
- const reorderedItemIds = Array.isArray(params?.data)
160
- ? params.data
161
- .filter((item: any) => !item?.isHeader)
162
- .map((item: any) => item?.id)
163
- .filter(Boolean)
164
- : undefined;
165
-
166
- console.log("[BottomSheetModalContent] handleDragEnd:", {
167
- from,
168
- to,
169
- reorderedItemIds,
170
- hasEditableCollection: !!editableCollection,
171
- hasMove: !!editableCollection?.move,
172
- });
173
-
174
- if (
175
- (reorderedItemIds?.length ||
176
- (typeof from === "number" &&
177
- typeof to === "number" &&
178
- from !== to)) &&
179
- editableCollection?.move
180
- ) {
181
- editableCollection.move(reorderedItemIds || []);
182
- }
183
- },
184
- [editableCollection]
185
- );
186
-
187
- const renderContext = useMemo(
188
- () => ({
189
- theme,
190
- ButtonComponent,
191
- current_selection,
192
- iconBaseProps,
193
- itemBaseProps,
194
- labelBaseProps,
195
- getSelectedItemIcon,
196
- getDefaultItemIcon,
197
- iconPlacement,
198
- editableCollection,
199
- behavior,
200
- }),
201
- [
202
- theme,
203
- ButtonComponent,
204
- current_selection,
205
- iconBaseProps,
206
- itemBaseProps,
207
- labelBaseProps,
208
- getSelectedItemIcon,
209
- getDefaultItemIcon,
210
- iconPlacement,
211
- editableCollection,
212
- behavior,
213
- ]
214
- );
215
-
216
102
  const bottomInset = useSafeAreaInsets().bottom;
217
103
 
218
- const hasNowPlaying = operations.includes("nowPlaying");
219
- const hasClearAll = operations.includes("clearAll");
220
- const hasAdd = operations.includes("add");
221
-
222
- const handleDeleteCollection = useCallback(() => {
223
- editableCollection?.deleteCollection?.();
224
- }, [editableCollection]);
225
-
226
- const handleCreatePlaylist = useCallback(() => {
227
- editableCollection?.add?.({ title: "Create New Playlist" });
228
- }, [editableCollection]);
229
-
230
- const headers = useMemo(() => {
231
- const list: Array<{ index: number; component: () => React.ReactElement }> =
232
- [];
233
-
234
- if (hasNowPlaying) {
235
- list.push({
236
- index: list.length,
237
- component: () => (
238
- <NowPlayingHeaderSection
239
- onClear={hasClearAll ? handleDeleteCollection : undefined}
240
- />
241
- ),
242
- });
243
- }
244
-
245
- if (hasAdd) {
246
- list.push({
247
- index: list.length,
248
- component: () => (
249
- <View
250
- style={{ paddingHorizontal: 20, paddingTop: 8, paddingBottom: 12 }}
251
- >
252
- <AudioPlayerButton
253
- configuration={VARIANT_WITH_ICON}
254
- data={{ title: "Create New Playlist" }}
255
- onPress={handleCreatePlaylist}
256
- />
257
- </View>
258
- ),
259
- });
260
- }
261
-
262
- return list.length > 0 ? list : undefined;
263
- }, [
264
- hasNowPlaying,
265
- hasClearAll,
266
- handleDeleteCollection,
267
- hasAdd,
268
- handleCreatePlaylist,
269
- ]);
270
-
271
- const renderBody = () => {
272
- if (ContentComponent) {
273
- return (
274
- <ScrollView
275
- contentContainerStyle={{
276
- paddingBottom: paddingBottom + bottomInset,
277
- }}
278
- >
279
- <ContentComponent
280
- {...contentComponentProps}
104
+ return (
105
+ <View
106
+ style={{
107
+ maxHeight: props.maxHeight,
108
+ paddingTop: paddingTop,
109
+ }}
110
+ >
111
+ {Header ? (
112
+ <BottomSheetDragArea>
113
+ <Header
281
114
  dismiss={dismiss}
282
- width={props.width}
283
- maxHeight={props.maxHeight}
115
+ configuration={theme}
116
+ summary={summary}
117
+ title={title}
284
118
  />
285
- </ScrollView>
286
- );
287
- }
288
-
289
- if (showCentralLoading) {
290
- return (
291
- <View
292
- style={[
293
- styles.centered,
294
- { backgroundColor: theme.modal_bottom_sheet_background_color },
295
- ]}
296
- >
297
- <ActivityIndicator color="#aaaaaa" />
298
- </View>
299
- );
300
- }
301
-
302
- if (error) {
303
- return (
304
- <View style={styles.centered}>
305
- <Text style={styles.errorText}>
306
- {typeof error === "string" ? error : error.message}
307
- </Text>
308
- </View>
309
- );
310
- }
311
-
312
- if (isSortable) {
313
- return (
314
- <SortableList
315
- sortableData={itemsToRender}
316
- headers={headers}
317
- scrollViewStyle={{
318
- flexShrink: 1,
319
- }}
320
- contentContainerStyle={{
321
- paddingBottom: paddingBottom + bottomInset,
322
- }}
323
- onDragEnd={handleDragEnd}
324
- renderItem={({ item, index, renderHandle }) =>
325
- cell.renderItem({
326
- item,
327
- index,
328
- onPress: onItemPress,
329
- context: renderContext,
330
- renderHandle,
331
- })
332
- }
333
- />
334
- );
335
- }
336
-
337
- return (
119
+ </BottomSheetDragArea>
120
+ ) : null}
338
121
  <ScrollView
339
122
  overScrollMode="never"
340
123
  bounces={false}
124
+ showsVerticalScrollIndicator={false}
341
125
  contentContainerStyle={{
342
126
  paddingBottom: paddingBottom + bottomInset,
343
127
  }}
344
128
  >
345
- {hasNowPlaying ? (
346
- <NowPlayingHeaderSection
347
- onClear={hasClearAll ? handleDeleteCollection : undefined}
348
- />
349
- ) : null}
350
- {hasAdd ? (
351
- <View
352
- style={{ paddingHorizontal: 20, paddingTop: 8, paddingBottom: 12 }}
353
- >
354
- <AudioPlayerButton
355
- configuration={VARIANT_WITH_ICON}
356
- data={{ title: "Create New Playlist" }}
357
- onPress={handleCreatePlaylist}
358
- />
359
- </View>
360
- ) : null}
361
- {(itemsToRender || []).map((item, index) =>
362
- cell.renderItem({
363
- item,
364
- index,
365
- onPress: onItemPress,
366
- context: renderContext,
367
- })
368
- )}
129
+ {scrollViewContent
130
+ ? scrollViewContent.items.map((item, index) =>
131
+ scrollViewContent.renderItem(item, index)
132
+ )
133
+ : null}
134
+ {!scrollViewContent &&
135
+ items.map((item, index) =>
136
+ item ? (
137
+ <ButtonComponent
138
+ key={index}
139
+ configuration={theme}
140
+ selectedItem={current_selection}
141
+ item={item}
142
+ onPress={handlePress}
143
+ label={theme[item?.label] ?? item?.label}
144
+ iconBaseProps={iconBaseProps}
145
+ itemBaseProps={itemBaseProps}
146
+ labelBaseProps={labelBaseProps}
147
+ selectedItemIcon={getSelectedItemIcon(theme)}
148
+ defaultItemIcon={getDefaultItemIcon(theme)}
149
+ iconPlacement={iconPlacement}
150
+ />
151
+ ) : null
152
+ )}
369
153
  </ScrollView>
370
- );
371
- };
372
-
373
- return (
374
- <View
375
- style={{
376
- maxHeight: props.maxHeight,
377
- paddingTop: paddingTop,
378
- }}
379
- >
380
- <BottomSheetDragArea>
381
- <Header
382
- dismiss={dismiss}
383
- configuration={theme}
384
- summary={summary}
385
- title={title}
386
- />
387
- </BottomSheetDragArea>
388
- {renderBody()}
389
154
  </View>
390
155
  );
391
156
  }
@@ -43,13 +43,11 @@ export function Button({
43
43
  }: ButtonProps) {
44
44
  const [focused, setFocused] = useState(false);
45
45
 
46
- const selected = selectedItem && item?.value === selectedItem?.value;
46
+ const selected = selectedItem && item.value === selectedItem?.value;
47
47
 
48
48
  const itemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
49
- () =>
50
- (item ? (configuration[item.asset] ?? item.asset) : undefined) ??
51
- defaultItemIcon,
52
- [item?.asset, defaultItemIcon]
49
+ () => configuration[item.asset] ?? item.asset ?? defaultItemIcon,
50
+ [item.asset, defaultItemIcon]
53
51
  );
54
52
 
55
53
  const selectedItemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
@@ -18,7 +18,7 @@ export function getCloseButtonProps(config: PluginConfiguration) {
18
18
  return {
19
19
  asset: modal_bottom_sheet_close_asset,
20
20
  assetFocused: modal_bottom_sheet_close_focus_asset,
21
- enabled: modal_bottom_sheet_close_switch !== false,
21
+ enabled: modal_bottom_sheet_close_switch,
22
22
  width: modal_bottom_sheet_close_width,
23
23
  height: modal_bottom_sheet_close_height,
24
24
  marginTop: modal_bottom_sheet_close_margin_top,
@@ -1,18 +1,7 @@
1
1
  import React, { useCallback, useState } from "react";
2
- import { actionExecutor } from "@applicaster/zapp-react-native-utils/actionsExecutor/ActionExecutor";
3
2
 
4
3
  import { BasicMeasurementsPortal as MeasurementsPortal } from "@applicaster/zapp-react-native-ui-components/Components/MeasurmentsPortal";
5
4
  import { BottomSheetModalContent } from "./BottomSheetModalContent";
6
- import { showTextInputAction } from "./showTextInput";
7
-
8
- actionExecutor.registerAction("showTextInput", showTextInputAction);
9
-
10
- export { SortableList, type SortableListProps } from "./SortableList";
11
-
12
- export {
13
- TextInputContent,
14
- type TextInputContentProps,
15
- } from "./TextInputContent";
16
5
 
17
6
  export type PluginConfiguration = {
18
7
  [key: string]: any;
@@ -1,88 +1,19 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`OfflineHandler renders 1`] = `
4
- <View
3
+ exports[`OfflineHandler renders its children without wrapping them in a notification view 1`] = `
4
+ <RNCSafeAreaProvider
5
+ onInsetsChange={[Function]}
5
6
  style={
6
- {
7
- "flex": 1,
8
- "position": "relative",
9
- }
7
+ [
8
+ {
9
+ "flex": 1,
10
+ },
11
+ undefined,
12
+ ]
10
13
  }
11
14
  >
12
- <View
13
- style={
14
- {
15
- "bottom": 0,
16
- "left": 0,
17
- "position": "absolute",
18
- "right": 0,
19
- "top": 0,
20
- }
21
- }
22
- >
23
- <View
24
- accessibilityState={
25
- {
26
- "busy": undefined,
27
- "checked": undefined,
28
- "disabled": undefined,
29
- "expanded": undefined,
30
- "selected": undefined,
31
- }
32
- }
33
- accessible={true}
34
- collapsable={false}
35
- focusable={true}
36
- onClick={[Function]}
37
- onResponderGrant={[Function]}
38
- onResponderMove={[Function]}
39
- onResponderRelease={[Function]}
40
- onResponderTerminate={[Function]}
41
- onResponderTerminationRequest={[Function]}
42
- onStartShouldSetResponder={[Function]}
43
- style={
44
- {
45
- "alignItems": "center",
46
- "backgroundColor": undefined,
47
- "flex": 1,
48
- "height": 88,
49
- "justifyContent": "center",
50
- "left": 0,
51
- "opacity": 0,
52
- "position": "absolute",
53
- "right": 0,
54
- "top": 0,
55
- "transform": [
56
- {
57
- "translateY": -88,
58
- },
59
- ],
60
- "width": "100%",
61
- }
62
- }
63
- >
64
- <View
65
- style={
66
- {
67
- "backgroundColor": undefined,
68
- "height": 44,
69
- }
70
- }
71
- />
72
- <Text
73
- style={
74
- {
75
- "color": undefined,
76
- "fontFamily": undefined,
77
- "fontSize": undefined,
78
- "letterSpacing": undefined,
79
- "lineHeight": undefined,
80
- }
81
- }
82
- >
83
- You are back online
84
- </Text>
85
- </View>
86
- </View>
87
- </View>
15
+ <Text>
16
+ child content
17
+ </Text>
18
+ </RNCSafeAreaProvider>
88
19
  `;