@ionic/portals-react-native 0.5.2 → 0.7.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 (49) hide show
  1. package/ReactNativePortals.podspec +39 -14
  2. package/android/build.gradle +78 -108
  3. package/android/gradle.properties +5 -3
  4. package/android/src/main/java/io/ionic/portals/reactnative/PortalView.kt +11 -8
  5. package/android/src/main/java/io/ionic/portals/reactnative/ReactNativePortalManager.kt +24 -24
  6. package/android/src/main/java/io/ionic/portals/reactnative/ReactNativePortalsModule.kt +0 -34
  7. package/android/src/main/java/io/ionic/portals/reactnative/ReactNativeWebVitalsModule.kt +0 -34
  8. package/ios/AssetMap+Codable.swift +33 -0
  9. package/ios/LiveUpdateManager+Async.swift +16 -46
  10. package/ios/Podfile +29 -4
  11. package/ios/Podfile.lock +478 -241
  12. package/ios/Portal.swift +50 -54
  13. package/ios/{PortalManager.m → PortalManager.mm} +0 -3
  14. package/ios/PortalView.swift +22 -12
  15. package/ios/{PortalWebVitals.m → PortalWebVitals.mm} +0 -1
  16. package/ios/PortalsConfig.swift +1 -88
  17. package/ios/PortalsReactNative-Bridging-Header.h +2 -0
  18. package/ios/PortalsReactNative.swift +17 -51
  19. package/ios/SyncResult+SyncError+Encodable.swift +55 -0
  20. package/ios/WebVitals.swift +17 -34
  21. package/package.json +62 -43
  22. package/src/{PortalView.android.tsx → BasePortalView.android.tsx} +2 -3
  23. package/src/{PortalView.tsx → BasePortalView.tsx} +2 -3
  24. package/src/{index.ts → index.tsx} +43 -96
  25. package/ios/AssetMap+Dict.swift +0 -28
  26. package/ios/LiveUpdate+Dict.swift +0 -30
  27. package/ios/LiveUpdateManagerError+Dict.swift +0 -19
  28. package/ios/ReactNativePortals.xcodeproj/project.pbxproj +0 -465
  29. package/ios/ReactNativePortals.xcodeproj/xcshareddata/xcschemes/ReactNativePortals.xcscheme +0 -67
  30. package/ios/ReactNativePortals.xcworkspace/contents.xcworkspacedata +0 -10
  31. package/ios/ReactNativePortals.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  32. package/ios/SyncResult+Dict.swift +0 -35
  33. package/lib/commonjs/PortalView.android.js +0 -28
  34. package/lib/commonjs/PortalView.android.js.map +0 -1
  35. package/lib/commonjs/PortalView.js +0 -15
  36. package/lib/commonjs/PortalView.js.map +0 -1
  37. package/lib/commonjs/index.js +0 -200
  38. package/lib/commonjs/index.js.map +0 -1
  39. package/lib/module/PortalView.android.js +0 -20
  40. package/lib/module/PortalView.android.js.map +0 -1
  41. package/lib/module/PortalView.js +0 -8
  42. package/lib/module/PortalView.js.map +0 -1
  43. package/lib/module/index.js +0 -176
  44. package/lib/module/index.js.map +0 -1
  45. package/lib/typescript/PortalView.android.d.ts +0 -4
  46. package/lib/typescript/PortalView.d.ts +0 -4
  47. package/lib/typescript/index.d.ts +0 -181
  48. /package/ios/{PortalView.m → PortalView.mm} +0 -0
  49. /package/ios/{PortalsPubSub.m → PortalsPubSub.mm} +0 -0
package/package.json CHANGED
@@ -1,86 +1,99 @@
1
1
  {
2
2
  "name": "@ionic/portals-react-native",
3
- "version": "0.5.2",
4
- "description": "Ionic Portals for React Native",
3
+ "version": "0.7.0",
4
+ "description": "Portals for React Native",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
7
- "types": "lib/typescript/index.d.ts",
7
+ "types": "lib/typescript/src/index.d.ts",
8
8
  "react-native": "src/index",
9
9
  "source": "src/index",
10
10
  "files": [
11
11
  "src",
12
12
  "lib",
13
- "android/build.gradle",
14
- "android/gradle.properties",
15
- "android/src/main",
13
+ "android",
16
14
  "ios",
17
15
  "cpp",
18
- "ReactNativePortals.podspec",
19
- "!lib/typescript/example",
16
+ "*.podspec",
20
17
  "!ios/build",
21
- "!ios/Pods",
22
- "!ios/**/xcuserdata",
18
+ "!android/build",
19
+ "!android/gradle",
20
+ "!android/gradlew",
21
+ "!android/gradlew.bat",
22
+ "!android/local.properties",
23
23
  "!**/__tests__",
24
24
  "!**/__fixtures__",
25
- "!**/__mocks__"
25
+ "!**/__mocks__",
26
+ "!**/.*"
26
27
  ],
27
28
  "scripts": {
29
+ "example": "yarn workspace @ionic/portals-react-native-example",
30
+ "webapp": "yarn workspace RNPortals",
28
31
  "test": "jest",
29
- "typescript": "tsc --noEmit",
32
+ "typecheck": "tsc --noEmit",
30
33
  "lint": "eslint \"**/*.{js,ts,tsx}\"",
31
34
  "lint:fix": "eslint \"**/*.{js,ts,tsx}\" --fix",
32
35
  "docs": "typedoc --out ./docs/documentation ./src --tsconfig ./tsconfig.build.json",
33
- "prepare": "bob build",
34
- "release": "release-it",
35
- "example": "yarn --cwd example",
36
- "pods": "cd example && pod-install --quiet",
37
- "bootstrap": "yarn example && yarn && yarn pods"
36
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
37
+ "prepare": "bob build"
38
38
  },
39
39
  "keywords": [
40
40
  "react-native",
41
41
  "ios",
42
42
  "android"
43
43
  ],
44
- "repository": "https://github.com/ionic-team/react-native-ionic-portals",
45
44
  "author": "Ionic <hi@ionicframework.com> (https://ionic.io/portals)",
46
45
  "license": "Commercial",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/ionic-team/ionic-portals-react-native.git"
49
+ },
47
50
  "bugs": {
48
- "url": "https://github.com/ionic-team/react-native-ionic-portals/issues"
51
+ "url": "https://github.com/ionic-team/ionic-portals-react-native/issues"
49
52
  },
50
- "homepage": "https://github.com/ionic-team/react-native-ionic-portals#readme",
53
+ "homepage": "https://github.com/ionic-team/ionic-portals-react-native#readme",
51
54
  "publishConfig": {
52
55
  "registry": "https://registry.npmjs.org/"
53
56
  },
54
57
  "devDependencies": {
55
- "@commitlint/config-conventional": "^11.0.0",
56
- "@react-native-community/eslint-config": "^2.0.0",
57
- "@release-it/conventional-changelog": "^2.0.0",
58
- "@types/jest": "^26.0.0",
59
- "@types/react": "^16.9.19",
60
- "@types/react-native": "0.62.13",
61
- "commitlint": "^11.0.0",
62
- "eslint": "^7.2.0",
63
- "eslint-config-prettier": "^7.0.0",
64
- "eslint-plugin-prettier": "^3.1.3",
65
- "husky": "^6.0.0",
66
- "jest": "^26.0.1",
67
- "pod-install": "^0.1.0",
68
- "prettier": "^2.0.5",
69
- "react": "16.13.1",
70
- "react-native": "0.63.4",
71
- "react-native-builder-bob": "^0.18.2",
58
+ "@commitlint/config-conventional": "^17.0.2",
59
+ "@evilmartians/lefthook": "^1.5.0",
60
+ "@react-native/eslint-config": "^0.73.1",
61
+ "@release-it/conventional-changelog": "^5.0.0",
62
+ "@types/jest": "^29.5.5",
63
+ "@types/react": "^18.2.44",
64
+ "commitlint": "^17.0.2",
65
+ "del-cli": "^5.1.0",
66
+ "eslint": "^8.51.0",
67
+ "eslint-config-prettier": "^9.0.0",
68
+ "eslint-plugin-prettier": "^5.0.1",
69
+ "jest": "^29.7.0",
70
+ "prettier": "^3.0.3",
71
+ "react": "18.2.0",
72
+ "react-native": "0.74.2",
73
+ "react-native-builder-bob": "^0.23.2",
74
+ "release-it": "^15.0.0",
75
+ "turbo": "^1.10.7",
72
76
  "typedoc": "^0.23.16",
73
- "typescript": "^4.1.3"
77
+ "typescript": "^5.2.2"
78
+ },
79
+ "resolutions": {
80
+ "@types/react": "^18.2.44"
74
81
  },
75
82
  "peerDependencies": {
76
83
  "react": "*",
77
84
  "react-native": "*"
78
85
  },
86
+ "workspaces": [
87
+ "example",
88
+ "web"
89
+ ],
90
+ "packageManager": "yarn@3.6.1",
79
91
  "jest": {
80
92
  "preset": "react-native",
81
93
  "modulePathIgnorePatterns": [
82
94
  "<rootDir>/example/node_modules",
83
- "<rootDir>/lib/"
95
+ "<rootDir>/lib/",
96
+ "<rootDir>/web/"
84
97
  ]
85
98
  },
86
99
  "commitlint": {
@@ -91,7 +104,7 @@
91
104
  "eslintConfig": {
92
105
  "root": true,
93
106
  "extends": [
94
- "@react-native-community",
107
+ "@react-native",
95
108
  "prettier"
96
109
  ],
97
110
  "rules": {
@@ -108,8 +121,14 @@
108
121
  }
109
122
  },
110
123
  "eslintIgnore": [
111
- "node_modules/",
112
- "lib/"
124
+ "example/**",
125
+ "lib/**",
126
+ "scripts/**",
127
+ "node_modules/**",
128
+ "ios/**",
129
+ "android/**",
130
+ "docs/**",
131
+ "web/**"
113
132
  ],
114
133
  "prettier": {
115
134
  "quoteProps": "consistent",
@@ -132,4 +151,4 @@
132
151
  ]
133
152
  ]
134
153
  }
135
- }
154
+ }
@@ -4,7 +4,6 @@ import {
4
4
  requireNativeComponent,
5
5
  UIManager,
6
6
  } from 'react-native';
7
- import type { PortalProps } from '.';
8
7
 
9
8
  const PortalViewManager = requireNativeComponent('AndroidPortalView');
10
9
 
@@ -17,7 +16,7 @@ const createFragment = (viewId: number | null) =>
17
16
  [viewId]
18
17
  );
19
18
 
20
- const PortalView = (props: PortalProps) => {
19
+ const BasePortalView = (props: any) => {
21
20
  const ref = useRef(null);
22
21
 
23
22
  useEffect(() => {
@@ -28,4 +27,4 @@ const PortalView = (props: PortalProps) => {
28
27
  return <PortalViewManager {...props} ref={ref} />;
29
28
  };
30
29
 
31
- export default PortalView;
30
+ export default BasePortalView;
@@ -1,11 +1,10 @@
1
1
  import React from 'react';
2
2
  import { requireNativeComponent } from 'react-native';
3
- import type { PortalProps } from '.';
4
3
 
5
4
  const HostComponentPortal = requireNativeComponent('IONPortalView');
6
5
 
7
- const PortalView = (props: PortalProps) => {
6
+ const BasePortalView = (props: any) => {
8
7
  return <HostComponentPortal {...props} />;
9
8
  };
10
9
 
11
- export default PortalView;
10
+ export default BasePortalView;
@@ -1,15 +1,44 @@
1
+ import React from 'react';
1
2
  import {
2
- EmitterSubscription,
3
+ type EmitterSubscription,
3
4
  NativeEventEmitter,
4
5
  NativeModules,
5
6
  Platform,
6
- ViewProps,
7
+ type ViewProps,
7
8
  } from 'react-native';
9
+ import BasePortalView from './BasePortalView';
8
10
 
9
11
  const { IONPortalPubSub, IONPortalsReactNative, IONPortalsWebVitals } =
10
12
  NativeModules;
11
13
 
12
- export { default as PortalView } from './PortalView';
14
+ export const PortalView = (props: PortalProps) => {
15
+ let webVitals: string[] | undefined;
16
+ if (props.webVitals) {
17
+ webVitals = [];
18
+ if (props.webVitals.firstContentfulPaint) {
19
+ webVitals.push('fcp');
20
+ registerVital(
21
+ props.portal.name,
22
+ 'fcp',
23
+ props.webVitals.firstContentfulPaint
24
+ );
25
+ }
26
+ if (props.webVitals.firstInputDelay) {
27
+ webVitals.push('fid');
28
+ registerVital(props.portal.name, 'fid', props.webVitals.firstInputDelay);
29
+ }
30
+ if (props.webVitals.timeToFirstByte) {
31
+ webVitals.push('ttfb');
32
+ registerVital(props.portal.name, 'ttfb', props.webVitals.timeToFirstByte);
33
+ }
34
+ }
35
+
36
+ const newProps = { ...props, webVitals: undefined };
37
+ // @ts-ignore
38
+ newProps.portal.webVitals = webVitals;
39
+
40
+ return <BasePortalView {...newProps} />;
41
+ };
13
42
 
14
43
  /**
15
44
  * The data that is received from a subscription event.
@@ -24,8 +53,6 @@ export interface Message {
24
53
 
25
54
  const PortalsPubSub = new NativeEventEmitter(IONPortalPubSub);
26
55
 
27
- // const subscriptionMap = new Map<number, EmitterSubscription>();
28
-
29
56
  /**
30
57
  * Subscribes to messages for a topic
31
58
  *
@@ -64,12 +91,14 @@ interface WebVitalsEvent {
64
91
  duration: number;
65
92
  }
66
93
 
67
- export const onFirstContentfulPaint = async (
94
+ const registerVital = (
68
95
  portalName: string,
96
+ vital: 'fcp' | 'fid' | 'ttfb',
69
97
  callback: (duration: number) => void
70
- ): Promise<void> => {
98
+ ) => {
99
+ if (Platform.OS === 'ios' && vital !== 'fcp') return;
71
100
  const listener = WebVitals.addListener(
72
- 'vitals:fcp',
101
+ `vitals:${vital}`,
73
102
  (event: WebVitalsEvent) => {
74
103
  if (event.portalName === portalName) {
75
104
  callback(event.duration);
@@ -77,57 +106,13 @@ export const onFirstContentfulPaint = async (
77
106
  }
78
107
  );
79
108
 
80
- await IONPortalsWebVitals.registerOnFirstContentfulPaint(portalName);
81
- webVitalsMap.set(`${portalName}-vitals:fcp`, listener);
82
- };
83
-
84
- export const onFirstInputDelay = async (
85
- portalName: string,
86
- callback: (duration: number) => void
87
- ) => {
88
- if (Platform.OS === 'android') {
89
- const listener = WebVitals.addListener(
90
- 'vitals:fid',
91
- (event: WebVitalsEvent) => {
92
- if (event.portalName === portalName) {
93
- callback(event.duration);
94
- }
95
- }
96
- );
97
-
98
- await IONPortalsWebVitals.registerOnFirstInputDelay(portalName);
99
- webVitalsMap.set(`${portalName}-vitals:fid`, listener);
100
- }
109
+ webVitalsMap.set(`${portalName}-vitals:${vital}`, listener);
101
110
  };
102
111
 
103
- export const onTimeToFirstByte = async (
104
- portalName: string,
105
- callback: (duration: number) => void
106
- ) => {
107
- if (Platform.OS === 'android') {
108
- const listener = WebVitals.addListener(
109
- 'vitals:ttfb',
110
- (event: WebVitalsEvent) => {
111
- if (event.portalName === portalName) {
112
- callback(event.duration);
113
- }
114
- }
115
- );
116
-
117
- await IONPortalsWebVitals.registerOnTimeToFirstByte(portalName);
118
- webVitalsMap.set(`${portalName}-vitals:ttfb`, listener);
119
- }
120
- };
121
-
122
- export const registerWebVitals = async (
123
- portalName: string,
124
- firstContentfulPaint: (duration: number) => void,
125
- firstInputDelay: (duration: number) => void,
126
- timeToFirstByte: (duration: number) => void
127
- ) => {
128
- onFirstContentfulPaint(portalName, firstContentfulPaint);
129
- onFirstInputDelay(portalName, firstInputDelay);
130
- onTimeToFirstByte(portalName, timeToFirstByte);
112
+ export type WebVitals = {
113
+ firstContentfulPaint?: (duration: number) => void;
114
+ firstInputDelay?: (duration: number) => void;
115
+ timeToFirstByte?: (duration: number) => void;
131
116
  };
132
117
 
133
118
  /**
@@ -184,48 +169,10 @@ export interface AssetMap {
184
169
  startDir?: string;
185
170
  }
186
171
 
187
- /**
188
- * A subset of {@link Portal} properties needed for rendering a Portal. `initialContext` can be used to override
189
- * any initialContext defined in the original {@link Portal} definition.
190
- */
191
- export type PortalProp = {
192
- portal: Pick<Portal, 'name' | 'initialContext'>;
193
- };
194
-
195
172
  /**
196
173
  * Props needed for rendering a {@link Portal}
197
174
  */
198
- export type PortalProps = PortalProp & ViewProps;
199
-
200
- /**
201
- * Adds a Portal to an internal registry. Must be called before attempting to render a {@link PortalView}.
202
- *
203
- * @param portal The portal to add to the internal registry.
204
- * @returns Promise containing the Portal that was added to the registry.
205
- */
206
- export const addPortal = async (portal: Portal): Promise<Portal> => {
207
- return IONPortalsReactNative.addPortal(portal);
208
- };
209
-
210
- /**
211
- * Adds all portals to an internal registry. This or {@link addPortal} must be called before attempting to render a {@link PortalView}
212
- *
213
- * @param portals The portals to add to the internal registry.
214
- * @returns Promise containing the Portals that were added to the registry.
215
- */
216
- export const addPortals = async (portals: Portal[]): Promise<Portal[]> => {
217
- return IONPortalsReactNative.addPortals(portals);
218
- };
219
-
220
- /**
221
- * Gets a {@link Portal} previously registered via {@link addPortal} or {@link addPortals}.
222
- *
223
- * @param name The portal name to retrieve from the internal registry.
224
- * @returns Promise containing the registered {@link Portal}. If the {@link Portal} was not registered, the Promise will fail.
225
- */
226
- export const getPortal = async (name: string): Promise<Portal> => {
227
- return IONPortalsReactNative.getPortal(name);
228
- };
175
+ export type PortalProps = { portal: Portal; webVitals?: WebVitals } & ViewProps;
229
176
 
230
177
  export interface LiveUpdate {
231
178
  /** The AppFlow application ID */
@@ -1,28 +0,0 @@
1
- //
2
- // AssetMap+Dict.swift
3
- // ReactNativePortals
4
- //
5
- // Created by Steven Sherry on 3/29/23.
6
- // Copyright © 2023 Facebook. All rights reserved.
7
- //
8
-
9
- import IonicPortals
10
-
11
- extension AssetMap {
12
- init?(_ dict: [String: Any]) {
13
- guard let name = dict["name"] as? String else { return nil }
14
- self.init(
15
- name: name,
16
- virtualPath: dict["virtualPath"] as? String,
17
- startDir: dict["startDir"] as? String ?? ""
18
- )
19
- }
20
-
21
- var dict: [String: Any] {
22
- return [
23
- "name": name,
24
- "virtualPath": virtualPath,
25
- "startDir": startDir
26
- ]
27
- }
28
- }
@@ -1,30 +0,0 @@
1
- //
2
- // LiveUpdate+Dict.swift
3
- // ReactNativePortals
4
- //
5
- // Created by Steven Sherry on 10/5/22.
6
- // Copyright © 2022 Ionic. All rights reserved.
7
- //
8
-
9
- import IonicLiveUpdates
10
-
11
- extension LiveUpdate {
12
- init?(_ dict: [String: Any]) {
13
- guard let appId = dict["appId"] as? String,
14
- let channel = dict["channel"] as? String,
15
- let syncOnAdd = dict["syncOnAdd"] as? Bool
16
- else { return nil }
17
-
18
- self.init(appId: appId, channel: channel, syncOnAdd: syncOnAdd)
19
- }
20
- }
21
-
22
- extension LiveUpdate {
23
- var dict: [String: Any] {
24
- return [
25
- "appId": appId,
26
- "channel": channel,
27
- "syncOnAdd": syncOnAdd
28
- ]
29
- }
30
- }
@@ -1,19 +0,0 @@
1
- //
2
- // LiveUpdateManagerError+Dict.swift
3
- // ReactNativePortals
4
- //
5
- // Created by Steven Sherry on 10/5/22.
6
- // Copyright © 2022 Ionic. All rights reserved.
7
- //
8
-
9
- import IonicLiveUpdates
10
-
11
- extension LiveUpdateManager.Error {
12
- var dict: [String: Any] {
13
- return [
14
- "appId": appId,
15
- "failStep": failStep.rawValue.uppercased(),
16
- "message": localizedDescription
17
- ]
18
- }
19
- }