plusui-native 0.2.0

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.
Files changed (44) hide show
  1. package/README.md +162 -0
  2. package/package.json +36 -0
  3. package/src/assets/icon-generator.js +251 -0
  4. package/src/assets/resource-embedder.js +351 -0
  5. package/src/doctor/detectors/cmake.js +84 -0
  6. package/src/doctor/detectors/compiler.js +145 -0
  7. package/src/doctor/detectors/just.js +45 -0
  8. package/src/doctor/detectors/nodejs.js +57 -0
  9. package/src/doctor/detectors/webview2.js +66 -0
  10. package/src/doctor/index.js +184 -0
  11. package/src/doctor/installers/linux.js +121 -0
  12. package/src/doctor/installers/macos.js +123 -0
  13. package/src/doctor/installers/windows.js +117 -0
  14. package/src/doctor/reporter.js +219 -0
  15. package/src/index.js +904 -0
  16. package/templates/base/Justfile +115 -0
  17. package/templates/base/README.md.template +168 -0
  18. package/templates/base/assets/README.md +88 -0
  19. package/templates/base/assets/icon.png +0 -0
  20. package/templates/manager.js +217 -0
  21. package/templates/react/.vscode/c_cpp_properties.json +24 -0
  22. package/templates/react/CMakeLists.txt.template +151 -0
  23. package/templates/react/frontend/index.html +12 -0
  24. package/templates/react/frontend/package.json.template +24 -0
  25. package/templates/react/frontend/src/App.tsx +134 -0
  26. package/templates/react/frontend/src/main.tsx +10 -0
  27. package/templates/react/frontend/src/styles/app.css +140 -0
  28. package/templates/react/frontend/tsconfig.json +21 -0
  29. package/templates/react/frontend/tsconfig.node.json +11 -0
  30. package/templates/react/frontend/vite.config.ts +14 -0
  31. package/templates/react/main.cpp.template +201 -0
  32. package/templates/react/package.json.template +23 -0
  33. package/templates/solid/.vscode/c_cpp_properties.json +24 -0
  34. package/templates/solid/CMakeLists.txt.template +151 -0
  35. package/templates/solid/frontend/index.html +12 -0
  36. package/templates/solid/frontend/package.json.template +21 -0
  37. package/templates/solid/frontend/src/App.tsx +133 -0
  38. package/templates/solid/frontend/src/main.tsx +5 -0
  39. package/templates/solid/frontend/src/styles/app.css +140 -0
  40. package/templates/solid/frontend/tsconfig.json +22 -0
  41. package/templates/solid/frontend/tsconfig.node.json +11 -0
  42. package/templates/solid/frontend/vite.config.ts +14 -0
  43. package/templates/solid/main.cpp.template +192 -0
  44. package/templates/solid/package.json.template +23 -0
@@ -0,0 +1,201 @@
1
+ #include <plusui/app.hpp>
2
+ #include <plusui/window.hpp>
3
+ #include <iostream>
4
+ #include "generated/assets.h"
5
+
6
+ // ============================================================================
7
+ // {{PROJECT_NAME}} - Configuration
8
+ // ============================================================================
9
+ // Change these values to configure your app. All options are true/false toggles
10
+ // or simple values. Easy to customize without digging through code.
11
+ // ============================================================================
12
+
13
+ // ----------------------------------------------------------------------------
14
+ // APP CONFIGURATION (Application-level settings)
15
+ // ----------------------------------------------------------------------------
16
+ struct AppConfig {
17
+ // --- Identity ---
18
+ std::string name = "{{PROJECT_NAME}}"; // Your app name (used for window title, etc.)
19
+ std::string version = "0.1.0";
20
+
21
+ // --- App Type ---
22
+ bool headless = false; // No window, background app only
23
+ bool singleInstance = true; // Only allow one instance of the app
24
+
25
+ // --- Startup ---
26
+ bool autoStart = false; // Launch on system startup
27
+ bool hiddenOnStartup = false; // Start hidden
28
+
29
+ // --- Security ---
30
+ bool webSecurity = true; // Enable web security (CORS, etc.)
31
+ bool allowFileAccess = false; // Allow file:// URLs
32
+ } appConfig;
33
+
34
+ // ----------------------------------------------------------------------------
35
+ // WINDOW CONFIGURATION (Window appearance and behavior)
36
+ // ----------------------------------------------------------------------------
37
+ struct WindowConfig {
38
+ // --- Size & Position ---
39
+ int width = 1200;
40
+ int height = 800;
41
+ int minWidth = 400; // Minimum window width
42
+ int minHeight = 300; // Minimum window height
43
+ int maxWidth = 0; // 0 = no limit
44
+ int maxHeight = 0; // 0 = no limit
45
+ bool centerOnStartup = true; // Center window on launch
46
+
47
+ // --- Appearance ---
48
+ bool showTitlebar = true; // Show native titlebar (set false for frameless)
49
+ bool showBorder = true; // Show window border
50
+ bool transparent = false; // Transparent window background
51
+ double opacity = 1.0; // Window opacity 0.0 (invisible) to 1.0 (solid)
52
+
53
+ // --- Behavior ---
54
+ bool resizable = true; // Allow user to resize window
55
+ bool minimizable = true; // Show minimize button
56
+ bool maximizable = true; // Show maximize button
57
+ bool closable = true; // Show close button
58
+ bool alwaysOnTop = false; // Keep window above all others
59
+ bool showInTaskbar = true; // Show in taskbar (false = hidden from taskbar)
60
+ bool fullscreen = false; // Start in fullscreen mode
61
+
62
+ // --- Dev Tools ---
63
+ bool devTools = true; // Enable DevTools (F12, right-click inspect)
64
+ bool contextMenu = true; // Enable right-click context menu
65
+
66
+ // --- WebView ---
67
+ bool scrollbars = false; // Show scrollbars in webview (false = hidden)
68
+ } windowConfig;
69
+
70
+ // ----------------------------------------------------------------------------
71
+ // SERVICES CONFIGURATION (Optional features)
72
+ // ----------------------------------------------------------------------------
73
+ struct ServicesConfig {
74
+ bool enableClipboard = true; // Enable clipboard read/write from frontend
75
+ bool enableDisplay = true; // Enable multi-display detection
76
+ bool enableKeyboard = true; // Enable keyboard shortcuts/hotkeys
77
+ bool enableMenu = true; // Enable custom menu bar
78
+ } servicesConfig;
79
+
80
+ // ============================================================================
81
+ // WEBGPU CONFIGURATION (Optional - 3D Graphics & GPU Compute)
82
+ // ============================================================================
83
+ // WebGPU provides native GPU acceleration for rendering and compute shaders.
84
+ // Requires: PLUSUI_ENABLE_WEBGPU build flag
85
+ //
86
+ // Usage in frontend:
87
+ // const adapter = await navigator.gpu.requestAdapter();
88
+ // const device = await adapter.requestDevice();
89
+ // const canvas = document.querySelector('canvas');
90
+ // const context = canvas.getContext('webgpu');
91
+ // context.configure({ device, format: 'bgra8unorm' });
92
+ //
93
+ // See: https://www.w3.org/TR/webgpu/ for full API documentation
94
+ // ============================================================================
95
+ struct WebGPUConfig {
96
+ bool enabled = false; // Enable WebGPU support
97
+ bool validateAPI = true; // Enable validation in debug builds
98
+ bool verbose = false; // Enable verbose logging for debugging
99
+ } webgpuConfig;
100
+
101
+ // ============================================================================
102
+ // MAIN - Application Entry Point
103
+ // ============================================================================
104
+ int main() {
105
+ // Use your app name as the variable name
106
+ auto {{PROJECT_NAME_LOWER}} = plusui::createApp()
107
+ .title(appConfig.name)
108
+ .width(windowConfig.width)
109
+ .height(windowConfig.height)
110
+ .centered(windowConfig.centerOnStartup)
111
+ .resizable(windowConfig.resizable)
112
+ .decorations(windowConfig.showTitlebar && windowConfig.showBorder)
113
+ .transparent(windowConfig.transparent)
114
+ .devtools(windowConfig.devTools)
115
+ .alwaysOnTop(windowConfig.alwaysOnTop)
116
+ .skipTaskbar(!windowConfig.showInTaskbar)
117
+ .scrollbars(windowConfig.scrollbars);
118
+
119
+ auto mainWindow = {{PROJECT_NAME_LOWER}}.build();
120
+
121
+ // ========================================
122
+ // ICON SETUP (optional)
123
+ // ========================================
124
+ // To set app icons, place icon.png in the assets/ folder
125
+ // The CLI will generate ASSET_ICON_PNG and ASSET_ICON_PNG_LEN automatically
126
+ // Then uncomment these lines:
127
+ // #ifdef ASSET_ICON_PNG
128
+ // mainWindow.window().setIconFromMemory(ASSET_ICON_PNG, ASSET_ICON_PNG_LEN);
129
+ // mainWindow.tray().setIconFromMemory(ASSET_ICON_PNG, ASSET_ICON_PNG_LEN);
130
+ // #endif
131
+
132
+ // ========================================
133
+ // SYSTEM TRAY (optional)
134
+ // ========================================
135
+ // mainWindow.tray().setTooltip(appConfig.name);
136
+ // mainWindow.tray().setVisible(true);
137
+
138
+ // Apply additional settings
139
+ if (windowConfig.opacity < 1.0) {
140
+ mainWindow.window().setTransparency(windowConfig.opacity);
141
+ }
142
+ if (windowConfig.fullscreen) {
143
+ mainWindow.window().setFullscreen(true);
144
+ }
145
+
146
+ // ========================================
147
+ // SYSTEM TRAY (if enabled)
148
+ // ========================================
149
+ // HEADLESS / HIDDEN STARTUP
150
+ // ========================================
151
+ if (appConfig.headless || appConfig.hiddenOnStartup) {
152
+ mainWindow.window().hide();
153
+ }
154
+
155
+ // ========================================
156
+ // NAVIGATION - Load Frontend
157
+ // ========================================
158
+ #ifdef PLUSUI_DEV_MODE
159
+ mainWindow.navigate("http://localhost:5173");
160
+ #else
161
+ mainWindow.loadFile("frontend/dist/index.html");
162
+ #endif
163
+
164
+ // ========================================
165
+ // CUSTOM C++ FUNCTIONS (expose to frontend)
166
+ // ========================================
167
+ // {{PROJECT_NAME_LOWER}}.bind("getVersion", [](const std::string& args) {
168
+ // return "\"" + appConfig.version + "\"";
169
+ // });
170
+ // Call from JS: const version = await app.invoke('getVersion');
171
+
172
+ // ========================================
173
+ // RUN APPLICATION
174
+ // ========================================
175
+ plusui::App runtime;
176
+ runtime.run();
177
+
178
+ return 0;
179
+ }
180
+
181
+ // ============================================================================
182
+ // FRONTEND API REFERENCE
183
+ // ============================================================================
184
+ // import { win, browser, router, app, display, clipboard } from 'plusui-native-core';
185
+ //
186
+ // WINDOW: win.minimize(), win.maximize(), win.close(), win.center(),
187
+ // win.setSize(w, h), win.setPosition(x, y), win.setTitle(str),
188
+ // win.setFullscreen(bool), win.setAlwaysOnTop(bool),
189
+ // win.getSize(), win.getPosition(), win.isMaximized(), win.isVisible()
190
+ //
191
+ // BROWSER: browser.navigate(url), browser.goBack(), browser.goForward(),
192
+ // browser.reload(), browser.getUrl(), browser.canGoBack()
193
+ //
194
+ // ROUTER: router.setRoutes({'/': 'url'}), router.push('/path')
195
+ //
196
+ // APP: app.quit(), app.invoke('customFn', args)
197
+ //
198
+ // DISPLAY: display.getAll(), display.getPrimary(), display.getCurrent()
199
+ //
200
+ // CLIPBOARD: clipboard.writeText(str), clipboard.readText(), clipboard.clear()
201
+
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "{{PROJECT_NAME_LOWER}}",
3
+ "version": "{{PROJECT_VERSION}}",
4
+ "description": "A PlusUI desktop application",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "plusui dev",
8
+ "dev:frontend": "plusui dev:frontend",
9
+ "dev:backend": "plusui dev:backend",
10
+ "bind": "plusui bind",
11
+ "bindgen": "plusui bindgen",
12
+ "build": "plusui build",
13
+ "build:frontend": "plusui build:frontend",
14
+ "build:backend": "plusui build:backend",
15
+ "build:all": "plusui build:all",
16
+ "start": "plusui run",
17
+ "clean": "plusui clean"
18
+ },
19
+ "devDependencies": {
20
+ "plusui-native": "file:../../Tools/plusui-cli"
21
+ }
22
+ }
23
+
@@ -0,0 +1,24 @@
1
+ {
2
+ "configurations": [
3
+ {
4
+ "name": "Windows",
5
+ "includePath": [
6
+ "${workspaceFolder}/src",
7
+ "${workspaceFolder}/../Core/include",
8
+ "${workspaceFolder}/build/dev/_deps/webview2/build/native/include",
9
+ "C:/Users/${env:USERNAME}/.nuget/packages/microsoft.web.webview2/1.0.2903.40/build/native/include"
10
+ ],
11
+ "defines": [
12
+ "PLUSUI_DEV_MODE",
13
+ "_WIN32",
14
+ "NDEBUG"
15
+ ],
16
+ "compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/cl.exe",
17
+ "cStandard": "c17",
18
+ "cppStandard": "c++20",
19
+ "intelliSenseMode": "windows-msvc-x64",
20
+ "compileCommands": "${workspaceFolder}/build/dev/compile_commands.json"
21
+ }
22
+ ],
23
+ "version": 4
24
+ }
@@ -0,0 +1,151 @@
1
+ cmake_minimum_required(VERSION 3.16)
2
+ project({{PROJECT_NAME}} VERSION {{PROJECT_VERSION}} LANGUAGES CXX)
3
+
4
+ set(CMAKE_CXX_STANDARD 20)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
7
+
8
+ # Platform detection
9
+ if(WIN32)
10
+ add_definitions(-DPLUSUI_EDGE)
11
+ elseif(APPLE)
12
+ add_definitions(-DPLUSUI_COCOA)
13
+ else()
14
+ add_definitions(-DPLUSUI_GTK)
15
+ endif()
16
+
17
+ # Development mode flag
18
+ option(PLUSUI_DEV_MODE "Enable development mode (connect to Vite dev server)" OFF)
19
+ if(PLUSUI_DEV_MODE)
20
+ add_definitions(-DPLUSUI_DEV_MODE)
21
+ endif()
22
+
23
+ # Find PlusUI Core library
24
+ # Strategy: Check multiple locations for the Core library
25
+ set(PLUSUI_FOUND FALSE)
26
+
27
+ # Location 1: Local development (sibling to project inside PlusUI repo)
28
+ set(PLUSUI_CORE_DEV "${CMAKE_SOURCE_DIR}/../Core")
29
+ if(EXISTS "${PLUSUI_CORE_DEV}/CMakeLists.txt")
30
+ message(STATUS "Found PlusUI Core at: ${PLUSUI_CORE_DEV}")
31
+ add_subdirectory("${PLUSUI_CORE_DEV}" "${CMAKE_BINARY_DIR}/plusui-core")
32
+ set(PLUSUI_FOUND TRUE)
33
+ endif()
34
+
35
+ # Location 2: Installed via npm (node_modules)
36
+ if(NOT PLUSUI_FOUND)
37
+ set(PLUSUI_CORE_NPM "${CMAKE_SOURCE_DIR}/node_modules/plusui-native-core/Core")
38
+ if(EXISTS "${PLUSUI_CORE_NPM}/CMakeLists.txt")
39
+ message(STATUS "Found PlusUI Core in node_modules: ${PLUSUI_CORE_NPM}")
40
+ add_subdirectory("${PLUSUI_CORE_NPM}" "${CMAKE_BINARY_DIR}/plusui-core")
41
+ set(PLUSUI_FOUND TRUE)
42
+ endif()
43
+ endif()
44
+
45
+ # Location 3: Parent directory development structure
46
+ if(NOT PLUSUI_FOUND)
47
+ set(PLUSUI_CORE_PARENT "${CMAKE_SOURCE_DIR}/../../Core")
48
+ if(EXISTS "${PLUSUI_CORE_PARENT}/CMakeLists.txt")
49
+ message(STATUS "Found PlusUI Core at: ${PLUSUI_CORE_PARENT}")
50
+ add_subdirectory("${PLUSUI_CORE_PARENT}" "${CMAKE_BINARY_DIR}/plusui-core")
51
+ set(PLUSUI_FOUND TRUE)
52
+ endif()
53
+ endif()
54
+
55
+ if(NOT PLUSUI_FOUND)
56
+ message(FATAL_ERROR "
57
+ PlusUI Core not found!
58
+
59
+ Make sure you have run 'npm install' or that this project is inside the PlusUI repository.
60
+
61
+ Searched locations:
62
+ - ${PLUSUI_CORE_DEV}
63
+ - ${PLUSUI_CORE_NPM}
64
+ - ${PLUSUI_CORE_PARENT}
65
+ ")
66
+ endif()
67
+
68
+ # Create the executable
69
+ add_executable({{PROJECT_NAME}} main.cpp)
70
+
71
+ # Optional: Add your own C++ files here
72
+ # file(GLOB_RECURSE MY_SOURCES "features/*.cpp")
73
+ # target_sources({{PROJECT_NAME}} PRIVATE ${MY_SOURCES})
74
+
75
+ # Link PlusUI library
76
+ target_link_libraries({{PROJECT_NAME}} PRIVATE plusui)
77
+ target_include_directories({{PROJECT_NAME}} PRIVATE ${CMAKE_SOURCE_DIR})
78
+
79
+ # Platform-specific setup
80
+ if(WIN32)
81
+ # Windows: WebView2
82
+ # Try to find WebView2 SDK headers
83
+ find_path(WEBVIEW2_INCLUDE_DIR
84
+ NAMES webview2.h
85
+ PATHS
86
+ "${CMAKE_SOURCE_DIR}/packages/Microsoft.Web.WebView2/build/native/include"
87
+ "${CMAKE_BINARY_DIR}/packages/Microsoft.Web.WebView2/build/native/include"
88
+ "$ENV{USERPROFILE}/.nuget/packages/microsoft.web.webview2/1.0.2903.40/build/native/include"
89
+ "$ENV{NUGET_PACKAGES}/microsoft.web.webview2/1.0.2903.40/build/native/include"
90
+ "C:/Program Files (x86)/Microsoft EdgeWebView/runtimes/win-x64/native"
91
+ "C:/Program Files/Microsoft EdgeWebView/runtimes/win-x64/native"
92
+ )
93
+
94
+ if(WEBVIEW2_INCLUDE_DIR)
95
+ message(STATUS "Found WebView2 headers at: ${WEBVIEW2_INCLUDE_DIR}")
96
+ target_include_directories({{PROJECT_NAME}} PRIVATE ${WEBVIEW2_INCLUDE_DIR})
97
+ else()
98
+ message(WARNING "WebView2 headers not found. Building may fail.")
99
+ message(STATUS "Please install WebView2 SDK via NuGet:")
100
+ message(STATUS " nuget install Microsoft.Web.WebView2 -OutputDirectory packages")
101
+ endif()
102
+
103
+ target_link_libraries({{PROJECT_NAME}} PRIVATE ole32 shell32 shlwapi user32 version)
104
+
105
+ # Set subsystem to Windows for release builds (no console window)
106
+ if(NOT PLUSUI_DEV_MODE)
107
+ set_target_properties({{PROJECT_NAME}} PROPERTIES
108
+ WIN32_EXECUTABLE TRUE
109
+ )
110
+ endif()
111
+ elseif(APPLE)
112
+ # macOS: WebKit
113
+ find_library(WEBKIT_LIBRARY WebKit REQUIRED)
114
+ find_library(COCOA_LIBRARY Cocoa REQUIRED)
115
+ target_link_libraries({{PROJECT_NAME}} PRIVATE ${WEBKIT_LIBRARY} ${COCOA_LIBRARY})
116
+
117
+ # Create app bundle for production
118
+ if(NOT PLUSUI_DEV_MODE)
119
+ set_target_properties({{PROJECT_NAME}} PROPERTIES
120
+ MACOSX_BUNDLE TRUE
121
+ MACOSX_BUNDLE_BUNDLE_NAME "{{PROJECT_NAME}}"
122
+ MACOSX_BUNDLE_BUNDLE_VERSION "{{PROJECT_VERSION}}"
123
+ MACOSX_BUNDLE_GUI_IDENTIFIER "com.plusui.{{PROJECT_NAME_LOWER}}"
124
+ )
125
+ endif()
126
+ else()
127
+ # Linux: GTK + WebKitGTK
128
+ find_package(PkgConfig REQUIRED)
129
+ pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
130
+ pkg_check_modules(WEBKIT2 REQUIRED webkit2gtk-4.0)
131
+ target_include_directories({{PROJECT_NAME}} PRIVATE ${GTK3_INCLUDE_DIRS} ${WEBKIT2_INCLUDE_DIRS})
132
+ target_link_libraries({{PROJECT_NAME}} PRIVATE ${GTK3_LIBRARIES} ${WEBKIT2_LIBRARIES})
133
+ endif()
134
+
135
+ # Copy frontend dist files to build directory after build
136
+ if(EXISTS "${CMAKE_SOURCE_DIR}/frontend/dist")
137
+ add_custom_command(TARGET {{PROJECT_NAME}} POST_BUILD
138
+ COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:{{PROJECT_NAME}}>/frontend"
139
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
140
+ "${CMAKE_SOURCE_DIR}/frontend/dist"
141
+ "$<TARGET_FILE_DIR:{{PROJECT_NAME}}>/frontend"
142
+ COMMENT "Copying frontend files to build directory"
143
+ )
144
+ endif()
145
+
146
+ # Set output directories for organized builds
147
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
148
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
149
+ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
150
+
151
+
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{PROJECT_NAME}}</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "{{PROJECT_NAME_LOWER}}-frontend",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "solid-js": "^1.8.0",
13
+ "plusui-native-core": "{{PLUSUI_CORE_PATH}}"
14
+ },
15
+ "devDependencies": {
16
+ "typescript": "^5.3.0",
17
+ "vite": "^5.0.0",
18
+ "vite-plugin-solid": "^2.10.0"
19
+ }
20
+ }
21
+
@@ -0,0 +1,133 @@
1
+ import { createSignal, onMount } from 'solid-js';
2
+ import { win, browser, router, app } from 'plusui-native-core';
3
+
4
+ // Define routes for your app (optional - for SPA routing)
5
+ const routes = {
6
+ '/': 'http://localhost:5173',
7
+ '/settings': 'http://localhost:5173/settings',
8
+ '/about': 'http://localhost:5173/about',
9
+ };
10
+
11
+ function App() {
12
+ const [windowSize, setWindowSize] = createSignal({ width: 0, height: 0 });
13
+ const [windowPos, setWindowPos] = createSignal({ x: 0, y: 0 });
14
+ const [currentUrl, setCurrentUrl] = createSignal('');
15
+ const [canGoBack, setCanGoBack] = createSignal(false);
16
+ const [canGoForward, setCanGoForward] = createSignal(false);
17
+
18
+ onMount(() => {
19
+ // Setup routes
20
+ router.setRoutes(routes);
21
+
22
+ // Listen for navigation changes
23
+ browser.onNavigate((url) => {
24
+ setCurrentUrl(url);
25
+ browser.canGoBack().then(setCanGoBack);
26
+ browser.canGoForward().then(setCanGoForward);
27
+ });
28
+
29
+ // Get initial state
30
+ browser.getUrl().then(setCurrentUrl);
31
+ browser.canGoBack().then(setCanGoBack);
32
+ browser.canGoForward().then(setCanGoForward);
33
+ });
34
+
35
+ const handleMinimize = async () => await win.minimize();
36
+ const handleMaximize = async () => await win.maximize();
37
+ const handleClose = async () => await win.close();
38
+ const handleGetSize = async () => {
39
+ const size = await win.getSize();
40
+ setWindowSize(size);
41
+ };
42
+ const handleGetPosition = async () => {
43
+ const pos = await win.getPosition();
44
+ setWindowPos(pos);
45
+ };
46
+
47
+ // Browser navigation
48
+ const handleGoBack = async () => await browser.goBack();
49
+ const handleGoForward = async () => await browser.goForward();
50
+ const handleReload = async () => await browser.reload();
51
+ const handleNavigate = async (url: string) => await browser.navigate(url);
52
+
53
+ // Router navigation
54
+ const handleGoHome = async () => await router.push('/');
55
+ const handleGoSettings = async () => await router.push('/settings');
56
+
57
+ // App control
58
+ const handleQuit = async () => await app.quit();
59
+
60
+ return (
61
+ <div class="app">
62
+ <header class="app-header">
63
+ <h1>{{PROJECT_NAME}}</h1>
64
+ <p>Built with PlusUI Framework</p>
65
+ </header>
66
+
67
+ <main class="app-content">
68
+ <div class="card">
69
+ <h2>Window Controls</h2>
70
+ <div class="button-group">
71
+ <button onClick={handleMinimize} class="button">Minimize</button>
72
+ <button onClick={handleMaximize} class="button">Maximize</button>
73
+ <button onClick={handleClose} class="button button-danger">Close</button>
74
+ </div>
75
+ </div>
76
+
77
+ <div class="card">
78
+ <h2>Window Size</h2>
79
+ <button onClick={handleGetSize} class="button">Get Size</button>
80
+ <Show when={windowSize().width > 0}>
81
+ <p class="info-text">Size: {windowSize().width} x {windowSize().height}</p>
82
+ </Show>
83
+ </div>
84
+
85
+ <div class="card">
86
+ <h2>Window Position</h2>
87
+ <div class="button-group">
88
+ <button onClick={handleGetPosition} class="button">Get Position</button>
89
+ <button onClick={() => win.setPosition(100, 100)} class="button">Move Left</button>
90
+ <button onClick={() => win.setPosition(800, 100)} class="button">Move Right</button>
91
+ </div>
92
+ <Show when={windowPos().x !== 0}>
93
+ <p class="info-text">Position: {windowPos().x}, {windowPos().y}</p>
94
+ </Show>
95
+ </div>
96
+
97
+ <div class="card">
98
+ <h2>Browser Navigation</h2>
99
+ <p class="info-text">Current: {currentUrl()}</p>
100
+ <div class="button-group">
101
+ <button onClick={handleGoBack} class="button" disabled={!canGoBack()}>Back</button>
102
+ <button onClick={handleGoForward} class="button" disabled={!canGoForward()}>Forward</button>
103
+ <button onClick={handleReload} class="button">Reload</button>
104
+ </div>
105
+ </div>
106
+
107
+ <div class="card">
108
+ <h2>Router (SPA Navigation)</h2>
109
+ <div class="button-group">
110
+ <button onClick={handleGoHome} class="button">Home /</button>
111
+ <button onClick={handleGoSettings} class="button">Settings</button>
112
+ </div>
113
+ <p style={{ 'font-size': '0.85em', color: '#666', 'margin-top': '10px' }}>
114
+ Define routes with <code>router.setRoutes({'{ ... }'})</code> then navigate with <code>router.push('/path')</code>
115
+ </p>
116
+ </div>
117
+
118
+ <div class="card">
119
+ <h2>App Control</h2>
120
+ <button onClick={handleQuit} class="button button-danger">Quit App</button>
121
+ </div>
122
+
123
+ <div class="info">
124
+ <p>Edit <code>frontend/src/App.tsx</code> to modify the UI.</p>
125
+ <p>Edit <code>main.cpp</code> to add C++ functionality.</p>
126
+ </div>
127
+ </main>
128
+ </div>
129
+ );
130
+ }
131
+
132
+ export default App;
133
+
@@ -0,0 +1,5 @@
1
+ import { render } from 'solid-js/web';
2
+ import App from './App';
3
+ import './styles/app.css';
4
+
5
+ render(() => <App />, document.getElementById('root')!);