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.
- package/README.md +162 -0
- package/package.json +36 -0
- package/src/assets/icon-generator.js +251 -0
- package/src/assets/resource-embedder.js +351 -0
- package/src/doctor/detectors/cmake.js +84 -0
- package/src/doctor/detectors/compiler.js +145 -0
- package/src/doctor/detectors/just.js +45 -0
- package/src/doctor/detectors/nodejs.js +57 -0
- package/src/doctor/detectors/webview2.js +66 -0
- package/src/doctor/index.js +184 -0
- package/src/doctor/installers/linux.js +121 -0
- package/src/doctor/installers/macos.js +123 -0
- package/src/doctor/installers/windows.js +117 -0
- package/src/doctor/reporter.js +219 -0
- package/src/index.js +904 -0
- package/templates/base/Justfile +115 -0
- package/templates/base/README.md.template +168 -0
- package/templates/base/assets/README.md +88 -0
- package/templates/base/assets/icon.png +0 -0
- package/templates/manager.js +217 -0
- package/templates/react/.vscode/c_cpp_properties.json +24 -0
- package/templates/react/CMakeLists.txt.template +151 -0
- package/templates/react/frontend/index.html +12 -0
- package/templates/react/frontend/package.json.template +24 -0
- package/templates/react/frontend/src/App.tsx +134 -0
- package/templates/react/frontend/src/main.tsx +10 -0
- package/templates/react/frontend/src/styles/app.css +140 -0
- package/templates/react/frontend/tsconfig.json +21 -0
- package/templates/react/frontend/tsconfig.node.json +11 -0
- package/templates/react/frontend/vite.config.ts +14 -0
- package/templates/react/main.cpp.template +201 -0
- package/templates/react/package.json.template +23 -0
- package/templates/solid/.vscode/c_cpp_properties.json +24 -0
- package/templates/solid/CMakeLists.txt.template +151 -0
- package/templates/solid/frontend/index.html +12 -0
- package/templates/solid/frontend/package.json.template +21 -0
- package/templates/solid/frontend/src/App.tsx +133 -0
- package/templates/solid/frontend/src/main.tsx +5 -0
- package/templates/solid/frontend/src/styles/app.css +140 -0
- package/templates/solid/frontend/tsconfig.json +22 -0
- package/templates/solid/frontend/tsconfig.node.json +11 -0
- package/templates/solid/frontend/vite.config.ts +14 -0
- package/templates/solid/main.cpp.template +192 -0
- package/templates/solid/package.json.template +23 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
* {
|
|
2
|
+
margin: 0;
|
|
3
|
+
padding: 0;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
body {
|
|
8
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
9
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
10
|
+
sans-serif;
|
|
11
|
+
-webkit-font-smoothing: antialiased;
|
|
12
|
+
-moz-osx-font-smoothing: grayscale;
|
|
13
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
14
|
+
color: #fff;
|
|
15
|
+
min-height: 100vh;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.app {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
min-height: 100vh;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.app-header {
|
|
25
|
+
padding: 3rem 2rem;
|
|
26
|
+
text-align: center;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.app-header h1 {
|
|
30
|
+
font-size: 3rem;
|
|
31
|
+
font-weight: 700;
|
|
32
|
+
margin-bottom: 0.5rem;
|
|
33
|
+
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.app-header p {
|
|
37
|
+
font-size: 1.2rem;
|
|
38
|
+
opacity: 0.9;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.app-content {
|
|
42
|
+
flex: 1;
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
padding: 2rem;
|
|
48
|
+
gap: 2rem;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.card {
|
|
52
|
+
background: rgba(255, 255, 255, 0.1);
|
|
53
|
+
backdrop-filter: blur(10px);
|
|
54
|
+
border-radius: 1rem;
|
|
55
|
+
padding: 2rem;
|
|
56
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
57
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
58
|
+
min-width: 400px;
|
|
59
|
+
text-align: center;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.card h2 {
|
|
63
|
+
margin-bottom: 1rem;
|
|
64
|
+
font-size: 1.3rem;
|
|
65
|
+
font-weight: 600;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.button-group {
|
|
69
|
+
display: flex;
|
|
70
|
+
gap: 0.75rem;
|
|
71
|
+
justify-content: center;
|
|
72
|
+
flex-wrap: wrap;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.button {
|
|
76
|
+
background: rgba(255, 255, 255, 0.2);
|
|
77
|
+
color: #fff;
|
|
78
|
+
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
79
|
+
padding: 0.75rem 1.5rem;
|
|
80
|
+
font-size: 1rem;
|
|
81
|
+
font-weight: 600;
|
|
82
|
+
border-radius: 0.5rem;
|
|
83
|
+
cursor: pointer;
|
|
84
|
+
transition: all 0.3s ease;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.button:hover {
|
|
88
|
+
background: rgba(255, 255, 255, 0.3);
|
|
89
|
+
transform: translateY(-2px);
|
|
90
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.button:active {
|
|
94
|
+
transform: translateY(0);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.button-danger {
|
|
98
|
+
background: rgba(231, 76, 60, 0.6);
|
|
99
|
+
border-color: rgba(231, 76, 60, 0.8);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.button-danger:hover {
|
|
103
|
+
background: rgba(231, 76, 60, 0.8);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.info-text {
|
|
107
|
+
margin-top: 1rem;
|
|
108
|
+
padding: 0.75rem 1rem;
|
|
109
|
+
background: rgba(255, 255, 255, 0.15);
|
|
110
|
+
border-radius: 0.5rem;
|
|
111
|
+
font-size: 1rem;
|
|
112
|
+
animation: fadeIn 0.3s ease;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@keyframes fadeIn {
|
|
116
|
+
from {
|
|
117
|
+
opacity: 0;
|
|
118
|
+
transform: translateY(-10px);
|
|
119
|
+
}
|
|
120
|
+
to {
|
|
121
|
+
opacity: 1;
|
|
122
|
+
transform: translateY(0);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.info {
|
|
127
|
+
text-align: center;
|
|
128
|
+
opacity: 0.8;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.info p {
|
|
132
|
+
margin: 0.5rem 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.info code {
|
|
136
|
+
background: rgba(0, 0, 0, 0.2);
|
|
137
|
+
padding: 0.2rem 0.5rem;
|
|
138
|
+
border-radius: 0.25rem;
|
|
139
|
+
font-family: 'Courier New', monospace;
|
|
140
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"jsx": "preserve",
|
|
14
|
+
"jsxImportSource": "solid-js",
|
|
15
|
+
"strict": true,
|
|
16
|
+
"noUnusedLocals": true,
|
|
17
|
+
"noUnusedParameters": true,
|
|
18
|
+
"noFallthroughCasesInSwitch": true
|
|
19
|
+
},
|
|
20
|
+
"include": ["src"],
|
|
21
|
+
"references": [{ "path": "./tsconfig.node.json" }]
|
|
22
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
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
|
+
// Set app icon from embedded assets
|
|
122
|
+
mainWindow.window().setIconFromMemory(ASSET_ICON_PNG, ASSET_ICON_PNG_LEN);
|
|
123
|
+
|
|
124
|
+
// Set tray icon from embedded assets
|
|
125
|
+
mainWindow.tray().setIconFromMemory(ASSET_ICON_PNG, ASSET_ICON_PNG_LEN);
|
|
126
|
+
mainWindow.tray().setTooltip(appConfig.name);
|
|
127
|
+
mainWindow.tray().setVisible(true);
|
|
128
|
+
|
|
129
|
+
// Apply additional settings
|
|
130
|
+
if (windowConfig.opacity < 1.0) {
|
|
131
|
+
mainWindow.window().setTransparency(windowConfig.opacity);
|
|
132
|
+
}
|
|
133
|
+
if (windowConfig.fullscreen) {
|
|
134
|
+
mainWindow.window().setFullscreen(true);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ========================================
|
|
138
|
+
// SYSTEM TRAY (if enabled)
|
|
139
|
+
// ========================================
|
|
140
|
+
// HEADLESS / HIDDEN STARTUP
|
|
141
|
+
// ========================================
|
|
142
|
+
if (appConfig.headless || appConfig.hiddenOnStartup) {
|
|
143
|
+
mainWindow.window().hide();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ========================================
|
|
147
|
+
// NAVIGATION - Load Frontend
|
|
148
|
+
// ========================================
|
|
149
|
+
#ifdef PLUSUI_DEV_MODE
|
|
150
|
+
mainWindow.navigate("http://localhost:5173");
|
|
151
|
+
#else
|
|
152
|
+
mainWindow.loadFile("frontend/dist/index.html");
|
|
153
|
+
#endif
|
|
154
|
+
|
|
155
|
+
// ========================================
|
|
156
|
+
// CUSTOM C++ FUNCTIONS (expose to frontend)
|
|
157
|
+
// ========================================
|
|
158
|
+
// {{PROJECT_NAME_LOWER}}.bind("getVersion", [](const std::string& args) {
|
|
159
|
+
// return "\"" + appConfig.version + "\"";
|
|
160
|
+
// });
|
|
161
|
+
// Call from JS: const version = await app.invoke('getVersion');
|
|
162
|
+
|
|
163
|
+
// ========================================
|
|
164
|
+
// RUN APPLICATION
|
|
165
|
+
// ========================================
|
|
166
|
+
plusui::App runtime;
|
|
167
|
+
runtime.run();
|
|
168
|
+
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ============================================================================
|
|
173
|
+
// FRONTEND API REFERENCE
|
|
174
|
+
// ============================================================================
|
|
175
|
+
// import { win, browser, router, app, display, clipboard } from 'plusui-native-core';
|
|
176
|
+
//
|
|
177
|
+
// WINDOW: win.minimize(), win.maximize(), win.close(), win.center(),
|
|
178
|
+
// win.setSize(w, h), win.setPosition(x, y), win.setTitle(str),
|
|
179
|
+
// win.setFullscreen(bool), win.setAlwaysOnTop(bool),
|
|
180
|
+
// win.getSize(), win.getPosition(), win.isMaximized(), win.isVisible()
|
|
181
|
+
//
|
|
182
|
+
// BROWSER: browser.navigate(url), browser.goBack(), browser.goForward(),
|
|
183
|
+
// browser.reload(), browser.getUrl(), browser.canGoBack()
|
|
184
|
+
//
|
|
185
|
+
// ROUTER: router.setRoutes({'/': 'url'}), router.push('/path')
|
|
186
|
+
//
|
|
187
|
+
// APP: app.quit(), app.invoke('customFn', args)
|
|
188
|
+
//
|
|
189
|
+
// DISPLAY: display.getAll(), display.getPrimary(), display.getCurrent()
|
|
190
|
+
//
|
|
191
|
+
// CLIPBOARD: clipboard.writeText(str), clipboard.readText(), clipboard.clear()
|
|
192
|
+
|
|
@@ -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
|
+
|