flowboard-react 0.1.0 → 0.3.0

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 (39) hide show
  1. package/README.md +3 -2
  2. package/lib/module/Flowboard.js +3 -2
  3. package/lib/module/Flowboard.js.map +1 -1
  4. package/lib/module/FlowboardProvider.js +18 -14
  5. package/lib/module/FlowboardProvider.js.map +1 -1
  6. package/lib/module/components/FlowboardFlow.js +70 -37
  7. package/lib/module/components/FlowboardFlow.js.map +1 -1
  8. package/lib/module/components/FlowboardRenderer.js +622 -105
  9. package/lib/module/components/FlowboardRenderer.js.map +1 -1
  10. package/lib/module/core/assetPreloader.js +20 -18
  11. package/lib/module/core/assetPreloader.js.map +1 -1
  12. package/lib/module/index.js +1 -0
  13. package/lib/module/index.js.map +1 -1
  14. package/lib/module/types/react-native-peers.d.js +2 -0
  15. package/lib/module/types/react-native-peers.d.js.map +1 -0
  16. package/lib/module/utils/flowboardUtils.js +20 -14
  17. package/lib/module/utils/flowboardUtils.js.map +1 -1
  18. package/lib/typescript/src/Flowboard.d.ts.map +1 -1
  19. package/lib/typescript/src/FlowboardProvider.d.ts.map +1 -1
  20. package/lib/typescript/src/components/FlowboardFlow.d.ts +1 -2
  21. package/lib/typescript/src/components/FlowboardFlow.d.ts.map +1 -1
  22. package/lib/typescript/src/components/FlowboardRenderer.d.ts.map +1 -1
  23. package/lib/typescript/src/core/assetPreloader.d.ts.map +1 -1
  24. package/lib/typescript/src/index.d.ts +2 -0
  25. package/lib/typescript/src/index.d.ts.map +1 -1
  26. package/lib/typescript/src/types/flowboard.d.ts +1 -0
  27. package/lib/typescript/src/types/flowboard.d.ts.map +1 -1
  28. package/lib/typescript/src/utils/flowboardUtils.d.ts +6 -0
  29. package/lib/typescript/src/utils/flowboardUtils.d.ts.map +1 -1
  30. package/package.json +17 -16
  31. package/src/Flowboard.ts +5 -2
  32. package/src/FlowboardProvider.tsx +20 -16
  33. package/src/components/FlowboardFlow.tsx +89 -49
  34. package/src/components/FlowboardRenderer.tsx +771 -98
  35. package/src/core/assetPreloader.ts +21 -32
  36. package/src/index.tsx +2 -0
  37. package/src/types/flowboard.ts +1 -0
  38. package/src/types/react-native-peers.d.ts +106 -0
  39. package/src/utils/flowboardUtils.ts +28 -14
@@ -1,14 +1,18 @@
1
1
  import { Image } from 'react-native';
2
2
 
3
+ function isNetworkLikeUri(value: unknown): value is string {
4
+ if (typeof value !== 'string') return false;
5
+ const normalized = value.trim();
6
+ if (!normalized) return false;
7
+ return /^(https?:|file:|content:|data:)/i.test(normalized);
8
+ }
9
+
3
10
  export class AssetPreloader {
4
11
  private preloadedUrls = new Set<string>();
5
12
 
6
13
  async preloadScreenAssets(screenData: Record<string, any>): Promise<void> {
7
14
  const assets = this.extractAssets(screenData);
8
- if (
9
- assets.networkImages.length === 0 &&
10
- assets.networkLotties.length === 0
11
- ) {
15
+ if (assets.networkImages.length === 0) {
12
16
  return;
13
17
  }
14
18
 
@@ -20,16 +24,6 @@ export class AssetPreloader {
20
24
  tasks.push(Image.prefetch(url).catch(() => null));
21
25
  }
22
26
 
23
- for (const url of assets.networkLotties) {
24
- if (this.preloadedUrls.has(url)) continue;
25
- this.preloadedUrls.add(url);
26
- tasks.push(
27
- fetch(url)
28
- .then(() => null)
29
- .catch(() => null)
30
- );
31
- }
32
-
33
27
  if (tasks.length > 0) {
34
28
  await Promise.all(tasks);
35
29
  }
@@ -41,11 +35,9 @@ export class AssetPreloader {
41
35
 
42
36
  private extractAssets(data: Record<string, any>): {
43
37
  networkImages: string[];
44
- networkLotties: string[];
45
38
  } {
46
39
  const assets = {
47
40
  networkImages: [] as string[],
48
- networkLotties: [] as string[],
49
41
  };
50
42
  this.scanWidget(data, assets, 0);
51
43
  return assets;
@@ -53,7 +45,7 @@ export class AssetPreloader {
53
45
 
54
46
  private scanWidget(
55
47
  widget: any,
56
- assets: { networkImages: string[]; networkLotties: string[] },
48
+ assets: { networkImages: string[] },
57
49
  depth: number
58
50
  ): void {
59
51
  if (!widget || depth > 50) return;
@@ -72,26 +64,23 @@ export class AssetPreloader {
72
64
  const source = props.source;
73
65
  const url = props.url;
74
66
  if (source === 'network' && url) {
75
- assets.networkImages.push(url);
67
+ if (isNetworkLikeUri(url)) assets.networkImages.push(url);
76
68
  }
77
- }
78
-
79
- if (type === 'lottie') {
80
- const source = props.source;
81
- const url = props.url;
82
- if (source === 'network' && url) {
83
- assets.networkLotties.push(url);
69
+ if (source === 'asset' && props.path) {
70
+ if (isNetworkLikeUri(props.path)) assets.networkImages.push(props.path);
84
71
  }
85
72
  }
86
73
 
87
74
  const background = widget.background ?? props.background;
88
- if (
89
- background &&
90
- typeof background === 'object' &&
91
- background.type === 'image'
92
- ) {
93
- const url = background.url;
94
- if (url) assets.networkImages.push(url);
75
+ if (background && typeof background === 'object') {
76
+ if (background.type === 'image') {
77
+ const url = background.url;
78
+ if (isNetworkLikeUri(url)) assets.networkImages.push(url);
79
+ }
80
+ if (background.type === 'asset') {
81
+ const path = background.path;
82
+ if (isNetworkLikeUri(path)) assets.networkImages.push(path);
83
+ }
95
84
  }
96
85
 
97
86
  Object.values(widget).forEach((value) => {
package/src/index.tsx CHANGED
@@ -1,5 +1,6 @@
1
1
  export { Flowboard } from './Flowboard';
2
2
  export { default as FlowboardProvider } from './FlowboardProvider';
3
+ export { default as FlowboardFlow } from './components/FlowboardFlow';
3
4
  export type {
4
5
  FlowboardContext,
5
6
  CustomScreenBuilder,
@@ -9,3 +10,4 @@ export type {
9
10
  FlowboardLaunchOptions,
10
11
  FlowboardData,
11
12
  } from './types/flowboard';
13
+ export type { FlowboardFlowProps } from './components/FlowboardFlow';
@@ -47,4 +47,5 @@ export type FlowboardLaunchOptions = {
47
47
  onStepChange?: OnStepChangeCallback;
48
48
  enableAnalytics?: boolean;
49
49
  alwaysRestart?: boolean;
50
+ resumeProgress?: boolean;
50
51
  };
@@ -0,0 +1,106 @@
1
+ declare module '@react-native-async-storage/async-storage' {
2
+ const AsyncStorage: any;
3
+ export default AsyncStorage;
4
+ }
5
+
6
+ declare module '@react-native-masked-view/masked-view' {
7
+ import type { ComponentType } from 'react';
8
+ const MaskedView: ComponentType<any>;
9
+ export default MaskedView;
10
+ }
11
+
12
+ declare module 'lottie-react-native' {
13
+ import type { ComponentType } from 'react';
14
+ const LottieView: ComponentType<any>;
15
+ export default LottieView;
16
+ }
17
+
18
+ declare module 'react-native-device-info' {
19
+ const DeviceInfo: any;
20
+ export default DeviceInfo;
21
+ }
22
+
23
+ declare module 'react-native-in-app-review' {
24
+ const InAppReview: {
25
+ isAvailable: () => boolean;
26
+ RequestInAppReview: () => Promise<boolean>;
27
+ };
28
+ export default InAppReview;
29
+ }
30
+
31
+ declare module 'react-native-linear-gradient' {
32
+ import type { ComponentType } from 'react';
33
+ const LinearGradient: ComponentType<any>;
34
+ export default LinearGradient;
35
+ }
36
+
37
+ declare module 'react-native-mask-input' {
38
+ import type { ComponentType } from 'react';
39
+ const MaskInput: ComponentType<any>;
40
+ export default MaskInput;
41
+ }
42
+
43
+ declare module 'react-native-pager-view' {
44
+ import { Component } from 'react';
45
+
46
+ export type PagerViewOnPageSelectedEvent = {
47
+ nativeEvent: {
48
+ position: number;
49
+ };
50
+ };
51
+
52
+ export default class PagerView extends Component<any> {
53
+ setPage(index: number): void;
54
+ setPageWithoutAnimation(index: number): void;
55
+ }
56
+ }
57
+
58
+ declare module 'react-native-permissions' {
59
+ export const PERMISSIONS: Record<string, any>;
60
+ export const RESULTS: Record<string, string>;
61
+ export function request(permission: string): Promise<string>;
62
+ export function requestNotifications(
63
+ options?: string[]
64
+ ): Promise<{ status: string }>;
65
+ export function openSettings(): Promise<void>;
66
+ }
67
+
68
+ declare module 'react-native-safe-area-context' {
69
+ import type { ComponentType } from 'react';
70
+ export const SafeAreaProvider: ComponentType<any>;
71
+ export const SafeAreaView: ComponentType<any>;
72
+ export const initialWindowMetrics: {
73
+ insets: {
74
+ top: number;
75
+ right: number;
76
+ bottom: number;
77
+ left: number;
78
+ };
79
+ } | null;
80
+ export function useSafeAreaInsets(): {
81
+ top: number;
82
+ right: number;
83
+ bottom: number;
84
+ left: number;
85
+ };
86
+ }
87
+
88
+ declare module 'react-native-svg' {
89
+ import type { ComponentType } from 'react';
90
+
91
+ const Svg: ComponentType<any>;
92
+ export default Svg;
93
+
94
+ export const Circle: ComponentType<any>;
95
+ export const Defs: ComponentType<any>;
96
+ export const G: ComponentType<any>;
97
+ export const Line: ComponentType<any>;
98
+ export const Path: ComponentType<any>;
99
+ export const Polygon: ComponentType<any>;
100
+ export const Rect: ComponentType<any>;
101
+ export const Stop: ComponentType<any>;
102
+ export const Text: ComponentType<any>;
103
+ export const TSpan: ComponentType<any>;
104
+ export const Use: ComponentType<any>;
105
+ export const LinearGradient: ComponentType<any>;
106
+ }
@@ -102,21 +102,21 @@ export function parseInsets(value: any): Insets {
102
102
  return { top: value, right: value, bottom: value, left: value };
103
103
  }
104
104
  if (value && typeof value === 'object') {
105
- if ('horizontal' in value || 'vertical' in value) {
106
- const horizontal = Number(value.horizontal ?? 0);
107
- const vertical = Number(value.vertical ?? 0);
108
- return {
109
- top: vertical,
110
- right: horizontal,
111
- bottom: vertical,
112
- left: horizontal,
113
- };
114
- }
105
+ const horizontal = Number(value.horizontal ?? 0);
106
+ const vertical = Number(value.vertical ?? 0);
107
+ const hasHorizontal = 'horizontal' in value;
108
+ const hasVertical = 'vertical' in value;
109
+
110
+ const top = Number(value.top ?? (hasVertical ? vertical : 0));
111
+ const right = Number(value.right ?? (hasHorizontal ? horizontal : 0));
112
+ const bottom = Number(value.bottom ?? (hasVertical ? vertical : 0));
113
+ const left = Number(value.left ?? (hasHorizontal ? horizontal : 0));
114
+
115
115
  return {
116
- top: Number(value.top ?? 0),
117
- right: Number(value.right ?? 0),
118
- bottom: Number(value.bottom ?? 0),
119
- left: Number(value.left ?? 0),
116
+ top,
117
+ right,
118
+ bottom,
119
+ left,
120
120
  };
121
121
  }
122
122
  return { ...EMPTY_INSETS };
@@ -136,6 +136,20 @@ export function insetsToStyle(insets: Insets): {
136
136
  };
137
137
  }
138
138
 
139
+ export function insetsToMarginStyle(insets: Insets): {
140
+ marginTop: number;
141
+ marginRight: number;
142
+ marginBottom: number;
143
+ marginLeft: number;
144
+ } {
145
+ return {
146
+ marginTop: insets.top,
147
+ marginRight: insets.right,
148
+ marginBottom: insets.bottom,
149
+ marginLeft: insets.left,
150
+ };
151
+ }
152
+
139
153
  export function formatDate(pattern: string, date = new Date()): string {
140
154
  const pad = (value: number, len = 2) => value.toString().padStart(len, '0');
141
155
  const replacements: Record<string, string> = {