diff --git a/ReactWindows/ReactNative.Tests/Bridge/JavaScriptModuleRegistryTests.cs b/ReactWindows/ReactNative.Tests/Bridge/JavaScriptModuleRegistryTests.cs
index 3e816c4a681..2275210dafd 100644
--- a/ReactWindows/ReactNative.Tests/Bridge/JavaScriptModuleRegistryTests.cs
+++ b/ReactWindows/ReactNative.Tests/Bridge/JavaScriptModuleRegistryTests.cs
@@ -2,8 +2,8 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using ReactNative.Bridge;
-using ReactNative.Modules.Core;
using ReactNative.UIManager;
+using ReactNative.UIManager.Events;
using System;
using System.Collections.Generic;
using System.Threading;
diff --git a/ReactWindows/ReactNative.Tests/UIManager/Events/RCTEventEmitterTests.cs b/ReactWindows/ReactNative.Tests/UIManager/Events/RCTEventEmitterTests.cs
index 0aa914c28f7..ed028631409 100644
--- a/ReactWindows/ReactNative.Tests/UIManager/Events/RCTEventEmitterTests.cs
+++ b/ReactWindows/ReactNative.Tests/UIManager/Events/RCTEventEmitterTests.cs
@@ -1,6 +1,6 @@
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Newtonsoft.Json.Linq;
-using ReactNative.Modules.Core;
+using ReactNative.UIManager.Events;
namespace ReactNative.Tests.UIManager.Events
{
diff --git a/ReactWindows/ReactNative/CoreModulesPackage.cs b/ReactWindows/ReactNative/CoreModulesPackage.cs
index 15a873ee454..70aa28cdbba 100644
--- a/ReactWindows/ReactNative/CoreModulesPackage.cs
+++ b/ReactWindows/ReactNative/CoreModulesPackage.cs
@@ -2,6 +2,7 @@
using ReactNative.Modules.Core;
using ReactNative.Tracing;
using ReactNative.UIManager;
+using ReactNative.UIManager.Events;
using System;
using System.Collections.Generic;
using Windows.UI.Xaml;
diff --git a/ReactWindows/ReactNative/ReactNative.csproj b/ReactWindows/ReactNative/ReactNative.csproj
index b81aa4bd673..14b5a3a2bc7 100644
--- a/ReactWindows/ReactNative/ReactNative.csproj
+++ b/ReactWindows/ReactNative/ReactNative.csproj
@@ -200,6 +200,9 @@
+
+
+
@@ -210,6 +213,7 @@
+
diff --git a/ReactWindows/ReactNative/UIManager/Events/RCTEventEmitter.cs b/ReactWindows/ReactNative/UIManager/Events/RCTEventEmitter.cs
index 06e98e780dc..b4981ea83a1 100644
--- a/ReactWindows/ReactNative/UIManager/Events/RCTEventEmitter.cs
+++ b/ReactWindows/ReactNative/UIManager/Events/RCTEventEmitter.cs
@@ -1,7 +1,7 @@
using Newtonsoft.Json.Linq;
using ReactNative.Bridge;
-namespace ReactNative.Modules.Core
+namespace ReactNative.UIManager.Events
{
///
/// JavaScript event emitter.
diff --git a/ReactWindows/ReactNative/UIManager/Events/TouchEventType.cs b/ReactWindows/ReactNative/UIManager/Events/TouchEventType.cs
new file mode 100644
index 00000000000..4d6da72d38c
--- /dev/null
+++ b/ReactWindows/ReactNative/UIManager/Events/TouchEventType.cs
@@ -0,0 +1,29 @@
+namespace ReactNative.UIManager.Events
+{
+ ///
+ /// Touch event types that the JavaScript module
+ /// understands.
+ ///
+ public enum TouchEventType
+ {
+ ///
+ /// Touch start event type.
+ ///
+ Start,
+
+ ///
+ /// Touch end event type.
+ ///
+ End,
+
+ ///
+ /// Touch move event type.
+ ///
+ Move,
+
+ ///
+ /// Touch cancel event type.
+ ///
+ Cancel,
+ }
+}
diff --git a/ReactWindows/ReactNative/UIManager/Events/TouchEventTypeExtensions.cs b/ReactWindows/ReactNative/UIManager/Events/TouchEventTypeExtensions.cs
new file mode 100644
index 00000000000..95b14aa07ae
--- /dev/null
+++ b/ReactWindows/ReactNative/UIManager/Events/TouchEventTypeExtensions.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace ReactNative.UIManager.Events
+{
+ static class TouchEventTypeExtensions
+ {
+ public static string GetJavaScriptEventName(this TouchEventType eventType)
+ {
+ switch (eventType)
+ {
+ case TouchEventType.Start:
+ return "topTouchStart";
+ case TouchEventType.End:
+ return "topTouchEnd";
+ case TouchEventType.Move:
+ return "topTouchMove";
+ case TouchEventType.Cancel:
+ return "topTouchCancel";
+ default:
+ throw new NotSupportedException("Unsupported touch event type.");
+ }
+ }
+ }
+}
diff --git a/ReactWindows/ReactNative/UIManager/PointerEvents.cs b/ReactWindows/ReactNative/UIManager/PointerEvents.cs
new file mode 100644
index 00000000000..46eb00f42b9
--- /dev/null
+++ b/ReactWindows/ReactNative/UIManager/PointerEvents.cs
@@ -0,0 +1,30 @@
+namespace ReactNative.UIManager
+{
+ ///
+ /// Possible values for pointer events that a view and its descendants should
+ /// receive. See https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
+ /// for more information.
+ ///
+ public enum PointerEvents
+ {
+ ///
+ /// Neither the container nor its children receive events.
+ ///
+ None,
+
+ ///
+ /// Container does not get events but all its children do.
+ ///
+ BoxNone,
+
+ ///
+ /// Container gets events but none of its children do.
+ ///
+ BoxOnly,
+
+ ///
+ /// Container and all of its children receive touch events.
+ ///
+ Auto,
+ }
+}
diff --git a/ReactWindows/ReactNative/UIManager/UIManagerModule.Constants.cs b/ReactWindows/ReactNative/UIManager/UIManagerModule.Constants.cs
new file mode 100644
index 00000000000..ede80c6a214
--- /dev/null
+++ b/ReactWindows/ReactNative/UIManager/UIManagerModule.Constants.cs
@@ -0,0 +1,260 @@
+using ReactNative.UIManager.Events;
+using System.Collections.Generic;
+
+namespace ReactNative.UIManager
+{
+ using Windows.UI.Xaml;
+ using Map = Dictionary;
+
+ public partial class UIManagerModule
+ {
+ private const string CUSTOM_BUBBLING_EVENT_TYPES_KEY = "customBubblingEventTypes";
+ private const string CUSTOM_DIRECT_EVENT_TYPES_KEY = "customDirectEventTypes";
+
+ public const string ACTION_DISMISSED = "dismissed";
+ public const string ACTION_ITEM_SELECTED = "itemSelected";
+
+ public static IDictionary CreateConstants(IReadOnlyList> viewManagers)
+ {
+ var constants = GetConstants();
+ var bubblingEventTypesConstants = GetBubblingEventTypeConstants();
+ var directEventTypesConstants = GetDirectEventTypeConstants();
+
+ foreach (var viewManager in viewManagers)
+ {
+ // TODO: add view manager exports
+ }
+
+ constants.Add(CUSTOM_BUBBLING_EVENT_TYPES_KEY, bubblingEventTypesConstants);
+ constants.Add(CUSTOM_DIRECT_EVENT_TYPES_KEY, directEventTypesConstants);
+
+ return constants;
+ }
+
+ public static IDictionary GetBubblingEventTypeConstants()
+ {
+ return new Map
+ {
+ {
+ "topChange",
+ new Map
+ {
+ {
+ "phasedRegistrationNames",
+ new Map
+ {
+ { "bubbled", "onChange" },
+ { "captured", "onChangeCapture" },
+ }
+ }
+ }
+ },
+ {
+ "topSelect",
+ new Map
+ {
+ {
+ "phasedRegistrationNames",
+ new Map
+ {
+ { "bubbled", "onSelect" },
+ { "captured", "onSelectCapture" },
+ }
+ }
+ }
+ },
+ {
+ TouchEventType.Start.GetJavaScriptEventName(),
+ new Map
+ {
+ {
+ "phasedRegistrationName",
+ new Map
+ {
+ { "bubbled", "onTouchStart" },
+ { "captured", "onTouchStartCapture" },
+ }
+ }
+ }
+ },
+ {
+ TouchEventType.Move.GetJavaScriptEventName(),
+ new Map
+ {
+ {
+ "phasedRegistrationName",
+ new Map
+ {
+ { "bubbled", "onTouchMove" },
+ { "captured", "onTouchMoveCapture" },
+ }
+ }
+ }
+ },
+ {
+ TouchEventType.Start.GetJavaScriptEventName(),
+ new Map
+ {
+ {
+ "phasedRegistrationName",
+ new Map
+ {
+ { "bubbled", "onTouchEnd" },
+ { "captured", "onTouchEndCapture" },
+ }
+ }
+ }
+ },
+ };
+ }
+
+ public static IDictionary GetDirectEventTypeConstants()
+ {
+ return new Map
+ {
+ {
+ "topSelectionChange",
+ new Map
+ {
+ { "registrationName", "onSelectionChange" },
+ }
+ },
+ {
+ "topLoadingStart",
+ new Map
+ {
+ { "registrationName", "onLoadingStart" },
+ }
+ },
+ {
+ "topLoadingFinish",
+ new Map
+ {
+ { "registrationName", "onLoadingFinish" },
+ }
+ },
+ {
+ "topLoadingError",
+ new Map
+ {
+ { "registrationName", "onLoadingError" },
+ }
+ },
+ {
+ "topLayout",
+ new Map
+ {
+ { "registrationName", "onLayout" },
+ }
+ },
+ };
+ }
+
+ public static IDictionary GetConstants()
+ {
+ return new Map
+ {
+ {
+ "UIView",
+ new Map
+ {
+ {
+ "ContentMode",
+ new Map
+ {
+ /* TODO: declare content mode properties */
+ }
+ },
+ }
+ },
+ {
+ "UIText",
+ new Map
+ {
+ {
+ "AutocapitalizationType",
+ new Map
+ {
+ /* TODO: declare capitalization types */
+ }
+ },
+ }
+ },
+ {
+ "Dimensions",
+ new Map
+ {
+ {
+ "window",
+ new Dictionary
+ {
+ { "width", 100 },
+ { "height", 100 },
+ { "scale", 1 },
+ /* TODO: verify values? */
+ /* TODO: density and DPI needed? */
+ }
+ },
+ }
+ },
+ {
+ "StyleConstants",
+ new Map
+ {
+ {
+ "PointerEventsValues",
+ new Map
+ {
+ { "none", PointerEvents.None.ToString() },
+ { "boxNone", PointerEvents.BoxNone.ToString() },
+ { "boxOnly", PointerEvents.BoxOnly.ToString() },
+ { "unspecified", PointerEvents.Auto.ToString() },
+ }
+ },
+ }
+ },
+ {
+ "PopupMenu",
+ new Map
+ {
+ { ACTION_DISMISSED, ACTION_DISMISSED },
+ { ACTION_ITEM_SELECTED, ACTION_ITEM_SELECTED },
+ }
+ },
+ {
+ "AccessibilityEventTypes",
+ new Map
+ {
+ /* TODO: declare accessibility event types */
+ }
+ },
+ };
+ }
+
+ private static void RecursiveMerge(IDictionary sink, IDictionary source)
+ {
+ foreach (var pair in source)
+ {
+ var existing = default(object);
+ if (sink.TryGetValue(pair.Key, out existing))
+ {
+ var sourceAsMap = pair.Value as IDictionary;
+ var sinkAsMap = existing as IDictionary;
+ if (sourceAsMap != null && sinkAsMap != null)
+ {
+ RecursiveMerge(sinkAsMap, sourceAsMap);
+ }
+ else
+ {
+ // TODO: replace with exception?
+ sink.Add(pair.Key, pair.Value);
+ }
+ }
+ else
+ {
+ sink.Add(pair.Key, pair.Value);
+ }
+ }
+ }
+ }
+}
diff --git a/ReactWindows/ReactNative/UIManager/UIManagerModule.cs b/ReactWindows/ReactNative/UIManager/UIManagerModule.cs
index a0cb9480a47..53117166df9 100644
--- a/ReactWindows/ReactNative/UIManager/UIManagerModule.cs
+++ b/ReactWindows/ReactNative/UIManager/UIManagerModule.cs
@@ -9,16 +9,19 @@ namespace ReactNative.UIManager
///
/// Native module to allow JS to create and update native Views.
///
- public class UIManagerModule : NativeModuleBase
+ public partial class UIManagerModule : NativeModuleBase
{
- private readonly UIImplementation _UIImplementation;
+ private readonly UIImplementation _uiImplementation;
+ private readonly IDictionary _moduleConstants;
+
private int nextRootTag = 1;
public UIManagerModule(ReactApplicationContext reactContext,
IReadOnlyList> viewManagerList,
UIImplementation uiImplementation)
{
- _UIImplementation = uiImplementation;
+ _uiImplementation = uiImplementation;
+ _moduleConstants = CreateConstants(viewManagerList);
}
public override string Name