1import React from 'react';
2import { findNodeHandle, NativeModules, requireNativeComponent } from 'react-native';
3import { requireNativeModule } from './requireNativeModule';
4/**
5 * A map that caches registered native components.
6 */
7const nativeComponentsCache = new Map();
8/**
9 * Requires a React Native component from cache if possible. This prevents
10 * "Tried to register two views with the same name" errors on fast refresh, but
11 * also when there are multiple versions of the same package with native component.
12 */
13function requireCachedNativeComponent(viewName) {
14    const cachedNativeComponent = nativeComponentsCache.get(viewName);
15    if (!cachedNativeComponent) {
16        const nativeComponent = requireNativeComponent(viewName);
17        nativeComponentsCache.set(viewName, nativeComponent);
18        return nativeComponent;
19    }
20    return cachedNativeComponent;
21}
22/**
23 * A drop-in replacement for `requireNativeComponent`.
24 */
25export function requireNativeViewManager(viewName) {
26    const { viewManagersMetadata } = NativeModules.NativeUnimoduleProxy;
27    const viewManagerConfig = viewManagersMetadata?.[viewName];
28    if (__DEV__ && !viewManagerConfig) {
29        const exportedViewManagerNames = Object.keys(viewManagersMetadata).join(', ');
30        console.warn(`The native view manager required by name (${viewName}) from NativeViewManagerAdapter isn't exported by expo-modules-core. Views of this type may not render correctly. Exported view managers: [${exportedViewManagerNames}].`);
31    }
32    // Set up the React Native native component, which is an adapter to the universal module's view
33    // manager
34    const reactNativeViewName = `ViewManagerAdapter_${viewName}`;
35    const ReactNativeComponent = requireCachedNativeComponent(reactNativeViewName);
36    const proxiedPropsNames = viewManagerConfig?.propsNames ?? [];
37    class NativeComponent extends React.PureComponent {
38        static displayName = viewName;
39        // This will be accessed from native when the prototype functions are called,
40        // in order to find the associated native view.
41        nativeTag = null;
42        componentDidMount() {
43            this.nativeTag = findNodeHandle(this);
44        }
45        render() {
46            const nativeProps = omit(this.props, proxiedPropsNames);
47            const proxiedProps = pick(this.props, proxiedPropsNames);
48            return React.createElement(ReactNativeComponent, { ...nativeProps, proxiedProperties: proxiedProps });
49        }
50    }
51    try {
52        const nativeModule = requireNativeModule(viewName);
53        const nativeViewPrototype = nativeModule.ViewPrototype;
54        if (nativeViewPrototype) {
55            // Temporarily each function is wrapped to pass the native tag as the argument.
56            // In the future, native will automatically get the tag from `this` and then we can simply use
57            // `Object.assign(NativeComponent.prototype, nativeViewPrototype)` instead.
58            for (const key of Object.getOwnPropertyNames(nativeViewPrototype)) {
59                NativeComponent.prototype[key] = function (...args) {
60                    return nativeViewPrototype[key].call(this, this.nativeTag, ...args);
61                };
62            }
63        }
64    }
65    catch {
66        // `requireNativeModule` may throw an error when the native module cannot be found.
67        // In some tests we don't mock the entire modules, but we do want to mock native views. For now,
68        // until we still have to support the legacy modules proxy and don't have better ways to mock,
69        // let's just gracefully skip assigning the prototype functions.
70        // See: https://github.com/expo/expo/blob/main/packages/expo-modules-core/src/__tests__/NativeViewManagerAdapter-test.native.tsx
71    }
72    return NativeComponent;
73}
74function omit(props, propNames) {
75    const copied = { ...props };
76    for (const propName of propNames) {
77        delete copied[propName];
78    }
79    return copied;
80}
81function pick(props, propNames) {
82    return propNames.reduce((prev, curr) => {
83        if (curr in props) {
84            prev[curr] = props[curr];
85        }
86        return prev;
87    }, {});
88}
89//# sourceMappingURL=NativeViewManagerAdapter.native.js.map