expo-module-template 10.15.3 → 10.15.5
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.
- package/$package.json +3 -2
- package/android/src/main/java/{%= project.package %}/{%- project.moduleName %}.kt +6 -3
- package/android/src/main/java/{%= project.package %}/{%- project.viewName %}.kt +24 -1
- package/example/App.tsx +63 -9
- package/expo-module.config.json +12 -4
- package/ios/{%- project.moduleName %}.swift +7 -3
- package/ios/{%- project.name %}.podspec +1 -2
- package/ios/{%- project.viewName %}.swift +32 -1
- package/package.json +2 -2
- package/src/index.ts +5 -24
- package/src/{%- project.moduleName %}.ts +11 -4
- package/src/{%- project.moduleName %}.web.ts +13 -7
- package/src/{%- project.name %}.types.ts +13 -1
- package/src/{%- project.viewName %}.tsx +2 -2
- package/src/{%- project.viewName %}.web.tsx +5 -1
package/$package.json
CHANGED
|
@@ -30,9 +30,10 @@
|
|
|
30
30
|
"homepage": "<%- repo %>#readme",
|
|
31
31
|
"dependencies": {},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@types/react": "
|
|
33
|
+
"@types/react": "~18.3.12",
|
|
34
34
|
"expo-module-scripts": "^4.0.0",
|
|
35
|
-
"expo
|
|
35
|
+
"expo": "~52.0.0-preview.0",
|
|
36
|
+
"react-native": "0.76.0"
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|
|
38
39
|
"expo": "*",
|
|
@@ -2,6 +2,7 @@ package <%- project.package %>
|
|
|
2
2
|
|
|
3
3
|
import expo.modules.kotlin.modules.Module
|
|
4
4
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
5
|
+
import java.net.URL
|
|
5
6
|
|
|
6
7
|
class <%- project.moduleName %> : Module() {
|
|
7
8
|
// Each module class must implement the definition function. The definition consists of components
|
|
@@ -38,10 +39,12 @@ class <%- project.moduleName %> : Module() {
|
|
|
38
39
|
// Enables the module to be used as a native view. Definition components that are accepted as part of
|
|
39
40
|
// the view definition: Prop, Events.
|
|
40
41
|
View(<%- project.viewName %>::class) {
|
|
41
|
-
// Defines a setter for the `
|
|
42
|
-
Prop("
|
|
43
|
-
|
|
42
|
+
// Defines a setter for the `url` prop.
|
|
43
|
+
Prop("url") { view: <%- project.viewName %>, url: Url ->
|
|
44
|
+
view.webView.loadUrl(url.toString())
|
|
44
45
|
}
|
|
46
|
+
// Defines an event that the view can send to JavaScript.
|
|
47
|
+
Events("onLoad")
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
}
|
|
@@ -1,7 +1,30 @@
|
|
|
1
1
|
package <%- project.package %>
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
+
import android.webkit.WebView
|
|
5
|
+
import android.webkit.WebViewClient
|
|
4
6
|
import expo.modules.kotlin.AppContext
|
|
7
|
+
import expo.modules.kotlin.viewevent.EventDispatcher
|
|
5
8
|
import expo.modules.kotlin.views.ExpoView
|
|
6
9
|
|
|
7
|
-
class <%- project.viewName %>(context: Context, appContext: AppContext) : ExpoView(context, appContext)
|
|
10
|
+
class <%- project.viewName %>(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
|
|
11
|
+
// Creates and initializes an event dispatcher for the `onLoad` event.
|
|
12
|
+
// The name of the event is inferred from the value and needs to match the event name defined in the module.
|
|
13
|
+
private val onLoad by EventDispatcher()
|
|
14
|
+
|
|
15
|
+
// Defines a WebView that will be used as the root subview.
|
|
16
|
+
internal val webView = WebView(context).apply {
|
|
17
|
+
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
|
18
|
+
webViewClient = object : WebViewClient() {
|
|
19
|
+
override fun onPageFinished(view: WebView, url: String) {
|
|
20
|
+
// Sends an event to JavaScript. Triggers a callback defined on the view component in JavaScript.
|
|
21
|
+
onLoad(mapOf("url" to url))
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
init {
|
|
27
|
+
// Adds the WebView to the view hierarchy.
|
|
28
|
+
addView(webView)
|
|
29
|
+
}
|
|
30
|
+
}
|
package/example/App.tsx
CHANGED
|
@@ -1,20 +1,74 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEvent } from 'expo';
|
|
2
|
+
import <%- project.name %>, { <%- project.viewName %> } from '<%- project.slug %>';
|
|
3
|
+
import { Button, SafeAreaView, ScrollView, Text, View } from 'react-native';
|
|
2
4
|
|
|
3
|
-
import * as <%- project.name %> from '<%- project.slug %>';
|
|
4
5
|
|
|
5
6
|
export default function App() {
|
|
7
|
+
const onChangePayload = useEvent(<%- project.name %>, "onChange");
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<SafeAreaView style={styles.container}>
|
|
11
|
+
<ScrollView style={styles.container}>
|
|
12
|
+
<Text style={styles.header}>Module API Example</Text>
|
|
13
|
+
<Group name="Constants">
|
|
14
|
+
<Text>{<%- project.name %>.PI}</Text>
|
|
15
|
+
</Group>
|
|
16
|
+
<Group name="Functions">
|
|
17
|
+
<Text>{<%- project.name %>.hello()}</Text>
|
|
18
|
+
</Group>
|
|
19
|
+
<Group name="Async functions">
|
|
20
|
+
<Button
|
|
21
|
+
title="Set value"
|
|
22
|
+
onPress={async () => {
|
|
23
|
+
await <%- project.name %>.setValueAsync("Hello from JS!");
|
|
24
|
+
}}
|
|
25
|
+
/>
|
|
26
|
+
</Group>
|
|
27
|
+
<Group name="Events">
|
|
28
|
+
<Text>{onChangePayload?.value}</Text>
|
|
29
|
+
</Group>
|
|
30
|
+
<Group name="Views">
|
|
31
|
+
<<%- project.viewName %>
|
|
32
|
+
url="https://www.example.com"
|
|
33
|
+
onLoad={({ nativeEvent: { url } }) => console.log(`Loaded: ${url}`)}
|
|
34
|
+
style={styles.view}
|
|
35
|
+
/>
|
|
36
|
+
</Group>
|
|
37
|
+
</ScrollView>
|
|
38
|
+
</SafeAreaView>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function Group(props: { name: string; children: React.ReactNode }) {
|
|
6
43
|
return (
|
|
7
|
-
<View style={styles.
|
|
8
|
-
<Text>{
|
|
44
|
+
<View style={styles.group}>
|
|
45
|
+
<Text style={styles.groupHeader}>{props.name}</Text>
|
|
46
|
+
{props.children}
|
|
9
47
|
</View>
|
|
10
48
|
);
|
|
11
49
|
}
|
|
12
50
|
|
|
13
|
-
const styles =
|
|
51
|
+
const styles = {
|
|
52
|
+
header: {
|
|
53
|
+
fontSize: 30,
|
|
54
|
+
margin: 20,
|
|
55
|
+
},
|
|
56
|
+
groupHeader: {
|
|
57
|
+
fontSize: 20,
|
|
58
|
+
marginBottom: 20,
|
|
59
|
+
},
|
|
60
|
+
group: {
|
|
61
|
+
margin: 20,
|
|
62
|
+
backgroundColor: '#fff',
|
|
63
|
+
borderRadius: 10,
|
|
64
|
+
padding: 20,
|
|
65
|
+
},
|
|
14
66
|
container: {
|
|
15
67
|
flex: 1,
|
|
16
|
-
backgroundColor: '#
|
|
17
|
-
|
|
18
|
-
|
|
68
|
+
backgroundColor: '#eee',
|
|
69
|
+
},
|
|
70
|
+
view: {
|
|
71
|
+
flex: 1,
|
|
72
|
+
height: 200,
|
|
19
73
|
},
|
|
20
|
-
}
|
|
74
|
+
};
|
package/expo-module.config.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
|
-
"platforms": [
|
|
3
|
-
|
|
4
|
-
"
|
|
2
|
+
"platforms": [
|
|
3
|
+
"apple",
|
|
4
|
+
"android",
|
|
5
|
+
"web"
|
|
6
|
+
],
|
|
7
|
+
"apple": {
|
|
8
|
+
"modules": [
|
|
9
|
+
"<%- project.moduleName %>"
|
|
10
|
+
]
|
|
5
11
|
},
|
|
6
12
|
"android": {
|
|
7
|
-
"modules": [
|
|
13
|
+
"modules": [
|
|
14
|
+
"<%- project.package %>.<%- project.moduleName %>"
|
|
15
|
+
]
|
|
8
16
|
}
|
|
9
17
|
}
|
|
@@ -35,10 +35,14 @@ public class <%- project.moduleName %>: Module {
|
|
|
35
35
|
// Enables the module to be used as a native view. Definition components that are accepted as part of the
|
|
36
36
|
// view definition: Prop, Events.
|
|
37
37
|
View(<%- project.viewName %>.self) {
|
|
38
|
-
// Defines a setter for the `
|
|
39
|
-
Prop("
|
|
40
|
-
|
|
38
|
+
// Defines a setter for the `url` prop.
|
|
39
|
+
Prop("url") { (view: MyModuleView, url: URL) in
|
|
40
|
+
if view.webView.url != url {
|
|
41
|
+
view.webView.load(URLRequest(url: url))
|
|
42
|
+
}
|
|
41
43
|
}
|
|
44
|
+
|
|
45
|
+
Events("onLoad")
|
|
42
46
|
}
|
|
43
47
|
}
|
|
44
48
|
}
|
|
@@ -23,8 +23,7 @@ Pod::Spec.new do |s|
|
|
|
23
23
|
# Swift/Objective-C compatibility
|
|
24
24
|
s.pod_target_xcconfig = {
|
|
25
25
|
'DEFINES_MODULE' => 'YES',
|
|
26
|
-
'SWIFT_COMPILATION_MODE' => 'wholemodule'
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
s.source_files = "**/*.{h,m,swift}"
|
|
28
|
+
s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
|
|
30
29
|
end
|
|
@@ -1,7 +1,38 @@
|
|
|
1
1
|
import ExpoModulesCore
|
|
2
|
+
import WebKit
|
|
2
3
|
|
|
3
4
|
// This view will be used as a native component. Make sure to inherit from `ExpoView`
|
|
4
5
|
// to apply the proper styling (e.g. border radius and shadows).
|
|
5
6
|
class <%- project.viewName %>: ExpoView {
|
|
6
|
-
|
|
7
|
+
let webView = WKWebView()
|
|
8
|
+
let onLoad = EventDispatcher()
|
|
9
|
+
var delegate: WebViewDelegate?
|
|
10
|
+
|
|
11
|
+
required init(appContext: AppContext? = nil) {
|
|
12
|
+
super.init(appContext: appContext)
|
|
13
|
+
clipsToBounds = true
|
|
14
|
+
delegate = WebViewDelegate { url in
|
|
15
|
+
self.onLoad(["url": url])
|
|
16
|
+
}
|
|
17
|
+
webView.navigationDelegate = delegate
|
|
18
|
+
addSubview(webView)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override func layoutSubviews() {
|
|
22
|
+
webView.frame = bounds
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class WebViewDelegate: NSObject, WKNavigationDelegate {
|
|
27
|
+
let onUrlChange: (String) -> Void
|
|
28
|
+
|
|
29
|
+
init(onUrlChange: @escaping (String) -> Void) {
|
|
30
|
+
self.onUrlChange = onUrlChange
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation) {
|
|
34
|
+
if let url = webView.url {
|
|
35
|
+
onUrlChange(url.absoluteString)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
7
38
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-module-template",
|
|
3
|
-
"version": "10.15.
|
|
3
|
+
"version": "10.15.5",
|
|
4
4
|
"description": "ExpoModuleTemplate standalone module",
|
|
5
5
|
"scripts": {},
|
|
6
6
|
"keywords": [
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
"dependencies": {},
|
|
23
23
|
"devDependencies": {},
|
|
24
24
|
"peerDependencies": {},
|
|
25
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "1f7a56b5a5bcef23ac6e55b16db53077f6a4065c"
|
|
26
26
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,24 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import <%- project.viewName %> from './<%- project.viewName %>';
|
|
7
|
-
import { ChangeEventPayload, <%- project.viewName %>Props } from './<%- project.name %>.types';
|
|
8
|
-
|
|
9
|
-
// Get the native constant value.
|
|
10
|
-
export const PI = <%- project.moduleName %>.PI;
|
|
11
|
-
|
|
12
|
-
export function hello(): string {
|
|
13
|
-
return <%- project.moduleName %>.hello();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export async function setValueAsync(value: string) {
|
|
17
|
-
return await <%- project.moduleName %>.setValueAsync(value);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function addChangeListener(listener: (event: ChangeEventPayload) => void): EventSubscription {
|
|
21
|
-
return <%- project.moduleName %>.addListener<ChangeEventPayload>('onChange', listener);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export { <%- project.viewName %>, <%- project.viewName %>Props, ChangeEventPayload };
|
|
1
|
+
// Reexport the native module. On web, it will be resolved to MyModule.web.ts
|
|
2
|
+
// and on native platforms to MyModule.ts
|
|
3
|
+
export { default } from './<%- project.moduleName %>';
|
|
4
|
+
export { default as <%- project.viewName %> } from './<%- project.viewName %>';
|
|
5
|
+
export * from './<%- project.name %>.types';
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import { requireNativeModule } from 'expo
|
|
1
|
+
import { NativeModule, requireNativeModule } from 'expo';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { <%- project.moduleName %>Events } from './<%- project.moduleName %>.types';
|
|
4
|
+
|
|
5
|
+
declare class <%- project.moduleName %> extends NativeModule<<%- project.moduleName %>Events> {
|
|
6
|
+
PI: number;
|
|
7
|
+
hello(): string;
|
|
8
|
+
setValueAsync(value: string): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// This call loads the native module object from the JSI.
|
|
12
|
+
export default requireNativeModule<<%- project.moduleName %>>('<%- project.name %>');
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { registerWebModule, NativeModule } from "expo";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { ChangeEventPayload } from './<%- project.name %>.types';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
type <%- project.moduleName %>Events = {
|
|
6
|
+
onChange: (params: ChangeEventPayload) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
class <%- project.moduleName %> extends NativeModule<<%- project.moduleName %>Events> {
|
|
10
|
+
PI = Math.PI;
|
|
7
11
|
async setValueAsync(value: string): Promise<void> {
|
|
8
|
-
|
|
9
|
-
}
|
|
12
|
+
this.emit('onChange', { value });
|
|
13
|
+
}
|
|
10
14
|
hello() {
|
|
11
15
|
return 'Hello world! 👋';
|
|
12
|
-
}
|
|
16
|
+
}
|
|
13
17
|
};
|
|
18
|
+
|
|
19
|
+
export default registerWebModule(<%- project.moduleName %>);
|
|
@@ -1,7 +1,19 @@
|
|
|
1
|
+
import type { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export type OnLoadEventPayload = {
|
|
4
|
+
url: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type <%- project.moduleName %>Events = {
|
|
8
|
+
onChange: (params: ChangeEventPayload) => void;
|
|
9
|
+
};
|
|
10
|
+
|
|
1
11
|
export type ChangeEventPayload = {
|
|
2
12
|
value: string;
|
|
3
13
|
};
|
|
4
14
|
|
|
5
15
|
export type <%- project.viewName %>Props = {
|
|
6
|
-
|
|
16
|
+
url: string;
|
|
17
|
+
onLoad: (event: { nativeEvent: OnLoadEventPayload }) => void;
|
|
18
|
+
style?: StyleProp<ViewStyle>;
|
|
7
19
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireNativeView } from 'expo';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
|
|
4
4
|
import { <%- project.viewName %>Props } from './<%- project.name %>.types';
|
|
5
5
|
|
|
6
6
|
const NativeView: React.ComponentType<<%- project.viewName %>Props> =
|
|
7
|
-
|
|
7
|
+
requireNativeView('<%- project.name %>');
|
|
8
8
|
|
|
9
9
|
export default function <%- project.viewName %>(props: <%- project.viewName %>Props) {
|
|
10
10
|
return <NativeView {...props} />;
|
|
@@ -5,7 +5,11 @@ import { <%- project.viewName %>Props } from './<%- project.name %>.types';
|
|
|
5
5
|
export default function <%- project.viewName %>(props: <%- project.viewName %>Props) {
|
|
6
6
|
return (
|
|
7
7
|
<div>
|
|
8
|
-
<
|
|
8
|
+
<iframe
|
|
9
|
+
style={{ flex: 1 }}
|
|
10
|
+
src={props.url}
|
|
11
|
+
onLoad={() => props.onLoad({ nativeEvent: { url: props.url } })}
|
|
12
|
+
/>
|
|
9
13
|
</div>
|
|
10
14
|
);
|
|
11
15
|
}
|