@ionic/portals-react-native 0.5.1 → 0.6.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 (48) 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 +37 -16
  6. package/android/src/main/java/io/ionic/portals/reactnative/ReactNativePortalsModule.kt +2 -3
  7. package/android/src/main/java/io/ionic/portals/reactnative/ReactNativeWebVitalsModule.kt +11 -19
  8. package/ios/IonicPortals+Codable.swift +77 -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/PortalView.swift +26 -8
  14. package/ios/PortalsConfig.swift +1 -88
  15. package/ios/PortalsReactNative-Bridging-Header.h +2 -0
  16. package/ios/PortalsReactNative.swift +41 -36
  17. package/ios/SyncResult+SyncError+Encodable.swift +55 -0
  18. package/ios/WebVitals.swift +19 -26
  19. package/package.json +62 -43
  20. package/src/{PortalView.android.tsx → BasePortalView.android.tsx} +2 -3
  21. package/src/{PortalView.tsx → BasePortalView.tsx} +2 -3
  22. package/src/{index.ts → index.tsx} +77 -39
  23. package/ios/LiveUpdate+Dict.swift +0 -30
  24. package/ios/LiveUpdateManagerError+Dict.swift +0 -19
  25. package/ios/ReactNativePortals.xcodeproj/project.pbxproj +0 -465
  26. package/ios/ReactNativePortals.xcodeproj/xcshareddata/xcschemes/ReactNativePortals.xcscheme +0 -67
  27. package/ios/ReactNativePortals.xcworkspace/contents.xcworkspacedata +0 -10
  28. package/ios/ReactNativePortals.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  29. package/ios/SyncResult+Dict.swift +0 -35
  30. package/lib/commonjs/PortalView.android.js +0 -28
  31. package/lib/commonjs/PortalView.android.js.map +0 -1
  32. package/lib/commonjs/PortalView.js +0 -15
  33. package/lib/commonjs/PortalView.js.map +0 -1
  34. package/lib/commonjs/index.js +0 -200
  35. package/lib/commonjs/index.js.map +0 -1
  36. package/lib/module/PortalView.android.js +0 -20
  37. package/lib/module/PortalView.android.js.map +0 -1
  38. package/lib/module/PortalView.js +0 -8
  39. package/lib/module/PortalView.js.map +0 -1
  40. package/lib/module/index.js +0 -176
  41. package/lib/module/index.js.map +0 -1
  42. package/lib/typescript/PortalView.android.d.ts +0 -4
  43. package/lib/typescript/PortalView.d.ts +0 -4
  44. package/lib/typescript/index.d.ts +0 -181
  45. /package/ios/{PortalManager.m → PortalManager.mm} +0 -0
  46. /package/ios/{PortalView.m → PortalView.mm} +0 -0
  47. /package/ios/{PortalWebVitals.m → PortalWebVitals.mm} +0 -0
  48. /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.1",
4
- "description": "Ionic Portals for React Native",
3
+ "version": "0.6.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.
@@ -64,12 +93,14 @@ interface WebVitalsEvent {
64
93
  duration: number;
65
94
  }
66
95
 
67
- export const onFirstContentfulPaint = async (
96
+ const registerVital = (
68
97
  portalName: string,
98
+ vital: 'fcp' | 'fid' | 'ttfb',
69
99
  callback: (duration: number) => void
70
- ): Promise<void> => {
100
+ ) => {
101
+ if (Platform.OS === 'ios' && vital !== 'fcp') return;
71
102
  const listener = WebVitals.addListener(
72
- 'vitals:fcp',
103
+ `vitals:${vital}`,
73
104
  (event: WebVitalsEvent) => {
74
105
  if (event.portalName === portalName) {
75
106
  callback(event.duration);
@@ -77,48 +108,49 @@ export const onFirstContentfulPaint = async (
77
108
  }
78
109
  );
79
110
 
111
+ webVitalsMap.set(`${portalName}-vitals:${vital}`, listener);
112
+ };
113
+
114
+ /**
115
+ * @deprecated Use {@link WebVitals} prop on {@link PortalView} instead. This will be removed in the next release.
116
+ */
117
+ export const onFirstContentfulPaint = async (
118
+ portalName: string,
119
+ callback: (duration: number) => void
120
+ ): Promise<void> => {
121
+ registerVital(portalName, 'fcp', callback);
80
122
  await IONPortalsWebVitals.registerOnFirstContentfulPaint(portalName);
81
- webVitalsMap.set(`${portalName}-vitals:fcp`, listener);
82
123
  };
83
124
 
125
+ /**
126
+ * @deprecated Use {@link WebVitals} prop on {@link PortalView} instead. This will be removed in the next release.
127
+ */
84
128
  export const onFirstInputDelay = async (
85
129
  portalName: string,
86
130
  callback: (duration: number) => void
87
131
  ) => {
88
132
  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
-
133
+ registerVital(portalName, 'fid', callback);
98
134
  await IONPortalsWebVitals.registerOnFirstInputDelay(portalName);
99
- webVitalsMap.set(`${portalName}-vitals:fid`, listener);
100
135
  }
101
136
  };
102
137
 
138
+ /**
139
+ * @deprecated Use {@link WebVitals} prop on {@link PortalView} instead. This will be removed in the next release.
140
+ */
103
141
  export const onTimeToFirstByte = async (
104
142
  portalName: string,
105
143
  callback: (duration: number) => void
106
144
  ) => {
107
145
  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
-
146
+ registerVital(portalName, 'ttfb', callback);
117
147
  await IONPortalsWebVitals.registerOnTimeToFirstByte(portalName);
118
- webVitalsMap.set(`${portalName}-vitals:ttfb`, listener);
119
148
  }
120
149
  };
121
150
 
151
+ /**
152
+ * @deprecated Use {@link WebVitals} prop on {@link PortalView} instead. This will be removed in the next release.
153
+ */
122
154
  export const registerWebVitals = async (
123
155
  portalName: string,
124
156
  firstContentfulPaint: (duration: number) => void,
@@ -130,6 +162,12 @@ export const registerWebVitals = async (
130
162
  onTimeToFirstByte(portalName, timeToFirstByte);
131
163
  };
132
164
 
165
+ export type WebVitals = {
166
+ firstContentfulPaint?: (duration: number) => void;
167
+ firstInputDelay?: (duration: number) => void;
168
+ timeToFirstByte?: (duration: number) => void;
169
+ };
170
+
133
171
  /**
134
172
  * Validates that a valid registration key has been procured from http://ionic.io/register-portals
135
173
  * @param key The registration key
@@ -184,21 +222,17 @@ export interface AssetMap {
184
222
  startDir?: string;
185
223
  }
186
224
 
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
225
  /**
196
226
  * Props needed for rendering a {@link Portal}
197
227
  */
198
- export type PortalProps = PortalProp & ViewProps;
228
+ export type PortalProps = { portal: Portal; webVitals?: WebVitals } & ViewProps;
199
229
 
200
230
  /**
201
- * Adds a Portal to an internal registry. Must be called before attempting to render a {@link PortalView}.
231
+ * @deprecated Portals are no longer centrally managed natively.
232
+ * Pass a {@link Portal} directly to {@link PortalView} instead.
233
+ * This will be removed in the next release.
234
+ *
235
+ * Adds a Portal to an internal registry.
202
236
  *
203
237
  * @param portal The portal to add to the internal registry.
204
238
  * @returns Promise containing the Portal that was added to the registry.
@@ -208,7 +242,9 @@ export const addPortal = async (portal: Portal): Promise<Portal> => {
208
242
  };
209
243
 
210
244
  /**
211
- * Adds all portals to an internal registry. This or {@link addPortal} must be called before attempting to render a {@link PortalView}
245
+ * @deprecated Portals are no longer centrally managed natively.
246
+ * Pass a {@link Portal} directly to {@link PortalView} instead.
247
+ * This will be removed in the next release.
212
248
  *
213
249
  * @param portals The portals to add to the internal registry.
214
250
  * @returns Promise containing the Portals that were added to the registry.
@@ -218,7 +254,9 @@ export const addPortals = async (portals: Portal[]): Promise<Portal[]> => {
218
254
  };
219
255
 
220
256
  /**
221
- * Gets a {@link Portal} previously registered via {@link addPortal} or {@link addPortals}.
257
+ * @deprecated Portals are no longer centrally managed natively.
258
+ * Pass a {@link Portal} directly to {@link PortalView} instead.
259
+ * This will be removed in the next release.
222
260
  *
223
261
  * @param name The portal name to retrieve from the internal registry.
224
262
  * @returns Promise containing the registered {@link Portal}. If the {@link Portal} was not registered, the Promise will fail.
@@ -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
- }