@natsuneko-laboratory/react-native-desktop-navigation 0.1.0-alpha.12
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/DesktopNavigation.podspec +18 -0
- package/LICENSE +21 -0
- package/NATIVE.md +300 -0
- package/README.md +127 -0
- package/dist/core/NavigationContainer.d.ts +23 -0
- package/dist/core/NavigationContainer.js +68 -0
- package/dist/core/NavigationItem.d.ts +27 -0
- package/dist/core/NavigationItem.js +71 -0
- package/dist/core/Scene.d.ts +19 -0
- package/dist/core/Scene.js +124 -0
- package/dist/core/SelectionNavigator.d.ts +38 -0
- package/dist/core/SelectionNavigator.js +194 -0
- package/dist/core/builder.d.ts +40 -0
- package/dist/core/builder.js +81 -0
- package/dist/core/context.d.ts +26 -0
- package/dist/core/context.js +36 -0
- package/dist/core/focus.d.ts +14 -0
- package/dist/core/focus.js +39 -0
- package/dist/core/hooks.d.ts +8 -0
- package/dist/core/hooks.js +48 -0
- package/dist/core/navigation.d.ts +6 -0
- package/dist/core/navigation.js +57 -0
- package/dist/core/store.d.ts +39 -0
- package/dist/core/store.js +391 -0
- package/dist/core/types.d.ts +155 -0
- package/dist/core/types.js +2 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +46 -0
- package/dist/native/host.d.ts +100 -0
- package/dist/native/host.js +190 -0
- package/dist/native/icons.d.ts +56 -0
- package/dist/native/icons.js +55 -0
- package/dist/native/index.d.ts +13 -0
- package/dist/native/index.js +44 -0
- package/dist/native/sidebar.d.ts +39 -0
- package/dist/native/sidebar.js +126 -0
- package/dist/native/specs/DesktopNavigationHostNativeComponent.d.ts +10 -0
- package/dist/native/specs/DesktopNavigationHostNativeComponent.js +4 -0
- package/dist/native/split.d.ts +27 -0
- package/dist/native/split.js +105 -0
- package/dist/native/stack.d.ts +26 -0
- package/dist/native/stack.js +66 -0
- package/dist/platform/index.d.ts +52 -0
- package/dist/platform/index.js +28 -0
- package/dist/platform/macos.d.ts +2 -0
- package/dist/platform/macos.js +18 -0
- package/dist/platform/windows.d.ts +2 -0
- package/dist/platform/windows.js +18 -0
- package/dist/routers/index.d.ts +23 -0
- package/dist/routers/index.js +393 -0
- package/dist/routers/types.d.ts +116 -0
- package/dist/routers/types.js +2 -0
- package/dist/sidebar/index.d.ts +17 -0
- package/dist/sidebar/index.js +18 -0
- package/dist/split/index.d.ts +42 -0
- package/dist/split/index.js +199 -0
- package/dist/stack/index.d.ts +23 -0
- package/dist/stack/index.js +88 -0
- package/dist/tabs/index.d.ts +13 -0
- package/dist/tabs/index.js +15 -0
- package/docs/GUIDE.md +384 -0
- package/macos/DDNNavigationComponentView.h +4 -0
- package/macos/DDNNavigationComponentView.mm +40 -0
- package/macos/DDNNavigationView.swift +398 -0
- package/macos/DDNNavigationViewManager.mm +11 -0
- package/package.json +82 -0
- package/react-native.config.js +19 -0
- package/src/core/NavigationContainer.tsx +137 -0
- package/src/core/NavigationItem.tsx +149 -0
- package/src/core/Scene.tsx +194 -0
- package/src/core/SelectionNavigator.tsx +371 -0
- package/src/core/builder.tsx +147 -0
- package/src/core/context.tsx +43 -0
- package/src/core/focus.tsx +50 -0
- package/src/core/hooks.ts +42 -0
- package/src/core/navigation.ts +77 -0
- package/src/core/store.ts +471 -0
- package/src/core/types.ts +176 -0
- package/src/index.ts +36 -0
- package/src/native/host.tsx +377 -0
- package/src/native/icons.ts +110 -0
- package/src/native/index.ts +56 -0
- package/src/native/sidebar.tsx +230 -0
- package/src/native/specs/DesktopNavigationHostNativeComponent.ts +12 -0
- package/src/native/split.tsx +160 -0
- package/src/native/stack.tsx +157 -0
- package/src/platform/index.tsx +76 -0
- package/src/platform/macos.ts +15 -0
- package/src/platform/windows.ts +15 -0
- package/src/routers/index.ts +442 -0
- package/src/routers/types.ts +117 -0
- package/src/sidebar/index.tsx +42 -0
- package/src/split/index.tsx +350 -0
- package/src/stack/index.tsx +213 -0
- package/src/tabs/index.tsx +40 -0
- package/windows/DesktopNavigation/DesktopNavigation.def +3 -0
- package/windows/DesktopNavigation/DesktopNavigation.vcxproj +125 -0
- package/windows/DesktopNavigation/NavigationHost.cpp +432 -0
- package/windows/DesktopNavigation/ReactPackageProvider.cpp +9 -0
- package/windows/DesktopNavigation/ReactPackageProvider.h +10 -0
- package/windows/DesktopNavigation/ReactPackageProvider.idl +6 -0
- package/windows/DesktopNavigation/pch.cpp +1 -0
- package/windows/DesktopNavigation/pch.h +27 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<?xml version='1.0' encoding='utf-8'?>
|
|
2
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build" ToolsVersion="15.0">
|
|
3
|
+
<Import Project="$(SolutionDir)\ExperimentalFeatures.props" Condition="Exists('$(SolutionDir)\ExperimentalFeatures.props')" />
|
|
4
|
+
<PropertyGroup Label="Globals">
|
|
5
|
+
<CppWinRTOptimized>true</CppWinRTOptimized>
|
|
6
|
+
<MinimalCoreWin>true</MinimalCoreWin>
|
|
7
|
+
<ProjectGuid>{D772993C-4468-49C9-9EBD-C0646B679CAD}</ProjectGuid>
|
|
8
|
+
<ProjectName>DesktopNavigation</ProjectName>
|
|
9
|
+
<Keyword>Win32Proj</Keyword>
|
|
10
|
+
<RootNamespace>DesktopNavigation</RootNamespace>
|
|
11
|
+
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
|
12
|
+
<DefaultLanguage>en-US</DefaultLanguage>
|
|
13
|
+
<MinimumVisualStudioVersion>17.0</MinimumVisualStudioVersion>
|
|
14
|
+
<AppxPackage>false</AppxPackage>
|
|
15
|
+
</PropertyGroup>
|
|
16
|
+
<PropertyGroup Label="ReactNativeWindowsProps">
|
|
17
|
+
<ReactNativeWindowsDir Condition="'$(ReactNativeWindowsDir)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\</ReactNativeWindowsDir>
|
|
18
|
+
<RunAutolinkCheck>false</RunAutolinkCheck>
|
|
19
|
+
</PropertyGroup>
|
|
20
|
+
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.WindowsSdk.Default.props" />
|
|
21
|
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
22
|
+
<ItemGroup Label="ProjectConfigurations">
|
|
23
|
+
<ProjectConfiguration Include="Debug|Win32">
|
|
24
|
+
<Configuration>Debug</Configuration>
|
|
25
|
+
<Platform>Win32</Platform>
|
|
26
|
+
</ProjectConfiguration>
|
|
27
|
+
<ProjectConfiguration Include="Release|Win32">
|
|
28
|
+
<Configuration>Release</Configuration>
|
|
29
|
+
<Platform>Win32</Platform>
|
|
30
|
+
</ProjectConfiguration>
|
|
31
|
+
<ProjectConfiguration Include="Debug|x64">
|
|
32
|
+
<Configuration>Debug</Configuration>
|
|
33
|
+
<Platform>x64</Platform>
|
|
34
|
+
</ProjectConfiguration>
|
|
35
|
+
<ProjectConfiguration Include="Release|x64">
|
|
36
|
+
<Configuration>Release</Configuration>
|
|
37
|
+
<Platform>x64</Platform>
|
|
38
|
+
</ProjectConfiguration>
|
|
39
|
+
<ProjectConfiguration Include="Debug|ARM64">
|
|
40
|
+
<Configuration>Debug</Configuration>
|
|
41
|
+
<Platform>ARM64</Platform>
|
|
42
|
+
</ProjectConfiguration>
|
|
43
|
+
<ProjectConfiguration Include="Release|ARM64">
|
|
44
|
+
<Configuration>Release</Configuration>
|
|
45
|
+
<Platform>ARM64</Platform>
|
|
46
|
+
</ProjectConfiguration>
|
|
47
|
+
</ItemGroup>
|
|
48
|
+
<PropertyGroup Label="Configuration">
|
|
49
|
+
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
50
|
+
<CharacterSet>Unicode</CharacterSet>
|
|
51
|
+
<PlatformToolset>v143</PlatformToolset>
|
|
52
|
+
<GenerateManifest>false</GenerateManifest>
|
|
53
|
+
</PropertyGroup>
|
|
54
|
+
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
|
55
|
+
<UseDebugLibraries>true</UseDebugLibraries>
|
|
56
|
+
</PropertyGroup>
|
|
57
|
+
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
|
58
|
+
<UseDebugLibraries>false</UseDebugLibraries>
|
|
59
|
+
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
60
|
+
</PropertyGroup>
|
|
61
|
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
62
|
+
<ImportGroup Label="ExtensionSettings">
|
|
63
|
+
</ImportGroup>
|
|
64
|
+
<ImportGroup Label="PropertySheets">
|
|
65
|
+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
66
|
+
</ImportGroup>
|
|
67
|
+
<ImportGroup Label="ReactNativeWindowsPropertySheets">
|
|
68
|
+
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.CppLib.props" Condition="Exists('$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.CppLib.props')" />
|
|
69
|
+
</ImportGroup>
|
|
70
|
+
<ItemDefinitionGroup>
|
|
71
|
+
<ClCompile>
|
|
72
|
+
<PrecompiledHeader>Use</PrecompiledHeader>
|
|
73
|
+
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
|
74
|
+
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
|
75
|
+
<WarningLevel>Level4</WarningLevel>
|
|
76
|
+
<SDLCheck>true</SDLCheck>
|
|
77
|
+
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
|
|
78
|
+
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
|
79
|
+
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
80
|
+
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
|
81
|
+
</ClCompile>
|
|
82
|
+
<Link>
|
|
83
|
+
<AdditionalDependencies>shell32.lib;user32.lib;windowsapp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
84
|
+
<SubSystem>Console</SubSystem>
|
|
85
|
+
<GenerateWindowsMetadata>true</GenerateWindowsMetadata>
|
|
86
|
+
<ModuleDefinitionFile>DesktopNavigation.def</ModuleDefinitionFile>
|
|
87
|
+
</Link>
|
|
88
|
+
</ItemDefinitionGroup>
|
|
89
|
+
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
|
90
|
+
<ClCompile>
|
|
91
|
+
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
92
|
+
</ClCompile>
|
|
93
|
+
</ItemDefinitionGroup>
|
|
94
|
+
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
|
95
|
+
<ClCompile>
|
|
96
|
+
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
97
|
+
</ClCompile>
|
|
98
|
+
</ItemDefinitionGroup>
|
|
99
|
+
<PropertyGroup Label="UserMacros" />
|
|
100
|
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
101
|
+
<ImportGroup Label="ReactNativeWindowsTargets">
|
|
102
|
+
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.CppLib.targets" Condition="Exists('$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.CppLib.targets')" />
|
|
103
|
+
</ImportGroup>
|
|
104
|
+
<Target Name="EnsureReactNativeWindowsTargets" BeforeTargets="PrepareForBuild">
|
|
105
|
+
<PropertyGroup>
|
|
106
|
+
<ErrorText>This project references targets in your node_modules\react-native-windows folder. The missing file is {0}.</ErrorText>
|
|
107
|
+
</PropertyGroup>
|
|
108
|
+
<Error Condition="!Exists('$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.CppLib.props')" Text="$([System.String]::Format('$(ErrorText)', '$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.CppLib.props'))" />
|
|
109
|
+
<Error Condition="!Exists('$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.CppLib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.CppLib.targets'))" />
|
|
110
|
+
</Target>
|
|
111
|
+
<ItemGroup>
|
|
112
|
+
<ClInclude Include="pch.h" />
|
|
113
|
+
<ClInclude Include="ReactPackageProvider.h" />
|
|
114
|
+
<ClCompile Include="pch.cpp">
|
|
115
|
+
<PrecompiledHeader>Create</PrecompiledHeader>
|
|
116
|
+
</ClCompile>
|
|
117
|
+
<ClCompile Include="ReactPackageProvider.cpp" />
|
|
118
|
+
<ClCompile Include="NavigationHost.cpp" />
|
|
119
|
+
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
|
120
|
+
<Midl Include="ReactPackageProvider.idl" />
|
|
121
|
+
</ItemGroup>
|
|
122
|
+
<Target Name="RequireNativeNavigationFabric" BeforeTargets="PrepareForBuild">
|
|
123
|
+
<Error Condition="'$(UseNewArchitecture)' != 'true' Or '$(UseExperimentalWinUI3)' != 'true'" Text="DesktopNavigation requires Fabric and XAML islands: set UseNewArchitecture and UseExperimentalWinUI3 to true (RNW 0.82+)." />
|
|
124
|
+
</Target>
|
|
125
|
+
</Project>
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
#include "pch.h"
|
|
2
|
+
|
|
3
|
+
// Fabric's XamlIsland API requires RNW 0.82+ and UseExperimentalWinUI3.
|
|
4
|
+
// React scenes are siblings of this island in the Fabric composition tree.
|
|
5
|
+
// The island reports its content slots; it never owns/reparents React children.
|
|
6
|
+
namespace winrt::DesktopNavigation {
|
|
7
|
+
using namespace Microsoft::ReactNative;
|
|
8
|
+
using namespace Microsoft::ReactNative::Composition;
|
|
9
|
+
using namespace Microsoft::UI::Xaml;
|
|
10
|
+
using namespace Microsoft::UI::Xaml::Controls;
|
|
11
|
+
using namespace Microsoft::UI::Xaml::Controls::Primitives;
|
|
12
|
+
using namespace Microsoft::UI::Xaml::Media;
|
|
13
|
+
using namespace Windows::Data::Json;
|
|
14
|
+
|
|
15
|
+
REACT_STRUCT(HostProps)
|
|
16
|
+
struct HostProps : implements<HostProps, IComponentProps> {
|
|
17
|
+
HostProps(ViewProps props, IComponentProps const &previous) : viewProps(props) {
|
|
18
|
+
if (previous) configuration = previous.as<HostProps>()->configuration;
|
|
19
|
+
}
|
|
20
|
+
void SetProp(uint32_t hash, hstring name, IJSValueReader value) noexcept {
|
|
21
|
+
ReadProp(hash, name, value, *this);
|
|
22
|
+
}
|
|
23
|
+
REACT_FIELD(configuration)
|
|
24
|
+
hstring configuration;
|
|
25
|
+
ViewProps viewProps;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
static void String(JsonObject const &object, wchar_t const *key, hstring const &value) {
|
|
29
|
+
object.SetNamedValue(key, JsonValue::CreateStringValue(value));
|
|
30
|
+
}
|
|
31
|
+
static void Number(JsonObject const &object, wchar_t const *key, double value) {
|
|
32
|
+
object.SetNamedValue(key, JsonValue::CreateNumberValue(value));
|
|
33
|
+
}
|
|
34
|
+
static SolidColorBrush Brush(hstring const &value, Windows::UI::Color fallback) {
|
|
35
|
+
if (value.size() == 7 || value.size() == 9) {
|
|
36
|
+
try {
|
|
37
|
+
auto bits = std::stoull(std::wstring(value.c_str() + 1), nullptr, 16);
|
|
38
|
+
if (value.size() == 7) bits = (bits << 8) | 255;
|
|
39
|
+
return SolidColorBrush({static_cast<uint8_t>(bits & 255), static_cast<uint8_t>((bits >> 24) & 255),
|
|
40
|
+
static_cast<uint8_t>((bits >> 16) & 255), static_cast<uint8_t>((bits >> 8) & 255)});
|
|
41
|
+
} catch (...) {}
|
|
42
|
+
}
|
|
43
|
+
return SolidColorBrush(fallback);
|
|
44
|
+
}
|
|
45
|
+
static IconElement ItemIcon(JsonObject const &item) {
|
|
46
|
+
if (!item.HasKey(L"icon")) return nullptr;
|
|
47
|
+
auto descriptor = item.GetNamedObject(L"icon");
|
|
48
|
+
auto type = descriptor.GetNamedString(L"type", L"");
|
|
49
|
+
auto size = descriptor.GetNamedNumber(L"size", 16);
|
|
50
|
+
IconElement icon{nullptr};
|
|
51
|
+
if (type == L"react") {
|
|
52
|
+
FontIcon placeholder;
|
|
53
|
+
placeholder.Glyph(L" ");
|
|
54
|
+
placeholder.Opacity(0);
|
|
55
|
+
icon = placeholder;
|
|
56
|
+
} else if (type == L"font") {
|
|
57
|
+
FontIcon font;
|
|
58
|
+
font.Glyph(descriptor.GetNamedString(L"glyph"));
|
|
59
|
+
font.FontSize(size);
|
|
60
|
+
// Without an override, WinUI uses SymbolThemeFontFamily (OS fallback).
|
|
61
|
+
auto family = descriptor.GetNamedString(L"fontFamily", L"");
|
|
62
|
+
if (!family.empty()) font.FontFamily(FontFamily(family));
|
|
63
|
+
icon = font;
|
|
64
|
+
} else if (type == L"image") {
|
|
65
|
+
BitmapIcon bitmap;
|
|
66
|
+
bitmap.ShowAsMonochrome(descriptor.GetNamedBoolean(L"template", false));
|
|
67
|
+
try { bitmap.UriSource(Windows::Foundation::Uri(descriptor.GetNamedString(L"uri"))); }
|
|
68
|
+
catch (hresult_error const &) { return nullptr; }
|
|
69
|
+
icon = bitmap;
|
|
70
|
+
}
|
|
71
|
+
if (icon) {
|
|
72
|
+
icon.Width(size); icon.Height(size);
|
|
73
|
+
if (descriptor.HasKey(L"color")) icon.Foreground(Brush(descriptor.GetNamedString(L"color"), {255, 32, 33, 36}));
|
|
74
|
+
Automation::AutomationProperties::SetAccessibilityView(icon, Automation::Peers::AccessibilityView::Raw);
|
|
75
|
+
}
|
|
76
|
+
return icon;
|
|
77
|
+
}
|
|
78
|
+
struct Host : implements<Host, IInspectable> {
|
|
79
|
+
XamlIsland island{nullptr};
|
|
80
|
+
Grid root{nullptr};
|
|
81
|
+
EventEmitter emitter{nullptr};
|
|
82
|
+
JsonObject config;
|
|
83
|
+
bool updating = false;
|
|
84
|
+
hstring structure;
|
|
85
|
+
hstring lastLayout;
|
|
86
|
+
NavigationView navigation{nullptr};
|
|
87
|
+
SplitView split{nullptr};
|
|
88
|
+
Button back{nullptr};
|
|
89
|
+
TextBlock title{nullptr};
|
|
90
|
+
Grid header{nullptr};
|
|
91
|
+
Border content{nullptr};
|
|
92
|
+
Border footer{nullptr};
|
|
93
|
+
std::map<hstring, NavigationViewItem> menu;
|
|
94
|
+
std::map<hstring, hstring> iconConfigurations;
|
|
95
|
+
std::map<hstring, Border> slots;
|
|
96
|
+
std::vector<ColumnDefinition> detailColumns;
|
|
97
|
+
event_token layoutToken{};
|
|
98
|
+
std::vector<std::pair<ScrollViewer, event_token>> scrollObservers;
|
|
99
|
+
void ClearScrollObservers() {
|
|
100
|
+
for (auto const &[viewer, token] : scrollObservers) viewer.ViewChanged(token);
|
|
101
|
+
scrollObservers.clear();
|
|
102
|
+
}
|
|
103
|
+
void ObserveScroll(ScrollViewer const &viewer) {
|
|
104
|
+
for (auto const &entry : scrollObservers) if (entry.first == viewer) return;
|
|
105
|
+
auto token = viewer.ViewChanged([this](auto const &, auto const &) { ReportLayout(); });
|
|
106
|
+
scrollObservers.emplace_back(viewer, token);
|
|
107
|
+
}
|
|
108
|
+
static Windows::Foundation::Rect Intersect(Windows::Foundation::Rect a, Windows::Foundation::Rect b) {
|
|
109
|
+
auto x = std::max(a.X, b.X), y = std::max(a.Y, b.Y);
|
|
110
|
+
return {x, y, std::max(0.0f, std::min(a.X + a.Width, b.X + b.Width) - x),
|
|
111
|
+
std::max(0.0f, std::min(a.Y + a.Height, b.Y + b.Height) - y)};
|
|
112
|
+
}
|
|
113
|
+
Windows::Foundation::Rect Bounds(FrameworkElement const &element) {
|
|
114
|
+
return element.TransformToVisual(root).TransformBounds({0, 0,
|
|
115
|
+
static_cast<float>(element.ActualWidth()), static_cast<float>(element.ActualHeight())});
|
|
116
|
+
}
|
|
117
|
+
static JsonObject RectJSON(Windows::Foundation::Rect rect) {
|
|
118
|
+
JsonObject value;
|
|
119
|
+
Number(value, L"x", rect.X); Number(value, L"y", rect.Y);
|
|
120
|
+
Number(value, L"width", rect.Width); Number(value, L"height", rect.Height);
|
|
121
|
+
return value;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
void Initialize(ContentIslandComponentView const &view) {
|
|
125
|
+
root = Grid();
|
|
126
|
+
island = XamlIsland();
|
|
127
|
+
island.Content(root);
|
|
128
|
+
view.Connect(island.ContentIsland());
|
|
129
|
+
layoutToken = root.LayoutUpdated([this](auto const &, auto const &) { ReportLayout(); });
|
|
130
|
+
}
|
|
131
|
+
void Close() {
|
|
132
|
+
updating = true;
|
|
133
|
+
ClearScrollObservers();
|
|
134
|
+
root.LayoutUpdated(layoutToken);
|
|
135
|
+
island.Close();
|
|
136
|
+
emitter = nullptr;
|
|
137
|
+
}
|
|
138
|
+
void Send(JsonObject message) {
|
|
139
|
+
if (updating || !emitter) return;
|
|
140
|
+
Number(message, L"revision", config.GetNamedNumber(L"revision", 0));
|
|
141
|
+
auto payload = message.Stringify();
|
|
142
|
+
emitter.DispatchEvent(L"navigationEvent", [payload](IJSValueWriter const &writer) {
|
|
143
|
+
writer.WriteObjectBegin();
|
|
144
|
+
writer.WritePropertyName(L"payload");
|
|
145
|
+
writer.WriteString(payload);
|
|
146
|
+
writer.WriteObjectEnd();
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
void Request(wchar_t const *type) { JsonObject event; String(event, L"type", type); Send(event); }
|
|
150
|
+
void Collapsed(bool value) {
|
|
151
|
+
if (value == config.GetNamedBoolean(L"collapsed", false)) return;
|
|
152
|
+
JsonObject event; String(event, L"type", L"collapse");
|
|
153
|
+
event.SetNamedValue(L"collapsed", JsonValue::CreateBooleanValue(value)); Send(event);
|
|
154
|
+
}
|
|
155
|
+
void Resize(hstring const &key, double width) {
|
|
156
|
+
JsonObject event; String(event, L"type", L"resize"); String(event, L"key", key);
|
|
157
|
+
Number(event, L"width", width); Send(event);
|
|
158
|
+
}
|
|
159
|
+
Border Slot(hstring const &key) {
|
|
160
|
+
Border slot;
|
|
161
|
+
slot.HorizontalAlignment(HorizontalAlignment::Stretch);
|
|
162
|
+
slot.VerticalAlignment(VerticalAlignment::Stretch);
|
|
163
|
+
slots.emplace(key, slot);
|
|
164
|
+
return slot;
|
|
165
|
+
}
|
|
166
|
+
void ReportLayout() {
|
|
167
|
+
if (updating || !emitter || !root || root.ActualWidth() <= 0) return;
|
|
168
|
+
JsonObject frames;
|
|
169
|
+
for (auto const &[key, slot] : slots) {
|
|
170
|
+
auto offset = slot.TransformToVisual(root).TransformPoint({0, 0});
|
|
171
|
+
JsonObject frame;
|
|
172
|
+
Number(frame, L"x", offset.X); Number(frame, L"y", offset.Y);
|
|
173
|
+
Number(frame, L"width", slot.ActualWidth()); Number(frame, L"height", slot.ActualHeight());
|
|
174
|
+
frames.SetNamedValue(key, frame);
|
|
175
|
+
}
|
|
176
|
+
JsonObject iconFrames;
|
|
177
|
+
for (auto const &[key, item] : menu) {
|
|
178
|
+
auto descriptor = iconConfigurations.find(key);
|
|
179
|
+
if (descriptor == iconConfigurations.end() || descriptor->second.empty()) continue;
|
|
180
|
+
if (JsonObject::Parse(descriptor->second).GetNamedString(L"type", L"") != L"react") continue;
|
|
181
|
+
auto icon = item.Icon();
|
|
182
|
+
if (!icon || !icon.IsLoaded() || icon.ActualWidth() <= 0) continue;
|
|
183
|
+
auto frame = Bounds(icon);
|
|
184
|
+
auto clip = Intersect(frame, Bounds(root));
|
|
185
|
+
auto ancestor = VisualTreeHelper::GetParent(icon);
|
|
186
|
+
while (ancestor && ancestor != root) {
|
|
187
|
+
if (auto element = ancestor.try_as<FrameworkElement>()) {
|
|
188
|
+
if (element.Visibility() != Visibility::Visible) { clip.Width = 0; clip.Height = 0; }
|
|
189
|
+
// Includes NavigationView's menu viewport and compact-pane bounds.
|
|
190
|
+
if (auto viewer = element.try_as<ScrollViewer>()) {
|
|
191
|
+
ObserveScroll(viewer);
|
|
192
|
+
clip = Intersect(clip, Bounds(viewer));
|
|
193
|
+
}
|
|
194
|
+
if (element.try_as<ScrollContentPresenter>()) clip = Intersect(clip, Bounds(element));
|
|
195
|
+
if (auto geometry = element.Clip().try_as<RectangleGeometry>()) {
|
|
196
|
+
clip = Intersect(clip, element.TransformToVisual(root).TransformBounds(geometry.Rect()));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
ancestor = VisualTreeHelper::GetParent(ancestor);
|
|
200
|
+
}
|
|
201
|
+
if (ancestor != root) continue;
|
|
202
|
+
JsonObject geometry;
|
|
203
|
+
geometry.SetNamedValue(L"frame", RectJSON(frame)); geometry.SetNamedValue(L"clip", RectJSON(clip));
|
|
204
|
+
iconFrames.SetNamedValue(key, geometry);
|
|
205
|
+
}
|
|
206
|
+
JsonObject event; String(event, L"type", L"layout");
|
|
207
|
+
Number(event, L"revision", config.GetNamedNumber(L"revision", 0));
|
|
208
|
+
event.SetNamedValue(L"frames", frames);
|
|
209
|
+
event.SetNamedValue(L"iconFrames", iconFrames);
|
|
210
|
+
if (navigation && footer && navigation.IsPaneOpen() && footer.Visibility() == Visibility::Visible &&
|
|
211
|
+
footer.IsLoaded() && footer.ActualWidth() > 0 && footer.ActualHeight() > 0) {
|
|
212
|
+
event.SetNamedValue(L"footerFrame", RectJSON(Intersect(Bounds(footer), Bounds(root))));
|
|
213
|
+
}
|
|
214
|
+
auto serialized = event.Stringify();
|
|
215
|
+
if (serialized == lastLayout) return;
|
|
216
|
+
lastLayout = serialized;
|
|
217
|
+
Send(event);
|
|
218
|
+
}
|
|
219
|
+
void BuildStack() {
|
|
220
|
+
RowDefinition heading; heading.Height({1, GridUnitType::Auto});
|
|
221
|
+
RowDefinition body; body.Height({1, GridUnitType::Star});
|
|
222
|
+
root.RowDefinitions().Append(heading); root.RowDefinitions().Append(body);
|
|
223
|
+
header = Grid(); header.MinHeight(44); header.Padding({10, 6, 10, 6});
|
|
224
|
+
back = Button(); back.HorizontalAlignment(HorizontalAlignment::Left);
|
|
225
|
+
back.Click([this](auto const &, auto const &) { Request(L"back"); });
|
|
226
|
+
title = TextBlock(); title.HorizontalAlignment(HorizontalAlignment::Center);
|
|
227
|
+
title.VerticalAlignment(VerticalAlignment::Center);
|
|
228
|
+
header.Children().Append(back); header.Children().Append(title);
|
|
229
|
+
root.Children().Append(header);
|
|
230
|
+
content = Slot(config.GetNamedString(L"activeKey")); Grid::SetRow(content, 1);
|
|
231
|
+
root.Children().Append(content);
|
|
232
|
+
}
|
|
233
|
+
void BuildSidebar(JsonArray const &items) {
|
|
234
|
+
navigation = NavigationView();
|
|
235
|
+
navigation.IsSettingsVisible(false);
|
|
236
|
+
navigation.IsBackButtonVisible(NavigationViewBackButtonVisible::Collapsed);
|
|
237
|
+
navigation.AlwaysShowHeader(false);
|
|
238
|
+
navigation.PaneDisplayMode(NavigationViewPaneDisplayMode::Left);
|
|
239
|
+
hstring section;
|
|
240
|
+
for (auto const &entry : items) {
|
|
241
|
+
auto item = entry.GetObject();
|
|
242
|
+
if (item.GetNamedBoolean(L"hidden", false)) continue;
|
|
243
|
+
auto heading = item.GetNamedString(L"section", L"");
|
|
244
|
+
if (!heading.empty() && heading != section) {
|
|
245
|
+
NavigationViewItemHeader group; group.Content(box_value(heading));
|
|
246
|
+
navigation.MenuItems().Append(group);
|
|
247
|
+
}
|
|
248
|
+
section = heading;
|
|
249
|
+
NavigationViewItem control; auto key = item.GetNamedString(L"key");
|
|
250
|
+
control.Tag(box_value(key)); navigation.MenuItems().Append(control); menu.emplace(key, control);
|
|
251
|
+
}
|
|
252
|
+
navigation.SelectionChanged([this](auto const &, NavigationViewSelectionChangedEventArgs const &args) {
|
|
253
|
+
auto item = args.SelectedItem().try_as<NavigationViewItem>();
|
|
254
|
+
if (!item) return;
|
|
255
|
+
JsonObject event; String(event, L"type", L"select");
|
|
256
|
+
String(event, L"key", unbox_value<hstring>(item.Tag())); Send(event);
|
|
257
|
+
});
|
|
258
|
+
navigation.PaneOpened([this](auto const &, auto const &) { Collapsed(false); });
|
|
259
|
+
navigation.PaneClosed([this](auto const &, auto const &) { Collapsed(true); });
|
|
260
|
+
// An empty, measured placeholder; the React footer is composited over it.
|
|
261
|
+
footer = Border(); footer.HorizontalAlignment(HorizontalAlignment::Stretch);
|
|
262
|
+
Automation::AutomationProperties::SetAccessibilityView(footer, Automation::Peers::AccessibilityView::Raw);
|
|
263
|
+
navigation.PaneFooter(footer);
|
|
264
|
+
content = Slot(config.GetNamedString(L"activeKey"));
|
|
265
|
+
navigation.Content(content); root.Children().Append(navigation);
|
|
266
|
+
}
|
|
267
|
+
Thumb Divider(hstring const &key, std::function<void(double)> resize) {
|
|
268
|
+
Thumb thumb; thumb.Width(6); thumb.HorizontalAlignment(HorizontalAlignment::Right);
|
|
269
|
+
thumb.Background(SolidColorBrush({255, 128, 128, 128}));
|
|
270
|
+
thumb.IsTabStop(true);
|
|
271
|
+
thumb.KeyDown([resize](auto const &, auto const &event) {
|
|
272
|
+
if (event.Key() == Windows::System::VirtualKey::Left || event.Key() == Windows::System::VirtualKey::Right) {
|
|
273
|
+
resize(event.Key() == Windows::System::VirtualKey::Right ? 10 : -10);
|
|
274
|
+
event.Handled(true);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
Automation::AutomationProperties::SetName(thumb, L"Resize " + key);
|
|
278
|
+
thumb.DragDelta([resize](auto const &, DragDeltaEventArgs const &event) { resize(event.HorizontalChange()); });
|
|
279
|
+
return thumb;
|
|
280
|
+
}
|
|
281
|
+
double Clamp(JsonObject const &column, double width) {
|
|
282
|
+
return std::clamp(width, column.GetNamedNumber(L"minWidth", 100), column.GetNamedNumber(L"maxWidth", 100000));
|
|
283
|
+
}
|
|
284
|
+
void BuildSplit(JsonArray const &columns) {
|
|
285
|
+
if (columns.Size() == 1) { root.Children().Append(Slot(columns.GetObjectAt(0).GetNamedString(L"key"))); return; }
|
|
286
|
+
split = SplitView(); split.DisplayMode(SplitViewDisplayMode::Inline); split.IsPaneOpen(true);
|
|
287
|
+
auto first = columns.GetObjectAt(0); auto firstKey = first.GetNamedString(L"key");
|
|
288
|
+
Grid pane;
|
|
289
|
+
auto firstSlot = Slot(firstKey); firstSlot.Margin({0, 0, 6, 0}); pane.Children().Append(firstSlot);
|
|
290
|
+
pane.Children().Append(Divider(firstKey, [this, firstKey](double delta) {
|
|
291
|
+
auto col = config.GetNamedArray(L"columns").GetObjectAt(0);
|
|
292
|
+
auto width = Clamp(col, split.OpenPaneLength() - 6 + delta);
|
|
293
|
+
split.OpenPaneLength(width + 6); Resize(firstKey, width);
|
|
294
|
+
}));
|
|
295
|
+
split.Pane(pane);
|
|
296
|
+
Grid detail;
|
|
297
|
+
for (uint32_t index = 1; index < columns.Size(); ++index) {
|
|
298
|
+
auto column = columns.GetObjectAt(index); auto key = column.GetNamedString(L"key");
|
|
299
|
+
ColumnDefinition definition;
|
|
300
|
+
definition.Width(index + 1 == columns.Size() ? GridLength{1, GridUnitType::Star} : GridLength{column.GetNamedNumber(L"width"), GridUnitType::Pixel});
|
|
301
|
+
definition.MinWidth(column.GetNamedNumber(L"minWidth", 100));
|
|
302
|
+
definition.MaxWidth(column.GetNamedNumber(L"maxWidth", 100000));
|
|
303
|
+
detail.ColumnDefinitions().Append(definition); detailColumns.push_back(definition);
|
|
304
|
+
Grid panel; Grid::SetColumn(panel, index - 1);
|
|
305
|
+
auto slot = Slot(key); panel.Children().Append(slot);
|
|
306
|
+
if (index + 1 < columns.Size()) {
|
|
307
|
+
slot.Margin({0, 0, 6, 0});
|
|
308
|
+
panel.Children().Append(Divider(key, [this, key, index, definition](double delta) {
|
|
309
|
+
auto col = config.GetNamedArray(L"columns").GetObjectAt(index);
|
|
310
|
+
auto width = Clamp(col, definition.ActualWidth() - 6 + delta);
|
|
311
|
+
definition.Width({width + 6, GridUnitType::Pixel}); Resize(key, width);
|
|
312
|
+
}));
|
|
313
|
+
}
|
|
314
|
+
detail.Children().Append(panel);
|
|
315
|
+
}
|
|
316
|
+
split.Content(detail); root.Children().Append(split);
|
|
317
|
+
}
|
|
318
|
+
void Apply(hstring const &json) {
|
|
319
|
+
JsonObject next;
|
|
320
|
+
if (!JsonObject::TryParse(json, next)) return;
|
|
321
|
+
updating = true;
|
|
322
|
+
config = next;
|
|
323
|
+
auto mode = config.GetNamedString(L"mode");
|
|
324
|
+
auto items = config.GetNamedArray(L"items", JsonArray());
|
|
325
|
+
auto columns = config.GetNamedArray(L"columns", JsonArray());
|
|
326
|
+
// Only structural changes recreate controls. Selection/ack updates retain focus.
|
|
327
|
+
JsonObject signature; String(signature, L"mode", mode);
|
|
328
|
+
if (mode == L"sidebar") {
|
|
329
|
+
JsonArray structureItems;
|
|
330
|
+
for (auto const &entry : items) {
|
|
331
|
+
auto item = entry.GetObject(); JsonObject identity;
|
|
332
|
+
String(identity, L"key", item.GetNamedString(L"key"));
|
|
333
|
+
String(identity, L"section", item.GetNamedString(L"section", L""));
|
|
334
|
+
identity.SetNamedValue(L"hidden", JsonValue::CreateBooleanValue(item.GetNamedBoolean(L"hidden", false)));
|
|
335
|
+
structureItems.Append(identity);
|
|
336
|
+
}
|
|
337
|
+
signature.SetNamedValue(L"items", structureItems);
|
|
338
|
+
}
|
|
339
|
+
JsonArray keys;
|
|
340
|
+
for (auto const &column : columns) keys.Append(JsonValue::CreateStringValue(column.GetObject().GetNamedString(L"key")));
|
|
341
|
+
signature.SetNamedValue(L"columns", keys);
|
|
342
|
+
auto nextStructure = signature.Stringify();
|
|
343
|
+
if (structure != nextStructure) {
|
|
344
|
+
ClearScrollObservers();
|
|
345
|
+
root.Children().Clear(); root.RowDefinitions().Clear(); root.ColumnDefinitions().Clear();
|
|
346
|
+
slots.clear(); menu.clear(); iconConfigurations.clear(); detailColumns.clear();
|
|
347
|
+
navigation = nullptr; split = nullptr; content = nullptr; footer = nullptr;
|
|
348
|
+
structure = nextStructure;
|
|
349
|
+
if (mode == L"sidebar") BuildSidebar(items);
|
|
350
|
+
else if (mode == L"split") BuildSplit(columns);
|
|
351
|
+
else BuildStack();
|
|
352
|
+
}
|
|
353
|
+
auto appearance = config.GetNamedObject(L"appearance", JsonObject());
|
|
354
|
+
root.Background(Brush(appearance.GetNamedString(L"backgroundColor", L""), {255, 255, 255, 255}));
|
|
355
|
+
auto foreground = Brush(appearance.GetNamedString(L"foregroundColor", L""), {255, 32, 33, 36});
|
|
356
|
+
auto active = config.GetNamedString(L"activeKey");
|
|
357
|
+
if (content) { slots.clear(); slots.emplace(active, content); }
|
|
358
|
+
if (mode == L"stack") {
|
|
359
|
+
header.Visibility(config.GetNamedBoolean(L"headerShown", true) ? Visibility::Visible : Visibility::Collapsed);
|
|
360
|
+
back.Visibility(config.GetNamedBoolean(L"canGoBack", false) ? Visibility::Visible : Visibility::Collapsed);
|
|
361
|
+
back.Content(box_value(config.GetNamedString(L"backTitle", L"Back")));
|
|
362
|
+
back.Foreground(Brush(appearance.GetNamedString(L"accentColor", L""), {255, 0, 103, 192}));
|
|
363
|
+
title.Foreground(foreground);
|
|
364
|
+
for (auto const &entry : items) { auto item = entry.GetObject(); if (item.GetNamedString(L"key") == active) title.Text(item.GetNamedString(L"title")); }
|
|
365
|
+
}
|
|
366
|
+
if (navigation) {
|
|
367
|
+
navigation.OpenPaneLength(config.GetNamedNumber(L"paneWidth", 240));
|
|
368
|
+
navigation.IsPaneOpen(!config.GetNamedBoolean(L"collapsed", false));
|
|
369
|
+
auto footerHeight = config.GetNamedNumber(L"footerHeight", 0);
|
|
370
|
+
footer.Height(footerHeight > 0 ? footerHeight : 0);
|
|
371
|
+
footer.Visibility(footerHeight > 0 ? Visibility::Visible : Visibility::Collapsed);
|
|
372
|
+
navigation.Foreground(foreground);
|
|
373
|
+
auto resource = Brush(appearance.GetNamedString(L"sidebarBackgroundColor", L""), {255, 245, 245, 247});
|
|
374
|
+
navigation.Resources().Insert(box_value(L"NavigationViewExpandedPaneBackground"), resource);
|
|
375
|
+
navigation.Resources().Insert(box_value(L"NavigationViewDefaultPaneBackground"), resource);
|
|
376
|
+
navigation.Resources().Insert(box_value(L"NavigationViewSelectionIndicatorForeground"), Brush(appearance.GetNamedString(L"accentColor", L""), {255, 0, 103, 192}));
|
|
377
|
+
for (auto const &entry : items) {
|
|
378
|
+
auto item = entry.GetObject(); auto it = menu.find(item.GetNamedString(L"key"));
|
|
379
|
+
if (it == menu.end()) continue;
|
|
380
|
+
it->second.Content(box_value(item.GetNamedString(L"title")));
|
|
381
|
+
it->second.IsEnabled(!item.GetNamedBoolean(L"disabled", false));
|
|
382
|
+
auto badge = item.GetNamedString(L"badge", L"");
|
|
383
|
+
if (badge.empty()) it->second.InfoBadge(nullptr);
|
|
384
|
+
else {
|
|
385
|
+
// InfoBadge only displays integers; other strings render as a dot.
|
|
386
|
+
InfoBadge info; wchar_t *end = nullptr;
|
|
387
|
+
auto value = std::wcstol(badge.c_str(), &end, 10);
|
|
388
|
+
if (end && *end == L'\0' && value > 0) info.Value(static_cast<int32_t>(value));
|
|
389
|
+
it->second.InfoBadge(info);
|
|
390
|
+
}
|
|
391
|
+
auto iconJSON = item.HasKey(L"icon") ? item.GetNamedObject(L"icon").Stringify() : hstring{};
|
|
392
|
+
auto oldIcon = iconConfigurations.find(it->first);
|
|
393
|
+
if (oldIcon == iconConfigurations.end() || oldIcon->second != iconJSON) {
|
|
394
|
+
it->second.Icon(ItemIcon(item));
|
|
395
|
+
iconConfigurations[it->first] = iconJSON;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
auto selected = menu.find(active);
|
|
399
|
+
navigation.SelectedItem(selected == menu.end() ? nullptr : selected->second);
|
|
400
|
+
}
|
|
401
|
+
if (split) {
|
|
402
|
+
split.OpenPaneLength(columns.GetObjectAt(0).GetNamedNumber(L"width") + 6);
|
|
403
|
+
for (size_t i = 0; i + 1 < detailColumns.size(); ++i)
|
|
404
|
+
detailColumns[i].Width({columns.GetObjectAt(static_cast<uint32_t>(i + 1)).GetNamedNumber(L"width") + 6, GridUnitType::Pixel});
|
|
405
|
+
}
|
|
406
|
+
updating = false;
|
|
407
|
+
// LayoutUpdated will deliver the new geometry after XAML has arranged.
|
|
408
|
+
lastLayout = L"";
|
|
409
|
+
root.InvalidateArrange();
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
void RegisterDesktopNavigation(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) {
|
|
415
|
+
using namespace winrt;
|
|
416
|
+
using namespace Microsoft::ReactNative;
|
|
417
|
+
using namespace Microsoft::ReactNative::Composition;
|
|
418
|
+
using namespace DesktopNavigation;
|
|
419
|
+
packageBuilder.as<IReactPackageBuilderFabric>().AddViewComponent(L"DesktopNavigationHost", [](IReactViewComponentBuilder const &builder) {
|
|
420
|
+
builder.SetCreateProps([](ViewProps props, IComponentProps const &previous) { return make<HostProps>(props, previous); });
|
|
421
|
+
builder.as<IReactCompositionViewComponentBuilder>().SetContentIslandComponentViewInitializer([](ContentIslandComponentView const &view) {
|
|
422
|
+
auto host = make_self<Host>(); host->Initialize(view); view.UserData(*host);
|
|
423
|
+
view.Destroying([](IInspectable const &sender, IInspectable const &) { sender.as<ContentIslandComponentView>().UserData().as<Host>()->Close(); });
|
|
424
|
+
});
|
|
425
|
+
builder.SetUpdatePropsHandler([](ComponentView const &view, IComponentProps const &props, IComponentProps const &) {
|
|
426
|
+
view.UserData().as<Host>()->Apply(props.as<HostProps>()->configuration);
|
|
427
|
+
});
|
|
428
|
+
builder.SetUpdateEventEmitterHandler([](ComponentView const &view, EventEmitter const &emitter) {
|
|
429
|
+
auto host = view.UserData().as<Host>(); host->emitter = emitter; host->lastLayout = L"";
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#include "pch.h"
|
|
2
|
+
#include "ReactPackageProvider.h"
|
|
3
|
+
#include "ReactPackageProvider.g.cpp"
|
|
4
|
+
void RegisterDesktopNavigation(winrt::Microsoft::ReactNative::IReactPackageBuilder const &builder);
|
|
5
|
+
namespace winrt::DesktopNavigation::implementation {
|
|
6
|
+
void ReactPackageProvider::CreatePackage(Microsoft::ReactNative::IReactPackageBuilder const &builder) noexcept {
|
|
7
|
+
RegisterDesktopNavigation(builder);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include "ReactPackageProvider.g.h"
|
|
3
|
+
namespace winrt::DesktopNavigation::implementation {
|
|
4
|
+
struct ReactPackageProvider : ReactPackageProviderT<ReactPackageProvider> {
|
|
5
|
+
void CreatePackage(Microsoft::ReactNative::IReactPackageBuilder const &builder) noexcept;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
namespace winrt::DesktopNavigation::factory_implementation {
|
|
9
|
+
struct ReactPackageProvider : ReactPackageProviderT<ReactPackageProvider, implementation::ReactPackageProvider> {};
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#include "pch.h"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#define NOMINMAX
|
|
3
|
+
#define WIN32_LEAN_AND_MEAN
|
|
4
|
+
#include <windows.h>
|
|
5
|
+
#undef GetCurrentTime
|
|
6
|
+
#include <unknwn.h>
|
|
7
|
+
#include <CppWinRTIncludes.h>
|
|
8
|
+
#include <winrt/Microsoft.ReactNative.h>
|
|
9
|
+
#include <winrt/Microsoft.ReactNative.Composition.h>
|
|
10
|
+
#include <winrt/Microsoft.ReactNative.Composition.Experimental.h>
|
|
11
|
+
#include <winrt/Microsoft.UI.Content.h>
|
|
12
|
+
#include <winrt/Windows.UI.h>
|
|
13
|
+
#include <winrt/Windows.System.h>
|
|
14
|
+
#include <winrt/Microsoft.UI.Xaml.Input.h>
|
|
15
|
+
#include <winrt/Microsoft.UI.Xaml.h>
|
|
16
|
+
#include <winrt/Microsoft.UI.Xaml.Controls.h>
|
|
17
|
+
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
|
|
18
|
+
#include <winrt/Microsoft.UI.Xaml.Media.h>
|
|
19
|
+
#include <winrt/Microsoft.UI.Xaml.Automation.h>
|
|
20
|
+
#include <winrt/Microsoft.UI.Xaml.Automation.Peers.h>
|
|
21
|
+
#include <functional>
|
|
22
|
+
#include <winrt/Windows.Data.Json.h>
|
|
23
|
+
#include <NativeModules.h>
|
|
24
|
+
#include <algorithm>
|
|
25
|
+
#include <cwchar>
|
|
26
|
+
#include <map>
|
|
27
|
+
#include <vector>
|