UNPKG

3.14 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @format
8 * @flow strict-local
9 */
10
11/* eslint-disable react-internal/warning-and-invariant-args */
12
13'use strict';
14
15import type {
16 ReactNativeBaseComponentViewConfig,
17 ViewConfigGetter,
18} from './ReactNativeTypes';
19
20const invariant = require('invariant');
21
22// Event configs
23const customBubblingEventTypes: $TEMPORARY$object<{||}> = {};
24const customDirectEventTypes: $TEMPORARY$object<{||}> = {};
25
26exports.customBubblingEventTypes = customBubblingEventTypes;
27exports.customDirectEventTypes = customDirectEventTypes;
28
29const viewConfigCallbacks = new Map();
30const viewConfigs = new Map();
31
32function processEventTypes(
33 viewConfig: ReactNativeBaseComponentViewConfig<>,
34): void {
35 const {bubblingEventTypes, directEventTypes} = viewConfig;
36
37 if (__DEV__) {
38 if (bubblingEventTypes != null && directEventTypes != null) {
39 for (const topLevelType in directEventTypes) {
40 invariant(
41 bubblingEventTypes[topLevelType] == null,
42 'Event cannot be both direct and bubbling: %s',
43 topLevelType,
44 );
45 }
46 }
47 }
48
49 if (bubblingEventTypes != null) {
50 for (const topLevelType in bubblingEventTypes) {
51 if (customBubblingEventTypes[topLevelType] == null) {
52 customBubblingEventTypes[topLevelType] =
53 bubblingEventTypes[topLevelType];
54 }
55 }
56 }
57
58 if (directEventTypes != null) {
59 for (const topLevelType in directEventTypes) {
60 if (customDirectEventTypes[topLevelType] == null) {
61 customDirectEventTypes[topLevelType] = directEventTypes[topLevelType];
62 }
63 }
64 }
65}
66
67/**
68 * Registers a native view/component by name.
69 * A callback is provided to load the view config from UIManager.
70 * The callback is deferred until the view is actually rendered.
71 */
72exports.register = function(name: string, callback: ViewConfigGetter): string {
73 invariant(
74 !viewConfigCallbacks.has(name),
75 'Tried to register two views with the same name %s',
76 name,
77 );
78 viewConfigCallbacks.set(name, callback);
79 return name;
80};
81
82/**
83 * Retrieves a config for the specified view.
84 * If this is the first time the view has been used,
85 * This configuration will be lazy-loaded from UIManager.
86 */
87exports.get = function(name: string): ReactNativeBaseComponentViewConfig<> {
88 let viewConfig;
89 if (!viewConfigs.has(name)) {
90 const callback = viewConfigCallbacks.get(name);
91 if (typeof callback !== 'function') {
92 invariant(
93 false,
94 'View config not found for name %s.%s',
95 name,
96 typeof name[0] === 'string' && /[a-z]/.test(name[0])
97 ? ' Make sure to start component names with a capital letter.'
98 : '',
99 );
100 }
101 viewConfigCallbacks.set(name, null);
102 viewConfig = callback();
103 processEventTypes(viewConfig);
104 viewConfigs.set(name, viewConfig);
105 } else {
106 viewConfig = viewConfigs.get(name);
107 }
108 invariant(viewConfig, 'View config not found for name %s', name);
109 return viewConfig;
110};